1086 lines
154 KiB
Plaintext
1086 lines
154 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": "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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",
|
|
"plt.title(\"Markov chain visiting density for uniform transition matrix $Q(x \\\\to y)$\")\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",
|
|
"plt.title(\"Markov chain visiting density for uniform Metropolis-Hastings transition matrix $P(x \\\\to y)$\")\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": "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\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": "iVBORw0KGgoAAAANSUhEUgAAAOsAAADrCAYAAACICmHVAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAApRklEQVR4nO3dZ2CT16H/8Z8kL8AD8JJssI23AQ8MwQnYgUAIw2mbtmGa/Ns0pEnb/70Nw2S099VtJiu7IzRpw0jApOntbRjZCRAwYdkQbDBgvA2eMnhb0n0hCSyj8YxzzvM4Ot93CeNn2RxblqXno7FYLODxeOpPq/QbwOPxhMUPK483TOKHlccbJvHDyuMNk/hh5fGGSfyw8njDJB8xvzksLMwSFxdH6U3h8XgnTpxotlgs4c5+TdRhjYuLw/Hjx8m8VTwe77Y0Gk2Vq1/jd4N5vGESP6w83jCJH1Yeb5jEDyuPN0zih5XHGyaJejRYaMbufpytM+JMnRFXmjvR02+CTqtFWJAfJkeFID06BHFho5jthgf5Y3J0MNKjQxAbSmG3qx9nBu32Dny/d3nKROywWiwWHKxoxrajVfi8/BpMZvcvvUsIH4WCnFg8OG0cggN8Ze++e6QKX5wXtrvyzlj8dKr83a8rmrFN4G5iRCBW5sTgp1PHIUjm7lcXmrD9aBW+ON/kcTcpIhAFBHZ5yqcR83rWadOmWZz9nLWsoQOFe0pwtq5D9Bswyk+HJxem4qE7Y6HRaET92XP11t3v6sXvBvr74MkFKVgpYfe7eiMKi0pxrkHa7lMLU1GQEyN692ydEYV7SlEmYTfI3wdPLUpFQU6s6D/LY5dGozlhsVimOf01OYfVYrHg9c8v4tXPK9Bvkvci9rviQ7FpSSaiRo/w+HstFgte+/wiXiOwOyPBumsIEbb76mcX8foX8ndnJoZi0+Is6EMCPP5es9mCVz6rwBtfXMSAh6+knspNDMOmJZmIDPa8y2MflcNqMltQuKcE/zhZR+atBBAVEoDtq3IQHx7o8veYzBasKyrBh6fI7UaPHoHtq3Iwwc330SazBWt2n8b/nK4nurtjVY7b798HTGas2V2Cf5WQ3d35aA7/flaFuTuskh8NfuYfZ4geVACoN/agYGsx6tq7Xf6epz4oJXpQAaCuvRsFbx1FvZvd9XtKiR7Um7tbi9FgdLP7QSnRg2rfXfFWMRqNPUT/Xh7dJB3WouM12HW8hvTbAgBoMPZg9a7TcPYVf/fxGhSdqKWyW+9md9e31fjgJJ3duvZurNlV4nT3vWPVxD8hOuzudn57eepM9GFtNPbgv/99jsbbcrNjla34+zdXHP5fg7Gb+m5xZSvePeL4POoGYzf+8FEZ1d0jl1uw/ajjbn17N56jvPvNpRbsKK6musEjl+jD+sK+MnT0DNB4Wxx66cB5tHf1Ddotx3UGuy/uL4exq//mfz+3l83uC/vKYey+tfvs3jJc72Wz29HT7/k38hRP1GEdMFuw90wjrbfFoa4+E3bb7mo3Xe/F3jMNzHaLTlh3r3X0YP9ZNrudfSbssd3Fv9rRgwNn2byfb/QOYM9xOnfxeWQTdVhbO/vQZzLTeltua0dxNSwWC3Z9Wy37RyVSdt//tobt7tEqWCwWvHesWvaPaMS0vdjlSyh5KkrUYe3oZnt3qaqlCxXXbuCTsmtMdyubO3Gp6QY+LbvKdPdycycuN3ey323qxOWmG0w3eeITdVh7Bky03g6Xna5uR7mEZ+zI3q1pR3njdfa71W240Mj+4JypMzLf5IlL1GFV4lH+Qxeb0TvA7q63vYMXmtGnxG5FM9NvNeyd5YdV9an+JXINHa6fMECzejdPVKBZg0JPVGi63qvILk94qj+sAwwf4Bmcp1ez0GrAzP6rKgD0K3R7ecJT/WEN8NEptKvMu8Zfodvrr9Dt5QlP9R+hFH2QIrvJ+mBFdlMilbm9E/iT+lWfqMPqoxX3+ksSzUwMw5iR7F80nZsYhpAR7HfzksMQHEDlAh5umzwuhPkmT1yiDusIX/Z30TLGhSBz/GimmxoNkDFeod1xoxXZTY/mh1XtiTqso0f60Xo7nDYjIRSRwQF4ICua6e7MhDBEBAXggawopru5iWEIC/THjxjf3rykcIQF+jPd5IlP1GENGeGLsEB2B/ahO62XIFmYrkfoKHa7K++MAQDkZxgwlumu9fben2Fgetff/n7mqTtRh1WjAR6eOYHW2+JQfNgozJsYCcD6COnPZ8Qx3NUz300IH4V706y3N8BXh58x2k2MCMTc1AgmWzx5iX40+Jd3xyPNQPeRUq0GeOnBDPjobr15j89OQCrlR4a1GmDD4gzoBj2Q9vgsVruZDru/np2I5EjXl7chkU6rwYYHM6BV4IFDnvhEH1ZfnRYbF2fAV0fvA/zwzAmYFjfWyW4m1d1Hcidgaqzjrp8P/d1H8+KRHTPG6S7NR+BX5U3AlCG7PPUm6eesk6JCsGVpFmj8O5qbGoGnF6Y6/bXJ0SHYtITO7r1pkXhygevdjYszqezOmxiJwvkpTn8tY9xobFycCZFXLBXU/EmRWD/f+e3lqTPJT4q4PyMKryybQvQrzvxJkXhzZbbD3d+h/TAzCi8T3l0wSY83C9zv/igrGluWZhH9SrcoXY83VrjffWBKNLYsIbubn27A6yuyHe5289Sf7It8n60zYl1RiayXkwX4alE4PxUPz4gT/P3TmVrr7vmr0ndH+OpQOD8FD8+ME3zB7dLadqwrKsGFq9JfxjbCV4cnF6TgZzOE75bUWHcrrknfHemnw5MLUvH/7hJ/YXMem6hd5Nte34AZf/rqEt45XIm2LuEvUNdqgDmpEfh9/kRJ9k3fgBlvfnkRf/vmCtpF70bi9/lpknff+OIi/n5E/O7cNOuulGv29g6Y8MYXl/CuhN170yLx+/yJiAkdKXqXxy7qh9VeT78J/y5twIenalFaY3R6wS+dVoPE8EDckxqBgpwYjB8r/x9PT78J/1tSjw9P1eFMrfvdOWkRWDGd/G5prRE3XOwmRdy6vePGkNn9V0k9PjxZhzN17nfnpEZgBaFdHv2YHVZ7xq5+lNa246uKJpQ3dKB3wAydRoPIkADkJoZhWtxYt1e/l5qxqx8ltW34uqL5tt28pHBMjR1DZbe9qw+lte0ud6fFjqGi5tl3v7pg3e0zWXf1g24vjV0evZgcVrGqWnzYKKzIicHiaeNlPWFerKoWb9frpo6TvfvlhSZst91eTy8HJaXmmc0WfFUhfDdxkCInZ5fHJuqHVY7mNtJPh/XzxT3YYk+O5jbKT4f1Eh9skaO5jfLT4amFqZL0OjkP5gX6++DJhalYKUGv47GLqiJHSnPLmTAWm5dmIVqgImdX1eTu3hk/FpuXZAnS60hqbnfFh2LzUmF6ndlswcufXsCbX16SvTsjIRSblwjT63jso6bIkdbcDDZFLsGDIkdacxOi19HS3DzpdQMmM57YdRr/LiV3sXEheh1PmagocjQ0twZjDwreKkZtW5fL3/PkB+Q1NyF6HS3NzZNeV7inlOhBvbnrQa/jqS9Jh5Wm5tbY0eNSVdv9bc1NYoJ0DcYerHGhyL1PUXOrN/a41Nx2FlcT/4Roz51ex1Nn6lTkrrTincNXHP5fg7Eb//0RfUVuqF5X396NZylrbkcvt2LbEEWurr0bz+1lr9fx1JskRY6FqrZhiCL3PCPNbahe9/y+cmaam6NeV+b0yQ5UdhmzKDxpqVaR6+6/pchdu96DfYw0t64+E4psqhpLRW6wXtdoZKfIdfaZ8AGlby14ZFO1Irf9qE2RO8ZYcyu2a26sd6uVUeRseh1P3alakatutSpyn5azVeSutHThUtMNfFbOVnOrtClyrHcvN3eisrmT6SZPfOIUuX7vUeROVrWhvIG9IneqiityPOeJU+RovRVuUkqRO3RRGc3toEK7XJFTf6rnM5RS5JTS3Bq5IsdzkeoPq7cpcv0KfFUFuCI3HFL9YfU2RS5AAaIE4IrccEj1HyGlFLkUytdGdhXtaxS7iity6o8rci7KTQzDaAV285LCuSLHc5qqFTmrqqaM5pY+LgQZ45TZVUSv44qc6uOKnJPsityPpyijyLG+vXcnhSOUK3KqT4Iix+6DatfNFqUbGCtyyuzab+/9mVyR492eBEUujtKb4lh8+C3Nzc9Hy3iXvV6XGBGIuWmDd9loffbLlfLUnyRFbiIDRW7Dg46a22OzEpjodRsedNTcWOh1ds1t8O6vGO1uXJzJFblhkkRFLhN+bnwWuTnT3Ox6Hc3dR/PiMTXWUVVjodc9mhd/m+bm56PFhgfp7v7y7njmD2bxpCfpX/7EqGBsWZpFBTZyp7lNigrB5qXsNTeaet38Sa5308fR0+sWTNJj3X3Od3nqTPKXqfwMA15bPoXoV7qFkz1rbvdnROHV5WQVOSGaGw29Lj/Ds+Zm1+tI7v4gMwqvrZjCFblhluyLfH9Xb8Ta3fIUuRG+OqxfkIKfi7jQNwm9TormRkKvG2m70PdDIi70fabWiLVFp2XpdSP9dHha4gXGeWyifkX+fpMZf/ryEt755gpaO/uc/EnnkdDcpOp1cjQ3u17392+uiNrVaTWYa1PzpGhuUvU6nVaDe9OsuyRALh69mMFUvQMmfFTagA9P1aGkph0dTi5w5qPVIJGwbtbTP2i3tt3phdWU3E2KDMKc1HCsyIkVJA4I2b2p9dUa3e7Otd1eIeIAT/mYK3LtXX0oqWnHwYpmlDV2oLffDJ1Wg8hgf+QmhmNq3BjEh40iflesrbMPJbXtODRkVx/sj7zkcEyJUWY3O8aq19HaPXihCWWN19E3YNsNCUBeUhiyY8a4VQak1tpp1evO1hlR2dxl0+uA8CB/TI4OQXp0CJVdb4iZIidGVZsQNgoFOTFYPHU8QmQ8W8e+u+1IFb4UsEtKrzObrXrdtqPCdwvulK/Xmc0WfHnhGrYdqcJXF5o87xJS8+y77x6pwtcCd1cSUPO8LeqHVY7mNtJPh8L54h5csidHc5Oj18l5cEuOXnem1ojCPdJ3pep1pbXtKCwqlfSgWqC/D55ckMIf1BIYtcNqNlvw6udkNLfpE8Zi85JMQd9Lms0WvPxZBd4koLmJ0etIam5i9botn17AHwnsitHrTGYLtnxyAX/6ioxet2mJsF1vjpoiR1pz0wdbNbfECPea2+rdJfhfgkiUPjgAOx51r9fR0NwMIQHYIUCv++37p/HRGXK7USEB2PHonR71uv98/xTRi7oLUfO8PSqK3Po95DW3xo4eFGw96laRW/9BKdGDenP3LfeKHA3NrcGm17lT5NYWlRA9qIBNzXOj11ksFqzZXUJcX6hr78ZKrtdJTpoi920NPjhJh1y42tGL1btOw+zkbhdNza2xower33euub13jJ7m1mDswWoXet2O4irinxDtudPrthdXE+ct7dW1d2Ptbq7XSUn0YWWhuX17pQ3vKKC5HbvSir8N2a1jsFtc2Yp3jzhqbrVtXXh+bznVXWd6XU1rF16grNd9c6kF24urqW58H5OgyLHR3DYeOI+2Tvaa20v7h+p1bDS3F/c7KnLP7y1nsztEkXtubxk6++jLCy/uK0dHD9frxCRBkWOjqjkocgw1t9t32Whutyly37FT5OxAdYOxGx+fY+Ps3Ogd4HqdyEQrcqxVNbPZgve/VUZz28lYc1Ns16bI7SyuZnpxcw45i0v1itzFphv4rIytqlbV0oWL127gszK2el1lcycuNXXic4UUOda391IT1+vENCwUuTIZL4OT2qnqNpxXYPd0tTKK3KnqNlRcY397uV4nPNUrcgcvNqFPAUVOKc1Nsd2KZqbfatjjep3wVM9nNHZ4l+am1K5Sah7X64Sn+sPqbYrcgFkZRY7lA1pq2B2Oqf6wKqWqKabIeZmax/U64an+PZUa6V2KnFJqXqpBIb2OP6lfcMNCkRvLkLCwp6QiJ+dF4lLLTQxDkBJ6HQexBCdOkfNTSJFjzBFad0cjUyFFLsNLbq+W63WiUrUiNzMhDBHBAXhgCltVLTcxDOFB/vgx4928pHCEBbLfnZVsVeRYv59np0RgjAL3moZrqlbk7JrbwskGhAV6jyKXn2Fgetf/pl6XwfU6NSdOkQPwi9w4Om/JkAZrblZFjo2qlhA+CvemDd6NY7KbFBGIuTbNjaVelxwZiHtSrLsBvjr8jNFuqj4Is5LDmWx9XxKvyOXFY1IUe82NhV5nV9VY63XONLfHZ7HS6xx3fz07kfquj5NdnudEH1YfBorcKjeaG93dCbdpbna9jrXm5udDX697TKHdx2clIJ3xg2jfhyT9y08zBOOVZXQUuXkTI7Hehao2MSoYL1PanT8pEuvnu9brtiylo8gtnOxac6Op1y1K12OtArv56QasmZdM/i/2giR/mVqYbsDrhBU5IZrbonTyep0QzY2GXveDTOvf6W6Xhl73w8wovLqM/e6PsqLwyrIsfvdXYrIv8n2uvgPrikokXeDb3kg/HZ4UeeHr7+qNWFck7QLfg3fFam4k9LpRfjo8tSgNK3NimO8+vSgNBSJ2Sah5o/x0eCY/DQU5/NFfTzFR5P7y9WW8fagSLSIUObmqWr/JjD9/dQlvHxan19lVtd8tkr77xy8v4W8i1TydVoN5aZH4XX6aJM2tb8C+K07N02k1uG9iJJ5ZpMzu7/LTiEBg3hBTRW7vmQb842QdSmuNDhfiskdDVROq1yVHBmFOagSW58Qw2/XVaZAUEXRTryOhuQ3W60pr3e/OTbPukrgSvl2v+6eH3WSbXrec0K43xVyRsytjhyqaUNZwAz0DJvhoNYgMDkBuUiiyY8YgITyQuH3ialcfbFXVsmLGICGcvObWcqMXpXVGHLJpbr0DZma7JbXtOFzRrJrdu5OtuzS0Pm+IyWEVq5vFho5EQU4MlkwbL+tpjGJ340JHoiAnFounjZO9+8X5a9h2VJiqRkrNM5st+LzctlvRBE8fPpK7n9l2DwrYJaX1eVvUD6ucBz9G+Oqwbn4KHp4RJ/pRQjmq2ghfq1738EzxipwcVU2OmldS047CPSW4cFX8NZqkPIhHYleOmueNUVXkSGlud8SNweYlWYIeACGpqk2PG4vNS4XrdZsJqWrTJ4zFFoF6nclsweZPzuNPX12WfQWLHNuukO+dTWYLNn18Hn/+Wv6uGDXPm6OmyK3edZqoiRIZ7I8dq3KQGOH66W60FDkhet1vd53GR4QVue2rPOt1pDW3KNuuO72u32TGbynsetLrvD0qilzhnhLieNHVjl4UbC1GTasbRW4PHUVu5dZit3rduqISogcVsF6kbOVW13odLc2t3rbrTpFbS2m34K2jXJGTmKTDuutbepqbR0WOkubW2NGDNbuc62Y7i6vxT0qaW4OxB2tcKnL0NLd6N3odTUWu3uj6/cxzn+jDWt/ejT/8m64ydryqDW8frrxtl4Ui987hKw7/r669G89RVtWKK1vx9yF6nVWRY6/XsVDkjlxu4XSGhKQpcgx0s00fX3B4dtBze8uY7G4Yotc9x0iRe+nAeQdFjpXm9tIQve7Zj9jsvsAVOdGJVuT2KaS5sVLVuvtvaW5XO3pwQDFFjo130zlot769G58wcoU6+0zYc5wrcmJSuSJXpagi956CihzLi4wPvr1MFblifldYTKpW5Gpau1FxzfsUOda3t7K5E5ebO/Ep49t7mStyolK/IlfjhYqcjJejSe1UdRsqFNjlipzwVK/IHfJCRU4Jze3ghWZF3BmuyAlP9XwGV+QY7Sr0fuaKnPBUf1i5Isdqlytyak/1h5Urcqx2uSKn9lT/nuKKHJu4Iqf+uCLnorwkhRS5ZO9S5NI5TCU4rsi52E2PVkaRy4hmr8hpFVTk+GEVHlfknKSUInd3klVzY77LFblhEVfknPQQV+SY7vKEJVqReySXneamhCKXGBGIuYMUuV8wur1JEYGYM0iRe5iR5pYSGeSgyP18BpvbyxU58Yl+NPjRvAmYHM1AkVusjCK34cGM23YVUeRm01fkfLQabFic4bD7K0a7Q28vz3OqVOQezYtHthPNbdMS+ruuFDmau840N7uaR1WRmxWPjCEPKrFQ5H41OwGT+QNLopP0LzBVH4xXl9PR3O6bGIn1C5xrbmkGeorcgkl6FLrQ62grcu40t80UNbe18xRQ5DIMWH0vV+SkJPnLxYLJBryxgrDmlm7AGwXuNbdFFPS6+zMMeG2Fe1UtP8OA15ZnE939oQBF7geZUXhFAc2NhiL3QFYUXlnKFTmpyb7Id1mDVZH7rp6t5kZCr5OiuZHQ66RobiQUuUB/Hzy9KFWU5kZq95lFaViREyP57/CWqF+Rf8Bkxl8OWhW55hvsVDW7XvfOYfG7clQ1u173zuErotQ8H60G902y7kpR1fpNZvzJpteJ3Z0/SY+nF6XK2n1HpJpn330mP40IBOYNMYOp+gbM2HfWqsiV1Laj3QkPaFfG7KoaCWWsb8Bs1etsupmr3RR9EOakkNPNhOz66bRI1gdiTkoEVuTEQh8SIHtXiNZ3czc1EiumxxDbvaXXud5N0d/6+EYGy9/1ppgrcjdVtYpmlDd0oGfABJ1Wi8hgf+QmhCE7dgwSI8grci03elFaa8Shi467+uAA5CaGYkoMnd3mG704Y9sta+hA75Dd7Fg6ap5992BFM8obHXfzkqy3l9auVetrYbrrDTFT5MSoajFjbylycp5yJlZViw0diRXTyeyKUdXiQkdiBQE1zzTo9grdJaHmmcwWfFZ2FduOVuHQxWbBu0umydPrvC3qh1WO5hbgq8W6+1Lwi5kTRD9KKEdzG+Grw9r7kiXtylHV5Oh1p2vaUVhUgopr0hQ5qXqd3N3181PwMwm73hhVRY6U5jYtdgy2LBWuyJHS3MTodSQ1NzF6nclswcaPz+MvBDQ3sXodqV0xep03R+Ww0tDcIoKsilySmxec09DchOp1pDU3IXpdv8mM/3zvFPYRvNi4EL2u32TGf+w8hf0EL65uCAnADg96nbdHRZGjobldu+5ZkaOhuQnR69YWkVfVPOl1dkWO5EEFhOl1q3edJnpQ7bsFbvQ6nvskHVaamtu16714woUiR1Nzu9rRizW7ne/uKK7C/1DadafXbS+uJv4J0Z47vW7b0Sr8m/AnRIfd3c53ee6TpMjR1txOOFHkWGhu315pwztONbdyqrvHrrTib0N2WWhuzvS6mtYuvLCP7u09erkV27giJzrRh/V5Rorcxo/POzxb5nlGmtvGIYrc83vL2Shy+8+jvctRr2OiyA3R6/7w0Tl0Mdh9cV+50ydV8FwnTpEzWbCfkSLX02/Grm9vKXL7GWlug/U6q+bGUK+zqWoNxm58fI6NdzNYr6tr72bm3XT2mbDnBFfkxCROketiq8jtPGZV5N47VqOI5sZekauy7hYrpMix3j1axb93FdGwUOQ+L2erqlW3WhW5z8vZqmpXWrqsihzjXbsix3r3cnMnrrS4fgSe5xhX5Fx0UiFF7lR1q1cpcqW17cw3h2tckXO1W6GQIlfRwhU5ntNUz2copsgptHvVy26vmNche3uqP6xckWO1yxU5taf6w6qYIufLFTkWcUVOeKp/T9G+hq3rXWUulanY7eWKnOpTvyKXoIwil5sUqogil8sVOZ6LuCLnYlcJRU6roCKXOX4MV+RUnqjDOoaxIpebaFXkfpw9juluXlI4woP88ZNsZTQ31ruzksMxdpQfc73uHq7IiUrUYQ0e4YvwIPaK3IJJerZ6ne36tqz1upU5Cul1d9kUuUy2itzKu7giJybVKnKJEYG410Fzi2OymzREkWOl1yVHDlHkZsYx2U3VB2F28uBddorcbK7IiUr0o8GrcidQ/z7DqeaWF09dr7Nrbqz1Omeq2mOzEqjrdT5aDTY8mKmYIscvoCYu6YocxZ+PrcqbcJvmxmL3l240N6qKnBPNjYVe9/isBKQPeTCLhV73a67ISUrSv4QUfRBeXeYeVJLagkl6rJ/vXJFL1QfjVUqK3MLJeqxzoblNjKKn17nT3GjqdfkZBqyZ51xzmxxNb/cHmVF4gitykpKhyOnxxopsol/phGhuN/U6grtCNDcaep0QzY2GXvfjKdEeNbf7M6zvE9K7W5ZwRFlqsi/yXd7YgcKiUpyR8eoJKZpbeaNVkTtbJ11zk6KqkVDzpKhqJPS6IH8fPJOfhuXT2e/+Lj8Ny0TsemtMFLmthyrx10OVaLreK/jvs6tqTy+UprkNmMx466B1t/mGuF05qtqAyYw/S9DrfLQazJ+sxzOLpKlqUtU8H60GC2y7Ui6yLXXXV2dT5CTuemPMYKp+kxn7zjbiw5O1KKk1OuUB7crYPakRxHQzu15n183c7ZLUzQbvltS0o82FIpdqCMI9KeR3rYqc+905tvdzBKHdvWfs72cXuz5apOqDMDc1Esunjyey600xV+RuKWNW3ayn3wydVgN9cABmJIYiO2YskiICiX/v0nTdunv44u27M5PCMGX8GKq7hy4247yT3ewY6y7pH1Xc3K1oRvnVDvQO2s1LCkdWzGgqu9eu96C0xmh9PzPc9YaYKXJiVLVxY0ZgRU4Mlt0RI+uJ+mJ1s/FjR2DF9FgsvWO87N1Py65iu8DdmLFWRW6pTL1O7C4pNc9ktuCTc9bdw5fY7Xpb1A9raW071hVJU9UCfLVYMy8Zq3LjJWlu6yTqZgG+Wqydl4JHcsUrcqdtuxcl7kpV805Wt6GwqASXmjpF747w1WHd/BQ8PCOO+a5UNc8bo6rIbSKkqmXHjMYry6YI1tw2fXwefyagm02NHYOXBep1JFU1sXrdSwfKsfVgJXO97qUD5Xjr68sevV0hu1uWCdPrvDlqihxpzS3cpsgle1DkSGtuQvQ6GpqbEL2u32TG/995Ege+I3c5ViF6Xd+AdZfkxcb1wQHY8ah7vc7bo6LI0dDcmmyKXLWba8nS0Nw86XW0NDdPep3FYsETu04TPaiAML1u9a7TxFWAxo4eFLzlWq/juU/SYaWpuTVd78UTu04x19zc6XU0NTd3et22o1XEPyHac6fXvXukCh+dobnLFTkpiT6sLDS3k9Xt+OshR0WOhebmTK9jobk50+tYaG7O9Lrqli68uJ/ubnFlK949whU5sYlX5Bhpbps+GarIsdHcbtPr9rHR3DYecFTknv2ojInmtkEpRW4/V+TEJlqRY6WqDVbkrnaw09x6+s0OitzHhL9fdNVgva6+vRuflCmjyLHybrq4Iic6cYpcJ1tFbkexXZFjr7mZzRbsZL57S69jeZHx7TbNbWdxlSK7PGGJU+R62N5tqW2zK3JsdbOa1m5cbGKv11W1dOFSkzJ63eXmTnxe3sR0t7K5E5XN4p9o4a0NC0WuXBHNrQ0XGsU/Q4nIrhcpcnJeWultcUXO1S5X5JjEFTnhqZ7P4Iocm7gip/5Uf1i5Isdqlytyak/1h3UEV+S+17tckROe6t9TSulmSilytK8V7HI3iityam9YKHIsKQl7uUmhTCkJezOTwhTR6/KSwhHMFTlVp3pFLn1cyG0X3maxmzFuNPPdW4oc+930aPbvZ61NCeQJS/2KXFAAHmCsm+UlhSMs0J+5qnZTkWO8OzslQhFFbk5qBEYz/jc1nBOtyEUwVOQesilyCyezVeRu7RoU2WWuyNl28zMMTOFquxLIE5ZqFbnBmpuvTstsNzkyEHNtmhtLvS4l0nq50lu77DS3WTbNzd9Hh4dnxDHZTTME39zlCUu8IpcXT/37DJ1Wgw1DNLdH81jpdY68wy/z4jEpir0ip5Re9/hsNnrdxsUZ/AJqIhN9WO0sIm3NLWvIgx0sFLnHZ92uyLHY/dVs15obTUXOmebGQq/7zT2JmBTFH1gSm6SPSHJkEF5fPoXKj3LcaW4p+iC85gGQkpo7zS3NQE+vuz/DgNUuVDWaep07zW1SVAi13R9mRuG3c5OI/73ekORPn/dN0uPNgmyiz0ARornNt+2S/EonRHOjodf9eEo0XvagudHQ634iQHNblG7Aa6R3s6OtlCRX5CQl+yLfF65ex7qiEpTWSn/1hBTNjYReJ0VzI6HXSdHcSOh1Qf4++P39aVh6h/Ddc/XW3XNyFLkAH/w+X9yut8ZEkfvroUpslaDIydXcpOp1cjS3AZMZfzl4GW8fuiJKr5Orqt3S68TvLphswNMLU5krcgsmG/DMolQYQvjFvYXEVJE78F0jPjxZh5LadqcfWD8fLdJsitzy6WRUtX6TGfvPNt7U3FqcKXKUdvedbcQ/Pe0agjEnJYKYqjZY6yutNTrd9ffRItUQjLmpEVg2fTwigsjpdf+0aX2sdr0p5oqcXRn75lIzyhuvo7vfBF+tFpHB/piRGIas8aOREhlE/HsXl7sh/piZEIasmNFIjqCw29GDklrbbsN19Awou6sPCcCMhFBFdmfaPr40tD5viMlhFaubRY+2K3LjESrjWUJid+163dJp8nfFqGok9bpPzjVi29EqfHOphfnuu0esu54ipeZ5W9QP6+madhRK1Nz8fWyKXF686B8VnKpuQ+GeUsmam1S9To6qJkevO1HVhvV7pO9K1etOVLWicE8pLktU5Nbelyxp1xujdlhJqmpTYkbjlaVTEBMqTDfbcOA83jpIRq97WcQuKVVNjF43YDLjpQPnsfWg/N1psWOwRYHdO+Ksu1IeSPSmqClypDW38CB/bH8kByl6tpqbEL2OhuYmRK/rGzDjNztP4hOCSJQQvY7e7p1u9Tpvj4oit2Y3ec3NrshVtTi/u0VLc2sSoMjR0NyE6HVP7DpF9MAAQvU6WrtHXep1PPdJOqw7iqvwL0qqWvMNq+bm7O7tDoqaW5M7RY6i5nbtei9Wu9h990gV8U+I9tzpdX//5grlXed6Hc99og8rC83tVHU7th687PD/alq78Dxlze1EVdttel1Naxeep6y5HXei17HQ3JzpdVUtnXhx/3mqu8cqb9freJ4Tr8jtY6O5bf7kAloGPUuHleY2VK97bi8bzW3jx+fRNmj32b1sNLehet0fPipDNwN5Yahex/OceEWO8PeLruodMGOXAprbYL2u0dhDXP92tztYkfu0jI13091vQtFxq+ZW29aFzxTQ63jCEq3Isbwo887iakUUuZ3HbilyLC/2rZQit6O46uYuy2tu228vT1iqV+QuXLuOL857hyJX3WpV5D5j9FXV3pWWLlxq6mS+yxU5calekTtV3YbyBva62ckqZRS5k1VtqLimjCIn5ZlgcuOKnPBUr8h9c7FFEc3t0EVlFLlDSilyFVyRU3uq5zMar3uX5nbVy24vV+SEp/rDyhU5VrtckVN7qj+sXJH7fu9yRU54qn9PcUWO0S5X5FQfV+RclJcUpogil+tlihyHqYTHFTkV7Wptep03KXKcfBSeqhW5vKRwRAQFsNfcbIrcT7LHMd2dlRyOsaP88NNstrf3Hpsi9xPGu3NSI7kiJ6JhocgtmKxHuDfodXcN1usYam53KaTX3cUVOTGJVuRW5bHX3FgrcnMU2E3VB2F28i1F7uGZbHbTDMGYPViRmxnHZHeiIRh3J4Ux2fq+JPrR4Edy45HJQpEbormtyqWvyDlT1Vjodc52H7ubjV634UFHze2xWfQVOV+d9fZyRU5ckhU5mj8fe+xu55rbpiV0dx+flXDbgzs+Oi02LM6gqsg509x8WChy9yQ6VeQ2Ud79zT2JmEj5E9H3MUkfkaTIILy+IpvKj3Ly0w0uFbnkSKsiR2P3/gwD1sxzrqql6oOp6XXuNLc0QzBeXU5Hc/tRVhSecKG5TYwKxiuUFLkHsrgiJzXJnz7nTYzEH1dOJfqVTojmdh8FRe6BrCiPmtv8SXq8sYLsrhDN7aZeR/Ar3U+zx2HzEve3dyEFve7BqeOwaUkWv/srMSKKXGFRCUpkKnJiNTcSep0UzY2EXidFcyOi1wX44L/yJ2LJHeMF/xkiel2AD/7r/olYMk34rrdG/Yr8JrMFbx+qxNZDl3G1Q7yq9rQMze2vNkXumghFTq6qJlWv89VpsHCyAU/J2H3rYCXePix+d1G6dVeK5qbUrjfGDKYaMJlx4Lur+PBULU7XGJ2yhHZljLSqdkuvc72bZgjGnNQILLuDxq5zNc9hl5CqNljNK/Wwa9XcYoj8nHqwmudqN8D31u7SO8jselPEDqtGo2kCUEXqDePxeLcVa7FYwp39gqjDyuPxlEv1L5Hj8XjW+GHl8YZJ/LDyeMMkflh5vGESP6w83jCJH1Yeb5jEDyuPN0zih5XHGybxw8rjDZP+D22LbU2OsyF0AAAAAElFTkSuQmCC\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 create a copy as not to alter the original x\n",
|
|
" # outside this function.\n",
|
|
" #\n",
|
|
" # NOTE: The copying in this function is the heaviest operation.\n",
|
|
" # Reducing this overhead would be great, but I am not familiar\n",
|
|
" # enough with references/pointers in Python.\n",
|
|
" copy_x = np.copy(x)\n",
|
|
" copy_x[i] = next_position\n",
|
|
" return disk_config_valid(copy_x, L)"
|
|
]
|
|
},
|
|
{
|
|
"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, 5106 were taken (51.1%).\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
|
|
}
|