coord.h

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////////////
00002 ///
00003 /// @file coord.h
00004 ///
00005 /// The coordinator class for the Conley-Morse graphs computation program.
00006 /// This file contains the definition of the coordinator class which prepares
00007 /// data for workers (chunks of the parameter range) and collects results
00008 /// of their computations.
00009 ///
00010 /// @author Pawel Pilarczyk
00011 ///
00012 /////////////////////////////////////////////////////////////////////////////
00013 
00014 // Copyright (C) 1997-2008 by Pawel Pilarczyk.
00015 //
00016 // This file is part of my research software package.  This is free software;
00017 // you can redistribute it and/or modify it under the terms of the GNU
00018 // General Public License as published by the Free Software Foundation;
00019 // either version 2 of the License, or (at your option) any later version.
00020 //
00021 // This software is distributed in the hope that it will be useful,
00022 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00023 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024 // GNU General Public License for more details.
00025 //
00026 // You should have received a copy of the GNU General Public License along
00027 // with this software; see the file "license.txt".  If not, write to the
00028 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00029 // MA 02111-1307, USA.
00030 
00031 // Started on February 11, 2008. Last revision: April 16, 2008.
00032 
00033 
00034 #ifndef _CMGRAPHS_COORD_H_
00035 #define _CMGRAPHS_COORD_H_
00036 
00037 
00038 // include some standard C++ header files
00039 #include <string>
00040 #include <iostream>
00041 #include <fstream>
00042 #include <cctype>
00043 
00044 // include selected header files from the CHomP library
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 // include local header files
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 // ------------- the coordinator class --------------
00062 // --------------------------------------------------
00063 
00064 /// The coordinator class which prepares chunks of parameter space
00065 /// to be processed by workers, and then incorporates the results
00066 /// of the computations into the final picture, and also saves the results
00067 /// to a log file.
00068 class Coordinator: public chomp::multiwork::mwCoordinator
00069 {
00070 public:
00071         /// The complete constructor of a coordinator.
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         /// The destructor.
00078         ~Coordinator ();
00079 
00080 private:
00081         /// A function for preparing data by the coordinator.
00082         int Prepare (chomp::multiwork::mwData &data);
00083 
00084         /// A function for accepting results by the coordinator.
00085         int Accept (chomp::multiwork::mwData &data);
00086 
00087         /// A function for taking rejected data by the coordinator.
00088         int Reject (chomp::multiwork::mwData &data);
00089 
00090         // The copy constructor is not allowed.
00091 //      Coordinator (const Coordinator &) {return;}
00092 
00093         // The assignment operator is not allowed.
00094 //      Coordinator &operator = (const Coordinator &) {return *this;}
00095 
00096 private:
00097         /// This is an auxiliary class whose objects store the information
00098         /// on the data chunks sent to workers.
00099         struct datapack
00100         {
00101                 /// The default constructor of an uninitialized data pack.
00102                 datapack () {}
00103 
00104                 /// A nice constructor which initializes all the data.
00105                 datapack (int _num, const parCube &_box):
00106                         num (_num), box (_box) {}
00107 
00108                 // the default copy constructor and operator = are good
00109 
00110                 // no destructor is necessary
00111 
00112                 /// The number of the data pack.
00113                 int num;
00114 
00115                 /// The cube (with respect to the iterator) sent to a worker.
00116                 parCube box;
00117         
00118         }; /* struct datapack */
00119 
00120 
00121 private:
00122         /// A procedure for reading the previously computed results.
00123         void readPreviousResults (const char *filename);
00124 
00125         /// A file to append the results to.
00126         std::ofstream interFile;
00127 
00128         /// A file to append the computed Conley-Morse graphs to.
00129         std::ofstream graphsFile;
00130 
00131         /// The current number of data pack sent for pre-caching indices.
00132         int currentCache;
00133 
00134         /// The number of indices to pre-cache.
00135         int maxCache;
00136 
00137         /// The coordinates of a box to send for pre-caching indices.
00138         parCoord cacheCoord [paramDim];
00139 
00140         /// The current number of data pack to prepare by the coordinator.
00141         int current;
00142 
00143         /// The number of parameter regions which are to be processed
00144         /// in this run of the program.
00145         int maxCurrent;
00146 
00147         /// The data packs sent for processing to workers.
00148         chomp::homology::multitable<datapack> sent;
00149 
00150         /// The number of data packs currently being processed by workers.
00151         int sentlen;
00152 
00153         /// The minimal size of a Morse set for which the indices should not
00154         /// be computed. Zero to compute all the Conley indices.
00155         int skipIndices;
00156 
00157         /// The file name prefix for saving the final result.
00158         std::string finalPrefix;
00159 
00160         /// The file name prefix for saving Morse sets by workers.
00161         std::string sharePrefix;
00162 
00163         /// The file name prefix for saving the phase space pictures
00164         /// of Morse decompositions.
00165         std::string phaseSpacePrefix;
00166 
00167         /// Should the full phase space be taken for plotting the pictures
00168         /// of Morse sets?
00169         bool fullPhaseSpace;
00170 
00171         /// The coordinates for lower (and upper) ends of rectangular regions
00172         /// in each direction.
00173         std::vector<parCoord> subCoords [paramDim];
00174 
00175         /// The minimal corner of the rectangle to iterate (zero coords).
00176         parCoord zeroIter [paramDim];
00177 
00178         /// The numbers of rectangular regions in each direction to iterate.
00179         parCoord maxIter [paramDim];
00180 
00181         /// A rectangle which iterates the rectangular sets to send.
00182         parRect *rectIterator;
00183 
00184         /// Parity bits of which rectangles are to be sent to workers.
00185         parCoord parityBits [paramDim];
00186 
00187         /// Have all the rectangular regions already been sent?
00188         bool allSent;
00189 
00190         /// The array of matching between parameter boxes.
00191         MatchArray<parCoord,int> matchArray;
00192 
00193         /// The total number of computed Morse decopositions.
00194         int morseDecComputed;
00195 
00196         /// The total number of re-used Morse decompositions.
00197         int morseDecReused;
00198 
00199         /// The parameter boxes for which wrong Conley indices
00200         /// were computed by workers.
00201         parCubes wrongIndexBoxes;
00202 
00203         /// The parameter boxes for which the Conley-Morse graph
00204         /// has already been written to the corresponding file.
00205         parCubes graphsWritten;
00206 
00207         /// The boxes representing parameter ranges which have already been
00208         /// processed in the previous run of the coordinator.
00209         parCubes previousBoxes;
00210 
00211         /// The lists of Morse set numbers for which the wrong Conley indices
00212         /// appeared.
00213         chomp::homology::multitable<std::vector<int> > wrongIndices;
00214 
00215         /// The left coordinates of a box that contains all the Morse sets.
00216         spcCoord coordLeftMin [spaceDim];
00217 
00218         /// The right coordinates of a box that contains all the Morse sets.
00219         spcCoord coordRightMax [spaceDim];
00220 
00221         /// The maximal image diameter encountered by the workers.
00222         int maxImgDiam;
00223 
00224         /// The maximal image volume encountered by the workers.
00225         int maxImgVol;
00226 
00227 }; /* class Coordinator */
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         // remember the prefix for saving Morse sets
00247         if (_sharePrefix && *_sharePrefix)
00248                 sharePrefix = _sharePrefix;
00249 
00250         // remember the prefix for saving pictures of Morse decompositions
00251         if (_phaseSpacePrefix && *_phaseSpacePrefix)
00252                 phaseSpacePrefix = _phaseSpacePrefix;
00253 
00254         // display a warning if no intermediate file name is provided
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         // display a warning if no file name for saving graphs was given
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         // remember the prefix for file names to which the final result
00273         // will be saved
00274         if (_finalPrefix && *_finalPrefix)
00275                 finalPrefix = _finalPrefix;
00276         else
00277                 throw "No file name prefix provided for the results.";
00278 
00279         // read the previously computed results of the computations
00280         if (_interFileName && *_interFileName)
00281                 this -> readPreviousResults (_interFileName);
00282 
00283         // prepare a rectangle for iterating the rectangular regions
00284         rectIterator = subRectangles (zeroIter, maxIter,
00285                 subCoords, _nWorkers);
00286 
00287         // prepare the parity bits
00288         for (int i = 0; i < paramDim; ++ i)
00289                 parityBits [i] = 0;
00290 
00291         // compute the number of regions which will be sent for processing
00292         maxCurrent = 1;
00293         for (int i = 0; i < paramDim; ++ i)
00294                 maxCurrent *= maxIter [i];
00295 
00296         // open the graphs file for appending
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         // open the results file for appending
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         // initialize the coordinate ranges
00317         for (int i = 0; i < spaceDim; ++ i)
00318         {
00319                 coordLeftMin [i] = 1 << finalDepth;
00320                 coordRightMax [i] = 0;
00321         }
00322 
00323         // initialize the data for pre-computation of cached Conley indices
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 } /* Coordinator::Coordinator */
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                 // add an equivalence class to the array of connections
00356                 if (in. peek () == 'E')
00357                 {
00358                         // read the letter indicating an equivalence class
00359                         in. get ();
00360                         ignorecomments (in);
00361 
00362                         // read and ignore the number of cubes in the class
00363                         if (std::isdigit (in. peek ()))
00364                         {
00365                                 int nCubes = 0;
00366                                 in >> nCubes;
00367                                 ignorecomments (in);
00368                         }
00369 
00370                         // read the first cube in the equivalence class
00371                         parCube firstCube;
00372                         in >> firstCube;
00373                         parCoord firstCoord [paramDim];
00374                         firstCube. coord (firstCoord);
00375                         ignorecomments (in);
00376 
00377                         // read all the remaining cubes
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                         // update the class counter
00389                         ++ countClasses;
00390                 }
00391 
00392                 // add a box to the list of previously processed boxes
00393                 else if (in. peek () == '*')
00394                 {
00395                         // read the asterisk
00396                         in. get ();
00397                         ignorecomments (in);
00398 
00399                         // read and ignore the datapack number
00400                         if (std::isdigit (in. peek ()))
00401                         {
00402                                 int num = 0;
00403                                 in >> num;
00404                                 ignorecomments (in);
00405                         }
00406 
00407                         // read the cube which has already been processed
00408                         parCube paramBox;
00409                         in >> paramBox;
00410                         previousBoxes. add (paramBox);
00411                         ignorecomments (in);
00412 
00413                         // update the box counter
00414                         ++ countBoxes;
00415                 }
00416 
00417                 // ignore the line if it is not understood
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 } /* Coordinator::readPreviousResults */
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 } /* Coordinator::~Coordinator */
00441 
00442 inline int Coordinator::Prepare (chomp::multiwork::mwData &data)
00443 {
00444         using chomp::homology::sout;
00445         using chomp::homology::sbug;
00446 
00447         // show a message about the first phase of computations
00448         if (!currentCache && maxCache)
00449                 sout << "=== PHASE 1: Computation of Conley indices ===\n";
00450 
00451         // skip all single boxes whose "ind" and "png" files already exist
00452         while (currentCache < maxCache)
00453         {
00454                 // if the cached indices file does not exist then send it
00455                 std::string cacheFileName (sharePrefix +
00456                         coord2str (cacheCoord, paramDim) + ".ind");
00457                 if (!fileExists (cacheFileName. c_str ()))
00458                         break;
00459 
00460                 // if the phase space picture does not exist then send it
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                 // take the next point
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                 // show a message about the second phase of computations
00479                 if (currentCache == maxCache)
00480                 {
00481                         sout << "=== PHASE 2: Continuation of Morse "
00482                                 "decompositions ===\n";
00483                 }
00484         }
00485 
00486         // decide if a single box for pre-caching of indices should be sent
00487         bool cacheToSend = (currentCache < maxCache);
00488 
00489         // determine the data pack to send if any
00490         const parCoord *coord = 0;
00491         while (!cacheToSend && !allSent)
00492         {
00493                 // take the next available set of coordinates
00494                 coord = rectIterator -> get ();
00495 
00496                 // if no new coordinates are available...
00497                 if (!coord)
00498                 {
00499                         // increase the parity bits
00500                         int nBit = 0;
00501                         while ((nBit < paramDim) && (parityBits [nBit] == 1))
00502                                 parityBits [nBit ++] = 0;
00503 
00504                         // quit if all the parity bits have been used
00505                         if (nBit == paramDim)
00506                         {
00507                                 allSent = true;
00508                                 break;
00509                         }
00510 
00511                         // increase the bit that was found
00512                         parityBits [nBit] = 1;
00513 
00514                         // rewind the iterator of box coordinates
00515                         coord = rectIterator -> get ();
00516                 }
00517 
00518                 // check if the coordinates satisfy the parity condition
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                 // if this box has already been processed before then skip it
00531                 if (parityOk && !previousBoxes. empty () &&
00532                         previousBoxes. check (parCube (coord, paramDim)))
00533                 {
00534                         continue;
00535                 }
00536 
00537                 // if the parity condition is satisfied then break the loop
00538                 if (parityOk)
00539                         break;
00540         }
00541 
00542         // save the final results if this is the end of computations.
00543         if (allSent && !sentlen && !finalPrefix. empty ())
00544         {
00545                 sout << "================================\n";
00546 
00547                 // show a warning about wrong Conley indices
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                 // show a summary on the number of computed Morse decomps
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                 // show the range of cubes in the Morse sets
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                 // show the max image diameter and volume encountered
00585                 sout << "Max img diam = " << maxImgDiam <<
00586                         ", max img vol = " << maxImgVol << ".\n";
00587 
00588                 // save the continuation classes to files
00589                 sout << "Saving the continuation classes...\n";
00590                 matchArray. saveSets (finalPrefix. c_str ());
00591         }
00592 
00593         // if all data has already been sent then return no data
00594         if (allSent)
00595                 return chomp::multiwork::mwNoData;
00596 
00597         // create a data pack with the current box
00598         parCube dataBox (cacheToSend ? cacheCoord : coord, paramDim);
00599         int dataNumber = cacheToSend ? -(currentCache + 1) : current;
00600         sent [sentlen ++] = datapack (dataNumber, dataBox);
00601 
00602         // prepare the parameter coordinate ranges to send
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                         // prepare the range of coordinates to process
00614                         // and add an overlap margin if necessary
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         // encode the data to send
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         // save the information on this data to the results file
00637         if (!cacheToSend)
00638         {
00639                 interFile << "+ " << dataNumber << " " << dataBox << "\n" <<
00640                         std::flush;
00641         }
00642 
00643         // show a message on what is being sent
00644         // and indicate the percentage of work done
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                 // increase the counter of the current box
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                 // show a message about the second phase of computations
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 } /* Coordinator::Prepare */
00684 
00685 inline int Coordinator::Accept (chomp::multiwork::mwData &data)
00686 {
00687         using chomp::homology::sout;
00688         using chomp::homology::sbug;
00689 
00690         // decode the number
00691         int dataNumber = 0;
00692         data >> dataNumber;
00693 
00694         // show a message informing about the reception of the data
00695         // and indicate the percentage of work done
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         // find the data chunk that corresponds to this number
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         // make a note in the log file that this result has been received
00718         if (dataNumber >= 0)
00719         {
00720                 interFile << "* " << dataNumber << " " <<
00721                         sent [pos]. box << "\n";
00722         }
00723 
00724         // retrieve the time of processing this entire chunk of boxes
00725         double processingTime = 0;
00726         data >> processingTime;
00727 
00728         // acquire the numbers of Morse sets with wrong Conley indices
00729         std::vector<std::vector<int> > localWrongIndices;
00730         data >> localWrongIndices;
00731 
00732         // acquire the numbers of Morse sets for which the Conley index
00733         // computation was skipped
00734         std::vector<std::vector<int> > skippedIndices;
00735         data >> skippedIndices;
00736 
00737         // acquire the numbers of Morse sets which are attractors
00738         std::vector<std::vector<int> > attractors;
00739         data >> attractors;
00740 
00741         // acquire the ranges of coordinates
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         // determine the number of processed boxes
00759         int countBoxes = 0;
00760         data >> countBoxes;
00761 
00762         // acquire data for each box
00763         bool graphsOutput = false;
00764         parCubes paramBoxes;
00765         for (int curNumber = 0; curNumber < countBoxes; ++ curNumber)
00766         {
00767                 // determine the actual box coordinates
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                 // retrieve the time used to process this box
00775                 double timeUsed = 0;
00776                 data >> timeUsed;
00777 
00778                 // was this Morse decomposition computed by this worker?
00779                 bool wasComputed = false;
00780                 data >> wasComputed;
00781                 if (wasComputed)
00782                         ++ morseDecComputed;
00783                 else
00784                         ++ morseDecReused;
00785 
00786                 // decode the Morse graph
00787                 chomp::homology::diGraph<> morseGraph;
00788                 data >> morseGraph;
00789 
00790                 // decode the sizes of each Morse set
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                 // make a note of wrong Conley indices if any
00797                 if (!localWrongIndices [curNumber]. empty ())
00798                 {
00799                         wrongIndices [wrongIndexBoxes. size ()] =
00800                                 localWrongIndices [curNumber];
00801                         wrongIndexBoxes. add (paramBox);
00802                 }
00803 
00804                 // decode the Conley indices and the eigenvalues
00805                 std::vector<theConleyIndexType> indices (nSets);
00806                 std::vector<IndexEigenValues> eigenValues (nSets);
00807                 for (int n = 0; n < nSets; ++ n)
00808                 {
00809                         // decode the Morse index of the n-th Morse set
00810                         data >> indices [n];
00811 
00812                         // decode the sets of nonzero eigenvalues
00813                         data >> eigenValues [n];
00814                 }
00815 
00816                 // write the Conley-Morse graph for the given box
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         // acquire data regarding the continuation relation between the boxes
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                 // determine the number of boxes in the equivalence class
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                 // prepare the coordinates of the first box in the class
00860                 parCoord coordZero [paramDim];
00861                 theClass [0]. coord (coordZero);
00862                 interFile << " " << theClass [0];
00863 
00864                 // make a note of all the other boxes being equivalent
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         // retrieve computed max image diameter and volume
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         // remove the data from the table containing the data that was sent
00886         -- sentlen;
00887         if (pos != sentlen)
00888                 sent [pos] = sent [sentlen];
00889 
00890         // indicate the number of equivalence classes acquired.
00891 //      sbug << nClasses << " equivalence class" <<
00892 //              ((nClasses == 1) ? "" : "es") << " acquired.\n";
00893 
00894         // flush the output files and say how many results have been accepted
00895         if (dataNumber >= 0)
00896                 interFile << std::flush;
00897         if (graphsOutput)
00898                 graphsFile << std::flush;
00899         return chomp::multiwork::mwOk;
00900 } /* Coordinator::Accept */
00901 
00902 inline int Coordinator::Reject (chomp::multiwork::mwData &/*data*/)
00903 {
00904         using chomp::homology::sout;
00905         sout << "WARNING: Data rejected by a worker.\n";
00906         return chomp::multiwork::mwError;
00907 } /* Coordinator::Reject */
00908 
00909 
00910 #endif // _CMGRAPHS_COORD_H_
00911 

Generated on Sun Mar 28 17:47:57 2010 for The Conley-Morse Graphs Software by  doxygen 1.5.3