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 CHANGED
@@ -22,7 +22,75 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- We'll be adding some wiki pages with usage details soon.
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
 
@@ -1,20 +1,29 @@
1
+ ##
2
+ # Sample DFA file.
3
+ #
4
+ # Accepts all binary strings starting with 00.
5
+ #
1
6
  states:
2
- - q1
3
- - q2
4
- - q3
7
+ - A
8
+ - B
9
+ - C
10
+ - D
5
11
  alphabet:
6
12
  - '0'
7
13
  - '1'
8
- start: q1
14
+ start: A
9
15
  accept:
10
- - q3
16
+ - C
11
17
  transitions:
12
- q1:
13
- '0': q2
14
- '1': q2
15
- q2:
16
- '0': q1
17
- '1': q3
18
- q3:
19
- '0': q3
20
- '1': q3
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
@@ -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
- heads.each_with_index do |head, i|
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
 
@@ -1,3 +1,3 @@
1
1
  module Automata
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.5"
3
3
  end
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 '01'" do
15
- @dfa.accepts?('01').should == true
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 '10'" do
27
- @dfa.accepts?('10').should == false
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 = ['q1','q2','q3']
44
- alphabet = ['0','1']
45
- start = 'q1'
46
- accept = ['q3']
55
+ states = %w( A B C D )
56
+ alphabet = %w( 0 1 )
57
+ start = 'A'
58
+ accept = %w( C )
47
59
  transitions = {
48
- 'q1' => {
49
- '0' => 'q2',
50
- '1' => 'q2'
60
+ 'A' => {
61
+ '0' => 'B',
62
+ '1' => 'D'
63
+ },
64
+ 'B' => {
65
+ '0' => 'C',
66
+ '1' => 'D'
51
67
  },
52
- 'q2' => {
53
- '0' => 'q1',
54
- '1' => 'q3'
68
+ 'C' => {
69
+ '0' => 'C',
70
+ '1' => 'C'
55
71
  },
56
- 'q3' => {
57
- '0' => 'q3',
58
- '1' => 'q3'
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 '01'" do
76
- @dfa.accepts?('01').should == true
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 '10'" do
88
- @dfa.accepts?('10').should == false
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.3
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-24 00:00:00.000000000 Z
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: &70308841255600 !ruby/object:Gem::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: *70308841255600
24
+ version_requirements: *70101266746740
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &70308841254660 !ruby/object:Gem::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: *70308841254660
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: -1969094852898081340
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: -1969094852898081340
84
+ hash: -2023160774653295454
84
85
  requirements: []
85
86
  rubyforge_project:
86
87
  rubygems_version: 1.8.17