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 BASE_SEARCH_H_
00034 #define BASE_SEARCH_H_
00035
00036 #include "change/conjugating_base_change.h"
00037 #include "change/random_base_transpose.h"
00038
00039 #include <boost/dynamic_bitset.hpp>
00040
00041 namespace permlib {
00042
00044 template<class BSGSIN, class TRANSRET>
00045 class BaseSearch {
00046 public:
00047 typedef typename BSGSIN::PERMtype PERM;
00048 typedef typename BSGSIN::TRANStype TRANS;
00049 typedef boost::shared_ptr< typename BaseSearch<BSGSIN,TRANSRET>::PERM> PERMptrType;
00050 typedef std::list<PERMptrType> PERMlistType;
00051
00053
00058 BaseSearch(const BSGSIN& bsgs, uint pruningLevelDCM, bool stopAfterFirstElement);
00059
00061 virtual ~BaseSearch(){}
00062
00064
00067 bool minOrbit(ulong alpha, BSGS<PERM,TRANSRET> &groupK, uint i, ulong beta_i) const;
00068
00070 virtual PERMptrType searchCosetRepresentative();
00071
00073
00079 virtual PERMptrType searchCosetRepresentative(BSGS<PERM,TRANSRET> &groupK, BSGS<PERM,TRANSRET> &groupL) = 0;
00080
00082 ulong m_statNodesVisited;
00084 ulong m_statNodesPrunedCosetMinimality;
00086 ulong m_statNodesPrunedCosetMinimality2;
00088 ulong m_statNodesPrunedChildRestriction;
00089
00090 protected:
00092 BSGSIN m_bsgs;
00094 BSGSIN* m_bsgs2;
00096 boost::scoped_ptr<SubgroupPredicate<PERM> > m_pred;
00097
00099 std::vector<ulong> m_order;
00101 boost::scoped_ptr<BaseSorterByReference> m_sorter;
00102
00104 ConjugatingBaseChange<PERM,TRANS,RandomBaseTranspose<PERM,TRANS> > m_baseChange;
00105
00107 const uint m_pruningLevelDCM;
00109 bool m_limitInitialized;
00111 uint m_limitBase;
00113 uint m_limitLevel;
00114
00116 bool pruneDCM(const PERM& t, uint backtrackLevel, BSGS<PERM,TRANSRET> &groupK, BSGS<PERM,TRANSRET> &groupL);
00118 bool checkLeaf(uint level);
00120 uint processLeaf(const PERM& t, uint level, uint backtrackLevel, uint completed, BSGS<PERM,TRANSRET> &groupK, BSGS<PERM,TRANSRET> &groupL);
00122 virtual const std::vector<ulong>& subgroupBase() const = 0;
00123
00125 void setupEmptySubgroup(BSGS<PERM,TRANSRET>& group) const;
00126
00128 const bool m_stopAfterFirstElement;
00130 PERMptrType m_lastElement;
00131 private:
00132 static PERMlistType ms_emptyList;
00133 };
00134
00135
00136
00137
00138
00139 template<class BSGSIN,class TRANSRET>
00140 typename BaseSearch<BSGSIN,TRANSRET>::PERMlistType BaseSearch<BSGSIN,TRANSRET>::ms_emptyList;
00141
00142
00143 template<class BSGSIN,class TRANSRET>
00144 BaseSearch<BSGSIN,TRANSRET>::BaseSearch(const BSGSIN& bsgs, uint pruningLevelDCM, bool stopAfterFirstElement)
00145 : m_statNodesVisited(0), m_statNodesPrunedCosetMinimality(0), m_statNodesPrunedCosetMinimality2(0),
00146 m_statNodesPrunedChildRestriction(0),
00147 m_bsgs(bsgs), m_bsgs2(0), m_pred(0), m_baseChange(m_bsgs),
00148 m_pruningLevelDCM(pruningLevelDCM),
00149 m_limitInitialized(false), m_limitBase(0), m_limitLevel(0),
00150 m_stopAfterFirstElement(stopAfterFirstElement),
00151 m_lastElement()
00152 {
00153 }
00154
00155
00156 template<class BSGSIN,class TRANSRET>
00157 bool BaseSearch<BSGSIN,TRANSRET>::minOrbit(ulong alpha, BSGS<PERM,TRANSRET> &groupK, uint i, ulong beta_i) const {
00158 PERMlistType S_i;
00159 std::copy_if(groupK.S.begin(), groupK.S.end(), std::back_inserter(S_i), PointwiseStabilizerPredicate<PERM>(groupK.B.begin(), groupK.B.begin() + i));
00160 if (S_i.empty()) {
00161 if (alpha == beta_i)
00162 return true;
00163 return (*m_sorter)(beta_i, alpha);
00164 }
00165
00166
00167 boost::dynamic_bitset<> orbitCharacteristic(m_bsgs.n);
00168 orbitCharacteristic.set(alpha, 1);
00169 std::list<ulong> orbit;
00170 orbit.push_back(alpha);
00171 for (std::list<ulong>::const_iterator it = orbit.begin(); it != orbit.end(); ++it) {
00172 ulong beta = *it;
00173 BOOST_FOREACH(const PERMptrType& p, S_i) {
00174 ulong beta_p = *p / beta;
00175 if (!orbitCharacteristic[beta_p]) {
00176 orbitCharacteristic.set(beta_p, 1);
00177 orbit.push_back(beta_p);
00178 if ((*m_sorter)(beta_p, beta_i)) {
00179 DEBUG(std::cout << "DCM2 beta_p = " << beta_p+1 << " , beta_i = " << beta_i+1 << std::endl;)
00180 return false;
00181 }
00182 }
00183 }
00184 }
00185 return true;
00186 }
00187
00188 template<class BSGSIN,class TRANSRET>
00189 bool BaseSearch<BSGSIN,TRANSRET>::pruneDCM(const PERM& t, uint backtrackLevel, BSGS<PERM,TRANSRET> &groupK, BSGS<PERM,TRANSRET> &groupL) {
00190
00191 if (backtrackLevel < m_pruningLevelDCM) {
00192
00193 std::vector<ulong> newBaseImage(subgroupBase().begin(), subgroupBase().end());
00194 for (uint j=0; j<=backtrackLevel; ++j)
00195 newBaseImage[j] = t / newBaseImage[j];
00196
00197 ConjugatingBaseChange<PERM,TRANSRET,RandomBaseTranspose<PERM,TRANSRET> > cbc(groupL);
00198 cbc.change(groupL, newBaseImage.begin(), newBaseImage.begin() + (backtrackLevel+1), false);
00199
00200 }
00201
00202 const ulong alpha = groupK.B[backtrackLevel];
00203
00204 for (uint i = 0; i <= backtrackLevel; ++i) {
00205 if (i == backtrackLevel || groupK.U[i].contains(alpha)) {
00206 DEBUG(std::cout << "DCM2 found " << (alpha+1) << " in U_" << i << " btLevel " << backtrackLevel << std::endl;)
00207 DEBUG(std::cout << " t = " << t << std::endl;)
00208
00209 if (!minOrbit(t / alpha, groupL, i, t / groupK.B[i])) {
00210 DEBUG(std::cout << "DCM2 : " << ((t / groupK.B[i]) + 1) << " // " << ((t / alpha) + 1) << std::endl;)
00211 DEBUG(std::cout << " K = " << groupK << std::endl;)
00212 DEBUG(std::cout << " L = " << groupL << std::endl;)
00213 return true;
00214 }
00215 }
00216 if (t / groupK.B[i] != groupL.B[i])
00217 return false;
00218 }
00219 return false;
00220 }
00221
00222 template<class BSGSIN,class TRANSRET>
00223 bool BaseSearch<BSGSIN,TRANSRET>::checkLeaf(uint level) {
00224 return m_limitInitialized && level >= m_limitLevel;
00225 }
00226
00227 template<class BSGSIN,class TRANSRET>
00228 uint BaseSearch<BSGSIN,TRANSRET>::processLeaf(const PERM& t, uint level, uint backtrackLevel, uint completed, BSGS<PERM,TRANSRET> &groupK, BSGS<PERM,TRANSRET> &groupL) {
00229 DEBUG(std::cout << "XXX level " << level << " bLevel " << backtrackLevel << std::endl;)
00230 DEBUG(std::cout << "XXX limitLevel " << m_limitLevel << " limitBase " << m_limitBase << std::endl;)
00231 if ((*m_pred)(t)) {
00232 if (m_stopAfterFirstElement) {
00233 m_lastElement = PERMptrType(new PERM(t));
00234 return 0;
00235 }
00236 const bool isIdentity = t.isIdentity();
00237 int posK = 0, posL = 0;
00238 if (m_limitInitialized && level == m_limitLevel && isIdentity) {
00239 PointwiseStabilizerPredicate<PERM> stabPred(m_bsgs.B.begin(), m_bsgs.B.begin() + m_limitBase);
00240 BOOST_FOREACH(const PERMptrType &s, m_bsgs.S) {
00241 if (stabPred(s)) {
00242 DEBUG(std::cout << *s << " extended gen\n";)
00243 BOOST_ASSERT((*m_pred)(*s));
00244 PERMptrType sK(new PERM(*s));
00245 PERMptrType sL(new PERM(*s));
00246 posK = std::max(posK, groupK.insertGenerator(sK, false));
00247 posL = std::max(posL, groupL.insertGenerator(sL, false));
00248 }
00249 }
00250
00251 }
00252 if (!isIdentity) {
00253 PERMptrType genK(new PERM(t));
00254 posK = std::max(posK, groupK.insertGenerator(genK, false));
00255 PERMptrType genL(new PERM(t));
00256 posL = std::max(posL, groupL.insertGenerator(genL, false));
00257 DEBUG(std::cout << "-- accepted" << std::endl;)
00258 }
00259 groupK.updateOrbits(posK);
00260 groupL.updateOrbits(posL);
00261 return completed;
00262 }
00263 return level;
00264 }
00265
00266 template<class BSGSIN,class TRANSRET>
00267 void BaseSearch<BSGSIN,TRANSRET>:: setupEmptySubgroup(BSGS<PERM,TRANSRET>& group) const {
00268 group.B = subgroupBase();
00269 group.U.resize(subgroupBase().size(), TRANSRET(this->m_bsgs.n));
00270 for (uint i=0; i<subgroupBase().size(); ++i)
00271 group.orbit(i, ms_emptyList);
00272 }
00273
00274 template<class BSGSIN,class TRANSRET>
00275 typename BaseSearch<BSGSIN,TRANSRET>::PERMptrType BaseSearch<BSGSIN,TRANSRET>::searchCosetRepresentative() {
00276 BSGS<PERM,TRANSRET> groupK(this->m_bsgs.n);
00277 BSGS<PERM,TRANSRET> groupL(this->m_bsgs.n);
00278
00279 setupEmptySubgroup(groupK);
00280 setupEmptySubgroup(groupL);
00281
00282 return this->searchCosetRepresentative(groupK, groupL);
00283 }
00284
00285 }
00286
00287 #endif // -- BASE_SEARCH_H_