00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef PERMUTATIONWORD_H_
00034 #define PERMUTATIONWORD_H_
00035
00036 #include "permutation.h"
00037 #include <vector>
00038
00039 #include <boost/shared_ptr.hpp>
00040 #include <boost/foreach.hpp>
00041
00042 namespace permlib {
00043
00044 typedef boost::shared_ptr<Permutation> PermutationPtr;
00045
00047
00050 class PermutationWord {
00051 public:
00053 typedef std::vector<unsigned long> perm;
00054
00056 explicit PermutationWord(unsigned int n);
00058 PermutationWord(unsigned int n, const std::string &cycles);
00060 explicit PermutationWord(const perm &p);
00062 PermutationWord(const PermutationWord &p);
00063
00065 PermutationWord operator*(const PermutationWord &p) const;
00067
00070 PermutationWord& operator*=(const PermutationWord &p);
00072
00075 PermutationWord& operator^=(const PermutationWord &p);
00077 PermutationWord operator~() const;
00079 PermutationWord& invertInplace();
00081 bool operator==(const PermutationWord &p2) const;
00082
00084 inline ulong operator/(ulong val) const { return at(val); }
00086 ulong at(ulong val) const;
00088 ulong operator%(ulong val) const;
00089
00091 friend std::ostream &operator<< (std::ostream &out, const PermutationWord &p);
00092
00094
00098 bool isIdentity(bool flush = false) const;
00099
00101
00102 inline void flush() { isIdentity(true); }
00104 inline uint size() const { return m_n; }
00105
00107 static ulong elementsNumber() { return ms_elements.size(); }
00108
00110 static void clearStorage();
00111 private:
00112 static std::vector<PermutationPtr> ms_elements;
00113 static std::vector<PermutationPtr> ms_elementsInverse;
00114 static void addElement(const perm &p);
00115 static void addElement(const perm &p, const perm &pInv);
00116 static void addElement(PermutationPtr p);
00117
00118 mutable std::vector<int> m_word;
00119 unsigned int m_n;
00120 };
00121
00122 std::vector<PermutationPtr> PermutationWord::ms_elements(1);
00123 std::vector<PermutationPtr> PermutationWord::ms_elementsInverse(1);
00124
00125 inline PermutationWord::PermutationWord(unsigned int n)
00126 : m_n(n)
00127 { }
00128
00129 inline PermutationWord::PermutationWord(unsigned int n, const std::string &cycles)
00130 : m_n(n)
00131 {
00132 Permutation *pp = new Permutation(n, cycles);
00133 ms_elements.push_back(PermutationPtr(pp));
00134 ms_elementsInverse.push_back(PermutationPtr(new Permutation(~*pp)));
00135 m_word.reserve(2);
00136 m_word.push_back(ms_elements.size()-1);
00137 }
00138
00139 inline PermutationWord::PermutationWord(const PermutationWord &p)
00140 : m_word(p.m_word), m_n(p.m_n)
00141 { }
00142
00143 inline PermutationWord::PermutationWord(const perm &p)
00144 : m_n(p.size())
00145 {
00146 addElement(p);
00147 m_word.reserve(2);
00148 m_word.push_back(ms_elements.size()-1);
00149 }
00150
00151 inline void PermutationWord::addElement(const perm &p) {
00152 PermutationPtr gen(new Permutation(p));
00153 ms_elements.push_back(gen);
00154 PermutationPtr genInv(new Permutation(~*gen));
00155 ms_elementsInverse.push_back(genInv);
00156 }
00157 inline void PermutationWord::addElement(PermutationPtr p) {
00158 ms_elements.push_back(p);
00159 PermutationPtr genInv(new Permutation(~*p));
00160 ms_elementsInverse.push_back(genInv);
00161 }
00162
00163 inline void PermutationWord::addElement(const perm &p, const perm &pInv) {
00164 PermutationPtr gen(new Permutation(p));
00165 ms_elements.push_back(gen);
00166 PermutationPtr genInv(new Permutation(pInv));
00167 ms_elementsInverse.push_back(genInv);
00168 }
00169
00170
00171 inline PermutationWord PermutationWord::operator*(const PermutationWord &p) const {
00172 PermutationWord res(*this);
00173 res *= p;
00174 return res;
00175 }
00176
00177 inline PermutationWord& PermutationWord::operator*=(const PermutationWord &p) {
00178 if (m_word.empty()) {
00179 m_word.insert(m_word.end(), p.m_word.begin(), p.m_word.end());
00180 return *this;
00181 } else if (p.m_word.empty())
00182 return *this;
00183
00184 m_word.insert(m_word.end(), p.m_word.begin(), p.m_word.end());
00185 return *this;
00186 }
00187
00188 inline PermutationWord& PermutationWord::operator^=(const PermutationWord &p) {
00189 if (m_word.empty()) {
00190 m_word.insert(m_word.end(), p.m_word.begin(), p.m_word.end());
00191 return *this;
00192 } else if (p.m_word.empty())
00193 return *this;
00194
00195 m_word.insert(m_word.begin(), p.m_word.begin(), p.m_word.end());
00196 return *this;
00197 }
00198
00199
00200 inline PermutationWord& PermutationWord::invertInplace() {
00201 std::vector<int> oldWord(m_word);
00202 for (uint i=0; i<oldWord.size(); ++i) {
00203 m_word[i] = -oldWord[oldWord.size() - 1 - i];
00204 }
00205 return *this;
00206 }
00207
00208 inline PermutationWord PermutationWord::operator~() const {
00209 PermutationWord inv(*this);
00210 for (uint i=0; i<m_word.size(); ++i) {
00211 inv.m_word[i] = -m_word[m_word.size() - 1 - i];
00212 }
00213 return inv;
00214 }
00215
00216 inline ulong PermutationWord::at(ulong val) const {
00217 ulong ret = val;
00218 BOOST_FOREACH(int e, m_word) {
00219 if (e > 0)
00220 ret = *(ms_elements[e]) / ret;
00221 else
00222 ret = *(ms_elementsInverse[-e]) / ret;
00223 }
00224 return ret;
00225 }
00226
00227 inline ulong PermutationWord::operator%(ulong val) const {
00228 ulong ret = val;
00229 for (std::vector<int>::reverse_iterator lit = m_word.rbegin(); lit != m_word.rend(); ++lit) {
00230 int e = *lit;
00231 if (e < 0)
00232 ret = *(ms_elements[-e]) / ret;
00233 else
00234 ret = *(ms_elementsInverse[e]) / ret;
00235 }
00236 return ret;
00237 }
00238
00239 inline bool PermutationWord::isIdentity(bool flush) const {
00240 if (m_word.empty()) {
00241 return true;
00242 }
00243 if (m_word.size() == 1) {
00244 if (flush)
00245 return true;
00246 int e = m_word.front();
00247 if (e>0)
00248 return ms_elements[e]->isIdentity();
00249 else
00250 return ms_elementsInverse[-e]->isIdentity();
00251 }
00252
00253 perm mult(m_n);
00254 perm multInv(m_n);
00255
00256 PermutationPtr resMult(new Permutation(m_n));
00257 BOOST_FOREACH(int e, m_word) {
00258 *resMult *= (e > 0)
00259 ? *ms_elements[e].get()
00260 : *ms_elementsInverse[-e].get();
00261 }
00262
00263 const bool isIdentity = resMult->isIdentity();
00264
00265 if (!isIdentity) {
00266 addElement(resMult);
00267 m_word.clear();
00268 m_word.reserve(2);
00269 m_word.push_back(ms_elements.size()-1);
00270 }
00271
00272
00273 return isIdentity;
00274 }
00275
00276 inline std::ostream &operator<< (std::ostream &out, const PermutationWord &p) {
00277 out << "W[";
00278 BOOST_FOREACH(int g, p.m_word) {
00279 out << g << ",";
00280 }
00281 out << "]";
00282 return out;
00283 }
00284
00285 inline bool PermutationWord::operator==(const PermutationWord &p2) const {
00286 if (m_n != p2.m_n)
00287 return false;
00288
00289
00290
00291
00292
00293
00294 return m_word == p2.m_word;
00295 }
00296
00297 inline void PermutationWord::clearStorage() {
00298 ms_elements.clear();
00299 ms_elements.resize(1);
00300 ms_elementsInverse.clear();
00301 ms_elementsInverse.resize(1);
00302 }
00303
00304 }
00305
00306 #endif // -- PERMUTATIONWORD_H_