automata 0.0.3 → 0.0.5
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.md +69 -1
- data/examples/dfa_sample.yml +23 -14
- data/examples/nfa_2.yml +31 -0
- data/lib/automata/nfa.rb +13 -6
- data/lib/automata/version.rb +1 -1
- data/spec/dfa_spec.rb +49 -21
- metadata +9 -8
data/README.md
CHANGED
@@ -22,7 +22,75 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
-
|
25
|
+
### Creating a new machine
|
26
|
+
|
27
|
+
Defining a new machine can be done in two ways:
|
28
|
+
* From a structured YAML file.
|
29
|
+
* Through class setter methods.
|
30
|
+
|
31
|
+
#### Building with YAML
|
32
|
+
|
33
|
+
We can easily define a machine's _n_-tuples in a YAML file. For example, let's create a DFA defined by the 5-tuple (_states_, _alphabet_, _start_, _accept_, _transitions_). We create the file `examples/dfa_sample.yml` with the following content:
|
34
|
+
|
35
|
+
states:
|
36
|
+
- A
|
37
|
+
- B
|
38
|
+
- C
|
39
|
+
- D
|
40
|
+
alphabet:
|
41
|
+
- '0'
|
42
|
+
- '1'
|
43
|
+
start: A
|
44
|
+
accept:
|
45
|
+
- C
|
46
|
+
transitions:
|
47
|
+
A:
|
48
|
+
'0': B
|
49
|
+
'1': D
|
50
|
+
B:
|
51
|
+
'0': C
|
52
|
+
'1': D
|
53
|
+
C:
|
54
|
+
'0': C
|
55
|
+
'1': C
|
56
|
+
D:
|
57
|
+
'0': D
|
58
|
+
'1': D
|
59
|
+
|
60
|
+
__Note:__ Integer hash keys are currently unsupported, hence they must be wrapped in quotes.
|
61
|
+
|
62
|
+
With our machine defined, we can create a new DFA object from the file.
|
63
|
+
|
64
|
+
dfa = Automata::DFA.new(file: 'examples/dfa_sample.yml')
|
65
|
+
|
66
|
+
Presto! We have a fully functioning DFA machine.
|
67
|
+
|
68
|
+
#### Building with setters
|
69
|
+
|
70
|
+
You also have the option of setting each variable in the machine's _n_-tuple definition. For example, let's create a new empty DFA and define its states.
|
71
|
+
|
72
|
+
dfa = Automata::DFA.new
|
73
|
+
dfa.states = ['A', 'B', 'C', 'D']
|
74
|
+
|
75
|
+
We can define each property of the DFA in a similar manner.
|
76
|
+
|
77
|
+
### Playing with our machine
|
78
|
+
|
79
|
+
Now that we've built a machine, we can pass it input and let it work its magic. Consider our DFA built using our `examples/dfa_sample.yml` file, which accepts all strings starting with _00_. Let's experiment with some input:
|
80
|
+
|
81
|
+
# We can make sure it's a valid DFA
|
82
|
+
>> dfa.is_valid?
|
83
|
+
=> true
|
84
|
+
>> dfa.accepts? '001'
|
85
|
+
=> true
|
86
|
+
>> dfa.accepts? '0101'
|
87
|
+
=> false
|
88
|
+
|
89
|
+
Awesomesauce.
|
90
|
+
|
91
|
+
## Special Characters
|
92
|
+
|
93
|
+
* _&_ - Represents an ε-transition (epsilon/empty transition)
|
26
94
|
|
27
95
|
## Contributing
|
28
96
|
|
data/examples/dfa_sample.yml
CHANGED
@@ -1,20 +1,29 @@
|
|
1
|
+
##
|
2
|
+
# Sample DFA file.
|
3
|
+
#
|
4
|
+
# Accepts all binary strings starting with 00.
|
5
|
+
#
|
1
6
|
states:
|
2
|
-
-
|
3
|
-
-
|
4
|
-
-
|
7
|
+
- A
|
8
|
+
- B
|
9
|
+
- C
|
10
|
+
- D
|
5
11
|
alphabet:
|
6
12
|
- '0'
|
7
13
|
- '1'
|
8
|
-
start:
|
14
|
+
start: A
|
9
15
|
accept:
|
10
|
-
-
|
16
|
+
- C
|
11
17
|
transitions:
|
12
|
-
|
13
|
-
'0':
|
14
|
-
'1':
|
15
|
-
|
16
|
-
'0':
|
17
|
-
'1':
|
18
|
-
|
19
|
-
'0':
|
20
|
-
'1':
|
18
|
+
A:
|
19
|
+
'0': B
|
20
|
+
'1': D
|
21
|
+
B:
|
22
|
+
'0': C
|
23
|
+
'1': D
|
24
|
+
C:
|
25
|
+
'0': C
|
26
|
+
'1': C
|
27
|
+
D:
|
28
|
+
'0': D
|
29
|
+
'1': D
|
data/examples/nfa_2.yml
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
##
|
2
|
+
# Sample NFA build file
|
3
|
+
#
|
4
|
+
# Accepts all binary strings where
|
5
|
+
# the last symbol is 0 or
|
6
|
+
# which contain only 1's
|
7
|
+
#
|
8
|
+
states:
|
9
|
+
- A
|
10
|
+
- B
|
11
|
+
- C
|
12
|
+
- D
|
13
|
+
alphabet:
|
14
|
+
- '0'
|
15
|
+
- '1'
|
16
|
+
start: B
|
17
|
+
accept:
|
18
|
+
- A
|
19
|
+
- D
|
20
|
+
transitions:
|
21
|
+
A:
|
22
|
+
'1': A
|
23
|
+
B:
|
24
|
+
'&':
|
25
|
+
- A
|
26
|
+
- C
|
27
|
+
C:
|
28
|
+
'0':
|
29
|
+
- C
|
30
|
+
- D
|
31
|
+
'1': C
|
data/lib/automata/nfa.rb
CHANGED
@@ -12,10 +12,6 @@ module Automata
|
|
12
12
|
#
|
13
13
|
class NFA < StateDiagram
|
14
14
|
|
15
|
-
#--
|
16
|
-
# TODO: Check if valid NFA.
|
17
|
-
#
|
18
|
-
|
19
15
|
##
|
20
16
|
# Determines whether the NFA accepts the given string.
|
21
17
|
#
|
@@ -27,8 +23,18 @@ module Automata
|
|
27
23
|
def accepts?(string)
|
28
24
|
heads = [@start]
|
29
25
|
string.each_char do |symbol|
|
30
|
-
newHeads = []
|
31
|
-
|
26
|
+
newHeads, eTrans = [], []
|
27
|
+
|
28
|
+
#--
|
29
|
+
# Move any e-transitions
|
30
|
+
heads.each do |head|
|
31
|
+
if has_transition?(head, '&')
|
32
|
+
transition(head, '&').each { |t| eTrans << t }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
eTrans.each { |h| heads << h }
|
36
|
+
|
37
|
+
heads.each do |head|
|
32
38
|
#--
|
33
39
|
# Check if head can transition read symbol
|
34
40
|
# Head dies if no transition for symbol
|
@@ -75,6 +81,7 @@ module Automata
|
|
75
81
|
# Whether a transition exists. (boolean)
|
76
82
|
#
|
77
83
|
def has_transition?(state, input)
|
84
|
+
return false unless @transitions.include? state
|
78
85
|
@transitions[state].has_key? input
|
79
86
|
end
|
80
87
|
|
data/lib/automata/version.rb
CHANGED
data/spec/dfa_spec.rb
CHANGED
@@ -11,8 +11,8 @@ describe Automata::DFA do
|
|
11
11
|
@dfa.should be_valid
|
12
12
|
end
|
13
13
|
|
14
|
-
it "should accept '
|
15
|
-
@dfa.accepts?('
|
14
|
+
it "should accept '00'" do
|
15
|
+
@dfa.accepts?('00').should == true
|
16
16
|
end
|
17
17
|
|
18
18
|
it "should accept '001101'" do
|
@@ -23,8 +23,20 @@ describe Automata::DFA do
|
|
23
23
|
@dfa.accepts?('').should == false
|
24
24
|
end
|
25
25
|
|
26
|
-
it "should not accept '
|
27
|
-
@dfa.accepts?('
|
26
|
+
it "should not accept '0'" do
|
27
|
+
@dfa.accepts?('0').should == false
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should not accept '1'" do
|
31
|
+
@dfa.accepts?('1').should == false
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should not accept '01'" do
|
35
|
+
@dfa.accepts?('01').should == false
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should not accept '100'" do
|
39
|
+
@dfa.accepts?('100').should == false
|
28
40
|
end
|
29
41
|
end
|
30
42
|
|
@@ -40,22 +52,26 @@ describe Automata::DFA do
|
|
40
52
|
|
41
53
|
context "Initializing a DFA by params" do
|
42
54
|
before do
|
43
|
-
states =
|
44
|
-
alphabet =
|
45
|
-
start = '
|
46
|
-
accept =
|
55
|
+
states = %w( A B C D )
|
56
|
+
alphabet = %w( 0 1 )
|
57
|
+
start = 'A'
|
58
|
+
accept = %w( C )
|
47
59
|
transitions = {
|
48
|
-
'
|
49
|
-
'0' => '
|
50
|
-
'1' => '
|
60
|
+
'A' => {
|
61
|
+
'0' => 'B',
|
62
|
+
'1' => 'D'
|
63
|
+
},
|
64
|
+
'B' => {
|
65
|
+
'0' => 'C',
|
66
|
+
'1' => 'D'
|
51
67
|
},
|
52
|
-
'
|
53
|
-
'0' => '
|
54
|
-
'1' => '
|
68
|
+
'C' => {
|
69
|
+
'0' => 'C',
|
70
|
+
'1' => 'C'
|
55
71
|
},
|
56
|
-
'
|
57
|
-
'0' => '
|
58
|
-
'1' => '
|
72
|
+
'D' => {
|
73
|
+
'0' => 'D',
|
74
|
+
'1' => 'D'
|
59
75
|
}
|
60
76
|
}
|
61
77
|
params = {
|
@@ -72,8 +88,8 @@ describe Automata::DFA do
|
|
72
88
|
@dfa.should be_valid
|
73
89
|
end
|
74
90
|
|
75
|
-
it "should accept '
|
76
|
-
@dfa.accepts?('
|
91
|
+
it "should accept '00'" do
|
92
|
+
@dfa.accepts?('00').should == true
|
77
93
|
end
|
78
94
|
|
79
95
|
it "should accept '001101'" do
|
@@ -84,8 +100,20 @@ describe Automata::DFA do
|
|
84
100
|
@dfa.accepts?('').should == false
|
85
101
|
end
|
86
102
|
|
87
|
-
it "should not accept '
|
88
|
-
@dfa.accepts?('
|
103
|
+
it "should not accept '0'" do
|
104
|
+
@dfa.accepts?('0').should == false
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should not accept '1'" do
|
108
|
+
@dfa.accepts?('1').should == false
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should not accept '01'" do
|
112
|
+
@dfa.accepts?('01').should == false
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should not accept '100'" do
|
116
|
+
@dfa.accepts?('100').should == false
|
89
117
|
end
|
90
118
|
end
|
91
119
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: automata
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-04-
|
12
|
+
date: 2012-04-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement: &
|
16
|
+
requirement: &70101266746740 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70101266746740
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &70101266745440 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: 2.9.0
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70101266745440
|
36
36
|
description: Create and simulate automaton.
|
37
37
|
email:
|
38
38
|
- jico@baligod.com
|
@@ -48,6 +48,7 @@ files:
|
|
48
48
|
- Rakefile
|
49
49
|
- automata.gemspec
|
50
50
|
- examples/dfa_sample.yml
|
51
|
+
- examples/nfa_2.yml
|
51
52
|
- examples/nfa_sample.yml
|
52
53
|
- lib/automata.rb
|
53
54
|
- lib/automata/dfa.rb
|
@@ -71,7 +72,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
71
72
|
version: '0'
|
72
73
|
segments:
|
73
74
|
- 0
|
74
|
-
hash: -
|
75
|
+
hash: -2023160774653295454
|
75
76
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
77
|
none: false
|
77
78
|
requirements:
|
@@ -80,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
81
|
version: '0'
|
81
82
|
segments:
|
82
83
|
- 0
|
83
|
-
hash: -
|
84
|
+
hash: -2023160774653295454
|
84
85
|
requirements: []
|
85
86
|
rubyforge_project:
|
86
87
|
rubygems_version: 1.8.17
|