Esempio n. 1
0
def slope_factors(f, vK, precision, reduce_function, slope_bound=0):
    r"""
    Return the slope factorizaton of a polynomial over a discretely valued field.

    INPUT:

    - ``f`` -- a monic polynomial over a field `K`
    - ``vK`` -- a discrete valuation on `K` such that `f` for which `f` is integral
    - ``precision`` -- a positive integer
    - ``reduce_function`` -- a function which takes as input an element of `K`
      and returns a simpler approximation; the approximation is with relative
      precision ``precision``
    - ``slope_bound`` -- a rational number (default: `0`)

    OUTPUT: a dictionary ``F`` whose keys are the pairwise distinct slopes `s_i`
    of the Newton polygon of `f` and the corresponding value is a monic and integral
    polynomial whose Newton polygon has exactly one slope `s_i`, and

    .. MATH::

            v_K( f - \prod_i f_i ) > N,

    where `N` is ``precision`` plus the valuation of the first nonzero
    coefficient of `f`.

    If ``slope_bound`` is given, then only those factors with slope < ``slope_bound``
    are computed.

    EXAMPLES::

        sage: from mclf.padic_extensions.slope_factors import slope_factors
        sage: from mclf.padic_extensions.fake_padic_completions import FakepAdicCompletion
        sage: from sage.all import GaussValuation
        sage: R.<x> = QQ[]
        sage: v2 = QQ.valuation(2)
        sage: Q2 = FakepAdicCompletion(QQ, v2)
        sage: f = (x - 2)*(x + 4) + 2^8
        sage: reduce_function = lambda g: Q2.reduce_polynomial(g, 5)
        sage: F = slope_factors(f, v2, 3, reduce_function)
        sage: F
        {-2: x + 4, -1: x + 30}
        sage: v = GaussValuation(R, v2)
        sage: v(f - F[-2]*F[-1])
        5


    """
    vK = vK.scale(1 / vK(vK.uniformizer()))
    assert not f.is_constant(), "f must be nonconstant"
    assert f.is_monic(), "f must be monic"
    NP = NewtonPolygon([(i, vK(f[i])) for i in range(f.degree() + 1)])
    slopes = NP.slopes(False)
    assert all(s <= 0 for s in slopes), "f must be integral"
    F = {}
    for i in range(len(slopes)):
        s = slopes[i]
        if s < slope_bound:
            g = factor_with_slope(f, vK, s, precision, reduce_function)
            F[s] = g
    return F
