# How to simplify expression through variable substitution [closed]

I am trying to simplify a complicated expression through variable substitution and part of the expression looks like:

$$2A_1^2+A_1B_2+2B_1^2-B_1A_2+2C_1^2+C_1D_2+2D_1^2-D_1C_2$$

I want to substitute $$A_1^2+B_1^2+C_1^2+D_1^2$$ with $$h_1^2$$ and substitute $$A_1B_2-B_1A_2+C_1D_2-D_1C_2$$ with $$h_{12}$$ and finally the expression would become $$2h_1^2+h_{12}$$.

I have tried to use /. to replace, however, it seems that Mathematica is not able to do the substitution when the expression don't explicitly contain the part to be substituted.

What's more, I also tried to use Solve and Reduce method. But as I am new to Mathematica, I cannot get a simple expression from Reduce (the results are divided into several conditions like B1=0&&B2=0) and I cannot get a desired result from Solve.

Could anybody give some examples on how to do this? Thanks in advance!!

• but $A_1 B_2-B_2 A_1+C_1 D_2-D_2 C_1$ is zero? Are these scalars or matrices? Commented Sep 30, 2022 at 11:06
• Sorry, the expressions are wrong, I will edit it. Thanks Commented Sep 30, 2022 at 11:28
• Welcome to the Mathematica Stack Exchange. Please add copy-paste-able code so that forum participants can copy and paste the same to their notebook environments and replicate the errors or difficulties you have encountered. Doing so will enable forum participants to provide you assistance in a focused manner. LateX code or images can be added if these provided added value. Copy directly from your input cell, click the Edit button under your post and format as code using the { } icon in the Edit window. Thanks.
– Syed
Commented Sep 30, 2022 at 11:39
• Hi, what did you mean by "I also tried to use Solve and Reduce method" ? How and why did you use it ? Commented Sep 30, 2022 at 12:12

See this answer for a more general discussion.

### Rule based solution:

If a direct substitution does not work you can make the substitution more obvious for Mathematica by picking out a simpler sub-expression that is clearly present and doing a substitution with that sub-expression:

2*A1^2 + A1*B2 + 2*B1^2 - B1*A2 + 2*C1^2 + C1*D2 + 2*D1^2 - D1*C2 /.
A1^2+B1^2 + C1^2 + D1^2 -> h1^2  /.
A1*B2 - B1*A2 + C1*D2 - D1*C2 -> h12


where A1^2+B1^2 + C1^2 + D1^2 is not explicitly present you can use

2*A1^2 + A1*B2 + 2*B1^2 - B1*A2 + 2*C1^2 + C1*D2 + 2*D1^2 - D1*C2 /.
A1^2 -> h1^2 - (B1^2 + C1^2 + D1^2) /.
A1*B2 - B1*A2 + C1*D2 - D1*C2 -> h12 // Simplify


In general if you would like to substitute a composite expression to a new variable, that is,

BigExpression /. CompositeExpression-> NewVariable

and the original expression (BigExpression in the example above) does not make the substitution obvious for Mathematica, you can instead pick out a simpler term in CompositeExpression and rewrite the substitution in terms of the simpler expression like in the above example.

## Ok, but how to automatize this ?

### Simplify

The answer provided by @Nasser is one possibility although I wonder whether the overhead of Simplify might take a long time with a BigBigExpression.

### Reduce

The answer provided in the link above gives a lot of possibilities. Here is one of them adapted to the problem at hand:

Refine[Reduce[{p ==
2*A1^2 + A1*B2 + 2*B1^2 - B1*A2 + 2*C1^2 + C1*D2 + 2*D1^2 - D1*C2,
A1^2 + B1^2 + C1^2 + D1^2 == h1^2,
A1*B2 - B1*A2 + C1*D2 - D1*C2 == h12}, {p}, {A1, B1, A2, B2, C1, D1, C2, D2}],
{h12 != 0, h1 != 0}]


output: (* p == 2 h1^2 + h12 || p == 2 h1^2 + h12 *)

Edit: You could use Variables in the above code instead of making the list of variables by hand.

You can then extract the expression by adding //First //Last to the expression above.

### Eliminate

