Thanks you very much! Setting Element = ParametricRealFieldElement in class ParametricRealField(Field) before def __init__ is the key.
By the way, it seems that I need to call Field.__init__(self, self) as Field constructor, otherwise I got the following error. <ipython-input-26-4f6c8185301c> in __init__(self, values, names) * 4* * 5* def __init__(self, values=[], names=()): ----> 6 Field.__init__(self) * 7* #self._element_class = ParametricRealFieldElement * 8* self._zero_element = ParametricRealFieldElement(Integer(0 ), parent=self) /Users/yzh/sage/src/sage/rings/ring.pyx in sage.rings.ring.IntegralDomain.__init__ (/Users/yzh/sage/src/build/cythonized/sage/rings/ring.c:13965)() * 1539* _default_category = IntegralDomains() * 1540* -> 1541 def __init__(self, base_ring, names=None, normalize=True, category=None): * 1542* """ * 1543* Initialize ``self``. TypeError: __init__() takes at least 1 positional argument (0 given) On Friday, July 22, 2016 at 2:08:34 PM UTC-7, vdelecroix wrote: > > 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.
