简体   繁体   中英

How to canonicalize list of expressions in SymPy?

I would like to canonicalize a list of SymPy expressions into lexicographic order. Or, at least, some semblance of it. This was simple on SymPy 0.7.2 and seems to have broken as of...

>>> import sympy
>>> sympy.__version__
'0.7.4.1'

Observe:

>>> f, g = sympy.symbols('f g', cls=sympy.Function)

>>> sorted([f, g])
[f, g]

>>> sorted([g, f])
[f, g]

Cool. I get back lexicographic ordering. Now, if I apply the functions...

>>> x = sympy.symbols('x')

>>> sorted([f(x),g(x)])

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/sympy/core/relational.py", line 226, in __nonzero__
    raise TypeError("symbolic boolean expression has no truth value.")
TypeError: symbolic boolean expression has no truth value.

...where that TypeError string has shown up elsewhere from Googling about but I've not been able to discern a workaround.

I see the same message with [f(x), g(x)].sort(). Using set([f(x), g(x)]) won't work in my larger use case because I need to permit duplicates.

Any ideas for a SymPy 0.7.2- and 0.7.4-friendly way to canonicalize a list of SymPy expressions? Playing around a bit sorted([f(x),g(x)], lambda x,y: x.compare(y)) seems to work but feels like a mouthful.

Use the 'ordered' function:

>>> list(ordered((g(x),f(x))))
[f(x), g(x)]

It returns a generator -- that's why the result is wrapped with list.

SymPy no longer compares expressions arbitrarily, similar to Python 3. If you want an arbitrary, but consistent order, use the default_sort_key key function to sorted:

>>> sorted([f(x), g(x)], key=default_sort_key)
[f(x), g(x)]

I believe ordered does something similar.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM