dlinear  0.0.1
Delta-complete SMT solver for linear programming
Loading...
Searching...
No Matches
DeltaQsoptexTheorySolver.cpp
1
6#include "DeltaQsoptexTheorySolver.h"
7
8#include <map>
9#include <utility>
10
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"
17
18namespace dlinear {
19
20DeltaQsoptexTheorySolver::DeltaQsoptexTheorySolver(PredicateAbstractor &predicate_abstractor,
21 const std::string &class_name)
22 : QsoptexTheorySolver(predicate_abstractor, class_name) {}
23
24void DeltaQsoptexTheorySolver::AddLiteral(const Variable &formula_var, const Formula &formula) {
25 DLINEAR_ASSERT(!is_consolidated_, "Cannot add literals after consolidation");
26 // Literal is already present
27 if (lit_to_theory_row_.contains(formula_var.get_id())) return;
28
29 DLINEAR_TRACE_FMT("DeltaQsoptexTheorySolver::AddLiteral({})", formula);
30
31 // Create the LP solver variables
32 for (const Variable &var : formula.GetFreeVariables()) AddVariable(var);
33 if (BoundPreprocessor::IsSimpleBound(formula)) return;
34
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);
38 qsx_sense_.emplace_back(~parseLpSense(formula));
39
40 // Update indexes
41 lit_to_theory_row_.emplace(formula_var.get_id(), qsx_row);
42 theory_row_to_lit_.emplace_back(formula_var, true);
43
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);
49}
50
51DeltaQsoptexTheorySolver::Explanations DeltaQsoptexTheorySolver::EnableLiteral(const Literal &lit) {
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");
54
55 Explanations explanations{preprocessor_.EnableLiteral(lit)};
56 if (!explanations.empty()) return explanations;
57
58 const auto &[var, truth] = lit;
59 const auto it = lit_to_theory_row_.find(var.get_id());
60 // If the literal was not already among the constraints (rows) of the LP, it must be a learned literal.
61 if (it == lit_to_theory_row_.end()) {
62 DLINEAR_TRACE_FMT("DeltaQsoptexTheorySolver::EnableLinearLiteral: ignoring ({})", lit);
63 return {};
64 }
65
66 // A non-trivial linear literal from the input problem
67 const int qsx_row = it->second;
68 // Update the truth value for the current iteration with the last SAT solver assignment
69 theory_row_to_lit_[qsx_row].truth = truth;
70
71 DLINEAR_TRACE_FMT("DeltaQsoptexTheorySolver::EnableLinearLiteral({})", lit);
72
73 EnableQsxRow(qsx_row, truth);
74 return explanations;
75}
76
77SatResult DeltaQsoptexTheorySolver::CheckSatCore(mpq_class *actual_precision, Explanations &explanations) {
78 DLINEAR_ASSERT(is_consolidated_, "The solver must be consolidate before checking for sat");
79
80 int status = -1;
81
82 const std::size_t rowcount = mpq_QSget_rowcount(qsx_);
83 const std::size_t colcount = mpq_QSget_colcount(qsx_);
84 // x: must be allocated/deallocated using QSopt_ex.
85 // Should have room for the (rowcount) "logical" variables, which come after the (colcount) "structural" variables.
86 x_.Resize(colcount + rowcount);
87 ray_.Resize(rowcount);
88
89 // Set the bounds for the variables
90 EnableQsxVarBound();
91 // Remove all the disabled rows from the LP solver
92 DisableQsxRows();
93
94 // Now we call the solver
95 int lp_status = -1;
96 DLINEAR_DEBUG_FMT("DeltaQsoptexTheorySolver::CheckSat: calling QSopt_ex (phase {})", config_.simplex_sat_phase());
97
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);
102 } else {
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);
106 }
107
108 if (status) {
109 DLINEAR_RUNTIME_ERROR_FMT("QSopt_ex returned {}", status);
110 } else {
111 DLINEAR_DEBUG_FMT("DeltaQsoptexTheorySolver::CheckSat: QSopt_ex has returned with precision = {}",
112 *actual_precision);
113 }
114
115 switch (lp_status) {
116 case QS_LP_FEASIBLE:
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;
125 case QS_LP_UNSOLVED:
126 DLINEAR_WARN("DeltaQsoptexTheorySolver::CheckSat: QSopt_ex failed to return a result");
127 return SatResult::SAT_UNSOLVED;
128 default:
129 DLINEAR_UNREACHABLE();
130 }
131}
132
133void DeltaQsoptexTheorySolver::EnableQsxRow(int qsx_row, bool truth) {
134 const LpRowSense sense = qsx_sense_[qsx_row];
135 mpq_class &rhs{qsx_rhs_[qsx_row]};
136 char qsx_sense;
137 if (truth) {
138 if (sense == LpRowSense::NQ) return;
139 qsx_sense = toChar(sense);
140 } else {
141 if (sense == LpRowSense::EQ) return;
142 qsx_sense = toChar(-sense);
143 }
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);
148}
149
150} // namespace dlinear
std::set< LiteralSet > Explanations
Set of explanations of the conflict.
Represents a symbolic form of a first-order logic formula.
const Variables & GetFreeVariables() const
Gets free variables (unquantified variables).
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
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.
Definition LpRowSense.h:23
A literal is a variable with an associated truth value, indicating whether it is true or false.
Definition literal.h:24
Variable var
Variable.
Definition literal.h:25