Esempio n. 2
0
    def upper_components(self):
        r"""
        Return the list of all upper components lying above this lower component.

        This lower component corresponds to a discrete valuation `v` on a rational
        function field `L(x)` extending the valuation `v_L`, where `L/K` is some
        finite extension of the base field `K`. The upper components correspond
        to the extensions of v to the function field of `Y_L` (which is a finite
        extension of `L(x)`).

        Since the computation of all extensions of a nonstandard valuation on a
        function field to a finite extension is not yet part of Sage, we have
        to appeal to the MacLane algorithm ourselves.

        EXAMPLES:

        This example shows that extending valuations also works if the equation
        is not integral wrt the valuation v ::

            sage: from mclf import *
            sage: R.<x> = QQ[]
            sage: Y = SuperellipticCurve(5*x^3 + 1, 2)
            sage: Y2 = SemistableModel(Y, QQ.valuation(5))
            sage: Y2.is_semistable()  # indirect doctest
            True

        """
        from sage.geometry.newton_polygon import NewtonPolygon
        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
        v = self.valuation()
        FY = self.reduction_tree().curve().function_field()
        FYL = base_change_of_function_field(FY, self.base_field())
        FXL = FYL.rational_function_field()
        assert v.domain() == FXL
        G = FYL.polynomial()
        # now FYL = FXL(y| G(y) = 0)

        # we first have to make G integral with respect to v
        np = NewtonPolygon([(i,v(G[i])) for i in range(G.degree() + 1)])
        r = np.slopes()[-1]   # the largest slope
        if r <= 0:      # G is integral w.r.t. v
            upper_valuations = [FYL.valuation(w)
                for w in v.mac_lane_approximants(FYL.polynomial(), require_incomparability=True)]
        else:           # G is not integral
            vK = self.reduction_tree().base_valuation()
            pi = vK.uniformizer()           # we construct a function field FYL1
            k = QQ(r/v(pi)).ceil()          # isomorphic to FYL, but with
            R1 = PolynomialRing(FXL, 'y1')  # integral equation G_1
            y1 = R1.gen()
            G1 = G(pi**(-k)*y1).monic()
            assert all([v(c) >= 0 for c in G1.coefficients()]), "new G is not integral!"
            FYL1 = FXL.extension(G1, 'y1')
            y1 = FYL1.gen()
            V = v.mac_lane_approximants(G1, require_incomparability=True)
            V = [FYL1.valuation(w) for w in V]   # the extensions of v to FYL1
            upper_valuations = [FYL.valuation((w,
                    FYL.hom(y1/pi**k), FYL1.hom(pi**k*FYL.gen()))) for w in V]
                                                 # made into valuations on FYL
        return [UpperComponent(self, w) for w in upper_valuations]
    def newton_polygon(self):
        r"""
        Returns a list of vertices of the Newton polygon of this polynomial.

        .. NOTE::

            If some coefficients have not enough precision an error is raised.

        EXAMPLES::

            sage: K = Qp(5)
            sage: R.<t> = K[]
            sage: f = 5 + 3*t + t^4 + 25*t^10
            sage: f.newton_polygon()
            Finite Newton polygon with 4 vertices: (0, 1), (1, 0), (4, 0), (10, 2)

            sage: g = f + K(0,0)*t^4; g
            (5^2 + O(5^22))*t^10 + (O(5^0))*t^4 + (3 + O(5^20))*t + (5 + O(5^21))
            sage: g.newton_polygon()
            Traceback (most recent call last):
            ...
            PrecisionError: The coefficient of t^4 has not enough precision

        TESTS:

        Check that :trac:`22936` is fixed::

            sage: S.<x> = PowerSeriesRing(GF(5))
            sage: R.<y> = S[]
            sage: p = x^2+y+x*y^2
            sage: p.newton_polygon()
            Finite Newton polygon with 3 vertices: (0, 2), (1, 0), (2, 1)

        AUTHOR:

        - Xavier Caruso (2013-03-20)
        """
        d = self.degree()
        from sage.geometry.newton_polygon import NewtonPolygon
        polygon = NewtonPolygon([(x, self[x].valuation()) for x in range(d+1)])
        polygon_prec = NewtonPolygon([ (x, self[x].precision_absolute()) for x in range(d+1) ])
        vertices = polygon.vertices(copy=False)
        vertices_prec = polygon_prec.vertices(copy=False)
        if len(vertices_prec) > 0:
            if vertices[0][0] > vertices_prec[0][0]:
                raise PrecisionError("first term with non-infinite valuation must have determined valuation")
            elif vertices[-1][0] < vertices_prec[-1][0]:
                raise PrecisionError("last term with non-infinite valuation must have determined valuation")
            else:
                for (x, y) in vertices:
                    if polygon_prec(x) <= y:
                         raise PrecisionError("The coefficient of %s^%s has not enough precision" % (self.parent().variable_name(), x))
        return polygon
Esempio n. 4
0
    def newton_polygon(self, f, valuations=None):
        r"""
        Return the newton polygon of the `\phi`-adic development of ``f``.

        INPUT:

        - ``f`` -- a polynomial in the domain of this valuation

        EXAMPLES::

            sage: R = Qp(2,5)
            sage: S.<x> = R[]
            sage: v = GaussValuation(S)
            sage: f = x^2 + 2*x + 3
            sage: v.newton_polygon(f)
            Finite Newton polygon with 2 vertices: (0, 0), (2, 0)

            sage: v = v.augmentation( x^2 + x + 1, 1)
            sage: v.newton_polygon(f)
            Finite Newton polygon with 2 vertices: (0, 0), (1, 1)
            sage: v.newton_polygon( f * v.phi()^3 )
            Finite Newton polygon with 2 vertices: (3, 3), (4, 4)

        """
        f = self.domain().coerce(f)

        from sage.geometry.newton_polygon import NewtonPolygon
        if valuations is None:
            valuations = self.valuations(f)
        return NewtonPolygon(list(enumerate(valuations)))
Esempio n. 5
0
    def _convert_(self, parent, prec):
        vertices = []
        for i in range(prec.last()):
            vertices.append((i, prec[i].flat_below()))
        from sage.geometry.newton_polygon import NewtonPolygon

        self._polygon = NewtonPolygon(vertices)
