bool LinearPropagator::propagate_true(const LinearConstraint& l) { assert(l.getRelation()==LinearConstraint::Relation::LE); auto minmax = computeMinMax(l); if (minmax.second <= l.getRhs()) return true; for (auto i : l.getViews()) { auto r = vs_.getCurrentRestrictor(i); auto wholeRange = vs_.getRestrictor(i); std::pair<int64,int64> mm; mm.first = minmax.first - r.lower(); mm.second = minmax.second - r.upper(); int64 up = l.getRhs() - mm.first; if (up < r.lower()) { //std::cout << "Constrain Variable " << i.first << " with new upper bound " << up << std::endl; return false; } if (up < r.upper()) { //std::cout << "Constrain Variable " << i.first << " with new upper bound " << up << std::endl; //auto newUpper = std::lower_bound(wholeRange.begin(), wholeRange.end(), up); auto newUpper = std::upper_bound(wholeRange.begin(), wholeRange.end(), up); if (!constrainUpperBound(newUpper)) // +1 is needed, as it is in iterator pointing after the element return false; minmax.first = mm.first + r.lower(); minmax.second = mm.second + *(newUpper-1); } } return true; }
std::vector<LinearLiteralPropagator::LinearConstraintClause> LinearLiteralPropagator::propagate_true(const ReifiedLinearConstraint& rl) { const LinearConstraint& l = rl.l; assert(l.getRelation()==LinearConstraint::Relation::LE); std::vector<LinearConstraintClause> ret; LinearConstraintClause::itervec clause; auto minmax = computeMinMax(l, clause); if (minmax.second <= l.getRhs()) return ret; //std::cout << "trying to propagate " << l << std::endl; auto views = l.getViews(); for (std::size_t index=0; index < views.size(); ++index) { auto& i = views[index]; auto wholeRange = vs_.getVariableStorage().getRestrictor(i); assert(wholeRange.size()>0); auto r = vs_.getVariableStorage().getCurrentRestrictor(i); std::pair<int64,int64> mm; mm.first = minmax.first - r.lower(); mm.second = minmax.second - r.upper(); //Literal prop = s_.falseLit(); bool prop = false; Restrictor::ViewIterator propIt(wholeRange.begin()); bool conflict = false; int64 up = l.getRhs() - mm.first; //// check if this returns the correct literals, /// see translatorClauseChecker::add, there is a positive and a negative add if (up < wholeRange.lower()) // derive false { //std::cout << "Constrain View " << i.v << "*" << i.a << "+" << i.c << " with new upper bound " << up << std::endl; propIt=wholeRange.begin();//can be removed conflict = true; } else if (up < r.upper()) { //std::cout << "Constrain Variable " << i.v << "*" << i.a << "+" << i.c << " with new upper bound " << up << std::endl; auto newUpper = std::upper_bound(wholeRange.begin(), wholeRange.end(), up, [](int64 val, int64 it){ return it > val; }); //assert(newUpper != r.end()); /// should never be able to happen, as up < r.upper().first, so there is something which is smaller, this means we do not need r ? if (newUpper==wholeRange.begin()) { propIt = newUpper; conflict=true; } else { propIt = newUpper; --newUpper; prop = true; //prop = vs_.getVariableCreator().getLiteral(newUpper); conflict = !constrainUpperBound((newUpper+1)); // +1 is needed, as it is an iterator pointing after the element minmax.first = mm.first + r.lower(); minmax.second = mm.second + *newUpper; //minmax = mm + std::minmax(i.second*(int64)r.lower(),i.second*(int64)((*newUpper))); } } if (prop || conflict) { LinearConstraintClause c(rl); LinearConstraintClause::itervec aux(clause); aux[index] = propIt; c.setClause(std::move(aux),index); c.setConflict(conflict); ret.emplace_back(c); } if (conflict) break; } //When i changed a bound, the reason for the next ones can change, right ? No! only the upper/lower bound is changes, the other bound is used for reason return ret; }
/// return false if the domain is empty void ConstraintStorage::constrainLowerBound(const View &u, const Solver& s) { constrainUpperBound(u*-1,s); }
void LinearLiteralPropagator::propagate_true(const ReifiedLinearConstraint& rl) { const LinearConstraint& l = rl.l; assert(l.getRelation()==LinearConstraint::Relation::LE); propClause_.clear(); auto minmax = computeMinMax(l, propClause_); if (minmax.second <= l.getRhs()) return; if (conf_.propStrength<=2) { if (minmax.first > l.getRhs()) { propClauses_.emplace_back(std::make_pair(~rl.v,std::move(propClause_))); } return; } //std::cout << "trying to propagate " << l << std::endl; auto& views = l.getViews(); for (std::size_t index=0; index < views.size(); ++index) { auto& i = views[index]; auto wholeRange = vs_.getVariableStorage().getRestrictor(i); assert(wholeRange.size()>0); auto r = vs_.getVariableStorage().getCurrentRestrictor(i); assert(r.begin() < r.end()); std::pair<int64,int64> mm; mm.first = minmax.first - r.lower(); mm.second = minmax.second - r.upper(); //Literal prop = s_.falseLit(); bool prop = false; Restrictor::ViewIterator propIt(wholeRange.begin()); bool conflict = false; int64 up = l.getRhs() - mm.first; if (up < wholeRange.lower()) // derive false { //std::cout << "Constrain View " << i.v << "*" << i.a << "+" << i.c << " with new upper bound " << up << std::endl; //propIt=wholeRange.begin();//can be removed conflict = true; } else if (up < r.upper()) { //std::cout << "Constrain Variable " << i.v << "*" << i.a << "+" << i.c << " with new upper bound " << up << std::endl; //std::cout << "This Variable before had domain " << r.lower() << " .. " << r.upper() << std::endl; auto newUpper = order::wrap_upper_bound(wholeRange.begin(), r.end(), up); //assert(newUpper != r.end()); /// should never be able to happen, as up < r.upper().first, so there is something which is smaller, this means we do not need r ? propIt = newUpper; if (newUpper==wholeRange.begin()) { conflict=true; } else { --newUpper; prop = true; //prop = vs_.getVariableCreator().getLiteral(newUpper); //std::cout << "the upper bound not included for this view will be " << *(newUpper+1) << std::endl; conflict = !constrainUpperBound((newUpper+1)); // +1 is needed, as it is an iterator pointing after the element //minmax.first = mm.first + r.lower(); minmax.second = mm.second + *newUpper; //minmax = mm + std::minmax(i.second*(int64)r.lower(),i.second*(int64)((*newUpper))); } } if (prop || conflict) { itervec aux; if (conflict) aux = std::move(propClause_); else aux = propClause_; aux[index] = propIt; propClauses_.emplace_back(std::make_pair(~rl.v,std::move(aux))); } if (conflict) break; } //When i changed a bound, the reason for the next ones can change, right ? No! only the upper/lower bound is changes, the other bound is used for reason }