It is possible to use patterns in assumptions such as f[_]>0. This does not seem to be explained in the documentation but is for instance pointed out in Is it possible to add some pattern to $Assumptions.

However, when trying to use this it seems to be very unreliable (perhaps that is why it is undocumented). For example if I want to simplify

 expr=f[a]^(p1 + p2) f[b]^(p1 - p2) f[c]^(p1 + p2) d^(p1 - p2)

one finds that

Simplify[expr, {Element[f[___], Reals], f[__] > 0, 
  c > 0, d > 0, p1 > 0, p2 > 0}]

does not combine f[a] and f[c] into one power while

Simplify[expr /. f[x_] :> x, {a > 0, b > 0, c > 0, d > 0, p1 > 0, 
  p2 > 0}]

does the job nicely. The only difference is that we changed the name of the variable f[x]->x and that we wrote out the assumptions explicitly. How do we get this to work for an assumption with a pattern for f[__]. It was pointed out in the linked question that perhaps the difference was due to Mathematica being more conservative in its assumptions on variables that aren't simple Symbols and that therefore the assumption Element[f[___], Reals] needs to be explicitly added. However we see here that doing this does not solve things.

I know that for such a simple expression I could easily write a replacement rule that does the simplification that I want to do. My point is that Simplify already knows how to do many useful simplifications and I don't want to have to write them all by hand for every simplification that I need. The point of Simplify is that you can use it on big expressions where you don't know what the exact simplifications you want to do are. I would like the power of Simplify but for expressions of the form f[uniqueLabel] where it knows f[uniqueLabel]>0.


2 Answers 2


I think the best solution is to collect all expressions matching the pattern by using Reap and Sow. One can than convert these to an explicit assumption table to be used in Simplify. For the example question this would look like:

  pattAssumptions_] := (Simplify[#1, (Greater[#, 0] &) /@ 
      Flatten[#2]] &) @@ Reap[expr /. (x : pattAssumptions) :> Sow[x]]

Applied like simplify[testExprSimpleSymbols, f[_]] it gives the desired output. Moreover, it is easily extendable to any case. (Although you will need to change the input of the function to accommodate putting different assumptions on different variables. This should also be an easy adjustment (use Sow's with different tags etc). The above gives a blueprint of the general idea.

  • $\begingroup$ Instead of Repace+Sow+Replace+DelayedRule, you could simply use Cases... $\endgroup$ Mar 20, 2019 at 21:21
  • 1
    $\begingroup$ Ah thanks, yes that sounds more elegant. edit: Except it doesn't seem to work. How would you use Cases? 2nd edit: ah I would need to change the levelspec $\endgroup$
    – Kvothe
    Mar 21, 2019 at 10:01
  • $\begingroup$ @HenrikSchumacher, thanks I have been doing that wrong for quite some time and it always felt too clumsy. I had a feeling that there was a better way but I hadn't thought of Cases with levelspec=Infinity. I had thought of asking this on stackexchange but you have saved me the trouble. $\endgroup$
    – Kvothe
    Mar 21, 2019 at 10:09

The following code:

Simplify[expr, {f[a] > 0, f[b] > 0}] // InputForm


(d*f[b])^(p1 - p2)*(f[a]*f[c])^(p1 + p2)

which seems to be what you wanted.

Assumptions in general are not patterns. So you have to use {a > 0, b > 0} as assumption list instead of {_Symbol > 0}. Same thing with {f[a] > 0, f[b] > 0} instead of {f[_] > 0}. The situation for Integrate[] is somewhat different because {f[_] > 0, Element[f[_], Reals]} apparently does work, but the use of patterns in assumptions is undocumented as far as I know. It makes you wonder why it is not allowed with some rare exceptions. Simplification turns out to be very complicated.

However, Simplify[] has an option you may use. Try this code:

trans[x_ u1_^v_ u2_^v_] := x (u1 u2)^v;
Simplify[expr, TransformationFunctions -> {Automatic, trans}]

which returns your expected result. If you want to be more careful try

trans[ x_ u1_^v_ f[u2_]^v_ ] := x (u1 f[u2])^v;

or some variant instead. Of course, if you are creative, there are other ways to make Mathematica do what you want, but with diminishing returns, I think.

  • $\begingroup$ Thanks, yes I solved the problem in the same way myself and maybe I should have included that in the question. But this won't always work. The next time the simplification will be different and I don't want to rewrite the whole Simplify function myself case by case. $\endgroup$
    – Kvothe
    Mar 20, 2019 at 9:06

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.