Spaces of valuations - Discrete Valuations and Discrete Pseudo-Valuations

Skip to content
Back to top
View this page
Edit this page

# Spaces of valuations

This module provides spaces of exponential pseudo-valuations on integral domains. It currently only provides support for such valuations if they are discrete, i.e., their image is a discrete additive subgroup of the rational numbers extended by \(\infty\).

AUTHORS:

- Julian Rüth (2016-10-14): initial version

EXAMPLES:

Sage

    sage: QQ.valuation(2).parent()
    Discrete pseudo-valuations on Rational Field

Python

    >>> from sage.all import *
    >>> QQ.valuation(Integer(2)).parent()
    Discrete pseudo-valuations on Rational Field

Note

Note that many tests not only in this module do not create instances of valuations directly since this gives the wrong inheritance structure on the resulting objects:

Sage

    sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
    sage: from sage.rings.valuation.trivial_valuation import TrivialDiscretePseudoValuation
    sage: H = DiscretePseudoValuationSpace(QQ)
    sage: v = TrivialDiscretePseudoValuation(H)
    sage: v._test_category()
    Traceback (most recent call last):
    ...
    AssertionError: False is not true

Python

    >>> from sage.all import *
    >>> from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
    >>> from sage.rings.valuation.trivial_valuation import TrivialDiscretePseudoValuation
    >>> H = DiscretePseudoValuationSpace(QQ)
    >>> v = TrivialDiscretePseudoValuation(H)
    >>> v._test_category()
    Traceback (most recent call last):
    ...
    AssertionError: False is not true

Instead, the valuations need to be created through the `__make_element_class__` of the containing space:

Sage

    sage: from sage.rings.valuation.trivial_valuation import TrivialDiscretePseudoValuation
    sage: v = H.__make_element_class__(TrivialDiscretePseudoValuation)(H)
    sage: v._test_category()

[Python]

    >>> from sage.all import *
    >>> from sage.rings.valuation.trivial_valuation import TrivialDiscretePseudoValuation
    >>> v = H.__make_element_class__(TrivialDiscretePseudoValuation)(H)
    >>> v._test_category()

The factories such as `TrivialPseudoValuation` provide the right inheritance structure:

Sage

    sage: v = valuations.TrivialPseudoValuation(QQ)
    sage: v._test_category()

Python

    >>> from sage.all import *
    >>> v = valuations.TrivialPseudoValuation(QQ)
    >>> v._test_category()

