Multi-named Vertices (or Overlapping Vertices) in TreePlot/LayeredGraphPlot, or Merging Trees

If there is a series of rules from which a TreePlot/LayeredGraphPlot is made:

{D->C, C->B, B->A}


And a new vertex is added that is technically the same as an existing vertex, but has an alternate name or alias, for instance, "Q", which is the same as "A", and we create a new rule:

{B->Q}


Is there a way in TreePlot/LayeredGraphPlot to combine Q and A into a single vertex with two names? It seems that it should be possible to have aliases in TreePlot/LayeredGraphPlot that allow a vertices to point to other vertices that have more than 1 name. Here is a graphical example of what I mean:

EDIT: An alternative way of viewing this question is merging 2 distinct trees but preserving all names and aliases of the linking vertex.

• I think a few more examples might help. I am interested, but I don't understand your needs well enough to attempt an answer. – Mr.Wizard Feb 2 '15 at 3:02
• @Mr.Wizard I guess what I am really asking is whether or not a vertex within a plot can have two simultaneous values, in the above case "A" and "Q". Therefore, given the rules lists I mention in the post, rather than generating two different plots, combining them into one plot, in which the vertex in question has two names rather than one. I'll update the post to change "node" to "vertex". Also, I see this is something that could apply to LayeredGraphPlot, among others. – iwantmyphd Jun 29 '15 at 15:00

treea = {D -> C, C -> B, B -> A};

treeb = {B -> Q};


Combine two trees based on starting vertex:

combined =
Flatten[GatherBy[Join[treea, treeb], First] /.
x : {a_Rule, b__} :> a[[1]] -> Row[Riffle[x[[All, 2]], "/"]]]


{D -> C, C -> B, B -> Row[{A, "/", Q}]}

Decorating:

vshape[c : {xc_, yc_}, name_, {w_, h_}] := {
Hue[0.6, 0.77, 0.8],
EdgeForm[{Hue[0.6, 0.77, 0.22], Thickness[.05]}],
Disk[c, {3 w, 2 h}]}

res = Graph[#, VertexShapeFunction -> vshape,
PerformanceGoal -> "Quality",
VertexLabels -> Placed["Name", Center],
VertexLabelStyle -> Directive[13, White],
EdgeStyle -> Hue[0.6, 0.77, 0.8],
GraphLayout -> {"LayeredDigraphEmbedding",
"Orientation" -> Bottom}, VertexSize -> .2,
ImageSize -> 50] & /@ {treea, treeb, combined};

Row[{res[[1]], Spacer[50], "+", Spacer[50], res[[2]], Spacer[50],
"->", Spacer[50], res[[3]]}]


• How would you handle treeb = {Q -> B} instead? – Carl Woll Aug 17 '17 at 18:44
• @Carl Woll you could use the similar technique: Flatten[GatherBy[combined, Last] /. x : {a_Rule, b__} :> Row[Riffle[x[[All, 1]], "/"]] -> a[[2]]] – halmir Aug 17 '17 at 19:02
• Or treeb = {Q->B, A->R}? Or treeb = {Q<->B, A->R}. My point is that using GatherBy instead of graph operations like VertexContract or VertexReplace seems a lot more complicated. – Carl Woll Aug 17 '17 at 19:37
• @Carl Woll yes, can be. But to use VertexContract or VertexReplace you need to find out what vertices you want to operate anyhow. – halmir Aug 17 '17 at 19:51
edges1 = {"D" -> "C", "C" -> "B", "B" -> "A"};
edges2 = {"B" -> "Q"};

options = {GraphLayout -> {"LayeredEmbedding", "RootVertex" -> "D",
"Orientation" -> Bottom},
EdgeShapeFunction -> ({Thick, Arrowheads[.1], Arrow[#1, {0, .1}]} &),
VertexLabels -> Placed["Name", Center], VertexSize -> Medium};

g1 = Graph[edges1];
g2 = Graph[edges2];
g3 = GraphUnion[g1, g2, ## & @@ options, ImageSize -> Medium];
g4 = SetProperty[
VertexContract[g3, {"A", "Q"}], {VertexSize -> {"A" -> Medium},
VertexLabels -> {"A" -> Placed["A/Q", Center]}, (options /.

Row[{g3, g4}, Spacer[20]]


An alternative to @kglr's answer is to use VertexReplace. Your original Graph:

g = Graph[
{"D"->"C", "C"->"B", "B"->"A", "B"->"Q"},
GraphLayout -> {"LayeredEmbedding", "RootVertex" -> "D", "Orientation" -> Left},
VertexLabels->"Name"
]


Use VertexReplace to identify both "A" and "Q" as "A/Q":

new = VertexReplace[g, Thread[{"A","Q"}->"A/Q"]];


And view the result:

Graph[new, VertexLabels->"Name"]
VertexList[new]


{"D", "C", "B", "A/Q"}