6#include "DeltaQsoptexTheorySolver.h"
11#include "dlinear/libs/libqsopt_ex.h"
12#include "dlinear/symbolic/symbolic.h"
13#include "dlinear/util/Stats.h"
14#include "dlinear/util/Timer.h"
15#include "dlinear/util/exception.h"
16#include "dlinear/util/logging.h"
20DeltaQsoptexTheorySolver::DeltaQsoptexTheorySolver(PredicateAbstractor &predicate_abstractor,
21 const std::string &class_name)
22 : QsoptexTheorySolver(predicate_abstractor, class_name) {}
24void DeltaQsoptexTheorySolver::AddLiteral(
const Variable &formula_var,
const Formula &formula) {
25 DLINEAR_ASSERT(!is_consolidated_,
"Cannot add literals after consolidation");
27 if (lit_to_theory_row_.contains(formula_var.get_id()))
return;
29 DLINEAR_TRACE_FMT(
"DeltaQsoptexTheorySolver::AddLiteral({})", formula);
33 if (BoundPreprocessor::IsSimpleBound(formula))
return;
35 const int qsx_row{mpq_QSget_rowcount(qsx_)};
36 mpq_QSnew_row(qsx_, mpq_NINFTY,
'G',
nullptr);
37 SetRowCoeff(formula, mpq_QSget_rowcount(qsx_) - 1);
41 lit_to_theory_row_.emplace(formula_var.get_id(), qsx_row);
42 theory_row_to_lit_.emplace_back(formula_var,
true);
44 DLINEAR_ASSERT(
static_cast<std::size_t
>(qsx_row) == theory_row_to_lit_.size() - 1,
45 "incorrect theory_row_to_lit_.size()");
46 DLINEAR_ASSERT(
static_cast<std::size_t
>(qsx_row) == qsx_sense_.size() - 1,
"incorrect spx_sense_.size()");
47 DLINEAR_ASSERT(
static_cast<std::size_t
>(qsx_row) == qsx_rhs_.size() - 1,
"incorrect spx_rhs_.size()");
48 DLINEAR_DEBUG_FMT(
"DeltaQsoptexTheorySolver::AddLiteral: {} ↦ {}", formula, qsx_row);
52 DLINEAR_ASSERT(is_consolidated_,
"The solver must be consolidate before enabling a literal");
53 DLINEAR_ASSERT(predicate_abstractor_.var_to_formula_map().contains(lit.
var),
"var must map to a theory literal");
55 Explanations explanations{preprocessor_.EnableLiteral(lit)};
56 if (!explanations.empty())
return explanations;
58 const auto &[var, truth] = lit;
59 const auto it = lit_to_theory_row_.find(var.get_id());
61 if (it == lit_to_theory_row_.end()) {
62 DLINEAR_TRACE_FMT(
"DeltaQsoptexTheorySolver::EnableLinearLiteral: ignoring ({})", lit);
67 const int qsx_row = it->second;
69 theory_row_to_lit_[qsx_row].truth = truth;
71 DLINEAR_TRACE_FMT(
"DeltaQsoptexTheorySolver::EnableLinearLiteral({})", lit);
73 EnableQsxRow(qsx_row, truth);
77SatResult DeltaQsoptexTheorySolver::CheckSatCore(mpq_class *actual_precision, Explanations &explanations) {
78 DLINEAR_ASSERT(is_consolidated_,
"The solver must be consolidate before checking for sat");
82 const std::size_t rowcount = mpq_QSget_rowcount(qsx_);
83 const std::size_t colcount = mpq_QSget_colcount(qsx_);
86 x_.Resize(colcount + rowcount);
87 ray_.Resize(rowcount);
96 DLINEAR_DEBUG_FMT(
"DeltaQsoptexTheorySolver::CheckSat: calling QSopt_ex (phase {})", config_.simplex_sat_phase());
98 if (1 == config_.simplex_sat_phase()) {
99 status = QSdelta_solver(qsx_, actual_precision->get_mpq_t(),
static_cast<mpq_t *
>(x_),
static_cast<mpq_t *
>(ray_),
100 nullptr, PRIMAL_SIMPLEX, &lp_status,
101 config_.continuous_output() ? QsoptexCheckSatPartialSolution : nullptr, this);
103 status = QSexact_delta_solver(qsx_,
static_cast<mpq_t *
>(x_),
static_cast<mpq_t *
>(ray_),
nullptr, PRIMAL_SIMPLEX,
104 &lp_status, actual_precision->get_mpq_t(),
105 config_.continuous_output() ? QsoptexCheckSatPartialSolution : nullptr, this);
109 DLINEAR_RUNTIME_ERROR_FMT(
"QSopt_ex returned {}", status);
111 DLINEAR_DEBUG_FMT(
"DeltaQsoptexTheorySolver::CheckSat: QSopt_ex has returned with precision = {}",
117 case QS_LP_DELTA_FEASIBLE:
118 UpdateModelSolution();
119 DLINEAR_DEBUG(
"DeltaQsoptexTheorySolver::CheckSat: returning SAT_DELTA_SATISFIABLE");
120 return SatResult::SAT_DELTA_SATISFIABLE;
121 case QS_LP_INFEASIBLE:
122 UpdateExplanations(explanations);
123 DLINEAR_DEBUG(
"DeltaQsoptexTheorySolver::CheckSat: returning SAT_UNSATISFIABLE");
124 return SatResult::SAT_UNSATISFIABLE;
126 DLINEAR_WARN(
"DeltaQsoptexTheorySolver::CheckSat: QSopt_ex failed to return a result");
127 return SatResult::SAT_UNSOLVED;
129 DLINEAR_UNREACHABLE();
133void DeltaQsoptexTheorySolver::EnableQsxRow(
int qsx_row,
bool truth) {
135 mpq_class &rhs{qsx_rhs_[qsx_row]};
138 if (sense == LpRowSense::NQ)
return;
139 qsx_sense =
toChar(sense);
141 if (sense == LpRowSense::EQ)
return;
142 qsx_sense =
toChar(-sense);
144 mpq_QSchange_sense(qsx_, qsx_row, qsx_sense);
145 mpq_QSchange_rhscoef(qsx_, qsx_row, rhs.get_mpq_t());
146 theory_rows_state_.at(qsx_row) =
true;
147 DLINEAR_TRACE_FMT(
"DeltaQsoptexTheorySolver::EnableLinearLiteral({}{})", truth ?
"" :
"¬", qsx_row);
std::set< LiteralSet > Explanations
Set of explanations of the conflict.
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.
char toChar(LpColBound bound)
Convert the bound to a character.
LpRowSense parseLpSense(const Formula &f)
Parse the sense from a formula.
LpRowSense
Sense of a linear programming row describing a constraint.
A literal is a variable with an associated truth value, indicating whether it is true or false.