I am trying to plot a directed planar graph in Maple but the command only accepts undirected graphs. The documentation does not mention this restriction. Is there a way to plot them in maple?
A small working example:
restart:
with(GraphTheory):
G:=Graph({{1,2},{2,3},{3,4}});
DrawPlanar(G);
This works but defines an undirected graph. By changing the {1,2} to [1,2], the edge is made directional and the DrawPlanar fails.
Does anyone know how to create a planar plot of a directed graph?
You could use the GraphTheory:-DrawGraph command.
The various display options of the DrawGraph command will not produce something laid out exactly like how DrawPlanar would do it.
I don't know of any reason for DrawPlanar to not support directed graphs; it just seems to be how it is programmed. I would suppose that DrawPlanar could be (re)programmed to use instead a mix of HasArc and HasEdge commands, etc, and attain the broader functionality.
Related
I am trying to draw a graph using Graphviz in Dot language, and this graph has edges which runs through nodes.
Please see the attached picture below.
So far I did not able to find a way to do this. Any help would be highly appreciated!.
Thanks in advance. ( Tips on any other way to render a graph like this would also be really helpful )
The information above is not that sufficient, however you can check the Drawing with Constrained ranks (Ref: Drawing graphs with dot by "Emden Gansner and Eleftherios Koutsofios and Stephen North").
Graph with constrained ranks
Please read the below for more information :Drawing graphs with dot
Had the same issue today, this worked for me in layout=dot.
(1) setting splines to false
(2) have the specific edge attribute constraint set to false, for edges which must go through another node.
splines=false
x -> y [constraint=false]
Be aware it only worked OK because I did not use a label for the edge.
Using the edge attributes taillabel and headlabel worked for me.
NetworkX is mostly for graph analysis, PyGraphviz mostly for drawing, and they're designed to work together. However, there's at least one respect in which NetworkX's graph drawing (via MatPlotLib) is superior to PyGraphviz's graph drawing (via Graphviz), namely that NetworkX has a spring layout algorithm (accessible via the spring_layout function) specifically for directed graphs while PyGraphviz has several spring layout algorithms (accessible via the neato program, and others) that lay out directed graphs as if they were undirected graphs. The only Graphviz / PyGraphviz layout program that really handles direction in a graph is dot, but dot creates hierarchical layouts, not force-directed layouts.
Here is an example that shows the difference between NetworkX and PyGraphviz for spring layouts of directed graphs:
import networkx as nx
import pygraphviz as pgv
import matplotlib.pyplot as ppt
edgelist = [(1,2),(1,9),(3,2),(3,9),(4,5),(4,6),(4,9),(5,9),(7,8),(7,9)]
nxd = nx.DiGraph()
nxu = nx.Graph()
gvd = pgv.AGraph(directed=True)
gvu = pgv.AGraph()
nxd.add_edges_from(edgelist)
nxu.add_edges_from(edgelist)
gvd.add_edges_from(edgelist)
gvu.add_edges_from(edgelist)
pos1 = nx.spring_layout(nxd)
nx.draw_networkx(nxd,pos1)
ppt.savefig('1_networkx_directed.png')
ppt.clf()
pos2 = nx.spring_layout(nxu)
nx.draw_networkx(nxu,pos2)
ppt.savefig('2_networkx_undirected.png')
ppt.clf()
gvd.layout(prog='neato')
gvd.draw('3_pygraphviz_directed.png')
gvu.layout(prog='neato')
gvu.draw('4_pygraphviz_undirected.png')
1_networkx_directed.png:(http://farm9.staticflickr.com/8516/8521343506_0c5d62e013.jpg)
2_networkx_undirected.png:(http://farm9.staticflickr.com/8246/8521343490_06ba1ec8e7.jpg)
3_pygraphviz_directed.png:(http://farm9.staticflickr.com/8365/8520231171_ef7784d983.jpg)
4_pygraphviz_undirected.png:(http://farm9.staticflickr.com/8093/8520231231_80c7eab443.jpg)
The third and fourth figures drawn are basically identical but for the arrowheads (the whole figure has been rotated, but apart from that, there's no difference). However, the first and second figures are differently laid out - and not just because NetworkX's layout algorithm introduces an element of randomness.
Repeatedly running the code above shows that this is not a chance occurrence. NetworkX's spring_layout function was apparently written on the assumption that if there is an arc from one node to another, the second node should be closer to the centre of the graph than the first (i.e. that if the graph described in edgelist is directed, node 2 should be closer to node 9 than nodes 1 and 3 are, node 6 should be closer to node 9 than node 4 is, and node 8 should be closer to node 9 than node 7 is; this doesn't always work perfectly as we see from nodes 4 and 5 in the first figure above, but that's a small issue compared to getting both 2 and 9 near the centre and the 'error' from my point of view is very slight). In other words, NetworkX's spring_layout is both hierarchical and force-directed.
That is a nice feature, because it makes core/periphery structures more obvious in directed graphs (where, depending on the assumptions you're working with, nodes without incoming arcs can be considered to be part of the periphery even if they have large numbers of outgoing arcs). #skyebend has explained below why most layout algorithms treat directed graphs as if they were undirected, but the graphs above show (a) that NetworkX treats them differently, and (b) that it does so in a principled way that is helpful for analysis.
Can this be replicated using PyGraphviz / Graphviz?
Unfortunately the documentation and the commented source code for NetworkX's spring_layout (actually fruchterman_reingold_layout) function provide no clue as to why NetworkX produces the result that it does.
This is the result of using PyGraphviz to draw the network using the NetworkX spring_layout function (see my own answer to this question below).
5_pygraphviz_plus_networkx.png:
(http://farm9.staticflickr.com/8378/8520231183_e7dfe21ab4.jpg)
Okay, I think I figured it out so I'm going to answer my own question. I don't think it can be done in PyGraphviz per se. However, one can instruct PyGraphviz to take the node positions from NetworkX but peg them (using !) so that the neato program is prevented from actually doing anything except rubber-stamping the node positions calculated by spring_layout. Add the following lines of code to the above:
for k,v in pos1.iteritems():
gvd.get_node(k).attr['pos']='{},{}!'.format(v[0]*10,v[1]*10)
gvd.layout(prog='neato')
gvd.draw('5_pygraphviz_plus_networkx.png')
The result is not perfect -- I had to multiply the co-ordinates by 10 in order to stop the nodes from being drawn on top of each other, which is (obviously) a kludge -- but it's an improvement, i.e. the nodes with 0 indegree are on the outside (benefit of laying out with NetworkX) and there are proper arrowheads that don't get swallowed up by the nodes themselves (benefit of drawing with PyGraphviz).
I am aware that this isn't strictly what I asked for, though (i.e. a solution using PyGraphviz / Graphviz itself).
If somebody can provide a better solution I'll be happy!
EDIT: Nobody's provided a better solution to the problem as articulated above, so I'm going to accept my own answer to signal that it actually works. However, I'm also voting up skyebend's answer because - although it doesn't solve the problem - it's a very useful contribution to understanding the underlying issues.
Graphviz also has an fdp and sfdp layout mode for doing force directed placement of nodes which is analogous to a spring layout. I'm not familiar with NetworkX, but it seems gvu.layout(prog='fdp') might work? If NetworkX allows passing additional arguments to Graphviz there are a number of configurable layout parameters you could tweak that may give you a layout closer to what you want. See Graphviz docs: http://www.graphviz.org/content/attrs
However, the fdp layouts treat the network as an undirected graph. Most 'spring' layouts I know of also treat networks as undirected because they must transform them into a Euclidean space (the screen) in which distances are symmetric. One exception would be 'magnetic' spring layouts which also attempt to align arcs so they are pointing in a similar direction to convey hierarchy, as a sort neato/dot hybrid.
Algorithm implementations may also differ in how they transform the network distances in an directed network to undirected weights/distances to be optimized by the layout. You may want to do this step explicitly yourself if you want more control over the way directed arcs are interpreted.
Using iGraph, how can I represent self-reflexive nodes with circle shaped curves? By default, these curves are represented by a pinched or tear drop shaped loop.
As Spacedman said, you would need to do quite some programming to do this. You could plot a graph without self-loops and then add them (graphs are basically a scatterplot and you can use points and similar functions to add lines to them), but this is not trivial (especially since you need to know the edge of nodes, not their center) and will cause the selfloops to be plotted on top of everything else which might not look good.
This weekend I have updated qgraph with how self-loops work. qgraph can be used to plot networks and should play nicely with igraph. e.g.:
# An adjacency matrix:
A <- matrix(1,3,3)
library("igraph")
# igraph graph and layout:
Graph <- graph.adjacency(A)
Layout <- layout.circle(Graph)
# Plot in qgraph:
library("qgraph")
qgraph(get.adjacency(Graph,sparse=FALSE),layout=Layout,diag=TRUE,directed=TRUE)
I am quite content with how these self-loops turned out and they seem to be more to what you describe. So this could be an option. However, my loops are just as hardcoded. For reference, I compute the edge of a node (starting and ending point of the loop) with the inner function qgraph:::Cent2Edge and compute the shape of the loop (spline) with the inner function qgraph:::SelfLoop.
Inside plot.igraph you can see that loops are drawn using a plot.bezier function, and all the control for that is pretty much hard coded there. You'd have to rewrite large chunks of plot.igraph to call a plot.circle function you'd have to write to do this.
Also, I'm guessing you don't want complete circles, but circle segments that start on the edge of the vertex symbol (the default blue circle with the vertex number in it) and end (possibly with an arrowhead) on another part of the edge of the vertex symbol? Or do you want circles that touch the symbol like the bezier teardrop loops do?
Either way, the answer seems to be 'no, not without doing some programming or submitting a feature request to the igraph guys'
I posted an earlier answer saying the layout functions were involved, but that's not true - the layout functions only position the vertices, and it is plot.igraph's job to draw the edges.
I'd like to be able to draw arcs between edges in graphs, as shown in the example below -- I'm using them to communicate information about the parameterizations of graphical models, and doing it by hand gets pretty old.
I've been using graphviz, which doesn't appear to supports that kind of annotation (if the answer confirming my fears at Connecting arcs between lines in Dot (GraphViz) isn't correct, that would make my day -- I really do need proper arcs and not the workaround the answer offers.) Are there any libraries (such as the JUNG library for Java) or tools that would make this possible?
Thanks,
Chris
You could consider reading in the layouted text output from dot, rendering the graph yourself and adding your annotation automatically. That would at least save you the (considerable) effort of implementing a routing algorithm.
I have a small library of a few shortest path search algorithms. They were developed for simple undirected graphs (the normal representation - vertices and edges). Now I'd like to somehow apply them on a bit different scenario - where the maps are represented as 2-dimensional shapes, connected by shared edges (edges of the polygons, that is). In this scenario, the search can start/end either at a map object or some point (x,y). What would be the best approach? Try to apply the algorithms onto shapes? or try to extract a 'normal' graph out of the shapes (I have preprocessing time available)? Any advice would be much appreciated, as I'm really not sure which way to go, and I don't have enough time (and skill) to explore many options...
Thanks a lot
What's the "path" you're looking for? A list of the shapes to traverse? (Otherwise you just draw a straight line between start+end points.)
It's easy to preprocess it into a format where the shapes are vertices and are connected by edges when the shapes share a polygon side. Then, just pass it off to your existing library to get the answer.