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 SCHREIERTRANSVERSAL_H_ 00034 #define SCHREIERTRANSVERSAL_H_ 00035 00036 #include <permlib/transversal/transversal.h> 00037 00038 namespace permlib { 00039 00041 template <class PERM> 00042 class SchreierTreeTransversal : public Transversal<PERM> { 00043 public: 00045 SchreierTreeTransversal(unsigned int n); 00046 00047 virtual bool trivialByDefinition(const PERM& x, unsigned long to) const; 00048 virtual PERM* at(unsigned long val) const; 00049 00050 virtual void updateGenerators(const std::map<PERM*,typename PERM::ptr>& generatorChange); 00051 00053 00057 SchreierTreeTransversal<PERM> clone(const std::map<PERM*,typename PERM::ptr>& generatorChange) const; 00058 00060 mutable unsigned int m_statMaxDepth; 00061 protected: 00062 virtual void registerMove(unsigned long from, unsigned long to, const typename PERM::ptr &p); 00063 }; 00064 00065 // 00066 // ---- IMPLEMENTATION 00067 // 00068 00069 template <class PERM> 00070 SchreierTreeTransversal<PERM>::SchreierTreeTransversal(unsigned int n) 00071 : Transversal<PERM>(n), m_statMaxDepth(0) 00072 { } 00073 00074 template <class PERM> 00075 bool SchreierTreeTransversal<PERM>::trivialByDefinition(const PERM& x, unsigned long to) const { 00076 return *Transversal<PERM>::m_transversal[to] == x; 00077 } 00078 00079 template <class PERM> 00080 void SchreierTreeTransversal<PERM>::registerMove(unsigned long from, unsigned long to, const typename PERM::ptr &p) { 00081 Transversal<PERM>::registerMove(from, to, p); 00082 Transversal<PERM>::m_transversal[to] = p; 00083 } 00084 00085 00086 template <class PERM> 00087 PERM* SchreierTreeTransversal<PERM>::at(unsigned long val) const { 00088 const std::vector<boost::shared_ptr<PERM> > &transversal = Transversal<PERM>::m_transversal; 00089 00090 if (transversal[val] == 0) { 00091 return 0; 00092 } 00093 00094 unsigned int depth = 1; 00095 PERM *res = new PERM(*transversal[val]); 00096 const PERM* inv = 0; 00097 //std::cout << "Schreier " << *res << std::endl; 00098 unsigned long pred = *res % val; 00099 //TODO: reserve space for PermutationWord-res beforehand (we know how long the m_word vector will be) 00100 while (pred != val) { 00101 inv = transversal[pred].get(); 00102 //std::cout << "Schreier2 " << inv << " / " << val << " , " << pred << std::endl; 00103 *res ^= *inv; 00104 val = pred; 00105 pred = *inv % pred; 00106 ++depth; 00107 } 00108 m_statMaxDepth = std::max(m_statMaxDepth, depth); 00109 //std::cout << "Schreier3 " << *res << std::endl; 00110 return res; 00111 } 00112 00113 template <class PERM> 00114 void SchreierTreeTransversal<PERM>::updateGenerators(const std::map<PERM*,typename PERM::ptr>& generatorChange) { 00115 unsigned int missedCount = 0; 00116 BOOST_FOREACH(typename PERM::ptr& p, this->m_transversal) { 00117 if (!p) 00118 continue; 00119 //std::cout << "require " << p.get() << std::endl; 00120 typename std::map<PERM*,typename PERM::ptr>::const_iterator pIt = generatorChange.find(p.get()); 00121 //BOOST_ASSERT( pIt != generatorChange.end() ); 00122 if (pIt != generatorChange.end()) { 00123 p = (*pIt).second; 00124 } else { 00125 ++missedCount; 00126 //std::cout << "missed " << p.get() << " = " << *p << std::endl; 00127 } 00128 } 00129 // we always miss the identity -- and not anything else 00130 BOOST_ASSERT( missedCount == 1 ); 00131 } 00132 00133 template <class PERM> 00134 SchreierTreeTransversal<PERM> SchreierTreeTransversal<PERM>::clone(const std::map<PERM*,typename PERM::ptr>& generatorChange) const { 00135 SchreierTreeTransversal<PERM> ret(*this); 00136 ret.updateGenerators(generatorChange); 00137 return ret; 00138 } 00139 00140 } 00141 00142 #endif // -- SCHREIERTRANSVERSAL_H_