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.