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 BACKTRACKSEARCH_H_
00034 #define BACKTRACKSEARCH_H_
00035
00036 #include "bsgs.h"
00037 #include "predicate/subgroup_predicate.h"
00038 #include "predicate/pointwise_stabilizer_predicate.h"
00039 #include "predicate/group_intersection_predicate.h"
00040
00041 #include "search/base_search.h"
00042
00043 #include <boost/scoped_ptr.hpp>
00044
00045 namespace permlib {
00046 namespace classic {
00047
00049 template <class BSGSIN, class TRANSRET>
00050 class BacktrackSearch : public BaseSearch<BSGSIN,TRANSRET> {
00051 public:
00052 typedef typename BaseSearch<BSGSIN,TRANSRET>::PERM PERM;
00053 typedef typename BaseSearch<BSGSIN,TRANSRET>::TRANS TRANS;
00054 typedef boost::shared_ptr< typename BacktrackSearch<BSGSIN,TRANSRET>::PERM> PERMptrType;
00055
00057
00063 BacktrackSearch(const BSGSIN& bsgs, uint pruningLevelDCM, bool breakAfterChildRestriction = false, bool stopAfterFirstElement = false);
00064
00066 void search(BSGS<PERM,TRANSRET> &groupK);
00067
00068 using BaseSearch<BSGSIN,TRANSRET>::searchCosetRepresentative;
00069 virtual PERMptrType searchCosetRepresentative(BSGS<PERM,TRANSRET> &groupK, BSGS<PERM,TRANSRET> &groupL);
00070 protected:
00071 virtual const std::vector<ulong>& subgroupBase() const;
00072
00074 void construct(SubgroupPredicate<PERM>* pred, bool addPredRefinement);
00076 uint search(const PERM& t, uint level, uint& completed, BSGS<PERM,TRANSRET> &groupK, BSGS<PERM,TRANSRET> &groupL);
00077 private:
00079
00082 const bool m_breakAfterChildRestriction;
00083 };
00084
00085
00086
00087
00088
00089
00090 template <class BSGSIN, class TRANSRET>
00091 BacktrackSearch<BSGSIN,TRANSRET>::BacktrackSearch(const BSGSIN& bsgs, uint pruningLevelDCM, bool breakAfterChildRestriction, bool stopAfterFirstElement)
00092 : BaseSearch<BSGSIN,TRANSRET>(bsgs, pruningLevelDCM, stopAfterFirstElement),
00093 m_breakAfterChildRestriction(breakAfterChildRestriction)
00094 { }
00095
00096 template <class BSGSIN, class TRANSRET>
00097 void BacktrackSearch<BSGSIN,TRANSRET>::search(BSGS<PERM,TRANSRET> &groupK) {
00098 BOOST_ASSERT(this->m_pred != 0);
00099
00100 setupEmptySubgroup(groupK);
00101
00102 this->m_order = BaseSorterByReference::createOrder(this->m_bsgs.n, this->m_bsgs.B.begin(), this->m_bsgs.B.end());
00103 this->m_sorter.reset(new BaseSorterByReference(this->m_order));
00104
00105 uint completed = this->m_bsgs.n;
00106 BSGS<PERM,TRANSRET> groupL(groupK);
00107 search(PERM(this->m_bsgs.n), 0, completed, groupK, groupL);
00108
00109 groupK.stripRedundantBasePoints();
00110 }
00111
00112 template <class BSGSIN, class TRANSRET>
00113 typename BacktrackSearch<BSGSIN,TRANSRET>::PERMptrType BacktrackSearch<BSGSIN,TRANSRET>::searchCosetRepresentative(BSGS<PERM,TRANSRET> &groupK, BSGS<PERM,TRANSRET> &groupL) {
00114 BOOST_ASSERT(this->m_pred != 0);
00115
00116 setupEmptySubgroup(groupK);
00117 setupEmptySubgroup(groupL);
00118
00119 this->m_order = BaseSorterByReference::createOrder(this->m_bsgs.n, this->m_bsgs.B.begin(), this->m_bsgs.B.end());
00120 this->m_sorter.reset(new BaseSorterByReference(this->m_order));
00121
00122 uint completed = this->m_bsgs.n;
00123 search(PERM(this->m_bsgs.n), 0, completed, groupK, groupL);
00124
00125 return BaseSearch<BSGSIN,TRANSRET>::m_lastElement;
00126 }
00127
00128 template <class BSGSIN, class TRANSRET>
00129 uint BacktrackSearch<BSGSIN,TRANSRET>::search(const PERM& g, uint level, uint& completed, BSGS<PERM,TRANSRET> &groupK, BSGS<PERM,TRANSRET> &groupL) {
00130 const std::vector<ulong> &B = this->m_bsgs.B;
00131 std::vector<TRANS > &U = this->m_bsgs.U;
00132
00133 DEBUG(std::cout << "starting with " << g << " @ " << level << std::endl;)
00134 ++this->m_statNodesVisited;
00135
00136 if (level == B.size() || this->checkLeaf(level)) {
00137 DEBUG(std::cout << "limit reached for " << g << " // " << (*this->m_pred)(g) << std::endl;)
00138 return processLeaf(g, level, level, completed, groupK, groupL);
00139 }
00140
00141
00142 std::vector<ulong> orbit(U[level].begin(), U[level].end());
00143 BOOST_FOREACH(ulong &alpha, orbit) {
00144 alpha = g / alpha;
00145 }
00146 std::sort(orbit.begin(), orbit.end(), *this->m_sorter);
00147 uint s = orbit.size();
00148
00149 std::vector<ulong>::const_iterator orbIt;
00150 for (orbIt = orbit.begin(); orbIt != orbit.end(); ++orbIt) {
00151 if (s < groupK.U[level].size()) {
00152 DEBUG(std::cout << "PRUNE the rest: s=" << s << " < " << groupK.U[level].size() << std::endl;)
00153 this->m_statNodesPrunedCosetMinimality += s;
00154
00155 break;
00156 }
00157
00158 --s;
00159 ulong beta = g % *orbIt;
00160 DEBUG(std::cout << " BETA = " << beta << " <-- " << B[level] << std::endl;)
00161 boost::scoped_ptr<PERM> u_beta_ptr(U[level].at(beta));
00162 *u_beta_ptr *= g;
00163
00164 if (!this->m_pred->childRestriction(*u_beta_ptr, level, B[level])) {
00165 ++this->m_statNodesPrunedChildRestriction;
00166 if (m_breakAfterChildRestriction)
00167 break;
00168 continue;
00169 }
00170 if (this->m_pruningLevelDCM && pruneDCM(*u_beta_ptr, level, groupK, groupL)) {
00171 ++this->m_statNodesPrunedCosetMinimality2;
00172 continue;
00173 }
00174
00175 uint ret = search(*u_beta_ptr, level+1, completed, groupK, groupL);
00176 if (BaseSearch<BSGSIN,TRANSRET>::m_stopAfterFirstElement && ret == 0)
00177 return 0;
00178 if (ret < level) {
00179 DEBUG(std::cout << "^^ MULTI BACKTRACK! leave " << level << " to " << ret << std::endl;)
00180 return ret;
00181 }
00182 }
00183 completed = std::min(completed, level);
00184
00185 return level;
00186 }
00187
00188 template<class BSGSIN,class TRANSRET>
00189 void BacktrackSearch<BSGSIN,TRANSRET>::construct(SubgroupPredicate<PERM>* pred, bool addPredRefinement) {
00190 this->m_pred.reset(pred);
00191 }
00192
00193 template<class BSGSIN,class TRANSRET>
00194 const std::vector<ulong>& BacktrackSearch<BSGSIN,TRANSRET>::subgroupBase() const {
00195 return this->m_bsgs.B;
00196 }
00197
00198 }
00199 }
00200
00201 #endif // -- BACKTRACKSEARCH_H_