Group Abstract Group Abstract

Message Boards Message Boards

0
|
8.6K Views
|
15 Replies
|
9 Total Likes
View groups...
Share
Share this post:

Plot Graph-objects with TreePlot?

Posted 9 years ago

According to the documentation, it should be possible to do a TreePlot[g] with some general Graph-object g. But this is not true. To make things worse, a Graph-object cannot be created from data suitable for TreePlot.

I have to create a graph g from some Depth-First-Search algorithm searching paths from some start-vertex to some end-vertex, draw it as a TreePlot, and then find and list paths from start to end by FindPath[g,start,end]. The algorithm records labeled edges of the graph, one after the other. (The graph is not really a tree, since in the last step all leaves end up in the same end-state, but this is not a problem for TreePlot).

Unfortunately such edges have to be recorded as

graphData={Labeled[vi->vj,label],...} for Graph, but as

graphData={{vi->vj,label},...} for TreePlot

and those two different notations are incompatible, i.e: the notation for Graph is not understood by TreePlot and the notation for TreePlot is not understood by Graph.

In the end I can either not draw a TreePlot or not create a Graph and FindPath from the same recorded data graphData.

Of course I could maintain both graphData-notations or convert one into the other. But why? For me the problem is, that TreePlot[g] does not accept general Graph-objects g. And this is a bug in Wolfram Language.

See the following code for tests. Actually I have the same problem with vertex labels, which is not elaborated here.

If[True, (* Test Graph (from Graph-Data) & TreePlot & FindPath *)
Block[{a, b1, b2, c, graphData, graph},

(* Define graphData as a labeled list of edges in a form suitable \
for Graph *)
Print[Style["1 Defining a graph by graphData suitable for Graph", 
Red, Bold]];
graphData = {Labeled[a -> b1, "a,b1"], Labeled[a -> b2, "a,b2"], 
b1 -> c, b2 -> c};
Echo[graphData, "1 graphData: "];
(* Make a Graph-object from graphData *)
graph = Graph[graphData];
Echo[Row[{Head[graph], " ", graph}], 
"1 make graph from graphData: "];
(* TreePlot and FindPath from graphData *)
Print[TreePlot[graphData, Left, a,
PlotLabel -> Style["1.1 TreePlot from graphData", Blue, Bold],
DirectedEdges -> True, VertexLabeling -> True, 
EdgeLabeling -> True]];
Print[Style[
Row[{"1.1 FindPath from graphData: All paths from a to c: ", 
FindPath[graphData, a, c, Infinity, All]}], Blue, Bold]];
(* TreePlot and FindPath from graph *)
Print[TreePlot[graph, Left, a,
PlotLabel -> Style["1.2 TreePlot from graph", Blue, Bold],
DirectedEdges -> True, VertexLabeling -> True, 
EdgeLabeling -> True]];
Print[Style[
Row[{"1.2 FindPath from graph: All paths from a to c: ", 
FindPath[graph, a, c, Infinity, All]}], Blue, Bold]];

(* Define graphData as a labeled list of edges in a Form suitable \
for TreePlot *)
Print[Style["2 Defining a graph by graphData suitable for TreePlot",
Red, Bold]];
graphData = {{a -> b1, "a,b1"}, {a -> b2, "a,b2"}, b1 -> c, b2 -> c};
Echo[graphData, "2 graphData: "];
(* Make a Graph-object from graphData *)
graph = Graph[graphData];
Echo[Row[{Head[graph], " ", graph}], 
"2 make graph from graphData: "];
(* TreePlot and FindPath from graphData *)
Print[TreePlot[graphData, Left, a,
PlotLabel -> Style["2.1 TreePlot from graphData", Blue, Bold],
DirectedEdges -> True, VertexLabeling -> True, 
EdgeLabeling -> True]];
Print[Style[
Row[{"2.1 FindPath from graphData: All paths from a to c: ", 
FindPath[graphData, a, c, Infinity, All]}], Blue, Bold]];
(* TreePlot and FindPath from graph *)
Print[TreePlot[graph, Left, a,
PlotLabel -> Style["2.2 TreePlot from graph", Blue, Bold],
DirectedEdges -> True, VertexLabeling -> True, 
EdgeLabeling -> True]];
Print[Style[
Row[{"2.2 FindPath from graph: All paths from a to c: ", 
FindPath[graph, a, c, Infinity, All]}], Blue, Bold]];
]
]

1 Defining a graph by graphData suitable for Graph

1 graphData:  {a->b1
a,b1

,a->b2
a,b2

,b1->c,b2->c}

