|
236 | 236 | "cell_type": "markdown", |
237 | 237 | "metadata": {}, |
238 | 238 | "source": [ |
239 | | - "This implementation is scalar, which is slow for large values of N. Thankfully, Devito gives us a simple way of implementing this using vectorization. Read on!" |
| 239 | + "A random walk with $N$ steps, starting at $x_0$, where we move\n", |
| 240 | + "to the left with probability $p$ and to the right\n", |
| 241 | + "with probability $1-p$ can now be implemented by" |
| 242 | + ] |
| 243 | + }, |
| 244 | + { |
| 245 | + "cell_type": "code", |
| 246 | + "execution_count": 303, |
| 247 | + "metadata": {}, |
| 248 | + "outputs": [], |
| 249 | + "source": [ |
| 250 | + "import random, numpy as np\n", |
| 251 | + "\n", |
| 252 | + "def random_walk1D(x0, N, p, random=random):\n", |
| 253 | + " \"\"\"1D random walk with 1 particle.\"\"\"\n", |
| 254 | + " # Store position in step k in position[k]\n", |
| 255 | + " position = np.zeros(N)\n", |
| 256 | + " position[0] = x0\n", |
| 257 | + " current_pos = x0\n", |
| 258 | + " for k in range(N-1):\n", |
| 259 | + " r = random.uniform(0, 1)\n", |
| 260 | + " if r <= p:\n", |
| 261 | + " current_pos -= 1\n", |
| 262 | + " else:\n", |
| 263 | + " current_pos += 1\n", |
| 264 | + " position[k+1] = current_pos\n", |
| 265 | + " return position" |
240 | 266 | ] |
241 | 267 | }, |
242 | 268 | { |
243 | 269 | "cell_type": "markdown", |
244 | 270 | "metadata": {}, |
245 | 271 | "source": [ |
| 272 | + "\n", |
246 | 273 | "Since $N$ is supposed to be large and we want to repeat the process for\n", |
247 | 274 | "many particles, we should speed up the code as much as possible.\n", |
248 | 275 | "Vectorization is the obvious technique here: we draw all the random\n", |
|
260 | 287 | }, |
261 | 288 | { |
262 | 289 | "cell_type": "code", |
263 | | - "execution_count": 4, |
| 290 | + "execution_count": 295, |
264 | 291 | "metadata": {}, |
265 | 292 | "outputs": [], |
266 | 293 | "source": [ |
267 | | - "import random, numpy as np\n", |
268 | | - "\n", |
269 | 294 | "N=200\n", |
270 | 295 | "p=50\n", |
271 | 296 | "r = np.random.uniform(0, 1, size=N)\n", |
|
276 | 301 | "cell_type": "markdown", |
277 | 302 | "metadata": {}, |
278 | 303 | "source": [ |
279 | | - "A random walk with $N$ steps, starting at $x_0$, where we move\n", |
280 | | - "to the left with probability $p$ and to the right\n", |
281 | | - "with probability $1-p$ can now be implemented by" |
| 304 | + "Our vectorized implementation using Devito is as follows:" |
282 | 305 | ] |
283 | 306 | }, |
284 | 307 | { |
285 | 308 | "cell_type": "code", |
286 | | - "execution_count": 5, |
| 309 | + "execution_count": 296, |
287 | 310 | "metadata": {}, |
288 | 311 | "outputs": [], |
289 | 312 | "source": [ |
|
292 | 315 | }, |
293 | 316 | { |
294 | 317 | "cell_type": "code", |
295 | | - "execution_count": 64, |
| 318 | + "execution_count": 304, |
296 | 319 | "metadata": {}, |
297 | 320 | "outputs": [], |
298 | 321 | "source": [ |
299 | | - "def random_walk1D(x0, N, p, random=random):\n", |
| 322 | + "def random_walk1D_vec(x0, N, p, random=random):\n", |
300 | 323 | " \"\"\"1D random walk with 1 particle.\"\"\"\n", |
301 | | - " # Create and initialise r\n", |
| 324 | + " # Create and initialise r with dimension x_d\n", |
302 | 325 | " x_d = Dimension(name='x_d', spacing=Constant('h_x'))\n", |
303 | 326 | " r = TimeFunction(name='r', dimensions=(x_d,), shape=(N+1,))\n", |
304 | 327 | " r.data[0] = x0\n", |
|
329 | 352 | }, |
330 | 353 | { |
331 | 354 | "cell_type": "code", |
332 | | - "execution_count": 5, |
| 355 | + "execution_count": 259, |
333 | 356 | "metadata": {}, |
334 | 357 | "outputs": [], |
335 | 358 | "source": [ |
|
648 | 671 | }, |
649 | 672 | { |
650 | 673 | "cell_type": "code", |
651 | | - "execution_count": 216, |
| 674 | + "execution_count": 283, |
652 | 675 | "metadata": {}, |
653 | 676 | "outputs": [], |
654 | 677 | "source": [ |
|
731 | 754 | }, |
732 | 755 | { |
733 | 756 | "cell_type": "code", |
734 | | - "execution_count": 39, |
| 757 | + "execution_count": 297, |
735 | 758 | "metadata": {}, |
736 | 759 | "outputs": [], |
737 | 760 | "source": [ |
|
740 | 763 | " # produce the same result\n", |
741 | 764 | " x0 = 0; N = 4; p = 0.5\n", |
742 | 765 | "\n", |
743 | | - " # First, check that random_walks1D for 1 walk reproduces\n", |
| 766 | + " # Check that random_walks1D for 1 walk reproduces\n", |
744 | 767 | " # the walk in random_walk1D\n", |
745 | 768 | " num_walks = 1\n", |
746 | 769 | " np.random.seed(10)\n", |
747 | 770 | " computed = random_walks1D(\n", |
748 | 771 | " x0, N, p, num_walks, random=np.random)\n", |
749 | 772 | " np.random.seed(10)\n", |
750 | | - " expected = random_walk1D(\n", |
| 773 | + " expected = random_walk1D_vec(\n", |
751 | 774 | " x0, N, p, random=np.random)\n", |
752 | 775 | " print(\"Computed: \", computed[0])\n", |
753 | 776 | " print(\"Expected: \", expected)\n", |
|
756 | 779 | }, |
757 | 780 | { |
758 | 781 | "cell_type": "code", |
759 | | - "execution_count": 40, |
| 782 | + "execution_count": 298, |
760 | 783 | "metadata": {}, |
761 | 784 | "outputs": [ |
762 | 785 | { |
|
857 | 880 | }, |
858 | 881 | { |
859 | 882 | "cell_type": "code", |
860 | | - "execution_count": 43, |
| 883 | + "execution_count": 239, |
861 | 884 | "metadata": {}, |
862 | 885 | "outputs": [], |
863 | 886 | "source": [ |
|
1061 | 1084 | }, |
1062 | 1085 | { |
1063 | 1086 | "cell_type": "code", |
1064 | | - "execution_count": 211, |
| 1087 | + "execution_count": 299, |
1065 | 1088 | "metadata": {}, |
1066 | 1089 | "outputs": [], |
1067 | 1090 | "source": [ |
|
1121 | 1144 | }, |
1122 | 1145 | { |
1123 | 1146 | "cell_type": "code", |
1124 | | - "execution_count": 212, |
| 1147 | + "execution_count": 301, |
1125 | 1148 | "metadata": {}, |
1126 | 1149 | "outputs": [], |
1127 | 1150 | "source": [ |
|
1152 | 1175 | }, |
1153 | 1176 | { |
1154 | 1177 | "cell_type": "code", |
1155 | | - "execution_count": 219, |
| 1178 | + "execution_count": 305, |
1156 | 1179 | "metadata": {}, |
1157 | 1180 | "outputs": [], |
1158 | 1181 | "source": [ |
|
1163 | 1186 | " x_d = Dimension(name='x_d', spacing=Constant('h_x'))\n", |
1164 | 1187 | " # Add space dimensions\n", |
1165 | 1188 | " d_d = Dimension(name='d', spacing=Constant('h_d'))\n", |
1166 | | - " r = TimeFunction(name='r', dimensions=(x_d,d_d), shape=(N+1,d))\n", |
| 1189 | + " r = TimeFunction(name='r', dimensions=(x_d, d_d), shape=(N+1, d))\n", |
1167 | 1190 | " r.data[0] = x0\n", |
1168 | 1191 | " \n", |
1169 | 1192 | " rs = random.uniform(0, 1, size=N*d).reshape(N,d)\n", |
1170 | | - " steps = Function(name='steps', dimensions=(x_d,d_d), shape=(N+1,d))\n", |
| 1193 | + " steps = Function(name='steps', dimensions=(x_d, d_d), shape=(N+1, d))\n", |
1171 | 1194 | " steps.data[:N] = np.where(rs <= p, -1, 1)\n", |
1172 | 1195 | " \n", |
1173 | 1196 | " # The next value is computed using the previous value and the steps function at that point\n", |
|
1198 | 1221 | }, |
1199 | 1222 | { |
1200 | 1223 | "cell_type": "code", |
1201 | | - "execution_count": 218, |
| 1224 | + "execution_count": 225, |
1202 | 1225 | "metadata": {}, |
1203 | 1226 | "outputs": [], |
1204 | 1227 | "source": [ |
|
0 commit comments