rgl 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +74 -0
- data/Makefile +72 -0
- data/README +240 -0
- data/Rakefile +210 -0
- data/TAGS +209 -0
- data/examples/canvas.rb +103 -0
- data/examples/codegraph +238 -0
- data/examples/example.jpg +0 -0
- data/examples/examples.rb +112 -0
- data/examples/graph.dot +54 -0
- data/examples/graph.png +0 -0
- data/examples/module_graph.jpg +0 -0
- data/examples/north.rb +12 -0
- data/examples/north/Graph.log +128 -0
- data/examples/north/g.10.0.graphml +28 -0
- data/examples/north/g.10.1.graphml +28 -0
- data/examples/north/g.10.11.graphml +31 -0
- data/examples/north/g.10.12.graphml +27 -0
- data/examples/north/g.10.13.graphml +27 -0
- data/examples/north/g.10.14.graphml +27 -0
- data/examples/north/g.10.15.graphml +26 -0
- data/examples/north/g.10.16.graphml +26 -0
- data/examples/north/g.10.17.graphml +26 -0
- data/examples/north/g.10.19.graphml +37 -0
- data/examples/north/g.10.2.graphml +28 -0
- data/examples/north/g.10.20.graphml +38 -0
- data/examples/north/g.10.22.graphml +43 -0
- data/examples/north/g.10.24.graphml +30 -0
- data/examples/north/g.10.25.graphml +45 -0
- data/examples/north/g.10.27.graphml +38 -0
- data/examples/north/g.10.28.graphml +30 -0
- data/examples/north/g.10.29.graphml +38 -0
- data/examples/north/g.10.3.graphml +26 -0
- data/examples/north/g.10.30.graphml +34 -0
- data/examples/north/g.10.31.graphml +42 -0
- data/examples/north/g.10.34.graphml +42 -0
- data/examples/north/g.10.37.graphml +28 -0
- data/examples/north/g.10.38.graphml +38 -0
- data/examples/north/g.10.39.graphml +36 -0
- data/examples/north/g.10.4.graphml +26 -0
- data/examples/north/g.10.40.graphml +37 -0
- data/examples/north/g.10.41.graphml +37 -0
- data/examples/north/g.10.42.graphml +26 -0
- data/examples/north/g.10.45.graphml +28 -0
- data/examples/north/g.10.46.graphml +32 -0
- data/examples/north/g.10.5.graphml +31 -0
- data/examples/north/g.10.50.graphml +30 -0
- data/examples/north/g.10.56.graphml +29 -0
- data/examples/north/g.10.57.graphml +32 -0
- data/examples/north/g.10.58.graphml +32 -0
- data/examples/north/g.10.6.graphml +26 -0
- data/examples/north/g.10.60.graphml +32 -0
- data/examples/north/g.10.61.graphml +34 -0
- data/examples/north/g.10.62.graphml +34 -0
- data/examples/north/g.10.68.graphml +30 -0
- data/examples/north/g.10.69.graphml +32 -0
- data/examples/north/g.10.7.graphml +29 -0
- data/examples/north/g.10.70.graphml +26 -0
- data/examples/north/g.10.71.graphml +27 -0
- data/examples/north/g.10.72.graphml +28 -0
- data/examples/north/g.10.74.graphml +29 -0
- data/examples/north/g.10.75.graphml +29 -0
- data/examples/north/g.10.78.graphml +27 -0
- data/examples/north/g.10.79.graphml +34 -0
- data/examples/north/g.10.8.graphml +29 -0
- data/examples/north/g.10.80.graphml +34 -0
- data/examples/north/g.10.82.graphml +35 -0
- data/examples/north/g.10.83.graphml +32 -0
- data/examples/north/g.10.85.graphml +34 -0
- data/examples/north/g.10.86.graphml +34 -0
- data/examples/north/g.10.88.graphml +37 -0
- data/examples/north/g.10.89.graphml +29 -0
- data/examples/north/g.10.9.graphml +26 -0
- data/examples/north/g.10.90.graphml +32 -0
- data/examples/north/g.10.91.graphml +31 -0
- data/examples/north/g.10.92.graphml +26 -0
- data/examples/north/g.10.93.graphml +32 -0
- data/examples/north/g.10.94.graphml +34 -0
- data/examples/north/g.12.8.graphml +40 -0
- data/examples/north/g.14.9.graphml +36 -0
- data/examples/north2.rb +21 -0
- data/examples/rdep-rgl.rb +395 -0
- data/install.rb +49 -0
- data/lib/rgl/adjacency.rb +151 -0
- data/lib/rgl/base.rb +299 -0
- data/lib/rgl/connected_components.rb +125 -0
- data/lib/rgl/dot.rb +63 -0
- data/lib/rgl/graphxml.rb +52 -0
- data/lib/rgl/implicit.rb +151 -0
- data/lib/rgl/mutable.rb +54 -0
- data/lib/rgl/rdot.rb +264 -0
- data/lib/rgl/topsort.rb +61 -0
- data/lib/rgl/transitiv_closure.rb +34 -0
- data/lib/rgl/traversal.rb +296 -0
- data/tests/TestComponents.rb +67 -0
- data/tests/TestDirectedGraph.rb +100 -0
- data/tests/TestEdge.rb +33 -0
- data/tests/TestGraphXML.rb +57 -0
- data/tests/TestImplicit.rb +52 -0
- data/tests/TestTransitiveClosure.rb +29 -0
- data/tests/TestTraversal.rb +222 -0
- data/tests/TestUnDirectedGraph.rb +98 -0
- metadata +163 -0
data/install.rb
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#! /usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'getoptlong'
|
|
4
|
+
require 'rbconfig'
|
|
5
|
+
require 'ftools'
|
|
6
|
+
require 'find'
|
|
7
|
+
|
|
8
|
+
SRC_BASE = 'lib'
|
|
9
|
+
SRC = 'rgl'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
INSTDIR = File.join Config::CONFIG['sitedir']
|
|
13
|
+
DESTDIR = File.join INSTDIR, SRC
|
|
14
|
+
|
|
15
|
+
opts = GetoptLong.new( [ "--uninstall", "-u", GetoptLong::NO_ARGUMENT ] )
|
|
16
|
+
|
|
17
|
+
def install
|
|
18
|
+
begin
|
|
19
|
+
File.makedirs( DESTDIR )
|
|
20
|
+
pwd = Dir.pwd
|
|
21
|
+
Dir.chdir(SRC_BASE)
|
|
22
|
+
Dir['*.rb'].each do |file|
|
|
23
|
+
dst = File.join( INSTDIR, file )
|
|
24
|
+
File.install(file, dst, 0644, true)
|
|
25
|
+
end
|
|
26
|
+
Find.find(SRC) do |file|
|
|
27
|
+
dst = File.join( INSTDIR, file )
|
|
28
|
+
File.install(file, dst, 0644, true) if file =~ /.rb$/
|
|
29
|
+
end
|
|
30
|
+
Dir.chdir(pwd)
|
|
31
|
+
rescue
|
|
32
|
+
puts $!
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def uninstall
|
|
37
|
+
begin
|
|
38
|
+
puts "Deleting:"
|
|
39
|
+
Find.find(DESTDIR) { |file| File.rm_f file,true }
|
|
40
|
+
Dir.delete DESTDIR
|
|
41
|
+
rescue
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
if (opt = opts.get) and opt[0] =~ /^-?-u/
|
|
46
|
+
uninstall
|
|
47
|
+
else
|
|
48
|
+
install
|
|
49
|
+
end
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#
|
|
2
|
+
# $Id: adjacency.rb,v 1.4 2002/11/10 21:21:20 monora Exp $
|
|
3
|
+
#
|
|
4
|
+
# The DirectedAdjacencyGraph class implements a generalized adjacency list
|
|
5
|
+
# graph structure. An AdjacencyGraph is basically a two-dimensional structure,
|
|
6
|
+
# where each element of the first dimension represents a vertex, and each of
|
|
7
|
+
# the vertices contains a one-dimensional structure that is the list of all
|
|
8
|
+
# adjacent vertices.
|
|
9
|
+
#
|
|
10
|
+
# The class for representing the adjacency list of a vertex is by default a
|
|
11
|
+
# Set, but can be configured by the client when a AdjacencyGraph is created.
|
|
12
|
+
|
|
13
|
+
require 'rgl/mutable'
|
|
14
|
+
require 'set'
|
|
15
|
+
|
|
16
|
+
module RGL
|
|
17
|
+
class DirectedAdjacencyGraph
|
|
18
|
+
include MutableGraph
|
|
19
|
+
|
|
20
|
+
# Shortcut for creating a DirectedAdjacencyGraph:
|
|
21
|
+
#
|
|
22
|
+
# RGL::DirectedAdjacencyGraph[1,2, 2,3, 2,4, 4,5].edges.to_a.to_s =>
|
|
23
|
+
# "(1-2)(2-3)(2-4)(4-5)"
|
|
24
|
+
def self.[](*a)
|
|
25
|
+
result = new
|
|
26
|
+
0.step(a.size-1,2) { |i| result.add_edge(a[i],a[i+1])}
|
|
27
|
+
result
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Returns a new empty DirectedAdjacencyGraph which has as edgelist class the
|
|
31
|
+
# given class. The default edgelist class is Set to ensure set semantics for
|
|
32
|
+
# edges and vertices.
|
|
33
|
+
def initialize(edgelist_class=Set)
|
|
34
|
+
@edgelist_class = edgelist_class
|
|
35
|
+
@vertice_dict = Hash.new
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Iterator for the keys of the vertice list hash.
|
|
39
|
+
def each_vertex(&b)
|
|
40
|
+
@vertice_dict.each_key(&b)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def each_adjacent(v, &b) # :nodoc:
|
|
44
|
+
adjacency_list = @vertice_dict[v] or raise NoVertexError, "No vertex #{v}."
|
|
45
|
+
adjacency_list.each(&b)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Returns true.
|
|
49
|
+
def directed?; true; end
|
|
50
|
+
|
|
51
|
+
# Complexity is O(1), since the vertices are kept in a Hash containing as
|
|
52
|
+
# value the list of adjacent vertices of _v_.
|
|
53
|
+
def has_vertex?(v); @vertice_dict.has_key?(v); end
|
|
54
|
+
|
|
55
|
+
# Complexity is O(1), if a Set is used as adjacency list, otherwise
|
|
56
|
+
# O(out_degree(v))
|
|
57
|
+
#
|
|
58
|
+
# ---
|
|
59
|
+
# MutableGraph interface.
|
|
60
|
+
def has_edge? (u, v)
|
|
61
|
+
has_vertex?(u) and @vertice_dict[u].include? v
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# See MutableGraph#add_vertex.
|
|
65
|
+
#
|
|
66
|
+
# If the vertex is already in (using eql?) the method does nothing.
|
|
67
|
+
def add_vertex(v)
|
|
68
|
+
@vertice_dict[v] ||= @edgelist_class.new
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# See MutableGraph#add_edge.
|
|
72
|
+
def add_edge (u,v)
|
|
73
|
+
add_vertex(u) # ensure key
|
|
74
|
+
add_vertex(v) # ensure key
|
|
75
|
+
basic_add_edge(u,v)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# See MutableGraph#remove_vertex.
|
|
79
|
+
def remove_vertex(v)
|
|
80
|
+
@vertice_dict.delete(v)
|
|
81
|
+
|
|
82
|
+
# remove v from all adjacency lists
|
|
83
|
+
@vertice_dict.each_value { |adjList| adjList.delete(v) }
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# See MutableGraph::remove_edge.
|
|
87
|
+
def remove_edge (u,v)
|
|
88
|
+
@vertice_dict[u].delete(v) unless @vertice_dict[u].nil?
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
protected
|
|
92
|
+
|
|
93
|
+
def basic_add_edge(u,v)
|
|
94
|
+
@vertice_dict[u].add v
|
|
95
|
+
end
|
|
96
|
+
end # class AdjacencyGraph
|
|
97
|
+
|
|
98
|
+
# AdjacencyGraph is an undirected Graph. The methods add_edge and remove_edge
|
|
99
|
+
# are reimplemented: If an edge (u,v) is added or removed then the reverse
|
|
100
|
+
# edge (v,u) is also added or removed.
|
|
101
|
+
class AdjacencyGraph < DirectedAdjacencyGraph
|
|
102
|
+
# Always returns false.
|
|
103
|
+
def directed?; false; end
|
|
104
|
+
|
|
105
|
+
# Also removes (v,u)
|
|
106
|
+
def remove_edge (u,v)
|
|
107
|
+
super
|
|
108
|
+
@vertice_dict[v].delete(u) unless @vertice_dict[v].nil?
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
protected
|
|
112
|
+
def basic_add_edge(u,v)
|
|
113
|
+
super
|
|
114
|
+
# Insert backwards edge
|
|
115
|
+
@vertice_dict[v].add u
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
module Graph
|
|
120
|
+
# Convert a general graph to an AdjacencyGraph. If the graph is directed
|
|
121
|
+
# returns a DirectedAdjacencyGraph else a AdjacencyGraph.
|
|
122
|
+
def to_adjacency
|
|
123
|
+
result = (directed? ? DirectedAdjacencyGraph : AdjacencyGraph).new
|
|
124
|
+
each_edge { |u,v| result.add_edge u,v }
|
|
125
|
+
result
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Return a new DirectedAdjacencyGraph which has the same set of vertices. If
|
|
129
|
+
# (u,v) is an edge of the graph then (v,u) is an edge of the result.
|
|
130
|
+
#
|
|
131
|
+
# If the graph is undirected the result is self.
|
|
132
|
+
def reverse
|
|
133
|
+
reurn self unless directed?
|
|
134
|
+
result = DirectedAdjacencyGraph.new
|
|
135
|
+
each_edge { |u,v| result.add_edge v,u }
|
|
136
|
+
result
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Return a new AdjacencyGraph which has the same set of vertices. If (u,v)
|
|
140
|
+
# is an edge of the graph (u,v) and (v,u) (which are the same edges) is an
|
|
141
|
+
# edge of the result.
|
|
142
|
+
#
|
|
143
|
+
# If the graph is undirected the result is self.
|
|
144
|
+
def to_undirected
|
|
145
|
+
return self unless directed?
|
|
146
|
+
result = AdjacencyGraph.new
|
|
147
|
+
each_edge { |u,v| result.add_edge u,v }
|
|
148
|
+
result
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
data/lib/rgl/base.rb
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# :include: ../../README
|
|
2
|
+
#
|
|
3
|
+
# ----
|
|
4
|
+
#
|
|
5
|
+
# Module RGL defines the namespace for all modules and classes of the graph
|
|
6
|
+
# library. The main module is RGL::Graph which defines the abstract behavior of
|
|
7
|
+
# all graphs in the library.
|
|
8
|
+
|
|
9
|
+
RGL_VERSION = "0.2.2"
|
|
10
|
+
|
|
11
|
+
unless Enumerable.instance_methods(true).grep(/inject/)
|
|
12
|
+
module Enumerable
|
|
13
|
+
def inject(*argv)
|
|
14
|
+
argc = argv.size
|
|
15
|
+
|
|
16
|
+
if argc == 0
|
|
17
|
+
first = true
|
|
18
|
+
result = nil
|
|
19
|
+
|
|
20
|
+
each { |e|
|
|
21
|
+
if first
|
|
22
|
+
first = false
|
|
23
|
+
result = e
|
|
24
|
+
else
|
|
25
|
+
result = yield(result, e)
|
|
26
|
+
end
|
|
27
|
+
}
|
|
28
|
+
elsif argc == 1
|
|
29
|
+
result = argv[0]
|
|
30
|
+
|
|
31
|
+
each { |e| result = yield(result, e) }
|
|
32
|
+
else
|
|
33
|
+
raise ArgumentError, "wrong # of arguments(#{argc} for 1)"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
result
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
module Enumerable
|
|
42
|
+
# Fixnum()
|
|
43
|
+
#
|
|
44
|
+
# Return the number of elements of the Enumerable. Same as _size_ but not all
|
|
45
|
+
# Enumerables implement size.
|
|
46
|
+
#--
|
|
47
|
+
# Should we call the methods _size_?
|
|
48
|
+
def length
|
|
49
|
+
inject(0) do |sum,v|
|
|
50
|
+
sum + 1
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
module RGL
|
|
56
|
+
class NotDirectedError < RuntimeError; end
|
|
57
|
+
class NotUndirectedError < RuntimeError; end
|
|
58
|
+
|
|
59
|
+
class NoVertexError < IndexError; end
|
|
60
|
+
class NoEdgeError < IndexError; end
|
|
61
|
+
|
|
62
|
+
# Module Edge includes classes for representing egdes of directed and
|
|
63
|
+
# undirected graphs. There is no need for a Vertex class, because every ruby
|
|
64
|
+
# object can be a vertex of a graph.
|
|
65
|
+
module Edge
|
|
66
|
+
# Simply a directed pair (source -> target). Must library functions try do
|
|
67
|
+
# omit to instantiate edges. They instead use two vertex parameters for
|
|
68
|
+
# representing edges (see each_edge). If a client wants to store edges
|
|
69
|
+
# explicitly DirecteEdge or UnDirectedEdge instances are return
|
|
70
|
+
# (i.e. Graph#edges).
|
|
71
|
+
class DirectedEdge
|
|
72
|
+
attr_accessor :source, :target
|
|
73
|
+
|
|
74
|
+
# Can be used to create an edge from a two element array.
|
|
75
|
+
def self.[](*a)
|
|
76
|
+
new(a[0],a[1])
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Create a new DirectedEdge with source _a_ and target _b_.
|
|
80
|
+
def initialize (a,b)
|
|
81
|
+
@source, @target = a,b
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Two directed edges (u,v) and (x,y) are equal iff u == x and v == y. eql?
|
|
85
|
+
# is needed when edges are inserted into a Set. eql? is aliased to ==.
|
|
86
|
+
def eql?(edge)
|
|
87
|
+
source == edge.source and target == edge.target
|
|
88
|
+
end
|
|
89
|
+
alias == eql?
|
|
90
|
+
|
|
91
|
+
# Returns (v,u) if self == (u,v).
|
|
92
|
+
def reverse
|
|
93
|
+
self.class.new(target, source)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Edges can be indexed. edge[0] == edge.source, edge[n] == edge.target for
|
|
97
|
+
# all n>0. Edges can thus be used as a two element array.
|
|
98
|
+
def [](index); index.zero? ? source : target; end
|
|
99
|
+
|
|
100
|
+
# DirectedEdge[1,2].to_s == "(1-2)"
|
|
101
|
+
def to_s
|
|
102
|
+
"(#{source}-#{target})"
|
|
103
|
+
end
|
|
104
|
+
# Returns the array [source,target].
|
|
105
|
+
def to_a; [source,target]; end
|
|
106
|
+
|
|
107
|
+
# Sort support is dispatched to the <=> method of Array
|
|
108
|
+
def <=> e
|
|
109
|
+
self.to_a <=> e.to_a
|
|
110
|
+
end
|
|
111
|
+
end # DirectedEdge
|
|
112
|
+
|
|
113
|
+
# An undirected edge is simply an undirected pair (source, target) used in
|
|
114
|
+
# undirected graphs. UnDirectedEdge[u,v] == UnDirectedEdge[v,u]
|
|
115
|
+
class UnDirectedEdge < DirectedEdge
|
|
116
|
+
def eql?(edge)
|
|
117
|
+
super or (target == edge.source and source == edge.target)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def hash
|
|
121
|
+
source.hash ^ target.hash
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# UnDirectedEdge[1,2].to_s == "(1=2)"
|
|
125
|
+
def to_s; "(#{source}=#{target})"; end
|
|
126
|
+
end
|
|
127
|
+
end # Edge
|
|
128
|
+
|
|
129
|
+
# In BGL terminology the module Graph defines the concept graph (see
|
|
130
|
+
# BOOST_DOC/graph_concepts.html). We though do not
|
|
131
|
+
# distinguish between IncidenceGraph, EdgeListGraph and VertexListGraph
|
|
132
|
+
# concept, which would complicate
|
|
133
|
+
# the interface two much. These concepts are defined in BGL to differentiate
|
|
134
|
+
# between efficient access to edges and vertices.
|
|
135
|
+
#
|
|
136
|
+
# The RGL Graph concept contains only few requirements that are common to all
|
|
137
|
+
# the graph
|
|
138
|
+
# concepts. These include especially the iterators defining the set of
|
|
139
|
+
# vertices and edges (see each_vertex and each_adjacent). Most other functions
|
|
140
|
+
# are derived from these fundamental iterators, i.e. num_vertices() or
|
|
141
|
+
# num_edges().
|
|
142
|
+
#
|
|
143
|
+
# Each graph is an enumerable of vertices.
|
|
144
|
+
module Graph
|
|
145
|
+
include Enumerable
|
|
146
|
+
include Edge
|
|
147
|
+
|
|
148
|
+
# The each_vertex iterator defines the set of vertices. This method must be
|
|
149
|
+
# defined be concrete graph classes. It defines the BGL VertexListGraph
|
|
150
|
+
# concept.
|
|
151
|
+
def each_vertex
|
|
152
|
+
raise NotImplementedError
|
|
153
|
+
yield v # for RDoc
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# The each_adjacent iterator defines the out edges of vertex _v_. This
|
|
157
|
+
# method must be defined be concrete graph classes. Its defines the BGL
|
|
158
|
+
# IncidenceGraph concept.
|
|
159
|
+
def each_adjacent (v)
|
|
160
|
+
raise NotImplementedError
|
|
161
|
+
yield u # for RDoc
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# The each_edge iterator should provide efficient access to all edges of the
|
|
165
|
+
# graph. Its defines the EdgeListGraph concept.
|
|
166
|
+
#
|
|
167
|
+
# This method must _not_ be defined be concrete graph classes, because it
|
|
168
|
+
# can be implemented using each_vertex and each_adjacent. However for
|
|
169
|
+
# undirected graph the function is inefficient because we must may not yield
|
|
170
|
+
# (v,u) if we already visited edge (u,v).
|
|
171
|
+
def each_edge (&block)
|
|
172
|
+
if directed?
|
|
173
|
+
each_vertex { |u|
|
|
174
|
+
each_adjacent(u) { |v| yield u,v }
|
|
175
|
+
}
|
|
176
|
+
else
|
|
177
|
+
each_edge_aux(&block) # concrete graphs should to this better
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Vertices get enumerated. A graph is thus an enumerable of vertices.
|
|
182
|
+
# ---
|
|
183
|
+
# === Testing
|
|
184
|
+
def each(&block); each_vertex(&block); end
|
|
185
|
+
|
|
186
|
+
# Is the graph directed? The default returns false.
|
|
187
|
+
def directed?; false; end
|
|
188
|
+
|
|
189
|
+
# Returns true if _v_ is a vertex of the graph. Same as include? inherited
|
|
190
|
+
# from enumerable. Complexity is O(num_vertices) by default. Concrete graph
|
|
191
|
+
# may bee better here (see AdjacencyGraph).
|
|
192
|
+
def has_vertex?(v); include?(v); end # inherited from enumerable
|
|
193
|
+
|
|
194
|
+
# Returns true if the graph has no vertex, i.e. num_vertices == 0.
|
|
195
|
+
# ---
|
|
196
|
+
# === accessing vertices and edges
|
|
197
|
+
def empty?; num_vertices.zero?; end
|
|
198
|
+
|
|
199
|
+
# Return the array of vertices. Synonym for to_a inherited by enumerable.
|
|
200
|
+
def vertices; to_a; end
|
|
201
|
+
|
|
202
|
+
# Returns the class for edges: DirectedEdge or UnDirectedEdge.
|
|
203
|
+
def edge_class; directed? ? DirectedEdge : UnDirectedEdge; end
|
|
204
|
+
|
|
205
|
+
# Return the array of edges (DirectedEdge or UnDirectedEdge) of the graph
|
|
206
|
+
# using each_edge, depending whether the graph is directed or not.
|
|
207
|
+
def edges
|
|
208
|
+
result = []
|
|
209
|
+
c = edge_class
|
|
210
|
+
each_edge { |u,v| result << c.new(u,v) }
|
|
211
|
+
result
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Returns an array of vertices adjacent to vertex _v_.
|
|
215
|
+
def adjacent_vertices (v)
|
|
216
|
+
r = []
|
|
217
|
+
each_adjacent(v) {|u| r << u}
|
|
218
|
+
r
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Returns the number of out-edges (for directed graphs) or the number of incident
|
|
222
|
+
# edges (for undirected graphs) of vertex _v_.
|
|
223
|
+
def out_degree (v)
|
|
224
|
+
r = 0
|
|
225
|
+
each_adjacent(v) { |u| r += 1}
|
|
226
|
+
r
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Returns the number of vertices.
|
|
230
|
+
def size # Why not in Enumerable?
|
|
231
|
+
#inject(0) { |n, v| n + 1 } # inject not yet available in Enumerable!
|
|
232
|
+
r = 0; each_vertex {|v| r +=1}; r
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Synonym for size.
|
|
236
|
+
def num_vertices; size; end
|
|
237
|
+
|
|
238
|
+
# Returns the number of edges.
|
|
239
|
+
def num_edges; r = 0; each_edge {|u,v| r +=1}; r; end
|
|
240
|
+
|
|
241
|
+
# Utility method to show a string representation of the edges of the graph.
|
|
242
|
+
def to_s
|
|
243
|
+
edges.sort.to_s
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
private
|
|
247
|
+
|
|
248
|
+
def each_edge_aux
|
|
249
|
+
# needed in each_edge
|
|
250
|
+
visited = Hash.new
|
|
251
|
+
each_vertex { |u|
|
|
252
|
+
each_adjacent(u) { |v|
|
|
253
|
+
edge = UnDirectedEdge.new u,v
|
|
254
|
+
unless visited.has_key? edge
|
|
255
|
+
visited[edge]=true
|
|
256
|
+
yield u, v
|
|
257
|
+
end
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
end
|
|
261
|
+
end # module Graph
|
|
262
|
+
|
|
263
|
+
# BGL defines the concept BidirectionalGraph as follows:
|
|
264
|
+
#
|
|
265
|
+
# The BidirectionalGraph concept refines IncidenceGraph and adds the
|
|
266
|
+
# requirement for efficient access to the in-edges of each vertex. This
|
|
267
|
+
# concept is separated from IncidenceGraph because for directed graphs
|
|
268
|
+
# efficient access to in-edges typically requires more storage space, and many
|
|
269
|
+
# algorithms do not require access to in-edges. For undirected graphs this is
|
|
270
|
+
# not an issue, since the in_edges() and out_edges() functions are the same,
|
|
271
|
+
# they both return the edges incident to the vertex.
|
|
272
|
+
module BidirectionalGraph
|
|
273
|
+
include Graph
|
|
274
|
+
|
|
275
|
+
# Iterator providing access to the in-edges (for directed graphs) or incident
|
|
276
|
+
# edges (for undirected graphs) of vertex _v_. For both directed and
|
|
277
|
+
# undirected graphs, the target of an out-edge is required to be vertex _v_
|
|
278
|
+
# and the source is required to be a vertex that is adjacent to _v_.
|
|
279
|
+
def each_in_neighbor (v)
|
|
280
|
+
raise NotImplementedError
|
|
281
|
+
yield u
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# Returns the number of in-edges (for directed graphs) or the number of
|
|
285
|
+
# incident edges (for undirected graphs) of vertex _v_.
|
|
286
|
+
def in_degree (v)
|
|
287
|
+
r = 0;
|
|
288
|
+
each_in_neighbor(v) { |u| r += 1}
|
|
289
|
+
r
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# Returns the number of in-edges plus out-edges (for directed graphs) or the
|
|
293
|
+
# number of incident edges (for undirected graphs) of vertex _v_.
|
|
294
|
+
def degree (v)
|
|
295
|
+
in_degree(v) + out_degree(v)
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
end # module RGL
|
|
299
|
+
|