Function Repository Resource:

TrigNSolve

Source Notebook

Solve a system of trigonometric or hyperbolic equations

Contributed by: Daniel Lichtblau

ResourceFunction["TrigNSolve"][eqns,vars]

numerically solves the trigonometric system eqns in vars.

Details and Options

ResourceFunction["TrigNSolve"] also handles hyperbolic functions in the input.
Input can be in the form of trigonometric or hyperbolic polynomials or equations.
ResourceFunction["TrigNSolve"] creates regular polyomials from its input, using a new set of internal variables. It uses NSolve to obtain intermediate solutions in these variables. It then post-processes using arc trigs and arc hyperbolics to solve for the original variables.
ResourceFunction["TrigNSolve"] takes Method and WorkingPrecision options (with defaults of Automatic for each).
The Method option is passed to NSolve.
For some methods the precision might be raised internally beyond what is specified by the WorkingPrecision option setting.
Examples are taken from the Mathematica.StackExchange forum.
Because ResourceFunction["TrigNSolve"] ultimately creates polynomials, it cannot handle mixed variables that appear both in polynomial and in trig form (e.g. x^2+Cos[x]).

ResourceFunction["TrigNSolve"] uses a hybrid symbolic-numeric methodology that, among other things, may use symbolic functions such as Together as well as numeric ones such as N. These have a way of occasionally interfering with one another. Thus there may be systems that require approximate input, or systems that cannot be solved at the default setting of WorkingPrecision. See Possible Issues for an example. It is not known whether there are systems that require exact input in order to get numeric solutions.

Examples

Basic Examples (3) 

A simple trigonometric system of equations:

In[1]:=
sys = {Cos[s + b] - 1/4, Sin[s] - Cos[b] - 5/3};

Solve it:

In[2]:=
tsol = ResourceFunction["TrigNSolve"][sys == 0, {s, b}]
Out[2]=

Check the solutions:

In[3]:=
sys /. tsol // Chop
Out[3]=

Scope (5) 

Find real solutions for a system of five equations:

In[4]:=
sys = {1 - Cos[theta1] - 2/3 Sin[phi + Pi/6] == 0.227746,
   h + 2/3 Cos[phi + Pi/6] - Sin[theta1] == -0.714585,
   -1. - Cos[theta2] - 2/3 Sin[phi - Pi/6] == (3 Cos[psi2])/4,
   2/5 + h + 2/3 Cos[phi - \[Pi]/6] - Sin[theta2] == (3 Sin[psi2])/4, 0.635187 Cos[phi - \[Pi]/6 - psi2] + 2/3 Cos[1.78586 + phi] Sin[psi2] == 0};
solns = ResourceFunction["TrigNSolve"][
   sys, {h, theta1, theta2, phi, psi2}];
