Implementing rules on functions in Mathematica

Viewed 101

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?

1 Answers

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]

Related