Navigation

Source code for sympy.polys.agca.homomorphisms

"""Computations with homomorphisms of modules and rings.This module implements classes for representing homomorphisms of rings andtheir modules. Instead of instantiating the classes directly, you should usethe function ``homomorphism(from, to, matrix)`` to create homomorphism objects."""from__future__importprint_function,divisionfromsympy.polys.agca.modulesimport(Module,FreeModule,QuotientModule,SubModule,SubQuotientModule)fromsympy.polys.polyerrorsimportCoercionFailedfromsympy.core.compatibilityimportrange# The main computational task for module homomorphisms is kernels.# For this reason, the concrete classes are organised by domain module type.

def_kernel(self):"""Compute the kernel of ``self``."""raiseNotImplementedErrordef_image(self):"""Compute the image of ``self``."""raiseNotImplementedErrordef_restrict_domain(self,sm):"""Implementation of domain restriction."""raiseNotImplementedErrordef_restrict_codomain(self,sm):"""Implementation of codomain restriction."""raiseNotImplementedErrordef_quotient_domain(self,sm):"""Implementation of domain quotient."""raiseNotImplementedErrordef_quotient_codomain(self,sm):"""Implementation of codomain quotient."""raiseNotImplementedError

def_apply(self,elem):"""Apply ``self`` to ``elem``."""raiseNotImplementedErrordef__call__(self,elem):returnself.codomain.convert(self._apply(self.domain.convert(elem)))def_compose(self,oth):""" Compose ``self`` with ``oth``, that is, return the homomorphism obtained by first applying then ``self``, then ``oth``. (This method is private since in this syntax, it is non-obvious which homomorphism is executed first.) """raiseNotImplementedErrordef_mul_scalar(self,c):"""Scalar multiplication. ``c`` is guaranteed in self.ring."""raiseNotImplementedErrordef_add(self,oth):""" Homomorphism addition. ``oth`` is guaranteed to be a homomorphism with same domain/codomain. """raiseNotImplementedErrordef_check_hom(self,oth):"""Helper to check that oth is a homomorphism with same domain/codomain."""ifnotisinstance(oth,ModuleHomomorphism):returnFalsereturnoth.domain==self.domainandoth.codomain==self.codomaindef__mul__(self,oth):ifisinstance(oth,ModuleHomomorphism)andself.domain==oth.codomain:returnoth._compose(self)try:returnself._mul_scalar(self.ring.convert(oth))exceptCoercionFailed:returnNotImplemented# NOTE: _compose will never be called from rmul__rmul__=__mul__def__div__(self,oth):try:returnself._mul_scalar(1/self.ring.convert(oth))exceptCoercionFailed:returnNotImplemented__truediv__=__div__def__add__(self,oth):ifself._check_hom(oth):returnself._add(oth)returnNotImplementeddef__sub__(self,oth):ifself._check_hom(oth):returnself._add(oth._mul_scalar(self.ring.convert(-1)))returnNotImplemented

