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 #ifndef PARTITION_H_
00034 #define PARTITION_H_
00035
00036 #include <algorithm>
00037 #include <list>
00038 #include <boost/foreach.hpp>
00039 #include <boost/dynamic_bitset.hpp>
00040
00041 namespace permlib {
00042 namespace partition {
00043
00044 template<class T>
00045 class BacktrackRefinement;
00046
00048 class Partition {
00049 public:
00051 explicit Partition(ulong n);
00052
00054
00061 template<class ForwardIterator>
00062 bool intersect(ForwardIterator begin, ForwardIterator end, uint j);
00064 bool undoIntersection();
00065
00068 template<class ForwardIterator>
00069 bool intersects(ForwardIterator begin, ForwardIterator end, uint j) const;
00070
00072 uint fixPointsSize() const;
00074 std::vector<ulong>::const_iterator fixPointsBegin() const;
00076 std::vector<ulong>::const_iterator fixPointsEnd() const;
00078 ulong cells() const;
00080 ulong cellSize(uint c) const;
00081
00082 typedef std::vector<ulong>::const_iterator CellIt;
00083
00084 CellIt cellBegin(ulong cell) const {
00085 BOOST_ASSERT(cell < cells());
00086 return partition.begin() + partitionCellBorder[cell];
00087 }
00088
00089 CellIt cellEnd(ulong cell) const {
00090 BOOST_ASSERT(cell < cells());
00091 return partition.begin() + partitionCellBorder[cell] + partitionCellLength[cell];
00092 }
00093 private:
00094 explicit Partition(ulong n, bool);
00095
00096 std::vector<ulong> partition;
00097 std::vector<uint> partitionCellBorder;
00098 std::vector<uint> partitionCellLength;
00099 std::vector<uint> partitionCellOf;
00100
00102 uint cellCounter;
00103
00106 std::vector<ulong> fix;
00108 uint fixCounter;
00109
00110 friend std::ostream& operator<<(std::ostream& out, const Partition& p);
00111
00112 template<class T>
00113 friend class BacktrackRefinement;
00114 };
00115
00116 inline std::ostream& operator<<(std::ostream& out, const Partition& p) {
00117 out << "[";
00118 std::vector<uint>::const_iterator border = p.partitionCellBorder.begin();
00119 std::vector<uint>::const_iterator length = p.partitionCellLength.begin();
00120 for (uint j = 0; j < p.cellCounter; ++j) {
00121 for (uint i = *border; i < *border + *length; ++i) {
00122 out << (p.partition[i] + 1) << " ";
00123 }
00124 out << "| ";
00125 ++border;
00126 ++length;
00127 }
00128 out << "]|(";
00129 int countFix = p.fixCounter;
00130 BOOST_FOREACH(ulong alpha, p.fix) {
00131 if (--countFix < 0)
00132 break;
00133 out << (alpha+1) << ",";
00134 }
00135 out << ")";
00136 return out;
00137 }
00138
00139 inline Partition::Partition(ulong n)
00140 : partition(n), partitionCellBorder(n), partitionCellLength(n), partitionCellOf(n), cellCounter(1), fix(n), fixCounter(0)
00141 {
00142 for (uint i=0; i<n; ++i) {
00143 partition[i] = i;
00144
00145 }
00146 partitionCellBorder[0] = 0;
00147 partitionCellLength[0] = n;
00148 }
00149
00150 inline Partition::Partition(ulong n, bool)
00151 : partition(n), partitionCellBorder(n), partitionCellLength(n), partitionCellOf(n), cellCounter(0), fix(n), fixCounter(0)
00152 { }
00153
00154 inline ulong Partition::cells() const {
00155 return cellCounter;
00156 }
00157
00158 inline uint Partition::fixPointsSize() const {
00159 return fixCounter;
00160 }
00161 inline std::vector<ulong>::const_iterator Partition::fixPointsBegin() const {
00162 return fix.begin();
00163 }
00164 inline std::vector<ulong>::const_iterator Partition::fixPointsEnd() const {
00165 return fix.begin() + fixCounter;
00166 }
00167 inline ulong Partition::cellSize(uint c) const {
00168 return partitionCellLength[c];
00169 }
00170
00171 template<class ForwardIterator>
00172 inline bool Partition::intersects(ForwardIterator begin, ForwardIterator end, uint j) const {
00173 while (begin != end) {
00174
00175 if (partitionCellOf[*begin++] == j)
00176 return true;
00177 }
00178 return false;
00179 }
00180
00182 template<class ForwardIterator>
00183 inline bool Partition::intersect(ForwardIterator otherCellBegin, ForwardIterator otherCellEnd, uint j) {
00184 if (!intersects(otherCellBegin, otherCellEnd, j))
00185 return false;
00186
00187
00188 static std::vector<ulong> newCell(partition.size());
00189
00190 ForwardIterator otherCellIt = otherCellBegin;
00191 std::vector<ulong>::iterator cellIt;
00192 std::vector<ulong>::reverse_iterator newCellIt;
00193 std::vector<ulong>::reverse_iterator newCellBeginIt;
00194 std::vector<ulong>::iterator newCell2It;
00195 std::vector<uint>::iterator borderIt;
00196 bool createdNewCell = false;
00197 const uint cellSize = partitionCellLength[j];
00198 if (j >= cellCounter)
00199 return false;
00200 if (cellSize <= 1)
00201 return false;
00202 std::vector<ulong>::iterator cellBeginIt = partition.begin() + partitionCellBorder[j];
00203 std::vector<ulong>::iterator cellEndIt = partition.begin() + (partitionCellBorder[j] + partitionCellLength[j]);
00204
00205 newCellBeginIt = newCell.rbegin() + (partition.size() - cellSize);
00206 newCellIt = newCellBeginIt;
00207 newCell2It = newCell.begin();
00208 uint newCellCounter = 0;
00209
00210 for (cellIt = cellBeginIt; cellIt != cellEndIt; ++cellIt) {
00211 while (otherCellIt != otherCellEnd && *otherCellIt < *cellIt) {
00212 ++otherCellIt;
00213 }
00214 if (otherCellIt != otherCellEnd && *cellIt == *otherCellIt) {
00215 *newCell2It = *cellIt;
00216 ++newCell2It;
00217 if (newCellCounter == 0) {
00218
00219
00220
00221 newCellIt = std::copy(cellBeginIt, cellIt, newCellIt);
00222 }
00223 ++newCellCounter;
00224 } else if (newCellCounter) {
00225 *newCellIt = *cellIt;
00226 ++newCellIt;
00227 }
00228 }
00229
00230 if (newCellCounter > 0 && newCellCounter < cellSize) {
00231 std::reverse(newCellBeginIt, newCellIt);
00232 std::copy(newCell.begin(), newCell.begin() + cellSize, cellBeginIt);
00233
00234
00235
00236 std::vector<ulong>::iterator fixIt = fix.begin() + fixCounter;
00237
00238 if (newCellCounter == 1) {
00239 *fixIt = newCell[0];
00240 ++fixIt;
00241 ++fixCounter;
00242 }
00243 if (newCellCounter == cellSize - 1) {
00244 *fixIt = newCell[cellSize - 1];
00245 ++fixIt;
00246 ++fixCounter;
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 partitionCellLength[j] = newCellCounter;
00258
00259
00260 partitionCellBorder[cellCounter] = partitionCellBorder[j] + newCellCounter;
00261 partitionCellLength[cellCounter] = cellSize - newCellCounter;
00262 for (uint i = partitionCellBorder[cellCounter]; i < partitionCellBorder[j] + cellSize; ++i) {
00263 partitionCellOf[partition[i]] = cellCounter;
00264 }
00265 ++cellCounter;
00266
00267 createdNewCell = true;
00268 }
00269
00270 return createdNewCell;
00271 }
00272
00273 inline bool Partition::undoIntersection() {
00274 if (partitionCellBorder[cellCounter-1] < 1)
00275 return false;
00276 --cellCounter;
00277 uint splitFromCellNumber = partitionCellOf[ partition[partitionCellBorder[cellCounter] - 1] ];
00278
00279 BOOST_ASSERT(partitionCellBorder[splitFromCellNumber] < partitionCellBorder[cellCounter]);
00280 BOOST_ASSERT(partitionCellLength[cellCounter] > 0 );
00281
00282
00283
00284 for (uint i=partitionCellBorder[cellCounter]; i<partitionCellBorder[cellCounter] + partitionCellLength[cellCounter]; ++i) {
00285 partitionCellOf[partition[i]] = splitFromCellNumber;
00286 }
00287 std::inplace_merge(partition.begin() + partitionCellBorder[splitFromCellNumber],
00288 partition.begin() + partitionCellBorder[cellCounter],
00289 partition.begin() + (partitionCellBorder[cellCounter] + partitionCellLength[cellCounter]));
00290
00291
00292 if (partitionCellLength[cellCounter] == 1) {
00293 --fixCounter;
00294 fix[fixCounter] = 0;
00295 }
00296 if (partitionCellLength[splitFromCellNumber] == 1) {
00297 --fixCounter;
00298 fix[fixCounter] = 0;
00299 }
00300
00301 partitionCellLength[splitFromCellNumber] += partitionCellLength[cellCounter];
00302
00303 partitionCellLength[cellCounter] = 0;
00304 partitionCellBorder[cellCounter] = 0;
00305
00306 return true;
00307 }
00308
00309 }
00310 }
00311
00312 #endif // -- PARTITION_H_