4

Here is an example:

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

Graph[{edge1, edge2}]

Example

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?

MarcoB
  • 67,153
  • 18
  • 91
  • 189

2 Answers2

4

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

halmir
  • 15,082
  • 37
  • 53
  • halmir's solution preserves the class of edge so that appropriate graph analysis functions work, e.g., VertexInDegree[g] yields ${5, 10, 5}$. +1. – David G. Stork Aug 20 '15 at 21:23
2

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

David G. Stork
  • 41,180
  • 3
  • 34
  • 96
  • 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. – MarcoB Aug 19 '15 at 22:21
  • 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. – David G. Stork Aug 19 '15 at 22:24
  • 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. – MarcoB Aug 19 '15 at 22:32
  • @becko Did you not see my three-edge solution posted yesterday? – David G. Stork Aug 20 '15 at 20:12
  • I see it now. This edit was not visible to me before. Deleting comments. – a06e Aug 20 '15 at 20:22