在此 RK4 ODE 求解器中,内部 lambda 如何使用外部 lambda 函数? Python

How does the inner lambda use the outer lambda fuction in this RK4 ODE-solver? 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)

现在程序运行正常,可以看到程序的整体算法。但我不明白 lambda 嵌套是如何工作的。如果我理解正确,RK4 中的所有 dyN 都是内部定义的函数,因为此 ODE 求解方法需要它们。但我不知道内部 lambdas 如何在它们的定义中使用外部 lambdas。也许我没有正确理解 lambda 语法。

这里发生的是定义并立即调用 lambda 函数。首先,意识到以下只是计算 y 平方的复杂方法:

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

嵌套依次将另一个 lambda 包裹在这样的构造周围以修改其参数。同样,以下是计算 w 的正弦平方的复杂方法,即 (math.sin(w))**2

( lambda z: (
        lambda x: x**2
    )(math.sin(z))
) (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) )

从那里,距离编写可读的龙格-库塔方法仅一小步。