How can I get all options of a function from IGraphM?

How can I get all options of a function from IGraphM?
For example, I want to retrieve the options for the function IGLayoutPlanar, but Options[IGLayoutPlanar] returns an empty list {}, even though I believe it does have some options. The documentation also doesn’t mention any options for this function.

This seems to apply to other functions in IGraphM as well. I suppose I could check the source code directly, but that’s a bit inconvenient.


Another question related to IGLayoutPlanar:
It seems to only work with simple graphs. Is there a way to make it work with multigraphs?
I’d like to display all parallel edges and show their labels as well.

Options: IGLayoutPlanar takes all options that Graph does and passes them on to Graph. This should be the case with all IGraph/M functions that produce a Graph expression. With the current design, only those options would appear in Options[IGLayoutPlanar] that are specific to IGLayoutPlanar, and there are no options like this at the moment.

The algorithm used here only produces vertex coordinates, not edge routing information. The vertex coordinates are chosen in such a way that straight-line edges would not intersect. Theoretically, with multigraphs, straight edges could be replaced with slightly curved ones, while avoiding intersections. But an infinitesimal separation between edges is not practically useful.

To be honest, I don’t think this layout is very useful in general, and the same applies to Mathematica’s built in planar layout. These layouts prove the points that intersections can be avoided, but they do not produce very readable figures, The Tutte layout is much better for that, but it only works for 3-vertex-connected graphs. If you have the time to work on extending the Tutte layout to more cases, that would be very welcome. I believe this is possible to some extent, but probably not easy.

If you want to extend this layout to a more practical multigraph one, you could subdivide each edge, re-do the layout, then use the coordinated of the dividing vertices to guide a BezierCurve. This is very straightforward, but it does take some amount of programming.

Since edge subdivision comes up so frequently, it would probably make sense to add a helper function to IGraph/M that does this.

I’m travelling at the moment, and unfortunately don’t have the time to implement a proof-of-concept of the subdivision idea. If you end up doing this, please post on this forum and show us what you got :slight_smile:

Thank you for the detailed answer.
I can do the subdivision and get the coordinates.
However, I’m not quite sure how to use BezierCurve.
For example, if the original edge is from a to b, then after subdivision, it becomes amid and midb.
I can get the coordinates of a, b, and mid from the planar layout,
and then replot each edge using BezierCurve with those coordinates.
I’ll give it a try and post the results sometime this week.

This is my attempt based on the guide. It seems to work, but it’s a bit messy though.

ClearAll[myIGLayoutPlanar];
Options[myIGLayoutPlanar]=Options[Graph];
myIGLayoutPlanar[g_Graph,opts:OptionsPattern[]]:=Module[{g1,rule,mapping,  newEdges,subdivideg,glayout,coords,coorToEdge, bezieredge},

g1=EdgeTaggedGraph[g];
(* subdivide *)
rule= {
DirectedEdge[u_, v_, l_] /; u =!= v :> With[{m = Unique[x]}, {DirectedEdge[u, m], DirectedEdge[m, v]}],
UndirectedEdge[u_, v_, l_] /; u =!= v :> With[{m = Unique[x]}, {UndirectedEdge[u, m], UndirectedEdge[m, v]}],
DirectedEdge[u_, u_, l_] :> With[{m = Unique[x], n = Unique[x]}, {DirectedEdge[u, m], DirectedEdge[m, n], DirectedEdge[n, u]}],
UndirectedEdge[u_, u_, l_] :>  With[{m = Unique[x], n = Unique[x]}, {UndirectedEdge[u, m], UndirectedEdge[m, n], UndirectedEdge[n, u]}] };

mapping =#->(#/.rule)&/@ EdgeList[g1] ;

newEdges=EdgeList[g1]/.mapping//Flatten;

subdivideg=Graph[Flatten[newEdges]];

glayout= IGLayoutPlanar[subdivideg];

(* get the coordinates *) 
coords=Thread[VertexList[glayout]->GraphEmbedding@glayout];

bezieredge[pts_,edge_]:=If[Head[edge]===UndirectedEdge, BezierCurve[Flatten[List@@@(edge/.mapping),1]/.coords],Arrow@BezierCurve[Flatten[List@@@(edge/.mapping),1]/.coords]];

EdgeTaggedGraph[EdgeList[g1], VertexCoordinates->(VertexList[g1]/.coords),EdgeShapeFunction->bezieredge, EdgeLabels->"EdgeTag",  PerformanceGoal -> "Quality"]
];

Test with undirected or directed multigraphs:

1 Like

Looks pretty cool, thanks for sharing the code! I’m excited to play with the code, but I’m swamped for another week.

1 Like