0

多変数関数を操作する Python で演算子 (積分器など) を定義するにはどうすればよいですか? 私の問題は、積分関数 numint を定義して多変数関数をその変数の 1 つに沿って数値的に積分するときに、その変数を最初に導入する必要がある一方で、オペレーターが可能な限り呼び出されたときにユーザーが導入する必要があることです。コードのある行から別の行に変更します。1 つの方法は、演算子を使用せず、積分を計算する必要がある変数で必要なときに積分式を埋め込むことですが、その方法ではコードが非常に煩雑になるため、可能な限り回避することをお勧めします。私にとって間違って動作するコードは次のとおりです。適切に機能させるためのアイデアはありますか?

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()して、複数の変数を持つ関数を 1 つの自由変数を持つ関数に変換できます。

編集:あなたの機能は

def numint(func, h):
    ...

したがって、たとえば使用する必要があります

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

次に、新しい関数を呼び出すことができます。

p(func)

キーワード引数を使用して、パーシャルに与える引数を示す必要があります。また、非キーワード引数はキーワード引数の後に続けることはできません。

Edit2: Python 自体には、方程式の記号操作を行う機能がないことに注意してください。これは、探しているようです。おそらく、これを SageMath の質問として再ラベル付けする必要があります。

于 2013-04-07T08:48:15.057 に答える