Esempio n. 6
0
def component_jumps(xi0, xi1):
    r""" Helper function for ``permanent_completion``.

    """
    from sage.geometry.newton_polygon import NewtonPolygon
    from mclf.berkovich.berkovich_line import valuations_from_inequality
    from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
    from mclf.berkovich.berkovich_line import TypeIIPointOnBerkovichLine

    assert xi0.is_leq(xi1), "xi0 has to be an ancestor of xi1"
    X = xi0.berkovich_line()
    vK = X.base_valuation()

    v0 = xi0.pseudovaluation_on_polynomial_ring()
    v1 = xi1.pseudovaluation_on_polynomial_ring()
    y = xi1.parameter()
    if hasattr(v1, "phi"):
        phi = v1.phi()
        # v1 is an inductive valuation
    else:
        phi = v1._G
        # v1 is a limit valuation
    assert v0(phi) < v1(phi), "xi0 is not an ancestor of xi1!"
    R = phi.parent()
    x = R.gen()
    S = PolynomialRing(R, 'T')
    T = S.gen()
    G = phi(x + T)
    NP = NewtonPolygon([(i, v1(G[i])) for i in range(G.degree() + 1)])
    V = []
    vertices = NP.vertices()
    for k in range(len(vertices) - 1):
        i, ai = vertices[k]
        j, aj = vertices[k + 1]
        a0 = aj - j * (ai - aj) / (i - j)
        # print("a0 = ", a0)
        V += valuations_from_inequality(vK, phi, a0, v0)
    ret = [TypeIIPointOnBerkovichLine(X, (v, y)) for v in V]
    """
    if xi1.is_in_unit_disk():
        ret = [X.point_from_polynomial_pseudovaluation(v) for v in V]
    else:
        ret = [X.point_from_polynomial_pseudovaluation(v, in_unit_disk=False) for v in V]
    """
    return [xi for xi in ret if (xi0.is_leq(xi) and xi.is_leq(xi1))]
Esempio n. 7
0
    def simplify_irreducible_polynomial(self, f):
        r"""
        Return a simpler polynomial generating the same extension.

        INPUT:

        - ``f`` -- an univariate polynomial over the underlying number field `K`
          which is integral and irreducible over `\hat{K}`

        OUTPUT:

        A polynomial `g` over `K` which is irreducible over `\hat{K}`,
        and which generates the same extension of `\hat{K}` as `f`.

        """
        R = f.parent()
        x = R.gen()
        assert R.base_ring() == self.number_field(), "f must be defined over K"
        # first we see if we can normalize f such that the unique slope of the
        # Newton polygon is >-1 and <=0.
        vK = self.valuation()
        NP = NewtonPolygon([(i, vK(f[i])) for i in range(f.degree() + 1)])
        slopes = NP.slopes(repetition=False)
        assert len(slopes) == 1, "f is not irreducible over the completion!"
        s = slopes[0]
        assert s <= 0, "f is not integral"
        if s <= -1:
            m = (-s).floor()
            pi = self.uniformizer()
            f = f(pi**m * x).monic()
        # Now we simplify the coefficients of f
        N = vK(f[0]).ceil() + 1
        n = f.degree()
        while True:
            g = R([self.reduce(f[i], N) for i in range(n + 1)])
            if g.is_squarefree() and self.is_approximate_irreducible_factor(
                    g, f):
                return g
            else:
                N = N + 1
Esempio n. 8
0
    def _init_(self, parent, prec, check=True):
        from sage.geometry.newton_polygon import NewtonPolygon, NewtonPolygon_element

        if isinstance(prec, NewtonPolygon_element):
            self._polygon = prec
        else:
            if not isinstance(prec, list):
                prec = [prec]
                # raise TypeError("prec must be either a Newton polygon, a list of coordinates (x,y) or a list of precisions")
            dimension = parent.dimension()
            vertices = []
            if len(prec) > 0:
                if isinstance(prec[0], tuple):
                    for p in prec:
                        if isinstance(p, tuple) and (len(p) == 2):
                            if (p[0] < 0) or (p[0] >= dimension):
                                raise IndexError
                            val = p[1]
                            if isinstance(val, Integer) or val is Infinity:
                                vertices.append((p[0], val))
                            else:
                                try:
                                    val = self._baseprec(val).flat_below()
                                except TypeError:
                                    raise TypeError(
                                        "prec must be either a Newton polygon, a list of coordinates (x,y) or a list of precisions"
                                    )
                                vertices.append((p[0], val))
                        else:
                            raise TypeError(
                                "prec must be either a Newton polygon, a list of coordinates (x,y) or a list of precisions"
                            )
                else:
                    if len(prec) > dimension:
                        raise ValueError("list too long")
                    for i in range(len(prec)):
                        val = prec[i]
                        if isinstance(val, Integer) or val is Infinity:
                            vertices.append((i, val))
                        else:
                            try:
                                val = self._baseprec(val).flat_below()
                            except TypeError:
                                raise TypeError(
                                    "prec must be either a Newton polygon, a list of coordinates (x,y) or a list of precisions"
                                )
                            vertices.append((i, val))
            self._polygon = NewtonPolygon(vertices)
