Why is isequaln (f, simplify (f)) false?
I have a function f
that is defined as:
syms c a t f = symfun(c + t - (2*(t - 2^(1/2)*(a*t)^(1/2))*(a - t/2))/(2*a - t), [c a t])
However, checking for equality with the simplified version gives:
isequaln(f, simplify(f)) ans = 0
Expected simplify
not to return the exact equivalent of the original function?
source to share
A problem with isequaln
sym/isequaln
is probably not a suitable function for checking equality. Using sym/isequaln
:
isequaln (A, B) returns true if A and B equally treat NaNs as equal.
As reported by @ Benoit_11, the documentation is not entirely clear, but like the numeric equivalent, the function seems to test for equality, not an identifier (despite the misuse of the word "identical"). A simplified function is an identity for an unfortified function, but it is not an equivalence. According to the documentation, sym/isequaln
can take things like assumptions
and possibly simple relationships into account, but does not perform transformations and simplifications internally. This is almost certainly due to the fact that simplification is computationally expensive, so most likely the design should only include a few well-defined (but not well-documented) tests.
Possible solution with traps
So how can you proceed? In addition to the sym/isequaln
Symbolic Math toolbox isAlways
, you can more accurately test for equality and inequality:
syms c a t f = symfun(c + t - (2*(t - 2^(1/2)*(a*t)^(1/2))*(a - t/2))/(2*a - t), [c a t]) g = simplify(f) isAlways(f==g)
However, in R2014b, this also returns the false
following warning:
Warning: Cannot prove 'c + t - ((2*t - 2*2^(1/2)*(a*t)^(1/2))*(a - t/2))/(2*a - t) == c +
2^(1/2)*(a*t)^(1/2)'.
> In /Applications/MATLAB_R2014b.app/toolbox/symbolic/symbolic/symengine.p>symengine at 56
In sym.isAlways at 38
You should be aware that symbolic variables are considered complex by default and that it isAlways
tries to prove this relationship for all possible combinations of complex values c
, a
and t
. Simplification is also a fuzzy process - from the documentation for simplify
:
Simplification of mathematical expression is not a well-defined subject. There is no universal idea as to which form of expression is the simplest. A form of mathematical expression that is simple for one problem may be difficult or even unsuitable for another.
If you look closely at your original equation, you will see that it contains a feature that has been simplified. In R2014b, score g(1,1,2)
returns 3
, but score f(1,1,2)
returns:
Error using mupadmex
Error in MuPAD command: Division by zero. [_power]
Evaluating: _symans_32_15992
...
Using assumptions
If you know something about your symbolic variables, you can avoid it by applying assumptions, for example.
syms c a t f = symfun(c + t - (2*(t - 2^(1/2)*(a*t)^(1/2))*(a - t/2))/(2*a - t), [c a t]) g = simplify(f) assume(t>2*a) isAlways(f==g)
which now returns true
. By the way, using @ Benoit_11 example, syms a b; isAlways((a+b)^2==a^2+2*a*b+b^2)
also returns true
directly.
source to share
The function makes it easy to return the simplest algebraic form of the function that you provide it. According to Matlab doc:
isequaln recursively compares the contents of symbolic data structures and properties of objects. If all content in the corresponding location is equal, isequaln returns logical 1 (true).
It's not clear to me how Matlab checks for "content in appropriate places", but it looks like while the simplified function is algebraically equivalent to the original, its "content" is not in the same place as the original, so Matlab sees them as different.
As @horchler rightly mentions in a comment, testing 2 functions with the same set of input arguments is hardly conclusive proof, like the following: so answer this with a grain of salt:
%//Define f and S = simplify(f);
syms c a t
f = symfun(c + t - (2*(t - 2^(1/2)*(a*t)^(1/2))*(a - t/2))/(2*a - t), [c a t])
f(c, a, t) =
c + t - ((2*t - 2*2^(1/2)*(a*t)^(1/2))*(a - t/2))/(2*a - t)
S = simplify(f)
S(c, a, t) =
c + 2^(1/2)*(a*t)^(1/2)
%// Check with dummy arguments:
isequaln(f(1,2,3),S(1,2,3))
ans =
1 %// seems to work...
Out of curiosity, if we compare 2 functions, namely (a + b) ^ 2 and a ^ 2 + 2ab + b ^ 2 (which are identical) and check the equivalence:
syms a b x1 = symfun(a^2+2*a*b+b^2,[a b]) x1(a, b) = a^2 + 2*a*b + b^2 x2 = symfun((a+b)^2,[a b]) x2(a, b) = (a + b)^2 isequaln(x1,x2) ans = 0
we get false again, although they are equivalent.
So to answer the question "Why is isequaln (f, simplify (f)) false?" I would say this because MATLAB organizes its content internally in a different way, so they seem to be two different functions. I know this is not a great explanation, but I hope this helped.
source to share