• Main Page
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

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: June 1, 2008.
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         return;
00265 } /* Coordinator::openResults */
00266 
00267 inline Coordinator::Coordinator (int _controlNumber,
00268         const char *_filename, bool _flushfile,
00269         double _paramMin, double _paramMax, bool _intervals,
00270         double _deltaMin, double _deltaMax, double _resolution,
00271         double _lambdaMin, double _lambdaMax, const char *_mapName,
00272         const char *_partName, int _partCountMin, int _partCountMax,
00273         int _startLevel, int _finalLevel,
00274         int _computeDelta, int _computeDelta0,
00275         int _computeLambda, int _computeC, int _computeLambda0,
00276         int _rigorous, int _sparseGraph):
00277         controlNumber (_controlNumber), flushfile (_flushfile),
00278         paramMin (_paramMin), paramMax (_paramMax), intervals (_intervals),
00279         deltaMin (_deltaMin), deltaMax (_deltaMax), resolution (_resolution),
00280         lambdaMin (_lambdaMin), lambdaMax (_lambdaMax),
00281         mapName (_mapName), partName (_partName),
00282         partCountMin (_partCountMin), partCountMax (_partCountMax),
00283         currentLevel (_startLevel), currentItem (0),
00284         startLevel (_startLevel), finalLevel (_finalLevel),
00285         singleItem (false),
00286         computeDelta (_computeDelta), computeDelta0 (_computeDelta0),
00287         computeLambda (_computeLambda), computeC (_computeC),
00288         computeLambda0 (_computeLambda0), rigorous (_rigorous),
00289         sparseGraph (_sparseGraph),
00290         loprec (9), hiprec (15)
00291 {
00292         using namespace chomp::homology;
00293 
00294         // check the correctness of levels
00295         if ((startLevel < 0) || (finalLevel < startLevel))
00296                 throw "Incorrect start/final levels requested.";
00297 
00298         // if there is only one parameter to consider, reset the levels
00299         if ((paramMin == paramMax) && (deltaMin == deltaMax) &&
00300                 (lambdaMin == lambdaMax) && (partCountMin == partCountMax))
00301         {
00302                 singleItem = true;
00303                 currentLevel = finalLevel = startLevel = 0;
00304         }
00305 
00306         // if the parameter of the equation is single, set no intervals
00307         if (paramMin == paramMax)
00308                 intervals = false;
00309 
00310         // process and open the results file if its file name is given
00311         if (_filename && *_filename)
00312         {
00313                 // read the previously computed results of the computations
00314                 bool resultsRead = this -> readResults (_filename);
00315                 if (!resultsRead)
00316                 {
00317                         sout << "Note: Could not open the results file. "
00318                                 "Any previous results will be ignored.\n";
00319                 }
00320 
00321                 // open the results file for appending
00322                 openResults (_filename, !resultsRead);
00323         }
00324 
00325         // otherwise, warn the user
00326         else
00327                 sout << "Warning: Results will not be saved to a file.";
00328 
00329         return;
00330 } /* Coordinator::Coordinator */
00331 
00332 inline Coordinator::~Coordinator ()
00333 {
00334         using namespace chomp::homology;
00335 
00336         f << "; Finished on " << currenttime ();
00337         f. close ();
00338         for (std::vector<bitVector *>::iterator it = processed. begin ();
00339                 it != processed. end (); ++ it)
00340         {
00341                 delete *it;
00342         }
00343         return;
00344 } /* Coordinator::~Coordinator */
00345 
00346 inline int Coordinator::numberOfItems (int level) const
00347 {
00348         if (singleItem)
00349                 return 1;
00350         else if (!intervals && (level == startLevel))
00351                 return (1 << level) + 1;
00352         else
00353                 return 1 << level;
00354 } /* Coordinator::numberOfItems */
00355 
00356 inline void Coordinator::updateProcessed (int level)
00357 {
00358         while (processed. size () <= static_cast<unsigned> (level))
00359         {
00360                 int nItems = numberOfItems (processed. size ());
00361                 processed. push_back (new bitVector (nItems));
00362         }
00363         return;
00364 } /* Coordinator::updateProcessed */
00365 
00366 inline int Coordinator::Prepare (chomp::multiwork::mwData &data)
00367 {
00368         using namespace chomp::homology;
00369         using namespace chomp::multiwork;
00370 
00371         // reset the data to prepare
00372         data. Reset ();
00373 
00374         // compute the current values of parameters to send
00375         int nItems = 0;
00376         while (1)
00377         {
00378                 // make sure the current item is set to an unmarked bit
00379                 updateProcessed (currentLevel);
00380                 nItems = numberOfItems (currentLevel);
00381                 if (currentItem < nItems)
00382                 {
00383                         currentItem = processed [currentLevel] ->
00384                                 findUnmarked (currentItem, nItems);
00385                 }
00386 
00387                 // if odd items only are processed, move to the next one
00388                 if ((currentItem < nItems) && !intervals &&
00389                         (currentLevel != startLevel) && !(currentItem & 1))
00390                 {
00391                         ++ currentItem;
00392                         continue;
00393                 }
00394 
00395                 // if an unmarked bit was found, then prepare the data
00396                 if (currentItem < nItems)
00397                 {
00398                         processed [currentLevel] -> mark (currentItem);
00399                         break;
00400                 }
00401 
00402                 // if the entire final level has been processed, finish
00403                 if (currentLevel == finalLevel)
00404                         return mwNoData;
00405 
00406                 // take the next level to process
00407                 ++ currentLevel;
00408                 currentItem = 0;
00409         }
00410 
00411         // prepare the parameters of computations to send
00412         double paramMin1 = (paramMin == paramMax) ? paramMin : (paramMin +
00413                 currentItem * (paramMax - paramMin) / (1 << currentLevel));
00414         double paramMax1 = intervals ? (paramMin + (currentItem + 1) *
00415                 (paramMax - paramMin) / (1 << currentLevel)) : paramMin1;
00416         double delta1 = (deltaMin == deltaMax) ? deltaMin :
00417                 exp (log (deltaMin) + currentItem * (log (deltaMax) -
00418                 log (deltaMin)) / (1 << currentLevel));
00419         double lambda1 = (lambdaMin == lambdaMax) ? lambdaMin : (lambdaMin +
00420                 currentItem * (lambdaMax - lambdaMin) / (1 << currentLevel));
00421         int partCount1 = (partCountMin == partCountMax) ? partCountMin :
00422                 static_cast <int> ((partCountMin +
00423                 static_cast<double> (currentItem) *
00424                 (partCountMax - partCountMin) / (1 << currentLevel)));
00425 
00426         // prepare data to send
00427         data << currentLevel;
00428         data << currentItem;
00429         data << mapName;
00430         data << partName;
00431         data << partCount1;
00432         data << paramMin1;
00433         data << paramMax1;
00434         data << delta1;
00435         data << resolution;
00436         data << lambda1;
00437         data << computeDelta;
00438         data << computeDelta0;
00439         data << computeLambda;
00440         data << computeC;
00441         data << computeLambda0;
00442         data << rigorous;
00443         data << sparseGraph;
00444         data << loprec;
00445         data << hiprec;
00446         data << controlNumber;
00447 
00448         // show a message on what has been done
00449         sout << "+ " << currentLevel << ":" << currentItem << ".\n";
00450 
00451         ++ currentItem;
00452         return mwOk;
00453 } /* Coordinator::Prepare */
00454 
00455 inline int Coordinator::Accept (chomp::multiwork::mwData &data)
00456 {
00457         using namespace chomp::homology;
00458         using namespace chomp::multiwork;
00459 
00460         // decode the number
00461         int cLevel = 0, cItem = 0;
00462         data >> cLevel;
00463         data >> cItem;
00464         double pMin = 0;
00465         double pMax = 0;
00466         data >> pMin;
00467         data >> pMax;
00468         int partCount = 0;
00469         data >> partCount;
00470         double deltaBad = 0;
00471         double delta = 0;
00472         double lambda = 0;
00473         double logC = 0;
00474         double lambda0 = 0;
00475         data >> deltaBad;
00476         data >> delta;
00477         data >> lambda;
00478         data >> logC;
00479         data >> lambda0;
00480         double compTime = 0;
00481         data >> compTime;
00482         int ctrl = 0;
00483         data >> ctrl;
00484         if (ctrl != controlNumber)
00485         {
00486                 f << "! Wrong data received.\n";
00487                 throw "Wrong data received from a worker.";
00488         }
00489 
00490         // say what has been received
00491         sout << "* " << cLevel << ":" << cItem << " [" << pMin << "," <<
00492                 pMax << "] k=" << partCount << " d=" << delta <<
00493                 " l=" << lambda << " lC=" << logC << " l0=" << lambda0 <<
00494                 " (" << compTime << "s)" << "\n";
00495 
00496         // save the data to the output file
00497         f << "* " << cLevel << ":" << cItem << " " <<
00498                 pMin << " " << pMax << " " << partCount << " " <<
00499                 std::setprecision (hiprec) << delta << " " <<
00500                 lambda << " " << logC << " " << lambda0 << " " <<
00501                 std::setprecision (loprec) << compTime << "\n";
00502 
00503         // flush the data file if requested to
00504         if (flushfile)
00505                 f << std::flush;
00506 
00507         return mwOk;
00508 } /* Coordinator::Accept */
00509 
00510 inline int Coordinator::Reject (chomp::multiwork::mwData &data)
00511 {
00512         using namespace chomp::homology;
00513         using namespace chomp::multiwork;
00514 
00515         // decode the number
00516         int cLevel = 0, cItem = 0;
00517         data >> cLevel;
00518         data >> cItem;
00519 
00520         // say that data has been rejected
00521         sout << "Data " << cLevel << ":" << cItem << " has been rejected.\n";
00522         throw "Data rejected by a worker.";
00523 
00524         return mwOk;
00525 } /* Coordinator::Reject */
00526 
00527 
00528 } // namespace unifexp
00529 
00530 #endif // _coord_h_
00531 
00532 /// @}
00533 

Generated on Sun Feb 3 2013 12:40:31 for The Uniform Expansion Software by  doxygen 1.7.2