PermLib
|
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 CONJUGATINGBASECHANGE_H_ 00034 #define CONJUGATINGBASECHANGE_H_ 00035 00036 #include <boost/foreach.hpp> 00037 #include <boost/scoped_ptr.hpp> 00038 #include <boost/cstdint.hpp> 00039 00040 #include <permlib/change/base_change.h> 00041 00042 namespace permlib { 00043 00044 template<class PERM> 00045 struct SymmetricGroup; 00046 00047 template<class PERM,class TRANS> 00048 struct BSGS; 00049 00051 template<class PERM, class TRANS, class BASETRANSPOSE> 00052 class ConjugatingBaseChange : public BaseChange<PERM,TRANS> { 00053 public: 00055 explicit ConjugatingBaseChange(const BSGSCore<PERM,TRANS>&); 00056 00058 template <class InputIterator> 00059 unsigned int change(BSGS<PERM,TRANS> &bsgs, InputIterator baseBegin, InputIterator baseEnd, bool skipRedundant = false) const; 00060 00062 template <class InputIterator> 00063 unsigned int change(SymmetricGroup<PERM> &bsgs, InputIterator baseBegin, InputIterator baseEnd, bool skipRedundant = false) const; 00064 }; 00065 00066 template<class PERM, class TRANS, class BASETRANSPOSE> 00067 ConjugatingBaseChange<PERM,TRANS,BASETRANSPOSE>::ConjugatingBaseChange(const BSGSCore<PERM,TRANS>&) 00068 : BaseChange<PERM,TRANS>() 00069 { } 00070 00071 template<class PERM, class TRANS, class BASETRANSPOSE> 00072 template<class InputIterator> 00073 unsigned int ConjugatingBaseChange<PERM,TRANS,BASETRANSPOSE>::change(BSGS<PERM,TRANS> &bsgs, InputIterator baseBegin, InputIterator baseEnd, bool skipRedundant) const { 00074 if (baseBegin == baseEnd) 00075 return 0; 00076 00077 const boost::uint64_t origOrder __attribute__((unused)) = bsgs.order(); 00078 BASETRANSPOSE trans; 00079 PERM c(bsgs.n); 00080 PERM cInv(bsgs.n); 00082 bool touchedC = false; 00083 00084 unsigned int baseTargetPos = 0; 00085 while (baseBegin != baseEnd && baseTargetPos < bsgs.B.size()) { 00086 const unsigned long alpha = cInv.at(*baseBegin); 00087 const unsigned long beta = bsgs.B[baseTargetPos]; 00088 const bool redundant = skipRedundant && isRedundant(bsgs, baseTargetPos, alpha); 00089 00090 if (!redundant && beta != alpha) { 00091 boost::scoped_ptr<PERM> r(bsgs.U[baseTargetPos].at(alpha)); 00092 if (r) { 00093 c ^= *r; 00094 cInv = ~c; 00095 touchedC = true; 00096 } else { 00097 unsigned int pos = bsgs.insertRedundantBasePoint(alpha, baseTargetPos); 00098 for (; pos > baseTargetPos; --pos) { 00099 trans.transpose(bsgs, pos-1); 00100 ++BaseChange<PERM,TRANS>::m_statTranspositions; 00101 } 00102 } 00103 } 00104 if (!redundant) 00105 ++baseTargetPos; 00106 00107 ++baseBegin; 00108 } 00109 00110 // insert remaining base points 00111 while (!skipRedundant && baseBegin != baseEnd) { 00112 const unsigned long alpha = cInv.at(*baseBegin); 00113 bsgs.insertRedundantBasePoint(alpha, baseTargetPos); 00114 00115 ++baseBegin; 00116 ++baseTargetPos; 00117 } 00118 00119 if (touchedC) { 00120 // correct generators by conjugation 00121 BOOST_FOREACH(typename PERM::ptr& g, bsgs.S) { 00122 *g ^= cInv; 00123 *g *= c; 00124 g->flush(); 00125 } 00126 00127 // correct base points 00128 BOOST_FOREACH(dom_int& beta, bsgs.B) { 00129 beta = c.at(beta); 00130 } 00131 } 00132 00133 // always strip redundant base points from the end of the new base 00134 bsgs.stripRedundantBasePoints(baseTargetPos); 00135 BaseChange<PERM,TRANS>::m_statScheierGeneratorsConsidered += trans.m_statScheierGeneratorsConsidered; 00136 00137 if (touchedC) { 00138 for (unsigned int i=0; i<bsgs.B.size(); ++i) { 00139 //std::cout << " ~~ permute " << bsgs.B[i] << std::endl; 00140 bsgs.U[i].permute(c, cInv); 00141 } 00142 } 00143 00144 BOOST_ASSERT(origOrder == bsgs.order()); 00145 00146 return baseTargetPos; 00147 } 00148 00149 template<class PERM, class TRANS, class BASETRANSPOSE> 00150 template<class InputIterator> 00151 unsigned int ConjugatingBaseChange<PERM,TRANS,BASETRANSPOSE>::change(SymmetricGroup<PERM> &bsgs, InputIterator baseBegin, InputIterator baseEnd, bool skipRedundant) const { 00152 unsigned int basePos = 0; 00153 while (baseBegin != baseEnd) { 00154 //std::cout << "base prefix " << *baseBegin << std::endl; 00155 for (unsigned int i = basePos; i < bsgs.B.size(); ++i) { 00156 if (bsgs.B[i] == *baseBegin) { 00157 std::swap(bsgs.B[i], bsgs.B[basePos]); 00158 //std::cout << " swap " << i << " and " << basePos << std::endl; 00159 break; 00160 } 00161 } 00162 ++basePos; 00163 ++baseBegin; 00164 } 00165 return basePos; 00166 } 00167 00168 } 00169 00170 #endif // -- CONJUGATINGBASECHANGE_H_