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 SCHREIERTRANSVERSAL_H_
00034 #define SCHREIERTRANSVERSAL_H_
00035
00036 #include "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, ulong to) const;
00048 virtual PERM* at(ulong val) const;
00049
00050 virtual void updateGenerators(const std::map<PERM*,PERMptr>& generatorChange);
00051
00053
00057 SchreierTreeTransversal<PERM> clone(const std::map<PERM*,PERMptr>& generatorChange) const;
00058
00060 mutable uint m_statMaxDepth;
00061 protected:
00062 virtual void registerMove(ulong from, ulong to, const PERMptr &p);
00063 };
00064
00065
00066
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, ulong to) const {
00076 return *Transversal<PERM>::m_transversal[to] == x;
00077 }
00078
00079 template <class PERM>
00080 void SchreierTreeTransversal<PERM>::registerMove(ulong from, ulong to, const PERMptr &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(ulong 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 uint depth = 1;
00095 PERM *res = new PERM(*transversal[val]);
00096 const PERM* inv = 0;
00097
00098 ulong pred = *res % val;
00099
00100 while (pred != val) {
00101 inv = transversal[pred].get();
00102
00103 *res ^= *inv;
00104 val = pred;
00105 pred = *inv % pred;
00106 ++depth;
00107 }
00108 m_statMaxDepth = std::max(m_statMaxDepth, depth);
00109
00110 return res;
00111 }
00112
00113 template <class PERM>
00114 void SchreierTreeTransversal<PERM>::updateGenerators(const std::map<PERM*,PERMptr>& generatorChange) {
00115 uint missedCount = 0;
00116 BOOST_FOREACH(PERMptr& p, this->m_transversal) {
00117 if (!p)
00118 continue;
00119
00120 typename std::map<PERM*,PERMptr>::const_iterator pIt = generatorChange.find(p.get());
00121
00122 if (pIt != generatorChange.end()) {
00123 p = (*pIt).second;
00124 } else {
00125 ++missedCount;
00126
00127 }
00128 }
00129
00130 BOOST_ASSERT( missedCount == 1 );
00131 }
00132
00133 template <class PERM>
00134 SchreierTreeTransversal<PERM> SchreierTreeTransversal<PERM>::clone(const std::map<PERM*,PERMptr>& generatorChange) const {
00135 SchreierTreeTransversal<PERM> ret(*this);
00136 ret.updateGenerators(generatorChange);
00137 return ret;
00138 }
00139
00140 }
00141
00142 #endif // -- SCHREIERTRANSVERSAL_H_