Graph.0.69 Module---how to get a DAG from graph with cycles

Ask a Question related to PERL Modules, Design and Development.

  1. #1

    Default Graph.0.69 Module---how to get a DAG from graph with cycles

    Here I use an example to illustrate the problem I met when using Graph
    Theory Module: I have a directed graph looks like the following (see the
    figure).
    Edges in the original directed graph:
    [main] -> [foo]; [main] -> [bar];
    [foo] -> [trouble];
    [trouble] -> [foo];

    I want to find all the cycles in the graph. whenever I find a cycle, I
    want to break it by deleting an edge starting from a vertex farthest
    away from node [main] to get the following graph ---in this case,
    deleting [trouble] -> [foo] because [trouble] is the farthest node in
    this cycle.
    So, edges after the desired manipulation are:
    [main] -> [foo]; [main] -> [bar];
    [foo] -> [trouble];
    -----------------------fiugre of original graph------------
    [main]
    / \
    [foo] [bar]
    / /
    / /
    [trouble]
    -----------------------end of the figure-------------------

    I tried to use @v = $g->connected_component_by_index($i), but it seems
    to return single nodes (which is deemed as strongly connected component
    itself), which is not what I want.
    $g->find_a_cycle does not work either, because it returns same cycle no
    matter how many times you call it.

    I am newbie in perl. Can someone give me a suggestion how to utilize
    the existing APIs in Graph.0.69 to achieve what I want?
    Here is what I experimented a bit(which failed), and it may give a
    better background of my question.

    ================================================== ==================
    #mycode.pl
    6
    7 use Graph;
    8 my $gcall = Graph->new;
    11
    12 while (<>) {
    13 chomp;
    14 if (/^(.*)\t->\t(.*)\t=>\w*\t->(\d*)/) {
    15 $gcall->add_edge($1, $2);
    16 print $1, " to ", $2, " with ", $3, "\n";
    17 #print $2, "\n";
    18 }
    19
    20 }
    21########at this point, the graph has been built#############
    46
    47 foreach (1..5) {
    48 print "SCC $_:",
    $gcall->strongly_connected_component_by_index($_), "\n\n";
    49 print "cycle $_:",
    $gcall->find_a_cycle;
    50}
    ######### my tries to try to report cycles, FAILED ####

    ================================================== ======================
    Sean Guest

  2. Similar Questions and Discussions

    1. Do we need Graph::Clique module?
      Hi, I am planning to implement an extension to Greg Bacon's implementation on clique reduction in a graph: ...
    2. GD::Graph - how to get rid of leading gap in line graph?
      Is there a way to get rid of the leading gap to the left of a line graph? Therefore, I want the graph line to start on the Y-axis, not the...
    3. Perl GD::Graph module: bug?
      While producing HTML Image MAP for the graph, I have found that th first line in linespoints graph type has suspicious coordinates o first line in...
    4. Proposed new module Graph::Timeline
      I am currently looking to create a Graph::Timeline module (similar in some respects to Image::Timeline) that would allow rendering timelines as...
    5. Finding cycles and Graph::Base
      William Goedicke <goedicke@goedsole.com> wrote: I don't know Graph::Base specifically, but an easy way to find cycles, if performance isn't a...
  3. #2

    Default Re: Graph.0.69 Module---how to get a DAG from graph with cycles

    In article <dr3c1l$gib$1@mailhub227.itcs.purdue.edu>, Sean
    <seanatpurdue@hotmail.com> wrote:
    > Here I use an example to illustrate the problem I met when using Graph
    > Theory Module: I have a directed graph looks like the following (see the
    > figure).
    > Edges in the original directed graph:
    > [main] -> [foo]; [main] -> [bar];
    > [foo] -> [trouble];
    > [trouble] -> [foo];
    >
    > I want to find all the cycles in the graph. whenever I find a cycle, I
    > want to break it by deleting an edge starting from a vertex farthest
    > away from node [main] to get the following graph ---in this case,
    > deleting [trouble] -> [foo] because [trouble] is the farthest node in
    > this cycle.
    > So, edges after the desired manipulation are:
    > [main] -> [foo]; [main] -> [bar];
    > [foo] -> [trouble];
    > -----------------------fiugre of original graph------------
    > [main]
    > / \
    > [foo] [bar]
    > / /
    > / /
    > [trouble]
    > -----------------------end of the figure-------------------
    >
    > I tried to use @v = $g->connected_component_by_index($i), but it seems
    > to return single nodes (which is deemed as strongly connected component
    > itself), which is not what I want.
    > $g->find_a_cycle does not work either, because it returns same cycle no
    > matter how many times you call it.
    >
    > I am newbie in perl. Can someone give me a suggestion how to utilize
    > the existing APIs in Graph.0.69 to achieve what I want?
    > Here is what I experimented a bit(which failed), and it may give a
    > better background of my question.
    >
    > ================================================== ==================
    > #mycode.pl
    > 6
    > 7 use Graph;
    > 8 my $gcall = Graph->new;
    > 11
    > 12 while (<>) {
    > 13 chomp;
    > 14 if (/^(.*)\t->\t(.*)\t=>\w*\t->(\d*)/) {
    > 15 $gcall->add_edge($1, $2);
    > 16 print $1, " to ", $2, " with ", $3, "\n";
    > 17 #print $2, "\n";
    > 18 }
    > 19
    > 20 }
    > 21########at this point, the graph has been built#############
    > 46
    > 47 foreach (1..5) {
    > 48 print "SCC $_:",
    > $gcall->strongly_connected_component_by_index($_), "\n\n";
    > 49 print "cycle $_:",
    > $gcall->find_a_cycle;
    > 50}
    > ######### my tries to try to report cycles, FAILED ####
    >
    > ================================================== ======================
    You have posted 19 lines of an at-least 50-line program, so your posted
    program is not complete. Also, you do not show your data. Here is a way
    to create a graph equivalent to your sample graph without reading
    external data:

    my $gcall = my $g = Graph->new( edges =>
    [ ['a','b'], ['a','c'], ['b','d'], ['d','b']] );

    Disclaimer: I don't know much about graphs, and I don't know about all
    the graph terminology used by the Graph module. In particular, I don't
    know what "connected" (strongly or weakly) means, so I don't know how
    that concept might be pertinent to your problem.

    It is true that Graph::find_a_cycle() will find a random cycle if one
    exists in your graph, and will only return one. However, if you then
    break that cycle by removing an edge, then you can go on to finding and
    breaking the next one.

    I am not sure how to find the vertex "farthest from node [main]" in
    cases more complex than your example. Here is a sample program that
    uses Graph::APSP_Floyd_Warshall() to find the "all pairs shortest
    paths" and Graph::path_length() to find the shortest path length from
    the root of the graph to any node. If these do not give the results you
    are looking for, then you will have to substitute some other method for
    picking which edge from a cycle of vertices to delete. The program adds
    a 3-vertex cycle to your original sample:

    #!/usr/local/bin/perl
    use strict;
    use warnings;
    use Graph;

    my $g = Graph->new(
    edges =>
    [
    ['a','b'],
    ['a','c'],
    ['b','d'],
    ['d','b'],
    ['c','e'],
    ['e','f'],
    ['f','c'],
    ]
    );

    print "Graph: ", $g->stringify(), "\n";
    my @v = sort $g->vertices();
    print "Vertices: @v\n";

    # find and remove all cycles
    while( my @cyc = $g->find_a_cycle() ) {
    print "\nFound cycle: @cyc\n";
    my $apsp = $g->APSP_Floyd_Warshall();
    my %dist = map { $_ => $apsp->path_length('a',$_) } @cyc;
    my $far = (sort { $dist{$a} <=> $dist{$b} } keys %dist )[-1];
    print "Farthest vertex is $far\n";
    CYC: for my $v ( @cyc ) {
    next if $v eq $far;
    next unless $g->has_edge($far,$v);
    print "Remove edge (${far}->$v)\n";
    $g->delete_edge($far,$v);
    print "Graph is now: ", $g->stringify(), "\n";
    last CYC;
    }
    }
    .... which gives as output:

    Graph: a-b,a-c,b-d,c-e,d-b,e-f,f-c
    Vertices: a b c d e f

    Found cycle: b d
    Farthest vertex is d
    Remove edge (d->b)
    Graph is now: a-b,a-c,b-d,c-e,e-f,f-c

    Found cycle: e f c
    Farthest vertex is f
    Remove edge (f->c)
    Graph is now: a-b,a-c,b-d,c-e,e-f

    __END__

    Note: this program can be made more efficient, but you should only
    worry about that if your graph is very large.

    Posted Via Usenet.com Premium Usenet Newsgroup Services
    ----------------------------------------------------------
    ** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
    ----------------------------------------------------------
    [url]http://www.usenet.com[/url]
    Jim Gibson Guest

  4. #3

    Default Re: Graph.0.69 Module---how to get a DAG from graph with cycles

    Hi Jim,
    Thanks so much for the prompt help. It is exactly what I wanted, and
    I'll port it to my program.

    Best regards,

    Jim Gibson wrote:
    > In article <dr3c1l$gib$1@mailhub227.itcs.purdue.edu>, Sean
    > <seanatpurdue@hotmail.com> wrote:
    >
    >
    >>Here I use an example to illustrate the problem I met when using Graph
    >>Theory Module: I have a directed graph looks like the following (see the
    >>figure).
    >>Edges in the original directed graph:
    >>[main] -> [foo]; [main] -> [bar];
    >>[foo] -> [trouble];
    >>[trouble] -> [foo];
    >>
    >>I want to find all the cycles in the graph. whenever I find a cycle, I
    >>want to break it by deleting an edge starting from a vertex farthest
    >>away from node [main] to get the following graph ---in this case,
    >>deleting [trouble] -> [foo] because [trouble] is the farthest node in
    >>this cycle.
    >>So, edges after the desired manipulation are:
    >>[main] -> [foo]; [main] -> [bar];
    >>[foo] -> [trouble];
    >>-----------------------fiugre of original graph------------
    >> [main]
    >> / \
    >> [foo] [bar]
    >> / /
    >> / /
    >> [trouble]
    >>-----------------------end of the figure-------------------
    >>
    >>I tried to use @v = $g->connected_component_by_index($i), but it seems
    >>to return single nodes (which is deemed as strongly connected component
    >>itself), which is not what I want.
    >>$g->find_a_cycle does not work either, because it returns same cycle no
    >>matter how many times you call it.
    >>
    >>I am newbie in perl. Can someone give me a suggestion how to utilize
    >>the existing APIs in Graph.0.69 to achieve what I want?
    >>Here is what I experimented a bit(which failed), and it may give a
    >>better background of my question.
    >>
    >>================================================ ====================
    >>#mycode.pl
    >> 6
    >> 7 use Graph;
    >> 8 my $gcall = Graph->new;
    >> 11
    >> 12 while (<>) {
    >> 13 chomp;
    >> 14 if (/^(.*)\t->\t(.*)\t=>\w*\t->(\d*)/) {
    >> 15 $gcall->add_edge($1, $2);
    >> 16 print $1, " to ", $2, " with ", $3, "\n";
    >> 17 #print $2, "\n";
    >> 18 }
    >> 19
    >> 20 }
    >> 21########at this point, the graph has been built#############
    >> 46
    >> 47 foreach (1..5) {
    >> 48 print "SCC $_:",
    >> $gcall->strongly_connected_component_by_index($_), "\n\n";
    >> 49 print "cycle $_:",
    >> $gcall->find_a_cycle;
    >> 50}
    >> ######### my tries to try to report cycles, FAILED ####
    >>
    >>================================================ ========================
    >
    >
    > You have posted 19 lines of an at-least 50-line program, so your posted
    > program is not complete. Also, you do not show your data. Here is a way
    > to create a graph equivalent to your sample graph without reading
    > external data:
    >
    > my $gcall = my $g = Graph->new( edges =>
    > [ ['a','b'], ['a','c'], ['b','d'], ['d','b']] );
    >
    > Disclaimer: I don't know much about graphs, and I don't know about all
    > the graph terminology used by the Graph module. In particular, I don't
    > know what "connected" (strongly or weakly) means, so I don't know how
    > that concept might be pertinent to your problem.
    >
    > It is true that Graph::find_a_cycle() will find a random cycle if one
    > exists in your graph, and will only return one. However, if you then
    > break that cycle by removing an edge, then you can go on to finding and
    > breaking the next one.
    >
    > I am not sure how to find the vertex "farthest from node [main]" in
    > cases more complex than your example. Here is a sample program that
    > uses Graph::APSP_Floyd_Warshall() to find the "all pairs shortest
    > paths" and Graph::path_length() to find the shortest path length from
    > the root of the graph to any node. If these do not give the results you
    > are looking for, then you will have to substitute some other method for
    > picking which edge from a cycle of vertices to delete. The program adds
    > a 3-vertex cycle to your original sample:
    >
    > #!/usr/local/bin/perl
    > use strict;
    > use warnings;
    > use Graph;
    >
    > my $g = Graph->new(
    > edges =>
    > [
    > ['a','b'],
    > ['a','c'],
    > ['b','d'],
    > ['d','b'],
    > ['c','e'],
    > ['e','f'],
    > ['f','c'],
    > ]
    > );
    >
    > print "Graph: ", $g->stringify(), "\n";
    > my @v = sort $g->vertices();
    > print "Vertices: @v\n";
    >
    > # find and remove all cycles
    > while( my @cyc = $g->find_a_cycle() ) {
    > print "\nFound cycle: @cyc\n";
    > my $apsp = $g->APSP_Floyd_Warshall();
    > my %dist = map { $_ => $apsp->path_length('a',$_) } @cyc;
    > my $far = (sort { $dist{$a} <=> $dist{$b} } keys %dist )[-1];
    > print "Farthest vertex is $far\n";
    > CYC: for my $v ( @cyc ) {
    > next if $v eq $far;
    > next unless $g->has_edge($far,$v);
    > print "Remove edge (${far}->$v)\n";
    > $g->delete_edge($far,$v);
    > print "Graph is now: ", $g->stringify(), "\n";
    > last CYC;
    > }
    > }
    > ... which gives as output:
    >
    > Graph: a-b,a-c,b-d,c-e,d-b,e-f,f-c
    > Vertices: a b c d e f
    >
    > Found cycle: b d
    > Farthest vertex is d
    > Remove edge (d->b)
    > Graph is now: a-b,a-c,b-d,c-e,e-f,f-c
    >
    > Found cycle: e f c
    > Farthest vertex is f
    > Remove edge (f->c)
    > Graph is now: a-b,a-c,b-d,c-e,e-f
    >
    > __END__
    >
    > Note: this program can be made more efficient, but you should only
    > worry about that if your graph is very large.
    >
    > Posted Via Usenet.com Premium Usenet Newsgroup Services
    > ----------------------------------------------------------
    > ** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
    > ----------------------------------------------------------
    > [url]http://www.usenet.com[/url]
    Sean Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139