{"id":361,"date":"2015-07-28T12:12:20","date_gmt":"2015-07-28T12:12:20","guid":{"rendered":"http:\/\/drsfenner.org\/blog\/?p=361"},"modified":"2016-02-05T16:24:36","modified_gmt":"2016-02-05T16:24:36","slug":"game-of-life-in-numpy-preliminaries-2","status":"publish","type":"post","link":"https:\/\/drsfenner.org\/blog\/2015\/07\/game-of-life-in-numpy-preliminaries-2\/","title":{"rendered":"Game of Life in NumPy (Preliminaries)"},"content":{"rendered":"<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>You might be familiar with <a href=\"http:\/\/en.wikipedia.org\/wiki\/Conway%27s_Game_of_Life\">Conway&#8217;s Game of Life<\/a>. It is a simple game based on the idea of modeling a dynamic system progressing over time. We progress from discrete time points <span class=\"math\">\\(t_i \\rightarrow t_i+1\\)<\/span> and apply very simple rules at each time point. The game progresses on a square grid of discrete points. Each cell on the grid has eight neighbors (the four cardinal directions, plus diagonals). The progression to the next time interval is given by the following:<\/p>\n<ul>\n<li>If I&#8217;m alive and I have fewer than two alive neighors, I die of loneliness.<\/li>\n<li>If I&#8217;m alive and I have two or three alive neighbors, I live.<\/li>\n<li>If I&#8217;m alive and I have more than three alive neighbors, I die of starvation.<\/li>\n<li>If I&#8217;m dead and I have three (exactly) live neighbors, I become alive by spontaneous combustion.<\/li>\n<\/ul>\n<p>Typically, these rules are applied by loops and conditionals. I want to show-off a lesser known corner of NumPy by looking at <code>as_strided<\/code> from NumPy&#8217;s dark corner of <code>stride_tricks<\/code>. We&#8217;ll get to know <code>as_strided<\/code> today and, in a future post, we&#8217;ll play the game of life using stride tricks &#8211; woot!<!--more--><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<h3 id=\"Introducing-Array-Strides\">Introducing Array Strides<a class=\"anchor-link\" href=\"#Introducing-Array-Strides\">&#182;<\/a><\/h3>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Before we get to anything fancy, we should review the role of strides in NumPy. Memory for all the elements in a NumPy array are layed out as one long contiguous block of (linear) memory. We use clever tricks to give this linear block of memory the structure we need to deal with rows and columns (or more dimensions). Consider the following:<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[1]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"kn\">import<\/span> <span class=\"nn\">numpy<\/span> <span class=\"kn\">as<\/span> <span class=\"nn\">np<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[2]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"n\">arr_1d<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mi\">12<\/span><span class=\"p\">)<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">arr_1d<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_subarea output_stream output_stdout output_text\">\n<pre>\r\n[ 0  1  2  3  4  5  6  7  8  9 10 11]\r\n\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[3]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"n\">arr_2d<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mi\">12<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">reshape<\/span><span class=\"p\">(<\/span><span class=\"mi\">3<\/span><span class=\"p\">,<\/span><span class=\"mi\">4<\/span><span class=\"p\">)<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">arr_2d<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_subarea output_stream output_stdout output_text\">\n<pre>\r\n[[ 0  1  2  3]\r\n [ 4  5  6  7]\r\n [ 8  9 10 11]]\r\n\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Both of these arrays have exactly the same elements. Perhaps surprisingly, the elements can be &#8211; and are! &#8211; stored in the exactly same flat sequence of values. The following gives us a look at that.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[4]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"k\">print<\/span> <span class=\"n\">arr_1d<\/span><span class=\"o\">.<\/span><span class=\"n\">flatten<\/span><span class=\"p\">()<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">arr_2d<\/span><span class=\"o\">.<\/span><span class=\"n\">flatten<\/span><span class=\"p\">()<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_subarea output_stream output_stdout output_text\">\n<pre>\r\n[ 0  1  2  3  4  5  6  7  8  9 10 11]\r\n[ 0  1  2  3  4  5  6  7  8  9 10 11]\r\n\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>It turns out that the <em>real<\/em> difference between the two arrays is not how they are stored in memory, but what we <em>do<\/em> with that flat block of data. And that is determined by the <code>shape<\/code> of the array.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[5]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"k\">print<\/span> <span class=\"n\">arr_1d<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">arr_2d<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_subarea output_stream output_stdout output_text\">\n<pre>\r\n(12,)\r\n(3, 4)\r\n\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Let&#8217;s look at the size of the 2-D array. The value of 4 tells us that the inner most dimension (it&#8217;s the last thing in the shape) has four elements in it. This has an interesting side-effect: it determines the step sized need for the outer dimension. To get from outer dimension 0 (the first visual row) to outer dimension 1 (the second visual row), we have to walk across the 4 elements of the inner dimension.<\/p>\n<p>We can apply this to give a formula to go from an multi-dimensional index <code>arr_2d[1,2]<\/code> to the specific element we need in the flat data as it really exists in memory <span class=\"math\">\\([1,2]{\\rightarrow}1*4+2\\)<\/span> More generally, that is <span class=\"math\">\\([row,col]{\\rightarrow}(row*rowSize)+col\\)<\/span> or perhaps <span class=\"math\">\\([1,2]{\\rightarrow}(row*numCols)+col\\)<\/span>. The same sort of reasoning applies as we add more dimensions. Here, <span class=\"math\">\\(rowSize\\)<\/span> (or, equivalently, <span class=\"math\">\\(numCols\\)<\/span>) determines the &quot;number of steps&quot; or the <em>stride<\/em> size (in the flat array) for the outer dimension. We can look at these explicitly:<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[6]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"k\">print<\/span> <span class=\"n\">arr_1d<\/span><span class=\"o\">.<\/span><span class=\"n\">strides<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">arr_2d<\/span><span class=\"o\">.<\/span><span class=\"n\">strides<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_subarea output_stream output_stdout output_text\">\n<pre>\r\n(8,)\r\n(32, 8)\r\n\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Whoa! Those aren&#8217;t at all what I led you to expect.<\/p>\n<p>One other factoid: we&#8217;re looking at the lower levels (inner workings and implementation details) of the NumPy library. This means we have to start worrying about the machine representations of our data. Our arrays have <code>dtype=np.int_<\/code> which is 64 bits per <code>int<\/code> on modern 64-bit CPUs (aka, <code>np.int64<\/code>). So, moving forward one data entry means moving forward 64 bits which is equivalent to 8 bytes. Dividing those values given by <code>arr.strides<\/code> by 8 gives us &quot;element strides&quot; (as opposed to the &quot;memory strides&quot; we&#8217;ll be working with) of <code>(1,)<\/code> for arr_1d and of <code>(4,1)<\/code> for arr_2d. We can rewrite <span class=\"math\">\\([1,2]{\\rightarrow}1*4+2\\)<\/span> as <span class=\"math\">\\([1,2]{\\rightarrow}1*\\color{red}{4}+2*\\color{red}{1}\\)<\/span> and the &quot;coefficient&quot; on the indices are now <span class=\"math\">\\(\\color{red}{(4,1)}\\)<\/span> which is the same as our &quot;element strides&quot;.<\/p>\n<p>In the remainder of this post, we will be working with the proper &quot;memory strides&quot;, not these slightly more convenient &quot;element strides&quot;.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<h3 id=\"Introducing-as_strided\">Introducing <code>as_strided<\/code><a class=\"anchor-link\" href=\"#Introducing-as_strided\">&#182;<\/a><\/h3>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[7]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"kn\">from<\/span> <span class=\"nn\">numpy.lib.stride_tricks<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">as_strided<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>We can use <code>as_strided<\/code> to customize the way we walk across an array. That is, we can specify strides other than those implied by the shape of the array. Because of the flexibility in specifying the strides, we also have to tell NumPy what the resulting output shape will be. Let&#8217;s revisit the 1-D array:<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[8]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"k\">print<\/span> <span class=\"n\">arr_1d<\/span>\r\n<span class=\"n\">shapeShifted<\/span> <span class=\"o\">=<\/span> <span class=\"n\">as_strided<\/span><span class=\"p\">(<\/span><span class=\"n\">arr_1d<\/span><span class=\"p\">,<\/span>            <span class=\"c\"># array to monkey with<\/span>\r\n                          <span class=\"n\">strides<\/span><span class=\"o\">=<\/span><span class=\"p\">(<\/span><span class=\"mi\">4<\/span><span class=\"o\">*<\/span><span class=\"mi\">8<\/span><span class=\"p\">,<\/span><span class=\"mi\">1<\/span><span class=\"o\">*<\/span><span class=\"mi\">8<\/span><span class=\"p\">),<\/span> <span class=\"c\"># custom step sizes<\/span>\r\n                          <span class=\"n\">shape<\/span><span class=\"o\">=<\/span><span class=\"p\">(<\/span><span class=\"mi\">3<\/span><span class=\"p\">,<\/span><span class=\"mi\">4<\/span><span class=\"p\">))<\/span>       <span class=\"c\"># output shape<\/span>\r\n\r\n<span class=\"k\">print<\/span> <span class=\"n\">shapeShifted<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_subarea output_stream output_stdout output_text\">\n<pre>\r\n[ 0  1  2  3  4  5  6  7  8  9 10 11]\r\n[[ 0  1  2  3]\r\n [ 4  5  6  7]\r\n [ 8  9 10 11]]\r\n\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>To recap, we told NumPy to walk across <code>arr_1d<\/code> using steps of 1 element on the inner-most axis (walking across the visual rows) and steps of 4 elements to kick off a new row.<\/p>\n<p>We can pull some other neat tricks. For example, look at what happens if we never &quot;start a new row&quot; (i.e., our outer stride is 0).<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[9]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"k\">print<\/span> <span class=\"n\">arr_1d<\/span><span class=\"o\">.<\/span><span class=\"n\">itemsize<\/span> <span class=\"c\"># number of bytes per element (aka, 8)<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">arr_1d<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\r\n<span class=\"n\">duplicated<\/span> <span class=\"o\">=<\/span> <span class=\"n\">as_strided<\/span><span class=\"p\">(<\/span><span class=\"n\">arr_1d<\/span><span class=\"p\">,<\/span> \r\n                        <span class=\"n\">strides<\/span><span class=\"o\">=<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">1<\/span><span class=\"o\">*<\/span><span class=\"n\">arr_1d<\/span><span class=\"o\">.<\/span><span class=\"n\">itemsize<\/span><span class=\"p\">),<\/span> \r\n                        <span class=\"n\">shape<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span><span class=\"n\">arr_1d<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]))<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">duplicated<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_subarea output_stream output_stdout output_text\">\n<pre>\r\n8\r\n12\r\n[[ 0  1  2  3  4  5  6  7  8  9 10 11]\r\n [ 0  1  2  3  4  5  6  7  8  9 10 11]]\r\n\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Really? This is exactly the sort of replication that happens in broadcasting. How did that output array get filled in? Consider how we filled in <code>duplicated[0,5]<\/code>. To fill in item <code>[0,5]<\/code> we have to take stride length for the outer dimension times the index of the outer dimension (<span class=\"math\">\\(0\\cdot0=0\\)<\/span>). We then have to take the stride length for the inner dimension times the index of the inner dimension (<span class=\"math\">\\(8\\cdot5=40\\)<\/span>). Adding the two gives us a flat offset of <code>40<\/code> (from <span class=\"math\">\\(0\\cdot0+8\\cdot5\\)<\/span>. When we try to fill in the second row of <code>duplicated<\/code>, we do something similar. For <code>duplicated[1,5]<\/code> the values are: <span class=\"math\">\\(0\\cdot1 + 8\\cdot5=40\\)<\/span> (note, the 0 is the same in both computations because are stride for the outer dimension is 0).<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>We can do something analogous to the other axis and broadcast column-wise, instead of row-wise. We use both styles (outer\/column and inner\/row) if we want to compute an outer product.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[10]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"n\">arr1<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"mi\">5<\/span><span class=\"p\">)<\/span>\r\n<span class=\"n\">arr2<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mi\">5<\/span><span class=\"p\">,<\/span><span class=\"mi\">8<\/span><span class=\"p\">)<\/span>\r\n\r\n<span class=\"n\">outerProdShape<\/span> <span class=\"o\">=<\/span> <span class=\"n\">arr1<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span> <span class=\"o\">+<\/span> <span class=\"n\">arr2<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span>\r\n\r\n<span class=\"n\">x<\/span> <span class=\"o\">=<\/span> <span class=\"n\">as_strided<\/span><span class=\"p\">(<\/span><span class=\"n\">arr1<\/span><span class=\"p\">,<\/span> \r\n               <span class=\"n\">strides<\/span><span class=\"o\">=<\/span><span class=\"p\">(<\/span><span class=\"n\">arr1<\/span><span class=\"o\">.<\/span><span class=\"n\">itemsize<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">),<\/span> \r\n               <span class=\"n\">shape<\/span><span class=\"o\">=<\/span><span class=\"n\">outerProdShape<\/span><span class=\"p\">)<\/span> <span class=\"c\"># copy oPS[0] times (arr2 shape)<\/span>\r\n<span class=\"n\">y<\/span> <span class=\"o\">=<\/span> <span class=\"n\">as_strided<\/span><span class=\"p\">(<\/span><span class=\"n\">arr2<\/span><span class=\"p\">,<\/span> \r\n               <span class=\"n\">strides<\/span><span class=\"o\">=<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"n\">arr2<\/span><span class=\"o\">.<\/span><span class=\"n\">itemsize<\/span><span class=\"p\">),<\/span> \r\n               <span class=\"n\">shape<\/span><span class=\"o\">=<\/span><span class=\"n\">outerProdShape<\/span><span class=\"p\">)<\/span> <span class=\"c\"># copy oPS[1] times (arr1 shape)<\/span>\r\n\r\n<span class=\"k\">print<\/span> <span class=\"s\">&quot;x:&quot;<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">x<\/span>\r\n\r\n<span class=\"k\">print<\/span> <span class=\"s\">&quot;y:&quot;<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">y<\/span>\r\n\r\n<span class=\"k\">print<\/span> <span class=\"s\">&quot;x*y:&quot;<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">x<\/span> <span class=\"o\">*<\/span> <span class=\"n\">y<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_subarea output_stream output_stdout output_text\">\n<pre>\r\nx:\r\n[[1 1 1]\r\n [2 2 2]\r\n [3 3 3]\r\n [4 4 4]]\r\ny:\r\n[[5 6 7]\r\n [5 6 7]\r\n [5 6 7]\r\n [5 6 7]]\r\nx*y:\r\n[[ 5  6  7]\r\n [10 12 14]\r\n [15 18 21]\r\n [20 24 28]]\r\n\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>This is the same answer that we get using NumPy&#8217;s built-in <code>outer<\/code> function:<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[11]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"k\">print<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">outer<\/span><span class=\"p\">(<\/span><span class=\"n\">arr1<\/span><span class=\"p\">,<\/span> <span class=\"n\">arr2<\/span><span class=\"p\">)<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_subarea output_stream output_stdout output_text\">\n<pre>\r\n[[ 5  6  7]\r\n [10 12 14]\r\n [15 18 21]\r\n [20 24 28]]\r\n\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>You might know that we can do some outer product like tasks with broadcasting by judicious use of a new axis (<code>np.newaxis<\/code>). Here&#8217;s an example:<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[12]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"k\">print<\/span> <span class=\"n\">arr1<\/span><span class=\"p\">[:,<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">newaxis<\/span><span class=\"p\">]<\/span> <span class=\"o\">*<\/span> <span class=\"n\">arr2<\/span><span class=\"p\">[<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">newaxis<\/span><span class=\"p\">,:]<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_subarea output_stream output_stdout output_text\">\n<pre>\r\n[[ 5  6  7]\r\n [10 12 14]\r\n [15 18 21]\r\n [20 24 28]]\r\n\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Indeed, it gives the same answer!<\/p>\n<p>Now, compare <code>arr1[:, np.newaxis]<\/code> with the custom strides we applied to <code>arr1<\/code>: <code>strides<\/code> took the value <code>(arr1.itemsize, 0)<\/code>. On the inner dimension, the <code>np.newaxis<\/code> performs the same task as the <code>0<\/code> stride size. No kidding!<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<h3 id=\"Neighborhoods\">Neighborhoods<a class=\"anchor-link\" href=\"#Neighborhoods\">&#182;<\/a><\/h3>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Let&#8217;s see how we can apply these tricks to pick out sub-arrays.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[13]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"n\">board<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mi\">16<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">reshape<\/span><span class=\"p\">((<\/span><span class=\"mi\">4<\/span><span class=\"p\">,<\/span><span class=\"mi\">4<\/span><span class=\"p\">))<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">board<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">board<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_subarea output_stream output_stdout output_text\">\n<pre>\r\n[[ 0  1  2  3]\r\n [ 4  5  6  7]\r\n [ 8  9 10 11]\r\n [12 13 14 15]]\r\n(4, 4)\r\n\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>We want to pick out the four &quot;complete&quot; neighborhoods centered around 5, 6, 7, and 8. Let&#8217;s look at the neighborhood for 5. What is the shape of the result? 3&#215;3. What are the strides? Well, to walk across a row is still just walking one element at a time and to get to the next row is still 4 elements at a time. These are <em>the same<\/em> as the strides in the original. The difference is we don&#8217;t take &quot;everything&quot;, we just take a selection. Let&#8217;s see if that actually works:<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[14]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"n\">neighbors<\/span> <span class=\"o\">=<\/span> <span class=\"n\">as_strided<\/span><span class=\"p\">(<\/span><span class=\"n\">board<\/span><span class=\"p\">,<\/span> <span class=\"n\">shape<\/span><span class=\"o\">=<\/span><span class=\"p\">(<\/span><span class=\"mi\">3<\/span><span class=\"p\">,<\/span><span class=\"mi\">3<\/span><span class=\"p\">),<\/span> <span class=\"n\">strides<\/span><span class=\"o\">=<\/span><span class=\"n\">board<\/span><span class=\"o\">.<\/span><span class=\"n\">strides<\/span><span class=\"p\">)<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">neighbors<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_subarea output_stream output_stdout output_text\">\n<pre>\r\n[[ 0  1  2]\r\n [ 4  5  6]\r\n [ 8  9 10]]\r\n\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Ok, nice. Now, if we want all four neighborhoods, what is the output shape? We have several 3&#215;3 results. How many? In this case, we have 2&#215;2 of them (for each of the &quot;center&quot; cells). This gives a shape of (2,2,3,3) &#8211; the neighborhoods are the inner dimensions and the organization of the neighborhoods is the outer dimensions.<\/p>\n<p>We know how to get one neighborhood out. That moves us across the inner two dimensions. Now we need to figure out how to get from one neighborhood to the next. Once we have the complete neighborhood for 5, we want to start the neighborhood for 6. It&#8217;s top-left neighbor is the number 1 &#8211; but this is just one element beyond where we started for the previous neighborhood (which means our stride is one element). And we can keep doing that the whole way across the board (we&#8217;ll stop based on the output shape).<\/p>\n<p>After we&#8217;ve walked across the board (neighborhood by neighborhood), how do we get to the next row? There are two ways to look at it. The first is by comparing the neighborhood for 5 to the neighborhood for 9. They differ by one row. So, our stride is four elements (the number of elements per row). The other way to think about this is where we are at after we walked the neighborhoods across the previous row. We will have gone through all the neighborhoods (inner most dimensions) and the first of the outer two dimensions. We now need to move forward one row &#8211; which again, is four elements. I prefer the first explanation!<\/p>\n<p>So, our strides (in terms of elements) end up being (4,0) within one neighborhood and (4,0) for progressing neighborhood to neighborhood. The total stride (element wise) is: (4,0,4,0). But, the component strides (our outer two dimensions) are the <em>same<\/em> as the strides of the board. This means that our neighborhood strides are <code>board.strides + board.strides<\/code>.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[15]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"k\">print<\/span> <span class=\"n\">board<\/span><span class=\"o\">.<\/span><span class=\"n\">strides<\/span> <span class=\"o\">+<\/span> <span class=\"n\">board<\/span><span class=\"o\">.<\/span><span class=\"n\">strides<\/span>\r\n\r\n<span class=\"n\">neighborhoods<\/span> <span class=\"o\">=<\/span> <span class=\"n\">as_strided<\/span><span class=\"p\">(<\/span><span class=\"n\">board<\/span><span class=\"p\">,<\/span> \r\n                           <span class=\"n\">shape<\/span><span class=\"o\">=<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span><span class=\"mi\">3<\/span><span class=\"p\">,<\/span><span class=\"mi\">3<\/span><span class=\"p\">),<\/span> \r\n                           <span class=\"n\">strides<\/span><span class=\"o\">=<\/span><span class=\"n\">board<\/span><span class=\"o\">.<\/span><span class=\"n\">strides<\/span><span class=\"o\">+<\/span><span class=\"n\">board<\/span><span class=\"o\">.<\/span><span class=\"n\">strides<\/span><span class=\"p\">)<\/span>\r\n\r\n<span class=\"k\">print<\/span> <span class=\"n\">neighborhoods<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">neighborhoods<\/span><span class=\"p\">[<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_subarea output_stream output_stdout output_text\">\n<pre>\r\n(32, 8, 32, 8)\r\n[[ 0  1  2]\r\n [ 4  5  6]\r\n [ 8  9 10]]\r\n[[ 5  6  7]\r\n [ 9 10 11]\r\n [13 14 15]]\r\n\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<h3 id=\"Generalizing\">Generalizing<a class=\"anchor-link\" href=\"#Generalizing\">&#182;<\/a><\/h3>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>We can generalize this a bit to work for more dimensions. For example, we could compute the neighbors in 3-D space or in 4-D space.<\/p>\n<p>The key points are that: (1) taking the neighborhood has the same <em>number<\/em> of dimensions as the input, (2) the number of neighborhoods is the length of the axis minus 2 (we don&#8217;t use the first or last elements on an axis as a neighborhood center), and (3) the new strides are just the original strides concatenated to the original strides.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[&nbsp;]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"k\">def<\/span> <span class=\"nf\">grid_nD<\/span><span class=\"p\">(<\/span><span class=\"n\">arr<\/span><span class=\"p\">):<\/span>\r\n    <span class=\"k\">assert<\/span> <span class=\"nb\">all<\/span><span class=\"p\">(<\/span><span class=\"n\">_len<\/span><span class=\"o\">&gt;<\/span><span class=\"mi\">2<\/span> <span class=\"k\">for<\/span> <span class=\"n\">_len<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">arr<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span><span class=\"p\">)<\/span>\r\n    \r\n    <span class=\"n\">nDims<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">arr<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"n\">newShape<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"n\">_len<\/span><span class=\"o\">-<\/span><span class=\"mi\">2<\/span> <span class=\"k\">for<\/span> <span class=\"n\">_len<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">arr<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span><span class=\"p\">]<\/span>\r\n    <span class=\"n\">newShape<\/span><span class=\"o\">.<\/span><span class=\"n\">extend<\/span><span class=\"p\">([<\/span><span class=\"mi\">3<\/span><span class=\"p\">]<\/span> <span class=\"o\">*<\/span> <span class=\"n\">nDims<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">print<\/span> <span class=\"s\">&quot;shape:&quot;<\/span><span class=\"p\">,<\/span> <span class=\"n\">newShape<\/span>\r\n    \r\n    <span class=\"n\">newStrides<\/span> <span class=\"o\">=<\/span> <span class=\"n\">arr<\/span><span class=\"o\">.<\/span><span class=\"n\">strides<\/span> <span class=\"o\">+<\/span> <span class=\"n\">arr<\/span><span class=\"o\">.<\/span><span class=\"n\">strides<\/span>\r\n    <span class=\"k\">print<\/span> <span class=\"s\">&quot;stride:&quot;<\/span><span class=\"p\">,<\/span> <span class=\"n\">newStrides<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"n\">as_strided<\/span><span class=\"p\">(<\/span><span class=\"n\">arr<\/span><span class=\"p\">,<\/span> <span class=\"n\">shape<\/span><span class=\"o\">=<\/span><span class=\"n\">newShape<\/span><span class=\"p\">,<\/span> <span class=\"n\">strides<\/span><span class=\"o\">=<\/span><span class=\"n\">newStrides<\/span><span class=\"p\">)<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Let&#8217;s test that on a 2D grid, since we&#8217;re pretty familiar with that case already.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[16]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"n\">x<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mi\">25<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">reshape<\/span><span class=\"p\">((<\/span><span class=\"mi\">5<\/span><span class=\"p\">,<\/span><span class=\"mi\">5<\/span><span class=\"p\">))<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">x<\/span>\r\n<span class=\"n\">neighborhoods<\/span> <span class=\"o\">=<\/span> <span class=\"n\">grid_nD<\/span><span class=\"p\">(<\/span><span class=\"n\">x<\/span><span class=\"p\">)<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">neighborhoods<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">neighborhoods<\/span><span class=\"p\">[<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_subarea output_stream output_stdout output_text\">\n<pre>\r\n[[ 0  1  2  3  4]\r\n [ 5  6  7  8  9]\r\n [10 11 12 13 14]\r\n [15 16 17 18 19]\r\n [20 21 22 23 24]]\r\nshape: [3, 3, 3, 3]\r\nstride: (40, 8, 40, 8)\r\n[[ 0  1  2]\r\n [ 5  6  7]\r\n [10 11 12]]\r\n[[12 13 14]\r\n [17 18 19]\r\n [22 23 24]]\r\n\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>And now let&#8217;s see how it works on a 3D grid. Here, we&#8217;ll use 64 total grid points, but write it as <span class=\"math\">\\(4*4*4\\)<\/span> to emphasize the similarity between the size of the dimensions and this cube-shaped grid.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[17]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"n\">x<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mi\">4<\/span><span class=\"o\">*<\/span><span class=\"mi\">4<\/span><span class=\"o\">*<\/span><span class=\"mi\">4<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">reshape<\/span><span class=\"p\">((<\/span><span class=\"mi\">4<\/span><span class=\"p\">,<\/span><span class=\"mi\">4<\/span><span class=\"p\">,<\/span><span class=\"mi\">4<\/span><span class=\"p\">))<\/span>\r\n<span class=\"n\">neighborhoods<\/span> <span class=\"o\">=<\/span> <span class=\"n\">grid_nD<\/span><span class=\"p\">(<\/span><span class=\"n\">x<\/span><span class=\"p\">)<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">neighborhoods<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">neighborhoods<\/span><span class=\"p\">[<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_subarea output_stream output_stdout output_text\">\n<pre>\r\nshape: [2, 2, 2, 3, 3, 3]\r\nstride: (128, 32, 8, 128, 32, 8)\r\n[[[ 0  1  2]\r\n  [ 4  5  6]\r\n  [ 8  9 10]]\r\n\r\n [[16 17 18]\r\n  [20 21 22]\r\n  [24 25 26]]\r\n\r\n [[32 33 34]\r\n  [36 37 38]\r\n  [40 41 42]]]\r\n[[[21 22 23]\r\n  [25 26 27]\r\n  [29 30 31]]\r\n\r\n [[37 38 39]\r\n  [41 42 43]\r\n  [45 46 47]]\r\n\r\n [[53 54 55]\r\n  [57 58 59]\r\n  [61 62 63]]]\r\n\r\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<h3 id=\"References-for-this-Material\">References for this Material<a class=\"anchor-link\" href=\"#References-for-this-Material\">&#182;<\/a><\/h3>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>I made varying use of the following material to put this together:<\/p>\n<ul>\n<li>http:\/\/scipy-lectures.github.io\/advanced\/advanced_numpy\/#indexing-scheme-strides<\/li>\n<li>http:\/\/chintaksheth.wordpress.com\/2013\/07\/31\/numpy-the-tricks-of-the-trade-part-ii\/<\/li>\n<li>http:\/\/wiki.scipy.org\/Cookbook\/GameOfLifeStrides<\/li>\n<li>http:\/\/www.rigtorp.se\/2011\/01\/01\/rolling-statistics-numpy.html<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<h3>\nAdditional Resources<br \/>\n<\/h3>\n<p>\nYou can grab a <a href=\"http:\/\/drsfenner.org\/public\/notebooks\/GameOfLifePrelims.ipynb\">copy of this notebook<\/a>.\n<\/p>\n<p>\nEven better, you can <a href=\"http:\/\/nbviewer.ipython.org\/url\/drsfenner.org\/public\/notebooks\/GameOfLifePrelims.ipynb\">view it using nbviewer<\/a>.\n<\/p>\n<h3>\nLicense<br \/>\n<\/h3>\n<p>\nUnless otherwise noted, the contents of this notebook are under the following license. The code in the notebook should be considered part of the text (i.e., licensed and treated as as follows).\n<\/p>\n<p><a rel=\"license\" href=\"http:\/\/creativecommons.org\/licenses\/by-nc-sa\/4.0\/\"><img decoding=\"async\" alt=\"Creative Commons License\" style=\"border-width:0\" src=\"https:\/\/i.creativecommons.org\/l\/by-nc-sa\/4.0\/88x31.png\" \/><\/a><br \/><span xmlns:dct=\"http:\/\/purl.org\/dc\/terms\/\" property=\"dct:title\">DrsFenner.org Blog And Notebooks<\/span> by <a xmlns:cc=\"http:\/\/creativecommons.org\/ns#\" href=\"drsfenner.org\" property=\"cc:attributionName\" rel=\"cc:attributionURL\">Mark and Barbara Fenner<\/a> is licensed under a <a rel=\"license\" href=\"http:\/\/creativecommons.org\/licenses\/by-nc-sa\/4.0\/\">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License<\/a>.<br \/>Permissions beyond the scope of this license may be available at <a xmlns:cc=\"http:\/\/creativecommons.org\/ns#\" href=\"drsfenner.org\/blog\/about-and-contacts\" rel=\"cc:morePermissions\">drsfenner.org\/blog\/about-and-contacts<\/a>.<\/p>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>You might be familiar with Conway&#8217;s Game of Life. It is a simple game based on the idea of modeling a dynamic system progressing over time. We progress from discrete time points \\(t_i \\rightarrow t_i+1\\) and apply very simple rules at each time point. The game progresses on a square grid of discrete points. Each [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,7],"tags":[],"class_list":["post-361","post","type-post","status-publish","format-standard","hentry","category-mrdr","category-sci-math-stat-python"],"_links":{"self":[{"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/posts\/361","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/comments?post=361"}],"version-history":[{"count":2,"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/posts\/361\/revisions"}],"predecessor-version":[{"id":422,"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/posts\/361\/revisions\/422"}],"wp:attachment":[{"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/media?parent=361"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/categories?post=361"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/tags?post=361"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}