jumoku 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/README.md +12 -12
- data/lib/jumoku.rb +2 -2
- data/lib/jumoku/builders/raw_tree.rb +4 -4
- data/lib/jumoku/builders/tree.rb +5 -5
- data/lib/jumoku/support/branch.rb +1 -1
- data/lib/jumoku/tree_api.rb +1 -1
- data/lib/jumoku/version.rb +1 -1
- data/spec/raw_tree_spec.rb +1 -1
- data/vendor/git/{graphy → plexus}/CREDITS.md +0 -0
- data/vendor/git/plexus/Gemfile +3 -0
- data/vendor/git/plexus/Gemfile.lock +28 -0
- data/vendor/git/{graphy → plexus}/LICENSE +3 -1
- data/vendor/git/plexus/README.md +208 -0
- data/vendor/git/plexus/Rakefile +25 -0
- data/vendor/git/{graphy → plexus}/TODO.md +1 -1
- data/vendor/git/{graphy → plexus}/VERSION +0 -0
- data/vendor/git/{graphy → plexus}/examples/graph_self.rb +0 -0
- data/vendor/git/{graphy → plexus}/examples/module_graph.jpg +0 -0
- data/vendor/git/{graphy → plexus}/examples/module_graph.rb +0 -0
- data/vendor/git/{graphy → plexus}/examples/self_graph.jpg +0 -0
- data/vendor/git/{graphy → plexus}/examples/visualize.jpg +0 -0
- data/vendor/git/{graphy → plexus}/examples/visualize.rb +0 -0
- data/vendor/git/plexus/lib/plexus.rb +90 -0
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/adjacency_graph.rb +9 -9
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/arc.rb +16 -22
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/arc_number.rb +2 -2
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/biconnected.rb +2 -2
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/chinese_postman.rb +2 -2
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/classes/graph_classes.rb +10 -10
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/common.rb +6 -6
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/comparability.rb +10 -10
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/directed_graph.rb +15 -13
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/directed_graph/algorithms.rb +21 -18
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/directed_graph/distance.rb +2 -2
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/dot.rb +2 -2
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/edge.rb +8 -9
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/ext.rb +3 -3
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/graph.rb +51 -56
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/graph_api.rb +2 -2
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/labels.rb +8 -8
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/maximum_flow.rb +2 -2
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/ruby_compatibility.rb +0 -0
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/search.rb +43 -44
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/strong_components.rb +4 -4
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/support/support.rb +3 -3
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/undirected_graph.rb +13 -14
- data/vendor/git/{graphy/lib/graphy → plexus/lib/plexus}/undirected_graph/algorithms.rb +4 -4
- data/vendor/git/plexus/lib/plexus/version.rb +6 -0
- data/vendor/git/plexus/plexus.gemspec +24 -0
- data/vendor/git/{graphy → plexus}/spec/biconnected_spec.rb +0 -0
- data/vendor/git/{graphy → plexus}/spec/chinese_postman_spec.rb +0 -0
- data/vendor/git/{graphy → plexus}/spec/community_spec.rb +0 -0
- data/vendor/git/{graphy → plexus}/spec/complement_spec.rb +0 -0
- data/vendor/git/{graphy → plexus}/spec/digraph_distance_spec.rb +0 -0
- data/vendor/git/{graphy → plexus}/spec/digraph_spec.rb +0 -0
- data/vendor/git/{graphy → plexus}/spec/dot_spec.rb +0 -0
- data/vendor/git/{graphy → plexus}/spec/edge_spec.rb +17 -18
- data/vendor/git/{graphy → plexus}/spec/inspection_spec.rb +13 -15
- data/vendor/git/{graphy → plexus}/spec/multi_edge_spec.rb +0 -0
- data/vendor/git/{graphy → plexus}/spec/neighborhood_spec.rb +3 -5
- data/vendor/git/{graphy → plexus}/spec/properties_spec.rb +1 -1
- data/vendor/git/{graphy → plexus}/spec/search_spec.rb +45 -45
- data/vendor/git/{graphy → plexus}/spec/spec.opts +0 -0
- data/vendor/git/{graphy → plexus}/spec/spec_helper.rb +13 -10
- data/vendor/git/{graphy → plexus}/spec/strong_components_spec.rb +0 -0
- data/vendor/git/{graphy → plexus}/spec/triangulated_spec.rb +1 -1
- data/vendor/git/{graphy → plexus}/spec/undirected_graph_spec.rb +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/CHANGELOG +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/Makefile +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/README +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/benchmark/dijkstra.rb +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/compare_comments.rb +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/doc/c-vs-rb.png +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/doc/compare_big.gp +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/doc/compare_big.png +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/doc/compare_small.gp +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/doc/compare_small.png +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/doc/results.csv +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/ext/priority_queue/CPriorityQueue/extconf.rb +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/ext/priority_queue/CPriorityQueue/priority_queue.c +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/lib/priority_queue.rb +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/lib/priority_queue/c_priority_queue.rb +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/lib/priority_queue/poor_priority_queue.rb +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/lib/priority_queue/ruby_priority_queue.rb +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/priority_queue.so +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/setup.rb +0 -0
- data/vendor/git/{graphy → plexus}/vendor/priority-queue/test/priority_queue_test.rb +0 -0
- data/vendor/git/{graphy → plexus}/vendor/rdot.rb +0 -0
- metadata +81 -78
- data/vendor/git/graphy/README.md +0 -186
- data/vendor/git/graphy/Rakefile +0 -61
- data/vendor/git/graphy/graphy.gemspec +0 -149
- data/vendor/git/graphy/lib/graphy.rb +0 -90
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module Plexus
|
2
2
|
# This module defines the minimum set of functions required to make a graph that can
|
3
3
|
# use the algorithms defined by this library.
|
4
4
|
#
|
@@ -32,4 +32,4 @@ module Graphy
|
|
32
32
|
end
|
33
33
|
|
34
34
|
end # GraphAPI
|
35
|
-
end #
|
35
|
+
end # Plexus
|
@@ -1,26 +1,26 @@
|
|
1
|
-
module
|
1
|
+
module Plexus
|
2
2
|
# This module add support for labels.
|
3
3
|
#
|
4
4
|
# The graph labeling process consist in assigning labels, traditionally represented
|
5
|
-
# by integers, to the edges or vertices, or both, of a graph.
|
5
|
+
# by integers, to the edges or vertices, or both, of a graph. Plexus recommands you
|
6
6
|
# abide by this rule and do use integers as labels.
|
7
7
|
#
|
8
|
-
# Some algorithms can make use of labeling (sea {
|
8
|
+
# Some algorithms can make use of labeling (sea {Plexus::Search} for instance).
|
9
9
|
module Labels
|
10
10
|
|
11
11
|
# Return a label for an edge or vertex.
|
12
12
|
def [](u)
|
13
|
-
(u.is_a?
|
13
|
+
(u.is_a? Plexus::Arc) ? edge_label(u) : vertex_label(u)
|
14
14
|
end
|
15
15
|
|
16
16
|
# Set a label for an edge or vertex.
|
17
17
|
def []=(u, value)
|
18
|
-
(u.is_a?
|
18
|
+
(u.is_a? Plexus::Arc) ? edge_label_set(u, value) : vertex_label_set(u, value)
|
19
19
|
end
|
20
20
|
|
21
21
|
# Delete a label entirely.
|
22
22
|
def delete_label(u)
|
23
|
-
(u.is_a?
|
23
|
+
(u.is_a? Plexus::Arc) ? edge_label_delete(u) : vertex_label_delete(u)
|
24
24
|
end
|
25
25
|
|
26
26
|
# Get the label for an edge.
|
@@ -42,7 +42,7 @@ module Graphy
|
|
42
42
|
|
43
43
|
# Set the label for an edge.
|
44
44
|
def edge_label_set(u, v = nil, l = nil, n = nil)
|
45
|
-
u.is_a?(
|
45
|
+
u.is_a?(Plexus::Arc) ? l = v : u = edge_convert(u, v, n)
|
46
46
|
edge_label_dict[u] = l
|
47
47
|
self
|
48
48
|
end
|
@@ -110,4 +110,4 @@ module Graphy
|
|
110
110
|
end
|
111
111
|
|
112
112
|
end # Labels
|
113
|
-
end #
|
113
|
+
end # Plexus
|
File without changes
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module Plexus
|
2
2
|
# **Search/traversal algorithms.**
|
3
3
|
#
|
4
4
|
# This module defines a collection of search/traversal algorithms, in a unified API.
|
@@ -35,7 +35,7 @@ module Graphy
|
|
35
35
|
# te = Proc.new { |x| puts "Tree Arc #{x}" }
|
36
36
|
# be = Proc.new { |x| puts "Back Arc #{x}" }
|
37
37
|
# fe = Proc.new { |x| puts "Forward Arc #{x}" }
|
38
|
-
# Digraph[1,2, 2,3, 3,4].dfs({
|
38
|
+
# Digraph[1,2, 2,3, 3,4].dfs({
|
39
39
|
# :enter_vertex => ev,
|
40
40
|
# :exit_vertex => xv,
|
41
41
|
# :start_vertex => sv,
|
@@ -43,7 +43,7 @@ module Graphy
|
|
43
43
|
# :tree_edge => te,
|
44
44
|
# :back_edge => be,
|
45
45
|
# :forward_edge => fe })
|
46
|
-
#
|
46
|
+
#
|
47
47
|
# Which outputs:
|
48
48
|
#
|
49
49
|
# Start vertex 1
|
@@ -70,7 +70,7 @@ module Graphy
|
|
70
70
|
#
|
71
71
|
# @param [Hash] options
|
72
72
|
def bfs(options = {}, &block)
|
73
|
-
|
73
|
+
plexus_search_helper(:shift, options, &block)
|
74
74
|
end
|
75
75
|
alias :bread_first_search :bfs
|
76
76
|
|
@@ -78,7 +78,7 @@ module Graphy
|
|
78
78
|
#
|
79
79
|
# @param [Hash] options
|
80
80
|
def dfs(options = {}, &block)
|
81
|
-
|
81
|
+
plexus_search_helper(:pop, options, &block)
|
82
82
|
end
|
83
83
|
alias :depth_first_search :dfs
|
84
84
|
|
@@ -127,7 +127,7 @@ module Graphy
|
|
127
127
|
te = Proc.new { |e| predecessor[e.target] = e.source if correct_tree }
|
128
128
|
rv = Proc.new { |v| correct_tree = (v == start) }
|
129
129
|
send routine, :start => start, :tree_edge => te, :root_vertex => rv
|
130
|
-
predecessor
|
130
|
+
predecessor
|
131
131
|
end
|
132
132
|
|
133
133
|
# Returns a hash of predecessors for the depth-first search tree rooted at the given node.
|
@@ -164,12 +164,12 @@ module Graphy
|
|
164
164
|
@set = {}
|
165
165
|
@tail = @node.new(nil, nil, Array.new(values))
|
166
166
|
@tail.instance_eval { @hash = (@@cnt += 1) }
|
167
|
-
values.each { |a| @set[a] = @tail }
|
167
|
+
values.each { |a| @set[a] = @tail }
|
168
168
|
end
|
169
169
|
|
170
170
|
# Pops an entry with the maximum lexical value from the queue.
|
171
171
|
#
|
172
|
-
# @return [vertex]
|
172
|
+
# @return [vertex]
|
173
173
|
def pop
|
174
174
|
return nil unless @tail
|
175
175
|
value = @tail[:data].pop
|
@@ -179,7 +179,7 @@ module Graphy
|
|
179
179
|
end
|
180
180
|
|
181
181
|
# Increase the lexical value of the given values.
|
182
|
-
#
|
182
|
+
#
|
183
183
|
# @param [Array] vertices values
|
184
184
|
def add_lexeme(values)
|
185
185
|
fix = {}
|
@@ -188,7 +188,7 @@ module Graphy
|
|
188
188
|
sw = @set[w]
|
189
189
|
if fix[sw]
|
190
190
|
s_prime = sw[:back]
|
191
|
-
else
|
191
|
+
else
|
192
192
|
s_prime = @node.new(sw[:back], sw, [])
|
193
193
|
s_prime.instance_eval { @hash = (@@cnt += 1) }
|
194
194
|
@tail = s_prime if @tail == sw
|
@@ -206,7 +206,7 @@ module Graphy
|
|
206
206
|
e[:forward][:back] = e[:back] if e[:forward]
|
207
207
|
e[:back][:forward] = e[:forward] if e[:back]
|
208
208
|
end
|
209
|
-
end
|
209
|
+
end
|
210
210
|
|
211
211
|
end
|
212
212
|
|
@@ -214,7 +214,7 @@ module Graphy
|
|
214
214
|
#
|
215
215
|
# The usual queue of vertices is replaced by a queue of *unordered subsets*
|
216
216
|
# of the vertices, which is sometimes refined but never reordered.
|
217
|
-
#
|
217
|
+
#
|
218
218
|
# Originally developed by Rose, Tarjan, and Leuker, *Algorithmic
|
219
219
|
# aspects of vertex elimination on graphs*, SIAM J. Comput. 5, 266-283
|
220
220
|
# MR53 #12077
|
@@ -224,32 +224,32 @@ module Graphy
|
|
224
224
|
#
|
225
225
|
# @return [vertex]
|
226
226
|
def lexicograph_bfs(&block)
|
227
|
-
lex_q =
|
227
|
+
lex_q = Plexus::Search::LexicographicQueue.new(vertices)
|
228
228
|
result = []
|
229
|
-
num_vertices.times do
|
229
|
+
num_vertices.times do
|
230
230
|
v = lex_q.pop
|
231
231
|
result.unshift(v)
|
232
|
-
lex_q.add_lexeme(adjacent(v))
|
232
|
+
lex_q.add_lexeme(adjacent(v))
|
233
233
|
end
|
234
234
|
result.each { |r| block.call(r) } if block
|
235
235
|
result
|
236
236
|
end
|
237
237
|
|
238
238
|
# A* Heuristic best first search.
|
239
|
-
#
|
239
|
+
#
|
240
240
|
# `start` is the starting vertex for the search.
|
241
241
|
#
|
242
|
-
# `func` is a `Proc` that when passed a vertex returns the heuristic
|
242
|
+
# `func` is a `Proc` that when passed a vertex returns the heuristic
|
243
243
|
# weight of sending the path through that node. It must always
|
244
244
|
# be equal to or less than the true cost.
|
245
|
-
#
|
246
|
-
# `options` are mostly callbacks passed in as a hash, the default block is
|
245
|
+
#
|
246
|
+
# `options` are mostly callbacks passed in as a hash, the default block is
|
247
247
|
# `:discover_vertex` and the weight is assumed to be the label for the {Arc}.
|
248
248
|
# The following options are valid, anything else is ignored:
|
249
249
|
#
|
250
250
|
# * `:weight` => can be a `Proc`, or anything else is accessed using the `[]` for the
|
251
251
|
# the label or it defaults to using
|
252
|
-
# the value stored in the label for the {Arc}. If it is a `Proc` it will
|
252
|
+
# the value stored in the label for the {Arc}. If it is a `Proc` it will
|
253
253
|
# pass the edge to the proc and use the resulting value.
|
254
254
|
# * `:discover_vertex` => `Proc` invoked when a vertex is first discovered
|
255
255
|
# and is added to the open list.
|
@@ -259,12 +259,12 @@ module Graphy
|
|
259
259
|
# immediately after it is examined.
|
260
260
|
# * `:edge_relaxed` => `Proc` invoked on edge `(u,v) if d[u] + w(u,v) < d[v]`.
|
261
261
|
# * `:edge_not_relaxed`=> `Proc` invoked if the edge is not relaxed (see above).
|
262
|
-
# * `:black_target` => `Proc` invoked when a vertex that is on the closed
|
262
|
+
# * `:black_target` => `Proc` invoked when a vertex that is on the closed
|
263
263
|
# list is "rediscovered" via a more efficient path, and is re-added
|
264
264
|
# to the open list.
|
265
|
-
# * `:finish_vertex` => Proc invoked on a vertex when it is added to the
|
265
|
+
# * `:finish_vertex` => Proc invoked on a vertex when it is added to the
|
266
266
|
# closed list, which happens after all of its out edges have been
|
267
|
-
# examined.
|
267
|
+
# examined.
|
268
268
|
#
|
269
269
|
# Can also be called like `astar_examine_edge {|e| ... }` or
|
270
270
|
# `astar_edge_relaxed {|e| ... }` for any of the callbacks.
|
@@ -272,9 +272,9 @@ module Graphy
|
|
272
272
|
# The criteria for expanding a vertex on the open list is that it has the
|
273
273
|
# lowest `f(v) = g(v) + h(v)` value of all vertices on open.
|
274
274
|
#
|
275
|
-
# The time complexity of A* depends on the heuristic. It is exponential
|
275
|
+
# The time complexity of A* depends on the heuristic. It is exponential
|
276
276
|
# in the worst case, but is polynomial when the heuristic function h
|
277
|
-
# meets the following condition: `|h(x) - h*(x)| < O(log h*(x))` where `h*`
|
277
|
+
# meets the following condition: `|h(x) - h*(x)| < O(log h*(x))` where `h*`
|
278
278
|
# is the optimal heuristic, i.e. the exact cost to get from `x` to the `goal`.
|
279
279
|
#
|
280
280
|
# See also: [A* search algorithm](http://en.wikipedia.org/wiki/A*_search_algorithm) on Wikipedia.
|
@@ -317,7 +317,7 @@ module Graphy
|
|
317
317
|
w = cost(e, options[:weight])
|
318
318
|
raise ArgumentError unless w
|
319
319
|
|
320
|
-
if d[v].nil? or (w + d[u]) < d[v]
|
320
|
+
if d[v].nil? or (w + d[u]) < d[v]
|
321
321
|
options.handle_callback(:edge_relaxed, e)
|
322
322
|
d[v] = w + d[u]
|
323
323
|
f[v] = d[v] + func.call(v)
|
@@ -325,9 +325,9 @@ module Graphy
|
|
325
325
|
|
326
326
|
unless color[v] == :gray
|
327
327
|
options.handle_callback(:black_target, v) if color[v] == :black
|
328
|
-
color[v] = :gray
|
328
|
+
color[v] = :gray
|
329
329
|
options.handle_callback(:discover_vertex, v)
|
330
|
-
queue.push v, f[v]
|
330
|
+
queue.push v, f[v]
|
331
331
|
block.call(v) if block
|
332
332
|
end
|
333
333
|
else
|
@@ -354,12 +354,12 @@ module Graphy
|
|
354
354
|
# @return [Array(vertices), call, nil] an array of nodes in path, or calls block on all nodes,
|
355
355
|
# upon failure returns `nil`
|
356
356
|
def best_first(start, goal, options, zero = 0, &block)
|
357
|
-
func = Proc.new { |v| zero }
|
357
|
+
func = Proc.new { |v| zero }
|
358
358
|
astar(start, goal, func, options, &block)
|
359
359
|
end
|
360
360
|
|
361
361
|
# @private
|
362
|
-
alias_method :pre_search_method_missing, :method_missing
|
362
|
+
alias_method :pre_search_method_missing, :method_missing
|
363
363
|
def method_missing(sym, *args, &block)
|
364
364
|
m1 = /^dfs_(\w+)$/.match(sym.to_s)
|
365
365
|
dfs((args[0] || {}).merge({ m1.captures[0].to_sym => block })) if m1
|
@@ -375,7 +375,7 @@ module Graphy
|
|
375
375
|
# @param [Symbol] op the algorithm to be used te perform the search
|
376
376
|
# @param [Hash] options
|
377
377
|
# @return [Object] result
|
378
|
-
def
|
378
|
+
def plexus_search_helper(op, options = {}, &block)
|
379
379
|
return nil if size == 0
|
380
380
|
result = []
|
381
381
|
|
@@ -401,7 +401,7 @@ module Graphy
|
|
401
401
|
# Loop till the search iterator exhausts the waiting list.
|
402
402
|
visited_edges = {} # This prevents retraversing edges in undirected graphs.
|
403
403
|
until waiting.empty?
|
404
|
-
|
404
|
+
plexus_search_iteration(options, waiting, color_map, visited_edges, result, op == :pop)
|
405
405
|
end
|
406
406
|
# Waiting for the list to be exhausted, check if a new root vertex is available.
|
407
407
|
u = color_map.detect { |key,value| value == :unvisited }
|
@@ -415,10 +415,10 @@ module Graphy
|
|
415
415
|
# Performs a search iteration (step).
|
416
416
|
#
|
417
417
|
# @private
|
418
|
-
def
|
418
|
+
def plexus_search_iteration(options, waiting, color_map, visited_edges, result, recursive = false)
|
419
419
|
# Fetch the next waiting vertex in the list.
|
420
420
|
#sleep
|
421
|
-
u = waiting.next
|
421
|
+
u = waiting.next
|
422
422
|
options.handle_vertex(:enter_vertex, u)
|
423
423
|
result << u
|
424
424
|
|
@@ -432,15 +432,15 @@ module Graphy
|
|
432
432
|
|
433
433
|
case color_map[v]
|
434
434
|
# If it's unvisited, it goes into the waiting list.
|
435
|
-
when :unvisited
|
435
|
+
when :unvisited
|
436
436
|
options.handle_edge(:tree_edge, e)
|
437
437
|
color_map[v] = :waiting
|
438
|
-
waiting.push(v)
|
438
|
+
waiting.push(v)
|
439
439
|
# If it's recursive (i.e. dfs), then call self.
|
440
|
-
|
441
|
-
when :waiting
|
440
|
+
plexus_search_iteration(options, waiting, color_map, visited_edges, result, true) if recursive
|
441
|
+
when :waiting
|
442
442
|
options.handle_edge(:back_edge, e)
|
443
|
-
else
|
443
|
+
else
|
444
444
|
options.handle_edge(:forward_edge, e)
|
445
445
|
end
|
446
446
|
end
|
@@ -470,8 +470,8 @@ module Graphy
|
|
470
470
|
# @return [Array] a linear representation of the sorted graph
|
471
471
|
def topsort(start = nil, &block)
|
472
472
|
result = []
|
473
|
-
go = true
|
474
|
-
back = Proc.new { |e| go = false }
|
473
|
+
go = true
|
474
|
+
back = Proc.new { |e| go = false }
|
475
475
|
push = Proc.new { |v| result.unshift(v) if go }
|
476
476
|
start ||= vertices[0]
|
477
477
|
dfs({ :exit_vertex => push, :back_edge => back, :start => start })
|
@@ -506,6 +506,5 @@ module Graphy
|
|
506
506
|
def cyclic?
|
507
507
|
not acyclic?
|
508
508
|
end
|
509
|
-
|
510
|
-
|
511
|
-
end # Graphy
|
509
|
+
end
|
510
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module Plexus
|
2
2
|
module StrongComponents
|
3
3
|
# strong_components computes the strongly connected components
|
4
4
|
# of a graph using Tarjan's algorithm based on DFS. See: Robert E. Tarjan
|
@@ -68,7 +68,7 @@ module Graphy
|
|
68
68
|
# Compute transitive closure of a graph. That is any node that is reachable
|
69
69
|
# along a path is added as a directed edge.
|
70
70
|
def transitive_closure!
|
71
|
-
cgtc = condensation.
|
71
|
+
cgtc = condensation.plexus_inner_transitive_closure!
|
72
72
|
cgtc.each do |cgv|
|
73
73
|
cgtc.adjacent(cgv).each do |adj|
|
74
74
|
cgv.each do |u|
|
@@ -82,7 +82,7 @@ module Graphy
|
|
82
82
|
# is not changed.
|
83
83
|
def transitive_closure() self.class.new(self).transitive_closure!; end
|
84
84
|
|
85
|
-
def
|
85
|
+
def plexus_inner_transitive_closure! # :nodoc:
|
86
86
|
sort.reverse.each do |u|
|
87
87
|
adjacent(u).each do |v|
|
88
88
|
adjacent(v).each {|w| add_edge!(u,w) unless edge?(u,w)}
|
@@ -90,4 +90,4 @@ module Graphy
|
|
90
90
|
end; self
|
91
91
|
end
|
92
92
|
end # StrongComponents
|
93
|
-
end #
|
93
|
+
end # Plexus
|
@@ -1,9 +1,9 @@
|
|
1
|
-
module
|
1
|
+
module Plexus
|
2
2
|
# Errors
|
3
3
|
# TODO FIXME: must review all raise lines and streamline things
|
4
4
|
|
5
5
|
# Base error class for the library.
|
6
|
-
class
|
6
|
+
class PlexusError < StandardError; end
|
7
7
|
|
8
|
-
class NoArcError <
|
8
|
+
class NoArcError < PlexusError; end
|
9
9
|
end
|
@@ -1,11 +1,10 @@
|
|
1
|
-
module
|
2
|
-
|
1
|
+
module Plexus
|
3
2
|
module UndirectedGraphBuilder
|
3
|
+
autoload :Algorithms, "plexus/undirected_graph/algorithms"
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
include Graphy::GraphBuilder
|
5
|
+
include Plexus::GraphBuilder
|
8
6
|
extends_host
|
7
|
+
|
9
8
|
module ClassMethods
|
10
9
|
def [](*a)
|
11
10
|
self.new.from_array(*a)
|
@@ -14,16 +13,16 @@ module Graphy
|
|
14
13
|
|
15
14
|
def initialize(*params)
|
16
15
|
args = (params.pop if params.last.kind_of? Hash) || {}
|
17
|
-
args[:algorithmic_category] =
|
16
|
+
args[:algorithmic_category] = Plexus::UndirectedGraphBuilder::Algorithms
|
18
17
|
super *(params << args)
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
22
|
-
# This is a Digraph that allows for parallel edges, but does not
|
23
|
-
# allow loops
|
21
|
+
# This is a Digraph that allows for parallel edges, but does not allow loops.
|
24
22
|
module UndirectedPseudoGraphBuilder
|
25
23
|
include UndirectedGraphBuilder
|
26
24
|
extends_host
|
25
|
+
|
27
26
|
module ClassMethods
|
28
27
|
def [](*a)
|
29
28
|
self.new.from_array(*a)
|
@@ -34,13 +33,14 @@ module Graphy
|
|
34
33
|
args = (params.pop if params.last.kind_of? Hash) || {}
|
35
34
|
args[:parallel_edges] = true
|
36
35
|
super *(params << args)
|
37
|
-
end
|
36
|
+
end
|
38
37
|
end
|
39
38
|
|
40
|
-
# This is a Digraph that allows for parallel edges and loops
|
39
|
+
# This is a Digraph that allows for parallel edges and loops.
|
41
40
|
module UndirectedMultiGraphBuilder
|
42
|
-
UndirectedPseudoGraphBuilder
|
41
|
+
include UndirectedPseudoGraphBuilder
|
43
42
|
extends_host
|
43
|
+
|
44
44
|
module ClassMethods
|
45
45
|
def [](*a)
|
46
46
|
self.new.from_array(*a)
|
@@ -51,7 +51,6 @@ module Graphy
|
|
51
51
|
args = (params.pop if params.last.kind_of? Hash) || {}
|
52
52
|
args[:loops] = true
|
53
53
|
super *(params << args)
|
54
|
-
end
|
54
|
+
end
|
55
55
|
end
|
56
|
-
|
57
|
-
end # Graphy
|
56
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module Plexus
|
2
2
|
module UndirectedGraphBuilder
|
3
3
|
module Algorithms
|
4
4
|
|
@@ -16,10 +16,10 @@ module Graphy
|
|
16
16
|
def balanced?(v) true; end
|
17
17
|
|
18
18
|
# UndirectedGraph uses Edge for the edge class.
|
19
|
-
def edge_class() @parallel_edges ?
|
19
|
+
def edge_class() @parallel_edges ? Plexus::MultiEdge : Plexus::Edge; end
|
20
20
|
|
21
21
|
def remove_edge!(u, v=nil)
|
22
|
-
unless u.kind_of?
|
22
|
+
unless u.kind_of? Plexus::Arc
|
23
23
|
raise ArgumentError if @parallel_edges
|
24
24
|
u = edge_class[u,v]
|
25
25
|
end
|
@@ -87,4 +87,4 @@ module Graphy
|
|
87
87
|
|
88
88
|
end # UndirectedGraphAlgorithms
|
89
89
|
end # UndirectedGraphBuilder
|
90
|
-
end #
|
90
|
+
end # Plexus
|