{"id":348,"date":"2015-04-17T13:43:33","date_gmt":"2015-04-17T13:43:33","guid":{"rendered":"http:\/\/drsfenner.org\/blog\/?p=348"},"modified":"2016-02-05T16:22:55","modified_gmt":"2016-02-05T16:22:55","slug":"sorting-friends-and-permutations-4","status":"publish","type":"post","link":"https:\/\/drsfenner.org\/blog\/2015\/04\/sorting-friends-and-permutations-4\/","title":{"rendered":"Sorting Friends and Permutations"},"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<h3 id=\"Introduction\">Introduction<a class=\"anchor-link\" href=\"#Introduction\">&#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>You may be familiar with permuations: a rearrangement of a sequence. If you are, you probably know that for a sequence of length <span class=\"math\">\\(n\\)<\/span>, there are <span class=\"math\">\\(n!\\)<\/span> arrangements (if the elements are all distinct &#8211; duplicates will reduce the number of unique rearrangements). There are many, many uses of permutations and many specific permutations of interest.<\/p>\n<p><!--more--><\/p>\n<p>The permutation I am interested in today is the sorted permutation: i.e., the one where the elements are in non-decreasing order. For any two arrangements (permutations) of a sequence, we can define a permutation function that maps the first sequence to the second sequence. In a few moments, I&#8217;m going to start referring to permutation-functions as permutations. It should be clear from context, but I&#8217;ll make a note if it is unclear. So, here&#8217;s an example. <span class=\"math\">\\(seq_1=[4,2]\\)<\/span> and <span class=\"math\">\\(seq_2=[2,4]\\)<\/span>. To mutate <span class=\"math\">\\(seq_1 \\rightarrow seq_2\\)<\/span>, we have to move some elements around. Namely, using 0-based sequence indexing: <span class=\"math\">\\(seq_1[0] \\rightarrow seq_1[1]\\)<\/span> and <span class=\"math\">\\(seq_1[1] \\rightarrow seq_1[0]\\)<\/span>. This can be expressed as a permuation-function (in terms of the sequence indices): <span class=\"math\">\\(\\begin{pmatrix}0 &amp; 1 \\\\ 1 &amp; 0\\end{pmatrix}\\)<\/span>. The top row represents the <em>source<\/em> indices and the bottom rows represents the <em>target<\/em> indices. Thus, the first column says, &quot;move item at position 0 to position 1&quot;. When we apply the entire permutation-function, we&#8217;re effectively doing <span class=\"math\">\\(seq_1[0] \\leftrightarrow seq_1[1]\\)<\/span> and this is a very common task in introductory algorithms. You may recognize it as a <em>swap<\/em> procedure that updates the underlying sequence: <em>swap(<\/em><span class=\"math\">\\(seq_1[0], seq_1[1]\\)<\/span><em>)<\/em>.<\/p>\n<p>I&#8217;m going to expand on these ideas and look at the relationship between permutation-functions, swapping, and sorting. Before we go down the rabbit hole, here&#8217;s a bit of motivation. Suppose, (1) you have a sequence which you sort using &quot;ordinary&quot; method and (2) you can easily extract the permutation-function that takes you from <span class=\"math\">\\(seq \\rightarrow sorted(seq)\\)<\/span>. Now, you have another data structure that needs to be modified (with the same permutation), and it only be modified by using pairwise swaps. If we can convert the permutation to a sequence of swaps, we can solve this problem nicely. That&#8217;s our goal. I&#8217;ll show a specific example where this arises at the end of the post (you might want to jump down to <a href=\"#The-Original-Motivation\">The Orginal Motivation<\/a> to see if this motivation works for you).<\/p>\n<p>One other note, an alternative to this use of permutations would be to perform the sorting on the primary data structure above and either (1) whenever that sort causes a swap (assuming an in-place sort) also perform an analogous swap in the secondary data structure or (2) extract a list of swaps and then apply them to the secondary data structure. We actually going to do something similar to (2), but we will extract the swaps needed to apply a permutation function.<\/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=\"A-Bit-more-on-Permutations\">A Bit more on Permutations<a class=\"anchor-link\" href=\"#A-Bit-more-on-Permutations\">&#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>Here&#8217;s another sequence and a permutation-function to sort it: <span class=\"math\">\\[\\begin{align}<br \/>\nseq_1 &amp;= [50,100,10] \\\\<br \/>\nsorted(seq_2) &amp;= [10,50,100] \\\\<br \/>\n&amp;\\begin{pmatrix}{}<br \/>\n0 &amp; 1 &amp; 2 \\\\<br \/>\n1 &amp; 2 &amp; 0<br \/>\n\\end{pmatrix}<br \/>\n\\end{align}\\]<\/span><\/p>\n<p>We can think about what it means to <em>apply<\/em> the permutation to <span class=\"math\">\\(seq_1\\)<\/span>. Here goes:<\/p>\n<ol style=\"list-style-type: decimal\">\n<li>\n<p><span class=\"math\">\\(seq_1[0] \\leftrightarrow seq_1[1]\\)<\/span><\/p>\n<p>After we perform this, <span class=\"math\">\\(seq_1\\)<\/span> has been mutated to <span class=\"math\">\\(seq_1 = [100,50,10]\\)<\/span>. Position 1 (with value 50) is in its final resting place. It doesn&#8217;t need to move anywhere. Position 0 used to have the value 50, now it is 100. Obviously (or maybe not!), performing this swap improved the ordering of <span class=\"math\">\\(seq_1\\)<\/span>. But, it invalidated our permutation-function in two ways: (1) we no longer need &quot;fix up&quot; position 1 (i.e, we no longer need a target position of 1) and (2) we no longer want to move position 1 somewhere else (which is exactly what the second column says to do).<\/p>\n<p>Let&#8217;s update the permutation-function so it can be applied to the rest of <span class=\"math\">\\(seq_1\\)<\/span> to sort it. The first thing we&#8217;ll do is remove the operation we just applied (we don&#8217;t want to do it again): <span class=\"math\">\\(\\begin{pmatrix}{} 1 &amp; 2 \\\\ 2 &amp; 0 \\end{pmatrix}\\)<\/span>. Now, first column says we want to move: <span class=\"math\">\\(seq_1[1] \\rightarrow seq_1[2]\\)<\/span>. But, this can&#8217;t be right! Remember <span class=\"math\">\\(seq_1[1]\\)<\/span> is in its final home. What went wrong? We moved what <em>used to be at position 1 to position 0<\/em>. So, what we <em>really<\/em> want to do is move <span class=\"math\">\\(seq_1[0] \\rightarrow seq_1[2]\\)<\/span>. Which means we want our permutation to be: <span class=\"math\">\\(\\begin{pmatrix}{} 0 &amp; 2 \\\\ 2 &amp; 0 \\end{pmatrix}\\)<\/span>.<\/p>\n<p>If we use <em>src<\/em> and <em>tgt<\/em> to refer to the first and second indices we used for swapping, what we said was &quot;after swapping at <em>src<\/em> and <em>tgt<\/em>: drop their column, find <em>tgt<\/em> in the sources &#8211; the first row &#8211; and replace it with <em>src<\/em>. That is, instead of coming from <em>tgt<\/em>, we now come from <em>src<\/em> (since we swapped them).<\/p>\n<p>We do the same process again with updated structures: <span class=\"math\">\\(seq_1 = [100,50,10]\\)<\/span> and <span class=\"math\">\\(\\begin{pmatrix}{} 0 &amp; 2 \\\\ 2 &amp; 0 \\end{pmatrix}\\)<\/span>. You may have noticed that this particular permutation-function has a special structure. And it is related to the fact that if only two items in a list are out of place, you only need <em>one<\/em> swap to fix both of them (someone once mentioned something about two birds, one stone &#8211; but I digress). Let&#8217;s see what happens.<\/p>\n<\/li>\n<li>\n<p><span class=\"math\">\\(seq_1[0] \\leftrightarrow seq_1[2]\\)<\/span><\/p>\n<p>Now, <span class=\"math\">\\(seq_1 = [10,50,100]\\)<\/span>. Our sequence is sorted, and we <em>could just stop<\/em>. But let&#8217;s fix the permutation anyway. First, we drop the initial column: <span class=\"math\">\\(\\begin{pmatrix}{} 2 \\\\ 0 \\end{pmatrix}\\)<\/span>. Second, in the sources locate <em>tgt<\/em> (2) and replace it with <em>src<\/em> (0). This gives a permutation: <span class=\"math\">\\(\\begin{pmatrix}{} 0 \\\\ 0 \\end{pmatrix}\\)<\/span>. Now, since swapping position 0 with position 0 is a null operation (it has no effect), we don&#8217;t even have to apply it. Which gels with out intuition of only needing one swap to fix two (and only two) out of place elements.<\/p>\n<\/li>\n<\/ol>\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<h5 id=\"Some-Helper-Code\">Some Helper Code<a class=\"anchor-link\" href=\"#Some-Helper-Code\">&#182;<\/a><\/h5>\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<span class=\"kn\">import<\/span> <span class=\"nn\">itertools<\/span> <span class=\"kn\">as<\/span> <span class=\"nn\">it<\/span>\r\n<span class=\"k\">def<\/span> <span class=\"nf\">swap<\/span><span class=\"p\">(<\/span><span class=\"n\">lst<\/span><span class=\"p\">,<\/span> <span class=\"n\">a<\/span><span class=\"p\">,<\/span> <span class=\"n\">b<\/span><span class=\"p\">):<\/span>\r\n    <span class=\"n\">lst<\/span><span class=\"p\">[<\/span><span class=\"n\">a<\/span><span class=\"p\">],<\/span> <span class=\"n\">lst<\/span><span class=\"p\">[<\/span><span class=\"n\">b<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">lst<\/span><span class=\"p\">[<\/span><span class=\"n\">b<\/span><span class=\"p\">],<\/span> <span class=\"n\">lst<\/span><span class=\"p\">[<\/span><span class=\"n\">a<\/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<h5 id=\"Apply-a-Permutation-to-a-List-(and-use-it-to-Sort)\">Apply a Permutation to a List (and use it to Sort)<a class=\"anchor-link\" href=\"#Apply-a-Permutation-to-a-List-(and-use-it-to-Sort)\">&#182;<\/a><\/h5>\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>Now, let&#8217;s encode in Python the steps we carried out by hand &#8212; since computers are designed for this sort of thing. We&#8217;ll make use of two helpers on the way to applying permutations. One is our representation of a permutation. We&#8217;ll use a dictionary so that the permutation <span class=\"math\">\\(\\begin{pmatrix}0 &amp; 1 &amp; 2 \\\\ 1 &amp; 2 &amp; 0 \\end{pmatrix}\\)<\/span> is stored in the python dictionary <code>{0:1, 1:2, 2:0}<\/code>. This is a natural data structure for an explicitly defined mathematical function and it allows constant time lookup of a key when we need to &quot;fix it up&quot;. The second helper we use is a decorate-sort-undecorate pattern to find the sorting permutation. Here is how that 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;[2]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"n\">lst<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"mi\">50<\/span><span class=\"p\">,<\/span> <span class=\"mi\">100<\/span><span class=\"p\">,<\/span> <span class=\"mi\">10<\/span><span class=\"p\">]<\/span>\r\n<span class=\"n\">valAndOrigin<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">sorted<\/span><span class=\"p\">((<\/span><span class=\"n\">j<\/span><span class=\"p\">,<\/span><span class=\"n\">i<\/span><span class=\"p\">)<\/span> <span class=\"k\">for<\/span> <span class=\"n\">i<\/span><span class=\"p\">,<\/span><span class=\"n\">j<\/span> <span class=\"ow\">in<\/span> <span class=\"nb\">enumerate<\/span><span class=\"p\">(<\/span><span class=\"n\">lst<\/span><span class=\"p\">))<\/span> <span class=\"c\"># sort by lst value, carry the index with it<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">valAndOrigin<\/span>\r\n\r\n<span class=\"n\">sortedValues<\/span><span class=\"p\">,<\/span> <span class=\"n\">origPos<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">zip<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">valAndOrigin<\/span><span class=\"p\">)<\/span> <span class=\"c\"># zip(*foo) says to &quot;unzip&quot; foo<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">sortedValues<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">origPos<\/span>\r\n\r\n<span class=\"c\"># we can drop any null operations (i.e., src == tgt)<\/span>\r\n<span class=\"n\">sortingPermutation<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">dict<\/span><span class=\"p\">((<\/span><span class=\"n\">j<\/span><span class=\"p\">,<\/span><span class=\"n\">i<\/span><span class=\"p\">)<\/span> <span class=\"k\">for<\/span> <span class=\"n\">i<\/span><span class=\"p\">,<\/span><span class=\"n\">j<\/span> <span class=\"ow\">in<\/span> <span class=\"nb\">enumerate<\/span><span class=\"p\">(<\/span><span class=\"n\">origPos<\/span><span class=\"p\">)<\/span> <span class=\"k\">if<\/span> <span class=\"n\">i<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">j<\/span><span class=\"p\">)<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">sortingPermutation<\/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[(10, 2), (50, 0), (100, 1)]\r\n(10, 50, 100)\r\n(2, 0, 1)\r\n{0: 1, 1: 2, 2: 0}\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=\"k\">def<\/span> <span class=\"nf\">extract_sorting_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">lst<\/span><span class=\"p\">):<\/span>\r\n    <span class=\"n\">_<\/span><span class=\"p\">,<\/span> <span class=\"n\">sortingPerm<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">zip<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"nb\">sorted<\/span><span class=\"p\">((<\/span><span class=\"n\">j<\/span><span class=\"p\">,<\/span><span class=\"n\">i<\/span><span class=\"p\">)<\/span> <span class=\"k\">for<\/span> <span class=\"n\">i<\/span><span class=\"p\">,<\/span><span class=\"n\">j<\/span> <span class=\"ow\">in<\/span> <span class=\"nb\">enumerate<\/span><span class=\"p\">(<\/span><span class=\"n\">lst<\/span><span class=\"p\">)))<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"nb\">dict<\/span><span class=\"p\">((<\/span><span class=\"n\">j<\/span><span class=\"p\">,<\/span> <span class=\"n\">i<\/span><span class=\"p\">)<\/span> <span class=\"k\">for<\/span> <span class=\"n\">i<\/span><span class=\"p\">,<\/span><span class=\"n\">j<\/span> <span class=\"ow\">in<\/span> <span class=\"nb\">enumerate<\/span><span class=\"p\">(<\/span><span class=\"n\">sortingPerm<\/span><span class=\"p\">)<\/span> <span class=\"k\">if<\/span> <span class=\"n\">i<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">j<\/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>Now, we can write the code to apply a permutation to a sequence (for us, the sequence is a python list). One quick note: we explicitly test to see if source and target are the same &#8212; and if they are, we skip the update. You might ask, &quot;how can that happen, other than in the last spot?&quot; It turns out the the example permutations we used above had only one <em>cycle<\/em>. I&#8217;ll discuss cycles more below (actually, they are going to be in a post of their own), but suffice to say that in each cycle, there will come a point of two differences (one swap needed). So, if there are many cycles in the permutation, even if we stop when we apply the next to last column (of the whole permutation), we will still have some identity swaps (null operations) at the end of earlier cycles.<\/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\">def<\/span> <span class=\"nf\">apply_permutation_to<\/span><span class=\"p\">(<\/span><span class=\"n\">perm<\/span><span class=\"p\">,<\/span> <span class=\"n\">lst<\/span><span class=\"p\">):<\/span>\r\n    <span class=\"n\">src<\/span><span class=\"p\">,<\/span> <span class=\"n\">tgt<\/span> <span class=\"o\">=<\/span> <span class=\"n\">perm<\/span><span class=\"o\">.<\/span><span class=\"n\">popitem<\/span><span class=\"p\">()<\/span>\r\n    <span class=\"k\">while<\/span> <span class=\"n\">perm<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"c\"># only need test if we haven&#39;t decomposed permutation to cycles<\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"n\">tgt<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">src<\/span><span class=\"p\">:<\/span> \r\n            <span class=\"n\">swap<\/span><span class=\"p\">(<\/span><span class=\"n\">lst<\/span><span class=\"p\">,<\/span> <span class=\"n\">tgt<\/span><span class=\"p\">,<\/span> <span class=\"n\">src<\/span><span class=\"p\">)<\/span>\r\n            <span class=\"c\"># update permutation FROM {tgt:perm[tgt]} TO {src:perm[tgt]}<\/span>\r\n            <span class=\"n\">perm<\/span><span class=\"p\">[<\/span><span class=\"n\">src<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">perm<\/span><span class=\"p\">[<\/span><span class=\"n\">tgt<\/span><span class=\"p\">];<\/span> <span class=\"k\">del<\/span> <span class=\"n\">perm<\/span><span class=\"p\">[<\/span><span class=\"n\">tgt<\/span><span class=\"p\">]<\/span>\r\n        <span class=\"n\">src<\/span><span class=\"p\">,<\/span> <span class=\"n\">tgt<\/span> <span class=\"o\">=<\/span> <span class=\"n\">perm<\/span><span class=\"o\">.<\/span><span class=\"n\">popitem<\/span><span class=\"p\">()<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"n\">lst<\/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>With those pieces, we can sort using the round-about process of decorated sort <span class=\"math\">\\(\\rightarrow\\)<\/span> permutation <span class=\"math\">\\(\\rightarrow\\)<\/span> auxilliary sort.<\/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\">def<\/span> <span class=\"nf\">create_permutation_and_sort<\/span><span class=\"p\">(<\/span><span class=\"n\">lst<\/span><span class=\"p\">):<\/span>\r\n    <span class=\"n\">sortingPerm<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_sorting_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">lst<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">if<\/span> <span class=\"ow\">not<\/span> <span class=\"n\">sortingPerm<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"k\">return<\/span> <span class=\"n\">lst<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"n\">apply_permutation_to<\/span><span class=\"p\">(<\/span><span class=\"n\">sortingPerm<\/span><span class=\"p\">,<\/span> <span class=\"n\">lst<\/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>And now we can test this by creating all permutations of lists from length 1 to length 8.<\/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\">def<\/span> <span class=\"nf\">test_perm_sort<\/span><span class=\"p\">():<\/span>\r\n    <span class=\"n\">MAX_LIST_SIZE<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">8<\/span>\r\n    <span class=\"n\">testLists<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"nb\">range<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,(<\/span><span class=\"n\">i<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">)<\/span><span class=\"o\">*<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span><span class=\"mi\">2<\/span><span class=\"p\">)<\/span> <span class=\"k\">for<\/span> <span class=\"n\">i<\/span> <span class=\"ow\">in<\/span> <span class=\"nb\">range<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"n\">MAX_LIST_SIZE<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">)]<\/span>\r\n    <span class=\"k\">for<\/span> <span class=\"n\">lst<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">testLists<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"k\">for<\/span> <span class=\"n\">testCase<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">it<\/span><span class=\"o\">.<\/span><span class=\"n\">permutations<\/span><span class=\"p\">(<\/span><span class=\"n\">lst<\/span><span class=\"p\">,<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">lst<\/span><span class=\"p\">)):<\/span>\r\n            <span class=\"k\">assert<\/span> <span class=\"nb\">sorted<\/span><span class=\"p\">(<\/span><span class=\"n\">testCase<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"n\">create_permutation_and_sort<\/span><span class=\"p\">(<\/span><span class=\"nb\">list<\/span><span class=\"p\">(<\/span><span class=\"n\">testCase<\/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 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=\"k\">try<\/span><span class=\"p\">:<\/span>\r\n    <span class=\"n\">test_perm_sort<\/span><span class=\"p\">()<\/span>\r\n    <span class=\"k\">print<\/span> <span class=\"s\">&quot;passed&quot;<\/span>\r\n<span class=\"k\">except<\/span> <span class=\"ne\">AssertionError<\/span><span class=\"p\">:<\/span>\r\n    <span class=\"k\">print<\/span> <span class=\"s\">&quot;failed&quot;<\/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\npassed\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<h5 id=\"Given-a-Permutation,-Convert-it-to-Series-of-Swaps-(and-use-it-to-Sort)\">Given a Permutation, Convert it to Series of Swaps (and use it to Sort)<a class=\"anchor-link\" href=\"#Given-a-Permutation,-Convert-it-to-Series-of-Swaps-(and-use-it-to-Sort)\">&#182;<\/a><\/h5>\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>Above, we discussed the need to extract a sequence of swaps from a permutation. It turns out that this is basically the same process as <em>applying<\/em> the permutation. The only difference is that instead of <em>performing<\/em> a swap, we <em>record<\/em> the swap.<\/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\">def<\/span> <span class=\"nf\">extract_swaps_from_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">perm<\/span><span class=\"p\">):<\/span>\r\n    <span class=\"n\">src<\/span><span class=\"p\">,<\/span> <span class=\"n\">tgt<\/span> <span class=\"o\">=<\/span> <span class=\"n\">perm<\/span><span class=\"o\">.<\/span><span class=\"n\">popitem<\/span><span class=\"p\">()<\/span>\r\n    <span class=\"n\">swaps<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\r\n    <span class=\"k\">while<\/span> <span class=\"n\">perm<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"c\"># print &quot;swap: &quot;, src, tgt <\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"n\">tgt<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">src<\/span><span class=\"p\">:<\/span> <span class=\"c\"># only need test if we haven&#39;t decomposed perm to cycles<\/span>\r\n            <span class=\"n\">swaps<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">((<\/span><span class=\"n\">tgt<\/span><span class=\"p\">,<\/span> <span class=\"n\">src<\/span><span class=\"p\">))<\/span>\r\n            <span class=\"c\"># update permutation FROM {tgt:perm[tgt]} TO {src:perm[tgt]}<\/span>\r\n            <span class=\"n\">perm<\/span><span class=\"p\">[<\/span><span class=\"n\">src<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">perm<\/span><span class=\"p\">[<\/span><span class=\"n\">tgt<\/span><span class=\"p\">];<\/span> <span class=\"k\">del<\/span> <span class=\"n\">perm<\/span><span class=\"p\">[<\/span><span class=\"n\">tgt<\/span><span class=\"p\">]<\/span>\r\n        <span class=\"n\">src<\/span><span class=\"p\">,<\/span> <span class=\"n\">tgt<\/span> <span class=\"o\">=<\/span> <span class=\"n\">perm<\/span><span class=\"o\">.<\/span><span class=\"n\">popitem<\/span><span class=\"p\">()<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"n\">swaps<\/span>\r\n\r\n<span class=\"k\">def<\/span> <span class=\"nf\">apply_swaps_to<\/span><span class=\"p\">(<\/span><span class=\"n\">swaps<\/span><span class=\"p\">,<\/span> <span class=\"n\">lst<\/span><span class=\"p\">):<\/span>\r\n    <span class=\"k\">for<\/span> <span class=\"n\">s<\/span><span class=\"p\">,<\/span><span class=\"n\">t<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">swaps<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"n\">swap<\/span><span class=\"p\">(<\/span><span class=\"n\">lst<\/span><span class=\"p\">,<\/span> <span class=\"n\">s<\/span><span class=\"p\">,<\/span> <span class=\"n\">t<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"n\">lst<\/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>And now we can do our sort in terms of applied swaps (instead using the permutation, we use the swaps directly).<\/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\">def<\/span> <span class=\"nf\">test_perm_swap_sort<\/span><span class=\"p\">():<\/span>\r\n    <span class=\"n\">MAX_LIST_SIZE<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">8<\/span>\r\n    <span class=\"n\">testLists<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"nb\">range<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,(<\/span><span class=\"n\">i<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">)<\/span><span class=\"o\">*<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span><span class=\"mi\">2<\/span><span class=\"p\">)<\/span> <span class=\"k\">for<\/span> <span class=\"n\">i<\/span> <span class=\"ow\">in<\/span> <span class=\"nb\">range<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"n\">MAX_LIST_SIZE<\/span><span class=\"p\">)]<\/span>\r\n    <span class=\"k\">for<\/span> <span class=\"n\">lst<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">testLists<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"k\">for<\/span> <span class=\"n\">testCase<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">it<\/span><span class=\"o\">.<\/span><span class=\"n\">permutations<\/span><span class=\"p\">(<\/span><span class=\"n\">lst<\/span><span class=\"p\">,<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">lst<\/span><span class=\"p\">)):<\/span>\r\n            <span class=\"n\">perm<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_sorting_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">lst<\/span><span class=\"p\">)<\/span>\r\n            <span class=\"k\">if<\/span> <span class=\"ow\">not<\/span> <span class=\"n\">perm<\/span><span class=\"p\">:<\/span> \r\n                <span class=\"k\">continue<\/span>\r\n            <span class=\"n\">swaps<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_swaps_from_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">perm<\/span><span class=\"p\">)<\/span>\r\n            <span class=\"c\"># print testCase, sorted(testCase), apply_swaps_to(swaps, list(testCase))<\/span>\r\n            <span class=\"k\">assert<\/span> <span class=\"nb\">sorted<\/span><span class=\"p\">(<\/span><span class=\"n\">testCase<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"n\">apply_swaps_to<\/span><span class=\"p\">(<\/span><span class=\"n\">swaps<\/span><span class=\"p\">,<\/span> <span class=\"nb\">list<\/span><span class=\"p\">(<\/span><span class=\"n\">testCase<\/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 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=\"k\">try<\/span><span class=\"p\">:<\/span>\r\n    <span class=\"n\">test_perm_swap_sort<\/span><span class=\"p\">()<\/span>\r\n    <span class=\"k\">print<\/span> <span class=\"s\">&quot;passed&quot;<\/span>\r\n<span class=\"k\">except<\/span> <span class=\"ne\">AssertionError<\/span><span class=\"p\">:<\/span>\r\n    <span class=\"k\">print<\/span> <span class=\"s\">&quot;failed&quot;<\/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\npassed\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=\"Factor-the-Common-Code\">Factor the Common Code<a class=\"anchor-link\" href=\"#Factor-the-Common-Code\">&#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>Since there is such a great similarity between apply the permutation and recording the swaps it makes, we can make a single common routine to do both tasks. Essentially, we create the right function to use inside the loop. We either use a simple swap function (curried to swap only on the given list) <em>or<\/em> we use an a function that can append to a record of the swaps. Both functions take a tuple <code>(src, tgt)<\/code> as their argument. Here is a first pass:<\/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\">def<\/span> <span class=\"nf\">apply_or_extract_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">perm<\/span><span class=\"p\">,<\/span> <span class=\"n\">lst<\/span><span class=\"o\">=<\/span><span class=\"p\">[]):<\/span>\r\n    <span class=\"k\">if<\/span> <span class=\"ow\">not<\/span> <span class=\"n\">lst<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"c\"># print &quot;in not lst&quot;<\/span>\r\n        <span class=\"n\">swaps<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\r\n        <span class=\"n\">innerFunc<\/span> <span class=\"o\">=<\/span> <span class=\"n\">swaps<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span>\r\n        <span class=\"c\"># print &quot;building swaps: &quot;, swaps, innerFunc<\/span>\r\n    <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"k\">def<\/span> <span class=\"nf\">innerFunc<\/span><span class=\"p\">(<\/span><span class=\"n\">args<\/span><span class=\"p\">):<\/span>\r\n            <span class=\"n\">swap<\/span><span class=\"p\">(<\/span><span class=\"n\">lst<\/span><span class=\"p\">,<\/span> <span class=\"n\">args<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">],<\/span> <span class=\"n\">args<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">])<\/span>\r\n            \r\n    <span class=\"n\">src<\/span><span class=\"p\">,<\/span> <span class=\"n\">tgt<\/span> <span class=\"o\">=<\/span> <span class=\"n\">perm<\/span><span class=\"o\">.<\/span><span class=\"n\">popitem<\/span><span class=\"p\">()<\/span>\r\n    <span class=\"k\">while<\/span> <span class=\"n\">perm<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"c\"># print &quot;swap: &quot;, src, tgt <\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"n\">tgt<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">src<\/span><span class=\"p\">:<\/span> <span class=\"c\"># only need test if we haven&#39;t decomposed perm to cycles<\/span>\r\n            <span class=\"n\">innerFunc<\/span><span class=\"p\">((<\/span><span class=\"n\">tgt<\/span><span class=\"p\">,<\/span> <span class=\"n\">src<\/span><span class=\"p\">))<\/span>\r\n            <span class=\"c\"># print &quot;added swaps (%s,%s): %s&quot; % (tgt, src, swaps)<\/span>\r\n            <span class=\"c\"># update permutation FROM {tgt:perm[tgt]} TO {src:perm[tgt]}<\/span>\r\n            <span class=\"n\">perm<\/span><span class=\"p\">[<\/span><span class=\"n\">src<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">perm<\/span><span class=\"p\">[<\/span><span class=\"n\">tgt<\/span><span class=\"p\">];<\/span> <span class=\"k\">del<\/span> <span class=\"n\">perm<\/span><span class=\"p\">[<\/span><span class=\"n\">tgt<\/span><span class=\"p\">]<\/span>\r\n        <span class=\"n\">src<\/span><span class=\"p\">,<\/span> <span class=\"n\">tgt<\/span> <span class=\"o\">=<\/span> <span class=\"n\">perm<\/span><span class=\"o\">.<\/span><span class=\"n\">popitem<\/span><span class=\"p\">()<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"n\">lst<\/span> <span class=\"k\">if<\/span> <span class=\"n\">lst<\/span> <span class=\"k\">else<\/span> <span class=\"n\">swaps<\/span>\r\n\r\n<span class=\"n\">extract_swaps_from_permutation<\/span> <span class=\"o\">=<\/span> <span class=\"n\">apply_or_extract_permutation<\/span>\r\n<span class=\"n\">apply_permutation_to<\/span> <span class=\"o\">=<\/span> <span class=\"n\">apply_or_extract_permutation<\/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;[12]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\"highlight\">\n<pre><span class=\"n\">test_perm_sort<\/span><span class=\"p\">()<\/span>\r\n<span class=\"n\">test_perm_swap_sort<\/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<h5 id=\"And-a-Cleaner-Refactoring\">And a Cleaner Refactoring<a class=\"anchor-link\" href=\"#And-a-Cleaner-Refactoring\">&#182;<\/a><\/h5>\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>The refactoring to <code>apply_or_extract_permatation<\/code> ended up being very dirty: there was &quot;a lot&quot; of ugliness in the creation of the two alternate inner functions. Also, the default argument (<code>lst=[]<\/code>) effects both the semantics of the call and the internal operation. Personally, I prefer one execution path through the function and to encapsulate the different semantics in their own, appropriate, functions.<\/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=\"k\">def<\/span> <span class=\"nf\">walk_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">perm<\/span><span class=\"p\">,<\/span> <span class=\"n\">op<\/span><span class=\"p\">):<\/span>            \r\n    <span class=\"n\">src<\/span><span class=\"p\">,<\/span> <span class=\"n\">tgt<\/span> <span class=\"o\">=<\/span> <span class=\"n\">perm<\/span><span class=\"o\">.<\/span><span class=\"n\">popitem<\/span><span class=\"p\">()<\/span>\r\n    <span class=\"k\">while<\/span> <span class=\"n\">perm<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"n\">tgt<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">src<\/span><span class=\"p\">:<\/span> <span class=\"c\"># only need test if we haven&#39;t decomposed perm to cycles<\/span>\r\n            <span class=\"n\">op<\/span><span class=\"p\">((<\/span><span class=\"n\">tgt<\/span><span class=\"p\">,<\/span> <span class=\"n\">src<\/span><span class=\"p\">))<\/span>\r\n            <span class=\"c\"># update permutation FROM {tgt:perm[tgt]} TO {src:perm[tgt]}<\/span>\r\n            <span class=\"n\">perm<\/span><span class=\"p\">[<\/span><span class=\"n\">src<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">perm<\/span><span class=\"p\">[<\/span><span class=\"n\">tgt<\/span><span class=\"p\">];<\/span> <span class=\"k\">del<\/span> <span class=\"n\">perm<\/span><span class=\"p\">[<\/span><span class=\"n\">tgt<\/span><span class=\"p\">]<\/span>\r\n        <span class=\"n\">src<\/span><span class=\"p\">,<\/span> <span class=\"n\">tgt<\/span> <span class=\"o\">=<\/span> <span class=\"n\">perm<\/span><span class=\"o\">.<\/span><span class=\"n\">popitem<\/span><span class=\"p\">()<\/span>\r\n    <span class=\"k\">return<\/span>\r\n\r\n<span class=\"k\">def<\/span> <span class=\"nf\">extract_swaps_from_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">perm<\/span><span class=\"p\">):<\/span>\r\n    <span class=\"n\">swaps<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[];<\/span> <span class=\"n\">op<\/span> <span class=\"o\">=<\/span> <span class=\"n\">swaps<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span>\r\n    <span class=\"n\">walk_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">perm<\/span><span class=\"p\">,<\/span> <span class=\"n\">op<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"n\">swaps<\/span>\r\n    \r\n<span class=\"k\">def<\/span> <span class=\"nf\">apply_permuation_to<\/span><span class=\"p\">(<\/span><span class=\"n\">perm<\/span><span class=\"p\">,<\/span> <span class=\"n\">lst<\/span><span class=\"p\">):<\/span>\r\n    <span class=\"k\">def<\/span> <span class=\"nf\">op<\/span><span class=\"p\">(<\/span><span class=\"n\">args<\/span><span class=\"p\">):<\/span>\r\n        <span class=\"n\">swap<\/span><span class=\"p\">(<\/span><span class=\"n\">lst<\/span><span class=\"p\">,<\/span> <span class=\"n\">args<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">],<\/span> <span class=\"n\">args<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">])<\/span>\r\n    <span class=\"n\">walk_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">perm<\/span><span class=\"p\">,<\/span> <span class=\"n\">op<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"n\">lst<\/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><code>walk_permutation<\/code> now does <em>just that<\/em>: it moves across the permutation and keeps track of updating it. It also applies the give side-effect operation. Also, the tasks specific to recording and performing are now completely factored into their own functions. We need to make sure we haven&#8217;t broken anything.<\/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\">test_perm_sort<\/span><span class=\"p\">()<\/span>\r\n<span class=\"n\">test_perm_swap_sort<\/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<h5 id=\"The-Lightbulb\">The Lightbulb<a class=\"anchor-link\" href=\"#The-Lightbulb\">&#182;<\/a><\/h5>\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>If you recall, we were extracting the swaps so that we could perform some other set of swapping. Well, we can extract the swaps and then apply them one at a time. <em>Or<\/em>, we could give a carefully constructed function that is performing the required swaps as we get them. And we can do this using <code>walk_permutation<\/code>&#8216;s second argument. Let&#8217;s take a look at the problem that inspired this post.<\/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<h5 id=\"The-Original-Motivation\">The Original Motivation<a class=\"anchor-link\" href=\"#The-Original-Motivation\">&#182;<\/a><\/h5>\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>Suppose we have a numpy array that also has an explicitly definied domain over which its dimensions are specified. For example, in probability problems we might specify a complete probability distribution over the events in the sample space. If we draw yellow and green balls from Urn I and red and blue balls from Urn II, the distribution might be:<\/p>\n<p><span class=\"math\">\\[\\begin{align}<br \/>\np(I = y) &amp;= .4 \\\\<br \/>\np(II = b) &amp;= .7 \\\\<br \/>\n\\\\<br \/>\np(I=y, II=b) &amp;= .4 * .7 = .28 \\\\<br \/>\np(I=y, II=r) &amp;= .4 * .3 = .12 \\\\<br \/>\np(I=g, II=b) &amp;= .6 * .7 = .42 \\\\<br \/>\np(I=g, II=r) &amp;= .6 * .3 = .18<br \/>\n\\end{align}\\]<\/span><\/p>\n<p>And we can represent that as a <span class=\"math\">\\(2&#215;2\\)<\/span> NumPy array:<\/p>\n<pre><code>p = np.array([[.28, .12],\r\n              [.42, .18]])<\/code><\/pre>\n<p>The two dimensions in <code>p<\/code> (the visual rows and columns) express the act that there are two random variable (the two Urns). The two entries per row (and per column) mean that each variable has two values. When multiplying two probability tables (really, multiplying two <em>potential functions<\/em>, but I&#8217;ll call them tables to simplify the terminology), the variables that occur in both need to be aligned and given special treatment. We call the set of all the random variables that occur in the table its <em>domain<\/em>.<\/p>\n<p>Hence, when we multiply (and perform other operations) on two tables, it is handy to have the variables in a sorted order. We can use binary search instead of linear search to locate a variable in the domain of the potential.<\/p>\n<p>Here&#8217;s a more complicated table.<\/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=\"n\">domain0<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"s\">&quot;B&quot;<\/span><span class=\"p\">,<\/span> <span class=\"s\">&quot;A&quot;<\/span><span class=\"p\">]<\/span>\r\n<span class=\"n\">p0<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">array<\/span><span class=\"p\">([[<\/span><span class=\"o\">.<\/span><span class=\"mi\">28<\/span><span class=\"p\">,<\/span> <span class=\"o\">.<\/span><span class=\"mi\">12<\/span><span class=\"p\">],<\/span>\r\n              <span class=\"p\">[<\/span><span class=\"o\">.<\/span><span class=\"mi\">42<\/span><span class=\"p\">,<\/span> <span class=\"o\">.<\/span><span class=\"mi\">18<\/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 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\">domain1<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"s\">&quot;E&quot;<\/span><span class=\"p\">,<\/span> <span class=\"s\">&quot;B&quot;<\/span><span class=\"p\">,<\/span> <span class=\"s\">&quot;A&quot;<\/span><span class=\"p\">]<\/span>\r\n<span class=\"n\">p1<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">array<\/span><span class=\"p\">([[[<\/span><span class=\"mi\">1<\/span><span class=\"o\">-.<\/span><span class=\"mo\">001<\/span><span class=\"p\">,<\/span> <span class=\"o\">.<\/span><span class=\"mo\">001<\/span><span class=\"p\">],<\/span>\r\n               <span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"o\">-.<\/span><span class=\"mi\">94<\/span> <span class=\"p\">,<\/span> <span class=\"o\">.<\/span><span class=\"mi\">94<\/span> <span class=\"p\">]],<\/span> \r\n              <span class=\"p\">[[<\/span><span class=\"mi\">1<\/span><span class=\"o\">-.<\/span><span class=\"mi\">29<\/span> <span class=\"p\">,<\/span> <span class=\"o\">.<\/span><span class=\"mi\">29<\/span> <span class=\"p\">],<\/span>\r\n               <span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"o\">-.<\/span><span class=\"mi\">95<\/span> <span class=\"p\">,<\/span> <span class=\"o\">.<\/span><span class=\"mi\">95<\/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 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\">domain2<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"s\">&quot;E&quot;<\/span><span class=\"p\">,<\/span> <span class=\"s\">&quot;B&quot;<\/span><span class=\"p\">,<\/span> <span class=\"s\">&quot;A&quot;<\/span><span class=\"p\">]<\/span>\r\n<span class=\"n\">p2<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">random<\/span><span class=\"o\">.<\/span><span class=\"n\">uniform<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"mi\">1<\/span><span class=\"p\">,(<\/span><span class=\"mi\">4<\/span><span class=\"p\">,<\/span><span class=\"mi\">3<\/span><span class=\"p\">,<\/span><span class=\"mi\">2<\/span><span class=\"p\">))<\/span>\r\n<span class=\"n\">p2<\/span> <span class=\"o\">=<\/span> <span class=\"n\">p2<\/span><span class=\"p\">[:,:]<\/span> <span class=\"o\">\/<\/span> <span class=\"n\">p2<\/span><span class=\"o\">.<\/span><span class=\"n\">sum<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/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>\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 sort the domain (and the dimensions of the array), we can:<\/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;[18]:<\/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\">apply_swaps_to_array_axes<\/span><span class=\"p\">(<\/span><span class=\"n\">swaps<\/span><span class=\"p\">,<\/span> <span class=\"n\">arr<\/span><span class=\"p\">):<\/span>\r\n    <span class=\"k\">for<\/span> <span class=\"n\">s<\/span><span class=\"p\">,<\/span><span class=\"n\">t<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">swaps<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"n\">arr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">swapaxes<\/span><span class=\"p\">(<\/span><span class=\"n\">arr<\/span><span class=\"p\">,<\/span> <span class=\"n\">s<\/span><span class=\"p\">,<\/span> <span class=\"n\">t<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"n\">arr<\/span>\r\n\r\n<span class=\"k\">print<\/span> <span class=\"n\">domain1<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">p1<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">p1<\/span> \r\n\r\n<span class=\"n\">perm<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_sorting_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">domain1<\/span><span class=\"p\">)<\/span>\r\n<span class=\"n\">swaps<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_swaps_from_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">perm<\/span><span class=\"p\">)<\/span>\r\n<span class=\"n\">result<\/span> <span class=\"o\">=<\/span> <span class=\"n\">apply_swaps_to_array_axes<\/span><span class=\"p\">(<\/span><span class=\"n\">swaps<\/span><span class=\"p\">,<\/span> <span class=\"n\">p1<\/span><span class=\"p\">)<\/span>\r\n\r\n<span class=\"k\">print<\/span> <span class=\"nb\">sorted<\/span><span class=\"p\">(<\/span><span class=\"n\">domain1<\/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\">result<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">result<\/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[&apos;E&apos;, &apos;B&apos;, &apos;A&apos;]\r\n(2, 2, 2)\r\n[[[ 0.999  0.001]\r\n  [ 0.06   0.94 ]]\r\n\r\n [[ 0.71   0.29 ]\r\n  [ 0.05   0.95 ]]]\r\n[&apos;A&apos;, &apos;B&apos;, &apos;E&apos;]\r\nshape:  (2, 2, 2)\r\n[[[ 0.999  0.71 ]\r\n  [ 0.06   0.05 ]]\r\n\r\n [[ 0.001  0.29 ]\r\n  [ 0.94   0.95 ]]]\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<h5 id=\"Lightbulb-(Part-II)\">Lightbulb (Part II)<a class=\"anchor-link\" href=\"#Lightbulb-(Part-II)\">&#182;<\/a><\/h5>\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>But wait. We can also apply those swaps with <code>walk_permutation<\/code>. But, we run into a problem. NumPy&#8217;s <code>swapaxes<\/code> routine returns view of the original array (it doesn&#8217;t update it). Because it doesn&#8217;t have side-effects, we have to do some <em>very ugly<\/em> code to force the side-effect. I can&#8217;t in good conscience recommend doing this. Thus, I&#8217;m going to stick with the solution above (and think if there is a nicer way to deal with this).<\/p>\n<p>Two notes: this routine updates the input array (pseudo-<em>in-place<\/em> b\/c a copy is made internally). Also, I have to do some ugliness to force the array to update itself (see <code>def swapper<\/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;[19]:<\/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\">domain1<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">p1<\/span>\r\n\r\n<span class=\"n\">perm<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_sorting_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">domain1<\/span><span class=\"p\">)<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">perm<\/span>\r\n\r\n<span class=\"k\">def<\/span> <span class=\"nf\">apply_permutation_on_axes<\/span><span class=\"p\">(<\/span><span class=\"n\">perm<\/span><span class=\"p\">,<\/span> <span class=\"n\">arr<\/span><span class=\"p\">):<\/span>\r\n    <span class=\"k\">def<\/span> <span class=\"nf\">swapper<\/span><span class=\"p\">(<\/span><span class=\"n\">args<\/span><span class=\"p\">):<\/span>\r\n        <span class=\"n\">view<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">swapaxes<\/span><span class=\"p\">(<\/span><span class=\"n\">arr<\/span><span class=\"p\">,<\/span> <span class=\"n\">args<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">],<\/span> <span class=\"n\">args<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">])<\/span>\r\n        <span class=\"n\">shape<\/span> <span class=\"o\">=<\/span> <span class=\"n\">view<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span>\r\n        <span class=\"n\">arr<\/span><span class=\"o\">.<\/span><span class=\"n\">flat<\/span> <span class=\"o\">=<\/span> <span class=\"n\">view<\/span><span class=\"o\">.<\/span><span class=\"n\">flatten<\/span><span class=\"p\">()<\/span> <span class=\"c\"># update the array values (from copy)<\/span>\r\n        <span class=\"n\">arr<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span> <span class=\"o\">=<\/span> <span class=\"n\">shape<\/span>\r\n    <span class=\"n\">walk_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">perm<\/span><span class=\"p\">,<\/span> <span class=\"n\">swapper<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"n\">arr<\/span>\r\n\r\n<span class=\"n\">res<\/span> <span class=\"o\">=<\/span> <span class=\"n\">apply_permutation_on_axes<\/span><span class=\"p\">(<\/span><span class=\"n\">perm<\/span><span class=\"p\">,<\/span> <span class=\"n\">p1<\/span><span class=\"p\">)<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">res<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">res<\/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[&apos;E&apos;, &apos;B&apos;, &apos;A&apos;]\r\n[[[ 0.999  0.001]\r\n  [ 0.06   0.94 ]]\r\n\r\n [[ 0.71   0.29 ]\r\n  [ 0.05   0.95 ]]]\r\n{0: 2, 2: 0}\r\n(2, 2, 2)\r\n[[[ 0.999  0.71 ]\r\n  [ 0.06   0.05 ]]\r\n\r\n [[ 0.001  0.29 ]\r\n  [ 0.94   0.95 ]]]\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>The fundamental problem with the answer above is that I&#8217;m forcing array mutation (a side-effect) when array&#8217;s really want to work on modified views. We can do this if we turn the <code>walk_permutation<\/code> that works by returning values instead of relying on side-effects. Here goes. It is <em>a lot<\/em> cleaner. <code>twoarg_swapaxes<\/code> serves to massage the arguments to <code>np.swapaxes<\/code>, it isn&#8217;t necessary &#8211; we could make a different <code>op(arr, (tgt, src))<\/code> call. But this matches the code above.<\/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;[20]:<\/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\">walk_and_update_with_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">arr<\/span><span class=\"p\">,<\/span> <span class=\"n\">perm<\/span><span class=\"p\">,<\/span> <span class=\"n\">op<\/span><span class=\"p\">):<\/span>            \r\n    <span class=\"n\">src<\/span><span class=\"p\">,<\/span> <span class=\"n\">tgt<\/span> <span class=\"o\">=<\/span> <span class=\"n\">perm<\/span><span class=\"o\">.<\/span><span class=\"n\">popitem<\/span><span class=\"p\">()<\/span>\r\n    <span class=\"k\">while<\/span> <span class=\"n\">perm<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"n\">tgt<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">src<\/span><span class=\"p\">:<\/span> <span class=\"c\"># only need test if we haven&#39;t decomposed perm to cycles<\/span>\r\n            <span class=\"n\">arr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">op<\/span><span class=\"p\">(<\/span><span class=\"n\">arr<\/span><span class=\"p\">,<\/span> <span class=\"p\">(<\/span><span class=\"n\">tgt<\/span><span class=\"p\">,<\/span> <span class=\"n\">src<\/span><span class=\"p\">))<\/span>\r\n            <span class=\"c\"># update permutation FROM {tgt:perm[tgt]} TO {src:perm[tgt]}<\/span>\r\n            <span class=\"n\">perm<\/span><span class=\"p\">[<\/span><span class=\"n\">src<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">perm<\/span><span class=\"p\">[<\/span><span class=\"n\">tgt<\/span><span class=\"p\">];<\/span> <span class=\"k\">del<\/span> <span class=\"n\">perm<\/span><span class=\"p\">[<\/span><span class=\"n\">tgt<\/span><span class=\"p\">]<\/span>\r\n        <span class=\"n\">src<\/span><span class=\"p\">,<\/span> <span class=\"n\">tgt<\/span> <span class=\"o\">=<\/span> <span class=\"n\">perm<\/span><span class=\"o\">.<\/span><span class=\"n\">popitem<\/span><span class=\"p\">()<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"n\">arr<\/span>\r\n\r\n<span class=\"k\">def<\/span> <span class=\"nf\">twoarg_swapaxes<\/span><span class=\"p\">(<\/span><span class=\"n\">arr<\/span><span class=\"p\">,<\/span> <span class=\"n\">axes<\/span><span class=\"p\">):<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">swapaxes<\/span><span class=\"p\">(<\/span><span class=\"n\">arr<\/span><span class=\"p\">,<\/span> <span class=\"n\">axes<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">],<\/span> <span class=\"n\">axes<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">])<\/span>\r\n\r\n<span class=\"n\">domain1<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"s\">&quot;E&quot;<\/span><span class=\"p\">,<\/span> <span class=\"s\">&quot;B&quot;<\/span><span class=\"p\">,<\/span> <span class=\"s\">&quot;A&quot;<\/span><span class=\"p\">]<\/span>\r\n<span class=\"n\">p1<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">array<\/span><span class=\"p\">([[[<\/span><span class=\"mi\">1<\/span><span class=\"o\">-.<\/span><span class=\"mo\">001<\/span><span class=\"p\">,<\/span> <span class=\"o\">.<\/span><span class=\"mo\">001<\/span><span class=\"p\">],<\/span>\r\n               <span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"o\">-.<\/span><span class=\"mi\">94<\/span> <span class=\"p\">,<\/span> <span class=\"o\">.<\/span><span class=\"mi\">94<\/span> <span class=\"p\">]],<\/span> \r\n              <span class=\"p\">[[<\/span><span class=\"mi\">1<\/span><span class=\"o\">-.<\/span><span class=\"mi\">29<\/span> <span class=\"p\">,<\/span> <span class=\"o\">.<\/span><span class=\"mi\">29<\/span> <span class=\"p\">],<\/span>\r\n               <span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"o\">-.<\/span><span class=\"mi\">95<\/span> <span class=\"p\">,<\/span> <span class=\"o\">.<\/span><span class=\"mi\">95<\/span> <span class=\"p\">]]])<\/span>\r\n\r\n<span class=\"k\">print<\/span> <span class=\"n\">domain1<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">p1<\/span>\r\n\r\n<span class=\"n\">perm<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_sorting_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">domain1<\/span><span class=\"p\">)<\/span>\r\n<span class=\"k\">print<\/span> <span class=\"n\">walk_and_update_with_permutation<\/span><span class=\"p\">(<\/span><span class=\"n\">p1<\/span><span class=\"p\">,<\/span> <span class=\"n\">perm<\/span><span class=\"p\">,<\/span> <span class=\"n\">twoarg_swapaxes<\/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[&apos;E&apos;, &apos;B&apos;, &apos;A&apos;]\r\n[[[ 0.999  0.001]\r\n  [ 0.06   0.94 ]]\r\n\r\n [[ 0.71   0.29 ]\r\n  [ 0.05   0.95 ]]]\r\n[[[ 0.999  0.71 ]\r\n  [ 0.06   0.05 ]]\r\n\r\n [[ 0.001  0.29 ]\r\n  [ 0.94   0.95 ]]]\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>\nAdditional Resources<br \/>\n<\/h3>\n<p>You can grab a <a href=\"http:\/\/drsfenner.org\/public\/notebooks\/PermutationsAndSorting.ipynb\">copy of this notebook<\/a>.<\/p>\n<p>Even better, you can <a href=\"http:\/\/nbviewer.ipython.org\/url\/drsfenner.org\/public\/notebooks\/PermutationsAndSorting.ipynb\">view it using nbviewer<\/a>.<\/p>\n<h3>\nLicense<br \/>\n<\/h3>\n<p>Unless 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).<\/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>Introduction&#182; You may be familiar with permuations: a rearrangement of a sequence. If you are, you probably know that for a sequence of length \\(n\\), there are \\(n!\\) arrangements (if the elements are all distinct &#8211; duplicates will reduce the number of unique rearrangements). There are many, many uses of permutations and many specific permutations [&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-348","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\/348","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=348"}],"version-history":[{"count":2,"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/posts\/348\/revisions"}],"predecessor-version":[{"id":420,"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/posts\/348\/revisions\/420"}],"wp:attachment":[{"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/media?parent=348"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/categories?post=348"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/tags?post=348"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}