PermLib
|
00001 // --------------------------------------------------------------------------- 00002 // 00003 // This file is part of PermLib. 00004 // 00005 // Copyright (c) 2009-2012 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 #include <boost/shared_ptr.hpp> 00033 #include <boost/scoped_ptr.hpp> 00034 #include <boost/iterator/counting_iterator.hpp> 00035 00036 #include <algorithm> 00037 00038 #include <permlib/abstract_permutation_group.h> 00039 #include <permlib/abstract_bsgs_helpers.h> 00040 00041 #include <permlib/change/random_base_transpose.h> 00042 #include <permlib/change/conjugating_base_change.h> 00043 #include <permlib/search/classic/set_stabilizer_search.h> 00044 #include <permlib/search/orbit_lex_min_search.h> 00045 00046 #ifndef ABSTRACT_BSGS_H_ 00047 #define ABSTRACT_BSGS_H_ 00048 00049 namespace permlib { 00050 00052 template<typename TRANS> 00053 class AbstractBSGS : public AbstractPermutationGroup { 00054 public: 00056 typedef BSGS<typename TRANS::PERMtype, TRANS> PermutationGroup; 00058 00062 AbstractBSGS(const boost::shared_ptr<PermutationGroup>& bsgs_, bool computeSupport = true); 00063 00064 virtual AbstractPermutationGroup* setStabilizer(const std::vector<dom_int>& s) const; 00065 virtual OrbitList* orbits() const; 00066 virtual OrbitList* orbits(const std::vector<dom_int>& s) const; 00067 virtual bool isLexMinSet(const std::vector<dom_int>& setIndices, const std::vector<dom_int>& rankIndices) const; 00068 virtual AbstractGroupType type() const { return AGT_BSGS; } 00069 00071 std::list<typename TRANS::PERMtype::ptr> generators() const; 00072 00074 const boost::shared_ptr<PermutationGroup> bsgs() const { return m_bsgs; } 00075 protected: 00076 virtual void transversalSizes(std::vector<unsigned long>& sizes) const; 00077 00078 template<typename Iterator> 00079 OrbitList* orbits(Iterator begin, Iterator end) const; 00080 00082 helpers::BaseSupportRestriction* supportRestriction(const std::vector<dom_int>& s) const; 00083 private: 00084 const boost::shared_ptr<PermutationGroup> m_bsgs; 00085 boost::shared_ptr<std::set<dom_int> > m_support; 00086 }; 00087 00088 00089 template<typename TRANS> 00090 AbstractBSGS<TRANS>::AbstractBSGS(const boost::shared_ptr<PermutationGroup>& bsgs_, bool computeSupport) 00091 : m_bsgs(bsgs_) 00092 { 00093 if ( ! computeSupport ) 00094 return; 00095 00096 m_support.reset( new std::set<dom_int>() ); 00097 BOOST_FOREACH(const typename TRANS::PERMtype::ptr& p, m_bsgs->S) { 00098 for (dom_int i = 0; i < m_bsgs->n; ++i) { 00099 if (p->at(i) != i) 00100 m_support->insert(i); 00101 } 00102 } 00103 } 00104 00105 template <class TRANS> 00106 void AbstractBSGS<TRANS>::transversalSizes(std::vector<unsigned long>& sizes) const { 00107 sizes.clear(); 00108 sizes.reserve(m_bsgs->U.size()); 00109 BOOST_FOREACH(const TRANS &Ui, m_bsgs->U) { 00110 sizes.push_back(Ui.size()); 00111 } 00112 } 00113 00114 template <class TRANS> 00115 AbstractPermutationGroup* AbstractBSGS<TRANS>::setStabilizer(const std::vector<dom_int>& s) const { 00116 if (s.empty()) 00117 return new AbstractBSGS<TRANS>(*this); 00118 00119 boost::scoped_ptr<helpers::BaseSupportRestriction> supRestriction( supportRestriction(s) ); 00120 if ( supRestriction->canBeIgnored() ) 00121 return new AbstractBSGS<TRANS>(*this); 00122 const std::vector<dom_int>* setToStabilize = supRestriction->set(); 00123 BOOST_ASSERT( setToStabilize ); 00124 00125 typedef typename TRANS::PERMtype PERM; 00126 PermutationGroup copy(*m_bsgs); 00127 // change the base so that is prefixed by the set 00128 ConjugatingBaseChange<PERM, TRANS, 00129 RandomBaseTranspose<PERM, TRANS> > baseChange(copy); 00130 baseChange.change(copy, setToStabilize->begin(), setToStabilize->end()); 00131 00132 // prepare search without DCM pruning 00133 classic::SetStabilizerSearch<BSGS<PERM, TRANS>, TRANS> backtrackSearch(copy, 0); 00134 backtrackSearch.construct(setToStabilize->begin(), setToStabilize->end()); 00135 00136 // start the search 00137 boost::shared_ptr<PermutationGroup> stabilizer(new PermutationGroup(copy.n)); 00138 backtrackSearch.search(*stabilizer); 00139 return new AbstractBSGS<TRANS>(stabilizer, m_support); 00140 } 00141 00142 template <class TRANS> 00143 AbstractPermutationGroup::OrbitList* AbstractBSGS<TRANS>::orbits() const { 00144 return this->orbits(boost::counting_iterator<dom_int>(0), boost::counting_iterator<dom_int>(m_bsgs->n)); 00145 } 00146 00147 template <class TRANS> 00148 AbstractPermutationGroup::OrbitList* AbstractBSGS<TRANS>::orbits(const std::vector<dom_int>& s) const { 00149 return this->orbits(s.begin(), s.end()); 00150 } 00151 00152 template <class TRANS> 00153 template<typename Iterator> 00154 AbstractPermutationGroup::OrbitList* AbstractBSGS<TRANS>::orbits(Iterator begin, Iterator end) const { 00155 OrbitList* retList = new OrbitList(); 00156 00157 for (Iterator it = begin; it != end; ++it) { 00158 const dom_int& alpha = *it; 00159 bool knownElement = false; 00160 BOOST_FOREACH(const std::set<dom_int>& orb, *retList) { 00161 if (orb.find(alpha) != orb.end()) { 00162 knownElement = true; 00163 break; 00164 } 00165 } 00166 00167 if (knownElement) 00168 continue; 00169 00170 typedef typename TRANS::PERMtype PERM; 00171 OrbitSet<PERM,dom_int> orbit; 00172 orbit.orbit(alpha, m_bsgs->S, typename Transversal<PERM>::TrivialAction()); 00173 retList->push_back(std::set<dom_int>(orbit.begin(), orbit.end())); 00174 } 00175 00176 return retList; 00177 } 00178 00179 template <class TRANS> 00180 bool AbstractBSGS<TRANS>::isLexMinSet(const std::vector<dom_int>& setIndices, const std::vector<dom_int>& rankIndices) const { 00181 if (setIndices.empty()) 00182 return true; 00183 00184 boost::scoped_ptr<helpers::BaseSupportRestriction> supRestriction( supportRestriction(setIndices) ); 00185 if ( supRestriction->canBeIgnored() ) 00186 return true; 00187 const std::vector<dom_int>* setToLexMin = supRestriction->set(); 00188 BOOST_ASSERT( setToLexMin ); 00189 00190 typedef typename TRANS::PERMtype PERM; 00191 const unsigned int n = m_bsgs->n; 00192 00193 // compute a permutation that we can use for conjugation 00194 typename PERM::perm conjugatingPerm(n); 00195 00196 // rank indices shall be mapped to 1,2,3,4,5,... 00197 unsigned int i = 0; 00198 dset rankSet(n); 00199 for (std::vector<dom_int>::const_iterator it = rankIndices.begin(); it != rankIndices.end(); ++it) 00200 { 00201 conjugatingPerm[*it] = i; 00202 rankSet[*it] = 1; 00203 ++i; 00204 } 00205 00206 // fill up the rest arbitrarily so that we get a proper permutation 00207 unsigned int v = 0; 00208 for ( ; i < n; ++i ) 00209 { 00210 while (rankSet[v]) 00211 ++v; 00212 conjugatingPerm[v] = i; 00213 ++v; 00214 } 00215 00216 PERM c(conjugatingPerm); 00217 PermutationGroup conjugatedBSGS(*m_bsgs); 00218 conjugatedBSGS.conjugate(c); 00219 00220 dset rankedTestSet(n); 00221 for (std::vector<dom_int>::const_iterator it = setToLexMin->begin(); it != setToLexMin->end(); ++it) 00222 { 00223 rankedTestSet[c / *it] = 1; 00224 } 00225 00226 OrbitLexMinSearch<PermutationGroup> orbLexMin(conjugatedBSGS, true); 00227 const bool t = ( orbLexMin.lexMin(rankedTestSet) == rankedTestSet ); 00228 return t; 00229 } 00230 00231 template <class TRANS> 00232 std::list<typename TRANS::PERMtype::ptr> AbstractBSGS<TRANS>::generators() const { 00233 return m_bsgs->S; 00234 } 00235 00236 template <class TRANS> 00237 helpers::BaseSupportRestriction* AbstractBSGS<TRANS>::supportRestriction(const std::vector<dom_int>& s) const { 00238 BOOST_ASSERT( m_bsgs ); 00239 if ( ! m_support ) 00240 return new helpers::BaseSupportRestriction(m_support, s); 00241 00242 // don't use full support restriction if the group base is small 00243 if (m_bsgs->B.size() <= 10 ) 00244 return new helpers::ReducedSupportRestriction(m_support, s); 00245 00246 return new helpers::FullSupportRestriction(m_support, s); 00247 } 00248 00249 } // end NS permlib 00250 00251 #endif