stamina 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. data/.gemtest +0 -0
  2. data/CHANGELOG.md +22 -0
  3. data/Gemfile +2 -0
  4. data/Gemfile.lock +33 -0
  5. data/LICENCE.md +22 -0
  6. data/Manifest.txt +16 -0
  7. data/README.md +78 -0
  8. data/Rakefile +23 -0
  9. data/bin/adl2dot +12 -0
  10. data/bin/classify +12 -0
  11. data/bin/redblue +12 -0
  12. data/bin/rpni +12 -0
  13. data/example/adl/automaton.adl +49 -0
  14. data/example/adl/sample.adl +53 -0
  15. data/example/basic/characteristic_sample.adl +32 -0
  16. data/example/basic/target.adl +9 -0
  17. data/example/competition/31_test.adl +1500 -0
  18. data/example/competition/31_training.adl +1759 -0
  19. data/lib/stamina.rb +19 -0
  20. data/lib/stamina/adl.rb +298 -0
  21. data/lib/stamina/automaton.rb +1237 -0
  22. data/lib/stamina/automaton/walking.rb +336 -0
  23. data/lib/stamina/classifier.rb +37 -0
  24. data/lib/stamina/command/adl2dot_command.rb +73 -0
  25. data/lib/stamina/command/classify_command.rb +57 -0
  26. data/lib/stamina/command/redblue_command.rb +58 -0
  27. data/lib/stamina/command/rpni_command.rb +58 -0
  28. data/lib/stamina/command/stamina_command.rb +79 -0
  29. data/lib/stamina/errors.rb +20 -0
  30. data/lib/stamina/induction/commons.rb +170 -0
  31. data/lib/stamina/induction/redblue.rb +264 -0
  32. data/lib/stamina/induction/rpni.rb +188 -0
  33. data/lib/stamina/induction/union_find.rb +377 -0
  34. data/lib/stamina/input_string.rb +123 -0
  35. data/lib/stamina/loader.rb +0 -0
  36. data/lib/stamina/markable.rb +42 -0
  37. data/lib/stamina/sample.rb +190 -0
  38. data/lib/stamina/version.rb +14 -0
  39. data/stamina.gemspec +190 -0
  40. data/stamina.noespec +35 -0
  41. data/tasks/debug_mail.rake +78 -0
  42. data/tasks/debug_mail.txt +13 -0
  43. data/tasks/gem.rake +68 -0
  44. data/tasks/spec_test.rake +79 -0
  45. data/tasks/unit_test.rake +77 -0
  46. data/tasks/yard.rake +51 -0
  47. data/test/stamina/adl_test.rb +491 -0
  48. data/test/stamina/automaton_additional_test.rb +190 -0
  49. data/test/stamina/automaton_classifier_test.rb +155 -0
  50. data/test/stamina/automaton_test.rb +1092 -0
  51. data/test/stamina/automaton_to_dot_test.rb +64 -0
  52. data/test/stamina/automaton_walking_test.rb +206 -0
  53. data/test/stamina/exit.rb +3 -0
  54. data/test/stamina/induction/induction_test.rb +70 -0
  55. data/test/stamina/induction/redblue_mergesamestatebug_expected.adl +19 -0
  56. data/test/stamina/induction/redblue_mergesamestatebug_pta.dot +64 -0
  57. data/test/stamina/induction/redblue_mergesamestatebug_sample.adl +9 -0
  58. data/test/stamina/induction/redblue_test.rb +83 -0
  59. data/test/stamina/induction/redblue_universal_expected.adl +4 -0
  60. data/test/stamina/induction/redblue_universal_sample.adl +5 -0
  61. data/test/stamina/induction/rpni_inria_expected.adl +7 -0
  62. data/test/stamina/induction/rpni_inria_sample.adl +9 -0
  63. data/test/stamina/induction/rpni_test.rb +129 -0
  64. data/test/stamina/induction/rpni_test_pta.dot +22 -0
  65. data/test/stamina/induction/rpni_universal_expected.adl +4 -0
  66. data/test/stamina/induction/rpni_universal_sample.adl +4 -0
  67. data/test/stamina/induction/union_find_test.rb +124 -0
  68. data/test/stamina/input_string_test.rb +323 -0
  69. data/test/stamina/markable_test.rb +70 -0
  70. data/test/stamina/randdfa.adl +66 -0
  71. data/test/stamina/sample.adl +4 -0
  72. data/test/stamina/sample_classify_test.rb +149 -0
  73. data/test/stamina/sample_test.rb +218 -0
  74. data/test/stamina/small_dfa.dot +16 -0
  75. data/test/stamina/small_dfa.gif +0 -0
  76. data/test/stamina/small_nfa.dot +18 -0
  77. data/test/stamina/small_nfa.gif +0 -0
  78. data/test/stamina/stamina_test.rb +69 -0
  79. data/test/test_all.rb +7 -0
  80. metadata +279 -0
