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

/home/r0/dav/atlas.dir/atlas3/sources/structure/tits.cpp

Go to the documentation of this file.
00001 /*!
00002 \file
00003 \brief Implementation of the classes TitsGroup and TitsElt.
00004 
00005   This module contains an implementation of a slight variant of the
00006   Tits group (also called extended Weyl group) as defined in J. Tits,
00007   J. of Algebra 4 (1966), pp. 96-116.
00008 
00009   The slight variant is that we include all elements of order two in the
00010   torus, instead of just the subgroup generated by the \f$m_\alpha\f$ (denoted
00011   \f$h_\alpha\f$ in Tits' paper.) Tits' original group may be defined by
00012   generators \f$\sigma_\alpha\f$ for \f$\alpha\f$ simple, subject to the braid
00013   relations and to \f$\sigma_\alpha^2= m_\alpha\f$; to get our group we just
00014   add a basis of elements of $H(2)$ as additional generators, and express the
00015   \f$m_\alpha\f$ in this basis. This makes for a simpler implementation, where
00016   totus parts are just elements of the $\Z/2\Z$-vector space $H(2)$.
00017 
00018   On a practical level, because the \f$\sigma_\alpha\f$ satisfy the braid
00019   relations, any element of the Weyl group has a canonical lifting in the Tits
00020   group; so we may uniquely represent any element of the Tits group as a pair
00021   $(t,w)$, with $t$ in $T(2)$ and $w$ in $W$ (the latter representing the
00022   canonical lift \f$\sigma_w\f$. The multiplication rules have to be
00023   thoroughly changed, though, to take into account the new relations.
00024 
00025   We have not tried to be optimally efficient here, as it is not
00026   expected that Tits computations will be significant computationally.
00027 */
00028 /*
00029   This is tits.cpp
00030 
00031   Copyright (C) 2004,2005 Fokko du Cloux
00032   part of the Atlas of Reductive Lie Groups
00033 
00034   See file main.cpp for full copyright notice
00035 */
00036 
00037 #include "tits.h"
00038 
00039 #include "lattice.h"
00040 #include "rootdata.h"
00041 #include "setutils.h"
00042 
00043 namespace atlas {
00044 
00045 
00046 /****************************************************************************
00047 
00048         Chapter II -- The TitsGroup class
00049 
00050 *****************************************************************************/
00051 
00052 namespace tits {
00053 
00054 /*!
00055   \brief Constructs the Tits group corresponding to the root datum |rd|, and
00056   the fundamental involution |d|.
00057 */
00058 TitsGroup::TitsGroup(const rootdata::RootDatum& rd,
00059                      const latticetypes::LatticeMatrix& d)
00060   : d_twist(makeTwist(d,rd))
00061   , d_weyl(*new weyl::WeylGroup(rd.cartanMatrix(),&d_twist))
00062   , d_rank(rd.rank())
00063   , d_simpleRoot(rd.semisimpleRank())   // set number of vectors, but not yet
00064   , d_simpleCoroot(rd.semisimpleRank()) // their size (which will be |d_rank|)
00065   , d_involution(d.transposed())
00066 {
00067   for (size_t j = 0; j < rd.semisimpleRank(); ++j) // reduce vectors mod 2
00068   {
00069     d_simpleRoot[j]  =latticetypes::SmallBitVector(rd.simpleRoot(j));
00070     d_simpleCoroot[j]=latticetypes::SmallBitVector(rd.simpleCoroot(j));
00071   }
00072 }
00073 
00074 // Switching between left and right torus parts is a fundamental tool.
00075 
00076 /*!
00077   \brief find torus part $x'$ so that $x.w=w.x'$
00078 
00079   Algorithm: for simple reflections this is |reflect|; repeat left-to-right
00080 
00081   Note: a more sophisticated algorithm would involve precomputing the
00082   conjugation matrices for the various pieces of w. Don't do it unless it
00083   turns out to really matter.
00084 */
00085 TorusPart TitsGroup::push_across(TorusPart x, const weyl::WeylElt& w) const
00086 {
00087   weyl::WeylWord ww=d_weyl.word(w);
00088 
00089   for (size_t j = 0; j < ww.size(); ++j)
00090     reflect(x,ww[j]);
00091 
00092   return x;
00093 }
00094 
00095 // find torus part $x'$ so that $w.x=x'.w$; inverse to |push_across|
00096 TorusPart TitsGroup::pull_across(const weyl::WeylElt& w, TorusPart x) const
00097 {
00098   weyl::WeylWord ww=d_weyl.word(w);
00099   for (size_t j=ww.size(); j-->0; )
00100     reflect(x,ww[j]);
00101   return x;
00102 }
00103 
00104 
00105 /*!
00106   \brief Left multiplication of |a| by the canonical generator \f$\sigma_s\f$.
00107 
00108   This is the basic case defining the group structure in the Tits group (since
00109   left-multiplication by an element of $T(2)$ just adds to the torus part).
00110 
00111   Algorithm: This is surprisingly simple: multiplying by \f$\sigma_s\f$ just
00112   amounts to reflecting the torus part through |s|, then left-multiplying the
00113   Weyl group part $w$ by |s| in the Weyl group, and if the length goes down in
00114   the latter step, add a factor of \f$(\sigma_s)^2=m_s\f$ to the torus part.
00115   (To see this, write in the length-decreasing case $w=s.w'$ with $w'$
00116   reduced; then \f$\sigma_s\sigma_w=m_s\sigma_{w'}\f$, so we need to add $m_s$
00117   to the reflected left torus part in that case.
00118 
00119   The upshot is a multiplication algorithm almost as fast as in the Weyl group!
00120 */
00121 void TitsGroup::sigma_mult(weyl::Generator s,TitsElt& a) const
00122 {
00123   reflect(a.d_t,s); // commute (left) torus part with $\sigma_s$
00124   if (d_weyl.leftMult(a.d_w,s)<0) // torus part adjusted on length decrease
00125     left_add(d_simpleCoroot[s],a);
00126 }
00127 
00128 void TitsGroup::sigma_inv_mult(weyl::Generator s,TitsElt& a) const
00129 {
00130   reflect(a.d_t,s); // commute (left) torus part with $\sigma_s$
00131   if (d_weyl.leftMult(a.d_w,s)>0) // torus part adjusted on length increase
00132     left_add(d_simpleCoroot[s],a);
00133 }
00134 
00135 
00136 /*!
00137   \brief Right multiplication of |a| by the canonical generator \f$sigma_s\f$.
00138 
00139   Algorithm: similar to above, but omitting the |reflect| (since the torus
00140   part is at the left), and using |weyl::mult| instead of |weyl::leftMult|,
00141   and |right_add| to add the possible contribution $m_s$ instead of
00142   |left_add|; the latter implicitly involves a call to |pull_across|.
00143 */
00144 void TitsGroup::mult_sigma(TitsElt& a, weyl::Generator s) const
00145 {
00146 // |WeylGroup::mult| multiplies $w$ by $s$, returns sign of the length change
00147   if (d_weyl.mult(a.d_w,s)<0) // torus part needs adjustment on length decrease
00148     right_add(a,d_simpleCoroot[s]);
00149 }
00150 
00151 void TitsGroup::mult_sigma_inv(TitsElt& a, weyl::Generator s) const
00152 {
00153   if (d_weyl.mult(a.d_w,s)>0)// torus part needs adjustment on length increase
00154     right_add(a,d_simpleCoroot[s]);
00155 }
00156 
00157 
00158 /*!
00159   \brief Product of general Tits group elements
00160 
00161   Algorithm: The algorithm is to multiply the second factors successively by
00162   the generators in a reduced expression for |a.w()|, then left-add |a.t()|.
00163 
00164   Since we have torus parts on the left, we prefer left-multiplication here.
00165 */
00166 TitsElt TitsGroup::prod(const TitsElt& a, TitsElt b) const
00167 {
00168   weyl::WeylWord ww=d_weyl.word(a.w());
00169 
00170   // first incorporate the Weyl group part
00171   for (size_t j = ww.size(); j-->0; )
00172     sigma_mult(ww[j],b);
00173 
00174   // and finally the torus part
00175   left_add(a.d_t,b);
00176   return b;
00177 }
00178 
00179 
00180 } // namespace tits
00181 
00182 /****************************************************************************
00183 
00184         Chapter II -- Functions declared in tits.h
00185 
00186 *****************************************************************************/
00187 
00188 namespace tits {
00189 
00190 /*!
00191   Synopsis: Returns the twist defined by |d|.
00192 
00193   Precondition: |d| holds an involution of the root datum which fixes the
00194   positive Weyl chamber.
00195 
00196   The value computed essentially gives the functionality of WeylGroup::twist
00197   and of TitsGroup::twist, but it cannot use those methods since it is called
00198   before they are available: our task here is to prepare the data that will be
00199   used by those methods.
00200 */
00201 weyl::Twist makeTwist(const latticetypes::LatticeMatrix& d,
00202                       const rootdata::RootDatum& rd)
00203 {
00204   latticetypes::WeightList sr(rd.beginSimpleRoot(),rd.endSimpleRoot());
00205 
00206   weyl::Twist result(sr.size());
00207 
00208   for (size_t j = 0; j<sr.size(); ++j) {
00209     latticetypes::Weight v(rd.rank());
00210     d.apply(v,sr[j]); // set |v| to $d(\alpha_j)$ as weight vector
00211     result[j] = setutils::find_index(sr,v); // find index of that simple root
00212     assert (result[j]<sr.size());
00213   }
00214 
00215   return result;
00216 }
00217 
00218 } // namespace tits
00219 
00220 } // namespace atlas

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