coord.h

Go to the documentation of this file.
00001 /// @addtogroup unifexp
00002 /// @{
00003 
00004 /////////////////////////////////////////////////////////////////////////////
00005 ///
00006 /// @file coord.h
00007 ///
00008 /// This file contains the definition of the class "coordinator"
00009 /// which coordinates series of computations.
00010 ///
00011 /// @author Pawel Pilarczyk
00012 ///
00013 /////////////////////////////////////////////////////////////////////////////
00014 
00015 // Copyright (C) 2007 by Pawel Pilarczyk.
00016 //
00017 // This file is part of my research program package.  This is free software;
00018 // you can redistribute it and/or modify it under the terms of the GNU
00019 // General Public License as published by the Free Software Foundation;
00020 // either version 2 of the License, or (at your option) any later version.
00021 //
00022 // This software is distributed in the hope that it will be useful,
00023 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025 // GNU General Public License for more details.
00026 //
00027 // You should have received a copy of the GNU General Public License along
00028 // with this software; see the file "license.txt".  If not, write to the
00029 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00030 // MA 02111-1307, USA.
00031 
00032 // Started on March 8, 2007. Last revision: August 22, 2007.
00033 
00034 #ifndef _coord_h_
00035 #define _coord_h_
00036 
00037 #include <iostream>
00038 #include <fstream>
00039 #include <iomanip>
00040 #include <vector>
00041 
00042 #include "chomp/system/config.h"
00043 #include "chomp/system/textfile.h"
00044 #include "chomp/system/timeused.h"
00045 #include "chomp/multiwork/mw.h"
00046 
00047 #include "bitvect.h"
00048 
00049 
00050 namespace unifexp {
00051 
00052 // --------------------------------------------------
00053 // ------------- the coordinator class --------------
00054 // --------------------------------------------------
00055 
00056 /// An object of this class coordinates a series of computations
00057 /// for the Uniform Expansion program.
00058 /// This class inherits from the mwCoordinator class
00059 /// to allow network distribution of the work.
00060 class Coordinator: public chomp::multiwork::mwCoordinator
00061 {
00062 public:
00063         /// The complete constructor of a coordinator.
00064         Coordinator (int _controlNumber,
00065                 const char *_filename, bool _flushfile,
00066                 double _paramMin, double _paramMax, bool _intervals,
00067                 double _deltaMin, double _deltaMax, double _resolution,
00068                 double _lambdaMin, double _lambdaMax, const char *_mapName,
00069                 const char *_partName, int _partCountMin, int _partCountMax,
00070                 int _startLevel, int _finalLevel,
00071                 int _computeDelta, int _computeDelta0,
00072                 int _computeLambda, int _computeC, int _computeLambda0,
00073                 int _rigorous, int _sparseGraph);
00074 
00075         /// The destructor of the coordinator.
00076         ~Coordinator ();
00077 
00078 private:
00079         /// A function for preparing data by a coordinator.
00080         int Prepare (chomp::multiwork::mwData &data);
00081 
00082         /// A function for accepting results by a coordinator.
00083         int Accept (chomp::multiwork::mwData &data);
00084 
00085         /// A function for taking rejected data by a coordinator.
00086         int Reject (chomp::multiwork::mwData &data);
00087 
00088         // --- Parameters of Computations ---
00089 
00090         /// The control number to recognize compatible workers.
00091         int controlNumber;
00092 
00093         /// A file to append the results to.
00094         std::ofstream f;
00095 
00096         /// Should the results file be flushed after every write?
00097         bool flushfile;
00098 
00099         /// The minimal value of the parameter 'a' to investigate.
00100         double paramMin;
00101 
00102         /// The maximal value of the parameter 'a' to investigate.
00103         double paramMax;
00104 
00105         /// Should the entire intervals of parameters be processed?
00106         bool intervals;
00107 
00108         /// The minimal value of delta if fixed.
00109         double deltaMin;
00110 
00111         /// The maximal value of delta if fixed.
00112         double deltaMax;
00113 
00114         /// The resolution with which lambda must be found.
00115         double resolution;
00116 
00117         /// The minimal value of lambda if requested.
00118         double lambdaMin;
00119 
00120         /// The maximal value of lambda if requested.
00121         double lambdaMax;
00122 
00123         /// The map type name.
00124         std::string mapName;
00125 
00126         /// The partition type name.
00127         std::string partName;
00128 
00129         /// The minimal size of the partition.
00130         int partCountMin;
00131 
00132         /// The maximal size of the partition.
00133         int partCountMax;
00134 
00135         // --- Current Data of Computations ---
00136 
00137         /// Reads the previously computed results from the input file.
00138         /// Returns true if successful, false if no results file exists.
00139         bool readResults (const char *filename);
00140 
00141         /// Opens a file with the results for appending or creates the file.
00142         /// If this is a new file then some introductory info is written.
00143         void openResults (const char *filename, bool newFile);
00144 
00145         /// The currently processed level.
00146         int currentLevel;
00147 
00148         /// The current element at the given level.
00149         int currentItem;
00150 
00151         /// The starting subdivision level.
00152         int startLevel;
00153 
00154         /// The final subdivision level.
00155         int finalLevel;
00156 
00157         /// Is there just one single parameter combination to be processed?
00158         bool singleItem;
00159 
00160         /// Should delta be computed?
00161         int computeDelta;
00162 
00163         /// Should delta0 be computed? (with paths in consideration)
00164         int computeDelta0;
00165 
00166         /// Should lambda be computed?
00167         int computeLambda;
00168 
00169         /// Should C be computed?
00170         int computeC;
00171 
00172         /// Should lambda0 be computed?
00173         int computeLambda0;
00174 
00175         /// Should the computations be rigorous?
00176         int rigorous;
00177 
00178         /// Should a sparse graph algorithm be used? [0=no, 1=yes, -1=auto]
00179         int sparseGraph;
00180 
00181         /// The bit fields for each level.
00182         std::vector<bitVector *> processed;
00183 
00184         /// The low precision for writing real numbers to files.
00185         int loprec;
00186 
00187         /// The high precision for writing real numbers to files.
00188         int hiprec;
00189 
00190         /// Computes the number of items at the given level.
00191         int numberOfItems (int level) const;
00192 
00193         /// Updates the processet bit vectors to the current level.
00194         void updateProcessed (int level);
00195 
00196 }; /* class Coordinator */
00197 
00198 // --------------------------------------------------
00199 
00200 inline bool Coordinator::readResults (const char *filename)
00201 {
00202         using namespace chomp::homology;
00203 
00204         // ignore a file with no or empty name
00205         if (!filename && !*filename)
00206                 return false;
00207 
00208         // open the file for reading
00209         std::ifstream in (filename);
00210         if (!in)
00211                 return false;
00212 
00213         // process all the lines with the results and mark which are read
00214         ignorecomments (in);
00215         while (in. peek () != EOF)
00216         {
00217                 if (in. peek () != '*')
00218                 {
00219                         ignoreline (in);
00220                         ignorecomments (in);
00221                         continue;
00222                 }
00223                 in. get ();
00224                 ignorecomments (in);
00225                 int cLevel = -1, cColon = -1, cItem = -1;
00226                 in >> cLevel;
00227                 ignorecomments (in);
00228                 cColon = in. get ();
00229                 ignorecomments (in);
00230                 in >> cItem;
00231                 if ((cLevel >= 0) && (cColon == ':') && (cItem >= 0) &&
00232                         (cItem < numberOfItems (cLevel)))
00233                 {
00234                         updateProcessed (cLevel);
00235                         processed [cLevel] -> mark (cItem);
00236                 }
00237                 ignoreline (in);
00238                 ignorecomments (in);
00239         }
00240         return true;
00241 } /* Coordinator::readResults */
00242 
00243 inline void Coordinator::openResults (const char *filename, bool newFile)
00244 {
00245         using namespace chomp::homology;
00246 
00247         // ignore a file with no or empty name
00248         if (!filename && !*filename)
00249                 return;
00250 
00251         // open the results file for appending
00252         f. open (filename, std::ios::out | std::ios::app);
00253         f << "; Started on " << currenttime ();
00254         if (!f)
00255                 fileerror (filename);
00256 
00257         // indicate the meaning of the data in each line
00258         if (newFile)
00259         {
00260                 f << "; level:num parMin parMax k delta lambda logC lambda0 "
00261                         "compTime\n";
00262         }
00263 
00264         // set the values of low/high precision for writing results
00265         loprec = f. precision ();
00266         hiprec = 15;
00267 
00268         return;
00269 } /* Coordinator::openResults */
00270 
00271 inline Coordinator::Coordinator (int _controlNumber,
00272         const char *_filename, bool _flushfile,
00273         double _paramMin, double _paramMax, bool _intervals,
00274         double _deltaMin, double _deltaMax, double _resolution,
00275         double _lambdaMin, double _lambdaMax, const char *_mapName,
00276         const char *_partName, int _partCountMin, int _partCountMax,
00277         int _startLevel, int _finalLevel,
00278         int _computeDelta, int _computeDelta0,
00279         int _computeLambda, int _computeC, int _computeLambda0,
00280         int _rigorous, int _sparseGraph):
00281         controlNumber (_controlNumber), flushfile (_flushfile),
00282         paramMin (_paramMin), paramMax (_paramMax), intervals (_intervals),
00283         deltaMin (_deltaMin), deltaMax (_deltaMax), resolution (_resolution),
00284         lambdaMin (_lambdaMin), lambdaMax (_lambdaMax),
00285         mapName (_mapName), partName (_partName),
00286         partCountMin (_partCountMin), partCountMax (_partCountMax),
00287         currentLevel (_startLevel), currentItem (0),
00288         startLevel (_startLevel), finalLevel (_finalLevel),
00289         singleItem (false),
00290         computeDelta (_computeDelta), computeDelta0 (_computeDelta0),
00291         computeLambda (_computeLambda), computeC (_computeC),
00292         computeLambda0 (_computeLambda0), rigorous (_rigorous),
00293         sparseGraph (_sparseGraph),
00294         loprec (6), hiprec (6)
00295 {
00296         using namespace chomp::homology;
00297 
00298         // check the correctness of levels
00299         if ((startLevel < 0) || (finalLevel < startLevel))
00300                 throw "Incorrect start/final levels requested.";
00301 
00302         // if there is only one parameter to consider, reset the levels
00303         if ((paramMin == paramMax) && (deltaMin == deltaMax) &&
00304                 (lambdaMin == lambdaMax) && (partCountMin == partCountMax))
00305         {
00306                 singleItem = true;
00307                 currentLevel = finalLevel = startLevel = 0;
00308         }
00309 
00310         // if the parameter of the equation is single, set no intervals
00311         if (paramMin == paramMax)
00312                 intervals = false;
00313 
00314         // process and open the results file if its file name is given
00315         if (_filename && *_filename)
00316         {
00317                 // read the previously computed results of the computations
00318                 bool resultsRead = this -> readResults (_filename);
00319                 if (!resultsRead)
00320                 {
00321                         sout << "Note: Could not open the results file. "
00322                                 "Any previous results will be ignored.\n";
00323                 }
00324 
00325                 // open the results file for appending
00326                 openResults (_filename, !resultsRead);
00327         }
00328 
00329         // otherwise, warn the user
00330         else
00331                 sout << "Warning: Results will not be saved to a file.";
00332 
00333         return;
00334 } /* Coordinator::Coordinator */
00335 
00336 inline Coordinator::~Coordinator ()
00337 {
00338         using namespace chomp::homology;
00339 
00340         f << "; Finished on " << currenttime ();
00341         f. close ();
00342         for (std::vector<bitVector *>::iterator it = processed. begin ();
00343                 it != processed. end (); ++ it)
00344         {
00345                 delete *it;
00346         }
00347         return;
00348 } /* Coordinator::~Coordinator */
00349 
00350 inline int Coordinator::numberOfItems (int level) const
00351 {
00352         if (singleItem)
00353                 return 1;
00354         else if (!intervals && (level == startLevel))
00355                 return (1 << level) + 1;
00356         else
00357                 return 1 << level;
00358 } /* Coordinator::numberOfItems */
00359 
00360 inline void Coordinator::updateProcessed (int level)
00361 {
00362         while (processed. size () <= static_cast<unsigned> (level))
00363         {
00364                 int nItems = numberOfItems (processed. size ());
00365                 processed. push_back (new bitVector (nItems));
00366         }
00367         return;
00368 } /* Coordinator::updateProcessed */
00369 
00370 inline int Coordinator::Prepare (chomp::multiwork::mwData &data)
00371 {
00372         using namespace chomp::homology;
00373         using namespace chomp::multiwork;
00374 
00375         // reset the data to prepare
00376         data. Reset ();
00377 
00378         // compute the current values of parameters to send
00379         int nItems = 0;
00380         while (1)
00381         {
00382                 // make sure the current item is set to an unmarked bit
00383                 updateProcessed (currentLevel);
00384                 nItems = numberOfItems (currentLevel);
00385                 if (currentItem < nItems)
00386                 {
00387                         currentItem = processed [currentLevel] ->
00388                                 findUnmarked (currentItem, nItems);
00389                 }
00390 
00391                 // if odd items only are processed, move to the next one
00392                 if ((currentItem < nItems) && !intervals &&
00393                         (currentLevel != startLevel) && !(currentItem & 1))
00394                 {
00395                         ++ currentItem;
00396                         continue;
00397                 }
00398 
00399                 // if an unmarked bit was found, then prepare the data
00400                 if (currentItem < nItems)
00401                 {
00402                         processed [currentLevel] -> mark (currentItem);
00403                         break;
00404                 }
00405 
00406                 // if the entire final level has been processed, finish
00407                 if (currentLevel == finalLevel)
00408                         return mwNoData;
00409 
00410                 // take the next level to process
00411                 ++ currentLevel;
00412                 currentItem = 0;
00413         }
00414 
00415         // prepare the parameters of computations to send
00416         double paramMin1 = (paramMin == paramMax) ? paramMin : (paramMin +
00417                 currentItem * (paramMax - paramMin) / (1 << currentLevel));
00418         double paramMax1 = intervals ? (paramMin + (currentItem + 1) *
00419                 (paramMax - paramMin) / (1 << currentLevel)) : paramMin1;
00420         double delta1 = (deltaMin == deltaMax) ? deltaMin :
00421                 exp (log (deltaMin) + currentItem * (log (deltaMax) -
00422                 log (deltaMin)) / (1 << currentLevel));
00423         double lambda1 = (lambdaMin == lambdaMax) ? lambdaMin : (lambdaMin +
00424                 currentItem * (lambdaMax - lambdaMin) / (1 << currentLevel));
00425         int partCount1 = (partCountMin == partCountMax) ? partCountMin :
00426                 static_cast <int> ((partCountMin +
00427                 static_cast<double> (currentItem) *
00428                 (partCountMax - partCountMin) / (1 << currentLevel)));
00429 
00430         // prepare data to send
00431         data << currentLevel;
00432         data << currentItem;
00433         data << mapName;
00434         data << partName;
00435         data << partCount1;
00436         data << paramMin1;
00437         data << paramMax1;
00438         data << delta1;
00439         data << resolution;
00440         data << lambda1;
00441         data << computeDelta;
00442         data << computeDelta0;
00443         data << computeLambda;
00444         data << computeC;
00445         data << computeLambda0;
00446         data << rigorous;
00447         data << sparseGraph;
00448         data << loprec;
00449         data << hiprec;
00450         data << controlNumber;
00451 
00452         // show a message on what has been done
00453         sout << "+ " << currentLevel << ":" << currentItem << ".\n";
00454 
00455         ++ currentItem;
00456         return mwOk;
00457 } /* Coordinator::Prepare */
00458 
00459 inline int Coordinator::Accept (chomp::multiwork::mwData &data)
00460 {
00461         using namespace chomp::homology;
00462         using namespace chomp::multiwork;
00463 
00464         // decode the number
00465         int cLevel = 0, cItem = 0;
00466         data >> cLevel;
00467         data >> cItem;
00468         double pMin = 0;
00469         double pMax = 0;
00470         data >> pMin;
00471         data >> pMax;
00472         int partCount = 0;
00473         data >> partCount;
00474         double deltaBad = 0;
00475         double delta = 0;
00476         double lambda = 0;
00477         double logC = 0;
00478         double lambda0 = 0;
00479         data >> deltaBad;
00480         data >> delta;
00481         data >> lambda;
00482         data >> logC;
00483         data >> lambda0;
00484         double compTime = 0;
00485         data >> compTime;
00486         int ctrl = 0;
00487         data >> ctrl;
00488         if (ctrl != controlNumber)
00489         {
00490                 f << "! Wrong data received.\n";
00491                 throw "Wrong data received from a worker.";
00492         }
00493 
00494         // say what has been received
00495         sout << "* " << cLevel << ":" << cItem << " [" << pMin << "," <<
00496                 pMax << "] k=" << partCount << " d=" << delta <<
00497                 " l=" << lambda << " lC=" << logC << " l0=" << lambda0 <<
00498                 " (" << compTime << "s)" << "\n";
00499 
00500         // save the data to the output file
00501         f << "* " << cLevel << ":" << cItem << " " <<
00502                 pMin << " " << pMax << " " << partCount << " " <<
00503                 std::setprecision (hiprec) << delta << " " <<
00504                 lambda << " " << logC << " " << lambda0 << " " <<
00505                 std::setprecision (loprec) << compTime << "\n";
00506 
00507         // flush the data file if requested to
00508         if (flushfile)
00509                 f << std::flush;
00510 
00511         return mwOk;
00512 } /* Coordinator::Accept */
00513 
00514 inline int Coordinator::Reject (chomp::multiwork::mwData &data)
00515 {
00516         using namespace chomp::homology;
00517         using namespace chomp::multiwork;
00518 
00519         // decode the number
00520         int cLevel = 0, cItem = 0;
00521         data >> cLevel;
00522         data >> cItem;
00523 
00524         // say that data has been rejected
00525         sout << "Data " << cLevel << ":" << cItem << " has been rejected.\n";
00526         throw "Data rejected by a worker.";
00527 
00528         return mwOk;
00529 } /* Coordinator::Reject */
00530 
00531 
00532 } // namespace unifexp
00533 
00534 #endif // _coord_h_
00535 
00536 /// @}
00537 

Generated on Wed Nov 21 11:08:41 2007 for The Uniform Expansion Software by  doxygen 1.5.3