The Conley-Morse Graphs Software
utils.h
Go to the documentation of this file.
1/////////////////////////////////////////////////////////////////////////////
2///
3/// @file utils.h
4///
5/// Utilites and helper functions.
6/// This file contains the definitions of various little useful utility
7/// procedures for the Conley-Morse graphs computation software.
8///
9/// @author Pawel Pilarczyk
10///
11/////////////////////////////////////////////////////////////////////////////
12
13// Copyright (C) 1997-2014 by Pawel Pilarczyk.
14//
15// This file is part of my research software package. This is free software:
16// you can redistribute it and/or modify it under the terms of the GNU
17// General Public License as published by the Free Software Foundation,
18// either version 3 of the License, or (at your option) any later version.
19//
20// This software is distributed in the hope that it will be useful,
21// but WITHOUT ANY WARRANTY; without even the implied warranty of
22// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23// GNU General Public License for more details.
24//
25// You should have received a copy of the GNU General Public License
26// along with this software; see the file "license.txt". If not,
27// please, see <https://www.gnu.org/licenses/>.
28
29// Started on February 11, 2008. Last revision: March 16, 2016.
30
31
32#ifndef _CMGRAPHS_UTILS_H_
33#define _CMGRAPHS_UTILS_H_
34
35
36// include some standard C++ header files
37#include <string>
38#include <sstream>
39#include <fstream>
40#include <iostream>
41#include <ios>
42#include <iomanip>
43#include <cmath>
44#include <algorithm>
45#include <vector>
46#include <new>
47
48// include selected header files from the CHomP library
49#include "chomp/system/config.h"
50#include "chomp/system/textfile.h"
51#include "chomp/cubes/cube.h"
52#include "chomp/multiwork/mw.h"
53#include "chomp/struct/autoarray.h"
54//#include "chomp/struct/digraph.h"
55
56// include local header files
57#include "config.h"
58#include "typedefs.h"
59//#include "typeintv.h"
60//#include "typedyns.h"
61//#include "eigenval.h"
62
63
64// --------------------------------------------------
65// ----------------- file existence -----------------
66// --------------------------------------------------
67
68/// Returns 'true' iff the given file exists and it is allowed to read it.
69inline bool fileExists (const char *filename)
70{
71 std::ifstream in (filename);
72 return !!in;
73} /* fileExists */
74
75
76// --------------------------------------------------
77// ---------- file name without extension -----------
78// --------------------------------------------------
79
80/// Returns the file name without its extension if any.
81/// If the file didn't have any extension, returns the original file name.
82inline std::string fileNameWithoutExt (const std::string &fileName)
83{
84 unsigned int pos = fileName. size ();
85 if (!pos)
86 return fileName;
87 while (1)
88 {
89 int ch = fileName [-- pos];
90 if ((pos == 0) || (ch == '/') || (ch == '\\') || (ch == ':'))
91 return fileName;
92 if (ch == '.')
93 return std::string (fileName, 0, pos);
94 }
95} /* fileNameWithoutExt */
96
97
98// --------------------------------------------------
99// ----------- local value of a variable ------------
100// --------------------------------------------------
101
102/// Initializes the given variable with the value provided
103/// and restores the previous value at the end of the current block.
104/// The restoration of the previous value takes place upon destruction
105/// of this object. This action effects in a local value of a given variable
106/// valid in the current block only (e.g., until 'return').
107template <class T>
109{
110public:
111 /// The only allowed constructor.
112 local_value (T &_variable, const T &_value):
113 variable (_variable), previous_value (_variable)
114 {variable = _value; return;}
115
116 /// The destructor which restores the original value of the variable.
118
119private:
120 /// A reference of the variable.
122
123 /// The original value of the variable.
125
126}; /* class local_value */
127
128
129// --------------------------------------------------
130// ---------------- parameter cubes -----------------
131// --------------------------------------------------
132
133/// Verifies whether the given box is located at the boundary
134/// of the small region which is either not at the boundary
135/// of the large region, or is adjacent to some other similar region.
136template <class intType1, class intType2, class intType3>
137inline bool internalBoundaryPoint (const intType1 *coord,
138 const intType2 *left, const intType2 *right,
139 const intType3 *limit, int dim)
140{
141 for (int i = 0; i < dim; ++ i)
142 {
143 if ((coord [i] == left [i]) && (left [i] != 0))
144 {
145 return true;
146 }
147 else if ((coord [i] == right [i] - 1) &&
148 (right [i] != limit [i]))
149 {
150 return true;
151 }
152 }
153 return false;
154} /* internalBoundaryPoint */
155
156/// Computes the real coordinates of the parameter cube
157/// which corresponds to the given box.
158/// Uses the globally defined ranges.
159template <class intType>
160void computeParam (const intType *curCoord,
161 double *leftMapParam, double *rightMapParam)
162{
163 for (int i = 0; i < paramCount; ++ i)
164 {
165 leftMapParam [i] = paramLeft [i];
166 rightMapParam [i] = paramRight [i];
167 for (int j = 0; j < paramDim; ++ j)
168 {
169 if (i != paramSelect [j])
170 continue;
171#ifndef NONLINEAR_PARAMETERS
172 double paramWidth = paramRight [i] - paramLeft [i];
173#endif
174 if (curCoord [j] > 0)
175 {
176#ifdef NONLINEAR_PARAMETERS
177 leftMapParam [i] = nonlinearParameter
178 (j, curCoord [j]);
179#else
180 leftMapParam [i] = paramLeft [i] +
181 curCoord [j] * paramWidth /
182 paramSubdiv [j];
183#endif
184 }
185#ifdef CONFIG_PARAMPOINTS
186 rightMapParam [i] = leftMapParam [i];
187#else
188 if (curCoord [j] < paramSubdiv [j] - 1)
189 {
190#ifdef NONLINEAR_PARAMETERS
191 rightMapParam [i] = nonlinearParameter
192 (j, curCoord [j] + 1);
193#else
194 rightMapParam [i] = paramLeft [i] +
195 (curCoord [j] + 1) * paramWidth /
196 paramSubdiv [j];
197#endif
198 }
199#endif
200 break;
201 }
202 }
203 return;
204} /* computeParam */
205
206/// Determines heuristically an optimal subdivision of a large parameter
207/// region into the given minimal number of smaller regions.
208/// Fills in the provided array of vectors with the division coordinates.
209/// Allocates a rectangle for iterating this region and returns its pointer.
210/// Note: The rectangle is built upon the two arrays provided; they should
211/// not be deleted or otherwise the pointers stored within the rectangle
212/// become invalid.
213inline parRect *subRectangles (parCoord *zeroIter, parCoord *maxIter,
214 std::vector<parCoord> *subCoords, int minCount)
215{
216 using chomp::homology::sbug;
217 const bool debug = true;
218
219 // use a fixed distance between boxes if requested to
220 int boxStep = 0;
221
222 // make a correction to the minimal requested number of parts
223 if (minCount == 0)
224 minCount = -4;
225 if (minCount < 0)
226 {
227 boxStep = -minCount;
228 minCount = 0;
229 }
230
231 // prepare the increasing order of all the sides
232 // of the full parameter rectangular area
233 bool taken [paramDim];
234 for (int i = 0; i < paramDim; ++ i)
235 taken [i] = false;
236 int increasing [paramDim];
237 for (int i = 0; i < paramDim; ++ i)
238 {
239 // find an index with the minimal value but not yet taken
240 int minIndex = -1;
241 for (int j = 0; j < paramDim; ++ j)
242 {
243 if (taken [j])
244 continue;
245 if ((minIndex < 0) ||
246 (paramSubdiv [j] < paramSubdiv [minIndex]))
247 {
248 minIndex = j;
249 }
250 }
251
252 // take this index
253 increasing [i] = minIndex;
254 taken [minIndex] = true;
255 }
256
257 // compute the recommended maximal volume of each rectangular region
258 double volume = 0;
259 if (minCount > 0)
260 {
261 volume = 1;
262 for (int i = 0; i < paramDim; ++ i)
263 volume *= paramSubdiv [i];
264 volume /= minCount;
265 }
266
267 // show debugging information if necessary
268 if (debug)
269 {
270 sbug << "Computing subdivisions - detailed information:\n";
271 sbug << " boxStep = " << boxStep << ", minCount = " <<
272 minCount << ", volume = " << volume << "\n";
273 }
274
275 // prepare the number of parts in each direction
276 // and fill in the maximal corner of the rectangle for iterating
277 for (int i = 0; i < paramDim; ++ i)
278 {
279 // determine the recommended side length
280 int index = increasing [i];
281 int localBoxStep = (boxStep < paramSubdiv [index]) ?
282 boxStep : paramSubdiv [index];
283 double side = volume ?
284 (std::exp (std::log (volume) / (paramDim - i))) :
285 (static_cast<double> (paramSubdiv [index]) /
286 ((paramSubdiv [index] + localBoxStep - 1) /
287 localBoxStep));
288 double delta = (volume && (i == paramDim - 1)) ?
289 0.99999 : 0.5;
290 maxIter [index] = static_cast<parCoord>
291 (paramSubdiv [index] / side + delta);
292 if (maxIter [index] > paramSubdiv [index])
293 maxIter [index] = paramSubdiv [index];
294 if (maxIter [index] <= 0)
295 maxIter [index] = 1;
296 if (debug)
297 {
298 sbug << " index " << index << ": remaining vol = " <<
299 volume << ", side = " << side << ", maxIter = " <<
300 maxIter [index] << "\n";
301 }
302
303 // divide the volume by the approximate side length
304 if (volume)
305 {
306 volume /= paramSubdiv [index];
307 volume *= maxIter [index];
308 }
309 // chomp::homology::sbug << " x " << maxIter [index] << "\n";
310 }
311
312 // fill in the array with the subdivision coordinates
313 int minWidth = 0;
314 int maxWidth = 0;
315 for (int i = 0; i < paramDim; ++ i)
316 {
317 if (debug)
318 {
319 sbug << " dir " << i << ":";
320 }
321 subCoords [i]. push_back (0);
322 for (int j = 1; j < maxIter [i]; ++ j)
323 {
324 parCoord coord = static_cast<parCoord>
325 ((static_cast<long> (paramSubdiv [i] +
326 maxIter [i] - 1) * j + maxIter [i] - 1) /
327 maxIter [i] - j);
328 subCoords [i]. push_back (coord);
329 if (debug)
330 {
331 parCoord width = subCoords [i] [j] -
332 subCoords [i] [j - 1] + 1;
333 if ((j == 1) || (width < minWidth))
334 minWidth = width;
335 if ((j == 1) || (maxWidth < width))
336 maxWidth = width;
337 sbug << " " << coord;
338 }
339 }
340 subCoords [i]. push_back (paramSubdiv [i]);
341 if (debug)
342 {
343 parCoord lastWidth = subCoords [i] [maxIter [i]] -
344 subCoords [i] [maxIter [i] - 1];
345 sbug << " " << paramSubdiv [i] << " (width " <<
346 minWidth << "-" << maxWidth << "; " <<
347 lastWidth << ")\n";
348 }
349 }
350
351 // prepare the minimal corner of the rectangle for iterating
352 for (int i = 0; i < paramDim; ++ i)
353 zeroIter [i] = 0;
354
355 // return the rectangle in question
356 return new parRect (zeroIter, maxIter, paramDim);
357} /* subRectangles */
358
359
360// --------------------------------------------------
361// ------ string representation of coordinates ------
362// --------------------------------------------------
363
364/// Returns the number of digits of the given non-negative integer number.
365template <class intType>
366inline int countDigits (intType x)
367{
368 intType tenPower = 10;
369 int digits = 1;
370 while (1)
371 {
372 if (x < tenPower)
373 return digits;
374 intType nextPower = tenPower * 10;
375 if (nextPower < tenPower)
376 return digits;
377 tenPower = nextPower;
378 ++ digits;
379 }
380} /* countDigits */
381
382/// Generates an underscore-separated list of non-negative coordinates
383/// padded with zeros to the same width assuming that their values
384/// are below the given limits.
385template <class intType1, class intType2>
386inline std::string coord2str (const intType1 *coords,
387 const intType2 *maxCoords, int dim)
388{
389 std::ostringstream str;
390 for (int i = 0; i < dim; ++ i)
391 {
392 if (i)
393 str << '_';
394 int maxDigits = countDigits (maxCoords [i] - 1);
395 int digits = countDigits (coords [i]);
396 for (int d = digits; d < maxDigits; ++ d)
397 str << '0';
398 str << coords [i];
399 }
400 return str. str ();
401} /* coord2str */
402
403/// Generates an underscore-separated list of non-negative coordinates.
404template <class intType>
405inline std::string coord2str (const intType *coords, int dim)
406{
407 std::ostringstream str;
408 for (int i = 0; i < dim; ++ i)
409 {
410 if (i)
411 str << '_';
412 str << coords [i];
413 }
414 return str. str ();
415} /* coord2str */
416
417/// Generates an underscore-separated list of non-negative coordinates.
418template <class cubeType>
419inline std::string coord2str (const cubeType &q)
420{
421 using chomp::homology::auto_array;
422
423 // determine the number of coordinates
424 int dim = q. dim ();
425 if (dim <= 0)
426 return std::string ("");
427
428 // prepare an array of coordinates (to be deallocated automatically)
429 typedef typename cubeType::CoordType coordType;
430 auto_array<coordType> coords (new coordType [dim]);
431 q. coord (coords. get ());
432
433 // compute the string representation of the coordinates
434 return coord2str (coords. get (), dim);
435} /* coord2str */
436
437
438// --------------------------------------------------
439// ------------- ranges of coordinates --------------
440// --------------------------------------------------
441
442/// A class whose objects store, update and show coordinate ranges.
444{
445public:
446 /// The default constructor.
447 CoordMinMax ();
448
449 /// The constructor from precomputed values.
450 CoordMinMax (const spcCoord *leftMin, const spcCoord *rightMax);
451
452 /// Returns true if at least one cube was taken for the ranges.
453 bool defined () const;
454
455 /// Updates the coordinate ranges for the given set of cubes.
456 void operator () (const spcCubes &theSet);
457
458// /// Updates the coordinate ranges for the entire Morse decomposition.
459// void operator () (const theMorseDecompositionType &morseDec);
460
461 /// The minimal coordinates.
463
464 /// The strict upper bound for the maximal coordinates.
466
467}; /* class CoordMinMax */
468
470{
471 for (int i = 0; i < spaceDim; ++ i)
472 {
473 coordLeftMin [i] = 1 << finalDepth;
474 coordRightMax [i] = 0;
475 }
476 return;
477} /* CoordMinMax::CoordMinMax */
478
479inline CoordMinMax::CoordMinMax (const spcCoord *leftMin,
480 const spcCoord *rightMax)
481{
482 for (int i = 0; i < spaceDim; ++ i)
483 {
484 coordLeftMin [i] = leftMin [i];
485 coordRightMax [i] = rightMax [i];
486 }
487 return;
488} /* CoordMinMax::CoordMinMax */
489
490inline bool CoordMinMax::defined () const
491{
492 return (coordLeftMin [0] < coordRightMax [0]);
493} /* CoordMinMax::defined */
494
495inline void CoordMinMax::operator () (const spcCubes &theSet)
496{
497 spcCoord coord [spaceDim];
498 int nCubes = theSet. size ();
499 for (int i = 0; i < nCubes; ++ i)
500 {
501 theSet [i]. coord (coord);
502 for (int j = 0; j < spaceDim; ++ j)
503 {
504 if (coordLeftMin [j] > coord [j])
505 coordLeftMin [j] = coord [j];
506 if (coordRightMax [j] <= coord [j])
507 coordRightMax [j] = coord [j] + 1;
508 }
509 }
510 return;
511} /* CoordMinMax::operator () */
512
513//inline void CoordMinMax::operator ()
514// (const theMorseDecompositionType &morseDec)
515//{
516// int nSets = morseDec. count ();
517// for (int n = 0; n < nSets; ++ n)
518// this -> operator () (morseDec [n]);
519// return;
520//} /* CoordMinMax::operator () */
521
522/// Outputs the ranges of coordinates to an output stream.
523/// In case the ranges are undefined, outputs "[unknown]".
524inline std::ostream &operator << (std::ostream &out,
525 const CoordMinMax &range)
526{
527 if (!range. defined ())
528 {
529 out << "[unknown]";
530 return out;
531 }
532 for (int i = 0; i < spaceDim; ++ i)
533 {
534 out << (i ? " x [" : "[") <<
535 range. coordLeftMin [i] << "," <<
536 range. coordRightMax [i] << "]";
537 }
538 return out;
539} /* operator << */
540
541/// Shows the real coordinates of the coordinate range.
542template <class OutStream>
543inline OutStream &showRealCoords (OutStream &out, const CoordMinMax &range)
544{
545 if (!range. defined ())
546 {
547 out << "[unknown]";
548 return out;
549 }
550 const spcCoord spaceResolution (1 << finalDepth);
551 for (int i = 0; i < spaceDim; ++ i)
552 {
553 double rangeMin = range. coordLeftMin [i] * spaceWidth [i] /
554 spaceResolution + spaceOffset [i];
555 double rangeMax = range. coordRightMax [i] * spaceWidth [i] /
556 spaceResolution + spaceOffset [i];
557 out << (i ? " x [" : "[") << rangeMin << "," <<
558 rangeMax << "]";
559 }
560 return out;
561} /* showRealCoords */
562
563/// Verifies if the given set of cubes is contained in the interior
564/// of the phase space box.
565inline bool checkIsolation (const spcCubes &theSet, int depth)
566{
567 spcCoord coord [spaceDim];
568 int nCubes = theSet. size ();
569 spcCoord rightBound = (1 << depth) - 1;
570 for (int i = 0; i < nCubes; ++ i)
571 {
572 theSet [i]. coord (coord);
573 for (int j = 0; j < spaceDim; ++ j)
574 {
575 if ((coord [j] <= 0) || (coord [j] >= rightBound))
576 return false;
577 }
578 }
579 return true;
580} /* checkIsolation */
581
582
583// --------------------------------------------------
584// --------- subdividing phase space cubes ----------
585// --------------------------------------------------
586
587/// Subdivides one set of cubes to another set of cubes
588/// with respect to twice finer grid.
589template <class typeCubes>
590void subdivideCubes (const typeCubes &X, typeCubes &result)
591{
592 typedef typename typeCubes::value_type tCube;
593 typedef typename typeCubes::value_type::CoordType tCoord;
594
595 if (X. empty ())
596 return;
597 int dim = X [0]. dim ();
598
599 tCoord cmin [tCube::MaxDim];
600 tCoord cmax [tCube::MaxDim];
601 int n = X. size ();
602 for (int i = 0; i < n; ++ i)
603 {
604 X [i]. coord (cmin);
605 for (int j = 0; j < dim; ++ j)
606 {
607 cmin [j] *= 2;
608 cmax [j] = cmin [j] + 2;
609 }
610 chomp::homology::tRectangle<tCoord> r (cmin, cmax, dim);
611 const tCoord *c;
612 while ((c = r. get ()) != 0)
613 result. add (tCube (c, dim));
614 }
615 return;
616} /* subdivideCubes */
617
618/// Subdivides a cube to a set of cubes with respect to twice finer grid.
619template <class typeCube, class typeCubes>
620void subdivideCube (const typeCube &q, typeCubes &result)
621{
622 typedef typename typeCubes::value_type::CoordType tCoord;
623
624 int dim = q. dim ();
625
626 tCoord cmin [typeCube::MaxDim];
627 tCoord cmax [typeCube::MaxDim];
628 q. coord (cmin);
629 for (int j = 0; j < dim; ++ j)
630 {
631 cmin [j] *= 2;
632 cmax [j] = cmin [j] + 2;
633 }
634 chomp::homology::tRectangle<tCoord> r (cmin, cmax, dim);
635 const tCoord *c;
636 while ((c = r. get ()) != 0)
637 result. add (typeCube (c, dim));
638 return;
639} /* subdivideCube */
640
641/// Embeds a set of cubes to another set of cubes
642/// with respect to twice coarser grid.
643template <class typeCubes>
644void embedCubes (const typeCubes &X, typeCubes &result)
645{
646 typedef typename typeCubes::value_type tCube;
647 typedef typename typeCubes::value_type::CoordType tCoord;
648
649 if (X. empty ())
650 return;
651 int dim = X [0]. dim ();
652
653 tCoord coord [tCube::MaxDim];
654 int n = X. size ();
655 for (int i = 0; i < n; ++ i)
656 {
657 X [i]. coord (coord);
658 for (int j = 0; j < dim; ++ j)
659 coord [j] /= 2;
660 result. add (tCube (coord, dim));
661 }
662 return;
663} /* embedCubes */
664
665/// Enhances the given set of cubes provided number of times.
666inline void enhanceCubes (spcCubes &X, int enhanceTimes, int subdivDepth)
667{
668 if (X. empty ())
669 return;
670 spcCoord coordBound = 1 << subdivDepth;
671 int dim = X [0]. dim ();
672 spcCoord *c = new spcCoord [dim];
673
674 int cur = 0;
675 while (enhanceTimes --)
676 {
677 int curBound = X. size ();
678 for (; cur < curBound; ++ cur)
679 {
680 X [cur]. coord (c);
681 chomp::homology::tNeighbors<spcCoord> n (c, dim);
682 const spcCoord *nc = 0;
683 while ((nc = n. get ()) != 0)
684 {
685 bool outOfSpace = false;
686 for (int i = 0; i < dim; ++ i)
687 {
688 if ((nc [i] < 0) ||
689 (nc [i] >= coordBound))
690 {
691 outOfSpace = true;
692 break;
693 }
694 }
695 if (!outOfSpace)
696 X. add (spcCube (nc, dim));
697 }
698 }
699 }
700
701 delete [] c;
702 return;
703} /* enhanceCubes */
704
705
706// --------------------------------------------------
707// --------------- phase space cubes ----------------
708// --------------------------------------------------
709
710/// Returns the volume of the given number of cubes in the phase space
711/// at the provided subdivision level.
712inline double cubesVolume (int_t nCubes, int subdiv)
713{
714 const spcCoord intWidth (static_cast<spcCoord> (1) << subdiv);
715 double cubeVolume (1.0);
716 for (int i = 0; i < spaceDim; ++ i)
717 cubeVolume *= spaceWidth [i] / intWidth;
718 return nCubes * cubeVolume;
719} /* cubesVolume */
720
721/// Crops the ranges, marks this fact if it occurred,
722/// and throws an exception if requested to.
723template <class CoordType>
724inline void cropRanges (CoordType *left, CoordType *right, int dim,
725 int intwidth, bool throwIfCropped, bool &cropped)
726{
727 for (int i = 0; i < dim; ++ i)
728 {
729 if (left [i] < 0)
730 {
731 left [i] = (right [i] > 0) ?
732 0 : (right [i] - 1);
733 if (throwIfCropped)
734 throw "Image sticks outside: left.";
735 cropped = true;
736 }
737 if (right [i] > intwidth)
738 {
739 right [i] = (left [i] < intwidth) ?
740 intwidth : (left [i] + 1);
741 if (throwIfCropped)
742 throw "Image sticks outside: right.";
743 cropped = true;
744 }
745 }
746 return;
747} /* cropRanges */
748
749/// Checks if the size of the image does not exceed the globally defined
750/// maximal diameter and maximal volume (throws exceptions should this
751/// be the case), and updates variables that store maximal values
752/// of these quantities.
753/// Returns the volume of the entire rectangular box.
754template <class CoordType>
755inline long checkImageSize (const CoordType *left, const CoordType *right,
756 int dim, int &maxImgDiam, int &maxImgVol,
757 int maxImgDiamAllowed, int maxImgVolAllowed)
758{
759 long volume = 1;
760 for (int i = 0; i < dim; ++ i)
761 {
762 int size = right [i] - left [i];
763 if (maxImgDiam < size)
764 maxImgDiam = size;
765 if (size > maxImgDiamAllowed)
766 throw "Excessive diameter of box image.";
767 volume *= size;
768 if (volume > maxImgVolAllowed)
769 throw "Excessive volume of box image.";
770 }
771 if (maxImgVol < volume)
772 maxImgVol = volume;
773 return volume;
774} /* checkImageSize */
775
776/// Checks if the given object is in the array of the given size.
777/// Returns true if yes, false otherwise.
778template <class ObjectType, class ArrayType>
779inline bool objectInArray (const ObjectType &theObject,
780 const ArrayType &theArray, int_t arraySize)
781{
782 for (int_t n = 0; n < arraySize; ++ n)
783 {
784 if (theArray [n] == theObject)
785 return true;
786 }
787 return false;
788} /* objectInArray */
789
790/// Replaces the hashed set of objects with another one
791/// that contains the same objects, but some of the objects
792/// are moved selectively to the front, taking the suggested
793/// step size in going through the initial hashed set.
794/// The hashed set must have the property that adding an element to it
795/// several times causes this element to be added only once.
796/// Note: The step should be a (small) number N such that
797/// groups of N consecutive objects are clustered together,
798/// and the purpose of this procedure is to take representatives
799/// of these clusters to the front of the hashed set.
800template <class HashSetType>
801inline void moveSomeToFront (HashSetType &X, int_t step)
802{
803 HashSetType Y;
804 int_t size = X. size ();
805
806 // take elements at positions that are multiples of the provided step
807 const int_t step1 = 25013 * step;
808 for (int_t i = step1 / 7; i < size; i += step1)
809 Y. add (X [i]);
810 const int_t step2 = 503 * step;
811 for (int_t i = step2 / 13; i < size; i += step2)
812 Y. add (X [i]);
813 for (int_t i = step >> 1; i < size; i += step)
814 Y. add (X [i]);
815
816 // take elements scattered in the set
817 const int_t step3 = 751;
818 for (int_t i = step3 >> 1; i < size; i += step3)
819 Y. add (X [i]);
820 const int_t step4 = 73;
821 for (int_t i = step4 >> 1; i < size; i += step4)
822 Y. add (X [i]);
823 const int_t step5 = 7;
824 for (int_t i = step5 >> 1; i < size; i += step5)
825 Y. add (X [i]);
826
827 // take all the elements
828 for (int_t i = 0; i < size; ++ i)
829 Y. add (X [i]);
830
831 // check that the transformation was correct
832 if (Y. size () != size)
833 throw "Wrong size of the new set in 'moveSomeToFront'.";
834
835 // replace the result with the new set
836 Y. swap (X);
837
838 return;
839} /* moveSomeToFront */
840
841/// Computes the volume of the intersection of the unitary cube
842/// with the provided coordinates with the given product of intervals.
843template <class CoordType, class IntervalType>
844inline double intersectionVolume (const CoordType *c,
845 const IntervalType *intervalBox, int dim)
846{
847 double vol = 1;
848 for (int i = 0; i < dim; ++ i)
849 {
850 // if the interval is disjoint (to the left of the cube)
851 if (c [i] >= intervalBox [i]. rightBound ())
852 return 0;
853 // if the interval is disjoint (to the right of the cube)
854 if (c [i] + 1 <= intervalBox [i]. leftBound ())
855 return 0;
856 // if the left endpoint of the interval is inside the cube
857 if (c [i] < intervalBox [i]. leftBound ())
858 {
859 // if the right endpoint of the interval is inside
860 if (c [i] + 1 > intervalBox [i]. rightBound ())
861 {
862 vol *= intervalBox [i]. rightBound () -
863 intervalBox [i]. leftBound ();
864 }
865 // if the right endpoint is outside of the cube
866 else
867 {
868 vol *= c [i] + 1 - intervalBox [i]. leftBound ();
869 }
870 }
871 // if the left endpoint of the interval is outside the cube
872 else
873 {
874 // if the right endpoint of the interval is inside
875 if (c [i] + 1 > intervalBox [i]. rightBound ())
876 {
877 vol *= intervalBox [i]. rightBound () - c [i];
878 }
879 // if the right endpoint is outside of the cube
880 else
881 {
882 // vol *= 1;
883 }
884 }
885 }
886 return vol;
887} /* intersectionVolume */
888
889
890// --------------------------------------------------
891// ------------------ set wrapper -------------------
892// --------------------------------------------------
893
894/// An imitation of an array whose entries are 1 iff the index
895/// belongs to the given set.
896/// This class may be useful if one needs to compute the subgraph
897/// of a directed graph restricted to a given set,
898/// using the subgraph method of the class diGraph.
899template <class elemType, class setType>
901{
902public:
903 /// The constructor of a set wrapper.
904 set2arrayWrapper (const setType &_theSet):
905 theSet (_theSet)
906 {
907 return;
908 }
909
910 /// The operator [] which returns 1
911 /// iff the element belongs to the set.
912 int operator [] (const elemType &n) const
913 {
914 return theSet. check (n) ? 1 : 0;
915 }
916
917private:
918 /// A reference to the wrapped set.
919 const setType &theSet;
920}; /* class set2arrayWrapper */
921
922
923// --------------------------------------------------
924// ------------------ graph utils -------------------
925// --------------------------------------------------
926
927/// Computes the graph corresponding to the restriction of the
928/// combinatorial map to the provided subset.
929template <class SetType, class GraphType>
930inline void computeRestrictedGraph (GraphType &restr, const GraphType &g,
931 const SetType &full, const SetType &subset)
932{
933 int_t subsetCount = subset. size ();
934 for (int_t i = 0; i < subsetCount; ++ i)
935 {
936 restr. addVertex ();
937 int_t vertex = full. getnumber (subset [i]);
938 int_t nEdges = g. countEdges (vertex);
939 for (int_t j = 0; j < nEdges; ++ j)
940 {
941 int_t target = g. getEdge (vertex, j);
942 int_t number = subset. getnumber
943 (full [target]);
944 if (number >= 0)
945 restr. addEdge (number);
946 }
947 }
948 return;
949} /* computeRestrictedGraph */
950
951
952// --------------------------------------------------
953// ----------------- output numbers -----------------
954// --------------------------------------------------
955
956/// Creates a text representation of a floating-point number
957/// at the prescribed precision.
958inline std::string double2string (const double &x, int precision)
959{
960 std::ostringstream out;
961 out. setf (std::ios::fixed);
962 out. precision (precision);
963 out << x;
964 return out. str ();
965} /* double2string */
966
967
968// --------------------------------------------------
969// --------------- progress indicator ---------------
970// --------------------------------------------------
971
972/// Shows a progress indicator to the screen as an integer number
973/// followed by an additional character (e.g. 'k').
974inline void showProgress (int n, char c)
975{
976 chomp::homology::scon << std::setw (9) << n << c <<
977 "\b\b\b\b\b\b\b\b\b\b";
978 return;
979} /* showProgress */
980
981
982#endif // _CMGRAPHS_UTILS_H_
983
A class whose objects store, update and show coordinate ranges.
Definition: utils.h:444
spcCoord coordLeftMin[spaceDim]
The minimal coordinates.
Definition: utils.h:462
bool defined() const
Returns true if at least one cube was taken for the ranges.
Definition: utils.h:490
void operator()(const spcCubes &theSet)
Updates the coordinate ranges for the given set of cubes.
Definition: utils.h:495
CoordMinMax()
The default constructor.
Definition: utils.h:469
spcCoord coordRightMax[spaceDim]
The strict upper bound for the maximal coordinates.
Definition: utils.h:465
Initializes the given variable with the value provided and restores the previous value at the end of ...
Definition: utils.h:109
local_value(T &_variable, const T &_value)
The only allowed constructor.
Definition: utils.h:112
~local_value()
The destructor which restores the original value of the variable.
Definition: utils.h:117
T previous_value
The original value of the variable.
Definition: utils.h:124
T & variable
A reference of the variable.
Definition: utils.h:121
An imitation of an array whose entries are 1 iff the index belongs to the given set.
Definition: utils.h:901
const setType & theSet
A reference to the wrapped set.
Definition: utils.h:919
set2arrayWrapper(const setType &_theSet)
The constructor of a set wrapper.
Definition: utils.h:904
int operator[](const elemType &n) const
The operator [] which returns 1 iff the element belongs to the set.
Definition: utils.h:912
Choice of configuration settings.
const SpaceOffsetType spaceOffset
An imitation of an array which returns the offset of the rectangular area in the phase space which co...
Definition: p_differ.h:108
const int paramSelect[paramDim]
The numbers of parameters to subdivide.
Definition: p_differ.h:74
const double paramRight[paramCount]
The right bounds on the parameters: b, h.
Definition: p_differ.h:88
const int paramDim
The dimension of the parameter space to iterate.
Definition: p_differ.h:67
const int spaceDim
The dimension of the phase space.
Definition: p_differ.h:48
const double paramLeft[paramCount]
The left bounds on the parameters: b > 1, h < (sqrt(b) - 1)^2.
Definition: p_differ.h:85
const int paramCount
The number of all the parameters, both varying and fixed.
Definition: p_differ.h:82
const SpaceWidthType spaceWidth
An imitation of an array which returns the width of the rectangular area in the phase space which con...
Definition: p_differ.h:128
const int finalDepth
The final depth of subdivisions in the phase space.
Definition: p_differ.h:58
const short int paramSubdiv[paramDim]
The numbers of subintervals in each direction of the parameter space.
Definition: p_differ.h:71
Customizable data types for the Conley-Morse graphs computation program.
capd::DInterval IntervalType
The type of an interval (from the CAPD library 2.9/3.0 beta).
Definition: typeintv.h:49
short int parCoord
The type of coordinates of cubes in the set of parameters.
Definition: typeparam.h:53
chomp::homology::tRectangle< parCoord > parRect
The type of a rectangle used to iterate sets of cubes of parameters.
Definition: typeparam.h:64
chomp::homology::hashedset< spcCube > spcCubes
The type of a set of cubes in the phase space.
Definition: typespace.h:58
int spcCoord
The type of coordinates of cubes in the phase space.
Definition: typespace.h:50
chomp::homology::tCubeBase< spcCoord > spcCube
The type of a cube in the phase space.
Definition: typespace.h:55
void embedCubes(const typeCubes &X, typeCubes &result)
Embeds a set of cubes to another set of cubes with respect to twice coarser grid.
Definition: utils.h:644
bool internalBoundaryPoint(const intType1 *coord, const intType2 *left, const intType2 *right, const intType3 *limit, int dim)
Verifies whether the given box is located at the boundary of the small region which is either not at ...
Definition: utils.h:137
std::string double2string(const double &x, int precision)
Creates a text representation of a floating-point number at the prescribed precision.
Definition: utils.h:958
void subdivideCube(const typeCube &q, typeCubes &result)
Subdivides a cube to a set of cubes with respect to twice finer grid.
Definition: utils.h:620
int countDigits(intType x)
Returns the number of digits of the given non-negative integer number.
Definition: utils.h:366
void subdivideCubes(const typeCubes &X, typeCubes &result)
Subdivides one set of cubes to another set of cubes with respect to twice finer grid.
Definition: utils.h:590
std::ostream & operator<<(std::ostream &out, const CoordMinMax &range)
Outputs the ranges of coordinates to an output stream.
Definition: utils.h:524
void showProgress(int n, char c)
Shows a progress indicator to the screen as an integer number followed by an additional character (e....
Definition: utils.h:974
OutStream & showRealCoords(OutStream &out, const CoordMinMax &range)
Shows the real coordinates of the coordinate range.
Definition: utils.h:543
bool objectInArray(const ObjectType &theObject, const ArrayType &theArray, int_t arraySize)
Checks if the given object is in the array of the given size.
Definition: utils.h:779
double cubesVolume(int_t nCubes, int subdiv)
Returns the volume of the given number of cubes in the phase space at the provided subdivision level.
Definition: utils.h:712
bool fileExists(const char *filename)
Returns 'true' iff the given file exists and it is allowed to read it.
Definition: utils.h:69
std::string fileNameWithoutExt(const std::string &fileName)
Returns the file name without its extension if any.
Definition: utils.h:82
double intersectionVolume(const CoordType *c, const IntervalType *intervalBox, int dim)
Computes the volume of the intersection of the unitary cube with the provided coordinates with the gi...
Definition: utils.h:844
parRect * subRectangles(parCoord *zeroIter, parCoord *maxIter, std::vector< parCoord > *subCoords, int minCount)
Determines heuristically an optimal subdivision of a large parameter region into the given minimal nu...
Definition: utils.h:213
void enhanceCubes(spcCubes &X, int enhanceTimes, int subdivDepth)
Enhances the given set of cubes provided number of times.
Definition: utils.h:666
std::string coord2str(const intType1 *coords, const intType2 *maxCoords, int dim)
Generates an underscore-separated list of non-negative coordinates padded with zeros to the same widt...
Definition: utils.h:386
void computeRestrictedGraph(GraphType &restr, const GraphType &g, const SetType &full, const SetType &subset)
Computes the graph corresponding to the restriction of the combinatorial map to the provided subset.
Definition: utils.h:930
void cropRanges(CoordType *left, CoordType *right, int dim, int intwidth, bool throwIfCropped, bool &cropped)
Crops the ranges, marks this fact if it occurred, and throws an exception if requested to.
Definition: utils.h:724
bool checkIsolation(const spcCubes &theSet, int depth)
Verifies if the given set of cubes is contained in the interior of the phase space box.
Definition: utils.h:565
long checkImageSize(const CoordType *left, const CoordType *right, int dim, int &maxImgDiam, int &maxImgVol, int maxImgDiamAllowed, int maxImgVolAllowed)
Checks if the size of the image does not exceed the globally defined maximal diameter and maximal vol...
Definition: utils.h:755
void computeParam(const intType *curCoord, double *leftMapParam, double *rightMapParam)
Computes the real coordinates of the parameter cube which corresponds to the given box.
Definition: utils.h:160
void moveSomeToFront(HashSetType &X, int_t step)
Replaces the hashed set of objects with another one that contains the same objects,...
Definition: utils.h:801