PermLib

base_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 BASECONSTRUCTION_H
00034 #define BASECONSTRUCTION_H
00035 
00036 #include <map>
00037 
00038 #include <permlib/predicate/pointwise_stabilizer_predicate.h>
00039 
00040 namespace permlib {
00041 
00043 template <class PERM, class TRANS>
00044 class BaseConstruction {
00045 public:
00047 
00050         explicit BaseConstruction(dom_int n);
00051 protected:
00053         dom_int m_n;
00054         
00056 
00064         template <class ForwardIterator, class InputIterator>
00065         void setup(ForwardIterator generatorsBegin, ForwardIterator generatorsEnd, InputIterator prescribedBaseBegin, InputIterator prescribedBaseEnd, BSGS<PERM, TRANS> &bsgs, std::vector<std::list<typename PERM::ptr> > &S) const;
00066         
00068         void mergeGenerators(std::vector<std::list<typename PERM::ptr> >& S, BSGS<PERM,TRANS>& ret) const;
00069         
00071         static const unsigned long *empty;
00072 };
00073 
00074 //
00075 //     ----       IMPLEMENTATION
00076 //
00077 
00078 template <class PERM, class TRANS>
00079 const unsigned long *BaseConstruction<PERM, TRANS>::empty = static_cast<unsigned long*>(0);
00080 
00081 
00082 template <class PERM, class TRANS>
00083 BaseConstruction<PERM,TRANS>::BaseConstruction(dom_int n) 
00084         : m_n(n) 
00085 { }
00086 
00087 template <class PERM, class TRANS>
00088 template <class ForwardIterator, class InputIterator>
00089 void BaseConstruction<PERM,TRANS>::setup(ForwardIterator generatorsBegin, ForwardIterator generatorsEnd, InputIterator prescribedBaseBegin, InputIterator prescribedBaseEnd, BSGS<PERM, TRANS> &bsgs, std::vector<std::list<typename PERM::ptr> > &S) const
00090 {
00091         std::vector<dom_int> &B = bsgs.B;
00092         std::vector<TRANS> &U = bsgs.U;
00093 
00094         B.insert(B.begin(), prescribedBaseBegin, prescribedBaseEnd);
00095 
00096         // extend base so that no group element fixes all base elements
00097         dom_int beta = m_n + 1;
00098         PointwiseStabilizerPredicate<PERM> stab_k(B.begin(), B.end());
00099         for (ForwardIterator genIt = generatorsBegin ; genIt != generatorsEnd; ++genIt) {
00100                 const typename PERM::ptr &gen = *genIt;
00101                 if (stab_k(gen)) {
00102                         if (bsgs.chooseBaseElement(*gen, beta)) {
00103                                 B.push_back(beta);
00104                                 stab_k = PointwiseStabilizerPredicate<PERM>(B.begin(), B.end());
00105                         }
00106                 }
00107         }
00108         BOOST_ASSERT(!B.empty());
00109 
00110         // pre-compute transversals and fundamental orbits for the current base
00111         unsigned int i = 0;
00112         std::vector<dom_int>::iterator Bit;
00113         for (Bit = B.begin(); Bit != B.end(); ++Bit) {
00114                 std::list<typename PERM::ptr> S_i;
00115                 std::copy_if(generatorsBegin, generatorsEnd,
00116                                 std::back_inserter(S_i), PointwiseStabilizerPredicate<PERM>(B.begin(), Bit));
00117 
00118                 U.push_back(TRANS(m_n));
00119                 S.push_back(S_i);
00120 
00121                 bsgs.orbit(i, S_i);
00122 
00123                 ++i;
00124         }
00125 }
00126 
00127 template <class PERM, class TRANS>
00128 void BaseConstruction<PERM,TRANS>::mergeGenerators(std::vector<std::list<typename PERM::ptr> >& S, BSGS<PERM,TRANS>& ret) const {
00129         std::map<PERM*,typename PERM::ptr> generatorMap;
00130         // merge all generators into one list
00131         BOOST_FOREACH(std::list<typename PERM::ptr> &S_j, S) {
00132                 BOOST_FOREACH(typename PERM::ptr &gen, S_j) {
00133                         bool found = false;
00134                         BOOST_FOREACH(const typename PERM::ptr& genS, ret.S) {
00135                                 if (*genS == *gen) {
00136                                         found = true;
00137                                         generatorMap.insert(std::make_pair(gen.get(), genS));
00138                                         break;
00139                                 }
00140                         }
00141                         if (!found) {
00142                                 ret.S.push_back(gen);
00143                                 generatorMap.insert(std::make_pair(gen.get(), gen));
00144                         }
00145                 }
00146         }
00147         BOOST_FOREACH(TRANS& U_i, ret.U) {
00148                 U_i.updateGenerators(generatorMap);
00149         }
00150 }
00151 
00152 }
00153 
00154 #endif // -- BASECONSTRUCTION_H