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

Commit

Permalink
more work on morphisms
Browse files Browse the repository at this point in the history
  • Loading branch information
xcaruso committed Sep 13, 2019
1 parent 6a52519 commit 0433a1a
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 19 deletions.
35 changes: 26 additions & 9 deletions src/sage/rings/ring_extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,17 @@ def from_base_ring(self, r):
return self.element_class(self, r)

def _Hom_(self, other, category):
if isinstance(self, RingExtension_class) or isinstance(other, RingExtension_class):
from sage.rings.ring_extension_homset import RingExtensionHomset
return RingExtensionHomset(self, other, category)
from sage.rings.ring_extension_homset import RingExtensionHomset
return RingExtensionHomset(self, other, category)

def hom(self, im_gens, codomain=None, base_map=None, check=True, category=None):
from sage.rings.ring_extension_homset import RingExtensionHomset
from sage.rings.ring_extension_morphism import RingExtensionHomomorphism
if codomain is None:
from sage.structure.sequence import Sequence
codomain = Sequence(im_gens).universe()
parent = RingExtensionHomset(self, codomain, category)
return RingExtensionHomomorphism(parent, im_gens, base_map, check)

def _pushout_(self, other):
r"""
Expand Down Expand Up @@ -441,11 +449,11 @@ def _an_element_(self):
elt = self._ring.an_element()
return self.element_class(self, elt)

def gens(self):
def gens(self, base=None):
return tuple([ self(x) for x in self._ring.gens() ])

def ngens(self):
return len(self.gens())
def ngens(self, base=None):
return len(self.gens(base))

def gen(self):
r"""
Expand Down Expand Up @@ -710,8 +718,17 @@ def modulus(self, var='x'):
S = PolynomialRing(self._base, name=var)
return S(coeffs)

def gens(self):
return (self(self._gen),)
def gens(self, base=None):
if base is None:
return (self(self._gen),)
gens = tuple([])
b = self
while b is not base:
gens += b.gens()
if b is b.base_ring():
raise ValueError("(%s) is not defined over (%s)" % (self, base))
b = b.base_ring()
return gens

def _repr_(self):
def _repr_(self, base=None):
return "%s in %s with defining polynomial %s over its base" % (self._type, self._name, self.modulus())
40 changes: 36 additions & 4 deletions src/sage/rings/ring_extension_element.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

from sage.structure.element cimport CommutativeAlgebraElement
from sage.structure.element cimport Element
from sage.rings.integer_ring import ZZ
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing


cdef class RingExtensionElement(CommutativeAlgebraElement):
Expand Down Expand Up @@ -225,10 +227,8 @@ cdef class RingExtensionElement(CommutativeAlgebraElement):

cdef class RingExtensionWithBasisElement(RingExtensionElement):
def _repr_(self):
parent = self._parent
names = parent._names
_, _, j = parent.vector_space()
coeffs = j(self)
names = self._parent._names
coeffs = self.vector()
s = ""
for i in range(len(names)):
if coeffs[i].is_zero(): continue
Expand All @@ -254,6 +254,38 @@ cdef class RingExtensionWithBasisElement(RingExtensionElement):
if s == "": return "0"
return s

def vector(self, base=None):
_, _, j = self._parent.vector_space(base)
return j(self)

def polynomial(self, base=None, var='x'):
from sage.rings.ring_extension import RingExtensionWithGen
if base is None:
base = self._parent._base
degrees = [ ]
b = self._parent
degree = 1
while b is not base:
if not isinstance(b, RingExtensionWithGen):
raise NotImplementedError
reldeg = b.relative_degree()
degree *= reldeg
degrees.append(reldeg)
if b is b.base_ring():
raise ValueError("(%s) is not defined over (%s)" % (self, base))
b = b.base_ring()
v = self.vector(base)
coeffs = { }
S = PolynomialRing(base, len(degrees), names=var)
for i in range(degree):
ii = ZZ(i)
exponents = [ ]
for j in range(len(degrees)):
ii, exponent = ii.quo_rem(degrees[j])
exponents.append(exponent)
coeffs[tuple(exponents)] = v[i]
return S(coeffs)

def matrix(self, base=None):
from sage.matrix.matrix_space import MatrixSpace
parent = self._parent
Expand Down
3 changes: 3 additions & 0 deletions src/sage/rings/ring_extension_morphism.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ from sage.rings.morphism cimport RingHomomorphism

