automaton 0.0.1

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.
@@ -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