Mixed directed/undirected graph [duplicate] - graphviz

For my application I need to represent simultaneously (on the same graph) two relations: one is simmetric, the other is not.
Targets:
Ideally the two relation should result in edges having different colors;
For the symmetric relation I would like not to have double-edges;
Is there a way of doing this with dot?

digraph {
A; B; C
subgraph Rel1 {
edge [dir=none, color=red]
A -> B -> C -> A
}
subgraph Rel2 {
edge [color=blue]
B -> C
C -> A
}
}

You can pass dir=none as an edge property to the undirected graph connections:
digraph {
A; B; C
A -> B
B -> C
C -> A [dir=none]
}

Related

Graphviz nested subgraph orientation

I recently came across the image below. I know it was created with graphviz/dot, but the source code is not available (lost to time).
Desired Output:
I have been trying to find a way to reverse engineer the source code, but the horizontal ordering of the nested subgraphs has been giving me difficulty. A bare minimum mostly-working example looks like this in code
digraph G {
A
B
subgraph cluster_0 {
edge [style=invis]
subgraph cluster_0_0 {
D -> E -> F
}
C -> D -> E -> F -> G
}
A -> C
A -> B
A -> G
B -> { D E F }
}
However, that gives me this output:
Adding newrank=true to the outer subgraph gives me the horizontal orientation I'm looking for:
digraph G {
A
B
subgraph cluster_0 {
newrank=true
edge [style=invis]
subgraph cluster_0_0 {
D -> E -> F
}
C -> D -> E -> F -> G
}
A -> C
A -> B
A -> G
B -> { D E F }
}
But this sets the nodes in the wrong order:
I hope there is a better solution, but here is one (the rest of the node labels should be evident):
digraph G {
newrank=true
splines=false // A->C edge gets wacky without this
node [shape=Mrecord]
// Mrecords produce this Warning:
// flat edge between adjacent nodes one of which has a record shape - replace records with HTML-like labels
// but Mrecords still seem to work, so maybe ignore warning ??
// hoped that ordering or weight or group attributes would
// position C and G as desired, but nope
// instead, clusters and constraint attribute worked, why?
A [group=T label="{Measure|4/4}"]
B [group=T]
A -> B
{
rank=same C F E D G // declare right-to-left ??
}
subgraph clusterCDEFG {
graph [style=rounded]
// within a rank, layout tends to be right-to-left
// so, declare right-to-left ??
// why do these clusters help position C & G ???
subgraph clusterG { peripheries=0
G
}
subgraph clusterDEF {
// declare right-to-left
F
E [group=T]
D
edge [style=invis]
// D -> E -> F
}
// why do these clusters help position C & G ???
subgraph clusterC { peripheries=0
C
}
}
A -> C [constraint=false] // why does this impact position within rank ??
A -> G [constraint=false] // why does this impact position within rank ??
B -> { F E D } // declare right-to-left ??
edge [style=invis]
// C -> D // Mrecord shape has problems
// F -> G // Mrecord shape has problems
}
Giving:

Graphviz enforce ordering between nodes of different levels

I have the following graph:
digraph {
stylesheet = "..."
subgraph cluster {
b; c; g;
{rank=same; b; g;}
}
a -> b;
b -> c;
c -> d;
c -> e;
f -> c;
{rank=same; a; f;}
}
Is there any way to force/encourage the edge f -> c to pass between nodes b and g? I've tried a number of different strategies and graphviz refuses to both:
keep b and g within the border, and
allow g to appear of to the side and not interfere with the rest of the graph.
Any suggestions would be much appreciated!
Indeed, the dot algorithm does not want to route the f->c edge as you want. However, the neato edge routing algorithm produces a closer result. So we use dot to position the nodes and neato -n to route the edges. Like so:
dot -Tdot myfile.gv >out.dot
neato -n -Tpng out.dot >myfile.png
Using this input:
digraph {
stylesheet = "https://g3doc.corp.google.com/frameworks/g3doc/includes/graphviz-style.css"
nodesep=.5 // optional
subgraph cluster {
b
c; g
{rank=same; b; g;}
}
f -> g [style=invis]
f:se -> c:nw [constraint=false]
a -> b;
b -> c;
c -> d;
c -> e;
}
Giving:
See https://graphviz.org/faq/#FaqDotWithNodeCoords
And https://graphviz.org/docs/outputs/canon/
(Close enough?)

In graphviz, can you bring two vertices closer together?

When describing a graph with graphviz, I sometimes find I want two vertices to appear closer together than the layout engine I chose places them. Is there a way to hint that I want them closer?
I'm mostly interested in the case of two connected vertices, so an answer specific to that case is fine.
Concrete example:
digraph G {
node [shape="circle"];
Start [shape="none" label=""];
C [shape="doublecircle"];
Start -> A;
A -> B [label="0,1"];
B -> C [label="0,1"];
C -> D [label="0,1"];
D -> D [label="0,1"];
}
I want the vertices Start and A to be closer.
You can't do that, but you can make nearly everything else twice as big, here is a start.
(But you can't increase the size of an edge to self)
digraph G {
rankdir=LR
edge[minlen=2 fontsize=28 arrowsize=2 penwidth=2]
node[fontsize=28 height=1 penwidth=2]
graph[fontsize=28 penwidth=2]
node [shape="circle"];
Start [shape="none" label=""];
C [shape="doublecircle"];
Start -> A[minlen=1]; // not twice the size to get the requested effect
A -> B [label="0,1"];
B -> C [label="0,1"];
C -> D [label="0,1"];
D -> D [label="0,1"];
}
[this answer applies specifically to dot]
there is no edge-level attribute that explicitly sets or changes edge length
the graph-level nodesep attribute sets minimum distance between two nodes of same rank
so:
digraph G {
nodesep=.17
{
rank=same
node [shape="circle"];
Start [shape="none" label=""];
C [shape="doublecircle"];
Start -> A;
A -> B [label="0,1"];
B -> C [label="0,1"];
C -> D [label="0,1"];
D -> D [label="0,1"];
}
}
produces:
To increase the distance between the other nodes, you can add spaces to the labels.
I'm not wild about it either, but this change:
B -> C [label=" 0,1 "]; // pad to make label (and edge) longer
produced this:

How to draw nodes at different "levels" in dot?

I would like to draw the following graph in dot:
How can this be done?
Use rank=same; to force this layout:
digraph example {
A -> B -> C -> D -> E;
{ rank = same {A, C, E}}
{ rank = same {B,D}}
}
Output:

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

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?
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;
}
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.
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.

Resources