I’m trying to extend some modules to work with Symbolics by getting rid of Bool conditionals and divide by zero checks etc. I’m trying to add some unit tests and I want to test if two symbolic equations are equivalent.
When I try and extend Base.:(==) by checking if the components of a composite type structure are == symbolically (I even throw in some simplify calls wrapping the LHS and RHS of the equals) it complains about non-Boolean being used in a Boolean context.
What’s the trick to see if two equations are the same symbolically so that my test cases can mean something.
Lol I know this is reviving a few years old thread, but I wanted to ask why this is still a thing with symbolics, as it generates a lot of comparability issues with other packages. Unless there is something within symbolics that utilizes == in a symbolic sense, this seems like a bad design choice?
For example, if I want to use symbolics with a package that runs ishermitian in a constructor, then it will just return an error. To fix this, it would require LinearAlgebra.jl, SparseArrays.jl and others to always be careful when doing any comparisons, and always use isequal instead of ==.
Those two print the same modulo a pair of parentheses, and isequal still says no. It’s a malformed single-argument Mul node - simplify on it throws a BoundsError, and expand normalises it away. Details in SymbolicUtils.jl#1044.
My middle-school maths teacher passed away a few years ago. Small mercy: she never had to see the sign rule get an entry in a bug tracker. Though she did already ship the fix “expand it first” so expand((-U)^2) == U^2 would have been a one-line answer from her, in red pen, with a note about tidying up my brackets.
Not really. Isequal and == are both structural comparisons, you don’t want these to include an internal simplify / expand as it could make them really slow. Even then, for complicated expressions, they might still fail. They will always be not completely reliable, so it is better to do an explicit form manipulation before checking equality. The bigger issue here is that they way == is defined in symbolics makes this unreliable comparison impossible as most packages use == and not isequal, which generates a lot of incompatibility issues and makes it hard to fine new uses for Symbolics.jl.
Edit: there is a good argument for modifying how power works so that it can distribute to any negative signs within an Mul automatically on creation. But I think that’s separate from the compatibility issues the current setup introduces.
I’m a bit confused on this part, because the documentation states the output for Base.:(==) is Bool or missing. It says that type promotion should be done to facilitate this comparison, and missing is only returned in special cases. The current implementation in symbolics returns Num, which breaks with this convention. It’s this break with convention which makes compatibility with other packages in the julia ecosystem problematic, because if two symbolic expressions end up in a if a==b situation, it throws an error instead of returning a true/false, and most packages use this instead of isequal, because something like isequal(0.0,-0.0) returns false while -0.0 == 0.0 returns true.
Let me phase this a bit better, are their routines in symbolics that are built around handling a the Num output of x==b? If not, then I don’t see any reason symbolics should break with the Base.:(==) convention outlined in the documentation.