mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Replace; #define __STDC_LIMIT_MACROS #define __STDC_FORMAT_MACROS With #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS #endif #ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS #endif This fixes a compile warning if you are defining these macros in your CXXFLAGS (as some distros do).
		
			
				
	
	
		
			1072 lines
		
	
	
	
		
			34 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1072 lines
		
	
	
	
		
			34 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#ifndef __STDC_FORMAT_MACROS
 | 
						|
#define __STDC_FORMAT_MACROS
 | 
						|
#endif
 | 
						|
#ifndef __STDC_LIMIT_MACROS
 | 
						|
#define __STDC_LIMIT_MACROS
 | 
						|
#endif
 | 
						|
/***************************************************************************************[Solver.cc]
 | 
						|
Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
 | 
						|
Copyright (c) 2007-2010, Niklas Sorensson
 | 
						|
 | 
						|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 | 
						|
associated documentation files (the "Software"), to deal in the Software without restriction,
 | 
						|
including without limitation the rights to use, copy, modify, merge, publish, distribute,
 | 
						|
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 | 
						|
furnished to do so, subject to the following conditions:
 | 
						|
 | 
						|
The above copyright notice and this permission notice shall be included in all copies or
 | 
						|
substantial portions of the Software.
 | 
						|
 | 
						|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
 | 
						|
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
						|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 | 
						|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
 | 
						|
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
						|
**************************************************************************************************/
 | 
						|
 | 
						|
#include <math.h>
 | 
						|
 | 
						|
#include "Alg.h"
 | 
						|
#include "Sort.h"
 | 
						|
#include "System.h"
 | 
						|
#include "Solver.h"
 | 
						|
 | 
						|
using namespace Minisat;
 | 
						|
 | 
						|
//=================================================================================================
 | 
						|
// Options:
 | 
						|
 | 
						|
 | 
						|
static const char* _cat = "CORE";
 | 
						|
 | 
						|
static DoubleOption  opt_var_decay         (_cat, "var-decay",   "The variable activity decay factor",            0.95,     DoubleRange(0, false, 1, false));
 | 
						|
static DoubleOption  opt_clause_decay      (_cat, "cla-decay",   "The clause activity decay factor",              0.999,    DoubleRange(0, false, 1, false));
 | 
						|
static DoubleOption  opt_random_var_freq   (_cat, "rnd-freq",    "The frequency with which the decision heuristic tries to choose a random variable", 0, DoubleRange(0, true, 1, true));
 | 
						|
static DoubleOption  opt_random_seed       (_cat, "rnd-seed",    "Used by the random variable selection",         91648253, DoubleRange(0, false, HUGE_VAL, false));
 | 
						|
static IntOption     opt_ccmin_mode        (_cat, "ccmin-mode",  "Controls conflict clause minimization (0=none, 1=basic, 2=deep)", 2, IntRange(0, 2));
 | 
						|
static IntOption     opt_phase_saving      (_cat, "phase-saving", "Controls the level of phase saving (0=none, 1=limited, 2=full)", 2, IntRange(0, 2));
 | 
						|
static BoolOption    opt_rnd_init_act      (_cat, "rnd-init",    "Randomize the initial activity", false);
 | 
						|
static BoolOption    opt_luby_restart      (_cat, "luby",        "Use the Luby restart sequence", true);
 | 
						|
static IntOption     opt_restart_first     (_cat, "rfirst",      "The base restart interval", 100, IntRange(1, INT32_MAX));
 | 
						|
static DoubleOption  opt_restart_inc       (_cat, "rinc",        "Restart interval increase factor", 2, DoubleRange(1, false, HUGE_VAL, false));
 | 
						|
static DoubleOption  opt_garbage_frac      (_cat, "gc-frac",     "The fraction of wasted memory allowed before a garbage collection is triggered",  0.20, DoubleRange(0, false, HUGE_VAL, false));
 | 
						|
static IntOption     opt_min_learnts_lim   (_cat, "min-learnts", "Minimum learnt clause limit",  0, IntRange(0, INT32_MAX));
 | 
						|
 | 
						|
 | 
						|
//=================================================================================================
 | 
						|
// Constructor/Destructor:
 | 
						|
 | 
						|
 | 
						|
Solver::Solver() :
 | 
						|
 | 
						|
    // Parameters (user settable):
 | 
						|
    //
 | 
						|
    verbosity        (0)
 | 
						|
  , var_decay        (opt_var_decay)
 | 
						|
  , clause_decay     (opt_clause_decay)
 | 
						|
  , random_var_freq  (opt_random_var_freq)
 | 
						|
  , random_seed      (opt_random_seed)
 | 
						|
  , luby_restart     (opt_luby_restart)
 | 
						|
  , ccmin_mode       (opt_ccmin_mode)
 | 
						|
  , phase_saving     (opt_phase_saving)
 | 
						|
  , rnd_pol          (false)
 | 
						|
  , rnd_init_act     (opt_rnd_init_act)
 | 
						|
  , garbage_frac     (opt_garbage_frac)
 | 
						|
  , min_learnts_lim  (opt_min_learnts_lim)
 | 
						|
  , restart_first    (opt_restart_first)
 | 
						|
  , restart_inc      (opt_restart_inc)
 | 
						|
 | 
						|
    // Parameters (the rest):
 | 
						|
    //
 | 
						|
  , learntsize_factor((double)1/(double)3), learntsize_inc(1.1)
 | 
						|
 | 
						|
    // Parameters (experimental):
 | 
						|
    //
 | 
						|
  , learntsize_adjust_start_confl (100)
 | 
						|
  , learntsize_adjust_inc         (1.5)
 | 
						|
 | 
						|
    // Statistics: (formerly in 'SolverStats')
 | 
						|
    //
 | 
						|
  , solves(0), starts(0), decisions(0), rnd_decisions(0), propagations(0), conflicts(0)
 | 
						|
  , dec_vars(0), num_clauses(0), num_learnts(0), clauses_literals(0), learnts_literals(0), max_literals(0), tot_literals(0)
 | 
						|
 | 
						|
  , watches            (WatcherDeleted(ca))
 | 
						|
  , order_heap         (VarOrderLt(activity))
 | 
						|
  , ok                 (true)
 | 
						|
  , cla_inc            (1)
 | 
						|
  , var_inc            (1)
 | 
						|
  , qhead              (0)
 | 
						|
  , simpDB_assigns     (-1)
 | 
						|
  , simpDB_props       (0)
 | 
						|
  , progress_estimate  (0)
 | 
						|
  , remove_satisfied   (true)
 | 
						|
  , next_var           (0)
 | 
						|
 | 
						|
    // Resource constraints:
 | 
						|
    //
 | 
						|
  , conflict_budget    (-1)
 | 
						|
  , propagation_budget (-1)
 | 
						|
  , asynch_interrupt   (false)
 | 
						|
{}
 | 
						|
 | 
						|
 | 
						|
