SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
VSHelper.h
Go to the documentation of this file.
1 #pragma once
2 
4 #include <smtrat-common/model.h>
5 #include <carl-arith/core/Common.h>
6 #include <carl-formula/model/evaluation/ModelEvaluation.h>
7 #include <carl-vs/substitute.h>
8 #include <carl-vs/zeros.h>
9 
10 #include <variant>
11 #include <vector>
12 
13 namespace smtrat {
14 namespace mcsat {
15 namespace vs {
16 namespace helper {
17 
18  inline void getFormulaAtoms(const FormulaT& f, FormulaSetT& result) {
19  if (f.type() == carl::FormulaType::CONSTRAINT || f.type() == carl::FormulaType::VARCOMPARE) {
20  result.insert(f);
21  } else if (f.type() == carl::FormulaType::NOT) {
22  getFormulaAtoms(f.subformula(), result);
23  } else if (f.is_nary()) {
24  for (const auto& sub : f.subformulas()) {
25  getFormulaAtoms(sub, result);
26  }
27  } else if (f.type() == carl::FormulaType::TRUE || f.type() == carl::FormulaType::FALSE) {
28  result.insert(f);
29  } else {
30  assert(false);
31  }
32  }
33 
34  /**
35  * Converts a DisjunctionOfConstraintConjunctions to a regular Formula.
36  */
37  inline FormulaT to_formula(const carl::vs::CaseDistinction<Poly>& docc) {
38  FormulasT constraintConjunctions;
39  for (const auto& conjunction : docc) {
40  FormulasT constraintConjunction;
41  for (const auto& constraint : conjunction) {
42  constraintConjunction.emplace_back(constraint);
43  }
44  constraintConjunctions.emplace_back(carl::FormulaType::AND, std::move(constraintConjunction));
45  }
46  return FormulaT(carl::FormulaType::OR, std::move(constraintConjunctions));
47  }
48 
49  /**
50  * Get zeros with side conditions of the given constraint.
51  *
52  * Kind of a generator function. Passes generated zeros to a callback function to avoid copying.
53  */
54  static bool generateZeros(const FormulaT& formula, const carl::Variable& eliminationVar, std::function<void(SqrtEx&& sqrtExpression, ConstraintsT&& sideConditions)> yield_result) {
55  std::vector<carl::vs::zero<Poly>> res;
56 
57  if (formula.type()==carl::FormulaType::CONSTRAINT) {
58  if (!carl::vs::gather_zeros(formula.constraint(), eliminationVar, res)) {
59  SMTRAT_LOG_DEBUG("smtrat.mcsat.vs", "Could not generate zero");
60  return false;
61  }
62  } else if (formula.type()==carl::FormulaType::TRUE || formula.type()==carl::FormulaType::FALSE) {
63  return true;
64  } else if (formula.type()==carl::FormulaType::VARCOMPARE) {
65  if (!carl::vs::gather_zeros(formula.variable_comparison(), eliminationVar, res)) {
66  SMTRAT_LOG_DEBUG("smtrat.mcsat.vs", "Could not generate zero");
67  return false;
68  }
69  } else {
70  assert(false);
71  return false;
72  }
73 
74  SMTRAT_LOG_DEBUG("smtrat.mcsat.vs", "Got zeros" << res);
75  for (auto& z : res) {
76  yield_result(std::move(z.sqrt_ex), std::move(z.side_condition));
77  }
78  return true;
79  }
80 
81  struct TestCandidate {
82  carl::vs::Term<Poly> term;
84  bool operator==(const TestCandidate& other) const {
85  return term == other.term && side_condition == other.side_condition;
86  }
87  };
88 
89  /**
90  * Adds a new substitution to the given list of substitutions or merges it to an existing one.
91  * Returns true if a new substitution was created.
92  */
93  static bool addOrMergeTestCandidate(std::vector<TestCandidate>& results, const TestCandidate& newSubstitution) {
94  if(!(std::find(results.begin(), results.end(), newSubstitution) != results.end())) {
95  results.push_back(newSubstitution);
96  return true;
97  }
98  return false;
99  }
100 
101  /**
102  * Generate all test candidates according to "vanilla" virtual substitution.
103  * Returns false iff VS is not applicable.
104  */
105  static bool generateTestCandidates( std::vector<TestCandidate>& results, const carl::Variable& eliminationVar, const FormulaSetT& constraints) {
106  SMTRAT_LOG_DEBUG("smtrat.mcsat.vs", "Generating test candidates for " << constraints << " and variable " << eliminationVar);
107 
108  // add minus infinity
109  TestCandidate minf = {carl::vs::Term<Poly>::minus_infty(), ConstraintsT()};
110  results.emplace_back(minf);
111 
112  // scan through conditions for test candidates
113  for (const auto& constraint : constraints) {
114  // Determine the substitution type: normal or +epsilon
115  assert(constraint.type() == carl::FormulaType::CONSTRAINT || constraint.type() == carl::FormulaType::TRUE || constraint.type() == carl::FormulaType::FALSE || constraint.type() == carl::FormulaType::VARCOMPARE);
116  bool isConstraint = constraint.type() == carl::FormulaType::CONSTRAINT || constraint.type() == carl::FormulaType::TRUE || constraint.type() == carl::FormulaType::FALSE;
117  const carl::Relation& relation = isConstraint ? constraint.constraint().relation() : constraint.variable_comparison().relation();
118  bool weakConstraint = (relation == carl::Relation::EQ || relation == carl::Relation::LEQ || relation == carl::Relation::GEQ);
119  auto subType = weakConstraint ? carl::vs::TermType::NORMAL : carl::vs::TermType::PLUS_EPSILON;
120 
121  // generate Zeros
122  bool res = generateZeros(constraint, eliminationVar, [&](SqrtEx&& sqrtExpression, ConstraintsT&& sideConditions) {
123  TestCandidate sub({carl::vs::Term<Poly>(subType, sqrtExpression), std::move(sideConditions)});
124  SMTRAT_LOG_DEBUG("smtrat.mcsat.vs", "Generated test candidate " << sub.term);
125  addOrMergeTestCandidate(results, sub);
126  });
127 
128  if (!res) {
129  SMTRAT_LOG_DEBUG("smtrat.mcsat.vs", "Could not generate zeros of " << eliminationVar << " in " << constraint);
130  return false;
131  }
132  }
133 
134  SMTRAT_LOG_DEBUG("smtrat.mcsat.vs", "Generated test candidates successfully");
135  return true;
136  }
137 
138  inline bool substitute(const FormulaT& constr, const carl::Variable var, const carl::vs::Term<Poly>& term, FormulaT& result) {
139  if (constr.type() == carl::FormulaType::CONSTRAINT) {
140  auto subres = carl::vs::substitute(constr.constraint(), var, term);
141  if (!subres) {
142  SMTRAT_LOG_DEBUG("smtrat.mcsat.vs", "Substitution failed");
143  return false;
144  } else {
145  result = helper::to_formula(*subres);
146  SMTRAT_LOG_DEBUG("smtrat.mcsat.vs", "Substitution obtained " << result);
147  return true;
148  }
149  } else if (constr.type() == carl::FormulaType::VARCOMPARE) {
150  auto subres = carl::vs::substitute(constr.variable_comparison(), var, term);
151  if (!subres) {
152  SMTRAT_LOG_DEBUG("smtrat.mcsat.vs", "Substitution failed");
153  return false;
154  } else {
155  if (std::holds_alternative<carl::vs::CaseDistinction<Poly>>(*subres)) {
156  result = helper::to_formula(std::get<carl::vs::CaseDistinction<Poly>>(*subres));
157  } else {
158  result = FormulaT(std::get<carl::VariableComparison<Poly>>(*subres));
159  }
160 
161  SMTRAT_LOG_DEBUG("smtrat.mcsat.vs", "Substitution obtained " << result);
162  return true;
163  }
164  } else {
165  SMTRAT_LOG_DEBUG("smtrat.mcsat.vs", "Formula type " << constr.type() << " not supported for substitution");
166  return false;
167  }
168  }
169 }
170 }
171 }
172 }
int var(Lit p)
Definition: SolverTypes.h:64
static bool find(V &ts, const T &t)
Definition: Alg.h:47
auto get(const It &it, level)
static bool generateZeros(const FormulaT &formula, const carl::Variable &eliminationVar, std::function< void(SqrtEx &&sqrtExpression, ConstraintsT &&sideConditions)> yield_result)
Get zeros with side conditions of the given constraint.
Definition: VSHelper.h:54
bool substitute(const FormulaT &constr, const carl::Variable var, const carl::vs::Term< Poly > &term, FormulaT &result)
Definition: VSHelper.h:138
static bool generateTestCandidates(std::vector< TestCandidate > &results, const carl::Variable &eliminationVar, const FormulaSetT &constraints)
Generate all test candidates according to "vanilla" virtual substitution.
Definition: VSHelper.h:105
void getFormulaAtoms(const FormulaT &f, FormulaSetT &result)
Definition: VSHelper.h:18
static bool addOrMergeTestCandidate(std::vector< TestCandidate > &results, const TestCandidate &newSubstitution)
Adds a new substitution to the given list of substitutions or merges it to an existing one.
Definition: VSHelper.h:93
FormulaT to_formula(const carl::vs::CaseDistinction< Poly > &docc)
Converts a DisjunctionOfConstraintConjunctions to a regular Formula.
Definition: VSHelper.h:37
Class to create the formulas for axioms.
@ NORMAL
Definition: types.h:53
carl::Constraints< Poly > ConstraintsT
Definition: types.h:31
carl::FormulaSet< Poly > FormulaSetT
Definition: types.h:41
carl::Formula< Poly > FormulaT
Definition: types.h:37
carl::SqrtEx< Poly > SqrtEx
Definition: model.h:22
carl::Formulas< Poly > FormulasT
Definition: types.h:39
#define SMTRAT_LOG_DEBUG(channel, msg)
Definition: logging.h:35
bool operator==(const TestCandidate &other) const
Definition: VSHelper.h:84