2
$\begingroup$

Given three expressiones as

exp1 = x y z*Exp[-t/(x^2 + y^2)] + 
 x/(y + z) Cos[(2 \[Pi])/T t] + (x z)/(y + z) Sin[(2 \[Pi])/T t] + 
 x y z/(x + y + z^2);
exp2 = E^(-(t/(x^2 + y^2))) x y z + (x y z)/(x + y + z^2);
exp3 = (x y z)/(x + y + z^2) + (x Cos[(2 \[Pi] t)/T])/(y + z) + (
   x z Sin[(2 \[Pi] t)/T])/(y + z);

How to split it into four parts and get the coefficients of Exp[x_], Sin[x_], Cos[x_], and others?

The expected three result are

coeff1 = {xyz, x/(y + z), (x z)/(y + z), x y z/(x + y + z^2)};
coeff2 = {(x y z)/(x + y + z^2), x y z, 0, 0};
coeff3 = {(x y z)/(x + y + z^2), 0, x/(y + z), (x z)/(y + z)};

I try

split = (a_ + b_*Exp[x_] + c_*Cos[y_] + d_*Sin[z_] -> {a, b, c, d});
exp1/.split
exp2/.split
exp3/.split

then the first return is correct as expected, however, the second and third just return what I input. So how to fix the rule? Thank you!

$\endgroup$
3
$\begingroup$

Explanation

The problem is that pattern matching in Mathematica is purely structural - this means that e.g. the pattern a_ + b_ * f[_] will not match 3 (even though you could set b to 0 from a mathematical point of view):

split = a_ + b_*f[_] :> {a, b};
1 + 3 f[x] /. split
3 /. split
(* {1, 3} *)
(* 3 *)

To circumvent this, we can use Optional to indicate that a given part of the pattern can be omitted:

split = a_ + HoldPattern@Optional[b_*f[_], 0 f[_]] :> {a, b};
1 + 3 f[x] /. split
3 /. split
(* {1, 3} *)
(* {3, 0} *)

Note the use of HoldPattern to prevent 0 f[_] from evaluating to 0. You might ask "why do we even need the second argument of Optional? After all, Plus has a global Default value of 0 set." However, this does not work:

split = a_ + Optional[b_*f[_]] :> {a, b};
1 + 3 f[x] /. split
3 /. split
(* {1, 3} *)
(* 3 *)

As far as I can tell, this is because the default value 0 does not match the pattern b_*f[_], which prevents Optional from working, as noted by @LeonidShifrin here:

This feature of the pattern-matcher is not very widely known, so I will stress it again: the default value for the (optional) pattern x:ptrn:default must match ptrn. For another example of such behavior, see this Mathgroup discussion.

Now there was some change regarding this, but it does not appear to affect this particular case.

We are also using the (undocumented?) fact that Optional will set the values of omitted pattern variables according to the default value:

{} /. {Optional[{a_, f[b_]}, {aDef, f[bDef]}]} :> {a, b}
(* {aDef, bDef} *)

Summary

  • We need an explicit default value for Optional because the pattern b_ f[_] does not match the global default 0
  • We need HoldPattern to prevent 0 f[_] from evaluating
  • The value of b_ is set to 0 in case the default of the Optional is used. This is done by matching b_ f[_] to the default 0 f[_]. (So if the default were to be 3 f[_], b would be 3)

Example of question

Armed with this knowledge, it becomes rather1 straightforward to fix the example of the question:

split = (
   a_ +
    HoldPattern@Optional[b_*E^x_, 0*E^_] +
    HoldPattern@Optional[c_*Cos[y_], 0*Cos[_]] + 
    HoldPattern@Optional[d_*Sin[z_], 0*Sin[_]] :> 
     {a, b, c, d}
   );
exp1 /. split
exp2 /. split
exp3 /. split
(* {(x y z)/(x + y + z^2), x y z, x/(y + z), (x z)/(y + z)} *)
(* {(x y z)/(x + y + z^2), x y z, 0, 0} *)
(* {(x y z)/(x + y + z^2), 0, x/(y + z), (x z)/(y + z)} *)

1 There is one small catch: We have to replace Exp[_] by E^_, since we're using HoldPattern, so Exp[_] no longer evaluates to E^_:

Exp[3] // InputForm
(* E^3 *)

E^3 // InputForm
(* E^3 *)

HoldPattern[Exp[3]] // InputForm
(* HoldPattern[Exp[3]] *)
$\endgroup$
  • $\begingroup$ Thank you for your patient explanation. Now I get the point. @Lukas Lang $\endgroup$ – tanghe2014 Oct 10 '19 at 14:37
1
$\begingroup$

If you want coefficients of your expression, you'd better use Coefficient.

Here are the functions for which you want to determine the coefficients:

functions = Cases[{exp1, exp2, exp3}, 
   Exp[x_]|Sin[x_]|Cos[x_], Infinity] // Union

$\{ e^{-\frac{t}{x^2+y^2}}\,, \, \cos\Big[\frac{2\pi t}{T}\Big]\,,\, \sin\Big[\frac{2\pi t}{T}\Big] \}$

Then the coefficients in, say, exp1 are:

Append[Coefficient[exp1, functions], 
  exp1 /. Alternatives @@ functions -> 0]

{x y z, x/(y + z), (x z)/(y + z), x y z/(x + y + z^2)}

which matches your coeff1.

Change the exp1 to exp2 or exp3 you obtain coefficients of your other expressions.

$\endgroup$
  • $\begingroup$ Thank you! @QuantumDot. You give a general solution to this question. $\endgroup$ – tanghe2014 Oct 10 '19 at 14:28
  • $\begingroup$ You're welcome. Don't forget to mark the most useful answer as accepted. $\endgroup$ – QuantumDot Oct 11 '19 at 3:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.