Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to replace implicit subexpressions in Mathematica?

I have this expression in Mathematica:

(a^2 (alpha + beta)^2)/(b^2 + c^2) + (a (alpha + beta))/(b^2 + c^2) + 1  

As you can see, the expression has a couple of subexpressions that repeat throughout it.

I want to be able to replace a/(b^2+c^2) with d and alpha+beta with gamma.

The final expression should then be:

1+d*gamma+a*d*gamma^2

I have much more complicated expressions where being able to do this would greatly simplify my work.

I have tried Googling this question, and I only find answers that use FactorTerms and ReplaceRepeated, but do not work consistently and for a more complicated expression like this one. I am hoping that someone here has the answer.

like image 989
felimz Avatar asked Dec 09 '11 22:12

felimz


2 Answers

The hard part for the case at hand is the rule for d. Perhaps, there are simpler ways to do it, but one way is to expand the powers to products, to make it work. Let's say this is your expression:

expr  = (a^2 (alpha + beta)^2)/(b^2 + c^2) + (a (alpha + beta))/(b^2 + c^2) + 1

and these are the rules one would naively write:

rules = {a/(b^2 + c^2) -> d, alpha + beta -> gamma}

What we would like to do now is to expand powers to products, in both expr and rules. The problem is that even if we do, they will auto-evaluate back to powers. To prevent that, we'll need to wrap them into, for example, Hold. Here is a function which will help us:

Clear[withExpandedPowers];
withExpandedPowers[expr_, f_: Hold] :=
  Module[{times},
    Apply[f,
       Hold[expr] /. x_^(n_Integer?Positive) :>
          With[{eval = times @@ Table[x, {n}]}, eval /; True] /.
       times -> Times //.
       HoldPattern[Times[left___, Times[middle__], right___]] :>
          Times[left, middle, right]]];

For example:

In[39]:= withExpandedPowers[expr]
Out[39]= Hold[1+(a (alpha+beta))/(b b+c c)+((alpha+beta) (alpha+beta) a a)/(b b+c c)]

The following will then do the job:

In[40]:= 
ReleaseHold[
   withExpandedPowers[expr] //. 
      withExpandedPowers[Map[MapAt[HoldPattern, #, 1] &, rules], Identity]]

Out[40]= 1 + d gamma + a d gamma^2

We had to additionally wrap the l.h.s. of rules in HoldPattern, to prevent products from collapsing back to powers there.

This is just one case where we had to fight the auto-simplification mechanism of Mathematica, but for this sort of problems this will be the main obstacle. I can't assess how robust this will be for larger and more complex expressions.

like image 112
Leonid Shifrin Avatar answered Dec 06 '22 13:12

Leonid Shifrin


Using ReplaceRepeated:

(a^2 (alpha + beta)^2)/(b^2 + c^2) + (a (alpha + beta))/(b^2 + c^2) + 
  1 //. {a/(b^2 + c^2) -> d, alpha + beta -> gamma}

Or using TransformationFunctions:

FullSimplify[(a^2 (alpha + beta)^2)/(b^2 + 
     c^2) + (a (alpha + beta))/(b^2 + c^2) + 1, 
 TransformationFunctions -> {Automatic, # /. 
     a/(b^2 + c^2) -> d &, # /. alpha + beta -> gamma &}]

Both give:

1 + gamma (d + (a^2 gamma)/(b^2 + c^2))
like image 42
Searke Avatar answered Dec 06 '22 13:12

Searke