Here is an example:

edge1 = Property[1 -> 2, EdgeStyle -> Red];
edge2 = Property[1 -> 2, EdgeStyle -> Blue];

Graph[{edge1, edge2}]


This does not work the way I want it. How can I make it so that I get two edges, one blue and one red?

  • $\begingroup$ Please post actual code in addition to pictures, so people can copy/paste your code and play with it. $\endgroup$ – MarcoB Aug 19 '15 at 20:30
  • $\begingroup$ If one edge is directed and another not, there's no problem: Graph[{1, 2}, {Property[1 \[DirectedEdge] 2, EdgeStyle -> Red], Property[1 <-> 2, EdgeStyle -> Blue]}] $\endgroup$ – David G. Stork Aug 19 '15 at 20:47
  • $\begingroup$ Hmm, is there a way around this sacrifice? :D $\endgroup$ – user32497 Aug 19 '15 at 21:31
  • $\begingroup$ I'm no expert of graph theory and its representation in Mathematica, but it seems to me that you are trying to specify two colors for the same edge of that graph, not for two different ones. David's suggestion works because now the graph has two different edges, one directed, and one undirected. $\endgroup$ – MarcoB Aug 19 '15 at 21:34
  • $\begingroup$ duplicate: Graph - Coloring parallel edges individually $\endgroup$ – kglr Oct 3 '18 at 22:43

Another trick you can do:

Graph[Join[Table[1 -> 2, {10}], Table[2 -> 3, {5}], 
  Table[3 -> 1, {5}]],
 EdgeShapeFunction -> {1 \[DirectedEdge] 
     2 -> (a = 0; {a++; ColorData[35, "ColorList"][[a]],
       Arrow[#]} &), 
   2 \[DirectedEdge] 
     3 -> (b = 0; {b++; ColorData[55, "ColorList"][[b]],
       Arrow[#]} &), 
   3 \[DirectedEdge] 1 -> (c = 0; {c++; ColorData[5, "ColorList"][[c]],
       Arrow[#]} &)}]

enter image description here

| improve this answer | |
  • $\begingroup$ halmir's solution preserves the class of edge so that appropriate graph analysis functions work, e.g., VertexInDegree[g] yields $\{5, 10, 5\}$. +1. $\endgroup$ – David G. Stork Aug 20 '15 at 21:23

The trick is to render both a directed and an undirected edge with the same arrow EdgeShapeFunction. Alas, the full graph representation will retain the different classes of edge, so functions such as FindKClan, VertexOutDegree, VertexInDegree, and others that distinguish between different classes of edge will give incorrect answers.

  Graph[{1, 2}, 
     {Property[1 \[DirectedEdge] 2, EdgeStyle -> Red], 
      Property[1 <-> 2, EdgeStyle -> Blue]}, 
    EdgeShapeFunction -> (Arrow[#] &)]

enter image description here

Because there are only two classes of edge (directed and undirected), following this approach also implies that one can have at most two edges between a given pair of vertexes.

You can kludge together a graph representation that appears as if three (or more) edges join two vertexes by forcing different vertexes to lie in the same position, through VertexCoordinates:

Graph[{1, 2, 3}, {Property[1 \[DirectedEdge] 2, EdgeStyle -> Red], 
  Property[1 <-> 2, EdgeStyle -> Blue], 
  Property[1 <-> 3, EdgeStyle -> Green]}, 
 EdgeShapeFunction -> (Arrow[#] &), 
 VertexCoordinates -> {{0, 0}, {1, 0}, {1, 0}}]

enter image description here

| improve this answer | |
  • $\begingroup$ Although the funny-looking (Arrow[#]&) works, I think that more properly you would want (Arrow[#1]&) for your EdgeShapeFunction, to reming the reader that a custom edge function is passed a sequence of two arguments: 1) a list of points describing the edge; 2) the edge denomination itself. Arrow needs only the first one. I think this is also the reason why simply using Arrow doesn't work: the edge definition would be interpreted as an arrow setback amount, which is expected to be a number. $\endgroup$ – MarcoB Aug 19 '15 at 22:21
  • $\begingroup$ I had originally defined an EdgeShapeFunction of the form ef[#, ___] and called it within Graph, as the two-argument approach would seem to require. I found indeed that both (Arrow[#]&) and (Arrow[#1]&) worked, but don't know why the former does. $\endgroup$ – David G. Stork Aug 19 '15 at 22:24
  • $\begingroup$ I think (Arrow[#]&) works because # always represents only the first argument provided to the function, i.e. it is automatically equivalent to #1, so that call discards the second argument passed to Arrow by EdgeShapeFunction. In other words, (Arrow[#]&) is equivalent to Arrow[#1]&; both are different from (Arrow) alone, which would behave as (Arrow[__]&), i.e. SlotSequence[]. That's why I suggested using #1 rather than #: although they are perfectly equivalent, the latter makes the intended behavior more explicit. $\endgroup$ – MarcoB Aug 19 '15 at 22:32
  • $\begingroup$ @becko Did you not see my three-edge solution posted yesterday? $\endgroup$ – David G. Stork Aug 20 '15 at 20:12
  • $\begingroup$ I see it now. This edit was not visible to me before. Deleting comments. $\endgroup$ – becko Aug 20 '15 at 20:22

Your Answer

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