Example #1
0
    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
Example #2
0
    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
Example #3
0
        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)
Example #4
0
    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
Example #5
0
        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)
Example #6
0
            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)
Example #7
0
            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)
Example #8
0
    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
Example #9
0
        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)
Example #10
0
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
Example #11
0
        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)
Example #12
0
        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)
Example #13
0
        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)
Example #14
0
            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)
Example #15
0
            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)
Example #16
0
    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
Example #17
0
        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)
Example #18
0
        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)
Example #19
0
        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
Example #20
0
        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