CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC2/src/CommonTools/Statistics/src/SequentialPartitionGenerator.cc

Go to the documentation of this file.
00001 #include "CommonTools/Statistics/interface/SequentialPartitionGenerator.h"
00002 
00003 SequentialPartitionGenerator::SequentialPartitionGenerator( int n, int k, int pmin ) :
00004   the_n(n), the_k(k), the_pmin(pmin), the_pmax(n) {}
00005 
00006 SequentialPartitionGenerator::SequentialPartitionGenerator(int n, int k, int pmin, int pmax) :
00007   the_n(n), the_k(k), the_pmin(pmin), the_pmax(pmax) {}
00008 
00009 SequentialPartitionGenerator::Partition SequentialPartitionGenerator::next_partition()
00010 {
00011   bool done=next_part(the_part);
00012   if (done)
00013   {
00014     return the_part;
00015   };
00016   SequentialPartitionGenerator::Partition empty;
00017   return empty;
00018 }
00019 
00020 bool SequentialPartitionGenerator::first_part(
00021     SequentialPartitionGenerator::Partition & p, int k, int n, int pmin, int pmax ) const
00022 {
00023   n_first++;
00024   bool done=false;
00025   switch (k) {
00026   case 1:
00027     p[0]=std::min(pmax,n);
00028     return (n<=pmax && p[0]>=pmin);
00029   case 2:
00030     for (int i=std::min(pmax,n-1);i>=pmin;i--) {
00031       if ((done=(i>=n-i && n-i>=pmin))) {p[0]=i;p[1]=n-i;}
00032       return done;
00033     }
00034   default:
00035     Partition pp(p.begin()+1,p.end());
00036     for (int i=std::min(pmax,n-k+1);i>=pmin;i--) {
00037       p[0]=i;
00038       done=this->first_part(pp,k-1,n-p[0],pmin,p[0]);
00039       if (done) {copy(pp.begin(),pp.end(),p.begin()+1);}
00040       return done;
00041     }
00042   }
00043   return done;
00044 }
00045 
00046 bool SequentialPartitionGenerator::next_part( 
00047     SequentialPartitionGenerator::Partition & p ) const
00048 {
00049   n_next++;
00050   bool done=false;
00051   int k=p.size();
00052   switch (k) {
00053     case 0:  // empty partition: first call to next_part, initialize
00054       p.insert(p.begin(),the_k,0);
00055       return this->first_part(p,the_k,the_n,the_pmin,the_pmax);
00056     case 1:
00057       return false;
00058     default:
00059       int n=0;
00060       for (int i=0;i<k;i++) n=n+p[i];
00061       SequentialPartitionGenerator::Partition pp(p.begin()+1,p.end());
00062       done = (pp.size()>1 ? this->next_part(pp) : false);
00063       if (done)
00064       {
00065         copy(pp.begin(),pp.end(),p.begin()+1);
00066       } else {
00067         done = (p[0]==1 ? false :
00068                 this->first_part(pp,k-1,n-p[0]+1,the_pmin,p[0]-1));
00069         if (done) { --p[0];copy(pp.begin(),pp.end(),p.begin()+1); }
00070       };
00071       return done;
00072   };
00073   return done;
00074 }