The Conley-Morse Graphs Software
morsedec.h
Go to the documentation of this file.
1/////////////////////////////////////////////////////////////////////////////
2///
3/// @file morsedec.h
4///
5/// Morse decompositions.
6/// This file contains the definition of a Morse decomposition class
7/// for a discrete dynamical system represented by a combinatorial
8/// cubical multivalued map. It also contains the interface to CHomP
9/// for the purpose of computing the Conley index of each Morse set.
10///
11/// @author Pawel Pilarczyk
12///
13/////////////////////////////////////////////////////////////////////////////
14
15// Copyright (C) 1997-2014 by Pawel Pilarczyk.
16//
17// This file is part of my research software package. This is free software:
18// you can redistribute it and/or modify it under the terms of the GNU
19// General Public License as published by the Free Software Foundation,
20// either version 3 of the License, or (at your option) any later version.
21//
22// This software is distributed in the hope that it will be useful,
23// but WITHOUT ANY WARRANTY; without even the implied warranty of
24// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25// GNU General Public License for more details.
26//
27// You should have received a copy of the GNU General Public License
28// along with this software; see the file "license.txt". If not,
29// please, see <https://www.gnu.org/licenses/>.
30
31// Started on January 3, 2007. Last revision: May 18, 2013.
32
33
34#ifndef _CMGRAPHS_MORSEDEC_H_
35#define _CMGRAPHS_MORSEDEC_H_
36
37
38// include some standard C++ header files
39#include <iostream>
40#include <sstream>
41#include <algorithm>
42#include <cmath>
43
44// include selected header files from the CHomP library
45#include "chomp/system/textfile.h"
46#include "chomp/homology/homology.h"
47#include "chomp/struct/digraph.h"
48
49// include local header files
50#include "conindex.h"
51
52
53// --------------------------------------------------
54// --------------- MorseDecomposition ---------------
55// --------------------------------------------------
56
57/// The Morse decoposition class. This is a template whose parameters
58/// define a class used to compute the combinatorial cubical multivalued map
59/// on Morse sets, a class which corresponds to a single cube,
60/// and a class which is used to keep sets of cubes
61/// (the hashed set by default).
62template <class mapcomp, class cubetype,
63 class cubsettype = chomp::homology::hashedset<cubetype> >
65{
66 /// The type of a combinatorial cubical multivalued map.
67 typedef chomp::homology::mvmap<cubetype,cubetype> cubmaptype;
68
69public:
70 /// The type of the map computation class.
71 typedef mapcomp MapCompType;
72
73 /// The type of a single cube.
74 typedef cubetype CubeType;
75
76 /// The type of a set of cubes used to store each Morse set.
77 typedef cubsettype CubSetType;
78
79 /// The type of the index pair.
81
82 /// The type of the Conley index.
84
85 /// The default constructor.
86 MorseDecomposition (const mapcomp &_M = mapcomp ());
87
88 /// The destructor.
90
91 /// The copy constructor.
93
94 /// The assignment operator.
97
98 /// Swaps the internal data with another object (note: both must be
99 /// initialized with the same map computation object reference).
100 void swap (MorseDecomposition &m);
101
102 // --- the combinatorial cubical multivalued map ---
103
104 /// The map computation class.
105 const mapcomp &M;
106
107 // --- Morse Sets ---
108
109 /// Changes (increases or decreases) the number of Morse sets.
110 int setnumber (int n);
111
112 /// Adds a cube to the given Morse set and increases the number
113 /// of Morse sets if necessary.
114 int add (int n, const cubetype &q);
115
116 /// Returns the number of Morse sets.
117 int count () const;
118
119 /// Returns the n-th Morse set. Throws an exception in case
120 /// of a wrong number.
121 const cubsettype &operator [] (int n) const;
122
123 /// Returns the n-th Morse set. Throws an exception in case
124 /// of a wrong number.
125 cubsettype &operator [] (int n);
126
127 /// Returns the approximate distance between the two Morse sets.
128 /// Warning: This computation may take some time for large sets.
129 /// Note: The values returned by this function are tabulated, and
130 /// are not updated when the Morse sets are modified with the 'add'
131 /// function. Call with (-1,-1) to reset the tabulation.
132 int distance (int n, int m) const;
133
134 // --- Connections ---
135
136 /// Adds a connection between the given Morse sets without adding
137 /// any cubes to this connection (like in a direct connection).
138 int addconn (int n, int m);
139
140 /// Adds a cube to the connecting orbit between the given Morse sets.
141 int addconn (int n, int m, const cubetype &q);
142
143 /// Checks whether there exists a connection between given sets.
144 /// Returns true if yes, false if no or wrong numbers.
145 bool connected (int n, int m) const;
146
147 /// Returns the connection between the given sets.
148 /// Throws an exception if there is no connection or wrong numbers.
149 const cubsettype &connection (int n, int m) const;
150
151 /// Returns the approximate maximal distance of a cube in the orbit
152 /// that connects the sets n and m (in either direction) from the
153 /// k-th Morse set, i.e., how far the orbit is from the set.
154 /// Note: This computation may take some time for large sets.
155 int distance (int n, int m, int k) const;
156
157 /// Returns the appropriate maximal distance between cubes that are
158 /// contained in the Morse set n and the connecting orbit n-m or m-n.
159 /// Note: The values returned by this function are tabulated, and
160 /// are not updated when the Morse sets are modified with the 'add'
161 /// function or when the connecting orbits are modified with the
162 /// 'addconn' function. Call with (-1,-1) to reset the tabulation.
163 int conndistance (int n, int m) const;
164
165 /// Creates a graph representation of the Morse decomposition.
166 /// Each Morse set corresponds to a vertex, and each connecting orbit
167 /// gives rise to a corresponding edge.
168 /// The graph given as an argument must be initially empty.
169 int makegraph (chomp::homology::diGraph<> &g) const;
170
171 // --- the Conley Indices of the Morse Components ---
172
173 /// Computes the Conley index of the given Morse set.
174 const IndexType &compute (int n);
175
176 /// Computes the Conley indices of all the Morse sets.
177 int compute ();
178
179 /// Verifies if the Conley index for the given Morse set has been
180 /// already computed.
181 bool computed (int n) const;
182
183 /// Retrieves the previously computed Conley index of the given
184 /// Morse set. Throws an exception if the index has not yet
185 /// been computed. Note that if the Morse set is chaned, then its
186 /// index should be computed again using one of the functions above.
187 const IndexType &index (int n) const;
188
189 /// Sets the index of the given Morse set to the apriori known one.
190 /// Does not compute it, but verifies if it is nontrivial.
191 const IndexType &setindex (int n, const typename MorseDecomposition
192 <mapcomp,cubetype,cubsettype>::IndexType &ind);
193
194 /// Returns true if the Conley index of the given Morse set is
195 /// trivial, and false if either nontrivial or not yet computed.
196 bool trivial (int n) const;
197
198 // --- operations on entire Morse decompositions ---
199
200 /// Computes the set-wise intersection of two Morse decompositions.
201 /// The Morse decomposition must be initially empty and different
202 /// from the objects passed as arguments.
203 void intersection
206
207 // --- joining sets ---
208
209 /// Joins the two given Morse sets. Updates the connecting orbits.
210 /// Resets the Conley index. The new Morse set replaces the n-th one,
211 /// and the numbers of Morse sets beyond the m-th one are shifted
212 /// downwards.
213 int join (int n, int m);
214
215 /// Make connecting orbits pass through the given Morse set,
216 /// because its invariant part is in fact empty. The Morse set
217 /// is deleted and its contents is included in connecting orbits.
218 int passthru (int n);
219
220 /// Make connecting orbits pass through the given Morse sets,
221 /// because their invariant part is in fact empty. The Morse sets
222 /// are deleted and their contents are included in the corresponding
223 /// connecting orbits. Important: The array must contain the numbers
224 /// of the Morse sets in the ascending order.
225 int passthru (chomp::homology::hashedset<int> &setsToRemove);
226
227 /// Joins small Morse sets with trivial indices with Morse sets
228 /// whose indices are nontrivial. Only sets whose size, as well as
229 /// the size of the connecting orbit is below the given limits are
230 /// joined, provided their distance is also limited.
231 int jointrivial (int_t maxsetsize, int_t maxconnsize,
232 int maxdistance);
233
234 // --- save to files / load from files ---
235
236 /// Save the Morse sets and connecting orbits to files.
237 /// Set numbers are attached to the given prefix.
238 /// Connections are numbered N-M.
239 int savetofiles (const char *prefix = 0);
240
241 /// Load the Morse sets and connecting orbits from files.
242 int loadfromfiles (const char *prefix = 0);
243
244private:
245 /// The number of Morse sets.
246 int nsets;
247
248 /// The Morse sets.
249 chomp::homology::multitable<cubsettype *> sets;
250
251 /// The Conley indices of the Morse sets.
252 chomp::homology::multitable<IndexType *> indices;
253
254 /// The table that stores the information on whether the indices
255 /// are trivial or not: -1 = unknown, 0 = trivial, 1 = nontrivial.
256 chomp::homology::multitable<int> nontrivial;
257
258 /// Connecting orbits from one set to another.
259 /// There is no connection iff the pointer is zero.
260 chomp::homology::multitable<chomp::homology::multitable<cubsettype *> >
262
263 /// Were any connections defined?
265
266 /// Tabulated distances between the Morse sets.
267 mutable chomp::homology::multitable<chomp::homology::multitable<int> >
269
270 /// Were any distances computed?
271 mutable bool distDefined;
272
273 /// Tabulated values of the function "conndistance".
274 mutable chomp::homology::multitable<chomp::homology::multitable<int> >
276
277 /// Were any values of conn distance defined?
278 mutable bool distconnDefined;
279
280 /// Initializes the connection array so that connections are defined
281 /// from this point on.
282 void setConnDefined (void);
283
284 /// Release the memory (used in the destructor and copy constructor).
285 /// Optionally, delete only Morse decompositions data for Morse sets
286 /// whose numbers are greater or equal the given number.
287 void deleteall (int firstnumber, int lastnumber);
288
289 /// Copy all the data (used in the copy constructor and operator =).
290 void copyall (const MorseDecomposition &m);
291
292 /// Add one Morse set and initialize its data.
293 void addone ();
294
295 /// Verifies if two Morse sets are adjacent to each other.
296 /// Note: If both sets are large, then this can be time-consuming.
297 bool adjacent (int n, int m, int margin = 0) const;
298
299 /// Returns the approximate distance between the two cubical sets.
300 /// If minimum is set to true, then computes the minimal distance
301 /// between any pair of cubes, one taken from X, the other from Y.
302 /// If minimum is set to false, then computes the maximal distance
303 /// of any cube in X from the set Y, that is, how far X is from Y
304 /// (warning: the latter relation is not symmetric!)
305 /// Note: This computation may take some time for large sets.
306 static int cubsetdistance (const cubsettype &X, const cubsettype &Y,
307 bool minimum);
308
309}; /* class MorseDecomposition */
310
311// --------------------------------------------------
312
313template <class mapcomp, class cubetype, class cubsettype>
315 (const mapcomp &_M): M (_M), nsets (0),
316 sets (256), indices (256), nontrivial (256),
317 connDefined (false), distDefined (false), distconnDefined (false)
318{
319 return;
320} /* MorseDecomposition::MorseDecomposition */
321
322template <class mapcomp, class cubetype, class cubsettype>
324 (void)
325{
326 // if connection arrays are already in use then do nothing
327 if (connDefined)
328 return;
329
330 // initialize the connecting orbits' pointers if necessary
331 for (int i = 0; i < nsets; ++ i)
332 {
333 for (int j = 0; j < nsets; ++ j)
334 {
335 conn [i] [j] = 0;
336 conn [j] [i] = 0;
337 }
338 }
339
340 // make a note that connection arrays are now in use
341 connDefined = true;
342
343 return;
344} /* MorseDecomposition::setConnDefined */
345
346template <class mapcomp, class cubetype, class cubsettype>
348 (int firstnumber, int lastnumber)
349{
350 int difference = lastnumber - firstnumber;
351 if (difference <= 0)
352 return;
353
354 for (int i = firstnumber; i < lastnumber; ++ i)
355 {
356 // delete the sets
357 if (sets [i])
358 {
359 delete sets [i];
360 sets [i] = 0;
361 }
362
363 // delete the indices
364 if (indices [i])
365 {
366 delete indices [i];
367 indices [i] = 0;
368 }
369 }
370
371 for (int i = lastnumber; i < nsets; ++ i)
372 {
373 // shift the sets
374 sets [i - difference] = sets [i];
375 sets [i] = 0;
376
377 // shift the indices
378 indices [i - difference] = indices [i];
379 indices [i] = 0;
380
381 // shift the nontriviality of Morse sets
382 nontrivial [i - difference] = nontrivial [i];
383 }
384
385 // delete the connecting orbits
386 if (connDefined)
387 {
388 for (int i = 0; i < nsets; ++ i)
389 {
390 // delete connections
391 for (int j = firstnumber; j < lastnumber; ++ j)
392 {
393 if (conn [i] [j])
394 {
395 delete conn [i] [j];
396 conn [i] [j] = 0;
397 }
398 }
399
400 // shift connections
401 for (int j = lastnumber; j < nsets; ++ j)
402 {
403 conn [i] [j - difference] = conn [i] [j];
404 conn [i] [j] = 0;
405 }
406 }
407 }
408
409 // shift tabulated distances
410 if (distDefined)
411 {
412 for (int i = 0; i < nsets; ++ i)
413 {
414 for (int j = lastnumber; j < nsets; ++ j)
415 dist [i] [j - difference] = dist [i] [j];
416 }
417 }
418 if (distconnDefined)
419 {
420 for (int i = 0; i < nsets; ++ i)
421 {
422 for (int j = lastnumber; j < nsets; ++ j)
423 {
424 distconn [i] [j - difference] =
425 distconn [i] [j];
426 }
427 }
428 }
429
430 if (connDefined)
431 {
432 for (int j = 0; j < nsets - difference; ++ j)
433 {
434 // delete connections
435 for (int i = firstnumber; i < lastnumber; ++ i)
436 {
437 if (conn [i] [j])
438 {
439 delete conn [i] [j];
440 conn [i] [j] = 0;
441 }
442 }
443
444 // shift connections
445 for (int i = lastnumber; i < nsets; ++ i)
446 {
447 conn [i - difference] [j] = conn [i] [j];
448 conn [i] [j] = 0;
449 }
450 }
451 }
452
453 // shift tabulated distances
454 if (distDefined)
455 {
456 for (int j = 0; j < nsets - difference; ++ j)
457 {
458 for (int i = lastnumber; i < nsets; ++ i)
459 dist [i - difference] [j] = dist [i] [j];
460 }
461 }
462 if (distconnDefined)
463 {
464 for (int j = 0; j < nsets - difference; ++ j)
465 {
466 for (int i = lastnumber; i < nsets; ++ i)
467 {
468 distconn [i - difference] [j] =
469 distconn [i] [j];
470 }
471 }
472 }
473
474 // update the number of Morse sets
475 nsets -= difference;
476 return;
477} /* MorseDecomposition::deleteall */
478
479template <class mapcomp, class cubetype, class cubsettype>
481 ()
482{
483 deleteall (0, nsets);
484 return;
485} /* MorseDecomposition::~MorseDecomposition */
486
487template <class mapcomp, class cubetype, class cubsettype>
490{
491 // copy the number of Morse sets
492 nsets = m. nsets;
493
494 for (int i = 0; i < nsets; ++ i)
495 {
496 // copy the Morse sets
497 if (m. sets [i])
498 sets [i] = new cubsettype (*(m. sets [i]));
499 else
500 sets [i] = 0;
501
502 // copy the Conley indices
503 if (m. indices [i])
504 indices [i] = new IndexType (*(m. indices [i]));
505 else
506 indices [i] = 0;
507 nontrivial [i] = m. nontrivial [i];
508 }
509
510 // copy the connecting orbits and tabulated distances
511 connDefined = m. connDefined;
512 if (m. connDefined)
513 {
514 for (int i = 0; i < nsets; ++ i)
515 {
516 for (int j = 0; j < nsets; ++ j)
517 {
518 if (m. conn [i] [j])
519 {
520 conn [i] [j] = new cubsettype
521 (*(m. conn [i] [j]));
522 }
523 else
524 conn [i] [j] = 0;
525 }
526 }
527 }
528 distDefined = m. distDefined;
529 if (m. distDefined)
530 {
531 for (int i = 0; i < nsets; ++ i)
532 {
533 for (int j = 0; j < nsets; ++ j)
534 {
535 dist [i] [j] = m. dist [i] [j];
536 }
537 }
538 }
539 distconnDefined = m. distconnDefined;
540 if (m. distconnDefined)
541 {
542 for (int i = 0; i < nsets; ++ i)
543 {
544 for (int j = 0; j < nsets; ++ j)
545 {
546 distconn [i] [j] = m. distconn [i] [j];
547 }
548 }
549 }
550 return;
551} /* MorseDecomposition::copyall */
552
553template <class mapcomp, class cubetype, class cubsettype>
556{
557 copyall (m);
558 return;
559} /* MorseDecomposition::MorseDecomposition */
560
561template <class mapcomp, class cubetype, class cubsettype>
565{
566 // protection from "M = M;"
567 if (this == &m)
568 return *this;
569
570 // delete the currently allocated Morse sets and connecting orbits
571 deleteall (0, nsets);
572
573 // copy the Morse sets from the other decomposition
574 copyall (m);
575
576 return *this;
577} /* MorseDecomposition::operator = */
578
579template <class mapcomp, class cubetype, class cubsettype>
582{
583 std::swap (this -> nsets, m. nsets);
584 this -> sets. swap (m. sets);
585 this -> indices. swap (m. indices);
586 this -> nontrivial. swap (m. nontrivial);
587 this -> conn. swap (m. conn);
588 std::swap (this -> connDefined, m. connDefined);
589 this -> dist. swap (m. dist);
590 std::swap (this -> distDefined, m. distDefined);
591 this -> distconn. swap (m. distconn);
592 std::swap (this -> distconnDefined, m. distconnDefined);
593 return;
594} /* MorseDecomposition::swap */
595
596template <class mapcomp, class cubetype, class cubsettype>
598{
599 // initialize the new Morse set pointer
600 sets [nsets] = new cubsettype;
601
602 // initialize the new Conley index pointer
603 indices [nsets] = 0;
604 nontrivial [nsets] = -1;
605
606 // initialize the connecting orbits' pointers if necessary
607 if (connDefined)
608 {
609 for (int i = 0; i < nsets; ++ i)
610 {
611 conn [nsets] [i] = 0;
612 conn [i] [nsets] = 0;
613 }
614 conn [nsets] [nsets] = 0;
615 }
616
617 // initialize the tabulated distances if necessary
618 if (distDefined)
619 {
620 for (int i = 0; i < nsets; ++ i)
621 {
622 dist [nsets] [i] = -1;
623 dist [i] [nsets] = -1;
624 }
625 dist [nsets] [nsets] = 0;
626 }
627 if (distconnDefined)
628 {
629 for (int i = 0; i < nsets; ++ i)
630 {
631 distconn [nsets] [i] = -1;
632 distconn [i] [nsets] = -1;
633 }
634 distconn [nsets] [nsets] = 0;
635 }
636
637 // increase the stored number of Morse sets
638 ++ nsets;
639 return;
640} /* MorseDecomposition::addone */
641
642template <class mapcomp, class cubetype, class cubsettype>
644 (int n, int m, int margin) const
645{
646 // define the right type of neighbors' iterator
647 typedef chomp::homology::tNeighbors<typename cubetype::CoordType>
648 neighborstype;
649
650 // make sure the arguments are correct
651 if ((n < 0) || (n >= nsets) || (m < 0) || (m >= nsets))
652 return false;
653 if (n == m)
654 return true;
655 if (margin < 0)
656 margin = 0;
657
658 // determine the smaller and the larger set
659 bool n_m = (sets [n] -> size () < sets [m] -> size ());
660 const cubsettype &smaller = n_m ? *(sets [n]) : *(sets [m]);
661 const cubsettype &larger = n_m ? *(sets [m]) : *(sets [n]);
662
663 // if both sets are empty, then the result is obvious
664 if (larger. empty ())
665 return false;
666
667 // prepare an auxiliary buffer for coordinates of a cube
668 int dim = larger [0]. dim ();
669 typename cubetype::CoordType *c =
670 new typename cubetype::CoordType [dim];
671
672 // create an enhanced set if the margin is nonzero
673 cubsettype enhanced;
674 if (margin)
675 enhanced = smaller;
676 int start = 0;
677 for (int i = 0; i < margin; ++ i)
678 {
679 int stop = enhanced. size ();
680 for (int n = start; n < stop; ++ n)
681 {
682 enhanced [n]. coord (c);
683 neighborstype nb (c, dim);
684 const typename cubetype::CoordType *nc;
685 while ((nc = nb. get ()) != 0)
686 enhanced. add (cubetype (nc, dim));
687 }
688 start = stop;
689 }
690
691 // choose the enhanced set or the original one,
692 // depending on the margin
693 const cubsettype &smallcheck = margin ? enhanced : smaller;
694
695 // for each cube in the smaller set, check if any of its neighbors
696 // is contained in the larger set
697 for (int_t i = 0; i < smallcheck. size (); ++ i)
698 {
699 smallcheck [i]. coord (c);
700 neighborstype n (c, dim);
701 const typename cubetype::CoordType *nc;
702 while ((nc = n. get ()) != 0)
703 {
704 if (larger. check (cubetype (nc, dim)))
705 {
706 delete [] c;
707 return true;
708 }
709 }
710 }
711 delete [] c;
712 return false;
713} /* MorseDecomposition::adjacent */
714
715template <class mapcomp, class cubetype, class cubsettype>
717 (const cubsettype &X, const cubsettype &Y, bool minimum)
718{
719 // if one of the sets is empty, then say that the distance is zero
720 if (X. empty () || Y. empty ())
721 return 0;
722
723 // prepare the arrays for the coordinates of the cubes to compare
724 int dim = X [0]. dim ();
725 typedef typename cubetype::CoordType coords;
726 coords *c = new coords [dim + dim];
727 coords *d = c + dim;
728
729 // for each pair of cubes (one in the n-th set, another in the
730 // m-th set), compute their distance and take the minimum
731 int best_dist = -1;
732 for (int_t i = 0; i < X. size (); ++ i)
733 {
734 X [i]. coord (c);
735 int local_dist = -1;
736 for (int_t j = 0; j < Y. size (); ++ j)
737 {
738 Y [j]. coord (d);
739 int dist0 = 0;
740 for (int k = 0; k < dim; ++ k)
741 dist0 += (c [k] - d [k]) * (c [k] - d [k]);
742 dist0 = static_cast<int>
743 (std::sqrt (static_cast<double> (dist0)));
744 if ((local_dist < 0) || (local_dist > dist0))
745 local_dist = dist0;
746 }
747
748 if (minimum)
749 {
750 if ((best_dist < 0) || (best_dist > local_dist))
751 best_dist = local_dist;
752 }
753 else
754 {
755 if ((best_dist < 0) || (best_dist < local_dist))
756 best_dist = local_dist;
757 }
758 }
759
760 delete [] c;
761 return best_dist;
762} /* MorseDecomposition::distance */
763
764// --------------------------------------------------
765
766template <class mapcomp, class cubetype, class cubsettype>
768 (int n)
769{
770 if (n < 0)
771 return 0;
772 while (n > nsets)
773 addone ();
774 if (n < nsets)
775 deleteall (n, nsets);
776 return 0;
777} /* MorseDecomposition::setnumber */
778
779template <class mapcomp, class cubetype, class cubsettype>
781 (int n, const cubetype &q)
782{
783 if (n < 0)
784 return 0;
785 while (n > nsets)
786 addone ();
787 sets [n] -> add (q);
788 return 0;
789} /* MorseDecomposition::add */
790
791// --------------------------------------------------
792
793template <class mapcomp, class cubetype, class cubsettype>
795 (int n, int m)
796{
797 if ((n < 0) || (m < 0))
798 return 0;
799 setConnDefined ();
800 while ((n > nsets) || (m > nsets))
801 addone ();
802 if (!conn [n] [m])
803 conn [n] [m] = new cubsettype;
804 return 0;
805} /* MorseDecomposition::addconn */
806
807template <class mapcomp, class cubetype, class cubsettype>
809 (int n, int m, const cubetype &q)
810{
811 if ((n < 0) || (m < 0))
812 return 0;
813 setConnDefined ();
814 while ((n > nsets) || (m > nsets))
815 addone ();
816 if (!conn [n] [m])
817 conn [n] [m] = new cubsettype;
818 conn [n] [m] -> add (q);
819 return 0;
820} /* MorseDecomposition::addconn */
821
822template <class mapcomp, class cubetype, class cubsettype>
824{
825 return nsets;
826} /* MorseDecomposition::count */
827
828template <class mapcomp, class cubetype, class cubsettype>
830 operator [] (int n) const
831{
832 if ((n < 0) || (n >= nsets) || !sets [n])
833 throw "Trying to access an undefined Morse set.";
834 return *(sets [n]);
835} /* MorseDecomposition::operator [] */
836
837template <class mapcomp, class cubetype, class cubsettype>
839 operator [] (int n)
840{
841 if ((n < 0) || (n >= nsets) || !sets [n])
842 throw "Trying to access an undefined Morse set.";
843 return *(sets [n]);
844} /* MorseDecomposition::operator [] */
845
846template <class mapcomp, class cubetype, class cubsettype>
848 (int n, int m) const
849{
850 // make sure that n <= m
851 if (n > m)
852 {
853 int tmp = n;
854 n = m;
855 m = tmp;
856 }
857
858 // if the number(s) are too large, return an undefined value
859 if (m >= nsets)
860 return -1;
861
862 // if both numbers are negative, reset all the distances
863 if (m < 0)
864 {
865 distDefined = false;
866 return -1;
867 }
868
869 // if one of the numbers is negative and the array of distances
870 // is not in use then no action is necessary
871 if ((n < 0) && !distDefined)
872 {
873 return -1;
874 }
875
876 // if the sets are the same, their distance is zero
877 if (n == m)
878 return 0;
879
880 // initialize the distance array if it was not done before
881 if (!distDefined)
882 {
883 for (int i = 0; i < nsets; ++ i)
884 {
885 for (int j = 0; j < nsets; ++ j)
886 {
887 dist [i] [j] = -1;
888 }
889 }
890 distDefined = true;
891 }
892
893 // if exactly one of the numbers is negative,
894 // reset the other set of distances only
895 if (n < 0)
896 {
897 for (int i = 0; i < nsets; ++ i)
898 {
899 dist [i] [m] = -1;
900 dist [m] [i] = -1;
901 }
902 return -1;
903 }
904
905 // if the distance is known then return it
906 if (dist [n] [m] >= 0)
907 return dist [n] [m];
908
909 // compute the distance and save it
910 int d = cubsetdistance (*(sets [n]), *(sets [m]), true);
911 dist [n] [m] = d;
912 dist [m] [n] = d;
913
914 // return the distance
915 return d;
916} /* MorseDecomposition::distance */
917
918// --------------------------------------------------
919
920template <class mapcomp, class cubetype, class cubsettype>
922 (int n, int m) const
923{
924 return ((n >= 0) && (n < nsets) && (m >= 0) && (m < nsets) &&
925 connDefined && conn [n] [m]);
926} /* MorseDecomposition::connected */
927
928template <class mapcomp, class cubetype, class cubsettype>
930 connection (int n, int m) const
931{
932 if ((n < 0) || (n >= nsets) || (m < 0) || (m >= nsets) ||
933 !connDefined || !conn [n] [m])
934 throw "Trying to access an undefined Morse set connection.";
935 return *(conn [n] [m]);
936} /* MorseDecomposition::connection */
937
938template <class mapcomp, class cubetype, class cubsettype>
940 (int n, int m, int k) const
941{
942 if ((n < 0) || (n >= nsets) || (m < 0) || (m >= nsets) ||
943 (k < 0) || (k >= nsets))
944 return -1;
945 if ((n == m) || !connDefined || (!conn [n] [m] && !conn [m] [n]))
946 return 0;
947 return cubsetdistance (conn [n] [m] ? *(conn [n] [m]) :
948 *(conn [m] [n]), *(sets [k]), false);
949} /* MorseDecomposition::distance */
950
951template <class mapcomp, class cubetype, class cubsettype>
953 (int n, int m) const
954{
955 // if the number(s) are too large, return an undefined value
956 if ((n >= nsets) || (m >= nsets))
957 return -1;
958
959 // if both numbers are negative, reset all the distances
960 if ((n < 0) && (m < 0))
961 {
962 distconnDefined = false;
963 return -1;
964 }
965
966 // if one of the numbers is negative and the tabulated distances
967 // are not in use then no action is necessary
968 if (((n < 0) || (m < 0)) && !distconnDefined)
969 {
970 return -1;
971 }
972
973 // initialize the distance array if it was not done before
974 if (!distconnDefined)
975 {
976 for (int i = 0; i < nsets; ++ i)
977 {
978 for (int j = 0; j < nsets; ++ j)
979 {
980 distconn [i] [j] = -1;
981 }
982 }
983 distconnDefined = true;
984 }
985
986 // if one of the numbers is negative, reset one set of distances only
987 if ((n < 0) || (m < 0))
988 {
989 int num = (n >= 0) ? n : m;
990 for (int i = 0; i < nsets; ++ i)
991 {
992 distconn [i] [num] = -1;
993 distconn [num] [i] = -1;
994 }
995 return -1;
996 }
997
998 // if the distance is known then return it
999 if (distconn [n] [m] >= 0)
1000 return distconn [n] [m];
1001
1002 // compute the distance and save it
1003 int d = distance (n, m, n);
1004 distconn [n] [m] = d;
1005
1006 // return the distance
1007 return d;
1008} /* MorseDecomposition::conndistance */
1009
1010template <class mapcomp, class cubetype, class cubsettype>
1012 (chomp::homology::diGraph<> &g) const
1013{
1014 for (int i = 0; i < nsets; ++ i)
1015 {
1016 g. addVertex ();
1017 for (int j = 0; j < nsets; ++ j)
1018 {
1019 if (connDefined && conn [i] [j])
1020 g. addEdge (j);
1021 }
1022 }
1023 return 0;
1024} /* MorseDecomposition::makegraph */
1025
1026// --------------------------------------------------
1027
1028template <class mapcomp, class cubetype, class cubsettype>
1031 (int n)
1032{
1033 if ((n < 0) || (n >= nsets) || !sets [n])
1034 throw "Trying to compute the Conley index of an undefined "
1035 "Morse set.";
1036
1037 // create an index pair and compute the map on the index pair
1038 PairType P (M);
1039 const cubsettype &cset = *(sets [n]);
1040 int_t csetsize = cset. size ();
1041 for (int_t i = 0; i < csetsize; ++ i)
1042 P. add (cset [i]);
1043 P. compute ();
1044
1045 // create the Conley index object and compute the index
1046 if (indices [n])
1047 delete indices [n];
1048 indices [n] = new IndexType ();
1049 indices [n] -> setIndexPair (&P);
1050
1051 indices [n] -> compute ();
1052 indices [n] -> setIndexPair (0);
1053
1054 // remember if the index is nontrivial or not
1055 if (indices [n] -> trivial ())
1056 nontrivial [n] = 0;
1057 else
1058 nontrivial [n] = 1;
1059
1060 return *(indices [n]);
1061} /* MorseDecomposition::compute */
1062
1063template <class mapcomp, class cubetype, class cubsettype>
1065{
1066 for (int i = 0; i < nsets; ++ i)
1067 compute (i);
1068 return 0;
1069} /* MorseDecomposition::compute */
1070
1071template <class mapcomp, class cubetype, class cubsettype>
1073 const
1074{
1075 return ((n >= 0) && (n < nsets) && indices [n]);
1076} /* MorseDecomposition::computed */
1077
1078template <class mapcomp, class cubetype, class cubsettype>
1081 (int n) const
1082{
1083 if ((n < 0) || (n >= nsets) || !indices [n])
1084 throw "Trying to get an undefined Conley index.";
1085 return *(indices [n]);
1086} /* MorseDecomposition::index */
1087
1088template <class mapcomp, class cubetype, class cubsettype>
1091 (int n, const typename
1093{
1094 if ((n < 0) || (n >= nsets))
1095 throw "Trying to set a Conley index out of range.";
1096 if (indices [n])
1097 delete indices [n];
1098 indices [n] = new IndexType (ind);
1099 if (indices [n] -> trivial ())
1100 nontrivial [n] = 0;
1101 else
1102 nontrivial [n] = 1;
1103 return *(indices [n]);
1104} /* MorseDecomposition::setindex */
1105
1106template <class mapcomp, class cubetype, class cubsettype>
1108 (int n) const
1109{
1110 return ((n >= 0) && (n < nsets) && (nontrivial [n] == 0));
1111} /* MorseDecomposition::trivial */
1112
1113// --------------------------------------------------
1114
1115template <class mapcomp, class cubetype, class cubsettype>
1119{
1120 for (int i = 0; i < m. nsets; ++ i)
1121 {
1122 for (int j = 0; j < n. nsets; ++ j)
1123 {
1124 cubsettype X;
1125 X. intersection (*(m. sets [i]), *(n. sets [j]));
1126 if (X. empty ())
1127 continue;
1128 addone ();
1129 sets [nsets - 1] -> swap (X);
1130 }
1131 }
1132 return;
1133} /* MorseDecomposition::intersection */
1134
1135// --------------------------------------------------
1136
1137template <class mapcomp, class cubetype, class cubsettype>
1139 (int n, int m)
1140{
1141 if ((n < 0) || (n >= nsets) || (m < 0) || (m >= nsets) || (n == m))
1142 throw "Incorrect numbers of Morse sets to join.";
1143
1144 // show a message
1145 chomp::homology::sbug << "* Joining Morse sets: " <<
1146 n << " and " << m << "(" << sets [n] -> size () <<
1147 " - " << ((conn [n] [m] ? conn [n] [m] -> size () :
1148 static_cast<int_t> (0)) +
1149 (conn [m] [n] ? conn [m] [n] -> size () :
1150 static_cast<int_t> (0))) << " - " <<
1151 sets [m] -> size () << ").\n";
1152
1153 // reset tabulated distances
1154 if (distDefined)
1155 {
1156 for (int i = 0; i < nsets; ++ i)
1157 {
1158 dist [i] [n] = -1;
1159 dist [n] [i] = -1;
1160 }
1161 }
1162 if (distconnDefined)
1163 {
1164 for (int i = 0; i < nsets; ++ i)
1165 {
1166 distconn [i] [n] = -1;
1167 distconn [n] [i] = -1;
1168 }
1169 }
1170
1171 // join the sets
1172 sets [n] -> add (*(sets [m]));
1173 if (connDefined && conn [n] [m])
1174 sets [n] -> add (*(conn [n] [m]));
1175 if (connDefined && conn [m] [n])
1176 sets [n] -> add (*(conn [m] [n]));
1177
1178 // adjust the connecting orbits
1179 if (connDefined)
1180 {
1181 for (int k = 0; k < nsets; ++ k)
1182 {
1183 if ((k == n) || (k == m))
1184 continue;
1185
1186 // adjust the connection (n+m) --> k
1187 if (conn [n] [k])
1188 {
1189 if (conn [m] [k])
1190 {
1191 conn [n] [k] ->
1192 add (*(conn [m] [k]));
1193 }
1194 conn [n] [k] -> remove (*(sets [n]));
1195 }
1196 else if (conn [m] [k])
1197 {
1198 conn [n] [k] = conn [m] [k];
1199 conn [m] [k] = 0;
1200 conn [n] [k] -> remove (*(sets [n]));
1201 }
1202
1203 // adjust the connection k --> (n+m)
1204 if (conn [k] [n])
1205 {
1206 if (conn [k] [m])
1207 {
1208 conn [k] [n] ->
1209 add (*(conn [k] [m]));
1210 }
1211 conn [k] [n] -> remove (*(sets [n]));
1212 }
1213 else if (conn [k] [m])
1214 {
1215 conn [k] [n] = conn [k] [m];
1216 conn [k] [m] = 0;
1217 conn [k] [n] -> remove (*(sets [n]));
1218 }
1219 }
1220 }
1221
1222 // reset the Conley index of the n-th Morse set if necessary
1223 if (indices [n] && nontrivial [m])
1224 {
1225 delete indices [n];
1226 indices [n] = 0;
1227 nontrivial [n] = -1;
1228 }
1229
1230 // delete the m-th Morse set which has been joined to the n-th one
1231 deleteall (m, m + 1);
1232 return 0;
1233} /* MorseDecomposition::join */
1234
1235template <class mapcomp, class cubetype, class cubsettype>
1237{
1238 using chomp::homology::sbug;
1239
1240 if ((n < 0) || (n >= nsets))
1241 throw "Incorrect numbers of Morse set to pass through.";
1242
1243 // show a message
1244// sbug << "* Passing through Morse set " << n << " (" <<
1245// sets [n] -> size () << " cubes).\n";
1246
1247 // join connecting orbits and reset tabulated distances
1248 for (int i = 0; i < nsets; ++ i)
1249 {
1250 if (i == n)
1251 continue;
1252 for (int j = 0; j < nsets; ++ j)
1253 {
1254 if (j == n)
1255 continue;
1256 // if (conn [i] [n] && !conn [n] [j])
1257 // {
1258 // sbug << "WARNIING: Passing through "
1259 // "an attractor: " << i << " -> " <<
1260 // n << " | " << j << ".\n";
1261 // }
1262 // else if (!conn [i] [n] && conn [n] [j])
1263 // {
1264 // sbug << "WARNIING: Passing through "
1265 // "a repeller: " << i << " | " <<
1266 // n << " -> " << j << ".\n";
1267 // }
1268 // else if (!conn [i] [n] && !conn [n] [j])
1269 // continue;
1270 if (connDefined && conn [i] [n] && conn [n] [j])
1271 {
1272 // sbug << "(orbits joined: " << i <<
1273 // " --[" << conn [i] [n] -> size () <<
1274 // "]-> " << n << "[" <<
1275 // sets [n] -> size () << "] --[" <<
1276 // conn [n] [j] -> size () << "]-> " <<
1277 // j << ")\n";
1278 // modify the connecting orbit
1279 if (!conn [i] [j])
1280 conn [i] [j] = new cubsettype;
1281 conn [i] [j] -> add (*(conn [i] [n]));
1282 conn [i] [j] -> add (*(conn [n] [j]));
1283 conn [i] [j] -> add (*(sets [n]));
1284
1285 // reset the corresponding distances
1286 if (distconnDefined)
1287 {
1288 distconn [i] [j] = -1;
1289 distconn [j] [i] = -1;
1290 }
1291 }
1292 }
1293 }
1294
1295 // delete the n-th Morse set
1296 deleteall (n, n + 1);
1297 return 0;
1298} /* MorseDecomposition::passthru */
1299
1300template <class mapcomp, class cubetype, class cubsettype>
1302 (chomp::homology::hashedset<int> &setsToRemove)
1303{
1304 using chomp::homology::sbug;
1305
1306 int nSetsToRemove = setsToRemove. size ();
1307// if (nSetsToRemove < 100)
1308 {
1309 for (int index = nSetsToRemove - 1; index >= 0; -- index)
1310 {
1311 this -> passthru (setsToRemove [index]);
1312 }
1313 }
1314
1315 // TODO: A more efficient version for higher numbers of sets.
1316
1317 return 0;
1318} /* MorseDecomposition::passthru */
1319
1320template <class mapcomp, class cubetype, class cubsettype>
1322 (int_t maxsetsize, int_t maxconnsize, int maxdistance)
1323{
1324 using chomp::homology::sbug;
1325 sbug << "- Join trivial: maxsetsize = " << maxsetsize <<
1326 ", maxconnsize = " << maxconnsize <<
1327 ", maxdistance = " << maxdistance << ".\n";
1328
1329 // compute the Conley indices of all the Morse sets if necessary
1330 for (int n = 0; n < nsets; ++ n)
1331 {
1332 if (nontrivial [n] < 0)
1333 compute (n);
1334 }
1335
1336 // join pairs of Morse sets
1337 bool allow_trivial = false;
1338 while (1)
1339 {
1340 // output information for debugging
1341 if (false) // DEBUG
1342 {
1343 using std::setw;
1344 sbug << "Morse decomposition connection set sizes:\n";
1345 sbug << " ";
1346 for (int i = 0; i < nsets; ++ i)
1347 sbug << setw (7) << i;
1348 sbug << "\n";
1349 for (int i = 0; i < nsets; ++ i)
1350 {
1351 sbug << setw (3) << i << " (" <<
1352 setw (7) << sets [i] -> size ();
1353 switch (nontrivial [i])
1354 {
1355 case -1: sbug << ")- "; break;
1356 case 1: sbug << ")+ "; break;
1357 case 0: sbug << "): "; break;
1358 default: sbug << ")[" << nontrivial [i] <<
1359 "] "; break;
1360 }
1361 for (int j = 0; j < nsets; ++ j)
1362 {
1363 if (connDefined && conn [i] [j])
1364 {
1365 sbug << setw (7) <<
1366 conn [i] [j] ->
1367 size ();
1368 }
1369 else
1370 sbug << " ---";
1371 }
1372 sbug << "\n";
1373 }
1374 }
1375
1376 // the numbers of best choice in the loop below
1377 int best_n = -1, best_m = -1;
1378 // the size of what is added to the Morse set
1379 // int_t best_size = 0;
1380 // the size of the nontrivial/large Morse set
1381 // int_t best_nsize = 0;
1382 // the best distance between the Morse sets found so far
1383 int best_dist = 0;
1384 // the best distance between the connecting orbit and the set
1385 int best_conndist = 0;
1386
1387 // check all pairs of sets and find the optimal ones to join
1388 for (int n = 0; n < nsets; ++ n)
1389 {
1390 for (int m = 0; m < nsets; ++ m)
1391 {
1392 // --- check the necessary conditions ---
1393
1394 // make sure these are two different sets
1395 if (n != m);
1396 else
1397 continue;
1398
1399 // remember the sizes of the two sets
1400 int_t nsize = sets [n] -> size ();
1401 int_t msize = sets [m] -> size ();
1402
1403 // check if the n-th set is nontrivial
1404 // or very large, and the m-th set is trivial
1405 if (!nontrivial [m] && (nontrivial [n] ||
1406 (nsize > maxsetsize) ||
1407 allow_trivial));
1408 else
1409 continue;
1410
1411 // count the size of connecting orbits
1412 int_t conn_nm =
1413 (connDefined && conn [n] [m]) ?
1414 conn [n] [m] -> size () :
1415 static_cast<int_t> (0);
1416 int_t conn_mn =
1417 (connDefined && conn [m] [n]) ?
1418 conn [m] [n] -> size () :
1419 static_cast<int_t> (0);
1420 // int_t add_size = msize + conn_nm + conn_mn;
1421
1422 // make sure the size limits are observed
1423 if ((msize < maxsetsize) &&
1424 (conn_nm < maxconnsize) &&
1425 (conn_mn < maxconnsize));
1426 else
1427 continue;
1428
1429 // make sure that no loop will be created
1430 bool looping = false;
1431 if (connDefined)
1432 {
1433 for (int k = 0; k < nsets; ++ k)
1434 {
1435 if ((conn [n] [k] &&
1436 conn [k] [m]) ||
1437 (conn [m] [k] &&
1438 conn [k] [n]))
1439 {
1440 looping = true;
1441 break;
1442 }
1443 }
1444 }
1445 if (looping)
1446 continue;
1447
1448 // compute the dist. between the Morse sets
1449 int dist0 = distance (n, m);
1450 // sbug << "- Dist (" << n << "," << m <<
1451 // ") = " << dist0 << ".\n";
1452 if (dist0 <= maxdistance);
1453 else
1454 continue;
1455
1456 // compute the maximal distance between cubes
1457 // in the connecting orbit and the Morse set
1458 int conndist0 = conndistance (n, m);
1459 // sbug << "- ConnDist (" << n << "," << m <<
1460 // ") = " << conndist << ".\n";
1461 if (conndist0 <= maxdistance);
1462 else
1463 continue;
1464
1465 // --- check if this is a better choice ---
1466
1467 // make sure that the distance is not going
1468 // to be increased
1469 if ((best_n < 0) || (dist0 + conndist0 <=
1470 best_dist + best_conndist));
1471 else
1472 continue;
1473
1474 // check if the size of what is added
1475 // to the nontrivial set does not exceed
1476 // the size found in the previous case
1477 // if ((best_n < 0) || (best_size < add_size));
1478 // else
1479 // continue;
1480
1481 // choose this pair of Morse sets
1482 best_n = n;
1483 best_m = m;
1484 // best_size = add_size;
1485 // best_nsize = nsize;
1486 best_dist = dist0;
1487 }
1488 }
1489
1490 // if no good pair has been found...
1491 if ((best_n < 0) || (best_m < 0))
1492 {
1493 // if loose criteria was already set, break the loop
1494 if (allow_trivial)
1495 break;
1496
1497 // loosen the criteria of checking the sets to join
1498 allow_trivial = true;
1499 continue;
1500 }
1501
1502 // join the two Morse sets (keep the n-th index if necessary)
1503 join (best_n, best_m);
1504 }
1505
1506 // compute the missing Conley indices
1507 for (int n = 0; n < nsets; ++ n)
1508 {
1509 if (nontrivial [n] < 0)
1510 compute (n);
1511 }
1512
1513 return 0;
1514} /* MorseDecomposition::jointrivial */
1515
1516template <class mapcomp, class cubetype, class cubsettype>
1518 (const char *prefix)
1519{
1520 for (int n = 0; n < nsets; ++ n)
1521 {
1522 // create a file for this Morse set
1523 std::ostringstream ofname;
1524 if (prefix)
1525 ofname << prefix;
1526 ofname << n;
1527 std::string fname = ofname. str ();
1528 ofname << ".cub";
1529 std::ofstream out (ofname. str (). c_str ());
1530
1531 // save the nontriviality of the index information
1532 out << "; This is the Morse set no. " << n << ".\n";
1533 out << "; Its Conley index ";
1534 switch (nontrivial [n])
1535 {
1536 case 0: out << "is trivial.\n"; break;
1537 case 1: out << "is nontrivial.\n"; break;
1538 default: out << "has not been computed.\n"; break;
1539 }
1540
1541 // save the Conley index itself
1542 if (indices [n])
1543 {
1544 out << "; The Conley index: " <<
1545 *(indices [n]) << "\n";
1546 }
1547
1548 // save the Morse set to a file
1549 out << *(sets [n]);
1550 out. close ();
1551
1552 // save the connecting orbits to files
1553 for (int m = 0; m < nsets; ++ m)
1554 {
1555 // if there is no connection, skip the file
1556 if (!connDefined || !conn [n] [m])
1557 continue;
1558
1559 // create a file name for the connection
1560 std::ostringstream connname;
1561 connname << fname << '-' << m << ".cub";
1562
1563 // save the connection
1564 std::ofstream outc (connname. str (). c_str ());
1565 outc << "; This is a covering of all the computed "
1566 "connecting orbits\n"
1567 "; that run from the Morse set no. " << n <<
1568 " to " << m << ".\n";
1569 if (conn [n] [m] -> empty ())
1570 {
1571 outc << "\n; Note: This set is empty "
1572 "which means that the orbit\n"
1573 "; was most likely not computed.\n";
1574 }
1575 else
1576 {
1577 outc << *(conn [n] [m]);
1578 }
1579 }
1580 }
1581 return 0;
1582} /* MorseDecomposition::savetofiles */
1583
1584template <class mapcomp, class cubetype, class cubsettype>
1586 (const char *prefix)
1587{
1588 for (int n = 0; ; ++ n)
1589 {
1590 // create a file name for this Morse set
1591 std::ostringstream fname;
1592 if (prefix)
1593 fname << prefix;
1594 fname << n;
1595
1596 // open a file if possible
1597 std::ifstream in (fname. str (). c_str ());
1598
1599 // if the file does not exist, then quit the reading process
1600 if (!in)
1601 break;
1602
1603 // read the Conley index information if any is available
1604 int nontrivialindex = -1;
1605 IndexType *theIndex = 0;
1606 while (in. peek () == ';')
1607 {
1608 // read the comment line from the input file
1609 std::string line;
1610 getline (in, line);
1611
1612 // look for the info that the index is nontrivial
1613 if (line. find ("Conley index is nontrivial") !=
1614 std::string::npos)
1615 {
1616 nontrivialindex = 1;
1617 continue;
1618 }
1619
1620 // look for the information that the index is trivial
1621 if (line. find ("Conley index is trivial") !=
1622 std::string::npos)
1623 {
1624 nontrivialindex = 0;
1625 continue;
1626 }
1627
1628 // look for the actual Conley index to read
1629 std::string indHeader ("Conley index: ");
1630 std::string::size_type pos = line. find (indHeader);
1631 if (pos != std::string::npos)
1632 {
1633 std::istringstream str (line);
1634 std::string::size_type len = pos +
1635 indHeader. size ();
1636 for (unsigned int i = 0; i < len; ++ i)
1637 str. get ();
1638 theIndex = new IndexType ();
1639 str >> *theIndex;
1640 continue;
1641 }
1642 }
1643
1644 // add a Morse set and read it
1645 this -> addone ();
1646 in >> *(sets [n]);
1647 in. close ();
1648 indices [n] = theIndex;
1649 nontrivial [n] = nontrivialindex;
1650 }
1651
1652 // load the connections from files
1653 for (int n = 0; n < nsets; ++ n)
1654 {
1655 for (int m = 0; m < nsets; ++ m)
1656 {
1657 // create a file name for this connection
1658 std::ostringstream fname;
1659 if (prefix)
1660 fname << prefix;
1661 fname << n << '-' << m;
1662
1663 // try opening the file for this connection
1664 std::ifstream in (fname. str (). c_str ());
1665 if (!in)
1666 continue;
1667
1668 // create the connection and read it
1669 addconn (n, m);
1670 in >> *(conn [n] [m]);
1671 }
1672 }
1673 return 0;
1674} /* MorseDecomposition::loadfromfiles */
1675
1676
1677#endif // _CMGRAPHS_MORSEDEC_H_
1678
1679
The class that computes and returns properties of the Conley index.
Definition: conindex.h:86
A generic class that computes an index pair given the isolating neighborhood and a means to compute t...
Definition: indpair.h:104
The Morse decoposition class.
Definition: morsedec.h:65
void copyall(const MorseDecomposition &m)
Copy all the data (used in the copy constructor and operator =).
Definition: morsedec.h:489
int passthru(int n)
Make connecting orbits pass through the given Morse set, because its invariant part is in fact empty.
Definition: morsedec.h:1236
bool distconnDefined
Were any values of conn distance defined?
Definition: morsedec.h:278
bool trivial(int n) const
Returns true if the Conley index of the given Morse set is trivial, and false if either nontrivial or...
Definition: morsedec.h:1108
static int cubsetdistance(const cubsettype &X, const cubsettype &Y, bool minimum)
Returns the approximate distance between the two cubical sets.
Definition: morsedec.h:717
const cubsettype & operator[](int n) const
Returns the n-th Morse set.
Definition: morsedec.h:830
int jointrivial(int_t maxsetsize, int_t maxconnsize, int maxdistance)
Joins small Morse sets with trivial indices with Morse sets whose indices are nontrivial.
Definition: morsedec.h:1322
IndexPair< mapcomp, cubetype, cubsettype > PairType
The type of the index pair.
Definition: morsedec.h:80
void addone()
Add one Morse set and initialize its data.
Definition: morsedec.h:597
bool connected(int n, int m) const
Checks whether there exists a connection between given sets.
Definition: morsedec.h:922
int conndistance(int n, int m) const
Returns the appropriate maximal distance between cubes that are contained in the Morse set n and the ...
Definition: morsedec.h:953
chomp::homology::multitable< chomp::homology::multitable< int > > dist
Tabulated distances between the Morse sets.
Definition: morsedec.h:268
int compute()
Computes the Conley indices of all the Morse sets.
Definition: morsedec.h:1064
const IndexType & setindex(int n, const typename MorseDecomposition< mapcomp, cubetype, cubsettype >::IndexType &ind)
Sets the index of the given Morse set to the apriori known one.
Definition: morsedec.h:1091
void setConnDefined(void)
Initializes the connection array so that connections are defined from this point on.
Definition: morsedec.h:324
const IndexType & index(int n) const
Retrieves the previously computed Conley index of the given Morse set.
Definition: morsedec.h:1081
void intersection(const MorseDecomposition< mapcomp, cubetype, cubsettype > &m, const MorseDecomposition< mapcomp, cubetype, cubsettype > &n)
Computes the set-wise intersection of two Morse decompositions.
Definition: morsedec.h:1117
int addconn(int n, int m)
Adds a connection between the given Morse sets without adding any cubes to this connection (like in a...
Definition: morsedec.h:795
cubetype CubeType
The type of a single cube.
Definition: morsedec.h:74
int nsets
The number of Morse sets.
Definition: morsedec.h:246
int makegraph(chomp::homology::diGraph<> &g) const
Creates a graph representation of the Morse decomposition.
Definition: morsedec.h:1012
const mapcomp & M
The map computation class.
Definition: morsedec.h:105
~MorseDecomposition()
The destructor.
Definition: morsedec.h:481
chomp::homology::multitable< int > nontrivial
The table that stores the information on whether the indices are trivial or not: -1 = unknown,...
Definition: morsedec.h:256
MorseDecomposition(const mapcomp &_M=mapcomp())
The default constructor.
Definition: morsedec.h:315
bool adjacent(int n, int m, int margin=0) const
Verifies if two Morse sets are adjacent to each other.
Definition: morsedec.h:644
bool distDefined
Were any distances computed?
Definition: morsedec.h:271
chomp::homology::multitable< chomp::homology::multitable< int > > distconn
Tabulated values of the function "conndistance".
Definition: morsedec.h:275
int count() const
Returns the number of Morse sets.
Definition: morsedec.h:823
mapcomp MapCompType
The type of the map computation class.
Definition: morsedec.h:71
const cubsettype & connection(int n, int m) const
Returns the connection between the given sets.
Definition: morsedec.h:930
int add(int n, const cubetype &q)
Adds a cube to the given Morse set and increases the number of Morse sets if necessary.
Definition: morsedec.h:781
int join(int n, int m)
Joins the two given Morse sets.
Definition: morsedec.h:1139
chomp::homology::multitable< chomp::homology::multitable< cubsettype * > > conn
Connecting orbits from one set to another.
Definition: morsedec.h:261
chomp::homology::multitable< IndexType * > indices
The Conley indices of the Morse sets.
Definition: morsedec.h:252
int setnumber(int n)
Changes (increases or decreases) the number of Morse sets.
Definition: morsedec.h:768
bool connDefined
Were any connections defined?
Definition: morsedec.h:264
int distance(int n, int m) const
Returns the approximate distance between the two Morse sets.
Definition: morsedec.h:848
chomp::homology::multitable< cubsettype * > sets
The Morse sets.
Definition: morsedec.h:249
bool computed(int n) const
Verifies if the Conley index for the given Morse set has been already computed.
Definition: morsedec.h:1072
void swap(MorseDecomposition &m)
Swaps the internal data with another object (note: both must be initialized with the same map computa...
Definition: morsedec.h:581
void deleteall(int firstnumber, int lastnumber)
Release the memory (used in the destructor and copy constructor).
Definition: morsedec.h:348
cubsettype CubSetType
The type of a set of cubes used to store each Morse set.
Definition: morsedec.h:77
chomp::homology::mvmap< cubetype, cubetype > cubmaptype
The type of a combinatorial cubical multivalued map.
Definition: morsedec.h:67
int savetofiles(const char *prefix=0)
Save the Morse sets and connecting orbits to files.
Definition: morsedec.h:1518
ConleyIndex< PairType > IndexType
The type of the Conley index.
Definition: morsedec.h:83
int loadfromfiles(const char *prefix=0)
Load the Morse sets and connecting orbits from files.
Definition: morsedec.h:1586
Conley index computation routines.