Cython 優化尋根 API#

以下尋根器的底層 C 函數可以使用 Cython 直接存取

尋根函數的 Cython API 很相似,除了沒有 disp 參數。使用 cimportscipy.optimize.cython_optimize 匯入尋根函數。

from scipy.optimize.cython_optimize cimport bisect, ridder, brentq, brenth

回呼簽名#

cython_optimize 中的 zeros 函數期望一個回呼,該回呼接受一個 double 作為純量獨立變數 (第一個參數),以及一個使用者定義的 struct 作為任何額外參數 (第二個參數)。

double (*callback_type)(double, void*) noexcept

範例#

使用 cython_optimize 需要 Cython 來編寫回呼,這些回呼會被編譯成 C 語言。有關編譯 Cython 的更多資訊,請參閱 Cython 文件

以下是基本步驟

  1. 建立一個 Cython .pyx 檔案,例如:myexample.pyx

  2. cython_optimize 匯入所需的尋根器。

  3. 編寫回呼函數,並呼叫選定的尋根函數,傳遞回呼、任何額外參數和其他求解器參數。

    from scipy.optimize.cython_optimize cimport brentq
    
    # import math from Cython
    from libc cimport math
    
    myargs = {'C0': 1.0, 'C1': 0.7}  # a dictionary of extra arguments
    XLO, XHI = 0.5, 1.0  # lower and upper search boundaries
    XTOL, RTOL, MITR = 1e-3, 1e-3, 10  # other solver parameters
    
    # user-defined struct for extra parameters
    ctypedef struct test_params:
        double C0
        double C1
    
    
    # user-defined callback
    cdef double f(double x, void *args) noexcept:
        cdef test_params *myargs = <test_params *> args
        return myargs.C0 - math.exp(-(x - myargs.C1))
    
    
    # Cython wrapper function
    cdef double brentq_wrapper_example(dict args, double xa, double xb,
                                       double xtol, double rtol, int mitr):
        # Cython automatically casts dictionary to struct
        cdef test_params myargs = args
        return brentq(
            f, xa, xb, <test_params *> &myargs, xtol, rtol, mitr, NULL)
    
    
    # Python function
    def brentq_example(args=myargs, xa=XLO, xb=XHI, xtol=XTOL, rtol=RTOL,
                       mitr=MITR):
        '''Calls Cython wrapper from Python.'''
        return brentq_wrapper_example(args, xa, xb, xtol, rtol, mitr)
    
  4. 如果您想從 Python 呼叫您的函數,請建立一個 Cython 包裝器和一個呼叫該包裝器的 Python 函數,或使用 cpdef。然後,在 Python 中,您可以匯入並執行範例。

    from myexample import brentq_example
    
    x = brentq_example()
    # 0.6999942848231314
    
  5. 如果您需要匯出任何 Cython 函數,請建立一個 Cython .pxd 檔案。

完整輸出#

cython_optimize 中的函數也可以將求解器的完整輸出複製到一個 C struct 中,該結構作為其最後一個參數傳遞。如果您不想要完整輸出,只需傳遞 NULL。完整輸出 struct 必須是 zeros_full_output 類型,它在 scipy.optimize.cython_optimize 中定義,具有以下欄位

  • int funcalls:函數呼叫次數

  • int iterations:迭代次數

  • int error_num:錯誤代碼

  • double root:函數的根

根會由 cython_optimize 複製到完整輸出 struct。錯誤代碼 -1 表示符號錯誤,-2 表示收斂錯誤,0 表示求解器收斂。從先前的範例繼續

from scipy.optimize.cython_optimize cimport zeros_full_output


# cython brentq solver with full output
cdef zeros_full_output brentq_full_output_wrapper_example(
        dict args, double xa, double xb, double xtol, double rtol,
        int mitr):
    cdef test_params myargs = args
    cdef zeros_full_output my_full_output
    # use my_full_output instead of NULL
    brentq(f, xa, xb, &myargs, xtol, rtol, mitr, &my_full_output)
    return my_full_output


# Python function
def brent_full_output_example(args=myargs, xa=XLO, xb=XHI, xtol=XTOL,
                              rtol=RTOL, mitr=MITR):
    '''Returns full output'''
    return brentq_full_output_wrapper_example(args, xa, xb, xtol, rtol,
                                              mitr)

result = brent_full_output_example()
# {'error_num': 0,
#  'funcalls': 6,
#  'iterations': 5,
#  'root': 0.6999942848231314}