44 using carl::operator<<;
46 inline bool isSubset(
const carl::Variables& subset,
const carl::Variables& superset) {
47 return std::includes(superset.begin(), superset.end(), subset.begin(), subset.end());
61 os <<
"(" << b.
constr <<
", " << b.
p <<
", " << b.
q <<
", " << b.
r <<
", " << b.
neg <<
")";
65 template<
class Comparator>
68 #define mcsat_yield(callback, result) if (callback(std::move(result))) { return; }
95 SMTRAT_LOG_DEBUG(
"smtrat.mcsat.fm",
"Lower bound " << lower <<
" in conflict with upper bound " << upper);
96 bool strict = carl::is_strict(lower.
constr.relation()) || carl::is_strict(upper.
constr.relation());
97 carl::Relation rel = (lower.
neg xor upper.
neg) ? (strict ? carl::Relation::GREATER : carl::Relation::GEQ) : (strict ? carl::Relation::LESS : carl::Relation::LEQ);
99 res.emplace_back(lower.
constr.negation());
100 res.emplace_back(upper.
constr.negation());
102 SMTRAT_LOG_DEBUG(
"smtrat.mcsat.fm",
"Conflict: " << lower.
q <<
" * " << upper.
p <<
" " << rel <<
" " << upper.
q <<
" * " << lower.
p);
110 SMTRAT_LOG_DEBUG(
"smtrat.mcsat.fm",
"Equality " << eq <<
" in conflict with inqequality " << ineq);
112 expl.emplace_back(ineq.
constr.negation());
113 expl.emplace_back(eq.
constr.negation());
114 expl.emplace_back(
ConstraintT(eq.
q*ineq.
p - ineq.
q*eq.
p, carl::Relation::NEQ));
115 SMTRAT_LOG_DEBUG(
"smtrat.mcsat.fm",
"Explanation: " << expl[0].negated() <<
" && " << expl[1].negated() <<
" -> " << expl[2]);
122 SMTRAT_LOG_DEBUG(
"smtrat.mcsat.fm",
"Lower bound " << lower <<
" and upper bound " << upper <<
" in conflict with inqequality " << ineq);
124 expl.emplace_back(ineq.
constr.negation());
125 expl.emplace_back(lower.
constr.negation());
126 expl.emplace_back(upper.
constr.negation());
128 expl.emplace_back(
ConstraintT(lower.
q*ineq.
p - ineq.
q*lower.
p, carl::Relation::NEQ));
129 SMTRAT_LOG_DEBUG(
"smtrat.mcsat.fm",
"Explanation: " << expl[0].negated() <<
" && " << expl[1].negated() <<
" && " << expl[2].negated() <<
" && " << expl[3].negated() <<
" -> " << expl[4]);
138 template<
typename Callback>
140 std::vector<Bound> mLower;
141 std::vector<Bound> mUpper;
142 std::multimap<Rational, Bound> mInequalities;
143 std::vector<Bound> mEqualities;
144 std::vector<std::pair<Bound, Bound>> mBoundPair;
155 if (b.var_info(
mVariable).max_degree() > 1) {
160 if (carl::is_zero(p)) {
166 if (!evalp.isRational()) {
167 SMTRAT_LOG_DEBUG(
"smtrat.mcsat.fm",
"Discarding bound " << b <<
" because " << p <<
" did not evaluate to a rational");
170 assert(evalp.isRational());
174 if (!evalq.isRational()) {
175 SMTRAT_LOG_DEBUG(
"smtrat.mcsat.fm",
"Discarding bound " << b <<
" because " << q <<
" did not evaluate to a rational");
178 assert(evalq.isRational());
180 if (carl::is_zero(evalp.asRational())) {
181 SMTRAT_LOG_DEBUG(
"smtrat.mcsat.fm",
"Discarding bound " << b <<
" because it does not contain " <<
mVariable <<
" after we evaluate it");
184 SMTRAT_LOG_DEBUG(
"smtrat.mcsat.fm",
"Bound " << b <<
" unsat because p is zero and q does not comply");
186 expl.emplace_back(b.negation());
190 SMTRAT_LOG_DEBUG(
"smtrat.mcsat.fm",
"Explanation: " << expl[0].negated() <<
" && " << expl[1].negated() <<
" -> " << expl[2]);
196 bool negated = evalp.asRational() < 0;
198 Rational r = evalq.asRational() / evalp.asRational();
202 SMTRAT_LOG_DEBUG(
"smtrat.mcsat.fm",
"Coefficient is " << evalp.asRational());
204 switch (b.relation()) {
205 case carl::Relation::LESS:
206 case carl::Relation::LEQ:
208 mLower.emplace_back(b, p, q, r, negated);
210 mUpper.emplace_back(b, p, q, r, negated);
214 mLower.emplace_back(b, p, q, r, negated);
215 mUpper.emplace_back(b, p, q, r, negated);
216 mEqualities.emplace_back(b, p, q, r, negated);
218 case carl::Relation::NEQ:
219 mInequalities.emplace(r,
Bound(b, p, q, r, negated));
221 case carl::Relation::GEQ:
222 case carl::Relation::GREATER:
224 mUpper.emplace_back(b, p, q, r, negated);
226 mLower.emplace_back(b, p, q, r, negated);
236 SMTRAT_LOG_DEBUG(
"smtrat.mcsat.fm",
"Looking for conflicts between lower and upper bounds");
246 for (
const Bound& lower : mLower) {
247 for (
const Bound& upper : mUpper) {
248 SMTRAT_LOG_DEBUG(
"smtrat.mcsat.fm",
"Combining " << lower <<
" and " << upper);
249 bool strict = carl::is_strict(lower.constr.relation()) || carl::is_strict(upper.constr.relation());
251 if (lower.r < upper.r) {
256 if (lower.r == upper.r && !strict) {
258 mBoundPair.push_back(std::make_pair(lower, upper));
267 SMTRAT_LOG_DEBUG(
"smtrat.mcsat.fm",
"Looking for conflicts with inequalities");
269 for (
const auto& eq : mEqualities) {
271 auto it = mInequalities.find(eq.r);
272 if (it != mInequalities.end()) {
277 for (
const auto& bounds : mBoundPair) {
278 SMTRAT_LOG_DEBUG(
"smtrat.mcsat.fm",
"Considering lower bound " << bounds.first <<
" and upper bound " << bounds.second);
279 auto it = mInequalities.find(bounds.first.r);
280 if (it != mInequalities.end()) {
328 return b1.
constr.variables().size() < b2.
constr.variables().size();
#define mcsat_yield(callback, result)
void sort(T *array, int size, LessThan lt)
Rational evaluate(carl::Variable v, const Poly &p, const Rational &r)
bool isSubset(const carl::Variables &subset, const carl::Variables &superset)
std::ostream & operator<<(std::ostream &os, const Bound &b)
bool includes(const VariableRange &superset, const carl::Variables &subset)
Class to create the formulas for axioms.
carl::Model< Rational, Poly > Model
carl::MultivariatePolynomial< Rational > Poly
carl::Constraint< Poly > ConstraintT
carl::Formulas< Poly > FormulasT
#define SMTRAT_LOG_DEBUG(channel, msg)
Bound(ConstraintT constr, Poly p, Poly q, Rational r, bool neg)
friend std::ostream & operator<<(std::ostream &os, const Bound &dt)
FormulasT conflictEqualityAndInequality(const Bound &eq, const Bound &ineq)
ConstraintT sideCondition(const Bound &b)
FormulasT conflictInequalitiesAndInequality(const Bound &lower, const Bound &upper, const Bound &ineq)
const std::vector< ConstraintT > & mBounds
ConflictGenerator(const std::vector< ConstraintT > &bounds, const Model &m, carl::Variable v)
ConstraintT sideConditionLoUp(const Bound &b)
void generateExplanation(Callback &&callback)
FormulasT conflictLowerAndUpperBound(const Bound &lower, const Bound &upper)
bool operator()(const Bound &, const Bound &) const
This heuristic chooses the explanation excluding the largest interval.
bool operator()(const Bound &b1, const Bound &b2) const
This heuristic chooses the explanation excluding the smallest interval.
bool operator()(const Bound &b1, const Bound &b2) const
This heuristic tries to minimize the number of variables occuring in the explanation.
bool operator()(const Bound &b1, const Bound &b2) const