Esempio n. 9
0
    def newton_polygon(self):
        r"""
        Returns a list of vertices of the Newton polygon of this polynomial.

        .. NOTE::

            If some coefficients have not enough precision an error is raised.

        EXAMPLES::

            sage: K = Qp(5)
            sage: R.<t> = K[]
            sage: f = 5 + 3*t + t^4 + 25*t^10
            sage: f.newton_polygon()
            Finite Newton polygon with 4 vertices: (0, 1), (1, 0), (4, 0), (10, 2)

            sage: g = f + K(0,0)*t^4; g
            (5^2 + O(5^22))*t^10 + (O(5^0))*t^4 + (3 + O(5^20))*t + (5 + O(5^21))
            sage: g.newton_polygon()
            Traceback (most recent call last):
            ...
            PrecisionError: The coefficient of t^4 has not enough precision

        TESTS:

        Check that :trac:`22936` is fixed::

            sage: S.<x> = PowerSeriesRing(GF(5))
            sage: R.<y> = S[]
            sage: p = x^2+y+x*y^2
            sage: p.newton_polygon()
            Finite Newton polygon with 3 vertices: (0, 2), (1, 0), (2, 1)

        AUTHOR:

        - Xavier Caruso (2013-03-20)
        """
        d = self.degree()
        from sage.geometry.newton_polygon import NewtonPolygon
        polygon = NewtonPolygon([(x, self[x].valuation()) for x in range(d+1)])
        polygon_prec = NewtonPolygon([ (x, self[x].precision_absolute()) for x in range(d+1) ])
        vertices = polygon.vertices(copy=False)
        vertices_prec = polygon_prec.vertices(copy=False)
        if len(vertices_prec) > 0:
            if vertices[0][0] > vertices_prec[0][0]:
                raise PrecisionError("first term with non-infinite valuation must have determined valuation")
            elif vertices[-1][0] < vertices_prec[-1][0]:
                raise PrecisionError("last term with non-infinite valuation must have determined valuation")
            else:
                for (x, y) in vertices:
                    if polygon_prec(x) <= y:
                         raise PrecisionError("The coefficient of %s^%s has not enough precision" % (self.parent().variable_name(), x))
        return polygon
Esempio n. 10
0
    def ramification_polygon(self):
        r"""
        Return the ramification polygon of this extension.

        The *ramification polygon* of a weak Galois extension `L/K`
        of `p`-adic number fields is the Newton polygon of the
        ramification polynomial, i.e. the polynomial

        .. MATH::

            G := P(x+\pi)/x

        where `\pi` is a prime element of `L` which generates the extension
        `L/K` and `P` is the minimal polynomial of `\pi` over `K^{nr}`, the
        maximal unramified subextension of .

        The (strictly negative) slopes of the ramification polygon (with respect
        to the valuation `v_L` on `L`, normalized such that `v_L(\pi_L)=1`)
        correspond to the jumps in the filtration of higher ramification groups,
        and the abscissae of the vertices of the corresponding vertices are equal
        to the order of the ramification subgroups that occur in the filtration.

        NOTE:

        - For the time being, we have to assume that `K=\mathbb{Q}_p`. In this
          case we can choose for `\pi` the canonical generator of the absolute
          number field `L_0` underlying `L`.

        """
        if not hasattr(self, "_ramification_polygon"):
            assert self.base_field().is_Qp(), "K has to be equal to Q_p"
            L = self.extension_field()
            vL = L.normalized_valuation()
            G = self.ramification_polynomial()
            self._ramification_polygon = NewtonPolygon([
                (i, vL(G[i])) for i in range(G.degree() + 1)
            ])
        return self._ramification_polygon
