automaton 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,27 @@
1
+ %%
2
+ %% This is file `multido.sty'.
3
+ %%
4
+ %% IMPORTANT NOTICE:
5
+ %%
6
+ %% multido.sty Copyright (C) 1997 Timothy Van Zandt
7
+ %% (C) 2004 Herbert Voss <voss@perce.de>
8
+ %% Rolf Niepraschk <Rolf.Niepraschk@ptb.de>
9
+ %%
10
+ %% This package may be distributed under the terms of the LaTeX Project
11
+ %% Public License, as described in lppl.txt in the base LaTeX distribution.
12
+ %% Either version 1.0 or, at your option, any later version.
13
+ %%
14
+
15
+ \ProvidesPackage{multido}
16
+ [2004/05/17 package wrapper for PSTricks `multido.tex', (HV/RN)]
17
+
18
+ \@ifundefined{MultidoLoaded}
19
+ {%
20
+ \input{multido.tex}
21
+ \ProvidesFile{multido.tex}
22
+ [\filedate\space v\fileversion\space `multido' (tvz)]
23
+ }{}
24
+
25
+ \endinput
26
+ %%
27
+ %% End of file `multido.sty'.
@@ -0,0 +1,24 @@
1
+ \documentclass{report}
2
+
3
+ \usepackage{vaucanson-g}
4
+
5
+ \begin{document}
6
+ \begin{VCPicture}{(0,0)(10, 10)}
7
+
8
+ % states
9
+ %\State[p]{(0,0)}{A} \State{(3,0)}{B} \State[r]{(6,0.5)}{C}
10
+ <%= @states.join("\n")%>
11
+
12
+ % initial--final
13
+ % \Initial{A}
14
+ <%= @initial %>
15
+
16
+ % \Final{C}
17
+ <%= @finals.join("\n")%>
18
+
19
+ % transitions
20
+ %\EdgeL{B}{A}{a} \EdgeL{B}{C}{b}
21
+ <%= @transitions.join("\n") %>
22
+
23
+ \end{VCPicture}
24
+ \end{document}
@@ -0,0 +1,14 @@
1
+ \ProvidesPackage{vaucanson-g}[2003/05/09 package wrapper for Vaucanson-G]
2
+ \DeclareOption{slides}{\AtEndOfPackage{\input VCPref-slides.tex}}
3
+ \ProcessOptions
4
+ \RequirePackage{ifthen}
5
+ \RequirePackage[usenames]{pstcol}
6
+ \RequirePackage{pst-node}
7
+ \RequirePackage{pst-plot}
8
+ \RequirePackage{pst-coil}
9
+ %\RequirePackage{multido}
10
+ \RequirePackage{pst-3d}
11
+ \RequirePackage{color}
12
+ \RequirePackage{calc}
13
+ \input Vaucanson-G.tex
14
+ \endinput
@@ -0,0 +1,180 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require 'automaton'
3
+
4
+ describe Automaton do
5
+
6
+ it "can be pruned" do
7
+ automata = Automaton.create(:a, :b, {:a => {'1' => [:b], '2' => [:d]}, :c => {'3' => [:b]}})
8
+ expected = Automaton.create(:a, :b, {:a => {'1' => [:b], '2' => [:d]}})
9
+ automata.prune.should == expected
10
+ end
11
+
12
+ it "has successors" do
13
+ automata = Automaton.create(:a, :b, {:a => {'1' => [:b, :c], '2' => [:d]}, :c => {'3' => [:b]}})
14
+ automata.successors_of(:a).should == Set[:b, :c, :d]
15
+ automata.successors_of(:b).should == Set.new
16
+ automata.successors_of(:c).should == Set[:b]
17
+ end
18
+
19
+ it "has start state and final states" do
20
+ automata = Automaton.create(:a, :b, {:a => {'1' => [:b, :c], '2' => [:d]}, :c => {'3' => [:b]}})
21
+ automata.start.should == :a
22
+ automata.finals.should == Set[:b]
23
+ end
24
+
25
+ it "is comparable" do
26
+ a = Automaton.create(:a, :b, '1' => {:a => :b})
27
+ b = Automaton.create(:a, :b, '1' => {:a => :b})
28
+ a.should == b
29
+ end
30
+
31
+ it "is taggable" do
32
+ automata = Automaton.create(:a, :b, :a => {'1' => [:b, :c]})
33
+ automata.tag(:left).should == Automaton.create(:a_left, [:b_left], :a_left => {'1' => [:b_left, :c_left]})
34
+ end
35
+
36
+ it "has reachable states" do
37
+ automata = Automaton.create(:a, :b, {:a => {'1' => [:b, :c], '2' => [:d]}, :x => {'3' => [:a]}})
38
+ automata.reachable_states.should == Set[:a, :b, :c, :d]
39
+ end
40
+
41
+ #NOTE This is meaningless now that the states are stored as a set
42
+ it "does not repeat reachable states" do
43
+ automata = Automaton.create(:a, :a, {:a => {'1' => [:a]}})
44
+ automata.reachable_states.should == Set[:a]
45
+ end
46
+
47
+ it "can deal with loops on reachable states" do
48
+ automata = Automaton.create(:a, :x, {:a => {'1' => [:b]}, :b => {'1' => [:a]}})
49
+ automata.reachable_states.should == Set[:a, :b]
50
+ end
51
+
52
+ it "has an alphabet" do
53
+ automata = Automaton.create(:a, :b, :a => {'1' => :b, '2' => :x},
54
+ :b => {'1' => :x, '2' => :c},
55
+ :x => {'1' => :x, '2' => :x})
56
+ automata.alphabet.should == Set['1', '2']
57
+ end
58
+
59
+ it "has transitions" do
60
+ automaton = Automaton.create(:a, :b, :a => {'1' => [:b, :c], '2' => [:d]}, :b => {'3' => [:f]})
61
+ one = Automaton::Transition.new(:a, Set[:b, :c], '1')
62
+ two = Automaton::Transition.new(:a, Set[:d], '2')
63
+ three = Automaton::Transition.new(:b, Set[:f], '3')
64
+ automaton.transitions.to_set.should == Set[one, two, three]
65
+ end
66
+
67
+ it "may not accept any strings" do
68
+ Automaton.create(:a, [:b], :a => {'1' => :b}).should be_accepting
69
+ Automaton.create(:a, [], :a => {'1' => :b}).should_not be_accepting
70
+ Automaton.create(:a, [:b], :a => {'1' =>:c}).should_not be_accepting
71
+ end
72
+
73
+ it "has a complement" do
74
+ automata = Automaton.create(:a, :b, {:a => {'1' => [:b, :c], '2' => [:d]}, :c => {'3' => [:b]}})
75
+ automata.complement.complement.should == automata
76
+ automata.complement.finals.should == Set[:a,:c,:d]
77
+ end
78
+
79
+ it "has intersection for total DFA" do
80
+ one = Automaton.create(:a, :b, :a => {'1' => :b, '2' => :a}, :b => {'1' => :b, '2' => :b})
81
+ two = Automaton.create(:x, [:x, :y], :x => {'1' => :y, '2' => :x}, :y => {'1' => :x, '2' => :y})
82
+ product = Automaton.create(:a_x, [:b_x, :b_y], :a_x => {'1' => :b_y, '2' => :a_x},
83
+ :b_x => {'1' => :b_y, '2' => :b_x},
84
+ :b_y => {'1' => :b_x, '2' => :b_y})
85
+ one.intersect(two).should == product
86
+ end
87
+
88
+ it "has intersection for NFA" do
89
+ one = Automaton.create(:a, :b, :a => {'2' => :a}, :b => {'1' => :b, '2' => [:a,:b]})
90
+ two = Automaton.create(:x, [:x, :y], :x => {'1' => :y, '2' => :x}, :y => {'1' => :x, '2' => :y})
91
+ product = Automaton.create(:a_x, [:b_x, :b_y], :a_x => {'2' => :a_x},
92
+ :a_y => {'2' => :a_y},
93
+ :b_x => {'1' => :b_y, '2' => [:a_x,:b_x]},
94
+ :b_y => {'1' => :b_x, '2' => [:a_y,:b_y]})
95
+ one.intersect(two).should == product
96
+ end
97
+
98
+ it "subtracts another automata from itself" do
99
+ one = Automaton.create(:a, [:b], :a => {'1' => [:b]})
100
+ one_two = Automaton.create(:a, [:b, :c], {:a => {'1' => :b, '2' => :c}})
101
+ (one_two - one).should be_accepting
102
+ (one - one_two).should_not be_accepting
103
+ (one - one).should_not be_accepting
104
+ end
105
+
106
+ it "can be made total" do
107
+ input = [:a, :b, {:a => {'1' => [:b,:c]}}]
108
+ automata = Automaton.create(*input)
109
+ total_automata = Automaton.create(:a, :b, :a => {'1' => [:b,:c], '2' => :x},
110
+ :b => {'1' => :x, '2' => :x},
111
+ :c => {'1' => :x, '2' => :x},
112
+ :x => {'1' => :x, '2' => :x})
113
+ automata.to_total(Set['1','2']).should == total_automata
114
+ automata.to_total(Set['1','2']).to_total(Set['1','2']).should == automata.to_total(Set['1','2'])
115
+ end
116
+
117
+ it "is comparable to other automata" do
118
+ a = Automaton.create(:a, [:b], :a => {'1' => :b})
119
+ b = Automaton.create(:a, [:b], :a => {'2' => :b})
120
+ a.should_not be_accepting_same_language_as(b)
121
+ a.should be_accepting_same_language_as(a)
122
+
123
+ a = Automaton.create(:a, [:b], :a => {'1' => :b})
124
+ b = Automaton.create(:a, [:b], :a => {'1' => :b})
125
+ a.should be_accepting_same_language_as(b)
126
+
127
+ end
128
+
129
+ it "determines if it accepts a subset of the lanugage of other automata" do
130
+ small = Automaton.create(:a, [:b], {:a => {'1' => :b}})
131
+ medium = Automaton.create(:a, [:b, :c], {:a => {'1' => :b}, :b => {'2' => :c}})
132
+ large = Automaton.create(:a, [:b, :c], {:a => {'1' => :b, '2' => :c}, :b => {'1' => :c}})
133
+
134
+ small.subset?(medium).should be_true
135
+ small.subset?(large).should be_true
136
+ large.subset?(large).should be_true
137
+ medium.subset?(small).should be_false
138
+ large.subset?(medium).should be_false
139
+ small.subset?(small).should be_true
140
+ medium.subset?(medium).should be_true
141
+ large.subset?(large).should be_true
142
+ end
143
+
144
+ it "has a latex representation" do
145
+ small = Automaton.create(:a, :b, :a => {'1' => :b})
146
+ latex = Automaton::Latex.new(:a, [:b], [[:a, 0, 0], [:b, 1, 1]], [[:a, :b, '1']])
147
+ small.to_tex.should == latex
148
+ end
149
+ end
150
+
151
+ describe Automaton::Graph do
152
+
153
+ it "allows a state to have no transitions" do
154
+ tf = Automaton::Graph.new
155
+ tf[:a].should == {}
156
+ tf[:a]='b'
157
+ tf[:a].should == 'b'
158
+ hash = {:b => {'2' => Set[:c]}}
159
+ Automaton::Graph.from_hash(hash)[:a].should_not == hash[:a]
160
+ Automaton::Graph.from_hash(hash)[:b].should == hash[:b]
161
+ end
162
+
163
+ it "can merge two hashes of transitions" do
164
+ t1 = {}
165
+ t2 = {'1' => Set[:a]}
166
+ Automaton::Graph.merge_transitions(t1,t2).should == t2
167
+ end
168
+
169
+ it "can merge in another transition function" do
170
+ tf1 = Automaton::Graph.from_hash({:a => {'1' => [:a,:b]}})
171
+ tf2 = Automaton::Graph.from_hash({:a => {'1' => [:a,:c]}})
172
+ tf3 = Automaton::Graph.from_hash({:b => {'1' => [:a,:c]}})
173
+ tf1.merge(tf1).should == tf1.merge(tf1)
174
+ tf2.merge(tf2).should == tf2.merge(tf2)
175
+ tf2.merge(tf1).should == tf1.merge(tf2)
176
+ tf2.merge(tf3).should == Automaton::Graph.from_hash({:b => {'1' => [:a,:c]}, :a => {'1' => [:a,:c]}})
177
+ tf1.merge(tf2).class.should == Automaton::Graph
178
+ end
179
+
180
+ end
@@ -0,0 +1,48 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require 'layout'
3
+
4
+ Node = Automaton::Layout::Node
5
+ describe Automaton::Layout do
6
+ before(:all) do
7
+ @a = Node.new(:a, 0, 0)
8
+ @b = Node.new(:b, 0, 1)
9
+ @c = Node.new(:c, 16, 0)
10
+ @a.connect(@b, @c)
11
+ end
12
+
13
+ it "does force direction" do
14
+ graph = Automaton::Layout.new(@a, @b, @c)
15
+ graph.nodes.size.should == 3
16
+ graph.force_direct
17
+ graph.normalize
18
+ graph.nodes.size.should == 3
19
+ end
20
+
21
+ describe Automaton::Layout::Node do
22
+
23
+ before(:all) do
24
+ @a = Node.new(:a, 0, 0)
25
+ @b = Node.new(:b, 0, 1)
26
+ @c = Node.new(:c, 4, 0)
27
+ @a.connect(@b, @c)
28
+ end
29
+
30
+ it "has repulsion" do
31
+ @a.repulsion(@b).should be_close_to_enum(Vector[0, 0.23], 0.01)
32
+ @a.repulsion(@c).should == -@c.repulsion(@a)
33
+ @a.repulsion(@c).should be_close_to_enum(Vector[0.0149, 0], 0.01)
34
+ end
35
+
36
+ it "has attraction" do
37
+ @a.attraction(@b).should be_close_to_enum(Vector[0, -0.8], 0.01)
38
+ @a.attraction(@c).should be_close_to_enum(Vector[0.4, 0], 0.01)
39
+ @a.attraction(@c).should == -@c.attraction(@a)
40
+ @b.attraction(@c).should be_close_to_enum(Vector[0, 0], 0.01)
41
+ end
42
+
43
+ it "has vector to other node" do
44
+ @a.vector(@b).should be_close_to_enum(Vector[0.0, 1.0])
45
+ @a.vector(@c).should be_close_to_enum(Vector[4.0, 0.0])
46
+ end
47
+ end
48
+ end
data/spec/spec.opts ADDED
File without changes
@@ -0,0 +1,45 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
10
+
11
+
12
+ module EnumerableMatchers #:nodoc:
13
+ class BeCloseToEnum #:nodoc:
14
+ def initialize(expected, delta)
15
+ @expected = expected
16
+ @delta = delta
17
+ end
18
+
19
+ def matches?(actual)
20
+ @actual = actual
21
+ return false if actual.nil?
22
+ return false unless @actual.size == @expected.size
23
+ @actual.to_a.zip(@expected.to_a).all? do |actual_item, expected_item|
24
+ (actual_item - expected_item).abs < @delta
25
+ end
26
+ end
27
+
28
+ def failure_message
29
+ "expected #{@expected} +/- (< #{@delta}), got #{@actual}"
30
+ end
31
+
32
+ def description
33
+ "be close to #{@expected} (within +- #{@delta})"
34
+ end
35
+ end
36
+
37
+
38
+ def be_close_to_enum(expected, delta = 1.0e-014)
39
+ BeCloseToEnum.new(expected, delta)
40
+ end
41
+ end
42
+
43
+ Spec::Runner.configure do |config|
44
+ config.include(EnumerableMatchers)
45
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: automaton
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tor Erik Linnerud
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-07-16 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rtex
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.0.0
24
+ version:
25
+ description:
26
+ email: tel@jklm.no
27
+ executables:
28
+ - tex2pdf
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README
33
+ files:
34
+ - lib/layout.rb
35
+ - lib/latex.rb
36
+ - lib/automaton.rb
37
+ - lib/generate.rb
38
+ - lib/ruby_extensions.rb
39
+ - lib/tex/template.tex
40
+ - lib/tex/VCPref-main.tex
41
+ - lib/tex/multido.sty
42
+ - lib/tex/FinalStateVar.tex
43
+ - lib/tex/vaucanson-g.sty
44
+ - lib/tex/Vaucanson-G.tex
45
+ - spec/spec.opts
46
+ - spec/spec_helper.rb
47
+ - spec/layout_spec.rb
48
+ - spec/automaton_spec.rb
49
+ - README
50
+ has_rdoc: true
51
+ homepage: http://www.jklm.no/automation
52
+ post_install_message:
53
+ rdoc_options: []
54
+
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ requirements: []
70
+
71
+ rubyforge_project: automaton
72
+ rubygems_version: 1.2.0
73
+ signing_key:
74
+ specification_version: 2
75
+ summary: Implementation of automata, supporting visualization and regular language operations
76
+ test_files:
77
+ - spec/layout_spec.rb
78
+ - spec/automaton_spec.rb