00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <cmath>
00035 #include <algorithm>
00036
00037 namespace Gecode { namespace Search {
00038
00040 template<class T, template<class> class E>
00041 class PbsBuilder : public Builder {
00042 using Builder::opt;
00043 public:
00045 PbsBuilder(const Options& opt);
00047 virtual Engine* operator() (Space* s) const;
00048 };
00049
00050 template<class T, template<class> class E>
00051 inline
00052 PbsBuilder<T,E>::PbsBuilder(const Options& opt)
00053 : Builder(opt,E<T>::best) {}
00054
00055 template<class T, template<class> class E>
00056 Engine*
00057 PbsBuilder<T,E>::operator() (Space* s) const {
00058 return build<T,PBS<T,E> >(s,opt);
00059 }
00060
00061 }}
00062
00063 #include <gecode/search/seq/dead.hh>
00064
00065 namespace Gecode { namespace Search { namespace Seq {
00066
00068 GECODE_SEARCH_EXPORT Stop*
00069 pbsstop(Stop* so);
00070
00072 GECODE_SEARCH_EXPORT Engine*
00073 pbsengine(Engine** slaves, Stop** stops, unsigned int n_slaves,
00074 const Statistics& stat, const Search::Options& opt, bool best);
00075
00076 }}}
00077
00078 namespace Gecode { namespace Search { namespace Par {
00079
00081 GECODE_SEARCH_EXPORT Stop*
00082 pbsstop(Stop* so);
00083
00085 GECODE_SEARCH_EXPORT Engine*
00086 pbsengine(Engine** slaves, Stop** stops, unsigned int n_slaves,
00087 const Statistics& stat, bool best);
00088
00089 }}}
00090
00091 namespace Gecode { namespace Search {
00092
00093 template<class T, template<class> class E>
00094 Engine*
00095 pbsseq(T* master, const Search::Statistics& stat, Options& opt) {
00096 Stop* stop = opt.stop;
00097 Region r;
00098
00099
00100 opt.threads = std::max(floor(opt.threads /
00101 static_cast<double>(opt.assets)),1.0);
00102
00103 unsigned int n_slaves = opt.assets;
00104 Engine** slaves = r.alloc<Engine*>(n_slaves);
00105 Stop** stops = r.alloc<Stop*>(n_slaves);
00106
00107 WrapTraceRecorder::engine(opt.tracer,
00108 SearchTracer::EngineType::PBS, n_slaves);
00109
00110 for (unsigned int i=0U; i<n_slaves; i++) {
00111 opt.stop = stops[i] = Seq::pbsstop(stop);
00112 Space* slave = (i == n_slaves-1) ?
00113 master : master->clone();
00114 (void) slave->slave(i);
00115 slaves[i] = build<T,E>(slave,opt);
00116 }
00117
00118 return Seq::pbsengine(slaves,stops,n_slaves,stat,opt,E<T>::best);
00119 }
00120
00121 template<class T, template<class> class E>
00122 Engine*
00123 pbsseq(T* master, SEBs& sebs,
00124 const Search::Statistics& stat, Options& opt, bool best) {
00125 Region r;
00126
00127 int n_slaves = sebs.size();
00128 Engine** slaves = r.alloc<Engine*>(n_slaves);
00129 Stop** stops = r.alloc<Stop*>(n_slaves);
00130
00131 WrapTraceRecorder::engine(opt.tracer,
00132 SearchTracer::EngineType::PBS, n_slaves);
00133
00134 for (int i=0; i<n_slaves; i++) {
00135
00136 stops[i] = Seq::pbsstop(sebs[i]->options().stop);
00137 sebs[i]->options().stop = stops[i];
00138 sebs[i]->options().clone = false;
00139 Space* slave = (i == n_slaves-1) ?
00140 master : master->clone();
00141 (void) slave->slave(i);
00142 slaves[i] = (*sebs[i])(slave);
00143 delete sebs[i];
00144 }
00145
00146 return Seq::pbsengine(slaves,stops,n_slaves,stat,opt,best);
00147 }
00148
00149 #ifdef GECODE_HAS_THREADS
00150
00151 template<class T, template<class> class E>
00152 Engine*
00153 pbspar(T* master, const Search::Statistics& stat, Options& opt) {
00154 Stop* stop = opt.stop;
00155 Region r;
00156
00157
00158 unsigned int n_slaves = std::min(static_cast<unsigned int>(opt.threads),
00159 opt.assets);
00160
00161 opt.threads = floor(opt.threads / static_cast<double>(n_slaves));
00162
00163 WrapTraceRecorder::engine(opt.tracer,
00164 SearchTracer::EngineType::PBS, n_slaves);
00165
00166 Engine** slaves = r.alloc<Engine*>(n_slaves);
00167 Stop** stops = r.alloc<Stop*>(n_slaves);
00168
00169 for (unsigned int i=0U; i<n_slaves; i++) {
00170 opt.stop = stops[i] = Par::pbsstop(stop);
00171 Space* slave = (i == n_slaves-1) ?
00172 master : master->clone();
00173 (void) slave->slave(i);
00174 slaves[i] = build<T,E>(slave,opt);
00175 }
00176
00177 return Par::pbsengine(slaves,stops,n_slaves,stat,E<T>::best);
00178 }
00179
00180 template<class T, template<class> class E>
00181 Engine*
00182 pbspar(T* master, SEBs& sebs,
00183 const Search::Statistics& stat, Options& opt, bool best) {
00184 Region r;
00185
00186
00187 int n_slaves = std::min(static_cast<int>(opt.threads),
00188 sebs.size());
00189
00190 WrapTraceRecorder::engine(opt.tracer,
00191 SearchTracer::EngineType::PBS, n_slaves);
00192
00193 Engine** slaves = r.alloc<Engine*>(n_slaves);
00194 Stop** stops = r.alloc<Stop*>(n_slaves);
00195
00196 for (int i=0; i<n_slaves; i++) {
00197
00198 stops[i] = Par::pbsstop(sebs[i]->options().stop);
00199 sebs[i]->options().stop = stops[i];
00200 sebs[i]->options().clone = false;
00201 Space* slave = (i == n_slaves-1) ?
00202 master : master->clone();
00203 (void) slave->slave(i);
00204 slaves[i] = (*sebs[i])(slave);
00205 delete sebs[i];
00206 }
00207
00208 for (int i=n_slaves; i<sebs.size(); i++)
00209 delete sebs[i];
00210
00211 return Par::pbsengine(slaves,stops,n_slaves,stat,best);
00212 }
00213
00214 #endif
00215
00216 }}
00217
00218 namespace Gecode {
00219
00220 template<class T, template<class> class E>
00221 PBS<T,E>::PBS(T* s, const Search::Options& o) {
00222 Search::Options opt(o.expand());
00223
00224 if (opt.assets == 0)
00225 throw Search::NoAssets("PBS::PBS");
00226
00227 Search::Statistics stat;
00228
00229 if (s->status(stat) == SS_FAILED) {
00230 stat.fail++;
00231 if (!opt.clone)
00232 delete s;
00233 e = Search::Seq::dead(opt,stat);
00234 return;
00235 }
00236
00237
00238 T* master = opt.clone ?
00239 dynamic_cast<T*>(s->clone()) : s;
00240 opt.clone = false;
00241
00242
00243 (void) master->master(0);
00244
00245
00246 if (o.assets == 1) {
00247 (void) master->slave(0);
00248 e = Search::build<T,E>(master,opt);
00249 return;
00250 }
00251
00252 #ifdef GECODE_HAS_THREADS
00253 if (opt.threads > 1.0)
00254 e = Search::pbspar<T,E>(master,stat,opt);
00255 else
00256 #endif
00257 e = Search::pbsseq<T,E>(master,stat,opt);
00258 }
00259
00260 template<class T, template<class> class E>
00261 void
00262 PBS<T,E>::build(T* s, SEBs& sebs, const Search::Options& o) {
00263
00264 bool best;
00265 {
00266 int b = 0;
00267 for (int i=0; i<sebs.size(); i++)
00268 b += sebs[i]->best() ? 1 : 0;
00269 if ((b > 0) && (b < sebs.size()))
00270 throw Search::MixedBest("PBS::PBS");
00271 best = (b == sebs.size());
00272 }
00273
00274 Search::Options opt(o.expand());
00275 Search::Statistics stat;
00276
00277 if (s->status(stat) == SS_FAILED) {
00278 stat.fail++;
00279 if (!opt.clone)
00280 delete s;
00281 e = Search::Seq::dead(opt,stat);
00282 return;
00283 }
00284
00285
00286 T* master = opt.clone ?
00287 dynamic_cast<T*>(s->clone()) : s;
00288 opt.clone = false;
00289
00290
00291 (void) master->master(0);
00292
00293 #ifdef GECODE_HAS_THREADS
00294 if (opt.threads > 1.0)
00295 e = Search::pbspar<T,E>(master,sebs,stat,opt,best);
00296 else
00297 #endif
00298 e = Search::pbsseq<T,E>(master,sebs,stat,opt,best);
00299 }
00300
00301 template<class T, template<class> class E>
00302 inline
00303 PBS<T,E>::PBS(T* s, SEBs& sebs, const Search::Options& o) {
00304 build(s,sebs,o);
00305 }
00306 template<class T, template<class> class E>
00307 inline
00308 PBS<T,E>::PBS(T* s, SEB seb0, SEB seb1,
00309 const Search::Options& o) {
00310 SEBs sebs({seb0, seb1});
00311 build(s,sebs,o);
00312 }
00313 template<class T, template<class> class E>
00314 inline
00315 PBS<T,E>::PBS(T* s, SEB seb0, SEB seb1, SEB seb2,
00316 const Search::Options& o) {
00317 SEBs sebs({seb0, seb1, seb2});
00318 build(s,sebs,o);
00319 }
00320 template<class T, template<class> class E>
00321 inline
00322 PBS<T,E>::PBS(T* s, SEB seb0, SEB seb1, SEB seb2, SEB seb3,
00323 const Search::Options& o) {
00324 SEBs sebs({seb0, seb1, seb2, seb3});
00325 build(s,sebs,o);
00326 }
00327
00328 template<class T, template<class> class E>
00329 inline T*
00330 pbs(T* s, const Search::Options& o) {
00331 PBS<T,E> r(s,o);
00332 return r.next();
00333 }
00334
00335 template<class T, template<class> class E>
00336 inline SEB
00337 pbs(const Search::Options& o) {
00338 return new Search::PbsBuilder<T,E>(o);
00339 }
00340
00341 }
00342
00343