Pi Day 2022 at RelationalAI
To celebrate Pi day, let's have some fun with π in our modeling language Rel.
We are excited to join the growing community of math lovers to celebrate International Pi Day. Pi Day is held on March 14 as its date, 3/14, resembles 3.14 --- the first three digits of π.
To celebrate Pi Day, we’re going to demonstrate how π can be approximated in various ways in our modeling language Rel, ranging from infinite series expressions to Monte-Carlo simulations. If you make it to the end, a little challenge awaits where you can test your Rel skills.
Using the Greek Letter π
Rel ships with a system-provided relation pi_float64
with the value of π as a Float64 number.
def output = pi_float64
Relation: 3.141592653589793
This is great, but the first thing we want to do is to refer to π using the Greek letter π
, which is possible because Rel supports Unicode characters, which are a superset of ASCII.
def π = pi_float64
Now we have a relation named π
that refers to our Float64 number of π. To test that it works, let’s query for this new relation.
Query: def
output
=
π
Output: 3.141592653589793
It works! Now let’s get to work.
Best Approximation of π
First, let’s look which of the following approximations (3.14
, 3.14159
, 22/7
, or 355/113
) comes closest to the actual irrational value of π.
To do this, we define a relation pi
that maps the name of the approximation to its actual value. We can think of pi
as a dictionary in other languages that maps a String name to its Float64 value.
Then we are asking the system to give us the name of the best approximation. In mathematical terms, we perform the following task:
In Rel it looks like this:
def pi["3.14"] = 3.14
def pi["22/7"] = 22/7
def pi["3.14159"] = 3.14159
def pi["355/113"] = 355/113
def best_approximation = argmin[abs[pi[i]-π] for i]
def output = best_approximation
Output: "355/113"
The most accurate approximation of the four options is 355/113
. It’s not surprising that 3.14
and 22/7
are not the most accurate options, but it’s interesting to see that 3.14159
is only the second best. It means that if you want to remember only six digits for π\piπ, the best option is 355/113
.
Computing π Using the Madhava-Leibniz Series
The Madhava-Leibniz series is one of the most famous infinite series that involves π. This series has a long history that goes back as far as the 14th century. It reads:
In Rel, we can express this series very naturally,
@inline
def leibniz_term[k] = (-1)^k/(2*k+1)
@inline
def leibniz_formula[n] =
4*sum[leibniz_term[x]
for x in range[0, n, 1]]
and plot its convergence behavior.
// collect convergence data
module leibniz_data
def n_terms = 50
def terms[i] = i, range(0, n_terms-1, 1, i)
def pi_approx[i] = leibniz_formula[terms[i]]
def error[i] = pi_approx[i] - π
end
// plot data
def output = vegalite:plot[
vegalite:line[:terms, :error, {:data, leibniz_data}]
]
From the plot, we can see that the Madhava-Leibniz series oscillates around π\piπ and converges slowly towards the exact value.
Calculate the Gaussian Integral
Another famous mathematical formula involving π\piπ is the Gaussian integral,
which is ubiquitous in many STEM areas including probability theory, statistics, and physics.
We can express this integral in Rel by discretizing the x axis and turning the integral into a sum x∫dx→∑Δx. We then use Rel’s aggregation capabilities to perform this sum.
// discretization parameters
def n = 100
def x_max = 10.0
def dx = 2*x_max / n
// x points
def x = -x_max + dx * range[0, n-1, 1]
// Gaussian
@inline
def gaussian[x] = natural_exp[-x^2]
// Gaussian Integral
def integral = sum[gaussian[i] for i in x] * dx
def pi = integral^2
def output = pi
Output: 3.1415926535897913
By approximating the integral with 100 points, we can approximate π with a surprisingly high accuracy of around 10−15.
Sampling a Unit Circle with Monte Carlo
Our last example is another famous one. To estimate π, we can use a Monte Carlo simulation. The key idea is to approximate the area of a circle with a radius of 0.5 --- which is π/4 --- by placing random points in an enclosing unit square and counting the points that fall within the circle.
The ratio between the number of points within the circle, Ncircle, and the total number of points placed, Ntotal, approximates the circle area of π/4.
In Rel, we can build this simulation with just a few lines of code:
@inline
def rand = random_threefry_float64
module sample
def size = 10^3
def x[i] = rand[i, 1] - 0.5, range(1, size, 1, i)
def y[i] = rand[i, 2] - 0.5, range(1, size, 1, i)
end
def points_in_circle(i) = sample:x[i]^2 + sample:y[i]^2 < 0.5^2
We’re using the Threefry pseudorandom number generator to place our random points. The module sample
contains all the information about our samples from the sample size size
to the x
and y
positions of the points. The relation points_in_circle
holds all the sample IDs where the point falls within the circle.
The only thing left is the calculation of the ratio Ncircle/Ntotal which we multiply by four to get π
.
Now it’s your turn! Complete the following query, and find the definition for ratio
such that the relation pi
holds the approximate value of π.
// def ratio = ???
def pi = 4*ratio
def output = pi
Output: 3.164
def ratio = count[points_in_circle] / sample:size
We hope you had fun playing around with π in Rel. Happy Pi Day from all of us at RelationalAI!