jumoku 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +0 -1
- data/lib/jumoku.rb +2 -3
- data/lib/jumoku/builders/extended.rb +15 -23
- data/lib/jumoku/builders/raw_directed_tree.rb +15 -0
- data/lib/jumoku/builders/raw_undirected_tree.rb +15 -0
- data/lib/jumoku/builders/shared.rb +2 -5
- data/lib/jumoku/support/ruby_compatibility.rb +19 -0
- data/lib/jumoku/version.rb +1 -1
- data/spec/arborescence_spec.rb +14 -0
- data/spec/behaviors/core_tree.rb +281 -0
- data/spec/behaviors/extended.rb +530 -0
- data/spec/raw_directed_tree_spec.rb +14 -0
- data/spec/raw_undirected_tree_spec.rb +9 -310
- data/spec/spec_helper.rb +2 -0
- data/spec/tree_spec.rb +8 -535
- metadata +21 -86
- data/lib/jumoku/tree_api.rb +0 -27
- data/vendor/git/plexus/CREDITS.md +0 -31
- data/vendor/git/plexus/Gemfile +0 -3
- data/vendor/git/plexus/Gemfile.lock +0 -28
- data/vendor/git/plexus/LICENSE +0 -37
- data/vendor/git/plexus/README.md +0 -208
- data/vendor/git/plexus/Rakefile +0 -25
- data/vendor/git/plexus/TODO.md +0 -20
- data/vendor/git/plexus/VERSION +0 -1
- data/vendor/git/plexus/examples/graph_self.rb +0 -56
- data/vendor/git/plexus/examples/module_graph.jpg +0 -0
- data/vendor/git/plexus/examples/module_graph.rb +0 -14
- data/vendor/git/plexus/examples/self_graph.jpg +0 -0
- data/vendor/git/plexus/examples/visualize.jpg +0 -0
- data/vendor/git/plexus/examples/visualize.rb +0 -10
- data/vendor/git/plexus/lib/plexus.rb +0 -90
- data/vendor/git/plexus/lib/plexus/adjacency_graph.rb +0 -224
- data/vendor/git/plexus/lib/plexus/arc.rb +0 -59
- data/vendor/git/plexus/lib/plexus/arc_number.rb +0 -52
- data/vendor/git/plexus/lib/plexus/biconnected.rb +0 -84
- data/vendor/git/plexus/lib/plexus/chinese_postman.rb +0 -91
- data/vendor/git/plexus/lib/plexus/classes/graph_classes.rb +0 -28
- data/vendor/git/plexus/lib/plexus/common.rb +0 -63
- data/vendor/git/plexus/lib/plexus/comparability.rb +0 -63
- data/vendor/git/plexus/lib/plexus/directed_graph.rb +0 -78
- data/vendor/git/plexus/lib/plexus/directed_graph/algorithms.rb +0 -95
- data/vendor/git/plexus/lib/plexus/directed_graph/distance.rb +0 -167
- data/vendor/git/plexus/lib/plexus/dot.rb +0 -94
- data/vendor/git/plexus/lib/plexus/edge.rb +0 -36
- data/vendor/git/plexus/lib/plexus/ext.rb +0 -79
- data/vendor/git/plexus/lib/plexus/graph.rb +0 -626
- data/vendor/git/plexus/lib/plexus/graph_api.rb +0 -35
- data/vendor/git/plexus/lib/plexus/labels.rb +0 -113
- data/vendor/git/plexus/lib/plexus/maximum_flow.rb +0 -77
- data/vendor/git/plexus/lib/plexus/ruby_compatibility.rb +0 -17
- data/vendor/git/plexus/lib/plexus/search.rb +0 -510
- data/vendor/git/plexus/lib/plexus/strong_components.rb +0 -93
- data/vendor/git/plexus/lib/plexus/support/support.rb +0 -9
- data/vendor/git/plexus/lib/plexus/undirected_graph.rb +0 -56
- data/vendor/git/plexus/lib/plexus/undirected_graph/algorithms.rb +0 -90
- data/vendor/git/plexus/lib/plexus/version.rb +0 -6
- data/vendor/git/plexus/plexus.gemspec +0 -24
- data/vendor/git/plexus/spec/biconnected_spec.rb +0 -27
- data/vendor/git/plexus/spec/chinese_postman_spec.rb +0 -27
- data/vendor/git/plexus/spec/community_spec.rb +0 -44
- data/vendor/git/plexus/spec/complement_spec.rb +0 -27
- data/vendor/git/plexus/spec/digraph_distance_spec.rb +0 -121
- data/vendor/git/plexus/spec/digraph_spec.rb +0 -339
- data/vendor/git/plexus/spec/dot_spec.rb +0 -48
- data/vendor/git/plexus/spec/edge_spec.rb +0 -158
- data/vendor/git/plexus/spec/inspection_spec.rb +0 -38
- data/vendor/git/plexus/spec/multi_edge_spec.rb +0 -32
- data/vendor/git/plexus/spec/neighborhood_spec.rb +0 -36
- data/vendor/git/plexus/spec/properties_spec.rb +0 -146
- data/vendor/git/plexus/spec/search_spec.rb +0 -227
- data/vendor/git/plexus/spec/spec.opts +0 -4
- data/vendor/git/plexus/spec/spec_helper.rb +0 -59
- data/vendor/git/plexus/spec/strong_components_spec.rb +0 -61
- data/vendor/git/plexus/spec/triangulated_spec.rb +0 -125
- data/vendor/git/plexus/spec/undirected_graph_spec.rb +0 -220
- data/vendor/git/plexus/vendor/priority-queue/CHANGELOG +0 -33
- data/vendor/git/plexus/vendor/priority-queue/Makefile +0 -140
- data/vendor/git/plexus/vendor/priority-queue/README +0 -133
- data/vendor/git/plexus/vendor/priority-queue/benchmark/dijkstra.rb +0 -171
- data/vendor/git/plexus/vendor/priority-queue/compare_comments.rb +0 -49
- data/vendor/git/plexus/vendor/priority-queue/doc/c-vs-rb.png +0 -0
- data/vendor/git/plexus/vendor/priority-queue/doc/compare_big.gp +0 -14
- data/vendor/git/plexus/vendor/priority-queue/doc/compare_big.png +0 -0
- data/vendor/git/plexus/vendor/priority-queue/doc/compare_small.gp +0 -15
- data/vendor/git/plexus/vendor/priority-queue/doc/compare_small.png +0 -0
- data/vendor/git/plexus/vendor/priority-queue/doc/results.csv +0 -37
- data/vendor/git/plexus/vendor/priority-queue/ext/priority_queue/CPriorityQueue/extconf.rb +0 -2
- data/vendor/git/plexus/vendor/priority-queue/ext/priority_queue/CPriorityQueue/priority_queue.c +0 -947
- data/vendor/git/plexus/vendor/priority-queue/lib/priority_queue.rb +0 -14
- data/vendor/git/plexus/vendor/priority-queue/lib/priority_queue/c_priority_queue.rb +0 -1
- data/vendor/git/plexus/vendor/priority-queue/lib/priority_queue/poor_priority_queue.rb +0 -46
- data/vendor/git/plexus/vendor/priority-queue/lib/priority_queue/ruby_priority_queue.rb +0 -526
- data/vendor/git/plexus/vendor/priority-queue/priority_queue.so +0 -0
- data/vendor/git/plexus/vendor/priority-queue/setup.rb +0 -1551
- data/vendor/git/plexus/vendor/priority-queue/test/priority_queue_test.rb +0 -371
- data/vendor/git/plexus/vendor/rdot.rb +0 -360
data/Gemfile
CHANGED
data/lib/jumoku.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
libpath = File.expand_path(File.dirname(__FILE__))
|
2
2
|
$:.unshift File.dirname(__FILE__) unless $:.include?(File.dirname(__FILE__)) || $:.include?(libpath)
|
3
|
-
$: << libpath + '/../vendor/git/plexus/lib'
|
4
3
|
|
5
4
|
require 'pathname'
|
6
5
|
require 'pp'
|
@@ -24,8 +23,7 @@ require 'plexus'
|
|
24
23
|
# (from the Facets library), both turning nodes into versatile handlers.
|
25
24
|
#
|
26
25
|
module Jumoku
|
27
|
-
#
|
28
|
-
autoload :TreeAPI, 'jumoku/tree_api'
|
26
|
+
# core implementations
|
29
27
|
autoload :Shared, 'jumoku/builders/shared'
|
30
28
|
autoload :Extended, 'jumoku/builders/extended'
|
31
29
|
|
@@ -46,6 +44,7 @@ module Jumoku
|
|
46
44
|
autoload :Arborescence, 'jumoku/classes/tree_classes'
|
47
45
|
|
48
46
|
# support
|
47
|
+
require 'jumoku/support/ruby_compatibility'
|
49
48
|
require 'jumoku/support/support'
|
50
49
|
require 'jumoku/ext/ext'
|
51
50
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Jumoku
|
2
|
-
# This module provides methods extending the core
|
2
|
+
# This module provides methods extending the core implementation. Most of those
|
3
3
|
# methods are cloning the receiver tree and perform their operation on the
|
4
4
|
# duplicated object. Some other are helpers adding reflexivity to trees.
|
5
5
|
# There are also a few in-place methods.
|
@@ -163,11 +163,16 @@ module Jumoku
|
|
163
163
|
#
|
164
164
|
# The process relies on {RawTreeBuilder#remove_node! remove_node!}.
|
165
165
|
#
|
166
|
-
# @param [#each] *
|
166
|
+
# @param [#each] *nodes an Enumerable nodes set; may contain Range
|
167
167
|
# @return [Tree] `self`
|
168
168
|
#
|
169
|
-
|
170
|
-
|
169
|
+
# @example
|
170
|
+
#
|
171
|
+
# remove_nodes! 1, 3..5
|
172
|
+
#
|
173
|
+
def remove_nodes!(*nodes)
|
174
|
+
nodes = nodes.to_a.map { |i| i.is_a?(Range) ? i.to_a : i }.flatten
|
175
|
+
nodes.each { |v| remove_node! v }
|
171
176
|
self
|
172
177
|
end
|
173
178
|
alias delete_nodes! remove_nodes!
|
@@ -265,18 +270,11 @@ module Jumoku
|
|
265
270
|
# @return [Boolean]
|
266
271
|
#
|
267
272
|
def branches?(*maybe_branches)
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
# Branch objects are really Edge objects within Plexus, therefore
|
272
|
-
# cannot rely on #eql? to compare those structures and must drop
|
273
|
-
# down to the attributes.
|
274
|
-
list.each do |e| # Jumoku::Branch structs
|
275
|
-
all = branches.any? do |b| # Plexus::Edge structs
|
276
|
-
(b[:source] == e[:source]) and (b[:target] == e[:target])
|
273
|
+
maybe_branches.create_branches_list(_branch_type).all? do |maybe_branch|
|
274
|
+
branches.any? do |branch|
|
275
|
+
maybe_branch == branch
|
277
276
|
end
|
278
277
|
end
|
279
|
-
all
|
280
278
|
end
|
281
279
|
alias has_branches? branches?
|
282
280
|
|
@@ -292,17 +290,11 @@ module Jumoku
|
|
292
290
|
#
|
293
291
|
def branches_among?(*maybe_branches)
|
294
292
|
list = maybe_branches.create_branches_list(_branch_type)
|
295
|
-
all
|
296
|
-
|
297
|
-
|
298
|
-
# cannot rely on #eql? to compare those structures and must drop
|
299
|
-
# down to the attributes.
|
300
|
-
branches.each do |e| # Plexus::Edge structs
|
301
|
-
all = list.any? do |b| # Jumoku::Branch structs
|
302
|
-
(b[:source] == e[:source]) and (b[:target] == e[:target])
|
293
|
+
branches.all? do |branch|
|
294
|
+
list.any? do |maybe_branch|
|
295
|
+
branch == maybe_branch
|
303
296
|
end
|
304
297
|
end
|
305
|
-
all
|
306
298
|
end
|
307
299
|
alias has_branches_among? branches_among?
|
308
300
|
|
@@ -22,6 +22,21 @@ module Jumoku
|
|
22
22
|
#
|
23
23
|
def initialize(*params)
|
24
24
|
super(*params) # Delegates to Plexus.
|
25
|
+
class << self; self; end.module_eval do
|
26
|
+
alias has_branch? has_arc?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Checks whether the tree is *really* a valid tree, that is if the
|
31
|
+
# following conditions are fulfilled:
|
32
|
+
#
|
33
|
+
# * directed
|
34
|
+
# * acyclic
|
35
|
+
# * connected
|
36
|
+
#
|
37
|
+
# @return [Boolean]
|
38
|
+
def valid?
|
39
|
+
super and directed?
|
25
40
|
end
|
26
41
|
|
27
42
|
private
|
@@ -26,6 +26,21 @@ module Jumoku
|
|
26
26
|
#
|
27
27
|
def initialize(*params)
|
28
28
|
super(*params) # Delegates to Plexus.
|
29
|
+
class << self; self; end.module_eval do
|
30
|
+
alias has_branch? has_edge?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Checks whether the tree is *really* a valid tree, that is if the
|
35
|
+
# following conditions are fulfilled:
|
36
|
+
#
|
37
|
+
# * undirected
|
38
|
+
# * acyclic
|
39
|
+
# * connected
|
40
|
+
#
|
41
|
+
# @return [Boolean]
|
42
|
+
def valid?
|
43
|
+
super && !directed?
|
29
44
|
end
|
30
45
|
|
31
46
|
private
|
@@ -1,15 +1,12 @@
|
|
1
1
|
module Jumoku
|
2
2
|
# This module provides the basic routines needed to implement the specialized
|
3
|
-
# builders: {UndirectedTreeBuilder} and {DirectedTreeBuilder}.
|
4
|
-
# implementations are under the control of the {TreeAPI}.
|
3
|
+
# builders: {UndirectedTreeBuilder} and {DirectedTreeBuilder}.
|
5
4
|
#
|
6
5
|
module Shared
|
7
6
|
def self.included(base)
|
8
7
|
base.class_eval do
|
9
8
|
# Late aliasing as it references methods provided by Plexus modules.
|
10
9
|
alias has_node? has_vertex?
|
11
|
-
alias has_branch? has_edge?
|
12
|
-
include TreeAPI
|
13
10
|
end
|
14
11
|
end
|
15
12
|
|
@@ -176,7 +173,7 @@ module Jumoku
|
|
176
173
|
#
|
177
174
|
# @return [Boolean]
|
178
175
|
def valid?
|
179
|
-
acyclic? and connected?
|
176
|
+
acyclic? and connected?
|
180
177
|
end
|
181
178
|
|
182
179
|
# Is the node a terminal node?
|
data/lib/jumoku/version.rb
CHANGED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Arborescence do
|
4
|
+
subject { Arborescence.new }
|
5
|
+
let(:tree) { subject }
|
6
|
+
let(:tree_type) { subject.class }
|
7
|
+
let(:branch_type) { subject.send :_branch_type }
|
8
|
+
|
9
|
+
it_should_behave_like "a legacy tree"
|
10
|
+
it "should be a directed graph" do
|
11
|
+
tree.class.ancestors.should include RawDirectedTreeBuilder
|
12
|
+
end
|
13
|
+
it_should_behave_like "a tree with extended features"
|
14
|
+
end
|
@@ -0,0 +1,281 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples_for "a legacy tree" do
|
4
|
+
describe "#new" do
|
5
|
+
it "should create a valid tree graph" do
|
6
|
+
tree.should be_valid
|
7
|
+
tree.nodes.should be_empty
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#add_node!" do
|
12
|
+
describe "an empty tree" do
|
13
|
+
it "should grow up as a valid tree when adding its first node" do
|
14
|
+
tree.nodes.size.should == 0
|
15
|
+
|
16
|
+
tree.add_node! 1 # adding a raw string as the first node
|
17
|
+
tree.nodes.size.should == 1
|
18
|
+
tree.nodes.should == [1]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "a tree with only one node" do
|
23
|
+
before :each do
|
24
|
+
tree.add_node! 1
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should raise an error when trying to add a new, disconnected node" do
|
28
|
+
# again, I'll use childX for the sake of this specs, as it is easy to
|
29
|
+
# remember, but the node is not really a "child" of the previous node,
|
30
|
+
# it is just connected
|
31
|
+
lambda { tree.add_node! 2 }.should raise_error
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should grow up as a valid tree when adding new, connected nodes" do
|
35
|
+
lambda { tree.add_node! 2, 1 }.should_not raise_error
|
36
|
+
|
37
|
+
tree.add_node! 3, 1
|
38
|
+
tree.add_node! 1, 4
|
39
|
+
tree.add_node! branch_type.new(3, 5)
|
40
|
+
|
41
|
+
tree.should be_valid
|
42
|
+
tree.nodes.size.should == 5
|
43
|
+
tree.nodes.sort.should == [1,2,3,4,5]
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should raise an error when trying to form a cycle" do
|
47
|
+
tree.add_node! 2, 1
|
48
|
+
tree.add_node! 3, 1
|
49
|
+
tree.add_node! 4, 2
|
50
|
+
|
51
|
+
lambda { tree.add_node! 4, 1 }.should raise_error ForbiddenCycle
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#add_branch!" do
|
57
|
+
describe "an empty tree" do
|
58
|
+
it "should create a branch and return the updated tree" do
|
59
|
+
tree.add_branch!(:one, :two).should be_a tree_type
|
60
|
+
tree.should be_valid
|
61
|
+
tree.nodes.should == [:one, :two]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "a tree containing a single node" do
|
66
|
+
before :each do
|
67
|
+
tree.add_node! 1
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should not allow disconnected branch creation" do
|
71
|
+
lambda { tree.add_branch! 10, 11 }.should raise_error RawTreeError
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should grow up as a valid tree when populated with connected branches" do
|
75
|
+
tree.nodes.size.should == 1
|
76
|
+
|
77
|
+
tree.add_branch! 1, 2
|
78
|
+
tree.nodes.should_not be_empty
|
79
|
+
tree.nodes.size.should == 2
|
80
|
+
tree.nodes.sort.should == [1, 2]
|
81
|
+
|
82
|
+
tree.add_branch! 2, 3
|
83
|
+
tree.nodes.size.should == 3
|
84
|
+
tree.nodes.sort.should == [1, 2, 3]
|
85
|
+
|
86
|
+
tree.add_branch! 3, 4
|
87
|
+
tree.add_branch! 2, 5
|
88
|
+
lambda { tree.add_branch! 5, 5 }.should raise_error ForbiddenCycle
|
89
|
+
lambda { tree.add_branch! 1, 5 }.should raise_error ForbiddenCycle
|
90
|
+
tree.add_branch! 5, 6
|
91
|
+
tree.nodes.size.should == 6
|
92
|
+
tree.nodes.sort.should == [1, 2, 3, 4, 5, 6]
|
93
|
+
tree.should be_valid
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "#remove_node!" do
|
99
|
+
describe "an empty tree" do
|
100
|
+
it "should not allow to remove a node since there's none" do
|
101
|
+
lambda { tree.remove_node! "undefinedNode" }.should raise_error UndefinedNode
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "a tree containing a single node" do
|
106
|
+
before :each do
|
107
|
+
tree.add_node! :last
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should allow for last node deletion" do
|
111
|
+
lambda { tree.remove_node! :last }.should_not raise_error
|
112
|
+
tree.nodes.should be_empty
|
113
|
+
tree.should be_valid
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "a tree containing one branch" do
|
118
|
+
before :each do
|
119
|
+
tree.add_node! 1
|
120
|
+
tree.add_node! 2, 1
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should allow to remove both nodes in any order" do
|
124
|
+
tree.remove_node! 1
|
125
|
+
tree.should be_valid
|
126
|
+
tree.nodes.sort.should == [2]
|
127
|
+
tree.should be_valid
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "a tree containing several branches" do
|
132
|
+
before :each do
|
133
|
+
# TODO: DRY this snippet
|
134
|
+
# i stands for internal, t for terminal
|
135
|
+
tree.add_branch! :i1, :i2
|
136
|
+
tree.add_branch! :i2, :i3
|
137
|
+
tree.add_branch! :i3, :i4
|
138
|
+
tree.add_branch! :i3, :i5
|
139
|
+
tree.add_branch! :i4, :t6
|
140
|
+
tree.add_branch! :i5, :t7
|
141
|
+
tree.add_branch! :i1, :t8
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should allow deletion of its terminal nodes but not of its internal nodes" do
|
145
|
+
tree.nodes.size.should == 8
|
146
|
+
lambda { tree.remove_node! :t8 }.should_not raise_error
|
147
|
+
tree.nodes.size.should == 7
|
148
|
+
tree.nodes.should_not include :t8
|
149
|
+
lambda { tree.remove_node! :i3 }.should raise_error UndefinedNode
|
150
|
+
tree.should be_valid
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should remain a valid tree after any terminal node was removed" do
|
154
|
+
tree.remove_node! :t6
|
155
|
+
tree.has_branch?(:i4, :t6).should_not be_true
|
156
|
+
tree.should be_valid
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "#remove_branch!" do
|
162
|
+
describe "an empty tree" do
|
163
|
+
it "should not allow for branch deletion" do
|
164
|
+
lambda { tree.remove_branch! :null, :none }.should raise_error RawTreeError
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "an tree containing one node" do
|
169
|
+
before :each do
|
170
|
+
tree.add_node! 1
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should not allow for branch deletion" do
|
174
|
+
lambda { tree.remove_branch! 1, :none }.should raise_error RawTreeError
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe "a tree containing several branches" do
|
179
|
+
before :each do
|
180
|
+
# TODO: DRY this snippet
|
181
|
+
# i stands for internal, t for terminal
|
182
|
+
tree.add_branch! :i1, :i2
|
183
|
+
tree.add_branch! :i2, :i3
|
184
|
+
tree.add_branch! :i3, :i4
|
185
|
+
tree.add_branch! :i3, :i5
|
186
|
+
tree.add_branch! :i4, :t6
|
187
|
+
tree.add_branch! :i5, :t7
|
188
|
+
tree.add_branch! :i1, :t8
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should allow for terminal branch deletion (triggers terminal node deletion)" do
|
192
|
+
tree.nodes.size.should == 8
|
193
|
+
lambda { tree.remove_branch! :i1, :i2 }.should raise_error RawTreeError
|
194
|
+
tree.nodes.size.should == 8
|
195
|
+
lambda { tree.remove_branch! :i1, :t8 }.should_not raise_error RawTreeError
|
196
|
+
tree.nodes.should_not include :t8
|
197
|
+
tree.has_branch?(:i1, :t8).should be_false
|
198
|
+
tree.should be_valid
|
199
|
+
|
200
|
+
tree.remove_branch! branch_type.new(:i5, :t7)
|
201
|
+
tree.has_branch?(:i5, :t7).should be_false
|
202
|
+
tree.should be_valid
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
describe "#nodes" do
|
208
|
+
describe "an empty tree" do
|
209
|
+
it "should not have any node" do
|
210
|
+
tree.nodes.should be_empty
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
describe "a tree containing several nodes" do
|
215
|
+
it "should be aware of its nodes" do
|
216
|
+
tree.add_node! :solo
|
217
|
+
tree.nodes.should == [:solo]
|
218
|
+
|
219
|
+
tree.add_branch! 2, :solo
|
220
|
+
tree.add_branch! 2, 3
|
221
|
+
tree.nodes.should == [:solo, 2, 3]
|
222
|
+
tree.should be_valid
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
describe "#terminal_nodes" do
|
228
|
+
describe "an empty tree" do
|
229
|
+
it "should have no terminal nodes" do
|
230
|
+
tree.terminal_nodes.should be_empty
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
describe "a tree containing one node" do
|
235
|
+
it "should have one terminal node" do
|
236
|
+
tree.add_node! 1
|
237
|
+
tree.terminal_nodes.should == [1]
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
describe "a tree with several branches" do
|
242
|
+
before :each do
|
243
|
+
tree.add_node! 1
|
244
|
+
tree.add_node! 2, 1
|
245
|
+
tree.add_node! 3, 2
|
246
|
+
end
|
247
|
+
|
248
|
+
it "should have a least two terminal nodes" do
|
249
|
+
tree.terminal_nodes.size.should >= 2
|
250
|
+
|
251
|
+
tree.add_node! 4, 3
|
252
|
+
tree.add_node! 5, 3
|
253
|
+
tree.terminal_nodes.sort.should == [1, 4, 5]
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
describe "#branches" do
|
259
|
+
describe "an empty tree" do
|
260
|
+
it "should not have any branch" do
|
261
|
+
tree.branches.should be_empty
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
describe "a tree containing one node" do
|
266
|
+
it "should not have any branch" do
|
267
|
+
tree.add_node! :solo
|
268
|
+
tree.branches.should be_empty
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
describe "a tree containing one branch" do
|
273
|
+
it "should have one branch only" do
|
274
|
+
tree.add_node! :one
|
275
|
+
tree.add_node! :two, :one
|
276
|
+
tree.branches.size.should == 1
|
277
|
+
tree.should be_valid
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|