我想重新编写 python 中的代码到 cython ,到目前为止,我通过不使用它们对本例中简化的所有部分进行了cython化。因此我无法保持此功能的python形状。但是,我需要估计在scipy.optimize
库使用之前的函数的根。我想知道我可以用什么来代替在cython中找到这个函数的根。 gsl
能否提供更好的工具来找到根源?应该怎么做?
def RsMassInsideR(mass, R):
def f(x):
xp = R/x
return (np.log(1+xp) - (xp/(1+xp)))*4*np.pi*delta*rho*x**3 - mass #rho and delta are constant
try:
rs = scipy.optimize.brenth(f, 0.01, 10.)
except ValueError, e:
print '!!!!!!!!!!!'
print mass, f(0.01), f(10.)
raise e
return rs
答案 0 :(得分:2)
我曾经面临过多维根发现的类似问题。由于我找到了使用GSL的解决方案,我想在这里分享我的代码。我使用的pyx
文件是
cdef extern from "gsl/gsl_errno.h":
char * gsl_strerror(int gsl_errno)
cdef extern from "gsl/gsl_vector.h":
ctypedef struct gsl_vector:
pass
ctypedef gsl_vector* const_gsl_vector "const gsl_vector*"
gsl_vector* gsl_vector_alloc(size_t n)
void gsl_vector_free(gsl_vector* v)
void gsl_vector_set(gsl_vector* v, size_t i, double x)
double gsl_vector_get(const_gsl_vector v, size_t i)
cdef extern from "gsl/gsl_multiroots.h":
# structures
ctypedef struct gsl_multiroot_function:
int (*f) (const_gsl_vector x, void* params, gsl_vector* f)
size_t n
void* params
ctypedef struct gsl_multiroot_fsolver_type:
pass
ctypedef gsl_multiroot_fsolver_type* const_gsl_multiroot_fsolver_type "const gsl_multiroot_fsolver_type*"
ctypedef struct gsl_multiroot_fsolver:
gsl_multiroot_fsolver_type* type
gsl_multiroot_function* function
gsl_vector* x
gsl_vector* f
gsl_vector* dx
void* state
# variables
gsl_multiroot_fsolver_type* gsl_multiroot_fsolver_hybrids
# functions
gsl_multiroot_fsolver* gsl_multiroot_fsolver_alloc(
gsl_multiroot_fsolver_type* T, size_t n)
void gsl_multiroot_fsolver_free(gsl_multiroot_fsolver* s)
int gsl_multiroot_fsolver_set(gsl_multiroot_fsolver* s,
gsl_multiroot_function* f,
const_gsl_vector x)
int gsl_multiroot_fsolver_iterate(gsl_multiroot_fsolver* s)
int gsl_multiroot_test_residual(const_gsl_vector f, double epsabs)
DEF GSL_SUCCESS = 0
DEF GSL_CONTINUE = -2
cdef size_t n = 2
cdef int rosenbrock_f(const_gsl_vector x, void* params, gsl_vector* f):
cdef double a = 1.
cdef double b = 10.
cdef double x0 = gsl_vector_get(x, 0)
cdef double x1 = gsl_vector_get(x, 1)
cdef double y0 = a * (1 - x0)
cdef double y1 = b * (x1 - x0 * x0)
gsl_vector_set(f, 0, y0)
gsl_vector_set(f, 1, y1)
return GSL_SUCCESS
def gsl_find_root():
#cdef const_gsl_multiroot_fsolver_type T
cdef gsl_multiroot_fsolver* s
cdef int status = GSL_CONTINUE
cdef size_t i, iter = 0
cdef gsl_multiroot_function func
func.f = &rosenbrock_f
func.n = n
cdef double x_init[2]
x_init[0] = -10.0
x_init[1] = -5.0
cdef gsl_vector* x = gsl_vector_alloc(n)
gsl_vector_set (x, 0, x_init[0])
gsl_vector_set (x, 1, x_init[1])
s = gsl_multiroot_fsolver_alloc(gsl_multiroot_fsolver_hybrids, n)
gsl_multiroot_fsolver_set(s, &func, x)
while iter < 100 and status == GSL_CONTINUE:
status = gsl_multiroot_fsolver_iterate(s)
if status != GSL_SUCCESS:
break
status = GSL_CONTINUE
print "%d: %f, %f" % (iter, gsl_vector_get (s.x, 0), gsl_vector_get (s.x, 1))
status = gsl_multiroot_test_residual(s.f, 1e-7)
iter += 1
print("status = %s" % gsl_strerror(status))
gsl_multiroot_fsolver_free(s)
gsl_vector_free(x)
它应该包含必要的概念,并且应该很容易使其适应一维根查找的简单情况。请注意,我这里只使用gsl_vector
而不是numpy数组。将numpy数组复制到gsl_vector
很容易,甚至可以使用gsl_vector
直接处理numpy数组中的数据,尽管我从未尝试过这个。