.canonicalize_radical() produces incorrect result

I'm trying to simplify some trigonometric expressions using sage, and I noticed that .simplify_full() doesn't optimize those, unless a .canonicalize_radical() is used (thanks slelievre for the hint). But that yields incorrect results for some expressions. For example:

sage: y = sqrt(sin(x)^2 + 4*sin(x) + 4) - sqrt(sin(x)^2 - 4*sin(x) + 4)
sage: y.simplify_full()
sqrt(sin(x)^2 + 4*sin(x) + 4) - sqrt(sin(x)^2 - 4*sin(x) + 4)

.canonicalize_radical() simplifies it further:

4

But that is wrong! The answer should be 2*sin(x). Obviously it selected an incorrect sign for the second sqrt(...).

Is there a way to make .canonicalize_radical() smarter? Or any other way to simplify an expression like this correctly?

edit retag close merge delete

Sort by » oldest newest most voted

A solution is to use simplify_sqrt_real, which assumes that x lies in the real domain:

sage: y = sqrt(sin(x)^2 + 4*sin(x) + 4) - sqrt(sin(x)^2 - 4*sin(x) + 4)
sage: from sage.manifolds.utilities import simplify_sqrt_real
sage: simplify_sqrt_real(y)
2*sin(x)

More generally, you can use simplify_chain_real, which applies a chain of simplifications (including simplify_sqrt_real) valid in the real domain:

sage: from sage.manifolds.utilities import simplify_chain_real
sage: simplify_chain_real(y)
2*sin(x)
more

Thank you! I've experimented with simplify_chain_real a little, and sometimes it produces a result that's bigger and more complex than the source, but it's definitely a good thing to try! Thanks! Also, according to simplify_chain_real docs, it still uses canonicalize_radical() internally, however I could not reproduce any issues with simplify_chain_real yet. Is it considered "safe to use"? Or is it better to use simplify_sqrt_real and simplify_abs_trig and use simplify_chain_real only as a hint, or verify the result by hand?

I would say it is pretty safe to use simplify_chain_real since it is used systematically in calculus on real manifolds and performs not too badly. Among all these examples, the only one where it was not sufficient is the hyperbolic plane example. It turned out necessary to add (cf. cell )

maxima_calculus.eval("domain: real;")

to have some sqrt simplification be done correctly.