3

I am looking for recommendations for math software that can do manipulations with trigonometric polynomials. Basically, I have a bunch of trigonometric expressions like $$K \cos{\left(\alpha + \chi_1 - \chi_2 - \phi_1 + \phi_2 \right)} + K \cos{\left(\alpha - \phi_1 + \phi_2 - \psi_1 + \psi_2 \right)} .$$ Here $K$, $r$ and $\alpha$ are parameters and $\phi_1, \phi_2, \psi_1, \psi_2, \chi_1, \chi_2$ are variables. A quite usual approach to my further analysis would be to expand it into products of sines and cosines of variables and group terms with the same powers. For example, $K \cos{\left(\alpha + \chi_1 - \chi_2 - \phi_1 + \phi_2 \right)}$ expands to $$K \sin{\left(\alpha \right)} \sin{\left(\chi_1 \right)} \sin{\left(\chi_2 \right)} \sin{\left(\phi_1 \right)} \cos{\left(\phi_2 \right)} - K \sin{\left(\alpha \right)} \sin{\left(\chi_1 \right)} \sin{\left(\chi_2 \right)} \sin{\left(\phi_2 \right)} \cos{\left(\phi_1 \right)} - K \sin{\left(\alpha \right)} \sin{\left(\chi_1 \right)} \sin{\left(\phi_1 \right)} \sin{\left(\phi_2 \right)} \cos{\left(\chi_2 \right)} - K \sin{\left(\alpha \right)} \sin{\left(\chi_1 \right)} \cos{\left(\chi_2 \right)} \cos{\left(\phi_1 \right)} \cos{\left(\phi_2 \right)} + K \sin{\left(\alpha \right)} \sin{\left(\chi_2 \right)} \sin{\left(\phi_1 \right)} \sin{\left(\phi_2 \right)} \cos{\left(\chi_1 \right)} + K \sin{\left(\alpha \right)} \sin{\left(\chi_2 \right)} \cos{\left(\chi_1 \right)} \cos{\left(\phi_1 \right)} \cos{\left(\phi_2 \right)} + K \sin{\left(\alpha \right)} \sin{\left(\phi_1 \right)} \cos{\left(\chi_1 \right)} \cos{\left(\chi_2 \right)} \cos{\left(\phi_2 \right)} - K \sin{\left(\alpha \right)} \sin{\left(\phi_2 \right)} \cos{\left(\chi_1 \right)} \cos{\left(\chi_2 \right)} \cos{\left(\phi_1 \right)} + K \sin{\left(\chi_1 \right)} \sin{\left(\chi_2 \right)} \sin{\left(\phi_1 \right)} \sin{\left(\phi_2 \right)} \cos{\left(\alpha \right)} + K \sin{\left(\chi_1 \right)} \sin{\left(\chi_2 \right)} \cos{\left(\alpha \right)} \cos{\left(\phi_1 \right)} \cos{\left(\phi_2 \right)} + K \sin{\left(\chi_1 \right)} \sin{\left(\phi_1 \right)} \cos{\left(\alpha \right)} \cos{\left(\chi_2 \right)} \cos{\left(\phi_2 \right)} - K \sin{\left(\chi_1 \right)} \sin{\left(\phi_2 \right)} \cos{\left(\alpha \right)} \cos{\left(\chi_2 \right)} \cos{\left(\phi_1 \right)} - K \sin{\left(\chi_2 \right)} \sin{\left(\phi_1 \right)} \cos{\left(\alpha \right)} \cos{\left(\chi_1 \right)} \cos{\left(\phi_2 \right)} + K \sin{\left(\chi_2 \right)} \sin{\left(\phi_2 \right)} \cos{\left(\alpha \right)} \cos{\left(\chi_1 \right)} \cos{\left(\phi_1 \right)} + K \sin{\left(\phi_1 \right)} \sin{\left(\phi_2 \right)} \cos{\left(\alpha \right)} \cos{\left(\chi_1 \right)} \cos{\left(\chi_2 \right)} + K \cos{\left(\alpha \right)} \cos{\left(\chi_1 \right)} \cos{\left(\chi_2 \right)} \cos{\left(\phi_1 \right)} \cos{\left(\phi_2 \right)}.$$

This is a simple example, however it already shows that coefficients of these polynomials are not just integers: they are also symbolic expressions, like $K \sin \alpha$. For example, if expressions are more complex, simple expansion won't help, I have to group up terms for further analysis.

