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 PERMUTATION_H_ 00034 #define PERMUTATION_H_ 00035 00036 #include <permlib/common.h> 00037 00038 // for I/O 00039 #include <string> 00040 #include <iostream> 00041 #include <boost/tokenizer.hpp> 00042 #include <sstream> 00043 #include <set> 00044 00045 #include <boost/shared_ptr.hpp> 00046 00047 namespace permlib { 00048 00050 class Permutation { 00051 public: 00053 typedef std::vector<dom_int> perm; 00054 00056 typedef boost::shared_ptr<Permutation> ptr; 00057 00059 explicit Permutation(dom_int n); 00061 Permutation(dom_int n, const std::string &cycles); 00063 explicit Permutation(const perm &p); 00065 Permutation(const Permutation &p) : m_perm(p.m_perm), m_isIdentity(p.m_isIdentity) {}; 00067 template<class InputIterator> 00068 Permutation(InputIterator begin, InputIterator end) : m_perm(begin, end) {} 00069 00071 Permutation operator*(const Permutation &p) const; 00073 00076 Permutation& operator*=(const Permutation &p); 00078 00081 Permutation& operator^=(const Permutation &p); 00083 Permutation operator~() const; 00085 Permutation& invertInplace(); 00087 bool operator==(const Permutation &p2) const { return m_perm == p2.m_perm; }; 00088 00090 inline dom_int operator/(dom_int val) const { return at(val); } 00092 inline dom_int at(dom_int val) const { return m_perm[val]; } 00093 00095 dom_int operator%(dom_int val) const; 00096 00098 friend std::ostream &operator<< (std::ostream &out, const Permutation &p); 00099 00101 00104 bool isIdentity() const; 00106 inline void flush() {}; 00108 inline dom_int size() const { return m_perm.size(); } 00109 00111 void setTransposition(dom_int pos, dom_int val); 00112 protected: 00114 perm m_perm; 00115 00117 bool m_isIdentity; 00118 00120 Permutation(dom_int n, bool) : m_perm(n), m_isIdentity(false) {} 00121 }; 00122 00123 00124 // 00125 // ---- IMPLEMENTATION 00126 // 00127 00128 inline Permutation::Permutation(dom_int n) 00129 : m_perm(n), m_isIdentity(true) 00130 { 00131 for (dom_int i=0; i<n; ++i) 00132 m_perm[i] = i; 00133 } 00134 00135 inline Permutation::Permutation(dom_int n, const std::string & cycles) 00136 : m_perm(n), m_isIdentity(false) 00137 { 00138 typedef boost::tokenizer<boost::char_separator<char> > tokenizer; 00139 boost::char_separator<char> sepCycles(","); 00140 tokenizer tokens(cycles, sepCycles); 00141 00142 for (dom_int i=0; i<n; ++i) 00143 m_perm[i] = i; 00144 00145 for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) { 00146 std::stringstream ss(*tok_iter); 00147 00148 unsigned int first, last, temp; 00149 ss >> first; 00150 last = first; 00151 00152 while (!ss.eof()) { 00153 ss >> temp; 00154 m_perm[last-1] = temp-1; 00155 last = temp; 00156 } 00157 m_perm[last-1] = first-1; 00158 } 00159 } 00160 00161 00162 inline Permutation::Permutation(const perm& p) 00163 : m_perm(p), m_isIdentity(false) 00164 { } 00165 00166 inline Permutation Permutation::operator*(const Permutation &p) const { 00167 BOOST_ASSERT(p.m_perm.size() == m_perm.size()); 00168 00169 Permutation res(m_perm.size(), true); 00170 for (dom_int i=0; i<m_perm.size(); ++i) { 00171 res.m_perm[i] = p.m_perm[m_perm[i]]; 00172 } 00173 return res; 00174 } 00175 00176 inline Permutation& Permutation::operator*=(const Permutation &p) { 00177 BOOST_ASSERT(p.m_perm.size() == m_perm.size()); 00178 m_isIdentity = false; 00179 00180 for (dom_int i=0; i<m_perm.size(); ++i) { 00181 m_perm[i] = p.m_perm[m_perm[i]]; 00182 } 00183 return *this; 00184 } 00185 00186 inline Permutation& Permutation::operator^=(const Permutation &p) { 00187 BOOST_ASSERT(p.m_perm.size() == m_perm.size()); 00188 m_isIdentity = false; 00189 perm tmp(m_perm); 00190 00191 for (dom_int i=0; i<m_perm.size(); ++i) { 00192 m_perm[i] = tmp[p.m_perm[i]]; 00193 } 00194 return *this; 00195 } 00196 00197 inline Permutation Permutation::operator~() const { 00198 Permutation res(m_perm.size(), true); 00199 for (dom_int i=0; i<m_perm.size(); ++i) { 00200 res.m_perm[m_perm[i]] = i; 00201 } 00202 return res; 00203 } 00204 00205 inline Permutation& Permutation::invertInplace() { 00206 perm tmp(m_perm); 00207 for (dom_int i=0; i<m_perm.size(); ++i) { 00208 m_perm[tmp[i]] = i; 00209 } 00210 return *this; 00211 } 00212 00213 inline dom_int Permutation::operator%(dom_int val) const { 00214 for (dom_int i = 0; i < m_perm.size(); ++i) { 00215 if (m_perm[i] == val) 00216 return i; 00217 } 00218 // must not happen, we have a permutation! 00219 BOOST_ASSERT(false); 00220 return -1; 00221 } 00222 00223 inline bool Permutation::isIdentity() const { 00224 if (m_isIdentity) 00225 return true; 00226 for (dom_int i=0; i<m_perm.size(); ++i) 00227 if (at(i) != i) 00228 return false; 00229 return true; 00230 } 00231 00232 inline void Permutation::setTransposition(dom_int pos, dom_int val) { 00233 BOOST_ASSERT(pos < m_perm.size()); 00234 BOOST_ASSERT(val < m_perm.size()); 00235 00236 m_perm[pos] = val; 00237 m_perm[val] = pos; 00238 } 00239 00240 inline std::ostream& operator<<(std::ostream& out, const Permutation& p) { 00241 std::set<dom_int> worked; 00242 bool output = false; 00243 for (dom_int x=0; x<p.m_perm.size(); ++x) { 00244 dom_int px, startX; 00245 startX = x; 00246 px = p.m_perm[x]; 00247 if (worked.count(x) || x == px) { 00248 continue; 00249 } 00250 00251 worked.insert(x); 00252 out << "(" << (x+1) << ","; 00253 while (p.m_perm[px] != startX) { 00254 out << (px+1) << ","; 00255 worked.insert(px); 00256 px = p.m_perm[px]; 00257 } 00258 worked.insert(px); 00259 out << (px+1); 00260 out << ")"; 00261 output = true; 00262 } 00263 if (!output) 00264 out << "()"; 00265 return out; 00266 } 00267 00268 } 00269 00270 #endif // -- PERMUTATION_H_