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 CONJUGATINGBASECHANGE_H_
00034 #define CONJUGATINGBASECHANGE_H_
00035
00036 #include <boost/foreach.hpp>
00037 #include <boost/scoped_ptr.hpp>
00038 #include <boost/cstdint.hpp>
00039
00040 #include <permlib/change/base_change.h>
00041
00042 namespace permlib {
00043
00044 template<class PERM>
00045 struct SymmetricGroup;
00046
00047 template<class PERM,class TRANS>
00048 struct BSGS;
00049
00051 template<class PERM, class TRANS, class BASETRANSPOSE>
00052 class ConjugatingBaseChange : public BaseChange<PERM,TRANS> {
00053 public:
00055 explicit ConjugatingBaseChange(const BSGSCore<PERM,TRANS>&);
00056
00058 template <class InputIterator>
00059 uint change(BSGS<PERM,TRANS> &bsgs, InputIterator baseBegin, InputIterator baseEnd, bool skipRedundant = false) const;
00060
00062 template <class InputIterator>
00063 uint change(SymmetricGroup<PERM> &bsgs, InputIterator baseBegin, InputIterator baseEnd, bool skipRedundant = false) const;
00064 };
00065
00066 template<class PERM, class TRANS, class BASETRANSPOSE>
00067 ConjugatingBaseChange<PERM,TRANS,BASETRANSPOSE>::ConjugatingBaseChange(const BSGSCore<PERM,TRANS>&)
00068 : BaseChange<PERM,TRANS>()
00069 { }
00070
00071 template<class PERM, class TRANS, class BASETRANSPOSE>
00072 template<class InputIterator>
00073 uint ConjugatingBaseChange<PERM,TRANS,BASETRANSPOSE>::change(BSGS<PERM,TRANS> &bsgs, InputIterator baseBegin, InputIterator baseEnd, bool skipRedundant) const {
00074 if (baseBegin == baseEnd)
00075 return 0;
00076
00077 const boost::uint64_t origOrder __attribute__((unused)) = bsgs.order();
00078 BASETRANSPOSE trans;
00079 PERM c(bsgs.n);
00080 PERM cInv(bsgs.n);
00082 bool touchedC = false;
00083
00084 uint baseTargetPos = 0;
00085 while (baseBegin != baseEnd && baseTargetPos < bsgs.B.size()) {
00086 const ulong alpha = cInv.at(*baseBegin);
00087 const ulong beta = bsgs.B[baseTargetPos];
00088 const bool redundant = skipRedundant && isRedundant(bsgs, baseTargetPos, alpha);
00089
00090 if (!redundant && beta != alpha) {
00091 boost::scoped_ptr<PERM> r(bsgs.U[baseTargetPos].at(alpha));
00092 if (r) {
00093 c ^= *r;
00094 cInv = ~c;
00095 touchedC = true;
00096 } else {
00097 uint pos = bsgs.insertRedundantBasePoint(alpha, baseTargetPos);
00098 for (; pos > baseTargetPos; --pos) {
00099 trans.transpose(bsgs, pos-1);
00100 ++BaseChange<PERM,TRANS>::m_statTranspositions;
00101 }
00102 }
00103 }
00104 if (!redundant)
00105 ++baseTargetPos;
00106
00107 ++baseBegin;
00108 }
00109
00110
00111 while (!skipRedundant && baseBegin != baseEnd) {
00112 const ulong alpha = cInv.at(*baseBegin);
00113 bsgs.insertRedundantBasePoint(alpha, baseTargetPos);
00114
00115 ++baseBegin;
00116 ++baseTargetPos;
00117 }
00118
00119 if (touchedC) {
00120
00121 BOOST_FOREACH(PERMptr& g, bsgs.S) {
00122 *g ^= cInv;
00123 *g *= c;
00124 g->flush();
00125 }
00126
00127
00128 BOOST_FOREACH(ulong &beta, bsgs.B) {
00129 beta = c.at(beta);
00130 }
00131 }
00132
00133
00134 bsgs.stripRedundantBasePoints(baseTargetPos);
00135 BaseChange<PERM,TRANS>::m_statScheierGeneratorsConsidered += trans.m_statScheierGeneratorsConsidered;
00136
00137 if (touchedC) {
00138 for (uint i=0; i<bsgs.B.size(); ++i) {
00139
00140 bsgs.U[i].permute(c, cInv);
00141 }
00142 }
00143
00144 BOOST_ASSERT(origOrder == bsgs.order());
00145
00146 return baseTargetPos;
00147 }
00148
00149 template<class PERM, class TRANS, class BASETRANSPOSE>
00150 template<class InputIterator>
00151 uint ConjugatingBaseChange<PERM,TRANS,BASETRANSPOSE>::change(SymmetricGroup<PERM> &bsgs, InputIterator baseBegin, InputIterator baseEnd, bool skipRedundant) const {
00152 uint basePos = 0;
00153 while (baseBegin != baseEnd) {
00154
00155 for (uint i = basePos; i < bsgs.B.size(); ++i) {
00156 if (bsgs.B[i] == *baseBegin) {
00157 std::swap(bsgs.B[i], bsgs.B[basePos]);
00158
00159 break;
00160 }
00161 }
00162 ++basePos;
00163 ++baseBegin;
00164 }
00165 return basePos;
00166 }
00167
00168 }
00169
00170 #endif // -- CONJUGATINGBASECHANGE_H_