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
00067 Array<Array<int> > parts = partitionInteger(n);
00068
00069
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
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
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
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 Array<int> elements = x.elements();
00348
00349
00350
00351 int n = elements.size();
00352 int maxNumSubsets = pow2(n);
00353
00354 Set<MultiSet<int> > rtn;
00355
00356
00357
00358
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