Sitemap

Calculus using Functional Python

4 min readNov 13, 2021
Press enter or click to view image in full size
Photo by Jafet Reyes on Unsplash

The aim this piece is to demonstrate some concepts of functional programming in Python, let’s dive-in!

Part Derivative:

The following function calculates the slope on a non-linear line.

Press enter or click to view image in full size
https://en.wikipedia.org/wiki/derivative

Now let rewrite the code in Python.

derivative = lambda f, x: ((f(x + 1e-3) - f(x)) / 1e-3)

This function is equivalent to the prior:

def derivative (f, x):
return ((f(x + 1e-3) - f(x)) / 1e-3)

Functions in Python are first-class functions, which means that you can treat them as variables.

Note that the value 1e-3 (0.001) is the limit when h approaches zero (h → 0).

Now we use a partial function:

derivative_of_sin = partial(derivative, math.sin)

Partial functions allow us to pass fewer arguments to multiple arguments function.

In this example, we create a partial function from the function derivative, and its first argument (the sine function), leaving x for call time.

x = 5
derivative_of_sin(x) # --> 0.28
math.cos(x) # --> 0.28

Correct! since the derivative of sin is cos.

Let’s try x²

derivative_of_x2 = partial(derivative, lambda a: a * a)

As you can see, we passed a lambda calculus expression because our function derivative expects a function.

derivative_of_x2(x) # --> 10

Ten is the correct answer since the derivative of is 2 * x.

Try to plug your function.

Part Integral:

We are going to use algebra to tackle the integral function.

This function has four important arguments; the range from a to b, the steps, and the input function.

Press enter or click to view image in full size
https://en.wikipedia.org/wiki/integral

In calculus, we find the integral of (x³ / 3) to find the solution.
With algebra, we stack multiple rectangles together to find the solution.

Using algebra:

| steps     | equation                     |   result |
|-----------+------------------------------+----------|
| 100 | (1e-1) * (10^2 + ... + 20^2) | 2318.349 |
| 1_000 | (1e-2) * (10^2 + ... + 20^2) | 2331.833 |
| 10_000 | (1e-3) * (10^2 + ... + 20^2) | 2333.183 |
| 100_000 | (1e-4) * (10^2 + ... + 20^2) | 2333.318 |
| 1_000_000 | (1e-5) * (10^2 + ... + 20^2) | 2333.331 |
| | | |
*steps count = (20 - 10) / 1e-5 = 1_000_000

Using calculus:

(1 / 3) * (20**3) - (1 / 3) * (10**3) # --> 2333.33

The algebra method is approaching the correct solution, albeit it requires a lot of calculation than you transistors!

Let’s define the function:

def integral (f, a, b):
delta = 1e-6
auc = 0
for i in np.arange(a, b, delta):
auc = auc + f(i)
return auc * delta

Note that AUC stands for the area under the curve.

Integral is a high-order function, which means that it can take a function as an argument or return a function.

Now, let’s use partial again:

integral_of_x2 = partial(integral, lambda x: x**2)

if we pass our partial function with the limits a and b, we get:

integral_of_x2(10, 20)    # ==> 2333.331

Hooray!

Part Integral++:

Another approach is using closures:

def integral (f, s):
delta = s
def g (a, b):
auc = 0
for i in np.arange(a, b, delta):
nonlocal auc
auc += f(i)
return auc * delta
return g

The integral function will return the function g.

The function g holds the value of delta way after the execution of the outer function; this is closure.

Next, we pass a complex function and the number of steps delta.

integral_of_complex = integral(lambda x: (5*x**2) - (8*x) + 5, 1e-5)

Passing the limits:

integral_of_complex2(10, 20) # --> 10515.66

That’s correct!

Final thoughts:

Functional programming has many elegant concepts, some concepts covered:

  • first-class functions
  • partial functions
  • lambda calculus
  • high-order functions
  • closures

You can find more examples on the GitHub link with additional functional techniques.

https://github.com/booletic/medium/blob/34b60709ce0bd0d657e1e2c88a58125a19b6ee91/calculus.ipynb

--

--

Responses (1)