Before I was using Python's SymPy to do expansions and term rewriting. However, I haven't found a way to collect terms as I want. For example, in a simplest expression $$ A \cos{\left(\alpha \right)} + B \sin{\left(\alpha \right)} \cos{\left(\alpha \right)} + C \cos{\left(\alpha \right)} $$ I expect terms to be gathered like this $$ (A+C) \cos{\left(\alpha \right)} + B \sin{\left(\alpha \right)} \cos{\left(\alpha \right)} ,$$ but using sympy.collect(expr, [sympy.cos(alpha), sympy.sin(alpha)]) or sympy.collect(expr, [sympy.cos(alpha), sympy.sin(alpha)], sympy.factor) leads to $$ \left(A + B \sin{\left(\alpha \right)} + C\right) \cos{\left(\alpha \right)},$$ which is not desirable. Exactly the same happens to regular polynomials too: collecting terms is greedy. The trigonometric problem could be converted to a problem of ordinary multivariate polynomials by substituting $\cos \theta = \frac{1-T^2}{1+T^2}$ and $\sin \theta = \frac{2T}{1+T^2}$, so I am okay with software that can group polynomials in the way that I need.

I would be glad to hear what are the alternatives to SymPy or how that could be done in SymPy if you've encountered this problem. Thanks in advance!

P.S. Special thanks if you know an open-source solution for this or can point to a tutorial where it is shown that a software can do this!

P.P.S. I also have big hopes for open-source software like Maxima, Reduce, Axiom. I'm currently skimming their tutorials, but haven't found if they can do what I'm asking.

Evgeny
  • 5,933

2 Answers2

2

In Wolfram Mathematica 12.0 writing:

Factor[a Cos[x] + b Sin[x] Cos[x] + c Cos[x]]

you get:

Cos[x] (a + c + b Sin[x])

since this is the standard factorization rule present in practically every CAS.

On the other hand, not all CAS have a function like:

Collect[a Cos[x] + b Sin[x] Cos[x] + c Cos[x], {Sin[x], Cos[x]}]

through which to obtain:

(a + c) Cos[x] + b Cos[x] Sin[x]

also applicable to more complicated cases:

expr = Expand[x^2 - x y + y^2 - 2 y - 3 x - 1 /. {x -> a1 + a2 Cos[t] + a3 Sin[t], 
                                                  y -> a4 + a5 Cos[t] + a6 Sin[t]}];
Collect[expr, {Cos[t], Sin[t], Cos[t] Sin[t]}]

-1 - 3 a1 + a1^2 - 2 a4 - a1 a4 + a4^2 + (-3 a2 + 2 a1 a2 - a2 a4 - 2 a5 - a1 a5 + 2 a4 a5) Cos[t] + (a2^2 - a2 a5 + a5^2) Cos[t]^2 + (-3 a3 + 2 a1 a3 - a3 a4 - 2 a6 - a1 a6 + 2 a4 a6) Sin[t] + (2 a2 a3 - a3 a5 - a2 a6 + 2 a5 a6) Cos[t] Sin[t] + (a3^2 - a3 a6 + a6^2) Sin[t]^2

But perhaps the most interesting thing is to be able to introduce custom rules like:

rule = Log[expr_] :> Log[Abs[expr]];

Integrate[(2 x^2 + 2 x + 1)/(x + 1), x]
Integrate[(2 x^2 + 2 x + 1)/(x + 1), x] /. rule

-1 + x^2 + Log[1 + x]

-1 + x^2 + Log[Abs[1 + x]]

Of course, it takes some time to get enough confidence.

  • 1
    That's pretty neat, +1! After comment by @YiFan I've tried to check what Mathematica can do. I've got a bit discouraged after checking Collect[A x + B x y + C x, {x, y}] in Wolfram Alpha and getting regular $x(A+By+C)$ as a first result. However, your code works in WA, so I have much better hopes now. It seems to be working even for multivariate polynomials Collect[a Cos[x] + b Sin[y] Cos[x] + c Cos[x] + d Sin^2[y], {Sin[y], Cos[x]}]. Thanks a lot for your answer! The only downside is access to Mathematica, which I don't have right now. – Evgeny Jan 15 '20 at 16:04
  • 1
  • @Somos Thanks for mentioning it, haven't heard about it before! That should simplify comparing to other CAS. – Evgeny Jan 16 '20 at 17:07
2

We can split $K$ by the usage of trigexpand:

(%i12) K:cos(alpha+xi1-xi2-phi1+phi2);
(%o12)               cos(xi2 - xi1 - phi2 + phi1 - alpha)
(%i13) trigexpand(K);
(%o13) cos(alpha) sin(phi1) sin(phi2) sin(xi1) sin(xi2)
 - sin(alpha) cos(phi1) sin(phi2) sin(xi1) sin(xi2)
 + sin(alpha) sin(phi1) cos(phi2) sin(xi1) sin(xi2)
 + cos(alpha) cos(phi1) cos(phi2) sin(xi1) sin(xi2)
 + sin(alpha) sin(phi1) sin(phi2) cos(xi1) sin(xi2)
 + cos(alpha) cos(phi1) sin(phi2) cos(xi1) sin(xi2)
 - cos(alpha) sin(phi1) cos(phi2) cos(xi1) sin(xi2)
 + sin(alpha) cos(phi1) cos(phi2) cos(xi1) sin(xi2)
 - sin(alpha) sin(phi1) sin(phi2) sin(xi1) cos(xi2)
 - cos(alpha) cos(phi1) sin(phi2) sin(xi1) cos(xi2)
 + cos(alpha) sin(phi1) cos(phi2) sin(xi1) cos(xi2)
 - sin(alpha) cos(phi1) cos(phi2) sin(xi1) cos(xi2)
 + cos(alpha) sin(phi1) sin(phi2) cos(xi1) cos(xi2)
 - sin(alpha) cos(phi1) sin(phi2) cos(xi1) cos(xi2)
 + sin(alpha) sin(phi1) cos(phi2) cos(xi1) cos(xi2)
 + cos(alpha) cos(phi1) cos(phi2) cos(xi1) cos(xi2)

