SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
MCBModule.tpp
Go to the documentation of this file.
1 /**
2  * @file MCB.cpp
3  * @author YOUR NAME <YOUR EMAIL ADDRESS>
4  *
5  * @version 2015-12-10
6  * Created on 2015-12-10.
7  */
8 
9 #include "MCBModule.h"
10 
11 #include <smtrat-common/model.h>
12 #include <carl-formula/formula/functions/Substitution.h>
13 
14 namespace smtrat
15 {
16  class MCBModelSubstitution: public ModelSubstitution {
17  private:
18  std::map<carl::Variable,Rational> mAssignments;
19  Rational mDefault;
20  public:
21  MCBModelSubstitution(const std::map<carl::Variable,Rational>& assignments): ModelSubstitution(), mAssignments(assignments), mDefault(0) {
22  for (const auto& a: mAssignments) {
23  if (a.second >= mDefault) mDefault = carl::ceil(a.second) + 1;
24  }
25  }
26  virtual void multiplyBy(const Rational& _number) {
27  for (auto& a: mAssignments)
28  a.second *= _number;
29  }
30  virtual void add(const Rational& _number) {
31  for (auto& a: mAssignments)
32  a.second += _number;
33  }
34  virtual carl::ModelSubstitutionPtr<Rational,Poly> clone() const {
35  return carl::createSubstitutionPtr<Rational,Poly,MCBModelSubstitution>(mAssignments);
36  }
37  virtual FormulaT representingFormula( const ModelVariable& ) {
38  assert(false);
39  return FormulaT();
40  }
41  virtual ModelValue evaluateSubstitution(const Model& model) const {
42  auto selection = mAssignments.end();
43  for (auto it = mAssignments.begin(); it != mAssignments.end(); it++) {
44  if (model.find(ModelVariable(it->first)) == model.end()) return carl::createSubstitution<Rational,Poly,MCBModelSubstitution>(*this);
45  const ModelValue& mv = model.evaluated(ModelVariable(it->first));
46  assert(mv.isBool());
47  if (mv.asBool()) {
48  assert(selection == mAssignments.end());
49  selection = it;
50  SMTRAT_LOG_DEBUG("smtrat.mcb", "Evaluating " << *this << " to " << selection->second << " on " << model);
51  break;
52  }
53  }
54  if (selection == mAssignments.end()) {
55  SMTRAT_LOG_DEBUG("smtrat.mcb", "Evaluating " << *this << " to default " << mDefault << " on " << model);
56  return ModelValue(mDefault);
57  }
58  return ModelValue(selection->second);
59  }
60  virtual bool dependsOn(const ModelVariable& var) const {
61  if (!var.is_variable()) return false;
62  return mAssignments.find(var.asVariable()) != mAssignments.end();
63  }
64  virtual void print(std::ostream& os) const {
65  os << "[";
66  for (auto it = mAssignments.begin(); it != mAssignments.end(); it++) {
67  if (it != mAssignments.begin()) os << ", ";
68  os << it->first << " -> " << it->second;
69  }
70  os << "]";
71  }
72  };
73 
74  template<class Settings>
75  MCBModule<Settings>::MCBModule(const ModuleInput* _formula, Conditionals& _conditionals, Manager* _manager):
76  PModule( _formula, _conditionals, _manager, Settings::moduleName )
77  {
78  collectChoicesFunction = std::bind(&MCBModule<Settings>::collectChoices, this, std::placeholders::_1);
79  }
80 
81  template<class Settings>
82  MCBModule<Settings>::~MCBModule()
83  {}
84 
85  template<class Settings>
86  Answer MCBModule<Settings>::checkCore()
87  {
88  mRemaining.clear();
89  mChoices.clear();
90  auto receivedFormula = firstUncheckedReceivedSubformula();
91  while (receivedFormula != rReceivedFormula().end()) {
92  carl::visit(receivedFormula->formula(), collectChoicesFunction);
93  receivedFormula++;
94  }
95  FormulaT newFormula = applyReplacements(FormulaT(rReceivedFormula()));
96  clearPassedFormula();
97  addSubformulaToPassedFormula(newFormula);
98 
99  Answer ans = runBackends();
100  if (ans == UNSAT) {
101  generateTrivialInfeasibleSubset();
102  }
103  return ans;
104  }
105 
106  template<typename Settings>
107  void MCBModule<Settings>::updateModel() const {
108  clearModel();
109  if (solverState() == SAT || (solverState() != UNSAT && appliedPreprocessing())) {
110  getBackendsModel();
111  mModel.update(mAssignments);
112  mAssignments.clear();
113  }
114  }
115 
116  template<typename Settings>
117  void MCBModule<Settings>::collectBounds(carl::ConstraintBounds<Poly>& cb, const FormulaT& formula, bool conjunction) const {
118  for (const auto& f: formula.subformulas()) {
119  if (f.type() == carl::FormulaType::CONSTRAINT || (f.type() == carl::FormulaType::NOT && f.subformula().type() == carl::FormulaType::CONSTRAINT)) {
120  addConstraintBound(cb, f, conjunction);
121  }
122  }
123  }
124 
125  template<typename Settings>
126  void MCBModule<Settings>::collectChoices(const FormulaT& formula) {
127  if (formula.type() != carl::FormulaType::OR) return;
128 
129  carl::ConstraintBounds<Poly> cb;
130  collectBounds(cb, formula, false);
131  if (cb.empty()) return;
132 
133  for (const auto& poly: cb) {
134  if (!poly.first.is_variable()) continue;
135  AVar var = poly.first.single_variable();
136  std::vector<std::pair<Rational,FormulaT>> choices;
137  for (const auto& entry: poly.second) {
138  if (entry.second.first != carl::Relation::EQ) break;
139  choices.emplace_back(entry.first, entry.second.second);
140  }
141  if (choices.size() != poly.second.size()) continue;
142  auto& m = mChoices[var];
143  for (const auto& c: choices) {
144  auto it = m.find(c.first);
145  if (it == m.end()) {
146  m.emplace(c.first, std::make_pair(carl::fresh_boolean_variable(), c.second));
147  }
148  }
149  }
150  }
151 
152  template<typename Settings>
153  FormulaT MCBModule<Settings>::applyReplacements(const FormulaT& f) {
154  if (mChoices.empty()) return f;
155  std::set<AVar> variables;
156  std::map<FormulaT, FormulaT> repl;
157  for (const auto& r: mChoices) {
158  variables.insert(r.first);
159  for (const auto& f: r.second) {
160  BVar v = f.second.first;
161  const FormulaT& form = f.second.second;
162  repl.emplace(form, FormulaT(v));
163  }
164  }
165  SMTRAT_LOG_DEBUG("smtrat.mcb", "Applying " << repl << " on \n\t" << f);
166  FormulaT res = carl::substitute(f, repl);
167  SMTRAT_LOG_DEBUG("smtrat.mcb", "Resulting in\n\t" << res);
168 
169  mRemaining.clear();
170  mRemaining = carl::variables(res).as_set();
171  FormulasT equiv;
172  for (const auto& v: variables) {
173  if (mRemaining.count(v) > 0) {
174  // Variable is still in the formula
175  for (const auto& r: mChoices.at(v)) {
176  equiv.push_back(FormulaT(carl::FormulaType::IFF, {FormulaT(r.second.first), r.second.second}));
177  }
178  } else {
179  // Variable has been eliminated
180  ModelVariable var(v);
181  std::map<BVar,Rational> assignment;
182  for (const auto& c: mChoices.at(v)) {
183  assignment.emplace(c.second.first, c.first);
184  }
185  SMTRAT_LOG_DEBUG("smtrat.mcb", "Adding " << var << " = " << assignment);
186  mAssignments.emplace(var, carl::createSubstitution<Rational,Poly,MCBModelSubstitution>(assignment));
187  }
188  for (const auto& c1: mChoices.at(v)) {
189  for (const auto& c2: mChoices.at(v)) {
190  if (c1.second.first >= c2.second.first) continue;
191  equiv.push_back(FormulaT(carl::FormulaType::OR, {FormulaT(c1.second.first).negated(), FormulaT(c2.second.first).negated()}));
192  SMTRAT_LOG_DEBUG("smtrat.mcb", "Adding exclusion " << equiv.back());
193  }
194  }
195  }
196  if (equiv.empty()) return res;
197  SMTRAT_LOG_DEBUG("smtrat.mcb", "Adding equivalences " << equiv);
198  equiv.push_back(res);
199  return FormulaT(carl::FormulaType::AND, std::move(equiv));
200  }
201 }
202 
203