Hi all, it looks like CSE and Subs don't interact very well. Here's what happens:
- CSE finds a few Subs instances that share the entirety of their 'point' values. - CSE creates a symbol for the entire 'point' value--i.e. the whole Tuple. - Upon construction of the new Subs with the symbol for 'point', Subs wraps that symbol in a Tuple. - When the CSE'd value of the symbol is substituted back into the expression, we end up with Tuple(Tuple(expr)). There are multiple ways of fixing this, none strikes me as 'obviously right': - Special-case Subs in CSE, to only look at the elements of Subs.point, not the whole thing. - Special-case Tuple in CSE--in effect, don't collect entire Tuples in CSE. (*) - Denest in the Subs constructor, i.e. turn Tuple(Tuple(x)) into Tuple(x). - Add a flag to prevent the Tuple wrapping in Subs when called from CSE. (*) is what I've implemented as a stopgap, patch attached. I'd much appreciate any insight/fixes for this. Thanks, Andreas
pgpDRfqLmlku3.pgp
Description: PGP signature
diff --git a/sympy/simplify/cse_main.py b/sympy/simplify/cse_main.py
index 0933291..4928c7f 100644
--- a/sympy/simplify/cse_main.py
+++ b/sympy/simplify/cse_main.py
@@ -3,7 +3,7 @@
import bisect
import difflib
-from sympy import Basic, Mul, Add
+from sympy import Basic, Mul, Add, Tuple
from sympy.utilities.iterables import preorder_traversal, numbered_symbols
import cse_opts
@@ -151,6 +151,9 @@ def insert(subtree):
pt.skip()
continue
+ if isinstance(subtree, Tuple):
+ continue
+
if subtree.is_Mul:
muls.add(subtree)
elif subtree.is_Add:
