Open eric-wieser opened 4 years ago
This is very strange:
In [1]: M = MatrixSymbol('M', 2, 2)
In [2]: e1 = Mul(-1, Determinant(M))
In [3]: e2 = - Determinant(M)
In [4]: e1.is_commutative
Out[4]: False
In [5]: e2.is_commutative
In [6]: e1 == e2
Out[6]: True
The is_commutative is clearly wrong. Determinant is a number, so it is commutative. There is probably some incorrect logic somewhere that assumes that since the arguments are noncommutative, the expression is.
I assume matrices of non-commutative symbols aren't supported anyway at the moment?
They might work with Matrix, though probably by accident. I don't know if it is tested. MatrixSymbol definitely represents a matrix of complex numbers.
I ask because if not, this should be fixable with a is_commutative = True
class variable?
I think that there are some fundamental flaws of treating commutativity based on its subexpressions. For example, for Basic, it treats whether an object is commutative or not based on whether its arguments are commutative or not.
I don't understand what is happening because as far as I can tell e1
and e2
above are the same but they give different results for is_commutative
.
Note that attempting to fix this by setting Determinant.is_commutative = True
, results in the error in #19327. The issue is that with that present, these lines are no longer executed:
meaning that Determinant.doit()
is never called.
I won't consider this issue fixed until I understand why e1 and e2 give different results.
I won't consider this issue fixed until I understand why e1 and e2 give different results.
A partial explanation:
-det_m
is implemented as Mul._from_args((S.NegativeOne, det_m), det_m.is_commutative)
.-1 * det_m
is implemented as Mul(S.NegativeOne, det_m)
And here's the thorough explanation:
Mul(*args)
calls AssocOp.__new__
, which splits the arguments into commutative and non-commutative via Mul.flatten
. The api of flatten
has no way to indicate "possibly commutative", so the None
gets turned to False
Mul._from_args
is happy to propagate is_commutative=None
Is is_commutative == None
even meaningful?
At any rate, it's not correct for Determinant
- help would be appreciated understanding why making it commutative (#19327) makes sympy crash.
Is
is_commutative == None
even meaningful?
No, it's not. Either commutative is true in which case the object is known to commute with anything else or it is not in which case commutative should be False.
Note that as of #19354 this is no longer an issue for Determinant
, but exactly the same problem exists for any custom Basic
instance with a non-commutative instance in its arguments.
I'm confused by this behavior:
Is there a bug here? Or do the two "commutative"s mean very different things?