Esempio n. 11
0
def _good_approximation(w, v):
    r""" Return a good approximation of this extension of a discrete valuation.

    INPUT:

    - ``w`` -- a discrete valuation on a field `L`, which is a finite extension
               of a field `K`
    - ``v`` -- the restriction of `w` to `K`

    OUTPUT: a discrete valuation on the polynomial ring over `K`, which
            is a 'good' approximation of `w`.

    Let `\alpha` denote the generator of the extension `L/K`, and `f\in K[x]`
    the minimal polynomial of `\alpha`. Also, let `v` denote the restriction
    of `w` to `K`. The finitely many extension of `v` to `L` correspond to the
    irreducible factors of `f` over the completion of `K` with respect to `v`.
    Write `g` for the factor corresponding to the given extension `w`.

    An *approximation* of `w` is a discrete valuation `\tilde{w}` on `K[x]` with
    the following properties:

    - the restriction of `\tilde{w}` to `K` is equal to `v`
    - `\tilde{w}(x)\geq 0`
    - `\tilde{w}(h) \leq w(h)`, for all `h\in K[x]`

    An approximation `\tilde{w}` is called *selective* if it is not an
    approximation for any other extension of `v` to `L` than `w`.

    Let `\tilde{w}` be a selective approximation of `w`. It is of the form

    MATH::

        \tilde{w} = [w_0, w_1(\phi_1)=\lambda_1,\ldots,w_n(\phi_n)=\lambda_n].

    Write `\phi:=\phi_n`. The approximation `\tilde{w}` is called *good* if

    - `\phi` has the same degree as the factor `g` of `f`, and
    - `\phi` has a root `\beta` (in the algebraic closure of the completion of
      `K`) which is closer to `\alpha` then any root of `f` different from `\alpha`

    It then follows from Krasner's Lemma that `\phi` generates the same extension
    of the completion of `K` than `g`, i.e.

    MATH::

        \hat{K}[\alpha]\cong\hat{K}[\beta].

    """
    from sage.geometry.newton_polygon import NewtonPolygon

    L = w.domain()
    alpha = L.gen()
    f = alpha.minpoly()
    x = f.parent().gen()
    F = f(alpha + x).shift(-1)
    np = NewtonPolygon([(i, w(F[i])) for i in range(F.degree() + 1)])
    mu = -np.slopes()[0]

    wt = _some_approximation(w, v)
    f = wt.domain()(f)
    assert hasattr(wt, "phi"), "wt = {}, L = {}".format(wt, L)
    while w(wt.phi()(alpha)) <= mu * wt.phi().degree():
        wt = wt.mac_lane_step(f)[0]
        """
        try:
            wt = wt.mac_lane_step(f)[0]
        except:
            print("wt = ", wt)
            print("domain = ", wt.domain())
            raise ValueError()
        """
    return wt