We can use the tex funtcion to generate TeX output.

I tried to mimic the simplifications of this answer in Maxima and got this when using the function facsum:

(%i1) load (facexp)$
(%i2) e:A*cos(a)+B*sin(a)*cos(a)+C*cos(a);
(%o2)                B cos(a) sin(a) + C cos(a) + A cos(a)
(%i3) facsum(e,sin(a),cos(a));
(%o3)                  B cos(a) sin(a) + (C + A) cos(a)
(%i4) expr : expand(x^2 - x *y + y^2 - 2 *y - 3 *x - 1 ),
x = a1 + a2 *cos(t) + a3 *sin(t),
y = a4 + a5 *cos(t) + a6 *sin(t)$
(%i5) facsum(expr,sin(t),cos(t));
         2             2     2
(%o5) (a6  - a3 a6 + a3 ) sin (t) + (2 a5 a6 - a2 a6 - a3 a5 + 2 a2 a3) cos(t)
 sin(t) + (2 a4 a6 - a1 a6 - 2 a6 - a3 a4 + 2 a1 a3 - 3 a3) sin(t)
      2             2     2
 + (a5  - a2 a5 + a2 ) cos (t) + (2 a4 a5 - a1 a5 - 2 a5 - a2 a4 + 2 a1 a2
                    2                    2
 - 3 a2) cos(t) + a4  - a1 a4 - 2 a4 + a1  - 3 a1 - 1

I am not aware of a documented Maxima function that extracts the coeffiecients except ratp_coeffs which does this for one variable. Or you can program your own function. But there is an undocumented function coeffsin the package coeflist that (almost) seems to do what you want

(%i1) load("coeflist")$
(%i2) expr : expand(x^2 - x *y + y^2 - 2 *y - 3 *x - 1 ),
     x = a1 + a2 *cos(t) + a3 *sin(t),
     y = a4 + a5 *cos(t) + a6 *sin(t)$
(%i13) expr2: coeffs(expr,sin(t),cos(t));
                                    2                    2
(%o13) [[%poly, sin(t), cos(t)], [a4  - a1 a4 - 2 a4 + a1  - 3 a1 - 1, 0, 0],
[2 a4 a5 - a1 a5 - 2 a5 - a2 a4 + 2 a1 a2 - 3 a2, 0, 1],
   2             2
[a5  - a2 a5 + a2 , 0, 2], [2 a4 a6 - a1 a6 - 2 a6 - a3 a4 + 2 a1 a3 - 3 a3,
                                                     2             2
1, 0], [2 a5 a6 - a2 a6 - a3 a5 + 2 a2 a3, 1, 1], [a6  - a3 a6 + a3 , 2, 0]]

demo("coeflist.demo")shows some additional function of this package.

if we want only the coefficients we skip the first element of this list and retrieve the first element of each remaining triple.

(%i10) map('first,rest(expr2));
          2                    2
(%o10) [a4  - a1 a4 - 2 a4 + a1  - 3 a1 - 1,
                                                   2             2
2 a4 a5 - a1 a5 - 2 a5 - a2 a4 + 2 a1 a2 - 3 a2, a5  - a2 a5 + a2 ,
2 a4 a6 - a1 a6 - 2 a6 - a3 a4 + 2 a1 a3 - 3 a3,
                                     2             2
2 a5 a6 - a2 a6 - a3 a5 + 2 a2 a3, a6  - a3 a6 + a3 ]

There is a postcript file (format.ps) in the directory that will contain some documentation. This documentation (in pdf format) can also be found here (Bruce R. Miller: An Expression Formatter for MACSYMA).

miracle173
  • 11,441
  • Thank you a lot for your answer! This is kind of an extra question, but is there a simple consistent way to get coefficients before all trigonometric terms in the final expression? Something that would return a list $\lbrack a6 -a3 , a6 + a_3 , 2, a5, a6 - a2 , a6 - a3, a5 + 2 ,a2 , a3, \dots \rbrack$ would be amazing. It would help me to solve the problem further. – Evgeny Feb 11 '20 at 12:11
  • @Evgeny I edited the answer – miracle173 Feb 11 '20 at 14:09