Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
backend morphism and tower of extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
xcaruso committed Sep 10, 2019
1 parent 77332e0 commit 631f228
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 121 deletions.
85 changes: 18 additions & 67 deletions src/sage/rings/algebra_from_morphism.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@


from sage.structure.unique_representation import UniqueRepresentation
from sage.categories.commutative_rings import CommutativeRings
from sage.categories.pushout import pushout
from sage.categories.algebras import Algebras
from sage.categories.commutative_algebras import CommutativeAlgebras
from sage.rings.integer_ring import IntegerRing, ZZ
from sage.rings.ring import CommutativeRing, CommutativeAlgebra
from sage.rings.morphism import RingHomomorphism
from sage.rings.morphism import AlgebraFromMorphismHomomorphism
from sage.rings.algebra_from_morphism_element import AlgebraFMElement


class AlgebraFromMorphism(CommutativeAlgebra, UniqueRepresentation):
Expand Down Expand Up @@ -63,6 +64,8 @@ class AlgebraFromMorphism(CommutativeAlgebra, UniqueRepresentation):
- Xavier Caruso (2016)
"""
Element = AlgebraFMElement

def __init__(self, defining_morphism, coerce):
r"""
TESTS::
Expand All @@ -85,14 +88,12 @@ def __init__(self, defining_morphism, coerce):
ring = defining_morphism.codomain()

if isinstance(ring, AlgebraFromMorphism):
try:
defining_morphism = defining_morphism._backend(forget="codomain")
except AttributeError:
defining_morphism = defining_morphism.post_compose(AlgebraToRing(self.Hom(ring)))
from sage.rings.morphism import backend_morphism
defining_morphism = backend_morphism(defining_morphism, forget="codomain")
coerce &= ring._coerce
ring = ring._backend()

CommutativeAlgebra.__init__(self, ZZ, category=Algebras(base))
CommutativeAlgebra.__init__(self, ZZ, category=CommutativeAlgebras(base))
self._base = base
self._ring = ring
self._coerce = coerce
Expand All @@ -102,64 +103,7 @@ def __init__(self, defining_morphism, coerce):
f = AlgebraFromMorphismHomomorphism(self._base.Hom(self), defining_morphism)
self.register_coercion(f)
if coerce:
from sage.rings.morphism import AlgebraToRing
self._populate_coercion_lists_(embedding = AlgebraToRing(self.Hom(ring)))

from sage.rings.algebra_from_morphism_element import AlgebraFMElement
self.element_class = AlgebraFMElement

def _element_constructor_(self, x, *args, **kwargs):
r"""
Convert ``x`` into an element of this parent
EXAMPLES::
sage: K = GF(5^4)
sage: L = GF(5^8)
sage: E = RingExtension(L,K)
Conversion of an element of the ring::
sage: a = L.random_element()
sage: a.parent()
Finite Field in z8 of size 5^8
sage: a.parent() is L
True
sage: aE = E(a)
sage: aE.parent()
Finite Field in z8 of size 5^8 viewed as an algebra over its base
sage: aE.parent() is E
True
Conversion from another extension::
sage: k = GF(5^2)
sage: F = RingExtension(K,k)
sage: b = K.gen(); b
z4
sage: bF = F(b); bF
z4
sage: bE = E(bF); bE
4*z8^7 + z8^6 + 3*z8^4 + z8^3 + z8^2 + 4
sage: bE.parent()
Finite Field in z8 of size 5^8 viewed as an algebra over its base
sage: bE.parent() is E
True
"""
from sage.rings.algebra_from_morphism_element import AlgebraFMElement
if isinstance(x, AlgebraFMElement):
x = x._backend()
try:
parent = x.parent()
if self._base.has_coerce_map_from(parent):
x = self._base.coerce_map_from(parent)(x)
x = self._defining_morphism(x)
except AttributeError:
pass
elt = self._ring(x, *args, **kwargs)
return self.element_class(self, elt)
self._populate_coercion_lists_(embedding = AlgebraFromMorphismHomomorphism(self.Hom(ring), ring.Hom(ring).identity()))

def from_base_ring(self, r):
r"""
Expand Down Expand Up @@ -201,8 +145,12 @@ def from_base_ring(self, r):
"""
if r not in self._base:
raise TypeError("%s is not an element of the base of %s (= %s)" % (r, self._ring, self._base))
elt = self._defining_morphism(r)
return self.element_class(self, elt)
return self.element_class(self, r)

