32
$\begingroup$

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?

$\endgroup$
3
  • $\begingroup$ The inverse operation can work, that is replacing $\frac{x}{w}$ to $\frac{x}{y*z}$. There must be a way to do it. $\endgroup$
    – CHM
    Commented Mar 25, 2012 at 3:43
  • 1
    $\begingroup$ 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. $\endgroup$
    – nixeagle
    Commented Mar 25, 2012 at 3:54
  • $\begingroup$ Becoming an FAQ hereabouts. Might have a look at this or that or the other. $\endgroup$ Commented May 10, 2012 at 14:31

6 Answers 6

50
$\begingroup$

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.

$\endgroup$
2
  • 1
    $\begingroup$ Upvoted this response for answering a related question of mine. $\endgroup$
    – user1602
    Commented Jul 10, 2012 at 4:49
  • $\begingroup$ I tried it on something, but it didn't get rid of the gamma. Simplify[Sin[\[Gamma]]+\[Gamma]^2(1+\[Beta]), {\[Gamma] == 1/Sqrt[1-\[Beta]^2],\[Beta]\[Element]Reals,\[Gamma]\[Element]Reals}] I didn't want to do Eliminate because I want Sin[\[Gamma] ] to be retained. Any suggestions? $\endgroup$
    – ions me
    Commented Sep 24, 2021 at 3:04
18
$\begingroup$

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.

$\endgroup$
3
  • $\begingroup$ 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. $\endgroup$
    – user001
    Commented Mar 25, 2012 at 8:42
  • $\begingroup$ Good answer, and it would be even better if you could provide some links to the discussions you refer to. $\endgroup$ Commented Mar 25, 2012 at 9:11
  • $\begingroup$ @Andrzej Just came across this--very nice! But why do you use RuleDelayed (:>), rather than just Rule (->)? In all the examples I've tried, the results with the two are identical. Are there instances in which the latter breaks? [If the two give identical results, I'd prefer Rule over RuleDelayed, since the former is conceptually simpler.] $\endgroup$
    – theorist
    Commented Mar 14, 2018 at 4:34
7
+50
$\begingroup$

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.

$\endgroup$
0
6
$\begingroup$

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
$\endgroup$
4
  • $\begingroup$ Blah, you edited your question just as I posted my answer! Give me a few on the updated question :) $\endgroup$
    – nixeagle
    Commented Mar 25, 2012 at 3:48
  • $\begingroup$ 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. $\endgroup$
    – user001
    Commented Mar 25, 2012 at 3:49
  • 2
    $\begingroup$ 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 ;). $\endgroup$
    – nixeagle
    Commented Mar 25, 2012 at 3:57
  • $\begingroup$ As this has not happened before (no results in search), I think it qualifies for meta discussion. $\endgroup$
    – CHM
    Commented Mar 25, 2012 at 3:58
3
$\begingroup$

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 *)
$\endgroup$
3
$\begingroup$

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

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.