rlsm 1.1.0 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,13 @@
1
1
  #include <ruby.h>
2
2
 
3
+ #ifndef RARRAY_PTR
4
+ #define RARRAY_PTR(ary) RARRAY(ary)->ptr
5
+ #endif
6
+
7
+ #ifndef RARRAY_LEN
8
+ #define RARRAY_LEN(ary) RARRAY(ary)->len
9
+ #endif
10
+
3
11
  static int
4
12
  c_subset_next(int* sub, int n, int k) {
5
13
  int i = k - 1;
@@ -49,16 +57,16 @@ ary2ruby(int* subset, int k, VALUE ary) {
49
57
  int i;
50
58
 
51
59
  for (i=0; i < k; ++i) {
52
- rb_ary_store(result, i, RARRAY(ary)->ptr[subset[i]]);
60
+ rb_ary_store(result, i, RARRAY_PTR(ary)[subset[i]]);
53
61
  }
54
62
 
55
63
  return result;
56
64
  }
57
65
 
58
66
  static VALUE
59
- powerset(VALUE self) {
67
+ powerset(VALUE self, VALUE ary) {
60
68
  int k;
61
- int n = RARRAY(self)->len;
69
+ int n = RARRAY_LEN(ary);
62
70
  if (!rb_block_given_p()) {
63
71
  VALUE result = rb_ary_new();
64
72
  for (k=0; k <= n; ++k) {
@@ -67,7 +75,7 @@ powerset(VALUE self) {
67
75
  for (i=0; i < k; ++i) { subset[i] = i; }
68
76
 
69
77
  while(1) {
70
- rb_ary_push(result, ary2ruby(subset,k,self));
78
+ rb_ary_push(result, ary2ruby(subset,k,ary));
71
79
  res = c_subset_next(subset, n, k);
72
80
  if (res == -1)
73
81
  break;
@@ -82,7 +90,7 @@ powerset(VALUE self) {
82
90
  for (i=0; i < k; ++i) { subset[i] = i; }
83
91
 
84
92
  while(1) {
85
- rb_yield(ary2ruby(subset,k,self));
93
+ rb_yield(ary2ruby(subset,k,ary));
86
94
  res = c_subset_next(subset, n, k);
87
95
  if (res == -1)
88
96
  break;
@@ -94,16 +102,16 @@ powerset(VALUE self) {
94
102
  }
95
103
 
96
104
  static VALUE
97
- permutations(VALUE self) {
105
+ permutations(VALUE self, VALUE ary) {
98
106
  int res;
99
- int n = RARRAY(self)->len;
107
+ int n = RARRAY_LEN(ary);
100
108
  int* perm = (int*) ALLOCA_N(int, n);
101
109
  int t;
102
110
  for (t=0; t < n; ++t) { perm[t] = t; }
103
111
 
104
112
  if (rb_block_given_p()) {
105
113
  while(1) {
106
- rb_yield(ary2ruby(perm, n, self));
114
+ rb_yield(ary2ruby(perm, n, ary));
107
115
  res = c_next_perm(perm, n);
108
116
  if (res == -1)
109
117
  break;
@@ -112,7 +120,7 @@ permutations(VALUE self) {
112
120
  else {
113
121
  VALUE result = rb_ary_new();
114
122
  while(1) {
115
- rb_ary_push(result,ary2ruby(perm, n, self));
123
+ rb_ary_push(result,ary2ruby(perm, n, ary));
116
124
  res = c_next_perm(perm, n);
117
125
  if (res == -1)
118
126
  break;
@@ -128,9 +136,10 @@ permutations(VALUE self) {
128
136
  extern "C" {
129
137
  #endif
130
138
  void Init_array_cext() {
131
- VALUE ary = rb_const_get(rb_cObject, rb_intern("Array"));
132
- rb_define_method(ary, "powerset", (VALUE(*)(ANYARGS))powerset, 0);
133
- rb_define_method(ary, "permutations", (VALUE(*)(ANYARGS))permutations, 0);
139
+ VALUE rlsm = rb_define_module("RLSM");
140
+ VALUE ary_ext = rb_define_module_under(rlsm, "ArrayExt");
141
+ rb_define_singleton_method(ary_ext, "powerset", (VALUE(*)(ANYARGS))powerset, 1);
142
+ rb_define_singleton_method(ary_ext, "permutations", (VALUE(*)(ANYARGS))permutations, 1);
134
143
  }
135
144
  #ifdef __cplusplus
136
145
  }
@@ -1,12 +1,20 @@
1
1
  #include <ruby.h>
2
2
 
3
+ #ifndef RARRAY_PTR
4
+ #define RARRAY_PTR(ary) RARRAY(ary)->ptr
5
+ #endif
6
+
7
+ #ifndef RARRAY_LEN
8
+ #define RARRAY_LEN(ary) RARRAY(ary)->len
9
+ #endif
10
+
3
11
  typedef int bool;
4
12
 
5
13
  static int
6
14
  mi_index(VALUE ary, int index) {
7
15
  int i;
8
- for (i=0; i < RARRAY(ary)->len; ++i) {
9
- if (NUM2INT(RARRAY(ary)->ptr[i]) == index) { return i; }
16
+ for (i=0; i < RARRAY_LEN(ary); ++i) {
17
+ if (NUM2INT(RARRAY_PTR(ary)[i]) == index) { return i; }
10
18
  }
11
19
 
12
20
  return -1;
@@ -40,7 +48,7 @@ mi_helper_init_table(VALUE diagonal, int order) {
40
48
  else if (i % order == 0)
41
49
  result[i] = i / order;
42
50
  else if (i % order == i / order)
43
- result[i] = NUM2INT(RARRAY(diagonal)->ptr[i / order]);
51
+ result[i] = NUM2INT(RARRAY_PTR(diagonal)[i / order]);
44
52
  else
45
53
  result[i] = 0;
46
54
  }
@@ -51,9 +59,9 @@ mi_helper_init_table(VALUE diagonal, int order) {
51
59
  static bool
52
60
  mi_is_perm_stable(VALUE diagonal, VALUE perm) {
53
61
  int i;
54
- for (i=0; i < RARRAY(diagonal)->len; ++i) {
55
- int a = NUM2INT(RARRAY(diagonal)->ptr[i]);
56
- int b = NUM2INT(RARRAY(perm)->ptr[NUM2INT(RARRAY(diagonal)->ptr[mi_index(perm, i)])]);
62
+ for (i=0; i < RARRAY_LEN(diagonal); ++i) {
63
+ int a = NUM2INT(RARRAY_PTR(diagonal)[i]);
64
+ int b = NUM2INT(RARRAY_PTR(perm)[NUM2INT(RARRAY_PTR(diagonal)[mi_index(perm, i)])]);
57
65
 
58
66
  if ( a != b)
59
67
  return 0;
@@ -62,25 +70,13 @@ mi_is_perm_stable(VALUE diagonal, VALUE perm) {
62
70
  return 1;
63
71
  }
64
72
 
65
- static bool
66
- mi_is_invertable(VALUE diag, int index) {
67
- int i, pot = NUM2INT(RARRAY(diag)->ptr[index]);
68
-
69
- for (i=0; i < RARRAY(diag)->len; ++i) {
70
- if (pot == 0) { return 1; }
71
- pot = NUM2INT(RARRAY(diag)->ptr[pot]);
72
- }
73
-
74
- return 0;
75
- }
76
-
77
73
  static VALUE
78
74
  mi_helper_select_perms(VALUE diagonal, VALUE perms, int order) {
79
75
  VALUE result = rb_ary_new();
80
76
  VALUE perm;
81
77
  int i;
82
- for (i=0; i < RARRAY(perms)->len; ++i) {
83
- perm = RARRAY(perms)->ptr[i];
78
+ for (i=0; i < RARRAY_LEN(perms); ++i) {
79
+ perm = RARRAY_PTR(perms)[i];
84
80
  if (mi_is_perm_stable(diagonal, perm))
85
81
  rb_ary_push(result, perm);
86
82
  }
@@ -88,36 +84,19 @@ mi_helper_select_perms(VALUE diagonal, VALUE perms, int order) {
88
84
  return result;
89
85
  }
90
86
 
91
- static int*
92
- mi_helper_rc_restrictions(VALUE diagonal, int order) {
93
- int* result = (int*) calloc(order, sizeof(int));
94
- result[0] = 1;
95
-
96
- int i;
97
- for (i=1; i < order; ++i) {
98
- result[i] = 1;
99
- if (NUM2INT(RARRAY(diagonal)->ptr[i]) == i)
100
- result[i] *= 2; /* idempotent */
101
- if (mi_is_invertable(diagonal, i))
102
- result[i] *= 3; /* invertible */
103
- }
104
-
105
- return result;
106
- }
107
-
108
87
  static bool
109
88
  mi_is_diagonal_valid(int* diagonal, int ord, VALUE perms) {
110
89
  int i,j;
111
90
  VALUE perm;
112
- for (i=0; i < RARRAY(perms)->len; ++i) {
113
- perm = RARRAY(perms)->ptr[i];
91
+ for (i=0; i < RARRAY_LEN(perms); ++i) {
92
+ perm = RARRAY_PTR(perms)[i];
114
93
 
115
94
  for (j=0; j < ord; ++j) {
116
95
  int ii, pdii;
117
96
  ii = mi_index(perm, j);
118
97
  if (diagonal[ii] == -1) { break; }
119
98
 
120
- pdii = NUM2INT(RARRAY(perm)->ptr[diagonal[ii]]);
99
+ pdii = NUM2INT(RARRAY_PTR(perm)[diagonal[ii]]);
121
100
  if (diagonal[j] < pdii) { break; }
122
101
  if (diagonal[j] > pdii) { return 0; }
123
102
  }
@@ -162,9 +141,9 @@ mi_is_iso_antiiso(const int* table, int order, VALUE perms) {
162
141
  int max_index = order*order;
163
142
  VALUE perm;
164
143
 
165
- for (p = 0; p < RARRAY(perms)->len; ++p) {
144
+ for (p = 0; p < RARRAY_LEN(perms); ++p) {
166
145
  int smaller_iso = 0, smaller_aiso = 0;
167
- perm = RARRAY(perms)->ptr[p];
146
+ perm = RARRAY_PTR(perms)[p];
168
147
  for (i = order+1; i < max_index; ++i) {
169
148
  int ix1, ix2, ti, tii, taii, ptii, ptaii;
170
149
  ix1 = mi_index(perm, i / order);
@@ -177,8 +156,8 @@ mi_is_iso_antiiso(const int* table, int order, VALUE perms) {
177
156
  if (ti == -1 || tii == -1 || taii == -1 )
178
157
  break;
179
158
 
180
- ptii = NUM2INT(RARRAY(perm)->ptr[tii]);
181
- ptaii = NUM2INT(RARRAY(perm)->ptr[taii]);
159
+ ptii = NUM2INT(RARRAY_PTR(perm)[tii]);
160
+ ptaii = NUM2INT(RARRAY_PTR(perm)[taii]);
182
161
 
183
162
  if (ti < ptii)
184
163
  smaller_iso = 1;
@@ -197,40 +176,9 @@ mi_is_iso_antiiso(const int* table, int order, VALUE perms) {
197
176
  return 1;
198
177
  }
199
178
 
200
- static bool
201
- mi_is_rc_rest_satisfied(const int* table, int order, const int* rc_rest) {
202
- int i,j,k;
203
- for (i=1; i < order; ++i) {
204
- if (rc_rest[i] != 1) {
205
- if (rc_rest[i] % 2 == 0) {
206
- for (j=1; j < order; ++j) {
207
- if (table[order*i + j] == 0 || table[order*j + i] == 0)
208
- return 0;
209
- }
210
- }
211
-
212
- if (rc_rest[i] % 3 == 0) {
213
- for (j=0; j < order; ++j) {
214
- for (k=j+1; k < order; ++k) {
215
- if (table[order*i + j] != -1 && table[order*i + j] == table[order*i + k] )
216
- return 0;
217
- if (table[order*j + i] != -1 && table[order*j + i] == table[order*k + i])
218
- return 0;
219
-
220
- }
221
- }
222
- }
223
- }
224
- }
225
-
226
- return 1;
227
- }
228
179
 
229
180
  static bool
230
- mi_table_valid(const int* table, int order, const int* rc_rest, VALUE perms) {
231
- if (!mi_is_rc_rest_satisfied(table, order, rc_rest))
232
- return 0;
233
-
181
+ mi_table_valid(const int* table, int order, VALUE perms) {
234
182
  if (!mi_is_associative(table, order))
235
183
  return 0;
236
184
 
@@ -253,7 +201,7 @@ each_diagonal(VALUE self, VALUE rorder, VALUE perms) {
253
201
  while(1) {
254
202
  diagonal[index]++;
255
203
  if (diagonal[index] >= order) {
256
- if (index == 1) { return; } /* finished */
204
+ if (index == 1) { return Qnil; } /* finished */
257
205
  diagonal[index] = -1;
258
206
  index--;
259
207
  }
@@ -270,25 +218,24 @@ each_diagonal(VALUE self, VALUE rorder, VALUE perms) {
270
218
 
271
219
  static VALUE
272
220
  e_w_diagonal(VALUE self, VALUE diagonal, VALUE perms) {
273
- int order = RARRAY(diagonal)->len, t_order = order*order;
221
+ int order = RARRAY_LEN(diagonal), t_order = order*order;
274
222
  int* table = mi_helper_init_table(diagonal, order);
275
223
  VALUE rperms = mi_helper_select_perms(diagonal, perms, order);
276
- int* rc_rest = mi_helper_rc_restrictions(diagonal, order);
277
224
 
278
- if (mi_table_valid(table, order, rc_rest, rperms)) { rb_yield(mi_ary2rb(table, t_order)); }
225
+ if (mi_table_valid(table, order, rperms)) { rb_yield(mi_ary2rb(table, t_order)); }
279
226
 
280
227
  int index = t_order - 2;
281
228
  while (1) {
282
229
  table[index]++;
283
230
  if (table[index] >= order) {
284
- if (index <= order + 2) { return; } /* finished */
231
+ if (index <= order + 2) { return Qnil; } /* finished */
285
232
  table[index] = -1;
286
233
  index--;
287
234
  /* skip diagonal and first column */
288
235
  if ((index % order == index / order) || (index % order == 0))
289
236
  index--;
290
237
  }
291
- else if (mi_table_valid(table, order, rc_rest, rperms)) {
238
+ else if (mi_table_valid(table, order, rperms)) {
292
239
  if (index == t_order - 2)
293
240
  rb_yield(mi_ary2rb(table, t_order));
294
241
  else {
@@ -307,14 +254,56 @@ static VALUE
307
254
  e_pos(VALUE self, VALUE table, VALUE rorder) {
308
255
  int i, order = NUM2INT(rorder);
309
256
  for(i=0; i < order; ++i) {
310
- if (NUM2INT(RARRAY(table)->ptr[i]) != i || NUM2INT(RARRAY(table)->ptr[order*i]) != i) {
311
- rb_raise(rb_const_get(rb_cObject, rb_intern("MonoidError")), "Neutral element isn't in first row.");
257
+ if (NUM2INT(RARRAY_PTR(table)[i]) != i || NUM2INT(RARRAY_PTR(table)[order*i]) != i) {
258
+ rb_raise(rb_const_get(rb_define_module("RLSM"), rb_intern("Error")), "Neutral element isn't in first row.");
312
259
  }
313
260
  }
314
261
 
315
262
  return Qnil;
316
263
  }
317
264
 
265
+ static VALUE
266
+ non_associative_triple(VALUE self) {
267
+ VALUE table = rb_iv_get(self, "@table");
268
+ VALUE max = NUM2INT(rb_iv_get(self, "@order"));
269
+ VALUE base = rb_iv_get(self, "@elements");
270
+
271
+ int i,j,k;
272
+ for (i=0; i < max; ++i) {
273
+ for (j=0; j < max; ++j) {
274
+ for (k=0; k < max; ++k) {
275
+ int ij,jk, i_jk, ij_k;
276
+ ij = NUM2INT(RARRAY_PTR(table)[max*i + j]);
277
+ jk = NUM2INT(RARRAY_PTR(table)[max*j + k]);
278
+ i_jk = NUM2INT(RARRAY_PTR(table)[max*i + jk]);
279
+ ij_k = NUM2INT(RARRAY_PTR(table)[max*ij + k]);
280
+ if (ij_k != i_jk) {
281
+ return (rb_ary_new3(3,RARRAY_PTR(base)[i],RARRAY_PTR(base)[j],RARRAY_PTR(base)[k]));
282
+ }
283
+ }
284
+ }
285
+ }
286
+
287
+ return (Qnil);
288
+ }
289
+
290
+ static VALUE
291
+ is_commutative(VALUE self) {
292
+ VALUE table = rb_iv_get(self, "@table");
293
+ VALUE max = NUM2INT(rb_iv_get(self, "@order"));
294
+
295
+ int i,j;
296
+ for (i=0; i < max; ++i) {
297
+ for (j=0; j < max; ++j) {
298
+ if (NUM2INT(RARRAY_PTR(table)[max*i + j]) != NUM2INT(RARRAY_PTR(table)[max*j + i]))
299
+ return (Qfalse);
300
+ }
301
+ }
302
+
303
+ return (Qtrue);
304
+ }
305
+
306
+
318
307
  #ifdef __cplusplus
319
308
  extern "C" {
320
309
  #endif
@@ -323,7 +312,9 @@ extern "C" {
323
312
  VALUE monoid = rb_define_class_under(rlsm, "Monoid", rb_cObject);
324
313
  rb_define_singleton_method(monoid, "each_diagonal", (VALUE(*)(ANYARGS))each_diagonal, 2);
325
314
  rb_define_singleton_method(monoid, "each_with_diagonal", (VALUE(*)(ANYARGS))e_w_diagonal, 2);
326
- rb_define_singleton_method(monoid, "enforce_identity_position", (VALUE(*)(ANYARGS))e_pos, 2);
315
+ rb_define_method(monoid, "enforce_identity_position", (VALUE(*)(ANYARGS))e_pos, 2);
316
+ rb_define_method(monoid, "is_commutative", (VALUE(*)(ANYARGS))is_commutative, 0);
317
+ rb_define_method(monoid, "non_associative_triple", (VALUE(*)(ANYARGS))non_associative_triple, 0);
327
318
  }
328
319
  #ifdef __cplusplus
329
320
  }
data/lib/rlsm.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module RLSM
2
- VERSION = "1.1.0"
2
+ VERSION = "1.8.1"
3
3
 
4
4
  def self.lib_path_to(file_name)
5
5
  File.join(File.dirname(__FILE__), 'rlsm', file_name)
data/lib/rlsm/dfa.rb CHANGED
@@ -6,6 +6,7 @@ RLSM::require_extension('array')
6
6
  require "strscan"
7
7
 
8
8
  module RLSM
9
+ # @private
9
10
  class DFA
10
11
  #Synonym for new.
11
12
  def self.[](description)
@@ -65,7 +66,7 @@ module RLSM
65
66
  #Processes given +string+ starting in state +state+.
66
67
  def [](state, string)
67
68
  unless @states.include?(state)
68
- raise DFAError, "Unknown state: #{state}"
69
+ raise RLSM::Error, "Unknown state: #{state}"
69
70
  end
70
71
 
71
72
  present_state = state
@@ -92,7 +93,7 @@ module RLSM
92
93
 
93
94
  #Checks if given +state+ is dead, i.e. its not a final state and it hs no outgoing transitions.
94
95
  def dead?(state)
95
- raise DFAError, "Unknown state: #{state}" unless @states.include?(state)
96
+ raise RLSM::Error, "Unknown state: #{state}" unless @states.include?(state)
96
97
 
97
98
  state != @initial_state and
98
99
  ! @final_states.include?(state) and
@@ -101,7 +102,7 @@ module RLSM
101
102
 
102
103
  #Checks if given +state+ is reachable, i.e. it exists a +string+, such that <tt>self << string == state</tt> is true.
103
104
  def reachable?(state)
104
- raise DFAError, "Unknown state: #{state}" unless @states.include?(state)
105
+ raise RLSM::Error, "Unknown state: #{state}" unless @states.include?(state)
105
106
 
106
107
  reachable_states.include? state
107
108
  end
@@ -312,7 +313,7 @@ module RLSM
312
313
  end
313
314
 
314
315
  def bijective_maps_to(other)
315
- bijective_maps = other.states.permutations.map do |perm|
316
+ bijective_maps = RLSM::ArrayExt::permutations(other.states).map do |perm|
316
317
  Hash[*@states.zip(perm).flatten]
317
318
  end
318
319
 
@@ -391,7 +392,7 @@ module RLSM
391
392
 
392
393
  def parse_initial_state(description)
393
394
  unless description.count('}') == 1
394
- raise DFAError, "None or at least two initial states."
395
+ raise RLSM::Error, "None or at least two initial states."
395
396
  end
396
397
 
397
398
  @initial_state = description[/\}\s*\*?(\w+)/,1]
@@ -436,14 +437,14 @@ module RLSM
436
437
  elsif parser.scan(/\w+/)
437
438
  #do nothing (states already parsed)
438
439
  else
439
- raise DFAError, "Parse Error, could not parse #{description}"
440
+ raise RLSM::Error, "Parse Error, could not parse #{description}"
440
441
  end
441
442
 
442
443
  break unless parser.scan(/ /)
443
444
  end
444
445
 
445
446
  unless parser.eos?
446
- raise DFAError, "Parse Error, could not parse #{description}"
447
+ raise RLSM::Error, "Parse Error, could not parse #{description}"
447
448
  end
448
449
 
449
450
  @alphabet = @alphabet.sort
@@ -466,7 +467,7 @@ module RLSM
466
467
  if trans[label].nil?
467
468
  trans[label] = destination
468
469
  elsif trans[label] != destination
469
- raise DFAError, "Parse Error: Transition labels must be uniq."
470
+ raise RLSM::Error, "Parse Error: Transition labels must be uniq."
470
471
  end
471
472
  end
472
473
  end