The Finite Resolution Dynamics Software
covboxes.h
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////////////
2 ///
3 /// @file covboxes.h
4 ///
5 /// A box cover type.
6 /// This file contains the definition of a class that represents
7 /// a cover of a bounded rectangular region in R^n by means of open boxes.
8 /// The class includes a method for computing a cover of any open box
9 /// or a point by means of the boxes in this class.
10 ///
11 /// @author Pawel Pilarczyk
12 ///
13 /////////////////////////////////////////////////////////////////////////////
14 
15 // Copyright (C) 1997-2010 by Pawel Pilarczyk.
16 //
17 // This file is part of my research software package. This is free software;
18 // you can redistribute it and/or modify it under the terms of the GNU
19 // General Public License as published by the Free Software Foundation;
20 // either version 2 of the License, or (at your option) any later version.
21 //
22 // This software is distributed in the hope that it will be useful,
23 // but WITHOUT ANY WARRANTY; without even the implied warranty of
24 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 // GNU General Public License for more details.
26 //
27 // You should have received a copy of the GNU General Public License along
28 // with this software; see the file "license.txt". If not, write to the
29 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
30 // MA 02111-1307, USA.
31 
32 // Started on March 13, 2009. Last revision: June 18, 2009.
33 
34 
35 #ifndef _FINRESDYN_COVBOXES_H_
36 #define _FINRESDYN_COVBOXES_H_
37 
38 
39 // include some standard C++ header files
40 #include <vector>
41 #include <cmath>
42 
43 // include some header files from the CHomP library
44 #include "chomp/struct/hashsets.h"
45 #include "chomp/cubes/pointset.h"
46 #include "chomp/cubes/cube.h"
47 
48 // include local header files
49 #include "rounding.h"
50 #include "streams.h"
51 
52 
53 // --------------------------------------------------
54 // --------------- dummy box numbers ----------------
55 // --------------------------------------------------
56 
57 /// A dummy class for adding box numbers.
59 {
60 public:
61  /// Forgets the box number.
62  void add (int) {};
63 
64 }; /* class DummyBoxNumbers */
65 
66 
67 // --------------------------------------------------
68 // ------------------- box cover --------------------
69 // --------------------------------------------------
70 
71 /// A cover of a subset in R^n consisting of open boxes.
72 template <class NumType>
74 {
75 public:
76  /// The type of numbers in the Henon map.
77  typedef NumType NumberType;
78 
79  /// The constructor of an open cover object.
80  tCoverBoxes (const int spaceDim, const NumType *leftCorner,
81  const NumType *boxWidths, const int *partCounts,
82  const NumType *overlap = 0);
83 
84  /// The destructor of an open cover object.
85  ~tCoverBoxes ();
86 
87  /// Returns the dimension of the phase space.
88  int dim () const;
89 
90  /// Returns the number of boxes in the cover.
91  int size () const;
92 
93  /// Returns the coordinates of the given box.
94  /// Throws an exception if the box with this number is undefined.
95  template <class ResultType>
96  void get (const int n,
97  ResultType *leftBounds, ResultType *rightBounds) const;
98 
99  /// Returns the coordinates of the left corner of the range box.
100  template <class ResultType>
101  void getLeftCorner (ResultType *leftCorner) const;
102 
103  /// Returns the width of the range box in each direction.
104  template <class ResultType>
105  void getBoxWidths (ResultType *boxWidths) const;
106 
107  /// Covers the given box and adds numbers of all the boxes
108  /// in the cover to a list using the provided class object
109  /// with its method "add". Adds boxes necessary to cover
110  /// the rectangle to the cover if they are not there yet.
111  /// Throws an exception if the predefined bounds of the covered
112  /// rectangular box have been exceeded.
113  /// If requested, comptues a rigorous upper bound for the square
114  /// of the diameter of the cover.
115  template <class InputType, class BoxNumbers>
116  void cover (const InputType *leftBounds,
117  const InputType *rightBounds, BoxNumbers &boxNumbers,
118  NumType *diameter2 = 0);
119 
120  /// Covers a given point with open boxes.
121  template <class InputType>
122  void cover (const InputType *x);
123 
124  /// Forgets the cover elements.
125  void forget ();
126 
127 private:
128  /// The dimension of the space.
129  int spaceDim;
130 
131  /// The lower left corner of the covered rectangle.
132  NumType *leftCorner;
133 
134  /// The widths of the covered rectangle in all the directions.
135  NumType *boxWidths;
136 
137  /// The upper right corner of the covered rectangle.
138  NumType *rightCorner;
139 
140  /// The numbers of parts into which the box is subdivided
141  /// in each direction.
143 
144  /// The minimal overlap width.
145  NumType *overlap;
146 
147  /// The type of integer coordinates for boxes that represent
148  /// cover elements.
149  typedef int CoordType;
150 
151  /// A temporary buffer for the coordinates of two cubes.
152  CoordType *buffer;
153 
154  /// The type of a cube that represents a cover element.
155  typedef chomp::homology::tCubeBase<CoordType> CubeType;
156 
157  /// The set of boxes in the cover.
158  chomp::homology::hashedset<CubeType> boxes;
159 
160  /// Computes the real left coordinate in the given direction
161  /// of a box represented by integer coordinates.
162  NumType leftBound (int coord, int dir) const;
163 
164  /// Computes the real right coordinate in the given direction
165  /// of a box represented by integer coordinates.
166  NumType rightBound (int coord, int dir) const;
167 
168  /// Computes the left coordinate in the given direction
169  /// of the leftmost box to cover the given real coordinate.
170  CoordType leftCoord (const NumType &bound, int dir) const;
171 
172  /// Computes the right coordinate in the given direction
173  /// of the rightmost box to cover the given real coordinate.
174  CoordType rightCoord (const NumType &bound, int dir) const;
175 
176  /// The copy constructor should not be used.
178 
179  /// The assignment operator should not be used.
180  tCoverBoxes<NumType> &operator = (const tCoverBoxes<NumType> &);
181 
182 }; /* class tCoverBoxes */
183 
184 // --------------------------------------------------
185 
186 template <class NumType>
187 inline tCoverBoxes<NumType>::tCoverBoxes (const int spaceDim,
188  const NumType *leftCorner, const NumType *boxWidths,
189  const int *partCounts, const NumType *overlap)
190 {
191  // make sure the space dimension is within the correct range
192  if ((spaceDim <= 0) || (spaceDim > 100000))
193  throw "Wrong space dimension for a box open cover.";
194  this -> spaceDim = spaceDim;
195 
196  // verify the data and throw an exception if necessary
197  for (int i = 0; i < spaceDim; ++ i)
198  {
199  if (boxWidths [i] <= 0)
200  throw "Trying to use a non-positive box width.";
201  if (partCounts [i] <= 0)
202  throw "Trying to use a non-positive no. of parts.";
203  if (overlap && (overlap [i] <= 0))
204  throw "Trying to use a too small overlap.";
205  if (overlap && (2.00001 * overlap [i] >=
206  boxWidths [i] / partCounts [i]))
207  {
208  throw "Trying to use too large overlap.";
209  }
210  }
211 
212  // copy the lower left corner of the covered area
213  this -> leftCorner = new NumType [spaceDim];
214  for (int i = 0; i < spaceDim; ++ i)
215  this -> leftCorner [i] = leftCorner [i];
216 
217  // copy the widths of the covered area in each direction
218  this -> boxWidths = new NumType [spaceDim];
219  for (int i = 0; i < spaceDim; ++ i)
220  this -> boxWidths [i] = boxWidths [i];
221 
222  // compute an upper bound for the region
223  this -> rightCorner = new NumType [spaceDim];
224  for (int i = 0; i < spaceDim; ++ i)
225  {
226  this -> rightCorner [i] = tRounding<NumberType>::add_up
227  (this -> leftCorner [i], this -> boxWidths [i]);
228  }
229 
230  // copy the number of parts in each direction
231  this -> partCounts = new int [spaceDim];
232  for (int i = 0; i < spaceDim; ++ i)
233  this -> partCounts [i] = partCounts [i];
234 
235  // copy or create the overlap size in each direction
236  this -> overlap = new NumType [spaceDim];
237  if (!overlap)
238  {
239  const NumType min_number =
241  for (int i = 0; i < spaceDim; ++ i)
242  this -> overlap [i] = min_number;
243  }
244  else
245  {
246  for (int i = 0; i < spaceDim; ++ i)
247  this -> overlap [i] = overlap [i];
248  }
249 
250  // allocate a buffer for temporary point coordinates
251  this -> buffer = new CoordType [2 * spaceDim];
252 
253  return;
254 } /* tCoverBoxes::tCoverBoxes */
255 
256 template <class NumType>
258 {
259  throw "Trying to use the copy constructor for an open cover.";
260  return;
261 } /* tCoverBoxes::tCoverBoxes */
262 
263 template <class NumType>
266 {
267  throw "Trying to use the assignment operator for an open cover.";
268  return *this;
269 } /* tCoverBoxes::operator = */
270 
271 template <class NumType>
273 {
274  delete [] leftCorner;
275  delete [] boxWidths;
276  delete [] rightCorner;
277  delete [] partCounts;
278  delete [] overlap;
279  delete [] buffer;
280  return;
281 } /* tCoverBoxes::~tCoverBoxes */
282 
283 template <class NumType>
284 inline int tCoverBoxes<NumType>::dim () const
285 {
286  return spaceDim;
287 } /* tCoverBoxes::dim */
288 
289 template <class NumType>
290 inline int tCoverBoxes<NumType>::size () const
291 {
292  return boxes. size ();
293 } /* tCoverBoxes::size */
294 
295 template <class NumType>
297 {
298  chomp::homology::hashedset<CubeType> empty;
299  boxes = empty;
300  return;
301 } /* tCoverBoxes::forget */
302 
303 template <class NumType>
304 inline NumType tCoverBoxes<NumType>::leftBound (int coord, int dir) const
305 {
306  if (coord == 0)
307  return leftCorner [dir];
308  typedef tRounding<NumType> rnd;
309  NumType left1 = rnd::mul_down (boxWidths [dir], coord);
310  NumType left2 = rnd::div_down (left1, partCounts [dir]);
311  return rnd::add_down (leftCorner [dir], left2);
312 } /* tCoverBoxes::leftBound */
313 
314 template <class NumType>
315 inline NumType tCoverBoxes<NumType>::rightBound (int coord, int dir) const
316 {
317  typedef tRounding<NumType> rnd;
318  if (coord == partCounts [dir])
319  return rnd::add_up (leftCorner [dir], boxWidths [dir]);
320  NumType right1 = rnd::mul_up (boxWidths [dir], coord + 1);
321  NumType right2 = rnd::div_up (right1, partCounts [dir]);
322  NumType right3 = rnd::add_up (right2, overlap [dir]);
323  return rnd::add_up (leftCorner [dir], right3);
324 } /* tCoverBoxes::rightBound */
325 
326 template <class NumType>
327 inline typename tCoverBoxes<NumType>::CoordType
329  (const NumType &bound, int dir) const
330 {
331  // make sure that the left end is within the region
332  if (bound < leftCorner [dir])
333  throw "Trying to cover a box that is too large (left).";
334 
335  // return the left corner of the region if this is the case
336  if (bound == leftCorner [dir])
337  return 0;
338 
339  // compute a candidate for the left corner coordinate
340  NumType offset = bound - leftCorner [dir];
341  int coord = static_cast<CoordType>
342  (offset * partCounts [dir] / boxWidths [dir]);
343  if (coord < 0)
344  return 0;
345 
346  // verify if the bound could be improved
347  if ((coord + 1 < partCounts [dir]) &&
348  (leftBound (coord + 1, dir) <= bound))
349  {
350  sbug << "* Left bound inc improve.\n";
351  ++ coord;
352  }
353 
354  // if the real lower bound that corresponds to this box
355  // is too large then decrease the coordinate of the box
356  if ((coord > 0) && (leftBound (coord, dir) > bound))
357  {
358  sbug << "* Left bound dec cover.\n";
359  -- coord;
360  }
361 
362  // if the box to the left overlaps this bound then take that box
363  if ((coord > 0) && (rightBound (coord - 1, dir) > bound))
364  {
365  sbug << "* Left bound dec overlap.\n";
366  -- coord;
367  }
368 
369  return coord;
370 } /* tCoverBoxes::leftCoord */
371 
372 template <class NumType>
373 inline typename tCoverBoxes<NumType>::CoordType
375  (const NumType &bound, int dir) const
376 {
377  // make sure that the right end is within the region
378  if (bound > rightCorner [dir])
379  throw "Trying to cover a box that is too large (right).";
380 
381  // return the right corner of the region if this is the case
382  if (bound == rightCorner [dir])
383  return partCounts [dir];
384 
385  // compute a candidate for the right corner coordinate
386  NumType offset = bound - leftCorner [dir] - overlap [dir];
387  int coord = (offset > 0) ? (static_cast<CoordType>
388  (offset * partCounts [dir] / boxWidths [dir]) + 1) : 1;
389  if (coord >= partCounts [dir])
390  return partCounts [dir];
391 
392  // if the bound could be improved then do it
393  if ((coord > 1) && (rightBound (coord - 2, dir) >= bound))
394  {
395  sbug << "* Right bound inc improve.\n";
396  -- coord;
397  }
398 
399  // if the actual right bound of this box is below the bound
400  // then take the next box to the right
401  if ((coord < partCounts [dir]) &&
402  (rightBound (coord - 1, dir) < bound))
403  {
404  sbug << "* Right bound inc cover.\n";
405  ++ coord;
406  }
407 
408  // if the box to the right overlaps this bound then take that box
409  if ((coord < partCounts [dir]) &&
410  (leftBound (coord, dir) < bound))
411  {
412  sbug << "* Right bound inc overlap.\n";
413  ++ coord;
414  }
415 
416  return coord;
417 } /* tCoverBoxes::rightCoord */
418 
419 template <class NumType>
420 template <class ResultType>
421 inline void tCoverBoxes<NumType>::get (const int n,
422  ResultType *leftBounds, ResultType *rightBounds) const
423 {
424  // extract the rounding class to shorten the notation
425  typedef tRounding<ResultType> rnd;
426 
427  // make sure that the box number is within the correct range
428  if ((n < 0) || (n >= boxes. size ()))
429  throw "Wrong cover element requested.";
430 
431  // extract the integer coordinates of the requested box
432  CoordType *boxCoord = buffer;
433  boxes [n]. coord (boxCoord);
434 
435  // compute the real coordinates of the box
436  for (int i = 0; i < spaceDim; ++ i)
437  {
438  leftBounds [i] = leftBound (boxCoord [i], i);
439  rightBounds [i] = rightBound (boxCoord [i], i);
440  }
441  return;
442 } /* tCoverBoxes::get */
443 
444 template <class NumType>
445 template <class ResultType>
446 inline void tCoverBoxes<NumType>::getLeftCorner (ResultType *leftCorner)
447  const
448 {
449  for (int i = 0; i < spaceDim; ++ i)
450  leftCorner [i] = this -> leftCorner [i];
451  return;
452 } /* tCoverBoxes::getLeftCorner */
453 
454 template <class NumType>
455 template <class ResultType>
456 inline void tCoverBoxes<NumType>::getBoxWidths (ResultType *boxWidths)
457  const
458 {
459  for (int i = 0; i < spaceDim; ++ i)
460  boxWidths [i] = this -> boxWidths [i];
461  return;
462 } /* tCoverBoxes::getBoxWidths */
463 
464 template <class NumType>
465 template <class InputType, class BoxNumbers>
466 inline void tCoverBoxes<NumType>::cover (const InputType *leftBounds,
467  const InputType *rightBounds, BoxNumbers &boxNumbers,
468  NumType *diameter2)
469 {
470  // prepare arrays of box coordinates
471  CoordType *left = buffer;
472  CoordType *right = buffer + spaceDim;
473 
474  // compute the lower left corner of the integer box coordinates
475  for (int i = 0; i < spaceDim; ++ i)
476  {
477  left [i] = leftCoord (leftBounds [i], i);
478  right [i] = rightCoord (rightBounds [i], i);
479  }
480 
481  // compute an upper bound for the diameter of the covering set
482  if (diameter2)
483  {
484  NumType squares = 0;
485  for (int i = 0; i < spaceDim; ++ i)
486  {
487  NumType diff = tRounding<NumType>::sub_up
488  (rightBound (right [i], i),
489  leftBound (left [i], i));
490  NumType diff2 = tRounding<NumType>::mul_up
491  (diff, diff);
493  (squares, diff2);
494  }
495  //using std::sqrt;
496  *diameter2 = squares;
497  }
498 
499  // add all the boxes in the computed range to the set
500  chomp::homology::tRectangle<CoordType> r (left, right, spaceDim);
501  const CoordType *c;
502  while ((c = r. get ()) != 0)
503  {
504  CubeType q (c, spaceDim);
505  int n = boxes. getnumber (q);
506  if (n >= 0)
507  boxNumbers. add (n);
508  else
509  {
510  boxNumbers. add (boxes. size ());
511  boxes. add (q);
512  }
513  }
514 
515  return;
516 } /* tCoverBoxes::cover */
517 
518 template <class NumType>
519 template <class InputType>
520 inline void tCoverBoxes<NumType>::cover (const InputType *x)
521 {
522  // extract the rounding class to shorten the notation
523  typedef tRounding<NumType> rnd;
524 
525  // prepare a possibly small open interval that contains the point
526  NumType *xLeft = new NumType [spaceDim];
527  NumType *xRight = new NumType [spaceDim];
528  NumType min_number = rnd::min_number ();
529  for (int i = 0; i < spaceDim; ++ i)
530  {
531  xLeft [i] = rnd::add_down (x [i], min_number);
532  xRight [i] = rnd::add_up (x [i], min_number);
533  }
534 
535  // cover this open interval
536  DummyBoxNumbers d;
537  this -> cover (xLeft, xRight, d);
538 
539  // clean up the memory and return
540  delete [] xRight;
541  delete [] xLeft;
542  return;
543 } /* tCoverBoxes::cover */
544 
545 template <class NumType>
546 inline std::ostream &operator << (std::ostream &out,
547  const tCoverBoxes<NumType> &cover)
548 {
549  int dim = cover. dim ();
550  NumType *buffer = new NumType [dim << 1];
551  NumType *leftBound = buffer;
552  NumType *rightBound = buffer + dim;
553  for (int n = 0; n < cover. size (); ++ n)
554  {
555  cover. get (n, leftBound, rightBound);
556  for (int i = 0; i < dim; ++ i)
557  {
558  out << (i ? " x [" : "[") << leftBound [i] <<
559  "," << rightBound [i] << "]";
560  }
561  out << "\n";
562  }
563  delete [] buffer;
564  return out;
565 } /* operator << */
566 
567 
568 #endif // _FINRESDYN_COVBOXES_H_
569 
void cover(const InputType *leftBounds, const InputType *rightBounds, BoxNumbers &boxNumbers, NumType *diameter2=0)
Covers the given box and adds numbers of all the boxes in the cover to a list using the provided clas...
Definition: covboxes.h:466
int dim() const
Returns the dimension of the phase space.
Definition: covboxes.h:284
Various output streams for the program.
void get(const int n, ResultType *leftBounds, ResultType *rightBounds) const
Returns the coordinates of the given box.
Definition: covboxes.h:421
NumType * overlap
The minimal overlap width.
Definition: covboxes.h:145
int CoordType
The type of integer coordinates for boxes that represent cover elements.
Definition: covboxes.h:149
Rigorous rounding of arithmetic operations.
A cover of a subset in R^n consisting of open boxes.
Definition: covboxes.h:73
tCoverBoxes(const int spaceDim, const NumType *leftCorner, const NumType *boxWidths, const int *partCounts, const NumType *overlap=0)
The constructor of an open cover object.
Definition: covboxes.h:187
NumType * boxWidths
The widths of the covered rectangle in all the directions.
Definition: covboxes.h:135
NumType NumberType
The type of numbers in the Henon map.
Definition: covboxes.h:77
A dummy class for adding box numbers.
Definition: covboxes.h:58
~tCoverBoxes()
The destructor of an open cover object.
Definition: covboxes.h:272
CoordType leftCoord(const NumType &bound, int dir) const
Computes the left coordinate in the given direction of the leftmost box to cover the given real coord...
Definition: covboxes.h:329
chomp::homology::tCubeBase< CoordType > CubeType
The type of a cube that represents a cover element.
Definition: covboxes.h:155
A class for rounding operations which uses the BOOST library.
Definition: rounding.h:48
void forget()
Forgets the cover elements.
Definition: covboxes.h:296
chomp::homology::hashedset< CubeType > boxes
The set of boxes in the cover.
Definition: covboxes.h:158
int spaceDim
The dimension of the space.
Definition: covboxes.h:129
int size() const
Returns the number of boxes in the cover.
Definition: covboxes.h:290
NumType leftBound(int coord, int dir) const
Computes the real left coordinate in the given direction of a box represented by integer coordinates...
Definition: covboxes.h:304
NumType * rightCorner
The upper right corner of the covered rectangle.
Definition: covboxes.h:138
static NumType min_number()
The smallest positive representable number.
NumType diameter2(const int dim, const NumType *leftBounds, const NumType *rightBounds)
Computes an upper bound for the square of the diameter of a given box.
Definition: attractor.h:78
void add(int)
Forgets the box number.
Definition: covboxes.h:62
void getLeftCorner(ResultType *leftCorner) const
Returns the coordinates of the left corner of the range box.
Definition: covboxes.h:446
void getBoxWidths(ResultType *boxWidths) const
Returns the width of the range box in each direction.
Definition: covboxes.h:456
std::ostream & operator<<(std::ostream &out, const tCoverBoxes< NumType > &cover)
Definition: covboxes.h:546
NumType * leftCorner
The lower left corner of the covered rectangle.
Definition: covboxes.h:132
NumType rightBound(int coord, int dir) const
Computes the real right coordinate in the given direction of a box represented by integer coordinates...
Definition: covboxes.h:315
int * partCounts
The numbers of parts into which the box is subdivided in each direction.
Definition: covboxes.h:142
CoordType * buffer
A temporary buffer for the coordinates of two cubes.
Definition: covboxes.h:152
CoordType rightCoord(const NumType &bound, int dir) const
Computes the right coordinate in the given direction of the rightmost box to cover the given real coo...
Definition: covboxes.h:375