# Replace a randomly chosen part of an expression

Given an arbitrary Mathematica expression, how can I choose a random part of the expression and replace it with another symbol of my choosing?

For example, given $$a x^3 +2y\cos(x)- \tanh(x^{y+3})/(x^4-\sqrt{b})$$, I want to select a single randomly chosen part of the expression that involves an $$x$$ term and replace it with $$\mathbf{u}$$. This part could be any sub-expression with an $$x$$ such as $$x^3,a x^3, 2y\cos(x),\cos(x),x, x^{y+3},\tanh(x^{y+3}),x^4,(x^4-\sqrt{b})$$, or even the whole expression. Examples:

$$\mathbf{u}\\ \mathbf{u} +2y\cos(x)- \tanh(x^{y+3})/(x^4-\sqrt{b})\\ a x^3 +2y\cos(x)- \tanh(x^{y+3})/\mathbf{u}\\ a x^3 +2y\cos(x)- \tanh(\mathbf{u})/(x^4-\sqrt{b})\\ a x^3 +\mathbf{u}- \tanh(x^{y+3})/(x^4-\sqrt{b})\\ a x^3 +2y\cos(x)- \mathbf{u}/(x^4-\sqrt{b})\\ \mathbf{u} - \tanh(x^{y+3})/(x^4-\sqrt{b})\\ a x^3 + 2y\cos(x) - \mathbf{u}\\ a x^3 + \mathbf{u}$$

Also I'd like to know which subexpression was chosen for replacement with $$\mathbf{u}$$. So far I've been able to generate random replacements like this:

expr = a x^3 + 2 y Cos[x] - Tanh[x^(y + 3)]/(x^4 - Sqrt[b]);
Table[ReplacePart[expr,
RandomChoice[Position[expr, _, Heads -> False]] -> u],
1000] // DeleteDuplicates


...but I have not been able to 1) only select expressions involving $$x$$, and 2) record which subexpression was chosen.

For clarification, the following image shows the expression tree for the example I gave above. Green nodes are eligible for replacement with $$\mathbf{u}$$ because they contain $$x$$ or some sub-expression involving $$x$$. Red nodes do not contain any $$x$$ and are not eligible for replacement:

• Is this in relation to (223870)? Jun 12, 2020 at 21:00
• @MarcoB yes, but I think it's a useful question in its own right, and applies to other things like fuzzing and genetic algorithms - it would be a bit hidden if I explored it in that question. Jun 12, 2020 at 21:02
• Wouldn't you need to break all the terms of a power, like $x^3 = x x x$ in the expression first, because it is possible to only replace one $x$ and keep the others in the power also? For example, you could replace $x^3$ as $u x^2$.
– Moo
Jun 12, 2020 at 22:43
• @Moo Good point. That would be interesting to see if you know how to implement it, but it's probably quite tricky. Jun 12, 2020 at 23:04

Here's one way:

expr = a x^3 + 2 y Cos[x] - Tanh[x^(y + 3)]/(x^4 - Sqrt[b]);
pos = Position[expr, x];
thisPos = RandomChoice[pos];
ReplacePart[expr, Drop[thisPos, -RandomInteger[{0, Length[thisPos] - 1}]] -> u]


Each time you execute it, you select a random term containing x from the expression and replace it with u.

• This will not select parts like Cos[x] or Tanh[x^(y+3)] - it will just replace the 'leaf' terms x. I want to replace any part of the expression tree provided it involves an x term at some leaf. Jun 12, 2020 at 21:05
• I don't understand the requirement... every possible combination of symbols in the expression "involve x" in some way. If you can replace a x^2 with u then why not replace Co[x]+a x^2 with u? Jun 12, 2020 at 21:08
• When I execute your code many times it just replaces a random $x$ with $u$. every possible combination of symbols in the expression "involve x" in some way - take $(y+3)$ and $2y$, they do not involve $x$. If you take the TreeForm of the expression, I want to replace a random node with $u$ provided that node is $x$ or it has some descendent node $x$. So that also covers things like replacing Tanh[x^(y+3)], x^(y+3), x by itself, or even the whole expression since it trivially involves $x$. Jun 12, 2020 at 21:14
• Thanks, your edit mostly works. The only slight problem is it sometimes chooses sub-expressions like this one for example 2 a x^3 + 2 y Cos[x], which doesn't appear in the expression and replaces nothing. I'm not sure why as I tried a similar approach moments ago and it happened to me also. Jun 12, 2020 at 21:54
• OK.. but the expression 2 a x^3 + 2 y Cos[x] certainly "involves x" in a nontrivial way. Jun 12, 2020 at 21:56

Depending on your definition of random the method from bill s might have a problem in that some elements can be selected in more than one way. For example in your expr the element at position {3} can be selected from either {3, 2, 1, 2, 1} or {3, 3, 1, 1}. If we use Position to find all elements directly (rather than Dropping afterward) we avoid this.

expr = a x^3 + 2 y Cos[x] - Tanh[x^(y + 3)]/(x^4 - Sqrt[b]);

pos = Most @ Position[expr, s_ /; ! FreeQ[s, x]]

ReplacePart[expr, RandomChoice[pos] -> u]


This never seems to replace the whole expression with $$u$$, even if I run it 100,000 times. Shouldn't that happen, as the Plus in the top of the TreeForm is eligible for replacement too?

I did not consider the whole expression to be a part. The term {} in the return of Position represents the whole expression, but I dropped it using Most because ReplacePart cannot use this specification.

If you want to include that as a possibility I propose this instead:

pos = Position[expr, s_ /; ! FreeQ[s, x]]

Module[{x = expr}, x[[## & @@ RandomChoice @ pos]] = u; x]

• This is exactly why they tell you not to accept answers too quickly! Jun 12, 2020 at 23:46
• This never seems to replace the whole expression with $u$, even if I run it 100,000 times. Shouldn't that happen, as the Plus in the top of the TreeForm is eligible for replacement too? Jun 12, 2020 at 23:50
• @flinty See the update. Jun 13, 2020 at 0:50