Add equality constraints.

This commit is contained in:
chriseth 2022-03-03 19:51:49 +01:00
parent 33f0e0d4b2
commit 2108580df6

View File

@ -330,7 +330,7 @@ optional<Literal> BooleanLPSolver::parseLiteral(smtutil::Expression const& _expr
} }
else if (_expr.name == "not") else if (_expr.name == "not")
return negate(parseLiteralOrReturnEqualBoolean(_expr.arguments.at(0))); return negate(parseLiteralOrReturnEqualBoolean(_expr.arguments.at(0)));
else if (_expr.name == "<=") else if (_expr.name == "<=" || _expr.name == "=")
{ {
optional<LinearExpression> left = parseLinearSum(_expr.arguments.at(0)); optional<LinearExpression> left = parseLinearSum(_expr.arguments.at(0));
optional<LinearExpression> right = parseLinearSum(_expr.arguments.at(1)); optional<LinearExpression> right = parseLinearSum(_expr.arguments.at(1));
@ -340,7 +340,7 @@ optional<Literal> BooleanLPSolver::parseLiteral(smtutil::Expression const& _expr
LinearExpression data = *left - *right; LinearExpression data = *left - *right;
data[0] *= -1; data[0] *= -1;
return Literal{true, addConditionalConstraint(Constraint{move(data), false, {}})}; return Literal{true, addConditionalConstraint(Constraint{move(data), _expr.name == "=", {}})};
} }
else if (_expr.name == ">=") else if (_expr.name == ">=")
return parseLiteral(_expr.arguments.at(1) <= _expr.arguments.at(0)); return parseLiteral(_expr.arguments.at(1) <= _expr.arguments.at(0));
@ -357,8 +357,36 @@ Literal BooleanLPSolver::negate(Literal const& _lit)
if (isConditionalConstraint(_lit.variable)) if (isConditionalConstraint(_lit.variable))
{ {
Constraint const& c = conditionalConstraint(_lit.variable); Constraint const& c = conditionalConstraint(_lit.variable);
solAssert(!c.equality, ""); if (c.equality)
{
// X = b
// X <= b - 1
Constraint le = c;
le.equality = false;
le.data[0] -= 1;
le.reasons.clear();
Literal leL{true, addConditionalConstraint(le)};
// X >= b + 1
// -X <= -b - 1
Constraint ge = c;
ge.equality = false;
ge.data *= -1;
ge.data[0] -= 1;
ge.reasons.clear();
Literal geL{true, addConditionalConstraint(ge)};
Literal equalBoolean = *parseLiteral(declareInternalVariable(true));
// a = or(x, y) <=> (-a \/ x \/ y) /\ (a \/ -x) /\ (a \/ -y)
state().clauses.emplace_back(Clause{vector<Literal>{negate(equalBoolean), leL, geL}});
state().clauses.emplace_back(Clause{vector<Literal>{equalBoolean, negate(leL)}});
state().clauses.emplace_back(Clause{vector<Literal>{equalBoolean, negate(geL)}});
return equalBoolean;
}
else
{
// X > b // X > b
// -x < -b // -x < -b
// -x <= -b - 1 // -x <= -b - 1
@ -369,6 +397,7 @@ Literal BooleanLPSolver::negate(Literal const& _lit)
negated.reasons.clear(); negated.reasons.clear();
return Literal{true, addConditionalConstraint(negated)}; return Literal{true, addConditionalConstraint(negated)};
} }
}
else else
return ~_lit; return ~_lit;
} }