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
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))]
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
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
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)