{"id":1413,"date":"2014-03-24T07:00:00","date_gmt":"2014-03-24T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2014\/03\/24\/enumerating-set-partitions-with-bell-numbers-and-stirling-numbers-of-the-second-kind\/"},"modified":"2014-03-24T07:00:00","modified_gmt":"2014-03-24T07:00:00","slug":"enumerating-set-partitions-with-bell-numbers-and-stirling-numbers-of-the-second-kind","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20140324-00\/?p=1413","title":{"rendered":"Enumerating set partitions with Bell numbers and Stirling numbers of the second kind"},"content":{"rendered":"<p>\nJust for fun,\ntoday&#8217;s Little Program is going to\ngenerate set partitions.\n(Why?\nBecause back in 2005,\nsomebody asked about it on an informal mailing list, suggesting it\nwould be an interesting puzzle,\nand now I finally got around to solving it.)\n<\/p>\n<p>\nThe person who asked the question said,\n<\/p>\n<blockquote CLASS=\"q\" STYLE=\"font-family: Times New Roman, serif\">\n<p>\nBelow we show the partitions of [4].\nThe periods separate the individual sets so that, for example,\n  1.23.4 is the partition {{1},{2,3},{4}}.\n<\/p>\n<table BORDER=\"0\" STYLE=\"font-family: Times New Roman, serif\">\n<tr>\n<td>1 blocks: <\/p>\n<td>1234 <\/p>\n<tr>\n<td>2 blocks:<\/p>\n<td>123.4,&nbsp; <\/p>\n<td>124.3,&nbsp; <\/p>\n<td>134.2,&nbsp; <\/p>\n<td>1.234,&nbsp;<\/p>\n<td>12.34,&nbsp; <\/p>\n<td>13.24,&nbsp; <\/p>\n<td>14.23 <\/p>\n<tr>\n<td>3 blocks:<\/p>\n<td>1.2.34,&nbsp; <\/p>\n<td>1.24.3,&nbsp; <\/p>\n<td>1.23.4,&nbsp;<\/p>\n<td>14.2.3,&nbsp; <\/p>\n<td>13.2.4,&nbsp; <\/p>\n<td>12.3.4 <\/p>\n<tr>\n<td>4 blocks: <\/p>\n<td>1.2.3.4 <br \/>\n<\/table>\n<\/blockquote>\n<p>\nI replied with a hint, saying,\n&#8220;<a HREF=\"http:\/\/www.theory.csc.uvic.ca\/~cos\/inf\/setp\/SetPartitions.html\">This page<\/a> explains what you need\nto do, once you reinterpret the Stirling recurrence as an enumeration.&#8221;\nOnly now, writing up this post,\ndid I realize that I linked to\n<i>the same page they were quoting from<\/i>.\n<\/p>\n<p>\nThe key is in the sentence,\n&#8220;They satisfy the following recurrence relation,\n<i>which forms\nthe basis of recursive algorithms for generating them<\/i>.&#8221;\nLet&#8217;s reinterpret the Stirling recurrence combinatorially.\nNo wait, we don&#8217;t need to.\n<a HREF=\"http:\/\/en.wikipedia.org\/wiki\/Stirling_numbers_of_the_second_kind#Recurrence_relation\">\nWikipedia did it for us<\/a>.\nGo read that first.\nIf you didn&#8217;t follow Wikipedia&#8217;s explanation, here&#8217;s another angle:\n<\/p>\n<p>\nSuppose you have a set of <var>n<\/var> elements,\nand you want to generate all the partitions into\n<var>k<\/var> blocks.\nWell, let&#8217;s look at element <var>n<\/var>.\nWhat happens when you delete it from the partition?\n<\/p>\n<p>\nOne possibility is that\n<var>n<\/var> was in a block all by itself.\nAfter you remove it,\nyou are left with a partition of <var>n<\/var> &minus; 1\nelements into\n<var>k<\/var> &minus; 1 blocks.\nTherefore, to generate the partitions where\n<var>n<\/var> is in a block all by itself,\nyou generate all the partitions of\n<var>n<\/var> &minus; 1\nelements into\n<var>k<\/var> &minus; 1 blocks,\nand then tack on a\nsingle block consisting of just element\n<var>n<\/var>.\n<\/p>\n<p>\nOn the other hand, if element <var>n<\/var> was not in a block by itself,\nthen removing it leaves a partition of\n<var>n<\/var> &minus; 1\nelements into\n<var>k<\/var> blocks.\n(Removing\n<var>n<\/var>\ndid not decrease the number of blocks because there are still other\nnumbers keeping that block alive.)\nNow, element\n<var>n<\/var> could have belonged to any of the\n<var>k<\/var> blocks,\nso you have\n<var>k<\/var> possible places where you could reinsert element\n<var>n<\/var>.\n<\/p>\n<p>\nTherefore, our algorithm goes like this:\n<\/p>\n<ul>\n<li>Handle base cases.\n<li>Otherwise,\n<ul>\n<li>Recursively call\n    <var>S<\/var>(<var>n<\/var> &minus; 1,\n    <var>k<\/var>) and add\n    element <var>n<\/var> separately into each of the <var>k<\/var> blocks.<\/p>\n<li>Recursively call\n    <var>S<\/var>(<var>n<\/var> &minus; 1,\n    <var>k<\/var> &minus; 1) and add\n    a single block consisting of just\n    <var>n<\/var>.\n<\/ul>\n<\/ul>\n<p>\nNow that we spelled out what we&#8217;re going to do,\nactually doing it is a bit anticlimactic.\n<\/p>\n<pre>\nfunction Stirling(n, k, f) {\n if (n == 0 &amp;&amp; k == 0) { f([]); return; }\n if (n == 0 || k == 0) { return; }\n Stirling(n-1, k-1, function(s) {\n  f(s.concat([[n]])); \/\/ append [n] to the array\n });\n Stirling(n-1, k, function(s) {\n  for (var i = 0; i &lt; k; i++) {\n   f(s.map(function(t, j) { \/\/ append n to the i'th subarray\n    return t.concat(i == j ? n : []);\n   }));\n  }\n });\n}\n<\/pre>\n<p>\nYou can test out this function by logging\nthe results to the console.\n<\/p>\n<pre>\nfunction logToConsole(s) {\n  console.log(JSON.stringify(s));\n}\nStirling(4, 2, logToConsole);\n<\/pre>\n<p>\nLet&#8217;s walk through the function.\nThe first test catches the vacuous base\ncase where you say,\n&#8220;Please show me all the ways of breaking\nup nothing into zero blocks.&#8221;\nThe answer is, &#8220;There is exactly one way\nof doing this, which is to break it into\nzero blocks.&#8221;\nMath is cute that way.\n<\/p>\n<p>\nThe second test catches the other base cases\nwhere you say,\n&#8220;Please show me all the ways of breaking up\n<code>n<\/code> elements into zero blocks&#8221;\n(can&#8217;t be done if <code>n &gt; 0<\/code>, because you will always\nhave elements left over),\nor you say,\n&#8220;Please show me all the ways of breaking up\n0 elements into <code>k<\/code> blocks&#8221;\n(which also can&#8217;t be done if <code>k &gt; 0<\/code>\nbecause\nthere are no elements to put in the\nfirst block).\n<\/p>\n<p>\nAfter disposing of the base cases,\nwe get to the meat of the recurrence.\nFirst, we ask for all the ways of\nbreaking\n<code>n - 1<\/code> elements\ninto\n<code>k - 1<\/code> blocks,\nand for each of them, we add\na single block consisting of just <code>n<\/code>.\n<\/p>\n<p>\nNext, we ask for all the ways of breaking\n<code>n - 1<\/code> elements\ninto\n<code>k<\/code> blocks,\nand for each of them, we go into a loop\nadding <code>n<\/code> to each block.\nThe goofy <code>map<\/code> creates a deep copy of the\narray and adds <code>n<\/code> to the <code>i<\/code>th block.\n<\/p>\n<p>\nHere&#8217;s a walkthrough of the goofy <code>map<\/code>:\n<\/p>\n<ul>\n<li>The <code>concat<\/code> method creates a new array consisting\n    of the starting array with the <code>concat<\/code> parameters\n    added at the end.\n    If a parameter is an array, then its elements are added;\n    otherwise the parameter itself is added.\n    For example,\n    <code>[1].concat(2, [3, 4])<\/code> returns\n    <code>[1, 2, 3, 4]<\/code>.\n    The <code>concat<\/code> method creates a new array,\n    and a common idiom is\n    <code>s.concat()<\/code> to make a shallow copy of an array.<\/p>\n<li>The <code>map<\/code> method calls the provided callback once\n    for each element of the array <code>s<\/code>.\n    The return values from all the callbacks are collected to\n    form a new array, which is returned.\n    For example, <code>[1,2,3].map(function (v) { return v * 2; })<\/code>\n    returns the new array <code>[2, 4, 6]<\/code>.<\/p>\n<li>The <code>map<\/code> callback is called with the subarray\n    as the first parameter and the index as the second parameter.\n    (There is also a third parameter, which we don&#8217;t use.)<\/p>\n<li>Therefore, if all we want to do was\n    create a deep copy of <code>s<\/code>,\n    we could write\n    <code>s.map(function (t, j) { return t.concat(); })<\/code>.<\/p>\n<li>But we don&#8217;t want a perfect deep copy.\n    We want to change the <code>i<\/code>th element.\n    Therefore, we check the index, and if it is equal to the <code>i<\/code>,\n    then we append <code>n<\/code>.\n    Otherwise, we append <code>[]<\/code> which appends nothing.<\/p>\n<li>After building the array (with modifications),\n    we pass it to the callback function <code>f<\/code>.\n<\/ul>\n<p>\nThis pattern is common enough that maybe we should pull it into\na helper function.\n<\/p>\n<pre>\nfunction copyArrayOfArrays(array, indexToEdit, editor) {\n return array.map(function(e, i) {\n  return i === indexToEdit ? editor(e) : e.concat();\n });\n}\nfunction Stirling(n, k, f) {\n if (n == 0 &amp;&amp; k == 0) { f([]); return; }\n if (n == 0 || k == 0) { return; }\n Stirling(n-1, k-1, function(s) {\n  f(s.concat([[n]])); \/\/ append [n] to the array\n });\n Stirling(n-1, k, function(s) {\n  for (var i = 0; i &lt; k; i++) {\n   f(copyArrayOfArrays(s, i, function(e) { return e.concat(n); }));\n  }\n });\n}\n<\/pre>\n<p>\nThe <code>copy&shy;Array&shy;Of&shy;Arrays<\/code>\nfunction abstracts the goofy <code>map<\/code>:\nYou give it an array of arrays,\nand optionally an index to edit and the function that\ndoes the editing.\nIt copies the array of arrays and calls your editor on the\nelement you want to edit.\n<\/p>\n<p>\nTo reduce the number of memory allocations,\nthe recursion could also be done destructively.\nYou&#8217;re then counting on the callback not modifying the result,\nsince you&#8217;re going to use it again.\n<\/p>\n<pre>\nfunction Stirling(n, k, f) {\n if (n == 0 &amp;&amp; k == 0) { f([]); return; }\n if (n == 0 || k == 0) { return; }\n Stirling(n-1, k, function(s) {\n  for (var i = 0; i &lt; k; i++) {\n   <font COLOR=\"blue\">s[i].push(n);\n   f(s);\n   s[i].pop();<\/font>\n  }\n });\n Stirling(n-1, k-1, function(s) {\n  <font COLOR=\"blue\">s.push([n]);\n  f(s);\n  s.pop();<\/font>\n });\n}\n<\/pre>\n<\/p>\n<p>\nThe original question was about enumerating all partitions\n(Bell numbers),\nand that&#8217;s easy to put together from the Stirling numbers.\n<\/p>\n<pre>\nfunction Bell(n, f) {\n for (var i = 1; i &lt;= n; i++) {\n  Stirling(n, i, f);\n }\n}\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Just for fun, today&#8217;s Little Program is going to generate set partitions. (Why? Because back in 2005, somebody asked about it on an informal mailing list, suggesting it would be an interesting puzzle, and now I finally got around to solving it.) The person who asked the question said, Below we show the partitions of [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-1413","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Just for fun, today&#8217;s Little Program is going to generate set partitions. (Why? Because back in 2005, somebody asked about it on an informal mailing list, suggesting it would be an interesting puzzle, and now I finally got around to solving it.) The person who asked the question said, Below we show the partitions of [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/1413","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=1413"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/1413\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=1413"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=1413"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=1413"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}