# Finding sub-expressions that simplify larger formula

If I use FullSimplify on a large formula it will consequently return a much smaller expression. However, suppose I notice the simplified expression can benefit from further intermediate definitions. For example, say I observe c = (1-a)(1-b), would make my expression drastically smaller.

Instead of spending time to try such substitutions, does Mathematica have functionality to perform this work for me? More particularly, how would I find optimal sub-expressions to simplify the following expression?

(1/(a^2 (b + m)))(-(-1 + a + 2 b) (-1 + 2 b + 2 m) - 4 b ArcTanh[1 - 2 b] + Log[4] + 2 ((2 + a) b + m + a m) Log[1 + a] - a (b + m) Log[4 - 4 b] + a Log[(2 - 2 b)/(1 + a)] - m Log[1 - b] + 2 Log[(1 - b)/(1 + a)] + (m - a (b + m)) Log[b])

• Probably not out of the box. However, there are further techniques that you could use to nudge MMA in the right direction, but we would absolutely need a practical example of an expression that displays these properties in order to give you a more specific answer. – MarcoB Sep 13 '18 at 14:23
• ExperimentalOptimizeExpression can look for common subexpressions, but it won't change the way the expression is written to expose more such subexpressions. I believe it is meant for speeding up computations (avoid computing the same thing twice), not for simplification. BTW +1, I wished for such a feature many times. – Szabolcs Sep 13 '18 at 14:48
• @MarcoB, I provided an example that FullSimplify cannot reduce further, but where I can see the module a(b + m). – user120911 Sep 13 '18 at 17:46
• Compile[] is also able to find common subexpressions if the whole expression is compilable in general. The resulting CompiledFunction contains a list of imperative program steps that is equal to the original expression. – Thies Heidecke Sep 17 '18 at 16:46

Note, that if you just propose Mathematica additional equalities, it will give them try:

f = (1/(a^2 (b + m))) (-(-1 + a + 2 b) (-1 + 2 b + 2 m) -
4 b ArcTanh[1 - 2 b] + Log[4] +
2 ((2 + a) b + m + a m) Log[1 + a] - a (b + m) Log[4 - 4 b] +
a Log[(2 - 2 b)/(1 + a)] - m Log[1 - b] +
2 Log[(1 - b)/(1 + a)] + (m - a (b + m)) Log[b]);

In[6]:=
LeafCount[f]
fs = FullSimplify[f, {c == 1 + a}];
LeafCount[fs]

Out[6]= 114

Out[8]= 90


Sometimes you can make a good guess from the additional information you have about you problem (in physics you often do).

One way to find repeating sub expressions:

SortBy[Select[
Tally[Level[f, -1]],
LeafCount[First[#]] > 3 &
], Last][[-3 ;;]] // Column


Compile[] is also able to find common subexpressions if the whole expression is compilable in general. The resulting CompiledFunction contains a list of imperative program steps that is equal to the original expression.

expr = (1/(a^2 (b+m))) (-(-1+a+2 b) (-1+2 b+2 m)-
4 b ArcTanh[1-2 b]+Log[4]+2 ((2+a) b+m+a m) Log[1+a]-
a (b+m) Log[4-4 b]+a Log[(2-2 b)/(1+a)]-m Log[1-b]+
2 Log[(1-b)/(1+a)]+(m-a (b+m)) Log[b]);

cf = Compile[{{a, _Real}, {b, _Real}, {m, _Real}}, Evaluate@expr]


Clicking on the + symbol reveals the generated code:

This expression can also be found as second to last part of the CompiledFunction expression:

cf[[-2]]

Function[{a, b, m},
Block[{Compile$5, Compile$2, Compile$21, Compile$28, Compile$33, Compile$34}, Compile$5 = -2 b; Compile$2 = b + m;
Compile$21 = 1 + a; Compile$28 = 1/Compile$21; Compile$33 = -b;
Compile$34 = 1 + Compile$33; (1/(
a^2 Compile$2))((1 - a + Compile$5) (-1 + 2 b + 2 m) -
4 b ArcTanh[1 + Compile$5] + Log[4] + 2 ((2 + a) b + m + a m) Log[Compile$21] -
a Compile$2 Log[4 - 4 b] + a Log[Compile$28 (2 + Compile$5)] - m Log[Compile$34] +
2 Log[Compile$28 Compile$34] + (m - a Compile\$2) Log[b])]]