Unexpected results with the subtraction operator / difference function

Hey folks,

I’m trying to subtract one graph from another and I’m getting results I wouldn’t expect. I’m creating a graph, finding a subcomponent, creating a subgraph, then subtracting the subgraph from the initial graph. igraph seems to be cutting the wrong edges. Could someone help me understand what’s going on? (all graphs are shown at the end. The forum limits the number of images new users can upload to 1.)

import igraph
g= igraph.Graph(directed=True)
g.add_vertices(["A","B","C","BA","BB","BC","CA","CAA"])
g.add_edges([["A","B"], ["A","C"],["B","BA"],["B","BB"], ["B","BC"],["C","CA"],["CA","CAA"]])
print(g)
layt = g.layout_reingold_tilford(mode="out", root=rn.indices)
igraph.plot(g, layout=layt,  vertex_label=g.vs["name"],
)

I see the graph in Figure 1 below, which I expected

sub = g.subcomponent("C", "out")
print(sub)
# sub_names = g.vs.
# sub_names = [g.vs[i]["name"] for i in sub]
sub = g.subgraph(sub)
sublayt = sub.layout_reingold_tilford(mode="out", root=[0])
igraph.plot(sub, layout=sublayt, vertex_label=sub.vs["name"])

I see the graph in Figure 2 below, which I expected.

subtracted = g.copy()
subtracted = subtracted - sub
subtractedlayt = subtracted.layout_reingold_tilford(mode="out", root=[0])

igraph.plot(subtracted, layout=subtractedlayt, vertex_label=subtracted.vs["name"])

I see the graph in Figure 3 below, which I did not expect. Shouldn’t the operation have just removed the C/CA/CAA subgraph from the first one? What am I missing here?

Figured out the issue is actually in the usage of the layout_reingold_tilford. It seems to actually create edges when you plot with a root node (that doesn’t have children? that is a child?). By removing the root kwarg, it works much better. The final graph is now:

BUT: Why is the subgraph still plotted at all? Why is A attached to C instead of B?

I think when you do

subtracted = subtracted - sub

the vertex labels aren’t taken into account, and it tries to remove an edge from 0->1 and from 1->2, which is an edge from A->B, and a nonexistent one from B->C. So it doesn’t do what you want at all. @tamas should this be fixed?

For example if I try to remove one edge it just removes the first edge instead of the expected second one:

    g = igraph.Graph(directed=True)
    g.add_vertices(["A", "B", "C"])
    g.add_edges([["A", "B"], ["B", "C"]])
    print("g", g)
    sub = g.subcomponent("B", "out")
    sub = g.subgraph(sub)
    print("sub", sub)
    subtracted = g.copy()
    subtracted = subtracted - sub
    print("subtracted", subtracted)
g IGRAPH DN-- 3 2 --
+ attr: name (v)
+ edges (vertex names):
A->B, B->C
sub IGRAPH DN-- 2 1 --
+ attr: name (v)
+ edges (vertex names):
B->C
subtracted IGRAPH DN-- 3 1 --
+ attr: name (v)
+ edges (vertex names):
B->C

If I try to remove 2 edges, they both get removed.