The Conley-Morse Graphs Software
compmdec.h
Go to the documentation of this file.
1/////////////////////////////////////////////////////////////////////////////
2///
3/// @file compmdec.h
4///
5/// Computation of Morse decompositions.
6/// This file contains the definition of a function for the computation
7/// of a Morse decomposition for a given map, as well as several auxiliary
8/// procedures necessary to compute this Morse decomposition in an efficient
9/// way by restricting the phase space to the invariant part computed
10/// with respect to a coarser grid. The computed Morse decomposition
11/// is processed further in order to eliminate spurious Morse sets
12/// wherever possible.
13///
14/// @author Pawel Pilarczyk
15///
16/////////////////////////////////////////////////////////////////////////////
17
18// Copyright (C) 1997-2014 by Pawel Pilarczyk.
19//
20// This file is part of my research software package. This is free software:
21// you can redistribute it and/or modify it under the terms of the GNU
22// General Public License as published by the Free Software Foundation,
23// either version 3 of the License, or (at your option) any later version.
24//
25// This software is distributed in the hope that it will be useful,
26// but WITHOUT ANY WARRANTY; without even the implied warranty of
27// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28// GNU General Public License for more details.
29//
30// You should have received a copy of the GNU General Public License
31// along with this software; see the file "license.txt". If not,
32// please, see <https://www.gnu.org/licenses/>.
33
34// Started on February 12, 2007. Last revision: August 22, 2014.
35
36
37#ifndef _CMGRAPHS_COMPMDEC_H_
38#define _CMGRAPHS_COMPMDEC_H_
39
40
41// include some standard C++ header files
42#include <algorithm>
43#include <new>
44#include <iostream>
45#include <iomanip>
46#include <ios>
47#include <string>
48#include <fstream>
49#include <sstream>
50#include <cstdio>
51
52// include selected header files from the CHomP library
53#include "chomp/system/textfile.h"
54#include "chomp/cubes/pointset.h"
55#include "chomp/struct/digraph.h"
56#include "chomp/struct/multitab.h"
57#include "chomp/struct/hashsets.h"
58#include "chomp/system/timeused.h"
59
60// include local header files
61#include "config.h"
62#include "typedefs.h"
63#include "conindex.h"
64#include "morsedec.h"
65#include "typedyns.h"
66#include "indcache.h"
67#include "invpart.h"
68#include "utils.h"
69#include "spacewrap.h"
70#include "procmdec.h"
71#include "morsecache.h"
72#include "eigenval.h"
73#include "dotgraph.h"
74#include "datatext.h"
75
76
77// --------------------------------------------------
78// ---- connection recorders for inclusionGraph -----
79// --------------------------------------------------
80
81/// A simple class for storing connections in an array that uses
82/// the "multitable" class.
84{
85public:
86 /// The constructor.
87 TConnTable (int_t _n, chomp::homology::multitable
88 <chomp::homology::multitable<int_t> > &_connections,
89 chomp::homology::multitable<int_t> &_conncount,
90 const int_t *_numTranslate);
91
92 /// Adds an element v at the connection from source to target.
93 void operator () (int_t source, int_t target, int_t v);
94
95private:
96 /// The number of vertices between the connections are recorded.
97 int_t n;
98
99 /// The tables of connectiong orbits; those for v -> w are stored
100 /// at the index n * v + w.
101 chomp::homology::multitable<chomp::homology::multitable<int_t> >
103
104 /// The numbers of elements in each connecting orbit.
105 chomp::homology::multitable<int_t> &conncount;
106
107 /// The translation table for vertex numbers in the connections.
108 const int_t *numTranslate;
109
110}; /* class TConnTable */
111
112inline TConnTable::TConnTable (int_t _n,
113 chomp::homology::multitable<chomp::homology::multitable<int_t> > &
114 _connections, chomp::homology::multitable<int_t> &_conncount,
115 const int_t *_numTranslate):
116 n (_n), connections (_connections), conncount (_conncount),
117 numTranslate (_numTranslate)
118{
119 int_t maxcount = n * n;
120 for (int_t i = 0; i < maxcount; ++ i)
121 conncount [i] = 0;
122 return;
123} /* TConnTable::TConnTable */
124
125inline void TConnTable::operator () (int_t source, int_t target, int_t v)
126{
127 int_t pos = n * source + target;
128 connections [pos] [conncount [pos] ++] = numTranslate [v];
129 return;
130} /* TConnTable::operator () */
131
132// --------------------------------------------------
133
134/// A simple class for storing connections in an array that uses
135/// the "multitable" class.
137{
138public:
139 /// The constructor.
141 const std::vector<int> &_setNumbers,
142 const spcCubes &spcX, const int_t *_numTranslate);
143
144 /// Adds an element v at the connection from source to target.
145 void operator () (int_t source, int_t target, int_t v);
146
147private:
148 /// The Morse decomposition in which to record the connections.
150
151 /// The numbers of Morse sets in the Morse decomposition
152 /// that correspond to their indices given by source and target.
153 const std::vector<int> &setNumbers;
154
155 /// The set which contains cubes to add.
156 const spcCubes &X;
157
158 /// The translation table for vertex numbers in the connections.
159 const int_t *numTranslate;
160
161}; /* class TConnMorse */
162
164 const std::vector<int> &_setNumbers, const spcCubes &spcX,
165 const int_t *_numTranslate): morseDec (_morseDec),
166 setNumbers (_setNumbers), X (spcX), numTranslate (_numTranslate)
167{
168 return;
169} /* TConnMorse::TConnMorse */
170
171inline void TConnMorse::operator () (int_t source, int_t target, int_t v)
172{
173 morseDec. addconn (setNumbers [source], setNumbers [target],
174 X [numTranslate [v]]);
175 return;
176} /* TConnMorse::operator () */
177
178
179// --------------------------------------------------
180// ------------ Conley index computation ------------
181// --------------------------------------------------
182
183/// This small auxiliary procedure sets a dummy Conley index to the given
184/// Morse set. The Conley index is set to be trivial, unless it is requested
185/// that a number of a Betti number is provided to be set to 1.
186inline void setDummyIndex (theMorseDecompositionType &morseDec, int n,
187 int nonzero = -1)
188{
189 int betti [spaceDim + 1];
190 for (int i = 0; i <= spaceDim; ++ i)
191 betti [i] = (i == nonzero) ? 1 : 0;
193 ind. define (betti, spaceDim);
194 morseDec. setindex (n, ind);
195 return;
196} /* setDummyIndex */
197
198/// Verifies that the provided Morse set can be used as a basis
199/// for a Conley index pair and computes the Conley index.
200/// If this verification fails then subdivides the Morse set
201/// and repeats the procedure restricted to the invariant part of the set.
202/// Returns 0 if succeeds or -1 in the case of failure.
203/// Makes a note of having reached the subdivision limit or having come
204/// across empty invariant part in the provided variable
205/// which is set to 1 in the former case and 0 in the latter
206/// (otherwise it is not modified).
207/// If a problem with isolation is encountered then sets "noIsolation" to 1.
208/// If the index pair is computed then sets the value of the variable
209/// which remembers if this is an attractor (empty exit set) or not.
211 const double *offset, const double *width,
212 int subdivDepth, const theMapType &theMap,
213 const theCubMapType &theCubMap0, const theCubMapType &theCubMap1,
214 int &subdivNonemptyInv, int &noIsolation, int &attractor)
215{
216 using chomp::homology::sbug;
217
218 // check the images to make sure that all of them are contained
219 // in the rectangular region of the given depth
220 spcCubes X;
221 for (int subdivisions = 0;; ++ subdivisions)
222 {
223 // determine the combinatorial map to use
224 theCubMapType subdivCubMap (offset, width,
225 1 << (subdivDepth + subdivisions),
226 subdivDepth + subdivisions, theMap);
227 if (subdivisions > 1)
228 {
229 subdivCubMap. setAllowedImgSize
230 (maxImageDiameter << 3, maxImageVolume << 3);
231 }
232 subdivCubMap. cache = false;
233 const theCubMapType &theCubMap =
234 (subdivisions > 1) ? subdivCubMap :
235 (subdivisions ? theCubMap1 : theCubMap0);
236 bool crop = theCubMap. cropping;
237
238 // restrict the set to its invariant part if necessary
239 if (subdivisions)
240 {
241 try
242 {
243 int result = invariantPart (X, theCubMap);
244 if (result < 0)
245 {
246 sbug << "An error occurred while "
247 "computing Inv(X).\n";
248 subdivNonemptyInv = 1;
249 return -1;
250 }
251 if (X. empty ())
252 {
253 sbug << "Inv(X) turned out to be "
254 "empty.\n";
255 setDummyIndex (morseDec, n);
256 subdivNonemptyInv = 0;
257 return 0;
258 }
259 }
260 catch (const char *msg)
261 {
262 subdivNonemptyInv = 1;
263 sbug << "Failed: " << msg << "\n";
264 sbug << "Failure: Unable to compute Inv.\n";
265 return -1;
266 }
267 }
268
269 // determine the set of cubes for which to compute the index
270 const spcCubes &theSet = subdivisions ? X : morseDec [n];
271
272 // try computing the Conley index using this set
273 // as a basis for the index pair
274 try
275 {
276 // set appropriate space wrapping
277 localSpaceWrapping wrapping
278 (1 << (subdivDepth + subdivisions));
279
280 // create an index pair object
281 theIndexPairType P (theCubMap);
282
283 // add cubes to the core part of the index pair
284 int size = theSet. size ();
285 for (int i = 0; i < size; ++ i)
286 P. add (theSet [i]);
287
288 // compute the map on the index pair
289 theCubMap. cropping = wrapping ? false : true;
290 theCubMap. cropped = false;
291 P. compute ();
292 theCubMap. cropping = crop;
293
294 // correctness check: if cropping is not allowed
295 // then an attempt of cropping should have caused
296 // an exception thrown, so this condition should
297 // never happen
299 theCubMap. cropped)
300 {
301 throw "Image cropped without permission!!!";
302 }
303
304 // verify if this is an attractor
305 attractor = P. countExit () ? 0 : 1;
306
307 // create the Conley index object
309 ind. setIndexPair (&P);
310
311 // compute the index
312 ind. compute ();
313 ind. setIndexPair (0);
314
315 // set the index of the Morse set
316 morseDec. setindex (n, ind);
317 return 0;
318 }
319 catch (const char *msg)
320 {
321 theCubMap. cropping = crop;
322 sbug << "Failed: " << msg << "\n";
323 }
324
325 // if the maximal subdivision level was reached then cancel
326 if (subdivisions == refineDepth)
327 {
328 sbug << "Failure: Max refinement depth " <<
329 refineDepth << " reached.\n";
330 subdivNonemptyInv = 1;
331 if (theCubMap. cropped)
332 noIsolation = 1;
333 return -1;
334 }
335
336 // determine the maximal allowed size of a set to refine
337 int maxRefineSize =
338 subdivisions ? maxRefineSize1 : maxRefineSize0;
339
340 // if the set is too large to subdivide then cancel
341 if (theSet. size () > maxRefineSize)
342 {
343 sbug << "Failure: Not subdividing" <<
344 (subdivisions ? " anymore" : "") <<
345 ", because the set size " <<
346 theSet. size () << "\nis beyond the max "
347 "allowed " << maxRefineSize << ".\n";
348 // sbug << "DEBUG: cropped = " << theCubMap. cropped << ".\n";
349 // sbug << "DEBUG: noIsolation = " << noIsolation << ".\n";
350 subdivNonemptyInv = 1;
351 if (theCubMap. cropped)
352 noIsolation = 1;
353 return -1;
354 }
355
356 // subdivide the set
357 sbug << "- subdiv " << (subdivDepth + subdivisions + 1) <<
358 ": " << theSet. size () << " -> ";
359 spcCubes Y;
360 subdivideCubes (theSet, Y);
361 spcCubes emptySet;
362 X = emptySet;
363 X. swap (Y);
364 sbug << X. size () << " ";
365 }
366
367 return -1;
368} /* computeConleyIndex */
369
370
371// --------------------------------------------------
372// -------------- chain recurrent set ---------------
373// --------------------------------------------------
374
375/// Computes the chain recurrent set of X.
376/// Note: The resulting set may be taken the same as X
377/// if one wants to replace the set with its chain recurrent set.
378template <class typeCubes>
379void chainRecurrentSet (const typeCubes &X, typeCubes &result,
380 const chomp::homology::diGraph<> &g)
381{
382 using chomp::homology::diGraph;
383 using chomp::homology::multitable;
384
385 typeCubes Y;
386
387 // make the result an empty set if the set X is empty
388 if (X. empty ())
389 {
390 result. swap (Y);
391 return;
392 }
393
394 // compute the components of the chain recurrent set of the graph
395 multitable<int_t> compVertices (8192);
396 multitable<int_t> compEnds (8192);
397 diGraph<> *sccAddr = 0;
398 diGraph<> *transpAddr = 0;
399 int_t nSets = chomp::homology::SCC (g, compVertices, compEnds,
400 sccAddr, transpAddr);
401
402 // create the union of the boxes corresponding to the SCCs
403 for (int_t n = 0; n < nSets; ++ n)
404 {
405 // determine the vertex range of this set
406 int_t beginVertex = n ? compEnds [n - 1] :
407 static_cast<int_t> (0);
408 int_t endVertex = compEnds [n];
409
410 // add the cubes to the Morse set
411 for (int_t i = beginVertex; i < endVertex; ++ i)
412 Y. add (X [compVertices [i]]);
413 }
414
415 result. swap (Y);
416 return;
417} /* chainRecurrentSet */
418
419
420// --------------------------------------------------
421// ----------- inv & Morse decomposition ------------
422// --------------------------------------------------
423
424/// Computes a Conley-Morse decomposition of ChainRecSet (X).
425/// The combinatorial cubical multivalued map F is encoded
426/// in the directed graph provided.
427/// The Morse decomposition structure must be initially empty.
428/// The arguments "offset", "width", "subdivDepth" and "theMap"
429/// are only necessary for the purpose of refining trivial Morse sets.
430/// The global constants "refineDepth", "maxRefineSize0" and "maxRefineSize1"
431/// determine, respectively, the maximal allowed refinement depth,
432/// and the maximal size of a cubical set which is refined if necessary.
433/// Further simplification of the computed Morse decomposition is done
434/// by joining Morse sets (see the description in "morsedec.h" for details).
435/// If requested, the Conley indices of Morse sets which have at least
436/// the given number of boxes are not computed (they are set to be trivial).
437/// If a file name prefix is nonempty then an attempt is being made
438/// to read cached Morse decomposition information from a file.
439template <class typeCubes, class typeMorseDec>
440void invMorseDec (const typeCubes &X, const chomp::homology::diGraph<> &g,
441 typeMorseDec &morseDec,
442 const double *offset, const double *width, int subdivDepth,
443 const theMapType &theMap,
444 const theCubMapType &theCubMap0, const theCubMapType &theCubMap1,
445 int_t skipIndices,
446 const std::string &cacheFileName, bool &morseDecComputed,
447 std::vector<int> &wrongIndices, std::vector<int> &skippedIndices,
448 std::vector<int> &attractors, bool connOrbits,
449 const double *leftMapParam, const double *rightMapParam,
450 int paramCount, chomp::homology::timeused &timeSubdiv)
451{
452 using chomp::homology::sbug;
453 using chomp::homology::diGraph;
454 using chomp::homology::multitable;
455 using chomp::homology::hashedset;
456 using chomp::homology::timeused;
457
458 // do nothing if the set X is empty
459 if (X. empty ())
460 {
461 sbug << "0.\n";
462 return;
463 }
464
465 // compute the components of the chain recurrent set of the graph
466 multitable<int_t> compVertices (8192);
467 multitable<int_t> compEnds (8192);
468 diGraph<> *sccAddr = 0;
469 diGraph<> *transpAddr = /*(savebasmin || savebasmax) ? &gT :*/ 0;
470 int_t nSets_big = chomp::homology::SCC (g, compVertices, compEnds,
471 sccAddr, transpAddr);
472 int_t nCubes = (nSets_big > 0) ? compEnds [nSets_big - 1] : 0;
473 sbug << nCubes << " (" << nSets_big << " sets).\n";
474 sbug << "Volume of the union of the Morse sets: " <<
475 cubesVolume (nCubes, subdivDepth) << ".\n";
476 sbug << "Morse decomp computed in " << timeSubdiv << ".\n";
477 int nSets = static_cast<int> (nSets_big);
478 if (static_cast<int_t> (nSets) != nSets_big)
479 throw "The number of Morse sets exceeds reasonable limits.";
480
481 // stop here if there are no recurrent components
482 // (this correction was suggested by Marcio Gameiro; thanks!)
483 if (!nSets)
484 return;
485
486 // prepare file names if necessary
487 bool cacheIndices = !cacheFileName. empty ();
488 std::string indFileNameStr = cacheFileName;
489 const char *indFileName = indFileNameStr. c_str ();
490 std::string lockFileNameStr = cacheFileName + ".lock";
491 const char *lockFileName = lockFileNameStr. c_str ();
492
493 // create the Morse decomposition data structure
494 // and count the number of cubes in the SCCs
495 timeused timeSetMorseDec;
496 timeSetMorseDec = 0;
497 sbug << "Initializing the MorseDec data structure... ";
498 morseDec. setnumber (nSets);
499 int_t countSCCcubes = 0;
500 for (int n = 0; n < nSets; ++ n)
501 {
502 // determine the vertex range of this set
503 int_t beginVertex = n ? compEnds [n - 1] :
504 static_cast<int_t> (0);
505 int_t endVertex = compEnds [n];
506 countSCCcubes += endVertex - beginVertex;
507
508 // add the cubes to the Morse set
509 for (int_t i = beginVertex; i < endVertex; ++ i)
510 morseDec. add (n, X [compVertices [i]]);
511 }
512 sbug << timeSetMorseDec << ".\n";
513
514 // verify if all the Morse sets are isolated
515 // from the outside of the box by at least one cube layer
516 sbug << "Checking isolation of the Morse sets... ";
517 bool isolated = true;
518 for (int n = 0; n < nSets; ++ n)
519 {
520 if (checkIsolation (morseDec [n], subdivDepth))
521 continue;
522 isolated = false;
523 break;
524 }
525 sbug << (isolated ? "[isolated]\n" : "[no isol]\n");
526
527 // retrieve the Conley indices from cache if possible
528 timeused timeConleyIndices;
529 timeConleyIndices = 0;
530 bool cachedAvailable = false;
531 IndexCache cached (nSets);
532 if (cacheIndices && fileExists (indFileName))
533 {
534 if (fileExists (lockFileName))
535 sbug << "! Skipping cached indices (locked).\n";
536 else if (cached. read (indFileName, morseDec) != 0)
537 sbug << "! Error while reading cached indices.\n";
538 else
539 {
540 sbug << "[using cached Conley indices]\n";
541 cachedAvailable = true;
542 }
543 }
544 morseDecComputed = !cachedAvailable;
545
546 // find small Morse sets whose invariant part is empty
547 std::vector<int> subdivNonemptyInv (nSets, -1);
548 if (!cachedAvailable)
549 {
550 timeused timeEmptyInv;
551 timeEmptyInv = 0;
552 sbug << "Checking small Morse sets for empty inv...\n";
553 for (int n = 0; n < nSets; ++ n)
554 {
555 // if the size of the set is too large then skip it
556 if (morseDec [n]. size () > maxRefineSize0)
557 continue;
558
559 // refine the set and check if its inv is nonempty
560 if (checkEmptyInv (morseDec [n], finalDepth,
561 offset, width, theMap,
562 theCubMap0, theCubMap1))
563 {
564 subdivNonemptyInv [n] = 0;
565 cached. emptyInv [n] = true;
566 }
567 }
568 sbug << "Invariant part of small Morse sets checked in " <<
569 timeEmptyInv << ".\n";
570 }
571
572#ifdef CONFIG_NOCONNECTIONS
573 sbug << "Note: Skippnig the computation of connecting orbits.\n";
574// bool computeconn = false;
575#else
576 {
577 // determine if it is necessary to compute the connecting
578 // orbits in terms of cubical sets
579 bool computeconn = connOrbits || (maxJoinSize > 0);
580
581 // compute the connecting orbits for the Morse decomposition
582 timeused timeConnOrb;
583 timeConnOrb = 0;
584
585 // prepare numbers of Morse sets with possibly nonempty inv
586 std::vector<int> setNumbers1;
587 for (int n = 0; n < nSets; ++ n)
588 {
589 if (cachedAvailable && cached. emptyInv [n])
590 continue;
591 if (subdivNonemptyInv [n] == 0)
592 continue;
593 setNumbers1. push_back (n);
594 }
595 int nSets1 (setNumbers1. size ());
596
597 sbug << "Computing connecting orbits between " << nSets1 <<
598 " sets... ";
599
600 // prepare tables with the corresponding components
601 multitable<int_t> compVertices1 (8192);
602 multitable<int_t> compEnds1 (8192);
603 int cur (0);
604 for (int i = 0; i < nSets1; ++ i)
605 {
606 int n (setNumbers1 [i]);
607 for (int j = n ? compEnds [n - 1] : 0;
608 j < compEnds [n]; ++ j)
609 {
610 compVertices1 [cur ++] = compVertices [j];
611 }
612 compEnds1 [i] = cur;
613 }
614
615 // create a graph in which possibly nontrivial Morse sets
616 // are collapsed to single vertices of the graph
617 int_t *newNumbers = computeconn ? new int_t [X. size ()] : 0;
618 diGraph<> collapsed;
619 chomp::homology::collapseVertices (g, nSets1, compVertices1,
620 compEnds1, collapsed, newNumbers);
621
622 // prepare a translation table for vertex numbers
623 int_t *oldNumbers = computeconn ? new int_t [X. size ()] : 0;
624 if (oldNumbers)
625 {
626 for (int_t i = 0; i < X. size (); ++ i)
627 oldNumbers [newNumbers [i]] = i;
628 }
629 if (newNumbers)
630 delete [] newNumbers;
631
632 // compute the connecting orbits and the connection graph
633 diGraph<> connGraph;
634 if (computeconn)
635 {
636 TConnMorse conn (morseDec, setNumbers1,
637 X, oldNumbers);
638 chomp::homology::inclusionGraph (collapsed, nSets1,
639 connGraph, conn);
640 }
641 else
642 {
643 chomp::homology::inclusionGraph (collapsed, nSets1,
644 connGraph);
645 }
646 if (oldNumbers)
647 delete [] oldNumbers;
648
649 // store the connections in the Morse decomposition structure
650 for (int v = 0; v < nSets1; ++ v)
651 {
652 int_t nEdges = connGraph. countEdges (v);
653 for (int_t e = 0; e < nEdges; ++ e)
654 {
655 int_t w = connGraph. getEdge (v, e);
656 morseDec. addconn (setNumbers1 [v],
657 setNumbers1 [w]);
658 }
659 }
660
661 // show the time used for computing connecting orbits
662 sbug << timeConnOrb << ".\n";
663 }
664#endif
665
666 // compute the Conley indices of the Morse sets
667 spcCubes wrongCubes;
668 spcCubes attrCubes;
669 spcCubes skipCubes;
670 for (int n = 0; n < nSets; ++ n)
671 {
672 if (cachedAvailable)
673 {
674 if (cached. wrongIndex [n])
675 wrongCubes. add (morseDec [n] [0]);
676 if (cached. attractor [n])
677 attrCubes. add (morseDec [n] [0]);
678 if (cached. skipped [n])
679 skipCubes. add (morseDec [n] [0]);
680 continue;
681 }
682
683 // skip the computation of the Conley index
684 // if it is known that its invariant part is empty
685 if (subdivNonemptyInv [n] == 0)
686 {
687 setDummyIndex (morseDec, n);
688 continue;
689 }
690
691 // skip the computation of the Conley index if requested to
692 if ((skipIndices > 0) &&
693 (morseDec [n]. size () >= skipIndices))
694 {
695 sbug << "* Skipping ConIndex (" << n << ").\n";
696 setDummyIndex (morseDec, n);
697 //??? subdivNonemptyInv [n] = 1;
698 cached. skipped [n] = true;
699 skipCubes. add (morseDec [n] [0]);
700 }
701 // or compute the Conley index
702 else
703 {
704 sbug << "* Computing Conley index of Morse Set " <<
705 n << " of " << nSets << " (" <<
706 morseDec [n]. size () << " cubes)...\n";
707 int noIsolation = -1;
708 int attractor = -1;
709 int result = computeConleyIndex (morseDec, n,
710 offset, width, subdivDepth, theMap,
711 theCubMap0, theCubMap1,
712 subdivNonemptyInv [n], noIsolation,
713 attractor);
714 if (attractor > 0)
715 {
716 cached. attractor [n] = true;
717 attrCubes. add (morseDec [n] [0]);
718 }
719 if (((result < 0) || (noIsolation > 0)) &&
720 setConleyIndex (morseDec, n, subdivDepth,
721 leftMapParam, rightMapParam, paramCount))
722 {
723 sbug << "* The index was set to an apriori "
724 "known one.\n";
725 }
726 else if (result < 0)
727 {
728 sbug << "* Failed to compute the index.\n";
729 setDummyIndex (morseDec, n);
730 cached. wrongIndex [n] = true;
731 cached. skipped [n] = true;
732 skipCubes. add (morseDec [n] [0]);
733 }
734 else if (noIsolation > 0)
735 {
736 sbug << "* No isolation detected. The index "
737 "could not be computed reliably.\n";
738 cached. wrongIndex [n] = true;
739 wrongCubes. add (morseDec [n] [0]);
740 }
741 else
742 {
743 sbug << "* The computed index is " <<
744 (morseDec. trivial (n) ?
745 "" : "non") << "trivial.\n";
746 }
747 }
748 }
749 sbug << "Conley indices determined in " <<
750 timeConleyIndices << ".\n";
751
752 // make a note of the Morse sets whose invariant part is empty
753 timeused timePassThru;
754 timePassThru = 0;
755 hashedset<int> passThru;
756 for (int n = 0; n < nSets; ++ n)
757 {
758 // if the cached result is available then use it
759 if (cachedAvailable)
760 {
761 if (cached. emptyInv [n])
762 passThru. push_back (n);
763 continue;
764 }
765
766 // if refinements were already tried and failed then skip it
767 if (subdivNonemptyInv [n] == 1)
768 continue;
769
770 // if refinements have already proved that inv is empty
771 // then make a note of it
772 if (subdivNonemptyInv [n] == 0)
773 {
774 passThru. push_back (n);
775 cached. emptyInv [n] = true;
776 continue;
777 }
778
779 // if the Conley index is nontrivial then inv is nonempty
780 if (morseDec. computed (n) && !morseDec. trivial (n))
781 continue;
782
783 // if the size of the set is too large then skip it
784 if (morseDec [n]. size () > maxRefineSize0)
785 continue;
786
787 // refine the set and check if its inv is nonempty
788 sbug << "Refining the set no. " << n << " (" <<
789 morseDec [n]. size () << " cubes)...\n";
790 if (checkEmptyInv (morseDec [n], finalDepth,
791 offset, width, theMap, theCubMap0, theCubMap1))
792 {
793 sbug << "Empty inv. The set will be removed.\n";
794 passThru. push_back (n);
795 cached. emptyInv [n] = true;
796 }
797 else
798 {
799 sbug << "Invariant part may be nonempty.\n";
800 }
801 }
802 sbug << "Morse sets with trivial indices analysed in " <<
803 timePassThru << ".\n";
804
805 // save the Conley indices and the information on empty inv
806 // to a file if they were computed and a file name prefix is provided
807 if (cacheIndices && !cachedAvailable && !fileExists (indFileName) &&
808 !fileExists (lockFileName))
809 {
810 // create the lock file
811 std::ofstream lockFile (lockFileName);
812 lockFile. close ();
813
814 // write the cached index information
815 cached. write (indFileName, morseDec);
816
817 // remove the lock file
818 std::remove (lockFileName);
819 }
820
821 // remove Morse sets whose invariant part is proven to be empty
822 if (!passThru. empty ())
823 {
824 sbug << "Removing " << passThru. size () <<
825 " spurious Morse sets... ";
826 timeused timeRemoving;
827 timeRemoving = 0;
828#ifdef CONFIG_NOCONNECTIONS
829 if ((passThru. size () > 20) &&
830 (passThru. size () > 0.8 * morseDec. count ()))
831 {
832 sbug << "[Q] ";
833
834 // determine the sizes of the Morse decompositions
835 int_t oldSize = morseDec. count ();
836 int_t newSize = morseDec. count () -
837 passThru. size ();
838
839 // create a new Morse decomposition
840 typeMorseDec newMorseDec (theCubMap0);
841 newMorseDec. setnumber (newSize);
842
843 // swap in the data from the old Morse decomposition
844 int_t newNumber = 0;
845 for (int_t oldNumber = 0; oldNumber < oldSize;
846 ++ oldNumber)
847 {
848 // if this set is to be skipped
849 if (passThru. check (oldNumber))
850 continue;
851
852 // if this set is to remain
853 newMorseDec [newNumber]. swap
854 (morseDec [oldNumber]);
855 if (morseDec. computed (oldNumber))
856 {
857 newMorseDec. setindex (newNumber,
858 morseDec. index (oldNumber));
859 }
860 ++ newNumber;
861 }
862 if (newNumber != newSize)
863 throw "A bug in the pass-through loop.";
864
865 // swap the Morse decompositions
866 morseDec. swap (newMorseDec);
867 }
868 else
869 {
870 for (int i = passThru. size () - 1; i >= 0; -- i)
871 {
872 morseDec. passthru (passThru [i]);
873 }
874 }
875#else
876 for (int i = passThru. size () - 1; i >= 0; -- i)
877 {
878 morseDec. passthru (passThru [i]);
879 }
880#endif
881 sbug << timeRemoving << ".\n";
882 }
883
884 // manipulate the Morse decomposition to make it a coarser one
885 if (maxJoinSize > 0)
886 {
887 sbug << "* " << morseDec. count () << " Morse sets; sizes: ";
888 for (int i = 0; i < morseDec. count (); ++ i)
889 sbug << (i ? " " : "") << morseDec [i]. size ();
890 sbug << "\n! Joining trivial Morse sets (size: " <<
891 maxJoinSize << ", conn: " << maxJoinConnection <<
892 ", dist: " << maxJoinDistance << ")...\n";
893 morseDec. jointrivial (maxJoinSize, maxJoinConnection,
895 }
896
897 // remember the new number of Morse sets in the Morse decomposition
898 nSets = morseDec. count ();
899
900 // determine the numbers of new Morse sets whose indices could not
901 // be computed
902 for (int_t i = 0; i < wrongCubes. size (); ++ i)
903 {
904 int n = 0;
905 while ((n < nSets) && !morseDec [n]. check (wrongCubes [i]))
906 ++ n;
907 if (n < nSets)
908 wrongIndices. push_back (n);
909 else
910 {
911 wrongIndices. push_back (-1);
912 sbug << "Note: A Morse set with a wrong index "
913 "could not be identified.\n";
914 }
915 }
916
917 // determine the numbers of new Morse sets whose indices were skipped
918 for (int_t i = 0; i < skipCubes. size (); ++ i)
919 {
920 int n = 0;
921 while ((n < nSets) && !morseDec [n]. check (skipCubes [i]))
922 ++ n;
923 if (n < nSets)
924 skippedIndices. push_back (n);
925 else
926 {
927 skippedIndices. push_back (-1);
928 sbug << "Note: A Morse set whose index was skipped "
929 "could not be identified.\n";
930 }
931 }
932
933 // determine the numbers of new Morse sets which are attractors
934 for (int_t i = 0; i < attrCubes. size (); ++ i)
935 {
936 int n = 0;
937 while ((n < nSets) && !morseDec [n]. check (attrCubes [i]))
938 ++ n;
939 if (n < nSets)
940 attractors. push_back (n);
941 else
942 {
943 attractors. push_back (-1);
944 sbug << "Note: A Morse set which is an attractor "
945 "could not be identified.\n";
946 }
947 }
948
949 // verify if all the new Morse sets are isolated
950 // from the outside of the box by at least one cube layer
951 sbug << "Checking isolation of the final Morse sets... ";
952 bool finalIsolated = true;
953 for (int n = 0; n < nSets; ++ n)
954 {
955 if (checkIsolation (morseDec [n], subdivDepth))
956 continue;
957 finalIsolated = false;
958 break;
959 }
960 sbug << (finalIsolated ? "[isolated]\n" : "[no isol]\n");
961
962 // show a summary information
963 sbug << "* " << morseDec. count () << " Morse sets [" <<
964 attrCubes. size () << " attractor(s)]; sizes: ";
965 for (int i = 0; i < morseDec. count (); ++ i)
966 sbug << (i ? " " : "") << morseDec [i]. size ();
967 sbug << ".\n";
968
969 // compute the min and max coordinates of Morse sets
970 CoordMinMax coordMinMax;
971 int_t nMorseSets = morseDec. count ();
972 for (int_t nSet = 0; nSet < nMorseSets; ++ nSet)
973 coordMinMax (morseDec [nSet]);
974 if (coordMinMax. defined ())
975 {
976 sbug << "The computed Morse sets are in " <<
977 coordMinMax << ".\n";
978 sbug << "Real coordinates: ";
979 showRealCoords (sbug, coordMinMax) << ".\n";
980 }
981
982 return;
983} /* invMorseDec */
984
985
986// --------------------------------------------------
987// -------------- Morse Decomposition ---------------
988// --------------------------------------------------
989
990/// Computes the Morse decomposition using all the pre- and postprocessing.
991/// The target Morse decomposition object must be already initialized
992/// with the right map which is to be used to compute the Conley indices
993/// of the Morse sets.
994/// If a file name prefix is nonempty then an attempt is being made
995/// to read cached Morse decomposition information from a file.
997 (theMapType &theMap,
998 const theCubMapType theCubMap0, const theCubMapType theCubMap1,
999 const double *offset, const double *width, int_t skipIndices,
1000 const std::string &cacheFileName,
1001 const std::string &pictureFileName,
1002 const std::string &cubesFilePrefix,
1003 const std::string &morseDecFileName,
1004 const std::string &graphFileName,
1005 const std::string &procFilePrefix,
1006 const std::string &mapOptFileName,
1007 bool &morseDecComputed,
1008 std::vector<int> &wrongIndices, std::vector<int> &skippedIndices,
1009 std::vector<int> &attractors, bool connOrbits,
1010 const double *leftMapParam, const double *rightMapParam,
1011 int paramCount)
1012{
1013 using chomp::homology::sbug;
1014 using chomp::homology::sout;
1015 using chomp::homology::diGraph;
1016 using chomp::homology::timeused;
1017
1018 // start measuring time of the subdivisions
1019 timeused timeSubdiv;
1020 timeSubdiv = 0;
1021
1022 // check for the presence of local map optimization hints
1023 // and use them if they are available
1024 bool mapOptRead = false;
1025 if (!mapOptFileName. empty () &&
1026 fileExists (mapOptFileName. c_str ()))
1027 {
1028 std::ifstream in (mapOptFileName. c_str ());
1029 std::string str;
1030 in >> str;
1031 chomp::homology::ignorecomments (in);
1032 if ((str. size () > 0) && (in. peek () == 'D'))
1033 {
1034 chomp::multiwork::mwData data;
1035 text2data (str, data);
1036 theMap. loadInternals (data);
1037 mapOptRead = true;
1038 sbug << "[using previous map optimization data]\n";
1039 }
1040 }
1041
1042 // create an empty Morse decomposition
1043 theMorseDecompositionType *morseDecPtr =
1044 new theMorseDecompositionType (theCubMap0);
1045 theMorseDecompositionType &morseDec = *morseDecPtr;
1046
1047 // retrieve the Morse decomposition and the auxiliary data
1048 // from a temporary binary compressed file if the file is available
1049 if (!morseDecFileName. empty () &&
1050 fileExists (morseDecFileName. c_str ()))
1051 {
1052 sbug << "Loading Morse dec cache... ";
1053 using chomp::homology::program_time;
1054 double start_load_time (program_time);
1055 loadMorseDecCache (morseDecFileName. c_str (), morseDec,
1056 wrongIndices, skippedIndices, attractors);
1057 double end_load_time (program_time);
1058 sbug << "(" << static_cast<long> ((end_load_time -
1059 start_load_time) * 100) / 100 << " sec.)\n";
1060 }
1061
1062 // otherwise compute the Morse decomposition
1063 else
1064 {
1065
1066 // create a cubical set with one cube
1067 spcCoord zero [spaceDim];
1068 for (int i = 0; i < spaceDim; ++ i)
1069 zero [i] = 0;
1070 spcCubes X;
1071 X. add (spcCube (zero, spaceDim));
1072
1073 // TEMPORARY CODE for GLOBCLOG (discussion on 2010-05-06)
1074 spcCubes restriction;
1075 bool restrictionRead = false;
1076 {
1077 std::ifstream restr ("restriction.cub");
1078 if (restr)
1079 {
1080 sout << "\n*** Restricting to a subset: ";
1081 restr >> restriction;
1082 sout << restriction. size () << " cubes. ***\n";
1083 restrictionRead = true;
1084 }
1085 }
1086
1087 // make the subdivision(s)
1088 for (int subdivDepth = 1; subdivDepth <= finalDepth; ++ subdivDepth)
1089 {
1090 // use the restriction cubes for X
1091 // or subdivide all the cubes in X
1092 {
1093 if (subdivDepth >= initialDepth)
1094 sbug << "Depth " << subdivDepth << ": ";
1095 if (restrictionRead && (subdivDepth <= initialDepth))
1096 {
1097 if (subdivDepth == initialDepth)
1098 X. swap (restriction);
1099 }
1100 else
1101 {
1102 spcCubes Y;
1103 subdivideCubes (X, Y);
1104 X. swap (Y);
1105 }
1106 if (subdivDepth >= initialDepth)
1107 sbug << X. size () << ". ";
1108 }
1109
1110 // if the initial subdivision depth has not been reached yet
1111 // then skip the computation of the invariant part
1112 if (subdivDepth < initialDepth)
1113 continue;
1114
1115 // shuffle the set of cubes so that the ODE integration
1116 // sapmles the entire phase space more or less uniformly
1117 moveSomeToFront (X, 1 << spaceDim);
1118
1119 // prepare a local multivalued cubical map
1120 // at this subdivision depth
1121 theCubMapType localCubMap (offset, width,
1122 1 << subdivDepth, subdivDepth, theMap);
1123
1124 // extract the multivalued cubical map
1125 // from the Morse decomposition if this is the final depth
1126 const theCubMapType &theCubMap =
1127 (subdivDepth == finalDepth) ?
1128 theCubMap0 : localCubMap;
1129
1130 // set the default limitations on image size
1131 theCubMap. setAllowedImgSize (maxImageDiameter,
1133
1134 // measure time of the construction of the graph of the map
1135 timeused timeMap;
1136 timeMap = 0;
1137
1138#ifdef CONFIG_ODEVART
1139 // prepare a set of cubes to be added to X
1140 // to make a necessary correction for isolation
1141 spcCubes Xadd;
1142#endif
1143 // compute the graph of the multivalued cubical map on X
1144 sbug << "F... ";
1145 diGraph<> g;
1146 while (1)
1147 {
1148 // try the computation with the current map
1149 try
1150 {
1151#ifdef CONFIG_ODEVART
1152 // compute the graph of the map and compute
1153 // a set that should be added to X
1154 // to preserve the isolation condition
1155 {
1156 spcCubes empty;
1157 Xadd. swap (empty);
1158 }
1159 int_t maxAdd (std::max
1160 (static_cast<int_t> (10000),
1161 X. size () / 100));
1162 computeMapGraphIsol (X, g, theCubMap, Xadd,
1163 maxAdd);
1164#else
1165 // compute the graph of the map
1166 computeMapGraph (X, g, theCubMap);
1167#endif
1168
1169 // show the avg size of the image of a cube
1170 int_t avgImgSize = g. countVertices () ?
1171 (g. countEdges () /
1172 g. countVertices ()) : 0;
1173 sbug << "[avg " << avgImgSize << "] ";
1174
1175 // show the time of computation of the map
1176 sbug << "(" << double2string
1177 (static_cast<double> (timeMap), 1) <<
1178 " sec) ";
1179
1180 // if there are no edges in the graph then OK
1181 if (!g. countEdges ())
1182 break;
1183
1184 // if it is not necessary to repeat then OK
1185 if (!theMap. adjust (true, subdivDepth))
1186 break;
1187 }
1188 // in case of failure, try adjusting the map;
1189 // if it is not possible to repeat then quit
1190 catch (const char *msg)
1191 {
1192 resetRounding ();
1193 sbug << "Failed (" << double2string
1194 (static_cast<double> (timeMap), 1) <<
1195 " sec).\nFailure reason: " <<
1196 msg << ".\n";
1197 if (!theMap. adjust (false, subdivDepth))
1198 throw;
1199 }
1200 catch (const std::exception &e)
1201 {
1202 resetRounding ();
1203 sbug << "Failed (" << double2string
1204 (static_cast<double> (timeMap), 1) <<
1205 " sec).\nFailure reason: " <<
1206 e. what () << "\n";
1207 if (!theMap. adjust (false, subdivDepth))
1208 throw;
1209 }
1210
1211 // forget the map cache and the graph
1212 // before trying again
1213 theCubMap. cleanCache ();
1214 diGraph<> dummy;
1215 g. swap (dummy);
1216 timeMap. reset ();
1217 }
1218
1219#ifdef CONFIG_ODEVART
1220 // add the computed correction to the set of cubes X
1221 X. add (Xadd);
1222#endif
1223
1224 // compute the requested Morse decomposition
1225 // if this is the final subdivision level
1226 if (subdivDepth == finalDepth)
1227 {
1228 // save the local map optimization data to a file
1229 if (!mapOptRead && !mapOptFileName. empty () &&
1230 !fileExists (mapOptFileName. c_str ()))
1231 {
1232 chomp::multiwork::mwData data;
1233 theMap. saveInternals (data);
1234 std::string str (data2text (data));
1235 std::ofstream out (mapOptFileName. c_str ());
1236 out << str << " D\n";
1237 sbug << "[map optimization data saved]\n";
1238 }
1239
1240 // set new limitations on image size to make sure
1241 // that the computations are not interrupted
1242 theCubMap0. setAllowedImgSize
1243 (maxImageDiameter << 3, maxImageVolume << 3);
1244 theCubMap1. setAllowedImgSize
1245 (maxImageDiameter << 3, maxImageVolume << 3);
1246
1247 // compute the Morse decomposition
1248 sbug << "Morse dec... ";
1249 invMorseDec (X, g, morseDec,
1250 offset, width, subdivDepth,
1251 theMap, theCubMap0, theCubMap1,
1252 skipIndices, cacheFileName, morseDecComputed,
1253 wrongIndices, skippedIndices, attractors,
1254 connOrbits, leftMapParam, rightMapParam,
1255 paramCount, timeSubdiv);
1256
1257 // turn on space wrapping if necessary
1258 localSpaceWrapping wrapping (1 << subdivDepth);
1259
1260 // run any extra analysis of the Morse decomposition,
1261 // unless already done before
1262 bool alreadyProcessed = false;
1263 if (!procFilePrefix. empty ())
1264 {
1265 std::string procMarkerName =
1266 procFilePrefix + ".mark";
1267 if (fileExists (procMarkerName. c_str ()))
1268 alreadyProcessed = true;
1269 else
1270 {
1271 std::ofstream markerFile
1272 (procMarkerName. c_str ());
1273 markerFile. close ();
1274 }
1275 }
1276 if (!alreadyProcessed)
1277 {
1278 processMorseDec (morseDec, X, g,
1279 theCubMap0, theCubMap1,
1280 cubesFilePrefix, procFilePrefix);
1281 }
1282 break;
1283 }
1284
1285 // compute the invariant part of the map on X
1286#ifdef CONFIG_NOCONNECTIONS
1287 sbug << "ChRec... ";
1288 chainRecurrentSet (X, X, g);
1289#else
1290 sbug << "Inv... ";
1291 invariantPart (X, g);
1292#endif
1293 sbug << X. size () << " ";
1294#ifdef CONFIG_ENHANCEINV
1295 sbug << "E" << CONFIG_ENHANCEINV << ": ";
1296 enhanceCubes (X, CONFIG_ENHANCEINV, subdivDepth);
1297 sbug << X. size () << " ";
1298#endif
1299 sbug << (checkIsolation (X, subdivDepth) ?
1300 "[isolated]\n" : "[no isol]\n");
1301
1302 // save the result to a file (for pictures for the paper)
1303 if (false)
1304 {
1305 std::ostringstream fstr;
1306 fstr << "_inv" << subdivDepth;
1307 std::string filename = fstr. str ();
1308 std::ofstream f (filename. c_str ());
1309 f << "; Inv(X) at depth " << subdivDepth << ".\n";
1310 f << X << "\n";
1311 sbug << "Inv(X) saved to " << filename << ".\n";
1312 }
1313 }
1314
1315 // end of the computation of the Morse decomposition
1316 }
1317
1318 // save the computed Morse sets to separate files
1319 if (!cubesFilePrefix. empty ())
1320 {
1321 sout << "Saving the Morse decomposition to '" <<
1322 cubesFilePrefix << "*'...\n";
1323 morseDec. savetofiles (cubesFilePrefix. c_str ());
1324 }
1325
1326 // save the computed Conley-Morse graph for the "dot" program
1327 if (!graphFileName. empty () &&
1328 !fileExists (graphFileName. c_str ()))
1329 {
1330 // create the Morse graph from the Morse decomposition
1331 chomp::homology::diGraph<> connGraph;
1332 morseDec. makegraph (connGraph);
1333 chomp::homology::diGraph<> morseGraph;
1334 transitiveReduction (connGraph, morseGraph);
1335
1336 // gather the sizes of each Morse set into a vector
1337 int nSets = morseGraph. countVertices ();
1338 std::vector<int_t> sizes (nSets);
1339 for (int n = 0; n < nSets; ++ n)
1340 sizes [n] = morseDec [n]. size ();
1341
1342 // gather the Conley indices and the eigenvalues
1343 std::vector<theConleyIndexType> indices (nSets);
1344 std::vector<IndexEigenValues> eigenValues (nSets);
1345 for (int n = 0; n < nSets; ++ n)
1346 {
1347 indices [n] = morseDec. index (n);
1348 eigenValues [n] = IndexEigenValues (indices [n]);
1349 }
1350
1351 sout << "Saving the Conley-Morse graph to '" <<
1352 graphFileName << "'...\n";
1353 std::ofstream graphFile (graphFileName. c_str ());
1354 writeDotGraph (graphFile, morseGraph, sizes,
1355 indices, eigenValues,
1356 wrongIndices, skippedIndices, attractors);
1357 graphFile << "\n";
1358 graphFile. close ();
1359 }
1360
1361 // save the Morse decomposition and the auxiliary data
1362 // to a temporary binary compressed file if requested to
1363 if (!morseDecFileName. empty () &&
1364 !fileExists (morseDecFileName. c_str ()))
1365 {
1366 sbug << "Saving Morse dec cache... ";
1367 using chomp::homology::program_time;
1368 double start_save_time (program_time);
1369 saveMorseDecCache (morseDecFileName. c_str (), morseDec,
1370 wrongIndices, skippedIndices, attractors);
1371 double end_save_time (program_time);
1372 sbug << "(" << static_cast<long> ((end_save_time -
1373 start_save_time) * 100) / 100 << " sec.)\n";
1374
1375 // DEBUG: verify if the Morse decomposition can be retrieved
1376 // correctly from the saved file, to make sure that this works
1377 if (false)
1378 {
1379 double start_verif_time (program_time);
1380 sbug << "DEBUG: Verifying Morse Dec cache... ";
1381 theMorseDecompositionType morseDec1 (theCubMap0);
1382 std::vector<int> wrongIndices1;
1383 std::vector<int> skippedIndices1;
1384 std::vector<int> attractors1;
1385 loadMorseDecCache (morseDecFileName. c_str (),
1386 morseDec1,
1387 wrongIndices1, skippedIndices1, attractors1);
1388 if (morseDec. count () != morseDec1. count ())
1389 throw "Wrong number of sets.";
1390 for (int n = 0; n < morseDec. count (); ++ n)
1391 {
1392 if (!(morseDec [n] == morseDec1 [n]))
1393 throw "Corrupted sets.";
1394 }
1395 if (!(wrongIndices == wrongIndices1))
1396 throw "Corrupted wrongIndices.";
1397 if (!(skippedIndices == skippedIndices1))
1398 throw "Corrupted skippedIndices.";
1399 if (!(attractors == attractors1))
1400 throw "Corrupted attractors.";
1401 double end_verif_time (program_time);
1402 sbug << "(" << static_cast<long> ((end_verif_time -
1403 start_verif_time) * 100) / 100 <<
1404 " sec.) All OK.\n";
1405 }
1406 }
1407
1408 return morseDecPtr;
1409} /* computeMorseDecomposition */
1410
1411
1412#endif // _CMGRAPHS_COMPMDEC_H_
1413
#define CONFIG_ENHANCEINV
Definition: c_lorenz_a.h:36
The class that computes and returns properties of the Conley index.
Definition: conindex.h:86
A class whose objects store, update and show coordinate ranges.
Definition: utils.h:444
Cached information on the Conley-Morse decompositions which contains information on computed Conley i...
Definition: indcache.h:66
Eigenvalues of the Conley index map gathered by levels.
Definition: eigenval.h:63
A generic class that computes an index pair given the isolating neighborhood and a means to compute t...
Definition: indpair.h:104
A generic map computation routine that computes a rigorous cubical multivalued map based on a functio...
Definition: mapcomp.h:69
This class defines a map derived from a sample difference equation.
Definition: m_differ.h:47
The Morse decoposition class.
Definition: morsedec.h:65
A simple class for storing connections in an array that uses the "multitable" class.
Definition: compmdec.h:137
void operator()(int_t source, int_t target, int_t v)
Adds an element v at the connection from source to target.
Definition: compmdec.h:171
const int_t * numTranslate
The translation table for vertex numbers in the connections.
Definition: compmdec.h:159
TConnMorse(theMorseDecompositionType &_morseDec, const std::vector< int > &_setNumbers, const spcCubes &spcX, const int_t *_numTranslate)
The constructor.
Definition: compmdec.h:163
theMorseDecompositionType & morseDec
The Morse decomposition in which to record the connections.
Definition: compmdec.h:149
const std::vector< int > & setNumbers
The numbers of Morse sets in the Morse decomposition that correspond to their indices given by source...
Definition: compmdec.h:153
const spcCubes & X
The set which contains cubes to add.
Definition: compmdec.h:156
A simple class for storing connections in an array that uses the "multitable" class.
Definition: compmdec.h:84
const int_t * numTranslate
The translation table for vertex numbers in the connections.
Definition: compmdec.h:108
chomp::homology::multitable< chomp::homology::multitable< int_t > > & connections
The tables of connectiong orbits; those for v -> w are stored at the index n * v + w.
Definition: compmdec.h:102
int_t n
The number of vertices between the connections are recorded.
Definition: compmdec.h:97
chomp::homology::multitable< int_t > & conncount
The numbers of elements in each connecting orbit.
Definition: compmdec.h:105
void operator()(int_t source, int_t target, int_t v)
Adds an element v at the connection from source to target.
Definition: compmdec.h:125
TConnTable(int_t _n, chomp::homology::multitable< chomp::homology::multitable< int_t > > &_connections, chomp::homology::multitable< int_t > &_conncount, const int_t *_numTranslate)
The constructor.
Definition: compmdec.h:112
Sets space wrapping locally.
Definition: spacewrap.h:82
void setDummyIndex(theMorseDecompositionType &morseDec, int n, int nonzero=-1)
This small auxiliary procedure sets a dummy Conley index to the given Morse set.
Definition: compmdec.h:186
theMorseDecompositionType * computeMorseDecomposition(theMapType &theMap, const theCubMapType theCubMap0, const theCubMapType theCubMap1, const double *offset, const double *width, int_t skipIndices, const std::string &cacheFileName, const std::string &pictureFileName, const std::string &cubesFilePrefix, const std::string &morseDecFileName, const std::string &graphFileName, const std::string &procFilePrefix, const std::string &mapOptFileName, bool &morseDecComputed, std::vector< int > &wrongIndices, std::vector< int > &skippedIndices, std::vector< int > &attractors, bool connOrbits, const double *leftMapParam, const double *rightMapParam, int paramCount)
Computes the Morse decomposition using all the pre- and postprocessing.
Definition: compmdec.h:997
void chainRecurrentSet(const typeCubes &X, typeCubes &result, const chomp::homology::diGraph<> &g)
Computes the chain recurrent set of X.
Definition: compmdec.h:379
void invMorseDec(const typeCubes &X, const chomp::homology::diGraph<> &g, typeMorseDec &morseDec, const double *offset, const double *width, int subdivDepth, const theMapType &theMap, const theCubMapType &theCubMap0, const theCubMapType &theCubMap1, int_t skipIndices, const std::string &cacheFileName, bool &morseDecComputed, std::vector< int > &wrongIndices, std::vector< int > &skippedIndices, std::vector< int > &attractors, bool connOrbits, const double *leftMapParam, const double *rightMapParam, int paramCount, chomp::homology::timeused &timeSubdiv)
Computes a Conley-Morse decomposition of ChainRecSet (X).
Definition: compmdec.h:440
int computeConleyIndex(theMorseDecompositionType &morseDec, int n, const double *offset, const double *width, int subdivDepth, const theMapType &theMap, const theCubMapType &theCubMap0, const theCubMapType &theCubMap1, int &subdivNonemptyInv, int &noIsolation, int &attractor)
Verifies that the provided Morse set can be used as a basis for a Conley index pair and computes the ...
Definition: compmdec.h:210
Choice of configuration settings.
Conley index computation routines.
Converting a binary data buffer into a printable text and vice versa.
void text2data(const std::string &str, chomp::multiwork::mwData &data)
Decodes a prevously prepared text back into binary data.
Definition: datatext.h:76
std::string data2text(const chomp::multiwork::mwData &data)
Encodes the entire binary data into a text string (single line, printable characters only).
Definition: datatext.h:48
Writing a graph in the "dot" format.
std::ostream & writeDotGraph(std::ostream &out, const chomp::homology::diGraph<> &g, const std::vector< int_t > &sizes, const std::vector< theConleyIndexType > &indices, const std::vector< IndexEigenValues > &eigenValues, const std::vector< int > &wrongIndices, const std::vector< int > &skippedIndices, const std::vector< int > &attractors)
Writes the given Conley-Morse graph to the output stream in the format for the 'dot' program.
Definition: dotgraph.h:61
Eigenvalues of the Conley index map.
Cached Conley indices for a Morse decomposition.
Computation of the invariant part of a set of cubes.
void invariantPart(typeCubes &X, const chomp::homology::diGraph<> &g, chomp::homology::diGraph<> *gInv=0)
Computes X := Inv (X) using the algorithm by Bill Kalies and Hyunju Ban.
Definition: invpart.h:60
bool checkEmptyInv(const spcCubes &X, int subdivDepth, const double *offset, const double *width, const theMapType &theMap, const theCubMapType &theCubMap0, const theCubMapType &theCubMap1)
Verifies whether the invariant part of the given set is empty by applying a limited number of refinem...
Definition: invpart.h:171
void computeMapGraph(const typeCubes &X, typeGraph &g, const typeCubMap &theCubMap, bool cropping=true)
Computes the cubical map on 'X' and fills out the graph 'g'.
Definition: mapgraph.h:56
Caching Morse decompositions using compressed binary files.
void loadMorseDecCache(const char *fileName, theMorseDecompositionType &morseDec, std::vector< int > &wrongIndices, std::vector< int > &skippedIndices, std::vector< int > &attractors)
Loads a Morse decomposition from a binary file.
Definition: morsecache.h:117
void saveMorseDecCache(const char *fileName, const theMorseDecompositionType &morseDec, const std::vector< int > &wrongIndices, const std::vector< int > &skippedIndices, const std::vector< int > &attractors)
Saves a Morse decomposition to a binary file.
Definition: morsecache.h:77
Morse decompositions.
const int refineDepth
The number of refinements that should be done if a Morse set with the trivial index is encountered or...
Definition: p_differ.h:139
const int maxRefineSize0
The maximal allowed size of a set of cubes in the phase space which can be refined at the initial sub...
Definition: p_differ.h:144
const int maxJoinConnection
The maximal size of a connecting orbit between two Morse sets which can be considered for joining.
Definition: p_differ.h:187
const int maxJoinSize
The maximal number of cubes in a trivial Morse set for which an attempt is made to join this set with...
Definition: p_differ.h:183
const bool ignoreIsolationForConleyIndex
Ignoring the isolation problem while computing the Conley index.
Definition: p_differ.h:216
const int maxJoinDistance
The maximal allowed distance between two Morse sets which can be considered for joining.
Definition: p_differ.h:191
const int maxImageVolume
The maximal allowed volume of the cubical image of a single box.
Definition: p_differ.h:164
const int spaceDim
The dimension of the phase space.
Definition: p_differ.h:48
const int initialDepth
The initial depth of subdivisions in the phase space.
Definition: p_differ.h:55
const int maxImageDiameter
The maximal allowed diameter of the cubical image of a signle box.
Definition: p_differ.h:159
const int paramCount
The number of all the parameters, both varying and fixed.
Definition: p_differ.h:82
const int finalDepth
The final depth of subdivisions in the phase space.
Definition: p_differ.h:58
const int maxRefineSize1
The maximal allowed size of a set of cubes in the phase space which can be refined at the subsequent ...
Definition: p_differ.h:149
bool setConleyIndex(theMorseDecompositionType &morseDec, int n, int subdivDepth, const double *leftMapParam, const double *rightMapParam, int paramCount)
Assigns a prescribed Conley index to the given Morse set whose index could not be computed because of...
Definition: indknown.h:68
void processMorseDec(const MorseDecType &morseDec, const CubSetType &allCubes, const GraphType &g, const CubMapType &theCubMap, const CubMapType &, const std::string &cubesFilePrefix, const std::string &procFilePrefix)
Post-processes a Morse decomposition by computing a decomposition of each Morse set into cycle sets a...
Definition: procexit.h:69
Dummy post-processing of Morse decompositions.
Helper functions and an auxiliary class for space wrapping.
Customizable data types for the Conley-Morse graphs computation program.
Data types for the dynamical systems data structures.
MorseDecomposition< theCubMapType, spcCube, spcCubes > theMorseDecompositionType
The type of the Morse decomposition.
Definition: typedyns.h:62
void resetRounding()
This function resets rounding switches of the processor and sets rounding to the nearest.
Definition: typeintv.h:65
chomp::homology::hashedset< spcCube > spcCubes
The type of a set of cubes in the phase space.
Definition: typespace.h:58
int spcCoord
The type of coordinates of cubes in the phase space.
Definition: typespace.h:50
chomp::homology::tCubeBase< spcCoord > spcCube
The type of a cube in the phase space.
Definition: typespace.h:55
Utilites and helper functions.
std::string double2string(const double &x, int precision)
Creates a text representation of a floating-point number at the prescribed precision.
Definition: utils.h:958
void subdivideCubes(const typeCubes &X, typeCubes &result)
Subdivides one set of cubes to another set of cubes with respect to twice finer grid.
Definition: utils.h:590
OutStream & showRealCoords(OutStream &out, const CoordMinMax &range)
Shows the real coordinates of the coordinate range.
Definition: utils.h:543
double cubesVolume(int_t nCubes, int subdiv)
Returns the volume of the given number of cubes in the phase space at the provided subdivision level.
Definition: utils.h:712
bool fileExists(const char *filename)
Returns 'true' iff the given file exists and it is allowed to read it.
Definition: utils.h:69
void enhanceCubes(spcCubes &X, int enhanceTimes, int subdivDepth)
Enhances the given set of cubes provided number of times.
Definition: utils.h:666
bool checkIsolation(const spcCubes &theSet, int depth)
Verifies if the given set of cubes is contained in the interior of the phase space box.
Definition: utils.h:565
void moveSomeToFront(HashSetType &X, int_t step)
Replaces the hashed set of objects with another one that contains the same objects,...
Definition: utils.h:801