dlinear  0.0.1
Delta-complete SMT solver for linear programming
Loading...
Searching...
No Matches
ContextImpl.cpp
1
6#include "ContextImpl.h"
7
8#include <iostream>
9#include <stdexcept>
10#include <utility>
11#include <vector>
12
13#include "dlinear/solver/BoundImplicator.h"
14#include "dlinear/solver/CadicalSatSolver.h"
15#include "dlinear/solver/PicosatSatSolver.h"
16#include "dlinear/solver/SatResult.h"
17#include "dlinear/symbolic/IfThenElseEliminator.h"
18#include "dlinear/symbolic/literal.h"
19#include "dlinear/util/OptionValue.hpp"
20#include "dlinear/util/Stats.h"
21#include "dlinear/util/exception.h"
22#include "dlinear/util/logging.h"
23
24#ifdef DLINEAR_PYDLINEAR
25#include "pydlinear/interrupt.h"
26#endif
27#ifdef DLINEAR_ENABLED_QSOPTEX
28#include "dlinear/solver/DeltaQsoptexTheorySolver.h"
29#endif
30#ifdef DLINEAR_ENABLED_SOPLEX
31#include "dlinear/solver/CompleteSoplexTheorySolver.h"
32#include "dlinear/solver/DeltaSoplexTheorySolver.h"
33#include "dlinear/solver/NNSoplexTheorySolver.h"
34#endif
35
36namespace {
37
38bool ParseBooleanOption([[maybe_unused]] const std::string &key, const std::string &val) {
39 if (val == "true") return true;
40 if (val == "false") return false;
41 DLINEAR_INVALID_ARGUMENT_EXPECTED(key, val, "bool [true, false]");
42}
43double ParseDoubleOption([[maybe_unused]] const std::string &key, const std::string &val) {
44 try {
45 return std::stod(val);
46 } catch (const std::invalid_argument &e) {
47 DLINEAR_INVALID_ARGUMENT_EXPECTED(key, val, "double");
48 } catch (const std::out_of_range &e) {
49 DLINEAR_OUT_OF_RANGE_FMT("Out of range value {} is provided for option {}. Expected double", val, key);
50 }
51}
52
53} // namespace
54
55namespace dlinear {
56
58 : config_{config},
59 output_{output},
60 logic_{},
61 model_{config_.lp_solver()},
62 have_objective_{false},
63 is_max_{false},
64 predicate_abstractor_{config},
65 ite_eliminator_{config},
66 sat_solver_{GetSatSolver()},
67 theory_solver_{GetTheorySolver()} {
68 boxes_.push_back(Box{config_.lp_solver()});
69}
70
72 if (is_true(f)) return; // Skip trivially true assertions.
73 if (is_false(f)) { // The formula is false. No point in adding it to the SAT solver. There is no point in continuing
74 stack_.push_back(f);
75 return;
76 }
77
78 DLINEAR_DEBUG_FMT("ContextImpl::Assert({})", f);
79 const Formula no_ite{ite_eliminator_.Process(f)};
80
81 // Note that the following does not mark `ite_var` as a model variable.
82 for (const auto &[ite_expr, ite_var] : ite_eliminator_.variables()) AddToBox(ite_var);
83 stack_.push_back(no_ite);
84 sat_solver_->AddFormula(no_ite);
85}
86void Context::Impl::AssertPiecewiseLinearFunction(const Variable &var, const Formula &cond, const Expression &active,
87 const Expression &inactive) {
88 DLINEAR_TRACE_FMT("ContextImpl::AssertPiecewiseLinearFunction({})", var);
89 DLINEAR_ASSERT(!var.is_dummy() && var.get_type() == Variable::Type::CONTINUOUS, "Variable must be a real variable");
90 DLINEAR_ASSERT(is_relational(cond), "Condition must be a relational formula");
91
92 const Formula condition_lit = predicate_abstractor_(cond);
93 const Formula active_lit = predicate_abstractor_(var - active == 0);
94 const Formula inactive_lit = predicate_abstractor_(var - inactive == 0);
95 // Make sure the cond is assigned a value (true or false) in the SAT solver
96 const Formula force_assignment(condition_lit || !condition_lit);
97 const Formula active_assertion{active_lit || !condition_lit};
98 const Formula inactive_assertion{inactive_lit || condition_lit};
99
100 DeclareVariable(var, false);
101 stack_.push_back(force_assignment);
102 stack_.push_back(active_assertion);
103 stack_.push_back(inactive_assertion);
104 sat_solver_->AddClause(force_assignment);
105 sat_solver_->AddClause(active_assertion);
106 sat_solver_->AddClause(inactive_assertion);
107}
108
109const PiecewiseLinearConstraint &Context::Impl::AddGuidedConstraint(
110 std::unique_ptr<PiecewiseLinearConstraint> &&constraint) {
111 return *pl_constraints_.emplace_back(std::move(constraint)).get();
112}
113
115 DLINEAR_DEBUG("ContextImpl::Pop()");
116 stack_.pop();
117 boxes_.pop();
118 sat_solver_->Pop();
119}
120
122 DLINEAR_DEBUG("ContextImpl::Push()");
123 sat_solver_->Push();
124 boxes_.push();
125 boxes_.push_back(boxes_.last());
126 stack_.push();
127}
128
129SatResult Context::Impl::CheckSat(mpq_class *precision) {
130 if (!logic_.has_value()) DLINEAR_WARN("Logic is not set. Defaulting to QF_LRA.");
131 if (config_.skip_check_sat()) {
132 DLINEAR_DEBUG("ContextImpl::CheckSat() - Skipping SAT check");
133 UpdateAndPrintOutput(SmtResult::SKIP_SAT);
135 }
136
137 const SatResult result = CheckSatCore(precision);
138 switch (result) {
141 model_ = ExtractModel(box());
142 DLINEAR_DEBUG_FMT("ContextImpl::CheckSat() - Found Model\n{}", model_);
143 break;
145 DLINEAR_DEBUG("ContextImpl::CheckSat() - Model not found");
146 model_.set_empty();
147 break;
149 DLINEAR_DEBUG("ContextImpl::CheckSat() - Unknown");
150 model_.set_empty();
151 break;
152 default:
153 DLINEAR_UNREACHABLE();
154 }
155
156 if (output_ == nullptr) return result;
157 DLINEAR_DEBUG("ContextImpl::CheckSat() - Setting output");
158 output_->actual_precision = *precision;
159 UpdateAndPrintOutput(parse_smt_result(result));
160 return result;
161}
162
163LpResult Context::Impl::CheckOpt(mpq_class *obj_lo, mpq_class *obj_up) {
164 if (!logic_.has_value()) DLINEAR_WARN("Logic is not set. Defaulting to QF_LRA.");
165 if (config_.skip_check_sat()) {
166 DLINEAR_DEBUG("ContextImpl::CheckOpt() - Skipping SAT check");
167 UpdateAndPrintOutput(SmtResult::SKIP_SAT);
169 }
170 const LpResult result = CheckOptCore(obj_lo, obj_up);
171 if (LpResult::LP_DELTA_OPTIMAL == result || LpResult::LP_OPTIMAL == result) {
172 model_ = ExtractModel(box());
173 DLINEAR_DEBUG_FMT("ContextImpl::CheckOpt() - Found Model\n{}", model_);
174 } else {
175 DLINEAR_DEBUG("ContextImpl::CheckOpt() - Model not found");
176 model_.set_empty();
177 }
178
179 if (output_ == nullptr) return result;
180 DLINEAR_DEBUG("ContextImpl::CheckSat() - Setting output");
181 output_->lower_bound = *obj_lo;
182 output_->upper_bound = *obj_up;
183 UpdateAndPrintOutput(parse_smt_result(result));
184 return result;
185}
186
188 DLINEAR_DEBUG_FMT("ContextImpl::AddToBox({})", v);
189 if (!box().has_variable(v)) box().Add(v);
190}
191
192void Context::Impl::DeclareVariable(const Variable &v, const bool is_model_variable) {
193 DLINEAR_DEBUG_FMT("ContextImpl::DeclareVariable({})", v);
194 AddToBox(v);
195 if (is_model_variable) MarkModelVariable(v);
196}
197
198void Context::Impl::SetDomain(const Variable &v, const Expression &lb, const Expression &ub) {
199 DLINEAR_TRACE_FMT("ContextImpl::SetDomain({}, [{}, {}])", v, lb, ub);
200 const mpq_class &lb_fp = lb.Evaluate();
201 const mpq_class &ub_fp = ub.Evaluate();
202 SetInterval(v, lb_fp, ub_fp);
203}
204
205void Context::Impl::Minimize(const Expression &obj_function) {
206 is_max_ = false;
207 MinimizeCore(obj_function);
208}
209
210void Context::Impl::Maximize(const Expression &obj_function) {
211 is_max_ = true;
212 MinimizeCore((-obj_function).Expand());
213}
214
215void Context::Impl::SetInfo(const std::string &key, const std::string &val) {
216 DLINEAR_DEBUG_FMT("ContextImpl::SetInfo({} ↦ {})", key, val);
217 info_[key] = val;
218}
219
220std::string Context::Impl::GetInfo(const std::string &key) const {
221 const auto it = info_.find(key);
222 if (it == info_.end()) return "";
223 return it->second;
224}
225
226void Context::Impl::SetInterval(const Variable &v, const mpq_class &lb, const mpq_class &ub) {
227 DLINEAR_DEBUG_FMT("ContextImpl::SetInterval({} = [{}, {}])", v, lb, ub);
228 if (lb > ub) DLINEAR_RUNTIME_ERROR_FMT("Lower bound {} is greater than upper bound {}.", lb, ub);
229 box()[v] = Interval{lb, ub};
230}
231
233 DLINEAR_DEBUG_FMT("ContextImpl::SetLogic({})", logic);
234 switch (logic) {
235 case Logic::QF_LRA:
236 logic_ = logic;
237 break;
238 case Logic::LRA:
239 default:
240 DLINEAR_RUNTIME_ERROR_FMT("Unsupported logic: {}", logic);
241 }
242}
243
244void Context::Impl::SetOption(const std::string &key, const std::string &val) {
245 DLINEAR_DEBUG_FMT("ContextImpl::SetOption({} ↦ {})", key, val);
246 option_[key] = val;
247 if (key == ":precision") config_.m_precision().SetFromFile(ParseDoubleOption(key, val));
248 if (key == ":produce-models") return config_.m_produce_models().SetFromFile(ParseBooleanOption(key, val));
249}
250
251std::string Context::Impl::GetOption(const std::string &key) const {
252 if (key == ":produce-models") return fmt::format("{}", config_.produce_models());
253 if (key == ":precision") return fmt::format("{}", config_.precision());
254 const auto it = option_.find(key);
255 if (it == option_.end()) return "";
256 return it->second;
257}
258
260 if (static_cast<int>(model_variables_.size()) == box.size()) {
261 // Every variable is a model variable. Simply return the @p box.
262 return box;
263 }
264 Box new_box{config_.lp_solver()};
265 for (const Variable &v : box.variables()) {
266 if (IsModelVariable(v)) {
267 new_box.Add(v, box[v].lb(), box[v].ub());
268 }
269 }
270 return new_box;
271}
272
274 return model_variables_.find(v.get_id()) != model_variables_.end();
275}
276
277void Context::Impl::MarkModelVariable(const Variable &v) { model_variables_.insert(v.get_id()); }
278
279const ScopedVector<Formula> &Context::Impl::assertions() const { return stack_; }
280
281bool Context::Impl::have_objective() const { return have_objective_; }
282
283bool Context::Impl::is_max() const { return is_max_; }
284
285[[nodiscard]] bool Context::Impl::Verify(const Box &model) const {
286 Environment env;
287 for (int i = 0; i < model.size(); i++) {
288 const Variable &var = model.variable(i);
289 const Interval &val = model.interval_vector()[i];
290 DLINEAR_ASSERT(!val.is_empty(), "Variable cannot have an empty value interval");
291 env.insert(var, val.ub());
292 }
293 for (const Formula &assertion : stack_) {
294 if (!assertion.Evaluate(env)) {
295 DLINEAR_ERROR_FMT("Not satisfied clause: {} - model {}", assertion, model);
296 return false;
297 }
298 }
299 return true;
300}
301
302SatResult Context::Impl::CheckSatCore(mpq_class *actual_precision) {
303 DLINEAR_DEBUG("ContextImpl::CheckSatCore()");
304 DLINEAR_TRACE_FMT("ContextImpl::CheckSat: Box =\n{}", box());
305
306 // If false ∈ stack, it's UNSAT.
307 for (const Formula &f : stack_.get_vector()) {
308 if (is_false(f)) {
309 DLINEAR_DEBUG_FMT("ContextImpl::CheckSat: Found false formula = {}", f);
311 }
312 }
313 // If stack = ∅ or stack = {true}, it's trivially SAT.
314 // std::all_of(stack_.get_vector().begin(), stack_.get_vector().end(), drake::symbolic::is_true);
315 if (stack_.empty() || (stack_.size() == 1 && is_true(stack_.first()))) {
316 DLINEAR_DEBUG_FMT("ContextImpl::CheckSatCore() - Found Model\n{}", box());
318 }
319
320 DLINEAR_DEV_FMT("STATE: {}", fmt::join(assertions(), "\n"));
321
322 // Temporarily disable to study the effect of guided constraints
323 if (config_.actual_bound_implication_frequency() != Config::PreprocessingRunningFrequency::NEVER) {
324 // Add some theory constraints to the SAT solver (e.g. (x > 0) => (x > -1))
325 BoundImplicator propagator{config_, [this](const Formula &f) { sat_solver_->AddFormula(f); },
326 predicate_abstractor_};
327 propagator.Propagate();
328 }
329
330 // Add the theory literals from the SAT solver to the theory solver.
331 theory_solver_->AddLiterals();
332 theory_solver_->Consolidate(box());
333
334 // Preprocess the fixed theory literals to avoid having to preprocess them again and again.
335 DLINEAR_TRACE_FMT("Fixed theory literals: {}", sat_solver_->FixedTheoryLiterals());
336 const std::set<LiteralSet> explanations{theory_solver_->PreprocessFixedLiterals(sat_solver_->FixedTheoryLiterals())};
337 if (!explanations.empty()) {
338 DLINEAR_DEBUG("ContextImpl::CheckSatCore() - Fixed bound check = UNSAT");
339 LearnExplanations(explanations);
341 }
342
343 DLINEAR_DEV("Start tightening bounds");
344 // Check the current constraints to see if there is anything that could be used to use for the guided constraints
345 for (const std::unique_ptr<PiecewiseLinearConstraint> &constraint : pl_constraints_) {
346 const std::set<LiteralSet> tight_explanations{constraint->TightenBounds(theory_solver_->m_fixed_preprocessor())};
347 DLINEAR_DEV_TRACE_FMT("Tighten Bounds: {} - {}", constraint->theory_var(), *constraint);
348 if (tight_explanations.empty()) continue;
349 DLINEAR_DEV_DEBUG("ContextImpl::CheckSatCore() - Tightening bounds check = UNSAT");
350 LearnExplanations(tight_explanations);
352 }
353 theory_solver_->Reset();
354
355 for (auto it = pl_constraints_.begin(); it != pl_constraints_.end();) {
356 const LiteralSet learned_clauses{it->get()->LearnedClauses()};
357 for (const Literal &learned_clause : learned_clauses) sat_solver_->AddLearnedClause(learned_clause);
358
359#ifndef NDEBUG
360 const Variable &var = it->get()->theory_var();
361 const auto &bound = theory_solver_->fixed_theory_bounds().at(var);
362 fmt::println("Fixed Bounds: {} = [{}, {}]", var, bound.active_lower_bound().get_d(),
363 bound.active_upper_bound().get_d());
364#endif
365 it = learned_clauses.empty() ? std::next(it) : pl_constraints_.erase(it);
366 }
367
368 if (!config_.onnx_file().empty()) {
369 auto &nnSoplexTheorySolver = static_cast<NNSoplexTheorySolver &>(*theory_solver_);
370 nnSoplexTheorySolver.SetPiecewiseLinearConstraints(pl_constraints_);
371 }
372
373 bool have_unsolved = false;
374 while (true) {
375 // Note that 'DLINEAR_PYDLINEAR' is only defined in setup.py, when we build dReal python package.
376#ifdef DLINEAR_PYDLINEAR
377 py_check_signals();
378#endif
379
380 DLINEAR_DEV_DEBUG("New iteration");
381 // The box is passed in to the SAT solver solely to provide the LP solver
382 // with initial bounds on the numerical variables.
383 const auto optional_model = sat_solver_->CheckSat();
384
385 // The SAT solver did not return a model.
386 if (!optional_model) {
387 if (have_unsolved) { // There was an unsolved theory instance. The SMT solver failed to prove UNSAT.
388 DLINEAR_DEBUG("ContextImpl::CheckSatCore() - Sat Check = UNKNOWN");
389 DLINEAR_RUNTIME_ERROR("LP solver failed to solve some instances");
390 } else { // There is no unsolved theory instance. The SAT solver succeeded in proving UNSAT.
391 DLINEAR_DEBUG("ContextImpl::CheckSatCore() - Sat Check = UNSAT");
393 }
394 }
395
396 // The SAT solver found a model that satisfies the formula. SAT from SATSolver.
397 DLINEAR_DEBUG("ContextImpl::CheckSatCore() - Sat Check = SAT");
398
399 // Extrapolate the boolean and theory model from the SAT model.
400 const std::vector<Literal> &boolean_model{optional_model->first};
401 const std::vector<Literal> &theory_model{optional_model->second};
402
403 // Update the Boolean variables in the model (not used by the LP solver).
404 for (const auto &[var, truth] : boolean_model) {
405 box()[var] = truth ? 1 : 0; // true -> 1 and false -> 0
406 }
407
408 // If there is no theory to solve, the SAT solver output is enough to return SAT.
409 if (theory_model.empty()) return SatResult::SAT_SATISFIABLE;
410
411 theory_solver_->Reset();
412 const TheorySolver::Explanations bound_explanations{theory_solver_->EnableLiterals(theory_model)};
413 if (!bound_explanations.empty()) {
414 DLINEAR_DEBUG("ContextImpl::CheckSatCore() - Enable bound check = UNSAT");
415 LearnExplanations(bound_explanations);
416 continue;
417 }
418
419 TheorySolver::Explanations theory_explanations;
420 // If the SAT solver found a model, we have to check if it is consistent with the theory
421 SatResult theory_result = theory_solver_->CheckSat(box(), actual_precision, theory_explanations);
422 if (theory_result == SatResult::SAT_DELTA_SATISFIABLE || theory_result == SatResult::SAT_SATISFIABLE) {
423 // SAT from TheorySolver.
424 DLINEAR_DEBUG_FMT("ContextImpl::CheckSatCore() - Theory Check = {}", theory_result);
425 box() = theory_solver_->model();
426 return theory_result;
427 }
428
429 if (theory_result == SatResult::SAT_UNSATISFIABLE) { // UNSAT from TheorySolver.
430 DLINEAR_DEBUG("ContextImpl::CheckSatCore() - Theory Check = UNSAT");
431 } else {
432 DLINEAR_ASSERT(theory_result == SatResult::SAT_UNSOLVED, "theory must be unsolved");
433 DLINEAR_WARN("ContextImpl::CheckSatCore() - Theory Check = UNKNOWN");
434 have_unsolved = true; // Will prevent return of UNSAT
435 theory_explanations.emplace(theory_model.cbegin(), theory_model.cend());
436 }
437 DLINEAR_ASSERT(!theory_explanations.empty(), "theory_explanations must not be empty");
438 LearnExplanations(theory_explanations);
439 }
440}
441
442LpResult Context::Impl::CheckOptCore([[maybe_unused]] mpq_class *obj_lo, [[maybe_unused]] mpq_class *obj_up) {
443 DLINEAR_RUNTIME_ERROR("CheckOptCore() Not implemented");
444}
445void Context::Impl::MinimizeCore([[maybe_unused]] const Expression &obj_expr) {
446 DLINEAR_RUNTIME_ERROR("MinimizeCore() Not implemented");
447}
448std::unique_ptr<TheorySolver> Context::Impl::GetTheorySolver() {
449 switch (config_.lp_solver()) {
450#ifdef DLINEAR_ENABLED_QSOPTEX
452 if (!config_.complete()) // TODO: add support for complete QSOPTEX
453 return std::make_unique<DeltaQsoptexTheorySolver>(predicate_abstractor_);
454 DLINEAR_RUNTIME_ERROR("Only delta-complete mode is supported for qsoptex");
455#endif
456#ifdef DLINEAR_ENABLED_SOPLEX
458 if (!config_.onnx_file().empty())
459 return std::make_unique<NNSoplexTheorySolver>(predicate_abstractor_);
460 else if (config_.complete())
461 return std::make_unique<CompleteSoplexTheorySolver>(predicate_abstractor_);
462 else
463 return std::make_unique<DeltaSoplexTheorySolver>(predicate_abstractor_);
464#endif
465 default:
466 DLINEAR_UNREACHABLE();
467 }
468}
469std::unique_ptr<SatSolver> Context::Impl::GetSatSolver() {
470 switch (config_.sat_solver()) {
471#ifdef DLINEAR_ENABLED_CADICAL
473 return std::make_unique<CadicalSatSolver>(predicate_abstractor_);
474#endif
475#ifdef DLINEAR_ENABLED_PICOSAT
477 return std::make_unique<PicosatSatSolver>(predicate_abstractor_);
478#endif
479 default:
480 DLINEAR_UNREACHABLE();
481 }
482}
484 DLINEAR_DEBUG_FMT("ContextImpl::LearnExplanation(): size of explanation = {} - stack size = {}", explanation.size(),
485 stack_.get_vector().size());
486 DLINEAR_DEV_FMT("ContextImpl::LearnExplanation({})", explanation);
487 DLINEAR_ASSERT(!explanations_so_far.contains(explanation), "Explanation already present, looping!");
488 DLINEAR_ASSERT(!explanation.empty(), "No explanation is provided. Infinite loop detected.");
489#ifndef NDEBUG
490 explanations_so_far.insert(explanation);
491#endif
492 sat_solver_->AddLearnedClause(explanation);
493}
494
496 DLINEAR_ASSERT(!explanations.empty(), "Explanations cannot be empty");
497 for (const LiteralSet &explanation : explanations) LearnExplanation(explanation);
498}
499
500void Context::Impl::UpdateAndPrintOutput(const SmtResult smt_result) const {
501 if (output_ == nullptr) return;
502 DLINEAR_DEBUG("ContextImpl::UpdateAndPrintOutput() - Setting output");
503 output_->result = smt_result;
504 output_->n_assertions = assertions().size();
505 if (config_.produce_models()) output_->model = model_;
506 if (config_.verify()) output_->complete_model = box();
507 if (config_.with_timings()) {
508 DLINEAR_DEBUG("ContextImpl::UpdateAndPrintOutput() - Setting timings");
509 output_->sat_stats = sat_solver_->stats();
510 output_->ite_stats = ite_eliminator_.stats();
511 output_->theory_stats = theory_solver_->stats();
512 output_->preprocessor_stats = theory_solver_->preprocessor().stats() + theory_solver_->fixed_preprocessor().stats();
513 output_->predicate_abstractor_stats = predicate_abstractor_.stats();
514 output_->cnfizer_stats = sat_solver_->cnfizer_stats();
515 }
516 if (!config_.silent() && config_.csv()) {
517 std::cout << "file,complete,satSolver,lpSolver,assertions,precision,actualPrecision,simplexPhase,"
518 "boundPropagationType,boundPropagationFrequency,boundImplicationFrequency,satDefaultPhase,lpMode,"
519 "timeUnit,parserTime,satTime,preprocessorTime,theoryTime,smtTime,result\n";
520 std::cout << config_.filename() << "," //
521 << config_.complete() << "," //
522 << config_.sat_solver() << "," //
523 << config_.lp_solver() << "," //
524 << output_->n_assertions << "," //
525 << config_.precision() << "," //
526 << output_->actual_precision.get_d() << "," //
527 << config_.simplex_sat_phase() << "," //
528 << config_.actual_bound_propagation_type() << "," //
529 << config_.actual_bound_propagation_frequency() << "," //
530 << config_.actual_bound_implication_frequency() << "," //
531 << config_.sat_default_phase() << "," //
532 << config_.actual_lp_mode() << "," //
533 << "s" << "," //
534 << output_->parser_stats.timer().seconds() << "," //
535 << output_->sat_stats.timer().seconds() << "," //
536 << output_->preprocessor_stats.timer().seconds() << "," //
537 << output_->theory_stats.timer().seconds() << "," //
538 << output_->smt_solver_timer.seconds() << "," //
539 << output_->result << std::endl;
540 } else if (!config_.silent()) {
541 std::cout << *output_ << std::endl;
542 }
543}
544
545} // namespace dlinear
Use theory reasoning to add relations between literals using some simple theory inferences.
void Propagate()
Use theory reasoning to propagate some simple theory inferences.
Collection of variables with associated intervals.
Definition Box.h:31
void Add(const Variable &v)
Add the variable v to the box.
Definition Box.cpp:39
const std::vector< Variable > & variables() const
Get read-only access to the variables of the box.
Definition Box.cpp:113
const std::vector< Interval > & interval_vector() const
Return the interval vector of the box.
Definition Box.cpp:121
Config::LPSolver lp_solver() const
Get read-only access to the lp_solver of the box.
Definition Box.h:104
int size() const
Get read-only access to the number of variables of the box.
Definition Box.cpp:100
const Variable & variable(int i) const
Return the i -th variable in the box.
Definition Box.cpp:115
Simple dataclass used to store the configuration of the program.
Definition Config.h:38
@ CADICAL
Cadical Solver. Default option.
@ PICOSAT
Picosat Solver.
@ QSOPTEX
Qsoptex Solver.
@ SOPLEX
Soplex Solver. Default option.
const LPSolver & lp_solver() const
Get read-write access to the lp_solver parameter of the configuration.
Definition Config.h:184
@ NEVER
Never run this preprocess, effectively disabling it.
void Assert(const Formula &f)
Assert a formula f.
Box ExtractModel(const Box &box) const
Extract a model from the box.
void Push()
Push the current set of assertions to the stack.
void SetDomain(const Variable &v, const Expression &lb, const Expression &ub)
Set a domain for the variable v, restricting it to the interval .
SatResult CheckSat(mpq_class *precision)
Check the satisfiability of the asserted formulas, and sets actual_precision to the actual max infeas...
void UpdateAndPrintOutput(SmtResult smt_result) const
Update the output_ with the last smt_result .
bool have_objective() const
Check whether or not there is an objective function (which may be zero) to optimize.
void SetOption(const std::string &key, const std::string &val)
Set an option key with a value val.
void LearnExplanations(const TheorySolver::Explanations &explanations)
The TheorySolver found a number of conflicts and the explanations are the set of literals that are re...
void SetInterval(const Variable &v, const mpq_class &lb, const mpq_class &ub)
Set the interval of v to in the current box (top one in boxes_).
bool Verify(const Box &model) const
Check whether the model satisfies all the assertions loaded in the context.
void SetLogic(Logic logic)
Set the current logic to logic.
const ScopedVector< Formula > & assertions() const
Get the the asserted formulas.
void MarkModelVariable(const Variable &v)
Mark the variable v as a model variable.
std::string GetInfo(const std::string &key) const
Get the info key.
void DeclareVariable(const Variable &v, bool is_model_variable)
Declare a variable v.
std::string GetOption(const std::string &key) const
Get the option key.
void SetInfo(const std::string &key, const std::string &val)
Set an info key with a value val.
bool is_max() const
Check whether or not the objective function (if present) is a maximization.
void Minimize(const Expression &obj_function)
Assert a formula minimizing a cost function f.
void AddToBox(const Variable &v)
Add the variable v to the current box.
void LearnExplanation(const LiteralSet &explanation)
The TheorySolver found a conflict and the explanation is the set of literals that are responsible.
SatResult CheckSatCore(mpq_class *actual_precision)
Check the satisfiability of the current set of assertions.
ScopedVector< Box > boxes_
Stack of boxes. The top one is the current box.
LpResult CheckOpt(mpq_class *obj_lo, mpq_class *obj_up)
Check the satisfiability of the asserted formulas, and (where possible) optimizes an objective functi...
void Maximize(const Expression &obj_function)
Assert a formula maximizing a cost function f.
std::unique_ptr< SatSolver > GetSatSolver()
Get the correct sat solver subclass based on the configuration.
bool IsModelVariable(const Variable &v) const
Check if the variable v is a model variable.
Impl(Config &config, SmtSolverOutput *output=nullptr)
Construct a context with config.
void Pop()
Pop the top of the stack of assertions.
void AssertPiecewiseLinearFunction(const Variable &var, const Formula &cond, const Expression &active, const Expression &inactive)
Assert a piecewise linear function with two possible branches.
LpResult CheckOptCore(mpq_class *obj_lo, mpq_class *obj_up)
Check the satisfiability of the asserted formulas, and (where possible) optimizes an objective functi...
Config & config_
Configuration of the context. It could be modified by the problem instance.
std::unique_ptr< TheorySolver > GetTheorySolver()
Get the correct theory solver subclass based on the configuration.
void DeclareVariable(const Variable &v, bool is_model_variable=true)
Declare a variable v.
Definition Context.cpp:31
const ScopedVector< Formula > & assertions() const
Get the the asserted formulas.
Definition Context.cpp:71
void SetInterval(const Variable &v, const mpq_class &lb, const mpq_class &ub)
Set the interval of v to in the current box (top one in boxes_).
Definition Context.cpp:59
const Box & model() const
Get a representation of a model computed by the solver in response to the last invocation of the chec...
Definition Context.cpp:67
const Box & box() const
Get the current active box from the top of the stack of boxes.
Definition Context.cpp:66
Specialised theory solver for neural networks using SoPlex.
A piecewise linear constraint is a constraint that assumes different linear functions depending on th...
std::set< LiteralSet > Explanations
Set of explanations of the conflict.
Represents a symbolic environment (mapping from a variable to a value).
std::pair< Environment::iterator, bool > insert(const key_type &key, const mapped_type &elem)
Inserts a pair (key, elem).
Represents a symbolic form of an expression.
mpq_class Evaluate(const Environment &env=Environment{}) const
Evaluates under a given environment (by default, an empty environment).
Represents a symbolic form of a first-order logic formula.
Represents a symbolic variable.
@ CONTINUOUS
A CONTINUOUS variable takes a mpq_class value.
bool is_dummy() const
Checks if this is a dummy variable (ID = 0) which is created by the default constructor.
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_NO_RESULT
No result has been obtained yet.
@ SAT_SATISFIABLE
The problem is satisfiable.
@ SAT_UNSATISFIABLE
The problem is unsatisfiable.
@ SAT_UNSOLVED
The problem has not been solved. An error may have occurred.
@ SAT_DELTA_SATISFIABLE
The problem is satisfiable, but with a delta >= 0.
Logic
The SMT-LIB logic the SMT2 file is using.
Definition Logic.h:17
@ QF_LRA
Quantifier free linear real arithmetic. It is the only one dlinear supports.
@ LRA
Linear real arithmetic.
SmtResult
SmtSolver Result based on the result of the solver.
@ SKIP_SAT
The user asked to skip the satisfiability check.
LpResult
Result of running the LP solver over the input problem.
Definition LpResult.h:14
@ LP_NO_RESULT
No result has been obtained yet.
@ LP_DELTA_OPTIMAL
The problem has been solved optimally, but with a delta.
@ LP_OPTIMAL
The problem has been solved optimally.
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
Data struct containing the output of the solver, such as the result of the computation as well as som...