PermLib

group_refinement.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 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_