nfa2dfa 1.1.1 → 1.1.2

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/lib/state.rb CHANGED
@@ -1,67 +1,72 @@
1
- # To change this template, choose Tools | Templates
2
- # and open the template in the editor.
3
-
4
- require 'graphviz'
5
- require_relative 'transition.rb'
6
-
7
- module Nfa2Dfa
8
- class State
9
- attr_reader :id, :is_final, :graphviz_node, :is_starting
10
-
11
- def initialize(id)
12
- @id = id
13
- @is_final = false
14
- @transitions = Array.new
15
- @graphviz_init = false
16
- @is_starting = false
17
- end
18
-
19
- def to_starting_node
20
- @is_starting = true
21
- end
22
-
23
- def graph_id
24
- is_starting ? (@id + "/init") : @id
25
- end
26
-
27
- def to_graph_node(graphviz_graph)
28
- if @is_final
29
- @graphviz_node = graphviz_graph.add_nodes(graph_id, :shape => "doublecircle")
30
- else
31
- @graphviz_node = graphviz_graph.add_nodes(graph_id, :shape => "circle")
32
- end
33
- @graphviz_init = false
34
- end
35
-
36
- def finalize
37
- @is_final = true
38
- end
39
-
40
- def add_transition(tr)
41
- @transitions.insert(@transitions.size, tr)
42
- end
43
-
44
- def clear_transitions
45
- @transitions.clear
46
- end
47
-
48
- def associate_transitions(all_transitions)
49
- @transitions.clear
50
- @id.split(',').each do |id_part|
51
- all_transitions.each do |transition|
52
- if id_part == transition.beginning_state.id
53
- add_transition(transition)
54
- end
55
- end
56
- end
57
- end
58
-
59
- def get_next(char)
60
- ret_val = Array.new
61
- @transitions.each do |trans|
62
- trans.alphabet == char ? ret_val.insert(ret_val.size, trans.ending_state) : NIL
63
- end
64
- ret_val
65
- end
66
- end
67
- end
1
+ require 'graphviz'
2
+ require_relative 'transition.rb'
3
+ # Part of Nfa2Dfa module
4
+ module Nfa2Dfa
5
+ # State of automaton
6
+ class State
7
+ attr_reader :id, :is_final, :graphviz_node, :is_starting
8
+
9
+ def initialize(id)
10
+ @id = id
11
+ @is_final = false
12
+ @transitions = []
13
+ @graphviz_init = false
14
+ @is_starting = false
15
+ end
16
+
17
+ def to_starting_node
18
+ @is_starting = true
19
+ end
20
+
21
+ def to_s
22
+ @id.to_s
23
+ end
24
+
25
+ def graph_id
26
+ is_starting ? (@id + '/init') : @id
27
+ end
28
+
29
+ def to_graph_node(viz_graph)
30
+ if @is_final
31
+ @graphviz_node = viz_graph.add_nodes(
32
+ graph_id, :shape => 'doublecircle')
33
+ else
34
+ @graphviz_node = viz_graph.add_nodes(graph_id, :shape => 'circle')
35
+ end
36
+ @graphviz_init = false
37
+ end
38
+
39
+ def finalize
40
+ @is_final = true
41
+ end
42
+
43
+ def add_transition(tr)
44
+ @transitions.insert(@transitions.size, tr)
45
+ end
46
+
47
+ def clear_transitions
48
+ @transitions.clear
49
+ end
50
+
51
+ def associate_transitions(all_transitions)
52
+ @transitions.clear
53
+ @id.split(',').each do |id_part|
54
+ all_transitions.each do |transition|
55
+ if id_part == transition.beginning_state.id
56
+ add_transition(transition)
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ def get_next(char)
63
+ ret_val = []
64
+ @transitions.each do |trans|
65
+ if trans.alphabet == char
66
+ ret_val.insert(ret_val.size, trans.ending_state)
67
+ end
68
+ end
69
+ ret_val
70
+ end
71
+ end
72
+ end
data/lib/transition.rb CHANGED
@@ -1,24 +1,31 @@
1
-
2
- require 'graphviz'
3
- require_relative 'state.rb'
4
-
5
- module Nfa2Dfa
6
- class Transition
7
-
8
- attr_reader :beginning_state, :alphabet, :ending_state
9
-
10
- def initialize(beg_state, alphabet, end_state)
11
- @beginning_state = beg_state
12
- @alphabet = alphabet
13
- @ending_state = end_state
14
- end
15
-
16
- def to_graph_transition(graphviz_graph)
17
- graphviz_graph.add_edges( @beginning_state.graphviz_node, @ending_state.graphviz_node, :label => @alphabet)
18
- end
19
-
20
- def print
21
- puts @beginning_state.id + "-" + @alphabet + "-" + @ending_state.id
22
- end
23
- end
24
- end
1
+ require 'graphviz'
2
+ require_relative 'state.rb'
3
+ # Part of Nfa2Dfa module
4
+ module Nfa2Dfa
5
+ # Transition between states
6
+ class Transition
7
+
8
+ attr_reader :beginning_state, :alphabet, :ending_state
9
+
10
+ def initialize(beg_state, alphabet, end_state)
11
+ @beginning_state = beg_state
12
+ @alphabet = alphabet
13
+ @ending_state = end_state
14
+ end
15
+
16
+ def to_graph_transition(graphviz_graph)
17
+ graphviz_graph.add_edges(
18
+ @beginning_state.graphviz_node,
19
+ @ending_state.graphviz_node, :label => @alphabet)
20
+ end
21
+
22
+ def to_s
23
+ ret = @beginning_state.to_s + '-' + alphabet + '-' + @ending_state.to_s
24
+ ret
25
+ end
26
+
27
+ def print
28
+ puts @beginning_state.id + '-' + @alphabet + '-' + @ending_state.id
29
+ end
30
+ end
31
+ end
@@ -1,134 +1,139 @@
1
- require 'rspec'
2
- require 'spec_helper'
3
- require_relative '../lib/automaton.rb'
4
-
5
- describe Nfa2Dfa::Automaton do
6
- before(:each) do
7
- @file_path = "#{File.dirname(__FILE__)}/testdata/valid_input.automat"
8
- @file_path2 = "#{File.dirname(__FILE__)}/testdata/valid_input2.automat"
9
- @file_path3 = "#{File.dirname(__FILE__)}/testdata/valid_input3.automat"
10
- end
11
- context "initializes as" do
12
- it "valid automaton" do
13
- mat = Automaton.init(@file_path)
14
- mat.should_not eq NIL
15
- mat.class.should eq Nfa2Dfa::Automaton
16
- end
17
- it "invalid automaton, when there is invalid input" do
18
- mat = Automaton.init("#{File.dirname(__FILE__)}/testdata/invalid_input.automat")
19
- mat.should eq NIL
20
- end
21
- end
22
- it "should be exportable in same format by method 'to_str'" do
23
- valid_str = "z f\na b\nz-a-f f-b-f\nz\nf"
24
- mat = Automaton.init(@file_path)
25
- mat.to_str.should eq valid_str
26
- end
27
-
28
- context "accepts method resolves" do
29
- subject { Automaton.init(@file_path) }
30
- it "valid words" do
31
- (subject.accepts? "a b").should eq true
32
- (subject.accepts? "a").should eq true
33
- (subject.accepts? "a b b b").should eq true
34
- (subject.accepts? "a b b").should eq true
35
- end
36
-
37
- it "invalid words" do
38
- (subject.accepts? "").should eq false
39
- (subject.accepts? "a a").should eq false
40
- (subject.accepts? "a a ").should eq false
41
- (subject.accepts? "a b a").should eq false
42
- end
43
- end
44
-
45
- it "should be able to check if automat is deterministic" do
46
- Automaton.init(@file_path).deterministic?.should eq true
47
- Automaton.init(@file_path2).deterministic?.should eq false
48
- end
49
-
50
- context "can create deterministic automaton" do
51
- it "returns Automaton class" do
52
- mat1 = Automaton.init(@file_path)
53
- mat2 = Automaton.init(@file_path2)
54
- mat3 = Automaton.init(@file_path3)
55
- mat1.determine.class.should eq Nfa2Dfa::Automaton
56
- mat2.determine.class.should eq Nfa2Dfa::Automaton
57
- mat3.determine.class.should eq Nfa2Dfa::Automaton
58
- end
59
- it "returns same instance of Automaton when already deterministic" do
60
- mat1 = Automaton.init(@file_path)
61
- mat1det = mat1.determine
62
- mat1.should eq mat1det
63
- end
64
- it "returns deterministic automaton" do
65
- mat2 = Automaton.init(@file_path2)
66
- mat2det = mat2.determine
67
- mat2det.deterministic?.should eq true
68
- end
69
-
70
- it "which can accept same words" do
71
- mat2 = Automaton.init(@file_path2)
72
- mat2det = mat2.determine
73
- word = ""
74
- (mat2.accepts? word).should eq mat2det.accepts? word
75
- (mat2.accepts? word).should eq true
76
- word = "a a"
77
- (mat2.accepts? word).should eq mat2det.accepts? word
78
- (mat2.accepts? word).should eq true
79
- word = "a b"
80
- (mat2.accepts? word).should eq mat2det.accepts? word
81
- (mat2.accepts? word).should eq true
82
- word = "a c"
83
- (mat2.accepts? word).should eq mat2det.accepts? word
84
- (mat2.accepts? word).should eq true
85
- word = "a c c"
86
- (mat2.accepts? word).should eq mat2det.accepts? word
87
- (mat2.accepts? word).should eq true
88
- word = "a c c a"
89
- (mat2.accepts? word).should eq mat2det.accepts? word
90
- (mat2.accepts? word).should eq true
91
- word = "a c c a c a"
92
- (mat2.accepts? word).should eq mat2det.accepts? word
93
- (mat2.accepts? word).should eq true
94
- word = "a c c a c a a b"
95
- (mat2.accepts? word).should eq mat2det.accepts? word
96
- (mat2.accepts? word).should eq true
97
- word = "c a b c a b c"
98
- (mat2.accepts? word).should eq mat2det.accepts? word
99
- (mat2.accepts? word).should eq true
100
- word = "a c c b c"
101
- (mat2.accepts? word).should eq mat2det.accepts? word
102
- (mat2.accepts? word).should eq true
103
- end
104
-
105
- it "which rejects same words" do
106
- mat2 = Automaton.init(@file_path3)
107
- mat2det = mat2.determine
108
- word = "0"
109
- (mat2.accepts? word).should eq mat2det.accepts? word
110
- (mat2.accepts? word).should eq false
111
- word = "1"
112
- (mat2.accepts? word).should eq mat2det.accepts? word
113
- (mat2.accepts? word).should eq false
114
- word = "0 1"
115
- (mat2.accepts? word).should eq mat2det.accepts? word
116
- (mat2.accepts? word).should eq false
117
- word = "1 0"
118
- (mat2.accepts? word).should eq mat2det.accepts? word
119
- (mat2.accepts? word).should eq false
120
- word = "1 1 1 1 0"
121
- (mat2.accepts? word).should eq mat2det.accepts? word
122
- (mat2.accepts? word).should eq false
123
- word = "0 0 0 0 1"
124
- (mat2.accepts? word).should eq mat2det.accepts? word
125
- (mat2.accepts? word).should eq false
126
- end
127
-
128
- it "should have method for exporting as GraphViz 'to_graph'" do
129
- mat = Automaton.init(@file_path2)
130
- expect(mat.methods.include?(:to_graph)).to be true
131
- end
132
- end
133
- end
134
-
1
+ require 'rspec'
2
+ require 'spec_helper'
3
+ require_relative '../lib/automaton.rb'
4
+
5
+ describe Nfa2Dfa::Automaton do
6
+ before(:each) do
7
+ @file_path = "#{File.dirname(__FILE__)}/testdata/valid_input.automat"
8
+ @file_path2 = "#{File.dirname(__FILE__)}/testdata/valid_input2.automat"
9
+ @file_path3 = "#{File.dirname(__FILE__)}/testdata/valid_input3.automat"
10
+ end
11
+
12
+ context 'initializes as' do
13
+ it 'valid automaton' do
14
+ mat = Automaton.init(@file_path)
15
+ mat.should_not eq NIL
16
+ mat.class.should eq Nfa2Dfa::Automaton
17
+ end
18
+
19
+ it 'invalid automaton, when there is invalid input' do
20
+ mat = Automaton.init("#{File.dirname(__FILE__)}" +
21
+ '/testdata/invalid_input.automat')
22
+ mat.should eq NIL
23
+ end
24
+ end
25
+
26
+ it 'should be exportable in same format by method \'to_str\'' do
27
+ valid_str = "z f\na b\nz-a-f f-b-f\nz\nf"
28
+ mat = Automaton.init(@file_path)
29
+ mat.to_str.should eq valid_str
30
+ end
31
+
32
+ context 'accepts method resolves' do
33
+ subject { Automaton.init(@file_path) }
34
+ it 'valid words' do
35
+ (subject.accepts? 'a b').should eq true
36
+ (subject.accepts? 'a').should eq true
37
+ (subject.accepts? 'a b b b').should eq true
38
+ (subject.accepts? 'a b b').should eq true
39
+ end
40
+
41
+ it 'invalid words' do
42
+ (subject.accepts? '').should eq false
43
+ (subject.accepts? 'a a').should eq false
44
+ (subject.accepts? 'a a ').should eq false
45
+ (subject.accepts? 'a b a').should eq false
46
+ end
47
+ end
48
+
49
+ it 'should be able to check if automat is deterministic' do
50
+ Automaton.init(@file_path).deterministic?.should eq true
51
+ Automaton.init(@file_path2).deterministic?.should eq false
52
+ end
53
+
54
+ context 'can create deterministic automaton' do
55
+ it 'returns Automaton class' do
56
+ mat1 = Automaton.init(@file_path)
57
+ mat2 = Automaton.init(@file_path2)
58
+ mat3 = Automaton.init(@file_path3)
59
+ mat1.determine.class.should eq Nfa2Dfa::Automaton
60
+ mat2.determine.class.should eq Nfa2Dfa::Automaton
61
+ mat3.determine.class.should eq Nfa2Dfa::Automaton
62
+ end
63
+
64
+ it 'returns same instance of Automaton when already deterministic' do
65
+ mat1 = Automaton.init(@file_path)
66
+ mat1det = mat1.determine
67
+ mat1.should eq mat1det
68
+ end
69
+
70
+ it 'returns deterministic automaton' do
71
+ mat2 = Automaton.init(@file_path2)
72
+ mat2det = mat2.determine
73
+ mat2det.deterministic?.should eq true
74
+ end
75
+
76
+ it 'which can accept same words' do
77
+ mat2 = Automaton.init(@file_path2)
78
+ mat2det = mat2.determine
79
+ word = ''
80
+ (mat2.accepts? word).should eq mat2det.accepts? word
81
+ (mat2.accepts? word).should eq true
82
+ word = 'a a'
83
+ (mat2.accepts? word).should eq mat2det.accepts? word
84
+ (mat2.accepts? word).should eq true
85
+ word = 'a b'
86
+ (mat2.accepts? word).should eq mat2det.accepts? word
87
+ (mat2.accepts? word).should eq true
88
+ word = 'a c'
89
+ (mat2.accepts? word).should eq mat2det.accepts? word
90
+ (mat2.accepts? word).should eq true
91
+ word = 'a c c'
92
+ (mat2.accepts? word).should eq mat2det.accepts? word
93
+ (mat2.accepts? word).should eq true
94
+ word = 'a c c a'
95
+ (mat2.accepts? word).should eq mat2det.accepts? word
96
+ (mat2.accepts? word).should eq true
97
+ word = 'a c c a c a'
98
+ (mat2.accepts? word).should eq mat2det.accepts? word
99
+ (mat2.accepts? word).should eq true
100
+ word = 'a c c a c a a b'
101
+ (mat2.accepts? word).should eq mat2det.accepts? word
102
+ (mat2.accepts? word).should eq true
103
+ word = 'c a b c a b c'
104
+ (mat2.accepts? word).should eq mat2det.accepts? word
105
+ (mat2.accepts? word).should eq true
106
+ word = 'a c c b c'
107
+ (mat2.accepts? word).should eq mat2det.accepts? word
108
+ (mat2.accepts? word).should eq true
109
+ end
110
+
111
+ it 'which rejects same words' do
112
+ mat2 = Automaton.init(@file_path3)
113
+ mat2det = mat2.determine
114
+ word = '0'
115
+ (mat2.accepts? word).should eq mat2det.accepts? word
116
+ (mat2.accepts? word).should eq false
117
+ word = '1'
118
+ (mat2.accepts? word).should eq mat2det.accepts? word
119
+ (mat2.accepts? word).should eq false
120
+ word = '0 1'
121
+ (mat2.accepts? word).should eq mat2det.accepts? word
122
+ (mat2.accepts? word).should eq false
123
+ word = '1 0'
124
+ (mat2.accepts? word).should eq mat2det.accepts? word
125
+ (mat2.accepts? word).should eq false
126
+ word = '1 1 1 1 0'
127
+ (mat2.accepts? word).should eq mat2det.accepts? word
128
+ (mat2.accepts? word).should eq false
129
+ word = '0 0 0 0 1'
130
+ (mat2.accepts? word).should eq mat2det.accepts? word
131
+ (mat2.accepts? word).should eq false
132
+ end
133
+
134
+ it 'should have method for exporting as GraphViz \'to_graph\'' do
135
+ mat = Automaton.init(@file_path2)
136
+ expect(mat.methods.include?(:to_graph)).to be true
137
+ end
138
+ end
139
+ end