00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef _CMGRAPHS_CONINDEX_H_
00034 #define _CMGRAPHS_CONINDEX_H_
00035
00036
00037
00038 #include <iostream>
00039 #include <algorithm>
00040 #include <new>
00041
00042
00043 #include "chomp/system/textfile.h"
00044 #include "chomp/system/timeused.h"
00045 #include "chomp/homology/homology.h"
00046
00047
00048 #include "interval/doubleInterval.h"
00049
00050
00051 #include "config.h"
00052
00053
00054
00055
00056
00057
00058 extern "C" {
00059 int dgeev_ (char *jobvl, char *jobvr, long int *n,
00060 double * a, long int *lda, double *wr, double *wi, double *vl,
00061 long int *ldvl, double *vr, long int *ldvr, double *work,
00062 long int *lwork, long int *info);
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
00072 class IdentityMap
00073 {
00074 public:
00075
00076 int operator () (const interval *x, interval *y, int dim) const;
00077
00078 };
00079
00080 inline int IdentityMap::operator () (const interval *x, interval *y, int dim)
00081 const
00082 {
00083 for (int i = 0; i < dim; ++ i)
00084 y [i] = x [i];
00085 return 0;
00086 }
00087
00088
00089
00090
00091 class UndefinedMap
00092 {
00093 public:
00094
00095 int operator () (const interval *x, interval *y, int dim) const;
00096
00097 };
00098
00099 inline int UndefinedMap::operator () (const interval *, interval *, int)
00100 const
00101 {
00102 throw "Trying to use an undefined map.";
00103 return 0;
00104 }
00105
00106
00107
00108
00109
00110
00111
00112
00113 template <class mapcomp, class cubetype,
00114 class cubsettype = chomp::homology::hashedset<cubetype> >
00115 class MapComputation
00116 {
00117 public:
00118
00119 MapComputation (const double *_offset, const double *_width,
00120 int _intwidth, const mapcomp &_M = mapcomp ());
00121
00122
00123 ~MapComputation ();
00124
00125
00126
00127
00128
00129
00130
00131 int operator () (const cubetype &q, cubsettype &img) const;
00132
00133
00134 bool cache;
00135
00136
00137 mutable bool cropping;
00138
00139
00140
00141 mutable bool cropped;
00142
00143
00144
00145 static int maxImgDiam;
00146
00147
00148
00149 static int maxImgVol;
00150
00151 private:
00152
00153 mutable int cacheused;
00154
00155
00156 const double *offset;
00157
00158
00159 const double *width;
00160
00161
00162 int intwidth;
00163
00164
00165
00166 const mapcomp &M;
00167
00168
00169 mutable cubsettype computed;
00170
00171
00172 mutable chomp::homology::multitable<cubetype> leftcache;
00173
00174
00175 mutable chomp::homology::multitable<cubetype> rightcache;
00176
00177
00178
00179
00180 int compute (const typename cubetype::CoordType *coord, int dim,
00181 typename cubetype::CoordType *left,
00182 typename cubetype::CoordType *right) const;
00183
00184 };
00185
00186
00187
00188 template <class mapcomp, class cubetype, class cubsettype>
00189 int MapComputation<mapcomp,cubetype,cubsettype>::maxImgDiam;
00190
00191 template <class mapcomp, class cubetype, class cubsettype>
00192 int MapComputation<mapcomp,cubetype,cubsettype>::maxImgVol;
00193
00194
00195
00196 template <class mapcomp, class cubetype, class cubsettype>
00197 inline MapComputation<mapcomp,cubetype,cubsettype>::MapComputation
00198 (const double *_offset, const double *_width,
00199 int _intwidth, const mapcomp &_M):
00200 cache (false), cropping (false), cropped (false), cacheused (0),
00201 offset (_offset), width (_width), intwidth (_intwidth), M (_M)
00202 {
00203 return;
00204 }
00205
00206 template <class mapcomp, class cubetype, class cubsettype>
00207 inline MapComputation<mapcomp,cubetype,cubsettype>::~MapComputation ()
00208 {
00209
00210
00211
00212
00213
00214
00215 if (cache && false)
00216 {
00217 std::ofstream f ("f.map");
00218 for (int i = 0; i < computed. size (); ++ i)
00219 {
00220 typename cubetype::CoordType c [cubetype::MaxDim];
00221 f << "[" << computed [i];
00222 computed [i]. coord (c);
00223 for (int j = 0; j < computed [i]. dim (); ++ j)
00224 ++ c [j];
00225 f << cubetype (c, computed [i]. dim ()) << "] ";
00226 f << "[" << leftcache [i] << rightcache [i] << "]\n";
00227 }
00228 }
00229 return;
00230 }
00231
00232 template <class mapcomp, class cubetype, class cubsettype>
00233 inline int MapComputation<mapcomp,cubetype,cubsettype>::compute
00234 (const typename cubetype::CoordType *coord, int dim,
00235 typename cubetype::CoordType *left,
00236 typename cubetype::CoordType *right) const
00237 {
00238
00239 std::auto_ptr<interval> xPtr (new interval [dim]);
00240 interval *x = xPtr. get ();
00241 for (int i = 0; i < dim; ++ i)
00242 {
00243 x [i] = interval (coord [i], coord [i] + 1);
00244 x [i] /= intwidth;
00245 x [i] *= width [i];
00246 x [i] += offset [i];
00247 }
00248
00249
00250 std::auto_ptr<interval> yPtr (new interval [dim]);
00251 interval *y = yPtr. get ();
00252 M (x, y, dim);
00253
00254
00255
00256 for (int i = 0; i < dim; ++ i)
00257 {
00258 y [i] -= offset [i];
00259 y [i] /= width [i];
00260 y [i] *= intwidth;
00261
00262 double left_b = y [i]. leftBound ();
00263 left [i] =
00264 static_cast<typename cubetype::CoordType> (left_b);
00265 for (int j = 0; (j < 4) && (left [i] >= left_b); ++ j)
00266 -- left [i];
00267 if ((left [i] >= left_b) || (left_b - left [i] > 2))
00268 throw "Map computation: Left bound out of range.";
00269
00270 double right_b = y [i]. rightBound ();
00271 right [i] =
00272 static_cast<typename cubetype::CoordType> (right_b);
00273 for (int j = 0; (j < 4) && (right [i] <= right_b); ++ j)
00274 ++ right [i];
00275 if ((right [i] <= right_b) || (right [i] - right_b > 2))
00276 throw "Map computation: Right bound out of range.";
00277 }
00278
00279 return 0;
00280 }
00281
00282 template <class mapcomp, class cubetype, class cubsettype>
00283 inline int MapComputation<mapcomp,cubetype,cubsettype>::operator ()
00284 (const cubetype &q, cubsettype &img) const
00285 {
00286 typedef typename cubetype::CoordType coordType;
00287
00288
00289 int dim = q. dim ();
00290 std::auto_ptr<coordType> leftPtr (new coordType [dim]);
00291 coordType *left = leftPtr. get ();
00292 std::auto_ptr<coordType> rightPtr (new coordType [dim]);
00293 coordType *right = rightPtr. get ();
00294
00295
00296 int number = cache ? computed. getnumber (q) : -1;
00297
00298
00299 if (number < 0)
00300 {
00301 q. coord (left);
00302 compute (left, dim, left, right);
00303
00304
00305 if (cache)
00306 {
00307 leftcache [computed. size ()] = cubetype (left, dim);
00308 rightcache [computed. size ()] =
00309 cubetype (right, dim);
00310 computed. add (q);
00311 }
00312 }
00313
00314
00315 else
00316 {
00317 ++ cacheused;
00318 leftcache [number]. coord (left);
00319 rightcache [number]. coord (right);
00320 }
00321
00322
00323 if (cropping)
00324 {
00325 for (int i = 0; i < dim; ++ i)
00326 {
00327 if (left [i] < 0)
00328 {
00329 left [i] = 0;
00330 if (right [i] <= left [i])
00331 right [i] = left [i] + 1;
00332 cropped = true;
00333 }
00334 if (right [i] > intwidth)
00335 {
00336 right [i] = intwidth;
00337 if (left [i] >= right [i])
00338 left [i] = right [i] - 1;
00339 cropped = true;
00340 }
00341 }
00342 }
00343
00344
00345 int volume = 1;
00346 for (int i = 0; i < dim; ++ i)
00347 {
00348 int size = right [i] - left [i];
00349 if (maxImgDiam < size)
00350 maxImgDiam = size;
00351 if (size > maxImageDiameter)
00352 throw "Excessive diameter of box image.";
00353 volume *= size;
00354 if (volume > maxImageVolume)
00355 throw "Excessive volume of box image.";
00356 }
00357 if (maxImgVol < volume)
00358 maxImgVol = volume;
00359
00360
00361 chomp::homology::tRectangle<typename cubetype::CoordType>
00362 r (left, right, dim);
00363 const typename cubetype::CoordType *c;
00364 while ((c = r. get ()) != 0)
00365 {
00366 img. add (cubetype (c, dim));
00367 }
00368
00369 return 0;
00370 }
00371
00372
00373
00374
00375 template<class cubetype, class cubsettype>
00376 class UndefinedComputation
00377 {
00378 public:
00379 int operator () (const cubetype &q, cubsettype &img) const;
00380
00381 };
00382
00383 template<class cubetype, class cubsettype>
00384 int UndefinedComputation<cubetype, cubsettype>::operator ()
00385 (const cubetype &q, cubsettype &img) const
00386 {
00387 throw "Trying to use undefined map computation.";
00388 return 0;
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 class EmptyIndexPair
00405 {
00406 public:
00407
00408 int dim () const {return 1;}
00409
00410
00411 int countInv () const {return 0;}
00412
00413
00414 int countExit () const {return 0;}
00415
00416
00417
00418 int getcube (int n, int *coord) const {return 0;}
00419
00420
00421 int imgcount (int n) const {return 0;}
00422
00423
00424 int getimgcube (int n, int i) const {return 0;}
00425
00426 };
00427
00428
00429
00430
00431
00432 template <class mapcomp, class cubetype = chomp::homology::cube,
00433 class cubsettype = chomp::homology::hashedset<cubetype> >
00434 class IndexPair
00435 {
00436 public:
00437
00438 IndexPair (const mapcomp &_M = mapcomp ());
00439
00440
00441 int add (const cubetype &q);
00442
00443
00444 int dim () const;
00445
00446
00447 int countInv () const;
00448
00449
00450 const cubsettype &getInv () const;
00451
00452
00453 int countExit () const;
00454
00455
00456 const cubsettype &getExit () const;
00457
00458
00459 int getcube (int n, int *coord) const;
00460
00461
00462
00463 int imgcount (int n) const;
00464
00465
00466 int getimgcube (int n, int i) const;
00467
00468
00469
00470 int compute (int n);
00471
00472
00473
00474
00475 int compute ();
00476
00477
00478 int clear ();
00479
00480 private:
00481
00482 cubsettype S;
00483
00484
00485 cubsettype exitSet;
00486
00487
00488 cubsettype outside;
00489
00490
00491 chomp::homology::mvmap<cubetype,cubetype> F;
00492
00493
00494 const mapcomp &M;
00495
00496 };
00497
00498
00499
00500 template <class mapcomp, class cubetype, class cubsettype>
00501 inline IndexPair<mapcomp,cubetype,cubsettype>::IndexPair
00502 (const mapcomp &_M): M (_M)
00503 {
00504 return;
00505 }
00506
00507 template <class mapcomp, class cubetype, class cubsettype>
00508 inline int IndexPair<mapcomp,cubetype,cubsettype>::dim () const
00509 {
00510 if (!S. empty ())
00511 return S [0]. dim ();
00512 else if (!exitSet. empty ())
00513 return exitSet [0]. dim ();
00514 else
00515 return -1;
00516 }
00517
00518 template <class mapcomp, class cubetype, class cubsettype>
00519 inline int IndexPair<mapcomp,cubetype,cubsettype>::countInv () const
00520 {
00521 return S. size ();
00522 }
00523
00524 template <class mapcomp, class cubetype, class cubsettype>
00525 inline const cubsettype &IndexPair<mapcomp,cubetype,cubsettype>::getInv ()
00526 const
00527 {
00528 return S;
00529 }
00530
00531 template <class mapcomp, class cubetype, class cubsettype>
00532 inline int IndexPair<mapcomp,cubetype,cubsettype>::countExit () const
00533 {
00534 return exitSet. size ();
00535 }
00536
00537 template <class mapcomp, class cubetype, class cubsettype>
00538 inline const cubsettype &IndexPair<mapcomp,cubetype,cubsettype>::getExit ()
00539 const
00540 {
00541 return exitSet;
00542 }
00543
00544 template <class mapcomp, class cubetype, class cubsettype>
00545 inline int IndexPair<mapcomp,cubetype,cubsettype>::getcube
00546 (int n, int *coord) const
00547 {
00548 int countS = S. size ();
00549 if (n < countS)
00550 {
00551 S [n]. coord (coord);
00552 return 0;
00553 }
00554 int countExit = exitSet. size ();
00555 if (n < countS + countExit)
00556 {
00557 exitSet [n - countS]. coord (coord);
00558 return 0;
00559 }
00560 outside [n - countS - countExit]. coord (coord);
00561 return 0;
00562 }
00563
00564 template <class mapcomp, class cubetype, class cubsettype>
00565 inline int IndexPair<mapcomp,cubetype,cubsettype>::imgcount (int n) const
00566 {
00567 int countS = S. size ();
00568 if (n < countS)
00569 return F (S [n]). size ();
00570 else
00571 return F (exitSet [n - countS]). size ();
00572 }
00573
00574 template <class mapcomp, class cubetype, class cubsettype>
00575 inline int IndexPair<mapcomp,cubetype,cubsettype>::getimgcube
00576 (int n, int i) const
00577 {
00578 int countS = S. size ();
00579 const cubetype &q = (n < countS) ? (F (S [n])) [i] :
00580 (F (exitSet [n - countS])) [i];
00581 int num = S. getnumber (q);
00582 if (num >= 0)
00583 return num;
00584 num = exitSet. getnumber (q);
00585 if (num >= 0)
00586 return (countS + num);
00587 int countExit = exitSet. size ();
00588 num = outside. getnumber (q);
00589 if (num >= 0)
00590 return (countS + countExit + num);
00591 throw "Index pair not prepared.";
00592
00593
00594
00595 }
00596
00597
00598
00599 template <class mapcomp, class cubetype, class cubsettype>
00600 inline int IndexPair<mapcomp,cubetype,cubsettype>::compute (int n)
00601 {
00602
00603 int countS = S. size ();
00604 const cubetype &q = (n < countS) ? S [n] : exitSet [n - countS];
00605
00606
00607 cubsettype img;
00608 M (q, img);
00609 F [q]. add (img);
00610
00611
00612 for (int i = 0; i < img. size (); ++ i)
00613 {
00614 if ((n < countS) && !S. check (img [i]))
00615 exitSet. add (img [i]);
00616 if (n >= countS)
00617 {
00618 if (S. check (img [i]))
00619 throw "Wrong index pair detected.";
00620 else if (!exitSet. check (img [i]))
00621 outside. add (img [i]);
00622 }
00623 }
00624
00625
00626 if (countS + exitSet. size () + outside. size () > maxIndexPairSize)
00627 throw "Excessive index pair size.";
00628
00629 return 0;
00630 }
00631
00632 template <class mapcomp, class cubetype, class cubsettype>
00633 inline int IndexPair<mapcomp,cubetype,cubsettype>::compute ()
00634 {
00635 chomp::homology::sbug << "Computing the index pair... ";
00636
00637 int countS = S. size ();
00638 for (int i = 0; i < countS; ++ i)
00639 compute (i);
00640 int countSX = countS + exitSet. size ();
00641 for (int i = countS; i < countSX; ++ i)
00642 compute (i);
00643
00644 chomp::homology::sbug << S. size () << " + " << exitSet. size () <<
00645 " + " << outside. size () << " cubes.\n";
00646 return 0;
00647 }
00648
00649 template <class mapcomp, class cubetype, class cubsettype>
00650 inline int IndexPair<mapcomp,cubetype,cubsettype>::add (const cubetype &q)
00651 {
00652 typename cubetype::CoordType coord [cubetype::MaxDim];
00653 q. coord (coord);
00654 cubetype r (coord, q. dim ());
00655 S. add (r);
00656 return 0;
00657 }
00658
00659 template <class mapcomp, class cubetype, class cubsettype>
00660 inline int IndexPair<mapcomp,cubetype,cubsettype>::clear ()
00661 {
00662 cubsettype empty;
00663 S = empty;
00664 exitSet = empty;
00665 outside = empty;
00666 chomp::homology::mvmap<cubetype,cubetype> nomap;
00667 F = nomap;
00668 return 0;
00669 }
00670
00671
00672
00673
00674
00675
00676 template <class IndexPair, class euclidom>
00677 class ConleyIndex;
00678
00679 template <class IndexPair, class euclidom>
00680 std::istream &operator >> (std::istream &in,
00681 ConleyIndex<IndexPair,euclidom> &c);
00682
00683 template <class IndexPair, class euclidom>
00684 std::ostream &operator << (std::ostream &out,
00685 const ConleyIndex<IndexPair,euclidom> &c);
00686
00687
00688
00689 template <class IndexPair = EmptyIndexPair,
00690 class euclidom = chomp::homology::integer>
00691 class ConleyIndex
00692 {
00693 public:
00694
00695 ConleyIndex (const IndexPair *c = 0);
00696
00697
00698 ConleyIndex (const ConleyIndex<IndexPair,euclidom> &c);
00699
00700
00701 ~ConleyIndex ();
00702
00703
00704 ConleyIndex<IndexPair,euclidom> &operator =
00705 (const ConleyIndex<IndexPair,euclidom> &c);
00706
00707
00708 void setIndexPair (const IndexPair *f);
00709
00710
00711
00712
00713 int compute (bool twolayer = false);
00714
00715
00716
00717 int reduce (bool shrink = true);
00718
00719
00720 void truncate (int newlevel);
00721
00722
00723
00724
00725
00726 int eigenvalues (int level, std::vector<double> &Re,
00727 std::vector<double> &Im, bool nonzero = true,
00728 bool sorted = true) const;
00729
00730
00731
00732 bool trivial () const;
00733
00734
00735 int BettiNumber (int n) const;
00736
00737
00738
00739 euclidom Coefficient (int n, int i) const;
00740
00741
00742
00743
00744 int dim () const;
00745
00746
00747
00748 const chomp::homology::mmatrix<euclidom> *Map (int n) const;
00749
00750
00751 std::string MapString (int n, const char *newline = "\n") const;
00752
00753
00754 std::string EigenString (int n) const;
00755
00756
00757 std::string HomString () const;
00758
00759
00760
00761 void define (const int *betti,
00762 const chomp::homology::mmatrix<euclidom> *matr,
00763 int _toplevel);
00764
00765
00766
00767 void define (const int *betti, int _toplevel);
00768
00769 private:
00770
00771 const IndexPair *cf;
00772
00773
00774 int toplevel;
00775
00776
00777
00778 std::vector<std::vector<euclidom> > coef;
00779
00780
00781 chomp::homology::mmatrix<euclidom> *indmap;
00782
00783
00784 friend std::ostream &operator << <> (std::ostream &out,
00785 const ConleyIndex<IndexPair,euclidom> &c);
00786
00787
00788
00789 friend std::istream &operator >> <> (std::istream &in,
00790 ConleyIndex<IndexPair,euclidom> &c);
00791
00792
00793
00794
00795 static double round (double x, double epsilon, double threshold);
00796
00797
00798
00799
00800 mutable int nontrivialindex;
00801
00802 };
00803
00804
00805
00806
00807
00808 struct ppComplex
00809 {
00810 double re, im;
00811 ppComplex (double _re, double _im): re (_re), im (_im) {}
00812
00813 };
00814
00815 inline bool operator < (const ppComplex &x, const ppComplex &y)
00816 {
00817 if (x. re < y. re)
00818 return true;
00819 else if (x. re > y. re)
00820 return false;
00821 return (x. im < y. im);
00822 }
00823
00824
00825
00826 template <class IndexPair, class euclidom>
00827 inline ConleyIndex<IndexPair,euclidom>::ConleyIndex (const IndexPair *c)
00828 {
00829 cf = c;
00830 toplevel = -1;
00831 indmap = 0;
00832 nontrivialindex = -1;
00833 return;
00834 }
00835
00836 template <class IndexPair, class euclidom>
00837 inline ConleyIndex<IndexPair,euclidom>::ConleyIndex
00838 (const ConleyIndex<IndexPair,euclidom> &c)
00839 {
00840 cf = c. cf;
00841 toplevel = c. toplevel;
00842 coef = c. coef;
00843 if (toplevel >= 0)
00844 indmap = new chomp::homology::mmatrix<euclidom> [toplevel + 1];
00845 else
00846 indmap = 0;
00847 for (int i = 0; i <= toplevel; ++ i)
00848 indmap [i] = c. indmap [i];
00849 nontrivialindex = c. nontrivialindex;
00850 return;
00851 }
00852
00853 template <class IndexPair, class euclidom>
00854 inline ConleyIndex<IndexPair,euclidom> &
00855 ConleyIndex<IndexPair,euclidom>::operator =
00856 (const ConleyIndex<IndexPair,euclidom> &c)
00857 {
00858 cf = c. cf;
00859 toplevel = c. toplevel;
00860 coef = c. coef;
00861 if (indmap)
00862 delete [] indmap;
00863 if (toplevel >= 0)
00864 indmap = new chomp::homology::mmatrix<euclidom> [toplevel + 1];
00865 else
00866 indmap = 0;
00867 for (int i = 0; i <= toplevel; ++ i)
00868 indmap [i] = c. indmap [i];
00869 nontrivialindex = c. nontrivialindex;
00870 return *this;
00871 }
00872
00873 template <class IndexPair, class euclidom>
00874 inline ConleyIndex<IndexPair,euclidom>::~ConleyIndex ()
00875 {
00876 if (indmap)
00877 delete [] indmap;
00878 return;
00879 }
00880
00881 template <class IndexPair, class euclidom>
00882 inline void ConleyIndex<IndexPair,euclidom>::setIndexPair
00883 (const IndexPair *f)
00884 {
00885 cf = f;
00886 return;
00887 }
00888
00889 template <class IndexPair, class euclidom>
00890 double ConleyIndex<IndexPair,euclidom>::round (double x, double epsilon,
00891 double threshold)
00892 {
00893 if ((x < 0) && (x > -threshold))
00894 return 0;
00895 if ((x > 0) && (x < threshold))
00896 return 0;
00897 x /= epsilon;
00898 long xl = static_cast<long> (x);
00899 if (xl - x > 0.5)
00900 -- xl;
00901 else if (x - xl > 0.5)
00902 ++ xl;
00903 return (xl * epsilon);
00904 }
00905
00906 template <class IndexPair, class euclidom>
00907 inline int ConleyIndex<IndexPair,euclidom>::BettiNumber (int n) const
00908 {
00909 if ((n < 0) || (n > toplevel))
00910 return 0;
00911 int size = coef [n]. size ();
00912 int count = 0;
00913 for (int i = 0; i < size; ++ i)
00914 if (coef [n] [i]. delta () == 1)
00915 ++ count;
00916 return count;
00917 }
00918
00919 template <class IndexPair, class euclidom>
00920 inline const chomp::homology::mmatrix<euclidom> *
00921 ConleyIndex<IndexPair,euclidom>::Map (int n) const
00922 {
00923 if (!indmap || (n < 0) || (n > toplevel))
00924 return 0;
00925 return (indmap + n);
00926 }
00927
00928 template <class IndexPair, class euclidom>
00929 inline euclidom ConleyIndex<IndexPair,euclidom>::Coefficient
00930 (int n, int i) const
00931 {
00932 euclidom zero;
00933 zero = 0;
00934 if ((n < 0) || (n > toplevel))
00935 return zero;
00936 int size = coef [n]. size ();
00937 if ((i < 0) || (i >= size))
00938 return zero;
00939 return coef [n] [i];
00940 }
00941
00942 template <class IndexPair, class euclidom>
00943 inline int ConleyIndex<IndexPair,euclidom>::dim () const
00944 {
00945 return toplevel;
00946 }
00947
00948 template <class IndexPair, class euclidom>
00949 inline std::string ConleyIndex<IndexPair,euclidom>::MapString (int n,
00950 const char *newline) const
00951 {
00952 if (!indmap || (n < 0) || (n > toplevel))
00953 return std::string ();
00954 std::ostringstream out;
00955 const chomp::homology::mmatrix<euclidom> &m = indmap [n];
00956 bool nonzero = false;
00957 for (int j = 0; j < m. getncols (); j ++)
00958 if (m. getcol (j). size ())
00959 {
00960 if (!nonzero)
00961 {
00962 out << "Map " << n << ":" << newline;
00963 nonzero = true;
00964 }
00965 out << "#" << (j + 1) << " = " << m. getcol (j) <<
00966 newline;
00967 }
00968 if (!nonzero)
00969 out << "Map" << n << " = 0" << newline;
00970 return out. str ();
00971 }
00972
00973 template <class IndexPair, class euclidom>
00974 inline std::string ConleyIndex<IndexPair,euclidom>::HomString () const
00975 {
00976 if (coef. size () <= 0)
00977 return std::string ("0");
00978 std::ostringstream out;
00979 int coefsize = coef. size ();
00980 for (int i = 0; i < coefsize; ++ i)
00981 {
00982 bool nonzero = false;
00983 if (i)
00984 out << ", ";
00985 int counter = 0;
00986 int size = coef [i]. size ();
00987 for (int j = 0; j < size; ++ j)
00988 {
00989 if (coef [i] [j]. delta () > 1)
00990 {
00991 if (nonzero)
00992 out << "+";
00993 if (counter)
00994 {
00995 out << "Z";
00996 if (counter > 1)
00997 out << "^" << counter;
00998 out << "+";
00999 counter = 0;
01000 }
01001 out << "Z_" << coef [i] [j];
01002 nonzero = true;
01003 }
01004 else
01005 ++ counter;
01006 }
01007 if (counter)
01008 {
01009 if (nonzero)
01010 out << "+";
01011 out << "Z";
01012 if (counter > 1)
01013 out << "^" << counter;
01014 nonzero = true;
01015 }
01016 if (!nonzero)
01017 out << "0";
01018 }
01019 return out. str ();
01020 }
01021
01022 template <class IndexPair, class euclidom>
01023 inline int ConleyIndex<IndexPair,euclidom>::compute (bool twolayer)
01024 {
01025 using namespace chomp::homology;
01026
01027
01028 sbug << "Preparing to compute the Conley index...\n";
01029 timeused prepTime;
01030
01031
01032 int shifted = twolayer ? 1 : 0;
01033 SetOfCubes X, A, Y, B;
01034 SetOfCubes Xflat, Aflat;
01035 int dim = cf -> dim ();
01036 int countS = cf -> countInv ();
01037 int c [Cube::MaxDim];
01038 typename Cube::CoordType coord [Cube::MaxDim];
01039 coord [dim] = 2;
01040 for (int i = 0; i < countS; ++ i)
01041 {
01042 cf -> getcube (i, c);
01043 for (int j = 0; j < dim; ++ j)
01044 {
01045 coord [j] = static_cast<typename Cube::CoordType>
01046 (c [j]);
01047 if (coord [j] != c [j])
01048 throw "Cube coordinatess out of range.";
01049 }
01050 Cube q (coord, dim + shifted);
01051 X. add (q);
01052 Y. add (q);
01053 Cube qflat (coord, dim);
01054 Xflat. add (qflat);
01055 }
01056 int countExit = cf -> countExit ();
01057 coord [dim] = 1;
01058 for (int i = 0; i < countExit; ++ i)
01059 {
01060 cf -> getcube (countS + i, c);
01061 for (int j = 0; j < dim; ++ j)
01062 {
01063 coord [j] = static_cast<typename Cube::CoordType>
01064 (c [j]);
01065 if (coord [j] != c [j])
01066 throw "Cube coordinatess out of range.";
01067 }
01068 Cube q (coord, dim + shifted);
01069 A. add (q);
01070 B. add (q);
01071 Cube qflat (coord, dim);
01072 Aflat. add (qflat);
01073 }
01074 coord [dim] = 0;
01075 for (int i = 0; i < countExit; ++ i)
01076 {
01077 int countImg = cf -> imgcount (countS + i);
01078 for (int j = 0; j < countImg; ++ j)
01079 {
01080 int n = cf -> getimgcube (countS + i, j);
01081 cf -> getcube (n, c);
01082 for (int j = 0; j < dim; ++ j)
01083 {
01084 coord [j] = static_cast<typename
01085 Cube::CoordType> (c [j]);
01086 if (coord [j] != c [j])
01087 throw "Coordinatess out of range.";
01088 }
01089 Cube q (coord, dim + shifted);
01090 B. add (q);
01091 }
01092 }
01093
01094 cubicalmap F;
01095 for (int i = 0; i < countS + countExit; ++ i)
01096 {
01097 if (i < countS)
01098 coord [dim] = 2;
01099 else
01100 coord [dim] = 1;
01101 cf -> getcube (i, c);
01102 for (int j = 0; j < dim; ++ j)
01103 coord [j] = (typename Cube::CoordType) (c [j]);
01104 const Cube q (coord, dim + shifted);
01105 F [q];
01106 int countImg = cf -> imgcount (i);
01107 for (int j = 0; j < countImg; ++ j)
01108 {
01109 int n = cf -> getimgcube (i, j);
01110 cf -> getcube (n, c);
01111 for (int j = 0; j < dim; ++ j)
01112 coord [j] = (typename Cube::CoordType)
01113 (c [j]);
01114 Cube qtest (coord, dim);
01115 if (Xflat. check (qtest))
01116 coord [dim] = 2;
01117 else if (Aflat. check (qtest))
01118 coord [dim] = 1;
01119 else
01120 coord [dim] = 0;
01121 Cube r (coord, dim + shifted);
01122 F [q]. add (r);
01123 }
01124 }
01125
01126
01127 SetOfCubes emptyset;
01128 Xflat = emptyset;
01129 Aflat = emptyset;
01130
01131
01132 static char debugfilename [] = "_/_x.cub";
01133 if (debugfilename [1] == '9')
01134 debugfilename [1] = 'A';
01135 if (debugfilename [1] < 'Z')
01136 ++ (debugfilename [1]);
01137
01138
01139 if (false)
01140 {
01141 { debugfilename [3] = 'x'; std::ofstream f (debugfilename); f << X; }
01142 { debugfilename [3] = 'a'; std::ofstream f (debugfilename); f << A; }
01143 { debugfilename [3] = 'y'; std::ofstream f (debugfilename); f << Y; }
01144 { debugfilename [3] = 'b'; std::ofstream f (debugfilename); f << B; }
01145 { debugfilename [3] = 'f'; std::ofstream f (debugfilename); f << F; }
01146 }
01147
01148
01149 sbug << "Preparation completed in " << prepTime << ".\n";
01150 prepTime = 0;
01151
01152
01153 sbug << "Computing the Conley index map in homology...\n";
01154 timeused compTime;
01155
01156
01157 chain<euclidom> *homXA = 0, *homYB = 0;
01158 chainmap<euclidom> *homF = 0;
01159 int maxlevelXA = -1, maxlevelYB = -1, maxlevelF = -1;
01160 bool error = false;
01161 try
01162 {
01163 chomp::homology::outputstream::mute mcon (scon);
01164 chomp::homology::outputstream::mute mout (sout);
01165 chomp::homology::outputstream::mute mbug (sbug);
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176 {
01177 maxlevelF = Homology (F, "F", X, "X", A, "A",
01178 Y, "Y", B, "B", homXA, maxlevelXA,
01179 homYB, maxlevelYB, homF, true);
01180 }
01181 }
01182 catch (...)
01183 {
01184
01185 if (twolayer)
01186 throw;
01187
01188
01189 else
01190 {
01191 sout << "*** Homology computation failed. "
01192 "Using a careful two-layer method. ***\n";
01193 error = true;
01194 }
01195 }
01196
01197
01198 if (!error && ((maxlevelF != maxlevelXA) ||
01199 (maxlevelXA != maxlevelYB)))
01200 {
01201 if (twolayer)
01202 throw "Wrong homology levels in the Conley index.";
01203 sout << "*** Homology levels don't agree. "
01204 "Using a careful two-layer method. ***\n";
01205 error = true;
01206 }
01207
01208
01209 sbug << "The map computed in " << compTime << ".\n";
01210 compTime = 0;
01211
01212
01213 if (error)
01214 {
01215 delete [] homXA;
01216 delete [] homYB;
01217 delete homF;
01218 X = emptyset;
01219 A = emptyset;
01220 Y = emptyset;
01221 B = emptyset;
01222 cubicalmap emptymap;
01223 F = emptymap;
01224 return this -> compute (true);
01225 }
01226
01227 toplevel = dim;
01228 for (int level = 0; level <= toplevel; ++ level)
01229 {
01230 std::vector<euclidom> coefficients;
01231 if (level <= maxlevelXA)
01232 {
01233 for (int i = 0; i < homXA [level]. size (); ++ i)
01234 coefficients. push_back
01235 (homXA [level]. coef (i));
01236 }
01237 coef. push_back (coefficients);
01238 }
01239 if (indmap)
01240 delete [] indmap;
01241 if (toplevel >= 0)
01242 indmap = new mmatrix<euclidom> [toplevel + 1];
01243 else
01244 {
01245 indmap = 0;
01246 nontrivialindex = 0;
01247 }
01248 for (int i = 0; i <= maxlevelXA; ++ i)
01249 indmap [i] = (*homF) [i];
01250
01251
01252 if (false && homF)
01253 {
01254 debugfilename [3] = 'h';
01255 std::ofstream f (debugfilename);
01256 f << *homF;
01257 }
01258
01259 delete [] homXA;
01260 delete [] homYB;
01261 delete homF;
01262 return 0;
01263 }
01264
01265 template <class IndexPair, class euclidom>
01266 inline int ConleyIndex<IndexPair,euclidom>::reduce (bool shrink)
01267 {
01268
01269
01270 const int twice_the_level = (toplevel + 1) << 1;
01271 for (int level = 0; level < twice_the_level; ++ level)
01272 {
01273
01274 bool columns = (level > toplevel);
01275 chomp::homology::mmatrix<euclidom> &matr = indmap [columns ?
01276 (level - toplevel - 1) : level];
01277
01278
01279 int n = columns ? matr. getncols () : matr. getnrows ();
01280 if (n <= 0)
01281 continue;
01282 int *lengths = new int [n];
01283 for (int i = 0; i < n; ++ i)
01284 lengths [i] = columns ? matr. getcol (i). size () :
01285 matr. getrow (i). size ();
01286
01287
01288
01289 for (int i = 0; i < n; ++ i)
01290 {
01291 int length = lengths [i];
01292 if (!length)
01293 continue;
01294 chomp::homology::chain<euclidom> col_row = columns ?
01295 matr. getcol (i) : matr. getrow (i);
01296 for (int j = 0; j < length; ++ j)
01297 {
01298 int row_col = col_row. num (j);
01299 if (lengths [row_col] > 0)
01300 continue;
01301 matr. add (columns ? row_col : i,
01302 columns ? i : row_col,
01303 -col_row. coef (j));
01304 }
01305 }
01306
01307
01308 delete [] lengths;
01309 }
01310
01311
01312 for (int level = toplevel; shrink && (level >= 0); -- level)
01313 {
01314
01315 chomp::homology::mmatrix<euclidom> &matr = indmap [level];
01316 std::vector<euclidom> &coefs = coef [level];
01317
01318
01319 if (!matr. getncols () || !coefs. size ())
01320 {
01321 coefs. clear ();
01322 chomp::homology::mmatrix<euclidom> emptymatr;
01323 matr = emptymatr;
01324
01325
01326 continue;
01327 }
01328
01329
01330 std::vector<int> selected;
01331 int ncols = matr. getncols ();
01332 for (int i = 0; i < ncols; ++ i)
01333 if (matr. getcol (i). size () >= 1)
01334 selected. push_back (i);
01335 int length = selected. size ();
01336
01337
01338 if (!length)
01339 {
01340 coefs. clear ();
01341 chomp::homology::mmatrix<euclidom> emptymatr;
01342 matr = emptymatr;
01343
01344
01345 continue;
01346 }
01347
01348
01349 chomp::homology::mmatrix<euclidom> newmatr;
01350 newmatr. define (length, length);
01351 for (int i = 0; i < length; ++ i)
01352 {
01353 for (int j = 0; j < length; ++ j)
01354 {
01355 newmatr. add (i, j, matr. get (selected [i],
01356 selected [j]));
01357 }
01358 }
01359 matr = newmatr;
01360
01361
01362 std::vector<euclidom> newcoefs (length);
01363 for (int i = 0; i < length; ++ i)
01364 newcoefs [i] = coefs [selected [i]];
01365 coefs = newcoefs;
01366 }
01367
01368
01369
01370 euclidom e1, minus1;
01371 e1 = 1;
01372 minus1 = -e1;
01373 if (e1 != minus1)
01374 {
01375 for (int level = 0; level <= toplevel; ++ level)
01376 {
01377
01378 chomp::homology::mmatrix<euclidom> &matr =
01379 indmap [level];
01380
01381
01382 int n = matr. getncols ();
01383 for (int i = 0; i < n; ++ i)
01384 {
01385 const chomp::homology::chain<euclidom> &column =
01386 matr. getcol (i);
01387 if (column. size () != 1)
01388 continue;
01389 if (column. coef (0) != minus1)
01390 continue;
01391 if (column. num (0) <= i)
01392 continue;
01393 matr. multiplyrow (i, minus1);
01394 matr. multiplycol (i, minus1);
01395 }
01396 }
01397 }
01398
01399 return 0;
01400 }
01401
01402 template <class IndexPair, class euclidom>
01403 inline void ConleyIndex<IndexPair,euclidom>::truncate (int newlevel)
01404 {
01405 if ((newlevel >= -1) && (newlevel <= toplevel))
01406 {
01407 toplevel = newlevel;
01408 coef. erase (coef. begin () + toplevel + 1, coef. end ());
01409 }
01410 return;
01411 }
01412
01413 template <class IndexPair, class euclidom>
01414 inline int ConleyIndex<IndexPair,euclidom>::eigenvalues (int level,
01415 std::vector<double> &Re, std::vector<double> &Im,
01416 bool nonzero, bool sorted) const
01417 {
01418
01419 if ((level < 0) || (level > toplevel))
01420 return -1;
01421
01422
01423 const chomp::homology::mmatrix<euclidom> &m = indmap [level];
01424 int fullsize = m. getncols ();
01425 if (fullsize <= 0)
01426 return 0;
01427
01428
01429 int size = fullsize;
01430 const std::vector<euclidom> &coefs = coef [level];
01431 std::vector<int> indices (size);
01432 int current = 0;
01433 for (int i = 0; i < fullsize; ++ i)
01434 {
01435 if (coefs [i]. delta () > 1)
01436 {
01437 indices [i] = -1;
01438 -- size;
01439 }
01440 else
01441 {
01442 indices [i] = current;
01443 ++ current;
01444 }
01445 }
01446 if (size <= 0)
01447 return 0;
01448
01449
01450 char N = 'N';
01451 long int dimension = size;
01452 std::auto_ptr<double> APtr (new double [size * size]);
01453 double *A = APtr. get ();
01454 std::auto_ptr<double> rePtr (new double [size]);
01455 double *re = rePtr. get ();
01456 std::auto_ptr<double> imPtr (new double [size]);
01457 double *im = imPtr. get ();
01458 long int worksize = 3 * size + (2 * size + 128);
01459 std::auto_ptr<double> workPtr (new double [worksize]);
01460 double *work = workPtr. get ();
01461 long int result = 0;
01462
01463
01464 double *ptr = A;
01465 for (int i = 0; i < size; ++ i)
01466 {
01467 for (int j = 0; j < size; ++ j)
01468 {
01469 *(ptr ++) = 0;
01470 }
01471 }
01472 for (int col = 0; col < fullsize; ++ col)
01473 {
01474 int icol = indices [col];
01475 if (icol < 0)
01476 continue;
01477 const chomp::homology::chain<euclidom> c = m. getcol (col);
01478 int len = c. size ();
01479 for (int i = 0; i < len; ++ i)
01480 {
01481 int irow = indices [c. num (i)];
01482 if (irow < 0)
01483 continue;
01484 euclidom e = c. coef (i);
01485 int n = e. delta ();
01486 euclidom e1;
01487 e1 = n;
01488 if (e1 != e)
01489 n = -n;
01490 A [size * irow + icol] = n;
01491 }
01492 }
01493
01494
01495
01496
01497
01498 dgeev_ (&N, &N, &dimension, A, &dimension, re, im,
01499 0, &dimension, 0, &dimension, work, &worksize, &result);
01500
01501
01502 if (result < 0)
01503 throw "Conley Index eigenvalues: LAPACK error.";
01504 else if (result > 0)
01505 throw "The QR algorithm failed in the Conley Index "
01506 "Eigenvalues computation.";
01507
01508
01509 std::vector<ppComplex> values;
01510 const double epsilon = 0.001;
01511 const double threshold = 0.01;
01512 for (int i = 0; i < size; ++ i)
01513 {
01514 re [i] = round (re [i], epsilon, threshold);
01515 im [i] = round (im [i], epsilon, threshold);
01516 if (nonzero && !re [i] && !im [i])
01517 continue;
01518 values. push_back (ppComplex (re [i], im [i]));
01519 }
01520
01521
01522 if (values. size ())
01523 nontrivialindex = 1;
01524
01525
01526 if (sorted)
01527 std::sort (values. begin (), values. end ());
01528
01529
01530 for (std::vector<ppComplex>::const_iterator it = values. begin ();
01531 it != values. end (); ++ it)
01532 {
01533 Re. push_back (it -> re);
01534 Im. push_back (it -> im);
01535 }
01536
01537 return values. size ();
01538 }
01539
01540 template <class IndexPair, class euclidom>
01541 inline bool ConleyIndex<IndexPair,euclidom>::trivial () const
01542 {
01543
01544 if (nontrivialindex >= 0)
01545 return !nontrivialindex;
01546
01547 for (int level = 0; level <= toplevel; ++ level)
01548 {
01549 std::vector<double> Re, Im;
01550 int n = eigenvalues (level, Re, Im, true, false);
01551 if (n)
01552 {
01553 nontrivialindex = 1;
01554 return false;
01555 }
01556
01557
01558 }
01559 nontrivialindex = 0;
01560 return true;
01561 }
01562
01563 template <class IndexPair, class euclidom>
01564 inline std::string ConleyIndex<IndexPair,euclidom>::EigenString (int n) const
01565 {
01566
01567 if (!indmap || (n < 0) || (n > toplevel))
01568 return std::string ();
01569
01570
01571 std::ostringstream out;
01572
01573
01574 std::vector<double> Re, Im;
01575 int count = eigenvalues (n, Re, Im);
01576 if (count > 0)
01577 nontrivialindex = 1;
01578
01579
01580 out << "Eigenvalues " << n << ": (";
01581 if (count >= 0)
01582 {
01583 for (int i = 0; i < count; ++ i)
01584 {
01585 if (i)
01586 out << ", ";
01587 if (Re [i])
01588 {
01589 out << Re [i];
01590 if (Im [i] > 0)
01591 out << "+";
01592 }
01593 if (Im [i])
01594 out << Im [i] << "i";
01595 }
01596 }
01597 else
01598 out << "ERROR";
01599 out << ").";
01600
01601 return out. str ();
01602 }
01603
01604 template <class IndexPair, class euclidom>
01605 inline void ConleyIndex<IndexPair,euclidom>::define (const int *betti,
01606 const chomp::homology::mmatrix<euclidom> *matr, int _toplevel)
01607 {
01608
01609 nontrivialindex = -1;
01610
01611
01612 toplevel = _toplevel;
01613
01614
01615 coef. clear ();
01616 euclidom e;
01617 e = 1;
01618 for (int i = 0; i <= toplevel; ++ i)
01619 {
01620 std::vector<euclidom> b;
01621 for (int j = betti [i]; j > 0; -- j)
01622 b. push_back (e);
01623 coef. push_back (b);
01624 }
01625
01626
01627 if (indmap)
01628 {
01629 delete [] indmap;
01630 indmap = 0;
01631 }
01632 if (toplevel >= 0)
01633 {
01634 indmap = new chomp::homology::mmatrix<euclidom>
01635 [toplevel + 1];
01636 }
01637 for (int level = 0; level <= toplevel; ++ level)
01638 {
01639 indmap [level] = matr [level];
01640 }
01641 return;
01642 }
01643
01644 template <class IndexPair, class euclidom>
01645 inline void ConleyIndex<IndexPair,euclidom>::define (const int *betti,
01646 int _toplevel)
01647 {
01648
01649 chomp::homology::mmatrix<euclidom> *matr = (_toplevel < 0) ? 0 :
01650 new chomp::homology::mmatrix<euclidom> [_toplevel + 1];
01651 for (int level = 0; level <= _toplevel; ++ level)
01652 {
01653 if (betti [level] > 0)
01654 matr [level]. identity (betti [level]);
01655 }
01656
01657
01658 this -> define (betti, matr, _toplevel);
01659
01660
01661 if (matr)
01662 delete [] matr;
01663 return;
01664 }
01665
01666
01667
01668 template <class IndexPair, class euclidom>
01669 std::ostream &operator << (std::ostream &out,
01670 const ConleyIndex<IndexPair,euclidom> &c)
01671 {
01672
01673 out << c. toplevel << " ";
01674 if (c. toplevel < 0)
01675 return out;
01676
01677
01678 for (int i = 0; i <= c. toplevel; ++ i)
01679 {
01680 int size = c. coef [i]. size ();
01681 out << size << " ";
01682 for (int j = 0; j < size; ++ j)
01683 out << c. coef [i] [j] << " ";
01684 }
01685
01686
01687 for (int i = 0; i <= c. toplevel; ++ i)
01688 {
01689 const chomp::homology::mmatrix<euclidom> &m = c. indmap [i];
01690 out << m. getnrows () << " " << m. getncols () << " ";
01691 for (int j = 0; j < m. getncols (); ++ j)
01692 {
01693 const chomp::homology::chain<euclidom> &col =
01694 m. getcol (j);
01695 out << col. size () << " ";
01696 for (int k = 0; k < col. size (); ++ k)
01697 {
01698 out << col. num (k) << " ";
01699 out << col. coef (k) << " ";
01700 }
01701 }
01702 }
01703
01704 return out;
01705 }
01706
01707 template <class IndexPair, class euclidom>
01708 std::istream &operator >> (std::istream &in,
01709 ConleyIndex<IndexPair,euclidom> &c)
01710 {
01711
01712 c. nontrivialindex = -1;
01713 if (c. indmap)
01714 {
01715 delete [] c. indmap;
01716 c. indmap = 0;
01717 }
01718 c. coef. clear ();
01719
01720
01721 in >> c. toplevel;
01722 if (c. toplevel < 0)
01723 return in;
01724
01725
01726 for (int i = 0; i <= c. toplevel; ++ i)
01727 {
01728 int size = -1;
01729 in >> size;
01730 if (size < 0)
01731 throw "Cannot decode the Conley index from input.";
01732 std::vector<euclidom> coef;
01733 for (int j = 0; j < size; ++ j)
01734 {
01735 euclidom e;
01736 e = 0;
01737 in >> e;
01738 if (e. delta () <= 0)
01739 throw "Wrong coefficient in the "
01740 "Conley index from input.";
01741 coef. push_back (e);
01742 }
01743 c. coef. push_back (coef);
01744 }
01745
01746
01747 if (c. toplevel >= 0)
01748 c. indmap = new chomp::homology::mmatrix<euclidom>
01749 [c. toplevel + 1];
01750 for (int i = 0; i <= c. toplevel; ++ i)
01751 {
01752 chomp::homology::mmatrix<euclidom> &m = c. indmap [i];
01753 int nrows = 0, ncols = 0;
01754 in >> nrows >> ncols;
01755 if ((nrows < 0) || (ncols < 0))
01756 throw "Wrong matrix size in the Conley index "
01757 "from input.";
01758 if ((nrows > 0) && (ncols > 0))
01759 m. define (nrows, ncols);
01760 for (int j = 0; j < ncols; ++ j)
01761 {
01762 int length = -1;
01763 in >> length;
01764 if (length < 0)
01765 throw "Negative column length in the "
01766 "Conley index from input.";
01767 for (int k = 0; k < length; ++ k)
01768 {
01769 int num = -1;
01770 in >> num;
01771 if ((num < 0) || (num >= nrows))
01772 throw "Wrong row number in the "
01773 "Conley index from input.";
01774 euclidom e;
01775 e = 0;
01776 in >> e;
01777 if (e. delta () <= 0)
01778 throw "Wrong matrix entry in the "
01779 "Conley index from input.";
01780 m. add (num, j, e);
01781 }
01782 }
01783 }
01784
01785 return in;
01786 }
01787
01788
01789 #endif // _CMGRAPHS_CONINDEX_H_
01790
01791