I think that the result you are looking for here is more complicated than you might expect. Your equations are polynomial in sin(A)
, cos(A)
etc. We also have polynomial relations like sin(A)**2 + cos(A)**2 - 1 = 0
. Putting these together we can systematically eliminate variables using the method of resultants. Here I've replaced sin(A)
and cos(A)
with symbols sA
and cA
so that we can more clearly see that we are working with polynomials:
from sympy import *
sA, cA, sB, cB, sC, cC, sD, cD, sE, cE = symbols('sA, cA, sB, cB, sC, cC, sD, cD, sE, cE')
eq1 = Eq(cC, -sB*sD*cE + sD*sE*cB)
eq2 = Eq(0, -sA*sB*sD*sE - sA*sD*cB*cE - cA*cD)
p1 = eq1.rewrite(Add)
p2 = eq2.rewrite(Add)
# Eliminate cD
p3 = sD**2 + cD**2 - 1
p1_1 = resultant(p1, p3, cD)
p2_1 = resultant(p2, p3, cD)
# Eliminate cE
p4 = sE**2 + cE**2 - 1
p1_2 = resultant(p1_1, p4, cE)
p2_2 = resultant(p2_1, p4, cE)
# Now eliminate sD to get an univariate polynomial for sE
p_final = resultant(p1_2, p2_2, sD)
This now gives us a polynomial equation for sE
with coefficients that include cA,cB,cC,sA,sB
i.e. we have eliminated cos(E)
, sin(D)
and cos(D)
from the system reducing it down to a single polynomial equation for the single unknown sin(E)
. The roots of this polynomial will give us the values of sin(E)
that would be the solutions of the system of equations that you showed (taking into account the important relationships between sin(D)
and cos(D)
and so on). The polynomial for sE
is of degree 16 and the expressions for the coefficients are actually too complicated to be included in a SO post which is limited to 30000 characters. Instead I will just show the leading coefficient (the coefficient of sE**16
):
In [47]: p = Poly(p_final, sE)
In [48]: str(p.LC())
Out[48]: 'cA**16*cB**16 + 8*cA**16*cB**14*sB**2 + 28*cA**16*cB**12*sB**4 + 56*cA**16*cB**10*sB**6 + 70*cA**16*cB**8*sB**8 + 56*cA**16*cB**6*sB**10 + 28*cA**16*cB**4*sB**12 + 8*cA**16*cB**2*sB**14 + cA**16*sB**16 + 8*cA**14*cB**16*cC**2*sA**2 + 32*cA**14*cB**14*cC**2*sA**2*sB**2 + 32*cA**14*cB**12*cC**2*sA**2*sB**4 - 32*cA**14*cB**10*cC**2*sA**2*sB**6 - 80*cA**14*cB**8*cC**2*sA**2*sB**8 - 32*cA**14*cB**6*cC**2*sA**2*sB**10 + 32*cA**14*cB**4*cC**2*sA**2*sB**12 + 32*cA**14*cB**2*cC**2*sA**2*sB**14 + 8*cA**14*cC**2*sA**2*sB**16 + 28*cA**12*cB**16*cC**4*sA**4 + 32*cA**12*cB**14*cC**4*sA**4*sB**2 - 112*cA**12*cB**12*cC**4*sA**4*sB**4 - 288*cA**12*cB**10*cC**4*sA**4*sB**6 - 344*cA**12*cB**8*cC**4*sA**4*sB**8 - 288*cA**12*cB**6*cC**4*sA**4*sB**10 - 112*cA**12*cB**4*cC**4*sA**4*sB**12 + 32*cA**12*cB**2*cC**4*sA**4*sB**14 + 28*cA**12*cC**4*sA**4*sB**16 + 56*cA**10*cB**16*cC**6*sA**6 - 32*cA**10*cB**14*cC**6*sA**6*sB**2 - 288*cA**10*cB**12*cC**6*sA**6*sB**4 + 32*cA**10*cB**10*cC**6*sA**6*sB**6 + 464*cA**10*cB**8*cC**6*sA**6*sB**8 + 32*cA**10*cB**6*cC**6*sA**6*sB**10 - 288*cA**10*cB**4*cC**6*sA**6*sB**12 - 32*cA**10*cB**2*cC**6*sA**6*sB**14 + 56*cA**10*cC**6*sA**6*sB**16 + 70*cA**8*cB**16*cC**8*sA**8 - 80*cA**8*cB**14*cC**8*sA**8*sB**2 - 344*cA**8*cB**12*cC**8*sA**8*sB**4 + 464*cA**8*cB**10*cC**8*sA**8*sB**6 + 1316*cA**8*cB**8*cC**8*sA**8*sB**8 + 464*cA**8*cB**6*cC**8*sA**8*sB**10 - 344*cA**8*cB**4*cC**8*sA**8*sB**12 - 80*cA**8*cB**2*cC**8*sA**8*sB**14 + 70*cA**8*cC**8*sA**8*sB**16 + 56*cA**6*cB**16*cC**10*sA**10 - 32*cA**6*cB**14*cC**10*sA**10*sB**2 - 288*cA**6*cB**12*cC**10*sA**10*sB**4 + 32*cA**6*cB**10*cC**10*sA**10*sB**6 + 464*cA**6*cB**8*cC**10*sA**10*sB**8 + 32*cA**6*cB**6*cC**10*sA**10*sB**10 - 288*cA**6*cB**4*cC**10*sA**10*sB**12 - 32*cA**6*cB**2*cC**10*sA**10*sB**14 + 56*cA**6*cC**10*sA**10*sB**16 + 28*cA**4*cB**16*cC**12*sA**12 + 32*cA**4*cB**14*cC**12*sA**12*sB**2 - 112*cA**4*cB**12*cC**12*sA**12*sB**4 - 288*cA**4*cB**10*cC**12*sA**12*sB**6 - 344*cA**4*cB**8*cC**12*sA**12*sB**8 - 288*cA**4*cB**6*cC**12*sA**12*sB**10 - 112*cA**4*cB**4*cC**12*sA**12*sB**12 + 32*cA**4*cB**2*cC**12*sA**12*sB**14 + 28*cA**4*cC**12*sA**12*sB**16 + 8*cA**2*cB**16*cC**14*sA**14 + 32*cA**2*cB**14*cC**14*sA**14*sB**2 + 32*cA**2*cB**12*cC**14*sA**14*sB**4 - 32*cA**2*cB**10*cC**14*sA**14*sB**6 - 80*cA**2*cB**8*cC**14*sA**14*sB**8 - 32*cA**2*cB**6*cC**14*sA**14*sB**10 + 32*cA**2*cB**4*cC**14*sA**14*sB**12 + 32*cA**2*cB**2*cC**14*sA**14*sB**14 + 8*cA**2*cC**14*sA**14*sB**16 + cB**16*cC**16*sA**16 + 8*cB**14*cC**16*sA**16*sB**2 + 28*cB**12*cC**16*sA**16*sB**4 + 56*cB**10*cC**16*sA**16*sB**6 + 70*cB**8*cC**16*sA**16*sB**8 + 56*cB**6*cC**16*sA**16*sB**10 + 28*cB**4*cC**16*sA**16*sB**12 + 8*cB**2*cC**16*sA**16*sB**14 + cC**16*sA**16*sB**16'
In general there are limitations on giving radical expressions for the roots of polynomials of degree 5 or more except in certain special cases due to the Abel-Ruffini theorem. If the coefficients are numeric rather than symbolic then we can work around those with things like RootOf. In this case though I doubt that it is possible to express the solutions of this system of equations using anything that you might recognise as an explicit closed form.
If you substitute numeric values for the symbolic unknowns then it should be possible to get approximate roots numerically (e.g. with nroots
) or it might become possible to get exact solutions:
In [62]: p_numeric = p.subs({cA:0,sA:1,cB:1/sqrt(2),sB:1/sqrt(2),cC:1})
In [63]: p_numeric
Out[63]:
8 6 4 2
16 14 12 10 35⋅sE 7⋅sE 7⋅sE sE 1
sE - 4⋅sE + 7⋅sE - 7⋅sE + ────── - ───── + ───── - ─── + ───
8 4 16 16 256
In [64]: roots(p_numeric)
Out[64]:
⎧-√2 √2 ⎫
⎨────: 8, ──: 8⎬
⎩ 2 2 ⎭
In [69]: nroots(p_numeric, n=8, maxsteps=500)
Out[69]:
[-0.70710678, 0.70710677, 0.70710679, -0.70710679 + 2.4757313e-9⋅ⅈ, -0.70710679 - 2.9650933e-9⋅ⅈ, -
0.70710678 + 4.9626324e-9⋅ⅈ, -0.70710678 - 6.2970508e-9⋅ⅈ, -0.70710678 + 5.3076725e-9⋅ⅈ, -0.7071067
8 - 5.388738e-9⋅ⅈ, -0.70710678 + 2.7281099e-9⋅ⅈ, 0.70710678 + 5.5825484e-9⋅ⅈ, 0.70710678 - 6.328749
4e-9⋅ⅈ, 0.70710678 + 7.8957797e-9⋅ⅈ, 0.70710678 - 8.1564975e-9⋅ⅈ, 0.70710679 + 5.6265597e-9⋅ⅈ, 0.70
710679 - 5.3161607e-9⋅ⅈ]
Note here that nsolve
has been unable to determine that there are repeated roots or whether or not the roots are real or have a small imaginary part. This is because finding the roots of a polynomial can be very ill-conditioned especially where there are many repeated roots (possibly the values that I chose to substitute are somewhat degenerate).
Most likely though if you are going to substitute values then it is better to do that at the start and e.g. just call solve/nsolve
with the substituted values.
https://en.wikipedia.org/wiki/Resultant
https://en.wikipedia.org/wiki/Abel%E2%80%93Ruffini_theorem