SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
ClauseChain.cpp
Go to the documentation of this file.
1 #include "ClauseChain.h"
2 
3 namespace smtrat::mcsat {
4 
7  std::unordered_set<FormulaT> toProcess;
8 
9  // initialize with conflicting clause
10  assert(mClauseChain.back().isConflicting());
11  if (mClauseChain.back().clause().is_nary()) {
12  for (const auto& lit : mClauseChain.back().clause()) {
13  if (isTseitinVar(lit)) {
14  toProcess.insert(lit);
15  } else {
16  result.push_back(lit);
17  }
18  }
19  } else {
20  if (isTseitinVar(mClauseChain.back().clause())) {
21  toProcess.insert(mClauseChain.back().clause());
22  } else {
23  result.push_back(mClauseChain.back().clause());
24  }
25  }
26 
27 
28  // resolve using propagations
29  for (auto iter = mClauseChain.rbegin()+1; iter != mClauseChain.rend(); iter++) {
30  if (iter->isPropagating()) {
31  // check if any tseitin variable can be resolved using this clause
32  if (toProcess.find(iter->impliedTseitinLiteral().negated()) == toProcess.end()) {
33  continue;
34  }
35 
36  // remove the processed tseitin variable
37  toProcess.erase(iter->impliedTseitinLiteral().negated());
38 
39  // add literals of clauses to respective sets
40  if (iter->clause().is_nary()) {
41  for (const auto& lit : iter->clause().subformulas()) {
42  if (lit != iter->impliedTseitinLiteral()) {
43  if (isTseitinVar(lit)) {
44  toProcess.insert(lit);
45  } else {
46  result.push_back(lit);
47  }
48  }
49  }
50  }
51 
52  if (toProcess.empty()) {
53  break;
54  }
55  }
56  }
57  assert(toProcess.empty());
58 
59  return FormulaT(carl::FormulaType::OR, std::move(result));
60 }
61 
63  FormulasT fs;
64  for (const auto& link : mClauseChain) {
65  fs.push_back(link.clause());
66  }
67  return FormulaT(carl::FormulaType::AND, std::move(fs));
68 }
69 
70 FormulaT _transformToImplicationChain(const FormulaT& formula, const Model& model, ClauseChain& chain, bool outermost, bool withEquivalences) {
71  switch(formula.type()) {
72  case carl::FormulaType::TRUE:
73  case carl::FormulaType::FALSE:
74  case carl::FormulaType::CONSTRAINT:
75  case carl::FormulaType::VARCOMPARE:
76  case carl::FormulaType::VARASSIGN:
77  {
78  return formula;
79  }
80  break;
81 
83  {
84  if (!withEquivalences || outermost) {
85  FormulasT newFormula;
86  for (const auto& sub : formula.subformulas()) {
87  FormulaT sub_result = _transformToImplicationChain(sub, model, chain, false, withEquivalences);
88  newFormula.push_back(std::move(sub_result));
89  }
90  return FormulaT(carl::FormulaType::OR, std::move(newFormula));
91  } else {
92  FormulaT tseitinVar = chain.createTseitinVar(formula);
93  FormulasT newFormula;
94  for (const auto& sub : formula.subformulas()) {
95  FormulaT sub_result = _transformToImplicationChain(sub, model, chain, false, withEquivalences);
96  newFormula.push_back(std::move(sub_result));
97  const auto& lit = newFormula.back();
98  // newFormula_1 || newFormula_2 || ... -> tseitinVar
99  chain.appendOptional(FormulaT(carl::FormulaType::OR, FormulasT({lit.negated(), tseitinVar})));
100  }
101  newFormula.push_back(tseitinVar.negated());
102  // tseitinVar -> newFormula_1 || newFormula_2 || ...
103  chain.appendPropagating(FormulaT(carl::FormulaType::OR, std::move(newFormula)), tseitinVar.negated());
104  return tseitinVar;
105  }
106  }
107  break;
108 
110  {
111  if (outermost) {
112  FormulasT newFormula;
113  for (const auto& sub : formula.subformulas()) {
114  FormulaT sub_result = _transformToImplicationChain(sub, model, chain, false, withEquivalences);
115  carl::ModelValue<Rational,Poly> eval = carl::evaluate(sub, model);
116  assert(eval.isBool());
117  if (!eval.asBool()) {
118  chain.appendConflicting(std::move(sub_result));
119  } else {
120  chain.appendOptional(std::move(sub_result));
121  }
122  }
123  return FormulaT(carl::FormulaType::TRUE);
124  } else {
125  FormulaT tseitinVar = chain.createTseitinVar(formula);
126  FormulasT newFormula;
127  for (const auto& sub : formula.subformulas()) {
128  FormulaT sub_result = _transformToImplicationChain(sub, model, chain, false, withEquivalences);
129  newFormula.push_back(std::move(sub_result));
130  const auto& lit = newFormula.back();
131  // tseitinVar -> newFormula_1 && ... && newFormula_n
132  carl::ModelValue<Rational,Poly> eval = carl::evaluate(sub, model);
133  assert(eval.isBool());
134  if (!eval.asBool()) {
135  chain.appendPropagating(FormulaT(carl::FormulaType::OR, FormulasT({lit, tseitinVar.negated()})), tseitinVar.negated());
136  } else {
137  chain.appendOptional(FormulaT(carl::FormulaType::OR, FormulasT({lit, tseitinVar.negated()})));
138  }
139  }
140 
141  if (withEquivalences) {
142  // newFormula_1 && ... && newFormula_n -> tseitinVar
143  FormulasT tmp;
144  std::transform (newFormula.begin(), newFormula.end(), std::back_inserter(tmp), [](const FormulaT& f) -> FormulaT { return f.negated(); } );
145  tmp.push_back(tseitinVar);
147  }
148 
149  return tseitinVar;
150  }
151  }
152 
153  default:
154  SMTRAT_LOG_WARN("smtrat.mcsat", "Invalid formula type " << formula);
155  assert(false);
156  return FormulaT();
157  }
158 }
159 
160 ClauseChain ClauseChain::from_formula(const FormulaT& formula, const Model& model, bool with_equivalence) {
162  FormulaT conflictingClause = _transformToImplicationChain(formula, model, chain, true, with_equivalence);
163  if (!conflictingClause.is_true()) {
164  chain.appendConflicting(std::move(conflictingClause));
165  }
166  return chain;
167 }
168 
169 
170 }
An explanation is either a single clause or a chain of clauses, satisfying the following properties:
Definition: ClauseChain.h:16
static ClauseChain from_formula(const FormulaT &f, const Model &model, bool with_equivalence)
Transforms a given Boolean conjunction over AND and OR to CNF via Tseitin-Transformation so that,...
FormulaT to_formula() const
Transforms the clause chain into a formula (containing Tseitin variables).
Definition: ClauseChain.cpp:62
FormulaT resolve() const
Performs resolution on the chain.
Definition: ClauseChain.cpp:5
void appendConflicting(const FormulaT &&clause)
Append a conflicting clause (regarding the current assignment).
Definition: ClauseChain.h:90
FormulaT createTseitinVar(const FormulaT &formula)
Create a Tseitin variable for the given formula.
Definition: ClauseChain.h:73
bool isTseitinVar(const FormulaT &var) const
Definition: ClauseChain.h:62
void appendPropagating(const FormulaT &&clause, const FormulaT &&impliedTseitinLiteral)
Append a clause that implies impliedTseitinLiteral under the current assignment.
Definition: ClauseChain.h:83
std::vector< Link > mClauseChain
Definition: ClauseChain.h:59
const std::vector< Link > & chain() const
Definition: ClauseChain.h:105
void appendOptional(const FormulaT &&clause)
Append an additional clause which is neither propagating nor conflicting.
Definition: ClauseChain.h:98
Rational evaluate(carl::Variable v, const Poly &p, const Rational &r)
Definition: utils.h:11
FormulaT _transformToImplicationChain(const FormulaT &formula, const Model &model, ClauseChain &chain, bool outermost, bool withEquivalences)
Definition: ClauseChain.cpp:70
carl::Formula< Poly > FormulaT
Definition: types.h:37
carl::Model< Rational, Poly > Model
Definition: model.h:13
carl::Formulas< Poly > FormulasT
Definition: types.h:39
#define SMTRAT_LOG_WARN(channel, msg)
Definition: logging.h:33