classMatrixHomomorphism(ModuleHomomorphism):""" Helper class for all homomoprhisms which are expressed via a matrix. That is, for such homomorphisms ``domain`` is contained in a module generated by finitely many elements `e_1, \dots, e_n`, so that the homomorphism is determined uniquely by its action on the `e_i`. It can thus be represented as a vector of elements of the codomain module, or potentially a supermodule of the codomain module (and hence conventionally as a matrix, if there is a similar interpretation for elements of the codomain module). Note that this class does *not* assume that the `e_i` freely generate a submodule, nor that ``domain`` is even all of this submodule. It exists only to unify the interface. Do not instantiate. Attributes: - matrix - the list of images determining the homomorphism. NOTE: the elements of matrix belong to either self.codomain or self.codomain.container Still non-implemented methods: - kernel - _apply """def__init__(self,domain,codomain,matrix):ModuleHomomorphism.__init__(self,domain,codomain)iflen(matrix)!=domain.rank:raiseValueError('Need to provide %s elements, got %s'%(domain.rank,len(matrix)))converter=self.codomain.convertifisinstance(self.codomain,(SubModule,SubQuotientModule)):converter=self.codomain.container.convertself.matrix=tuple(converter(x)forxinmatrix)def_sympy_matrix(self):"""Helper function which returns a sympy matrix ``self.matrix``."""fromsympy.matricesimportMatrixc=lambdax:xifisinstance(self.codomain,(QuotientModule,SubQuotientModule)):c=lambdax:x.datareturnMatrix([[self.ring.to_sympy(y)foryinc(x)]forxinself.matrix]).Tdef__repr__(self):lines=repr(self._sympy_matrix()).split('\n')t=" : %s -> %s"%(self.domain,self.codomain)s=' '*len(t)n=len(lines)foriinrange(n//2):lines[i]+=slines[n//2]+=tforiinrange(n//2+1,n):lines[i]+=sreturn'\n'.join(lines)def_restrict_domain(self,sm):"""Implementation of domain restriction."""returnSubModuleHomomorphism(sm,self.codomain,self.matrix)def_restrict_codomain(self,sm):"""Implementation of codomain restriction."""returnself.__class__(self.domain,sm,self.matrix)def_quotient_domain(self,sm):"""Implementation of domain quotient."""returnself.__class__(self.domain/sm,self.codomain,self.matrix)def_quotient_codomain(self,sm):"""Implementation of codomain quotient."""Q=self.codomain/smconverter=Q.convertifisinstance(self.codomain,SubModule):converter=Q.container.convertreturnself.__class__(self.domain,self.codomain/sm,[converter(x)forxinself.matrix])def_add(self,oth):returnself.__class__(self.domain,self.codomain,[x+yforx,yinzip(self.matrix,oth.matrix)])def_mul_scalar(self,c):returnself.__class__(self.domain,self.codomain,[c*xforxinself.matrix])def_compose(self,oth):returnself.__class__(self.domain,oth.codomain,[oth(x)forxinself.matrix])classFreeModuleHomomorphism(MatrixHomomorphism):""" Concrete class for homomorphisms with domain a free module or a quotient thereof. Do not instantiate; the constructor does not check that your data is well defined. Use the ``homomorphism`` function instead: >>> from sympy import QQ >>> from sympy.abc import x >>> from sympy.polys.agca import homomorphism >>> F = QQ.old_poly_ring(x).free_module(2) >>> homomorphism(F, F, [[1, 0], [0, 1]]) Matrix([ [1, 0], : QQ[x]**2 -> QQ[x]**2 [0, 1]]) """def_apply(self,elem):ifisinstance(self.domain,QuotientModule):elem=elem.datareturnsum(x*eforx,einzip(elem,self.matrix))def_image(self):returnself.codomain.submodule(*self.matrix)def_kernel(self):# The domain is either a free module or a quotient thereof.# It does not matter if it is a quotient, because that won't increase# the kernel.# Our generators {e_i} are sent to the matrix entries {b_i}.# The kernel is essentially the syzygy module of these {b_i}.syz=self.image().syzygy_module()returnself.domain.submodule(*syz.gens)classSubModuleHomomorphism(MatrixHomomorphism):""" Concrete class for homomorphism with domain a submodule of a free module or a quotient thereof. Do not instantiate; the constructor does not check that your data is well defined. Use the ``homomorphism`` function instead: >>> from sympy import QQ >>> from sympy.abc import x >>> from sympy.polys.agca import homomorphism >>> M = QQ.old_poly_ring(x).free_module(2)*x >>> homomorphism(M, M, [[1, 0], [0, 1]]) Matrix([ [1, 0], : <[x, 0], [0, x]> -> <[x, 0], [0, x]> [0, 1]]) """def_apply(self,elem):ifisinstance(self.domain,SubQuotientModule):elem=elem.datareturnsum(x*eforx,einzip(elem,self.matrix))def_image(self):returnself.codomain.submodule(*[self(x)forxinself.domain.gens])def_kernel(self):syz=self.image().syzygy_module()returnself.domain.submodule(*[sum(xi*giforxi,giinzip(s,self.domain.gens))forsinsyz.gens])