summaryrefslogtreecommitdiffstats
path: root/src/sat/glucose/Glucose.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sat/glucose/Glucose.cpp')
-rw-r--r--src/sat/glucose/Glucose.cpp1438
1 files changed, 1438 insertions, 0 deletions
diff --git a/src/sat/glucose/Glucose.cpp b/src/sat/glucose/Glucose.cpp
new file mode 100644
index 00000000..05f2945d
--- /dev/null
+++ b/src/sat/glucose/Glucose.cpp
@@ -0,0 +1,1438 @@
+/***************************************************************************************[Solver.cc]
+ Glucose -- Copyright (c) 2013, Gilles Audemard, Laurent Simon
+ CRIL - Univ. Artois, France
+ LRI - Univ. Paris Sud, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose are exactly the same as Minisat on which it is based on. (see below).
+
+---------------
+
+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 "sat/glucose/Sort.h"
+#include "sat/glucose/Solver.h"
+#include "sat/glucose/Constants.h"
+#include "sat/glucose/System.h"
+
+using namespace Glucose;
+
+//=================================================================================================
+// Options:
+
+static const char* _cat = "CORE";
+static const char* _cr = "CORE -- RESTART";
+static const char* _cred = "CORE -- REDUCE";
+static const char* _cm = "CORE -- MINIMIZE";
+static const char* _certified = "CORE -- CERTIFIED UNSAT";
+
+
+
+
+static BoolOption opt_incremental (_cat,"incremental", "Use incremental SAT solving", false);
+static DoubleOption opt_K (_cr, "K", "The constant used to force restart", 0.8, DoubleRange(0, false, 1, false));
+static DoubleOption opt_R (_cr, "R", "The constant used to block restart", 1.4, DoubleRange(1, false, 5, false));
+static IntOption opt_size_lbd_queue (_cr, "szLBDQueue", "The size of moving average for LBD (restarts)", 50, IntRange(10, INT32_MAX));
+static IntOption opt_size_trail_queue (_cr, "szTrailQueue", "The size of moving average for trail (block restarts)", 5000, IntRange(10, INT32_MAX));
+
+static IntOption opt_first_reduce_db (_cred, "firstReduceDB", "The number of conflicts before the first reduce DB", 2000, IntRange(0, INT32_MAX));
+static IntOption opt_inc_reduce_db (_cred, "incReduceDB", "Increment for reduce DB", 300, IntRange(0, INT32_MAX));
+static IntOption opt_spec_inc_reduce_db (_cred, "specialIncReduceDB", "Special increment for reduce DB", 1000, IntRange(0, INT32_MAX));
+static IntOption opt_lb_lbd_frozen_clause (_cred, "minLBDFrozenClause", "Protect clauses if their LBD decrease and is lower than (for one turn)", 30, IntRange(0, INT32_MAX));
+
+static IntOption opt_lb_size_minimzing_clause (_cm, "minSizeMinimizingClause", "The min size required to minimize clause", 30, IntRange(3, INT32_MAX));
+static IntOption opt_lb_lbd_minimzing_clause (_cm, "minLBDMinimizingClause", "The min LBD required to minimize clause", 6, IntRange(3, INT32_MAX));
+
+
+static DoubleOption opt_var_decay (_cat, "var-decay", "The variable activity decay factor", 0.8, 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 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));
+
+
+BoolOption opt_certified (_certified, "certified", "Certified UNSAT using DRUP format", false );
+StringOption opt_certified_file (_certified, "certified-output", "Certified UNSAT output file", "NULL");
+
+
+//=================================================================================================
+// Constructor/Destructor:
+
+
+Solver::Solver() :
+
+ // Parameters (user settable):
+ //
+ SolverType(0)
+ , pCnfFunc(NULL)
+ , nCallConfl(1000)
+ , verbEveryConflicts(10000)
+ , terminate_search_early(false)
+ , pstop(NULL)
+
+ , verbosity (0)
+ , showModel (0)
+ , K (opt_K)
+ , R (opt_R)
+ , sizeLBDQueue (opt_size_lbd_queue)
+ , sizeTrailQueue (opt_size_trail_queue)
+ , firstReduceDB (opt_first_reduce_db)
+ , incReduceDB (opt_inc_reduce_db)
+ , specialIncReduceDB (opt_spec_inc_reduce_db)
+ , lbLBDFrozenClause (opt_lb_lbd_frozen_clause)
+ , lbSizeMinimizingClause (opt_lb_size_minimzing_clause)
+ , lbLBDMinimizingClause (opt_lb_lbd_minimzing_clause)
+ , var_decay (opt_var_decay)
+ , clause_decay (opt_clause_decay)
+ , random_var_freq (opt_random_var_freq)
+ , random_seed (opt_random_seed)
+ , 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)
+ , certifiedOutput (NULL)
+ , certifiedUNSAT (opt_certified)
+ // Statistics: (formerly in 'SolverStats')
+ //
+ , nbRemovedClauses(0),nbReducedClauses(0), nbDL2(0),nbBin(0),nbUn(0) , nbReduceDB(0)
+ , solves(0), starts(0), decisions(0), rnd_decisions(0), propagations(0),conflicts(0),conflictsRestarts(0),nbstopsrestarts(0),nbstopsrestartssame(0),lastblockatrestart(0)
+ , dec_vars(0), clauses_literals(0), learnts_literals(0), max_literals(0), tot_literals(0)
+ , curRestart(1)
+
+ , ok (true)
+ , cla_inc (1)
+ , var_inc (1)
+ , watches (WatcherDeleted(ca))
+ , watchesBin (WatcherDeleted(ca))
+ , qhead (0)
+ , simpDB_assigns (-1)
+ , simpDB_props (0)
+ , order_heap (VarOrderLt(activity))
+ , progress_estimate (0)
+ , remove_satisfied (true)
+
+ // Resource constraints:
+ //
+ , conflict_budget (-1)
+ , propagation_budget (-1)
+ , asynch_interrupt (false)
+ , incremental(opt_incremental)
+ , nbVarsInitialFormula(INT32_MAX)
+{
+ MYFLAG=0;
+ // Initialize only first time. Useful for incremental solving, useless otherwise
+ lbdQueue.initSize(sizeLBDQueue);
+ trailQueue.initSize(sizeTrailQueue);
+ sumLBD = 0;
+ nbclausesbeforereduce = firstReduceDB;
+ totalTime4Sat=0;totalTime4Unsat=0;
+ nbSatCalls=0;nbUnsatCalls=0;
+
+
+ if(certifiedUNSAT) {
+ if(!strcmp(opt_certified_file,"NULL")) {
+ certifiedOutput = fopen("/dev/stdout", "wb");
+ } else {
+ certifiedOutput = fopen(opt_certified_file, "wb");
+ }
+ // fprintf(certifiedOutput,"o proof DRUP\n");
+ }
+}
+
+
+Solver::~Solver()
+{
+}
+
+
+/****************************************************************
+ Set the incremental mode
+****************************************************************/
+
+// This function set the incremental mode to true.
+// You can add special code for this mode here.
+
+void Solver::setIncrementalMode() {
+ incremental = true;
+}
+
+// Number of variables without selectors
+void Solver::initNbInitialVars(int nb) {
+ nbVarsInitialFormula = nb;
+}
+
+
+//=================================================================================================
+// 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(bool sign, bool dvar)
+{
+ int v = nVars();
+ watches .init(mkLit(v, false));
+ watches .init(mkLit(v, true ));
+ watchesBin .init(mkLit(v, false));
+ watchesBin .init(mkLit(v, true ));
+ assigns .push(l_Undef);
+ vardata .push(mkVarData(CRef_Undef, 0));
+ //activity .push(0);
+ activity .push(rnd_init_act ? drand(random_seed) * 0.00001 : 0);
+ seen .push(0);
+ permDiff .push(0);
+ polarity .push(sign);
+ decision .push();
+ trail .capacity(v+1);
+ setDecisionVar(v, dvar);
+ return v;
+}
+
+
+
+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);
+
+ vec<Lit> oc;
+ oc.clear();
+
+ Lit p; int i, j, flag = 0;
+ if(certifiedUNSAT) {
+ for (i = j = 0, p = lit_Undef; i < ps.size(); i++) {
+ oc.push(ps[i]);
+ if (value(ps[i]) == l_True || ps[i] == ~p || value(ps[i]) == l_False)
+ flag = 1;
+ }
+ }
+
+ 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 (flag && (certifiedUNSAT)) {
+ for (i = j = 0, p = lit_Undef; i < ps.size(); i++)
+ fprintf(certifiedOutput, "%i ", (var(ps[i]) + 1) * (-2 * sign(ps[i]) + 1));
+ fprintf(certifiedOutput, "0\n");
+
+ fprintf(certifiedOutput, "d ");
+ for (i = j = 0, p = lit_Undef; i < oc.size(); i++)
+ fprintf(certifiedOutput, "%i ", (var(oc[i]) + 1) * (-2 * sign(oc[i]) + 1));
+ fprintf(certifiedOutput, "0\n");
+ }
+
+ 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);
+ if(c.size()==2) {
+ watchesBin[~c[0]].push(Watcher(cr, c[1]));
+ watchesBin[~c[1]].push(Watcher(cr, c[0]));
+ } else {
+ watches[~c[0]].push(Watcher(cr, c[1]));
+ watches[~c[1]].push(Watcher(cr, c[0]));
+ }
+ if (c.learnt()) learnts_literals += c.size();
+ else clauses_literals += c.size(); }
+
+
+
+
+void Solver::detachClause(CRef cr, bool strict) {
+ const Clause& c = ca[cr];
+
+ assert(c.size() > 1);
+ if(c.size()==2) {
+ if (strict){
+ remove(watchesBin[~c[0]], Watcher(cr, c[1]));
+ remove(watchesBin[~c[1]], Watcher(cr, c[0]));
+ }else{
+ // Lazy detaching: (NOTE! Must clean all watcher lists before garbage collecting this clause)
+ watchesBin.smudge(~c[0]);
+ watchesBin.smudge(~c[1]);
+ }
+ } else {
+ if (strict){
+ remove(watches[~c[0]], Watcher(cr, c[1]));
+ remove(watches[~c[1]], Watcher(cr, c[0]));
+ }else{
+ // Lazy detaching: (NOTE! Must clean all watcher lists before garbage collecting this clause)
+ watches.smudge(~c[0]);
+ watches.smudge(~c[1]);
+ }
+ }
+ if (c.learnt()) learnts_literals -= c.size();
+ else clauses_literals -= c.size(); }
+
+
+void Solver::removeClause(CRef cr) {
+
+ Clause& c = ca[cr];
+
+ if (certifiedUNSAT) {
+ fprintf(certifiedOutput, "d ");
+ for (int i = 0; i < c.size(); i++)
+ fprintf(certifiedOutput, "%i ", (var(c[i]) + 1) * (-2 * sign(c[i]) + 1));
+ fprintf(certifiedOutput, "0\n");
+ }
+
+ 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 {
+ if(incremental) // Check clauses with many selectors is too time consuming
+ return (value(c[0]) == l_True) || (value(c[1]) == l_True);
+
+ // Default mode.
+ for (int i = 0; i < c.size(); i++)
+ if (value(c[i]) == l_True)
+ return true;
+ return false;
+}
+
+/************************************************************
+ * Compute LBD functions
+ *************************************************************/
+
+inline unsigned int Solver::computeLBD(const vec<Lit> & lits,int end) {
+ int nblevels = 0;
+ MYFLAG++;
+
+ if(incremental) { // ----------------- INCREMENTAL MODE
+ if(end==-1) end = lits.size();
+ unsigned int nbDone = 0;
+ for(int i=0;i<lits.size();i++) {
+ if(nbDone>=end) break;
+ if(isSelector(var(lits[i]))) continue;
+ nbDone++;
+ int l = level(var(lits[i]));
+ if (permDiff[l] != MYFLAG) {
+ permDiff[l] = MYFLAG;
+ nblevels++;
+ }
+ }
+ } else { // -------- DEFAULT MODE. NOT A LOT OF DIFFERENCES... BUT EASIER TO READ
+ for(int i=0;i<lits.size();i++) {
+ int l = level(var(lits[i]));
+ if (permDiff[l] != MYFLAG) {
+ permDiff[l] = MYFLAG;
+ nblevels++;
+ }
+ }
+ }
+
+ return nblevels;
+}
+
+inline unsigned int Solver::computeLBD(const Clause &c) {
+ int nblevels = 0;
+ MYFLAG++;
+
+ if(incremental) { // ----------------- INCREMENTAL MODE
+ int nbDone = 0;
+ for(int i=0;i<c.size();i++) {
+ if(nbDone>=c.sizeWithoutSelectors()) break;
+ if(isSelector(var(c[i]))) continue;
+ nbDone++;
+ int l = level(var(c[i]));
+ if (permDiff[l] != MYFLAG) {
+ permDiff[l] = MYFLAG;
+ nblevels++;
+ }
+ }
+ } else { // -------- DEFAULT MODE. NOT A LOT OF DIFFERENCES... BUT EASIER TO READ
+ for(int i=0;i<c.size();i++) {
+ int l = level(var(c[i]));
+ if (permDiff[l] != MYFLAG) {
+ permDiff[l] = MYFLAG;
+ nblevels++;
+ }
+ }
+ }
+ return nblevels;
+}
+
+
+/******************************************************************
+ * Minimisation with binary reolution
+ ******************************************************************/
+void Solver::minimisationWithBinaryResolution(vec<Lit> &out_learnt) {
+
+ // Find the LBD measure
+ unsigned int lbd = computeLBD(out_learnt);
+ Lit p = ~out_learnt[0];
+
+ if(lbd<=lbLBDMinimizingClause){
+ MYFLAG++;
+
+ for(int i = 1;i<out_learnt.size();i++) {
+ permDiff[var(out_learnt[i])] = MYFLAG;
+ }
+
+ vec<Watcher>& wbin = watchesBin[p];
+ int nb = 0;
+ for(int k = 0;k<wbin.size();k++) {
+ Lit imp = wbin[k].blocker;
+ if(permDiff[var(imp)]==MYFLAG && value(imp)==l_True) {
+ nb++;
+ permDiff[var(imp)]= MYFLAG-1;
+ }
+ }
+ int l = out_learnt.size()-1;
+ if(nb>0) {
+ nbReducedClauses++;
+ for(int i = 1;i<out_learnt.size()-nb;i++) {
+ if(permDiff[var(out_learnt[i])]!=MYFLAG) {
+ Lit p = out_learnt[l];
+ out_learnt[l] = out_learnt[i];
+ out_learnt[i] = p;
+ l--;i--;
+ }
+ }
+
+ out_learnt.shrink(nb);
+
+ }
+ }
+}
+
+// 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();
+
+ return next == var_Undef ? lit_Undef : mkLit(next, rnd_pol ? drand(random_seed) < 0.5 : (polarity[next] != 0));
+}
+
+
+/*_________________________________________________________________________________________________
+|
+| 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,vec<Lit>&selectors, int& out_btlevel,unsigned int &lbd,unsigned int &szWithoutSelectors)
+{
+ 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];
+
+ // Special case for binary clauses
+ // The first one has to be SAT
+ if( p != lit_Undef && c.size()==2 && value(c[0])==l_False) {
+
+ assert(value(c[1])==l_True);
+ Lit tmp = c[0];
+ c[0] = c[1], c[1] = tmp;
+ }
+
+ if (c.learnt())
+ claBumpActivity(c);
+
+#ifdef DYNAMICNBLEVEL
+ // DYNAMIC NBLEVEL trick (see competition'09 companion paper)
+ if(c.learnt() && c.lbd()>2) {
+ unsigned int nblevels = computeLBD(c);
+ if(nblevels+1<c.lbd() ) { // improve the LBD
+ if(c.lbd()<=lbLBDFrozenClause) {
+ c.setCanBeDel(false);
+ }
+ // seems to be interesting : keep it for the next round
+ c.setLBD(nblevels); // Update it
+ }
+ }
+#endif
+
+
+ for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){
+ Lit q = c[j];
+
+ if (!seen[var(q)] && level(var(q)) > 0){
+ if(!isSelector(var(q)))
+ varBumpActivity(var(q));
+ seen[var(q)] = 1;
+ if (level(var(q)) >= decisionLevel()) {
+ pathC++;
+#ifdef UPDATEVARACTIVITY
+ // UPDATEVARACTIVITY trick (see competition'09 companion paper)
+ if(!isSelector(var(q)) && (reason(var(q))!= CRef_Undef) && ca[reason(var(q))].learnt())
+ lastDecisionLevel.push(q);
+#endif
+
+ } else {
+ if(isSelector(var(q))) {
+ assert(value(q) == l_False);
+ selectors.push(q);
+ } 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;
+
+ for(i = 0;i<selectors.size();i++)
+ out_learnt.push(selectors[i]);
+
+ out_learnt.copyTo(analyze_toclear);
+ if (ccmin_mode == 2){
+ uint32_t abstract_level = 0;
+ for (i = 1; i < out_learnt.size(); i++)
+ abstract_level |= abstractLevel(var(out_learnt[i])); // (maintain an abstraction of levels involved in conflict)
+
+ for (i = j = 1; i < out_learnt.size(); i++)
+ if (reason(var(out_learnt[i])) == CRef_Undef || !litRedundant(out_learnt[i], abstract_level))
+ 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]))];
+ // Thanks to Siert Wieringa for this bug fix!
+ for (int k = ((c.size()==2) ? 0: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();
+
+
+ /* ***************************************
+ Minimisation with binary clauses of the asserting clause
+ First of all : we look for small clauses
+ Then, we reduce clauses with small LBD.
+ Otherwise, this can be useless
+ */
+ if(!incremental && out_learnt.size()<=lbSizeMinimizingClause) {
+ minimisationWithBinaryResolution(out_learnt);
+ }
+ // 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));
+ }
+
+
+ // Compute the size of the clause without selectors (incremental mode)
+ if(incremental) {
+ szWithoutSelectors = 0;
+ for(int i=0;i<out_learnt.size();i++) {
+ if(!isSelector(var((out_learnt[i])))) szWithoutSelectors++;
+ else if(i>0) break;
+ }
+ } else
+ szWithoutSelectors = out_learnt.size();
+
+ // Compute LBD
+ lbd = computeLBD(out_learnt,out_learnt.size()-selectors.size());
+
+
+#ifdef UPDATEVARACTIVITY
+ // UPDATEVARACTIVITY trick (see competition'09 companion paper)
+ if(lastDecisionLevel.size()>0) {
+ for(int i = 0;i<lastDecisionLevel.size();i++) {
+ if(ca[reason(var(lastDecisionLevel[i]))].lbd()<lbd)
+ varBumpActivity(var(lastDecisionLevel[i]));
+ }
+ lastDecisionLevel.clear();
+ }
+#endif
+
+
+
+ for (j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0; // ('seen[]' is now cleared)
+ for(j = 0 ; j<selectors.size() ; j++) seen[var(selectors[j])] = 0;
+}
+
+
+// Check if 'p' can be removed. 'abstract_levels' is used to abort early if the algorithm is
+// visiting literals at levels that cannot be removed later.
+bool Solver::litRedundant(Lit p, uint32_t abstract_levels)
+{
+ analyze_stack.clear(); analyze_stack.push(p);
+ int top = analyze_toclear.size();
+ while (analyze_stack.size() > 0){
+ assert(reason(var(analyze_stack.last())) != CRef_Undef);
+ Clause& c = ca[reason(var(analyze_stack.last()))]; analyze_stack.pop();
+ if(c.size()==2 && value(c[0])==l_False) {
+ assert(value(c[1])==l_True);
+ Lit tmp = c[0];
+ c[0] = c[1], c[1] = tmp;
+ }
+
+ for (int i = 1; i < c.size(); i++){
+ Lit p = c[i];
+ if (!seen[var(p)] && level(var(p)) > 0){
+ if (reason(var(p)) != CRef_Undef && (abstractLevel(var(p)) & abstract_levels) != 0){
+ seen[var(p)] = 1;
+ analyze_stack.push(p);
+ analyze_toclear.push(p);
+ }else{
+ for (int j = top; j < analyze_toclear.size(); j++)
+ seen[var(analyze_toclear[j])] = 0;
+ analyze_toclear.shrink(analyze_toclear.size() - top);
+ return false;
+ }
+ }
+ }
+ }
+
+ 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, vec<Lit>& out_conflict)
+{
+ out_conflict.clear();
+ out_conflict.push(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.push(~trail[i]);
+ }else{
+ Clause& c = ca[reason(x)];
+ // for (int j = 1; j < c.size(); j++) Minisat (glucose 2.0) loop
+ // Bug in case of assumptions due to special data structures for Binary.
+ // Many thanks to Sam Bayless (sbayless@cs.ubc.ca) for discover this bug.
+ for (int j = ((c.size()==2) ? 0: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;
+ watches.cleanAll();
+ watchesBin.cleanAll();
+ while (qhead < trail.size()){
+ Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate.
+ vec<Watcher>& ws = watches[p];
+ Watcher *i, *j, *end;
+ num_props++;
+
+
+ // First, Propagate binary clauses
+ vec<Watcher>& wbin = watchesBin[p];
+
+ for(int k = 0;k<wbin.size();k++) {
+
+ Lit imp = wbin[k].blocker;
+
+ if(value(imp) == l_False) {
+ return wbin[k].cref;
+ }
+
+ if(value(imp) == l_Undef) {
+ uncheckedEnqueue(imp,wbin[k].cref);
+ }
+ }
+
+
+
+ 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:
+ if(incremental) { // ----------------- INCREMENTAL MODE
+ int choosenPos = -1;
+ for (int k = 2; k < c.size(); k++) {
+
+ if (value(c[k]) != l_False){
+ if(decisionLevel()>assumptions.size()) {
+ choosenPos = k;
+ break;
+ } else {
+ choosenPos = k;
+
+ if(value(c[k])==l_True || !isSelector(var(c[k]))) {
+ break;
+ }
+ }
+
+ }
+ }
+ if(choosenPos!=-1) {
+ c[1] = c[choosenPos]; c[choosenPos] = false_lit;
+ watches[~c[1]].push(w);
+ goto NextClause; }
+ } else { // ----------------- DEFAULT MODE (NOT INCREMENTAL)
+ 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) {
+
+ // Main criteria... Like in MiniSat we keep all binary clauses
+ if(ca[x].size()> 2 && ca[y].size()==2) return 1;
+
+ if(ca[y].size()>2 && ca[x].size()==2) return 0;
+ if(ca[x].size()==2 && ca[y].size()==2) return 0;
+
+ // Second one based on literal block distance
+ if(ca[x].lbd()> ca[y].lbd()) return 1;
+ if(ca[x].lbd()< ca[y].lbd()) return 0;
+
+
+ // Finally we can use old activity or size, we choose the last one
+ return ca[x].activity() < ca[y].activity();
+ //return x->size() < y->size();
+
+ //return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity()); }
+ }
+};
+
+void Solver::reduceDB()
+{
+
+ int i, j;
+ nbReduceDB++;
+ sort(learnts, reduceDB_lt(ca));
+
+ // We have a lot of "good" clauses, it is difficult to compare them. Keep more !
+ if(ca[learnts[learnts.size() / RATIOREMOVECLAUSES]].lbd()<=3) nbclausesbeforereduce +=specialIncReduceDB;
+ // Useless :-)
+ if(ca[learnts.last()].lbd()<=5) nbclausesbeforereduce +=specialIncReduceDB;
+
+
+ // Don't delete binary or locked clauses. From the rest, delete clauses from the first half
+ // Keep clauses which seem to be usefull (their lbd was reduce during this sequence)
+
+ int limit = learnts.size() / 2;
+
+ for (i = j = 0; i < learnts.size(); i++){
+ Clause& c = ca[learnts[i]];
+ if (c.lbd()>2 && c.size() > 2 && c.canBeDel() && !locked(c) && (i < limit)) {
+ removeClause(learnts[i]);
+ nbRemovedClauses++;
+ }
+ else {
+ if(!c.canBeDel()) limit++; //we keep c, so we can delete an other clause
+ c.setCanBeDel(true); // At the next step, c can be delete
+ 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
+ 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);
+
+ 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,selectors;
+ unsigned int nblevels,szWoutSelectors;
+ bool blocked=false;
+ starts++;
+ for (;;){
+ CRef confl = propagate();
+ if (confl != CRef_Undef){
+ // CONFLICT
+ conflicts++; conflictC++;conflictsRestarts++;
+ if(conflicts%5000==0 && var_decay<0.95)
+ var_decay += 0.01;
+
+ if (verbosity >= 1 && conflicts%verbEveryConflicts==0){
+ printf("c | %8d %7d %5d | %7d %8d %8d | %5d %8d %6d %8d | %6.3f %% |\n",
+ (int)starts,(int)nbstopsrestarts, (int)(conflicts/starts),
+ (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]), nClauses(), (int)clauses_literals,
+ (int)nbReduceDB, nLearnts(), (int)nbDL2,(int)nbRemovedClauses, progressEstimate()*100);
+ }
+ if (decisionLevel() == 0) {
+ return l_False;
+
+ }
+
+ trailQueue.push(trail.size());
+ // BLOCK RESTART (CP 2012 paper)
+ if( conflictsRestarts>LOWER_BOUND_FOR_BLOCKING_RESTART && lbdQueue.isvalid() && trail.size()>R*trailQueue.getavg()) {
+ lbdQueue.fastclear();
+ nbstopsrestarts++;
+ if(!blocked) {lastblockatrestart=starts;nbstopsrestartssame++;blocked=true;}
+ }
+
+ learnt_clause.clear();
+ selectors.clear();
+ analyze(confl, learnt_clause, selectors,backtrack_level,nblevels,szWoutSelectors);
+
+ lbdQueue.push(nblevels);
+ sumLBD += nblevels;
+
+ cancelUntil(backtrack_level);
+
+ if (certifiedUNSAT) {
+ for (int i = 0; i < learnt_clause.size(); i++)
+ fprintf(certifiedOutput, "%i " , (var(learnt_clause[i]) + 1) *
+ (-2 * sign(learnt_clause[i]) + 1) );
+ fprintf(certifiedOutput, "0\n");
+ }
+
+ if (learnt_clause.size() == 1){
+ uncheckedEnqueue(learnt_clause[0]);nbUn++;
+ }else{
+ CRef cr = ca.alloc(learnt_clause, true);
+ ca[cr].setLBD(nblevels);
+ ca[cr].setSizeWithoutSelectors(szWoutSelectors);
+ if(nblevels<=2) nbDL2++; // stats
+ if(ca[cr].size()==2) nbBin++; // stats
+ learnts.push(cr);
+ attachClause(cr);
+
+ claBumpActivity(ca[cr]);
+ uncheckedEnqueue(learnt_clause[0], cr);
+ }
+ varDecayActivity();
+ claDecayActivity();
+
+
+ }else{
+
+ // Our dynamic restart, see the SAT09 competition compagnion paper
+ if ( (conflictsRestarts && lbdQueue.isvalid() && lbdQueue.getavg()*K > sumLBD/conflictsRestarts) || (pstop && *pstop) ) {
+ lbdQueue.fastclear();
+ progress_estimate = progressEstimate();
+ int bt = 0;
+ if(incremental) { // DO NOT BACKTRACK UNTIL 0.. USELESS
+ bt = (decisionLevel()<assumptions.size()) ? decisionLevel() : assumptions.size();
+ }
+ cancelUntil(bt);
+ return l_Undef;
+ }
+
+ // Simplify the set of problem clauses:
+ if (decisionLevel() == 0 && !simplify()) {
+ return l_False;
+ }
+ // Perform clause database reduction !
+ if(conflicts>=curRestart* nbclausesbeforereduce)
+ {
+
+ assert(learnts.size()>0);
+ curRestart = (conflicts/ nbclausesbeforereduce)+1;
+ reduceDB();
+ nbclausesbeforereduce += incReduceDB;
+ }
+
+ 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){
+ printf("c last restart ## conflicts : %d %d \n",conflictC,decisionLevel());
+ // 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();
+}
+
+void Solver::printIncrementalStats() {
+
+ printf("c---------- Glucose Stats -------------------------\n");
+ printf("c restarts : %lld\n", starts);
+ printf("c nb ReduceDB : %lld\n", nbReduceDB);
+ printf("c nb removed Clauses : %lld\n",nbRemovedClauses);
+ printf("c nb learnts DL2 : %lld\n", nbDL2);
+ printf("c nb learnts size 2 : %lld\n", nbBin);
+ printf("c nb learnts size 1 : %lld\n", nbUn);
+
+ printf("c conflicts : %lld \n",conflicts);
+ printf("c decisions : %lld\n",decisions);
+ printf("c propagations : %lld\n",propagations);
+
+ printf("c SAT Calls : %d in %g seconds\n",nbSatCalls,totalTime4Sat);
+ printf("c UNSAT Calls : %d in %g seconds\n",nbUnsatCalls,totalTime4Unsat);
+ printf("c--------------------------------------------------\n");
+
+
+}
+
+
+// NOTE: assumptions passed in member-variable 'assumptions'.
+lbool Solver::solve_()
+{
+
+ if(incremental && certifiedUNSAT) {
+ printf("Can not use incremental and certified unsat in the same time\n");
+ exit(-1);
+ }
+ model.clear();
+ conflict.clear();
+ if (!ok) return l_False;
+ double curTime = cpuTime();
+
+
+ solves++;
+
+
+
+ lbool status = l_Undef;
+ if(!incremental && verbosity>=1) {
+ printf("c ========================================[ MAGIC CONSTANTS ]==============================================\n");
+ printf("c | Constants are supposed to work well together :-) |\n");
+ printf("c | however, if you find better choices, please let us known... |\n");
+ printf("c |-------------------------------------------------------------------------------------------------------|\n");
+ printf("c | | | |\n");
+ printf("c | - Restarts: | - Reduce Clause DB: | - Minimize Asserting: |\n");
+ printf("c | * LBD Queue : %6d | * First : %6d | * size < %3d |\n",lbdQueue.maxSize(),nbclausesbeforereduce,lbSizeMinimizingClause);
+ printf("c | * Trail Queue : %6d | * Inc : %6d | * lbd < %3d |\n",trailQueue.maxSize(),incReduceDB,lbLBDMinimizingClause);
+ printf("c | * K : %6.2f | * Special : %6d | |\n",K,specialIncReduceDB);
+ printf("c | * R : %6.2f | * Protected : (lbd)< %2d | |\n",R,lbLBDFrozenClause);
+ printf("c | | | |\n");
+printf("c ==================================[ Search Statistics (every %6d conflicts) ]=========================\n",verbEveryConflicts);
+ printf("c | |\n");
+
+ printf("c | RESTARTS | ORIGINAL | LEARNT | Progress |\n");
+ printf("c | NB Blocked Avg Cfc | Vars Clauses Literals | Red Learnts LBD2 Removed | |\n");
+ printf("c =========================================================================================================\n");
+ }
+
+ // Search:
+ int curr_restarts = 0;
+ while (status == l_Undef){
+ status = search(0); // the parameter is useless in glucose, kept to allow modifications
+ if (!withinBudget() || terminate_search_early || (pstop && *pstop)) break;
+ curr_restarts++;
+ }
+
+ if (!incremental && verbosity >= 1)
+ printf("c =========================================================================================================\n");
+
+
+ if (certifiedUNSAT){ // Want certified output
+ if (status == l_False)
+ fprintf(certifiedOutput, "0\n");
+ fclose(certifiedOutput);
+ }
+
+
+ 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);
+
+ double finalTime = cpuTime();
+ if(status==l_True) {
+ nbSatCalls++;
+ totalTime4Sat +=(finalTime-curTime);
+ }
+ if(status==l_False) {
+ nbUnsatCalls++;
+ totalTime4Unsat +=(finalTime-curTime);
+ }
+
+ // ABC callback
+ if (pCnfFunc && !terminate_search_early) {// hack to avoid calling callback twise if the solver was terminated early
+ int * pCex = NULL;
+ int message = (status == l_True ? 1 : status == l_False ? 0 : -1);
+ if (status == l_True) {
+ pCex = new int[nVars()];
+ for (int i = 0; i < nVars(); i++)
+ pCex[i] = (model[i] == l_True);
+ }
+
+ int callback_result = pCnfFunc(pCnfMan, message, pCex);
+ assert(callback_result == 0);
+ }
+ else if (pCnfFunc)
+ terminate_search_early = false; // for next run
+
+ return status;
+}
+
+//=================================================================================================
+// 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 i, cnt = 0;
+ for (i = 0; i < clauses.size(); i++)
+ if (!satisfied(ca[clauses[i]]))
+ cnt++;
+
+ for (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 += assumptions.size();
+
+ fprintf(f, "p cnf %d %d\n", max, cnt);
+
+ for (i = 0; i < assumptions.size(); i++){
+ assert(value(assumptions[i]) != l_False);
+ fprintf(f, "%s%d 0\n", sign(assumptions[i]) ? "-" : "", mapVar(var(assumptions[i]), map, max)+1);
+ }
+
+ for (i = 0; i < clauses.size(); i++)
+ toDimacs(f, ca[clauses[i]], map, max);
+
+ if (verbosity > 0)
+ printf("Wrote %d clauses with %d variables.\n", cnt, max);
+}
+
+
+//=================================================================================================
+// Garbage Collection methods:
+
+void Solver::relocAll(ClauseAllocator& to)
+{
+ int v, s, i, j;
+ // All watchers:
+ //
+ // for (int i = 0; i < watches.size(); i++)
+ watches.cleanAll();
+ watchesBin.cleanAll();
+ for (v = 0; v < nVars(); v++)
+ for (s = 0; s < 2; s++){
+ Lit p = mkLit(v, s != 0);
+ // printf(" >>> RELOCING: %s%d\n", sign(p)?"-":"", var(p)+1);
+ vec<Watcher>& ws = watches[p];
+ for (j = 0; j < ws.size(); j++)
+ ca.reloc(ws[j].cref, to);
+ vec<Watcher>& ws2 = watchesBin[p];
+ for (j = 0; j < ws2.size(); j++)
+ ca.reloc(ws2[j].cref, to);
+ }
+
+ // All reasons:
+ //
+ for (i = 0; i < trail.size(); i++){
+ Var v = var(trail[i]);
+
+ if (reason(v) != CRef_Undef && (ca[reason(v)].reloced() || locked(ca[reason(v)])))
+ ca.reloc(vardata[v].reason, to);
+ }
+
+ // All learnt:
+ //
+ for (i = 0; i < learnts.size(); i++)
+ ca.reloc(learnts[i], to);
+
+ // All original:
+ //
+ for (i = 0; i < clauses.size(); i++)
+ ca.reloc(clauses[i], to);
+}
+
+
+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);
+}