covboxes.h

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////////////
00002 ///
00003 /// @file covboxes.h
00004 ///
00005 /// A box cover type.
00006 /// This file contains the definition of a class that represents
00007 /// a cover of a bounded rectangular region in R^n by means of open boxes.
00008 /// The class includes a method for computing a cover of any open box
00009 /// or a point by means of the boxes in this class.
00010 ///
00011 /// @author Pawel Pilarczyk
00012 ///
00013 /////////////////////////////////////////////////////////////////////////////
00014 
00015 // Copyright (C) 1997-2010 by Pawel Pilarczyk.
00016 //
00017 // This file is part of my research software package.  This is free software;
00018 // you can redistribute it and/or modify it under the terms of the GNU
00019 // General Public License as published by the Free Software Foundation;
00020 // either version 2 of the License, or (at your option) any later version.
00021 //
00022 // This software is distributed in the hope that it will be useful,
00023 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025 // GNU General Public License for more details.
00026 //
00027 // You should have received a copy of the GNU General Public License along
00028 // with this software; see the file "license.txt".  If not, write to the
00029 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00030 // MA 02111-1307, USA.
00031 
00032 // Started on March 13, 2009. Last revision: June 18, 2009.
00033 
00034 
00035 #ifndef _FINRESDYN_COVBOXES_H_
00036 #define _FINRESDYN_COVBOXES_H_
00037 
00038 
00039 // include some standard C++ header files
00040 #include <vector>
00041 #include <cmath>
00042 
00043 // include some header files from the CHomP library
00044 #include "chomp/struct/hashsets.h"
00045 #include "chomp/cubes/pointset.h"
00046 #include "chomp/cubes/cube.h"
00047 
00048 // include local header files
00049 #include "rounding.h"
00050 #include "streams.h"
00051 
00052 
00053 // --------------------------------------------------
00054 // --------------- dummy box numbers ----------------
00055 // --------------------------------------------------
00056 
00057 /// A dummy class for adding box numbers.
00058 class DummyBoxNumbers
00059 {
00060 public:
00061         /// Forgets the box number.
00062         void add (int) {};
00063 
00064 }; /* class DummyBoxNumbers */
00065 
00066 
00067 // --------------------------------------------------
00068 // ------------------- box cover --------------------
00069 // --------------------------------------------------
00070 
00071 /// A cover of a subset in R^n consisting of open boxes.
00072 template <class NumType>
00073 class tCoverBoxes
00074 {
00075 public:
00076         /// The type of numbers in the Henon map.
00077         typedef NumType NumberType;
00078 
00079         /// The constructor of an open cover object.
00080         tCoverBoxes (const int spaceDim, const NumType *leftCorner,
00081                 const NumType *boxWidths, const int *partCounts,
00082                 const NumType *overlap = 0);
00083 
00084         /// The destructor of an open cover object.
00085         ~tCoverBoxes ();
00086 
00087         /// Returns the dimension of the phase space.
00088         int dim () const;
00089 
00090         /// Returns the number of boxes in the cover.
00091         int size () const;
00092 
00093         /// Returns the coordinates of the given box.
00094         /// Throws an exception if the box with this number is undefined.
00095         template <class ResultType>
00096         void get (const int n,
00097                 ResultType *leftBounds, ResultType *rightBounds) const;
00098 
00099         /// Returns the coordinates of the left corner of the range box.
00100         template <class ResultType>
00101         void getLeftCorner (ResultType *leftCorner) const;
00102 
00103         /// Returns the width of the range box in each direction.
00104         template <class ResultType>
00105         void getBoxWidths (ResultType *boxWidths) const;
00106 
00107         /// Covers the given box and adds numbers of all the boxes
00108         /// in the cover to a list using the provided class object
00109         /// with its method "add". Adds boxes necessary to cover
00110         /// the rectangle to the cover if they are not there yet.
00111         /// Throws an exception if the predefined bounds of the covered
00112         /// rectangular box have been exceeded.
00113         /// If requested, comptues a rigorous upper bound for the square
00114         /// of the diameter of the cover.
00115         template <class InputType, class BoxNumbers>
00116         void cover (const InputType *leftBounds,
00117                 const InputType *rightBounds, BoxNumbers &boxNumbers,
00118                 NumType *diameter2 = 0);
00119 
00120         /// Covers a given point with open boxes.
00121         template <class InputType>
00122         void cover (const InputType *x);
00123 
00124         /// Forgets the cover elements.
00125         void forget ();
00126 
00127 private:
00128         /// The dimension of the space.
00129         int spaceDim;
00130 
00131         /// The lower left corner of the covered rectangle.
00132         NumType *leftCorner;
00133 
00134         /// The widths of the covered rectangle in all the directions.
00135         NumType *boxWidths;
00136 
00137         /// The upper right corner of the covered rectangle.
00138         NumType *rightCorner;
00139 
00140         /// The numbers of parts into which the box is subdivided
00141         /// in each direction.
00142         int *partCounts;
00143 
00144         /// The minimal overlap width.
00145         NumType *overlap;
00146 
00147         /// The type of integer coordinates for boxes that represent
00148         /// cover elements.
00149         typedef int CoordType;
00150 
00151         /// A temporary buffer for the coordinates of two cubes.
00152         CoordType *buffer;
00153 
00154         /// The type of a cube that represents a cover element.
00155         typedef chomp::homology::tCubeBase<CoordType> CubeType;
00156 
00157         /// The set of boxes in the cover.
00158         chomp::homology::hashedset<CubeType> boxes;
00159 
00160         /// Computes the real left coordinate in the given direction
00161         /// of a box represented by integer coordinates.
00162         NumType leftBound (int coord, int dir) const;
00163 
00164         /// Computes the real right coordinate in the given direction
00165         /// of a box represented by integer coordinates.
00166         NumType rightBound (int coord, int dir) const;
00167 
00168         /// Computes the left coordinate in the given direction
00169         /// of the leftmost box to cover the given real coordinate.
00170         CoordType leftCoord (const NumType &bound, int dir) const;
00171 
00172         /// Computes the right coordinate in the given direction
00173         /// of the rightmost box to cover the given real coordinate.
00174         CoordType rightCoord (const NumType &bound, int dir) const;
00175 
00176         /// The copy constructor should not be used.
00177         tCoverBoxes (const tCoverBoxes<NumType> &);
00178 
00179         /// The assignment operator should not be used.
00180         tCoverBoxes<NumType> &operator = (const tCoverBoxes<NumType> &);
00181 
00182 }; /* class tCoverBoxes */
00183 
00184 // --------------------------------------------------
00185 
00186 template <class NumType>
00187 inline tCoverBoxes<NumType>::tCoverBoxes (const int spaceDim,
00188         const NumType *leftCorner, const NumType *boxWidths,
00189         const int *partCounts, const NumType *overlap)
00190 {
00191         // make sure the space dimension is within the correct range
00192         if ((spaceDim <= 0) || (spaceDim > 100000))
00193                 throw "Wrong space dimension for a box open cover.";
00194         this -> spaceDim = spaceDim;
00195 
00196         // verify the data and throw an exception if necessary
00197         for (int i = 0; i < spaceDim; ++ i)
00198         {
00199                 if (boxWidths [i] <= 0)
00200                         throw "Trying to use a non-positive box width.";
00201                 if (partCounts [i] <= 0)
00202                         throw "Trying to use a non-positive no. of parts.";
00203                 if (overlap && (overlap [i] <= 0))
00204                         throw "Trying to use a too small overlap.";
00205                 if (overlap && (2.00001 * overlap [i] >=
00206                         boxWidths [i] / partCounts [i]))
00207                 {
00208                         throw "Trying to use too large overlap.";
00209                 }
00210         }
00211 
00212         // copy the lower left corner of the covered area
00213         this -> leftCorner = new NumType [spaceDim];
00214         for (int i = 0; i < spaceDim; ++ i)
00215                 this -> leftCorner [i] = leftCorner [i];
00216 
00217         // copy the widths of the covered area in each direction
00218         this -> boxWidths = new NumType [spaceDim];
00219         for (int i = 0; i < spaceDim; ++ i)
00220                 this -> boxWidths [i] = boxWidths [i];
00221 
00222         // compute an upper bound for the region
00223         this -> rightCorner = new NumType [spaceDim];
00224         for (int i = 0; i < spaceDim; ++ i)
00225         {
00226                 this -> rightCorner [i] = tRounding<NumberType>::add_up
00227                         (this -> leftCorner [i], this -> boxWidths [i]);
00228         }
00229 
00230         // copy the number of parts in each direction
00231         this -> partCounts = new int [spaceDim];
00232         for (int i = 0; i < spaceDim; ++ i)
00233                 this -> partCounts [i] = partCounts [i];
00234 
00235         // copy or create the overlap size in each direction
00236         this -> overlap = new NumType [spaceDim];
00237         if (!overlap)
00238         {
00239                 const NumType min_number =
00240                         tRounding<NumType>::min_number ();
00241                 for (int i = 0; i < spaceDim; ++ i)
00242                         this -> overlap [i] = min_number;
00243         }
00244         else
00245         {
00246                 for (int i = 0; i < spaceDim; ++ i)
00247                         this -> overlap [i] = overlap [i];
00248         }
00249 
00250         // allocate a buffer for temporary point coordinates
00251         this -> buffer = new CoordType [2 * spaceDim];
00252 
00253         return;
00254 } /* tCoverBoxes::tCoverBoxes */
00255 
00256 template <class NumType>
00257 inline tCoverBoxes<NumType>::tCoverBoxes (const tCoverBoxes<NumType> &)
00258 {
00259         throw "Trying to use the copy constructor for an open cover.";
00260         return;
00261 } /* tCoverBoxes::tCoverBoxes */
00262 
00263 template <class NumType>
00264 inline tCoverBoxes<NumType> &tCoverBoxes<NumType>::operator =
00265         (const tCoverBoxes<NumType> &)
00266 {
00267         throw "Trying to use the assignment operator for an open cover.";
00268         return;
00269 } /* tCoverBoxes::operator = */
00270 
00271 template <class NumType>
00272 inline tCoverBoxes<NumType>::~tCoverBoxes ()
00273 {
00274         delete [] leftCorner;
00275         delete [] boxWidths;
00276         delete [] rightCorner;
00277         delete [] partCounts;
00278         delete [] overlap;
00279         delete [] buffer;
00280         return;
00281 } /* tCoverBoxes::~tCoverBoxes */
00282 
00283 template <class NumType>
00284 inline int tCoverBoxes<NumType>::dim () const
00285 {
00286         return spaceDim;
00287 } /* tCoverBoxes::dim */
00288 
00289 template <class NumType>
00290 inline int tCoverBoxes<NumType>::size () const
00291 {
00292         return boxes. size ();
00293 } /* tCoverBoxes::size */
00294 
00295 template <class NumType>
00296 inline void tCoverBoxes<NumType>::forget ()
00297 {
00298         chomp::homology::hashedset<CubeType> empty;
00299         boxes = empty;
00300         return;
00301 } /* tCoverBoxes::forget */
00302 
00303 template <class NumType>
00304 inline NumType tCoverBoxes<NumType>::leftBound (int coord, int dir) const
00305 {
00306         if (coord == 0)
00307                 return leftCorner [dir];
00308         typedef tRounding<NumType> rnd;
00309         NumType left1 = rnd::mul_down (boxWidths [dir], coord);
00310         NumType left2 = rnd::div_down (left1, partCounts [dir]);
00311         return rnd::add_down (leftCorner [dir], left2);
00312 } /* tCoverBoxes::leftBound */
00313 
00314 template <class NumType>
00315 inline NumType tCoverBoxes<NumType>::rightBound (int coord, int dir) const
00316 {
00317         typedef tRounding<NumType> rnd;
00318         if (coord == partCounts [dir])
00319                 return rnd::add_up (leftCorner [dir], boxWidths [dir]);
00320         NumType right1 = rnd::mul_up (boxWidths [dir], coord + 1);
00321         NumType right2 = rnd::div_up (right1, partCounts [dir]);
00322         NumType right3 = rnd::add_up (right2, overlap [dir]);
00323         return rnd::add_up (leftCorner [dir], right3);
00324 } /* tCoverBoxes::rightBound */
00325 
00326 template <class NumType>
00327 inline typename tCoverBoxes<NumType>::CoordType
00328         tCoverBoxes<NumType>::leftCoord
00329         (const NumType &bound, int dir) const
00330 {
00331         // make sure that the left end is within the region
00332         if (bound < leftCorner [dir])
00333                 throw "Trying to cover a box that is too large (left).";
00334 
00335         // return the left corner of the region if this is the case
00336         if (bound == leftCorner [dir])
00337                 return 0;
00338 
00339         // compute a candidate for the left corner coordinate
00340         NumType offset = bound - leftCorner [dir];
00341         int coord = static_cast<CoordType>
00342                 (offset * partCounts [dir] / boxWidths [dir]);
00343         if (coord < 0)
00344                 return 0;
00345 
00346         // verify if the bound could be improved
00347         if ((coord + 1 < partCounts [dir]) &&
00348                 (leftBound (coord + 1, dir) <= bound))
00349         {
00350                 sbug << "* Left bound inc improve.\n";
00351                 ++ coord;
00352         }
00353 
00354         // if the real lower bound that corresponds to this box
00355         // is too large then decrease the coordinate of the box
00356         if ((coord > 0) && (leftBound (coord, dir) > bound))
00357         {
00358                 sbug << "* Left bound dec cover.\n";
00359                 -- coord;
00360         }
00361 
00362         // if the box to the left overlaps this bound then take that box
00363         if ((coord > 0) && (rightBound (coord - 1, dir) > bound))
00364         {
00365                 sbug << "* Left bound dec overlap.\n";
00366                 -- coord;
00367         }
00368 
00369         return coord;
00370 } /* tCoverBoxes::leftCoord */
00371 
00372 template <class NumType>
00373 inline typename tCoverBoxes<NumType>::CoordType
00374         tCoverBoxes<NumType>::rightCoord
00375         (const NumType &bound, int dir) const
00376 {
00377         // make sure that the right end is within the region
00378         if (bound > rightCorner [dir])
00379                 throw "Trying to cover a box that is too large (right).";
00380 
00381         // return the right corner of the region if this is the case
00382         if (bound == rightCorner [dir])
00383                 return partCounts [dir];
00384 
00385         // compute a candidate for the right corner coordinate
00386         NumType offset = bound - leftCorner [dir] - overlap [dir];
00387         int coord = (offset > 0) ? (static_cast<CoordType>
00388                 (offset * partCounts [dir] / boxWidths [dir]) + 1) : 1;
00389         if (coord >= partCounts [dir])
00390                 return partCounts [dir];
00391 
00392         // if the bound could be improved then do it
00393         if ((coord > 1) && (rightBound (coord - 2, dir) >= bound))
00394         {
00395                 sbug << "* Right bound inc improve.\n";
00396                 -- coord;
00397         }
00398 
00399         // if the actual right bound of this box is below the bound
00400         // then take the next box to the right
00401         if ((coord < partCounts [dir]) &&
00402                 (rightBound (coord - 1, dir) < bound))
00403         {
00404                 sbug << "* Right bound inc cover.\n";
00405                 ++ coord;
00406         }
00407 
00408         // if the box to the right overlaps this bound then take that box
00409         if ((coord < partCounts [dir]) &&
00410                 (leftBound (coord, dir) < bound))
00411         {
00412                 sbug << "* Right bound inc overlap.\n";
00413                 ++ coord;
00414         }
00415 
00416         return coord;
00417 } /* tCoverBoxes::rightCoord */
00418 
00419 template <class NumType>
00420 template <class ResultType>
00421 inline void tCoverBoxes<NumType>::get (const int n,
00422                 ResultType *leftBounds, ResultType *rightBounds) const
00423 {
00424         // extract the rounding class to shorten the notation
00425         typedef tRounding<ResultType> rnd;
00426 
00427         // make sure that the box number is within the correct range
00428         if ((n < 0) || (n >= boxes. size ()))
00429                 throw "Wrong cover element requested.";
00430 
00431         // extract the integer coordinates of the requested box
00432         CoordType *boxCoord = buffer;
00433         boxes [n]. coord (boxCoord);
00434 
00435         // compute the real coordinates of the box
00436         for (int i = 0; i < spaceDim; ++ i)
00437         {
00438                 leftBounds [i] = leftBound (boxCoord [i], i);
00439                 rightBounds [i] = rightBound (boxCoord [i], i);
00440         }
00441         return;
00442 } /* tCoverBoxes::get */
00443 
00444 template <class NumType>
00445 template <class ResultType>
00446 inline void tCoverBoxes<NumType>::getLeftCorner (ResultType *leftCorner)
00447         const
00448 {
00449         for (int i = 0; i < spaceDim; ++ i)
00450                 leftCorner [i] = this -> leftCorner [i];
00451         return;
00452 } /* tCoverBoxes::getLeftCorner */
00453 
00454 template <class NumType>
00455 template <class ResultType>
00456 inline void tCoverBoxes<NumType>::getBoxWidths (ResultType *boxWidths)
00457         const
00458 {
00459         for (int i = 0; i < spaceDim; ++ i)
00460                 boxWidths [i] = this -> boxWidths [i];
00461         return;
00462 } /* tCoverBoxes::getBoxWidths */
00463 
00464 template <class NumType>
00465 template <class InputType, class BoxNumbers>
00466 inline void tCoverBoxes<NumType>::cover (const InputType *leftBounds,
00467         const InputType *rightBounds, BoxNumbers &boxNumbers,
00468         NumType *diameter2)
00469 {
00470         // prepare arrays of box coordinates
00471         CoordType *left = buffer;
00472         CoordType *right = buffer + spaceDim;
00473 
00474         // compute the lower left corner of the integer box coordinates
00475         for (int i = 0; i < spaceDim; ++ i)
00476         {
00477                 left [i] = leftCoord (leftBounds [i], i);
00478                 right [i] = rightCoord (rightBounds [i], i);
00479         }
00480 
00481         // compute an upper bound for the diameter of the covering set
00482         if (diameter2)
00483         {
00484                 NumType squares = 0;
00485                 for (int i = 0; i < spaceDim; ++ i)
00486                 {
00487                         NumType diff = tRounding<NumType>::sub_up
00488                                 (rightBound (right [i], i),
00489                                 leftBound (left [i], i));
00490                         NumType diff2 = tRounding<NumType>::mul_up
00491                                 (diff, diff);
00492                         squares = tRounding<NumType>::add_up
00493                                 (squares, diff2);
00494                 }
00495                 //using std::sqrt;
00496                 *diameter2 = squares;
00497         }
00498 
00499         // add all the boxes in the computed range to the set
00500         chomp::homology::tRectangle<CoordType> r (left, right, spaceDim);
00501         const CoordType *c;
00502         while ((c = r. get ()) != 0)
00503         {
00504                 CubeType q (c, spaceDim);
00505                 int n = boxes. getnumber (q);
00506                 if (n >= 0)
00507                         boxNumbers. add (n);
00508                 else
00509                 {
00510                         boxNumbers. add (boxes. size ());
00511                         boxes. add (q);
00512                 }
00513         }
00514 
00515         return;
00516 } /* tCoverBoxes::cover */
00517 
00518 template <class NumType>
00519 template <class InputType>
00520 inline void tCoverBoxes<NumType>::cover (const InputType *x)
00521 {
00522         // extract the rounding class to shorten the notation
00523         typedef tRounding<NumType> rnd;
00524 
00525         // prepare a possibly small open interval that contains the point
00526         NumType *xLeft = new NumType [spaceDim];
00527         NumType *xRight = new NumType [spaceDim];
00528         NumType min_number = rnd::min_number ();
00529         for (int i = 0; i < spaceDim; ++ i)
00530         {
00531                 xLeft [i] = rnd::add_down (x [i], min_number);
00532                 xRight [i] = rnd::add_up (x [i], min_number);
00533         }
00534 
00535         // cover this open interval
00536         DummyBoxNumbers d;
00537         this -> cover (xLeft, xRight, d);
00538 
00539         // clean up the memory and return
00540         delete [] xRight;
00541         delete [] xLeft;
00542         return;
00543 } /* tCoverBoxes::cover */
00544 
00545 template <class NumType>
00546 inline std::ostream &operator << (std::ostream &out,
00547         const tCoverBoxes<NumType> &cover)
00548 {
00549         int dim = cover. dim ();
00550         NumType *buffer = new NumType [dim << 1];
00551         NumType *leftBound = buffer;
00552         NumType *rightBound = buffer + dim;
00553         for (int n = 0; n < cover. size (); ++ n)
00554         {
00555                 cover. get (n, leftBound, rightBound);
00556                 for (int i = 0; i < dim; ++ i)
00557                 {
00558                         out << (i ? " x [" : "[") << leftBound [i] <<
00559                                 "," << rightBound [i] << "]";
00560                 }
00561                 out << "\n";
00562         }
00563         delete [] buffer;
00564         return out;
00565 } /* operator << */
00566 
00567 
00568 #endif // _FINRESDYN_COVBOXES_H_
00569 

Generated on Mon Apr 12 15:09:57 2010 for The Finite Resolution Dynamics Software by  doxygen 1.5.3