def _Hom_(self, other, category):
if isinstance(self, AlgebraFromMorphism) or isinstance(other, AlgebraFromMorphism):
from sage.rings.homset import AlgebraFromMorphismHomset
return AlgebraFromMorphismHomset(self, other, category)

def _pushout_(self, other):
r"""
Expand Down Expand Up @@ -447,6 +395,9 @@ def _an_element_(self):
elt = self._ring.an_element()
return self.element_class(self, elt)

def ngens(self):
return self._ring.ngens()

def gen(self):
r"""
Return a generator of this extension
Expand Down
7 changes: 7 additions & 0 deletions src/sage/rings/algebra_from_morphism_constructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,3 +277,10 @@ def RingExtension(ring, base=None, defining_morphism=None):
else:
raise ValueError("No coercion map from %s to %s" % (codomain,ring))
return AlgebraFromMorphism(defining_morphism, coerce)


def TowerExtensions(*rings):
tower = rings[-1]
for i in range(len(rings)-2, -1, -1):
tower = RingExtension(rings[i], tower)
return tower
13 changes: 11 additions & 2 deletions src/sage/rings/algebra_from_morphism_element.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,22 @@ cdef class AlgebraFMElement(CommutativeAlgebraElement):
- Xavier Caruso (2016)
"""
def __init__(self, parent, element, *args, **kwds):
def __init__(self, parent, x, *args, **kwds):
from sage.rings.algebra_from_morphism import AlgebraFromMorphism
if not isinstance(parent, AlgebraFromMorphism):
raise TypeError("%s is not an instance of AlgebraFromMorphism" % parent)
if isinstance(x, AlgebraFMElement):
x = x._backend()
try:
parentx = x.parent()
if parent.base().has_coerce_map_from(parentx):
x = parent.base().coerce_map_from(parentx)(x)
x = parent.defining_morphism()(x)
except AttributeError:
pass
Element.__init__(self, parent)
ring = parent._backend()
self._element = ring(element, *args, **kwds)
self._element = ring(x, *args, **kwds)

def _repr_(self):
r"""
Expand Down
2 changes: 1 addition & 1 deletion src/sage/rings/all.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,4 @@
del absolute_import

# Extensions
from sage.rings.algebra_from_morphism_constructor import RingExtension
from sage.rings.algebra_from_morphism_constructor import RingExtension, TowerExtensions
21 changes: 21 additions & 0 deletions src/sage/rings/homset.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,3 +332,24 @@ def _coerce_impl(self, x):
if x.parent() == self:
return morphism.RingHomomorphism_from_quotient(self, x._phi())
raise TypeError


class AlgebraFromMorphismHomset(RingHomset_generic):
def __call__(self, *args, **kwargs):
from sage.rings.morphism import AlgebraFromMorphismHomomorphism
return AlgebraFromMorphismHomomorphism(self, *args, **kwargs)

def _coerce_impl(self, x):
from sage.rings.morphism import AlgebraFromMorphismHomomorphism
from sage.rings.algebra_from_morphism import AlgebraFromMorphism
if isinstance(x, AlgebraFromMorphismHomomorphism):
x = x._backend()
domain = self.domain()
if isinstance(domain, AlgebraFromMorphism):
domain = domain._backend()
codomain = self.codomain()
if isinstance(codomain, AlgebraFromMorphism):
codomain = codomain._backend()
if domain is x.domain() and codomain is x.codomain():
return AlgebraFromMorphismHomomorphism(self, x)
raise TypeError
2 changes: 0 additions & 2 deletions src/sage/rings/morphism.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ cdef class FrobeniusEndomorphism_generic(RingHomomorphism):
cdef class RingHomomorphism_coercion(RingHomomorphism):
pass

cdef class AlgebraToRing(RingHomomorphism):
cpdef Element _call_(self, x)

cdef class AlgebraFromMorphismHomomorphism(RingHomomorphism):
cdef _backend_morphism
Expand Down
95 changes: 46 additions & 49 deletions src/sage/rings/morphism.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2097,62 +2097,33 @@ cdef class FrobeniusEndomorphism_generic(RingHomomorphism):

from sage.rings.algebra_from_morphism import AlgebraFromMorphism

