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 RBASE_H_
00034 #define RBASE_H_
00035
00036 #include <permlib/predicate/subgroup_predicate.h>
00037
00038 #include <permlib/search/base_search.h>
00039
00040 #include <permlib/search/partition/partition.h>
00041 #include <permlib/search/partition/refinement_family.h>
00042 #include <permlib/search/partition/backtrack_refinement.h>
00043
00044 #include <permlib/change/conjugating_base_change.h>
00045 #include <permlib/change/random_base_transpose.h>
00046
00047 #include <permlib/sorter/base_sorter.h>
00048
00049 #include <utility>
00050
00051 namespace permlib {
00052 namespace partition {
00053
00055 template<class BSGSIN,class TRANSRET>
00056 class RBase : public BaseSearch<BSGSIN,TRANSRET> {
00057 public:
00058 typedef typename BaseSearch<BSGSIN,TRANSRET>::PERM PERM;
00059 typedef typename BaseSearch<BSGSIN,TRANSRET>::TRANS TRANS;
00060 typedef boost::shared_ptr< typename RBase<BSGSIN,TRANSRET>::PERM> PERMptrType;
00061
00063
00068 RBase(const BSGSIN& bsgs, uint pruningLevelDCM, bool stopAfterFirstElement = false);
00069
00070 typedef typename Refinement<PERM>::RefinementPtr RefinementPtr;
00071 typedef typename RefinementFamily<PERM>::PartitionPtr PartitionPtr;
00072 typedef typename std::list<std::pair<PartitionPtr,RefinementPtr> >::const_iterator PartitionIt;
00073
00075 void search(BSGS<PERM,TRANSRET> &groupK);
00076
00077 using BaseSearch<BSGSIN,TRANSRET>::searchCosetRepresentative;
00078 virtual PERMptrType searchCosetRepresentative(BSGS<PERM,TRANSRET> &groupK, BSGS<PERM,TRANSRET> &groupL);
00079 protected:
00081 Partition m_partition;
00082 Partition m_partition2;
00083
00085
00090 void construct(SubgroupPredicate<PERM>* pred, RefinementFamily<PERM>* predRefinement);
00091
00093 virtual uint processNewFixPoints(const Partition& pi, uint level);
00094
00095 virtual const std::vector<ulong>& subgroupBase() const;
00096 private:
00098 std::vector<ulong> m_subgroupBase;
00100 std::list<std::pair<PartitionPtr,RefinementPtr> > partitions;
00101
00103 uint search(PartitionIt pIt, Partition &pi, const PERM& t, const PERM* t2, uint level, uint backtrackLevel, uint& completed, BSGS<PERM,TRANSRET> &groupK, BSGS<PERM,TRANSRET> &groupL);
00104
00106 bool updateMappingPermutation(const BSGSIN& bsgs, const Partition& sigma, const Partition& pi2, PERM& t2) const;
00107 };
00108
00109 template<class BSGSIN,class TRANSRET>
00110 RBase<BSGSIN,TRANSRET>::RBase(const BSGSIN& bsgs, uint pruningLevelDCM, bool stopAfterFirstElement)
00111 : BaseSearch<BSGSIN,TRANSRET>(bsgs, pruningLevelDCM, stopAfterFirstElement),
00112 m_partition(bsgs.n), m_partition2(bsgs.n)
00113 { }
00114
00115 template<class BSGSIN,class TRANSRET>
00116 void RBase<BSGSIN,TRANSRET>::construct(SubgroupPredicate<PERM>* pred, RefinementFamily<PERM>* predRefinement) {
00117 this->m_pred.reset(pred);
00118 typedef typename boost::shared_ptr<RefinementFamily<PERM> > RefinementFamilyPtr;
00119 std::list<RefinementFamilyPtr> refinements;
00120
00121 if (!this->m_bsgs.isSymmetricGroup()) {
00122 RefinementFamilyPtr gr( new GroupRefinementFamily<PERM,TRANS>(this->m_bsgs) );
00123 refinements.push_back(gr);
00124 }
00125
00126 if (predRefinement) {
00127 RefinementFamilyPtr predR( predRefinement );
00128 refinements.push_back(predR);
00129 }
00130
00131 DEBUG(print_iterable(this->m_bsgs.B.begin(), this->m_bsgs.B.end(), 1, "orig BSGS");)
00132
00133 Partition pi(m_partition);
00134 while (pi.cells() < this->m_bsgs.n) {
00135 DEBUG(std::cout << std::endl << "PI0 = " << pi << std::endl;)
00136 bool found = false;
00137 do {
00138 found = false;
00139 uint foo = 0;
00140 BOOST_FOREACH(RefinementFamilyPtr ref, refinements) {
00141 const uint oldFixPointsSize = pi.fixPointsSize();
00142 std::pair<PartitionPtr,RefinementPtr> newRef = ref->apply(pi);
00143 if (newRef.first) {
00144 partitions.push_back(newRef);
00145 if (oldFixPointsSize < pi.fixPointsSize()) {
00146 processNewFixPoints(pi, partitions.size());
00147 }
00148
00149 found = true;
00150 }
00151 ++foo;
00152 }
00153 } while(found);
00154
00155 DEBUG(std::cout << std::endl << "PI1 = " << pi << std::endl;)
00156
00157 if (pi.cells() < this->m_bsgs.n) {
00158 ulong alpha = -1;
00159
00160
00161 if (pi.fixPointsSize() < this->m_bsgs.B.size())
00162 alpha = this->m_bsgs.B[pi.fixPointsSize()];
00163 DEBUG(std::cout << "choose alpha = " << alpha << std::endl;)
00164 RefinementPtr br(new BacktrackRefinement<PERM>(this->m_bsgs.n, alpha));
00165 BacktrackRefinement<PERM>* ref = dynamic_cast<BacktrackRefinement<PERM> *>(br.get());
00166 ref->initializeAndApply(pi);
00167 PartitionPtr newPi(new Partition(pi));
00168 DEBUG(std::cout << "BACKTRACK " << (ref->alpha()+1) << " in " << pi << " --> " << *newPi << std::endl;)
00169 partitions.push_back(std::make_pair(newPi, br));
00170
00171 processNewFixPoints(pi, partitions.size());
00172
00173
00174 m_subgroupBase.push_back(ref->alpha());
00175 }
00176 }
00177
00178 this->m_order = BaseSorterByReference::createOrder(this->m_bsgs.n, pi.fixPointsBegin(), pi.fixPointsEnd());
00179 this->m_sorter.reset(new BaseSorterByReference(this->m_order));
00180 for (typename std::list<std::pair<PartitionPtr,RefinementPtr> >::iterator pIt = partitions.begin(); pIt != partitions.end(); ++pIt) {
00181 (*pIt).second->sort(*this->m_sorter, 0);
00182 DEBUG(std::cout << "SIGMA = " << *(*pIt).first << std::endl;)
00183 }
00184
00185 DEBUG(print_iterable(this->m_order.begin(), this->m_order.end(), 0, "ORDER");)
00186 }
00187
00188 template<class BSGSIN,class TRANSRET>
00189 uint RBase<BSGSIN,TRANSRET>::processNewFixPoints(const Partition& pi, uint level) {
00190 const uint basePos = this->m_baseChange.change(this->m_bsgs, pi.fixPointsBegin(), pi.fixPointsEnd(), true);
00191 if (this->m_bsgs2)
00192 this->m_baseChange.change(*this->m_bsgs2, pi.fixPointsBegin(), pi.fixPointsEnd(), true);
00193
00194 DEBUG(print_iterable(this->m_bsgs.B.begin(), this->m_bsgs.B.end(), 1, "change base");)
00195 return basePos;
00196 }
00197
00198 template<class BSGSIN,class TRANSRET>
00199 void RBase<BSGSIN,TRANSRET>::search(BSGS<PERM,TRANSRET> &groupK) {
00200 BOOST_ASSERT( this->m_pred != 0 );
00201
00202 setupEmptySubgroup(groupK);
00203
00204 uint completed = partitions.size();
00205 BSGS<PERM,TRANSRET> groupL(groupK);
00206 PERM identH(this->m_bsgs.n);
00207 search(partitions.begin(), m_partition2, PERM(this->m_bsgs.n), &identH, 0, 0, completed, groupK, groupL);
00208 }
00209
00210 template<class BSGSIN,class TRANSRET>
00211 typename RBase<BSGSIN,TRANSRET>::PERMptrType RBase<BSGSIN,TRANSRET>::searchCosetRepresentative(BSGS<PERM,TRANSRET> &groupK, BSGS<PERM,TRANSRET> &groupL) {
00212 BOOST_ASSERT( this->m_pred != 0 );
00213
00214
00215
00216
00217
00218
00219
00220 uint completed = partitions.size();
00221
00222 PERM identH(this->m_bsgs.n);
00223 search(partitions.begin(), m_partition2, PERM(this->m_bsgs.n), &identH, 0, 0, completed, groupK, groupL);
00224
00225 return BaseSearch<BSGSIN,TRANSRET>::m_lastElement;
00226 }
00227
00228
00229
00230 template<class BSGSIN,class TRANSRET>
00231 uint RBase<BSGSIN,TRANSRET>::search(PartitionIt pIt, Partition &pi, const PERM& t, const PERM* t2, uint level, uint backtrackLevel, uint& completed, BSGS<PERM,TRANSRET> &groupK, BSGS<PERM,TRANSRET> &groupL) {
00232 ++this->m_statNodesVisited;
00233
00234 if (pIt == partitions.end() || this->checkLeaf(level)) {
00235 DEBUG(std::cout << "LEAF: " << pi << " with t = " << t << std::endl;)
00236 return processLeaf(t, level, backtrackLevel, completed, groupK, groupL);
00237 }
00238
00239 const Partition& sigma = *((*pIt).first);
00240 const RefinementPtr& ref = (*pIt).second;
00241 ++pIt;
00242
00243 uint s = ref->alternatives();
00244 const bool isBacktrack = ref->type() == Backtrack;
00245 const bool isGroup = ref->type() == Group;
00246 const PERM* tForRefinement = &t;
00247
00248 if (isGroup) {
00249 GroupRefinement<PERM,TRANS>* gref = static_cast<GroupRefinement<PERM,TRANS>*>(ref.get());
00250 if (this->m_bsgs2 && gref->bsgs() == *this->m_bsgs2) {
00251 tForRefinement = t2;
00252 }
00253 }
00254
00255 ref->sort(*this->m_sorter, &pi);
00256 typedef typename Refinement<PERM>::RefinementPtrIterator RefIt;
00257 for (RefIt rIt = ref->backtrackBegin(); rIt != ref->backtrackEnd(); ++rIt) {
00258 if (isBacktrack && s < groupK.U[backtrackLevel].size()) {
00259 DEBUG(std::cout << "PRUNE the rest: s=" << s << " < " << groupK.U[backtrackLevel].size() << std::endl;)
00260 this->m_statNodesPrunedCosetMinimality += s;
00261 break;
00262 }
00263
00264 --s;
00265 RefinementPtr ref2 = *rIt;
00266
00267 const uint oldFixPointsSize = pi.fixPointsSize();
00268 DEBUG(std::cout << " refinement from " << pi << std::endl;)
00269 const uint strictRefinement = ref2->apply2(pi, *tForRefinement);
00270 DEBUG(std::cout << " to " << pi << " with " << strictRefinement << std::endl;)
00271 DEBUG(for(uint jj=0; jj<level; ++jj) std::cout << " ";)
00272 DEBUG(std::cout << "NODE " << sigma << " ~~~> " << pi << std::endl;)
00273
00274
00275
00276
00277
00278
00279 if (!strictRefinement) {
00280 DEBUG(std::cout << "no strict refinement " << sigma << " -- " << pi << std::endl;)
00281 ++this->m_statNodesPrunedChildRestriction;
00282 continue;
00283 }
00284 if (pi.cells() != sigma.cells()) {
00285 DEBUG(std::cout << "cell number mismatch " << sigma << " -- " << pi << std::endl;)
00286 ref2->undo(pi, strictRefinement);
00287 ++this->m_statNodesPrunedChildRestriction;
00288 continue;
00289 }
00290 if (pi.fixPointsSize() != sigma.fixPointsSize()) {
00291 DEBUG(std::cout << "fix point number mismatch " << sigma << " -- " << pi << std::endl;)
00292 ref2->undo(pi, strictRefinement);
00293 ++this->m_statNodesPrunedChildRestriction;
00294 continue;
00295 }
00296 PERM tG(t);
00297 PERM* tH = 0;
00298 if (pi.fixPointsSize() != oldFixPointsSize) {
00299 if (!updateMappingPermutation(this->m_bsgs, sigma, pi, tG)) {
00300 DEBUG(std::cout << "no t found " << sigma << " -- " << pi << "; tG = " << tG << std::endl;)
00301 ref2->undo(pi, strictRefinement);
00302 ++this->m_statNodesPrunedChildRestriction;
00303 continue;
00304 }
00305 if (this->m_bsgs2) {
00306 tH = new PERM(*t2);
00307 if (!updateMappingPermutation(*this->m_bsgs2, sigma, pi, *tH)) {
00308 DEBUG(std::cout << "no t found " << sigma << " -- " << pi << "; tH = " << tH << std::endl;)
00309 ref2->undo(pi, strictRefinement);
00310 ++this->m_statNodesPrunedChildRestriction;
00311 continue;
00312 }
00313 }
00314 }
00315 if (this->m_pruningLevelDCM && isBacktrack) {
00316 if (pruneDCM(tG, backtrackLevel, groupK, groupL)) {
00317 ++this->m_statNodesPrunedCosetMinimality2;
00318 ref2->undo(pi, strictRefinement);
00319 continue;
00320 }
00321 }
00322 uint ret = search(pIt, pi, tG, tH ? tH : t2, level+1, isBacktrack ? (backtrackLevel + 1) : backtrackLevel, completed, groupK, groupL);
00323 delete tH;
00324 DEBUG(std::cout << "retract " << strictRefinement << " from " << pi << " to ";)
00325 ref2->undo(pi, strictRefinement);
00326 DEBUG(std::cout << pi << std::endl;)
00327 if (BaseSearch<BSGSIN,TRANSRET>::m_stopAfterFirstElement && ret == 0)
00328 return 0;
00329 if (ret < level)
00330 return ret;
00331 }
00332
00333 completed = std::min(completed, level);
00334 return level;
00335 }
00336
00337 template<class BSGSIN,class TRANSRET>
00338 bool RBase<BSGSIN,TRANSRET>::updateMappingPermutation(const BSGSIN& bsgs, const Partition& sigma, const Partition& pi, PERM& t2) const {
00339 typedef std::vector<ulong>::const_iterator FixIt;
00340 std::vector<ulong>::const_iterator bIt;
00341 ulong i = 0;
00342 FixIt fixSigmaIt = sigma.fixPointsBegin();
00343 const FixIt fixSigmaEndIt = sigma.fixPointsEnd();
00344 FixIt fixPiIt = pi.fixPointsBegin();
00345 DEBUG(print_iterable(bsgs.B.begin(), bsgs.B.end(), 1, "B ");)
00346 DEBUG(print_iterable(fixSigmaIt, fixSigmaEndIt, 1, "Sigma");)
00347 for (bIt = bsgs.B.begin(); bIt != bsgs.B.end(); ++bIt, ++i) {
00348 DEBUG(std::cout << " base: " << (*bIt)+1 << std::endl;)
00349 while (fixSigmaIt != fixSigmaEndIt && *fixSigmaIt != *bIt) {
00350 DEBUG(std::cout << " skipping " << (*fixSigmaIt)+1 << " for " << (*bIt)+1 << std::endl;)
00351 ++fixSigmaIt;
00352 ++fixPiIt;
00353 }
00354 if (fixSigmaIt == fixSigmaEndIt) {
00355 DEBUG(std::cout << " no more fix point found for " << (*bIt)+1 << std::endl;)
00356 return true;
00357 }
00358 const ulong alpha = *fixSigmaIt;
00359 const ulong beta = *fixPiIt;
00360 if (t2 / alpha != beta) {
00361 boost::scoped_ptr<PERM> u_beta(bsgs.U[i].at(t2 % beta));
00362 if (u_beta) {
00363
00364 t2 ^= *u_beta;
00365 } else {
00366
00367 return false;
00368 }
00369 }
00370
00371 ++fixSigmaIt;
00372 ++fixPiIt;
00373 }
00374 return true;
00375 }
00376
00377 template<class BSGSIN,class TRANSRET>
00378 const std::vector<ulong>& RBase<BSGSIN,TRANSRET>::subgroupBase() const {
00379 return m_subgroupBase;
00380 }
00381
00382 }
00383 }
00384
00385 #endif // -- RBASE_H_