0

如何在 Python 中定义操作多变量函数的运算符(例如积分器)?我的问题是,当我定义一个积分函数 numint 以数值积分一个多变量函数沿它的一个变量时,应该首先引入该变量,而我需要在调用运算符时由用户引入它可以从一行代码更改为另一行。一种方法是不使用运算符并在需要时将积分公式植入应该计算积分的变量,但这样代码会变得非常麻烦,因此最好尽可能避免它。对我来说错误的代码如下。有什么让它正常工作的想法吗?

var('x,y,z,t,x1,y1,z1,t1')
U=function('U0',x,y,z,t,x1,y1,z1,t1)
U=sin(x*y*z*t - x1*y1*z1*t1)^5

num=2
def numint(f, u, h):
    integ = 0.5*h*(f(u=0) + f(u=1))
    for i in range(1,num):
        integ = integ + h * f(u=i*h)
    return integ

print numint(U,t1,1/num)+numint(U,t,1/num)

现在进行积分的变量是“u”,在函数“U”中根本找不到,因此结果将是:

2*sin(t*x*y*z - t1*x1*y1*z1)^5

虽然我期待它曾经集成一次 U WRT t 和一次 WRT t1 然后将它们加在一起。

据我所知,问题在于局部变量和全局变量。也许使用闭包和嵌套函数是定义运算符的合适方法,如在此处提供的示例中所做的那样,但该示例对单变量函数很有用,我不能将它用于多变量函数。


更新。下面的代码做我想要的(见最后一个打印命令,以前的打印是为了实验)但我应该使用函数的自由参数(如y)并尝试使用虚拟变量(如u上面的示例代码)失败:

var('x,y,z,t,x1,y1,z1,t1')
R=[x,y,z,t]
R1=[x1,y1,z1,t1]
U=function('U0',*(R+R1))
U0(x,y,z,t,x1,y1,z1,t1)=sin(x-x1)*sin(y-y1)*sin(z-z1)*sin(t-t1)
         # if write U0=... instead of U0(...)=... the order of arguments of U0 is not
         # specified and e.g. sin(x-x1) might become sin(x-y) from the system's viewpoint

num=2
def numint(func, h):

    #integ = 0.5*h*(func(x=x,y=0,z=z,t=t,x1=x1,y1=y1,z1=z1,t1=t1) + func(x=x,y=1,z=z,t=t,x1=x1,y1=y1,z1=z1,t1=t1))
    #for i in range(1,num):
    #    integ = integ + h * func(x=x,y=i*h,z=z,t=t,x1=x1,y1=y1,z1=z1,t1=t1)

    #integ = 0.5*h*(func(x,0,z,t,x1,y1,z1,t1) + func(x,1,z,t,x1,y1,z1,t1))
    #for i in range(1,num):
    #    integ = integ + h * func(x,i*h,z,t,x1,y1,z1,t1)

    integ = 0.5*h*(func(y=0) + func(y=1))
    for i in range(1,num):
        integ = integ + h * func(y=i*h)

    return integ

print numint(U,h=1/num),'\n'
print numint(U0,h=1/num),'\n\n'

print U0(y=z,z=y),'\n'
print numint(U(y=z,z=y),h=1/num),'\n'
print numint(U0(y=z,z=y),h=1/num),'\n\n'

print numint(U0(y=t,t=y),h=1/num).substitute(t=y)+numint(U0(y=t1,t1=y),h=1/num).substitute(t1=y)

结果是:

0.250000000000000*U0(x, 0, z, t, x1, y1, z1, t1) + 1/2*U0(x, 1/2, z, t,
x1, y1, z1, t1) + 0.250000000000000*U0(x, 1, z, t, x1, y1, z1, t1) 

1/2*sin(-y1 + 1/2)*sin(z - z1)*sin(x - x1)*sin(t - t1) +
0.250000000000000*sin(-y1 + 1)*sin(z - z1)*sin(x - x1)*sin(t - t1) +
0.250000000000000*sin(z - z1)*sin(x - x1)*sin(t - t1)*sin(-y1) 


sin(-y1 + z)*sin(y - z1)*sin(x - x1)*sin(t - t1) 

0.250000000000000*U0(x, z, 0, t, x1, y1, z1, t1) + 1/2*U0(x, z, 1/2, t,
x1, y1, z1, t1) + 0.250000000000000*U0(x, z, 1, t, x1, y1, z1, t1) 

1/2*sin(-z1 + 1/2)*sin(-y1 + z)*sin(x - x1)*sin(t - t1) +
0.250000000000000*sin(-z1 + 1)*sin(-y1 + z)*sin(x - x1)*sin(t - t1) +
0.250000000000000*sin(-y1 + z)*sin(x - x1)*sin(t - t1)*sin(-z1) 


1/2*sin(-t1 + 1/2)*sin(z - z1)*sin(y - y1)*sin(x - x1) +
0.250000000000000*sin(-t1 + 1)*sin(z - z1)*sin(y - y1)*sin(x - x1) +
0.250000000000000*sin(t - 1)*sin(z - z1)*sin(y - y1)*sin(x - x1) +
1/2*sin(t - 1/2)*sin(z - z1)*sin(y - y1)*sin(x - x1) +
0.250000000000000*sin(z - z1)*sin(y - y1)*sin(x - x1)*sin(t) +
0.250000000000000*sin(z - z1)*sin(y - y1)*sin(x - x1)*sin(-t1)

请注意我是如何被迫使用.substitute(). 这里集成是单变量的,但是当集成的维度增加时,这种编码方式会变得混乱。有什么想法可以更清洁、更直接地进行此操作吗?

4

2 回答 2

1

您可以使用functools.partial()将具有多个变量的函数转换为具有一个自由变量的函数。

编辑:你的功能是

def numint(func, h):
    ...

所以你应该使用例如

p = partial(numint, h=1/2.0)

然后你可以调用新函数:

p(func)

应该使用关键字参数来指示您将哪些参数提供给部分!并且非关键字论点不能跟在关键字论点之后。

Edit2:请注意,Python 本身不具备对方程进行符号操作的能力,这似乎是您正在寻找的。您可能应该将其重新标记为 SageMath 问题。

于 2013-04-07T08:48:15.057 回答
0
var('x,y,z,t,x1,y1,z1,t1,var1')
U=function('U0',x,y,z,t,x1,y1,z1,t1)
U0(x,y,z,t,x1,y1,z1,t1)=sin(x-x1)*sin(y-y1)*sin(z-z1)*sin(t-t1)
    # if write U0=... instead of U0(...)=... the order of arguments of U0 is not
    # specified and e.g. sin(x-x1) might become sin(x-y) from the system's viewpoint

num=2.0
def numint(func, h):
    #global var1
    integ = 0.5*h*(func(var1=0) + func(var1=1))
    for i in range(1,num):
        integ = integ + h * func(var1=i*h)
    return integ


print numint(U0(x=var1),1/num)+numint(U0(y1=var1),1/num)
于 2013-04-11T14:17:34.080 回答