3
$\begingroup$

In my calculations I often end up with large expressions that contain a lot of terms like $\sqrt{a^2}$, where I know that $a>0$ is always satisfied.

I know that Mathematica won't simplify such expressions by default (which is good), since $a$ could be complex. I also know that one can use Simplify with Assumptions or PowerExpand to get rid of the square roots.

The issue is that my expressions can be potentially very large, so applying Simplify or PowerExpand in the intermediate steps is not really an option. It just costs too much time...

Consider for example

exp = Sum[coeff[i] Sqrt[ab^2], {i, 1, 20000}];
AbsoluteTiming[PowerExpand[exp];]

On my machine PowerExpand requires 7.7 seconds to get rid of the square roots, which is painfully slow.

Now I can use the dirty trick

Unprotect[Power];
Power[Power[ab, 2], Rational[1, 2]] = ab;
Protect[Power];

and with

AbsoluteTiming[exp2 = exp;]
exp2[[1 ;; 10]]

the square roots are all gone in less than 0.05 seconds.

Of course, I know that it is almost always a bad idea to redefine system functions, but in this particular case I just cannot come up with any good alternative.

One possible solution is to do something like

AbsoluteTiming[
 sqrts = Cases[exp, Power[_, _Rational], Infinity] //DeleteDuplicates // Sort;
 sqrtsSimp = PowerExpand /@ sqrts;
 repRule = Thread[Rule[sqrts, sqrtsSimp]];
 exp2 = exp /. repRule;
]

This seems to be almost as fast as the dirty trick, but the disadvantage is that I have to explicitly apply it to my expressions (possibly after each subsequent evaluation). With redefined Power, however, the simplification is done automatically, so I know that I don't have to bother about square roots at all.

I wonder if there are better solutions to my problem? It may well be that I'm missing some obvious tricks to deal with such things.

$\endgroup$
2
$\begingroup$

One way is to substitute it manually as

exp = Sum[coeff[i] Sqrt[ab^2], {i, 1, 20000}];
AbsoluteTiming[exp2 = exp /. Sqrt[ab^2] -> ab;]

0.028188, Null}

$\endgroup$
1
$\begingroup$

A reasonably general approach is

exp /. Power[Power[a_, c_], d_] -> Power[a, c d]
$\endgroup$
0
$\begingroup$

In a complicated expression, with many repeated subexpressions, it can be useful to extract the parts and simplifying before substituting back in

Union[Cases[exp, __Power, ∞]]
(* {b^2, Sqrt[a b^2]} *)

AbsoluteTiming[exp /. Thread[% -> PowerExpand[%]];]
(* {0.060599, Null} *)

Note that Sqrt is automatically changed to Power (despite appearances) so the rule must match that.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.