def _element_constructor_(self, x): r""" Create an element in this group from ``x``. INPUT: - ``x`` -- a rational number TESTS:: sage: sys.path.append(os.getcwd()); from mac_lane import * # optional: standalone sage: DiscreteValueGroup(0)(0) 0 sage: DiscreteValueGroup(0)(1) Traceback (most recent call last): ... ValueError: `1` is not in Trivial Additive Abelian Group. sage: DiscreteValueGroup(1)(1) 1 sage: DiscreteValueGroup(1)(1/2) Traceback (most recent call last): ... ValueError: `1/2` is not in Additive Abelian Group generated by 1. """ x = QQ.coerce(x) if x == 0 or (self._generator != 0 and x / self._generator in ZZ): return x raise ValueError("`{0}` is not in {1}.".format(x, self))
def _element_constructor_(self, x): r""" Create an element from ``x``. INPUT: - ``x`` -- a rational number or `\infty` TESTS:: sage: sys.path.append(os.getcwd()); from mac_lane import * # optional: standalone sage: DiscreteValuationCodomain()(0) 0 sage: DiscreteValuationCodomain()(infinity) +Infinity sage: DiscreteValuationCodomain()(-infinity) -Infinity """ if x is infinity: return x if x is -infinity: return x if x not in QQ: raise ValueError("must be a rational number or infinity") return QQ.coerce(x)
def _element_constructor_(self, x): r""" Create an element in this group from ``x``. INPUT: - ``x`` -- a rational number TESTS:: sage: from sage.rings.valuation.value_group import DiscreteValueSemigroup sage: DiscreteValueSemigroup([])(0) 0 sage: DiscreteValueSemigroup([])(1) Traceback (most recent call last): ... ValueError: `1` is not in Trivial Additive Abelian Semigroup. sage: DiscreteValueSemigroup([1])(1) 1 sage: DiscreteValueSemigroup([1])(-1) Traceback (most recent call last): ... ValueError: `-1` is not in Additive Abelian Semigroup generated by 1. """ x = QQ.coerce(x) if x in self._generators or self._solve_linear_program(x) is not None: return x raise ValueError("`{0}` is not in {1}.".format(x,self))
def _element_constructor_(self, x): r""" Create an element in this group from ``x``. INPUT: - ``x`` -- a rational number TESTS:: sage: from sage.rings.valuation.value_group import DiscreteValueGroup sage: DiscreteValueGroup(0)(0) 0 sage: DiscreteValueGroup(0)(1) Traceback (most recent call last): ... ValueError: `1` is not in Trivial Additive Abelian Group. sage: DiscreteValueGroup(1)(1) 1 sage: DiscreteValueGroup(1)(1/2) Traceback (most recent call last): ... ValueError: `1/2` is not in Additive Abelian Group generated by 1. """ x = QQ.coerce(x) if x == 0 or (self._generator != 0 and x/self._generator in ZZ): return x raise ValueError("`{0}` is not in {1}.".format(x,self))
def _element_constructor_(self, x): r""" Create an element from ``x``. INPUT: - ``x`` -- a rational number or `\infty` TESTS:: sage: from sage.rings.valuation.value_group import DiscreteValuationCodomain sage: DiscreteValuationCodomain()(0) 0 sage: DiscreteValuationCodomain()(infinity) +Infinity sage: DiscreteValuationCodomain()(-infinity) -Infinity """ if x is infinity: return x if x is -infinity: return x if x not in QQ: raise ValueError("must be a rational number or infinity") return QQ.coerce(x)
def _element_constructor_(self, x): r""" Create an element from ``x``. INPUT: - ``x`` -- a rational number or `\infty` TESTS:: sage: from sage.rings.valuation.value_group import DiscreteValuationCodomain sage: DiscreteValuationCodomain()(0) 0 sage: DiscreteValuationCodomain()(infinity) +Infinity sage: DiscreteValuationCodomain()(-infinity) -Infinity """ if x is infinity: return x if x is -infinity: return x if x not in QQ: raise ValueError("must be a rational number or infinity") return QQ.coerce(x)
def _element_constructor_(self, x): r""" Create an element in this group from ``x``. INPUT: - ``x`` -- a rational number TESTS:: sage: from sage.rings.valuation.value_group import DiscreteValueSemigroup sage: DiscreteValueSemigroup([])(0) 0 sage: DiscreteValueSemigroup([])(1) Traceback (most recent call last): ... ValueError: `1` is not in Trivial Additive Abelian Semigroup. sage: DiscreteValueSemigroup([1])(1) 1 sage: DiscreteValueSemigroup([1])(-1) Traceback (most recent call last): ... ValueError: `-1` is not in Additive Abelian Semigroup generated by 1. """ x = QQ.coerce(x) if x in self._generators or self._solve_linear_program(x) is not None: return x raise ValueError("`{0}` is not in {1}.".format(x,self))
def _element_constructor_(self, x): r""" Create an element in this group from ``x``. INPUT: - ``x`` -- a rational number TESTS:: sage: from sage.rings.valuation.value_group import DiscreteValueGroup sage: DiscreteValueGroup(0)(0) 0 sage: DiscreteValueGroup(0)(1) Traceback (most recent call last): ... ValueError: `1` is not in Trivial Additive Abelian Group. sage: DiscreteValueGroup(1)(1) 1 sage: DiscreteValueGroup(1)(1/2) Traceback (most recent call last): ... ValueError: `1/2` is not in Additive Abelian Group generated by 1. """ x = QQ.coerce(x) if x == 0 or (self._generator != 0 and x/self._generator in ZZ): return x raise ValueError("`{0}` is not in {1}.".format(x,self))
def __init__(self, expo, values, dop=None, check=True): r""" TESTS:: sage: from ore_algebra import * sage: from ore_algebra.analytic.naive_sum import * sage: Dops, x, Dx = DifferentialOperators() sage: LogSeriesInitialValues(0, {0: (1, 0)}, x*Dx^3 + 2*Dx^2 + x*Dx) Traceback (most recent call last): ... ValueError: invalid initial data for x*Dx^3 + 2*Dx^2 + x*Dx at 0 """ try: self.expo = QQ.coerce(expo) except TypeError: self.expo = QQbar.coerce(expo) if isinstance(values, dict): all_values = sum(values.values(), ()) # concatenation of tuples else: all_values = values values = dict((n, (values[n], )) for n in xrange(len(values))) self.universe = Sequence(all_values).universe() if not utilities.is_numeric_parent(self.universe): raise ValueError("initial values must coerce into a ball field") self.shift = { s: tuple(self.universe(a) for a in ini) for s, ini in values.iteritems() } try: if check and dop is not None and not self.is_valid_for(dop): raise ValueError( "invalid initial data for {} at 0".format(dop)) except TypeError: # coercion problems btw QQbar and number fields pass
def _element_constructor_(self, x): r""" Create an element in this group from ``x``. INPUT: - ``x`` -- a rational number TESTS:: sage: sys.path.append(os.getcwd()); from mac_lane import * # optional: standalone sage: DiscreteValueSemigroup([])(0) 0 sage: DiscreteValueSemigroup([])(1) Traceback (most recent call last): ... ValueError: `1` is not in Trivial Additive Abelian Semigroup. sage: DiscreteValueSemigroup([1])(1) 1 sage: DiscreteValueSemigroup([1])(-1) Traceback (most recent call last): ... ValueError: `-1` is not in Additive Abelian Semigroup generated by 1. """ x = QQ.coerce(x) if x in self._generators or self._solve_linear_program(x) is not None: return x raise ValueError("`{0}` is not in {1}.".format(x, self))
def create_key(self, base, s): r""" Create a key which uniquely identifies a valuation. TESTS:: sage: 3*ZZ.valuation(2) is 2*(3/2*ZZ.valuation(2)) # indirect doctest True """ from sage.rings.all import infinity, QQ if s is infinity or s not in QQ or s <= 0: # for these values we can not return a TrivialValuation() in # create_object() because that would override that instance's # _factory_data and lead to pickling errors raise ValueError("s must be a positive rational") if base.is_trivial(): # for the same reason we can not accept trivial valuations here raise ValueError("base must not be trivial") s = QQ.coerce(s) if s == 1: # we would override the _factory_data of base if we just returned # it in create_object() so we just refuse to do so raise ValueError("s must not be 1") if isinstance(base, ScaledValuation_generic): return self.create_key(base._base_valuation, s*base._scale) return base, s
def __init__(self, expo, values, dop=None, check=True, mults=None): r""" TESTS:: sage: from ore_algebra import * sage: from ore_algebra.analytic.naive_sum import * sage: from ore_algebra.analytic.differential_operator import DifferentialOperator sage: Dops, x, Dx = DifferentialOperators() sage: LogSeriesInitialValues(0, {0: (1, 0)}, ....: DifferentialOperator(x*Dx^3 + 2*Dx^2 + x*Dx)) Traceback (most recent call last): ... ValueError: invalid initial data for x*Dx^3 + 2*Dx^2 + x*Dx at 0 """ try: self.expo = QQ.coerce(expo) except TypeError: try: self.expo = QQbar.coerce(expo) except TypeError: # symbolic; won't be sortable self.expo = expo if isinstance(values, dict): all_values = tuple( chain.from_iterable(ini if isinstance(ini, tuple) else (ini, ) for ini in values.values())) else: all_values = values values = dict((n, (values[n], )) for n in range(len(values))) self.universe = Sequence(all_values).universe() if not utilities.is_numeric_parent(self.universe): raise ValueError("initial values must coerce into a ball field") self.shift = {} if mults is not None: for s, m in mults: self.shift[s] = [self.universe.zero()] * m for k, ini in values.items(): if isinstance(k, tuple): # requires mult != None s, m = k s = int(s) self.shift[s][m] = self.universe(ini) else: s = int(k) self.shift[s] = tuple(self.universe(a) for a in ini) self.shift = {s: tuple(ini) for s, ini in self.shift.items()} try: if check and dop is not None and not self.is_valid_for(dop): raise ValueError( "invalid initial data for {} at 0".format(dop)) except TypeError: # coercion problems btw QQbar and number fields pass
def __classcall__(cls, generator): r""" Normalizes ``generator`` to a positive rational so that this is a unique parent. TESTS:: sage: sys.path.append(os.getcwd()); from mac_lane import * # optional: standalone sage: DiscreteValueGroup(1) is DiscreteValueGroup(-1) True """ generator = QQ.coerce(generator) generator = generator.abs() return super(DiscreteValueGroup, cls).__classcall__(cls, generator)
def __classcall__(cls, generator): r""" Normalizes ``generator`` to a positive rational so that this is a unique parent. TESTS:: sage: from sage.rings.valuation.value_group import DiscreteValueGroup sage: DiscreteValueGroup(1) is DiscreteValueGroup(-1) True """ generator = QQ.coerce(generator) generator = generator.abs() return super(DiscreteValueGroup, cls).__classcall__(cls, generator)
def __classcall__(cls, generator): r""" Normalizes ``generator`` to a positive rational so that this is a unique parent. TESTS:: sage: from sage.rings.valuation.value_group import DiscreteValueGroup sage: DiscreteValueGroup(1) is DiscreteValueGroup(-1) True """ generator = QQ.coerce(generator) generator = generator.abs() return super(DiscreteValueGroup, cls).__classcall__(cls, generator)
def some_elements(self): r""" Return some typical elements in this semigroup. EXAMPLES:: sage: from sage.rings.valuation.value_group import DiscreteValueSemigroup sage: list(DiscreteValueSemigroup([-3/8,1/2]).some_elements()) [0, -3/8, 1/2, ...] """ yield self(0) if self.is_trivial(): return for g in self._generators: yield g from sage.rings.all import ZZ for x in (ZZ**len(self._generators)).some_elements(): yield QQ.coerce(sum([abs(c)*g for c,g in zip(x,self._generators)]))
def some_elements(self): r""" Return some typical elements in this semigroup. EXAMPLES:: sage: from sage.rings.valuation.value_group import DiscreteValueSemigroup sage: list(DiscreteValueSemigroup([-3/8,1/2]).some_elements()) [0, -3/8, 1/2, ...] """ yield self(0) if self.is_trivial(): return for g in self._generators: yield g from sage.rings.all import ZZ for x in (ZZ**len(self._generators)).some_elements(): yield QQ.coerce(sum([abs(c)*g for c,g in zip(x,self._generators)]))
def some_elements(self): r""" Return some typical elements in this semigroup. EXAMPLES:: sage: sys.path.append(os.getcwd()); from mac_lane import * # optional: standalone sage: list(DiscreteValueSemigroup([-3/8,1/2]).some_elements()) [0, -3/8, 1/2, ...] """ yield self(0) if self.is_trivial(): return for g in self._generators: yield g from sage.rings.all import ZZ for x in (ZZ**len(self._generators)).some_elements(): yield QQ.coerce( sum([abs(c) * g for c, g in zip(x, self._generators)]))
def __classcall__(cls, generators): r""" Normalize ``generators``. TESTS: We do not find minimal generators or something like that but just sort the generators and drop generators that are trivially contained in the semigroup generated by the remaining generators:: sage: sys.path.append(os.getcwd()); from mac_lane import * # optional: standalone sage: DiscreteValueSemigroup([1,2]) is DiscreteValueSemigroup([1]) True In this case, the normalization is not sufficient to determine that these are the same semigroup:: sage: DiscreteValueSemigroup([1,-1,1/3]) is DiscreteValueSemigroup([1/3,-1/3]) False """ if generators in QQ: generators = [generators] generators = list(set([QQ.coerce(g) for g in generators if g != 0])) generators.sort() simplified_generators = generators # this is not very efficient but there should never be more than a # couple of generators for g in generators: for h in generators: if g == h: continue from sage.rings.all import NN if h / g in NN: simplified_generators.remove(h) break return super(DiscreteValueSemigroup, cls).__classcall__(cls, tuple(simplified_generators))
def __classcall__(cls, generators): r""" Normalize ``generators``. TESTS: We do not find minimal generators or something like that but just sort the generators and drop generators that are trivially contained in the semigroup generated by the remaining generators:: sage: from sage.rings.valuation.value_group import DiscreteValueSemigroup sage: DiscreteValueSemigroup([1,2]) is DiscreteValueSemigroup([1]) True In this case, the normalization is not sufficient to determine that these are the same semigroup:: sage: DiscreteValueSemigroup([1,-1,1/3]) is DiscreteValueSemigroup([1/3,-1/3]) False """ if generators in QQ: generators = [generators] generators = list(set([QQ.coerce(g) for g in generators if g != 0])) generators.sort() simplified_generators = generators # this is not very efficient but there should never be more than a # couple of generators for g in generators: for h in generators: if g == h: continue from sage.rings.all import NN if h/g in NN: simplified_generators.remove(h) break return super(DiscreteValueSemigroup, cls).__classcall__(cls, tuple(simplified_generators))
def _mul_(self, other, switch_sides=False): r""" Return the semigroup generated by ``other`` times the generators of this semigroup. INPUT: - ``other`` -- a rational number EXAMPLES:: sage: sys.path.append(os.getcwd()); from mac_lane import * # optional: standalone sage: D = DiscreteValueSemigroup(1/2) sage: 1/2 * D Additive Abelian Semigroup generated by 1/4 sage: D * (1/2) Additive Abelian Semigroup generated by 1/4 sage: D * 0 Trivial Additive Abelian Semigroup """ other = QQ.coerce(other) return DiscreteValueSemigroup([g * other for g in self._generators])
def _mul_(self, other, switch_sides=False): r""" Return the semigroup generated by ``other`` times the generators of this semigroup. INPUT: - ``other`` -- a rational number EXAMPLES:: sage: from sage.rings.valuation.value_group import DiscreteValueSemigroup sage: D = DiscreteValueSemigroup(1/2) sage: 1/2 * D Additive Abelian Semigroup generated by 1/4 sage: D * (1/2) Additive Abelian Semigroup generated by 1/4 sage: D * 0 Trivial Additive Abelian Semigroup """ other = QQ.coerce(other) return DiscreteValueSemigroup([g*other for g in self._generators])
def _mul_(self, other, switch_sides=False): r""" Return the semigroup generated by ``other`` times the generators of this semigroup. INPUT: - ``other`` -- a rational number EXAMPLES:: sage: from sage.rings.valuation.value_group import DiscreteValueSemigroup sage: D = DiscreteValueSemigroup(1/2) sage: 1/2 * D Additive Abelian Semigroup generated by 1/4 sage: D * (1/2) Additive Abelian Semigroup generated by 1/4 sage: D * 0 Trivial Additive Abelian Semigroup """ other = QQ.coerce(other) return DiscreteValueSemigroup([g*other for g in self._generators])
def __init__(self, point, dop=None): """ TESTS:: sage: from ore_algebra import * sage: from ore_algebra.analytic.path import Point sage: Dops, x, Dx = DifferentialOperators() sage: [Point(z, Dx) ....: for z in [1, 1/2, 1+I, QQbar(I), RIF(1/3), CIF(1/3), pi, ....: RDF(1), CDF(I), 0.5r, 0.5jr, 10r, QQbar(1), AA(1/3)]] [1, 1/2, I + 1, I, [0.333333333333333...], [0.333333333333333...], 3.141592653589794?, 1.000000000000000, 1.000000000000000*I, 0.5000000000000000, 0.5000000000000000*I, 10, 1, 1/3] sage: Point(sqrt(2), Dx).iv() [1.414...] """ SageObject.__init__(self) from sage.rings.complex_double import ComplexDoubleField_class from sage.rings.complex_field import ComplexField_class from sage.rings.complex_interval_field import ComplexIntervalField_class from sage.rings.real_double import RealDoubleField_class from sage.rings.real_mpfi import RealIntervalField_class from sage.rings.real_mpfr import RealField_class point = sage.structure.coerce.py_scalar_to_element(point) try: parent = point.parent() except AttributeError: raise TypeError("unexpected value for point: " + repr(point)) if isinstance(point, Point): self.value = point.value elif isinstance( parent, (number_field_base.NumberField, RealBallField, ComplexBallField)): self.value = point elif QQ.has_coerce_map_from(parent): self.value = QQ.coerce(point) # must come before QQbar, due to a bogus coerce map (#14485) elif parent is sage.symbolic.ring.SR: try: return self.__init__(point.pyobject(), dop) except TypeError: pass try: return self.__init__(QQbar(point), dop) except (TypeError, ValueError, NotImplementedError): pass try: self.value = RLF(point) except (TypeError, ValueError): self.value = CLF(point) elif QQbar.has_coerce_map_from(parent): alg = QQbar.coerce(point) NF, val, hom = alg.as_number_field_element() if NF is QQ: self.value = QQ.coerce(val) # parent may be ZZ else: embNF = number_field.NumberField(NF.polynomial(), NF.variable_name(), embedding=hom(NF.gen())) self.value = val.polynomial()(embNF.gen()) elif isinstance( parent, (RealField_class, RealDoubleField_class, RealIntervalField_class)): self.value = RealBallField(point.prec())(point) elif isinstance(parent, (ComplexField_class, ComplexDoubleField_class, ComplexIntervalField_class)): self.value = ComplexBallField(point.prec())(point) else: try: self.value = RLF.coerce(point) except TypeError: self.value = CLF.coerce(point) parent = self.value.parent() assert (isinstance( parent, (number_field_base.NumberField, RealBallField, ComplexBallField)) or parent is RLF or parent is CLF) self.dop = dop or point.dop self.keep_value = False
def __init__(self, point, dop=None, singular=None, **kwds): """ INPUT: - ``singular``: can be set to True to force this point to be considered a singular point, even if this cannot be checked (e.g. because we only have an enclosure) TESTS:: sage: from ore_algebra import * sage: from ore_algebra.analytic.path import Point sage: Dops, x, Dx = DifferentialOperators() sage: [Point(z, Dx) ....: for z in [1, 1/2, 1+I, QQbar(I), RIF(1/3), CIF(1/3), pi, ....: RDF(1), CDF(I), 0.5r, 0.5jr, 10r, QQbar(1), AA(1/3)]] [1, 1/2, I + 1, I, [0.333333333333333...], [0.333333333333333...], 3.141592653589794?, ~1.0000, ~1.0000*I, ~0.50000, ~0.50000*I, 10, 1, 1/3] sage: Point(sqrt(2), Dx).iv() [1.414...] sage: Point(RBF(0), (x-1)*x*Dx, singular=True).dist_to_sing() 1.000000000000000 """ SageObject.__init__(self) from sage.rings.complex_double import ComplexDoubleField_class from sage.rings.complex_field import ComplexField_class from sage.rings.complex_interval_field import ComplexIntervalField_class from sage.rings.real_double import RealDoubleField_class from sage.rings.real_mpfi import RealIntervalField_class from sage.rings.real_mpfr import RealField_class point = sage.structure.coerce.py_scalar_to_element(point) try: parent = point.parent() except AttributeError: raise TypeError("unexpected value for point: " + repr(point)) if isinstance(point, Point): self.value = point.value elif isinstance(parent, (RealBallField, ComplexBallField)): self.value = point elif isinstance(parent, number_field_base.NumberField): _, hom = good_number_field(point.parent()) self.value = hom(point) elif QQ.has_coerce_map_from(parent): self.value = QQ.coerce(point) elif QQbar.has_coerce_map_from(parent): alg = QQbar.coerce(point) NF, val, hom = alg.as_number_field_element() if NF is QQ: self.value = QQ.coerce(val) # parent may be ZZ else: embNF = number_field.NumberField(NF.polynomial(), NF.variable_name(), embedding=hom(NF.gen())) self.value = val.polynomial()(embNF.gen()) elif isinstance( parent, (RealField_class, RealDoubleField_class, RealIntervalField_class)): self.value = RealBallField(point.prec())(point) elif isinstance(parent, (ComplexField_class, ComplexDoubleField_class, ComplexIntervalField_class)): self.value = ComplexBallField(point.prec())(point) elif parent is sage.symbolic.ring.SR: try: return self.__init__(point.pyobject(), dop) except TypeError: pass try: return self.__init__(QQbar(point), dop) except (TypeError, ValueError, NotImplementedError): pass try: self.value = RLF(point) except (TypeError, ValueError): self.value = CLF(point) else: try: self.value = RLF.coerce(point) except TypeError: self.value = CLF.coerce(point) parent = self.value.parent() assert (isinstance( parent, (number_field_base.NumberField, RealBallField, ComplexBallField)) or parent is RLF or parent is CLF) if dop is None: # TBI if isinstance(point, Point): self.dop = point.dop else: self.dop = DifferentialOperator(dop.numerator()) self._force_singular = bool(singular) self.options = kwds