@@ -0,0 +1,64 @@
1
+ require 'test/unit'
2
+ require 'stamina'
3
+ module Stamina
4
+ module Utils
5
+ class DotTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @automaton = Automaton.new do |a|
9
+ add_state(:initial => true, :accepting => false)
10
+ add_state(:initial => false, :accepting => true)
11
+ add_state(:initial => false, :accepting => true, :error => true)
12
+ connect(0, 1, 'a')
13
+ connect(1, 0, 'b')
14
+ connect(1, 2, 'a')
15
+ connect(2, 2, nil)
16
+ end
17
+ end
18
+
19
+ def test_attributes2dot
20
+ attrs = {:label => 'hello'}
21
+ assert_equal 'label="hello"', @automaton.send(:attributes2dot, attrs)
22
+ attrs = {:label => 'hello', :color => 'red'}
23
+ assert_equal 'color="red" label="hello"', @automaton.send(:attributes2dot, attrs)
24
+ attrs = {:label => 'O"Neil'}
25
+ assert_equal 'label="O\"Neil"', @automaton.send(:attributes2dot, attrs)
26
+ end
27
+
28
+ def test_automaton_to_dot_with_default_rewriter
29
+ expected = <<-EOF
30
+ #digraph G {
31
+ # graph [rankdir="LR"];
32
+ # 0 [color="black" fillcolor="green" shape="circle" style="filled"];
33
+ # 1 [color="black" fillcolor="white" shape="doublecircle" style="filled"];
34
+ # 2 [color="black" fillcolor="red" shape="doublecircle" style="filled"];
35
+ # 0 -> 1 [label="a"];
36
+ # 1 -> 0 [label="b"];
37
+ # 1 -> 2 [label="a"];
38
+ # 2 -> 2 [label=""];
39
+ #}
40
+ EOF
41
+ expected = expected.gsub(/^\s+#/,'')
42
+ assert_equal expected, @automaton.to_dot
43
+ end
44
+
45
+ def test_automaton_with_specific_rewriter
46
+ expected = <<-EOF
47
+ #digraph G {
48
+ # graph [];
49
+ # 0 [accepting="false" initial="true"];
50
+ # 1 [accepting="true" initial="false"];
51
+ # 2 [accepting="true" error="true" initial="false"];
52
+ # 0 -> 1 [symbol="a"];
53
+ # 1 -> 0 [symbol="b"];
54
+ # 1 -> 2 [symbol="a"];
55
+ # 2 -> 2 [symbol=""];
56
+ #}
57
+ EOF
58
+ expected = expected.gsub(/^\s+#/,'')
59
+ assert_equal expected, @automaton.to_dot {|elm,kind| elm.data}
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,206 @@
1
+ require 'test/unit'
2
+ require 'stamina/stamina_test'
3
+ module Stamina
4
+ class Automaton
5
+ # Tests Walking module on Automaton class
6
+ class WalkingTest < StaminaTest
7
+
8
+ # Tests Walking#step on examples
9
+ def test_step_on_examples
10
+ assert_equal([], @small_dfa.step(0, 'b'))
11
+ assert_equal(@small_dfa.ith_states(1), @small_dfa.step(0, 'a'))
12
+ assert_equal(@small_dfa.ith_states(1,3), @small_dfa.step([0,1], 'a').sort)
13
+ assert_equal(@small_dfa.ith_states(1), @small_dfa.step([0,2], 'a').sort)
14
+
15
+ assert_equal([], @small_nfa.step(0, 'b'))
16
+ assert_equal(@small_nfa.ith_states(1), @small_nfa.step(0, 'a'))
17
+ assert_equal([], @small_nfa.step(2, 'b'))
18
+ assert_equal(@small_nfa.ith_states(2,3), @small_nfa.step(1, 'b').sort)
19
+ assert_equal(@small_nfa.ith_states(0,1), @small_nfa.step([0,3], 'a').sort)
20
+ end
21
+
22
+ # Tests Walking#dfa_step on examples
23
+ def test_step_on_examples
24
+ assert_equal(nil, @small_dfa.dfa_step(0, 'b'))
25
+ assert_equal(@small_dfa.ith_state(1), @small_dfa.dfa_step(0, 'a'))
26
+ assert_equal(@small_dfa.ith_states(1), @small_dfa.dfa_step([0], 'a'))
27
+ assert_equal(@small_dfa.ith_states(1,3), @small_dfa.dfa_step([0,1], 'a').sort)
28
+ assert_equal(@small_dfa.ith_states(1), @small_dfa.dfa_step([0,2], 'a').sort)
29
+ end
30
+
31
+ # Tests Walking#delta on examples
32
+ def test_delta_on_examples
33
+ assert_equal([], @small_dfa.delta(0, 'b'))
34
+ assert_equal(@small_dfa.ith_states(1), @small_dfa.delta(0, 'a'))
35
+ assert_equal(@small_dfa.ith_states(1,3), @small_dfa.delta([0,1], 'a').sort)
36
+ assert_equal(@small_dfa.ith_states(1), @small_dfa.delta([0,2], 'a').sort)
37
+
38
+ assert_equal([], @small_nfa.delta(0, 'b'))
39
+ assert_equal(@small_nfa.ith_states(1), @small_nfa.delta(0, 'a'))
40
+ assert_equal(@small_nfa.ith_states(1,2,3), @small_nfa.delta(2, 'b').sort)
41
+ assert_equal(@small_nfa.ith_states(1,2,3), @small_nfa.delta(1, 'b').sort)
42
+ assert_equal(@small_nfa.ith_states(0,1), @small_nfa.delta([0,3], 'a').sort)
43
+ end
44
+
45
+ # Tests Walking#dfa_delta on examples
46
+ def test_delta_on_examples
47
+ assert_equal(nil, @small_dfa.dfa_delta(0, 'b'))
48
+ assert_equal(@small_dfa.ith_state(1), @small_dfa.dfa_delta(0, 'a'))
49
+ assert_equal(@small_dfa.ith_states(1,3), @small_dfa.dfa_delta([0,1], 'a').sort)
50
+ assert_equal(@small_dfa.ith_states(1), @small_dfa.dfa_delta([0,2], 'a').sort)
51
+ end
52
+
53
+ # Tests Walking#split on examples
54
+ def test_split_on_examples
55
+ assert_equal([[], @small_dfa.ith_states(3), []], @small_dfa.split('?'))
56
+ assert_equal([[], @small_dfa.ith_states(3), ['a']], @small_dfa.split('? a'))
57
+ assert_equal([['b'], @small_dfa.ith_states(2), []], @small_dfa.split('? b'))
58
+ assert_equal([['b'], @small_dfa.ith_states(2), ['a']], @small_dfa.split('? b a'))
59
+ assert_equal([['b','c'], @small_dfa.ith_states(0), []], @small_dfa.split('? b c'))
60
+
61
+ assert_equal([[], @small_nfa.ith_states(0,3), []], @small_nfa.split('?'))
62
+ assert_equal([[], @small_nfa.ith_states(0,3), ['b']], @small_nfa.split('? b'))
63
+ assert_equal([['a'], @small_nfa.ith_states(0,1), []], @small_nfa.split('? a',nil,true))
64
+ assert_equal([['a'], @small_nfa.ith_states(0,1), ['c']], @small_nfa.split('? a c',nil,true))
65
+ assert_equal([['a','b'], @small_nfa.ith_states(1,2,3), []], @small_nfa.split('? a b',nil,true))
66
+ end
67
+
68
+ # Tests Walking#dfa_split on examples
69
+ def test_split_on_examples
70
+ assert_equal([[], @small_dfa.ith_state(3), []], @small_dfa.dfa_split('?'))
71
+ assert_equal([[], @small_dfa.ith_state(3), ['a']], @small_dfa.dfa_split('? a'))
72
+ assert_equal([['b'], @small_dfa.ith_state(2), []], @small_dfa.dfa_split('? b'))
73
+ assert_equal([['b'], @small_dfa.ith_state(2), ['a']], @small_dfa.dfa_split('? b a'))
74
+ assert_equal([['b','c'], @small_dfa.ith_state(0), []], @small_dfa.dfa_split('? b c'))
75
+ assert_equal([['b','c'], @small_dfa.ith_states(0), []], @small_dfa.dfa_split('? b c',[3]))
76
+ end
77
+
78
+ # Tests Walking#reached on examples
79
+ def test_reached_on_examples
80
+ assert_equal([], @small_dfa.reached('? a a'))
81
+ assert_equal(@small_dfa.ith_states(2), @small_dfa.reached('? b'))
82
+ assert_equal(@small_dfa.ith_states(1), @small_dfa.reached('? b c a c'))
83
+ assert_equal(@small_dfa.ith_states(1), @small_dfa.reached('? a c', @small_dfa.ith_state(0)))
84
+ assert_equal(@small_dfa.ith_states(1), @small_dfa.reached('? a c',0))
85
+ assert_equal(@small_dfa.ith_states(1), @small_dfa.reached('? a',[0]))
86
+ assert_equal(@small_dfa.ith_states(1,3), @small_dfa.reached('? a',[0,1]))
87
+ assert_equal(@small_dfa.ith_states(2), @small_dfa.reached('? b',[3,1]))
88
+ assert_equal(@small_dfa.ith_states(2), @small_dfa.reached('? b',[0,3,1]))
89
+
90
+ assert_equal(@small_nfa.ith_states(0,3), @small_nfa.reached('?').sort)
91
+ assert_equal(@small_nfa.ith_states(0,1), @small_nfa.reached('? a').sort)
92
+ assert_equal(@small_nfa.ith_states(1,2,3), @small_nfa.reached('? a b').sort)
93
+ end
94
+
95
+ # Tests Walking#dfa_reached on examples
96
+ def test_dfa_reached_on_examples
97
+ assert_equal(nil, @small_dfa.dfa_reached('? a a'))
98
+ assert_equal(@small_dfa.ith_state(2), @small_dfa.dfa_reached('? b'))
99
+ assert_equal(@small_dfa.ith_state(1), @small_dfa.dfa_reached('? b c a c'))
100
+ assert_equal(@small_dfa.ith_state(1), @small_dfa.dfa_reached('? a c', @small_dfa.ith_state(0)))
101
+ assert_equal(@small_dfa.ith_state(1), @small_dfa.dfa_reached('? a c',0))
102
+ assert_equal(@small_dfa.ith_states(1), @small_dfa.dfa_reached('? a',[0]))
103
+ assert_equal(@small_dfa.ith_states(1,3), @small_dfa.dfa_reached('? a',[0,1]))
104
+ assert_equal(@small_dfa.ith_states(2), @small_dfa.dfa_reached('? b',[3,1]))
105
+ assert_equal(@small_dfa.ith_states(2), @small_dfa.dfa_reached('? b',[0,3,1]))
106
+ end
107
+
108
+ # Tests Walking#dfa_reached
109
+ def test_dfa_reached_on_simple_deterministic_automaton
110
+ s0, s1 = nil
111
+ fa = Automaton.new do |fa|
112
+ s0 = fa.add_state(:initial => true)
113
+ s1 = fa.add_state
114
+ fa.connect(s0, s1, 'a')
115
+ fa.connect(s1, s0, 'b')
116
+ end
117
+ assert_equal(s0, fa.dfa_reached('? '))
118
+ assert_equal(s1, fa.dfa_reached('? a'))
119
+ assert_equal(s0, fa.dfa_reached('? a b'))
120
+ assert_equal(s1, fa.dfa_reached('? a b a'))
121
+ assert_equal(s0, fa.dfa_reached('? a b a b'))
122
+ assert_nil(fa.dfa_reached('? a a'))
123
+ assert_nil(fa.dfa_reached('? b'))
124
+ assert_nil(fa.dfa_reached('? a b b'))
125
+ end
126
+
127
+ # Tests Walking#reached on a deterministic automaton
128
+ def test_reached_on_simple_deterministic_automaton
129
+ s0, s1 = nil
130
+ fa = Automaton.new do |fa|
131
+ s0 = fa.add_state(:initial => true)
132
+ s1 = fa.add_state
133
+ fa.connect(s0, s1, 'a')
134
+ fa.connect(s1, s0, 'b')
135
+ end
136
+ assert_equal([s0], fa.reached('?'))
137
+ assert_equal([s1], fa.reached('? a'))
138
+ assert_equal([s0], fa.reached('? a b'))
139
+ assert_equal([s1], fa.reached('? a b a'))
140
+ assert_equal([s0], fa.reached('? a b a b'))
141
+ assert_equal([], fa.reached('? a a'))
142
+ assert_equal([], fa.reached('? b'))
143
+ assert_equal([], fa.reached('? a b b'))
144
+ end
145
+
146
+ # Tests Walking#reached on a non-deterministic automaton.
147
+ def test_reached_on_non_deterministic_automaton
148
+ s0, s1, s2, s3, s4 = nil
149
+ fa = Automaton.new do |fa|
150
+ s0 = fa.add_state(:initial => true) #
151
+ s1, s2, s3, s4 = fa.add_n_states(4) # s1 -b-> s3
152
+ fa.connect(s0, s1, 'a') # a
153
+ fa.connect(s0, s2, 'a') # s0
154
+ fa.connect(s1, s3, 'b') # a
155
+ fa.connect(s2, s4, 'c') # s2 -c-> s4
156
+ end #
157
+ assert_equal([], s2.delta('b'))
158
+ assert_equal([s0], fa.reached('?'))
159
+ assert_equal([], fa.reached('? c'))
160
+ assert_equal([s1,s2], fa.reached('? a').sort)
161
+ assert_equal([s3], fa.reached('? a b'))
162
+ assert_equal([s4], fa.reached('? a c'))
163
+ assert_equal([s1,s2], fa.reached('? a').sort)
164
+
165
+ # add a looping b on s2
166
+ fa.connect(s2, s2, 'b')
167
+ assert_equal([s2,s3], fa.reached('? a b').sort)
168
+
169
+ # add an epsilon from s2 to s1
170
+ fa.connect(s2, s1, nil)
171
+ assert_equal([s1,s2], fa.reached('? a').sort)
172
+ assert_equal([s1,s2,s3], fa.reached('? a b').sort)
173
+ end
174
+
175
+ # Tests Walking#accepts? and Walking#rejects?
176
+ def test_accepts_and_rejects
177
+ fa = Automaton.new do
178
+ add_state(:initial => true)
179
+ add_state(:accepting => true)
180
+ add_state(:error => true)
181
+ add_state(:accepting => true, :error => true)
182
+ connect(0,1,'a')
183
+ connect(1,0,'b')
184
+ connect(0,2,'b')
185
+ connect(1,3,'a')
186
+ end
187
+ assert_equal(false, fa.accepts?("?"))
188
+ assert_equal(true, fa.accepts?("? a"))
189
+ assert_equal(false, fa.accepts?("? a b"))
190
+ assert_equal(true, fa.accepts?("? a b a"))
191
+ assert_equal(false, fa.accepts?("? z"), "not accepts? on no state")
192
+ assert_equal(false, fa.accepts?("? b"), "not accepts? on non accepting error state")
193
+ assert_equal(false, fa.accepts?("? a a"), "not accepts? on accepting error state")
194
+
195
+ assert_equal(true, fa.rejects?("?"))
196
+ assert_equal(false, fa.rejects?("? a"))
197
+ assert_equal(true, fa.rejects?("? a b"))
198
+ assert_equal(false, fa.rejects?("? a b a"))
199
+ assert_equal(true, fa.rejects?("? z"), "rejects? on no state")
200
+ assert_equal(true, fa.rejects?("? b"), "rejects? on non accepting error state")
201
+ assert_equal(true, fa.rejects?("? a a"), "rejects? on accepting error state")
202
+ end
203
+
204
+ end # class WalkingTest
205
+ end # class Automaton
206
+ end # module Stamina
@@ -0,0 +1,3 @@
1
+ # This file is only used in the test, to check that some parsing method do not
2
+ # execute ruby code. If not the case, a SystemExit will be raised
3
+ + Kernel.exit(-1)
@@ -0,0 +1,70 @@
1
+ require 'test/unit'
2
+ require 'stamina'
3
+ require 'stamina/induction/union_find'
4
+ require 'stamina/induction/commons'
5
+ module Stamina
6
+ module Induction
7
+ class InductionTest < Test::Unit::TestCase
8
+ include Stamina::Induction::Commons
9
+
10
+ # Asserts that two states are equivalent and recurse.
11
+ def equivalent_states!(s1, s2, equivalences)
12
+ return "#{s1.index} and #{s2.index} don't agree on flags" \
13
+ unless s1.initial? == s2.initial? \
14
+ and s1.accepting? == s2.accepting? \
15
+ and s1.error? == s2.error?
16
+ return "#{s1.index} and #{s2.index} don't agree on out symbols #{s1.out_symbols.inspect} #{s2.out_symbols.inspect}"\
17
+ unless s1.out_symbols.sort == s2.out_symbols.sort
18
+ equivalences[s1.index] = s2.index
19
+ s1.out_symbols.each do |symbol|
20
+ s1_target = s1.dfa_step(symbol)
21
+ s2_target = s2.dfa_step(symbol)
22
+ return false if (s1_target.nil? or s2_target.nil?)
23
+ if equivalences.has_key?(s1_target.index)
24
+ return "#{s1.index} and #{s2.index} don't agree on #{symbol}"\
25
+ unless equivalences[s1_target.index]==s2_target.index
26
+ else
27
+ return msg \
28
+ if msg=equivalent_states!(s1_target, s2_target, equivalences)
29
+ end
30
+ end
31
+ nil
32
+ end
33
+
34
+ # Checks if two DFAs are equivalent.
35
+ def equivalent?(dfa1, dfa2)
36
+ return "not same number of states" unless dfa1.state_count==dfa2.state_count
37
+ equivalent_states!(dfa1.initial_state, dfa2.initial_state, {})
38
+ end
39
+
40
+ # Puts a PTA under @pta
41
+ def setup
42
+ @sample = Stamina::ADL.parse_sample <<-EOF
43
+ +
44
+ - a
45
+ - a a
46
+ + a b
47
+ - b a b a
48
+ + b a b b
49
+ + b b
50
+ EOF
51
+ @pta = sample2pta(@sample)
52
+ end
53
+
54
+ # Returns index-th state of the PTA
55
+ def s(index)
56
+ @pta.ith_state(index)
57
+ end
58
+
59
+ # Factors a UnionFind instance from the PTA under @pta.
60
+ def factor_ufds
61
+ pta2ufds(@pta)
62
+ end
63
+
64
+ # Just to avoid a stupid ruby error on empty test units.
65
+ def test_empty
66
+ end
67
+
68
+ end
69
+ end # module Induction
70
+ end # module Stamina
@@ -0,0 +1,19 @@
1
+ 6 12
2
+ 0 true false
3
+ 1 false true
4
+ 2 false false
5
+ 3 false false
6
+ 4 false false
7
+ 5 false false
8
+ 0 1 0
9
+ 0 1 1
10
+ 1 2 0
11
+ 1 1 1
12
+ 2 0 0
13
+ 2 3 1
14
+ 3 4 0
15
+ 3 4 1
16
+ 4 5 0
17
+ 4 1 1
18
+ 5 0 0
19
+ 5 2 1
@@ -0,0 +1,64 @@
1
+ digraph G {
2
+ graph [rankdir="LR"];
3
+ 0 [color="black" fillcolor="green" shape="circle" style="filled"];
4
+ 1 [color="black" fillcolor="white" shape="doublecircle" style="filled"];
5
+ 2 [color="black" fillcolor="white" shape="circle" style="filled"];
6
+ 3 [color="black" fillcolor="white" shape="circle" style="filled"];
7
+ 4 [color="black" fillcolor="white" shape="circle" style="filled"];
8
+ 5 [color="black" fillcolor="white" shape="circle" style="filled"];
9
+ 6 [color="black" fillcolor="white" shape="circle" style="filled"];
10
+ 7 [color="black" fillcolor="white" shape="circle" style="filled"];
11
+ 8 [color="black" fillcolor="white" shape="circle" style="filled"];
12
+ 9 [color="black" fillcolor="white" shape="circle" style="filled"];
13
+ 10 [color="black" fillcolor="white" shape="circle" style="filled"];
14
+ 11 [color="black" fillcolor="white" shape="circle" style="filled"];
15
+ 12 [color="black" fillcolor="red" shape="circle" style="filled"];
16
+ 13 [color="black" fillcolor="white" shape="circle" style="filled"];
17
+ 14 [color="black" fillcolor="white" shape="circle" style="filled"];
18
+ 15 [color="black" fillcolor="red" shape="circle" style="filled"];
19
+ 16 [color="black" fillcolor="red" shape="circle" style="filled"];
20
+ 17 [color="black" fillcolor="white" shape="circle" style="filled"];
21
+ 18 [color="black" fillcolor="red" shape="circle" style="filled"];
22
+ 19 [color="black" fillcolor="white" shape="doublecircle" style="filled"];
23
+ 20 [color="black" fillcolor="white" shape="circle" style="filled"];
24
+ 21 [color="black" fillcolor="white" shape="circle" style="filled"];
25
+ 22 [color="black" fillcolor="white" shape="doublecircle" style="filled"];
26
+ 23 [color="black" fillcolor="white" shape="circle" style="filled"];
27
+ 24 [color="black" fillcolor="white" shape="circle" style="filled"];
28
+ 25 [color="black" fillcolor="white" shape="circle" style="filled"];
29
+ 26 [color="black" fillcolor="white" shape="circle" style="filled"];
30
+ 27 [color="black" fillcolor="white" shape="doublecircle" style="filled"];
31
+ 28 [color="black" fillcolor="white" shape="circle" style="filled"];
32
+ 29 [color="black" fillcolor="white" shape="circle" style="filled"];
33
+ 30 [color="black" fillcolor="white" shape="doublecircle" style="filled"];
34
+ 0 -> 2 [label="1"];
35
+ 2 -> 4 [label="1"];
36
+ 4 -> 7 [label="1"];
37
+ 7 -> 11 [label="1"];
38
+ 11 -> 15 [label="0"];
39
+ 0 -> 1 [label="0"];
40
+ 1 -> 3 [label="0"];
41
+ 3 -> 6 [label="1"];
42
+ 6 -> 10 [label="1"];
43
+ 10 -> 14 [label="0"];
44
+ 14 -> 18 [label="1"];
45
+ 18 -> 20 [label="0"];
46
+ 20 -> 22 [label="1"];
47
+ 18 -> 21 [label="1"];
48
+ 21 -> 23 [label="0"];
49
+ 23 -> 24 [label="0"];
50
+ 24 -> 26 [label="1"];
51
+ 26 -> 28 [label="1"];
52
+ 28 -> 29 [label="0"];
53
+ 29 -> 30 [label="1"];
54
+ 24 -> 25 [label="0"];
55
+ 25 -> 27 [label="0"];
56
+ 14 -> 17 [label="0"];
57
+ 17 -> 19 [label="1"];
58
+ 6 -> 9 [label="0"];
59
+ 9 -> 13 [label="0"];
60
+ 13 -> 16 [label="1"];
61
+ 3 -> 5 [label="0"];
62
+ 5 -> 8 [label="0"];
63
+ 8 -> 12 [label="0"];
64
+ }
@@ -0,0 +1,9 @@
1
+ - 1 1 1 1 0
2
+ + 0
3
+ - 0 0 1 1 0 1
4
+ + 0 0 1 1 0 1 0 1
5
+ + 0 0 1 1 0 1 1 0 0 1 1 0 1
6
+ + 0 0 1 1 0 1 1 0 0 0 0
7
+ + 0 0 1 1 0 0 1
8
+ - 0 0 1 0 0 1
9
+ - 0 0 0 0 0
@@ -0,0 +1,83 @@
1
+ require File.join(File.dirname(__FILE__), "induction_test")
2
+ module Stamina
3
+ module Induction
4
+ class RedBlueTest < Stamina::Induction::InductionTest
5
+
6
+ # Factors a ready to be tested RedBlue instance
7
+ def redblue(ufds)
8
+ redblue = Stamina::Induction::RedBlue.new(:verbose => false)
9
+ redblue.instance_eval do
10
+ @ufds = ufds
11
+ end
12
+ redblue
13
+ end
14
+
15
+ def test_merge_and_determinize_score
16
+ redblue = redblue(factor_ufds)
17
+ assert_equal nil, redblue.merge_and_determinize_score(1, 0)
18
+ assert_equal 1, redblue.merge_and_determinize_score(1, 3)
19
+ assert_equal 1, redblue.merge_and_determinize_score(2, 0)
20
+ end
21
+
22
+ def test_main_whole_execution
23
+ ufds = factor_ufds
24
+ redblue = redblue(ufds)
25
+ assert_equal [0, 1, 0, 1, 0, 1, 0, 0, 1, 0], redblue.main(ufds).to_a
26
+ end
27
+
28
+ def test_execute_whole_execution
29
+ expected = Stamina::ADL.parse_automaton <<-EOF
30
+ 2 4
31
+ 0 true true
32
+ 1 false false
33
+ 0 0 b
34
+ 0 1 a
35
+ 1 0 b
36
+ 1 1 a
37
+ EOF
38
+ dfa = RedBlue.execute(@sample)
39
+ assert_equal true, @sample.correctly_classified_by?(dfa)
40
+ assert_equal @sample.signature, dfa.signature(@sample)
41
+ assert_nil equivalent?(expected, dfa)
42
+ end
43
+
44
+ def test_on_dedicated_examples
45
+ here = File.dirname(__FILE__)
46
+ Dir["#{here}/redblue_*_sample.adl"].each do |sample_file|
47
+ name = (/^redblue_(.*?)_sample.adl$/.match(File.basename(sample_file)))[1]
48
+ sample = Stamina::ADL.parse_sample_file(sample_file)
49
+ expected = Stamina::ADL.parse_automaton_file(File.join(here, "redblue_#{name}_expected.adl"))
50
+ assert sample.correctly_classified_by?(expected)
51
+ dfa = RedBlue.execute(sample)
52
+ assert sample.correctly_classified_by?(dfa)
53
+ assert_equal sample.signature, dfa.signature(sample)
54
+ assert_nil equivalent?(expected, dfa)
55
+ end
56
+ end
57
+
58
+ # Tests on characteristic sample
59
+ def test_on_public_characteristic_example
60
+ example_folder = File.join(File.dirname(__FILE__), '..', '..', '..', 'example', 'basic')
61
+ sample = Stamina::ADL.parse_sample_file(File.join(example_folder, 'characteristic_sample.adl'))
62
+ redblued = Stamina::Induction::RedBlue.execute(sample)
63
+ assert_equal 4, redblued.state_count
64
+ s0, = redblued.initial_state
65
+ s1 = redblued.dfa_step(s0, 'b')
66
+ s2 = redblued.dfa_step(s0, 'a')
67
+ s3 = redblued.dfa_step(s2, 'b')
68
+ assert_equal true, s0.accepting?
69
+ assert_equal true, s3.accepting?
70
+ assert_equal false, s1.accepting?
71
+ assert_equal false, s2.accepting?
72
+ assert_equal s1, s1.dfa_step('a')
73
+ assert_equal s1, s1.dfa_step('b')
74
+ assert_equal s2, s2.dfa_step('a')
75
+ assert_equal s3, s2.dfa_step('b')
76
+ assert_equal s3, s3.dfa_step('b')
77
+ assert_equal s0, s3.dfa_step('a')
78
+ assert_equal sample.signature, redblued.signature(sample)
79
+ end
80
+
81
+ end
82
+ end
83
+ end