utils.h

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////////////
00002 ///
00003 /// @file utils.h
00004 ///
00005 /// Utilites and helper functions.
00006 /// This file contains the definitions of various little useful utility
00007 /// procedures for the Conley-Morse graphs computation software.
00008 ///
00009 /// @author Pawel Pilarczyk
00010 ///
00011 /////////////////////////////////////////////////////////////////////////////
00012 
00013 // Copyright (C) 1997-2008 by Pawel Pilarczyk.
00014 //
00015 // This file is part of my research software package.  This is free software;
00016 // you can redistribute it and/or modify it under the terms of the GNU
00017 // General Public License as published by the Free Software Foundation;
00018 // either version 2 of the License, or (at your option) any later version.
00019 //
00020 // This software is distributed in the hope that it will be useful,
00021 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 // GNU General Public License for more details.
00024 //
00025 // You should have received a copy of the GNU General Public License along
00026 // with this software; see the file "license.txt".  If not, write to the
00027 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00028 // MA 02111-1307, USA.
00029 
00030 // Started on February 11, 2008. Last revision: April 13, 2008.
00031 
00032 
00033 #ifndef _CMGRAPHS_UTILS_H_
00034 #define _CMGRAPHS_UTILS_H_
00035 
00036 
00037 // include some standard C++ header files
00038 #include <string>
00039 #include <sstream>
00040 #include <fstream>
00041 #include <cmath>
00042 #include <algorithm>
00043 #include <vector>
00044 
00045 // include selected header files from the CHomP library
00046 #include "chomp/system/config.h"
00047 #include "chomp/system/textfile.h"
00048 #include "chomp/cubes/cube.h"
00049 #include "chomp/multiwork/mw.h"
00050 
00051 // include local header files
00052 #include "config.h"
00053 #include "typedefs.h"
00054 #include "eigenval.h"
00055 
00056 
00057 // --------------------------------------------------
00058 // ----------------- file existence -----------------
00059 // --------------------------------------------------
00060 
00061 /// Returns 'true' iff the given file exists and it is allowed to read it.
00062 inline bool fileExists (const char *filename)
00063 {
00064         std::ifstream in (filename);
00065         return !!in;
00066 } /* fileExists */
00067 
00068 
00069 // --------------------------------------------------
00070 // ----------- local value of a variable ------------
00071 // --------------------------------------------------
00072 
00073 /// Initializes the given variable with the value provided
00074 /// and restores the previous value at the end of the current block.
00075 /// The restoration of the previous value takes place upon destruction
00076 /// of this object. This action effects in a local value of a given variable
00077 /// valid in the current block only (e.g., until 'return').
00078 template <class T>
00079 class local_value
00080 {
00081 public:
00082         /// The only allowed constructor.
00083         local_value (T &_variable, const T &_value):
00084                 variable (_variable), previous_value (_variable)
00085                 {variable = _value; return;}
00086 
00087         /// The destructor which restores the original value of the variable.
00088         ~local_value () {variable = previous_value; return;}
00089 
00090 private:
00091         /// A reference of the variable.
00092         T &variable;
00093 
00094         /// The original value of the variable.
00095         T previous_value;
00096 
00097 }; /* class local_value */
00098 
00099 
00100 // --------------------------------------------------
00101 // ---------------- parameter cubes -----------------
00102 // --------------------------------------------------
00103 
00104 /// Verifies whether the given box is located at the boundary
00105 /// of the small region which is either not at the boundary
00106 /// of the large region, or is adjacent to some other similar region.
00107 template <class intType1, class intType2, class intType3>
00108 inline bool internalBoundaryPoint (const intType1 *coord,
00109         const intType2 *left, const intType2 *right,
00110         const intType3 *limit, int dim)
00111 {
00112         for (int i = 0; i < dim; ++ i)
00113         {
00114                 if ((coord [i] == left [i]) && (left [i] != 0))
00115                 {
00116                         return true;
00117                 }
00118                 else if ((coord [i] == right [i] - 1) &&
00119                         (right [i] != limit [i]))
00120                 {
00121                         return true;
00122                 }
00123         }
00124         return false;
00125 } /* internalBoundaryPoint */
00126 
00127 /// Computes the real coordinates of the parameter cube
00128 /// which corresponds to the given box.
00129 /// Uses the globally defined ranges.
00130 template <class intType>
00131 void computeParam (const intType *curCoord,
00132         double *leftMapParam, double *rightMapParam)
00133 {
00134         for (int i = 0; i < paramCount; ++ i)
00135         {
00136                 leftMapParam [i] = paramLeft [i];
00137                 rightMapParam [i] = paramRight [i];
00138                 for (int j = 0; j < paramDim; ++ j)
00139                 {
00140                         if (i != paramSelect [j])
00141                                 continue;
00142                         double paramWidth = paramRight [i] - paramLeft [i];
00143                         if (curCoord [j] > 0)
00144                         {
00145                                 leftMapParam [i] = paramLeft [i] +
00146                                         curCoord [j] * paramWidth /
00147                                         paramSubdiv [j];
00148                         }
00149                         if (curCoord [j] < paramSubdiv [j] - 1)
00150                         {
00151                                 rightMapParam [i] = paramLeft [i] +
00152                                         (curCoord [j] + 1) * paramWidth /
00153                                         paramSubdiv [j];
00154                         }
00155                         break;
00156                 }
00157         }
00158         return;
00159 } /* computeParam */
00160 
00161 /// Determines heuristically an optimal subdivision of a large parameter
00162 /// region into the given minimal number of smaller regions.
00163 /// Fills in the provided array of vectors with the division coordinates.
00164 /// Allocates a rectangle for iterating this region and returns its pointer.
00165 /// Note: The rectangle is built upon the two arrays provided; they should
00166 /// not be deleted or otherwise the pointers stored within the rectangle
00167 /// become invalid.
00168 inline parRect *subRectangles (parCoord *zeroIter, parCoord *maxIter,
00169         std::vector<parCoord> *subCoords, int minCount)
00170 {
00171         using chomp::homology::sbug;
00172 
00173         // make a correction to the minimal requested number of parts
00174         if (minCount < 1)
00175                 minCount = 1;
00176 
00177         // prepare the increasing order of all the sides
00178         // of the full parameter rectangular area
00179         bool taken [paramDim];
00180         for (int i = 0; i < paramDim; ++ i)
00181                 taken [i] = false;
00182         int increasing [paramDim];
00183         for (int i = 0; i < paramDim; ++ i)
00184         {
00185                 // find an index with the minimal value but not yet taken
00186                 int minIndex = -1;
00187                 for (int j = 0; j < paramDim; ++ j)
00188                 {
00189                         if (taken [j])
00190                                 continue;
00191                         if ((minIndex < 0) ||
00192                                 (paramSubdiv [j] < paramSubdiv [minIndex]))
00193                         {
00194                                 minIndex = j;
00195                         }
00196                 }
00197 
00198                 // take this index
00199                 increasing [i] = minIndex;
00200                 taken [minIndex] = true;
00201         }
00202 
00203         // compute the recommended maximal volume of each rectangular region
00204         double volume = 1;
00205         for (int i = 0; i < paramDim; ++ i)
00206                 volume *= paramSubdiv [i];
00207         volume /= minCount;
00208 
00209         // prepare the number of parts in each direction
00210         // and fill in the maximal corner of the rectangle for iterating
00211         for (int i = 0; i < paramDim; ++ i)
00212         {
00213                 // determine the recommended side length
00214                 int index = increasing [i];
00215                 double side = std::exp (std::log (volume) / (paramDim - i));
00216                 double delta = (i == paramDim - 1) ? 0.99999 : 0.5;
00217                 maxIter [index] = static_cast<int>
00218                         (paramSubdiv [index] / side + delta);
00219         //      chomp::homology::sbug << "Vol = " << volume <<
00220         //              ", side = " << side <<
00221         //              ", maxIter = " << maxIter [index] << "\n";
00222                 if (maxIter [index] > paramSubdiv [index])
00223                         maxIter [index] = paramSubdiv [index];
00224                 if (maxIter [index] <= 0)
00225                         maxIter [index] = 1;
00226 
00227                 // divide the volume by the approximate side length
00228                 volume /= paramSubdiv [index];
00229                 volume *= maxIter [index];
00230         //      chomp::homology::sbug << " x " << maxIter [index] << "\n";
00231         }
00232 
00233         // fill in the array with the subdivision coordinates
00234         for (int i = 0; i < paramDim; ++ i)
00235         {
00236                 subCoords [i]. push_back (0);
00237                 for (int j = 1; j < maxIter [i]; ++ j)
00238                 {
00239                         subCoords [i]. push_back ((paramSubdiv [i] * j +
00240                                 maxIter [i] / 2) / maxIter [i]);
00241                 }
00242                 subCoords [i]. push_back (paramSubdiv [i]);
00243         }
00244 
00245         // prepare the minimal corner of the rectangle for iterating
00246         for (int i = 0; i < paramDim; ++ i)
00247                 zeroIter [i] = 0;
00248 
00249         // return the rectangle in question
00250         return new parRect (zeroIter, maxIter, paramDim);
00251 } /* subRectangles */
00252 
00253 
00254 // --------------------------------------------------
00255 // ------ string representation of coordinates ------
00256 // --------------------------------------------------
00257 
00258 /// Returns the number of digits of the given non-negative integer number.
00259 template <class intType>
00260 inline int countDigits (intType x)
00261 {
00262         intType tenPower = 10;
00263         int digits = 1;
00264         while (1)
00265         {
00266                 if (x < tenPower)
00267                         return digits;
00268                 intType nextPower = tenPower * 10;
00269                 if (nextPower < tenPower)
00270                         return digits;
00271                 tenPower = nextPower;
00272                 ++ digits;
00273         }
00274 } /* countDigits */
00275 
00276 /// Generates an underscore-separated list of non-negative coordinates
00277 /// padded with zeros to the same width assuming that their values
00278 /// are below the given limits.
00279 template <class intType1, class intType2>
00280 inline std::string coord2str (const intType1 *coords,
00281         const intType2 *maxCoords, int dim)
00282 {
00283         std::ostringstream str;
00284         for (int i = 0; i < dim; ++ i)
00285         {
00286                 if (i)
00287                         str << '_';
00288                 int maxDigits = countDigits (maxCoords [i] - 1);
00289                 int digits = countDigits (coords [i]);
00290                 for (int d = digits; d < maxDigits; ++ d)
00291                         str << '0';
00292                 str << coords [i];
00293         }
00294         return str. str ();
00295 } /* coord2str */
00296 
00297 /// Generates an underscore-separated list of non-negative coordinates.
00298 template <class intType>
00299 inline std::string coord2str (const intType *coords, int dim)
00300 {
00301         std::ostringstream str;
00302         for (int i = 0; i < dim; ++ i)
00303         {
00304                 if (i)
00305                         str << '_';
00306                 str << coords [i];
00307         }
00308         return str. str ();
00309 } /* coord2str */
00310 
00311 
00312 // --------------------------------------------------
00313 // ------------- ranges of coordinates --------------
00314 // --------------------------------------------------
00315 
00316 /// Updates the minimal and maximal coordinates of the box
00317 /// which contains all the Morse sets.
00318 inline void coordMinMax (const theMorseDecompositionType &morseDec,
00319         spcCoord *coordLeftMin, spcCoord *coordRightMax)
00320 {
00321         spcCoord coord [spaceDim];
00322         int nSets = morseDec. count ();
00323         for (int n = 0; n < nSets; ++ n)
00324         {
00325                 const spcCubes &theSet = morseDec [n];
00326                 int nCubes = theSet. size ();
00327                 for (int i = 0; i < nCubes; ++ i)
00328                 {
00329                         theSet [i]. coord (coord);
00330                         for (int j = 0; j < spaceDim; ++ j)
00331                         {
00332                                 if (coordLeftMin [j] > coord [j])
00333                                         coordLeftMin [j] = coord [j];
00334                                 if (coordRightMax [j] <= coord [j])
00335                                         coordRightMax [j] = coord [j] + 1;
00336                         }
00337                 }
00338         }
00339         return;
00340 } /* coordMinMax */
00341 
00342 
00343 // --------------------------------------------------
00344 // --------- subdividing phase space cubes ----------
00345 // --------------------------------------------------
00346 
00347 /// Subdivides one set of cubes to another set of cubes
00348 /// with respect to twice finer grid.
00349 template <class typeCubes>
00350 void subdivideCubes (const typeCubes &X, typeCubes &result)
00351 {
00352         typedef typename typeCubes::value_type tCube;
00353         typedef typename typeCubes::value_type::CoordType tCoord;
00354 
00355         if (X. empty ())
00356                 return;
00357         int dim = X [0]. dim ();
00358 
00359         tCoord cmin [tCube::MaxDim];
00360         tCoord cmax [tCube::MaxDim];
00361         int n = X. size ();
00362         for (int i = 0; i < n; ++ i)
00363         {
00364                 X [i]. coord (cmin);
00365                 for (int j = 0; j < dim; ++ j)
00366                 {
00367                         cmin [j] *= 2;
00368                         cmax [j] = cmin [j] + 2;
00369                 }
00370                 chomp::homology::tRectangle<tCoord> r (cmin, cmax, dim);
00371                 const tCoord *c;
00372                 while ((c = r. get ()) != 0)
00373                         result. add (tCube (c, dim));
00374         }
00375         return;
00376 } /* subdivideCubes */
00377 
00378 /// Subdivides a cube to a set of cubes with respect to twice finer grid.
00379 template <class typeCube, class typeCubes>
00380 void subdivideCube (const typeCube &q, typeCubes &result)
00381 {
00382         typedef typename typeCubes::value_type::CoordType tCoord;
00383 
00384         int dim = q. dim ();
00385 
00386         tCoord cmin [typeCube::MaxDim];
00387         tCoord cmax [typeCube::MaxDim];
00388         q. coord (cmin);
00389         for (int j = 0; j < dim; ++ j)
00390         {
00391                 cmin [j] *= 2;
00392                 cmax [j] = cmin [j] + 2;
00393         }
00394         chomp::homology::tRectangle<tCoord> r (cmin, cmax, dim);
00395         const tCoord *c;
00396         while ((c = r. get ()) != 0)
00397                 result. add (typeCube (c, dim));
00398         return;
00399 } /* subdivideCube */
00400 
00401 /// Embeds a set of cubes to another set of cubes
00402 /// with respect to twice coarser grid.
00403 template <class typeCubes>
00404 void embedCubes (const typeCubes &X, typeCubes &result)
00405 {
00406         typedef typename typeCubes::value_type tCube;
00407         typedef typename typeCubes::value_type::CoordType tCoord;
00408 
00409         if (X. empty ())
00410                 return;
00411         int dim = X [0]. dim ();
00412 
00413         tCoord coord [tCube::MaxDim];
00414         int n = X. size ();
00415         for (int i = 0; i < n; ++ i)
00416         {
00417                 X [i]. coord (coord);
00418                 for (int j = 0; j < dim; ++ j)
00419                         coord [j] /= 2;
00420                 result. add (tCube (coord, dim));
00421         }
00422         return;
00423 } /* embedCubes */
00424 
00425 
00426 #endif // _CMGRAPHS_UTILS_H_
00427 

Generated on Sun Mar 28 17:47:58 2010 for The Conley-Morse Graphs Software by  doxygen 1.5.3