package Graph
::Traversal
;
Graph::Traversal - graph traversal
$s = Graph::Traversal->new($G, %param)
Returns a new graph search object for the graph $G
and the parameters %param.
Usually not used directly but instead via frontends like
Graph::DFS for depth-first searching and Graph::BFS for
$dfs = Graph::DFS->new($G, %param)
$bfs = Graph::BFS->new($G, %param)
I<%param documentation to be written>
Resets a graph search object $S to its initial state.
@
{ $S->{ pool
} }{ $G->vertices } = ( );
$S->{ active_list
} = [ ];
$S->{ preorder_list
} = [ ];
$S->{ postorder_list
} = [ ];
$S->{ active_pool
} = { };
$S->{ vertex_found
} = { };
$S->{ vertex_root
} = { };
$S->{ vertex_successors
} = { };
# $o = $S->_get_next_root_vertex(\%param)
# Returns a vertex hopefully suitable as a root vertex of a tree.
# If $param->{ get_next_root } exists, it will be used the determine
# the root. If it is a code reference, the result of running it
# with parameters ($S, %param) will be the next root. Otherwise
# it is assumed to be the next root vertex as it is.
# Otherwise an unseen vertex having the maximal out-degree
sub _get_next_root_vertex
{
my %param = ( %{ $S->{ param
} }, @_ ?
%{ $_[0] } : ( ));
if ( exists $param{ get_next_root
} ) {
if ( ref $param{ get_next_root
} eq 'CODE' ) {
return $param{ get_next_root
}->( $S, %param ); # Dynamic.
my $get_next_root = $param{ get_next_root
}; # Static.
delete $S->{ param
}->{ get_next_root
};
delete $_[0]->{ get_next_root
} if @_;
return $G->largest_out_degree( keys %{ $S->{ pool
} } );
# $S->_mark_vertex_found( $u )
# Marks the vertex $u as a new vertex in the search object $S.
$S->{ vertex_found
}->{ $u } = $S->{ when }++;
delete $S->{ pool
}->{ $u };
# $o = $S->_next_state(%param)
# Returns a graph search object.
my $S = shift; # The current state.
my $G = $S->{ G
}; # The current graph.
my %param = ( %{ $S->{ param
} }, @_);
my ($u, $v); # The current vertex and its successor.
my $return = 0; # Return when this becomes true.
# Initialize our search when needed.
unless ( @
{ $S->{ active_list
} } ) {
$u = $S->_get_next_root_vertex(\
%param);
return wantarray ?
( ) : $u unless defined $u;
} while exists $S->{ vertex_found
}->{ $u };
# A new root vertex found.
push @
{ $S->{ active_list
} }, $u;
$S->{ active_pool
}->{ $u } = 1;
push @
{ $S->{ root_list
} }, $u;
$S->{ vertex_root
}->{ $u } = $#{ $S->{ root_list } };
# Get the current vertex.
$u = $param{ current
}->( $S );
return wantarray ?
() : $u unless defined $u;
# Record the vertex if necessary.
unless ( exists $S->{ vertex_found
}->{ $u } ) {
$S->_mark_vertex_found( $u );
push @
{ $S->{ preorder_list
} }, $u;
$return++ if $param{ return_next_preorder
};
# Initialized the list successors if necessary.
$S->{ vertex_successors
}->{ $u } = [ $G->successors( $u ) ]
unless exists $S->{ vertex_successors
}->{ $u };
# Get the next successor vertex.
$v = shift @
{ $S->{ vertex_successors
}->{ $u } };
# Something to do for each successor?
$param{ successor
}->( $u, $v, $S )
if exists $param{ successor
};
unless ( exists $S->{ vertex_found
}->{ $v } ) {
$S->_mark_vertex_found( $v );
push @
{ $S->{ preorder_list
} }, $v;
$S->{ vertex_root
}->{ $v } = $S->{ vertex_root
}->{ $u };
push @
{ $S->{ active_list
} }, $v;
$S->{ active_pool
}->{ $v } = 1;
# Something to for each unseen edge?
# For multiedges, triggered only for the first edge.
$param{ unseen_successor
}->( $u, $v, $S )
if exists $param{ unseen_successor
};
# Something to do for each seen edge?
# For multiedges, triggered for the 2nd, etc, edges.
$param{ seen_successor
}->( $u, $v, $S )
if exists $param{ seen_successor
};
$return++ if $param{ return_next_edge
};
} elsif ( not exists $S->{ vertex_finished
}->{ $u } ) {
# Finish off with this vertex (we run out of descendants).
$param{ finish
}->( $S );
$S->{ vertex_finished
}->{ $u } = $S->{ when }++;
push @
{ $S->{ postorder_list
} }, $u;
delete $S->{ active_pool
}->{ $u };
$return++ if $param{ return_next_postorder
};
# Return an edge if so asked.
return ( $u, $v ) if $param{ return_next_edge
};
Returns the next vertex in preorder of the graph
encapsulated within the search object $s.
$S->_next_state( return_next_preorder
=> 1, @_ );
Returns the next vertex in postorder of the graph
encapsulated within the search object $S.
$S->_next_state( return_next_postorder
=> 1, @_ );
Returns the vertices of the next edge of the graph
encapsulated within the search object $s.
$S->_next_state( return_next_edge
=> 1, @_ );
Returns all the vertices in preorder of the graph
encapsulated within the search object $S.
1 while defined $S->next_preorder; # Process entire graph.
return @
{ $S->{ preorder_list
} };
Returns all the vertices in postorder of the graph
encapsulated within the search object $S.
1 while defined $S->next_postorder; # Process entire graph.
return @
{ $S->{ postorder_list
} };
Returns all the edges of the graph
encapsulated within the search object $S.
push @E, $u, $v while ($u, $v) = $S->next_edge;
Returns all the root vertices of the trees of
the graph encapsulated within the search object $S.
"The root vertices" is ambiguous: what really happens
is that either the roots from the previous search made
on the $s are returned; or a preorder search is done
and the roots of this search are returned.
unless exists $S->{ preorder_list
} and
@
{ $S->{ preorder_list
} } == $S->{ G
}->vertices;
return @
{ $S->{ root_list
} };
Returns as a hash of ($vertex, index) pairs where index is an index
into the vertex_root list of the traversal.
"The root vertices" is ambiguous; see the documentation of the roots()
(This is the old vertex_roots().)
unless exists $S->{ preorder_list
} and
@
{ $S->{ preorder_list
} } == $G->vertices;
map { ( $_, $S->{ vertex_root
}->{ $_ } ) } $G->vertices;
Returns as a hash of ($vertex, $root) pairs all the vertices
and the root vertices of their search trees of the graph
encapsulated within the search object $S.
"The root vertices" is ambiguous; see the documentation of
the roots() method for more details.
(See also _vertex_roots()).
unless exists $S->{ preorder_list
} and
@
{ $S->{ preorder_list
} } == $G->vertices;
map { ( $_, $S->{root_list
}[$S->{ vertex_root
}->{ $_ }] ) }
delete $S->{ G
}; # Release the graph.
Copyright 1999, O'Reilly & Associates.
This code is distributed under the same copyright terms as Perl itself.