automata 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/automata/dfa.rb +16 -26
- data/lib/automata/nfa.rb +31 -59
- data/lib/automata/state_diagram.rb +17 -8
- data/lib/automata/version.rb +1 -1
- metadata +7 -7
data/lib/automata/dfa.rb
CHANGED
@@ -1,49 +1,39 @@
|
|
1
1
|
module Automata
|
2
|
-
|
3
|
-
##
|
4
2
|
# Deterministic Finite Automata.
|
5
|
-
#
|
6
|
-
# Each state of a DFA must have exactly one transition for each transition
|
7
|
-
# defined at creation.
|
8
|
-
#
|
9
|
-
#--
|
10
|
-
# TODO: Check that each state is connected.
|
11
|
-
#
|
12
3
|
class DFA < StateDiagram
|
13
|
-
|
14
|
-
|
15
|
-
#
|
16
|
-
#
|
17
|
-
# * *Returns*:
|
18
|
-
# Whether or not the DFA is valid (boolean).
|
4
|
+
# Verifies that the initialized DFA is valid.
|
5
|
+
# Checks that each state has a transition for each
|
6
|
+
# symbol in the alphabet.
|
19
7
|
#
|
8
|
+
# @return [Boolean] whether or not the DFA is valid.
|
20
9
|
def valid?
|
10
|
+
# @todo Check that each state is connected.
|
11
|
+
# Iterate through each states to verify the graph
|
12
|
+
# is not disjoint.
|
21
13
|
@transitions.each do |key, val|
|
22
14
|
@alphabet.each { |a| return false unless @transitions[key].has_key? a }
|
23
15
|
end
|
24
16
|
true
|
25
17
|
end
|
26
18
|
|
27
|
-
|
28
|
-
# Determines whether the DFA accepts the given string.
|
29
|
-
#
|
30
|
-
# * *Args*:
|
31
|
-
# - +string+ -> The string to use as input for the DFA.
|
19
|
+
# Determines whether the DFA accepts a given string.
|
32
20
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
|
36
|
-
def accepts?(string)
|
21
|
+
# @param [String] input the string to use as input for the DFA.
|
22
|
+
# @return [Boolean] whether or not the DFA accepts the string.
|
23
|
+
def accepts?(input)
|
37
24
|
head = @start
|
38
|
-
|
25
|
+
input.each_char do |symbol|
|
39
26
|
head = @transitions[head][symbol]
|
40
27
|
end
|
41
28
|
is_accept_state? head
|
42
29
|
end
|
43
30
|
|
31
|
+
# Determines if a given state is an accept state.
|
32
|
+
#
|
33
|
+
# @param [String] state the state label to check.
|
34
|
+
# @return [Boolean] whether or not the state is an accept state.
|
44
35
|
def is_accept_state?(state)
|
45
36
|
@accept.include? state
|
46
37
|
end
|
47
38
|
end
|
48
|
-
|
49
39
|
end
|
data/lib/automata/nfa.rb
CHANGED
@@ -1,39 +1,27 @@
|
|
1
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
|
-
#
|
2
|
+
# Nondeterministic Finite Automata.
|
13
3
|
class NFA < StateDiagram
|
4
|
+
# @todo Check that each state is connected.
|
5
|
+
# Iterate through each states to verify the graph
|
6
|
+
# is not disjoint.
|
14
7
|
|
15
|
-
|
16
|
-
# Determines whether the NFA accepts the given string.
|
8
|
+
# Determines whether the NFA accepts a given string.
|
17
9
|
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
|
21
|
-
# Whether or not the DFA accepts the string (boolean).
|
22
|
-
#
|
23
|
-
def accepts?(string)
|
10
|
+
# @param [String] input the string to use as input for the NFA.
|
11
|
+
# @return [Boolean] Whether or not the NFA accepts the input string.
|
12
|
+
def accepts?(input)
|
24
13
|
heads = [@start]
|
25
14
|
|
26
|
-
#--
|
27
15
|
# Move any initial e-transitions
|
28
16
|
if has_transition?(@start, '&')
|
29
17
|
transition(@start, '&').each { |h| heads << h }
|
30
18
|
end
|
31
19
|
|
32
|
-
|
20
|
+
# Iterate through each symbol of input string
|
21
|
+
input.each_char do |symbol|
|
33
22
|
newHeads, eTrans = [], []
|
34
23
|
|
35
24
|
heads.each do |head|
|
36
|
-
#--
|
37
25
|
# Check if head can transition read symbol
|
38
26
|
# Head dies if no transition for symbol
|
39
27
|
if has_transition?(head, symbol)
|
@@ -41,7 +29,6 @@ module Automata
|
|
41
29
|
end
|
42
30
|
end
|
43
31
|
|
44
|
-
#--
|
45
32
|
# Move any e-transitions
|
46
33
|
newHeads.each do |head|
|
47
34
|
if has_transition?(head, '&')
|
@@ -58,52 +45,37 @@ module Automata
|
|
58
45
|
false
|
59
46
|
end
|
60
47
|
|
61
|
-
|
62
|
-
#
|
63
|
-
# state and input symbol.
|
64
|
-
#
|
65
|
-
# * *Args*:
|
66
|
-
# - +state+ -> State transitioning from.
|
67
|
-
# - +input+ -> Input symbol.
|
68
|
-
# * *Returns*:
|
69
|
-
# The array of transition states. Nil if none.
|
48
|
+
# Determines the transition states, if any, from a given
|
49
|
+
# beginning state and input symbol pair.
|
70
50
|
#
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
51
|
+
# @note NFA ε-transitions
|
52
|
+
# ε-transitions are supported through the use of the
|
53
|
+
# reserved input alphabet character '&'.
|
54
|
+
# @param [String] state state label for beginning state.
|
55
|
+
# @param [String] symbol input symbol.
|
56
|
+
# @return [Array] Array of destination transition states.
|
57
|
+
def transition(state, symbol)
|
58
|
+
dests = @transitions[state][symbol]
|
59
|
+
dests = [dests] unless dests.kind_of? Array
|
60
|
+
dests
|
79
61
|
end
|
80
62
|
|
81
|
-
|
82
|
-
#
|
83
|
-
# for a state, given an input symbol.
|
63
|
+
# Determines whether or not any transition states exist
|
64
|
+
# given a beginning state and input symbol pair.
|
84
65
|
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
|
88
|
-
# * *Returns*:
|
89
|
-
# Whether a transition exists. (boolean)
|
90
|
-
#
|
91
|
-
def has_transition?(state, input)
|
66
|
+
# @param (see #transition)
|
67
|
+
# @return [Boolean] Whether or not a transition exists.
|
68
|
+
def has_transition?(state, symbol)
|
92
69
|
return false unless @transitions.include? state
|
93
|
-
@transitions[state].has_key?
|
70
|
+
@transitions[state].has_key? symbol
|
94
71
|
end
|
95
72
|
|
96
|
-
|
97
|
-
# Determine if a given state is an accept state.
|
98
|
-
#
|
99
|
-
# * *Args*:
|
100
|
-
# - +state+ -> The state.
|
101
|
-
# * *Returns*:
|
102
|
-
# Whether or not the state is an accept state. (boolean)
|
73
|
+
# Determines if a given state is an accept state.
|
103
74
|
#
|
75
|
+
# @param [String] state the state label to check.
|
76
|
+
# @return [Boolean] whether or not the state is an accept state.
|
104
77
|
def accept_state?(state)
|
105
78
|
@accept.include? state
|
106
79
|
end
|
107
80
|
end
|
108
|
-
|
109
81
|
end
|
@@ -1,14 +1,25 @@
|
|
1
1
|
module Automata
|
2
|
-
|
3
|
-
##
|
4
2
|
# A generic state diagram class represented as a 5-tuple.
|
5
|
-
#
|
6
|
-
#--
|
7
|
-
# TODO: Check for valid transitions against declared states and alphabet.
|
8
|
-
#
|
9
3
|
class StateDiagram
|
10
4
|
attr_accessor :states, :alphabet, :start, :accept, :transitions
|
11
5
|
|
6
|
+
# @todo Validate machine
|
7
|
+
# Check that each transition reads a valid, declared
|
8
|
+
# input symbol.
|
9
|
+
|
10
|
+
# Initialize and build a StateDiagram object.
|
11
|
+
#
|
12
|
+
# @param [Hash] params the parameters to build the machine with.
|
13
|
+
# @option [String] :file a YAML file containing machine params.
|
14
|
+
# @option [Array<String>] :states the state labels of the machine.
|
15
|
+
# @option [Array<String>] :alphabet the alphabet of input symbols.
|
16
|
+
# @option [String] :start the start state of the machine.
|
17
|
+
# @option [Array<String>] :accept the accept states of the machine.
|
18
|
+
# @option [Hash] :transitions nested hash of transitions for each state.
|
19
|
+
# @note The :transitions hash structure will vary
|
20
|
+
# Different machines will require different transition structures.
|
21
|
+
# Please refer to the {http://github.com/jico/automata/wiki wiki}
|
22
|
+
# for details regarding each machine type.
|
12
23
|
def initialize(params={})
|
13
24
|
yaml = {}
|
14
25
|
yaml = YAML::load_file(params[:file]) if params.has_key? :file
|
@@ -18,7 +29,5 @@ module Automata
|
|
18
29
|
@accept = yaml['accept'] || params[:accept]
|
19
30
|
@transitions = yaml['transitions'] || params[:transitions]
|
20
31
|
end
|
21
|
-
|
22
32
|
end
|
23
|
-
|
24
33
|
end
|
data/lib/automata/version.rb
CHANGED
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.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ 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: &70318108152500 !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: *70318108152500
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &70318108151900 !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: *70318108151900
|
36
36
|
description: Create and simulate automaton.
|
37
37
|
email:
|
38
38
|
- jico@baligod.com
|
@@ -72,7 +72,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
72
72
|
version: '0'
|
73
73
|
segments:
|
74
74
|
- 0
|
75
|
-
hash:
|
75
|
+
hash: 149328891026543090
|
76
76
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
77
|
none: false
|
78
78
|
requirements:
|
@@ -81,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
81
81
|
version: '0'
|
82
82
|
segments:
|
83
83
|
- 0
|
84
|
-
hash:
|
84
|
+
hash: 149328891026543090
|
85
85
|
requirements: []
|
86
86
|
rubyforge_project:
|
87
87
|
rubygems_version: 1.8.17
|