In first year calculus the definite integral of a function \(f(x)\) over the interval \([a, b]\) is defined to be the limit of a sequence of Riemann sums: \[ \int_a^b f(x)\, dx = \lim_{n \to \infty} \sum_{i=0}^{n-1} f(x_i) \, \Delta x \] where \(\Delta x = (b - a)/n\) and \(x_i = a + i \cdot \Delta x\) - So the definite integral can be approximated using Riemann sums for suitably large values of \(n\)
import numpy as np
def num_int(f, a, b, n):
dx = (b-a)/n
x = np.arange(a, b, step = dx)
y = f(x)
return y.sum() * dx
Note this takes a function f
as input.
Try approximating \(\int_0^1 x^2 \, dx\) with \(n=\{10,50,5000\}\)
def x_squared(x):
return x ** 2
approx1 = num_int(x_squared, 0, 1, 10)
approx2 = num_int(x_squared, 0, 1, 50)
approx3 = num_int(x_squared, 0, 1, 5000)
print(approx1, approx2, approx3)
## 0.2850000000000001 0.3234 0.33323334
We could create an adaptive version of this that keeps trying larger values of n
until the results are “close enough”
num_int
uses the left endpoint rule to compute Riemann sums for a function \(f(x)\)\[ \begin{split} \int_a^b f(x)\, dx & = \lim_{n \to \infty} \sum_{i=0}^{n-1} f(x_{i+1}) \, \Delta x \qquad \textrm{right endpoint} \\ \int_a^b f(x)\, dx & = \lim_{n \to \infty} \sum_{i=0}^{n-1} f\left((x_i+x_{i+1})/2\right) \, \Delta x \qquad \textrm{midpoint} \end{split} \]
We’ll write a function that implements any of these rules, and check it with \(\int_0^1 x^2 \, dx\) and \(\int_0^1 x^3 \, dx\).
from sympy import *
x = Symbol('x')
integrate(x**2,x) ## no "plus a constant"
## x**3/3
Or definite integrals:
integrate(x**2,(x,0,1))
## 1/3
But:
integrate(log(x)**x,x)
## Integral(exp(x*log(log(x))), x)
(see Wikipedia for more information on symbolic integration)
integrate(sqrt(1-x**2),x)
## x*sqrt(-x**2 + 1)/2 + asin(x)/2
integrate(sqrt(1-x**2),(x,0,1))
## pi/4
numpy.linspace(start,stop,num, endpoint=True)
is a more convenient way to generate evenly (linearly) spaced valuesnumpy.arange()
)import matplotlib.pyplot as plt
import numpy.random as npr
x = np.linspace(0,1,101)
y = np.sqrt(1-x**2)
fig, ax = plt.subplots()
ax.plot(x,y)
xr = npr.uniform(size=200)
yr = npr.uniform(size=200)
incirc = xr**2+yr**2<1
ax.plot(xr[incirc],yr[incirc],"b*")
ax.plot(xr[np.logical_not(incirc)],yr[np.logical_not(incirc)],"ro")
from math import pi
incirc.mean()*4/pi
## 0.884901483590938
Overlap of circles at (1.5,2.5) (radius 1), (4,3) (radius 3), (1,2) (radius 2)
import numpy.random as npr
import numpy as np
c = ((2,2.5),(4,3),(1,2))
r = (1.5,3,2)
npr.seed(101)
x = npr.uniform(c[0][0]-r[0],c[0][0]+r[0],size=1000000)
y = npr.uniform(c[0][1]-r[0],c[0][1]+r[0],size=1000000)
tests = np.tile(True,10**6) ## boolean vector
def incirc(x,y,ctr,radius):
dsq = (x-ctr[0])**2+(y-ctr[1])**2
return(dsq<radius**2)
for c0,r0 in zip(c,r): ## zip() rearranges lists
tests = tests & incirc(x,y,c0,r0)
print(np.mean(tests))
## 0.78613
## 0.658081
## 0.48976
print(r[0]**2*np.mean(tests))
## 1.10196
x = (a*x +c ) % m
Simple example:
x = [5] ## starting value
a,c,m = 2,3,10 ## constants
for i in range(9):
newx = (a*x[-1]+c) % m
x.append(newx)
print(x)
## [5, 3, 9, 1, 5, 3, 9, 1, 5, 3]
a,c,m = 16807,0,2147483647
x = [5]
for i in range(9):
newx = (a*x[-1]+c) % m
x.append(newx)
print(np.array(x)/m)
## [2.32830644e-09 3.91318463e-05 6.57688941e-01 7.78026611e-01
## 2.93250660e-01 6.63836187e-01 9.47959316e-02 2.35223081e-01
## 3.94323584e-01 3.96482029e-01]
numpy
: referenceimport numpy.random as npr
a = npr.rand(1000)
choice()
(with or without replacement)shuffle()
(in-place)seed()
Rules:
life_init(size, init_dens)
: set up a size*size
2D array of zeros; set a density init_dens
to 1life_step(w,nw)
: run the Conway rules on an array w
and return the new array nw
count_nbr(w,i,j)
: count the number of neighbours in the 3x3 square around w[i,j]
life_show(w, ax)
: plot an image of the current array w
on axes ax
import os
import matplotlib.pyplot as plt
os.chdir("../code")
from life import *
os.chdir("../notes")
w = life_init()
fig, ax = plt.subplots()
life_show(w, ax)
fig.savefig("pix/life1.png")
nw = w.copy()
(nw, w) = life_step(w,nw)
life_show(w, ax)
fig.savefig("pix/life2.png")
fig, ax = plt.subplots(5,5)
for i in range(ax.shape[0]):
for j in range(ax.shape[1]):
nw, w = life_step(w,nw)
life_show(w, ax[i][j])
fig.savefig("pix/life3.png")
fig, ax = plt.subplots(5,5)
for i in range(ax.shape[0]):
for j in range(ax.shape[1]):
for k in range(10):
life_show(w, ax[i][j])
nw, w = life_step(w,nw)
fig.savefig("pix/life4.png")