Ticket #14828: trac_14828_padic_polynomials.patch

File trac_14828_padic_polynomials.patch, 39.8 KB (added by caruso, 6 years ago)
  • sage/geometry/newton_polygon.py

    # HG changeset patch
    # User Xavier Caruso <xavier.caruso@normalesup.org>
    # Date 1362306702 -3600
    # Node ID f84a2fa36d4e6a84ac6f1c7a71a5a5fb676f5385
    # Parent  c15ae313df2c14ff4f3de4c3f7a9bd1c04e60b7e
    Trac #14828: Slope factorisation of padic polynomials
    
    diff --git a/sage/geometry/newton_polygon.py b/sage/geometry/newton_polygon.py
    a b  
    751751                y += slope
    752752                vertices.append((x,y))
    753753        else:
    754             vertices = arg
     754            vertices = [ ]
     755            for (x,y) in arg:
     756                if y is not Infinity:
     757                    vertices.append((x,y))
    755758        if len(vertices) == 0:
    756759            polyhedron = Polyhedron(base_ring=self.base_ring(), ambient_dim=2)
    757760        else:
  • sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py

    diff --git a/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py b/sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py
    a b  
    2121ZZ = sage.rings.integer_ring.ZZ
    2222PrecisionError = precision_error.PrecisionError
    2323Integer = sage.rings.integer.Integer
    24 Polynomial_generic_domain = sage.rings.polynomial.polynomial_element_generic.Polynomial_generic_domain
    2524Polynomial_integer_dense = sage.rings.polynomial.polynomial_integer_dense_ntl.Polynomial_integer_dense_ntl
     25Polynomial_generic_cdv = sage.rings.polynomial.polynomial_element_generic.Polynomial_generic_cdv
    2626
    27 class Polynomial_padic_capped_relative_dense(Polynomial_generic_domain):
     27class Polynomial_padic_capped_relative_dense(Polynomial_generic_cdv):
    2828    def __init__(self, parent, x=None, check=True, is_gen=False, construct = False, absprec = infinity, relprec = infinity):
    2929        """
    3030        TESTS:
     
    3737            (1 + O(13^7))*t + (2 + O(13^7))
    3838        """
    3939        Polynomial.__init__(self, parent, is_gen=is_gen)
     40        self._polygon = None
    4041        parentbr = parent.base_ring()
    4142        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
    4243        if construct:
     
    294295         13^2 + O(13^9),
    295296         0,
    296297         2 + O(13^7)]
    297          """
    298 
     298        """
    299299        if self._list is None:
    300300            self._comp_list()
    301301        return list(self._list)
     
    758758    def __copy__(self):
    759759        return Polynomial_padic_capped_relative_dense(self.parent(), (copy.copy(self._poly), self._valbase, copy.copy(self._relprecs), self._normalized, copy.copy(self._valaddeds), copy.copy(self._list)), construct = True)
    760760
    761     def degree(self):
     761    def degree(self, secure=False):
    762762        """
    763         Returns the degree of self, i.e., the largest $n$ so that the
    764         coefficient of $x^n$ does not compare equal to $0$.
     763        INPUT:
     764
     765        - secure  -- a boolean (default: False)
     766
     767        OUTPUT:
     768
     769        The degree of self.
     770
     771        If ``secure`` is True and the degree of this polynomial
     772        is not determined (because the leading coefficient is
     773        indistinguishable from 0), an error is raised
     774
     775        If ``secure`` is False, the returned value is the largest
     776        $n$ so that the coefficient of $x^n$ does not compare equal
     777        to $0$.
    765778
    766779        EXAMPLES:
     780
    767781            sage: K = Qp(3,10)
     782            sage: R.<T> = K[]
     783            sage: f = T + 2; f
     784            (1 + O(3^10))*T + (2 + O(3^10))
     785            sage: f.degree()
     786            1
     787            sage: (f-T).degree()
     788            0
     789            sage: (f-T).degree(secure=True)
     790            Traceback (most recent call last):
     791            ...
     792            PrecisionError: the leading coefficient is indistinguishable from 0
     793
    768794            sage: x = O(3^5)
    769             sage: li =[3^i * x for i in range(0,5)]; li
     795            sage: li = [3^i * x for i in range(0,5)]; li
    770796            [O(3^5), O(3^6), O(3^7), O(3^8), O(3^9)]
    771             sage: R.<T> = K[]
    772797            sage: f = R(li); f
    773798            (O(3^9))*T^4 + (O(3^8))*T^3 + (O(3^7))*T^2 + (O(3^6))*T + (O(3^5))
    774799            sage: f.degree()
    775800            -1
     801            sage: f.degree(secure=True)
     802            Traceback (most recent call last):
     803            ...
     804            PrecisionError: the leading coefficient is indistinguishable from 0
    776805        """
    777806        self._normalize()
    778         return Integer(self._poly.degree())
     807        deg = Integer(self._poly.degree())
     808        if secure and deg < self.prec_degree():
     809            raise PrecisionError("the leading coefficient is indistinguishable from 0")
     810        return deg
    779811
    780812    def prec_degree(self):
    781813        """
     
    837869        If n == None, returns a list of valuations of coefficients.  Otherwise,
    838870        returns the valuation of the coefficient of x^n.
    839871        """
     872        if self._valaddeds is None:
     873            self._comp_valaddeds()
    840874        if n is None:
    841875            self._normalize()
    842             return [c + self._valbase for c in self._valadded]
     876            return [ c + self._valbase for c in self._valaddeds ]
    843877        n = int(n)
    844878        if n < 0 or n >= len(self._relprecs):
    845879            return infinity
    846         if self._valaddeds is None:
    847             return self._valbase + self._poly[n].valuation(self.base_ring().prime())
    848         else:
    849             return self._valbase + self._valaddeds[n]
     880        return self._valbase + self._valaddeds[n]
    850881
    851882    def valuation(self, val_of_var = None):
    852883        """
     
    945976            zzpoly = self._poly.rescale(Integer(a))
    946977        return Polynomial_padic_capped_relative_dense(self.parent(), (zzpoly, self._valbase, relprec, False, valadded, None), construct = True)
    947978
    948     def quo_rem(self, right):
    949         return self._quo_rem_naive(right)
     979    def quo_rem(self, right, secure=False):
     980        return self._quo_rem_list(right, secure=secure)
    950981
    951982    def _quo_rem_naive(self, right):
    952983        """
     
    965996            f = f - a * (x ** (f.degree() - g.degree())) * g
    966997        return (quo, f)
    967998
     999    def _quo_rem_list(self, right, secure):
     1000        """
     1001        An implementation of quo_rem using lists of coefficients.
     1002
     1003        Faster than the previous one.
     1004
     1005        AUTHOR:
     1006
     1007        - Xavier Caruso (2013-03)
     1008        """
     1009        if right.is_zero():
     1010            raise ZeroDivisionError, "cannot divide by a polynomial indistinguishable from 0"
     1011        a = self.list(); da = len(a)-1
     1012        b = right.list(); db = right.degree(secure=secure)
     1013        inv = ~b[db]
     1014        q = [ ]
     1015        for i in range(da,db-1,-1):
     1016            c = inv*a[i]
     1017            q.append(c)
     1018            for j in range(db):
     1019                a[j+i-db] -= c*b[j]
     1020        q.reverse()
     1021        K = self.base_ring().fraction_field()
     1022        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
     1023        parent = PolynomialRing(K, name=self.parent().variable_name())
     1024        return parent(q), parent(a[:db])
     1025
    9681026    #def gcd(self, right):
    9691027    #    raise NotImplementedError
    9701028
     
    9861044    #def resultant(self):
    9871045    #    raise NotImplementedError
    9881046
    989     def newton_slopes(self):
     1047    def is_eisenstein(self, secure=False):
    9901048        """
    991         Returns a list of the Newton slopes of this polynomial.  These are the valuations of the roots of this polynomial.
     1049        Return True if this polynomial is an Eisenstein polynomial.
    9921050
    9931051        EXAMPLES:
    994         sage: K = Qp(13)
    995         sage: R.<t> = K[]
    996         sage: f = t^4 + 13^5*t^2 + 4*13^2*t - 13^7
    997         sage: f.newton_polygon()
    998         [(0, 7), (1, 2), (4, 0)]
    999         sage: f.newton_slopes()
    1000         [5, 2/3, 2/3, 2/3]
     1052
     1053            sage: K = Qp(5)
     1054            sage: R.<t> = K[]
     1055            sage: f = 5 + 5*t + t^4
     1056            sage: f.is_eisenstein()
     1057            True
     1058
     1059        TESTS:
     1060
     1061            sage: f = R([K(5,1),0,0,1]); f
     1062            (1 + O(5^20))*t^3 + (O(5))
     1063            sage: f.is_eisenstein()
     1064            Traceback (most recent call last):
     1065            ...
     1066            PrecisionError: Not enough precision on the constant coefficient
     1067
     1068            sage: g = R([5,K(0,0),0,1]); g
     1069            (1 + O(5^20))*t^3 + (O(5^0))*t + (5 + O(5^21))
     1070            sage: g.is_eisenstein()
     1071            True
     1072            sage: g.is_eisenstein(secure=True)
     1073            Traceback (most recent call last):
     1074            ...
     1075            PrecisionError: Not enough precision on the coefficient of t
     1076
     1077        AUTHOR:
     1078
     1079        - Xavier Caruso (2013-03)
    10011080        """
    1002         polygon = self.newton_polygon()
    1003         if polygon == []:
    1004             return []
    1005         answer = [infinity] * polygon[0][0]
    1006         for m in range(1, len(polygon)):
    1007             dx = polygon[m][0] - polygon[m - 1][0]
    1008             dy = polygon[m][1] - polygon[m - 1][1]
    1009             answer.extend([-dy / dx] * dx)
    1010         return answer       
     1081        deg = self.degree()
     1082        if secure and self.prec_degree() > deg:
     1083            raise PrecisionError("The degree of the polynomial is not determined")
     1084        if self._valaddeds is None:
     1085            self._comp_valaddeds()
     1086        compval = 1 - self._valbase
     1087        valaddeds = self._valaddeds
     1088        relprecs = self._relprecs
     1089        if relprecs[0] <= compval:   # not enough precision
     1090            if valaddeds[0] < relprecs[0]: return False
     1091            raise PrecisionError("Not enough precision on the constant coefficient")
     1092        else:
     1093            if valaddeds[0] != compval: return False
     1094        for i in range(1,deg):
     1095            if relprecs[i] < compval:   # not enough precision
     1096                if valaddeds[i] < relprecs[i]: return False
     1097                if secure:
     1098                    if i == 1:
     1099                        raise PrecisionError("Not enough precision on the coefficient of %s" % self.variable_name())
     1100                    else:
     1101                        raise PrecisionError("Not enough precision on the coefficient of %s^%s" % (self.variable_name(), i))
     1102            else:
     1103                if valaddeds[i] < compval: return False
     1104        if valaddeds[deg] != -self._valbase: return False
     1105        return True
     1106
    10111107
    10121108    def newton_polygon(self):
    10131109        r"""
    10141110        Returns a list of vertices of the Newton polygon of this polynomial.
    10151111
    10161112        NOTES:
    1017         The vertices are listed so that the first coordinates are strictly increasing, up to the polynomial's degree (not the limit of available precision information).  Also note that if some coefficients have very low precision an error is raised.
    10181113
    1019         EXAMPLES:
    1020         sage: K = Qp(13)
    1021         sage: R.<t> = K[]
    1022         sage: f = t^4 + 13^5*t^2 + 4*13^2*t - 13^7
    1023         sage: f.newton_polygon()
    1024         [(0, 7), (1, 2), (4, 0)]
     1114        If some coefficients have not enough precision an error is raised.
     1115
     1116        EXAMPLES::
     1117
     1118            sage: K = Qp(5)
     1119            sage: R.<t> = K[]
     1120            sage: f = 5 + 3*t + t^4 + 25*t^10
     1121            sage: f.newton_polygon()
     1122            Finite Newton polygon with 4 vertices: (0, 1), (1, 0), (4, 0), (10, 2)
     1123
     1124            sage: g = f + K(0,0)*t^4; g
     1125            (5^2 + O(5^22))*t^10 + (O(5^0))*t^4 + (3 + O(5^20))*t + (5 + O(5^21))
     1126            sage: g.newton_polygon()
     1127            Traceback (most recent call last):
     1128            ...
     1129            PrecisionError: The coefficient of t^4 has not enough precision
     1130
     1131        AUTHOR:
     1132
     1133        - Xavier Caruso (2013-03-20)
    10251134        """
    1026         if self._poly == 0:
    1027             return []
    1028         for x in range(len(self._relprecs)):
    1029             if not self._relprecs[x] is infinity:
    1030                 break
    1031         if self._valaddeds is None:
    1032             self._comp_valaddeds()
    1033         if self._poly[x] == 0:
    1034             raise PrecisionError, "first term with non-infinite valuation must have determined valuation"
    1035         yrel = self._valaddeds[x]
    1036         answer = [(x, self._valbase + yrel)]
    1037         xf = self._poly.degree()
    1038         if xf == x:
    1039             return answer
    1040         yfrel = self._valaddeds[xf]
    1041         curslope = (yfrel - yrel) / (xf - x)
    1042         for i in range(x + 1, xf):
    1043             yrel += curslope
    1044             if self._valaddeds[i] < yrel:
    1045                 if self._relprecs[i] == self._valaddeds[i]:
    1046                     raise PrecisionError, "not enough precision known in coefficient %s to compute newton polygon"%i
    1047                 yrel = self._valaddeds[i]
    1048                 answer.append((i, self._valbase + yrel))
    1049                 curslope = (yfrel - yrel) / (xf - i)
    1050         from sage.misc.stopgap import stopgap
    1051         stopgap("Check that the Newton polygon below is actually convex.", 6667)
    1052         answer.append((xf, self._valbase + self._valaddeds[xf]))
    1053         return answer
    1054 
    1055     def hensel_lift(self, a):
    1056         raise NotImplementedError
     1135        if self._polygon is None:
     1136            if self._valaddeds is None:
     1137                self._comp_valaddeds()
     1138            from sage.geometry.newton_polygon import NewtonPolygon
     1139            self._polygon = polygon = NewtonPolygon([ (x,self._valaddeds[x]) for x in range(len(self._valaddeds)) ])
     1140            polygon_prec = NewtonPolygon([ (x,self._relprecs[x]) for x in range(len(self._relprecs)) ])
     1141            vertices = polygon.vertices(copy=False)
     1142            vertices_prec = polygon_prec.vertices(copy=False)
     1143            if vertices[0][0] > vertices_prec[0][0]:
     1144                self._polygon = "first term with non-infinite valuation must have determined valuation"
     1145            elif vertices[-1][0] < vertices_prec[-1][0]:
     1146                self._polygon = "last term with non-infinite valuation must have determined valuation"
     1147            else:
     1148                for (x,y) in vertices:
     1149                    if polygon_prec(x) <= y:
     1150                        self._polygon = "The coefficient of %s^%s has not enough precision" % (self.parent().variable_name(), x)
     1151                        break
     1152        if isinstance(self._polygon, str):
     1153            raise PrecisionError(self._polygon)
     1154        return self._polygon
    10571155
    10581156    def factor_mod(self):
    10591157        r"""
  • sage/rings/polynomial/polynomial_element.pxd

    diff --git a/sage/rings/polynomial/polynomial_element.pxd b/sage/rings/polynomial/polynomial_element.pxd
    a b  
    2828    cdef void __normalize(self)
    2929#    cdef _dict_to_list(self, x, zero)
    3030
     31cdef class Polynomial_generic_dense_inexact(Polynomial_generic_dense):
     32    pass
     33
    3134cpdef is_Polynomial(f)
    3235cpdef Polynomial_generic_dense _new_constant_dense_poly(list coeffs, Parent P, sample)
    3336
  • sage/rings/polynomial/polynomial_element.pyx

    diff --git a/sage/rings/polynomial/polynomial_element.pyx b/sage/rings/polynomial/polynomial_element.pyx
    a b  
    66666666def make_generic_polynomial(parent, coeffs):
    66676667    return parent(coeffs)
    66686668
     6669cdef class Polynomial_generic_dense_inexact(Polynomial_generic_dense):
     6670    """
     6671    A dense polynomial over an inexact ring.
     6672
     6673    AUTHOR:
     6674
     6675    - Xavier Caruso (2013-03)
     6676    """
     6677    cdef void __normalize(self):
     6678        cdef list x = self.__coeffs
     6679        cdef Py_ssize_t n = len(x) - 1
     6680        cdef RingElement c
     6681        while n >= 0:
     6682            c = x[n]
     6683            if c.is_zero() and c.precision_absolute() is infinity.Infinity:
     6684                del x[n]
     6685                n -= 1
     6686            else:
     6687                break
     6688
     6689    def degree(self, secure=False):
     6690        """
     6691        INPUT:
     6692
     6693        - secure  -- a boolean (default: False)
     6694
     6695        OUTPUT:
     6696
     6697        The degree of self.
     6698
     6699        If ``secure`` is True and the degree of this polynomial
     6700        is not determined (because the leading coefficient is
     6701        indistinguishable from 0), an error is raised
     6702
     6703        If ``secure`` is False, the returned value is the largest
     6704        $n$ so that the coefficient of $x^n$ does not compare equal
     6705        to $0$.
     6706
     6707        EXAMPLES:
     6708
     6709            sage: K = Qp(3,10)
     6710            sage: R.<T> = K[]
     6711            sage: f = T + 2; f
     6712            (1 + O(3^10))*T + (2 + O(3^10))
     6713            sage: f.degree()
     6714            1
     6715            sage: (f-T).degree()
     6716            0
     6717            sage: (f-T).degree(secure=True)
     6718            Traceback (most recent call last):
     6719            ...
     6720            PrecisionError: the leading coefficient is indistinguishable from 0
     6721
     6722            sage: x = O(3^5)
     6723            sage: li = [3^i * x for i in range(0,5)]; li
     6724            [O(3^5), O(3^6), O(3^7), O(3^8), O(3^9)]
     6725            sage: f = R(li); f
     6726            (O(3^9))*T^4 + (O(3^8))*T^3 + (O(3^7))*T^2 + (O(3^6))*T + (O(3^5))
     6727            sage: f.degree()
     6728            -1
     6729            sage: f.degree(secure=True)
     6730            Traceback (most recent call last):
     6731            ...
     6732            PrecisionError: the leading coefficient is indistinguishable from 0
     6733
     6734        AUTHOR:
     6735
     6736        - Xavier Caruso (2013-03)
     6737        """
     6738        coeffs = self.__coeffs
     6739        d = len(coeffs) - 1
     6740        while d >= 0:
     6741            c = coeffs[d]
     6742            if c.is_zero():
     6743                if secure:
     6744                    from sage.rings.padics.precision_error import PrecisionError
     6745                    raise PrecisionError("the leading coefficient is indistinguishable from 0")
     6746                else:
     6747                    d -= 1
     6748            else:
     6749                break
     6750        return d
     6751
     6752    def prec_degree(self):
     6753        """
     6754        Returns the largest $n$ so that precision information is
     6755        stored about the coefficient of $x^n$.
     6756
     6757        Always greater than or equal to degree.
     6758
     6759        EXAMPLES:
     6760
     6761            sage: K = Qp(3,10)
     6762            sage: R.<T> = K[]
     6763            sage: f = T + 2; f
     6764            (1 + O(3^10))*T + (2 + O(3^10))
     6765            sage: f.degree()
     6766            1
     6767            sage: f.prec_degree()
     6768            1
     6769
     6770            sage: g = f - T; g
     6771            (O(3^10))*T + (2 + O(3^10))
     6772            sage: g.degree()
     6773            0
     6774            sage: g.prec_degree()
     6775            1
     6776
     6777        AUTHOR:
     6778
     6779        - Xavier Caruso (2013-03)
     6780        """
     6781        return len(self.__coeffs) - 1
     6782
     6783
    66696784cdef class ConstantPolynomialSection(Map):
    66706785    """
    66716786    This class is used for conversion from a polynomial ring to its base ring.
  • sage/rings/polynomial/polynomial_element_generic.py

    diff --git a/sage/rings/polynomial/polynomial_element_generic.py b/sage/rings/polynomial/polynomial_element_generic.py
    a b  
    2929#                  http://www.gnu.org/licenses/
    3030################################################################################
    3131
    32 from sage.rings.polynomial.polynomial_element import Polynomial, Polynomial_generic_dense
     32from sage.rings.polynomial.polynomial_element import Polynomial, Polynomial_generic_dense, Polynomial_generic_dense_inexact
    3333from sage.structure.element import IntegralDomainElement, EuclideanDomainElement
    3434
    3535from sage.rings.polynomial.polynomial_singular_interface import Polynomial_singular_repr
     
    666666    def __init__(self, parent, x=None, check=True, is_gen = False, construct=False):
    667667        Polynomial_generic_dense.__init__(self, parent, x, check, is_gen)
    668668
     669
     670##########################################
     671# Over discrete valuation rings and fields
     672##########################################
     673
     674class Polynomial_generic_cdv(Polynomial):
     675    """
     676    A generic class for polynomials over complete discrete
     677    valuation rings and fields.
     678
     679    AUTHOR:
     680
     681    - Xavier Caruso (2013-03)
     682    """
     683    def newton_slopes(self, repetition=True):
     684        """
     685        Returns a list of the Newton slopes of this polynomial.  These are the valuations of the roots of this polynomial.
     686
     687        If ``repetition`` is True, each slope is repeated a number of times equal to its multiplicity.
     688        Otherwise it appears only one time.
     689
     690        EXAMPLES:
     691
     692            sage: K = Qp(5)
     693            sage: R.<t> = K[]
     694            sage: f = 5 + 3*t + t^4 + 25*t^10
     695            sage: f.newton_polygon()
     696            Finite Newton polygon with 4 vertices: (0, 1), (1, 0), (4, 0), (10, 2)
     697            sage: f.newton_slopes()
     698            [1, 0, 0, 0, -1/3, -1/3, -1/3, -1/3, -1/3, -1/3]
     699
     700            sage: f.newton_slopes(repetition=False)
     701            [1, 0, -1/3]
     702
     703        AUTHOR:
     704
     705        - Xavier Caruso (2013-03-20)
     706        """
     707        polygon = self.newton_polygon()
     708        return [ -s for s in polygon.slopes(repetition=repetition) ]
     709
     710    def newton_polygon(self):
     711        r"""
     712        Returns a list of vertices of the Newton polygon of this polynomial.
     713
     714        NOTES:
     715
     716        If some coefficients have not enough precision an error is raised.
     717
     718        EXAMPLES:
     719
     720            sage: K = Qp(5)
     721            sage: R.<t> = K[]
     722            sage: f = 5 + 3*t + t^4 + 25*t^10
     723            sage: f.newton_polygon()
     724            Finite Newton polygon with 4 vertices: (0, 1), (1, 0), (4, 0), (10, 2)
     725
     726            sage: g = f + K(0,0)*t^4; g
     727            (5^2 + O(5^22))*t^10 + (O(5^0))*t^4 + (3 + O(5^20))*t + (5 + O(5^21))
     728            sage: g.newton_polygon()
     729            Traceback (most recent call last):
     730            ...
     731            PrecisionError: The coefficient of t^4 has not enough precision
     732
     733        AUTHOR:
     734
     735        - Xavier Caruso (2013-03-20)
     736        """
     737        d = self.degree()
     738        from sage.geometry.newton_polygon import NewtonPolygon
     739        polygon = NewtonPolygon([ (x, self[x].valuation()) for x in range(d+1) ])
     740        polygon_prec = NewtonPolygon([ (x, self[x].precision_absolute()) for x in range(d+1) ])
     741        vertices = polygon.vertices(copy=False)
     742        vertices_prec = polygon_prec.vertices(copy=False)
     743        if vertices[0][0] > vertices_prec[0][0]:
     744            raise PrecisionError("first term with non-infinite valuation must have determined valuation")
     745        elif vertices[-1][0] < vertices_prec[-1][0]:
     746            raise PrecisionError("last term with non-infinite valuation must have determined valuation")
     747        else:
     748            for (x,y) in vertices:
     749                if polygon_prec(x) <= y:
     750                    raise PrecisionError("The coefficient of %s^%s has not enough precision" % (self.parent().variable_name(), x))
     751        return polygon
     752
     753    def hensel_lift(self, a):
     754        """
     755        Lift `a` to a root of this polynomial (using
     756        Newton iteration).
     757
     758        If `a` is not close enough to a root (so that
     759        Newton iteration does not converge), an error
     760        is raised.
     761
     762        EXAMPLES:
     763
     764            sage: K = Qp(5, 10)
     765            sage: P.<x> = PolynomialRing(K)
     766            sage: f = x^2 + 1
     767            sage: root = f.hensel_lift(2); root
     768            2 + 5 + 2*5^2 + 5^3 + 3*5^4 + 4*5^5 + 2*5^6 + 3*5^7 + 3*5^9 + O(5^10)
     769            sage: f(root)
     770            O(5^10)
     771
     772            sage: g = (x^2 + 1)*(x - 7)
     773            sage: g.hensel_lift(2)  # here, 2 is a multiple root modulo p
     774            Traceback (most recent call last):
     775            ...
     776            ValueError: a is not close enough to a root of this polynomial
     777
     778        AUTHOR:
     779
     780        - Xavier Caruso (2013-03-23)
     781        """
     782        base = self.base_ring()
     783        selfa = self(a)
     784        der = self.derivative()
     785        dera = der(a)
     786        if selfa.valuation() <= 2*dera.valuation():
     787            raise ValueError("a is not close enough to a root of this polynomial")
     788        # Newton iteration
     789        # Todo: compute everything up to the adequate precision at each step
     790        b = ~dera
     791        while(True):
     792            na = a - selfa * b
     793            if na == a: return a
     794            a = na
     795            selfa = self(a)
     796            dera = der(a)
     797            b *= 2 - dera*b
     798
     799
     800    def _factor_of_degree(self, deg):
     801        """
     802        Return a factor of self of degree deg.
     803        Algorithm is Newton iteration.
     804
     805        This fails if deg is not a breakpoint in the Newton polygon of self.
     806
     807        Only for internal use!
     808
     809        EXAMPLES:
     810
     811            sage: K = Qp(5)
     812            sage: R.<x> = K[]
     813            sage: K = Qp(5)
     814            sage: R.<t> = K[]
     815            sage: f = 5 + 3*t + t^4 + 25*t^10
     816
     817            sage: g = f._factor_of_degree(4)
     818            sage: (f % g).is_zero()
     819            True
     820
     821            sage: g = f._factor_of_degree(3)    # not tested
     822            Traceback (most recent call last)
     823            ...
     824            KeyboardInterrupt:
     825
     826        AUTHOR:
     827
     828        - Xavier Caruso (2013-03-20)
     829        """
     830        coeffs = self.list()
     831        a = self.truncate(deg+1)
     832        b = v = self.parent()(1)
     833        x = self % a
     834        while(not x.is_zero()):
     835            a += (v*x) % a
     836            b, x = self.quo_rem(a)
     837            b %= a
     838            v = (v * (2 - b*v)) % a
     839
     840        return a
     841
     842    def factor_of_slope(self, slope=None):
     843        """
     844        INPUT:
     845
     846        -  slope -- a rational number (default: the first slope
     847           in the Newton polygon of self)
     848
     849        OUTPUT:
     850
     851        The factor of self corresponding to the slope ``slope`` (i.e.
     852        the unique monic divisor of self whose slope is ``slope`` and
     853        degree is the length of ``slope`` in the Newton polygon).
     854
     855        EXAMPLES:
     856
     857            sage: K = Qp(5)
     858            sage: R.<x> = K[]
     859            sage: K = Qp(5)
     860            sage: R.<t> = K[]
     861            sage: f = 5 + 3*t + t^4 + 25*t^10
     862            sage: f.newton_slopes()
     863            [1, 0, 0, 0, -1/3, -1/3, -1/3, -1/3, -1/3, -1/3]
     864
     865            sage: g = f.factor_of_slope(0)
     866            sage: g.newton_slopes()
     867            [0, 0, 0]
     868            sage: (f % g).is_zero()
     869            True
     870
     871            sage: h = f.factor_of_slope()
     872            sage: h.newton_slopes()
     873            [1]
     874            sage: (f % h).is_zero()
     875            True
     876
     877        If ``slope`` is not a slope of self, the corresponding factor
     878        is `1`::
     879
     880            sage: f.factor_of_slope(-1)
     881            (1 + O(5^20))
     882
     883        AUTHOR:
     884
     885        - Xavier Caruso (2013-03-20)
     886        """
     887        one = self.parent()(1)
     888        vertices = self.newton_polygon().vertices(copy=False)
     889        if len(vertices) < 2:
     890            if slope is Infinity:
     891                return self.parent().gen() ** self.degree()
     892            else:
     893                return one
     894        if slope is None:
     895            deg_first = vertices[0][0]
     896            deg_last = vertices[1][0]
     897        else:
     898            (deg_first, y_first) = vertices[0]
     899            for i in range(1, len(vertices)):
     900                (deg_last, y_last) = vertices[i]
     901                slope_cur = (y_first - y_last) / (deg_last - deg_first)
     902                if slope_cur == slope:
     903                    break
     904                elif slope_cur < slope:
     905                    return one
     906                deg_first = deg_last
     907                y_first = y_last
     908            if slope_cur > slope:
     909                return one
     910        if deg_last == self.degree():
     911            div = self
     912        else:
     913            div = self._factor_of_degree(deg_last)
     914        if deg_first > 0:
     915            div2 = div._factor_of_degree(deg_first)
     916            div,_ = div.quo_rem(div2)
     917        return div.monic()
     918
     919    def slope_factorization(self):
     920        """
     921        Return a factorization of self into a product of factors
     922        corresponding to each slope in the Newton polygon.
     923
     924        EXAMPLES:
     925
     926            sage: K = Qp(5)
     927            sage: R.<x> = K[]
     928            sage: K = Qp(5)
     929            sage: R.<t> = K[]
     930            sage: f = 5 + 3*t + t^4 + 25*t^10
     931            sage: f.newton_slopes()
     932            [1, 0, 0, 0, -1/3, -1/3, -1/3, -1/3, -1/3, -1/3]
     933
     934            sage: F = f.slope_factorization()
     935            sage: F.prod() == f
     936            True
     937            sage: for (f,_) in F:
     938            ...       print f.newton_slopes()
     939            [-1/3, -1/3, -1/3, -1/3, -1/3, -1/3]
     940            [0, 0, 0]
     941            [1]
     942
     943        AUTHOR:
     944
     945        - Xavier Caruso (2013-03-20)
     946        """
     947        vertices = self.newton_polygon().vertices(copy=False)
     948
     949        unit = self.leading_coefficient()
     950        P = ~unit * self
     951
     952        deg_first = vertices[0][0]
     953        factors = [ ]
     954        if deg_first > 0:
     955            P >>= deg_first
     956            factors.append((self._parent.gen(), deg_first))
     957        if len(vertices) > 2:
     958            for i in range(1, len(vertices)-1):
     959                deg = vertices[i][0]
     960                div = P._factor_of_degree(deg-deg_first)
     961                factors.append((div,1))
     962                P,_ = P.quo_rem(div)
     963                deg_first = deg
     964        if len(vertices) > 1:
     965            factors.append((P,1))
     966        factors.reverse()
     967        return Factorization(factors,sort=False,unit=unit)
     968
     969class Polynomial_generic_dense_cdv(Polynomial_generic_dense_inexact, Polynomial_generic_cdv):
     970    pass
     971
     972class Polynomial_generic_sparse_cdv(Polynomial_generic_sparse, Polynomial_generic_cdv):
     973    pass
     974
     975
     976class Polynomial_generic_cdvr(Polynomial_generic_cdv):
     977    pass
     978
     979class Polynomial_generic_dense_cdvr(Polynomial_generic_dense_cdv, Polynomial_generic_cdvr):
     980    pass
     981
     982class Polynomial_generic_sparse_cdvr(Polynomial_generic_sparse_cdv, Polynomial_generic_cdvr):
     983    pass
     984
     985
     986class Polynomial_generic_cdvf(Polynomial_generic_cdv, Polynomial_generic_field):
     987    pass
     988
     989class Polynomial_generic_dense_cdvf(Polynomial_generic_dense_cdv, Polynomial_generic_cdvf):
     990    pass
     991
     992class Polynomial_generic_sparse_cdvf(Polynomial_generic_sparse_cdv, Polynomial_generic_cdvf):
     993    pass
     994
    669995############################################################################
    670996# XXX:  Ensures that the generic polynomials implemented in SAGE via PARI  #
    671997# until at least until 4.5.0 unpickle correctly as polynomials implemented #
  • sage/rings/polynomial/polynomial_ring.py

    diff --git a/sage/rings/polynomial/polynomial_ring.py b/sage/rings/polynomial/polynomial_ring.py
    a b  
    13541354       
    13551355class PolynomialRing_integral_domain(PolynomialRing_commutative, integral_domain.IntegralDomain):
    13561356    def __init__(self, base_ring, name="x", sparse=False, implementation=None,
    1357             element_class=None):
     1357            element_class=None, category=None):
    13581358        """
    13591359        TESTS:
    13601360            sage: from sage.rings.polynomial.polynomial_ring import PolynomialRing_integral_domain as PRing
     
    13851385                else:
    13861386                    raise ValueError, "Unknown implementation %s for ZZ[x]"%implementation
    13871387        PolynomialRing_commutative.__init__(self, base_ring, name=name,
    1388                 sparse=sparse, element_class=element_class)
    1389    
     1388                sparse=sparse, element_class=element_class, category=category)
     1389
    13901390    def _repr_(self):
    13911391        """
    13921392        TESTS:
     
    14021402                           PolynomialRing_singular_repr,
    14031403                           principal_ideal_domain.PrincipalIdealDomain,
    14041404                           ):
    1405     def __init__(self, base_ring, name="x", sparse=False, element_class=None, implementation=None):
     1405    def __init__(self, base_ring, name="x", sparse=False, element_class=None, implementation=None, category=None):
    14061406        """
    14071407        TESTS:
    14081408            sage: from sage.rings.polynomial.polynomial_ring import PolynomialRing_field as PRing
     
    14501450            else:
    14511451                element_class = polynomial_element_generic.Polynomial_generic_dense_field
    14521452
    1453         PolynomialRing_integral_domain.__init__(self, base_ring, name=name, sparse=sparse, element_class=element_class)
     1453        PolynomialRing_integral_domain.__init__(self, base_ring, name=name, sparse=sparse, element_class=element_class, category=category)
    14541454
    14551455        self._has_singular = can_convert_to_singular(self)
    14561456
     
    17961796                self._fraction_field = FractionField_1poly_field(self)
    17971797            return self._fraction_field
    17981798
    1799 class PolynomialRing_dense_padic_ring_generic(PolynomialRing_integral_domain):
    1800     pass
    18011799
    1802 class PolynomialRing_dense_padic_field_generic(PolynomialRing_field):
    1803     pass
     1800class PolynomialRing_cdvr(PolynomialRing_integral_domain):
     1801    def __init__(self, base_ring, name=None, sparse=False, element_class=None, category=None):
     1802        if element_class is None:
     1803            if sparse:
     1804                from sage.rings.polynomial.polynomial_element_generic import Polynomial_generic_sparse_cdvr
     1805                element_class = Polynomial_generic_sparse_cdvr
     1806            else:
     1807                from sage.rings.polynomial.polynomial_element_generic import Polynomial_generic_dense_cdvr
     1808                element_class = Polynomial_generic_dense_cdvr
     1809        PolynomialRing_integral_domain.__init__(self, base_ring, name, sparse, element_class=element_class, category=category)
     1810
     1811class PolynomialRing_cdvf(PolynomialRing_cdvr, PolynomialRing_field):
     1812    def __init__(self, base_ring, name=None, sparse=False, element_class=None, category=None):
     1813        if element_class is None:
     1814            if sparse:
     1815                from sage.rings.polynomial.polynomial_element_generic import Polynomial_generic_sparse_cdvf
     1816                element_class = Polynomial_generic_sparse_cdvf
     1817            else:
     1818                from sage.rings.polynomial.polynomial_element_generic import Polynomial_generic_dense_cdvf
     1819                element_class = Polynomial_generic_dense_cdvf
     1820        PolynomialRing_field.__init__(self, base_ring, name, sparse, element_class=element_class, category=category)
     1821
     1822class PolynomialRing_dense_padic_ring_generic(PolynomialRing_cdvr):
     1823    def __init__(self, base_ring, name=None, element_class=None, category=None):
     1824        PolynomialRing_cdvr.__init__(self, base_ring, sparse=False, name=name, element_class=element_class, category=category)
     1825
     1826class PolynomialRing_dense_padic_field_generic(PolynomialRing_cdvf):
     1827    def __init__(self, base_ring, name=None, element_class=None, category=None):
     1828        PolynomialRing_cdvf.__init__(self, base_ring, sparse=False, name=name, element_class=element_class, category=category)
    18041829
    18051830class PolynomialRing_dense_padic_ring_capped_relative(PolynomialRing_dense_padic_ring_generic):
    1806     def __init__(self, base_ring, name=None, element_class=None):
     1831    def __init__(self, base_ring, name=None, element_class=None, category=None):
    18071832        """
    18081833        TESTS::
    18091834       
     
    18191844                    Polynomial_padic_capped_relative_dense
    18201845            element_class = Polynomial_padic_capped_relative_dense
    18211846        PolynomialRing_dense_padic_ring_generic.__init__(self, base_ring,
    1822                 name=name, element_class=element_class)
     1847                name=name, element_class=element_class, category=category)
    18231848
    18241849class PolynomialRing_dense_padic_ring_capped_absolute(PolynomialRing_dense_padic_ring_generic):
    1825     def __init__(self, base_ring, name=None, element_class=None):
     1850    def __init__(self, base_ring, name=None, element_class=None, category=None):
    18261851        """
    18271852        TESTS::
    18281853       
     
    18371862                    Polynomial_padic_flat
    18381863            element_class = Polynomial_padic_flat
    18391864        PolynomialRing_dense_padic_ring_generic.__init__(self, base_ring,
    1840                 name=name, element_class=element_class)
     1865                name=name, element_class=element_class, category=category)
    18411866
    18421867class PolynomialRing_dense_padic_ring_fixed_mod(PolynomialRing_dense_padic_ring_generic):
    1843     def __init__(self, base_ring, name=None, element_class=None):
     1868    def __init__(self, base_ring, name=None, element_class=None, category=None):
    18441869        """
    18451870        TESTS::
    18461871       
     
    18561881                    Polynomial_padic_flat
    18571882            element_class = Polynomial_padic_flat
    18581883        PolynomialRing_dense_padic_ring_generic.__init__(self, base_ring,
    1859                 name=name, element_class=element_class)
     1884                name=name, element_class=element_class, category=category)
    18601885
    18611886class PolynomialRing_dense_padic_ring_lazy(PolynomialRing_dense_padic_ring_generic):
    1862     def __init__(self, base_ring, name=None, element_class=None):
     1887    def __init__(self, base_ring, name=None, element_class=None, category=None):
    18631888        """
    18641889        TESTS::
    18651890       
     
    18751900        if element_class is None:
    18761901            element_class = polynomial_element_generic.Polynomial_generic_dense
    18771902        PolynomialRing_dense_padic_ring_generic.__init__(self, base_ring,
    1878                 name=name, element_class=element_class)
     1903                name=name, element_class=element_class, category=category)
    18791904
    18801905class PolynomialRing_dense_padic_field_capped_relative(PolynomialRing_dense_padic_field_generic):
    1881     def __init__(self, base_ring, name=None, element_class=None):
     1906    def __init__(self, base_ring, name=None, element_class=None, category=None):
    18821907        """
    18831908        TESTS::
    18841909       
     
    18941919                    Polynomial_padic_capped_relative_dense
    18951920            element_class = Polynomial_padic_capped_relative_dense
    18961921        PolynomialRing_dense_padic_field_generic.__init__(self, base_ring,
    1897                 name=name, element_class=element_class)
     1922                name=name, element_class=element_class, category=category)
    18981923
    18991924class PolynomialRing_dense_padic_field_lazy(PolynomialRing_dense_padic_field_generic):
    1900     def __init__(self, base_ring, name=None, element_class=None):
     1925    def __init__(self, base_ring, name=None, element_class=None, category=None):
    19011926        """
    19021927        TESTS::
    19031928       
     
    19121937        if element_class is None:
    19131938            element_class = polynomial_element_generic.Polynomial_generic_dense
    19141939        PolynomialRing_dense_padic_field_generic.__init__(self, base_ring,
    1915                 name=name, element_class=element_class)
     1940                name=name, element_class=element_class, category=category)
    19161941
    19171942class PolynomialRing_dense_mod_n(PolynomialRing_commutative):
    19181943    def __init__(self, base_ring, name=None, element_class=None,
    1919             implementation=None):
     1944            implementation=None, category=None):
    19201945        """
    19211946        TESTS::
    19221947       
     
    19681993                else:
    19691994                    element_class = modn_dense_ntl.Polynomial_dense_modn_ntl_ZZ
    19701995        PolynomialRing_commutative.__init__(self, base_ring, name=name,
    1971                 element_class=element_class)
     1996                element_class=element_class, category=category)
    19721997
    19731998    @cached_method
    19741999    def modulus(self):
     
    19962021class PolynomialRing_dense_mod_p(PolynomialRing_field,
    19972022                                 PolynomialRing_dense_mod_n,
    19982023                                 PolynomialRing_singular_repr):
    1999     def __init__(self, base_ring, name="x", implementation=None):
     2024    def __init__(self, base_ring, name="x", implementation=None, category=None):
    20002025        """
    20012026        TESTS::
    20022027       
     
    20472072            self._implementation_names = ('NTL',)
    20482073            self._implementation_repr = ' (using NTL)'
    20492074        PolynomialRing_dense_mod_n.__init__(self, base_ring, name=name,
    2050                 element_class=element_class)
     2075                element_class=element_class, category=category)
    20512076
    20522077        from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular
    20532078        self._has_singular = can_convert_to_singular(self)
  • sage/rings/polynomial/polynomial_ring_constructor.py

    diff --git a/sage/rings/polynomial/polynomial_ring_constructor.py b/sage/rings/polynomial/polynomial_ring_constructor.py
    a b  
    5252_ID = IntegralDomains()
    5353from sage.categories.commutative_rings import CommutativeRings
    5454_CommutativeRings = CommutativeRings()
     55from sage.categories.complete_discrete_valuation import CompleteDiscreteValuationRings, CompleteDiscreteValuationFields
     56_CompleteDiscreteValuationRings = CompleteDiscreteValuationRings()
     57_CompleteDiscreteValuationFields = CompleteDiscreteValuationFields()
    5558
    5659import weakref
    5760_cache = weakref.WeakValueDictionary()
     
    545548        elif isinstance(base_ring, padic_base_leaves.pAdicRingFixedMod):
    546549            R = m.PolynomialRing_dense_padic_ring_fixed_mod(base_ring, name)
    547550
     551        elif base_ring in _CompleteDiscreteValuationRings:
     552            R = m.PolynomialRing_cdvr(base_ring, name, sparse)
     553
     554        elif base_ring in _CompleteDiscreteValuationFields:
     555            R = m.PolynomialRing_cdvf(base_ring, name, sparse)
     556
    548557        elif base_ring.is_field(proof = False):
    549558            R = m.PolynomialRing_field(base_ring, name, sparse, implementation=implementation)
    550559