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
00034 #ifndef _CMGRAPHS_COORD_H_
00035 #define _CMGRAPHS_COORD_H_
00036
00037
00038
00039 #include <string>
00040 #include <iostream>
00041 #include <fstream>
00042 #include <cctype>
00043
00044
00045 #include "chomp/system/config.h"
00046 #include "chomp/system/textfile.h"
00047 #include "chomp/cubes/cube.h"
00048 #include "chomp/multiwork/mw.h"
00049
00050
00051 #include "config.h"
00052 #include "confinfo.h"
00053 #include "typedefs.h"
00054 #include "utils.h"
00055 #include "dataconv.h"
00056 #include "matcharr.h"
00057 #include "dotgraph.h"
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 class Coordinator: public chomp::multiwork::mwCoordinator
00069 {
00070 public:
00071
00072 Coordinator (const char *_interFileName, const char *_graphsFileName,
00073 const char *_finalPrefix, const char *_sharePrefix,
00074 const char *_phaseSpacePrefix, bool _fullPhaseSpace,
00075 int _skipIndices, int _nWorkers);
00076
00077
00078 ~Coordinator ();
00079
00080 private:
00081
00082 int Prepare (chomp::multiwork::mwData &data);
00083
00084
00085 int Accept (chomp::multiwork::mwData &data);
00086
00087
00088 int Reject (chomp::multiwork::mwData &data);
00089
00090
00091
00092
00093
00094
00095
00096 private:
00097
00098
00099 struct datapack
00100 {
00101
00102 datapack () {}
00103
00104
00105 datapack (int _num, const parCube &_box):
00106 num (_num), box (_box) {}
00107
00108
00109
00110
00111
00112
00113 int num;
00114
00115
00116 parCube box;
00117
00118 };
00119
00120
00121 private:
00122
00123 void readPreviousResults (const char *filename);
00124
00125
00126 std::ofstream interFile;
00127
00128
00129 std::ofstream graphsFile;
00130
00131
00132 int currentCache;
00133
00134
00135 int maxCache;
00136
00137
00138 parCoord cacheCoord [paramDim];
00139
00140
00141 int current;
00142
00143
00144
00145 int maxCurrent;
00146
00147
00148 chomp::homology::multitable<datapack> sent;
00149
00150
00151 int sentlen;
00152
00153
00154
00155 int skipIndices;
00156
00157
00158 std::string finalPrefix;
00159
00160
00161 std::string sharePrefix;
00162
00163
00164
00165 std::string phaseSpacePrefix;
00166
00167
00168
00169 bool fullPhaseSpace;
00170
00171
00172
00173 std::vector<parCoord> subCoords [paramDim];
00174
00175
00176 parCoord zeroIter [paramDim];
00177
00178
00179 parCoord maxIter [paramDim];
00180
00181
00182 parRect *rectIterator;
00183
00184
00185 parCoord parityBits [paramDim];
00186
00187
00188 bool allSent;
00189
00190
00191 MatchArray<parCoord,int> matchArray;
00192
00193
00194 int morseDecComputed;
00195
00196
00197 int morseDecReused;
00198
00199
00200
00201 parCubes wrongIndexBoxes;
00202
00203
00204
00205 parCubes graphsWritten;
00206
00207
00208
00209 parCubes previousBoxes;
00210
00211
00212
00213 chomp::homology::multitable<std::vector<int> > wrongIndices;
00214
00215
00216 spcCoord coordLeftMin [spaceDim];
00217
00218
00219 spcCoord coordRightMax [spaceDim];
00220
00221
00222 int maxImgDiam;
00223
00224
00225 int maxImgVol;
00226
00227 };
00228
00229
00230
00231 inline Coordinator::Coordinator (const char *_interFileName,
00232 const char *_graphsFileName,
00233 const char *_finalPrefix, const char *_sharePrefix,
00234 const char *_phaseSpacePrefix, bool _fullPhaseSpace,
00235 int _skipIndices, int _nWorkers):
00236 currentCache (0), maxCache (0),
00237 current (0), maxCurrent (0), sentlen (0),
00238 skipIndices (_skipIndices), fullPhaseSpace (_fullPhaseSpace),
00239 rectIterator (0), allSent (false),
00240 matchArray (paramDim, paramSubdiv),
00241 morseDecComputed (0), morseDecReused (0),
00242 maxImgDiam (0), maxImgVol (0)
00243 {
00244 using chomp::homology::sout;
00245
00246
00247 if (_sharePrefix && *_sharePrefix)
00248 sharePrefix = _sharePrefix;
00249
00250
00251 if (_phaseSpacePrefix && *_phaseSpacePrefix)
00252 phaseSpacePrefix = _phaseSpacePrefix;
00253
00254
00255 if (!_interFileName || !*_interFileName)
00256 {
00257 sout << "WARNING: No file name for intermediate results "
00258 "has been provided.\n"
00259 " It will not be possible to restart "
00260 "the computations if they are interrupted.\n";
00261 }
00262
00263
00264 if (!_graphsFileName || !*_graphsFileName)
00265 {
00266 sout << "WARNING: No file name for saving the Conley-Morse "
00267 "graphs has been provided.\n"
00268 " The computed Conley-Morse graphs "
00269 "Will be discarded.\n";
00270 }
00271
00272
00273
00274 if (_finalPrefix && *_finalPrefix)
00275 finalPrefix = _finalPrefix;
00276 else
00277 throw "No file name prefix provided for the results.";
00278
00279
00280 if (_interFileName && *_interFileName)
00281 this -> readPreviousResults (_interFileName);
00282
00283
00284 rectIterator = subRectangles (zeroIter, maxIter,
00285 subCoords, _nWorkers);
00286
00287
00288 for (int i = 0; i < paramDim; ++ i)
00289 parityBits [i] = 0;
00290
00291
00292 maxCurrent = 1;
00293 for (int i = 0; i < paramDim; ++ i)
00294 maxCurrent *= maxIter [i];
00295
00296
00297 if (_graphsFileName && *_graphsFileName)
00298 {
00299 graphsFile. open (_graphsFileName,
00300 std::ios::out | std::ios::app);
00301 graphsFile << "; --- Conley-Morse graphs ---\n";
00302 graphsFile << std::flush;
00303 }
00304
00305
00306 if (_interFileName && *_interFileName)
00307 {
00308 interFile. open (_interFileName,
00309 std::ios::out | std::ios::app);
00310 interFile << "; Started on " <<
00311 chomp::homology::currenttime () << ";\n";
00312 showConfigInfo (interFile, "; ", maxIter);
00313 interFile << std::flush;
00314 }
00315
00316
00317 for (int i = 0; i < spaceDim; ++ i)
00318 {
00319 coordLeftMin [i] = 1 << finalDepth;
00320 coordRightMax [i] = 0;
00321 }
00322
00323
00324 if (!sharePrefix. empty ())
00325 {
00326 for (int i = 0; i < paramDim; ++ i)
00327 cacheCoord [i] = 0;
00328 maxCache = 1;
00329 for (int i = 0; i < paramDim; ++ i)
00330 maxCache *= paramSubdiv [i];
00331 }
00332
00333 return;
00334 }
00335
00336 inline void Coordinator::readPreviousResults (const char *filename)
00337 {
00338 using chomp::homology::sout;
00339 using chomp::homology::ignoreline;
00340 using chomp::homology::ignorecomments;
00341
00342 std::ifstream in (filename);
00343 if (!in)
00344 {
00345 sout << "Note: Could not open the results file. "
00346 "Any previous results will be ignored.\n";
00347 return;
00348 }
00349
00350 int countClasses = 0;
00351 int countBoxes = 0;
00352 ignorecomments (in);
00353 while (!in. eof ())
00354 {
00355
00356 if (in. peek () == 'E')
00357 {
00358
00359 in. get ();
00360 ignorecomments (in);
00361
00362
00363 if (std::isdigit (in. peek ()))
00364 {
00365 int nCubes = 0;
00366 in >> nCubes;
00367 ignorecomments (in);
00368 }
00369
00370
00371 parCube firstCube;
00372 in >> firstCube;
00373 parCoord firstCoord [paramDim];
00374 firstCube. coord (firstCoord);
00375 ignorecomments (in);
00376
00377
00378 while (in. peek () == '(')
00379 {
00380 parCube otherCube;
00381 in >> otherCube;
00382 parCoord otherCoord [paramDim];
00383 otherCube. coord (otherCoord);
00384 matchArray. join (firstCoord, otherCoord);
00385 ignorecomments (in);
00386 }
00387
00388
00389 ++ countClasses;
00390 }
00391
00392
00393 else if (in. peek () == '*')
00394 {
00395
00396 in. get ();
00397 ignorecomments (in);
00398
00399
00400 if (std::isdigit (in. peek ()))
00401 {
00402 int num = 0;
00403 in >> num;
00404 ignorecomments (in);
00405 }
00406
00407
00408 parCube paramBox;
00409 in >> paramBox;
00410 previousBoxes. add (paramBox);
00411 ignorecomments (in);
00412
00413
00414 ++ countBoxes;
00415 }
00416
00417
00418 else
00419 {
00420 ignoreline (in);
00421 ignorecomments (in);
00422 }
00423 }
00424
00425 chomp::homology::sout << countBoxes << " previously computed "
00426 "parameter ranges read from a file.\n";
00427 maxCurrent -= countBoxes;
00428 chomp::homology::sout << countClasses << " previously computed "
00429 "equivalence classes processed.\n";
00430 return;
00431 }
00432
00433 inline Coordinator::~Coordinator ()
00434 {
00435 if (rectIterator)
00436 delete rectIterator;
00437 interFile << "; Finished on " << chomp::homology::currenttime ();
00438 interFile. close ();
00439 return;
00440 }
00441
00442 inline int Coordinator::Prepare (chomp::multiwork::mwData &data)
00443 {
00444 using chomp::homology::sout;
00445 using chomp::homology::sbug;
00446
00447
00448 if (!currentCache && maxCache)
00449 sout << "=== PHASE 1: Computation of Conley indices ===\n";
00450
00451
00452 while (currentCache < maxCache)
00453 {
00454
00455 std::string cacheFileName (sharePrefix +
00456 coord2str (cacheCoord, paramDim) + ".ind");
00457 if (!fileExists (cacheFileName. c_str ()))
00458 break;
00459
00460
00461 if (!phaseSpacePrefix. empty ())
00462 {
00463 std::string pictureFileName = phaseSpacePrefix +
00464 coord2str (cacheCoord, paramDim) + ".png";
00465 if (!fileExists (pictureFileName. c_str ()))
00466 break;
00467 }
00468
00469
00470 for (int i = 0; i < paramDim; ++ i)
00471 {
00472 if (++ (cacheCoord [i]) < paramSubdiv [i])
00473 break;
00474 cacheCoord [i] = 0;
00475 }
00476 ++ currentCache;
00477
00478
00479 if (currentCache == maxCache)
00480 {
00481 sout << "=== PHASE 2: Continuation of Morse "
00482 "decompositions ===\n";
00483 }
00484 }
00485
00486
00487 bool cacheToSend = (currentCache < maxCache);
00488
00489
00490 const parCoord *coord = 0;
00491 while (!cacheToSend && !allSent)
00492 {
00493
00494 coord = rectIterator -> get ();
00495
00496
00497 if (!coord)
00498 {
00499
00500 int nBit = 0;
00501 while ((nBit < paramDim) && (parityBits [nBit] == 1))
00502 parityBits [nBit ++] = 0;
00503
00504
00505 if (nBit == paramDim)
00506 {
00507 allSent = true;
00508 break;
00509 }
00510
00511
00512 parityBits [nBit] = 1;
00513
00514
00515 coord = rectIterator -> get ();
00516 }
00517
00518
00519 bool parityOk = true;
00520 for (int i = 0; i < paramDim; ++ i)
00521 {
00522 if (parityBits [i] && (coord [i] & 1))
00523 continue;
00524 if (!parityBits [i] && !(coord [i] & 1))
00525 continue;
00526 parityOk = false;
00527 break;
00528 }
00529
00530
00531 if (parityOk && !previousBoxes. empty () &&
00532 previousBoxes. check (parCube (coord, paramDim)))
00533 {
00534 continue;
00535 }
00536
00537
00538 if (parityOk)
00539 break;
00540 }
00541
00542
00543 if (allSent && !sentlen && !finalPrefix. empty ())
00544 {
00545 sout << "================================\n";
00546
00547
00548 if (!wrongIndexBoxes. empty ())
00549 {
00550 sout << "\n*** WARNING: Some Conley indices at " <<
00551 wrongIndexBoxes. size () <<
00552 " parameters were not computed\n"
00553 "*** because of lack of isolation.\n\n";
00554 std::ofstream bad ((finalPrefix + ".bad"). c_str ());
00555 bad << "; Parameter boxes for which at least one "
00556 "Conley index could not be computed:\n";
00557 bad << wrongIndexBoxes;
00558 }
00559
00560
00561 int volume = 1;
00562 for (int i = 0; i < paramDim; ++ i)
00563 volume *= paramSubdiv [i];
00564 int percent = static_cast<int>
00565 (morseDecComputed * 100.0 / volume);
00566 sout << morseDecComputed << " out of " <<
00567 volume << " Morse decomps computed (" <<
00568 percent << "%) and " << morseDecReused <<
00569 " reused.\n";
00570
00571
00572 if (coordLeftMin [0] < coordRightMax [0])
00573 {
00574 sout << "The computed Morse sets are in ";
00575 for (int i = 0; i < spaceDim; ++ i)
00576 {
00577 sout << (i ? " x [" : "[") <<
00578 coordLeftMin [i] << "," <<
00579 coordRightMax [i] << "]";
00580 }
00581 sout << ".\n";
00582 }
00583
00584
00585 sout << "Max img diam = " << maxImgDiam <<
00586 ", max img vol = " << maxImgVol << ".\n";
00587
00588
00589 sout << "Saving the continuation classes...\n";
00590 matchArray. saveSets (finalPrefix. c_str ());
00591 }
00592
00593
00594 if (allSent)
00595 return chomp::multiwork::mwNoData;
00596
00597
00598 parCube dataBox (cacheToSend ? cacheCoord : coord, paramDim);
00599 int dataNumber = cacheToSend ? -(currentCache + 1) : current;
00600 sent [sentlen ++] = datapack (dataNumber, dataBox);
00601
00602
00603 int leftCoords [paramDim], rightCoords [paramDim];
00604 for (int i = 0; i < paramDim; ++ i)
00605 {
00606 if (cacheToSend)
00607 {
00608 leftCoords [i] = cacheCoord [i];
00609 rightCoords [i] = cacheCoord [i] + 1;
00610 }
00611 else
00612 {
00613
00614
00615 int left = subCoords [i] [coord [i]];
00616 int right = subCoords [i] [coord [i] + 1];
00617 if (right < paramSubdiv [i])
00618 ++ right;
00619 leftCoords [i] = left;
00620 rightCoords [i] = right;
00621 }
00622 }
00623
00624
00625 data. Reset ();
00626 data << dataNumber;
00627 data << paramDim;
00628 for (int i = 0; i < paramDim; ++ i)
00629 data << leftCoords [i] << rightCoords [i];
00630 data << skipIndices;
00631 data << sharePrefix;
00632 data << phaseSpacePrefix;
00633 data << fullPhaseSpace;
00634 data << controlNumber;
00635
00636
00637 if (!cacheToSend)
00638 {
00639 interFile << "+ " << dataNumber << " " << dataBox << "\n" <<
00640 std::flush;
00641 }
00642
00643
00644
00645 sout << "Sending " << dataNumber << " " << dataBox;
00646 if (!cacheToSend)
00647 {
00648 for (int i = 0; i < paramDim; ++ i)
00649 {
00650 sout << (i ? " x [" : ": [") << leftCoords [i] <<
00651 "," << rightCoords [i] << "]";
00652 }
00653 }
00654 int countSent = cacheToSend ? currentCache : current;
00655 int maxToSend = cacheToSend ? maxCache : maxCurrent;
00656 sout << ", " << (100 * (countSent + 1) /
00657 (maxToSend ? maxToSend : 1)) << "% sent.\n";
00658
00659 if (cacheToSend)
00660 {
00661
00662 for (int i = 0; i < paramDim; ++ i)
00663 {
00664 if (++ (cacheCoord [i]) < paramSubdiv [i])
00665 break;
00666 cacheCoord [i] = 0;
00667 }
00668 ++ currentCache;
00669
00670
00671 if (currentCache == maxCache)
00672 {
00673 sout << "=== PHASE 2: Continuation of Morse "
00674 "decompositions ===\n";
00675 }
00676 }
00677 else
00678 {
00679 ++ current;
00680 }
00681
00682 return chomp::multiwork::mwOk;
00683 }
00684
00685 inline int Coordinator::Accept (chomp::multiwork::mwData &data)
00686 {
00687 using chomp::homology::sout;
00688 using chomp::homology::sbug;
00689
00690
00691 int dataNumber = 0;
00692 data >> dataNumber;
00693
00694
00695
00696 int countSent = sentlen;
00697 int countPrepared = (dataNumber >= 0) ? current : currentCache;
00698 int maxPrepared = (dataNumber >= 0) ? maxCurrent : maxCache;
00699 for (int i = 0; i < sentlen; ++ i)
00700 {
00701 if ((dataNumber >= 0) && (sent [i]. num < 0))
00702 -- countSent;
00703 else if ((dataNumber < 0) && (sent [i]. num >= 0))
00704 -- countSent;
00705 }
00706 sout << "Receiving " << dataNumber << ", " <<
00707 (100 * (countPrepared - countSent + 1) /
00708 (maxPrepared ? maxPrepared : 1)) << "% completed.\n";
00709
00710
00711 int pos = 0;
00712 while ((pos < sentlen) && (sent [pos]. num != dataNumber))
00713 ++ pos;
00714 if (pos >= sentlen)
00715 throw "Wrong data chunk number returned by a worker.";
00716
00717
00718 if (dataNumber >= 0)
00719 {
00720 interFile << "* " << dataNumber << " " <<
00721 sent [pos]. box << "\n";
00722 }
00723
00724
00725 double processingTime = 0;
00726 data >> processingTime;
00727
00728
00729 std::vector<std::vector<int> > localWrongIndices;
00730 data >> localWrongIndices;
00731
00732
00733
00734 std::vector<std::vector<int> > skippedIndices;
00735 data >> skippedIndices;
00736
00737
00738 std::vector<std::vector<int> > attractors;
00739 data >> attractors;
00740
00741
00742 spcCube cubeLeftMin;
00743 spcCube cubeRightMax;
00744 data >> cubeLeftMin;
00745 data >> cubeRightMax;
00746 spcCoord localLeftMin [spaceDim];
00747 spcCoord localRightMax [spaceDim];
00748 cubeLeftMin. coord (localLeftMin);
00749 cubeRightMax. coord (localRightMax);
00750 for (int i = 0; i < spaceDim; ++ i)
00751 {
00752 if (coordLeftMin [i] > localLeftMin [i])
00753 coordLeftMin [i] = localLeftMin [i];
00754 if (coordRightMax [i] < localRightMax [i])
00755 coordRightMax [i] = localRightMax [i];
00756 }
00757
00758
00759 int countBoxes = 0;
00760 data >> countBoxes;
00761
00762
00763 bool graphsOutput = false;
00764 parCubes paramBoxes;
00765 for (int curNumber = 0; curNumber < countBoxes; ++ curNumber)
00766 {
00767
00768 parCube paramBox;
00769 data >> paramBox;
00770 paramBoxes. add (paramBox);
00771 if (paramBoxes. size () <= curNumber)
00772 throw "Repeated box found in the results.";
00773
00774
00775 double timeUsed = 0;
00776 data >> timeUsed;
00777
00778
00779 bool wasComputed = false;
00780 data >> wasComputed;
00781 if (wasComputed)
00782 ++ morseDecComputed;
00783 else
00784 ++ morseDecReused;
00785
00786
00787 chomp::homology::diGraph<> morseGraph;
00788 data >> morseGraph;
00789
00790
00791 int nSets = morseGraph. countVertices ();
00792 std::vector<int> sizes (nSets);
00793 for (int n = 0; n < nSets; ++ n)
00794 data >> sizes [n];
00795
00796
00797 if (!localWrongIndices [curNumber]. empty ())
00798 {
00799 wrongIndices [wrongIndexBoxes. size ()] =
00800 localWrongIndices [curNumber];
00801 wrongIndexBoxes. add (paramBox);
00802 }
00803
00804
00805 std::vector<theConleyIndexType> indices (nSets);
00806 std::vector<IndexEigenValues> eigenValues (nSets);
00807 for (int n = 0; n < nSets; ++ n)
00808 {
00809
00810 data >> indices [n];
00811
00812
00813 data >> eigenValues [n];
00814 }
00815
00816
00817 if (!graphsWritten. check (paramBox))
00818 {
00819 graphsFile << paramBox << " ";
00820 writeDotGraph (graphsFile, morseGraph, sizes,
00821 indices, eigenValues,
00822 localWrongIndices [curNumber],
00823 skippedIndices [curNumber],
00824 attractors [curNumber]);
00825 graphsFile << "\n";
00826 graphsWritten. add (paramBox);
00827 graphsOutput = true;
00828 }
00829 }
00830 if (paramBoxes. empty ())
00831 {
00832 sbug << "Results for no boxes accepted.\n";
00833 }
00834 else if (paramBoxes. size () == 1)
00835 {
00836 sbug << "Results for one box (processed in " <<
00837 processingTime << " sec) accepted.\n";
00838 }
00839 else
00840 {
00841 sbug << "Results for " << paramBoxes. size () << " boxes "
00842 "(processed in " << processingTime <<
00843 " sec) accepted.\n";
00844 }
00845
00846
00847 std::vector<std::vector<parCube> > matchClasses;
00848 data >> matchClasses;
00849 int nClasses = matchClasses. size ();
00850 for (int n = 0; n < nClasses; ++ n)
00851 {
00852
00853 const std::vector<parCube> &theClass = matchClasses [n];
00854 int nBoxes = theClass. size ();
00855 if (nBoxes < 2)
00856 continue;
00857 interFile << "E " << nBoxes;
00858
00859
00860 parCoord coordZero [paramDim];
00861 theClass [0]. coord (coordZero);
00862 interFile << " " << theClass [0];
00863
00864
00865 for (int i = 1; i < nBoxes; ++ i)
00866 {
00867 interFile << " " << theClass [i];
00868 parCoord coordBox [paramDim];
00869 theClass [i]. coord (coordBox);
00870 matchArray. join (coordZero, coordBox);
00871 }
00872 interFile << "\n";
00873 }
00874
00875
00876 int localMaxImgDiam = 0;
00877 int localMaxImgVol = 0;
00878 data >> localMaxImgDiam;
00879 data >> localMaxImgVol;
00880 if (maxImgDiam < localMaxImgDiam)
00881 maxImgDiam = localMaxImgDiam;
00882 if (maxImgVol < localMaxImgVol)
00883 maxImgVol = localMaxImgVol;
00884
00885
00886 -- sentlen;
00887 if (pos != sentlen)
00888 sent [pos] = sent [sentlen];
00889
00890
00891
00892
00893
00894
00895 if (dataNumber >= 0)
00896 interFile << std::flush;
00897 if (graphsOutput)
00898 graphsFile << std::flush;
00899 return chomp::multiwork::mwOk;
00900 }
00901
00902 inline int Coordinator::Reject (chomp::multiwork::mwData &)
00903 {
00904 using chomp::homology::sout;
00905 sout << "WARNING: Data rejected by a worker.\n";
00906 return chomp::multiwork::mwError;
00907 }
00908
00909
00910 #endif // _CMGRAPHS_COORD_H_
00911