cython和numpy:'cfunc.to_py:65:25:'ndarray'不是类型标识符'

Dav*_*jad 4 numpy cython

我有一个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中正常工作(尽管速度稍慢).