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: QQ.valuation(2).parent()
Discrete pseudo-valuations on Rational Field
>>> 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: 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
>>> 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: from sage.rings.valuation.trivial_valuation import TrivialDiscretePseudoValuation
sage: v = H.__make_element_class__(TrivialDiscretePseudoValuation)(H)
sage: v._test_category()
>>> 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: v = valuations.TrivialPseudoValuation(QQ)
sage: v._test_category()
>>> from sage.all import *
>>> v = valuations.TrivialPseudoValuation(QQ)
>>> v._test_category()
class sage.rings.valuation.valuation_space.DiscretePseudoValuationSpace(domain)[source]#

Bases: UniqueRepresentation, Homset

The space of discrete pseudo-valuations on domain.

EXAMPLES:

sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
sage: H = DiscretePseudoValuationSpace(QQ)
sage: QQ.valuation(2) in H
True
>>> 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[source]#

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: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
sage: H = DiscretePseudoValuationSpace(QQ)
sage: QQ.valuation(2).is_discrete_pseudo_valuation() # indirect doctest
True
>>> 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: from sage.rings.valuation.valuation import DiscretePseudoValuation
sage: m = DiscretePseudoValuation(H)
sage: m.parent() is H
True
sage: m.is_discrete_pseudo_valuation()
True
>>> 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: m._test_category()
Traceback (most recent call last):
...
AssertionError: False is not true
>>> 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: m = H.__make_element_class__(DiscretePseudoValuation)(H)
sage: m._test_category()
>>> from sage.all import *
>>> m = H.__make_element_class__(DiscretePseudoValuation)(H)
>>> m._test_category()
change_domain(ring)[source]#

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: v = QQ.valuation(3)
sage: v.change_domain(ZZ)
3-adic valuation
>>> from sage.all import *
>>> v = QQ.valuation(Integer(3))
>>> v.change_domain(ZZ)
3-adic valuation
element_with_valuation(s)[source]#

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

EXAMPLES:

sage: v = ZZ.valuation(2)
sage: v.element_with_valuation(10)
1024
>>> from sage.all import *
>>> v = ZZ.valuation(Integer(2))
>>> v.element_with_valuation(Integer(10))
1024
extension(ring)[source]#

Return the unique extension of this valuation to ring.

EXAMPLES:

sage: v = ZZ.valuation(2)
sage: w = v.extension(QQ)
sage: w.domain()
Rational Field
>>> from sage.all import *
>>> v = ZZ.valuation(Integer(2))
>>> w = v.extension(QQ)
>>> w.domain()
Rational Field
extensions(ring)[source]#

Return the extensions of this valuation to ring.

EXAMPLES:

sage: v = ZZ.valuation(2)
sage: v.extensions(QQ)
[2-adic valuation]
>>> from sage.all import *
>>> v = ZZ.valuation(Integer(2))
>>> v.extensions(QQ)
[2-adic valuation]
inverse(x, precision)[source]#

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: v = ZZ.valuation(2)
sage: x = 3
sage: y = v.inverse(3, 2); y
3
sage: x*y - 1
8
>>> 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: v.inverse(2, 2)
Traceback (most recent call last):
...
ValueError: element has no approximate inverse in this ring
>>> 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: v = QQ.valuation(2)
sage: v.inverse(2, 2)
1/2
>>> from sage.all import *
>>> v = QQ.valuation(Integer(2))
>>> v.inverse(Integer(2), Integer(2))
1/2
is_discrete_pseudo_valuation()[source]#

Return whether this valuation is a discrete pseudo-valuation.

EXAMPLES:

sage: QQ.valuation(2).is_discrete_pseudo_valuation()
True
>>> from sage.all import *
>>> QQ.valuation(Integer(2)).is_discrete_pseudo_valuation()
True
is_discrete_valuation()[source]#

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: QQ.valuation(2).is_discrete_valuation()
True
>>> from sage.all import *
>>> QQ.valuation(Integer(2)).is_discrete_valuation()
True
is_negative_pseudo_valuation()[source]#

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: QQ.valuation(2).is_negative_pseudo_valuation()
False
>>> from sage.all import *
>>> QQ.valuation(Integer(2)).is_negative_pseudo_valuation()
False
is_trivial()[source]#

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: QQ.valuation(7).is_trivial()
False
>>> from sage.all import *
>>> QQ.valuation(Integer(7)).is_trivial()
False
lift(X)[source]#

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

