How can I reverse the direction of every edge in a Graphviz (dot language) graph?
Asked Answered
S

3

10

I have a directed graph specified in Graphviz's dot language, e.g.

digraph G { A -> B [label="foo"]; A -> B [label="bar"]; B -> A; C; }

I want to automatically process this into a graph with its edges reversed, i.e.

digraph G { B -> A [label="foo"]; B -> A [label="bar"]; A -> B; C; }

I would like to use a robust solution (i.e. one that understands the graph and therefore probably doesn't use sed) that preserves any existing edge labels and other attributes. Note that I am not merely talking about getting dot to render my graph with the arrows pointing backward; I really need a graph whose edges are reversed. (In this case, I intend to reverse the edges, apply prune, then reverse the edges again.)

How can I reverse the direction of every edge in a Graphviz (dot-language) graph?

Seam answered 13/4, 2012 at 20:7 Comment(0)
A
13

Easiest way is to include a graph-level dir statement where you reverse the direction of the arrows. By default, the direction is forward. If you reverse it at the top of your graph, then without changing a single other line, the graph will show up the way you want.

What you have now is this:

digraph G
{
    edge [dir="forward"]; /* implied */
    A -> B [label="foo"];
    A -> B [label="bar"];
    B -> A;
    C;
}

What you want is this:

digraph G
{
    edge [dir="back"]; /* note the change to this line */
    A -> B [label="foo"];
    A -> B [label="bar"];
    B -> A;
    C;
}
Amena answered 11/8, 2014 at 0:15 Comment(2)
I think you have to set the attribute on edges, not the whole graph. Like this: edge [dir="back"];Bowerbird
Yes, @ScottMcIntyre has it right: you have to put an edge [dir="back"]; directive at the beginning of the body of the graph for it to work.Mcmullen
S
2

The best I've come up with so far is

BEG_G {
    graph_t g = graph($.name + " reversed", "D");
    int edge_id = 0;
}

N {
    clone(g, $);
}

E {
    node_t newHead = clone(g, $.head);
    node_t newTail = clone(g, $.tail);
    edge_t newEdge = edge_sg(g, newHead, newTail, edge_id);
    copyA($, newEdge);
    edge_id++;
}

END_G {
    $O = g;
}

which I then invoke with gvpr.

This does add a "key" attribute to all resultant edges, but I'm not sure how to avoid that and still preserve multiple edges between the same pair of nodes.

When I do echo 'digraph G { A -> B [label="foo"]; A -> B [label="bar"]; B -> A; C; }' | gvpr -f reverseAllEdges.gvpr, I get:

digraph "G reversed" {
    A -> B [key=2];
    B -> A [key=0, label=foo];
    B -> A [key=1, label=bar];
    C;
}

I don't know how robust this will prove to be, but it looks promising.

Seam answered 13/4, 2012 at 20:13 Comment(0)
B
0

The Python library NetworkX has a directed multigraph type, MultiDiGraph, which has a reverse() method. It also uses pydot for loading and writing DOT files.

Bearskin answered 8/6, 2012 at 11:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.