1 make graph from graphData:  Graph 

TreePlot::grph: {a->b1
a,b1

,a->b2
a,b2

,b1->c,b2->c} is not a valid graph.

TreePlot::grph: {a->b1
a,b1

,a->b2
a,b2

,b1->c,b2->c} is not a valid graph.

TreePlot::grph: {a->b1
a,b1

,a->b2
a,b2

,b1->c,b2->c} is not a valid graph.

General::stop: Further output of TreePlot::grph will be suppressed during this calculation.

TreePlot[{a->b1
a,b1

,a->b2
a,b2

,b1->c,b2->c},Left,a,PlotLabel->1.1 TreePlot from graphData,DirectedEdges->True,VertexLabeling->True,EdgeLabeling->True]

1.1 FindPath from graphData: All paths from a to c: {{a,b2,c},{a,b1,c}}

TreePlot[SparseArray[Specified elements: 4
Dimensions: {4,4}

],Left,a,PlotLabel->1.2 TreePlot from graph,DirectedEdges->True,VertexLabeling->True,EdgeLabeling->True,DirectedEdges->True]

1.2 FindPath from graph: All paths from a to c: {{a,b2,c},{a,b1,c}}

2 Defining a graph by graphData suitable for TreePlot

2 graphData:  {{a->b1,a,b1},{a->b2,a,b2},b1->c,b2->c}

2 make graph from graphData:  Graph Graph[{{a->b1,a,b1},{a->b2,a,b2},b1->c,b2->c}]



FindPath::graph: A graph object is expected at position 1 in FindPath[{{a->b1,a,b1},{a->b2,a,b2},b1->c,b2->c},a,c,\[Infinity],All].

2.1 FindPath from graphData: All paths from a to c: FindPath[{{a->b1,a,b1},{a->b2,a,b2},b1->c,b2->c},a,c,\[Infinity],All]

TreePlot[Graph[{{a->b1,a,b1},{a->b2,a,b2},b1->c,b2->c}],Left,a,PlotLabel->2.2 TreePlot from graph,DirectedEdges->True,VertexLabeling->True,EdgeLabeling->True]

FindPath::graph: A graph object is expected at position 1 in FindPath[Graph[{{a->b1,a,b1},{a->b2,a,b2},b1->c,b2->c}],a,c,\[Infinity],All].

2.2 FindPath from graph: All paths from a to c: FindPath[Graph[{{a->b1,a,b1},{a->b2,a,b2},b1->c,b2->c}],a,c,\[Infinity],All]
POSTED BY: Werner Geiger
15 Replies

I'm not sure why this thread is so big for such a simple misunderstanding (definitely not a bug). Just read the manual.

You have two functions: TreePlot and TreeGraph, one handles a list of rules, the other handles directed and undirected edges. For all the functions is clearly states in the top of the documentation the various inputs they can receive (list of rules, list of directed/undirected edges, adjacency matrix, ...)

  • FindPath accepts Graph objects, but also a list of rules (as per the last line of the possible syntax inputs).
  • TreePlot accepts list of rules, adjacency matrix
  • TreeGraph accepts (just like Graph) a list of (un)directed edges.

See also the documentation headers:

enter image description here enter image description here

And note the info contained under Details and Options:

enter image description here

Read also the guides:

  • guide/GraphConstructionAndRepresentation
  • guide/GraphVisualization
  • guide/GraphsAndNetworks

Since v8 Mathematica has support for undirected edges, all functions prior to that only supported basic plotting through GraphPlot and its friends (working on list of rules and adjacency matrices, but only one-way). This functionality was more focused on visualization, not so much on calculations. The new Graph functionality since v8 support both types edge types and is also designed for calculations.

The difference between the two ways of graph visualisations is:

TreePlot[{1 -> 2, 1 -> 3, 1 -> 4}]
AtomQ[%]

TreeGraph[{1~DirectedEdge ~2, 1~DirectedEdge ~3, 1~DirectedEdge ~4}]
AtomQ[%]

Functions ending on Plot output visualisations, intended for viewing things, NOT to work and edit on (though not impossible to still manipulate it because of the homoiconic nature of Wolfram Language).

Functions ending on Graph output Graph objects which are displayed as plot, but are much more than that as they are treated as atoms, the internal structure of the graph is preserved (not turned into dots and lines and so on), and one can do calculations on those.

Also in the future you should try to get the core of your problem, long pieces of code make the thread unwieldy and hard to interpret, try to find the minimum amount of code to present your problem.

