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 BSGS_H_
00034 #define BSGS_H_
00035
00036 #include <map>
00037 #include <list>
00038 #include <vector>
00039
00040 #include <boost/cstdint.hpp>
00041 #include <boost/foreach.hpp>
00042 #include <boost/scoped_ptr.hpp>
00043 #include <boost/shared_ptr.hpp>
00044 #include <boost/utility.hpp>
00045
00046 #include "bsgs_core.h"
00047
00048 #include "predicate/pointwise_stabilizer_predicate.h"
00049 #include "predicate/stabilizes_point_predicate.h"
00050
00051 #include "redundant_base_point_insertion_strategy.h"
00052
00053 namespace permlib {
00054
00055 template <class PERM, class TRANS>
00056 struct BSGS;
00057
00058 template <class PERM, class TRANS>
00059 std::ostream &operator<< (std::ostream &out, const BSGS<PERM,TRANS> &bsgs) {
00060 out << "BASE[" << bsgs.B.size() << "]" << std::endl;
00061 BOOST_FOREACH(ulong beta, bsgs.B) {
00062 out << (beta+1) << ",";
00063 }
00064 out << std::endl;
00065 out << "SGS[" << bsgs.S.size() << "]" << std::endl;
00066 BOOST_FOREACH(const boost::shared_ptr<PERM> &g, bsgs.S) {
00067 out << *g << ",";
00068 }
00069 out << std::endl;
00070 out << "U" << std::endl;
00071 BOOST_FOREACH(const TRANS &U, bsgs.U) {
00072 for (uint i=0; i<bsgs.n; ++i)
00073
00074 boost::scoped_ptr<PERM> dummy(U.at(i));
00075 out << U.size() << "{" << U.m_statMaxDepth << "}" << ",";
00076 }
00077 out << " = " << bsgs.order() << std::endl;
00078 BOOST_FOREACH(const TRANS &U, bsgs.U) {
00079 out << U << std::endl;
00080 }
00081 return out;
00082 }
00083
00085 template <class PERM, class TRANS>
00086 struct BSGS : public BSGSCore<PERM,TRANS> {
00088 explicit BSGS(uint n);
00090
00094 BSGS(const BSGS<PERM,TRANS>& bsgs);
00095
00097
00101 BSGS<PERM,TRANS>& operator=(const BSGS<PERM,TRANS>&);
00102
00104
00107 boost::uint64_t order() const;
00108
00110
00115 uint sift(const PERM& g, PERM& siftee, uint j = 0) const;
00117
00123 uint sift(const PERM& g, PERM& siftee, uint j, uint k) const;
00125 bool sifts(const PERM& g) const;
00126
00128
00134 bool chooseBaseElement(const PERM &h, ulong &beta) const;
00136
00141 uint insertRedundantBasePoint(uint beta, uint minPos = 0);
00143 void stripRedundantBasePoints(int minPos = 0);
00144
00146
00149 void orbit(uint j, const PERMlist &generators);
00151
00154 void orbitUpdate(uint j, const PERMlist &generators, const PERMptr &g);
00155
00157
00162 int insertGenerator(const PERMptr& g, bool updateOrbit);
00164
00168 void updateOrbits(int pos);
00169
00171
00174 PERM random(const int i = 0) const;
00175
00177 friend std::ostream &operator<< <> (std::ostream &out, const BSGS<PERM,TRANS> &bsgs);
00178 private:
00180 template <class BaseIterator, class TransversalIterator>
00181 uint sift(const PERM& g, PERM& siftee, BaseIterator begin, BaseIterator end, TransversalIterator beginT, TransversalIterator endT) const;
00182
00184 mutable boost::uint64_t m_order;
00185
00187 static int ms_bsgsId;
00188
00190 void copyTransversals(const BSGS<PERM,TRANS>& bsgs);
00191 };
00192
00193
00194
00195
00196
00197 template <class PERM, class TRANS>
00198 int BSGS<PERM,TRANS>::ms_bsgsId = 0;
00199
00200 template <class PERM, class TRANS>
00201 BSGS<PERM,TRANS>::BSGS(uint n)
00202 : BSGSCore<PERM,TRANS>(++ms_bsgsId, n, 0),
00203 m_order(1)
00204 {}
00205
00206 template <class PERM, class TRANS>
00207 BSGS<PERM,TRANS>::BSGS(const BSGS<PERM,TRANS>& bsgs)
00208 : BSGSCore<PERM,TRANS>(bsgs.m_id, bsgs.B, bsgs.U, bsgs.n),
00209 m_order(bsgs.m_order)
00210 {
00211 copyTransversals(bsgs);
00212 }
00213
00214 template <class PERM, class TRANS>
00215 BSGS<PERM,TRANS>& BSGS<PERM,TRANS>::operator=(const BSGS<PERM,TRANS>& bsgs) {
00216 if (this == &bsgs)
00217 return *this;
00218
00219 this->B = bsgs.B;
00220 this->n = bsgs.n;
00221 this->m_order = bsgs.m_order;
00222 this->m_id = bsgs.m_id;
00223
00224 copyTransversals(bsgs);
00225 return *this;
00226 }
00227
00228 template <class PERM, class TRANS>
00229 template <class BaseIterator, class TransversalIterator>
00230 uint BSGS<PERM, TRANS>::sift(const PERM& g, PERM& siftee, BaseIterator begin, BaseIterator end, TransversalIterator beginT, TransversalIterator endT) const{
00231 uint k = 0;
00232 siftee = g;
00233 BaseIterator baseIt;
00234 TransversalIterator transIt;
00235 for (baseIt = begin, transIt = beginT; baseIt != end && transIt != endT; ++baseIt, ++transIt) {
00236 ulong b = *baseIt;
00237 const TRANS& U_i = *transIt;
00238
00239 boost::scoped_ptr<PERM> u_b(U_i.at(siftee / b));
00240 if (u_b == 0)
00241 return k;
00242 u_b->invertInplace();
00243 siftee *= *u_b;
00244 ++k;
00245 }
00246 return k;
00247 }
00248
00249 template <class PERM, class TRANS>
00250 uint BSGS<PERM, TRANS>::sift(const PERM& g, PERM& siftee, uint j) const {
00251 return sift(g, siftee, this->B.begin() + j, this->B.end(), this->U.begin() + j, this->U.end());
00252 }
00253
00254 template <class PERM, class TRANS>
00255 uint BSGS<PERM, TRANS>::sift(const PERM& g, PERM& siftee, uint j, uint k) const {
00256 return sift(g, siftee, this->B.begin() + j, this->B.begin() + k, this->U.begin() + j, this->U.begin() + k);
00257 }
00258
00259 template <class PERM, class TRANS>
00260 bool BSGS<PERM, TRANS>::sifts(const PERM& g) const {
00261 PERM siftee(this->n);
00262 uint m = sift(g, siftee);
00263 return this->B.size() == m && siftee.isIdentity();
00264 }
00265
00266 template <class PERM, class TRANS>
00267 bool BSGS<PERM, TRANS>::chooseBaseElement(const PERM &h, ulong &beta) const {
00268 for (beta = 0; beta < this->n; ++beta) {
00269 if (std::find(this->B.begin(), this->B.end(), beta) != this->B.end())
00270 continue;
00271 if (h / beta != beta)
00272 return true;
00273 }
00274 return false;
00275 }
00276
00277 template <class PERM, class TRANS>
00278 void BSGS<PERM, TRANS>::orbit(uint j, const PERMlist &generators) {
00279 this->U[j].orbit(this->B[j], generators);
00280
00281 m_order = 0;
00282 }
00283
00284 template <class PERM, class TRANS>
00285 void BSGS<PERM, TRANS>::orbitUpdate(uint j, const PERMlist &generators, const PERMptr &g) {
00286 this->U[j].orbitUpdate(this->B[j], generators, g);
00287
00288 m_order = 0;
00289 }
00290
00291 template <class PERM, class TRANS>
00292 PERM BSGS<PERM, TRANS>::random(const int i) const {
00293 BOOST_ASSERT( i >= 0 );
00294 PERM g(this->n);
00295 for (int l = this->U.size()-1; l>=i ; --l) {
00296
00297 ulong beta = *(boost::next(this->U[l].begin(), randomInt(this->U[l].size())));
00298 boost::scoped_ptr<PERM> u_beta(this->U[l].at(beta));
00299 g *= *u_beta;
00300 }
00301 return g;
00302 }
00303
00304 template <class PERM, class TRANS>
00305 int BSGS<PERM, TRANS>::insertGenerator(const PERMptr& g, bool updateOrbit) {
00306 int pos = 0;
00307 for (; static_cast<uint>(pos) < this->B.size(); ++pos) {
00308 if (*g / this->B[pos] != this->B[pos])
00309 break;
00310 }
00311
00312 if (static_cast<uint>(pos) == this->B.size()) {
00313 ulong beta;
00314 bool newBaseElement __attribute__((unused)) = chooseBaseElement(*g, beta);
00315 BOOST_ASSERT( newBaseElement );
00316 this->B.push_back(beta);
00317 this->U.push_back(TRANS(this->n));
00318 }
00319
00320 const int insertionPosition = pos;
00321 this->S.push_back(g);
00322
00323 if (updateOrbit) {
00324 boost::uint64_t oldOrder = order();
00325
00326 for (; pos >= 0; --pos) {
00327 PERMlist orbitGenerators;
00328
00329 std::copy_if(this->S.begin(), this->S.end(), std::back_inserter(orbitGenerators),
00330 PointwiseStabilizerPredicate<PERM>(this->B.begin(), this->B.begin() + pos));
00331 if (orbitGenerators.size() > 0)
00332 orbitUpdate(pos, orbitGenerators, g);
00333 }
00334
00335 if (order() <= oldOrder) {
00336 this->S.pop_back();
00337 return -1;
00338 }
00339 }
00340
00341 return insertionPosition;
00342 }
00343
00344 template <class PERM, class TRANS>
00345 void BSGS<PERM, TRANS>::updateOrbits(int pos) {
00346 if (pos < 0)
00347 return;
00348 for (; pos >= 0; --pos) {
00349 PERMlist orbitGenerators;
00350 std::copy_if(this->S.begin(), this->S.end(), std::back_inserter(orbitGenerators),
00351 PointwiseStabilizerPredicate<PERM>(this->B.begin(), this->B.begin() + pos));
00352 if (orbitGenerators.size() > 0)
00353 orbit(pos, orbitGenerators);
00354 }
00355 }
00356
00357 template <class PERM, class TRANS>
00358 boost::uint64_t BSGS<PERM, TRANS>::order() const {
00359 if (m_order == 0) {
00360 m_order = 1;
00361 BOOST_FOREACH(const TRANS &Ui, this->U) {
00362 m_order *= Ui.size();
00363 }
00364 }
00365 return m_order;
00366 }
00367
00368
00369 template <class PERM, class TRANS>
00370 uint BSGS<PERM, TRANS>::insertRedundantBasePoint(uint beta, uint minPos) {
00371 PERMlist S_i;
00372 TrivialRedundantBasePointInsertionStrategy<PERM,TRANS> is(*this);
00373 int pos = is.findInsertionPoint(beta, S_i);
00374 if (pos < 0)
00375 return -(pos+1);
00376 pos = std::max(static_cast<uint>(pos), minPos);
00377
00378 this->B.insert(this->B.begin() + pos, beta);
00379 this->U.insert(this->U.begin() + pos, TRANS(this->n));
00380 this->U[pos].orbit(beta, S_i);
00381 return pos;
00382 }
00383
00384 template <class PERM, class TRANS>
00385 void BSGS<PERM, TRANS>::stripRedundantBasePoints(int minPos) {
00386 for (int i = this->B.size()-1; i >= minPos; --i) {
00387 if (this->U[i].size() <= 1) {
00388 if (i == static_cast<int>(this->B.size()-1)) {
00389 this->B.pop_back();
00390 this->U.pop_back();
00391 } else {
00392 this->B.erase(this->B.begin() + i);
00393 this->U.erase(this->U.begin() + i);
00394 }
00395 }
00396 }
00397 }
00398
00399 template <class PERM, class TRANS>
00400 void BSGS<PERM,TRANS>::copyTransversals(const BSGS<PERM,TRANS>& bsgs) {
00401 std::map<PERM*,PERMptr> genMap;
00402 BOOST_FOREACH(const PERMptr& p, bsgs.S) {
00403 boost::shared_ptr<PERM> deepcopy(new PERM(*p));
00404
00405 genMap.insert(std::make_pair(p.get(), deepcopy));
00406 this->S.push_back(deepcopy);
00407 }
00408 for (uint i=0; i<this->B.size(); ++i) {
00409 this->U[i] = bsgs.U[i].clone(genMap);
00410 }
00411 }
00412
00413 }
00414
00415 #endif // -- BSGS_H_