我正在使用基于 Python 2.7 的数学软件 SageMath。以下简化代码是从初始估计开始递归计算两个函数。当我尝试在代码中引入“数值积分运算符”而不是使用内置函数时,它会给出错误:
> PicklingError: Can't pickle <type 'function'>: attribute lookup __ builtin__.function failed
代码是:
reset()
forget()
from multiprocessing import Pool, cpu_count
#variables
var('x,y, x1,y1')
N=5 #number of iterations
var('q')
#functions' name definition (without specifying the rules) # n is the level of estimation
U0=[]
U1=[]
for n in range(N+1):
U0.append(function('U0_%s' %i, x,y))
U1.append(function('U1_%s' %i, x,y, x1,y1))
#initial estimation of the functions
U0[0]=sin(x+y)
U1[0]=sin(x1+y1)*cos(x-y)
#numerical integrator
num=20.0 # at each call of the int function h is assigned (b-a)/num, so assigned to num here
def numint(f, x, a, b, h):
#pickle_function(f)
integ = 0.5*h*(f(x=a) + f(x=b))
for i in range(1,num):
integ = integ + h * f(x=a+i*h)
return integ
#the integral operators
def Ix(f,x):
return pool.apply( numint, (f,x,-1.0,+1.0,2.0/num) )
def Iy(f,y):
return pool.apply_async( numint, (f,y,-1.0,+1.0,2.0/num) )
def IR(f,x,y):
return Iy(Ix(f,x),y)
def N0(n,f0,f1):
return f0[n] + IR(f1[n],x1,y1) + IR(IR(f1[n],x,y),x1,y1)
def N1(n,f0,f1):
return f1[n] + IR(f0[n],x,y) - IR(IR(f1[n],x,y),x1,y1)
#the calculations
pool = Pool(processes=cpu_count())
for n in range(N):
worker0 = N0(n,U0,U1)
worker1 = N1(n,U0,U1)
U0[n+1] = U0[n] - worker0.get()
U1[n+1] = U1[n] - worker1.get()
show(U0[n+1])
show(U1[n+1])
据我通过搜索网络和阅读文档了解到,这个酸洗错误要么是由于积分运算符(无论如何是一个函数)不是 Picklable,要么是因为它的参数不是 Picklable。我试图让操作符本身可腌制但没有成功,但我想问题应该是由于积分操作符本身是它的被积函数的函数,并且由于它是一个操作符,它的被积函数中的函数没有被确定,因为一开始,所以也许操作符的第一个参数(它本身是一个函数)没有在顶层明确定义是操作符不能整体picklable的原因?知道如何克服这个错误吗?
注意。主要代码比这里提供的简约代码复杂得多,所以我宁愿定义一个整数运算符来防止代码的可读性。