7
$\begingroup$

I’m working on a Markov Chain and hope there is a way to impose control over how Mathematica places edges to connect vertices in a Graph. My Markov Chain currently consists of 4 vertices with 2 of the edges crossing and is shown below. The edge coming out of Vertex 4 labeled m and connecting to Vertex 1 is what I’d like to change.

Rather than being orientated as a vertical straight line, is it possible to direct this edge from Vertex 4 to the right in an arc so that the arc passes to the right of the k and then connects to Vertex 1 ? This will remove the crossing, be easier for others to read and be more architecturally correct.

enter image description here

My code is below. Thanks for any help.

softwareapplication = 
DiscreteMarkovProcess[
1, {{0, b, c, 0}, {e, f, g, h}, {i, 0, k, l}, {m, n, o, 0}}];

transitionmatrix = 
MarkovProcessProperties[softwareapplication, "TransitionMatrix"] // 
MatrixForm

vertexlabels = {1 -> Placed["1", Center], 2 -> Placed["2", Center], 
3 -> Placed["3", Center], 4 -> Placed["4", Center]};

edgelabels = {
1 \[DirectedEdge] 2 -> transitionmatrix[[1, 1, 2]],
1 \[DirectedEdge] 3 -> transitionmatrix[[1, 1, 3]],
2 \[DirectedEdge] 1 -> transitionmatrix[[1, 2, 1]],
2 \[DirectedEdge] 2 -> transitionmatrix[[1, 2, 2]],
2 \[DirectedEdge] 3 -> Placed[transitionmatrix[[1, 2, 3]], .25],
2 \[DirectedEdge] 4 -> transitionmatrix[[1, 2, 4]],
3 \[DirectedEdge] 1 -> transitionmatrix[[1, 3, 1]],
3 \[DirectedEdge] 3 -> transitionmatrix[[1, 3, 3]],
3 \[DirectedEdge] 4 -> transitionmatrix[[1, 3, 4]],
4 \[DirectedEdge] 1 -> Placed[transitionmatrix[[1, 4, 1]], .25],
4 \[DirectedEdge] 2 -> transitionmatrix[[1, 4, 2]],
4 \[DirectedEdge] 3 -> transitionmatrix[[1, 4, 3]]
};

Graph[softwareapplication, VertexLabels -> vertexlabels, 
EdgeLabels -> edgelabels, VertexSize -> Small, ImageSize -> Medium, 
VertexCoordinates -> {{0, 2}, {-1, 1}, {1, 1}, {0, 0}}]
$\endgroup$
  • $\begingroup$ I suspect that if you need fine grained control like this then it'll be easier to draw the layout using graphics primitives than the use Graph-related functionality. GrapLayout -> "PlanarEmbedding" will plot with no edge crossings, but you can't specify your vertex coordinates, so it's probably not useful for you. There's the "EdgeLayout" option but it doesn't seem to have anything that will automatically create a crossing-free edge layout, given some vertex coordinates. To sum up: it's probably difficult to do this automatically using Mathematica. $\endgroup$ – Szabolcs Jan 31 '14 at 18:41
  • $\begingroup$ My suggestion is to either do it manually or use other tools to lay out the graph and the edges, such as GraphViz or maybe yEd. $\endgroup$ – Szabolcs Jan 31 '14 at 18:44
  • $\begingroup$ Thanks for the reply. Having control over the vertex coordinates, labels and overall architecture is important. I must say that if you are correct this would be one of a very few cases (maybe the only case) where Mathematica cannot be coaxed into providing a solution to a valid technical need I have. I believe it's depth come from the idea of it being a "language" as opposed to being a canned software product limited to usage as the developers anticipate the usage will be. I'm still hopeful that there is an answer to this. Thanks again. $\endgroup$ – Steve Jan 31 '14 at 18:56
  • $\begingroup$ Steve, well, it seems I was wrong, and luckily there was a simple solution! :-) $\endgroup$ – Szabolcs Jan 31 '14 at 19:24
9
$\begingroup$

For example:

g1 = Graph[softwareapplication, VertexLabels -> vertexlabels, 
          EdgeLabels -> edgelabels, VertexSize -> Small, ImageSize -> Medium,
          VertexCoordinates -> {{0, 2}, {-1, 1}, {1, 1}, {0, 0}}, 
          EdgeShapeFunction -> Automatic];
PropertyValue[{g1, 4 \[DirectedEdge] 1}, EdgeShapeFunction] = 
      ({Red, Arrowheads[{{.02, .98}}], Arrow@BezierCurve[Riffle[#1, {{4, 1}}]]} &);
g1

Mathematica graphics

$\endgroup$
  • $\begingroup$ Once again belisarius+Mathematica are victorious. Thank you. $\endgroup$ – Steve Jan 31 '14 at 19:04
  • $\begingroup$ You can get more rounded shapes by adding control points PropertyValue[{g1, 4 \[DirectedEdge] 1}, EdgeShapeFunction] = ({Red, Arrowheads[{{Automatic, .98}}], Arrow@BezierCurve[{#, {1.7, 0}, {1.7, 1}, {1.7, 1}, {1.7, 2}, #2} & @@ #1[[{1, -1}]]]} &); $\endgroup$ – Dr. belisarius Jan 31 '14 at 19:13
  • $\begingroup$ Thanks again, it will take me some time to fully digest your original solution as I am by no means a power user. Also, continued kudos to Wolfram Research for developing (in my opinion) the deepest technical computing environment on the planet. Whatever your guiding philosophy has been thru version 9, do continue it thru version 20 and beyond :) $\endgroup$ – Steve Jan 31 '14 at 19:22
  • $\begingroup$ Nice answer, as usual! +1 $\endgroup$ – ciao Feb 1 '14 at 0:55
1
$\begingroup$

Update: Using the process softwareapplication as the first argument in Graph and setting EdgeLabels based on the transition matrix of the process, we can do everything in one step:

Graph[softwareapplication, 
   EdgeShapeFunction -> {DirectedEdge[4, 1] -> 
   ({Red, Arrow[GraphElementData[{"CurvedArc", "Curvature" -> -4}][##], .1]} &)}, 
   EdgeLabels -> {DirectedEdge[i_, j_] :> 
    MarkovProcessProperties[softwareapplication, "TransitionMatrix"][[i, j]]}]

enter image description here

Original answer:

You can also use the built-in (and undocumented) edge shape function "CurvedArc":

SetProperty[{g1, 4 -> 1},  EdgeShapeFunction -> 
 ({Red, Arrow[GraphElementData[{"CurvedArc", "Curvature" -> -4}][##], .1]} &)]

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.