asmodis-rlsm 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/spec/dfa_spec.rb ADDED
@@ -0,0 +1,99 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'dfa')
2
+
3
+ describe RLSM::DFA do
4
+ before :each do
5
+ @dfa = RLSM::DFA.new ['a'],[0],0,[0],[['a',0,0]]
6
+ @dfa2 = RLSM::DFA.new( ['a', 'b'], [0,1,2], 0, [2],
7
+ [['a',0,0], ['a',1,2], ['a',2,2],
8
+ ['b',0,1], ['b',1,1], ['b',2,2]])
9
+ @dfa3 = RLSM::DFA.new( ['a', 'b'], [0,1,2], 0, [2],
10
+ [['a',0,0], ['a',1,2], ['a',2,2],
11
+ ['b',0,1], ['b',1,1]])
12
+
13
+ @dfa4 = RLSM::DFA.new( ['a', 'b'], [0,1,2,3,4], 0, [2,3],
14
+ [['a',0,0], ['a',1,2], ['a',2,2],
15
+ ['b',0,1], ['b',1,1],
16
+ ['a',3,4], ['a',4,3], ['b',3,2]])
17
+
18
+ @dfa5 = RLSM::DFA.new( ['a', 'b'], [0,1,2], 0, [1],
19
+ [['a',0,0], ['a',1,2], ['a',2,2],
20
+ ['b',0,1], ['b',1,1]])
21
+
22
+ @dfa5b = RLSM::DFA.new( ['a', 'b'], [0,1,'c'], 0, [1],
23
+ [['a',0,0], ['a',1,'c'], ['a','c','c'],
24
+ ['b',0,1], ['b',1,1]])
25
+ end
26
+
27
+ it "should have an initial state" do
28
+ @dfa.initial_state.should_not be_nil
29
+ @dfa.initial_state.label.should == '0'
30
+ @dfa2.initial_state.should_not be_nil
31
+ @dfa2.initial_state.label.should == '0'
32
+ end
33
+
34
+ it "should know the number of states" do
35
+ @dfa.num_states.should == 1
36
+ @dfa2.num_states.should == 3
37
+ end
38
+
39
+ it "should know the number of final states" do
40
+ @dfa.num_finals.should == 1
41
+ @dfa2.num_finals.should == 1
42
+ end
43
+
44
+ it "should know if it is complete" do
45
+ @dfa.complete?.should == true
46
+ @dfa2.complete?.should == true
47
+ @dfa3.complete?.should == false
48
+ end
49
+
50
+ it "should complete a non complete DFA if requested" do
51
+ @dfa3.complete.should be_complete
52
+ end
53
+
54
+ it "should find dead states" do
55
+ [@dfa,@dfa2,@dfa3].each { |d| d.dead_states?.should == false }
56
+
57
+ @dfa5.dead_states?.should == true
58
+ @dfa5.dead_states.map { |s| s.label }.should == ['2']
59
+ end
60
+
61
+ it "should find unreachable states" do
62
+ [@dfa,@dfa2,@dfa3].each { |d| d.unreachable_states?.should == false }
63
+
64
+ @dfa4.unreachable_states?.should == true
65
+ @dfa4.unreachable_states.size.should == 2
66
+ @dfa4.unreachable_states.map { |s| s.label }.sort.should == ['3','4']
67
+ end
68
+
69
+ it "should remove dead states" do
70
+ @dfa5.remove_dead_states.states.map { |s| s.label }.should == ['0','1']
71
+ end
72
+
73
+ it "should remove unreachable states" do
74
+ d = @dfa4.remove_unreachable_states
75
+ d.states.map { |s| s.label }.sort.should == ['0','1','2']
76
+ end
77
+
78
+ it "should minimize a DFA" do
79
+ d = RLSM::DFA.new(['a','b','c'], [0,1,2,3,4], 0, [4],
80
+ [['a',0,1], ['b',0,2], ['c',1,3], ['c',2,3], ['c',3,4]])
81
+
82
+ d.minimize!
83
+ d.states.map { |s| s.label }.sort.should == ['0','12', '3','4']
84
+ end
85
+
86
+ it "should check for isomorphisms" do
87
+ @dfa2.should be_isomorph_to(@dfa2)
88
+ @dfa5.should be_isomorph_to(@dfa5b)
89
+ @dfa3.should_not be_isomorph_to(@dfa2)
90
+ end
91
+
92
+ it "should calculate the transition monoid" do
93
+ @dfa.transition_monoid.should == RLSM::Monoid.new('0')
94
+ end
95
+
96
+ it "should caclulate a RegExp representation" do
97
+ @dfa.to_regexp.to_s.should == 'a*'
98
+ end
99
+ end
@@ -0,0 +1,270 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'monoid')
2
+
3
+ describe RLSM::Monoid, "basic stuff" do
4
+ before :each do
5
+ @m1 = RLSM::Monoid.new '0'
6
+ @m2 = RLSM::Monoid.new '00 01' #-> 01 11
7
+ @m3 = RLSM::Monoid.new '012 112 212'
8
+ end
9
+
10
+ it "should have '0' as the neutral element" do
11
+ @m1[0,0].should == 0
12
+
13
+ [0,1].each { |x| @m2[0,x].should == x; @m2[x,0].should == x }
14
+ [0,1,2].each { |x| @m3[0,x].should == x; @m3[x,0].should == x }
15
+ end
16
+
17
+ it "should decide if an other monoid is isomorphic" do
18
+ @m2.should == RLSM::Monoid.new('01 11')
19
+ @m3.should == RLSM::Monoid.new('002 012 022')
20
+
21
+ @m2.should_not == @m3
22
+
23
+ @m2.should_not == RLSM::Monoid.new('01 10')
24
+ end
25
+
26
+ end
27
+
28
+ describe RLSM::Monoid do
29
+ before :each do
30
+ @m0 = RLSM::Monoid.new '0'
31
+ @m1 = RLSM::Monoid.new '01 11'
32
+ @m2 = RLSM::Monoid.new '0123 1032 2323 3232'
33
+ end
34
+
35
+ [[],[0],[1], [2], [1,2], [1,3], [2,3], [1,2,3]].each do |set|
36
+ @m0 = RLSM::Monoid.new '0'
37
+ @m1 = RLSM::Monoid.new '01 11'
38
+ @m2 = RLSM::Monoid.new '0123 1032 2323 3232'
39
+
40
+ case set
41
+ when [], [0]
42
+ [@m0, @m1, @m2].each do |m|
43
+ it "should calculate the submonoid of #{m} generated by #{set}" do
44
+ sm = m.get_submonoid(set)
45
+ sm.should_not be_nil
46
+ sm.should == RLSM::Monoid.new('0')
47
+ end
48
+ end
49
+ when [1]
50
+ it "should calculate the submonoid of #{@m1} generated by #{set}" do
51
+ @m1.get_submonoid(set).should == @m1
52
+ end
53
+
54
+ it "should calculate the submonoid of #{@m2} generated by #{set}" do
55
+ @m2.get_submonoid(set).should == RLSM::Monoid.new('01 10')
56
+ end
57
+ when [2]
58
+ it "should calculate the submonoid of #{@m2} generated by #{set}" do
59
+ @m2.get_submonoid(set).should == @m1
60
+ end
61
+ when [1,2]
62
+ it "should calculate the submonoid of #{@m2} generated by #{set}" do
63
+ @m2.get_submonoid(set).should == @m2
64
+ end
65
+ when [1,3]
66
+ it "should calculate the submonoid of #{@m2} generated by #{set}" do
67
+ @m2.get_submonoid(set).should == @m2
68
+ end
69
+ when [2,3]
70
+ it "should calculate the submonoid of #{@m2} generated by #{set}" do
71
+ @m2.get_submonoid(set).should == RLSM::Monoid.new('012 112 221')
72
+ end
73
+ when [1,2,3]
74
+ it "should calculate the submonoid of #{@m2} generated by #{set}" do
75
+ @m2.get_submonoid(set).should == @m2
76
+ end
77
+ end
78
+ end
79
+
80
+ it "should calculate the generator subset of #{RLSM::Monoid.new('0')}" do
81
+ RLSM::Monoid.new('0').generating_subset.should == []
82
+ end
83
+
84
+ it "should calculate the generator subset of #{RLSM::Monoid.new('01 11')}" do
85
+ RLSM::Monoid.new('01 11').generating_subset.should == [1]
86
+ end
87
+
88
+ it "should calculate the generator subset of #{RLSM::Monoid.new('0123 1032 2323 3232')}" do
89
+ RLSM::Monoid.new('0123 1032 2323 3232').generating_subset.should == [1,2]
90
+ end
91
+ end
92
+
93
+
94
+ describe RLSM::Monoid do
95
+ before :each do
96
+ @m1 = RLSM::Monoid.new '012345 113315 245255 315355 442245 555555'
97
+ @m2 = RLSM::Monoid.new '012345 103254 235454 324545 455454 544545'
98
+ end
99
+
100
+ it "should calculate left ideals of elements" do
101
+ @m1.left_ideal_of(0).should == [0,1,2,3,4,5]
102
+ @m1.left_ideal_of(1).should == [1,4,5]
103
+ @m1.left_ideal_of(2).should == [2,3,5]
104
+ @m1.left_ideal_of(3).should == [2,3,5]
105
+ @m1.left_ideal_of(4).should == [1,4,5]
106
+ @m1.left_ideal_of(5).should == [5]
107
+ end
108
+
109
+ it "should calculate right ideals of elements" do
110
+ @m1.right_ideal_of(0).should == [0,1,2,3,4,5]
111
+ @m1.right_ideal_of(1).should == [1,3,5]
112
+ @m1.right_ideal_of(2).should == [2,4,5]
113
+ @m1.right_ideal_of(3).should == [1,3,5]
114
+ @m1.right_ideal_of(4).should == [2,4,5]
115
+ @m1.right_ideal_of(5).should == [5]
116
+ end
117
+
118
+ it "should calculate ideals of elements" do
119
+ @m1.ideal_of(0).should == [0,1,2,3,4,5]
120
+ @m1.ideal_of(1).should == [1,2,3,4,5]
121
+ @m1.ideal_of(2).should == [1,2,3,4,5]
122
+ @m1.ideal_of(3).should == [1,2,3,4,5]
123
+ @m1.ideal_of(4).should == [1,2,3,4,5]
124
+ @m1.ideal_of(5).should == [5]
125
+ end
126
+
127
+ it "should calculate L-classes of elements" do
128
+ @m1.l_class_of(0).should == [0]
129
+ @m1.l_class_of(1).should == [1,4]
130
+ @m1.l_class_of(2).should == [2,3]
131
+ @m1.l_class_of(3).should == [2,3]
132
+ @m1.l_class_of(4).should == [1,4]
133
+ @m1.l_class_of(5).should == [5]
134
+ end
135
+
136
+ it "should calculate R-classes of elements" do
137
+ @m1.r_class_of(0).should == [0]
138
+ @m1.r_class_of(1).should == [1,3]
139
+ @m1.r_class_of(2).should == [2,4]
140
+ @m1.r_class_of(3).should == [1,3]
141
+ @m1.r_class_of(4).should == [2,4]
142
+ @m1.r_class_of(5).should == [5]
143
+ end
144
+
145
+ # it "should calculate J-classes of elements" do
146
+ # @m1.j_class_of(0).should == [0]
147
+ # @m1.j_class_of(1).should == [1,2,3,4]
148
+ # @m1.j_class_of(2).should == [1,2,3,4]
149
+ # @m1.j_class_of(3).should == [1,2,3,4]
150
+ # @m1.j_class_of(4).should == [1,2,3,4]
151
+ # @m1.j_class_of(5).should == [5]
152
+ # end
153
+
154
+ it "should calculate H-classes of elements" do
155
+ @m1.h_class_of(0).should == [0]
156
+ @m1.h_class_of(1).should == [1]
157
+ @m1.h_class_of(2).should == [2]
158
+ @m1.h_class_of(3).should == [3]
159
+ @m1.h_class_of(4).should == [4]
160
+ @m1.h_class_of(5).should == [5]
161
+ end
162
+
163
+ it "should calculate D-classes of elements" do
164
+ @m1.d_class_of(0).should == [0]
165
+ @m1.d_class_of(1).should == [1,2,3,4]
166
+ @m1.d_class_of(2).should == [1,2,3,4]
167
+ @m1.d_class_of(3).should == [1,2,3,4]
168
+ @m1.d_class_of(4).should == [1,2,3,4]
169
+ @m1.d_class_of(5).should == [5]
170
+ end
171
+
172
+ it "should detect aperiodicity" do
173
+ @m1.aperiodic?.should == true
174
+ @m2.aperiodic?.should == false
175
+ end
176
+ end
177
+
178
+ describe RLSM::Monoid do
179
+ before :each do
180
+ @m1 = RLSM::Monoid.new '0'
181
+ @m2 = RLSM::Monoid.new '01 10'
182
+ @m3 = RLSM::Monoid.new '01 11'
183
+ @m4 = RLSM::Monoid.new '012 102 222'
184
+ end
185
+
186
+ it "should detect a null element" do
187
+ @m1.null_element.should == false
188
+ @m2.null_element.should == false
189
+ @m3.null_element.should == 1
190
+ @m4.null_element.should == 2
191
+ end
192
+
193
+ it "should detect idempotent elements" do
194
+ [@m1, @m2, @m3].each { |m| m.idempotent?(0).should == true }
195
+ @m2.idempotent?(1).should == false
196
+ @m3.idempotent?(1).should == true
197
+ @m4.idempotent?(2).should == true
198
+ @m4.idempotent?(1).should == false
199
+ end
200
+
201
+ it "should find all idempotents" do
202
+ @m1.idempotents.should == [0]
203
+ @m2.idempotents.should == [0]
204
+ @m3.idempotents.should == [0,1]
205
+ @m4.idempotents.should == [0,2]
206
+ end
207
+
208
+ it "should decide if all elements are idempotent" do
209
+ @m1.idempotent?.should == true
210
+ @m2.idempotent?.should == false
211
+ @m3.idempotent?.should == true
212
+ @m4.idempotent?.should == false
213
+ end
214
+ end
215
+
216
+ describe RLSM::Monoid do
217
+ before :each do
218
+ @m1 = RLSM::Monoid.new('0123 1032 2323 3232')
219
+ end
220
+
221
+ it "should calculate all submonoids of a given order upto to isomorphie" do
222
+ @m1.submonoids_of_order(1).should == [RLSM::Monoid.new('0')]
223
+ @m1.submonoids_of_order(2).should == [RLSM::Monoid.new('01 10'), RLSM::Monoid.new('01 11')]
224
+ @m1.submonoids_of_order(3).should == [RLSM::Monoid.new('012 112 221')]
225
+ @m1.submonoids_of_order(4).should == [@m1]
226
+ end
227
+
228
+ it "should calculate all submonoids upto to isomorphie" do
229
+ @m1.submonoids.should == [RLSM::Monoid.new('0'), RLSM::Monoid.new('01 10'), RLSM::Monoid.new('01 11'),RLSM::Monoid.new('012 112 221'), @m1]
230
+
231
+ RLSM::Monoid.new('0').submonoids.should == [RLSM::Monoid.new('0')]
232
+ end
233
+
234
+ it "should calculate all proper submonoids upto to isomorphie" do
235
+ @m1.proper_submonoids.should == [RLSM::Monoid.new('01 10'), RLSM::Monoid.new('01 11'),RLSM::Monoid.new('012 112 221')]
236
+
237
+ RLSM::Monoid.new('0').proper_submonoids.should == []
238
+ end
239
+ end
240
+
241
+ describe RLSM::Monoid do
242
+ ['0', '01 11', '012 112 212', '01234 11111 21212 31133 41234'].each do |tab|
243
+ it "should detect syntacticity of #{tab}" do
244
+ RLSM::Monoid.new(tab).syntactic?.should == true
245
+ end
246
+
247
+ it "should find a disjunctive subset of #{tab}" do
248
+ case tab
249
+ when '0'
250
+ RLSM::Monoid.new(tab).disjunctive_subset.should == []
251
+ when '01 11'
252
+ RLSM::Monoid.new(tab).disjunctive_subset.should == [0]
253
+ when '012 112 212'
254
+ RLSM::Monoid.new(tab).disjunctive_subset.should == [1]
255
+ when '01234 11111 21212 31133 41234'
256
+ RLSM::Monoid.new(tab).disjunctive_subset.should == [0,4]
257
+ end
258
+ end
259
+ end
260
+
261
+ ['0123 1111 2222 3333', '01234 10234 22222 33222 44222'].each do |tab|
262
+ it "should detect nonsyntacticity of #{tab}" do
263
+ RLSM::Monoid.new(tab).syntactic?.should == false
264
+ end
265
+
266
+ it "should not find a disjunctive subset of #{tab}" do
267
+ RLSM::Monoid.new(tab).disjunctive_subset.should be_nil
268
+ end
269
+ end
270
+ end
@@ -0,0 +1,25 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'dfa')
2
+
3
+ describe RLSM::RegExp do
4
+ ['(ab', '(|ab)', '(ab|)', 'ab(*)', '(*a|b)', 'ab()cd'].each do |str|
5
+ it "should raise error for input #{str}" do
6
+ lambda { RLSM::RegExp.new str }.should raise_error(Exception)
7
+ end
8
+ end
9
+
10
+ ['', '&', 'a', 'a|b', 'ab', '(a|b)c', '(a*|bc&&&d)|abc|(a|b|c)*'].each do |s|
11
+ it "should accept the input #{s}" do
12
+ lambda { RLSM::RegExp.new s }.should_not raise_error(Exception)
13
+ end
14
+ end
15
+
16
+ it "should simplify a input" do
17
+ RLSM::RegExp.new('a&&**&&c***(bbbcccaa)**').to_s.should == 'ac*(bbbcccaa)*'
18
+ end
19
+
20
+ it "should convert a regexp to an dfa" do
21
+ dfa1 = RLSM::RegExp.new('(a|b)aa*(&|b)a*').to_dfa
22
+ dfa1.states.size.should == 4
23
+ dfa1.final_states.map {|f| f.label}.sort.should == ['1', '2'].sort
24
+ end
25
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: asmodis-rlsm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - asmodis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-10-19 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: RLSM contains the three classes DFA, Monoid and REgExp for work with regular languages.
17
+ email: g.diemant@gmx.net
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ - LICENCE
25
+ files:
26
+ - LICENCE
27
+ - README
28
+ - lib/monkey_patching.rb
29
+ - lib/monoid.rb
30
+ - lib/mgen.rb
31
+ - lib/rlsm_regexp.rb
32
+ - lib/dfa.rb
33
+ - lib/rlsm.rb
34
+ has_rdoc: true
35
+ homepage: http://github.org/asmodis/rlsm
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --main
39
+ - README
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ requirements: []
55
+
56
+ rubyforge_project:
57
+ rubygems_version: 1.2.0
58
+ signing_key:
59
+ specification_version: 2
60
+ summary: Classes for work with formal languages
61
+ test_files:
62
+ - spec/monoid_spec.rb
63
+ - spec/dfa_spec.rb
64
+ - spec/regexp_spec.rb