lib/rgl/mutable.rb
# mutable.rb
require 'rgl/base'
module RGL
# A MutableGraph can be changed via the addition or removal of edges and
# vertices.
#
module MutableGraph
include Graph
# Add a new vertex _v_ to the graph. If the vertex is already in the
# graph (tested via eql?), the method does nothing.
#
def add_vertex(v)
raise NotImplementedError
end
# Inserts the edge (u,v) into the graph.
#
# Note that for undirected graphs, (u,v) is the same edge as (v,u), so
# after a call to the function #add_edge, this implies that edge (u,v)
# will appear in the out-edges of u and (u,v) (or equivalently (v,u))
# will appear in the out-edges of v. Put another way, v will be adjacent
# to u and u will be adjacent to v.
#
def add_edge(u, v)
raise NotImplementedError
end
# Add all objects in _a_ to the vertex set.
#
def add_vertices(*a)
a.each { |v| add_vertex v }
end
# Add all edges in the _edges_ array to the edge set. Elements of the
# array can be both two-element arrays or instances of {Edge::DirectedEdge} or
# {Edge::UnDirectedEdge}.
#
def add_edges(*edges)
edges.each { |edge| add_edge(edge[0], edge[1]) }
end
# Remove u from the vertex set of the graph. All edges whose target is
# _v_ are also removed from the edge set of the graph.
#
# Postcondition: num_vertices is one less, _v_ no longer appears in the
# vertex set of the graph, and there no edge with source or target _v_.
#
def remove_vertex(v)
raise NotImplementedError
end
# Remove the edge (u,v) from the graph. If the graph allows parallel
# edges, this removes all occurrences of (u,v).
#
# Precondition: u and v are vertices in the graph.
# Postcondition: (u,v) is no longer in the edge set for g.
#
def remove_edge(u, v)
raise NotImplementedError
end
# Remove all vertices specified by the array a from the graph by calling
# {#remove_vertex}.
#
def remove_vertices(*a)
a.each { |v| remove_vertex v }
end
# Returns all minimum cycles that pass through a give vertex.
# The format is an Array of cycles, with each cycle being an Array
# of vertices in the cycle.
# @return [Array[Array]]
def cycles_with_vertex(vertex)
cycles_with_vertex_helper(vertex, vertex, [])
end
protected
def cycles_with_vertex_helper(vertex, start, visited)
adjacent_vertices(start).reject { |x| visited.include?(x) }.inject([]) do |acc, adj|
local_visited = Array.new(visited) << adj
acc << local_visited if (adj==vertex)
acc = acc + cycles_with_vertex_helper(vertex, adj, local_visited)
end
end
public
# @return [Array] of all minimum cycles in a graph
#
# This is not an efficient implementation O(n^4) and could
# be done using Minimum Spanning Trees. Hint. Hint.
#
def cycles
g = self.clone
self.inject([]) do |acc, v|
acc = acc.concat(g.cycles_with_vertex(v))
g.remove_vertex(v); acc
end
end
end # module MutableGraph
end # module RGL