Cannot solve simultaneous trig equation

74 views
Skip to first unread message

Jean Marc Roberge

unread,
Sep 22, 2022, 1:59:35 PM9/22/22
to sympy
I am trying to solve 3 trigonometric equation using the solve operation in simply but program never exits loop. per the code below I first calculate the result of the equation using known values (x1,y1,z1) and then use the result of that to as the answer in the equation to solve. the answer should be the x1,z1,z1 values initially used but the loop never ends and provides no result.
What as I doing incorrectly ?

code used
import sympy as sym
from sympy import solve, Eq
from sympy import sin,cos
rad=.01745329
x1=30*rad
y1=15*rad
z1=25*rad
l1=50.00
l2=50.00
l3=50.00
x,y,z= sym.symbols("x,y,z")

print((l2*cos(y1)+l3*cos(z1-y1))*cos(x1))
print((l2*cos(y1)+l3*cos(z1-y1))*sin(x1))
print(l1+(l2*sin(y1)-l3*sin(z1-y1)))

eq1 = Eq((l2*cos(y)+l3*cos(z-y))*cos(x),84.4692460844174)
eq2 = Eq((l2*cos(y)+l3*cos(z-y))*sin(x),84.4692460844174)
eq3 = Eq((l1+(l2*sin(y)-l3*sin(z-y))),54.2585427870506)

result = solve([eq1,eq2,eq3],[x,y,z])
print(result)

Aaron Meurer

unread,
Sep 23, 2022, 2:18:19 PM9/23/22
to sy...@googlegroups.com
If you are only interested in a numerical solution, you are better off
using nsolve(). solve() only tries to find a closed-form symbolic
solution, and the solution to this system might not even exist in
closed-form.

For example:

>>> nsolve([eq1,eq2,eq3], [x, y, z], [1j, 1j, 1j])
Matrix([
[0.785398163397448 - 7.44899462227771e-31*I],
[ 0.0356339138701676 + 0.615283513362025*I],
[-6.32074851537401e-24 + 1.23056702672405*I]])

Small values can be trimmed to 0 with chop:

>>> _.evalf(chop=True)
Matrix([
[ 0.785398163397448],
[0.0356339138701676 + 0.615283513362025*I],
[ 1.23056702672405*I]])

Here I used a complex starting point since the solution is complex,
and nsolve() typically won't find complex solutions unless the
starting point is complex.

Aaron Meurer
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/9fbad812-2f33-43d5-a33c-b109a97a3d27n%40googlegroups.com.

Peter Stahlecker

unread,
Sep 24, 2022, 4:24:44 AM9/24/22
to sy...@googlegroups.com
Thanks! I did not know about nsolve.
Would nsolve be ‚better‘ than converting the equations to numpy, using lambdify, and the use scipy.optimize.fsolve ?

Thanks, Peter


--
Best regards,

Peter Stahlecker

Oscar Benjamin

unread,
Sep 24, 2022, 7:08:22 AM9/24/22
to sympy
On Sat, 24 Sept 2022 at 09:24, Peter Stahlecker
<peter.st...@gmail.com> wrote:
>
> Thanks! I did not know about nsolve.
> Would nsolve be ‚better‘ than converting the equations to numpy, using lambdify, and the use scipy.optimize.fsolve ?

When you use nsolve more or less the same thing happens: the equations
are lambdified but converted to mpmath rather than numpy and then
solved with mpath's findroot function rather than scipy's fsolve. The
tradeoffs between using mpmath vs numpy are the usual ones for
variable precision vs fixed precision: accuracy vs speed.

Since numpy/scipy use fixed precision hardware level floating point
(i.e. 64 bit floats) they can be faster than mpmath which uses
software level arbitrary precision floating point. Likewise since
numpy/scipy use lots of C and Fortran code they can also be faster
than mpmath which is pure Python. On the other hand there may not be
much of a speed difference for relatively "small" systems that do not
benefit significantly from vectorisation and where the overheads of
the Python wrappers in numpy/scipy dominate over the routines that are
implemented in the compiled parts.

Since mpmath uses variable precision arithmetic it can calculate
answers that are more accurate than is possible when using numpy/scipy
or any other fixed precision libraries e.g.:

