Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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}}]
share|improve this question
    
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. –  Szabolcs Jan 31 at 18:41
    
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. –  Szabolcs Jan 31 at 18:44
    
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. –  Steve Jan 31 at 18:56
    
Steve, well, it seems I was wrong, and luckily there was a simple solution! :-) –  Szabolcs Jan 31 at 19:24

1 Answer 1

up vote 8 down vote accepted

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

share|improve this answer
    
Once again belisarius+Mathematica are victorious. Thank you. –  Steve Jan 31 at 19:04
    
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}]]]} &); –  belisarius Jan 31 at 19:13
    
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 :) –  Steve Jan 31 at 19:22
    
Nice answer, as usual! +1 –  rasher Feb 1 at 0:55

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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