iconofthestoneage-doodl 0.0.2 → 0.0.4
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/lib/app/selfrunning.rb +185 -0
- data/lib/app/simple_app.rb +49 -0
- data/lib/app/simple_controller.rb +584 -0
- data/lib/app/simple_model.rb +292 -0
- data/lib/app/simple_view.rb +148 -0
- data/lib/breadth_first_search.rb +69 -0
- data/lib/connected_components.rb +29 -0
- data/lib/depth_first_search.rb +73 -0
- data/lib/edge.rb +57 -0
- data/lib/graph.rb +365 -0
- data/lib/graph_canvas.rb +187 -0
- data/lib/graph_generator.rb +121 -0
- data/lib/jruby/renderer.rb +413 -0
- data/lib/layout/collapse_layout.rb +23 -0
- data/lib/layout/fr_layout.rb +105 -0
- data/lib/layout/isom_layout.rb +77 -0
- data/lib/layout/kk_layout.rb +203 -0
- data/lib/layout/layout.rb +240 -0
- data/lib/layout/morph_layout.rb +65 -0
- data/lib/node.rb +57 -0
- data/lib/shortest_path/all_pair.rb +35 -0
- data/lib/shortest_path/bellman_ford.rb +60 -0
- data/lib/shortest_path/dijkstra.rb +74 -0
- data/lib/shortest_path/floyd_warshall.rb +68 -0
- data/lib/shortest_path/johnson_all_pair.rb +64 -0
- data/lib/shortest_path/single_source.rb +32 -0
- data/spec/breadth_first_search_spec.rb +145 -0
- data/spec/connected_components_spec.rb +50 -0
- data/spec/depth_first_search_spec.rb +89 -0
- data/spec/edge_spec.rb +58 -0
- data/spec/graph_generator_spec.rb +277 -0
- data/spec/graph_spec.rb +269 -0
- data/spec/jruby/renderer_spec.rb +214 -0
- data/spec/layout/layout_spec.rb +146 -0
- data/spec/node_spec.rb +179 -0
- data/spec/rspec_helper.rb +9 -0
- data/spec/rspec_suite.rb +12 -0
- data/spec/shortest_path/bellman_ford_spec.rb +101 -0
- data/spec/shortest_path/dijkstra_spec.rb +133 -0
- data/spec/shortest_path/floyd_warshall_spec.rb +84 -0
- data/spec/shortest_path/johnson_all_pair_spec.rb +90 -0
- metadata +43 -2
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'rspec_helper'
|
2
|
+
require 'layout/layout'
|
3
|
+
|
4
|
+
include Doodl
|
5
|
+
|
6
|
+
describe Location do
|
7
|
+
before(:each) do
|
8
|
+
@v = Location.new(3, 3)
|
9
|
+
end
|
10
|
+
it "should be initialized using two fixnums" do
|
11
|
+
lambda { Location.new(0, 0) }.should_not raise_error(Exception)
|
12
|
+
lambda { Location.new(0.0, 0.0) }.should_not raise_error(Exception)
|
13
|
+
v = Location.new(1, 0)
|
14
|
+
v.x.should == 1
|
15
|
+
v.y.should == 0
|
16
|
+
v = Location.new(1.1, 0.1)
|
17
|
+
v.x.should == 1.1
|
18
|
+
v.y.should == 0.1
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should be initialized with two points" do
|
22
|
+
lambda { Location.new(Location.new(0,0), Location.new(0,0)) }.should_not raise_error(Exception)
|
23
|
+
v = Location.new(Location.new(1, 1), Location.new(2, 2))
|
24
|
+
v.x.should == 1
|
25
|
+
v.y.should == 1
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should return have an unary - operator" do
|
29
|
+
v = Location.new(1, 4)
|
30
|
+
w = -v
|
31
|
+
w.x.should == -1
|
32
|
+
w.y.should == -4
|
33
|
+
v.should_not == w
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should have a / operator" do
|
37
|
+
x = @v / 2.0
|
38
|
+
x.x.should == 1.5
|
39
|
+
x.y.should == 1.5
|
40
|
+
x.should_not == @v
|
41
|
+
@v.x.should == 3
|
42
|
+
@v.y.should == 3
|
43
|
+
y = @v
|
44
|
+
y /= 3
|
45
|
+
y.x == 1
|
46
|
+
@v.should_not == y
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should have a * operator" do
|
50
|
+
x = @v * 2.0
|
51
|
+
x.x.should == 6.0
|
52
|
+
x.y.should == 6.0
|
53
|
+
x.should_not == @v
|
54
|
+
@v.y.should == 3
|
55
|
+
@v.y.should == 3
|
56
|
+
y = @v
|
57
|
+
y *= 3
|
58
|
+
y.x.should == 9
|
59
|
+
@v.should_not == y
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should have an + operator" do
|
63
|
+
x = @v + @v
|
64
|
+
x.x.should == 6.0
|
65
|
+
x.y.should == 6.0
|
66
|
+
x.should_not == @v
|
67
|
+
@v.x.should == 3
|
68
|
+
@v.y.should == 3
|
69
|
+
y = @v
|
70
|
+
y += x
|
71
|
+
y.x.should == 9
|
72
|
+
@v.should_not == y
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should have an binary - operator" do
|
76
|
+
x = @v - @v
|
77
|
+
x.x.should == 0.0
|
78
|
+
x.y.should == 0.0
|
79
|
+
x.should_not == @v
|
80
|
+
@v.x.should == 3
|
81
|
+
@v.y.should == 3
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should have a #div! method which alters and returns the vector" do
|
85
|
+
@v.div!(2.0).should == @v
|
86
|
+
@v.x.should == 1.5
|
87
|
+
@v.y.should == 1.5
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should have a #mul! method which multiplies and retruns the vector" do
|
91
|
+
@v.mul!(2).should == @v
|
92
|
+
@v.x.should == 6
|
93
|
+
@v.y.should == 6
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should have a #add! method which adds two scalars and returns the vector" do
|
97
|
+
@v.add!(1, 2).should == @v
|
98
|
+
@v.x.should == 4
|
99
|
+
@v.y.should == 5
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should have a #add! method which adds an other vector returns the vector" do
|
103
|
+
@v.add!(Location.new(1, 2)).should == @v
|
104
|
+
@v.x.should == 4
|
105
|
+
@v.y.should == 5
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should have a #sub! method which subtracts two scalars and returns the vector" do
|
109
|
+
@v.sub!(1, 2).should == @v
|
110
|
+
@v.x.should == 2
|
111
|
+
@v.y.should == 1
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should have a #add! method which subtracts an other vector returns the vector" do
|
115
|
+
@v.sub!(Location.new(1, 2)).should == @v
|
116
|
+
@v.x.should == 2
|
117
|
+
@v.y.should == 1
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should return the length of the vector when sent #length" do
|
121
|
+
@v.length.should == Math.sqrt(18)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should have the length of 1 when altered by sending #normalize!" do
|
125
|
+
v = Location.new(3.0, 4.0)
|
126
|
+
length = v.length
|
127
|
+
v.normalize!.should == v
|
128
|
+
v.length.should == 1
|
129
|
+
(v.x / v.y).should be_close(3.0/4.0, Float::EPSILON)
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should have a rotate_radians! method" do
|
133
|
+
v = Location.new(1.0, 0.0)
|
134
|
+
v.rotate_radians!(Math::PI).should == v
|
135
|
+
v.x.should be_close(-1.0, Float::EPSILON)
|
136
|
+
v.y.should be_close(0.0, Float::EPSILON)
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should have a rotate! method" do
|
140
|
+
v = Location.new(1.0, 0.0)
|
141
|
+
v.rotate!(180).should == v
|
142
|
+
v.x.should be_close(-1.0, Float::EPSILON)
|
143
|
+
v.y.should be_close(0.0, Float::EPSILON)
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
data/spec/node_spec.rb
ADDED
@@ -0,0 +1,179 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rspec_helper'
|
4
|
+
|
5
|
+
require 'enumerator'
|
6
|
+
require "node"
|
7
|
+
|
8
|
+
include Doodl
|
9
|
+
|
10
|
+
describe "DirectedNode" do
|
11
|
+
|
12
|
+
before(:each) do
|
13
|
+
@node = DirectedNode.new
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should add an edge when sent #add_edge" do
|
17
|
+
@node.should respond_to(:add_out_edge)
|
18
|
+
lambda { @node.add_out_edge(:edge) }.should_not raise_error(Exception)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return whether it includes an added edge when sent #include_edge?(edge)" do
|
22
|
+
@node.should respond_to(:includes_out_edge?)
|
23
|
+
@node.add_out_edge(:edge)
|
24
|
+
@node.includes_out_edge?(:edge).should == true
|
25
|
+
@node.includes_out_edge?(:else).should == false
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should return a Iterator that iterates over the added edge when sent #each_edge" do
|
29
|
+
@node.should respond_to(:each_out_edge)
|
30
|
+
@node.add_out_edge(:edge)
|
31
|
+
@node.add_out_edge(:other)
|
32
|
+
enum = Enumerable::Enumerator.new(@node, :each_out_edge)
|
33
|
+
enum.to_a.should == [:edge, :other]
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return the number of included nodes when sent #degree" do
|
37
|
+
@node.should respond_to(:out_degree)
|
38
|
+
@node.out_degree.should == 0
|
39
|
+
@node.add_out_edge(:edge1)
|
40
|
+
@node.out_degree.should == 1
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should delete an included edge when sent delete_edge(edge)" do
|
44
|
+
@node.should respond_to(:del_out_edge)
|
45
|
+
@node.add_out_edge(:edge)
|
46
|
+
@node.del_out_edge(:edge)
|
47
|
+
@node.out_degree.should == 0
|
48
|
+
@node.add_out_edge(:edge)
|
49
|
+
@node.del_out_edge(:other)
|
50
|
+
@node.out_degree.should == 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "UndirectedNode" do
|
55
|
+
|
56
|
+
before(:each) do
|
57
|
+
@node = UndirectedNode.new
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should add an edge when sent #add_edge" do
|
61
|
+
@node.should respond_to(:add_edge)
|
62
|
+
lambda { @node.add_edge(:edge) }.should_not raise_error(Exception)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should return whether it includes an added edge when sent #include_edge?(edge)" do
|
66
|
+
@node.should respond_to(:includes_edge?)
|
67
|
+
@node.add_edge(:edge)
|
68
|
+
@node.includes_edge?(:edge).should == true
|
69
|
+
@node.includes_edge?(:else).should == false
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should return a Iterator that iterates over the added edge when sent #each_edge" do
|
73
|
+
@node.should respond_to(:each_edge)
|
74
|
+
@node.add_edge(:edge)
|
75
|
+
@node.add_edge(:other)
|
76
|
+
enum = Enumerable::Enumerator.new(@node, :each_edge)
|
77
|
+
enum.to_a.should == [:edge, :other]
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should return the number of included nodes when sent #degree" do
|
81
|
+
@node.should respond_to(:degree)
|
82
|
+
@node.degree.should == 0
|
83
|
+
@node.add_edge(:edge1)
|
84
|
+
@node.degree.should == 1
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should delete an included edge when sent delete_edge(edge)" do
|
88
|
+
@node.should respond_to(:del_edge)
|
89
|
+
@node.add_edge(:edge)
|
90
|
+
@node.del_edge(:edge)
|
91
|
+
@node.degree.should == 0
|
92
|
+
@node.add_edge(:edge)
|
93
|
+
@node.del_edge(:other)
|
94
|
+
@node.degree.should == 1
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "SimpleBidirectionalNode" do
|
100
|
+
|
101
|
+
before(:each) do
|
102
|
+
@node = SimpleBidirectionalNode.new
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should add an edge when sent #add_in_edge" do
|
106
|
+
@node.should respond_to(:add_in_edge)
|
107
|
+
lambda { @node.add_in_edge(:edge) }.should_not raise_error(Exception)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should return whether it includes an added edge when sent #include_in_edge?(edge)" do
|
111
|
+
@node.should respond_to(:includes_in_edge?)
|
112
|
+
@node.add_in_edge(:edge)
|
113
|
+
@node.includes_in_edge?(:edge).should == true
|
114
|
+
@node.includes_in_edge?(:else).should == false
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should return a Iterator that iterates over the added edge when sent #each_in_edge" do
|
118
|
+
@node.should respond_to(:each_in_edge)
|
119
|
+
@node.add_in_edge(:edge)
|
120
|
+
@node.add_in_edge(:other)
|
121
|
+
enum = Enumerable::Enumerator.new(@node, :each_in_edge)
|
122
|
+
enum.to_a.should == [:edge, :other]
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should return the number of included nodes when sent #in_degree" do
|
126
|
+
@node.should respond_to(:in_degree)
|
127
|
+
@node.in_degree.should == 0
|
128
|
+
@node.add_in_edge(:edge1)
|
129
|
+
@node.in_degree.should == 1
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should delete an included edge when sent delete_in_edge(edge)" do
|
133
|
+
@node.should respond_to(:del_in_edge)
|
134
|
+
@node.add_in_edge(:edge)
|
135
|
+
@node.del_in_edge(:edge)
|
136
|
+
@node.in_degree.should == 0
|
137
|
+
@node.add_in_edge(:edge)
|
138
|
+
@node.del_in_edge(:other)
|
139
|
+
@node.in_degree.should == 1
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should add an edge when sent #add_out_edge" do
|
143
|
+
@node.should respond_to(:add_out_edge)
|
144
|
+
lambda { @node.add_out_edge(:edge) }.should_not raise_error(Exception)
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should return whether it includes an added edge when sent #include_out_edge?(edge)" do
|
148
|
+
@node.should respond_to(:includes_out_edge?)
|
149
|
+
@node.add_out_edge(:edge)
|
150
|
+
@node.includes_out_edge?(:edge).should == true
|
151
|
+
@node.includes_out_edge?(:else).should == false
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should return a Iterator that iterates over the added edge when sent #each_out_edge" do
|
155
|
+
@node.should respond_to(:each_out_edge)
|
156
|
+
@node.add_out_edge(:edge)
|
157
|
+
@node.add_out_edge(:other)
|
158
|
+
enum = Enumerable::Enumerator.new(@node, :each_out_edge)
|
159
|
+
enum.to_a.should == [:edge, :other]
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should return the number of included nodes when sent #out_degree" do
|
163
|
+
@node.should respond_to(:out_degree)
|
164
|
+
@node.out_degree.should == 0
|
165
|
+
@node.add_out_edge(:edge1)
|
166
|
+
@node.out_degree.should == 1
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should delete an included edge when sent delete_out_edge(edge)" do
|
170
|
+
@node.should respond_to(:del_out_edge)
|
171
|
+
@node.add_out_edge(:edge)
|
172
|
+
@node.del_out_edge(:edge)
|
173
|
+
@node.out_degree.should == 0
|
174
|
+
@node.add_out_edge(:edge)
|
175
|
+
@node.del_out_edge(:other)
|
176
|
+
@node.out_degree.should == 1
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "spec"
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'lib')
|
7
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'spec')
|
8
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '../lib')
|
9
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '../spec')
|
data/spec/rspec_suite.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require "rspec_helper"
|
2
|
+
require "graph"
|
3
|
+
require "shortest_path/bellman_ford"
|
4
|
+
|
5
|
+
include Doodl
|
6
|
+
|
7
|
+
describe "BellbanFord" do
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
@graph = DirectedGraph.new
|
11
|
+
@u = @graph.add_node
|
12
|
+
@v = @graph.add_node
|
13
|
+
@w = @graph.add_node
|
14
|
+
@x = @graph.add_node
|
15
|
+
@y = @graph.add_node
|
16
|
+
@z = @graph.add_node
|
17
|
+
|
18
|
+
@uv = @graph.add_edge(@u, @v)
|
19
|
+
@uw = @graph.add_edge(@u, @w)
|
20
|
+
@ux = @graph.add_edge(@u, @x)
|
21
|
+
@vx = @graph.add_edge(@v, @x)
|
22
|
+
@xz = @graph.add_edge(@x, @z)
|
23
|
+
@wy = @graph.add_edge(@w, @y)
|
24
|
+
@yz = @graph.add_edge(@y, @z)
|
25
|
+
|
26
|
+
@weight = @graph.attach_edge_data(:weight)
|
27
|
+
@weight[@uv] = 1
|
28
|
+
@weight[@uw] = 1
|
29
|
+
@weight[@ux] = 1
|
30
|
+
@weight[@vx] = 1
|
31
|
+
@weight[@xz] = 1
|
32
|
+
@weight[@wy] = 1
|
33
|
+
@weight[@yz] = 1
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should raise an ArgumentError when not initialized a graph and a start node" do
|
37
|
+
lambda { BellmanFord.new(Object.new, :node) }.should raise_error(ArgumentError)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should raise an ArgumentError when not initialized with a start_node that is a graph member" do
|
41
|
+
lambda { BellmanFord.new(Graph.new, :node) }.should raise_error(ArgumentError)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should NOT raise an ArgumentError when initialized with a weighted graph, a contained node" do
|
45
|
+
graph = DirectedGraph.new
|
46
|
+
node = graph.add_node
|
47
|
+
lambda { BellmanFord.new(graph, node, Hash.new(1)) }.should_not raise_error(ArgumentError)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should return the distance 0 for the start node" do
|
51
|
+
bf = BellmanFord.new(@graph, @u, @weight)
|
52
|
+
bf.dist[@u].should == 0
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return the shortest distance d(u,x) with u being the source and x being a node of the graph when sent #dist[x]" do
|
56
|
+
bf = BellmanFord.new(@graph, @u, @weight)
|
57
|
+
bf.dist[@v].should == 1
|
58
|
+
bf.dist[@x].should == 1
|
59
|
+
bf.dist[@w].should == 1
|
60
|
+
bf.dist[@y].should == 2
|
61
|
+
bf.dist[@z].should == 2
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should return INFINITY when sent #dist[x] if x is not reachable" do
|
65
|
+
bf = BellmanFord.new(@graph, @z, @weight)
|
66
|
+
bf.dist[@u].should == INFINITY
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should return the previous node of x in the shortes path tree when sent #prev[x]" do
|
70
|
+
bf = BellmanFord.new(@graph, @u, @weight)
|
71
|
+
bf.prev[@u].should == nil
|
72
|
+
bf.prev[@v].should == @u
|
73
|
+
bf.prev[@x].should == @u
|
74
|
+
bf.prev[@y].should == @w
|
75
|
+
bf.prev[@z].should == @x
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should return nil when sent #prev[x] and x is not reachable" do
|
79
|
+
fw = BellmanFord.new(@graph, @z, @weight)
|
80
|
+
fw.prev[@u].should == nil
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should return an array containing the nodes of the shortest path when sent node_path_to(x)" do
|
84
|
+
bf = BellmanFord.new(@graph, @u, @weight)
|
85
|
+
bf.node_path_to(@u).should == [@u]
|
86
|
+
bf.node_path_to(@v).should == [@u, @v]
|
87
|
+
bf.node_path_to(@z).should == [@u, @x, @z]
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should return an array of edge representing the shortest path, when sent edge_path_to" do
|
91
|
+
bf = BellmanFord.new(@graph, @u, @weight)
|
92
|
+
bf.edge_path_to(@u).should == []
|
93
|
+
bf.edge_path_to(@v).should == [@graph.get_edge(@u, @v)]
|
94
|
+
bf.edge_path_to(@z).should == [@graph.get_edge(@u, @x), @graph.get_edge(@x, @z)]
|
95
|
+
bf = BellmanFord.new(@graph, @u, Hash.new(1))
|
96
|
+
bf.edge_path_to(@u).should == []
|
97
|
+
bf.edge_path_to(@v).should == [@graph.get_edge(@u, @v)]
|
98
|
+
bf.edge_path_to(@z).should == [@graph.get_edge(@u, @x), @graph.get_edge(@x, @z)]
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|