Esempio n. 12
0
    def is_approximate_irreducible_factor(self, g, f, v=None):
        r"""
        Check whether ``g`` is an approximate irreducible factor of ``f``.

        INPUT:

        - ``g``: univariate polynomial over the underlying number field `K_0`
        - ``f``: univariate polynomial over `K_0`
        - ``v``: a MacLane valuation on `K_0[x]` approximating ``g``, or ``None``;
          here *approximating* means that ``LimitValuation(v, g)`` is well-defined.

        Output: True if ``g`` is an approximate irreducible factor of f, i.e.
        if g is irreducible over `K` and Krasner's condition is satified,
        If true, the stem field of ``g`` over `K` is a subfield of the
        splitting field of ``f`` over `K`.

        Her we say that *Krasner's Condition* holds if for some root `\alpha`
        of `g` there exists a root `\beta` of `f` such that `\alpha` is `p`-adically
        closer to `\beta` than to any other root of `g`.

        Note that if `\deg(g)=1` then the condition is nontrivial, even though
        the conclusion from Krasner's Lemma is trivial.

        """
        K = self.number_field()
        vK = self.valuation()
        assert K.has_coerce_map_from(f.parent().base_ring())
        f = f.change_ring(K)
        R = f.parent()
        assert K.has_coerce_map_from(g.parent().base_ring())
        g = R(g)
        assert g.is_monic(), 'g has to be monic'
        f = f.monic()
        if g == f:
            return True
        x = R.gen()

        if g.degree() == 1:             # the case deg(g)=1 is different
            alpha = -g[0]               # the unique root of g
            F = f(x+alpha)
            if F[0] == 0:               # alpha is an exact root of f
                return True
            np_f = NewtonPolygon([(i, vK(F[i])) for i in range(F.degree()+1)])
            # the slopes correspond to vK(alpha-beta), beta the roots of f
            return ( len(np_f.vertices())>1 and np_f.vertices()[1][0]==1 and
                    np_f.slopes()[0]<0 )

        # now deg(g)>1
        if v == None:
            V = vK.mac_lane_approximants(g)
            if len(V) != 1:
                return False   # g is not irreducible
            v = V[0]
        v = LimitValuation(v, g)
        # if v(f) == Infinity:
        if (v._G).divides(f):
            return True
        # the valuation v has the property
        #        v(h)=vK(h(alpha))
        # for all h in K[x], where alpha is a root of g

        S = PolynomialRing(R, 'T')
        G = g(x + S.gen()).shift(-1)
        np_g = NewtonPolygon([(i, v(G[i])) for i in range(G.degree()+1)])
        # the slopes of np_g correspond to the valuations of
        # alpha-alpha_i, where alpha_i runs over all roots of
        # g distinct from alpha

        F = f(x + S.gen())
        np_f = NewtonPolygon([(i, v(F[i])) for i in range(F.degree()+1)])
        # the slopes of np_f correspond to the valuations of
        # alpha-beta, where beta runs over all roots of f

        result = min(np_g.slopes()) > min(np_f.slopes())
        # this is true if there is a root beta of f
        # such that vK(alpha-beta)>vK(alpha-alpha_i) for all i
        return result
Esempio n. 13
0
 def hodge_polygon(self):
     expand_hodge = []
     for i, h in enumerate(self.hodge):
         expand_hodge += [i] * h
     return NewtonPolygon(expand_hodge).vertices()
Esempio n. 14
0
    def newton_polygon(self):
        r"""
        Returns the Newton polygon of this polynomial.

        .. NOTE::

            If some coefficients have not enough precision an error is raised.

        OUTPUT:

        - a Newton polygon

        EXAMPLES::

            sage: K = Qp(2, prec=5)
            sage: P.<x> = K[]
            sage: f = x^4 + 2^3*x^3 + 2^13*x^2 + 2^21*x + 2^37
            sage: f.newton_polygon()
            Finite Newton polygon with 4 vertices: (0, 37), (1, 21), (3, 3), (4, 0)

            sage: K = Qp(5)
            sage: R.<t> = K[]
            sage: f = 5 + 3*t + t^4 + 25*t^10
            sage: f.newton_polygon()
            Finite Newton polygon with 4 vertices: (0, 1), (1, 0), (4, 0), (10, 2)

        Here is an example where the computation fails because precision is
        not sufficient::

            sage: g = f + K(0,0)*t^4; g
            (5^2 + O(5^22))*t^10 + (O(5^0))*t^4 + (3 + O(5^20))*t + (5 + O(5^21))
            sage: g.newton_polygon()
            Traceback (most recent call last):
            ...
            PrecisionError: The coefficient of t^4 has not enough precision

        TESTS::

            sage: (5*f).newton_polygon()
            Finite Newton polygon with 4 vertices: (0, 2), (1, 1), (4, 1), (10, 3)

        AUTHOR:

        - Xavier Caruso (2013-03-20)
        """
        if self._valaddeds is None:
            self._comp_valaddeds()
        from sage.geometry.newton_polygon import NewtonPolygon
        valbase = self._valbase
        polygon = NewtonPolygon([(x, val + valbase)
                                 for x, val in enumerate(self._valaddeds)])
        polygon_prec = NewtonPolygon([(x, val + valbase)
                                      for x, val in enumerate(self._relprecs)])
        vertices = polygon.vertices(copy=False)
        vertices_prec = polygon_prec.vertices(copy=False)

        # The two following tests should always fail (i.e. the corresponding errors
        # should never be raised). However, it's probably safer to keep them.
        if vertices[0][0] > vertices_prec[0][0]:
            raise PrecisionError("The constant coefficient has not enough precision")
        if vertices[-1][0] < vertices_prec[-1][0]:
            raise PrecisionError("The leading coefficient has not enough precision")

        for (x, y) in vertices:
            if polygon_prec(x) <= y:
                raise PrecisionError("The coefficient of %s^%s has not enough precision" % (self.parent().variable_name(), x))
        return polygon
