morsedec.h

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////////////
00002 ///
00003 /// @file morsedec.h
00004 ///
00005 /// Morse decompositions.
00006 /// This file contains the definition of a Morse decomposition class
00007 /// for a discrete dynamical system represented by a combinatorial
00008 /// cubical multivalued map. It also contains the interface to CHomP
00009 /// for the purpose of computing the Conley index of each Morse set.
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 January 3, 2007. Last revision: February 29, 2008.
00033 
00034 
00035 #ifndef _CMGRAPHS_MORSEDEC_H_
00036 #define _CMGRAPHS_MORSEDEC_H_
00037 
00038 
00039 // include some standard C++ header files
00040 #include <iostream>
00041 #include <sstream>
00042 #include <algorithm>
00043 
00044 // include selected header files from the CHomP library
00045 #include "chomp/system/textfile.h"
00046 #include "chomp/homology/homology.h"
00047 #include "chomp/struct/digraph.h"
00048 
00049 // include selected header files from the CAPD library
00050 #include "interval/doubleInterval.h"
00051 
00052 // include local header files
00053 #include "conindex.h"
00054 
00055 
00056 // --------------------------------------------------
00057 // --------------- MorseDecomposition ---------------
00058 // --------------------------------------------------
00059 
00060 /// The Morse decoposition class. This is a template whose parameters
00061 /// define a class used to compute the combinatorial cubical multivalued map
00062 /// on Morse sets, a class which corresponds to a single cube,
00063 /// and a class which is used to keep sets of cubes
00064 /// (the hashed set by default).
00065 template <class mapcomp, class cubetype,
00066         class cubsettype = chomp::homology::hashedset<cubetype> >
00067 class MorseDecomposition
00068 {
00069         /// The type of a combinatorial cubical multivalued map.
00070         typedef chomp::homology::mvmap<cubetype,cubetype> cubmaptype;
00071 public:
00072         /// The type of the map computation class.
00073         typedef mapcomp MapCompType;
00074 
00075         /// The type of a single cube.
00076         typedef cubetype CubeType;
00077 
00078         /// The type of a set of cubes used to store each Morse set.
00079         typedef cubsettype CubSetType;
00080 
00081         /// The type of the index pair.
00082         typedef IndexPair<mapcomp,cubetype,cubsettype> PairType;
00083 
00084         /// The type of the Conley index.
00085         typedef ConleyIndex<PairType> IndexType;
00086 
00087         /// The default constructor.
00088         MorseDecomposition (const mapcomp &_M = mapcomp ());
00089 
00090         /// The destructor.
00091         ~MorseDecomposition ();
00092 
00093         /// The copy constructor.
00094         MorseDecomposition (const MorseDecomposition &m);
00095 
00096         /// The assignment operator.
00097         MorseDecomposition<mapcomp,cubetype,cubsettype> &operator =
00098                 (const MorseDecomposition<mapcomp,cubetype,cubsettype> &m);
00099 
00100         // --- the combinatorial cubical multivalued map ---
00101         
00102         /// The map computation class.
00103         const mapcomp &M;
00104 
00105         // --- Morse Sets ---
00106         
00107         /// Changes (increases or decreases) the number of Morse sets.
00108         int setnumber (int n);
00109 
00110         /// Adds a cube to the given Morse set and increases the number
00111         /// of Morse sets if necessary.
00112         int add (int n, const cubetype &q);
00113 
00114         /// Returns the number of Morse sets.
00115         int count () const;
00116 
00117         /// Returns the n-th Morse set. Throws an exception in case
00118         /// of a wrong number.
00119         const cubsettype &operator [] (int n) const;
00120 
00121         /// Returns the approximate distance between the two Morse sets.
00122         /// Warning: This computation may take some time for large sets.
00123         /// Note: The values returned by this function are tabulated, and
00124         /// are not updated when the Morse sets are modified with the 'add'
00125         /// function. Call with (-1,-1) to reset the tabulation.
00126         int distance (int n, int m) const;
00127 
00128         // --- Connections ---
00129 
00130         /// Adds a connection between the given Morse sets without adding
00131         /// any cubes to this connection (like in a direct connection).
00132         int addconn (int n, int m);
00133 
00134         /// Adds a cube to the connecting orbit between the given Morse sets.
00135         int addconn (int n, int m, const cubetype &q);
00136 
00137         /// Checks whether there exists a connection between given sets.
00138         /// Returns true if yes, false if no or wrong numbers.
00139         bool connected (int n, int m) const;
00140 
00141         /// Returns the connection between the given sets.
00142         /// Throws an exception if there is no connection or wrong numbers.
00143         const cubsettype &connection (int n, int m) const;
00144 
00145         /// Returns the approximate maximal distance of a cube in the orbit
00146         /// that connects the sets n and m (in either direction) from the
00147         /// k-th Morse set, i.e., how far the orbit is from the set.
00148         /// Note: This computation may take some time for large sets.
00149         int distance (int n, int m, int k) const;
00150 
00151         /// Returns the appropriate maximal distance between cubes that are
00152         /// contained in the Morse set n and the connecting orbit n-m or m-n.
00153         /// Note: The values returned by this function are tabulated, and
00154         /// are not updated when the Morse sets are modified with the 'add'
00155         /// function or when the connecting orbits are modified with the
00156         /// 'addconn' function. Call with (-1,-1) to reset the tabulation.
00157         int conndistance (int n, int m) const;
00158 
00159         /// Creates a graph representation of the Morse decomposition.
00160         /// Each Morse set corresponds to a vertex, and each connecting orbit
00161         /// gives rise to a corresponding edge.
00162         /// The graph given as an argument must be initially empty.
00163         int makegraph (chomp::homology::diGraph<> &g) const;
00164 
00165         // --- the Conley Indices of the Morse Components ---
00166 
00167         /// Computes the Conley index of the given Morse set.
00168         const IndexType &compute (int n);
00169 
00170         /// Computes the Conley indices of all the Morse sets.
00171         int compute ();
00172 
00173         /// Verifies if the Conley index for the given Morse set has been
00174         /// already computed.
00175         bool computed (int n) const;
00176 
00177         /// Retrieves the previously computed Conley index of the given
00178         /// Morse set. Throws an exception if the index has not yet
00179         /// been computed. Note that if the Morse set is chaned, then its
00180         /// index should be computed again using one of the functions above.
00181         const IndexType &index (int n) const;
00182 
00183         /// Sets the index of the given Morse set to the apriori known one.
00184         /// Does not compute it, but verifies if it is nontrivial.
00185         const IndexType &setindex (int n, const typename MorseDecomposition
00186                 <mapcomp,cubetype,cubsettype>::IndexType &ind);
00187 
00188         /// Returns true if the Conley index of the given Morse set is
00189         /// trivial, and false if either nontrivial or not yet computed.
00190         bool trivial (int n) const;
00191 
00192         // --- operations on entire Morse decompositions ---
00193 
00194         /// Computes the set-wise intersection of two Morse decompositions.
00195         /// The Morse decomposition must be initially empty and different
00196         /// from the objects passed as arguments.
00197         void intersection
00198                 (const MorseDecomposition<mapcomp,cubetype,cubsettype> &m,
00199                 const MorseDecomposition<mapcomp,cubetype,cubsettype> &n);
00200 
00201         // --- joining sets ---
00202 
00203         /// Joins the two given Morse sets. Updates the connecting orbits.
00204         /// Resets the Conley index. The new Morse set replaces the n-th one,
00205         /// and the numbers of Morse sets beyond the m-th one are shifted
00206         /// downwards.
00207         int join (int n, int m);
00208 
00209         /// Make connecting orbits pass through the given Morse set,
00210         /// because its invariant part is in fact empty. The Morse set
00211         /// is deleted and its contents is included in connecting orbits.
00212         int passthru (int n);
00213 
00214         /// Joins small Morse sets with trivial indices with Morse sets
00215         /// whose indices are nontrivial. Only sets whose size, as well as
00216         /// the size of the connecting orbit is below the given limits are
00217         /// joined, provided their distance is also limited.
00218         int jointrivial (int maxsetsize, int maxconnsize, int maxdistance);
00219 
00220         // --- save to files / load from files ---
00221 
00222         /// Save the Morse sets and connecting orbits to files.
00223         /// Set numbers are attached to the given prefix.
00224         /// Connections are numbered N-M.
00225         int savetofiles (const char *prefix = 0);
00226 
00227         /// Load the Morse sets and connecting orbits from files.
00228         int loadfromfiles (const char *prefix = 0);
00229 
00230 private:
00231         /// The number of Morse sets.
00232         int nsets;
00233 
00234         /// The Morse sets.
00235         chomp::homology::multitable<cubsettype *> sets;
00236 
00237         /// The Conley indices of the Morse sets.
00238         chomp::homology::multitable<IndexType *> indices;
00239         
00240         /// The table that stores the information on whether the indices
00241         /// are trivial or not: -1 = unknown, 0 = trivial, 1 = nontrivial.
00242         chomp::homology::multitable<int> nontrivial;
00243 
00244         /// Connecting orbits from one set to another.
00245         /// There is no connection iff the pointer is zero.
00246         chomp::homology::multitable<chomp::homology::multitable<cubsettype *> >
00247                 conn;
00248 
00249         /// Tabulated distances between the Morse sets.
00250         mutable chomp::homology::multitable<chomp::homology::multitable<int> >
00251                 dist;
00252 
00253         /// Tabulated values of the function "conndistance".
00254         mutable chomp::homology::multitable<chomp::homology::multitable<int> >
00255                 distconn;
00256 
00257         /// Release the memory (used in the destructor and copy constructor).
00258         /// Optionally, delete only Morse decompositions data for Morse sets
00259         /// whose numbers are greater or equal the given number.
00260         void deleteall (int firstnumber, int lastnumber);
00261 
00262         /// Copy all the data (used in the copy constructor and operator =).
00263         void copyall (const MorseDecomposition &m);
00264 
00265         /// Add one Morse set and initialize its data.
00266         void addone ();
00267 
00268         /// Verifies if two Morse sets are adjacent to each other.
00269         /// Note: If both sets are large, then this can be time-consuming.
00270         bool adjacent (int n, int m, int margin = 0) const;
00271 
00272         /// Returns the approximate distance between the two cubical sets.
00273         /// If minimum is set to true, then computes the minimal distance
00274         /// between any pair of cubes, one taken from X, the other from Y.
00275         /// If minimum is set to false, then computes the maximal distance
00276         /// of any cube in X from the set Y, that is, how far X is from Y
00277         /// (warning: the latter relation is not symmetric!)
00278         /// Note: This computation may take some time for large sets.
00279         static int cubsetdistance (const cubsettype &X, const cubsettype &Y,
00280                 bool minimum);
00281 
00282 }; /* class MorseDecomposition */
00283 
00284 // --------------------------------------------------
00285 
00286 template <class mapcomp, class cubetype, class cubsettype>
00287 inline MorseDecomposition<mapcomp,cubetype,cubsettype>::MorseDecomposition
00288         (const mapcomp &_M): M (_M), nsets (0)
00289 {
00290         return;
00291 } /* MorseDecomposition::MorseDecomposition */
00292 
00293 template <class mapcomp, class cubetype, class cubsettype>
00294 inline void MorseDecomposition<mapcomp,cubetype,cubsettype>::deleteall
00295         (int firstnumber, int lastnumber)
00296 {
00297         int difference = lastnumber - firstnumber;
00298         if (difference <= 0)
00299                 return;
00300 
00301         for (int i = firstnumber; i < lastnumber; ++ i)
00302         {
00303                 // delete the sets
00304                 if (sets [i])
00305                 {
00306                         delete sets [i];
00307                         sets [i] = 0;
00308                 }
00309 
00310                 // delete the indices
00311                 if (indices [i])
00312                 {
00313                         delete indices [i];
00314                         indices [i] = 0;
00315                 }
00316         }
00317 
00318         for (int i = lastnumber; i < nsets; ++ i)
00319         {
00320                 // shift the sets
00321                 sets [i - difference] = sets [i];
00322                 sets [i] = 0;
00323 
00324                 // shift the indices
00325                 indices [i - difference] = indices [i];
00326                 indices [i] = 0;
00327                 
00328                 // shift the nontriviality of Morse sets
00329                 nontrivial [i - difference] = nontrivial [i];
00330         }
00331 
00332         // delete the connecting orbits and tabulated distances
00333         for (int i = 0; i < nsets; ++ i)
00334         {
00335                 // delete connections
00336                 for (int j = firstnumber; j < lastnumber; ++ j)
00337                 {
00338                         if (conn [i] [j])
00339                         {
00340                                 delete conn [i] [j];
00341                                 conn [i] [j] = 0;
00342                         }
00343                 }
00344 
00345                 // shift connections and tabulated distances
00346                 for (int j = lastnumber; j < nsets; ++ j)
00347                 {
00348                         conn [i] [j - difference] = conn [i] [j];
00349                         conn [i] [j] = 0;
00350                         dist [i] [j - difference] = dist [i] [j];
00351                         distconn [i] [j - difference] = distconn [i] [j];
00352                 }
00353         }
00354         for (int j = 0; j < nsets - difference; ++ j)
00355         {
00356                 // delete connections
00357                 for (int i = firstnumber; i < lastnumber; ++ i)
00358                 {
00359                         if (conn [i] [j])
00360                         {
00361                                 delete conn [i] [j];
00362                                 conn [i] [j] = 0;
00363                         }
00364                 }
00365 
00366                 // shift connections and tabulated distances
00367                 for (int i = lastnumber; i < nsets; ++ i)
00368                 {
00369                         conn [i - difference] [j] = conn [i] [j];
00370                         conn [i] [j] = 0;
00371                         dist [i - difference] [j] = dist [i] [j];
00372                         distconn [i - difference] [j] = distconn [i] [j];
00373                 }
00374         }
00375 
00376         // update the number of Morse sets
00377         nsets -= difference;
00378         return;
00379 } /* MorseDecomposition::deleteall */
00380 
00381 template <class mapcomp, class cubetype, class cubsettype>
00382 inline MorseDecomposition<mapcomp,cubetype,cubsettype>::~MorseDecomposition
00383         ()
00384 {
00385         deleteall (0, nsets);
00386         return;
00387 } /* MorseDecomposition::~MorseDecomposition */
00388 
00389 template <class mapcomp, class cubetype, class cubsettype>
00390 inline void MorseDecomposition<mapcomp,cubetype,cubsettype>::copyall
00391         (const MorseDecomposition<mapcomp,cubetype,cubsettype> &m)
00392 {
00393         // copy the number of Morse sets
00394         nsets = m. nsets;
00395 
00396         for (int i = 0; i < nsets; ++ i)
00397         {
00398                 // copy the Morse sets
00399                 if (m. sets [i])
00400                         sets [i] = new cubsettype (*(m. sets [i]));
00401                 else
00402                         sets [i] = 0;
00403 
00404                 // copy the Conley indices
00405                 if (m. indices [i])
00406                         indices [i] = new IndexType (*(m. indices [i]));
00407                 else
00408                         indices [i] = 0;
00409                 nontrivial [i] = m. nontrivial [i];
00410 
00411                 // copy the connecting orbits and tabulated distances
00412                 for (int j = 0; j < nsets; ++ j)
00413                 {
00414                         if (m. conn [i] [j])
00415                         {
00416                                 conn [i] [j] =
00417                                         new cubsettype (*(m. conn [i] [j]));
00418                         }
00419                         else
00420                                 conn [i] [j] = 0;
00421                         dist [i] [j] = m. dist [i] [j];
00422                         distconn [i] [j] = m. distconn [i] [j];
00423                 }
00424         }
00425         return;
00426 } /* MorseDecomposition::copyall */
00427 
00428 template <class mapcomp, class cubetype, class cubsettype>
00429 inline MorseDecomposition<mapcomp,cubetype,cubsettype>::MorseDecomposition
00430         (const MorseDecomposition<mapcomp,cubetype,cubsettype> &m): M (m. M)
00431 {
00432         copyall (m);
00433         return;
00434 } /* MorseDecomposition::MorseDecomposition */
00435 
00436 template <class mapcomp, class cubetype, class cubsettype>
00437 inline MorseDecomposition<mapcomp,cubetype,cubsettype> &
00438         MorseDecomposition<mapcomp,cubetype,cubsettype>::operator =
00439         (const MorseDecomposition<mapcomp,cubetype,cubsettype> &m)
00440 {
00441         // protection from "M = M;"
00442         if (this == &m)
00443                 return *this;
00444 
00445         // delete the currently allocated Morse sets and connecting orbits
00446         deleteall (0, nsets);
00447 
00448         // copy the Morse sets from the other decomposition
00449         copyall (m);
00450 
00451         return *this;
00452 } /* MorseDecomposition::operator = */
00453 
00454 template <class mapcomp, class cubetype, class cubsettype>
00455 inline void MorseDecomposition<mapcomp,cubetype,cubsettype>::addone ()
00456 {
00457         // initialize the new Morse set pointer
00458         sets [nsets] = new cubsettype;
00459 
00460         // initialize the new Conley index pointer
00461         indices [nsets] = 0;
00462         nontrivial [nsets] = -1;
00463 
00464         // initialize the connecting orbits' pointers
00465         for (int i = 0; i < nsets; ++ i)
00466         {
00467                 conn [nsets] [i] = 0;
00468                 conn [i] [nsets] = 0;
00469         }
00470         conn [nsets] [nsets] = 0;
00471 
00472         // initialize the tabulated distances
00473         for (int i = 0; i < nsets; ++ i)
00474         {
00475                 dist [nsets] [i] = -1;
00476                 dist [i] [nsets] = -1;
00477                 distconn [nsets] [i] = -1;
00478                 distconn [i] [nsets] = -1;
00479         }
00480         dist [nsets] [nsets] = 0;
00481         distconn [nsets] [nsets] = 0;
00482 
00483         // increase the stored number of Morse sets
00484         ++ nsets;
00485         return;
00486 } /* MorseDecomposition::addone */
00487 
00488 template <class mapcomp, class cubetype, class cubsettype>
00489 inline bool MorseDecomposition<mapcomp,cubetype,cubsettype>::adjacent
00490         (int n, int m, int margin) const
00491 {
00492         // define the right type of neighbors' iterator
00493         typedef chomp::homology::tNeighbors<typename cubetype::CoordType>
00494                 neighborstype;
00495 
00496         // make sure the arguments are correct
00497         if ((n < 0) || (n >= nsets) || (m < 0) || (m >= nsets))
00498                 return false;
00499         if (n == m)
00500                 return true;
00501         if (margin < 0)
00502                 margin = 0;
00503 
00504         // determine the smaller and the larger set
00505         bool n_m = (sets [n] -> size () < sets [m] -> size ());
00506         const cubsettype &smaller = n_m ? *(sets [n]) : *(sets [m]);
00507         const cubsettype &larger = n_m ? *(sets [m]) : *(sets [n]);
00508 
00509         // if both sets are empty, then the result is obvious
00510         if (larger. empty ())
00511                 return false;
00512 
00513         // prepare an auxiliary buffer for coordinates of a cube
00514         int dim = larger [0]. dim ();
00515         typename cubetype::CoordType *c =
00516                 new typename cubetype::CoordType [dim];
00517 
00518         // create an enhanced set if the margin is nonzero
00519         cubsettype enhanced;
00520         if (margin)
00521                 enhanced = smaller;
00522         int start = 0;
00523         for (int i = 0; i < margin; ++ i)
00524         {
00525                 int stop = enhanced. size ();
00526                 for (int n = start; n < stop; ++ n)
00527                 {
00528                         enhanced [n]. coord (c);
00529                         neighborstype n (c, dim);
00530                         const typename cubetype::CoordType *nc;
00531                         while ((nc = n. get ()) != 0)
00532                                 enhanced. add (cubetype (nc, dim));
00533                 }
00534                 start = stop;
00535         }
00536 
00537         // choose the enhanced set or the original one,
00538         // depending on the margin
00539         const cubsettype &smallcheck = margin ? enhanced : smaller;
00540 
00541         // for each cube in the smaller set, check if any of its neighbors
00542         // is contained in the larger set
00543         for (int i = 0; i < smallcheck. size (); ++ i)
00544         {
00545                 smallcheck [i]. coord (c);
00546                 neighborstype n (c, dim);
00547                 const typename cubetype::CoordType *nc;
00548                 while ((nc = n. get ()) != 0)
00549                 {
00550                         if (larger. check (cubetype (nc, dim)))
00551                         {
00552                                 delete [] c;
00553                                 return true;
00554                         }
00555                 }
00556         }
00557         delete [] c;
00558         return false;
00559 } /* MorseDecomposition::adjacent */
00560 
00561 template <class mapcomp, class cubetype, class cubsettype>
00562 inline int MorseDecomposition<mapcomp,cubetype,cubsettype>::cubsetdistance
00563         (const cubsettype &X, const cubsettype &Y, bool minimum)
00564 {
00565         // if one of the sets is empty, then say that the distance is zero
00566         if (X. empty () || Y. empty ())
00567                 return 0;
00568 
00569         // prepare the arrays for the coordinates of the cubes to compare
00570         int dim = X [0]. dim ();
00571         typedef typename cubetype::CoordType coords;
00572         coords *c = new coords [dim + dim];
00573         coords *d = c + dim;
00574 
00575         // for each pair of cubes (one in the n-th set, another in the
00576         // m-th set), compute their distance and take the minimum
00577         int best_dist = -1;
00578         for (int i = 0; i < X. size (); ++ i)
00579         {
00580                 X [i]. coord (c);
00581                 int local_dist = -1;
00582                 for (int j = 0; j < Y. size (); ++ j)
00583                 {
00584                         Y [j]. coord (d);
00585                         int dist = 0;
00586                         for (int k = 0; k < dim; ++ k)
00587                                 dist += (c [k] - d [k]) * (c [k] - d [k]);
00588                         dist = static_cast<int> (std::sqrt (dist));
00589                         if ((local_dist < 0) || (local_dist > dist))
00590                                 local_dist = dist;
00591                 }
00592 
00593                 if (minimum)
00594                 {
00595                         if ((best_dist < 0) || (best_dist > local_dist))
00596                                 best_dist = local_dist;
00597                 }
00598                 else
00599                 {
00600                         if ((best_dist < 0) || (best_dist < local_dist))
00601                                 best_dist = local_dist;
00602                 }
00603         }
00604 
00605         delete [] c;
00606         return best_dist;
00607 } /* MorseDecomposition::distance */
00608 
00609 // --------------------------------------------------
00610 
00611 template <class mapcomp, class cubetype, class cubsettype>
00612 inline int MorseDecomposition<mapcomp,cubetype,cubsettype>::setnumber
00613         (int n)
00614 {
00615         if (n < 0)
00616                 return 0;
00617         while (n > nsets)
00618                 addone ();
00619         if (n < nsets)
00620                 deleteall (n, nsets);
00621         return 0;
00622 } /* MorseDecomposition::setnumber */
00623 
00624 template <class mapcomp, class cubetype, class cubsettype>
00625 inline int MorseDecomposition<mapcomp,cubetype,cubsettype>::add
00626         (int n, const cubetype &q)
00627 {
00628         if (n < 0)
00629                 return 0;
00630         while (n > nsets)
00631                 addone ();
00632         sets [n] -> add (q);
00633         return 0;
00634 } /* MorseDecomposition::add */
00635 
00636 // --------------------------------------------------
00637 
00638 template <class mapcomp, class cubetype, class cubsettype>
00639 inline int MorseDecomposition<mapcomp,cubetype,cubsettype>::addconn
00640         (int n, int m)
00641 {
00642         if ((n < 0) || (m < 0))
00643                 return 0;
00644         while ((n > nsets) || (m > nsets))
00645                 addone ();
00646         if (!conn [n] [m])
00647                 conn [n] [m] = new cubsettype;
00648         return 0;
00649 } /* MorseDecomposition::addconn */
00650 
00651 template <class mapcomp, class cubetype, class cubsettype>
00652 inline int MorseDecomposition<mapcomp,cubetype,cubsettype>::addconn
00653         (int n, int m, const cubetype &q)
00654 {
00655         if ((n < 0) || (m < 0))
00656                 return 0;
00657         while ((n > nsets) || (m > nsets))
00658                 addone ();
00659         if (!conn [n] [m])
00660                 conn [n] [m] = new cubsettype;
00661         conn [n] [m] -> add (q);
00662         return 0;
00663 } /* MorseDecomposition::addconn */
00664 
00665 template <class mapcomp, class cubetype, class cubsettype>
00666 inline int MorseDecomposition<mapcomp,cubetype,cubsettype>::count () const
00667 {
00668         return nsets;
00669 } /* MorseDecomposition::count */
00670 
00671 template <class mapcomp, class cubetype, class cubsettype>
00672 inline const cubsettype &MorseDecomposition<mapcomp,cubetype,cubsettype>::
00673 	operator [] (int n) const
00674 {
00675         if ((n < 0) || (n >= nsets) || !sets [n])
00676                 throw "Trying to access an undefined Morse set.";
00677         return *(sets [n]);
00678 } /* MorseDecomposition::operator [] */
00679 
00680 template <class mapcomp, class cubetype, class cubsettype>
00681 inline int MorseDecomposition<mapcomp,cubetype,cubsettype>::distance
00682         (int n, int m) const
00683 {
00684         // make sure that n <= m
00685         if (n > m)
00686         {
00687                 int tmp = n;
00688                 n = m;
00689                 m = tmp;
00690         }
00691 
00692         // if the number(s) are too large, return an undefined value
00693         if (m >= nsets)
00694                 return -1;
00695 
00696         // if both numbers are negative, reset all the distances
00697         if (m < 0)
00698         {
00699                 for (int i = 0; i < nsets; ++ i)
00700                 {
00701                         for (int j = 0; j < nsets; ++ j)
00702                                 dist [i] [j] = -1;
00703                 }
00704                 return -1;
00705         }
00706 
00707         // if one of the numbers is negative, reset one set of distances only
00708         if (n < 0)
00709         {
00710                 for (int i = 0; i < nsets; ++ i)
00711                 {
00712                         dist [i] [m] = -1;
00713                         dist [m] [i] = -1;
00714                 }
00715                 return -1;
00716         }
00717 
00718         // if the sets are the same, their distance is zero
00719         if (n == m)
00720                 return 0;
00721 
00722         // if the distance is known, then return it
00723         if (dist [n] [m] >= 0)
00724                 return dist [n] [m];
00725 
00726         // compute the distance and save it
00727         int d = cubsetdistance (*(sets [n]), *(sets [m]), true);
00728         dist [n] [m] = d;
00729         dist [m] [n] = d;
00730 
00731         // return the distance
00732         return d;
00733 } /* MorseDecomposition::distance */
00734 
00735 // --------------------------------------------------
00736 
00737 template <class mapcomp, class cubetype, class cubsettype>
00738 inline bool MorseDecomposition<mapcomp,cubetype,cubsettype>::connected
00739         (int n, int m) const
00740 {
00741         return ((n >= 0) && (n < nsets) && (m >= 0) && (m < nsets) &&
00742                 conn [n] [m]);
00743 } /* MorseDecomposition::connected */
00744 
00745 template <class mapcomp, class cubetype, class cubsettype>
00746 inline const cubsettype &MorseDecomposition<mapcomp,cubetype,cubsettype>::
00747 	connection (int n, int m) const
00748 {
00749         if ((n < 0) || (n >= nsets) || (m < 0) || (m >= nsets) ||
00750                 !conn [n] [m])
00751                 throw "Trying to access an undefined Morse set connection.";
00752         return *(conn [n] [m]);
00753 } /* MorseDecomposition::connection */
00754 
00755 template <class mapcomp, class cubetype, class cubsettype>
00756 inline int MorseDecomposition<mapcomp,cubetype,cubsettype>::distance
00757         (int n, int m, int k) const
00758 {
00759         if ((n < 0) || (n >= nsets) || (m < 0) || (m >= nsets) ||
00760                 (k < 0) || (k >= nsets))
00761                 return -1;
00762         if ((n == m) || (!conn [n] [m] && !conn [m] [n]))
00763                 return 0;
00764         return cubsetdistance (conn [n] [m] ? *(conn [n] [m]) :
00765                 *(conn [m] [n]), *(sets [k]), false);
00766 } /* MorseDecomposition::distance */
00767 
00768 template <class mapcomp, class cubetype, class cubsettype>
00769 inline int MorseDecomposition<mapcomp,cubetype,cubsettype>::conndistance
00770         (int n, int m) const
00771 {
00772         // if the number(s) are too large, return an undefined value
00773         if ((n >= nsets) || (m >= nsets))
00774                 return -1;
00775 
00776         // if both numbers are negative, reset all the distances
00777         if ((n < 0) && (m < 0))
00778         {
00779                 for (int i = 0; i < nsets; ++ i)
00780                 {
00781                         for (int j = 0; j < nsets; ++ j)
00782                                 distconn [i] [j] = -1;
00783                 }
00784                 return -1;
00785         }
00786 
00787         // if one of the numbers is negative, reset one set of distances only
00788         if ((n < 0) || (m < 0))
00789         {
00790                 int num = (n >= 0) ? n : m;
00791                 for (int i = 0; i < nsets; ++ i)
00792                 {
00793                         distconn [i] [num] = -1;
00794                         distconn [num] [i] = -1;
00795                 }
00796                 return -1;
00797         }
00798 
00799         // if the distance is known, then return it
00800         if (distconn [n] [m] >= 0)
00801                 return distconn [n] [m];
00802 
00803         // compute the distance and save it
00804         int d = distance (n, m, n);
00805         distconn [n] [m] = d;
00806 
00807         // return the distance
00808         return d;
00809 } /* MorseDecomposition::conndistance */
00810 
00811 template <class mapcomp, class cubetype, class cubsettype>
00812 inline int MorseDecomposition<mapcomp,cubetype,cubsettype>::makegraph
00813         (chomp::homology::diGraph<> &g) const
00814 {
00815         for (int i = 0; i < nsets; ++ i)
00816         {
00817                 g. addVertex ();
00818                 for (int j = 0; j < nsets; ++ j)
00819                 {
00820                         if (conn [i] [j])
00821                                 g. addEdge (j);
00822                 }
00823         }
00824         return 0;
00825 } /* MorseDecomposition::makegraph */
00826 
00827 // --------------------------------------------------
00828 
00829 template <class mapcomp, class cubetype, class cubsettype>
00830 inline const typename MorseDecomposition<mapcomp,cubetype,cubsettype>::
00831 	IndexType &MorseDecomposition<mapcomp,cubetype,cubsettype>::compute
00832         (int n)
00833 {
00834         if ((n < 0) || (n >= nsets) || !sets [n])
00835                 throw "Trying to compute the Conley index of an undefined "
00836                         "Morse set.";
00837 
00838         // create an index pair and compute the map on the index pair
00839         PairType P (M);
00840         const cubsettype &cset = *(sets [n]);
00841         int csetsize = cset. size ();
00842         for (int i = 0; i < csetsize; ++ i)
00843                 P. add (cset [i]);
00844         P. compute ();
00845 
00846         // create the Conley index object and compute the index
00847         if (indices [n])
00848                 delete indices [n];
00849         indices [n] = new IndexType ();
00850         indices [n] -> setIndexPair (&P);
00851 
00852         indices [n] -> compute ();
00853         indices [n] -> setIndexPair (0);
00854 
00855         // remember if the index is nontrivial or not
00856         if (indices [n] -> trivial ())
00857                 nontrivial [n] = 0;
00858         else
00859                 nontrivial [n] = 1;
00860 
00861         return *(indices [n]);
00862 } /* MorseDecomposition::compute */
00863 
00864 template <class mapcomp, class cubetype, class cubsettype>
00865 inline int MorseDecomposition<mapcomp,cubetype,cubsettype>::compute ()
00866 {
00867         for (int i = 0; i < nsets; ++ i)
00868                 compute (i);
00869         return 0;
00870 } /* MorseDecomposition::compute */
00871 
00872 template <class mapcomp, class cubetype, class cubsettype>
00873 inline bool MorseDecomposition<mapcomp,cubetype,cubsettype>::computed (int n)
00874         const
00875 {
00876         return ((n >= 0) && (n < nsets) && indices [n]);
00877 } /* MorseDecomposition::computed */
00878 
00879 template <class mapcomp, class cubetype, class cubsettype>
00880 inline const typename MorseDecomposition<mapcomp,cubetype,cubsettype>::
00881 	IndexType &MorseDecomposition<mapcomp,cubetype,cubsettype>::index
00882         (int n) const
00883 {
00884         if ((n < 0) || (n >= nsets) || !indices [n])
00885                 throw "Trying to get an undefined Conley index.";
00886         return *(indices [n]);
00887 } /* MorseDecomposition::index */
00888 
00889 template <class mapcomp, class cubetype, class cubsettype>
00890 inline const typename MorseDecomposition<mapcomp,cubetype,cubsettype>::
00891 	IndexType &MorseDecomposition<mapcomp,cubetype,cubsettype>::setindex
00892         (int n, const typename
00893         MorseDecomposition<mapcomp,cubetype,cubsettype>::IndexType &ind)
00894 {
00895         if ((n < 0) || (n >= nsets))
00896                 throw "Trying to set a Conley index out of range.";
00897         if (indices [n])
00898                 delete indices [n];
00899         indices [n] = new IndexType (ind);
00900         if (indices [n] -> trivial ())
00901                 nontrivial [n] = 0;
00902         else
00903                 nontrivial [n] = 1;
00904         return *(indices [n]);
00905 } /* MorseDecomposition::setindex */
00906 
00907 template <class mapcomp, class cubetype, class cubsettype>
00908 inline bool MorseDecomposition<mapcomp,cubetype,cubsettype>::trivial
00909         (int n) const
00910 {
00911         return ((n >= 0) && (n < nsets) && (nontrivial [n] == 0));
00912 } /* MorseDecomposition::trivial */
00913 
00914 // --------------------------------------------------
00915 
00916 template <class mapcomp, class cubetype, class cubsettype>
00917 inline void MorseDecomposition<mapcomp,cubetype,cubsettype>::intersection
00918         (const MorseDecomposition<mapcomp,cubetype,cubsettype> &m,
00919         const MorseDecomposition<mapcomp,cubetype,cubsettype> &n)
00920 {
00921         for (int i = 0; i < m. nsets; ++ i)
00922         {
00923                 for (int j = 0; j < n. nsets; ++ j)
00924                 {
00925                         cubsettype X;
00926                         X. intersection (*(m. sets [i]), *(n. sets [j]));
00927                         if (X. empty ())
00928                                 continue;
00929                         addone ();
00930                         sets [nsets - 1] -> swap (X);
00931                 }
00932         }
00933         return;
00934 } /* MorseDecomposition::intersection */
00935 
00936 // --------------------------------------------------
00937 
00938 template <class mapcomp, class cubetype, class cubsettype>
00939 inline int MorseDecomposition<mapcomp,cubetype,cubsettype>::join
00940         (int n, int m)
00941 {
00942         if ((n < 0) || (n >= nsets) || (m < 0) || (m >= nsets) || (n == m))
00943                 throw "Incorrect numbers of Morse sets to join.";
00944 
00945         // show a message
00946         chomp::homology::sbug << "* Joining Morse sets: " <<
00947                 n << " and " << m << "(" << sets [n] -> size () <<
00948                 " - " << ((conn [n] [m] ? conn [n] [m] -> size () : 0) +
00949                 (conn [m] [n] ? conn [m] [n] -> size () : 0)) << " - " <<
00950                 sets [m] -> size () << ").\n";
00951 
00952         // reset tabulated distances
00953         for (int i = 0; i < nsets; ++ i)
00954         {
00955                 dist [i] [n] = -1;
00956                 dist [n] [i] = -1;
00957                 distconn [i] [n] = -1;
00958                 distconn [n] [i] = -1;
00959         }
00960 
00961         // join the sets
00962         sets [n] -> add (*(sets [m]));
00963         if (conn [n] [m])
00964                 sets [n] -> add (*(conn [n] [m]));
00965         if (conn [m] [n])
00966                 sets [n] -> add (*(conn [m] [n]));
00967 
00968         // adjust the connecting orbits
00969         for (int k = 0; k < nsets; ++ k)
00970         {
00971                 if ((k == n) || (k == m))
00972                         continue;
00973 
00974                 // adjust the connection (n+m) --> k
00975                 if (conn [n] [k])
00976                 {
00977                         if (conn [m] [k])
00978                                 conn [n] [k] -> add (*(conn [m] [k]));
00979                         conn [n] [k] -> remove (*(sets [n]));
00980                 }
00981                 else if (conn [m] [k])
00982                 {
00983                         conn [n] [k] = conn [m] [k];
00984                         conn [m] [k] = 0;
00985                         conn [n] [k] -> remove (*(sets [n]));
00986                 }
00987 
00988                 // adjust the connection k --> (n+m)
00989                 if (conn [k] [n])
00990                 {
00991                         if (conn [k] [m])
00992                                 conn [k] [n] -> add (*(conn [k] [m]));
00993                         conn [k] [n] -> remove (*(sets [n]));
00994                 }
00995                 else if (conn [k] [m])
00996                 {
00997                         conn [k] [n] = conn [k] [m];
00998                         conn [k] [m] = 0;
00999                         conn [k] [n] -> remove (*(sets [n]));
01000                 }
01001         }
01002 
01003         // reset the Conley index of the n-th Morse set if necessary
01004         if (indices [n] && nontrivial [m])
01005         {
01006                 delete indices [n];
01007                 indices [n] = 0;
01008                 nontrivial [n] = -1;
01009         }
01010 
01011         // delete the m-th Morse set which has been joined to the n-th one
01012         deleteall (m, m + 1);
01013         return 0;
01014 } /* MorseDecomposition::join */
01015 
01016 template <class mapcomp, class cubetype, class cubsettype>
01017 inline int MorseDecomposition<mapcomp,cubetype,cubsettype>::passthru (int n)
01018 {
01019         using chomp::homology::sbug;
01020 
01021         if ((n < 0) || (n >= nsets))
01022                 throw "Incorrect numbers of Morse set to pass through.";
01023 
01024         // show a message
01025 //      sbug << "* Passing through Morse set " << n << " (" <<
01026 //              sets [n] -> size () << " cubes).\n";
01027 
01028         // join connecting orbits and reset tabulated distances
01029         for (int i = 0; i < nsets; ++ i)
01030         {
01031                 if (i == n)
01032                         continue;
01033                 for (int j = 0; j < nsets; ++ j)
01034                 {
01035                         if (j == n)
01036                                 continue;
01037                 //      if (conn [i] [n] && !conn [n] [j])
01038                 //      {
01039                 //              sbug << "WARNIING: Passing through "
01040                 //                      "an attractor: " << i << " -> " <<
01041                 //                      n << " | " << j << ".\n";
01042                 //      }
01043                 //      else if (!conn [i] [n] && conn [n] [j])
01044                 //      {
01045                 //              sbug << "WARNIING: Passing through "
01046                 //                      "a repeller: " << i << " | " <<
01047                 //                      n << " -> " << j << ".\n";
01048                 //      }
01049                 //      else if (!conn [i] [n] && !conn [n] [j])
01050                 //              continue;
01051                         if (conn [i] [n] && conn [n] [j])
01052                         {
01053                         //      sbug << "(orbits joined: " << i <<
01054                         //              " --[" << conn [i] [n] -> size () <<
01055                         //              "]-> " << n << "[" <<
01056                         //              sets [n] -> size () << "] --[" <<
01057                         //              conn [n] [j] -> size () << "]-> " <<
01058                         //              j << ")\n";
01059                                 // modify the connecting orbit
01060                                 if (!conn [i] [j])
01061                                         conn [i] [j] = new cubsettype;
01062                                 conn [i] [j] -> add (*(conn [i] [n]));
01063                                 conn [i] [j] -> add (*(conn [n] [j]));
01064                                 conn [i] [j] -> add (*(sets [n]));
01065 
01066                                 // reset the corresponding distances
01067                                 distconn [i] [j] = -1;
01068                                 distconn [j] [i] = -1;
01069                         }
01070                 }
01071         }
01072 
01073         // delete the n-th Morse set
01074         deleteall (n, n + 1);
01075         return 0;
01076 } /* MorseDecomposition::passthru */
01077 
01078 template <class mapcomp, class cubetype, class cubsettype>
01079 inline int MorseDecomposition<mapcomp,cubetype,cubsettype>::jointrivial
01080         (int maxsetsize, int maxconnsize, int maxdistance)
01081 {
01082         using chomp::homology::sbug;
01083         sbug << "- Join trivial: maxsetsize = " << maxsetsize <<
01084                 ", maxconnsize = " << maxconnsize <<
01085                 ", maxdistance = " << maxdistance << ".\n";
01086 
01087         // compute the Conley indices of all the Morse sets if necessary
01088         for (int n = 0; n < nsets; ++ n)
01089         {
01090                 if (nontrivial [n] < 0)
01091                         compute (n);
01092         }
01093 
01094         // join pairs of Morse sets
01095         bool allow_trivial = false;
01096         while (1)
01097         {
01098                 // output information for debugging
01099                 if (false) // DEBUG
01100                 {
01101                         using std::setw;
01102                         sbug << "Morse decomposition connection set sizes:\n";
01103                         sbug << "               ";
01104                         for (int i = 0; i < nsets; ++ i)
01105                                 sbug << setw (7) << i;
01106                         sbug << "\n";
01107                         for (int i = 0; i < nsets; ++ i)
01108                         {
01109                                 sbug << setw (3) << i << " (" <<
01110                                         setw (7) << sets [i] -> size ();
01111                                 switch (nontrivial [i])
01112                                 {
01113                                 case -1: sbug << ")- "; break;
01114                                 case 1: sbug << ")+ "; break;
01115                                 case 0: sbug << "): "; break;
01116                                 default: sbug << ")[" << nontrivial [i] <<
01117                                         "] "; break;
01118                                 }
01119                                 for (int j = 0; j < nsets; ++ j)
01120                                 {
01121                                         if (conn [i] [j])
01122                                                 sbug << setw (7) <<
01123                                                         conn [i] [j] ->
01124                                                         size ();
01125                                         else
01126                                                 sbug << "    ---";
01127                                 }
01128                                 sbug << "\n";
01129                         }
01130                 }
01131 
01132                 // the numbers of best choice in the loop below
01133                 int best_n = -1, best_m = -1;
01134                 // the size of what is added to the Morse set
01135                 int best_size = 0;
01136                 // the size of the nontrivial/large Morse set
01137                 int best_nsize = 0;
01138                 // the best distance between the Morse sets found so far
01139                 int best_dist = 0;
01140                 // the best distance between the connecting orbit and the set
01141                 int best_conndist = 0;
01142 
01143                 // check all pairs of sets and find the optimal ones to join
01144                 for (int n = 0; n < nsets; ++ n)
01145                 {
01146                         for (int m = 0; m < nsets; ++ m)
01147                         {
01148                                 // --- check the necessary conditions ---
01149 
01150                                 // make sure these are two different sets
01151                                 if (n != m);
01152                                 else
01153                                         continue;
01154 
01155                                 // remember the sizes of the two sets
01156                                 int nsize = sets [n] -> size ();
01157                                 int msize = sets [m] -> size ();
01158 
01159                                 // check if the n-th set is nontrivial
01160                                 // or very large, and the m-th set is trivial
01161                                 if (!nontrivial [m] && (nontrivial [n] ||
01162                                         (nsize > maxsetsize) ||
01163                                         allow_trivial));
01164                                 else
01165                                         continue;
01166 
01167                                 // count the size of connecting orbits
01168                                 int conn_nm = conn [n] [m] ?
01169                                         conn [n] [m] -> size () : 0;
01170                                 int conn_mn = conn [m] [n] ?
01171                                         conn [m] [n] -> size () : 0;
01172                                 int add_size = msize + conn_nm + conn_mn;
01173 
01174                                 // make sure the size limits are observed
01175                                 if ((msize < maxsetsize) &&
01176                                         (conn_nm < maxconnsize) &&
01177                                         (conn_mn < maxconnsize));
01178                                 else
01179                                         continue;
01180 
01181                                 // make sure that no loop will be created
01182                                 bool looping = false;
01183                                 for (int k = 0; k < nsets; ++ k)
01184                                 {
01185                                         if ((conn [n] [k] && conn [k] [m]) ||
01186                                                 (conn [m] [k] &&
01187                                                 conn [k] [n]))
01188                                         {
01189                                                 looping = true;
01190                                                 break;
01191                                         }
01192                                 }
01193                                 if (looping)
01194                                         continue;
01195 
01196                                 // compute the dist. between the Morse sets
01197                                 int dist = distance (n, m);
01198                         //      sbug << "- Dist (" << n << "," << m <<
01199                         //              ") = " << dist << ".\n";
01200                                 if (dist <= maxdistance);
01201                                 else
01202                                         continue;
01203 
01204                                 // compute the maximal distance between cubes
01205                                 // in the connecting orbit and the Morse set
01206                                 int conndist = conndistance (n, m);
01207                         //      sbug << "- ConnDist (" << n << "," << m <<
01208                         //              ") = " << conndist << ".\n";
01209                                 if (conndist <= maxdistance);
01210                                 else
01211                                         continue;
01212 
01213                                 // --- check if this is a better choice ---
01214 
01215                                 // make sure that the distance is not going
01216                                 // to be increased
01217                                 if ((best_n < 0) || (dist + conndist <=
01218                                         best_dist + best_conndist));
01219                                 else
01220                                         continue;
01221 
01222                                 // check if the size of what is added
01223                                 // to the nontrivial set does not exceed
01224                                 // the size found in the previous case
01225                         //      if ((best_n < 0) || (best_size < add_size));
01226                         //      else
01227                         //              continue;
01228 
01229                                 // choose this pair of Morse sets
01230                                 best_n = n;
01231                                 best_m = m;
01232                                 best_size = add_size;
01233                                 best_nsize = nsize;
01234                                 best_dist = dist;
01235                         }
01236                 }
01237 
01238                 // if no good pair has been found...
01239                 if ((best_n < 0) || (best_m < 0))
01240                 {
01241                         // if loose criteria was already set, break the loop
01242                         if (allow_trivial)
01243                                 break;
01244 
01245                         // loosen the criteria of checking the sets to join
01246                         allow_trivial = true;
01247                         continue;
01248                 }
01249 
01250                 // join the two Morse sets (keep the n-th index if necessary)
01251                 join (best_n, best_m);
01252         }
01253 
01254         // compute the missing Conley indices
01255         for (int n = 0; n < nsets; ++ n)
01256         {
01257                 if (nontrivial [n] < 0)
01258                         compute (n);
01259         }
01260 
01261         return 0;
01262 } /* MorseDecomposition::jointrivial */
01263 
01264 template <class mapcomp, class cubetype, class cubsettype>
01265 inline int MorseDecomposition<mapcomp,cubetype,cubsettype>::savetofiles
01266         (const char *prefix)
01267 {
01268         for (int n = 0; n < nsets; ++ n)
01269         {
01270                 // create a file for this Morse set
01271                 std::ostringstream ofname;
01272                 if (prefix)
01273                         ofname << prefix;
01274                 ofname << n;
01275                 std::string fname = ofname. str ();
01276                 std::ofstream out (fname. c_str ());
01277 
01278                 // save the nontriviality of the index information
01279                 out << "; This is the Morse set no. " << n << ".\n";
01280                 out << "; Its Conley index ";
01281                 switch (nontrivial [n])
01282                 {
01283                 case 0: out << "is trivial.\n"; break;
01284                 case 1: out << "is nontrivial.\n"; break;
01285                 default: out << "has not been computed.\n"; break;
01286                 }
01287 
01288                 // save the Conley index itself
01289                 if (indices [n])
01290                 {
01291                         out << "; The Conley index: " <<
01292                                 *(indices [n]) << "\n";
01293                 }
01294 
01295                 // save the Morse set to a file
01296                 out << *(sets [n]);
01297                 out. close ();
01298 
01299                 // save the connecting orbits to files
01300                 for (int m = 0; m < nsets; ++ m)
01301                 {
01302                         // if there is no connection, skip the file
01303                         if (!conn [n] [m])
01304                                 continue;
01305 
01306                         // create a file name for the connection
01307                         std::ostringstream connname;
01308                         connname << fname << '-' << m;
01309 
01310                         // save the connection
01311                         std::ofstream outc (connname. str (). c_str ());
01312                         outc << "; This is a covering of all the computed "
01313                                 "connecting orbits\n"
01314                                 "; that run from the Morse set no. " << n <<
01315                                 " to " << m << ".\n";
01316                         if (conn [n] [m] -> empty ())
01317                         {
01318                                 outc << "\n; Note: This set is empty "
01319                                         "which means that the orbit\n"
01320                                         "; was most likely not computed.\n";
01321                         }
01322                         else
01323                                 outc << *(conn [n] [m]);
01324                 }
01325         }
01326         return 0;
01327 } /* MorseDecomposition::savetofiles */
01328 
01329 template <class mapcomp, class cubetype, class cubsettype>
01330 inline int MorseDecomposition<mapcomp,cubetype,cubsettype>::loadfromfiles
01331         (const char *prefix)
01332 {
01333         for (int n = 0; ; ++ n)
01334         {
01335                 // create a file name for this Morse set
01336                 std::ostringstream fname;
01337                 if (prefix)
01338                         fname << prefix;
01339                 fname << n;
01340 
01341                 // open a file if possible
01342                 std::ifstream in (fname. str (). c_str ());
01343 
01344                 // if the file does not exist, then quit the reading process
01345                 if (!in)
01346                         break;
01347 
01348                 // read the Conley index information if any is available
01349                 int nontrivialindex = -1;
01350                 IndexType *theIndex = 0;
01351                 while (in. peek () == ';')
01352                 {
01353                         // read the comment line from the input file
01354                         std::string line;
01355                         getline (in, line);
01356 
01357                         // look for the info that the index is nontrivial
01358                         if (line. find ("Conley index is nontrivial") !=
01359                                 std::string::npos)
01360                         {
01361                                 nontrivialindex = 1;
01362                                 continue;
01363                         }
01364 
01365                         // look for the information that the index is trivial
01366                         if (line. find ("Conley index is trivial") !=
01367                                 std::string::npos)
01368                         {
01369                                 nontrivialindex = 0;
01370                                 continue;
01371                         }
01372 
01373                         // look for the actual Conley index to read
01374                         std::string indHeader ("Conley index: ");
01375                         std::string::size_type pos = line. find (indHeader);
01376                         if (pos != std::string::npos)
01377                         {
01378                                 std::istringstream str (line);
01379                                 std::string::size_type len = pos +
01380                                         indHeader. size ();
01381                                 for (unsigned int i = 0; i < len; ++ i)
01382                                         str. get ();
01383                                 theIndex = new IndexType ();
01384                                 str >> *theIndex;
01385                                 continue;
01386                         }
01387                 }
01388 
01389                 // add a Morse set and read it
01390                 this -> addone ();
01391                 in >> *(sets [n]);
01392                 in. close ();
01393                 indices [n] = theIndex;
01394                 nontrivial [n] = nontrivialindex;
01395         }
01396 
01397         // load the connections from files
01398         for (int n = 0; n < nsets; ++ n)
01399         {
01400                 for (int m = 0; m < nsets; ++ m)
01401                 {
01402                         // create a file name for this connection
01403                         std::ostringstream fname;
01404                         if (prefix)
01405                                 fname << prefix;
01406                         fname << n << '-' << m;
01407 
01408                         // try opening the file for this connection
01409                         std::ifstream in (fname. str (). c_str ());
01410                         if (!in)
01411                                 continue;
01412 
01413                         // create the connection and read it
01414                         conn [n] [m] = new cubsettype;
01415                         in >> *(conn [n] [m]);
01416                 }
01417         }
01418         return 0;
01419 } /* MorseDecomposition::loadfromfiles */
01420 
01421 
01422 #endif // _CMGRAPHS_MORSEDEC_H_
01423 
01424 

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