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 deformation_space(lengths): r""" Deformation space of the given ``lengths`` This is the smallest vector space defined over `\QQ` that contains the vector ``lengths``. Its dimension is `rank`. EXAMPLES:: sage: from surface_dynamics.misc.linalg import deformation_space sage: K.<sqrt2> = QuadraticField(2) sage: v3 = vector([sqrt2, 1, 1+sqrt2]) sage: deformation_space(v3) Vector space of degree 3 and dimension 2 over Rational Field Basis matrix: [1 0 1] [0 1 1] sage: v4 = vector([sqrt2, 1, 1+sqrt2, 1-sqrt2]) sage: deformation_space(v4) Vector space of degree 4 and dimension 2 over Rational Field Basis matrix: [ 1 0 1 -1] [ 0 1 1 1] sage: v = vector([1, 5, 2, 9]) sage: deformation_space(v) Vector space of degree 4 and dimension 1 over Rational Field Basis matrix: [1 5 2 9] The deformation space has some covariance relation with respect to matrix actions:: sage: m3 = matrix(3, [1,-1,0,2,-3,4,5,-2,2]) sage: deformation_space(v3 * m3) == deformation_space(v3) * m3 True sage: deformation_space(m3 * v3) == deformation_space(v3) * m3.transpose() True sage: m4 = matrix(4, [1,-1,0,1,2,-3,0,4,5,3,-2,2,1,1,1,1]) sage: deformation_space(v4 * m4) == deformation_space(v4) * m4 True sage: deformation_space(m4 * v4) == deformation_space(v4) * m4.transpose() True """ from sage.matrix.constructor import matrix try: m_lengths = matrix([u.vector() for u in lengths]) except AttributeError: from sage.rings.rational_field import QQ lengths = [QQ.coerce(i) for i in lengths] m_lengths = matrix([[i] for i in lengths]) return m_lengths.column_space()
def relation_space(v): r""" Relation space of the given vector ``v`` This is the sub vector space of `\QQ^d` given as the kernel of the map `n \mapsto n \cdot \lambda`. The dimension is `d - rank`. EXAMPLES:: sage: from surface_dynamics.misc.linalg import relation_space sage: K.<sqrt2> = QuadraticField(2) sage: v3 = vector([sqrt2, 1, 1+sqrt2]) sage: relation_space(v3) Vector space of degree 3 and dimension 1 over Rational Field Basis matrix: [ 1 1 -1] sage: v4 = vector([sqrt2, 1, 1+sqrt2, 1-sqrt2]) sage: relation_space(v4) Vector space of degree 4 and dimension 2 over Rational Field Basis matrix: [ 1 0 -1/2 1/2] [ 0 1 -1/2 -1/2] sage: v = vector([1,2,5,3]) sage: relation_space(v) Vector space of degree 4 and dimension 3 over Rational Field Basis matrix: [ 1 0 0 -1/3] [ 0 1 0 -2/3] [ 0 0 1 -5/3] The relation space has some covariance relation with respect to matrix actions:: sage: m3 = matrix(3, [1,-1,0,2,-3,4,5,-2,2]) sage: relation_space(v3 * m3) == relation_space(v3) * ~m3.transpose() True sage: relation_space(m3 * v3) == relation_space(v3) * ~m3 True sage: m4 = matrix(4, [1,-1,0,1,2,-3,0,4,5,3,-2,2,1,1,1,1]) sage: relation_space(v4 * m4) == relation_space(v4) * ~m4.transpose() True sage: relation_space(m4 * v4) == relation_space(v4) * ~m4 True """ from sage.matrix.constructor import matrix try: m_lengths = matrix([u.vector() for u in v]) except AttributeError: from sage.rings.rational_field import QQ v = [QQ.coerce(i) for i in v] m_lengths = matrix([[i] for i in v]) return m_lengths.left_kernel()
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.integer_ring 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: 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: 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])