SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
VarScheduler.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "SolverTypes.h"
4 #include "Heap.h"
5 #include <functional>
6 #include <random>
7 
8 namespace smtrat
9 {
10  /**
11  * Base class for variable schedulers. Removes the need to implement stubs.
12  *
13  * During instantiation, the Scheduler is constructed with a const SATModule& as parameter.
14  */
16 
17  protected:
18  std::function<double(Minisat::Var)> getActivity;
19  std::function<char(Minisat::Var)> getPolarity;
20  std::function<void(Minisat::Var,bool)> setPolarity;
21  std::function<bool(Minisat::Var)> isDecisionVar;
22  std::function<bool(Minisat::Var)> isBoolValueUndef;
23  std::function<bool(Minisat::Var)> isTheoryAbstraction;
24  std::function<const FormulaT&(Minisat::Var)> reabstractVariable;
25  std::function<const FormulaT&(Minisat::Lit)> reabstractLiteral;
26  std::function<const Minisat::Clause&(Minisat::CRef)> getClause;
29  std::function<unsigned(const FormulaT&)> currentlySatisfiedByBackend;
30  std::function</*const*/ Minisat::Var(const FormulaT&)> abstractVariable;
31  std::function<const Minisat::Lit(const FormulaT&)> abstractLiteral;
32  std::function<bool(const FormulaT&)> isAbstractedFormula;
33 
34  public:
35  template<typename BaseModule>
36  VarSchedulerBase(BaseModule& baseModule) :
37  getActivity([&baseModule](Minisat::Var v){ return baseModule.activity[v]; }),
38  getPolarity([&baseModule](Minisat::Var v){ return baseModule.polarity[v]; }),
39  setPolarity([&baseModule](Minisat::Var v, bool p){ return baseModule.polarity[v] = p; }),
40  isDecisionVar([&baseModule](Minisat::Var v){ return baseModule.decision[v]; }),
41  isBoolValueUndef([&baseModule](Minisat::Var v){ return baseModule.bool_value(v) == l_Undef; }),
42  isTheoryAbstraction([&baseModule](Minisat::Var v){ return (baseModule.mBooleanConstraintMap.size() > v) && (baseModule.mBooleanConstraintMap[v].first != nullptr); }),
43  reabstractVariable([&baseModule](Minisat::Var v) -> const auto& { return baseModule.mBooleanConstraintMap[v].first->reabstraction; }),
44  reabstractLiteral([&baseModule](Minisat::Lit l) -> const auto& { return Minisat::sign(l) ? baseModule.mBooleanConstraintMap[Minisat::var(l)].second->reabstraction : baseModule.mBooleanConstraintMap[Minisat::var(l)].first->reabstraction; }),
45  getClause([&baseModule](Minisat::CRef cl) -> const auto& { return baseModule.getClause(cl); }),
46  getBoolVarValue([&baseModule](Minisat::Var v){ return baseModule.bool_value(v); }),
47  getBoolLitValue([&baseModule](Minisat::Lit l){ return baseModule.bool_value(l); }),
48  currentlySatisfiedByBackend([&baseModule](const FormulaT& f){ return baseModule.currentlySatisfiedByBackend(f); }),
49  abstractVariable([&baseModule](const FormulaT& f) { return Minisat::var(baseModule.mConstraintLiteralMap.at(f).front()); }),
50  abstractLiteral([&baseModule](const FormulaT& f) { return baseModule.mConstraintLiteralMap.at(f).front(); }),
51  isAbstractedFormula([&baseModule](const FormulaT& f) { return baseModule.mConstraintLiteralMap.count(f) > 0; })
52  {}
53 
54  /**
55  * Rebuild heap.
56  */
57  void rebuild() { assert(false); }
58 
59  /**
60  * Insert a variable. If already contained, do nothing.
61  */
62  void insert(Minisat::Var) { assert(false); }
63 
64  /**
65  * Returns the next variable to be decided.
66  */
67  // Minisat::Var top() { assert(false); }
68 
69  /**
70  * Returns and removes the next variable to be decided.
71  */
72  Minisat::Lit pop() { assert(false); return Minisat::mkLit(0); }
73 
74  /**
75  * Check if empty.
76  */
77  bool empty() {assert(false); return true; }
78 
79  /**
80  * Check if variable is contained.
81  */
82  // bool contains(Minisat::Var) { assert(false); }
83 
84  /**
85  * Print.
86  */
87  void print() const { assert(false); }
88 
89  // Events called by SATModule
90 
92  }
93 
95  }
96 
98  }
99 
100  template<typename Constraints>
101  void rebuildTheoryVars(const Constraints&) {
102  }
103 
104  void attachClause(Minisat::CRef /* cl */) {
105  }
106 
107  void detachClause(Minisat::CRef /* cl */) {
108  }
109 
110  void relocateClauses(std::function<void(Minisat::CRef&)> /* relocate */) {
111  }
112  };
113 
114  /**
115  * Minisat's activity-based variable scheduling.
116  */
118  struct VarOrderLt
119  {
120  std::function<bool(Minisat::Var,Minisat::Var)> cmp;
121 
123  {
124  return cmp(x,y);
125  }
126 
127  explicit VarOrderLt( std::function<bool(Minisat::Var,Minisat::Var)> cmp ) :
128  cmp( cmp )
129  {}
130  };
131 
133 
134  protected:
137  }
138 
139  public:
140  template<typename BaseModule>
141  explicit VarSchedulerMinisat( BaseModule& baseModule, std::function<bool(Minisat::Var,Minisat::Var)> cmp ) :
142  VarSchedulerBase( baseModule ),
143  order_heap( VarOrderLt( cmp ) )
144  {}
145 
146  template<typename BaseModule>
147  explicit VarSchedulerMinisat( BaseModule& baseModule ) :
148  VarSchedulerMinisat( baseModule, [this](Minisat::Var x, Minisat::Var y) -> bool { return getActivity(x) > getActivity(y); } )
149  {}
150 
151  void rebuild() {
153  for(Minisat::Var v = 0; v < order_heap.size(); v++)
154  if(order_heap.inHeap(v) && valid(v))
155  vs.push(v);
156  order_heap.build(vs);
157  }
158 
160  if (!order_heap.inHeap(var) && valid(var))
161  order_heap.insert(var);
162  }
163 
165  if (empty())
166  return var_Undef;
167  return order_heap[0];
168  }
169 
171  if (empty())
172  return Minisat::lit_Undef;
173  auto next = order_heap.removeMin();
174  return Minisat::mkLit( next, getPolarity(next) );
175  }
176 
177  bool empty() {
178  while(!order_heap.empty() && !valid(order_heap[0]))
179  order_heap.removeMin();
180  return order_heap.empty();
181  }
182 
183  /*
184  bool contains(Minisat::Var var) {
185  return order_heap.inHeap(var) && valid(var);
186  }
187  */
188 
189  void print() const {
190  order_heap.print();
191  }
192 
193  // Events called by SATModule
194 
196  if(order_heap.inHeap(var))
197  order_heap.decrease(var);
198  }
199 
201  if(order_heap.inHeap(var))
202  order_heap.increase(var);
203  }
204 
206  rebuild();
207  }
208 
209  };
210 
212  std::vector<Minisat::Var> ordering;
213 
214  private:
216  auto iter = std::find(ordering.begin(), ordering.end(), var);
217  if (iter == ordering.end()) {
218  auto it = ordering.begin();
219  std::size_t idx = 0;
220  if (ordering.size() > 0) {
221  std::random_device rd;
222  std::mt19937 gen(rd());
223  std::uniform_int_distribution<std::size_t> dis(0, ordering.size()-1);
224  idx = dis(gen);
225  }
226  it += idx;
227  iter = ordering.insert(it, var);
228  }
229  return iter;
230  }
231 
232  public:
233  template<typename BaseModule>
234  explicit VarSchedulerFixedRandom( BaseModule& baseModule ) :
235  VarSchedulerMinisat( baseModule, [this](Minisat::Var x, Minisat::Var y) { return getIndex(x) > getIndex(y); } )
236  {}
237  };
238 
239  /**
240  * Random scheduler
241  */
243 
244  std::vector<Minisat::Var> vars;
245 
246  protected:
248  return isDecisionVar(var) && isBoolValueUndef(var);
249  }
250 
251  public:
252  template<typename BaseModule>
253  explicit VarSchedulerRandom( BaseModule& baseModule ) :
254  VarSchedulerBase( baseModule )
255  {}
256 
257  void rebuild() {}
258 
260  if (std::find(vars.begin(), vars.end(), var) == vars.end() && valid(var)) {
261  auto it = vars.begin();
262  std::random_device rd;
263  std::mt19937 gen(rd());
264  std::uniform_int_distribution<std::size_t> dis(0, vars.size()-1);
265  it += dis(gen);
266  vars.insert(it, var);
267  }
268  }
269 
270  /*
271  Minisat::Var top() {
272  if (empty())
273  return var_Undef;
274  return vars.back();
275  }
276  */
277 
279  if (empty())
280  return Minisat::lit_Undef;
281  auto res = vars.back();
282  vars.pop_back();
283  return Minisat::mkLit( res, getPolarity(res) );
284  }
285 
286  bool empty() {
287  while(!vars.empty() && !valid(vars.back()))
288  vars.pop_back();
289  return vars.empty();
290  }
291 
292  /*
293  bool contains(Minisat::Var var) {
294  return std::find(vars.begin(), vars.end(), var) != vars.end() && valid(var);
295  }
296  */
297 
298  void print() const {
299  std::cout << "Random scheduler contents: " << vars << std::endl;
300  }
301  };
302 
303 
304  /**
305  * Scheduler for SMT, implementing theory guided heuristics.
306  */
307  template<TheoryGuidedDecisionHeuristicLevel theory_conflict_guided_decision_heuristic>
310 
311  public:
312  template<typename BaseModule>
313  explicit VarSchedulerSMTTheoryGuided( BaseModule& baseModule ) :
314  VarSchedulerBase( baseModule ),
315  minisat( baseModule )
316  {}
317 
318  void rebuild() {
319  minisat.rebuild();
320  }
321 
323  minisat.insert(var);
324  }
325 
327  Minisat::Var next = var_Undef;
328  std::vector<Minisat::Var> varsToRestore;
329 
330  while (next == var_Undef) {
331  if (minisat.empty()) {
332  next = var_Undef;
333  break;
334  }
335  else {
336  next = var(minisat.pop());
337 
338  if (isTheoryAbstraction(next)) {
339  unsigned consistency = currentlySatisfiedByBackend(reabstractVariable(next));
340  bool skipVariable = false;
341  switch (theory_conflict_guided_decision_heuristic) {
342  case TheoryGuidedDecisionHeuristicLevel::CONFLICT_FIRST: {
343  switch (consistency) {
344  case 0:
345  setPolarity(next, false);
346  break;
347  case 1:
348  setPolarity(next, true);
349  break;
350  default:
351  skipVariable = true;
352  break;
353  }
354  break;
355  }
356  case TheoryGuidedDecisionHeuristicLevel::SATISFIED_FIRST: {
357  switch (consistency) {
358  case 0:
359  setPolarity(next, true);
360  break;
361  case 1:
362  setPolarity(next, false);
363  break;
364  default:
365  skipVariable = true;
366  break;
367  }
368  break;
369  }
370  default:
371  assert( theory_conflict_guided_decision_heuristic == TheoryGuidedDecisionHeuristicLevel::DISABLED );
372  break;
373  }
374  if (skipVariable) {
375  varsToRestore.push_back(next);
376  next = var_Undef;
377  }
378  }
379  }
380  }
381  for (auto v : varsToRestore) {
382  minisat.insert(v);
383  }
384  if (next == var_Undef) {
385  return minisat.pop();
386  } else {
387  return Minisat::mkLit(next, getPolarity(next));
388  }
389  }
390 
391  bool empty() {
392  return minisat.empty();
393  }
394 
395  void print() const {
396  minisat.print();
397  }
398 
399  // Events called by SATModule
400 
402  minisat.increaseActivity(var);
403  }
404 
406  minisat.decreaseActivity(var);
407  }
408 
410  minisat.rebuildActivities();
411  }
412 
413  };
414 }
#define var_Undef
Definition: SolverTypes.h:43
#define l_Undef
Definition: SolverTypes.h:99
void print() const
Definition: Heap.h:182
void build(vec< int > &ns)
Definition: Heap.h:159
void insert(int n)
Definition: Heap.h:136
void decrease(int n)
Definition: Heap.h:112
int removeMin()
Definition: Heap.h:146
int size() const
Definition: Heap.h:91
bool empty() const
Definition: Heap.h:96
void increase(int n)
Definition: Heap.h:118
bool inHeap(int n) const
Definition: Heap.h:101
void push(void)
Definition: Vec.h:147
Base class for variable schedulers.
Definition: VarScheduler.h:15
VarSchedulerBase(BaseModule &baseModule)
Definition: VarScheduler.h:36
std::function< bool(Minisat::Var)> isTheoryAbstraction
Definition: VarScheduler.h:23
std::function< bool(Minisat::Var)> isDecisionVar
Definition: VarScheduler.h:21
std::function< const FormulaT &(Minisat::Var)> reabstractVariable
Definition: VarScheduler.h:24
std::function< double(Minisat::Var)> getActivity
Definition: VarScheduler.h:18
void rebuild()
Rebuild heap.
Definition: VarScheduler.h:57
std::function< const Minisat::Clause &(Minisat::CRef)> getClause
Definition: VarScheduler.h:26
std::function< Minisat::lbool(Minisat::Var)> getBoolVarValue
Definition: VarScheduler.h:27
void increaseActivity(Minisat::Var)
Definition: VarScheduler.h:91
std::function< Minisat::lbool(Minisat::Lit)> getBoolLitValue
Definition: VarScheduler.h:28
void rebuildTheoryVars(const Constraints &)
Definition: VarScheduler.h:101
bool empty()
Check if empty.
Definition: VarScheduler.h:77
void insert(Minisat::Var)
Insert a variable.
Definition: VarScheduler.h:62
void relocateClauses(std::function< void(Minisat::CRef &)>)
Definition: VarScheduler.h:110
void attachClause(Minisat::CRef)
Definition: VarScheduler.h:104
std::function< bool(Minisat::Var)> isBoolValueUndef
Definition: VarScheduler.h:22
void detachClause(Minisat::CRef)
Definition: VarScheduler.h:107
std::function< unsigned(const FormulaT &)> currentlySatisfiedByBackend
Definition: VarScheduler.h:29
std::function< const Minisat::Lit(const FormulaT &)> abstractLiteral
Definition: VarScheduler.h:31
std::function< char(Minisat::Var)> getPolarity
Definition: VarScheduler.h:19
std::function< void(Minisat::Var, bool)> setPolarity
Definition: VarScheduler.h:20
std::function< bool(const FormulaT &)> isAbstractedFormula
Definition: VarScheduler.h:32
Minisat::Lit pop()
Returns the next variable to be decided.
Definition: VarScheduler.h:72
std::function< const FormulaT &(Minisat::Lit)> reabstractLiteral
Definition: VarScheduler.h:25
void decreaseActivity(Minisat::Var)
Definition: VarScheduler.h:94
void print() const
Check if variable is contained.
Definition: VarScheduler.h:87
std::function< Minisat::Var(const FormulaT &)> abstractVariable
Definition: VarScheduler.h:30
std::vector< Minisat::Var > ordering
Definition: VarScheduler.h:212
auto getIndex(Minisat::Var var)
Definition: VarScheduler.h:215
VarSchedulerFixedRandom(BaseModule &baseModule)
Definition: VarScheduler.h:234
Minisat's activity-based variable scheduling.
Definition: VarScheduler.h:117
VarSchedulerMinisat(BaseModule &baseModule, std::function< bool(Minisat::Var, Minisat::Var)> cmp)
Definition: VarScheduler.h:141
void increaseActivity(Minisat::Var var)
Definition: VarScheduler.h:195
Minisat::Heap< VarOrderLt > order_heap
Definition: VarScheduler.h:132
VarSchedulerMinisat(BaseModule &baseModule)
Definition: VarScheduler.h:147
void insert(Minisat::Var var)
Definition: VarScheduler.h:159
bool valid(Minisat::Var var)
Definition: VarScheduler.h:135
void decreaseActivity(Minisat::Var var)
Definition: VarScheduler.h:200
std::vector< Minisat::Var > vars
Definition: VarScheduler.h:244
void insert(Minisat::Var var)
Definition: VarScheduler.h:259
bool valid(Minisat::Var var)
Definition: VarScheduler.h:247
VarSchedulerRandom(BaseModule &baseModule)
Definition: VarScheduler.h:253
Scheduler for SMT, implementing theory guided heuristics.
Definition: VarScheduler.h:308
void increaseActivity(Minisat::Var var)
Definition: VarScheduler.h:401
void insert(Minisat::Var var)
Definition: VarScheduler.h:322
VarSchedulerSMTTheoryGuided(BaseModule &baseModule)
Definition: VarScheduler.h:313
void decreaseActivity(Minisat::Var var)
Definition: VarScheduler.h:405
Definition: Alg.h:27
int Var
Definition: SolverTypes.h:42
int var(Lit p)
Definition: SolverTypes.h:64
static bool find(V &ts, const T &t)
Definition: Alg.h:47
RegionAllocator< uint32_t >::Ref CRef
Definition: SolverTypes.h:142
Lit mkLit(Var var, bool sign=false)
Definition: SolverTypes.h:60
bool sign(Lit p)
Definition: SolverTypes.h:63
const Lit lit_Undef
Definition: SolverTypes.h:72
std::vector< carl::Variable > vars(const std::pair< QuantifierType, std::vector< carl::Variable >> &p)
Definition: QEQuery.h:43
Class to create the formulas for axioms.
carl::Formula< Poly > FormulaT
Definition: types.h:37
VarOrderLt(std::function< bool(Minisat::Var, Minisat::Var)> cmp)
Definition: VarScheduler.h:127
bool operator()(Minisat::Var x, Minisat::Var y)
Definition: VarScheduler.h:122
std::function< bool(Minisat::Var, Minisat::Var)> cmp
Definition: VarScheduler.h:120