# wrapping vector class

I am trying to wrap the vector class to add some extra cases, but I am having trouble doing so. This is the code I have:

def lower_triangular_entries(dim,x,y):
return upper_triangular_entries(dim,y,x)

def upper_triangular_entries(dim,x,y):
if y<=x:
return 1
else:
return 0

class OneParamSubgroup(vector):
#TO DO: define scalar multiplication
def __init__(self, data, type_A=False):
if type_A:
BasisChange=matrix(ZZ, len(data)-1, len(data)-1,
lambda x,y: lower_triangular(len(data)-1,x,y))
v=vector(data[0:len(data)-1])
v=tuple(BasisChange*v)
#data given in terms of basis T
else:
v=data
vector.__init__(self, v)
def __repr__(self):
return self


However, I get the following error when running on terminal

Traceback (most recent call last):
File "test.sage.py", line 7, in <module>
File "sage/structure/sage_object.pyx", line 1057, in sage.structure.sage_object.load (build/cythonized/sage/structure/sage_object.c:12915)
File "<string>", line 3, in <module>
ImportError: cannot import name vector


and the following on the Notebook

TypeError                                 Traceback (most recent call last)
<ipython-input-1-ec2394617192> in <module>()
8         return Integer(0)
9
---> 10 class OneParamSubgroup(vector):
11     #TO DO: define scalar multiplication
12     def __init__(self, data, type_A=False):

TypeError: Error when calling the metaclass bases
cannot create 'builtin_function_or_method' instances


Any idea of what I am doing wrong?

edit retag close merge delete

Sort by » oldest newest most voted

In Sage, vector is a function, not a class, so you can't inherit from it. You should use Vector instead:

from sage.structure.element import Vector
class OneParamSubgroup(Vector):
...


I found this by looking at the help for vector (vector?). At the end, it tells me

File:           ..../sage/local/lib/python2.7/site-packages/sage/modules/free_module_element.pyx
Type:           builtin_function_or_method


Actually, Vector may not be perfect. What sort of vectors are you working with? Some other classes may provide more methods. Some examples:

sage: type(vector([1, 2])).mro() # integer entries
[<type 'sage.modules.vector_integer_dense.Vector_integer_dense'>,
<type 'sage.modules.free_module_element.FreeModuleElement'>,
<type 'sage.structure.element.Vector'>,
<type 'sage.structure.element.ModuleElement'>,
<type 'sage.structure.element.Element'>,
<type 'sage.structure.sage_object.SageObject'>,
<type 'object'>]
sage: type(vector([1., 2])).mro() # real
[<type 'sage.modules.free_module_element.FreeModuleElement_generic_dense'>,
<type 'sage.modules.free_module_element.FreeModuleElement'>,
<type 'sage.structure.element.Vector'>,
<type 'sage.structure.element.ModuleElement'>,
<type 'sage.structure.element.Element'>,
<type 'sage.structure.sage_object.SageObject'>,
<type 'object'>]
sage: type(vector([1/2, 2])).mro() # rational
[<type 'sage.modules.vector_rational_dense.Vector_rational_dense'>,
<type 'sage.modules.free_module_element.FreeModuleElement'>,
<type 'sage.structure.element.Vector'>,
<type 'sage.structure.element.ModuleElement'>,
<type 'sage.structure.element.Element'>,
<type 'sage.structure.sage_object.SageObject'>,
<type 'object'>]


So you could instead inherit from Vector_rational_dense, etc.

Edit: to use Vector_rational_dense, you could do this:

from sage.modules.vector_rational_dense import Vector_rational_dense

class test(Vector_rational_dense):
def __init__(self, parent, value):
Vector_rational_dense.__init__(self, parent, value)

xi2 = test(QQ**3, [2,2,1])

# or do this:

def vector_constructor(value):
return test(QQ**len(value), value)

xi3 = vector_constructor([2,2,1])

more

@John_Palmieri Thank you thank you, you can't believe how long I've been struggling with this. How did you know where to import it from? And when I do w=OneParamSubgroup([1,2]), if it is just the empty wrapper calling Vector.__init__, will it have the same effect as doing vecctor([1,2])?

( 2019-06-25 23:05:32 +0200 )edit

@John_Palmieri I guess I want rational vectors (to keep it safe). Should I use from sage.structure.element import Vector_rational_dense?

( 2019-06-25 23:09:11 +0200 )edit
1

To find where to import, use import_statements('Vector_rational_dense'). Also, calling Vector.__init__(self, data, ...) should have the same effect as Vector(data, ...). As far as vector([1,2]), you need to read the source code to see exactly what that does. It looks like it tries to determine the base ring, then creates a free module M of the appropriate rank over that ring, then does M(data). I think that in turn calls the _element_constructor_ method for the free module.

( 2019-06-25 23:14:49 +0200 )edit

@John_Palmieri Actually, (disregard original comment, there was mistake), it doesn't work. I do MWE:

from sage.structure.element import Vector
class test(Vector):
def __init__(self,value):
Vector.__init__(self, value)
xi2=test([2,2,1])


Get error:

  File "test.sage.py", line 23, in <module>
xi2=test([_sage_const_2 ,_sage_const_2 ,_sage_const_1 ])
File "<string>", line 4, in __init__
File "sage/structure/element.pyx", line 388, in sage.structure.element.Element.__init__ (build/cythonized/sage/structure/element.c:4248)
TypeError: Cannot convert list to sage.structure.parent.Parent

( 2019-06-25 23:25:30 +0200 )edit
2

First, use Vector_rational_dense instead of Vector. Or if you use Vector, be prepared to implement lots of things from scratch, since this class is pretty general purpose and doesn't even have an __init__ method. Next, it seems that Vector_rational_dense requires two arguments, the vector space and then the data; furthermore, for any class that inherits from it, it intercepts the arguments, so your __init__ method should have those same arguments. (Vector_rational_denseis defined using Cython; see https://cython.readthedocs.io/en/late....) See my edited answer.

( 2019-06-26 01:59:00 +0200 )edit