# 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

## Stats

Seen: 265 times

Last updated: Jan 22 '20