EXAMPLES:

sage: v = QQ.valuation(2)
sage: v.lift(v.residue_ring().one())
1
>>> from sage.all import *
>>> v = QQ.valuation(Integer(2))
>>> v.lift(v.residue_ring().one())
1
lower_bound(x)[source]#

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: v = ZZ.valuation(2)
sage: v.lower_bound(2^10)
10
>>> from sage.all import *
>>> v = ZZ.valuation(Integer(2))
>>> v.lower_bound(Integer(2)**Integer(10))
10
reduce(x)[source]#

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

EXAMPLES:

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 non-negative valuation
>>> 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 non-negative valuation
residue_field()[source]#

Return the residue field of this valuation, i.e., the field of fractions of the residue_ring(), the elements of non-negative valuation modulo the elements of positive valuation.

EXAMPLES:

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
>>> 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()[source]#

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

sage: QQ.valuation(2).residue_ring()
Finite Field of size 2
sage: valuations.TrivialValuation(QQ).residue_ring()
Rational Field
>>> 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: 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...
>>> 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)[source]#

Return the restriction of this valuation to ring.

EXAMPLES:

sage: v = QQ.valuation(2)
sage: w = v.restriction(ZZ)
sage: w.domain()
Integer Ring
>>> from sage.all import *
>>> v = QQ.valuation(Integer(2))
>>> w = v.restriction(ZZ)
>>> w.domain()
Integer Ring
scale(scalar)[source]#

Return this valuation scaled by scalar.

INPUT:

  • scalar – a non-negative rational number or infinity

EXAMPLES:

sage: v = ZZ.valuation(3)
sage: w = v.scale(3)
sage: w(3)
3
>>> 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: w/3 == v
True
>>> from sage.all import *
>>> w/Integer(3) == v
True

Multiplication by zero produces the trivial discrete valuation:

sage: w = 0*v
sage: w(3)
0
sage: w(0)
+Infinity
>>> 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: w = infinity*v
sage: w(3)
+Infinity
sage: w(0)
+Infinity
>>> from sage.all import *
>>> w = infinity*v
>>> w(Integer(3))
+Infinity
>>> w(Integer(0))
+Infinity
separating_element(others)[source]#

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: v2 = QQ.valuation(2)
sage: v3 = QQ.valuation(3)
sage: v5 = QQ.valuation(5)
sage: v2.separating_element([v3,v5])
4/15
>>> 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)[source]#

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

For non-negative 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: v = ZZ.valuation(2)
sage: v.shift(1, 10)
1024
sage: v.shift(11, -1)
5
>>> 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: 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
>>> 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)[source]#

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: v = ZZ.valuation(2)
sage: v.simplify(6, force=True)
2
sage: v.simplify(6, error=0, force=True)
0
>>> 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()[source]#

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

EXAMPLES:

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

Trivial valuations have no uniformizer:

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
>>> 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)[source]#

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: v = ZZ.valuation(2)
sage: v.upper_bound(2^10)
10
>>> from sage.all import *
>>> v = ZZ.valuation(Integer(2))
>>> v.upper_bound(Integer(2)**Integer(10))
10
value_group()[source]#

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: QQ.valuation(2).value_group()
Additive Abelian Group generated by 1
>>> 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: 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.
>>> 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()[source]#

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: G = QQ.valuation(2).value_semigroup(); G
Additive Abelian Semigroup generated by -1, 1
sage: G in AdditiveMagmas().AdditiveAssociative().AdditiveUnital().AdditiveInverse()
True
>>> 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: Zp(2).valuation().value_semigroup()
Additive Abelian Semigroup generated by 1
>>> 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: 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
>>> 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[source]#

Bases: Action

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

EXAMPLES:

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