rlsm 1.0.0 → 1.1.0
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.
- data/{README.txt → README} +10 -23
- data/Rakefile +79 -7
- data/ext/array/array_c_ext.c +137 -0
- data/ext/array/extconf.rb +2 -0
- data/ext/binop/binop_c_ext.c +57 -0
- data/ext/binop/extconf.rb +2 -0
- data/ext/monoid/extconf.rb +2 -0
- data/ext/monoid/monoid_c_ext.c +330 -0
- data/lib/rlsm.rb +10 -14
- data/lib/rlsm/binary_operation.rb +151 -0
- data/lib/rlsm/dfa.rb +418 -602
- data/lib/rlsm/helper.rb +12 -0
- data/lib/rlsm/monoid.rb +454 -694
- data/lib/rlsm/regexp.rb +125 -0
- data/lib/rlsm/regexp_parser.rb +450 -0
- data/test/helpers.rb +66 -0
- data/test/test_binop.rb +119 -0
- data/test/test_dfa.rb +435 -0
- data/test/test_monoid.rb +552 -0
- data/test/test_regexp.rb +440 -0
- metadata +109 -37
- data/History.txt +0 -6
- data/Manifest.txt +0 -18
- data/bin/smon +0 -39
- data/data/monoids.db +0 -0
- data/lib/database.rb +0 -95
- data/lib/monkey_patching/array_ext.rb +0 -50
- data/lib/rlsm/re.rb +0 -504
- data/lib/smon/base.rb +0 -284
- data/lib/smon/db.rb +0 -98
- data/lib/smon/dot.rb +0 -65
- data/lib/smon/latex.rb +0 -313
- data/lib/smon/smon.rb +0 -183
- data/stdarb.tex +0 -118
data/{README.txt → README}
RENAMED
@@ -1,24 +1,19 @@
|
|
1
1
|
= rlsm
|
2
|
+
rlsm stands for *R*egular *L*anguages and *S*yntactic *M*onoids.
|
2
3
|
|
3
|
-
|
4
|
+
Source is availible from
|
5
|
+
http://github.com/asmodis/rlsm
|
6
|
+
|
7
|
+
RDoc-Documentation is availible from
|
8
|
+
http://rlsm.rubyforge.org
|
4
9
|
|
5
10
|
== DESCRIPTION:
|
6
11
|
|
7
12
|
This is a ruby implementation of three concepts:
|
8
|
-
- Deterministic Finite Automata
|
13
|
+
- Deterministic Finite Automata
|
9
14
|
- Regular Expressions (in the sense of theoretical computer sience)
|
10
|
-
- Monoids
|
11
|
-
|
12
|
-
|
13
|
-
== FEATURES/PROBLEMS:
|
14
|
-
|
15
|
-
It is possible to convert
|
16
|
-
Monoid -> DFA
|
17
|
-
DFA -> RegExp
|
18
|
-
RegExp -> DFA
|
19
|
-
DFA -> Monoid
|
15
|
+
- Monoids
|
20
16
|
|
21
|
-
Also it is possible to ask a monoid for some properties.
|
22
17
|
|
23
18
|
== SYNOPSIS:
|
24
19
|
|
@@ -29,24 +24,16 @@ Also it is possible to ask a monoid for some properties.
|
|
29
24
|
m.isomorph_to?(m) # => true
|
30
25
|
m.commutative? # => false
|
31
26
|
|
32
|
-
== REQUIREMENTS:
|
33
|
-
|
34
|
-
Depends on
|
35
|
-
- sqlite3-ruby
|
36
|
-
|
37
27
|
== INSTALL:
|
38
28
|
|
39
|
-
|
40
|
-
|
41
|
-
sudo gem install rlsm
|
29
|
+
gem install rlsm
|
42
30
|
|
43
|
-
is sufficent.
|
44
31
|
|
45
32
|
== LICENSE:
|
46
33
|
|
47
34
|
(The MIT License)
|
48
35
|
|
49
|
-
Copyright (c)
|
36
|
+
Copyright (c) 2009 Gunther Diemant <g.diemant@gmx.net>
|
50
37
|
|
51
38
|
Permission is hereby granted, free of charge, to any person obtaining
|
52
39
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
@@ -1,12 +1,84 @@
|
|
1
1
|
# -*- ruby -*-
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'hoe'
|
5
|
-
require './lib/rlsm.rb'
|
3
|
+
require File.join(File.dirname(__FILE__), 'lib', 'rlsm')
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
task :build_ext do
|
6
|
+
Dir.chdir File.join(File.dirname(__FILE__), 'ext') do
|
7
|
+
Dir.foreach('.') do |extension|
|
8
|
+
Dir.chdir extension do
|
9
|
+
if File.exists? 'extconf.rb'
|
10
|
+
ruby 'extconf.rb'
|
11
|
+
sh "make"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
10
16
|
end
|
11
17
|
|
12
|
-
|
18
|
+
task :test => :build_ext do
|
19
|
+
Dir.chdir File.join(File.dirname(__FILE__), 'test') do
|
20
|
+
Dir.glob("test_*").each do |file|
|
21
|
+
ruby file
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
task :create_manifest do
|
27
|
+
Dir.chdir(File.dirname(__FILE__)) do
|
28
|
+
File.open("Manifest", 'w') do |manifest|
|
29
|
+
FileList['lib/**/*.rb', 'ext/**/*.c','ext/**/*.rb', 'test/**/*'].to_a.each do |file|
|
30
|
+
manifest.puts file
|
31
|
+
end
|
32
|
+
|
33
|
+
manifest.puts "Rakefile"
|
34
|
+
manifest.puts "README"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
task :create_gemspec => :create_manifest do
|
40
|
+
Dir.chdir(File.dirname(__FILE__)) do
|
41
|
+
readme = File.open("README")
|
42
|
+
manifest = File.open("Manifest")
|
43
|
+
filelist = "[" + manifest.to_a.map { |line| "'#{line.chomp}'" }.join(", ") + "]"
|
44
|
+
manifest.close
|
45
|
+
|
46
|
+
readme_string = '<<DESCRIPTION' + "\n" + readme.to_a.join + "\nDESCRIPTION"
|
47
|
+
readme.close
|
48
|
+
|
49
|
+
File.open(".gemspec", 'w') do |gemspec|
|
50
|
+
gemspec.puts <<GEMSPEC
|
51
|
+
# -*- ruby -*-
|
52
|
+
|
53
|
+
require "rake"
|
54
|
+
|
55
|
+
Gem::Specification.new do |s|
|
56
|
+
s.author = "Gunther Diemant"
|
57
|
+
s.email = "g.diemant@gmx.net"
|
58
|
+
s.homepage = "http://github.com/asmodis/rlsm"
|
59
|
+
s.rubyforge_project = 'rlsm'
|
60
|
+
|
61
|
+
s.name = 'rlsm'
|
62
|
+
s.version = '#{RLSM::VERSION}'
|
63
|
+
s.add_development_dependency('minitest')
|
64
|
+
s.add_development_dependency('thoughtbot-shoulda')
|
65
|
+
s.summary = "Library for investigating regular languages and syntactic monoids."
|
66
|
+
s.description = #{readme_string}
|
67
|
+
|
68
|
+
s.files = #{filelist}
|
69
|
+
s.test_files = FileList['test/test_*.rb']
|
70
|
+
s.extensions = FileList['ext/**/extconf.rb']
|
71
|
+
|
72
|
+
s.has_rdoc = true
|
73
|
+
s.extra_rdoc_files = ['README']
|
74
|
+
s.rdoc_options << '--main' << 'README'
|
75
|
+
end
|
76
|
+
GEMSPEC
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
task :create_gem => :create_gemspec do
|
82
|
+
sh "gem build .gemspec"
|
83
|
+
sh "mv *.gem gem/"
|
84
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
static int
|
4
|
+
c_subset_next(int* sub, int n, int k) {
|
5
|
+
int i = k - 1;
|
6
|
+
|
7
|
+
while(i >= 0 && sub[i] == n-k+i) { i--; }
|
8
|
+
|
9
|
+
if (i < 0)
|
10
|
+
return -1;
|
11
|
+
|
12
|
+
int j;
|
13
|
+
int sub_i = sub[i];
|
14
|
+
for (j=i; j < k; ++j) {
|
15
|
+
sub[j] = sub_i + 1 + j - i;
|
16
|
+
}
|
17
|
+
|
18
|
+
return 0;
|
19
|
+
}
|
20
|
+
|
21
|
+
static int
|
22
|
+
c_next_perm(int* perm, int n) {
|
23
|
+
int i = n-2;
|
24
|
+
while (i >= -1 && perm[i+1] < perm[i]) { i--; }
|
25
|
+
if ( i < 0 ) { return -1; }
|
26
|
+
|
27
|
+
int j = n-1;
|
28
|
+
while ( perm[j] < perm[i] ) { j--; }
|
29
|
+
|
30
|
+
int temp = perm[i];
|
31
|
+
perm[i] = perm[j];
|
32
|
+
perm[j] = temp;
|
33
|
+
|
34
|
+
int* tmp = (int*) ALLOCA_N(int, n);
|
35
|
+
|
36
|
+
int k;
|
37
|
+
for (k=0; k < n; ++k) { tmp[k] = perm[k]; }
|
38
|
+
|
39
|
+
for (k = i+1; k < n; ++k) {
|
40
|
+
perm[k] = tmp[n+i-k];
|
41
|
+
}
|
42
|
+
|
43
|
+
return 0;
|
44
|
+
}
|
45
|
+
|
46
|
+
static VALUE
|
47
|
+
ary2ruby(int* subset, int k, VALUE ary) {
|
48
|
+
VALUE result = rb_ary_new2(k);
|
49
|
+
int i;
|
50
|
+
|
51
|
+
for (i=0; i < k; ++i) {
|
52
|
+
rb_ary_store(result, i, RARRAY(ary)->ptr[subset[i]]);
|
53
|
+
}
|
54
|
+
|
55
|
+
return result;
|
56
|
+
}
|
57
|
+
|
58
|
+
static VALUE
|
59
|
+
powerset(VALUE self) {
|
60
|
+
int k;
|
61
|
+
int n = RARRAY(self)->len;
|
62
|
+
if (!rb_block_given_p()) {
|
63
|
+
VALUE result = rb_ary_new();
|
64
|
+
for (k=0; k <= n; ++k) {
|
65
|
+
int i,res;
|
66
|
+
int* subset = ALLOCA_N(int, k);
|
67
|
+
for (i=0; i < k; ++i) { subset[i] = i; }
|
68
|
+
|
69
|
+
while(1) {
|
70
|
+
rb_ary_push(result, ary2ruby(subset,k,self));
|
71
|
+
res = c_subset_next(subset, n, k);
|
72
|
+
if (res == -1)
|
73
|
+
break;
|
74
|
+
}
|
75
|
+
}
|
76
|
+
return result;
|
77
|
+
}
|
78
|
+
else {
|
79
|
+
for (k=0; k <= n; ++k) {
|
80
|
+
int i,res;
|
81
|
+
int* subset = ALLOCA_N(int, k);
|
82
|
+
for (i=0; i < k; ++i) { subset[i] = i; }
|
83
|
+
|
84
|
+
while(1) {
|
85
|
+
rb_yield(ary2ruby(subset,k,self));
|
86
|
+
res = c_subset_next(subset, n, k);
|
87
|
+
if (res == -1)
|
88
|
+
break;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
return Qnil;
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
static VALUE
|
97
|
+
permutations(VALUE self) {
|
98
|
+
int res;
|
99
|
+
int n = RARRAY(self)->len;
|
100
|
+
int* perm = (int*) ALLOCA_N(int, n);
|
101
|
+
int t;
|
102
|
+
for (t=0; t < n; ++t) { perm[t] = t; }
|
103
|
+
|
104
|
+
if (rb_block_given_p()) {
|
105
|
+
while(1) {
|
106
|
+
rb_yield(ary2ruby(perm, n, self));
|
107
|
+
res = c_next_perm(perm, n);
|
108
|
+
if (res == -1)
|
109
|
+
break;
|
110
|
+
}
|
111
|
+
}
|
112
|
+
else {
|
113
|
+
VALUE result = rb_ary_new();
|
114
|
+
while(1) {
|
115
|
+
rb_ary_push(result,ary2ruby(perm, n, self));
|
116
|
+
res = c_next_perm(perm, n);
|
117
|
+
if (res == -1)
|
118
|
+
break;
|
119
|
+
}
|
120
|
+
|
121
|
+
return result;
|
122
|
+
}
|
123
|
+
|
124
|
+
return Qnil;
|
125
|
+
}
|
126
|
+
|
127
|
+
#ifdef __cplusplus
|
128
|
+
extern "C" {
|
129
|
+
#endif
|
130
|
+
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);
|
134
|
+
}
|
135
|
+
#ifdef __cplusplus
|
136
|
+
}
|
137
|
+
#endif
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
|
4
|
+
static VALUE
|
5
|
+
non_associative_triple(VALUE self) {
|
6
|
+
VALUE table = rb_iv_get(self, "@table");
|
7
|
+
VALUE max = NUM2INT(rb_iv_get(self, "@order"));
|
8
|
+
VALUE base = rb_iv_get(self, "@elements");
|
9
|
+
|
10
|
+
int i,j,k;
|
11
|
+
for (i=0; i < max; ++i) {
|
12
|
+
for (j=0; j < max; ++j) {
|
13
|
+
for (k=0; k < max; ++k) {
|
14
|
+
int ij,jk, i_jk, ij_k;
|
15
|
+
ij = NUM2INT(RARRAY(table)->ptr[max*i + j]);
|
16
|
+
jk = NUM2INT(RARRAY(table)->ptr[max*j + k]);
|
17
|
+
i_jk = NUM2INT(RARRAY(table)->ptr[max*i + jk]);
|
18
|
+
ij_k = NUM2INT(RARRAY(table)->ptr[max*ij + k]);
|
19
|
+
if (ij_k != i_jk) {
|
20
|
+
return (rb_ary_new3(3,RARRAY(base)->ptr[i],RARRAY(base)->ptr[j],RARRAY(base)->ptr[k]));
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
return (Qnil);
|
27
|
+
}
|
28
|
+
|
29
|
+
static VALUE
|
30
|
+
is_commutative(VALUE self) {
|
31
|
+
VALUE table = rb_iv_get(self, "@table");
|
32
|
+
VALUE max = NUM2INT(rb_iv_get(self, "@order"));
|
33
|
+
|
34
|
+
int i,j;
|
35
|
+
for (i=0; i < max; ++i) {
|
36
|
+
for (j=0; j < max; ++j) {
|
37
|
+
if (NUM2INT(RARRAY(table)->ptr[max*i + j]) != NUM2INT(RARRAY(table)->ptr[max*j + i]))
|
38
|
+
return (Qfalse);
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
return (Qtrue);
|
43
|
+
}
|
44
|
+
|
45
|
+
#ifdef __cplusplus
|
46
|
+
extern "C" {
|
47
|
+
#endif
|
48
|
+
void Init_binop_cext() {
|
49
|
+
VALUE rlsm = rb_define_module("RLSM");
|
50
|
+
VALUE binop = rb_define_class_under(rlsm, "BinaryOperation", rb_cObject);
|
51
|
+
|
52
|
+
rb_define_private_method(binop, "is_commutative", (VALUE(*)(ANYARGS))is_commutative, 0);
|
53
|
+
rb_define_private_method(binop, "non_associative_triple", (VALUE(*)(ANYARGS))non_associative_triple, 0);
|
54
|
+
}
|
55
|
+
#ifdef __cplusplus
|
56
|
+
}
|
57
|
+
#endif
|
@@ -0,0 +1,330 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
typedef int bool;
|
4
|
+
|
5
|
+
static int
|
6
|
+
mi_index(VALUE ary, int index) {
|
7
|
+
int i;
|
8
|
+
for (i=0; i < RARRAY(ary)->len; ++i) {
|
9
|
+
if (NUM2INT(RARRAY(ary)->ptr[i]) == index) { return i; }
|
10
|
+
}
|
11
|
+
|
12
|
+
return -1;
|
13
|
+
}
|
14
|
+
|
15
|
+
static int*
|
16
|
+
mi_new_ary(int length, int val) {
|
17
|
+
int* result = (int*) calloc(length, sizeof(int));
|
18
|
+
int i;
|
19
|
+
for (i=0; i < length; ++i) { result[i] = val; }
|
20
|
+
|
21
|
+
return result;
|
22
|
+
}
|
23
|
+
|
24
|
+
static VALUE mi_ary2rb(const int* ary, int length) {
|
25
|
+
VALUE result = rb_ary_new2(length);
|
26
|
+
int i;
|
27
|
+
for (i=0; i < length; ++i) { rb_ary_store(result, i, INT2NUM(ary[i])); }
|
28
|
+
|
29
|
+
return result;
|
30
|
+
}
|
31
|
+
|
32
|
+
static int*
|
33
|
+
mi_helper_init_table(VALUE diagonal, int order) {
|
34
|
+
int* result = (int*) calloc(order*order, sizeof(int));
|
35
|
+
|
36
|
+
int i;
|
37
|
+
for (i = 0; i < order*order; ++i) {
|
38
|
+
if (i < order)
|
39
|
+
result[i] = i;
|
40
|
+
else if (i % order == 0)
|
41
|
+
result[i] = i / order;
|
42
|
+
else if (i % order == i / order)
|
43
|
+
result[i] = NUM2INT(RARRAY(diagonal)->ptr[i / order]);
|
44
|
+
else
|
45
|
+
result[i] = 0;
|
46
|
+
}
|
47
|
+
|
48
|
+
return result;
|
49
|
+
}
|
50
|
+
|
51
|
+
static bool
|
52
|
+
mi_is_perm_stable(VALUE diagonal, VALUE perm) {
|
53
|
+
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)])]);
|
57
|
+
|
58
|
+
if ( a != b)
|
59
|
+
return 0;
|
60
|
+
}
|
61
|
+
|
62
|
+
return 1;
|
63
|
+
}
|
64
|
+
|
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
|
+
static VALUE
|
78
|
+
mi_helper_select_perms(VALUE diagonal, VALUE perms, int order) {
|
79
|
+
VALUE result = rb_ary_new();
|
80
|
+
VALUE perm;
|
81
|
+
int i;
|
82
|
+
for (i=0; i < RARRAY(perms)->len; ++i) {
|
83
|
+
perm = RARRAY(perms)->ptr[i];
|
84
|
+
if (mi_is_perm_stable(diagonal, perm))
|
85
|
+
rb_ary_push(result, perm);
|
86
|
+
}
|
87
|
+
|
88
|
+
return result;
|
89
|
+
}
|
90
|
+
|
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
|
+
static bool
|
109
|
+
mi_is_diagonal_valid(int* diagonal, int ord, VALUE perms) {
|
110
|
+
int i,j;
|
111
|
+
VALUE perm;
|
112
|
+
for (i=0; i < RARRAY(perms)->len; ++i) {
|
113
|
+
perm = RARRAY(perms)->ptr[i];
|
114
|
+
|
115
|
+
for (j=0; j < ord; ++j) {
|
116
|
+
int ii, pdii;
|
117
|
+
ii = mi_index(perm, j);
|
118
|
+
if (diagonal[ii] == -1) { break; }
|
119
|
+
|
120
|
+
pdii = NUM2INT(RARRAY(perm)->ptr[diagonal[ii]]);
|
121
|
+
if (diagonal[j] < pdii) { break; }
|
122
|
+
if (diagonal[j] > pdii) { return 0; }
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
return 1;
|
127
|
+
}
|
128
|
+
|
129
|
+
|
130
|
+
static bool
|
131
|
+
mi_is_associative(const int* table, int order) {
|
132
|
+
int x1,x2,x3;
|
133
|
+
for (x1=1; x1 < order; ++x1) {
|
134
|
+
for (x2=1; x2 < order; ++x2) {
|
135
|
+
for (x3=1; x3 < order; ++x3) {
|
136
|
+
int x1x2, x2x3, x1_x2x3, x1x2_x3;
|
137
|
+
|
138
|
+
x1x2 = table[order*x1 + x2];
|
139
|
+
if (x1x2 == -1) { break; }
|
140
|
+
|
141
|
+
x2x3 = table[order*x2 + x3];
|
142
|
+
if (x2x3 == -1) { break; }
|
143
|
+
|
144
|
+
x1x2_x3 = table[order*x1x2 + x3];
|
145
|
+
if (x1x2_x3 == -1) { break; }
|
146
|
+
|
147
|
+
x1_x2x3 = table[order*x1 + x2x3];
|
148
|
+
if (x1_x2x3 == -1) { break; }
|
149
|
+
|
150
|
+
if (x1_x2x3 != x1x2_x3)
|
151
|
+
return 0;
|
152
|
+
}
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
return 1;
|
157
|
+
}
|
158
|
+
|
159
|
+
static bool
|
160
|
+
mi_is_iso_antiiso(const int* table, int order, VALUE perms) {
|
161
|
+
int p,i;
|
162
|
+
int max_index = order*order;
|
163
|
+
VALUE perm;
|
164
|
+
|
165
|
+
for (p = 0; p < RARRAY(perms)->len; ++p) {
|
166
|
+
int smaller_iso = 0, smaller_aiso = 0;
|
167
|
+
perm = RARRAY(perms)->ptr[p];
|
168
|
+
for (i = order+1; i < max_index; ++i) {
|
169
|
+
int ix1, ix2, ti, tii, taii, ptii, ptaii;
|
170
|
+
ix1 = mi_index(perm, i / order);
|
171
|
+
ix2 = mi_index(perm, i % order);
|
172
|
+
|
173
|
+
ti = table[i];
|
174
|
+
tii = table[order*ix1 + ix2];
|
175
|
+
taii = table[order*ix2 + ix1];
|
176
|
+
|
177
|
+
if (ti == -1 || tii == -1 || taii == -1 )
|
178
|
+
break;
|
179
|
+
|
180
|
+
ptii = NUM2INT(RARRAY(perm)->ptr[tii]);
|
181
|
+
ptaii = NUM2INT(RARRAY(perm)->ptr[taii]);
|
182
|
+
|
183
|
+
if (ti < ptii)
|
184
|
+
smaller_iso = 1;
|
185
|
+
|
186
|
+
if (ti < ptaii)
|
187
|
+
smaller_aiso = 1;
|
188
|
+
|
189
|
+
if (smaller_iso == 1 && smaller_aiso == 1)
|
190
|
+
break;
|
191
|
+
|
192
|
+
if ((smaller_iso == 0 && ti > ptii) || (smaller_aiso == 0 && ti > ptaii))
|
193
|
+
return 0;
|
194
|
+
}
|
195
|
+
}
|
196
|
+
|
197
|
+
return 1;
|
198
|
+
}
|
199
|
+
|
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
|
+
|
229
|
+
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
|
+
|
234
|
+
if (!mi_is_associative(table, order))
|
235
|
+
return 0;
|
236
|
+
|
237
|
+
if (!mi_is_iso_antiiso(table, order, perms))
|
238
|
+
return 0;
|
239
|
+
|
240
|
+
return 1;
|
241
|
+
}
|
242
|
+
|
243
|
+
|
244
|
+
static VALUE
|
245
|
+
each_diagonal(VALUE self, VALUE rorder, VALUE perms) {
|
246
|
+
rb_need_block();
|
247
|
+
|
248
|
+
int order = NUM2INT(rorder);
|
249
|
+
int* diagonal = mi_new_ary(order, 0);
|
250
|
+
rb_yield(mi_ary2rb(diagonal, order));
|
251
|
+
|
252
|
+
int index = order - 1;
|
253
|
+
while(1) {
|
254
|
+
diagonal[index]++;
|
255
|
+
if (diagonal[index] >= order) {
|
256
|
+
if (index == 1) { return; } /* finished */
|
257
|
+
diagonal[index] = -1;
|
258
|
+
index--;
|
259
|
+
}
|
260
|
+
else if (mi_is_diagonal_valid(diagonal, order, perms)) {
|
261
|
+
if (index == order -1)
|
262
|
+
rb_yield(mi_ary2rb(diagonal, order));
|
263
|
+
else
|
264
|
+
index++;
|
265
|
+
}
|
266
|
+
}
|
267
|
+
|
268
|
+
return Qnil;
|
269
|
+
}
|
270
|
+
|
271
|
+
static VALUE
|
272
|
+
e_w_diagonal(VALUE self, VALUE diagonal, VALUE perms) {
|
273
|
+
int order = RARRAY(diagonal)->len, t_order = order*order;
|
274
|
+
int* table = mi_helper_init_table(diagonal, order);
|
275
|
+
VALUE rperms = mi_helper_select_perms(diagonal, perms, order);
|
276
|
+
int* rc_rest = mi_helper_rc_restrictions(diagonal, order);
|
277
|
+
|
278
|
+
if (mi_table_valid(table, order, rc_rest, rperms)) { rb_yield(mi_ary2rb(table, t_order)); }
|
279
|
+
|
280
|
+
int index = t_order - 2;
|
281
|
+
while (1) {
|
282
|
+
table[index]++;
|
283
|
+
if (table[index] >= order) {
|
284
|
+
if (index <= order + 2) { return; } /* finished */
|
285
|
+
table[index] = -1;
|
286
|
+
index--;
|
287
|
+
/* skip diagonal and first column */
|
288
|
+
if ((index % order == index / order) || (index % order == 0))
|
289
|
+
index--;
|
290
|
+
}
|
291
|
+
else if (mi_table_valid(table, order, rc_rest, rperms)) {
|
292
|
+
if (index == t_order - 2)
|
293
|
+
rb_yield(mi_ary2rb(table, t_order));
|
294
|
+
else {
|
295
|
+
index++;
|
296
|
+
/* skip diagonal and first column */
|
297
|
+
if ((index % order == index / order) || (index % order == 0))
|
298
|
+
index++;
|
299
|
+
}
|
300
|
+
}
|
301
|
+
}
|
302
|
+
|
303
|
+
return Qnil;
|
304
|
+
}
|
305
|
+
|
306
|
+
static VALUE
|
307
|
+
e_pos(VALUE self, VALUE table, VALUE rorder) {
|
308
|
+
int i, order = NUM2INT(rorder);
|
309
|
+
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.");
|
312
|
+
}
|
313
|
+
}
|
314
|
+
|
315
|
+
return Qnil;
|
316
|
+
}
|
317
|
+
|
318
|
+
#ifdef __cplusplus
|
319
|
+
extern "C" {
|
320
|
+
#endif
|
321
|
+
void Init_monoid_cext() {
|
322
|
+
VALUE rlsm = rb_define_module("RLSM");
|
323
|
+
VALUE monoid = rb_define_class_under(rlsm, "Monoid", rb_cObject);
|
324
|
+
rb_define_singleton_method(monoid, "each_diagonal", (VALUE(*)(ANYARGS))each_diagonal, 2);
|
325
|
+
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);
|
327
|
+
}
|
328
|
+
#ifdef __cplusplus
|
329
|
+
}
|
330
|
+
#endif
|