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_
toself
, 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()
orrestriction()
, 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 valuationprecision
– 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 toX
again viareduce()
.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 theresidue_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 touniformizer()
bys
“digits”.For non-negative
s
, this just returnsx
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 ofx
(or strictly greater thanerror
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