SymPy无法求解三角方程组

时间:2018-01-11 19:25:45

标签: python sympy

我正在尝试让SymPy解决一个方程组,但它给我一个错误说:

NotImplementedError: could not solve 3*sin(3*t0/2)*tan(t0) + 2*cos(3*t0/2) - 4

我是否有另一种方法可以解决方程组:

sin(x)+(y-x)cos(x)           = 0

-1.5(y-x)sin(1.5x)+cos(1.5x) = 2

我用过:

from sympy import *
solve([sin(x)+(y-x)cos(x), -1.5(y-x)sin(1.5x)+cos(1.5x)-2], x, y)

2 个答案:

答案 0 :(得分:4)

SymPy可以用这个方程做得更好,但最终它相当于一些10度多项式,其根只能抽象地表示。我将描述可以采取的步骤,并展示SymPy可以走多远。这是一个半手动的解决方案流程,应该更加自动化。

首先,不要在方程中加上1.5或其他浮点数。相反,引入系数# Here is an example of the tensor a = tf.constant([[1.0, 0.0], [0.0, 1.0], [1.0, 0.0], [0.0, 1.0]]) # Evaluate the tensor in a session print(tf.Session().run(a)) 并使用:

a = Rational(3, 2)

变量y可以使用第一个等式消除:eq = [sin(x) + (y-x)*cos(x), -a*(y-x)*sin(a*x) + cos(a*x) - 2] ,这很容易让我们看到,但SymPy有时会错过机会。让我们帮忙吧:

y=x-tan(x)

原样,eq1 = eq[1].subs(y, x-tan(x)) # 3*sin(3*x/2)*tan(x)/2 + cos(3*x/2) - 2 solve(另一种SymPy求解器)放弃了等式,因为不同参数的三角函数的混合。我们中的一些人记得从学校时代开始,三角函数可以表示为半参数正切的有理函数,所以让我们这样做:用solveset重写方程。

tan

如上所述,这使争论减半。在trig函数中使用像x / 4这样的分数是不好的。引入新符号eq2 = eq1.rewrite(tan) # (-tan(3*x/4)**2 + 1)/(tan(3*x/4)**2 + 1) - 2 + 3*tan(3*x/4)*tan(x)/(tan(3*x/4)**2 + 1) ,并使u = x / 4:

var('u')

现在,我们可以使用eq3 = eq2.subs(x, 4*u) # (-tan(3*u)**2 + 1)/(tan(3*u)**2 + 1) - 2 + 3*tan(3*u)*tan(4*u)/(tan(3*u)**2 + 1) tan(u)扩展所有这些切线。等式变长:

expand_trig

但它也更简单,因为eq4 = expand_trig(eq3) # (1 - (-tan(u)**3 + 3*tan(u))**2/(-3*tan(u)**2 + 1)**2)/(1 + (-tan(u)**3 + 3*tan(u))**2/(-3*tan(u)**2 + 1)**2) - 2 + 3*(-4*tan(u)**3 + 4*tan(u))*(-tan(u)**3 + 3*tan(u))/((1 + (-tan(u)**3 + 3*tan(u))**2/(-3*tan(u)**2 + 1)**2)*(-3*tan(u)**2 + 1)*(tan(u)**4 - 6*tan(u)**2 + 1)) 可以被视为另一个未知,比如tan(u)

v

太好了,现在我们有了理性的功能。可以使用eq5 = eq4.subs(tan(u), v) # (1 - (-v**3 + 3*v)**2/(-3*v**2 + 1)**2)/(1 + (-v**3 + 3*v)**2/(-3*v**2 + 1)**2) - 2 + 3*(-4*v**3 + 4*v)*(-v**3 + 3*v)/((1 + (-v**3 + 3*v)**2/(-3*v**2 + 1)**2)*(-3*v**2 + 1)*(v**4 - 6*v**2 + 1)) 处理。默认情况下,solveset(eq5, x)提供了所有复杂的解决方案,我们只需要真正的根,所以让我们将域指定为Reals:

solveset

这些没有代数公式,因此它们有些抽象地记录,但这些是我们可以使用的实际数字:

vsol = list(solveset(eq5, v, domain=S.Reals))

例如,我们现在可以回到x和y,并评估解决方案:

[CRootOf(3*v**10 + 9*v**8 - 78*v**6 + 22*v**4 - 21*v**2 + 1, 0),
 CRootOf(3*v**10 + 9*v**8 - 78*v**6 + 22*v**4 - 21*v**2 + 1, 1),
 CRootOf(3*v**10 + 9*v**8 - 78*v**6 + 22*v**4 - 21*v**2 + 1, 2),
 CRootOf(3*v**10 + 9*v**8 - 78*v**6 + 22*v**4 - 21*v**2 + 1, 3)]

数值是

xsol = [4*atan(v) for v in vsol] 
ysol = [x - tan(x) for x in xsol]
numsol = [(N(x), N(y)) for x, y in zip(xsol, ysol)]

当然还有无限多,因为切线是周期性的。最后,让我们检查这些实际工作:

[(-4.35962510714700, -1.64344290066272),
 (-0.877886785847899, 0.326585146723377),
 (0.877886785847899, -0.326585146723377),
 (4.35962510714700, 1.64344290066272)]

这些是1e-15或更少的数量的数组,所以是的,方程式在机器精度范围内。

与我们从SciPy或其他数字解算器获得的纯数字解决方案不同,这些解决方案可以在不重复过程的情况下以任何准确度进行评估。例如,第一个x解决方案的50位数字:

residuals = [[e.subs({x: xv, y: yv}) for e in eq] for xv, yv in numsol]

答案 1 :(得分:2)

只是为了它的乐趣,这里是一个只需要求解5次多项式的手动解决方案:

撰写t = x/2a = y-xs = sin tc = cos tS = sin xC = cos x

可以重写给定的等式

(1)  2 sc + a (c^2 - s^2) = 0
(2)  3 a s^3 - 9 a c^2 s - 6 c s^2 + 2 c^3 = 4

将{1}乘以3 s并添加到(2):

(3)  -6 a c^2 s + 2 c^3 = 4

接下来,我们替换a = -S / C并使用S = 2scs^2 = 1 - c^2

(4)  12 c^3 (1 - c^2) / C + 2 c^3 = 4

C = 2 c^2 - 1相乘:

(5)  c^3 (12 - 12 c^2 + 4 c^2 - 2) = 8 c^2 - 4

最后,

(6)   4 c^5 - 5 c^3 + 4 c^2 - 2 = 0

这有一对复杂的解决方案,一个在余弦域之外的真正解决方案,另外两个解决方案为x提供了四个主要解决方案。

(7)   c_1/2 = 0.90520121, -0.57206084
(8)   x_1/2/3/4 = +/- 2 arccos(x_1/2)