Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

/home/r0/dav/atlas.dir/atlas3/sources/gkmod/involutions.cpp

Go to the documentation of this file.
00001 /*!
00002 \file
00003 \brief Implementation of the class InvolutionSet.
00004 */
00005 /*
00006   This is involutions.cpp
00007 
00008   Copyright (C) 2004,2005 Fokko du Cloux
00009   part of the Atlas of Reductive Lie Groups
00010 
00011   See file main.cpp for full copyright notice
00012 */
00013 
00014 #include "involutions.h"
00015 
00016 #include <map>
00017 #include <set>
00018 #include <stack>
00019 
00020 #include "complexredgp.h"
00021 #include "latticetypes.h"
00022 #include "rootdata.h"
00023 
00024 
00025 /*
00026    In this file, the unadorned term involution always means twisted involution
00027 */
00028 
00029 namespace atlas {
00030 
00031   // namespace {
00032   namespace involutions {
00033   namespace helper {
00034 
00035   using namespace involutions;
00036 
00037       /*!
00038 \brief Derived class of InvolutionSet, to carry out the construction
00039 of InvolutionSet.
00040       */
00041   class Helper:public InvolutionSet {
00042 
00043   private:
00044 
00045     /*! \brief Entry |d_toDualWeyl[s]| gives generator whose inner
00046 representation in $W$ coincides with that of |s| in the dual Weyl group
00047     */
00048     weyl::WeylInterface d_toDualWeyl;
00049 
00050   public:
00051 
00052     // constructors and destructors
00053     explicit Helper(complexredgp::ComplexReductiveGroup&);
00054 
00055     virtual ~Helper() {}
00056 
00057     // manipulators
00058     void fill(const complexredgp::ComplexReductiveGroup&);
00059 
00060     void fillCartan(const complexredgp::ComplexReductiveGroup&);
00061 
00062     void fillInvolutions(const weyl::WeylGroup&);
00063 
00064     void fillDualInvolutions(const weyl::WeylGroup&);
00065 
00066     void weylCorrelation(const complexredgp::ComplexReductiveGroup&);
00067  };
00068 
00069   }
00070 
00071   }
00072 
00073 
00074 /*****************************************************************************
00075 
00076         Chapter I -- The InvolutionSet class
00077 
00078 ******************************************************************************/
00079 
00080 namespace involutions {
00081 
00082   using namespace atlas::involutions::helper;
00083 
00084 InvolutionSet::InvolutionSet()
00085 
00086 {}
00087 
00088 
00089 /*!
00090 \brief Constructor; computes the set of twisted involutions for G.
00091 
00092   NOTE: the set of involutions is actually constructed twice: once by
00093   fillCartan(), and then here. This is unfortunate, but negligible in the
00094   grand scheme of things, and having G remember its involution set runs
00095   against the principle of keeping the ComplexReductiveGroup class fairly
00096   small. Also this should be easy enough to change in the future if desired.
00097 */
00098 InvolutionSet::InvolutionSet(complexredgp::ComplexReductiveGroup& G)
00099 {
00100   Helper help(G);
00101   swap(help);
00102 }
00103 
00104 /******** copy, assignment and swap *****************************************/
00105 void InvolutionSet::swap(InvolutionSet& other)
00106 
00107 {
00108   std::swap(d_size,other.d_size);
00109   std::swap(d_rank,other.d_rank);
00110   d_action.swap(other.d_action);
00111   d_cartan.swap(other.d_cartan);
00112   d_involution.swap(other.d_involution);
00113   d_dualInvolution.swap(other.d_dualInvolution);
00114 
00115   return;
00116 }
00117 
00118 /******** assignment *******************************************************/
00119 
00120 /*!
00121 \brief Index of w in d_involution.
00122 
00123   Precondition: w is a twisted involution for W;
00124 
00125   Algorithm: find a reduced expression of w as an involution, and follow the
00126   action pointers.
00127 */
00128 size_t InvolutionSet::involutionNbr(const weyl::TwistedInvolution& w,
00129                                     const weyl::WeylGroup& W) const
00130 {
00131   using namespace weyl;
00132 
00133   WeylWord ww;
00134   W.involutionOut(ww,w);
00135 
00136   size_t x = 0;
00137 
00138   for (size_t j = 0; j < ww.size(); ++j)
00139     x = action(ww[j],x);
00140 
00141   return x;
00142 }
00143 
00144 }
00145 
00146 /*****************************************************************************
00147 
00148         Chapter II -- The Helper class
00149 
00150 ******************************************************************************/
00151 
00152 // namespace {
00153   namespace involutions {
00154   namespace helper {
00155 
00156 Helper::Helper(complexredgp::ComplexReductiveGroup& G)
00157   : InvolutionSet()
00158   , d_toDualWeyl(G.semisimpleRank())
00159 {
00160   using namespace weyl;
00161 
00162   // fill in the full cartan structure for G
00163   G.fillCartan();
00164 
00165   d_size = G.numInvolutions();
00166   d_rank = G.semisimpleRank();
00167 
00168   weylCorrelation(G);
00169   fill(G);
00170 }
00171 
00172 /******** manipulators *******************************************************/
00173 
00174 
00175 /*!
00176 \brief Fills the tables.
00177 
00178   Precondition: size and rank have been set.
00179 */
00180 void Helper::fill(const complexredgp::ComplexReductiveGroup& G)
00181 {
00182 
00183   const weyl::WeylGroup& W = G.weylGroup();
00184 
00185   // fill the action and involution tables
00186   fillInvolutions(W);
00187 
00188   // fill in the dual involution table
00189   fillDualInvolutions(W);
00190 
00191   // fill in the cartan table
00192   fillCartan(G);
00193 
00194   return;
00195 }
00196 
00197 
00198 /*!
00199 \brief Fills the Cartan table.
00200 
00201   Precondition: the action and involution tables have been filled;
00202 
00203   Explanation: it is important that we use the same numbering of Cartan
00204   subgroups as in G. The algorithm is to use the representative of Cartan
00205   \#j returned by G.twistedInvolution(j), locate that in the involution set,
00206   and then number its cross-orbit with j's.
00207 */
00208 void Helper::fillCartan(const complexredgp::ComplexReductiveGroup& G)
00209 {
00210   using namespace weyl;
00211 
00212   const WeylGroup& W = G.weylGroup();
00213 
00214   d_cartan.resize(d_size);
00215 
00216   std::set<size_t> found;
00217   std::stack<size_t> toDo;
00218 
00219   for (size_t cn = 0; cn < G.numCartanClasses(); ++cn) {
00220 
00221     const TwistedInvolution& w = G.twistedInvolution(cn);
00222     size_t x0 = involutionNbr(w,W);
00223 
00224     // find cross-orbit of x0
00225     found.clear();
00226 
00227     found.insert(x0);
00228     toDo.push(x0);
00229 
00230     while (!toDo.empty()) {
00231 
00232       size_t x = toDo.top();
00233       toDo.pop();
00234 
00235       for (Generator s = 0; s < d_rank; ++s) {
00236         const TwistedInvolution& w = involution(x);
00237         if (W.hasTwistedCommutation(s,w))
00238           continue;
00239         size_t sx = action(s,x);
00240         if (found.insert(sx).second)
00241           toDo.push(sx);
00242       }
00243     }
00244 
00245     // write result
00246     std::set<size_t>::iterator found_end = found.end();
00247     for (std::set<size_t>::iterator i = found.begin(); i != found_end; ++i)
00248       d_cartan[*i] = cn;
00249 
00250   }
00251 
00252 
00253 }
00254 
00255 /*!
00256 \brief Fills the action and involution tables.
00257 
00258   Precondition: size and rank have been set; W is the relevant Weyl group.
00259 
00260   Explanation: action(s,w) is s.w if s and w twisted-commute, s.w.twist(s)
00261   otherwise.
00262 
00263   Algorithm: we fill the table in order of increasing involution length, by
00264   the naive algorithm of looking at all the slots which have not yet been
00265   filled, computing the result and looking it up in a set of elements for the
00266   next length.
00267 */
00268 void Helper::fillInvolutions(const weyl::WeylGroup& W)
00269 {
00270   using namespace weyl;
00271 
00272   d_action.resize(d_rank);
00273   for (size_t s = 0; s < d_action.size(); ++s)
00274     d_action[s].resize(d_size,UndefInvolution);
00275 
00276   d_involution.resize(d_size);
00277 
00278   std::map<TwistedInvolution,size_t> found;
00279   size_t nextLength = 1;
00280   size_t firstNew = 1;
00281 
00282   for (size_t x = 0; x < d_size; ++x) {
00283 
00284     if (x == nextLength) { // update
00285       nextLength += found.size();
00286       found.clear();
00287     }
00288 
00289     for (size_t s = 0; s < d_rank; ++s) {
00290 
00291       if (action(s,x) != UndefInvolution)
00292         continue;
00293 
00294       const TwistedInvolution& w = involution(x);
00295       TwistedInvolution sw = w;
00296 
00297       if (W.hasTwistedCommutation(s,w)) { // action is product
00298         W.leftMult(sw,s);
00299       } else { // action is twisted commutation
00300         W.twistedConjugate(sw,s);
00301       }
00302 
00303       if (found.insert(std::make_pair(sw,firstNew)).second) {
00304         // found a new element
00305         d_involution[firstNew] = sw;
00306         d_action[s][x] = firstNew;
00307         d_action[s][firstNew] = x;
00308         ++firstNew;
00309       } else { // sw is already known
00310         size_t sx = found.find(sw)->second;
00311         d_action[s][x] = sx;
00312         d_action[s][sx] = x;
00313       }
00314     }
00315   }
00316 }
00317 
00318 /*!
00319 \brief Fills the dual involution table.
00320 
00321   Precondition: the action and involution tables have been filled; d_toDualWeyl
00322   is set;
00323 */
00324 void Helper::fillDualInvolutions(const weyl::WeylGroup& W)
00325 {
00326   using namespace weyl;
00327 
00328   d_dualInvolution.resize(d_size);
00329 
00330   for (size_t j = 0; j < d_size; ++j) {
00331     WeylElt w = involution(j).w();
00332     W.twist(w);
00333     WeylElt v = W.longest();
00334     W.mult(v,w);
00335     W.invert(v);
00336     d_dualInvolution[j] = TwistedInvolution(W.translation(v,d_toDualWeyl));
00337   }
00338 }
00339 
00340 /*!
00341 \brief Fills in d_toDualWeyl.
00342 
00343   Explanation: |d_toDualWeyl[s]| is the outer representation of the generator
00344   that in the Weyl group has the same inner representation as |s| has in the
00345   dual Weyl group. Thus we can move elements from the Weyl group to the dual
00346   Weyl group by translating them via |d_toDualWeyl| and then interpreting the
00347   resulting inner representation in the dual Weyl group (translation operates
00348   on inner representations but uses a table defined in terms of outer
00349   representations).
00350 */
00351 void Helper::weylCorrelation(const complexredgp::ComplexReductiveGroup& G)
00352 {
00353   using namespace latticetypes;
00354   using namespace rootdata;
00355   using namespace weyl;
00356 
00357   const WeylGroup& W = G.weylGroup();
00358 
00359   // make dual Weyl group
00360   LatticeMatrix c;
00361   cartanMatrix(c,G.rootDatum());
00362   c.transpose();   // transposing the Cartan matrix may change Weyl group
00363   WeylGroup dW(c); // twist is irrelevant here
00364 
00365   // fill in d_toDualWeyl
00366   for (size_t s = 0; s < W.rank(); ++s) {
00367     weyl::WeylElt w=dW.generator(s); // converts |s| to inner numbering |dW|
00368     weyl::WeylWord ww=W.word(w); // interpret |w| in |dW|; gives singleton
00369     d_toDualWeyl[s] = ww[0];
00370   }
00371 }
00372 
00373 } // namespace helper
00374 
00375 } // namespace involutions
00376 
00377 } // namespace atlas

Generated on Wed Mar 26 16:49:33 2008 for atlas by  doxygen 1.3.9.1