# Replacing composite variables by a single variable

To replace a single variable by another variable, one can simply use the the replace all (/.) operator (e.g., x/(y*z) /. x -> w returns $\displaystyle \frac{w}{yz}$).

How does one replace an expression consisting of multiple variables? Trying to replace the denominator in the previous expression by a single variable fails with the following syntax:

x/(y*z) /. y*z -> w
x/(y*z) /. y*z :> w
x/(y*z) /. (y*z) -> w
x/(y*z) /. (y*z) :> w
x/(y*z) /. Times[y, z] -> w
x/(y*z) /. Times[y, z] :> w


Edit: By applying FullForm, I see that the variable substitution can be made by the following lengthy expression:

x/(y*z) /. Times[Power[y, -1], Power[z, -1]] -> w^-1


However, this now fails in a case such as the following:

(x + Log[y*z])/(y*z) /. Times[Power[y, -1], Power[z, -1]] -> w^-1


Now one must use something like the following (which does not work).

(x + Log[y*z])/(y*z) /. {Times[Power[y, -1], Power[z, -1]] -> w^-1, Times[y, z] -> w}


Is there a more general way to replace variables with delving into the full form representation?

-
The inverse operation can work, that is replacing $\frac{x}{w}$ to $\frac{x}{y*z}$. There must be a way to do it. –  CHM Mar 25 '12 at 3:43
Well in your example it does not work as Mathematica is rewriting the whole term inside the log expression as well. Something like this though will do the correct behavior: (x + Log[y*z])/(y*z) /. {z y -> w, 1/(z y) -> w} That is rewrite the y*z to w first and then rewrite the 1/(y*z). Basically you need to remember that Mathematica likes to treat all divisions as multiplications by the inverse. –  nixeagle Mar 25 '12 at 3:54
Becoming an FAQ hereabouts. Might have a look at this or that or the other. –  Daniel Lichtblau May 10 '12 at 14:31

You can't use replacements that way, because Mathematica does not do replacements on expressions the way they appear to you. To see what I mean, take a look at the FullForm of your expression:

x/(y*z) // FullForm
Out[1]= Times[x,Power[y,-1],Power[z,-1]]


Whereas, the replacement that you're using is Times[y, z].

In general, it is not a good idea to use approaches that exploit the structure of expressions to do mathematical replacements. You might think you have nailed the replacement down, but it will break for a slightly different equation or terms.

To do this in a fail safe manner, you can use Simplify as:

Simplify[x/(y z), w == y z]
Out[2]= x/w


For more complicated examples, you might have to use Eliminate. From the documentation:

Eliminate[{f == x^5 + y^5, a == x + y, b == x y}, {x, y}]
Out[3] = f == a^5 - 5 a^3 b + 5 a b^2


Also read the tutorial on eliminating variables.

-
+1 for "not a good idea in general". –  Oleksandr R. Mar 25 '12 at 3:49
Upvoted this response for answering a related question of mine. –  user1602 Jul 10 '12 at 4:49

Since nobody pointed this out I think there is still room for another reply. Note that this works fine

Unevaluated[(x + Log[y*z])/(y*z)] /. (y*z) :> w
(x + Log[w])/w


In more complex cases you may also need to use HoldPattern

Unevaluated[(x + Log[(y*z)/2])/((y*z)/2)] /. HoldPattern[((y*z)/2)] :> w

(x + Log[w])/w


This is not a panacea. Mathematica's pattern matching is purely syntactical so for more complicated replacement you need to use more algebraic functions. The key one is PolynomialReduce. This is what Simplify uses, but using Simplify for replacements is not a good idea in general since you can't readily predict the result (it depends on the setting of the option ComplexityFunction and others). There is a great deal about this in the MathGroup archives, particularly in posts by Daniel Lichtblau and a few of my own.

You will find a discussion and some useful links here.

-
Thanks for your post Andrzej. Do you recommend using PolynomialReduce for general replacements? I noticed that using Simplify is computationally demanding (compared to replace /.) even for very simple substitutions. –  user001 Mar 25 '12 at 8:42
Good answer, and it would be even better if you could provide some links to the discussions you refer to. –  Sjoerd C. de Vries Mar 25 '12 at 9:11

This stumped me for a few moments until I looked at the FullForm of your expression.

x/(y*z) // FullForm


yields

Times[x,Power[y,-1],Power[z,-1]]


Notice here that the variables are rewritten internally by Mathematica to read as

x*(1/y)*(1/z)


With this knowledge in hand we can now write a working replacement rule.

x/(y*z) /. 1/(y*z) -> w


And this will yield the expected result of

x w.


For mathematical expressions one ought to use Simplify.

Simplify[(x + Log[y*z])/(y*z),w==y*z]


which gives

(x+Log[w])/w

-
Blah, you edited your question just as I posted my answer! Give me a few on the updated question :) –  nixeagle Mar 25 '12 at 3:48
Thanks, I figured it out about the same time as you and RM. Sorry to edit. I'm hoping to find a general way to make a substitution that does not require analysis of the FullForm and construction of an elaborate replacement syntax. –  user001 Mar 25 '12 at 3:49
Actually I think RM has this nailed down. Use Simplify for mathematical expressions. I was going to add that to my answer as well, but looks like I've been beaten ;). –  nixeagle Mar 25 '12 at 3:57
As this has not happened before (no results in search), I think it qualifies for meta discussion. –  CHM Mar 25 '12 at 3:58

You are looking for a variable transformation, so I would do something like (if you know that y is not 0):

x/(y*z) /. z->w/y


In that way, you get rid of z, and if there is any other place in the expression where it appears, it will get replaced too.

-

I usually make replacements with the method like that of FJRA. However, just for completeness of this set of answers I would like to mention the ReplacePart method. For example, if our function is like this:

 expr = (x + Log[y*z/2])/(y*z);


the replacement may be done as follows:

 ReplacePart[expr, {{3, 2, 1} -> w/2, {1, 1} -> w/z}]

(*   (x + Log[w/2])/w *)

-

You may look at the function TermErsetzung I posted here.

So it will work like this:

TermErsetzung[w == y z, {y, z}][x/(y z)]
%[[1]


With the output:

{x/w}

x/w

-