PermLib

random_schreier_sims_construction.h

00001 // ---------------------------------------------------------------------------
00002 //
00003 //  This file is part of PermLib.
00004 //
00005 // Copyright (c) 2009-2011 Thomas Rehn <thomas@carmen76.de>
00006 // All rights reserved.
00007 // 
00008 // Redistribution and use in source and binary forms, with or without
00009 // modification, are permitted provided that the following conditions
00010 // are met:
00011 // 1. Redistributions of source code must retain the above copyright
00012 //    notice, this list of conditions and the following disclaimer.
00013 // 2. Redistributions in binary form must reproduce the above copyright
00014 //    notice, this list of conditions and the following disclaimer in the
00015 //    documentation and/or other materials provided with the distribution.
00016 // 3. The name of the author may not be used to endorse or promote products
00017 //    derived from this software without specific prior written permission.
00018 // 
00019 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00020 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00021 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00022 // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00023 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00024 // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00025 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00026 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00028 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 //
00030 // ---------------------------------------------------------------------------
00031 
00032 
00033 #ifndef RANDOMSCHREIERSIMSCONSTRUCTION_H_
00034 #define RANDOMSCHREIERSIMSCONSTRUCTION_H_
00035 
00036 #include <permlib/construct/base_construction.h>
00037 #include <permlib/generator/random_generator.h>
00038 #include <permlib/bsgs.h>
00039 
00040 #include <boost/foreach.hpp>
00041 
00042 namespace permlib {
00043 
00045 
00049 template <class PERM, class TRANS>
00050 class RandomSchreierSimsConstruction : public BaseConstruction<PERM, TRANS> {
00051 public:
00053 
00058         RandomSchreierSimsConstruction(unsigned int n, RandomGenerator<PERM> *rng, unsigned long knownOrder = 0);
00059 
00061 
00063         template <class ForwardIterator>
00064         BSGS<PERM, TRANS> construct(ForwardIterator generatorsBegin, ForwardIterator generatorsEnd, bool& guaranteedBSGS) const;
00065 
00067 
00077         template <class ForwardIterator, class InputIterator>
00078         BSGS<PERM, TRANS> construct(ForwardIterator generatorsBegin, ForwardIterator generatorsEnd, InputIterator prescribedBaseBegin, InputIterator prescribedBaseEnd, bool& guaranteedBSGS) const;
00079 
00081         mutable unsigned int m_statRandomElementsConsidered;
00082 
00084         static const unsigned int minimalConsecutiveSiftingElementCount = 20;
00085         
00087         static const unsigned int maxIterationFactor = 10000;
00088 private:
00089         RandomGenerator<PERM> *m_rng;
00090         unsigned long m_knownOrder;
00091 };
00092 
00093 //
00094 //     ----       IMPLEMENTATION
00095 //
00096 
00097 template <class PERM, class TRANS>
00098 RandomSchreierSimsConstruction<PERM,TRANS>::RandomSchreierSimsConstruction(unsigned int n, RandomGenerator<PERM> *rng, unsigned long knownOrder) 
00099         : BaseConstruction<PERM, TRANS>(n), m_statRandomElementsConsidered(0), m_rng(rng), m_knownOrder(knownOrder)
00100 { }
00101 
00102 template <class PERM, class TRANS>
00103 template <class ForwardIterator>
00104 inline BSGS<PERM, TRANS> RandomSchreierSimsConstruction<PERM,TRANS>::construct(ForwardIterator generatorsBegin, ForwardIterator generatorsEnd, bool& guaranteedBSGS) const {
00105         return construct(generatorsBegin, generatorsEnd, BaseConstruction<PERM,TRANS>::empty, BaseConstruction<PERM,TRANS>::empty, guaranteedBSGS);
00106 }
00107 
00108 template <class PERM, class TRANS>
00109 template <class ForwardIterator, class InputIterator>
00110 BSGS<PERM, TRANS> RandomSchreierSimsConstruction<PERM, TRANS>
00111 	::construct(ForwardIterator generatorsBegin, ForwardIterator generatorsEnd, InputIterator prescribedBaseBegin, InputIterator prescribedBaseEnd, bool& guaranteedBSGS) const
00112 {
00113         const unsigned int &n = BaseConstruction<PERM, TRANS>::m_n;
00114         BSGS<PERM, TRANS> ret(n);
00115         std::vector<dom_int> &B = ret.B;
00116         std::vector<TRANS> &U = ret.U;
00117         std::vector<std::list<typename PERM::ptr> > S;
00118         setup(generatorsBegin, generatorsEnd, prescribedBaseBegin, prescribedBaseEnd, ret, S);
00119         
00120         unsigned int consecutiveSiftingElementCount = minimalConsecutiveSiftingElementCount;
00121         if (m_knownOrder > 0) 
00122                 // remove consecutive sifting limit if we have the group order as Las Vegas-abort criterion
00123                 consecutiveSiftingElementCount = maxIterationFactor;
00124         const unsigned int maxIterationCount = B.size() * maxIterationFactor;
00125         for (unsigned int it = 0; it < maxIterationCount; ++it) {
00126                 bool isProbableBSGS = true;
00127                 for (unsigned int i = 0; i < consecutiveSiftingElementCount && ret.order() != m_knownOrder; ++i) {
00128                         PERM g = m_rng->next();
00129                         ++m_statRandomElementsConsidered;
00130                         PERM h(n);
00131                         unsigned int j = ret.sift(g, h);
00132                         if (j < B.size() || !h.isIdentity()) {
00133                                 // flush it, because we add it as a generator
00134                                 h.flush();
00135                                 
00136                                 if (j == B.size()) {
00137                                         dom_int gamma = n+1;
00138                                         if (ret.chooseBaseElement(h, gamma)) {
00139                                                 B.push_back(gamma);
00140                                         }
00141                                         BOOST_ASSERT(j < B.size());
00142                                         S.push_back(std::list<typename PERM::ptr>());
00143                                         U.push_back(TRANS(n));
00144                                 }
00145                                 
00146                                 boost::shared_ptr<PERM> hPtr(new PERM(h));
00147                                 S[j].insert(S[j].end(), hPtr);
00148 
00149                                 ret.orbitUpdate(j, S[j], hPtr);
00150                                 isProbableBSGS = false;
00151                                 break;
00152                         }
00153                 }
00154                 if (isProbableBSGS)
00155                         break;
00156         }
00157         
00158         mergeGenerators(S, ret);
00159         
00160         // convinience check of group order
00161         guaranteedBSGS = ret.order() == m_knownOrder;
00162         
00163         return ret;
00164 }
00165 
00166 }
00167 
00168 #endif // -- RANDOMSCHREIERSIMSCONSTRUCTION_H_