lib/rgl/adjacency.rb in rgl-0.2.2 vs lib/rgl/adjacency.rb in rgl-0.2.3
- old
+ new
@@ -1,151 +1,184 @@
+# adjacency.rb
#
-# $Id: adjacency.rb,v 1.4 2002/11/10 21:21:20 monora Exp $
+# $Id: adjacency.rb,v 1.7 2005/03/30 21:25:34 monora Exp $
#
# The DirectedAdjacencyGraph class implements a generalized adjacency list
-# graph structure. An AdjacencyGraph is basically a two-dimensional structure,
-# where each element of the first dimension represents a vertex, and each of
-# the vertices contains a one-dimensional structure that is the list of all
-# adjacent vertices.
+# graph structure. An AdjacencyGraph is basically a two-dimensional structure
+# (ie, a list of lists). Each element of the first dimension represents a
+# vertex. Each of the vertices contains a one-dimensional structure that is
+# the list of all adjacent vertices.
#
-# The class for representing the adjacency list of a vertex is by default a
-# Set, but can be configured by the client when a AdjacencyGraph is created.
+# The class for representing the adjacency list of a vertex is, by default, a
+# Set. This can be configured by the client, however, when an AdjacencyGraph
+# is created.
require 'rgl/mutable'
require 'set'
module RGL
+
class DirectedAdjacencyGraph
- include MutableGraph
- # Shortcut for creating a DirectedAdjacencyGraph:
- #
- # RGL::DirectedAdjacencyGraph[1,2, 2,3, 2,4, 4,5].edges.to_a.to_s =>
- # "(1-2)(2-3)(2-4)(4-5)"
- def self.[](*a)
- result = new
- 0.step(a.size-1,2) { |i| result.add_edge(a[i],a[i+1])}
- result
- end
+ include MutableGraph
- # Returns a new empty DirectedAdjacencyGraph which has as edgelist class the
- # given class. The default edgelist class is Set to ensure set semantics for
- # edges and vertices.
- def initialize(edgelist_class=Set)
- @edgelist_class = edgelist_class
- @vertice_dict = Hash.new
- end
+ # Shortcut for creating a DirectedAdjacencyGraph:
+ #
+ # RGL::DirectedAdjacencyGraph[1,2, 2,3, 2,4, 4,5].edges.to_a.to_s =>
+ # "(1-2)(2-3)(2-4)(4-5)"
- # Iterator for the keys of the vertice list hash.
- def each_vertex(&b)
- @vertice_dict.each_key(&b)
- end
+ def self.[] (*a)
+ result = new
+ 0.step(a.size-1, 2) { |i| result.add_edge(a[i], a[i+1]) }
+ result
+ end
- def each_adjacent(v, &b) # :nodoc:
- adjacency_list = @vertice_dict[v] or raise NoVertexError, "No vertex #{v}."
- adjacency_list.each(&b)
- end
+ # Returns a new empty DirectedAdjacencyGraph which has as its edgelist
+ # class the given class. The default edgelist class is Set, to ensure
+ # set semantics for edges and vertices.
- # Returns true.
- def directed?; true; end
+ def initialize (edgelist_class = Set)
+ @edgelist_class = edgelist_class
+ @vertice_dict = Hash.new
+ end
- # Complexity is O(1), since the vertices are kept in a Hash containing as
- # value the list of adjacent vertices of _v_.
- def has_vertex?(v); @vertice_dict.has_key?(v); end
+ # Iterator for the keys of the vertice list hash.
- # Complexity is O(1), if a Set is used as adjacency list, otherwise
- # O(out_degree(v))
- #
- # ---
- # MutableGraph interface.
- def has_edge? (u, v)
- has_vertex?(u) and @vertice_dict[u].include? v
- end
+ def each_vertex (&b)
+ @vertice_dict.each_key(&b)
+ end
- # See MutableGraph#add_vertex.
- #
- # If the vertex is already in (using eql?) the method does nothing.
- def add_vertex(v)
- @vertice_dict[v] ||= @edgelist_class.new
- end
+ def each_adjacent (v, &b) # :nodoc:
+ adjacency_list = @vertice_dict[v] or
+ raise NoVertexError, "No vertex #{v}."
+ adjacency_list.each(&b)
+ end
- # See MutableGraph#add_edge.
- def add_edge (u,v)
- add_vertex(u) # ensure key
- add_vertex(v) # ensure key
- basic_add_edge(u,v)
- end
+ # Returns true.
- # See MutableGraph#remove_vertex.
- def remove_vertex(v)
- @vertice_dict.delete(v)
-
- # remove v from all adjacency lists
- @vertice_dict.each_value { |adjList| adjList.delete(v) }
- end
+ def directed?
+ true
+ end
- # See MutableGraph::remove_edge.
- def remove_edge (u,v)
- @vertice_dict[u].delete(v) unless @vertice_dict[u].nil?
- end
+ # Complexity is O(1), because the vertices are kept in a Hash containing
+ # as values the lists of adjacent vertices of _v_.
- protected
+ def has_vertex? (v)
+ @vertice_dict.has_key?(v)
+ end
- def basic_add_edge(u,v)
- @vertice_dict[u].add v
- end
- end # class AdjacencyGraph
+ # Complexity is O(1), if a Set is used as adjacency list. Otherwise,
+ # complexity is O(out_degree(v)).
+ #
+ # ---
+ # MutableGraph interface.
- # AdjacencyGraph is an undirected Graph. The methods add_edge and remove_edge
- # are reimplemented: If an edge (u,v) is added or removed then the reverse
- # edge (v,u) is also added or removed.
- class AdjacencyGraph < DirectedAdjacencyGraph
- # Always returns false.
- def directed?; false; end
-
- # Also removes (v,u)
- def remove_edge (u,v)
- super
- @vertice_dict[v].delete(u) unless @vertice_dict[v].nil?
- end
+ def has_edge? (u, v)
+ has_vertex?(u) and @vertice_dict[u].include?(v)
+ end
- protected
- def basic_add_edge(u,v)
- super
- # Insert backwards edge
- @vertice_dict[v].add u
- end
- end
+ # See MutableGraph#add_vertex.
+ #
+ # If the vertex is already in the graph (using eql?), the method does
+ # nothing.
+ def add_vertex (v)
+ @vertice_dict[v] ||= @edgelist_class.new
+ end
+
+ # See MutableGraph#add_edge.
+
+ def add_edge (u, v)
+ add_vertex(u) # ensure key
+ add_vertex(v) # ensure key
+ basic_add_edge(u, v)
+ end
+
+ # See MutableGraph#remove_vertex.
+
+ def remove_vertex (v)
+ @vertice_dict.delete(v)
+
+ # remove v from all adjacency lists
+
+ @vertice_dict.each_value { |adjList| adjList.delete(v) }
+ end
+
+ # See MutableGraph::remove_edge.
+
+ def remove_edge (u, v)
+ @vertice_dict[u].delete(v) unless @vertice_dict[u].nil?
+ end
+
+ protected
+
+ def basic_add_edge (u, v)
+ @vertice_dict[u].add(v)
+ end
+
+ end # class DirectedAdjacencyGraph
+
+ # AdjacencyGraph is an undirected Graph. The methods add_edge and
+ # remove_edge are reimplemented: If an edge (u,v) is added or removed,
+ # then the reverse edge (v,u) is also added or removed.
+
+ class AdjacencyGraph < DirectedAdjacencyGraph
+
+ def directed? # Always returns false.
+ false
+ end
+
+ # Also removes (v,u)
+
+ def remove_edge (u, v)
+ super
+ @vertice_dict[v].delete(u) unless @vertice_dict[v].nil?
+ end
+
+ protected
+
+ def basic_add_edge (u,v)
+ super
+ @vertice_dict[v].add(u) # Insert backwards edge
+ end
+
+ end # class AdjacencyGraph
+
module Graph
- # Convert a general graph to an AdjacencyGraph. If the graph is directed
- # returns a DirectedAdjacencyGraph else a AdjacencyGraph.
- def to_adjacency
- result = (directed? ? DirectedAdjacencyGraph : AdjacencyGraph).new
- each_edge { |u,v| result.add_edge u,v }
- result
- end
- # Return a new DirectedAdjacencyGraph which has the same set of vertices. If
- # (u,v) is an edge of the graph then (v,u) is an edge of the result.
- #
- # If the graph is undirected the result is self.
- def reverse
- reurn self unless directed?
- result = DirectedAdjacencyGraph.new
- each_edge { |u,v| result.add_edge v,u }
- result
- end
+ # Convert a general graph to an AdjacencyGraph. If the graph is directed,
+ # returns a DirectedAdjacencyGraph; otherwise, returns an AdjacencyGraph.
- # Return a new AdjacencyGraph which has the same set of vertices. If (u,v)
- # is an edge of the graph (u,v) and (v,u) (which are the same edges) is an
- # edge of the result.
- #
- # If the graph is undirected the result is self.
- def to_undirected
- return self unless directed?
- result = AdjacencyGraph.new
- each_edge { |u,v| result.add_edge u,v }
- result
- end
- end
-end
+ def to_adjacency
+ result = (directed? ? DirectedAdjacencyGraph : AdjacencyGraph).new
+ each_edge { |u,v| result.add_edge(u, v) }
+ result
+ end
+
+ # Return a new DirectedAdjacencyGraph which has the same set of vertices.
+ # If (u,v) is an edge of the graph, then (v,u) is an edge of the result.
+ #
+ # If the graph is undirected, the result is self.
+
+ def reverse
+ return self unless directed?
+ result = DirectedAdjacencyGraph.new
+ each_vertex { |v| result.add_vertex v }
+ each_edge { |u,v| result.add_edge(v, u) }
+ result
+ end
+
+ # Return a new AdjacencyGraph which has the same set of vertices. If (u,v)
+ # is an edge of the graph, then (u,v) and (v,u) (which are the same edges)
+ # are edges of the result.
+ #
+ # If the graph is undirected, the result is self.
+
+ def to_undirected
+ return self unless directed?
+ result = AdjacencyGraph.new
+ each_edge { |u,v| result.add_edge(u, v) }
+ result
+ end
+
+ end # module Graph
+end # module RGL