1
$\begingroup$

I have an expression like this:

$f=t_1(\sin(\alpha),\cos(\beta),\cos(\gamma)^2) \cdot r_1(x,y,z)+t_n(\sin(\alpha),\cos(\beta),\cos(\gamma)^2) \cdot r_n(x,y,z)$

Where $t_i$ and $r_i$ - functions of trigonometric functions $\sin(\cdot),\cos(\cdot)...$ and variables $x,y,z$, respectively.

I need to split these variables into two vectors by their "nature" i.e. into a vector containing trigonometric terms $t_i$ and a vector containing terms $r_i$ from variables $x,y,z$, i.e.

enter image description here

Let's take the expression as an example:

$f=\sin(\alpha)\cos(\beta)\sin(\gamma)^3x^2y+\sin(\beta)\cos(\alpha)\sin(\gamma)^4x^2y+\sin(\alpha)^2\cos(\beta)xyz+(\sin(\alpha)\cos(\beta)+1)x^3y^2z^5$

Naturally, everything should be with a minimum of code corrections made "manually". And even better if everything is automatic. I will be happy and grateful for help.

 f=Sin[\[Alpha]] Cos[\[Beta]] Sin[\[Gamma]] x^2 y + Sin[\[Beta]] Cos[\[Alpha]] Sin[\[Gamma]]^4 x^2 y + Sin[\[Alpha]]^2 Cos[\[Beta]] x y z + (Sin[\[Alpha]] Cos[\[Beta]] + 1) x^3 y^2 z^5
$\endgroup$
1
  • $\begingroup$ It seems to me that the Level command could be the initial step. $\endgroup$
    – ayr
    Commented Jan 23, 2022 at 6:11

1 Answer 1

3
$\begingroup$
Clear["Global`*"]

f = Sin[α] Cos[β] Sin[γ] x^2 y + 
  Sin[α]^2 Cos[β] x y z + (Sin[α] Cos[β] + 
     1) x^3 y^2 z^5

(* x y z Cos[β] Sin[α]^2 + 
 x^3 y^2 z^5 (1 + Cos[β] Sin[α]) + 
 x^2 y Cos[β] Sin[α] Sin[γ] *)

Note that the order of the terms change on input.

var = Variables[Level[f, {-2}]] /. {_Sin | _Cos :> Nothing}

(* {x, y, z} *)

To obtain v1, set all of the variables in var to 1

v1 = (List @@ f) /. Thread[var -> 1]

(* {Cos[β] Sin[α]^2, 1 + Cos[β] Sin[α], 
 Cos[β] Sin[α] Sin[γ]} *)

Divide the list by v1 to remove the trig factors

v2 = (List @@ f)/v1

(* {x y z, x^3 y^2 z^5, x^2 y} *)

f == v1 . v2

(* True *)

Defining a function

split[f_] := Module[
  {var = Variables[Level[f, {-2}]] /. {_Sin | _Cos :> Nothing},
   list = List @@ f, v1},
  {v1 = list /. Thread[var -> 1],
   list/v1}]

{v1, v2} = split[f]

(* {{Cos[β] Sin[α]^2, 1 + Cos[β] Sin[α], 
  Cos[β] Sin[α] Sin[γ]}, {x y z, x^3 y^2 z^5, x^2 y}} *)

f == Dot @@ %

(* True *)

EDIT: Modifying the definition of split to handle additional forms of input.

split[f_] := Module[
  {var = Variables[Level[f, {-2}]] /. {_Sin | _Cos :> Nothing},
   list = List @@ f, v1, v2, v2m},
  {v1 = list /. Thread[var -> 1],
   v2 = list/v1};
  If[v2 == (v2m = DeleteDuplicates[v2]),
   {v1, v2},
   split[Collect[f2, v2m]]]]

f2 = Sin[α] Cos[β] Sin[γ] x^2 y + 
   Sin[β] Cos[α] Sin[γ]^4 x^2 y + 
   Sin[α]^2 Cos[β] x y z + (Sin[α] Cos[β] + 
      1) x^3 y^2 z^5;

{v1, v2} = split[f2]

(* {{Cos[β] Sin[α]^2, 1 + Cos[β] Sin[α], 
  Cos[β] Sin[α] Sin[γ] + 
   Cos[α] Sin[β] Sin[γ]^4}, {x y z, x^3 y^2 z^5, x^2 y}} *)

f2 == Dot @@ % // Simplify

(* True *)
$\endgroup$
3
  • $\begingroup$ A very good and clear example. Thank you! But this code didn't work for this expression. f=Sin[\[Alpha]] Cos[\[Beta]] Sin[\[Gamma]] x^2 y + Sin[\[Beta]] Cos[\[Alpha]] Sin[\[Gamma]]^4 x^2 y + Sin[\[Alpha]]^2 Cos[\[Beta]] x y z + (Sin[\[Alpha]] Cos[\[Beta]] + 1) x^3 y^2 z^5. Terms with x^2 y not merged, although first we need to take this term out of the bracket $\endgroup$
    – ayr
    Commented Jan 23, 2022 at 8:20
  • 1
    $\begingroup$ I think the edit does what you want; however, it is best to provide the desired output in addition to the input. $\endgroup$
    – Bob Hanlon
    Commented Jan 23, 2022 at 16:28
  • $\begingroup$ Bob, assembly (bracketing) can be done with a simpler command. Other than that, your vectorization code is perfectly functional. I accept it as an answer. Total@MonomialList[f, {x, y, z}] $\endgroup$
    – ayr
    Commented Jan 23, 2022 at 16:43

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.