How to impose control over vertex-to-vertex Graph edges?

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.

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}}]

• 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. Commented Jan 31, 2014 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. Commented Jan 31, 2014 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. Commented Jan 31, 2014 at 18:56
• Steve, well, it seems I was wrong, and luckily there was a simple solution! :-) Commented Jan 31, 2014 at 19:24

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


• Once again belisarius+Mathematica are victorious. Thank you. Commented Jan 31, 2014 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}]]]} &); Commented Jan 31, 2014 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 :) Commented Jan 31, 2014 at 19:22
• Nice answer, as usual! +1
– ciao
Commented Feb 1, 2014 at 0:55

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]]}]


You can also use the built-in (and undocumented) edge shape function "CurvedArc":
SetProperty[{g1, 4 -> 1},  EdgeShapeFunction ->