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

ClusterSequence_TiledN2.cc

Go to the documentation of this file.
00001 //STARTHEADER
00002 // $Id: ClusterSequence_TiledN2.cc 1021 2008-01-15 20:32:25Z soyez $
00003 //
00004 // Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
00005 //
00006 //----------------------------------------------------------------------
00007 // This file is part of FastJet.
00008 //
00009 //  FastJet is free software; you can redistribute it and/or modify
00010 //  it under the terms of the GNU General Public License as published by
00011 //  the Free Software Foundation; either version 2 of the License, or
00012 //  (at your option) any later version.
00013 //
00014 //  The algorithms that underlie FastJet have required considerable
00015 //  development and are described in hep-ph/0512210. If you use
00016 //  FastJet as part of work towards a scientific publication, please
00017 //  include a citation to the FastJet paper.
00018 //
00019 //  FastJet is distributed in the hope that it will be useful,
00020 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022 //  GNU General Public License for more details.
00023 //
00024 //  You should have received a copy of the GNU General Public License
00025 //  along with FastJet; if not, write to the Free Software
00026 //  Foundation, Inc.:
00027 //      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028 //----------------------------------------------------------------------
00029 //ENDHEADER
00030 
00031 
00032 // The plain N^2 part of the ClusterSequence class -- separated out
00033 // from the rest of the class implementation so as to speed up
00034 // compilation of this particular part while it is under test.
00035 
00036 #include<iostream>
00037 #include<vector>
00038 #include<cmath>
00039 #include<algorithm>
00040 #include "fastjet/PseudoJet.hh"
00041 #include "fastjet/ClusterSequence.hh"
00042 #include "fastjet/internal/MinHeap.hh"
00043 
00044 FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
00045 
00046 using namespace std;
00047 
00048 
00049 //----------------------------------------------------------------------
00050 void ClusterSequence::_bj_remove_from_tiles(TiledJet * const jet) {
00051   Tile * tile = & _tiles[jet->tile_index];
00052 
00053   if (jet->previous == NULL) {
00054     // we are at head of the tile, so reset it.
00055     // If this was the only jet on the tile then tile->head will now be NULL
00056     tile->head = jet->next;
00057   } else {
00058     // adjust link from previous jet in this tile
00059     jet->previous->next = jet->next;
00060   }
00061   if (jet->next != NULL) {
00062     // adjust backwards-link from next jet in this tile
00063     jet->next->previous = jet->previous;
00064   }
00065 }
00066 
00067 //----------------------------------------------------------------------
00086 void ClusterSequence::_initialise_tiles() {
00087 
00088   // first decide tile sizes
00089   _tile_size_eta = _Rparam;
00090   _n_tiles_phi   = int(floor(twopi/_Rparam));
00091   _tile_size_phi = twopi / _n_tiles_phi; // >= _Rparam and fits in 2pi
00092 
00093   // always include zero rapidity in the tiling region
00094   _tiles_eta_min = 0.0;
00095   _tiles_eta_max = 0.0;
00096   // but go no further than following
00097   const double maxrap = 7.0;
00098 
00099   // and find out how much further one should go
00100   for(unsigned int i = 0; i < _jets.size(); i++) {
00101     double eta = _jets[i].rap();
00102     // first check if eta is in range -- to avoid taking into account
00103     // very spurious rapidities due to particles with near-zero kt.
00104     if (abs(eta) < maxrap) {
00105       if (eta < _tiles_eta_min) {_tiles_eta_min = eta;}
00106       if (eta > _tiles_eta_max) {_tiles_eta_max = eta;}
00107     }
00108   }
00109 
00110   // now adjust the values
00111   _tiles_ieta_min = int(floor(_tiles_eta_min/_tile_size_eta));
00112   _tiles_ieta_max = int(floor( _tiles_eta_max/_tile_size_eta));
00113   _tiles_eta_min = _tiles_ieta_min * _tile_size_eta;
00114   _tiles_eta_max = _tiles_ieta_max * _tile_size_eta;
00115 
00116   // allocate the tiles
00117   _tiles.resize((_tiles_ieta_max-_tiles_ieta_min+1)*_n_tiles_phi);
00118 
00119   // now set up the cross-referencing between tiles
00120   for (int ieta = _tiles_ieta_min; ieta <= _tiles_ieta_max; ieta++) {
00121     for (int iphi = 0; iphi < _n_tiles_phi; iphi++) {
00122       Tile * tile = & _tiles[_tile_index(ieta,iphi)];
00123       // no jets in this tile yet
00124       tile->head = NULL; // first element of tiles points to itself
00125       tile->begin_tiles[0] =  tile;
00126       Tile ** pptile = & (tile->begin_tiles[0]);
00127       pptile++;
00128       //
00129       // set up L's in column to the left of X
00130       tile->surrounding_tiles = pptile;
00131       if (ieta > _tiles_ieta_min) {
00132         // with the itile subroutine, we can safely run tiles from
00133         // idphi=-1 to idphi=+1, because it takes care of
00134         // negative and positive boundaries
00135         for (int idphi = -1; idphi <=+1; idphi++) {
00136           *pptile = & _tiles[_tile_index(ieta-1,iphi+idphi)];
00137           pptile++;
00138         }       
00139       }
00140       // now set up last L (below X)
00141       *pptile = & _tiles[_tile_index(ieta,iphi-1)];
00142       pptile++;
00143       // set up first R (above X)
00144       tile->RH_tiles = pptile;
00145       *pptile = & _tiles[_tile_index(ieta,iphi+1)];
00146       pptile++;
00147       // set up remaining R's, to the right of X
00148       if (ieta < _tiles_ieta_max) {
00149         for (int idphi = -1; idphi <= +1; idphi++) {
00150           *pptile = & _tiles[_tile_index(ieta+1,iphi+idphi)];
00151           pptile++;
00152         }       
00153       }
00154       // now put semaphore for end tile
00155       tile->end_tiles = pptile;
00156       // finally make sure tiles are untagged
00157       tile->tagged = false;
00158     }
00159   }
00160 
00161 }
00162 
00163 
00164 //----------------------------------------------------------------------
00166 int ClusterSequence::_tile_index(const double & eta, const double & phi) const {
00167   int ieta, iphi;
00168   if      (eta <= _tiles_eta_min) {ieta = 0;}
00169   else if (eta >= _tiles_eta_max) {ieta = _tiles_ieta_max-_tiles_ieta_min;}
00170   else {
00171     //ieta = int(floor((eta - _tiles_eta_min) / _tile_size_eta));
00172     ieta = int(((eta - _tiles_eta_min) / _tile_size_eta));
00173     // following needed in case of rare but nasty rounding errors
00174     if (ieta > _tiles_ieta_max-_tiles_ieta_min) {
00175       ieta = _tiles_ieta_max-_tiles_ieta_min;} 
00176   }
00177   // allow for some extent of being beyond range in calculation of phi
00178   // as well
00179   //iphi = (int(floor(phi/_tile_size_phi)) + _n_tiles_phi) % _n_tiles_phi;
00180   // with just int and no floor, things run faster but beware
00181   iphi = int((phi+twopi)/_tile_size_phi) % _n_tiles_phi;
00182   return (iphi + ieta * _n_tiles_phi);
00183 }
00184 
00185 
00186 //----------------------------------------------------------------------
00187 // overloaded version which additionally sets up information regarding the
00188 // tiling
00189 inline void ClusterSequence::_tj_set_jetinfo( TiledJet * const jet,
00190                                               const int _jets_index) {
00191   // first call the generic setup
00192   _bj_set_jetinfo<>(jet, _jets_index);
00193 
00194   // Then do the setup specific to the tiled case.
00195 
00196   // Find out which tile it belonds to
00197   jet->tile_index = _tile_index(jet->eta, jet->phi);
00198 
00199   // Insert it into the tile's linked list of jets
00200   Tile * tile = &_tiles[jet->tile_index];
00201   jet->previous   = NULL;
00202   jet->next       = tile->head;
00203   if (jet->next != NULL) {jet->next->previous = jet;}
00204   tile->head      = jet;
00205 }
00206 
00207 
00208 //----------------------------------------------------------------------
00210 void ClusterSequence::_print_tiles(TiledJet * briefjets ) const {
00211   for (vector<Tile>::const_iterator tile = _tiles.begin(); 
00212        tile < _tiles.end(); tile++) {
00213     cout << "Tile " << tile - _tiles.begin()<<" = ";
00214     vector<int> list;
00215     for (TiledJet * jetI = tile->head; jetI != NULL; jetI = jetI->next) {
00216       list.push_back(jetI-briefjets);
00217       //cout <<" "<<jetI-briefjets;
00218     }
00219     sort(list.begin(),list.end());
00220     for (unsigned int i = 0; i < list.size(); i++) {cout <<" "<<list[i];}
00221     cout <<"\n";
00222   }
00223 }
00224 
00225 
00226 //----------------------------------------------------------------------
00233 void ClusterSequence::_add_neighbours_to_tile_union(const int tile_index, 
00234                vector<int> & tile_union, int & n_near_tiles) const {
00235   for (Tile * const * near_tile = _tiles[tile_index].begin_tiles; 
00236        near_tile != _tiles[tile_index].end_tiles; near_tile++){
00237     // get the tile number
00238     tile_union[n_near_tiles] = *near_tile - & _tiles[0];
00239     n_near_tiles++;
00240   }
00241 }
00242 
00243 
00244 //----------------------------------------------------------------------
00248 inline void ClusterSequence::_add_untagged_neighbours_to_tile_union(
00249                const int tile_index, 
00250                vector<int> & tile_union, int & n_near_tiles)  {
00251   for (Tile ** near_tile = _tiles[tile_index].begin_tiles; 
00252        near_tile != _tiles[tile_index].end_tiles; near_tile++){
00253     if (! (*near_tile)->tagged) {
00254       (*near_tile)->tagged = true;
00255       // get the tile number
00256       tile_union[n_near_tiles] = *near_tile - & _tiles[0];
00257       n_near_tiles++;
00258     }
00259   }
00260 }
00261 
00262 
00263 //----------------------------------------------------------------------
00265 void ClusterSequence::_tiled_N2_cluster() {
00266 
00267   _initialise_tiles();
00268 
00269   int n = _jets.size();
00270   TiledJet * briefjets = new TiledJet[n];
00271   TiledJet * jetA = briefjets, * jetB;
00272   TiledJet oldB;
00273   
00274 
00275   // will be used quite deep inside loops, but declare it here so that
00276   // memory (de)allocation gets done only once
00277   vector<int> tile_union(3*n_tile_neighbours);
00278   
00279   // initialise the basic jet info 
00280   for (int i = 0; i< n; i++) {
00281     _tj_set_jetinfo(jetA, i);
00282     //cout << i<<": "<<jetA->tile_index<<"\n";
00283     jetA++; // move on to next entry of briefjets
00284   }
00285   TiledJet * tail = jetA; // a semaphore for the end of briefjets
00286   TiledJet * head = briefjets; // a nicer way of naming start
00287 
00288   // set up the initial nearest neighbour information
00289   vector<Tile>::const_iterator tile;
00290   for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
00291     // first do it on this tile
00292     for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
00293       for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
00294         double dist = _bj_dist(jetA,jetB);
00295         if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
00296         if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
00297       }
00298     }
00299     // then do it for RH tiles
00300     for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
00301       for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
00302         for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
00303           double dist = _bj_dist(jetA,jetB);
00304           if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
00305           if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
00306         }
00307       }
00308     }
00309   }
00310   
00311   // now create the diJ (where J is i's NN) table -- remember that 
00312   // we differ from standard normalisation here by a factor of R2
00313   double * diJ = new double[n];
00314   jetA = head;
00315   for (int i = 0; i < n; i++) {
00316     diJ[i] = _bj_diJ(jetA);
00317     jetA++; // have jetA follow i
00318   }
00319 
00320   // now run the recombination loop
00321   int history_location = n-1;
00322   while (tail != head) {
00323 
00324     // find the minimum of the diJ on this round
00325     double diJ_min = diJ[0];
00326     int diJ_min_jet = 0;
00327     for (int i = 1; i < n; i++) {
00328       if (diJ[i] < diJ_min) {diJ_min_jet = i; diJ_min  = diJ[i];}
00329     }
00330 
00331     // do the recombination between A and B
00332     history_location++;
00333     jetA = & briefjets[diJ_min_jet];
00334     jetB = jetA->NN;
00335     // put the normalisation back in
00336     diJ_min *= _invR2; 
00337 
00338     //if (n == 19) {cout << "Hello "<<jetA-head<<" "<<jetB-head<<"\n";}
00339 
00340     //cout <<" WILL RECOMBINE "<< jetA-briefjets<<" "<<jetB-briefjets<<"\n";
00341 
00342     if (jetB != NULL) {
00343       // jet-jet recombination
00344       // If necessary relabel A & B to ensure jetB < jetA, that way if
00345       // the larger of them == newtail then that ends up being jetA and 
00346       // the new jet that is added as jetB is inserted in a position that
00347       // has a future!
00348       if (jetA < jetB) {swap(jetA,jetB);}
00349 
00350       int nn; // new jet index
00351       _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
00352 
00353       //OBS// get the two history indices
00354       //OBSint hist_a = _jets[jetA->_jets_index].cluster_hist_index();
00355       //OBSint hist_b = _jets[jetB->_jets_index].cluster_hist_index();
00356       //OBS// create the recombined jet
00357       //OBS_jets.push_back(_jets[jetA->_jets_index] + _jets[jetB->_jets_index]);
00358       //OBSint nn = _jets.size() - 1;
00359       //OBS_jets[nn].set_cluster_hist_index(history_location);
00360       //OBS// update history
00361       //OBS//cout <<n-1<<" "<<jetA-head<<" "<<jetB-head<<"; ";
00362       //OBS_add_step_to_history(history_location, 
00363       //OBS                min(hist_a,hist_b),max(hist_a,hist_b),
00364       //OBS                        nn, diJ_min);
00365 
00366       // what was jetB will now become the new jet
00367       _bj_remove_from_tiles(jetA);
00368       oldB = * jetB;  // take a copy because we will need it...
00369       _bj_remove_from_tiles(jetB);
00370       _tj_set_jetinfo(jetB, nn); // also registers the jet in the tiling
00371     } else {
00372       // jet-beam recombination
00373       _do_iB_recombination_step(jetA->_jets_index, diJ_min);
00374             
00375       //OBS// get the hist_index
00376       //OBSint hist_a = _jets[jetA->_jets_index].cluster_hist_index();
00377       //OBS//cout <<n-1<<" "<<jetA-head<<" "<<-1<<"; ";
00378       //OBS_add_step_to_history(history_location,hist_a,BeamJet,Invalid,diJ_min); 
00379       _bj_remove_from_tiles(jetA);
00380     }
00381 
00382     // first establish the set of tiles over which we are going to 
00383     // have to run searches for updated and new nearest-neighbours
00384     int n_near_tiles = 0;
00385     _add_neighbours_to_tile_union(jetA->tile_index, tile_union, n_near_tiles);
00386     if (jetB != NULL) {
00387       bool sort_it = false;
00388       if (jetB->tile_index != jetA->tile_index) {
00389         sort_it = true;
00390         _add_neighbours_to_tile_union(jetB->tile_index,tile_union,n_near_tiles);
00391       }
00392       if (oldB.tile_index != jetA->tile_index && 
00393           oldB.tile_index != jetB->tile_index) {
00394         sort_it = true;
00395         _add_neighbours_to_tile_union(oldB.tile_index,tile_union,n_near_tiles);
00396       }
00397 
00398       if (sort_it) {
00399         // sort the tiles before then compressing the list
00400         sort(tile_union.begin(), tile_union.begin()+n_near_tiles);
00401         // and now condense the list
00402         int nnn = 1;
00403         for (int i = 1; i < n_near_tiles; i++) {
00404           if (tile_union[i] != tile_union[nnn-1]) {
00405             tile_union[nnn] = tile_union[i]; 
00406             nnn++;
00407           }
00408         }
00409         n_near_tiles = nnn;
00410       }
00411     }
00412 
00413     // now update our nearest neighbour info and diJ table
00414     // first reduce size of table
00415     tail--; n--;
00416     if (jetA == tail) {
00417       // there is nothing to be done
00418     } else {
00419       // Copy last jet contents and diJ info into position of jetA
00420       *jetA = *tail;
00421       diJ[jetA - head] = diJ[tail-head];
00422       // IN the tiling fix pointers to tail and turn them into
00423       // pointers to jetA (from predecessors, successors and the tile
00424       // head if need be)
00425       if (jetA->previous == NULL) {
00426         _tiles[jetA->tile_index].head = jetA;
00427       } else {
00428         jetA->previous->next = jetA;
00429       }
00430       if (jetA->next != NULL) {jetA->next->previous = jetA;}
00431     }
00432 
00433     // Initialise jetB's NN distance as well as updating it for 
00434     // other particles.
00435     for (int itile = 0; itile < n_near_tiles; itile++) {
00436       Tile * tile = &_tiles[tile_union[itile]];
00437       for (TiledJet * jetI = tile->head; jetI != NULL; jetI = jetI->next) {
00438         // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
00439         if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
00440           jetI->NN_dist = _R2;
00441           jetI->NN      = NULL;
00442           // now go over tiles that are neighbours of I (include own tile)
00443           for (Tile ** near_tile  = tile->begin_tiles; 
00444                        near_tile != tile->end_tiles; near_tile++) {
00445             // and then over the contents of that tile
00446             for (TiledJet * jetJ  = (*near_tile)->head; 
00447                             jetJ != NULL; jetJ = jetJ->next) {
00448               double dist = _bj_dist(jetI,jetJ);
00449               if (dist < jetI->NN_dist && jetJ != jetI) {
00450                 jetI->NN_dist = dist; jetI->NN = jetJ;
00451               }
00452             }
00453           }
00454           diJ[jetI-head] = _bj_diJ(jetI); // update diJ 
00455         }
00456         // check whether new jetB is closer than jetI's current NN and
00457         // if need to update things
00458         if (jetB != NULL) {
00459           double dist = _bj_dist(jetI,jetB);
00460           if (dist < jetI->NN_dist) {
00461             if (jetI != jetB) {
00462               jetI->NN_dist = dist;
00463               jetI->NN = jetB;
00464               diJ[jetI-head] = _bj_diJ(jetI); // update diJ...
00465             }
00466           }
00467           if (dist < jetB->NN_dist) {
00468             if (jetI != jetB) {
00469               jetB->NN_dist = dist;
00470               jetB->NN      = jetI;}
00471           }
00472         }
00473       }
00474     }
00475 
00476 
00477     if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
00478     //cout << n<<" "<<briefjets[95].NN-briefjets<<" "<<briefjets[95].NN_dist <<"\n";
00479 
00480     // remember to update pointers to tail
00481     for (Tile ** near_tile = _tiles[tail->tile_index].begin_tiles; 
00482                  near_tile!= _tiles[tail->tile_index].end_tiles; near_tile++){
00483       // and then the contents of that tile
00484       for (TiledJet * jetJ = (*near_tile)->head; 
00485                      jetJ != NULL; jetJ = jetJ->next) {
00486         if (jetJ->NN == tail) {jetJ->NN = jetA;}
00487       }
00488     }
00489 
00490     //for (int i = 0; i < n; i++) {
00491     //  if (briefjets[i].NN-briefjets >= n && briefjets[i].NN != NULL) {cout <<"YOU MUST BE CRAZY for n ="<<n<<", i = "<<i<<", NN = "<<briefjets[i].NN-briefjets<<"\n";}
00492     //}
00493 
00494 
00495     if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
00496     //cout << briefjets[95].NN-briefjets<<" "<<briefjets[95].NN_dist <<"\n";
00497 
00498   }
00499 
00500   // final cleaning up;
00501   delete[] diJ;
00502   delete[] briefjets;
00503 }
00504 
00505 
00506 //----------------------------------------------------------------------
00508 void ClusterSequence::_faster_tiled_N2_cluster() {
00509 
00510   _initialise_tiles();
00511 
00512   int n = _jets.size();
00513   TiledJet * briefjets = new TiledJet[n];
00514   TiledJet * jetA = briefjets, * jetB;
00515   TiledJet oldB;
00516   
00517 
00518   // will be used quite deep inside loops, but declare it here so that
00519   // memory (de)allocation gets done only once
00520   vector<int> tile_union(3*n_tile_neighbours);
00521   
00522   // initialise the basic jet info 
00523   for (int i = 0; i< n; i++) {
00524     _tj_set_jetinfo(jetA, i);
00525     //cout << i<<": "<<jetA->tile_index<<"\n";
00526     jetA++; // move on to next entry of briefjets
00527   }
00528   TiledJet * head = briefjets; // a nicer way of naming start
00529 
00530   // set up the initial nearest neighbour information
00531   vector<Tile>::const_iterator tile;
00532   for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
00533     // first do it on this tile
00534     for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
00535       for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
00536         double dist = _bj_dist(jetA,jetB);
00537         if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
00538         if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
00539       }
00540     }
00541     // then do it for RH tiles
00542     for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
00543       for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
00544         for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
00545           double dist = _bj_dist(jetA,jetB);
00546           if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
00547           if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
00548         }
00549       }
00550     }
00551     // no need to do it for LH tiles, since they are implicitly done
00552     // when we set NN for both jetA and jetB on the RH tiles.
00553   }
00554 
00555   
00556   // now create the diJ (where J is i's NN) table -- remember that 
00557   // we differ from standard normalisation here by a factor of R2
00558   // (corrected for at the end). 
00559   struct diJ_plus_link {
00560     double     diJ; // the distance
00561     TiledJet * jet; // the jet (i) for which we've found this distance
00562                     // (whose NN will the J).
00563   };
00564   diJ_plus_link * diJ = new diJ_plus_link[n];
00565   jetA = head;
00566   for (int i = 0; i < n; i++) {
00567     diJ[i].diJ = _bj_diJ(jetA); // kt distance * R^2
00568     diJ[i].jet = jetA;  // our compact diJ table will not be in      
00569     jetA->diJ_posn = i; // one-to-one corresp. with non-compact jets,
00570                         // so set up bi-directional correspondence here.
00571     jetA++; // have jetA follow i 
00572   }
00573 
00574   // now run the recombination loop
00575   int history_location = n-1;
00576   while (n > 0) {
00577 
00578     // find the minimum of the diJ on this round
00579     diJ_plus_link * best, *stop; // pointers a bit faster than indices
00580     // could use best to keep track of diJ min, but it turns out to be
00581     // marginally faster to have a separate variable (avoids n
00582     // dereferences at the expense of n/2 assignments).
00583     double diJ_min = diJ[0].diJ; // initialise the best one here.
00584     best = diJ;                  // and here
00585     stop = diJ+n;
00586     for (diJ_plus_link * here = diJ+1; here != stop; here++) {
00587       if (here->diJ < diJ_min) {best = here; diJ_min  = here->diJ;}
00588     }
00589 
00590     // do the recombination between A and B
00591     history_location++;
00592     jetA = best->jet;
00593     jetB = jetA->NN;
00594     // put the normalisation back in
00595     diJ_min *= _invR2; 
00596 
00597     if (jetB != NULL) {
00598       // jet-jet recombination
00599       // If necessary relabel A & B to ensure jetB < jetA, that way if
00600       // the larger of them == newtail then that ends up being jetA and 
00601       // the new jet that is added as jetB is inserted in a position that
00602       // has a future!
00603       if (jetA < jetB) {swap(jetA,jetB);}
00604 
00605       int nn; // new jet index
00606       _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
00607       
00608       //OBS// get the two history indices
00609       //OBSint ihstry_a = _jets[jetA->_jets_index].cluster_hist_index();
00610       //OBSint ihstry_b = _jets[jetB->_jets_index].cluster_hist_index();
00611       //OBS// create the recombined jet
00612       //OBS_jets.push_back(_jets[jetA->_jets_index] + _jets[jetB->_jets_index]);
00613       //OBSint nn = _jets.size() - 1;
00614       //OBS_jets[nn].set_cluster_hist_index(history_location);
00615       //OBS// update history
00616       //OBS//cout <<n-1<<" "<<jetA-head<<" "<<jetB-head<<"; ";
00617       //OBS_add_step_to_history(history_location, 
00618       //OBS                min(ihstry_a,ihstry_b),max(ihstry_a,ihstry_b),
00619       //OBS                        nn, diJ_min);
00620       // what was jetB will now become the new jet
00621       _bj_remove_from_tiles(jetA);
00622       oldB = * jetB;  // take a copy because we will need it...
00623       _bj_remove_from_tiles(jetB);
00624       _tj_set_jetinfo(jetB, nn); // cause jetB to become _jets[nn]
00625                                  // (also registers the jet in the tiling)
00626     } else {
00627       // jet-beam recombination
00628       // get the hist_index
00629       _do_iB_recombination_step(jetA->_jets_index, diJ_min);
00630       //OBSint ihstry_a = _jets[jetA->_jets_index].cluster_hist_index();
00631       //OBS//cout <<n-1<<" "<<jetA-head<<" "<<-1<<"; ";
00632       //OBS_add_step_to_history(history_location,ihstry_a,BeamJet,Invalid,diJ_min); 
00633       _bj_remove_from_tiles(jetA);
00634     }
00635 
00636     // first establish the set of tiles over which we are going to
00637     // have to run searches for updated and new nearest-neighbours --
00638     // basically a combination of vicinity of the tiles of the two old
00639     // and one new jet.
00640     int n_near_tiles = 0;
00641     _add_untagged_neighbours_to_tile_union(jetA->tile_index, 
00642                                            tile_union, n_near_tiles);
00643     if (jetB != NULL) {
00644       if (jetB->tile_index != jetA->tile_index) {
00645         _add_untagged_neighbours_to_tile_union(jetB->tile_index,
00646                                                tile_union,n_near_tiles);
00647       }
00648       if (oldB.tile_index != jetA->tile_index && 
00649           oldB.tile_index != jetB->tile_index) {
00650         _add_untagged_neighbours_to_tile_union(oldB.tile_index,
00651                                                tile_union,n_near_tiles);
00652       }
00653     }
00654 
00655     // now update our nearest neighbour info and diJ table
00656     // first reduce size of table
00657     n--;
00658     // then compactify the diJ by taking the last of the diJ and copying
00659     // it to the position occupied by the diJ for jetA
00660     diJ[n].jet->diJ_posn = jetA->diJ_posn;
00661     diJ[jetA->diJ_posn] = diJ[n];
00662 
00663     // Initialise jetB's NN distance as well as updating it for 
00664     // other particles.
00665     // Run over all tiles in our union 
00666     for (int itile = 0; itile < n_near_tiles; itile++) {
00667       Tile * tile = &_tiles[tile_union[itile]];
00668       tile->tagged = false; // reset tag, since we're done with unions
00669       // run over all jets in the current tile
00670       for (TiledJet * jetI = tile->head; jetI != NULL; jetI = jetI->next) {
00671         // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
00672         if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
00673           jetI->NN_dist = _R2;
00674           jetI->NN      = NULL;
00675           // now go over tiles that are neighbours of I (include own tile)
00676           for (Tile ** near_tile  = tile->begin_tiles; 
00677                        near_tile != tile->end_tiles; near_tile++) {
00678             // and then over the contents of that tile
00679             for (TiledJet * jetJ  = (*near_tile)->head; 
00680                             jetJ != NULL; jetJ = jetJ->next) {
00681               double dist = _bj_dist(jetI,jetJ);
00682               if (dist < jetI->NN_dist && jetJ != jetI) {
00683                 jetI->NN_dist = dist; jetI->NN = jetJ;
00684               }
00685             }
00686           }
00687           diJ[jetI->diJ_posn].diJ = _bj_diJ(jetI); // update diJ kt-dist
00688         }
00689         // check whether new jetB is closer than jetI's current NN and
00690         // if jetI is closer than jetB's current (evolving) nearest
00691         // neighbour. Where relevant update things
00692         if (jetB != NULL) {
00693           double dist = _bj_dist(jetI,jetB);
00694           if (dist < jetI->NN_dist) {
00695             if (jetI != jetB) {
00696               jetI->NN_dist = dist;
00697               jetI->NN = jetB;
00698               diJ[jetI->diJ_posn].diJ = _bj_diJ(jetI); // update diJ...
00699             }
00700           }
00701           if (dist < jetB->NN_dist) {
00702             if (jetI != jetB) {
00703               jetB->NN_dist = dist;
00704               jetB->NN      = jetI;}
00705           }
00706         }
00707       }
00708     }
00709 
00710     // finally, register the updated kt distance for B
00711     if (jetB != NULL) {diJ[jetB->diJ_posn].diJ = _bj_diJ(jetB);}
00712 
00713   }
00714 
00715   // final cleaning up;
00716   delete[] diJ;
00717   delete[] briefjets;
00718 }
00719 
00720 
00721 
00722 //----------------------------------------------------------------------
00725 void ClusterSequence::_minheap_faster_tiled_N2_cluster() {
00726 
00727   _initialise_tiles();
00728 
00729   int n = _jets.size();
00730   TiledJet * briefjets = new TiledJet[n];
00731   TiledJet * jetA = briefjets, * jetB;
00732   TiledJet oldB;
00733   
00734 
00735   // will be used quite deep inside loops, but declare it here so that
00736   // memory (de)allocation gets done only once
00737   vector<int> tile_union(3*n_tile_neighbours);
00738   
00739   // initialise the basic jet info 
00740   for (int i = 0; i< n; i++) {
00741     _tj_set_jetinfo(jetA, i);
00742     //cout << i<<": "<<jetA->tile_index<<"\n";
00743     jetA++; // move on to next entry of briefjets
00744   }
00745   TiledJet * head = briefjets; // a nicer way of naming start
00746 
00747   // set up the initial nearest neighbour information
00748   vector<Tile>::const_iterator tile;
00749   for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
00750     // first do it on this tile
00751     for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
00752       for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
00753         double dist = _bj_dist(jetA,jetB);
00754         if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
00755         if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
00756       }
00757     }
00758     // then do it for RH tiles
00759     for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
00760       for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
00761         for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
00762           double dist = _bj_dist(jetA,jetB);
00763           if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
00764           if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
00765         }
00766       }
00767     }
00768     // no need to do it for LH tiles, since they are implicitly done
00769     // when we set NN for both jetA and jetB on the RH tiles.
00770   }
00771 
00772   
00776   //struct diJ_plus_link {
00777   //  double     diJ; // the distance
00778   //  TiledJet * jet; // the jet (i) for which we've found this distance
00779   //                  // (whose NN will the J).
00780   //};
00781   //diJ_plus_link * diJ = new diJ_plus_link[n];
00782   //jetA = head;
00783   //for (int i = 0; i < n; i++) {
00784   //  diJ[i].diJ = _bj_diJ(jetA); // kt distance * R^2
00785   //  diJ[i].jet = jetA;  // our compact diJ table will not be in            
00786   //  jetA->diJ_posn = i; // one-to-one corresp. with non-compact jets,
00787   //                      // so set up bi-directional correspondence here.
00788   //  jetA++; // have jetA follow i 
00789   //}
00790 
00791   vector<double> diJs(n);
00792   for (int i = 0; i < n; i++) {
00793     diJs[i] = _bj_diJ(&briefjets[i]);
00794     briefjets[i].label_minheap_update_done();
00795   }
00796   MinHeap minheap(diJs);
00797   // have a stack telling us which jets we'll have to update on the heap
00798   vector<TiledJet *> jets_for_minheap;
00799   jets_for_minheap.reserve(n); 
00800 
00801   // now run the recombination loop
00802   int history_location = n-1;
00803   while (n > 0) {
00804 
00805     double diJ_min = minheap.minval() *_invR2;
00806     jetA = head + minheap.minloc();
00807 
00808     // do the recombination between A and B
00809     history_location++;
00810     jetB = jetA->NN;
00811 
00812     if (jetB != NULL) {
00813       // jet-jet recombination
00814       // If necessary relabel A & B to ensure jetB < jetA, that way if
00815       // the larger of them == newtail then that ends up being jetA and 
00816       // the new jet that is added as jetB is inserted in a position that
00817       // has a future!
00818       if (jetA < jetB) {swap(jetA,jetB);}
00819 
00820       int nn; // new jet index
00821       _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
00822       
00823       // what was jetB will now become the new jet
00824       _bj_remove_from_tiles(jetA);
00825       oldB = * jetB;  // take a copy because we will need it...
00826       _bj_remove_from_tiles(jetB);
00827       _tj_set_jetinfo(jetB, nn); // cause jetB to become _jets[nn]
00828                                  // (also registers the jet in the tiling)
00829     } else {
00830       // jet-beam recombination
00831       // get the hist_index
00832       _do_iB_recombination_step(jetA->_jets_index, diJ_min);
00833       _bj_remove_from_tiles(jetA);
00834     }
00835 
00836     // remove the minheap entry for jetA
00837     minheap.remove(jetA-head);
00838 
00839     // first establish the set of tiles over which we are going to
00840     // have to run searches for updated and new nearest-neighbours --
00841     // basically a combination of vicinity of the tiles of the two old
00842     // and one new jet.
00843     int n_near_tiles = 0;
00844     _add_untagged_neighbours_to_tile_union(jetA->tile_index, 
00845                                            tile_union, n_near_tiles);
00846     if (jetB != NULL) {
00847       if (jetB->tile_index != jetA->tile_index) {
00848         _add_untagged_neighbours_to_tile_union(jetB->tile_index,
00849                                                tile_union,n_near_tiles);
00850       }
00851       if (oldB.tile_index != jetA->tile_index && 
00852           oldB.tile_index != jetB->tile_index) {
00853         _add_untagged_neighbours_to_tile_union(oldB.tile_index,
00854                                                tile_union,n_near_tiles);
00855       }
00856       // indicate that we'll have to update jetB in the minheap
00857       jetB->label_minheap_update_needed();
00858       jets_for_minheap.push_back(jetB);
00859     }
00860 
00861 
00862     // Initialise jetB's NN distance as well as updating it for 
00863     // other particles.
00864     // Run over all tiles in our union 
00865     for (int itile = 0; itile < n_near_tiles; itile++) {
00866       Tile * tile = &_tiles[tile_union[itile]];
00867       tile->tagged = false; // reset tag, since we're done with unions
00868       // run over all jets in the current tile
00869       for (TiledJet * jetI = tile->head; jetI != NULL; jetI = jetI->next) {
00870         // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
00871         if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
00872           jetI->NN_dist = _R2;
00873           jetI->NN      = NULL;
00874           // label jetI as needing heap action...
00875           if (!jetI->minheap_update_needed()) {
00876             jetI->label_minheap_update_needed();
00877             jets_for_minheap.push_back(jetI);}
00878           // now go over tiles that are neighbours of I (include own tile)
00879           for (Tile ** near_tile  = tile->begin_tiles; 
00880                        near_tile != tile->end_tiles; near_tile++) {
00881             // and then over the contents of that tile
00882             for (TiledJet * jetJ  = (*near_tile)->head; 
00883                             jetJ != NULL; jetJ = jetJ->next) {
00884               double dist = _bj_dist(jetI,jetJ);
00885               if (dist < jetI->NN_dist && jetJ != jetI) {
00886                 jetI->NN_dist = dist; jetI->NN = jetJ;
00887               }
00888             }
00889           }
00890         }
00891         // check whether new jetB is closer than jetI's current NN and
00892         // if jetI is closer than jetB's current (evolving) nearest
00893         // neighbour. Where relevant update things
00894         if (jetB != NULL) {
00895           double dist = _bj_dist(jetI,jetB);
00896           if (dist < jetI->NN_dist) {
00897             if (jetI != jetB) {
00898               jetI->NN_dist = dist;
00899               jetI->NN = jetB;
00900               // label jetI as needing heap action...
00901               if (!jetI->minheap_update_needed()) {
00902                 jetI->label_minheap_update_needed();
00903                 jets_for_minheap.push_back(jetI);}
00904             }
00905           }
00906           if (dist < jetB->NN_dist) {
00907             if (jetI != jetB) {
00908               jetB->NN_dist = dist;
00909               jetB->NN      = jetI;}
00910           }
00911         }
00912       }
00913     }
00914 
00915     // deal with jets whose minheap entry needs updating
00916     while (jets_for_minheap.size() > 0) {
00917       TiledJet * jetI = jets_for_minheap.back(); 
00918       jets_for_minheap.pop_back();
00919       minheap.update(jetI-head, _bj_diJ(jetI));
00920       jetI->label_minheap_update_done();
00921     }
00922     n--;
00923   }
00924 
00925   // final cleaning up;
00926   delete[] briefjets;
00927 }
00928 
00929 
00930 FASTJET_END_NAMESPACE
00931 

Generated on Fri Aug 15 13:45:28 2008 for fastjet by  doxygen 1.4.2