automata 0.0.2 → 0.0.3
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 +5 -1
- data/examples/nfa_sample.yml +28 -0
- data/lib/automata/dfa.rb +1 -1
- data/lib/automata/nfa.rb +94 -0
- data/lib/automata/version.rb +1 -1
- data/lib/automata.rb +1 -0
- data/spec/nfa_spec.rb +111 -0
- metadata +12 -8
data/README.md
CHANGED
@@ -2,8 +2,12 @@
|
|
2
2
|
|
3
3
|
A sweet Ruby gem for creating and simulating deterministic/nondeterministic finite automata, push-down automata, and Turing machines.
|
4
4
|
|
5
|
+
__Note:__ This gem is still under development. Not all automata have been fully implemented yet.
|
6
|
+
|
5
7
|
## Installation
|
6
8
|
|
9
|
+
Requires __Ruby 1.9.3__.
|
10
|
+
|
7
11
|
Add this line to your application's Gemfile:
|
8
12
|
|
9
13
|
gem 'automata'
|
@@ -18,7 +22,7 @@ Or install it yourself as:
|
|
18
22
|
|
19
23
|
## Usage
|
20
24
|
|
21
|
-
|
25
|
+
We'll be adding some wiki pages with usage details soon.
|
22
26
|
|
23
27
|
## Contributing
|
24
28
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
##
|
2
|
+
# Sample NFA build file
|
3
|
+
# Accepts: a* + (ab)*
|
4
|
+
#
|
5
|
+
states:
|
6
|
+
- q1
|
7
|
+
- q2
|
8
|
+
- q3
|
9
|
+
- q4
|
10
|
+
alphabet:
|
11
|
+
- a
|
12
|
+
- b
|
13
|
+
start: q1
|
14
|
+
accept:
|
15
|
+
- q1
|
16
|
+
- q2
|
17
|
+
- q4
|
18
|
+
transitions:
|
19
|
+
q1:
|
20
|
+
a:
|
21
|
+
- q2
|
22
|
+
- q3
|
23
|
+
q2:
|
24
|
+
a: q2
|
25
|
+
q3:
|
26
|
+
b: q4
|
27
|
+
q4:
|
28
|
+
a: q3
|
data/lib/automata/dfa.rb
CHANGED
@@ -28,7 +28,7 @@ module Automata
|
|
28
28
|
# Determines whether the DFA accepts the given string.
|
29
29
|
#
|
30
30
|
# * *Args*:
|
31
|
-
# - +string
|
31
|
+
# - +string+ -> The string to use as input for the DFA.
|
32
32
|
#
|
33
33
|
# * *Returns*:
|
34
34
|
# Whether or not the DFA accepts the string (boolean).
|
data/lib/automata/nfa.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
module Automata
|
2
|
+
|
3
|
+
##
|
4
|
+
# Deterministic Finite Automata.
|
5
|
+
#
|
6
|
+
# NFA nodes do not need to have a transition for each
|
7
|
+
# symbol in the alphabet. Empty transitions, denoted by
|
8
|
+
# the '&' charactar, force a transition to another node.
|
9
|
+
#
|
10
|
+
#--
|
11
|
+
# TODO: Check that each state is connected.
|
12
|
+
#
|
13
|
+
class NFA < StateDiagram
|
14
|
+
|
15
|
+
#--
|
16
|
+
# TODO: Check if valid NFA.
|
17
|
+
#
|
18
|
+
|
19
|
+
##
|
20
|
+
# Determines whether the NFA accepts the given string.
|
21
|
+
#
|
22
|
+
# * *Args*:
|
23
|
+
# - +string+ -> The string to use as input for the DFA.
|
24
|
+
# * *Returns*:
|
25
|
+
# Whether or not the DFA accepts the string (boolean).
|
26
|
+
#
|
27
|
+
def accepts?(string)
|
28
|
+
heads = [@start]
|
29
|
+
string.each_char do |symbol|
|
30
|
+
newHeads = []
|
31
|
+
heads.each_with_index do |head, i|
|
32
|
+
#--
|
33
|
+
# Check if head can transition read symbol
|
34
|
+
# Head dies if no transition for symbol
|
35
|
+
if has_transition?(head, symbol)
|
36
|
+
transition(head, symbol).each { |t| newHeads << t }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
heads = newHeads
|
40
|
+
break if heads.empty?
|
41
|
+
end
|
42
|
+
|
43
|
+
heads.each { |head| return true if accept_state? head }
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Determine the states to transition to from a given
|
49
|
+
# state and input symbol.
|
50
|
+
#
|
51
|
+
# * *Args*:
|
52
|
+
# - +state+ -> State transitioning from.
|
53
|
+
# - +input+ -> Input symbol.
|
54
|
+
# * *Returns*:
|
55
|
+
# The array of transition states. Nil if none.
|
56
|
+
#
|
57
|
+
def transition(state, input)
|
58
|
+
if has_transition?(state, input)
|
59
|
+
dests = @transitions[state][input]
|
60
|
+
dests = [dests] unless dests.kind_of? Array
|
61
|
+
dests
|
62
|
+
else
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Determine whether or not a transition exists
|
69
|
+
# for a state, given an input symbol.
|
70
|
+
#
|
71
|
+
# * *Args*:
|
72
|
+
# - +state+ -> State transitioning from.
|
73
|
+
# - +input+ -> Input symbol.
|
74
|
+
# * *Returns*:
|
75
|
+
# Whether a transition exists. (boolean)
|
76
|
+
#
|
77
|
+
def has_transition?(state, input)
|
78
|
+
@transitions[state].has_key? input
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# Determine if a given state is an accept state.
|
83
|
+
#
|
84
|
+
# * *Args*:
|
85
|
+
# - +state+ -> The state.
|
86
|
+
# * *Returns*:
|
87
|
+
# Whether or not the state is an accept state. (boolean)
|
88
|
+
#
|
89
|
+
def accept_state?(state)
|
90
|
+
@accept.include? state
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
data/lib/automata/version.rb
CHANGED
data/lib/automata.rb
CHANGED
data/spec/nfa_spec.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Automata::NFA do
|
4
|
+
|
5
|
+
context "Initializing from a valid file" do
|
6
|
+
before do
|
7
|
+
@nfa = Automata::NFA.new(file: 'examples/nfa_sample.yml')
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should accept 'a'" do
|
11
|
+
@nfa.accepts?('a').should == true
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should accept 'aa'" do
|
15
|
+
@nfa.accepts?('aa').should == true
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should accept the empty string" do
|
19
|
+
@nfa.accepts?('').should == true
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should not accept 'b'" do
|
23
|
+
@nfa.accepts?('b').should == false
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should accept 'ab'" do
|
27
|
+
@nfa.accepts?('ab').should == true
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should accept 'abab'" do
|
31
|
+
@nfa.accepts?('abab').should == true
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should accept 'aab'" do
|
35
|
+
@nfa.accepts?('aab').should == false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "Initializing an empty NFA" do
|
40
|
+
before do
|
41
|
+
@nfa = Automata::NFA.new
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should be created successfully" do
|
45
|
+
@nfa.should be_an_instance_of Automata::NFA
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "Initializing a NFA by params" do
|
50
|
+
before do
|
51
|
+
states = ['q1','q2','q3','q4']
|
52
|
+
alphabet = ['a','b']
|
53
|
+
start = 'q1'
|
54
|
+
accept = ['q1','q2','q4']
|
55
|
+
transitions = {
|
56
|
+
'q1' => {
|
57
|
+
'a' => ['q2','q3']
|
58
|
+
},
|
59
|
+
'q2' => {
|
60
|
+
'a' => 'q2'
|
61
|
+
},
|
62
|
+
'q3' => {
|
63
|
+
'b' => 'q4'
|
64
|
+
},
|
65
|
+
'q4' => {
|
66
|
+
'a' => 'q3'
|
67
|
+
}
|
68
|
+
}
|
69
|
+
params = {
|
70
|
+
states: states,
|
71
|
+
alphabet: alphabet,
|
72
|
+
start: start,
|
73
|
+
accept: accept,
|
74
|
+
transitions: transitions
|
75
|
+
}
|
76
|
+
@nfa = Automata::NFA.new(params)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should be created successfully" do
|
80
|
+
@nfa.should be_an_instance_of Automata::NFA
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should accept 'a'" do
|
84
|
+
@nfa.accepts?('a').should == true
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should accept 'aa'" do
|
88
|
+
@nfa.accepts?('aa').should == true
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should accept the empty string" do
|
92
|
+
@nfa.accepts?('').should == true
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should not accept 'b'" do
|
96
|
+
@nfa.accepts?('b').should == false
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should accept 'ab'" do
|
100
|
+
@nfa.accepts?('ab').should == true
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should accept 'abab'" do
|
104
|
+
@nfa.accepts?('abab').should == true
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should accept 'aab'" do
|
108
|
+
@nfa.accepts?('aab').should == false
|
109
|
+
end
|
110
|
+
end
|
111
|
+
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.3
|
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-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement: &
|
16
|
+
requirement: &70308841255600 !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: *70308841255600
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &70308841254660 !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: *70308841254660
|
36
36
|
description: Create and simulate automaton.
|
37
37
|
email:
|
38
38
|
- jico@baligod.com
|
@@ -48,11 +48,14 @@ files:
|
|
48
48
|
- Rakefile
|
49
49
|
- automata.gemspec
|
50
50
|
- examples/dfa_sample.yml
|
51
|
+
- examples/nfa_sample.yml
|
51
52
|
- lib/automata.rb
|
52
53
|
- lib/automata/dfa.rb
|
54
|
+
- lib/automata/nfa.rb
|
53
55
|
- lib/automata/state_diagram.rb
|
54
56
|
- lib/automata/version.rb
|
55
57
|
- spec/dfa_spec.rb
|
58
|
+
- spec/nfa_spec.rb
|
56
59
|
- spec/spec_helper.rb
|
57
60
|
homepage: http://github.com/jico/automata
|
58
61
|
licenses: []
|
@@ -68,7 +71,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
68
71
|
version: '0'
|
69
72
|
segments:
|
70
73
|
- 0
|
71
|
-
hash: -
|
74
|
+
hash: -1969094852898081340
|
72
75
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
76
|
none: false
|
74
77
|
requirements:
|
@@ -77,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
77
80
|
version: '0'
|
78
81
|
segments:
|
79
82
|
- 0
|
80
|
-
hash: -
|
83
|
+
hash: -1969094852898081340
|
81
84
|
requirements: []
|
82
85
|
rubyforge_project:
|
83
86
|
rubygems_version: 1.8.17
|
@@ -87,4 +90,5 @@ summary: This gem provides a number of classes to create and simulate Determinis
|
|
87
90
|
Finite Automata, Push-down Automata, and Turing Machines.
|
88
91
|
test_files:
|
89
92
|
- spec/dfa_spec.rb
|
93
|
+
- spec/nfa_spec.rb
|
90
94
|
- spec/spec_helper.rb
|