# Possible bug with identity morphism

I have a number field U for which I consider its automorphisms through Hom(U,U). The identity one=Hom(U,U).identity() behaves weirdly under right multiplication:

U = CyclotomicField(3)
f = Hom(U,U)[1]
print f
print "--------------------"
one = Hom(U,U).identity()
print f*one
print "--------------------"
print one*f
print "--------------------"
print f*f


When I run this code, I expect f to be printed thrice, followed by the identity morphism. However, while the first and third output do in fact both print f, the second prints

Composite map:
From: Cyclotomic Field of order 3 and degree 2
To:   Cyclotomic Field of order 3 and degree 2
Defn:   Identity endomorphism of Cyclotomic Field of order 3 and degree 2
then
Ring endomorphism of Cyclotomic Field of order 3 and degree 2
Defn: zeta3 |--> -zeta3 - 1


Is this a bug or is this this behaviour explained somewhere in the documentation?

edit retag close merge delete

Sort by » oldest newest most voted

In general it is entirely unclear if "writing out" a composite map is easier/more efficient than keeping the composite form. It depends on the implementations of the maps and the way the maps get used subsequently. Sage is taking a cautious approach here and leaves the map in the form closest to how it's given. It has one optimization: If the identity map finds it gets precomposed with another map than it knows to just return the other map (multiplication happens left-to-right in python). Apparently the other maps don't check if the map they get precomposed with is the identity map. They could, but the test might be more expensive than the gains made.

You can always work out the composed map by using it on the generators:

sage: g=f*one
sage: U.Hom(U)([g(a) for a in U.gens()])
Ring endomorphism of Cyclotomic Field of order 3 and degree 2
Defn: zeta3 |--> -zeta3 - 1

more

f and one*f are the same mathematical object, but are not represented in the same way by Sage:

sage: g = f*one
sage: type(f)
<class 'sage.rings.number_field.morphism.CyclotomicFieldHomomorphism_im_gens'>
sage: type(g)
<type 'sage.categories.map.FormalCompositeMap'>


You should not worry about that, since:

sage: g in Hom(U,U)
True
sage: f == g
True
sage: g.parent()
Automorphism group of Cyclotomic Field of order 3 and degree 2
sage: f.parent()
Automorphism group of Cyclotomic Field of order 3 and degree 2


EDIT regarding the comment, a possible workaround would be to define the one not as the identity of Hom(U,U).identity() but as Hom(U,U)[0] since it will be of the same type as f and everything will work well:

sage: Hom(U,U)[0]
Ring endomorphism of Cyclotomic Field of order 3 and degree 2
Defn: zeta3 |--> zeta3
sage: Hom(U,U).identity()
Identity endomorphism of Cyclotomic Field of order 3 and degree 2
sage: Hom(U,U)[0] == Hom(U,U).identity()
True

sage: one = Hom(U,U)[0]
sage: type(one)
<class 'sage.rings.number_field.morphism.CyclotomicFieldHomomorphism_im_gens'>
sage: one*f
Ring endomorphism of Cyclotomic Field of order 3 and degree 2
Defn: zeta3 |--> -zeta3 - 1
sage: f*one
Ring endomorphism of Cyclotomic Field of order 3 and degree 2
Defn: zeta3 |--> -zeta3 - 1
sage: one
Ring endomorphism of Cyclotomic Field of order 3 and degree 2
Defn: zeta3 |--> zeta3
sage: f
Ring endomorphism of Cyclotomic Field of order 3 and degree 2
Defn: zeta3 |--> -zeta3 - 1

more

Is there any way to coerce the formal composite map to one of the former type? I compute the product of O(n) morphisms as f = one and for phi in l: f = phi*f, and the latter becomes an unreadable block of composite maps when I print the result, and it doesn't help the algorithmic complexity either when trying to evaluate the function I presume. I can work around this by reverse iterating the list and doing right multiplication with phi instead, but this feels like a hack. Furthermore, my question was whether any piece of documentation justifies this counter intuitive result.

( 2018-06-17 09:10:17 -0600 )edit