PermLib
abstract_bsgs.h
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