Matching (y/x)^u terms wherever the appear in an expression

At least one of the problems you are encountering is that -2 and -x do not share the same structure:

{-2, -x} // FullForm
List[-2, Times[-1, x]]

You can not destructure -2 using patterns. You can check numerically however:

(y/x)^2 /. x^a_. y^b_. /; b == -a :> t^b
t^2

Remember also that a matched expression is not further replaced, so you may need ReplaceRepeated. Applied to your examples:

(1 + 2 (y^2/x^2))/(2 (y/x)) //. x^a_. y^b_. /; b == -a :> t^b

y/x + Sqrt[1 + (y/x)^2] //. x^a_. y^b_. /; b == -a :> t^b
(1 + 2 t^2)/(2 t)

t + Sqrt[1 + t^2]

A second potential problem is operating on a manually entered held form such as HoldForm[(1 + 2 (y^2/x^2))/(2 (y/x))] without realizing that this can have a very different internal form compared to an evaluated expression. Compare:

foo = HoldForm[(1 + 2 (y^2/x^2))/(2 (y/x))];
bar = HoldForm @@ {(1 + 2 (y^2/x^2))/(2 (y/x))};

foo // TreeForm
bar // TreeForm

enter image description here

enter image description here


I would be remiss not to mention that general algebraic manipulation should not be done with pattern matching if at all avoidable. See for example Replacing composite variables by a single variable and be aware of:

  • Can I simplify an expression into form which uses my own definitions?

Other things to be aware of:

  • More general pattern fails to match everything the more specific pattern does.
  • Pattern matching on Orderless functions inside Hold

A simple solution: replace y with t x, and if there are any cases of t x hanging around with the x not cancelling, replace them with y.

(expression /. {y -> t x}) /. t x -> y

Testing it on some examples:

((1 + 2 (y^2/x^2))/(2 (y/x)) /. {y -> t x}) /. t x -> y
(y/5 /. {y -> t x}) /. t x -> y
(x/y /. {y -> t x}) /. t x -> y
(y/x + Sqrt[1 + (y/x)^2] /. {y -> t x}) /. t x -> y

(1 + 2 t^2)/(2 t)

y/5

1/t

t + Sqrt[1 + t^2]

I would imagine that this is unlikely to be very robust. But I haven't tested on any convoluted examples.

Edit: To deal with the xs left at the end, just replace them all with y/t

r[expr_] := expr /. {y -> t x} /. {t x -> y} /. {x -> y/t}

Then, in addition to the above examples, we get

r[(y/x)*y]
r[y^4/x^3]

t y

t^3 y


I know, this is not really the answer to your question. But at least in this specific problem, this helps:

expr /. {y -> t x}

Next try:

r = {
   Times[z___, Power[x, k_], Power[y, l_], w___] :> If[k == -l,
     Times[z, Power[t, l], w],
     Times[z, Power[x, k], Power[y, l], w]
     ],
   Times[z___, x, Power[y, -1], w___] :> Times[z, 1/t, w],
   Times[z___, Power[x, -1], y, w___] :> Times[z, t, w]
   };

x/y //. r
y^2/x^2 //. r
y^3/x^2 //. r
(1 + 2 (y^2/x^2))/(2 (y/x)) //. r
y/x + Sqrt[1 + (y/x)^2] //. r

(* 1/t *)
(* t^2 *)
(* y^3/x^2 *)
(* (1 + 2 t^2)/(2 t) *)
(* t + Sqrt[1 + t^2] *)

The second branch of the If statement can be used to further elaborate on the third example. But admittedly, this is starting to get complicated...