Cython optimieren Wurzel-Suche API#
Die zugrundeliegenden C-Funktionen für die folgenden Wurzel-Sucher können direkt über Cython aufgerufen werden
Die Cython-API für die Wurzel-Suchfunktionen ist ähnlich, mit dem Unterschied, dass es kein disp-Argument gibt. Importieren Sie die Wurzel-Suchfunktionen mit cimport aus scipy.optimize.cython_optimize.
from scipy.optimize.cython_optimize cimport bisect, ridder, brentq, brenth
Callback-Signatur#
Die Nullstellen-Funktionen in cython_optimize erwarten einen Callback, der eine Gleitkommazahl für die skalare unabhängige Variable als 1. Argument und eine benutzerdefinierte struct mit zusätzlichen Parametern als 2. Argument entgegennimmt.
double (*callback_type)(double, void*) noexcept
Beispiele#
Die Verwendung von cython_optimize erfordert Cython, um Callbacks zu schreiben, die in C kompiliert werden. Weitere Informationen zur Kompilierung von Cython finden Sie in der Cython-Dokumentation.
Dies sind die grundlegenden Schritte
Erstellen Sie eine Cython
.pyx-Datei, zum Beispiel:myexample.pyx.Importieren Sie den gewünschten Wurzel-Sucher aus
cython_optimize.Schreiben Sie die Callback-Funktion und rufen Sie die ausgewählte Wurzel-Suchfunktion auf, wobei Sie den Callback, alle zusätzlichen Argumente und die anderen Solver-Parameter übergeben.
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)
Wenn Sie Ihre Funktion aus Python aufrufen möchten, erstellen Sie eine Cython-Wrapper und eine Python-Funktion, die den Wrapper aufruft, oder verwenden Sie
cpdef. Dann können Sie in Python das Beispiel importieren und ausführen.from myexample import brentq_example x = brentq_example() # 0.6999942848231314
Erstellen Sie eine Cython
.pxd-Datei, wenn Sie Cython-Funktionen exportieren müssen.
Vollständige Ausgabe#
Die Funktionen in cython_optimize können auch die vollständige Ausgabe vom Solver in eine C struct kopieren, die als letztes Argument übergeben wird. Wenn Sie keine vollständige Ausgabe wünschen, übergeben Sie einfach NULL. Die vollständige Ausgabe-struct muss vom Typ zeros_full_output sein, welche in scipy.optimize.cython_optimize mit den folgenden Feldern definiert ist
int funcalls: Anzahl der Funktionsaufrufeint iterations: Anzahl der Iterationenint error_num: Fehlernummerdouble root: Wurzel der Funktion
Die Wurzel wird von cython_optimize in die vollständige Ausgabe-struct kopiert. Eine Fehlernummer von -1 bedeutet einen Vorzeichenfehler, -2 einen Konvergenzfehler und 0 bedeutet, dass der Solver konvergiert ist. Fortsetzung des vorherigen Beispiels
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}