cython与python在scipy.optimize.fsolve中的不同结果

cython与python在scipy.optimize.fsolve中的不同结果,python,numpy,scipy,cython,Python,Numpy,Scipy,Cython,我在代码中多次调用了一个函数。cython版本和原始python代码给了我相同的答案(在1e-7中,我理解这与cython与python类型有关……这里不是问题,但可能很重要) 我尝试使用scipy.optimize.fsolve()查找函数的根。python版本运行良好,但cython版本存在分歧 代码非常复杂,有一个大的外部文件来准备一些参数,所以我不能发布所有内容。我发布了赛昂密码。完整的代码是 def euler_外部(float b_prime,int index_b, np.ndar

我在代码中多次调用了一个函数。cython版本和原始python代码给了我相同的答案(在
1e-7
中,我理解这与cython与python类型有关……这里不是问题,但可能很重要)

我尝试使用
scipy.optimize.fsolve()
查找函数的根。python版本运行良好,但cython版本存在分歧

代码非常复杂,有一个大的外部文件来准备一些参数,所以我不能发布所有内容。我发布了赛昂密码。完整的代码是

def euler_外部(float b_prime,int index_b,
np.ndarray[np.double_t,ndim=1]b_网格,int index_y,
np.ndarray[np.double_t,ndim=1]y_网格,
np.ndarray[np.double_t,ndim=1]y_vec,
np.ndarray[np.double_t,ndim=2]pol_mat_b,float q,
np.ndarray[np.double_t,ndim=2]pol_mat_q,
np.ndarray[np.double_t,ndim=2]P,浮动β,
int n_ygrid,int check=0):
'''
b_prime-感兴趣的变量。想找到解决这个问题的b_素数吗
功能
'''
cdef双b、y、c、uc、e_ucp、eul_val
cdef int i
cdef np.ndarray[np.float64_t,ndim=1]uct,c_prime=np.zeros((n_ygrid,)
b=b_网格[索引b]
y=y网格[索引y]
#获取今天的消费价值
c=b+y-b_素数/q
#获取明天可能的消费价值
如果检查:
c_素数=b_素数+y_向量-b_网格[0]/q
其他:
对于范围内的i(n_ygrid):
c_素数[i]=(b_素数+y_向量[i]-
(np.interp(b_素数,b_网格,pol_mat_b[:,i])/
np.interp(b_素数,b_网格,pol_mat_q[:,i]))

如果c如上面的注释所述,Python和Cython版本的结果之间存在差异的原因是Cython函数中,有几个输入被声明为
float
,而实际的Python变量是
double
精度

Cython函数的舍入误差的增加似乎是
fsolve
无法收敛的原因-当这些输入被声明为
double
时,Python和Cython版本会产生完全相同的结果,并且
fsolve
会正确收敛



另一方面,目标函数中的舍入误差妨碍收敛的情况表明。您可能需要考虑是否有可能重新制定模型,以提高其数值稳定性。

您正在将一些输入变量声明为
float
。它们真的是浮动的,还是实际上是双倍的?可以想象,将双精度下推到浮点值可以解释Python和Cython结果之间的差异。如果你的系统是病态的,梯度中额外的舍入误差可能会导致无法收敛。谢谢@ali\m。将float更改为double更改了函数,以便给出与原始python完全相同的答案,
fsolve()
收敛到相同的答案。作为一个答案张贴,我会接受它。
def euler_outside(float b_prime, int index_b,
                  np.ndarray[np.double_t, ndim=1] b_grid, int index_y,
                  np.ndarray[np.double_t, ndim=1] y_grid,
                  np.ndarray[np.double_t, ndim=1] y_vec,
                  np.ndarray[np.double_t, ndim=2] pol_mat_b, float q,
                  np.ndarray[np.double_t, ndim=2] pol_mat_q,
                  np.ndarray[np.double_t, ndim=2] P, float beta,
                  int n_ygrid, int check=0):
    '''
    b_prime - the variable of interest. want to find b_prime that solves this
    function
    '''
    cdef double b, y, c, uc, e_ucp, eul_val
    cdef int i
    cdef np.ndarray[np.float64_t, ndim=1] uct, c_prime = np.zeros((n_ygrid,))

    b = b_grid[index_b]
    y = y_grid[index_y]

    # Get value of consumption today
    c = b + y - b_prime/q

    # Get possible values of consumption tomorrow
    if check:
        c_prime = b_prime + y_vec - b_grid[0]/q
    else:
        for i in range(n_ygrid):
            c_prime[i] = (b_prime + y_vec[i] -
                         (np.interp(b_prime, b_grid, pol_mat_b[:,i]) /
                          np.interp(b_prime, b_grid, pol_mat_q[:,i])))

    if c<0:
        return 1e10

    uc = utility_prime(c)
    uct = utility_prime(c_prime)

    e_ucp = np.inner( uct, P[index_y,:] )
    eul_val = uc - beta*q * e_ucp

    return eul_val