I found the following code in my search to improve my codes for numerical analysis:
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)
Now, the program works fine and can see the overall algorithm of the program. But i can't understand how does the lambda nesting works. If i understand correctly all the dyN
in RK4
are functions that are defined inside as they are needed for this ODE-solving method. But i don't know how the inner lambdas use the outer lambdas in their definition. Perhaps I'm not understanding the lambda syntax correctly.
What happens here is that lambda functions are defined and immediately called. First, realise that the following is just a complicated way of calculating the square of y
:
( lambda x:
x**2
)( y )
The nesting in turn passes wraps another lambda
around such a construction to modify its argument. Again, the following would be a complicated way to calculate the square of the sine of w
, i.e., (math.sin(w))**2
( lambda z: (
lambda x: x**2
)(math.sin(z))
) (w)
So, the way to read this is to apply the steps from bottom to top to each other.
Writing the lambda
-construction from your example with normal functions and without nested calls, it becomes:
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) )
From there, it is only a short step to a readably written Runge–Kutta method.