1

Suppose you have the following expression:

expr = f[p^(3) * q^(5) * m] * f[p^(-2) * q^(-5) * m] * f[p^(1/2) * q^(1) * m] + 5 * f[p^(1) * q^(2) * n] * f[q^(-2) * n] + s * f[p^(h) * q^(r) * j] * f[p^(1-h) * q^(-r) * j].

Moreover, suppose that the function f is such that

f[p^(a) * q^(b) * x] * f[p^(1-a) * q^(-b) * x] == 1

for any value (numerical or symbolic) of the exponents a,b and for any x. This means that

expr == f[p^(1/2) * q^(1) * m] + 5 + s.

How can I teach Mathematica to recognise this property of f and then simplify expr according to it?

I tried to implement it as the following rule

/.f[p^(a_)*q^(b_)*x_]f[p^(1-a_)*q^(-b_)*x_]->1

but it doesn't work. It only works if you specify the numerical value of the exponents a and b, but not if you want them to be generic.

What is the right way to write such a rule?

FaMa
  • 11
  • 2

1 Answers1

0

The answer here may provide a solution : How to insert a subexpression into a larger expression in Mathematica? c/o Rojo

For example, using your expression expr and a larger expression A

expr = f[p^(a)*q^(b)*x] f[p^(1 - a)*q^(-b)*x];
A = 3 expr + z (f[p^(a)*q^(b)*x]) + y expr

doThat[expr_, vars_List] := Expand[Simplify[expr /. Flatten[
       Solve[# == ToString@#, First@Variables@#] & /@ vars]], 
    Alternatives @@ ToString /@ vars] /.
   Thread[ToString /@ vars -> vars];

done = doThat[A, {expr}];
ans = Simplify[done //. expr -> 1]

3 + y + z f[p^a q^b x]

The expected answer.

For general cases as per the comment, a pattern can be used, e.g.

expr = f[p^(a)*q^(b)*x] f[p^(1 - a)*q^(-b)*x];
A = 3 expr + z (f[p^(a)*q^(b)*x]) +
  y f[p^(h)*q^(l)*x] f[p^(1 - h)*q^(-l)*x];

done = doThat[A, {expr}];
ans = Simplify[done //.
   f[p^(a_)*q^(b_)*x] f[p^(1 - a_)*q^(-b_)*x] -> 1]

3 + y + z f[p^a q^b x]

But in the end it can simply be done by

A /. f[p^(a_)*q^(b_)*x] f[p^(1 - a_)*q^(-b_)*x] -> 1

3 + y + z f[p^a q^b x]

2nd edit

A = (3 f[p^(a)*q^(b)*x] f[p^(1 - a)*q^(-b)*x] +
   z (f[p^(a)*q^(b)*x]) +
   y f[p^(h)*q^(l)*x] f[p^(1 - h)*q^(-l)*x] f[p m])

A /. h -> 2 /. f[p^(a_)*q^(b_)*x_] f[p^(1 - a_)*q^(-b_)*x_] -> 1

3 + z f[p^a q^b x] + y f[m p] f[(q^-l x)/p] f[p^2 q^l x]

When h is 2 the second replacement no longer applies to the expression containing p^(1 - h) because the form has become p^(-1).

On the other hand, keeping the variables symbolic by using Z instead of 2

A /. h -> Z /. f[p^(a_)*q^(b_)*x_] f[p^(1 - a_)*q^(-b_)*x_] -> 1

3 + y f[m p] + z f[p^a q^b x]

Chris Degnen
  • 8,443
  • 2
  • 23
  • 40
  • Thank you for the answer! Actually I am not convinced it works. Indeed, if you use for example `A = 3 expr + z (f[p^(a)*q^(b)*x]) + y f[p^(h)*q^(l)*x] f[p^(1 - h)*q^(-l)*x]`, which should give the same answer you got, the output is `3 + z f[p^a q^b x] + y f[p^(1 - h) q^-l x] f[p^h q^l x]`. – FaMa Mar 29 '22 at 20:14
  • Ok, looks like you can just use the pattern anyway. – Chris Degnen Mar 29 '22 at 22:18
  • It still does not work properly. If you want to apply such a routine to a specific expression, whose exponents are numbers, mathematica will not recognise the pattern `f[p^(a_)*q^(b_)*x_] f[p^(1 - a_)*q^(-b_)*x_] -> 1`. For example, take `A = (3 f[p^(a)*q^(b)*x] f[p^(1 - a)*q^(-b)*x] + z (f[p^(a)*q^(b)*x]) + y f[p^(h)*q^(l)*x] f[p^(1 - h)*q^(-l)*x] f[p m]) /. h -> 2`. The routine output will then be `3 + y f[m p] f[(m q^-l)/p] f[m p^2 q^l] + z f[p^a q^b x]`. Clearly mathematica is not applying the general rule to specific cases. This is precisely where my question originated. – FaMa Mar 30 '22 at 06:13
  • I used your new example - see 2nd edit. It seems to work. – Chris Degnen Mar 30 '22 at 06:20
  • My example set `h` to a specific value, i.e. 2. You instead set `expr` to be 2, which is not different from what we discussed before. – FaMa Mar 30 '22 at 06:29
  • I will try to better explain what I need: given an expression `A` containing sums and products of the function `f`, I want Mathematica to recognise every time there is a combination of the type `f[p^(a_)*q^(b_)*x_] f[p^(1 - a_)*q^(-b_)*x_]` and set it to be 1. Inside `A` the function `f` can appear with numerical exponents for `p,q,...`, so Mathematica has to set `f[p^(a_)*q^(b_)*x_] f[p^(1 - a_)*q^(-b_)*x_]->1` whenever the specific numerical exponents `a,b` satisfy this generic relation. – FaMa Mar 30 '22 at 06:35
  • I have edited my 2nd edit to show the effect of `h -> 2`. – Chris Degnen Mar 30 '22 at 08:53
  • Clearly I did not explain well what I needed. I will edit my question. Hopefully it will be clearer. – FaMa Mar 30 '22 at 15:59