22
$\begingroup$

Frequently, Mathematica will produce some expression in a complicated form, with a number of unset variables. For me, it is rare that I would be interested in solutions that are generalized to both real and imaginary arguments, so my method is usually to run a FullSimplify on the expression, with every unset variable being assumed be an element of the reals:

FullSimplify[a+Log[Exp[b^2 - c^2]]-Log[d],
    Assumptions->{a \[Element] Reals, b \[Element] Reals,
                  c \[Element] Reals, d \[Element] Reals}]

This is quite cumbersome, especially if the expression has many unset parameters. My question is: Can someone write a function that automatically extracts all unset parameters in an expression, and then uses that to set the Assumptions parameter automatically? The second part I know how to do (Element[#, Reals] & /@ pars), but not the extracting the unset parameters part. Ideally it would only take the function itself as its argument:

fullSimplifyReals[a+Log[Exp[b^2 - c^2]]-Log[d]]

Edit: I am accepting Szabolics' answer for now, as it seems to do what I want it to in my limited testing. For convenience, here is the functional form of Szabolics' answer:

fullSimplifyReals[x_] := Assuming[_Symbol \[Element] Reals, FullSimplify@x];
$\endgroup$

5 Answers 5

16
$\begingroup$

This is just an idea, and I am not confident about the safety of this approach. From the docs,

Element[patt, dom] asserts that any expression matching the pattern patt is an element of dom.

So we can set

$Assumptions = _Symbol \[Element] Reals

and then

FullSimplify[a + Log[Exp[b^2 - c^2]] - Log[d]]

(* ==> a + b^2 - c^2 - Log[d] *)

While I can't promise that this won't cause any trouble, I would definitely try it, at least to see if the approach works well in practice. You can keep a second kernel for testing and comparing without this setting.

$\endgroup$
5
  • $\begingroup$ I didn't realize that would work. Very nice! $\endgroup$
    – Mr.Wizard
    Commented Apr 4, 2013 at 1:09
  • $\begingroup$ Or even _ \[Element] Reals to make it also work with subscripts and friends. Do you see any additional risks? $\endgroup$
    – Rojo
    Commented Apr 4, 2013 at 18:45
  • $\begingroup$ @Rojo I haven't done any tests, but I was worried that _ \[Element] Reals would assume that every subexpression is real. For example, it would not only assume that x is real, but also that Sqrt[x] is real. I believe this is analogous to how Reduce work on a Real domain: it also assumes that subexpressions are real too, not just variables, though I can't find this in the docs right now (except for one item under Possible Issues. I'd have to think up an example where this makes a difference, but I remember MathGroup tests discussing unexpected results from ... $\endgroup$
    – Szabolcs
    Commented Apr 4, 2013 at 21:30
  • $\begingroup$ @Rojo Reduce, where Reduce[..., Reals] works differently than Reduce[(x|y) \[Element] Reals && eq, ...] $\endgroup$
    – Szabolcs
    Commented Apr 4, 2013 at 21:31
  • $\begingroup$ @Rojo Some related info: forums.wolfram.com/mathgroup/archive/2007/Nov/msg00928.html $\endgroup$
    – Szabolcs
    Commented Apr 4, 2013 at 21:45
8
$\begingroup$

ComplexExpand does precisely the assumptions you want to do with FullSimplify.

I'm not sure it's a good suggestion (usable in general), but you could use :

FullSimplify[
    a + Log[Exp[b^2 - c^2]] - Log[d], 
    TransformationFunctions -> {Automatic, ComplexExpand}
    ]

Automatic is necessary to let FulSimplify use the default TransformationFunctions

It works with your example and gives : a + b^2 - c^2 - Log[d]

It' s not easy to speculate about efficiency of the suggestion in general:

FullSimplify performs a sequence of transformations trying to minimize ComplexityFunction. The problem is that after the use of ComplexExpand the information "vars are Reals" is lost. So the next try, which is not a ComplexExpand, may destruct the work of ComplexExpand. I think this is not very likely because ComplexityFunction would become worst in most cases.

$\endgroup$
2
$\begingroup$

In your case - and many similar cases PowerExpand will do (or PowerExpand inc combination with FullSimplify ):

f = a + Log[Exp[b^2 - c^2]] - Log[d];

PowerExpand[f]
a + b^2 - c^2 - Log[d]

Because, from Documentation:

PowerExpand converts (a b)^c to a^cb^c, and (a^b)^c to a^(b c), and Log[a^b] to b Log[a]. The transformations made by PowerExpand are correct in general only if c is an integer or a and b are positive real numbers.

But for the sake of exercise or in case of something more cumbersome... Consider this prototype, you can be build up I am sure. I bet this depends on a particular case, especially if constants like Pi or E are involved... Basically this will work:

fullSimplifyReals[f_] := 
 Assuming[Cases[f, _Symbol, Infinity] \[Element] Reals, FullSimplify[f]]

fullSimplifyReals[f]

a + b^2 - c^2 - Log[d]

Because

Cases[f, _Symbol, Infinity]
{a, d, E, b, c}

But you see E stuck there? If you want to be clean and not assign constants to be "reals" or "integers", then

cons = ToExpression[Select[Names["System`*"], MemberQ[Attributes[#], Constant] &]]
{Catalan, ChampernowneNumber, \[Degree], E, EulerGamma, 
 Glaisher, GoldenRatio, Khinchin, MachinePrecision, \[Pi]}

and redefine

fullSimplifyReals[f_] := Assuming[Complement[
 Cases[f, _Symbol, Infinity], cons] \[Element] Reals, FullSimplify[f]]
$\endgroup$
3
  • $\begingroup$ Certainly I am interested in the more general case, I just couldn't dig up any horrendously long examples! Is there no way to extract the unset variables within an expression? That seems to be the most straightforward way... $\endgroup$
    – Guillochon
    Commented Apr 2, 2013 at 21:18
  • $\begingroup$ @Guillochon Cases[... , _Symbol, Infinity] works as a start. Is it what you had in imnd? $\endgroup$ Commented Apr 2, 2013 at 21:21
  • $\begingroup$ Yes that's very much similar to what I have in mind, it would be good to test in on a variety of cases. I'll accept in the next few days once I've had a chance to try it out. $\endgroup$
    – Guillochon
    Commented Apr 2, 2013 at 21:48
2
$\begingroup$

A mashup of the above answers gives what is, in my view, the simplest solution:

Assuming[_Symbol \[Element] Reals, FullSimplify[expression]]

For comparison:

FullSimplify[Sqrt[x^2]]  (* Gives Sqrt[x^2] *)
Assuming[_Symbol \[Element] Reals, FullSimplify[Sqrt[x^2]]] (* Gives Abs[x] *)
Assuming[_Symbol >= 0, FullSimplify[Sqrt[x^2]]] (* Gives x *)
$\endgroup$
1
$\begingroup$

Here is an old hack I've been using for a while now. Modifying internal functions is often inadvisable but nothing has burst into flames yet. I also haven't looked at this code in many years so it's probably not written particularly well. Further, if Szabolcs's trick doesn't have unforseen problems it's basically obsolete. Nevertheless, it might be of interest to someone.

Syntax:

FullSimplify[a + Log[Exp[b^2 - c^2]] - Log[d], All \[Element] Reals]
a + b^2 - c^2 - Log[d]

Code:

fs = {Simplify, FullSimplify};

Unprotect /@ fs;

(#[e_, h_[r1___, All, r2___], opts___] := #[
      e, (h[r1, #, r2] & /@ Cases[Level[e, {-1}], _Symbol]), opts]) & /@ fs;

(#[e_, c_List?(MemberQ[#, All, {-1}] &), opts___] := 
     Module[{s = Cases[Level[e, {-1}], _Symbol], 
       afb = Function[{eq}, (eq /. All -> #) & /@ s]}, #[
       e, (If[MemberQ[#, All, {1}], Sequence @@ afb[#], #]) & /@ c, opts]]) & /@ fs;

Protect /@ fs;
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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