4
$\begingroup$

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] }

But instead, I obtain:

{}

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]]
$\endgroup$
6
  • 2
    $\begingroup$ because mathematica automatically rewrites expr as Sin[t \[Omega]] $\endgroup$
    – Nasser
    Commented Dec 13, 2019 at 22:38
  • 1
    $\begingroup$ 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? $\endgroup$
    – MarcoB
    Commented Dec 13, 2019 at 22:39
  • $\begingroup$ 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. $\endgroup$ Commented Dec 13, 2019 at 22:44
  • $\begingroup$ @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? $\endgroup$ Commented Dec 13, 2019 at 22:45
  • 1
    $\begingroup$ @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. $\endgroup$
    – MarcoB
    Commented Dec 13, 2019 at 22:51

4 Answers 4

2
$\begingroup$

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 ω]}
*)
$\endgroup$
2
  • $\begingroup$ 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? $\endgroup$ Commented Dec 13, 2019 at 22:56
  • $\begingroup$ Ouch: I failed to notice that ReplaceAll does not apply to subparts. I've edited the question accordingly. Sorry for having wasted your time. $\endgroup$ Commented Dec 13, 2019 at 23:20
2
$\begingroup$

Try this instead

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

In reply to the comment

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.

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

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)] *)
$\endgroup$
1
  • $\begingroup$ 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. $\endgroup$ Commented Dec 13, 2019 at 23:22
1
$\begingroup$

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, ω]]]]

$\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.