def __eq__(self,other): """ TESTS:: sage: P = Poset([["a","b"],["d"],["c"],["d"],[]], facade = False) sage: Q = Poset([["a","b"],["d"],["c"],[],[]], facade = False) sage: P(0).__eq__(P(4)) False sage: from sage.combinat.posets.elements import PosetElement sage: PosetElement(P,0,"c") == PosetElement(P,0,"c") True sage: PosetElement(P,0,"c") == PosetElement(Q,0,"c") False sage: PosetElement(P,0,"b") == PosetElement(P,0,"c") False .. warning:: as an optimization, this only compares the parent and vertex, using the invariant that, in a proper poset element, ``self.element == other.element`` if and only ``self.vertex == other.vertex``:: sage: PosetElement(P,1,"c") == PosetElement(P,0,"c") True Test that :trac:`12351` is fixed:: sage: P(0) == int(0) False """ # This should instead exploit unique representation, using # self is other, or best inherit __eq__ from there. But there # are issues around pickling and rich comparison functions. return have_same_parent(self, other) \ and self.vertex == other.vertex
def __eq__(self, other): """ TESTS:: sage: P = Poset([["a","b"],["d"],["c"],["d"],[]], facade = False) sage: Q = Poset([["a","b"],["d"],["c"],[],[]], facade = False) sage: P(0).__eq__(P(4)) False sage: from sage.combinat.posets.elements import PosetElement sage: PosetElement(P,0,"c") == PosetElement(P,0,"c") True sage: PosetElement(P,0,"c") == PosetElement(Q,0,"c") False sage: PosetElement(P,0,"b") == PosetElement(P,0,"c") False .. warning:: as an optimization, this only compares the parent and vertex, using the invariant that, in a proper poset element, ``self.element == other.element`` if and only ``self.vertex == other.vertex``:: sage: PosetElement(P,1,"c") == PosetElement(P,0,"c") True Test that :trac:`12351` is fixed:: sage: P(0) == int(0) False """ # This should instead exploit unique representation, using # self is other, or best inherit __eq__ from there. But there # are issues around pickling and rich comparison functions. return have_same_parent(self, other) \ and self.vertex == other.vertex
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 __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 __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 __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 __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 polynomial_derivative( p, q ): # this just extends a function by bilinearity; we would want it to be built using ModulesWithBasis """ Return the derivative of `q` w.r.t. `p`. INPUT: - `p`, `q` -- two polynomials in the same multivariate polynomial ring `\K[X]` OUTPUT: a polynomial The polynomial `p(\partial)(q)`, where `p(\partial)` the differential operator obtained by substituting each variable `x` in `p` by `\frac{\partial}{\partial x}`. EXAMPLES:: sage: R = QQ['x,y'] sage: x,y = R.gens() sage: polynomial_derivative(x, x) 1 sage: polynomial_derivative(x, x^3) 3*x^2 sage: polynomial_derivative(x^2, x^3) 6*x sage: polynomial_derivative(x+y, x^3) 3*x^2 sage: polynomial_derivative(x+y, x^3*y^3) 3*x^3*y^2 + 3*x^2*y^3 sage: p = -x^2*y + 3*y^2 sage: q = x*(x+2*y+1)^3 sage: polynomial_derivative(p, q) 72*x^2 + 144*x*y + 36*x - 48*y - 24 sage: -diff(q, [x,x,y]) + 3 * diff(q, [y,y]) 72*x^2 + 144*x*y + 36*x - 48*y - 24 """ if not have_same_parent(p, q): raise ValueError("p and q should have the same parent") R = p.parent() result = R.zero() # We would want to use R.sum_of_terms_if_not_None for (e1, c1) in items_of_vector(p): for (e2, c2) in items_of_vector(q): m = polynomial_derivative_on_basis(e1, e2) if m is None: continue (e3, c3) = m result += R({e3: c1 * c2 * c3}) return result
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 __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 __sub__(left, right): """ Return the difference between ``left`` and ``right``, if it exists. This top-level implementation delegates the work to the ``_sub_`` method or to coercion. See the extensive documentation at the top of :ref:`sage.structure.element`. 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): 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 __le__(self, other): r""" Return if this growth element is at most (less than or 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:`_le_`. EXAMPLES:: sage: import sage.rings.asymptotic.growth_group as agg sage: P_ZZ = agg.MonomialGrowthGroup(ZZ, 'x') sage: P_QQ = agg.MonomialGrowthGroup(QQ, 'x') sage: P_ZZ.gen() <= P_QQ.gen()^2 True sage: ~P_ZZ.gen() <= P_ZZ.gen() True """ from sage.structure.element import have_same_parent if have_same_parent(self, other): return self._le_(other) from sage.structure.element import get_coercion_model import operator try: return get_coercion_model().bin_op(self, other, operator.le) except TypeError: return False
def __add__(self, right): r""" Return the sum of ``self`` and ``right``. This calls the `_add_` 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 an ``_add_`` method in the element class or a ``summation`` method in the parent class. EXAMPLES:: sage: F = CommutativeAdditiveSemigroups().example() sage: (a,b,c,d) = F.additive_semigroup_generators() sage: a + b a + b """ if have_same_parent(self, right) and hasattr(self, "_add_"): return self._add_(right) from sage.structure.element import get_coercion_model import operator return get_coercion_model().bin_op(self, right, operator.add)
def __le__(self, other): r""" Return if this element is less than or equal to ``other``. INPUT: - ``other`` -- an element. OUTPUT: A boolean. .. NOTE:: This method uses the coercion framework to find a suitable common parent. This method can be deleted once :trac:`10130` is fixed and provides these methods automatically. TESTS:: sage: from sage.combinat.posets.cartesian_product import CartesianProductPoset sage: QQ.CartesianProduct = CartesianProductPoset # needed until #19269 is fixed sage: def le_sum(left, right): ....: return (sum(left) < sum(right) or ....: sum(left) == sum(right) and left[0] <= right[0]) sage: C = cartesian_product((QQ, QQ), order=le_sum) sage: C((1/3, 2)) <= C((2, 1/3)) True sage: C((1/3, 2)) <= C((2, 2)) True The following example tests that the coercion gets involved in comparisons; it can be simplified once :trac:`18182` is merged. :: sage: class MyCP(CartesianProductPoset): ....: def _coerce_map_from_(self, S): ....: if isinstance(S, self.__class__): ....: S_factors = S.cartesian_factors() ....: R_factors = self.cartesian_factors() ....: if len(S_factors) == len(R_factors): ....: if all(r.has_coerce_map_from(s) ....: for r,s in zip(R_factors, S_factors)): ....: return True sage: QQ.CartesianProduct = MyCP sage: A = cartesian_product((QQ, ZZ), order=le_sum) sage: B = cartesian_product((QQ, QQ), order=le_sum) sage: A((1/2, 4)) <= B((1/2, 5)) True """ from sage.structure.element import have_same_parent if have_same_parent(self, other): return self._le_(other) from sage.structure.element import get_coercion_model import operator try: return get_coercion_model().bin_op(self, other, operator.le) except TypeError: return False
def __le__(self, other): r""" Return if this element is less than or equal to ``other``. INPUT: - ``other`` -- an element. OUTPUT: A boolean. .. NOTE:: This method uses the coercion framework to find a suitable common parent. This method can be deleted once :trac:`10130` is fixed and provides these methods automatically. TESTS:: sage: from sage.combinat.posets.cartesian_product import CartesianProductPoset sage: QQ.CartesianProduct = CartesianProductPoset # needed until #19269 is fixed sage: def le_sum(left, right): ....: return (sum(left) < sum(right) or ....: sum(left) == sum(right) and left[0] <= right[0]) sage: C = cartesian_product((QQ, QQ), order=le_sum) sage: C((1/3, 2)) <= C((2, 1/3)) True sage: C((1/3, 2)) <= C((2, 2)) True The following example tests that the coercion gets involved in comparisons; it can be simplified once #18182 is in merged. :: sage: class MyCP(CartesianProductPoset): ....: def _coerce_map_from_(self, S): ....: if isinstance(S, self.__class__): ....: S_factors = S.cartesian_factors() ....: R_factors = self.cartesian_factors() ....: if len(S_factors) == len(R_factors): ....: if all(r.has_coerce_map_from(s) ....: for r,s in zip(R_factors, S_factors)): ....: return True sage: QQ.CartesianProduct = MyCP sage: A = cartesian_product((QQ, ZZ), order=le_sum) sage: B = cartesian_product((QQ, QQ), order=le_sum) sage: A((1/2, 4)) <= B((1/2, 5)) True """ from sage.structure.element import have_same_parent if have_same_parent(self, other): return self._le_(other) from sage.structure.element import get_coercion_model import operator try: return get_coercion_model().bin_op(self, other, operator.le) except TypeError: return False