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
1.3.9.1