我有一个cdef函数,它将两个numpy.ndarrays作为参数(1).它给了我一个'cfunc.to_py:65:25:'ndarray'不是类型标识符'错误.当我用def(python)函数(2)或cpdef(3)替换cdef时,错误消失.这是一个错误吗?我怎么解决这个问题?代码如下.
(1) cdef float F(np.ndarray xx, np.ndarray y_non_labor, float wage, float gamma, float one_by_gamma, float l, float one_minus_l, int lenx):
(2) def F(np.ndarray xx, np.ndarray y_non_labor, float wage, float gamma, float one_by_gamma, float l, float one_minus_l, int lenx):
(3) cpdef float F(np.ndarray xx, np.ndarray y_non_labor, float wage, float gamma, float one_by_gamma, float l, float one_minus_l, int lenx):
# cython: profile=True
# cython: boundscheck=False
# cython: wraparound=False
cimport cython
from libc.stdlib cimport malloc
from scipy.optimize import minimize
cimport numpy as np
import numpy as np
# due to instabilities associated with "constraint optimization" with bounds
# we will transform the problem so that that it becomes an unconstraint optimization problem without bounds
def transform(x):
x1 = x * x / (1 + x * x)
s = 1 - sum(x1)
return x1, s
# on the next cython update try cdef float F(..)
@cython.cdivision(True)
cdef float F(np.ndarray xx, np.ndarray y_non_labor, float wage, float gamma, float one_by_gamma, float l, float one_minus_l, int lenx):
cdef float s
cdef float *z_non_labor = <float *>malloc(lenx * sizeof(float))
cdef float z_labor
cdef float labor
cdef float value
cdef float summation
cdef float non_labor
cdef float x
cdef float ynl
for i from 0 <= i < lenx:
x = xx[i]
z_non_labor[i] = x * x / (1 + x * x)
s = 0
for i from 0 <= i < lenx:
s += z_non_labor[i]
z_labor = 1 - s
summation = 0
for i from 0 <= i < lenx:
ynl = y_non_labor[i]
summation += (z_non_labor[i] / ynl) ** gamma
non_labor = summation ** one_by_gamma
labor = z_labor / wage
# labor and non-labor inputs together
value = (labor ** l) * (non_labor ** one_minus_l)
return - value
def optimization(np.ndarray seed_weights,
np.ndarray input_prices,
float wage,
float gamma,
float one_by_gamma,
float l,
float one_minus_l):
cdef int lenx
lenx = len(seed_weights)
args=(input_prices,
wage,
gamma,
one_by_gamma,
l,
one_minus_l,
lenx)
return minimize(F, seed_weights, args=args, method='Nelder-Mead')
Run Code Online (Sandbox Code Playgroud)
Dav*_*idW 14
我认为这是一个相当模糊的错误.说明如下.工作回合即将结束.
在Cython 0.21上,我得到了一个不同的错误
filename.pyx:73:21: Cannot convert 'float (ndarray, ndarray, float,
float, float, float, float, int)' to Python object.
Run Code Online (Sandbox Code Playgroud)
这对我来说很有意义,因为minimise将可调用的Python对象作为其第一个答案,同时cdef仅生成C函数.[ cpdef生成两者并在可能的地方调用C函数]
在Cython 0.22和0.23上,我得到你描述的错误.完整的错误是
@cname("__Pyx_CFunc_float____ndarray____ndarray____float____float____float____float____float____int___to_py")
cdef object __Pyx_CFunc_float____ndarray____ndarray____float____float____float____float____float____int___to_py(float (*f)(ndarray, ndarray, float, float, float, float, float, int) except *):
def wrap(ndarray xx, ndarray y_non_labor, float wage, float gamma, float one_by_gamma, float l, float one_minus_l, int lenx):
^
------------------------------------------------------------
cfunc.to_py:30:25: 'ndarray' is not a type identifier
Run Code Online (Sandbox Code Playgroud)
您会注意到这是针对wrap您未定义的功能.wrap似乎只是因为你正在调用而生成minimize它,并且它意识到你需要一个Python对象,所以有助于def为你创建一个函数(如果你注释掉minimize对错误的调用就会消失).这似乎是围绕Cython 0.22进行的增强.
不幸的是,包装的代码使用ndarray而不是np.ndarray你已经定义它(这必须是一个错误!).workround是添加以下行
from numpy cimport ndarray
Run Code Online (Sandbox Code Playgroud)
(这使其ndarray自身成为有效类型).
但是,由于minimize必须通过兼容Python的包装器调用它,您也可以使用cpdef(也可以通过兼容Python的包装器调用,但是在没有错误的情况下以不同的方式生成包装器).使用时几乎没有任何缺点cpdef- 在可能的情况下,该函数仍然可以作为纯C函数快速调用,并且也可以在Python中正常工作(尽管速度稍慢).