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 TRANSVERSAL_H_ 00034 #define TRANSVERSAL_H_ 00035 00036 #include <permlib/sorter/base_sorter.h> 00037 #include <permlib/transversal/orbit.h> 00038 00039 #include <map> 00040 #include <list> 00041 #include <vector> 00042 00043 #include <boost/foreach.hpp> 00044 #include <boost/shared_ptr.hpp> 00045 00046 namespace permlib { 00047 00048 template <class PERM> 00049 class Transversal; 00050 00051 template <class PERM> 00052 std::ostream &operator<< (std::ostream &out, const Transversal<PERM> &t) { 00053 out << "{"; 00054 BOOST_FOREACH (boost::shared_ptr<PERM> p, t.m_transversal) { 00055 if (p) 00056 out << *p << ", "; 00057 else 00058 out << "O, "; 00059 } 00060 out << "}"; 00061 return out; 00062 } 00063 00065 template <class PERM> 00066 class Transversal : public Orbit<PERM,unsigned long> { 00067 public: 00069 00072 Transversal(unsigned int n); 00074 virtual ~Transversal() {} 00075 00077 virtual PERM* at(unsigned long val) const = 0; 00078 00080 virtual bool trivialByDefinition(const PERM& x, unsigned long to) const = 0; 00081 00083 virtual bool contains(const unsigned long& val) const; 00084 00086 std::list<unsigned long>::const_iterator begin() const { return this->m_orbit.begin(); }; 00088 std::list<unsigned long>::const_iterator end() const { return this->m_orbit.end(); }; 00089 00091 unsigned int size() const { return this->m_orbit.size(); } 00092 00094 inline unsigned int n() const { return m_n; } 00095 00097 00101 template <class InputIterator> 00102 void sort(InputIterator Bbegin, InputIterator Bend); 00103 00105 inline bool sorted() const { return m_sorted; } 00106 00108 struct TrivialAction { 00110 unsigned long operator()(const PERM &p, unsigned long v) const { 00111 return p / v; 00112 } 00113 }; 00114 00116 00120 virtual void orbit(unsigned long alpha, const std::list<typename PERM::ptr> &generators); 00122 00127 virtual void orbitUpdate(unsigned long alpha, const std::list<typename PERM::ptr> &generators, const typename PERM::ptr &g); 00128 00130 00134 virtual void permute(const PERM& g, const PERM& gInv); 00136 00139 virtual void updateGenerators(const std::map<PERM*,typename PERM::ptr>& generatorChange) {} 00140 00141 virtual const unsigned long& element() const; 00142 00144 friend std::ostream &operator<< <> (std::ostream &out, const Transversal<PERM> &p); 00145 protected: 00147 unsigned int m_n; 00148 00150 std::vector<boost::shared_ptr<PERM> > m_transversal; 00151 00153 std::list<unsigned long> m_orbit; 00154 00156 bool m_sorted; 00157 00159 virtual void registerMove(unsigned long from, unsigned long to, const typename PERM::ptr &p); 00160 00161 virtual bool foundOrbitElement(const unsigned long& alpha, const unsigned long& alpha_p, const typename PERM::ptr& p); 00162 }; 00163 00164 // 00165 // ---- IMPLEMENTATION 00166 // 00167 00168 template <class PERM> 00169 Transversal<PERM>::Transversal(unsigned int n) 00170 : m_n(n), m_transversal(n), m_sorted(false) 00171 { } 00172 00173 template <class PERM> 00174 void Transversal<PERM>::orbit(unsigned long beta, const std::list<typename PERM::ptr> &generators) { 00175 Orbit<PERM,unsigned long>::orbit(beta, generators, TrivialAction(), m_orbit); 00176 } 00177 00178 template <class PERM> 00179 void Transversal<PERM>::orbitUpdate(unsigned long beta, const std::list<typename PERM::ptr> &generators, const typename PERM::ptr &g) { 00180 Orbit<PERM,unsigned long>::orbitUpdate(beta, generators, g, TrivialAction(), m_orbit); 00181 } 00182 00183 template <class PERM> 00184 bool Transversal<PERM>::foundOrbitElement(const unsigned long& alpha, const unsigned long& alpha_p, const typename PERM::ptr& p) { 00185 if (!m_transversal[alpha_p]) { 00186 if (!p) { 00187 typename PERM::ptr identity(new PERM(m_n)); 00188 registerMove(alpha, alpha_p, identity); 00189 } else { 00190 registerMove(alpha, alpha_p, p); 00191 } 00192 return true; 00193 } 00194 return false; 00195 } 00196 00197 template <class PERM> 00198 bool Transversal<PERM>::contains(const unsigned long& val) const { 00199 return m_transversal[val] != 0; 00200 } 00201 00202 template <class PERM> 00203 void Transversal<PERM>::registerMove(unsigned long from, unsigned long to, const typename PERM::ptr &p) { 00204 m_sorted = false; 00205 } 00206 00207 00208 template <class PERM> 00209 template <class InputIterator> 00210 void Transversal<PERM>::sort(InputIterator Bbegin, InputIterator Bend) { 00211 this->m_orbit.sort(BaseSorter(m_n, Bbegin, Bend)); 00212 m_sorted = true; 00213 } 00214 00215 template <class PERM> 00216 void Transversal<PERM>::permute(const PERM& g, const PERM& gInv) { 00217 std::vector<boost::shared_ptr<PERM> > temp(m_n); 00218 for (unsigned long i=0; i<m_n; ++i) { 00219 const unsigned long j = g / i; 00220 temp[j] = m_transversal[i]; 00221 } 00222 std::copy(temp.begin(), temp.end(), m_transversal.begin()); 00223 BOOST_FOREACH(unsigned long& alpha, this->m_orbit) { 00224 alpha = g / alpha; 00225 } 00226 m_sorted = false; 00227 } 00228 00229 template <class PERM> 00230 inline const unsigned long& Transversal<PERM>::element() const { 00231 return m_orbit.front(); 00232 } 00233 00234 } 00235 00236 #endif // -- TRANSVERSAL_H_