PermLib

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