Daumantas Versockas
Daumantas Versockas

Reputation: 777

python-igraph union with current graph issue

I have a graph subclass. My attempt is to append a subgaph (also an instance of igraph.Graph) as an union

import igraph

class Graph(igraph.Graph):

    def __init__(self, param_1, param_2):
        self.param_1 = param_1
        self.param_2 = param_2
        super(Graph, self).__init__()

    def append_subgraph(self, subgraph):
        self = igraph.union([self, subgraph])

def execute():
    graph = Graph(None, None)
    graph2 = Graph(None, None)
    graph.append_subgraph(graph2)
    print(graph)

if __name__ == '__main__':
    execute()

When I am executing a this method on a instance of this class, I get an error

File "/usr/local/lib/python3.9/site-packages/igraph/operators.py", line 180, in union
    res = _union(newgraphs, edgemaps)
TypeError: __init__() got an unexpected keyword argument '__ptr'

Although, this issue is not applicable when I merge 2x separate graphs without the reference to self.

Has anyone faced this issue before?

Upvotes: 1

Views: 169

Answers (1)

salt-die
salt-die

Reputation: 854

I'll create a minimal example to replicate this problem and then show you how to fix it, but first let's check that there are no errors with graph union (everything will be done in ipython for my convenience):

In [36]: import igraph as ig
...: ig.union((ig.Graph(), ig.Graph()))
Out[36]: <igraph.Graph at 0x24343faab80>

Ok, we know the union works, let's try a minimal inheritance:

In [37]: class Graph(ig.Graph):
    ...:     ...
    ...: ig.union((Graph(), Graph()))
Out[37]: <__main__.Graph at 0x24343faac70>

So far, so good. Let's try to add our new __init__:

In [38]: class Graph(ig.Graph):
    ...:     def __init__(self, p, q):
    ...:         self.p = p
    ...:         self.q = q
    ...:         super().__init__()
    ...: ig.union((Graph(1, 2), Graph(1, 2)))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-38-68cf6a0e1e15> in <module>
      4         self.q = q
      5         super().__init__()
----> 6 ig.union((Graph(1, 2), Graph(1, 2)))

c:\python38\lib\site-packages\igraph\operators.py in union(graphs, byname)
    178     # If any graph has any edge attributes, we need edgemaps
    179     edgemaps = any(len(g.edge_attributes()) for g in graphs)
--> 180     res = _union(newgraphs, edgemaps)
    181     if edgemaps:
    182         graph_union = res["graph"]

TypeError: __init__() got an unexpected keyword argument '__ptr'

There's our error. igraph is expecting Graph to accept the same arguments and keyword-arguments as ig.Graph. This is how we can fix it:

In [39]: class Graph(ig.Graph):
    ...:     def __init__(self, *args, p=None, q=None, **kwargs):
    ...:         self.p = p
    ...:         self.q = q
    ...:         super().__init__(*args, **kwargs)
    ...: ig.union((Graph(p=1, q=2), Graph(p=1, q=2)))
Out[39]: <__main__.Graph at 0x24343faa400>

We've changed the signature of our __init__ to accept arbitrary positional arguments, our specific parameters as keyword-arguments, then arbitrary keyword-arguments. Now, igraph can pass the same arguments it passed to ig.Graphs. Hope this helps!

Upvotes: 3

Related Questions