# How can I recover a graph from a graphical output in a notebook after resetting the kernel?

I have an old Mathematica notebook with an output for a graph structure $G$ I would like to recover. However, the routine for building up the graph is stochastic, so I can't simply rerun the code.

Can I recover the vertices and edges of a graph from its output in an old notebook after the kernel has been restarted?

More specifically, say I run the command:

G = RandomGraph[{50, 600}]


Which produces and graphical output that clearly can't be reconstructed by eye. I then quit the kernel. Can I recover the vertex and edges of $G$ using the output graphic?

-
The output of RandomGraph is not graphics, but an actual live graph object. You can pass it to other functions such as EdgeList. However, the output of GraphPlot is just graphics, not a Graph object. If you have a true Graph object, just use it. –  Szabolcs Apr 15 '13 at 17:15
@PlatoManiac I used Show[G] to display the graph. And it appears that EdgeRules fails? –  PinoAir Apr 15 '13 at 17:16
@Szabolcs Prior to quitting the kernel, I can click on the graph and get things like edge and vertex lists. Afterwards, it seems to become a graphics object? Is the data lost? –  PinoAir Apr 15 '13 at 17:17
No, the data should not be lost just because you quit. But if you use Show, then yes, it is lost. You can extract the Line objects from the graphs and try to reconstruct based on those. Theoretically it's possible, though it takes some work and manual tweaking. Use functions like Cases with level specifications to extract the data. –  Szabolcs Apr 15 '13 at 17:21
How old is "old"? –  Ｊ. Ｍ. Apr 15 '13 at 17:23

If you have a notebook with the following assignment:

g = Graph[{1 \[DirectedEdge] 2, 2 \[DirectedEdge] 3,
3 \[DirectedEdge] 1}, EdgeShapeFunction -> "CarvedArcArrow"]


And the output is visible (note that Head[g] is Graph not Graphics

and then you kill the kernel so that g is no longer assigned, you can retrieve the original graph by doing the following:

1. Select the cell containing the Graph object
2. Press CTRL-SHIFT-E
3. Copy the cell formatting text into a new symbol and evaluate this cell (e.g. newg)
4. In a new cell, execute CellPrint[newg]

The result of step 4 should be a copy of the original graph. Note I have only tried this with a few example graphs from the documentation, so it is possible that complex graphs cause some problems.

-
You can also copy/paste the graph object to the rhs of newg = . –  kguler Apr 13 at 1:06
@kguler right. I went straight for copy as and didn't think to take the simple route. –  bobthechemist Apr 13 at 1:38

To simulate the situation, evaluate the following expression and then quit the kernel:

$graph = RandomGraph[{50, 50}]  We can verify that $graph no longer holds the graph by observing its syntax coloring, or by evaluating it.

To recover the graph, enter and evaluate the following expression in a new input cell directly below the output cell that holds the rendered graph:

$recoveredGraph = ToExpression[First @ NotebookRead @ ExperimentalPreviousCell[], StandardForm];  We can now look at the graph's properties: VertexList @$recoveredGraph
(*
{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,
27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50}
*)

EdgeRules @ $recoveredGraph (* {1->6,1->12,1->43,2->15,2->20,2->50,3->11,3->24,4->21,4->50,5->49, 6->43,6->46,7->14,7->24,7->27,8->16,8->26,8->31,9->13,9->21,9->30, 9->31,10->35,11->31,11->38,14->32,14->35,14->45,15->36,17->18,17->20, 17->26,18->48,19->50,21->28,21->47,21->49,22->33,22->34,24->49, 26->27,30->35,36->48,37->44,37->49,38->49,41->44,45->50,48->49} *)$recoveredGraph // FullForm
(*
Graph[List[1,2,3,4,5,...],...]
*)


Recovering the Edge Rules from a Graphic

A comment on the question notes that the OP had used Show on the graph. If so, then the original graphics object is no longer contained in the output cell. In that event, $recoveredGraph would contain the Graphics object that renders the graph, but the Graph properties would be lost. It is possible to recover the edge rules from such a graphic using heuristic rules. First, we'll simulate the situation: $graph = RandomGraph[{50, 600}];

$shownGraph = Show @$graph;


$shownGraph now contains a graphic object generated from a graph. First, we will extract the coordinates of the lines and points in the graph: $lines = Cases[$shownGraph, _Line, Infinity][[1, 1]]; (* {{{0.117695, 0.70709}, {0.742439, 0.420549}}, ... } *)$points = Cases[$shownGraph, _DiskBox, Infinity][[All, 1]]; (* {{0.0873652, 0.721}, {0.772768, 0.406639}, ... } *)  Inspection will show that the line endpoints are not identical to the point positions. But they are mighty close. So we will use the heuristic of assuming that the point closest to a line endpoint is the position of the associated vertex. First, we will create a map from point coordinates to vertex numbers: $vertexMap = Thread[$points -> Range @ Length @$points];
(* {{0.0873652, 0.721} -> 1, {0.772768, 0.406639} -> 2, ...} *)


Then, we will use Nearest to apply this map to each line endpoint:

$recoveredEdgePairs = Map[Nearest[$vertexMap, #]&, $lines, {2}]; (* {{{1}, {2}}, {{1}, {3}}, {{1}, {4}}, ... *)  Finally, we will convert these pairs into rules $recoveredEdgeRules = $recoveredEdgePairs /. {{f_}, {t_}} :> (f->t) (* {1 -> 2, 1 -> 3, 1 -> 4, 1 -> 5, 1 -> 6, 1 -> 10, ...} *)  In this toy example, we can check whether the recovered rules match the original graph. $recoveredEdgeRules === EdgeRules @ \$graph
(* True *)
`

Of course, this last check does not work in the real situation and we just have to cross our fingers that the heuristic has worked. Note that this workflow presumes a certain structure for the graphic output -- something that could change from release to release, or even based upon the specific graph generation options. These steps are for version 9.

-