compmdec.h

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////////////
00002 ///
00003 /// @file compmdec.h
00004 ///
00005 /// Computation of Morse decompositions.
00006 /// This file contains the definition of a function for the computation
00007 /// of a Morse decomposition for a given map, as well as several auxiliary
00008 /// procedures necessary to compute this Morse decomposition in an efficient
00009 /// way by restricting the phase space to the invariant part computed
00010 /// with respect to a coarser grid. The computed Morse decomposition
00011 /// is processed further in order to eliminate spurious Morse sets
00012 /// wherever possible.
00013 ///
00014 /// @author Pawel Pilarczyk
00015 ///
00016 /////////////////////////////////////////////////////////////////////////////
00017 
00018 // Copyright (C) 1997-2008 by Pawel Pilarczyk.
00019 //
00020 // This file is part of my research software package.  This is free software;
00021 // you can redistribute it and/or modify it under the terms of the GNU
00022 // General Public License as published by the Free Software Foundation;
00023 // either version 2 of the License, or (at your option) any later version.
00024 //
00025 // This software is distributed in the hope that it will be useful,
00026 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00027 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00028 // GNU General Public License for more details.
00029 //
00030 // You should have received a copy of the GNU General Public License along
00031 // with this software; see the file "license.txt".  If not, write to the
00032 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00033 // MA 02111-1307, USA.
00034 
00035 // Started on February 12, 2007. Last revision: April 14, 2008.
00036 
00037 
00038 #ifndef _CMGRAPHS_COMPMDEC_H_
00039 #define _CMGRAPHS_COMPMDEC_H_
00040 
00041 
00042 // include some standard C++ header files
00043 #include <algorithm>
00044 #include <new>
00045 #include <iostream>
00046 #include <iomanip>
00047 #include <string>
00048 #include <fstream>
00049 #include <sstream>
00050 #include <cstdio>
00051 
00052 // include selected header files from the CHomP library
00053 #include "chomp/system/textfile.h"
00054 #include "chomp/cubes/pointset.h"
00055 #include "chomp/struct/digraph.h"
00056 #include "chomp/struct/multitab.h"
00057 #include "chomp/system/timeused.h"
00058 
00059 // include local header files
00060 #include "config.h"
00061 #include "typedefs.h"
00062 #include "conindex.h"
00063 #include "morsedec.h"
00064 #include "indcache.h"
00065 #include "invpart.h"
00066 #include "utils.h"
00067 
00068 
00069 // --------------------------------------------------
00070 // ---- connection recorders for inclusionGraph -----
00071 // --------------------------------------------------
00072 
00073 /// A simple class for storing connections in an array that uses
00074 /// the "multitable" class.
00075 class TConnTable
00076 {
00077 public:
00078         /// The constructor.
00079         TConnTable (int _n, chomp::homology::multitable
00080                 <chomp::homology::multitable<int> > &_connections,
00081                 chomp::homology::multitable<int> &_conncount,
00082                 const int *_numTranslate);
00083 
00084         /// Adds an element v at the connection from source to target.
00085         void operator () (int source, int target, int v);
00086 
00087 private:
00088         /// The number of vertices between the connections are recorded.
00089         int n;
00090 
00091         /// The tables of connectiong orbits; those for v -> w are stored
00092         /// at the index n * v + w.
00093         chomp::homology::multitable<chomp::homology::multitable<int> >
00094                 &connections;
00095 
00096         /// The numbers of elements in each connecting orbit.
00097         chomp::homology::multitable<int> &conncount;
00098 
00099         /// The translation table for vertex numbers in the connections.
00100         const int *numTranslate;
00101 
00102 }; /* class TConnTable */
00103 
00104 inline TConnTable::TConnTable (int _n,
00105         chomp::homology::multitable<chomp::homology::multitable<int> > &
00106         _connections, chomp::homology::multitable<int> &_conncount,
00107         const int *_numTranslate):
00108         n (_n), connections (_connections), conncount (_conncount),
00109         numTranslate (_numTranslate)
00110 {
00111         int maxcount = n * n;
00112         for (int i = 0; i < maxcount; ++ i)
00113                 conncount [i] = 0;
00114         return;
00115 } /* TConnTable::TConnTable */
00116 
00117 inline void TConnTable::operator () (int source, int target, int v)
00118 {
00119         int pos = n * source + target;
00120         connections [pos] [conncount [pos] ++] = numTranslate [v];
00121         return;
00122 } /* TConnTable::operator () */
00123 
00124 // --------------------------------------------------
00125 
00126 /// A simple class for storing connections in an array that uses
00127 /// the "multitable" class.
00128 class TConnMorse
00129 {
00130 public:
00131         /// The constructor.
00132         TConnMorse (theMorseDecompositionType &_morseDec,
00133                 const spcCubes &_X, const int *_numTranslate);
00134 
00135         /// Adds an element v at the connection from source to target.
00136         void operator () (int source, int target, int v);
00137 
00138 private:
00139         /// The Morse decomposition in which to record the connections.
00140         theMorseDecompositionType &morseDec;
00141 
00142         /// The set which contains cubes to add.
00143         const spcCubes &X;
00144 
00145         /// The translation table for vertex numbers in the connections.
00146         const int *numTranslate;
00147 
00148 }; /* class TConnMorse */
00149 
00150 inline TConnMorse::TConnMorse (theMorseDecompositionType &_morseDec,
00151         const spcCubes &_X, const int *_numTranslate):
00152         morseDec (_morseDec), X (_X), numTranslate (_numTranslate)
00153 {
00154         return;
00155 } /* TConnMorse::TConnMorse */
00156 
00157 inline void TConnMorse::operator () (int source, int target, int v)
00158 {
00159         morseDec. addconn (source, target, X [numTranslate [v]]);
00160         return;
00161 } /* TConnMorse::operator () */
00162 
00163 
00164 // --------------------------------------------------
00165 // ------------ Conley index computation ------------
00166 // --------------------------------------------------
00167 
00168 /// This small auxiliary procedure sets a dummy Conley index to the given
00169 /// Morse set. The Conley index is set to be trivial, unless it is requested
00170 /// that a number of a Betti number is provided to be set to 1.
00171 inline void setDummyIndex (theMorseDecompositionType &morseDec, int n,
00172         int nonzero = -1)
00173 {
00174         int betti [spaceDim + 1];
00175         for (int i = 0; i <= spaceDim; ++ i)
00176                 betti [i] = (i == nonzero) ? 1 : 0;
00177         theConleyIndexType ind;
00178         ind. define (betti, spaceDim);
00179         morseDec. setindex (n, ind);
00180         return;
00181 } /* setDummyIndex */
00182 
00183 /// Verifies that the provided Morse set can be used as a basis
00184 /// for a Conley index pair and computes the Conley index.
00185 /// If this verification fails then subdivides the Morse set
00186 /// and repeats the procedure restricted to the invariant part of the set.
00187 /// Returns 0 if succeeds or -1 in the case of failure.
00188 /// Makes a note of having reached the subdivision limit or having come
00189 /// across empty invariant part in the provided variable
00190 /// which is set to 1 in the former case and 0 in the latter
00191 /// (otherwise it is not modified).
00192 /// If a problem with isolation is encountered then sets "noIsolation" to 1.
00193 /// If the index pair is computed then sets the value of the variable
00194 /// which remembers if this is an attractor (empty exit set) or not.
00195 inline int computeConleyIndex (theMorseDecompositionType &morseDec, int n,
00196         const double *offset, const double *width,
00197         int subdivDepth, const theMapType &theMap,
00198         const theCubMapType &theCubMap0, const theCubMapType &theCubMap1,
00199         int &subdivNonemptyInv, int &noIsolation, int &attractor)
00200 {
00201         using chomp::homology::sbug;
00202 
00203         // check the images to make sure that all of them are contained
00204         // in the rectangular region of the given depth
00205         spcCubes X;
00206         for (int subdivisions = 0;; ++ subdivisions)
00207         {
00208                 // determine the combinatorial map to use
00209                 theCubMapType subdivCubMap (offset, width,
00210                         1 << (subdivDepth + subdivisions), theMap);
00211                 subdivCubMap. cache = false;
00212                 const theCubMapType &theCubMap =
00213                         (subdivisions > 1) ? subdivCubMap :
00214                         (subdivisions ? theCubMap1 : theCubMap0);
00215                 bool crop = theCubMap. cropping;
00216 
00217                 // restrict the set to its invariant part if necessary
00218                 if (subdivisions)
00219                 {
00220                         try
00221                         {
00222                                 int result = invariantPart (X, theCubMap);
00223                                 if (result < 0)
00224                                 {
00225                                         subdivNonemptyInv = 1;
00226                                         return -1;
00227                                 }
00228                                 if (X. empty ())
00229                                 {
00230                                         setDummyIndex (morseDec, n);
00231                                         subdivNonemptyInv = 0;
00232                                         return 0;
00233                                 }
00234                         }
00235                         catch (const char *msg)
00236                         {
00237                                 subdivNonemptyInv = 1;
00238                                 sbug << "Failed: " << msg << "\n";
00239                                 sbug << "Failure: Unable to compute Inv.\n";
00240                                 return -1;
00241                         }
00242                 }
00243 
00244                 // determine the set of cubes for which to compute the index
00245                 const spcCubes &theSet = subdivisions ? X : morseDec [n];
00246 
00247                 // try computing the Conley index using this set
00248                 // as a basis for the index pair
00249                 try
00250                 {
00251                         // create an index pair object
00252                         theIndexPairType P (theCubMap);
00253 
00254                         // add cubes to the core part of the index pair
00255                         int size = theSet. size ();
00256                         for (int i = 0; i < size; ++ i)
00257                                 P. add (theSet [i]);
00258 
00259                         // compute the map on the index pair
00260                         theCubMap. cropping = true;
00261                         theCubMap. cropped = false;
00262                         P. compute ();
00263                         theCubMap. cropping = crop;
00264 
00265                         // if no cropping took place then compute the index
00266                         if (ignoreIsolationForConleyIndex ||
00267                                 !theCubMap. cropped)
00268                         {
00269                                 // verify if this is an attractor
00270                                 attractor = P. countExit () ? 0 : 1;
00271 
00272                                 // create the Conley index object
00273                                 theConleyIndexType ind;
00274                                 ind. setIndexPair (&P);
00275 
00276                                 // compute the index
00277                                 ind. compute ();
00278                                 ind. setIndexPair (0);
00279 
00280                                 // set the index of the Morse set
00281                                 morseDec. setindex (n, ind);
00282                                 return 0;
00283                         }
00284                 }
00285                 catch (const char *msg)
00286                 {
00287                         theCubMap. cropping = crop;
00288                         sbug << "Failed: " << msg << "\n";
00289                 }
00290 
00291                 // if the maximal subdivision level was reached then cancel
00292                 if (subdivisions == refineDepth)
00293                 {
00294                         sbug << "Failure: Max refinement depth " <<
00295                                 refineDepth << " reached.\n";
00296                         subdivNonemptyInv = 1;
00297                         if (theCubMap. cropped)
00298                                 noIsolation = 1;
00299                         return -1;
00300                 }
00301 
00302                 // determine the maximal allowed size of a set to refine
00303                 int maxRefineSize =
00304                         subdivisions? maxRefineSize0 : maxRefineSize1;
00305 
00306                 // if the set is too large to subdivide then cancel
00307                 if (theSet. size () > maxRefineSize)
00308                 {
00309                         sbug << "Failure: The set size " <<
00310                                 theSet. size () << " is beyond the max "
00311                                 "allowed " << maxRefineSize << ".\n";
00312                         subdivNonemptyInv = 1;
00313                         if (theCubMap. cropped)
00314                                 noIsolation = 1;
00315                         return -1;
00316                 }
00317 
00318                 // subdivide the set
00319                 sbug << "- subdiv " << (subdivDepth + subdivisions + 1) <<
00320                         ": " << theSet. size () << " -> ";
00321                 spcCubes Y;
00322                 subdivideCubes (theSet, Y);
00323                 spcCubes emptySet;
00324                 X = emptySet;
00325                 X. swap (Y);
00326                 sbug << X. size () << " ";
00327         }
00328 
00329         return -1;
00330 } /* computeConleyIndex */
00331 
00332 
00333 // --------------------------------------------------
00334 // ----------- inv & Morse decomposition ------------
00335 // --------------------------------------------------
00336 
00337 /// Computes a Conley-Morse decomposition of ChainRecSet (X).
00338 /// The combinatorial cubical multivalued map F is encoded
00339 /// in the directed graph provided.
00340 /// The Morse decomposition structure must be initially empty.
00341 /// The areguments "offset", "width", "subdivDepth" and "theMap"
00342 /// are only necessary for the purpose of refining trivial Morse sets.
00343 /// The global constants "refineDepth", "maxRefineSize0" and "maxRefineSize1"
00344 /// determine, respectively, the maximal allowed refinement depth,
00345 /// and the maximal size of a cubical set which is refined if necessary.
00346 /// Further simplification of the computed Morse decomposition is done
00347 /// by joining Morse sets (see the description in "morsedec.h" for details).
00348 /// If requested, the Conley indices of Morse sets which have at least
00349 /// the given number of boxes are not computed (they are set to be trivial).
00350 /// If a file name prefix is nonempty then an attempt is being made
00351 /// to read cached Morse decomposition information from a file.
00352 template <class typeCubes, class typeMorseDec>
00353 void invMorseDec (const typeCubes &X, const chomp::homology::diGraph<> &g,
00354         typeMorseDec &morseDec,
00355         const double *offset, const double *width, int subdivDepth,
00356         const theMapType &theMap,
00357         const theCubMapType &theCubMap0, const theCubMapType &theCubMap1,
00358         int skipIndices,
00359         const std::string &cacheFileName, bool &morseDecComputed,
00360         std::vector<int> &wrongIndices, std::vector<int> &skippedIndices,
00361         std::vector<int> &attractors, bool connOrbits,
00362         const double *leftMapParam, const double *rightMapParam,
00363         int paramCount)
00364 {
00365         using chomp::homology::sbug;
00366         using chomp::homology::diGraph;
00367         using chomp::homology::multitable;
00368 
00369         // do nothing if the set X is empty
00370         if (X. empty ())
00371                 return;
00372 
00373         // determine if it is necessary to compute the connecting orbits
00374         // in terms of cubical sets
00375         bool computeconn = connOrbits || (maxJoinSize > 0);
00376 
00377         // compute the components of the chain recurrent set of the graph
00378         multitable<int> compVertices, compEnds;
00379         diGraph<> *sccAddr = 0;
00380         diGraph<> *transpAddr = /*(savebasmin || savebasmax) ? &gT :*/ 0;
00381         int nSets = chomp::homology::SCC (g, compVertices, compEnds,
00382                 sccAddr, transpAddr);
00383 
00384         // create the Morse decomposition data structure
00385         // and count the number of cubes in the SCC
00386         morseDec. setnumber (nSets);
00387         int countSCCcubes = 0;
00388         for (int n = 0; n < nSets; ++ n)
00389         {
00390                 // determine the vertex range of this set
00391                 int beginVertex = n ? compEnds [n - 1] : 0;
00392                 int endVertex = compEnds [n];
00393                 countSCCcubes += endVertex - beginVertex;
00394 
00395                 // add the cubes to the Morse set
00396                 for (int i = beginVertex; i < endVertex; ++ i)
00397                         morseDec. add (n, X [compVertices [i]]);
00398         }
00399 
00400         // compute the connecting orbits for the Morse decomposition
00401         {
00402                 // collapse Morse sets to single vertices of a graph
00403                 int *newNumbers = computeconn ? new int [X. size ()] : 0;
00404                 diGraph<> collapsed;
00405                 chomp::homology::collapseVertices (g, nSets, compVertices,
00406                         compEnds, collapsed, newNumbers);
00407 
00408                 // prepare a translation table for vertex numbers
00409                 int *oldNumbers = computeconn ?
00410                         new int [X. size () - countSCCcubes + nSets] : 0;
00411                 if (oldNumbers)
00412                 {
00413                         for (int i = 0; i < X. size (); ++ i)
00414                                 oldNumbers [newNumbers [i]] = i;
00415                 }
00416                 if (newNumbers)
00417                         delete [] newNumbers;
00418 
00419                 // compute the connecting orbits and the connection graph
00420                 diGraph<> connGraph;
00421                 TConnMorse conn (morseDec, X, oldNumbers);
00422                 if (computeconn)
00423                 {
00424                         chomp::homology::inclusionGraph (collapsed, nSets,
00425                                 connGraph, conn);
00426                 }
00427                 else
00428                 {
00429                         chomp::homology::inclusionGraph (collapsed, nSets,
00430                                 connGraph);
00431                 }
00432                 if (oldNumbers)
00433                         delete [] oldNumbers;
00434 
00435                 // store the connections in the Morse decomposition structure
00436                 for (int v = 0; v < nSets; ++ v)
00437                 {
00438                         int nEdges = connGraph. countEdges (v);
00439                         for (int e = 0; e < nEdges; ++ e)
00440                         {
00441                                 int w = connGraph. getEdge (v, e);
00442                                 morseDec. addconn (v, w);
00443                         }
00444                 }
00445         }
00446 
00447         // prepare file names if necessary
00448         bool cacheIndices = !cacheFileName. empty ();
00449         std::string indFileNameStr = cacheFileName;
00450         const char *indFileName = indFileNameStr. c_str ();
00451         std::string lockFileNameStr = cacheFileName + ".lock";
00452         const char *lockFileName = lockFileNameStr. c_str ();
00453 
00454         // retrieve the Conley indices from cache if possible
00455         bool cachedAvailable = false;
00456         IndexCache cached (nSets);
00457         if (cacheIndices && fileExists (indFileName))
00458         {
00459                 if (fileExists (lockFileName))
00460                         sbug << "! Skipping cached indices (locked).\n";
00461                 else if (cached. read (indFileName, morseDec) != 0)
00462                         sbug << "! Error while reading cached indices.\n";
00463                 else
00464                 {
00465                         sbug << "[using cached Conley indices]\n";
00466                         cachedAvailable = true;
00467                 }
00468         }
00469         morseDecComputed = !cachedAvailable;
00470 
00471         // compute the Conley indices of the Morse sets
00472         spcCubes wrongCubes;
00473         spcCubes attrCubes;
00474         spcCubes skipCubes;
00475         std::vector<int> subdivNonemptyInv (nSets, -1);
00476         for (int n = 0; n < nSets; ++ n)
00477         {
00478                 if (cachedAvailable)
00479                 {
00480                         if (cached. wrongIndex [n])
00481                                 wrongCubes. add (morseDec [n] [0]);
00482                         if (cached. attractor [n])
00483                                 attrCubes. add (morseDec [n] [0]);
00484                         if (cached. skipped [n])
00485                                 skipCubes. add (morseDec [n] [0]);
00486                         continue;
00487                 }
00488 
00489                 // skip the computation of the Conley index if requested to
00490                 if ((skipIndices > 0) &&
00491                         (morseDec [n]. size () >= skipIndices))
00492                 {
00493                         sbug << "* Skipping ConIndex (" << n << ").\n";
00494                         setDummyIndex (morseDec, n);
00495                         subdivNonemptyInv [n] = 1;
00496                         cached. skipped [n] = true;
00497                         skipCubes. add (morseDec [n] [0]);
00498                 }
00499                 // or compute the Conley index
00500                 else
00501                 {
00502                         sbug << "* Computing the Conley index "
00503                                 "of the Morse set no. " << n << " (" <<
00504                                 morseDec [n]. size () << " cubes)...\n";
00505                         int noIsolation = -1;
00506                         int attractor = -1;
00507                         int result = computeConleyIndex (morseDec, n,
00508                                 offset, width, subdivDepth, theMap,
00509                                 theCubMap0, theCubMap1,
00510                                 subdivNonemptyInv [n], noIsolation,
00511                                 attractor);
00512                         if (attractor > 0)
00513                         {
00514                                 cached. attractor [n] = true;
00515                                 attrCubes. add (morseDec [n] [0]);
00516                         }
00517                         if (((result < 0) || (noIsolation > 0)) &&
00518                                 setConleyIndex (morseDec, n, subdivDepth,
00519                                 leftMapParam, rightMapParam, paramCount))
00520                         {
00521                                 sbug << "* The index was set to an apriori "
00522                                         "known one.\n";
00523                         }
00524                         else if (result < 0)
00525                         {
00526                                 sbug << "* Failed to compute the index.\n";
00527                                 setDummyIndex (morseDec, n);
00528                                 cached. wrongIndex [n] = true;
00529                                 wrongCubes. add (morseDec [n] [0]);
00530                         }
00531                         else if (noIsolation > 0)
00532                         {
00533                                 sbug << "* No isolation detected. The index "
00534                                         "could not be computed reliably.\n";
00535                                 cached. wrongIndex [n] = true;
00536                                 wrongCubes. add (morseDec [n] [0]);
00537                         }
00538                         else
00539                         {
00540                                 sbug << "* The computed index is " <<
00541                                         (morseDec. trivial (n) ?
00542                                         "" : "non") << "trivial.\n";
00543                         }
00544                 }
00545         }
00546 
00547         // make a note of the Morse sets whose invariant part is empty
00548         std::vector<int> passThru;
00549         for (int n = 0; n < nSets; ++ n)
00550         {
00551                 // if the cached result is available then use it
00552                 if (cachedAvailable)
00553                 {
00554                         if (cached. emptyInv [n])
00555                                 passThru. push_back (n);
00556                         continue;
00557                 }
00558 
00559                 // if refinements were already tried and failed then skip it
00560                 if (subdivNonemptyInv [n] == 1)
00561                         continue;
00562 
00563                 // if refinements have already proved that inv is empty
00564                 // then make a note of it
00565                 if (subdivNonemptyInv [n] == 0)
00566                 {
00567                         passThru. push_back (n);
00568                         cached. emptyInv [n] = true;
00569                         continue;
00570                 }
00571 
00572                 // if the Conley index is nontrivial then inv is nonempty
00573                 if (!morseDec. trivial (n))
00574                         continue;
00575 
00576                 // if the size of the set is too large then skip it
00577                 if (morseDec [n]. size () > maxRefineSize0)
00578                         continue;
00579 
00580                 // refine the set and check if its inv is nonempty
00581                 sbug << "Refining the set no. " << n << " (" <<
00582                         morseDec [n]. size () << " cubes)...\n";
00583                 if (checkEmptyInv (morseDec [n], finalDepth,
00584                         offset, width, theMap, theCubMap0, theCubMap1))
00585                 {
00586                         sbug << "Empty inv. The set will be removed.\n";
00587                         passThru. push_back (n);
00588                         cached. emptyInv [n] = true;
00589                 }
00590                 else
00591                 {
00592                         sbug << "Invariant part may be nonempty.\n";
00593                 }
00594         }
00595 
00596         // save the Conley indices and the information on empty inv
00597         // to a file if they were computed and a file name prefix is provided
00598         if (cacheIndices && !cachedAvailable && !fileExists (indFileName) &&
00599                 !fileExists (lockFileName))
00600         {
00601                 // create the lock file
00602                 std::ofstream lockFile (lockFileName);
00603                 lockFile. close ();
00604 
00605                 // write the cached index information
00606                 cached. write (indFileName, morseDec);
00607 
00608                 // remove the lock file
00609                 std::remove (lockFileName);
00610         }
00611 
00612         // remove Morse sets whose invariant part is proven to be empty
00613         for (int i = passThru. size () - 1; i >= 0; -- i)
00614         {
00615                 morseDec. passthru (passThru [i]);
00616         }
00617 
00618         // manipulate the Morse decomposition to make it a coarser one
00619         if (maxJoinSize > 0)
00620         {
00621                 sbug << "* " << morseDec. count () << " Morse sets; sizes: ";
00622                 for (int i = 0; i < morseDec. count (); ++ i)
00623                         sbug << (i ? " " : "") << morseDec [i]. size ();
00624                 sbug << "\n! Joining trivial Morse sets (size: " <<
00625                         maxJoinSize << ", conn: " << maxJoinConnection <<
00626                         ", dist: " << maxJoinDistance << ")...\n";
00627                 morseDec. jointrivial (maxJoinSize, maxJoinConnection,
00628                         maxJoinDistance);
00629         }
00630 
00631         // remember the new number of Morse sets in the Morse decomposition
00632         nSets = morseDec. count ();
00633 
00634         // determine the numbers of new Morse sets whose indices could not
00635         // be computed
00636         for (int i = 0; i < wrongCubes. size (); ++ i)
00637         {
00638                 int n = 0;
00639                 while ((n < nSets) && !morseDec [n]. check (wrongCubes [i]))
00640                         ++ n;
00641                 if (n < nSets)
00642                         wrongIndices. push_back (n);
00643                 else
00644                 {
00645                         wrongIndices. push_back (-1);
00646                         sbug << "Note: A Morse set with a wrong index "
00647                                 "could not be identified.\n";
00648                 }
00649         }
00650 
00651         // determine the numbers of new Morse sets whose indices were skipped
00652         for (int i = 0; i < skipCubes. size (); ++ i)
00653         {
00654                 int n = 0;
00655                 while ((n < nSets) && !morseDec [n]. check (skipCubes [i]))
00656                         ++ n;
00657                 if (n < nSets)
00658                         skippedIndices. push_back (n);
00659                 else
00660                 {
00661                         skippedIndices. push_back (-1);
00662                         sbug << "Note: A Morse set whose index was skipped "
00663                                 "could not be identified.\n";
00664                 }
00665         }
00666 
00667         // determine the numbers of new Morse sets which are attractors
00668         for (int i = 0; i < attrCubes. size (); ++ i)
00669         {
00670                 int n = 0;
00671                 while ((n < nSets) && !morseDec [n]. check (attrCubes [i]))
00672                         ++ n;
00673                 if (n < nSets)
00674                         attractors. push_back (n);
00675                 else
00676                 {
00677                         attractors. push_back (-1);
00678                         sbug << "Note: A Morse set which is an attractor "
00679                                 "could not be identified.\n";
00680                 }
00681         }
00682 
00683         // show a summary information
00684         sbug << "* " << morseDec. count () << " Morse sets [" <<
00685                 attrCubes. size () << " attractor(s)]; sizes: ";
00686         for (int i = 0; i < morseDec. count (); ++ i)
00687                 sbug << (i ? " " : "") << morseDec [i]. size ();
00688         sbug << "\n";
00689 
00690         return;
00691 } /* invMorseDec */
00692 
00693 
00694 // --------------------------------------------------
00695 // -------------- Morse Decomposition ---------------
00696 // --------------------------------------------------
00697 
00698 /// Computes the Morse decomposition using all the pre- and postprocessing.
00699 /// The target Morse decomposition object must be already initialized
00700 /// with the right map which is to be used to compute the Conley indices
00701 /// of the Morse sets.
00702 /// If a file name prefix is nonempty then an attempt is being made
00703 /// to read cached Morse decomposition information from a file.
00704 inline theMorseDecompositionType *computeMorseDecomposition
00705         (const theMapType &theMap,
00706         const theCubMapType theCubMap0, const theCubMapType theCubMap1,
00707         const double *offset, const double *width, int skipIndices,
00708         const std::string &cacheFileName, bool &morseDecComputed,
00709         std::vector<int> &wrongIndices, std::vector<int> &skippedIndices,
00710         std::vector<int> &attractors, bool connOrbits,
00711         const double *leftMapParam, const double *rightMapParam,
00712         int paramCount)
00713 {
00714         using chomp::homology::sbug;
00715         using chomp::homology::diGraph;
00716         using chomp::homology::multitable;
00717 
00718         // create an empty Morse decomposition
00719         theMorseDecompositionType *morseDecPtr =
00720                 new theMorseDecompositionType (theCubMap0);
00721         theMorseDecompositionType &morseDec = *morseDecPtr;
00722 
00723         // create a cubical set with one cube
00724         spcCoord zero [spaceDim];
00725         for (int i = 0; i < spaceDim; ++ i)
00726                 zero [i] = 0;
00727         spcCubes X;
00728         X. add (spcCube (zero, spaceDim));
00729 
00730         // make the initial subdivision(s)
00731         for (int subdivDepth = 1; subdivDepth <= finalDepth; ++ subdivDepth)
00732         {
00733                 // subdivide all the cubes in X
00734                 {
00735                         spcCubes Y;
00736                         subdivideCubes (X, Y);
00737                         X. swap (Y);
00738                 }
00739 
00740                 // if the initial subdivision depth has not been reached yet
00741                 // then skip the computation of the invariant part
00742                 if (subdivDepth < initialDepth)
00743                         continue;
00744 
00745                 // indicate the number of cubes after the subdivision
00746                 sbug << "Depth " << subdivDepth << ": " <<
00747                         X. size () << ". ";
00748 
00749                 // prepare a local multivalued cubical map
00750                 // at this subdivision depth
00751                 theCubMapType localCubMap (offset, width,
00752                         1 << subdivDepth, theMap);
00753 
00754                 // extract the multivalued cubical map
00755                 // from the Morse decomposition if this is the final depth
00756                 const theCubMapType &theCubMap =
00757                         (subdivDepth == finalDepth) ?
00758                         theCubMap0 : localCubMap;
00759 
00760                 // compute the graph of the multivalued cubical map on X
00761                 sbug << "F... ";
00762                 diGraph<> g;
00763                 computeMapGraph (X, g, theCubMap);
00764 
00765                 // show the average size of the image of a cube
00766                 int avgImgSize = g. countEdges () /
00767                         (X. size () ? X. size () : 1);
00768                 sbug << "[avg " << avgImgSize << "] ";
00769 
00770                 // compute the requested Morse decomposition
00771                 // if this is the final subdivision level
00772                 if (subdivDepth == finalDepth)
00773                 {
00774                         sbug << "Morse dec...\n";
00775                         invMorseDec (X, g, morseDec,
00776                                 offset, width, finalDepth,
00777                                 theMap, theCubMap0, theCubMap1,
00778                                 skipIndices, cacheFileName, morseDecComputed,
00779                                 wrongIndices, skippedIndices, attractors,
00780                                 connOrbits, leftMapParam, rightMapParam,
00781                                 paramCount);
00782                         break;
00783                 }
00784 
00785                 // compute the invariant part of the map on X
00786                 sbug << "Inv... ";
00787                 invariantPart (X, g);
00788                 sbug << X. size () << " left.\n";
00789 
00790                 // save the result to a file (for pictures for the paper)
00791                 if (false)
00792                 {
00793                         std::ostringstream fstr;
00794                         fstr << "_inv" << subdivDepth;
00795                         std::string filename = fstr. str ();
00796                         std::ofstream f (filename. c_str ());
00797                         f << "; Inv(X) at level " << subdivDepth << ".\n";
00798                         f << X << "\n";
00799                         sbug << "Inv(X) saved to " << filename << ".\n";
00800                 }
00801         }
00802 
00803         return morseDecPtr;
00804 } /* computeMorseDecomposition */
00805 
00806 
00807 #endif // _CMGRAPHS_COMPMDEC_H_
00808 
00809 

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