9
$\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$
4
  • $\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, 2014 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, 2014 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, 2014 at 18:56
  • $\begingroup$ Steve, well, it seems I was wrong, and luckily there was a simple solution! :-) $\endgroup$
    – Szabolcs
    Jan 31, 2014 at 19:24

2 Answers 2

11
$\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$
4
  • $\begingroup$ Once again belisarius+Mathematica are victorious. Thank you. $\endgroup$
    – Steve
    Jan 31, 2014 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$ Jan 31, 2014 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, 2014 at 19:22
  • $\begingroup$ Nice answer, as usual! +1 $\endgroup$
    – ciao
    Feb 1, 2014 at 0:55
3
$\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 and acknowledge that you have read and understand our privacy policy and code of conduct.

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