def is_morphism(self): r""" returns ``True`` if self is a morphism (no common zero of defining polynomials). The map is a morphism if and only if the ideal generated by the defining polynomials is the unit ideal. OUTPUT: - Boolean EXAMPLES:: sage: P.<x,y>=ProjectiveSpace(QQ,1) sage: H=Hom(P,P) sage: f=H([x^2+y^2,y^2]) sage: f.is_morphism() True :: sage: P.<x,y,z>=ProjectiveSpace(RR,2) sage: H=Hom(P,P) sage: f=H([x*z-y*z,x^2-y^2,z^2]) sage: f.is_morphism() False :: sage: R.<t>=PolynomialRing(GF(5)) sage: P.<x,y,z>=ProjectiveSpace(R,2) sage: H=Hom(P,P) sage: f=H([x*z-t*y^2,x^2-y^2,t*z^2]) sage: f.is_morphism() True """ from sage.schemes.projective.projective_space import is_ProjectiveSpace if is_ProjectiveSpace(self.domain())==False or is_ProjectiveSpace(self.codomain())==False: raise NotImplementedError R=self.coordinate_ring() F=self._polys if R.base_ring().is_field(): J=R.ideal(F) else: S=PolynomialRing(R.base_ring().fraction_field(),R.gens(),R.ngens()) J=S.ideal([S.coerce(F[i]) for i in range(R.ngens())]) if J.dimension()>0: return False else: return True
def primes_of_bad_reduction(self, check=True): r""" Determines the primes of bad reduction for a map `self: \mathbb{P}^N \to \mathbb{P}^N` defined over `\ZZ` or `\QQ`. If ``check`` is ``True``, each prime is verified to be of bad reduction. ALGORITHM: `p` is a prime of bad reduction if and only if the defining polynomials of self have a common zero. Or stated another way, `p` is a prime of bad reducion if and only if the radical of the ideal defined by the defining polynomials of self is not `(x_0,x_1,\ldots,x_N)`. This happens if and only if some power of each `x_i` is not in the ideal defined by the defining polynomials of self. This last condition is what is checked. The lcm of the coefficients of the monomials `x_i` in a groebner basis is computed. This may return extra primes. INPUT: - ``check`` -- Boolean (optional - default: ``True``) OUTPUT: - a list of integer primes. EXAMPLES:: sage: P.<x,y>=ProjectiveSpace(QQ,1) sage: H=Hom(P,P) sage: f=H([1/3*x^2+1/2*y^2,y^2]) sage: print f.primes_of_bad_reduction() [2, 3] :: sage: P.<x,y,z,w>=ProjectiveSpace(QQ,3) sage: H=Hom(P,P) sage: f=H([12*x*z-7*y^2,31*x^2-y^2,26*z^2,3*w^2-z*w]) sage: f.primes_of_bad_reduction() [2, 3, 7, 13, 31] :: This is an example where check=False returns extra primes sage: P.<x,y,z>=ProjectiveSpace(ZZ,2) sage: H=Hom(P,P) sage: f=H([3*x*y^2 + 7*y^3 - 4*y^2*z + 5*z^3, -5*x^3 + x^2*y + y^3 + 2*x^2*z, -2*x^2*y + x*y^2 + y^3 - 4*y^2*z + x*z^2]) sage: f.primes_of_bad_reduction(False) [2, 5, 37, 2239, 304432717] sage: f.primes_of_bad_reduction() [5, 37, 2239, 304432717] """ if self.base_ring() != ZZ and self.base_ring() != QQ: raise TypeError("Must be ZZ or QQ") from sage.schemes.projective.projective_space import is_ProjectiveSpace if is_ProjectiveSpace(self.domain())==False or is_ProjectiveSpace(self.codomain())==False: raise NotImplementedError R=self.coordinate_ring() F=self._polys if R.base_ring().is_field(): J=R.ideal(F) else: S=PolynomialRing(R.base_ring().fraction_field(),R.gens(),R.ngens()) J=S.ideal([S.coerce(F[i]) for i in range(R.ngens())]) if J.dimension()>0: raise TypeError("Not a morphism.") #normalize to coefficients in the ring not the fraction field. F=[F[i]*lcm([F[j].denominator() for j in range(len(F))]) for i in range(len(F))] #move the ideal to the ring of integers if R.base_ring().is_field(): S=PolynomialRing(R.base_ring().ring_of_integers(),R.gens(),R.ngens()) F=[F[i].change_ring(R.base_ring().ring_of_integers()) for i in range(len(F))] J=S.ideal(F) else: J=R.ideal(F) GB=J.groebner_basis() badprimes=[] #get the primes dividing the coefficients of the monomials x_i^k_i for i in range(len(GB)): LT=GB[i].lt().degrees() power=0 for j in range(R.ngens()): if LT[j]!=0: power+=1 if power==1: badprimes=badprimes+GB[i].lt().coefficients()[0].support() badprimes=list(set(badprimes)) badprimes.sort() #check to return only the truly bad primes if check==True: index=0 while index < len(badprimes): #figure out which primes are really bad primes... S=PolynomialRing(GF(badprimes[index]),R.gens(),R.ngens()) J=S.ideal([S.coerce(F[j]) for j in range(R.ngens())]) if J.dimension()==0: badprimes.pop(index) else: index+=1 return(badprimes)