In [5]: nsolve(x**2 - 2, 1)
Out[5]: 1.41421356237310

In [6]: nsolve(x**2 - 2, 1, prec=50)
Out[6]: 1.4142135623730950488016887242096980785696718753769

The default precision used by nsolve is 15 decimal digits i.e.
basically the same precision as you would expect for 64 bit floats (53
binary digits, ~15 decimal digits) so it should return a result with
the same precision as fsolve. That does not mean that there is no
accuracy gain by default though. Solvers like fsolve that work
*within* the same precision as the output format that they return will
typically return a result that is less accurate than implied by the
precision. In other words the fact that fsolve uses 64 bit floats does
not imply that it returns the most accurate possible 64 bit floats:

In [7]: from scipy.optimize import fsolve

In [8]: fsolve(lambda x: x**2 - 2, 1) # the digits shown are correct
Out[8]: array([1.41421356])

In [9]: fsolve(lambda x: x**2 - 2, 1)[0] # last digits not quite right
Out[9]: 1.4142135623730947

With mpmath's findroot even if you only want the accuracy of 64 bit
floats it will use a higher precision internally in order to round the
result to the desired precision at the end.

The example shown above of x**2 - 2 is a relatively well behaved one
where both nsolve and fsolve can easily find an accurate answer
although the answer from nsolve is slightly more accurate. If you try
something more numerically difficult then you can see bigger output
errors from both functions as well as cases where nsolve throws an
error because it doesn't think that it has enough precision to be able
to converge.

Lastly, nsolve is more convenient just because you don't have to use
lambdify explicitly. Ideally it would be possible to have nsolve call
fsolve so that it would be easier to switch between findroot and
fsolve.

--
Oscar

Peter Stahlecker

unread,
Sep 24, 2022, 7:45:31 AM9/24/22
to sy...@googlegroups.com
Dear Oscar,
Thanks a lot for this very clear explanation!!
I think, I had a problem with accuracy in one of the programs I play around with to use my free time, so I will try it with nsolve.
Peter



--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.

Jeremy Monat

unread,
Sep 26, 2022, 8:34:25 PM9/26/22
to sy...@googlegroups.com
You can get more tips on numerical solving on the recently-published (on the development version of the docs) page Solve One or a System of Equations Numerically.

Best,
Jeremy  Monat

Aaron Meurer

unread,
Sep 27, 2022, 2:02:50 AM9/27/22
to sy...@googlegroups.com
It's not relevant to your equation, but for completeness, another
reason you might want to use mpmath instead of scipy is that mpmath
supports more functions than scipy. For example, scipy's zeta()
doesn't support complex arguments, so it's impossible to use it to
find nontrivial roots. But mpmath (via nsolve) can:

>>> scipy.optimize.fsolve(scipy.special.zeta, .5 + 14j)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/aaronmeurer/anaconda3/lib/python3.9/site-packages/scipy/optimize/minpack.py",
line 160, in fsolve
res = _root_hybr(func, x0, args, jac=fprime, **options)
File "/Users/aaronmeurer/anaconda3/lib/python3.9/site-packages/scipy/optimize/minpack.py",
line 226, in _root_hybr
shape, dtype = _check_func('fsolve', 'func', func, x0, args, n, (n,))
File "/Users/aaronmeurer/anaconda3/lib/python3.9/site-packages/scipy/optimize/minpack.py",
line 24, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
File "/Users/aaronmeurer/anaconda3/lib/python3.9/site-packages/scipy/special/_basic.py",
line 2542, in zeta
return ufuncs._riemann_zeta(x, out)
TypeError: ufunc '_riemann_zeta' not supported for the input types,
and the inputs could not be safely coerced to any supported types
according to the casting rule ''safe''
>>> nsolve(zeta(z), z, 0.5 + 14j)
0.5 + 14.1347251417347*I

Every function in SymPy is in mpmath, but not every function is in SciPy.

Aaron Meurer
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/CAHVvXxRqaf2xOiL%2BuM6zDMLpk8UYgwX44ay%2BGb%2Bbi-8KwqiPUA%40mail.gmail.com.
Reply all
Reply to author
Forward
0 new messages