POSTED BY: Sander Huisman
Posted 9 years ago
POSTED BY: Werner Geiger

To add:

Note that in the TreePlot documentation a Graph object is not a valid input. There is however some 'hidden' (undocumented) functionality inside the definition of Treeplot. Namely:

TreePlot[g_ ? GraphQ, expr___] := Block[{res, adj, opts},
    adj = AdjacencyMatrix @ g;
    Condition[
       opts = opts = toTreePlotOptions @ g;
       res = TreePlot[adj, expr, opts];
       res /; UnsameQ[res, $Failed],
       MatrixQ[adj]
    ]
]

You can see how that it can handle Graph objects in some ways, but note that this is undocumented and might as well get removed in future versions! It might be some remnants from development (opts = opts = makes me think this).

POSTED BY: Sander Huisman
Posted 9 years ago

@ Werner: "->" is not the same as \DirectedEdge, otherwise I would have no reason to changed it. Did you run the code with my corrections in it (as posted above)?

POSTED BY: Michael Helmle

Word "bug" should not be placed in the title unless it is proven to be a bug. Reading the "details" section for the functions will help your understanding.

Docs clearly say (details section):

TreePlot returns a Graphics object.

so how can you expect it to be a Graph object?

Also, if you need a Graph object, what is wrong with TreeGraph or general structured embeddings for layered graphs such as trees and directed acyclic graphs:

Graph[..., GraphLayout -> "LayeredEmbedding"]
Graph[..., GraphLayout -> "LayeredDigraphEmbedding"]
Graph[..., GraphLayout -> "RadialEmbedding"]
Graph[..., GraphLayout -> "BalloonEmbedding"]

Also docs clearly say (details section):

TreePlot generates a tree plot of the graph g.

And here it is:

TreePlot[TreeGraph[{1 -> 2, 1 -> 3, 1 -> 4}]]
TreePlot[RandomGraph[{15, 34}]]
POSTED BY: Sam Carrettie
Posted 9 years ago

Hello Werner,

replace

graphData = {Labeled[a -> b1, "a,b1"], Labeled[a -> b2, "a,b2"], 
   b1 -> c, b2 -> c};

by

graphData = {Labeled[a \[DirectedEdge] b1, "a,b1"], 
   Labeled[a \[DirectedEdge] b2, "a,b2"], b1 \[DirectedEdge] c, 
   b2 \[DirectedEdge] c};

Treeplot requires a graph not just graphdata:

Print[TreePlot[Graph[graphData], 
   PlotLabel -> Style["1.1 TreePlot from graphData", Blue, Bold], 
   DirectedEdges -> True, VertexLabeling -> True, 
   EdgeLabeling -> True]];

Note that I also took out the "a". With these changes the 1st part should run.

I copied the changed version in below:

