# ReplaceList doesn't apply rules down to subparts

Somewhat related to a previous question, I'm experimenting with ReplaceList to get the list of all possible transformations we can obtain by applying a rule to an expression. But I don't manage to make it work as expected:

expr := 1+Cos[ω t - π/4 + 3π/4]
rule := Cos[a_ + b_] -> X[a,b]
ReplaceList[expr,{ rule }]


I expected the result:

>     { 1+X[ω t - π/4, 3π/4], 1+X[ω t, -π/4 + 3π/4] }


{}


Why is Mathematica unable to apply rule on expr? How should I fix my code to obtain the expected result?

As an extra requirement, I missed the fact that ReplaceAll like Replace "does not map down to subparts".

I'm probably looking for a mix between ReplaceList and Cases (?)

As per comment, to avoid Mathematica to rewrite the expression as a sinus, I tried wrapping it inside various Hold* functions--in no case, the rule is applied.

expr := Hold[1+Cos[ω t - π/4 + 3π/4]]

expr := HoldForm[1+Cos[ω t - π/4 + 3π/4]]

expr := HoldComplete[1+Cos[ω t - π/4 + 3π/4]]

• because mathematica automatically rewrites expr as Sin[t \[Omega]] – Nasser Dec 13 '19 at 22:38
• Because expr evaluates to -Sin[t ω], which does not contain any expression with Cos head, so nothing in it matches the left-hand side of your rule? I also find your rule definition using SetDelayed somewhat odd, so I wonder whether there might not be a misunderstanding there. Why should it matter that rule is evaluated every time it is called? – MarcoB Dec 13 '19 at 22:39
• Thanks both of you for the comments. @Nasser, I tried wrapping the expression definition in Hold, HoldForm and HoldComplete. It prevents rewriting the expression as as sinus--but the rule still doesn't apply. – Sylvain Leroux Dec 13 '19 at 22:44
• @Marco "I also find your rule definition using SetDelayed somewhat odd, so I wonder whether there might not be a misunderstanding there." Indeed. What would be the consequences of using SetDelayed instead of Set? – Sylvain Leroux Dec 13 '19 at 22:45
• @Sylvain I think you might want RuleDelayed (:>) rather than SetDelayed, i.e. you would want to delay the evaluation of the right-hand side of the rule until a and b have been given values. I have put the rest in an answer cause it was getting too long for comments. – MarcoB Dec 13 '19 at 22:51

As discussed in comments, you have to somehow prevent MMA from rewriting your Cos expression, which you can accomplish with a Hold function. I am still not sure that I understand the intended outcome, but I wonder if this is what you are after:

Clear[expr, rule]
expr = HoldForm@Cos[ω t - π/4 + 3 π/4]
rule = HoldForm@Cos[a_ + b_] :> X[a, b]
ReplaceList[expr, rule]

(* Out:
{X[t ω, π/2], X[-(π/4), (3 π)/4 + t ω],
X[(3 π)/4, -(π/4) + t ω],
X[-(π/4) + t ω, (3 π)/4],
X[(3 π)/4 + t ω, -(π/4)], X[π/2, t ω]}
*)

• Yes, that's what I was looking for. One question though: why in another answer given by @ChrisDegnen he has to use ReleaseHold whereas you don't need it? I also notice in his answer - π/4 + 3 π/4 was replaced by -π/2 (something I don't want). Is that related to ReleaseHold? – Sylvain Leroux Dec 13 '19 at 22:56
• Ouch: I failed to notice that ReplaceAll does not apply to subparts. I've edited the question accordingly. Sorry for having wasted your time. – Sylvain Leroux Dec 13 '19 at 23:20

expr := Hold[Cos[ω t - π/4 + 3 π/4]]
rule := Cos[a_ + b_] :> X[a, b]
ReleaseHold[ReplaceAll[expr, {rule}]]

X[t ω, π/2]


expr := Hold[Cos[ω t - π/4 + 3 π/4]]
rule := Cos[a_] :> (a /. List -> X)
ReleaseHold[ReplaceAll[expr /. Plus -> List, {rule}]]

X[t ω, -(π/4), (3 π)/4]


I'm sure there is a simpler way.

• Thanks, @Chris. Is there a way to prevent - π/4 + 3 π/4 to be reduced to -π/2? – Sylvain Leroux Dec 13 '19 at 22:58
• I failed to notice that ReplaceAll does not apply to subparts. I've edited the question accordingly. Sorry @Chris for having wasted your time. – Sylvain Leroux Dec 13 '19 at 23:20

You may be trying to solve the wrong problem. It is better to define a rule that applies to all the forms in which your expression might appear. For example

expr = Cos[ω t - π/4 + (3 π)/4]
(* -Sin[t ω] *)

rule = {Cos[a_ + b_.] -> X[a, b], Sin[a_ + b_.] -> X[a, -(π/2) + b]};

expr /. rule
(* -X[t ω, -(π/2)] *)

• Thnaks @mikado. I don't have checked your answer yet--but I wanted to warn you ASAP I've edited the question because I failed to notice initially Replace was not replacing down to subexpressions. Sorry for that. – Sylvain Leroux Dec 13 '19 at 23:22

Perhaps this approach is more in keeping with your coding style.

expr = Inactivate[1 + Cos[ω t - π/4 + 3 π/4], Cos]
rule = Inactive[Cos][Plus[args__]] -> X[args]
ReplaceAll[expr, rule]


1 + X[π/2 + t ω]

Notes

• Personally, I prefer the short form
expr /. rule

to using ReplaceAll.
• The revised rule you see above was written after I inspected
expr // FullForm


Plus[1, Inactive[Cos][Plus[Times[Rational[1, 2], Pi], Times[t, ω]]]]