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 GROUPREFINEMENT_H_ 00034 #define GROUPREFINEMENT_H_ 00035 00036 #include <permlib/predicate/pointwise_stabilizer_predicate.h> 00037 #include <permlib/search/partition/refinement.h> 00038 00039 namespace permlib { 00040 namespace partition { 00041 00043 template<class PERM,class TRANS> 00044 class GroupRefinement : public Refinement<PERM> { 00045 public: 00047 explicit GroupRefinement(const BSGSCore<PERM,TRANS>& bsgs); 00048 00049 virtual unsigned int apply(Partition& pi) const; 00050 virtual unsigned int apply2(Partition& pi, const PERM& t) const; 00051 00052 virtual bool init(Partition& pi); 00053 00055 const BSGSCore<PERM,TRANS>& bsgs() const; 00056 private: 00057 const BSGSCore<PERM,TRANS>& m_bsgs; 00058 00059 std::vector<unsigned long> thetaOrbit; 00060 std::vector<int> thetaBorder; 00061 00062 unsigned int apply2(Partition& pi, const PERM* t) const; 00063 }; 00064 00065 template<class PERM,class TRANS> 00066 GroupRefinement<PERM,TRANS>::GroupRefinement(const BSGSCore<PERM,TRANS>& bsgs) 00067 : Refinement<PERM>(bsgs.n, Group), m_bsgs(bsgs), thetaOrbit(m_bsgs.n), thetaBorder(m_bsgs.n, -1) 00068 { 00069 } 00070 00071 template<class PERM,class TRANS> 00072 unsigned int GroupRefinement<PERM,TRANS>::apply(Partition& pi) const { 00073 return apply2(pi, 0); 00074 } 00075 00076 template<class PERM,class TRANS> 00077 unsigned int GroupRefinement<PERM,TRANS>::apply2(Partition& pi, const PERM& t) const { 00078 return apply2(pi, &t); 00079 } 00080 00081 template<class PERM,class TRANS> 00082 unsigned int GroupRefinement<PERM,TRANS>::apply2(Partition& pi, const PERM* t) const { 00083 BOOST_ASSERT( this->initialized() ); 00084 00085 std::vector<unsigned long> myTheta(thetaOrbit); 00086 00087 std::vector<unsigned long>::iterator thetaIt; 00088 std::vector<unsigned long>::iterator thetaBeginIt, thetaEndIt; 00089 std::list<int>::const_iterator cellPairIt = Refinement<PERM>::m_cellPairs.begin(); 00090 unsigned int ret = false; 00091 while (cellPairIt != Refinement<PERM>::m_cellPairs.end()) { 00092 const int thetaC = *cellPairIt; 00093 ++cellPairIt; 00094 if (*cellPairIt < 0) { 00095 ++cellPairIt; 00096 continue; 00097 } 00098 00099 int borderLo = 0; 00100 if (thetaC > 0) 00101 borderLo = thetaBorder[thetaC-1]; 00102 thetaBeginIt = myTheta.begin() + borderLo; 00103 thetaEndIt = myTheta.begin() + thetaBorder[thetaC]; 00104 00105 if (t) { 00106 for (thetaIt = thetaBeginIt; thetaIt != thetaEndIt; ++thetaIt) { 00107 *thetaIt = *t / *thetaIt; 00108 } 00109 std::sort(thetaBeginIt, thetaEndIt); 00110 } 00111 00112 for (int c = *cellPairIt; c >= 0; c = *(++cellPairIt)) { 00113 if (t) { 00114 PERMLIB_DEBUG(std::cout << "apply theta " << thetaC << "," << c << " t = " << *t << " to " << pi << std::endl;) 00115 } else { 00116 PERMLIB_DEBUG(std::cout << "apply theta " << thetaC << "," << c << " t = 0 to " << pi << std::endl;) 00117 } 00118 //print_iterable(thetaBeginIt, thetaEndIt, 1, "theta apply"); 00119 if (pi.intersect(thetaBeginIt, thetaEndIt, c)) 00120 ++ret; 00121 } 00122 ++cellPairIt; 00123 } 00124 00125 return ret; 00126 } 00127 00128 template<class PERM,class TRANS> 00129 bool GroupRefinement<PERM,TRANS>::init(Partition& pi) { 00130 unsigned int fixSize = pi.fixPointsSize(); 00131 if (fixSize > 0) { 00132 boost::dynamic_bitset<> orbitCharacterstic(m_bsgs.n); 00133 00134 std::vector<dom_int>::const_iterator Bit; 00135 std::vector<unsigned long>::const_iterator fixIt = pi.fixPointsBegin(); 00136 std::vector<unsigned long>::const_iterator fixEndIt = pi.fixPointsEnd(); 00137 for (Bit = m_bsgs.B.begin(); Bit != m_bsgs.B.end(); ++Bit) { 00138 while (fixIt != fixEndIt && *fixIt != *Bit) { 00139 PERMLIB_DEBUG(std::cout << "skip " << (*fixIt + 1) << " for " << (*Bit + 1) << std::endl;) 00140 ++fixIt; 00141 } 00142 if (fixIt == fixEndIt) 00143 break; 00144 ++fixIt; 00145 } 00146 //PointwiseStabilizerPredicate<PERM> fixStab(m_bsgs.B.begin(), m_bsgs.B.begin() + std::min(fixSize, static_cast<unsigned int>(m_bsgs.B.size()))); 00147 #ifdef PERMLIB_DEBUG_OUTPUT 00148 print_iterable(m_bsgs.B.begin(), m_bsgs.B.end(), 1, " BSGS "); 00149 print_iterable(m_bsgs.B.begin(), Bit, 1, "to fix"); 00150 print_iterable(pi.fixPointsBegin(), pi.fixPointsEnd(), 1, " fix"); 00151 #endif 00152 PointwiseStabilizerPredicate<PERM> fixStab(m_bsgs.B.begin(), Bit); 00153 std::list<PERM> S_fix; 00154 BOOST_FOREACH(const typename PERM::ptr& p, m_bsgs.S) { 00155 if (fixStab(p)) { 00156 //std::cout << "$ " << *p << " fixes " << std::min(fixSize, static_cast<unsigned long>(m_bsgs.B.size())) << " points" << std::endl; 00157 S_fix.push_back(*p); 00158 } 00159 } 00160 00161 unsigned int thetaIndex = 0; 00162 std::vector<int>::iterator thetaBorderIt = thetaBorder.begin(); 00163 std::vector<unsigned long>::iterator thetaIt = thetaOrbit.begin(); 00164 for (unsigned long alpha = 0; alpha < m_bsgs.n; ++alpha) { 00165 if (orbitCharacterstic[alpha]) 00166 continue; 00167 orbitCharacterstic.flip(alpha); 00168 std::vector<unsigned long>::iterator thetaOrbitBeginIt = thetaIt; 00169 *thetaIt = alpha; 00170 ++thetaIt; 00171 ++thetaIndex; 00172 std::vector<unsigned long>::iterator thetaOrbitEndIt = thetaIt; 00173 00174 std::vector<unsigned long>::iterator it; 00175 for (it = thetaOrbitBeginIt; it != thetaOrbitEndIt; ++it) { 00176 unsigned long beta = *it; 00177 BOOST_FOREACH(const PERM &p, S_fix) { 00178 unsigned long beta_p = p / beta; 00179 if (!orbitCharacterstic[beta_p]) { 00180 *thetaIt = beta_p; 00181 ++thetaIt; 00182 ++thetaOrbitEndIt; 00183 ++thetaIndex; 00184 orbitCharacterstic.flip(beta_p); 00185 } 00186 } 00187 } 00188 *thetaBorderIt = thetaIndex; 00189 ++thetaBorderIt; 00190 } 00191 00192 thetaIt = thetaOrbit.begin(); 00193 std::vector<unsigned long>::iterator thetaItEnd; 00194 thetaBorderIt = thetaBorder.begin(); 00195 unsigned int thetaC = 0; 00196 int oldBorder = 0; 00197 while (thetaBorderIt != thetaBorder.end() && *thetaBorderIt >= 0) { 00198 thetaItEnd = thetaOrbit.begin() + *thetaBorderIt; 00199 std::sort(thetaIt, thetaItEnd); 00200 00201 if (*thetaBorderIt - oldBorder != 1 || std::find(pi.fixPointsBegin(), pi.fixPointsEnd(), *thetaIt) == pi.fixPointsEnd()) { 00202 bool hasTheta = false; 00203 const unsigned int oldCellNumber = pi.cells(); 00204 for (unsigned int c = 0; c < oldCellNumber; ++c) { 00205 if (pi.cellSize(c) == 1) 00206 continue; 00207 00208 //std::cout << " theta pi = " << pi << std::endl; 00209 //print_iterable(thetaIt, thetaItEnd, 1, "theta prep"); 00210 if (pi.intersect(thetaIt, thetaItEnd, c)) { 00211 PERMLIB_DEBUG(std::cout << "prepare theta " << thetaC << "," << c << std::endl;) 00212 //print_iterable(thetaIt, thetaItEnd, 1, "theta prep"); 00213 if (!hasTheta) { 00214 Refinement<PERM>::m_cellPairs.push_back(thetaC); 00215 hasTheta = true; 00216 } 00217 Refinement<PERM>::m_cellPairs.push_back(c); 00218 //std::cout << (thetaIt - thetaOrbit.begin()) << " - " << (thetaItEnd - thetaOrbit.begin()) << std::endl; 00219 } 00220 //std::cout << "pii = " << pi << std::endl; 00221 } 00222 00223 if (hasTheta) 00224 Refinement<PERM>::m_cellPairs.push_back(-1); 00225 } 00226 00227 oldBorder = *thetaBorderIt; 00228 thetaIt = thetaItEnd; 00229 ++thetaC; 00230 ++thetaBorderIt; 00231 } 00232 //print_iterable(Refinement<PERM>::m_cellPairs.begin(), Refinement<PERM>::m_cellPairs.end(), 0, "cell pairs"); 00233 if (!Refinement<PERM>::m_cellPairs.empty()) { 00234 typename Refinement<PERM>::RefinementPtr ref(new GroupRefinement<PERM,TRANS>(*this)); 00235 Refinement<PERM>::m_backtrackRefinements.push_back(ref); 00236 return true; 00237 } 00238 } 00239 00240 return false; 00241 } 00242 00243 template<class PERM,class TRANS> 00244 const BSGSCore<PERM,TRANS>& GroupRefinement<PERM,TRANS>::bsgs() const { 00245 return m_bsgs; 00246 } 00247 00248 } 00249 } 00250 00251 #endif // -- GROUPREFINEMENT_H_