Path: blob/master/src/sage/schemes/projective/endPN_minimal_model.py
8820 views
r"""1Sage functions to compute minimal models of rational functions2under the conjugation action of `PGL_2(QQ)`.34AUTHORS:56- Alex Molnar (May 22, 2012)78- Brian Stout, Ben Hutz (Nov 2013): Modified code to use projective morphism functionality9so that it can be included in Sage.1011REFERENCES:1213.. [Bruin-Molnar] N. Bruin and A. Molnar, Minimal models for rational14functions in a dynamical setting15LMS Journal of Computation and Mathematics, Volume 15 (2012), pp 400-417.1617.. [Molnar] A. Molnar, Fractional Linear Minimal Models of Rational Functions,18M.Sc. Thesis.19"""2021#*****************************************************************************22# Copyright (C) 2012 Alexander Molnar23#24# Distributed under the terms of the GNU General Public License (GPL)25# as published by the Free Software Foundation; either version 2 of26# the License, or (at your option) any later version.27# http://www.gnu.org/licenses/28#*****************************************************************************2930from sage.categories.homset import End31from copy import copy32from sage.matrix.constructor import matrix33from sage.rings.arith import gcd34from sage.rings.finite_rings.integer_mod_ring import Zmod35from sage.rings.integer_ring import ZZ36from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing37from sage.rings.rational_field import QQ38from sage.schemes.affine.affine_space import AffineSpace3940def bCheck(c,v,p,b):41r"""42Compute a lower bound on the value of ``b`` needed, for a transformation43`A(z) = z*p^k + b` to satisfy `ord_p(Res(\phi^A)) < ord_p(Res(\phi))` for a44rational map `\phi`. See Theorem 3.3.5 in [Molnar, M.Sc. thesis].4546INPUT:4748- ``c`` -- a list of polynomials in `b`. See v for their use.4950- ``v`` -- a list of rational numbers, where we are considering the inequalities51`ord_p(c[i]) > v[i]`.5253- ``p`` -- a prime.5455- ``b`` -- local variable.5657OUTPUT:5859- ``bval`` -- Integer, lower bound in Theorem 3.3.56061EXAMPLES::6263sage: R.<b> = PolynomialRing(QQ)64sage: from sage.schemes.projective.endPN_minimal_model import bCheck65sage: bCheck(11664*b^2 + 70227*b + 76059, 15/2, 3, b)66-167"""68val = (v+1).floor()69deg = c.degree()70coeffs = c.coeffs()71lcoeff = coeffs[deg]; coeffs.remove(lcoeff)72check1 = [(coeffs[i].valuation(p) - lcoeff.valuation(p))/(deg - i) for i in range(0,len(coeffs)) if coeffs[i] != 0]73check2 = (val - lcoeff.valuation(p))/deg74check1.append(check2)75bval = min(check1)76return (bval).ceil()777879def scale(c,v,p):80r"""81Given an integral polynomial ``c``, we can write `c = p^i*c'`, where ``p`` does not82divide ``c``. Returns ``c'`` and `v - i` where `i` is the smallest valuation of the83coefficients of `c`.8485INPUT:8687- ``c`` -- an integer polynomial8889- ``v`` -- an integer - the bound on the exponent from blift9091- ``p`` -- a prime9293OUTPUT:9495- Boolean -- the new exponent bound is 0 or negative9697- the scaled integer polynomial9899- an integer the new exponent bound100101EXAMPLES::102103sage: R.<b> = PolynomialRing(QQ)104sage: from sage.schemes.projective.endPN_minimal_model import scale105sage: scale(24*b^3 + 108*b^2 + 162*b + 81, 1, 3)106[False, 8*b^3 + 36*b^2 + 54*b + 27, 0]107"""108scaleval = min([coeff.valuation(p) for coeff in c.coefficients()])109if scaleval > 0:110c = c/(p**scaleval)111v = v - scaleval112if v <= 0:113flag = False114else:115flag = True116return [flag,c,v]117118119def blift(LF,Li,p,S=None):120r"""121Search for a solution to the given list of inequalities. If found, lift the solution to122an appropriate valuation. See Lemma 3.3.6 in [Molnar, M.Sc. thesis]123124INPUT:125126- ``LF`` -- a list of integer polynomials in one variable (the normalized coefficients)127128- ``Li`` -- an integer, the bound on coefficients129130- ``p`` -- a prime131132OUTPUT:133134- Boolean -- whether or not the lift is successful135136- integer -- the lift137138EXAMPLES::139140sage: R.<b> = PolynomialRing(QQ)141sage: from sage.schemes.projective.endPN_minimal_model import blift142sage: blift([8*b^3 + 12*b^2 + 6*b + 1, 48*b^2 + 483*b + 117, 72*b + 1341, -24*b^2 + 411*b + 99, -144*b + 1233, -216*b], 2, 3)143(True, 4)144"""145146P = LF[0].parent()147#Determine which inequalities are trivial, and scale the rest, so that we only lift148#as many times as needed.149keepScaledIneqs = [scale(P(coeff),Li,p) for coeff in LF if coeff != 0]150keptVals = [i[2] for i in keepScaledIneqs if i[0]]151if keptVals != []:152#Determine the valuation to lift until.153liftval = max(keptVals)154else:155#All inequalities are satisfied.156return True,1157if S is None:158S = PolynomialRing(Zmod(p),'b')159keptScaledIneqs = [S(i[1]) for i in keepScaledIneqs if i[0]]160#We need a solution for each polynomial on the left hand side of the inequalities,161#so we need only find a solution for their gcd.162g = gcd(keptScaledIneqs)163rts = g.roots(multiplicities=False)164for r in rts:165#Recursively try to lift each root166r_initial=QQ(r)167newInput = P([r_initial,p])168LG = [F(newInput) for F in LF]169lift,lifted = blift(LG,Li,p,S=S)170if lift:171#Lift successful.172return True,r_initial+ p*lifted173#Lift non successful.174return False,0175176177def affine_minimal(vp, return_transformation = False,D=None, quick = False):178r"""179Given vp a scheme morphisms on the projective line over the rationals,180this procedure determines if `\phi` is minimal. In particular, it determines181if the map is affine minimal, which is enough to decide if it is minimal182or not. See Proposition 2.10 in [Bruin-Molnar].183184INPUT:185186- ``vp`` -- scheme morphism on the projective line.187188- ``D`` -- a list of primes, in case one only wants to check minimality189at those specific primes.190191- ``return_transformation`` -- a boolean value, default value True. This192signals a return of the ``PGL_2`` transformation193to conjugate ``vp`` to the calculated minimal194model. default: False195196- ``quick`` -- a boolean value. If true the algorithm terminates once197algorithm determines F/G is not minimal, otherwise algorithm198only terminates once a minimal model has been found.199200OUTPUT:201202- ``newvp`` -- scheme morphism on the projective line.203204- ``conj`` -- linear fractional transformation which conjugates ``vp`` to ``newvp``205206EXAMPLES::207sage: PS.<X,Y> = ProjectiveSpace(QQ,1)208sage: H = Hom(PS,PS)209sage: vp = H([X^2+9*Y^2,X*Y])210sage: from sage.schemes.projective.endPN_minimal_model import affine_minimal211sage: affine_minimal(vp,True)212(213Scheme endomorphism of Projective Space of dimension 1 over Rational214Field215Defn: Defined on coordinates by sending (X : Y) to216(X^2 + Y^2 : X*Y)217,218[3 0]219[0 1]220)221"""222BR=vp.domain().base_ring()223conj=matrix(BR,2,2,1)224flag = True225d = vp.degree()226227vp.normalize_coordinates();228Affvp=vp.dehomogenize(1)229R=Affvp.coordinate_ring()230if R.is_field():231#want the polynomial ring not the fraction field232R=R.ring()233F=R(Affvp[0].numerator())234G=R(Affvp[0].denominator())235if G.degree()==0 or F.degree()==0:236raise TypeError("Affine minimality is only considered for maps not of the form f or 1/f for a polynomial f.")237z=F.parent().gen(0)238minF,minG = F,G239#If the valuation of a prime in the resultant is small enough, we can say the240#map is affine minimal at that prime without using the local minimality loop. See241#Theorem 3.2.2 in [Molnar, M.Sc. thesis]242if d%2 == 0:243g = d244else:245g = 2*d246Res = vp.resultant();247248#Some quantities needed for the local minimization loop, but we compute now249#since the value is constant, so we do not wish to compute in every local loop.250#See Theorem 3.3.3 in [Molnar, M.Sc thesis]251252H=F-z*minG253d1=F.degree()254A=AffineSpace(BR,1,H.parent().variable_name())255end_ring=End(A)256257ubRes = end_ring([H/minG]).homogenize(1).resultant()258#Set the primes to check minimality at, if not already prescribed259if D is None:260D = ZZ(Res).prime_divisors()261262#Check minimality at all primes in D. If D is all primes dividing263#Res(minF/minG), this is enough to show whether minF/minG is minimal or not. See264#Propositions 3.2.1 and 3.3.7 in [Molnar, M.Sc. thesis].265for p in D:266while True:267if Res.valuation(p) < g:268#The model is minimal at p269min = True270else:271#The model may not be minimal at p.272newvp,conj = Min(vp,p,ubRes,conj)273if newvp==vp:274min=True275else:276vp=newvp277Affvp=vp.dehomogenize(1)278min=False279if min:280#The model is minimal at p281break282elif F == Affvp[0].numerator() and G == Affvp[0].denominator():283#The model is minimal at p284break285else:286#The model is not minimal at p287flag = False288if quick:289break290if quick and not flag:291break292293if quick: #only return whether the model is minimal294return flag295296if return_transformation:297return vp, conj298return vp299300def Min(Fun,p,ubRes,conj):301r"""302Local loop for Affine_minimal, where we check minimality at the prime p.303First we bound the possible k in our transformations A = zp^k + b. See Theorems3043.3.2 and 3.3.3 in [Molnar, M.Sc. thesis].305306INPUT:307308- ``Fun`` -- a projective space morphisms309310- ``p`` - a prime.311312- ``ubRes`` -- integer -- The upper bound needed for Theorem 3.3.3 in [Molnar, M.Sc. thesis].313314- ``conj`` -- a 2x2 matrix keeping track of the conjugation315316OUTPUT:317318- Boolean -- True if Fun is minimal at ``p``, False otherwise319320- a projective morphism minimal at ``p``321322EXAMPLES::323324sage: P.<x,y> = ProjectiveSpace(QQ,1)325sage: H = End(P)326sage: f = H([149*x^2 + 39*x*y + y^2, -8*x^2 + 137*x*y + 33*y^2])327sage: from sage.schemes.projective.endPN_minimal_model import Min328sage: Min(f, 3, -27000000, matrix(QQ,[[1, 0],[0, 1]]))329(330Scheme endomorphism of Projective Space of dimension 1 over Rational331Field332Defn: Defined on coordinates by sending (x : y) to333(181*x^2 + 313*x*y + 81*y^2 : -24*x^2 + 73*x*y + 151*y^2)334,335[3 4]336[0 1]337)338"""339340d=Fun.degree()341AffFun=Fun.dehomogenize(1)342R=AffFun.coordinate_ring()343if R.is_field():344#want the polynomial ring not the fraction field345R=R.ring()346F=R(AffFun[0].numerator())347G=R(AffFun[0].denominator())348dG = G.degree()349if dG > (d+1)/2:350lowerBound = (-2*(G[dG]).valuation(p)/(2*dG - d + 1) + 1).floor()351else:352lowerBound = (-2*(F[d]).valuation(p)/(d-1) + 1).floor()353upperBound = 2*(ubRes.valuation(p))354355if upperBound < lowerBound:356#There are no possible transformations to reduce the resultant.357return Fun,conj358else:359#Looping over each possible k, we search for transformations to reduce the360#resultant of F/G361k = lowerBound362Qb = PolynomialRing(QQ,'b')363b=Qb.gen(0)364Q = PolynomialRing(Qb,'z')365z=Q.gen(0)366while k <= upperBound:367A = (p**k)*z + b368Ft = Q(F(A) - b*G(A))369Gt = Q((p**k)*G(A))370Fcoeffs = Ft.coeffs()371Gcoeffs = Gt.coeffs()372coeffs = Fcoeffs + Gcoeffs373RHS = (d + 1)*k/2374#If there is some b such that Res(phi^A) < Res(phi), we must have ord_p(c) >375#RHS for each c in coeffs.376377#Make sure constant coefficients in coeffs satisfy the inequality.378379if all( QQ(c).valuation(p) > RHS for c in coeffs if c.degree() ==0 ):380#Constant coefficients in coeffs have large enough valuation, so check381#the rest.382#We start by checking if simply picking b=0 works383if all(c(0).valuation(p) > RHS for c in coeffs):384#A = z*p^k satisfies the inequalities, and F/G is not minimal385386#"Conjugating by", p,"^", k, "*z +", 0387newconj=matrix(QQ,2,2,[p**k,0,0,1])388minFun=Fun.conjugate(newconj)389conj=conj*newconj390391minFun.normalize_coordinates()392return minFun, conj393394#Otherwise we search if any value of b will work. We start by finding a395#minimum bound on the valuation of b that is necessary. See Theorem 3.3.5396#in [Molnar, M.Sc. thesis].397bval = max([bCheck(coeff,RHS,p,b) for coeff in coeffs if coeff.degree() > 0])398399#We scale the coefficients in coeffs, so that we may assume ord_p(b) is400#at least 0401scaledCoeffs = [coeff(b*(p**bval)) for coeff in coeffs]402403#We now scale the inequalities, ord_p(coeff) > RHS, so that coeff is in404#ZZ[b]405scale = QQ(max([coeff.denominator() for coeff in scaledCoeffs]))406normalizedCoeffs = [coeff*scale for coeff in scaledCoeffs]407scaleRHS = RHS + scale.valuation(p)408409#We now search for integers that satisfy the inequality ord_p(coeff) >410#RHS. See Lemma 3.3.6 in [Molnar, M.Sc. thesis].411bound = (scaleRHS+1).floor()412bool,sol = blift(normalizedCoeffs,bound,p)413414#If bool is true after lifting, we have a solution b, and F/G is not415#minimal.416if bool:417#Rescale, conjugate and return new map418bsol = QQ(sol*(p**bval))419#"Conjugating by ", p,"^", k, "*z +", bsol420newconj=matrix(QQ,2,2,[p**k,bsol,0,1])421minFun=Fun.conjugate(newconj)422conj=conj*newconj423424minFun.normalize_coordinates()425return minFun, conj426k = k + 1427return Fun, conj428429430