6#include "BoundPreprocessor.h"
14#include "dlinear/libs/libgmp.h"
15#include "dlinear/util/Infinity.h"
16#include "dlinear/util/exception.h"
18#if DEBUGGING_PREPROCESSOR
21#include "dlinear/solver/Context.h"
28void cartesian_product(
const std::set<LiteralSet>& a,
const std::set<LiteralSet>& b,
const std::set<LiteralSet>& c,
29 const LiteralSet& explanation_to_add, std::set<LiteralSet>& destination) {
30 const std::set<LiteralSet> empty_set{{}};
31 const std::set<LiteralSet>& first = a.empty() ? empty_set : a;
32 const std::set<LiteralSet>& second = b.empty() ? empty_set : b;
33 const std::set<LiteralSet>& third = c.empty() ? empty_set : c;
34 for (
const auto& a_set : first) {
35 for (
const auto& b_set : second) {
36 for (
const auto& c_set : third) {
38 new_set.insert(a_set.begin(), a_set.end());
39 new_set.insert(b_set.begin(), b_set.end());
40 new_set.insert(c_set.begin(), c_set.end());
41 new_set.insert(explanation_to_add.begin(), explanation_to_add.end());
42 destination.insert(new_set);
49#if DEBUGGING_PREPROCESSOR
51bool print_all =
false;
52Variable find_variable(
const BoundPreprocessor& preprocessor,
const std::string& name) {
53 for (
const Variable& var : preprocessor.theory_cols())
54 if (var.get_name() == name) return var;
55 DLINEAR_UNREACHABLE();
57bool check_explanation(
const BoundPreprocessor& preprocessor,
const LiteralSet& explanation) {
59 Config config = preprocessor.config();
61 config.m_filename() =
"";
62 config.m_read_from_stdin() =
false;
63 config.m_disable_eq_propagation() =
true;
64 Context smt_solver{config};
65 for (
const auto& [var, truth] : explanation) {
66 const Formula f = truth ? preprocessor.predicate_abstractor()[var] : !preprocessor.predicate_abstractor()[var];
67 for (
const Variable& free : f.GetFreeVariables()) {
68 smt_solver.DeclareVariable(free);
72 const auto result = smt_solver.CheckSat(&zero);
80[[maybe_unused]]
bool check_explanation(
const BoundPreprocessor& preprocessor,
81 const std::set<LiteralSet>& explanations) {
82 for (
const auto& explanation : explanations) {
83 return check_explanation(preprocessor, explanation);
91 : config_{predicate_abstractor.config()},
92 predicate_abstractor_{predicate_abstractor},
93 stats_{config_.with_timings(),
"BoundPreprocessor",
"Process"} {}
96 DLINEAR_TRACE_FMT(
"BoundPreprocessor::AddVariable({})", var);
102 std::set<LiteralSet> explanations;
107 std::set<LiteralSet>& explanations) {
108 for (
const Literal& l : enabled_literals) {
110 if (!explanation.empty()) explanations.insert(explanation.begin(), explanation.end());
115 std::set<LiteralSet> explanations;
120 if (enabled_literals_.contains(lit))
return;
121 DLINEAR_TRACE_FMT(
"BoundPreprocessor::EnableLiteral({})", lit);
122 const auto& [formula_var, truth] = lit;
132 if (!violation.empty()) {
133 DLINEAR_DEBUG_FMT(
"BoundPreprocessor::EnableLiteral: {} conflict found", violation.explanation());
134 violation.explanations(explanations, lit);
137 if (eq_bound !=
nullptr) {
138 DLINEAR_ASSERT(!
env_.
contains(var) ||
env_[var] == *eq_bound,
"No conflict should arise from this assignment");
139 env_[var] = *eq_bound;
142 enabled_literals_.insert(lit);
143 DLINEAR_TRACE_FMT(
"BoundPreprocessor::EnableLiteral: added constraint {}", lit);
149 it->second.GetActiveExplanation(explanation);
152 Explanations explanations;
153 Process(enabled_literals_, explanations);
158 Explanations explanations;
159 Process(enabled_literals, explanations);
164 "Method Process should not be called with a frequency of NEVER");
168 DLINEAR_TRACE_FMT(
"BoundPreprocessor::Process({})", enabled_literals);
169 std::list<Literal> mutable_enabled_formula_vars{enabled_literals.begin(), enabled_literals.end()};
172 mutable_enabled_formula_vars.remove_if([
this](
const Literal& lit) {
177 PropagateConstraints(mutable_enabled_formula_vars, explanations);
178 DLINEAR_DEBUG_FMT(
"BoundPreprocessor::Process: {} conflict found in propagation", explanations.size());
179 if (!explanations.empty())
return;
182 for (
const Literal& lit : enabled_literals) {
185 if (
IsNotEqualTo(formula, lit.
truth)) mutable_enabled_formula_vars.push_back(lit);
188 EvaluateFormulas(mutable_enabled_formula_vars, explanations);
189 DLINEAR_DEBUG_FMT(
"BoundPreprocessor::Process: {} conflict found in evaluation", explanations.size());
200 enabled_literals_.clear();
206 enabled_literals_ = fixed_preprocessor.enabled_literals_;
210 Explanations& explanations) {
211 DLINEAR_TRACE_FMT(
"BoundPreprocessor::PropagateEqPolynomial({})", lit);
215 DLINEAR_ASSERT_FMT(
IsEqualTo(formula, lit.
truth),
"Lit must encode an equal to relation. Got {}", lit);
216 DLINEAR_ASSERT_FMT(formula.IsFlattened(),
"The formula must be flattened. Got {}", formula);
217 DLINEAR_ASSERT(ShouldPropagateEqPolynomial(lit),
"The formula should be propagated");
218 DLINEAR_ASSERT(!
env_.
contains(var_to_propagate),
"The variable must not be in the environment yet");
219 DLINEAR_ASSERT(!var_to_propagate.
is_dummy(),
"The variable must be valid");
222 std::vector<Variable> dependencies;
224 mpq_class rhs{get_constant_value(get_rhs_expression(formula))};
225 mpq_class var_coeff{};
226 for (
const auto& [expr, coeff] : get_expr_to_coeff_map_in_addition(get_lhs_expression(formula))) {
227 DLINEAR_ASSERT(is_variable(expr),
"All expressions in lhs formula must be variables");
228 const Variable& var = get_variable(expr);
229 if (var.
equal_to(var_to_propagate)) {
233 rhs -=
env_.
at(var) * coeff;
234 dependencies.emplace_back(var);
236 DLINEAR_ASSERT(var_coeff != 0,
"The propagated variable coefficient cannot be 0");
242 for (
const Variable& dependency : dependencies) {
244 explanation.insert(dependency_explanation.begin(), dependency_explanation.end());
247 const auto [env_it, inserted] =
env_.
insert(var_to_propagate, rhs);
248 DLINEAR_ASSERT(inserted,
"The variable was not in the environment before");
254 if (!violation.empty()) {
255 explanation.insert(lit);
256 violation.explanation(explanation);
257 DLINEAR_DEBUG_FMT(
"BoundPreprocessor::PropagateConstraints: {} conflict found", explanation);
258 explanations.insert(explanation);
264 DLINEAR_TRACE_FMT(
"BoundPreprocessor::PropagateConstraints: {} = {} thanks to constraint {} and {}", var_to_propagate,
265 rhs, lit, dependencies);
271 const std::vector<Bound>& assumptions,
272 dlinear::BoundPreprocessor::Explanations& explanations) {
274 DLINEAR_DEV_FMT(
"Bounds initial: {}", bounds);
275 for (
auto assumption = assumptions.begin(); assumption != assumptions.end(); ++assumption) {
277 if (!violation.empty()) {
278 for (
auto added_assumption = assumptions.begin(); added_assumption != assumption; ++added_assumption) {
284 DLINEAR_DEV_FMT(
"Bounds assumptions: {}", bounds);
287 for (
const Bound& assumption : assumptions) bounds.RemoveBound(assumption);
288 DLINEAR_DEV_FMT(
"Bounds after: {}", bounds);
293 Explanations& explanations) {
294 DLINEAR_TRACE_FMT(
"BoundPreprocessor::PropagateInPolynomial({})", lit);
298 DLINEAR_ASSERT(is_relational(formula),
"Formula should be a relational relation other than = or !=");
299 DLINEAR_ASSERT(formula.IsFlattened(),
"The formula must be flattened");
300 DLINEAR_ASSERT(!var_to_propagate.
is_dummy(),
"The variable must be valid");
305 std::vector<Variable> dependencies;
307 mpq_class l_rhs{get_constant_value(get_rhs_expression(formula))};
308 mpq_class u_rhs{get_constant_value(get_rhs_expression(formula))};
309 mpq_class var_coeff{};
310 for (
const auto& [expr, coeff] : get_expr_to_coeff_map_in_addition(get_lhs_expression(formula))) {
311 DLINEAR_ASSERT(is_variable(expr),
"All expressions in lhs formula must be variables");
312 const Variable& var = get_variable(expr);
313 if (var.
equal_to(var_to_propagate)) {
318 "All other variable, except the one being propagated, must be bounded");
319 const mpq_class& lower_bound =
theory_bounds_.at(var).active_lower_bound();
320 const mpq_class& upper_bound =
theory_bounds_.at(var).active_upper_bound();
321 dependencies.emplace_back(var);
323 l_rhs -= upper_bound * coeff;
324 u_rhs -= lower_bound * coeff;
325 theory_bounds_.at(var).GetActiveBound(upper_bound).explanation(l_explanation);
326 theory_bounds_.at(var).GetActiveBound(lower_bound).explanation(u_explanation);
328 l_rhs -= lower_bound * coeff;
329 u_rhs -= upper_bound * coeff;
330 theory_bounds_.at(var).GetActiveBound(lower_bound).explanation(l_explanation);
331 theory_bounds_.at(var).GetActiveBound(upper_bound).explanation(u_explanation);
334 DLINEAR_ASSERT(var_coeff != 0,
"The propagated variable coefficient cannot be 0");
341 std::swap(l_rhs, u_rhs);
342 std::swap(l_explanation, u_explanation);
351 if (l_rhs == u_rhs) {
352 DLINEAR_ASSERT_FMT(l_explanation == u_explanation,
"The explanations must be the same. {} vs {} instead",
353 l_explanation, u_explanation);
356 if (!violation.empty()) {
357 l_explanation.insert(lit);
360 DLINEAR_DEBUG_FMT(
"BoundPreprocessor::PropagateConstraints2: Eq bound {} conflict found", l_explanation);
361 explanations.insert(l_explanation);
365 "No conflict should arise from this assignment");
373 if (!violation.empty()) {
375 l_explanation.insert(lit);
376 violation.explanation(l_explanation);
377 DLINEAR_DEBUG_FMT(
"BoundPreprocessor::PropagateConstraints2: Lower bound {} conflict found", l_explanation);
378 explanations.insert(l_explanation);
387 if (!violation.empty()) {
391 u_explanation.insert(lit);
392 violation.explanation(u_explanation);
393 DLINEAR_DEBUG_FMT(
"BoundPreprocessor::PropagateConstraints2: Upper bound {} conflict found", u_explanation);
394 explanations.insert(u_explanation);
400 DLINEAR_TRACE_FMT(
"BoundPreprocessor::PropagateConstraints: {} = [{}, {}] thanks to constraint {} and {}",
401 var_to_propagate, l_rhs, u_rhs, lit, dependencies);
405 if (eq_bound !=
nullptr) {
406 DLINEAR_ASSERT(!
env_.
contains(var_to_propagate) ||
env_[var_to_propagate] == *eq_bound,
407 "No conflict should arise from this assignment");
408 env_[var_to_propagate] = *eq_bound;
427 DLINEAR_ASSERT(var_coeff < 0,
"The coefficient must be less than 0");
443 if (!violation.empty()) {
447 DLINEAR_DEBUG_FMT(
"BoundPreprocessor::PropagateConstraints: {} conflict found", bound.
explanation);
451 DLINEAR_TRACE_FMT(
"BoundPreprocessor::PropagateConstraints: {} = [{}, {}] thanks to constraint {} and {}",
452 var_to_propagate, l_rhs, u_rhs, lit, dependencies);
454 if (eq_bound !=
nullptr) {
455 DLINEAR_ASSERT(!
env_.
contains(var_to_propagate) ||
env_[var_to_propagate] == *eq_bound,
456 "No conflict should arise from this assignment");
457 env_[var_to_propagate] = *eq_bound;
462void BoundPreprocessor::PropagateConstraints(std::list<Literal>& enabled_literals, Explanations& explanations) {
463 DLINEAR_TRACE(
"BoundPreprocessor::PropagateConstraints()");
466 PropagateEqConstraints(enabled_literals, explanations);
469 PropagateBoundConstraints(enabled_literals, explanations);
471void BoundPreprocessor::PropagateEqConstraints(std::list<Literal>& enabled_literals, Explanations& explanations) {
472 DLINEAR_TRACE_FMT(
"BoundPreprocessor::PropagateEqConstraints({})", enabled_literals);
473 bool continue_propagating;
476 continue_propagating =
false;
477 for (
auto it = enabled_literals.begin(); it != enabled_literals.end();) {
478 const Literal& lit = *it;
479 const Variable*
const var_to_propagate = ShouldPropagateEqPolynomial(lit);
480 if (var_to_propagate ==
nullptr) {
488 continue_propagating =
true;
489 it = enabled_literals.erase(it);
491 }
while (continue_propagating && explanations.empty());
492 DLINEAR_TRACE_FMT(
"BoundPreprocessor::PropagateEqConstraints: explanation -> {}", explanations);
494void BoundPreprocessor::PropagateBoundConstraints(std::list<Literal>& enabled_literals, Explanations& explanations) {
495 DLINEAR_TRACE_FMT(
"BoundPreprocessor::PropagateBoundConstraints({})", enabled_literals);
496 bool continue_propagating;
499 continue_propagating =
false;
500 for (
auto it = enabled_literals.begin(); it != enabled_literals.end();) {
501 const Literal& lit = *it;
503 const Variable*
const var_to_propagate = ShouldPropagateBoundsPolynomial(lit);
504 if (var_to_propagate ==
nullptr) {
512 continue_propagating =
true;
513 it = enabled_literals.erase(it);
515 }
while (continue_propagating && explanations.empty());
516 DLINEAR_TRACE_FMT(
"BoundPreprocessor::PropagateBoundConstraints: explanation -> {}", explanations);
519void BoundPreprocessor::EvaluateFormulas(std::list<Literal>& enabled_literals, Explanations& explanations) {
520 DLINEAR_ASSERT(explanations.empty(),
"The explanations vector must be empty");
521 DLINEAR_TRACE(
"BoundPreprocessor::EvaluateFormulas()");
522 for (
const Literal& lit : enabled_literals) {
523 if (!ShouldEvaluate(lit))
continue;
525 const bool satisfied = formula.Evaluate(
env_) == lit.truth;
527 DLINEAR_DEBUG_FMT(
"BoundPreprocessor::EvaluateFormulas: {} => FAIL", lit);
528 FormulaViolationExplanation(lit, formula, explanations);
533void BoundPreprocessor::FormulaViolationExplanation(
const Literal& lit,
const Formula& formula,
534 Explanations& explanations) {
535 DLINEAR_TRACE_FMT(
"BoundPreprocessor::FormulaViolationExplanation({})", formula);
538 explanation.insert(lit);
539 for (
const auto& var : formula.GetFreeVariables()) {
540 DLINEAR_ASSERT(
env_.
find(var) !=
env_.
end(),
"All free variables must be in the environment");
541 GetExplanation(var, explanation);
543#if DEBUGGING_PREPROCESSOR
544 const bool res = check_explanation(*
this, explanation);
546 for (
const auto& var : formula.GetFreeVariables()) {
549 GetExplanation(var, ex);
552 for (
const auto& var_name : {
"x_87",
"x_97"}) {
553 Variable var = find_variable(*
this, var_name);
556 GetExplanation(var, ex);
559 DLINEAR_ASSERT(res,
"Explanation must be valid");
562 explanations.insert(explanation);
565bool BoundPreprocessor::ShouldEvaluate(
const Literal& lit)
const {
566 DLINEAR_TRACE_FMT(
"BoundPreprocessor::ShouldEvaluate({})", lit);
568 return ShouldEvaluate(formula);
570bool BoundPreprocessor::ShouldEvaluate(
const Formula& formula)
const {
571 DLINEAR_TRACE_FMT(
"BoundPreprocessor::ShouldEvaluate({})", formula);
573 return std::all_of(formula.GetFreeVariables().begin(), formula.GetFreeVariables().end(),
574 [
this](
const Variable& v) { return env_.contains(v); });
577const Variable* BoundPreprocessor::ShouldPropagateEqPolynomial(
const Literal& lit)
const {
578 DLINEAR_TRACE_FMT(
"BoundPreprocessor::ShouldPropagateEqPolynomial({})", lit);
579 const auto& [formula_var, truth] = lit;
582 if (!
IsEqualTo(formula, truth))
return nullptr;
583 return ShouldPropagateEqPolynomial(formula);
585const Variable* BoundPreprocessor::ShouldPropagateEqPolynomial(
const Formula& formula)
const {
586 DLINEAR_TRACE_FMT(
"BoundPreprocessor::ShouldPropagateEqPolynomial({})", formula);
588 if (!is_equal_to(formula) && !is_not_equal_to(formula))
return nullptr;
589 if (formula.GetFreeVariables().size() < 2)
return nullptr;
590 DLINEAR_ASSERT(is_addition(get_lhs_expression(formula)),
"lhs expression must be an addition");
593 const Variable* missing_var =
nullptr;
594 for (
const auto& [expr, coeff] : get_expr_to_coeff_map_in_addition(get_lhs_expression(formula))) {
595 DLINEAR_ASSERT(is_variable(expr),
"All expressions in lhs formula must be variables");
598 if (missing_var !=
nullptr)
return nullptr;
599 missing_var = &get_variable(expr);
603const Variable* BoundPreprocessor::ShouldPropagateBoundsPolynomial(
const Literal& lit)
const {
604 DLINEAR_TRACE_FMT(
"BoundPreprocessor::ShouldPropagateInPolynomial({})", lit);
605 const auto& [formula_var, truth] = lit;
608 if (!is_relational(formula))
return nullptr;
610 return ShouldPropagateBoundsPolynomial(formula);
612const Variable* BoundPreprocessor::ShouldPropagateBoundsPolynomial(
const Formula& formula)
const {
613 DLINEAR_TRACE_FMT(
"BoundPreprocessor::ShouldPropagateInPolynomial({})", formula);
615 if (!is_relational(formula))
return nullptr;
616 if (formula.GetFreeVariables().size() < 2)
return nullptr;
617 DLINEAR_ASSERT(is_addition(get_lhs_expression(formula)),
"lhs expression must be an addition");
622 const Variable* missing_var =
nullptr;
623 for (
const auto& [expr, coeff] : get_expr_to_coeff_map_in_addition(get_lhs_expression(formula))) {
624 DLINEAR_ASSERT(is_variable(expr),
"All expressions in lhs formula must be variables");
625 const Variable& var = get_variable(expr);
629 if (missing_var !=
nullptr)
return nullptr;
636std::pair<Variable, Variable> BoundPreprocessor::ExtractBoundEdge(
const Formula& formula)
const {
637 DLINEAR_ASSERT(formula.GetFreeVariables().size() == 2,
"Formula should have exactly two free variables");
638 DLINEAR_ASSERT(formula.IsFlattened(),
"The formula must be flattened");
639 const Expression& lhs = get_lhs_expression(formula);
641 const std::map<Expression, mpq_class>&
map = get_expr_to_coeff_map_in_addition(lhs);
642 DLINEAR_ASSERT(
map.size() == 2,
"Expression should have exactly two variables");
643 DLINEAR_ASSERT(get_constant_value(get_rhs_expression(formula)) == 0,
"The right-hand side must be 0");
646 get_variable(
map.cbegin()->first),
647 get_variable(std::next(
map.cbegin())->first),
652 DLINEAR_ASSERT(is_equal_to(formula),
"Formula should be an equality relation");
653 DLINEAR_ASSERT(formula.
GetFreeVariables().
size() == 2,
"Formula should have exactly two free variables");
654 DLINEAR_ASSERT(formula.IsFlattened(),
"The formula must be flattened");
655 const Expression& lhs = get_lhs_expression(formula);
657 const std::map<Expression, mpq_class>&
map = get_expr_to_coeff_map_in_addition(lhs);
658 DLINEAR_ASSERT(
map.size() == 2,
"Expression should have exactly two variables");
659 DLINEAR_ASSERT(get_constant_value(get_rhs_expression(formula)) == 0,
"The right-hand side must be 0");
661 return -(std::next(
map.cbegin())->second) /
map.cbegin()->second;
671Bound BoundPreprocessor::GetSimpleBound(
const Literal& lit,
const Formula& formula)
const {
672 DLINEAR_ASSERT(
IsSimpleBound(formula),
"Formula must be a simple bound");
673 const Expression& lhs{get_lhs_expression(formula)};
674 const Expression& rhs{get_rhs_expression(formula)};
676 if (is_variable(lhs) && is_constant(rhs))
return {&get_constant_value(rhs),
LpColBound::B, lit};
677 if (is_constant(lhs) && is_variable(rhs))
return {&get_constant_value(lhs),
LpColBound::B, lit};
680 if (is_variable(lhs) && is_constant(rhs))
return {&get_constant_value(rhs),
LpColBound::SL, lit};
681 if (is_constant(lhs) && is_variable(rhs))
return {&get_constant_value(lhs),
LpColBound::SU, lit};
684 if (is_variable(lhs) && is_constant(rhs))
return {&get_constant_value(rhs),
LpColBound::L, lit};
685 if (is_constant(lhs) && is_variable(rhs))
return {&get_constant_value(lhs),
LpColBound::U, lit};
688 if (is_variable(lhs) && is_constant(rhs))
return {&get_constant_value(rhs),
LpColBound::SU, lit};
689 if (is_constant(lhs) && is_variable(rhs))
return {&get_constant_value(lhs),
LpColBound::SL, lit};
692 if (is_variable(lhs) && is_constant(rhs))
return {&get_constant_value(rhs),
LpColBound::U, lit};
693 if (is_constant(lhs) && is_variable(rhs))
return {&get_constant_value(lhs),
LpColBound::L, lit};
696 if (is_variable(lhs) && is_constant(rhs))
return {&get_constant_value(rhs),
LpColBound::D, lit};
697 if (is_constant(lhs) && is_variable(rhs))
return {&get_constant_value(lhs),
LpColBound::D, lit};
699 DLINEAR_RUNTIME_ERROR_FMT(
"Formula {} not supported", formula);
704 if (!is_relational(formula))
return false;
709 const Expression& lhs{get_lhs_expression(formula)};
710 const Expression& rhs{get_rhs_expression(formula)};
711 return ((is_constant(lhs) && is_variable(rhs)) || (is_variable(lhs) && is_constant(rhs)));
715 return truth ? is_equal_to(formula) : is_not_equal_to(formula);
719 return truth ? is_not_equal_to(formula) : is_equal_to(formula);
723 return truth ? is_greater_than(formula) : is_less_than_or_equal_to(formula);
727 return truth ? is_less_than(formula) : is_greater_than_or_equal_to(formula);
731 return truth ? is_greater_than_or_equal_to(formula) : is_less_than(formula);
735 return truth ? is_less_than_or_equal_to(formula) : is_greater_than(formula);
741 it->second.GetActiveExplanation(explanation);
744std::ostream& operator<<(std::ostream& os,
const BoundPreprocessor& preprocessor) {
745 return os <<
"BoundPreprocessor{" <<
"env_ = " << preprocessor.env() <<
", "
746 <<
"theory_bounds_ = " << preprocessor.theory_bounds() <<
"}";
LiteralSet explanation() const
Produce and explanation formed by all the theory literals present in the violation.
This class uses some basic algebraic operations to preprocess the constraints and identify violations...
static bool IsSimpleBound(const Formula &formula)
Check whether the formula is a simple relational bound.
static bool IsGreaterThan(const Formula &formula, bool truth=true)
Check whether the formula is a simple relational bound with a greater than operator ( ).
std::list< mpq_class > temporary_mpq_vector_
Vector used to store temporary mpq values obtained from more complex constraints.
bool PropagateEqPolynomial(const Literal &lit, const Variable &var_to_propagate, Explanations &explanations)
Propagate the bounds of the variables in the given formula.
const mpq_class * StoreTemporaryMpq(const mpq_class &value)
Vector used to store the mpq_class elements obtained from more complex constraints.
static bool IsLessThan(const Formula &formula, bool truth=true)
Check whether the formula is a simple relational bound with a less than operator ( ).
static bool IsLessThanOrEqualTo(const Formula &formula, bool truth=true)
Check whether the formula is a simple relational bound with a less than or equal to operator ( ).
BoundPreprocessor(const PredicateAbstractor &predicate_abstractor)
Construct a new Bound Preprocessor object using the predicate_abstractor.
static bool IsNotEqualTo(const Formula &formula, bool truth=true)
Check whether the formula is a simple relational bound with a non-equality operator ( ).
std::set< LiteralSet > EnableLiteral(const Literal &lit)
Enable the literal lit.
std::set< LiteralSet > EnableLiterals(const std::vector< Literal > &enabled_literals)
Preprocess all the enabled_literals.
void SetInfinityBounds(const Variable &var, const mpq_class &lb, const mpq_class &ub)
Set the lower and upper infinity bounds (lb, ub) of the variable var.
IterationStats stats_
Statistics of the preprocessing.
mpq_class ExtractEqBoundCoefficient(const Formula &formula) const
Given a formula of the form , with being constants, extract the coefficient .
const Config & config_
Configuration of the preprocessor.
bool PropagateBoundsPolynomial(const Literal &lit, const Variable &var_to_propagate, Explanations &explanations)
Propagate the bounds of the variables in the given formula.
void Clear()
Clear the preprocessor.
void GetActiveExplanation(const Variable &var, LiteralSet &explanation)
Get the active explanation for the variable var.
Explanations Process()
Process all enabled literals.
BoundVectorMap theory_bounds_
Theory bounds for each theory variable.
static bool IsGreaterThanOrEqualTo(const Formula &formula, bool truth=true)
Check whether the formula is a simple relational bound with a less than or equal to operator ( ).
static bool IsEqualTo(const Formula &formula, bool truth=true)
Check whether the formula is a simple relational bound with an equality operator ( ).
const PredicateAbstractor & predicate_abstractor_
Predicate abstractor used to get the constraints from the literals.
Environment env_
Environment storing the values of all the variables with a fixed value.
void AddVariable(const Variable &var)
Add a theory variable to the preprocessor.
Data structure to store the LP solver bounds in a sorted vector to determine the active lower and upp...
const mpq_class * GetActiveEqualityBound() const
Return the active equality bound.
const mpq_class & active_lower_bound() const
Get read-only access to the active_lower_bound of the BoundVector.
bool RemoveBound(const Bound &bound)
Remove bound from the vector if it is present.
BoundIterator AddBound(const Bound &bound)
Add a new bound to the vector.
const mpq_class & active_upper_bound() const
Get read-only access to the active_upper_bound of the BoundVector.
BoundPropagationType actual_bound_propagation_type() const
Get read-only access to the actual actual_bound_propagation_type parameter of the configuration.
@ EQ_POLYNOMIAL
Only propagate bound in theory formulae in the form .
@ BOUND_POLYNOMIAL
Propagate all possible constraints.
@ NEVER
Never run this preprocess, effectively disabling it.
PreprocessingRunningFrequency actual_bound_propagation_frequency() const
Get read-only access to the actual bound_propagation_frequency parameter of the configuration.
static const mpq_class & ninfinity(const Config &config)
Get the negative infinity value for the given LP solver in the config.
static const mpq_class & infinity(const Config &config)
Get the positive infinity value for the given LP solver in the config.
void Increase()
Increase the iteration counter by one.
Predicate abstraction is a method to convert a first-order logic formula into a Boolean formula.
Timer & m_timer()
Get read-write access to the timer of the stats.
bool enabled() const
Check whether the stats is enabled.
The TimeGuard wraps a timer object and pauses it when the guard object is destructed.
Represents a symbolic environment (mapping from a variable to a value).
const mapped_type & at(const key_type &key) const
Returns the value that is mapped to a key equivalent to key.
iterator find(const key_type &key)
Finds element with specific key.
iterator end()
Returns an iterator to the end.
std::pair< Environment::iterator, bool > insert(const key_type &key, const mapped_type &elem)
Inserts a pair (key, elem).
const_iterator cend() const
Returns a const iterator to the end.
bool contains(const key_type &key) const
Checks whether the environment contains a variable key.
std::size_t erase(const key_type &key)
Erases the element with specific key.
Represents a symbolic form of an expression.
Represents a symbolic variable.
bool is_dummy() const
Checks if this is a dummy variable (ID = 0) which is created by the default constructor.
bool equal_to(const Variable &v) const
Checks the equality of two variables based on their ID values.
size_type size() const
Returns the number of elements.
const_iterator cbegin() const
Returns a const iterator to the beginning.
Global namespace for the dlinear library.
std::set< Formula > map(const std::set< Formula > &formulas, const std::function< Formula(const Formula &)> &func)
Given formulas = {fâ, ..., fâ} and a func : Formula â Formula, map(formulas, func) returns a set {fun...
@ SAT_UNSATISFIABLE
The problem is unsatisfiable.
@ B
Both upper and lower bound are equal (fixed)
@ D
Variable must be different from the bound.
std::set< Literal > LiteralSet
A set of literals.
Tuple containing the value, bound type and theory literal associated with the bound.
LiteralSet explanation
Explanation for the existence of the bound (e.g. propagation)
A literal is a variable with an associated truth value, indicating whether it is true or false.