Once again: you would better read
http://doc.sagemath.org/html/en/thematic_tutorials/coercion_and_categories.html#coercion-and-categories
1. In this document it is written how to write an Element and a Parent
class. In particular, to write a Parent class (e.g. your
ParametricRealField) you need to set an attribute named `Element` and
not `_element_class`. And this should be done *before* the call to Field
constructor.
(... Though, I wish this would have appeared sooner in the tutorial ...)
2. Next, the proper way to call the Field constructor is
Field.__init__(self)
why do you provide an additional argument?
3. In order to be able to perform algebraic operations with your
elements you need to define the following four methods in
ParametricRealFieldElement
def __neg__(self):
# should return the result of -self
def __invert__(self):
# should return the result of self^(-1)
def _mul_(left, right):
# should return the result of left * right
def _add_(left, right):
# should return the result of left + right
And optionally the following two methods
def _sub_(left, right):
# should return the result of left - right
def _div_(left, right):
# should return the result of left / right
Vincent
On 17/07/16 13:57, Yuan ZHOU wrote:
Thanks a lot for the instructions. I revised my code as follows.
from sage.structure.coerce_maps import CallableConvertMap
class ParametricRealFieldElement(FieldElement):
def __init__(self, value, parent=None):
FieldElement.__init__(self, parent)
self._val = value
def __hash__(self):
return hash(self._val)
class ParametricRealField(Field):
def __init__(self, values=[], names=()):
Field.__init__(self, self)
self._element_class = ParametricRealFieldElement
self._zero_element = ParametricRealFieldElement(0, parent=self)
self._one_element = ParametricRealFieldElement(1, parent=self)
self._gens = [ ParametricRealFieldElement(value, parent=self) for
value in values ]
def _an_element_impl(self):
return ParametricRealFieldElement(1, parent=self)
def _coerce_map_from_(self, S):
return CallableConvertMap(S, self, lambda s:
ParametricRealFieldElement(s, parent=self), parent_as_first_arg=False)
def _coerce_impl(self, x):
return self(x)
Now I have
sage: K.<a,b> = ParametricRealField([2, 1])
sage: K in CommutativeRings()
True
However, sage: R.<x,y> = PolynomialRing(K) raises NotImplementedError.
I suspect that the _element_constructor_ method of the class
ParametricRealField needs to be provided.
I tried the following in class ParametricRealField(Field):
def _element_constructor_(self, elt):
if elt.parent() == self:
return elt
return ParametricRealFieldElement(elt, parent=self)
This allows me to construct K and R, but I'm not able to get the generators
of R.
sage: K.<a,b> = ParametricRealField([2, 1])
sage: R.<x,y> = PolynomialRing(K)
sage: x
---------------------------------------------------------------------------
TypeError: unsupported operand parent(s) for '*': '<class
'__main__.ParametricRealField_with_category'>' and '<class
'__main__.ParametricRealField_with_category'>'
On Wednesday, July 13, 2016 at 6:57:56 PM UTC+1, vdelecroix wrote:
Please read the extensive documentation at
http://doc.sagemath.org/html/en/thematic_tutorials/coercion_and_categories.html#coercion-and-categories
Concerning your code, you need at least to:
1 - remove the attribute _parent and the method parent in
ParametricRealFieldElement
2 - remove the __call__ in ParametricRealField
3 - call the constructor of FieldElement as in
class ParametricRealFieldElement(FieldElement):
def __init__(self, value, parent=None):
...
...
FieldElement.__init__(self, parent)
4 - call the constructor of Field as in
class ParametricRealField(Field):
def __init__(self, values=[], names=()):
...
...
Field.__init__(self)
On 13/07/16 08:55, Yuan ZHOU wrote:
Hi,
I wish to construct a new class ParametricRealField. I implemented it as
follows.
class ParametricRealFieldElement(FieldElement):
def __init__(self, value, parent=None):
FieldElement.__init__(self, parent) ## this is so that
canonical_coercion works.
self._val = value
self._parent = parent ## this is so that .parent() works.
def parent(self):
return self._parent
def __hash__(self):
return hash(self._val)
class ParametricRealField(Field):
def __init__(self, values=[], names=()):
NumberField.__init__(self)
self._element_class = ParametricRealFieldElement
self._zero_element = ParametricRealFieldElement(0, parent=self)
self._one_element = ParametricRealFieldElement(1, parent=self)
self._gens = [ ParametricRealFieldElement(value, parent=self)
for
value in values ]
def _an_element_impl(self):
return ParametricRealFieldElement(1, parent=self)
def _coerce_map_from_(self, S):
return CallableConvertMap(S, self, lambda s:
ParametricRealFieldElement(s, parent=self), parent_as_first_arg=False)
def __call__(self, elt):
if parent(elt) == self:
return elt
return ParametricRealFieldElement(elt, parent=self)
def _coerce_impl(self, x):
return self(x)
Then I got an error when running the following code.
sage: K.<a,b> = ParametricRealField([2, 1])
sage: K.is_commutative()
True
sage: K.is_ring()
True
sage: K in CommutativeRings()
False
sage: R = PolynomialRing(K, 'x')
---------------------------------------------------------------------------
TypeError: Base ring <class '__main__.ParametricRealField'> must be a
commutative ring.
How can I make K commutative?
Thanks,
Yuan
--
You received this message because you are subscribed to the Google Groups
"sage-support" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sage-support.
For more options, visit https://groups.google.com/d/optout.