rsolns = Select[solns, FreeQ[#, Complex] &]
Out[6]=

Check that residuals are small:

In[7]:=
Map[Norm, MapApply[Subtract, sys] /. rsolns] // Chop
Out[7]=

A system can have variables appearing in trigs or as ordinary variables and can also have radical expressions:

In[8]:=
sys = {1/(4 Sin[x]) - (a Sin[x])/(Sqrt[1 + a^2 + 2 a Cos[x]])^3,
   r^3 - 3/a^3 + (2 (a + Cos[x]))/(Sqrt[1 + a^2 + 2 a Cos[x]])^3,
   r^3 - 3 + (1 + a Cos[x])/(Sqrt[1 + a^2 + 2 a Cos[x]])^3 + 1/(4 Sin[x])};
solns = ResourceFunction["TrigNSolve"][sys, {r, a, x}, Method -> Automatic];
Select[solns, FreeQ[#, Complex] &]
Out[9]=

Solve a mixed trig-hyperbolic system:

In[10]:=
eqns = {Cosh[1]*Cosh[r3] - Sinh[1]*Sinh[r3]*Cos[-a3] == 1/2*(Cosh[1]*Cosh[2] - Sinh[1]*Sinh[2]*Cos[-1]), 1/2*(Cosh[1]*Cosh[2] - Sinh[1]*Sinh[2]*Cos[-1]) == Cosh[2]*Cosh[r3] - Sinh[2]*Sinh[r3]*Cos[1 - a3]};
ResourceFunction["TrigNSolve"][eqns, {r3, a3}]
Out[11]=

Solve a system in trigs and ordinary variables:

In[12]:=
tsys = {Cos[ArcTan[1.1496/h]] == Cos[0.0591 Pi]*Cos[y]*Cos[0.44167 Pi - x] + Sin[0.0591 Pi]*Sin[y],
    Cos[ArcTan[1.501428/h]] == Cos[0.0591 Pi]*Cos[y]*Cos[0.4 Pi - x] + Sin[0.0591 Pi]*Sin[y], Cos[ArcTan[1.927918/h]] == Cos[0.0591 Pi]*Cos[y]*Cos[0.358333 Pi - x] + Sin[0.0591 Pi]*Sin[y]};
solns = ResourceFunction["TrigNSolve"][tsys, {h, x, y}];
rsolns = Select[solns, FreeQ[#, Complex] &]
Out[13]=

Numerically solve a difficult trigonometric system and extract real-valued solutions:

In[14]:=
dvalRules = {da -> 1.12, db -> 1.23, dc -> 0.84};
eqns = {2 a b/(a + b) Sin[(aA + aB)/2] == dc, 2 b c/(b + c) Cos[aA/2] == da, 2 c a (c + a) Cos[aB/2] == db, Sin[aA]/Sin[aA + aB] == da/dc, Sin[aB]/Sin[aA + aB] == db/dc} /. dvalRules /. {aA -> 2 aA, aB -> 2 aB};
solns = ResourceFunction["TrigNSolve"][eqns, {a, b, c}];
realSolns = Select[solns, FreeQ[#, Complex] &]
Out[15]=

A nontrivial mixed system:

In[16]:=
g[z_, b_, r_, a_] := (z - b)/(z - r*I^a)
h[z_, b_, r_, a_] := g[z, b, r, a] + g[Conjugate[z], b, r, a]
f[w_, b_, r_, a_] := h[I^w, b, r, a]
{re, im} = ComplexExpand[ReIm@f[w, b, r, a]];
im1 = Numerator[Together[im]];
rederiv1 = Numerator[Together[D[re, w]]];
tpolys = {im1, rederiv1} /. {w -> 1/5, r -> 97/100};

Solve it:

In[17]:=
ResourceFunction["TrigNSolve"][N[tpolys] == 0, {a, b}]
Out[17]=

Options (5) 

Method (5) 

Use the "Endomorphism" method from NSolve on a large trigonometric system:

In[18]:=
(* Evaluate this cell to get the example input *) CloudGet["https://www.wolframcloud.com/obj/f12ed61d-01b1-4b93-8e52-2c82cf3eca02"]
Out[19]=

Extract real-valued solutions:

In[20]:=
rsolsE = Select[tsolsE, FreeQ[#, Complex] &]
Out[20]=

Compare to the default MethodAutomatic timing:

In[21]:=
First[AbsoluteTiming[
  tsolsA = ResourceFunction["TrigNSolve"][tpolys, {a1, a3, b1, b2, c2, c3}]]]
Out[21]=

And to the "Monodromy" method:

In[22]:=
First[AbsoluteTiming[
  tsolsM = ResourceFunction["TrigNSolve"][tpolys, {a1, a3, b1, b2, c2, c3}, Method -> "Monodromy"]]]
Out[22]=

Timing results strongly suggest that "Homotopy" was used as the Automatic default for this example:

In[23]:=
First[AbsoluteTiming[
  tsolsM = ResourceFunction["TrigNSolve"][tpolys, {a1, a3, b1, b2, c2, c3}, Method -> "Homotopy"]]]
Out[23]=

Possible Issues (2) 

TrigNSolve requires that variables appearing in trig functions not also appear as polynomial variables:

In[24]:=
ResourceFunction[
 "TrigNSolve"][{x^2 + y - Cos[y], Sin[x] + y^2} == 0, {x, y}]
Out[24]=

Some systems cannot be solved in exact form and require numericization in advance:

A nontrivial mixed system:

In[25]:=
g[z_, b_, r_, a_] := (z - b)/(z - r*I^a)
h[z_, b_, r_, a_] := g[z, b, r, a] + g[Conjugate[z], b, r, a]
f[w_, b_, r_, a_] := h[I^w, b, r, a]
{re, im} = ComplexExpand[ReIm@f[w, b, r, a]];
im1 = Numerator[Together[im]];
rederiv1 = Numerator[Together[D[re, w]]];
tpolys = {im1, rederiv1} /. {w -> 1/5, r -> 97/100};

Using N we solve it readily:

In[26]:=
AbsoluteTiming[
 Head@ResourceFunction["TrigNSolve"][N[tpolys] == 0, {a, b}]]
Out[26]=

We cannot solve the exact form:

In[27]:=
Head[ResourceFunction["TrigNSolve"][tpolys == 0, {a, b}]]
Out[27]=

Alternatively the exact input can be handled but only at nontrivial WorkingPrecision:

In[28]:=
Head[ResourceFunction["TrigNSolve"][tpolys == 0, {a, b}, WorkingPrecision -> 50]]
Out[28]=

Requirements

Wolfram Language 13.0 (December 2021) or above

Version History

  • 1.0.2 – 02 May 2025
  • 1.0.1 – 20 June 2024
  • 1.0.0 – 17 June 2024

Related Resources

Author Notes

This was written in to fill a need as seen from several questions that have appeared on the Mathematica StackExchange forum over the years. A few were used in the examples above.

License Information