jumoku 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +0 -2
- data/lib/jumoku.rb +36 -8
- data/lib/jumoku/builders/arborescence.rb +11 -0
- data/lib/jumoku/builders/extended.rb +327 -0
- data/lib/jumoku/builders/raw_directed_tree.rb +33 -0
- data/lib/jumoku/builders/raw_undirected_tree.rb +37 -0
- data/lib/jumoku/builders/{raw_tree.rb → shared.rb} +38 -63
- data/lib/jumoku/builders/tree.rb +5 -330
- data/lib/jumoku/classes/tree_classes.rb +6 -4
- data/lib/jumoku/ext/ext.rb +8 -2
- data/lib/jumoku/raw_tree_node.rb +5 -5
- data/lib/jumoku/support/branch.rb +9 -1
- data/lib/jumoku/support/support.rb +6 -13
- data/lib/jumoku/tree_api.rb +7 -7
- data/lib/jumoku/version.rb +2 -2
- data/spec/{raw_tree_spec.rb → raw_undirected_tree_spec.rb} +48 -86
- data/spec/tree_spec.rb +36 -48
- metadata +8 -4
@@ -1,7 +1,9 @@
|
|
1
1
|
module Jumoku
|
2
|
-
#
|
3
|
-
class
|
2
|
+
# "Raw" implementations.
|
3
|
+
class RawUndirectedTree; include RawUndirectedTreeBuilder; end
|
4
|
+
class RawDirectedTree; include RawDirectedTreeBuilder; end
|
4
5
|
|
5
|
-
#
|
6
|
-
class Tree;
|
6
|
+
# "Useful" implementations.
|
7
|
+
class Tree; include TreeBuilder; end
|
8
|
+
class Arborescence; include ArborescenceBuilder; end
|
7
9
|
end
|
data/lib/jumoku/ext/ext.rb
CHANGED
@@ -42,9 +42,15 @@ class Array
|
|
42
42
|
self.create_pairs.flatten(1)
|
43
43
|
end
|
44
44
|
|
45
|
-
|
45
|
+
# Create a list of branches object based on an expandable array of nodes.
|
46
|
+
#
|
47
|
+
# TODO: refacto, it's painful having to pass the branch_type
|
48
|
+
#
|
49
|
+
# @param [DirectedBranch, UndirectedBranch] branch_type
|
50
|
+
#
|
51
|
+
def create_branches_list(branch_type)
|
46
52
|
branches = []
|
47
|
-
self.expand_branches!.each_by(2) { |pair| branches <<
|
53
|
+
self.expand_branches!.each_by(2) { |pair| branches << branch_type.new(pair[0], pair[1]) }
|
48
54
|
branches
|
49
55
|
end
|
50
56
|
end
|
data/lib/jumoku/raw_tree_node.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
module Jumoku
|
2
2
|
module RawTree
|
3
|
-
|
4
|
-
#
|
3
|
+
# This module describes RawTree nodes.
|
4
|
+
#
|
5
|
+
# You may also use this module as a mixin to have a class behave
|
6
|
+
# as a RawTree node, while customizing behaviors.
|
5
7
|
#
|
6
|
-
# You can include it in a class of your own to make it act
|
7
|
-
# as a raw tree node, while customizing behaviors.
|
8
8
|
module Node
|
9
|
-
|
10
9
|
# Creates a new node.
|
11
10
|
#
|
12
11
|
# @param [#to_s, #to_sym] name a valid name, considering the :names_as options
|
@@ -15,6 +14,7 @@ module Jumoku
|
|
15
14
|
# @param [Array(#to_s)] children an array of children nodes ids
|
16
15
|
#
|
17
16
|
# @return [OpenObject] the node as an OpenObject instance
|
17
|
+
#
|
18
18
|
def create name, data = OpenObject.new, children = []
|
19
19
|
@name = name
|
20
20
|
@data = data
|
@@ -1,15 +1,8 @@
|
|
1
1
|
module Jumoku
|
2
|
-
|
3
|
-
class
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
class RawTreeError < JumokuError; end
|
9
|
-
# Error related to nodes.
|
10
|
-
|
11
|
-
class RawTreeNodeError < RawTreeError; end
|
12
|
-
# Raised if one attempts to add an already existing branch to a tree.
|
13
|
-
|
14
|
-
class BranchAlreadyExistError < JumokuError; end
|
2
|
+
class JumokuError < StandardError; end
|
3
|
+
class RawTreeError < JumokuError; end
|
4
|
+
class RawTreeNodeError < RawTreeError; end
|
5
|
+
class BranchAlreadyExistError < JumokuError; end
|
6
|
+
class ForbiddenCycle < JumokuError; end
|
7
|
+
class UndefinedNode < JumokuError; end
|
15
8
|
end
|
data/lib/jumoku/tree_api.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Jumoku
|
2
|
-
# This module defines the minimum set of
|
3
|
-
# use the algorithms defined
|
2
|
+
# This module defines the minimum set of methods required to build a tree
|
3
|
+
# which can use the algorithms defined in this library.
|
4
4
|
#
|
5
|
-
#
|
5
|
+
# A module based abiding to the TreeAPI must implement the following routines:
|
6
6
|
#
|
7
7
|
# * add_node!(n, l = nil) — adds a node to the tree and return the tree; l is an optional label (see Plexus library).
|
8
8
|
# * add_branch!(i, j = nil, l = nil) — adds a branch to the tree and return the tree. i can be a {Branch}, or (i,j) a node pair; l is an optional label.
|
@@ -11,17 +11,17 @@ module Jumoku
|
|
11
11
|
# * nodes — returns an array of all nodes.
|
12
12
|
# * terminal_nodes — returns an array of all terminal nodes.
|
13
13
|
# * branches — returns an array of all branches.
|
14
|
+
#
|
14
15
|
module TreeAPI
|
15
|
-
|
16
|
-
#
|
16
|
+
# @raise [JumokuError] if the API is not completely implemented
|
17
|
+
#
|
17
18
|
def self.included(klass)
|
18
19
|
@api_methods ||= [:add_node!, :add_branch!, :remove_node!, :remove_branch!, :nodes, :terminal_nodes, :branches]
|
19
20
|
ruby_18 { @api_methods.each { |m| m.to_s } }
|
20
21
|
|
21
22
|
@api_methods.each do |meth|
|
22
|
-
raise "Must implement #{meth}" unless klass.instance_methods.include?(meth)
|
23
|
+
raise JumokuError, "Must implement #{meth}" unless klass.instance_methods.include?(meth)
|
23
24
|
end
|
24
25
|
end
|
25
|
-
|
26
26
|
end
|
27
27
|
end
|
data/lib/jumoku/version.rb
CHANGED
@@ -1,21 +1,8 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
# The RawTree builder implements TreeAPI and ensures the tree
|
4
|
-
# is a valid tree as far as Graph Theory is concerned:
|
5
|
-
# a tree is an undirected, connected, acyclic graph.
|
6
|
-
#
|
7
|
-
# Note: these tests may make use of the "root"/"children" terminology.
|
8
|
-
# Be aware this has got *no* structural meaning as a tree is, by
|
9
|
-
# definition, undirected. Those terms are used only to simplify
|
10
|
-
# nodes creation within the tests, so I recall who branched who.
|
11
|
-
# For tests about rooted tree, see arborescence_spec.rb
|
12
|
-
describe "RawTreeBuilder" do
|
13
|
-
before :each do
|
14
|
-
#class MyTree
|
15
|
-
#include RawTreeBuilder
|
16
|
-
#end
|
1
|
+
require 'spec_helper'
|
17
2
|
|
18
|
-
|
3
|
+
describe RawUndirectedTree do
|
4
|
+
before :each do
|
5
|
+
@tree = RawUndirectedTree.new
|
19
6
|
end
|
20
7
|
|
21
8
|
describe "#new" do
|
@@ -23,8 +10,8 @@ describe "RawTreeBuilder" do
|
|
23
10
|
@tree.should_not be_directed
|
24
11
|
@tree.should be_acyclic
|
25
12
|
@tree.should be_connected
|
26
|
-
# aka @tree.should be_valid,
|
27
|
-
|
13
|
+
# aka @tree.should be_valid, which we will use further on
|
14
|
+
@tree.should be_valid
|
28
15
|
@tree.nodes.should be_empty
|
29
16
|
end
|
30
17
|
end
|
@@ -36,7 +23,7 @@ describe "RawTreeBuilder" do
|
|
36
23
|
it "should grow up as a valid tree when adding its first node" do
|
37
24
|
@tree.nodes.size.should == 0
|
38
25
|
|
39
|
-
@tree.add_node! "root"
|
26
|
+
@tree.add_node! "root" # adding a raw string as the first node
|
40
27
|
@tree.nodes.size.should == 1
|
41
28
|
@tree.nodes.should == ["root"]
|
42
29
|
end
|
@@ -44,33 +31,34 @@ describe "RawTreeBuilder" do
|
|
44
31
|
|
45
32
|
describe "a tree with only one node" do
|
46
33
|
before :each do
|
47
|
-
|
34
|
+
# remember, this 'root' thing retain no particular meaning, it's just a raw string
|
35
|
+
# and I could have written "Joe" instead
|
36
|
+
@tree.add_node! "root"
|
48
37
|
end
|
49
38
|
|
50
|
-
it "should raise an error when trying to add a new
|
39
|
+
it "should raise an error when trying to add a new, disconnected node" do
|
40
|
+
# again, I'll use childX for the sake of this specs, as it is easy to
|
41
|
+
# remember, but the node is not really a "child" of the previous node,
|
42
|
+
# it is just connected
|
51
43
|
lambda { @tree.add_node! "child1" }.should raise_error
|
52
44
|
end
|
53
45
|
|
54
|
-
it "should grow up as a valid tree when adding new
|
46
|
+
it "should grow up as a valid tree when adding new, connected nodes" do
|
55
47
|
lambda { @tree.add_node! "child1", "root" }.should_not raise_error
|
56
48
|
|
57
49
|
@tree.add_node! "child2", "root"
|
58
50
|
@tree.add_node! "grand-child1", "child2"
|
59
|
-
@tree.add_node! Jumoku::
|
51
|
+
@tree.add_node! Jumoku::UndirectedBranch.new("grand-child2", "child2")
|
60
52
|
|
61
53
|
@tree.nodes.size.should == 5
|
62
|
-
|
63
|
-
the_nodes = ["root", "child1", "child2", "grand-child1", "grand-child2"]
|
64
|
-
@tree.nodes.should == the_nodes
|
65
|
-
@tree.topsort.should_not == the_nodes
|
54
|
+
@tree.nodes.should == ["root", "child1", "child2", "grand-child1", "grand-child2"]
|
66
55
|
|
67
56
|
@tree.add_node! "grand-grand-child1", "grand-child1"
|
68
57
|
@tree.add_node! "child3", "root"
|
69
58
|
@tree.add_node! "grand-child3", "child3"
|
70
59
|
@tree.add_node! "grand-grand-grand-child", "grand-grand-child1"
|
71
|
-
|
72
|
-
@tree.should
|
73
|
-
@tree.should be_connected
|
60
|
+
|
61
|
+
@tree.should be_valid
|
74
62
|
end
|
75
63
|
|
76
64
|
it "should raise an error when trying to form a cycle" do
|
@@ -78,34 +66,35 @@ describe "RawTreeBuilder" do
|
|
78
66
|
@tree.add_node! "child2", "root"
|
79
67
|
@tree.add_node! "grand-child", "child1"
|
80
68
|
|
81
|
-
lambda { @tree.add_node! "grand-child", "child2" }.should raise_error
|
69
|
+
lambda { @tree.add_node! "grand-child", "child2" }.should raise_error ForbiddenCycle
|
82
70
|
|
83
71
|
@tree.add_node! "grand-grand-child", "grand-child"
|
84
|
-
|
85
|
-
lambda { @tree.add_node! "grand-grand-child", "
|
72
|
+
|
73
|
+
lambda { @tree.add_node! "grand-grand-child", "child1" }.should raise_error ForbiddenCycle
|
74
|
+
lambda { @tree.add_node! "grand-grand-child", "child2" }.should raise_error ForbiddenCycle
|
86
75
|
end
|
87
76
|
end
|
88
77
|
end
|
89
78
|
|
90
79
|
describe "#add_branch!" do
|
91
80
|
describe "an empty tree" do
|
92
|
-
it "should
|
93
|
-
|
94
|
-
@tree.nodes.should == [:first, :branch]
|
81
|
+
it "should create a branch and return the updated tree" do
|
82
|
+
@tree.add_branch!(:one, :two).should be_a RawUndirectedTree
|
95
83
|
@tree.should be_valid
|
84
|
+
@tree.nodes.should == [:one, :two]
|
96
85
|
end
|
97
86
|
end
|
98
87
|
|
99
|
-
describe "a tree
|
88
|
+
describe "a tree containing a single node" do
|
100
89
|
before :each do
|
101
90
|
@tree.add_node! 1
|
102
91
|
end
|
103
92
|
|
104
|
-
it "should not allow
|
93
|
+
it "should not allow disconnected branch creation" do
|
105
94
|
lambda { @tree.add_branch! 10, 11 }.should raise_error RawTreeError
|
106
95
|
end
|
107
96
|
|
108
|
-
it "should grow up as a valid tree when populated with
|
97
|
+
it "should grow up as a valid tree when populated with connected branches" do
|
109
98
|
@tree.nodes.size.should == 1
|
110
99
|
|
111
100
|
@tree.add_branch! 1, 2
|
@@ -119,7 +108,8 @@ describe "RawTreeBuilder" do
|
|
119
108
|
|
120
109
|
@tree.add_branch! 3, 4
|
121
110
|
@tree.add_branch! 2, 5
|
122
|
-
lambda { @tree.add_branch! 5, 5 }.should raise_error
|
111
|
+
lambda { @tree.add_branch! 5, 5 }.should raise_error ForbiddenCycle
|
112
|
+
lambda { @tree.add_branch! 1, 5 }.should raise_error ForbiddenCycle
|
123
113
|
@tree.add_branch! 4, 3
|
124
114
|
@tree.add_branch! 5, 6
|
125
115
|
@tree.nodes.size.should == 6
|
@@ -132,11 +122,11 @@ describe "RawTreeBuilder" do
|
|
132
122
|
describe "#remove_node!" do
|
133
123
|
describe "an empty tree" do
|
134
124
|
it "should not allow to remove a node since there's none" do
|
135
|
-
lambda { @tree.remove_node! "
|
125
|
+
lambda { @tree.remove_node! "undefinedNode" }.should raise_error UndefinedNode
|
136
126
|
end
|
137
127
|
end
|
138
128
|
|
139
|
-
describe "a tree
|
129
|
+
describe "a tree containing a single node" do
|
140
130
|
before :each do
|
141
131
|
@tree.add_node! :last
|
142
132
|
end
|
@@ -148,12 +138,12 @@ describe "RawTreeBuilder" do
|
|
148
138
|
end
|
149
139
|
end
|
150
140
|
|
151
|
-
describe "a tree
|
141
|
+
describe "a tree containing one branch" do
|
152
142
|
before :each do
|
153
|
-
@tree1 =
|
143
|
+
@tree1 = RawUndirectedTree.new
|
154
144
|
@tree1.add_node! 1
|
155
145
|
@tree1.add_node! 2, 1
|
156
|
-
@tree2 =
|
146
|
+
@tree2 = RawUndirectedTree.new
|
157
147
|
@tree2.add_node! 1
|
158
148
|
@tree2.add_node! 2, 1
|
159
149
|
end
|
@@ -171,7 +161,7 @@ describe "RawTreeBuilder" do
|
|
171
161
|
end
|
172
162
|
end
|
173
163
|
|
174
|
-
describe "a tree
|
164
|
+
describe "a tree containing several branches" do
|
175
165
|
before :each do
|
176
166
|
# TODO: DRY this snippet
|
177
167
|
# i stands for internal, t for terminal
|
@@ -189,7 +179,7 @@ describe "RawTreeBuilder" do
|
|
189
179
|
lambda { @tree.remove_node! :t8 }.should_not raise_error
|
190
180
|
@tree.nodes.size.should == 7
|
191
181
|
@tree.nodes.should_not include :t8
|
192
|
-
lambda { @tree.remove_node! :i3 }.should raise_error
|
182
|
+
lambda { @tree.remove_node! :i3 }.should raise_error UndefinedNode
|
193
183
|
@tree.should be_valid
|
194
184
|
end
|
195
185
|
|
@@ -208,7 +198,7 @@ describe "RawTreeBuilder" do
|
|
208
198
|
end
|
209
199
|
end
|
210
200
|
|
211
|
-
describe "an tree
|
201
|
+
describe "an tree containing one node" do
|
212
202
|
before :each do
|
213
203
|
@tree.add_node! 1
|
214
204
|
end
|
@@ -218,7 +208,7 @@ describe "RawTreeBuilder" do
|
|
218
208
|
end
|
219
209
|
end
|
220
210
|
|
221
|
-
describe "a tree
|
211
|
+
describe "a tree containing several branches" do
|
222
212
|
before :each do
|
223
213
|
# TODO: DRY this snippet
|
224
214
|
# i stands for internal, t for terminal
|
@@ -240,7 +230,7 @@ describe "RawTreeBuilder" do
|
|
240
230
|
@tree.has_branch?(:i1, :t8).should be_false
|
241
231
|
@tree.should be_valid
|
242
232
|
|
243
|
-
@tree.remove_branch!
|
233
|
+
@tree.remove_branch! UndirectedBranch.new(:i5, :t7)
|
244
234
|
@tree.has_branch?(:i5, :t7).should be_false
|
245
235
|
@tree.should be_valid
|
246
236
|
end
|
@@ -254,8 +244,8 @@ describe "RawTreeBuilder" do
|
|
254
244
|
end
|
255
245
|
end
|
256
246
|
|
257
|
-
describe "a tree
|
258
|
-
it "should be aware of its
|
247
|
+
describe "a tree containing several nodes" do
|
248
|
+
it "should be aware of its nodes" do
|
259
249
|
@tree.add_node! :solo
|
260
250
|
@tree.nodes.should == [:solo]
|
261
251
|
|
@@ -274,14 +264,14 @@ describe "RawTreeBuilder" do
|
|
274
264
|
end
|
275
265
|
end
|
276
266
|
|
277
|
-
describe "a tree
|
267
|
+
describe "a tree containing one node" do
|
278
268
|
it "should have one terminal node" do
|
279
269
|
@tree.add_node! 1
|
280
270
|
@tree.terminal_nodes.should == [1]
|
281
271
|
end
|
282
272
|
end
|
283
273
|
|
284
|
-
describe "a
|
274
|
+
describe "a tree with several branches" do
|
285
275
|
before :each do
|
286
276
|
@tree.add_node! 1
|
287
277
|
@tree.add_node! 2, 1
|
@@ -305,49 +295,21 @@ describe "RawTreeBuilder" do
|
|
305
295
|
end
|
306
296
|
end
|
307
297
|
|
308
|
-
describe "a tree
|
298
|
+
describe "a tree containing one node" do
|
309
299
|
it "should not have any branch" do
|
310
300
|
@tree.add_node! :solo
|
311
301
|
@tree.branches.should be_empty
|
312
302
|
end
|
313
303
|
end
|
314
304
|
|
315
|
-
describe "a tree
|
305
|
+
describe "a tree containing one branch" do
|
316
306
|
it "should have one branch only (undirected)" do
|
317
307
|
@tree.add_node! :one
|
318
308
|
@tree.add_node! :two, :one
|
319
309
|
@tree.branches.size.should == 1
|
320
|
-
@tree.branches.first.class.should == Plexus::Edge
|
321
|
-
# a lazy wrapper of it
|
322
|
-
@tree.should be_valid
|
323
|
-
end
|
324
|
-
end
|
325
|
-
|
326
|
-
describe "a tree with n nodes" do
|
327
|
-
before :each do
|
328
|
-
# TODO: DRY this as random_tree(n = 10)
|
329
|
-
@n = rand(50) # number of nodes
|
330
|
-
@tree.add_node! @n
|
331
|
-
@old_node = @n
|
332
|
-
|
333
|
-
(@n - 1).times do
|
334
|
-
begin
|
335
|
-
@new_node = rand(100)
|
336
|
-
@tree.add_node!(@new_node, @old_node)
|
337
|
-
rescue RawTreeError
|
338
|
-
retry # cycle detected!
|
339
|
-
end
|
340
|
-
@old_node = @new_node
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
it "should have n - 1 branches" do
|
345
|
-
@tree.nodes.size.should == @n
|
346
|
-
@tree.branches.size.should == @n - 1
|
310
|
+
@tree.branches.first.class.should == Plexus::Edge
|
347
311
|
@tree.should be_valid
|
348
312
|
end
|
349
313
|
end
|
350
314
|
end
|
351
|
-
|
352
|
-
# TODO: add a final test which sums it up
|
353
315
|
end
|
data/spec/tree_spec.rb
CHANGED
@@ -1,20 +1,8 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
# The Tree builder extends the core functionalities provided
|
4
|
-
# by RawTreeBuilder.
|
5
|
-
#
|
6
|
-
# Note: these tests may make use of the "root"/"children" terminology.
|
7
|
-
# Be aware this has got *no* structural meaning as a tree is, by
|
8
|
-
# definition, undirected. Those terms are used only to simplify
|
9
|
-
# nodes creation within the tests, so I recall who branched who.
|
10
|
-
# For tests about rooted tree, see arborescence_spec.rb
|
11
|
-
describe "TreeBuilder" do
|
12
|
-
before :each do
|
13
|
-
class MyTree
|
14
|
-
include TreeBuilder
|
15
|
-
end
|
1
|
+
require 'spec_helper'
|
16
2
|
|
17
|
-
|
3
|
+
describe Tree do
|
4
|
+
before :each do
|
5
|
+
@tree = Tree.new
|
18
6
|
end
|
19
7
|
|
20
8
|
describe "#new" do
|
@@ -24,15 +12,15 @@ describe "TreeBuilder" do
|
|
24
12
|
end
|
25
13
|
end
|
26
14
|
|
27
|
-
##
|
28
|
-
## The following tests focus on
|
15
|
+
## The core TreeAPI is tested in raw_tree_spec.rb.
|
16
|
+
## The following tests focus on methods added by TreeBuilder.
|
29
17
|
|
30
18
|
describe "#add_node" do
|
31
19
|
describe "an empty tree" do
|
32
20
|
it "should create a new, valid tree with a single node when its first node is added" do
|
33
21
|
@tree.add_node 1
|
34
|
-
@tree.should be_empty
|
35
|
-
|
22
|
+
@tree.should be_empty # the original tree is not modified
|
23
|
+
# a brand new tree is created instead, extending the original one
|
36
24
|
new_tree = @tree.add_node 1
|
37
25
|
new_tree.nodes.should == [1]
|
38
26
|
new_tree.should be_valid
|
@@ -70,7 +58,7 @@ describe "TreeBuilder" do
|
|
70
58
|
end
|
71
59
|
end
|
72
60
|
|
73
|
-
describe "a
|
61
|
+
describe "a populated tree" do
|
74
62
|
before :each do
|
75
63
|
@tree.add_branch! 1, 2
|
76
64
|
@tree.add_branch! 2, 3
|
@@ -97,7 +85,7 @@ describe "TreeBuilder" do
|
|
97
85
|
end
|
98
86
|
end
|
99
87
|
|
100
|
-
describe "a tree
|
88
|
+
describe "a tree containing one node" do
|
101
89
|
before :each do
|
102
90
|
@tree.add_node! 1
|
103
91
|
end
|
@@ -154,11 +142,11 @@ describe "TreeBuilder" do
|
|
154
142
|
@tree.nodes.should == [1, 2, 3, 4]
|
155
143
|
@tree.should be_valid
|
156
144
|
|
157
|
-
@tree.add_nodes!
|
145
|
+
@tree.add_nodes! UndirectedBranch.new(5, 2)
|
158
146
|
@tree.nodes.should == [1, 2, 3, 4, 5]
|
159
147
|
@tree.should be_valid
|
160
148
|
|
161
|
-
@tree.add_nodes! 3,4, 1,10,
|
149
|
+
@tree.add_nodes! 3,4, 1,10, UndirectedBranch.new(10, 11), -1,1
|
162
150
|
@tree.nodes.size.should == 8
|
163
151
|
@tree.should be_valid
|
164
152
|
|
@@ -181,12 +169,12 @@ describe "TreeBuilder" do
|
|
181
169
|
new_tree.nodes.should == [1, 2, 3, 4]
|
182
170
|
new_tree.should be_valid
|
183
171
|
|
184
|
-
new_tree = @tree.add_nodes
|
172
|
+
new_tree = @tree.add_nodes UndirectedBranch.new(4, 5)
|
185
173
|
@tree.should be_empty
|
186
174
|
new_tree.nodes.should == [4, 5]
|
187
175
|
new_tree.should be_valid
|
188
176
|
|
189
|
-
new_tree = @tree.add_nodes 3,4, 4,10,
|
177
|
+
new_tree = @tree.add_nodes 3,4, 4,10, UndirectedBranch.new(10, 11), -1,3
|
190
178
|
@tree.should be_empty
|
191
179
|
new_tree.nodes.size.should == 5
|
192
180
|
new_tree.should be_valid
|
@@ -204,11 +192,11 @@ describe "TreeBuilder" do
|
|
204
192
|
describe "#add_branches!" do
|
205
193
|
describe "an empty tree" do
|
206
194
|
it "should allow for adding its first branches" do
|
207
|
-
@tree.add_branches!
|
195
|
+
@tree.add_branches! UndirectedBranch.new(1, 2), 1,3, 3,4
|
208
196
|
@tree.nodes.should == [1, 2, 3, 4]
|
209
197
|
@tree.should be_valid
|
210
198
|
|
211
|
-
branch =
|
199
|
+
branch = UndirectedBranch.new(1, 4)
|
212
200
|
lambda { @tree.add_branches! branch }.should raise_error, RawTreeError
|
213
201
|
end
|
214
202
|
end
|
@@ -223,11 +211,11 @@ describe "TreeBuilder" do
|
|
223
211
|
@tree.nodes.should == [1, 2, 3]
|
224
212
|
@tree.should be_valid
|
225
213
|
|
226
|
-
@tree.add_branches!
|
214
|
+
@tree.add_branches! UndirectedBranch.new(0,1), 3,4, UndirectedBranch.new(4,5)
|
227
215
|
[0..5].all? { |n| @tree.nodes.include? n } and @tree.nodes.size.should == 5
|
228
216
|
@tree.should be_valid
|
229
217
|
|
230
|
-
lambda { @tree.add_branches!
|
218
|
+
lambda { @tree.add_branches! UndirectedBranch.new(2, 5) }.should raise_error, RawTreeError
|
231
219
|
end
|
232
220
|
end
|
233
221
|
end
|
@@ -235,7 +223,7 @@ describe "TreeBuilder" do
|
|
235
223
|
describe "add_branches" do
|
236
224
|
describe "an empty tree" do
|
237
225
|
it "should create a new, valid tree populated with its first branches" do
|
238
|
-
b1, b2, b3 =
|
226
|
+
b1, b2, b3 = UndirectedBranch.new(1, 2), UndirectedBranch.new(2, 3), UndirectedBranch.new(3, 4)
|
239
227
|
new_tree = @tree.add_branches b1, b2, b3
|
240
228
|
@tree.should be_empty
|
241
229
|
new_tree.nodes.should == [1, 2, 3, 4]
|
@@ -251,13 +239,13 @@ describe "TreeBuilder" do
|
|
251
239
|
end
|
252
240
|
|
253
241
|
it "should create a new, valid tree extended with its new branches" do
|
254
|
-
new_tree = @tree.add_branches 4, :five,
|
242
|
+
new_tree = @tree.add_branches 4, :five, UndirectedBranch.new(:five, "six")
|
255
243
|
@tree.nodes.should == (1..4).to_a
|
256
244
|
new_tree.nodes.should == [1, 2, 3, 4, :five, "six"]
|
257
245
|
new_tree.should be_valid
|
258
246
|
|
259
247
|
lambda { @tree.add_branches 10, 11 }.should raise_error, RawTreeError
|
260
|
-
lambda { @tree.add_branches
|
248
|
+
lambda { @tree.add_branches UndirectedBranch.new 1,4 }.should raise_error, RawTreeError
|
261
249
|
end
|
262
250
|
end
|
263
251
|
end
|
@@ -324,7 +312,7 @@ describe "TreeBuilder" do
|
|
324
312
|
describe "#remove_branches!" do
|
325
313
|
describe "an empty tree" do
|
326
314
|
it "should not allow for removing branches" do
|
327
|
-
lambda { @tree.remove_branches
|
315
|
+
lambda { @tree.remove_branches UndirectedBranch.new(:foo, :bar), 1,2 }.should raise_error, RawTreeError
|
328
316
|
end
|
329
317
|
end
|
330
318
|
|
@@ -344,11 +332,11 @@ describe "TreeBuilder" do
|
|
344
332
|
end
|
345
333
|
|
346
334
|
it "should allow for removing branches until it has no more branches or a sole node" do
|
347
|
-
@tree.remove_branches! 1,2,
|
335
|
+
@tree.remove_branches! 1,2, UndirectedBranch.new(2,3), 3,4
|
348
336
|
@tree.should be_empty
|
349
337
|
@tree.should be_valid
|
350
338
|
|
351
|
-
lambda { @tree.remove_branches!
|
339
|
+
lambda { @tree.remove_branches! UndirectedBranch.new(:foo, :bar), UndirectedBranch.new(1, 2) }.should raise_error, RawTreeError
|
352
340
|
end
|
353
341
|
end
|
354
342
|
end
|
@@ -356,7 +344,7 @@ describe "TreeBuilder" do
|
|
356
344
|
describe "#remove_branches" do
|
357
345
|
describe "an empty tree" do
|
358
346
|
it "should not allow for removing branches" do
|
359
|
-
lambda { @tree.remove_branches :foo, :bar,
|
347
|
+
lambda { @tree.remove_branches :foo, :bar, UndirectedBranch.new(1, 2) }.should raise_error, RawTreeError
|
360
348
|
end
|
361
349
|
end
|
362
350
|
|
@@ -376,12 +364,12 @@ describe "TreeBuilder" do
|
|
376
364
|
end
|
377
365
|
|
378
366
|
it "should allow for removing branches until it has no more branches or a sole node, creating a new, valid tree" do
|
379
|
-
new_tree = @tree.remove_branches 1,2,
|
367
|
+
new_tree = @tree.remove_branches 1,2, UndirectedBranch.new(2,3), 3,4
|
380
368
|
@tree.nodes.should == [1, 2, 3, 4]
|
381
369
|
new_tree.should be_empty
|
382
370
|
new_tree.should be_valid
|
383
371
|
|
384
|
-
lambda { @tree.remove_branches
|
372
|
+
lambda { @tree.remove_branches UndirectedBranch.new(:foo, :bar), UndirectedBranch.new(1, 2) }.should raise_error, RawTreeError
|
385
373
|
end
|
386
374
|
end
|
387
375
|
end
|
@@ -527,12 +515,12 @@ describe "TreeBuilder" do
|
|
527
515
|
describe "#add_consecutive_nodes!" do
|
528
516
|
describe "a tree" do
|
529
517
|
it "should grow as a valid, populated tree if all specified nodes define a valid tree structure" do
|
530
|
-
@tree.add_consecutive_nodes!(1, 2, 3, :four,
|
531
|
-
@tree.has_branches?(1,2, 2,3,
|
532
|
-
@tree.has_branches?(1,2, 2,3,
|
533
|
-
@tree.has_branches_among?(1,2, 2,3,
|
534
|
-
@tree.has_branches_among?(1,2, 2,3,
|
535
|
-
@tree.has_branches_among?(1,2, 2,3,
|
518
|
+
@tree.add_consecutive_nodes!(1, 2, 3, :four, UndirectedBranch.new(:foo, "bar"))
|
519
|
+
@tree.has_branches?(1,2, 2,3, UndirectedBranch.new(3, :four), :four,:foo, :foo,"bar").should be_true # each specified branch exist
|
520
|
+
@tree.has_branches?(1,2, 2,3, UndirectedBranch.new(3, :four), :four,:foo).should be_true # each specified branch exist
|
521
|
+
@tree.has_branches_among?(1,2, 2,3, UndirectedBranch.new(3, :four), :four,:foo).should be_false # do not list every existing branch
|
522
|
+
@tree.has_branches_among?(1,2, 2,3, UndirectedBranch.new(3, :four), :four,:foo, :foo,"bar").should be_true # list all existing branches
|
523
|
+
@tree.has_branches_among?(1,2, 2,3, UndirectedBranch.new(3, :four), :four,:foo, :foo,"bar", Array.new, "NIL").should be_true # list all existing branches
|
536
524
|
@tree.should be_valid
|
537
525
|
end
|
538
526
|
end
|
@@ -541,10 +529,10 @@ describe "TreeBuilder" do
|
|
541
529
|
describe "#add_consecutive_nodes" do
|
542
530
|
describe "a tree" do
|
543
531
|
it "should create a new, valid, populated tree if all specified nodes define a valid tree structure" do
|
544
|
-
new_tree = @tree.add_consecutive_nodes(1, 2, 3, :four,
|
532
|
+
new_tree = @tree.add_consecutive_nodes(1, 2, 3, :four, UndirectedBranch.new(:foo, "bar"))
|
545
533
|
@tree.should be_empty
|
546
|
-
new_tree.has_branches?(1,2, 2,3,
|
547
|
-
new_tree.has_branches?(1,2, 2,3,
|
534
|
+
new_tree.has_branches?(1,2, 2,3, UndirectedBranch.new(3, :four), :four,:foo, :foo,"bar").should be_true
|
535
|
+
new_tree.has_branches?(1,2, 2,3, UndirectedBranch.new(3, :four), :four,:foo).should be_true
|
548
536
|
new_tree.should be_valid
|
549
537
|
end
|
550
538
|
end
|