20

Is it possible and practical for Mathematica to draw something like this (being created by Graphviz):

enter image description here

This is the best that I can get (but the shape and style are not satisfying):

enter image description here

Code:

GraphPlot[{{A -> C, "go"}, {C -> B, "gone"}, {C -> D, 
   "went"}, {C -> C, "loop"}}, VertexLabeling -> True, 
 DirectedEdges -> True]
Ning
  • 2,850
  • 2
  • 16
  • 23
  • There is no reason you cannot use graphics primitives to draw something like this. Are you requesting an automatic layout solution? – Mr.Wizard Nov 13 '11 at 03:34
  • 1
    @Mr.Wizard Yes, I am looking for some higher level primitives for drawing complicated state diagrams. I don't know whether Mathematica provides that. I searched through the documentation and checked the options of "GraphPlot" function and ended up with the code above. – Ning Nov 13 '11 at 03:36
  • Why did you accept my answer? The shape it still wrong. I appreciate it, but I think you should wait for a better answer. – Mr.Wizard Nov 13 '11 at 04:18
  • Yes, I think it may inhibit other answers. Again, thank you however. – Mr.Wizard Nov 13 '11 at 04:37
  • @Mr.Wizard You are a very nice person to have in a community, thank you! – Ning Nov 13 '11 at 05:04

2 Answers2

21

You can do something like this using VertexRenderingFunction.

GraphPlot[{{A -> C, "go"}, {C -> B, "gone"}, {C -> D, "went"}, {C -> C, "loop"}}, 
 DirectedEdges -> True, 
 VertexRenderingFunction -> ({{White, Disk[#, 0.15]}, 
     AbsoluteThickness[2], Circle[#, 0.15], 
     If[MatchQ[#2, A | B], Circle[#, 0.12], {}], Text[#2, #]} &)]

enter image description here


Method Updated February 2015

To preserve the ability to interactively rearrange the graph with the drawing tools (double click) one must keep the vertex graphics inside of GraphicsComplex, with indexes rather than coordinates. I believe one could do this from VertexRenderingFunction using an incrementing variable but it seems easier an possibly more robust to do it with post-processing. This works in versions 7 and 10 of Mathematica, presumably 8 and 9 as well:

GraphPlot[
  {{A -> C, "go"}, {C -> B, "gone"}, {C -> D, "went"}, {C -> C, "loop"}},
  DirectedEdges -> True
] /.
 Tooltip[Point[n_Integer], label_] :>
   {{White, Disk[n, 0.15]},
    Black, AbsoluteThickness[2], Circle[n, 0.15], 
    If[MatchQ[label, A | B], Circle[n, 0.12], {}], Text[label, n]}

enter image description here

Mr.Wizard
  • 24,179
  • 5
  • 44
  • 125
  • Is there a "VertexLabelingFunction"? – Ning Nov 13 '11 at 04:53
  • @Ning I had an error in my answer; I meant `VertexRenderingFunction`. I don't believe there is a Vertex**Labeling*Funcion. Also, I noticed that I had a flaw in my graphics relative to your original example regarding the circle sizes. I corrected this is the second version I just put up. – Mr.Wizard Nov 13 '11 at 04:57
5

There's no need for interactive placement to get your vertices at the desired location as mr.Wizard suggests in his answer. You can use VertexCoordinateRules for that:

GraphPlot[{{A -> C, "go"}, {C -> B, "gone"}, {C -> D, "went"}, {C -> C, "loop"}}, 
    DirectedEdges -> True, 
    VertexRenderingFunction -> 
          ({{White, Disk[#, 0.15]}, AbsoluteThickness[2], Circle[#, 0.15], 
           If[MatchQ[#2, A | B], Circle[#, 0.12], {}], Text[#2, #]} &),
    VertexCoordinateRules -> 
          {A -> {0, 0}, C -> {0.75, 0},B -> {1.5, 0.25}, D -> {1.5, -0.25}}
]

enter image description here

Community
  • 1
  • 1
Sjoerd C. de Vries
  • 16,122
  • 3
  • 42
  • 94
  • I didn't mean that it was necessary to have interactive layout, but I can see how that may be inferred. This method works too. Do you know of any way to preserve the editability besides a variation of the hack I used? – Mr.Wizard Nov 13 '11 at 22:23
  • @Mr.Wizard I don't see an easy way out. – Sjoerd C. de Vries Nov 13 '11 at 22:57