rlsm 1.1.0 → 1.8.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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