def __init__(self, surface, m, ring=None): if surface.is_mutable(): if surface.is_finite(): self._s=surface.copy() else: raise ValueError("Can not apply matrix to mutable infinite surface.") else: self._s=surface det = m.determinant() if det>0: self._det_sign=1 elif det<0: self._det_sign=-1 else: raise ValueError("Can not apply matrix with zero determinant to surface.") self._m=m if ring is None: if m.base_ring() == self._s.base_ring(): base_ring = self._s.base_ring() else: from sage.structure.element import get_coercion_model cm = get_coercion_model() base_ring = cm.common_parent(m.base_ring(), self._s.base_ring()) else: base_ring=ring self._P = ConvexPolygons(base_ring) Surface.__init__(self, base_ring, self._s.base_label(), finite=self._s.is_finite())
def _eval_(self, n, x): """ EXAMPLES:: sage: y=var('y') sage: bessel_I(y,x) bessel_I(y, x) sage: bessel_I(0.0, 1.0) 1.26606587775201 sage: bessel_I(1/2, 1) sqrt(2)*sinh(1)/sqrt(pi) sage: bessel_I(-1/2, pi) sqrt(2)*cosh(pi)/pi """ if (not isinstance(n, Expression) and not isinstance(x, Expression) and (is_inexact(n) or is_inexact(x))): coercion_model = get_coercion_model() n, x = coercion_model.canonical_coercion(n, x) return self._evalf_(n, x, parent(n)) # special identities if n == Integer(1) / Integer(2): return sqrt(2 / (pi * x)) * sinh(x) elif n == -Integer(1) / Integer(2): return sqrt(2 / (pi * x)) * cosh(x) return None # leaves the expression unevaluated
def _eval_(self, n, m, theta, phi, **kwargs): r""" TESTS:: sage: x, y = var('x y') sage: spherical_harmonic(1, 2, x, y) 0 sage: spherical_harmonic(1, -2, x, y) 0 sage: spherical_harmonic(1/2, 2, x, y) spherical_harmonic(1/2, 2, x, y) sage: spherical_harmonic(3, 2, x, y) 15/4*sqrt(7/30)*cos(x)*e^(2*I*y)*sin(x)^2/sqrt(pi) sage: spherical_harmonic(3, 2, 1, 2) 15/4*sqrt(7/30)*cos(1)*e^(4*I)*sin(1)^2/sqrt(pi) sage: spherical_harmonic(3 + I, 2., 1, 2) -0.351154337307488 - 0.415562233975369*I """ from sage.structure.coerce import parent cc = get_coercion_model().canonical_coercion coerced = cc(phi, cc(theta, cc(n, m)[0])[0])[0] if is_inexact(coerced) and not isinstance(coerced, Expression): return self._evalf_(n, m, theta, phi, parent=parent(coerced)) elif n in ZZ and m in ZZ and n > -1: if abs(m) > n: return ZZ(0) return meval("spherical_harmonic({},{},{},{})".format(ZZ(n), ZZ(m), maxima(theta), maxima(phi))) return
def _evalf_(self, n, x, parent=None, algorithm=None): """ EXAMPLES:: sage: bessel_J(0.0, 1.0) 0.765197686557967 sage: bessel_J(0, 1).n(digits=20) 0.76519768655796655145 sage: bessel_J(0.5, 1.5) 0.649838074753747 Check for correct rounding (:trac:`17122`):: sage: R = RealField(113) sage: a = R("8.935761195587725798762818805462843676e-01") sage: aa = RealField(200)(a) sage: for n in [-10..10]: ....: b = bessel_J(R(n), a) ....: bb = R(bessel_J(n, aa)) ....: if b != bb: ....: print n, b-bb """ if parent is not None: x = parent(x) try: return x.jn(Integer(n)) except Exception: pass n, x = get_coercion_model().canonical_coercion(n, x) import mpmath return mpmath_utils.call(mpmath.besselj, n, x, parent=parent)
def weight_lattice_realization(self): r""" Return the weight lattice realization used to express weights. The weight lattice realization is the common parent which all weight lattice realizations of the crystals of ``self`` coerce into. EXAMPLES:: sage: LaZ = RootSystem(['A',2,1]).weight_lattice(extended=True).fundamental_weights() sage: LaQ = RootSystem(['A',2,1]).weight_space(extended=True).fundamental_weights() sage: B = crystals.LSPaths(LaQ[1]) sage: B.weight_lattice_realization() Extended weight space over the Rational Field of the Root system of type ['A', 2, 1] sage: C = crystals.AlcovePaths(LaZ[1]) sage: C.weight_lattice_realization() Extended weight lattice of the Root system of type ['A', 2, 1] sage: D = crystals.DirectSum([B,C]) sage: D.weight_lattice_realization() Extended weight space over the Rational Field of the Root system of type ['A', 2, 1] """ cm = get_coercion_model() return cm.common_parent(*[crystal.weight_lattice_realization() for crystal in self.crystals])
def __mul__(self, right): r""" Product of two elements INPUT: - ``self``, ``right`` -- two elements This calls the `_mul_` method of ``self``, if it is available and the two elements have the same parent. Otherwise, the job is delegated to the coercion model. Do not override; instead implement a ``_mul_`` method in the element class or a ``product`` method in the parent class. EXAMPLES:: sage: S = Semigroups().example("free") sage: x = S('a'); y = S('b') sage: x * y 'ab' """ if have_same_parent(self, right) and hasattr(self, "_mul_"): return self._mul_(right) from sage.structure.element import get_coercion_model import operator return get_coercion_model().bin_op(self, right, operator.mul)
def _eval_(self, n, m, theta, phi, **kwargs): r""" TESTS:: sage: x, y = var('x y') sage: spherical_harmonic(1, 2, x, y) 0 sage: spherical_harmonic(1, -2, x, y) 0 sage: spherical_harmonic(1/2, 2, x, y) spherical_harmonic(1/2, 2, x, y) sage: spherical_harmonic(3, 2, x, y) 15/4*sqrt(7/30)*cos(x)*e^(2*I*y)*sin(x)^2/sqrt(pi) sage: spherical_harmonic(3, 2, 1, 2) 15/4*sqrt(7/30)*cos(1)*e^(4*I)*sin(1)^2/sqrt(pi) sage: spherical_harmonic(3 + I, 2., 1, 2) -0.351154337307488 - 0.415562233975369*I """ from sage.structure.coerce import parent cc = get_coercion_model().canonical_coercion coerced = cc(phi, cc(theta, cc(n, m)[0])[0])[0] if is_inexact(coerced) and not isinstance(coerced, Expression): return self._evalf_(n, m, theta, phi, parent=parent(coerced)) elif n in ZZ and m in ZZ and n > -1: if abs(m) > n: return ZZ(0) return meval("spherical_harmonic({},{},{},{})".format( ZZ(n), ZZ(m), maxima(theta), maxima(phi))) return
def _evalf_try_(self, a, b, z): """ Call :meth:`_evalf_` if one of the arguments is numerical and none of the arguments are symbolic. OUTPUT: - ``None`` if we didn't succeed to call :meth:`_evalf_` or if the input wasn't suitable for it. - otherwise, a numerical value for the function. EXAMPLES:: sage: hypergeometric._evalf_try_((1.0,), (2.0,), 3.0) 6.36184564106256 sage: hypergeometric._evalf_try_((1.0, 1), (), 3.0) -0.0377593153441588 + 0.750349833788561*I sage: hypergeometric._evalf_try_((1, 1), (), 3) # exact input sage: hypergeometric._evalf_try_((x,), (), 1.0) # symbolic sage: hypergeometric._evalf_try_(1.0, 2.0, 3.0) # not tuples """ # We need to override this for hypergeometric functions since # the first 2 arguments are tuples and the generic _evalf_try_ # cannot handle that. if not isinstance(a,tuple) or not isinstance(b,tuple): return None args = list(a) + list(b) + [z] if any(self._is_numerical(x) for x in args): if not any(isinstance(x, Expression) for x in args): p = get_coercion_model().common_parent(*args) return self._evalf_(a, b, z, parent=p)
def __eq__(self, other): """ Check equality. TESTS:: sage: R.<x,y,z> = QQ[] sage: W = DifferentialWeylAlgebra(R) sage: dx,dy,dz = W.differentials() sage: dy*(x^3-y*z)*dx == -z*dx + x^3*dx*dy - y*z*dx*dy True sage: W.zero() == 0 True sage: W.one() == 1 True sage: x == 1 False sage: x + 1 == 1 False sage: W(x^3 - y*z) == x^3 - y*z True """ if have_same_parent(self, other): return self.__monomials == other.__monomials try: return get_coercion_model().bin_op(self, other, operator.eq) except TypeError: return False
def direct_sum(self, other): """ Return the direct sum. INPUT: - ``other`` -- a filtered vector space. OUTPUT: The direct sum as a filtered vector space. EXAMPLES:: sage: V = FilteredVectorSpace(2, 0) sage: W = FilteredVectorSpace({0:[(1,-1),(2,1)], 1:[(1,1)]}) sage: V.direct_sum(W) QQ^4 >= QQ^1 >= 0 sage: V + W # syntactic sugar QQ^4 >= QQ^1 >= 0 sage: V + V == FilteredVectorSpace(4, 0) True sage: W = FilteredVectorSpace([(1,-1),(2,1)], {1:[0,1], 2:[1]}) sage: V + W QQ^4 >= QQ^2 >= QQ^1 >= 0 A suitable base ring is chosen if they do not match:: sage: v = [(1,0), (0,1)] sage: F1 = FilteredVectorSpace(v, {0:[0], 1:[1]}, base_ring=QQ) sage: F2 = FilteredVectorSpace(v, {0:[0], 1:[1]}, base_ring=RDF) sage: F1 + F2 RDF^4 >= RDF^2 >= 0 """ from sage.structure.element import get_coercion_model base_ring = get_coercion_model().common_parent(self.base_ring(), other.base_ring()) # construct the generators self_gens, self_filt = self.presentation() other_gens, other_filt = other.presentation() generators = \ [ list(v) + [base_ring.zero()]*other.dimension() for v in self_gens ] + \ [ [base_ring.zero()]*self.dimension() + list(v) for v in other_gens ] # construct the filtration dictionary def join_indices(self_indices, other_indices): self_indices = tuple(self_indices) other_indices = tuple(i + len(self_gens) for i in other_indices) return self_indices + other_indices filtration = dict() self_indices = set() other_indices = set() for deg in reversed(uniq(self_filt.keys() + other_filt.keys())): self_indices.update(self_filt.get(deg, [])) other_indices.update(other_filt.get(deg, [])) gens = join_indices(self_indices, other_indices) filtration[deg] = gens return FilteredVectorSpace(generators, filtration, base_ring=base_ring)
def __init__(self, surface, m, ring=None): if surface.is_mutable(): if surface.is_finite(): self._s=surface.copy() else: raise ValueError("Can not apply matrix to mutable infinite surface.") else: self._s=surface det = m.determinant() if det>0: self._det_sign=1 elif det<0: self._det_sign=-1 else: raise ValueError("Can not apply matrix with zero determinant to surface.") self._m=m if ring is None: if m.base_ring() == self._s.base_ring(): base_ring = self._s.base_ring() else: from sage.structure.element import get_coercion_model cm = get_coercion_model() base_ring = cm.common_parent(m.base_ring(), self._s.base_ring()) else: base_ring=ring self._P=Polygons(base_ring) Surface.__init__(self, base_ring, self._s.base_label(), finite=self._s.is_finite())
def tensor_product(self, other): r""" Return the graded tensor product. INPUT: - ``other`` -- a filtered vector space. OUTPUT: The graded tensor product, that is, the tensor product of a generator of degree `d_1` with a generator in degree `d_2` has degree `d_1 + d_2`. EXAMPLES:: sage: F1 = FilteredVectorSpace(1, 1) sage: F2 = FilteredVectorSpace(1, 2) sage: F1.tensor_product(F2) QQ^1 >= 0 sage: F1 * F2 QQ^1 >= 0 sage: F1.min_degree() 1 sage: F2.min_degree() 2 sage: (F1*F2).min_degree() 3 A suitable base ring is chosen if they do not match:: sage: v = [(1,0), (0,1)] sage: F1 = FilteredVectorSpace(v, {0:[0], 1:[1]}, base_ring=QQ) sage: F2 = FilteredVectorSpace(v, {0:[0], 1:[1]}, base_ring=RDF) sage: F1 * F2 RDF^4 >= RDF^3 >= RDF^1 >= 0 """ V = self W = other from sage.structure.element import get_coercion_model base_ring = get_coercion_model().common_parent(V.base_ring(), W.base_ring()) from sage.modules.tensor_operations import VectorCollection, TensorOperation V_generators, V_indices = V.presentation() W_generators, W_indices = W.presentation() V_coll = VectorCollection(V_generators, base_ring, V.dimension()) W_coll = VectorCollection(W_generators, base_ring, W.dimension()) T = TensorOperation([V_coll, W_coll], 'product') filtration = dict() for V_deg in V.support(): for W_deg in W.support(): deg = V_deg + W_deg indices = filtration.get(deg, set()) for i in V_indices[V_deg]: for j in W_indices[W_deg]: i_tensor_j = T.index_map(i, j) indices.add(i_tensor_j) filtration[deg] = indices return FilteredVectorSpace(T.vectors(), filtration, base_ring=base_ring)
def __add__(self, other): """ Return the sum of two subgroups. EXAMPLES:: sage: C = J0(22).cuspidal_subgroup() sage: C.gens() [[(1/5, 1/5, 4/5, 0)], [(0, 0, 0, 1/5)]] sage: A = C.subgroup([C.0]); B = C.subgroup([C.1]) sage: A + B == C True """ if not isinstance(other, FiniteSubgroup): raise TypeError("only addition of two finite subgroups is defined") A = self.abelian_variety() B = other.abelian_variety() if not A.in_same_ambient_variety(B): raise ValueError( "self and other must be in the same ambient Jacobian") K = get_coercion_model().common_parent(self.field_of_definition(), other.field_of_definition()) lattice = self.lattice() + other.lattice() if A != B: lattice += C.lattice() return FiniteSubgroup_lattice(self.abelian_variety(), lattice, field_of_definition=K)
def _evalf_(self, n, x, parent=None, algorithm=None): """ EXAMPLES:: sage: bessel_Y(0.5, 1.5) -0.0460831658930974 sage: bessel_Y(1.0+2*I, 3.0+4*I) 0.699410324467538 + 0.228917940896421*I sage: bessel_Y(0, 1).n(256) 0.08825696421567695798292676602351516282781752309067554671104384761199978932351 Check for correct rounding (:trac:`17122`):: sage: R = RealField(113) sage: a = R("8.935761195587725798762818805462843676e-01") sage: aa = RealField(200)(a) sage: for n in [-10..10]: ....: b = bessel_Y(R(n), a) ....: bb = R(bessel_Y(n, aa)) ....: if b != bb: ....: print n, b-bb """ if parent is not None: x = parent(x) try: return x.yn(Integer(n)) except Exception: pass n, x = get_coercion_model().canonical_coercion(n, x) import mpmath return mpmath_utils.call(mpmath.bessely, n, x, parent=parent)
def _evalf_try_(self, a, b, z): """ Call :meth:`_evalf_` if one of the arguments is numerical and none of the arguments are symbolic. OUTPUT: - ``None`` if we didn't succeed to call :meth:`_evalf_` or if the input wasn't suitable for it. - otherwise, a numerical value for the function. EXAMPLES:: sage: hypergeometric._evalf_try_((1.0,), (2.0,), 3.0) 6.36184564106256 sage: hypergeometric._evalf_try_((1.0, 1), (), 3.0) -0.0377593153441588 + 0.750349833788561*I sage: hypergeometric._evalf_try_((1, 1), (), 3) # exact input sage: hypergeometric._evalf_try_((x,), (), 1.0) # symbolic sage: hypergeometric._evalf_try_(1.0, 2.0, 3.0) # not tuples """ # We need to override this for hypergeometric functions since # the first 2 arguments are tuples and the generic _evalf_try_ # cannot handle that. if not isinstance(a, tuple) or not isinstance(b, tuple): return None args = list(a) + list(b) + [z] if any(self._is_numerical(x) for x in args): if not any(isinstance(x, Expression) for x in args): p = get_coercion_model().common_parent(*args) return self._evalf_(a, b, z, parent=p)
def __add__(self, other): """ Return the sum of two subgroups. EXAMPLES:: sage: C = J0(22).cuspidal_subgroup() sage: C.gens() [[(1/5, 1/5, 4/5, 0)], [(0, 0, 0, 1/5)]] sage: A = C.subgroup([C.0]); B = C.subgroup([C.1]) sage: A + B == C True """ if not isinstance(other, FiniteSubgroup): raise TypeError("only addition of two finite subgroups is defined") A = self.abelian_variety() B = other.abelian_variety() if not A.in_same_ambient_variety(B): raise ValueError("self and other must be in the same ambient Jacobian") K = get_coercion_model().common_parent(self.field_of_definition(), other.field_of_definition()) lattice = self.lattice() + other.lattice() if A != B: lattice += C.lattice() return FiniteSubgroup_lattice(self.abelian_variety(), lattice, field_of_definition=K)
def weight_lattice_realization(self): r""" Return the weight lattice realization used to express weights. The weight lattice realization is the common parent which all weight lattice realizations of the crystals of ``self`` coerce into. EXAMPLES:: sage: LaZ = RootSystem(['A',2,1]).weight_lattice(extended=True).fundamental_weights() sage: LaQ = RootSystem(['A',2,1]).weight_space(extended=True).fundamental_weights() sage: B = crystals.LSPaths(LaQ[1]) sage: B.weight_lattice_realization() Extended weight space over the Rational Field of the Root system of type ['A', 2, 1] sage: C = crystals.AlcovePaths(LaZ[1]) sage: C.weight_lattice_realization() Extended weight lattice of the Root system of type ['A', 2, 1] sage: D = crystals.DirectSum([B,C]) sage: D.weight_lattice_realization() Extended weight space over the Rational Field of the Root system of type ['A', 2, 1] """ cm = get_coercion_model() return cm.common_parent(*[ crystal.weight_lattice_realization() for crystal in self.crystals ])
def apply_matrix(self, m, in_place=True, mapping=False): r""" Carry out the GL(2,R) action of m on this surface and return the result. If in_place=True, then this is done in place and changes the surface. This can only be carried out if the surface is finite and mutable. If mapping=True, then we return a GL2RMapping between this surface and its image. In this case in_place must be False. If in_place=False, then a copy is made before the deformation. """ if mapping == True: assert in_place == False, "Can not modify in place and return a mapping." return GL2RMapping(self, m) if not in_place: if self.is_finite(): from sage.structure.element import get_coercion_model cm = get_coercion_model() field = cm.common_parent(self.base_ring(), m.base_ring()) s = self.copy(mutable=True, new_field=field) return s.apply_matrix(m) else: return m * self else: # Make sure m is in the right state from sage.matrix.constructor import Matrix m = Matrix(self.base_ring(), 2, 2, m) assert m.det() != self.base_ring().zero( ), "Can not deform by degenerate matrix." assert self.is_finite( ), "In place GL(2,R) action only works for finite surfaces." us = self.underlying_surface() assert us.is_mutable( ), "In place changes only work for mutable surfaces." for label in self.label_iterator(): us.change_polygon(label, m * self.polygon(label)) if m.det() < self.base_ring().zero(): # Polygons were all reversed orientation. Need to redo gluings. # First pass record new gluings in a dictionary. new_glue = {} seen_labels = set() for p1 in self.label_iterator(): n1 = self.polygon(p1).num_edges() for e1 in range(n1): p2, e2 = self.opposite_edge(p1, e1) n2 = self.polygon(p2).num_edges() if p2 in seen_labels: pass elif p1 == p2 and e1 > e2: pass else: new_glue[(p1, n1 - 1 - e1)] = (p2, n2 - 1 - e2) seen_labels.add(p1) # Second pass: reassign gluings for (p1, e1), (p2, e2) in iteritems(new_glue): us.change_edge_gluing(p1, e1, p2, e2) return self
def __truediv__(left, right): """ Return the result of the division of ``left`` by ``right``, if possible. This top-level implementation delegates the work to the ``_div_`` method if ``left`` and ``right`` have the same parent and to coercion otherwise. See the extensive documentation at the top of :ref:`sage.structure.element`. .. SEEALSO:: :meth:`_div_` EXAMPLES:: sage: G = FreeGroup(2) sage: x0, x1 = G.group_generators() sage: c1 = cartesian_product([x0, x1]) sage: c2 = cartesian_product([x1, x0]) sage: c1.__div__(c2) (x0*x1^-1, x1*x0^-1) sage: c1 / c2 (x0*x1^-1, x1*x0^-1) Division supports coercion:: sage: C = cartesian_product([G, G]) sage: H = Hom(G, C) sage: phi = H(lambda g: cartesian_product([g, g])) sage: phi.register_as_coercion() sage: x1 / c1 (x1*x0^-1, 1) sage: c1 / x1 (x0*x1^-1, 1) Depending on how the division itself is implemented in :meth:`_div_`, division may fail even when ``right`` actually divides ``left``:: sage: x = cartesian_product([2, 1]) sage: y = cartesian_product([1, 1]) sage: x / y (2, 1) sage: x / x Traceback (most recent call last): ... TypeError: no conversion of this rational to integer TESTS:: sage: c1.__div__.__module__ 'sage.categories.magmas' """ from sage.structure.element import have_same_parent if have_same_parent(left, right): return left._div_(right) from sage.structure.element import get_coercion_model import operator return get_coercion_model().bin_op(left, right, operator.div)
def cup_product(self, cochain): """ Return the cup product with another cochain INPUT: - ``cochain`` -- cochain over the same cell complex EXAMPLES:: sage: T2 = simplicial_complexes.Torus() sage: C1 = T2.n_chains(1, base_ring=ZZ, cochains=True) sage: def l(i, j): ....: return C1(Simplex([i, j])) sage: l1 = l(1, 3) + l(1, 4) + l(1, 6) + l(2, 4) - l(4, 5) + l(5, 6) sage: l2 = l(1, 6) - l(2, 3) - l(2, 5) + l(3, 6) - l(4, 5) + l(5, 6) The two one-cocycles are cohomology generators:: sage: l1.is_cocycle(), l1.is_coboundary() (True, False) sage: l2.is_cocycle(), l2.is_coboundary() (True, False) Their cup product is a two-cocycle that is again non-trivial in cohomology:: sage: l12 = l1.cup_product(l2) sage: l12 \chi_(1, 3, 6) - \chi_(2, 4, 5) - \chi_(4, 5, 6) sage: l1.parent().degree(), l2.parent().degree(), l12.parent().degree() (1, 1, 2) sage: l12.is_cocycle(), l12.is_coboundary() (True, False) """ if not isinstance(cochain.parent(), Cochains): raise ValueError('argument must be a cochain') if cochain.parent().cell_complex() != self.parent().cell_complex(): raise ValueError('cochain must be over the same cell complex') left_deg = self.parent().degree() right_deg = cochain.parent().degree() left_chains = self.parent().dual() right_chains = cochain.parent().dual() base_ring = get_coercion_model().common_parent( left_chains.base_ring(), right_chains.base_ring()) cx = self.parent().cell_complex() codomain = cx.n_chains( left_deg + right_deg, base_ring=base_ring, cochains=True) accumulator = codomain.zero() for cell in codomain.indices(): for (coeff, left_cell, right_cell) in cx.alexander_whitney(cell, left_deg): if not coeff: continue left = left_chains(left_cell) right = right_chains(right_cell) accumulator += codomain(cell) * coeff * self.eval(left) * cochain.eval(right) return accumulator
def __eq__(self, other): r""" Return if this growth element is equal to ``other``. INPUT: - ``other`` -- an element. OUTPUT: A boolean. .. NOTE:: This function uses the coercion model to find a common parent for the two operands. The comparison of two elements with the same parent is done in :meth:`_eq_`. EXAMPLES:: sage: import sage.rings.asymptotic.growth_group as agg sage: G = agg.GenericGrowthGroup(ZZ) sage: G.an_element() == G.an_element() True sage: G(raw_element=42) == G(raw_element=7) False :: sage: G_ZZ = agg.GenericGrowthGroup(ZZ) sage: G_QQ = agg.GenericGrowthGroup(QQ) sage: G_ZZ(raw_element=1) == G_QQ(raw_element=1) True :: sage: P_ZZ = agg.MonomialGrowthGroup(ZZ, 'x') sage: P_QQ = agg.MonomialGrowthGroup(QQ, 'x') sage: P_ZZ.gen() == P_QQ.gen() True sage: ~P_ZZ.gen() == P_ZZ.gen() False sage: ~P_ZZ(1) == P_ZZ(1) True """ from sage.structure.element import have_same_parent if have_same_parent(self, other): return self._eq_(other) from sage.structure.element import get_coercion_model import operator try: return get_coercion_model().bin_op(self, other, operator.eq) except TypeError: return False
def apply_matrix(self,m,in_place=True, mapping=False): r""" Carry out the GL(2,R) action of m on this surface and return the result. If in_place=True, then this is done in place and changes the surface. This can only be carried out if the surface is finite and mutable. If mapping=True, then we return a GL2RMapping between this surface and its image. In this case in_place must be False. If in_place=False, then a copy is made before the deformation. """ if mapping==True: assert in_place==False, "Can not modify in place and return a mapping." return GL2RMapping(self, m) if not in_place: if self.is_finite(): from sage.structure.element import get_coercion_model cm = get_coercion_model() field = cm.common_parent(self.base_ring(), m.base_ring()) s=self.copy(mutable=True, new_field=field) return s.apply_matrix(m) else: return m*self else: # Make sure m is in the right state from sage.matrix.constructor import Matrix m=Matrix(self.base_ring(), 2, 2, m) assert m.det()!=self.base_ring().zero(), "Can not deform by degenerate matrix." assert self.is_finite(), "In place GL(2,R) action only works for finite surfaces." us=self.underlying_surface() assert us.is_mutable(), "In place changes only work for mutable surfaces." for label in self.label_iterator(): us.change_polygon(label,m*self.polygon(label)) if m.det()<self.base_ring().zero(): # Polygons were all reversed orientation. Need to redo gluings. # First pass record new gluings in a dictionary. new_glue={} seen_labels=set() for p1 in self.label_iterator(): n1=self.polygon(p1).num_edges() for e1 in xrange(n1): p2,e2=self.opposite_edge(p1,e1) n2=self.polygon(p2).num_edges() if p2 in seen_labels: pass elif p1==p2 and e1>e2: pass else: new_glue[(p1, n1-1-e1)]=(p2, n2-1-e2) seen_labels.add(p1) # Second pass: reassign gluings for (p1,e1),(p2,e2) in new_glue.iteritems(): us.change_edge_gluing(p1,e1,p2,e2) return self
def __mul__(self,other): parent = self.parent() if isinstance(other,Matrix_inexact) and parent.base_ring() is other.parent().base_ring(): group = self.group() if other.group() != group: raise TypeError("Can multiply only two matrices in the same group") return self._matrix_times_matrix_(other) else: from sage.structure.element import get_coercion_model return get_coercion_model().bin_op(self,other,mul)
def __mul__(self,other): parent = self.parent() if parent == other.parent(): group = self.group() if other.group() != group: raise GroupError("Can multiply only two elements in the same group") return self._mul_(other) else: from sage.structure.element import get_coercion_model return get_coercion_model().bin_op(self,other,mul)
def __eq__(left, right): if not have_same_parent(left, right): from sage.structure.element import get_coercion_model try: return get_coercion_model().bin_op(left, right, operator.eq) except TypeError: return False else: left, right = left.reduce(), right.reduce() return super(SteenrodAlgebraBase.Element, left).__eq__(right)
def eval(self, other): """ Evaluate this cochain on the chain ``other``. INPUT: - ``other`` -- a chain for the same cell complex in the same dimension with the same base ring OUTPUT: scalar EXAMPLES:: sage: S2 = simplicial_complexes.Sphere(2) sage: C_2 = S2.n_chains(1) sage: C_2_co = S2.n_chains(1, cochains=True) sage: x = C_2.basis()[Simplex((0,2))] sage: y = C_2.basis()[Simplex((1,3))] sage: z = x+2*y sage: a = C_2_co.basis()[Simplex((1,3))] sage: b = C_2_co.basis()[Simplex((0,3))] sage: c = 3*a-2*b sage: z (0, 2) + 2*(1, 3) sage: c -2*\chi_(0, 3) + 3*\chi_(1, 3) sage: c.eval(z) 6 TESTS:: sage: z.eval(c) # z is not a cochain Traceback (most recent call last): ... AttributeError: 'Chains_with_category.element_class' object has no attribute 'eval' sage: c.eval(c) # can't evaluate a cochain on a cochain Traceback (most recent call last): ... ValueError: argument is not a chain """ if not isinstance(other.parent(), Chains): raise ValueError('argument is not a chain') if other.parent().indices() != self.parent().indices(): raise ValueError('the cells are not compatible') result = sum(coeff * other.coefficient(cell) for cell, coeff in self) R = self.base_ring() if R != other.base_ring(): cm = get_coercion_model() R = cm.common_parent(R, other.base_ring()) return R(result)
def __rmul__(right, left): """ TESTS:: sage: F = CombinatorialFreeModule(QQ, ["a", "b"]) sage: x = F.monomial("a") sage: int(2) * x 2*B['a'] TODO: make a better unit test once Modules().example() is implemented """ from sage.structure.element import get_coercion_model import operator return get_coercion_model().bin_op(left, right, operator.mul)
def tangent_vector(self, lab, p, v, ring=None): r""" Return a tangent vector. INPUT: - ``lab`` -- label of a polygon - ``p`` -- coordinates of a point in the polygon - ``v`` -- coordinates of a vector in R^2 EXAMPLES:: sage: from flatsurf.geometry.chamanara import chamanara_surface sage: S = chamanara_surface(1/2) sage: S.tangent_vector(S.base_label(), (1/2,1/2), (1,1)) SimilaritySurfaceTangentVector in polygon (1, [-1 0] [ 0 -1]) based at (1/2, -3/2) with vector (1, 1) sage: K.<sqrt2> = QuadraticField(2) sage: S.tangent_vector(S.base_label(), (1/2,1/2), (1,sqrt2)) SimilaritySurfaceTangentVector in polygon (1, [-1 0] [ 0 -1]) based at (1/2, -3/2) with vector (1, sqrt2) """ p = vector(p) v = vector(v) if p.parent().dimension() != 2 or v.parent().dimension() != 2: raise ValueError("p (={!r}) and v (={!v}) should have two coordinates") if ring is None: R = p.base_ring() if R != v.base_ring(): from sage.structure.element import get_coercion_model cm = get_coercion_model() R = cm.common_parent(R, v.base_ring()) p = p.change_ring(R) v = v.change_ring(R) R2 = self.base_ring() if R != R2: if R2.has_coerce_map_from(R): p = p.change_ring(R2) v = v.change_ring(R2) R = R2 elif not R.has_coerce_map_from(R2): raise ValueError("not able to find a common ring for arguments") return self.tangent_bundle(R)(lab, p, v) else: return self.tangent_bundle(ring)(lab, p, v)
def __init__(self, surface, m, ring=None): self._s=surface if m.determinant()<=0: raise ValueError("Currently only works with matrices of positive determinant.""") self._m=m if ring is None: if m.base_ring() == self._s.base_ring(): self._base_ring = self._s.base_ring() else: from sage.structure.element import get_coercion_model cm = get_coercion_model() self._base_ring = cm.common_parent(m.base_ring(), self._s.base_ring()) else: self._base_ring=ring self._P=Polygons(self._base_ring)
def __init__(self, domain_intervals, directed_move, parent=None): function = fast_linear_function(directed_move[0], directed_move[1]) pieces = [(interval, function) for interval in domain_intervals] self._piecewise = piecewise = PiecewiseLinearFunction_1d(pieces) self.directed_move = tuple(directed_move) if parent is None: from sage.structure.element import get_coercion_model from sage.categories.rings import Rings cm = get_coercion_model() domain = cm.common_parent(directed_move[1], *piecewise.end_points()) if domain in Rings(): domain = domain.fraction_field() parent = FullMoveSemigroup(domain) super(FunctionalDirectedMove, self).__init__(parent)
def __mul__(self, right): """ EXAMPLES:: sage: s = SFASchur(QQ) sage: a = s([2]) sage: a._mul_(a) #indirect doctest s[2, 2] + s[3, 1] + s[4] Todo: use AlgebrasWithBasis(QQ).example() """ if have_same_parent(self, right) and hasattr(self, "_mul_"): return self._mul_(right) from sage.structure.element import get_coercion_model import operator return get_coercion_model().bin_op(self, right, operator.mul)
def __disabled_cmp__(left, right): if not have_same_parent(left, right): from sage.structure.element import get_coercion_model try: return get_coercion_model().bin_op(left, right, cmp) except TypeError: return -1 else: print( ( type(left._monomial_coefficients), type(right._monomial_coefficients), ) ) left, right = left.reduce(), right.reduce() return super(SteenrodAlgebraBase.Element, left).__cmp__(right)
def __radd__(self, left): r""" Handles the sum of two elements, when the left hand side needs to be coerced first. EXAMPLES:: sage: F = CommutativeAdditiveSemigroups().example() sage: (a,b,c,d) = F.additive_semigroup_generators() sage: a.__radd__(b) a + b """ if have_same_parent(left, self) and hasattr(left, "_add_"): return left._add_(self) from sage.structure.element import get_coercion_model import operator return get_coercion_model().bin_op(left, self, operator.add)
def _eval_(self, n, x): """ EXAMPLES:: sage: a, b = var('a, b') sage: bessel_J(a, b) bessel_J(a, b) sage: bessel_J(1.0, 1.0) 0.440050585744933 """ if (not isinstance(n, Expression) and not isinstance(x, Expression) and (is_inexact(n) or is_inexact(x))): coercion_model = get_coercion_model() n, x = coercion_model.canonical_coercion(n, x) return self._evalf_(n, x, parent(n)) return None
def _eval_(self, n, x): """ EXAMPLES:: sage: a,b = var('a, b') sage: bessel_Y(a, b) bessel_Y(a, b) sage: bessel_Y(0, 1).n(128) 0.088256964215676957982926766023515162828 """ if (not isinstance(n, Expression) and not isinstance(x, Expression) and (is_inexact(n) or is_inexact(x))): coercion_model = get_coercion_model() n, x = coercion_model.canonical_coercion(n, x) return self._evalf_(n, x, parent(n)) return None # leaves the expression unevaluated
def __sub__(left, right): """ Top-level subtraction operator See extensive documentation at the top of element.pyx. EXAMPLES:: sage: F = CombinatorialFreeModule(QQ, ['a','b']) sage: a,b = F.basis() sage: a - b B['a'] - B['b'] """ if have_same_parent(left, right) and hasattr(left, "_sub_"): return left._sub_(right) from sage.structure.element import get_coercion_model import operator return get_coercion_model().bin_op(left, right, operator.sub)
def _act_on_(self, x, self_on_left): """ Return the action of ``self`` on ``x`` by seeing if there is an action of the defining Lie algebra. EXAMPLES:: sage: L = lie_algebras.VirasoroAlgebra(QQ) sage: d = L.basis() sage: x = d[-1]*d[-2]*d[-1] + 3*d[-3] sage: x PBW[-2]*PBW[-1]^2 + PBW[-3]*PBW[-1] + 3*PBW[-3] sage: M = L.verma_module(1/2,3/4) sage: v = M.highest_weight_vector() sage: x * v 3*d[-3]*v + d[-3]*d[-1]*v + d[-2]*d[-1]*d[-1]*v """ # Try the _acted_upon_ first as it might have a direct PBW action # implemented that is faster ret = x._acted_upon_(self, not self_on_left) if ret is not None: return ret cm = get_coercion_model() L = self.parent()._g if self_on_left: if cm.discover_action(L, x.parent(), mul): ret = x.parent().zero() for mon, coeff in self._monomial_coefficients.items(): term = coeff * x for k, exp in reversed(mon._sorted_items()): for _ in range(exp): term = L.monomial(k) * term ret += term return ret else: if cm.discover_action(x.parent(), L, mul): ret = x.parent().zero() for mon, coeff in self._monomial_coefficients.items(): term = coeff * x for k, exp in reversed(mon._sorted_items()): for _ in range(exp): term = term * L.monomial(k) ret += term return ret return None
def _eval_(self, a, b, z, **kwargs): """ EXAMPLES:: sage: hypergeometric([], [], 0) 1 """ if not isinstance(a,tuple) or not isinstance(b,tuple): raise ValueError('First two parameters must be of type list.') coercion_model = get_coercion_model() co = reduce(lambda x, y: coercion_model.canonical_coercion(x, y)[0], a + b + (z,)) if is_inexact(co) and not isinstance(co, Expression): from sage.structure.coerce import parent return self._evalf_(a, b, z, parent=parent(co)) if not isinstance(z, Expression) and z == 0: # Expression is excluded return Integer(1) # to avoid call to Maxima return
def __classcall_private__(cls, k, q1, q2, q3, base_ring=None, prefix='B'): r""" Normalize input to ensure a unique representation. TESTS:: sage: R.<q,r,s> = ZZ[] sage: B3 = algebras.Blob(3, q, r, s) sage: Bp = algebras.Blob(3, q, r, s, R, prefix='B') sage: B3 is Bp True """ if base_ring is None: base_ring = get_coercion_model().common_parent(q1, q2, q3) q1 = base_ring(q1) q2 = base_ring(q2) q3 = base_ring(q3) return super(BlobAlgebra, cls).__classcall__(cls, k, q1, q2, q3, base_ring, prefix)
def __eq__(self, other): r""" Equality test. EXAMPLES:: sage: UCF = UniversalCyclotomicField() sage: UCF.one() == 1 True sage: 1 == UCF.one() True sage: UCF(2/3) == 2/3 True sage: 2/3 == UCF(2/3) True sage: UCF.gen(3) == UCF.gen(5) False sage: UCF.gen(5) + UCF.gen(3) == UCF.gen(3) + UCF.gen(5) True sage: UCF.zero() == None False sage: QQbar.zeta(5) == UCF.gen(5) True sage: UCF.gen(5) == QQbar.zeta(5) True sage: QQbar.zeta(5) == UCF.gen(5,2) False sage: UCF.gen(5,2) == QQbar.zeta(5) False """ if parent(self) is not parent(other): from sage.structure.element import get_coercion_model cm = get_coercion_model() try: self, other = cm.canonical_coercion(self, other) except TypeError: return False return self == other return self._obj == other._obj
def weight_ring(self): """ Returns the weight ring for this species. This is determined by asking Sage's coercion model what the result is when you multiply (and add) elements of the weight rings for each of the operands. EXAMPLES:: sage: G = species.SimpleGraphSpecies() sage: G.weight_ring() Rational Field """ from sage.structure.element import get_coercion_model cm = get_coercion_model() f_weights = self._F.weight_ring() g_weights = self._G.weight_ring() return cm.explain(f_weights, g_weights, verbosity=0)