00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "SundanceCombinatorialUtils.hpp"
00044 #include "SundanceIntVec.hpp"
00045 #include "PlayaExceptions.hpp"
00046 #include "PlayaTabs.hpp"
00047 #include "SundanceOut.hpp"
00048 #include <algorithm>
00049 #include <iterator>
00050 #include <iostream>
00051
00052
00053 namespace Sundance
00054 {
00055 using namespace Teuchos;
00056 using std::endl;
00057
00058 Array<Array<int> > partitionInteger(int n)
00059 {
00060 typedef Array<int> Aint;
00061 typedef Array<Array<int> > AAint;
00062 static Array<Array<Array<int> > > rtn =
00063 tuple<AAint>(
00064 tuple<Aint>(tuple(1)),
00065 tuple<Aint>(tuple(2), tuple(1, 1)),
00066 tuple<Aint>(
00067 tuple(3),
00068 tuple(2, 1),
00069 tuple(1, 1, 1)),
00070 tuple<Aint>(
00071 tuple(4),
00072 tuple(3, 1),
00073 tuple(2, 2),
00074 tuple(2, 1, 1),
00075 tuple(1,1,1,1)),
00076 tuple<Aint>(
00077 tuple(5),
00078 tuple(4, 1),
00079 tuple(3, 2),
00080 tuple(3, 1, 1),
00081 tuple(2, 2, 1),
00082 tuple(2, 1, 1, 1),
00083 tuple(1, 1, 1, 1, 1)
00084 ));
00085 TEUCHOS_TEST_FOR_EXCEPTION(n<1 || n>5, std::runtime_error,
00086 "case n=" << n << " not implemented in partitionInteger()");
00087 return rtn[n-1];
00088 }
00089
00090
00091 bool nextNum(Array<int>& digits, const Array<int>& radix)
00092 {
00093
00094 int n = digits.size();
00095 int j = n-1;
00096 while(j >= 0)
00097 {
00098 if (digits[j]==(radix[j]-1))
00099 {
00100 digits[j] = 0;
00101 j--;
00102 }
00103 else
00104 {
00105 digits[j]++;
00106 return true;
00107 }
00108 }
00109 return false;
00110 }
00111
00112 void weightedPartitions(int n, const Array<int>& w,
00113 Array<Array<int> >& parts)
00114 {
00115 int S = w.size();
00116 for (int i=0; i<S; i++)
00117 {
00118 TEUCHOS_TEST_FOR_EXCEPT(w[i] <= 0);
00119 }
00120
00121 Array<Array<int> > trial(S);
00122 Array<int> radix(S);
00123 for (int i=0; i<S; i++)
00124 {
00125 trial[i].resize(n/w[i]+1);
00126 for (int j=0; j<trial[i].size(); j++)
00127 {
00128 trial[i][j] = j;
00129 }
00130 radix[i] = trial[i].size();
00131 }
00132
00133 bool workLeft = true;
00134 Array<int> index(S, 0);
00135 while (workLeft)
00136 {
00137 Array<int> vals(S);
00138 int count = 0;
00139 for (int i=0; i<S; i++)
00140 {
00141 vals[i] = trial[i][index[i]];
00142 count += w[i]*vals[i];
00143 }
00144 if (count==n)
00145 {
00146 parts.append(vals);
00147 }
00148 workLeft = nextNum(index, radix);
00149 }
00150 }
00151
00152 void weightedOrderedPartitions(const IntVec& v, const Array<int>& w,
00153 Array<Array<IntVec> >& parts)
00154 {
00155 int D = v.size();
00156 int S = w.size();
00157 Array<int> radix(D);
00158
00159 Array<Array<Array<int> > > nParts(D);
00160 for (int i=0; i<D; i++)
00161 {
00162 weightedPartitions(v[i], w, nParts[i]);
00163 radix[i] = nParts[i].size();
00164 if (radix[i]==0) radix[i] = 1;
00165 }
00166
00167 bool workLeft = true;
00168 Array<int> index(D, 0);
00169 while (workLeft)
00170 {
00171 Array<IntVec> L(S, D);
00172 for (int i=0; i<D; i++)
00173 {
00174 for (int j=0; j<S; j++)
00175 {
00176 if (nParts[i].size()==0) L[i][j] = 0;
00177 else L[j][i] = nParts[i][index[i]][j];
00178 }
00179 }
00180
00181 bool accept = true;
00182 for (int i=0; i<S; i++)
00183 {
00184 if (L[i].abs()==0) {accept = false; break;}
00185 if (i>0 && !(L[i-1] < L[i])) {accept = false; break;}
00186 }
00187 if (accept)
00188 {
00189 parts.append(L);
00190 }
00191 workLeft = nextNum(index, radix);
00192 }
00193
00194 }
00195
00196
00197 void pSet(const IntVec& lambda, const IntVec& nu, int s,
00198 Array<Array<IntVec> >& K, Array<Array<IntVec> >& L)
00199 {
00200 Array<Array<IntVec> > KParts;
00201 lambda.getPartitions(s, KParts);
00202
00203 for (int i=0; i<KParts.size(); i++)
00204 {
00205 const Array<IntVec>& kPart = KParts[i];
00206 Array<int> w(s);
00207 for (int j=0; j<s; j++) w[j] = kPart[j].abs();
00208 Array<Array<IntVec> > LParts;
00209 weightedOrderedPartitions(nu, w, LParts);
00210 for (int j=0; j<LParts.size(); j++)
00211 {
00212 K.append(kPart);
00213 L.append(LParts[j]);
00214 }
00215 }
00216
00217 }
00218
00219
00220
00221 Array<Array<Array<int> > > compositions(int n)
00222 {
00223 Array<Array<Array<int> > > q(n);
00224
00225 Array<Array<int> > x = partitionInteger(n);
00226
00227 Array<Array<int> > p;
00228 for (int m=0; m<x.size(); m++)
00229 {
00230 Array<int> tmp;
00231 Array<int> y = x[m];
00232 std::sort(y.begin(), y.end());
00233 tmp.resize(y.size());
00234 std::copy(y.begin(), y.end(), tmp.begin());
00235 p.append(tmp);
00236 while (std::next_permutation(y.begin(), y.end()))
00237 {
00238 tmp.resize(y.size());
00239 std::copy(y.begin(), y.end(), tmp.begin());
00240 p.append(tmp);
00241 }
00242 }
00243
00244 for (int i=0; i<p.size(); i++)
00245 {
00246 q[p[i].size()-1].append(p[i]);
00247 }
00248
00249 return q;
00250 }
00251
00252 void restrictedCompositions(int n, int len, Array<Array<int> >& rComps)
00253 {
00254 rComps = nonNegCompositions(n, len);
00255 }
00256
00257 Array<Array<int> > nonNegCompositions(int n, int J)
00258 {
00259
00260 Array<Array<int> > parts = partitionInteger(n);
00261
00262
00263 Array<Array<int> > jParts;
00264 for (int i=0; i<parts.size(); i++)
00265 {
00266 if (parts[i].size() <= J) jParts.append(parts[i]);
00267 }
00268
00269
00270 for (int i=0; i<jParts.size(); i++)
00271 {
00272 for (int j=jParts[i].size(); j<J; j++)
00273 {
00274 jParts[i].append(0);
00275 }
00276 }
00277
00278
00279 Array<Array<int> > all;
00280 for (int i=0; i<jParts.size(); i++)
00281 {
00282 Array<int> tmp;
00283 Array<int> y = jParts[i];
00284 std::sort(y.begin(), y.end());
00285 tmp.resize(y.size());
00286 std::copy(y.begin(), y.end(), tmp.begin());
00287 all.append(tmp);
00288 while (std::next_permutation(y.begin(), y.end()))
00289 {
00290 tmp.resize(y.size());
00291 std::copy(y.begin(), y.end(), tmp.begin());
00292 all.append(tmp);
00293 }
00294 }
00295
00296 return all;
00297 }
00298
00299
00300
00301 Set<Pair<MultiSet<int> > >
00302 loadPartitions(int x, int n,
00303 const MultiSet<int>& left,
00304 const MultiSet<int>& right)
00305 {
00306 Set<Pair<MultiSet<int> > > rtn;
00307 for (int i=0; i<n; i++)
00308 {
00309 MultiSet<int> L = left;
00310 MultiSet<int> R = right;
00311
00312 for (int j=0; j<n; j++)
00313 {
00314 if (j < i) L.put(x);
00315 else R.put(x);
00316 }
00317 rtn.put(Pair<MultiSet<int> >(L, R));
00318 rtn.put(Pair<MultiSet<int> >(R, L));
00319 }
00320 return rtn;
00321 }
00322
00323
00324 Set<Pair<MultiSet<int> > >
00325 binaryPartition(const MultiSet<int>& m)
00326 {
00327 Set<Pair<MultiSet<int> > > tmp1;
00328
00329
00330 Map<int, int> counts = countMap(m);
00331
00332 for (Map<int, int>::const_iterator
00333 i=counts.begin(); i!=counts.end(); i++)
00334 {
00335 int x = i->first;
00336 int n = i->second;
00337 if (tmp1.size()==0)
00338 {
00339 MultiSet<int> L;
00340 MultiSet<int> R;
00341 tmp1 = loadPartitions(x, n, L, R);
00342 }
00343 else
00344 {
00345 Set<Pair<MultiSet<int> > > tmp2;
00346 for (Set<Pair<MultiSet<int> > >::const_iterator
00347 j=tmp1.begin(); j!=tmp1.end(); j++)
00348 {
00349 MultiSet<int> L = j->first();
00350 MultiSet<int> R = j->second();
00351 Set<Pair<MultiSet<int> > > t
00352 = loadPartitions(x, n, L, R);
00353 tmp2.merge(t);
00354 }
00355 tmp1 = tmp2;
00356 }
00357 }
00358
00359 #ifdef BLAH
00360 Set<SortedPair<MultiSet<int> > > rtn;
00361 for (Set<Pair<MultiSet<int> > >::const_iterator
00362 j=tmp1.begin(); j!=tmp1.end(); j++)
00363 {
00364 rtn.put(SortedPair<MultiSet<int> >(j->first(), j->second()));
00365 }
00366 #endif
00367
00368
00369 return tmp1;
00370 }
00371
00372
00373
00374 Set<MultiSet<MultiSet<int> > >
00375 multisetPartitions(const MultiSet<int>& m)
00376 {
00377 Set<MultiSet<MultiSet<int> > > rtn;
00378 int mSize = m.size();
00379 if (m.size()==0) return rtn;
00380 if (m.size()==1) return makeSet(makeMultiSet(m));
00381 rtn.put(makeMultiSet(m));
00382
00383 Set<Pair<MultiSet<int> > >
00384 twoParts = binaryPartition(m);
00385
00386 for (Set<Pair<MultiSet<int> > >::const_iterator
00387 i=twoParts.begin(); i!=twoParts.end(); i++)
00388 {
00389 MultiSet<int> L = i->first();
00390 MultiSet<int> R = i->second();
00391 if ((int) L.size() == mSize || (int) R.size() == mSize) continue;
00392 if ((int) L.size() > 0 && (int) R.size() > 0) rtn.put(makeMultiSet(L, R));
00393
00394 Array<MultiSet<MultiSet<int> > > lParts;
00395 Array<MultiSet<MultiSet<int> > > rParts;
00396 if (L.size() > 0)
00397 {
00398 lParts = multisetPartitions(L).elements();
00399 }
00400 if (R.size() > 0)
00401 {
00402 rParts = multisetPartitions(R).elements();
00403 }
00404 for (int j=0; j<lParts.size(); j++)
00405 {
00406 for (int k=0; k<rParts.size(); k++)
00407 {
00408 const MultiSet<MultiSet<int> >& a = lParts[j];
00409 const MultiSet<MultiSet<int> >& b = rParts[k];
00410 MultiSet<MultiSet<int> > combined;
00411 for (MultiSet<MultiSet<int> >::const_iterator
00412 x=a.begin(); x!=a.end(); x++)
00413 {
00414 combined.put(*x);
00415 }
00416 for (MultiSet<MultiSet<int> >::const_iterator
00417 x=b.begin(); x!=b.end(); x++)
00418 {
00419 combined.put(*x);
00420 }
00421 rtn.put(combined);
00422 }
00423 }
00424 }
00425 return rtn;
00426 }
00427
00428
00429 Map<int, int> countMap(const MultiSet<int>& m)
00430 {
00431 Map<int, int> rtn;
00432 for (MultiSet<int>::const_iterator i=m.begin(); i!=m.end(); i++)
00433 {
00434 if (rtn.containsKey(*i)) rtn[*i]++;
00435 else rtn.put(*i, 1);
00436 }
00437 return rtn;
00438 }
00439
00440
00441 Array<Array<int> > indexCombinations(const Array<int>& s)
00442 {
00443
00444 Array<int> D(s.size(), 0);
00445 Array<int> C(s.size(), -1);
00446
00447 int p=1;
00448 for (int k=1; k<=s.size(); k++)
00449 {
00450 D[s.size()-k] = p;
00451 p = p*s[s.size() - k];
00452 }
00453 Array<Array<int> > rtn(p);
00454
00455 for (int i=0; i<p; i++)
00456 {
00457 for (int j=0; j<s.size(); j++)
00458 {
00459 if ( (i % D[j])==0 )
00460 {
00461 C[j] = (C[j]+1) % s[j];
00462 }
00463 }
00464 rtn[i] = C;
00465 }
00466 return rtn;
00467 }
00468
00469
00470 Array<Array<Array<int> > > binnings(const MultiSet<int>& mu, int n)
00471 {
00472 int N = mu.size();
00473 Array<Array<int> > c = compositions(N)[n-1];
00474 Array<Array<Array<int> > > rtn;
00475
00476 for (int i=0; i<c.size(); i++)
00477 {
00478 Array<Array<Array<int> > > a = indexArrangements(mu, c[i]);
00479 for (int j=0; j<a.size(); j++)
00480 {
00481 rtn.append(a[j]);
00482 }
00483 }
00484 return rtn;
00485 }
00486
00487
00488
00489 Array<Array<Array<int> > > indexArrangements(const MultiSet<int>& mu,
00490 const Array<int> & k)
00491 {
00492 int nBins = k.size();
00493
00494 int M = 0;
00495 for (int i=0; i<nBins; i++)
00496 {
00497 M += k[i];
00498 }
00499
00500 Array<int> I;
00501 for (MultiSet<int>::const_iterator iter=mu.begin(); iter!=mu.end(); iter++)
00502 {
00503 I.append(*iter);
00504 }
00505
00506 Array<Array<Array<int> > > rtn;
00507
00508 do
00509 {
00510 Array<Array<int> > bins(nBins);
00511 int count = 0;
00512 for (int i=0; i<nBins; i++)
00513 {
00514 for (int j=0; j<k[i]; j++)
00515 {
00516 bins[i].append(I[count++]);
00517 }
00518 }
00519 rtn.append(bins);
00520 }
00521 while (std::next_permutation(I.begin(), I.end()));
00522 return rtn;
00523
00524 }
00525
00526
00527 Set<MultiSet<int> > multisetSubsets(const MultiSet<int>& x)
00528 {
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540 Array<int> elements = x.elements();
00541
00542
00543
00544 int n = elements.size();
00545 int maxNumSubsets = pow2(n);
00546
00547 Set<MultiSet<int> > rtn;
00548
00549
00550
00551
00552 for (int i=1; i<maxNumSubsets; i++)
00553 {
00554 Array<int> bits = bitsOfAnInteger(i, n);
00555 MultiSet<int> ms;
00556 for (int j=0; j<n; j++)
00557 {
00558 if (bits[j] == 1) ms.put(elements[j]);
00559 }
00560 rtn.put(ms);
00561 }
00562 return rtn;
00563 }
00564
00565
00566 Array<Array<MultiSet<int> > > multisetCompositions(int s,
00567 const MultiSet<int>& x)
00568 {
00569 Set<MultiSet<MultiSet<int> > > parts = multisetPartitions(x);
00570
00571 Array<Array<MultiSet<int> > > rtn;
00572
00573 typedef Set<MultiSet<MultiSet<int> > >::const_iterator iter;
00574 for (iter i=parts.begin(); i!=parts.end(); i++)
00575 {
00576 if ((int) i->size()!=s) continue;
00577 Array<MultiSet<int> > y = i->elements();
00578 Array<MultiSet<int> > tmp(y.size());
00579 std::sort(y.begin(), y.end());
00580 std::copy(y.begin(), y.end(), tmp.begin());
00581 rtn.append(tmp);
00582 while (std::next_permutation(y.begin(), y.end()))
00583 {
00584 tmp.resize(y.size());
00585 std::copy(y.begin(), y.end(), tmp.begin());
00586 rtn.append(tmp);
00587 }
00588 }
00589 return rtn;
00590 }
00591
00592 Array<Array<int> > distinctIndexTuples(int m, int n)
00593 {
00594 Array<Array<int> > rtn;
00595 Array<int> cur(m);
00596 for (int i=0; i<m; i++) cur[i] = i;
00597 if (m==1)
00598 {
00599 for (int i=0; i<n; i++) rtn.append(tuple(i));
00600 return rtn;
00601 }
00602
00603 while(cur[0] < (n-m)+1)
00604 {
00605 rtn.append(cur);
00606 for (int i=(m-1); i>=0; i--)
00607 {
00608 if (cur[i] < (n-1))
00609 {
00610 cur[i]++;
00611 bool overflow = false;
00612 for (int j=i+1; j<m; j++)
00613 {
00614 cur[j] = cur[j-1]+1;
00615 if (cur[j] >= n) overflow = true;
00616 }
00617 if (overflow) continue;
00618 else break;
00619 }
00620 }
00621 }
00622 return rtn;
00623 }
00624
00625 Array<int> bitsOfAnInteger(int x, int n)
00626 {
00627 TEUCHOS_TEST_FOR_EXCEPTION(x >= pow2(n), std::logic_error,
00628 "Invalid input to bitsOfAnIteger");
00629
00630 Array<int> rtn(n);
00631
00632 int r = x;
00633 for (int b=n-1; b>=0; b--)
00634 {
00635 rtn[b] = r/pow2(b);
00636 r = r - rtn[b]*pow2(b);
00637 }
00638 return rtn;
00639 }
00640
00641
00642
00643
00644
00645 int pow2(int n)
00646 {
00647 static Array<int> p2(1,1);
00648
00649 if ((int) n >= p2.size())
00650 {
00651 int oldN = p2.size();
00652 for (int i=oldN; i<=n; i++) p2.push_back(p2[i-1]*2);
00653 }
00654
00655 return p2[n];
00656 }
00657 }
00658
00659
00660
00661
00662
00663
00664
00665
00666