3
$\begingroup$

I want to divide a product into two pieces, one is the terms of form f[x, _], the other is the leftover factors free of x:

rule = Times[fac_., (fxs : Repeated[f[x, _]])] /; 
        FreeQ[Times[fac], x] :> FAC[Times[fac]]*FX[Times[fxs]]

For example:

Replace[f[y, 1]*f[x, 1]*f[x, 2], rule]

(* FAC[f[y, 1]] FX[f[x, 1] f[x, 2]] *)

I use fac_. in rule because there may be no other coefficients present. For example, I hope

Replace[f[x, 1]*f[x, 2], rule]

returns

FX[f[x, 1] f[x, 2]]

but the actual output is

(* f[x, 1] f[x, 2] *)

In fact, the following returns False:

MatchQ[f[x, 1]*f[x, 2], 
       Times[fac_., (fxs : Repeated[f[x, _]])] /; FreeQ[Times[fac], x]]

It seems that _. does not work. Why?

$\endgroup$
8
  • $\begingroup$ Can you give an example that contains both factors with x and ones without x, together with your expected output? $\endgroup$
    – MarcoB
    Commented Oct 2 at 13:57
  • $\begingroup$ @MarcoB Actually OP has provided both. I've modified the typesetting a little to make it more obvious. $\endgroup$
    – xzczd
    Commented Oct 2 at 14:30
  • 1
    $\begingroup$ Condition seems part of the problem. Try it with Optional[fac_?(FreeQ[#1, x] &)] instead of fac_. ... /; ... $\endgroup$
    – Michael E2
    Commented Oct 2 at 19:36
  • $\begingroup$ @Michael E2, you are right. I add Condition for Optional in a wrong form. But unluckly, your suggestion does not work either. Now I use a a rule list for my exception {HoldPattern@Times[fxs : Repeated[f[x, _]]] :> FX[Times[fxs]], Times[fac_ /; FreeQ[x][fac], (fxs : Repeated[f[x, _]])] :> FAC[Times[fac]]*FX[Times[fxs]] }. But I still want to know how to use Optional with Condition in this example. $\endgroup$
    – Crack-Hu
    Commented Oct 3 at 6:06
  • 1
    $\begingroup$ My understanding is, the "apply to" in document actually means "directly apply to". We can see the example is x_ : 1 /; OddQ[x] (Condition and Optional are next to each other), and this results in a warning. It's not your case, I think. $\endgroup$
    – xzczd
    Commented Oct 5 at 14:24

2 Answers 2

2
$\begingroup$

The OP requires Condition, and probably they require Optional, too. If not, then this:

Since Times[] is 1:

rule = Times[fac___, (fxs : f[x, _] ..)] /; FreeQ[Times[fac], x] :> 
   FAC[Times[fac]]*FX[Times[fxs]];
Replace[f[y, 1]*f[y, 3]*f[x, 1]*f[x, 2], rule]
(*  FAC[f[y, 1] f[y, 3]] FX[f[x, 1] f[x, 2]]  *)

Replace[f[x, 1]*f[x, 2], rule]
(*  FAC[1] FX[f[x, 1] f[x, 2]]  *)

This technically meets the requirements of Condition and Optional, but in light of the foregoing, it feels a cheat:

rule = Times[Optional[fac___, 1], (fxs : f[x, _] ..)] /; 
   FreeQ[Times[{fac}], x] :> FAC[Times[fac]]*FX[Times[fxs]]
$\endgroup$
2
  • $\begingroup$ Yeah, You are right, good solution for my purpose, I should have thought of that earlier. Thank you so much $\endgroup$
    – Crack-Hu
    Commented Oct 5 at 11:32
  • $\begingroup$ But, to go further, how to make Replace[f[x, 1], rule] return FAC[1]*FX[f[x, 1]]? $\endgroup$
    – Crack-Hu
    Commented Oct 5 at 11:48
2
$\begingroup$

Maybe like this (post-process to taste)?

isolateXterms[expr_] := Module[{vars = Variables[expr]},
  vars = Complement[vars, Select[vars, ! FreeQ[#, x] &]];
  FactorTermsList[expr, vars]
  ]
isolateXterms[f[y, 1]*f[x, 1]*f[x, 2]]

(* Out[421]= {1, f[x, 1] f[x, 2], f[y, 1]} *)
$\endgroup$

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.