class sage.rings.valuation.valuation_space.DiscretePseudoValuationSpace(domain)

  Bases: `UniqueRepresentation`, `Homset`

  The space of discrete pseudo-valuations on `domain`.

  EXAMPLES:

  Sage

      sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
      sage: H = DiscretePseudoValuationSpace(QQ)
      sage: QQ.valuation(2) in H
      True

  Python

      >>> from sage.all import *
      >>> from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
      >>> H = DiscretePseudoValuationSpace(QQ)
      >>> QQ.valuation(Integer(2)) in H
      True

  Note

  We do not distinguish between the space of discrete valuations and the space of discrete pseudo-valuations. This is entirely for practical reasons: We would like to model the fact that every discrete valuation is also a discrete pseudo-valuation. At first, it seems to be sufficient to make sure that the `in` operator works which can essentially be achieved by overriding `_element_constructor_` of the space of discrete pseudo-valuations to accept discrete valuations by just returning them. Currently, however, if one does not change the parent of an element in `_element_constructor_` to `self`, then one cannot register that conversion as a coercion. Consequently, the operators `<=` and `>=` cannot be made to work between discrete valuations and discrete pseudo-valuations on the same domain (because the implementation only calls `_richcmp` if both operands have the same parent.) Of course, we could override `__ge__` and `__le__` but then we would likely run into other surprises. So in the end, we went for a single homspace for all discrete valuations (pseudo or not) as this makes the implementation much easier.

  Todo

  The comparison problem might be fixed by Issue #22029 or similar.

  class ElementMethods

    Bases: `object`

    Provides methods for discrete pseudo-valuations that are added automatically to valuations in this space.

    EXAMPLES:

    Here is an example of a method that is automagically added to a discrete valuation:

    Sage

        sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
        sage: H = DiscretePseudoValuationSpace(QQ)
        sage: QQ.valuation(2).is_discrete_pseudo_valuation() # indirect doctest
        True

    Python

        >>> from sage.all import *
        >>> from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
        >>> H = DiscretePseudoValuationSpace(QQ)
        >>> QQ.valuation(Integer(2)).is_discrete_pseudo_valuation() # indirect doctest
        True

    The methods will be provided even if the concrete type is not created with `__make_element_class__`:

    Sage

        sage: from sage.rings.valuation.valuation import DiscretePseudoValuation
        sage: m = DiscretePseudoValuation(H)
        sage: m.parent() is H
        True
        sage: m.is_discrete_pseudo_valuation()
        True

    [Python]

        >>> from sage.all import *
        >>> from sage.rings.valuation.valuation import DiscretePseudoValuation
        >>> m = DiscretePseudoValuation(H)
        >>> m.parent() is H
        True
        >>> m.is_discrete_pseudo_valuation()
        True

    However, the category framework advises you to use inheritance:

    Sage

        sage: m._test_category()
        Traceback (most recent call last):
        ...
        AssertionError: False is not true

    Python

        >>> from sage.all import *
        >>> m._test_category()
        Traceback (most recent call last):
        ...
        AssertionError: False is not true

    Using `__make_element_class__`, makes your concrete valuation inherit from this class:

    Sage

        sage: m = H.__make_element_class__(DiscretePseudoValuation)(H)
        sage: m._test_category()

    [Python]

        >>> from sage.all import *
        >>> m = H.__make_element_class__(DiscretePseudoValuation)(H)
        >>> m._test_category()

    change_domain(ring)

      Return this valuation over `ring`.

      Unlike `extension()` or `restriction()`, this might not be completely sane mathematically. It is essentially a conversion of this valuation into another space of valuations.

      EXAMPLES:

      Sage

          sage: v = QQ.valuation(3)
          sage: v.change_domain(ZZ)
          3-adic valuation

      Python

          >>> from sage.all import *
          >>> v = QQ.valuation(Integer(3))
          >>> v.change_domain(ZZ)
          3-adic valuation

    element_with_valuation(s)

      Return an element in the domain of this valuation with valuation `s`.

      EXAMPLES:

      Sage

          sage: v = ZZ.valuation(2)
          sage: v.element_with_valuation(10)
          1024

      Python

          >>> from sage.all import *
          >>> v = ZZ.valuation(Integer(2))
          >>> v.element_with_valuation(Integer(10))
          1024

    extension(ring)

      Return the unique extension of this valuation to `ring`.

      EXAMPLES:

      Sage

          sage: v = ZZ.valuation(2)
          sage: w = v.extension(QQ)
          sage: w.domain()
          Rational Field

      Python

          >>> from sage.all import *
          >>> v = ZZ.valuation(Integer(2))
          >>> w = v.extension(QQ)
          >>> w.domain()
          Rational Field

    extensions(ring)

      Return the extensions of this valuation to `ring`.

      EXAMPLES:

      Sage

          sage: v = ZZ.valuation(2)
          sage: v.extensions(QQ)
          [2-adic valuation]

      Python

          >>> from sage.all import *
          >>> v = ZZ.valuation(Integer(2))
          >>> v.extensions(QQ)
          [2-adic valuation]

    inverse(x, precision)

      Return an approximate inverse of `x`.

      The element returned is such that the product differs from 1 by an element of valuation at least `precision`.

      INPUT:

      - `x` – an element in the domain of this valuation

      - `precision` – a rational or infinity

      EXAMPLES:

      Sage

          sage: v = ZZ.valuation(2)
          sage: x = 3
          sage: y = v.inverse(3, 2); y
          3
          sage: x*y - 1
          8

      Python

          >>> from sage.all import *
          >>> v = ZZ.valuation(Integer(2))
          >>> x = Integer(3)
          >>> y = v.inverse(Integer(3), Integer(2)); y
          3
          >>> x*y - Integer(1)
          8

      This might not be possible for elements of positive valuation:

      Sage

          sage: v.inverse(2, 2)
          Traceback (most recent call last):
          ...
          ValueError: element has no approximate inverse in this ring

      [Python]

          >>> from sage.all import *
          >>> v.inverse(Integer(2), Integer(2))
          Traceback (most recent call last):
          ...
          ValueError: element has no approximate inverse in this ring

      Of course this always works over fields:

      Sage

          sage: v = QQ.valuation(2)
          sage: v.inverse(2, 2)
          1/2

      Python

          >>> from sage.all import *
          >>> v = QQ.valuation(Integer(2))
          >>> v.inverse(Integer(2), Integer(2))
          1/2

    is_discrete_pseudo_valuation()

      Return whether this valuation is a discrete pseudo-valuation.

      EXAMPLES:

      Sage

          sage: QQ.valuation(2).is_discrete_pseudo_valuation()
          True

      Python

          >>> from sage.all import *
          >>> QQ.valuation(Integer(2)).is_discrete_pseudo_valuation()
          True

    is_discrete_valuation()

      Return whether this valuation is a discrete valuation, i.e., whether it is a `discrete pseudo valuation` that only sends zero to \(\infty\).

      EXAMPLES:

      Sage

          sage: QQ.valuation(2).is_discrete_valuation()
          True

      Python

          >>> from sage.all import *
          >>> QQ.valuation(Integer(2)).is_discrete_valuation()
          True

    is_negative_pseudo_valuation()

      Return whether this valuation is a discrete pseudo-valuation that does attain \(-\infty\), i.e., it is non-trivial and its domain contains an element with valuation \(\infty\) that has an inverse.

      EXAMPLES:

      Sage

          sage: QQ.valuation(2).is_negative_pseudo_valuation()
          False

      Python

          >>> from sage.all import *
          >>> QQ.valuation(Integer(2)).is_negative_pseudo_valuation()
          False

    is_trivial()

      Return whether this valuation is trivial, i.e., whether it is constant \(\infty\) or constant zero for everything but the zero element.

      Subclasses need to override this method if they do not implement `uniformizer()`.

      EXAMPLES:

      Sage

          sage: QQ.valuation(7).is_trivial()
          False

      Python

          >>> from sage.all import *
          >>> QQ.valuation(Integer(7)).is_trivial()
          False

    lift(X)

      Return a lift of `X` in the domain which reduces down to `X` again via `reduce()`.

      EXAMPLES:

      Sage

          sage: v = QQ.valuation(2)
          sage: v.lift(v.residue_ring().one())
          1

      Python

          >>> from sage.all import *
          >>> v = QQ.valuation(Integer(2))
          >>> v.lift(v.residue_ring().one())
          1

    lower_bound(x)

      Return a lower bound of this valuation at `x`.

      Use this method to get an approximation of the valuation of `x` when speed is more important than accuracy.

      EXAMPLES:

      Sage

          sage: v = ZZ.valuation(2)
          sage: v.lower_bound(2^10)
          10

      Python

          >>> from sage.all import *
          >>> v = ZZ.valuation(Integer(2))
          >>> v.lower_bound(Integer(2)**Integer(10))
          10

    reduce(x)

      Return the image of `x` in the `residue_ring()` of this valuation.

      EXAMPLES:

      Sage

          sage: v = QQ.valuation(2)
          sage: v.reduce(2)
          0
          sage: v.reduce(1)
          1
          sage: v.reduce(1/3)
          1
          sage: v.reduce(1/2)
          Traceback (most recent call last):
          ...
          ValueError: reduction is only defined for elements of nonnegative valuation

      Python

          >>> from sage.all import *
          >>> v = QQ.valuation(Integer(2))
          >>> v.reduce(Integer(2))
          0
          >>> v.reduce(Integer(1))
          1
          >>> v.reduce(Integer(1)/Integer(3))
          1
          >>> v.reduce(Integer(1)/Integer(2))
          Traceback (most recent call last):
          ...
          ValueError: reduction is only defined for elements of nonnegative valuation

    residue_field()

      Return the residue field of this valuation, i.e., the field of fractions of the `residue_ring()`, the elements of nonnegative valuation modulo the elements of positive valuation.

      EXAMPLES:

      Sage

          sage: QQ.valuation(2).residue_field()
          Finite Field of size 2
          sage: valuations.TrivialValuation(QQ).residue_field()
          Rational Field

          sage: valuations.TrivialValuation(ZZ).residue_field()
          Rational Field
          sage: GaussValuation(ZZ['x'], ZZ.valuation(2)).residue_field()
          Rational function field in x over Finite Field of size 2

      Python

          >>> from sage.all import *
          >>> QQ.valuation(Integer(2)).residue_field()
          Finite Field of size 2
          >>> valuations.TrivialValuation(QQ).residue_field()
          Rational Field

          >>> valuations.TrivialValuation(ZZ).residue_field()
          Rational Field
          >>> GaussValuation(ZZ['x'], ZZ.valuation(Integer(2))).residue_field()
          Rational function field in x over Finite Field of size 2

    residue_ring()

      Return the residue ring of this valuation, i.e., the elements of nonnegative valuation modulo the elements of positive valuation. EXAMPLES:

      Sage

          sage: QQ.valuation(2).residue_ring()
          Finite Field of size 2
          sage: valuations.TrivialValuation(QQ).residue_ring()
          Rational Field

      Python

          >>> from sage.all import *
          >>> QQ.valuation(Integer(2)).residue_ring()
          Finite Field of size 2
          >>> valuations.TrivialValuation(QQ).residue_ring()
          Rational Field

      Note that a residue ring always exists, even when a residue field may not:

      Sage

          sage: valuations.TrivialPseudoValuation(QQ).residue_ring()
          Quotient of Rational Field by the ideal (1)
          sage: valuations.TrivialValuation(ZZ).residue_ring()
          Integer Ring
          sage: GaussValuation(ZZ['x'], ZZ.valuation(2)).residue_ring()
          Univariate Polynomial Ring in x over Finite Field of size 2...

      [Python]

          >>> from sage.all import *
          >>> valuations.TrivialPseudoValuation(QQ).residue_ring()
          Quotient of Rational Field by the ideal (1)
          >>> valuations.TrivialValuation(ZZ).residue_ring()
          Integer Ring
          >>> GaussValuation(ZZ['x'], ZZ.valuation(Integer(2))).residue_ring()
          Univariate Polynomial Ring in x over Finite Field of size 2...

    restriction(ring)

      Return the restriction of this valuation to `ring`.

      EXAMPLES:

      Sage

          sage: v = QQ.valuation(2)
          sage: w = v.restriction(ZZ)
          sage: w.domain()
          Integer Ring

      Python

          >>> from sage.all import *
          >>> v = QQ.valuation(Integer(2))
          >>> w = v.restriction(ZZ)
          >>> w.domain()
          Integer Ring

    scale(scalar)

      Return this valuation scaled by `scalar`.

      INPUT:

      - `scalar` – a nonnegative rational number or infinity

      EXAMPLES:

      Sage

          sage: v = ZZ.valuation(3)
          sage: w = v.scale(3)
          sage: w(3)
          3

      Python

          >>> from sage.all import *
          >>> v = ZZ.valuation(Integer(3))
          >>> w = v.scale(Integer(3))
          >>> w(Integer(3))
          3

      Scaling can also be done through multiplication with a scalar:

      Sage

          sage: w/3 == v
          True

      [Python]

          >>> from sage.all import *
          >>> w/Integer(3) == v
          True

      Multiplication by zero produces the trivial discrete valuation:

      Sage

          sage: w = 0*v
          sage: w(3)
          0
          sage: w(0)
          +Infinity

      Python

          >>> from sage.all import *
          >>> w = Integer(0)*v
          >>> w(Integer(3))
          0
          >>> w(Integer(0))
          +Infinity

      Multiplication by infinity produces the trivial discrete pseudo-valuation:

      Sage

          sage: w = infinity*v
          sage: w(3)
          +Infinity
          sage: w(0)
          +Infinity

      [Python]

          >>> from sage.all import *
          >>> w = infinity*v
          >>> w(Integer(3))
          +Infinity
          >>> w(Integer(0))
          +Infinity

    separating_element(others)

      Return an element in the domain of this valuation which has positive valuation with respect to this valuation but negative valuation with respect to the valuations in `others`.

      EXAMPLES:

      Sage

          sage: v2 = QQ.valuation(2)
          sage: v3 = QQ.valuation(3)
          sage: v5 = QQ.valuation(5)
          sage: v2.separating_element([v3,v5])
          4/15

      Python

          >>> from sage.all import *
          >>> v2 = QQ.valuation(Integer(2))
          >>> v3 = QQ.valuation(Integer(3))
          >>> v5 = QQ.valuation(Integer(5))
          >>> v2.separating_element([v3,v5])
          4/15

    shift(x, s)

      Shift `x` in its expansion with respect to `uniformizer()` by `s` “digits”.

      For nonnegative `s`, this just returns `x` multiplied by a power of the uniformizer \(\pi\).

      For negative `s`, it does the same but when not over a field, it drops coefficients in the \(\pi\)-adic expansion which have negative valuation.

      EXAMPLES:

      Sage

          sage: v = ZZ.valuation(2)
          sage: v.shift(1, 10)
          1024
          sage: v.shift(11, -1)
          5

      Python

          >>> from sage.all import *
          >>> v = ZZ.valuation(Integer(2))
          >>> v.shift(Integer(1), Integer(10))
          1024
          >>> v.shift(Integer(11), -Integer(1))
          5

      For some rings, there is no clear \(\pi\)-adic expansion. In this case, this method performs negative shifts by iterated division by the uniformizer and substraction of a lift of the reduction:

      Sage

          sage: R.<x> = ZZ[]
          sage: v = ZZ.valuation(2)
          sage: w = GaussValuation(R, v)
          sage: w.shift(x, 1)
          2*x
          sage: w.shift(2*x, -1)
          x
          sage: w.shift(x + 2*x^2, -1)
          x^2

      [Python]

          >>> from sage.all import *
          >>> R = ZZ['x']; (x,) = R._first_ngens(1)
          >>> v = ZZ.valuation(Integer(2))
          >>> w = GaussValuation(R, v)
          >>> w.shift(x, Integer(1))
          2*x
          >>> w.shift(Integer(2)*x, -Integer(1))
          x
          >>> w.shift(x + Integer(2)*x**Integer(2), -Integer(1))
          x^2

    simplify(x, error=None, force=False)

      Return a simplified version of `x`.

      Produce an element which differs from `x` by an element of valuation strictly greater than the valuation of `x` (or strictly greater than `error` if set.)

      If `force` is not set, then expensive simplifications may be avoided.

      EXAMPLES:

      Sage

          sage: v = ZZ.valuation(2)
          sage: v.simplify(6, force=True)
          2
          sage: v.simplify(6, error=0, force=True)
          0

      Python

          >>> from sage.all import *
          >>> v = ZZ.valuation(Integer(2))
          >>> v.simplify(Integer(6), force=True)
          2
          >>> v.simplify(Integer(6), error=Integer(0), force=True)
          0

    uniformizer()

      Return an element in the domain which has positive valuation and generates the value group of this valuation.

      EXAMPLES:

      Sage

          sage: QQ.valuation(11).uniformizer()
          11

      Python

          >>> from sage.all import *
          >>> QQ.valuation(Integer(11)).uniformizer()
          11

      Trivial valuations have no uniformizer:

      Sage

          sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
          sage: v = DiscretePseudoValuationSpace(QQ).an_element()
          sage: v.is_trivial()
          True
          sage: v.uniformizer()
          Traceback (most recent call last):
          ...
          ValueError: Trivial valuations do not define a uniformizing element

      [Python]

          >>> from sage.all import *
          >>> from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
          >>> v = DiscretePseudoValuationSpace(QQ).an_element()
          >>> v.is_trivial()
          True
          >>> v.uniformizer()
          Traceback (most recent call last):
          ...
          ValueError: Trivial valuations do not define a uniformizing element

    upper_bound(x)

      Return an upper bound of this valuation at `x`.

      Use this method to get an approximation of the valuation of `x` when speed is more important than accuracy.

      EXAMPLES:

      Sage

          sage: v = ZZ.valuation(2)
          sage: v.upper_bound(2^10)
          10

      Python

          >>> from sage.all import *
          >>> v = ZZ.valuation(Integer(2))
          >>> v.upper_bound(Integer(2)**Integer(10))
          10

    value_group()

      Return the value group of this discrete pseudo-valuation, the discrete additive subgroup of the rational numbers which is generated by the valuation of the `uniformizer()`.

      EXAMPLES:

      Sage

          sage: QQ.valuation(2).value_group()
          Additive Abelian Group generated by 1

      Python

          >>> from sage.all import *
          >>> QQ.valuation(Integer(2)).value_group()
          Additive Abelian Group generated by 1

      A pseudo-valuation that is \(\infty\) everywhere, does not have a value group:

      Sage

          sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
          sage: v = DiscretePseudoValuationSpace(QQ).an_element()
          sage: v.value_group()
          Traceback (most recent call last):
          ...
          ValueError: The trivial pseudo-valuation that is infinity everywhere does not have a value group.

      [Python]

          >>> from sage.all import *
          >>> from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
          >>> v = DiscretePseudoValuationSpace(QQ).an_element()
          >>> v.value_group()
          Traceback (most recent call last):
          ...
          ValueError: The trivial pseudo-valuation that is infinity everywhere does not have a value group.

    value_semigroup()

      Return the value semigroup of this discrete pseudo-valuation, the additive subsemigroup of the rational numbers which is generated by the valuations of the elements in the domain.

      EXAMPLES:

      Most commonly, in particular over fields, the semigroup is the group generated by the valuation of the uniformizer:

      Sage

          sage: G = QQ.valuation(2).value_semigroup(); G
          Additive Abelian Semigroup generated by -1, 1
          sage: G in AdditiveMagmas().AdditiveAssociative().AdditiveUnital().AdditiveInverse()
          True

      Python

          >>> from sage.all import *
          >>> G = QQ.valuation(Integer(2)).value_semigroup(); G
          Additive Abelian Semigroup generated by -1, 1
          >>> G in AdditiveMagmas().AdditiveAssociative().AdditiveUnital().AdditiveInverse()
          True

      If the domain is a discrete valuation ring, then the semigroup consists of the positive elements of the `value_group()`:

      Sage

          sage: Zp(2).valuation().value_semigroup()
          Additive Abelian Semigroup generated by 1

      [Python]

          >>> from sage.all import *
          >>> Zp(Integer(2)).valuation().value_semigroup()
          Additive Abelian Semigroup generated by 1

      The semigroup can have a more complicated structure when the uniformizer is not in the domain:

      Sage

          sage: v = ZZ.valuation(2)
          sage: R.<x> = ZZ[]
          sage: w = GaussValuation(R, v)
          sage: u = w.augmentation(x, 5/3)
          sage: u.value_semigroup()
          Additive Abelian Semigroup generated by 1, 5/3

      Python

          >>> from sage.all import *
          >>> v = ZZ.valuation(Integer(2))
          >>> R = ZZ['x']; (x,) = R._first_ngens(1)
          >>> w = GaussValuation(R, v)
          >>> u = w.augmentation(x, Integer(5)/Integer(3))
          >>> u.value_semigroup()
          Additive Abelian Semigroup generated by 1, 5/3

class sage.rings.valuation.valuation_space.ScaleAction

  Bases: `Action`

  Action of integers, rationals and the infinity ring on valuations by scaling it.

  EXAMPLES:

  Sage

      sage: v = QQ.valuation(5)
      sage: from operator import mul
      sage: v.parent().get_action(ZZ, mul, self_on_left=False)
      Left action by Integer Ring on Discrete pseudo-valuations on Rational Field

  Python

      >>> from sage.all import *
      >>> v = QQ.valuation(Integer(5))
      >>> from operator import mul
      >>> v.parent().get_action(ZZ, mul, self_on_left=False)
      Left action by Integer Ring on Discrete pseudo-valuations on Rational Field