rgl 0.5.9 → 0.5.10
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.
- checksums.yaml +4 -4
- data/ChangeLog +2 -2
- data/README.md +11 -11
- data/examples/canvas.rb +1 -1
- data/examples/graph.dot +971 -0
- data/examples/insel_der_tausend_gefahren.rb +1 -1
- data/examples/north/g.10.0.graphml +1 -1
- data/examples/north/g.10.1.graphml +1 -1
- data/examples/north/g.10.11.graphml +1 -1
- data/examples/north/g.10.12.graphml +1 -1
- data/examples/north/g.10.13.graphml +1 -1
- data/examples/north/g.10.14.graphml +1 -1
- data/examples/north/g.10.15.graphml +1 -1
- data/examples/north/g.10.16.graphml +1 -1
- data/examples/north/g.10.17.graphml +1 -1
- data/examples/north/g.10.19.graphml +1 -1
- data/examples/north/g.10.2.graphml +1 -1
- data/examples/north/g.10.20.graphml +1 -1
- data/examples/north/g.10.22.graphml +1 -1
- data/examples/north/g.10.24.graphml +1 -1
- data/examples/north/g.10.25.graphml +1 -1
- data/examples/north/g.10.27.graphml +1 -1
- data/examples/north/g.10.28.graphml +1 -1
- data/examples/north/g.10.29.graphml +1 -1
- data/examples/north/g.10.3.graphml +1 -1
- data/examples/north/g.10.30.graphml +1 -1
- data/examples/north/g.10.31.graphml +1 -1
- data/examples/north/g.10.34.graphml +1 -1
- data/examples/north/g.10.37.graphml +1 -1
- data/examples/north/g.10.38.graphml +1 -1
- data/examples/north/g.10.39.graphml +1 -1
- data/examples/north/g.10.4.graphml +1 -1
- data/examples/north/g.10.40.graphml +1 -1
- data/examples/north/g.10.41.graphml +1 -1
- data/examples/north/g.10.42.graphml +1 -1
- data/examples/north/g.10.45.graphml +1 -1
- data/examples/north/g.10.46.graphml +1 -1
- data/examples/north/g.10.5.graphml +1 -1
- data/examples/north/g.10.50.graphml +1 -1
- data/examples/north/g.10.56.graphml +1 -1
- data/examples/north/g.10.57.graphml +1 -1
- data/examples/north/g.10.58.graphml +1 -1
- data/examples/north/g.10.6.graphml +1 -1
- data/examples/north/g.10.60.graphml +1 -1
- data/examples/north/g.10.61.graphml +1 -1
- data/examples/north/g.10.62.graphml +1 -1
- data/examples/north/g.10.68.graphml +1 -1
- data/examples/north/g.10.69.graphml +1 -1
- data/examples/north/g.10.7.graphml +1 -1
- data/examples/north/g.10.70.graphml +1 -1
- data/examples/north/g.10.71.graphml +1 -1
- data/examples/north/g.10.72.graphml +1 -1
- data/examples/north/g.10.74.graphml +1 -1
- data/examples/north/g.10.75.graphml +1 -1
- data/examples/north/g.10.78.graphml +1 -1
- data/examples/north/g.10.79.graphml +1 -1
- data/examples/north/g.10.8.graphml +1 -1
- data/examples/north/g.10.80.graphml +1 -1
- data/examples/north/g.10.82.graphml +1 -1
- data/examples/north/g.10.83.graphml +1 -1
- data/examples/north/g.10.85.graphml +1 -1
- data/examples/north/g.10.86.graphml +1 -1
- data/examples/north/g.10.88.graphml +1 -1
- data/examples/north/g.10.89.graphml +1 -1
- data/examples/north/g.10.9.graphml +1 -1
- data/examples/north/g.10.90.graphml +1 -1
- data/examples/north/g.10.91.graphml +1 -1
- data/examples/north/g.10.92.graphml +1 -1
- data/examples/north/g.10.93.graphml +1 -1
- data/examples/north/g.10.94.graphml +1 -1
- data/examples/north/g.12.8.graphml +1 -1
- data/examples/north/g.14.9.graphml +1 -1
- data/examples/north.rb +1 -1
- data/examples/rdep-rgl.rb +3 -3
- data/lib/rgl/adjacency.rb +43 -51
- data/lib/rgl/base.rb +71 -60
- data/lib/rgl/bellman_ford.rb +4 -3
- data/lib/rgl/bidirectional.rb +2 -2
- data/lib/rgl/bipartite.rb +1 -1
- data/lib/rgl/condensation.rb +3 -3
- data/lib/rgl/connected_components.rb +6 -6
- data/lib/rgl/dot.rb +5 -7
- data/lib/rgl/edmonds_karp.rb +7 -2
- data/lib/rgl/graph_iterator.rb +4 -2
- data/lib/rgl/graph_visitor.rb +16 -14
- data/lib/rgl/graph_wrapper.rb +3 -2
- data/lib/rgl/graphxml.rb +4 -4
- data/lib/rgl/implicit.rb +35 -35
- data/lib/rgl/mutable.rb +7 -7
- data/lib/rgl/path_builder.rb +3 -2
- data/lib/rgl/prim.rb +3 -1
- data/lib/rgl/rdot.rb +7 -7
- data/lib/rgl/topsort.rb +8 -7
- data/lib/rgl/transitivity.rb +6 -6
- data/lib/rgl/traversal.rb +47 -47
- data/test/traversal_test.rb +1 -1
- metadata +4 -3
data/lib/rgl/dot.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
# dot.rb
|
2
2
|
#
|
3
|
-
# $Id$
|
4
|
-
#
|
5
3
|
# Minimal Dot support, based on Dave Thomas's dot module (included in rdoc).
|
6
4
|
# rdot.rb is a modified version which also contains support for undirected
|
7
5
|
# graphs.
|
8
6
|
#
|
9
|
-
# You need to have [GraphViz](
|
7
|
+
# You need to have [GraphViz](https://www.graphviz.org) installed, because the
|
10
8
|
# functions in this modul execute the GraphViz executables _dot_ or _dotty_.
|
11
9
|
|
12
10
|
require 'rgl/rdot'
|
@@ -24,8 +22,8 @@ module RGL
|
|
24
22
|
v
|
25
23
|
end
|
26
24
|
|
27
|
-
# Return a
|
28
|
-
# undirected Graph. _params_ can contain any graph property specified in
|
25
|
+
# Return a {DOT::Digraph} for directed graphs or a {DOT::Graph} for an
|
26
|
+
# undirected {Graph}. _params_ can contain any graph property specified in
|
29
27
|
# rdot.rb.
|
30
28
|
#
|
31
29
|
def to_dot_graph(params = {})
|
@@ -67,7 +65,7 @@ module RGL
|
|
67
65
|
s << to_dot_graph(params).to_s << "\n"
|
68
66
|
end
|
69
67
|
|
70
|
-
# Call dotty[
|
68
|
+
# Call dotty[https://www.graphviz.org] for the graph which is written to the
|
71
69
|
# file 'graph.dot' in the current directory.
|
72
70
|
#
|
73
71
|
def dotty(params = {})
|
@@ -80,7 +78,7 @@ module RGL
|
|
80
78
|
end
|
81
79
|
end
|
82
80
|
|
83
|
-
# Use dot[
|
81
|
+
# Use dot[https://www.graphviz.org] to create a graphical representation of
|
84
82
|
# the graph. Returns the filename of the graphics file.
|
85
83
|
#
|
86
84
|
def write_to_graphic_file(fmt='png', dotfile="graph", options={})
|
data/lib/rgl/edmonds_karp.rb
CHANGED
@@ -3,6 +3,9 @@ require 'rgl/traversal'
|
|
3
3
|
|
4
4
|
module RGL
|
5
5
|
|
6
|
+
# Implements {https://en.wikipedia.org/wiki/Edmonds%E2%80%93Karp_algorithm
|
7
|
+
# Edmonds–Karp algorithm}.
|
8
|
+
# @see Graph#maximum_flow
|
6
9
|
class EdmondsKarpAlgorithm
|
7
10
|
|
8
11
|
# Initializes Edmonds-Karp algorithm for a _graph_ with provided edges capacities map.
|
@@ -17,9 +20,10 @@ module RGL
|
|
17
20
|
|
18
21
|
# Finds the maximum flow from the _source_ to the _sink_ in the graph.
|
19
22
|
#
|
20
|
-
# Returns flows map as a hash that maps each edge of the graph to a flow
|
21
|
-
# the maximum total flow.
|
23
|
+
# Returns flows map as a hash that maps each edge of the graph to a flow
|
24
|
+
# through that edge that is required to reach the maximum total flow.
|
22
25
|
#
|
26
|
+
# @return [Hash]
|
23
27
|
def maximum_flow(source, sink)
|
24
28
|
raise ArgumentError.new("source and sink can't be equal") if source == sink
|
25
29
|
|
@@ -127,6 +131,7 @@ module RGL
|
|
127
131
|
# Raises ArgumentError if a reverse edge is missing, edge capacity is missing, an edge has negative capacity, or a
|
128
132
|
# reverse edge has positive capacity.
|
129
133
|
#
|
134
|
+
# @return [Hash]
|
130
135
|
def maximum_flow(edge_capacities_map, source, sink)
|
131
136
|
EdmondsKarpAlgorithm.new(self, edge_capacities_map).maximum_flow(source, sink)
|
132
137
|
end
|
data/lib/rgl/graph_iterator.rb
CHANGED
@@ -5,15 +5,17 @@ require 'rgl/graph_wrapper'
|
|
5
5
|
module RGL
|
6
6
|
|
7
7
|
# A GraphIterator is the abstract basis for all Iterators on graphs.
|
8
|
-
# Each graph iterator should implement the protocol defined in module
|
8
|
+
# Each graph iterator should implement the protocol defined in module
|
9
|
+
# {https://rubydoc.info/github/monora/stream Stream}.
|
9
10
|
#
|
10
11
|
module GraphIterator
|
11
12
|
include Stream
|
12
13
|
include GraphWrapper
|
13
14
|
|
15
|
+
# @return [int]
|
14
16
|
def length
|
15
17
|
inject(0) { |sum| sum + 1 }
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
19
|
-
end # RGL
|
21
|
+
end # RGL
|
data/lib/rgl/graph_visitor.rb
CHANGED
@@ -2,8 +2,8 @@ require 'rgl/graph_wrapper'
|
|
2
2
|
|
3
3
|
module RGL
|
4
4
|
|
5
|
-
# Module GraphVisitor defines the
|
6
|
-
#
|
5
|
+
# Module GraphVisitor defines the
|
6
|
+
# {https://www.boost.org/libs/graph/doc/visitor_concepts.html BGL Visitor Concepts}.
|
7
7
|
#
|
8
8
|
# Visitors provide a mechanism for extending an algorithm (i.e., for
|
9
9
|
# customizing what is done at each step of the algorithm). They allow users
|
@@ -12,7 +12,7 @@ module RGL
|
|
12
12
|
# Graph algorithms typically have multiple event points where one may want to
|
13
13
|
# insert a call-back. Therefore, visitors have several methods that
|
14
14
|
# correspond to the various event points. Each algorithm has a different
|
15
|
-
# set of event points. The following are common to both DFS and BFS search
|
15
|
+
# set of event points. The following are common to both DFS and BFS search:
|
16
16
|
#
|
17
17
|
# * examine_vertex
|
18
18
|
# * examine_edge
|
@@ -21,25 +21,26 @@ module RGL
|
|
21
21
|
# * forward_edge
|
22
22
|
# * finish_vertex
|
23
23
|
#
|
24
|
-
# These methods are all
|
25
|
-
# using the methods set_*_event_handler
|
24
|
+
# These methods are all named +handle_*+ and can be set to appropriate blocks,
|
25
|
+
# using the methods +set_*_event_handler+, which are defined for each event
|
26
26
|
# mentioned above.
|
27
27
|
#
|
28
|
-
# As an alternative, you can also override the handle_
|
28
|
+
# As an alternative, you can also override the +handle_*+ methods in a
|
29
29
|
# subclass, to configure the algorithm (as an example, see TarjanSccVisitor).
|
30
30
|
#
|
31
31
|
# During a graph traversal, vertices are *colored* using the colors :GRAY
|
32
32
|
# (when waiting) and :BLACK when finished. All other vertices are :WHITE.
|
33
|
-
# The color_map is also maintained in the visitor.
|
33
|
+
# The +color_map+ is also maintained in the visitor.
|
34
34
|
#
|
35
35
|
module GraphVisitor
|
36
36
|
|
37
37
|
include GraphWrapper
|
38
38
|
|
39
|
+
# @return [Hash] a map which store the colors for each vertex
|
39
40
|
attr_reader :color_map
|
40
41
|
|
41
42
|
# Create a new GraphVisitor on _graph_.
|
42
|
-
#
|
43
|
+
# @param [Graph] graph
|
43
44
|
def initialize(graph)
|
44
45
|
super(graph)
|
45
46
|
reset
|
@@ -59,7 +60,7 @@ module RGL
|
|
59
60
|
|
60
61
|
# Shall we follow the edge (u,v); i.e. v has color :WHITE
|
61
62
|
#
|
62
|
-
def follow_edge?(u, v)
|
63
|
+
def follow_edge?(u, v)
|
63
64
|
@color_map[v] == :WHITE
|
64
65
|
end
|
65
66
|
|
@@ -67,10 +68,10 @@ module RGL
|
|
67
68
|
# vertex to the start vertex.
|
68
69
|
#
|
69
70
|
# This is similar to BGLs
|
70
|
-
#
|
71
|
+
# {https://www.boost.org/libs/graph/doc/distance_recorder.html distance_recorder}.
|
71
72
|
#
|
72
|
-
# After the distance_map is attached, the visitor has a new method
|
73
|
-
# distance_to_root
|
73
|
+
# After the +distance_map+ is attached, the visitor has a new method
|
74
|
+
# +distance_to_root+, which answers the distance to the start vertex.
|
74
75
|
#
|
75
76
|
def attach_distance_map(map = Hash.new(0))
|
76
77
|
@distance_map = map
|
@@ -123,7 +124,8 @@ module RGL
|
|
123
124
|
extend ClassMethods # add class methods to GraphVisitor class itself
|
124
125
|
|
125
126
|
def self.included(base)
|
126
|
-
|
127
|
+
# when GraphVisitor is included into a class/module, add class methods as well
|
128
|
+
base.extend ClassMethods
|
127
129
|
end
|
128
130
|
|
129
131
|
def_event_handlers :examine_vertex,
|
@@ -135,4 +137,4 @@ module RGL
|
|
135
137
|
|
136
138
|
end # module GraphVisitor
|
137
139
|
|
138
|
-
end # module RGL
|
140
|
+
end # module RGL
|
data/lib/rgl/graph_wrapper.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
module RGL
|
2
2
|
|
3
|
-
module GraphWrapper
|
3
|
+
module GraphWrapper
|
4
4
|
|
5
|
+
# @return [Graph] the wrapped graph
|
5
6
|
attr_accessor :graph
|
6
7
|
|
7
8
|
# Creates a new GraphWrapper on _graph_.
|
@@ -12,4 +13,4 @@ module RGL
|
|
12
13
|
|
13
14
|
end # module GraphWrapper
|
14
15
|
|
15
|
-
end # RGL
|
16
|
+
end # RGL
|
data/lib/rgl/graphxml.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# graphxml.rb
|
2
2
|
#
|
3
3
|
# This file contains minimal support for creating RGL graphs from the GraphML
|
4
|
-
# format (see
|
4
|
+
# format (see https://graphml.graphdrawing.org/). The main purpose is to
|
5
5
|
# have a rich set of example graphs to have some more tests.
|
6
6
|
#
|
7
7
|
# See the examples directory, which contains a subdirectory _north_ with the
|
8
8
|
# Graph catalog GraphViz (see
|
9
|
-
#
|
9
|
+
# https://www.research.att.com/sw/tools/graphviz/refs.html).
|
10
10
|
#
|
11
11
|
# We use REXML::StreamListener from the REXML library
|
12
|
-
# (
|
12
|
+
# (https://www.germane-software.com/software/rexml) to parse the grapml files.
|
13
13
|
|
14
14
|
require 'rgl/mutable'
|
15
15
|
require 'rexml/document'
|
@@ -48,7 +48,7 @@ module RGL
|
|
48
48
|
end # class MutableGraphParser
|
49
49
|
|
50
50
|
# Initializes an RGL graph from a subset of the GraphML format given in
|
51
|
-
# +source+ (see
|
51
|
+
# +source+ (see https://graphml.graphdrawing.org/).
|
52
52
|
#
|
53
53
|
def from_graphxml(source)
|
54
54
|
listener = MutableGraphParser.new(self)
|
data/lib/rgl/implicit.rb
CHANGED
@@ -3,25 +3,26 @@
|
|
3
3
|
# This file contains the definition of the class RGL::ImplicitGraph, which
|
4
4
|
# defines vertex and edge iterators using blocks (which again call blocks).
|
5
5
|
#
|
6
|
-
# An ImplicitGraph provides a handy way to define graphs on the fly, using two
|
7
|
-
# blocks for the two iterators defining a graph. A directed cyclic graph,
|
8
|
-
# with five vertices can be created as follows:
|
9
|
-
#
|
10
|
-
# g = RGL::ImplicitGraph.new do |g|
|
11
|
-
# g.vertex_iterator { |b| 0.upto(4,&b) }
|
12
|
-
# g.adjacent_iterator { |x, b| b.call((x+1)%5) }
|
13
|
-
# g.directed = true
|
14
|
-
# end
|
15
|
-
#
|
16
|
-
# g.to_s # => "(0-1)(1-2)(2-3)(3-4)(4-0)"
|
17
|
-
#
|
18
|
-
# Other examples are given by the methods vertices_filtered_by and
|
19
|
-
# edges_filtered_by, which can be applied to any graph.
|
20
6
|
|
21
7
|
require 'rgl/base'
|
22
8
|
|
23
9
|
module RGL
|
24
10
|
|
11
|
+
# An ImplicitGraph provides a handy way to define graphs on the fly, using two
|
12
|
+
# blocks for the two iterators defining a graph. Other examples are given by the
|
13
|
+
# methods {#vertices_filtered_by} and {#edges_filtered_by}, which can be
|
14
|
+
# applied to any graph.
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# # A directed cyclic graph, with five vertices can be created as follows:
|
18
|
+
# g = RGL::ImplicitGraph.new do |g|
|
19
|
+
# g.vertex_iterator { |b| 0.upto(4,&b) }
|
20
|
+
# g.adjacent_iterator { |x, b| b.call((x+1)%5) }
|
21
|
+
# g.directed = true
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# g.to_s # => "(0-1)(1-2)(2-3)(3-4)(4-0)"
|
25
|
+
#
|
25
26
|
class ImplicitGraph
|
26
27
|
|
27
28
|
include Graph
|
@@ -31,10 +32,10 @@ module RGL
|
|
31
32
|
EMPTY_VERTEX_ITERATOR = proc { |b| }
|
32
33
|
EMPTY_NEIGHBOR_ITERATOR = proc { |x, b| }
|
33
34
|
|
34
|
-
# Create a new ImplicitGraph, which is empty by default. The caller should
|
35
|
+
# Create a new {ImplicitGraph}, which is empty by default. The caller should
|
35
36
|
# configure the graph using vertex and neighbor iterators. If the graph is
|
36
|
-
# directed, the client should set
|
37
|
-
# for
|
37
|
+
# directed, the client should set +@directed+ to true. The default value
|
38
|
+
# for +@directed+ is false.
|
38
39
|
#
|
39
40
|
def initialize
|
40
41
|
@directed = false
|
@@ -43,21 +44,21 @@ module RGL
|
|
43
44
|
yield self if block_given? # Let client overwrite defaults.
|
44
45
|
end
|
45
46
|
|
46
|
-
# Returns the value of
|
47
|
+
# Returns the value of +@directed+.
|
47
48
|
#
|
48
49
|
def directed?
|
49
50
|
@directed
|
50
51
|
end
|
51
52
|
|
52
|
-
def each_vertex(&block)
|
53
|
+
def each_vertex(&block)
|
53
54
|
@vertex_iterator.call(block)
|
54
55
|
end
|
55
56
|
|
56
|
-
def each_adjacent(v, &block)
|
57
|
+
def each_adjacent(v, &block)
|
57
58
|
@adjacent_iterator.call(v, block)
|
58
59
|
end
|
59
60
|
|
60
|
-
def each_edge(&block)
|
61
|
+
def each_edge(&block)
|
61
62
|
if defined? @edge_iterator
|
62
63
|
@edge_iterator.call(block)
|
63
64
|
else
|
@@ -67,7 +68,7 @@ module RGL
|
|
67
68
|
|
68
69
|
# Sets the vertex_iterator to _block_,
|
69
70
|
# which must be a block of one parameter
|
70
|
-
# which again is the block called by each_vertex.
|
71
|
+
# which again is the block called by {#each_vertex}.
|
71
72
|
#
|
72
73
|
def vertex_iterator(&block)
|
73
74
|
@vertex_iterator = block
|
@@ -98,15 +99,14 @@ module RGL
|
|
98
99
|
|
99
100
|
module Graph
|
100
101
|
|
101
|
-
#
|
102
|
-
#
|
103
|
-
# Return a new ImplicitGraph which has as vertices all vertices of the
|
102
|
+
# Returns a new {ImplicitGraph} which has as vertices all vertices of the
|
104
103
|
# receiver which satisfy the predicate _filter_.
|
105
104
|
#
|
106
|
-
# The methods provides similar functionality as
|
107
|
-
#
|
105
|
+
# The methods provides similar functionality as
|
106
|
+
# {https://www.boost.org/doc/libs/1_36_0/libs/graph/doc/filtered_graph.html
|
107
|
+
# BGLs Filtered Graph}
|
108
108
|
#
|
109
|
-
#
|
109
|
+
# @example
|
110
110
|
#
|
111
111
|
# def complete (n)
|
112
112
|
# set = n.integer? ? (1..n) : n
|
@@ -120,7 +120,7 @@ module RGL
|
|
120
120
|
#
|
121
121
|
# complete(4).to_s # => "(1=2)(1=3)(1=4)(2=3)(2=4)(3=4)"
|
122
122
|
# complete(4).vertices_filtered_by { |v| v != 4 }.to_s # => "(1=2)(1=3)(2=3)"
|
123
|
-
#
|
123
|
+
# @return [ImplicitGraph]
|
124
124
|
def vertices_filtered_by(&filter)
|
125
125
|
implicit_graph do |g|
|
126
126
|
g.vertex_iterator do |b|
|
@@ -133,15 +133,15 @@ module RGL
|
|
133
133
|
end
|
134
134
|
end
|
135
135
|
|
136
|
-
#
|
136
|
+
# Returns a new {ImplicitGraph} which has as edges all edges of the receiver
|
137
137
|
# which satisfy the predicate _filter_ (a block with two parameters).
|
138
138
|
#
|
139
|
-
#
|
139
|
+
# @example
|
140
140
|
#
|
141
141
|
# g = complete(7).edges_filtered_by { |u,v| u+v == 7 }
|
142
142
|
# g.to_s => "(1=6)(2=5)(3=4)"
|
143
143
|
# g.vertices => [1, 2, 3, 4, 5, 6, 7]
|
144
|
-
#
|
144
|
+
# @return [ImplicitGraph]
|
145
145
|
def edges_filtered_by(&filter)
|
146
146
|
implicit_graph do |g|
|
147
147
|
g.adjacent_iterator do |v, b|
|
@@ -156,10 +156,10 @@ module RGL
|
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
159
|
-
# Return a new ImplicitGraph which is isomorphic (i.e. has same edges and
|
159
|
+
# Return a new {ImplicitGraph} which is isomorphic (i.e. has same edges and
|
160
160
|
# vertices) to the receiver. It is a shortcut, also used by
|
161
|
-
# edges_filtered_by and vertices_filtered_by.
|
162
|
-
#
|
161
|
+
# {#edges_filtered_by} and {#vertices_filtered_by}.
|
162
|
+
# @return [ImplicitGraph]
|
163
163
|
def implicit_graph
|
164
164
|
result = ImplicitGraph.new do |g|
|
165
165
|
g.vertex_iterator { |b| self.each_vertex(&b) }
|
data/lib/rgl/mutable.rb
CHANGED
@@ -21,7 +21,7 @@ module RGL
|
|
21
21
|
# Inserts the edge (u,v) into the graph.
|
22
22
|
#
|
23
23
|
# Note that for undirected graphs, (u,v) is the same edge as (v,u), so
|
24
|
-
# after a call to the function add_edge
|
24
|
+
# after a call to the function #add_edge, this implies that edge (u,v)
|
25
25
|
# will appear in the out-edges of u and (u,v) (or equivalently (v,u))
|
26
26
|
# will appear in the out-edges of v. Put another way, v will be adjacent
|
27
27
|
# to u and u will be adjacent to v.
|
@@ -37,8 +37,8 @@ module RGL
|
|
37
37
|
end
|
38
38
|
|
39
39
|
# Add all edges in the _edges_ array to the edge set. Elements of the
|
40
|
-
# array can be both two-element arrays or instances of DirectedEdge or
|
41
|
-
# UnDirectedEdge.
|
40
|
+
# array can be both two-element arrays or instances of {Edge::DirectedEdge} or
|
41
|
+
# {Edge::UnDirectedEdge}.
|
42
42
|
#
|
43
43
|
def add_edges(*edges)
|
44
44
|
edges.each { |edge| add_edge(edge[0], edge[1]) }
|
@@ -65,7 +65,7 @@ module RGL
|
|
65
65
|
end
|
66
66
|
|
67
67
|
# Remove all vertices specified by the array a from the graph by calling
|
68
|
-
# remove_vertex.
|
68
|
+
# {#remove_vertex}.
|
69
69
|
#
|
70
70
|
def remove_vertices(*a)
|
71
71
|
a.each { |v| remove_vertex v }
|
@@ -74,14 +74,14 @@ module RGL
|
|
74
74
|
# Returns all minimum cycles that pass through a give vertex.
|
75
75
|
# The format is an Array of cycles, with each cycle being an Array
|
76
76
|
# of vertices in the cycle.
|
77
|
-
#
|
77
|
+
# @return [Array[Array]]
|
78
78
|
def cycles_with_vertex(vertex)
|
79
79
|
cycles_with_vertex_helper(vertex, vertex, [])
|
80
80
|
end
|
81
81
|
|
82
82
|
protected
|
83
83
|
|
84
|
-
def cycles_with_vertex_helper(vertex, start, visited)
|
84
|
+
def cycles_with_vertex_helper(vertex, start, visited)
|
85
85
|
adjacent_vertices(start).reject { |x| visited.include?(x) }.inject([]) do |acc, adj|
|
86
86
|
local_visited = Array.new(visited) << adj
|
87
87
|
acc << local_visited if (adj==vertex)
|
@@ -91,7 +91,7 @@ module RGL
|
|
91
91
|
|
92
92
|
public
|
93
93
|
|
94
|
-
#
|
94
|
+
# @return [Array] of all minimum cycles in a graph
|
95
95
|
#
|
96
96
|
# This is not an efficient implementation O(n^4) and could
|
97
97
|
# be done using Minimum Spanning Trees. Hint. Hint.
|
data/lib/rgl/path_builder.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module RGL
|
2
2
|
|
3
|
-
|
3
|
+
class PathBuilder
|
4
4
|
|
5
5
|
def initialize(source, parents_map)
|
6
6
|
@source = source
|
@@ -16,6 +16,7 @@ module RGL
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
# @return [Hash]
|
19
20
|
def paths(targets)
|
20
21
|
paths_map = {}
|
21
22
|
|
@@ -37,4 +38,4 @@ module RGL
|
|
37
38
|
|
38
39
|
end
|
39
40
|
|
40
|
-
end # RGL
|
41
|
+
end # RGL
|
data/lib/rgl/prim.rb
CHANGED
@@ -3,6 +3,8 @@ require 'rgl/adjacency'
|
|
3
3
|
|
4
4
|
module RGL
|
5
5
|
|
6
|
+
# Implements {https://en.wikipedia.org/wiki/Prim%27s_algorithm Prim's algorithm}.
|
7
|
+
# @see Graph#prim_minimum_spanning_tree
|
6
8
|
class PrimAlgorithm
|
7
9
|
|
8
10
|
# Replacement for default distance combinator that is used in Dijkstra's algorithm. While building a minimum
|
@@ -36,7 +38,7 @@ module RGL
|
|
36
38
|
|
37
39
|
# Finds the minimum spanning tree of the graph.
|
38
40
|
#
|
39
|
-
# Returns an AdjacencyGraph that represents the minimum spanning tree of the graph's connectivity component that
|
41
|
+
# Returns an {AdjacencyGraph} that represents the minimum spanning tree of the graph's connectivity component that
|
40
42
|
# contains the starting vertex. The algorithm starts from an arbitrary vertex if the _start_vertex_ is not given.
|
41
43
|
# Since the implementation relies on the Dijkstra's algorithm, Prim's algorithm uses the same visitor class and emits
|
42
44
|
# the same events.
|
data/lib/rgl/rdot.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
-
# This is a modified version of dot.rb from Dave Thomas's rdoc project. I
|
2
|
-
# renamed it to rdot.rb to avoid collision with an installed rdoc/dot.
|
3
|
-
#
|
4
|
-
# It also supports undirected edges.
|
5
|
-
|
6
1
|
module RGL
|
7
2
|
|
3
|
+
# This is a modified version of +dot.rb+ from {https://ruby.github.io/rdoc Dave
|
4
|
+
# Thomas's rdoc project}. I renamed it to +rdot.rb+ to avoid collision with an
|
5
|
+
# installed rdoc/dot.
|
6
|
+
#
|
7
|
+
# It also supports undirected edges.
|
8
8
|
module DOT
|
9
9
|
|
10
10
|
# options for node declaration
|
11
11
|
|
12
12
|
NODE_OPTS = [
|
13
13
|
# attributes due to
|
14
|
-
#
|
14
|
+
# https://www.graphviz.org/Documentation/dotguide.pdf
|
15
15
|
# February 23, 2008
|
16
16
|
'color', # default: black; node shape color
|
17
17
|
'comment', # any string (format-dependent)
|
@@ -139,7 +139,7 @@ module RGL
|
|
139
139
|
|
140
140
|
attr_accessor :name, :options
|
141
141
|
|
142
|
-
def initialize(params = {}, option_list = [])
|
142
|
+
def initialize(params = {}, option_list = [])
|
143
143
|
@name = params['name'] ? params['name'] : nil
|
144
144
|
@options = {}
|
145
145
|
|
data/lib/rgl/topsort.rb
CHANGED
@@ -10,10 +10,11 @@ module RGL
|
|
10
10
|
# such that if edge (u,v) appears in the graph, then u comes before v in
|
11
11
|
# the ordering. The graph must be a directed acyclic graph (DAG).
|
12
12
|
#
|
13
|
-
# The iterator can also be applied to undirected graph or to a
|
13
|
+
# The iterator can also be applied to an undirected graph or to a directed graph
|
14
14
|
# which contains a cycle. In this case, the Iterator does not reach all
|
15
|
-
# vertices. The implementation of acyclic? uses this fact.
|
15
|
+
# vertices. The implementation of {Graph#acyclic?} uses this fact.
|
16
16
|
#
|
17
|
+
# @see Graph#topsort_iterator
|
17
18
|
class TopsortIterator
|
18
19
|
|
19
20
|
include GraphIterator
|
@@ -23,7 +24,7 @@ module RGL
|
|
23
24
|
set_to_begin
|
24
25
|
end
|
25
26
|
|
26
|
-
def set_to_begin
|
27
|
+
def set_to_begin
|
27
28
|
@waiting = Array.new
|
28
29
|
@inDegrees = Hash.new(0)
|
29
30
|
|
@@ -39,7 +40,8 @@ module RGL
|
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
42
|
-
|
43
|
+
# @private
|
44
|
+
def basic_forward
|
43
45
|
u = @waiting.pop
|
44
46
|
graph.each_adjacent(u) do |v|
|
45
47
|
@inDegrees[v] -= 1
|
@@ -52,16 +54,15 @@ module RGL
|
|
52
54
|
true
|
53
55
|
end
|
54
56
|
|
55
|
-
# :nodoc: FIXME
|
56
57
|
def at_end?
|
57
58
|
@waiting.empty?
|
58
|
-
end
|
59
|
+
end
|
59
60
|
|
60
61
|
end # class TopsortIterator
|
61
62
|
|
62
63
|
module Graph
|
63
64
|
|
64
|
-
#
|
65
|
+
# @return [TopsortIterator] for the graph.
|
65
66
|
#
|
66
67
|
def topsort_iterator
|
67
68
|
TopsortIterator.new(self)
|
data/lib/rgl/transitivity.rb
CHANGED
@@ -6,7 +6,7 @@ module RGL
|
|
6
6
|
|
7
7
|
module Graph
|
8
8
|
|
9
|
-
# Returns an
|
9
|
+
# Returns an {DirectedAdjacencyGraph} which is the transitive closure of
|
10
10
|
# this graph. Meaning, for each path u -> ... -> v in this graph, the path
|
11
11
|
# is copied and the edge u -> v is added. This method supports working with
|
12
12
|
# cyclic graphs by ensuring that edges are created between every pair of
|
@@ -15,8 +15,8 @@ module RGL
|
|
15
15
|
# This method should run in O(|V||E|) time, where |V| and |E| are the number
|
16
16
|
# of vertices and edges respectively.
|
17
17
|
#
|
18
|
-
# Raises
|
19
|
-
#
|
18
|
+
# Raises {NotDirectedError} if run on an undirected graph.
|
19
|
+
# @return DirectedAdjacencyGraph
|
20
20
|
def transitive_closure
|
21
21
|
raise NotDirectedError,
|
22
22
|
"transitive_closure only supported for directed graphs" unless directed?
|
@@ -86,7 +86,7 @@ module RGL
|
|
86
86
|
g
|
87
87
|
end
|
88
88
|
|
89
|
-
# Returns an
|
89
|
+
# Returns an {DirectedAdjacencyGraph} which is the transitive reduction
|
90
90
|
# of this graph. Meaning, that each edge u -> v is omitted if path
|
91
91
|
# u -> ... -> v exists. This method supports working with cyclic graphs;
|
92
92
|
# however, cycles are arbitrarily simplified which may lead to variant,
|
@@ -95,8 +95,8 @@ module RGL
|
|
95
95
|
# This method should run in O(|V||E|) time, where |V| and |E| are the number
|
96
96
|
# of vertices and edges respectively.
|
97
97
|
#
|
98
|
-
# Raises
|
99
|
-
#
|
98
|
+
# Raises {NotDirectedError} if run on an undirected graph.
|
99
|
+
# @return DirectedAdjacencyGraph
|
100
100
|
def transitive_reduction
|
101
101
|
raise NotDirectedError,
|
102
102
|
"transitive_reduction only supported for directed graphs" unless directed?
|