2 * **************************************************************************************[Solver.cc]
3 * Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
4 * Copyright (c) 2007-2010, Niklas Sorensson
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:
12 * The above copyright notice and this permission notice shall be included in all copies or
13 * substantial portions of the Software.
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.
23 * @author Florian Corzilius <corzilius@cs.rwth-aachen.de>
28 #include "SATModule.h"
30 #include <carl-formula/formula/functions/Complexity.h>
33 //#define DEBUG_SATMODULE
34 //#define DEBUG_SATMODULE_THEORY_PROPAGATION
35 //#define DEBUG_SATMODULE_DECISION_HEURISTIC
36 //#define DEBUG_SATMODULE_LEMMA_HANDLING
39 using namespace Minisat;
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 ) );
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):
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 ),
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')
91 clauses_literals( 0 ),
92 learnts_literals( 0 ),
98 watches( WatcherDeleted( ca ) ),
100 simpDB_assigns( -1 ),
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 ),
114 mExcludedAssignments( false ),
115 mCurrentAssignmentConsistent( SAT ),
116 mNumberOfFullLazyCalls( 0 ),
118 mNumberOfTheoryCalls( 0 ),
119 mReceivedFormulaPurelyPropositional(true),
120 mConstraintLiteralMap(),
123 mFormulaAssumptionMap(),
124 mFormulaCNFInfosMap(),
125 mClauseInformation(),
126 mLiteralClausesMap(),
127 mNumberOfSatisfiedClauses( 0 ),
129 mAllActivitiesChanged( false ),
130 mChangedActivities(),
132 mRelevantVariables(),
133 mNonTseitinShadowedOccurrences(),
134 mTseitinVarShadows(),
135 mTseitinVarFormulaMap(),
136 mCurrentTheoryConflicts(),
137 mCurrentTheoryConflictTypes(),
138 mCurrentTheoryConflictEvaluations(),
140 mTheoryConflictIdCounter( 0 ),
141 mUpperBoundOnMinimal( passedFormulaEnd() ),
142 mLiteralsClausesMap(),
143 mLiteralsActivOccurrences(),
144 //mTheoryVariableStack(),
145 //mNextTheoryVariable(mTheoryVariableStack.end()),
148 if (Settings::mc_sat) {
149 ca.extra_clause_field = true;
151 mCurrentTheoryConflicts.reserve(100);
152 mCurrentTheoryConflictTypes.reserve(100);
154 uncheckedEnqueue( mkLit( mTrueVar, false ) );
155 mBooleanConstraintMap.push( std::make_pair( nullptr, nullptr ) );
158 template<class Settings>
159 SATModule<Settings>::~SATModule()
161 while( mBooleanConstraintMap.size() > 0 )
163 Abstraction* abstrAToDel = mBooleanConstraintMap.last().first;
164 Abstraction* abstrBToDel = mBooleanConstraintMap.last().second;
165 mBooleanConstraintMap.pop();
168 abstrAToDel = nullptr;
169 abstrBToDel = nullptr;
180 ScopedBool( bool& watch, bool newValue ):
193 template<class Settings>
194 bool SATModule<Settings>::addCore( ModuleInput::const_iterator _subformula )
196 if( _subformula->formula().is_false() )
198 mModelComputed = false;
199 mOptimumComputed = false;
200 mInfeasibleSubsets.emplace_back();
201 mInfeasibleSubsets.back().insert( _subformula->formula() );
204 else if( !_subformula->formula().is_true() )
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 ) )
215 assumptions.push( createLiteral( _subformula->formula(), _subformula->formula() ) );
216 assert( mFormulaAssumptionMap.find( _subformula->formula() ) == mFormulaAssumptionMap.end() );
217 mFormulaAssumptionMap.emplace( _subformula->formula(), assumptions.last() );
221 addClauses( _subformula->formula(), NORMAL_CLAUSE, 0, _subformula->formula() );
223 if ( isLemmaLevel(NORMAL) && decisionLevel() == 0)
225 if (_subformula->formula().property_holds(carl::PROP_IS_A_LITERAL) && _subformula->formula().property_holds(carl::PROP_CONTAINS_BOOLEAN))
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());
240 updateInfeasibleSubset();
244 template<class Settings>
245 void SATModule<Settings>::removeCore( ModuleInput::const_iterator _subformula )
247 if( _subformula->formula().is_false() || _subformula->formula().is_true() )
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 )
255 assert( learnts[i] != CRef_Undef );
256 removeClause( learnts[i] );
259 mUnorderedClauseLookup.clear();
261 if( _subformula->formula().property_holds( carl::PROP_IS_A_LITERAL ) )
263 auto iter = mFormulaAssumptionMap.find( _subformula->formula() );
264 assert( iter != mFormulaAssumptionMap.end() );
266 while( assumptions[i] != iter->second ) ++i;
267 while( i < assumptions.size() - 1 )
269 assumptions[i] = assumptions[i+1];
273 mFormulaAssumptionMap.erase( iter );
274 ConstraintLiteralsMap::iterator constraintLiteralPair = mConstraintLiteralMap.find( _subformula->formula() );
275 if( constraintLiteralPair != mConstraintLiteralMap.end() )
276 removeLiteralOrigin( constraintLiteralPair->second.front(), _subformula->formula() );
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() )
285 mFormulaCNFInfosMap.erase( cnfInfoIter );
287 std::vector<FormulaT> constraints;
288 carl::arithmetic_constraints(_subformula->formula(), constraints);
289 for( const FormulaT& constraint : constraints )
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() );
301 template<class Settings>
302 void SATModule<Settings>::removeLiteralOrigin( Lit _litToRemove, const FormulaT& _origin )
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 )
310 auto& origs = *abstr.origins;
311 auto iter = origs.begin();
312 while( iter != origs.end() )
314 if( *iter == _origin || (iter->type() == carl::FormulaType::AND && iter->contains( _origin )) )
316 if (iter != --origs.end())
318 *iter = origs.back();
334 abstr.origins = nullptr;
339 template<class Settings>
340 double SATModule<Settings>::luby( double y, int x )
342 // Find the finite subsequence that contains index 'x', and the
343 // size of that subsequence:
345 for( size = 1, seq = 0; size < x + 1; seq++, size = 2 * size + 1 );
347 while( size - 1 != x )
349 size = (size - 1) >> 1;
354 return pow( y, seq );
357 template<class Settings>
358 Answer SATModule<Settings>::checkCore()
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();
367 ScopedBool scopedBool( mBusy, true );
369 // assumptions.clear();
373 if (Settings::mc_sat) {
374 #ifdef DEBUG_SATMODULE
375 std::cout << "### Processing clause" << std::endl;
376 print(std::cout, "###");
378 mMCSAT.initVariables(mBooleanConstraintMap);
379 for (const auto& v : mMCSAT.theoryVarAbstractions()) {
380 var_scheduler.insert(v);
382 assert(mMCSAT.level() == 0);
383 if (var_scheduler.empty()) {
384 SMTRAT_LOG_DEBUG("smtrat.sat", "We have no variables in our variable scheduler.");
386 var_scheduler.rebuildTheoryVars(mBooleanConstraintMap);
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;
397 assert( !mInfeasibleSubsets.empty() );
398 #ifdef SMTRAT_DEVOPTION_Statistics
404 mReceivedFormulaPurelyPropositional = rReceivedFormula().is_only_propositional();
405 if( mReceivedFormulaPurelyPropositional )
407 mAllActivitiesChanged = false;
408 mChangedBooleans.clear();
409 mChangedActivities.clear();
411 else if( Settings::initiate_activities )
413 double highestActivity = 0;
414 for( int pos = 0; pos < activity.size(); ++pos )
416 double& act = activity[pos];
418 if( Settings::check_active_literal_occurrences && false )
420 const auto& litActOccs = mLiteralsActivOccurrences[(size_t)pos];
421 act = (double)litActOccs.first + (double)litActOccs.second;
423 if( mBooleanConstraintMap[pos].first != nullptr )
425 act /= (double)carl::complexity(mBooleanConstraintMap[pos].first->reabstraction);
429 auto tvfIter = mTseitinVarFormulaMap.find( pos );
430 if( tvfIter != mTseitinVarFormulaMap.end() )
431 act /= (double)carl::complexity(tvfIter->second);
433 if( act > highestActivity )
434 highestActivity = act;
436 if( highestActivity > 1 )
438 for( int pos = 0; pos < activity.size(); ++pos )
440 activity[pos] /= highestActivity;
443 var_scheduler.rebuildActivities();
445 Minisat::lbool result = l_Undef;
446 mUpperBoundOnMinimal = passedFormulaEnd();
447 bool isOptimal = true;
450 if( Settings::use_restarts )
453 int current_restarts = -1;
454 while( current_restarts < mCurr_Restarts )
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;
465 if (isLemmaLevel(LemmaLevel::ADVANCED))
467 assert(result == l_True);
468 computeAdvancedLemmas();
470 if( !Settings::stop_search_after_first_unknown )
472 unknown_excludes.clear();
473 mExcludedAssignments = false;
475 // ##### Stop here if not in optimization mode!
476 if( !is_minimizing() )
478 std::vector<CRef> excludedAssignments;
479 if( result == l_Undef )
481 else if( result == l_False )
483 if( mUpperBoundOnMinimal != rPassedFormula().end() )
485 cleanUpAfterOptimizing( excludedAssignments );
492 assert( result == l_True );
493 Answer runBackendAnswer = runBackends( true, mFullCheck, objective() );
494 assert(is_sat(runBackendAnswer));
495 isOptimal = isOptimal && (runBackendAnswer == OPTIMAL);
497 auto modelIter = mModel.find( objective() );
498 assert( modelIter != mModel.end() );
499 const ModelValue& mv = modelIter->second;
500 if( mv.isMinusInfinity() )
502 cleanUpAfterOptimizing( excludedAssignments );
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 )
515 if( assigns[k] != l_Undef )
517 if( mBooleanConstraintMap[k].first != nullptr )
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))
523 excludeClause.push( mkLit( k, assigns[k] != l_False ) );
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() )
534 cleanUpAfterOptimizing( excludedAssignments );
537 if( confl != CRef_Undef )
538 handleConflict( confl );
542 #ifdef SMTRAT_DEVOPTION_Statistics
545 if( result == l_True )
547 return (is_minimizing() && isOptimal) ? OPTIMAL : SAT;
549 else if( result == l_False )
551 SMTRAT_LOG_DEBUG("smtrat.sat", "ok = false");
553 updateInfeasibleSubset();
559 template<class Settings>
560 Minisat::lbool SATModule<Settings>::checkFormula()
562 if( Settings::use_restarts )
565 int current_restarts = -1;
566 Minisat::lbool result = l_Undef;
567 while( current_restarts < mCurr_Restarts )
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;
582 template<class Settings>
583 void SATModule<Settings>::computeAdvancedLemmas()
585 #ifdef DEBUG_SATMODULE
586 printCurrentAssignment();
588 SMTRAT_LOG_TRACE("smtrat.sat", "Find all dependent variables");
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())
596 // If non are selected, all variables are relevant
597 for (BooleanVarMap::const_iterator iterVar = mBooleanVarMap.begin(); iterVar != mBooleanVarMap.end(); ++iterVar)
599 testVarsPositive.insert(iterVar->second);
604 for (std::set<FormulaT>::const_iterator iterVar = getInformationRelevantFormulas().begin(); iterVar != getInformationRelevantFormulas().end(); ++iterVar)
606 testVarsPositive.insert(mBooleanVarMap.at(iterVar->boolean()));
610 Minisat::lbool result = l_Undef;
611 while (!testVarsPositive.empty())
613 for (int pos = 0; pos < assigns.size(); ++pos)
615 if (assigns[pos] == l_True)
617 testVarsPositive.erase(pos);
621 // Reset the state until level 0
622 cancelUntil(0, true);
623 mPropagatedLemmas.clear();
625 if (testVarsPositive.empty())
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);
640 result = checkFormula();
641 if (result == l_False)
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);
654 else if (result == l_True)
656 SMTRAT_LOG_DEBUG("smtrat.sat", "Sat with variable: " << mMinisatVarMap.find(testCandidate)->second);
657 #ifdef DEBUG_SATMODULE
658 printCurrentAssignment();
663 SMTRAT_LOG_TRACE("smtrat.sat", "UNKNOWN with variable: " << mMinisatVarMap.find(testCandidate)->second);
667 assumptions.shrink(assumptions.size() - assumptionSizeStart);
670 template<class Settings>
671 void SATModule<Settings>::updateModel() const
673 if( !mModelComputed && !mOptimumComputed )
676 if( solverState() != UNSAT || is_minimizing() )
678 for( BooleanVarMap::const_iterator bVar = mBooleanVarMap.begin(); bVar != mBooleanVarMap.end(); ++bVar )
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));
686 Module::getBackendsModel();
687 if( Settings::check_if_all_clauses_are_satisfied && trail.size() < assigns.size() )
689 getDefaultModel( mModel, (FormulaT)rReceivedFormula(), false );
691 if (Settings::mc_sat) {
692 mModel.update(mMCSAT.model());
698 template<class Settings>
699 void SATModule<Settings>::updateModel( Model& model, bool only_relevant_variables ) const
702 if( solverState() == SAT )
704 if ( only_relevant_variables )
706 // Set assignment for all relevant variables (might be partial assignment)
707 for ( size_t i = 0; i < mRelevantVariables.size(); ++i )
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 ) );
719 // Set assignment for all defined variables (might be partial assignment)
720 for (BooleanVarMap::const_iterator bVar = mBooleanVarMap.begin(); bVar != mBooleanVarMap.end(); ++bVar)
722 ModelValue assignment = assigns[bVar->second] == l_True;
723 model.insert(std::make_pair(bVar->first, assignment));
726 Module::getBackendsModel();
727 if (Settings::check_if_all_clauses_are_satisfied && trail.size() < assigns.size())
729 getDefaultModel(model, (FormulaT)rReceivedFormula(), false);
734 template<class Settings>
735 void SATModule<Settings>::updateAllModels()
737 SMTRAT_LOG_TRACE("smtrat.sat", "Update all models");
738 mComputeAllSAT = true;
740 int sizeLearntsStart = learnts.size();
741 if( solverState() == SAT )
743 // Compute all satisfying assignments
744 SMTRAT_LOG_TRACE("smtrat.sat", "Compute more assignments");
746 // Construct list of all relevant variables
747 mRelevantVariables.clear();
748 if (getInformationRelevantFormulas().empty())
750 // If non are selected, all variables are relevant
751 for ( BooleanVarMap::const_iterator iterVar = mBooleanVarMap.begin(); iterVar != mBooleanVarMap.end(); ++ iterVar)
753 mRelevantVariables.push_back( iterVar->second );
758 for ( std::set<FormulaT>::const_iterator iterVar = getInformationRelevantFormulas().begin(); iterVar != getInformationRelevantFormulas().end(); ++iterVar )
760 mRelevantVariables.push_back( mBooleanVarMap.at( iterVar->boolean() ) );
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 )
768 auto mvIter = mMinisatVarMap.find(mRelevantVariables[ i ]);
769 assert( mvIter != mMinisatVarMap.end() );
770 std::cout << mRelevantVariables[ i ] << " (" << mvIter->second << "), ";
772 std::cout << std::endl;
775 Minisat::lbool result = l_False;
779 // Compute assignment
780 #ifdef DEBUG_SATMODULE
781 printCurrentAssignment();
783 updateModel( model, true );
784 mAllModels.push_back( model );
785 SMTRAT_LOG_TRACE("smtrat.sat", "Model: " << model);
786 // Exclude assignment
787 vec<Lit> excludeClause;
789 for ( size_t i = 0; i < mRelevantVariables.size(); ++i )
791 index = mRelevantVariables[ i ];
792 // Add negated literal
793 Lit lit = mkLit( index, assigns[ index ] == l_True);
794 excludeClause.push( lit );
796 #ifdef DEBUG_SATMODULE
797 std::cout << "Added exclude: " << std::endl;
798 printClause( excludeClause );
801 if( addClause( excludeClause, PERMANENT_CLAUSE ) )
802 clause = learnts.last();
803 else if( excludeClause.size() == 1)
804 break; // already unsat
807 if( !ok || decisionLevel() <= assumptions.size() )
811 handleConflict( clause );
814 result = checkFormula();
815 } while( result == l_True );
816 SMTRAT_LOG_TRACE("smtrat.sat", ( result == l_False ? "UnSAT" : "Undef" ));
818 // Remove clauses for excluded assignments
819 clearLearnts( sizeLearntsStart );
820 mComputeAllSAT = false;
821 cancelUntil(0, true);
824 template<class Settings>
825 void SATModule<Settings>::updateInfeasibleSubset()
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() )
833 // getInfeasibleSubsets();
837 // Just add all sub formulas.
838 // TODO: compute a better infeasible subset
839 for( auto subformula = rReceivedFormula().begin(); subformula != rReceivedFormula().end(); ++subformula )
841 infeasibleSubset.insert( subformula->formula() );
844 mInfeasibleSubsets.push_back( std::move(infeasibleSubset) );
847 template<class Settings>
848 void SATModule<Settings>::cleanUpAfterOptimizing( const std::vector<CRef>& _excludedAssignments )
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 )
861 template<class Settings>
862 void SATModule<Settings>::removeUpperBoundOnMinimal()
864 if( mUpperBoundOnMinimal != passedFormulaEnd() )
866 FormulaT bound = mUpperBoundOnMinimal->formula();
867 eraseSubformulaFromPassedFormula( mUpperBoundOnMinimal, true );
871 template<class Settings>
872 void SATModule<Settings>::addBooleanAssignments( RationalAssignment& _rationalAssignment ) const
874 for( BooleanVarMap::const_iterator bVar = mBooleanVarMap.begin(); bVar != mBooleanVarMap.end(); ++bVar )
876 if( assigns[bVar->second] == l_True )
878 assert( _rationalAssignment.find( bVar->first ) == _rationalAssignment.end() );
879 _rationalAssignment.insert( std::pair< const carl::Variable, Rational >( bVar->first, 1 ) );
881 else if( assigns[bVar->second] == l_False )
883 assert( _rationalAssignment.find( bVar->first ) == _rationalAssignment.end() );
884 _rationalAssignment.insert( std::pair< const carl::Variable, Rational >( bVar->first, 0 ) );
889 template<class Settings>
890 void SATModule<Settings>::updateCNFInfoCounter( typename FormulaCNFInfosMap::iterator _iter, const FormulaT& _origin, bool _increment )
892 assert( _iter != mFormulaCNFInfosMap.end() );
894 ++_iter->second.mCounter;
896 --_iter->second.mCounter;
897 for( std::size_t pos = 0; pos < _iter->second.mClauses.size(); )
899 Minisat::CRef cr = _iter->second.mClauses[pos];
900 assert( cr != CRef_Undef );
901 auto ciIter = mClauseInformation.find( cr );
902 assert( ciIter != mClauseInformation.end() );
905 ciIter->second.addOrigin( _origin );
910 ciIter->second.removeOrigin( _origin );
911 // if the counter becomes zero, remove the clause
912 if( _iter->second.mCounter == 0 )
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 )
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;
929 mClauseInformation.erase( ciIter );
930 if( Settings::check_if_all_clauses_are_satisfied )
932 const Clause& c = ca[cr];
933 for( int i = 0; i < c.size(); ++i )
934 mLiteralClausesMap[Minisat::toInt(c[i])].erase( cr );
937 if( pos < _iter->second.mClauses.size() - 1 )
938 _iter->second.mClauses[pos] = _iter->second.mClauses.back();
939 _iter->second.mClauses.pop_back();
945 // Invoke this procedure recursively on all sub-formulas, which again contain sub-formulas
946 if( _iter->first.is_nary() )
948 for( const FormulaT& formula : _iter->first.subformulas() )
950 if( formula.is_nary() )
952 auto cnfInfoIter = mFormulaCNFInfosMap.find( formula.remove_negations() );
953 if( cnfInfoIter != mFormulaCNFInfosMap.end() )
955 updateCNFInfoCounter( cnfInfoIter, _origin, _increment );
956 if( !_increment && cnfInfoIter->second.mClauses.empty() )
958 mFormulaCNFInfosMap.erase( cnfInfoIter );
966 template<class Settings>
967 Lit SATModule<Settings>::addClauses( const FormulaT& _formula, unsigned _type, unsigned _depth, const FormulaT& _original )
969 SMTRAT_LOG_DEBUG("smtrat.sat", "Adding formula " << _formula);
971 bool everythingDecisionRelevant = !Settings::formula_guided_decision_heuristic;
972 unsigned nextDepth = _depth+1;
973 switch( _formula.type() )
975 case carl::FormulaType::TRUE:
976 case carl::FormulaType::FALSE:
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:
988 SMTRAT_LOG_TRACE("smtrat.sat", "Adding a negation: " << _formula);
990 if( _formula.is_literal() )
992 l = createLiteral( _formula, _original, everythingDecisionRelevant || _depth <= 1 );
993 SMTRAT_LOG_TRACE("smtrat.sat", "It is a literal: " << l);
996 l = neg( addClauses( _formula.subformula(), _type, nextDepth, _original ) );
997 SMTRAT_LOG_TRACE("smtrat.sat", "It is not a literal, but now: " << l);
1001 SMTRAT_LOG_DEBUG("smtrat.sat", "Depth is zero");
1004 addClause(c, LEMMA_CLAUSE);
1005 //assumptions.push( l );
1006 //assert( mFormulaAssumptionMap.find( _formula ) == mFormulaAssumptionMap.end() );
1007 //mFormulaAssumptionMap.emplace( _formula, assumptions.last() );
1014 auto cnfInfoIter = mFormulaCNFInfosMap.end();
1015 if( _type == NORMAL_CLAUSE )
1017 cnfInfoIter = mFormulaCNFInfosMap.find( _formula );
1018 if( cnfInfoIter != mFormulaCNFInfosMap.end() )
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
1029 (_depth == 0 && cnfInfoIter->second.mCounter > 1) ||
1030 mNonassumedTseitinVariable.test(std::size_t(var(l)))
1032 SMTRAT_LOG_DEBUG("smtrat.sat", _original << " should be assumed, adding it to assumptions");
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.
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)));
1051 cnfInfoIter = mFormulaCNFInfosMap.emplace( _formula, CNFInfos() ).first;
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() )
1061 case carl::FormulaType::ITE:
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 );
1070 lits.push( negCondLit ); lits.push( thenLit ); addClause_( lits, _type, _original, cnfInfoIter );
1072 lits.clear(); lits.push( condLit ); lits.push( elseLit ); addClause_( lits, _type, _original, cnfInfoIter );
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 )
1079 mTseitinVarFormulaMap.emplace( (int)var(tsLit), _formula );
1081 if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
1083 mTseitinVarShadows.emplace( (signed)var(tsLit), std::vector<signed>{ (signed)var(condLit), (signed)var(thenLit), (signed)var(elseLit)} );
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 );
1096 case carl::FormulaType::IMPLIES:
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 );
1103 // (or -premise conclusion)
1104 lits.push( neg( premLit ) ); lits.push( conLit ); addClause_( lits, _type, _original, cnfInfoIter );
1107 Lit negConLit = _formula.conclusion().is_literal() ? addClauses( _formula.conclusion().negated(), _type, nextDepth, _original ) : neg( conLit );
1108 if( !mReceivedFormulaPurelyPropositional && Settings::initiate_activities )
1110 mTseitinVarFormulaMap.emplace( (int)var(tsLit), _formula );
1112 if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
1114 mTseitinVarShadows.emplace( (signed)var(tsLit), std::vector<signed>{ (signed)var(premLit), (signed)var(conLit)} );
1116 // (or -ts -prem con)
1117 lits.push( neg( tsLit ) ); lits.push( negPremLit ); lits.push( conLit ); addClause_( lits, _type, _original, cnfInfoIter );
1119 lits.clear(); lits.push( tsLit ); lits.push( premLit ); addClause_( lits, _type, _original, cnfInfoIter );
1121 lits.clear(); lits.push( tsLit ); lits.push( negConLit ); addClause_( lits, _type, _original, cnfInfoIter );
1124 case carl::FormulaType::OR:
1126 for( const auto& sf : _formula.subformulas() )
1127 lits.push( addClauses( sf, _type, nextDepth, _original ) );
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.
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)));
1145 addClause_( lits, _type, _original, cnfInfoIter );
1148 if( !mReceivedFormulaPurelyPropositional && Settings::initiate_activities )
1150 mTseitinVarFormulaMap.emplace( (int)var(tsLit), _formula );
1152 if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
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) );
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.
1164 // (or ts -a1) .. (or ts -an)
1166 litsTmp.push( tsLit );
1168 for( const auto& sf : _formula.subformulas() )
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 );
1177 SMTRAT_LOG_DEBUG("smtrat.sat", "Added formula " << _formula << " -> " << tsLit);
1180 case carl::FormulaType::AND:
1182 assert( _depth != 0 ); // because, this should be split in the module input
1183 if( !mReceivedFormulaPurelyPropositional && Settings::initiate_activities )
1185 mTseitinVarFormulaMap.emplace( (int)var(tsLit), _formula );
1187 // (or -ts a1) .. (or -ts an)
1188 // (or ts -a1 .. -an)
1190 litsTmp.push( neg( tsLit ) );
1191 for( const auto& sf : _formula.subformulas() )
1193 Lit l = addClauses( sf, _type, nextDepth, _original );
1194 assert( l != lit_Undef );
1196 addClause_( litsTmp, _type, _original, cnfInfoIter );
1198 Lit negL = sf.is_literal() ? addClauses( sf.negated(), _type, nextDepth, _original ) : neg( l );
1201 if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
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) );
1209 addClause_( lits, _type, _original, cnfInfoIter );
1210 if( _type == NORMAL_CLAUSE )
1211 cnfInfoIter->second.mLiteral = tsLit;
1214 case carl::FormulaType::IFF:
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 );
1223 for( ; sfIter != _formula.subformulas().end(); ++sfIter )
1225 Lit k = addClauses( *sfIter, _type, nextDepth, _original );
1226 Lit negK = sfIter->is_literal() ? addClauses( sfIter->negated(), _type, nextDepth, _original ) : neg( k );
1228 tmp.clear(); tmp.push( negL ); tmp.push( k ); addClause_( tmp, _type, _original, cnfInfoIter );
1230 tmp.clear(); tmp.push( l ); tmp.push( negK ); addClause_( tmp, _type, _original, cnfInfoIter );
1236 for( const auto& sf : _formula.subformulas() )
1238 Lit l = addClauses( sf, _type, nextDepth, _original );
1239 Lit negL = sf.is_literal() ? addClauses( sf.negated(), _type, nextDepth, _original ) : neg( l );
1243 if( !mReceivedFormulaPurelyPropositional && Settings::initiate_activities )
1245 mTseitinVarFormulaMap.emplace( (int)var(tsLit), _formula );
1247 if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
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) );
1255 lits.push( tsLit ); addClause_( lits, _type, _original, cnfInfoIter );
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)
1261 for( int i = 1; i < lits.size(); ++i )
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 );
1268 case carl::FormulaType::XOR:
1272 for( const auto& sf : _formula.subformulas() )
1274 lits.push( addClauses( sf, _type, nextDepth, _original ) );
1275 negLits.push( sf.is_literal() ? addClauses( sf.negated(), _type, nextDepth, _original ) : neg( lits.last() ) );
1277 if( _type == NORMAL_CLAUSE )
1278 cnfInfoIter->second.mLiteral = tsLit;
1281 addXorClauses( lits, negLits, 0, true, _type, tmp, _original, cnfInfoIter );
1284 if( !mReceivedFormulaPurelyPropositional && Settings::initiate_activities )
1286 mTseitinVarFormulaMap.emplace( (int)var(tsLit), _formula );
1288 if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
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) );
1295 lits.push( neg( tsLit ) );
1296 negLits.push( tsLit );
1297 addXorClauses( lits, negLits, 0, true, _type, tmp, _original, cnfInfoIter );
1300 case carl::FormulaType::EXISTS:
1301 case carl::FormulaType::FORALL:
1303 std::cerr << "Formula must be quantifier-free!" << std::endl;
1306 SMTRAT_LOG_ERROR("smtrat.sat", "Unexpected formula type " << _formula.type());
1307 SMTRAT_LOG_ERROR("smtrat.sat", _formula);
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 )
1318 if( _from == _literals.size() - 1 )
1320 _clause.push( _numOfNegatedLitsEven ? _literals[_from] : _negLiterals[_from] );
1321 addClause_( _clause, _type, _original, _formulaCNFInfoIter );
1326 _clause.push( _literals[_from] );
1327 addXorClauses( _literals, _negLiterals, _from+1, _numOfNegatedLitsEven, _type, _clause, _original, _formulaCNFInfoIter );
1329 _clause.push( _negLiterals[_from] );
1330 addXorClauses( _literals, _negLiterals, _from+1, !_numOfNegatedLitsEven, _type, _clause, _original, _formulaCNFInfoIter );
1335 template<class Settings>
1336 Lit SATModule<Settings>::createLiteral( const FormulaT& _formula, const FormulaT& _origin, bool _decisionRelevant )
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 )
1345 BooleanVarMap::iterator booleanVarPair = mBooleanVarMap.find(content.boolean());
1346 if( booleanVarPair != mBooleanVarMap.end() )
1348 if( _decisionRelevant ) {
1349 if (Settings::mc_sat) {
1350 setDecisionVar( booleanVarPair->second, _decisionRelevant, content.type() != carl::FormulaType::VARASSIGN );
1352 setDecisionVar( booleanVarPair->second, _decisionRelevant );
1356 l = mkLit( booleanVarPair->second, negated );
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);
1371 l = mkLit( var, negated );
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() )
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() )
1390 activity[abstractionVar] = maxActivity() + 1;
1391 polarity[abstractionVar] = false;
1393 if( _decisionRelevant ) {
1394 if (Settings::mc_sat) {
1395 setDecisionVar( abstractionVar, _decisionRelevant, content.type() != carl::FormulaType::VARASSIGN );
1397 setDecisionVar( abstractionVar, _decisionRelevant );
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 )
1406 if( !abstr.consistencyRelevant )
1408 addConstraintToInform_( abstr.reabstraction );
1409 if( (sign(constraintLiteralPair->second.front()) && assigns[abstractionVar] == l_False)
1410 || (!sign(constraintLiteralPair->second.front()) && assigns[abstractionVar] == l_True) )
1412 if( ++abstr.updateInfo > 0 )
1413 mChangedBooleans.push_back( abstractionVar );
1415 abstr.consistencyRelevant = true;
1417 if( !_origin.is_true() )
1419 if( abstr.origins == nullptr )
1421 abstr.origins = std::shared_ptr<std::vector<FormulaT>>( new std::vector<FormulaT>() );
1423 abstr.origins->push_back( _origin );
1426 SMTRAT_LOG_DEBUG("smtrat.sat", _formula << " -> " << constraintLiteralPair->second.front());
1427 return constraintLiteralPair->second.front();
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();
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);
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);
1453 // add the constraint and its negation to the constraints to inform backends about
1454 if( !_origin.is_true() )
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 )
1460 abstr.origins = std::shared_ptr<std::vector<FormulaT>>( new std::vector<FormulaT>() );
1464 abstr.origins->push_back( _origin );
1465 abstr.consistencyRelevant = true;
1466 addConstraintToInform_( invertedConstraint );
1470 abstr.origins->push_back( _origin );
1471 abstr.consistencyRelevant = true;
1472 addConstraintToInform_( constraint );
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 );
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;
1505 template<class Settings>
1506 Lit SATModule<Settings>::getLiteral( const FormulaT& _formula ) const
1508 bool negated = _formula.type() == carl::FormulaType::NOT;
1509 const FormulaT& content = negated ? _formula.subformula() : _formula;
1510 if( content.type() == carl::FormulaType::BOOL )
1512 BooleanVarMap::const_iterator booleanVarPair = mBooleanVarMap.find(content.boolean());
1513 assert( booleanVarPair != mBooleanVarMap.end() );
1514 return mkLit( booleanVarPair->second, negated );
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();
1523 template<class Settings>
1524 void SATModule<Settings>::adaptPassedFormula()
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 )
1530 assert( mBooleanConstraintMap[posInAssigns].first != nullptr && mBooleanConstraintMap[posInAssigns].second != nullptr );
1531 adaptPassedFormula( *mBooleanConstraintMap[posInAssigns].first );
1532 adaptPassedFormula( *mBooleanConstraintMap[posInAssigns].second );
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 )
1538 for( int i = 0; i < mBooleanConstraintMap.size(); ++i )
1540 if( mBooleanConstraintMap[i].first != nullptr )
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]);
1551 mAllActivitiesChanged = false;
1555 for( signed v : mChangedActivities )
1557 if( mBooleanConstraintMap[v].first != nullptr )
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]);
1569 mChangedActivities.clear();
1570 if( mChangedPassedFormula )
1572 mCurrentAssignmentConsistent = SAT;
1574 // assert( passedFormulaCorrect() );
1577 template<class Settings>
1578 void SATModule<Settings>::adaptPassedFormula( Abstraction& _abstr )
1580 if( _abstr.updatedReabstraction || _abstr.updateInfo < 0 )
1582 SMTRAT_LOG_DEBUG("smtrat.sat", "Removing " << _abstr.reabstraction);
1583 assert( !_abstr.reabstraction.is_true() );
1584 if( _abstr.position != rPassedFormula().end() )
1586 removeOrigins( _abstr.position, _abstr.origins );
1587 _abstr.position = passedFormulaEnd();
1588 mChangedPassedFormula = true;
1591 if( _abstr.updatedReabstraction || _abstr.updateInfo > 0 )
1593 SMTRAT_LOG_DEBUG("smtrat.sat", "Adding " << _abstr.reabstraction);
1594 assert( !_abstr.reabstraction.is_true() );
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
1602 auto res = addSubformulaToPassedFormula( _abstr.reabstraction, _abstr.origins );
1603 _abstr.position = res.first;
1604 _abstr.position->setDeducted( _abstr.isDeduction );
1605 mChangedPassedFormula = true;
1607 _abstr.updateInfo = 0;
1608 _abstr.updatedReabstraction = false;
1611 template<class Settings>
1612 bool SATModule<Settings>::passedFormulaCorrect() const
1614 for( int k = 0; k < mBooleanConstraintMap.size(); ++k )
1616 if( assigns[k] != l_Undef )
1618 if( mBooleanConstraintMap[k].first != nullptr )
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))
1624 if( !rPassedFormula().contains( abstr.reabstraction ) )
1626 // std::cout << "does not contain " << abstr.reabstraction << std::endl;
1633 for( auto subformula = rPassedFormula().begin(); subformula != rPassedFormula().end(); ++subformula )
1635 if( value( getLiteral( subformula->formula() ) ) != l_True )
1637 // std::cout << "should not contain " << iter->first << std::endl;
1644 template<class Settings>
1645 Var SATModule<Settings>::newVar( bool sign, bool dvar, double _activity, bool insertIntoHeap )
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 );
1655 polarity.push( sign );
1657 trail.capacity( v + 1 );
1658 setDecisionVar( v, dvar, insertIntoHeap );
1659 if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
1661 mNonTseitinShadowedOccurrences.push( dvar ? 1 : 0 );
1663 if( /*!mReceivedFormulaPurelyPropositional &&*/ Settings::check_active_literal_occurrences )
1665 mLiteralsClausesMap.emplace_back();
1666 mLiteralsActivOccurrences.emplace_back();
1671 template<class Settings>
1672 bool SATModule<Settings>::addClause( const vec<Lit>& _clause, unsigned _type )
1674 SMTRAT_LOG_DEBUG("smtrat.sat", "Adding clause " << _clause);
1675 #ifdef DEBUG_SATMODULE_LEMMA_HANDLING
1676 std::cout << "add clause ";
1677 printClause(_clause,true);
1679 assert( _clause.size() != 0 );
1682 _clause.copyTo( add_tmp );
1684 #ifdef SMTRAT_DEVOPTION_Statistics
1685 if( _type != NORMAL_CLAUSE ) mStatistics.lemmaLearned();
1687 // Check if clause is satisfied and remove false/duplicate literals:true);
1688 Minisat::sort( add_tmp );
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 )
1698 for( i = j = 0, p = lit_Undef; i < add_tmp.size(); ++i )
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 )
1706 // ignore repeated literals
1707 if( add_tmp[i] == p )
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 )
1712 if( level( var( add_tmp[i] ) ) == 0 )
1715 ++falseLiteralsCount; // if we decide to keep it, we count it into the false literals
1717 // this literal is a keeper
1718 add_tmp[j++] = p = add_tmp[i];
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() )
1725 //if (_type != CONFLICT_CLAUSE) { //!Settings::mc_sat ||
1726 #ifdef DEBUG_SATMODULE_LEMMA_HANDLING
1727 std::cout << "add to mLemmas:" << add_tmp << std::endl;
1729 SMTRAT_LOG_DEBUG("smtrat.sat", "add_lemma = " << add_tmp);
1731 add_tmp.copyTo( mLemmas.last() );
1732 mLemmasRemovable.push( _type != NORMAL_CLAUSE );
1736 // if all false, we're in conflict
1737 if( add_tmp.size() == falseLiteralsCount )
1739 SMTRAT_LOG_DEBUG("smtrat.sat", "ok = false");
1741 add_tmp.copyTo( mLemmas.last() );
1742 mLemmasRemovable.push( _type != NORMAL_CLAUSE );
1746 CRef cr = CRef_Undef;
1747 // if not unit, add the clause
1748 if( add_tmp.size() > 1 )
1750 lemma_lt lt( *this );
1751 Minisat::sort( add_tmp, lt );
1752 cr = ca.alloc( add_tmp, NORMAL_CLAUSE );
1756 // check if it propagates
1757 if( add_tmp.size() == falseLiteralsCount + 1 )
1759 if( assigns[var(add_tmp[0])] == l_Undef )
1761 assert( assigns[var(add_tmp[0])] != l_False );
1762 if (add_tmp.size() == 1) {
1763 assumptions.push(add_tmp[0]);
1765 uncheckedEnqueue( add_tmp[0], cr );
1766 if (propagateConsistently(false) != CRef_Undef) {
1778 template<class Settings>
1779 int SATModule<Settings>::level( const vec< Lit >& _clause ) const
1782 for( int i = 0; i < _clause.size(); ++i )
1784 if( value( _clause[i] ) != l_Undef )
1786 int varLevel = level( var( _clause[i] ) );
1787 if( varLevel > result ) result = varLevel;
1793 template<class Settings>
1794 CRef SATModule<Settings>::storeLemmas()
1796 // decision level to backtrack to
1797 int backtrackLevel = decisionLevel();
1798 SMTRAT_LOG_DEBUG("smtrat.sat", "Storing " << mLemmas.size() << " lemmas");
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
1806 // - Sort lemmas again
1807 // - Add lemma as clause
1808 // - If conflicting: use as conflict
1809 // - If propagating: propagate manually
1811 // In general, we have the following cases for the first two literals:
1812 // - UU, UT, TT, TF: lemma is neither unit nor conflicting
1814 // - FF: conflicting
1815 // TU, FU, FT: Can not occur due to sorting
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");
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");
1837 SMTRAT_LOG_DEBUG("smtrat.sat", "-- Lemma is singleton, but was already propagated at DL0");
1839 } else if (value(lemma[0]) == l_False) {
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;
1848 } else if (value(lemma[0]) == l_Undef && value(lemma[1]) == l_False) {
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;
1857 SMTRAT_LOG_DEBUG("smtrat.sat", "Backtracking to " << backtrackLevel);
1858 SMTRAT_CHECKPOINT("nlsat", "backtrack", backtrackLevel);
1859 cancelUntil(backtrackLevel, true);
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];
1866 mLemmasRemovable.pop();
1867 SMTRAT_LOG_DEBUG("smtrat.sat", "Processing lemma " << lemma);
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++) {
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]);
1885 SMTRAT_LOG_DEBUG("smtrat.sat", lemma << " is a duplicate of " << corig);
1890 SMTRAT_LOG_ERROR("smtrat.sat", "Adding a clause we already have: " << lemma);
1895 if (lemma.size() == 0) {
1896 SMTRAT_LOG_DEBUG("smtrat.sat", "-- Lemma is trivial conflict, ok = false");
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);
1908 learnts.push(lemma_ref);
1910 clauses.push(lemma_ref);
1912 attachClause(lemma_ref);
1913 SMTRAT_LOG_DEBUG("smtrat.sat", "-- Added lemma as clause " << lemma_ref);
1915 #ifdef DEBUG_SATMODULE
1916 std::cout << "### Processing clause" << std::endl;
1917 print(std::cout, "###");
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");
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]);
1931 SMTRAT_LOG_DEBUG("smtrat.sat", "-- Lemma is singleton, but was already propagated at DL0");
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;
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
1951 // while( i < mLemmas.size() )
1953 // // we need this loop as when we backtrack, due to registration more lemmas could be added
1954 // for( ; i < mLemmas.size(); ++i )
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 )
1962 // backtrackLevel = 0;
1965 // for (int i = 0; i < lemma.size(); i++) {
1966 // valueAndUpdate(lemma[i]);
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 )
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 )
1982 // SMTRAT_LOG_DEBUG("smtrat.sat", "Backtracking to " << backtrackLevel);
1983 // if( currentBacktrackLevel < backtrackLevel )
1984 // backtrackLevel = currentBacktrackLevel;
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;
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 )
2000 // // the current lemma
2001 // vec<Lit>& lemma = mLemmas[i];
2002 // if( lemma.size() == 0 )
2004 // SMTRAT_LOG_DEBUG("smtrat.sat", "ok = false");
2006 // return CRef_Undef;
2008 // for (int i = 0; i < lemma.size(); i++) {
2009 // valueAndUpdate(lemma[i]);
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 )
2017 // lemma_ref = ca.alloc( lemma, removable );
2019 // learnts.push( lemma_ref );
2021 // clauses.push( lemma_ref );
2022 // attachClause( lemma_ref );
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;
2034 // if( conflict == CRef_Undef && value(lemma[0]) != l_True )
2036 // if( lemma.size() == 1 || (value(lemma[1]) == l_False && trailIndex(var(lemma[1])) < backtrack_index) )
2038 // if( value(lemma[0]) == l_False )
2040 // // we have a conflict
2041 // if( lemma.size() > 1 )
2043 // #ifdef DEBUG_SATMODULE_LEMMA_HANDLING
2044 // std::cout << "lemma is better as conflict" << std::endl;
2046 // conflict = lemma_ref;
2048 // SMTRAT_LOG_DEBUG("smtrat.sat", "Unit conflict " << conflict);
2050 // if (value(lemma[0]) == l_False) {
2051 // SMTRAT_LOG_DEBUG("smtrat.sat", "ok = false");
2053 // return CRef_Undef;
2055 // uncheckedEnqueue(lemma[0]);
2061 // uncheckedEnqueue(lemma[0], lemma_ref);
2066 // // clear the lemmas
2068 // mLemmasRemovable.clear();
2069 // SMTRAT_LOG_DEBUG("smtrat.sat", "Stored lemmas, returning conflict " << conflict);
2073 template<class Settings>
2074 void SATModule<Settings>::attachClause( CRef cr )
2076 SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Clause: " << 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] ) );
2084 learnts_literals += (uint64_t)c.size();
2087 clauses_literals += (uint64_t)c.size();
2088 if( /*!mReceivedFormulaPurelyPropositional &&*/ Settings::check_active_literal_occurrences )
2090 bool clauseSatisfied = bool_satisfied(c);
2091 for( int i = 0; i < c.size(); ++i )
2093 size_t v = (size_t)var(c[i]);
2094 assert(mLiteralsClausesMap.size() > v);
2097 if( !clauseSatisfied )
2098 ++(mLiteralsActivOccurrences[v].second);
2099 mLiteralsClausesMap[v].addNegative( cr );
2103 if( !clauseSatisfied )
2104 ++(mLiteralsActivOccurrences[v].first);
2105 mLiteralsClausesMap[v].addPositive( cr );
2109 var_scheduler.attachClause(cr);
2112 template<class Settings>
2113 void SATModule<Settings>::detachClause( CRef cr, bool strict )
2115 const Clause& c = ca[cr];
2116 assert( c.size() > 1 );
2120 Minisat::remove( watches[~c[0]], Watcher( cr, c[1] ) );
2121 Minisat::remove( watches[~c[1]], Watcher( cr, c[0] ) );
2125 // Lazy detaching: (NOTE! Must clean all watcher lists before garbage collecting this clause)
2126 watches.smudge( ~c[0] );
2127 watches.smudge( ~c[1] );
2131 learnts_literals -= (uint64_t)c.size();
2133 clauses_literals -= (uint64_t)c.size();
2134 if( /*!mReceivedFormulaPurelyPropositional &&*/ Settings::check_active_literal_occurrences )
2136 bool clauseSatisfied = bool_satisfied(c);
2137 for( int i = 0; i < c.size(); ++i )
2139 size_t v = (size_t)var(c[i]);
2142 if( !clauseSatisfied )
2144 assert( mLiteralsActivOccurrences[v].second > 0 );
2145 --(mLiteralsActivOccurrences[v].second);
2147 mLiteralsClausesMap[v].removeNegative( cr );
2151 if( !clauseSatisfied )
2153 assert( mLiteralsActivOccurrences[v].first > 0 );
2154 --(mLiteralsActivOccurrences[v].first);
2156 mLiteralsClausesMap[v].removePositive( cr );
2160 var_scheduler.detachClause(cr);
2163 template<class Settings>
2164 void SATModule<Settings>::removeClause( CRef cr )
2168 // Don't leave pointers to free'd memory!
2170 vardata[var( c[0] )].reason = CRef_Undef;
2175 template<class Settings>
2176 bool SATModule<Settings>::satisfied( const Clause& c ) const
2178 for( int i = 0; i < c.size(); i++ )
2180 if( value( c[i] ) == l_True )
2186 template<class Settings>
2187 bool SATModule<Settings>::bool_satisfied( const Clause& c ) const
2189 for( int i = 0; i < c.size(); i++ )
2191 if( bool_value( c[i] ) == l_True )
2197 template<class Settings>
2198 void SATModule<Settings>::cancelUntil( int level, bool force )
2200 if( level < assumptions.size() && !force )
2201 level = assumptions.size();
2202 #ifdef DEBUG_SATMODULE
2203 std::cout << "### cancel until " << level << " (forced: " << force << ")" << std::endl;
2205 if( decisionLevel() > level )
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 );
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]);
2224 Var x = var( trail[c] );
2225 resetVariableAssignment( x );
2226 if (Settings::mc_sat) {
2227 mMCSAT.undoBooleanAssignment(trail[c]);
2229 VarData& vd = vardata[x];
2230 if( vd.mExpPos > 0 )
2232 removeTheoryPropagation( vd.mExpPos );
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 );
2241 Minisat::Lit curlit = trail[c];
2242 assert(lit != neg(curlit));
2243 if (trail_lim.last() == c) trail_lim.pop();
2245 if (curlit == lit) break;
2247 SMTRAT_LOG_DEBUG("smtrat.sat.mc", "Done.");
2250 template<class Settings>
2251 void SATModule<Settings>::cancelAssignmentUntil( int level )
2253 for( int c = trail.size() - 1; c >= trail_lim[level]; --c )
2255 SMTRAT_LOG_DEBUG("smtrat.sat.mc", "Backtracking " << trail[c]);
2256 if (Settings::mc_sat) {
2257 mMCSAT.backtrackTo(trail[c]);
2259 Var x = var( trail[c] );
2260 resetVariableAssignment( x );
2261 if (Settings::mc_sat) {
2262 mMCSAT.undoBooleanAssignment(trail[c]);
2264 VarData& vd = vardata[x];
2265 if( vd.mExpPos > 0 )
2267 removeTheoryPropagation( vd.mExpPos );
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 );
2278 template<class Settings>
2279 void SATModule<Settings>::resetVariableAssignment( Var _var )
2281 Minisat::lbool& ass = assigns[_var];
2282 bool wasAssignedToFalse = ass == l_False;
2283 if( !mReceivedFormulaPurelyPropositional && mBooleanConstraintMap[_var].first != nullptr )
2285 Abstraction* abstrptr = wasAssignedToFalse ? mBooleanConstraintMap[_var].second : mBooleanConstraintMap[_var].first;
2286 assert( abstrptr != nullptr );
2287 Abstraction& abstr = *abstrptr;
2288 if( abstr.position != rPassedFormula().end() )
2290 if( abstr.updateInfo >=0 && --abstr.updateInfo < 0 )
2292 mChangedBooleans.push_back( _var );
2295 else if( abstr.consistencyRelevant )
2297 abstr.updateInfo = 0;
2301 if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
2303 auto iter = mTseitinVarShadows.find( (signed) _var );
2304 if( iter != mTseitinVarShadows.end() )
2306 for( signed var : iter->second )
2308 decrementTseitinShadowOccurrences(var);
2313 if( /*!mReceivedFormulaPurelyPropositional &&*/ Settings::check_active_literal_occurrences )
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 )
2320 const Clause& c = ca[cr];
2321 // Check if clause is not yet satisfied.
2322 if( !bool_satisfied(c) )
2324 for( int i = 0; i < c.size(); ++i )
2326 size_t v = (size_t)var(c[i]);
2327 std::pair<size_t,size_t>& litActOccs = mLiteralsActivOccurrences[v];
2329 if( litActOccs.first == 0 )
2331 if( litActOccs.second == 0 )
2334 insertVarOrder( x );
2338 auto pfdIter = std::find( mPropagationFreeDecisions.begin(), mPropagationFreeDecisions.end(), mkLit( x, true ) );
2339 if( pfdIter != mPropagationFreeDecisions.end() )
2341 *pfdIter = mPropagationFreeDecisions.back();
2342 mPropagationFreeDecisions.pop_back();
2346 else if( litActOccs.second == 0 )
2348 auto pfdIter = std::find( mPropagationFreeDecisions.begin(), mPropagationFreeDecisions.end(), mkLit( x, false ) );
2349 if( pfdIter != mPropagationFreeDecisions.end() )
2351 *pfdIter = mPropagationFreeDecisions.back();
2352 mPropagationFreeDecisions.pop_back();
2357 ++(litActOccs.second);
2361 ++(litActOccs.first);
2367 if( Settings::check_if_all_clauses_are_satisfied && !mReceivedFormulaPurelyPropositional && mNumberOfSatisfiedClauses > 0 )
2369 auto litClausesIter = mLiteralClausesMap.find( (int) _var );
2370 if( litClausesIter != mLiteralClausesMap.end() )
2372 for( CRef cl : litClausesIter->second )
2374 if( !satisfied( ca[cl] ) )
2376 assert( mNumberOfSatisfiedClauses > 0 );
2377 --mNumberOfSatisfiedClauses;
2384 template<class Settings>
2385 CRef SATModule<Settings>::propagateConsistently( bool _checkWithTheory )
2387 CRef confl = CRef_Undef;
2389 ScopedBool scopedBool( mBusy, true );
2391 // add lemmas that we're left behind
2392 if( mLemmas.size() > 0 )
2394 SMTRAT_LOG_DEBUG("smtrat.sat", "Storing lemmas");
2395 confl = storeLemmas();
2396 SMTRAT_LOG_DEBUG("smtrat.sat", "-> " << confl);
2397 if( confl != CRef_Undef )
2402 // keep running until we have checked everything, we have no conflict and no new literals have been asserted
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 )
2411 if (!Settings::mc_sat) {
2412 // do the theory check
2414 if( mCurrentAssignmentConsistent == ABORTED )
2416 mCurrentAssignmentConsistent = UNKNOWN;
2421 if( Settings::allow_theory_propagation ) {
2422 SMTRAT_LOG_DEBUG("smtrat.sat", "Processing lemmas");
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);
2435 // even though in conflict, we still need to discharge the lemmas
2436 if( mLemmas.size() > 0 )
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
2451 SMTRAT_LOG_DEBUG("smtrat.sat", "Aborting due to !ok");
2454 assert(Settings::mc_sat || mChangedBooleans.empty() || _checkWithTheory );
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
2466 SMTRAT_LOG_TRACE("smtrat.sat", "Returning " << confl);
2470 template<class Settings>
2471 void SATModule<Settings>::propagateTheory()
2473 carl::uint pos = mTheoryPropagations.size();
2474 collectTheoryPropagations();
2475 while( pos < mTheoryPropagations.size() )
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 )
2482 uncheckedEnqueue( conclLit, CRef_Lazy );
2483 vardata[var(conclLit)].mExpPos = (int)pos;
2488 if( value(conclLit) == l_False )
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 );
2496 if( (std::size_t) pos != mTheoryPropagations.size()-1 )
2497 tp = std::move( mTheoryPropagations.back() );
2498 mTheoryPropagations.pop_back();
2503 template<class Settings>
2504 CRef SATModule<Settings>::reason( Var x )
2506 VarData& vd = vardata[x];
2507 // if we already have a reason, just return it
2508 if( vd.reason != CRef_Lazy )
2511 // what's the literal we are trying to explain
2512 Lit l = mkLit(x, value(x) != l_True);
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 ) ) );
2523 // remove theory propagation
2524 removeTheoryPropagation( vd.mExpPos );
2526 // sort the literals by trail index level
2528 Minisat::sort( explanation, lt );
2529 assert( explanation[0] == l );
2531 // compute the assertion level for this clause
2533 Lit prev = lit_Undef;
2534 for( i = 0, j = 0; i < explanation.size(); ++i )
2536 assert( value(explanation[i]) != l_Undef );
2537 assert( i == 0 || trailIndex(var(explanation[0])) > trailIndex(var(explanation[i])) );
2539 // always keep the first literal
2542 prev = explanation[j++] = explanation[i];
2545 // ignore duplicate literals
2546 if( explanation[i] == prev )
2548 // ignore zero level literals
2549 if( level(var(explanation[i])) == 0 )
2551 // keep this literal
2552 prev = explanation[j++] = explanation[i];
2554 explanation.shrink(i - j);
2556 // we need an explanation clause so we add a fake literal
2559 // add not TRUE to the clause
2560 explanation.push( mkLit( mTrueVar, true ) );
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);
2571 template<class Settings>
2572 void SATModule<Settings>::removeTheoryPropagation( int _position )
2574 assert( _position >= 0 );
2575 assert( (std::size_t)_position < mTheoryPropagations.size() );
2576 if( (std::size_t) _position != mTheoryPropagations.size()-1 )
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 );
2584 mTheoryPropagations.pop_back();
2587 template<class Settings>
2588 void SATModule<Settings>::theoryCall()
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;
2600 if( !mReceivedFormulaPurelyPropositional && decisionLevel() >= assumptions.size() &&
2601 (!Settings::try_full_lazy_call_first || mNumberOfFullLazyCalls > 0 || trail.size() == assigns.size()) )
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())
2608 adaptPassedFormula();
2610 bool finalCheck = fullAssignment();
2611 if( mChangedPassedFormula || finalCheck )
2613 #ifdef DEBUG_SATMODULE
2614 std::cout << "### Check the constraints: { "; for( auto& subformula : rPassedFormula() ) std::cout << subformula.formula() << " "; std::cout << "}" << std::endl;
2616 mChangedPassedFormula = false;
2617 mCurrentAssignmentConsistent = runBackends( finalCheck, mFullCheck, carl::Variable::NO_VARIABLE );
2618 SMTRAT_LOG_DEBUG("smtrat.sat", "Result: " << mCurrentAssignmentConsistent);
2619 switch( mCurrentAssignmentConsistent )
2623 case UNSAT: learnTheoryConflicts();
2628 mCurrentAssignmentConsistent = UNKNOWN;
2635 template<class Settings>
2636 bool SATModule<Settings>::expPositionsCorrect() const
2638 for( int i = 0; i < vardata.size(); ++i )
2640 if( vardata[i].reason == CRef_Lazy && vardata[i].mExpPos < 0 )
2646 template<class Settings>
2647 void SATModule<Settings>::constructLemmas()
2649 for( VarLemmaMap::const_iterator iter = mPropagatedLemmas.begin(); iter != mPropagatedLemmas.end(); ++iter )
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 )
2657 addLemma( FormulaT( carl::FormulaType::IMPLIES, premise, mvIter->second.negated() ) );
2661 assert( assigns[ iter->first ] == l_True );
2662 FormulaT lemma = FormulaT( carl::FormulaType::IMPLIES, premise, mvIter->second );
2668 template<class Settings>
2669 Minisat::lbool SATModule<Settings>::search( int nof_conflicts )
2675 mCurrentAssignmentConsistent = SAT;
2679 #ifdef DEBUG_SATMODULE
2680 std::cout << "######################################################################" << std::endl;
2681 std::cout << "### Next iteration" << std::endl;
2682 print(std::cout, "###");
2684 if( !mComputeAllSAT && anAnswerFound() )
2688 if (Settings::mc_sat) {
2689 SMTRAT_LOG_DEBUG("smtrat.sat", "MCSAT::BCP()");
2690 confl = propagateConsistently(false);
2693 SMTRAT_LOG_DEBUG("smtrat.sat", "DPLL::BCP()");
2694 confl = propagateConsistently();
2696 SMTRAT_LOG_TRACE("smtrat.sat", "Continuing after propagation, ok = " << ok << ", confl = " << confl);
2699 if( !mReceivedFormulaPurelyPropositional && !Settings::stop_search_after_first_unknown && mExcludedAssignments )
2701 // Maybe not needed here?: assert(mMCSAT.is_consistent());
2706 if( confl == CRef_Undef )
2708 SMTRAT_LOG_TRACE("smtrat.sat", "No conflict");
2709 if( Settings::check_if_all_clauses_are_satisfied && !mReceivedFormulaPurelyPropositional )
2711 if( decisionLevel() >= assumptions.size() && mNumberOfSatisfiedClauses == (size_t)clauses.size() )
2713 // Maybe not needed here?: assert(mMCSAT.is_consistent());
2717 if( Settings::use_restarts && nof_conflicts >= 0 && (conflictC >= nof_conflicts) ) // ||!withinBudget()) )
2719 #ifdef DEBUG_SATMODULE
2720 std::cout << "###" << std::endl << "### Restart." << std::endl << "###" << std::endl;
2722 // Reached bound on number of conflicts:
2723 progress_estimate = progressEstimate();
2726 #ifdef SMTRAT_DEVOPTION_Statistics
2727 mStatistics.restart();
2731 if( learnts.size() - nAssigns() >= max_learnts && rReceivedFormula().is_only_propositional() )
2733 // Reduce the set of learned clauses:
2737 SMTRAT_LOG_DEBUG("smtrat.sat", "Looking for next literal");
2738 Lit next = lit_Undef;
2739 while( decisionLevel() < assumptions.size() )
2741 // Perform user provided assumption:
2742 Lit p = assumptions[decisionLevel()];
2743 if( value( p ) == l_True )
2745 SMTRAT_LOG_DEBUG("smtrat.sat", "Assumption " << p << " is already true");
2746 // Dummy decision level:
2749 else if( value( p ) == l_False )
2751 SMTRAT_LOG_DEBUG("smtrat.sat", "Assumption " << p << " is already false");
2752 if( !mReceivedFormulaPurelyPropositional && !Settings::stop_search_after_first_unknown && mExcludedAssignments )
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());
2760 SMTRAT_LOG_DEBUG("smtrat.sat", "Deciding assumption " << p);
2767 * Look for literals that are
2768 * - fully assigned in the theory
2769 * - unassigned in boolean
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);
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));
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();
2801 #ifdef DEBUG_SATMODULE
2802 std::cout << "######################################################################" << std::endl;
2803 std::cout << "### Before handling conflict" << std::endl;
2804 print(std::cout, "###");
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);
2810 handleTheoryConflict(*conflict);
2811 #ifdef SMTRAT_DEVOPTION_Statistics
2812 mMCSATStatistics.theoryConflict();
2818 // If we do not already have a branching literal, we pick one
2819 if( next == lit_Undef )
2821 assert(!Settings::mc_sat || mMCSAT.fullConsistencyCheck());
2823 // New variable decision:
2825 #ifdef SMTRAT_DEVOPTION_Statistics
2826 mStatistics.decide();
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();
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");
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();
2861 assert(mMCSAT.is_consistent() == mMCSAT.fullConsistencyCheck());
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();
2871 handleTheoryConflict(std::get<mcsat::Explanation>(res));
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);
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();
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();
2899 } else if (Settings::mcsat_boolean_domain_propagation == MCSAT_BOOLEAN_DOMAIN_PROPAGATION::FULL) {
2900 auto res = mMCSAT.propagateBooleanDomain(next);
2902 SMTRAT_LOG_DEBUG("smtrat.sat", "Propagate " << next);
2903 uncheckedEnqueue( next, CRef_TPropagation );
2904 #ifdef SMTRAT_DEVOPTION_Statistics
2905 mMCSATStatistics.insertedLazyExplanation();
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();
2916 assert(boost::indeterminate(res.first));
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();
2926 SMTRAT_LOG_DEBUG("smtrat.sat", "Decision " << next << " is possible");
2929 } else if (Settings::mcsat_boolean_domain_propagation == MCSAT_BOOLEAN_DOMAIN_PROPAGATION::PARTIAL_CONFLICT) {
2930 auto res = mMCSAT.isBooleanDecisionFeasible(next, true);
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();
2942 #ifdef SMTRAT_DEVOPTION_Statistics
2943 mMCSATStatistics.booleanDecision();
2946 SMTRAT_LOG_DEBUG("smtrat.sat", "Deciding upon " << next);
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;
2955 SMTRAT_LOG_DEBUG("smtrat.sat", "-> " << next);
2956 if( next == lit_Undef )
2958 SMTRAT_LOG_DEBUG("smtrat.sat", "Entering SAT case");
2959 if( mReceivedFormulaPurelyPropositional || mCurrentAssignmentConsistent == SAT )
2962 if (Settings::mc_sat) assert(mMCSAT.is_consistent());
2967 SMTRAT_LOG_DEBUG("smtrat.sat", "Current assignment is unknown");
2968 assert( mCurrentAssignmentConsistent == UNKNOWN );
2969 if( Settings::stop_search_after_first_unknown )
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 );
2985 if( mReceivedFormulaPurelyPropositional || Settings::stop_search_after_first_unknown || next != lit_Undef )
2987 // Increase decision level and enqueue 'next'
2989 assert( bool_value( next ) == l_Undef );
2990 #ifdef DEBUG_SATMODULE
2991 std::cout << "### Decide " << (sign(next) ? "-" : "" ) << var(next) << std::endl;
2993 SMTRAT_CHECKPOINT("nlsat", "decision", next);
2994 uncheckedEnqueue( next );
2999 if( confl != CRef_Undef )
3001 SMTRAT_LOG_DEBUG("smtrat.sat", "Hit conflicting clause " << confl);
3004 #ifdef SMTRAT_DEVOPTION_Statistics
3005 mMCSATStatistics.booleanConflict();
3008 if( decisionLevel() <= assumptions.size() )
3010 if( !mReceivedFormulaPurelyPropositional && !Settings::stop_search_after_first_unknown && mExcludedAssignments ) {
3011 SMTRAT_LOG_DEBUG("smtrat.sat", "Return undef due to excluded: " << mExcludedAssignments);
3014 // TODO is that needed here?!?
3015 // assert(mMCSAT.is_consistent());
3019 // DPLL::resolve_conflict()
3020 handleConflict( confl );
3025 template<class Settings>
3026 void SATModule<Settings>::handleConflict( CRef _confl )
3028 learnt_clause.clear();
3029 assert( _confl != CRef_Undef );
3030 SMTRAT_LOG_DEBUG("smtrat.sat", "Conflict clause: " << _confl);
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 );
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;
3045 SMTRAT_CHECKPOINT("nlsat", "backtrack", backtrack_level);
3047 if(Settings::mc_sat) {
3048 cancelUntil( backtrack_level, true );
3050 cancelUntil( backtrack_level );
3053 #ifdef DEBUG_SATMODULE
3054 print(std::cout, "###");
3057 if (Settings::mc_sat) {
3058 //for (int i = 0; i < learnt_clause.size(); i++) {
3059 // valueAndUpdate(learnt_clause[i]);
3061 Minisat::sort(learnt_clause, lemma_lt(*this));
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 )
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] );
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] );
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();
3094 SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Decide literal as clause is not asserting");
3095 assert(assumptions.size() <= backtrack_level);
3097 uncheckedEnqueue( learnt_clause[0], _confl );
3100 SMTRAT_CHECKPOINT("nlsat", "propagation", _confl, learnt_clause[0]);
3101 uncheckedEnqueue( learnt_clause[0], _confl );
3103 decrementLearntSizeAdjustCnt();
3110 template<class Settings>
3111 void SATModule<Settings>::decrementLearntSizeAdjustCnt()
3113 if( --learntsize_adjust_cnt == 0 )
3115 learntsize_adjust_confl *= learntsize_adjust_inc;
3116 learntsize_adjust_cnt = (int)learntsize_adjust_confl;
3117 max_learnts *= learntsize_inc;
3119 if( verbosity >= 1 )
3120 printf( "| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n",
3122 (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]),
3124 (int)clauses_literals,
3127 (double)learnts_literals / nLearnts(),
3128 progressEstimate() * 100 );
3132 template<class Settings>
3133 bool SATModule<Settings>::fullAssignment()
3135 return var_scheduler.empty();
3138 template<class Settings>
3139 Lit SATModule<Settings>::pickBranchLit()
3143 if( /*!mReceivedFormulaPurelyPropositional &&*/ Settings::check_active_literal_occurrences && false)
3145 Var next_var = var_Undef;
3146 while( next_var == var_Undef && !mPropagationFreeDecisions.empty() )
3148 Lit l = mPropagationFreeDecisions.back();
3149 mPropagationFreeDecisions.pop_back();
3150 if( assigns[var(l)] == l_Undef )
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();
3164 for (auto it = vars.rbegin(); it != vars.rend(); it++) {
3165 var_scheduler.insert(*it);
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);
3174 template<class Settings>
3175 bool SATModule<Settings>::analyze( CRef confl, vec<Lit>& out_learnt, int& out_btlevel )
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;
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;
3195 // Generate conflict clause:
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;
3201 std::set<Minisat::Var> seenTheoryVars; // for MCSAT theory var bumping
3205 SMTRAT_LOG_DEBUG("smtrat.sat", "out_learnt = " << out_learnt);
3207 assert( confl != CRef_Undef ); // (otherwise should be UIP)
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();
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));
3220 if (explanation.is_nary()) {
3221 for (const auto& f: explanation) {
3222 expClause.push(createLiteral(f));
3226 expClause.push(createLiteral(explanation));
3228 SMTRAT_LOG_DEBUG("smtrat.sat", "Explanation for " << p << ": " << expClause);
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);
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]);
3249 Clause& c = ca[confl];
3250 sat::detail::validateClause(c, mMinisatVarMap, mBooleanConstraintMap, Settings::validate_clauses);
3251 SMTRAT_LOG_DEBUG("smtrat.sat", "c = " << c);
3253 claBumpActivity( c );
3255 // assert that c[0] is actually p
3256 for( int j = (p == lit_Undef) ? 0 : 0; j < c.size(); 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);
3265 if( !seen[var( q )] && qlevel > 0 )
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);
3275 //if (Settings::mc_sat && reason(var(q)) == CRef_TPropagation) {
3276 // SMTRAT_LOG_DEBUG("smtrat.sat", "\t" << q << " is result of theory propagation");
3278 // SMTRAT_LOG_DEBUG("smtrat.sat", "\tTo process: " << q << ", pathC = " << pathC);
3280 if (bool_value(q) == l_Undef) {
3282 SMTRAT_LOG_DEBUG("smtrat.sat", "\tq is false by theory assignment, forwarding to out_learnt.");
3284 else if( level(var(q)) == qlevel && qlevel >= decisionLevel() ) {
3286 SMTRAT_LOG_DEBUG("smtrat.sat", "\tTo process: " << q << ", pathC = " << pathC);
3289 SMTRAT_LOG_DEBUG("smtrat.sat", "\tpushing = " << q << " to out_learnt");
3290 out_learnt.push( q );
3296 if (!Settings::mcsat_learn_lazy_explanations) {
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);
3309 SMTRAT_LOG_DEBUG("smtrat.sat", "Still on highest DL, pathC = " << pathC);
3314 if (Settings::mc_sat) {
3315 for (auto tvar : seenTheoryVars) {
3316 varBumpActivity(tvar);
3320 if (Settings::mc_sat) {
3322 for (int i = 1; i < out_learnt.size(); i++) {
3323 if (out_learnt[i] == ~p) found = true;
3325 if (!found) out_learnt[0] = ~p;
3327 out_learnt[0] = out_learnt[out_learnt.size()-1];
3334 SMTRAT_LOG_DEBUG("smtrat.sat", "Before sorting " << out_learnt);
3335 if (Settings::mc_sat) {
3336 Minisat::sort(out_learnt, lemma_lt(*this));
3338 SMTRAT_LOG_DEBUG("smtrat.sat", "After sorting " << out_learnt);
3340 // Simplify conflict clause:
3343 out_learnt.copyTo( analyze_toclear );
3344 if( !Settings::mc_sat && ccmin_mode == 2 )
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)
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];
3355 else if( !Settings::mc_sat && ccmin_mode == 1 )
3357 for( i = j = 1; i < out_learnt.size(); i++ )
3359 Var x = var( out_learnt[i] );
3361 if( reason( x ) == CRef_Undef )
3362 out_learnt[j++] = out_learnt[i];
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 )
3369 out_learnt[j++] = out_learnt[i];
3376 i = j = out_learnt.size();
3378 max_literals += (uint64_t)out_learnt.size();
3379 out_learnt.shrink( i - j );
3380 tot_literals += (uint64_t)out_learnt.size();
3382 // Find correct backtrack level:
3384 if( out_learnt.size() == 1 )
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());
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];
3402 out_btlevel = levels[0]-1;
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;
3410 levels.erase(std::unique(levels.begin(), levels.end()), levels.end());
3411 out_btlevel = levels[1];
3414 out_btlevel = levels[0]-1;
3417 SMTRAT_LOG_DEBUG("smtrat.sat", "-> " << out_btlevel << " (" << out_learnt << ")");
3418 assert(out_btlevel >= 0);
3420 SMTRAT_LOG_DEBUG("smtrat.sat", "Figuring out level to backtrack to for " << out_learnt);
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) {
3430 max_lvl = currentLitLevel;
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];
3438 out_btlevel = max_lvl;
3439 SMTRAT_LOG_DEBUG("smtrat.sat", "-> " << out_btlevel << " (" << out_learnt << ")");
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;
3448 template<class Settings>
3449 bool SATModule<Settings>::litRedundant( Lit p, uint32_t abstract_levels )
3451 analyze_stack.clear();
3452 analyze_stack.push( p );
3453 int top = analyze_toclear.size();
3454 while( analyze_stack.size() > 0 )
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();
3462 for( int i = 1; i < c_size; i++ )
3464 Lit p = ca[c_reason][i];
3465 if( !seen[var( p )] && level( var( p ) ) > 0 )
3467 if( reason( var( p ) ) != CRef_Undef && (abstractLevel( var( p ) ) & abstract_levels) != 0 )
3470 analyze_stack.push( p );
3471 analyze_toclear.push( p );
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 );
3487 template<class Settings>
3488 void SATModule<Settings>::uncheckedEnqueue( Lit p, CRef from )
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() )
3494 auto litClausesIter = mLiteralClausesMap.find( Minisat::toInt( p ) );
3495 if( litClausesIter != mLiteralClausesMap.end() )
3497 for( CRef cl : litClausesIter->second )
3499 if( !satisfied( ca[cl] ) )
3501 assert( mNumberOfSatisfiedClauses < (size_t)clauses.size() );
3502 ++mNumberOfSatisfiedClauses;
3507 if( /*!mReceivedFormulaPurelyPropositional &&*/ Settings::check_active_literal_occurrences )
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 )
3514 const Clause& c = ca[cr];
3515 // Check if clause is not yet satisfied.
3516 if( !bool_satisfied(c) )
3518 for( int i = 0; i < c.size(); ++i )
3520 size_t v = (size_t)var(c[i]);
3521 std::pair<size_t,size_t>& litActOccs = mLiteralsActivOccurrences[v];
3524 assert( litActOccs.second > 0 );
3525 --(litActOccs.second);
3529 assert( litActOccs.first > 0 );
3530 --(litActOccs.first);
3532 if( litActOccs.first == 0 )
3534 if( litActOccs.second == 0 )
3535 decision[var(c[i])] = false;
3537 mPropagationFreeDecisions.push_back( mkLit( var(c[i]), true ) );
3541 if( litActOccs.second == 0 )
3542 mPropagationFreeDecisions.push_back( mkLit( var(c[i]), false ) );
3548 assigns[var( p )] = Minisat::lbool( !sign( p ) );
3549 if (Settings::mc_sat) {
3550 mMCSAT.doBooleanAssignment(p);
3552 if( !mReceivedFormulaPurelyPropositional && mBooleanConstraintMap[var( p )].first != nullptr )
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 ) );
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
3569 if( ++abstr.updateInfo > 0 )
3571 unsigned res = currentlySatisfiedByBackend( abstr.reabstraction );
3574 mCurrentAssignmentConsistent = UNKNOWN;
3576 mChangedBooleans.push_back( var( p ) );
3580 vardata[var( p )] = VarData( from, decisionLevel(), trail.size() );
3585 vardata[var( p )] = VarData( from, decisionLevel(), trail.size() );
3589 // Save reasons (clauses) implicating a variable value
3590 if (isLemmaLevel(LemmaLevel::NORMAL) && decisionLevel() == 0 && !mComputeAllSAT)
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) );
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 );
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() )
3615 // Insert formulas from contained variable into set for current variable
3616 pFormulas->insert( pFormulas->end(), itFormulas->second.begin(), itFormulas->second.end() );
3621 if( !mReceivedFormulaPurelyPropositional && Settings::formula_guided_decision_heuristic )
3623 auto iter = mTseitinVarShadows.find( (signed) var(p) );
3624 if( iter != mTseitinVarShadows.end() )
3626 for( signed var : iter->second )
3628 incrementTseitinShadowOccurrences(var);
3634 template<class Settings>
3635 CRef SATModule<Settings>::propagate()
3637 CRef confl = CRef_Undef;
3641 while( qhead < trail.size() )
3643 Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate.
3644 vec<Watcher>& ws = watches[p];
3645 Watcher * i, *j, *end;
3647 SMTRAT_LOG_DEBUG("smtrat.sat.bcp", "Current literal: " << p);
3649 for( i = j = (Watcher*)ws, end = i + ws.size(); i != end; )
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 )
3656 SMTRAT_LOG_TRACE("smtrat.sat.bcp", "Skipping clause " << i->cref << " due to blocker " << i->blocker);
3661 // Make sure the false literal is data[1]:
3664 SMTRAT_LOG_TRACE("smtrat.sat.bcp", "Analyzing clause " << c);
3666 if( c[0] == false_lit )
3667 c[0] = c[1], c[1] = false_lit;
3668 assert( c[1] == false_lit );
3671 SMTRAT_LOG_TRACE("smtrat.sat.bcp", "Clause is now " << c << " after moving the false literal");
3673 // If 0th watch is true, then clause is already satisfied.
3675 Watcher w = Watcher( cr, first );
3676 if( first != blocker && value( first ) == l_True )
3678 SMTRAT_LOG_DEBUG("smtrat.sat.bcp", "Clause " << c << " is satisfied by " << first);
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) {
3690 if( value( c[k] ) != l_False )
3694 watches[~c[1]].push( w );
3695 SMTRAT_LOG_TRACE("smtrat.sat.bcp", "Clause is now " << c << " after setting " << c[1] << " as new watch");
3700 SMTRAT_LOG_TRACE("smtrat.sat.bcp", "Clause is now " << c << " after no new watch was found");
3702 // Did not find watch -- clause is unit under assignment:
3704 if( value( first ) == l_False )
3706 SMTRAT_LOG_DEBUG("smtrat.sat.bcp", "Clause is conflicting " << c);
3707 SMTRAT_CHECKPOINT("nlsat", "conflict-clause", cr);
3709 qhead = trail.size();
3710 // Copy the remaining watches:
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);
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();
3732 ws.shrink( (int) (i - j) );
3734 propagations += (uint64_t)num_props;
3735 // simpDB_props -= (uint64_t)num_props;
3736 SMTRAT_LOG_TRACE("smtrat.sat.bcp", "Returning " << confl);
3742 ClauseAllocator& ca;
3744 reduceDB_lt( ClauseAllocator& ca_ ):
3747 bool operator ()( CRef x, CRef y )
3749 return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity());
3753 template<class Settings>
3754 void SATModule<Settings>::reduceDB()
3757 double extra_lim = cla_inc / learnts.size(); // Remove any clause below this activity
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++ )
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) )
3768 removeClause( learnts[i] );
3771 learnts[j++] = learnts[i];
3773 learnts.shrink( i - j );
3777 template<class Settings>
3778 void SATModule<Settings>::clearLearnts( int n )
3780 for( int i = n; i < learnts.size(); ++i )
3782 removeClause( learnts[i] );
3784 learnts.shrink( learnts.size() - n );
3787 template<class Settings>
3788 void SATModule<Settings>::removeSatisfied( vec<CRef>& cs )
3791 for( i = j = 0; i < cs.size(); i++ )
3793 Clause& c = ca[cs[i]];
3794 if( satisfied( c ) )
3795 removeClause( cs[i] );
3802 template<class Settings>
3803 void SATModule<Settings>::simplify()
3805 assert( decisionLevel() == assumptions.size() );
3806 #ifdef DEBUG_SATMODULE
3807 std::cout << __func__ << std::endl;
3811 if( propagate() != CRef_Undef )
3813 SMTRAT_LOG_DEBUG("smtrat.sat", "ok = false");
3817 if( nAssigns() == simpDB_assigns )// || (simpDB_props > 0) )
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())
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)
3834 template<class Settings>
3835 bool SATModule<Settings>::processLemmas()
3837 bool lemmasLearned = false;
3838 std::vector<Module*>::const_iterator backend = usedBackends().begin();
3839 while( backend != usedBackends().end() )
3841 // Learn the lemmas.
3842 (*backend)->updateLemmas();
3843 if( !(mCurrentAssignmentConsistent == SAT && fullAssignment()) )
3845 for( const auto& lem : (*backend)->lemmas() )
3847 if( lem.mLemma.type() != carl::FormulaType::TRUE )
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();
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;
3857 addClauses( lem.mLemma, lem.mLemmaType == LemmaType::PERMANENT ? PERMANENT_CLAUSE : LEMMA_CLAUSE );
3858 if( numOfLearnts < mLemmas.size() )
3859 lemmasLearned = true;
3863 (*backend)->clearLemmas();
3866 return lemmasLearned;
3869 template<class Settings>
3870 void SATModule<Settings>::learnTheoryConflicts()
3872 std::vector<Module*>::const_iterator backend = usedBackends().begin();
3873 while( backend != usedBackends().end() )
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);
3881 assert( (*backend)->solverState() != UNSAT || !infSubsets.empty() );
3882 for( auto infsubset = infSubsets.begin(); infsubset != infSubsets.end(); ++infsubset )
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 )
3891 if( mUpperBoundOnMinimal != passedFormulaEnd() && mUpperBoundOnMinimal->formula() == *subformula )
3893 containsUpperBoundOnMinimal = true;
3896 // add literal to clause
3897 explanation.push( neg( getLiteral( *subformula ) ) );
3899 addClause( explanation, containsUpperBoundOnMinimal ? PERMANENT_CLAUSE : CONFLICT_CLAUSE );
3905 template<class Settings>
3906 void SATModule<Settings>::adaptConflictEvaluation( size_t& _clauseEvaluation, Lit _lit, bool _firstLiteral )
3908 switch( Settings::conflict_clause_evaluation_strategy )
3910 case CCES::SECOND_LEVEL_MINIMIZER:
3912 size_t litLevel = (size_t) level( var( _lit ) );
3913 if( _firstLiteral || litLevel > _clauseEvaluation )
3914 _clauseEvaluation = litLevel;
3917 case CCES::LITERALS_BLOCKS_DISTANCE:
3921 mLevelCounter.clear();
3922 _clauseEvaluation = 0;
3924 if( mLevelCounter.insert( level( var( _lit ) ) ).second )
3925 ++_clauseEvaluation;
3928 case CCES::SECOND_LEVEL_MINIMIZER_PLUS_LBD:
3930 size_t litLevel = (size_t) level( var( _lit ) ) * (size_t) decisionLevel();
3933 mLevelCounter.clear();
3934 mLevelCounter.insert( level( var( _lit ) ) );
3935 _clauseEvaluation = litLevel + 1;
3939 bool levelAdded = mLevelCounter.insert( level( var( _lit ) ) ).second;
3940 if( litLevel > _clauseEvaluation )
3941 _clauseEvaluation = litLevel + mLevelCounter.size();
3942 else if( levelAdded )
3943 ++_clauseEvaluation;
3954 template<class Settings>
3955 double SATModule<Settings>::progressEstimate() const
3957 double progress = 0;
3958 double F = 1.0 / nVars();
3960 for( int i = 0; i <= decisionLevel(); i++ )
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);
3967 return progress / nVars();
3970 template<class Settings>
3971 void SATModule<Settings>::relocAll( ClauseAllocator& to )
3973 // relocate clauses in mFormulaClausesMap
3974 for( auto& iter : mFormulaCNFInfosMap )
3976 std::vector<CRef> tmp;
3977 for( CRef c : iter.second.mClauses )
3980 tmp.insert( tmp.end(), c );
3982 iter.second.mClauses = std::move( tmp );
3985 carl::FastMap<Minisat::CRef,ClauseInformation> tmp;
3986 for( auto& ciPair : mClauseInformation )
3988 CRef c = ciPair.first;
3990 tmp.emplace( c, ciPair.second );
3992 mClauseInformation = std::move( tmp );
3994 if( Settings::check_if_all_clauses_are_satisfied )
3996 for( auto& lcsPair : mLiteralClausesMap )
3998 std::unordered_set<CRef>& cls = lcsPair.second;
3999 std::unordered_set<CRef> tmp;
4003 tmp.insert( tmp.end(), c );
4005 cls = std::move(tmp);
4009 if( /*!mReceivedFormulaPurelyPropositional &&*/ Settings::check_active_literal_occurrences )
4011 for( auto& cls : mLiteralsClausesMap )
4013 cls.reloc( ca, to );
4017 var_scheduler.relocateClauses([&](Minisat::CRef& cl) { ca.reloc(cl, to); });
4021 // for (int i = 0; i < watches.size(); i++)
4023 for( int v = 0; v < nVars(); v++ )
4024 for( int s = 0; s < 2; s++ )
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 );
4035 for( int i = 0; i < trail.size(); i++ )
4037 Var v = var( trail[i] );
4039 if( reason( v ) != CRef_Undef && (ca[reason( v )].reloced() || locked( ca[reason( v )] )) )
4040 ca.reloc( vardata[v].reason, to );
4045 for( int i = 0; i < learnts.size(); i++ )
4046 ca.reloc( learnts[i], to );
4050 for( int i = 0; i < clauses.size(); i++ )
4051 ca.reloc( clauses[i], to );
4054 template<class Settings>
4055 void SATModule<Settings>::garbageCollect()
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 );
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 );
4069 template<class Settings>
4070 Var SATModule<Settings>::mapVar( Var x, vec<Var>& map, Var& max )
4072 if( map.size() <= x || map[x] == -1 )
4074 map.growTo( x + 1, -1 );
4080 template<class Settings>
4081 void SATModule<Settings>::print( std::ostream& _out, const std::string& _init ) const
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;
4101 template<class Settings>
4102 void SATModule<Settings>::printConstraintLiteralMap( std::ostream& _out, const std::string& _init ) const
4104 _out << _init << " ConstraintLiteralMap" << std::endl;
4105 for( ConstraintLiteralsMap::const_iterator clPair = mConstraintLiteralMap.begin(); clPair != mConstraintLiteralMap.end(); ++clPair )
4107 _out << _init << " " << clPair->first << " -> [";
4108 for( auto litIter = clPair->second.begin(); litIter != clPair->second.end(); ++litIter )
4111 if( sign( *litIter ) )
4115 _out << var( *litIter );
4117 _out << " ]" << std::endl;
4121 template<class Settings>
4122 void SATModule<Settings>::printFormulaCNFInfosMap( std::ostream& _out, const std::string& _init ) const
4124 _out << _init << " FormulaCNFInfosMap" << std::endl;
4125 for( const auto& fcsPair : mFormulaCNFInfosMap )
4127 _out << _init << " " << fcsPair.first << std::endl;
4128 _out << _init << " Literal: " << fcsPair.second.mLiteral;
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;
4138 template<class Settings>
4139 void SATModule<Settings>::printClauseInformation( std::ostream& _out, const std::string& _init ) const
4141 _out << _init << " ClauseInformation" << std::endl;
4142 for( auto& ciPair : mClauseInformation )
4144 _out << _init << " " << ciPair.first << " -> (stored in satisfied: " << (ciPair.second.mStoredInSatisfied ? "yes" : "no") << ", position: " << ciPair.second.mPosition << ")" << std::endl;
4148 template<class Settings>
4149 void SATModule<Settings>::printBooleanVarMap( std::ostream& _out, const std::string& _init ) const
4151 _out << _init << " BooleanVarMap" << std::endl;
4152 for( BooleanVarMap::const_iterator clPair = mBooleanVarMap.begin(); clPair != mBooleanVarMap.end(); ++clPair )
4154 _out << _init << " " << clPair->first << " -> " << clPair->second;
4155 auto tvfIter = mTseitinVarFormulaMap.find( (int)clPair->second );
4156 if( tvfIter != mTseitinVarFormulaMap.end() )
4157 _out << " ( " << tvfIter->second << " )";
4162 template<class Settings>
4163 void SATModule<Settings>::printBooleanConstraintMap( std::ostream& _out, const std::string& _init ) const
4165 _out << _init << " BooleanConstraintMap" << std::endl;
4166 for( int k = 0; k < mBooleanConstraintMap.size(); ++k )
4168 if( mBooleanConstraintMap[k].first != nullptr )
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;
4177 _out << _init << " Boolean Variables" << std::endl;
4178 for( const auto& it: mMinisatVarMap )
4180 _out << _init << " " << it.first << " -> " << it.second << std::endl;
4184 template<class Settings>
4185 void SATModule<Settings>::printClause( const vec<Lit>& _clause, bool _withAssignment, std::ostream& _out, const std::string& _init ) const
4188 for( int pos = 0; pos < _clause.size(); ++pos )
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] ) ) << ")";
4197 template<class Settings>
4198 void SATModule<Settings>::printClause( CRef _clause, bool _withAssignment, std::ostream& _out, const std::string& _init ) const
4200 const Clause& c = ca[_clause];
4202 for( int pos = 0; pos < c.size(); ++pos )
4204 _out << " " << c[pos];
4205 if( _withAssignment )
4207 _out << " [" << (value( c[pos] ) == l_True ? "true@" : (value( c[pos] ) == l_False ? "false@" : "undef"));
4208 if( value( c[pos] ) != l_Undef )
4210 _out << level( var( c[pos] ) );
4215 _out << " [" << ((uint32_t) _clause) << "]" << std::endl;
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
4221 _out << _init << " " << _name << ":" << std::endl;
4222 // Handle case when solver is in contradictory state:
4225 _out << _init << " p cnf 1 2" << std::endl;
4226 _out << _init << " 1 0" << std::endl;
4227 _out << _init << " -1 0" << std::endl;
4234 // Cannot use removeClauses here because it is not safe
4235 // to deallocate them at this point. Could be improved.
4237 for( int i = _from; i < _clauses.size(); i++ )
4238 if( !satisfied( ca[_clauses[i]] ) )
4241 for( int i = _from; i < _clauses.size(); i++ )
4242 if( !satisfied( ca[_clauses[i]] ) )
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 );
4250 // Assumptions are added as unit clauses:
4251 cnt += assumptions.size();
4253 _out << _init << " p cnf " << max << " " << cnt << std::endl;
4255 for( int i = 0; i < assumptions.size(); i++ )
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;
4261 for( int i = _from; i < _clauses.size(); i++ )
4263 if( !_onlyNotSatisfied || !satisfied(ca[_clauses[i]]) )
4265 _out << _init << " " << i;
4266 if( !_onlyNotSatisfied )
4267 _out << (satisfied(ca[_clauses[i]]) ? " (ok)" : " ");
4269 printClause( _clauses[i], _withAssignment, _out, "" );
4275 _out << _init << " Wrote " << cnt << " clauses with " << max << " variables." << std::endl;
4278 template<class Settings>
4279 void SATModule<Settings>::printCurrentAssignment( std::ostream& _out, const std::string& _init ) const
4281 _out << _init << " Assignments: ";
4282 for( int pos = 0; pos < assigns.size(); ++pos )
4286 _out << _init << " ";
4288 _out << std::setw( 5 ) << pos;
4289 _out << " (" << std::setw( 7 ) << activity[pos] << ") " << " -> ";
4290 if( assigns[pos] == 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 << " )";
4298 auto tvfIter = mTseitinVarFormulaMap.find( pos );
4299 if( tvfIter != mTseitinVarFormulaMap.end() )
4300 _out << " ( " << tvfIter->second << " )";
4304 else if( assigns[pos] == 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 << " )";
4312 auto tvfIter = mTseitinVarFormulaMap.find( pos );
4313 if( tvfIter != mTseitinVarFormulaMap.end() )
4314 _out << " ( " << tvfIter->second.negated() << " )";
4320 _out << "l_Undef" << std::endl;
4325 template<class Settings>
4326 void SATModule<Settings>::printDecisions( std::ostream& _out, const std::string& _init ) const
4328 _out << _init << " Decisions: ";
4330 for( int pos = 0; pos < trail.size(); ++pos )
4332 if( level < trail_lim.size() )
4334 if( pos == trail_lim[level] )
4341 _out << _init << " ";
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)
4350 _out << " ( " << mBooleanConstraintMap[v].first->reabstraction << " )";
4351 _out << " [" << mBooleanConstraintMap[v].first->updateInfo << "]";
4353 else if (assigns[v] == l_False && mBooleanConstraintMap[v].second != nullptr)
4355 _out << " ( " << mBooleanConstraintMap[v].second->reabstraction << " )";
4356 _out << " [" << mBooleanConstraintMap[v].second->updateInfo << "]";
4359 _out << " ( " << static_cast<const void*>(mBooleanConstraintMap[v].first) << " / " << static_cast<const void*>(mBooleanConstraintMap[v].second) << " )";
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;
4369 template<class Settings>
4370 void SATModule<Settings>::printPropagatedLemmas( std::ostream& _out, const std::string& _init ) const
4372 _out << _init << " Propagated lemmas:" << std::endl;
4373 for( VarLemmaMap::const_iterator itFormulas = mPropagatedLemmas.begin(); itFormulas != mPropagatedLemmas.end(); ++itFormulas )
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 )
4381 if ( iter != formulas.begin() )
4387 _out << " }" << std::endl;
4391 template<class Settings>
4392 void SATModule<Settings>::printLiteralsActiveOccurrences( std::ostream& _out, const std::string& _init ) const
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;
4399 template<class Settings>
4400 void SATModule<Settings>::collectStats()
4402 #ifdef SMTRAT_DEVOPTION_Statistics
4403 mStatistics.rNrTotalVariablesAfter() = (size_t) nVars();
4404 mStatistics.rNrClauses() = (size_t) nClauses();
4407 } // namespace smtrat