{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Monte Carlo Integration\n",
"\n",
"Monte Carlo Integration is an integral approximation method using random inputs. It is discussed in § 8.5 of \n",
"* [L] *A Primer on Scientific Programming with Python* by Hans Petter Langtangen, 2nd edition.\n",
"\n",
"There is a lot of useful information in Chapter 8 of [L]. You should read the full chapter.\n",
"\n",
"\n",
"**Topics Discussed:**\n",
"* Monte Carlo Integration\n",
"* Another example of the use of classes\n",
"* Vectorization"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# Standard imports\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import math as m\n",
"from mpmath import mp, iv"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Monte Carlo Integration\n",
"\n",
"Let $B$ be a box in $n$-dimensional space determined by vectors $a, b \\in {\\mathbb R}^n$:\n",
"$$B = \\{x \\in {\\mathbb R}^n: \\text{$a_i \\leq x_i \\leq b_i$ for $i=0, \\ldots, n-1$}\\}.$$\n",
"Let $f$ be a real-valued function defined on $B$. We are interested in estimating the integral of $f$ over $B$ with respect to $n$-dimensional volume:\n",
"$$I = \\int_B f~dV.$$\n",
"\n",
"If $x^{(0)}, x^{(1)}, \\ldots, x^{(K-1)}$ are $K$ uniformly distributed random elements of $B$, then an estimate for the integral $I$ is given by\n",
"$$\\frac{Vol(B)}{K} \\sum_{i=0}^{K-1} f(x^{(i)}).$$\n",
"Estimating an integral in this way is called (naive) *Monte Carlo Integration*. \n",
"\n",
"This type of integration is discussed in **L** § 8.5. It is very slow, but has the advantage that it is just as fast in high dimensions as it is in low dimensions. There are variants of this integration technique which are much faster (but also more difficult to program). A more comprehensive article on the subject is here:\n",
"* Caflisch, R. E. (1998). \"Monte Carlo and quasi-Monte Carlo methods\". Acta Numerica . 7 : 1–49. doi:10.1017/S0962492900002804 ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Boxes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To emphasize the recently learned programming technique of classes, we will attempt to use classes to program Monte Carlo Integration. First we will represent a box as a class. We should create a box by passing two vectors `a` and `b` such that each coordinate of $a$ is smaller than the corresponding coordinate of $b$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Below we create an initial version of a box class. It just has an initialization method taking vectors `a` and `b` and a `__repr__` method for giving a nice string representation."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"class Box:\n",
" def __init__(self, a, b):\n",
" r\"\"\"\n",
" Construct a box from two vectors a and b. These vectors must be of the same\n",
" size and the entries of a must be smaller than those of b.\n",
" \"\"\"\n",
" # Copy the a and b values, and make sure they are numpy arrays.\n",
" self._a = np.array(a)\n",
" self._b = np.array(b)\n",
" \n",
" # Check to see that a and b are vectors of the same shape:\n",
" if self._a.shape != self._b.shape:\n",
" raise ValueError(\"Vectors a and b need to have the same shape.\")\n",
" \n",
" # Check that the coordinates of a are all smaller than the coordinates of b.\n",
" if not (self._a < self._b).all():\n",
" raise ValueError(\"The coordinates of the vector a need to be smaller than \" +\n",
" \"those of b.\")\n",
" \n",
" def __repr__(self):\n",
" return \"Box({}, {})\".format(repr(self._a), repr(self._b))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that the `__init__` method will cause `ValueErrors` if the data passed to it is incorrect. According to the [Python Documentation](https://docs.python.org/3/library/exceptions.html#ValueError), “a `ValueError` is raised when an operation or function receives an argument that has the right type but an inappropriate value.” "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Below we demonstrate the use of the class to represent the a square in the plane centered at the origin with sidelength $2$."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Box(array([-1, -1]), array([1, 1]))"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"B = Box([-1, -1], [1, 1])\n",
"B"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notice that the volume of the box shows up in our integral calculation. We add a method to compute the volume of our box. Note that `np.prod` can be used to compute the product of elements of a vector. Thus the volume should be `np.prod(b-a)`."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"class Box:\n",
" def __init__(self, a, b):\n",
" r\"\"\"\n",
" Construct a box from two vectors a and b. These vectors must be of the same\n",
" size and the entries of a must be smaller than those of b.\n",
" \"\"\"\n",
" # Copy the a and b values, and make sure they are numpy arrays.\n",
" self._a = np.array(a)\n",
" self._b = np.array(b)\n",
" \n",
" # Check to see that a and b are vectors of the same shape:\n",
" if self._a.shape != self._b.shape:\n",
" raise ValueError(\"Vectors a and b need to have the same shape.\")\n",
" \n",
" # Check that the coordinates of a are all smaller than the coordinates of b.\n",
" if not (self._a < self._b).all():\n",
" raise ValueError(\"The coordinates of the vector a need to be smaller than \" +\n",
" \"those of b.\")\n",
" \n",
" def __repr__(self):\n",
" return \"Box({}, {})\".format(repr(self._a), repr(self._b))\n",
"\n",
" def volume(self):\n",
" \"\"\"Return the volume of this box.\"\"\"\n",
" return np.prod(self._b - self._a)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"4"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"B = Box([-1, -1], [1, 1])\n",
"B.volume()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The other thing we need is to be able to sample a uniformly random point in the box. Note that `v = np.random.random_sample(size)` returns a random vector `v` of the given size with entries taken uniformly at random from `[0,1)`. Then \n",
"$$(b-a)*v+a$$\n",
"will be a uniformly random element of our box."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"class Box:\n",
" def __init__(self, a, b):\n",
" r\"\"\"\n",
" Construct a box from two vectors a and b. These vectors must be of the same\n",
" size and the entries of a must be smaller than those of b.\n",
" \"\"\"\n",
" # Copy the a and b values, and make sure they are numpy arrays.\n",
" self._a = np.array(a)\n",
" self._b = np.array(b)\n",
" \n",
" # Check to see that a and b are vectors of the same shape:\n",
" if self._a.shape != self._b.shape:\n",
" raise ValueError(\"Vectors a and b need to have the same shape.\")\n",
" \n",
" # Check that the coordinates of a are all smaller than the coordinates of b.\n",
" if not (self._a < self._b).all():\n",
" raise ValueError(\"The coordinates of the vector a need to be smaller than \" +\n",
" \"those of b.\")\n",
" \n",
" def __repr__(self):\n",
" return \"Box({}, {})\".format(repr(self._a), repr(self._b))\n",
"\n",
" def volume(self):\n",
" \"\"\"Return the volume of this box.\"\"\"\n",
" return np.prod(self._b - self._a)\n",
" \n",
" def random(self):\n",
" \"\"\"Return a uniformly random point in the box.\"\"\"\n",
" # To simplify notation:\n",
" a = self._a\n",
" b = self._b\n",
" return (b-a)*np.random.random_sample(a.size) + a"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here we demonstrate the use of the random method."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([-0.37186459, 0.89479477])"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"B = Box([-1, -1], [1, 1])\n",
"B.random()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here we plot 100 random points in the box."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"x = []\n",
"y = []\n",
"for i in range(100):\n",
" xcoord,ycoord = B.random()\n",
" x.append(xcoord)\n",
" y.append(ycoord)\n",
"\n",
"plt.plot(x, y, \"o\")\n",
"plt.gca().set_aspect(1)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we are ready to try to estimate an integral. Recall that we estimate the integral of $f$ over $B$ using $K$ uniformly distributed random elements of $B$ and computing \n",
"$$\\frac{Vol(B)}{K} \\sum_{i=0}^{K-1} f(x^{(i)}).$$\n",
"\n",
"Below we add a `integral_estimate` function to our class. We will use `f` for our function and `trials` for $K$ above."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"class Box:\n",
" def __init__(self, a, b):\n",
" r\"\"\"\n",
" Construct a box from two vectors a and b. These vectors must be of the same\n",
" size and the entries of a must be smaller than those of b.\n",
" \"\"\"\n",
" # Copy the a and b values, and make sure they are numpy arrays.\n",
" self._a = np.array(a)\n",
" self._b = np.array(b)\n",
" \n",
" # Check to see that a and b are vectors of the same shape:\n",
" if self._a.shape != self._b.shape:\n",
" raise ValueError(\"Vectors a and b need to have the same shape.\")\n",
" \n",
" # Check that the coordinates of a are all smaller than the coordinates of b.\n",
" if not (self._a < self._b).all():\n",
" raise ValueError(\"The coordinates of the vector a need to be smaller than \" +\n",
" \"those of b.\")\n",
" \n",
" def __repr__(self):\n",
" return \"Box({}, {})\".format(repr(self._a), repr(self._b))\n",
"\n",
" def volume(self):\n",
" \"\"\"Return the volume of this box.\"\"\"\n",
" return np.prod(self._b - self._a)\n",
" \n",
" def random(self):\n",
" \"\"\"Return a uniformly random point in the box.\"\"\"\n",
" # To simplify notation:\n",
" a = self._a\n",
" b = self._b\n",
" return (b-a)*np.random.random_sample(a.size) + a\n",
"\n",
" def integral_estimate(self, f, trials):\n",
" \"\"\"\n",
" Estimate the integral of f over this box using Monte Carlo integration.\n",
" \n",
" The function `f` should be a real-valued function defined on vectors in the box.\n",
" We estimate the integral by sampling vectors at random from the box. The number\n",
" of vectors used is given by the integer `trials`.\n",
" \"\"\"\n",
" # We compute the sum of f(x^(i)) where x^(i) is taken at random.\n",
" # We'll store the result in total.\n",
" total = 0\n",
" for i in range(trials):\n",
" total += f(self.random())\n",
" \n",
" # return the estimated integral:\n",
" return self.volume() * total / trials\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We will do a standard thing: Attempt to compute $\\pi$. The number $\\pi$ is the area of the unit circle. So, we can define\n",
"$$f(x,y) = \\begin{cases}\n",
"1 & \\text{if $x^2+y^2 \\leq 1$} \\\\\n",
"0 & \\text{otherwise.}\n",
"\\end{cases}$$\n",
"Then if $B$ is the box used in our examples above, \n",
"$$\\pi = \\int_B f~dA.$$\n",
"Thus we can approximate $\\pi$ by choosing points at random from $B$ and computing \n",
"$$\\frac{Vol(B)}{K} \\sum_{i=0}^{K-1} f(x^{(i)}).$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To do this, we only need to code the function $f$. Note that the function takes as input a vector with two entries. The two coordinates of `v` can be accessed using `x,y = v`."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"def f(v):\n",
" x,y = v\n",
" if x**2 + y**2 <= 1:\n",
" return 1\n",
" else:\n",
" return 0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here we approximate $\\pi$ using 1000 points."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3.2"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"B = Box([-1, -1], [1, 1])\n",
"B.integral_estimate(f, 1000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that the algorithm is random, so the estimate will vary as we recompute."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3.104"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"B.integral_estimate(f, 1000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To get a better estimate we can increase the number of points used:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3.12928"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"B.integral_estimate(f, 100000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Below we compute the error as a function of the number of points, using powers of two for the number of points."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"powers = [m.floor(1.25**k) for k in range(1,60)]\n",
"errors = []\n",
"for k in powers:\n",
" error = abs( B.integral_estimate(f,k) - m.pi )\n",
" errors.append(error)\n",
"plt.plot(powers, errors, \"o\")\n",
"plt.xscale(\"log\")\n",
"plt.yscale(\"log\")\n",
"plt.xlabel(\"Number of points used\")\n",
"plt.ylabel(\"Error in integral estimate\")\n",
"plt.title(\"Number of points versus Error (log-log plot)\")\n",
"plt.gca().set_aspect(1)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In the log-log plot, you should see the error estimates clustering along a line of slope $-\\frac{1}{2}$. This indicates that the error is on the order of a constant times $\\frac{1}{\\sqrt{K}}$ where $K$ is the number of points used. This is the typical form of the error estimate in any dimension.\n",
"\n",
"Unfortunately this is a very slow improvement of the error. To get an extra digit of precision, we need to use 100 times as many sample points! Even using a million points as below only seems to give a few digits of accuracy."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3.14126"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"B.integral_estimate(f, 10**6)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Vectorization\n",
"\n",
"Vectorization is a computational technique to speed up repetitive computations. Numpy has vectorized methods that increase computational speed. I will demonstrate this and then give a heuristic explaination of why it works. \n",
"\n",
"Vectorization is discussed in **L** in § 4.2.4 and in the context of Random Numbers and Games in § 8.3.2 and later examples in chapter 8.\n",
"\n",
"*Remark:* Vectorization is an advanced topic and will not be tested. However, it may be important in work in the real world. In this notebook, I notice a speed up of at least $100 \\times$ when using vectorization."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For example if we let `x` be a random collection of 100,000 numbers. Then we can sum in three ways: \n",
" * Looping.\n",
" * Use python's built in `sum` function.\n",
" * Use numpy's `sum` function.\n",
"\n",
"We'll use [`timeit`](https://docs.python.org/3/library/timeit.html) to time how long each method takes."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"x = np.random.random_sample(100000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To use `timeit` we find it convienient to write our two sum methods as functions:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"def loop_sum():\n",
" total = 0.0\n",
" for value in x:\n",
" total += value\n",
" return total\n",
"\n",
"def built_in_sum():\n",
" return sum(x)\n",
"\n",
"def np_sum():\n",
" return np.sum(x)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"import timeit"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The following is the time (in seconds) it takes to run `loop_sum` 100 times."
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.9095920210238546"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"loop_time = timeit.timeit(loop_sum, number=100)\n",
"loop_time"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now `built_in_sum`."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.8919960469938815"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"built_in_time = timeit.timeit(built_in_sum, number=100)\n",
"built_in_time"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that the above two times are about the same.\n",
"\n",
"Now we store the amount of time it takes to run `np_sum` 10 times."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.005518718040548265"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np_sum_time = timeit.timeit(np_sum, number=100)\n",
"np_sum_time"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"That took much less time. We can compute the speed up by taking the ratio:"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"164.81944073618408"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"loop_time / np_sum_time"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The numpy method is over $100\\times$ faster on my computer!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The reason for the speed increase is that numpy knows several things the other algorithms don't take advantage of:\n",
"* The things being added are (standard floating point) numbers.\n",
"* The numbers are stored in an organized way (since they are numpy arrays).\n",
"\n",
"The numpy `sum` function takes advantage of hardware and software optimization made possible by knowing these facts to compute the sum quickly. The computations `numpy` carries out are done in pre-compiled and optimized `C` code, whereas the other two computations are carried out directly in Python, which slows things down. Essentially vectorization makes up for the [speed difference between Python and C](https://wiki.python.org/moin/Why%20is%20Python%20slower%20than%20the%20xxx%20language).\n",
"\n",
"The built in `sum` function and the loop algorithm both work with more general data types, which is very useful if not fast. For example, the built in `sum` works with lists as demonstrated below."
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sum([[i] for i in range(10)], [])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We'd like to take advantage of this in our code. The first thing to do is to allow the `random` method to take a parameter `trials` giving number of random points to compute. We give the number of trials a default value of `None` to use the old behavior of returning just one point. Otherwise, we `trials` can be set to a positive integer. We'd like to return a matrix in this case with `trials` columns and a random point in the box in each column. After trial and error, we found the following command did this:\n",
"```python\n",
"((b-a)*np.random.random_sample((trials,)+a.shape) + a).transpose()\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In the `integral_estimate` method, we will call the `random` method with the trials parameter. Then we make use of the `sum` function in `numpy` to add the images of the random points under our function `f`. Our function `f` must therefore be able to handle numpy arrays."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Below we have the vectorized version of the `Box` class."
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
"class VectorizedBox:\n",
" def __init__(self, a, b):\n",
" r\"\"\"\n",
" Construct a box from two vectors a and b. These vectors must be of the same\n",
" size and the entries of a must be smaller than those of b.\n",
" \"\"\"\n",
" # Copy the a and b values, and make sure they are numpy arrays.\n",
" self._a = np.array(a)\n",
" self._b = np.array(b)\n",
" \n",
" # Check to see that a and b are vectors of the same shape:\n",
" if self._a.shape != self._b.shape:\n",
" raise ValueError(\"Vectors a and b need to have the same shape.\")\n",
" \n",
" # Check that the coordinates of a are all smaller than the coordinates of b.\n",
" if not (self._a < self._b).all():\n",
" raise ValueError(\"The coordinates of the vector a need to be smaller than \" +\n",
" \"those of b.\")\n",
" \n",
" def __repr__(self):\n",
" return \"Box({}, {})\".format(repr(self._a), repr(self._b))\n",
"\n",
" def volume(self):\n",
" \"\"\"Return the volume of this box.\"\"\"\n",
" return np.prod(self._b - self._a)\n",
" \n",
" def random(self, trials = None):\n",
" \"\"\"\n",
" By default trials is None and we return a uniformly random point in the box.\n",
" \n",
" Otherwise trials should be a positive integer. We return a matrix with the \n",
" number of columns equal to trials. Each column is a point in the box chosen\n",
" uniformly at random.\n",
" \"\"\"\n",
" # To simplify notation:\n",
" a = self._a\n",
" b = self._b\n",
" if trials is None:\n",
" # Default handling\n",
" return (b-a)*np.random.random_sample(a.size) + a\n",
" else:\n",
" # Handling if using multiple trials.\n",
" return ((b-a)*np.random.random_sample((trials,)+a.shape) + a).transpose()\n",
"\n",
" def integral_estimate(self, f, trials):\n",
" \"\"\"\n",
" Estimate the integral of f over this box using Monte Carlo integration.\n",
" \n",
" The function `f` should be a real-valued function defined on vectors in the box.\n",
" We estimate the integral by sampling vectors at random from the box. The number\n",
" of vectors used is given by the integer `trials`.\n",
" \n",
" The function `f` allow numpy arrays (matrices) as input for multiple trials \n",
" (with each trial a column of the matrix).\n",
" \"\"\"\n",
" # We compute the sum of f(x^(i)) where x^(i) is taken at random.\n",
" # We'll store the result in total.\n",
" total = np.sum(f(self.random(trials)))\n",
" # return the estimated integral:\n",
" return self.volume() * total / trials"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Our usual box in the plane:"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
"B = VectorizedBox([-1, -1], [1, 1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here we check that the `random` method of `VectorizedBox` works as expected."
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0.59881336, 0.41775306])"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"B.random()"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[-0.21416903, -0.87180757, 0.0078377 , -0.18763971, -0.11024967],\n",
" [-0.20580511, 0.66991187, -0.35497872, 0.95677071, 0.4738001 ]])"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v = B.random(5)\n",
"v"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that each column is a random point in the box. This is what we wanted."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we vectorize our function $f$. Note that it will return `True` or `False`."
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [],
"source": [
"def vectorized_f(v):\n",
" x,y = v\n",
" return x**2 + y**2 <= 1"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([ True, False, True, True, True])"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vectorized_f(v)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In Python, when you use True and False in numerical expressions `True` is $1$ and `False` is $0$. So, we can find the number of trues with:"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"4"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.sum(vectorized_f(v))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Our integral approximation should be working then. Here we try with a million trials. It runs much faster."
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3.139592"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"B.integral_estimate(vectorized_f, 10**6)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We will use `timeit` to compare the original method with the vectorized version."
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [],
"source": [
"def original_computation():\n",
" B = Box([-1, -1], [1, 1])\n",
" return B.integral_estimate(f, 10**6)\n",
"\n",
"def vectorized_computation():\n",
" B = VectorizedBox([-1, -1], [1, 1])\n",
" return B.integral_estimate(vectorized_f, 10**6)"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"5.060465669957921"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"t1 = timeit.timeit(original_computation, number=1)\n",
"t1"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.04013419500552118"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"t2 = timeit.timeit(vectorized_computation, number=1)\n",
"t2"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"126.08863013850815"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"t1/t2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This version is about a 100 times faster. We extend our error graph from above:"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"B = VectorizedBox([-1, -1], [1, 1])\n",
"powers = [m.floor(1.25**k) for k in range(1,80)]\n",
"errors = []\n",
"for k in powers:\n",
" error = abs( B.integral_estimate(vectorized_f,k) - m.pi )\n",
" errors.append(error)\n",
"plt.plot(powers, errors, \"o\")\n",
"plt.xscale(\"log\")\n",
"plt.yscale(\"log\")\n",
"plt.xlabel(\"Number of points used\")\n",
"plt.ylabel(\"Error in integral estimate\")\n",
"plt.title(\"Number of points versus Error (log-log plot)\")\n",
"plt.gca().set_aspect(1)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Example: Volume of a torus"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let $C$ be the unit circle in the $xy$-plane centered at the origin and of radius $2$. Let $T$ be the three dimensional region consisting of points whose distance from $C$ is less than one. We will estimate the volume of $T$, which is a solid torus."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here $R=2$ is the major radius and $r=1$ is the minor radius. The volume of a torus of this form has the formula \n",
"$$V=2 \\pi^2 r^2 R.$$\n",
"See for example, the [discussion on Wikipedia](https://en.wikipedia.org/wiki/Torus#Geometry)."
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"39.47841760435743"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"actual_volume = 2*np.pi**2*2\n",
"actual_volume"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Before computing the volume, we will plot it to get a sense of what $T$ looks like."
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[]"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"from mpl_toolkits.mplot3d import Axes3D\n",
"fig = plt.figure()\n",
"ax = fig.gca(projection='3d')\n",
"theta = np.linspace(0, 2*np.pi, 100)\n",
"ax.plot(2*np.cos(theta), 2*np.sin(theta),0, \"r\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The distance from a point to a smooth curve can be realized by a line segment between the point and the curve which is orthogonal to the curve. (This is essentially the principle behind Lagrange multipliers.) A point $(x,y,0)$ on $C$ determines a plane orthogonal to $C$ at $(x,y,0)$: the span of the unit orthogonal vectors $\\frac{1}{2} (x,y,0)$ and $(0,0,1)$. Thus the points $(x',y',z')$ that have unit distance from $(x,y,0)$ and so that the line segment from $(x',y',z')$ to $(x,y,0)$ is perpendicular to $C$ have the form:\n",
"$$(x',y',z') = (x,y,0) + \\frac{\\cos \\phi}{2} (x,y,0) + \\sin \\phi(0,0,1)$$\n",
"for some angle $\\phi$. This means that we can parameterize the boundary of $T$ using\n",
"$$(x',y',z') = (1+\\frac{\\cos \\phi}{2}) (2 \\cos \\theta,2\\sin \\theta,0) + \\sin \\phi(0,0,1)$$\n",
"or\n",
"$$(x',y',z') = \\left((2+\\cos \\phi)\\cos \\theta, (2+\\cos \\phi)\\sin \\theta, \\sin \\phi\\right).$$"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"from matplotlib import cm\n",
"from matplotlib.ticker import LinearLocator, FormatStrFormatter\n",
"\n",
"fig = plt.figure(figsize=plt.figaspect(0.333)*1.5)\n",
"ax = fig.gca(projection='3d')\n",
"ax.view_init(70,20)\n",
"\n",
"# Make data.\n",
"theta = np.linspace(0, 2*np.pi, 100)\n",
"phi = np.linspace(0, 2*np.pi, 100)\n",
"theta, phi = np.meshgrid(theta, phi)\n",
"X = (2+np.cos(phi))*np.cos(theta)\n",
"Y = (2+np.cos(phi))*np.sin(theta)\n",
"Z = np.sin(phi)\n",
"\n",
"# Plot the surface.\n",
"surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,\n",
" linewidth=0, antialiased=False)\n",
"\n",
"# Customize the z axis.\n",
"#ax.set_zlim(-1.0, 1.0)\n",
"ax.zaxis.set_major_locator(LinearLocator(10))\n",
"ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))\n",
"\n",
"# Add a color bar which maps values to colors.\n",
"fig.colorbar(surf, shrink=0.5, aspect=5)\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To find the volume of the region, by 3D Monte Carlo Integration we need a function that returns True for points in the torus and False for points outside the torus. The closest point on the circle $C$ to $(x,y,z)$ is \n",
"$$\\left(\\frac{2x}{\\sqrt{x^2+y^2}}, \\frac{2y}{\\sqrt{x^2+y^2}},0\\right)$$\n",
"unless $x=y=0$ in which case all points on the circle are equally distant. So, we can check if the distanct from $C$ is less than one by computing the distance from $(x,y,z)$ to the above point. This is \n",
"$$\\sqrt{\\left(x - \\frac{2x}{\\sqrt{x^2+y^2}}\\right)^2 + \\left(y - \\frac{2y}{\\sqrt{x^2+y^2}}\\right)^2 + z^2}.$$\n",
"We can just check if the square of this distance is less than one."
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [],
"source": [
"def inside_torus(v):\n",
" x,y,z = v\n",
" dist_from_z_axis = np.sqrt(x**2 + y**2)\n",
" return (x-2*x/dist_from_z_axis)**2 + \\\n",
" (y-2*y/dist_from_z_axis)**2 + z**2 <= 1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"With this function, we can try to compute the volume."
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [],
"source": [
"box = VectorizedBox((-3,-3,-1), (3,3,1))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We use ten million sample points:"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"39.4777296"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"volume_estimate = box.integral_estimate(inside_torus, 10**7)\n",
"volume_estimate"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Below we indicate the absolute error:"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.00068800435742844"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"error = abs(volume_estimate - actual_volume)\n",
"error"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It is also possible to compute the volume as a 2D integral. We'd express the volume of $T$ as an integral of the form\n",
"$$Vol(T) = \\int_{-3}^3 \\int_{-3}^3 f(x,y)~dy~dx.$$\n",
"Here $f(x,y)$ would be the function which is zero if $(x,y,0)$ lies outside the torus and would be the length of the line segment joining $(x,y,z)$ to $(x,y,-z)$ where $(x,y,z)$ is a point in the boundary of $T$. The closest point on $C$ to all of these points on the line segment is again \n",
"$$\\left(\\frac{2x}{\\sqrt{x^2+y^2}}, \\frac{2y}{\\sqrt{x^2+y^2}},0\\right)$$\n",
"Our $z$ is the positive real number so that \n",
"$$1 = \\sqrt{\\left(x - \\frac{2x}{\\sqrt{x^2+y^2}}\\right)^2 + \\left(y - \\frac{2y}{\\sqrt{x^2+y^2}}\\right)^2 + z^2}.$$\\\n",
"Solving for $z^2$ we see that \n",
"$$z^2 = 1 - \\left(x - \\frac{2x}{\\sqrt{x^2+y^2}}\\right)^2 - \\left(y - \\frac{2y}{\\sqrt{x^2+y^2}}\\right)^2.$$\n",
"If this number is negative then $(x,y,0)$ will not be in $T$. Thus, we have\n",
"$$f(x,y) = 2\\sqrt{\\max\\left(0, 1 - \\left(x - \\frac{2x}{\\sqrt{x^2+y^2}}\\right)^2 - \\left(y - \\frac{2y}{\\sqrt{x^2+y^2}}\\right)^2\\right)}.$$\n",
"\n",
"To code this we discovered the `maximum` function in numpy which differs from the `max` function. The `maximum` function returns the maximum of two values, while `max` returns the maximum over an array."
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [],
"source": [
"def f(v):\n",
" x,y = v\n",
" dist_from_z_axis = np.sqrt(x**2 + y**2)\n",
" return 2*np.sqrt(np.maximum(0.,\n",
" 1.0 - (x-2*x/dist_from_z_axis)**2 - (y-2*y/dist_from_z_axis)**2))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here we create our 2D box."
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [],
"source": [
"box = VectorizedBox((-3,-3), (3,3))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we estimate the volume using 10 million sample points."
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"39.48084506392184"
]
},
"execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"volume_estimate = box.integral_estimate(f, 10**7)\n",
"volume_estimate"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.002427459564408707"
]
},
"execution_count": 47,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"error = abs(volume_estimate - actual_volume)\n",
"error"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}