Python 使用类方法作为GSL QAGS的被积函数
我想用一个类的成员函数作为gsl_函数的全局函数,但我不知道该怎么做。由于我现在只了解C的基本知识,我知道我必须将类实例(被积函数)发送到void参数,但从技术上讲,我无法在Python 使用类方法作为GSL QAGS的被积函数,python,function,class,methods,cython,Python,Function,Class,Methods,Cython,我想用一个类的成员函数作为gsl_函数的全局函数,但我不知道该怎么做。由于我现在只了解C的基本知识,我知道我必须将类实例(被积函数)发送到void参数,但从技术上讲,我无法在cython中对其进行编码,这是一个cython示例 from cython_gsl cimport * ctypedef double * double_ptr ctypedef void * void_ptr cdef double foo(double x, void * params) nogil: cd
cython
中对其进行编码,这是一个cython示例
from cython_gsl cimport *
ctypedef double * double_ptr
ctypedef void * void_ptr
cdef double foo(double x, void * params) nogil:
cdef double alpha, f
alpha = (<double_ptr> params)[0]
f = log(alpha*x) / sqrt(x)
return f
def main():
cdef gsl_integration_workspace * w
cdef double result, error, expected, alpha
w = gsl_integration_workspace_alloc (1000)
expected = -4.0
alpha = 1
cdef gsl_function F
F.function = &foo
F.params = &alpha
gsl_integration_qags (&F, 0, 1, 0, 1e-7, 1000, w, &result, &error)
print "result = % .18f\n" % result
print "estimated error = % .18f\n" % error
来自cython\u gsl cimport的*
ctypedef double*double\u ptr
ctypedef void*void\u ptr
cdef双foo(双x,无效*参数)编号:
双α,f
alpha=(参数)[0]
f=对数(α*x)/sqrt(x)
返回f
def main():
cdef gsl_集成_工作区*w
cdef双重结果,错误,预期,alpha
w=gsl\u集成\u工作空间\u分配(1000)
预期值=-4.0
α=1
cdef gsl_函数F
F.function=&foo
F.params=&alpha
gsl_集成_质量保证(&F、0、1、0、1e-7、1000、w、结果和错误)
打印“结果=%.18f\n”%result
打印“估计错误=%.18f\n”%error
假设我有以下课程:
from math import *
cdef class Foo(object):
def __init__(self, double a=1.2, double b=0.6):
self.a = a
self.b = b
def _integrand(self,double x):
cdef double self.a = (<double_ptr> params)[0]
cdef double self.b = (<double_ptr> params)[1]
return self.a*log(x)+self.b/x**3
def whole(self, double upper_limit=10,double lower_limit=0):
cdef gsl_integration_workspace * w
cdef double result, error, expected, alpha
w = gsl_integration_workspace_alloc (1000)
expected = -4.0
params[0] = self.a
params[1] = self.b
cdef gsl_function F
F.function = &self._integrand
F.params = params
gsl_integration_qags (&F, lower_limit,upper_limit , 0, 1e-7, 1000, w, &result, &error)
return result,error
从数学导入*
cdef类Foo(对象):
定义初始值(自,双a=1.2,双b=0.6):
self.a=a
self.b=b
def_被积函数(自,双x):
cdef double self.a=(参数)[0]
cdef double self.b=(参数)[1]
返回self.a*log(x)+self.b/x**3
def整体(自身,双上限=10,双下限=0):
cdef gsl_集成_工作区*w
cdef双重结果,错误,预期,alpha
w=gsl\u集成\u工作空间\u分配(1000)
预期值=-4.0
参数[0]=self.a
参数[1]=self.b
cdef gsl_函数F
F.函数=&self.\u被积函数
F.params=params
gsl_集成_qags(&F、下限、上限、0、1e-7、1000、w、结果和错误)
返回结果,错误
如何将
Foo.\u被积函数
转换为可由gsl
使用的全局函数?只需取出“self”并将a&b添加到其调用签名中,然后删除代码即可
def _integrand(x, a, b):
return a*log(x)+b/x**3
在Python中,您可以使用
functools.partial
像函数预定义self
参数一样传递方法:
from functools import partial
foo = Foo()
integrand_func = partial(Foo._integrand, foo)
但是你不能在C中定义这样一个偏函数。因此,我将被积函数外部化,并将其定义为类的一个参数,而不是一个额外的方法。请注意,这类似于使用静态方法,但是。另一个重要提示是使用log
formmath.h
。请参见下面的原型:
#cython: wraparound=False
#cython: boundscheck=False
#cython: cdivision=True
#cython: nonecheck=False
cdef extern from "math.h":
double log(double x) nogil
ctypedef double (*function)(double x, void *params)
cdef struct integrandFoo_p:
double *a
double *b
cdef struct gsl_function:
function function
void *params
cdef double integrandFoo(double x, void *params):
cdef integrandFoo_p *p=<integrandFoo_p *>params
cdef double a, b
a = p.a[0]
b = p.b[0]
return a*log(x)+b/(x*x*x)
cdef void trapzd(gsl_function *F, double lower_limit, double upper_limit,
int num, double *result, double *error):
cdef int i
cdef double x
f = F[0].function
p = F[0].params
result[0] = 0.
for i in range(num+1):
x = lower_limit + (upper_limit - lower_limit)*i/num
if i==0 or i==num:
result[0] += f(x, p)*0.5
else:
result[0] += f(x, p)
error[0] = 0.
cdef class Foo(object):
cdef double a
cdef double b
cdef double result
cdef double error
cdef function f
def __init__(self):
self.a = 1.2
self.b = 0.6
self.f = <function>integrandFoo
cdef void integrate(self, double lower_limit=1, double upper_limit=10):
#cdef gsl_integration_workspace * w
cdef double result, error, expected, alpha
cdef integrandFoo_p p
cdef gsl_function F
#w = gsl_integration_workspace_alloc(1000)
p.a = &self.a
p.b = &self.b
expected = -4.0
F.function = self.f
F.params = &p
trapzd(&F, lower_limit, upper_limit, 1000, &self.result, &self.error)
#gsl_integration_qags(&F, lower_limit, upper_limit, 0, 1e-7,
#1000, w, &result, &error)
def main():
foo = Foo()
print 'HERE', foo.result, foo.error
foo.integrate()
print 'HERE', foo.result, foo.error
#cython:wrapparound=False
#cython:boundscheck=False
#cython:cdivision=True
#cython:nonecheck=False
“math.h”中的cdef外部变量:
双对数(双x)nogil
ctypedef double(*函数)(双x,无效*参数)
cdef结构集成文件:
双倍*a
双倍*b
cdef结构gsl_函数:
功能
void*params
cdef double integrandFoo(双x,void*params):
cdef integrandFoo_p*p=params
cdef双a,b
a=p.a[0]
b=p.b[0]
返回a*log(x)+b/(x*x*x)
cdef void trapzd(gsl_函数*F,双下限,双上限,
int num,double*结果,double*错误):
cdef int i
cdef双x
f=f[0]。函数
p=F[0]。参数
结果[0]=0。
对于范围内的i(num+1):
x=下限+(上限-下限)*i/num
如果i==0或i==num:
结果[0]+=f(x,p)*0.5
其他:
结果[0]+=f(x,p)
错误[0]=0。
cdef类Foo(对象):
cdef双a
cdef双b
cdef双重结果
双误
cdef函数
定义初始化(自):
self.a=1.2
self.b=0.6
self.f=integrandFoo
cdef无效积分(自、双下限=1、双上限=10):
#cdef gsl_集成_工作区*w
cdef双重结果,错误,预期,alpha
cdef集成程序
cdef gsl_函数F
#w=gsl\u集成\u工作空间\u分配(1000)
p、 a=&self.a
p、 b=&self.b
预期值=-4.0
函数=self.F
F.params=&p
trapzd(&F,下限,上限,1000,&self.result,&self.error)
#gsl\U集成\U qags(&F,下限,上限,0,1e-7,
#1000、w、结果和错误)
def main():
foo=foo()
打印“此处”,foo.result,foo.error
foo.integrate()
打印“此处”,foo.result,foo.error
一个问题:最后一行不应该说return self.a*log(x)+self.b/x**3
?在绑定到的类的实例的上下文之外,您想要创建全局的特定方法没有任何意义。它取决于a
和b
,两者都是实例类属性。“你为什么要做你要做的事?”阿鲁伊斯丹特,因为这只是我更大问题的一个例子。我想在一个类中使用这个积分,但我不知道该怎么做。@Saullo如果我想在类中添加一个实例来计算给定函数的积分,我该怎么做呢?@staticmethod
是否有助于使被积函数独立于整个类,或者使一个通用的被积函数
在类外没有一个明确的给定函数,并且在类中被调用以获取类参数作为输入可以解决这个问题Dalekmy的问题是,我需要在类内定义被积函数,因为不是在本例中,而是我需要使用类内的其他瞬间来构建被积函数。然而,仍然有两个问题我无法用cython构建您的答案。例如,第一个错误无法将类型“integrandFoo\u p”分配给“integrandFoo\u p*”
,第二个错误是self.f=integrandFoo
它引发的无法将类型“double(double,void*)”分配给“function”
,然后对于p.a=&self.a
我得到了这个错误无法获取Python的地址