Generated on Tue Apr 18 10:22:10 2017 for Gecode by doxygen 1.6.3

pbs.hpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2015
00008  *
00009  *  Last modified:
00010  *     $Date: 2016-04-19 17:19:45 +0200 (Tue, 19 Apr 2016) $ by $Author: schulte $
00011  *     $Revision: 14967 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  *
00036  */
00037 
00038 namespace Gecode { namespace Search { namespace Meta { namespace Parallel {
00039 
00040 
00041   forceinline
00042   CollectAll::CollectAll(void)
00043     : solutions(heap) {}
00044   forceinline bool
00045   CollectAll::add(Space* s, Slave<CollectAll>*) {
00046     solutions.push(s);
00047     return true;
00048   }
00049   forceinline bool
00050   CollectAll::constrain(const Space& b) {
00051     (void) b;
00052     return false;
00053   }
00054   forceinline bool
00055   CollectAll::empty(void) const {
00056     return solutions.empty();
00057   }
00058   forceinline Space*
00059   CollectAll::get(Slave<CollectAll>*&) {
00060     return solutions.pop();
00061   }
00062   forceinline
00063   CollectAll::~CollectAll(void) {
00064   }
00065 
00066 
00067   forceinline
00068   CollectBest::CollectBest(void)
00069     : b(NULL), reporter(NULL) {}
00070   forceinline bool
00071   CollectBest::add(Space* s, Slave<CollectBest>* r) {
00072     if (b != NULL) {
00073       b->constrain(*s);
00074       if (b->status() == SS_FAILED) {
00075         delete b;
00076       } else {
00077         delete s;
00078         return false;
00079       }
00080     }
00081     b = s;
00082     reporter = r;
00083     return true;
00084   }
00085   forceinline bool
00086   CollectBest::constrain(const Space& s) {
00087     if (b != NULL) {
00088       b->constrain(s);
00089       if (b->status() == SS_FAILED) {
00090         delete b;
00091       } else {
00092         return false;
00093       }
00094     }
00095     b = s.clone(false);
00096     reporter = NULL;
00097     return true;
00098   }
00099   forceinline bool
00100   CollectBest::empty(void) const {
00101     return reporter == NULL;
00102   }
00103   forceinline Space*
00104   CollectBest::get(Slave<CollectBest>*& r) {
00105     assert(!empty());
00106     r = reporter;
00107     reporter = NULL;
00108     return b->clone(false);
00109   }
00110   forceinline
00111   CollectBest::~CollectBest(void) {
00112     delete b;
00113   }
00114 
00115 
00116   forceinline
00117   PortfolioStop::PortfolioStop(Stop* so0)
00118     : so(so0), tostop(NULL) {}
00119 
00120   forceinline void
00121   PortfolioStop::share(volatile bool* ts) {
00122     tostop = ts;
00123   }
00124 
00125 
00126   template<class Collect>
00127   forceinline
00128   Slave<Collect>::Slave(PBS<Collect>* m, Engine* s, Stop* so)
00129     : Support::Runnable(false), master(m), slave(s), stop(so) {}
00130   template<class Collect>
00131   forceinline Statistics
00132   Slave<Collect>::statistics(void) const {
00133     return slave->statistics();
00134   }
00135   template<class Collect>
00136   forceinline bool
00137   Slave<Collect>::stopped(void) const {
00138     return slave->stopped();
00139   }
00140   template<class Collect>
00141   forceinline void
00142   Slave<Collect>::constrain(const Space& b) {
00143     slave->constrain(b);
00144   }
00145   template<class Collect>
00146   Slave<Collect>::~Slave(void) {
00147     delete slave;
00148     delete stop;
00149   }
00150 
00151 
00152 
00153   template<class Collect>
00154   forceinline
00155   PBS<Collect>::PBS(Engine** engines, Stop** stops, unsigned int n,
00156                     const Statistics& stat0)
00157     : stat(stat0), slaves(heap.alloc<Slave<Collect>*>(n)), n_slaves(n),
00158       slave_stop(false), tostop(false), n_busy(0) {
00159     // Initialize slaves
00160     for (unsigned int i=n_slaves; i--; ) {
00161       slaves[i] = new Slave<Collect>(this,engines[i],stops[i]);
00162       static_cast<PortfolioStop*>(stops[i])->share(&tostop);
00163     }
00164   }
00165 
00166   template<class Collect>
00167   forceinline bool
00168   PBS<Collect>::report(Slave<Collect>* slave, Space* s) {
00169     // If b is false the report should be repeated (solution was worse)
00170     bool b = true;
00171     m.acquire();
00172     if (s != NULL) {
00173       b = solutions.add(s,slave);
00174       if (b)
00175         tostop = true;
00176     } else if (slave->stopped()) {
00177       if (!tostop)
00178         slave_stop = true;
00179     } else {
00180       // Delete slave from slaves
00181       stat += slave->statistics();
00182       // Do not actually delete, the thread should do that upon termination
00183       slave->todelete(true);
00184       unsigned int i=0;
00185       while (slaves[i] != slave)
00186         i++;
00187       assert(i < n_slaves);
00188       slaves[i] = slaves[--n_slaves];
00189     }
00190     if (b) {
00191       if (--n_busy == 0)
00192         idle.signal();
00193     }
00194     m.release();
00195     return b;
00196   }
00197 
00198   template<class Collect>
00199   void
00200   Slave<Collect>::run(void) {
00201     Space* s;
00202     do {
00203       s = slave->next();
00204     } while (!master->report(this,s));
00205   }
00206 
00207   template<class Collect>
00208   Space*
00209   PBS<Collect>::next(void) {
00210     m.acquire();
00211     if (solutions.empty()) {
00212       // Clear all
00213       tostop = false;
00214       slave_stop = false;
00215 
00216       // Invariant: all slaves are idle!
00217       assert(n_busy == 0);
00218       assert(!tostop);
00219 
00220       if (n_slaves > 0) {
00221         // Run all slaves
00222         n_busy = n_slaves;
00223         for (unsigned int i=n_slaves; i--; )
00224           Support::Thread::run(slaves[i]);
00225         m.release();
00226         // Wait for all slaves to become idle
00227         idle.wait();
00228         m.acquire();
00229       }
00230     }
00231 
00232     // Invariant all slaves are idle!
00233     assert(n_busy == 0);
00234 
00235     Space* s;
00236 
00237     // Process solutions
00238     if (solutions.empty()) {
00239       s = NULL;
00240     } else {
00241       Slave<Collect>* r;
00242       s = solutions.get(r);
00243       if (Collect::best)
00244         for (unsigned int i=n_slaves; i--; )
00245           if (slaves[i] != r)
00246             slaves[i]->constrain(*s);
00247     }
00248 
00249     m.release();
00250     return s;
00251   }
00252 
00253   template<class Collect>
00254   bool
00255   PBS<Collect>::stopped(void) const {
00256     return slave_stop;
00257   }
00258 
00259   template<class Collect>
00260   Statistics
00261   PBS<Collect>::statistics(void) const {
00262     Statistics s(stat);
00263     for (unsigned int i=n_slaves; i--; )
00264       s += slaves[i]->statistics();
00265     return s;
00266   }
00267 
00268   template<class Collect>
00269   void
00270   PBS<Collect>::constrain(const Space& b) {
00271     if (!Collect::best)
00272       throw NoBest("PBS::constrain");
00273     if (solutions.constrain(b)) {
00274       // The solution is better
00275       for (unsigned int i=n_slaves; i--; )
00276         slaves[i]->constrain(b);
00277     }
00278   }
00279 
00280   template<class Collect>
00281   PBS<Collect>::~PBS(void) {
00282     for (unsigned int i=n_slaves; i--; )
00283       delete slaves[i];
00284     // Note that n_slaves might be different now!
00285     heap.rfree(slaves);
00286   }
00287 
00288 }}}}
00289 
00290 // STATISTICS: search-meta