diff --git a/gecode/int/branch/cbs.hpp b/gecode/int/branch/cbs.hpp index 331681d9e2..3071acb6e0 100755 --- a/gecode/int/branch/cbs.hpp +++ b/gecode/int/branch/cbs.hpp @@ -147,6 +147,8 @@ namespace Gecode { namespace Int { namespace Branch { // Lambda we pass to propagators via solndistrib to query solution densities auto SendMarginal = [this](unsigned int prop_id, unsigned int var_id, int val, double dens) { + if (!varIdToPos.isIn(var_id)) return; + if (logProp[prop_id].dens < dens) { logProp[prop_id].var_id = var_id; logProp[prop_id].val = val; @@ -157,6 +159,11 @@ namespace Gecode { namespace Int { namespace Branch { for (auto& kv : logProp) kv.second.visited = false; + // We can change rho's value. Actually, there is no memory exception + // with rho = 1. But with other values of rho, there is a memory + // exception for some crossword problems. + float rho = 1; + for (Propagators p(home, PropagatorGroup::all); p(); ++p) { unsigned int prop_id = p.propagator().id(); unsigned int domsum; @@ -181,7 +188,7 @@ namespace Gecode { namespace Int { namespace Branch { // If the domain size sum of all variables in the propagator has changed // since the last time we called this function, we need to recompute // solution densities. Otherwise, we can reuse them. - if (logProp[prop_id].domsum != domsum) { + if (domsum < rho * logProp[prop_id].domsum || logProp[prop_id].domsum == 0) { logProp[prop_id].dens = -1; // Solution density computation p.propagator().solndistrib(home, SendMarginal); diff --git a/gecode/int/extensional/compact.hpp b/gecode/int/extensional/compact.hpp index ae2c619182..62640795e9 100755 --- a/gecode/int/extensional/compact.hpp +++ b/gecode/int/extensional/compact.hpp @@ -533,6 +533,79 @@ namespace Gecode { namespace Int { namespace Extensional { return sizeof(*this); } +#ifdef GECODE_HAS_CBS + template + void + void + PosCompact::solndistrib(Space& home, + Propagator::SendMarginal send) const { + + int minVal = std::numeric_limits::max(); + int maxVal = std::numeric_limits::min(); + + for (Advisors as(c); as(); ++as) { + CTAdvisor& a = as.advisor(); + View x = a.view(); + + minVal = std::min(x.min(), minVal); + maxVal = std::max(x.max(), maxVal); + } + + Region r; + unsigned long long int* solCounts = r.alloc(maxVal - minVal + 1); + + for (Advisors as(c); as(); ++as) { + CTAdvisor& a = as.advisor(); + View x = a.view(); + + if (x.assigned()) continue; + + // Normalization constant for keeping densities values between 0 and 1 + double normalization = 0; + + for (ValidSupports vs(*this, a); vs(); ++vs) { + assert(vs.val() >= minVal); + assert(vs.val() <= maxVal); + + unsigned long long int cbsSupports = table.ones(vs.supports()); + solCounts[vs.val() - minVal] = cbsSupports; + normalization += cbsSupports; + } + + // Because we approximate the permanent of each value for the variable, we + // assign densities in a separate loop where we normalize solution densities. + for (ValidSupports vs(*this, a); vs(); ++vs) { + send(this->id(), + x.id(), + x.baseval(vs.val()), + solCounts[vs.val() - minVal] / normalization); + } + } + + r.free(); + } + + template + void + PosCompact::domainsizesum(Propagator::InDecision in, + unsigned int& size, + unsigned int& size_b) const { + size = 0; + size_b = 0; + + for (Advisors as(c); as(); ++as) { + CTAdvisor& a = as.advisor(); + View x = a.view(); + + if (!x.assigned()) { + size += x.size(); + if (in(x.id())) + size_b += x.size(); + } + } + } +#endif + template void PosCompact::reschedule(Space& home) {