SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
SATModule.tpp
Go to the documentation of this file.
1 /*
2  * **************************************************************************************[Solver.cc]
3  * Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
4  * Copyright (c) 2007-2010, Niklas Sorensson
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7  * associated documentation files (the "Software"), to deal in the Software without restriction,
8  * including without limitation the rights to use, copy, modify, merge, publish, distribute,
9  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all copies or
13  * substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
16  * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
19  * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20  */
21 /**
22  * @file SATModule.cpp
23  * @author Florian Corzilius <corzilius@cs.rwth-aachen.de>
24  * @since 2012-01-18
25  * @version 2014-10-02
26  */
27 
28 #include "SATModule.h"
29 #include <iomanip>
30 #include <carl-formula/formula/functions/Complexity.h>
31 
32 #ifdef LOGGING
33 //#define DEBUG_SATMODULE
34 //#define DEBUG_SATMODULE_THEORY_PROPAGATION
35 //#define DEBUG_SATMODULE_DECISION_HEURISTIC
36 //#define DEBUG_SATMODULE_LEMMA_HANDLING
37 #endif
38 
39 using namespace Minisat;
40 
41 namespace smtrat
42 {
43  // Options:
44  static const char* _cat = "CORE";
45  static DoubleOption opt_var_decay( _cat, "var-decay", "The variable activity decay factor", 0.95, DoubleRange( 0, false, 1, false ) );
46  static DoubleOption opt_clause_decay( _cat, "cla-decay", "The clause activity decay factor", 0.999, DoubleRange( 0, false, 1, false ) );
47  static DoubleOption opt_random_var_freq( _cat, "rnd-freq", "The frequency with which the decision heuristic tries to choose a random variable",
48  0, DoubleRange( 0, true, 1, true ) );
49  static DoubleOption opt_random_seed( _cat, "rnd-seed", "Used by the random variable selection", 91648253,
50  DoubleRange( 0, false, HUGE_VAL, false ) );
51  static IntOption opt_ccmin_mode( _cat, "ccmin-mode", "Controls conflict clause minimization (0=none, 1=basic, 2=deep)", 2, IntRange( 0, 2 ) );
52  static IntOption opt_phase_saving( _cat, "phase-saving", "Controls the level of phase saving (0=none, 1=limited, 2=full)", 2, IntRange( 0, 2 ) );
53  static BoolOption opt_rnd_init_act( _cat, "rnd-init", "Randomize the initial activity", false );
54  static BoolOption opt_luby_restart( _cat, "luby", "Use the Luby restart sequence", true );
55  static IntOption opt_restart_first( _cat, "rfirst", "The base restart interval", 25, IntRange( 1, INT32_MAX ) );
56  static DoubleOption opt_restart_inc( _cat, "rinc", "Restart interval increase factor", 3, DoubleRange( 1, false, HUGE_VAL, false ) );
57  static DoubleOption opt_garbage_frac( _cat, "gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered", 0.20,
58  DoubleRange( 0, false, HUGE_VAL, false ) );
59 
60  template<class Settings>
61  SATModule<Settings>::SATModule( const ModuleInput* _formula, Conditionals& _foundAnswer, Manager* const _manager ):
62  Module( _formula, _foundAnswer, _manager, Settings::moduleName ),
63  // Parameters (user settable):
64  verbosity( 0 ),
65  var_decay( opt_var_decay ),
66  clause_decay( opt_clause_decay ),
67  random_var_freq( opt_random_var_freq ),
68  random_seed( opt_random_seed ),
69  luby_restart( opt_luby_restart ),
70  ccmin_mode( opt_ccmin_mode ),
71  phase_saving( opt_phase_saving ),
72  rnd_pol( false ),
73  rnd_init_act( opt_rnd_init_act ),
74  garbage_frac( opt_garbage_frac ),
75  restart_first( opt_restart_first ),
76  restart_inc( opt_restart_inc ),
77  // Parameters (the rest):
78  learntsize_factor( 1 ),
79  learntsize_inc( 1.5 ),
80  // Parameters (experimental):
81  learntsize_adjust_start_confl( 100 ),
82  learntsize_adjust_inc( 1.5 ),
83  // Statistics: (formerly in 'SolverStats')
84  solves( 0 ),
85  starts( 0 ),
86  decisions( 0 ),
87  rnd_decisions( 0 ),
88  propagations( 0 ),
89  conflicts( 0 ),
90  dec_vars( 0 ),
91  clauses_literals( 0 ),
92  learnts_literals( 0 ),
93  max_literals( 0 ),
94  tot_literals( 0 ),
95  ok( true ),
96  cla_inc( 1 ),
97  var_inc( 1 ),
98  watches( WatcherDeleted( ca ) ),
99  qhead( 0 ),
100  simpDB_assigns( -1 ),
101  simpDB_props( 0 ),
102  var_scheduler( *this ),
103  progress_estimate( 0 ),
104  remove_satisfied( Settings::remove_satisfied ),
105  // Resource constraints:
106  conflict_budget( -1 ),
107  propagation_budget( -1 ),
108  asynch_interrupt( false ),
109  mChangedPassedFormula( false ),
110  mComputeAllSAT( false ),
111  mFullAssignmentCheckedForConsistency( false ),
112  mOptimumComputed( false ),
113  mBusy( false ),
114  mExcludedAssignments( false ),
115  mCurrentAssignmentConsistent( SAT ),
116  mNumberOfFullLazyCalls( 0 ),
117  mCurr_Restarts( 0 ),
118  mNumberOfTheoryCalls( 0 ),
119  mReceivedFormulaPurelyPropositional(true),
120  mConstraintLiteralMap(),
121  mBooleanVarMap(),
122  mMinisatVarMap(),
123  mFormulaAssumptionMap(),
124  mFormulaCNFInfosMap(),
125  mClauseInformation(),
126  mLiteralClausesMap(),
127  mNumberOfSatisfiedClauses( 0 ),
128  mChangedBooleans(),
129  mAllActivitiesChanged( false ),
130  mChangedActivities(),
131  mPropagatedLemmas(),
132  mRelevantVariables(),
133  mNonTseitinShadowedOccurrences(),
134  mTseitinVarShadows(),
135  mTseitinVarFormulaMap(),
136  mCurrentTheoryConflicts(),
137  mCurrentTheoryConflictTypes(),
138  mCurrentTheoryConflictEvaluations(),
139  mLevelCounter(),
140  mTheoryConflictIdCounter( 0 ),
141  mUpperBoundOnMinimal( passedFormulaEnd() ),
142  mLiteralsClausesMap(),
143  mLiteralsActivOccurrences(),
144  //mTheoryVariableStack(),
145  //mNextTheoryVariable(mTheoryVariableStack.end()),
146  mMCSAT(*this)
147  {
148  if (Settings::mc_sat) {
149  ca.extra_clause_field = true;
150  }
151  mCurrentTheoryConflicts.reserve(100);
152  mCurrentTheoryConflictTypes.reserve(100);
153  mTrueVar = newVar();
154  uncheckedEnqueue( mkLit( mTrueVar, false ) );
155  mBooleanConstraintMap.push( std::make_pair( nullptr, nullptr ) );
156  }
157 
158  template<class Settings>
159  SATModule<Settings>::~SATModule()
160  {
161  while( mBooleanConstraintMap.size() > 0 )
162  {
163  Abstraction* abstrAToDel = mBooleanConstraintMap.last().first;
164  Abstraction* abstrBToDel = mBooleanConstraintMap.last().second;
165  mBooleanConstraintMap.pop();
166  delete abstrAToDel;
167  delete abstrBToDel;
168  abstrAToDel = nullptr;
169  abstrBToDel = nullptr;
170  }
171  }
172 
173  class ScopedBool
174  {
175  bool& watch;
176  bool oldValue;
177 
178  public:
179 
180  ScopedBool( bool& watch, bool newValue ):
181  watch(watch),
182  oldValue(watch)
183  {
184  watch = newValue;
185  }
186 
187  ~ScopedBool()
188  {
189  watch = oldValue;
190  }
191  };
192 
193  template<class Settings>
194  bool SATModule<Settings>::addCore( ModuleInput::const_iterator _subformula )
195  {
196  if( _subformula->formula().is_false() )
197  {
198  mModelComputed = false;
199  mOptimumComputed = false;
200  mInfeasibleSubsets.emplace_back();
201  mInfeasibleSubsets.back().insert( _subformula->formula() );
202  return false;
203  }
204  else if( !_subformula->formula().is_true() )
205  {
206  if( !_subformula->formula().is_only_propositional() )
207  mReceivedFormulaPurelyPropositional = false;
208  mModelComputed = false;
209  mOptimumComputed = false;
210  //TODO Matthias: better solution?
211  cancelUntil(0, true);
212  adaptPassedFormula();
213  if( _subformula->formula().property_holds( carl::PROP_IS_A_LITERAL ) )
214  {
215  assumptions.push( createLiteral( _subformula->formula(), _subformula->formula() ) );
216  assert( mFormulaAssumptionMap.find( _subformula->formula() ) == mFormulaAssumptionMap.end() );
217  mFormulaAssumptionMap.emplace( _subformula->formula(), assumptions.last() );
218  }
219  else
220  {
221  addClauses( _subformula->formula(), NORMAL_CLAUSE, 0, _subformula->formula() );
222  }
223  if ( isLemmaLevel(NORMAL) && decisionLevel() == 0)
224  {
225  if (_subformula->formula().property_holds(carl::PROP_IS_A_LITERAL) && _subformula->formula().property_holds(carl::PROP_CONTAINS_BOOLEAN))
226  {
227  // Add literal from unary clause to lemmas
228  carl::carlVariables vars = carl::boolean_variables(_subformula->formula());
229  assert(vars.size() == 1);
230  // Get corresponding Minisat variable
231  BooleanVarMap::const_iterator itVar = mBooleanVarMap.find(*vars.begin());
232  assert(itVar != mBooleanVarMap.end());
233  Minisat::Var var = itVar->second;
234  // Insert new propagated lemma
235  mPropagatedLemmas[var].push_back(_subformula->formula());
236  }
237  }
238  }
239  if( !ok )
240  updateInfeasibleSubset();
241  return ok;
242  }
243 
244  template<class Settings>
245  void SATModule<Settings>::removeCore( ModuleInput::const_iterator _subformula )
246  {
247  if( _subformula->formula().is_false() || _subformula->formula().is_true() )
248  return;
249  cancelUntil( 0, true ); // can we do better than this?
250  if( !mReceivedFormulaPurelyPropositional )
251  adaptPassedFormula();
252  assert( rPassedFormula().empty() );
253  for( int i = 0; i < learnts.size(); ++i )
254  {
255  assert( learnts[i] != CRef_Undef );
256  removeClause( learnts[i] );
257  }
258  learnts.clear();
259  mUnorderedClauseLookup.clear();
260  ok = true;
261  if( _subformula->formula().property_holds( carl::PROP_IS_A_LITERAL ) )
262  {
263  auto iter = mFormulaAssumptionMap.find( _subformula->formula() );
264  assert( iter != mFormulaAssumptionMap.end() );
265  int i = 0;
266  while( assumptions[i] != iter->second ) ++i;
267  while( i < assumptions.size() - 1 )
268  {
269  assumptions[i] = assumptions[i+1];
270  ++i;
271  }
272  assumptions.pop();
273  mFormulaAssumptionMap.erase( iter );
274  ConstraintLiteralsMap::iterator constraintLiteralPair = mConstraintLiteralMap.find( _subformula->formula() );
275  if( constraintLiteralPair != mConstraintLiteralMap.end() )
276  removeLiteralOrigin( constraintLiteralPair->second.front(), _subformula->formula() );
277  }
278  else
279  {
280  auto cnfInfoIter = mFormulaCNFInfosMap.find( _subformula->formula().remove_negations() );
281  assert( cnfInfoIter != mFormulaCNFInfosMap.end() );
282  updateCNFInfoCounter( cnfInfoIter, _subformula->formula(), false );
283  if( cnfInfoIter->second.mClauses.empty() )
284  {
285  mFormulaCNFInfosMap.erase( cnfInfoIter );
286  }
287  std::vector<FormulaT> constraints;
288  carl::arithmetic_constraints(_subformula->formula(), constraints);
289  for( const FormulaT& constraint : constraints )
290  {
291  ConstraintLiteralsMap::iterator constraintLiteralPair = mConstraintLiteralMap.find( constraint );
292  if( constraintLiteralPair != mConstraintLiteralMap.end() )
293  removeLiteralOrigin( constraintLiteralPair->second.front(), _subformula->formula() );
294  constraintLiteralPair = mConstraintLiteralMap.find( constraint.negated() );
295  if( constraintLiteralPair != mConstraintLiteralMap.end() )
296  removeLiteralOrigin( constraintLiteralPair->second.front(), _subformula->formula() );
297  }
298  }
299  }
300 
301  template<class Settings>
302  void SATModule<Settings>::removeLiteralOrigin( Lit _litToRemove, const FormulaT& _origin )
303  {
304  int abstractionVar = var(_litToRemove);
305  auto& abstrPair = mBooleanConstraintMap[abstractionVar];
306  assert( abstrPair.first != nullptr && abstrPair.second != nullptr );
307  Abstraction& abstr = sign(_litToRemove) ? *abstrPair.second : *abstrPair.first;
308  if( abstr.origins != nullptr )
309  {
310  auto& origs = *abstr.origins;
311  auto iter = origs.begin();
312  while( iter != origs.end() )
313  {
314  if( *iter == _origin || (iter->type() == carl::FormulaType::AND && iter->contains( _origin )) )
315  {
316  if (iter != --origs.end())
317  {
318  *iter = origs.back();
319  origs.pop_back();
320  }
321  else
322  {
323  origs.pop_back();
324  break;
325  }
326  }
327  else
328  {
329  ++iter;
330  }
331  }
332  if( origs.empty() )
333  {
334  abstr.origins = nullptr;
335  }
336  }
337  }
338 
339  template<class Settings>
340  double SATModule<Settings>::luby( double y, int x )
341  {
342  // Find the finite subsequence that contains index 'x', and the
343  // size of that subsequence:
344  int size, seq;
345  for( size = 1, seq = 0; size < x + 1; seq++, size = 2 * size + 1 );
346 
347  while( size - 1 != x )
348  {
349  size = (size - 1) >> 1;
350  seq--;
351  x = x % size;
352  }
353 
354  return pow( y, seq );
355  }
356 
357  template<class Settings>
358  Answer SATModule<Settings>::checkCore()
359  {
360  //for( const auto& f : rReceivedFormula() )
361  // std::cout << " " << f.formula() << std::endl;
362 // std::cout << ((FormulaT) rReceivedFormula()) << std::endl;
363  #ifdef SMTRAT_DEVOPTION_Statistics
364  mStatistics.rNrTotalVariablesBefore() = (size_t) nVars();
365  mStatistics.rNrClauses() = (size_t) nClauses();
366  #endif
367  ScopedBool scopedBool( mBusy, true );
368  budgetOff();
369 // assumptions.clear();
370  Module::init();
371  processLemmas();
372 
373  if (Settings::mc_sat) {
374  #ifdef DEBUG_SATMODULE
375  std::cout << "### Processing clause" << std::endl;
376  print(std::cout, "###");
377  #endif
378  mMCSAT.initVariables(mBooleanConstraintMap);
379  for (const auto& v : mMCSAT.theoryVarAbstractions()) {
380  var_scheduler.insert(v);
381  }
382  assert(mMCSAT.level() == 0);
383  if (var_scheduler.empty()) {
384  SMTRAT_LOG_DEBUG("smtrat.sat", "We have no variables in our variable scheduler.");
385  } else {
386  var_scheduler.rebuildTheoryVars(mBooleanConstraintMap);
387  }
388  }
389  ++solves;
390  // compared to original minisat we add the number of clauses with size 1 (nAssigns()) and learnts, we got after init()
391  max_learnts = (nAssigns() + nClauses() + nLearnts() ) * learntsize_factor;
392  learntsize_adjust_confl = learntsize_adjust_start_confl;
393  learntsize_adjust_cnt = (int)learntsize_adjust_confl;
394 
395  if( !ok )
396  {
397  assert( !mInfeasibleSubsets.empty() );
398  #ifdef SMTRAT_DEVOPTION_Statistics
399  collectStats();
400  #endif
401  mBusy = false;
402  return UNSAT;
403  }
404  mReceivedFormulaPurelyPropositional = rReceivedFormula().is_only_propositional();
405  if( mReceivedFormulaPurelyPropositional )
406  {
407  mAllActivitiesChanged = false;
408  mChangedBooleans.clear();
409  mChangedActivities.clear();
410  }
411  else if( Settings::initiate_activities )
412  {
413  double highestActivity = 0;
414  for( int pos = 0; pos < activity.size(); ++pos )
415  {
416  double& act = activity[pos];
417  act = 1;
418  if( Settings::check_active_literal_occurrences && false )
419  {
420  const auto& litActOccs = mLiteralsActivOccurrences[(size_t)pos];
421  act = (double)litActOccs.first + (double)litActOccs.second;
422  }
423  if( mBooleanConstraintMap[pos].first != nullptr )
424  {
425  act /= (double)carl::complexity(mBooleanConstraintMap[pos].first->reabstraction);
426  }
427  else
428  {
429  auto tvfIter = mTseitinVarFormulaMap.find( pos );
430  if( tvfIter != mTseitinVarFormulaMap.end() )
431  act /= (double)carl::complexity(tvfIter->second);
432  }
433  if( act > highestActivity )
434  highestActivity = act;
435  }
436  if( highestActivity > 1 )
437  {
438  for( int pos = 0; pos < activity.size(); ++pos )
439  {
440  activity[pos] /= highestActivity;
441  }
442  }
443  var_scheduler.rebuildActivities();
444  }
445  Minisat::lbool result = l_Undef;
446  mUpperBoundOnMinimal = passedFormulaEnd();
447  bool isOptimal = true;
448  while( true )
449  {
450  if( Settings::use_restarts )
451  {
452  mCurr_Restarts = 0;
453  int current_restarts = -1;
454  while( current_restarts < mCurr_Restarts )
455  {
456  current_restarts = mCurr_Restarts;
457  double rest_base = luby_restart ? luby( restart_inc, mCurr_Restarts ) : pow( restart_inc, mCurr_Restarts );
458  result = search( (int)rest_base * restart_first );
459  // if( !withinBudget() ) break;
460  }
461  }
462  else
463  result = search();
464 
465  if (isLemmaLevel(LemmaLevel::ADVANCED))
466  {
467  assert(result == l_True);
468  computeAdvancedLemmas();
469  }
470  if( !Settings::stop_search_after_first_unknown )
471  {
472  unknown_excludes.clear();
473  mExcludedAssignments = false;
474  }
475  // ##### Stop here if not in optimization mode!
476  if( !is_minimizing() )
477  break;
478  std::vector<CRef> excludedAssignments;
479  if( result == l_Undef )
480  break;
481  else if( result == l_False )
482  {
483  if( mUpperBoundOnMinimal != rPassedFormula().end() )
484  {
485  cleanUpAfterOptimizing( excludedAssignments );
486  result = l_True;
487  }
488  break;
489  }
490  else
491  {
492  assert( result == l_True );
493  Answer runBackendAnswer = runBackends( true, mFullCheck, objective() );
494  assert(is_sat(runBackendAnswer));
495  isOptimal = isOptimal && (runBackendAnswer == OPTIMAL);
496  updateModel();
497  auto modelIter = mModel.find( objective() );
498  assert( modelIter != mModel.end() );
499  const ModelValue& mv = modelIter->second;
500  if( mv.isMinusInfinity() )
501  {
502  cleanUpAfterOptimizing( excludedAssignments );
503  break;
504  }
505  assert( mv.isRational() ); // @todo: how do we handle the other model value types?
506  // Add a new upper bound on the yet computed minimum
507  removeUpperBoundOnMinimal();
508  FormulaT newUpperBoundOnMinimal( objective() - mv.asRational(), carl::Relation::LESS );
509  addConstraintToInform_( newUpperBoundOnMinimal );
510  mUpperBoundOnMinimal = addSubformulaToPassedFormula( newUpperBoundOnMinimal, newUpperBoundOnMinimal ).first;
511  // Exclude the last theory call with a clause.
512  vec<Lit> excludeClause;
513  for( int k = 0; k < mBooleanConstraintMap.size(); ++k )
514  {
515  if( assigns[k] != l_Undef )
516  {
517  if( mBooleanConstraintMap[k].first != nullptr )
518  {
519  assert( mBooleanConstraintMap[k].second != nullptr );
520  const Abstraction& abstr = assigns[k] == l_False ? *mBooleanConstraintMap[k].second : *mBooleanConstraintMap[k].first;
521  if( !abstr.reabstraction.is_true() && abstr.consistencyRelevant && (abstr.reabstraction.type() == carl::FormulaType::UEQ || abstr.reabstraction.type() == carl::FormulaType::BITVECTOR || abstr.reabstraction.constraint().is_consistent() != 1))
522  {
523  excludeClause.push( mkLit( k, assigns[k] != l_False ) );
524  }
525  }
526  }
527  }
528  addClause( excludeClause, PERMANENT_CLAUSE );
529  CRef confl = storeLemmas();
530  if( confl != CRef_Undef )
531  excludedAssignments.push_back( confl );
532  if( !ok || decisionLevel() <= assumptions.size() )
533  {
534  cleanUpAfterOptimizing( excludedAssignments );
535  break;
536  }
537  if( confl != CRef_Undef )
538  handleConflict( confl );
539  }
540  }
541 
542  #ifdef SMTRAT_DEVOPTION_Statistics
543  collectStats();
544  #endif
545  if( result == l_True )
546  {
547  return (is_minimizing() && isOptimal) ? OPTIMAL : SAT;
548  }
549  else if( result == l_False )
550  {
551  SMTRAT_LOG_DEBUG("smtrat.sat", "ok = false");
552  ok = false;
553  updateInfeasibleSubset();
554  return UNSAT;
555  }
556  return UNKNOWN;
557  }
558 
559  template<class Settings>
560  Minisat::lbool SATModule<Settings>::checkFormula()
561  {
562  if( Settings::use_restarts )
563  {
564  mCurr_Restarts = 0;
565  int current_restarts = -1;
566  Minisat::lbool result = l_Undef;
567  while( current_restarts < mCurr_Restarts )
568  {
569  current_restarts = mCurr_Restarts;
570  double rest_base = luby_restart ? luby( restart_inc, mCurr_Restarts ) : pow( restart_inc, mCurr_Restarts );
571  result = search( (int)rest_base * restart_first );
572  // if( !withinBudget() ) break;
573  }
574  return result;
575  }
576  else
577  {
578  return search();
579  }
580  }
581 
582  template<class Settings>
583  void SATModule<Settings>::computeAdvancedLemmas()
584  {
585 #ifdef DEBUG_SATMODULE
586  printCurrentAssignment();
587 #endif
588  SMTRAT_LOG_TRACE("smtrat.sat", "Find all dependent variables");
589  clearLemmas();
590  int assumptionSizeStart = assumptions.size();
591  // Initialize set of all variables which are not tested yet for positive assignment
592  std::set<Minisat::Var> testVarsPositive;
593  Minisat::Var testCandidate;
594  if (getInformationRelevantFormulas().empty())
595  {
596  // If non are selected, all variables are relevant
597  for (BooleanVarMap::const_iterator iterVar = mBooleanVarMap.begin(); iterVar != mBooleanVarMap.end(); ++iterVar)
598  {
599  testVarsPositive.insert(iterVar->second);
600  }
601  }
602  else
603  {
604  for (std::set<FormulaT>::const_iterator iterVar = getInformationRelevantFormulas().begin(); iterVar != getInformationRelevantFormulas().end(); ++iterVar)
605  {
606  testVarsPositive.insert(mBooleanVarMap.at(iterVar->boolean()));
607  }
608  }
609 
610  Minisat::lbool result = l_Undef;
611  while (!testVarsPositive.empty())
612  {
613  for (int pos = 0; pos < assigns.size(); ++pos)
614  {
615  if (assigns[pos] == l_True)
616  {
617  testVarsPositive.erase(pos);
618  }
619  }
620 
621  // Reset the state until level 0
622  cancelUntil(0, true);
623  mPropagatedLemmas.clear();
624 
625  if (testVarsPositive.empty())
626  {
627  break;
628  }
629 
630  // Set new positive assignment
631  // TODO matthias: ignore other variables as "Oxxxx"
632  testCandidate = *testVarsPositive.begin();
633  SMTRAT_LOG_DEBUG("smtrat.sat", "Test candidate: " << mMinisatVarMap.find(testCandidate)->second);
634  Lit nextLit = mkLit(testCandidate, false);
635  assert(assumptions.size() <= assumptionSizeStart + 1);
636  assumptions.shrink(assumptions.size() - assumptionSizeStart);
637  assumptions.push(nextLit);
638 
639  // Check again
640  result = checkFormula();
641  if (result == l_False)
642  {
643  auto mvIter = mMinisatVarMap.find((int)testCandidate);
644  assert( mvIter != mMinisatVarMap.end() );
645  SMTRAT_LOG_DEBUG("smtrat.sat", "Unsat with variable: " << mvIter->second);
646  testVarsPositive.erase(testCandidate);
647  //Construct lemma via infeasible subset
648  updateInfeasibleSubset();
649  FormulaT infeasibleSubset = FormulaT(carl::FormulaType::AND, infeasibleSubsets()[0]);
650  FormulaT lemma = FormulaT(carl::FormulaType::IMPLIES, infeasibleSubset, mvIter->second.negated());
651  SMTRAT_LOG_DEBUG("smtrat.sat", "Add propagated lemma: " << lemma);
652  addLemma(lemma);
653  }
654  else if (result == l_True)
655  {
656  SMTRAT_LOG_DEBUG("smtrat.sat", "Sat with variable: " << mMinisatVarMap.find(testCandidate)->second);
657 #ifdef DEBUG_SATMODULE
658  printCurrentAssignment();
659 #endif
660  }
661  else
662  {
663  SMTRAT_LOG_TRACE("smtrat.sat", "UNKNOWN with variable: " << mMinisatVarMap.find(testCandidate)->second);
664  }
665  }
666  //Clear
667  assumptions.shrink(assumptions.size() - assumptionSizeStart);
668  }
669 
670  template<class Settings>
671  void SATModule<Settings>::updateModel() const
672  {
673  if( !mModelComputed && !mOptimumComputed )
674  {
675  clearModel();
676  if( solverState() != UNSAT || is_minimizing() )
677  {
678  for( BooleanVarMap::const_iterator bVar = mBooleanVarMap.begin(); bVar != mBooleanVarMap.end(); ++bVar )
679  {
680  auto v = static_cast<std::size_t>(bVar->second);
681  if (!mTseitinVariable.test(v)) {
682  ModelValue assignment = assigns[bVar->second] == l_True;
683  mModel.insert(std::make_pair(bVar->first, assignment));
684  }
685  }
686  Module::getBackendsModel();
687  if( Settings::check_if_all_clauses_are_satisfied && trail.size() < assigns.size() )
688  {
689  getDefaultModel( mModel, (FormulaT)rReceivedFormula(), false );
690  }
691  if (Settings::mc_sat) {
692  mModel.update(mMCSAT.model());
693  }
694  }
695  }
696  }
697 
698  template<class Settings>
699  void SATModule<Settings>::updateModel( Model& model, bool only_relevant_variables ) const
700  {
701  model.clear();
702  if( solverState() == SAT )
703  {
704  if ( only_relevant_variables )
705  {
706  // Set assignment for all relevant variables (might be partial assignment)
707  for ( size_t i = 0; i < mRelevantVariables.size(); ++i )
708  {
709  int index = mRelevantVariables[ i ];
710  ModelValue assignment = assigns[ index ] == l_True;
711  auto mvIter = mMinisatVarMap.find(index);
712  assert( mvIter != mMinisatVarMap.end() );
713  carl::Variable var = mvIter->second.boolean();
714  model.insert( std::make_pair( var, assignment ) );
715  }
716  }
717  else
718  {
719  // Set assignment for all defined variables (might be partial assignment)
720  for (BooleanVarMap::const_iterator bVar = mBooleanVarMap.begin(); bVar != mBooleanVarMap.end(); ++bVar)
721  {
722  ModelValue assignment = assigns[bVar->second] == l_True;
723  model.insert(std::make_pair(bVar->first, assignment));
724  }
725  }
726  Module::getBackendsModel();
727  if (Settings::check_if_all_clauses_are_satisfied && trail.size() < assigns.size())
728  {
729  getDefaultModel(model, (FormulaT)rReceivedFormula(), false);
730  }
731  }
732  }
733 
734  template<class Settings>
735  void SATModule<Settings>::updateAllModels()
736  {
737  SMTRAT_LOG_TRACE("smtrat.sat", "Update all models");
738  mComputeAllSAT = true;
739  clearModels();
740  int sizeLearntsStart = learnts.size();
741  if( solverState() == SAT )
742  {
743  // Compute all satisfying assignments
744  SMTRAT_LOG_TRACE("smtrat.sat", "Compute more assignments");
745 
746  // Construct list of all relevant variables
747  mRelevantVariables.clear();
748  if (getInformationRelevantFormulas().empty())
749  {
750  // If non are selected, all variables are relevant
751  for ( BooleanVarMap::const_iterator iterVar = mBooleanVarMap.begin(); iterVar != mBooleanVarMap.end(); ++ iterVar)
752  {
753  mRelevantVariables.push_back( iterVar->second );
754  }
755  }
756  else
757  {
758  for ( std::set<FormulaT>::const_iterator iterVar = getInformationRelevantFormulas().begin(); iterVar != getInformationRelevantFormulas().end(); ++iterVar )
759  {
760  mRelevantVariables.push_back( mBooleanVarMap.at( iterVar->boolean() ) );
761  }
762  }
763  assert( mRelevantVariables.size() > 0);
764  #ifdef DEBUG_SATMODULE
765  std::cout << "Relevant variables: ";
766  for ( std::size_t i = 0; i < mRelevantVariables.size(); ++i )
767  {
768  auto mvIter = mMinisatVarMap.find(mRelevantVariables[ i ]);
769  assert( mvIter != mMinisatVarMap.end() );
770  std::cout << mRelevantVariables[ i ] << " (" << mvIter->second << "), ";
771  }
772  std::cout << std::endl;
773  #endif
774 
775  Minisat::lbool result = l_False;
776  Model model;
777  do
778  {
779  // Compute assignment
780  #ifdef DEBUG_SATMODULE
781  printCurrentAssignment();
782  #endif
783  updateModel( model, true );
784  mAllModels.push_back( model );
785  SMTRAT_LOG_TRACE("smtrat.sat", "Model: " << model);
786  // Exclude assignment
787  vec<Lit> excludeClause;
788  int index;
789  for ( size_t i = 0; i < mRelevantVariables.size(); ++i )
790  {
791  index = mRelevantVariables[ i ];
792  // Add negated literal
793  Lit lit = mkLit( index, assigns[ index ] == l_True);
794  excludeClause.push( lit );
795  }
796  #ifdef DEBUG_SATMODULE
797  std::cout << "Added exclude: " << std::endl;
798  printClause( excludeClause );
799  #endif
800  CRef clause;
801  if( addClause( excludeClause, PERMANENT_CLAUSE ) )
802  clause = learnts.last();
803  else if( excludeClause.size() == 1)
804  break; // already unsat
805  else
806  assert( false );
807  if( !ok || decisionLevel() <= assumptions.size() )
808  {
809  break;
810  }
811  handleConflict( clause );
812 
813  // Check again
814  result = checkFormula();
815  } while( result == l_True );
816  SMTRAT_LOG_TRACE("smtrat.sat", ( result == l_False ? "UnSAT" : "Undef" ));
817  }
818  // Remove clauses for excluded assignments
819  clearLearnts( sizeLearntsStart );
820  mComputeAllSAT = false;
821  cancelUntil(0, true);
822  }
823 
824  template<class Settings>
825  void SATModule<Settings>::updateInfeasibleSubset()
826  {
827  assert( isLemmaLevel(LemmaLevel::ADVANCED) || !ok );
828  mInfeasibleSubsets.clear();
829  // Set the infeasible subset to the set of all clauses.
830  FormulaSetT infeasibleSubset;
831 // if( mpReceivedFormula->is_constraint_conjunction() )
832 // {
833 // getInfeasibleSubsets();
834 // }
835 // else
836 // {
837  // Just add all sub formulas.
838  // TODO: compute a better infeasible subset
839  for( auto subformula = rReceivedFormula().begin(); subformula != rReceivedFormula().end(); ++subformula )
840  {
841  infeasibleSubset.insert( subformula->formula() );
842  }
843 // }
844  mInfeasibleSubsets.push_back( std::move(infeasibleSubset) );
845  }
846 
847  template<class Settings>
848  void SATModule<Settings>::cleanUpAfterOptimizing( const std::vector<CRef>& _excludedAssignments )
849  {
850  mModelComputed = true; // fix the last found model
851  mOptimumComputed = true;
852  removeUpperBoundOnMinimal();
853  mUpperBoundOnMinimal = passedFormulaEnd();
854  // Remove the added clauses for the exclusion of Boolean assignments.
855  for( CRef cl : _excludedAssignments )
856  {
857  removeClause( cl );
858  }
859  }
860 
861  template<class Settings>
862  void SATModule<Settings>::removeUpperBoundOnMinimal()
863  {
864  if( mUpperBoundOnMinimal != passedFormulaEnd() )
865  {
866  FormulaT bound = mUpperBoundOnMinimal->formula();
867  eraseSubformulaFromPassedFormula( mUpperBoundOnMinimal, true );
868  }
869  }
870 
871  template<class Settings>
872  void SATModule<Settings>::addBooleanAssignments( RationalAssignment& _rationalAssignment ) const
873  {
874  for( BooleanVarMap::const_iterator bVar = mBooleanVarMap.begin(); bVar != mBooleanVarMap.end(); ++bVar )
875  {
876  if( assigns[bVar->second] == l_True )
877  {
878  assert( _rationalAssignment.find( bVar->first ) == _rationalAssignment.end() );
879  _rationalAssignment.insert( std::pair< const carl::Variable, Rational >( bVar->first, 1 ) );
880  }
881  else if( assigns[bVar->second] == l_False )
882  {
883  assert( _rationalAssignment.find( bVar->first ) == _rationalAssignment.end() );
884  _rationalAssignment.insert( std::pair< const carl::Variable, Rational >( bVar->first, 0 ) );
885  }
886  }
887  }
888 
889  template<class Settings>
890  void SATModule<Settings>::updateCNFInfoCounter( typename FormulaCNFInfosMap::iterator _iter, const FormulaT& _origin, bool _increment )
891  {
892  assert( _iter != mFormulaCNFInfosMap.end() );
893  if( _increment )
894  ++_iter->second.mCounter;
895  else
896  --_iter->second.mCounter;
897  for( std::size_t pos = 0; pos < _iter->second.mClauses.size(); )
898  {
899  Minisat::CRef cr = _iter->second.mClauses[pos];
900  assert( cr != CRef_Undef );
901  auto ciIter = mClauseInformation.find( cr );
902  assert( ciIter != mClauseInformation.end() );
903  if( _increment )
904  {
905  ciIter->second.addOrigin( _origin );
906  ++pos;
907  }
908  else
909  {
910  ciIter->second.removeOrigin( _origin );
911  // if the counter becomes zero, remove the clause
912  if( _iter->second.mCounter == 0 )
913  {
914  // remove this clause and each information we stored for it
915  assert( ciIter->second.mOrigins.size() == 0 );
916  vec<CRef>& cls = ciIter->second.mStoredInSatisfied ? satisfiedClauses : clauses;
917  if( ciIter->second.mPosition < cls.size() - 1 )
918  {
919  cls[ciIter->second.mPosition] = cls.last();
920  auto ciIterB = mClauseInformation.find( cls[ciIter->second.mPosition] );
921  assert( ciIterB != mClauseInformation.end() );
922  ciIterB->second.mPosition = ciIter->second.mPosition;
923  cls.pop();
924  }
925  else
926  {
927  cls.pop();
928  }
929  mClauseInformation.erase( ciIter );
930  if( Settings::check_if_all_clauses_are_satisfied )
931  {
932  const Clause& c = ca[cr];
933  for( int i = 0; i < c.size(); ++i )
934  mLiteralClausesMap[Minisat::toInt(c[i])].erase( cr );
935  }
936  removeClause( cr );
937  if( pos < _iter->second.mClauses.size() - 1 )
938  _iter->second.mClauses[pos] = _iter->second.mClauses.back();
939  _iter->second.mClauses.pop_back();
940  }
941  else
942  ++pos;
943  }
944  }
945  // Invoke this procedure recursively on all sub-formulas, which again contain sub-formulas
946  if( _iter->first.is_nary() )
947  {
948  for( const FormulaT& formula : _iter->first.subformulas() )
949  {
950  if( formula.is_nary() )
951  {
952  auto cnfInfoIter = mFormulaCNFInfosMap.find( formula.remove_negations() );
953  if( cnfInfoIter != mFormulaCNFInfosMap.end() )
954  {
955  updateCNFInfoCounter( cnfInfoIter, _origin, _increment );
956  if( !_increment && cnfInfoIter->second.mClauses.empty() )
957  {
958  mFormulaCNFInfosMap.erase( cnfInfoIter );
959  }
960  }
961  }
962  }
963  }
964  }
965 
966  template<class Settings>
967  Lit SATModule<Settings>::addClauses( const FormulaT& _formula, unsigned _type, unsigned _depth, const FormulaT& _original )
968  {
969  SMTRAT_LOG_DEBUG("smtrat.sat", "Adding formula " << _formula);
970  assert( _type < 4 );
971  bool everythingDecisionRelevant = !Settings::formula_guided_decision_heuristic;
972  unsigned nextDepth = _depth+1;
973  switch( _formula.type() )
974  {
975  case carl::FormulaType::TRUE:
976  case carl::FormulaType::FALSE:
977  assert( false );
978  break;
979  case carl::FormulaType::BOOL:
980  case carl::FormulaType::UEQ:
981  case carl::FormulaType::CONSTRAINT:
982  case carl::FormulaType::VARCOMPARE:
983  case carl::FormulaType::VARASSIGN:
984  case carl::FormulaType::BITVECTOR:
985  return createLiteral( _formula, _original, everythingDecisionRelevant || _depth <= 1 );
986  case carl::FormulaType::NOT:
987  {
988  SMTRAT_LOG_TRACE("smtrat.sat", "Adding a negation: " << _formula);
989  Lit l = lit_Undef;
990  if( _formula.is_literal() )
991  {
992  l = createLiteral( _formula, _original, everythingDecisionRelevant || _depth <= 1 );
993  SMTRAT_LOG_TRACE("smtrat.sat", "It is a literal: " << l);
994  }
995  else {
996  l = neg( addClauses( _formula.subformula(), _type, nextDepth, _original ) );
997  SMTRAT_LOG_TRACE("smtrat.sat", "It is not a literal, but now: " << l);
998  }
999  if( _depth == 0 )
1000  {
1001  SMTRAT_LOG_DEBUG("smtrat.sat", "Depth is zero");
1002  vec<Lit> c;
1003  c.push(l);
1004  addClause(c, LEMMA_CLAUSE);
1005  //assumptions.push( l );
1006  //assert( mFormulaAssumptionMap.find( _formula ) == mFormulaAssumptionMap.end() );
1007  //mFormulaAssumptionMap.emplace( _formula, assumptions.last() );
1008  return lit_Undef;
1009  }
1010  return l;
1011  }
1012  default:
1013  {
1014  auto cnfInfoIter = mFormulaCNFInfosMap.end();
1015  if( _type == NORMAL_CLAUSE )
1016  {
1017  cnfInfoIter = mFormulaCNFInfosMap.find( _formula );
1018  if( cnfInfoIter != mFormulaCNFInfosMap.end() )
1019  {
1020  updateCNFInfoCounter( cnfInfoIter, _original, true );
1021  SMTRAT_LOG_DEBUG("smtrat.sat", "Recovered literal for " << _original << ": " << cnfInfoIter->second.mLiteral);
1022  Lit l = cnfInfoIter->second.mLiteral;
1023  // If it was not assumed yet
1024  if (!mAssumedTseitinVariable.test(std::size_t(var(l)))) {
1025  SMTRAT_LOG_DEBUG("smtrat.sat", _original << " is not assumed yet");
1026  // If we have a top-level clause right now and it is already used somewhere else
1027  // Or there already was a top-level clause but it is not assumed yet
1028  if (
1029  (_depth == 0 && cnfInfoIter->second.mCounter > 1) ||
1030  mNonassumedTseitinVariable.test(std::size_t(var(l)))
1031  ) {
1032  SMTRAT_LOG_DEBUG("smtrat.sat", _original << " should be assumed, adding it to assumptions");
1033  /*
1034  * If this literal is a tseitin variable, it may belong to a top-level clause.
1035  * In this case, it is not eagerly added to the assumptions but only lazily when it is actually reused.
1036  * This is the case now. We backtrack to DL0 (+ assumptions.size()) and add it to the assumptions now.
1037  * This can only happen if a formula is added with some boolean structure, as only then the tseitin variable will be used.
1038  * Examples are addCore() or a lemma from a backend, in these cases it is safe to reset.
1039  * In particular this can not happen for infeasible subsets or conflict clauses, where a reset might not be safe.
1040  */
1041  cancelUntil(assumptions.size());
1042  assumptions.push(l);
1043  assert(mFormulaAssumptionMap.find(_formula) == mFormulaAssumptionMap.end());
1044  mFormulaAssumptionMap.emplace(_formula, assumptions.last());
1045  mNonassumedTseitinVariable.reset(std::size_t(var(l)));
1046  mAssumedTseitinVariable.set(std::size_t(var(l)));
1047  }
1048  }
1049  return l;
1050  }
1051  cnfInfoIter = mFormulaCNFInfosMap.emplace( _formula, CNFInfos() ).first;
1052  }
1053  vec<Lit> lits;
1054  FormulaT tsVar = carl::FormulaPool<Poly>::getInstance().createTseitinVar( _formula );
1055  Lit tsLit = createLiteral( tsVar, _original, everythingDecisionRelevant || _depth <= 1 );
1056  mTseitinVariable.set(static_cast<std::size_t>(var(tsLit)));
1057  if( _type == NORMAL_CLAUSE )
1058  cnfInfoIter->second.mLiteral = tsLit;
1059  switch( _formula.type() )
1060  {
1061  case carl::FormulaType::ITE:
1062  {
1063  Lit condLit = addClauses( _formula.condition(), _type, nextDepth, _original );
1064  Lit negCondLit = _formula.condition().is_literal() ? addClauses( _formula.condition().negated(), _type, nextDepth, _original ) : neg( condLit );
1065  Lit thenLit = addClauses( _formula.first_case(), _type, nextDepth, _original );
1066  Lit elseLit = addClauses( _formula.second_case(), _type, nextDepth, _original );
1067  if( _depth == 0 )
1068  {
1069  // (or -cond then)
1070  lits.push( negCondLit ); lits.push( thenLit ); addClause_( lits, _type, _original, cnfInfoIter );
1071  // (or cond else)
1072  lits.clear(); lits.push( condLit ); lits.push( elseLit ); addClause_( lits, _type, _original, cnfInfoIter );
1073  return lit_Undef;
1074  }
1075  Lit negThenLit = _formula.first_case().is_literal() ? addClauses( _formula.first_case().negated(), _type, nextDepth, _original ) : neg( thenLit );
1076  Lit negElseLit = _formula.second_case().is_literal() ? addClauses( _formula.second_case().negated(), _type, nextDepth, _original ) : neg( elseLit );
1077  if( !mReceivedFormulaPurelyPropositional && Settings::initiate_activities )
1078  {
1079  mTseitinVarFormulaMap.emplace( (int)var(tsLit), _formula );
1080  }
1081  if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
1082  {
1083  mTseitinVarShadows.emplace( (signed)var(tsLit), std::vector<signed>{ (signed)var(condLit), (signed)var(thenLit), (signed)var(elseLit)} );
1084  }
1085  // (or ts -cond -then)
1086  lits.push( tsLit ); lits.push( negCondLit ); lits.push( negThenLit ); addClause_( lits, _type, _original, cnfInfoIter );
1087  // (or ts cond -else)
1088  lits.clear(); lits.push( tsLit ); lits.push( condLit ); lits.push( negElseLit ); addClause_( lits, _type, _original, cnfInfoIter );
1089  // (or -ts -cond then)
1090  lits.clear(); lits.push( neg( tsLit ) ); lits.push( negCondLit ); lits.push( thenLit ); addClause_( lits, _type, _original, cnfInfoIter );
1091  // (or -ts cond else)
1092  lits.clear(); lits.push( neg( tsLit ) ); lits.push( condLit ); lits.push( elseLit ); addClause_( lits, _type, _original, cnfInfoIter );
1093 
1094  return tsLit;
1095  }
1096  case carl::FormulaType::IMPLIES:
1097  {
1098  Lit premLit = addClauses( _formula.premise(), _type, nextDepth, _original );
1099  Lit negPremLit = _formula.premise().is_literal() ? addClauses( _formula.premise().negated(), _type, nextDepth, _original ) : neg( premLit );
1100  Lit conLit = addClauses( _formula.conclusion(), _type, nextDepth, _original );
1101  if( _depth == 0 )
1102  {
1103  // (or -premise conclusion)
1104  lits.push( neg( premLit ) ); lits.push( conLit ); addClause_( lits, _type, _original, cnfInfoIter );
1105  return lit_Undef;
1106  }
1107  Lit negConLit = _formula.conclusion().is_literal() ? addClauses( _formula.conclusion().negated(), _type, nextDepth, _original ) : neg( conLit );
1108  if( !mReceivedFormulaPurelyPropositional && Settings::initiate_activities )
1109  {
1110  mTseitinVarFormulaMap.emplace( (int)var(tsLit), _formula );
1111  }
1112  if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
1113  {
1114  mTseitinVarShadows.emplace( (signed)var(tsLit), std::vector<signed>{ (signed)var(premLit), (signed)var(conLit)} );
1115  }
1116  // (or -ts -prem con)
1117  lits.push( neg( tsLit ) ); lits.push( negPremLit ); lits.push( conLit ); addClause_( lits, _type, _original, cnfInfoIter );
1118  // (or ts prem)
1119  lits.clear(); lits.push( tsLit ); lits.push( premLit ); addClause_( lits, _type, _original, cnfInfoIter );
1120  // (or ts -con)
1121  lits.clear(); lits.push( tsLit ); lits.push( negConLit ); addClause_( lits, _type, _original, cnfInfoIter );
1122  return tsLit;
1123  }
1124  case carl::FormulaType::OR:
1125  {
1126  for( const auto& sf : _formula.subformulas() )
1127  lits.push( addClauses( sf, _type, nextDepth, _original ) );
1128  if( _depth == 0 )
1129  {
1130  /*
1131  * This is a top-level clause. The full tseitin encoding would be:
1132  * ts and (or -ts a1 ... an) and (or ts -a1) ... (or ts -an)
1133  * However ts will become an assumption and thus -ts can be skipped and (or ts -ak) is satisfied anyway.
1134  * We therefore only add (or a1 .. an).
1135  * However if the formula is reused in a nested formula somewhere else, we need ts to be forced to true.
1136  * To avoid work (and because always doing that induces problems when adding infeasible subsets) we do this lazily.
1137  * We add ts to mNonassumedTseitinVariable and only add it to the assumptions when it is actually reused in another formula.
1138  */
1139  if (_type == NORMAL_CLAUSE) {
1140  SMTRAT_LOG_DEBUG("smtrat.sat", "top-level clause has new tseitin literal " << tsLit << ", marking it as non-assumed");
1141  assert(!mAssumedTseitinVariable.test(std::size_t(var(tsLit))));
1142  assert(cnfInfoIter->second.mCounter == 1);
1143  mNonassumedTseitinVariable.set(std::size_t(var(tsLit)));
1144  }
1145  addClause_( lits, _type, _original, cnfInfoIter );
1146  return lit_Undef;
1147  }
1148  if( !mReceivedFormulaPurelyPropositional && Settings::initiate_activities )
1149  {
1150  mTseitinVarFormulaMap.emplace( (int)var(tsLit), _formula );
1151  }
1152  if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
1153  {
1154  std::vector<signed> vars;
1155  for( int pos = 0; pos < lits.size(); ++pos )
1156  vars.push_back( (signed)var(lits[pos]) );
1157  mTseitinVarShadows.emplace( (signed)var(tsLit), std::move(vars) );
1158  }
1159  // (or -ts a1 .. an)
1160  lits.push( neg( tsLit ) );
1161  addClause_( lits, _type, _original, cnfInfoIter );
1162  // Only add on deeper levels, otherwise ts is an assumption and the clauses are immediately satisfied anyway.
1163  if (_depth != 0) {
1164  // (or ts -a1) .. (or ts -an)
1165  vec<Lit> litsTmp;
1166  litsTmp.push( tsLit );
1167  int i = 0;
1168  for( const auto& sf : _formula.subformulas() )
1169  {
1170  assert( i < lits.size() );
1171  litsTmp.push( sf.is_literal() ? addClauses( sf.negated(), _type, nextDepth, _original ) : neg( lits[i] ) );
1172  addClause_( litsTmp, _type, _original, cnfInfoIter );
1173  litsTmp.pop();
1174  ++i;
1175  }
1176  }
1177  SMTRAT_LOG_DEBUG("smtrat.sat", "Added formula " << _formula << " -> " << tsLit);
1178  return tsLit;
1179  }
1180  case carl::FormulaType::AND:
1181  {
1182  assert( _depth != 0 ); // because, this should be split in the module input
1183  if( !mReceivedFormulaPurelyPropositional && Settings::initiate_activities )
1184  {
1185  mTseitinVarFormulaMap.emplace( (int)var(tsLit), _formula );
1186  }
1187  // (or -ts a1) .. (or -ts an)
1188  // (or ts -a1 .. -an)
1189  vec<Lit> litsTmp;
1190  litsTmp.push( neg( tsLit ) );
1191  for( const auto& sf : _formula.subformulas() )
1192  {
1193  Lit l = addClauses( sf, _type, nextDepth, _original );
1194  assert( l != lit_Undef );
1195  litsTmp.push( l );
1196  addClause_( litsTmp, _type, _original, cnfInfoIter );
1197  litsTmp.pop();
1198  Lit negL = sf.is_literal() ? addClauses( sf.negated(), _type, nextDepth, _original ) : neg( l );
1199  lits.push( negL );
1200  }
1201  if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
1202  {
1203  std::vector<signed> vars;
1204  for( int pos = 0; pos < lits.size(); ++pos )
1205  vars.push_back( (signed)var(lits[pos]) );
1206  mTseitinVarShadows.emplace( (signed)var(tsLit), std::move(vars) );
1207  }
1208  lits.push( tsLit );
1209  addClause_( lits, _type, _original, cnfInfoIter );
1210  if( _type == NORMAL_CLAUSE )
1211  cnfInfoIter->second.mLiteral = tsLit;
1212  return tsLit;
1213  }
1214  case carl::FormulaType::IFF:
1215  {
1216  vec<Lit> tmp;
1217  if( _depth == 0 )
1218  {
1219  auto sfIter = _formula.subformulas().begin();
1220  Lit l = addClauses( *sfIter, _type, nextDepth, _original );
1221  Lit negL = sfIter->is_literal() ? addClauses( sfIter->negated(), _type, nextDepth, _original ) : neg( l );
1222  ++sfIter;
1223  for( ; sfIter != _formula.subformulas().end(); ++sfIter )
1224  {
1225  Lit k = addClauses( *sfIter, _type, nextDepth, _original );
1226  Lit negK = sfIter->is_literal() ? addClauses( sfIter->negated(), _type, nextDepth, _original ) : neg( k );
1227  // (or -l k)
1228  tmp.clear(); tmp.push( negL ); tmp.push( k ); addClause_( tmp, _type, _original, cnfInfoIter );
1229  // (or l -k)
1230  tmp.clear(); tmp.push( l ); tmp.push( negK ); addClause_( tmp, _type, _original, cnfInfoIter );
1231  l = k;
1232  negL = negK;
1233  }
1234  return lit_Undef;
1235  }
1236  for( const auto& sf : _formula.subformulas() )
1237  {
1238  Lit l = addClauses( sf, _type, nextDepth, _original );
1239  Lit negL = sf.is_literal() ? addClauses( sf.negated(), _type, nextDepth, _original ) : neg( l );
1240  lits.push( l );
1241  tmp.push( negL );
1242  }
1243  if( !mReceivedFormulaPurelyPropositional && Settings::initiate_activities )
1244  {
1245  mTseitinVarFormulaMap.emplace( (int)var(tsLit), _formula );
1246  }
1247  if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
1248  {
1249  std::vector<signed> vars;
1250  for( int pos = 0; pos < lits.size(); ++pos )
1251  vars.push_back( (signed)var(lits[pos]) );
1252  mTseitinVarShadows.emplace( (signed)var(tsLit), std::move(vars) );
1253  }
1254  // (or a1 .. an h)
1255  lits.push( tsLit ); addClause_( lits, _type, _original, cnfInfoIter );
1256  lits.pop();
1257  // (or -a1 .. -an h)
1258  tmp.push( tsLit ); addClause_( tmp, _type, _original, cnfInfoIter );
1259  // (or -a1 a2 -h) (or a1 -a2 -h) .. (or -a{n-1} an -h) (or a{n-1} -an -h)
1260  vec<Lit> tmpB;
1261  for( int i = 1; i < lits.size(); ++i )
1262  {
1263  tmpB.clear(); tmpB.push( tmp[i-1] ); tmpB.push( lits[i] ); tmpB.push( neg( tsLit ) ); addClause_( tmpB, _type, _original, cnfInfoIter );
1264  tmpB.clear(); tmpB.push( lits[i-1] ); tmpB.push( tmp[i] ); tmpB.push( neg( tsLit ) ); addClause_( tmpB, _type, _original, cnfInfoIter );
1265  }
1266  return tsLit;
1267  }
1268  case carl::FormulaType::XOR:
1269  {
1270  vec<Lit> negLits;
1271  vec<Lit> tmp;
1272  for( const auto& sf : _formula.subformulas() )
1273  {
1274  lits.push( addClauses( sf, _type, nextDepth, _original ) );
1275  negLits.push( sf.is_literal() ? addClauses( sf.negated(), _type, nextDepth, _original ) : neg( lits.last() ) );
1276  }
1277  if( _type == NORMAL_CLAUSE )
1278  cnfInfoIter->second.mLiteral = tsLit;
1279  if( _depth == 0 )
1280  {
1281  addXorClauses( lits, negLits, 0, true, _type, tmp, _original, cnfInfoIter );
1282  return lit_Undef;
1283  }
1284  if( !mReceivedFormulaPurelyPropositional && Settings::initiate_activities )
1285  {
1286  mTseitinVarFormulaMap.emplace( (int)var(tsLit), _formula );
1287  }
1288  if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
1289  {
1290  std::vector<signed> vars;
1291  for( int pos = 0; pos < lits.size(); ++pos )
1292  vars.push_back( (signed)var(lits[pos]) );
1293  mTseitinVarShadows.emplace( (signed)var(tsLit), std::move(vars) );
1294  }
1295  lits.push( neg( tsLit ) );
1296  negLits.push( tsLit );
1297  addXorClauses( lits, negLits, 0, true, _type, tmp, _original, cnfInfoIter );
1298  return tsLit;
1299  }
1300  case carl::FormulaType::EXISTS:
1301  case carl::FormulaType::FORALL:
1302  assert( false );
1303  std::cerr << "Formula must be quantifier-free!" << std::endl;
1304  break;
1305  default:
1306  SMTRAT_LOG_ERROR("smtrat.sat", "Unexpected formula type " << _formula.type());
1307  SMTRAT_LOG_ERROR("smtrat.sat", _formula);
1308  assert( false );
1309  }
1310  }
1311  }
1312  return lit_Undef;
1313  }
1314 
1315  template<class Settings>
1316  void SATModule<Settings>::addXorClauses( const vec<Lit>& _literals, const vec<Lit>& _negLiterals, int _from, bool _numOfNegatedLitsEven, unsigned _type, vec<Lit>& _clause, const FormulaT& _original, typename FormulaCNFInfosMap::iterator _formulaCNFInfoIter )
1317  {
1318  if( _from == _literals.size() - 1 )
1319  {
1320  _clause.push( _numOfNegatedLitsEven ? _literals[_from] : _negLiterals[_from] );
1321  addClause_( _clause, _type, _original, _formulaCNFInfoIter );
1322  _clause.pop();
1323  }
1324  else
1325  {
1326  _clause.push( _literals[_from] );
1327  addXorClauses( _literals, _negLiterals, _from+1, _numOfNegatedLitsEven, _type, _clause, _original, _formulaCNFInfoIter );
1328  _clause.pop();
1329  _clause.push( _negLiterals[_from] );
1330  addXorClauses( _literals, _negLiterals, _from+1, !_numOfNegatedLitsEven, _type, _clause, _original, _formulaCNFInfoIter );
1331  _clause.pop();
1332  }
1333  }
1334 
1335  template<class Settings>
1336  Lit SATModule<Settings>::createLiteral( const FormulaT& _formula, const FormulaT& _origin, bool _decisionRelevant )
1337  {
1338  //SMTRAT_LOG_DEBUG("smtrat.sat", "Creating literal for " << _formula << " with origin " << _origin << ", decisionRelevant = " << _decisionRelevant);
1339  assert( _formula.property_holds( carl::PROP_IS_A_LITERAL ) );
1340  FormulaT content = _formula.base_formula();
1341  bool negated = (content != _formula);
1342  if( content.type() == carl::FormulaType::BOOL )
1343  {
1344  Lit l = lit_Undef;
1345  BooleanVarMap::iterator booleanVarPair = mBooleanVarMap.find(content.boolean());
1346  if( booleanVarPair != mBooleanVarMap.end() )
1347  {
1348  if( _decisionRelevant ) {
1349  if (Settings::mc_sat) {
1350  setDecisionVar( booleanVarPair->second, _decisionRelevant, content.type() != carl::FormulaType::VARASSIGN );
1351  } else {
1352  setDecisionVar( booleanVarPair->second, _decisionRelevant );
1353  }
1354  }
1355 
1356  l = mkLit( booleanVarPair->second, negated );
1357  }
1358  else
1359  {
1360  Var var = newVar( true, _decisionRelevant, content.activity(), !Settings::mc_sat );
1361  mBooleanVarMap[content.boolean()] = var;
1362  mMinisatVarMap.emplace((int)var,content);
1363  mBooleanConstraintMap.push( std::make_pair( nullptr, nullptr ) );
1364  if (Settings::mc_sat) {
1365  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Adding " << var << " that abstracts " << content << " having type " << content.type());
1366  if (content.type() != carl::FormulaType::VARASSIGN) {
1367  mMCSAT.addBooleanVariable(var);
1368  insertVarOrder(var);
1369  }
1370  }
1371  l = mkLit( var, negated );
1372  }
1373  return l;
1374  }
1375  else
1376  {
1377  SMTRAT_LOG_TRACE("smtrat.sat", "Looking for constraint " << content);
1378  assert( supportedConstraintType( content ) );
1379  double act = fabs( _formula.activity() );
1380  bool preferredToTSolver = false; //(_formula.content()<0)
1381  SMTRAT_LOG_TRACE("smtrat.sat", "Looking for " << _formula << " in " << mConstraintLiteralMap);
1382  auto constraintLiteralPair = mConstraintLiteralMap.find( _formula );
1383  if( constraintLiteralPair != mConstraintLiteralMap.end() )
1384  {
1385  SMTRAT_LOG_TRACE("smtrat.sat", "Constraint " << content << " already exists");
1386  // Check whether the theory solver wants this literal to assigned as soon as possible.
1387  int abstractionVar = var(constraintLiteralPair->second.front());
1388  if( act == std::numeric_limits<double>::infinity() )
1389  {
1390  activity[abstractionVar] = maxActivity() + 1;
1391  polarity[abstractionVar] = false;
1392  }
1393  if( _decisionRelevant ) {
1394  if (Settings::mc_sat) {
1395  setDecisionVar( abstractionVar, _decisionRelevant, content.type() != carl::FormulaType::VARASSIGN );
1396  } else {
1397  setDecisionVar( abstractionVar, _decisionRelevant );
1398  }
1399  }
1400  // add the origin
1401  auto& abstrPair = mBooleanConstraintMap[abstractionVar];
1402  assert( abstrPair.first != nullptr && abstrPair.second != nullptr );
1403  Abstraction& abstr = sign(constraintLiteralPair->second.front()) ? *abstrPair.second : *abstrPair.first;
1404  if( !_origin.is_true() || !negated )
1405  {
1406  if( !abstr.consistencyRelevant )
1407  {
1408  addConstraintToInform_( abstr.reabstraction );
1409  if( (sign(constraintLiteralPair->second.front()) && assigns[abstractionVar] == l_False)
1410  || (!sign(constraintLiteralPair->second.front()) && assigns[abstractionVar] == l_True) )
1411  {
1412  if( ++abstr.updateInfo > 0 )
1413  mChangedBooleans.push_back( abstractionVar );
1414  }
1415  abstr.consistencyRelevant = true;
1416  }
1417  if( !_origin.is_true() )
1418  {
1419  if( abstr.origins == nullptr )
1420  {
1421  abstr.origins = std::shared_ptr<std::vector<FormulaT>>( new std::vector<FormulaT>() );
1422  }
1423  abstr.origins->push_back( _origin );
1424  }
1425  }
1426  SMTRAT_LOG_DEBUG("smtrat.sat", _formula << " -> " << constraintLiteralPair->second.front());
1427  return constraintLiteralPair->second.front();
1428  }
1429  else
1430  {
1431  SMTRAT_LOG_TRACE("smtrat.sat", "Constraint " << content << " does not exist yet");
1432  // Add a fresh Boolean variable as an abstraction of the constraint.
1433  #ifdef SMTRAT_DEVOPTION_Statistics
1434  if( preferredToTSolver ) mStatistics.initialTrue();
1435  #endif
1436  FormulaT constraint = content;
1437  FormulaT invertedConstraint = content.negated();
1438  assert(constraint.type() != carl::FormulaType::NOT);
1439  assert(invertedConstraint.type() != carl::FormulaType::NOT);
1440  SMTRAT_LOG_TRACE("smtrat.sat", "Adding " << constraint << " / " << invertedConstraint << ", negated? " << negated);
1441 
1442  // Note: insertVarOrder cannot be called inside newVar, as some orderings may depend on the abstracted constraint (ugly hack)
1443  Var constraintAbstraction = newVar( !preferredToTSolver, _decisionRelevant, act, !Settings::mc_sat );
1444  // map the abstraction variable to the abstraction information for the constraint and it's negation
1445  mBooleanConstraintMap.push( std::make_pair( new Abstraction( passedFormulaEnd(), constraint ), new Abstraction( passedFormulaEnd(), invertedConstraint ) ) );
1446  if (Settings::mc_sat) {
1447  SMTRAT_LOG_TRACE("smtrat.sat.mcsat", "Adding " << constraintAbstraction << " that abstracts " << content << " having type " << content.type());
1448  if (content.type() != carl::FormulaType::VARASSIGN) {
1449  mMCSAT.addBooleanVariable(constraintAbstraction);
1450  insertVarOrder(constraintAbstraction);
1451  }
1452  }
1453  // add the constraint and its negation to the constraints to inform backends about
1454  if( !_origin.is_true() )
1455  {
1456  assert( mBooleanConstraintMap.last().first != nullptr && mBooleanConstraintMap.last().second != nullptr );
1457  Abstraction& abstr = negated ? *mBooleanConstraintMap.last().second : *mBooleanConstraintMap.last().first;
1458  if( abstr.origins == nullptr )
1459  {
1460  abstr.origins = std::shared_ptr<std::vector<FormulaT>>( new std::vector<FormulaT>() );
1461  }
1462  if( negated )
1463  {
1464  abstr.origins->push_back( _origin );
1465  abstr.consistencyRelevant = true;
1466  addConstraintToInform_( invertedConstraint );
1467  }
1468  else
1469  {
1470  abstr.origins->push_back( _origin );
1471  abstr.consistencyRelevant = true;
1472  addConstraintToInform_( constraint );
1473  }
1474  }
1475  else
1476  {
1477  assert( mBooleanConstraintMap.last().first != nullptr );
1478  mBooleanConstraintMap.last().first->consistencyRelevant = true;
1479  addConstraintToInform_( constraint );
1480  assert( mBooleanConstraintMap.last().second != nullptr );
1481  mBooleanConstraintMap.last().second->consistencyRelevant = true;
1482  addConstraintToInform_( invertedConstraint );
1483  }
1484  // create a literal for the constraint and its negation
1485  assert(FormulaT( carl::FormulaType::NOT, invertedConstraint ) == constraint);
1486  assert((negated ? _formula : FormulaT( carl::FormulaType::NOT, constraint )) == invertedConstraint);
1487  Lit litPositive = mkLit( constraintAbstraction, false );
1488  std::vector<Lit> litsA;
1489  litsA.push_back( litPositive );
1490  mConstraintLiteralMap.insert( std::make_pair( FormulaT( carl::FormulaType::NOT, invertedConstraint ), litsA ) );
1491  mConstraintLiteralMap.insert( std::make_pair( constraint, std::move( litsA ) ) );
1492  Lit litNegative = mkLit( constraintAbstraction, true );
1493  std::vector<Lit> litsB;
1494  litsB.push_back( litNegative );
1495  mConstraintLiteralMap.insert( std::make_pair( negated ? _formula : FormulaT( carl::FormulaType::NOT, constraint ), litsB ) );
1496  mConstraintLiteralMap.insert( std::make_pair( invertedConstraint, std::move( litsB ) ) );
1497  // we return the abstraction variable as literal, if the negated flag was negative,
1498  // otherwise we return the abstraction variable's negation
1499  Lit res = negated ? litNegative : litPositive;
1500  return res;
1501  }
1502  }
1503  }
1504 
1505  template<class Settings>
1506  Lit SATModule<Settings>::getLiteral( const FormulaT& _formula ) const
1507  {
1508  bool negated = _formula.type() == carl::FormulaType::NOT;
1509  const FormulaT& content = negated ? _formula.subformula() : _formula;
1510  if( content.type() == carl::FormulaType::BOOL )
1511  {
1512  BooleanVarMap::const_iterator booleanVarPair = mBooleanVarMap.find(content.boolean());
1513  assert( booleanVarPair != mBooleanVarMap.end() );
1514  return mkLit( booleanVarPair->second, negated );
1515  }
1516  assert( supportedConstraintType( content ) );
1517  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Literals: " << mConstraintLiteralMap);
1518  ConstraintLiteralsMap::const_iterator constraintLiteralPair = mConstraintLiteralMap.find( content );
1519  assert( constraintLiteralPair != mConstraintLiteralMap.end() );
1520  return negated ? neg( constraintLiteralPair->second.front() ) : constraintLiteralPair->second.front();
1521  }
1522 
1523  template<class Settings>
1524  void SATModule<Settings>::adaptPassedFormula()
1525  {
1526  SMTRAT_LOG_TRACE("smtrat.sat", "...");
1527  // Adapt the constraints in the passed formula for the just assigned Booleans being abstractions of constraints.
1528  for( signed posInAssigns : mChangedBooleans )
1529  {
1530  assert( mBooleanConstraintMap[posInAssigns].first != nullptr && mBooleanConstraintMap[posInAssigns].second != nullptr );
1531  adaptPassedFormula( *mBooleanConstraintMap[posInAssigns].first );
1532  adaptPassedFormula( *mBooleanConstraintMap[posInAssigns].second );
1533  }
1534  mChangedBooleans.clear();
1535  // Update the activities of the constraints in the passed formula according to the activity of the SAT solving process.
1536  if( mAllActivitiesChanged )
1537  {
1538  for( int i = 0; i < mBooleanConstraintMap.size(); ++i )
1539  {
1540  if( mBooleanConstraintMap[i].first != nullptr )
1541  {
1542  assert( mBooleanConstraintMap[i].second != nullptr );
1543  auto posInPasForm = mBooleanConstraintMap[i].first->position;
1544  if( posInPasForm != rPassedFormula().end() )
1545  posInPasForm->formula().set_activity(activity[i]);
1546  posInPasForm = mBooleanConstraintMap[i].second->position;
1547  if( posInPasForm != rPassedFormula().end() )
1548  posInPasForm->formula().set_activity(activity[i]);
1549  }
1550  }
1551  mAllActivitiesChanged = false;
1552  }
1553  else
1554  {
1555  for( signed v : mChangedActivities )
1556  {
1557  if( mBooleanConstraintMap[v].first != nullptr )
1558  {
1559  assert( mBooleanConstraintMap[v].second != nullptr );
1560  auto posInPasForm = mBooleanConstraintMap[v].first->position;
1561  if( posInPasForm != rPassedFormula().end() )
1562  posInPasForm->formula().set_activity(activity[v]);
1563  posInPasForm = mBooleanConstraintMap[v].second->position;
1564  if( posInPasForm != rPassedFormula().end() )
1565  posInPasForm->formula().set_activity(activity[v]);
1566  }
1567  }
1568  }
1569  mChangedActivities.clear();
1570  if( mChangedPassedFormula )
1571  {
1572  mCurrentAssignmentConsistent = SAT;
1573  }
1574 // assert( passedFormulaCorrect() );
1575  }
1576 
1577  template<class Settings>
1578  void SATModule<Settings>::adaptPassedFormula( Abstraction& _abstr )
1579  {
1580  if( _abstr.updatedReabstraction || _abstr.updateInfo < 0 )
1581  {
1582  SMTRAT_LOG_DEBUG("smtrat.sat", "Removing " << _abstr.reabstraction);
1583  assert( !_abstr.reabstraction.is_true() );
1584  if( _abstr.position != rPassedFormula().end() )
1585  {
1586  removeOrigins( _abstr.position, _abstr.origins );
1587  _abstr.position = passedFormulaEnd();
1588  mChangedPassedFormula = true;
1589  }
1590  }
1591  if( _abstr.updatedReabstraction || _abstr.updateInfo > 0 )
1592  {
1593  SMTRAT_LOG_DEBUG("smtrat.sat", "Adding " << _abstr.reabstraction);
1594  assert( !_abstr.reabstraction.is_true() );
1595  assert(
1596  _abstr.reabstraction.type() == carl::FormulaType::UEQ ||
1597  _abstr.reabstraction.type() == carl::FormulaType::BITVECTOR ||
1598  (_abstr.reabstraction.type() == carl::FormulaType::CONSTRAINT && _abstr.reabstraction.constraint().is_consistent() == 2) ||
1599  _abstr.reabstraction.type() == carl::FormulaType::VARCOMPARE ||
1600  _abstr.reabstraction.type() == carl::FormulaType::VARASSIGN
1601  );
1602  auto res = addSubformulaToPassedFormula( _abstr.reabstraction, _abstr.origins );
1603  _abstr.position = res.first;
1604  _abstr.position->setDeducted( _abstr.isDeduction );
1605  mChangedPassedFormula = true;
1606  }
1607  _abstr.updateInfo = 0;
1608  _abstr.updatedReabstraction = false;
1609  }
1610 
1611  template<class Settings>
1612  bool SATModule<Settings>::passedFormulaCorrect() const
1613  {
1614  for( int k = 0; k < mBooleanConstraintMap.size(); ++k )
1615  {
1616  if( assigns[k] != l_Undef )
1617  {
1618  if( mBooleanConstraintMap[k].first != nullptr )
1619  {
1620  assert( mBooleanConstraintMap[k].second != nullptr );
1621  const Abstraction& abstr = assigns[k] == l_False ? *mBooleanConstraintMap[k].second : *mBooleanConstraintMap[k].first;
1622  if( !abstr.reabstraction.is_true() && abstr.consistencyRelevant && (abstr.reabstraction.type() == carl::FormulaType::UEQ || abstr.reabstraction.type() == carl::FormulaType::BITVECTOR || abstr.reabstraction.constraint().is_consistent() != 1))
1623  {
1624  if( !rPassedFormula().contains( abstr.reabstraction ) )
1625  {
1626 // std::cout << "does not contain " << abstr.reabstraction << std::endl;
1627  return false;
1628  }
1629  }
1630  }
1631  }
1632  }
1633  for( auto subformula = rPassedFormula().begin(); subformula != rPassedFormula().end(); ++subformula )
1634  {
1635  if( value( getLiteral( subformula->formula() ) ) != l_True )
1636  {
1637 // std::cout << "should not contain " << iter->first << std::endl;
1638  return false;
1639  }
1640  }
1641  return true;
1642  }
1643 
1644  template<class Settings>
1645  Var SATModule<Settings>::newVar( bool sign, bool dvar, double _activity, bool insertIntoHeap )
1646  {
1647  int v = nVars();
1648  watches.init( mkLit( v, false ) );
1649  watches.init( mkLit( v, true ) );
1650  assigns.push( l_Undef );
1651  vardata.push( VarData( CRef_Undef, -1, -1 ) );
1652  activity.push( _activity == std::numeric_limits<double>::infinity() ? maxActivity() + 1 : _activity );
1653  // activity.push( rnd_init_act ? drand( random_seed ) * 0.00001 : 0 );
1654  seen.push( 0 );
1655  polarity.push( sign );
1656  decision.push();
1657  trail.capacity( v + 1 );
1658  setDecisionVar( v, dvar, insertIntoHeap );
1659  if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
1660  {
1661  mNonTseitinShadowedOccurrences.push( dvar ? 1 : 0 );
1662  }
1663  if( /*!mReceivedFormulaPurelyPropositional &&*/ Settings::check_active_literal_occurrences )
1664  {
1665  mLiteralsClausesMap.emplace_back();
1666  mLiteralsActivOccurrences.emplace_back();
1667  }
1668  return v;
1669  }
1670 
1671  template<class Settings>
1672  bool SATModule<Settings>::addClause( const vec<Lit>& _clause, unsigned _type )
1673  {
1674  SMTRAT_LOG_DEBUG("smtrat.sat", "Adding clause " << _clause);
1675  #ifdef DEBUG_SATMODULE_LEMMA_HANDLING
1676  std::cout << "add clause ";
1677  printClause(_clause,true);
1678  #endif
1679  assert( _clause.size() != 0 );
1680  assert(_type < 4);
1681  add_tmp.clear();
1682  _clause.copyTo( add_tmp );
1683 
1684  #ifdef SMTRAT_DEVOPTION_Statistics
1685  if( _type != NORMAL_CLAUSE ) mStatistics.lemmaLearned();
1686  #endif
1687  // Check if clause is satisfied and remove false/duplicate literals:true);
1688  Minisat::sort( add_tmp );
1689 
1690  int falseLiteralsCount = 0;
1691  // check the clause for tautologies and similar
1692  // note, that we do not change original clauses, as due to incrementality we
1693  // want to know the clauses of a formula regardless of the context of other formulas
1694  if( _type != NORMAL_CLAUSE )
1695  {
1696  Lit p;
1697  int i, j;
1698  for( i = j = 0, p = lit_Undef; i < add_tmp.size(); ++i )
1699  {
1700  // tautologies are ignored
1701  if( add_tmp[i] == ~p )
1702  return true; // clause can be ignored
1703  // clauses with 0-level true literals are also ignored
1704  if( value( add_tmp[i] ) == l_True && level( var( add_tmp[i] ) ) == 0 )
1705  return true;
1706  // ignore repeated literals
1707  if( add_tmp[i] == p )
1708  continue;
1709  // if a liteal is false at 0 level (both sat and user level) we also ignore it
1710  if( value( add_tmp[i] ) == l_False )
1711  {
1712  if( level( var( add_tmp[i] ) ) == 0 )
1713  continue;
1714  else
1715  ++falseLiteralsCount; // if we decide to keep it, we count it into the false literals
1716  }
1717  // this literal is a keeper
1718  add_tmp[j++] = p = add_tmp[i];
1719  }
1720  add_tmp.shrink( i - j );
1721  SMTRAT_LOG_DEBUG("smtrat.sat", "add_tmp = " << add_tmp);
1722  SMTRAT_LOG_DEBUG("smtrat.sat", "false literals: " << falseLiteralsCount);
1723  if( mBusy || decisionLevel() > assumptions.size() )
1724  {
1725  //if (_type != CONFLICT_CLAUSE) { //!Settings::mc_sat ||
1726  #ifdef DEBUG_SATMODULE_LEMMA_HANDLING
1727  std::cout << "add to mLemmas:" << add_tmp << std::endl;
1728  #endif
1729  SMTRAT_LOG_DEBUG("smtrat.sat", "add_lemma = " << add_tmp);
1730  mLemmas.push();
1731  add_tmp.copyTo( mLemmas.last() );
1732  mLemmasRemovable.push( _type != NORMAL_CLAUSE );
1733  return true;
1734  //}
1735  }
1736  // if all false, we're in conflict
1737  if( add_tmp.size() == falseLiteralsCount )
1738  {
1739  SMTRAT_LOG_DEBUG("smtrat.sat", "ok = false");
1740  mLemmas.push();
1741  add_tmp.copyTo( mLemmas.last() );
1742  mLemmasRemovable.push( _type != NORMAL_CLAUSE );
1743  return false;
1744  }
1745  }
1746  CRef cr = CRef_Undef;
1747  // if not unit, add the clause
1748  if( add_tmp.size() > 1 )
1749  {
1750  lemma_lt lt( *this );
1751  Minisat::sort( add_tmp, lt );
1752  cr = ca.alloc( add_tmp, NORMAL_CLAUSE );
1753  clauses.push( cr );
1754  attachClause( cr );
1755  }
1756  // check if it propagates
1757  if( add_tmp.size() == falseLiteralsCount + 1 )
1758  {
1759  if( assigns[var(add_tmp[0])] == l_Undef )
1760  {
1761  assert( assigns[var(add_tmp[0])] != l_False );
1762  if (add_tmp.size() == 1) {
1763  assumptions.push(add_tmp[0]);
1764  } else {
1765  uncheckedEnqueue( add_tmp[0], cr );
1766  if (propagateConsistently(false) != CRef_Undef) {
1767  ok = false;
1768  }
1769  }
1770  return ok;
1771  }
1772  else
1773  return ok;
1774  }
1775  return true;
1776  }
1777 
1778  template<class Settings>
1779  int SATModule<Settings>::level( const vec< Lit >& _clause ) const
1780  {
1781  int result = 0;
1782  for( int i = 0; i < _clause.size(); ++i )
1783  {
1784  if( value( _clause[i] ) != l_Undef )
1785  {
1786  int varLevel = level( var( _clause[i] ) );
1787  if( varLevel > result ) result = varLevel;
1788  }
1789  }
1790  return result;
1791  }
1792 
1793  template<class Settings>
1794  CRef SATModule<Settings>::storeLemmas()
1795  {
1796  // decision level to backtrack to
1797  int backtrackLevel = decisionLevel();
1798  SMTRAT_LOG_DEBUG("smtrat.sat", "Storing " << mLemmas.size() << " lemmas");
1799 
1800  // First phase:
1801  // - Sort lemmas (only for analyzing, order may change due to backtracking again...)
1802  // - Figure out whether one is conflicting
1803  // - Determine decision level to backtrack to
1804  // Backtrack
1805  // Second phase:
1806  // - Sort lemmas again
1807  // - Add lemma as clause
1808  // - If conflicting: use as conflict
1809  // - If propagating: propagate manually
1810 
1811  // In general, we have the following cases for the first two literals:
1812  // - UU, UT, TT, TF: lemma is neither unit nor conflicting
1813  // - UF: unit
1814  // - FF: conflicting
1815  // TU, FU, FT: Can not occur due to sorting
1816 
1817  for (int i = 0; i < mLemmas.size(); i++) {
1818  auto& lemma = mLemmas[i];
1819  SMTRAT_LOG_DEBUG("smtrat.sat", "Analyzing lemma " << lemma);
1820  // if it's an empty lemma, we have a conflict at zero level
1821  if (lemma.size() == 0) {
1822  SMTRAT_LOG_DEBUG("smtrat.sat", "-- Lemma is trivial conflict, backtrack immediately");
1823  backtrackLevel = 0;
1824  break;
1825  }
1826  // Sort to make sure watches are at the front
1827  SMTRAT_LOG_DEBUG("smtrat.sat", "Sorting lemma " << lemma);
1828  Minisat::sort(lemma, lemma_lt(*this));
1829  SMTRAT_LOG_DEBUG("smtrat.sat", "Resulting lemma " << lemma);
1830  if (lemma.size() == 1) {
1831  // Backtrack to DL0 if (a) it is not assigned to true or (b) assigned to true later than DL0
1832  if (value(lemma[0]) != l_True || level(var(lemma[0])) > 0) {
1833  SMTRAT_LOG_DEBUG("smtrat.sat", "-- Lemma is singleton, backtrack to DL0");
1834  backtrackLevel = 0;
1835  break;
1836  } else {
1837  SMTRAT_LOG_DEBUG("smtrat.sat", "-- Lemma is singleton, but was already propagated at DL0");
1838  }
1839  } else if (value(lemma[0]) == l_False) {
1840  // Conflicting
1841  assert(value(lemma[1]) == l_False);
1842  // Backtrack to highest DL such that it looks like a regular conflict
1843  int lvl = min_theory_level(var(lemma[1])); // instead of 0
1844  SMTRAT_LOG_DEBUG("smtrat.sat", "-- Lemma is conflicting, propagates on DL" << lvl);
1845  if (lvl < backtrackLevel) {
1846  backtrackLevel = lvl;
1847  }
1848  } else if (value(lemma[0]) == l_Undef && value(lemma[1]) == l_False) {
1849  // Unit
1850  int lvl = theory_level(var(lemma[1]));
1851  SMTRAT_LOG_DEBUG("smtrat.sat", "-- Lemma is propagating on DL" << lvl);
1852  if (lvl < backtrackLevel) {
1853  backtrackLevel = lvl;
1854  }
1855  }
1856  }
1857  SMTRAT_LOG_DEBUG("smtrat.sat", "Backtracking to " << backtrackLevel);
1858  SMTRAT_CHECKPOINT("nlsat", "backtrack", backtrackLevel);
1859  cancelUntil(backtrackLevel, true);
1860 
1861  CRef conflict = CRef_Undef;
1862  for (int i = mLemmas.size()-1; i >= 0; i--) {
1863  auto lemma = std::move(mLemmas[i]);
1864  bool removable = mLemmasRemovable[i];
1865  mLemmas.pop();
1866  mLemmasRemovable.pop();
1867  SMTRAT_LOG_DEBUG("smtrat.sat", "Processing lemma " << lemma);
1868 
1869  if (Settings::check_for_duplicate_clauses) {
1870  SMTRAT_LOG_DEBUG("smtrat.sat", "Checking for existing clause " << lemma);
1871  std::size_t dups = 0;
1872  for (int i = 0; i < learnts.size(); i++) {
1873  const auto& corig = ca[learnts[i]];
1874  if (lemma.size() != corig.size()) continue;
1875  Minisat::vec<Minisat::Lit> c;
1876  for (int j = 0; j < corig.size(); j++) {
1877  c.push(corig[j]);
1878  }
1879  Minisat::sort(c, lemma_lt(*this));
1880  bool different = false;
1881  for (int j = 0; j < lemma.size(); j++) {
1882  different = different || (c[j] != lemma[j]);
1883  }
1884  if (!different) {
1885  SMTRAT_LOG_DEBUG("smtrat.sat", lemma << " is a duplicate of " << corig);
1886  dups++;
1887  }
1888  }
1889  if (dups > 0) {
1890  SMTRAT_LOG_ERROR("smtrat.sat", "Adding a clause we already have: " << lemma);
1891  }
1892  assert(dups == 0);
1893  }
1894 
1895  if (lemma.size() == 0) {
1896  SMTRAT_LOG_DEBUG("smtrat.sat", "-- Lemma is trivial conflict, ok = false");
1897  ok = false;
1898  return CRef_Undef;
1899  }
1900  // Resort in case the backtracking changed the order
1901  Minisat::sort(lemma, lemma_lt(*this));
1902  SMTRAT_LOG_DEBUG("smtrat.sat", "Sorted -> " << lemma);
1903  // If lemma is not a single literal, attach it
1904  CRef lemma_ref = CRef_Undef;
1905  if (lemma.size() > 1) {
1906  lemma_ref = ca.alloc(lemma, removable);
1907  if (removable) {
1908  learnts.push(lemma_ref);
1909  } else {
1910  clauses.push(lemma_ref);
1911  }
1912  attachClause(lemma_ref);
1913  SMTRAT_LOG_DEBUG("smtrat.sat", "-- Added lemma as clause " << lemma_ref);
1914  }
1915  #ifdef DEBUG_SATMODULE
1916  std::cout << "### Processing clause" << std::endl;
1917  print(std::cout, "###");
1918  #endif
1919  if (lemma.size() == 1) {
1920  // Only a single literal
1921  assert(decisionLevel() == 0);
1922  assert(lemma_ref == CRef_Undef);
1923  if (value(lemma[0]) == l_False) {
1924  SMTRAT_LOG_DEBUG("smtrat.sat", "-- Lemma is singleton conflict, ok = false");
1925  ok = false;
1926  return CRef_Undef;
1927  } else if (value(lemma[0]) == l_Undef) {
1928  SMTRAT_LOG_DEBUG("smtrat.sat", "-- Lemma is singleton, add as assumption");
1929  assumptions.push(lemma[0]);
1930  } else {
1931  SMTRAT_LOG_DEBUG("smtrat.sat", "-- Lemma is singleton, but was already propagated at DL0");
1932  }
1933  } else if (value(lemma[0]) == l_Undef && value(lemma[1]) == l_False) {
1934  SMTRAT_LOG_DEBUG("smtrat.sat", "-- Lemma is unit, propagating " << lemma[0]);
1935  SMTRAT_CHECKPOINT("nlsat", "propagation", lemma_ref, lemma[0]);
1936  uncheckedEnqueue(lemma[0], lemma_ref);
1937  } else if (value(lemma[0]) == l_False) {
1938  SMTRAT_LOG_DEBUG("smtrat.sat", lemma[0] << " is false, hence " << lemma[1] << " should also be false...");
1939  assert(value(lemma[1]) == l_False);
1940  SMTRAT_LOG_DEBUG("smtrat.sat", "-- Lemma is conflicting, use as conflict");
1941  conflict = lemma_ref;
1942  }
1943  }
1944  return conflict;
1945 
1946  // Wenn conflicting:
1947  // wenn nur ein lit auf letztem DL: zu vorletztem DL backtracken, einfügen, per hand propagieren
1948  // sonst: zu letztem DL backtracken, einfügen, analyze aufrufen
1949  // check for propagation and level to backtrack to
1950 // int i = 0;
1951 // while( i < mLemmas.size() )
1952 // {
1953 // // we need this loop as when we backtrack, due to registration more lemmas could be added
1954 // for( ; i < mLemmas.size(); ++i )
1955 // {
1956 // // The current lemma
1957 // vec<Lit>& lemma = mLemmas[i];
1958 // SMTRAT_LOG_DEBUG("smtrat.sat", "Analyzing lemma " << lemma);
1959 // // if it's an empty lemma, we have a conflict at zero level
1960 // if( lemma.size() == 0 )
1961 // {
1962 // backtrackLevel = 0;
1963 // continue;
1964 // }
1965 // for (int i = 0; i < lemma.size(); i++) {
1966 // valueAndUpdate(lemma[i]);
1967 // }
1968 // // sort the lemma to be able to attach
1969 // sort( lemma, lt );
1970 // // see if the lemma propagates something
1971 // SMTRAT_LOG_DEBUG("smtrat.sat", "Model: " << mCurrentTheoryModel);
1972 // SMTRAT_LOG_DEBUG("smtrat.sat", "Lemma: " << lemma);
1973 // SMTRAT_LOG_DEBUG("smtrat.sat", "value(lemma[1]) " << value(lemma[1]));
1974 // SMTRAT_LOG_DEBUG("smtrat.sat", "level(lemma[1]) " << level(var(lemma[1])));
1975 // if( lemma.size() == 1 || value(lemma[1]) == l_False )
1976 // {
1977 // // this lemma propagates, see which level we need to backtrack to
1978 // int currentBacktrackLevel = lemma.size() == 1 ? 0 : level(var(lemma[0]));
1979 // // even if the first literal is true, we should propagate it at this level (unless it's set at a lower level)
1980 // if( value(lemma[0]) != l_True || level(var(lemma[0])) > currentBacktrackLevel )
1981 // {
1982 // SMTRAT_LOG_DEBUG("smtrat.sat", "Backtracking to " << backtrackLevel);
1983 // if( currentBacktrackLevel < backtrackLevel )
1984 // backtrackLevel = currentBacktrackLevel;
1985 // }
1986 // }
1987 // }
1988 // // pop so that propagation would be current
1989 // SMTRAT_LOG_DEBUG("smtrat.sat", "Backtracking to " << backtrackLevel);
1990 // cancelUntil( backtrackLevel, true );
1991 // #ifdef DEBUG_SATMODULE_LEMMA_HANDLING
1992 // std::cout << "backtrack to " << backtrackLevel << std::endl;
1993 // #endif
1994 // }
1995 // // last index in the trail
1996 // int backtrack_index = trail.size();
1997 // // attach all the clauses and enqueue all the propagations
1998 // for( int i = 0; i < mLemmas.size(); ++i )
1999 // {
2000 // // the current lemma
2001 // vec<Lit>& lemma = mLemmas[i];
2002 // if( lemma.size() == 0 )
2003 // {
2004 // SMTRAT_LOG_DEBUG("smtrat.sat", "ok = false");
2005 // ok = false;
2006 // return CRef_Undef;
2007 // }
2008 // for (int i = 0; i < lemma.size(); i++) {
2009 // valueAndUpdate(lemma[i]);
2010 // }
2011 // SMTRAT_LOG_DEBUG("smtrat.sat", "Adding lemma " << lemma);
2012 // bool removable = mLemmasRemovable[i];
2013 // // attach it if non-unit
2014 // CRef lemma_ref = CRef_Undef;
2015 // if( lemma.size() > 1 )
2016 // {
2017 // lemma_ref = ca.alloc( lemma, removable );
2018 // if( removable )
2019 // learnts.push( lemma_ref );
2020 // else
2021 // clauses.push( lemma_ref );
2022 // attachClause( lemma_ref );
2023 // }
2024 // // if the lemma is propagating enqueue its literal (or set the conflict)
2025 // #ifdef DEBUG_SATMODULE
2026 // std::cout << "######################################################################" << std::endl;
2027 // std::cout << "###" << std::endl; printBooleanConstraintMap(std::cout, "###");
2028 // std::cout << "###" << std::endl; printClauses( clauses, "Clauses", std::cout, "### ", 0, false, false );
2029 // std::cout << "###" << std::endl; printClauses( learnts, "Learnts", std::cout, "### ", 0, false, false );
2030 // std::cout << "###" << std::endl; printCurrentAssignment( std::cout, "### " );
2031 // std::cout << "###" << std::endl; printDecisions( std::cout, "### " );
2032 // std::cout << "###" << std::endl;
2033 // #endif
2034 // if( conflict == CRef_Undef && value(lemma[0]) != l_True )
2035 // {
2036 // if( lemma.size() == 1 || (value(lemma[1]) == l_False && trailIndex(var(lemma[1])) < backtrack_index) )
2037 // {
2038 // if( value(lemma[0]) == l_False )
2039 // {
2040 // // we have a conflict
2041 // if( lemma.size() > 1 )
2042 // {
2043 // #ifdef DEBUG_SATMODULE_LEMMA_HANDLING
2044 // std::cout << "lemma is better as conflict" << std::endl;
2045 // #endif
2046 // conflict = lemma_ref;
2047 // } else {
2048 // SMTRAT_LOG_DEBUG("smtrat.sat", "Unit conflict " << conflict);
2049 // cancelUntil(0);
2050 // if (value(lemma[0]) == l_False) {
2051 // SMTRAT_LOG_DEBUG("smtrat.sat", "ok = false");
2052 // ok = false;
2053 // return CRef_Undef;
2054 // }
2055 // uncheckedEnqueue(lemma[0]);
2056 // break;
2057 // }
2058 // }
2059 // else
2060 // {
2061 // uncheckedEnqueue(lemma[0], lemma_ref);
2062 // }
2063 // }
2064 // }
2065 // }
2066 // // clear the lemmas
2067 // mLemmas.clear();
2068 // mLemmasRemovable.clear();
2069 // SMTRAT_LOG_DEBUG("smtrat.sat", "Stored lemmas, returning conflict " << conflict);
2070 // return conflict;
2071  }
2072 
2073  template<class Settings>
2074  void SATModule<Settings>::attachClause( CRef cr )
2075  {
2076  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Clause: " << cr);
2077  Clause& c = ca[cr];
2078  sat::detail::validateClause(c, mMinisatVarMap, mBooleanConstraintMap, Settings::validate_clauses);
2079  assert( c.size() > 1 );
2080  watches[~c[0]].push( Watcher( cr, c[1] ) );
2081  watches[~c[1]].push( Watcher( cr, c[0] ) );
2082  if( c.learnt() )
2083  {
2084  learnts_literals += (uint64_t)c.size();
2085  }
2086  else
2087  clauses_literals += (uint64_t)c.size();
2088  if( /*!mReceivedFormulaPurelyPropositional &&*/ Settings::check_active_literal_occurrences )
2089  {
2090  bool clauseSatisfied = bool_satisfied(c);
2091  for( int i = 0; i < c.size(); ++i )
2092  {
2093  size_t v = (size_t)var(c[i]);
2094  assert(mLiteralsClausesMap.size() > v);
2095  if( sign(c[i]) )
2096  {
2097  if( !clauseSatisfied )
2098  ++(mLiteralsActivOccurrences[v].second);
2099  mLiteralsClausesMap[v].addNegative( cr );
2100  }
2101  else
2102  {
2103  if( !clauseSatisfied )
2104  ++(mLiteralsActivOccurrences[v].first);
2105  mLiteralsClausesMap[v].addPositive( cr );
2106  }
2107  }
2108  }
2109  var_scheduler.attachClause(cr);
2110  }
2111 
2112  template<class Settings>
2113  void SATModule<Settings>::detachClause( CRef cr, bool strict )
2114  {
2115  const Clause& c = ca[cr];
2116  assert( c.size() > 1 );
2117 
2118  if( strict )
2119  {
2120  Minisat::remove( watches[~c[0]], Watcher( cr, c[1] ) );
2121  Minisat::remove( watches[~c[1]], Watcher( cr, c[0] ) );
2122  }
2123  else
2124  {
2125  // Lazy detaching: (NOTE! Must clean all watcher lists before garbage collecting this clause)
2126  watches.smudge( ~c[0] );
2127  watches.smudge( ~c[1] );
2128  }
2129 
2130  if( c.learnt() )
2131  learnts_literals -= (uint64_t)c.size();
2132  else
2133  clauses_literals -= (uint64_t)c.size();
2134  if( /*!mReceivedFormulaPurelyPropositional &&*/ Settings::check_active_literal_occurrences )
2135  {
2136  bool clauseSatisfied = bool_satisfied(c);
2137  for( int i = 0; i < c.size(); ++i )
2138  {
2139  size_t v = (size_t)var(c[i]);
2140  if( sign(c[i]) )
2141  {
2142  if( !clauseSatisfied )
2143  {
2144  assert( mLiteralsActivOccurrences[v].second > 0 );
2145  --(mLiteralsActivOccurrences[v].second);
2146  }
2147  mLiteralsClausesMap[v].removeNegative( cr );
2148  }
2149  else
2150  {
2151  if( !clauseSatisfied )
2152  {
2153  assert( mLiteralsActivOccurrences[v].first > 0 );
2154  --(mLiteralsActivOccurrences[v].first);
2155  }
2156  mLiteralsClausesMap[v].removePositive( cr );
2157  }
2158  }
2159  }
2160  var_scheduler.detachClause(cr);
2161  }
2162 
2163  template<class Settings>
2164  void SATModule<Settings>::removeClause( CRef cr )
2165  {
2166  Clause& c = ca[cr];
2167  detachClause( cr );
2168  // Don't leave pointers to free'd memory!
2169  if( locked( c ) )
2170  vardata[var( c[0] )].reason = CRef_Undef;
2171  c.mark( 1 );
2172  ca.free( cr );
2173  }
2174 
2175  template<class Settings>
2176  bool SATModule<Settings>::satisfied( const Clause& c ) const
2177  {
2178  for( int i = 0; i < c.size(); i++ )
2179  {
2180  if( value( c[i] ) == l_True )
2181  return true;
2182  }
2183  return false;
2184  }
2185 
2186  template<class Settings>
2187  bool SATModule<Settings>::bool_satisfied( const Clause& c ) const
2188  {
2189  for( int i = 0; i < c.size(); i++ )
2190  {
2191  if( bool_value( c[i] ) == l_True )
2192  return true;
2193  }
2194  return false;
2195  }
2196 
2197  template<class Settings>
2198  void SATModule<Settings>::cancelUntil( int level, bool force )
2199  {
2200  if( level < assumptions.size() && !force )
2201  level = assumptions.size();
2202  #ifdef DEBUG_SATMODULE
2203  std::cout << "### cancel until " << level << " (forced: " << force << ")" << std::endl;
2204  #endif
2205  if( decisionLevel() > level )
2206  {
2207  cancelAssignmentUntil( level );
2208  qhead = trail_lim[level];
2209  SMTRAT_LOG_TRACE("smtrat.sat", "Reset qhead to " << qhead << " from " << trail_lim);
2210  trail.shrink( trail.size() - trail_lim[level] );
2211  trail_lim.shrink( trail_lim.size() - level );
2212  ok = true;
2213  }
2214  }
2215 
2216  template<class Settings>
2217  void SATModule<Settings>::cancelIncludingLiteral( Minisat::Lit lit ) {
2218  SMTRAT_LOG_DEBUG("smtrat.sat.mc", "Backtracking until we hit " << lit);
2219  for (int c = trail.size() - 1; c >= 0; --c) {
2220  SMTRAT_LOG_DEBUG("smtrat.sat.mc", "Backtracking " << trail[c]);
2221  if (Settings::mc_sat) {
2222  mMCSAT.backtrackTo(trail[c]);
2223  }
2224  Var x = var( trail[c] );
2225  resetVariableAssignment( x );
2226  if (Settings::mc_sat) {
2227  mMCSAT.undoBooleanAssignment(trail[c]);
2228  }
2229  VarData& vd = vardata[x];
2230  if( vd.mExpPos > 0 )
2231  {
2232  removeTheoryPropagation( vd.mExpPos );
2233  vd.mExpPos = -1;
2234  }
2235  vd.reason = CRef_Undef;
2236  vd.mTrailIndex = -1;
2237  if( (phase_saving > 1 || (phase_saving == 1)) && c > trail_lim.last() )
2238  polarity[x] = sign( trail[c] );
2239  insertVarOrder( x );
2240  qhead = c;
2241  Minisat::Lit curlit = trail[c];
2242  assert(lit != neg(curlit));
2243  if (trail_lim.last() == c) trail_lim.pop();
2244  trail.pop();
2245  if (curlit == lit) break;
2246  }
2247  SMTRAT_LOG_DEBUG("smtrat.sat.mc", "Done.");
2248  }
2249 
2250  template<class Settings>
2251  void SATModule<Settings>::cancelAssignmentUntil( int level )
2252  {
2253  for( int c = trail.size() - 1; c >= trail_lim[level]; --c )
2254  {
2255  SMTRAT_LOG_DEBUG("smtrat.sat.mc", "Backtracking " << trail[c]);
2256  if (Settings::mc_sat) {
2257  mMCSAT.backtrackTo(trail[c]);
2258  }
2259  Var x = var( trail[c] );
2260  resetVariableAssignment( x );
2261  if (Settings::mc_sat) {
2262  mMCSAT.undoBooleanAssignment(trail[c]);
2263  }
2264  VarData& vd = vardata[x];
2265  if( vd.mExpPos > 0 )
2266  {
2267  removeTheoryPropagation( vd.mExpPos );
2268  vd.mExpPos = -1;
2269  }
2270  vd.reason = CRef_Undef;
2271  vd.mTrailIndex = -1;
2272  if( (phase_saving > 1 || (phase_saving == 1)) && c > trail_lim.last() )
2273  polarity[x] = sign( trail[c] );
2274  insertVarOrder( x );
2275  }
2276  }
2277 
2278  template<class Settings>
2279  void SATModule<Settings>::resetVariableAssignment( Var _var )
2280  {
2281  Minisat::lbool& ass = assigns[_var];
2282  bool wasAssignedToFalse = ass == l_False;
2283  if( !mReceivedFormulaPurelyPropositional && mBooleanConstraintMap[_var].first != nullptr )
2284  {
2285  Abstraction* abstrptr = wasAssignedToFalse ? mBooleanConstraintMap[_var].second : mBooleanConstraintMap[_var].first;
2286  assert( abstrptr != nullptr );
2287  Abstraction& abstr = *abstrptr;
2288  if( abstr.position != rPassedFormula().end() )
2289  {
2290  if( abstr.updateInfo >=0 && --abstr.updateInfo < 0 )
2291  {
2292  mChangedBooleans.push_back( _var );
2293  }
2294  }
2295  else if( abstr.consistencyRelevant )
2296  {
2297  abstr.updateInfo = 0;
2298  }
2299  }
2300 
2301  if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
2302  {
2303  auto iter = mTseitinVarShadows.find( (signed) _var );
2304  if( iter != mTseitinVarShadows.end() )
2305  {
2306  for( signed var : iter->second )
2307  {
2308  decrementTseitinShadowOccurrences(var);
2309  }
2310  }
2311  }
2312  ass = l_Undef;
2313  if( /*!mReceivedFormulaPurelyPropositional &&*/ Settings::check_active_literal_occurrences )
2314  {
2315  // Check clauses which are going to be satisfied by this assignment.
2316  size_t v = (size_t)_var;
2317  const std::vector<CRef>& satisfiedClauses = wasAssignedToFalse ? mLiteralsClausesMap[v].negatives() : mLiteralsClausesMap[v].positives();
2318  for( CRef cr : satisfiedClauses )
2319  {
2320  const Clause& c = ca[cr];
2321  // Check if clause is not yet satisfied.
2322  if( !bool_satisfied(c) )
2323  {
2324  for( int i = 0; i < c.size(); ++i )
2325  {
2326  size_t v = (size_t)var(c[i]);
2327  std::pair<size_t,size_t>& litActOccs = mLiteralsActivOccurrences[v];
2328  Var x = var(c[i]);
2329  if( litActOccs.first == 0 )
2330  {
2331  if( litActOccs.second == 0 )
2332  {
2333  decision[x] = true;
2334  insertVarOrder( x );
2335  }
2336  else
2337  {
2338  auto pfdIter = std::find( mPropagationFreeDecisions.begin(), mPropagationFreeDecisions.end(), mkLit( x, true ) );
2339  if( pfdIter != mPropagationFreeDecisions.end() )
2340  {
2341  *pfdIter = mPropagationFreeDecisions.back();
2342  mPropagationFreeDecisions.pop_back();
2343  }
2344  }
2345  }
2346  else if( litActOccs.second == 0 )
2347  {
2348  auto pfdIter = std::find( mPropagationFreeDecisions.begin(), mPropagationFreeDecisions.end(), mkLit( x, false ) );
2349  if( pfdIter != mPropagationFreeDecisions.end() )
2350  {
2351  *pfdIter = mPropagationFreeDecisions.back();
2352  mPropagationFreeDecisions.pop_back();
2353  }
2354  }
2355  if( sign(c[i]) )
2356  {
2357  ++(litActOccs.second);
2358  }
2359  else
2360  {
2361  ++(litActOccs.first);
2362  }
2363  }
2364  }
2365  }
2366  }
2367  if( Settings::check_if_all_clauses_are_satisfied && !mReceivedFormulaPurelyPropositional && mNumberOfSatisfiedClauses > 0 )
2368  {
2369  auto litClausesIter = mLiteralClausesMap.find( (int) _var );
2370  if( litClausesIter != mLiteralClausesMap.end() )
2371  {
2372  for( CRef cl : litClausesIter->second )
2373  {
2374  if( !satisfied( ca[cl] ) )
2375  {
2376  assert( mNumberOfSatisfiedClauses > 0 );
2377  --mNumberOfSatisfiedClauses;
2378  }
2379  }
2380  }
2381  }
2382  }
2383 
2384  template<class Settings>
2385  CRef SATModule<Settings>::propagateConsistently( bool _checkWithTheory )
2386  {
2387  CRef confl = CRef_Undef;
2388 
2389  ScopedBool scopedBool( mBusy, true );
2390 
2391  // add lemmas that we're left behind
2392  if( mLemmas.size() > 0 )
2393  {
2394  SMTRAT_LOG_DEBUG("smtrat.sat", "Storing lemmas");
2395  confl = storeLemmas();
2396  SMTRAT_LOG_DEBUG("smtrat.sat", "-> " << confl);
2397  if( confl != CRef_Undef )
2398  return confl;
2399  if( !ok )
2400  return CRef_Undef;
2401  }
2402  // keep running until we have checked everything, we have no conflict and no new literals have been asserted
2403  do
2404  {
2405  SMTRAT_LOG_DEBUG("smtrat.sat", "Propagating");
2406  // Propagate on the clauses
2407  confl = propagate();
2408  // If no conflict, do the theory check
2409  if( confl == CRef_Undef && _checkWithTheory )
2410  {
2411  if (!Settings::mc_sat) {
2412  // do the theory check
2413  theoryCall();
2414  if( mCurrentAssignmentConsistent == ABORTED )
2415  {
2416  mCurrentAssignmentConsistent = UNKNOWN;
2417  return CRef_Undef;
2418  }
2419  // propagate theory
2420  propagateTheory();
2421  if( Settings::allow_theory_propagation ) {
2422  SMTRAT_LOG_DEBUG("smtrat.sat", "Processing lemmas");
2423  processLemmas();
2424  }
2425  // if there are lemmas (or conflicts) update them
2426  if( mLemmas.size() > 0 ) {
2427  SMTRAT_LOG_DEBUG("smtrat.sat", "Storing lemmas");
2428  confl = storeLemmas();
2429  SMTRAT_LOG_DEBUG("smtrat.sat", "-> " << confl);
2430  }
2431  }
2432  }
2433  else
2434  {
2435  // even though in conflict, we still need to discharge the lemmas
2436  if( mLemmas.size() > 0 )
2437  {
2438  SMTRAT_LOG_DEBUG("smtrat.sat", "Storing lemmas");
2439  // remember the trail size
2440  int oldLevel = decisionLevel();
2441  // update the lemmas
2442  CRef lemmaConflict = storeLemmas();
2443  // if we get a conflict, we prefer it since it's earlier in the trail
2444  if( lemmaConflict != CRef_Undef )
2445  confl = lemmaConflict; // lemma conflict takes precedence, since it's earlier in the trail
2446  else if( oldLevel > decisionLevel() )
2447  confl = CRef_Undef; // Otherwise, the Boolean conflict is canceled in the case we popped the trail
2448  }
2449  }
2450  if( !ok ) {
2451  SMTRAT_LOG_DEBUG("smtrat.sat", "Aborting due to !ok");
2452  return CRef_Undef;
2453  }
2454  assert(Settings::mc_sat || mChangedBooleans.empty() || _checkWithTheory );
2455 
2456  }
2457  while (confl == CRef_Undef // We have a conflict -> leave propagation, enter conflict resoltion
2458  && (qhead < trail.size() // We did not finish propagation yet
2459  || (decisionLevel() >= assumptions.size()
2460  && mCurrentAssignmentConsistent != SAT
2461  && !mChangedBooleans.empty()
2462  && !Settings::mc_sat
2463  )
2464  )
2465  );
2466  SMTRAT_LOG_TRACE("smtrat.sat", "Returning " << confl);
2467  return confl;
2468  }
2469 
2470  template<class Settings>
2471  void SATModule<Settings>::propagateTheory()
2472  {
2473  carl::uint pos = mTheoryPropagations.size();
2474  collectTheoryPropagations();
2475  while( pos < mTheoryPropagations.size() )
2476  {
2477  TheoryPropagation& tp = mTheoryPropagations[pos];
2478  SMTRAT_LOG_DEBUG("smtrat.sat", "Propagating " << tp.mPremise << " -> " << tp.mConclusion);
2479  Lit conclLit = createLiteral( tp.mConclusion );
2480  if( value(conclLit) == l_Undef )
2481  {
2482  uncheckedEnqueue( conclLit, CRef_Lazy );
2483  vardata[var(conclLit)].mExpPos = (int)pos;
2484  ++pos;
2485  }
2486  else
2487  {
2488  if( value(conclLit) == l_False )
2489  {
2490  vec<Lit> explanation;
2491  for( const auto& subformula : tp.mPremise )
2492  explanation.push( neg( getLiteral( subformula ) ) );
2493  explanation.push( conclLit );
2494  addClause( explanation, LEMMA_CLAUSE );
2495  }
2496  if( (std::size_t) pos != mTheoryPropagations.size()-1 )
2497  tp = std::move( mTheoryPropagations.back() );
2498  mTheoryPropagations.pop_back();
2499  }
2500  }
2501  }
2502 
2503  template<class Settings>
2504  CRef SATModule<Settings>::reason( Var x )
2505  {
2506  VarData& vd = vardata[x];
2507  // if we already have a reason, just return it
2508  if( vd.reason != CRef_Lazy )
2509  return vd.reason;
2510 
2511  // what's the literal we are trying to explain
2512  Lit l = mkLit(x, value(x) != l_True);
2513 
2514  // get the explanation
2515  assert( vd.mExpPos >= 0 && (std::size_t)vd.mExpPos < mTheoryPropagations.size() );
2516  TheoryPropagation& tp = mTheoryPropagations[(std::size_t)vd.mExpPos];
2517  vec<Lit> explanation;
2518  assert( getLiteral( tp.mConclusion ) == l );
2519  explanation.push( l );
2520  for( const auto& subformula : tp.mPremise )
2521  explanation.push( neg( getLiteral( subformula ) ) );
2522 
2523  // remove theory propagation
2524  removeTheoryPropagation( vd.mExpPos );
2525 
2526  // sort the literals by trail index level
2527  lemma_lt lt(*this);
2528  Minisat::sort( explanation, lt );
2529  assert( explanation[0] == l );
2530 
2531  // compute the assertion level for this clause
2532  int i, j;
2533  Lit prev = lit_Undef;
2534  for( i = 0, j = 0; i < explanation.size(); ++i )
2535  {
2536  assert( value(explanation[i]) != l_Undef );
2537  assert( i == 0 || trailIndex(var(explanation[0])) > trailIndex(var(explanation[i])) );
2538 
2539  // always keep the first literal
2540  if( i == 0 )
2541  {
2542  prev = explanation[j++] = explanation[i];
2543  continue;
2544  }
2545  // ignore duplicate literals
2546  if( explanation[i] == prev )
2547  continue;
2548  // ignore zero level literals
2549  if( level(var(explanation[i])) == 0 )
2550  continue;
2551  // keep this literal
2552  prev = explanation[j++] = explanation[i];
2553  }
2554  explanation.shrink(i - j);
2555 
2556  // we need an explanation clause so we add a fake literal
2557  if( j == 1 )
2558  {
2559  // add not TRUE to the clause
2560  explanation.push( mkLit( mTrueVar, true ) );
2561  }
2562 
2563  // construct the reason
2564  CRef real_reason = ca.alloc( explanation, LEMMA_CLAUSE );
2565  vardata[x] = VarData( real_reason, level(x), trailIndex(x) );
2566  learnts.push(real_reason);
2567  attachClause(real_reason);
2568  return real_reason;
2569  }
2570 
2571  template<class Settings>
2572  void SATModule<Settings>::removeTheoryPropagation( int _position )
2573  {
2574  assert( _position >= 0 );
2575  assert( (std::size_t)_position < mTheoryPropagations.size() );
2576  if( (std::size_t) _position != mTheoryPropagations.size()-1 )
2577  {
2578  TheoryPropagation& tp = mTheoryPropagations.back();
2579  VarData& vd = vardata[var(getLiteral( tp.mConclusion ))];
2580  assert( (std::size_t) vd.mExpPos == mTheoryPropagations.size()-1 );
2581  vd.mExpPos = _position;
2582  mTheoryPropagations[(std::size_t)_position] = std::move( tp );
2583  }
2584  mTheoryPropagations.pop_back();
2585  }
2586 
2587  template<class Settings>
2588  void SATModule<Settings>::theoryCall()
2589  {
2590  #ifdef DEBUG_SATMODULE
2591  std::cout << "### Sat iteration" << std::endl;
2592  std::cout << "######################################################################" << std::endl;
2593  std::cout << "###" << std::endl; printBooleanConstraintMap(std::cout, "###");
2594  std::cout << "###" << std::endl; printClauses( clauses, "Clauses", std::cout, "### ", 0, false, false );
2595  std::cout << "###" << std::endl; printClauses( learnts, "Learnts", std::cout, "### ", 0, false, false );
2596  std::cout << "###" << std::endl; printCurrentAssignment( std::cout, "### " );
2597  std::cout << "###" << std::endl; printDecisions( std::cout, "### " );
2598  std::cout << "###" << std::endl;
2599  #endif
2600  if( !mReceivedFormulaPurelyPropositional && decisionLevel() >= assumptions.size() &&
2601  (!Settings::try_full_lazy_call_first || mNumberOfFullLazyCalls > 0 || trail.size() == assigns.size()) )
2602  {
2603  if( Settings::try_full_lazy_call_first && trail.size() == assigns.size() )
2604  ++mNumberOfFullLazyCalls;
2605  // Check constraints corresponding to the positively assigned Boolean variables for consistency.
2606  if( mCurrentAssignmentConsistent != SAT || is_minimizing())
2607  {
2608  adaptPassedFormula();
2609  }
2610  bool finalCheck = fullAssignment();
2611  if( mChangedPassedFormula || finalCheck )
2612  {
2613  #ifdef DEBUG_SATMODULE
2614  std::cout << "### Check the constraints: { "; for( auto& subformula : rPassedFormula() ) std::cout << subformula.formula() << " "; std::cout << "}" << std::endl;
2615  #endif
2616  mChangedPassedFormula = false;
2617  mCurrentAssignmentConsistent = runBackends( finalCheck, mFullCheck, carl::Variable::NO_VARIABLE );
2618  SMTRAT_LOG_DEBUG("smtrat.sat", "Result: " << mCurrentAssignmentConsistent);
2619  switch( mCurrentAssignmentConsistent )
2620  {
2621  case SAT:
2622  break;
2623  case UNSAT: learnTheoryConflicts();
2624  break;
2625  case UNKNOWN:
2626  break;
2627  default:
2628  mCurrentAssignmentConsistent = UNKNOWN;
2629  break;
2630  }
2631  }
2632  }
2633  }
2634 
2635  template<class Settings>
2636  bool SATModule<Settings>::expPositionsCorrect() const
2637  {
2638  for( int i = 0; i < vardata.size(); ++i )
2639  {
2640  if( vardata[i].reason == CRef_Lazy && vardata[i].mExpPos < 0 )
2641  return false;
2642  }
2643  return true;
2644  }
2645 
2646  template<class Settings>
2647  void SATModule<Settings>::constructLemmas()
2648  {
2649  for( VarLemmaMap::const_iterator iter = mPropagatedLemmas.begin(); iter != mPropagatedLemmas.end(); ++iter )
2650  {
2651  // Construct formula
2652  FormulaT premise( carl::FormulaType::AND, std::move( iter->second ) );
2653  auto mvIter = mMinisatVarMap.find(iter->first);
2654  assert( mvIter != mMinisatVarMap.end() );
2655  if( assigns[ iter->first ] == l_False )
2656  {
2657  addLemma( FormulaT( carl::FormulaType::IMPLIES, premise, mvIter->second.negated() ) );
2658  }
2659  else
2660  {
2661  assert( assigns[ iter->first ] == l_True );
2662  FormulaT lemma = FormulaT( carl::FormulaType::IMPLIES, premise, mvIter->second );
2663  addLemma( lemma );
2664  }
2665  }
2666  }
2667 
2668  template<class Settings>
2669  Minisat::lbool SATModule<Settings>::search( int nof_conflicts )
2670  {
2671 
2672  assert( ok );
2673  int conflictC = 0;
2674  starts++;
2675  mCurrentAssignmentConsistent = SAT;
2676 
2677  for( ; ; )
2678  {
2679  #ifdef DEBUG_SATMODULE
2680  std::cout << "######################################################################" << std::endl;
2681  std::cout << "### Next iteration" << std::endl;
2682  print(std::cout, "###");
2683  #endif
2684  if( !mComputeAllSAT && anAnswerFound() )
2685  return l_Undef;
2686 
2687  CRef confl;
2688  if (Settings::mc_sat) {
2689  SMTRAT_LOG_DEBUG("smtrat.sat", "MCSAT::BCP()");
2690  confl = propagateConsistently(false);
2691  } else {
2692  // DPLL::BCP()
2693  SMTRAT_LOG_DEBUG("smtrat.sat", "DPLL::BCP()");
2694  confl = propagateConsistently();
2695  }
2696  SMTRAT_LOG_TRACE("smtrat.sat", "Continuing after propagation, ok = " << ok << ", confl = " << confl);
2697  if( !ok )
2698  {
2699  if( !mReceivedFormulaPurelyPropositional && !Settings::stop_search_after_first_unknown && mExcludedAssignments )
2700  return l_Undef;
2701  // Maybe not needed here?: assert(mMCSAT.is_consistent());
2702  return l_False;
2703  }
2704 
2705  // NO CONFLICT
2706  if( confl == CRef_Undef )
2707  {
2708  SMTRAT_LOG_TRACE("smtrat.sat", "No conflict");
2709  if( Settings::check_if_all_clauses_are_satisfied && !mReceivedFormulaPurelyPropositional )
2710  {
2711  if( decisionLevel() >= assumptions.size() && mNumberOfSatisfiedClauses == (size_t)clauses.size() )
2712  {
2713  // Maybe not needed here?: assert(mMCSAT.is_consistent());
2714  return l_True;
2715  }
2716  }
2717  if( Settings::use_restarts && nof_conflicts >= 0 && (conflictC >= nof_conflicts) ) // ||!withinBudget()) )
2718  {
2719  #ifdef DEBUG_SATMODULE
2720  std::cout << "###" << std::endl << "### Restart." << std::endl << "###" << std::endl;
2721  #endif
2722  // Reached bound on number of conflicts:
2723  progress_estimate = progressEstimate();
2724  cancelUntil( 0 );
2725  ++mCurr_Restarts;
2726  #ifdef SMTRAT_DEVOPTION_Statistics
2727  mStatistics.restart();
2728  #endif
2729  return l_Undef;
2730  }
2731  if( learnts.size() - nAssigns() >= max_learnts && rReceivedFormula().is_only_propositional() )
2732  {
2733  // Reduce the set of learned clauses:
2734  reduceDB();
2735  }
2736 
2737  SMTRAT_LOG_DEBUG("smtrat.sat", "Looking for next literal");
2738  Lit next = lit_Undef;
2739  while( decisionLevel() < assumptions.size() )
2740  {
2741  // Perform user provided assumption:
2742  Lit p = assumptions[decisionLevel()];
2743  if( value( p ) == l_True )
2744  {
2745  SMTRAT_LOG_DEBUG("smtrat.sat", "Assumption " << p << " is already true");
2746  // Dummy decision level:
2747  newDecisionLevel();
2748  }
2749  else if( value( p ) == l_False )
2750  {
2751  SMTRAT_LOG_DEBUG("smtrat.sat", "Assumption " << p << " is already false");
2752  if( !mReceivedFormulaPurelyPropositional && !Settings::stop_search_after_first_unknown && mExcludedAssignments )
2753  return l_Undef;
2754  // Inconsistency is not possible here, even if mMCSAT.is_consistent() holds, as all theory decisions are backtracked
2755  // at this point, thus no assert(mMCSAT.is_consistent());
2756  return l_False;
2757  }
2758  else
2759  {
2760  SMTRAT_LOG_DEBUG("smtrat.sat", "Deciding assumption " << p);
2761  next = p;
2762  break;
2763  }
2764  }
2765 
2766  /**
2767  * Look for literals that are
2768  * - fully assigned in the theory
2769  * - unassigned in boolean
2770  */
2771  if (Settings::mc_sat && next == lit_Undef) {
2772  SMTRAT_LOG_DEBUG("smtrat.sat", "Looking for semantic propagations...");
2773  Minisat::Var v = mMCSAT.topSemanticPropagation();
2774  if (v != var_Undef) {
2775  assert(bool_value(v) == l_Undef);
2776  auto tv = theoryValue(v);
2777  SMTRAT_LOG_DEBUG("smtrat.sat", "Undef, theory value of " << v << " is " << tv);
2778  assert (tv != l_Undef);
2779  SMTRAT_LOG_DEBUG("smtrat.sat", "Propagating " << v << " = " << tv);
2780  if (tv == l_True) next = mkLit(v, false);
2781  else if (tv == l_False) next = mkLit(v, true);
2782  assert(next != lit_Undef);
2783  }
2784  if (next == lit_Undef && false) { // can be enabled to verify that semantic propagations work
2785  assert(mMCSAT.topSemanticPropagation() == var_Undef);
2786  for (std::size_t level = 0; level <= mMCSAT.level(); level++) {
2787  for (auto v: mMCSAT.get(level).decidedVariables) {
2788  SMTRAT_LOG_DEBUG("smtrat.sat", "Checking if " << v << " has been semantically propagated");
2789  assert(theoryValue(v) != l_Undef);
2790  assert(bool_value(v) != l_Undef);
2791  assert(theoryValue(v) == bool_value(v) || !mMCSAT.is_consistent(v));
2792  }
2793  }
2794  }
2795  }
2796 
2797  if (Settings::mc_sat && next == lit_Undef && !mMCSAT.is_consistent()) {
2798  SMTRAT_LOG_DEBUG("smtrat.sat", "Trail inconsistent, fixing inconsistencies...");
2799  auto conflict = mMCSAT.explainInconsistency();
2800  if (conflict) {
2801  #ifdef DEBUG_SATMODULE
2802  std::cout << "######################################################################" << std::endl;
2803  std::cout << "### Before handling conflict" << std::endl;
2804  print(std::cout, "###");
2805  #endif
2806  SMTRAT_LOG_DEBUG("smtrat.sat", "Conflict: " << *conflict);
2807  if (std::holds_alternative<FormulaT>(*conflict)) {
2808  sat::detail::validateClause(std::get<FormulaT>(*conflict), Settings::validate_clauses);
2809  }
2810  handleTheoryConflict(*conflict);
2811  #ifdef SMTRAT_DEVOPTION_Statistics
2812  mMCSATStatistics.theoryConflict();
2813  #endif
2814  continue;
2815  }
2816  }
2817 
2818  // If we do not already have a branching literal, we pick one
2819  if( next == lit_Undef )
2820  {
2821  assert(!Settings::mc_sat || mMCSAT.fullConsistencyCheck());
2822 
2823  // New variable decision:
2824  decisions++;
2825  #ifdef SMTRAT_DEVOPTION_Statistics
2826  mStatistics.decide();
2827  #endif
2828 
2829  SMTRAT_LOG_DEBUG("smtrat.sat", "Picking a literal for a decision");
2830  next = pickBranchLit();
2831  if (Settings::mc_sat && next != lit_Undef && mMCSAT.isTheoryVar(var(next))) { // theory decision
2832  const carl::Variable& tvar = mMCSAT.carlVar(var(next));
2833  assert(!mMCSAT.isAssignedTheoryVariable(tvar));
2834  SMTRAT_LOG_DEBUG("smtrat.sat", "Picked " << next << " for a theory decision, assigning...");
2835  auto res = mMCSAT.makeTheoryDecision(tvar);
2836  if (std::holds_alternative<FormulasT>(res)) {
2837  #ifdef SMTRAT_DEVOPTION_Statistics
2838  mMCSATStatistics.theoryDecision();
2839  #endif
2840  mCurrentAssignmentConsistent = SAT;
2841  const auto& assignments = std::get<FormulasT>(res);
2842  assert(assignments.size() > 0);
2843  static_assert(Settings::mcsat_num_insert_assignments > 0);
2844  // create assignments
2845  for (unsigned int i = 0; i < assignments.size() && i < Settings::mcsat_num_insert_assignments; i++) {
2846  // Note that this literal is marked as decision relevant. When reinserted into the heap, it is
2847  // converted to the corresponding theory variable representation.
2848  auto lit = createLiteral(assignments[i], FormulaT(carl::FormulaType::TRUE), true);
2849  mMCSAT.pushTheoryDecision(assignments[i], lit);
2850  SMTRAT_LOG_DEBUG("smtrat.sat", "Insert " << lit << " (" << assignments[i] << ") into SAT solver");
2851  newDecisionLevel();
2852  uncheckedEnqueue(lit);
2853  if (!mMCSAT.is_consistent()) {
2854  SMTRAT_LOG_DEBUG("smtrat.sat", "Trail got inconsistent, stopping inserting assignments");
2855  #ifdef SMTRAT_DEVOPTION_Statistics
2856  mMCSATStatistics.inconsistentTheoryDecision();
2857  #endif
2858  break;
2859  }
2860  }
2861  assert(mMCSAT.is_consistent() == mMCSAT.fullConsistencyCheck());
2862  continue;
2863  } else {
2864  mCurrentAssignmentConsistent = UNSAT;
2865  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Conflict while generating theory decision on level " << (mMCSAT.level()+1));
2866  insertVarOrder(var(next));
2867  SMTRAT_LOG_DEBUG("smtrat.sat", "Conflict: " << std::get<mcsat::Explanation>(res));
2868  #ifdef SMTRAT_DEVOPTION_Statistics
2869  mMCSATStatistics.theoryConflict();
2870  #endif
2871  handleTheoryConflict(std::get<mcsat::Explanation>(res));
2872  continue;
2873  }
2874  } else if (Settings::mc_sat && next != lit_Undef) { // Boolean decision
2875  SMTRAT_LOG_DEBUG("smtrat.sat", "Picked " << next << " for Boolean decision, checking for feasibility...");
2876  assert(bool_value(next) == l_Undef);
2877  // Note that all literals evaluating to some values should already been propagated semantically
2878  assert(!((mBooleanConstraintMap.size() > var(next)) && (mBooleanConstraintMap[var(next)].first != nullptr)) || mMCSAT.evaluateLiteral(next) == l_Undef);
2879  if (Settings::mcsat_boolean_domain_propagation == MCSAT_BOOLEAN_DOMAIN_PROPAGATION::PARTIAL) {
2880  auto res = mMCSAT.isBooleanDecisionFeasible(next);
2881  if (!res.first) {
2882  if (res.second) {
2883  SMTRAT_LOG_DEBUG("smtrat.sat", "Found conflict " << *res.second);
2884  insertVarOrder(var(next));
2885  handleTheoryConflict(*res.second);
2886  #ifdef SMTRAT_DEVOPTION_Statistics
2887  mMCSATStatistics.theoryConflict();
2888  #endif
2889  continue;
2890  } else {
2891  SMTRAT_LOG_DEBUG("smtrat.sat", "Decision " << next << " leads to conflict, propagate " << ~next);
2892  uncheckedEnqueue( ~next, CRef_TPropagation );
2893  #ifdef SMTRAT_DEVOPTION_Statistics
2894  mMCSATStatistics.insertedLazyExplanation();
2895  #endif
2896  continue;
2897  }
2898  }
2899  } else if (Settings::mcsat_boolean_domain_propagation == MCSAT_BOOLEAN_DOMAIN_PROPAGATION::FULL) {
2900  auto res = mMCSAT.propagateBooleanDomain(next);
2901  if (res.first) {
2902  SMTRAT_LOG_DEBUG("smtrat.sat", "Propagate " << next);
2903  uncheckedEnqueue( next, CRef_TPropagation );
2904  #ifdef SMTRAT_DEVOPTION_Statistics
2905  mMCSATStatistics.insertedLazyExplanation();
2906  #endif
2907  continue;
2908  } else if (!res.first) {
2909  SMTRAT_LOG_DEBUG("smtrat.sat", "Propagate " << ~next);
2910  uncheckedEnqueue( ~next, CRef_TPropagation );
2911  #ifdef SMTRAT_DEVOPTION_Statistics
2912  mMCSATStatistics.insertedLazyExplanation();
2913  #endif
2914  continue;
2915  } else {
2916  assert(boost::indeterminate(res.first));
2917  if (res.second) {
2918  SMTRAT_LOG_DEBUG("smtrat.sat", "Found conflict " << *res.second);
2919  insertVarOrder(var(next));
2920  handleTheoryConflict(*res.second);
2921  #ifdef SMTRAT_DEVOPTION_Statistics
2922  mMCSATStatistics.theoryConflict();
2923  #endif
2924  continue;
2925  } else {
2926  SMTRAT_LOG_DEBUG("smtrat.sat", "Decision " << next << " is possible");
2927  }
2928  }
2929  } else if (Settings::mcsat_boolean_domain_propagation == MCSAT_BOOLEAN_DOMAIN_PROPAGATION::PARTIAL_CONFLICT) {
2930  auto res = mMCSAT.isBooleanDecisionFeasible(next, true);
2931  if (!res.first) {
2932  assert (res.second);
2933  SMTRAT_LOG_DEBUG("smtrat.sat", "Found conflict " << *res.second);
2934  insertVarOrder(var(next));
2935  handleTheoryConflict(*res.second);
2936  #ifdef SMTRAT_DEVOPTION_Statistics
2937  mMCSATStatistics.theoryConflict();
2938  #endif
2939  continue;
2940  }
2941  }
2942  #ifdef SMTRAT_DEVOPTION_Statistics
2943  mMCSATStatistics.booleanDecision();
2944  #endif
2945  }
2946  SMTRAT_LOG_DEBUG("smtrat.sat", "Deciding upon " << next);
2947  }
2948  if (Settings::mc_sat && next == lit_Undef) {
2949  assert(mMCSAT.fullConsistencyCheck());
2950  assert(mMCSAT.theoryAssignmentComplete());
2951  SMTRAT_LOG_DEBUG("smtrat.sat", "No further theory variable to assign.");
2952  mCurrentAssignmentConsistent = SAT;
2953  }
2954 
2955  SMTRAT_LOG_DEBUG("smtrat.sat", "-> " << next);
2956  if( next == lit_Undef )
2957  {
2958  SMTRAT_LOG_DEBUG("smtrat.sat", "Entering SAT case");
2959  if( mReceivedFormulaPurelyPropositional || mCurrentAssignmentConsistent == SAT )
2960  {
2961  // Model found:
2962  if (Settings::mc_sat) assert(mMCSAT.is_consistent());
2963  return l_True;
2964  }
2965  else
2966  {
2967  SMTRAT_LOG_DEBUG("smtrat.sat", "Current assignment is unknown");
2968  assert( mCurrentAssignmentConsistent == UNKNOWN );
2969  if( Settings::stop_search_after_first_unknown )
2970  return l_Undef;
2971  else
2972  {
2973  mExcludedAssignments = true;
2974  learnt_clause.clear();
2975  for( auto subformula = rPassedFormula().begin(); subformula != rPassedFormula().end(); ++subformula )
2976  learnt_clause.push( neg( getLiteral( subformula->formula() ) ) );
2977  addClause( learnt_clause, LEMMA_CLAUSE );
2978  SMTRAT_LOG_DEBUG("smtrat.sat", "Storing lemmas");
2979  confl = storeLemmas();
2980  if( confl != CRef_Undef )
2981  unknown_excludes.push( confl );
2982  }
2983  }
2984  }
2985  if( mReceivedFormulaPurelyPropositional || Settings::stop_search_after_first_unknown || next != lit_Undef )
2986  {
2987  // Increase decision level and enqueue 'next'
2988  newDecisionLevel();
2989  assert( bool_value( next ) == l_Undef );
2990  #ifdef DEBUG_SATMODULE
2991  std::cout << "### Decide " << (sign(next) ? "-" : "" ) << var(next) << std::endl;
2992  #endif
2993  SMTRAT_CHECKPOINT("nlsat", "decision", next);
2994  uncheckedEnqueue( next );
2995  }
2996  }
2997 
2998  // CONFLICT
2999  if( confl != CRef_Undef )
3000  {
3001  SMTRAT_LOG_DEBUG("smtrat.sat", "Hit conflicting clause " << confl);
3002  conflicts++;
3003  conflictC++;
3004  #ifdef SMTRAT_DEVOPTION_Statistics
3005  mMCSATStatistics.booleanConflict();
3006  #endif
3007 
3008  if( decisionLevel() <= assumptions.size() )
3009  {
3010  if( !mReceivedFormulaPurelyPropositional && !Settings::stop_search_after_first_unknown && mExcludedAssignments ) {
3011  SMTRAT_LOG_DEBUG("smtrat.sat", "Return undef due to excluded: " << mExcludedAssignments);
3012  return l_Undef;
3013  }
3014  // TODO is that needed here?!?
3015  // assert(mMCSAT.is_consistent());
3016  return l_False;
3017  }
3018 
3019  // DPLL::resolve_conflict()
3020  handleConflict( confl );
3021  }
3022  }
3023  }
3024 
3025  template<class Settings>
3026  void SATModule<Settings>::handleConflict( CRef _confl )
3027  {
3028  learnt_clause.clear();
3029  assert( _confl != CRef_Undef );
3030  SMTRAT_LOG_DEBUG("smtrat.sat", "Conflict clause: " << _confl);
3031 
3032  int backtrack_level;
3033 // bool conflictClauseNotAsserting = analyze( _confl, learnt_clause, backtrack_level );
3034  bool newClause = analyze( _confl, learnt_clause, backtrack_level );
3035  SMTRAT_LOG_DEBUG("smtrat.sat", "Analyze produces new clause? " << newClause);
3036  if (learnt_clause.size() == 0) std::exit(32);
3037  assert( learnt_clause.size() > 0 );
3038 
3039  #ifdef DEBUG_SATMODULE
3040  printClause( learnt_clause, true, std::cout, "### Asserting clause: " );
3041  std::cout << "### Backtrack to level " << backtrack_level << std::endl;
3042  std::cout << "###" << std::endl;
3043  #endif
3044 
3045  SMTRAT_CHECKPOINT("nlsat", "backtrack", backtrack_level);
3046 
3047  if(Settings::mc_sat) {
3048  cancelUntil( backtrack_level, true );
3049  } else {
3050  cancelUntil( backtrack_level );
3051  }
3052 
3053  #ifdef DEBUG_SATMODULE
3054  print(std::cout, "###");
3055  #endif
3056 
3057  if (Settings::mc_sat) {
3058  //for (int i = 0; i < learnt_clause.size(); i++) {
3059  // valueAndUpdate(learnt_clause[i]);
3060  //}
3061  Minisat::sort(learnt_clause, lemma_lt(*this));
3062  }
3063 
3064  SMTRAT_LOG_DEBUG("smtrat.sat.mc", "Learning clause " << learnt_clause);
3065  SMTRAT_LOG_DEBUG("smtrat.sat.mc", "Conflict clause " << _confl);
3066  assert( value( learnt_clause[0] ) == l_Undef );
3067  if( learnt_clause.size() == 1 )
3068  {
3069  SMTRAT_CHECKPOINT("nlsat", "new-assumption", learnt_clause[0]);
3070  assert((Settings::mc_sat && decisionLevel() <= assumptions.size()) || (!Settings::mc_sat && decisionLevel() == assumptions.size()));
3071  assumptions.push( learnt_clause[0] );
3072  // assumptions are inserted in search()
3073  // newDecisionLevel();
3074  // uncheckedEnqueue( learnt_clause[0] );
3075  }
3076  else
3077  {
3078  if (newClause) {
3079  // learnt clause is the asserting clause.
3080  _confl = ca.alloc( learnt_clause, CONFLICT_CLAUSE );
3081  learnts.push( _confl );
3082  attachClause( _confl );
3083  claBumpActivity( ca[_confl] );
3084  }
3085  if (Settings::mc_sat) {
3086  if (value(learnt_clause[1]) == l_False) {
3087  SMTRAT_CHECKPOINT("nlsat", "propagation", _confl, learnt_clause[0]);
3088  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Propagate asserting clause");
3089  uncheckedEnqueue( learnt_clause[0], _confl );
3090  } else if (Settings::mcsat_backjump_decide) {
3091  #ifdef SMTRAT_DEVOPTION_Statistics
3092  mMCSATStatistics.backjumpDecide();
3093  #endif
3094  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Decide literal as clause is not asserting");
3095  assert(assumptions.size() <= backtrack_level);
3096  newDecisionLevel();
3097  uncheckedEnqueue( learnt_clause[0], _confl );
3098  }
3099  } else {
3100  SMTRAT_CHECKPOINT("nlsat", "propagation", _confl, learnt_clause[0]);
3101  uncheckedEnqueue( learnt_clause[0], _confl );
3102  }
3103  decrementLearntSizeAdjustCnt();
3104  }
3105 
3106  varDecayActivity();
3107  claDecayActivity();
3108  }
3109 
3110  template<class Settings>
3111  void SATModule<Settings>::decrementLearntSizeAdjustCnt()
3112  {
3113  if( --learntsize_adjust_cnt == 0 )
3114  {
3115  learntsize_adjust_confl *= learntsize_adjust_inc;
3116  learntsize_adjust_cnt = (int)learntsize_adjust_confl;
3117  max_learnts *= learntsize_inc;
3118 
3119  if( verbosity >= 1 )
3120  printf( "| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n",
3121  (int)conflicts,
3122  (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]),
3123  nClauses(),
3124  (int)clauses_literals,
3125  (int)max_learnts,
3126  nLearnts(),
3127  (double)learnts_literals / nLearnts(),
3128  progressEstimate() * 100 );
3129  }
3130  }
3131 
3132  template<class Settings>
3133  bool SATModule<Settings>::fullAssignment()
3134  {
3135  return var_scheduler.empty();
3136  }
3137 
3138  template<class Settings>
3139  Lit SATModule<Settings>::pickBranchLit()
3140  {
3141 
3142 
3143  if( /*!mReceivedFormulaPurelyPropositional &&*/ Settings::check_active_literal_occurrences && false)
3144  {
3145  Var next_var = var_Undef;
3146  while( next_var == var_Undef && !mPropagationFreeDecisions.empty() )
3147  {
3148  Lit l = mPropagationFreeDecisions.back();
3149  mPropagationFreeDecisions.pop_back();
3150  if( assigns[var(l)] == l_Undef )
3151  return l;
3152  }
3153  }
3154  SMTRAT_LOG_TRACE("smtrat.sat", "Retrieving next variable from the heap");
3155  Lit next = var_scheduler.pop();
3156  if (Settings::mc_sat) {
3157  std::vector<Minisat::Var> vars;
3158  while(mMCSAT.hasUnassignedDep(Minisat::var(next))) {
3159  SMTRAT_LOG_TRACE("smtrat.sat", "Variable " << Minisat::var(next) << " has undecided dependency");
3160  vars.push_back(Minisat::var(next));
3161  assert(!var_scheduler.empty());
3162  next = var_scheduler.pop();
3163  }
3164  for (auto it = vars.rbegin(); it != vars.rend(); it++) {
3165  var_scheduler.insert(*it);
3166  }
3167  }
3168  assert(next == lit_Undef || (decision[Minisat::var(next)] && bool_value(next) == l_Undef));
3169  assert(!Settings::mc_sat || next == lit_Undef || mBooleanConstraintMap[Minisat::var(next)].first == nullptr || mBooleanConstraintMap[Minisat::var(next)].first->reabstraction.type() != carl::FormulaType::VARASSIGN);
3170  SMTRAT_LOG_TRACE("smtrat.sat", "Got " << next);
3171  return next;
3172  }
3173 
3174  template<class Settings>
3175  bool SATModule<Settings>::analyze( CRef confl, vec<Lit>& out_learnt, int& out_btlevel )
3176  {
3177  #ifdef DEBUG_SATMODULE
3178  std::cout << "### Analyze" << std::endl;
3179  std::cout << "######################################################################" << std::endl;
3180  std::cout << "###" << std::endl; printBooleanConstraintMap(std::cout, "###");
3181  std::cout << "###" << std::endl; printClauses( clauses, "Clauses", std::cout, "### ", 0, false, false );
3182  std::cout << "###" << std::endl; printClauses( learnts, "Learnts", std::cout, "### ", 0, false, false );
3183  std::cout << "###" << std::endl; printCurrentAssignment( std::cout, "### " );
3184  std::cout << "###" << std::endl; printDecisions( std::cout, "### " );
3185  std::cout << "###" << std::endl << "Assumptions: " << assumptions << std::endl;
3186  std::cout << "###" << std::endl;
3187  #endif
3188  assert( confl != CRef_Undef );
3189  SMTRAT_LOG_DEBUG("smtrat.sat", "Analyzing conflict " << ca[confl] << " on DL" << decisionLevel());
3190  sat::detail::validateClause(ca[confl], mMinisatVarMap, mBooleanConstraintMap, Settings::validate_clauses);
3191  int pathC = 0; // number of literals that must be resolved
3192  int resolutionSteps = -1;
3193  Lit p = lit_Undef;
3194 
3195  // Generate conflict clause:
3196  //
3197  out_learnt.push(); // (leave room for the asserting literal)
3198  int index = trail.size() - 1;
3199  for (int i = 0; i < seen.size(); i++) seen[i] = 0;
3200 
3201  std::set<Minisat::Var> seenTheoryVars; // for MCSAT theory var bumping
3202 
3203  do
3204  {
3205  SMTRAT_LOG_DEBUG("smtrat.sat", "out_learnt = " << out_learnt);
3206 
3207  assert( confl != CRef_Undef ); // (otherwise should be UIP)
3208 
3209  bool gotClause = true;
3210  if (Settings::mc_sat && confl == CRef_TPropagation) {
3211  SMTRAT_LOG_DEBUG("smtrat.sat", "Found " << p << " to be result of theory propagation.");
3212  #ifdef SMTRAT_DEVOPTION_Statistics
3213  mMCSATStatistics.usedLazyExplanation();
3214  #endif
3215  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Current state: " << mMCSAT);
3216  cancelIncludingLiteral(p); // does not affect decision levels of literals processed later nor decisionLevel()
3217  auto explanation = mcsat::resolveExplanation(mMCSAT.explainTheoryPropagation(p));
3218 
3219  vec<Lit> expClause;
3220  if (explanation.is_nary()) {
3221  for (const auto& f: explanation) {
3222  expClause.push(createLiteral(f));
3223  }
3224  }
3225  else {
3226  expClause.push(createLiteral(explanation));
3227  }
3228  SMTRAT_LOG_DEBUG("smtrat.sat", "Explanation for " << p << ": " << expClause);
3229 
3230  if (expClause.size() > 1) {
3231  Minisat::sort(expClause, lemma_lt(*this));
3232  confl = ca.alloc(expClause, LEMMA_CLAUSE);
3233  SMTRAT_LOG_DEBUG("smtrat.sat", "Explanation for " << p << ": " << ca[confl]);
3234  if (Settings::mcsat_learn_lazy_explanations) {
3235  clauses.push(confl);
3236  attachClause(confl);
3237  }
3238  } else {
3239  // we can safely do this as we backtracked using cancelIncludingLiteral
3240  SMTRAT_LOG_DEBUG("smtrat.sat", "Literal " << p << " is an assumption");
3241  assumptions.push(expClause[0]);
3242  SMTRAT_LOG_DEBUG("smtrat.sat", "\tpushing = " << expClause[0] << " to out_learnt");
3243  out_learnt.push(expClause[0]);
3244  gotClause = false;
3245  }
3246  }
3247 
3248  if (gotClause) {
3249  Clause& c = ca[confl];
3250  sat::detail::validateClause(c, mMinisatVarMap, mBooleanConstraintMap, Settings::validate_clauses);
3251  SMTRAT_LOG_DEBUG("smtrat.sat", "c = " << c);
3252  if( c.learnt() )
3253  claBumpActivity( c );
3254 
3255  // assert that c[0] is actually p
3256  for( int j = (p == lit_Undef) ? 0 : 0; j < c.size(); j++ )
3257  {
3258  Lit q = c[j];
3259  if (q == p) continue;
3260  auto qlevel = theory_level(var(q));
3261  SMTRAT_LOG_DEBUG("smtrat.sat", "\tLooking at literal " << q << " from level " << qlevel);
3262  SMTRAT_LOG_DEBUG("smtrat.sat", "\tseen? " << static_cast<bool>(seen[var(q)]));
3263  assert(value(q) == l_False);
3264 
3265  if( !seen[var( q )] && qlevel > 0 )
3266  {
3267  SMTRAT_LOG_DEBUG("smtrat.sat", "\tNot seen yet, level = " << qlevel);
3268  varBumpActivity( var( q ) );
3269  if (Settings::mc_sat) {
3270  for (auto tvar : mMCSAT.theoryVars(var(q))) {
3271  seenTheoryVars.insert(tvar);
3272  }
3273  }
3274  seen[var( q )] = 1;
3275  //if (Settings::mc_sat && reason(var(q)) == CRef_TPropagation) {
3276  // SMTRAT_LOG_DEBUG("smtrat.sat", "\t" << q << " is result of theory propagation");
3277  // pathC++;
3278  // SMTRAT_LOG_DEBUG("smtrat.sat", "\tTo process: " << q << ", pathC = " << pathC);
3279  //} else {
3280  if (bool_value(q) == l_Undef) {
3281  out_learnt.push(q);
3282  SMTRAT_LOG_DEBUG("smtrat.sat", "\tq is false by theory assignment, forwarding to out_learnt.");
3283  }
3284  else if( level(var(q)) == qlevel && qlevel >= decisionLevel() ) {
3285  pathC++;
3286  SMTRAT_LOG_DEBUG("smtrat.sat", "\tTo process: " << q << ", pathC = " << pathC);
3287  }
3288  else {
3289  SMTRAT_LOG_DEBUG("smtrat.sat", "\tpushing = " << q << " to out_learnt");
3290  out_learnt.push( q );
3291  }
3292  //}
3293  }
3294  }
3295 
3296  if (!Settings::mcsat_learn_lazy_explanations) {
3297  ca.free(confl);
3298  }
3299  }
3300 
3301  // Select next clause to look at:
3302  while( !seen[var( trail[index--] )] );
3303  assert(index + 1 < trail.size());
3304  p = trail[index + 1];
3305  confl = reason( var( p ) );
3306  SMTRAT_LOG_DEBUG("smtrat.sat", "Backtracking to " << p << " with reason " << confl);
3307  seen[var( p )] = 0;
3308  pathC--;
3309  SMTRAT_LOG_DEBUG("smtrat.sat", "Still on highest DL, pathC = " << pathC);
3310  ++resolutionSteps;
3311  }
3312  while( pathC > 0 );
3313 
3314  if (Settings::mc_sat) {
3315  for (auto tvar : seenTheoryVars) {
3316  varBumpActivity(tvar);
3317  }
3318  }
3319 
3320  if (Settings::mc_sat) {
3321  bool found = false;
3322  for (int i = 1; i < out_learnt.size(); i++) {
3323  if (out_learnt[i] == ~p) found = true;
3324  }
3325  if (!found) out_learnt[0] = ~p;
3326  else {
3327  out_learnt[0] = out_learnt[out_learnt.size()-1];
3328  out_learnt.pop();
3329  }
3330  } else {
3331  out_learnt[0] = ~p;
3332  }
3333 
3334  SMTRAT_LOG_DEBUG("smtrat.sat", "Before sorting " << out_learnt);
3335  if (Settings::mc_sat) {
3336  Minisat::sort(out_learnt, lemma_lt(*this));
3337  }
3338  SMTRAT_LOG_DEBUG("smtrat.sat", "After sorting " << out_learnt);
3339 
3340  // Simplify conflict clause:
3341  //
3342  int i, j;
3343  out_learnt.copyTo( analyze_toclear );
3344  if( !Settings::mc_sat && ccmin_mode == 2 )
3345  {
3346  uint32_t abstract_level = 0;
3347  for( i = 1; i < out_learnt.size(); i++ )
3348  abstract_level |= abstractLevel( var( out_learnt[i] ) ); // (maintain an abstraction of levels involved in conflict)
3349 
3350  for( i = j = 1; i < out_learnt.size(); i++ )
3351  if( reason( var( out_learnt[i] ) ) == CRef_Undef ||!litRedundant( out_learnt[i], abstract_level ) )
3352  out_learnt[j++] = out_learnt[i];
3353 
3354  }
3355  else if( !Settings::mc_sat && ccmin_mode == 1 )
3356  {
3357  for( i = j = 1; i < out_learnt.size(); i++ )
3358  {
3359  Var x = var( out_learnt[i] );
3360 
3361  if( reason( x ) == CRef_Undef )
3362  out_learnt[j++] = out_learnt[i];
3363  else
3364  {
3365  Clause& c = ca[reason( var( out_learnt[i] ) )];
3366  for( int k = 1; k < c.size(); k++ )
3367  if( !seen[var( c[k] )] && level( var( c[k] ) ) > 0 )
3368  {
3369  out_learnt[j++] = out_learnt[i];
3370  break;
3371  }
3372  }
3373  }
3374  }
3375  else
3376  i = j = out_learnt.size();
3377 
3378  max_literals += (uint64_t)out_learnt.size();
3379  out_learnt.shrink( i - j );
3380  tot_literals += (uint64_t)out_learnt.size();
3381 
3382  // Find correct backtrack level:
3383  //
3384  if( out_learnt.size() == 1 )
3385  out_btlevel = 0;
3386  else if (Settings::mc_sat) {
3387  SMTRAT_LOG_DEBUG("smtrat.sat", "Figuring out level to backtrack to for " << out_learnt);
3388  std::vector<int> levels;
3389  for( int i = 0; i < out_learnt.size(); i++ ) {
3390  // Attention: theory_level gives the latest level that a literal was assigned (first from theory, then by decision)
3391  // Here, we need the earliest!
3392  levels.emplace_back(min_theory_level(var(out_learnt[i])));
3393  SMTRAT_LOG_DEBUG("smtrat.sat", out_learnt[i] << " is assigned at " << levels.back());
3394  }
3395  std::sort(levels.rbegin(), levels.rend());
3396  assert(levels.size() > 0);
3397  if (!Settings::mcsat_backjump_decide) {
3398  levels.erase(std::unique(levels.begin(), levels.end()), levels.end());
3399  if (levels.size() > 1) {
3400  out_btlevel = levels[1];
3401  } else {
3402  out_btlevel = levels[0]-1;
3403  }
3404  } else {
3405  if (levels.size() > 1) {
3406  if (levels[0] == levels[1]) {
3407  // levels[0] is a theory decision deciding more than one literal in the explanation clause
3408  out_btlevel = levels[0]-1;
3409  } else {
3410  levels.erase(std::unique(levels.begin(), levels.end()), levels.end());
3411  out_btlevel = levels[1];
3412  }
3413  } else {
3414  out_btlevel = levels[0]-1;
3415  }
3416  }
3417  SMTRAT_LOG_DEBUG("smtrat.sat", "-> " << out_btlevel << " (" << out_learnt << ")");
3418  assert(out_btlevel >= 0);
3419  } else {
3420  SMTRAT_LOG_DEBUG("smtrat.sat", "Figuring out level to backtrack to for " << out_learnt);
3421  int max_i = 0;
3422  int max_lvl = 0;
3423  // Find the first literal assigned at the next-highest level:
3424  for( int i = 1; i < out_learnt.size(); i++ ) {
3425  assert(reason(var(out_learnt[i])) != CRef_TPropagation);
3426  int currentLitLevel = theory_level(var(out_learnt[i]));
3427  SMTRAT_LOG_DEBUG("smtrat.sat", out_learnt[i] << " is assigned at " << currentLitLevel);
3428  if (currentLitLevel > max_lvl) {
3429  max_i = i;
3430  max_lvl = currentLitLevel;
3431  }
3432  }
3433  SMTRAT_LOG_DEBUG("smtrat.sat", out_learnt[max_i] << " is max-level literal at " << max_lvl);
3434  // Swap-in this literal at index 1:
3435  Lit p = out_learnt[max_i];
3436  out_learnt[max_i] = out_learnt[1];
3437  out_learnt[1] = p;
3438  out_btlevel = max_lvl;
3439  SMTRAT_LOG_DEBUG("smtrat.sat", "-> " << out_btlevel << " (" << out_learnt << ")");
3440  }
3441 
3442  for( int j = 0; j < analyze_toclear.size(); j++ )
3443  seen[var( analyze_toclear[j] )] = 0; // ('seen[]' is now cleared)
3444  SMTRAT_LOG_DEBUG("smtrat.sat", "Performed " << resolutionSteps << " steps");
3445  return resolutionSteps > 0;
3446  }
3447 
3448  template<class Settings>
3449  bool SATModule<Settings>::litRedundant( Lit p, uint32_t abstract_levels )
3450  {
3451  analyze_stack.clear();
3452  analyze_stack.push( p );
3453  int top = analyze_toclear.size();
3454  while( analyze_stack.size() > 0 )
3455  {
3456  CRef c_reason = reason(var(analyze_stack.last()));
3457  assert( c_reason != CRef_Undef );
3458  Clause& c = ca[c_reason];
3459  int c_size = c.size();
3460  analyze_stack.pop();
3461 
3462  for( int i = 1; i < c_size; i++ )
3463  {
3464  Lit p = ca[c_reason][i];
3465  if( !seen[var( p )] && level( var( p ) ) > 0 )
3466  {
3467  if( reason( var( p ) ) != CRef_Undef && (abstractLevel( var( p ) ) & abstract_levels) != 0 )
3468  {
3469  seen[var( p )] = 1;
3470  analyze_stack.push( p );
3471  analyze_toclear.push( p );
3472  }
3473  else
3474  {
3475  for( int j = top; j < analyze_toclear.size(); j++ )
3476  seen[var( analyze_toclear[j] )] = 0;
3477  analyze_toclear.shrink( analyze_toclear.size() - top );
3478  return false;
3479  }
3480  }
3481  }
3482  }
3483 
3484  return true;
3485  }
3486 
3487  template<class Settings>
3488  void SATModule<Settings>::uncheckedEnqueue( Lit p, CRef from )
3489  {
3490  SMTRAT_LOG_DEBUG("smtrat.sat", "Enqueue " << p << " from " << from);
3491  assert( bool_value( p ) == l_Undef );
3492  if( Settings::check_if_all_clauses_are_satisfied && !mReceivedFormulaPurelyPropositional && mNumberOfSatisfiedClauses < (size_t)clauses.size() )
3493  {
3494  auto litClausesIter = mLiteralClausesMap.find( Minisat::toInt( p ) );
3495  if( litClausesIter != mLiteralClausesMap.end() )
3496  {
3497  for( CRef cl : litClausesIter->second )
3498  {
3499  if( !satisfied( ca[cl] ) )
3500  {
3501  assert( mNumberOfSatisfiedClauses < (size_t)clauses.size() );
3502  ++mNumberOfSatisfiedClauses;
3503  }
3504  }
3505  }
3506  }
3507  if( /*!mReceivedFormulaPurelyPropositional &&*/ Settings::check_active_literal_occurrences )
3508  {
3509  // Check clauses which are going to be satisfied by this assignment.
3510  size_t v = (size_t)var(p);
3511  const std::vector<CRef>& nowSatisfiedClauses = sign(p) ? mLiteralsClausesMap[v].negatives() : mLiteralsClausesMap[v].positives();
3512  for( CRef cr : nowSatisfiedClauses )
3513  {
3514  const Clause& c = ca[cr];
3515  // Check if clause is not yet satisfied.
3516  if( !bool_satisfied(c) )
3517  {
3518  for( int i = 0; i < c.size(); ++i )
3519  {
3520  size_t v = (size_t)var(c[i]);
3521  std::pair<size_t,size_t>& litActOccs = mLiteralsActivOccurrences[v];
3522  if( sign(c[i]) )
3523  {
3524  assert( litActOccs.second > 0 );
3525  --(litActOccs.second);
3526  }
3527  else
3528  {
3529  assert( litActOccs.first > 0 );
3530  --(litActOccs.first);
3531  }
3532  if( litActOccs.first == 0 )
3533  {
3534  if( litActOccs.second == 0 )
3535  decision[var(c[i])] = false;
3536  else
3537  mPropagationFreeDecisions.push_back( mkLit( var(c[i]), true ) );
3538  }
3539  else
3540  {
3541  if( litActOccs.second == 0 )
3542  mPropagationFreeDecisions.push_back( mkLit( var(c[i]), false ) );
3543  }
3544  }
3545  }
3546  }
3547  }
3548  assigns[var( p )] = Minisat::lbool( !sign( p ) );
3549  if (Settings::mc_sat) {
3550  mMCSAT.doBooleanAssignment(p);
3551  }
3552  if( !mReceivedFormulaPurelyPropositional && mBooleanConstraintMap[var( p )].first != nullptr )
3553  {
3554  Abstraction* abstrptr = sign( p ) ? mBooleanConstraintMap[var( p )].second : mBooleanConstraintMap[var( p )].first;
3555  assert(abstrptr != nullptr);
3556  Abstraction& abstr = *abstrptr;
3557  SMTRAT_LOG_DEBUG("smtrat.sat", "Adding literal " << p << ": " << abstr.reabstraction);
3558  if (abstr.updatedReabstraction) {
3559  mChangedBooleans.push_back( var( p ) );
3560  } else {
3561  if (!abstr.reabstraction.is_true() && abstr.consistencyRelevant && (
3562  abstr.reabstraction.type() == carl::FormulaType::UEQ ||
3563  abstr.reabstraction.type() == carl::FormulaType::BITVECTOR ||
3564  abstr.reabstraction.type() == carl::FormulaType::VARCOMPARE ||
3565  abstr.reabstraction.type() == carl::FormulaType::VARASSIGN ||
3566  abstr.reabstraction.constraint().is_consistent() != 1
3567  ))
3568  {
3569  if( ++abstr.updateInfo > 0 )
3570  {
3571  unsigned res = currentlySatisfiedByBackend( abstr.reabstraction );
3572  if( res != 1 )
3573  {
3574  mCurrentAssignmentConsistent = UNKNOWN;
3575  }
3576  mChangedBooleans.push_back( var( p ) );
3577  }
3578  }
3579  }
3580  vardata[var( p )] = VarData( from, decisionLevel(), trail.size() );
3581  trail.push_( p );
3582  }
3583  else
3584  {
3585  vardata[var( p )] = VarData( from, decisionLevel(), trail.size() );
3586  trail.push_( p );
3587  }
3588 
3589  // Save reasons (clauses) implicating a variable value
3590  if (isLemmaLevel(LemmaLevel::NORMAL) && decisionLevel() == 0 && !mComputeAllSAT)
3591  {
3592  if ( from != CRef_Undef) {
3593  // Find corresponding formula
3594  auto iter = mClauseInformation.find( from );
3595  assert( iter != mClauseInformation.end() );
3596  FormulaT formula = iter->second.mOrigins.back();
3597  assert( formula.property_holds(carl::PROP_IS_A_CLAUSE) && formula.property_holds(carl::PROP_CONTAINS_BOOLEAN) );
3598 
3599  // Get lemmas for variable
3600  // Notice: new pair is inserted if not already contained
3601  FormulasT* pFormulas = &mPropagatedLemmas[ var(p) ];
3602  // Insert reason for variable
3603  pFormulas->push_back( formula );
3604 
3605  // Find formulas for contained variables
3606  auto vars = carl::boolean_variables(formula);
3607  for (const auto& v: vars) {
3608  BooleanVarMap::const_iterator itVar = mBooleanVarMap.find( v );
3609  assert( itVar != mBooleanVarMap.end() );
3610  Minisat::Var var = itVar->second;
3611  // Find possible formulas for variable
3612  VarLemmaMap::const_iterator itFormulas = mPropagatedLemmas.find( var );
3613  if ( itFormulas != mPropagatedLemmas.end() )
3614  {
3615  // Insert formulas from contained variable into set for current variable
3616  pFormulas->insert( pFormulas->end(), itFormulas->second.begin(), itFormulas->second.end() );
3617  }
3618  }
3619  }
3620  }
3621  if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
3622  {
3623  auto iter = mTseitinVarShadows.find( (signed) var(p) );
3624  if( iter != mTseitinVarShadows.end() )
3625  {
3626  for( signed var : iter->second )
3627  {
3628  incrementTseitinShadowOccurrences(var);
3629  }
3630  }
3631  }
3632  }
3633 
3634  template<class Settings>
3635  CRef SATModule<Settings>::propagate()
3636  {
3637  CRef confl = CRef_Undef;
3638  int num_props = 0;
3639  watches.cleanAll();
3640 
3641  while( qhead < trail.size() )
3642  {
3643  Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate.
3644  vec<Watcher>& ws = watches[p];
3645  Watcher * i, *j, *end;
3646  num_props++;
3647  SMTRAT_LOG_DEBUG("smtrat.sat.bcp", "Current literal: " << p);
3648 
3649  for( i = j = (Watcher*)ws, end = i + ws.size(); i != end; )
3650  {
3651  SMTRAT_LOG_DEBUG("smtrat.sat.bcp", "Considering clause " << i->cref);
3652  // Try to avoid inspecting the clause:
3653  Lit blocker = i->blocker;
3654  if( value( blocker ) == l_True )
3655  {
3656  SMTRAT_LOG_TRACE("smtrat.sat.bcp", "Skipping clause " << i->cref << " due to blocker " << i->blocker);
3657  *j++ = *i++;
3658  continue;
3659  }
3660 
3661  // Make sure the false literal is data[1]:
3662  CRef cr = i->cref;
3663  Clause& c = ca[cr];
3664  SMTRAT_LOG_TRACE("smtrat.sat.bcp", "Analyzing clause " << c);
3665  Lit false_lit = ~p;
3666  if( c[0] == false_lit )
3667  c[0] = c[1], c[1] = false_lit;
3668  assert( c[1] == false_lit );
3669  i++;
3670 
3671  SMTRAT_LOG_TRACE("smtrat.sat.bcp", "Clause is now " << c << " after moving the false literal");
3672 
3673  // If 0th watch is true, then clause is already satisfied.
3674  Lit first = c[0];
3675  Watcher w = Watcher( cr, first );
3676  if( first != blocker && value( first ) == l_True )
3677  {
3678  SMTRAT_LOG_DEBUG("smtrat.sat.bcp", "Clause " << c << " is satisfied by " << first);
3679  *j++ = w;
3680  continue;
3681  }
3682 
3683  // Look for new watch:
3684  for( int k = 2; k < c.size(); k++ ) {
3685  if (Settings::mc_sat) {
3686  if (value(c[k]) == l_Undef && theoryValue(c[k]) == l_False) {
3687  assert(false);
3688  }
3689  }
3690  if( value( c[k] ) != l_False )
3691  {
3692  c[1] = c[k];
3693  c[k] = false_lit;
3694  watches[~c[1]].push( w );
3695  SMTRAT_LOG_TRACE("smtrat.sat.bcp", "Clause is now " << c << " after setting " << c[1] << " as new watch");
3696  goto NextClause;
3697  }
3698  }
3699 
3700  SMTRAT_LOG_TRACE("smtrat.sat.bcp", "Clause is now " << c << " after no new watch was found");
3701 
3702  // Did not find watch -- clause is unit under assignment:
3703  *j++ = w;
3704  if( value( first ) == l_False )
3705  {
3706  SMTRAT_LOG_DEBUG("smtrat.sat.bcp", "Clause is conflicting " << c);
3707  SMTRAT_CHECKPOINT("nlsat", "conflict-clause", cr);
3708  confl = cr;
3709  qhead = trail.size();
3710  // Copy the remaining watches:
3711  while( i < end )
3712  *j++ = *i++;
3713  }
3714  else
3715  {
3716  SMTRAT_LOG_DEBUG("smtrat.sat.bcp", "Clause is propagating " << c);
3717  if (Settings::mc_sat && value(first) != l_Undef) {
3718  assert(value(first) != l_Undef);
3719  } else {
3720  SMTRAT_CHECKPOINT("nlsat", "propagation", cr, first);
3721  assert( value( first ) == l_Undef );
3722  uncheckedEnqueue( first, cr );
3723  #ifdef SMTRAT_DEVOPTION_Statistics
3724  mStatistics.propagate();
3725  #endif
3726  }
3727  }
3728 
3729 NextClause:
3730  ;
3731  }
3732  ws.shrink( (int) (i - j) );
3733  }
3734  propagations += (uint64_t)num_props;
3735 // simpDB_props -= (uint64_t)num_props;
3736  SMTRAT_LOG_TRACE("smtrat.sat.bcp", "Returning " << confl);
3737  return confl;
3738  }
3739 
3740  struct reduceDB_lt
3741  {
3742  ClauseAllocator& ca;
3743 
3744  reduceDB_lt( ClauseAllocator& ca_ ):
3745  ca( ca_ )
3746  {}
3747  bool operator ()( CRef x, CRef y )
3748  {
3749  return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity());
3750  }
3751  };
3752 
3753  template<class Settings>
3754  void SATModule<Settings>::reduceDB()
3755  {
3756  int i, j;
3757  double extra_lim = cla_inc / learnts.size(); // Remove any clause below this activity
3758 
3759  Minisat::sort( learnts, reduceDB_lt( ca ) );
3760  // Don't delete binary or locked clauses. From the rest, delete clauses from the first half
3761  // and clauses with activity smaller than 'extra_lim':
3762  for( i = j = 0; i < learnts.size(); i++ )
3763  {
3764  Clause& c = ca[learnts[i]];
3765  if( c.type() != PERMANENT_CLAUSE && c.size() > 2 && !locked( c ) && (i < learnts.size() / 2 || c.activity() < extra_lim) )
3766 // if( c.size() > 2 && !locked( c ) && (i < learnts.size() / 2 || c.activity() < extra_lim) )
3767  {
3768  removeClause( learnts[i] );
3769  }
3770  else
3771  learnts[j++] = learnts[i];
3772  }
3773  learnts.shrink( i - j );
3774  checkGarbage();
3775  }
3776 
3777  template<class Settings>
3778  void SATModule<Settings>::clearLearnts( int n )
3779  {
3780  for( int i = n; i < learnts.size(); ++i )
3781  {
3782  removeClause( learnts[i] );
3783  }
3784  learnts.shrink( learnts.size() - n );
3785  }
3786 
3787  template<class Settings>
3788  void SATModule<Settings>::removeSatisfied( vec<CRef>& cs )
3789  {
3790  int i, j;
3791  for( i = j = 0; i < cs.size(); i++ )
3792  {
3793  Clause& c = ca[cs[i]];
3794  if( satisfied( c ) )
3795  removeClause( cs[i] );
3796  else
3797  cs[j++] = cs[i];
3798  }
3799  cs.shrink( i - j );
3800  }
3801 
3802  template<class Settings>
3803  void SATModule<Settings>::simplify()
3804  {
3805  assert( decisionLevel() == assumptions.size() );
3806  #ifdef DEBUG_SATMODULE
3807  std::cout << __func__ << std::endl;
3808  #endif
3809  while( ok )
3810  {
3811  if( propagate() != CRef_Undef )
3812  {
3813  SMTRAT_LOG_DEBUG("smtrat.sat", "ok = false");
3814  ok = false;
3815  return;
3816  }
3817  if( nAssigns() == simpDB_assigns )// || (simpDB_props > 0) )
3818  {
3819  return;
3820  }
3821  // Remove satisfied clauses:
3822  removeSatisfied( learnts );
3823  if( remove_satisfied ) // Can be turned off.
3824  removeSatisfied( clauses );
3825  // @todo: free somehow splitting variables, which are assigned in decision level 0 (aka assumption.size())
3826  checkGarbage();
3827  var_scheduler.rebuild();
3828  simpDB_assigns = nAssigns();
3829 // simpDB_props = (int64_t)(clauses_literals + learnts_literals); // (shouldn't depend on stats really, but it will do for now)
3830  processLemmas();
3831  }
3832  }
3833 
3834  template<class Settings>
3835  bool SATModule<Settings>::processLemmas()
3836  {
3837  bool lemmasLearned = false;
3838  std::vector<Module*>::const_iterator backend = usedBackends().begin();
3839  while( backend != usedBackends().end() )
3840  {
3841  // Learn the lemmas.
3842  (*backend)->updateLemmas();
3843  if( !(mCurrentAssignmentConsistent == SAT && fullAssignment()) )
3844  {
3845  for( const auto& lem : (*backend)->lemmas() )
3846  {
3847  if( lem.mLemma.type() != carl::FormulaType::TRUE )
3848  {
3849  SMTRAT_LOG_DEBUG("smtrat.sat", "Found a lemma: " << lem.mLemma);
3850  SMTRAT_VALIDATION_ADD("smtrat.modules.sat.lemma",(*backend)->moduleName() + "_lemma",FormulaT( carl::FormulaType::NOT, lem.mLemma ), false);
3851  int numOfLearnts = mLemmas.size();
3852  /*{
3853  std::lock_guard<std::mutex> lock( Module::mOldSplittingVarMutex );
3854  std::cout << __func__ << ":" << __LINE__ << ": " << (*backend)->moduleName() << " (" <<(*backend)->id() << ")" << std::endl;
3855  std::cout << lem.mLemma << std::endl;
3856  }*/
3857  addClauses( lem.mLemma, lem.mLemmaType == LemmaType::PERMANENT ? PERMANENT_CLAUSE : LEMMA_CLAUSE );
3858  if( numOfLearnts < mLemmas.size() )
3859  lemmasLearned = true;
3860  }
3861  }
3862  }
3863  (*backend)->clearLemmas();
3864  ++backend;
3865  }
3866  return lemmasLearned;
3867  }
3868 
3869  template<class Settings>
3870  void SATModule<Settings>::learnTheoryConflicts()
3871  {
3872  std::vector<Module*>::const_iterator backend = usedBackends().begin();
3873  while( backend != usedBackends().end() )
3874  {
3875  const std::vector<FormulaSetT>& infSubsets = (*backend)->infeasibleSubsets();
3876  #ifdef DEBUG_SATMODULE
3877  for (const auto& iss : infSubsets) {
3878  SMTRAT_LOG_DEBUG("smtrat.sat", "Infeasible subset: " << iss);
3879  }
3880  #endif
3881  assert( (*backend)->solverState() != UNSAT || !infSubsets.empty() );
3882  for( auto infsubset = infSubsets.begin(); infsubset != infSubsets.end(); ++infsubset )
3883  {
3884  assert( !infsubset->empty() );
3885  SMTRAT_VALIDATION_ADD("smtrat.modules.sat.infeasible_subset",(*backend)->moduleName() + "_infeasible_subset",*infsubset, false);
3886  // Add the according literals to the conflict clause.
3887  vec<Lit> explanation;
3888  bool containsUpperBoundOnMinimal = false;
3889  for( auto subformula = infsubset->begin(); subformula != infsubset->end(); ++subformula )
3890  {
3891  if( mUpperBoundOnMinimal != passedFormulaEnd() && mUpperBoundOnMinimal->formula() == *subformula )
3892  {
3893  containsUpperBoundOnMinimal = true;
3894  continue;
3895  }
3896  // add literal to clause
3897  explanation.push( neg( getLiteral( *subformula ) ) );
3898  }
3899  addClause( explanation, containsUpperBoundOnMinimal ? PERMANENT_CLAUSE : CONFLICT_CLAUSE );
3900  }
3901  ++backend;
3902  }
3903  }
3904 
3905  template<class Settings>
3906  void SATModule<Settings>::adaptConflictEvaluation( size_t& _clauseEvaluation, Lit _lit, bool _firstLiteral )
3907  {
3908  switch( Settings::conflict_clause_evaluation_strategy )
3909  {
3910  case CCES::SECOND_LEVEL_MINIMIZER:
3911  {
3912  size_t litLevel = (size_t) level( var( _lit ) );
3913  if( _firstLiteral || litLevel > _clauseEvaluation )
3914  _clauseEvaluation = litLevel;
3915  break;
3916  }
3917  case CCES::LITERALS_BLOCKS_DISTANCE:
3918  {
3919  if( _firstLiteral )
3920  {
3921  mLevelCounter.clear();
3922  _clauseEvaluation = 0;
3923  }
3924  if( mLevelCounter.insert( level( var( _lit ) ) ).second )
3925  ++_clauseEvaluation;
3926  break;
3927  }
3928  case CCES::SECOND_LEVEL_MINIMIZER_PLUS_LBD:
3929  {
3930  size_t litLevel = (size_t) level( var( _lit ) ) * (size_t) decisionLevel();
3931  if( _firstLiteral )
3932  {
3933  mLevelCounter.clear();
3934  mLevelCounter.insert( level( var( _lit ) ) );
3935  _clauseEvaluation = litLevel + 1;
3936  }
3937  else
3938  {
3939  bool levelAdded = mLevelCounter.insert( level( var( _lit ) ) ).second;
3940  if( litLevel > _clauseEvaluation )
3941  _clauseEvaluation = litLevel + mLevelCounter.size();
3942  else if( levelAdded )
3943  ++_clauseEvaluation;
3944  }
3945  break;
3946  }
3947  default:
3948  {
3949  assert( false );
3950  }
3951  }
3952  }
3953 
3954  template<class Settings>
3955  double SATModule<Settings>::progressEstimate() const
3956  {
3957  double progress = 0;
3958  double F = 1.0 / nVars();
3959 
3960  for( int i = 0; i <= decisionLevel(); i++ )
3961  {
3962  int beg = i == 0 ? 0 : trail_lim[i - 1];
3963  int end = i == decisionLevel() ? trail.size() : trail_lim[i];
3964  progress += pow( F, i ) * (end - beg);
3965  }
3966 
3967  return progress / nVars();
3968  }
3969 
3970  template<class Settings>
3971  void SATModule<Settings>::relocAll( ClauseAllocator& to )
3972  {
3973  // relocate clauses in mFormulaClausesMap
3974  for( auto& iter : mFormulaCNFInfosMap )
3975  {
3976  std::vector<CRef> tmp;
3977  for( CRef c : iter.second.mClauses )
3978  {
3979  ca.reloc( c, to );
3980  tmp.insert( tmp.end(), c );
3981  }
3982  iter.second.mClauses = std::move( tmp );
3983  }
3984 
3985  carl::FastMap<Minisat::CRef,ClauseInformation> tmp;
3986  for( auto& ciPair : mClauseInformation )
3987  {
3988  CRef c = ciPair.first;
3989  ca.reloc( c, to );
3990  tmp.emplace( c, ciPair.second );
3991  }
3992  mClauseInformation = std::move( tmp );
3993 
3994  if( Settings::check_if_all_clauses_are_satisfied )
3995  {
3996  for( auto& lcsPair : mLiteralClausesMap )
3997  {
3998  std::unordered_set<CRef>& cls = lcsPair.second;
3999  std::unordered_set<CRef> tmp;
4000  for( CRef c : cls )
4001  {
4002  ca.reloc( c, to );
4003  tmp.insert( tmp.end(), c );
4004  }
4005  cls = std::move(tmp);
4006  }
4007  }
4008 
4009  if( /*!mReceivedFormulaPurelyPropositional &&*/ Settings::check_active_literal_occurrences )
4010  {
4011  for( auto& cls : mLiteralsClausesMap )
4012  {
4013  cls.reloc( ca, to );
4014  }
4015  }
4016 
4017  var_scheduler.relocateClauses([&](Minisat::CRef& cl) { ca.reloc(cl, to); });
4018 
4019  // All watchers:
4020  //
4021  // for (int i = 0; i < watches.size(); i++)
4022  watches.cleanAll();
4023  for( int v = 0; v < nVars(); v++ )
4024  for( int s = 0; s < 2; s++ )
4025  {
4026  Lit p = mkLit( v, s );
4027  // printf(" >>> RELOCING: %s%d\n", sign(p)?"-":"", var(p)+1);
4028  vec<Watcher>& ws = watches[p];
4029  for( int j = 0; j < ws.size(); j++ )
4030  ca.reloc( ws[j].cref, to );
4031  }
4032 
4033  // All reasons:
4034  //
4035  for( int i = 0; i < trail.size(); i++ )
4036  {
4037  Var v = var( trail[i] );
4038 
4039  if( reason( v ) != CRef_Undef && (ca[reason( v )].reloced() || locked( ca[reason( v )] )) )
4040  ca.reloc( vardata[v].reason, to );
4041  }
4042 
4043  // All learnt:
4044  //
4045  for( int i = 0; i < learnts.size(); i++ )
4046  ca.reloc( learnts[i], to );
4047 
4048  // All original:
4049  //
4050  for( int i = 0; i < clauses.size(); i++ )
4051  ca.reloc( clauses[i], to );
4052  }
4053 
4054  template<class Settings>
4055  void SATModule<Settings>::garbageCollect()
4056  {
4057  // Initialize the next region to a size corresponding to the estimated utilization degree. This
4058  // is not precise but should avoid some unnecessary reallocations for the new region:
4059  ClauseAllocator to(ca.size() > ca.wasted() ? ca.size() - ca.wasted() : 0 );
4060 
4061  relocAll( to );
4062  if( verbosity >= 2 )
4063  printf( "| Garbage collection: %12d bytes => %12d bytes |\n",
4064  ca.size() * ClauseAllocator::Unit_Size,
4065  to.size() * ClauseAllocator::Unit_Size );
4066  to.moveTo( ca );
4067  }
4068 
4069  template<class Settings>
4070  Var SATModule<Settings>::mapVar( Var x, vec<Var>& map, Var& max )
4071  {
4072  if( map.size() <= x || map[x] == -1 )
4073  {
4074  map.growTo( x + 1, -1 );
4075  map[x] = max++;
4076  }
4077  return map[x];
4078  }
4079 
4080  template<class Settings>
4081  void SATModule<Settings>::print( std::ostream& _out, const std::string& _init ) const
4082  {
4083  _out << _init << std::endl;
4084  _out << _init << " ";
4085  var_scheduler.print();
4086  _out << _init << std::endl;
4087  printBooleanConstraintMap( _out, _init );
4088  _out << _init << std::endl;
4089  printClauses( clauses, "Clauses", _out, _init );
4090  _out << _init << std::endl;
4091  printClauses( learnts, "Learnts", _out, _init );
4092  _out << _init << std::endl;
4093  printCurrentAssignment( _out, _init );
4094  _out << _init << std::endl;
4095  printDecisions( _out, _init );
4096  _out << _init << std::endl;
4097  _out << _init << " mcsat: " << mMCSAT << std::endl;
4098  _out << _init << std::endl;
4099  }
4100 
4101  template<class Settings>
4102  void SATModule<Settings>::printConstraintLiteralMap( std::ostream& _out, const std::string& _init ) const
4103  {
4104  _out << _init << " ConstraintLiteralMap" << std::endl;
4105  for( ConstraintLiteralsMap::const_iterator clPair = mConstraintLiteralMap.begin(); clPair != mConstraintLiteralMap.end(); ++clPair )
4106  {
4107  _out << _init << " " << clPair->first << " -> [";
4108  for( auto litIter = clPair->second.begin(); litIter != clPair->second.end(); ++litIter )
4109  {
4110  _out << " ";
4111  if( sign( *litIter ) )
4112  {
4113  _out << "-";
4114  }
4115  _out << var( *litIter );
4116  }
4117  _out << " ]" << std::endl;
4118  }
4119  }
4120 
4121  template<class Settings>
4122  void SATModule<Settings>::printFormulaCNFInfosMap( std::ostream& _out, const std::string& _init ) const
4123  {
4124  _out << _init << " FormulaCNFInfosMap" << std::endl;
4125  for( const auto& fcsPair : mFormulaCNFInfosMap )
4126  {
4127  _out << _init << " " << fcsPair.first << std::endl;
4128  _out << _init << " Literal: " << fcsPair.second.mLiteral;
4129  _out << std::endl;
4130  _out << _init << " Counter: " << fcsPair.second.mCounter << std::endl;
4131  _out << _init << " {";
4132  for( auto cref : fcsPair.second.mClauses )
4133  _out << " " << cref;
4134  _out << " }" << std::endl;
4135  }
4136  }
4137 
4138  template<class Settings>
4139  void SATModule<Settings>::printClauseInformation( std::ostream& _out, const std::string& _init ) const
4140  {
4141  _out << _init << " ClauseInformation" << std::endl;
4142  for( auto& ciPair : mClauseInformation )
4143  {
4144  _out << _init << " " << ciPair.first << " -> (stored in satisfied: " << (ciPair.second.mStoredInSatisfied ? "yes" : "no") << ", position: " << ciPair.second.mPosition << ")" << std::endl;
4145  }
4146  }
4147 
4148  template<class Settings>
4149  void SATModule<Settings>::printBooleanVarMap( std::ostream& _out, const std::string& _init ) const
4150  {
4151  _out << _init << " BooleanVarMap" << std::endl;
4152  for( BooleanVarMap::const_iterator clPair = mBooleanVarMap.begin(); clPair != mBooleanVarMap.end(); ++clPair )
4153  {
4154  _out << _init << " " << clPair->first << " -> " << clPair->second;
4155  auto tvfIter = mTseitinVarFormulaMap.find( (int)clPair->second );
4156  if( tvfIter != mTseitinVarFormulaMap.end() )
4157  _out << " ( " << tvfIter->second << " )";
4158  _out << std::endl;
4159  }
4160  }
4161 
4162  template<class Settings>
4163  void SATModule<Settings>::printBooleanConstraintMap( std::ostream& _out, const std::string& _init ) const
4164  {
4165  _out << _init << " BooleanConstraintMap" << std::endl;
4166  for( int k = 0; k < mBooleanConstraintMap.size(); ++k )
4167  {
4168  if( mBooleanConstraintMap[k].first != nullptr )
4169  {
4170  assert( mBooleanConstraintMap[k].second != nullptr );
4171  _out << _init << " " << k << " -> " << mBooleanConstraintMap[k].first->reabstraction;
4172  _out << " (" << std::setw( 7 ) << activity[k] << ") [" << mBooleanConstraintMap[k].first->updateInfo << "]" << std::endl;
4173  _out << _init << " ~" << k << " -> " << mBooleanConstraintMap[k].second->reabstraction;
4174  _out << " (" << std::setw( 7 ) << activity[k] << ") [" << mBooleanConstraintMap[k].second->updateInfo << "]" << std::endl;
4175  }
4176  }
4177  _out << _init << " Boolean Variables" << std::endl;
4178  for( const auto& it: mMinisatVarMap )
4179  {
4180  _out << _init << " " << it.first << " -> " << it.second << std::endl;
4181  }
4182  }
4183 
4184  template<class Settings>
4185  void SATModule<Settings>::printClause( const vec<Lit>& _clause, bool _withAssignment, std::ostream& _out, const std::string& _init ) const
4186  {
4187  _out << _init;
4188  for( int pos = 0; pos < _clause.size(); ++pos )
4189  {
4190  _out << " " << _clause[pos];
4191  if( _withAssignment )
4192  _out << "(" << (value( _clause[pos] ) == l_True ? "true" : (value( _clause[pos] ) == l_False ? "false" : "undef")) << "@" << level( var( _clause[pos] ) ) << ")";
4193  }
4194  _out << std::endl;
4195  }
4196 
4197  template<class Settings>
4198  void SATModule<Settings>::printClause( CRef _clause, bool _withAssignment, std::ostream& _out, const std::string& _init ) const
4199  {
4200  const Clause& c = ca[_clause];
4201  _out << _init;
4202  for( int pos = 0; pos < c.size(); ++pos )
4203  {
4204  _out << " " << c[pos];
4205  if( _withAssignment )
4206  {
4207  _out << " [" << (value( c[pos] ) == l_True ? "true@" : (value( c[pos] ) == l_False ? "false@" : "undef"));
4208  if( value( c[pos] ) != l_Undef )
4209  {
4210  _out << level( var( c[pos] ) );
4211  }
4212  _out << "]";
4213  }
4214  }
4215  _out << " [" << ((uint32_t) _clause) << "]" << std::endl;
4216  }
4217 
4218  template<class Settings>
4219  void SATModule<Settings>::printClauses( const vec<CRef>& _clauses, const std::string _name, std::ostream& _out, const std::string& _init, int _from, bool _withAssignment, bool _onlyNotSatisfied ) const
4220  {
4221  _out << _init << " " << _name << ":" << std::endl;
4222  // Handle case when solver is in contradictory state:
4223  if( !ok )
4224  {
4225  _out << _init << " p cnf 1 2" << std::endl;
4226  _out << _init << " 1 0" << std::endl;
4227  _out << _init << " -1 0" << std::endl;
4228  return;
4229  }
4230 
4231  vec<Var> map;
4232  Var max = 0;
4233 
4234  // Cannot use removeClauses here because it is not safe
4235  // to deallocate them at this point. Could be improved.
4236  int cnt = 0;
4237  for( int i = _from; i < _clauses.size(); i++ )
4238  if( !satisfied( ca[_clauses[i]] ) )
4239  cnt++;
4240 
4241  for( int i = _from; i < _clauses.size(); i++ )
4242  if( !satisfied( ca[_clauses[i]] ) )
4243  {
4244  const Clause& c = ca[_clauses[i]];
4245  for( int j = 0; j < c.size(); j++ )
4246  if( value( c[j] ) != l_False )
4247  mapVar( var( c[j] ), map, max );
4248  }
4249 
4250  // Assumptions are added as unit clauses:
4251  cnt += assumptions.size();
4252 
4253  _out << _init << " p cnf " << max << " " << cnt << std::endl;
4254 
4255  for( int i = 0; i < assumptions.size(); i++ )
4256  {
4257 // assert( isLemmaLevel(LemmaLevel::ADVANCED) || value( assumptions[i] ) != l_False );
4258  _out << _init << " " << (sign( assumptions[i] ) ? "-" : "") << var( assumptions[i] ) << std::endl;//(mapVar( var( assumptions[i] ), map, max )) << std::endl;
4259  }
4260 
4261  for( int i = _from; i < _clauses.size(); i++ )
4262  {
4263  if( !_onlyNotSatisfied || !satisfied(ca[_clauses[i]]) )
4264  {
4265  _out << _init << " " << i;
4266  if( !_onlyNotSatisfied )
4267  _out << (satisfied(ca[_clauses[i]]) ? " (ok)" : " ");
4268  _out << ": ";
4269  printClause( _clauses[i], _withAssignment, _out, "" );
4270 
4271  }
4272  }
4273 
4274  if( verbosity > 0 )
4275  _out << _init << " Wrote " << cnt << " clauses with " << max << " variables." << std::endl;
4276  }
4277 
4278  template<class Settings>
4279  void SATModule<Settings>::printCurrentAssignment( std::ostream& _out, const std::string& _init ) const
4280  {
4281  _out << _init << " Assignments: ";
4282  for( int pos = 0; pos < assigns.size(); ++pos )
4283  {
4284  if( pos > 0 )
4285  {
4286  _out << _init << " ";
4287  }
4288  _out << std::setw( 5 ) << pos;
4289  _out << " (" << std::setw( 7 ) << activity[pos] << ") " << " -> ";
4290  if( assigns[pos] == l_True )
4291  {
4292  _out << "l_True";
4293  // if it is not a Boolean variable
4294  if( mBooleanConstraintMap[pos].first != nullptr && mBooleanConstraintMap[pos].first->consistencyRelevant )
4295  _out << " ( " << mBooleanConstraintMap[pos].first->reabstraction << " )";
4296  else
4297  {
4298  auto tvfIter = mTseitinVarFormulaMap.find( pos );
4299  if( tvfIter != mTseitinVarFormulaMap.end() )
4300  _out << " ( " << tvfIter->second << " )";
4301  }
4302  _out << std::endl;
4303  }
4304  else if( assigns[pos] == l_False )
4305  {
4306  _out << "l_False";
4307  // if it is not a Boolean variable
4308  if( mBooleanConstraintMap[pos].second != nullptr && mBooleanConstraintMap[pos].second->consistencyRelevant )
4309  _out << " ( " << mBooleanConstraintMap[pos].second->reabstraction << " )";
4310  else
4311  {
4312  auto tvfIter = mTseitinVarFormulaMap.find( pos );
4313  if( tvfIter != mTseitinVarFormulaMap.end() )
4314  _out << " ( " << tvfIter->second.negated() << " )";
4315  }
4316  _out << std::endl;
4317  }
4318  else
4319  {
4320  _out << "l_Undef" << std::endl;
4321  }
4322  }
4323  }
4324 
4325  template<class Settings>
4326  void SATModule<Settings>::printDecisions( std::ostream& _out, const std::string& _init ) const
4327  {
4328  _out << _init << " Decisions: ";
4329  int level = 0;
4330  for( int pos = 0; pos < trail.size(); ++pos )
4331  {
4332  if( level < trail_lim.size() )
4333  {
4334  if( pos == trail_lim[level] )
4335  {
4336  ++level;
4337  }
4338  }
4339  if( pos > 0 )
4340  {
4341  _out << _init << " ";
4342  }
4343  std::stringstream tmpStream;
4344  tmpStream << (sign( trail[pos] ) ? "-" : "") << var( trail[pos] );
4345  _out << std::setw( 6 ) << tmpStream.str() << " @ " << level;
4346  // if it is not a Boolean variable
4347  auto v = var(trail[pos]);
4348  if (assigns[v] == l_True && mBooleanConstraintMap[v].first != nullptr)
4349  {
4350  _out << " ( " << mBooleanConstraintMap[v].first->reabstraction << " )";
4351  _out << " [" << mBooleanConstraintMap[v].first->updateInfo << "]";
4352  }
4353  else if (assigns[v] == l_False && mBooleanConstraintMap[v].second != nullptr)
4354  {
4355  _out << " ( " << mBooleanConstraintMap[v].second->reabstraction << " )";
4356  _out << " [" << mBooleanConstraintMap[v].second->updateInfo << "]";
4357  }
4358  else {
4359  _out << " ( " << static_cast<const void*>(mBooleanConstraintMap[v].first) << " / " << static_cast<const void*>(mBooleanConstraintMap[v].second) << " )";
4360  }
4361  assert(vardata[var(trail[pos])].mTrailIndex == pos);
4362  if (vardata[var(trail[pos])].reason != CRef_Undef) {
4363  _out << " due to " << vardata[var(trail[pos])].reason;
4364  }
4365  _out << std::endl;
4366  }
4367  }
4368 
4369  template<class Settings>
4370  void SATModule<Settings>::printPropagatedLemmas( std::ostream& _out, const std::string& _init ) const
4371  {
4372  _out << _init << " Propagated lemmas:" << std::endl;
4373  for( VarLemmaMap::const_iterator itFormulas = mPropagatedLemmas.begin(); itFormulas != mPropagatedLemmas.end(); ++itFormulas )
4374  {
4375  auto mvIter = mMinisatVarMap.find(itFormulas->first);
4376  assert( mvIter != mMinisatVarMap.end() );
4377  _out << _init << " " << mvIter->second << " <- { ";
4378  FormulasT formulas = itFormulas->second;
4379  for ( FormulasT::iterator iter = formulas.begin(); iter != formulas.end(); ++iter )
4380  {
4381  if ( iter != formulas.begin() )
4382  {
4383  _out << ", ";
4384  }
4385  _out << *iter;
4386  }
4387  _out << " }" << std::endl;
4388  }
4389  }
4390 
4391  template<class Settings>
4392  void SATModule<Settings>::printLiteralsActiveOccurrences( std::ostream& _out, const std::string& _init ) const
4393  {
4394  _out << _init << "Literals' active occurrences:" << std::endl;
4395  for( std::size_t pos = 0; pos < mLiteralsActivOccurrences.size(); ++pos )
4396  _out << _init << " " << pos << " -> " << mLiteralsActivOccurrences[pos] << std::endl;
4397  }
4398 
4399  template<class Settings>
4400  void SATModule<Settings>::collectStats()
4401  {
4402  #ifdef SMTRAT_DEVOPTION_Statistics
4403  mStatistics.rNrTotalVariablesAfter() = (size_t) nVars();
4404  mStatistics.rNrClauses() = (size_t) nClauses();
4405  #endif
4406  }
4407 } // namespace smtrat
4408