Solver::~Solver()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//=================================================================================================
 | 
						|
// Minor methods:
 | 
						|
 | 
						|
 | 
						|
// Creates a new SAT variable in the solver. If 'decision' is cleared, variable will not be
 | 
						|
// used as a decision variable (NOTE! This has effects on the meaning of a SATISFIABLE result).
 | 
						|
//
 | 
						|
Var Solver::newVar(lbool upol, bool dvar)
 | 
						|
{
 | 
						|
    Var v;
 | 
						|
    if (free_vars.size() > 0){
 | 
						|
        v = free_vars.last();
 | 
						|
        free_vars.pop();
 | 
						|
    }else
 | 
						|
        v = next_var++;
 | 
						|
 | 
						|
    watches  .init(mkLit(v, false));
 | 
						|
    watches  .init(mkLit(v, true ));
 | 
						|
    assigns  .insert(v, l_Undef);
 | 
						|
    vardata  .insert(v, mkVarData(CRef_Undef, 0));
 | 
						|
    activity .insert(v, rnd_init_act ? drand(random_seed) * 0.00001 : 0);
 | 
						|
    seen     .insert(v, 0);
 | 
						|
    polarity .insert(v, true);
 | 
						|
    user_pol .insert(v, upol);
 | 
						|
    decision .reserve(v);
 | 
						|
    trail    .capacity(v+1);
 | 
						|
    setDecisionVar(v, dvar);
 | 
						|
    return v;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Note: at the moment, only unassigned variable will be released (this is to avoid duplicate
 | 
						|
// releases of the same variable).
 | 
						|
void Solver::releaseVar(Lit l)
 | 
						|
{
 | 
						|
    if (value(l) == l_Undef){
 | 
						|
        addClause(l);
 | 
						|
        released_vars.push(var(l));
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool Solver::addClause_(vec<Lit>& ps)
 | 
						|
{
 | 
						|
    assert(decisionLevel() == 0);
 | 
						|
    if (!ok) return false;
 | 
						|
 | 
						|
    // Check if clause is satisfied and remove false/duplicate literals:
 | 
						|
    sort(ps);
 | 
						|
    Lit p; int i, j;
 | 
						|
    for (i = j = 0, p = lit_Undef; i < ps.size(); i++)
 | 
						|
        if (value(ps[i]) == l_True || ps[i] == ~p)
 | 
						|
            return true;
 | 
						|
        else if (value(ps[i]) != l_False && ps[i] != p)
 | 
						|
            ps[j++] = p = ps[i];
 | 
						|
    ps.shrink(i - j);
 | 
						|
 | 
						|
    if (ps.size() == 0)
 | 
						|
        return ok = false;
 | 
						|
    else if (ps.size() == 1){
 | 
						|
        uncheckedEnqueue(ps[0]);
 | 
						|
        return ok = (propagate() == CRef_Undef);
 | 
						|
    }else{
 | 
						|
        CRef cr = ca.alloc(ps, false);
 | 
						|
        clauses.push(cr);
 | 
						|
        attachClause(cr);
 | 
						|
    }
 | 
						|
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void Solver::attachClause(CRef cr){
 | 
						|
    const Clause& c = ca[cr];
 | 
						|
    assert(c.size() > 1);
 | 
						|
    watches[~c[0]].push(Watcher(cr, c[1]));
 | 
						|
    watches[~c[1]].push(Watcher(cr, c[0]));
 | 
						|
    if (c.learnt()) num_learnts++, learnts_literals += c.size();
 | 
						|
    else            num_clauses++, clauses_literals += c.size();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void Solver::detachClause(CRef cr, bool strict){
 | 
						|
    const Clause& c = ca[cr];
 | 
						|
    assert(c.size() > 1);
 | 
						|
    
 | 
						|
    // Strict or lazy detaching:
 | 
						|
    if (strict){
 | 
						|
        remove(watches[~c[0]], Watcher(cr, c[1]));
 | 
						|
        remove(watches[~c[1]], Watcher(cr, c[0]));
 | 
						|
    }else{
 | 
						|
        watches.smudge(~c[0]);
 | 
						|
        watches.smudge(~c[1]);
 | 
						|
    }
 | 
						|
 | 
						|
    if (c.learnt()) num_learnts--, learnts_literals -= c.size();
 | 
						|
    else            num_clauses--, clauses_literals -= c.size();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void Solver::removeClause(CRef cr) {
 | 
						|
    Clause& c = ca[cr];
 | 
						|
    detachClause(cr);
 | 
						|
    // Don't leave pointers to free'd memory!
 | 
						|
    if (locked(c)) vardata[var(c[0])].reason = CRef_Undef;
 | 
						|
    c.mark(1); 
 | 
						|
    ca.free(cr);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool Solver::satisfied(const Clause& c) const {
 | 
						|
    for (int i = 0; i < c.size(); i++)
 | 
						|
        if (value(c[i]) == l_True)
 | 
						|
            return true;
 | 
						|
    return false; }
 | 
						|
 | 
						|
 | 
						|
// Revert to the state at given level (keeping all assignment at 'level' but not beyond).
 | 
						|
//
 | 
						|
void Solver::cancelUntil(int level) {
 | 
						|
    if (decisionLevel() > level){
 | 
						|
        for (int c = trail.size()-1; c >= trail_lim[level]; c--){
 | 
						|
            Var      x  = var(trail[c]);
 | 
						|
            assigns [x] = l_Undef;
 | 
						|
            if (phase_saving > 1 || (phase_saving == 1 && c > trail_lim.last()))
 | 
						|
                polarity[x] = sign(trail[c]);
 | 
						|
            insertVarOrder(x); }
 | 
						|
        qhead = trail_lim[level];
 | 
						|
        trail.shrink(trail.size() - trail_lim[level]);
 | 
						|
        trail_lim.shrink(trail_lim.size() - level);
 | 
						|
    } }
 | 
						|
 | 
						|
 | 
						|
//=================================================================================================
 | 
						|
// Major methods:
 | 
						|
 | 
						|
 | 
						|
Lit Solver::pickBranchLit()
 | 
						|
{
 | 
						|
    Var next = var_Undef;
 | 
						|
 | 
						|
    // Random decision:
 | 
						|
    if (drand(random_seed) < random_var_freq && !order_heap.empty()){
 | 
						|
        next = order_heap[irand(random_seed,order_heap.size())];
 | 
						|
        if (value(next) == l_Undef && decision[next])
 | 
						|
            rnd_decisions++; }
 | 
						|
 | 
						|
    // Activity based decision:
 | 
						|
    while (next == var_Undef || value(next) != l_Undef || !decision[next])
 | 
						|
        if (order_heap.empty()){
 | 
						|
            next = var_Undef;
 | 
						|
            break;
 | 
						|
        }else
 | 
						|
            next = order_heap.removeMin();
 | 
						|
 | 
						|
    // Choose polarity based on different polarity modes (global or per-variable):
 | 
						|
    if (next == var_Undef)
 | 
						|
        return lit_Undef;
 | 
						|
    else if (user_pol[next] != l_Undef)
 | 
						|
        return mkLit(next, user_pol[next] == l_True);
 | 
						|
    else if (rnd_pol)
 | 
						|
        return mkLit(next, drand(random_seed) < 0.5);
 | 
						|
    else
 | 
						|
        return mkLit(next, polarity[next]);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*_________________________________________________________________________________________________
 | 
						|
|
 | 
						|
|  analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&)  ->  [void]
 | 
						|
|  
 | 
						|
|  Description:
 | 
						|
|    Analyze conflict and produce a reason clause.
 | 
						|
|  
 | 
						|
|    Pre-conditions:
 | 
						|
|      * 'out_learnt' is assumed to be cleared.
 | 
						|
|      * Current decision level must be greater than root level.
 | 
						|
|  
 | 
						|
|    Post-conditions:
 | 
						|
|      * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'.
 | 
						|
|      * If out_learnt.size() > 1 then 'out_learnt[1]' has the greatest decision level of the 
 | 
						|
|        rest of literals. There may be others from the same level though.
 | 
						|
|  
 | 
						|
|________________________________________________________________________________________________@*/
 | 
						|
void Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel)
 | 
						|
{
 | 
						|
    int pathC = 0;
 | 
						|
    Lit p     = lit_Undef;
 | 
						|
 | 
						|
    // Generate conflict clause:
 | 
						|
    //
 | 
						|
    out_learnt.push();      // (leave room for the asserting literal)
 | 
						|
    int index   = trail.size() - 1;
 | 
						|
 | 
						|
    do{
 | 
						|
        assert(confl != CRef_Undef); // (otherwise should be UIP)
 | 
						|
        Clause& c = ca[confl];
 | 
						|
 | 
						|
        if (c.learnt())
 | 
						|
            claBumpActivity(c);
 | 
						|
 | 
						|
        for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){
 | 
						|
            Lit q = c[j];
 | 
						|
 | 
						|
            if (!seen[var(q)] && level(var(q)) > 0){
 | 
						|
                varBumpActivity(var(q));
 | 
						|
                seen[var(q)] = 1;
 | 
						|
                if (level(var(q)) >= decisionLevel())
 | 
						|
                    pathC++;
 | 
						|
                else
 | 
						|
                    out_learnt.push(q);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        
 | 
						|
        // Select next clause to look at:
 | 
						|
        while (!seen[var(trail[index--])]);
 | 
						|
        p     = trail[index+1];
 | 
						|
        confl = reason(var(p));
 | 
						|
        seen[var(p)] = 0;
 | 
						|
        pathC--;
 | 
						|
 | 
						|
    }while (pathC > 0);
 | 
						|
    out_learnt[0] = ~p;
 | 
						|
 | 
						|
    // Simplify conflict clause:
 | 
						|
    //
 | 
						|
    int i, j;
 | 
						|
    out_learnt.copyTo(analyze_toclear);
 | 
						|
    if (ccmin_mode == 2){
 | 
						|
        for (i = j = 1; i < out_learnt.size(); i++)
 | 
						|
            if (reason(var(out_learnt[i])) == CRef_Undef || !litRedundant(out_learnt[i]))
 | 
						|
                out_learnt[j++] = out_learnt[i];
 | 
						|
        
 | 
						|
    }else if (ccmin_mode == 1){
 | 
						|
        for (i = j = 1; i < out_learnt.size(); i++){
 | 
						|
            Var x = var(out_learnt[i]);
 | 
						|
 | 
						|
            if (reason(x) == CRef_Undef)
 | 
						|
                out_learnt[j++] = out_learnt[i];
 | 
						|
            else{
 | 
						|
                Clause& c = ca[reason(var(out_learnt[i]))];
 | 
						|
                for (int k = 1; k < c.size(); k++)
 | 
						|
                    if (!seen[var(c[k])] && level(var(c[k])) > 0){
 | 
						|
                        out_learnt[j++] = out_learnt[i];
 | 
						|
                        break; }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }else
 | 
						|
        i = j = out_learnt.size();
 | 
						|
 | 
						|
    max_literals += out_learnt.size();
 | 
						|
    out_learnt.shrink(i - j);
 | 
						|
    tot_literals += out_learnt.size();
 | 
						|
 | 
						|
    // Find correct backtrack level:
 | 
						|
    //
 | 
						|
    if (out_learnt.size() == 1)
 | 
						|
        out_btlevel = 0;
 | 
						|
    else{
 | 
						|
        int max_i = 1;
 | 
						|
        // Find the first literal assigned at the next-highest level:
 | 
						|
        for (int i = 2; i < out_learnt.size(); i++)
 | 
						|
            if (level(var(out_learnt[i])) > level(var(out_learnt[max_i])))
 | 
						|
                max_i = i;
 | 
						|
        // Swap-in this literal at index 1:
 | 
						|
        Lit p             = out_learnt[max_i];
 | 
						|
        out_learnt[max_i] = out_learnt[1];
 | 
						|
        out_learnt[1]     = p;
 | 
						|
        out_btlevel       = level(var(p));
 | 
						|
    }
 | 
						|
 | 
						|
    for (int j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0;    // ('seen[]' is now cleared)
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Check if 'p' can be removed from a conflict clause.
 | 
						|
bool Solver::litRedundant(Lit p)
 | 
						|
{
 | 
						|
    enum { seen_undef = 0, seen_source = 1, seen_removable = 2, seen_failed = 3 };
 | 
						|
    assert(seen[var(p)] == seen_undef || seen[var(p)] == seen_source);
 | 
						|
    assert(reason(var(p)) != CRef_Undef);
 | 
						|
 | 
						|
    Clause*               c     = &ca[reason(var(p))];
 | 
						|
    vec<ShrinkStackElem>& stack = analyze_stack;
 | 
						|
    stack.clear();
 | 
						|
 | 
						|
    for (uint32_t i = 1; ; i++){
 | 
						|
        if (i < (uint32_t)c->size()){
 | 
						|
            // Checking 'p'-parents 'l':
 | 
						|
            Lit l = (*c)[i];
 | 
						|
            
 | 
						|
            // Variable at level 0 or previously removable:
 | 
						|
            if (level(var(l)) == 0 || seen[var(l)] == seen_source || seen[var(l)] == seen_removable){
 | 
						|
                continue; }
 | 
						|
            
 | 
						|
            // Check variable can not be removed for some local reason:
 | 
						|
            if (reason(var(l)) == CRef_Undef || seen[var(l)] == seen_failed){
 | 
						|
                stack.push(ShrinkStackElem(0, p));
 | 
						|
                for (int i = 0; i < stack.size(); i++)
 | 
						|
                    if (seen[var(stack[i].l)] == seen_undef){
 | 
						|
                        seen[var(stack[i].l)] = seen_failed;
 | 
						|
                        analyze_toclear.push(stack[i].l);
 | 
						|
                    }
 | 
						|
                    
 | 
						|
                return false;
 | 
						|
            }
 | 
						|
 | 
						|
            // Recursively check 'l':
 | 
						|
            stack.push(ShrinkStackElem(i, p));
 | 
						|
            i  = 0;
 | 
						|
            p  = l;
 | 
						|
            c  = &ca[reason(var(p))];
 | 
						|
        }else{
 | 
						|
            // Finished with current element 'p' and reason 'c':
 | 
						|
            if (seen[var(p)] == seen_undef){
 | 
						|
                seen[var(p)] = seen_removable;
 | 
						|
                analyze_toclear.push(p);
 | 
						|
            }
 | 
						|
 | 
						|
            // Terminate with success if stack is empty:
 | 
						|
            if (stack.size() == 0) break;
 | 
						|
            
 | 
						|
            // Continue with top element on stack:
 | 
						|
            i  = stack.last().i;
 | 
						|
            p  = stack.last().l;
 | 
						|
            c  = &ca[reason(var(p))];
 | 
						|
 | 
						|
            stack.pop();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*_________________________________________________________________________________________________
 | 
						|
|
 | 
						|
|  analyzeFinal : (p : Lit)  ->  [void]
 | 
						|
|  
 | 
						|
|  Description:
 | 
						|
|    Specialized analysis procedure to express the final conflict in terms of assumptions.
 | 
						|
|    Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and
 | 
						|
|    stores the result in 'out_conflict'.
 | 
						|
|________________________________________________________________________________________________@*/
 | 
						|
void Solver::analyzeFinal(Lit p, LSet& out_conflict)
 | 
						|
{
 | 
						|
    out_conflict.clear();
 | 
						|
    out_conflict.insert(p);
 | 
						|
 | 
						|
    if (decisionLevel() == 0)
 | 
						|
        return;
 | 
						|
 | 
						|
    seen[var(p)] = 1;
 | 
						|
 | 
						|
    for (int i = trail.size()-1; i >= trail_lim[0]; i--){
 | 
						|
        Var x = var(trail[i]);
 | 
						|
        if (seen[x]){
 | 
						|
            if (reason(x) == CRef_Undef){
 | 
						|
                assert(level(x) > 0);
 | 
						|
                out_conflict.insert(~trail[i]);
 | 
						|
            }else{
 | 
						|
                Clause& c = ca[reason(x)];
 | 
						|
                for (int j = 1; j < c.size(); j++)
 | 
						|
                    if (level(var(c[j])) > 0)
 | 
						|
                        seen[var(c[j])] = 1;
 | 
						|
            }
 | 
						|
            seen[x] = 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    seen[var(p)] = 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void Solver::uncheckedEnqueue(Lit p, CRef from)
 | 
						|
{
 | 
						|
    assert(value(p) == l_Undef);
 | 
						|
    assigns[var(p)] = lbool(!sign(p));
 | 
						|
    vardata[var(p)] = mkVarData(from, decisionLevel());
 | 
						|
    trail.push_(p);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*_________________________________________________________________________________________________
 | 
						|
|
 | 
						|
|  propagate : [void]  ->  [Clause*]
 | 
						|
|  
 | 
						|
|  Description:
 | 
						|
|    Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned,
 | 
						|
|    otherwise CRef_Undef.
 | 
						|
|  
 | 
						|
|    Post-conditions:
 | 
						|
|      * the propagation queue is empty, even if there was a conflict.
 | 
						|
|________________________________________________________________________________________________@*/
 | 
						|
CRef Solver::propagate()
 | 
						|
{
 | 
						|
    CRef    confl     = CRef_Undef;
 | 
						|
    int     num_props = 0;
 | 
						|
 | 
						|
    while (qhead < trail.size()){
 | 
						|
        Lit            p   = trail[qhead++];     // 'p' is enqueued fact to propagate.
 | 
						|
        vec<Watcher>&  ws  = watches.lookup(p);
 | 
						|
        Watcher        *i, *j, *end;
 | 
						|
        num_props++;
 | 
						|
 | 
						|
        for (i = j = (Watcher*)ws, end = i + ws.size();  i != end;){
 | 
						|
            // Try to avoid inspecting the clause:
 | 
						|
            Lit blocker = i->blocker;
 | 
						|
            if (value(blocker) == l_True){
 | 
						|
                *j++ = *i++; continue; }
 | 
						|
 | 
						|
            // Make sure the false literal is data[1]:
 | 
						|
            CRef     cr        = i->cref;
 | 
						|
            Clause&  c         = ca[cr];
 | 
						|
            Lit      false_lit = ~p;
 | 
						|
            if (c[0] == false_lit)
 | 
						|
                c[0] = c[1], c[1] = false_lit;
 | 
						|
            assert(c[1] == false_lit);
 | 
						|
            i++;
 | 
						|
 | 
						|
            // If 0th watch is true, then clause is already satisfied.
 | 
						|
            Lit     first = c[0];
 | 
						|
            Watcher w     = Watcher(cr, first);
 | 
						|
            if (first != blocker && value(first) == l_True){
 | 
						|
                *j++ = w; continue; }
 | 
						|
 | 
						|
            // Look for new watch:
 | 
						|
            for (int k = 2; k < c.size(); k++)
 | 
						|
                if (value(c[k]) != l_False){
 | 
						|
                    c[1] = c[k]; c[k] = false_lit;
 | 
						|
                    watches[~c[1]].push(w);
 | 
						|
                    goto NextClause; }
 | 
						|
 | 
						|
            // Did not find watch -- clause is unit under assignment:
 | 
						|
            *j++ = w;
 | 
						|
            if (value(first) == l_False){
 | 
						|
                confl = cr;
 | 
						|
                qhead = trail.size();
 | 
						|
                // Copy the remaining watches:
 | 
						|
                while (i < end)
 | 
						|
                    *j++ = *i++;
 | 
						|
            }else
 | 
						|
                uncheckedEnqueue(first, cr);
 | 
						|
 | 
						|
        NextClause:;
 | 
						|
        }
 | 
						|
        ws.shrink(i - j);
 | 
						|
    }
 | 
						|
    propagations += num_props;
 | 
						|
    simpDB_props -= num_props;
 | 
						|
 | 
						|
    return confl;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*_________________________________________________________________________________________________
 | 
						|
|
 | 
						|
|  reduceDB : ()  ->  [void]
 | 
						|
|  
 | 
						|
|  Description:
 | 
						|
|    Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked
 | 
						|
|    clauses are clauses that are reason to some assignment. Binary clauses are never removed.
 | 
						|
|________________________________________________________________________________________________@*/
 | 
						|
struct reduceDB_lt { 
 | 
						|
    ClauseAllocator& ca;
 | 
						|
    reduceDB_lt(ClauseAllocator& ca_) : ca(ca_) {}
 | 
						|
    bool operator () (CRef x, CRef y) { 
 | 
						|
        return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity()); } 
 | 
						|
};
 | 
						|
void Solver::reduceDB()
 | 
						|
{
 | 
						|
    int     i, j;
 | 
						|
    double  extra_lim = cla_inc / learnts.size();    // Remove any clause below this activity
 | 
						|
 | 
						|
    sort(learnts, reduceDB_lt(ca));
 | 
						|
    // Don't delete binary or locked clauses. From the rest, delete clauses from the first half
 | 
						|
    // and clauses with activity smaller than 'extra_lim':
 | 
						|
    for (i = j = 0; i < learnts.size(); i++){
 | 
						|
        Clause& c = ca[learnts[i]];
 | 
						|
        if (c.size() > 2 && !locked(c) && (i < learnts.size() / 2 || c.activity() < extra_lim))
 | 
						|
            removeClause(learnts[i]);
 | 
						|
        else
 | 
						|
            learnts[j++] = learnts[i];
 | 
						|
    }
 | 
						|
    learnts.shrink(i - j);
 | 
						|
    checkGarbage();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void Solver::removeSatisfied(vec<CRef>& cs)
 | 
						|
{
 | 
						|
    int i, j;
 | 
						|
    for (i = j = 0; i < cs.size(); i++){
 | 
						|
        Clause& c = ca[cs[i]];
 | 
						|
        if (satisfied(c))
 | 
						|
            removeClause(cs[i]);
 | 
						|
        else{
 | 
						|
            // Trim clause:
 | 
						|
            assert(value(c[0]) == l_Undef && value(c[1]) == l_Undef);
 | 
						|
            for (int k = 2; k < c.size(); k++)
 | 
						|
                if (value(c[k]) == l_False){
 | 
						|
                    c[k--] = c[c.size()-1];
 | 
						|
                    c.pop();
 | 
						|
                }
 | 
						|
            cs[j++] = cs[i];
 | 
						|
        }
 | 
						|
    }
 | 
						|
    cs.shrink(i - j);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void Solver::rebuildOrderHeap()
 | 
						|
{
 | 
						|
    vec<Var> vs;
 | 
						|
    for (Var v = 0; v < nVars(); v++)
 | 
						|
        if (decision[v] && value(v) == l_Undef)
 | 
						|
            vs.push(v);
 | 
						|
    order_heap.build(vs);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*_________________________________________________________________________________________________
 | 
						|
|
 | 
						|
|  simplify : [void]  ->  [bool]
 | 
						|
|  
 | 
						|
|  Description:
 | 
						|
|    Simplify the clause database according to the current top-level assigment. Currently, the only
 | 
						|
|    thing done here is the removal of satisfied clauses, but more things can be put here.
 | 
						|
|________________________________________________________________________________________________@*/
 | 
						|
bool Solver::simplify()
 | 
						|
{
 | 
						|
    assert(decisionLevel() == 0);
 | 
						|
 | 
						|
    if (!ok || propagate() != CRef_Undef)
 | 
						|
        return ok = false;
 | 
						|
 | 
						|
    if (nAssigns() == simpDB_assigns || (simpDB_props > 0))
 | 
						|
        return true;
 | 
						|
 | 
						|
    // Remove satisfied clauses:
 | 
						|
    removeSatisfied(learnts);
 | 
						|
    if (remove_satisfied){       // Can be turned off.
 | 
						|
        removeSatisfied(clauses);
 | 
						|
 | 
						|
        // TODO: what todo in if 'remove_satisfied' is false?
 | 
						|
 | 
						|
        // Remove all released variables from the trail:
 | 
						|
        for (int i = 0; i < released_vars.size(); i++){
 | 
						|
            assert(seen[released_vars[i]] == 0);
 | 
						|
            seen[released_vars[i]] = 1;
 | 
						|
        }
 | 
						|
 | 
						|
        int i, j;
 | 
						|
        for (i = j = 0; i < trail.size(); i++)
 | 
						|
            if (seen[var(trail[i])] == 0)
 | 
						|
                trail[j++] = trail[i];
 | 
						|
        trail.shrink(i - j);
 | 
						|
        //printf("trail.size()= %d, qhead = %d\n", trail.size(), qhead);
 | 
						|
        qhead = trail.size();
 | 
						|
 | 
						|
        for (int i = 0; i < released_vars.size(); i++)
 | 
						|
            seen[released_vars[i]] = 0;
 | 
						|
 | 
						|
        // Released variables are now ready to be reused:
 | 
						|
        append(released_vars, free_vars);
 | 
						|
        released_vars.clear();
 | 
						|
    }
 | 
						|
    checkGarbage();
 | 
						|
    rebuildOrderHeap();
 | 
						|
 | 
						|
    simpDB_assigns = nAssigns();
 | 
						|
    simpDB_props   = clauses_literals + learnts_literals;   // (shouldn't depend on stats really, but it will do for now)
 | 
						|
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*_________________________________________________________________________________________________
 | 
						|
|
 | 
						|
|  search : (nof_conflicts : int) (params : const SearchParams&)  ->  [lbool]
 | 
						|
|  
 | 
						|
|  Description:
 | 
						|
|    Search for a model the specified number of conflicts. 
 | 
						|
|    NOTE! Use negative value for 'nof_conflicts' indicate infinity.
 | 
						|
|  
 | 
						|
|  Output:
 | 
						|
|    'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If
 | 
						|
|    all variables are decision variables, this means that the clause set is satisfiable. 'l_False'
 | 
						|
|    if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached.
 | 
						|
|________________________________________________________________________________________________@*/
 | 
						|
lbool Solver::search(int nof_conflicts)
 | 
						|
{
 | 
						|
    assert(ok);
 | 
						|
    int         backtrack_level;
 | 
						|
    int         conflictC = 0;
 | 
						|
    vec<Lit>    learnt_clause;
 | 
						|
    starts++;
 | 
						|
 | 
						|
    for (;;){
 | 
						|
        CRef confl = propagate();
 | 
						|
        if (confl != CRef_Undef){
 | 
						|
            // CONFLICT
 | 
						|
            conflicts++; conflictC++;
 | 
						|
            if (decisionLevel() == 0) return l_False;
 | 
						|
 | 
						|
            learnt_clause.clear();
 | 
						|
            analyze(confl, learnt_clause, backtrack_level);
 | 
						|
            cancelUntil(backtrack_level);
 | 
						|
 | 
						|
            if (learnt_clause.size() == 1){
 | 
						|
                uncheckedEnqueue(learnt_clause[0]);
 | 
						|
            }else{
 | 
						|
                CRef cr = ca.alloc(learnt_clause, true);
 | 
						|
                learnts.push(cr);
 | 
						|
                attachClause(cr);
 | 
						|
                claBumpActivity(ca[cr]);
 | 
						|
                uncheckedEnqueue(learnt_clause[0], cr);
 | 
						|
            }
 | 
						|
 | 
						|
            varDecayActivity();
 | 
						|
            claDecayActivity();
 | 
						|
 | 
						|
            if (--learntsize_adjust_cnt == 0){
 | 
						|
                learntsize_adjust_confl *= learntsize_adjust_inc;
 | 
						|
                learntsize_adjust_cnt    = (int)learntsize_adjust_confl;
 | 
						|
                max_learnts             *= learntsize_inc;
 | 
						|
 | 
						|
                if (verbosity >= 1)
 | 
						|
                    printf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n", 
 | 
						|
                           (int)conflicts, 
 | 
						|
                           (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]), nClauses(), (int)clauses_literals, 
 | 
						|
                           (int)max_learnts, nLearnts(), (double)learnts_literals/nLearnts(), progressEstimate()*100);
 | 
						|
            }
 | 
						|
 | 
						|
        }else{
 | 
						|
            // NO CONFLICT
 | 
						|
            if ((nof_conflicts >= 0 && conflictC >= nof_conflicts) || !withinBudget()){
 | 
						|
                // Reached bound on number of conflicts:
 | 
						|
                progress_estimate = progressEstimate();
 | 
						|
                cancelUntil(0);
 | 
						|
                return l_Undef; }
 | 
						|
 | 
						|
            // Simplify the set of problem clauses:
 | 
						|
            if (decisionLevel() == 0 && !simplify())
 | 
						|
                return l_False;
 | 
						|
 | 
						|
            if (learnts.size()-nAssigns() >= max_learnts)
 | 
						|
                // Reduce the set of learnt clauses:
 | 
						|
                reduceDB();
 | 
						|
 | 
						|
            Lit next = lit_Undef;
 | 
						|
            while (decisionLevel() < assumptions.size()){
 | 
						|
                // Perform user provided assumption:
 | 
						|
                Lit p = assumptions[decisionLevel()];
 | 
						|
                if (value(p) == l_True){
 | 
						|
                    // Dummy decision level:
 | 
						|
                    newDecisionLevel();
 | 
						|
                }else if (value(p) == l_False){
 | 
						|
                    analyzeFinal(~p, conflict);
 | 
						|
                    return l_False;
 | 
						|
                }else{
 | 
						|
                    next = p;
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            if (next == lit_Undef){
 | 
						|
                // New variable decision:
 | 
						|
                decisions++;
 | 
						|
                next = pickBranchLit();
 | 
						|
 | 
						|
                if (next == lit_Undef)
 | 
						|
                    // Model found:
 | 
						|
                    return l_True;
 | 
						|
            }
 | 
						|
 | 
						|
            // Increase decision level and enqueue 'next'
 | 
						|
            newDecisionLevel();
 | 
						|
            uncheckedEnqueue(next);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
double Solver::progressEstimate() const
 | 
						|
{
 | 
						|
    double  progress = 0;
 | 
						|
    double  F = 1.0 / nVars();
 | 
						|
 | 
						|
    for (int i = 0; i <= decisionLevel(); i++){
 | 
						|
        int beg = i == 0 ? 0 : trail_lim[i - 1];
 | 
						|
        int end = i == decisionLevel() ? trail.size() : trail_lim[i];
 | 
						|
        progress += pow(F, i) * (end - beg);
 | 
						|
    }
 | 
						|
 | 
						|
    return progress / nVars();
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
  Finite subsequences of the Luby-sequence:
 | 
						|
 | 
						|
  0: 1
 | 
						|
  1: 1 1 2
 | 
						|
  2: 1 1 2 1 1 2 4
 | 
						|
  3: 1 1 2 1 1 2 4 1 1 2 1 1 2 4 8
 | 
						|
  ...
 | 
						|
 | 
						|
 | 
						|
 */
 | 
						|
 | 
						|
static double luby(double y, int x){
 | 
						|
 | 
						|
    // Find the finite subsequence that contains index 'x', and the
 | 
						|
    // size of that subsequence:
 | 
						|
    int size, seq;
 | 
						|
    for (size = 1, seq = 0; size < x+1; seq++, size = 2*size+1);
 | 
						|
 | 
						|
    while (size-1 != x){
 | 
						|
        size = (size-1)>>1;
 | 
						|
        seq--;
 | 
						|
        x = x % size;
 | 
						|
    }
 | 
						|
 | 
						|
    return pow(y, seq);
 | 
						|
}
 | 
						|
 | 
						|
// NOTE: assumptions passed in member-variable 'assumptions'.
 | 
						|
lbool Solver::solve_()
 | 
						|
{
 | 
						|
    model.clear();
 | 
						|
    conflict.clear();
 | 
						|
    if (!ok) return l_False;
 | 
						|
 | 
						|
    solves++;
 | 
						|
 | 
						|
    max_learnts = nClauses() * learntsize_factor;
 | 
						|
    if (max_learnts < min_learnts_lim)
 | 
						|
        max_learnts = min_learnts_lim;
 | 
						|
 | 
						|
    learntsize_adjust_confl   = learntsize_adjust_start_confl;
 | 
						|
    learntsize_adjust_cnt     = (int)learntsize_adjust_confl;
 | 
						|
    lbool   status            = l_Undef;
 | 
						|
 | 
						|
    if (verbosity >= 1){
 | 
						|
        printf("============================[ Search Statistics ]==============================\n");
 | 
						|
        printf("| Conflicts |          ORIGINAL         |          LEARNT          | Progress |\n");
 | 
						|
        printf("|           |    Vars  Clauses Literals |    Limit  Clauses Lit/Cl |          |\n");
 | 
						|
        printf("===============================================================================\n");
 | 
						|
    }
 | 
						|
 | 
						|
    // Search:
 | 
						|
    int curr_restarts = 0;
 | 
						|
    while (status == l_Undef){
 | 
						|
        double rest_base = luby_restart ? luby(restart_inc, curr_restarts) : pow(restart_inc, curr_restarts);
 | 
						|
        status = search(rest_base * restart_first);
 | 
						|
        if (!withinBudget()) break;
 | 
						|
        curr_restarts++;
 | 
						|
    }
 | 
						|
 | 
						|
    if (verbosity >= 1)
 | 
						|
        printf("===============================================================================\n");
 | 
						|
 | 
						|
 | 
						|
    if (status == l_True){
 | 
						|
        // Extend & copy model:
 | 
						|
        model.growTo(nVars());
 | 
						|
        for (int i = 0; i < nVars(); i++) model[i] = value(i);
 | 
						|
    }else if (status == l_False && conflict.size() == 0)
 | 
						|
        ok = false;
 | 
						|
 | 
						|
    cancelUntil(0);
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool Solver::implies(const vec<Lit>& assumps, vec<Lit>& out)
 | 
						|
{
 | 
						|
    trail_lim.push(trail.size());
 | 
						|
    for (int i = 0; i < assumps.size(); i++){
 | 
						|
        Lit a = assumps[i];
 | 
						|
 | 
						|
        if (value(a) == l_False){
 | 
						|
            cancelUntil(0);
 | 
						|
            return false;
 | 
						|
        }else if (value(a) == l_Undef)
 | 
						|
            uncheckedEnqueue(a);
 | 
						|
    }
 | 
						|
 | 
						|
    unsigned trail_before = trail.size();
 | 
						|
    bool     ret          = true;
 | 
						|
    if (propagate() == CRef_Undef){
 | 
						|
        out.clear();
 | 
						|
        for (int j = trail_before; j < trail.size(); j++)
 | 
						|
            out.push(trail[j]);
 | 
						|
    }else
 | 
						|
        ret = false;
 | 
						|
    
 | 
						|
    cancelUntil(0);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
//=================================================================================================
 | 
						|
// Writing CNF to DIMACS:
 | 
						|
// 
 | 
						|
// FIXME: this needs to be rewritten completely.
 | 
						|
 | 
						|
static Var mapVar(Var x, vec<Var>& map, Var& max)
 | 
						|
{
 | 
						|
    if (map.size() <= x || map[x] == -1){
 | 
						|
        map.growTo(x+1, -1);
 | 
						|
        map[x] = max++;
 | 
						|
    }
 | 
						|
    return map[x];
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void Solver::toDimacs(FILE* f, Clause& c, vec<Var>& map, Var& max)
 | 
						|
{
 | 
						|
    if (satisfied(c)) return;
 | 
						|
 | 
						|
    for (int i = 0; i < c.size(); i++)
 | 
						|
        if (value(c[i]) != l_False)
 | 
						|
            fprintf(f, "%s%d ", sign(c[i]) ? "-" : "", mapVar(var(c[i]), map, max)+1);
 | 
						|
    fprintf(f, "0\n");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void Solver::toDimacs(const char *file, const vec<Lit>& assumps)
 | 
						|
{
 | 
						|
    FILE* f = fopen(file, "wr");
 | 
						|
    if (f == NULL)
 | 
						|
        fprintf(stderr, "could not open file %s\n", file), exit(1);
 | 
						|
    toDimacs(f, assumps);
 | 
						|
    fclose(f);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void Solver::toDimacs(FILE* f, const vec<Lit>& assumps)
 | 
						|
{
 | 
						|
    // Handle case when solver is in contradictory state:
 | 
						|
    if (!ok){
 | 
						|
        fprintf(f, "p cnf 1 2\n1 0\n-1 0\n");
 | 
						|
        return; }
 | 
						|
 | 
						|
    vec<Var> map; Var max = 0;
 | 
						|
 | 
						|
    // Cannot use removeClauses here because it is not safe
 | 
						|
    // to deallocate them at this point. Could be improved.
 | 
						|
    int cnt = 0;
 | 
						|
    for (int i = 0; i < clauses.size(); i++)
 | 
						|
        if (!satisfied(ca[clauses[i]]))
 | 
						|
            cnt++;
 | 
						|
        
 | 
						|
    for (int i = 0; i < clauses.size(); i++)
 | 
						|
        if (!satisfied(ca[clauses[i]])){
 | 
						|
            Clause& c = ca[clauses[i]];
 | 
						|
            for (int j = 0; j < c.size(); j++)
 | 
						|
                if (value(c[j]) != l_False)
 | 
						|
                    mapVar(var(c[j]), map, max);
 | 
						|
        }
 | 
						|
 | 
						|
    // Assumptions are added as unit clauses:
 | 
						|
    cnt += assumps.size();
 | 
						|
 | 
						|
    fprintf(f, "p cnf %d %d\n", max, cnt);
 | 
						|
 | 
						|
    for (int i = 0; i < assumps.size(); i++){
 | 
						|
        assert(value(assumps[i]) != l_False);
 | 
						|
        fprintf(f, "%s%d 0\n", sign(assumps[i]) ? "-" : "", mapVar(var(assumps[i]), map, max)+1);
 | 
						|
    }
 | 
						|
 | 
						|
    for (int i = 0; i < clauses.size(); i++)
 | 
						|
        toDimacs(f, ca[clauses[i]], map, max);
 | 
						|
 | 
						|
    if (verbosity > 0)
 | 
						|
        printf("Wrote DIMACS with %d variables and %d clauses.\n", max, cnt);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void Solver::printStats() const
 | 
						|
{
 | 
						|
    double cpu_time = cpuTime();
 | 
						|
    double mem_used = memUsedPeak();
 | 
						|
    printf("restarts              : %" PRIu64 "\n", starts);
 | 
						|
    printf("conflicts             : %-12" PRIu64 "   (%.0f /sec)\n", conflicts   , conflicts   /cpu_time);
 | 
						|
    printf("decisions             : %-12" PRIu64 "   (%4.2f %% random) (%.0f /sec)\n", decisions, (float)rnd_decisions*100 / (float)decisions, decisions   /cpu_time);
 | 
						|
    printf("propagations          : %-12" PRIu64 "   (%.0f /sec)\n", propagations, propagations/cpu_time);
 | 
						|
    printf("conflict literals     : %-12" PRIu64 "   (%4.2f %% deleted)\n", tot_literals, (max_literals - tot_literals)*100 / (double)max_literals);
 | 
						|
    if (mem_used != 0) printf("Memory used           : %.2f MB\n", mem_used);
 | 
						|
    printf("CPU time              : %g s\n", cpu_time);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//=================================================================================================
 | 
						|
// Garbage Collection methods:
 | 
						|
 | 
						|
void Solver::relocAll(ClauseAllocator& to)
 | 
						|
{
 | 
						|
    // All watchers:
 | 
						|
    //
 | 
						|
    watches.cleanAll();
 | 
						|
    for (int v = 0; v < nVars(); v++)
 | 
						|
        for (int s = 0; s < 2; s++){
 | 
						|
            Lit p = mkLit(v, s);
 | 
						|
            vec<Watcher>& ws = watches[p];
 | 
						|
            for (int j = 0; j < ws.size(); j++)
 | 
						|
                ca.reloc(ws[j].cref, to);
 | 
						|
        }
 | 
						|
 | 
						|
    // All reasons:
 | 
						|
    //
 | 
						|
    for (int i = 0; i < trail.size(); i++){
 | 
						|
        Var v = var(trail[i]);
 | 
						|
 | 
						|
        // Note: it is not safe to call 'locked()' on a relocated clause. This is why we keep
 | 
						|
        // 'dangling' reasons here. It is safe and does not hurt.
 | 
						|
        if (reason(v) != CRef_Undef && (ca[reason(v)].reloced() || locked(ca[reason(v)]))){
 | 
						|
            assert(!isRemoved(reason(v)));
 | 
						|
            ca.reloc(vardata[v].reason, to);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // All learnt:
 | 
						|
    //
 | 
						|
    int i, j;
 | 
						|
    for (i = j = 0; i < learnts.size(); i++)
 | 
						|
        if (!isRemoved(learnts[i])){
 | 
						|
            ca.reloc(learnts[i], to);
 | 
						|
            learnts[j++] = learnts[i];
 | 
						|
        }
 | 
						|
    learnts.shrink(i - j);
 | 
						|
 | 
						|
    // All original:
 | 
						|
    //
 | 
						|
    for (i = j = 0; i < clauses.size(); i++)
 | 
						|
        if (!isRemoved(clauses[i])){
 | 
						|
            ca.reloc(clauses[i], to);
 | 
						|
            clauses[j++] = clauses[i];
 | 
						|
        }
 | 
						|
    clauses.shrink(i - j);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void Solver::garbageCollect()
 | 
						|
{
 | 
						|
    // Initialize the next region to a size corresponding to the estimated utilization degree. This
 | 
						|
    // is not precise but should avoid some unnecessary reallocations for the new region:
 | 
						|
    ClauseAllocator to(ca.size() - ca.wasted()); 
 | 
						|
 | 
						|
    relocAll(to);
 | 
						|
    if (verbosity >= 2)
 | 
						|
        printf("|  Garbage collection:   %12d bytes => %12d bytes             |\n", 
 | 
						|
               ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size);
 | 
						|
    to.moveTo(ca);
 | 
						|
}
 |