A faster method from the above link uses Eliminate. For your example you can use:

Eliminate[{p == 2*A1^2 + A1*B2 + 2*B1^2 - B1*A2 + 2*C1^2 + C1*D2 + 2*D1^2 - D1*C2,
A1^2 + B1^2 + C1^2 + D1^2 == h1^2,
A1*B2 - B1*A2 + C1*D2 - D1*C2 == h12}, {A1, B1, A2, B2, C1, D1, C2,
D2}]


output: (* -2 h1^2 + p == h12 *)

You can obtain the expression for p by using SolveValues

First@SolveValues[-2 h1^2 + p == h12, p]


output: 2 h1^2 + h12

## BenchMarks

It is likely that the comparison of timings will change if the expression is more complicated.

I did not try the method using Solve from the first link above.

I used RepeatedTiming.

Simplify: 0.000695496 s

Rule: 0.0000197091 s

Reduce: 0.0833688 s

Eliminate: 0.00161821 s

Edit

I got interested in how these methods compare when the expression is more complicated. Hence, I used AntiSimplify from the resource functions. I was unable to use it with RessourceFunction so I installed it as a package.

original expression:

s = 2*A1^2 + A1*B2 + 2*B1^2 - B1*A2 + 2*C1^2 + C1*D2 + 2*D1^2 - D1*C2


