SundanceCombinatorialUtils.cpp
Go to the documentation of this file.
00001 #include "SundanceCombinatorialUtils.hpp"
00002 #include "SundanceExceptions.hpp"
00003 #include "SundanceTabs.hpp"
00004 #include <algorithm>
00005 #include <iterator>
00006 #include <iostream>
00007 
00008 
00009 namespace Sundance
00010 {
00011 using namespace Teuchos;
00012 
00013 Array<Array<int> > partitionInteger(int n)
00014 {
00015   typedef Array<int> Aint;
00016   typedef Array<Array<int> > AAint;
00017   static Array<Array<Array<int> > > rtn =
00018     tuple<AAint>(
00019       tuple<Aint>(tuple(1)), 
00020       tuple<Aint>(tuple(2), tuple(1, 1)),
00021       tuple<Aint>(tuple(3), tuple(2, 1), tuple(1, 1, 1)),
00022       tuple<Aint>(tuple(4), tuple(3, 1), tuple(2, 2), tuple(2, 1, 1), tuple(1,1,1,1)));
00023   TEST_FOR_EXCEPTION(n<1 || n>4, RuntimeError, 
00024     "case n=" << n << " not implemented in partitionInteger()");
00025   return rtn[n-1];
00026 }
00027 
00028 
00029 
00030   
00031 
00032 
00033 Array<Array<Array<int> > > compositions(int n)
00034 {
00035   Array<Array<Array<int> > > q(n);
00036 
00037   Array<Array<int> > x = partitionInteger(n);
00038 
00039   Array<Array<int> > p;
00040   for (int m=0; m<x.size(); m++)
00041   {
00042     Array<int> tmp;
00043     Array<int> y = x[m];
00044     std::sort(y.begin(), y.end());
00045     tmp.resize(y.size());
00046     std::copy(y.begin(), y.end(), tmp.begin());
00047     p.append(tmp);
00048     while (std::next_permutation(y.begin(), y.end())) 
00049     { 
00050       tmp.resize(y.size());
00051       std::copy(y.begin(), y.end(), tmp.begin());
00052       p.append(tmp);
00053     }
00054   }
00055 
00056   for (int i=0; i<p.size(); i++)
00057   {
00058     q[p[i].size()-1].append(p[i]);
00059   }
00060 
00061   return q;
00062 }
00063 
00064 Array<Array<int> > nonNegCompositions(int n, int J)
00065 {
00066   /* find all partitions */
00067   Array<Array<int> > parts = partitionInteger(n);
00068     
00069   /* find the partitions into J or fewer terms */
00070   Array<Array<int> > jParts;
00071   for (int i=0; i<parts.size(); i++)
00072   {
00073     if (parts[i].size() <= J) jParts.append(parts[i]);
00074   }
00075 
00076   /* Pad with zeros until all remaining partitions have size=J */
00077   for (int i=0; i<jParts.size(); i++)
00078   {
00079     for (int j=jParts[i].size(); j<J; j++)
00080     {
00081       jParts[i].append(0);
00082     }
00083   }
00084 
00085   /* form all permutations */
00086   Array<Array<int> > all;
00087   for (int i=0; i<jParts.size(); i++)
00088   {
00089     Array<int> tmp;
00090     Array<int> y = jParts[i];
00091     std::sort(y.begin(), y.end());
00092     tmp.resize(y.size());
00093     std::copy(y.begin(), y.end(), tmp.begin());
00094     all.append(tmp);
00095     while (std::next_permutation(y.begin(), y.end())) 
00096     { 
00097       tmp.resize(y.size());
00098       std::copy(y.begin(), y.end(), tmp.begin());
00099       all.append(tmp);
00100     }
00101   }
00102 
00103   return all;
00104 }
00105 
00106 
00107   
00108 Set<Pair<MultiSet<int> > >
00109 loadPartitions(int x, int n, 
00110   const MultiSet<int>& left, 
00111   const MultiSet<int>& right)
00112 {
00113   Set<Pair<MultiSet<int> > > rtn;
00114   for (int i=0; i<n; i++)
00115   {
00116     MultiSet<int> L = left;
00117     MultiSet<int> R = right;
00118 
00119     for (int j=0; j<n; j++) 
00120     {
00121       if (j < i) L.put(x);
00122       else R.put(x);
00123     }
00124     rtn.put(Pair<MultiSet<int> >(L, R));
00125     rtn.put(Pair<MultiSet<int> >(R, L));
00126   }
00127   return rtn;
00128 }
00129 
00130 
00131 Set<Pair<MultiSet<int> > >
00132 binaryPartition(const MultiSet<int>& m)
00133 {
00134   Set<Pair<MultiSet<int> > > tmp1;
00135 
00136 
00137   Map<int, int> counts = countMap(m);
00138     
00139   for (Map<int, int>::const_iterator 
00140          i=counts.begin(); i!=counts.end(); i++)
00141   {
00142     int x = i->first;
00143     int n = i->second;
00144     if (tmp1.size()==0)
00145     {
00146       MultiSet<int> L;
00147       MultiSet<int> R;
00148       tmp1 = loadPartitions(x, n, L, R);
00149     }
00150     else
00151     {
00152       Set<Pair<MultiSet<int> > > tmp2;
00153       for (Set<Pair<MultiSet<int> > >::const_iterator
00154              j=tmp1.begin(); j!=tmp1.end(); j++)
00155       {
00156         MultiSet<int> L = j->first();
00157         MultiSet<int> R = j->second();
00158         Set<Pair<MultiSet<int> > > t 
00159           = loadPartitions(x, n, L, R);
00160         tmp2.merge(t);
00161       }
00162       tmp1 = tmp2;
00163     }
00164   }
00165 
00166 #ifdef BLAH
00167   Set<SortedPair<MultiSet<int> > > rtn;
00168   for (Set<Pair<MultiSet<int> > >::const_iterator
00169          j=tmp1.begin(); j!=tmp1.end(); j++)
00170   {
00171     rtn.put(SortedPair<MultiSet<int> >(j->first(), j->second()));
00172   }
00173 #endif
00174 
00175     
00176   return tmp1;
00177 }
00178 
00179 
00180 
00181 Set<MultiSet<MultiSet<int> > >
00182 multisetPartitions(const MultiSet<int>& m)
00183 {
00184   Set<MultiSet<MultiSet<int> > > rtn;
00185   int mSize = m.size();
00186   if (m.size()==0) return rtn;
00187   if (m.size()==1) return makeSet(makeMultiSet(m));
00188   rtn.put(makeMultiSet(m));
00189 
00190   Set<Pair<MultiSet<int> > > 
00191     twoParts = binaryPartition(m);
00192 
00193   for (Set<Pair<MultiSet<int> > >::const_iterator 
00194          i=twoParts.begin(); i!=twoParts.end(); i++)
00195   {
00196     MultiSet<int> L = i->first();
00197     MultiSet<int> R = i->second();
00198     if ((int) L.size() == mSize || (int) R.size() == mSize) continue;
00199     if ((int) L.size() > 0 && (int) R.size() > 0) rtn.put(makeMultiSet(L, R));
00200 
00201     Array<MultiSet<MultiSet<int> > > lParts;
00202     Array<MultiSet<MultiSet<int> > > rParts;
00203     if (L.size() > 0)
00204     {
00205       lParts = multisetPartitions(L).elements();
00206     }
00207     if (R.size() > 0)
00208     {
00209       rParts = multisetPartitions(R).elements();
00210     }
00211     for (int j=0; j<lParts.size(); j++)
00212     {
00213       for (int k=0; k<rParts.size(); k++)
00214       {
00215         const MultiSet<MultiSet<int> >& a = lParts[j];
00216         const MultiSet<MultiSet<int> >& b = rParts[k];
00217         MultiSet<MultiSet<int> > combined;
00218         for (MultiSet<MultiSet<int> >::const_iterator 
00219                x=a.begin(); x!=a.end(); x++)
00220         {
00221           combined.put(*x);
00222         }
00223         for (MultiSet<MultiSet<int> >::const_iterator 
00224                x=b.begin(); x!=b.end(); x++)
00225         {
00226           combined.put(*x);
00227         }
00228         rtn.put(combined);
00229       }
00230     }
00231   }
00232   return rtn;
00233 }
00234 
00235 
00236 Map<int, int> countMap(const MultiSet<int>& m)
00237 {
00238   Map<int, int> rtn;
00239   for (MultiSet<int>::const_iterator i=m.begin(); i!=m.end(); i++)
00240   {
00241     if (rtn.containsKey(*i)) rtn[*i]++;
00242     else rtn.put(*i, 1);
00243   }
00244   return rtn;
00245 }
00246 
00247 
00248 Array<Array<int> > indexCombinations(const Array<int>& s)
00249 {
00250 
00251   Array<int> D(s.size(), 0);
00252   Array<int> C(s.size(), -1);
00253 
00254   int p=1;
00255   for (int k=1; k<=s.size(); k++)
00256   {
00257     D[s.size()-k] = p;
00258     p = p*s[s.size() - k];
00259   }
00260   Array<Array<int> > rtn(p);
00261 
00262   for (int i=0; i<p; i++)
00263   {
00264     for (int j=0; j<s.size(); j++)
00265     {
00266       if ( (i % D[j])==0 )
00267       {
00268         C[j] = (C[j]+1) % s[j];
00269       }
00270     }
00271     rtn[i] = C;
00272   }
00273   return rtn;
00274 }
00275 
00276 
00277 Array<Array<Array<int> > > binnings(const MultiSet<int>& mu, int n)
00278 {
00279   int N = mu.size();
00280   Array<Array<int> > c = compositions(N)[n-1];
00281   Array<Array<Array<int> > > rtn;
00282 
00283   for (int i=0; i<c.size(); i++)
00284   {
00285     Array<Array<Array<int> > > a = indexArrangements(mu, c[i]);
00286     for (int j=0; j<a.size(); j++)
00287     {
00288       rtn.append(a[j]);
00289     }
00290   }
00291   return rtn;
00292 }
00293 
00294 
00295 
00296 Array<Array<Array<int> > > indexArrangements(const MultiSet<int>& mu,
00297   const Array<int> & k) 
00298 {
00299   int nBins = k.size();
00300     
00301   int M = 0;
00302   for (int i=0; i<nBins; i++)
00303   {
00304     M += k[i];
00305   }
00306 
00307   Array<int> I;
00308   for (MultiSet<int>::const_iterator iter=mu.begin(); iter!=mu.end(); iter++)
00309   {
00310     I.append(*iter);
00311   }
00312 
00313   Array<Array<Array<int> > > rtn;
00314     
00315   do
00316   {
00317     Array<Array<int> > bins(nBins);
00318     int count = 0;
00319     for (int i=0; i<nBins; i++)
00320     {
00321       for (int j=0; j<k[i]; j++)
00322       {
00323         bins[i].append(I[count++]);
00324       }
00325     }
00326     rtn.append(bins);
00327   }
00328   while (std::next_permutation(I.begin(), I.end()));
00329   return rtn;
00330     
00331 }
00332 
00333 
00334 Set<MultiSet<int> > multisetSubsets(const MultiSet<int>& x)
00335 {
00336   /* We'll generate the subsets by traversing them in bitwise order.
00337    * For a multiset having N elements, there are up to 2^N subsets each
00338    * of which can be described by a N-bit number with the i-th
00339    * bit indicating whether the i-th element is in the subset. Note that
00340    * with a multiset, repetitions can occur so we need to record the
00341    * results in a Set object to eliminate duplicates. 
00342    */
00343 
00344   /* Make an indexable array of the elements. This will be convenient
00345    * because we'll need to access the i-th element after reading
00346    * the i-th bit. */
00347   Array<int> elements = x.elements();
00348 
00349   /* Compute the maximum number of subsets. This number will be reached
00350    * only in the case of no repetitions. */
00351   int n = elements.size();
00352   int maxNumSubsets = pow2(n);
00353     
00354   Set<MultiSet<int> > rtn;
00355     
00356     
00357   /* Loop over subsets in bitwise order. We start the count at 1 
00358      to avoid including the empty subset */
00359   for (int i=1; i<maxNumSubsets; i++)
00360   {
00361     Array<int> bits = bitsOfAnInteger(i, n);
00362     MultiSet<int> ms;
00363     for (int j=0; j<n; j++) 
00364     {
00365       if (bits[j] == 1) ms.put(elements[j]);
00366     }
00367     rtn.put(ms);
00368   }
00369   return rtn;
00370 }
00371 
00372 
00373 Array<Array<MultiSet<int> > > multisetCompositions(int s,
00374   const MultiSet<int>& x)
00375 {
00376   Set<MultiSet<MultiSet<int> > > parts = multisetPartitions(x);
00377 
00378   Array<Array<MultiSet<int> > > rtn;
00379 
00380   typedef Set<MultiSet<MultiSet<int> > >::const_iterator iter;
00381   for (iter i=parts.begin(); i!=parts.end(); i++)
00382   {
00383     if ((int) i->size()!=s) continue;
00384     Array<MultiSet<int> > y = i->elements();
00385     Array<MultiSet<int> > tmp(y.size());
00386     std::sort(y.begin(), y.end());
00387     std::copy(y.begin(), y.end(), tmp.begin());
00388     rtn.append(tmp);
00389     while (std::next_permutation(y.begin(), y.end())) 
00390     { 
00391       tmp.resize(y.size());
00392       std::copy(y.begin(), y.end(), tmp.begin());
00393       rtn.append(tmp);
00394     }
00395   }
00396   return rtn;
00397 }
00398 
00399 Array<Array<int> > distinctIndexTuples(int m, int n)
00400 {
00401   Array<Array<int> > rtn;
00402   Array<int> cur(m);
00403   for (int i=0; i<m; i++) cur[i] = i;
00404   if (m==1) 
00405   {
00406     for (int i=0; i<n; i++) rtn.append(tuple(i));
00407     return rtn;
00408   }
00409 
00410   while(cur[0] < (n-m)+1)
00411   {
00412     rtn.append(cur);
00413     for (int i=(m-1); i>=0; i--)
00414     {
00415       if (cur[i] < (n-1)) 
00416       {
00417         cur[i]++;
00418         bool overflow = false;
00419         for (int j=i+1; j<m; j++) 
00420         {
00421           cur[j] = cur[j-1]+1;
00422           if (cur[j] >= n) overflow = true;
00423         }
00424         if (overflow) continue;
00425         else break;
00426       }
00427     }
00428   }
00429   return rtn;
00430 }
00431   
00432 Array<int> bitsOfAnInteger(int x, int n)
00433 {
00434   TEST_FOR_EXCEPTION(x >= pow2(n), InternalError,
00435     "Invalid input to bitsOfAnIteger");
00436                      
00437   Array<int> rtn(n);
00438     
00439   int r = x;
00440   for (int b=n-1; b>=0; b--)
00441   {
00442     rtn[b] = r/pow2(b);
00443     r = r - rtn[b]*pow2(b);
00444   }
00445   return rtn;
00446 }
00447 
00448 
00449 
00450 
00451 
00452 int pow2(int n)
00453 {
00454   static Array<int> p2(1,1);
00455 
00456   if ((int) n >= p2.size())
00457   {
00458     int oldN = p2.size(); 
00459     for (int i=oldN; i<=n; i++) p2.push_back(p2[i-1]*2);
00460   }
00461     
00462   return p2[n];
00463 }
00464 }
00465 
00466 
00467 
00468   
00469 
00470 
00471 
00472 
00473 

Site Contact