Skip to content

FormalSum should work with non-comparable values #22346

@jdemeyer

Description

@jdemeyer

FormalSum sorts its entries, which is not guaranteed to work, especially on Python 3.

sage: from sage.structure.richcmp import *
sage: @richcmp_method
....: class NoCmp(object):
....:     def __richcmp__(self, other, op):
....:         if op not in (op_EQ, op_NE):
....:             raise RuntimeError
sage: nc = NoCmp()
sage: FormalSum([(1,nc), (1,1)])
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-23-33e7842a248f> in <module>()
----> 1 FormalSum([(Integer(1),nc), (Integer(1),Integer(1))])

/usr/local/src/sage-config/local/lib/python2.7/site-packages/sage/structure/formal_sum.pyc in __init__(self, x, parent, check, reduce)
    132         assert isinstance(parent, parent.category().parent_class)
    133         if reduce:  # first reduce
--> 134             self.reduce()
    135         if check:   # then check
    136             k = parent.base_ring()

/usr/local/src/sage-config/local/lib/python2.7/site-packages/sage/structure/formal_sum.pyc in reduce(self)
    302             self._data = v
    303             return
--> 304         v.sort()
    305         w = []
    306         last = v[0][0]

/usr/local/src/sage-config/local/lib/python2.7/site-packages/sage/rings/integer.pyx in sage.rings.integer.Integer.__richcmp__ (build/cythonized/sage/rings/integer.c:7887)()
    961             c = mpz_cmp_d((<Integer>left).value, d)
    962         else:
--> 963             return coercion_model.richcmp(left, right, op)
    964 
    965         return rich_to_bool_sgn(op, c)

/usr/local/src/sage-config/local/lib/python2.7/site-packages/sage/structure/coerce.pyx in sage.structure.coerce.CoercionModel_cache_maps.richcmp (build/cythonized/sage/structure/coerce.c:20648)()
   1957         # we would end up trying the same coercion again.
   1958         if not y_is_Element and Py_TYPE(y).tp_richcompare:
-> 1959             res = Py_TYPE(y).tp_richcompare(y, x, revop(op))
   1960             if res is not NotImplemented:
   1961                 return res

/usr/local/src/sage-config/local/lib/python2.7/site-packages/sage/structure/richcmp.pyx in sage.structure.richcmp.slot_tp_richcompare (build/cythonized/sage/structure/richcmp.c:1768)()
    271     Function to put in the ``tp_richcompare`` slot.
    272     """
--> 273     return self.__richcmp__(other, op)
    274 
    275 

<ipython-input-19-9d5470810a1a> in __richcmp__(self, other, op)
      3     def __richcmp__(self, other, op):
      4         if op not in (op_EQ, op_NE):
----> 5             raise RuntimeError
      6 

RuntimeError:

To fix this, we do not sort the terms in reduce(). Instead, we keep the existing ordering.

This requires adding a few straightforward __hash__ functions in modular.

Component: coercion

Keywords: richcmp

Author: Jeroen Demeyer

Branch: bcc0a23

Reviewer: Marc Mezzarobba

Issue created by migration from https://trac.sagemath.org/ticket/22346

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions