#ifndef Glucose_Solver_h
#define Glucose_Solver_h
#include "mtl/Heap.h"
#include "mtl/Alg.h"
#include "utils/Options.h"
#include "core/SolverTypes.h"
#include "core/BoundedQueue.h"
#include "core/Constants.h"
#include "mtl/Clone.h"
#include "core/SolverStats.h"
namespace Glucose {
enum CoreStats {
sumResSeen,
sumRes,
sumTrail,
nbPromoted,
originalClausesSeen,
sumDecisionLevels,
nbPermanentLearnts,
nbRemovedClauses,
nbRemovedUnaryWatchedClauses,
nbReducedClauses,
nbDL2,
nbBin,
nbUn,
nbReduceDB,
rnd_decisions,
nbstopsrestarts,
nbstopsrestartssame,
lastblockatrestart,
dec_vars,
clauses_literals,
learnts_literals,
max_literals,
tot_literals,
noDecisionConflict,
lcmtested,
lcmreduced,
sumSizes
} ;
#define coreStatsSize 27
class Solver : public Clone {
friend class SolverConfiguration;
public:
Solver();
Solver(const Solver &s);
virtual ~Solver();
virtual Clone* clone() const {
return new Solver(*this);
}
virtual Var newVar (bool polarity = true, bool dvar = true); bool addClause (const vec<Lit>& ps); bool addEmptyClause(); bool addClause (Lit p); bool addClause (Lit p, Lit q); bool addClause (Lit p, Lit q, Lit r); virtual bool addClause_( vec<Lit>& ps); bool simplify (); bool solve (const vec<Lit>& assumps); lbool solveLimited (const vec<Lit>& assumps); bool solve (); bool solve (Lit p); bool solve (Lit p, Lit q); bool solve (Lit p, Lit q, Lit r); bool okay () const;
void toDimacs (FILE* f, const vec<Lit>& assumps); void toDimacs (const char *file, const vec<Lit>& assumps);
void toDimacs (FILE* f, Clause& c, vec<Var>& map, Var& max);
void toDimacs (const char* file);
void toDimacs (const char* file, Lit p);
void toDimacs (const char* file, Lit p, Lit q);
void toDimacs (const char* file, Lit p, Lit q, Lit r);
void printLit(Lit l);
void printClause(CRef c);
void printInitialClause(CRef c);
void setPolarity (Var v, bool b); void setDecisionVar (Var v, bool b);
lbool value (Var x) const; lbool value (Lit p) const; lbool modelValue (Var x) const; lbool modelValue (Lit p) const; int nAssigns () const; int nClauses () const; int nLearnts () const; int nVars () const; int nFreeVars () ;
inline char valuePhase(Var v) {return polarity[v];}
void setIncrementalMode();
void initNbInitialVars(int nb);
void printIncrementalStats();
bool isIncremental();
void setConfBudget(int64_t x);
void setPropBudget(int64_t x);
void budgetOff();
void interrupt(); void clearInterrupt();
virtual void garbageCollect();
void checkGarbage(double gf);
void checkGarbage();
vec<lbool> model; vec<Lit> conflict;
int verbosity;
int verbEveryConflicts;
int showModel;
double K;
double R;
double sizeLBDQueue;
double sizeTrailQueue;
int firstReduceDB;
int incReduceDB;
int specialIncReduceDB;
unsigned int lbLBDFrozenClause;
bool chanseokStrategy;
int coLBDBound; int lbSizeMinimizingClause;
unsigned int lbLBDMinimizingClause;
bool useLCM; bool LCMUpdateLBD;
double var_decay;
double max_var_decay;
double clause_decay;
double random_var_freq;
double random_seed;
int ccmin_mode; int phase_saving; bool rnd_pol; bool rnd_init_act; bool randomizeFirstDescent;
double garbage_frac;
FILE* certifiedOutput;
bool certifiedUNSAT;
bool vbyte;
void write_char (unsigned char c);
void write_lit (int n);
template <typename T> void addToDrat(T & lits, bool add);
uint32_t panicModeLastRemoved, panicModeLastRemovedShared;
bool useUnaryWatched; bool promoteOneWatchedClause;
virtual void parallelImportClauseDuringConflictAnalysis(Clause &c,CRef confl);
virtual bool parallelImportClauses(); virtual void parallelImportUnaryClauses();
virtual void parallelExportUnaryClause(Lit p);
virtual void parallelExportClauseDuringSearch(Clause &c);
virtual bool parallelJobIsFinished();
virtual bool panicModeIsEnabled();
double luby(double y, int x);
vec<uint64_t> stats;
uint64_t solves,starts,decisions,propagations,conflicts,conflictsRestarts;
protected:
long curRestart;
bool glureduce;
uint32_t restart_inc;
bool luby_restart;
bool adaptStrategies;
uint32_t luby_restart_factor;
bool randomize_on_restarts, fixed_randomize_on_restarts, newDescent;
uint32_t randomDescentAssignments;
bool forceUnsatOnNewDescent;
struct VarData { CRef reason; int level; };
static inline VarData mkVarData(CRef cr, int l){ VarData d = {cr, l}; return d; }
struct Watcher {
CRef cref;
Lit blocker;
Watcher(CRef cr, Lit p) : cref(cr), blocker(p) {}
bool operator==(const Watcher& w) const { return cref == w.cref; }
bool operator!=(const Watcher& w) const { return cref != w.cref; }
};
struct WatcherDeleted
{
const ClauseAllocator& ca;
WatcherDeleted(const ClauseAllocator& _ca) : ca(_ca) {}
bool operator()(const Watcher& w) const { return ca[w.cref].mark() == 1; }
};
struct VarOrderLt {
const vec<double>& activity;
bool operator () (Var x, Var y) const { return activity[x] > activity[y]; }
VarOrderLt(const vec<double>& act) : activity(act) { }
};
int lastIndexRed;
bool ok; double cla_inc; vec<double> activity; double var_inc; OccLists<Lit, vec<Watcher>, WatcherDeleted>
watches; OccLists<Lit, vec<Watcher>, WatcherDeleted>
watchesBin; OccLists<Lit, vec<Watcher>, WatcherDeleted>
unaryWatches; vec<CRef> clauses; vec<CRef> learnts; vec<CRef> permanentLearnts; vec<CRef> permanentLearntsReduced; vec<CRef> unaryWatchedClauses; vec<CRef> mostActiveClauses;
vec<lbool> assigns; vec<char> polarity; vec<char> forceUNSAT;
void bumpForceUNSAT(Lit q);
vec<char> decision; vec<Lit> trail; vec<int> nbpos;
vec<int> trail_lim; vec<VarData> vardata; int qhead; int simpDB_assigns; int64_t simpDB_props; vec<Lit> assumptions; Heap<VarOrderLt> order_heap; double progress_estimate; bool remove_satisfied; vec<unsigned int> permDiff;
vec<Lit> lastDecisionLevel;
ClauseAllocator ca;
int nbclausesbeforereduce;
bqueue<unsigned int> trailQueue,lbdQueue; float sumLBD; int sumAssumptions;
CRef lastLearntClause;
vec<char> seen;
vec<Lit> analyze_stack;
vec<Lit> analyze_toclear;
vec<Lit> add_tmp;
unsigned int MYFLAG;
double max_learnts;
double learntsize_adjust_confl;
int learntsize_adjust_cnt;
int64_t conflict_budget; int64_t propagation_budget; bool asynch_interrupt;
int incremental; int nbVarsInitialFormula; double totalTime4Sat,totalTime4Unsat;
int nbSatCalls,nbUnsatCalls;
vec<int> assumptionPositions,initialPositions;
void insertVarOrder (Var x); Lit pickBranchLit (); void newDecisionLevel (); void uncheckedEnqueue (Lit p, CRef from = CRef_Undef); bool enqueue (Lit p, CRef from = CRef_Undef); CRef propagate (); CRef propagateUnaryWatches(Lit p); void cancelUntil (int level); void analyze (CRef confl, vec<Lit>& out_learnt, vec<Lit> & selectors, int& out_btlevel,unsigned int &nblevels,unsigned int &szWithoutSelectors); void analyzeFinal (Lit p, vec<Lit>& out_conflict); bool litRedundant (Lit p, uint32_t abstract_levels); lbool search (int nof_conflicts); virtual lbool solve_ (bool do_simp = true, bool turn_off_simp = false); virtual void reduceDB (); void removeSatisfied (vec<CRef>& cs); void rebuildOrderHeap ();
void adaptSolver();
void varDecayActivity (); void varBumpActivity (Var v, double inc); void varBumpActivity (Var v); void claDecayActivity (); void claBumpActivity (Clause& c);
void attachClause (CRef cr); void detachClause (CRef cr, bool strict = false); void detachClausePurgatory(CRef cr, bool strict = false);
void attachClausePurgatory(CRef cr);
void removeClause (CRef cr, bool inPurgatory = false); bool locked (const Clause& c) const; bool satisfied (const Clause& c) const;
template <typename T> unsigned int computeLBD(const T & lits,int end=-1);
void minimisationWithBinaryResolution(vec<Lit> &out_learnt);
virtual void relocAll (ClauseAllocator& to);
int decisionLevel () const; uint32_t abstractLevel (Var x) const; CRef reason (Var x) const;
int level (Var x) const;
double progressEstimate () const; bool withinBudget () const;
inline bool isSelector(Var v) {return (incremental && v>nbVarsInitialFormula);}
static inline double drand(double& seed) {
seed *= 1389796;
int q = (int)(seed / 2147483647);
seed -= (double)q * 2147483647;
return seed / 2147483647; }
static inline int irand(double& seed, int size) {
return (int)(drand(seed) * size); }
public:
bool simplifyAll();
void simplifyLearnt(Clause& c);
int trailRecord;
void litsEnqueue(int cutP, Clause& c);
void cancelUntilTrailRecord();
void simpleUncheckEnqueue(Lit p, CRef from = CRef_Undef);
CRef simplePropagate();
CRef simplePropagateUnaryWatches(Lit p);
vec<Lit> simp_learnt_clause;
vec<CRef> simp_reason_clause;
void simpleAnalyze(CRef confl, vec<Lit>& out_learnt, vec<CRef>& reason_clause, bool True_confl);
bool removed(CRef cr);
int performLCM;
vec<int> valueDup;
void compareValue();
void wholeCompareValue();
};
inline CRef Solver::reason(Var x) const { return vardata[x].reason; }
inline int Solver::level (Var x) const { return vardata[x].level; }
inline void Solver::insertVarOrder(Var x) {
if (!order_heap.inHeap(x) && decision[x]) order_heap.insert(x); }
inline void Solver::varDecayActivity() { var_inc *= (1 / var_decay); }
inline void Solver::varBumpActivity(Var v) { varBumpActivity(v, var_inc); }
inline void Solver::varBumpActivity(Var v, double inc) {
if ( (activity[v] += inc) > 1e100 ) {
for (int i = 0; i < nVars(); i++)
activity[i] *= 1e-100;
var_inc *= 1e-100; }
if (order_heap.inHeap(v))
order_heap.decrease(v); }
inline void Solver::claDecayActivity() { cla_inc *= (1 / clause_decay); }
inline void Solver::claBumpActivity (Clause& c) {
if ( (c.activity() += cla_inc) > 1e20 ) {
for (int i = 0; i < learnts.size(); i++)
ca[learnts[i]].activity() *= 1e-20;
cla_inc *= 1e-20; } }
inline void Solver::checkGarbage(void){ return checkGarbage(garbage_frac); }
inline void Solver::checkGarbage(double gf){
if (ca.wasted() > ca.size() * gf)
garbageCollect(); }
inline bool Solver::enqueue (Lit p, CRef from) { return value(p) != l_Undef ? value(p) != l_False : (uncheckedEnqueue(p, from), true); }
inline bool Solver::addClause (const vec<Lit>& ps) { ps.copyTo(add_tmp); return addClause_(add_tmp); }
inline bool Solver::addEmptyClause () { add_tmp.clear(); return addClause_(add_tmp); }
inline bool Solver::addClause (Lit p) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp); }
inline bool Solver::addClause (Lit p, Lit q) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp); }
inline bool Solver::addClause (Lit p, Lit q, Lit r) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); }
inline bool Solver::locked (const Clause& c) const {
if(c.size()>2)
return value(c[0]) == l_True && reason(var(c[0])) != CRef_Undef && ca.lea(reason(var(c[0]))) == &c;
return
(value(c[0]) == l_True && reason(var(c[0])) != CRef_Undef && ca.lea(reason(var(c[0]))) == &c)
||
(value(c[1]) == l_True && reason(var(c[1])) != CRef_Undef && ca.lea(reason(var(c[1]))) == &c);
}
inline void Solver::newDecisionLevel() { trail_lim.push(trail.size()); }
inline int Solver::decisionLevel () const { return trail_lim.size(); }
inline uint32_t Solver::abstractLevel (Var x) const { return 1 << (level(x) & 31); }
inline lbool Solver::value (Var x) const { return assigns[x]; }
inline lbool Solver::value (Lit p) const { return assigns[var(p)] ^ sign(p); }
inline lbool Solver::modelValue (Var x) const { return model[x]; }
inline lbool Solver::modelValue (Lit p) const { return model[var(p)] ^ sign(p); }
inline int Solver::nAssigns () const { return trail.size(); }
inline int Solver::nClauses () const { return clauses.size(); }
inline int Solver::nLearnts () const { return learnts.size(); }
inline int Solver::nVars () const { return vardata.size(); }
inline int Solver::nFreeVars () {
int a = stats[dec_vars];
return (int)(a) - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]); }
inline void Solver::setPolarity (Var v, bool b) { polarity[v] = b; }
inline void Solver::setDecisionVar(Var v, bool b)
{
if ( b && !decision[v]) stats[dec_vars]++;
else if (!b && decision[v]) stats[dec_vars]--;
decision[v] = b;
insertVarOrder(v);
}
inline void Solver::setConfBudget(int64_t x){ conflict_budget = conflicts + x; }
inline void Solver::setPropBudget(int64_t x){ propagation_budget = propagations + x; }
inline void Solver::interrupt(){ asynch_interrupt = true; }
inline void Solver::clearInterrupt(){ asynch_interrupt = false; }
inline void Solver::budgetOff(){ conflict_budget = propagation_budget = -1; }
inline bool Solver::withinBudget() const {
return !asynch_interrupt &&
(conflict_budget < 0 || conflicts < (uint64_t)conflict_budget) &&
(propagation_budget < 0 || propagations < (uint64_t)propagation_budget); }
inline bool Solver::solve () { budgetOff(); assumptions.clear(); return solve_() == l_True; }
inline bool Solver::solve (Lit p) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_() == l_True; }
inline bool Solver::solve (Lit p, Lit q) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_() == l_True; }
inline bool Solver::solve (Lit p, Lit q, Lit r) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_() == l_True; }
inline bool Solver::solve (const vec<Lit>& assumps){ budgetOff(); assumps.copyTo(assumptions); return solve_() == l_True; }
inline lbool Solver::solveLimited (const vec<Lit>& assumps){ assumps.copyTo(assumptions); return solve_(); }
inline bool Solver::okay () const { return ok; }
inline void Solver::toDimacs (const char* file){ vec<Lit> as; toDimacs(file, as); }
inline void Solver::toDimacs (const char* file, Lit p){ vec<Lit> as; as.push(p); toDimacs(file, as); }
inline void Solver::toDimacs (const char* file, Lit p, Lit q){ vec<Lit> as; as.push(p); as.push(q); toDimacs(file, as); }
inline void Solver::toDimacs (const char* file, Lit p, Lit q, Lit r){ vec<Lit> as; as.push(p); as.push(q); as.push(r); toDimacs(file, as); }
template <typename T>inline unsigned int Solver::computeLBD(const T &lits, int end) {
int nblevels = 0;
MYFLAG++;
#ifdef INCREMENTAL
if(incremental) { if(end==-1) end = lits.size();
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 { #endif
for(int i = 0; i < lits.size(); i++) {
int l = level(var(lits[i]));
if(permDiff[l] != MYFLAG) {
permDiff[l] = MYFLAG;
nblevels++;
}
}
#ifdef INCREMENTAL
}
#endif
return nblevels;
}
inline void Solver::printLit(Lit l)
{
printf("%s%d:%c", sign(l) ? "-" : "", var(l)+1, value(l) == l_True ? '1' : (value(l) == l_False ? '0' : 'X'));
}
inline void Solver::printClause(CRef cr)
{
Clause &c = ca[cr];
for (int i = 0; i < c.size(); i++){
printLit(c[i]);
printf(" ");
}
}
inline void Solver::printInitialClause(CRef cr)
{
Clause &c = ca[cr];
for (int i = 0; i < c.size(); i++){
if(!isSelector(var(c[i]))) {
printLit(c[i]);
printf(" ");
}
}
}
template <typename T>inline void Solver::addToDrat(T &lits, bool add) {
if(vbyte) {
if(add)
write_char('a');
else
write_char('d');
for(int i = 0; i < lits.size(); i++)
write_lit(2 * (var(lits[i]) + 1) + sign(lits[i]));
write_lit(0);
}
else {
if(!add)
fprintf(certifiedOutput, "d ");
for(int i = 0; i < lits.size(); i++)
fprintf(certifiedOutput, "%i ", (var(lits[i]) + 1) * (-2 * sign(lits[i]) + 1));
fprintf(certifiedOutput, "0\n");
}
}
struct reduceDBAct_lt {
ClauseAllocator& ca;
reduceDBAct_lt(ClauseAllocator& ca_) : ca(ca_) {
}
bool operator()(CRef x, CRef y) {
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;
return ca[x].activity() < ca[y].activity();
}
};
struct reduceDB_lt {
ClauseAllocator& ca;
reduceDB_lt(ClauseAllocator& ca_) : ca(ca_) {
}
bool operator()(CRef x, CRef y) {
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;
if (ca[x].lbd() > ca[y].lbd()) return 1;
if (ca[x].lbd() < ca[y].lbd()) return 0;
return ca[x].activity() < ca[y].activity();
}
};
}
#endif