Ask Your Question
0

Attempting to enrich quiver class yields "unexpected keyword argument" error

asked 2020-01-21 18:03:17 -0500

Will Dana gravatar image

I would like to do some computations with preprojective algebras, variations on the path algebra of a quiver in which every arrow has a partner going the other direction. I will want to construct representations of the "double quiver" in which I can conveniently compare the linear map associated to each arrow to that of its partner.

I figured I should create a class (something I haven't done in Python before) inheriting from DiGraph which has the extra data of a dictionary pairing the edges. My code to do this, with the constructor taking an arbitrary quiver and adding reversed copies of all the edges, is as follows:

class DoubleQuiver(sage.graphs.digraph.DiGraph):
def __init__(self, digraph):
    edges = []
    self._edgePairs = {}
    for e in digraph.edges():
        self._edgePairs[(e[0], e[1], e[2] + '0')] = (e[1], e[0], e[2] + '1')
        self._edgePairs[(e[1], e[0], e[2] + '1')] = (e[0], e[1], e[2] + '0')
        edges.append((e[0], e[1], e[2] + '0'))
        edges.append((e[1], e[0], e[2] + '1'))
    super(DoubleQuiver, self).__init__(edges, multiedges=True)

def flip(self, edge):
    assert edge in self.edges()
    return self._edgePairs[edge]

If I make a test digraph and run

DoubleQuiver(test)

it runs fine, and running methods like edges() or vertices() produces the results I expected. However, when I attempt to evaluate

DoubleQuiver(test).path_semigroup()

I get an error:

Error in lines 1-1
Traceback (most recent call last):
  File "/cocalc/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 1234, in execute
    flags=compile_flags), namespace, locals)
  File "", line 1, in <module>
  File "/ext/sage/sage-8.9_1804/local/lib/python2.7/site-packages/sage/graphs/digraph.py", line 2511, in path_semigroup
    return PathSemigroup(self)
  File "sage/misc/classcall_metaclass.pyx", line 335, in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ (build/cythonized/sage/misc/classcall_metaclass.c:1741)
    return cls.classcall(cls, *args, **kwds)
  File "/ext/sage/sage-8.9_1804/local/lib/python2.7/site-packages/sage/quivers/path_semigroup.py", line 118, in __classcall__
    Q = Q.copy(immutable=True, weighted=True)
  File "/ext/sage/sage-8.9_1804/local/lib/python2.7/site-packages/sage/graphs/generic_graph.py", line 1206, in copy
    data_structure=data_structure)
TypeError: __init__() got an unexpected keyword argument 'weighted'

How should I modify my class definition to avoid this error, or is there a better way of accomplishing what I'm trying to do? (Also, is it relevant that I'm trying this on CoCalc?)

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
0

answered 2020-01-22 15:54:46 -0500

Will Dana gravatar image

I believe I've found the issue. The __init__() referred to in the error message seems to be that of the class I'm defining. Presumably when I run the path_semigroup() method, it attempts to initialize a new DoubleQuiver for some reason, and includes an input for the "weighted" argument, something that the DiGraph constructor takes but the DoubleQuiver constructor, as written, does not.

Inserting **kwargs into the arguments of __init__ and the call it makes to DiGraph's __init__ appears to fix the problem by allowing for any missing arguments:

def __init__(self, digraph, multiedges=True, **kwargs):
edges = []
self._edgePairs = {}
for e in digraph.edges():
    self._edgePairs[(e[0], e[1], e[2] + '0')] = (e[1], e[0], e[2] + '1')
    self._edgePairs[(e[1], e[0], e[2] + '1')] = (e[0], e[1], e[2] + '0')
    edges.append((e[0], e[1], e[2] + '0'))
    edges.append((e[1], e[0], e[2] + '1'))
super(DoubleQuiver, self).__init__(edges, multiedges=True, **kwargs)

An aside: Another problem that this revealed, which provides further evidence that path_semigroup() calls __init__ again, is that the resulting path semigroup actually had all the arrows doubled again. I fixed this by checking whether the digraph input to __init__ is already an instance of DoubleQuiver.

edit flag offensive delete link more

Comments

This is basically correct, and passing an arbitrary **kwargs to a subclass's constructor is a fairly common idiom. A couple (very minor) nitpicks where your code is non-idiomatic:

  • Python has a style guide called PEP-8, which is also used by Sage (see Sage Coding Conventions. Most of your code is already PEP-8 except the self._edgePairs. camelCase is not used for local variables or attributes; instead you could call this self._edge_pairs (like I said, very minor)
  • The line assert edge in self.edges() is unnecessary; if it isn't true the following line will raise a KeyError, which is more explicit than an AssertionError anyways.
Iguananaut gravatar imageIguananaut ( 2020-01-23 09:45:28 -0500 )edit
0

answered 2020-01-22 15:48:44 -0500

eric_g gravatar image

updated 2020-01-22 15:50:41 -0500

If you look at the __init__() method of the class you are inheriting from, you will notice that it has a keyword argument weighted, as well as many other keyword arguments; simply type

DiGraph.__init__?

to see this. To have a description of these arguments, type

DiGraph?

So, I would say that the __init__() method of your class should have a keyword argument weighted (possibly with the default value None) and should pass it to super(DoubleQuiver, self).__init__() as follows:

    super(DoubleQuiver, self).__init__(edges, multiedges=True, weighted=weighted)
edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2020-01-21 18:03:17 -0500

Seen: 110 times

Last updated: Jan 22