If[True,(*Test Graph (from Graph-Data)& TreePlot& FindPath*)
 Block[{a, b1, b2, c, graphData, 
   graph},(*Define graphData as a labeled list of edges in a form \
suitable for Graph*)
  Print[Style["1 Defining a graph by graphData suitable for Graph", 
    Red, Bold]];
  (* graphData={Labeled[a\[Rule]b1,"a,b1"],Labeled[a\[Rule]b2,"a,b2"],
  b1\[Rule]c,b2\[Rule]c};*)
  graphData = {Labeled[a \[DirectedEdge] b1, "a,b1"], 
    Labeled[a \[DirectedEdge] b2, "a,b2"], b1 \[DirectedEdge] c, 
    b2 \[DirectedEdge] c};
  Echo[graphData, "1 graphData: "];
  (*Make a Graph-object from graphData*)graph = Graph[graphData];
  Echo[Row[{Head[graph], " ", graph}], 
   "1 make graph from graphData: "];
  (*TreePlot and FindPath from graphData*)(* Print[TreePlot[graphData,
  Left,a,PlotLabel\[Rule]Style["1.1 TreePlot from graphData",Blue,
  Bold],DirectedEdges\[Rule]True,VertexLabeling\[Rule]True,
  EdgeLabeling\[Rule]True]];*)
  Print[TreePlot[Graph[graphData], 
    PlotLabel -> Style["1.1 TreePlot from graphData", Blue, Bold], 
    DirectedEdges -> True, VertexLabeling -> True, 
    EdgeLabeling -> True]];
  (* Print[Style[
  Row[{"1.1 FindPath from graphData: All paths from a to c: ",
  FindPath[graphData,a,c,Infinity,All]}],Blue,Bold]];*)
  Print[Style[
    Row[{"1.1 FindPath from graphData: All paths from a to c: ", 
      FindPath[Graph[graphData], a, c, Infinity, All]}], Blue, Bold]];
  (*TreePlot and FindPath from graph*)
  Print[TreePlot[graph, Left, 
    PlotLabel -> Style["1.2 TreePlot from graph", Blue, Bold], 
    DirectedEdges -> True, VertexLabeling -> True, 
    EdgeLabeling -> True]];
  Print[Style[
    Row[{"1.2 FindPath from graph: All paths from a to c: ", 
      FindPath[graph, a, c, Infinity, All]}], Blue, Bold]];
  (*Define graphData as a labeled list of edges in a Form suitable \
for TreePlot*)
  Print[Style["2 Defining a graph by graphData suitable for TreePlot",
     Red, Bold]];
  (* graphData={{a\[Rule]b1,"a,b1"},{a\[Rule]b2,"a,b2"},b1\[Rule]c,
  b2\[Rule]c};*)
  graphData = {Labeled[a \[DirectedEdge] b1, "a,b1"], 
    Labeled[a \[DirectedEdge] b2, "a,b2"], b1 \[DirectedEdge] c, 
    b2 \[DirectedEdge] c};
  Echo[graphData, "2 graphData: "];
  (*Make a Graph-object from graphData*)graph = Graph[graphData];
  Echo[Row[{Head[graph], " ", graph}], 
   "2 make graph from graphData: "];
  (*TreePlot and FindPath from graphData*)(* Print[TreePlot[graphData,
  Left,a,PlotLabel\[Rule]Style["2.1 TreePlot from graphData",Blue,
  Bold],DirectedEdges\[Rule]True,VertexLabeling\[Rule]True,
  EdgeLabeling\[Rule]True]];*)
  Print[TreePlot[Graph[graphData], 
    PlotLabel -> Style["2.1 TreePlot from graphData", Blue, Bold], 
    DirectedEdges -> True, VertexLabeling -> True, 
    EdgeLabeling -> True]];
  Print[Style[
    Row[{"2.1 FindPath from graphData: All paths from a to c: ", 
      FindPath[Graph[graphData], a, c, Infinity, All]}], Blue, Bold]];
  (*TreePlot and FindPath from graph*)
  Print[TreePlot[graph, Left, 
    PlotLabel -> Style["2.2 TreePlot from graph", Blue, Bold], 
    DirectedEdges -> True, VertexLabeling -> True, 
    EdgeLabeling -> True]];
  Print[Style[
    Row[{"2.2 FindPath from graph: All paths from a to c: ", 
      FindPath[graph, a, c, Infinity, All]}], Blue, Bold]];]]
POSTED BY: Michael Helmle
POSTED BY: Sander Huisman
Posted 9 years ago
POSTED BY: Werner Geiger
Posted 9 years ago

Standard Graph- or TreeGraph-objects or their defining data are obviously useless. It's a horrible mess.

I want to solve some problem, but not debug WL.

POSTED BY: Werner Geiger
Posted 9 years ago

Sorry for plaguing you with my funny but probably nonsense problems. I have enough of digging into all those strange features or bugs within WL concerning graphs. I will just maintain my own abstract data structure defining a graph and then convert this to whatever the WL-functions like to have.

POSTED BY: Werner Geiger
Posted 9 years ago
POSTED BY: Werner Geiger
Posted 9 years ago
POSTED BY: Werner Geiger
Posted 9 years ago

I think you misunderstood my post and did not read it. I did not expect TreePlot to return a Graph-object. Why should I do that? I expected TreePlot to accept any general Graph-object AS INPUT as described in the documentation. But it doesn't, as you can see from my post and code above.

Me personally thinks that this is a bug, but I am not sure. Maybe I have some basic misunderstanding. This is why I posted that here as a question: "..... A bug?"

Probably the confusion comes from WL not clearly distinguishing between Graph-objects and the different kinds of data-lists defining those graphs. Which are incompatibly different for Graph/FindPath and TreePlot.

Anyway, your hint to TreeGraph told me, that this accepts the same defining data as Graph and returns a Graph-object which might be suitable for TreePlot and FindPath. Thanks! I will test that.

POSTED BY: Werner Geiger
Posted 9 years ago

I'm afraid the solution is to record the graphData in some totally abstract form like {vertices,edges}={{{vertex,label},...},{{edge,label},...}} and then convert this for TreePlot and Graph/FindPath as desired.

Pretty stupid.

POSTED BY: Werner Geiger
Posted 9 years ago
POSTED BY: Werner Geiger
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard