00001
00002
00003
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifndef _CHOMP_MULTIWORK_MWSUBDIV_H_
00035 #define _CHOMP_MULTIWORK_MWSUBDIV_H_
00036
00037 #include <cmath>
00038 #include <iostream>
00039 #include <fstream>
00040 #include <string>
00041 #include <sstream>
00042 #include <exception>
00043
00044 #include "chomp/system/config.h"
00045 #include "chomp/system/textfile.h"
00046 #include "chomp/system/timeused.h"
00047 #include "chomp/system/arg.h"
00048 #include "chomp/cubes/pointset.h"
00049 #include "chomp/cubes/cube.h"
00050 #include "chomp/multiwork/mw.h"
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 namespace chomp {
00073 namespace multiwork {
00074
00075 using chomp::homology::sout;
00076 using chomp::homology::sbug;
00077 using chomp::homology::slog;
00078 using chomp::homology::ignorecomments;
00079 using chomp::homology::ignoreline;
00080 using chomp::homology::hashedset;
00081 using chomp::homology::multitable;
00082 using chomp::homology::tRectangle;
00083 using chomp::homology::tCubeFix;
00084 using chomp::homology::arguments;
00085 using chomp::homology::arg;
00086 using chomp::homology::argswitch;
00087 using chomp::homology::arghelp;
00088 using chomp::homology::argstreams;
00089 using chomp::homology::setstreams;
00090 using chomp::homology::commandline;
00091 using chomp::homology::currenttime;
00092 using chomp::homology::program_time;
00093
00094
00095
00096
00097
00098
00103 typedef int (*fcompute) (const double *left, const double *right,
00104 int dim, int level);
00105
00107 template <int dim, class coord>
00108 class mwSubWorker: public mwWorker
00109 {
00110 public:
00112 mwSubWorker (fcompute _compute);
00113
00114 private:
00116 int Process (mwData &data);
00117
00119 fcompute compute;
00120
00121 };
00122
00123
00124
00125 template <int dim, class coord>
00126 inline mwSubWorker<dim,coord>::mwSubWorker (fcompute _compute):
00127 compute (_compute)
00128 {
00129 return;
00130 }
00131
00132
00133
00134 template <int dim, class coord>
00135 int mwSubWorker<dim,coord>::Process (mwData &data)
00136 {
00137
00138 int current = 0;
00139 data >> current;
00140
00141
00142 sout << "- " << current << ".\n";
00143
00144
00145 int level = 0;
00146 data >> level;
00147
00148
00149 bool full = false;
00150 data >> full;
00151
00152
00153 double left [dim];
00154 double right [dim];
00155 for (int i = 0; i < dim; ++ i)
00156 {
00157 data >> left [i];
00158 if (full)
00159 data >> right [i];
00160 }
00161
00162
00163 int dataEndMarker = 0;
00164 data >> dataEndMarker;
00165 if (dataEndMarker != 13)
00166 {
00167 data. Reset ();
00168 sout << "! Incompatible data received. Rejecting it.\n";
00169 return mwReject;
00170 }
00171
00172
00173 int result = compute (left, full ? right : left, dim, level);
00174
00175
00176 if (result < 0)
00177 {
00178 sout << "! Data no. " << current <<
00179 " produced a negative result. Rejecting it.\n";
00180 return mwReject;
00181 }
00182
00183
00184 sout << "= " << current << " " << result << ".\n";
00185
00186
00187 data. Reset ();
00188 data << current;
00189 data << result;
00190 return mwOk;
00191 }
00192
00193
00194
00195
00196
00197
00202 template <class coord>
00203 inline double mwSubdivPoint (const double &left, const double &right,
00204 coord part, coord full)
00205 {
00206
00207
00208
00209
00210 if (part == 0)
00211 return left;
00212 else if (part == full)
00213 return right;
00214
00215
00216
00217 while (!(part & 1) && !(full & 1))
00218 {
00219 part >>= 1;
00220 full >>= 1;
00221 }
00222
00223
00224 double fraction = static_cast<double> (part) / full;
00225 return (left + (right - left) * fraction);
00226 }
00227
00228
00229
00230
00231
00232
00235 template <int dim, class coord>
00236 class mwIniProbes
00237 {
00238 public:
00240 mwIniProbes (int level = 2);
00241
00243 ~mwIniProbes ();
00244
00247 tCubeFix<dim,coord> get ();
00248
00250 bool available () const;
00251
00252 private:
00254 mwIniProbes (const mwIniProbes<dim,coord> &);
00255
00257 mwIniProbes<dim,coord> &operator = (const mwIniProbes<dim,coord> &);
00258
00260 coord left [dim];
00261
00263 coord right [dim];
00264
00266 tRectangle<coord> rect;
00267
00269 const coord *next;
00270
00271 };
00272
00273
00274
00275 template <int dim, class coord>
00276 inline mwIniProbes<dim,coord>::mwIniProbes (int level)
00277 {
00278 if (level < 2)
00279 throw "Too low initial level. Should be at least 2.";
00280 for (int i = 0; i < dim; ++ i)
00281 {
00282 this -> left [i] = 1;
00283 this -> right [i] = 1 << level;
00284 }
00285 this -> rect = tRectangle<coord> (this -> left, this -> right, dim);
00286 this -> next = this -> rect. get ();
00287 return;
00288 }
00289
00290 template <int dim, class coord>
00291 inline mwIniProbes<dim,coord>::mwIniProbes (const mwIniProbes<dim,coord> &)
00292 {
00293 return;
00294 }
00295
00296 template <int dim, class coord>
00297 inline mwIniProbes<dim,coord> &mwIniProbes<dim,coord>::operator =
00298 (const mwIniProbes<dim,coord> &)
00299 {
00300 return *this;
00301 }
00302
00303 template <int dim, class coord>
00304 inline mwIniProbes<dim,coord>::~mwIniProbes ()
00305 {
00306 return;
00307 }
00308
00309 template <int dim, class coord>
00310 inline tCubeFix<dim,coord> mwIniProbes<dim,coord>::get ()
00311 {
00312 tCubeFix<dim,coord> q (this -> next, dim);
00313 this -> next = this -> rect. get ();
00314 return q;
00315 }
00316
00317 template <int dim, class coord>
00318 inline bool mwIniProbes<dim,coord>::available () const
00319 {
00320 return !!(this -> next);
00321 }
00322
00323
00324
00325
00326
00327
00330 template <int dim, class coord>
00331 class mwBoxes
00332 {
00333 public:
00335 mwBoxes (const tCubeFix<dim,coord> &q);
00336
00338 ~mwBoxes ();
00339
00342 tCubeFix<dim,coord> get ();
00343
00345 bool available () const;
00346
00347 private:
00349 mwBoxes (const mwBoxes<dim,coord> &);
00350
00352 mwBoxes<dim,coord> &operator = (const mwBoxes<dim,coord> &);
00353
00355 coord left [dim];
00356
00358 coord right [dim];
00359
00361 tRectangle<coord> rect;
00362
00364 const coord *next;
00365
00366 };
00367
00368
00369
00370 template <int dim, class coord>
00371 inline mwBoxes<dim,coord>::mwBoxes (const tCubeFix<dim,coord> &q)
00372 {
00373 q. coord (this -> left);
00374 for (int i = 0; i < dim; ++ i)
00375 {
00376 this -> right [i] = left [i] + 1;
00377 -- (this -> left [i]);
00378 }
00379 this -> rect = tRectangle<coord> (this -> left, this -> right, dim);
00380 this -> next = this -> rect. get ();
00381 return;
00382 }
00383
00384 template <int dim, class coord>
00385 inline mwBoxes<dim,coord>::mwBoxes (const mwBoxes<dim,coord> &)
00386 {
00387 return;
00388 }
00389
00390 template <int dim, class coord>
00391 inline mwBoxes<dim,coord> &mwBoxes<dim,coord>::operator =
00392 (const mwBoxes<dim,coord> &)
00393 {
00394 return *this;
00395 }
00396
00397 template <int dim, class coord>
00398 inline mwBoxes<dim,coord>::~mwBoxes ()
00399 {
00400 return;
00401 }
00402
00403 template <int dim, class coord>
00404 inline tCubeFix<dim,coord> mwBoxes<dim,coord>::get ()
00405 {
00406 const coord *current = this -> next;
00407 this -> next = this -> rect. get ();
00408 return tCubeFix<dim,coord> (current, dim);
00409 }
00410
00411 template <int dim, class coord>
00412 inline bool mwBoxes<dim,coord>::available () const
00413 {
00414 return !!(this -> next);
00415 }
00416
00417
00418
00419
00420
00421
00424 template <int dim, class coord>
00425 class mwCorners
00426 {
00427 public:
00429 mwCorners (const tCubeFix<dim,coord> &q);
00430
00432 ~mwCorners ();
00433
00436 tCubeFix<dim,coord> get ();
00437
00439 bool available () const;
00440
00441 private:
00443 mwCorners (const mwCorners<dim,coord> &);
00444
00446 mwCorners<dim,coord> &operator = (const mwCorners<dim,coord> &);
00447
00449 coord left [dim];
00450
00452 coord right [dim];
00453
00455 tRectangle<coord> rect;
00456
00458 const coord *next;
00459
00460 };
00461
00462
00463
00464 template <int dim, class coord>
00465 inline mwCorners<dim,coord>::mwCorners (const tCubeFix<dim,coord> &q)
00466 {
00467 q. coord (this -> left);
00468 for (int i = 0; i < dim; ++ i)
00469 {
00470 this -> right [i] = left [i] + 2;
00471 }
00472 this -> rect = tRectangle<coord> (this -> left, this -> right, dim);
00473 this -> next = this -> rect. get ();
00474 return;
00475 }
00476
00477 template <int dim, class coord>
00478 inline mwCorners<dim,coord>::mwCorners (const mwCorners<dim,coord> &)
00479 {
00480 return;
00481 }
00482
00483 template <int dim, class coord>
00484 inline mwCorners<dim,coord> &mwCorners<dim,coord>::operator =
00485 (const mwCorners<dim,coord> &)
00486 {
00487 return *this;
00488 }
00489
00490 template <int dim, class coord>
00491 inline mwCorners<dim,coord>::~mwCorners ()
00492 {
00493 return;
00494 }
00495
00496 template <int dim, class coord>
00497 inline tCubeFix<dim,coord> mwCorners<dim,coord>::get ()
00498 {
00499 const coord *current = this -> next;
00500 this -> next = this -> rect. get ();
00501 return tCubeFix<dim,coord> (current, dim);
00502 }
00503
00504 template <int dim, class coord>
00505 inline bool mwCorners<dim,coord>::available () const
00506 {
00507 return !!(this -> next);
00508 }
00509
00510
00511
00512
00513
00514
00518 template <int dim, class coord>
00519 class mwSubDataPack
00520 {
00521 public:
00523 mwSubDataPack () {}
00524
00526 mwSubDataPack (int _num, const tCubeFix<dim,coord> &_q,
00527 int _level, bool _full):
00528 num (_num), q (_q), level (_level), full (_full) {}
00529
00530
00531
00532
00534 int num;
00535
00537 tCubeFix<dim,coord> q;
00538
00540 int level;
00541
00543 bool full;
00544
00545 };
00546
00547
00548
00549
00550
00551
00554 template <int dim, class coord>
00555 class mwSubCoordinator: public mwCoordinator
00556 {
00558 static const int ppMaxSubdiv = 8 * sizeof (coord) - 2;
00559
00561
00562
00564 typedef tCubeFix<dim,coord> ppCube;
00565
00567 static const int ppMaxDim = ppCube::MaxDim;
00568
00570 typedef hashedset<ppCube> ppCubes;
00571
00573 typedef tRectangle<coord> ppRect;
00574
00576 typedef mwSubDataPack<dim,coord> ppPack;
00577
00578 public:
00580 mwSubCoordinator ();
00581
00583 mwSubCoordinator (const char *filename,
00584 int _inilevel, int _maxlevel, bool _flushfile,
00585 const double *_paramLeft, const double *_paramRight);
00586
00588 ~mwSubCoordinator ();
00589
00590 private:
00591
00592
00594 int Prepare (mwData &data);
00595
00597 int Accept (mwData &data);
00598
00600 int Reject (mwData &data);
00601
00602
00603
00606 ppCubes Negative [ppMaxSubdiv];
00607
00610 ppCubes Good [ppMaxSubdiv];
00611
00613 ppCubes Test [ppMaxSubdiv];
00614
00616 ppCubes CurProbes [ppMaxSubdiv];
00617
00619 ppCubes Failed [ppMaxSubdiv];
00620
00623 ppCubes Successful [ppMaxSubdiv];
00624
00626 ppCubes Waiting [ppMaxSubdiv];
00627
00629 ppCubes CurBoxes [ppMaxSubdiv];
00630
00631
00632
00636 bool FindMinCube
00637 (const typename mwSubCoordinator<dim,coord>::ppCubes tab [],
00638 const typename mwSubCoordinator<dim,coord>::ppCubes sent [],
00639 int minlevel, int maxlevel, int &level,
00640 typename mwSubCoordinator<dim,coord>::ppCube &q);
00641
00644 static typename mwSubCoordinator<dim,coord>::ppCube UpLevel
00645 (const typename mwSubCoordinator<dim,coord>::ppCube &q);
00646
00649 static typename mwSubCoordinator<dim,coord>::ppCube UpLevel
00650 (const typename mwSubCoordinator<dim,coord>::ppCube &box,
00651 const typename mwSubCoordinator<dim,coord>::ppCube &corner);
00652
00656 static typename mwSubCoordinator<dim,coord>::ppCube DownLevel
00657 (const typename mwSubCoordinator<dim,coord>::ppCube &q);
00658
00663 int Contained (const typename mwSubCoordinator<dim,coord>::ppCube &q,
00664 int level,
00665 const typename mwSubCoordinator<dim,coord>::ppCubes tab [],
00666 int minlevel) const;
00667
00668
00669
00671 void NegativeProbe (const ppCube &q, int level);
00672
00674 void GoodProbe (const ppCube &q, int level);
00675
00677 void FailedBox (const ppCube &q, int level);
00678
00680 void SuccessfulBox (const ppCube &q, int level);
00681
00682
00683
00685 double paramLeft [dim];
00686
00688 double paramRight [dim];
00689
00692 int inilevel;
00693
00695 int maxlevel;
00696
00698 mwIniProbes<dim,coord> iniProbes;
00699
00702 ppCubes iniProcessed;
00703
00704
00705
00707 std::ofstream f;
00708
00710 bool flushfile;
00711
00713 int ReadResults (std::istream &in);
00714
00715
00716
00718 int current;
00719
00721 multitable<ppPack> sent;
00722
00724 int sentlen;
00725
00726
00727
00729 int countNegative;
00730
00732 int countGood;
00733
00735 int countFailed;
00736
00739 int countSuccessful;
00740
00741 };
00742
00743
00744
00745 template <int dim, class coord>
00746 const int mwSubCoordinator<dim,coord>::ppMaxSubdiv;
00747
00748
00749
00750 template <int dim, class coord>
00751 inline mwSubCoordinator<dim,coord>::mwSubCoordinator ()
00752 {
00753 return;
00754 }
00755
00756 template <int dim, class coord>
00757 mwSubCoordinator<dim,coord>::mwSubCoordinator (const char *filename,
00758 int _inilevel, int _maxlevel, bool _flushfile,
00759 const double *_paramLeft, const double *_paramRight):
00760 inilevel ((_inilevel < 2) ? 2 : _inilevel),
00761 maxlevel ((_maxlevel <= inilevel) ? (inilevel + 1) : _maxlevel),
00762 iniProbes (inilevel),
00763 flushfile (_flushfile),
00764 current (0), sentlen (0),
00765 countNegative (0), countGood (0),
00766 countFailed (0), countSuccessful (0)
00767 {
00768
00769 if (!filename || !*filename)
00770 sout << "WARNING: No results file name given. "
00771 "Computation results will not be saved.\n";
00772
00773
00774 if (maxlevel > ppMaxSubdiv)
00775 {
00776 sout << "WARNING: Max subdivision level decreased from " <<
00777 maxlevel << " to " << ppMaxSubdiv << ".\n";
00778 maxlevel = ppMaxSubdiv;
00779 if (inilevel >= maxlevel)
00780 inilevel = maxlevel - 1;
00781 }
00782
00783
00784 if (filename && *filename)
00785 {
00786 std::ifstream in (filename);
00787 if (!in)
00788 sout << "Note: Could not open the results file. "
00789 "Any previous results will be ignored.\n";
00790 else
00791 {
00792 this -> ReadResults (in);
00793 in. close ();
00794 }
00795 }
00796
00797
00798 if (filename && *filename)
00799 {
00800 f. open (filename, std::ios::out | std::ios::app);
00801 f << "; Started on " << currenttime ();
00802 if (flushfile)
00803 f << std::flush;
00804 }
00805
00806
00807 for (int i = 0; i < dim; ++ i)
00808 {
00809 paramLeft [i] = _paramLeft [i];
00810 paramRight [i] = _paramRight [i];
00811 }
00812
00813 return;
00814 }
00815
00816 template <int dim, class coord>
00817 inline mwSubCoordinator<dim,coord>::~mwSubCoordinator ()
00818 {
00819 f << "; A total of " << (countNegative + countGood) <<
00820 " probes and " << (countFailed + countSuccessful) <<
00821 " boxes have been processed.\n";
00822 f << "; The verification was negative for " << countNegative <<
00823 " probes, and " << countGood << " probes were good.\n";
00824 f << "; The verification failed for " << countFailed <<
00825 " boxes, and was successful for " << countSuccessful <<
00826 " boxes.\n";
00827 f << "; Finished on " << currenttime ();
00828 f << "; ---------------------------------------------------\n";
00829 f. close ();
00830 return;
00831 }
00832
00833
00834
00835 template <int dim, class coord>
00836 inline bool mwSubCoordinator<dim,coord>::FindMinCube
00837 (const typename mwSubCoordinator<dim,coord>::ppCubes tab [],
00838 const typename mwSubCoordinator<dim,coord>::ppCubes sent [],
00839 int minlevel, int maxlevel,
00840 int &level, typename mwSubCoordinator<dim,coord>::ppCube &q)
00841 {
00842 for (int l = minlevel; l < maxlevel; ++ l)
00843 {
00844 const ppCubes &theSet = tab [l];
00845 const ppCubes &sentSet = sent [l];
00846 int number = theSet. size ();
00847 for (int i = number - 1; i >= 0; -- i)
00848 {
00849 const ppCube &c = theSet [i];
00850 if (!sentSet. check (c))
00851 {
00852 level = l;
00853 q = c;
00854 return true;
00855 }
00856 }
00857 }
00858 return false;
00859 }
00860
00861 template <int dim, class coord>
00862 int mwSubCoordinator<dim,coord>::Prepare (mwData &data)
00863 {
00864
00865 ppPack &pack = sent [sentlen];
00866
00867
00868
00869 bool iniProbe = false;
00870 while (iniProbes. available ())
00871 {
00872 pack = ppPack (current, iniProbes. get (), inilevel, false);
00873 if (iniProcessed. check (pack. q))
00874 {
00875 iniProcessed. remove (pack. q);
00876 continue;
00877 }
00878 else
00879 {
00880 iniProbe = true;
00881 break;
00882 }
00883 }
00884
00885
00886 if (!iniProbe)
00887 {
00888
00889 int levelT = 0;
00890 ppCube cubeT;
00891 bool foundT = this -> FindMinCube (Test, CurProbes,
00892 inilevel, maxlevel, levelT, cubeT);
00893
00894
00895 int levelW = 0;
00896 ppCube cubeW;
00897 bool foundW = this -> FindMinCube (Waiting, CurBoxes,
00898 inilevel, maxlevel, levelW, cubeW);
00899
00900
00901 if (!foundT && !foundW)
00902 return mwNoData;
00903
00904
00905 if (foundT && (!foundW || (levelT <= levelW)))
00906 {
00907 pack = ppPack (current, cubeT, levelT, false);
00908 CurProbes [levelT]. add (cubeT);
00909 }
00910
00911 else
00912 {
00913 pack = ppPack (current, cubeW, levelW, true);
00914 CurBoxes [levelW]. add (cubeW);
00915 }
00916 }
00917
00918
00919 coord c [ppMaxDim];
00920 pack. q. coord (c);
00921 int fullSize = 1 << pack. level;
00922 double left [ppMaxDim];
00923 double right [ppMaxDim];
00924 for (int i = 0; i < dim; ++ i)
00925 {
00926
00927 left [i] = mwSubdivPoint (paramLeft [i], paramRight [i],
00928 c [i], fullSize);
00929
00930
00931 if (pack. full)
00932 {
00933
00934 right [i] = mwSubdivPoint (paramLeft [i],
00935 paramRight [i], c [i] + 1, fullSize);
00936
00937
00938
00939
00940 if (left [i] == right [i])
00941 {
00942
00943 f << "; The resolution of representable "
00944 "numbers exceeded.\n; Decreasing "
00945 "max level from " << maxlevel <<
00946 " to " << pack. level << ".\n";
00947 if (flushfile)
00948 f << std::flush;
00949
00950
00951 sout << "WARNING: The resolution of "
00952 "representable numbers exceeded.\n"
00953 "Decreasing max level from " <<
00954 maxlevel << " to " << pack. level <<
00955 ".\n";
00956
00957
00958 maxlevel = pack. level;
00959 return mwNoData;
00960 }
00961 }
00962 }
00963
00964
00965 f << "+ " << pack. num;
00966 for (int i = 0; i < dim; ++ i)
00967 {
00968 f << (i ? "x[" : " [") << left [i];
00969 if (pack. full)
00970 f << "," << right [i];
00971 f << "]";
00972 }
00973 f << ".\n";
00974 if (flushfile)
00975 f << std::flush;
00976
00977
00978 data << pack. num;
00979
00980
00981 data << pack. level;
00982
00983
00984 data << pack. full;
00985
00986
00987 for (int i = 0; i < dim; ++ i)
00988 {
00989 data << left [i];
00990 if (pack. full)
00991 data << right [i];
00992 }
00993
00994
00995 const int dataEndMarker = 13;
00996 data << dataEndMarker;
00997
00998
00999 sout << "+ " << pack. num << ".\n";
01000
01001
01002 ++ current;
01003 ++ sentlen;
01004
01005 return mwOk;
01006 }
01007
01008
01009
01010 template <int dim, class coord>
01011 typename mwSubCoordinator<dim,coord>::ppCube
01012 mwSubCoordinator<dim,coord>::UpLevel
01013 (const typename mwSubCoordinator<dim,coord>::ppCube &q)
01014 {
01015 coord c [dim];
01016 q. coord (c);
01017 for (int i = 0; i < dim; ++ i)
01018 c [i] <<= 1;
01019 return ppCube (c, dim);
01020 }
01021
01022 template <int dim, class coord>
01023 typename mwSubCoordinator<dim,coord>::ppCube
01024 mwSubCoordinator<dim,coord>::UpLevel
01025 (const typename mwSubCoordinator<dim,coord>::ppCube &box,
01026 const typename mwSubCoordinator<dim,coord>::ppCube &corner)
01027 {
01028 coord cBox [dim];
01029 box. coord (cBox);
01030 coord cCorner [dim];
01031 corner. coord (cCorner);
01032 for (int i = 0; i < dim; ++ i)
01033 {
01034 if (cBox [i] == cCorner [i])
01035 cBox [i] <<= 1;
01036 else
01037 cBox [i] = (cBox [i] << 1) + 1;
01038 }
01039 return ppCube (cBox, dim);
01040 }
01041
01042 template <int dim, class coord>
01043 typename mwSubCoordinator<dim,coord>::ppCube
01044 mwSubCoordinator<dim,coord>::DownLevel
01045 (const typename mwSubCoordinator<dim,coord>::ppCube &q)
01046 {
01047 coord c [dim];
01048 q. coord (c);
01049 for (int i = 0; i < dim; ++ i)
01050 c [i] >>= 1;
01051 return ppCube (c, dim);
01052 }
01053
01054 template <int dim, class coord>
01055 int mwSubCoordinator<dim,coord>::Contained
01056 (const typename mwSubCoordinator<dim,coord>::ppCube &q, int level,
01057 const typename mwSubCoordinator<dim,coord>::ppCubes tab [],
01058 int minlevel) const
01059 {
01060
01061 if (tab [level]. check (q))
01062 return level;
01063
01064
01065 if (minlevel < inilevel)
01066 minlevel = inilevel;
01067 ppCube box = q;
01068 while (-- level > minlevel)
01069 {
01070 box = DownLevel (box);
01071 if (tab [level]. check (box))
01072 return level;
01073 }
01074
01075 return 0;
01076 }
01077
01078 template <int dim, class coord>
01079 void mwSubCoordinator<dim,coord>::NegativeProbe (const ppCube &q, int level)
01080 {
01081
01082 Negative [level]. add (q);
01083 sbug << "@ NegProbe [" << level << "]: " << q << "\n";
01084
01085
01086
01087 mwBoxes<dim,coord> boxes (q);
01088 while (boxes. available ())
01089 {
01090
01091 ppCube box = boxes. get ();
01092
01093
01094
01095 if (Waiting [level]. check (box) &&
01096 !CurBoxes [level]. check (box))
01097 {
01098 sbug << "# FailedBox [" << level << "]: " <<
01099 box << "\n";
01100 Waiting [level]. remove (box);
01101 FailedBox (box, level);
01102 }
01103 }
01104
01105 return;
01106 }
01107
01108 template <int dim, class coord>
01109 void mwSubCoordinator<dim,coord>::GoodProbe (const ppCube &q, int level)
01110 {
01111
01112 if (Good [level]. check (q))
01113 {
01114 sbug << "@ GoodKnown [" << level << "]: " << q << "\n";
01115 return;
01116 }
01117
01118
01119 Good [level]. add (q);
01120 sbug << "@ GoodProbe [" << level << "]: " << q << "\n";
01121
01122
01123 if (level + 1 == maxlevel)
01124 return;
01125
01126
01127 ppCube probe = UpLevel (q);
01128 Good [level + 1]. add (probe);
01129 sbug << "+ GoodProbe [" << (level + 1) << "]: " << probe << "\n";
01130
01131
01132 mwBoxes<dim,coord> boxes (probe);
01133 while (boxes. available ())
01134 {
01135
01136
01137 ppCube box = boxes. get ();
01138 if (!Contained (box, level + 1, Successful, 0))
01139 {
01140
01141 Waiting [level + 1]. add (box);
01142 sbug << "+ Waiting [" << (level + 1) << "]: " <<
01143 box << "\n";
01144 }
01145 }
01146
01147 return;
01148 }
01149
01150 template <int dim, class coord>
01151 void mwSubCoordinator<dim,coord>::FailedBox (const ppCube &q, int level)
01152 {
01153
01154 Failed [level]. add (q);
01155 sbug << "@ FailedBox [" << level << "]: " << q << "\n";
01156
01157
01158 if (level + 1 == maxlevel)
01159 return;
01160
01161
01162 mwCorners<dim,coord> corners (q);
01163 while (corners. available ())
01164 {
01165
01166 ppCube c = corners. get ();
01167
01168
01169 if (Negative [level]. check (c))
01170 continue;
01171
01172
01173
01174 if (!Good [level]. check (c))
01175 {
01176 Test [level]. add (c);
01177 sbug << "+ Test [" << level << "]: " << c << "\n";
01178 continue;
01179 }
01180
01181
01182
01183
01184 ppCube box = UpLevel (q, c);
01185 if (!Successful [level + 1]. check (box) &&
01186 !Failed [level + 1]. check (box))
01187 {
01188 Waiting [level + 1]. add (box);
01189 sbug << "+ Waiting [" << (level + 1) << "]: " <<
01190 box << "\n";
01191 }
01192
01193
01194 ppCube probe = UpLevel (c);
01195 Good [level + 1]. add (probe);
01196 sbug << "+ Good [" << (level + 1) << "]: " << probe << "\n";
01197 }
01198
01199 return;
01200 }
01201
01202 template <int dim, class coord>
01203 void mwSubCoordinator<dim,coord>::SuccessfulBox (const ppCube &q, int level)
01204 {
01205
01206 if (Successful [level]. check (q))
01207 {
01208 sbug << "@ SuccessKnown [" << level << "]: " << q << "\n";
01209 return;
01210 }
01211
01212
01213
01214 if (Contained (q, level, Successful, 0))
01215 {
01216 sbug << "@ SuccessSubset [" << level << "]: " << q << "\n";
01217 return;
01218 }
01219
01220
01221 Successful [level]. add (q);
01222 sbug << "@ SuccessBox [" << level << "]: " << q << "\n";
01223
01224
01225 mwCorners<dim,coord> corners (q);
01226 while (corners. available ())
01227 {
01228
01229 ppCube c = corners. get ();
01230
01231
01232 if (Test [level]. check (c))
01233 {
01234 Test [level]. remove (c);
01235 sbug << "- Test [" << level << "]: " << c << "\n";
01236 }
01237
01238
01239 ppCube cornerBox = UpLevel (q, c);
01240 if (Waiting [level + 1]. check (cornerBox))
01241 {
01242 Waiting [level + 1]. remove (cornerBox);
01243 sbug << "- Waiting [" << (level + 1) << "]: " <<
01244 cornerBox << "\n";
01245
01246
01247
01248
01249
01250 }
01251
01252
01253 if (Good [level]. check (c))
01254 continue;
01255
01256
01257 Good [level]. add (c);
01258 sbug << "+ Good [" << level << "]: " << c << "\n";
01259
01260
01261 ppCube probe = UpLevel (c);
01262 Good [level + 1]. add (probe);
01263 sbug << "+ Good [" << (level + 1) << "]: " << probe << "\n";
01264
01265
01266 mwBoxes<dim,coord> boxes (probe);
01267 while (boxes. available ())
01268 {
01269
01270 ppCube box = boxes. get ();
01271
01272
01273
01274 if (!Contained (box, level + 1, Successful, 0))
01275 {
01276 Waiting [level + 1]. add (box);
01277 sbug << "+ Waiting [" << (level + 1) <<
01278 "]: " << box << "\n";
01279 }
01280 }
01281 }
01282
01283 return;
01284 }
01285
01286 template <int dim, class coord>
01287 int mwSubCoordinator<dim,coord>::Accept (mwData &data)
01288 {
01289
01290 int n = 0;
01291 data >> n;
01292
01293
01294 int result = 0;
01295 data >> result;
01296
01297
01298 sout << "* " << n << " " << result << ".\n";
01299
01300
01301 int pos = 0;
01302 while ((pos < sentlen) && (sent [pos]. num != n))
01303 ++ pos;
01304 if (pos >= sentlen)
01305 {
01306 sout << "ERROR: Wrong data pack number received "
01307 "from a worker.\n";
01308 return mwError;
01309 }
01310 const ppPack &pack = sent [pos];
01311
01312
01313 f << (pack. full ? "* " : "@ ") << n << " " << result <<
01314 " " << pack. level << " " << pack. q << ".\n";
01315 if (flushfile)
01316 f << std::flush;
01317
01318
01319 const ppCube &q = pack. q;
01320 int level = pack. level;
01321 bool full = pack. full;
01322
01323
01324 if (full)
01325 {
01326 CurBoxes [level]. remove (q);
01327 Waiting [level]. remove (q);
01328 if (result)
01329 {
01330 ++ countSuccessful;
01331 SuccessfulBox (q, level);
01332 }
01333 else
01334 {
01335 ++ countFailed;
01336 FailedBox (q, level);
01337 }
01338 }
01339 else
01340 {
01341 CurProbes [level]. remove (q);
01342 Test [level]. remove (q);
01343 if (result)
01344 {
01345 ++ countGood;
01346 GoodProbe (q, level);
01347 }
01348 else
01349 {
01350 ++ countNegative;
01351 NegativeProbe (q, level);
01352 }
01353 }
01354
01355
01356 -- sentlen;
01357 if (pos != sentlen)
01358 sent [pos] = sent [sentlen];
01359
01360 return mwOk;
01361 }
01362
01363 template <int dim, class coord>
01364 int mwSubCoordinator<dim,coord>::Reject (mwData &data)
01365 {
01366
01367 int n = 0;
01368 data >> n;
01369
01370
01371 sout << "!!! Data no. " << n << " rejected.\n";
01372
01373 return mwError;
01374 }
01375
01376
01377
01378 template <int dim, class coord>
01379 int mwSubCoordinator<dim,coord>::ReadResults (std::istream &in)
01380 {
01381 ignorecomments (in);
01382 while (!in. eof ())
01383 {
01384
01385 int ch = in. get ();
01386
01387
01388 if ((ch != '*') && (ch != '@'))
01389 {
01390 ignoreline (in);
01391 ignorecomments (in);
01392 continue;
01393 }
01394
01395
01396 if ((ch == '*') || (ch == '@'))
01397 {
01398 int n = -1;
01399 in >> n;
01400 if (n < 0)
01401 break;
01402 }
01403
01404
01405 int result = -1;
01406 if ((ch == '*') || (ch == '@'))
01407 {
01408 in >> result;
01409 if (result < 0)
01410 break;
01411 }
01412
01413
01414 int level = -1;
01415 in >> level;
01416 if (level < 0)
01417 break;
01418
01419
01420 ppCube q;
01421 in >> q;
01422
01423
01424 if (in. peek () != '.')
01425 break;
01426
01427
01428 ignoreline (in);
01429 ignorecomments (in);
01430
01431
01432 if (ch == '*')
01433 {
01434 Waiting [level]. remove (q);
01435 if (result)
01436 SuccessfulBox (q, level);
01437 else
01438 FailedBox (q, level);
01439 }
01440 else if (ch == '@')
01441 {
01442 if (level == inilevel)
01443 iniProcessed. add (q);
01444 else
01445 Test [level]. remove (q);
01446 if (result)
01447 GoodProbe (q, level);
01448 else
01449 NegativeProbe (q, level);
01450 }
01451 }
01452
01453 return 0;
01454 }
01455
01456
01457
01458
01459
01460
01464 template <int dim, class coord>
01465 int mwSubdivMain (int argc, char *argv [],
01466 const char *title, const char *helpinfo,
01467 int defaultPortNumber, int controlNumber,
01468 const double *paramLeft, const double *paramRight,
01469 int minSubdivLevel, fcompute compute)
01470 {
01471 const char *arginfo = "\
01472 Command line arguments (at least '-w' or '-m N' must be specified):\n\
01473 -w [port] - run as a worker (by default the program runs as a coordinator),\n\
01474 -c [port] - run as a coordinator only (don't process any data locally),\n\
01475 -p port - set the port number for the multi-work communication,\n\
01476 -k - keep workers waiting after the computations have been completed,\n\
01477 computer:port - use this connection at start-up (can be repeated),\n\
01478 -s FILE - save the workers' list to this file (default: mwsubdiv.txt),\n\
01479 -r FILE - retrieve the workers' list from this file (def: mwsubdiv.txt),\n\
01480 -f filename - results file (new results will be appended); coord only!\n\
01481 --flush - flush the results file very frequently (slows down the program),\n\
01482 -i N - set the initial subdivision level (some minimum is enforced),\n\
01483 -m N - set the maximal subdivision level (default: inilevel + 2),\n\
01484 -q - quit all the workers who are waiting (provide addresses or use -r),\n\
01485 --quiet - do not display any messages on the standard output,\n\
01486 --log filename - save the console output to the given file,\n\
01487 --help - show this brief help information and exit.\n\
01488 For more information ask the author at http://www.PawelPilarczyk.com/.";
01489
01490
01491 char *retrieveworkers = 0;
01492 char *saveworkers = 0;
01493 const int maxaddr = 1024;
01494 char *addr [maxaddr];
01495 int naddr = 0;
01496 int portnum = -1;
01497 int workport = -1;
01498 int coordport = -1;
01499 bool keepworkers = false;
01500 bool quitworkers = false;
01501 char *filename = 0;
01502 int inilevel = 0;
01503 int maxlevel = 0;
01504 bool flushfile = false;
01505
01506
01507 arguments a;
01508 arg (a, 0, addr, naddr, maxaddr);
01509 arg (a, "r", retrieveworkers, "mwsubdiv.txt");
01510 arg (a, "s", saveworkers, "mwsubdiv.txt");
01511 arg (a, "f", filename);
01512 arg (a, "i", inilevel);
01513 arg (a, "m", maxlevel);
01514 arg (a, "w", workport, defaultPortNumber);
01515 arg (a, "p", portnum);
01516 arg (a, "c", coordport, defaultPortNumber);
01517 argswitch (a, "k", keepworkers, true);
01518 argswitch (a, "q", quitworkers, true);
01519 argswitch (a, "-flush", flushfile, true);
01520 arghelp (a);
01521
01522 argstreamprepare (a);
01523 int argresult = a. analyze (argc, argv);
01524 argstreamset ();
01525
01526
01527 if (argresult >= 0)
01528 sout << title << '\n';
01529
01530
01531 if (argresult < 0)
01532 {
01533 sout << "Call with '--help' for help.\n";
01534 return 2;
01535 }
01536
01537
01538
01539 int port = defaultPortNumber;
01540 bool localwork = (coordport < 0);
01541 if (coordport >= 0)
01542 port = coordport;
01543 bool worker = (workport >= 0);
01544 if (workport >= 0)
01545 port = workport;
01546 if (portnum >= 0)
01547 port = portnum;
01548
01549
01550 if (!maxlevel && !worker && !quitworkers)
01551 argresult = 1;
01552
01553
01554 if (argresult > 0)
01555 {
01556 sout << helpinfo << '\n' << arginfo << '\n';
01557 return 1;
01558 }
01559
01560
01561 try
01562 {
01563
01564 program_time = "Aborted after:";
01565 program_time = 1;
01566
01567
01568 if (quitworkers)
01569 {
01570
01571 mwSubCoordinator<dim,coord> c;
01572
01573
01574 c. Port (port);
01575 c. ControlNumber (controlNumber);
01576
01577
01578 if (retrieveworkers)
01579 c. Load (retrieveworkers);
01580 for (int i = 0; i < naddr; ++ i)
01581 c. Add (addr [i]);
01582
01583
01584 sout << "Quitting workers... ";
01585 c. QuitWorkers ();
01586 sout << "Done.\n";
01587 }
01588
01589
01590 else if (worker)
01591 {
01592
01593 mwSubWorker<dim,coord> w (compute);
01594
01595
01596 w. Port (port);
01597 w. ControlNumber (controlNumber);
01598 for (int i = 0; i < naddr; ++ i)
01599 w. Add (addr [i]);
01600
01601
01602 sout << "Running as a worker...\n";
01603 int result = w. Work ();
01604 if (result == mwOk)
01605 sout << "Work completed successfully.\n";
01606 else
01607 sout << "Could not work - probably "
01608 "an error occurred.\n";
01609 }
01610
01611
01612 else
01613 {
01614
01615 if (inilevel <= minSubdivLevel)
01616 inilevel = minSubdivLevel;
01617 if (maxlevel <= inilevel)
01618 maxlevel = inilevel + 2;
01619
01620
01621 mwSubWorker<dim,coord> w (compute);
01622 mwSubCoordinator<dim,coord> c (filename, inilevel,
01623 maxlevel, flushfile, paramLeft, paramRight);
01624
01625
01626 c. KeepWorkers (keepworkers);
01627 c. Port (port);
01628 c. ControlNumber (controlNumber);
01629 for (int i = 0; i < naddr; ++ i)
01630 c. Add (addr [i]);
01631 if (retrieveworkers)
01632 c. Load (retrieveworkers);
01633
01634
01635 sout << "Running as a coordinator...\n";
01636 int result = c. Coordinate (localwork ? &w : 0);
01637 if (result == mwOk)
01638 sout << "The task completed successfully.\n";
01639 else
01640 sout << "Could not coordinate - probably "
01641 "an error occurred.\n";
01642
01643
01644 if (saveworkers)
01645 c. SaveWorkers (saveworkers);
01646 }
01647
01648
01649 program_time = "Total time used:";
01650
01651
01652 return 0;
01653 }
01654 catch (const char *msg)
01655 {
01656 sout << "ERROR: " << msg << '\n';
01657 return -1;
01658 }
01659 catch (const std::exception &e)
01660 {
01661 sout << "ERROR: " << e. what () << '\n';
01662 return -1;
01663 }
01664 catch (...)
01665 {
01666 sout << "ABORT: An unknown error occurred.\n";
01667 return -1;
01668 }
01669 }
01670
01671
01672 }
01673 }
01674
01675 #endif // _CHOMP_MULTIWORK_MWSUBDIV_H_
01676
01678