dlinear  0.0.1
Delta-complete SMT solver for linear programming
Loading...
Searching...
No Matches
TheorySolver.cpp
1
6#include "TheorySolver.h"
7
8#include "dlinear/util/exception.h"
9#include "dlinear/util/logging.h"
10
11namespace dlinear {
12
13TheorySolver::TheorySolver(const PredicateAbstractor &predicate_abstractor, const std::string &class_name)
14 : config_{predicate_abstractor.config()},
15 is_consolidated_{false},
16 predicate_abstractor_{predicate_abstractor},
17 fixed_preprocessor_{predicate_abstractor},
18 preprocessor_{predicate_abstractor},
19 model_{config_.lp_solver()},
20 stats_{config_.with_timings(), class_name, "Total time spent in CheckSat", "Total # of CheckSat"} {}
21
22const Box &TheorySolver::model() const { return model_; }
23std::set<Literal> TheorySolver::enabled_literals() const {
24 std::set<Literal> enabled_lits{};
25 for (std::size_t i = 0; i < theory_row_to_lit_.size(); ++i) {
26 if (theory_rows_state_[i]) enabled_lits.insert(theory_row_to_lit_[i]);
27 }
28 for (const auto &[var, bound] : preprocessor_.theory_bounds()) {
29 const BoundIterator it = bound.GetActiveBounds();
30 it.explanation(enabled_lits);
31 }
32 return enabled_lits;
33}
34
39
41 DLINEAR_TRACE_FMT("TheorySolver::PreprocessFixedLiterals({})", fixed_literals);
42 DLINEAR_ASSERT(is_consolidated_, "Fixed literals can be preprocessed only after consolidation");
43 Explanations explanations{};
44 for (const Literal &lit : fixed_literals) fixed_preprocessor_.EnableLiteral(lit, explanations);
47 fixed_preprocessor_.Process(explanations);
48 }
50 DLINEAR_TRACE_FMT("TheorySolver::PreprocessFixedLiterals() -> {}", explanations);
51 return explanations;
52}
53
54TheorySolver::Explanations TheorySolver::EnableLiterals(const std::span<const Literal> theory_literals) {
55 Explanations explanations{};
56 for (const Literal &lit : theory_literals) {
57 const Explanations explanation{EnableLiteral(lit)};
58 // Check if the literal that was just enabled is conflicting with the current model.
59 // If so, return the explanation containing a superset of the conflicting literals
60 explanations.insert(explanation.begin(), explanation.end());
61 }
62 return explanations;
63}
64
66 DLINEAR_TRACE("TheorySolver::UpdateExplanation()");
67 LiteralSet explanation{};
68 UpdateExplanation(explanation);
69 explanations.insert(explanation);
70}
71
73 if (is_consolidated_) return;
74 DLINEAR_DEBUG("TheorySolver::Consolidate()");
75 theory_rows_state_.resize(theory_row_to_lit_.size(), false);
76 is_consolidated_ = true;
77}
78
80 DLINEAR_TRACE("TheorySolver::Reset()");
81 DLINEAR_ASSERT(is_consolidated_, "The solver must be consolidate before resetting it");
82 // Clear constraint bounds, keeping only the fixed ones
84 // Disable all rows
85 theory_rows_state_.assign(theory_rows_state_.size(), false);
86}
87
88#ifndef NDEBUG
89void TheorySolver::DumpEnabledLiterals() {
90 fmt::println("(set-logic QF_LRA)");
91 for (const auto &[var, bound] : preprocessor_.theory_bounds()) {
92 fmt::println("(declare-const {} Real)", var);
93 }
94 for (const auto &lit : enabled_literals()) {
95 fmt::println("(assert {})", lit.truth ? predicate_abstractor_[lit.var].to_smt2_string()
96 : (!predicate_abstractor_[lit.var]).to_smt2_string());
97 }
98 fmt::println("(check-sat)");
99 fmt::println("(exit)");
100}
101#endif
102
103void TheorySolver::BoundsToTheoryRows(const Variable &var, BoundViolationType type, std::set<int> &theory_rows) const {
104 if (type == BoundViolationType::NO_BOUND_VIOLATION) return;
105 auto it = preprocessor_.theory_bounds().find(var);
106 if (it == preprocessor_.theory_bounds().end()) return;
107 const BoundVector &bound = it->second;
108 return BoundsToTheoryRows(
109 var, type == BoundViolationType::LOWER_BOUND_VIOLATION ? bound.active_lower_bound() : bound.active_upper_bound(),
110 theory_rows);
111}
112void TheorySolver::BoundsToTheoryRows(const Variable &var, const mpq_class &value, std::set<int> &theory_rows) const {
113 auto bound_it = preprocessor_.theory_bounds().find(var);
114 if (bound_it == preprocessor_.theory_bounds().end()) return;
115 const BoundVector &bound = bound_it->second;
116 for (auto it = bound.GetActiveBound(value); it; ++it) {
117 theory_rows.insert(lit_to_theory_row_.at(it->theory_literal.var.get_id()));
118 for (const Literal &exp : it->explanation) theory_rows.insert(lit_to_theory_row_.at(exp.var.get_id()));
119 }
120}
121SatResult TheorySolver::CheckSat(const Box &box, mpq_class *actual_precision, std::set<LiteralSet> &explanations) {
122 TimerGuard timer_guard(&stats_.m_timer(), stats_.enabled());
124
125 DLINEAR_TRACE_FMT("TheorySolver::CheckSat: Box = \n{}", box);
126 DLINEAR_ASSERT(is_consolidated_, "The solver must be consolidate before CheckSat");
127
128 model_ = box;
129 DLINEAR_ASSERT(std::all_of(theory_col_to_var_.begin(), theory_col_to_var_.end(),
130 [&box](const Variable &var) { return box.has_variable(var); }),
131 "All theory variables must be present in the box");
132
133 // If we can immediately return SAT afterward
134 if (theory_row_to_lit_.empty()) {
135 DLINEAR_DEBUG("TheorySolver::CheckSat: no need to call LP solver");
138 }
139
142 timer_guard.Pause(); // Pause the timer to measure the time spent in the preprocessor
143 preprocessor_.Process(explanations);
144 timer_guard.Resume();
145 DLINEAR_DEBUG("TheorySolver::CheckSat: conflict detected in preprocessing");
146 if (!explanations.empty()) return SatResult::SAT_UNSATISFIABLE;
147 }
148
149 DLINEAR_DEV_DEBUG_FMT("TheorySolver::CheckSat: running {}", config_.lp_solver());
150 return CheckSatCore(actual_precision, explanations);
151}
152
153} // namespace dlinear
BoundIterator class.
LiteralSet explanation() const
Produce and explanation formed by all the theory literals present in the violation.
const BoundVectorMap & theory_bounds() const
Get read-only access to the bounds of the variables in the LP solver of the BoundPreprocessor.
std::set< LiteralSet > EnableLiteral(const Literal &lit)
Enable the literal lit.
void Clear()
Clear the preprocessor.
Explanations Process()
Process all enabled literals.
Collection of variables with associated intervals.
Definition Box.h:31
const LPSolver & lp_solver() const
Get read-write access to the lp_solver parameter of the configuration.
Definition Config.h:184
@ ON_ITERATION
Run this preprocess only at every iteration.
@ ON_FIXED
Run this preprocess only once, on fixed literals, before all iterations.
@ ALWAYS
Run this preprocess at every chance it gets. Usually combines ON_FIXED and ON_ITERATION.
PreprocessingRunningFrequency actual_bound_propagation_frequency() const
Get read-only access to the actual bound_propagation_frequency parameter of the configuration.
Definition Config.cpp:65
void Increase()
Increase the iteration counter by one.
Definition Stats.cpp:39
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...
Timer & m_timer()
Get read-write access to the timer of the stats.
Definition Stats.h:50
bool enabled() const
Check whether the stats is enabled.
Definition Stats.h:48
virtual void Reset()
Reset the linear problem.
BoundPreprocessor preprocessor_
Preprocessor for the bounds.
virtual SatResult CheckSatCore(mpq_class *actual_precision, std::set< LiteralSet > &explanations)=0
Check the satisfiability of the theory.
const BoundVectorMap & theory_bounds() const
Get read-only access to the bounds of each theory variable of the TheorySolver.
Box model_
Model produced by the theory solver.
virtual void UpdateModelBounds()=0
Update each variable in the model with the bounds passed to the theory solver.
std::vector< Literal > theory_row_to_lit_
Theory row ⇔ Literal The row is the constraint used by the theory solver.
virtual void AddLiteral(const Variable &formula_var, const Formula &formula)=0
Add a Literal to the theory solver.
TheorySolver(const PredicateAbstractor &predicate_abstractor, const std::string &class_name="TheorySolver")
Construct a new Theory Solver object.
virtual Explanations PreprocessFixedLiterals(const LiteralSet &fixed_literals)
Add the fixed literals to the theory solver.
std::map< Variable::Id, int > lit_to_theory_row_
Literal ⇔ theory row.
std::vector< bool > theory_rows_state_
Whether each theory row is enabled or not.
@ NO_BOUND_VIOLATION
The bounds of the variable have no role in the infeasibility.
@ LOWER_BOUND_VIOLATION
The lower bound is involved in the infeasibility.
const Config & config_
Configuration of the theory solver.
std::set< Literal > enabled_literals() const
Get read-only access to the vector of enabled literals of the TheorySolver.
virtual void UpdateExplanation(LiteralSet &explanation)=0
Use the result from the theory solver to update the explanation with the conflict that has been detec...
std::set< LiteralSet > Explanations
Set of explanations of the conflict.
const PredicateAbstractor & predicate_abstractor_
Predicate abstractor used to create the theory solver.
Explanations EnableLiterals(std::span< const Literal > theory_literals)
Activate the literals that have previously been added to the theory solver.
bool is_consolidated_
Whether the solver has been consolidated.
const Box & model() const
Get read-only access to the model that satisfies all the constraints of the TheorySolver.
virtual void AddLiterals()
Add a vector of literals to the theory solver.
BoundPreprocessor fixed_preprocessor_
Preprocessor for the bounds. Only computed on fixed literal theories.
virtual Explanations EnableLiteral(const Literal &lit)=0
Activate the literal that had previously been added to the theory solver.
void UpdateExplanations(Explanations &explanations)
Use the result from the theory solver to update the explanations with the conflict that has been dete...
virtual void Consolidate(const Box &box)
Consolidate the solver.
std::vector< Variable > theory_col_to_var_
Theory column ⇔ Variable.
SatResult CheckSat(const Box &box, mpq_class *actual_precision, std::set< LiteralSet > &explanations)
Check the satisfiability of the theory.
IterationStats stats_
Statistics of the theory solver.
The TimeGuard wraps a timer object and pauses it when the guard object is destructed.
Definition Timer.h:129
void Resume()
Resume the guarded timer object.
Definition Timer.cpp:85
void Pause()
Pause the guarded timer object.
Definition Timer.cpp:81
Represents a symbolic variable.
Global namespace for the dlinear library.
SatResult
Result of running the theory solver over the literals decided by the SAT solver.
Definition SatResult.h:17
@ SAT_SATISFIABLE
The problem is satisfiable.
@ SAT_UNSATISFIABLE
The problem is unsatisfiable.
std::set< Literal > LiteralSet
A set of literals.
Definition literal.h:28
A literal is a variable with an associated truth value, indicating whether it is true or false.
Definition literal.h:24