Files
cds-monte-carlo-methods/Exercise sheet 4/exercise_sheet_04.ipynb
2022-10-04 10:20:27 +02:00

1104 lines
146 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "7711bd97",
"metadata": {},
"source": [
"# Exercise sheet\n",
"\n",
"Some general remarks about the exercises:\n",
"* For your convenience functions from the lecture are included below. Feel free to reuse them without copying to the exercise solution box.\n",
"* For each part of the exercise a solution box has been added, but you may insert additional boxes. Do not hesitate to add Markdown boxes for textual or LaTeX answers (via `Cell > Cell Type > Markdown`). But make sure to replace any part that says `YOUR CODE HERE` or `YOUR ANSWER HERE` and remove the `raise NotImplementedError()`.\n",
"* Please make your code readable by humans (and not just by the Python interpreter): choose informative function and variable names and use consistent formatting. Feel free to check the [PEP 8 Style Guide for Python](https://www.python.org/dev/peps/pep-0008/) for the widely adopted coding conventions or [this guide for explanation](https://realpython.com/python-pep8/).\n",
"* Make sure that the full notebook runs without errors before submitting your work. This you can do by selecting `Kernel > Restart & Run All` in the jupyter menu.\n",
"* For some exercises test cases have been provided in a separate cell in the form of `assert` statements. When run, a successful test will give no output, whereas a failed test will display an error message.\n",
"* Each sheet has 100 points worth of exercises. Note that only the grades of sheets number 2, 4, 6, 8 count towards the course examination. Submitting sheets 1, 3, 5, 7 & 9 is voluntary and their grades are just for feedback.\n",
"\n",
"Please fill in your name here:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "e39c230e",
"metadata": {},
"outputs": [],
"source": [
"NAME = \"Kees van Kempen\"\n",
"NAMES_OF_COLLABORATORS = \"\""
]
},
{
"cell_type": "markdown",
"id": "2e7caa84",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"id": "0c4606a8",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "markdown",
"checksum": "1ba146ece4effd3e8dcf33fe63ec69dc",
"grade": false,
"grade_id": "cell-455926422ebe4f85",
"locked": true,
"schema_version": 3,
"solution": false,
"task": false
}
},
"source": [
"**Exercise sheet 4**\n",
"\n",
"Code from the lectures:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "6d3bb610",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "ac562d84531ae19e1d920c10a8861b8e",
"grade": false,
"grade_id": "cell-6b2d0465c2abaaa6",
"locked": true,
"schema_version": 3,
"solution": false,
"task": false
}
},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pylab as plt\n",
"import networkx as nx\n",
"\n",
"rng = np.random.default_rng()\n",
"%matplotlib inline\n",
"\n",
"def draw_transition_graph(P):\n",
" # construct a directed graph directly from the matrix\n",
" graph = nx.DiGraph(P) \n",
" # draw it in such a way that edges in both directions are visible and have appropriate width\n",
" nx.draw_networkx(graph,connectionstyle='arc3, rad = 0.15',width=[6*P[u,v] for u,v in graph.edges()])\n",
"\n",
"def sample_next(P,current):\n",
" return rng.choice(len(P),p=P[current])\n",
"\n",
"def sample_chain(P,start,n):\n",
" chain = [start]\n",
" for _ in range(n):\n",
" chain.append(sample_next(P,chain[-1]))\n",
" return chain\n",
"\n",
"def stationary_distributions(P):\n",
" eigenvalues, eigenvectors = np.linalg.eig(np.transpose(P))\n",
" # make list of normalized eigenvectors for which the eigenvalue is very close to 1\n",
" return [eigenvectors[:,i]/np.sum(eigenvectors[:,i]) for i in range(len(eigenvalues)) \n",
" if np.abs(eigenvalues[i]-1) < 1e-10]\n",
"\n",
"def markov_sample_mean(P,start,function,n):\n",
" total = 0\n",
" state = start\n",
" for _ in range(n):\n",
" state = sample_next(P,state)\n",
" total += function[state]\n",
" return total/n"
]
},
{
"cell_type": "markdown",
"id": "2f7814d8",
"metadata": {},
"source": [
"## Markov Chain on a graph\n",
"\n",
"**(50 points)**\n",
"\n",
"The goal of this exercise is to use Metropolis-Hastings to sample a uniform vertex in a (finite, undirected) connected graph $G$. More precisely, the state space $\\Gamma = \\{0,\\ldots,n-1\\}$ is the set of vertices of a graph and the desired probability mass function is $\\pi(x) = 1/n$ for $x\\in\\Gamma$. The set of edges is denoted $E = \\{ \\{x_1,y_1\\}, \\ldots,\\{x_k,y_k\\}\\}$, $x_i,y_i\\in\\Gamma$, and we assume that there are no edges connecting a vertex with itself ($x_i\\neq y_i$) and there is at most one edge between any pair of vertices. The **neighbors** of a vertex $x$ are the vertices $y\\neq x$ such that $\\{x,y\\}\\in E$. The **degree** $d_x$ of a vertex $x$ is its number of neighbours. An example is the following graph:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "071e5617",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"edges = [(0,1),(1,2),(0,3),(1,4),(2,5),(3,4),(4,5),(3,6),(4,7),(5,8),(6,7),(7,8),(5,7),(0,4)]\n",
"example_graph = nx.Graph(edges)\n",
"nx.draw(example_graph,with_labels=True)"
]
},
{
"cell_type": "markdown",
"id": "952c97cd",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "markdown",
"checksum": "a9ae9f2c0eb7e99b85fd90ae657a9202",
"grade": false,
"grade_id": "cell-a8413209ddb70ab0",
"locked": true,
"schema_version": 3,
"solution": false,
"task": false
}
},
"source": [
"A natural proposal transition matrix is $Q(x \\to y) = \\frac{1}{d_x} \\mathbf{1}_{\\{\\{x,y\\}\\in E\\}}$. In other words, when at $x$ the proposed next state is chosen uniformly among its neighbors.\n",
"\n",
"__(a)__ Write a function `sample_proposal` that, given a (networkX) graph and node $x$, samples $y$ according to transition matrix $Q(x \\to y)$. _Hint_: a useful Graph member function is [`neighbors`](https://networkx.org/documentation/stable/reference/classes/generated/networkx.Graph.neighbors.html). **(10 pts)**"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "449da919",
"metadata": {
"deletable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "db0642dd7c9f53225d13fb9674c89a56",
"grade": false,
"grade_id": "cell-df840ef2dee49b9f",
"locked": false,
"schema_version": 3,
"solution": true,
"task": false
}
},
"outputs": [],
"source": [
"def sample_proposal(graph,x):\n",
" '''Pick a random node y from the neighbors of x in graph with uniform\n",
" probability, according to Q.'''\n",
" y_list = np.fromiter(graph.neighbors(x), dtype=int)\n",
" return rng.choice(y_list)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "604ce3f4",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "690a774380e6a4383ccb5da2dee8a737",
"grade": true,
"grade_id": "cell-c70fec7da167b7be",
"locked": true,
"points": 10,
"schema_version": 3,
"solution": false,
"task": false
}
},
"outputs": [],
"source": [
"from nose.tools import assert_almost_equal\n",
"assert sample_proposal(nx.Graph([(0,1)]),0)==1\n",
"assert_almost_equal([sample_proposal(example_graph,3) for _ in range(1000)].count(4),333,delta=50)\n",
"assert_almost_equal([sample_proposal(example_graph,8) for _ in range(1000)].count(5),500,delta=60)"
]
},
{
"cell_type": "markdown",
"id": "f7a2e658",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "markdown",
"checksum": "99c1e08eed2976f4625452d9eed6a5d5",
"grade": false,
"grade_id": "cell-4c74e7dae57e50e3",
"locked": true,
"schema_version": 3,
"solution": false,
"task": false
}
},
"source": [
"__(b)__ Let us consider the Markov chain corresponding to the transition matrix $Q(x \\to y)$. Produce a histogram of the states visited in the first ~20000 steps. Compare this to the exact stationary distribution found by the function `stationary_distributions` from the lecture applied to the transition matrix $Q$. _Hint_: another useful Graph member function is [`degree`](https://networkx.org/documentation/stable/reference/classes/generated/networkx.Graph.degree.html). **(15 pts)**"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "f52fcbd5",
"metadata": {
"deletable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "44377fd9fa8cd0c3bc78ab03753db1ce",
"grade": false,
"grade_id": "cell-ca4f5c3685b72c8a",
"locked": false,
"schema_version": 3,
"solution": true,
"task": false
}
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAY4AAAEICAYAAABI7RO5AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAgcklEQVR4nO3de7xVZb3v8c9XLoKEqYCGgIGdJQhoZCvRMKU8ukVL1HQneaF2W6QkI7NCK1PzvF6eDpnbNkJoCFneXl621OF4TdLcaCyIdCGhqKhLURC3eMEL4O/8McZiTyZzrTUGrrHWhPV9v17zNed8xvM84zeGuH5zPGOMZygiMDMzy2qn9g7AzMy2L04cZmaWixOHmZnl4sRhZma5OHGYmVkunds7gLbQu3fvGDhwYHuHYWa2XVm0aNGrEdGnvLxDJI6BAwdSV1fX3mGYmW1XJD1XqdxDVWZmlosTh5mZ5eLEYWZmuXSIcxxmtv3asGEDDQ0NvPvuu+0dyg6rW7du9O/fny5dumSq78RhZlWtoaGBnj17MnDgQCS1dzg7nIhg7dq1NDQ0MGjQoExtPFRlZlXt3XffpVevXk4aBZFEr169ch3ROXGYWdVz0ihW3v3rxGFmZrn4HIdZwUaPHr1N7ebPn9+qcdi2ef3117nhhhv41re+xfz585k6dSp//OMf22z9s2fP5uijj2bvvfcG4F//9V8577zzGDp0aK5+WjN2Jw6zVnL78lUVy19d/36r9gdw0uC+29Sn5ff6669z9dVX861vfauwdWzcuJHOnSv/OZ49ezbDhw/fnDiuvfbawuLIqtDEIekY4N+ATsC1EXF52fIhwHXAQcCPImJqWj4YuLmk6r7ARRFxpaSLgbOANemyCyNiXpHbYfZhXHr9be0dgn0IU6ZM4emnn2bEiBF06dKFHj16cPLJJ1NfX8+nP/1pfve73yGJRYsWcd555/HWW2/Ru3dvZs+eTd++fVmyZAkTJ05k/fr1fOITn2DWrFnsvvvujB49ms9+9rM8/PDDHH/88YwePXqr9g8//DB1dXWcdtppdO/enQULFjBmzBimTp1KbW0td911FxdeeCGbNm2id+/e3H///fz1r39l8uTJvPPOO3Tv3p3rrruOwYMHt+o+KSxxSOoETAOOAhqAhZLmRsQTJdVeA84FTihtGxHLgREl/bwI3FFS5ZeNScbMrEiXX3459fX1LFmyhPnz5zN27FiWLl3K3nvvzahRo3j44YcZOXIk3/72t7nzzjvp06cPN998Mz/60Y+YNWsWZ555Jr/61a844ogjuOiii7jkkku48sorgeRo5s9//jMbNmzgiCOOqNj+3//93zcnilJr1qzhrLPO4sEHH2TQoEG89tprAAwZMoQHH3yQzp07c99993HhhRdy222t++OlyCOOg4EVEfEMgKSbgLHA5sQREauB1ZKOa6afI4GnI6LiZFtm1nG1x/mjgw8+mP79+wMwYsQIVq5cyW677UZ9fT1HHXUUAJs2baJv376sW7eO119/nSOOOAKA8ePHc8opp2zu6ytf+QoAy5cvr9i+OY888giHH3745nsv9thjDwDWrVvH+PHjeeqpp5DEhg0btnlbm1Jk4ugHvFDyvQEYuQ39nArcWFY2SdKZQB3wvYj4r/JGkiYAEwD22WefbVitmdnWdt55582fO3XqxMaNG4kIhg0bxoIFC7aou27dumb76tGjB0CT7ZsTERUvo/3JT37C5z//ee644w5Wrly5zcm1OUUmjkoXBkeuDqSuwPHABSXF04GfpX39DPgF8C9brShiJjAToLa2Ntd6zWz70BZXnvXs2ZM333yz2TqDBw9mzZo1LFiwgEMPPZQNGzbw5JNPMmzYMHbffXceeughPve5z3H99ddvPvrI2r6p9R966KGcc845PPvss5uHqvbYYw/WrVtHv379gOTEehGKTBwNwICS7/2Bl3L2MQZYHBGvNBaUfpZ0DdB218WZWYfTq1cvRo0axfDhw+nevTt77bXXVnW6du3Krbfeyrnnnsu6devYuHEjkydPZtiwYcyZM2fzyfF9992X6667Llf7r33ta0ycOHHzyfFGffr0YebMmZx00kl88MEH7Lnnntx777384Ac/YPz48VxxxRV84QtfKGSfKKKYH+OSOgNPkpyjeBFYCHw1IpZWqHsx8Fb5Ce/0vMjdEXFdSVnfiFiVfv4uMDIiTm0ultra2vCDnKxozV0+29o60uW4y5YtY//992/vMHZ4lfazpEURUVtet7AjjojYKGkScDfJ5bizImKppInp8hmSPkZynmJX4ANJk4GhEfGGpF1Irsg6u6zrn0saQTJUtbLCcjMzK1Ch93Gk91fMKyubUfL5ZZIhrEpt1wO9KpSf0cphmplZDp6ryszMcnHiMDOzXJw4zMwsFycOMzPLxbPjmtl2pbUve662S5tHjx5dcW6qprTHVO8+4jAzs1ycOMzMWvD2229z3HHH8clPfpLhw4dz8803c+mll/KZz3yG4cOHM2HCBBpvph49ejTf/e53Ofzww9l///1ZuHAhJ510EjU1Nfz4xz8GYOXKlQwZMoTx48dz4IEHcvLJJ7N+/fqt1nvPPfdw6KGHctBBB3HKKafw1ltvAXDXXXcxZMgQDjvsMG6//fa22xEpJw4zsxbcdddd7L333vz973+nvr6eY445hkmTJrFw4ULq6+t55513thgq6tq1Kw8++CATJ05k7NixTJs2jfr6embPns3atWuBZEbcCRMm8Nhjj7Hrrrty9dVXb7HOV199lcsuu4z77ruPxYsXU1tbyxVXXMG7777LWWedxR/+8AceeughXn755TbdF+DEYWbWogMOOID77ruPH/7whzz00EN89KMf5YEHHmDkyJEccMAB/OlPf2Lp0v+eTen444/f3G7YsGH07duXnXfemX333ZcXXkgmDR8wYACjRo0C4PTTT+cvf/nLFut85JFHeOKJJxg1ahQjRoxgzpw5PPfcc/zjH/9g0KBB1NTUIInTTz+9jfbCf/PJcTOzFuy3334sWrSIefPmccEFF3D00Uczbdo06urqGDBgABdffDHvvvvu5vqNU6/vtNNOW0zDvtNOO7Fx40aAraZEL/8eERx11FHceOOWT5VYsmRJxenU25KPOMzMWvDSSy+xyy67cPrpp3P++eezePFiAHr37s1bb73FrbfemrvP559/fvNstzfeeCOHHXbYFssPOeQQHn74YVasWAHA+vXrefLJJxkyZAjPPvssTz/99Oa2bc1HHGa2XWmPy2cff/xxvv/977PTTjvRpUsXpk+fzn/8x39wwAEHMHDgQD7zmc/k7nP//fdnzpw5nH322dTU1PDNb35zi+V9+vRh9uzZjBs3jvfeew+Ayy67jP3224+ZM2dy3HHH0bt3bw477DDq6+tbZTuzKmxa9WriadWtLXha9WLsiNOqr1y5ki9+8Ytt/ge/OXmmVfdQlZmZ5eLEYWbWxgYOHFhVRxt5OXGYWdXrCEPq7Snv/nXiMLOq1q1bN9auXevkUZCIYO3atXTr1i1zG19VZWZVrX///jQ0NLBmzZr2DmWH1a1bN/r3r/gw1oqcOMysqnXp0oVB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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"def chain_Q_histogram(graph,start,k):\n",
" '''Produce a histogram (a Numpy array of length equal to the number of \n",
" nodes of graph) of the states visited (excluding initial state) by the \n",
" Q Markov chain in the first k steps when started at start.'''\n",
" n = graph.number_of_nodes()\n",
" number_of_visits = np.zeros(n)\n",
" x = start\n",
" \n",
" for _ in range(k):\n",
" x = sample_proposal(graph, x)\n",
" number_of_visits[x] += 1\n",
" \n",
" return number_of_visits\n",
"\n",
"def transition_matrix_Q(graph):\n",
" '''Construct transition matrix Q from graph as two-dimensional Numpy array.'''\n",
" n = example_graph.number_of_nodes()\n",
" Q = np.zeros((n, n))\n",
" for x in range(n): \n",
" for k in example_graph.neighbors(x):\n",
" Q[x, k] = 1/example_graph.degree(x)\n",
" return Q\n",
"\n",
"# Compare histogram and stationary distribution in a plot\n",
"x_start = 1\n",
"k = 100000\n",
"\n",
"plt.figure()\n",
"x_list = list(range(example_graph.number_of_nodes()))\n",
"plt.bar(x_list, chain_Q_histogram(example_graph, x_start, k)/k, color=\"lightblue\", label=\"sampled\")\n",
"plt.scatter(x_list, stationary_distributions(transition_matrix_Q(example_graph)), s=200, marker=\"_\", color=\"black\", label=\"theoretical\")\n",
"plt.ylabel(\"visiting density\")\n",
"plt.xlabel(\"node $x$\")\n",
"plt.legend()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "812cd2ef",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "c3e08e0577c953ca68fe8159cadc0634",
"grade": true,
"grade_id": "cell-bdea40714e10d0e8",
"locked": true,
"points": 15,
"schema_version": 3,
"solution": false,
"task": false
}
},
"outputs": [],
"source": [
"assert_almost_equal(transition_matrix_Q(example_graph)[3,4],1/3,delta=1e-9)\n",
"assert_almost_equal(transition_matrix_Q(example_graph)[3,7],0.0,delta=1e-9)\n",
"assert_almost_equal(transition_matrix_Q(example_graph)[2,2],0.0,delta=1e-9)\n",
"assert_almost_equal(np.sum(transition_matrix_Q(example_graph)[7]),1.0,delta=1e-9)\n",
"assert chain_Q_histogram(nx.Graph([(0,1)]),0,100)[1] == 50\n",
"assert len(chain_Q_histogram(example_graph,0,100)) == example_graph.number_of_nodes()"
]
},
{
"cell_type": "markdown",
"id": "8ebe4946",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "markdown",
"checksum": "f4338397c60be0fc0069e30bec121faa",
"grade": false,
"grade_id": "cell-5a9debbf863b9e3b",
"locked": true,
"schema_version": 3,
"solution": false,
"task": false
}
},
"source": [
"__(c)__ Determine the appropriate Metropolis-Hastings acceptance probability $A(x \\to y)$ for $x\\neq y$\n",
"and write a function that, given a graph and $x$, samples the next state with $y$ according to the Metropolis-Hastings transition matrix $P(x \\to y)$. **(10 pts)**"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "37804448",
"metadata": {
"deletable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "639522f9ff68136165c0d9daa174b4ba",
"grade": false,
"grade_id": "cell-92e3b11a3af7eb99",
"locked": false,
"schema_version": 3,
"solution": true,
"task": false
}
},
"outputs": [],
"source": [
"def acceptance_probability(graph,x,y):\n",
" '''Compute A(x -> y) for the supplied graph (assuming x!=y).'''\n",
" assert x != y\n",
" \n",
" Q = transition_matrix_Q(graph)\n",
" n = graph.number_of_nodes()\n",
" # We want to sample a uniform mass distribution pi:\n",
" pi = np.ones(n)/n\n",
" \n",
" if Q[x, y] == 0:\n",
" return 0\n",
" else:\n",
" A = pi[y]*Q[y, x]/( pi[x]*Q[x, y] )\n",
" return np.min([1., A])\n",
"\n",
"def sample_next_state(graph,x):\n",
" '''Return next random state y according to MH transition matrix P(x -> y).'''\n",
" y = sample_proposal(graph, x)\n",
" return y if rng.random() < acceptance_probability(graph, x, y) else x"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "058d3728",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "6bf922f8787f02c80681390ce8a8f84c",
"grade": true,
"grade_id": "cell-fbfc2607999d0c99",
"locked": true,
"points": 10,
"schema_version": 3,
"solution": false,
"task": false
}
},
"outputs": [],
"source": [
"assert_almost_equal(acceptance_probability(example_graph,3,4),0.6,delta=1e-9)\n",
"assert_almost_equal(acceptance_probability(example_graph,8,7),0.5,delta=1e-9)\n",
"assert_almost_equal(acceptance_probability(example_graph,7,8),1.0,delta=1e-9)\n",
"assert_almost_equal(acceptance_probability(nx.Graph([(0,1)]),0,1),1,delta=1e-9)"
]
},
{
"cell_type": "markdown",
"id": "cbf205bf",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "markdown",
"checksum": "da69b710a3b1986ac9f9997235c1a472",
"grade": false,
"grade_id": "cell-97f7d289177acf39",
"locked": true,
"schema_version": 3,
"solution": false,
"task": false
}
},
"source": [
"__(d)__ Do the same as in part (b) but now for the Markov chain corresponding to $P$. Verify that the histogram of the Markov chain approaches a flat distribution and corroborate this by calculating the explicit matrix $P$ and applying `stationary_distributions` to it. _Hint_: for determining the explicit matrix $P(x\\to y)$, remember that the formula $P(x\\to y) = Q(x\\to y)A(x\\to y)$ only holds for $x\\neq y$. What is $P(x\\to x)$? **(15 pts)**"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "5de68351",
"metadata": {
"deletable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "bd25c9f6b39133973fd2d1594e210b30",
"grade": false,
"grade_id": "cell-3b7fde395331916d",
"locked": false,
"schema_version": 3,
"solution": true,
"task": false
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"def chain_P_histogram(graph,start,k):\n",
" '''Produce a histogram of the states visited (excluding initial state) \n",
" by the P Markov chain in the first n steps when started at start.'''\n",
" n = graph.number_of_nodes()\n",
" number_of_visits = np.zeros(n)\n",
" x = start\n",
" \n",
" for _ in range(k):\n",
" x = sample_next_state(graph, x)\n",
" number_of_visits[x] += 1\n",
" \n",
" return number_of_visits\n",
"\n",
"def transition_matrix_P(graph):\n",
" '''Construct transition matrix Q from graph as numpy array.'''\n",
" n = graph.number_of_nodes()\n",
" P = np.zeros((n, n))\n",
" Q = transition_matrix_Q(graph)\n",
" \n",
" for x in range(n):\n",
" for y in range(n):\n",
" if x != y:\n",
" P[y, x] = Q[x, y]*acceptance_probability(graph, x, y)\n",
" # Finally, we have to calculate P(x -> x):\n",
" P[x, x] = 1 - np.sum(P[:, x])\n",
" return P\n",
"\n",
"# plotting\n",
"x_start = 1\n",
"k = 40000\n",
"\n",
"plt.figure()\n",
"x_list = list(range(example_graph.number_of_nodes()))\n",
"plt.bar(x_list, chain_P_histogram(example_graph, x_start, k)/k, color=\"lightblue\", label=\"sampled\")\n",
"plt.axhline(y = 1/example_graph.number_of_nodes(), marker=\"_\", linestyle = \"dashed\", color=\"black\", label=\"theoretical\")\n",
"plt.ylabel(\"visiting density\")\n",
"plt.xlabel(\"node $x$\")\n",
"plt.legend()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "4b5cc504",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "1b756f8dff589048e791db63f89d8624",
"grade": true,
"grade_id": "cell-8c4b6c60ee96f037",
"locked": true,
"points": 10,
"schema_version": 3,
"solution": false,
"task": false
}
},
"outputs": [],
"source": [
"assert_almost_equal(transition_matrix_P(example_graph)[3,4],1/5,delta=1e-9)\n",
"assert_almost_equal(transition_matrix_P(example_graph)[3,7],0.0,delta=1e-9)\n",
"assert_almost_equal(transition_matrix_P(example_graph)[2,2],0.41666666,delta=1e-5)\n",
"assert_almost_equal(np.sum(transition_matrix_P(example_graph)[7]),1.0,delta=1e-9)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "f4e9d8aa",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "22ff259ba7ad6066040f3417cc8d4483",
"grade": true,
"grade_id": "cell-a63274314d1b2a2d",
"locked": true,
"points": 5,
"schema_version": 3,
"solution": false,
"task": false
}
},
"outputs": [],
"source": [
"assert len(chain_P_histogram(example_graph,0,100)) == example_graph.number_of_nodes()\n",
"assert_almost_equal(chain_P_histogram(example_graph,0,20000)[8],2222,delta=180)"
]
},
{
"cell_type": "markdown",
"id": "89f65139",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "markdown",
"checksum": "9b277d17c7b55bb15e5708e6ca90c4f9",
"grade": false,
"grade_id": "cell-da50533d4d46c293",
"locked": true,
"schema_version": 3,
"solution": false,
"task": false
}
},
"source": [
"## MCMC simulation of disk model\n",
"\n",
"**(50 points)**\n",
"\n",
"Recall that in the disk model with we would like to sample the positions $x = (x_1,y_1,\\ldots,x_N,y_N)\\in [0,L)^{2N}$ of $N$ disks of radius $1$ in the torus $[0,L)^2$ with uniform density $\\pi(x) = \\mathbf{1}_{\\{\\text{all pairwise distance }\\geq 2\\}}(x) / Z$, where $Z$ is the unknown partition function of the model. We will assume $L > 2$ and $N\\geq 1$. For the purposes of this simulation we will store the state $x$ in a `np.array` of dimension $(N,2)$ with values in $[0,L)$. Such a configuration can be conveniently plotted using the following function:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "683d2de3",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "4c7cb2d90103cd790145cae15d46e99e",
"grade": false,
"grade_id": "cell-d661f575ab9f80ea",
"locked": true,
"schema_version": 3,
"solution": false,
"task": false
}
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAOsAAADrCAYAAACICmHVAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAatUlEQVR4nO3deXwU9d0H8M/sbnY3x2Zz7G5uEo6QkINwBEkAAblFURCVeqA+VkVbW7WlWns91uPxsT5iLdVWhaoFQYrWq1QqhyJyBMIZyE1CLshu7mzu7O48f3CUcrmb7OxvfzPf9+vlPwZ2PxnmszM78/v9RhBFEYQQ/6diHYAQ4h4qKyGcoLISwgkqKyGcoLISwgkqKyGc0Hjyh9VBRlFjtEiVxSuGRATBGBjAOgbhULmtA939TqYZ+urLG0VRNF/uZx6VVWO0IObe33sllBTmpkfhzaXZrGMQTpXU27Fg5bfoc7qYZah66caqK/1MNqfB4UEBeH5hJusYhGMp0Qb8eOYI1jGuSDZlfeamdJgNOtYxCOcenjYcmXFG1jEuSxZl/d6EBNw8Jo51DCIDGrUKK+8Y65fXPbgv64SkcDx7cwbrGERGkkzBeP3OcVCrBNZR/gPXZY0LC8Sf7h4PrYbrX4P4oSnJJvxy/ijWMf4Dt3u5MTAAq+7NhimEvqcSadw/ZSjuzU1kHeM8Lstq0Gnw1/uvwaiYUNZRiMw9c1M6lmQnsI4BgMOyGgMDsPaBichKCGMdhSiAIAj438WZuOMa9oXlqqyxRj3WP5hDRSU+JQgC/mdRJh6eNpxpDm7KOj4xHJ8+OgVpsXTqS3xPEAT8/PpUvLokCzpGFzS5KOvt2fFY/2AODXogzC0aG48Ny3IRFer7fdGvyxqq1+CV27Lwu1uz6PYM8RtjEsLwjx9di7npUT59X79twIxUC7b8ZBoWj49nHYWQS5gNOry5NBuvfW8MwoN8M9rJo1k3vhBj1OPJeSlYNJZKSvzfzWPiMGm4CS9+UYRPDtXBJeFioX5T1rCgAPxg+nDck5sEfYCadRxC3GY26LDi9jF4aOowvLy5BNuKbZK8D/OyWgw63DlxCO6fMhShev8bPE2Iu1KjQ7H6vgnYf7IZb+44ge3FNq8eaZmVNWdYBJbmJGFuehQ0ar/96kyIxyYkRWBCUgRqW7rwfl41/ra/Bk2dfYN+XZ+VVaMSkJ0UjlmjojA7LQqJkcG+emtCmIgPD8JT81LxxKyR2FPRhK2FVmwrsuJUW8+AXk+ysobqNciMNyIjzois+DBMHm6C0UdXzQjxJ1qNCtNGmjFtpBnPLczA8VNt2FfZjIK6Nhyra8OJhk443Thf9qissUY9Hpk+HJ29DvSfffEAlYBArQYWgw6WUB0sBj1ijHokRAQN7DcjRObSY41Ij/33ahTdfU5UNnbCau/BjJeu/Pc8KmtkiA5PzksdcEhCyKUCtWqkxYYiDVcfSktXdgjhBJWVEE4wv89K5EMURfQ5XXCdXXZXrRJoTLcXUVmJR/ocLpTU21FQ14ai0+043dYDm70H1vYeNHX0wXHRVU19gAoWgx4Wgw5RoXrEhwciPc6IzDgjkiKDIAj+tSiZP6OykqsSRRGHalqxtdCKnWWNKKm3e7RifU+/C9XNXahu7rrkZwa9BlnxYZieYsactGgMiaQ7CFcjiKL746Gys7PF/Px8CeMQf5F/shkfHqjF1iIbGjt6ffKeyZYQzMuIxu3ZCYq99ScIwgFRFC/7DBg6spLzOnsd+PhQHdburUJxvd3n719m60DZ9nK8/lU5pqdYsDQnEdNGmqHys/V7WaGyEnT1ObB6ZyXe2lkBe4+DdRy4RGB7sQ3bi20YZg7GT2aPxA2ZMYr/fktlVbB+pwvr91Vj5fZyNNh9c6rrqYqGTjy67hDeiq/Ak3NTMSXZxDoSM1RWhTpQ1YInPzyCEw2drKO45WhtG+5enYfZaVF4YVEGLAY960g+R2VVmJ5+J1ZsKcWqnRWSrmoglS2FVuw/2YxnFqRj4VhlPYyM7lgrSNHpdtzwh5146xs+i3pOa1c/Ht9wGMvW5KO9p591HJ+hsirE5mOnsfhPu7k57XXHv45bsfD1Xaho6GAdxSeorDIniiJe3VKKR94/iK4+J+s4XlfR0ImFr+/C1yXSrHvkT6isMuZwuvDEhsN4bVsZPBj7wp32Hge+/14+NuyvZh1FUnSBSaYcThd+tP4QvjhWzzqKTzhdIn7+9wL0OVxYmpvEOo4k6MgqQ06XiMc2HFZMUc8RReA3nx3Hujx5HmGprDL0q0+OYdPR06xjMCGKwC8/KcAXBfL7/amsMvPe7pNYv0+eRxZ3iSLw041HUHiqnXUUr6Kyysju8kY8949C1jH8QlefEw/+NR9NPpox5AtUVpmobenCD9YdvGTyt5LVtXbjkfcPurXMJw+orDLx1EdH0dqlnNE87tpX2YxVOytYx/AKKqsMvJ9XhV3lTaxj+K0VW0pRbuN/lBOVlXO1LV148Z/FrGP4tV6HCz/78Aj3p8NUVs49+3khOnrZTxj3d4eqW/EB5yOcqKwcO1jdgi8LraxjcOO1rWXo6ed3fDSVlWMvfUGnv56w2Xvxl12VrGMMGJWVU1+X2JBX2cw6Bnf+/PUJtHF61ZzKyqk3d8jjdoSvtfc4sJ7T765UVg6V2zqwp4Ju1QzUurxquDi8Mkxl5dDavVWsI3CturkLO0obWMfwGJWVM919Tnx0sJZ1DO7x+IFHZeXMjlKbXyzEzbtvyhq4W2yNysqZLYXyX2vIF/qdIr4u4etUmMrKEZdLVMTCYL6yrYivASVUVo4cqmlBU2cf6xiy8XVJAxwePL6SNSorR/ZVtrCOICtt3f0otfIzG4fKypFjdW2sI8gOT9uUysqRAo52LF4crWtlHcFtVFZOtHX1o7q5i3UM2Smo42dRNSorJyoa+fluxZNKjp6TQ2XlhLVdPqv0+ZP2Hgc3c1yprJxosPewjiBbNk4+CKmsnLDZ+diheGTj5IOQysqJZhoMIRleti2VlRMOJ3/zL3nBy8LoVFZOOOX8gFXGeFmilMrKCbUgsI4gW2oVH9uWysoJrYb+qaQSoOZj2/KRkiAiWMs6gmxFhvCxbamsnLCE6lhHkC2LgY9tS2XlhMWgZx1BtnjZtlRWTkTRkVUS4UEB3FwP4CMlwTBzCDi5aMmVEZYQ1hHcRmXlRIhOg6GmYNYxZCcjzsg6gtuorBzJ5GjH4sXoeH62KZWVIzwdBXjB0wcglZUjOcMiWUeQFVOIDsPN9J2VSCAjzogYIx+3GXgwM9UCgaNhnFRWzsxItbCOIBszR/G1LamsnJmVFsU6gizoA1S4NtnMOoZHqKycmTzcBBMnY1n92axRUQjUqlnH8AiVlTNajQq3ZyewjsG9pTmJrCN4jMrKobtyEmk00yCkRBkwkcMr61RWDsWFBdKFpkG4O2cI6wgDQmXl1CPTR7COwCWLQYdbx/P5NYLKyqnxieGYTVeGPfbjmcncXVg6h8rKsSfnptB3Vw8kRQbhexP4PKoCVFauJUcZsHhcPOsY3Fg+NwUaTtZbuhx+kxMAwNPzR9F9Vzdcl2LGjaNjWccYFCor5yKCtXju5gzWMfxaqF6DF28ZzTrGoFFZZeD6zBjcMDqGdQy/9asb0xAtgwkQVFaZeO7mDMSFBbKO4XfmpUfLZsQXlVUmIoK1eOue8QgM4PO2hBRSow1YsSSLdQyvobLKSHqsEa/cngWOpmhKJiJYi7fvyUaQVsM6itdQWWVmfmYMHpuZzDoGU1qNCm/cNQ4JEUGso3gVlVWGHp81EvdPHso6BhMBagFv3DlOlkvgUFll6jcL0nDfpCTWMXxKq1bhj3eOk+0EfSqrjD1zUzp+MH046xg+ERigxpv3jMfc9GjWUSRDZZW5J+el4uVbR3PziIiBiAsLxIeP5OK6FHlPG5TvvyA577bsBKx/MAdmTp6W5okJSeH49NHJSI/lZ/3fgaKyKsT4xHB89uhkTBwawTqKVwgC8F+Tk/D+AzkwhcjvQ+hyqKwKEmMMxAcP5eC3N6UjiNM5nQCQGBmEDx7MwX8vSJf16f3FlPObEgCAIAi4d1ISNj82FZOG83V7Q60ScN/Z7DyuoTRY8hneQTwyJDII6x7MwfZiK363uQTF9XbWka5qXno0ls9N4eoRjd5GZWWso9cBW3sPrO29aOjoRWevAw6nCwCgUasQpFXDbNAhKlQPi0EHgz7Aq+8/IzUK00da8OmROry2tQwnm7q8+vqDNWWECcvnpmBMQhjrKMxRWX2oprkLh2taUVDXhoLaNhw/1Yb2HodHr2HQa5AWE4rMOCMy440YHR826Oe2qlQCFo2Nx8IxcdhR2oC1e6uwvdgGlziolx0wg06DRePisDQnEclRBjYh/JAgiu7/i2RnZ4v5+fkSxpEXp0vEgaoWbC2yYmuhFRWNnZK8T2JkEGamRmFWmgXXJEV4ZemS2pYu/P1gHbYWWVFQ1wYPdpMB0WlUmDQ8EnPSo3FTViyCdco8jgiCcEAUxezL/ozK6n01zV1Yu7cKHx6oRVNnn0/fOywoALeMjcfS3ESvPSnd2t6DbUU2fFPagIK6NtS1dg/6NdUqASPMIRiTEIbrUi2YOtIkqxkyA0Vl9ZEdpQ14d1cldpQ2MDuFPEcQzjwX575JSV4fK9vc2YeCujYUnW5HfVsPrO1n/mvo6EV3nwtOlwuCIECtEmDQaxBl0MMSeuZ7d3x4INJjjUiLCeV2SVApUVkltv9kM176ohj5VS2so1xWVrwRT81LxaQRJtZRyHe4WlnpvGMQym12vPjPYmwrtrGOclVHattw56o8XJtswi/mj8KomFDWkcgA0KCIAXC6RLz+VTnmv/at3xf1QjvLGrFg5bdYsaUU/WdvDxF+0JHVQ6VWO5ZvPIKjtW2sowyIwyXiD9vK8OXxevzfbVnIiJP/AHi5oCOrB/6WX4MbV37LbVEvVFxvx6I3dmHNnpOsoxA3UVnd4HSJePbzQjz54VH0OeRz+tjvFPHrT4/jFx8X0GkxB6is36Gtux/3vbMPf9lVyTqKZNblVeOuVXlo9vE9YeIZKutVNHf24c6392JnWSPrKJLbV9mMJW/ugc3ewzoKuQIq6xW0nC3q8VPtrKP4TJmtA0ve3AtbOxXWH1FZL6Otux93r87z+2ljUqhs7MRdq/LQ1NHLOgq5CJX1Ik6XiEfXHVTUEfViZbYOLFtzQFYX0+SAynqR5zcVKuI76nfJr2rBrz85xjoGuQCV9QJ/21+Dd3adZB3Db2zIr8G7Mr4Kzhsq61nF9e34FR1JLvH8piIcrmllHYOAygoAcDhdWL7xCPpoYMAlHC4RyzceQa/DyTqK4lFZAbzx9Qkcq1PuBaXvUm7rwIotpaxjKJ7iy1pSb8fK7WWsY/i9VTsr6XSYMcWX9YV/FqHfyXhZBw44XSKe/0ch6xiKpuiy7j7RiG9KG1jH4EZ+VQu2FlpZx1AsRZf1d5tLWEfgzsv/KoGL9QJTCqXYsm4ttNJ3sAEosdrx+dFTrGMokmLL+s5uutk/UO/uPsk6giIpsqwnGjqw+0QT6xjcOlTdimN1/K+WwRtFlnXt3irJV5iXu7V7q1hHUBzFlbXf6cJHB2pZx+Dep4dPoavPs+f0kMFRXFn3VjR5/DAocqnufifNTvIxxZWV7hN6D21L31JeWYv4WZTb331VYqN7rj6kqLKWWe1eeQIaOaOxow9H6aqwzyiqrDQIwvuO0Db1GUWVle4Nel8BbVOfUVRZacfyvgIZPEqEF4opqyiKKDxNE8y9rbyhAz39tIqELyimrI0dfejpp2VbvM3pEmGlRcF9QjFlpcdCSMdmpwXBfUFBZaUdSiq2dtq2vqCYsjbQDiUZOg32DcWU1d5L44Gl0knb1icUU1YHrQksGQcNOfQJjSd/uKKhE9Nf/godvU44XGd2fo1KhSCtGhaDDpZQHSwGPWLD9EiLMSIzzghjUIAkwYn/oKoOjMsloqKxAwV1bThh6/zOi6AelbWzz4GTTV2X/Vl18+X/f0JEIEbHh2HaSDNmpFpgCtF58pZeo1YJTN5XCQJo27pFFEUcqmnFtiIr9lU2o/BUOzr73L9H7VFZB6KmuRs1zd3YdPQ0VAIwJiEMs9OisXhcHCyheqnf/rxgneS/qmIFatWsI/gtURSxq7wJnx85hW3FNjQO4rm3Pt2DXSJwsLoVB6tbsWJLCeakRePunETkDo+U/L3NjI7oSmA20La9WFtXPzYeqMH7edWobOz0ymsyO9z0O0VsKjiNTQWnkRJlwBOzR2JeRrRk72cJpR1KKhaD786Q/F1TRy/++FU51u+r9vqIOb84Nyyx2vHw2gMYkxCGp+alSnKkjfLhKbfSRNEHITp6HXj7mwqs/rYSHRLdyvKLsp5zuKYVd7y9F7NGReGFRRleLZgpRAetWkWPdfQyQQCijcr+IPzsyCk8+/lxNHb0Sfo+fnmfdWuRFXNe/carqxCqVQJGRod47fXIGUmRwQjS+tVnvs80dvTi4TUH8OP1hyQvKuCnZQWAtu5+/HTjEXz/3f1o6fTOhsiMM3rldci/KXWbbj52GrNX7MDm4/U+e0+/Les524ptuOn1b1FcP/i5qBkK3bGkpLSyiqKIV74swcNrD6Klq9+n7+33ZQXO3Ktd/MZufDnIT7Gs+DDvBCLnZcYrp6ydvQ4sW3MAK7eXM3l/LsoKAJ19TixbewCrdlYM+DXSYkKZjaCSI4NOg/GJ4axj+ESDvRe3/nkPvmS4VjI3ZQUAUQSe31SEldvKBvT3VSoBM1LNXk6lXFNTzAhQc7ULDYi1vQdL3tqDIsbLAnG5pV/ZUoo3vh7YqcjMUVFeTqNcsxWwLRvsvbjj7b2oaPDOKKTB4LKswJmnlq8ZwJPMpiaboQ/g9tf2GwFqAdelWFjHkFRHrwNLV+f5RVEBjssKAL/97Dh2n/Ds4UiBWjVuHB0rUSLlmJMWLevpjy6XiMc/OITiejvrKOdxXVaHS8QP3z+ImitMz7uSe3ITJUqkHHfnyHsbvrKlxO+ei8R1WQGgpasfD7yXj24P5gWOjg9DloJuOXhbsiXEJzOlWNl09DRe/+oE6xiX4L6swJmJAC9tLvbo79yTmyRNGAWQ85mJrb0Hv/i4gHWMy5JFWQHgvT0nkVfR5PafXzg2DsPMwRImkqe4sEDcPiGBdQzJPP33ArR1+3ZkkrtkU1ZRBJ786Kjbp8NqlYCfzUmROJX8PDF7JHQaea4M8dGBWmwr9q/vqReSTVkBoKqpC3/Y7v6AieszY5CVECZdIJlJiTLglrFxrGNIoq27H89tKmQd46pkVVYAeGdXpUeLTv9y/igItN6XW56enwqVTBdH+/OOE2j18cB8T8murD39Lvx+q/tH12uGRmCpzG9DeMPicfGYLtNBENb2Hryzq5J1jO8ku7ICwMb8GlQ0dLj9539+fSqGRARJmIhvUaE6/GZBGusYknltWxkXTxiUZVkdLhFvezA7J0irwUuLR9Pp8BW8eEsmjIHyHK3UYO/Fh/neW5FESrIsKwB8evgU2nvc/w6SOzwSj81MljARn5ZNHYYZqfIdsL9hfzU363LJtqxdfU6P13B6bGYy5mdKtxwqb65LMeOpeamsY0jG6RKxfl8N6xhuk21ZAWCth7NyBEHAK7eNQVpMqESJ+DHcHIzX7hgr26u/ALC92Ia61m7WMdwm67KeaOjEsbo2j/5OoFaNVfdmIy4sUKJU/s9s0GH1vRMQqpfn99RzPj1cxzqCR2RdVuDMsqaeig0LxLoHJypy8erIYC3WPTARSSZ5D8Xsd7qwo7SBdQyPUFmvIDEyGBseylXUEdZs0OGDh3KQHGVgHUVyeRXNsPfw9RBo2Zf1WF076tvcH9F0oSRTMDYsy0FqtPx33mGmYGxclquIogID/xBnSfZlBYC8Svdn41wsPjwIHz0yCbPT5Hv7YtpIMz7+4WTZn/peKK+ymXUEjymirAW1nl1kuliwToO3lo7Ho9eN8FIi//HAlKH4y30TZDvo4XJ6+p0os/rPci3uUsRDSgo8vCJ8OYIgYPncFEwYGoGnPzqKUwM8tfYXZoMOLyzMwJx05d1XLjrdDodLZB3DY4o4shaeaocoeucfZ9pIM/71xFQsyeZ3AvaisXHY+sQ0RRYVgMe38/yFIspq73XgtBePhAZ9AF66dTTWfP8apHB0QWaYORir783Gq0vGyHplwu9SbnN/koc/UcRpMADY7L2I9fJtmGuTzfjiMRM+PlSHFVtK/XY0THSoHo/PSsZt2QlQy3hEkrus7b2sIwyIcsrqwYR0T6hUAhaPj8eCrFhs2F+N9/ZU+c0nd1JkEJbmJuGuiUOgD5DnUiwDYbXzeb1BOWW1S/tpqtWosDQ3CUtzk7C7vBFr9lZhS6HV5xcy1KozK+UvzU3E1GQTBJr3dwkbHVn9W5MPnkx9zqQRJkwaYUJzZx+2F9uwtdCKnWUN6PRgbWNPBAaoMXmECbPTLJiRGgWzQXnDJD3R7KWHc/uaYsraz2DOYkSwFreOj8et4+PR63Bif2ULjtS2oqC2DQV1bQP+jhtr1CMjzojMOCNGJ4Rh4tAIOs31AC/zVy+mmLI6vXTrZqB0GjWmJJswJdl0/v+1dvXhVGsPbPYe2Np7YbP3oLPPCefZU2e1SkBQgBqWUB0sBj0soTrEGgMRHqxl9WvIgpPDe6yAgsqq9sPvbmFBWoQFaZEGmj/rS2qVwGVhFXGfFQA0av8rK2FDw+ntK8WUNYJOHclZvO4Liimrha6QkrN43RcUU1azQc86AvETllA+9wXFlFWJS7SQy+N1X1BEWQMD1IgxKmd5FnJ1w0whrCMMiCLKmhYbSgPYyXmZnD71XhFlzYzj8x+HSCM9NhQ8fnYroqwZVFZygSCtBsPM/J0KK6Ks1yRFsI5A/MwEDvcJ2Zc12RKCIZH0OEfyn2aN4u9Zs7Iv68xR8l1ClAzc5BEmBHI2U0n2ZZ2dxt8nKJGe/uwcYJ7IuqxxYYEYmxDOOgbxUwuyYlhH8Iisy3rnxCGyfmQhGZzrM2IQydGgftmWVatWYckEftf2JdLTalS4naN9RLZlnZcRDVMIn2NAie/cNXEINwMkZFlWQQAemjqMdQzCgfjwINwwOpZ1DLfIsqw3ZMbQqCXitp/OHokADlYSkV1ZNSoBy+eksI5BOJJkCubi+obgyQObBEFoAFAlXRxCFC9RFEXz5X7gUVkJIezI7jSYELmishLCCSorIZygshLCCSorIZygshLCCSorIZygshLCCSorIZz4f8LWKPoUcky6AAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"def plot_disk_configuration(positions,L):\n",
" fig,ax = plt.subplots()\n",
" ax.set_aspect('equal')\n",
" ax.set_ylim(0,L)\n",
" ax.set_xlim(0,L)\n",
" ax.set_yticklabels([])\n",
" ax.set_xticklabels([])\n",
" ax.set_yticks([])\n",
" ax.set_xticks([])\n",
" for x,y in positions:\n",
" # consider all horizontal and vertical copies that may be visible\n",
" for x_shift in [z for z in x + [-L,0,L] if -1<z<L+1]:\n",
" for y_shift in [z for z in y + [-L,0,L] if -1<z<L+1]:\n",
" ax.add_patch(plt.Circle((x_shift,y_shift),1))\n",
" plt.show()\n",
" \n",
"# Example with N=3 and L=5\n",
"positions = np.array([[0.1,0.5],[2.1,1.5],[3.2,3.4]])\n",
"plot_disk_configuration(positions,5)"
]
},
{
"cell_type": "markdown",
"id": "efa2f1c9",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "markdown",
"checksum": "d29e40f9d0e8d304d266f016150aeab7",
"grade": false,
"grade_id": "cell-527056f298dedf7c",
"locked": true,
"schema_version": 3,
"solution": false,
"task": false
}
},
"source": [
"__(a)__ Write a function `two_disks_overlap` that tests whether disks at position $\\mathbf{x}_1 \\in [0,L)^{2}$ and position $\\mathbf{x}_2 \\in [0,L)^{2}$ overlap and a function `disk_config_valid` that checks whether a full configuration is valid (non-overlapping and non-touching). _Hint:_ The minimal separation in the $x$-direction can be expressed as a function of `x1[0]-x2[0]` and the minimal separation in the y-direction as a function of `x1[1]-x2[1]`. Then use pythagoras. **(15 pts)**"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "19c010eb",
"metadata": {
"deletable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "bbf8ae650d9d4a66a3e4ac4722a3f60e",
"grade": false,
"grade_id": "cell-1b2a61bf719003e0",
"locked": false,
"schema_version": 3,
"solution": true,
"task": false
}
},
"outputs": [],
"source": [
"def two_disks_overlap(x1,x2,L):\n",
" '''Return True if the disks centered at x1 and x2 (represented as 2-element arrays) overlap in [0,L)^2.'''\n",
" # To take into account all overlap with the boundaries, we will also\n",
" # test shifted disks. As d(x1 + d, x2) = d(x1, x2 - d), we do not have\n",
" # to shift both disks explicitly.\n",
" for dx in [0, -L, L]:\n",
" for dy in [0, -L, L]:\n",
" if (x1[0] - x2[0] + dx)**2 + (x1[1] - x2[1] + dy)**2 <= 4:\n",
" return True\n",
" return False\n",
" \n",
"def disk_config_valid(x,L):\n",
" '''Return True if the configuration x (as two-dimensional array) is non-overlapping in [0,L)^2.'''\n",
" n = len(x)\n",
" for idx_x1 in range(n):\n",
" # We should not compare x1 with itself, and the previous disks have\n",
" # already been compared.\n",
" for idx_x2 in range(idx_x1 + 1, n):\n",
" if two_disks_overlap(x[idx_x1], x[idx_x2], L):\n",
" return False\n",
" return True"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "e0f2024a",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "05fc821fed0690aabc13fd66da800694",
"grade": true,
"grade_id": "cell-9f544deda0526691",
"locked": true,
"points": 10,
"schema_version": 3,
"solution": false,
"task": false
}
},
"outputs": [],
"source": [
"assert two_disks_overlap(np.array([1,1]),np.array([1,1]),5)\n",
"assert two_disks_overlap(np.array([0.6,0.6]),np.array([4.1,0.5]),5)\n",
"assert two_disks_overlap(np.array([0.3,0.3]),np.array([4.6,4.6]),5)\n",
"assert not two_disks_overlap(np.array([1,1]),np.array([3.1,1]),7)\n",
"assert not two_disks_overlap(np.array([1,1]),np.array([1,3.1]),7)\n",
"assert not two_disks_overlap(np.array([1,1]),np.array([1.01+np.sqrt(2),1.01+np.sqrt(2)]),6)\n",
"assert two_disks_overlap(np.array([1,1]),np.array([0.99+np.sqrt(2),0.99+np.sqrt(2)]),6)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "68e57e57",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "8705cb3a08fc636963fe61806348d093",
"grade": true,
"grade_id": "cell-699454de327d56d5",
"locked": true,
"points": 5,
"schema_version": 3,
"solution": false,
"task": false
}
},
"outputs": [],
"source": [
"assert disk_config_valid(np.array([[0.1,0.5],[2.1,1.5],[3.2,3.4]]),5)\n",
"assert not disk_config_valid(np.array([[0.1,0.5],[2.1,1.5],[3.2,3.4],[4.1,2.3]]),5)\n",
"assert disk_config_valid(np.array([[1,1],[3.1,1],[1,3.1]]),6)\n",
"assert not disk_config_valid(np.array([[1,1],[3.1,1],[1,3.1],[2.5,2.5]]),6)"
]
},
{
"cell_type": "markdown",
"id": "fe7c5736",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "markdown",
"checksum": "db023e65fc2613d624f29977a82bf1f1",
"grade": false,
"grade_id": "cell-b0e00f11b0f85525",
"locked": true,
"schema_version": 3,
"solution": false,
"task": false
}
},
"source": [
"__(b)__ Assuming $N \\leq \\lceil \\frac12 L -1 \\rceil^2$ where $\\lceil r\\rceil$ is the smallest integer larger or equal to $r$, write a function `generate_initial_positions` that produces an arbitrary non-overlapping (and non-touching) initial condition given $N$ and $L$. The layout need not be random, any deterministic layout is ok (e.g. grid). **(10 pts)**"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "f86a04ed",
"metadata": {
"deletable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "b17579d74c8ff8572d81f18997b49c90",
"grade": false,
"grade_id": "cell-53c1bd894d6fe27d",
"locked": false,
"schema_version": 3,
"solution": true,
"task": false
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"def generate_initial_positions(N,L):\n",
" '''Return array of positions of N disks in non-overlapping positions.'''\n",
" assert N <= np.ceil( (.5*L**2 - 1)**2 )\n",
" \n",
" disks = np.zeros((N, 2))\n",
" i = 0\n",
" # To have the disks non-touchting, we have them 2.0001 apart instead of 2.\n",
" for x in np.arange(1, L - 1, 2.0001):\n",
" for y in np.arange(1, L - 1, 2.0001):\n",
" if i + 1 > N: return disks\n",
" disks[i] = x, y\n",
" i += 1\n",
" return disks\n",
" \n",
"plot_disk_configuration(generate_initial_positions(33,14.5),14.5)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "3d3dc3db",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "fa73c21133aa2b913b931b266e7782f0",
"grade": true,
"grade_id": "cell-e1c80d8b59301b93",
"locked": true,
"points": 10,
"schema_version": 3,
"solution": false,
"task": false
}
},
"outputs": [],
"source": [
"for l in [4,9.2,14.5]:\n",
" for n in range(1,int(np.ceil(l/2-1)**2)+1):\n",
" assert disk_config_valid(generate_initial_positions(n,l),l), \"Failed for n = {}, l = {}\".format(n,l)"
]
},
{
"cell_type": "markdown",
"id": "eb5dbe07",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "markdown",
"checksum": "b4bb37c92263c95c89055362336f894a",
"grade": false,
"grade_id": "cell-1bd76964ec9620ce",
"locked": true,
"schema_version": 3,
"solution": false,
"task": false
}
},
"source": [
"__(c)__ Write a function `remains_valid_after_move` that determines whether in a non-overlapping configuration $x$ moving the $i$th disk to `next_position` results in a valid non-overlapping configuration. **(10 pts)**"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "56252046",
"metadata": {
"deletable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "04ff82e1b0e3386f2cb15412695c1864",
"grade": false,
"grade_id": "cell-d54b4fa9b2f8eb92",
"locked": false,
"schema_version": 3,
"solution": true,
"task": false
}
},
"outputs": [],
"source": [
"def remains_valid_after_move(x,i,next_position,L):\n",
" '''Returns True if replacing x[i] by next_position would yield a valid configuration,\n",
" otherwise False.'''\n",
" # We need to ensure that x is not changed after this function,\n",
" # as alterations done on x will affect x outside the function.\n",
" \n",
" #current_position = np.copy(x[i])\n",
" current_position = x[i].copy()\n",
" #print(type(current_position))\n",
" x[i] = next_position\n",
" ret = disk_config_valid(x, L)\n",
" x[i] = current_position\n",
" return ret\n",
" \n",
" # An alternative approach was to fully copy x, but that turned\n",
" # out to be a lot slower:\n",
" #copy_x = np.copy(x)\n",
" #copy_x[i] = next_position\n",
" #return disk_config_valid(copy_x, L)\n",
" \n",
" # This was tested using the following code.\n",
" #\n",
" # L = 11.3\n",
" # N = 20\n",
" # delta = .3\n",
" # x = generate_initial_positions(N, L)\n",
" # %timeit [MH_disk_move(x, L, delta) for _ in range(1000)]\n",
" #\n",
" # For the full copy method:\n",
" # 2.05 s ± 46.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n",
" # For the current method, changing x[i] back:\n",
" # 138 ms ± 12.3 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "167bdc3e",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "37fe75b415d4e31369d6b6bb1041609b",
"grade": true,
"grade_id": "cell-e4902309b9869f3d",
"locked": true,
"points": 10,
"schema_version": 3,
"solution": false,
"task": false
}
},
"outputs": [],
"source": [
"assert remains_valid_after_move([[0.1,0.5],[2.1,1.5],[3.2,3.4]],0,[4.5,0.5],5)\n",
"assert not remains_valid_after_move([[0.1,0.5],[2.1,1.5],[3.2,3.4]],1,[4.5,0.5],5)\n",
"assert not remains_valid_after_move([[0.1,0.5],[2.1,1.5],[3.2,3.4]],2,[3.2,2.5],5)\n",
"assert remains_valid_after_move([[0.1,0.5],[2.1,1.5],[3.2,3.4]],2,[3.2,3.8],5)"
]
},
{
"cell_type": "markdown",
"id": "a8cd0c44",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"cell_type": "markdown",
"checksum": "8e0cfe7c5bce12cc34e939c5c151ed65",
"grade": false,
"grade_id": "cell-582ca3e158908e6c",
"locked": true,
"schema_version": 3,
"solution": false,
"task": false
}
},
"source": [
"__(d)__ Implement the Metropolis-Hastings transition by selecting a uniformly chosen disk and displacing it by $ (\\delta\\,\\mathcal{N}_1,\\delta\\,\\mathcal{N}_2)$ where $\\delta>0$ is a parameter and $\\mathcal{N}_i$ are independent normal random variables (make sure to keep positions within $[0,L)^2$ by taking the new position modulo $L$). Test run your simulation for $L=11.3$ and $N=20$ and $\\delta = 0.3$ and about $10000$ Markov chain steps and plot the final state. **(15 pts)**"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "ccaa8f9f",
"metadata": {
"deletable": false,
"nbgrader": {
"cell_type": "code",
"checksum": "24f09b7137c0184ddb872ef558f756a9",
"grade": true,
"grade_id": "cell-e180b99ca699c610",
"locked": false,
"points": 15,
"schema_version": 3,
"solution": true,
"task": false
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Of 10000 proposed moves, 5282 were taken (52.8%).\n"
]
}
],
"source": [
"def MH_disk_move(x,L,delta):\n",
" '''Perform random MH move on configuration x, thus changing the array x (if accepted). \n",
" Return True if move was accepted, False otherwise.'''\n",
" \n",
" # Although it is tempting to use the wacky method of pulling two independent\n",
" # normal RVs using the method developed two weeks ago, let's just use Numpy.\n",
" N1, N2 = rng.normal(), rng.normal()\n",
" n = len(x)\n",
" i = np.floor(rng.random()*n).astype(int)\n",
" new_position = x[i] + delta*np.array([N1, N2])\n",
" new_position %= L\n",
" \n",
" if remains_valid_after_move(x, i, new_position, L):\n",
" x[i] = new_position\n",
" return True\n",
" return False\n",
" \n",
"# Test run and plot resulting configuration\n",
"steps = 10000\n",
"num_moves = 0\n",
"\n",
"L = 11.3\n",
"N = 20\n",
"delta = .3\n",
"\n",
"x = generate_initial_positions(N, L)\n",
"plot_disk_configuration(x, L)\n",
"\n",
"for _ in range(steps):\n",
" num_moves += MH_disk_move(x, L, delta)\n",
"\n",
"plot_disk_configuration(x, L)\n",
"print(\"Of {} proposed moves, {} were taken ({:.1f}%).\".format(steps, num_moves, num_moves/steps*100))"
]
}
],
"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.9.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}