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

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 close merge delete

Sort by ยป oldest newest most voted

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)

more

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.

more

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.
( 2020-01-23 16:45:28 +0200 )edit