indcache.h

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////////////
00002 ///
00003 /// @file indcache.h
00004 ///
00005 /// Cached Conley indices for a Morse decomposition.
00006 /// This file contains the definition of a class for caching computed
00007 /// Conley indices for a Morse decomposition. The Conley indices can be
00008 /// saved to a file or retrieved from a file, including the information
00009 /// on a nontrivial invariant part for Morse sets with the trivial index.
00010 ///
00011 /// @author Pawel Pilarczyk
00012 ///
00013 /////////////////////////////////////////////////////////////////////////////
00014 
00015 // Copyright (C) 1997-2008 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 February 12, 2007. Last revision: March 8, 2008.
00033 
00034 
00035 #ifndef _CMGRAPHS_INDCACHE_H_
00036 #define _CMGRAPHS_INDCACHE_H_
00037 
00038 
00039 // include some standard C++ header files
00040 #include <fstream>
00041 
00042 // include selected header files from the CHomP library
00043 #include "chomp/system/textfile.h"
00044 #include "chomp/cubes/pointset.h"
00045 
00046 // include local header files
00047 #include "config.h"
00048 #include "typedefs.h"
00049 #include "conindex.h"
00050 #include "morsedec.h"
00051 
00052 
00053 // --------------------------------------------------
00054 // ------------- cached Conley indices --------------
00055 // --------------------------------------------------
00056 
00057 /// Cached information on the Conley-Morse decompositions
00058 /// which contains information on computed Conley indices
00059 /// for Morse sets and also the information on whether the invariant part
00060 /// was proved to be empty for the sets with the trivial index.
00061 class IndexCache
00062 {
00063 public:
00064         /// The constructor of an empty cached information structure
00065         /// for the given number of Morse sets.
00066         IndexCache (int nSets);
00067 
00068         /// Reads the cached information from a file, matches it
00069         /// with the given Morse decomposition and sets the Conley indices.
00070         /// Returns 0 if succeeded, or -1 if failed.
00071         int read (const std::string &fileName,
00072                 theMorseDecompositionType &morseDec);
00073 
00074         /// Writes the cached information for the given Morse decomposition
00075         /// to a file.
00076         /// Returns 0 if succeeded, 1 if the file already exists,
00077         /// or -1 in the case of failure.
00078         int write (const std::string &fileName,
00079                 const theMorseDecompositionType &morseDec) const;
00080 
00081         /// The destructor of a cached information structure.
00082         ~IndexCache ();
00083 
00084         /// The information on whether the invariant part of the given set
00085         /// has been proven to be empty.
00086         std::vector<bool> emptyInv;
00087 
00088         /// The information on whether the given Morse set is an attractor
00089         /// in the sense that its image is contained in itself.
00090         std::vector<bool> attractor;
00091 
00092         /// The information on whether the given index could not be computed
00093         /// because of a problem with isolation.
00094         std::vector<bool> wrongIndex;
00095 
00096         /// The information on whether the computation of the given index
00097         /// was skipped due to the limit on the size of the set.
00098         std::vector<bool> skipped;
00099 
00100 }; /* class IndexCache */
00101 
00102 // --------------------------------------------------
00103 
00104 inline IndexCache::IndexCache (int nSets): emptyInv (nSets, false),
00105         attractor (nSets, false), wrongIndex (nSets, false),
00106         skipped (nSets, false)
00107 {
00108         return;
00109 } /* IndexCache::IndexCache */
00110 
00111 inline IndexCache::~IndexCache ()
00112 {
00113         return;
00114 } /* IndexCache::IndexCache */
00115 
00116 int IndexCache::read (const std::string &fileName,
00117         theMorseDecompositionType &morseDec)
00118 {
00119         using chomp::homology::ignoreline;
00120         using chomp::homology::ignorecomments;
00121         using chomp::homology::sbug;
00122 
00123         // open the file to read the cached index information from
00124         std::ifstream in (fileName. c_str ());
00125         if (!in)
00126                 return -1;
00127         ignorecomments (in);
00128 
00129         // read the number of Morse sets and make sure that it is correct
00130         int nSets = -1;
00131         in >> nSets;
00132         ignorecomments (in);
00133         if (nSets != morseDec. count ())
00134         {
00135                 sbug << "Wrong number of Morse sets: " << nSets <<
00136                         " instead of " << morseDec. count () << ".\n";
00137                 return -1;
00138         }
00139 
00140         // prepare variables to read for each Morse set
00141         int number = -1;
00142         int empty = -1;
00143         int attr = -1;
00144         int wrong = -1;
00145         int skip = -1;
00146         int nCubes = -1;
00147         spcCube reprCube;
00148         theConleyIndexType ind;
00149         int countItems = 0;
00150 
00151         // prepare counters and matched bits to verify correctness
00152         int countSets = 0;
00153         std::vector<bool> matched (nSets, false);
00154         bool found = false;
00155 
00156         // read the Conley index and other information for each Morse set
00157         while (1)
00158         {
00159                 // read the control character which determines
00160                 // the kind of information to be read
00161                 int character = in. get ();
00162                 ignorecomments (in);
00163                 if (countSets && (character == 'M'))
00164                         character = 0x100;
00165 
00166                 switch (character)
00167                 {
00168                 // save the information previously gathered
00169                 case EOF:
00170                 case 0x100:
00171                         // make sure the number of items read is good
00172                         if (countItems < 7)
00173                         {
00174                                 sbug << "Only " << countItems << " elements "
00175                                         "read, at least 7 expected.\n";
00176                                 return -1;
00177                         }
00178 
00179                         // find the Morse set which corresponds to this one
00180                         // and fill in the corresponding information
00181                         found = false;
00182                         for (int setNum = 0; setNum < nSets; ++ setNum)
00183                         {
00184                                 if (matched [setNum])
00185                                         continue;
00186                                 if (morseDec [setNum]. size () != nCubes)
00187                                         continue;
00188                                 if (!morseDec [setNum]. check (reprCube))
00189                                         continue;
00190                                 matched [setNum] = true;
00191                                 emptyInv [setNum] = (empty == 1);
00192                                 attractor [setNum] = (attr == 1);
00193                                 wrongIndex [setNum] = (wrong == 1);
00194                                 skipped [setNum] = (skip == 1);
00195                                 morseDec. setindex (setNum, ind);
00196                                 found = true;
00197                                 break;
00198                         }
00199 
00200                         // return error code if the Morse set was not matched
00201                         if (!found)
00202                         {
00203                                 sbug << "Morse set no. " << number <<
00204                                         " could not be matched with any "
00205                                         "Morse set in the Morse dec.\n";
00206                                 return -1;
00207                         }
00208 
00209                         // quit if this is the end of the data
00210                         if (character == EOF)
00211                         {
00212                                 if (countSets == nSets)
00213                                         return 0;
00214                                 sbug << "Cached information for " <<
00215                                         countSets << " Morse sets found, " <<
00216                                         nSets << " expected.\n";
00217                                 return -1;
00218                         }
00219 
00220                         // reset the variables
00221                         number = -1;
00222                         empty = -1;
00223                         attr = -1;
00224                         wrong = -1;
00225                         skip = -1;
00226                         nCubes = -1;
00227                         countItems = 0;
00228                         // [no 'break' after this case...]
00229 
00230                 // verify the number of the subsequent Morse set
00231                 case 'M':
00232                         in >> number;
00233                         ignorecomments (in);
00234                         if (number != countSets)
00235                         {
00236                                 sbug << "Wrong Morse set number: " <<
00237                                         number << " (" << countSets <<
00238                                         " expected).\n";
00239                                 return -1;
00240                         }
00241                         ++ countSets;
00242                         ++ countItems;
00243                         break;
00244 
00245                 // check if the invariant part of this set is empty or not
00246                 case 'E':
00247                         in >> empty;
00248                         ignorecomments (in);
00249                         if ((empty != 0) && (empty != 1))
00250                         {
00251                                 sbug << "The number 0 or 1 expected "
00252                                         "for 'emptyInv', " << empty <<
00253                                         " found.\n";
00254                                 return -1;
00255                         }
00256                         ++ countItems;
00257                         break;
00258 
00259                 // check if this is an attractor
00260                 case 'A':
00261                         in >> attr;
00262                         ignorecomments (in);
00263                         if ((attr != 0) && (attr != 1))
00264                         {
00265                                 sbug << "The number 0 or 1 expected "
00266                                         "for 'attractor', " << attr <<
00267                                         " found.\n";
00268                                 return -1;
00269                         }
00270                         ++ countItems;
00271                         break;
00272 
00273                 // check if the Morse set is wrong (no isolation)
00274                 case 'W':
00275                         in >> wrong;
00276                         ignorecomments (in);
00277                         if ((wrong != 0) && (wrong != 1))
00278                         {
00279                                 sbug << "The number 0 or 1 expected "
00280                                         "for 'wrong index', " << wrong <<
00281                                         " found.\n";
00282                                 return -1;
00283                         }
00284                         ++ countItems;
00285                         break;
00286 
00287                 // check if the computation for this set was skipped or not
00288                 case 'S':
00289                         in >> skip;
00290                         ignorecomments (in);
00291                         if ((skip != 0) && (skip != 1))
00292                         {
00293                                 sbug << "The number 0 or 1 expected "
00294                                         "for 'skipped index', " << skip <<
00295                                         " found.\n";
00296                                 return -1;
00297                         }
00298                         ++ countItems;
00299                         break;
00300 
00301                 // acquire the number of cubes in the Morse set
00302                 case 'N':
00303                         in >> nCubes;
00304                         ignorecomments (in);
00305                         if (nCubes < 0)
00306                         {
00307                                 sbug << "Negative number of cubes found.\n";
00308                                 return -1;
00309                         }
00310                         ++ countItems;
00311                         break;
00312 
00313                 // read a representative cube from the Morse set
00314                 case 'Q':
00315                         // make sure that a cube is waiting at the input
00316                         if (in. peek () != '(')
00317                         {
00318                                 sbug << "An opening parenthesis of a cube "
00319                                         "not present.\n";
00320                                 return -1;
00321                         }
00322 
00323                         in >> reprCube;
00324                         ignorecomments (in);
00325                         ++ countItems;
00326                         break;
00327 
00328                 // read the Conley index
00329                 case 'I':
00330                         in >> ind;
00331                         ignorecomments (in);
00332                         ++ countItems;
00333                         break;
00334 
00335                 // ignore any unsupported data (for backwards compatibility)
00336                 default:
00337                         ignoreline (in);
00338                         ignorecomments (in);
00339                         break;
00340                 }
00341         }
00342 
00343         return 0;
00344 } /* IndexCache::read */
00345 
00346 int IndexCache::write (const std::string &fileName,
00347         const theMorseDecompositionType &morseDec) const
00348 {
00349         // create the file to write the cached index information to
00350         std::ofstream out (fileName. c_str ());
00351         if (!out)
00352                 return -1;
00353         out << "; Cached information with Conley indices "
00354                 "for a Morse decomposition.\n";
00355 
00356         // write the number of Morse sets
00357         int nSets = morseDec. count ();
00358         out << "; The number of Morse sets:\n";
00359         out << nSets << "\n";
00360 
00361         // write the description of the information
00362         out << "; -----------------------------------------------\n";
00363         out << "; M - the consecutive number of a Morse set\n";
00364         out << "; E - 1 if the invariant set is empty, 0 if unknown\n";
00365         out << "; A - 1 if this is an attractor, 0 if not or unknown\n";
00366         out << "; W - 1 if the index is wrong (no isolation), 0 if good\n";
00367         out << "; S - 1 if the index computation was skipped, 0 otherwise\n";
00368         out << "; N - the number of cubes in the Morse set\n";
00369         out << "; Q - a representative cube\n";
00370         out << "; I - the Conley index encoded in numbers\n";
00371 
00372         // write the Conley index and other information for each Morse set
00373         for (int n = 0; n < nSets; ++ n)
00374         {
00375                 out << "; -----------------------------------------------\n";
00376                 out << "M " << n << "\n";
00377                 out << "E " << (emptyInv [n] ? 1 : 0) << "\n";
00378                 out << "A " << (attractor [n] ? 1 : 0) << "\n";
00379                 out << "W " << (wrongIndex [n] ? 1 : 0) << "\n";
00380                 out << "S " << (skipped [n] ? 1 : 0) << "\n";
00381                 out << "N " << morseDec [n]. size () << "\n";
00382                 out << "Q " << morseDec [n] [0] << "\n";
00383                 out << "I " << morseDec. index (n) << "\n";
00384         }
00385 
00386         return 0;
00387 } /* IndexCache::write */
00388 
00389 
00390 #endif // _CMGRAPHS_INDCACHE_H_
00391 

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