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,145 @@
|
|
1
|
+
require "rspec_helper"
|
2
|
+
|
3
|
+
require "breadth_first_search"
|
4
|
+
require "graph"
|
5
|
+
|
6
|
+
include Doodl
|
7
|
+
|
8
|
+
describe "BreadthFirstSearch" do
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
@empty = DirectedGraph.new
|
12
|
+
@graph = DirectedGraph.new
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
describe "All Graphs" do
|
17
|
+
before(:each) do
|
18
|
+
@node = @graph.add_node
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should raise an ArgumentError when NOT initialized with a Graph and an node" do
|
22
|
+
lambda { BreadthFirstSearch.new(:do, :dont) }.should raise_error(ArgumentError)
|
23
|
+
lambda { BreadthFirstSearch.new(@empty_graph, :node) }.should raise_error(ArgumentError)
|
24
|
+
lambda { BreadthFirstSearch.new(@empty_graph, @node) }.should raise_error(ArgumentError)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should NOT raise an ArgumentError when initialized with a Graph with a Start-Node that is part of the Graph" do
|
28
|
+
node = @empty.add_node
|
29
|
+
lambda { DepthFirstSearch.new(@empty, node) }.should_not raise_error(ArgumentError)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "Unconnected Graph n[a, b, c] e[]" do
|
34
|
+
before(:each) do
|
35
|
+
@a = @graph.add_node
|
36
|
+
@b = @graph.add_node
|
37
|
+
@c = @graph.add_node
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should return [start_node] when sent BreadthFirstSearch.new(graph, start_node).list" do
|
41
|
+
BreadthFirstSearch.new(@graph, @a).list.should == [@a]
|
42
|
+
BreadthFirstSearch.new(@graph, @b).list.should == [@b]
|
43
|
+
BreadthFirstSearch.new(@graph, @c).list.should == [@c]
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should return INFINITY when sent BreadthFirstSearch.new(graph, start_node).dist[x] if x != start_node" do
|
47
|
+
BreadthFirstSearch.new(@graph, @a).dist[@b].should == INFINITY
|
48
|
+
BreadthFirstSearch.new(@graph, @a).dist[@c].should == INFINITY
|
49
|
+
BreadthFirstSearch.new(@graph, @b).dist[@a].should == INFINITY
|
50
|
+
BreadthFirstSearch.new(@graph, @b).dist[@c].should == INFINITY
|
51
|
+
BreadthFirstSearch.new(@graph, @c).dist[@a].should == INFINITY
|
52
|
+
BreadthFirstSearch.new(@graph, @c).dist[@b].should == INFINITY
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return 0 when sent BreadthFirstSearch.new(graph, start_node).dist[start_node]" do
|
56
|
+
BreadthFirstSearch.new(@graph, @a).dist[@a].should == 0
|
57
|
+
BreadthFirstSearch.new(@graph, @b).dist[@b].should == 0
|
58
|
+
BreadthFirstSearch.new(@graph, @c).dist[@c].should == 0
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should visit a visitor" do
|
62
|
+
visitor = mock("visitor")
|
63
|
+
visitor.should_receive(:init).exactly(3).times
|
64
|
+
visitor.should_receive(:discover).once
|
65
|
+
visitor.should_receive(:examine_node).once
|
66
|
+
visitor.should_not_receive(:examine_node)
|
67
|
+
BreadthFirstSearch.new(@graph, @a, visitor)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "Adjacent Graph v:[a, b, c, d] e[(a b), (a c), (b,d)]" do
|
72
|
+
before(:each) do
|
73
|
+
@a = @graph.add_node
|
74
|
+
@b = @graph.add_node
|
75
|
+
@c = @graph.add_node
|
76
|
+
@d = @graph.add_node
|
77
|
+
@m = @graph.add_edge(@a, @b)
|
78
|
+
@n = @graph.add_edge(@b, @c)
|
79
|
+
@o = @graph.add_edge(@b, @d)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should return a list which starts with start_node when sent BreadthFirstSearch.new(graph, start_node).list" do
|
83
|
+
BreadthFirstSearch.new(@graph, @a).list.first.should == @a
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should return the list [a, b, c, d]" do
|
87
|
+
BreadthFirstSearch.new(@graph, @a).list.should == [@a, @b, @c, @d]
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should visit the visitor" do
|
91
|
+
visitor = mock("visitor")
|
92
|
+
visitor.should_receive(:init).exactly(4).times
|
93
|
+
visitor.should_receive(:discover).once.with(@graph, @a)
|
94
|
+
visitor.should_receive(:discover).once.with(@graph, @b)
|
95
|
+
visitor.should_receive(:discover).once.with(@graph, @c)
|
96
|
+
visitor.should_receive(:discover).once.with(@graph, @d)
|
97
|
+
visitor.should_receive(:examine_node).once.with(@graph, @a)
|
98
|
+
visitor.should_receive(:examine_node).once.with(@graph, @b)
|
99
|
+
visitor.should_receive(:examine_node).once.with(@graph, @c)
|
100
|
+
visitor.should_receive(:examine_node).once.with(@graph, @d)
|
101
|
+
visitor.should_receive(:examine_edge).once.with(@graph, @m)
|
102
|
+
visitor.should_receive(:examine_edge).once.with(@graph, @n)
|
103
|
+
visitor.should_receive(:examine_edge).once.with(@graph, @o)
|
104
|
+
BreadthFirstSearch.new(@graph, @a, visitor)
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "Cyclic Graph v:[a, b, c, d] e[(a b), (a c), (c, a), (c, d)]" do
|
110
|
+
before(:each) do
|
111
|
+
@a = @graph.add_node
|
112
|
+
@b = @graph.add_node
|
113
|
+
@c = @graph.add_node
|
114
|
+
@d = @graph.add_node
|
115
|
+
@ab = @graph.add_edge(@a, @b)
|
116
|
+
@bc = @graph.add_edge(@b, @c)
|
117
|
+
@ca = @graph.add_edge(@c, @a)
|
118
|
+
@cd = @graph.add_edge(@c, @d)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should return the list [a, b, c, d]" do
|
122
|
+
BreadthFirstSearch.new(@graph, @a).list.should == [@a, @b, @c, @d]
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should visit the visitor" do
|
126
|
+
visitor = mock("visitor")
|
127
|
+
visitor.should_receive(:init).exactly(4).times
|
128
|
+
visitor.should_receive(:discover).once.with(@graph, @a)
|
129
|
+
visitor.should_receive(:discover).once.with(@graph, @b)
|
130
|
+
visitor.should_receive(:discover).once.with(@graph, @c)
|
131
|
+
visitor.should_receive(:discover).once.with(@graph, @d)
|
132
|
+
visitor.should_receive(:examine_node).once.with(@graph, @a)
|
133
|
+
visitor.should_receive(:examine_node).once.with(@graph, @b)
|
134
|
+
visitor.should_receive(:examine_node).once.with(@graph, @c)
|
135
|
+
visitor.should_receive(:examine_node).once.with(@graph, @d)
|
136
|
+
visitor.should_receive(:examine_edge).once.with(@graph, @ab)
|
137
|
+
visitor.should_receive(:examine_edge).once.with(@graph, @bc)
|
138
|
+
visitor.should_receive(:examine_edge).once.with(@graph, @ca)
|
139
|
+
visitor.should_receive(:examine_edge).once.with(@graph, @cd)
|
140
|
+
BreadthFirstSearch.new(@graph, @a, visitor)
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rspec_helper'
|
4
|
+
|
5
|
+
require "graph"
|
6
|
+
require "connected_components"
|
7
|
+
|
8
|
+
include Doodl
|
9
|
+
|
10
|
+
describe ConnectedComponents do
|
11
|
+
before(:each) do
|
12
|
+
@graph = UndirectedGraph.new
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return 0 if the graph is empty when sent num_connected_components" do
|
16
|
+
ConnectedComponents.new(@graph).num_connected_components.should == 0
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return 1 if the graph has one node" do
|
20
|
+
@graph.add_node
|
21
|
+
ConnectedComponents.new(@graph).num_connected_components.should == 1
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return 2 if the graph has thow unlinked nodes" do
|
25
|
+
@graph.add_node
|
26
|
+
@graph.add_node
|
27
|
+
ConnectedComponents.new(@graph).num_connected_components.should == 2
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return 1 if the graph has two linked nodes" do
|
31
|
+
a = @graph.add_node
|
32
|
+
b = @graph.add_node
|
33
|
+
@graph.add_edge(a, b)
|
34
|
+
ConnectedComponents.new(@graph, a).num_connected_components.should == 1
|
35
|
+
ConnectedComponents.new(@graph, b).num_connected_components.should == 1
|
36
|
+
ConnectedComponents.new(@graph).num_connected_components.should == 1
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should map the nodes to an integer id of their connected component" do
|
40
|
+
@a = @graph.add_node
|
41
|
+
@b = @graph.add_node
|
42
|
+
@c = @graph.add_node
|
43
|
+
@graph.add_edge(@b, @c)
|
44
|
+
cc = ConnectedComponents.new(@graph, @a)
|
45
|
+
cc.num_connected_components.should == 2
|
46
|
+
cc.component[@a].should == 1
|
47
|
+
cc.component[@b].should == 2
|
48
|
+
cc.component[@c].should == 2
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "rspec_helper"
|
4
|
+
|
5
|
+
require "depth_first_search"
|
6
|
+
require "graph"
|
7
|
+
|
8
|
+
include Doodl
|
9
|
+
|
10
|
+
describe "DepthFirstSearch" do
|
11
|
+
|
12
|
+
before(:each) do
|
13
|
+
@graph = DirectedGraph.new
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "Graph: v:[a, b], e[(a b)]" do
|
17
|
+
|
18
|
+
before(:each) do
|
19
|
+
@a = @graph.add_node
|
20
|
+
@b = @graph.add_node
|
21
|
+
@e = @graph.add_edge(@a, @b)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return [a, b] when sent #depth_first_list(a)" do
|
25
|
+
@dfs = DepthFirstSearch.new(@graph, @a)
|
26
|
+
@dfs.list.should == [@a, @b]
|
27
|
+
c = @graph.add_node
|
28
|
+
@dfs = DepthFirstSearch.new(@graph, @a).list.should == [@a, @b, c]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return 1 when sent #d(b)" do
|
32
|
+
@dfs = DepthFirstSearch.new(@graph, @a)
|
33
|
+
@dfs.dist[@b].should == 1
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should visit a start_node, discover, finish, examine" do
|
37
|
+
visitor = mock("visitor")
|
38
|
+
visitor.should_receive(:start_node).once.with(@graph, @a)
|
39
|
+
visitor.should_receive(:discover).once.with(@graph, @a)
|
40
|
+
visitor.should_receive(:discover).once.with(@graph, @b)
|
41
|
+
visitor.should_receive(:finish).once.with(@graph, @a)
|
42
|
+
visitor.should_receive(:finish).once.with(@graph, @b)
|
43
|
+
visitor.should_receive(:examine).once.with(@graph, @e)
|
44
|
+
@dfs = DepthFirstSearch.new(@graph, @a, visitor)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "Graph: v:[a, b, c, d], e[(a b) (a c) (b c) (b d) (d a)]" do
|
50
|
+
|
51
|
+
before(:each) do
|
52
|
+
@a = @graph.add_node
|
53
|
+
@b = @graph.add_node
|
54
|
+
@c = @graph.add_node
|
55
|
+
@d = @graph.add_node
|
56
|
+
@ab = @graph.add_edge(@a, @b)
|
57
|
+
@ac = @graph.add_edge(@a, @c)
|
58
|
+
@bd = @graph.add_edge(@b, @d)
|
59
|
+
@cd = @graph.add_edge(@c, @d)
|
60
|
+
@da = @graph.add_edge(@d, @a)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should return [a, b, d, c] when sent #depth_first_list(a)" do
|
64
|
+
DepthFirstSearch.new(@graph, @a).list.should == [@a, @b, @d, @c]
|
65
|
+
DepthFirstSearch.new(@graph, @a, nil, 1).list.should == [@a, @b, @c, @d]
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should return the right distance when sent #d" do
|
69
|
+
DepthFirstSearch.new(@graph, @a).dist[@a].should == 0
|
70
|
+
DepthFirstSearch.new(@graph, @a).dist[@b].should == 1
|
71
|
+
DepthFirstSearch.new(@graph, @a).dist[@c].should == 3
|
72
|
+
DepthFirstSearch.new(@graph, @a).dist[@d].should == 2
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should visit back edge (da)" do
|
76
|
+
visitor = mock("visitor")
|
77
|
+
visitor.should_receive(:back_edge).once.with(@graph, @da)
|
78
|
+
DepthFirstSearch.new(@graph, @a, visitor)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should visit forward/cross edge (cd)" do
|
82
|
+
visitor = mock("visitor")
|
83
|
+
visitor.should_receive(:forward_edge).once.with(@graph, @cd)
|
84
|
+
DepthFirstSearch.new(@graph, @a, visitor)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
data/spec/edge_spec.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rspec_helper'
|
4
|
+
|
5
|
+
require "edge"
|
6
|
+
|
7
|
+
describe Doodl::Edge do
|
8
|
+
before(:each) do
|
9
|
+
@edge = Doodl::Edge.new(:s, :t)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be initialized with a source and a target" do
|
13
|
+
lambda { Doodl::Edge.new(:s, :t) }.should_not raise_error(Exception)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return true when sent #reflexive? and source and target are the same" do
|
17
|
+
edge = Doodl::Edge.new(:s, :s)
|
18
|
+
edge.reflexive?.should == true
|
19
|
+
edge = Doodl::Edge.new(:s, :t)
|
20
|
+
edge.reflexive?.should_not == true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe Doodl::DirectedEdge do
|
25
|
+
before(:each) do
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should return true when sent #directed?" do
|
29
|
+
Doodl::DirectedEdge.new(:x, :y).directed?.should == true
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should be equal to an other edge with the same source and target" do
|
33
|
+
Doodl::DirectedEdge.new(:x, :y).should == Doodl::DirectedEdge.new(:x, :y)
|
34
|
+
Doodl::DirectedEdge.new(:x, :y).should_not == Doodl::DirectedEdge.new(:x, :z)
|
35
|
+
Doodl::DirectedEdge.new(:x, :y).should_not == Doodl::DirectedEdge.new(:z, :y)
|
36
|
+
|
37
|
+
Doodl::DirectedEdge.new(:x, :y).should_not == "anything"
|
38
|
+
Doodl::DirectedEdge.new(:x, :y).should_not == true
|
39
|
+
Doodl::DirectedEdge.new(:x, :y).should_not == nil
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
describe Doodl::UndirectedEdge do
|
45
|
+
before(:each) do
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should return true when sent #directed?" do
|
49
|
+
Doodl::UndirectedEdge.new(:x, :y).directed?.should == false
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should be equal to an other edge with the same source and target or with fliped source and targets" do
|
53
|
+
Doodl::UndirectedEdge.new(:x, :y).should == Doodl::UndirectedEdge.new(:x, :y)
|
54
|
+
Doodl::UndirectedEdge.new(:x, :y).should == Doodl::UndirectedEdge.new(:y, :x)
|
55
|
+
Doodl::UndirectedEdge.new(:x, :y).should_not == Doodl::UndirectedEdge.new(:z, :y)
|
56
|
+
Doodl::UndirectedEdge.new(:x, :y).should_not == Doodl::UndirectedEdge.new(:x, :z)
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,277 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rspec_helper'
|
4
|
+
require 'graph'
|
5
|
+
require 'graph_generator'
|
6
|
+
|
7
|
+
include Doodl
|
8
|
+
|
9
|
+
describe "All Graphs Generator" , :shared => true do
|
10
|
+
|
11
|
+
describe "GraphGenerator Ring" do
|
12
|
+
it "should generate a graph with #size nodes when sent #gen_ring(size)" do
|
13
|
+
@graph.gen_ring_graph(0)
|
14
|
+
@graph.num_nodes.should == 0
|
15
|
+
@graph.gen_ring_graph(1)
|
16
|
+
@graph.num_nodes.should == 1
|
17
|
+
@graph.gen_ring_graph(2)
|
18
|
+
@graph.num_nodes.should == 2
|
19
|
+
@graph.gen_ring_graph(3)
|
20
|
+
@graph.num_nodes.should == 3
|
21
|
+
@graph.gen_ring_graph(4)
|
22
|
+
@graph.num_nodes.should == 4
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should generate a graph with #size edges when sent #gen_ring(size)" do
|
26
|
+
@graph.gen_ring_graph(0)
|
27
|
+
@graph.num_edges.should == 0
|
28
|
+
@graph.gen_ring_graph(1)
|
29
|
+
@graph.num_edges.should == 0
|
30
|
+
@graph.gen_ring_graph(2)
|
31
|
+
if @graph.directed?
|
32
|
+
@graph.num_edges.should == 2
|
33
|
+
else
|
34
|
+
@graph.num_edges.should == 1
|
35
|
+
end
|
36
|
+
@graph.gen_ring_graph(3)
|
37
|
+
@graph.num_edges.should == 3
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should generate a graph whose nodes have each an outdegree of one" do
|
41
|
+
@graph.gen_ring_graph(2)
|
42
|
+
if @graph.directed?
|
43
|
+
@graph.nodes.inject(true) { |memo, node| memo and (node.out_degree == 1) }.should == true
|
44
|
+
@graph.gen_ring_graph(3)
|
45
|
+
@graph.nodes.inject(true) { |memo, node| memo and (node.out_degree == 1) }.should == true
|
46
|
+
@graph.gen_ring_graph(4)
|
47
|
+
@graph.nodes.inject(true) { |memo, node| memo and (node.out_degree == 1) }.should == true
|
48
|
+
else
|
49
|
+
@graph.nodes.inject(true) { |memo, node| memo and (node.degree == 1) }.should == true
|
50
|
+
@graph.gen_ring_graph(3)
|
51
|
+
@graph.nodes.inject(true) { |memo, node| memo and (node.degree == 2) }.should == true
|
52
|
+
@graph.gen_ring_graph(4)
|
53
|
+
@graph.nodes.inject(true) { |memo, node| memo and (node.degree == 2) }.should == true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "GraphGenerator Random" do
|
60
|
+
it "should generate a random graph of size num_of_nodes when sent gen_random_graph(num_of_nodes)" do
|
61
|
+
@graph.gen_random_graph(0)
|
62
|
+
@graph.num_nodes.should == 0
|
63
|
+
@graph.gen_random_graph(1)
|
64
|
+
@graph.num_nodes.should == 1
|
65
|
+
@graph.gen_random_graph(2)
|
66
|
+
@graph.num_nodes.should == 2
|
67
|
+
@graph.gen_random_graph(3)
|
68
|
+
@graph.num_nodes.should == 3
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should generate a random graph with random edges when sent gen_random(num_nodes)" do
|
72
|
+
@graph.gen_random_graph(0)
|
73
|
+
@graph.num_edges.should == 0
|
74
|
+
@graph.gen_random_graph(1)
|
75
|
+
@graph.num_edges.should == 0
|
76
|
+
@graph.gen_random_graph(2)
|
77
|
+
if @graph.directed?
|
78
|
+
@graph.num_edges.should <= 2
|
79
|
+
else
|
80
|
+
@graph.num_edges.should <= 1
|
81
|
+
end
|
82
|
+
@graph.num_edges.should >= 0
|
83
|
+
@graph.gen_random_graph(3)
|
84
|
+
if @graph.directed?
|
85
|
+
@graph.num_edges.should <= 3*2
|
86
|
+
else
|
87
|
+
@graph.num_edges.should <= 3
|
88
|
+
end
|
89
|
+
@graph.num_edges.should >= 0
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should generate a random graph with num_of_edges edges when sent gen_random(num_nodes, num_edges)" do
|
93
|
+
@graph.gen_random_graph(0)
|
94
|
+
@graph.num_edges.should == 0
|
95
|
+
@graph.gen_random_graph(1, 0)
|
96
|
+
@graph.num_edges.should == 0
|
97
|
+
@graph.gen_random_graph(2, 1)
|
98
|
+
@graph.num_edges.should == 1
|
99
|
+
if @graph.directed?
|
100
|
+
@graph.gen_random_graph(2, 2)
|
101
|
+
@graph.num_edges.should == 2
|
102
|
+
end
|
103
|
+
@graph.gen_random_graph(3, 1)
|
104
|
+
@graph.num_edges.should == 1
|
105
|
+
@graph.gen_random_graph(3, 3)
|
106
|
+
@graph.num_edges.should == 3
|
107
|
+
if @graph.directed?
|
108
|
+
@graph.gen_random_graph(3, 6)
|
109
|
+
@graph.num_edges.should == 6
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should raise an ArgumentError when num_edges is greater than the # of possible edges in a graph" do
|
114
|
+
lambda { @graph.gen_random_graph(0, 1) }.should raise_error(ArgumentError)
|
115
|
+
lambda { @graph.gen_random_graph(1, 2) }.should raise_error(ArgumentError)
|
116
|
+
lambda { @graph.gen_random_graph(3, 7) }.should raise_error(ArgumentError)
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "GraphGenerator Connected" do
|
122
|
+
|
123
|
+
def max_edges(graph)
|
124
|
+
num_nodes = graph.num_nodes
|
125
|
+
if graph.directed?
|
126
|
+
num_nodes * (num_nodes-1)
|
127
|
+
else
|
128
|
+
num_nodes * (num_nodes-1) / 2
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should generate a graph of #size nodes when sent gen_connected(size)" do
|
133
|
+
@graph.gen_connected_graph(0)
|
134
|
+
@graph.num_nodes.should == 0
|
135
|
+
@graph.gen_connected_graph(1)
|
136
|
+
@graph.num_nodes.should == 1
|
137
|
+
@graph.gen_connected_graph(2)
|
138
|
+
@graph.num_nodes.should == 2
|
139
|
+
@graph.gen_connected_graph(3)
|
140
|
+
@graph.num_nodes.should == 3
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should generate a graph with n*n-1 edges (directed) or n*(n-1)/2 edges (undirected)" do
|
144
|
+
@graph.gen_connected_graph(0)
|
145
|
+
@graph.num_edges.should == 0
|
146
|
+
@graph.gen_connected_graph(1)
|
147
|
+
@graph.num_edges.should == 0
|
148
|
+
@graph.gen_connected_graph(2)
|
149
|
+
@graph.num_edges.should == max_edges(@graph)
|
150
|
+
@graph.gen_connected_graph(3)
|
151
|
+
@graph.num_edges.should == max_edges(@graph)
|
152
|
+
@graph.gen_connected_graph(4)
|
153
|
+
@graph.num_edges.should == max_edges(@graph)
|
154
|
+
@graph.gen_connected_graph(9)
|
155
|
+
@graph.num_edges.should == max_edges(@graph)
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should generate a graph whose nodes have each an outdegree/degree of num_edges-1" do
|
159
|
+
if @graph.directed?
|
160
|
+
@graph.gen_connected_graph(2)
|
161
|
+
@graph.nodes.inject(true) { |memo, node| memo and (node.out_degree == 1) }.should == true
|
162
|
+
@graph.gen_connected_graph(3)
|
163
|
+
@graph.nodes.inject(true) { |memo, node| memo and (node.out_degree == 2) }.should == true
|
164
|
+
@graph.gen_connected_graph(4)
|
165
|
+
@graph.nodes.inject(true) { |memo, node| memo and (node.out_degree == 3) }.should == true
|
166
|
+
else
|
167
|
+
@graph.gen_connected_graph(2)
|
168
|
+
@graph.nodes.inject(true) { |memo, node| memo and (node.degree == 1) }.should == true
|
169
|
+
@graph.gen_connected_graph(3)
|
170
|
+
@graph.nodes.inject(true) { |memo, node| memo and (node.degree == 2) }.should == true
|
171
|
+
@graph.gen_connected_graph(4)
|
172
|
+
@graph.nodes.inject(true) { |memo, node| memo and (node.degree == 3) }.should == true
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
describe "GraphGenerator Linear" do
|
179
|
+
it "should generate a graph with #size nodes when sent #gen_linear_graph(size)" do
|
180
|
+
@graph.gen_linear_graph(0)
|
181
|
+
@graph.num_nodes.should == 0
|
182
|
+
@graph.gen_linear_graph(1)
|
183
|
+
@graph.num_nodes.should == 1
|
184
|
+
@graph.gen_linear_graph(2)
|
185
|
+
@graph.num_nodes.should == 2
|
186
|
+
@graph.gen_linear_graph(3)
|
187
|
+
@graph.num_nodes.should == 3
|
188
|
+
@graph.gen_linear_graph(4)
|
189
|
+
@graph.num_nodes.should == 4
|
190
|
+
end
|
191
|
+
|
192
|
+
it "should generate a graph with #size edges when sent #gen_linear_graph(size)" do
|
193
|
+
@graph.gen_linear_graph(0)
|
194
|
+
@graph.num_edges.should == 0
|
195
|
+
@graph.gen_linear_graph(1)
|
196
|
+
@graph.num_edges.should == 0
|
197
|
+
@graph.gen_linear_graph(2)
|
198
|
+
@graph.num_edges.should == 1
|
199
|
+
@graph.gen_linear_graph(3)
|
200
|
+
@graph.num_edges.should == 2
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should generate a graph whose nodes have each an outdegree of one" do
|
204
|
+
@graph.gen_linear_graph(5)
|
205
|
+
if @graph.directed?
|
206
|
+
@graph.nodes.inject(true) { |memo, node| memo and (node.out_degree == 1 or node == @graph.nodes.last) }.should == true
|
207
|
+
else
|
208
|
+
@graph.nodes.inject(true) { |memo, node| memo and (node.degree == 2 or
|
209
|
+
((node == @graph.nodes.first or node == @graph.nodes.last) and node.degree == 1))
|
210
|
+
}.should == true
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
|
216
|
+
describe "GraphGenerator Mesh" do
|
217
|
+
it "should generate a graph with #rows*colums nodes when sent #gen_linear_graph(rows, colums)" do
|
218
|
+
@graph.gen_mesh_graph(0, 0)
|
219
|
+
@graph.num_nodes.should == 0
|
220
|
+
@graph.gen_mesh_graph(1, 1)
|
221
|
+
@graph.num_nodes.should == 1
|
222
|
+
@graph.gen_mesh_graph(1, 2)
|
223
|
+
@graph.num_nodes.should == 2
|
224
|
+
@graph.gen_mesh_graph(1, 3)
|
225
|
+
@graph.num_nodes.should == 3
|
226
|
+
|
227
|
+
@graph.gen_mesh_graph(2, 1)
|
228
|
+
@graph.num_nodes.should == 2
|
229
|
+
@graph.gen_mesh_graph(3, 1)
|
230
|
+
@graph.num_nodes.should == 3
|
231
|
+
|
232
|
+
@graph.gen_mesh_graph(2, 2)
|
233
|
+
@graph.num_nodes.should == 4
|
234
|
+
@graph.gen_mesh_graph(3, 3)
|
235
|
+
@graph.num_nodes.should == 9
|
236
|
+
|
237
|
+
@graph.gen_mesh_graph(2)
|
238
|
+
@graph.num_nodes.should == 4
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should have edges" do
|
242
|
+
@graph.gen_mesh_graph(0, 0)
|
243
|
+
@graph.num_edges.should == 0
|
244
|
+
@graph.gen_mesh_graph(1, 0)
|
245
|
+
@graph.num_edges.should == 0
|
246
|
+
@graph.gen_mesh_graph(1, 1)
|
247
|
+
@graph.num_edges.should == 0
|
248
|
+
@graph.gen_mesh_graph(1, 2)
|
249
|
+
@graph.num_edges.should == 1
|
250
|
+
@graph.gen_mesh_graph(2, 1)
|
251
|
+
@graph.num_edges.should == 1
|
252
|
+
@graph.gen_mesh_graph(2, 2)
|
253
|
+
@graph.num_edges.should == 4
|
254
|
+
@graph.gen_mesh_graph(2)
|
255
|
+
@graph.num_edges.should == 4
|
256
|
+
@graph.gen_mesh_graph(3)
|
257
|
+
@graph.num_edges.should == 12
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
end
|
262
|
+
|
263
|
+
describe "DirectedGraph" do
|
264
|
+
before(:each) do
|
265
|
+
@graph = DirectedGraph.new
|
266
|
+
end
|
267
|
+
|
268
|
+
it_should_behave_like "All Graphs Generator"
|
269
|
+
end
|
270
|
+
|
271
|
+
describe "UndirectedGraph" do
|
272
|
+
before(:each) do
|
273
|
+
@graph = UndirectedGraph.new
|
274
|
+
end
|
275
|
+
|
276
|
+
it_should_behave_like "All Graphs Generator"
|
277
|
+
end
|