This code is a non-recursive modification of this algorithm to detect cycles in directed graphs. It's intended to be used with Graph::Directed, but it should be easy to convert it to other graph modules.
I've put some tests at the bottom of the file, to make it easy to see if it works (and how to use it).
Hope this is usefull,
Joost.
Update: replace tabs with spaces to fix indenting.
#!/usr/local/bin/perl5.8.2 -w use strict; use Test::More tests => 5; BEGIN { use_ok('Graph::Directed'); } # returns a graph cointaining all vertices that are in one # or more cycles. sub cycles { my $G = shift; my $H = $G->copy; return reduce_to_cycles($H); } # reduce_to_cycles() modifies the input graph, use cycles() to make # a copy first. sub reduce_to_cycles { my $G = shift; while ($G->vertices) { # get the 'end' vertices my @ends = grep { ! $G->out_edges($_) or ! $G->in_edges($_) } +$G->vertices; if (@ends) { # remove 'end' vertices, and repeat $G->delete_vertices(@ends); next; } else { # Graph is not empty, but also has no end vertices # any more, so we're left with cycles... return $G; } } return $G; } # tests my $G = Graph::Directed->new; is(cycles($G)->vertices,0,"Empty graph"); $G->add_vertices('a' .. 'b'); is(cycles($G)->vertices,0,"No edges"); my $last = 'd'; for ('a' .. 'd') { $G->add_edge($last,$_); $last = $_; } is(cycles($G)->vertices,4,"Square"); $G->add_edges('e','a','d','f'); # one 'pointing in' and one 'pointing +out' is(cycles($G)->vertices,4,"End points");
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Detecting cyclic graphs
by bsb (Priest) on Jan 06, 2004 at 08:48 UTC |