# Why does using ReplaceAll twice produce a different result?

Why does this:

Solve[a x^4 + b x^3 + c x^2 + d x + e == 0,  x] /.
{2 c^3 - 9 b c d + 27 a d^2 + 27 b^2 e - 72 a c e -> F}


produce a different result from this?

Solve[a x^4 + b x^3 + c x^2 + d x + e == 0,  x] /.
{2 c^3 - 9 b c d + 27 a d^2 + 27 b^2 e - 72 a c e -> F} /.
{2 c^3 - 9 b c d + 27 a d^2 + 27 b^2 e - 72 a c e -> F}

-
... because the first replacement modifies the original expression? It's a bad idea to use replacement rules for algebraic manipulations. Replacement rules work at the language level, using the structure in FullForm. It does not care about any mathematical structure visible to you (except when it happens to coincide). –  rm -rf Dec 2 '13 at 4:00
Then how should I go about this type of algebraic replacement operation in Mathematica? –  David Zhang Dec 2 '13 at 4:13
It's usually problem dependent, but common approaches involve using Solve, Eliminate, Reduce, GroebnerBasis, etc. You might find some useful posts in algebraic-manipulations (perhaps by Daniel Lichtblau or Artes). –  rm -rf Dec 2 '13 at 4:15
You can also use Simplify with TransformationFunctions -> {xf}, where xf is defined by xf[2 c^3 - 9 b c d + 27 a d^2 + 27 b^2 e - 72 a c e + rest___] := F + rest and xf[expr_] := expr. Look up the options to Simplify. –  Michael E2 Dec 2 '13 at 4:29

The problem is that the expression has parts of the form

pat + Sqrt[stuff + (pat)^2]


where pat is Plus[2 c^3, -9 b c d,…]. That means the above has the form

Plus[2 c^3, -9 b c d,…, Sqrt[Plus[…, Power[Plus[2 c^3, -9 b c d,…], 2]]


Mathematica grabs the whole Plus but replaces only the terms that match pat. What's important is that the rest of the whole Plus expression is not looked at further, so the part inside Sqrt is not replaced on the first Replace.

Minimal example:

a + b + Sqrt[(a + b)^2 + c] /. a + b -> F
(* Sqrt[(a + b)^2 + c] + F *)

% /. a + b -> F
(* F + Sqrt[c + F^2] *)


Since there's no limit to the depth pat may appear, ReplaceRepeated is a way to ensure that all possible matches are replaced.

a + b + Sqrt[(a + b)^2 + c] //. a + b -> F
(* F + Sqrt[c + F^2] *)


Another way I mentioned in a comment is to use Simplify with TransformationFunctions. With TransformationFunctions -> {xf}, only the transformation xf will be tried and it's not too slow.

Clear[xf];
xf[2 c^3 - 9 b c d + 27 a d^2 + 27 b^2 e - 72 a c e + rest___] := F + rest;
xf[expr_] := expr;
Simplify[Solve[a x^4 + b x^3 + c x^2 + d x + e == 0, x], TransformationFunctions -> {xf}]
(* output omitted *)


To include the regular simplification transformations, include Automatic in the list. This took about 13 sec., since the expressions from Solve are fairly long.

Simplify[Solve[a x^4 + b x^3 + c x^2 + d x + e == 0, x],
TransformationFunctions -> {Automatic, xf}]
(* output omitted *)

-

the result of Solve[a x^4 + b x^3 + c x^2 + d x + e == 0, x] produces instances of parts with form 2 c^3 - 9 b c d + 27 a d^2 + 27 b^2 e - 72 a c e. The first application of the replacement rule modifies them all to F. The resulting expression is then not returned 'as is' but is put in standard form. This is similar to the modification when you enter (a + b) + (a + c) and get as reply 2a + b + c. Now this standard form happens to again produce 2 c^3 - 9 b c d + 27 a d^2 + 27 b^2 e - 72 a c e, but only after the replacement rule has done its job. So you need (want?) the //. (or ReplaceRepeated) operation in this case. Even then, using a Simplify on the result could again generate parts that are replaceble by 'previous replacement rules'.

-