我一直在尝试使用scipy求解器来解决以下方程组:
from scipy.optimize import fsolve
import math
import numpy as np
S0 = 1000
u = 1
d = 1
delta_t = 1
r = 0
psi_r = (np.exp(-r*delta_t))**(-1)
fi_r = np.exp(-r*delta_t)
fi_2r = np.exp(-2*r*delta_t)
def equations(p):
p_u,p_m,p_d = p
return (p_u+p_m+p_d - 1, fi_r*(p_u*(S0+u) + p_m*S0 + p_u*(S0-d)) -S0,fi_2r*
(p_u*p_u*(S0+2*u) + 2*p_m*p_u*(S0+u) + (2*p_u*p_d+p_m*p_m)*S0 + 2*p_m*p_d*(S0-d) + p_d*p_d*(S0-2*d)) - S0)
p_u,p_m,p_d = fsolve(equations,(0.3,0.5,0.4))
print(equations((p_u,p_m,p_d)))
问题在于,尽管第一个等式表明我的未知数之和应为1,但它永远不会给出满足此结果的结果。我得到的是意外的数字,大约10到-12,有时甚至是负数,我知道这不是正确的解决方案。
我知道我必须尝试几个初步的猜测,但我担心的是到目前为止没有一个猜测给我的概率总和为1.
答案 0 :(得分:2)
通常,当系统有多个解决方案时,数值解算器返回的解决方案取决于初始解决方案估计以及实现的算法。但是,通常,很难“控制”求解器返回的解属性。
在您的情况下,您需要一个解决方案,其所有元素都位于[0,1]
区间内。但是,fsolve
算法会收敛到不满足此属性的解决方案。不幸的是,fsolve
不允许对它返回的解决方案施加任何约束(据我所知,任何其他数值方程求解器的情况也是如此)。
对解决方案施加约束的一种解决方法是将方程解决问题公式化为约束优化问题。一种直接的方法如下。
假设您需要针对向量[f(x)==0, g(x)==0]
求解两个方程x
。请注意,系统的任何解决方案也是函数f(x)**2+g(x)**2
的最小化,可以通过调用scipy.optimize.least_squares
来获得。现在,scipy.optimize.least_squares
接受它返回的解的边界,这实际上允许您找到具有所需绑定属性的原始方程组的解。
from scipy.optimize import least_squares
sol = least_squares(equations,(0.3,0.5,0.4), bounds = (0,1))
print('solution: ', sol.x, '\n', 'equations:', equations(sol.x))
solution: [ 0.295 0.4101 0.295 ] equations: (0.0, 0.0, 0.0)
请注意,返回的解决方案确实是概率分布和方程组的根。