SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
MaxSMT_FuMalikIncremental.h
Go to the documentation of this file.
1 #pragma once
2 
3 namespace smtrat {
4 namespace maxsmt {
5 
6 template<typename Solver>
8  Solver& mSolver;
9  const std::vector<FormulaT>& softClauses;
10 
12  FormulasT fs;
13  for (const auto& f : mSolver.formula()) fs.push_back(f.formula());
14  // TODO reuse solver: but then, formulaPositionMap cannot be reused; maybe add interface to Manager for disabling clauses
15  Solver tmpSolver;
16  for (const auto& f : fs) tmpSolver.add(f);
18  }
19 
21  mSolver.add(formula);
22  for (auto it = mSolver.formulaBegin(); it != mSolver.formulaEnd(); ++it) {
23  if (it->formula() == formula) {
24  return it;
25  }
26  }
27  assert(false && "Formula was not added correctly to backend. Expected to find formula.");
28  return mSolver.formulaEnd();
29  }
30 
31 public:
32  MaxSMTBackend(Solver& solver, const std::vector<FormulaT>& softClauses) : mSolver(solver), softClauses(softClauses) {}
33 
34  Answer run() {
35  std::map<FormulaT, carl::Variable> blockingVars;
36  std::map<FormulaT, ModuleInput::iterator> formulaPositionMap;
37 
38  // a set of assignments we need to keep track of the enabled clauses
39  std::map<carl::Variable, FormulaT> assignments;
40  std::map<FormulaT, FormulaT> extendedClauses;
41 
42  std::vector<FormulaT> newSoftClauses;
43 
44  // now add all soft clauses with a blocking variable which we assert to false in order to enable all soft clauses
45  // NB! if we added the soft clauses directly to the backend we would need to remove them later on which is not what we want
46  // in an incremental approach
47  for (const FormulaT& clause : softClauses) {
48  carl::Variable blockingVar = carl::fresh_boolean_variable();
49 
50  // remember the blockingVar associated to clause
51  blockingVars[clause] = blockingVar;
52 
53  // add the clause v blockingVar to backend
54  FormulaT clauseWithBlockingVar(carl::FormulaType::OR, FormulaT(blockingVar), clause);
55  extendedClauses[clauseWithBlockingVar] = clause;
56  mSolver.add(clauseWithBlockingVar);
57 
58  newSoftClauses.push_back(clauseWithBlockingVar);
59 
60  // enable the clause related to blocking var
61  assignments[blockingVar] = !FormulaT(blockingVar);
62  formulaPositionMap[assignments[blockingVar]] = addToSolver(assignments[blockingVar]);
63  }
64 
65  // TODO implement weighted case according to https://www.seas.upenn.edu/~xsi/data/cp16.pdf
66  for (;;) {
67  std::vector<carl::Variable> relaxationVars;
68 
69  Answer ans = mSolver.check();
70  SMTRAT_LOG_DEBUG("smtrat.maxsmt.fumalik", "Checked satisfiability of current soft/hardclause mixture got... " << ans);
71  if (ans == Answer::SAT) return Answer::SAT;
72 
73  auto core = computeUnsatCore();
74  if (core.first != Answer::UNSAT) {
75  return core.first;
76  }
77  SMTRAT_LOG_DEBUG("smtrat.maxsmt.fumalik", "Got unsat core " << core.second);
78  for (auto it : core.second) {
79  // skip hard clauses
80  if (std::find(softClauses.begin(), softClauses.end(), it) == softClauses.end() &&
81  std::find(newSoftClauses.begin(), newSoftClauses.end(), it) == newSoftClauses.end() ) continue;
82 
83  relaxationVars.push_back(carl::fresh_boolean_variable()); // r
84  carl::Variable blockingRelaxationVar = carl::fresh_boolean_variable(); // b_r
85 
86  // build new clause to add to formula
87  assert(extendedClauses.find(it) != extendedClauses.end());
88  FormulaT replacementClause = FormulaT(carl::FormulaType::OR, extendedClauses[it], FormulaT(relaxationVars.back()), FormulaT(blockingRelaxationVar));
89  newSoftClauses.push_back(replacementClause);
90 
91  extendedClauses[replacementClause] = it;
92  blockingVars[replacementClause] = blockingRelaxationVar;
93  assignments[blockingRelaxationVar] = !FormulaT(blockingRelaxationVar);
94 
95  SMTRAT_LOG_DEBUG("smtrat.maxsat.fumalik", "adding clause to backend: " << replacementClause);
96  mSolver.add(replacementClause);
97  formulaPositionMap[assignments[blockingRelaxationVar]] = addToSolver(assignments[blockingRelaxationVar]);
98 
99  // disable original clause
100  carl::Variable prevBlockingVar = blockingVars[extendedClauses[it]];
101  const auto& prevAssignment = assignments.find(prevBlockingVar);
102  assert(prevAssignment != assignments.end() && "Could not find an assignment which we must have made before.");
103 
104  mSolver.remove(formulaPositionMap[prevAssignment->second]);
105  assignments.erase(prevAssignment);
106 
107  SMTRAT_LOG_DEBUG("smtrat.maxsat.fumalik", "adding clause to backend: " << FormulaT(prevBlockingVar));
108  mSolver.add(FormulaT(prevBlockingVar));
109 
110  }
111 
112  Poly relaxationPoly;
113  for (carl::Variable& var : relaxationVars) {
114  relaxationPoly = relaxationPoly + var;
115  }
116 
117  // \sum r \ in relaxationVars : r <= 1
118  FormulaT pbEncoding = FormulaT(ConstraintT(relaxationPoly - Rational(1),carl::Relation::LEQ));
119  mSolver.add(pbEncoding);
120  // addSubformulaToPassedFormula(pbEncoding); // translate/solve this in backend!
121  SMTRAT_LOG_DEBUG("smtrat.maxsmt.fumalik", "Adding cardinality constraint to solver: " << pbEncoding);
122  }
123 
124  return Answer::SAT;
125  }
126 
127 };
128 
129 }
130 }
super::iterator iterator
Passing through the list::iterator.
Definition: ModuleInput.h:144
std::pair< Answer, FormulasT > compute_core(const FormulasT &formulas)
Definition: UnsatCore.h:53
MaxSMTBackend(Solver &solver, const std::vector< FormulaT > &softClauses)
int var(Lit p)
Definition: SolverTypes.h:64
static bool find(V &ts, const T &t)
Definition: Alg.h:47
Class to create the formulas for axioms.
carl::Formula< Poly > FormulaT
Definition: types.h:37
MaxSMTStrategy
Definition: MaxSMT.h:9
carl::MultivariatePolynomial< Rational > Poly
Definition: types.h:25
Answer
An enum with the possible answers a Module can give.
Definition: types.h:57
carl::Constraint< Poly > ConstraintT
Definition: types.h:29
carl::Formulas< Poly > FormulasT
Definition: types.h:39
mpq_class Rational
Definition: types.h:19
#define SMTRAT_LOG_DEBUG(channel, msg)
Definition: logging.h:35