lib/rgl/topsort.rb
# topsort.rb
require 'rgl/graph_iterator'
module RGL
# Topological Sort Iterator
#
# The topological sort algorithm creates a linear ordering of the vertices
# such that if edge (u,v) appears in the graph, then u comes before v in
# the ordering. The graph must be a directed acyclic graph.
#
# The iterator can also be applied to an undirected graph or to a directed graph
# which contains a cycle. In this case, the iterator does not reach all
# vertices. The implementation of {Graph#acyclic?} uses this fact.
#
# @see Graph#topsort_iterator
class TopsortIterator
include GraphIterator
def initialize(g)
super(g)
set_to_begin
end
def set_to_begin
@waiting = Array.new
@inDegrees = Hash.new(0)
graph.each_vertex do |u|
@inDegrees[u] = 0 unless @inDegrees.has_key?(u)
graph.each_adjacent(u) do |v|
@inDegrees[v] += 1
end
end
@inDegrees.each_pair do |v, indegree|
@waiting.push(v) if indegree.zero?
end
end
# @private
def basic_forward
u = @waiting.pop
graph.each_adjacent(u) do |v|
@inDegrees[v] -= 1
@waiting.push(v) if @inDegrees[v].zero?
end
u
end
def at_beginning?
true
end
def at_end?
@waiting.empty?
end
end # class TopsortIterator
module Graph
# @return [TopsortIterator] for the graph.
#
def topsort_iterator
TopsortIterator.new(self)
end
# Returns true if the graph contains no cycles. This is only meaningful
# for directed graphs. Returns false for undirected graphs.
#
def acyclic?
topsort_iterator.length == num_vertices
end
end # module Graph
end # module RGL