def _richcmp_(self, other, op): r""" Return the result of comparing this element to ``other`` with respect to ``op``. EXAMPLES:: sage: from henselization import * sage: R = ZZ.henselization(2) sage: R(3) == R(2) # indirect doctest False """ if op == 2: # == from .mac_lane_element import MacLaneElement_base if isinstance(other, MacLaneElement_base): return other._richcmp_(self, op) elif isinstance(other, BaseElement_base): from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing if (self._base is other._base or # polynomial quotient rings are not unique parents yet so # we need to work around the failing "is" (is_PolynomialQuotientRing(self._base) and is_PolynomialQuotientRing(other._base) and self._base == other._base)): if self._valuation is other._valuation: return self._x == other._x elif other in self.parent().base(): return self._x == other if op == 3: # != return not (self == other) raise NotImplementedError
def extensions(self, ring): r""" Return the extensions of this valuation to ``ring``. EXAMPLES:: sage: sys.path.append(os.getcwd()); from mac_lane import * # optional: standalone sage: v = pAdicValuation(ZZ, 2) sage: v.extensions(GaussianIntegers()) [2-adic valuation] TESTS:: sage: R.<a> = QQ[] sage: L.<a> = QQ.extension(x^3 - 2) sage: R.<b> = L[] sage: M.<b> = L.extension(b^2 + 2*b + a) sage: pAdicValuation(M, 2) 2-adic valuation Check that we can extend to a field written as a quotient:: sage: R.<x> = QQ[] sage: K.<a> = QQ.extension(x^2 + 1) sage: R.<y> = K[] sage: L.<b> = R.quo(x^2 + a) sage: pAdicValuation(QQ, 2).extensions(L) [2-adic valuation] """ if self.domain() is ring: return [self] domain_fraction_field = _fraction_field(self.domain()) if domain_fraction_field is not self.domain(): if domain_fraction_field.is_subring(ring): return pAdicValuation(domain_fraction_field, self).extensions(ring) if self.domain().is_subring(ring): from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing if is_PolynomialQuotientRing(ring): if is_PolynomialQuotientRing(self.domain()): if self.domain().modulus() == ring.modulus(): base_extensions = self._base_valuation.extensions(self._base_valuation.domain().change_ring(self._base_valuation.domain().base_ring().fraction_field())) return [pAdicValuation(ring, base._initial_approximation) for base in base_extensions] if ring.base_ring() is self.domain(): from sage.categories.all import IntegralDomains if ring in IntegralDomains(): return self._extensions_to_quotient(ring) else: return sum([w.extensions(ring) for w in self.extensions(ring.base_ring())], []) from sage.rings.number_field.number_field import is_NumberField if is_NumberField(ring.fraction_field()): if ring.base_ring().fraction_field() is self.domain().fraction_field(): from valuation_space import DiscretePseudoValuationSpace parent = DiscretePseudoValuationSpace(ring) approximants = self.mac_lane_approximants(ring.fraction_field().relative_polynomial().change_ring(self.domain()), assume_squarefree=True) return [pAdicValuation(ring, approximant, approximants) for approximant in approximants] if ring.base_ring() is not ring and self.domain().is_subring(ring.base_ring()): return sum([w.extensions(ring) for w in self.extensions(ring.base_ring())], []) return super(pAdicValuation_base, self).extensions(ring)
def _normalize_number_field_data(self, R): r""" Helper method which returns the defining data of the number field ``R``. EXAMPLES:: sage: sys.path.append(os.getcwd()); from mac_lane import * # optional: standalone sage: R.<x> = QQ[] sage: K = R.quo(x^2 + 1) sage: pAdicValuation._normalize_number_field_data(K) (Rational Field, Univariate Quotient Polynomial Ring in xbar over Rational Field with modulus x^2 + 1, x^2 + 1) """ from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing from sage.rings.number_field.number_field import is_NumberField from sage.rings.fraction_field import is_FractionField if is_NumberField(R.fraction_field()): L = R.fraction_field() G = L.relative_polynomial() K = L.base_ring() elif is_PolynomialQuotientRing(R): from sage.categories.all import NumberFields if R.base_ring().fraction_field() not in NumberFields(): raise NotImplementedError("can not normalize quotients over %r"%(R.base_ring(),)) L = R.fraction_field() K = R.base_ring().fraction_field() G = R.modulus().change_ring(K) else: raise NotImplementedError("can not normalize %r"%(R,)) return K, L, G
def create_key_and_extra_args(self, R, prime=None, approximants=None): r""" Create a unique key identifying the valuation of ``R`` with respect to ``prime``. EXAMPLES:: sage: sys.path.append(os.getcwd()); from mac_lane import * # optional: standalone sage: pAdicValuation(QQ, 2) # indirect doctest 2-adic valuation """ from sage.rings.all import ZZ, QQ from sage.rings.padics.padic_generic import pAdicGeneric from sage.rings.number_field.number_field import is_NumberField from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing if R.characteristic() != 0: # We do not support equal characteristic yet raise ValueError("R must be a ring of characteristic zero.") if R is ZZ or R is QQ: return self.create_key_for_integers(R, prime), {} elif isinstance(R, pAdicGeneric): return self.create_key_for_local_ring(R, prime), {} elif is_NumberField(R.fraction_field()) or is_PolynomialQuotientRing(R): return self.create_key_and_extra_args_for_number_field(R, prime, approximants=approximants) else: raise NotImplementedError("p-adic valuations not implemented for %r"%(R,))
def _fraction_field(ring): r""" Return a fraction field of ``ring``. EXAMPLES: This works around some annoyances with ``ring.fraction_field()``:: sage: R.<x> = ZZ[] sage: S = R.quo(x^2 + 1) sage: S.fraction_field() Fraction Field of Univariate Quotient Polynomial Ring in xbar over Integer Ring with modulus x^2 + 1 sage: from mac_lane.padic_valuation import _fraction_field sage: _fraction_field(S) Univariate Quotient Polynomial Ring in xbar over Rational Field with modulus x^2 + 1 """ from sage.categories.all import Fields if ring in Fields(): return ring from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing if is_PolynomialQuotientRing(ring): from sage.categories.all import IntegralDomains if ring in IntegralDomains(): return ring.base().change_ring(ring.base_ring().fraction_field()).quo(ring.modulus()) return ring.fraction_field()
def _normalize_number_field_data(self, R): r""" Helper method which returns the defining data of the number field ``R``. EXAMPLES:: sage: R.<x> = QQ[] sage: K = R.quo(x^2 + 1) sage: valuations.pAdicValuation._normalize_number_field_data(K) (Rational Field, Univariate Quotient Polynomial Ring in xbar over Rational Field with modulus x^2 + 1, x^2 + 1) """ from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing from sage.rings.number_field.number_field import is_NumberField from sage.rings.fraction_field import is_FractionField if is_NumberField(R.fraction_field()): L = R.fraction_field() G = L.relative_polynomial() K = L.base_ring() elif is_PolynomialQuotientRing(R): from sage.categories.all import NumberFields if R.base_ring().fraction_field() not in NumberFields(): raise NotImplementedError("can not normalize quotients over %r"%(R.base_ring(),)) L = R.fraction_field() K = R.base_ring().fraction_field() G = R.modulus().change_ring(K) else: raise NotImplementedError("can not normalize %r"%(R,)) return K, L, G
def _fraction_field(ring): r""" Return a fraction field of ``ring``. EXAMPLES: This works around some annoyances with ``ring.fraction_field()``:: sage: R.<x> = ZZ[] sage: S = R.quo(x^2 + 1) sage: S.fraction_field() Fraction Field of Univariate Quotient Polynomial Ring in xbar over Integer Ring with modulus x^2 + 1 sage: from sage.rings.padics.padic_valuation import _fraction_field sage: _fraction_field(S) Univariate Quotient Polynomial Ring in xbar over Rational Field with modulus x^2 + 1 """ from sage.categories.all import Fields if ring in Fields(): return ring from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing if is_PolynomialQuotientRing(ring): from sage.categories.all import IntegralDomains if ring in IntegralDomains(): return ring.base().change_ring(ring.base_ring().fraction_field()).quo(ring.modulus()) return ring.fraction_field()
def create_key_and_extra_args(self, R, prime=None, approximants=None): r""" Create a unique key identifying the valuation of ``R`` with respect to ``prime``. EXAMPLES:: sage: QQ.valuation(2) # indirect doctest 2-adic valuation """ from sage.rings.all import ZZ, QQ from sage.rings.padics.padic_generic import pAdicGeneric from sage.rings.number_field.number_field import is_NumberField from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing if R.characteristic() != 0: # We do not support equal characteristic yet raise ValueError("R must be a ring of characteristic zero.") if R is ZZ or R is QQ: return self.create_key_for_integers(R, prime), {} elif isinstance(R, pAdicGeneric): return self.create_key_for_local_ring(R, prime), {} elif is_NumberField(R.fraction_field()) or is_PolynomialQuotientRing(R): return self.create_key_and_extra_args_for_number_field(R, prime, approximants=approximants) else: raise NotImplementedError("p-adic valuations not implemented for %r"%(R,))
def _coerce_map_from_patched(self, domain): r""" TESTS:: sage: sys.path.append(os.getcwd()); from mac_lane import * # optional: standalone sage: R.<x> = ZZ[] sage: S.<x> = QQ[] sage: S.quo(x^2 + 1).coerce_map_from(R.quo(x^2 + 1)).is_injective() # indirect doctest True """ from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing if is_PolynomialQuotientRing(domain) and domain.modulus() == self.modulus(): if self.base().has_coerce_map_from(domain.base()): return DefaultConvertMap_unique_patched3(domain, self) from sage.rings.fraction_field import is_FractionField if is_FractionField(domain): # this should be implemented on a much higher level: # if there is a morphism R -> K then there is a morphism Frac(R) -> K if self.has_coerce_map_from(domain.base()): return True return self._coerce_map_from_original(domain)
def create_object(self, version, key, **extra_args): r""" Create a `p`-adic valuation from ``key``. EXAMPLES:: sage: ZZ.valuation(5) # indirect doctest 5-adic valuation """ from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ from sage.rings.padics.padic_generic import pAdicGeneric from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing from sage.rings.number_field.number_field import is_NumberField R = key[0] parent = DiscretePseudoValuationSpace(R) if isinstance(R, pAdicGeneric): assert (len(key) == 1) return parent.__make_element_class__(pAdicValuation_padic)(parent) elif R is ZZ or R is QQ: prime = key[1] assert (len(key) == 2) return parent.__make_element_class__(pAdicValuation_int)(parent, prime) else: v = key[1] approximants = extra_args['approximants'] parent = DiscretePseudoValuationSpace(R) K = R.fraction_field() if is_NumberField(K): G = K.relative_polynomial() elif is_PolynomialQuotientRing(R): G = R.modulus() else: raise NotImplementedError return parent.__make_element_class__(pAdicFromLimitValuation)( parent, v, G.change_ring(R.base_ring()), approximants)
def create_object(self, version, key, **extra_args): r""" Create a `p`-adic valuation from ``key``. EXAMPLES:: sage: ZZ.valuation(5) # indirect doctest 5-adic valuation """ from sage.rings.all import ZZ, QQ from sage.rings.padics.padic_generic import pAdicGeneric from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing from sage.rings.number_field.number_field import is_NumberField R = key[0] parent = DiscretePseudoValuationSpace(R) if isinstance(R, pAdicGeneric): assert(len(key)==1) return parent.__make_element_class__(pAdicValuation_padic)(parent) elif R is ZZ or R is QQ: prime = key[1] assert(len(key)==2) return parent.__make_element_class__(pAdicValuation_int)(parent, prime) else: v = key[1] approximants = extra_args['approximants'] parent = DiscretePseudoValuationSpace(R) K = R.fraction_field() if is_NumberField(K): G = K.relative_polynomial() elif is_PolynomialQuotientRing(R): G = R.modulus() else: raise NotImplementedError return parent.__make_element_class__(pAdicFromLimitValuation)(parent, v, G.change_ring(R.base_ring()), approximants)
def extensions(self, ring): r""" Return the extensions of this valuation to ``ring``. EXAMPLES:: sage: v = ZZ.valuation(2) sage: v.extensions(GaussianIntegers()) [2-adic valuation] TESTS:: sage: R.<a> = QQ[] sage: L.<a> = QQ.extension(x^3 - 2) sage: R.<b> = L[] sage: M.<b> = L.extension(b^2 + 2*b + a) sage: M.valuation(2) 2-adic valuation Check that we can extend to a field written as a quotient:: sage: R.<x> = QQ[] sage: K.<a> = QQ.extension(x^2 + 1) sage: R.<y> = K[] sage: L.<b> = R.quo(x^2 + a) sage: QQ.valuation(2).extensions(L) [2-adic valuation] A case where there was at some point an internal error in the approximants code:: sage: R.<x> = QQ[] sage: L.<a> = NumberField(x^4 + 2*x^3 + 2*x^2 + 8) sage: QQ.valuation(2).extensions(L) [[ 2-adic valuation, v(x + 2) = 3/2 ]-adic valuation, [ 2-adic valuation, v(x) = 1/2 ]-adic valuation] A case where the extension was incorrect at some point:: sage: v = QQ.valuation(2) sage: L.<a> = NumberField(x^2 + 2) sage: M.<b> = L.extension(x^2 + 1) sage: w = v.extension(L).extension(M) sage: w(w.uniformizer()) 1/4 A case where the extensions could not be separated at some point:: sage: v = QQ.valuation(2) sage: R.<x> = QQ[] sage: F = x^48 + 120*x^45 + 56*x^42 + 108*x^36 + 32*x^33 + 40*x^30 + 48*x^27 + 80*x^24 + 112*x^21 + 96*x^18 + 96*x^15 + 24*x^12 + 96*x^9 + 16*x^6 + 96*x^3 + 68 sage: L.<a> = QQ.extension(F) sage: v.extensions(L) [[ 2-adic valuation, v(x) = 1/24, v(x^24 + 4*x^18 + 10*x^12 + 12*x^6 + 8*x^3 + 6) = 29/8 ]-adic valuation, [ 2-adic valuation, v(x) = 1/24, v(x^24 + 4*x^18 + 2*x^12 + 12*x^6 + 8*x^3 + 6) = 29/8 ]-adic valuation] """ if self.domain() is ring: return [self] domain_fraction_field = _fraction_field(self.domain()) if domain_fraction_field is not self.domain(): if domain_fraction_field.is_subring(ring): return pAdicValuation(domain_fraction_field, self).extensions(ring) if self.domain().is_subring(ring): from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing if is_PolynomialQuotientRing(ring): if is_PolynomialQuotientRing(self.domain()): if self.domain().modulus() == ring.modulus(): base_extensions = self._base_valuation.extensions( self._base_valuation.domain().change_ring( self._base_valuation.domain().base_ring( ).fraction_field())) return [ pAdicValuation(ring, base._initial_approximation) for base in base_extensions ] if ring.base_ring() is self.domain(): from sage.categories.all import IntegralDomains if ring in IntegralDomains(): return self._extensions_to_quotient(ring) elif self.domain().is_subring(ring.base_ring()): return sum([ w.extensions(ring) for w in self.extensions(ring.base_ring()) ], []) from sage.rings.number_field.number_field import is_NumberField if is_NumberField(ring.fraction_field()): if ring.base_ring().fraction_field() is self.domain( ).fraction_field(): from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace parent = DiscretePseudoValuationSpace(ring) approximants = self.mac_lane_approximants( ring.fraction_field().relative_polynomial( ).change_ring(self.domain()), assume_squarefree=True, require_incomparability=True) return [ pAdicValuation(ring, approximant, approximants) for approximant in approximants ] if ring.base_ring() is not ring and self.domain().is_subring( ring.base_ring()): return sum([ w.extensions(ring) for w in self.extensions(ring.base_ring()) ], []) return super(pAdicValuation_base, self).extensions(ring)
def extensions(self, ring): r""" Return the extensions of this valuation to ``ring``. EXAMPLES:: sage: v = ZZ.valuation(2) sage: v.extensions(GaussianIntegers()) [2-adic valuation] TESTS:: sage: R.<a> = QQ[] sage: L.<a> = QQ.extension(x^3 - 2) sage: R.<b> = L[] sage: M.<b> = L.extension(b^2 + 2*b + a) sage: M.valuation(2) 2-adic valuation Check that we can extend to a field written as a quotient:: sage: R.<x> = QQ[] sage: K.<a> = QQ.extension(x^2 + 1) sage: R.<y> = K[] sage: L.<b> = R.quo(x^2 + a) sage: QQ.valuation(2).extensions(L) [2-adic valuation] A case where there was at some point an internal error in the approximants code:: sage: R.<x> = QQ[] sage: L.<a> = NumberField(x^4 + 2*x^3 + 2*x^2 + 8) sage: QQ.valuation(2).extensions(L) [[ 2-adic valuation, v(x + 2) = 3/2 ]-adic valuation, [ 2-adic valuation, v(x) = 1/2 ]-adic valuation] A case where the extension was incorrect at some point:: sage: v = QQ.valuation(2) sage: L.<a> = NumberField(x^2 + 2) sage: M.<b> = L.extension(x^2 + 1) sage: w = v.extension(L).extension(M) sage: w(w.uniformizer()) 1/4 A case where the extensions could not be separated at some point:: sage: v = QQ.valuation(2) sage: R.<x> = QQ[] sage: F = x^48 + 120*x^45 + 56*x^42 + 108*x^36 + 32*x^33 + 40*x^30 + 48*x^27 + 80*x^24 + 112*x^21 + 96*x^18 + 96*x^15 + 24*x^12 + 96*x^9 + 16*x^6 + 96*x^3 + 68 sage: L.<a> = QQ.extension(F) sage: v.extensions(L) [[ 2-adic valuation, v(x) = 1/24, v(x^24 + 4*x^18 + 10*x^12 + 12*x^6 + 8*x^3 + 6) = 29/8 ]-adic valuation, [ 2-adic valuation, v(x) = 1/24, v(x^24 + 4*x^18 + 2*x^12 + 12*x^6 + 8*x^3 + 6) = 29/8 ]-adic valuation] """ if self.domain() is ring: return [self] domain_fraction_field = _fraction_field(self.domain()) if domain_fraction_field is not self.domain(): if domain_fraction_field.is_subring(ring): return pAdicValuation(domain_fraction_field, self).extensions(ring) if self.domain().is_subring(ring): from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing if is_PolynomialQuotientRing(ring): if is_PolynomialQuotientRing(self.domain()): if self.domain().modulus() == ring.modulus(): base_extensions = self._base_valuation.extensions(self._base_valuation.domain().change_ring(self._base_valuation.domain().base_ring().fraction_field())) return [pAdicValuation(ring, base._initial_approximation) for base in base_extensions] if ring.base_ring() is self.domain(): from sage.categories.all import IntegralDomains if ring in IntegralDomains(): return self._extensions_to_quotient(ring) elif self.domain().is_subring(ring.base_ring()): return sum([w.extensions(ring) for w in self.extensions(ring.base_ring())], []) from sage.rings.number_field.number_field import is_NumberField if is_NumberField(ring.fraction_field()): if ring.base_ring().fraction_field() is self.domain().fraction_field(): from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace parent = DiscretePseudoValuationSpace(ring) approximants = self.mac_lane_approximants(ring.fraction_field().relative_polynomial().change_ring(self.domain()), assume_squarefree=True, require_incomparability=True) return [pAdicValuation(ring, approximant, approximants) for approximant in approximants] if ring.base_ring() is not ring and self.domain().is_subring(ring.base_ring()): return sum([w.extensions(ring) for w in self.extensions(ring.base_ring())], []) return super(pAdicValuation_base, self).extensions(ring)