2017-11-02 7 views
1

私は数値解析のための私のコードを改善するために、私の検索では、次のコードを見つけました:このRK4 ODEソルバでは、内側のラムダが外側のラムダfuctionをどのように使用しますか? Pythonの

from math import sqrt 

def RK4(f): 
    return lambda t, y, dt: (
     lambda dy1: (
      lambda dy2: (
       lambda dy3: (
        lambda dy4: (dy1 + 2 * dy2 + 2 * dy3 + dy4)/6 
       )(dt * f(t + dt, y + dy3)) 
      )(dt * f(t + dt/2, y + dy2/2)) 
     )(dt * f(t + dt/2, y + dy1/2)) 
    )(dt * f(t, y)) 

def theory(t): 
    return (t**2 + 4)**2/16 

dy = RK4(lambda t, y: t * sqrt(y)) 

t, y, dt = 0., 1., .1 
while t <= 10: 
    if abs(round(t) - t) < 1e-5: 
     print("y(%2.1f)\t= %4.6f \t error: %4.6g" % (t, y, abs(y - theory(t)))) 
    t, y = t + dt, y + dy(t, y, dt) 

、プログラムが正常に動作し、プログラムの全体的なアルゴリズムを見ることができます。しかし、私はラムダネストがどのように機能するのか理解できません。私が正しく理解していれば、RK4dyNは、このODE解決方法に必要なときに内部で定義されている関数です。しかし、私は内側のラムダがどのように外側のラムダを使用しているのか分かりません。おそらく私はラムダ構文を正しく理解していないでしょう。

+0

[Understanding Python lambdas](https://stackoverflow.com/questions/32928543/understanding-python-lambdas)の可能な複製 – LutzL

答えて

2

ここでは、ラムダ関数が定義され、すぐに呼び出されることがあります。まず、次はyの平方を計算するだけの複雑な方法であることを認識:

(lambda x: 
    x**2 
)(y) 

順番に営巣が経過すると、その引数を変更するには、このような構成の周りに別のlambdaをラップします。再び、次のだからすなわち、(math.sin(w))**2

(lambda z: (
     lambda x: x**2 
    )(math.sin(z)) 
) (w) 

wの正弦の二乗を計算するために複雑な方法であろう、これを読み取るための方法は、相互に下から上へのステップを適用することです。通常の機能とし、ネストされた呼び出しなしであなたの例からlambda構築 - を書く

、それは次のようになります。

def step_5(f,dy1,dy2,dy3,dy4): 
    return (dy1 + 2 * dy2 + 2 * dy3 + dy4)/6 

def step_4(f,dy1,dy2,dy3): 
    return step_5(dy1,dy2,dy3, dt * f(t + dt, y + dy3)) 

def step_3(f,dy1,dy2): 
    return step_4(dy1,dy2, dt * f(t + dt/2, y + dy2/2)) 

def step_2(f,dy1): 
    return step_3(dy1, dt * f(t + dt/2, y + dy1/2)) 

def RK4(f): 
    return step_2(dt * f(t, y)) 

そこから、それは読み出し可能に書かれたルンゲクッタ法への唯一の短いステップです。

関連する問題