32#ifndef _CMGRAPHS_CONINDEX_H_
33#define _CMGRAPHS_CONINDEX_H_
42#include "chomp/system/textfile.h"
43#include "chomp/system/timeused.h"
44#include "chomp/homology/homology.h"
45#include "chomp/struct/autoarray.h"
59int dgeev_ (
char *jobvl,
char *jobvr, int32 *n,
60 double *a, int32 *lda,
double *wr,
double *wi,
double *vl,
61 int32 *ldvl,
double *vr, int32 *ldvr,
double *work,
62 int32 *lwork, int32 *info);
70template <
class IndexPair,
class eucl
idom>
73template <
class IndexPair,
class eucl
idom>
77template <
class IndexPair,
class eucl
idom>
84 class euclidom = chomp::homology::integer>
107 int compute (
bool twolayer =
false);
111 int reduce (
bool shrink =
true);
120 int eigenvalues (
int level, std::vector<double> &Re,
121 std::vector<double> &Im,
bool nonzero =
true,
122 bool sorted =
true)
const;
142 const chomp::homology::mmatrix<euclidom> *
Map (
int n)
const;
145 std::string
MapString (
int n,
const char *newline =
"\n")
const;
155 void define (
const int *betti,
156 const chomp::homology::mmatrix<euclidom> *matr,
161 void define (
const int *betti,
int _toplevel);
172 std::vector<std::vector<euclidom> >
coef;
175 chomp::homology::mmatrix<euclidom> *
indmap;
178 friend std::ostream &operator << <> (std::ostream &out,
183 friend std::istream &operator >> <> (std::istream &in,
189 static double round (
double x,
double epsilon,
double threshold);
213 else if (x. re > y. re)
215 return (x. im < y. im);
220template <
class IndexPair,
class eucl
idom>
226 nontrivialindex = -1;
230template <
class IndexPair,
class eucl
idom>
235 toplevel = c. toplevel;
238 indmap =
new chomp::homology::mmatrix<euclidom> [toplevel + 1];
241 for (
int i = 0; i <= toplevel; ++ i)
242 indmap [i] = c. indmap [i];
243 nontrivialindex = c. nontrivialindex;
247template <
class IndexPair,
class eucl
idom>
253 toplevel = c. toplevel;
258 indmap =
new chomp::homology::mmatrix<euclidom> [toplevel + 1];
261 for (
int i = 0; i <= toplevel; ++ i)
262 indmap [i] = c. indmap [i];
263 nontrivialindex = c. nontrivialindex;
267template <
class IndexPair,
class eucl
idom>
275template <
class IndexPair,
class eucl
idom>
283template <
class IndexPair,
class eucl
idom>
287 if ((x < 0) && (x > -threshold))
289 if ((x > 0) && (x < threshold))
292 long xl =
static_cast<long> (x);
295 else if (x - xl > 0.5)
297 return (xl * epsilon);
300template <
class IndexPair,
class eucl
idom>
303 if ((n < 0) || (n > toplevel))
305 int size = coef [n]. size ();
307 for (
int i = 0; i < size; ++ i)
308 if (coef [n] [i]. delta () == 1)
313template <
class IndexPair,
class eucl
idom>
314inline const chomp::homology::mmatrix<euclidom> *
317 if (!indmap || (n < 0) || (n > toplevel))
322template <
class IndexPair,
class eucl
idom>
328 if ((n < 0) || (n > toplevel))
330 int size = coef [n]. size ();
331 if ((i < 0) || (i >= size))
336template <
class IndexPair,
class eucl
idom>
342template <
class IndexPair,
class eucl
idom>
344 const char *newline)
const
346 if (!indmap || (n < 0) || (n > toplevel))
347 return std::string ();
348 std::ostringstream out;
349 const chomp::homology::mmatrix<euclidom> &m = indmap [n];
350 bool nonzero =
false;
351 for (
int j = 0; j < m. getncols (); j ++)
352 if (m. getcol (j). size ())
356 out <<
"Map " << n <<
":" << newline;
359 out <<
"#" << (j + 1) <<
" = " << m. getcol (j) <<
363 out <<
"Map " << n <<
" = 0" << newline;
367template <
class IndexPair,
class eucl
idom>
370 if (coef. size () <= 0)
371 return std::string (
"0");
372 std::ostringstream out;
373 int coefsize = coef. size ();
374 for (
int i = 0; i < coefsize; ++ i)
376 bool nonzero =
false;
380 int size = coef [i]. size ();
381 for (
int j = 0; j < size; ++ j)
383 if (coef [i] [j]. delta () > 1)
391 out <<
"^" << counter;
395 out <<
"Z_" << coef [i] [j];
407 out <<
"^" << counter;
416template <
class IndexPair,
class eucl
idom>
423 using namespace chomp::homology;
427 typedef typename CubeType::CoordType CoordType;
428 typedef chomp::homology::mvmap<CubeType,CubeType> MvMapType;
431 sbug <<
"Preparing to compute the Conley index...\n";
435 CubSetType X, A, Y, B;
436 int dim = cf -> dim ();
437 int countS = cf -> countInv ();
438 CoordType c [CubeType::MaxDim];
439 for (
int i = 0; i < countS; ++ i)
441 cf -> getcube (i, c);
446 int countExit = cf -> countExit ();
447 for (
int i = 0; i < countExit; ++ i)
449 cf -> getcube (countS + i, c);
454 for (
int i = 0; i < countExit; ++ i)
456 int countImg = cf -> imgcount (countS + i);
457 for (
int j = 0; j < countImg; ++ j)
459 int n = cf -> getimgcube (countS + i, j);
460 cf -> getcube (n, c);
467 for (
int i = 0; i < countS + countExit; ++ i)
469 cf -> getcube (i, c);
470 const CubeType q (c, dim);
472 int countImg = cf -> imgcount (i);
473 for (
int j = 0; j < countImg; ++ j)
475 int n = cf -> getimgcube (i, j);
476 cf -> getcube (n, c);
483 static char debugfilename [] =
"_/_x.cub";
484 if (debugfilename [1] ==
'9')
485 debugfilename [1] =
'A';
486 if (debugfilename [1] <
'Z')
487 ++ (debugfilename [1]);
492 { debugfilename [3] =
'x'; std::ofstream f (debugfilename); f << X; }
493 { debugfilename [3] =
'a'; std::ofstream f (debugfilename); f << A; }
494 { debugfilename [3] =
'y'; std::ofstream f (debugfilename); f << Y; }
495 { debugfilename [3] =
'b'; std::ofstream f (debugfilename); f << B; }
496 { debugfilename [3] =
'f'; std::ofstream f (debugfilename); f << F; }
500 sbug <<
"Preparation completed in " << prepTime <<
".\n";
504 sbug <<
"Computing the Conley index map in homology...\n";
508 chain<euclidom> *homXA = 0, *homYB = 0;
509 chainmap<euclidom> *homF = 0;
510 int maxlevelXA = -1, maxlevelYB = -1, maxlevelF = -1;
519 maxlevelF = chomp::homology::Homology2l
520 (F,
"F", X,
"X", A,
"A",
521 homXA, maxlevelXA, homF, 0xFF);
522 maxlevelYB = maxlevelXA;
526 maxlevelF = chomp::homology::Homology
527 (F,
"F", X,
"X", A,
"A",
528 Y,
"Y", B,
"B", homXA, maxlevelXA,
529 homYB, maxlevelYB, homF,
true, 0x03);
541 sout <<
"*** Homology computation failed. "
542 "Using a careful two-layer method. ***\n";
548 if (!error && ((maxlevelF != maxlevelXA) ||
549 (maxlevelXA != maxlevelYB)))
552 throw "Wrong homology levels in the Conley index.";
553 sout <<
"*** Homology levels don't agree. "
554 "Using a careful two-layer method. ***\n";
559 sbug <<
"The map computed in " << compTime <<
".\n";
575 return this -> compute (
true);
579 for (
int level = 0; level <= toplevel; ++ level)
581 std::vector<euclidom> coefficients;
582 if (level <= maxlevelXA)
584 for (
int i = 0; i < homXA [level]. size (); ++ i)
585 coefficients. push_back
586 (homXA [level]. coef (i));
588 coef. push_back (coefficients);
593 indmap =
new mmatrix<euclidom> [toplevel + 1];
599 for (
int i = 0; i <= maxlevelXA; ++ i)
600 indmap [i] = (*homF) [i];
605 debugfilename [3] =
'h';
606 std::ofstream f (debugfilename);
616template <
class IndexPair,
class eucl
idom>
621 const int twice_the_level = (toplevel + 1) << 1;
622 for (
int level = 0; level < twice_the_level; ++ level)
625 bool columns = (level > toplevel);
626 chomp::homology::mmatrix<euclidom> &matr = indmap [columns ?
627 (level - toplevel - 1) : level];
630 int n = columns ? matr. getncols () : matr. getnrows ();
633 int *lengths =
new int [n];
634 for (
int i = 0; i < n; ++ i)
635 lengths [i] = columns ? matr. getcol (i). size () :
636 matr. getrow (i). size ();
640 for (
int i = 0; i < n; ++ i)
642 int length = lengths [i];
645 chomp::homology::chain<euclidom> col_row = columns ?
646 matr. getcol (i) : matr. getrow (i);
647 for (
int j = 0; j < length; ++ j)
649 int row_col = col_row. num (j);
650 if (lengths [row_col] > 0)
652 matr. add (columns ? row_col : i,
653 columns ? i : row_col,
663 for (
int level = toplevel; shrink && (level >= 0); -- level)
666 chomp::homology::mmatrix<euclidom> &matr = indmap [level];
667 std::vector<euclidom> &coefs = coef [level];
670 if (!matr. getncols () || !coefs. size ())
673 chomp::homology::mmatrix<euclidom> emptymatr;
681 std::vector<int> selected;
682 int ncols = matr. getncols ();
683 for (
int i = 0; i < ncols; ++ i)
684 if (matr. getcol (i). size () >= 1)
685 selected. push_back (i);
686 int length = selected. size ();
692 chomp::homology::mmatrix<euclidom> emptymatr;
700 chomp::homology::mmatrix<euclidom> newmatr;
701 newmatr. define (length, length);
702 for (
int i = 0; i < length; ++ i)
704 for (
int j = 0; j < length; ++ j)
706 newmatr. add (i, j, matr. get (selected [i],
713 std::vector<euclidom> newcoefs (length);
714 for (
int i = 0; i < length; ++ i)
715 newcoefs [i] = coefs [selected [i]];
726 for (
int level = 0; level <= toplevel; ++ level)
729 chomp::homology::mmatrix<euclidom> &matr =
733 int n = matr. getncols ();
734 for (
int i = 0; i < n; ++ i)
736 const chomp::homology::chain<euclidom> &column =
738 if (column. size () != 1)
740 if (column. coef (0) != minus1)
742 if (column. num (0) <= i)
744 matr. multiplyrow (i, minus1);
745 matr. multiplycol (i, minus1);
753template <
class IndexPair,
class eucl
idom>
756 if ((newlevel >= -1) && (newlevel <= toplevel))
759 coef. erase (coef. begin () + toplevel + 1, coef. end ());
764template <
class IndexPair,
class eucl
idom>
766 std::vector<double> &Re, std::vector<double> &Im,
767 bool nonzero,
bool sorted)
const
769 using chomp::homology::auto_array;
772 if ((level < 0) || (level > toplevel))
776 const chomp::homology::mmatrix<euclidom> &m = indmap [level];
777 int fullsize = m. getncols ();
783 const std::vector<euclidom> &coefs = coef [level];
784 std::vector<int> indices (size);
786 for (
int i = 0; i < fullsize; ++ i)
788 if (coefs [i]. delta () > 1)
795 indices [i] = current;
804 int32 dimension = size;
805 auto_array<double> APtr (
new double [size * size]);
806 double *A = APtr. get ();
807 auto_array<double> rePtr (
new double [size]);
808 double *re = rePtr. get ();
809 auto_array<double> imPtr (
new double [size]);
810 double *im = imPtr. get ();
811 int32 worksize = 3 * size + (2 * size + 128);
812 auto_array<double> workPtr (
new double [worksize]);
813 double *work = workPtr. get ();
818 for (
int i = 0; i < size; ++ i)
820 for (
int j = 0; j < size; ++ j)
825 for (
int col = 0; col < fullsize; ++ col)
827 int icol = indices [col];
830 const chomp::homology::chain<euclidom> c = m. getcol (col);
831 int len = c. size ();
832 for (
int i = 0; i < len; ++ i)
834 int irow = indices [c. num (i)];
837 euclidom e = c. coef (i);
843 A [size * irow + icol] = n;
851 dgeev_ (&N, &N, &dimension, A, &dimension, re, im,
852 0, &dimension, 0, &dimension, work, &worksize, &result);
856 throw "Conley Index eigenvalues: LAPACK error.";
858 throw "The QR algorithm failed in the Conley Index "
859 "Eigenvalues computation.";
862 std::vector<ppComplex> values;
863 const double epsilon = 0.001;
864 const double threshold = 0.01;
865 for (
int i = 0; i < size; ++ i)
867 re [i] = round (re [i], epsilon, threshold);
868 im [i] = round (im [i], epsilon, threshold);
869 if (nonzero && !re [i] && !im [i])
871 values. push_back (
ppComplex (re [i], im [i]));
880 std::sort (values. begin (), values. end ());
883 for (std::vector<ppComplex>::const_iterator it = values. begin ();
884 it != values. end (); ++ it)
886 Re. push_back (it -> re);
887 Im. push_back (it -> im);
890 return values. size ();
893template <
class IndexPair,
class eucl
idom>
897 if (nontrivialindex >= 0)
898 return !nontrivialindex;
900 for (
int level = 0; level <= toplevel; ++ level)
902 std::vector<double> Re, Im;
903 int n = eigenvalues (level, Re, Im,
true,
false);
916template <
class IndexPair,
class eucl
idom>
920 if (!indmap || (n < 0) || (n > toplevel))
921 return std::string ();
924 std::ostringstream out;
927 std::vector<double> Re, Im;
928 int count = eigenvalues (n, Re, Im);
933 out <<
"Eigenvalues " << n <<
": (";
936 for (
int i = 0; i < count; ++ i)
947 out << Im [i] <<
"i";
957template <
class IndexPair,
class eucl
idom>
959 const chomp::homology::mmatrix<euclidom> *matr,
int _toplevel)
962 nontrivialindex = -1;
965 toplevel = _toplevel;
971 for (
int i = 0; i <= toplevel; ++ i)
973 std::vector<euclidom> b;
974 for (
int j = betti [i]; j > 0; -- j)
987 indmap =
new chomp::homology::mmatrix<euclidom>
990 for (
int level = 0; level <= toplevel; ++ level)
992 indmap [level] = matr [level];
997template <
class IndexPair,
class eucl
idom>
1002 chomp::homology::mmatrix<euclidom> *matr = (_toplevel < 0) ? 0 :
1003 new chomp::homology::mmatrix<euclidom> [_toplevel + 1];
1004 for (
int level = 0; level <= _toplevel; ++ level)
1006 if (betti [level] > 0)
1007 matr [level]. identity (betti [level]);
1011 this -> define (betti, matr, _toplevel);
1021template <
class IndexPair,
class eucl
idom>
1026 out << c. toplevel <<
" ";
1027 if (c. toplevel < 0)
1031 for (
int i = 0; i <= c. toplevel; ++ i)
1033 int size = c. coef [i]. size ();
1035 for (
int j = 0; j < size; ++ j)
1036 out << c. coef [i] [j] <<
" ";
1040 for (
int i = 0; i <= c. toplevel; ++ i)
1042 const chomp::homology::mmatrix<euclidom> &m = c. indmap [i];
1043 out << m. getnrows () <<
" " << m. getncols () <<
" ";
1044 for (
int j = 0; j < m. getncols (); ++ j)
1046 const chomp::homology::chain<euclidom> &col =
1048 out << col. size () <<
" ";
1049 for (
int k = 0; k < col. size (); ++ k)
1051 out << col. num (k) <<
" ";
1052 out << col. coef (k) <<
" ";
1060template <
class IndexPair,
class eucl
idom>
1065 c. nontrivialindex = -1;
1068 delete [] c. indmap;
1075 if (c. toplevel < 0)
1079 for (
int i = 0; i <= c. toplevel; ++ i)
1084 throw "Cannot decode the Conley index from input.";
1085 std::vector<euclidom> coef;
1086 for (
int j = 0; j < size; ++ j)
1091 if (e. delta () <= 0)
1092 throw "Wrong coefficient in the "
1093 "Conley index from input.";
1094 coef. push_back (e);
1096 c. coef. push_back (coef);
1100 if (c. toplevel >= 0)
1101 c. indmap =
new chomp::homology::mmatrix<euclidom>
1103 for (
int i = 0; i <= c. toplevel; ++ i)
1105 chomp::homology::mmatrix<euclidom> &m = c. indmap [i];
1106 int nrows = 0, ncols = 0;
1107 in >> nrows >> ncols;
1108 if ((nrows < 0) || (ncols < 0))
1109 throw "Wrong matrix size in the Conley index "
1111 if ((nrows > 0) && (ncols > 0))
1112 m. define (nrows, ncols);
1113 for (
int j = 0; j < ncols; ++ j)
1118 throw "Negative column length in the "
1119 "Conley index from input.";
1120 for (
int k = 0; k < length; ++ k)
1124 if ((num < 0) || (num >= nrows))
1125 throw "Wrong row number in the "
1126 "Conley index from input.";
1130 if (e. delta () <= 0)
1131 throw "Wrong matrix entry in the "
1132 "Conley index from input.";
1143template <
class IndexPair,
class eucl
idom>
1146 const char *newline =
"\n")
1148 int toplevel = c. dim ();
1149 out <<
"Homology: " << c. HomString () << newline;
1150 for (
int n = 0; n <= toplevel; ++ n)
1152 out <<
"- Level " << n <<
":" << newline;
1153 out <<
"Nonzero eigenvalues: " << c. EigenString (n) <<
1155 out << c. MapString (n, newline);
The class that computes and returns properties of the Conley index.
bool trivial() const
Verifies if the index is trivial.
const chomp::homology::mmatrix< euclidom > * Map(int n) const
Retrieves the matrix of the index map at the given level.
int eigenvalues(int level, std::vector< double > &Re, std::vector< double > &Im, bool nonzero=true, bool sorted=true) const
Computes the eigenvalues of the index map.
int nontrivialindex
Variable that stores the tabulated information on whether the index is nontrivial.
void define(const int *betti, const chomp::homology::mmatrix< euclidom > *matr, int _toplevel)
Defines the Conley index by the given Betti numbers and the given maps in homology.
std::vector< std::vector< euclidom > > coef
The torsion coefficients of the corresponding homology generators.
const IndexPair * cf
An object that feeds this class with cubes.
int toplevel
The number of the top homology level.
~ConleyIndex()
The destructor.
euclidom Coefficient(int n, int i) const
Retrieves the 'i'th [torsion] coefficient at the nth level.
void setIndexPair(const IndexPair *f)
Sets the index pair to be used to compute the Conley index.
int dim() const
Retrieves the top level, or the maximal dimension of the index.
int compute(bool twolayer=false)
Computes the Conley index.
ConleyIndex(const IndexPair *c=0)
The default constructor.
std::string HomString() const
Retrieves a human-readable text representation of the homology.
std::string MapString(int n, const char *newline="\n") const
Retrieves a human-readable text representation of the map.
chomp::homology::mmatrix< euclidom > * indmap
The matrices of the index map at each level.
int BettiNumber(int n) const
Retrieves the nth Betti number.
void truncate(int newlevel)
Truncates the Conley index to the new top level.
static double round(double x, double epsilon, double threshold)
Rounds a real number to the given precision.
int reduce(bool shrink=true)
Reduces the index map using some shift equivalences to certain extent.
std::string EigenString(int n) const
Retrieves a human-readable text showing the eigenvalues.
The empty index pair class simulates an empty index pair.
A generic class that computes an index pair given the isolating neighborhood and a means to compute t...
cubetype CubeType
The type of a cube.
cubsettype CubSetType
The type of a set of cubes.
Choice of configuration settings.
std::istream & operator>>(std::istream &in, ConleyIndex< IndexPair, euclidom > &c)
int dgeev_(char *jobvl, char *jobvr, int32 *n, double *a, int32 *lda, double *wr, double *wi, double *vl, int32 *ldvl, double *vr, int32 *ldvr, double *work, int32 *lwork, int32 *info)
bool operator<(const ppComplex &x, const ppComplex &y)
std::ostream & operator<<(std::ostream &out, const ConleyIndex< IndexPair, euclidom > &c)
std::ostream & writeIndexInfo(std::ostream &out, const ConleyIndex< IndexPair, euclidom > &c, const char *newline="\n")
Writes the Conley index information in human-readable form to an output stream.
The Conley index pair computation.
Map computation routines.
An auxiliary class that represents complex numbers.
ppComplex(double _re, double _im)
Customizable data types for the Conley-Morse graphs computation program.