anti-simplified expression (note I installed the package from the Author's note to use AntiSimplify):

s2 = AntiSimplify[s, A1^2 + B1^2, "Complexity" -> 3]


output:

Cos[49/3 (17576/125 - (8619 A1^2)/175 + (11271 A1^4)/1960 - (
4913 A1^6)/21952 - (8619 B1^2)/175 + (11271 A1^2 B1^2)/980 - (
14739 A1^4 B1^2)/21952 + (11271 B1^4)/1960 - (14739 A1^2 B1^4)/
21952 - (4913 B1^6)/21952 - (26/5 - 17/28 (A1^2 + B1^2))^3) Sin[
Cosh[Sin[A1^2 + B1^2]]]] (-(56/9) Cos[A1^2 + B1^2]^2 Cos[
1/2 (29791/343 - (1922 A1^2)/735 + (124 A1^4)/4725 - (8 A1^6)/
91125 - (1922 B1^2)/735 + (248 A1^2 B1^2)/4725 - (
8 A1^4 B1^2)/30375 + (124 B1^4)/4725 - (8 A1^2 B1^4)/30375 - (
8 B1^6)/91125 - (31/7 -
2/45 (A1^2 + B1^2))^3 + \[Pi])]^4 + (2 A1^2 - A2 B1 +
2 B1^2 + A1 B2 + 2 C1^2 - C2 D1 + 2 D1^2 + C1 D2) Cos[
9/32 (13824/6859 + (27648 A1^2)/15523 + (18432 A1^4)/35131 + (
4096 A1^6)/79507 + (27648 B1^2)/15523 + (36864 A1^2 B1^2)/
35131 + (12288 A1^4 B1^2)/79507 + (18432 B1^4)/35131 + (
12288 A1^2 B1^4)/79507 + (4096 B1^6)/
79507 - (24/19 + 16/43 (A1^2 + B1^2))^3) (1 +
Sinh[Cosh[A1^2 + B1^2]])])


Check:

Simplify[s - s2]


output: 0

• Reduce took too long no matter the option I chose for "Complexity" in AntiSimplify.

• The rule based method is fast but it was unable to obtain the desired expression as the rule has to be applied differently at different parts.

Thus the last two contenders are Simplify and Eliminate (I did not try with Solve). Who will win ?

(I used AbsoluteTiming and both methods gave the same output)

Simplify: 0.087227 s

Eliminate: 0.00586 s

Note: Using Simplify a second time reduced the timing. Does Simplify save information ? Perhaps the repeated timing before was not a good choice.

• The edit by community was me. For an unknown reason I was logged off when I added the edit and so it was considered as an edit from someone outside of the community. Commented Sep 30, 2022 at 13:25

You could use simplification with side relations.

Clear["Global*"]
expr = 2*A1^2 + A1*B2 + 2*B1^2 - B1*A2 + 2*C1^2 + C1*D2 + 2*D1^2 -D1*C2
side = {h12 == A1*B2 - B1*A2 + C1*D2 - D1*C2, A1^2 + B1^2 + C1^2 + D1^2 == h1}
Simplify[expr, side] /. h1 -> h1^2


You can't do the $$h_{1}^2$$ in the side relation, since it has to be a one symbol there (atomic). But you could always replace $$h_1$$ by $$h_{1}^2$$ afterwords.

• Thanks, that helps a lot Commented Sep 30, 2022 at 11:45
• I came back to this example to test If I understood why you said that you can not have h1^2 in a side relation. side = {h12 == A1*B2 - B1*A2 + C1*D2 - D1*C2, A1^2 + B1^2 + C1^2 + D1^2 == h1^2} and Simplify[expr, side] gave the result directly without having to use /. h1 -> h1^2 Commented Dec 23, 2022 at 12:43

The most powerful and general method to perform algebraic substitutions is based on computing the GroebnerBasis. In your case the syntax is

gb = GroebnerBasis[{-expr + 2*A1^2 + A1*B2 + 2*B1^2 - B1*A2 + 2*C1^2 +
C1*D2 + 2*D1^2 - D1*C2,
-h12 + A1*B2 - B1*A2 + C1*D2 - D1*C2, -h1^2 + A1^2 + B1^2 + C1^2 +
D1^2}, {h12, h1, expr}, {A1, B1, C1, D1, A2, B2, C2, D2},
MonomialOrder -> EliminationOrder]

Solve[gb == 0, expr]


(* {{expr -> 2 h1^2 + h12}} *)

Your can find many samples on how to use it by searching the answers. It is related to the demonstrated Eliminate example, though Eliminate implementation (as far as I know) is more limited.

• Hi! Would you agree that this way of using variable elimination is a bit fragile? For example, suppose the expression to simplify is 2*A1^2+A1*B2+2*B1^2-B1*A2+2*C1^2+C1*D2+2*D1^2, missing the final -D1*C2. Then your approach returns no result, but I think a useful result in that case would be C2 D1+2 h1^2+h12. Commented Sep 30, 2022 at 14:06
• @user293787 It think then your simply have to move some of coefficients from eliminate list to keep list. In your mentioned case. GroebnerBasis[{-expr + 2*A1^2 + A1*B2 + 2*B1^2 - B1*A2 + 2*C1^2 + C1*D2 + 2*D1^2, -h12 + A1*B2 - B1*A2 + C1*D2 - D1*C2, -h1^2 + A1^2 + B1^2 + C1^2 + D1^2}, {h12, h1, expr, D1, C2}, {A1, B1, C1, A2, B2, D2}, MonomialOrder -> EliminationOrder] I agree, however, that PolynomialReduce your suggest is a good approach. From my point of view this is a question of test, since computation of gb highly depends of order of variables.
– Acus
Commented Sep 30, 2022 at 14:34
• @user293787, Sorry, test->taste
– Acus
Commented Sep 30, 2022 at 14:40
• @userrandrand In complicated cases computed gb will have many elements, which may include initial expression (in my example denoted as expr). In this example elimination is trivial since computed gb has only single element (no choice). Therefore in hard cases there will be many variants and you have to decide which one is more suitable for your. Solve is not suitable for elimination (at least I don't know how to use it for the task). Also computation time (and answer) of GroebnerBasis depend very much on variables order.
– Acus
Commented Sep 30, 2022 at 15:46

Since OPs expressions and relations are all polynomials, this is a natural problem for PolynomialReduce and GroebnerBasis:

(* list all quantities that are zero *)
relations={A1^2+B1^2+C1^2+D1^2-h1^2,
A1*B2-B1*A2+C1*D2-D1*C2-h12};

(* construct a Groebner basis for these relations *)
variables={A1,B1,C1,D1,A2,B2,C2,D2,h1,h12};
gb=GroebnerBasis[relations,variables];

(* simplify expression *)
expression=2*A1^2+A1*B2+2*B1^2-B1*A2+2*C1^2+C1*D2+2*D1^2-D1*C2;
Last[PolynomialReduce[expression,gb,variables]]

(* 2 h1^2+h12 *)