automata 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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
- TODO: Write usage instructions here
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* -> The string to use as input for the DFA.
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).
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Automata
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/automata.rb CHANGED
@@ -2,6 +2,7 @@ require "automata/version"
2
2
  require 'yaml'
3
3
  require "automata/state_diagram"
4
4
  require "automata/dfa"
5
+ require "automata/nfa"
5
6
 
6
7
  module Automata
7
8
  # Your code goes here...
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.2
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-23 00:00:00.000000000 Z
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: &70316676891620 !ruby/object:Gem::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: *70316676891620
24
+ version_requirements: *70308841255600
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &70316676891100 !ruby/object:Gem::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: *70316676891100
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: -1178858470182539386
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: -1178858470182539386
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