cdef class AlgebraToRing(RingHomomorphism):
cdef class AlgebraFromMorphismHomomorphism(RingHomomorphism):
r"""
Coercion map between an extension and its ring
It acts as the identity, only modifies the parent
EXAMPLES::
Homomorphisms between extensions
sage: K = GF(5^2)
sage: L = GF(5^4)
sage: E = RingExtension(L,K)
EXAMPLES:
sage: coerce_map = L.coerce_map_from(E)
sage: coerce_map
Ring morphism:
From: Finite Field in z4 of size 5^4 viewed as an algebra over its base
To: Finite Field in z4 of size 5^4
sage: type(coerce_map)
<type 'sage.rings.morphism.AlgebraToRing'>
sage: F = GF(5^2)
sage: K = GF(5^4)
sage: L = GF(5^8)
sage: E1 = RingExtension(K,F)
sage: E2 = RingExtension(L,K)
sage: x = E.random_element()
sage: x == coerce_map(x)
True
"""
cpdef Element _call_(self, x):
r"""
TESTS::
sage: K = GF(5^2)
sage: L = GF(5^4)
sage: E = RingExtension(L,K)
sage: coerce_map = L.coerce_map_from(E)
sage: x = coerce_map(E.gen()); x
z4
sage: x.parent() is L
True
"""
return x._backend()


cdef class AlgebraFromMorphismHomomorphism(RingHomomorphism):
def __init__(self, parent, backend_morphism):
def __init__(self, parent, backend):
RingHomomorphism.__init__(self, parent)
backend_domain = self.domain()
if isinstance(backend_domain, AlgebraFromMorphism):
backend_domain = backend_domain._backend()
backend_codomain = self.codomain()
if isinstance(backend_codomain, AlgebraFromMorphism):
backend_codomain = backend_codomain._backend()
if backend_morphism.domain() is not backend_domain:
backend = backend_morphism(backend)
if backend.domain() is not backend_domain:
raise TypeError("the domain of the backend morphism is not correct")
if backend_morphism.codomain() is not backend_codomain:
if backend.codomain() is not backend_codomain:
raise TypeError("the codomain of the backend morphism is not correct")
self._backend_morphism = backend_morphism
self._backend_morphism = backend
# We should probably allow for more general constructions but
# self._backend_morphism = backend_domain.Hom(backend_codomain)(*args, **kwargs)
# does not work currently
Expand All @@ -2165,13 +2136,8 @@ cdef class AlgebraFromMorphismHomomorphism(RingHomomorphism):
y = self._codomain(y)
return y

def _backend(self, forget=None):
backend = self._backend_morphism
if forget == "domain" and not isinstance(self.domain(), AlgebraFromMorphism):
return self.__class__(backend.domain().Hom(self._codomain), backend)
if forget == "codomain" and not isinstance(self.codomain(), AlgebraFromMorphism):
return self.__class__(self._domain.Hom(backend.codomain()), backend)
return backend
def _backend(self):
return self._backend_morphism

cdef _update_slots(self, dict _slots):
self._backend_morphism = _slots['_backend_morphism']
Expand All @@ -2182,3 +2148,34 @@ cdef class AlgebraFromMorphismHomomorphism(RingHomomorphism):
slots['_backend_morphism'] = self._backend_morphism
return slots



def _backend_morphism(f):
from sage.categories.map import FormalCompositeMap
if not isinstance(f.domain(), AlgebraFromMorphism) and not isinstance(f.codomain(), AlgebraFromMorphism):
return f
elif isinstance(f, AlgebraFromMorphismHomomorphism):
return f._backend()
elif isinstance(f, FormalCompositeMap):
return _backend_morphism(f.then()) * _backend_morphism(f.first())
else:
raise NotImplementedError

def backend_morphism(f, forget="all"):
try:
g = _backend_morphism(f)
if forget is None and (isinstance(f.domain(), AlgebraFromMorphism) or isinstance(f.codomain(), AlgebraFromMorphism)):
g = AlgebraFromMorphismHomomorphism(f.domain().Hom(f.codomain()), g)
if forget == "domain" and isinstance(f.codomain(), AlgebraFromMorphism):
g = AlgebraFromMorphismHomomorphism(g.domain().Hom(f.codomain()), g)
if forget == "codomain" and isinstance(f.domain(), AlgebraFromMorphism):
g = AlgebraFromMorphismHomomorphism(f.domain().Hom(g.codomain()), g)
except NotImplementedError:
g = f
if (forget == "all" or forget == "domain") and isinstance(f.domain(), AlgebraFromMorphism):
ring = f.domain()._backend()
g = g * AlgebraFromMorphismHomomorphism(ring.Hom(f.domain()), ring.Hom(ring).identity())
if (forget == "all" or forget == "codomain") and isinstance(f.codomain(), AlgebraFromMorphism):
ring = f.codomain()._backend()
g = AlgebraFromMorphismHomomorphism(f.codomain().Hom(ring), ring.Hom(ring).identity()) * g
return g

0 comments on commit 631f228

Please sign in to comment.