/* * @return: * 1: you can never propagate l without a backtrack * 2: you can not propagate l now, but maybe after more assignments * 3: you can propagate l now */ int SymmetryPropagator::canPropagate(Lit l) { if (getPCSolver().isDecided(l.getAtom()) || symmetrical.count(l) == 0 || getPCSolver().value(symmetrical.at(l)) == l_True) { return 1; } if (getPCSolver().getLevel(l.getAtom()) == 0) { return 3; } rClause cl = getPCSolver().getExplanation(l); int nbUndefs = 0; for (int i = 0; i < getPCSolver().getClauseSize(cl); ++i) { lbool val = getPCSolver().value(getSymmetrical(getPCSolver().getClauseLit(cl, i))); if (val == l_True) { return 1; } else if (val == l_Undef) { ++nbUndefs; if (nbUndefs >= 2) { return 2; } } } return 3; }
std::string ExternalConstraintVisitor::toString(const Lit& l) const { auto overriddenit = atom2string.find(l.getAtom()); if(overriddenit!=atom2string.cend()){ return sign(l)?"~"+overriddenit->second:overriddenit->second; } std::stringstream ss; if (getRemapper()->wasInput(l)) { auto lit = getRemapper()->getLiteral(l); if (getTranslator()->hasTranslation(lit)) { ss << getTranslator()->toString(lit); return ss.str(); } } ss << (sign(l) ? "~" : "") << "i_" << var(l) + 1; // NOTE: do not call <<l, this will cause an infinite loop (as that calls this method!) return ss.str(); }
rClause SymmetryPropagator::notifypropagate() { Lit l = getNextToPropagate(); if (l == lit_Undef) { return nullPtrClause; } std::vector<Lit> symClause; if (getPCSolver().getLevel(l.getAtom()) == 0) { // TODO: @Broes: is this the right trick to use for a propagation / conflict at level 0? symClause.push_back(symmetrical.at(l)); symClause.push_back(not l); } else { getSymmetricalClause(getPCSolver().getExplanation(l), symClause); } auto c = getPCSolver().createClause(Disjunction(getID(), symClause), true); bool isConflict = true; for (auto ll : symClause) { MAssert(getPCSolver().value(ll)==l_Undef || getPCSolver().value(ll)==l_False); if (getPCSolver().value(ll) == l_Undef) { isConflict = false; break; } } if (isConflict) { if (verbosity() > 1) { cout << "Symmetry propagation detected conflict!" << endl; for(auto ll: symClause){ cout << ll.x << ",";// << "-" << getPCSolver().value(ll) << "|"; } cout << endl; } getPCSolver().addConflictClause(c); return c; } else { if (verbosity() > 1) { cout << "Symmetry propagation detected propagation!" << endl; for(auto ll: symClause){ cout << ll.x << ",";// << "-" << getPCSolver().value(ll) << "|"; } cout << endl; } getPCSolver().addLearnedClause(c); return nullPtrClause; } }
BinaryConstraint::BinaryConstraint(PCSolver* engine, IntView* _left, EqType comp, IntView* _right, const Lit& h) : Propagator(engine, "binary constraint") { // FIXME optimize if left and right are the same variable! switch (comp) { case EqType::EQ: { stringstream ss; ss <<_left->toString() << " = " << _right->toString(); getPCSolver().setString(h.getAtom(),ss.str()); auto lefthead = mkPosLit(getPCSolver().newAtom()); auto righthead = mkPosLit(getPCSolver().newAtom()); add(Implication(h, ImplicationType::EQUIVALENT, { lefthead, righthead }, true)); add(CPBinaryRelVar(righthead, _left->getID(), EqType::GEQ, _right->getID())); head_ = lefthead; left_ = getPCSolver().getIntView(_left->getID(), 0); right_ = getPCSolver().getIntView(_right->getID(), 0); break; } case EqType::NEQ: { stringstream ss; ss <<_left->toString() << " != " << _right->toString(); getPCSolver().setString(h.getAtom(),ss.str()); auto lefthead = mkPosLit(getPCSolver().newAtom()); auto righthead = mkPosLit(getPCSolver().newAtom()); add(Implication(h, ImplicationType::EQUIVALENT, { lefthead, righthead }, false)); add(CPBinaryRelVar(righthead, _left->getID(), EqType::G, _right->getID())); head_ = lefthead; left_ = getPCSolver().getIntView(_left->getID(), 0); if(_right->minValue()==getMinElem<int>()){ add(Disjunction({head_})); notifyNotPresent(); return; } right_ = getPCSolver().getIntView(_right->getID(), -1); break; } case EqType::LEQ: head_ = h; left_ = getPCSolver().getIntView(_left->getID(), 0); right_ = getPCSolver().getIntView(_right->getID(), 0); break; case EqType::L: head_ = h; left_ = getPCSolver().getIntView(_left->getID(), 0); if(_right->minValue()==getMinElem<int>()){ add(Disjunction({not head_})); notifyNotPresent(); return; } right_ = getPCSolver().getIntView(_right->getID(), -1); break; case EqType::GEQ: head_ = h; left_ = getPCSolver().getIntView(_right->getID(), 0); right_ = getPCSolver().getIntView(_left->getID(), 0); break; case EqType::G: head_ = h; left_ = getPCSolver().getIntView(_right->getID(), 0); if(_left->minValue()==getMinElem<int>()){ add(Disjunction({not head_})); notifyNotPresent(); return; } right_ = getPCSolver().getIntView(_left->getID(), -1); break; } getPCSolver().accept(this); getPCSolver().accept(this, head(), FAST); getPCSolver().accept(this, not head(), FAST); if(left_->isPartial()){ add(Implication(not head(), ImplicationType::IMPLIEDBY, {left_->getNoImageLit()}, true)); getPCSolver().accept(this, left_->getNoImageLit(), FAST); getPCSolver().accept(this, not left_->getNoImageLit(), FAST); } if(right_->isPartial()){ add(Implication(not head(), ImplicationType::IMPLIEDBY, {right_->getNoImageLit()}, true)); getPCSolver().accept(this, right_->getNoImageLit(), FAST); getPCSolver().accept(this, not right_->getNoImageLit(), FAST); } getPCSolver().acceptBounds(left(), this); getPCSolver().acceptBounds(right(), this); getPCSolver().acceptForPropagation(this); stringstream ss; ss<<left()->toString() << " =< " << right()->toString(); getPCSolver().setString(head().getAtom(), ss.str()); if (verbosity() > 5) { clog << "Binconstr: " << toString(head()) << " <=> " << left()->toString() << " =< " << right()->toString() << "\n"; } }