Esempio n. 15
0
class NewtonBigOh_polynomial(BigOh_polynomial):
    def _init_(self, parent, prec, check=True):
        from sage.geometry.newton_polygon import NewtonPolygon, NewtonPolygon_element

        if isinstance(prec, NewtonPolygon_element):
            self._polygon = prec
        else:
            if not isinstance(prec, list):
                prec = [prec]
                # raise TypeError("prec must be either a Newton polygon, a list of coordinates (x,y) or a list of precisions")
            dimension = parent.dimension()
            vertices = []
            if len(prec) > 0:
                if isinstance(prec[0], tuple):
                    for p in prec:
                        if isinstance(p, tuple) and (len(p) == 2):
                            if (p[0] < 0) or (p[0] >= dimension):
                                raise IndexError
                            val = p[1]
                            if isinstance(val, Integer) or val is Infinity:
                                vertices.append((p[0], val))
                            else:
                                try:
                                    val = self._baseprec(val).flat_below()
                                except TypeError:
                                    raise TypeError(
                                        "prec must be either a Newton polygon, a list of coordinates (x,y) or a list of precisions"
                                    )
                                vertices.append((p[0], val))
                        else:
                            raise TypeError(
                                "prec must be either a Newton polygon, a list of coordinates (x,y) or a list of precisions"
                            )
                else:
                    if len(prec) > dimension:
                        raise ValueError("list too long")
                    for i in range(len(prec)):
                        val = prec[i]
                        if isinstance(val, Integer) or val is Infinity:
                            vertices.append((i, val))
                        else:
                            try:
                                val = self._baseprec(val).flat_below()
                            except TypeError:
                                raise TypeError(
                                    "prec must be either a Newton polygon, a list of coordinates (x,y) or a list of precisions"
                                )
                            vertices.append((i, val))
            self._polygon = NewtonPolygon(vertices)

    def _convert_(self, parent, prec):
        vertices = []
        for i in range(prec.last()):
            vertices.append((i, prec[i].flat_below()))
        from sage.geometry.newton_polygon import NewtonPolygon

        self._polygon = NewtonPolygon(vertices)

    def is_exact(self):
        return len(self._polygon.vertices()) == 0

    def _getitem_by_num(self, i):
        from sage.functions.other import ceil

        val = self._polygon(i)
        if val is Infinity:
            return self._base_exactprec
        else:
            return self._baseprec(ceil(val))

    def _add_(self, other):
        return self.__class__(self.parent(), self._polygon + other._polygon)

    def _mul_(self, other):
        return self.__class__(self.parent(), self._polygon * other._polygon)

    def _lmul_(self, coeff):
        return self.__class__(self.parent(), self._polygon.__lshift__(coeff.flat_below()))

    def _rmul_(self, coeff):
        return self.__class__(self.parent(), self._polygon.__lshift__(coeff.flat_below()))

    def __pow__(self, exp, ignored=None):
        return self.__class__(self.parent(), self._polygon ** exp)

    def first(self):
        vertices = self._polygon.vertices()
        if len(vertices) == 0:
            return self.parent().dimension()
        else:
            return vertices[0][0]

    def last(self):
        vertices = self._polygon.vertices()
        if len(vertices) == 0:
            return 0
        else:
            return vertices[-1][0] + 1

    def __lshift__(self, i):
        return self.__class__(self.parent(), self._polygon.__lshift__(i))

    def __rshift__(self, i):
        return self.__class__(self.parent(), self._polygon.__rshift__(i))

    def flat_below(self):
        vertices = self._polygon.vertices()
        if len(vertices) == 0:
            return Infinity
        else:
            return min([v[1] for v in vertices])

    def to_workprec(self, last=None):
        vertices = self._polygon.vertices()
        if len(vertices) == 0:
            return Infinity
        last_x = vertices[-1][0] + 1
        if last is None:
            last = last_x
        if last > len(vertices):
            return Infinity
        elif last < len(vertices):
            raise ValueError("still inexact BigOh's after last")  # is it really an error?
        else:
            return max([v[1] for v in vertices])

    def equals(self, other):
        return self._polygon == other._polygon

    def contains(self, other):
        return self._polygon <= other._polygon

    def _repr_(self, model):
        return BigOh_polynomial._repr_(self, model)