Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: utf-8 -*- Augmented valuations on polynomial rings
Implements augmentations of (inductive) valuations.
AUTHORS:
- Julian Rüth (2013-04-15): initial version
EXAMPLES:
Starting from a :mod:`Gauss valuation <sage.rings.valuation.gauss_valuation>`, we can create augmented valuations on polynomial rings::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x, 1); w [ Gauss valuation induced by 2-adic valuation, v(x) = 1 ] sage: w(x) 1
This also works for polynomial rings over base rings which are not fields. However, much of the functionality is only available over fields::
sage: R.<x> = ZZ[] sage: v = GaussValuation(R, ZZ.valuation(2)) sage: w = v.augmentation(x, 1); w [ Gauss valuation induced by 2-adic valuation, v(x) = 1 ] sage: w(x) 1
TESTS::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x, 1) sage: TestSuite(w).run() # long time
sage: w = v.augmentation(x, 2) sage: TestSuite(w).run() # long time
Run the test suite for a valuation with a residual extension::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, 1) sage: TestSuite(w).run() # long time
Run the test suite for an iterated residual extension starting from a non-prime residue field::
sage: R.<u> = Qq(4, 40) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, 1/2) sage: TestSuite(w).run() # long time
sage: ww = w.augmentation(x^8 + 4*x^7 + 2*x^6 + 2*x^5 + x^4 + 2*x^3 + 4*(u + 1)*x^2 + 6*(u + 1)*x + 4 + 3*u, 10) sage: TestSuite(ww).run() # long time
Run the test suite for an augmentation of a ramified augmentation::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x, 3/4) sage: TestSuite(w).run() # long time
sage: ww = w.augmentation(x^4 + 8, 5) sage: TestSuite(ww).run() # long time
Run the test suite for a ramified augmentation of an unramified augmentation::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, 1) sage: TestSuite(w).run() # long time
sage: ww = w.augmentation(x^4 + 2*x^3 + 5*x^2 + 8*x + 3, 16/3) sage: TestSuite(ww).run() # long time
Run the test suite for a ramified augmentation of a ramified augmentation::
sage: R.<u> = Qq(4, 20) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, 1/2) sage: TestSuite(w).run() # long time
sage: ww = w.augmentation((x^2 + x + u)^2 + 2, 5/3) sage: TestSuite(ww).run() # long time
Run the test suite for another augmentation with iterated residue field extensions::
sage: R.<u> = Qq(4, 10) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, 1) sage: TestSuite(w).run() # long time
sage: ww = w.augmentation((x^2 + x + u)^2 + 2*x*(x^2 + x + u) + 4*x, 3) sage: TestSuite(ww).run() # long time
Run the test suite for a rather trivial pseudo-valuation::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x, infinity) sage: TestSuite(w).run() # long time
Run the test suite for an infinite valuation which extends the residue field::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, infinity) sage: TestSuite(w).run() # long time
Run the test suite for an infinite valuation which extends a valuation which extends the residue field::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, 1/2) sage: TestSuite(w).run() # long time
sage: ww = w.augmentation((x^2 + x + u)^2 + 2, infinity) sage: TestSuite(ww).run() # long time
Run the test suite if the polynomial ring is not over a field::
sage: R.<x> = ZZ[] sage: v = GaussValuation(R, ZZ.valuation(2)) sage: w = v.augmentation(x, 1) sage: TestSuite(w).run() # long time
REFERENCES:
Augmentations are described originally in [Mac1936I]_ and [Mac1936II]_. An overview can also be found in Chapter 4 of [Rüt2014]_.
""" #***************************************************************************** # Copyright (C) 2013-2017 Julian Rüth <julian.rueth@fsfe.org> # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # http://www.gnu.org/licenses/ #*****************************************************************************
r""" Factory for augmented valuations.
EXAMPLES:
This factory is not meant to be called directly. Instead, :meth:`~sage.rings.valuation.inductive_valuation.NonFinalInductiveValuation.augmentation` of a valuation should be called::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x, 1) # indirect doctest
Note that trivial parts of the augmented valuation might be dropped, so you should not rely on ``_base_valuation`` to be the valuation you started with::
sage: ww = w.augmentation(x, 2) sage: ww._base_valuation is v True
""" r""" Create a key which uniquely identifies the valuation over ``base_valuation`` which sends ``phi`` to ``mu``.
.. NOTE::
The uniqueness that this factory provides is not why we chose to use a factory. However, it makes pickling and equality checks much easier. At the same time, going through a factory makes it easier to enforce that all instances correctly inherit methods from the parent Hom space.
TESTS::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x, 1) # indirect doctest sage: ww = v.augmentation(x, 1) sage: w is ww True
""" raise ValueError(reason) raise ValueError("the value of the key polynomial must strictly increase but `%s` does not exceed `%s`."%(mu, base_valuation(phi))) raise TypeError("base_valuation must be inductive")
# drop base_valuation and extend base_valuation._base_valuation instead
r""" Create the augmented valuation represented by ``key``.
TESTS::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, 1) # indirect doctest
"""
else: else:
r""" An augmented valuation is a discrete valuation on a polynomial ring. It extends another discrete valuation `v` by setting the valuation of a polynomial `f` to the minumum of `v(f_i)i\mu` when writing `f=\sum_i f_i\phi^i`.
INPUT:
- ``v`` -- a :class:`~sage.rings.valuation.inductive_valuation.InductiveValuation` on a polynomial ring
- ``phi`` -- a :meth:`key polynomial <sage.rings.valuation.inductive_valuation.NonFinalInductiveValuation.is_key>` over ``v``
- ``mu`` -- a rational number such that ``mu > v(phi)`` or ``infinity``
EXAMPLES::
sage: K.<u> = CyclotomicField(5) sage: R.<x> = K[] sage: v = GaussValuation(R, K.valuation(2)) sage: w = v.augmentation(x, 1/2); w # indirect doctest [ Gauss valuation induced by 2-adic valuation, v(x) = 1/2 ] sage: ww = w.augmentation(x^4 + 2*x^2 + 4*u, 3); ww [ Gauss valuation induced by 2-adic valuation, v(x) = 1/2, v(x^4 + 2*x^2 + 4*u) = 3 ]
TESTS::
sage: TestSuite(w).run() # long time sage: TestSuite(ww).run() # long time
""" r""" TESTS::
sage: K.<u> = Qq(4, 5) sage: R.<x> = K[] sage: v = GaussValuation(R) sage: from sage.rings.valuation.augmented_valuation import AugmentedValuation sage: w = AugmentedValuation(v, x, 1/2) sage: from sage.rings.valuation.augmented_valuation import AugmentedValuation_base sage: isinstance(w, AugmentedValuation_base) True
sage: TestSuite(w).run() # long time
"""
r""" Return an equivalence unit of minimal degree and valuation ``s``.
INPUT:
- ``s`` -- a rational number
- ``reciprocal`` -- a boolean (default: ``False``); whether or not to return the equivalence unit as the :meth:`~sage.rings.valuation.inductive_valuation.InductiveValuation.equivalence_reciprocal` of the equivalence unit of valuation ``-s``.
OUTPUT:
A polynomial in the domain of this valuation which :meth:`~sage.rings.valuation.inductive_valuation.InductiveValuation.is_equivalence_unit` for this valuation.
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, 1)
sage: w.equivalence_unit(0) 1 + O(2^5) sage: w.equivalence_unit(-4) 2^-4 + O(2)
Since an equivalence unit is of effective degree zero, `\phi` must not divide it. Therefore, its valuation is in the value group of the base valuation::
sage: w = v.augmentation(x, 1/2)
sage: w.equivalence_unit(3/2) Traceback (most recent call last): ... ValueError: 3/2 is not in the value semigroup of 2-adic valuation sage: w.equivalence_unit(1) 2 + O(2^6)
An equivalence unit might not be integral, even if ``s >= 0``::
sage: w = v.augmentation(x, 3/4) sage: ww = w.augmentation(x^4 + 8, 5)
sage: ww.equivalence_unit(1/2) (2^-1 + O(2^4))*x^2
""" else:
def element_with_valuation(self, s): r""" Create an element of minimal degree and of valuation ``s``.
INPUT:
- ``s`` -- a rational number in the value group of this valuation
OUTPUT:
An element in the domain of this valuation
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, 1/2) sage: w.element_with_valuation(0) 1 + O(2^5) sage: w.element_with_valuation(1/2) (1 + O(2^5))*x^2 + (1 + O(2^5))*x + u + O(2^5) sage: w.element_with_valuation(1) 2 + O(2^6) sage: c = w.element_with_valuation(-1/2); c (2^-1 + O(2^4))*x^2 + (2^-1 + O(2^4))*x + u*2^-1 + O(2^4) sage: w(c) -1/2 sage: w.element_with_valuation(1/3) Traceback (most recent call last): ... ValueError: s must be in the value group of the valuation but 1/3 is not in Additive Abelian Group generated by 1/2.
"""
r""" Return a printable representation of this valuation.
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, 1/2) sage: w # indirect doctest [ Gauss valuation induced by 2-adic valuation, v((1 + O(2^5))*x^2 + (1 + O(2^5))*x + u + O(2^5)) = 1/2 ]
"""
r""" Return a list with the chain of augmentations down to the underlying :mod:`Gauss valuation <sage.rings.valuation.gauss_valuation>`.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x, 1) sage: w.augmentation_chain() [[ Gauss valuation induced by 2-adic valuation, v(x) = 1 ], Gauss valuation induced by 2-adic valuation]
For performance reasons, (and to simplify the underlying implementation,) trivial augmentations might get dropped. You should not rely on :meth:`augmentation_chain` to contain all the steps that you specified to create the current valuation::
sage: ww = w.augmentation(x, 2) sage: ww.augmentation_chain() [[ Gauss valuation induced by 2-adic valuation, v(x) = 2 ], Gauss valuation induced by 2-adic valuation]
"""
def psi(self): r""" Return the minimal polynomial of the residue field extension of this valuation.
OUTPUT:
A polynomial in the residue ring of the base valuation
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S)
sage: w = v.augmentation(x^2 + x + u, 1/2) sage: w.psi() x^2 + x + u0
sage: ww = w.augmentation((x^2 + x + u)^2 + 2, 5/3) sage: ww.psi() x + 1
"""
def E(self): r""" Return the ramification index of this valuation over its underlying Gauss valuation.
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S)
sage: w = v.augmentation(x^2 + x + u, 1) sage: w.E() 1
sage: w = v.augmentation(x, 1/2) sage: w.E() 2
""" raise NotImplementedError("ramification index is not defined over a trivial Gauss valuation")
def F(self): r""" Return the degree of the residue field extension of this valuation over the underlying Gauss valuation.
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S)
sage: w = v.augmentation(x^2 + x + u, 1) sage: w.F() 2
sage: w = v.augmentation(x, 1/2) sage: w.F() 1
"""
r""" Return the extensions of this valuation to ``ring``.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, 1)
sage: w.extensions(GaussianIntegers().fraction_field()['x']) [[ Gauss valuation induced by 2-adic valuation, v(x^2 + x + 1) = 1 ]]
"""
else: # We construct a valuation with [v, w(phi) = mu] which should be such that # self(phi) = self._mu, i.e., w(phi) = w(unit) + sum e_i * w(f_i) where # the sum runs over all the factors in the equivalence decomposition of phi # Solving for mu gives
return super(AugmentedValuation_base, self).extensions(ring)
r""" Return the restriction of this valuation to ``ring``.
EXAMPLES::
sage: K = GaussianIntegers().fraction_field() sage: R.<x> = K[] sage: v = GaussValuation(R, K.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, 1)
sage: w.restriction(QQ['x']) [ Gauss valuation induced by 2-adic valuation, v(x^2 + x + 1) = 1 ]
""" return super(AugmentedValuation_base, self).restriction(ring)
r""" Return a uniformizing element for this valuation.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, 1)
sage: w.uniformizer() 2
"""
r""" Return whether this valuation is a Gauss valuation.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, 1)
sage: w.is_gauss_valuation() False
"""
r""" Return a monic integral irreducible polynomial which defines the same extension of the base ring of the domain as the irreducible polynomial ``G`` together with maps between the old and the new polynomial.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, 1)
sage: w.monic_integral_model(5*x^2 + 1/2*x + 1/4) (Ring endomorphism of Univariate Polynomial Ring in x over Rational Field Defn: x |--> 1/2*x, Ring endomorphism of Univariate Polynomial Ring in x over Rational Field Defn: x |--> 2*x, x^2 + 1/5*x + 1/5)
"""
r""" Return whether this valuation is greater or equal than ``other`` everywhere.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, 1) sage: w >= v True sage: ww = v.augmentation(x^2 + x + 1, 2) sage: ww >= w True sage: www = w.augmentation(x^4 + 2*x^3 + 5*x^2 + 8*x + 3, 16/3) sage: www >= w True sage: www >= ww False
""" return other.is_discrete_valuation() else:
return super(AugmentedValuation_base, self)._ge_(other)
r""" Return whether this valuation is trivial, i.e., zero outside of zero.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, 1) sage: w.is_trivial() False
""" # We need to override the default implementation from valuation_space # because that one uses uniformizer() which might not be implemented if # the base ring is not a field.
r""" Return this valuation scaled by ``scalar``.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, 1) sage: 3*w # indirect doctest [ Gauss valuation induced by 3 * 2-adic valuation, v(x^2 + x + 1) = 3 ]
""" return super(AugmentedValuation_base, self).scale(scalar)
r""" Return a name for a generator of the residue ring.
This method is used by :meth:`residue_ring` to work around name clashes with names in subrings of the residue ring.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, 1) sage: w._residue_ring_generator_name() 'u1'
""" # we need a name for a generator that is not present already in base # use this name, it has no meaning in base # use this name, base can not handle strings, so hopefully, # there are no variable names (such as in QQ or GF(p))
r""" Return an estimate on the coefficient size of ``f``.
The number returned is an estimate on the factor between the number of bits used by ``f`` and the minimal number of bits used by an element congruent to ``f``.
This is used by :meth:`simplify` to decide whether simplification of coefficients is going to lead to a significant shrinking of the coefficients of ``f``.
EXAMPLES::
sage: R.<u> = QQ[] sage: K.<u> = QQ.extension(u^2 + u+ 1) sage: S.<x> = K[] sage: v = GaussValuation(S, K.valuation(2)) sage: w = v.augmentation(x^2 + x + u, 1/2) sage: w._relative_size(x^2 + x + 1) 1 sage: w._relative_size(1048576*x^2 + 1048576*x + 1048576) 11
"""
r""" Return whether this valuation attains `-\infty`.
EXAMPLES:
No element in the domain of an augmented valuation can have valuation `-\infty`, so this method always returns ``False``::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, valuations.TrivialValuation(QQ)) sage: w = v.augmentation(x, infinity) sage: w.is_negative_pseudo_valuation() False
"""
r""" Return this valuation over ``ring``.
EXAMPLES:
We can change the domain of an augmented valuation even if there is no coercion between rings::
sage: R.<x> = GaussianIntegers()[] sage: v = GaussValuation(R, GaussianIntegers().valuation(2)) sage: v = v.augmentation(x, 1) sage: v.change_domain(QQ['x']) [ Gauss valuation induced by 2-adic valuation, v(x) = 1 ]
"""
r""" An augmented valuation which can not be augmented anymore, either because it augments a trivial valuation or because it is infinite.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, valuations.TrivialValuation(QQ)) sage: w = v.augmentation(x, 1)
""" r""" TESTS::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, valuations.TrivialValuation(QQ)) sage: w = v.augmentation(x, 1) sage: from sage.rings.valuation.augmented_valuation import FinalAugmentedValuation sage: isinstance(w, FinalAugmentedValuation) True
"""
def residue_ring(self): r""" Return the residue ring of this valuation, i.e., the elements of non-negative valuation modulo the elements of positive valuation.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
sage: w = v.augmentation(x, 1) sage: w.residue_ring() Rational Field
sage: w = v.augmentation(x^2 + x + 1, infinity) sage: w.residue_ring() Number Field in u1 with defining polynomial x^2 + x + 1
An example with a non-trivial base valuation::
sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, infinity) sage: w.residue_ring() Finite Field in u1 of size 2^2
Since trivial extensions of finite fields are not implemented, the resulting ring might be identical to the residue ring of the underlying valuation::
sage: w = v.augmentation(x, infinity) sage: w.residue_ring() Finite Field of size 2
TESTS:
We avoid clashes in generator names::
sage: K.<x> = FunctionField(QQ) sage: v = K.valuation(x^2 + 2) sage: R.<y> = K[] sage: L.<y> = K.extension(y^2 + x^2) sage: w = v.extension(L) sage: w.residue_field() Number Field in uu1 with defining polynomial y^2 - 2 over its base field sage: w.residue_field().base_field() Number Field in u1 with defining polynomial x^2 + 2
""" # the following is correct, even if the polynomial ring is not over a field
else: # Do not call extension() if self.psi().degree() == 1: # In that case the resulting field appears to be the same as the original field, # however, it is not == to the original field (for finite fields at # least) but a distinct copy (this is a bug in finite field's # extension() implementation.)
r""" Reduce ``f`` module this valuation.
INPUT:
- ``f`` -- an element in the domain of this valuation
- ``check`` -- whether or not to check whether ``f`` has non-negative valuation (default: ``True``)
- ``degree_bound`` -- an a-priori known bound on the degree of the result which can speed up the computation (default: not set)
- ``coefficients`` -- the coefficients of ``f`` as produced by :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.coefficients` or ``None`` (default: ``None``); this can be used to speed up the computation when the expansion of ``f`` is already known from a previous computation.
- ``valuations`` -- the valuations of ``coefficients`` or ``None`` (default: ``None``); ignored
OUTPUT:
an element of the :meth:`residue_ring` of this valuation, the reduction modulo the ideal of elements of positive valuation
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
sage: w = v.augmentation(x, 1) sage: w.reduce(x^2 + x + 1) 1
sage: w = v.augmentation(x^2 + x + 1, infinity) sage: w.reduce(x) u1
TESTS:
Cases with non-trivial base valuation::
sage: R.<u> = Qq(4, 10) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: v.reduce(x) x sage: v.reduce(S(u)) u0
sage: w = v.augmentation(x^2 + x + u, 1/2) sage: w.reduce(S.one()) 1 sage: w.reduce(S(2)) 0 sage: w.reduce(S(u)) u0 sage: w.reduce(x) # this gives the generator of the residue field extension of w over v u1 sage: f = (x^2 + x + u)^2 / 2 sage: w.reduce(f) x sage: w.reduce(f + x + 1) x + u1 + 1
sage: ww = w.augmentation((x^2 + x + u)^2 + 2, 5/3) sage: g = ((x^2 + x + u)^2 + 2)^3 / 2^5 sage: ww.reduce(g) x sage: ww.reduce(f) 1 sage: ww.is_equivalent(f, 1) True sage: ww.reduce(f * g) x sage: ww.reduce(f + g) x + 1
"""
raise ValueError("f must have non-negative valuation")
else: constant_term = coefficients[0]
def _residue_field_generator(self): r""" Return a root of :meth:`psi` in :meth:`residue_ring`.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
sage: w = v.augmentation(x, 1) sage: w._residue_field_generator() 0
sage: w = v.augmentation(x^2 + x + 1, infinity) sage: w._residue_field_generator() u1
A case with non-trivial base valuation::
sage: R.<u> = Qq(4, 10) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, infinity) sage: w._residue_field_generator() u1
""" else:
r""" Return a polynomial which reduces to ``F``.
INPUT:
- ``F`` -- an element of the :meth:`residue_ring`
ALGORITHM:
We simply undo the steps performed in :meth:`reduce`.
OUTPUT:
A polynomial in the domain of the valuation with reduction ``F``
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
sage: w = v.augmentation(x, 1) sage: w.lift(1/2) 1/2
sage: w = v.augmentation(x^2 + x + 1, infinity) sage: w.lift(w.residue_ring().gen()) x
A case with non-trivial base valuation::
sage: R.<u> = Qq(4, 10) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, infinity) sage: w.lift(w.residue_ring().gen()) (1 + O(2^10))*x
"""
# Write F as a polynomial in self._residue_field_generator() # We only have to do that if psi is non-trivial G = F.element() else:
r""" An augmented valuation which can be augmented further.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, 1)
""" r""" TESTS::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, 1) sage: from sage.rings.valuation.augmented_valuation import NonFinalAugmentedValuation sage: isinstance(w, NonFinalAugmentedValuation) True
"""
def residue_ring(self): r""" Return the residue ring of this valuation, i.e., the elements of non-negative valuation modulo the elements of positive valuation.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2))
sage: w = v.augmentation(x^2 + x + 1, 1) sage: w.residue_ring() Univariate Polynomial Ring in x over Finite Field in u1 of size 2^2
Since trivial valuations of finite fields are not implemented, the resulting ring might be identical to the residue ring of the underlying valuation::
sage: w = v.augmentation(x, 1) sage: w.residue_ring() Univariate Polynomial Ring in x over Finite Field of size 2 (using ...)
""" raise NotImplementedError("only implemented for polynomial rings over fields")
else: # Do not call extension() if self.psi().degree() == 1: # In that case the resulting field appears to be the same as the original field, # however, it is not == to the original field (for finite fields at # least) but a distinct copy (this is a bug in finite field's # extension() implementation.) pass
r""" Reduce ``f`` module this valuation.
INPUT:
- ``f`` -- an element in the domain of this valuation
- ``check`` -- whether or not to check whether ``f`` has non-negative valuation (default: ``True``)
- ``degree_bound`` -- an a-priori known bound on the degree of the result which can speed up the computation (default: not set)
- ``coefficients`` -- the coefficients of ``f`` as produced by :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.coefficients` or ``None`` (default: ``None``); this can be used to speed up the computation when the expansion of ``f`` is already known from a previous computation.
- ``valuations`` -- the valuations of ``coefficients`` or ``None`` (default: ``None``)
OUTPUT:
an element of the :meth:`residue_ring` of this valuation, the reduction modulo the ideal of elements of positive valuation
ALGORITHM:
We follow the algorithm given in the proof of Theorem 12.1 of [Mac1936I]_: If ``f`` has positive valuation, the reduction is simply zero. Otherwise, let `f=\sum f_i\phi^i` be the expansion of `f`, as computed by :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.coefficients`. Since the valuation is zero, the exponents `i` must all be multiples of `\tau`, the index the value group of the base valuation in the value group of this valuation. Hence, there is an :meth:`~sage.rings.valuation.inductive_valuation.InductiveValuation.equivalence_unit` `Q` with the same valuation as `\phi^\tau`. Let `Q'` be its :meth:`~sage.rings.valuation.inductive_valuation.InductiveValuation.equivalence_reciprocal`. Now, rewrite each term `f_i\phi^{i\tau}=(f_iQ^i)(\phi^\tau Q^{-1})^i`; it turns out that the second factor in this expression is a lift of the generator of the :meth:`~sage.rings.valuation.valuation_space.DiscretePseudoValuationSpace.ElementMethods.residue_field`. The reduction of the first factor can be computed recursively.
EXAMPLES::
sage: R.<u> = Qq(4, 10) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: v.reduce(x) x sage: v.reduce(S(u)) u0
sage: w = v.augmentation(x^2 + x + u, 1/2) sage: w.reduce(S.one()) 1 sage: w.reduce(S(2)) 0 sage: w.reduce(S(u)) u0 sage: w.reduce(x) # this gives the generator of the residue field extension of w over v u1 sage: f = (x^2 + x + u)^2 / 2 sage: w.reduce(f) x sage: w.reduce(f + x + 1) x + u1 + 1
sage: ww = w.augmentation((x^2 + x + u)^2 + 2, 5/3) sage: g = ((x^2 + x + u)^2 + 2)^3 / 2^5 sage: ww.reduce(g) x sage: ww.reduce(f) 1 sage: ww.is_equivalent(f, 1) True sage: ww.reduce(f * g) x sage: ww.reduce(f + g) x + 1
"""
from itertools import islice coefficients = islice(coefficients, 0, tau*degree_bound + 1, 1)
# rewrite as sum of f_i phi^{i tau}, i.e., drop the coefficients that # can have no influence on the reduction raise ValueError("f must not have negative valuation") else: # the validity of the coefficients with i % tau == 0 is checked by # the recursive call to reduce below # replace f_i by f_i Q^{i tau} # we do not know the correct valuation of the coefficient, but # the computation is faster if we know that the coefficient # has positive valuation else:
# recursively reduce the f_i Q^{i tau} if valuations[i] is not infinity else self._base_valuation.residue_ring().zero() for i,c in enumerate(coefficients)]
# reduce the Q'^i phi^i
def _residue_field_generator(self): r""" Return a root of :meth:`psi` in :meth:`residue_ring`.
EXAMPLES::
sage: R.<u> = Qq(4, 10) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, 1/2) sage: w._residue_field_generator() u1
""" else:
r""" Return a polynomial which reduces to ``F``.
INPUT:
- ``F`` -- an element of the :meth:`residue_ring`
- ``report_coefficients`` -- whether to return the coefficients of the :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.phi`-adic expansion or the actual polynomial (default: ``False``, i.e., return the polynomial)
OUTPUT:
A polynomial in the domain of the valuation with reduction ``F``, monic if ``F`` is monic.
ALGORITHM:
Since this is the inverse of :meth:`reduce`, we only have to go backwards through the algorithm described there.
EXAMPLES::
sage: R.<u> = Qq(4, 10) sage: S.<x> = R[] sage: v = GaussValuation(S)
sage: w = v.augmentation(x^2 + x + u, 1/2) sage: y = w.residue_ring().gen() sage: u1 = w.residue_ring().base().gen()
sage: w.lift(1) 1 + O(2^10) sage: w.lift(0) 0 sage: w.lift(u1) (1 + O(2^10))*x sage: w.reduce(w.lift(y)) == y True sage: w.reduce(w.lift(y + u1 + 1)) == y + u1 + 1 True
sage: ww = w.augmentation((x^2 + x + u)^2 + 2, 5/3) sage: y = ww.residue_ring().gen() sage: u2 = ww.residue_ring().base().gen()
sage: ww.reduce(ww.lift(y)) == y True sage: ww.reduce(ww.lift(1)) == 1 True sage: ww.reduce(ww.lift(y + 1)) == y + 1 True
A more complicated example::
sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, 1) sage: ww = w.augmentation((x^2 + x + u)^2 + 2*x*(x^2 + x + u) + 4*x, 3) sage: u = ww.residue_ring().base().gen()
sage: F = ww.residue_ring()(u); F u2 sage: f = ww.lift(F); f (2^-1 + O(2^9))*x^2 + (2^-1 + O(2^9))*x + u*2^-1 + O(2^9) sage: F == ww.reduce(f) True
"""
raise NotImplementedError("only implemented for polynomial rings over fields")
# in the last step of reduce, the f_iQ^i are reduced, and evaluated at # the generator of the residue field # here, we undo this: for c in F.coefficients(sparse=False) ] # now the coefficients correspond to the expansion with (f_iQ^i)(Q^{-1} phi)^i
# now we undo the factors of Q^i (the if else is necessary to handle the case when mu is infinity, i.e., when _Q_reciprocal() is undefined) for i,c in enumerate(coeffs) ] # reduce the coefficients mod phi; the part that exceeds phi has no effect on the reduction of the coefficient
r""" Lift the irreducible polynomial ``F`` to a key polynomial.
INPUT:
- ``F`` -- an irreducible non-constant polynomial in the :meth:`residue_ring` of this valuation
- ``check`` -- whether or not to check correctness of ``F`` (default: ``True``)
OUTPUT:
A polynomial `f` in the domain of this valuation which is a key polynomial for this valuation and which, for a suitable equivalence unit `R`, satifies that the reduction of `Rf` is ``F``
ALGORITHM:
We follow the algorithm described in Theorem 13.1 [Mac1936I]_ which, after a :meth:`lift` of ``F``, essentially shifts the valuations of all terms in the `\phi`-adic expansion up and then kills the leading coefficient.
EXAMPLES::
sage: R.<u> = Qq(4, 10) sage: S.<x> = R[] sage: v = GaussValuation(S)
sage: w = v.augmentation(x^2 + x + u, 1/2) sage: y = w.residue_ring().gen() sage: f = w.lift_to_key(y + 1); f (1 + O(2^10))*x^4 + (2 + O(2^11))*x^3 + (1 + u*2 + O(2^10))*x^2 + (u*2 + O(2^11))*x + (u + 1) + u*2 + O(2^10) sage: w.is_key(f) True
A more complicated example::
sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, 1) sage: ww = w.augmentation((x^2 + x + u)^2 + 2*x*(x^2 + x + u) + 4*x, 3)
sage: u = ww.residue_ring().base().gen() sage: y = ww.residue_ring().gen() sage: f = ww.lift_to_key(y^3+y+u) sage: f.degree() 12 sage: ww.is_key(f) True
"""
raise NotImplementedError("only implemented for polynomial rings over fields")
raise TypeError("there are no keys over this valuation") raise ValueError("F must not be constant") raise ValueError("F must be monic") raise ValueError("F must be irreducible")
return self.phi()
# In the phi-adic development, the second-highest coefficient could # spill over into the highest coefficient (which is a constant one) # so we need to mod it away. # This can not happen for other coefficients because self._Q() has # degree at most the degree of phi.
def _Q(self, e): r""" Return the polynomial `Q^e` used in the construction to :meth:`reduce` an element to the :meth:`residue_ring`.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, 1)
sage: w._Q(1) 2
"""
r""" Return the :meth:`equivalence_reciprocal` of the ``e``-th power of :meth:`_Q`.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x^2 + x + 1, 1)
sage: w._Q_reciprocal() 1/2
"""
# esentially this checks that the reduction of Q'*phi^tau is the # generator of the residue field
r""" A finite augmented valuation, i.e., an augmented valuation which is discrete, or equivalently an augmented valuation which assigns to its last key polynomial a finite valuation.
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, 1/2)
""" r""" EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, 1/2) sage: from sage.rings.valuation.augmented_valuation import FiniteAugmentedValuation sage: isinstance(w, FiniteAugmentedValuation) True
"""
def value_group(self): r""" Return the value group of this valuation.
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S)
sage: w = v.augmentation(x^2 + x + u, 1/2) sage: w.value_group() Additive Abelian Group generated by 1/2
sage: ww = w.augmentation((x^2 + x + u)^2 + 2, 5/3) sage: ww.value_group() Additive Abelian Group generated by 1/6
"""
r""" Return the value semigroup of this valuation.
EXAMPLES::
sage: R.<u> = Zq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S)
sage: w = v.augmentation(x^2 + x + u, 1/2) sage: w.value_semigroup() Additive Abelian Semigroup generated by 1/2
sage: ww = w.augmentation((x^2 + x + u)^2 + 2, 5/3) sage: ww.value_semigroup() Additive Abelian Semigroup generated by 1/2, 5/3
"""
r""" Return the valuations of the `f_i\phi^i` in the expansion `f=\sum_i f_i\phi^i`.
INPUT:
- ``f`` -- a polynomial in the domain of this valuation
- ``coefficients`` -- the coefficients of ``f`` as produced by :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.coefficients` or ``None`` (default: ``None``); this can be used to speed up the computation when the expansion of ``f`` is already known from a previous computation.
- ``call_error`` -- whether or not to speed up the computation by assuming that the result is only used to compute the valuation of ``f`` (default: ``False``)
OUTPUT:
An iterator over rational numbers (or infinity) `[v(f_0), v(f_1\phi), \dots]`
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S)
sage: w = v.augmentation(x^2 + x + u, 1/2) sage: list(w.valuations( x^2 + 1 )) [0, 1/2]
sage: ww = w.augmentation((x^2 + x + u)^2 + 2, 5/3) sage: list(ww.valuations( ((x^2 + x + u)^2 + 2)^3 )) [+Infinity, +Infinity, +Infinity, 5]
"""
else:
r""" Return a simplified version of ``f``.
Produce an element which differs from ``f`` by an element of valuation strictly greater than the valuation of ``f`` (or strictly greater than ``error`` if set.)
INPUT:
- ``f`` -- an element in the domain of this valuation
- ``error`` -- a rational, infinity, or ``None`` (default: ``None``), the error allowed to introduce through the simplification
- ``force`` -- whether or not to simplify ``f`` even if there is heuristically no change in the coefficient size of ``f`` expected (default: ``False``)
- ``effective_degree`` -- when set, assume that coefficients beyond ``effective_degree`` in the :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.phi`-adic development can be safely dropped (default: ``None``)
- ``size_heuristic_bound`` -- when ``force`` is not set, the expected factor by which the coefficients need to shrink to perform an actual simplification (default: 32)
- ``phiadic`` -- whether to simplify the coefficients in the `\phi`-adic expansion recursively. This tends to be slower and sometimes leads to very huge coefficients in the `x`-adic expansion (default: ``False``.)
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, 1/2) sage: w.simplify(x^10/2 + 1, force=True) # not tested - error is incorrect (u + 1)*2^-1 + O(2^4)
"""
# if the caller was sure that we should simplify, then we should try to do the best simplification possible error = self(f) if force else self.upper_bound(f)
0 if valuations[i] > error else self._base_valuation.simplify(c, error=error-i*self._mu, force=force, phiadic=True) for (i,c) in enumerate(coefficients)])(self.phi()) else:
r""" Return a lower bound of this valuation at ``f``.
Use this method to get an approximation of the valuation of ``f`` when speed is more important than accuracy.
ALGORITHM:
The main cost of evaluation is the computation of the :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.coefficients` of the :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.phi`-adic expansion of ``f`` (which often leads to coefficient bloat.) So unless :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.phi` is trivial, we fall back to valuation which this valuation augments since it is guaranteed to be smaller everywhere.
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, 1/2) sage: w.lower_bound(x^2 + x + u) 0
"""
else:
r""" Return an upper bound of this valuation at ``f``.
Use this method to get an approximation of the valuation of ``f`` when speed is more important than accuracy.
ALGORITHM:
Any entry of :meth:`valuations` serves as an upper bound. However, computation of the :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.phi`-adic expansion of ``f`` is quite costly. Therefore, we produce an upper bound on the last entry of :meth:`valuations`, namely the valuation of the leading coefficient of ``f`` plus the valuation of the appropriate power of :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.phi`.
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, 1/2) sage: w.upper_bound(x^2 + x + u) 1/2
"""
r""" An augmented valuation which is discrete, i.e., which assigns a finite valuation to its last key polynomial, but which can not be further augmented.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, valuations.TrivialValuation(QQ)) sage: w = v.augmentation(x, 1)
""" r""" TESTS::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, valuations.TrivialValuation(QQ)) sage: w = v.augmentation(x, 1) sage: from sage.rings.valuation.augmented_valuation import FinalFiniteAugmentedValuation sage: isinstance(w, FinalFiniteAugmentedValuation) True
"""
r""" An augmented valuation which is discrete, i.e., which assigns a finite valuation to its last key polynomial, and which can be augmented furter.
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x, 1)
""" r""" TESTS::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x, 1) sage: from sage.rings.valuation.augmented_valuation import NonFinalFiniteAugmentedValuation sage: isinstance(w, NonFinalFiniteAugmentedValuation) True
"""
r""" An augmented valuation which is infinite, i.e., which assigns valuation infinity to its last key polynomial (and which can therefore not be augmented further.)
EXAMPLES::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x, infinity)
""" r""" TESTS::
sage: R.<x> = QQ[] sage: v = GaussValuation(R, QQ.valuation(2)) sage: w = v.augmentation(x, infinity) sage: from sage.rings.valuation.augmented_valuation import InfiniteAugmentedValuation sage: isinstance(w, InfiniteAugmentedValuation) True
"""
def value_group(self): r""" Return the value group of this valuation.
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x, infinity) sage: w.value_group() Additive Abelian Group generated by 1
"""
def value_semigroup(self): r""" Return the value semigroup of this valuation.
EXAMPLES::
sage: R.<u> = Zq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x, infinity) sage: w.value_semigroup() Additive Abelian Semigroup generated by 1
"""
r""" Return the valuations of the `f_i\phi^i` in the expansion `f=\sum_i f_i\phi^i`.
INPUT:
- ``f`` -- a polynomial in the domain of this valuation
- ``coefficients`` -- the coefficients of ``f`` as produced by :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.coefficients` or ``None`` (default: ``None``); this can be used to speed up the computation when the expansion of ``f`` is already known from a previous computation.
- ``call_error`` -- whether or not to speed up the computation by assuming that the result is only used to compute the valuation of ``f`` (default: ``False``)
OUTPUT:
An iterator over rational numbers (or infinity) `[v(f_0), v(f_1\phi), \dots]`
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x, infinity) sage: list(w.valuations(x^2 + 1)) [0, +Infinity, +Infinity]
"""
constant_coefficient = coefficients[0] else:
r""" Return a simplified version of ``f``.
Produce an element which differs from ``f`` by an element of valuation strictly greater than the valuation of ``f`` (or strictly greater than ``error`` if set.)
INPUT:
- ``f`` -- an element in the domain of this valuation
- ``error`` -- a rational, infinity, or ``None`` (default: ``None``), the error allowed to introduce through the simplification
- ``force`` -- whether or not to simplify ``f`` even if there is heuristically no change in the coefficient size of ``f`` expected (default: ``False``)
- ``effective_degree`` -- ignored; for compatibility with other ``simplify`` methods
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, infinity) sage: w.simplify(x^10/2 + 1, force=True) # not tested - error incorrect (u + 1)*2^-1 + O(2^4)
"""
error = self.upper_bound(f)
return f
r""" Return a lower bound of this valuation at ``f``.
Use this method to get an approximation of the valuation of ``f`` when speed is more important than accuracy.
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, infinity) sage: w.lower_bound(x^2 + x + u) +Infinity
"""
r""" Return an upper bound of this valuation at ``f``.
Use this method to get an approximation of the valuation of ``f`` when speed is more important than accuracy.
EXAMPLES::
sage: R.<u> = Qq(4, 5) sage: S.<x> = R[] sage: v = GaussValuation(S) sage: w = v.augmentation(x^2 + x + u, infinity) sage: w.upper_bound(x^2 + x + u) +Infinity
""" |