Math 581d

Morphisms

A morphism is a structure preserving map between two parents.  Sage supports the creation of morphisms.

In Sage, the typical way you specify a morphism from a "Parent with Generators" (which is most parents), is to give the images of the generators.  However, one can define morphisms using whatever method you want, and apply them however you want ("im_gens" is just what the data is called).

{{{id=3| /// }}}

Recall our example from last time, in which we created a new parent data type GoldenIntegers.    Suppose we would like the ring of golden integers to be viewed naturally as embedded in some other specific ring, from the point of view of the coercion model.  Without modifying Sage itself, the only way to do this is to learn about morphisms and:

  1. Use the embedding option to _populate_coercion_lists, as explained here, or
  2. Register a new coercion, as explained here, or
  3. Define a convert method on GoldenRingElement. 

We will explain all of these approaches below.

{{{id=42| /// }}}

Here's our code from last time.   Note that I implemented _mul_ this time.

{{{id=1| class GoldenIntegers(Ring): def __init__(self): Ring.__init__(self, base=ZZ) def _repr_(self): return "The Golden Ring" def gen(self, i=0): if i == 0: return GoldenElement(self, 0, 1) else: raise IndexError def ngens(self): return 1 def _element_constructor_(self, x): if isinstance(x, GoldenElement): return x return GoldenElement(self, ZZ(x), ZZ(0)) def _coerce_map_from_(self, S): print "_coerce_map_from_(%s, %s)"%(self, S) if S is ZZ: return True if S == Integers(13): return True class GoldenElement(RingElement): def __init__(self, parent, a, b): RingElement.__init__(self, parent) # sets self._parent to parent self._a = a self._b = b def _repr_(self): return "%s + %s*(1+sqrt(5))/2"%(self._a, self._b) def _add_(left, right): return GoldenElement(left.parent(), left._a+right._a, left._b+right._b) def _sub_(left, right): return GoldenElement(left.parent(), left._a-right._a, left._b-right._b) def _mul_(left, right): (a,b,c,d) = (left._a,left._b,right._a,right._b) return GoldenElement(left.parent(), a*c + b*d, b*c + a*d + b*d) /// }}} {{{id=6| R = GoldenIntegers(); R /// The Golden Ring }}}

Registering a coercion.

Let's try the second method, of registering a new coercion.  First we create the homset of homomorphisms from R to RDF (=real double precision field).  In Sage, homsets are normal parent objects, just like any other parents.

{{{id=7| H = Hom(R, RDF); H /// Set of Homomorphisms from The Golden Ring to Real Double Field }}} {{{id=74| isinstance(H, Parent) /// True }}} {{{id=12| gamma_in_RDF = RDF( (1+sqrt(5))/2 ); gamma_in_RDF /// 1.61803398875 }}}

A homomorphism is simply specified by giving the image of the generators.

{{{id=8| phi = H([gamma_in_RDF]); phi /// Traceback (most recent call last): File "", line 1, in File "_sage_input_12.py", line 10, in exec compile(u'open("___code___.py","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("cGhpID0gSChbZ2FtbWFfaW5fUkRGXSk7IHBoaQ=="),globals())+"\\n"); execfile(os.path.abspath("___code___.py"))' + '\n', '', 'single') File "", line 1, in File "/private/var/folders/7y/7y-O1iZOGTmMUMnLq7otq++++TI/-Tmp-/tmpfkBIYX/___code___.py", line 2, in exec compile(u'phi = H([gamma_in_RDF]); phi' + '\n', '', 'single') File "", line 1, in File "/Users/wstein/sage/install/sage-4.6/local/lib/python2.6/site-packages/sage/rings/homset.py", line 81, in __call__ raise TypeError, "images do not define a valid homomorphism" TypeError: images do not define a valid homomorphism }}} {{{id=75| gamma_in_RDF^2 - gamma_in_RDF - 1 == 0 /// True }}}

Checking with %debug on the console, we find that this is because:

ipdb> morphism.RingHomomorphism_im_gens(self, im_gens, check=check)
*** NotImplementedError: Verification of correctness of homomorphisms from The Golden Ring not yet implemented.

 

ipdb> morphism.RingHomomorphism_im_gens(self, im_gens, check=check)

*** NotImplementedError: Verification of correctness of homomorphisms from The Golden Ring not yet implemented.

 

 

This is a message that is produced in parent.pyx because we didn't define the method _is_valid_homomorphism_ yet.  Let's do it:

{{{id=18| R._is_valid_homomorphism_? ///

File: /Users/wstein/sage/install/sage-4.6/devel/sage/sage/structure/parent.pyx

Type: <type ‘builtin_function_or_method’>

Definition: R._is_valid_homomorphism_(codomain, im_gens)

Docstring:

Return True if im_gens defines a valid homomorphism from self to codomain; otherwise return False.

If determining whether or not a homomorphism is valid has not been implemented for this ring, then a NotImplementedError exception is raised.

}}} {{{id=14| class GoldenIntegers(Ring): def __init__(self): Ring.__init__(self, base=ZZ) def _is_valid_homomorphism_(self, codomain, im_gens): if len(im_gens) != 1: return False if im_gens[0]**2 - im_gens[0] - 1 == 0: return True return False def _repr_(self): return "The Golden Ring" def gen(self, i=0): if i == 0: return GoldenElement(self, 0, 1) else: raise IndexError def ngens(self): return 1 def _element_constructor_(self, x): if isinstance(x, GoldenElement): return x return GoldenElement(self, ZZ(x), ZZ(0)) def _coerce_map_from_(self, S): print "_coerce_map_from_(%s, %s)"%(self, S) if S is ZZ: return True if S == Integers(13): return True /// }}}

It works!

{{{id=10| R = GoldenIntegers(); H = Hom(R, RDF); phi = H([ gamma_in_RDF ]); phi /// Ring morphism: From: The Golden Ring To: Real Double Field Defn: 0 + 1*(1+sqrt(5))/2 |--> 1.61803398875 }}}

But we can't use it yet.

{{{id=22| gamma = R.0; phi(gamma) /// Traceback (most recent call last): File "", line 1, in File "_sage_input_15.py", line 10, in exec compile(u'open("___code___.py","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("Z2FtbWEgPSBSLjA7IHBoaShnYW1tYSk="),globals())+"\\n"); execfile(os.path.abspath("___code___.py"))' + '\n', '', 'single') File "", line 1, in File "/private/var/folders/7y/7y-O1iZOGTmMUMnLq7otq++++TI/-Tmp-/tmpFC7uNh/___code___.py", line 2, in exec compile(u'gamma = R.gen(0); phi(gamma)' + '\n', '', 'single') File "", line 1, in File "map.pyx", line 440, in sage.categories.map.Map.__call__ (sage/categories/map.c:3365) File "morphism.pyx", line 1087, in sage.rings.morphism.RingHomomorphism_im_gens._call_ (sage/rings/morphism.c:5636) File "element.pyx", line 416, in sage.structure.element.Element._im_gens_ (sage/structure/element.c:3216) NotImplementedError }}}

Again, looking at the above traceback and possibly consulting the source code of Sage, we find that there is another method that we have to define: _im_gens_

{{{id=21| gamma._im_gens_? ///

File: /Users/wstein/sage/install/sage-4.6/devel/sage/sage/structure/element.pyx

Type: <type 'builtin_function_or_method'>

Definition: gamma._im_gens_(codomain, im_gens)

Docstring:



        Return the image of self in codomain under the map that sends
        the images of the generators of the parent of self to the
        tuple of elements of im_gens.
}}} {{{id=76| phi1(7 + 2*gamma) /// _im_gens_(7 + 2*(1+sqrt(5))/2, Real Double Field, [-0.61803398875]) 5.7639320225 }}}

No problem:

{{{id=11| class GoldenElement(RingElement): def __init__(self, parent, a, b): RingElement.__init__(self, parent) # sets self._parent to parent self._a = a self._b = b def _im_gens_(self, codomain, im_gens): print "_im_gens_(%s, %s, %s)"%(self, codomain, im_gens) return codomain(self._a) + codomain(self._b)*im_gens[0] def _repr_(self): return "%s + %s*(1+sqrt(5))/2"%(self._a, self._b) def _add_(left, right): return GoldenElement(left.parent(), left._a+right._a, left._b+right._b) def _sub_(left, right): return GoldenElement(left.parent(), left._a-right._a, left._b-right._b) def _mul_(left, right): (a,b,c,d) = (left._a,left._b,right._a,right._b) return GoldenElement(left.parent(), a*c + b*d, b*c + a*d + b*d) /// }}} {{{id=26| R = GoldenIntegers(); H = Hom(R, RDF); phi = H([ RDF((1+sqrt(5))/2) ]) phi1 = H([ RDF((1-sqrt(5))/2) ]) gamma = R.0; phi(gamma) /// _im_gens_(0 + 1*(1+sqrt(5))/2, Real Double Field, [1.61803398875]) 1.61803398875 }}} {{{id=27| phi(3 + gamma) /// _coerce_map_from_(The Golden Ring, Integer Ring) _im_gens_(3 + 1*(1+sqrt(5))/2, Real Double Field, [1.61803398875]) 4.61803398875 }}} {{{id=28| 2*gamma /// 0 + 2*(1+sqrt(5))/2 }}} {{{id=29| phi(7 + 2*gamma) /// _im_gens_(7 + 2*(1+sqrt(5))/2, Real Double Field, [1.61803398875]) 10.2360679775 }}}

So finally, we have a working morphism.  Let's use it to register a new coercion!

{{{id=30| gamma + RDF(2.3) /// _coerce_map_from_(The Golden Ring, Real Double Field) _coerce_map_from_(The Golden Ring, Rational Field) Traceback (most recent call last): File "", line 1, in File "_sage_input_34.py", line 10, in exec compile(u'open("___code___.py","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("Z2FtbWEgKyBSREYoMi4zKQ=="),globals())+"\\n"); execfile(os.path.abspath("___code___.py"))' + '\n', '', 'single') File "", line 1, in File "/private/var/folders/7y/7y-O1iZOGTmMUMnLq7otq++++TI/-Tmp-/tmpT56CgE/___code___.py", line 3, in exec compile(u'gamma + RDF(_sage_const_2p3 )' + '\n', '', 'single') File "", line 1, in File "element.pyx", line 1274, in sage.structure.element.RingElement.__add__ (sage/structure/element.c:10853) File "coerce.pyx", line 765, in sage.structure.coerce.CoercionModel_cache_maps.bin_op (sage/structure/coerce.c:6995) TypeError: unsupported operand parent(s) for '+': 'The Golden Ring' and 'Real Double Field' }}} {{{id=35| phi.register_as_coercion() /// Traceback (most recent call last): File "", line 1, in File "_sage_input_35.py", line 10, in exec compile(u'open("___code___.py","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("cGhpLnJlZ2lzdGVyX2FzX2NvZXJjaW9uKCk="),globals())+"\\n"); execfile(os.path.abspath("___code___.py"))' + '\n', '', 'single') File "", line 1, in File "/private/var/folders/7y/7y-O1iZOGTmMUMnLq7otq++++TI/-Tmp-/tmpXLJdiI/___code___.py", line 2, in exec compile(u'phi.register_as_coercion()' + '\n', '', 'single') File "", line 1, in File "morphism.pyx", line 116, in sage.categories.morphism.Morphism.register_as_coercion (sage/categories/morphism.c:2387) File "parent.pyx", line 1368, in sage.structure.parent.Parent.register_coercion (sage/structure/parent.c:9695) File "parent.pyx", line 1408, in sage.structure.parent.Parent.register_coercion (sage/structure/parent.c:9635) AssertionError: coercion from The Golden Ring to Real Double Field already registered or discovered }}}

What went wrong?  The problem is that Sage already started automatically deciding on coercions, and once that happpens, for efficiency and consistency reasons you are not allowed to register further coercions.  The solution is to register the coercion map right when you make R.

{{{id=33| R = GoldenIntegers() H = Hom(R, RDF) phi = H([ gamma_in_RDF ]) psi = R.hom([CDF( (1+sqrt(5))/2 )]) phi.register_as_coercion() psi.register_as_coercion() /// }}}

Now, let's try it out:

{{{id=34| gamma = R.0 gamma + RDF(2.5) /// _coerce_map_from_(The Golden Ring, Real Double Field) _im_gens_(0 + 1*(1+sqrt(5))/2, Real Double Field, [1.61803398875]) 4.11803398875 }}} {{{id=79| class GoldenIntegers(Ring): def __init__(self): Ring.__init__(self, base=ZZ) phi = self.hom([ gamma_in_RDF ]) psi = self.hom([CDF( (1+sqrt(5))/2 )]) phi.register_as_coercion() psi.register_as_coercion() def _is_valid_homomorphism_(self, codomain, im_gens): if len(im_gens) != 1: return False if im_gens[0]**2 - im_gens[0] - 1 == 0: return True return False def _repr_(self): return "The Golden Ring" def gen(self, i=0): if i == 0: return GoldenElement(self, 0, 1) else: raise IndexError def ngens(self): return 1 def _element_constructor_(self, x): if isinstance(x, GoldenElement): return x return GoldenElement(self, ZZ(x), ZZ(0)) def _coerce_map_from_(self, S): print "_coerce_map_from_(%s, %s)"%(self, S) if S is ZZ: return True if S == Integers(13): return True /// }}} {{{id=80| R = GoldenIntegers() /// }}} {{{id=78| R.0 + RDF(1.5) /// _coerce_map_from_(The Golden Ring, Real Double Field) _im_gens_(0 + 1*(1+sqrt(5))/2, Real Double Field, [1.61803398875]) 3.11803398875 }}} {{{id=81| 3 + 2*R.0 + CDF(1,1) /// _coerce_map_from_(The Golden Ring, Integer Ring) _coerce_map_from_(The Golden Ring, Complex Double Field) _im_gens_(3 + 2*(1+sqrt(5))/2, Complex Double Field, [1.61803398875]) 7.2360679775 + 1.0*I }}} {{{id=83| a = 3 + 2*R.0; b = CDF(1,1) /// }}} {{{id=84| timeit('a*b') /// 625 loops, best of 3: 55.4 µs per loop }}} {{{id=85| timeit('a*a') /// 625 loops, best of 3: 3.82 µs per loop }}} {{{id=82| /// }}} {{{id=77| /// }}}

Nice!  Notice that the coercion ended up going into the real double field.

{{{id=40| gamma + CDF(1,2) /// _coerce_map_from_(The Golden Ring, Complex Double Field) _im_gens_(0 + 1*(1+sqrt(5))/2, Complex Double Field, [1.61803398875]) 2.61803398875 + 2.0*I }}}

Summary:

In order to create a working morphism from instances of our GoldenRing class to some other ring $S$, we did the following:

  1. Defined the method def _is_valid_homomorphism_(self, codomain, im_gens)  in the GoldenRing class, which verifies that a morphism is valid.
  2. Defined the method def _im_gens_(self, codomain, im_gens) in the GoldenElement class, which computes where an element goes under a valid morphism.
  3. Learned about H = Hom(A,B), which creates the set of homomorphisms from A to B.
  4. Learned that we make elements of H like so:   H(list of images of generators of A in B)

We also learned about register_as_coercion, which must be called immediately after you make your parent.  Using that we can inform Sage that it should add some morphisms to the coercion model.

{{{id=86| Hom(A,B)( [images of generators] ) or A.hom([images of generators]) /// }}} {{{id=44| /// }}} {{{id=87| R = GoldenIntegers(); gamma = R.0 gamma + CDF(2.3) /// _coerce_map_from_(The Golden Ring, Complex Double Field) _im_gens_(0 + 1*(1+sqrt(5))/2, Real Double Field, [1.61803398875]) 3.91803398875 }}} {{{id=88| R = GoldenIntegers() psi = R.hom([CDF( (1-sqrt(5))/2 )]) psi.register_as_coercion() /// hi mom! The Golden Ring, Real Double Field, [1.61803398875] ret true hi mom! The Golden Ring, Complex Double Field, [-0.61803398875] ret false Traceback (most recent call last): File "", line 1, in File "_sage_input_68.py", line 10, in exec compile(u'open("___code___.py","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("UiA9IEdvbGRlbkludGVnZXJzKCkKcHNpID0gUi5ob20oW0NERiggKDEtc3FydCg1KSkvMiApXSkKcHNpLnJlZ2lzdGVyX2FzX2NvZXJjaW9uKCk="),globals())+"\\n"); execfile(os.path.abspath("___code___.py"))' + '\n', '', 'single') File "", line 1, in File "/private/var/folders/7y/7y-O1iZOGTmMUMnLq7otq++++TI/-Tmp-/tmpkQL91_/___code___.py", line 4, in psi = R.hom([CDF( (_sage_const_1 -sqrt(_sage_const_5 ))/_sage_const_2 )]) File "parent_gens.pyx", line 464, in sage.structure.parent_gens.ParentWithGens.hom (sage/structure/parent_gens.c:3707) File "parent.pyx", line 1253, in sage.structure.parent.Parent.hom (sage/structure/parent.c:8538) File "/Users/wstein/sage/install/sage-4.6/local/lib/python2.6/site-packages/sage/rings/homset.py", line 81, in __call__ raise TypeError, "images do not define a valid homomorphism" TypeError: images do not define a valid homomorphism }}} {{{id=90| a = CDF((1-sqrt(5))/2); a /// -0.61803398875 }}} {{{id=93| a^2 /// 0.38196601125 - 9.35546906121e-17*I }}} {{{id=91| a^2 - a - 1 == 0 /// False }}} {{{id=92| a^2 - a - 1 /// -9.35546906121e-17*I }}} {{{id=89| R.0 + CDF(1,1) /// _coerce_map_from_(The Golden Ring, Complex Double Field) _im_gens_(0 + 1*(1+sqrt(5))/2, Complex Double Field, [1.61803398875]) 2.61803398875 + 1.0*I }}}

Finally, there is also the embedding= option.  We abuse it below.  (I say "abuse", since in fact the golden ring doesn't really embed into RDF, since RDF is a finite set, due to rounding.)

{{{id=38| class GoldenIntegers(Ring): def __init__(self): Ring.__init__(self, base=ZZ) phi = self.hom([RDF( (1+sqrt(5))/2 )]) self._populate_coercion_lists_(embedding=phi) def _is_valid_homomorphism_(self, codomain, im_gens): print "hi mom! %s, %s, %s"%(self, codomain, im_gens) if len(im_gens) != 1: print "ret false" return False if im_gens[0]**2 - im_gens[0] - 1 == 0: print "ret true" return True print "ret false" return False def _repr_(self): return "The Golden Ring" def gen(self, i=0): if i == 0: return GoldenElement(self, 0, 1) else: raise IndexError def ngens(self): return 1 def _element_constructor_(self, x): if isinstance(x, GoldenElement): return x return GoldenElement(self, ZZ(x), ZZ(0)) def _coerce_map_from_(self, S): print "_coerce_map_from_(%s, %s)"%(self, S) if S is ZZ: return True if S == Integers(13): return True /// }}} {{{id=45| R = GoldenIntegers(); gamma = R.0 gamma + RDF(2.3) /// _coerce_map_from_(The Golden Ring, Real Double Field) _im_gens_(0 + 1*(1+sqrt(5))/2, Real Double Field, [1.61803398875]) 3.91803398875 }}}

Since RDF embeds into the symbolic ring, the following automatically works.  

{{{id=48| R.0 + sqrt(2) /// _coerce_map_from_(The Golden Ring, Symbolic Ring) _im_gens_(0 + 1*(1+sqrt(5))/2, Real Double Field, [1.61803398875]) sqrt(2) + 1.61803398875 }}}

However, it seems a bit weird to turn (1+sqrt(5))/2 into the number 1.61803398875, just to put it somewhere where we could represent (1+sqrt(5))/2 exactly!  Let's try embedding into SR, instead.

{{{id=46| class GoldenIntegers(Ring): def __init__(self): Ring.__init__(self, base=ZZ) phi = self.hom([( 1+sqrt(5))/2 ]) self._populate_coercion_lists_(embedding=phi) def _is_valid_homomorphism_(self, codomain, im_gens): if len(im_gens) != 1: return False if im_gens[0]**2 - im_gens[0] - 1 == 0: return True return False def _repr_(self): return "The Golden Ring" def gen(self, i=0): if i == 0: return GoldenElement(self, 0, 1) else: raise IndexError def ngens(self): return 1 def _element_constructor_(self, x): if isinstance(x, GoldenElement): return x return GoldenElement(self, ZZ(x), ZZ(0)) def _coerce_map_from_(self, S): print "_coerce_map_from_(%s, %s)"%(self, S) if S is ZZ: return True if S == Integers(13): return True /// }}} {{{id=51| R = GoldenIntegers(); gamma = R.0 gamma + sqrt(2) /// _coerce_map_from_(The Golden Ring, Symbolic Ring) _im_gens_(0 + 1*(1+sqrt(5))/2, Symbolic Ring, [1/2*sqrt(5) + 1/2]) sqrt(2) + 1/2*sqrt(5) + 1/2 }}}

But now the following won't work, because there isn't a canonical map in any direction.

{{{id=52| gamma + RDF(2.3) /// _coerce_map_from_(The Golden Ring, Real Double Field) _coerce_map_from_(The Golden Ring, Symbolic Ring) _coerce_map_from_(The Golden Ring, The Golden Ring) _coerce_map_from_(The Golden Ring, Symbolic Ring) _coerce_map_from_(The Golden Ring, The Golden Ring) _coerce_map_from_(The Golden Ring, Symbolic Ring) _coerce_map_from_(The Golden Ring, The Golden Ring) _coerce_map_from_(The Golden Ring, Symbolic Ring) _coerce_map_from_(The Golden Ring, The Golden Ring) _coerce_map_from_(The Golden Ring, Symbolic Ring) _coerce_map_from_(The Golden Ring, The Golden Ring) _coerce_map_from_(The Golden Ring, Integer Ring) _coerce_map_from_(The Golden Ring, Rational Field) Traceback (most recent call last): File "", line 1, in File "_sage_input_76.py", line 10, in exec compile(u'open("___code___.py","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("Z2FtbWEgKyBSREYoMi4zKQ=="),globals())+"\\n"); execfile(os.path.abspath("___code___.py"))' + '\n', '', 'single') File "", line 1, in File "/private/var/folders/7y/7y-O1iZOGTmMUMnLq7otq++++TI/-Tmp-/tmp7EnLcb/___code___.py", line 3, in exec compile(u'gamma + RDF(_sage_const_2p3 )' + '\n', '', 'single') File "", line 1, in File "element.pyx", line 1274, in sage.structure.element.RingElement.__add__ (sage/structure/element.c:10853) File "coerce.pyx", line 765, in sage.structure.coerce.CoercionModel_cache_maps.bin_op (sage/structure/coerce.c:6995) TypeError: unsupported operand parent(s) for '+': 'The Golden Ring' and 'Real Double Field' }}}

There is a canonical coercion from the golden ring to the symbolic ring, and one from RDF to the symbolic ring, but the coercion system doesn't know how to figure out that this is the best place to map things to.  (And I don't know how to tell it to do so...)

{{{id=58| /// }}}

Look at the _populate_coercion_lists_ method in more detail:

{{{id=59| R._populate_coercion_lists_?? /// }}} {{{id=62| /// }}}

Let's use a Convert Methods to make it so golden elements automatically coerce to arbitrary precision reals

There is something called the _convert_method_name, which allows you to add a method to your elements, to make it so certain rings automatically can coerce elements in.  For example, below we figure out what the method name is for arbitrary precision floating point numbers, then define it for our GoldenElement class.  Now there is automatically a coercion map to arbitrary precision reals.  This is similar to the builtin Python methods like __float__.

{{{id=57| RR._convert_method_name /// '_mpfr_' }}} {{{id=94| RDF._convert_method_name /// '_real_double_' }}} {{{id=53| class GoldenElement(RingElement): def __init__(self, parent, a, b): RingElement.__init__(self, parent) # sets self._parent to parent self._a = a self._b = b def _mpfr_(self, F): return self._a + self._b * (1+F(5).sqrt())/2 def __float__(self): return float(self._a) + float(self._b) + float( (1+sqrt(5))/2 ) def _im_gens_(self, codomain, im_gens): return codomain(self._a) + codomain(self._b)*im_gens[0] def _repr_(self): return "%s + %s*(1+sqrt(5))/2"%(self._a, self._b) def _add_(left, right): return GoldenElement(left.parent(), left._a+right._a, left._b+right._b) def _sub_(left, right): return GoldenElement(left.parent(), left._a-right._a, left._b-right._b) def _mul_(left, right): (a,b,c,d) = (left._a,left._b,right._a,right._b) return GoldenElement(left.parent(), a*c + b*d, b*c + a*d + b*d) /// }}} {{{id=55| R = GoldenIntegers() x = 2*R.0 + 5 RealField(200)(x) /// _coerce_map_from_(The Golden Ring, Integer Ring) _coerce_map_from_(The Golden Ring, Real Field with 200 bits of precision) 8.2360679774997896964091736687312762354406183596115257242709 }}} {{{id=95| x + RealField(200)(7) /// _coerce_map_from_(The Golden Ring, Rational Field) Traceback (most recent call last): File "", line 1, in File "_sage_input_82.py", line 10, in exec compile(u'open("___code___.py","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("eCArIFJlYWxGaWVsZCgyMDApKDcp"),globals())+"\\n"); execfile(os.path.abspath("___code___.py"))' + '\n', '', 'single') File "", line 1, in File "/private/var/folders/7y/7y-O1iZOGTmMUMnLq7otq++++TI/-Tmp-/tmpylmNnX/___code___.py", line 3, in exec compile(u'x + RealField(_sage_const_200 )(_sage_const_7 )' + '\n', '', 'single') File "", line 1, in File "element.pyx", line 1274, in sage.structure.element.RingElement.__add__ (sage/structure/element.c:10853) File "coerce.pyx", line 765, in sage.structure.coerce.CoercionModel_cache_maps.bin_op (sage/structure/coerce.c:6995) TypeError: unsupported operand parent(s) for '+': 'The Golden Ring' and 'Real Field with 200 bits of precision' }}} {{{id=69| float(x) /// 8.6180339887498949 }}} {{{id=64| RealField(300)(x) /// _coerce_map_from_(The Golden Ring, Real Field with 300 bits of precision) 8.23606797749978969640917366873127623544061835961152572427089724541052092563780489941441441 }}} {{{id=65| RR(x) /// _coerce_map_from_(The Golden Ring, Real Field with 53 bits of precision) 8.23606797749979 }}} {{{id=67| /// }}} {{{id=71| /// }}} {{{id=70| /// }}} {{{id=68| /// }}}