我正在尝试让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)
答案 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/2
,a = y-x
,s = sin t
,c = cos t
,S = sin x
和
C = 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 = 2sc
和s^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)