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

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

Go to the documentation of this file.
00001 /*
00002   This is wgraph.cpp
00003 
00004   Copyright (C) 2004,2005 Fokko du Cloux
00005   part of the Atlas of Reductive Lie Groups
00006 
00007   See file main.cpp for full copyright notice
00008 */
00009 
00010 #include "wgraph.h"
00011 #include "filekl.h"
00012 #include "bitset.h"
00013 #include "blocks.h"
00014 
00015 #include <algorithm>
00016 #include <iostream>
00017 
00018 namespace atlas {
00019 
00020 /*****************************************************************************
00021 
00022         Chapter I -- The WGraph and DecomposedWGraph classes
00023 
00024 ******************************************************************************/
00025 
00026 namespace wgraph {
00027 
00028 /******** constructors and destructors ***************************************/
00029 WGraph::WGraph(size_t r)
00030   :d_rank(r)
00031 
00032 /*
00033   Synopsis: constructor
00034 
00035   Makes an empty W-graph with rank r.
00036 */
00037 
00038 {}
00039 
00040 WGraph::~WGraph()
00041 
00042 {}
00043 
00044 /******** copy, assignment and swap ******************************************/
00045 void WGraph::swap(WGraph& other)
00046 
00047 {
00048   std::swap(d_rank,other.d_rank);
00049   d_graph.swap(other.d_graph);
00050   d_coeff.swap(other.d_coeff);
00051   d_descent.swap(other.d_descent);
00052 
00053   return;
00054 }
00055 
00056 /******** manipulators *******************************************************/
00057 void WGraph::reset()
00058 
00059 /*
00060   Synopsis: resets the W-graph
00061 
00062   Preserves size and rank; resets edge and coefficient lists to empty lists;
00063   resets descent sets to empty.
00064 */
00065 
00066 {
00067   d_graph.reset();
00068   d_coeff.assign(size(),CoeffList());
00069   d_descent.assign(size(),bitset::RankFlags());
00070 
00071   return;
00072 }
00073 
00074 void WGraph::resize(size_t n)
00075 
00076 /*
00077   Synopsis: resizes the lists to size n
00078 
00079   Preserves the existing parts if n > size().
00080 */
00081 
00082 {
00083   d_graph.resize(n);
00084   d_coeff.resize(n);
00085   d_descent.resize(n);
00086 
00087   return;
00088 }
00089 
00090 DecomposedWGraph::DecomposedWGraph(const WGraph& wg)
00091   : d_cell(), d_part(wg.size()), d_id(), d_induced()
00092 {
00093   using partition::Partition; using partition::PartitionIterator;
00094 
00095   Partition pi;
00096   wg.cells(pi,&d_induced);
00097 
00098   d_cell.reserve(pi.classCount()); // there will be this many cells
00099   d_id.resize(pi.classCount());    // and vectors of identification numbers
00100 
00101 
00102   std::vector<unsigned int> relno(wg.size()); // number of element in its cell
00103   PartitionIterator i(pi);
00104   for (cell_no n=0; n<d_id.size(); ++n,++i)
00105   {
00106     d_cell.push_back(WGraph(wg.rank()));
00107     WGraph& cur_cell = d_cell.back();
00108     cur_cell.resize(i->second-i->first);
00109     std::vector<unsigned int>& idn=d_id[n];
00110     idn.resize(cur_cell.size());
00111 
00112     for (PartitionIterator::SubIterator j=i->first; j!=i->second; ++j)
00113     {
00114       size_t y = *j; size_t z=j-i->first; // |y| gets renamed |z| in cell
00115 
00116       d_part[y]=n; // or equivalently |d_part[y]=pi(y)|
00117       relno[y]=z; idn[z]=y;
00118 
00119       cur_cell.descent(z) = wg.descent(y);
00120     }
00121   }
00122   // make sure all values |relno[y]| are defined before proceeding
00123 
00124   for (i.rewind(); i(); ++i)
00125   {
00126     cell_no n=d_part[*i->first]; // cell number, constant through next loop
00127     for (PartitionIterator::SubIterator j=i->first; j!=i->second; ++j)
00128     {
00129       size_t y = *j; size_t z=relno[y]; // |z==j-i->first|
00130       const graph::EdgeList& edge = wg.edgeList(y);
00131       const CoeffList& coeff = wg.coeffList(y);
00132       graph::EdgeList& cur_el = d_cell[n].edgeList(z);
00133       CoeffList& cur_cl = d_cell[n].coeffList(z);
00134       for (size_t k = 0; k < edge.size(); ++k)
00135         if (d_part[edge[k]]==n) // only look at edges within this cell
00136         {
00137           cur_el.push_back(relno[edge[k]]);
00138           cur_cl.push_back(     coeff[k]);
00139         }
00140     } // for (j)
00141   } // for (i)
00142 
00143 }
00144 
00145 } // namespace wgraph
00146 
00147 /*****************************************************************************
00148 
00149         Chapter II -- Functions declared in wgraph.h
00150 
00151 ******************************************************************************/
00152 
00153 namespace wgraph {
00154 
00155 void cells(std::vector<WGraph>& wc, const WGraph& wg)
00156 
00157 /*
00158   Synopsis: puts in wc the cells of the W-graph wg.
00159 */
00160 
00161 {
00162   using namespace graph;
00163   using namespace partition;
00164 
00165   Partition pi;
00166   wg.cells(pi); // do not collect information about induced graph here
00167 
00168   for (PartitionIterator i(pi); i(); ++i) {
00169     wc.push_back(WGraph(wg.rank()));
00170     WGraph& wci = wc.back();
00171     wci.resize(i->second - i->first);
00172 
00173     /* looping over |z| rather than using |*i| directly implements the
00174        renumbering of each cell (what was |y=*(i->first+z)| becomes just |z|)
00175     */
00176     for (size_t z = 0; z < wci.size(); ++z) {
00177       size_t y = i->first[z];
00178       wci.descent(z) = wg.descent(y);
00179       const EdgeList& el = wg.edgeList(y);
00180       EdgeList& eli = wci.edgeList(z);
00181       const CoeffList& cl = wg.coeffList(y);
00182       CoeffList& cli = wci.coeffList(z);
00183       for (size_t j = 0; j < el.size(); ++j) {
00184         size_t x = el[j];
00185         if (pi(x) != pi(y)) // an edge leading out of the current cell
00186           continue;         // ignore these
00187         // find relative address of x in this class
00188         size_t xi = std::lower_bound(i->first,i->second,x) - i->first;
00189         eli.push_back(xi);
00190         cli.push_back(cl[j]);
00191       }
00192     } //for (z)
00193   } // for (i)
00194 
00195 } // cells
00196 
00197 /* The following function is an alternative to the function |wGraph| defined
00198    in kl.cpp. Here we do not assume that a KLContext is available, but that
00199    binary files with information about the block, matrix, and KL polynomials
00200    are avaialble. As a consequence we must redo the work of
00201    |kl::Helper::fillMuRow| as well as that to the mentioned |wGraph| function.
00202 */
00203 
00204 WGraph wGraph
00205   ( std::ifstream& block_file
00206   , std::ifstream& matrix_file
00207   , std::ifstream& KL_file)
00208 {
00209   using blocks::BlockElt;
00210   typedef std::auto_ptr<filekl::polynomial_info> pol_aptr;
00211 
00212   filekl::matrix_info mi(block_file,matrix_file);
00213   pol_aptr pol_p(NULL);
00214 
00215   try
00216   { pol_p=pol_aptr(new filekl::cached_pol_info(KL_file));
00217   }
00218   catch (std::exception& e)
00219   {
00220     std::cerr << "Failed to use cached polynomials: " << e.what() << std::endl;
00221     pol_p=pol_aptr(new filekl::polynomial_info(KL_file));
00222   }
00223 
00224   filekl::polynomial_info& poli=*pol_p;
00225 
00226   size_t max_mu=1;                       // maximal mu found
00227   std::pair<BlockElt,BlockElt> max_pair; // corresponding (x,y)
00228 
00229   WGraph result(mi.rank()); result.resize(mi.block_size());
00230 
00231   // fill in descent sets
00232   for (BlockElt y = 0; y < mi.block_size(); ++y)
00233   {
00234     bitset::RankFlags d_y = result.descent(y) = mi.descent_set(y);
00235     size_t ly = mi.length(y);
00236     if (ly==0) continue; // nothing more to do; avoid negative |d| below
00237 
00238 #ifdef VERBOSE
00239     std::cerr << "reading edges for y=" << y;
00240     if (max_mu>1) std::cerr << ", maximal mu: " << max_mu;
00241     std::cerr << '\r';
00242 #endif
00243 
00244     const filekl::strong_prim_list& spy=mi.strongly_primitives(y);
00245 
00246     filekl::strong_prim_list::const_iterator start= spy.begin();
00247     // traverse lengths |lx| of opposite parity to |ly|, up to |ly-3|
00248     for (size_t lx=(ly-1)%2,d = (ly-1)/2; d>0; --d,lx+=2) // d=(ly-1-lx)/2
00249     {
00250       filekl::strong_prim_list::const_iterator stop =
00251         std::lower_bound(start,spy.end()-1,mi.first_of_length(lx+1));
00252       for (start= std::lower_bound(start,stop,mi.first_of_length(lx));
00253            start<stop; ++start)
00254         if (mi.descent_set(*start)!=d_y)
00255         {
00256           BlockElt x = *start;
00257           filekl::KLIndex klp = mi.find_pol_nr(x,y);
00258 
00259           if (poli.degree(klp)==d)
00260           {
00261             result.edgeList(x).push_back(y);
00262             size_t mu=poli.leading_coeff(klp);
00263             if (mu>max_mu) { max_mu=mu; max_pair=std::make_pair(x,y); }
00264             result.coeffList(x).push_back(mu);
00265           }
00266 
00267         } // for (start...) if (descent!=d_y)
00268     } // for (lx,d)
00269 
00270     // for length |ly-1| we cannot limit ourselves to strongly primitives
00271     BlockElt end=mi.first_of_length(ly);
00272     for (BlockElt x=mi.first_of_length(ly-1); x<end; ++x)
00273     {
00274       bitset::RankFlags d_x=mi.descent_set(x);
00275       if (d_x==d_y) continue; // this case would lead nowhere anyway
00276       filekl::KLIndex klp = mi.find_pol_nr(x,y);
00277       if (klp!=filekl::KLIndex(0)) // then some edge between |x| and |y| exists
00278       {
00279         size_t mu=poli.leading_coeff(klp);
00280         if (mu>max_mu) { max_mu=mu; max_pair=std::make_pair(x,y); }
00281         if (not d_y.contains(d_x))
00282         {
00283           result.edgeList(x).push_back(y);
00284           result.coeffList(x).push_back(mu);
00285         }
00286         if (not d_x.contains(d_y))
00287         {
00288           result.edgeList(y).push_back(x);
00289           result.coeffList(y).push_back(mu);
00290         }
00291       } // if (klp!=KLIndex(0))
00292     } // for (x)
00293   } // for (y)
00294 
00295   size_t n_edges=0;
00296   for (BlockElt y = 0; y < mi.block_size(); ++y)
00297     n_edges+=result.edgeList(y).size();
00298 
00299   if (max_mu==1) std::cout << "All edges found are simple.\n";
00300   else std::cout << "Maximal edge multiplicity " << max_mu << " for ("
00301                  << max_pair.first << ',' << max_pair.second <<")\n";
00302   std::cout << "Total number of (directed) edges in graph is " << n_edges
00303             << '.' << std::endl;
00304 
00305   return result;
00306 }
00307 
00308 
00309 }
00310 
00311 }

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