6#include "BoundImplicator.h"
10#include "dlinear/util/exception.h"
16 : config_{config}, assert_{
std::move(assert)}, predicate_abstractor_{predicate_abstractor} {}
20 DLINEAR_ASSERT(assertion.
GetFreeVariables().
size() == 1u,
"Assertion must have exactly one free variable");
21 DLINEAR_ASSERT(is_relational(assertion),
"Assertion must be relational");
22 const Expression& lhs = get_lhs_expression(assertion);
23 const Expression& rhs = get_rhs_expression(assertion);
24 DLINEAR_ASSERT((is_variable(lhs) || is_multiplication(lhs)) && is_constant(rhs),
25 "lhs must be a variable or multiplication and rhs must be a constant");
27 const mpq_class& constant = get_constant_value(rhs);
33 if (is_variable(lhs)) {
34 const Variable& var = get_variable(lhs);
35 constraints_[var].emplace(constant, row_sense, bool_var);
37 DLINEAR_ASSERT(is_multiplication(lhs),
"lhs must be a multiplication");
38 const auto& base_to_exponent_map = get_base_to_exponent_map_in_multiplication(lhs);
39 DLINEAR_ASSERT(base_to_exponent_map.size() == 1,
"lhs must have exactly one base");
40 DLINEAR_ASSERT(is_variable(base_to_exponent_map.begin()->first),
"lhs' base must be a variable");
41 const Variable& var = get_variable(base_to_exponent_map.begin()->first);
42 DLINEAR_ASSERT(is_variable(var),
"lhs base must be a variable");
43 const mpq_class& coeff = get_constant_in_multiplication(lhs);
44 constraints_[var].emplace(constant / coeff, row_sense, bool_var);
50 "Method Propagate should not be called with a frequency of NEVER");
52 if (!is_relational(assertion)) {
53 fmt::println(
"Assertion must be relational. Skipping.");
70 if (constraints.size() <= 1)
continue;
76 for (
const Constraint& constraint : constraints) {
77 const auto& [value, sense, bool_var] = constraint;
79 if (last_l_constraint !=
nullptr) {
80 DLINEAR_TRACE_FMT(
"BoundImplicator::PropagateAssertions: {} => {}",
84 last_l_constraint = &constraint;
88 if (last_l_constraint ==
nullptr)
continue;
90 DLINEAR_TRACE_FMT(
"BoundImplicator::PropagateAssertions: {} => {}",
98 for (
const Constraint& constraint : std::views::reverse(constraints)) {
99 const auto& [value, sense, bool_var] = constraint;
101 if (last_g_constraint !=
nullptr) {
102 DLINEAR_TRACE_FMT(
"BoundImplicator::PropagateAssertions: {} => {}",
106 last_g_constraint = &constraint;
110 if (last_g_constraint ==
nullptr)
continue;
112 DLINEAR_TRACE_FMT(
"BoundImplicator::PropagateAssertions: {} => {}",
119 const Constraint* last_eq_constraint =
nullptr;
120 for (
const Constraint& constraint : constraints) {
121 const auto& [value, sense, bool_var] = constraint;
123 if (last_eq_constraint !=
nullptr) {
124 if (value == last_eq_constraint->
value) {
125 DLINEAR_TRACE_FMT(
"BoundImplicator::PropagateAssertions: {} <=> {}",
130 DLINEAR_TRACE_FMT(
"BoundImplicator::PropagateAssertions: {} || {}",
134 last_eq_constraint = &constraint;
142std::strong_ordering BoundImplicator::Constraint::operator<=>(
const BoundImplicator::Constraint& o)
const {
143 const auto& [value_l, type_l, bool_var_l] = *
this;
144 const auto& [value_r, type_r, bool_var_r] = o;
145 if (value_l < value_r)
return std::strong_ordering::less;
146 if (value_l > value_r)
return std::strong_ordering::greater;
147 if (type_l < type_r)
return std::strong_ordering::less;
148 if (type_l > type_r)
return std::strong_ordering::greater;
149 if (bool_var_l->less(*bool_var_r))
return std::strong_ordering::less;
150 if (bool_var_l->equal_to(*bool_var_r))
return std::strong_ordering::equal;
151 return std::strong_ordering::greater;
void PropagateAssertions()
Propagate the sorted constraints by adding them to the context by calling the assert_ function.
const PredicateAbstractor & predicate_abstractor_
Predicate abstractor.
void Propagate()
Use theory reasoning to propagate some simple theory inferences.
std::map< Variable, SortedVector< Constraint > > constraints_
Map of constraints for each variable.
BoundImplicator(const Config &config, std::function< void(const Formula &)> assert, const PredicateAbstractor &predicate_abstractor)
Construct a BoundImplicator.
const Config & config_
Configuration.
void AddAssertion(const Formula &assertion)
Add an assertion to the constraints_ map.
const std::function< void(const Formula &)> assert_
Assertion function. It adds assertions to the context.
Simple dataclass used to store the configuration of the program.
PreprocessingRunningFrequency actual_bound_implication_frequency() const
Get read-only access to the actual bound_implication_frequency parameter of the configuration.
@ NEVER
Never run this preprocess, effectively disabling it.
Predicate abstraction is a method to convert a first-order logic formula into a Boolean formula.
const std::unordered_map< Variable, Formula > & var_to_formula_map() const
Get read-only access to the map of previously converted formulae to variable of the PredicateAbstract...
Represents a symbolic form of an expression.
Represents a symbolic variable.
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.
Global namespace for the dlinear library.
Formula iff(const Formula &f1, const Formula &f2)
Return a formula f1 ⇔ f2.
Formula imply(const Formula &f1, const Formula &f2)
Return a formula f1 ⇒ f2.
LpRowSense parseLpSense(const Formula &f)
Parse the sense from a formula.
LpRowSense
Sense of a linear programming row describing a constraint.
@ LE
Less than or equal to.
mpq_class value
Value of the constraint.
LpRowSense row_sense
Type of the constraint (e.g. <=, <, =, >, >=)
const Variable * variable
Boolean variable encoding the constraint.