cdef class RingExtensionHomomorphism(RingHomomorphism):
cdef _backend_morphism
cdef _gens
cdef _im_gens
cdef _base_map
cpdef Element _call_(self, x)
78 changes: 72 additions & 6 deletions src/sage/rings/ring_extension_morphism.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ cdef class RingExtensionHomomorphism(RingHomomorphism):
sage: E2 = RingExtension(L,K)
"""
def __init__(self, parent, defn, base_map=None, check=False):
def __init__(self, parent, defn, base_map=None, check=True):
RingHomomorphism.__init__(self, parent)
backend_domain = domain = self.domain()
if isinstance(backend_domain, RingExtension_class):
Expand All @@ -81,9 +81,24 @@ cdef class RingExtensionHomomorphism(RingHomomorphism):
if backend.codomain() is not backend_codomain:
raise TypeError("the codomain of the backend morphism is not correct")
self._backend_morphism = backend
self._im_gens = None
self._base_map = False
elif isinstance(defn, (list, tuple)):
if domain.ngens() != len(defn):
raise ValueError("the number of images does not match the number of generators")
# We figure out what is the base
if base_map is not None:
base = base_map.domain()
gens = domain.gens(base)
else:
base = domain
gens = tuple([])
while True:
if len(gens) == len(defn):
break
if len(gens) > len(defn) or base is base.base_ring():
raise ValueError("the number of images does not match the number of generators")
gens += base.gens()
base = base.base_ring()
# We construct the backend morphism
im_gens = [ codomain(x) for x in defn ]
backend_bases = [ backend_domain ]
b = backend_domain.base_ring()
Expand All @@ -95,18 +110,49 @@ cdef class RingExtensionHomomorphism(RingHomomorphism):
for current_domain in backend_bases:
current_im_gens = [ ]
for x in current_domain.gens():
pol = codomain(backend_codomain(x)).polynomial()
pol = domain(backend_domain(x)).polynomial(base)
if base_map is not None:
pol = pol.map_coefficients(base_map)
y = pol(im_gens)
if isinstance(codomain, RingExtension_class):
y = y._backend()
current_im_gens.append(y)
current_morphism = current_domain.Hom(backend_codomain)(current_im_gens, base_map=current_morphism, check=check)
current_morphism = current_domain.hom(current_im_gens, base_map=current_morphism, check=check)
# We check that everything went well
if check:
for i in range(len(gens)):
if current_morphism(domain(gens[i])._backend()) != im_gens[i]._backend():
raise ValueError("images do not define a valid homomorphism")
# instead of the following code, it would be better to write
# if backend_morphism(base_map) != current_morphism.restriction(base._backend()):
# raise ValueError("images do not define a valid homomorphism")
# but many things need to be implemented for that
current = base
while current is not current.base_ring():
for g in current.gens():
gg = domain(g)
x = gg._backend()
if base_map is None:
y = codomain(gg)
else:
y = codomain(base_map(g))
if isinstance(codomain, RingExtension_class):
y = y._backend()
if current_morphism(x) != y:
raise ValueError("images do not define a valid homomorphism")
current = current.base_ring()
self._backend_morphism = current_morphism
self._im_gens = im_gens[:domain.ngens()]
if base is domain.base_ring():
self._base_map = base_map
else:
self._base_map = {
'im_gens': defn[domain.ngens():],
'base_map': base_map,
'check': False
}
else:
raise TypeError
self._base_map = base_map

cpdef Element _call_(self, x):
if isinstance(self.domain(), RingExtension_class):
Expand All @@ -120,8 +166,28 @@ cdef class RingExtensionHomomorphism(RingHomomorphism):
return self._backend_morphism

def base_map(self):
if self._base_map is False:
raise NotImplementedError
if isinstance(self._base_map, dict):
self._base_map = self.domain().base_ring().hom(**self._base_map)
return self._base_map

def _repr_defn(self):
import re
s = ""
if self._im_gens is not None:
gens = self.domain().gens()
for i in range(len(gens)):
s += "%s |--> %s\n" % (gens[i], self._im_gens[i])
if self._base_map is not None:
s += "with base map"
ss = self.base_map()._repr_defn()
ss = re.sub('\nwith base map:?$', '', ss, 0, re.MULTILINE)
if ss != "": s += ":\n" + ss
if s[-1] == "\n":
s = s[:-1]
return s

cdef _update_slots(self, dict _slots):
self._backend_morphism = _slots['_backend_morphism']
RingHomomorphism._update_slots(self, _slots)
Expand Down

0 comments on commit 0433a1a

Please sign in to comment.