Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent auto-layout of Graph[] objects in Mathematica 8

Some types of objects have special input/output formatting in Mathematica. This includes Graphics, raster images, and, as of Mathematica 8, graphs (Graph[]). Unfortunately large graphs may take a very long time to visualize, much longer than most other operations I'm doing on them during interactive work.

How can I prevent auto-layout of Graph[] objects in StandardForm and TraditionalForm, and have them displayed as e.g. -Graph-, preferably preserving the interpretability of the output (perhaps using Interpretation?). I think this will involve changing Format and/or MakeBoxes in some way, but I was unsuccessful in getting this to work.

I would like to do this in a reversible way, and preferably define a function that will return the original interactive graph display when applied to a Graph object (not the same as GraphPlot, which is not interactive).

On a related note, is there a way to retrieve Format/MakeBoxes definitions associated with certain symbols? FormatValues is one relevant function, but it is empty for Graph.

Sample session:

In[1]:= Graph[{1->2, 2->3, 3->1}]
Out[1]= -Graph-

In[2]:= interactiveGraphPlot[%] (* note that % works *)
Out[2]= (the usual interactive graph plot should be shown here)
like image 209
Szabolcs Avatar asked May 09 '11 14:05

Szabolcs


3 Answers

Though I do not have Mathematica 8 to try this in, one possibility is to use this construct:

Unprotect[Graph]

MakeBoxes[g_Graph, StandardForm] /; TrueQ[$short] ^:= 
 ToBoxes@Interpretation[Skeleton["Graph"], g]

$short = True;

Afterward, a Graph object should display in Skeleton form, and setting $short = False should restore default behavior.

Hopefully this works to automate the switching:

interactiveGraphPlot[g_Graph] := Block[{$short}, Print[g]]

Mark's concern about modifying Graph caused me to consider the option of using $PrePrint. I think this should also prevent the slow layout step from taking place. It may be more desirable, assuming you are not already using $PrePrint for something else.

$PrePrint = 
  If[TrueQ[$short], # /. _Graph -> Skeleton["Graph"], #] &;

$short = True

Also conveniently, at least with Graphics (again I cannot test with Graph in v7) you can get the graphic with simply Print. Here, shown with Graphics:

g = Plot[Sin[x], {x, 0, 2 Pi}]

(*  Out =  <<"Graphics">>  *)

Then

Print[g]

enter image description here

I left the $short test in place for easy switching via a global symbol, but one could leave it out and use:

    $PrePrint = # /. _Graph -> Skeleton["Graph"] &;

And then use $PrePrint = . to reset the default functionality.

like image 182
Mr.Wizard Avatar answered Oct 17 '22 09:10

Mr.Wizard


You can use GraphLayout option of Graph as well as graph-constructors to suppress the rendering. A graph can still be visualized with GraphPlot. Try the following

{gr1, gr2, gr3} = {RandomGraph[{100, 120}, GraphLayout -> None], 
  PetersenGraph[10, 3, GraphLayout -> None], 
  Graph[{1 -> 2, 2 -> 3, 3 -> 1}, GraphLayout -> None]}

enter image description here

In order to make working easier, you can use SetOptions to set GraphLayout option to None for all graph constructors you are interested in.

like image 37
Sasha Avatar answered Oct 17 '22 11:10

Sasha


Have you tried simply suppressing the output? I don't think that V8's Graph command does any layout, if you do so. To explore this, we can generate a large list of edges and compare the timings of graph[edges];, Graph[edges];, and GraphPlot[edges];

In[23]:= SeedRandom[1];
edges = Union[Rule @@@ (Sort /@ 
      RandomInteger[{1, 5000}, {50000, 2}])];

In[25]:= t = AbsoluteTime[];
graph[edges];

In[27]:= AbsoluteTime[] - t

Out[27]= 0.029354

In[28]:= t = AbsoluteTime[];
Graph[edges];

In[30]:= AbsoluteTime[] - t

Out[30]= 0.080434

In[31]:= t = AbsoluteTime[];
GraphPlot[edges];

In[33]:= AbsoluteTime[] - t

Out[33]= 4.934918

The inert graph command is, of course, the fastest. The Graph command takes much longer, but no where near as long as the GraphPlot command. Thus, it seems to me that Graph is not, in fact, computing the layout, as GraphPlot does.

The logical question is, what is Graph spending it's time on. Let's examine the InputForm of Graph output in a simple case:

Graph[{1 -> 2, 2 -> 3, 3 -> 1, 1 -> 4}] // InputForm

Out[123]//InputForm=
    Graph[{1, 2, 3, 4}, 
      {DirectedEdge[1, 2], 
       DirectedEdge[2, 3], 
       DirectedEdge[3, 1], 
       DirectedEdge[1, 4]}]

Note that the vertices of the graph have been determined and I think this is what Graph is doing. In fact, the amount of time it took to compute Graph[edges] in the first example, comparable to the fastest way that I can think to do this:

Union[Sequence @@@ edges]; // Timing

This took 0.087045 seconds.

like image 1
Mark McClure Avatar answered Oct 17 '22 10:10

Mark McClure