Advertisement
mate2code

Partitions of multisets (oeis.org/A249620)

Nov 22nd, 2014
986
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 6.80 KB | None | 0 0
  1. <?php
  2.  
  3. // en.wikiversity.org/wiki/Partitions_of_multisets
  4. // oeis.org/A249620
  5.  
  6. // Rather quick and dirty script to create the partitions of multisets with up to 8 elements.
  7. // The essential steps are the creation of the partitions of {1..n} from the values in oeis.org/A231428,
  8. // the replacement of 1..n with the elements of the multiset using preg_replace
  9. // and the removal of redundant rows in the new array.
  10. // There are certainly better ways to do this.
  11. // Tilman Piesk, November 2014
  12.  
  13.  
  14. // the numbers n and k determine the output
  15. // n is the number of elements in the multiset, and k its signature
  16. $n = 5;  // values between 1 and 8
  17. $k = 3;  // values between 0 and $partnum[$n]-1
  18.  
  19. // the numbers of partitions of n (oeis.org/A000041)
  20. $partnum = array(1, 1, 2, 3, 5, 7, 11, 15, 22);
  21.  
  22. // the partitions of an 8-element set (oeis.org/A231428)
  23. // $setpartsDec = array(0,1,2,4,7,8,12,16,18,25,32,33,42,52,63,64,68,80,96,116,128,130,136,160...268435455);
  24.  
  25. // non-one addends of the partitions of 8 in the order defined by oeis.org/A194602
  26. $intparts = array(
  27.     array(),
  28.     array(2),
  29.     array(3),
  30.     array(2, 2),
  31.     array(4),
  32.     array(3, 2),
  33.     array(5),
  34.     array(2, 2, 2),
  35.     array(4, 2),
  36.     array(3, 3),
  37.     array(6),
  38.     array(3, 2, 2),
  39.     array(5, 2),
  40.     array(4, 3),
  41.     array(7),
  42.     array(2, 2, 2, 2),
  43.     array(4, 2, 2),
  44.     array(3, 3, 2),
  45.     array(6, 2),
  46.     array(5, 3),
  47.     array(4, 4),
  48.     array(8)
  49. );
  50.  
  51.  
  52. // $setparts will contain the set partitions in this form: https://oeis.org/A231428/a231428.txt
  53. $setparts = array();
  54.  
  55. // the binary digits go from $setpartBin to $setpartMat using these coordinates
  56. $coord = array(
  57.     array(1,0),
  58.     array(2,0),array(2,1),
  59.     array(3,0),array(3,1),array(3,2),
  60.     array(4,0),array(4,1),array(4,2),array(4,3),
  61.     array(5,0),array(5,1),array(5,2),array(5,3),array(5,4),
  62.     array(6,0),array(6,1),array(6,2),array(6,3),array(6,4),array(6,5),
  63.     array(7,0),array(7,1),array(7,2),array(7,3),array(7,4),array(7,5),array(7,6)
  64. );
  65.  
  66. for ($a=0; $a<4140; $a++) {
  67.  
  68.     // decimal from A231428 to binary string
  69.     $setpartBin = strrev(decbin($setpartsDec[$a]));
  70.  
  71.     // this is going to be the equivalence relation matrix of the set partition
  72.     $setpartMat = array(
  73.         array(1, 0, 0, 0, 0, 0, 0, 0),
  74.         array(0, 1, 0, 0, 0, 0, 0, 0),
  75.         array(0, 0, 1, 0, 0, 0, 0, 0),
  76.         array(0, 0, 0, 1, 0, 0, 0, 0),
  77.         array(0, 0, 0, 0, 1, 0, 0, 0),
  78.         array(0, 0, 0, 0, 0, 1, 0, 0),
  79.         array(0, 0, 0, 0, 0, 0, 1, 0),
  80.         array(0, 0, 0, 0, 0, 0, 0, 1)
  81.     );
  82.  
  83.     // get the 1s from $setpartBin and put them in $setpartMat
  84.     for ($b = 0; $b < strlen($setpartBin); $b++) {
  85.         if ($setpartBin[$b] == '1') {
  86.             $i = $coord[$b][0];
  87.             $j = $coord[$b][1];
  88.             $setpartMat[$i][$j] = 1;
  89.             $setpartMat[$j][$i] = 1;
  90.         }
  91.     }
  92.  
  93.     // remove redundant rows from $setpartMat
  94.     $setpartMat = array_unique($setpartMat, SORT_REGULAR);
  95.  
  96.     $blocks = array();
  97.  
  98.     foreach ($setpartMat as $matrow) {
  99.         $block = array();
  100.         for ($b = 0; $b < 8; $b++) {
  101.             if ($matrow[$b] == 1) {
  102.                 array_push($block, $b + 1);  // the elements are numbered from 1
  103.             }
  104.         }
  105.         if (count($block) > 1) {  // only non-singleton blocks shall be shown
  106.             array_push($blocks, $block);
  107.         }
  108.     }
  109.  
  110.     array_push($setparts, $blocks);
  111.  
  112. }
  113. // $setparts is ready
  114.  
  115.  
  116. ////////////////////////////////////////////////////////////////////////////////////////////////
  117.  
  118.  
  119. // the numbers of partitions of n-sets (oeis.org/A000110)
  120. $bells = array(1, 1, 2, 5, 15, 52, 203, 877, 4140);
  121. $bell = $bells[$n];
  122.  
  123. // $setpartsBell is an array of the first $bell set partitions
  124. $setpartsBell = array_slice($setparts, 0, $bell);
  125.  
  126. foreach ($setpartsBell as $b => $setpart) {
  127.     $merge = array();
  128.     foreach ($setpart as $block) {
  129.         $merge = array_merge($merge, $block);
  130.     }
  131.     $singletons= array_diff( range(1, $n), $merge);
  132.     foreach ($singletons as $singleton) {
  133.         array_push($setpart, $singleton);
  134.     }
  135.     sort($setpart);
  136.     $setpartsBell[$b] = $setpart;
  137. }
  138. $setpartsBellStr = var_export($setpartsBell, true);
  139. $setpartsBellStr = preg_replace('/\s/', '', $setpartsBellStr);  // remove white space
  140. $setpartsBellStr = preg_replace('/\d+=>/', '', $setpartsBellStr);  // remove indices
  141.  
  142.  
  143. // the signature of the multiset is the $k-th element of $intparts
  144. // it is in the form $intpartAddends = array(3,2) and must be transformed in the form $intpartMultiset = 1,1,1,2,2,3,4,5 (lengh $n)
  145. $intpartAddends = $intparts[$k];
  146. $intpartMultiset = array();
  147. $count = 1;
  148. foreach($intpartAddends as $addend) {
  149.     for ($i=1; $i<=$addend; $i++) {
  150.         array_push($intpartMultiset, $count);
  151.     }
  152.     $count++;
  153. }
  154. // elements for the non-one addends must be added to get length $n
  155. while (count($intpartMultiset)<$n) {
  156.     array_push($intpartMultiset, $count++);
  157. }
  158.  
  159.  
  160. // $setpartsBellStr is $setpartsBell as a string, i.e. it is an array that contains partitions of the set {1..n}
  161. // now the numbers 1..n shall be replaced by the corresponding elements of $intpartMultiset to get the partitions of the multiset
  162. $count = 1;
  163. foreach ($intpartMultiset as $val) {
  164.     $setpartsBellStr = preg_replace("/$count/", "$val", $setpartsBellStr);
  165.     $count++;
  166. }
  167.  
  168. // create the array of partitions of the multiset from the manipulated string
  169. eval( '$multisetparts =' . $setpartsBellStr . ';' );
  170.  
  171. // remove redundant partitions
  172. foreach ($multisetparts as $key => $val) {
  173.     $derp = $val;
  174.     sort($derp);
  175.     $multisetparts[$key] = $derp;
  176. }
  177.  
  178. sort($multisetparts);
  179. $multisetparts = array_map("unserialize", array_unique(array_map("serialize", $multisetparts)));
  180.  
  181.  
  182. ////////////////////////////////////////////////////////////////////////////////////////////////
  183.  
  184.  
  185. // print the content of $multisetparts on the screen
  186. // for n=5 and k=3 this looks like http://pastebin.com/g5AJBRgT
  187. $outputStr = "elements in multiset: $n         integer partition: $k (" . implode('+',$intpartAddends);
  188. if (array_sum($intpartAddends)<$n) {
  189.     if ($k==0) {
  190.         $outputStr .= '1' . str_repeat('+1', $n - array_sum($intpartAddends) - 1);
  191.     } else {
  192.         $outputStr .= str_repeat('+1', $n - array_sum($intpartAddends));
  193.     }
  194. }
  195. $outputStr .= ")\n\n";
  196.  
  197. $i = 1;
  198. $mspLen = count($multisetparts);
  199. $strPadLen = strlen((string)($mspLen));
  200. foreach ($multisetparts as $part) {
  201.     $outputStr .= str_pad($i, $strPadLen, ' ', STR_PAD_LEFT) . ':    ';
  202.     $partLen = count($part);
  203.     foreach ($part as $block) {
  204.         if (!is_array($block)) {
  205.             $block = array($block);
  206.         }
  207.         $outputStr .= '{ ' . implode(' ', $block) . ' }';
  208.     }
  209.     if ($i < $mspLen) {
  210.         $outputStr .= "\n";
  211.     }
  212.     $i++;
  213. }
  214.  
  215. echo $outputStr;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement