/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Christian Schulte * * Copyright: * Christian Schulte, 2015 * * This file is part of Gecode, the generic constraint * development environment: * http://www.gecode.org * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include namespace Gecode { namespace Search { namespace Par { forceinline CollectAll::CollectAll(void) : solutions(heap) {} forceinline bool CollectAll::add(Space* s, Slave*) { solutions.push(s); return true; } forceinline bool CollectAll::constrain(const Space& b) { (void) b; return false; } forceinline bool CollectAll::empty(void) const { return solutions.empty(); } forceinline Space* CollectAll::get(Slave*&) { return solutions.pop(); } forceinline CollectAll::~CollectAll(void) { while (!solutions.empty()) delete solutions.pop(); } forceinline CollectBest::CollectBest(void) : b(nullptr), reporter(nullptr) {} forceinline bool CollectBest::add(Space* s, Slave* r) { if (b != nullptr) { b->constrain(*s); if (b->status() == SS_FAILED) { delete b; } else { delete s; return false; } } b = s; reporter = r; return true; } forceinline bool CollectBest::constrain(const Space& s) { if (b != nullptr) { b->constrain(s); if (b->status() == SS_FAILED) { delete b; } else { return false; } } b = s.clone(); reporter = nullptr; return true; } forceinline bool CollectBest::empty(void) const { return reporter == nullptr; } forceinline Space* CollectBest::get(Slave*& r) { assert(!empty()); r = reporter; reporter = nullptr; return b->clone(); } forceinline CollectBest::~CollectBest(void) { delete b; } forceinline PortfolioStop::PortfolioStop(Stop* so0) : so(so0), tostop(nullptr) {} forceinline void PortfolioStop::share(volatile bool* ts) { tostop = ts; } template forceinline Slave::Slave(PBS* m, Engine* s, Stop* so) : Support::Runnable(false), master(m), slave(s), stop(so) {} template forceinline Statistics Slave::statistics(void) const { return slave->statistics(); } template forceinline bool Slave::stopped(void) const { return slave->stopped(); } template forceinline void Slave::constrain(const Space& b) { slave->constrain(b); } template Slave::~Slave(void) { delete slave; delete stop; } template forceinline PBS::PBS(Engine** engines, Stop** stops, unsigned int n, const Statistics& stat0) : stat(stat0), slaves(heap.alloc*>(n)), n_slaves(n), n_active(n), slave_stop(false), tostop(false), n_busy(0) { // Initialize slaves for (unsigned int i=0U; i(this,engines[i],stops[i]); static_cast(stops[i])->share(&tostop); } } template forceinline bool PBS::report(Slave* slave, Space* s) { // If b is false the report should be repeated (solution was worse) bool b = true; m.acquire(); if (s != nullptr) { b = solutions.add(s,slave); if (b) tostop = true; } else if (slave->stopped()) { if (!tostop) slave_stop = true; } else { // Move slave to inactive, as it has exhausted its engine unsigned int i=0; while (slaves[i] != slave) i++; assert(i < n_active); assert(n_active > 0); std::swap(slaves[i],slaves[--n_active]); tostop = true; } if (b) { if (--n_busy == 0) idle.signal(); } m.release(); return b; } template void Slave::run(void) { Space* s; do { s = slave->next(); } while (!master->report(this,s)); } template Space* PBS::next(void) { m.acquire(); if (solutions.empty()) { // Clear all tostop = false; slave_stop = false; // Invariant: all slaves are idle! assert(n_busy == 0); assert(!tostop); if (n_active > 0) { // Run all active slaves n_busy = n_active; for (unsigned int i=0U; i* r; s = solutions.get(r); if (Collect::best) for (unsigned int i=0U; iconstrain(*s); } m.release(); return s; } template bool PBS::stopped(void) const { return slave_stop; } template Statistics PBS::statistics(void) const { assert(n_busy == 0); Statistics s(stat); for (unsigned int i=0U; istatistics(); return s; } template void PBS::constrain(const Space& b) { assert(n_busy == 0); if (!Collect::best) throw NoBest("PBS::constrain"); if (solutions.constrain(b)) { // The solution is better for (unsigned int i=0U; iconstrain(b); } } template PBS::~PBS(void) { assert(n_busy == 0); heap.free*>(slaves,n_slaves); } }}} // STATISTICS: search-par