FastJet 3.0beta1
ClosestPair2D.hh
00001 //STARTHEADER
00002 // $Id: ClosestPair2D.hh 1761 2010-09-16 10:43:18Z 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 #ifndef __FASTJET_CLOSESTPAIR2D__HH__
00032 #define __FASTJET_CLOSESTPAIR2D__HH__
00033 
00034 #include<vector>
00035 #include<stack>
00036 #include<iostream>
00037 #include "fastjet/internal/ClosestPair2DBase.hh"
00038 #include "fastjet/internal/SearchTree.hh"
00039 #include "fastjet/internal/MinHeap.hh"
00040 
00041 FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
00042 
00043 //----------------------------------------------------------------------
00044 /// \if internal_doc
00045 /// @ingroup internal
00046 /// \class ClosestPair2D
00047 /// concrete implementation for finding closest pairs in 2D -- will
00048 /// use Chan's (hopefully efficient) shuffle based structures
00049 /// \endif
00050 class ClosestPair2D : public ClosestPair2DBase {
00051 public:
00052   /// constructor from a vector of 2D positions -- number of objects
00053   /// after insertion and deletion must never exceed positions.size();
00054   /// objects are given IDs that correspond to their index in the vector 
00055   /// of positions
00056   ClosestPair2D(const std::vector<Coord2D> & positions, 
00057                 const Coord2D & left_corner, const Coord2D & right_corner) {
00058     _initialize(positions, left_corner, right_corner, positions.size());
00059   };
00060 
00061   /// constructor which allows structure to grow beyond positions.size(), up
00062   /// to max_size
00063   ClosestPair2D(const std::vector<Coord2D> & positions, 
00064                 const Coord2D & left_corner, const Coord2D & right_corner,
00065                 const unsigned int max_size) {
00066     _initialize(positions, left_corner, right_corner, max_size);
00067   };
00068 
00069   /// provides the IDs of the closest pair as well as the distance between
00070   /// them
00071   void closest_pair(unsigned int & ID1, unsigned int & ID2, 
00072                     double & distance2) const;
00073 
00074   /// removes the entry labelled by ID from the object;
00075   void remove(unsigned int ID);
00076  
00077   /// inserts the position into the closest pair structure and returns the
00078   /// ID that has been allocated for the object.
00079   unsigned int insert(const Coord2D &);
00080 
00081   /// removes ID1 and ID2 and inserts position, returning the ID 
00082   /// corresponding to position...
00083   virtual unsigned int replace(unsigned int ID1, unsigned int ID2, 
00084                                const Coord2D & position);
00085 
00086   /// replaces IDs_to_remove with points at the new_positions
00087   /// indicating the IDs allocated to the new points in new_IDs
00088   virtual void replace_many(const std::vector<unsigned int> & IDs_to_remove,
00089                             const std::vector<Coord2D> & new_positions,
00090                             std::vector<unsigned int> & new_IDs);
00091 
00092   // mostly for checking how things are working...
00093   inline void print_tree_depths(std::ostream & outdev) const {
00094     outdev    << _trees[0]->max_depth() << " "
00095               << _trees[1]->max_depth() << " "
00096               << _trees[2]->max_depth() << "\n";
00097   };
00098 
00099   unsigned int size();
00100 
00101 private:
00102   
00103   void _initialize(const std::vector<Coord2D> & positions, 
00104               const Coord2D & left_corner, const Coord2D & right_corner,
00105               const unsigned int max_size);
00106 
00107   static const unsigned int _nshift = 3;
00108 
00109   class Point; // will be defined below
00110 
00111   /// since sets of three objects will crop up repeatedly, useful
00112   /// to have a triplet class?
00113   template<class T> class triplet {
00114   public:
00115     inline const T & operator[](unsigned int i) const {return _contents[i];};
00116     inline       T & operator[](unsigned int i)       {return _contents[i];};
00117   private:
00118     T _contents[_nshift];
00119   };
00120 
00121 
00122   /// class that will take care of ordering of shuffles for us
00123   class Shuffle {
00124   public:
00125     unsigned int x, y;
00126     Point * point;
00127     bool operator<(const Shuffle &) const;
00128     void operator+=(unsigned int shift) {x += shift; y+= shift;};
00129   };
00130 
00131   typedef SearchTree<Shuffle>     Tree;
00132   typedef Tree::circulator        circulator;
00133   typedef Tree::const_circulator  const_circulator;
00134 
00135 
00136   triplet<std::auto_ptr<Tree> >  _trees;
00137   std::auto_ptr<MinHeap> _heap;
00138   std::vector<Point>     _points;
00139   std::stack<Point *>    _available_points;
00140 
00141   /// points that are "under review" in some way
00142   std::vector<Point *>   _points_under_review;
00143 
00144   // different statuses for review
00145   static const unsigned int _remove_heap_entry = 1;
00146   static const unsigned int _review_heap_entry = 2;
00147   static const unsigned int _review_neighbour  = 4;
00148 
00149   /// add a label to a point as to the nature of review needed
00150   /// (includes adding it to list of points needing review) [doesn't
00151   /// affect other labels already set for the point]
00152   void _add_label(Point * point, unsigned int review_flag);
00153 
00154   /// sets the label for the point to be exclusively this 
00155   /// review flag (and adds it to list of points needing review
00156   /// if not already there)
00157   void _set_label(Point * point, unsigned int review_flag);
00158 
00159   /// for all entries of the _points_under_review[] vector, carry out
00160   /// the actions indicated by its review flag; the points are
00161   /// then removed from _points_under_review[] and their flags
00162   /// set to zero
00163   void _deal_with_points_to_review();
00164 
00165   /// carry out the search-tree related operations of point removal
00166   void _remove_from_search_tree(Point * point_to_remove);
00167 
00168   /// carry out the search-tree related operations of point insertion
00169   void _insert_into_search_tree(Point * new_point);
00170 
00171   /// takes a point and creates a shuffle with the given shift
00172   void _point2shuffle(Point & , Shuffle & , unsigned int shift);
00173 
00174   /// pieces needed for converting coordinates to integer
00175   Coord2D _left_corner;
00176   double _range;
00177 
00178   int _ID(const Point *) const;
00179 
00180   triplet<unsigned int> _shifts;     // absolute shifts
00181   triplet<unsigned int> _rel_shifts; // shifts relative to previous shift
00182 
00183   unsigned int _cp_search_range;
00184 };
00185 
00186 
00187 //----------------------------------------------------------------------
00188 /// \if internal_doc
00189 /// @ingroup internal
00190 /// \class ClosestPair2D::Point
00191 /// class for representing all info needed about a point
00192 /// \endif
00193 class ClosestPair2D::Point {
00194 public:
00195   /// the point's coordinates
00196   Coord2D coord;
00197   /// a pointer to its closest neighbour in our structure
00198   Point * neighbour;
00199   /// the corresponding squared distance
00200   double  neighbour_dist2;
00201   /// circulators for each of the shifts of the shuffles
00202   triplet<circulator> circ;
00203 
00204   /// indicates that something special is currently happening to this point
00205   unsigned int review_flag;
00206 
00207   /// returns the distance between two of these objects
00208   double distance2(const Point & other) const {
00209     return coord.distance2(other.coord);
00210   };
00211 
00212   /// creates a shuffle for us with a given shift
00213   //void set_shuffle(Shuffle & shuffle);
00214 };
00215 
00216 
00217 //----------------------------------------------------------------------
00218 /// returns true if floor(ln_base2(x)) < floor(ln_base2(y)), using
00219 /// Chan's neat trick...
00220 inline bool floor_ln2_less(unsigned x, unsigned y) {
00221   if (x>y) return false;
00222   return (x < (x^y)); // beware of operator precedence...
00223 }
00224 
00225 
00226 //----------------------------------------------------------------------
00227 /// returns the ID for the specified point...
00228 inline int ClosestPair2D::_ID(const Point * point) const {
00229   return point - &(_points[0]);
00230 }
00231 
00232 
00233 //
00234 inline unsigned int ClosestPair2D::size() {
00235   return _points.size() - _available_points.size();
00236 }
00237 
00238 
00239 
00240 FASTJET_END_NAMESPACE
00241 
00242 #endif // __FASTJET_CLOSESTPAIR2D__HH__
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends