SRCS+=$(wildcard NodeFactory/*.cpp)
OBJS = $(SRCS:.cpp=.o)
OBJS+= ASTKind.o
-CFLAGS += -I$(MTL)
+CFLAGS += -I$(MTL) -I$(SOLVER_INCLUDE)
+
#Make the ast library for use by other modules
libast.a:$(OBJS) depend
depend: $(SRCS)
@$(CXX) -MM $(CXXFLAGS) $(SRCS) > $@
-#-include depend
\ No newline at end of file
+#-include depend
SRCS=main.cpp versionString.cpp Globals.cpp
OBJS = $(SRCS:.cpp=.o)
+CFLAGS += -I$(MTL) -I$(SOLVER_INCLUDE)
LIBS = -L../to-sat -ltosat \
-L../STPManager -lstpmgr \
# This rebuilds each time, because the target "parser" is not created
# Until the dependencies on each of the libraries is included, that's safest.
parser: $(OBJS) depend
- $(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o stp
+ $(CXX) $(CXXFLAGS) -I$(MTL) $(LDFLAGS) $(OBJS) $(LIBS) -o stp
@mv stp ../../bin/stp
#.PHONY: clean
-#-include depend
\ No newline at end of file
+#-include depend
#include "../AST/NodeFactory/TypeChecker.h"
#include "../AST/NodeFactory/SimplifyingNodeFactory.h"
#include "../parser/ParserInterface.h"
+#include <sys/time.h>
+
#ifdef EXT_HASH_MAP
using namespace __gnu_cxx;
//#define DEBUG_BITARRAY
-#include <stdint.h>
#include <string.h>
#include <assert.h>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
-#ifndef uint
-#define uint unsigned int
-#endif
+namespace MINISAT
+{
+using namespace MINISAT;
class BitArray
{
uint64_t* mp;
};
+}; //NAMESPACE MINISAT
+
#endif //BITARRAY_H
#ifndef BoundedQueue_h
#define BoundedQueue_h
-#include "../mtl/Vec.h"
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include "Vec.h"
//=================================================================================================
namespace MINISAT
{
+using namespace MINISAT;
template <class T>
class bqueue {
vec<T> elems;
int first;
- int last;
- unsigned long long sumofqueue;
- int maxsize;
- int queuesize; // Number of current elements (must be < maxsize !)
-
+ int last;
+ uint64_t sumofqueue;
+ int maxsize;
+ int queuesize; // Number of current elements (must be < maxsize !)
+
public:
- bqueue(void) : first(0), last(0), sumofqueue(0), maxsize(0), queuesize(0) { }
-
- void initSize(int size) {growTo(size);} // Init size of bounded size queue
-
- void push(T x) {
- if (queuesize==maxsize) {
- assert(last==first); // The queue is full, next value to enter will replace oldest one
- sumofqueue -= elems[last];
- if ((++last) == maxsize) last = 0;
- } else
- queuesize++;
- sumofqueue += x;
- elems[first] = x;
- if ((++first) == maxsize) first = 0;
- }
+ bqueue(void) : first(0), last(0), sumofqueue(0), maxsize(0), queuesize(0) { }
+
+ void initSize(int size) {growTo(size);} // Init size of bounded size queue
+
+ void push(T x) {
+ if (queuesize==maxsize) {
+ assert(last==first); // The queue is full, next value to enter will replace oldest one
+ sumofqueue -= elems[last];
+ if ((++last) == maxsize) last = 0;
+ } else
+ queuesize++;
+ sumofqueue += x;
+ elems[first] = x;
+ if ((++first) == maxsize) first = 0;
+ }
- T peek() { assert(queuesize>0); return elems[last]; }
- void pop() {sumofqueue-=elems[last]; queuesize--; if ((++last) == maxsize) last = 0;}
-
- unsigned long long getsum() const {return sumofqueue;}
- unsigned int getavg() const {return (unsigned int)(sumofqueue/((unsigned long long)queuesize));}
- int isvalid() const {return (queuesize==maxsize);}
-
- void growTo(int size) {
- elems.growTo(size);
- first=0; maxsize=size; queuesize = 0;
- for(int i=0;i<size;i++) elems[i]=0;
- }
+ T peek() { assert(queuesize>0); return elems[last]; }
+ void pop() {sumofqueue-=elems[last]; queuesize--; if ((++last) == maxsize) last = 0;}
+
+ uint64_t getsum() const {return sumofqueue;}
+ uint32_t getavg() const {return (uint64_t)sumofqueue/(uint64_t)queuesize;}
+ int isvalid() const {return (queuesize==maxsize);}
+
+ void growTo(int size) {
+ elems.growTo(size);
+ first=0; maxsize=size; queuesize = 0;
+ for(int i=0;i<size;i++) elems[i]=0;
+ }
- void fastclear() {first = 0; last = 0; queuesize=0; sumofqueue=0;} // to be called after restarts... Discard the queue
-
+ void fastclear() {first = 0; last = 0; queuesize=0; sumofqueue=0;} // to be called after restarts... Discard the queue
+
int size(void) { return queuesize; }
void clear(bool dealloc = false) { elems.clear(dealloc); first = 0; maxsize=0; queuesize=0;sumofqueue=0;}
-
-
-};
-
};
//=================================================================================================
+
+}; //namespace MINISAT
+
#endif
--- /dev/null
+/**************************************************************************************************
+From: Solver.C -- (C) Niklas Een, Niklas Sorensson, 2004
+**************************************************************************************************/
+
+#ifndef CSET_H
+#define CSET_H
+
+#include "Vec.h"
+#include <limits>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+class Clause;
+
+template <class T>
+uint32_t calcAbstraction(const T& ps) {
+ uint32_t abstraction = 0;
+ for (uint32_t i = 0; i != ps.size(); i++)
+ abstraction |= 1 << (ps[i].toInt() & 31);
+ return abstraction;
+}
+
+//#pragma pack(push)
+//#pragma pack(1)
+class ClauseSimp
+{
+ public:
+ ClauseSimp(Clause* c, const uint32_t _index) :
+ clause(c)
+ , index(_index)
+ {}
+
+ Clause* clause;
+ uint32_t index;
+};
+//#pragma pack(pop)
+
+class CSet {
+ vec<uint32_t> where; // Map clause ID to position in 'which'.
+ vec<ClauseSimp> which; // List of clauses (for fast iteration). May contain 'Clause_NULL'.
+ vec<uint32_t> free; // List of positions holding 'Clause_NULL'.
+
+ public:
+ //ClauseSimp& operator [] (uint32_t index) { return which[index]; }
+ void reserve(uint32_t size) { where.reserve(size);}
+ uint32_t size(void) const { return which.size(); }
+ uint32_t nElems(void) const { return which.size() - free.size(); }
+
+ bool add(const ClauseSimp& c) {
+ assert(c.clause != NULL);
+ where.growTo(c.index+1, std::numeric_limits<uint32_t>::max());
+ if (where[c.index] != std::numeric_limits<uint32_t>::max()) {
+ return true;
+ }
+ if (free.size() > 0){
+ where[c.index] = free.last();
+ which[free.last()] = c;
+ free.pop();
+ }else{
+ where[c.index] = which.size();
+ which.push(c);
+ }
+ return false;
+ }
+
+ bool exclude(const ClauseSimp& c) {
+ assert(c.clause != NULL);
+ if (c.index >= where.size() || where[c.index] == std::numeric_limits<uint32_t>::max()) {
+ //not inside
+ return false;
+ }
+ free.push(where[c.index]);
+ which[where[c.index]].clause = NULL;
+ where[c.index] = std::numeric_limits<uint32_t>::max();
+ return true;
+ }
+
+ void clear(void) {
+ for (uint32_t i = 0; i < which.size(); i++) {
+ if (which[i].clause != NULL) {
+ where[which[i].index] = std::numeric_limits<uint32_t>::max();
+ }
+ }
+ which.clear();
+ free.clear();
+ }
+
+ class iterator
+ {
+ public:
+ iterator(ClauseSimp* _it) :
+ it(_it)
+ {}
+
+ void operator++()
+ {
+ it++;
+ }
+
+ const bool operator!=(const iterator& iter) const
+ {
+ return (it != iter.it);;
+ }
+
+ ClauseSimp& operator*() {
+ return *it;
+ }
+
+ ClauseSimp*& operator->() {
+ return it;
+ }
+ private:
+ ClauseSimp* it;
+ };
+
+ iterator begin()
+ {
+ return iterator(which.getData());
+ }
+
+ iterator end()
+ {
+ return iterator(which.getData() + which.size());
+ }
+};
+
+}; //NAMESPACE MINISAT
+
+#endif //CSET_H
\ No newline at end of file
--- /dev/null
+#include "Clause.h"
+
+//boost::pool<> binaryClausePool(sizeof(Clause)+2*sizeof(Lit));
#ifndef CLAUSE_H
#define CLAUSE_H
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
#include <stdint.h>
+#endif //_MSC_VER
#include <cstdio>
#include <vector>
#include <sys/types.h>
-#include "mtl/Vec.h"
+#include "Vec.h"
#include "SolverTypes.h"
#include "PackedRow.h"
-
-namespace MINISAT
-{
-
+#include "constants.h"
+//#include "pool.hpp"
#ifndef uint
#define uint unsigned int
#endif
using std::vector;
+namespace MINISAT
+{
+using namespace MINISAT;
//=================================================================================================
// Clause -- a simple class for representing a clause:
class Clause
{
-public:
- const uint group;
protected:
- /**
- bit-layout of size_etc:
- range type meaning
- --------------------------------------------
- 0th bit bool learnt clause
- 1st - 2nd bit 2bit int marking
- 3rd bit bool inverted xor
- 4th -31st bit 28bit uint size
- */
- uint32_t size_etc;
- union { int act; uint32_t abst; } extra;
+ #ifdef STATS_NEEDED
+ uint group;
+ #endif
+
+ uint32_t isLearnt:1;
+ uint32_t strenghtened:1;
+ uint32_t varChanged:1;
+ uint32_t sorted:1;
+ uint32_t invertedXor:1;
+ uint32_t isXorClause:1;
+ uint32_t subsume0Done:1;
+ uint32_t mySize:20;
+
+ union {int32_t act; uint32_t abst;} extra;
+ #ifdef _MSC_VER
+ Lit data[1];
+ #else
Lit data[0];
+ #endif //_MSC_VER
+#ifdef _MSC_VER
public:
-
+#endif //_MSC_VER
template<class V>
- Clause(const V& ps, const uint _group, const bool learnt) :
- group(_group)
+ Clause(const V& ps, const uint _group, const bool learnt)
{
- size_etc = 0;
- setSize(ps.size());
- setLearnt(learnt);
+ isXorClause = false;
+ strenghtened = false;
+ sorted = false;
+ varChanged = true;
+ subsume0Done = false;
+ mySize = ps.size();
+ isLearnt = learnt;
+ setGroup(_group);
for (uint i = 0; i < ps.size(); i++) data[i] = ps[i];
if (learnt) extra.act = 0;
else calcAbstraction();
}
+public:
+ #ifndef _MSC_VER
// -- use this function instead:
template<class T>
friend Clause* Clause_new(const T& ps, const uint group, const bool learnt = false);
+ #endif //_MSC_VER
- uint size () const {
- return size_etc >> 4;
+ const uint size () const {
+ return mySize;
}
- void shrink (uint i) {
+ void resize (const uint size) {
+ mySize = size;
+ }
+ void shrink (const uint i) {
assert(i <= size());
- size_etc = (((size_etc >> 4) - i) << 4) | (size_etc & ((1 << 4)-1));
+ mySize -= i;
}
void pop () {
shrink(1);
}
- bool learnt () const {
- return size_etc & 1;
+ const bool isXor () {
+ return isXorClause;
+ }
+ const bool learnt () const {
+ return isLearnt;
+ }
+ const bool getStrenghtened() const {
+ return strenghtened;
}
- uint32_t mark () const {
- return (size_etc >> 1) & 3;
+ void setStrenghtened() {
+ strenghtened = true;
+ sorted = false;
+ subsume0Done = false;
}
- void mark (uint32_t m) {
- size_etc = (size_etc & ~6) | ((m & 3) << 1);
+ void unsetStrenghtened() {
+ strenghtened = false;
+ }
+ const bool getVarChanged() const {
+ return varChanged;
+ }
+ void setVarChanged() {
+ varChanged = true;
+ sorted = false;
+ subsume0Done = false;
+ }
+ void unsetVarChanged() {
+ varChanged = false;
+ }
+ const bool getSorted() const {
+ return sorted;
+ }
+ void setSorted() {
+ sorted = true;
+ }
+ void setUnsorted() {
+ sorted = false;
+ }
+ void subsume0Finished() {
+ subsume0Done = 1;
+ }
+ const bool subsume0IsFinished() {
+ return subsume0Done;
}
Lit& operator [] (uint32_t i) {
return extra.act;
}
- Lit subsumes (const Clause& other) const;
+ void makeNonLearnt() {
+ assert(isLearnt);
+ isLearnt = false;
+ calcAbstraction();
+ }
+
+ void makeLearnt(const uint32_t newActivity) {
+ extra.act = newActivity;
+ isLearnt = true;
+ }
- inline void strengthen(const Lit p)
+ inline void strengthen(const Lit p)
{
remove(*this, p);
+ sorted = false;
calcAbstraction();
}
void calcAbstraction() {
- uint32_t abstraction = 0;
+ extra.abst = 0;
for (uint32_t i = 0; i != size(); i++)
- abstraction |= 1 << (data[i].var() & 31);
- extra.abst = abstraction;
+ extra.abst |= 1 << (data[i].toInt() & 31);
+ }
+
+ uint32_t getAbst()
+ {
+ return extra.abst;
}
const Lit* getData () const {
Lit* getData () {
return data;
}
+ const Lit* getDataEnd () const {
+ return data+size();
+ }
+ Lit* getDataEnd () {
+ return data+size();
+ }
void print() {
- printf("Clause group: %d, size: %d, learnt:%d, lits: ", group, size(), learnt());
+ printf("Clause group: %d, size: %d, learnt:%d, lits: ", getGroup(), size(), learnt());
plainPrint();
}
void plainPrint(FILE* to = stdout) const {
}
fprintf(to, "0\n");
}
-protected:
- void setSize(uint32_t size) {
- size_etc = (size_etc & ((1 << 4)-1)) + (size << 4);
+ #ifdef STATS_NEEDED
+ const uint32_t getGroup() const
+ {
+ return group;
+ }
+ void setGroup(const uint32_t _group)
+ {
+ group = _group;
+ }
+ #else
+ const uint getGroup() const
+ {
+ return 0;
}
- void setLearnt(bool learnt) {
- size_etc = (size_etc & ~1) + learnt;
+ void setGroup(const uint32_t _group)
+ {
+ return;
}
+ #endif //STATS_NEEDED
};
class XorClause : public Clause
{
+
+#ifdef _MSC_VER
public:
+#else //_MSC_VER
+protected:
+#endif //_MSC_VER
+
// NOTE: This constructor cannot be used directly (doesn't allocate enough memory).
template<class V>
XorClause(const V& ps, const bool inverted, const uint _group) :
Clause(ps, _group, false)
{
- setInverted(inverted);
+ invertedXor = inverted;
+ isXorClause = true;
+ calcXorAbstraction();
}
+public:
+ #ifndef _MSC_VER
// -- use this function instead:
template<class V>
friend XorClause* XorClause_new(const V& ps, const bool inverted, const uint group);
+ #endif //_MSC_VER
inline bool xor_clause_inverted() const
{
- return size_etc & 8;
+ return invertedXor;
}
inline void invert(bool b)
{
- size_etc ^= (uint32_t)b << 3;
+ invertedXor ^= b;
+ }
+ void calcXorAbstraction() {
+ extra.abst = 0;
+ for (uint32_t i = 0; i != size(); i++)
+ extra.abst |= 1 << (data[i].var() & 31);
}
void print() {
- printf("XOR Clause group: %d, size: %d, learnt:%d, lits:\"", group, size(), learnt());
+ printf("XOR Clause group: %d, size: %d, learnt:%d, lits:\"", getGroup(), size(), learnt());
plainPrint();
}
}
friend class MatrixFinder;
-
-protected:
- inline void setInverted(bool inverted)
- {
- size_etc = (size_etc & 7) + ((uint32_t)inverted << 3) + (size_etc & ~15);
- }
};
+//extern boost::pool<> binaryClausePool;
+
template<class T>
Clause* Clause_new(const T& ps, const uint group, const bool learnt = false)
{
- void* mem = malloc(sizeof(Clause) + sizeof(Lit)*(ps.size()));
+ void* mem;
+ //if (ps.size() != 2)
+ mem = malloc(sizeof(Clause) + sizeof(Lit)*(ps.size()));
+ //else
+ // mem = binaryClausePool.malloc();
Clause* real= new (mem) Clause(ps, group, learnt);
return real;
}
return real;
}
+inline void clauseFree(Clause* c)
+{
+ //if (binaryClausePool.is_from(c)) binaryClausePool.free(c);
+ //else
+ free(c);
+}
+
/*_________________________________________________________________________________________________
|
| subsumes : (other : const Clause&) -> Lit
| lit_Undef - Clause subsumes 'other'
| p - The literal p can be deleted from 'other'
|________________________________________________________________________________________________@*/
-inline Lit Clause::subsumes(const Clause& other) const
+/*inline Lit Clause::subsumes(const Clause& other) const
{
if (other.size() < size() || (extra.abst & ~other.extra.abst) != 0)
return lit_Error;
}
return ret;
-}
+}*/
+//typedef sptr<Clause> ClausePtr;
+//typedef sptr<XorClause> XorClausePtr;
+typedef Clause* ClausePtr;
+typedef XorClause* XorClausePtr;
+#pragma pack(push)
+#pragma pack(1)
class WatchedBin {
public:
- WatchedBin(Clause *_clause, Lit _impliedLit) : impliedLit(_impliedLit), clause(_clause) {};
+ WatchedBin(Clause *_clause, Lit _impliedLit) : clause(_clause), impliedLit(_impliedLit) {};
+ ClausePtr clause;
Lit impliedLit;
- Clause *clause;
};
class Watched {
public:
- Watched(Clause *_clause, Lit _blockedLit) : blockedLit(_blockedLit), clause(_clause) {};
+ Watched(Clause *_clause, Lit _blockedLit) : clause(_clause), blockedLit(_blockedLit) {};
+ ClausePtr clause;
Lit blockedLit;
- Clause *clause;
};
+#pragma pack(pop)
-};
+}; //NAMESPACE MINISAT
#endif //CLAUSE_H
**************************************************************************************************/
#include "ClauseCleaner.h"
+#include "VarReplacer.h"
+
+#ifdef _MSC_VER
+#define __builtin_prefetch(a,b,c)
+#endif //_MSC_VER
+
+//#define DEBUG_CLEAN
namespace MINISAT
{
using namespace MINISAT;
-//#define DEBUG_CLEAN
-
ClauseCleaner::ClauseCleaner(Solver& _solver) :
solver(_solver)
{
- for (uint i = 0; i < 4; i++) {
+ for (uint i = 0; i < 6; i++) {
lastNumUnitarySat[i] = solver.get_unitary_learnts_num();
lastNumUnitaryClean[i] = solver.get_unitary_learnts_num();
}
if (lastNumUnitarySat[type] + limit >= solver.get_unitary_learnts_num())
return;
- int i,j;
- for (i = j = 0; i < cs.size(); i++) {
- if (satisfied(*cs[i]))
- solver.removeClause(*cs[i]);
+ Clause **i,**j, **end;
+ for (i = j = cs.getData(), end = i + cs.size(); i != end; i++) {
+ if (i+1 != end)
+ __builtin_prefetch(*(i+1), 0, 0);
+ if (satisfied(**i))
+ solver.removeClause(**i);
else
- cs[j++] = cs[i];
+ *j++ = *i;
}
cs.shrink_(i - j);
lastNumUnitarySat[type] = solver.get_unitary_learnts_num();
}
+void ClauseCleaner::cleanClauses(vec<Clause*>& cs, ClauseSetType type, const uint limit)
+{
+ assert(solver.decisionLevel() == 0);
+ assert(solver.qhead == solver.trail.size());
+
+ if (lastNumUnitaryClean[type] + limit >= solver.get_unitary_learnts_num())
+ return;
+
+ Clause **s, **ss, **end;
+ for (s = ss = cs.getData(), end = s + cs.size(); s != end;) {
+ if (s+1 != end)
+ __builtin_prefetch(*(s+1), 1, 0);
+ if (cleanClause(**s)) {
+ clauseFree(*s);
+ s++;
+ } else if (type != ClauseCleaner::binaryClauses && (*s)->size() == 2) {
+ solver.binaryClauses.push(*s);
+ solver.becameBinary++;
+ s++;
+ } else {
+ *ss++ = *s++;
+ }
+ }
+ cs.shrink(s-ss);
+
+ lastNumUnitaryClean[type] = solver.get_unitary_learnts_num();
+
+ #ifdef VERBOSE_DEBUG
+ cout << "cleanClauses(Clause) useful ?? Removed: " << s-ss << endl;
+ #endif
+}
+
inline const bool ClauseCleaner::cleanClause(Clause& c)
{
Lit origLit1 = c[0];
for (i = j = c.getData(), end = i + c.size(); i != end; i++) {
lbool val = solver.value(*i);
if (val == l_Undef) {
- *j = *i;
- j++;
+ *j++ = *i;
+ continue;
}
+
if (val == l_True) {
solver.detachModifiedClause(origLit1, origLit2, origSize, &c);
return true;
if ((c.size() > 2) && (c.size() - (i-j) == 2)) {
solver.detachModifiedClause(origLit1, origLit2, c.size(), &c);
c.shrink(i-j);
+ c.setStrenghtened();
solver.attachClause(c);
- } else {
+ } else if (i != j) {
+ c.setStrenghtened();
c.shrink(i-j);
if (c.learnt())
solver.learnts_literals -= i-j;
return false;
}
-void ClauseCleaner::cleanClauses(vec<Clause*>& cs, ClauseSetType type, const uint limit)
+void ClauseCleaner::cleanClauses(vec<XorClause*>& cs, ClauseSetType type, const uint limit)
{
- #ifdef DEBUG_CLEAN
assert(solver.decisionLevel() == 0);
- #endif
+ assert(solver.qhead == solver.trail.size());
if (lastNumUnitaryClean[type] + limit >= solver.get_unitary_learnts_num())
return;
- Clause **s, **ss, **end;
+ XorClause **s, **ss, **end;
for (s = ss = cs.getData(), end = s + cs.size(); s != end;) {
+ if (s+1 != end)
+ __builtin_prefetch(*(s+1), 1, 0);
if (cleanClause(**s)) {
- free(*s);
+ solver.freeLater.push(*s);
s++;
} else {
*ss++ = *s++;
lastNumUnitaryClean[type] = solver.get_unitary_learnts_num();
#ifdef VERBOSE_DEBUG
- cout << "cleanClauses(Clause) useful ?? Removed: " << s-ss << endl;
+ cout << "cleanClauses(XorClause) useful: ?? Removed: " << s-ss << endl;
#endif
}
-void ClauseCleaner::cleanClauses(vec<XorClause*>& cs, ClauseSetType type, const uint limit)
+inline const bool ClauseCleaner::cleanClause(XorClause& c)
+{
+ Lit *i, *j, *end;
+ Var origVar1 = c[0].var();
+ Var origVar2 = c[1].var();
+ uint32_t origSize = c.size();
+ for (i = j = c.getData(), end = i + c.size(); i != end; i++) {
+ const lbool& val = solver.assigns[i->var()];
+ if (val.isUndef()) {
+ *j = *i;
+ j++;
+ } else c.invert(val.getBool());
+ }
+ c.shrink(i-j);
+
+ switch (c.size()) {
+ case 0: {
+ solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
+ return true;
+ }
+ case 2: {
+ vec<Lit> ps(2);
+ ps[0] = c[0].unsign();
+ ps[1] = c[1].unsign();
+ solver.varReplacer->replace(ps, c.xor_clause_inverted(), c.getGroup());
+ solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
+ return true;
+ }
+ default:
+ if (i-j > 0) {
+ c.setStrenghtened();
+ solver.clauses_literals -= i-j;
+ }
+ return false;
+ }
+}
+
+void ClauseCleaner::cleanClausesBewareNULL(vec<ClauseSimp>& cs, ClauseCleaner::ClauseSetType type, Subsumer& subs, const uint limit)
{
- #ifdef DEBUG_CLEAN
assert(solver.decisionLevel() == 0);
- #endif
+ assert(solver.qhead == solver.trail.size());
if (lastNumUnitaryClean[type] + limit >= solver.get_unitary_learnts_num())
return;
- XorClause **s, **ss, **end;
- for (s = ss = cs.getData(), end = s + cs.size(); s != end;) {
- if (cleanClause(**s)) {
- (**s).mark(1);
- solver.freeLater.push(*s);
- s++;
+ ClauseSimp *s, *end;
+ for (s = cs.getData(), end = s + cs.size(); s != end; s++) {
+ if (s+1 != end)
+ __builtin_prefetch((s+1)->clause, 1, 0);
+ if (s->clause == NULL)
+ continue;
+
+ if (cleanClauseBewareNULL(*s, subs)) {
+ continue;
+ } else if (s->clause->size() == 2)
+ solver.becameBinary++;
+ }
+
+ lastNumUnitaryClean[type] = solver.get_unitary_learnts_num();
+}
+
+inline const bool ClauseCleaner::cleanClauseBewareNULL(ClauseSimp cc, Subsumer& subs)
+{
+ Clause& c = *cc.clause;
+ vec<Lit> origClause(c.size());
+ memcpy(origClause.getData(), c.getData(), sizeof(Lit)*c.size());
+
+ Lit *i, *j, *end;
+ for (i = j = c.getData(), end = i + c.size(); i != end; i++) {
+ lbool val = solver.value(*i);
+ if (val == l_Undef) {
+ *j++ = *i;
+ continue;
+ }
+
+ if (val == l_True) {
+ subs.unlinkModifiedClause(origClause, cc);
+ free(cc.clause);
+ return true;
+ }
+ }
+
+ if (i != j) {
+ c.setStrenghtened();
+ if (origClause.size() > 2 && origClause.size()-(i-j) == 2) {
+ subs.unlinkModifiedClause(origClause, cc);
+ subs.clauses[cc.index] = cc;
+ c.shrink(i-j);
+ solver.attachClause(c);
+ subs.linkInAlreadyClause(cc);
} else {
- *ss++ = *s++;
+ c.shrink(i-j);
+ subs.unlinkModifiedClauseNoDetachNoNULL(origClause, cc);
+ subs.linkInAlreadyClause(cc);
+ if (c.learnt())
+ solver.learnts_literals -= i-j;
+ else
+ solver.clauses_literals -= i-j;
}
+ c.calcAbstraction();
+ subs.updateClause(cc);
}
- cs.shrink(s-ss);
- lastNumUnitaryClean[type] = solver.get_unitary_learnts_num();
+ return false;
+}
+
+void ClauseCleaner::cleanXorClausesBewareNULL(vec<XorClauseSimp>& cs, ClauseCleaner::ClauseSetType type, XorSubsumer& subs, const uint limit)
+{
+ assert(solver.decisionLevel() == 0);
+ assert(solver.qhead == solver.trail.size());
- #ifdef VERBOSE_DEBUG
- cout << "cleanClauses(XorClause) useful: ?? Removed: " << s-ss << endl;
- #endif
+ if (lastNumUnitaryClean[type] + limit >= solver.get_unitary_learnts_num())
+ return;
+
+ XorClauseSimp *s, *end;
+ for (s = cs.getData(), end = s + cs.size(); s != end; s++) {
+ if (s+1 != end)
+ __builtin_prefetch((s+1)->clause, 1, 0);
+ if (s->clause == NULL)
+ continue;
+
+ cleanXorClauseBewareNULL(*s, subs);
+ }
+
+ lastNumUnitaryClean[type] = solver.get_unitary_learnts_num();
}
-inline const bool ClauseCleaner::cleanClause(XorClause& c)
+inline const bool ClauseCleaner::cleanXorClauseBewareNULL(XorClauseSimp cc, XorSubsumer& subs)
{
+ XorClause& c = *cc.clause;
+ vec<Lit> origClause(c.size());
+ memcpy(origClause.getData(), c.getData(), sizeof(Lit)*c.size());
+
Lit *i, *j, *end;
- Var origVar1 = c[0].var();
- Var origVar2 = c[1].var();
- uint32_t origSize = c.size();
for (i = j = c.getData(), end = i + c.size(); i != end; i++) {
const lbool& val = solver.assigns[i->var()];
if (val.isUndef()) {
}
c.shrink(i-j);
- switch (c.size()) {
+ switch(c.size()) {
case 0: {
- solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
+ subs.unlinkModifiedClause(origClause, cc);
+ free(cc.clause);
return true;
}
case 2: {
vec<Lit> ps(2);
ps[0] = c[0].unsign();
ps[1] = c[1].unsign();
- solver.varReplacer->replace(ps, c.xor_clause_inverted(), c.group);
- solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
+ solver.varReplacer->replace(ps, c.xor_clause_inverted(), c.getGroup());
+ subs.unlinkModifiedClause(origClause, cc);
+ free(cc.clause);
return true;
}
default:
- solver.clauses_literals -= i-j;
- return false;
+ if (i-j > 0) {
+ subs.unlinkModifiedClauseNoDetachNoNULL(origClause, cc);
+ subs.linkInAlreadyClause(cc);
+ c.calcXorAbstraction();
+ }
}
+
+ return false;
}
bool ClauseCleaner::satisfied(const Clause& c) const
return final;
}
-};
+}; //NAMESPACE MINISAT
#ifndef CLAUSECLEANER_H
#define CLAUSECLEANER_H
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
#include "Solver.h"
+#include "Subsumer.h"
+#include "XorSubsumer.h"
namespace MINISAT
{
+using namespace MINISAT;
class ClauseCleaner
{
public:
ClauseCleaner(Solver& solver);
- enum ClauseSetType {clauses, xorclauses, learnts, conglomerate};
+ enum ClauseSetType {clauses, xorclauses, learnts, binaryClauses, simpClauses, xorSimpClauses};
void cleanClauses(vec<Clause*>& cs, ClauseSetType type, const uint limit = 0);
+ void cleanClausesBewareNULL(vec<ClauseSimp>& cs, ClauseSetType type, Subsumer& subs, const uint limit = 0);
+ void cleanXorClausesBewareNULL(vec<XorClauseSimp>& cs, ClauseSetType type, XorSubsumer& subs, const uint limit = 0);
+ const bool cleanClauseBewareNULL(ClauseSimp c, Subsumer& subs);
+ const bool cleanXorClauseBewareNULL(XorClauseSimp c, XorSubsumer& subs);
+
void cleanClauses(vec<XorClause*>& cs, ClauseSetType type, const uint limit = 0);
void removeSatisfied(vec<Clause*>& cs, ClauseSetType type, const uint limit = 0);
void removeSatisfied(vec<XorClause*>& cs, ClauseSetType type, const uint limit = 0);
- void removeAndCleanAll();
+ void removeAndCleanAll(const bool nolimit = false);
bool satisfied(const Clause& c) const;
bool satisfied(const XorClause& c) const;
private:
- const bool cleanClause(Clause& c);
const bool cleanClause(XorClause& c);
+ const bool cleanClause(Clause& c);
- uint lastNumUnitarySat[4];
- uint lastNumUnitaryClean[4];
+ uint lastNumUnitarySat[6];
+ uint lastNumUnitaryClean[6];
Solver& solver;
};
-inline void ClauseCleaner::removeAndCleanAll()
+inline void ClauseCleaner::removeAndCleanAll(const bool nolimit)
{
+ //uint limit = std::min((uint)((double)solver.order_heap.size() * PERCENTAGECLEANCLAUSES), FIXCLEANREPLACE);
uint limit = (double)solver.order_heap.size() * PERCENTAGECLEANCLAUSES;
+ if (nolimit) limit = 0;
+ removeSatisfied(solver.binaryClauses, ClauseCleaner::binaryClauses, limit);
cleanClauses(solver.clauses, ClauseCleaner::clauses, limit);
cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses, limit);
cleanClauses(solver.learnts, ClauseCleaner::learnts, limit);
}
+}; //NAMESPACE MINISAT
-};
#endif //CLAUSECLEANER_H
**************************************************************************************************/
#include "Conglomerate.h"
-#include "Solver.h"
#include "VarReplacer.h"
#include "ClauseCleaner.h"
#include <utility>
#include <algorithm>
+#include <cstring>
+#include "time_mem.h"
+#include <iomanip>
using std::make_pair;
//#define VERBOSE_DEBUG
using std::endl;
#endif
-
namespace MINISAT
{
using namespace MINISAT;
-Conglomerate::Conglomerate(Solver *_s) :
- S(_s)
+Conglomerate::Conglomerate(Solver& _solver) :
+ found(0)
+ , solver(_solver)
{}
Conglomerate::~Conglomerate()
free(calcAtFinish[i]);
}
-const vector<bool>& Conglomerate::getRemovedVars() const
-{
- return removedVars;
-}
-
-const vec<XorClause*>& Conglomerate::getCalcAtFinish() const
-{
- return calcAtFinish;
-}
-
-vec<XorClause*>& Conglomerate::getCalcAtFinish()
+void Conglomerate::blockVars()
{
- return calcAtFinish;
-}
-
-void Conglomerate::fillVarToXor()
-{
- blocked.clear();
- varToXor.clear();
-
- blocked.resize(S->nVars(), false);
- for (Clause *const*it = S->clauses.getData(), *const*end = it + S->clauses.size(); it != end; it++) {
+ for (Clause *const*it = solver.clauses.getData(), *const*end = it + solver.clauses.size(); it != end; it++) {
const Clause& c = **it;
for (const Lit* a = &c[0], *end = a + c.size(); a != end; a++) {
blocked[a->var()] = true;
}
}
- for (Lit* it = &(S->trail[0]), *end = it + S->trail.size(); it != end; it++)
+ for (Clause *const*it = solver.binaryClauses.getData(), *const*end = it + solver.binaryClauses.size(); it != end; it++) {
+ const Clause& c = **it;
+ blocked[c[0].var()] = true;
+ blocked[c[1].var()] = true;
+ }
+
+ for (Lit* it = &(solver.trail[0]), *end = it + solver.trail.size(); it != end; it++)
blocked[it->var()] = true;
- const vec<Clause*>& clauses = S->varReplacer->getClauses();
+ const vec<Clause*>& clauses = solver.varReplacer->getClauses();
for (Clause *const*it = clauses.getData(), *const*end = it + clauses.size(); it != end; it++) {
const Clause& c = **it;
for (const Lit* a = &c[0], *end = a + c.size(); a != end; a++) {
blocked[a->var()] = true;
}
}
+}
+
+void Conglomerate::fillVarToXor()
+{
+ varToXor.clear();
uint i = 0;
- for (XorClause* const* it = S->xorclauses.getData(), *const*end = it + S->xorclauses.size(); it != end; it++, i++) {
+ for (XorClause* const* it = solver.xorclauses.getData(), *const*end = it + solver.xorclauses.size(); it != end; it++, i++) {
const XorClause& c = **it;
for (const Lit * a = &c[0], *end = a + c.size(); a != end; a++) {
if (!blocked[a->var()])
}
}
-void Conglomerate::process_clause(XorClause& x, const uint num, Var remove_var, vec<Lit>& vars) {
+void Conglomerate::removeVar(const Var var)
+{
+ solver.setDecisionVar(var, false);
+ solver.activity[var] = 0.0;
+ solver.order_heap.update(var);
+ removedVars[var] = true;
+ found++;
+}
+
+void Conglomerate::processClause(XorClause& x, uint32_t num, Var remove_var)
+{
for (const Lit* a = &x[0], *end = a + x.size(); a != end; a++) {
Var var = a->var();
if (var != remove_var) {
- vars.push(Lit(var, false));
varToXorMap::iterator finder = varToXor.find(var);
if (finder != varToXor.end()) {
- vector<pair<XorClause*, uint> >::iterator it =
- std::find(finder->second.begin(), finder->second.end(), make_pair(&x, num));
+ vector<pair<XorClause*, uint32_t> >::iterator it =
+ std::find(finder->second.begin(), finder->second.end(), make_pair(&x, num));
finder->second.erase(it);
}
}
}
}
-uint Conglomerate::conglomerateXors()
+const bool Conglomerate::heuleProcessFull()
{
- if (S->xorclauses.size() == 0)
- return 0;
+ #ifdef VERBOSE_DEBUG
+ cout << "Heule XOR-ing started" << endl;
+ #endif
+
+ double time = cpuTime();
+ found = 0;
+ uint oldToReplaceVars = solver.varReplacer->getNewToReplaceVars();
+ solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses);
+ if (solver.ok == false)
+ return false;
+
+ toRemove.clear();
+ toRemove.resize(solver.xorclauses.size(), false);
+ blocked.clear();
+ blocked.resize(solver.nVars(), false);
+ fillVarToXor();
+ if (!heuleProcess())
+ goto end;
+
+ if (solver.verbosity >=1) {
+ std::cout << "c | Heule-processings XORs:" << std::setw(8) << std::setprecision(2) << std::fixed << cpuTime()-time
+ << " Found smaller XOR-s: " << std::setw(6) << found
+ << " New bin anti/eq-s: " << std::setw(3) << solver.varReplacer->getNewToReplaceVars() - oldToReplaceVars
+ << std::setw(0) << " |" << std::endl;
+ }
+
+end:
+
+ clearToRemove();
+ return solver.ok;
+}
+
+const bool Conglomerate::conglomerateXorsFull()
+{
#ifdef VERBOSE_DEBUG
cout << "Finding conglomerate xors started" << endl;
#endif
- S->clauseCleaner->cleanClauses(S->xorclauses, ClauseCleaner::xorclauses);
+ double time = cpuTime();
+ found = 0;
+ uint32_t origNumClauses = solver.xorclauses.size();
- toRemove.clear();
- toRemove.resize(S->xorclauses.size(), false);
+ solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses);
+ if (solver.ok == false)
+ return false;
+ toRemove.clear();
+ toRemove.resize(solver.xorclauses.size(), false);
+ blocked.clear();
+ blocked.resize(solver.nVars(), false);
+ blockVars();
fillVarToXor();
+ if (conglomerateXors() == false)
+ goto end;
+
+end:
+
+ clearToRemove();
+ assert(origNumClauses >= solver.xorclauses.size());
+ if (solver.verbosity >=1) {
+ std::cout << "c | Conglomerating XORs:" << std::setw(8) << std::setprecision(2) << std::fixed << cpuTime()-time << " s "
+ << " removed " << std::setw(8) << found << " vars"
+ << " removed " << std::setw(8) << origNumClauses-solver.xorclauses.size() << " clauses"
+ << std::setw(0) << " |" << std::endl;
+ }
+
+ clearLearntsFromToRemove();
+ solver.order_heap.filter(Solver::VarFilter(solver));
+
+ return solver.ok;
+}
+
+void Conglomerate::fillNewSet(vector<vector<Lit> >& newSet, vector<pair<XorClause*, uint32_t> >& clauseSet) const
+{
+ newSet.clear();
+ newSet.resize(clauseSet.size());
- uint found = 0;
+ XorClause& firstXorClause = *(clauseSet[0].first);
+ newSet[0].resize(firstXorClause.size());
+ memcpy(&newSet[0][0], firstXorClause.getData(), sizeof(Lit)*firstXorClause.size());
+
+ for (uint i = 1; i < clauseSet.size(); i++) {
+ XorClause& thisXorClause = *clauseSet[i].first;
+ newSet[i] = newSet[0];
+ newSet[i].resize(firstXorClause.size()+thisXorClause.size());
+ memcpy(&newSet[i][firstXorClause.size()], thisXorClause.getData(), sizeof(Lit)*thisXorClause.size());
+ clearDouble(newSet[i]);
+ }
+}
+
+const bool Conglomerate::heuleProcess()
+{
+ vector<vector<Lit> > newSet;
+ while(varToXor.begin() != varToXor.end()) {
+ varToXorMap::iterator it = varToXor.begin();
+ vector<pair<XorClause*, uint32_t> >& clauseSet = it->second;
+ const Var var = it->first;
+
+ if (blocked[var] || clauseSet.size() == 1) {
+ varToXor.erase(it);
+ blocked[var] = true;
+ continue;
+ }
+ blocked[var] = true;
+
+ std::sort(clauseSet.begin(), clauseSet.end(), ClauseSetSorter());
+ fillNewSet(newSet, clauseSet);
+
+ for (uint i = 1; i < newSet.size(); i++) if (newSet[i].size() <= 2) {
+ found++;
+ XorClause& thisXorClause = *clauseSet[i].first;
+ const bool inverted = !clauseSet[0].first->xor_clause_inverted() ^ thisXorClause.xor_clause_inverted();
+ const uint old_group = thisXorClause.getGroup();
+
+ #ifdef VERBOSE_DEBUG
+ cout << "- XOR1:";
+ clauseSet[0].first->plainPrint();
+ cout << "- XOR2:";
+ thisXorClause.plainPrint();
+ #endif
+
+ if (!dealWithNewClause(newSet[i], inverted, old_group))
+ return false;
+ assert(newSet.size() == clauseSet.size());
+ }
+
+ varToXor.erase(it);
+ }
+
+ return (solver.ok = (solver.propagate() == NULL));
+}
+
+const bool Conglomerate::conglomerateXors()
+{
+ vector<vector<Lit> > newSet;
while(varToXor.begin() != varToXor.end()) {
varToXorMap::iterator it = varToXor.begin();
- const vector<pair<XorClause*, uint> >& c = it->second;
- const uint& var = it->first;
+ vector<pair<XorClause*, uint32_t> >& clauseSet = it->second;
+ const Var var = it->first;
//We blocked the var during dealWithNewClause (it was in a 2-long xor-clause)
if (blocked[var]) {
continue;
}
- S->setDecisionVar(var, false);
- removedVars[var] = true;
-
- if (c.size() == 0) {
+ if (clauseSet.size() == 0) {
+ removeVar(var);
varToXor.erase(it);
continue;
}
- #ifdef VERBOSE_DEBUG
- cout << "--- New conglomerate set ---" << endl;
- #endif
+ std::sort(clauseSet.begin(), clauseSet.end(), ClauseSetSorter());
+ fillNewSet(newSet, clauseSet);
+
+ int diff = 0;
+ for (size_t i = 1; i < newSet.size(); i++)
+ diff += (int)newSet[i].size()-(int)clauseSet[i].first->size();
+
+ if (newSet.size() > 2) {
+ blocked[var] = true;
+ varToXor.erase(it);
+ continue;
+ }
- XorClause& x = *(c[0].first);
- bool first_inverted = !x.xor_clause_inverted();
- vec<Lit> first_vars;
- process_clause(x, c[0].second, var, first_vars);
+ XorClause& firstXorClause = *(clauseSet[0].first);
+ bool first_inverted = !firstXorClause.xor_clause_inverted();
+ removeVar(var);
#ifdef VERBOSE_DEBUG
+ cout << "--- New conglomerate set ---" << endl;
cout << "- Removing: ";
- x.plainPrint();
+ firstXorClause.plainPrint();
cout << "Adding var " << var+1 << " to calcAtFinish" << endl;
#endif
- assert(!toRemove[c[0].second]);
- toRemove[c[0].second] = true;
- S->detachClause(x);
- calcAtFinish.push(&x);
- found++;
+ assert(!toRemove[clauseSet[0].second]);
+ toRemove[clauseSet[0].second] = true;
+ processClause(firstXorClause, clauseSet[0].second, var);
+ solver.detachClause(firstXorClause);
+ calcAtFinish.push(&firstXorClause);
- for (uint i = 1; i < c.size(); i++) {
- vec<Lit> ps(first_vars.size());
- memcpy(ps.getData(), first_vars.getData(), sizeof(Lit)*first_vars.size());
- XorClause& x = *c[i].first;
- process_clause(x, c[i].second, var, ps);
-
+ for (uint i = 1; i < clauseSet.size(); i++) {
+ XorClause& thisXorClause = *clauseSet[i].first;
#ifdef VERBOSE_DEBUG
cout << "- Removing: ";
- x.plainPrint();
+ thisXorClause.plainPrint();
#endif
- const uint old_group = x.group;
- bool inverted = first_inverted ^ x.xor_clause_inverted();
- assert(!toRemove[c[i].second]);
- toRemove[c[i].second] = true;
- S->removeClause(x);
- found++;
- clearDouble(ps);
+ const uint old_group = thisXorClause.getGroup();
+ const bool inverted = first_inverted ^ thisXorClause.xor_clause_inverted();
+ assert(!toRemove[clauseSet[i].second]);
+ toRemove[clauseSet[i].second] = true;
+ processClause(thisXorClause, clauseSet[i].second, var);
+ solver.removeClause(thisXorClause);
- if (!dealWithNewClause(ps, inverted, old_group)) {
- clearToRemove();
- S->ok = false;
- return found;
- }
+ if (!dealWithNewClause(newSet[i], inverted, old_group))
+ return false;
+ assert(newSet.size() == clauseSet.size());
}
varToXor.erase(it);
}
- clearToRemove();
-
- if (S->ok != false)
- S->ok = (S->propagate() == NULL);
-
- return found;
+ return (solver.ok = (solver.propagate() == NULL));
}
-bool Conglomerate::dealWithNewClause(vec<Lit>& ps, const bool inverted, const uint old_group)
+bool Conglomerate::dealWithNewClause(vector<Lit>& ps, const bool inverted, const uint old_group)
{
switch(ps.size()) {
case 0: {
cout << "--> xor is 0-long" << endl;
#endif
- if (!inverted)
+ if (!inverted) {
+ solver.ok = false;
return false;
+ }
break;
}
case 1: {
cout << "--> xor is 1-long, attempting to set variable " << ps[0].var()+1 << endl;
#endif
- if (S->assigns[ps[0].var()] == l_Undef) {
- assert(S->decisionLevel() == 0);
+ if (solver.assigns[ps[0].var()] == l_Undef) {
+ assert(solver.decisionLevel() == 0);
blocked[ps[0].var()] = true;
- S->uncheckedEnqueue(Lit(ps[0].var(), inverted));
- } else if (S->assigns[ps[0].var()] != boolToLBool(!inverted)) {
+ solver.uncheckedEnqueue(Lit(ps[0].var(), inverted));
+ } else if (solver.assigns[ps[0].var()] != boolToLBool(!inverted)) {
#ifdef VERBOSE_DEBUG
cout << "Conflict. Aborting.";
#endif
+ solver.ok = false;
return false;
+ } else {
+ #ifdef VERBOSE_DEBUG
+ cout << "Variable already set to correct value";
+ #endif
}
break;
}
case 2: {
#ifdef VERBOSE_DEBUG
- cout << "--> xor is 2-long, must later replace variable, adding var " << ps[0].var() + 1 << " to calcAtFinish:" << endl;
+ cout << "--> xor is 2-long, must later replace variable" << endl;
XorClause* newX = XorClause_new(ps, inverted, old_group);
newX->plainPrint();
free(newX);
#endif
- S->varReplacer->replace(ps, inverted, old_group);
+ vec<Lit> tmpPS(2);
+ tmpPS[0] = ps[0];
+ tmpPS[1] = ps[1];
+ if (solver.varReplacer->replace(tmpPS, inverted, old_group) == false)
+ return false;
blocked[ps[0].var()] = true;
blocked[ps[1].var()] = true;
break;
newX->plainPrint();
#endif
- S->xorclauses.push(newX);
+ solver.xorclauses.push(newX);
toRemove.push_back(false);
- S->attachClause(*newX);
+ solver.attachClause(*newX);
for (const Lit * a = &((*newX)[0]), *end = a + newX->size(); a != end; a++) {
if (!blocked[a->var()])
- varToXor[a->var()].push_back(make_pair(newX, toRemove.size()-1));
+ varToXor[a->var()].push_back(make_pair(newX, (uint32_t)(toRemove.size()-1)));
}
break;
}
return true;
}
-void Conglomerate::clearDouble(vec<Lit>& ps) const
-{
- std::sort(ps.getData(), ps.getData() + ps.size());
+void Conglomerate::clearDouble(vector<Lit>& ps) const
+{
+ std::sort(ps.begin(), ps.end());
Lit p;
- uint i, j;
- for (i = j = 0, p = lit_Undef; i < ps.size(); i++) {
+ uint32_t i, j;
+ for (i = j = 0, p = lit_Undef; i != ps.size(); i++) {
+ ps[i] = ps[i].unsign();
if (ps[i] == p) {
//added, but easily removed
j--;
p = lit_Undef;
- } else //just add
+ } else
ps[j++] = p = ps[i];
}
- ps.shrink(i - j);
+ ps.resize(ps.size() - (i - j));
}
void Conglomerate::clearToRemove()
{
- assert(toRemove.size() == S->xorclauses.size());
+ assert(toRemove.size() == solver.xorclauses.size());
- XorClause **a = S->xorclauses.getData();
+ XorClause **a = solver.xorclauses.getData();
XorClause **r = a;
- XorClause **end = a + S->xorclauses.size();
+ XorClause **end = a + solver.xorclauses.size();
for (uint i = 0; r != end; i++) {
if (!toRemove[i])
*a++ = *r++;
else {
- (**a).mark(1);
r++;
}
}
- S->xorclauses.shrink(r-a);
-
- clearLearntsFromToRemove();
+ solver.xorclauses.shrink(r-a);
}
void Conglomerate::clearLearntsFromToRemove()
{
- Clause **a = S->learnts.getData();
+ Clause **a = solver.learnts.getData();
Clause **r = a;
- Clause **end = a + S->learnts.size();
+ Clause **end = a + solver.learnts.size();
for (; r != end;) {
const Clause& c = **r;
bool inside = false;
- if (!S->locked(c)) {
+ if (!solver.locked(c)) {
for (uint i = 0; i < c.size(); i++) {
if (removedVars[c[i].var()]) {
inside = true;
if (!inside)
*a++ = *r++;
else {
- S->removeClause(**r);
+ solver.removeClause(**r);
r++;
}
}
- S->learnts.shrink(r-a);
+ solver.learnts.shrink(r-a);
}
void Conglomerate::doCalcAtFinish()
bool final = c.xor_clause_inverted();
for (int k = 0, size = c.size(); k < size; k++ ) {
- const lbool& val = S->assigns[c[k].var()];
+ const lbool& val = solver.assigns[c[k].var()];
if (val == l_Undef)
toAssign.push_back(c[k].var());
else
if (toAssign.size() == 0) {
cout << "ERROR: toAssign.size() == 0 !!" << endl;
for (int k = 0, size = c.size(); k < size; k++ ) {
- cout << "Var: " << c[k].var() + 1 << " Level: " << S->level[c[k].var()] << endl;
+ cout << "Var: " << c[k].var() + 1 << " Level: " << solver.level[c[k].var()] << endl;
}
}
if (toAssign.size() > 1) {
assert(toAssign.size() > 0);
for (uint i = 1; i < toAssign.size(); i++) {
- S->uncheckedEnqueue(Lit(toAssign[i], true), &c);
+ solver.uncheckedEnqueue(Lit(toAssign[i], true), &c);
}
- S->uncheckedEnqueue(Lit(toAssign[0], final), &c);
- assert(S->clauseCleaner->satisfied(c));
+ solver.uncheckedEnqueue(Lit(toAssign[0], final), &c);
+ assert(solver.clauseCleaner->satisfied(c));
}
}
-void Conglomerate::addRemovedClauses()
+const bool Conglomerate::addRemovedClauses()
{
#ifdef VERBOSE_DEBUG
cout << "Executing addRemovedClauses" << endl;
for(uint i2 = 0; i2 != c.size() ; i2++) {
ps.push(Lit(c[i2].var(), false));
}
- S->addXorClause(ps, c.xor_clause_inverted(), c.group, tmp, true);
+ if (!solver.addXorClause(ps, c.xor_clause_inverted(), c.getGroup(), tmp))
+ return false;
free(&c);
}
calcAtFinish.clear();
for (uint i = 0; i < removedVars.size(); i++) {
if (removedVars[i]) {
removedVars[i] = false;
- S->setDecisionVar(i, true);
+ solver.setDecisionVar(i, true);
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Inserting Var " << i+1 << " back into the order_heap" << std::endl;
+ #endif //VERBOSE_DEBUG
}
}
+
+ return true;
}
void Conglomerate::newVar()
removedVars.resize(removedVars.size()+1, false);
}
-};
+}; //NAMESPACE MINISAT
#include <vector>
#include <map>
#include <set>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
#include "Clause.h"
#include "VarReplacer.h"
+#include "Solver.h"
using std::vector;
using std::pair;
using std::map;
using std::set;
-class Solver;
-
namespace MINISAT
{
using namespace MINISAT;
+class Solver;
+
class Conglomerate
{
public:
- Conglomerate(Solver *S);
+ Conglomerate(Solver& solver);
~Conglomerate();
- uint conglomerateXors(); ///<Conglomerate XOR-s that are attached using a variable
- void addRemovedClauses(); ///<Add clauses that have been removed. Used if solve() is called multiple times
+ const bool conglomerateXorsFull();
+ const bool heuleProcessFull();
+ const bool addRemovedClauses(); ///<Add clauses that have been removed. Used if solve() is called multiple times
void doCalcAtFinish(); ///<Calculate variables removed during conglomeration
+
const vec<XorClause*>& getCalcAtFinish() const;
vec<XorClause*>& getCalcAtFinish();
const vector<bool>& getRemovedVars() const;
+
void newVar();
private:
- void process_clause(XorClause& x, const uint num, Var remove_var, vec<Lit>& vars);
+ struct ClauseSetSorter {
+ bool operator () (const pair<XorClause*, uint32_t>& a, const pair<XorClause*, uint32_t>& b) {
+ return a.first->size() < b.first->size();
+ }
+ };
+
+ const bool conglomerateXors();
+ const bool heuleProcess();
+
+ void fillNewSet(vector<vector<Lit> >& newSet, vector<pair<XorClause*, uint32_t> >& clauseSet) const;
+
+ void removeVar(const Var var);
+ void processClause(XorClause& x, uint32_t num, Var remove_var);
+ void blockVars();
void fillVarToXor();
- void clearDouble(vec<Lit>& ps) const;
+ void clearDouble(vector<Lit>& ps) const;
void clearToRemove();
void clearLearntsFromToRemove();
- bool dealWithNewClause(vec<Lit>& ps, const bool inverted, const uint old_group);
+ bool dealWithNewClause(vector<Lit>& ps, const bool inverted, const uint old_group);
- typedef map<uint, vector<pair<XorClause*, uint> > > varToXorMap;
+ typedef map<uint, vector<pair<XorClause*, uint32_t> > > varToXorMap;
varToXorMap varToXor;
vector<bool> blocked;
vector<bool> toRemove;
vector<bool> removedVars;
vec<XorClause*> calcAtFinish;
+ uint found;
- Solver* S;
-};
+ Solver& solver;
};
+inline const vector<bool>& Conglomerate::getRemovedVars() const
+{
+ return removedVars;
+}
+
+inline const vec<XorClause*>& Conglomerate::getCalcAtFinish() const
+{
+ return calcAtFinish;
+}
+
+inline vec<XorClause*>& Conglomerate::getCalcAtFinish()
+{
+ return calcAtFinish;
+}
+
+}; //NAMESPACE MINISAT
+
#endif //CONGLOMERATE_H
--- /dev/null
+/***********************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************************************/
+
+#ifndef DOUBLEPACKEDROW_H
+#define DOUBLEPACKEDROW_H
+
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include <stdlib.h>
+
+#include "SolverTypes.h"
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+class DoublePackedRow
+{
+ private:
+ class BitIter {
+ public:
+ inline void operator=(const lbool toSet)
+ {
+ val &= ~((unsigned char)3 << offset);
+ val |= toSet.value << offset;
+ }
+
+ inline operator lbool() const
+ {
+ return lbool((val >> offset) & 3);
+ }
+
+ inline const bool isUndef() const {
+ return ((lbool)*this).isUndef();
+ }
+ inline const bool isDef() const {
+ return ((lbool)*this).isDef();
+ }
+ inline const bool getBool() const {
+ return ((lbool)*this).getBool();
+ }
+ inline const bool operator==(lbool b) const {
+ return ((lbool)*this) == b;
+ }
+ inline const bool operator!=(lbool b) const {
+ return ((lbool)*this) != b;
+ }
+ const lbool operator^(const bool b) const {
+ return ((lbool)*this) ^ b;
+ }
+
+ private:
+ friend class DoublePackedRow;
+ inline BitIter(unsigned char& mp, const uint32_t _offset) :
+ val(mp)
+ , offset(_offset)
+ {}
+
+ unsigned char& val;
+ const uint32_t offset;
+ };
+
+ class BitIterConst {
+ public:
+ inline operator lbool() const
+ {
+ return lbool((val >> offset) & 3);
+ }
+
+ inline const bool isUndef() const {
+ return ((lbool)*this).isUndef();
+ }
+ inline const bool isDef() const {
+ return ((lbool)*this).isDef();
+ }
+ inline const bool getBool() const {
+ return ((lbool)*this).getBool();
+ }
+ inline const bool operator==(lbool b) const {
+ return ((lbool)*this) == b;
+ }
+ inline const bool operator!=(lbool b) const {
+ return ((lbool)*this) != b;
+ }
+ const lbool operator^(const bool b) const {
+ return ((lbool)*this) ^ b;
+ }
+
+
+ private:
+ friend class DoublePackedRow;
+ inline BitIterConst(unsigned char& mp, const uint32_t _offset) :
+ val(mp)
+ , offset(_offset)
+ {}
+
+ const unsigned char& val;
+ const uint32_t offset;
+ };
+
+ public:
+ DoublePackedRow() :
+ numElems(0)
+ , mp(NULL)
+ {}
+
+ uint32_t size() const
+ {
+ return numElems;
+ }
+
+ void growTo(const uint32_t newNumElems)
+ {
+ uint32_t oldSize = numElems/4 + (bool)(numElems % 4);
+ uint32_t newSize = newNumElems/4 + (bool)(newNumElems % 4);
+
+ if (oldSize >= newSize) {
+ numElems = std::max(newNumElems, numElems);
+ return;
+ }
+
+ mp = (unsigned char*)realloc(mp, newSize*sizeof(unsigned char));
+ numElems = newNumElems;
+ }
+
+ inline BitIter operator[](const uint32_t at)
+ {
+ return BitIter(mp[at/4], (at%4)*2);
+ }
+
+ inline const BitIterConst operator[](const uint32_t at) const
+ {
+ return BitIterConst(mp[at/4], (at%4)*2);
+ }
+
+ inline void push(const lbool val)
+ {
+ growTo(numElems+1);
+ (*this)[numElems-1] = val;
+ }
+
+ /*void clear(const uint32_t at)
+ {
+ mp[at/32] &= ~((uint64_t)3 << ((at%32)*2));
+ }*/
+
+ private:
+
+ Var numElems;
+ unsigned char *mp;
+};
+
+}; //NAMESPACE MINISAT
+
+#endif //DOUBLEPACKEDROW_H
--- /dev/null
+/***********************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************************************/
+
+#include "FailedVarSearcher.h"
+
+#include <iomanip>
+#include <utility>
+#include <set>
+using std::make_pair;
+using std::set;
+
+#include "Solver.h"
+#include "ClauseCleaner.h"
+#include "time_mem.h"
+#include "VarReplacer.h"
+
+//#define FINDBINARYXOR
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+FailedVarSearcher::FailedVarSearcher(Solver& _solver):
+ solver(_solver)
+ , finishedLastTime(true)
+ , lastTimeWentUntil(0)
+ , numPropsMultiplier(1.0)
+ , lastTimeFoundTruths(0)
+{
+}
+
+void FailedVarSearcher::addFromSolver(const vec< XorClause* >& cs)
+{
+ xorClauseSizes.clear();
+ xorClauseSizes.growTo(cs.size());
+ occur.resize(solver.nVars());
+ for (Var var = 0; var < solver.nVars(); var++) {
+ occur[var].clear();
+ }
+
+ uint32_t i = 0;
+ for (XorClause * const*it = cs.getData(), * const*end = it + cs.size(); it != end; it++, i++) {
+ if (it+1 != end)
+ __builtin_prefetch(*(it+1), 1, 1);
+
+ const XorClause& cl = **it;
+ xorClauseSizes[i] = cl.size();
+ for (const Lit *l = cl.getData(), *end2 = l + cl.size(); l != end2; l++) {
+ occur[l->var()].push_back(i);
+ }
+ }
+}
+
+inline void FailedVarSearcher::removeVarFromXors(const Var var)
+{
+ vector<uint32_t>& occ = occur[var];
+ if (occ.empty()) return;
+
+ for (uint32_t *it = &occ[0], *end = it + occ.size(); it != end; it++) {
+ xorClauseSizes[*it]--;
+ if (!xorClauseTouched[*it]) {
+ xorClauseTouched.setBit(*it);
+ investigateXor.push(*it);
+ }
+ }
+}
+
+inline void FailedVarSearcher::addVarFromXors(const Var var)
+{
+ vector<uint32_t>& occ = occur[var];
+ if (occ.empty()) return;
+
+ for (uint32_t *it = &occ[0], *end = it + occ.size(); it != end; it++) {
+ xorClauseSizes[*it]++;
+ }
+}
+
+const TwoLongXor FailedVarSearcher::getTwoLongXor(const XorClause& c)
+{
+ TwoLongXor tmp;
+ uint32_t num = 0;
+ tmp.inverted = c.xor_clause_inverted();
+
+ for(const Lit *l = c.getData(), *end = l + c.size(); l != end; l++) {
+ if (solver.assigns[l->var()] == l_Undef) {
+ assert(num < 2);
+ tmp.var[num] = l->var();
+ num++;
+ } else {
+ tmp.inverted ^= (solver.assigns[l->var()] == l_True);
+ }
+ }
+
+ std::sort(&tmp.var[0], &tmp.var[0]+2);
+ assert(num == 2);
+ return tmp;
+}
+
+const bool FailedVarSearcher::search(uint64_t numProps)
+{
+ assert(solver.decisionLevel() == 0);
+
+ //Saving Solver state
+ Heap<Solver::VarOrderLt> backup_order_heap(solver.order_heap);
+ vector<bool> backup_polarities = solver.polarity;
+ vec<double> backup_activity;
+ backup_activity.growTo(solver.activity.size());
+ std::copy(solver.activity.getData(), solver.activity.getDataEnd(), backup_activity.getData());
+ double backup_var_inc = solver.var_inc;
+ uint32_t origHeapSize = solver.order_heap.size();
+
+ //General Stats
+ double time = cpuTime();
+ uint32_t numFailed = 0;
+ uint32_t goodBothSame = 0;
+ uint32_t from;
+ if (finishedLastTime || lastTimeWentUntil >= solver.nVars())
+ from = 0;
+ else
+ from = lastTimeWentUntil;
+ uint64_t origProps = solver.propagations;
+
+ //If failed var searching is going good, do successively more and more of it
+ if (lastTimeFoundTruths > 500 || (double)lastTimeFoundTruths > (double)solver.order_heap.size() * 0.05) std::max(numPropsMultiplier*1.7, 5.0);
+ else numPropsMultiplier = 1.0;
+ numProps = (uint64_t) ((double)numProps * numPropsMultiplier);
+
+ //For failure
+ bool failed;
+
+ //For BothSame
+ BitArray propagated;
+ propagated.resize(solver.nVars());
+ BitArray propValue;
+ propValue.resize(solver.nVars());
+ vector<pair<Var, bool> > bothSame;
+
+ //For 2-long xor (rule 6 of Equivalent literal propagation in the DLL procedure by Chu-Min Li)
+ set<TwoLongXor> twoLongXors;
+ uint32_t toReplaceBefore = solver.varReplacer->getNewToReplaceVars();
+ uint32_t lastTrailSize = solver.trail.size();
+ bool binXorFind = true;
+ if (solver.xorclauses.size() < 5 ||
+ solver.xorclauses.size() > 30000 ||
+ solver.order_heap.size() > 30000 ||
+ solver.nClauses() > 100000)
+ binXorFind = false;
+ if (binXorFind) addFromSolver(solver.xorclauses);
+ xorClauseTouched.resize(solver.xorclauses.size());
+
+ finishedLastTime = true;
+ lastTimeWentUntil = solver.nVars();
+ for (Var var = from; var < solver.nVars(); var++) {
+ if (solver.assigns[var] == l_Undef && solver.order_heap.inHeap(var)) {
+ if ((int)solver.propagations - (int)origProps >= (int)numProps) {
+ finishedLastTime = false;
+ lastTimeWentUntil = var;
+ break;
+ }
+
+ if (binXorFind) {
+ if (lastTrailSize < solver.trail.size()) {
+ for (uint32_t i = lastTrailSize; i != solver.trail.size(); i++) {
+ removeVarFromXors(solver.trail[i].var());
+ }
+ }
+ lastTrailSize = solver.trail.size();
+ xorClauseTouched.setZero();
+ investigateXor.clear();
+ }
+
+ propagated.setZero();
+ twoLongXors.clear();
+
+ solver.newDecisionLevel();
+ solver.uncheckedEnqueue(Lit(var, false));
+ failed = (solver.propagate(false) != NULL);
+ if (failed) {
+ solver.cancelUntil(0);
+ numFailed++;
+ solver.uncheckedEnqueue(Lit(var, true));
+ solver.ok = (solver.propagate(false) == NULL);
+ if (!solver.ok) goto end;
+ continue;
+ } else {
+ assert(solver.decisionLevel() > 0);
+ for (int c = solver.trail.size()-1; c >= (int)solver.trail_lim[0]; c--) {
+ Var x = solver.trail[c].var();
+ propagated.setBit(x);
+ if (solver.assigns[x].getBool())
+ propValue.setBit(x);
+ else
+ propValue.clearBit(x);
+
+ if (binXorFind) removeVarFromXors(x);
+ }
+
+ if (binXorFind) {
+ for (uint32_t *it = investigateXor.getData(), *end = it + investigateXor.size(); it != end; it++) {
+ if (xorClauseSizes[*it] == 2)
+ twoLongXors.insert(getTwoLongXor(*solver.xorclauses[*it]));
+ }
+ for (int c = solver.trail.size()-1; c >= (int)solver.trail_lim[0]; c--) {
+ addVarFromXors(solver.trail[c].var());
+ }
+ xorClauseTouched.setZero();
+ investigateXor.clear();
+ }
+
+ solver.cancelUntil(0);
+ }
+
+ solver.newDecisionLevel();
+ solver.uncheckedEnqueue(Lit(var, true));
+ failed = (solver.propagate(false) != NULL);
+ if (failed) {
+ solver.cancelUntil(0);
+ numFailed++;
+ solver.uncheckedEnqueue(Lit(var, false));
+ solver.ok = (solver.propagate(false) == NULL);
+ if (!solver.ok) goto end;
+ continue;
+ } else {
+ assert(solver.decisionLevel() > 0);
+ for (int c = solver.trail.size()-1; c >= (int)solver.trail_lim[0]; c--) {
+ Var x = solver.trail[c].var();
+ if (propagated[x] && propValue[x] == solver.assigns[x].getBool())
+ bothSame.push_back(make_pair(x, !propValue[x]));
+ if (binXorFind) removeVarFromXors(x);
+ }
+
+ if (binXorFind) {
+ if (twoLongXors.size() > 0) {
+ for (uint32_t *it = investigateXor.getData(), *end = it + investigateXor.size(); it != end; it++) {
+ if (xorClauseSizes[*it] == 2) {
+ TwoLongXor tmp = getTwoLongXor(*solver.xorclauses[*it]);
+ if (twoLongXors.find(tmp) != twoLongXors.end()) {
+ vec<Lit> ps(2);
+ ps[0] = Lit(tmp.var[0], false);
+ ps[1] = Lit(tmp.var[1], false);
+ if (!solver.varReplacer->replace(ps, tmp.inverted, 0))
+ goto end;
+ }
+ }
+ }
+ }
+ for (int c = solver.trail.size()-1; c >= (int)solver.trail_lim[0]; c--) {
+ addVarFromXors(solver.trail[c].var());
+ }
+ }
+
+ solver.cancelUntil(0);
+ }
+
+ for(uint32_t i = 0; i != bothSame.size(); i++) {
+ solver.uncheckedEnqueue(Lit(bothSame[i].first, bothSame[i].second));
+ }
+ goodBothSame += bothSame.size();
+ bothSame.clear();
+ solver.ok = (solver.propagate(false) == NULL);
+ if (!solver.ok) goto end;
+ }
+ }
+
+end:
+ //Restoring Solver state
+ if (solver.verbosity >= 1) {
+ std::cout << "c | Failvars: "<< std::setw(5) << numFailed <<
+ " Bprop vars: " << std::setw(6) << goodBothSame <<
+ " Replaced: " << std::setw(3) << (solver.varReplacer->getNewToReplaceVars() - toReplaceBefore) <<
+ " Props: " << std::setw(8) << std::setprecision(2) << (int)solver.propagations - (int)origProps <<
+ " Time: " << std::setw(6) << std::fixed << std::setprecision(2) << cpuTime() - time <<
+ std::setw(5) << " |" << std::endl;
+ }
+
+ solver.order_heap.filter(Solver::VarFilter(solver));
+
+ if (solver.ok && (numFailed || goodBothSame)) {
+ double time = cpuTime();
+ if ((int)origHeapSize - (int)solver.order_heap.size() > origHeapSize/15 && solver.nClauses() + solver.learnts.size() > 500000) {
+ solver.clauses_literals = 0;
+ solver.learnts_literals = 0;
+ for (uint32_t i = 0; i < solver.nVars(); i++) {
+ solver.binwatches[i*2].clear();
+ solver.binwatches[i*2+1].clear();
+ solver.watches[i*2].clear();
+ solver.watches[i*2+1].clear();
+ solver.xorwatches[i].clear();
+ }
+ solver.varReplacer->reattachInternalClauses();
+ cleanAndAttachClauses(solver.binaryClauses);
+ cleanAndAttachClauses(solver.clauses);
+ cleanAndAttachClauses(solver.learnts);
+ cleanAndAttachClauses(solver.xorclauses);
+ } else {
+ solver.clauseCleaner->removeAndCleanAll();
+ }
+ if (solver.verbosity >= 1 && numFailed + goodBothSame > 100) {
+ std::cout << "c | Cleaning up after failed var search: " << std::setw(8) << std::fixed << std::setprecision(2) << cpuTime() - time << " s "
+ << std::setw(33) << " | " << std::endl;
+ }
+ }
+
+ lastTimeFoundTruths = goodBothSame + numFailed;
+
+ solver.var_inc = backup_var_inc;
+ std::copy(backup_activity.getData(), backup_activity.getDataEnd(), solver.activity.getData());
+ solver.order_heap = backup_order_heap;
+ solver.polarity = backup_polarities;
+ solver.order_heap.filter(Solver::VarFilter(solver));
+
+ return solver.ok;
+}
+
+template<class T>
+inline void FailedVarSearcher::cleanAndAttachClauses(vec<T*>& cs)
+{
+ T **i = cs.getData();
+ T **j = i;
+ for (T **end = cs.getDataEnd(); i != end; i++) {
+ if (cleanClause(**i)) {
+ solver.attachClause(**i);
+ *j++ = *i;
+ } else {
+ free(*i);
+ }
+ }
+ cs.shrink(i-j);
+}
+
+inline const bool FailedVarSearcher::cleanClause(Clause& ps)
+{
+ uint32_t origSize = ps.size();
+
+ Lit *i = ps.getData();
+ Lit *j = i;
+ for (Lit *end = ps.getDataEnd(); i != end; i++) {
+ if (solver.value(*i) == l_True) return false;
+ if (solver.value(*i) == l_Undef) {
+ *j++ = *i;
+ }
+ }
+ ps.shrink(i-j);
+ assert(ps.size() > 1);
+
+ if (ps.size() != origSize) ps.setStrenghtened();
+ if (origSize != 2 && ps.size() == 2)
+ solver.becameBinary++;
+
+ return true;
+}
+
+inline const bool FailedVarSearcher::cleanClause(XorClause& ps)
+{
+ uint32_t origSize = ps.size();
+
+ Lit *i = ps.getData(), *j = i;
+ for (Lit *end = ps.getDataEnd(); i != end; i++) {
+ if (solver.assigns[i->var()] == l_True) ps.invert(true);
+ if (solver.assigns[i->var()] == l_Undef) {
+ *j++ = *i;
+ }
+ }
+ ps.shrink(i-j);
+
+ if (ps.size() == 0) return false;
+ assert(ps.size() > 1);
+
+ if (ps.size() != origSize) ps.setStrenghtened();
+ if (ps.size() == 2) {
+ vec<Lit> tmp(2);
+ tmp[0] = ps[0].unsign();
+ tmp[1] = ps[1].unsign();
+ solver.varReplacer->replace(tmp, ps.xor_clause_inverted(), ps.getGroup());
+ return false;
+ }
+
+ return true;
+}
+
+}; //NAMESPACE MINISAT
--- /dev/null
+/***********************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************************************/
+
+#ifndef FAILEDVARSEARCHER_H
+#define FAILEDVARSEARCHER_H
+
+#include "SolverTypes.h"
+#include "Clause.h"
+#include "BitArray.h"
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+class Solver;
+
+class TwoLongXor
+{
+ public:
+ const bool operator==(const TwoLongXor& other) const
+ {
+ if (var[0] == other.var[0] && var[1] == other.var[1] && inverted == other.inverted)
+ return true;
+ return false;
+ }
+ const bool operator<(const TwoLongXor& other) const
+ {
+ if (var[0] < other.var[0]) return true;
+ if (var[0] > other.var[0]) return false;
+
+ if (var[1] < other.var[1]) return true;
+ if (var[1] > other.var[1]) return false;
+
+ if (inverted < other.inverted) return true;
+ if (inverted > other.inverted) return false;
+
+ return false;
+ }
+
+ Var var[2];
+ bool inverted;
+};
+
+class FailedVarSearcher {
+ public:
+ FailedVarSearcher(Solver& _solver);
+
+ const bool search(uint64_t numProps);
+
+ private:
+ const TwoLongXor getTwoLongXor(const XorClause& c);
+ void addFromSolver(const vec<XorClause*>& cs);
+
+ template<class T>
+ void cleanAndAttachClauses(vec<T*>& cs);
+ const bool cleanClause(Clause& ps);
+ const bool cleanClause(XorClause& ps);
+
+ Solver& solver;
+
+ vec<uint32_t> xorClauseSizes;
+ vector<vector<uint32_t> > occur;
+ void removeVarFromXors(const Var var);
+ void addVarFromXors(const Var var);
+ BitArray xorClauseTouched;
+ vec<uint32_t> investigateXor;
+
+ bool finishedLastTime;
+ uint32_t lastTimeWentUntil;
+ double numPropsMultiplier;
+ uint32_t lastTimeFoundTruths;
+};
+
+}; //NAMESPACE MINISAT
+
+#endif //FAILEDVARSEARCHER_H
\ No newline at end of file
#include "FindUndef.h"
#include "Solver.h"
+#include "VarReplacer.h"
#include <algorithm>
namespace MINISAT
{
+using namespace MINISAT;
-FindUndef::FindUndef(Solver& _s) :
- S(_s)
+FindUndef::FindUndef(Solver& _solver) :
+ solver(_solver)
, isPotentialSum(0)
{
- dontLookAtClause.resize(S.clauses.size(), false);
- isPotential.resize(S.nVars(), false);
- fillPotential();
- satisfies.resize(S.nVars(), 0);
}
void FindUndef::fillPotential()
{
- int trail = S.decisionLevel()-1;
+ int trail = solver.decisionLevel()-1;
while(trail > 0) {
- assert(trail < S.trail_lim.size());
- uint at = S.trail_lim[trail];
+ assert(trail < solver.trail_lim.size());
+ uint at = solver.trail_lim[trail];
assert(at > 0);
- Var v = S.trail[at].var();
- isPotential[v] = true;
- isPotentialSum++;
+ Var v = solver.trail[at].var();
+ if (solver.assigns[v] != l_Undef) {
+ isPotential[v] = true;
+ isPotentialSum++;
+ }
trail--;
}
- for (XorClause** it = S.xorclauses.getData(), **end = it + S.xorclauses.size(); it != end; it++) {
+ for (XorClause** it = solver.xorclauses.getData(), **end = it + solver.xorclauses.size(); it != end; it++) {
XorClause& c = **it;
for (Lit *l = c.getData(), *end = l + c.size(); l != end; l++) {
if (isPotential[l->var()]) {
isPotential[l->var()] = false;
isPotentialSum--;
}
- assert(!S.value(*l).isUndef());
+ assert(!solver.value(*l).isUndef());
}
}
- vector<Var> replacingVars = S.varReplacer->getReplacingVars();
+ vector<Var> replacingVars = solver.varReplacer->getReplacingVars();
for (Var *it = &replacingVars[0], *end = it + replacingVars.size(); it != end; it++) {
if (isPotential[*it]) {
isPotential[*it] = false;
{
for (uint i = 0; i < isPotential.size(); i++)
if (isPotential[i])
- S.assigns[i] = l_Undef;
+ solver.assigns[i] = l_Undef;
+}
+
+void FindUndef::moveBinToNormal()
+{
+ binPosition = solver.clauses.size();
+ for (uint i = 0; i != solver.binaryClauses.size(); i++)
+ solver.clauses.push(solver.binaryClauses[i]);
+ solver.binaryClauses.clear();
+}
+
+void FindUndef::moveBinFromNormal()
+{
+ for (uint i = binPosition; i != solver.clauses.size(); i++)
+ solver.binaryClauses.push(solver.clauses[i]);
+ solver.clauses.shrink(solver.clauses.size() - binPosition);
}
const uint FindUndef::unRoll()
{
+ if (solver.decisionLevel() == 0) return 0;
+
+ moveBinToNormal();
+
+ dontLookAtClause.resize(solver.clauses.size(), false);
+ isPotential.resize(solver.nVars(), false);
+ fillPotential();
+ satisfies.resize(solver.nVars(), 0);
+
while(!updateTables()) {
assert(isPotentialSum > 0);
}
unboundIsPotentials();
+ moveBinFromNormal();
return isPotentialSum;
}
bool allSat = true;
uint i = 0;
- for (Clause** it = S.clauses.getData(), **end = it + S.clauses.size(); it != end; it++, i++) {
+ for (Clause** it = solver.clauses.getData(), **end = it + solver.clauses.size(); it != end; it++, i++) {
if (dontLookAtClause[i])
continue;
Clause& c = **it;
bool definitelyOK = false;
- Var v;
+ Var v = var_Undef;
uint numTrue = 0;
for (Lit *l = c.getData(), *end = l + c.size(); l != end; l++) {
- if (S.value(*l) == l_True) {
+ if (solver.value(*l) == l_True) {
if (!isPotential[l->var()]) {
dontLookAtClause[i] = true;
definitelyOK = true;
continue;
if (numTrue == 1) {
+ assert(v != var_Undef);
isPotential[v] = false;
isPotentialSum--;
dontLookAtClause[i] = true;
continue;
}
+ //numTrue > 1
allSat = false;
for (Lit *l = c.getData(), *end = l + c.size(); l != end; l++) {
- if (S.value(*l) == l_True)
+ if (solver.value(*l) == l_True)
satisfies[l->var()]++;
}
}
return allSat;
}
-};
+
+}; //NAMESPACE MINISAT
#ifndef FINDUNDEF_H
#define FINDUNDEF_H
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
#include <vector>
using std::vector;
namespace MINISAT
{
+using namespace MINISAT;
class FindUndef {
public:
- FindUndef(Solver& S);
+ FindUndef(Solver& _solver);
const uint unRoll();
private:
- Solver& S;
+ Solver& solver;
+ void moveBinToNormal();
+ void moveBinFromNormal();
bool updateTables();
void fillPotential();
void unboundIsPotentials();
vector<uint32_t> satisfies;
vector<bool> isPotential;
uint32_t isPotentialSum;
+ uint32_t binPosition;
};
-};
-#endif //
+}; //NAMESPACE MINISAT
+#endif //
\ No newline at end of file
Gaussian::~Gaussian()
{
for (uint i = 0; i < clauses_toclear.size(); i++)
- free(clauses_toclear[i].first);
+ clauseFree(clauses_toclear[i].first);
}
inline void Gaussian::set_matrixset_to_cur()
while (do_again_gauss) {
do_again_gauss = false;
solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses);
+ if (solver.ok == false)
+ return l_False;
init();
Clause* confl;
gaussian_ret g = gaussian(confl);
uint num_xorclauses = 0;
for (uint32_t i = 0; i != xorclauses.size(); i++) {
- #ifdef DEBUG_GAUSS
- assert(xorclauses[i]->mark() || !Solver.cpplauseCleaner->satisfied(*xorclauses[i]));
- #endif
- if (!xorclauses[i]->mark()) {
- num_xorclauses++;
- XorClause& c = *xorclauses[i];
- for (uint i2 = 0; i2 < c.size(); i2++) {
- assert(solver.assigns[c[i2].var()].isUndef());
- var_to_col[c[i2].var()] = unassigned_col - 1;
- }
+ num_xorclauses++;
+ XorClause& c = *xorclauses[i];
+ for (uint i2 = 0; i2 < c.size(); i2++) {
+ assert(solver.assigns[c[i2].var()].isUndef());
+ var_to_col[c[i2].var()] = unassigned_col - 1;
}
}
for (uint32_t i = 0; i != xorclauses.size(); i++) {
const XorClause& c = *xorclauses[i];
- if (!c.mark()) {
- origMat.matrix.getVarsetAt(matrix_row).set(c, var_to_col, origMat.num_cols);
- origMat.matrix.getMatrixAt(matrix_row).set(c, var_to_col, origMat.num_cols);
- matrix_row++;
- }
+ origMat.matrix.getVarsetAt(matrix_row).set(c, var_to_col, origMat.num_cols);
+ origMat.matrix.getMatrixAt(matrix_row).set(c, var_to_col, origMat.num_cols);
+ matrix_row++;
}
assert(origMat.num_rows == matrix_row);
}
assert(best_row != UINT_MAX);
m.matrix.getVarsetAt(best_row).fill(tmp_clause, solver.assigns, col_to_var_original);
- confl = Clause_new(tmp_clause, solver.learnt_clause_group++, false);
+ confl = (Clause*)XorClause_new(tmp_clause, false, solver.learnt_clause_group++);
Clause& cla = *confl;
#ifdef STATS_NEEDED
if (solver.dynamic_behaviour_analysis)
- solver.logger.set_group_name(confl->group, "learnt gauss clause");
+ solver.logger.set_group_name(confl->getGroup(), "learnt gauss clause");
#endif
if (cla.size() <= 1)
if (maxlevel != solver.decisionLevel()) {
#ifdef STATS_NEEDED
if (solver.dynamic_behaviour_analysis)
- solver.logger.conflict(Logger::gauss_confl_type, maxlevel, confl->group, *confl);
+ solver.logger.conflict(Logger::gauss_confl_type, maxlevel, confl->getGroup(), *confl);
#endif
solver.cancelUntil(maxlevel);
}
cout << "(" << matrix_no << ")Canceling until sublevel " << sublevel << endl;
#endif
- for (Gaussian **gauss = &(solver.gauss_matrixes[0]), **end= gauss + solver.gauss_matrixes.size(); gauss != end; gauss++)
+ for (vector<Gaussian*>::iterator gauss = solver.gauss_matrixes.begin(), end= solver.gauss_matrixes.end(); gauss != end; gauss++)
if (*gauss != this) (*gauss)->canceling(sublevel);
for (int level = solver.trail.size()-1; level >= (int)sublevel; level--) {
#endif
m.matrix.getVarsetAt(row).fill(tmp_clause, solver.assigns, col_to_var_original);
- Clause& cla = *Clause_new(tmp_clause, solver.learnt_clause_group++, false);
+ Clause& cla = *(Clause*)XorClause_new(tmp_clause, false, solver.learnt_clause_group++);
#ifdef VERBOSE_DEBUG
cout << "(" << matrix_no << ")matrix prop clause: ";
cla.plainPrint();
clauses_toclear.push_back(std::make_pair(&cla, solver.trail.size()-1));
#ifdef STATS_NEEDED
if (solver.dynamic_behaviour_analysis)
- solver.logger.set_group_name(cla.group, "gauss prop clause");
+ solver.logger.set_group_name(cla.getGroup(), "gauss prop clause");
#endif
solver.uncheckedEnqueue(cla[0], &cla);
{
if (//nof_conflicts >= 0
//&& conflictC >= nof_conflicts/8
- /*&&*/ called > 100
- && (double)useful_confl/(double)called < 0.1
- && (double)useful_prop/(double)called < 0.3 )
+ !config.dontDisable
+ && called > 50
+ && useful_confl*2+useful_prop < (uint)((double)called*0.05) )
disabled = true;
}
switch (g) {
case conflict: {
useful_confl++;
- llbool ret = solver.handle_conflict(learnt_clause, confl, conflictC);
- free(confl);
+ llbool ret = solver.handle_conflict(learnt_clause, confl, conflictC, true);
+ clauseFree(confl);
if (ret != l_Nothing) return ret;
return l_Continue;
Lit lit = (*confl)[0];
#ifdef STATS_NEEDED
if (solver.dynamic_behaviour_analysis)
- solver.logger.conflict(Logger::gauss_confl_type, 0, confl->group, *confl);
+ solver.logger.conflict(Logger::gauss_confl_type, 0, confl->getGroup(), *confl);
#endif
solver.cancelUntil(0);
if (solver.assigns[lit.var()].isDef()) {
- free(confl);
+ clauseFree(confl);
return l_False;
}
solver.uncheckedEnqueue(lit);
- free(confl);
+ clauseFree(confl);
return l_Continue;
}
case nothing:
return true;
}
-const bool Gaussian::check_matrix_against_varset(PackedMatrix& matrix, const matrixset& m) const
+void Gaussian::check_matrix_against_varset(PackedMatrix& matrix, const matrixset& m) const
{
for (uint i = 0; i < matrix.getSize(); i++) {
const PackedRow mat_row = matrix.getMatrixAt(i);
#endif
}*/
-};
+}; //NAMESPACE MINISAT
#define GAUSSIAN_H
#include <vector>
+#include <limits>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
#include "SolverTypes.h"
#include "Solver.h"
#include "GaussianConfig.h"
#include "PackedMatrix.h"
#include "BitArray.h"
-namespace MINISAT
-{
-using namespace MINISAT;
-
//#define VERBOSE_DEBUG
//#define DEBUG_GAUSS
using std::endl;
#endif
+namespace MINISAT
+{
+using namespace MINISAT;
+
class Clause;
-static const uint16_t unassigned_col = -1;
-static const Var unassigned_var = -1;
+static const uint16_t unassigned_col = std::numeric_limits<uint16_t>::max();
+static const Var unassigned_var = std::numeric_limits<Var>::max();
class Gaussian
{
void print_matrix_row(const T& row) const; // Print matrix row 'row'
template<class T>
void print_matrix_row_with_assigns(const T& row) const;
- const bool check_matrix_against_varset(PackedMatrix& matrix,const matrixset& m) const;
+ void check_matrix_against_varset(PackedMatrix& matrix,const matrixset& m) const;
const bool check_last_one_in_cols(matrixset& m) const;
const void check_first_one_in_row(matrixset& m, const uint j);
void print_matrix(matrixset& m) const;
inline bool Gaussian::should_init() const
{
- return (solver.starts >= config.starts_from && config.decision_until > 0);
+ return (config.decision_until > 0);
}
inline bool Gaussian::should_check_gauss(const uint decisionlevel, const uint starts) const
{
return (!disabled
- && starts >= config.starts_from
&& decisionlevel < config.decision_until);
}
return;
uint a = 0;
for (int i = clauses_toclear.size()-1; i >= 0 && clauses_toclear[i].second > sublevel; i--) {
- free(clauses_toclear[i].first);
+ clauseFree(clauses_toclear[i].first);
a++;
}
clauses_toclear.resize(clauses_toclear.size()-a);
if (messed_matrix_vars_since_reversal)
return;
int c = std::min((int)gauss_last_level, (int)(solver.trail.size())-1);
- for (; c >= sublevel; c--) {
+ for (; c >= (int)sublevel; c--) {
Var var = solver.trail[c].var();
if (var < var_is_in.getSize()
&& var_is_in[var]
}
std::ostream& operator << (std::ostream& os, const vec<Lit>& v);
-};
+
+}; //NAMESPACE MINISAT
#endif //GAUSSIAN_H
#ifndef GAUSSIANCONFIG_H
#define GAUSSIANCONFIG_H
-#include <sys/types.h>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
#include "PackedRow.h"
namespace MINISAT
GaussianConfig() :
only_nth_gauss_save(2)
, decision_until(0)
- , starts_from(2)
+ , dontDisable(false)
{
}
//tuneable gauss parameters
uint only_nth_gauss_save; //save only every n-th gauss matrix
uint decision_until; //do Gauss until this level
- uint starts_from; //Gauss elimination starts from this restart number
+ bool dontDisable; //If activated, gauss elimination is never disabled
};
-};
+}; //NAMESPACE MINISAT
+
#endif //GAUSSIANCONFIG_H
#include <iomanip>
#include <fstream>
#include <sstream>
+#include <limits>
using std::cout;
using std::endl;
using std::ofstream;
#include "Solver.h"
#include "Gaussian.h"
-namespace MINISAT
-{
-
#define FST_WIDTH 10
#define SND_WIDTH 35
#define TRD_WIDTH 10
+namespace MINISAT
+{
+using namespace MINISAT;
+
Logger::Logger(int& _verbosity) :
proof_graph_on(false)
, mini_proof(false)
times_var_propagated.resize(var+1, 0);
times_var_guessed.resize(var+1, 0);
depths_of_assigns_for_var.resize(var+1);
+ depths_of_assigns_unit.resize(var+1, false);
}
}
times_group_caused_conflict.resize(group+1, 0);
times_group_caused_propagation.resize(group+1, 0);
depths_of_propagations_for_group.resize(group+1);
+ depths_of_propagations_unit.resize(group+1, false);
depths_of_conflicts_for_group.resize(group+1);
}
}
if (statistics_on) {
times_group_caused_conflict[group]++;
- depths_of_conflicts_for_group[group].push_back(S->decisionLevel());
+ depths_of_conflicts_for_group[group].sum += S->decisionLevel();
+ depths_of_conflicts_for_group[group].num ++;
no_conflicts++;
sum_conflict_depths += S->trail.size() - S->trail_lim[0];
sum_decisions_on_branches += S->decisionLevel();
sum_propagations_on_branches += S->trail.size() - S->trail_lim[0] - S->decisionLevel();
- map<uint, uint>::iterator it = branch_depth_distrib.find(S->decisionLevel());
- if (it == branch_depth_distrib.end())
- branch_depth_distrib[S->decisionLevel()] = 1;
- else
- it->second++;
+ if (branch_depth_distrib.size() <= S->decisionLevel())
+ branch_depth_distrib.resize(S->decisionLevel()+1, 0);
+ branch_depth_distrib[S->decisionLevel()]++;
}
}
type = add_clause_type;
else
type = guess_type;
- group = UINT_MAX;
+ group = std::numeric_limits<uint>::max();
} else {
type = simple_propagation_type;
- group = c->group;
+ group = c->getGroup();
}
//graph
if (statistics_on) {
switch (type) {
case simple_propagation_type:
- depths_of_propagations_for_group[group].push_back(S->decisionLevel());
+ depths_of_propagations_for_group[group].sum += S->decisionLevel();
+ depths_of_propagations_for_group[group].num ++;
+ if (S->decisionLevel() == 0) depths_of_propagations_unit[group] = true;
times_group_caused_propagation[group]++;
case add_clause_type:
no_propagations++;
times_var_propagated[lit.var()]++;
- depths_of_assigns_for_var[lit.var()].push_back(S->decisionLevel());
+ depths_of_assigns_for_var[lit.var()].sum += S->decisionLevel();
+ depths_of_assigns_for_var[lit.var()].num ++;
+ if (S->decisionLevel() == 0) depths_of_assigns_unit[lit.var()] = true;
break;
case guess_type:
no_decisions++;
times_var_guessed[lit.var()]++;
- depths_of_assigns_for_var[lit.var()].push_back(S->decisionLevel());
+ depths_of_assigns_for_var[lit.var()].sum += S->decisionLevel();
+ depths_of_assigns_for_var[lit.var()].num ++;
break;
}
}
{
vector<pair<double, uint> > prop_ordered;
for (uint i = 0; i < depths_of_assigns_for_var.size(); i++) {
- double avg = 0.0;
- bool was_unit = false;
- for (vector<uint>::const_iterator it = depths_of_assigns_for_var[i].begin(); it != depths_of_assigns_for_var[i].end(); it++) {
- avg += *it;
- if (*it == 0) was_unit = true;
- }
- if (depths_of_assigns_for_var[i].size() > 0 && !was_unit) {
- avg /= (double) depths_of_assigns_for_var[i].size();
+ double avg = (double)depths_of_assigns_for_var[i].sum
+ /(double)depths_of_assigns_for_var[i].num;
+ if (depths_of_assigns_for_var[i].num > 0 && !depths_of_assigns_unit[i])
prop_ordered.push_back(std::make_pair(avg, i));
- }
}
if (!prop_ordered.empty()) {
{
vector<pair<double, uint> > prop_ordered;
for (uint i = 0; i < depths_of_propagations_for_group.size(); i++) {
- double avg = 0.0;
- bool was_unit = false;
- for (vector<uint>::const_iterator it = depths_of_propagations_for_group[i].begin(); it != depths_of_propagations_for_group[i].end(); it++) {
- avg += *it;
- if (*it == 0) was_unit = true;
- }
- if (depths_of_propagations_for_group[i].size() > 0 && !was_unit) {
- avg /= (double) depths_of_propagations_for_group[i].size();
+ double avg = (double)depths_of_propagations_for_group[i].sum
+ /(double)depths_of_propagations_for_group[i].num;
+ if (depths_of_propagations_for_group[i].num > 0 && !depths_of_propagations_unit[i])
prop_ordered.push_back(std::make_pair(avg, i));
- }
}
if (!prop_ordered.empty()) {
{
vector<pair<double, uint> > confl_ordered;
for (uint i = 0; i < depths_of_conflicts_for_group.size(); i++) {
- double avg = 0.0;
- for (vector<uint>::const_iterator it = depths_of_conflicts_for_group[i].begin(); it != depths_of_conflicts_for_group[i].end(); it++)
- avg += *it;
- if (depths_of_conflicts_for_group[i].size() > 0) {
- avg /= (double) depths_of_conflicts_for_group[i].size();
+ double avg = (double)depths_of_conflicts_for_group[i].sum
+ /(double)depths_of_conflicts_for_group[i].num;
+ if (depths_of_conflicts_for_group[i].num > 0)
confl_ordered.push_back(std::make_pair(avg, i));
- }
}
if (!confl_ordered.empty()) {
const uint range = 20;
map<uint, uint> range_stat;
- for (map<uint, uint>::const_iterator it = branch_depth_distrib.begin(); it != branch_depth_distrib.end(); it++) {
- //cout << it->first << " : " << it->second << endl;
- range_stat[it->first/range] += it->second;
+ uint i = 0;
+ for (vector<uint>::const_iterator it = branch_depth_distrib.begin(); it != branch_depth_distrib.end(); it++, i++) {
+ range_stat[i/range] += *it;
}
- //cout << endl;
print_footer();
print_simple_line(" No. search branches with branch depth between");
ss << "branch_depths/branch_depth_file" << runid << "-" << S->starts << ".txt";
ofstream branch_depth_file;
branch_depth_file.open(ss.str().c_str());
- uint i = 0;
+ i = 0;
- for (map<uint, uint>::iterator it = range_stat.begin(); it != range_stat.end(); it++) {
+ for (map<uint, uint>::iterator it = range_stat.begin(); it != range_stat.end(); it++, i++) {
std::stringstream ss2;
ss2 << it->first*range << " - " << it->first*range + range-1;
print_line(ss2.str(), it->second);
branch_depth_file << "\"\"";
branch_depth_file << endl;
}
- i++;
}
if (branch_depth_file.is_open())
branch_depth_file.close();
print_footer();
print_simple_line(display);
print_header("var", "name", "value");
- for (uint i = from; i < S->trail.size(); i++) {
+ uint32_t until;
+ if (S->decisionLevel() > 0)
+ until = S->trail_lim[0];
+ else
+ until = S->trail.size();
+ for (uint i = from; i < until; i++) {
Var var = S->trail[i].var();
- bool sign = S->trail[i].sign();
- std::stringstream ss;
- print_line(var+1, varnames[var], sign);
+ bool value = !(S->trail[i].sign());
+ print_line(var+1, varnames[var], value);
}
print_footer();
}
for (vecit it = props_by_group.begin(); it != props_by_group.end(); it++)
*it = 0;
- typedef vector<vector<uint> >::iterator vecvecit;
+ typedef vector<MyAvg>::iterator avgIt;
- for (vecvecit it = depths_of_propagations_for_group.begin(); it != depths_of_propagations_for_group.end(); it++)
- it->clear();
+ for (avgIt it = depths_of_propagations_for_group.begin(); it != depths_of_propagations_for_group.end(); it++) {
+ it->sum = 0;
+ it->num = 0;
+ }
- for (vecvecit it = depths_of_conflicts_for_group.begin(); it != depths_of_conflicts_for_group.end(); it++)
- it->clear();
+ for (avgIt it = depths_of_conflicts_for_group.begin(); it != depths_of_conflicts_for_group.end(); it++) {
+ it->sum = 0;
+ it->num = 0;
+ }
- for (vecvecit it = depths_of_assigns_for_var.begin(); it != depths_of_assigns_for_var.end(); it++)
- it->clear();
+ for (avgIt it = depths_of_assigns_for_var.begin(); it != depths_of_assigns_for_var.end(); it++) {
+ it->sum = 0;
+ it->num = 0;
+ }
+ for (uint i = 0; i < depths_of_assigns_unit.size(); i++)
+ depths_of_assigns_unit[i] = false;
+
+ for (uint i = 0; i < depths_of_propagations_unit.size(); i++)
+ depths_of_propagations_unit[i] = false;
sum_conflict_depths = 0;
no_conflicts = 0;
last_unitary_learnt_clauses = S->get_unitary_learnts_num();
}
-};
+}; //NAMESPACE MINISAT
#include <vector>
#include <string>
#include <map>
-
-#include "mtl/Vec.h"
-#include "mtl/Heap.h"
-#include "mtl/Alg.h"
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include "Vec.h"
+#include "Heap.h"
+#include "Alg.h"
#include "SolverTypes.h"
-#include "stdint.h"
#include "limits.h"
#include "Clause.h"
-#ifndef uint
-#define uint unsigned int
-#endif
-
-namespace MINISAT
-{
-
using std::vector;
using std::pair;
using std::string;
using std::map;
+namespace MINISAT
+{
+using namespace MINISAT;
+
class Solver;
+class MyAvg {
+public:
+ MyAvg() :
+ sum(0)
+ , num(0)
+ {}
+
+ uint sum;
+ uint num;
+};
+
class Logger
{
public:
vector<uint> times_group_caused_conflict;
vector<uint> times_group_caused_propagation;
- vector<vector<uint> > depths_of_propagations_for_group;
- vector<vector<uint> > depths_of_conflicts_for_group;
- vector<vector<uint> > depths_of_assigns_for_var;
+ vector<MyAvg> depths_of_propagations_for_group;
+ vector<bool> depths_of_propagations_unit;
+ vector<MyAvg> depths_of_conflicts_for_group;
+ vector<MyAvg> depths_of_assigns_for_var;
+ vector<bool> depths_of_assigns_unit;
//the distribution of branch depths. first = depth, second = number of occurances
- map<uint, uint> branch_depth_distrib;
+ vector<uint> branch_depth_distrib;
uint sum_conflict_depths;
uint no_conflicts;
uint proofStarts;
};
-};
+}; //NAMESPACE MINISAT
+
#endif //LOGGER_H
MTL = mtl
MTRAND = MTRand
-SOURCES = Conglomerate.cpp FindUndef.cpp Gaussian.cpp Logger.cpp MatrixFinder.cpp PackedRow.cpp Solver.cpp VarReplacer.cpp XorFinder.cpp ClauseCleaner.cpp RestartTypeChooser.cpp
+SOURCES = Logger.cpp Solver.cpp Gaussian.cpp PackedRow.cpp XorFinder.cpp Conglomerate.cpp MatrixFinder.cpp VarReplacer.cpp FindUndef.cpp ClauseCleaner.cpp RestartTypeChooser.cpp Clause.cpp FailedVarSearcher.cpp PartFinder.cpp Subsumer.cpp PartHandler.cpp XorSubsumer.cpp
OBJECTS = $(SOURCES:.cpp=.o)
LIB = libminisat.a
CFLAGS += -I$(MTL) -I$(MTRAND) -DEXT_HASH_MAP -ffloat-store $(CFLAGS_M32) -c
#include <map>
#include <iomanip>
#include <math.h>
-namespace MINISAT
-{
-
using std::set;
using std::map;
using std::cout;
using std::endl;
+namespace MINISAT
+{
+using namespace MINISAT;
+
//#define PART_FINDING
-MatrixFinder::MatrixFinder(Solver *_s) :
- unAssigned(_s->nVars() + 1)
- , S(_s)
+MatrixFinder::MatrixFinder(Solver& _solver) :
+ solver(_solver)
{
}
const uint MatrixFinder::findMatrixes()
{
table.clear();
- table.resize(S->nVars(), unAssigned);
+ table.resize(solver.nVars(), var_Undef);
reverseTable.clear();
matrix_no = 0;
- if (S->xorclauses.size() == 0)
+ if (solver.xorclauses.size() == 0)
return 0;
- S->clauseCleaner->cleanClauses(S->xorclauses, ClauseCleaner::xorclauses);
+ solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses);
+ //TODO check for solver.ok == false
- for (XorClause** c = S->xorclauses.getData(), **end = c + S->xorclauses.size(); c != end; c++) {
+ for (XorClause** c = solver.xorclauses.getData(), **end = c + solver.xorclauses.size(); c != end; c++) {
set<uint> tomerge;
vector<Var> newSet;
for (Lit *l = &(**c)[0], *end2 = l + (**c).size(); l != end2; l++) {
- if (table[l->var()] != unAssigned)
+ if (table[l->var()] != var_Undef)
tomerge.insert(table[l->var()]);
else
newSet.push_back(l->var());
vector<vector<Var> > xorFingerprintInMatrix(matrix_no);
#endif
- for (XorClause** c = S->xorclauses.getData(), **end = c + S->xorclauses.size(); c != end; c++) {
+ for (XorClause** c = solver.xorclauses.getData(), **end = c + solver.xorclauses.size(); c != end; c++) {
XorClause& x = **c;
const uint matrix = table[x[0].var()];
assert(matrix < matrix_no);
double variance = 0.0;
for (uint i2 = 0; i2 < xorSizesInMatrix[i].size(); i2++)
variance += pow((double)xorSizesInMatrix[i][i2]-avg, 2);
- variance /= xorSizesInMatrix.size();
+ variance /= (double)xorSizesInMatrix.size();
const double stdDeviation = sqrt(variance);
if (numXorInMatrix[a].second >= 20
&& numXorInMatrix[a].second <= 1000
&& realMatrixNum < 3)
{
- if (S->verbosity >=1)
+ if (solver.verbosity >=1)
cout << "c | Matrix no " << std::setw(4) << realMatrixNum;
- S->gauss_matrixes.push_back(new Gaussian(*S, S->gaussconfig, realMatrixNum, xorsInMatrix[i]));
+ solver.gauss_matrixes.push_back(new Gaussian(solver, solver.gaussconfig, realMatrixNum, xorsInMatrix[i]));
realMatrixNum++;
} else {
- if (S->verbosity >=1 && numXorInMatrix[a].second >= 20)
+ if (solver.verbosity >=1 /*&& numXorInMatrix[a].second >= 20*/)
cout << "c | Unused Matrix ";
}
- if (S->verbosity >=1 && numXorInMatrix[a].second >= 20) {
+ if (solver.verbosity >=1 /*&& numXorInMatrix[a].second >= 20*/) {
cout << std::setw(5) << numXorInMatrix[a].second << " x" << std::setw(5) << reverseTable[i].size();
cout << " density:" << std::setw(5) << std::fixed << std::setprecision(1) << density << "%";
cout << " xorlen avg:" << std::setw(5) << std::fixed << std::setprecision(2) << avg;
}
}
}
-};
+
+}; //NAMESPACE MINISAT
#ifndef MATRIXFINDER_H
#define MATRIXFINDER_H
-#include <sys/types.h>
-#include "Clause.h"
#include <vector>
#include <map>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include "Clause.h"
+#include "Solver.h"
namespace MINISAT
{
+using namespace MINISAT;
class Solver;
class MatrixFinder {
public:
- MatrixFinder(Solver* S);
+ MatrixFinder(Solver& solver);
const uint findMatrixes();
private:
inline const bool firstPartOfSecond(const XorClause& c1, const XorClause& c2) const;
map<uint, vector<Var> > reverseTable; //matrix -> vars
- vector<uint> table; //var -> matrix
+ vector<Var> table; //var -> matrix
uint matrix_no;
- const uint unAssigned;
- Solver* S;
-};
+ Solver& solver;
};
+}; //NAMESPACE MINISAT
+
#endif //MATRIXFINDER_H
--- /dev/null
+// MersenneTwister.h
+// Mersenne Twister random number generator -- a C++ class MTRand
+// Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
+// Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com
+
+// The Mersenne Twister is an algorithm for generating random numbers. It
+// was designed with consideration of the flaws in various other generators.
+// The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
+// are far greater. The generator is also fast; it avoids multiplication and
+// division, and it benefits from caches and pipelines. For more information
+// see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html
+
+// Reference
+// M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
+// Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on
+// Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.
+
+// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+// Copyright (C) 2000 - 2003, Richard J. Wagner
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// 3. The names of its contributors may not be used to endorse or promote
+// products derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The original code included the following notice:
+//
+// When you use this, send an email to: matumoto@math.keio.ac.jp
+// with an appropriate reference to your work.
+//
+// It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu
+// when you write.
+
+#ifndef MERSENNETWISTER_H
+#define MERSENNETWISTER_H
+
+#include <iostream>
+#include <limits.h>
+#include <stdio.h>
+#include <time.h>
+#include <math.h>
+
+namespace MINISAT
+{
+
+// Not thread safe (unless auto-initialization is avoided and each thread has
+// its own MTRand object)
+
+class MTRand {
+// Data
+public:
+ typedef unsigned long uint32; // unsigned integer type, at least 32 bits
+
+ enum { N = 624 }; // length of state vector
+ enum { SAVE = N + 1 }; // length of array for save()
+
+protected:
+ enum { M = 397 }; // period parameter
+
+ uint32 state[N]; // internal state
+ uint32 *pNext; // next value to get from state
+ int left; // number of values left before reload needed
+
+
+//Methods
+public:
+ MTRand( const uint32& oneSeed ); // initialize with a simple uint32
+ MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or an array
+ MTRand(); // auto-initialize with /dev/urandom or time() and clock()
+
+ // Do NOT use for CRYPTOGRAPHY without securely hashing several returned
+ // values together, otherwise the generator state can be learned after
+ // reading 624 consecutive values.
+
+ // Access to 32-bit random numbers
+ double rand(); // real number in [0,1]
+ double rand( const double& n ); // real number in [0,n]
+ double randExc(); // real number in [0,1)
+ double randExc( const double& n ); // real number in [0,n)
+ double randDblExc(); // real number in (0,1)
+ double randDblExc( const double& n ); // real number in (0,n)
+ uint32 randInt(); // integer in [0,2^32-1]
+ uint32 randInt( const uint32& n ); // integer in [0,n] for n < 2^32
+ double operator()() { return rand(); } // same as rand()
+
+ // Access to 53-bit random numbers (capacity of IEEE double precision)
+ double rand53(); // real number in [0,1)
+
+ // Access to nonuniform random number distributions
+ double randNorm( const double& mean = 0.0, const double& variance = 0.0 );
+
+ // Re-seeding functions with same behavior as initializers
+ void seed( const uint32 oneSeed );
+ void seed( uint32 *const bigSeed, const uint32 seedLength = N );
+ void seed();
+
+ // Saving and loading generator state
+ void save( uint32* saveArray ) const; // to array of size SAVE
+ void load( uint32 *const loadArray ); // from such array
+ friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand );
+ friend std::istream& operator>>( std::istream& is, MTRand& mtrand );
+
+protected:
+ void initialize( const uint32 oneSeed );
+ void reload();
+ uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; }
+ uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; }
+ uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; }
+ uint32 mixBits( const uint32& u, const uint32& v ) const
+ { return hiBit(u) | loBits(v); }
+ uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const
+ { return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL); }
+ static uint32 hash( time_t t, clock_t c );
+};
+
+
+inline MTRand::MTRand( const uint32& oneSeed )
+ { seed(oneSeed); }
+
+inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength )
+ { seed(bigSeed,seedLength); }
+
+inline MTRand::MTRand()
+ { seed(); }
+
+inline double MTRand::rand()
+ { return double(randInt()) * (1.0/4294967295.0); }
+
+inline double MTRand::rand( const double& n )
+ { return rand() * n; }
+
+inline double MTRand::randExc()
+ { return double(randInt()) * (1.0/4294967296.0); }
+
+inline double MTRand::randExc( const double& n )
+ { return randExc() * n; }
+
+inline double MTRand::randDblExc()
+ { return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); }
+
+inline double MTRand::randDblExc( const double& n )
+ { return randDblExc() * n; }
+
+inline double MTRand::rand53()
+{
+ uint32 a = randInt() >> 5, b = randInt() >> 6;
+ return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada
+}
+
+inline double MTRand::randNorm( const double& mean, const double& variance )
+{
+ // Return a real number from a normal (Gaussian) distribution with given
+ // mean and variance by Box-Muller method
+ double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance;
+ double phi = 2.0 * 3.14159265358979323846264338328 * randExc();
+ return mean + r * cos(phi);
+}
+
+inline MTRand::uint32 MTRand::randInt()
+{
+ // Pull a 32-bit integer from the generator state
+ // Every other access function simply transforms the numbers extracted here
+
+ if( left == 0 ) reload();
+ --left;
+
+ register uint32 s1;
+ s1 = *pNext++;
+ s1 ^= (s1 >> 11);
+ s1 ^= (s1 << 7) & 0x9d2c5680UL;
+ s1 ^= (s1 << 15) & 0xefc60000UL;
+ return ( s1 ^ (s1 >> 18) );
+}
+
+inline MTRand::uint32 MTRand::randInt( const uint32& n )
+{
+ // Find which bits are used in n
+ // Optimized by Magnus Jonsson (magnus@smartelectronix.com)
+ uint32 used = n;
+ used |= used >> 1;
+ used |= used >> 2;
+ used |= used >> 4;
+ used |= used >> 8;
+ used |= used >> 16;
+
+ // Draw numbers until one is found in [0,n]
+ uint32 i;
+ do
+ i = randInt() & used; // toss unused bits to shorten search
+ while( i > n );
+ return i;
+}
+
+
+inline void MTRand::seed( const uint32 oneSeed )
+{
+ // Seed the generator with a simple uint32
+ initialize(oneSeed);
+ reload();
+}
+
+
+inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength )
+{
+ // Seed the generator with an array of uint32's
+ // There are 2^19937-1 possible initial states. This function allows
+ // all of those to be accessed by providing at least 19937 bits (with a
+ // default seed length of N = 624 uint32's). Any bits above the lower 32
+ // in each element are discarded.
+ // Just call seed() if you want to get array from /dev/urandom
+ initialize(19650218UL);
+ register int i = 1;
+ register uint32 j = 0;
+ register int k = ( N > seedLength ? N : seedLength );
+ for( ; k; --k )
+ {
+ state[i] =
+ state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
+ state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
+ state[i] &= 0xffffffffUL;
+ ++i; ++j;
+ if( i >= N ) { state[0] = state[N-1]; i = 1; }
+ if( j >= seedLength ) j = 0;
+ }
+ for( k = N - 1; k; --k )
+ {
+ state[i] =
+ state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
+ state[i] -= i;
+ state[i] &= 0xffffffffUL;
+ ++i;
+ if( i >= N ) { state[0] = state[N-1]; i = 1; }
+ }
+ state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array
+ reload();
+}
+
+
+inline void MTRand::seed()
+{
+ // Seed the generator with an array from /dev/urandom if available
+ // Otherwise use a hash of time() and clock() values
+
+ // First try getting an array from /dev/urandom
+ FILE* urandom = fopen( "/dev/urandom", "rb" );
+ if( urandom )
+ {
+ uint32 bigSeed[N];
+ register uint32 *s = bigSeed;
+ register int i = N;
+ register bool success = true;
+ while( success && i-- )
+ success = fread( s++, sizeof(uint32), 1, urandom );
+ fclose(urandom);
+ if( success ) { seed( bigSeed, N ); return; }
+ }
+
+ // Was not successful, so use time() and clock() instead
+ seed( hash( time(NULL), clock() ) );
+}
+
+
+inline void MTRand::initialize( const uint32 seed )
+{
+ // Initialize generator state with seed
+ // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
+ // In previous versions, most significant bits (MSBs) of the seed affect
+ // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
+ register uint32 *s = state;
+ register uint32 *r = state;
+ register int i = 1;
+ *s++ = seed & 0xffffffffUL;
+ for( ; i < N; ++i )
+ {
+ *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
+ r++;
+ }
+}
+
+
+inline void MTRand::reload()
+{
+ // Generate N new values in state
+ // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
+ register uint32 *p = state;
+ register int i;
+ for( i = N - M; i--; ++p )
+ *p = twist( p[M], p[0], p[1] );
+ for( i = M; --i; ++p )
+ *p = twist( p[M-N], p[0], p[1] );
+ *p = twist( p[M-N], p[0], state[0] );
+
+ left = N, pNext = state;
+}
+
+
+inline MTRand::uint32 MTRand::hash( time_t t, clock_t c )
+{
+ // Get a uint32 from t and c
+ // Better than uint32(x) in case x is floating point in [0,1]
+ // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk)
+
+ static uint32 differ = 0; // guarantee time-based seeds will change
+
+ uint32 h1 = 0;
+ unsigned char *p = (unsigned char *) &t;
+ for( size_t i = 0; i < sizeof(t); ++i )
+ {
+ h1 *= UCHAR_MAX + 2U;
+ h1 += p[i];
+ }
+ uint32 h2 = 0;
+ p = (unsigned char *) &c;
+ for( size_t j = 0; j < sizeof(c); ++j )
+ {
+ h2 *= UCHAR_MAX + 2U;
+ h2 += p[j];
+ }
+ return ( h1 + differ++ ) ^ h2;
+}
+
+
+inline void MTRand::save( uint32* saveArray ) const
+{
+ register uint32 *sa = saveArray;
+ register const uint32 *s = state;
+ register int i = N;
+ for( ; i--; *sa++ = *s++ ) {}
+ *sa = left;
+}
+
+
+inline void MTRand::load( uint32 *const loadArray )
+{
+ register uint32 *s = state;
+ register uint32 *la = loadArray;
+ register int i = N;
+ for( ; i--; *s++ = *la++ ) {}
+ left = *la;
+ pNext = &state[N-left];
+}
+
+
+inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand )
+{
+ register const MTRand::uint32 *s = mtrand.state;
+ register int i = mtrand.N;
+ for( ; i--; os << *s++ << "\t" ) {}
+ return os << mtrand.left;
+}
+
+
+inline std::istream& operator>>( std::istream& is, MTRand& mtrand )
+{
+ register MTRand::uint32 *s = mtrand.state;
+ register int i = mtrand.N;
+ for( ; i--; is >> *s++ ) {}
+ is >> mtrand.left;
+ mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left];
+ return is;
+}
+};
+
+#endif // MERSENNETWISTER_H
+
+// Change log:
+//
+// v0.1 - First release on 15 May 2000
+// - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
+// - Translated from C to C++
+// - Made completely ANSI compliant
+// - Designed convenient interface for initialization, seeding, and
+// obtaining numbers in default or user-defined ranges
+// - Added automatic seeding from /dev/urandom or time() and clock()
+// - Provided functions for saving and loading generator state
+//
+// v0.2 - Fixed bug which reloaded generator one step too late
+//
+// v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
+//
+// v0.4 - Removed trailing newline in saved generator format to be consistent
+// with output format of built-in types
+//
+// v0.5 - Improved portability by replacing static const int's with enum's and
+// clarifying return values in seed(); suggested by Eric Heimburg
+// - Removed MAXINT constant; use 0xffffffffUL instead
+//
+// v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
+// - Changed integer [0,n] generator to give better uniformity
+//
+// v0.7 - Fixed operator precedence ambiguity in reload()
+// - Added access for real numbers in (0,1) and (0,n)
+//
+// v0.8 - Included time.h header to properly support time_t and clock_t
+//
+// v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
+// - Allowed for seeding with arrays of any length
+// - Added access for real numbers in [0,1) with 53-bit resolution
+// - Added access for real numbers from normal (Gaussian) distributions
+// - Increased overall speed by optimizing twist()
+// - Doubled speed of integer [0,n] generation
+// - Fixed out-of-range number generation on 64-bit machines
+// - Improved portability by substituting literal constants for long enum's
+// - Changed license from GNU LGPL to BSD
#ifndef PACKEDMATRIX_H
#define PACKEDMATRIX_H
-#include "PackedRow.h"
#include <algorithm>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
-//#define DEBUG_MATRIX
+#include "PackedRow.h"
-#ifndef uint
-#define uint unsigned int
-#endif
+//#define DEBUG_MATRIX
namespace MINISAT
{
+using namespace MINISAT;
class PackedMatrix
{
public:
PackedMatrix() :
- numRows(0)
+ mp(NULL)
+ , numRows(0)
, numCols(0)
- , mp(NULL)
{
}
private:
+ uint64_t* mp;
uint numRows;
uint numCols;
- uint64_t* mp;
-};
};
+}; //NAMESPACE MINISAT
+
#endif //PACKEDMATRIX_H
**************************************************************************************************/
#include "PackedRow.h"
+
namespace MINISAT
{
+using namespace MINISAT;
std::ostream& operator << (std::ostream& os, const PackedRow& m)
{
- for(uint i = 0; i < m.size*64; i++) {
+ for(uint32_t i = 0; i < m.size*64; i++) {
os << m[i];
}
os << " -- xor: " << m.is_true();
return (!std::equal(b.mp-1, b.mp+size, mp-1));
}
-uint PackedRow::popcnt() const
+uint32_t PackedRow::popcnt() const
{
- uint popcnt = 0;
- for (uint i = 0; i < size; i++) if (mp[i]) {
+ uint32_t popcnt = 0;
+ for (uint32_t i = 0; i < size; i++) if (mp[i]) {
uint64_t tmp = mp[i];
for (uint i2 = 0; i2 < 64; i2++) {
popcnt += (tmp & 1);
return popcnt;
}
-uint PackedRow::popcnt(const uint from) const
+uint32_t PackedRow::popcnt(const uint32_t from) const
{
- uint popcnt = 0;
- for (uint i = from/64; i != size; i++) if (mp[i]) {
+ uint32_t popcnt = 0;
+ for (uint32_t i = from/64; i != size; i++) if (mp[i]) {
uint64_t tmp = mp[i];
- uint i2;
+ uint32_t i2;
if (i == from/64) {
i2 = from%64;
tmp >>= i2;
bool final = !is_true_internal;
tmp_clause.clear();
- uint col = 0;
+ uint32_t col = 0;
bool wasundef = false;
- for (uint i = 0; i < size; i++) for (uint i2 = 0; i2 < 64; i2++) {
+ for (uint32_t i = 0; i < size; i++) for (uint32_t i2 = 0; i2 < 64; i2++) {
if ((mp[i] >> i2) &1) {
- const uint& var = col_to_var_original[col];
- assert(var != UINT_MAX);
+ const Var& var = col_to_var_original[col];
+ assert(var != std::numeric_limits<Var>::max());
const lbool& val = assigns[var];
const bool val_bool = val.getBool();
} else
assert(!final);
}
-};
+
+}; //NAMESPACE MINISAT
//#define DEBUG_ROW
#include <vector>
-#include <limits.h>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
#include "SolverTypes.h"
-#include "mtl/Vec.h"
+#include "Vec.h"
#include <string.h>
#include <iostream>
#include <algorithm>
-
+#include <limits>
#ifndef uint
#define uint unsigned int
#endif
+using std::vector;
+
namespace MINISAT
{
-
-using std::vector;
+using namespace MINISAT;
class PackedMatrix;
assert(b.size == size);
#endif
- for (uint i = 0; i != size; i++) {
+ for (uint32_t i = 0; i != size; i++) {
*(mp + i) ^= *(b.mp + i);
}
assert(b.size == size);
#endif
- for (uint i = 0; i != 2*size+1; i++) {
+ for (uint32_t i = 0; i != 2*size+1; i++) {
*(mp + i) ^= *(b.mp + i);
}
}
- uint popcnt() const;
- uint popcnt(uint from) const;
+ uint32_t popcnt() const;
+ uint32_t popcnt(uint32_t from) const;
bool popcnt_is_one() const
{
char popcount = 0;
- for (uint i = 0; i != size; i++) {
+ for (uint32_t i = 0; i != size; i++) {
uint64_t tmp = mp[i];
while(tmp) {
popcount += tmp & 1;
return popcount == 1;
}
- bool popcnt_is_one(uint from) const
+ bool popcnt_is_one(uint32_t from) const
{
from++;
tmp >>= from%64;
if (tmp) return false;
- for (uint i = from/64+1; i != size; i++)
+ for (uint32_t i = from/64+1; i != size; i++)
if (mp[i]) return false;
return true;
}
inline const bool isZero() const
{
- for (uint i = 0; i != size; i++) {
+ for (uint32_t i = 0; i != size; i++) {
if (mp[i]) return false;
}
return true;
memset(mp, 0, sizeof(uint64_t)*size);
}
- inline void clearBit(const uint i)
+ inline void clearBit(const uint32_t i)
{
mp[i/64] &= ~((uint64_t)1 << (i%64));
}
inline void invert_is_true(const bool b = true)
{
- is_true_internal ^= b;
+ is_true_internal ^= (uint64_t)b;
}
- inline void setBit(const uint i)
+ inline void setBit(const uint32_t i)
{
mp[i/64] |= ((uint64_t)1 << (i%64));
}
uint64_t * __restrict mp1 = mp-1;
uint64_t * __restrict mp2 = b.mp-1;
- uint i = 2*(size+1);
+ uint32_t i = 2*(size+1);
while(i != 0) {
std::swap(*mp1, *mp2);
}
}
- inline const bool operator[](const uint& i) const
+ inline const bool operator[](const uint32_t& i) const
{
#ifdef DEBUG_ROW
assert(size*64 > i);
}
template<class T>
- void set(const T& v, const vector<uint16_t>& var_to_col, const uint matrix_size)
+ void set(const T& v, const vector<uint16_t>& var_to_col, const uint32_t matrix_size)
{
assert(size == (matrix_size/64) + ((bool)(matrix_size % 64)));
//mp = new uint64_t[size];
setZero();
- for (uint i = 0; i != v.size(); i++) {
- const uint toset_var = var_to_col[v[i].var()];
- assert(toset_var != UINT_MAX);
+ for (uint32_t i = 0; i != v.size(); i++) {
+ const uint32_t toset_var = var_to_col[v[i].var()];
+ assert(toset_var != std::numeric_limits<uint32_t>::max());
setBit(toset_var);
}
assert(size > 0);
#endif
- for(uint i = var; i != size*64; i++)
+ for(uint32_t i = var; i != size*64; i++)
if (this->operator[](i)) return i;
- return ULONG_MAX;
+ return std::numeric_limits<unsigned long int>::max();
}
friend std::ostream& operator << (std::ostream& os, const PackedRow& m);
- PackedRow(const uint _size, uint64_t* const _mp) :
- size(_size)
- , mp(_mp+1)
+private:
+ friend class PackedMatrix;
+ PackedRow(const uint32_t _size, uint64_t* const _mp) :
+ mp(_mp+1)
, is_true_internal(*_mp)
+ , size(_size)
{}
-
-private:
- friend class PackedMatrix;
- const uint size;
+
uint64_t* __restrict const mp;
uint64_t& is_true_internal;
+ const uint32_t size;
};
std::ostream& operator << (std::ostream& os, const PackedRow& m);
-};
+
+}; //NAMESPACE MINISAT
#endif //PACKEDROW_H
--- /dev/null
+/***********************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************************************/
+
+#include "PartFinder.h"
+
+#include "Solver.h"
+#include "Gaussian.h"
+#include "GaussianConfig.h"
+#include "ClauseCleaner.h"
+#include "time_mem.h"
+#include "VarReplacer.h"
+
+#include <set>
+#include <map>
+#include <iomanip>
+#include <math.h>
+#include "FailedVarSearcher.h"
+using std::set;
+using std::map;
+
+//#define VERBOSE_DEBUG
+
+using std::cout;
+using std::endl;
+
+//#define PART_FINDING
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+PartFinder::PartFinder(Solver& _solver) :
+ solver(_solver)
+{
+}
+
+const bool PartFinder::findParts()
+{
+ assert(solver.performReplace);
+
+ double time = cpuTime();
+
+ table.clear();
+ table.resize(solver.nVars(), std::numeric_limits<uint32_t>::max());
+ reverseTable.clear();
+ part_no = 0;
+
+ solver.clauseCleaner->removeAndCleanAll(true);
+ if (solver.ok == false) return false;
+ while (solver.varReplacer->getNewToReplaceVars() > 0) {
+ if (solver.performReplace && !solver.varReplacer->performReplace(true))
+ return false;
+ solver.clauseCleaner->removeAndCleanAll(true);
+ if (solver.ok == false) return false;
+ }
+ assert(solver.varReplacer->getClauses().size() == 0);
+
+ addToPart(solver.clauses);
+ addToPart(solver.binaryClauses);
+ addToPart(solver.xorclauses);
+
+ const uint parts = setParts();
+
+ #ifndef NDEBUG
+ for (map<uint, vector<Var> >::const_iterator it = reverseTable.begin(); it != reverseTable.end(); it++) {
+ for (uint i2 = 0; i2 < it->second.size(); i2++) {
+ assert(table[(it->second)[i2]] == it->first);
+ }
+ }
+ #endif
+
+ if (solver.verbosity >= 2 || (solver.verbosity >=1 && parts > 1)) {
+ std::cout << "c | Found parts: " << std::setw(10) << parts
+ << " time: " << std::setprecision(2) << std::setw(4) << cpuTime() - time
+ << " s" << std::setw(28) << " |" << std::endl;
+ }
+
+ return true;
+}
+
+template<class T>
+void PartFinder::addToPart(const vec<T*>& cs)
+{
+ set<uint> tomerge;
+ vector<Var> newSet;
+ for (T* const* c = cs.getData(), * const*end = c + cs.size(); c != end; c++) {
+ if ((*c)->learnt()) continue;
+ tomerge.clear();
+ newSet.clear();
+ for (const Lit *l = (*c)->getData(), *end2 = l + (*c)->size(); l != end2; l++) {
+ if (table[l->var()] != std::numeric_limits<uint32_t>::max())
+ tomerge.insert(table[l->var()]);
+ else
+ newSet.push_back(l->var());
+ }
+ if (tomerge.size() == 1) {
+ //no trees to merge, only merge the clause into one tree
+
+ const uint into = *tomerge.begin();
+ map<uint, vector<Var> >::iterator intoReverse = reverseTable.find(into);
+ for (uint i = 0; i < newSet.size(); i++) {
+ intoReverse->second.push_back(newSet[i]);
+ table[newSet[i]] = into;
+ }
+ continue;
+ }
+
+ for (set<uint>::iterator it = tomerge.begin(); it != tomerge.end(); it++) {
+ newSet.insert(newSet.end(), reverseTable[*it].begin(), reverseTable[*it].end());
+ reverseTable.erase(*it);
+ }
+
+ for (uint i = 0; i < newSet.size(); i++)
+ table[newSet[i]] = part_no;
+ reverseTable[part_no] = newSet;
+ part_no++;
+ }
+}
+
+const uint PartFinder::setParts()
+{
+ vector<uint> numClauseInPart(part_no, 0);
+ vector<uint> sumLitsInPart(part_no, 0);
+
+ calcIn(solver.clauses, numClauseInPart, sumLitsInPart);
+ calcIn(solver.binaryClauses, numClauseInPart, sumLitsInPart);
+ calcIn(solver.xorclauses, numClauseInPart, sumLitsInPart);
+
+ uint parts = 0;
+ for (uint i = 0; i < numClauseInPart.size(); i++) {
+ if (sumLitsInPart[i] == 0) continue;
+ if (solver.verbosity >= 2 || ( solver.verbosity >= 1 && reverseTable.size() > 1) ) {
+ std::cout << "c | Found part " << std::setw(8) << i
+ << " vars: " << std::setw(10) << reverseTable[i].size()
+ << " clauses:" << std::setw(10) << numClauseInPart[i]
+ << " lits size:" << std::setw(10) << sumLitsInPart[i] << std::endl;
+ }
+ parts++;
+ }
+
+ if (parts > 1) {
+ #ifdef VERBOSE_DEBUG
+ for (map<uint, vector<Var> >::iterator it = reverseTable.begin(), end = reverseTable.end(); it != end; it++) {
+ cout << "-- set begin --" << endl;
+ for (vector<Var>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
+ cout << *it2 << ", ";
+ }
+ cout << "-------" << endl;
+ }
+ #endif
+ }
+
+ return parts;
+}
+
+template<class T>
+void PartFinder::calcIn(const vec<T*>& cs, vector<uint>& numClauseInPart, vector<uint>& sumLitsInPart)
+{
+ for (T*const* c = cs.getData(), *const*end = c + cs.size(); c != end; c++) {
+ if ((*c)->learnt()) continue;
+ T& x = **c;
+ const uint part = table[x[0].var()];
+ assert(part < part_no);
+
+ //for stats
+ numClauseInPart[part]++;
+ sumLitsInPart[part] += x.size();
+ }
+}
+
+}; //NAMESPACE MINISAT
--- /dev/null
+/***********************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************************************/
+
+#ifndef PARTFINDER_H
+#define PARTFINDER_H
+
+#include <vector>
+#include <map>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include "Clause.h"
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+class Solver;
+
+using std::map;
+using std::vector;
+using std::pair;
+
+class PartFinder {
+
+ public:
+ PartFinder(Solver& solver);
+ const bool findParts();
+
+ const map<uint32_t, vector<Var> >& getReverseTable() const; // part->var
+ const uint32_t getVarPart(const Var var) const;
+ const vector<uint32_t>& getTable() const; //var -> part
+ const vector<Var>& getPartVars(const uint32_t part);
+
+ private:
+ const uint setParts();
+ template<class T>
+ void addToPart(const vec<T*>& cs);
+
+ struct mysorter
+ {
+ bool operator () (const pair<uint, uint>& left, const pair<uint, uint>& right)
+ {
+ return left.second < right.second;
+ }
+ };
+
+ //const bool findParts(vector<Var>& xorFingerprintInMatrix, vector<XorClause*>& xorsInMatrix);
+ template<class T>
+ void calcIn(const vec<T*>& cs, vector<uint>& numClauseInPart, vector<uint>& sumLitsInPart);
+
+ map<uint32_t, vector<Var> > reverseTable; //part -> vars
+ vector<uint32_t> table; //var -> part
+ uint32_t part_no;
+
+ Solver& solver;
+};
+
+inline const map<uint32_t, vector<Var> >& PartFinder::getReverseTable() const
+{
+ return reverseTable;
+}
+
+inline const vector<Var>& PartFinder::getTable() const
+{
+ return table;
+}
+
+inline const uint32_t PartFinder::getVarPart(const Var var) const
+{
+ return table[var];
+}
+
+inline const vector<Var>& PartFinder::getPartVars(const uint32_t part)
+{
+ return reverseTable[part];
+}
+
+}; //NAMESPACE MINISAT
+
+#endif //PARTFINDER_H
--- /dev/null
+/***********************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************************************/
+
+#include "PartHandler.h"
+#include "VarReplacer.h"
+#include <iostream>
+#include <assert.h>
+
+//#define VERBOSE_DEBUG
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+PartHandler::PartHandler(Solver& s) :
+ solver(s)
+{
+}
+
+
+const bool PartHandler::handle()
+{
+ if (solver.performReplace == false)
+ return true;
+
+ PartFinder partFinder(solver);
+ if (!partFinder.findParts())
+ return false;
+
+ uint32_t num_parts = partFinder.getReverseTable().size();
+ if (num_parts == 1)
+ return true;
+
+ map<uint32_t, vector<Var> > reverseTable = partFinder.getReverseTable();
+ assert(num_parts == partFinder.getReverseTable().size());
+
+ vector<pair<uint32_t, uint32_t> > sizes;
+ for (map<uint32_t, vector<Var> >::iterator it = reverseTable.begin(); it != reverseTable.end(); it++)
+ sizes.push_back(std::make_pair(it->first, (uint32_t)it->second.size()));
+
+ std::sort(sizes.begin(), sizes.end(), sort_pred());
+ assert(sizes.size() > 1);
+
+ for (uint32_t it = 0; it < sizes.size()-1; it++) {
+ uint32_t part = sizes[it].first;
+ vector<Var> vars = reverseTable[part];
+ if (solver.verbosity >= 1)
+ std::cout << "c Solving part " << part << std::endl;
+
+ Solver newSolver;
+ newSolver.mtrand.seed(solver.mtrand.randInt());
+ newSolver.random_var_freq = solver.random_var_freq;
+ newSolver.var_decay = solver.var_decay;
+ newSolver.verbosity = solver.verbosity;
+ newSolver.restrictedPickBranch = solver.restrictedPickBranch;
+ newSolver.greedyUnbound = solver.greedyUnbound;
+ newSolver.findNormalXors = solver.findNormalXors;
+ newSolver.findBinaryXors = solver.findBinaryXors;
+ newSolver.regularlyFindBinaryXors = solver.regularlyFindBinaryXors;
+ newSolver.conglomerateXors = solver.conglomerateXors;
+ newSolver.schedSimplification = solver.schedSimplification;
+ newSolver.performReplace = solver.performReplace;
+ newSolver.failedVarSearch = solver.failedVarSearch;
+ newSolver.gaussconfig.dontDisable = solver.gaussconfig.dontDisable;
+ newSolver.heuleProcess = solver.heuleProcess;
+ newSolver.doSubsumption = solver.doSubsumption;
+ newSolver.doPartHandler = solver.doPartHandler;
+ newSolver.fixRestartType = solver.fixRestartType;
+ newSolver.var_inc = solver.var_inc;
+ newSolver.polarity_mode = Solver::polarity_manual;
+ std::sort(vars.begin(), vars.end());
+ uint32_t i2 = 0;
+ for (Var var = 0; var < solver.nVars(); var++) {
+ if (i2 < vars.size() && vars[i2] == var) {
+ newSolver.newVar(solver.decision_var[var]);
+ newSolver.activity[var] = solver.activity[var];
+ newSolver.defaultPolarities[var] = solver.polarity[var];
+ newSolver.order_heap.update(var);
+ assert(partFinder.getVarPart(var) == part);
+ if (solver.decision_var[var]) {
+ solver.setDecisionVar(var, false);
+ if (solver.decision_var[var]) decisionVarRemoved.push(var);
+ }
+ i2++;
+ } else {
+ assert(partFinder.getVarPart(var) != part);
+ newSolver.newVar(false);
+ }
+ }
+ solver.order_heap.filter(Solver::VarFilter(solver));
+
+ assert(solver.varReplacer->getClauses().size() == 0);
+ moveClauses(solver.clauses, newSolver, part, partFinder);
+ moveClauses(solver.binaryClauses, newSolver, part, partFinder);
+ moveClauses(solver.xorclauses, newSolver, part, partFinder);
+ moveLearntClauses(solver.binaryClauses, newSolver, part, partFinder);
+ moveLearntClauses(solver.learnts, newSolver, part, partFinder);
+ assert(checkClauseMovement(newSolver, part, partFinder));
+
+ lbool status = newSolver.solve();
+ if (status == l_False)
+ return false;
+ assert(status != l_Undef);
+
+ for (Var var = 0; var < newSolver.nVars(); var++) {
+ if (newSolver.model[var] != l_Undef) {
+ assert(solver.assigns[var] == l_Undef);
+ }
+ }
+
+ assert(newSolver.decisionLevel() == 0);
+ for (uint32_t i = 0; i < newSolver.trail.size(); i++) {
+ solver.uncheckedEnqueue(newSolver.trail[i]);
+ }
+ solver.ok = (solver.propagate() == NULL);
+ assert(solver.ok);
+
+ for (Var var = 0; var < newSolver.nVars(); var++) {
+ if (newSolver.model[var] != l_Undef) {
+ assert(savedState[var] == l_Undef);
+ assert(partFinder.getVarPart(var) == part);
+ savedState[var] = newSolver.model[var];
+ }
+ }
+
+ if (solver.verbosity >= 1)
+ std::cout << "c Solved part" << std::endl;
+ }
+ if (solver.verbosity >= 1)
+ std::cout << "c Coming back to original instance" << std::endl;
+
+ solver.order_heap.filter(Solver::VarFilter(solver));
+
+ //Checking that all variables that are not in the remaining part are all non-decision vars, and none have been set
+ for (Var var = 0; var < solver.nVars(); var++) {
+ if (savedState[var] != l_Undef) {
+ assert(solver.decision_var[var] == false);
+ assert(solver.assigns[var] == l_Undef || solver.level[var] == 0);
+ }
+ }
+
+ //Checking that all remaining clauses contain only variables that are in the remaining part
+ assert(checkClauseMovement(solver, sizes[sizes.size()-1].first, partFinder));
+
+ return true;
+}
+
+const bool PartHandler::checkClauseMovement(const Solver& thisSolver, const uint32_t part, const PartFinder& partFinder) const
+{
+ if (!checkOnlyThisPart(thisSolver.clauses, part, partFinder))
+ return false;
+ if (!checkOnlyThisPart(thisSolver.learnts, part, partFinder))
+ return false;
+ if (!checkOnlyThisPart(thisSolver.binaryClauses, part, partFinder))
+ return false;
+ if (!checkOnlyThisPart(thisSolver.xorclauses, part, partFinder))
+ return false;
+
+ return true;
+}
+
+template<class T>
+const bool PartHandler::checkOnlyThisPart(const vec<T*>& cs, const uint32_t part, const PartFinder& partFinder) const
+{
+ for(T * const*it = cs.getData(), * const*end = it + cs.size(); it != end; it++) {
+ const T& c = **it;
+ for(const Lit *l = c.getData(), *end2 = l + c.size(); l != end2; l++) {
+ if (partFinder.getVarPart(l->var()) != part) return false;
+ }
+ }
+
+ return true;
+}
+
+void PartHandler::moveClauses(vec<Clause*>& cs, Solver& newSolver, const uint32_t part, PartFinder& partFinder)
+{
+ Clause **i, **j, **end;
+ for (i = j = cs.getData(), j = i , end = i + cs.size(); i != end; i++) {
+ if ((**i).learnt() || partFinder.getVarPart((**i)[0].var()) != part) {
+ *j++ = *i;
+ continue;
+ }
+ solver.detachClause(**i);
+ vec<Lit> cs((*i)->size());
+ std::copy((**i).getData(), (**i).getDataEnd(), cs.getData());
+ newSolver.addClause(cs, (**i).getGroup());
+ //NOTE: we need the CS because otherwise, the addClause could have changed **i, which we need to re-add later!
+ clausesRemoved.push(*i);
+ }
+ cs.shrink(i-j);
+}
+
+void PartHandler::moveClauses(vec<XorClause*>& cs, Solver& newSolver, const uint32_t part, PartFinder& partFinder)
+{
+ XorClause **i, **j, **end;
+ for (i = j = cs.getData(), end = i + cs.size(); i != end; i++) {
+ if (partFinder.getVarPart((**i)[0].var()) != part) {
+ *j++ = *i;
+ continue;
+ }
+ solver.detachClause(**i);
+ vec<Lit> cs((*i)->size());
+ for (uint32_t i2 = 0; i2 < (*i)->size(); i2++)
+ cs[i2] = (**i)[i2].unsign();
+ newSolver.addXorClause(cs, (**i).xor_clause_inverted(), (**i).getGroup());
+ //NOTE: we need the CS because otherwise, the addXorClause could have changed **i, which we need to re-add later!
+ xorClausesRemoved.push(*i);
+ }
+ cs.shrink(i-j);
+}
+
+void PartHandler::moveLearntClauses(vec<Clause*>& cs, Solver& newSolver, const uint32_t part, PartFinder& partFinder)
+{
+ Clause **i, **j, **end;
+ for (i = j = cs.getData(), end = i + cs.size() ; i != end; i++) {
+ if (!(**i).learnt()) {
+ *j++ = *i;
+ continue;
+ }
+
+ Clause& c = **i;
+ assert(c.size() > 0);
+ uint32_t clause_part = partFinder.getVarPart(c[0].var());
+ bool removed = false;
+ for (const Lit* l = c.getData(), *end = l + c.size(); l != end; l++) {
+ if (partFinder.getVarPart(l->var()) != clause_part) {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Learnt clause in both parts!" << std::endl;
+ #endif
+
+ removed = true;
+ solver.removeClause(c);
+ break;
+ }
+ }
+ if (removed) continue;
+ if (clause_part == part) {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Learnt clause in this part!" << std::endl;
+ #endif
+
+ solver.detachClause(c);
+ newSolver.addLearntClause(c, c.getGroup(), c.activity());
+ free(*i);
+ } else {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Learnt clause in other part!" << std::endl;
+ #endif
+
+ *j++ = *i;
+ }
+ }
+ cs.shrink(i-j);
+}
+
+void PartHandler::addSavedState()
+{
+ for (Var var = 0; var < savedState.size(); var++) {
+ if (savedState[var] != l_Undef) {
+ assert(solver.assigns[var] == l_Undef || (solver.assigns[var] == savedState[var] && solver.level[var] == 0));
+ //decision level should NOT be 0.... TODO
+ solver.uncheckedEnqueue(Lit(var, savedState[var] == l_False));
+ assert(solver.assigns[var] == savedState[var]);
+ savedState[var] = l_Undef;
+ }
+ }
+
+ for (uint32_t var = 0; var < decisionVarRemoved.size(); var++)
+ solver.setDecisionVar(var, true);
+ decisionVarRemoved.clear();
+}
+
+void PartHandler::readdRemovedClauses()
+{
+ for (Clause **it = clausesRemoved.getData(), **end = clausesRemoved.getDataEnd(); it != end; it++) {
+ solver.addClause(**it, (*it)->getGroup());
+ assert(solver.ok);
+ }
+ clausesRemoved.clear();
+
+ for (XorClause **it = xorClausesRemoved.getData(), **end = xorClausesRemoved.getDataEnd(); it != end; it++) {
+ for (Lit *l = (*it)->getData(), *end2 = (*it)->getDataEnd(); l != end2; l++) {
+ *l = l->unsign();
+ }
+ solver.addXorClause(**it, (*it)->getGroup());
+ assert(solver.ok);
+ }
+ xorClausesRemoved.clear();
+}
+
+}; //NAMESPACE MINISAT
--- /dev/null
+/***********************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************************************/
+
+#ifndef PARTHANDLER_H
+#define PARTHANDLER_H
+
+#include "Solver.h"
+#include "PartFinder.h"
+#include "Vec.h"
+#include "SolverTypes.h"
+
+#include <map>
+#include <vector>
+using std::map;
+using std::vector;
+using std::pair;
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+class PartHandler
+{
+ public:
+ PartHandler(Solver& solver);
+ const bool handle();
+ const vec<lbool>& getSavedState();
+ void newVar();
+ void addSavedState();
+ void readdRemovedClauses();
+
+ private:
+ struct sort_pred {
+ bool operator()(const std::pair<int,int> &left, const std::pair<int,int> &right) {
+ return left.second < right.second;
+ }
+ };
+
+ //For moving clauses
+ void moveClauses(vec<XorClause*>& cs, Solver& newSolver, const uint32_t part, PartFinder& partFinder);
+ void moveClauses(vec<Clause*>& cs, Solver& newSolver, const uint32_t part, PartFinder& partFinder);
+ void moveLearntClauses(vec<Clause*>& cs, Solver& newSolver, const uint32_t part, PartFinder& partFinder);
+
+ //Checking moved clauses
+ const bool checkClauseMovement(const Solver& thisSolver, const uint32_t part, const PartFinder& partFinder) const;
+ template<class T>
+ const bool checkOnlyThisPart(const vec<T*>& cs, const uint32_t part, const PartFinder& partFinder) const;
+
+ Solver& solver;
+ vec<lbool> savedState;
+ vec<Var> decisionVarRemoved; //variables whose decision-ness has been removed
+ vec<Clause*> clausesRemoved;
+ vec<XorClause*> xorClausesRemoved;
+};
+
+inline const vec<lbool>& PartHandler::getSavedState()
+{
+ return savedState;
+}
+
+inline void PartHandler::newVar()
+{
+ savedState.push(l_Undef);
+}
+
+}; //NAMESPACE MINISAT
+
+#endif //PARTHANDLER_H
#include "Solver.h"
//#define VERBOSE_DEBUG
+//#define PRINT_VARS
namespace MINISAT
{
using namespace MINISAT;
-RestartTypeChooser::RestartTypeChooser(const Solver* const _s) :
- S(_s)
+RestartTypeChooser::RestartTypeChooser(const Solver& s) :
+ solver(s)
, topX(100)
- , limit(30)
+ , limit(40)
{
}
-const RestartType RestartTypeChooser::choose()
+void RestartTypeChooser::addInfo()
{
firstVarsOld = firstVars;
calcHeap();
std::cout << " Same vars in first&second first 100: " << sameIn << std::endl;
#endif
sameIns.push_back(sameIn);
- } else
- return static_restart;
+ }
#ifdef VERBOSE_DEBUG
- std::cout << "Avg same vars in first&second first 100: " << avg() << std::endl;
+ std::cout << "Avg same vars in first&second first 100: " << avg() << " standard Deviation:" << stdDeviation(sameIns) <<std::endl;
#endif
-
- if (avg() > (double)limit)
+}
+
+const RestartType RestartTypeChooser::choose()
+{
+ if (countVarsDegreeStDev().second < 80 &&
+ (avg() > (double)limit || ((avg() > (double)(limit*0.9) && stdDeviation(sameIns) < 5))))
return static_restart;
else
return dynamic_restart;
return (sum/(double)sameIns.size());
}
+const double RestartTypeChooser::stdDeviation(vector<uint32_t>& measure) const
+{
+ double average = avg();
+ double variance = 0.0;
+ for (uint i = 0; i != measure.size(); i++)
+ variance += pow((double)measure[i]-average, 2);
+ variance /= (double)measure.size();
+
+ return sqrt(variance);
+}
+
void RestartTypeChooser::calcHeap()
{
firstVars.clear();
firstVars.reserve(topX);
- #ifdef VERBOSE_DEBUG
+ #ifdef PRINT_VARS
std::cout << "First vars:" << std::endl;
#endif
- Heap<Solver::VarOrderLt> tmp(S->order_heap);
+ Heap<Solver::VarOrderLt> tmp(solver.order_heap);
uint32_t thisTopX = std::min(tmp.size(), topX);
for (uint32_t i = 0; i != thisTopX; i++) {
- #ifdef VERBOSE_DEBUG
+ #ifdef PRINT_VARS
std::cout << tmp.removeMin()+1 << ", ";
#endif
firstVars.push_back(tmp.removeMin());
}
- #ifdef VERBOSE_DEBUG
+ #ifdef PRINT_VARS
std::cout << std::endl;
#endif
}
-};
+const std::pair<double, double> RestartTypeChooser::countVarsDegreeStDev() const
+{
+ vector<uint32_t> degrees;
+ degrees.resize(solver.nVars(), 0);
+ addDegrees(solver.clauses, degrees);
+ addDegrees(solver.binaryClauses, degrees);
+ addDegrees(solver.xorclauses, degrees);
+ uint32_t sum = 0;
+ uint32_t *i = °rees[0], *j = i;
+ for (uint32_t *end = i + degrees.size(); i != end; i++) {
+ if (*i != 0) {
+ sum += *i;
+ *j++ = *i;
+ }
+ }
+ degrees.resize(degrees.size() - (i-j));
+
+ double avg = (double)sum/(double)degrees.size();
+ double stdDev = stdDeviation(degrees);
+
+ #ifdef VERBOSE_DEBUG
+ std::cout << "varsDegree avg:" << avg << " stdDev:" << stdDev << std::endl;
+ #endif
+
+ return std::make_pair(avg, stdDev);
+}
+
+template<class T>
+void RestartTypeChooser::addDegrees(const vec<T*>& cs, vector<uint32_t>& degrees) const
+{
+ for (T * const*c = cs.getData(), * const*end = c + cs.size(); c != end; c++) {
+ T& cl = **c;
+ if (cl.learnt()) continue;
+
+ for (const Lit *l = cl.getData(), *end2 = l + cl.size(); l != end2; l++) {
+ degrees[l->var()]++;
+ }
+ }
+}
+
+template void RestartTypeChooser::addDegrees(const vec<Clause*>& cs, vector<uint32_t>& degrees) const;
+template void RestartTypeChooser::addDegrees(const vec<XorClause*>& cs, vector<uint32_t>& degrees) const;
+
+}; //NAMESPACE MINISAT
+
#ifndef RESTARTTYPECHOOSER_H
#define RESTARTTYPECHOOSER_H
-#include "SolverTypes.h"
+#include "Solver.h"
#include <vector>
-#include <sys/types.h>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include "SolverTypes.h"
+
using std::vector;
namespace MINISAT
{
+using namespace MINISAT;
class Solver;
class RestartTypeChooser
{
public:
- RestartTypeChooser(const Solver* const S);
+ RestartTypeChooser(const Solver& s);
+ void addInfo();
const RestartType choose();
+ void reset();
private:
void calcHeap();
const double avg() const;
+ const std::pair<double, double> countVarsDegreeStDev() const;
+ const double stdDeviation(vector<uint32_t>& measure) const;
- const Solver* const S;
+ template<class T>
+ void addDegrees(const vec<T*>& cs, vector<uint32_t>& degrees) const;
+
+ const Solver& solver;
const uint32_t topX;
const uint32_t limit;
vector<Var> sameIns;
vector<Var> firstVars, firstVarsOld;
};
-};
+inline void RestartTypeChooser::reset()
+{
+ sameIns.clear();
+}
+
+}; //NAMESPACE MINISAT
#endif //RESTARTTYPECHOOSER_H
--- /dev/null
+/*
+Please see LICENSE-CPOL.html in the root directory for the licencing of this file.
+Originally by: cppnow
+Link: http://www.codeproject.com/KB/cpp/smallptr.aspx
+*/
+
+#include "SmallPtr.h"
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+uintptr_t sptr_base::_segs = 1;
+//boost::mutex sptr_base::_m;
+uintptr_t sptr_base::_seg_map[sptr_base::ALIGNMENT] = { 0 };
+
+}; //NAMESPACE MINISAT
--- /dev/null
+/*
+Please see LICENSE-CPOL.html in the root directory for the licencing of this file.
+Originally by: cppnow
+Link: http://www.codeproject.com/KB/cpp/smallptr.aspx
+*/
+
+#ifndef __SMALL_PTR_H__
+#define __SMALL_PTR_H__
+
+//#include <boost/static_assert.hpp>
+
+#include <cstring>
+#include <stdlib.h>
+#include "singleton.hpp"
+//#include <boost/thread/mutex.hpp>
+//#include <boost/thread/locks.hpp>
+
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#define is_n_aligned(T, N) ((sizeof(T) % (N)) == 0)
+
+#ifdef WIN32
+# ifdef WIN64
+# define USE64
+# else
+# define USE32
+# endif
+#endif
+
+#ifdef __GNUG__
+# if defined(__amd64__) || defined(__x86_64__)
+# define USE64
+# elif defined(__i386__)
+# define USE32
+# endif
+#endif
+
+#include <exception>
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+class bad_alignment : public std::exception
+{
+public:
+ bad_alignment(const char *const& w) {}
+};
+class bad_segment : public std::exception
+{
+public:
+ bad_segment(const char *const& w) {}
+};
+
+class sptr_base
+{
+protected:
+ static const uint32_t ALIGNMENT_BITS = 2;
+ static const uint32_t ALIGNMENT = (1<<ALIGNMENT_BITS);
+ static const uintptr_t ALIGNMENT_MASK = ALIGNMENT - 1;
+
+protected:
+ static uintptr_t _seg_map[ALIGNMENT];
+ static uintptr_t _segs;
+ //static boost::mutex _m;
+
+ inline static uintptr_t ptr2seg(uintptr_t p)
+ {
+ p &= ~0xFFFFFFFFULL; // Keep only high part
+ uintptr_t s = _segs;
+ uintptr_t i = 0;
+ for (; i < s; ++i)
+ if (_seg_map[i] == p)
+ return i;
+
+ // Not found - now we do it the "right" way (mutex and all)
+ //boost::lock_guard<boost::mutex> lock(_m);
+ for (i = 0; i < s; ++i)
+ if (_seg_map[i] == p)
+ return i;
+
+ i = _segs++;
+ if (_segs > ALIGNMENT) {
+ //throw bad_segment("Segment out of range");
+ exit(-1);
+ }
+
+ _seg_map[i] = p;
+ return i;
+ }
+
+};
+
+template<class TYPE>
+class sptr : public sptr_base
+{
+public:
+ typedef TYPE type;
+ typedef TYPE* native_pointer_type;
+ typedef const TYPE* const_native_pointer_type;
+
+ sptr() throw()
+ : _ptr(0)
+ {}
+
+ // Copy constructor
+ sptr(const sptr<TYPE>& o) throw()
+ : _ptr(o._ptr)
+ {
+ }
+
+ // Copy from a related pointer type
+ // Although just copying _ptr would be more efficient - it may
+ // also be wrong - e.g. multiple inheritence
+ template<class O>
+ sptr(const sptr<O>& o)
+ : _ptr(encode(static_cast<TYPE*>(o.get())))
+ {
+ }
+
+ template<class O>
+ sptr(const O* p)
+ : _ptr(encode(static_cast<const TYPE*>(p)))
+ {
+ }
+
+ sptr<TYPE>& operator=(const sptr<TYPE>& o) throw()
+ {
+ _ptr = o._ptr;
+ return *this;
+ }
+
+ template<class O>
+ sptr<TYPE>& operator=(const sptr<O>& o)
+ {
+ _ptr = encode(static_cast<const TYPE*>(o.get()));
+ return *this;
+ }
+
+private:
+ inline uint32_t encode(const_native_pointer_type ptr) const
+ {
+#ifdef USE64
+
+ uintptr_t p = reinterpret_cast<uintptr_t>(ptr);
+
+ if ((p & ALIGNMENT_MASK) != 0) {
+ //throw bad_alignment("Pointer is not aligned");
+ exit(-1);
+ }
+
+ return (uint32_t)(ptr2seg(p) + p);
+
+#else // 32 bit machine
+ return reinterpret_cast<uint32_t>(ptr);
+#endif
+ }
+
+ inline native_pointer_type decode(uint32_t e) const
+ {
+#ifdef USE64
+ uintptr_t el = e;
+ uintptr_t ptr = (_seg_map[el & ALIGNMENT_MASK] + el) & ~ALIGNMENT_MASK;
+
+ return reinterpret_cast<native_pointer_type>(ptr);
+#else
+ return reinterpret_cast<native_pointer_type>(e);
+#endif
+ }
+
+ void check_alignment() const
+ {
+ //BOOST_STATIC_ASSERT(is_n_aligned(TYPE, ALIGNMENT));
+ }
+
+ void inc_sptr(uint32_t& e, uintptr_t offset = 1)
+ {
+ check_alignment();
+#ifdef USE64
+ uintptr_t el = e;
+ uintptr_t seg = el & ALIGNMENT_MASK;
+ el += offset*ALIGNMENT;
+
+ // check for overflow
+ if (el > 0xFFFFFFFFULL)
+ return encode(decode(e)+1);
+ e = (uint32_t)el;
+#else
+ e+= (uint32_t)offset;
+#endif
+ }
+
+ void dec_sptr(uint32_t& e, size_t offset = 1)
+ {
+ check_alignment();
+#ifdef USE64
+ uintptr_t el = e;
+ uintptr_t seg = el & ALIGNMENT_MASK;
+ e-= offset*ALIGNMENT;
+
+ // check for underflow
+ if (el > 0xFFFFFFFFULL)
+ return encode(decode(e)-1);
+ e = (uint32_t)el;
+#else
+ e -= (uint32_t)offset;
+#endif
+ }
+public:
+
+ TYPE* get() const throw() { return decode(_ptr); }
+
+ // Pointer operators
+
+ TYPE& operator*() { return *decode(_ptr); }
+ const TYPE& operator*() const { return *decode(_ptr); }
+
+ TYPE* operator->() { return decode(_ptr); }
+ const TYPE* operator->() const { return decode(_ptr); }
+
+ template<class O>
+ bool operator==(const sptr<O>& o) const
+ {
+ return o._ptr == this->_ptr;
+ }
+
+ operator TYPE*() const { return get(); }
+
+ sptr<TYPE>& operator++( )
+ {
+ inc_sptr(_ptr);
+ return *this;
+ }
+
+ sptr<TYPE> operator++( int )
+ {
+ sptr<TYPE> p = *this;
+ inc_sptr(_ptr);
+ return p;
+ }
+
+ sptr<TYPE>& operator--( )
+ {
+ dec_sptr(_ptr);
+ return *this;
+ }
+ sptr<TYPE> operator--( int )
+ {
+ sptr<TYPE> p = *this;
+ dec_sptr(_ptr);
+ return p;
+ }
+
+ sptr<TYPE>& operator+=(size_t offset)
+ {
+ inc_sptr(_ptr, offset);
+ return *this;
+ }
+
+ sptr<TYPE>& operator-=(size_t offset)
+ {
+ dec_sptr(_ptr, offset);
+ return *this;
+ }
+
+private:
+ uint32_t _ptr;
+};
+
+}; //NAMESPACE MINISAT
+
+#endif
+
#include <algorithm>
#include <limits.h>
#include <vector>
-#include <time.h>
+#include <iomanip>
#include "Clause.h"
#include "time_mem.h"
+
#include "VarReplacer.h"
#include "FindUndef.h"
#include "Gaussian.h"
#include "XorFinder.h"
#include "ClauseCleaner.h"
#include "RestartTypeChooser.h"
+#include "FailedVarSearcher.h"
+#include "Subsumer.h"
+#include "PartHandler.h"
+#include "XorSubsumer.h"
+
+#ifdef _MSC_VER
+#define __builtin_prefetch(a,b,c)
+//#define __builtin_prefetch(a,b)
+#endif //_MSC_VER
+
+//#define VERBOSE_DEBUG_POLARITIES
+//#define DEBUG_DYNAMIC_RESTART
namespace MINISAT
{
// More parameters:
//
, expensive_ccmin (true)
- , polarity_mode (polarity_user)
+ , polarity_mode (polarity_auto)
, verbosity (0)
, restrictedPickBranch(0)
- , xorFinder (true)
+ , findNormalXors (true)
+ , findBinaryXors (true)
+ , regularlyFindBinaryXors(true)
, performReplace (true)
+ , conglomerateXors (true)
+ , heuleProcess (true)
+ , schedSimplification(true)
+ , doSubsumption (true)
+ , doXorSubsumption (true)
+ , doPartHandler (true)
+ , doHyperBinRes (true)
+ , doBlockedClause (true)
+ , failedVarSearch (true)
+ , libraryUsage (true)
, greedyUnbound (false)
, fixRestartType (auto_restart)
// Statistics: (formerly in 'SolverStats')
//
- , starts(0), decisions(0), rnd_decisions(0), propagations(0), conflicts(0)
+ , starts(0), dynStarts(0), staticStarts(0), fullStarts(0), decisions(0), rnd_decisions(0), propagations(0), conflicts(0)
, clauses_literals(0), learnts_literals(0), max_literals(0), tot_literals(0)
- , nbDL2(0), nbBin(0), lastNbBin(0), nbReduceDB(0)
+ , nbDL2(0), nbBin(0), lastNbBin(0), becameBinary(0), lastSearchForBinaryXor(0), nbReduceDB(0)
+ , improvedClauseNo(0), improvedClauseSize(0)
, ok (true)
, var_inc (1)
, curRestart (1)
- , conf4Stats (0)
, nbclausesbeforereduce (NBCLAUSESBEFOREREDUCE)
+ , nbCompensateSubsumer (0)
, qhead (0)
, simpDB_assigns (-1)
, progress_estimate(0)
, remove_satisfied (true)
, mtrand((unsigned long int)0)
- //, mtrand((unsigned long int)time(NULL))
, restartType (static_restart)
#ifdef STATS_NEEDED
, logger(verbosity)
, MYFLAG (0)
, learnt_clause_group(0)
, libraryCNFFile (NULL)
+ , simplifying (false)
{
- varReplacer = new VarReplacer(this);
- conglomerate = new Conglomerate(this);
+ varReplacer = new VarReplacer(*this);
+ conglomerate = new Conglomerate(*this);
clauseCleaner = new ClauseCleaner(*this);
+ failedVarSearcher = new FailedVarSearcher(*this);
+ partHandler = new PartHandler(*this);
+ subsumer = new Subsumer(*this);
+ restartTypeChooser = new RestartTypeChooser(*this);
#ifdef STATS_NEEDED
logger.setSolver(this);
Solver::~Solver()
{
- for (uint32_t i = 0; i != learnts.size(); i++) free(learnts[i]);
- for (uint32_t i = 0; i != clauses.size(); i++) free(clauses[i]);
+ for (uint32_t i = 0; i != learnts.size(); i++) clauseFree(learnts[i]);
+ for (uint32_t i = 0; i != clauses.size(); i++) clauseFree(clauses[i]);
+ for (uint32_t i = 0; i != binaryClauses.size(); i++) clauseFree(binaryClauses[i]);
for (uint32_t i = 0; i != xorclauses.size(); i++) free(xorclauses[i]);
clearGaussMatrixes();
for (uint32_t i = 0; i != freeLater.size(); i++) free(freeLater[i]);
delete varReplacer;
delete conglomerate;
delete clauseCleaner;
+ delete failedVarSearcher;
+ delete partHandler;
+ delete subsumer;
+ delete restartTypeChooser;
if (libraryCNFFile)
fclose(libraryCNFFile);
// Creates a new SAT variable in the solver. If 'decision_var' 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)
+Var Solver::newVar(bool dvar)
{
Var v = nVars();
watches .push(); // (list for positive literal)
binwatches.push(); // (list for positive literal)
binwatches.push(); // (list for negative literal)
xorwatches.push(); // (list for variables in xors)
- reason .push(NULL);
+ reason .push((Clause*)NULL);
assigns .push(l_Undef);
level .push(-1);
activity .push(0);
- seen .push(0);
+ seen .push_back(0);
+ seen .push_back(0);
permDiff .push(0);
- polarity .push_back((char)sign);
+
+ polarity .push_back(true);
+ defaultPolarities.push_back(true);
decision_var.push_back(dvar);
+ insertVarOrder(v);
+
varReplacer->newVar();
conglomerate->newVar();
+ partHandler->newVar();
+ subsumer->newVar();
insertVarOrder(v);
return v;
}
-bool Solver::addXorClause(vec<Lit>& ps, bool xor_clause_inverted, const uint group, char* group_name, const bool internal)
+template<class T>
+XorClause* Solver::addXorClauseInt(T& ps, bool xor_clause_inverted, const uint32_t group)
{
- assert(decisionLevel() == 0);
- if (libraryCNFFile && !internal) {
- fprintf(libraryCNFFile, "x");
- for (uint i = 0; i < ps.size(); i++) {
- fprintf(libraryCNFFile, "%s%d ", ps[i].sign() ? "-" : "", ps[i].var()+1);
- }
- fprintf(libraryCNFFile, "0\n");
- }
-
- #ifdef STATS_NEEDED
- if (dynamic_behaviour_analysis)
- logger.set_group_name(group, group_name);
- #endif
-
- if (!ok)
- return false;
-
- // Check if clause is satisfied and remove false/duplicate literals:
- if (varReplacer->getNumLastReplacedVars()) {
- for (uint32_t i = 0; i != ps.size(); i++) {
- ps[i] = varReplacer->getReplaceTable()[ps[i].var()] ^ ps[i].sign();
- }
- }
-
std::sort(ps.getData(), ps.getData()+ps.size());
Lit p;
uint32_t i, j;
for (i = j = 0, p = lit_Undef; i != ps.size(); i++) {
xor_clause_inverted ^= ps[i].sign();
ps[i] ^= ps[i].sign();
-
+
if (ps[i] == p) {
//added, but easily removed
j--;
else //modify xor_clause_inverted instead of adding
xor_clause_inverted ^= (assigns[ps[i].var()].getBool());
}
- ps.shrink_(i - j);
-
+ ps.shrink(i - j);
+
switch(ps.size()) {
- case 0: {
- if (xor_clause_inverted)
- return true;
- return ok = false;
- }
- case 1: {
- assert(assigns[ps[0].var()].isUndef());
- uncheckedEnqueue(ps[0] ^ xor_clause_inverted);
- return ok = (propagate() == NULL);
- }
- case 2: {
- #ifdef VERBOSE_DEBUG
- cout << "--> xor is 2-long, replacing var " << ps[0].var()+1 << " with " << (!xor_clause_inverted ? "-" : "") << ps[1].var()+1 << endl;
- #endif
-
- varReplacer->replace(ps, xor_clause_inverted, group);
- break;
- }
- default: {
- learnt_clause_group = std::max(group+1, learnt_clause_group);
- XorClause* c = XorClause_new(ps, xor_clause_inverted, group);
-
- xorclauses.push(c);
- attachClause(*c);
- if (!internal)
- varReplacer->newClause();
- break;
- }
+ case 0: {
+ if (!xor_clause_inverted) ok = false;
+ return NULL;
+ }
+ case 1: {
+ assert(assigns[ps[0].var()].isUndef());
+ uncheckedEnqueue(ps[0] ^ xor_clause_inverted);
+ ok = (propagate() == NULL);
+ return NULL;
+ }
+ case 2: {
+ #ifdef VERBOSE_DEBUG
+ cout << "--> xor is 2-long, replacing var " << ps[0].var()+1 << " with " << (!xor_clause_inverted ? "-" : "") << ps[1].var()+1 << endl;
+ #endif
+
+ varReplacer->replace(ps, xor_clause_inverted, group);
+ return NULL;
+ }
+ default: {
+ learnt_clause_group = std::max(group+1, learnt_clause_group);
+ XorClause* c = XorClause_new(ps, xor_clause_inverted, group);
+ attachClause(*c);
+ return c;
+ }
}
-
- return true;
}
-bool Solver::addClause(vec<Lit>& ps, const uint group, char* group_name)
+template XorClause* Solver::addXorClauseInt(vec<Lit>& ps, bool xor_clause_inverted, const uint32_t group);
+template XorClause* Solver::addXorClauseInt(XorClause& ps, bool xor_clause_inverted, const uint32_t group);
+
+template<class T>
+bool Solver::addXorClause(T& ps, bool xor_clause_inverted, const uint group, char* group_name)
{
assert(decisionLevel() == 0);
+ if (ps.size() > (0x01UL << 18)) {
+ std::cout << "Too long clause!" << std::endl;
+ exit(-1);
+ }
if (libraryCNFFile) {
- for (uint32_t i = 0; i != ps.size(); i++) {
+ fprintf(libraryCNFFile, "x");
+ for (uint i = 0; i < ps.size(); i++) {
fprintf(libraryCNFFile, "%s%d ", ps[i].sign() ? "-" : "", ps[i].var()+1);
}
fprintf(libraryCNFFile, "0\n");
if (!ok)
return false;
+ assert(qhead == trail.size());
// Check if clause is satisfied and remove false/duplicate literals:
- if (varReplacer->getNumLastReplacedVars()) {
+ if (varReplacer->getNumLastReplacedVars() || subsumer->getNumElimed()) {
for (uint32_t i = 0; i != ps.size(); i++) {
ps[i] = varReplacer->getReplaceTable()[ps[i].var()] ^ ps[i].sign();
+ if (subsumer->getVarElimed()[ps[i].var()] && !subsumer->unEliminate(ps[i].var()))
+ return false;
}
}
+ XorClause* c = addXorClauseInt(ps, xor_clause_inverted, group);
+ if (c != NULL) xorclauses.push(c);
+
+ return ok;
+}
+
+template bool Solver::addXorClause(vec<Lit>& ps, bool xor_clause_inverted, const uint group, char* group_name);
+template bool Solver::addXorClause(XorClause& ps, bool xor_clause_inverted, const uint group, char* group_name);
+
+
+template<class T>
+bool Solver::addLearntClause(T& ps, const uint group, const uint32_t activity)
+{
+ Clause* c = addClauseInt(ps, group);
+ if (c == NULL)
+ return ok;
+
+ clauses_literals -= c->size();
+
+ c->makeLearnt(activity);
+ learnts.push(c);
+ learnts_literals += c->size();
+ return ok;
+}
+template bool Solver::addLearntClause(Clause& ps, const uint group, const uint32_t activity);
+template bool Solver::addLearntClause(vec<Lit>& ps, const uint group, const uint32_t activity);
+
+template <class T>
+Clause* Solver::addClauseInt(T& ps, uint group)
+{
+ assert(ok);
+
std::sort(ps.getData(), ps.getData()+ps.size());
- Lit p;
+ Lit p = lit_Undef;
uint32_t i, j;
- for (i = j = 0, p = lit_Undef; i != ps.size(); i++) {
+ for (i = j = 0; i != ps.size(); i++) {
if (value(ps[i]).getBool() || ps[i] == ~p)
- return true;
+ return NULL;
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;
+ ok = false;
+ return NULL;
} else if (ps.size() == 1) {
- assert(value(ps[0]) == l_Undef);
uncheckedEnqueue(ps[0]);
- return ok = (propagate() == NULL);
- } else {
- learnt_clause_group = std::max(group+1, learnt_clause_group);
- Clause* c = Clause_new(ps, group);
+ ok = (propagate() == NULL);
+ return NULL;
+ }
+
+ learnt_clause_group = std::max(group+1, learnt_clause_group);
+ Clause* c = Clause_new(ps, group);
+ attachClause(*c);
+
+ return c;
+}
- clauses.push(c);
- attachClause(*c);
- varReplacer->newClause();
+template Clause* Solver::addClauseInt(Clause& ps, const uint group);
+template Clause* Solver::addClauseInt(vec<Lit>& ps, const uint group);
+
+template<class T>
+bool Solver::addClause(T& ps, const uint group, char* group_name)
+{
+ assert(decisionLevel() == 0);
+ if (ps.size() > (0x01UL << 18)) {
+ std::cout << "Too long clause!" << std::endl;
+ exit(-1);
+ }
+
+ if (libraryCNFFile) {
+ for (uint32_t i = 0; i != ps.size(); i++) {
+ fprintf(libraryCNFFile, "%s%d ", ps[i].sign() ? "-" : "", ps[i].var()+1);
+ }
+ fprintf(libraryCNFFile, "0\n");
}
+
+ #ifdef STATS_NEEDED
+ if (dynamic_behaviour_analysis)
+ logger.set_group_name(group, group_name);
+ #endif
- return true;
+ if (!ok)
+ return false;
+ assert(qhead == trail.size());
+
+ // Check if clause is satisfied and remove false/duplicate literals:
+ if (varReplacer->getNumLastReplacedVars() || subsumer->getNumElimed()) {
+ for (uint32_t i = 0; i != ps.size(); i++) {
+ ps[i] = varReplacer->getReplaceTable()[ps[i].var()] ^ ps[i].sign();
+ if (subsumer->getVarElimed()[ps[i].var()] && !subsumer->unEliminate(ps[i].var()))
+ return false;
+ }
+ }
+
+ Clause* c = addClauseInt(ps, group);
+ if (c != NULL) {
+ if (c->size() > 2)
+ clauses.push(c);
+ else
+ binaryClauses.push(c);
+ }
+
+ return ok;
}
+template bool Solver::addClause(vec<Lit>& ps, const uint group, char* group_name);
+template bool Solver::addClause(Clause& ps, const uint group, char* group_name);
+
void Solver::attachClause(XorClause& c)
{
assert(c.size() > 2);
if (decisionLevel() > level) {
- for (Gaussian **gauss = &gauss_matrixes[0], **end= gauss + gauss_matrixes.size(); gauss != end; gauss++)
+ for (vector<Gaussian*>::iterator gauss = gauss_matrixes.begin(), end= gauss_matrixes.end(); gauss != end; gauss++)
(*gauss)->canceling(trail_lim[level]);
+
for (int c = trail.size()-1; c >= (int)trail_lim[level]; c--) {
Var x = trail[c].var();
#ifdef VERBOSE_DEBUG
assert(libraryCNFFile != NULL);
}
-void Solver::set_gaussian_decision_until(const uint to)
-{
- gaussconfig.decision_until = to;
-}
-
void Solver::clearGaussMatrixes()
{
for (uint i = 0; i < gauss_matrixes.size(); i++)
gauss_matrixes.clear();
}
+inline bool Solver::defaultPolarity()
+{
+ switch(polarity_mode) {
+ case polarity_false:
+ return true;
+ case polarity_true:
+ return false;
+ case polarity_rnd:
+ return mtrand.randInt(1);
+ default:
+ assert(false);
+ }
+
+ return true;
+}
+
+void tallyVotes(const vec<Clause*>& cs, vector<double>& votes, vector<bool>& positiveLiteral, vector<bool>& negativeLiteral)
+{
+ for (const Clause * const*it = cs.getData(), * const*end = it + cs.size(); it != end; it++) {
+ const Clause& c = **it;
+ if (c.learnt()) continue;
+
+ double divider;
+ if (c.size() > 63)
+ divider = 0.0;
+ else
+ divider = 1.0/(double)((uint64_t)1<<(c.size()-1));
+ for (const Lit *it2 = &c[0], *end2 = it2 + c.size(); it2 != end2; it2++) {
+ if (it2->sign()) {
+ negativeLiteral[it2->var()] = true;
+ votes[it2->var()] += divider;
+ } else {
+ positiveLiteral[it2->var()] = true;
+ votes[it2->var()] -= divider;
+ }
+ }
+ }
+}
+
+void tallyVotes(const vec<XorClause*>& cs, vector<double>& votes, vector<bool>& positiveLiteral, vector<bool>& negativeLiteral)
+{
+ for (const XorClause * const*it = cs.getData(), * const*end = it + cs.size(); it != end; it++) {
+ const XorClause& c = **it;
+ double divider;
+ if (c.size() > 63)
+ divider = 0.0;
+ else
+ divider = 1.0/(double)((uint64_t)1<<(c.size()-1));
+ for (const Lit *it2 = &c[0], *end2 = it2 + c.size(); it2 != end2; it2++) {
+ votes[it2->var()] += divider;
+ negativeLiteral[it2->var()] = true;
+ positiveLiteral[it2->var()] = true;
+ }
+ }
+}
+
+const lbool Solver::calculateDefaultPolarities()
+{
+ #ifdef VERBOSE_DEBUG_POLARITIES
+ std::cout << "Default polarities: " << std::endl;
+ #endif
+
+ assert(decisionLevel() == 0);
+
+ if (polarity_mode == polarity_auto) {
+ double time = cpuTime();
+
+ vector<double> votes;
+ vector<bool> positiveLiteral;
+ vector<bool> negativeLiteral;
+ votes.resize(nVars(), 0.0);
+ positiveLiteral.resize(nVars(), false);
+ negativeLiteral.resize(nVars(), false);
+
+ tallyVotes(clauses, votes, positiveLiteral, negativeLiteral);
+ tallyVotes(binaryClauses, votes, positiveLiteral, negativeLiteral);
+ tallyVotes(varReplacer->getClauses(), votes, positiveLiteral, negativeLiteral);
+ tallyVotes(xorclauses, votes, positiveLiteral, negativeLiteral);
+
+ Var i = 0;
+ for (vector<double>::const_iterator it = votes.begin(), end = votes.end(); it != end; it++, i++) {
+ defaultPolarities[i] = (*it >= 0.0);
+ #ifdef VERBOSE_DEBUG_POLARITIES
+ std::cout << !defaultPolarities[i] << ", ";
+ #endif //VERBOSE_DEBUG_POLARITIES
+ }
+
+ if (verbosity >= 2) {
+ std::cout << "c | Calc-ed default polarities: "
+ << std::fixed << std::setw(6) << std::setprecision(2) << cpuTime()-time << " s"
+ << " |" << std:: endl;
+ }
+ } else if (polarity_mode != polarity_manual){
+ for (uint i = 0; i != defaultPolarities.size(); i++) {
+ defaultPolarities[i] = defaultPolarity();
+ #ifdef VERBOSE_DEBUG_POLARITIES
+ std::cout << !defaultPolarities[i] << ", ";
+ #endif //VERBOSE_DEBUG_POLARITIES
+ }
+ }
+ #ifdef VERBOSE_DEBUG_POLARITIES
+ std::cout << std::endl;
+ #endif //VERBOSE_DEBUG_POLARITIES
+
+ return l_Undef;
+}
+
+void Solver::setDefaultPolarities()
+{
+ assert(polarity.size() == defaultPolarities.size());
+
+ for (uint i = 0; i != polarity.size(); i++)
+ polarity[i] = defaultPolarities[i];
+}
+
//=================================================================================================
// Major methods:
-Lit Solver::pickBranchLit(int polarity_mode)
+Lit Solver::pickBranchLit()
{
#ifdef VERBOSE_DEBUG
cout << "decision level: " << decisionLevel() << " ";
Var next = var_Undef;
+
+ bool random = mtrand.randDblExc() < random_var_freq;
+
// Random decision:
- if (mtrand.randDblExc() < random_var_freq && !order_heap.empty()) {
+ if (random && !order_heap.empty()) {
if (restrictedPickBranch == 0) next = order_heap[mtrand.randInt(order_heap.size()-1)];
else next = order_heap[mtrand.randInt(std::min((uint32_t)order_heap.size()-1, restrictedPickBranch))];
}
// Activity based decision:
- //bool dont_do_bad_decision = false;
- //if (restrictedPickBranch != 0) dont_do_bad_decision = (mtrand.randInt(100) != 0);
while (next == var_Undef || assigns[next] != l_Undef || !decision_var[next])
if (order_heap.empty()) {
next = var_Undef;
next = order_heap.removeMin();
}
- bool sign = false;
- switch (polarity_mode) {
- case polarity_true:
- sign = false;
- break;
- case polarity_false:
- sign = true;
- break;
- case polarity_user:
- if (next != var_Undef)
+ bool sign;
+ if (next != var_Undef) {
+ if (simplifying && random)
+ sign = mtrand.randInt(1);
+ /*else
+ sign = polarity[next] ^ (mtrand.randInt(200) == 1);*/
+ else if (avgBranchDepth.isvalid())
+ sign = polarity[next] ^ (mtrand.randInt(avgBranchDepth.getavg()) == 1);
+ else
sign = polarity[next];
- break;
- case polarity_rnd:
- sign = mtrand.randInt(1);
- break;
- default:
- assert(false);
}
assert(next == var_Undef || value(next) == l_Undef);
}
}
+// Assumes 'seen' is cleared (will leave it cleared)
+template<class T1, class T2>
+bool subset(const T1& A, const T2& B, vector<bool>& seen)
+{
+ for (uint i = 0; i != B.size(); i++)
+ seen[B[i].toInt()] = 1;
+ for (uint i = 0; i != A.size(); i++) {
+ if (!seen[A[i].toInt()]) {
+ for (uint i = 0; i != B.size(); i++)
+ seen[B[i].toInt()] = 0;
+ return false;
+ }
+ }
+ for (uint i = 0; i != B.size(); i++)
+ seen[B[i].toInt()] = 0;
+ return true;
+}
+
/*_________________________________________________________________________________________________
|
| Effect:
| Will undo part of the trail, upto but not beyond the assumption of the current decision level.
|________________________________________________________________________________________________@*/
-void Solver::analyze(Clause* confl, vec<Lit>& out_learnt, int& out_btlevel, int &nbLevels/*, int &merged*/)
+Clause* Solver::analyze(Clause* confl, vec<Lit>& out_learnt, int& out_btlevel, int &nbLevels/*, int &merged*/)
{
int pathC = 0;
Lit p = lit_Undef;
+ Clause* oldConfl = NULL;
// Generate conflict clause:
//
if (p != lit_Undef)
reverse_binary_clause(c);
- for (uint j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++) {
+ for (uint j = (p == lit_Undef) ? 0 : 1; j != c.size(); j++) {
const Lit& q = c[j];
- const uint my_var = q.var();
+ const Var my_var = q.var();
if (!seen[my_var] && level[my_var] > 0) {
varBumpActivity(my_var);
// Select next clause to look at:
while (!seen[trail[index--].var()]);
p = trail[index+1];
+ oldConfl = confl;
confl = reason[p.var()];
+ __builtin_prefetch(confl, 1, 0);
seen[p.var()] = 0;
pathC--;
}
#ifdef UPDATEVARACTIVITY
- if (lastDecisionLevel.size() > 0) {
- for(uint32_t i = 0; i != lastDecisionLevel.size(); i++) {
- if (reason[lastDecisionLevel[i].var()]->activity() < nbLevels)
- varBumpActivity(lastDecisionLevel[i].var());
- }
- lastDecisionLevel.clear();
+ for(uint32_t i = 0; i != lastDecisionLevel.size(); i++) {
+ if (reason[lastDecisionLevel[i].var()]->activity() < nbLevels)
+ varBumpActivity(lastDecisionLevel[i].var());
}
+ lastDecisionLevel.clear();
#endif
for (uint32_t j = 0; j != analyze_toclear.size(); j++)
seen[analyze_toclear[j].var()] = 0; // ('seen[]' is now cleared)
+
+ if (out_learnt.size() == 1)
+ return NULL;
+
+ if (!oldConfl->isXor() && out_learnt.size() < oldConfl->size()) {
+ if (!subset(out_learnt, *oldConfl, seen)) return NULL;
+ improvedClauseNo++;
+ improvedClauseSize += oldConfl->size() - out_learnt.size();
+ return oldConfl;
+ }
+
+ return NULL;
}
}
-void Solver::uncheckedEnqueue(Lit p, Clause* from)
+void Solver::uncheckedEnqueue(Lit p, ClausePtr from)
{
#ifdef VERBOSE_DEBUG
cout << "uncheckedEnqueue var " << p.var()+1 << " to " << !p.sign() << " level: " << decisionLevel() << " sublevel: " << trail.size() << endl;
| Post-conditions:
| * the propagation queue is empty, even if there was a conflict.
|________________________________________________________________________________________________@*/
-Clause* Solver::propagate(const bool xor_as_well)
+Clause* Solver::propagate(const bool update)
{
Clause* confl = NULL;
- int num_props = 0;
+ uint32_t num_props = 0;
#ifdef VERBOSE_DEBUG
cout << "Propagation started" << endl;
#endif
+ uint32_t qheadBin = qhead;
while (qhead < trail.size()) {
+
Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate.
vec<Watched>& ws = watches[p.toInt()];
- Watched *i, *j, *end;
- num_props++;
+ Watched *i, *j, *end;
//First propagate binary clauses
- vec<WatchedBin> & wbin = binwatches[p.toInt()];
- for(WatchedBin *k = wbin.getData(), *end = k + wbin.size(); k != end; k++) {
- Lit imp = k->impliedLit;
- lbool val = value(imp);
- if (val.isUndef()) {
- uncheckedEnqueue(imp, k->clause);
- } else if (val == l_False)
- return k->clause;
+ while (qheadBin < trail.size()) {
+ Lit p = trail[qheadBin++];
+ vec<WatchedBin> & wbin = binwatches[p.toInt()];
+ num_props++;
+ for(WatchedBin *k = wbin.getData(), *end = k + wbin.size(); k != end; k++) {
+ lbool val = value(k->impliedLit);
+ if (val.isUndef()) {
+ uncheckedEnqueue(k->impliedLit, k->clause);
+ } else if (val == l_False) {
+ confl = k->clause;
+ //goto EndPropagate;
+ }
+ }
}
+ if (confl != NULL)
+ goto EndPropagate;
//Next, propagate normal clauses
#endif
for (i = j = ws.getData(), end = i + ws.size(); i != end;) {
+ if (i+1 != end)
+ __builtin_prefetch((i+1)->clause, 1, 0);
+
if(value(i->blockedLit).getBool()) { // Clause is sat
*j++ = *i++;
continue;
j++;
} else {
// Look for new watch:
- for (uint32_t k = 2; k != c.size(); k++)
- if (value(c[k]) != l_False) {
- c[1] = c[k];
- c[k] = false_lit;
+ for (Lit *k = &c[2], *end2 = c.getData()+c.size(); k != end2; k++) {
+ if (value(*k) != l_False) {
+ c[1] = *k;
+ *k = false_lit;
watches[(~c[1]).toInt()].push(Watched(&c, c[0]));
goto FoundWatch;
}
+ }
// Did not find watch -- clause is unit under assignment:
j->clause = &c;
} else {
uncheckedEnqueue(first, &c);
#ifdef DYNAMICNBLEVEL
- if (c.learnt() && c.activity() > 2) { // GA
+ if (update && c.learnt() && c.activity() > 2) { // GA
MYFLAG++;
int nbLevels =0;
- for(Lit *i = c.getData(), *end = i+c.size(); i != end; i++) {
- int l = level[i->var()];
- if (permDiff[l] != MYFLAG) {
- permDiff[l] = MYFLAG;
+ for(Lit *l = c.getData(), *end2 = l+c.size(); l != end2; l++) {
+ int lev = level[l->var()];
+ if (permDiff[lev] != MYFLAG) {
+ permDiff[lev] = MYFLAG;
nbLevels++;
}
ws.shrink_(i - j);
//Finally, propagate XOR-clauses
- if (xor_as_well && !confl) confl = propagate_xors(p);
+ if (xorclauses.size() > 0 && !confl) confl = propagate_xors(p);
}
+EndPropagate:
propagations += num_props;
simpDB_props -= num_props;
Clause* confl = NULL;
- vec<XorClause*>& ws = xorwatches[p.var()];
- XorClause **i, **j, **end;
+ vec<XorClausePtr>& ws = xorwatches[p.var()];
+ XorClausePtr *i, *j, *end;
for (i = j = ws.getData(), end = i + ws.size(); i != end;) {
XorClause& c = **i++;
+ if (i != end)
+ __builtin_prefetch(*i, 1, 0);
// Make sure the false literal is data[1]:
if (c[0].var() == p.var()) {
cout << endl;
#endif
bool final = c.xor_clause_inverted();
- for (int k = 0, size = c.size(); k != size; k++ ) {
+ for (uint32_t k = 0, size = c.size(); k != size; k++ ) {
const lbool& val = assigns[c[k].var()];
if (val.isUndef() && k >= 2) {
Lit tmp(c[1]);
// First criteria
if (xsize > 2 && ysize == 2) return 1;
if (ysize > 2 && xsize == 2) return 0;
- if (xsize == 2 && ysize == 2) return 0;
// Second criteria
if (x->activity() > y->activity()) return 1;
if (x->activity() < y->activity()) return 0;
//return x->oldActivity() < y->oldActivity();
- return xsize < ysize;
+ return xsize > ysize;
}
};
nbReduceDB++;
std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_lt());
- for (i = j = 0; i != learnts.size() / RATIOREMOVECLAUSES; i++){
+
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Cleaning clauses" << endl;
+ for (uint i = 0; i != learnts.size(); i++) {
+ std::cout << "activity:" << learnts[i]->activity() << " \tsize:" << learnts[i]->size() << std::endl;
+ }
+ #endif
+
+
+ const uint removeNum = (double)learnts.size() / (double)RATIOREMOVECLAUSES;
+ for (i = j = 0; i != removeNum; i++){
+ //NOTE: The next instruciton only works if removeNum < learnts.size() (strictly smaller!!)
+ __builtin_prefetch(learnts[i+1], 0, 0);
if (learnts[i]->size() > 2 && !locked(*learnts[i]) && learnts[i]->activity() > 2)
removeClause(*learnts[i]);
else
{
vector<Lit> unitaries;
if (decisionLevel() > 0) {
- for (uint32_t i = 0; i != trail_lim[0]; i++)
+ for (uint32_t i = 0; i != trail_lim[0]; i++) {
unitaries.push_back(trail[i]);
+ }
}
return unitaries;
}
-void Solver::dump_sorted_learnts(const char* file)
+void Solver::dumpSortedLearnts(const char* file, const uint32_t maxSize)
{
FILE* outfile = fopen(file, "w");
if (!outfile) {
exit(-1);
}
- if (decisionLevel() > 0) {
- for (uint32_t i = 0; i != trail_lim[0]; i++)
- printf("%s%d 0\n", trail[i].sign() ? "-" : "", trail[i].var());
+ fprintf(outfile, "c unitaries\n");
+ if (maxSize > 0) {
+ if (trail_lim.size() > 0) {
+ for (uint32_t i = 0; i != trail_lim[0]; i++) {
+ fprintf(outfile,"%s%d 0\n", trail[i].sign() ? "-" : "", trail[i].var()+1);
+ }
+ }
+ else {
+ for (uint32_t i = 0; i != trail.size(); i++) {
+ fprintf(outfile,"%s%d 0\n", trail[i].sign() ? "-" : "", trail[i].var()+1);
+ }
+ }
+ }
+
+ fprintf(outfile, "c clauses from binaryClauses\n");
+ if (maxSize >= 2) {
+ for (uint i = 0; i != binaryClauses.size(); i++) {
+ if (binaryClauses[i]->learnt())
+ binaryClauses[i]->plainPrint(outfile);
+ }
}
+ fprintf(outfile, "c clauses from learnts\n");
std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_lt());
for (int i = learnts.size()-1; i >= 0 ; i--) {
- learnts[i]->plainPrint(outfile);
+ if (learnts[i]->size() <= maxSize)
+ learnts[i]->plainPrint(outfile);
}
+
+ fprintf(outfile, "c clauses representing 2-long XOR clauses\n");
+ const vector<Lit>& table = varReplacer->getReplaceTable();
+ for (Var var = 0; var != table.size(); var++) {
+ Lit lit = table[var];
+ if (lit.var() == var)
+ continue;
+
+ fprintf(outfile, "%s%d %d 0\n", (!lit.sign() ? "-" : ""), lit.var()+1, var+1);
+ fprintf(outfile, "%s%d -%d 0\n", (lit.sign() ? "-" : ""), lit.var()+1, var+1);
+ }
+
fclose(outfile);
}
maxRestarts = num;
}
+inline int64_t abs64(int64_t a)
+{
+ if (a < 0) return -a;
+ return a;
+}
+
/*_________________________________________________________________________________________________
|
| simplify : [void] -> [bool]
return l_False;
}
- if (nAssigns() == simpDB_assigns || (simpDB_props > 0)) {
+ if (simpDB_props > 0) {
return l_Undef;
}
-
- // Remove satisfied clauses:
- clauseCleaner->removeAndCleanAll();
- if (((double)(nbBin - lastNbBin)/BINARY_TO_XOR_APPROX) > (double)order_heap.size() * PERCENTAGEPERFORMREPLACE) {
- XorFinder xorFinder(this, learnts, ClauseCleaner::learnts);
- xorFinder.doNoPart(2, 2);
- if (!ok) return l_False;
+
+ double slowdown = (100000.0/(double)binaryClauses.size());
+ slowdown = std::min(3.5, slowdown);
+ slowdown = std::max(0.2, slowdown);
+
+ double speedup = 50000000.0/(double)(propagations-lastSearchForBinaryXor);
+ speedup = std::min(3.5, speedup);
+ speedup = std::max(0.2, speedup);
+
+ /*std::cout << "new:" << nbBin - lastNbBin + becameBinary << std::endl;
+ std::cout << "left:" << ((double)(nbBin - lastNbBin + becameBinary)/BINARY_TO_XOR_APPROX) * slowdown << std::endl;
+ std::cout << "right:" << (double)order_heap.size() * PERCENTAGEPERFORMREPLACE * speedup << std::endl;*/
+
+ if (findBinaryXors && regularlyFindBinaryXors &&
+ (((double)abs64((int64_t)nbBin - (int64_t)lastNbBin + (int64_t)becameBinary)/BINARY_TO_XOR_APPROX) * slowdown) >
+ ((double)order_heap.size() * PERCENTAGEPERFORMREPLACE * speedup)) {
+ lastSearchForBinaryXor = propagations;
+ clauseCleaner->cleanClauses(clauses, ClauseCleaner::clauses);
+ clauseCleaner->cleanClauses(learnts, ClauseCleaner::learnts);
+ clauseCleaner->removeSatisfied(binaryClauses, ClauseCleaner::binaryClauses);
+ if (ok == false)
+ return l_False;
+
+ XorFinder xorFinder(this, binaryClauses, ClauseCleaner::binaryClauses);
+ if (xorFinder.doNoPart(2, 2) == false)
+ return l_False;
lastNbBin = nbBin;
+ becameBinary = 0;
}
- if (performReplace
- && ((double)varReplacer->getNewToReplaceVars()/(double)order_heap.size()) > PERCENTAGEPERFORMREPLACE) {
- varReplacer->performReplace();
- if (!ok) return l_False;
- }
+
+ // Remove satisfied clauses:
+ clauseCleaner->removeAndCleanAll();
+ if (ok == false)
+ return l_False;
+ if (performReplace && varReplacer->performReplace() == false)
+ return l_False;
// Remove fixed variables from the variable heap:
order_heap.filter(VarFilter(*this));
| 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)
+lbool Solver::search(int nof_conflicts, int nof_conflicts_fullrestart, const bool update)
{
assert(ok);
int conflictC = 0;
llbool ret;
starts++;
- for (Gaussian **gauss = &gauss_matrixes[0], **end= gauss + gauss_matrixes.size(); gauss != end; gauss++) {
+ if (restartType == static_restart)
+ staticStarts++;
+ else
+ dynStarts++;
+
+ for (vector<Gaussian*>::iterator gauss = gauss_matrixes.begin(), end= gauss_matrixes.end(); gauss != end; gauss++) {
ret = (*gauss)->full_init();
if (ret != l_Nothing) return ret;
}
for (;;) {
- Clause* confl = propagate();
+ Clause* confl = propagate(update);
if (confl != NULL) {
- ret = handle_conflict(learnt_clause, confl, conflictC);
+ ret = handle_conflict(learnt_clause, confl, conflictC, update);
if (ret != l_Nothing) return ret;
} else {
bool at_least_one_continue = false;
- for (Gaussian **gauss = &gauss_matrixes[0], **end= gauss + gauss_matrixes.size(); gauss != end; gauss++) {
+ for (vector<Gaussian*>::iterator gauss = gauss_matrixes.begin(), end= gauss_matrixes.end(); gauss != end; gauss++) {
ret = (*gauss)->find_truths(learnt_clause, conflictC);
if (ret == l_Continue) at_least_one_continue = true;
else if (ret != l_Nothing) return ret;
}
if (at_least_one_continue) continue;
- ret = new_decision(nof_conflicts, conflictC);
+ ret = new_decision(nof_conflicts, nof_conflicts_fullrestart, conflictC);
if (ret != l_Nothing) return ret;
}
}
}
-llbool Solver::new_decision(int& nof_conflicts, int& conflictC)
+llbool Solver::new_decision(const int& nof_conflicts, const int& nof_conflicts_fullrestart, int& conflictC)
{
// Reached bound on number of conflicts?
switch (restartType) {
case dynamic_restart:
if (nbDecisionLevelHistory.isvalid() &&
- ((nbDecisionLevelHistory.getavg()*0.7) > (totalSumOfDecisionLevel / conf4Stats))) {
+ ((nbDecisionLevelHistory.getavg()) > (totalSumOfDecisionLevel / (double)(conflicts - conflictsAtLastSolve)))) {
+
+ #ifdef DEBUG_DYNAMIC_RESTART
+ if (nbDecisionLevelHistory.isvalid()) {
+ std::cout << "nbDecisionLevelHistory.getavg():" << nbDecisionLevelHistory.getavg() <<std::endl;
+ //std::cout << "calculated limit:" << ((double)(nbDecisionLevelHistory.getavg())*0.9*((double)fullStarts + 20.0)/20.0) << std::endl;
+ std::cout << "totalSumOfDecisionLevel:" << totalSumOfDecisionLevel << std::endl;
+ std::cout << "conflicts:" << conflicts<< std::endl;
+ std::cout << "conflictsAtLastSolve:" << conflictsAtLastSolve << std::endl;
+ std::cout << "conflicts-conflictsAtLastSolve:" << conflicts-conflictsAtLastSolve<< std::endl;
+ std::cout << "fullStarts:" << fullStarts << std::endl;
+ }
+ #endif
+
nbDecisionLevelHistory.fastclear();
- progress_estimate = progressEstimate();
+ #ifdef STATS_NEEDED
+ if (dynamic_behaviour_analysis)
+ progress_estimate = progressEstimate();
+ #endif
cancelUntil(0);
return l_Undef;
}
break;
case static_restart:
if (nof_conflicts >= 0 && conflictC >= nof_conflicts) {
- progress_estimate = progressEstimate();
+ #ifdef STATS_NEEDED
+ if (dynamic_behaviour_analysis)
+ progress_estimate = progressEstimate();
+ #endif
cancelUntil(0);
return l_Undef;
}
assert(false);
break;
}
+ if (nof_conflicts_fullrestart >= 0 && conflicts >= nof_conflicts_fullrestart) {
+ #ifdef STATS_NEEDED
+ if (dynamic_behaviour_analysis)
+ progress_estimate = progressEstimate();
+ #endif
+ cancelUntil(0);
+ return l_Undef;
+ }
// Simplify the set of problem clauses:
if (decisionLevel() == 0 && simplify() == l_False) {
}
// Reduce the set of learnt clauses:
- if (conflicts >= curRestart * nbclausesbeforereduce) {
+ if (conflicts >= curRestart * nbclausesbeforereduce + nbCompensateSubsumer) {
curRestart ++;
reduceDB();
nbclausesbeforereduce += 500;
if (next == lit_Undef) {
// New variable decision:
decisions++;
- next = pickBranchLit(polarity_mode);
+ next = pickBranchLit();
if (next == lit_Undef)
return l_True;
return l_Nothing;
}
-llbool Solver::handle_conflict(vec<Lit>& learnt_clause, Clause* confl, int& conflictC)
+llbool Solver::handle_conflict(vec<Lit>& learnt_clause, Clause* confl, int& conflictC, const bool update)
{
#ifdef VERBOSE_DEBUG
cout << "Handling conflict: ";
if (decisionLevel() == 0)
return l_False;
learnt_clause.clear();
- analyze(confl, learnt_clause, backtrack_level, nbLevels);
- conf4Stats++;
- if (restartType == dynamic_restart) {
- nbDecisionLevelHistory.push(nbLevels);
+ Clause* c = analyze(confl, learnt_clause, backtrack_level, nbLevels);
+ if (update) {
+ avgBranchDepth.push(decisionLevel());
+ if (restartType == dynamic_restart)
+ nbDecisionLevelHistory.push(nbLevels);
totalSumOfDecisionLevel += nbLevels;
+ } else {
+ conflictsAtLastSolve++;
}
#ifdef STATS_NEEDED
if (dynamic_behaviour_analysis)
- logger.conflict(Logger::simple_confl_type, backtrack_level, confl->group, learnt_clause);
+ logger.conflict(Logger::simple_confl_type, backtrack_level, confl->getGroup(), learnt_clause);
#endif
cancelUntil(backtrack_level);
#endif
//Normal learnt
} else {
- Clause* c = Clause_new(learnt_clause, learnt_clause_group++, true);
- #ifdef STATS_NEEDED
- if (dynamic_behaviour_analysis)
- logger.set_group_name(c->group, "learnt clause");
- #endif
- learnts.push(c);
- c->setActivity(nbLevels); // LS
+ if (c) {
+ detachClause(*c);
+ for (uint i = 0; i != learnt_clause.size(); i++)
+ (*c)[i] = learnt_clause[i];
+ c->resize(learnt_clause.size());
+ if (c->learnt() && c->activity() > nbLevels)
+ c->setActivity(nbLevels); // LS
+ c->setStrenghtened();
+ } else {
+ c = Clause_new(learnt_clause, learnt_clause_group++, true);
+ #ifdef STATS_NEEDED
+ if (dynamic_behaviour_analysis)
+ logger.set_group_name(c->getGroup(), "learnt clause");
+ #endif
+ if (c->size() > 2) {
+ learnts.push(c);
+ c->setActivity(nbLevels); // LS
+ } else {
+ binaryClauses.push(c);
+ nbBin++;
+ }
+ }
if (nbLevels <= 2) nbDL2++;
- if (c->size() == 2) nbBin++;
attachClause(*c);
uncheckedEnqueue(learnt_clause[0], c);
}
for (uint32_t 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);
+ progress += pow(F, (int)i) * (end - beg);
}
return progress / nVars();
uint useful_prop = 0;
uint useful_confl = 0;
uint disabled = 0;
- for (Gaussian *const*gauss = &gauss_matrixes[0], *const*end= gauss + gauss_matrixes.size(); gauss != end; gauss++) {
+ for (vector<Gaussian*>::const_iterator gauss = gauss_matrixes.begin(), end= gauss_matrixes.end(); gauss != end; gauss++) {
disabled += (*gauss)->get_disabled();
called += (*gauss)->get_called();
useful_prop += (*gauss)->get_useful_prop();
}
}
-inline void Solver::chooseRestartType(const lbool& status, RestartTypeChooser& restartTypeChooser)
+inline void Solver::chooseRestartType(const uint& lastFullRestart)
{
- if (status.isUndef() && starts > 2 && starts < 8) {
- RestartType tmp = restartTypeChooser.choose();
- if (fixRestartType != auto_restart)
- tmp = fixRestartType;
- if (starts == 7) {
+ uint relativeStart = starts - lastFullRestart;
+
+ if (relativeStart > RESTART_TYPE_DECIDER_FROM && relativeStart < RESTART_TYPE_DECIDER_UNTIL) {
+ if (fixRestartType == auto_restart)
+ restartTypeChooser->addInfo();
+
+ if (relativeStart == (RESTART_TYPE_DECIDER_UNTIL-1)) {
+ RestartType tmp;
+ if (fixRestartType == auto_restart)
+ tmp = restartTypeChooser->choose();
+ else
+ tmp = fixRestartType;
+
if (tmp == dynamic_restart) {
nbDecisionLevelHistory.fastclear();
nbDecisionLevelHistory.initSize(100);
- totalSumOfDecisionLevel = 0;
- clearGaussMatrixes();
- if (verbosity >= 1)
+ if (verbosity >= 2)
printf("c | Decided on dynamic restart strategy |\n");
} else {
- if (verbosity >= 1)
+ if (verbosity >= 2)
printf("c | Decided on static restart strategy |\n");
+
+ if (gaussconfig.decision_until > 0 && xorclauses.size() > 1 && xorclauses.size() < 20000) {
+ double time = cpuTime();
+ MatrixFinder m(*this);
+ const uint numMatrixes = m.findMatrixes();
+ if (verbosity >=1)
+ printf("c | Finding matrixes : %4.2lf s (found %5d) |\n", cpuTime()-time, numMatrixes);
+ }
}
restartType = tmp;
+ restartTypeChooser->reset();
}
- } else {
- #ifdef VERBOSE_DEBUG
- restartTypeChooser.choose();
- #endif
}
}
-inline void Solver::performStepsBeforeSolve()
+inline void Solver::setDefaultRestartType()
{
- if (performReplace
- && ((double)varReplacer->getNewToReplaceVars()/(double)order_heap.size()) > PERCENTAGEPERFORMREPLACE) {
- varReplacer->performReplace();
- if (!ok) return;
+ if (fixRestartType != auto_restart) restartType = fixRestartType;
+ else restartType = static_restart;
+ if (restartType == dynamic_restart) {
+ nbDecisionLevelHistory.fastclear();
+ nbDecisionLevelHistory.initSize(100);
}
+}
+
+const lbool Solver::simplifyProblem(const uint32_t numConfls, const uint64_t numProps)
+{
+ Heap<VarOrderLt> backup_order_heap(order_heap);
+ vector<bool> backup_polarities = polarity;
+ RestartType backup_restartType= restartType;
+ double backup_random_var_freq = random_var_freq;
+ vec<double> backup_activity;
+ backup_activity.growTo(activity.size());
+ std::copy(activity.getData(), activity.getDataEnd(), backup_activity.getData());
+ double backup_var_inc = var_inc;
- if (xorFinder) {
- double time;
- if (clauses.size() < MAX_CLAUSENUM_XORFIND) {
- XorFinder xorFinder(this, clauses, ClauseCleaner::clauses);
- xorFinder.doNoPart(2, 10);
- if (!ok) return;
-
- if (performReplace
- && ((double)varReplacer->getNewToReplaceVars()/(double)order_heap.size()) > PERCENTAGEPERFORMREPLACE) {
- varReplacer->performReplace();
- if (!ok) return;
- }
+ if (verbosity >= 2)
+ std::cout << "c | " << std::setw(24) << " "
+ << "Simplifying problem for " << std::setw(8) << numConfls << " confls"
+ << std::setw(24) << " |" << std::endl;
+ random_var_freq = 1;
+ simplifying = true;
+ uint64_t origConflicts = conflicts;
+
+ lbool status = l_Undef;
+ restartType = static_restart;
+
+ while(status == l_Undef && conflicts-origConflicts < numConfls) {
+ printRestartStat();
+ status = search(100, -1, false);
+ starts--;
+ }
+ if (status != l_Undef)
+ goto end;
+ printRestartStat();
+
+ if (heuleProcess && xorclauses.size() > 1) {
+ if (!conglomerate->heuleProcessFull()) {
+ status = l_False;
+ goto end;
}
- if (xorclauses.size() > 1) {
- uint orig_total = 0;
- uint orig_num_cls = xorclauses.size();
- for (uint i = 0; i < xorclauses.size(); i++) {
- orig_total += xorclauses[i]->size();
+ while (performReplace && varReplacer->needsReplace()) {
+ if (!varReplacer->performReplace()) {
+ status = l_False;
+ goto end;
}
-
- time = cpuTime();
- uint foundCong = conglomerate->conglomerateXors();
- if (verbosity >=1)
- printf("c | Conglomerating XORs: %4.2lf s (removed %6d vars) |\n", cpuTime()-time, foundCong);
- if (!ok) return;
-
- uint new_total = 0;
- uint new_num_cls = xorclauses.size();
- for (uint i = 0; i < xorclauses.size(); i++) {
- new_total += xorclauses[i]->size();
- }
- if (verbosity >=1) {
- printf("c | Sum xclauses before: %8d, after: %12d |\n", orig_num_cls, new_num_cls);
- printf("c | Sum xlits before: %11d, after: %12d |\n", orig_total, new_total);
- }
-
- if (performReplace
- && ((double)varReplacer->getNewToReplaceVars()/(double)order_heap.size()) > PERCENTAGEPERFORMREPLACE) {
- varReplacer->performReplace();
- if (!ok) return;
+ if (!conglomerate->heuleProcessFull()) {
+ status = l_False;
+ goto end;
}
}
}
- if (gaussconfig.decision_until > 0 && xorclauses.size() > 1 && xorclauses.size() < 20000) {
- double time = cpuTime();
- MatrixFinder m(this);
- const uint numMatrixes = m.findMatrixes();
- if (verbosity >=1)
- printf("c | Finding matrixes : %4.2lf s (found %5d) |\n", cpuTime()-time, numMatrixes);
+ if (failedVarSearch && !failedVarSearcher->search((nClauses() < 500000 && order_heap.size() < 50000) ? 6000000 : 2000000)) {
+ status = l_False;
+ goto end;
+ }
+
+ if (doXorSubsumption && xorclauses.size() > 1) {
+ XorSubsumer xsub(*this);
+ if (!xsub.simplifyBySubsumption()) {
+ status = l_False;
+ goto end;
+ }
+ }
+
+ if (doSubsumption) {
+ if (!subsumer->simplifyBySubsumption()) {
+ status = l_False;
+ goto end;
+ }
}
+
+end:
+ random_var_freq = backup_random_var_freq;
+ if (verbosity >= 2)
+ printf("c Simplifying finished |\n");
+
+ var_inc = backup_var_inc;
+ std::copy(backup_activity.getData(), backup_activity.getDataEnd(), activity.getData());
+ order_heap = backup_order_heap;
+ simplifying = false;
+ order_heap.filter(VarFilter(*this));
+ polarity = backup_polarities;
+ restartType = backup_restartType;
+
+ return status;
+}
+
+const bool Solver::checkFullRestart(int& nof_conflicts, int& nof_conflicts_fullrestart, uint& lastFullRestart)
+{
+ if (nof_conflicts_fullrestart > 0 && conflicts >= nof_conflicts_fullrestart) {
+ clearGaussMatrixes();
+ if (verbosity >= 2)
+ printf("c | Fully restarting |\n");
+ nof_conflicts = restart_first + (double)restart_first*restart_inc;
+ nof_conflicts_fullrestart = (double)nof_conflicts_fullrestart * FULLRESTART_MULTIPLIER_MULTIPLIER;
+ restartType = static_restart;
+ lastFullRestart = starts;
+
+ /*if (findNormalXors && clauses.size() < MAX_CLAUSENUM_XORFIND) {
+ XorFinder xorFinder(this, clauses, ClauseCleaner::clauses);
+ if (!xorFinder.doNoPart(3, 10))
+ return false;
+ }*/
+
+ if (doPartHandler && !partHandler->handle())
+ return false;
+
+ /*if (calculateDefaultPolarities() == l_False)
+ return false;
+ setDefaultPolarities();*/
+
+ fullStarts++;
+ }
+
+ return true;
+}
+
+inline void Solver::performStepsBeforeSolve()
+{
+ assert(qhead == trail.size());
+ if (performReplace && !varReplacer->performReplace()) return;
+
+
+ if (doSubsumption
+ && !libraryUsage
+ && clauses.size() + binaryClauses.size() + learnts.size() < 4800000
+ && !subsumer->simplifyBySubsumption())
+ return;
+
+ const uint32_t lastReplacedVars = varReplacer->getNumReplacedVars();
+ if (findBinaryXors && binaryClauses.size() < MAX_CLAUSENUM_XORFIND) {
+ XorFinder xorFinder(this, binaryClauses, ClauseCleaner::binaryClauses);
+ if (!xorFinder.doNoPart(2, 2)) return;
+
+ if (performReplace && !varReplacer->performReplace(true)) return;
+ }
+
+ if (findNormalXors && clauses.size() < MAX_CLAUSENUM_XORFIND) {
+ XorFinder xorFinder(this, clauses, ClauseCleaner::clauses);
+ if (!xorFinder.doNoPart(3, 10)) return;
+ }
+
+ if (xorclauses.size() > 1) {
+ if (heuleProcess) {
+ if (!conglomerate->heuleProcessFull()) return;
+
+ while (performReplace && varReplacer->needsReplace()) {
+ if (!varReplacer->performReplace()) return;
+ if (!conglomerate->heuleProcessFull()) return;
+ }
+ }
+
+ if (conglomerateXors && !conglomerate->conglomerateXorsFull())
+ return;
+
+ if (doXorSubsumption && xorclauses.size() > 1) {
+ XorSubsumer xsub(*this);
+ if (!xsub.simplifyBySubsumption())
+ return;
+ }
+
+ if (performReplace && !varReplacer->performReplace())
+ return;
+ }
+}
+
+void Solver::checkSolution()
+{
+ // Extend & check:
+ model.growTo(nVars());
+ for (Var var = 0; var != nVars(); var++) model[var] = value(var);
+ verifyModel();
+ model.clear();
}
lbool Solver::solve(const vec<Lit>& assumps)
{
+ if (!ok) return l_False;
+ assert(qhead == trail.size());
+
if (libraryCNFFile)
fprintf(libraryCNFFile, "c Solver::solve() called\n");
model.clear();
conflict.clear();
clearGaussMatrixes();
- restartType = static_restart;
- conglomerate->addRemovedClauses();
+ setDefaultRestartType();
+ totalSumOfDecisionLevel = 0;
+ conflictsAtLastSolve = conflicts;
+ avgBranchDepth.fastclear();
+ avgBranchDepth.initSize(500);
+
+ if (!conglomerate->addRemovedClauses()) return l_False;
starts = 0;
- if (!ok) return l_False;
-
assumps.copyTo(assumptions);
- double nof_conflicts = restart_first;
+ int nof_conflicts = restart_first;
+ int nof_conflicts_fullrestart = (double)restart_first * (double)FULLRESTART_MULTIPLIER;
+ //nof_conflicts_fullrestart = -1;
+ uint lastFullRestart = starts;
lbool status = l_Undef;
+ uint64_t nextSimplify = 30000;
if (nClauses() * learntsize_factor < nbclausesbeforereduce) {
if (nClauses() * learntsize_factor < nbclausesbeforereduce/2)
nbclausesbeforereduce = (nClauses() * learntsize_factor)/2;
}
- performStepsBeforeSolve();
- if (!ok) return l_False;
-
- printStatHeader();
+ if (conflicts == 0) {
+ performStepsBeforeSolve();
+ if (!ok) return l_False;
- RestartTypeChooser restartTypeChooser(this);
+ printStatHeader();
+ if (calculateDefaultPolarities() == l_False)
+ return l_False;
+ setDefaultPolarities();
+ }
// Search:
while (status == l_Undef && starts < maxRestarts) {
+
+ if (schedSimplification && conflicts >= nextSimplify) {
+ status = simplifyProblem(500, 7000000);
+ nextSimplify = conflicts * 1.5;
+ if (status != l_Undef) break;
+ }
+
printRestartStat();
#ifdef STATS_NEEDED
if (dynamic_behaviour_analysis) {
}
#endif
- status = search((int)nof_conflicts);
- nof_conflicts *= restart_inc;
-
- chooseRestartType(status, restartTypeChooser);
+ status = search(nof_conflicts, nof_conflicts_fullrestart);
+ nof_conflicts = (double)nof_conflicts * restart_inc;
+ if (!checkFullRestart(nof_conflicts, nof_conflicts_fullrestart, lastFullRestart))
+ return l_False;
+ chooseRestartType(lastFullRestart);
+ //if (avgBranchDepth.isvalid())
+ // std::cout << "avg branch depth:" << avgBranchDepth.getavg() << std::endl;
}
printEndSearchStat();
freeLater.clear();
if (status == l_True) {
- conglomerate->doCalcAtFinish();
- varReplacer->extendModel();
- // Extend & copy model:
- model.growTo(nVars());
- for (uint32_t i = 0; i != nVars(); i++) model[i] = value(i);
-#ifndef NDEBUG
- verifyModel();
-#endif
if (greedyUnbound) {
double time = cpuTime();
FindUndef finder(*this);
if (verbosity >= 1)
printf("c Greedy unbounding :%5.2lf s, unbounded: %7d vars\n", cpuTime()-time, unbounded);
}
- } if (status == l_False) {
+
+ partHandler->addSavedState();
+ conglomerate->doCalcAtFinish();
+ varReplacer->extendModelPossible();
+#ifndef NDEBUG
+ //checkSolution();
+#endif
+
+ if (subsumer->getNumElimed() > 0) {
+ Solver s;
+ s.doSubsumption = false;
+ s.findBinaryXors = false;
+ s.findNormalXors = false;
+ s.failedVarSearch = false;
+ s.greedyUnbound = greedyUnbound;
+ for (Var var = 0; var < nVars(); var++) {
+ s.newVar(decision_var[var] || subsumer->getVarElimed()[var] || varReplacer->varHasBeenReplaced(var));
+ if (value(var) != l_Undef) {
+ vec<Lit> tmp;
+ tmp.push(Lit(var, value(var) == l_False));
+ s.addClause(tmp);
+ }
+ }
+ varReplacer->extendModelImpossible(s);
+ subsumer->extendModel(s);
+
+ status = s.solve();
+ assert(status == l_True);
+ for (Var var = 0; var < nVars(); var++) {
+ if (assigns[var] == l_Undef) uncheckedEnqueue(Lit(var, s.model[var] == l_False));
+ }
+ }
+ // Extend & copy model:
+#ifndef NDEBUG
+ //checkSolution();
+#endif
+ model.growTo(nVars());
+ for (Var var = 0; var != nVars(); var++) model[var] = value(var);
+
+ }
+
+ if (status == l_False) {
if (conflict.size() == 0)
ok = false;
}
#ifdef LS_STATS_NBBUMP
for(int i=0;i<learnts.size();i++)
printf("## %d %d %d\n", learnts[i]->size(),learnts[i]->activity(),
- (unsigned int)learnts[i]->nbBump());
+ (uint)learnts[i]->nbBump());
#endif
cancelUntil(0);
+ if (doPartHandler && status != l_False) partHandler->readdRemovedClauses();
+
return status;
}
bool final = c.xor_clause_inverted();
#ifdef VERBOSE_DEBUG
- XorClause* c2 = XorClause_new(c, c.xor_clause_inverted(), c.group);
+ XorClause* c2 = XorClause_new(c, c.xor_clause_inverted(), c.getGroup());
std::sort(c2->getData(), c2->getData()+ c2->size());
c2->plainPrint();
free(c2);
return failed;
}
-void Solver::verifyModel()
+bool Solver::verifyClauses(const vec<Clause*>& cs) const
{
+ #ifdef VERBOSE_DEBUG
+ cout << "Checking clauses whether they have been properly satisfied." << endl;;
+ #endif
+
bool failed = false;
- for (uint32_t i = 0; i != clauses.size(); i++) {
- Clause& c = *clauses[i];
+
+ for (uint32_t i = 0; i != cs.size(); i++) {
+ Clause& c = *cs[i];
for (uint j = 0; j < c.size(); j++)
if (modelValue(c[j]) == l_True)
goto next;
-
+
printf("unsatisfied clause: ");
- clauses[i]->plainPrint();
+ cs[i]->plainPrint();
failed = true;
-next:
+ next:
;
}
- failed |= verifyXorClauses(xorclauses);
- failed |= verifyXorClauses(conglomerate->getCalcAtFinish());
+ return failed;
+}
- assert(!failed);
+void Solver::verifyModel()
+{
+ assert(!verifyClauses(clauses));
+ assert(!verifyClauses(binaryClauses));
+
+ assert(!verifyXorClauses(xorclauses));
+ assert(!verifyXorClauses(conglomerate->getCalcAtFinish()));
if (verbosity >=1)
printf("c Verified %d clauses.\n", clauses.size() + xorclauses.size() + conglomerate->getCalcAtFinish().size());
void Solver::printRestartStat() const
{
#ifdef STATS_NEEDED
- if (verbosity >= 1 && !(dynamic_behaviour_analysis && logger.statistics_on)) {
+ if (verbosity >= 2 && !(dynamic_behaviour_analysis && logger.statistics_on)) {
#else
- if (verbosity >= 1) {
+ if (verbosity >= 2) {
#endif
- printf("c | %9d | %7d %8d %8d | %8d %8d %6.0f |", (int)conflicts, (int)order_heap.size(), (int)nClauses(), (int)clauses_literals, (int)(nbclausesbeforereduce*curRestart), (int)nLearnts(), (double)learnts_literals/nLearnts());
+ printf("c | %9d | %7d %8d %8d | %8d %8d %6.0f |", (int)conflicts, (int)order_heap.size(), (int)nClauses(), (int)clauses_literals, (int)(nbclausesbeforereduce*curRestart+nbCompensateSubsumer), (int)nLearnts(), (double)learnts_literals/nLearnts());
print_gauss_sum_stats();
}
}
}
}
+}; //NAMESPACE MINISAT
-};
#include <cstdio>
#include <string.h>
#include <stdio.h>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
-#include "mtl/Vec.h"
-#include "mtl/Heap.h"
-#include "mtl/Alg.h"
-#include "MTRand/MersenneTwister.h"
+#include "Vec.h"
+#include "Heap.h"
+#include "Alg.h"
+#include "MersenneTwister.h"
#include "SolverTypes.h"
#include "Clause.h"
-#include "VarReplacer.h"
#include "GaussianConfig.h"
#include "Logger.h"
#include "constants.h"
#include "BoundedQueue.h"
-#include "RestartTypeChooser.h"
-
-#ifdef _MSC_VER
- #include <ctime>
-#else
- #include <sys/time.h>
- #include <sys/resource.h>
- #include <unistd.h>
-#endif
namespace MINISAT
{
class XorFinder;
class FindUndef;
class ClauseCleaner;
+class FailedVarSearcher;
+class Subsumer;
+class PartHandler;
+class RestartTypeChooser;
#ifdef VERBOSE_DEBUG
using std::cout;
using std::endl;
#endif
-
//=================================================================================================
// Solver -- the main class:
+
class Solver
{
public:
// Problem specification:
//
- Var newVar (bool polarity = true, bool dvar = true); // Add a new variable with parameters specifying variable mode.
- bool addClause (vec<Lit>& ps, const uint group, char* group_name); // Add a clause to the solver. NOTE! 'ps' may be shrunk by this method!
- bool addXorClause (vec<Lit>& ps, bool xor_clause_inverted, const uint group, char* group_name, const bool internal = false); // Add a xor-clause to the solver. NOTE! 'ps' may be shrunk by this method!
+ Var newVar (bool dvar = true); // Add a new variable with parameters specifying variable mode.
+ template<class T>
+ bool addClause (T& ps, const uint group = 0, char* group_name = ""); // Add a clause to the solver. NOTE! 'ps' may be shrunk by this method!
+ template<class T>
+ bool addXorClause (T& ps, bool xor_clause_inverted, const uint group = 0, char* group_name = ""); // Add a xor-clause to the solver. NOTE! 'ps' may be shrunk by this method!
// Solving:
//
void setDecisionVar (Var v, bool b); // Declare if a variable should be eligible for selection in the decision heuristic.
void setSeed (const uint32_t seed); // Sets the seed to be the given number
void setMaxRestarts(const uint num); //sets the maximum number of restarts to given value
- void set_gaussian_decision_until(const uint to);
- template<class T>
- void removeWatchedCl(vec<T> &ws, const Clause *c);
- template<class T>
- bool findWatchedCl(vec<T>& ws, const Clause *c);
- template<class T>
- void removeWatchedBinCl(vec<T> &ws, const Clause *c);
- template<class T>
- bool findWatchedBinCl(vec<T>& ws, const Clause *c);
// Read state:
//
lbool modelValue (const Lit& p) const; // The value of a literal in the last model. The last call to solve must have been satisfiable.
uint32_t nAssigns () const; // The current number of assigned literals.
uint32_t nClauses () const; // The current number of original clauses.
+ uint32_t nLiterals () const; // The current number of total literals.
uint32_t nLearnts () const; // The current number of learnt clauses.
uint32_t nVars () const; // The current number of variables.
int polarity_mode; // Controls which polarity the decision heuristic chooses. See enum below for allowed modes. (default polarity_false)
int verbosity; // Verbosity level. 0=silent, 1=some progress report (default 0)
Var restrictedPickBranch; // Pick variables to branch on preferentally from the highest [0, restrictedPickBranch]. If set to 0, preferentiality is turned off (i.e. picked randomly between [0, all])
- bool xorFinder; // Automatically find xor-clauses and convert them
+ bool findNormalXors; // Automatically find non-binary xor-clauses and convert them
+ bool findBinaryXors; // Automatically find binary xor-clauses and convert them
+ bool regularlyFindBinaryXors; // Regularly find binary xor-clauses and convert them
bool performReplace; // Should var-replacing be performed?
+ bool conglomerateXors; // Conglomerate XORs
+ bool heuleProcess; // Process XORs according to Heule
+ bool schedSimplification;// Schedule simplification
+ bool doSubsumption; // Should try to subsume clauses
+ bool doXorSubsumption; // Should try to subsume xor clauses
+ bool doPartHandler; // Should try to subsume clauses
+ bool doHyperBinRes; // Should try carry out hyper-binary resolution
+ bool doBlockedClause; // Should try to remove blocked clauses
+ bool failedVarSearch; // Should search for failed vars and doulbly propagated vars
+ bool libraryUsage; // Set true if not used as a library
+ bool sateliteUsed; // whether satielite was used on CNF before calling
friend class FindUndef;
bool greedyUnbound; //If set, then variables will be greedily unbounded (set to l_Undef)
RestartType fixRestartType; // If set, the solver will always choose the given restart strategy
-
+ GaussianConfig gaussconfig;
- enum { polarity_true = 0, polarity_false = 1, polarity_user = 2, polarity_rnd = 3 };
+ enum { polarity_true = 0, polarity_false = 1, polarity_rnd = 3, polarity_auto = 4, polarity_manual = 5};
// Statistics: (read-only member variable)
//
- uint64_t starts, decisions, rnd_decisions, propagations, conflicts;
+ uint64_t starts, dynStarts, staticStarts, fullStarts, decisions, rnd_decisions, propagations, conflicts;
uint64_t clauses_literals, learnts_literals, max_literals, tot_literals;
- uint64_t nbDL2, nbBin, lastNbBin, nbReduceDB;
+ uint64_t nbDL2, nbBin, lastNbBin, becameBinary, lastSearchForBinaryXor, nbReduceDB;
+ uint64_t improvedClauseNo, improvedClauseSize;
//Logging
void needStats(); // Prepares the solver to output statistics
const vec<Clause*>& get_learnts() const; //Get all learnt clauses that are >1 long
const vector<Lit> get_unitary_learnts() const; //return the set of unitary learnt clauses
const uint get_unitary_learnts_num() const; //return the number of unitary learnt clauses
- void dump_sorted_learnts(const char* file); // Dumps all learnt clauses (including unitary ones) into the file
+ void dumpSortedLearnts(const char* file, const uint32_t maxSize); // Dumps all learnt clauses (including unitary ones) into the file
void needLibraryCNFFile(const char* fileName); //creates file in current directory with the filename indicated, and puts all calls from the library into the file.
protected:
vector<Gaussian*> gauss_matrixes;
- GaussianConfig gaussconfig;
void print_gauss_sum_stats() const;
void clearGaussMatrixes();
friend class Gaussian;
+ template <class T>
+ Clause* addClauseInt(T& ps, uint group);
+ template<class T>
+ XorClause* addXorClauseInt(T& ps, bool xor_clause_inverted, const uint32_t group);
+ template<class T>
+ bool addLearntClause(T& ps, const uint group, const uint32_t activity);
+ template<class T>
+ void removeWatchedCl(vec<T> &ws, const Clause *c);
+ template<class T>
+ bool findWatchedCl(vec<T>& ws, const Clause *c);
+ template<class T>
+ void removeWatchedBinCl(vec<T> &ws, const Clause *c);
+ template<class T>
+ bool findWatchedBinCl(vec<T>& ws, const Clause *c);
// Helper structures:
//
//
bool ok; // If FALSE, the constraints are already unsatisfiable. No part of the solver state may be used!
vec<Clause*> clauses; // List of problem clauses.
+ vec<Clause*> binaryClauses; // Binary clauses are regularly moved here
vec<XorClause*> xorclauses; // List of problem xor-clauses. Will be freed
vec<Clause*> learnts; // List of learnt clauses.
vec<XorClause*> freeLater; // List of xorclauses to free at the end (due to matrixes, they cannot be freed immediately)
vec<double> activity; // A heuristic measurement of the activity of a variable.
double var_inc; // Amount to bump next variable with.
vec<vec<Watched> > watches; // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true).
- vec<vec<XorClause*> > xorwatches; // 'xorwatches[var]' is a list of constraints watching var in XOR clauses.
+ vec<vec<XorClausePtr> > xorwatches; // 'xorwatches[var]' is a list of constraints watching var in XOR clauses.
vec<vec<WatchedBin> > binwatches;
vec<lbool> assigns; // The current assignments
vector<bool> polarity; // The preferred polarity of each variable.
vector<bool> decision_var; // Declares if a variable is eligible for selection in the decision heuristic.
vec<Lit> trail; // Assignment stack; stores all assigments made in the order they were made.
vec<uint32_t> trail_lim; // Separator indices for different decision levels in 'trail'.
- vec<Clause*> reason; // 'reason[var]' is the clause that implied the variables current value, or 'NULL' if none.
+ vec<ClausePtr> reason; // 'reason[var]' is the clause that implied the variables current value, or 'NULL' if none.
vec<int32_t> level; // 'level[var]' contains the level at which the assignment was made.
vec<Var> permDiff; // LS: permDiff[var] contains the current conflict number... Used to count the number of different decision level variables in learnt clause
#ifdef UPDATEVARACTIVITY
vec<Lit> lastDecisionLevel;
#endif
uint64_t curRestart;
- uint64_t conf4Stats;
uint32_t nbclausesbeforereduce;
+ uint32_t nbCompensateSubsumer; // Number of learnt clauses that subsumed normal clauses last time subs. was executed
uint32_t qhead; // Head of queue (as index into the trail -- no more explicit propagation queue in MiniSat).
uint32_t simpDB_assigns; // Number of top-level assignments since last execution of 'simplify()'.
int64_t simpDB_props; // Remaining number of propagations that must be made before next execution of 'simplify()'.
Heap<VarOrderLt> order_heap; // A priority queue of variables ordered with respect to the variable activity.
double progress_estimate;// Set by 'search()'.
bool remove_satisfied; // Indicates whether possibly inefficient linear scan for satisfied clauses should be performed in 'simplify'.
- bqueue<unsigned int> nbDecisionLevelHistory; // Set of last decision level in conflict clauses
- float totalSumOfDecisionLevel;
+ bqueue<uint> nbDecisionLevelHistory; // Set of last decision level in conflict clauses
+ double totalSumOfDecisionLevel;
+ uint64_t conflictsAtLastSolve;
+ bqueue<uint> avgBranchDepth; // Avg branch depth
MTRand mtrand; // random number generaton
RestartType restartType; // Used internally to determine which restart strategy to choose
friend class Logger;
// Temporaries (to reduce allocation overhead). Each variable is prefixed by the method in which it is
// used, exept 'seen' wich is used in several places.
//
- vec<char> seen;
+ vector<bool> seen;
vec<Lit> analyze_stack;
vec<Lit> analyze_toclear;
vec<Lit> add_tmp;
lbool simplify (); // Removes already satisfied clauses.
//int nbPropagated (int level);
void insertVarOrder (Var x); // Insert a variable in the decision order priority queue.
- Lit pickBranchLit (int polarity_mode); // Return the next decision variable.
+ Lit pickBranchLit (); // Return the next decision variable.
void newDecisionLevel (); // Begins a new decision level.
- void uncheckedEnqueue (Lit p, Clause* from = NULL); // Enqueue a literal. Assumes value of literal is undefined.
+ void uncheckedEnqueue (Lit p, ClausePtr from = (Clause*)NULL); // Enqueue a literal. Assumes value of literal is undefined.
bool enqueue (Lit p, Clause* from = NULL); // Test if fact 'p' contradicts current state, enqueue otherwise.
- Clause* propagate (const bool xor_as_well = true); // Perform unit propagation. Returns possibly conflicting clause.
+ Clause* propagate (const bool update = true); // Perform unit propagation. Returns possibly conflicting clause.
Clause* propagate_xors (const Lit& p);
void cancelUntil (int level); // Backtrack until a certain level.
- void analyze (Clause* confl, vec<Lit>& out_learnt, int& out_btlevel, int &nblevels); // (bt = backtrack)
+ Clause* analyze (Clause* confl, vec<Lit>& out_learnt, int& out_btlevel, int &nblevels); // (bt = backtrack)
void analyzeFinal (Lit p, vec<Lit>& out_conflict); // COULD THIS BE IMPLEMENTED BY THE ORDINARIY "analyze" BY SOME REASONABLE GENERALIZATION?
bool litRedundant (Lit p, uint32_t abstract_levels); // (helper method for 'analyze()')
- lbool search (int nof_conflicts); // Search for a given number of conflicts.
+ lbool search (int nof_conflicts, int nof_conflicts_fullrestart, const bool update = true); // Search for a given number of conflicts.
void reduceDB (); // Reduce the set of learnt clauses.
- llbool handle_conflict (vec<Lit>& learnt_clause, Clause* confl, int& conflictC);// Handles the conflict clause
- llbool new_decision (int& nof_conflicts, int& conflictC); // Handles the case when all propagations have been made, and now a decision must be made
+ llbool handle_conflict (vec<Lit>& learnt_clause, Clause* confl, int& conflictC, const bool update);// Handles the conflict clause
+ llbool new_decision (const int& nof_conflicts, const int& nof_conflicts_fullrestart, int& conflictC); // Handles the case when all propagations have been made, and now a decision must be made
// Maintaining Variable/Clause activity:
//
friend class XorFinder;
friend class Conglomerate;
friend class MatrixFinder;
+ friend class PartFinder;
friend class VarReplacer;
friend class ClauseCleaner;
friend class RestartTypeChooser;
+ friend class FailedVarSearcher;
+ friend class Subsumer;
+ friend class XorSubsumer;
+ friend class PartHandler;
Conglomerate* conglomerate;
VarReplacer* varReplacer;
ClauseCleaner* clauseCleaner;
- void chooseRestartType(const lbool& status, RestartTypeChooser& restartTypeChooser);
+ FailedVarSearcher* failedVarSearcher;
+ PartHandler* partHandler;
+ Subsumer* subsumer;
+ RestartTypeChooser* restartTypeChooser;
+ void chooseRestartType(const uint& lastFullRestart);
+ void setDefaultRestartType();
+ const bool checkFullRestart(int& nof_conflicts, int& nof_conflicts_fullrestart, uint& lastFullRestart);
void performStepsBeforeSolve();
+ const lbool simplifyProblem(const uint32_t numConfls, const uint64_t numProps);
+ bool simplifying;
// Debug & etc:
void printLit (const Lit l) const;
void verifyModel ();
+ bool verifyClauses (const vec<Clause*>& cs) const;
bool verifyXorClauses (const vec<XorClause*>& cs) const;
+ void checkSolution();
void checkLiteralCount();
void printStatHeader () const;
void printRestartStat () const;
void printEndSearchStat() const;
double progressEstimate () const; // DELETE THIS ?? IT'S NOT VERY USEFUL ...
+
+ // Polarity chooser
+ vector<bool> defaultPolarities; //The default polarity to set the var polarity when doing a full restart
+ const lbool calculateDefaultPolarities(); //Calculates the default polarity for each var, and fills defaultPolarities[] with it
+ bool defaultPolarity(); //if polarity_mode is not polarity_auto, this returns the default polarity of the variable
+ void setDefaultPolarities(); //sets the polarity[] to that indicated by defaultPolarities[]
};
inline void Solver::varBumpActivity(Var v)
{
if ( (activity[v] += var_inc) > 1e100 ) {
+ //printf("RESCALE!!!!!!\n");
+ //std::cout << "var_inc: " << var_inc << std::endl;
// Rescale:
- for (uint32_t i = 0; i != nVars(); i++)
- activity[i] *= 1e-100;
+ for (Var var = 0; var != nVars(); var++) {
+ activity[var] *= 1e-95;
+ }
var_inc *= 1e-100;
+ //var_inc = 1;
+ //std::cout << "var_inc: " << var_inc << std::endl;
+
+ /*Heap<VarOrderLt> copy_order_heap2(order_heap);
+ while(!copy_order_heap2.empty()) {
+ Var v = copy_order_heap2.getmin();
+ if (decision_var[v])
+ std::cout << "var_" << v+1 << " act: " << activity[v] << std::endl;
+ }*/
}
// Update order_heap with respect to new activity:
}
inline uint32_t Solver::nClauses () const
{
- return clauses.size() + xorclauses.size();
+ return clauses.size() + xorclauses.size()+binaryClauses.size();
+}
+inline uint32_t Solver::nLiterals () const
+{
+ return clauses_literals + learnts_literals;
}
inline uint32_t Solver::nLearnts () const
{
inline void Solver::setVariableName(Var var, char* name)
{}
#endif
+
inline const uint Solver::get_unitary_learnts_num() const
{
if (decisionLevel() > 0)
c[0] = c[1], c[1] = tmp;
}
}
+/*inline void Solver::calculate_xor_clause(Clause& c2) const {
+ if (c2.isXor() && ((XorClause*)&c2)->updateNeeded()) {
+ XorClause& c = *((XorClause*)&c2);
+ bool final = c.xor_clause_inverted();
+ for (int k = 0, size = c.size(); k != size; k++ ) {
+ const lbool& val = assigns[c[k].var()];
+ assert(val != l_Undef);
+
+ c[k] = c[k].unsign() ^ val.getBool();
+ final ^= val.getBool();
+ }
+ if (final)
+ c[0] = c[0].unsign() ^ !assigns[c[0].var()].getBool();
+
+ c.setUpdateNeeded(false);
+ }
+}*/
+
inline void Solver::removeClause(Clause& c)
{
detachClause(c);
- free(&c);
+ clauseFree(&c);
}
inline void Solver::removeClause(XorClause& c)
{
detachClause(c);
freeLater.push(&c);
- c.mark(1);
}
}
//=================================================================================================
-};
+
+}; //NAMESPACE MINISAT
#endif //SOLVER_H
#define SOLVERTYPES_H
#include <cassert>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
#include <stdint.h>
-#include "mtl/Alg.h"
+#endif //_MSC_VER
+
+#include "Alg.h"
namespace MINISAT
{
return Lit(x ^ 1);
}
Lit operator^(const bool b) const {
- return Lit(x ^ b);
+ return Lit(x ^ (uint32_t)b);
}
Lit& operator^=(const bool b) {
- x ^= b;
+ x ^= (uint32_t)b;
return *this;
}
bool sign() const {
return value;
}
inline const bool getBool() const {
- return (value+1) >> 1;
+ return value == 1;
}
inline const bool operator==(lbool b) const {
return value == b.value;
return value != b.value;
}
lbool operator^(const bool b) const {
- return lbool(value - value*2*b);
+ return b ? lbool(-value) : lbool(value);
}
//lbool operator ^ (const bool b) const { return b ? lbool(-value) : lbool(value); }
const llbool l_Continue = toLbool(3);
lbool::lbool(llbool b) : value(b.value) {};
-};
+
+}; //NAMESPACE MINISAT
#endif //SOLVERTYPES_H
--- /dev/null
+/**************************************************************************************************
+Originally From: Solver.C -- (C) Niklas Een, Niklas Sorensson, 2004
+Substantially modified by: Mate Soos (2010)
+**************************************************************************************************/
+
+#include "Solver.h"
+#include "Subsumer.h"
+#include "ClauseCleaner.h"
+#include "time_mem.h"
+#include "assert.h"
+#include <iomanip>
+#include <cmath>
+#include <algorithm>
+#include "VarReplacer.h"
+#include "Conglomerate.h"
+#include "XorFinder.h"
+
+#ifdef _MSC_VER
+#define __builtin_prefetch(a,b,c)
+#endif //_MSC_VER
+
+
+//#define VERBOSE_DEBUG
+#ifdef VERBOSE_DEBUG
+#define BIT_MORE_VERBOSITY
+#endif
+
+//#define BIT_MORE_VERBOSITY
+//#define HYPER_DEBUG
+//#define HYPER_DEBUG2
+//#define TOUCH_LESS
+
+#ifdef VERBOSE_DEBUG
+using std::cout;
+using std::endl;
+#endif //VERBOSE_DEBUG
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+Subsumer::Subsumer(Solver& s):
+ solver(s)
+ , numCalls(0)
+ , numElimed(0)
+{
+};
+
+Subsumer::~Subsumer()
+{
+}
+
+void Subsumer::extendModel(Solver& solver2)
+{
+ vec<Lit> tmp;
+ typedef map<Var, vector<vector<Lit> > > elimType;
+ for (elimType::iterator it = elimedOutVar.begin(), end = elimedOutVar.end(); it != end; it++) {
+ Var var = it->first;
+
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Reinserting elimed var: " << var+1 << std::endl;
+ #endif
+
+ for (vector<vector<Lit> >::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
+ tmp.clear();
+ tmp.growTo(it2->size());
+ std::copy(it2->begin(), it2->end(), tmp.getData());
+
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Reinserting Clause: ";
+ for (uint32_t i = 0; i < tmp.size(); i++) {
+ std::cout << (tmp[i].sign() ? "-" : "")<< tmp[i].var()+1 << " ";
+ }
+ std::cout << std::endl;
+ #endif
+
+ solver2.addClause(tmp);
+ assert(solver2.ok);
+ }
+ }
+}
+
+const bool Subsumer::unEliminate(const Var var)
+{
+ vec<Lit> tmp;
+ typedef map<Var, vector<vector<Lit> > > elimType;
+ elimType::iterator it = elimedOutVar.find(var);
+ assert(it != elimedOutVar.end());
+
+ solver.setDecisionVar(var, true);
+ var_elimed[var] = false;
+ numElimed--;
+ for (vector<vector<Lit> >::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
+ tmp.clear();
+ tmp.growTo(it2->size());
+ memcpy(tmp.getData(), &((*it2)[0]), sizeof(Lit)*it2->size()); //*it2 is never empty
+ solver.addClause(tmp);
+ }
+ elimedOutVar.erase(it);
+
+ if (!solver.ok) return false;
+ return true;
+}
+
+bool selfSubset(uint32_t A, uint32_t B)
+{
+ uint32_t B_tmp = B | ((B & 0xAAAAAAAALL) >> 1) | ((B & 0x55555555LL) << 1);
+ if ((A & ~B_tmp) == 0){
+ uint32_t C = A & ~B;
+ return (C & (C-1)) == 0;
+ }else
+ return false;
+}
+
+// Assumes 'seen' is cleared (will leave it cleared)
+bool selfSubset(Clause& A, Clause& B, vec<char>& seen)
+{
+ for (uint32_t i = 0; i < B.size(); i++)
+ seen[B[i].toInt()] = 1;
+
+ bool flip = false;
+ for (uint32_t i = 0; i < A.size(); i++) {
+ if (!seen[A[i].toInt()]) {
+ if (flip == true || !seen[(~A[i]).toInt()]) {
+ for (uint32_t i = 0; i < B.size(); i++) seen[B[i].toInt()] = 0;
+ return false;
+ }
+ flip = true;
+ }
+ }
+ for (uint32_t i = 0; i < B.size(); i++)
+ seen[B[i].toInt()] = 0;
+ return flip;
+}
+
+// Will put NULL in 'cs' if clause removed.
+uint32_t Subsumer::subsume0(Clause& ps)
+{
+ ps.subsume0Finished();
+ ps.unsetVarChanged();
+ uint32_t retIndex = std::numeric_limits<uint32_t>::max();
+ #ifdef VERBOSE_DEBUG
+ cout << "subsume0 orig clause:";
+ ps.plainPrint();
+ cout << "pointer:" << &ps << endl;
+ #endif
+
+ vec<ClauseSimp> subs;
+ findSubsumed(ps, subs);
+ for (uint32_t i = 0; i < subs.size(); i++){
+ clauses_subsumed++;
+ #ifdef VERBOSE_DEBUG
+ cout << "subsume0 removing:";
+ subs[i].clause->plainPrint();
+ #endif
+
+ Clause* tmp = subs[i].clause;
+ unlinkClause(subs[i]);
+ free(tmp);
+ retIndex = subs[i].index;
+ }
+
+ return retIndex;
+}
+
+// Will put NULL in 'cs' if clause removed.
+uint32_t Subsumer::subsume0(Clause& ps, uint32_t abs)
+{
+ ps.subsume0Finished();
+ ps.unsetVarChanged();
+ uint32_t retIndex = std::numeric_limits<uint32_t>::max();
+ #ifdef VERBOSE_DEBUG
+ cout << "subsume0 orig clause:";
+ ps.plainPrint();
+ cout << "pointer:" << &ps << endl;
+ #endif
+
+ vec<ClauseSimp> subs;
+ findSubsumed(ps, abs, subs);
+ for (uint32_t i = 0; i < subs.size(); i++){
+ clauses_subsumed++;
+ #ifdef VERBOSE_DEBUG
+ cout << "subsume0 removing:";
+ subs[i].clause->plainPrint();
+ #endif
+
+ Clause* tmp = subs[i].clause;
+ unlinkClause(subs[i]);
+ free(tmp);
+ retIndex = subs[i].index;
+ }
+
+ return retIndex;
+}
+
+void Subsumer::unlinkClause(ClauseSimp c, Var elim)
+{
+ Clause& cl = *c.clause;
+
+ if (elim != var_Undef) {
+ assert(!cl.learnt());
+ io_tmp.clear();
+ for (int i = 0; i < cl.size(); i++)
+ io_tmp.push_back(cl[i]);
+ elimedOutVar[elim].push_back(io_tmp);
+ }
+
+ if (updateOccur(cl)) {
+ for (uint32_t i = 0; i < cl.size(); i++) {
+ maybeRemove(occur[cl[i].toInt()], &cl);
+ #ifndef TOUCH_LESS
+ touch(cl[i]);
+ #endif
+ }
+ }
+
+ solver.detachClause(cl);
+
+ // Remove from iterator vectors/sets:
+ for (uint32_t i = 0; i < iter_vecs.size(); i++) {
+ vec<ClauseSimp>& cs = *iter_vecs[i];
+ for (uint32_t j = 0; j < cs.size(); j++)
+ if (cs[j].clause == &cl)
+ cs[j].clause = NULL;
+ }
+ for (uint32_t i = 0; i < iter_sets.size(); i++) {
+ CSet& cs = *iter_sets[i];
+ cs.exclude(c);
+ }
+
+ // Remove clause from clause touched set:
+ if (updateOccur(cl)) {
+ cl_touched.exclude(c);
+ cl_added.exclude(c);
+ }
+
+ clauses[c.index].clause = NULL;
+}
+
+void Subsumer::unlinkModifiedClause(vec<Lit>& origClause, ClauseSimp c)
+{
+ if (updateOccur(*c.clause)) {
+ for (uint32_t i = 0; i < origClause.size(); i++) {
+ maybeRemove(occur[origClause[i].toInt()], c.clause);
+ #ifndef TOUCH_LESS
+ touch(origClause[i]);
+ #endif
+ }
+ }
+
+ solver.detachModifiedClause(origClause[0], origClause[1], origClause.size(), c.clause);
+
+ // Remove from iterator vectors/sets:
+ for (uint32_t i = 0; i < iter_vecs.size(); i++){
+ vec<ClauseSimp>& cs = *iter_vecs[i];
+ for (uint32_t j = 0; j < cs.size(); j++)
+ if (cs[j].clause == c.clause)
+ cs[j].clause = NULL;
+ }
+ for (uint32_t i = 0; i < iter_sets.size(); i++){
+ CSet& cs = *iter_sets[i];
+ cs.exclude(c);
+ }
+
+ // Remove clause from clause touched set:
+ if (updateOccur(*c.clause)) {
+ cl_touched.exclude(c);
+ cl_added.exclude(c);
+ }
+
+ clauses[c.index].clause = NULL;
+}
+
+void Subsumer::unlinkModifiedClauseNoDetachNoNULL(vec<Lit>& origClause, ClauseSimp c)
+{
+ if (updateOccur(*c.clause)) {
+ for (uint32_t i = 0; i < origClause.size(); i++) {
+ maybeRemove(occur[origClause[i].toInt()], c.clause);
+ #ifndef TOUCH_LESS
+ touch(origClause[i]);
+ #endif
+ }
+ }
+
+ // Remove from iterator vectors/sets:
+ for (uint32_t i = 0; i < iter_vecs.size(); i++){
+ vec<ClauseSimp>& cs = *iter_vecs[i];
+ for (uint32_t j = 0; j < cs.size(); j++)
+ if (cs[j].clause == c.clause)
+ cs[j].clause = NULL;
+ }
+ for (uint32_t i = 0; i < iter_sets.size(); i++){
+ CSet& cs = *iter_sets[i];
+ cs.exclude(c);
+ }
+
+ // Remove clause from clause touched set:
+ if (updateOccur(*c.clause)) {
+ cl_touched.exclude(c);
+ cl_added.exclude(c);
+ }
+}
+
+void Subsumer::subsume1(ClauseSimp& ps)
+{
+ vec<ClauseSimp> Q;
+ vec<ClauseSimp> subs;
+ vec<Lit> qs;
+ uint32_t q;
+
+ ps.clause->unsetStrenghtened();
+ registerIteration(Q);
+ registerIteration(subs);
+
+ Q.push(ps);
+ q = 0;
+ while (q < Q.size()){
+ if (Q[q].clause == NULL) { q++; continue; }
+ #ifdef VERBOSE_DEBUG
+ cout << "subsume1 orig clause:";
+ Q[q].clause->plainPrint();
+ #endif
+
+ qs.clear();
+ for (uint32_t i = 0; i < Q[q].clause->size(); i++)
+ qs.push((*Q[q].clause)[i]);
+
+ for (uint32_t i = 0; i < qs.size(); i++){
+ qs[i] = ~qs[i];
+
+ uint32_t abst = calcAbstraction(qs);
+
+ findSubsumed(qs, abst, subs);
+ for (uint32_t j = 0; j < subs.size(); j++){
+ /*#ifndef NDEBUG
+ if (&counter != NULL && counter == -1){
+ dump(*subs[j].clause);
+ qs[i] = ~qs[i];
+ dump(qs);
+ printf(L_LIT"\n", L_lit(qs[i]));
+ exit(0);
+ }
+ #endif*/
+ if (subs[j].clause == NULL) continue;
+ ClauseSimp c = subs[j];
+ Clause& cl = *c.clause;
+ #ifdef VERBOSE_DEBUG
+ cout << "orig clause :";
+ cl.plainPrint();
+ #endif
+ unlinkClause(subs[j]);
+
+ literals_removed++;
+ cl.strengthen(qs[i]);
+ Lit *a, *b, *end;
+ for (a = b = cl.getData(), end = a + cl.size(); a != end; a++) {
+ lbool val = solver.value(*a);
+ if (val == l_Undef)
+ *b++ = *a;
+
+ if (val == l_True) {
+ free(&cl);
+ goto endS;
+ }
+ }
+ cl.shrink(a-b);
+ cl.setStrenghtened();
+
+ #ifdef VERBOSE_DEBUG
+ cout << "strenghtened :";
+ c.clause->plainPrint();
+ #endif
+
+ if (cl.size() == 0) {
+ solver.ok = false;
+ unregisterIteration(Q);
+ unregisterIteration(subs);
+ free(&cl);
+ return;
+ }
+ if (cl.size() > 1) {
+ cl.calcAbstraction();
+ linkInAlreadyClause(c);
+ clauses[c.index] = c;
+ solver.attachClause(cl);
+ if (cl.size() == 2) solver.becameBinary++;
+ updateClause(c);
+ Q.push(c);
+ } else {
+ assert(cl.size() == 1);
+ solver.uncheckedEnqueue(cl[0]);
+ solver.ok = (solver.propagate() == NULL);
+ if (!solver.ok) {
+ unregisterIteration(Q);
+ unregisterIteration(subs);
+ return;
+ }
+ #ifdef VERBOSE_DEBUG
+ cout << "Found that var " << cl[0].var()+1 << " must be " << std::boolalpha << !cl[0].sign() << endl;
+ #endif
+ free(&cl);
+ }
+ endS:;
+ }
+
+ qs[i] = ~qs[i];
+ subs.clear();
+ }
+ q++;
+ }
+
+ unregisterIteration(Q);
+ unregisterIteration(subs);
+}
+
+void Subsumer::updateClause(ClauseSimp c)
+{
+ if (!c.clause->learnt()) subsume0(*c.clause);
+
+ cl_touched.add(c);
+}
+
+void Subsumer::almost_all_database()
+{
+ #ifdef BIT_MORE_VERBOSITY
+ std::cout << "c Larger database" << std::endl;
+ #endif
+ // Optimized variant when virtually whole database is involved:
+ cl_added .clear();
+ cl_touched.clear();
+
+ for (uint32_t i = 0; i < clauses.size(); i++) {
+ if (numMaxSubsume1 == 0) break;
+ if (clauses[i].clause != NULL && updateOccur(*clauses[i].clause)) {
+ subsume1(clauses[i]);
+ numMaxSubsume1--;
+ if (!solver.ok) return;
+ }
+ }
+
+ assert(solver.ok);
+ solver.ok = (solver.propagate() == NULL);
+ if (!solver.ok) {
+ std::cout << "c (contradiction during subsumption)" << std::endl;
+ return;
+ }
+ solver.clauseCleaner->cleanClausesBewareNULL(clauses, ClauseCleaner::simpClauses, *this);
+
+ #ifdef VERBOSE_DEBUG
+ cout << "subsume1 part 1 finished" << endl;
+ #endif
+
+ CSet s1;
+ registerIteration(s1);
+ while (cl_touched.size() > 0 && numMaxSubsume1 > 0){
+ #ifdef VERBOSE_DEBUG
+ std::cout << "c cl_touched was > 0, new iteration" << std::endl;
+ #endif
+ for (CSet::iterator it = cl_touched.begin(), end = cl_touched.end(); it != end; ++it) {
+ if (it->clause != NULL)
+ s1.add(*it);
+ }
+ cl_touched.clear();
+
+ for (CSet::iterator it = s1.begin(), end = s1.end(); it != end; ++it) {
+ if (numMaxSubsume1 == 0) break;
+ if (it->clause != NULL) {
+ subsume1(*it);
+ numMaxSubsume1--;
+ if (!solver.ok) return;
+ }
+ }
+ s1.clear();
+
+ if (!solver.ok) return;
+ solver.ok = (solver.propagate() == NULL);
+ if (!solver.ok) {
+ printf("c (contradiction during subsumption)\n");
+ unregisterIteration(s1);
+ return;
+ }
+ solver.clauseCleaner->cleanClausesBewareNULL(clauses, ClauseCleaner::simpClauses, *this);
+ }
+ unregisterIteration(s1);
+}
+
+void Subsumer::smaller_database()
+{
+ #ifdef BIT_MORE_VERBOSITY
+ std::cout << "c Smaller database" << std::endl;
+ #endif
+ // Set used in 1-subs:
+ // (1) clauses containing a negated literal of an added clause.
+ // (2) all added or strengthened ("touched") clauses.
+ //
+ // Set used in 0-subs:
+ // (1) clauses containing a (non-negated) literal of an added clause, including the added clause itself.
+ // (2) all strenghtened clauses -- REMOVED!! We turned on eager backward subsumption which supersedes this.
+
+ #ifdef BIT_MORE_VERBOSITY
+ printf(" PREPARING\n");
+ #endif
+
+ CSet s0, s1; // 's0' is used for 0-subsumption, 's1' for 1-subsumption
+ vec<char> ol_seen(solver.nVars()*2, 0);
+ for (CSet::iterator it = cl_added.begin(), end = cl_added.end(); it != end; ++it) {
+ if (it->clause == NULL) continue;
+ ClauseSimp& c = *it;
+ Clause& cl = *it->clause;
+
+ s1.add(c);
+ for (uint32_t j = 0; j < cl.size(); j++){
+ if (ol_seen[cl[j].toInt()]) continue;
+ ol_seen[cl[j].toInt()] = 1;
+
+ vec<ClauseSimp>& n_occs = occur[(~cl[j]).toInt()];
+ for (uint32_t k = 0; k < n_occs.size(); k++)
+ if (n_occs[k].clause != c.clause && n_occs[k].clause->size() <= cl.size() && selfSubset(n_occs[k].clause->getAbst(), c.clause->getAbst()) && selfSubset(*n_occs[k].clause, cl, seen_tmp))
+ s1.add(n_occs[k]);
+
+ vec<ClauseSimp>& p_occs = occur[cl[j].toInt()];
+ for (uint32_t k = 0; k < p_occs.size(); k++)
+ if (subsetAbst(p_occs[k].clause->getAbst(), c.clause->getAbst()))
+ s0.add(p_occs[k]);
+ }
+ }
+ cl_added.clear();
+
+ registerIteration(s0);
+ registerIteration(s1);
+
+ #ifdef BIT_MORE_VERBOSITY
+ printf(" FIXED-POINT\n");
+ #endif
+
+ // Fixed-point for 1-subsumption:
+ while (s1.size() > 0 || cl_touched.size() > 0){
+ for (CSet::iterator it = cl_touched.begin(), end = cl_touched.end(); it != end; ++it) {
+ if (it->clause != NULL) {
+ s1.add(*it);
+ s0.add(*it);
+ }
+ }
+
+ cl_touched.clear();
+ assert(solver.qhead == solver.trail.size());
+
+ #ifdef BIT_MORE_VERBOSITY
+ printf("s1.size()=%d cl_touched.size()=%d\n", s1.size(), cl_touched.size());
+ #endif
+
+ for (CSet::iterator it = s1.begin(), end = s1.end(); it != end; ++it) {
+ if (numMaxSubsume1 == 0) break;
+ if (it->clause != NULL) {
+ subsume1(*it);
+ numMaxSubsume1--;
+ if (!solver.ok) return;
+ }
+ }
+ s1.clear();
+
+ if (!solver.ok) return;
+ solver.ok = (solver.propagate() == NULL);
+ if (!solver.ok){
+ printf("c (contradiction during subsumption)\n");
+ unregisterIteration(s1);
+ unregisterIteration(s0);
+ return;
+ }
+ solver.clauseCleaner->cleanClausesBewareNULL(clauses, ClauseCleaner::simpClauses, *this);
+ }
+ unregisterIteration(s1);
+
+ // Iteration pass for 0-subsumption:
+ for (CSet::iterator it = s0.begin(), end = s0.end(); it != end; ++it) {
+ if (it->clause != NULL)
+ subsume0(*it->clause);
+ }
+ s0.clear();
+ unregisterIteration(s0);
+}
+
+ClauseSimp Subsumer::linkInClause(Clause& cl)
+{
+ ClauseSimp c(&cl, clauseID++);
+ clauses.push(c);
+ if (updateOccur(cl)) {
+ for (uint32_t i = 0; i < cl.size(); i++) {
+ occur[cl[i].toInt()].push(c);
+ touch(cl[i].var());
+ }
+ }
+ cl_added.add(c);
+
+ return c;
+}
+
+void Subsumer::linkInAlreadyClause(ClauseSimp& c)
+{
+ Clause& cl = *c.clause;
+
+ if (updateOccur(cl)) {
+ for (uint32_t i = 0; i < c.clause->size(); i++) {
+ occur[cl[i].toInt()].push(c);
+ touch(cl[i].var());
+ }
+ }
+}
+
+void Subsumer::addFromSolver(vec<Clause*>& cs)
+{
+ Clause **i = cs.getData();
+ Clause **j = i;
+ for (Clause **end = i + cs.size(); i != end; i++) {
+ if (i+1 != end)
+ __builtin_prefetch(*(i+1), 1, 1);
+
+ if ((*i)->learnt()) {
+ *j++ = *i;
+ (*i)->setUnsorted();
+ continue;
+ }
+ ClauseSimp c(*i, clauseID++);
+ clauses.push(c);
+ Clause& cl = *c.clause;
+ if (updateOccur(cl)) {
+ for (uint32_t i = 0; i < cl.size(); i++) {
+ occur[cl[i].toInt()].push(c);
+ touch(cl[i].var());
+ }
+ if (fullSubsume || cl.getVarChanged()) cl_added.add(c);
+ else if (cl.getStrenghtened()) cl_touched.add(c);
+
+ if (cl.getVarChanged() || cl.getStrenghtened())
+ cl.calcAbstraction();
+ }
+ }
+ cs.shrink(i-j);
+}
+
+void Subsumer::addBackToSolver()
+{
+ #ifdef HYPER_DEBUG2
+ uint32_t binaryLearntAdded = 0;
+ #endif
+
+ for (uint32_t i = 0; i < clauses.size(); i++) {
+ if (clauses[i].clause != NULL) {
+ assert(clauses[i].clause->size() > 1);
+ if (clauses[i].clause->size() == 2) {
+ #ifdef HYPER_DEBUG2
+ if (clauses[i].clause->learnt())
+ binaryLearntAdded++;
+ #endif
+ solver.binaryClauses.push(clauses[i].clause);
+ } else {
+ if (clauses[i].clause->learnt())
+ solver.learnts.push(clauses[i].clause);
+ else
+ solver.clauses.push(clauses[i].clause);
+ }
+ }
+ }
+
+ #ifdef HYPER_DEBUG2
+ std::cout << "Binary learnt added:" << binaryLearntAdded << std::endl;
+ #endif
+}
+
+void Subsumer::removeWrong(vec<Clause*>& cs)
+{
+ Clause **i = cs.getData();
+ Clause **j = i;
+ for (Clause **end = i + cs.size(); i != end; i++) {
+ Clause& c = **i;
+ if (!c.learnt()) {
+ *j++ = *i;
+ continue;
+ }
+ bool remove = false;
+ for (Lit *l = c.getData(), *end2 = l+c.size(); l != end2; l++) {
+ if (var_elimed[l->var()]) {
+ remove = true;
+ solver.detachClause(c);
+ free(&c);
+ break;
+ }
+ }
+ if (!remove)
+ *j++ = *i;
+ }
+ cs.shrink(i-j);
+}
+
+void Subsumer::fillCannotEliminate()
+{
+ std::fill(cannot_eliminate.getData(), cannot_eliminate.getDataEnd(), false);
+ for (uint32_t i = 0; i < solver.xorclauses.size(); i++) {
+ const XorClause& c = *solver.xorclauses[i];
+ for (uint32_t i2 = 0; i2 < c.size(); i2++)
+ cannot_eliminate[c[i2].var()] = true;
+ }
+
+ const vector<bool>& tmp2 = solver.conglomerate->getRemovedVars();
+ for (uint32_t i = 0; i < tmp2.size(); i++) {
+ if (tmp2[i]) cannot_eliminate[i] = true;
+ }
+
+ const vec<Clause*>& tmp = solver.varReplacer->getClauses();
+ for (uint32_t i = 0; i < tmp.size(); i++) {
+ const Clause& c = *tmp[i];
+ for (uint32_t i2 = 0; i2 < c.size(); i2++)
+ cannot_eliminate[c[i2].var()] = true;
+ }
+
+ #ifdef VERBOSE_DEBUG
+ uint32_t tmpNum = 0;
+ for (uint32_t i = 0; i < cannot_eliminate.size(); i++)
+ if (cannot_eliminate[i])
+ tmpNum++;
+ std::cout << "Cannot eliminate num:" << tmpNum << std::endl;
+ #endif
+}
+
+void Subsumer::subsume0LearntSet(vec<Clause*>& cs)
+{
+ Clause** a = cs.getData();
+ Clause** b = a;
+ for (Clause** end = a + cs.size(); a != end; a++) {
+ if (numMaxSubsume0 == 0) break;
+ if (!(*a)->subsume0IsFinished()) {
+ numMaxSubsume0--;
+ uint32_t index = subsume0(**a, calcAbstraction(**a));
+ if (index != std::numeric_limits<uint32_t>::max()) {
+ (*a)->makeNonLearnt();
+ clauses[index].clause = *a;
+ linkInAlreadyClause(clauses[index]);
+ solver.learnts_literals -= (*a)->size();
+ solver.clauses_literals += (*a)->size();
+ cl_added.add(clauses[index]);
+ continue;
+ }
+ if (numMaxSubsume1 > 0 &&
+ (((*a)->size() == 2 && clauses.size() < 3500000) ||
+ ((*a)->size() <= 3 && clauses.size() < 300000) ||
+ ((*a)->size() <= 4 && clauses.size() < 60000))) {
+ ClauseSimp c(*a, clauseID++);
+ (*a)->calcAbstraction();
+ clauses.push(c);
+ subsume1(c);
+ numMaxSubsume1--;
+ if (!solver.ok)
+ return;
+ assert(clauses[c.index].clause != NULL);
+ clauses.pop();
+ clauseID--;
+ }
+ }
+ *b++ = *a;
+ }
+ cs.shrink(a-b);
+}
+
+const bool Subsumer::treatLearnts()
+{
+ subsume0LearntSet(solver.learnts);
+ if (!solver.ok) return false;
+ subsume0LearntSet(solver.binaryClauses);
+ if (!solver.ok) return false;
+ solver.ok = (solver.propagate() == NULL);
+ if (!solver.ok){
+ printf("c (contradiction during subsumption)\n");
+ return false;
+ }
+ solver.clauseCleaner->cleanClausesBewareNULL(clauses, ClauseCleaner::simpClauses, *this);
+ return true;
+}
+
+const bool Subsumer::simplifyBySubsumption()
+{
+ if (solver.nClauses() > 20000000) return true;
+
+ double myTime = cpuTime();
+ uint32_t origTrailSize = solver.trail.size();
+ clauses_subsumed = 0;
+ literals_removed = 0;
+ numblockedClauseRemoved = 0;
+ numCalls++;
+ clauseID = 0;
+ numVarsElimed = 0;
+ blockTime = 0.0;
+
+ //if (solver.clauses.size() < 2000000) addAllXorAsNorm();
+
+ //For VE
+ touched_list.clear();
+ touched.clear();
+ touched.growTo(solver.nVars(), false);
+ for (Var var = 0; var < solver.nVars(); var++) {
+ if (solver.decision_var[var] && solver.assigns[var] == l_Undef) touch(var);
+ occur[2*var].clear();
+ occur[2*var+1].clear();
+ }
+
+ if (solver.performReplace && !solver.varReplacer->performReplace(true))
+ return false;
+ fillCannotEliminate();
+
+ clauses.clear();
+ cl_added.clear();
+ cl_touched.clear();
+
+ clauses.reserve(solver.clauses.size() + solver.binaryClauses.size());
+ cl_added.reserve(solver.clauses.size() + solver.binaryClauses.size());
+ cl_touched.reserve(solver.clauses.size() + solver.binaryClauses.size());
+
+ solver.clauseCleaner->cleanClauses(solver.clauses, ClauseCleaner::clauses);
+ addFromSolver(solver.clauses);
+ solver.clauseCleaner->cleanClauses(solver.binaryClauses, ClauseCleaner::binaryClauses);
+ addFromSolver(solver.binaryClauses);
+
+ //Limits
+ if (clauses.size() > 3500000)
+ numMaxSubsume0 = 900000 * (1+numCalls/2);
+ else
+ numMaxSubsume0 = 2000000 * (1+numCalls/2);
+
+ if (clauses.size() > 3500000)
+ numMaxSubsume1 = 100000 * (1+numCalls/2);
+ else
+ numMaxSubsume1 = 500000 * (1+numCalls/2);
+
+ if (clauses.size() > 3500000)
+ numMaxElim = (uint32_t)((double)solver.order_heap.size() / 5.0 * (0.8+(double)(numCalls)/4.0));
+ else
+ numMaxElim = (uint32_t)((double)solver.order_heap.size() / 2.0 * (0.8+(double)(numCalls)/4.0));
+
+ if (clauses.size() > 3500000)
+ numMaxBlockToVisit = (int64_t)(30000.0 * (0.8+(double)(numCalls)/3.0));
+ else
+ numMaxBlockToVisit = (int64_t)(50000.0 * (0.8+(double)(numCalls)/3.0));
+
+ if (solver.order_heap.size() > 200000)
+ numMaxBlockVars = (uint32_t)((double)solver.order_heap.size() / 3.5 * (0.8+(double)(numCalls)/4.0));
+ else
+ numMaxBlockVars = (uint32_t)((double)solver.order_heap.size() / 1.5 * (0.8+(double)(numCalls)/4.0));
+
+ if (clauses.size() < 200000)
+ fullSubsume = true;
+ else
+ fullSubsume = false;
+
+ #ifdef BIT_MORE_VERBOSITY
+ std::cout << "c num clauses:" << clauses.size() << std::endl;
+ std::cout << "c time to link in:" << cpuTime()-myTime << std::endl;
+ #endif
+
+ for (uint32_t i = 0; i < clauses.size(); i++) {
+ if (numMaxSubsume0 == 0) break;
+ if (clauses[i].clause != NULL &&
+ (fullSubsume
+ || !clauses[i].clause->subsume0IsFinished())
+ ) {
+ subsume0(*clauses[i].clause);
+ numMaxSubsume0--;
+ }
+ }
+
+ origNClauses = clauses.size();
+ uint32_t origNLearnts = solver.learnts.size();
+
+ if (!treatLearnts()) return false;
+
+ #ifdef BIT_MORE_VERBOSITY
+ std::cout << "c time until pre-subsume0 clauses and subsume1 2-learnts:" << cpuTime()-myTime << std::endl;
+ #endif
+
+ if (!solver.ok) return false;
+ #ifdef VERBOSE_DEBUG
+ std::cout << "c pre-subsumed:" << clauses_subsumed << std::endl;
+ std::cout << "c cl_added:" << cl_added.size() << std::endl;
+ std::cout << "c cl_touched:" << cl_touched.size() << std::endl;
+ std::cout << "c clauses:" << clauses.size() << std::endl;
+ std::cout << "c origNClauses:" << origNClauses << std::endl;
+ #endif
+
+ if (clauses.size() > 10000000) goto endSimplifyBySubsumption;
+
+ do{
+ if (solver.doBlockedClause && numCalls % 3 == 1) blockedClauseRemoval();
+
+ #ifdef BIT_MORE_VERBOSITY
+ std::cout << "c time before the start of almost_all/smaller: " << cpuTime() - myTime << std::endl;
+ #endif
+ if (numMaxSubsume0 > 0) {
+ if (cl_added.size() > origNClauses / 2) {
+ almost_all_database();
+ if (!solver.ok) return false;
+ } else {
+ smaller_database();
+ if (!solver.ok) return false;
+ }
+ }
+ cl_added.clear();
+ assert(cl_added.size() == 0);
+ assert(solver.ok);
+ solver.ok = (solver.propagate() == NULL);
+ if (!solver.ok) {
+ printf("c (contradiction during subsumption)\n");
+ return false;
+ }
+ solver.clauseCleaner->cleanClausesBewareNULL(clauses, ClauseCleaner::simpClauses, *this);
+
+ #ifdef BIT_MORE_VERBOSITY
+ std::cout << "c time until the end of almost_all/smaller: " << cpuTime() - myTime << std::endl;
+ printf("c VARIABLE ELIMINIATION\n");
+ std::cout << "c toucheds list size:" << touched_list.size() << std::endl;
+ #endif
+ vec<Var> init_order;
+ orderVarsForElim(init_order); // (will untouch all variables)
+
+ for (bool first = true; numMaxElim > 0; first = false){
+ uint32_t vars_elimed = 0;
+ int clauses_before = solver.nClauses();
+ vec<Var> order;
+
+ if (first) {
+ //init_order.copyTo(order);
+ for (uint32_t i = 0; i < init_order.size(); i++) {
+ const Var var = init_order[i];
+ if (!var_elimed[var] && !cannot_eliminate[var] && solver.decision_var[var] && solver.assigns[var] == l_Undef)
+ order.push(init_order[i]);
+ }
+ } else {
+ for (uint32_t i = 0; i < touched_list.size(); i++) {
+ const Var var = touched_list[i];
+ if (!var_elimed[var] && !cannot_eliminate[var] && solver.decision_var[var] && solver.assigns[var] == l_Undef) {
+ order.push(touched_list[i]);
+ touched[touched_list[i]] = 0;
+ }
+ }
+ touched_list.clear();
+ }
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Order size:" << order.size() << std::endl;
+ #endif
+
+ assert(solver.qhead == solver.trail.size());
+ for (uint32_t i = 0; i < order.size() && numMaxElim > 0; i++, numMaxElim--) {
+ if (maybeEliminate(order[i])) {
+ if (!solver.ok) {
+ printf("c (contradiction during subsumption)\n");
+ return false;
+ }
+ solver.ok = (solver.propagate() == NULL);
+ if (!solver.ok) {
+ printf("c (contradiction during subsumption)\n");
+ return false;
+ }
+ vars_elimed++;
+ }
+ }
+ assert(solver.qhead == solver.trail.size());
+
+ if (vars_elimed == 0) break;
+
+ numVarsElimed += vars_elimed;
+ #ifdef BIT_MORE_VERBOSITY
+ printf("c #clauses-removed: %-8d #var-elim: %d\n", clauses_before - solver.nClauses(), vars_elimed);
+ std::cout << "c time until the end of varelim: " << cpuTime() - myTime << std::endl;
+ #endif
+ }
+ }while (cl_added.size() > 100);
+ endSimplifyBySubsumption:
+
+ if (!solver.ok) return false;
+ solver.ok = (solver.propagate() == NULL);
+ if (!solver.ok) {
+ printf("c (contradiction during subsumption)\n");
+ return false;
+ }
+
+ #ifndef DNDEBUG
+ verifyIntegrity();
+ #endif
+
+ //vector<char> var_merged = merge();
+ removeWrong(solver.learnts);
+ removeWrong(solver.binaryClauses);
+
+ solver.clauseCleaner->cleanClausesBewareNULL(clauses, ClauseCleaner::simpClauses, *this);
+ if (solver.doHyperBinRes && clauses.size() < 1000000 && numCalls > 1 && !hyperBinRes())
+ return false;
+
+ solver.ok = (solver.propagate() == NULL);
+ if (!solver.ok) return false;
+ solver.clauseCleaner->cleanClausesBewareNULL(clauses, ClauseCleaner::simpClauses, *this);
+
+ solver.order_heap.filter(Solver::VarFilter(solver));
+
+ addBackToSolver();
+ solver.nbCompensateSubsumer += origNLearnts-solver.learnts.size();
+ /*if (solver.findNormalXors && solver.clauses.size() < MAX_CLAUSENUM_XORFIND) {
+ XorFinder xorFinder(&solver, solver.clauses, ClauseCleaner::clauses);
+ if (!xorFinder.doNoPart(3, 4)) return false;
+ }*/
+
+ if (solver.verbosity >= 1) {
+ std::cout << "c | lits-rem: " << std::setw(9) << literals_removed
+ << " cl-subs: " << std::setw(8) << clauses_subsumed
+ << " v-elim: " << std::setw(6) << numVarsElimed
+ << " v-fix: " << std::setw(4) <<solver.trail.size() - origTrailSize
+ << " time: " << std::setprecision(2) << std::setw(5) << (cpuTime() - myTime) << " s"
+ //<< " blkClRem: " << std::setw(5) << numblockedClauseRemoved
+ << " |" << std::endl;
+
+ if (numblockedClauseRemoved > 0 || blockTime > 0.0) {
+ std::cout
+ << "c | Blocked clauses removed: " << std::setw(8) << numblockedClauseRemoved
+ << " Time: " << std::fixed << std::setprecision(2) << std::setw(4) << blockTime << " s"
+ << " |" << std::endl;
+ }
+ }
+
+ return true;
+}
+
+void Subsumer::findSubsumed(Clause& ps, vec<ClauseSimp>& out_subsumed)
+{
+ #ifdef VERBOSE_DEBUG
+ cout << "findSubsumed: ";
+ for (uint32_t i = 0; i < ps.size(); i++) {
+ if (ps[i].sign()) printf("-");
+ printf("%d ", ps[i].var() + 1);
+ }
+ printf("0\n");
+ #endif
+
+ int min_i = 0;
+ for (uint32_t i = 1; i < ps.size(); i++){
+ if (occur[ps[i].toInt()].size() < occur[ps[min_i].toInt()].size())
+ min_i = i;
+ }
+
+ vec<ClauseSimp>& cs = occur[ps[min_i].toInt()];
+ for (ClauseSimp *it = cs.getData(), *end = it + cs.size(); it != end; it++){
+ if (it+1 != end)
+ __builtin_prefetch((it+1)->clause, 1, 1);
+
+ if (it->clause != &ps && subsetAbst(ps.getAbst(), it->clause->getAbst()) && ps.size() <= it->clause->size() && subset(ps, *it->clause)) {
+ out_subsumed.push(*it);
+ #ifdef VERBOSE_DEBUG
+ cout << "subsumed: ";
+ it->clause->plainPrint();
+ #endif
+ }
+ }
+}
+
+void Subsumer::findSubsumed(Clause& ps, uint32_t abs, vec<ClauseSimp>& out_subsumed)
+{
+ #ifdef VERBOSE_DEBUG
+ cout << "findSubsumed: ";
+ for (uint32_t i = 0; i < ps.size(); i++) {
+ if (ps[i].sign()) printf("-");
+ printf("%d ", ps[i].var() + 1);
+ }
+ printf("0\n");
+ #endif
+
+ int min_i = 0;
+ for (uint32_t i = 1; i < ps.size(); i++){
+ if (occur[ps[i].toInt()].size() < occur[ps[min_i].toInt()].size())
+ min_i = i;
+ }
+
+ vec<ClauseSimp>& cs = occur[ps[min_i].toInt()];
+ for (ClauseSimp *it = cs.getData(), *end = it + cs.size(); it != end; it++){
+ if (it+1 != end)
+ __builtin_prefetch((it+1)->clause, 1, 1);
+
+ if (it->clause != &ps && subsetAbst(abs, it->clause->getAbst()) && ps.size() <= it->clause->size() && subset(ps, *it->clause)) {
+ out_subsumed.push(*it);
+ #ifdef VERBOSE_DEBUG
+ cout << "subsumed: ";
+ it->clause->plainPrint();
+ #endif
+ }
+ }
+}
+
+void Subsumer::findSubsumed(const vec<Lit>& ps, const uint32_t abst, vec<ClauseSimp>& out_subsumed)
+{
+ #ifdef VERBOSE_DEBUG
+ cout << "findSubsumed: ";
+ for (uint32_t i = 0; i < ps.size(); i++) {
+ if (ps[i].sign()) printf("-");
+ printf("%d ", ps[i].var() + 1);
+ }
+ printf("0\n");
+ #endif
+
+ uint32_t min_i = 0;
+ for (uint32_t i = 1; i < ps.size(); i++){
+ if (occur[ps[i].toInt()].size() < occur[ps[min_i].toInt()].size())
+ min_i = i;
+ }
+
+ vec<ClauseSimp>& cs = occur[ps[min_i].toInt()];
+ for (ClauseSimp *it = cs.getData(), *end = it + cs.size(); it != end; it++){
+ if (it+1 != end)
+ __builtin_prefetch((it+1)->clause, 1, 1);
+
+ if (subsetAbst(abst, it->clause->getAbst()) && ps.size() <= it->clause->size() && subset(ps, *it->clause)) {
+ out_subsumed.push(*it);
+ #ifdef VERBOSE_DEBUG
+ cout << "subsumed: ";
+ it->clause->plainPrint();
+ #endif
+ }
+ }
+}
+
+void inline Subsumer::MigrateToPsNs(vec<ClauseSimp>& poss, vec<ClauseSimp>& negs, vec<ClauseSimp>& ps, vec<ClauseSimp>& ns, const Var x)
+{
+ poss.moveTo(ps);
+ negs.moveTo(ns);
+
+ for (uint32_t i = 0; i < ps.size(); i++)
+ unlinkClause(ps[i], x);
+ for (uint32_t i = 0; i < ns.size(); i++)
+ unlinkClause(ns[i], x);
+}
+
+void inline Subsumer::DeallocPsNs(vec<ClauseSimp>& ps, vec<ClauseSimp>& ns)
+{
+ for (uint32_t i = 0; i < ps.size(); i++) {
+ clauses[ps[i].index].clause = NULL;
+ free(ps[i].clause);
+ }
+ for (uint32_t i = 0; i < ns.size(); i++) {
+ clauses[ns[i].index].clause = NULL;
+ free(ns[i].clause);
+ }
+}
+
+// Returns TRUE if variable was eliminated.
+bool Subsumer::maybeEliminate(const Var x)
+{
+ assert(solver.qhead == solver.trail.size());
+ assert(!var_elimed[x]);
+ assert(!cannot_eliminate[x]);
+ assert(solver.decision_var[x]);
+ if (solver.value(x) != l_Undef) return false;
+ if (occur[Lit(x, false).toInt()].size() == 0 && occur[Lit(x, true).toInt()].size() == 0)
+ return false;
+
+ vec<ClauseSimp>& poss = occur[Lit(x, false).toInt()];
+ vec<ClauseSimp>& negs = occur[Lit(x, true).toInt()];
+
+ // Heuristic CUT OFF:
+ if (poss.size() >= 10 && negs.size() >= 10)
+ return false;
+
+ // Count clauses/literals before elimination:
+ int before_clauses = poss.size() + negs.size();
+ uint32_t before_literals = 0;
+ for (int i = 0; i < poss.size(); i++) before_literals += poss[i].clause->size();
+ for (int i = 0; i < negs.size(); i++) before_literals += negs[i].clause->size();
+
+ // Heuristic CUT OFF2:
+ if ((poss.size() >= 3 && negs.size() >= 3 && before_literals > 300)
+ && clauses.size() > 1500000)
+ return false;
+ if ((poss.size() >= 5 && negs.size() >= 5 && before_literals > 400)
+ && clauses.size() <= 1500000 && clauses.size() > 200000)
+ return false;
+ if ((poss.size() >= 10 && negs.size() >= 10 && before_literals > 700)
+ && clauses.size() <= 200000)
+ return false;
+
+ // Count clauses/literals after elimination:
+ int after_clauses = 0;
+ //int after_literals = 0;
+ vec<Lit> dummy;
+ //vec<ClauseSimp> dummy2;
+ for (int i = 0; i < poss.size(); i++){
+ for (int j = 0; j < negs.size(); j++){
+ // Merge clauses. If 'y' and '~y' exist, clause will not be created.
+ dummy.clear();
+ bool ok = merge(*poss[i].clause, *negs[j].clause, Lit(x, false), Lit(x, true), dummy);
+ if (ok){
+ //findSubsumed(dummy, calcAbstraction(dummy), dummy2);
+ //after_clauses -= (int)dummy2.size();
+ after_clauses++;
+ if (after_clauses > before_clauses) goto Abort;
+ //after_literals += dummy.size();
+ }
+ }
+ }
+ Abort:;
+
+ // Maybe eliminate:
+ if (after_clauses <= before_clauses) {
+ vec<ClauseSimp> ps, ns;
+ MigrateToPsNs(poss, negs, ps, ns, x);
+ for (int i = 0; i < ps.size(); i++) for (int j = 0; j < ns.size(); j++){
+ dummy.clear();
+ bool ok = merge(*ps[i].clause, *ns[j].clause, Lit(x, false), Lit(x, true), dummy);
+ if (ok){
+ Clause* cl = solver.addClauseInt(dummy, 0);
+ if (cl != NULL) {
+ ClauseSimp c = linkInClause(*cl);
+ subsume0(*cl);
+ //subsume1(c);
+ }
+ if (!solver.ok) return true;
+ }
+ }
+ DeallocPsNs(ps, ns);
+ goto Eliminated;
+ }
+
+ after_clauses = 0;
+ //after_literals = 0;
+ for (int i = 0; i < poss.size(); i++){
+ for (int j = 0; j < negs.size(); j++){
+ // Merge clauses. If 'y' and '~y' exist, clause will not be created.
+ dummy.clear();
+ bool ok = merge(*poss[i].clause, *negs[j].clause, Lit(x, false), Lit(x, true), dummy);
+ if (ok){
+ //findSubsumed(dummy, calcAbstraction(dummy), dummy2);
+ //after_clauses -= (int)dummy2.size();
+ after_clauses++;
+ if (after_clauses > before_clauses) goto Abort2;
+ //after_literals += dummy.size();
+ }
+ }
+ }
+ Abort2:
+
+ // Maybe eliminate:
+ if (after_clauses <= before_clauses) {
+ vec<ClauseSimp> ps, ns;
+ MigrateToPsNs(poss, negs, ps, ns, x);
+ for (int i = 0; i < ps.size(); i++) for (int j = 0; j < ns.size(); j++){
+ dummy.clear();
+ bool ok = merge(*ps[i].clause, *ns[j].clause, Lit(x, false), Lit(x, true), dummy);
+ if (ok){
+ Clause* cl = solver.addClauseInt(dummy, 0);
+ if (cl != NULL) {
+ ClauseSimp c = linkInClause(*cl);
+ subsume0(*cl);
+ //subsume1(c);
+ }
+ if (!solver.ok) return true;
+ }
+ }
+ DeallocPsNs(ps, ns);
+ goto Eliminated;
+ }
+
+ return false;
+
+ Eliminated:
+ assert(occur[Lit(x, false).toInt()].size() + occur[Lit(x, true).toInt()].size() == 0);
+ var_elimed[x] = 1;
+ numElimed++;
+ solver.setDecisionVar(x, false);
+ return true;
+}
+
+// Returns FALSE if clause is always satisfied ('out_clause' should not be used). 'seen' is assumed to be cleared.
+bool Subsumer::merge(Clause& ps, Clause& qs, Lit without_p, Lit without_q, vec<Lit>& out_clause)
+{
+ for (uint32_t i = 0; i < ps.size(); i++){
+ if (ps[i] != without_p){
+ seen_tmp[ps[i].toInt()] = 1;
+ out_clause.push(ps[i]);
+ }
+ }
+
+ for (uint32_t i = 0; i < qs.size(); i++){
+ if (qs[i] != without_q){
+ if (seen_tmp[(~qs[i]).toInt()]){
+ for (uint32_t i = 0; i < ps.size(); i++)
+ seen_tmp[ps[i].toInt()] = 0;
+ return false;
+ }
+ if (!seen_tmp[qs[i].toInt()])
+ out_clause.push(qs[i]);
+ }
+ }
+
+ for (uint32_t i = 0; i < ps.size(); i++)
+ seen_tmp[ps[i].toInt()] = 0;
+
+ return true;
+}
+
+struct myComp {
+ bool operator () (const pair<int, Var>& x, const pair<int, Var>& y) {
+ return x.first < y.first ||
+ (!(y.first < x.first) && x.second < y.second);
+ }
+};
+
+// Side-effect: Will untouch all variables.
+void Subsumer::orderVarsForElim(vec<Var>& order)
+{
+ order.clear();
+ vec<pair<int, Var> > cost_var;
+ for (int i = 0; i < touched_list.size(); i++){
+ Var x = touched_list[i];
+ touched[x] = 0;
+ cost_var.push(std::make_pair( occur[Lit(x, false).toInt()].size() * occur[Lit(x, true).toInt()].size() , x ));
+ }
+
+ touched_list.clear();
+ std::sort(cost_var.getData(), cost_var.getData()+cost_var.size(), myComp());
+
+ for (int x = 0; x < cost_var.size(); x++) {
+ if (cost_var[x].first != 0)
+ order.push(cost_var[x].second);
+ }
+}
+
+const bool Subsumer::hyperUtility(vec<ClauseSimp>& iter, const Lit lit, BitArray& inside, vec<ClauseSimp>& addToClauses, uint32_t& hyperBinAdded, uint32_t& hyperBinUnitary)
+{
+ for (ClauseSimp *it = iter.getData(), *end = it + iter.size() ; it != end; it++) {
+ if (it->clause == NULL) continue;
+ uint32_t notIn = 0;
+ Lit notInLit = Lit(0,false);
+
+ Clause& cl2 = *it->clause;
+ for (uint32_t i = 0; i < cl2.size(); i++) {
+ if (cl2[i].var() == lit.var()) {
+ notIn = 2;
+ break;
+ }
+ if (!inside[cl2[i].toInt()]) {
+ notIn++;
+ notInLit = cl2[i];
+ }
+ if (notIn > 1) break;
+ }
+
+ if (notIn == 0) {
+ if (solver.assigns[lit.var()] == l_Undef) {
+ solver.uncheckedEnqueue(lit);
+ solver.ok = (solver.propagate() == NULL);
+ if (!solver.ok) return false;
+ hyperBinUnitary++;
+ } else if (solver.assigns[lit.var()] != boolToLBool(!lit.sign())) {
+ solver.ok = false;
+ return false;
+ }
+ }
+
+ if (notIn == 1 && !inside[(~notInLit).toInt()]) {
+ vec<Lit> cs(2);
+ cs[0] = lit;
+ cs[1] = notInLit;
+ Clause *cl3 = Clause_new(cs, 0);
+ uint32_t index = subsume0(*cl3);
+ if (index != std::numeric_limits<uint32_t>::max()) {
+ ClauseSimp c(cl3, index);
+ addToClauses.push(c);
+ inside.setBit((~notInLit).toInt());
+ #ifdef HYPER_DEBUG
+ std::cout << "HyperBinRes adding clause: ";
+ cl3->plainPrint();
+ #endif
+ hyperBinAdded++;
+ }
+ }
+ }
+
+ return true;
+}
+
+const bool Subsumer::hyperBinRes()
+{
+ double myTime = cpuTime();
+
+ BitArray inside;
+ inside.resize(solver.nVars()*2);
+ uint32_t hyperBinAdded = 0;
+ uint32_t hyperBinUnitary = 0;
+ vec<ClauseSimp> addToClauses;
+ uint64_t totalClausesChecked = 0;
+
+ vec<Var> varsToCheck;
+
+ if (clauses.size() > 100000 || solver.order_heap.size() > 30000) {
+ Heap<Solver::VarOrderLt> tmp(solver.order_heap);
+ uint32_t thisTopX = std::min(tmp.size(), 1000U);
+ for (uint32_t i = 0; i != thisTopX; i++)
+ varsToCheck.push(tmp.removeMin());
+ } else {
+ for (Var i = 0; i < solver.nVars(); i++)
+ varsToCheck.push(i);
+ }
+
+ for (Var test = 0; test < 2*varsToCheck.size(); test++) if (solver.assigns[test/2] == l_Undef && solver.decision_var[test/2]) {
+ if (totalClausesChecked > 5000000)
+ break;
+
+ inside.setZero();
+ Lit lit(varsToCheck[test/2], test&1);
+ #ifdef HYPER_DEBUG
+ std::cout << "Resolving with literal:" << (lit.sign() ? "-" : "") << lit.var()+1 << std::endl;
+ #endif
+
+ vec<Lit> addedToInside;
+ vec<ClauseSimp>& set = occur[lit.toInt()];
+ for (ClauseSimp *it = set.getData(), *end = it + set.size() ; it != end; it++) {
+ if (it->clause == NULL) continue;
+ Clause& cl2 = *it->clause;
+ if (cl2.size() > 2) continue;
+ assert(cl2[0] == lit || cl2[1] == lit);
+ if (cl2[0] == lit) {
+ inside.setBit((~cl2[1]).toInt());
+ addedToInside.push(~cl2[1]);
+ } else {
+ inside.setBit((~cl2[0]).toInt());
+ addedToInside.push(~cl2[0]);
+ }
+ }
+
+ uint32_t sum = 0;
+ for (uint32_t add = 0; add < addedToInside.size(); add++) {
+ sum += occur[addedToInside[add].toInt()].size();
+ }
+
+ if (sum < clauses.size()) {
+ totalClausesChecked += sum;
+ for (uint32_t add = 0; add < addedToInside.size(); add++) {
+ vec<ClauseSimp>& iter = occur[addedToInside[add].toInt()];
+ if (!hyperUtility(iter, lit, inside, addToClauses, hyperBinAdded, hyperBinUnitary))
+ return false;
+ }
+ } else {
+ totalClausesChecked += clauses.size();
+ if (!hyperUtility(clauses, lit, inside, addToClauses, hyperBinAdded, hyperBinUnitary))
+ return false;
+ }
+
+ for (uint32_t i = 0; i < addToClauses.size(); i++) {
+ Clause *c = solver.addClauseInt(*addToClauses[i].clause, 0);
+ free(addToClauses[i].clause);
+ if (c != NULL) {
+ ClauseSimp cc(c, addToClauses[i].index);
+ clauses[cc.index] = cc;
+ linkInAlreadyClause(cc);
+ solver.becameBinary++; //since this binary did not exist, and now it exists.
+ subsume1(cc);
+ }
+ if (!solver.ok) return false;
+ }
+ addToClauses.clear();
+ }
+
+ if (solver.verbosity >= 1) {
+ std::cout << "c | Hyper-binary res binary added: " << std::setw(5) << hyperBinAdded
+ << " unitaries: " << std::setw(5) << hyperBinUnitary
+ << " time: " << std::setprecision(2) << std::setw(5)<< cpuTime() - myTime << " s"
+ << " |" << std::endl;
+ }
+
+ return true;
+}
+
+class varDataStruct
+{
+ public:
+ varDataStruct() :
+ numPosClauses (0)
+ , numNegClauses (0)
+ , sumPosClauseSize (0)
+ , sumNegClauseSize (0)
+ , posHash(0)
+ , negHash(0)
+ {}
+ const bool operator < (const varDataStruct& other) const
+ {
+ if (numPosClauses < other.numPosClauses) return true;
+ if (numPosClauses > other.numPosClauses) return false;
+
+ if (numNegClauses < other.numNegClauses) return true;
+ if (numNegClauses > other.numNegClauses) return false;
+
+ if (sumPosClauseSize < other.sumPosClauseSize) return true;
+ if (sumPosClauseSize > other.sumPosClauseSize) return false;
+
+ if (sumNegClauseSize < other.sumNegClauseSize) return true;
+ if (sumNegClauseSize > other.sumNegClauseSize) return false;
+
+ if (posHash < other.posHash) return true;
+ if (posHash > other.posHash) return false;
+
+ if (negHash < other.negHash) return true;
+ if (negHash > other.negHash) return false;
+
+ return false;
+ }
+
+ const bool operator == (const varDataStruct& other) const
+ {
+ if (numPosClauses == other.numPosClauses &&
+ numNegClauses == other.numNegClauses &&
+ sumPosClauseSize == other.sumPosClauseSize &&
+ sumNegClauseSize == other.sumNegClauseSize &&
+ posHash == other.posHash &&
+ negHash == other.negHash)
+ return true;
+
+ return false;
+ }
+
+ void reversePolarity()
+ {
+ std::swap(numPosClauses, numNegClauses);
+ std::swap(sumPosClauseSize, sumNegClauseSize);
+ std::swap(posHash, negHash);
+ }
+
+ uint32_t numPosClauses;
+ uint32_t numNegClauses;
+ uint32_t sumPosClauseSize;
+ uint32_t sumNegClauseSize;
+ int posHash;
+ int negHash;
+};
+
+int hash32shift(int key)
+{
+ key = ~key + (key << 15); // key = (key << 15) - key - 1;
+ key = key ^ (key >> 12);
+ key = key + (key << 2);
+ key = key ^ (key >> 4);
+ key = key * 2057; // key = (key + (key << 3)) + (key << 11);
+ key = key ^ (key >> 16);
+ return key;
+}
+
+void Subsumer::verifyIntegrity()
+{
+ vector<uint> occurNum(solver.nVars()*2, 0);
+
+ for (uint32_t i = 0; i < clauses.size(); i++) {
+ if (clauses[i].clause == NULL) continue;
+ Clause& c = *clauses[i].clause;
+ for (uint32_t i2 = 0; i2 < c.size(); i2++)
+ occurNum[c[i2].toInt()]++;
+ }
+
+ for (uint32_t i = 0; i < occurNum.size(); i++) {
+ assert(occurNum[i] == occur[i].size());
+ }
+}
+
+const bool Subsumer::allTautology(const vec<Lit>& ps, const Lit lit)
+{
+ #ifdef VERBOSE_DEBUG
+ cout << "allTautology: ";
+ for (uint32_t i = 0; i < ps.size(); i++) {
+ if (ps[i].sign()) printf("-");
+ printf("%d ", ps[i].var() + 1);
+ }
+ printf("0\n");
+ #endif
+
+ vec<ClauseSimp>& cs = occur[lit.toInt()];
+ if (cs.size() == 0) return true;
+
+ for (const Lit *l = ps.getData(), *end = ps.getDataEnd(); l != end; l++) {
+ seen_tmp[l->toInt()] = true;
+ }
+
+ bool allIsTautology = true;
+ for (ClauseSimp *it = cs.getData(), *end = cs.getDataEnd(); it != end; it++){
+ if (it+1 != end)
+ __builtin_prefetch((it+1)->clause, 1, 1);
+
+ Clause& c = *it->clause;
+ for (Lit *l = c.getData(), *end2 = l + c.size(); l != end2; l++) {
+ if (*l != lit && seen_tmp[(~(*l)).toInt()]) {
+ goto next;
+ }
+ }
+ allIsTautology = false;
+ break;
+
+ next:;
+ }
+
+ for (const Lit *l = ps.getData(), *end = ps.getDataEnd(); l != end; l++) {
+ seen_tmp[l->toInt()] = false;
+ }
+
+ return allIsTautology;
+}
+
+void Subsumer::blockedClauseRemoval()
+{
+ if (numMaxBlockToVisit < 0) return;
+ if (solver.order_heap.size() < 1) return;
+ double myTime = cpuTime();
+ vec<ClauseSimp> toRemove;
+
+ touchedBlockedVars = priority_queue<VarOcc, vector<VarOcc>, MyComp>();
+ touchedBlockedVarsBool.clear();
+ touchedBlockedVarsBool.growTo(solver.nVars(), false);
+ for (uint32_t i = 0; i < solver.order_heap.size() && i < numMaxBlockVars; i++) {
+ touchBlockedVar(solver.order_heap[solver.mtrand.randInt(solver.order_heap.size()-1)]);
+ }
+
+ while (touchedBlockedVars.size() > 100 && numMaxBlockToVisit > 0) {
+ VarOcc vo = touchedBlockedVars.top();
+ touchedBlockedVars.pop();
+
+ if (var_elimed[vo.var] || solver.assigns[vo.var] != l_Undef || !solver.decision_var[vo.var] || cannot_eliminate[vo.var])
+ continue;
+ touchedBlockedVarsBool[vo.var] = false;
+ Lit lit = Lit(vo.var, false);
+ Lit negLit = Lit(vo.var, true);
+
+ numMaxBlockToVisit -= (int64_t)occur[lit.toInt()].size();
+ numMaxBlockToVisit -= (int64_t)occur[negLit.toInt()].size();
+ if (!tryOneSetting(lit, negLit)) {
+ tryOneSetting(negLit, lit);
+ }
+ }
+ blockTime += cpuTime() - myTime;
+
+ #ifdef BIT_MORE_VERBOSITY
+ std::cout << "c Total fime for block until now: " << blockTime << std::endl;
+ #endif
+}
+
+const bool Subsumer::tryOneSetting(const Lit lit, const Lit negLit)
+{
+ uint32_t toRemove = 0;
+ bool returnVal = false;
+ vec<Lit> cl;
+
+ for(ClauseSimp *it = occur[lit.toInt()].getData(), *end = occur[lit.toInt()].getDataEnd(); it != end; it++) {
+ cl.clear();
+ cl.growTo(it->clause->size()-1);
+ for (uint32_t i = 0, i2 = 0; i < it->clause->size(); i++) {
+ if ((*it->clause)[i] != lit) {
+ cl[i2] = (*it->clause)[i];
+ i2++;
+ }
+ }
+
+ if (allTautology(cl, negLit)) {
+ toRemove++;
+ } else {
+ break;
+ }
+ }
+
+ if (toRemove == occur[lit.toInt()].size()) {
+ var_elimed[lit.var()] = true;
+ solver.setDecisionVar(lit.var(), false);
+ vec<ClauseSimp> toRemove(occur[lit.toInt()]);
+ for (ClauseSimp *it = toRemove.getData(), *end = toRemove.getDataEnd(); it != end; it++) {
+ unlinkClause(*it, lit.var());
+ numblockedClauseRemoved++;
+ }
+
+ vec<ClauseSimp> toRemove2(occur[negLit.toInt()]);
+ for (ClauseSimp *it = toRemove2.getData(), *end = toRemove2.getDataEnd(); it != end; it++) {
+ unlinkClause(*it, lit.var());
+ numblockedClauseRemoved++;
+ }
+ returnVal = true;
+ }
+
+ return returnVal;
+}
+
+void Subsumer::addAllXorAsNorm()
+{
+ uint32_t added = 0;
+ XorClause **i = solver.xorclauses.getData(), **j = i;
+ for (XorClause **end = solver.xorclauses.getDataEnd(); i != end; i++) {
+ if ((*i)->size() > 3) {
+ *j++ = *i;
+ continue;
+ }
+ added++;
+ if ((*i)->size() == 3) addXorAsNormal3(**i);
+ //if ((*i)->size() == 4) addXorAsNormal4(**i);
+ solver.removeClause(**i);
+ }
+ solver.xorclauses.shrink(i-j);
+ std::cout << "Added XOR as norm:" << added << std::endl;
+}
+
+void Subsumer::addXorAsNormal3(XorClause& c)
+{
+ assert(c.size() == 3);
+ Clause *tmp;
+ vec<Var> vars;
+ vec<Lit> vars2(c.size());
+ const bool inverted = c.xor_clause_inverted();
+
+ for (uint32_t i = 0; i < c.size(); i++) {
+ vars.push(c[i].var());
+ }
+
+ vars2[0] = Lit(vars[0], false ^ inverted);
+ vars2[1] = Lit(vars[1], false ^ inverted);
+ vars2[2] = Lit(vars[2], false ^ inverted);
+ tmp = solver.addClauseInt(vars2, c.getGroup());
+ if (tmp) solver.clauses.push(tmp);
+
+ vars2[0] = Lit(vars[0], true ^ inverted);
+ vars2[1] = Lit(vars[1], true ^ inverted);
+ vars2[2] = Lit(vars[2], false ^ inverted);
+ tmp = solver.addClauseInt(vars2, c.getGroup());
+ if (tmp) solver.clauses.push(tmp);
+
+ vars2[0] = Lit(vars[0], true ^ inverted);
+ vars2[1] = Lit(vars[1], false ^ inverted);
+ vars2[2] = Lit(vars[2], true ^ inverted);
+ tmp = solver.addClauseInt(vars2, c.getGroup());
+ if (tmp) solver.clauses.push(tmp);
+
+ vars2[0] = Lit(vars[0], false ^ inverted);
+ vars2[1] = Lit(vars[1], true ^ inverted);
+ vars2[2] = Lit(vars[2], true ^ inverted);
+ tmp = solver.addClauseInt(vars2, c.getGroup());
+ if (tmp) solver.clauses.push(tmp);
+}
+
+void Subsumer::addXorAsNormal4(XorClause& c)
+{
+ assert(c.size() == 4);
+ Clause *tmp;
+ vec<Var> vars;
+ vec<Lit> vars2(c.size());
+ const bool inverted = !c.xor_clause_inverted();
+
+ for (uint32_t i = 0; i < c.size(); i++) {
+ vars.push(c[i].var());
+ }
+
+ vars2[0] = Lit(vars[0], false ^ inverted);
+ vars2[1] = Lit(vars[1], false ^ inverted);
+ vars2[2] = Lit(vars[2], false ^ inverted);
+ vars2[3] = Lit(vars[3], true ^ inverted);
+ tmp = solver.addClauseInt(vars2, c.getGroup());
+ if (tmp) solver.clauses.push(tmp);
+
+ vars2[0] = Lit(vars[0], false ^ inverted);
+ vars2[1] = Lit(vars[1], true ^ inverted);
+ vars2[2] = Lit(vars[2], false ^ inverted);
+ vars2[3] = Lit(vars[3], false ^ inverted);
+ tmp = solver.addClauseInt(vars2, c.getGroup());
+ if (tmp) solver.clauses.push(tmp);
+
+ vars2[0] = Lit(vars[0], false ^ inverted);
+ vars2[1] = Lit(vars[1], false ^ inverted);
+ vars2[2] = Lit(vars[2], true ^ inverted);
+ vars2[3] = Lit(vars[3], false ^ inverted);
+ tmp = solver.addClauseInt(vars2, c.getGroup());
+ if (tmp) solver.clauses.push(tmp);
+
+ vars2[0] = Lit(vars[0], false ^ inverted);
+ vars2[1] = Lit(vars[1], false ^ inverted);
+ vars2[2] = Lit(vars[2], false ^ inverted);
+ vars2[3] = Lit(vars[3], true ^ inverted);
+ tmp = solver.addClauseInt(vars2, c.getGroup());
+ if (tmp) solver.clauses.push(tmp);
+
+ vars2[0] = Lit(vars[0], false ^ inverted);
+ vars2[1] = Lit(vars[1], true ^ inverted);
+ vars2[2] = Lit(vars[2], true ^ inverted);
+ vars2[3] = Lit(vars[3], true ^ inverted);
+ tmp = solver.addClauseInt(vars2, c.getGroup());
+ if (tmp) solver.clauses.push(tmp);
+
+ vars2[0] = Lit(vars[0], true ^ inverted);
+ vars2[1] = Lit(vars[1], false ^ inverted);
+ vars2[2] = Lit(vars[2], true ^ inverted);
+ vars2[3] = Lit(vars[3], true ^ inverted);
+ tmp = solver.addClauseInt(vars2, c.getGroup());
+ if (tmp) solver.clauses.push(tmp);
+
+ vars2[0] = Lit(vars[0], true ^ inverted);
+ vars2[1] = Lit(vars[1], true ^ inverted);
+ vars2[2] = Lit(vars[2], false ^ inverted);
+ vars2[3] = Lit(vars[3], true ^ inverted);
+ tmp = solver.addClauseInt(vars2, c.getGroup());
+ if (tmp) solver.clauses.push(tmp);
+
+ vars2[0] = Lit(vars[0], true ^ inverted);
+ vars2[1] = Lit(vars[1], true ^ inverted);
+ vars2[2] = Lit(vars[2], true ^ inverted);
+ vars2[3] = Lit(vars[3], false ^ inverted);
+ tmp = solver.addClauseInt(vars2, c.getGroup());
+ if (tmp) solver.clauses.push(tmp);
+}
+
+/*vector<char> Subsumer::merge()
+{
+ vector<char> var_merged(solver.nVars(), false);
+ double myTime = cpuTime();
+
+ vector<varDataStruct> varData(solver.nVars());
+
+ for (Var var = 0; var < solver.nVars(); var++) if (solver.decision_var[var] && solver.assigns[var] == l_Undef && !cannot_eliminate[var]) {
+ varDataStruct thisVar;
+
+ vec<ClauseSimp>& toCountPos = occur[Lit(var, false).toInt()];
+ thisVar.numPosClauses = toCountPos.size();
+ for (uint32_t i2 = 0; i2 < toCountPos.size(); i2++) {
+ thisVar.sumPosClauseSize += toCountPos[i2].clause->size();
+ for (Lit *l = toCountPos[i2].clause->getData(), *end = l + toCountPos[i2].clause->size(); l != end; l++) {
+ if (l->var() != var) thisVar.posHash ^= hash32shift(l->toInt());
+ }
+ }
+
+ vec<ClauseSimp>& toCountNeg = occur[Lit(var, true).toInt()];
+ thisVar.numNegClauses = toCountNeg.size();
+ for (uint32_t i2 = 0; i2 < toCountNeg.size(); i2++) {
+ thisVar.sumNegClauseSize += toCountNeg[i2].clause->size();
+ for (Lit *l = toCountNeg[i2].clause->getData(), *end = l + toCountNeg[i2].clause->size(); l != end; l++) {
+ if (l->var() != var) thisVar.negHash ^= hash32shift(l->toInt());
+ }
+ }
+
+ varData[var] = thisVar;
+ }
+
+ map<varDataStruct, vector<Var> > dataToVar;
+ for (Var var = 0; var < solver.nVars(); var++) if (solver.decision_var[var] && solver.assigns[var] == l_Undef) {
+ dataToVar[varData[var]].push_back(var);
+ assert(dataToVar[varData[var]].size() > 0);
+ }
+
+ for (map<varDataStruct, vector<Var> >::iterator it = dataToVar.begin(); it != dataToVar.end(); it++) {
+ //std::cout << "size: " << it->second.size() << std::endl;
+ for (uint i = 0; i < it->second.size()-1; i++) {
+ assert(it->second.size() > i+1);
+ assert(varData[it->second[i]] == varData[it->second[i+1]]);
+ }
+ }
+
+ uint64_t checked = 0;
+ uint64_t replaced = 0;
+ for (Var var = 0; var < solver.nVars(); var++) if (solver.decision_var[var] && solver.assigns[var] == l_Undef && !cannot_eliminate[var]) {
+ varDataStruct tmp = varData[var];
+ assert(dataToVar[tmp].size() > 0);
+
+ if (dataToVar[tmp].size() > 0) {
+ map<varDataStruct, vector<Var> >::iterator it = dataToVar.find(tmp);
+ for (uint i = 0; i < it->second.size(); i++) if (it->second[i] != var) {
+ checked ++;
+ if (checkIfSame(Lit(var, false), Lit(it->second[i], false)) &&
+ (checkIfSame(Lit(var, true), Lit(it->second[i], true))))
+ {
+ vec<Lit> ps(2);
+ ps[0] = Lit(var, false);
+ ps[1] = Lit(it->second[i], false);
+ solver.varReplacer->replace(ps, true, 0);
+ replaced++;
+ goto next;
+
+ }
+ }
+ }
+
+ tmp.reversePolarity();
+ if (dataToVar[tmp].size() > 0) {
+ map<varDataStruct, vector<Var> >::iterator it = dataToVar.find(tmp);
+ for (uint i = 0; i < it->second.size(); i++) if (it->second[i] != var) {
+ checked ++;
+ if (checkIfSame(Lit(var, true), Lit(it->second[i], false)) &&
+ (checkIfSame(Lit(var, false), Lit(it->second[i], true))))
+ {
+ vec<Lit> ps(2);
+ ps[0] = Lit(var, false);
+ ps[1] = Lit(it->second[i], false);
+ solver.varReplacer->replace(ps, false, 0);
+ replaced++;
+ goto next;
+ }
+ }
+ }
+
+ next:;
+ }
+
+ std::cout << "c | Merging vars in same clauses. checked: " << std::setw(5) << checked << " replaced: " << std::setw(5) << replaced << " time: " << std::setprecision(2) << std::setw(5) << cpuTime()-myTime << std::endl;
+
+ return var_merged;
+}*/
+
+/*const bool Subsumer::checkIfSame(const Lit lit1, const Lit lit2)
+{
+ assert(lit1.var() != lit2.var());
+ #ifdef VERBOSE_DEBUG
+ std::cout << "checking : " << lit1.var()+1 << " , " << lit2.var()+1 << std::endl;
+ #endif
+
+ vec<ClauseSimp>& occSet1 = occur[lit1.toInt()];
+ vec<ClauseSimp>& occSet2 = occur[lit2.toInt()];
+ vec<Lit> tmp;
+
+ for (ClauseSimp *it = occSet1.getData(), *end = it + occSet1.size(); it != end; it++) {
+ bool found = false;
+ tmp.clear();
+ uint32_t clauseSize = it->clause->size();
+
+ for (Lit *l = it->clause->getData(), *end2 = l + it->clause->size(); l != end2; l++) {
+ if (l->var() != lit1.var()) {
+ tmp.push(*l);
+ seen_tmp[l->toInt()] = true;
+ }
+ }
+ #ifdef VERBOSE_DEBUG
+ std::cout << "orig: ";
+ it->clause->plainPrint();
+ #endif
+
+ for (ClauseSimp *it2 = occSet2.getData(), *end2 = it2 + occSet2.size(); (it2 != end2 && !found); it2++) {
+ if (it2->clause->size() != clauseSize) continue;
+
+ for (Lit *l = it2->clause->getData(), *end3 = l + tmp.size(); l != end3; l++) if (l->var() != lit1.var()) {
+ if (!seen_tmp[l->toInt()]) goto next;
+ }
+ found = true;
+
+ #ifdef VERBOSE_DEBUG
+ std::cout << "OK: ";
+ it2->clause->plainPrint();
+ #endif
+ next:;
+ }
+
+ for (Lit *l = tmp.getData(), *end2 = l + tmp.size(); l != end2; l++) {
+ seen_tmp[l->toInt()] = false;
+ }
+
+ if (!found) return false;
+ }
+ #ifdef VERBOSE_DEBUG
+ std::cout << "OK" << std::endl;
+ #endif
+
+ return true;
+}*/
+
+/*void Subsumer::pureLiteralRemoval()
+{
+ for (Var var = 0; var < solver.nVars(); var++) if (solver.decision_var[var] && solver.assigns[var] == l_Undef && !cannot_eliminate[var] && !var_elimed[var] && !solver.varReplacer->varHasBeenReplaced(var)) {
+ uint32_t numPosClauses = occur[Lit(var, false).toInt()].size();
+ uint32_t numNegClauses = occur[Lit(var, true).toInt()].size();
+ if (numNegClauses > 0 && numPosClauses > 0) continue;
+
+ if (numNegClauses == 0 && numPosClauses == 0) {
+ if (solver.decision_var[var]) madeVarNonDecision.push(var);
+ solver.setDecisionVar(var, false);
+ pureLitRemoved[var] = true;
+ pureLitsRemovedNum++;
+ continue;
+ }
+
+ if (numPosClauses == 0 && numNegClauses > 0) {
+ if (solver.decision_var[var]) madeVarNonDecision.push(var);
+ solver.setDecisionVar(var, false);
+ pureLitRemoved[var] = true;
+ assignVar.push(Lit(var, true));
+ vec<ClauseSimp> occ(occur[Lit(var, true).toInt()]);
+ for (ClauseSimp *it = occ.getData(), *end = occ.getDataEnd(); it != end; it++) {
+ unlinkClause(*it);
+ pureLitClauseRemoved.push(it->clause);
+ }
+ pureLitsRemovedNum++;
+ continue;
+ }
+
+ if (numNegClauses == 0 && numPosClauses > 0) {
+ if (solver.decision_var[var]) madeVarNonDecision.push(var);
+ solver.setDecisionVar(var, false);
+ pureLitRemoved[var] = true;
+ assignVar.push(Lit(var, false));
+ vec<ClauseSimp> occ(occur[Lit(var, false).toInt()]);
+ for (ClauseSimp *it = occ.getData(), *end = occ.getDataEnd(); it != end; it++) {
+ unlinkClause(*it);
+ pureLitClauseRemoved.push(it->clause);
+ }
+ pureLitsRemovedNum++;
+ continue;
+ }
+ }
+}*/
+
+/*void Subsumer::undoPureLitRemoval()
+{
+ assert(solver.ok);
+ for (uint32_t i = 0; i < madeVarNonDecision.size(); i++) {
+ assert(!solver.decision_var[madeVarNonDecision[i]]);
+ assert(solver.assigns[madeVarNonDecision[i]] == l_Undef);
+ solver.setDecisionVar(madeVarNonDecision[i], true);
+ pureLitRemoved[madeVarNonDecision[i]] = false;
+ }
+ madeVarNonDecision.clear();
+
+ for (Lit *l = assignVar.getData(), *end = assignVar.getDataEnd(); l != end; l++) {
+ solver.uncheckedEnqueue(*l);
+ solver.ok = (solver.propagate() == NULL);
+ assert(solver.ok);
+ }
+ assignVar.clear();
+}
+
+void Subsumer::reAddPureLitClauses()
+{
+ for (Clause **it = pureLitClauseRemoved.getData(), **end = pureLitClauseRemoved.getDataEnd(); it != end; it++) {
+ solver.addClause(**it, (*it)->getGroup());
+ free(*it);
+ assert(solver.ok);
+ }
+ pureLitClauseRemoved.clear();
+}*/
+
+}; //NAMESPACE MINISAT
--- /dev/null
+/**************************************************************************************************
+Originally From: Solver.C -- (C) Niklas Een, Niklas Sorensson, 2004
+Substantially modified by: Mate Soos (2010)
+**************************************************************************************************/
+
+#ifndef SIMPLIFIER_H
+#define SIMPLIFIER_H
+
+#include "Solver.h"
+#include "Queue.h"
+#include "CSet.h"
+#include "BitArray.h"
+#include <map>
+#include <vector>
+#include <queue>
+using std::vector;
+using std::map;
+using std::priority_queue;
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+class ClauseCleaner;
+
+class Subsumer
+{
+public:
+
+ Subsumer(Solver& S2);
+ ~Subsumer();
+ const bool simplifyBySubsumption();
+ void unlinkModifiedClause(vec<Lit>& origClause, ClauseSimp c);
+ void unlinkModifiedClauseNoDetachNoNULL(vec<Lit>& origClause, ClauseSimp c);
+ void unlinkClause(ClauseSimp cc, Var elim = var_Undef);
+ ClauseSimp linkInClause(Clause& cl);
+ void linkInAlreadyClause(ClauseSimp& c);
+ void updateClause(ClauseSimp c);
+ void newVar();
+ void extendModel(Solver& solver2);
+ const bool unEliminate(const Var var);
+ const vec<char>& getVarElimed() const;
+ const uint32_t getNumElimed() const;
+
+private:
+
+ friend class ClauseCleaner;
+
+ //Main
+ vec<ClauseSimp> clauses;
+ CSet learntClauses;
+ vec<char> touched; // Is set to true when a variable is part of a removed clause. Also true initially (upon variable creation).
+ vec<Var> touched_list; // A list of the true elements in 'touched'.
+ CSet cl_touched; // Clauses strengthened.
+ CSet cl_added; // Clauses created.
+ vec<vec<ClauseSimp> > occur; // 'occur[index(lit)]' is a list of constraints containing 'lit'.
+ vec<vec<ClauseSimp>* > iter_vecs; // Vectors currently used for iterations. Removed clauses will be looked up and replaced by 'Clause_NULL'.
+ vec<CSet* > iter_sets; // Sets currently used for iterations.
+ Solver& solver; // The Solver
+
+
+ vec<char> var_elimed; // 'eliminated[var]' is TRUE if variable has been eliminated.
+ vec<char> cannot_eliminate;//
+ map<Var, vector<vector<Lit> > > elimedOutVar;
+
+ // Temporaries (to reduce allocation overhead):
+ //
+ vec<char> seen_tmp; // (used in various places)
+ vector<Lit> io_tmp; // (used for reading/writing clauses from/to disk)
+
+
+ //Limits
+ uint32_t numVarsElimed;
+ uint32_t numMaxSubsume1;
+ uint32_t numMaxSubsume0;
+ uint32_t numMaxElim;
+ int64_t numMaxBlockToVisit;
+ uint32_t numMaxBlockVars;
+
+ //Start-up
+ void addFromSolver(vec<Clause*>& cs);
+ void addBackToSolver();
+ void removeWrong(vec<Clause*>& cs);
+ void fillCannotEliminate();
+ const bool treatLearnts();
+ void addAllXorAsNorm();
+ void addXorAsNormal3(XorClause& c);
+ void addXorAsNormal4(XorClause& c);
+
+ //Iterations
+ void registerIteration (CSet& iter_set) { iter_sets.push(&iter_set); }
+ void unregisterIteration(CSet& iter_set) { remove(iter_sets, &iter_set); }
+ void registerIteration (vec<ClauseSimp>& iter_vec) { iter_vecs.push(&iter_vec); }
+ void unregisterIteration(vec<ClauseSimp>& iter_vec) { remove(iter_vecs, &iter_vec); }
+
+ // Subsumption:
+ void touch(const Var x);
+ void touch(const Lit p);
+ bool updateOccur(Clause& c);
+ void findSubsumed(Clause& ps, vec<ClauseSimp>& out_subsumed);
+ void findSubsumed(const vec<Lit>& ps, const uint32_t abst, vec<ClauseSimp>& out_subsumed);
+ void findSubsumed(Clause& ps, uint32_t abs, vec<ClauseSimp>& out_subsumed);
+ bool isSubsumed(Clause& ps);
+ uint32_t subsume0(Clause& ps);
+ uint32_t subsume0(Clause& ps, uint32_t abs);
+ void subsume0LearntSet(vec<Clause*>& cs);
+ void subsume1(ClauseSimp& ps);
+ void smaller_database();
+ void almost_all_database();
+ template<class T1, class T2>
+ bool subset(const T1& A, const T2& B);
+ bool subsetAbst(uint32_t A, uint32_t B);
+
+ void orderVarsForElim(vec<Var>& order);
+ int substitute(Lit x, Clause& def, vec<Clause*>& poss, vec<Clause*>& negs, vec<Clause*>& new_clauses);
+ bool maybeEliminate(Var x);
+ void MigrateToPsNs(vec<ClauseSimp>& poss, vec<ClauseSimp>& negs, vec<ClauseSimp>& ps, vec<ClauseSimp>& ns, const Var x);
+ void DeallocPsNs(vec<ClauseSimp>& ps, vec<ClauseSimp>& ns);
+ bool merge(Clause& ps, Clause& qs, Lit without_p, Lit without_q, vec<Lit>& out_clause);
+
+
+ //hyperBinRes
+ void addFromSolverAll(vec<Clause*>& cs);
+ const bool hyperBinRes();
+ const bool hyperUtility(vec<ClauseSimp>& iter, const Lit lit, BitArray& inside, vec<ClauseSimp>& addToClauses, uint32_t& hyperBinAdded, uint32_t& hyperBinUnitary);
+
+ //merging
+ //vector<char> merge();
+ //const bool checkIfSame(const Lit var1, const Lit var2);
+
+ class VarOcc {
+ public:
+ VarOcc(const Var& v, const uint32_t num) :
+ var(v)
+ , occurnum(num)
+ {}
+ Var var;
+ uint32_t occurnum;
+ };
+
+ struct MyComp {
+ const bool operator() (const VarOcc& l1, const VarOcc& l2) const {
+ return l1.occurnum > l2.occurnum;
+ }
+ };
+
+ void blockedClauseRemoval();
+ const bool allTautology(const vec<Lit>& ps, const Lit lit);
+ uint32_t numblockedClauseRemoved;
+ const bool tryOneSetting(const Lit lit, const Lit negLit);
+ priority_queue<VarOcc, vector<VarOcc>, MyComp> touchedBlockedVars;
+ vec<bool> touchedBlockedVarsBool;
+ void touchBlockedVar(const Var x);
+ double blockTime;
+
+
+ //validity checking
+ void verifyIntegrity();
+
+ uint32_t clauses_subsumed;
+ uint32_t literals_removed;
+ uint32_t origNClauses;
+ uint32_t numCalls;
+ bool fullSubsume;
+ uint32_t clauseID;
+ uint32_t numElimed;
+};
+
+template <class T, class T2>
+void maybeRemove(vec<T>& ws, const T2& elem)
+{
+ if (ws.size() > 0)
+ removeW(ws, elem);
+}
+
+inline void Subsumer::touch(const Var x)
+{
+ if (!touched[x]) {
+ touched[x] = 1;
+ touched_list.push(x);
+ }
+}
+
+inline void Subsumer::touchBlockedVar(const Var x)
+{
+ if (!touchedBlockedVarsBool[x]) {
+ touchedBlockedVars.push(VarOcc(x, occur[Lit(x, false).toInt()].size()*occur[Lit(x, true).toInt()].size()));
+ touchedBlockedVarsBool[x] = 1;
+ }
+}
+
+inline void Subsumer::touch(const Lit p)
+{
+ touch(p.var());
+}
+
+inline bool Subsumer::updateOccur(Clause& c)
+{
+ return !c.learnt();
+}
+
+inline bool Subsumer::subsetAbst(uint32_t A, uint32_t B)
+{
+ return !(A & ~B);
+}
+
+// Assumes 'seen' is cleared (will leave it cleared)
+template<class T1, class T2>
+bool Subsumer::subset(const T1& A, const T2& B)
+{
+ for (uint32_t i = 0; i != B.size(); i++)
+ seen_tmp[B[i].toInt()] = 1;
+ for (uint32_t i = 0; i != A.size(); i++) {
+ if (!seen_tmp[A[i].toInt()]) {
+ for (uint32_t i = 0; i != B.size(); i++)
+ seen_tmp[B[i].toInt()] = 0;
+ return false;
+ }
+ }
+ for (uint32_t i = 0; i != B.size(); i++)
+ seen_tmp[B[i].toInt()] = 0;
+ return true;
+}
+
+inline void Subsumer::newVar()
+{
+ occur .push();
+ occur .push();
+ seen_tmp .push(0); // (one for each polarity)
+ seen_tmp .push(0);
+ touched .push(1);
+ var_elimed .push(0);
+ touchedBlockedVarsBool.push(0);
+ cannot_eliminate.push(0);
+}
+
+inline const vec<char>& Subsumer::getVarElimed() const
+{
+ return var_elimed;
+}
+
+inline const uint32_t Subsumer::getNumElimed() const
+{
+ return numElimed;
+}
+
+}; //NAMESPACE MINISAT
+
+#endif //SIMPLIFIER_H
CryptoMiniSat
-SVN revision: 686
-GIT revision: 30b79471e85e0dde20440ea5c51c78246d14c8ab
+GIT revision: e2b5fe1abd1777f753c775026d905a10006ce79b
**************************************************************************************************/
#include "VarReplacer.h"
+#include <iostream>
+#include <iomanip>
-#include "Solver.h"
#include "Conglomerate.h"
#include "ClauseCleaner.h"
+#include "PartHandler.h"
+#include "time_mem.h"
//#define VERBOSE_DEBUG
//#define DEBUG_REPLACER
+//#define REPLACE_STATISTICS
#ifdef VERBOSE_DEBUG
#include <iostream>
namespace MINISAT
{
+using namespace MINISAT;
-VarReplacer::VarReplacer(Solver *_s) :
+VarReplacer::VarReplacer(Solver& _solver) :
replacedLits(0)
- , lastReplacedLits(0)
, replacedVars(0)
, lastReplacedVars(0)
- , addedNewClause(false)
- , S(_s)
+ , solver(_solver)
{
}
VarReplacer::~VarReplacer()
{
for (uint i = 0; i != clauses.size(); i++)
+ //binaryClausePool.free(clauses[i]);
free(clauses[i]);
}
-void VarReplacer::performReplace()
+const bool VarReplacer::performReplaceInternal()
{
#ifdef VERBOSE_DEBUG
cout << "Replacer started." << endl;
#endif
+ double time = cpuTime();
- S->clauseCleaner->cleanClauses(S->clauses, ClauseCleaner::clauses);
- S->clauseCleaner->cleanClauses(S->learnts, ClauseCleaner::learnts);
- S->clauseCleaner->cleanClauses(S->xorclauses, ClauseCleaner::xorclauses);
-
- if (replacedVars == lastReplacedVars) return;
+ #ifdef REPLACE_STATISTICS
+ uint numRedir = 0;
+ for (uint i = 0; i < table.size(); i++) {
+ if (table[i].var() != i)
+ numRedir++;
+ }
+ std::cout << "Number of trees:" << reverseTable.size() << std::endl;
+ std::cout << "Number of redirected nodes:" << numRedir << std::endl;
+ /*map<Var, vector<Var> >::iterator it = reverseTable.begin();
+ map<Var, vector<Var> >::iterator end = reverseTable.end();
+ for (;it != end; it++) {
+ std::cout << "Tree size: " << it->second.size() << std::endl;
+ }*/
+ #endif //REPLACE_STATISTICS
+
+ solver.clauseCleaner->cleanClauses(solver.clauses, ClauseCleaner::clauses);
+ solver.clauseCleaner->cleanClauses(solver.learnts, ClauseCleaner::learnts);
+ solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses);
+ solver.clauseCleaner->removeSatisfied(solver.binaryClauses, ClauseCleaner::binaryClauses);
+ if (solver.ok == false)
+ return false;
#ifdef VERBOSE_DEBUG
{
}
#endif
- uint i = 0;
- const vector<bool>& removedVars = S->conglomerate->getRemovedVars();
- for (vector<Lit>::const_iterator it = table.begin(); it != table.end(); it++, i++) {
- if (it->var() == i) continue;
+ Var var = 0;
+ const vector<bool>& removedVars = solver.conglomerate->getRemovedVars();
+ const vec<lbool>& removedVars2 = solver.partHandler->getSavedState();
+ const vec<char>& removedVars3 = solver.subsumer->getVarElimed();
+ for (vector<Lit>::const_iterator it = table.begin(); it != table.end(); it++, var++) {
+ if (it->var() == var || removedVars[it->var()] || removedVars2[it->var()] != l_Undef || removedVars3[it->var()]) continue;
#ifdef VERBOSE_DEBUG
- cout << "Setting var " << i+1 << " to a non-decision var" << endl;
+ cout << "Setting var " << var+1 << " to a non-decision var" << endl;
#endif
- S->setDecisionVar(i, false);
- if (!removedVars[it->var()])
- S->setDecisionVar(it->var(), true);
+ bool wasDecisionVar = solver.decision_var[var];
+ solver.setDecisionVar(var, false);
+ solver.setDecisionVar(it->var(), true);
+
+ double& activity1 = solver.activity[var];
+ double& activity2 = solver.activity[it->var()];
+ if (wasDecisionVar && activity1 > activity2) {
+ activity2 = activity1;
+ solver.order_heap.update(it->var());
+ solver.polarity[it->var()] = solver.polarity[var]^it->sign();
+ }
+
+ activity1 = 0.0;
+ solver.order_heap.update(var);
}
+ assert(solver.order_heap.heapProperty());
+
+ if (solver.verbosity >= 2)
+ std::cout << "c | Replacing " << std::setw(8) << replacedVars-lastReplacedVars << " vars";
- replace_set(S->clauses);
- replace_set(S->learnts);
+ lastReplacedVars = replacedVars;
- replace_set(S->xorclauses, true);
- replace_set(S->conglomerate->getCalcAtFinish(), false);
+ if (!replace_set(solver.clauses)) return false;
+ if (!replace_set(solver.learnts)) return false;
+ if (!replace_set(solver.binaryClauses)) return false;
+
+ if (!replace_set(solver.xorclauses, true)) return false;
+ if (!replace_set(solver.conglomerate->getCalcAtFinish(), false)) return false;
for (uint i = 0; i != clauses.size(); i++)
- S->removeClause(*clauses[i]);
+ solver.removeClause(*clauses[i]);
clauses.clear();
- if (S->verbosity >=1)
- printf("c | Replacing %8d vars, replaced %8d lits |\n", replacedVars-lastReplacedVars, replacedLits-lastReplacedLits);
+ if (solver.verbosity >= 2) {
+ std::cout << " Replaced " << std::setw(8) << replacedLits<< " lits"
+ << " Time: " << std::setw(8) << std::fixed << std::setprecision(2) << cpuTime()-time << " s "
+ << std::setw(12) << " |" << std::endl;
+ }
- addedNewClause = false;
- lastReplacedVars = replacedVars;
- lastReplacedLits = replacedLits;
+ replacedLits = 0;
- if (S->ok)
- S->ok = (S->propagate() == NULL);
+ solver.order_heap.filter(Solver::VarFilter(solver));
- S->order_heap.filter(Solver::VarFilter(*S));
+ return solver.ok;
}
-void VarReplacer::replace_set(vec<XorClause*>& cs, const bool isAttached)
+const bool VarReplacer::replace_set(vec<XorClause*>& cs, const bool isAttached)
{
XorClause **a = cs.getData();
XorClause **r = a;
changed = true;
*l = Lit(newlit.var(), false);
c.invert(newlit.sign());
+ c.setVarChanged();
replacedLits++;
}
}
if (isAttached && changed && handleUpdatedClause(c, origVar1, origVar2)) {
- c.mark(1);
- S->freeLater.push(&c);
+ if (solver.ok == false) return false;
+ solver.freeLater.push(&c);
r++;
} else {
*a++ = *r++;
}
}
cs.shrink(r-a);
+
+ return solver.ok;
}
const bool VarReplacer::handleUpdatedClause(XorClause& c, const Var origVar1, const Var origVar2)
//added, but easily removed
j--;
p = lit_Undef;
- if (!S->assigns[c[i].var()].isUndef())
- c.invert(S->assigns[c[i].var()].getBool());
- } else if (S->assigns[c[i].var()].isUndef()) //just add
+ if (!solver.assigns[c[i].var()].isUndef())
+ c.invert(solver.assigns[c[i].var()].getBool());
+ solver.clauses_literals -= 2;
+ } else if (solver.assigns[c[i].var()].isUndef()) //just add
c[j++] = p = c[i];
- else c.invert(S->assigns[c[i].var()].getBool()); //modify xor_clause_inverted instead of adding
+ else c.invert(solver.assigns[c[i].var()].getBool()); //modify xor_clause_inverted instead of adding
}
c.shrink(i - j);
switch (c.size()) {
case 0:
- S->detachModifiedClause(origVar1, origVar2, origSize, &c);
+ solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
if (!c.xor_clause_inverted())
- S->ok = false;
+ solver.ok = false;
return true;
case 1:
- S->detachModifiedClause(origVar1, origVar2, origSize, &c);
- S->uncheckedEnqueue(c[0] ^ c.xor_clause_inverted());
+ solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
+ solver.uncheckedEnqueue(c[0] ^ c.xor_clause_inverted());
+ solver.ok = (solver.propagate() == NULL);
return true;
case 2: {
- S->detachModifiedClause(origVar1, origVar2, origSize, &c);
+ solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
vec<Lit> ps(2);
ps[0] = c[0];
ps[1] = c[1];
- addBinaryXorClause(ps, c.xor_clause_inverted(), c.group, true);
+ addBinaryXorClause(ps, c.xor_clause_inverted(), c.getGroup(), true);
return true;
}
default:
- if (origVar1 != c[0].var() || origVar2 != c[1].var()) {
- S->detachModifiedClause(origVar1, origVar2, origSize, &c);
- S->attachClause(c);
- }
+ solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
+ solver.attachClause(c);
return false;
}
return false;
}
-void VarReplacer::replace_set(vec<Clause*>& cs)
+const bool VarReplacer::replace_set(vec<Clause*>& cs)
{
Clause **a = cs.getData();
Clause **r = a;
if (table[l->var()].var() != l->var()) {
changed = true;
*l = table[l->var()] ^ l->sign();
+ c.setVarChanged();
replacedLits++;
}
}
if (changed && handleUpdatedClause(c, origLit1, origLit2)) {
- free(&c);
+ if (solver.ok == false) return false;
+ clauseFree(&c);
r++;
} else {
*a++ = *r++;
}
}
cs.shrink(r-a);
+
+ return solver.ok;
}
const bool VarReplacer::handleUpdatedClause(Clause& c, const Lit origLit1, const Lit origLit2)
uint32_t i, j;
const uint origSize = c.size();
for (i = j = 0, p = lit_Undef; i != origSize; i++) {
- if (S->value(c[i]) == l_True || c[i] == ~p) {
+ if (solver.value(c[i]) == l_True || c[i] == ~p) {
satisfied = true;
break;
}
- else if (S->value(c[i]) != l_False && c[i] != p)
+ else if (solver.value(c[i]) != l_False && c[i] != p)
c[j++] = p = c[i];
}
c.shrink(i - j);
if (satisfied) {
- S->detachModifiedClause(origLit1, origLit2, origSize, &c);
+ solver.detachModifiedClause(origLit1, origLit2, origSize, &c);
return true;
}
switch(c.size()) {
case 0:
- S->detachModifiedClause(origLit1, origLit2, origSize, &c);
- S->ok = false;
+ solver.detachModifiedClause(origLit1, origLit2, origSize, &c);
+ solver.ok = false;
return true;
case 1 :
- S->detachModifiedClause(origLit1, origLit2, origSize, &c);
- S->uncheckedEnqueue(c[0]);
+ solver.detachModifiedClause(origLit1, origLit2, origSize, &c);
+ solver.uncheckedEnqueue(c[0]);
+ solver.ok = (solver.propagate() == NULL);
return true;
- case 2:
- S->detachModifiedClause(origLit1, origLit2, origSize, &c);
- S->attachClause(c);
- return false;
default:
- if (origLit1 != c[0] || origLit2 != c[1]) {
- S->detachModifiedClause(origLit1, origLit2, origSize, &c);
- S->attachClause(c);
- }
+ solver.detachModifiedClause(origLit1, origLit2, origSize, &c);
+ solver.attachClause(c);
+
return false;
}
return false;
}
-const uint VarReplacer::getNumReplacedLits() const
-{
- return replacedLits;
-}
-
-const uint VarReplacer::getNumReplacedVars() const
-{
- return replacedVars;
-}
-
-const uint VarReplacer::getNumLastReplacedVars() const
-{
- return lastReplacedVars;
-}
-
-const uint VarReplacer::getNewToReplaceVars() const
-{
- return replacedVars-lastReplacedVars;
-}
-
-const vector<Lit>& VarReplacer::getReplaceTable() const
-{
- return table;
-}
-
const vector<Var> VarReplacer::getReplacingVars() const
{
vector<Var> replacingVars;
return replacingVars;
}
-const vec<Clause*>& VarReplacer::getClauses() const
-{
- return clauses;
-}
-
-void VarReplacer::extendModel() const
+void VarReplacer::extendModelPossible() const
{
uint i = 0;
for (vector<Lit>::const_iterator it = table.begin(); it != table.end(); it++, i++) {
if (it->var() == i) continue;
#ifdef VERBOSE_DEBUG
- cout << "Extending model: var "; S->printLit(Lit(i, false));
- cout << " to "; S->printLit(*it);
+ cout << "Extending model: var "; solver.printLit(Lit(i, false));
+ cout << " to "; solver.printLit(*it);
cout << endl;
#endif
- assert(S->assigns[it->var()] != l_Undef);
- if (S->assigns[i] == l_Undef) {
- bool val = (S->assigns[it->var()] == l_False);
- S->uncheckedEnqueue(Lit(i, val ^ it->sign()));
- } else {
- assert(S->assigns[i].getBool() == (S->assigns[it->var()].getBool() ^ it->sign()));
+ if (solver.assigns[it->var()] != l_Undef) {
+ if (solver.assigns[i] == l_Undef) {
+ bool val = (solver.assigns[it->var()] == l_False);
+ solver.uncheckedEnqueue(Lit(i, val ^ it->sign()));
+ } else {
+ assert(solver.assigns[i].getBool() == (solver.assigns[it->var()].getBool() ^ it->sign()));
+ }
+ }
+ solver.ok = (solver.propagate() == NULL);
+ assert(solver.ok);
+ }
+}
+
+void VarReplacer::extendModelImpossible(Solver& solver2) const
+{
+ vec<Lit> tmpClause;
+ uint i = 0;
+ for (vector<Lit>::const_iterator it = table.begin(); it != table.end(); it++, i++) {
+ if (it->var() == i) continue;
+ if (solver.assigns[it->var()] == l_Undef) {
+ assert(solver.assigns[it->var()] == l_Undef);
+ assert(solver.assigns[i] == l_Undef);
+
+ tmpClause.clear();
+ tmpClause.push(Lit(it->var(), true));
+ tmpClause.push(Lit(i, it->sign()));
+ solver2.addClause(tmpClause);
+ assert(solver2.ok);
+
+ tmpClause.clear();
+ tmpClause.push(Lit(it->var(), false));
+ tmpClause.push(Lit(i, it->sign()^true));
+ solver2.addClause(tmpClause);
+ assert(solver2.ok);
}
}
}
-void VarReplacer::replace(vec<Lit>& ps, const bool xor_clause_inverted, const uint group)
+template<class T>
+const bool VarReplacer::replace(T& ps, const bool xor_clause_inverted, const uint group)
{
#ifdef VERBOSE_DEBUG
- cout << "replace() called with var " << ps[0].var()+1 << " and var " << ps[1].var()+1 << " with xor_clause_inverted " << xor_clause_inverted << endl;
+ std::cout << "replace() called with var " << ps[0].var()+1 << " and var " << ps[1].var()+1 << " with xor_clause_inverted " << xor_clause_inverted << std::endl;
#endif
- #ifdef DEBUG_REPLACER
assert(ps.size() == 2);
assert(!ps[0].sign());
assert(!ps[1].sign());
- assert(S->assigns[ps[0].var()].isUndef());
- assert(S->assigns[ps[1].var()].isUndef());
+ #ifdef DEBUG_REPLACER
+ assert(solver.assigns[ps[0].var()].isUndef());
+ assert(solver.assigns[ps[1].var()].isUndef());
#endif
- addBinaryXorClause(ps, xor_clause_inverted, group);
Var var = ps[0].var();
Lit lit = Lit(ps[1].var(), !xor_clause_inverted);
assert(var != lit.var());
//Detect circle
- if (alreadyIn(var, lit)) return;
- replacedVars++;
+ if (alreadyIn(var, lit)) return solver.ok;
Lit lit1 = table[var];
bool inverted = false;
}
if (inverted) {
- //Inversion is also set
Lit lit2 = table[var];
- //triangular cycle
+ //Inversion is also set, triangular cycle
+ //A->B, A->C, B->C. There is nothing to add
if (lit1.var() == lit2.var()) {
if ((lit1.sign() ^ lit2.sign()) != lit.sign()) {
#ifdef VERBOSE_DEBUG
cout << "Inverted cycle in var-replacement -> UNSAT" << endl;
#endif
- S->ok = false;
+ return (solver.ok = false);
}
- return;
+ return true;
}
+ //Inversion is also set
if (lit2.var() != var) {
+ assert(table[lit1.var()].var() == lit1.var());
setAllThatPointsHereTo(lit1.var(), Lit(lit.var(), lit1.sign()));
- table[lit1.var()] = Lit(lit.var(), lit1.sign());
- reverseTable[lit.var()].push_back(lit1.var());
+ assert(table[lit2.var()].var() == lit2.var());
setAllThatPointsHereTo(lit2.var(), lit ^ lit2.sign());
- table[lit2.var()] = lit ^ lit2.sign();
- reverseTable[lit.var()].push_back(lit2.var());
table[lit.var()] = Lit(lit.var(), false);
- return;
+ replacedVars++;
+ addBinaryXorClause(ps, xor_clause_inverted, group);
+ return true;
}
}
//Follow forwards
- Lit lit2 = table[lit.var()];
- if (lit2.var() != lit.var())
- lit = lit2 ^ lit.sign();
+ Lit litX = table[lit.var()];
+ if (litX.var() != lit.var())
+ lit = litX ^ lit.sign();
//Follow backwards
setAllThatPointsHereTo(var, lit);
+ replacedVars++;
+ addBinaryXorClause(ps, xor_clause_inverted, group);
- table[var] = lit;
- reverseTable[lit.var()].push_back(var);
+ return true;
}
-void VarReplacer::addBinaryXorClause(vec<Lit>& ps, const bool xor_clause_inverted, const uint group, const bool internal)
+template const bool VarReplacer::replace(vec<Lit>& ps, const bool xor_clause_inverted, const uint group);
+template const bool VarReplacer::replace(XorClause& ps, const bool xor_clause_inverted, const uint group);
+
+template<class T>
+void VarReplacer::addBinaryXorClause(T& ps, const bool xor_clause_inverted, const uint group, const bool internal)
{
+ assert(internal || (replacedVars > lastReplacedVars));
#ifdef DEBUG_REPLACER
assert(!ps[0].sign());
assert(!ps[1].sign());
ps[0] ^= xor_clause_inverted;
c = Clause_new(ps, group, false);
- if (internal)
- S->clauses.push(c);
- else
+ if (internal) {
+ solver.binaryClauses.push(c);
+ solver.becameBinary++;
+ } else
clauses.push(c);
- S->attachClause(*c);
+ solver.attachClause(*c);
ps[0] ^= true;
ps[1] ^= true;
c = Clause_new(ps, group, false);
- if (internal)
- S->clauses.push(c);
- else
+ if (internal) {
+ solver.binaryClauses.push(c);
+ solver.becameBinary++;
+ } else
clauses.push(c);
- S->attachClause(*c);
+ solver.attachClause(*c);
}
+template void VarReplacer::addBinaryXorClause(vec<Lit>& ps, const bool xor_clause_inverted, const uint group, const bool internal);
+template void VarReplacer::addBinaryXorClause(XorClause& ps, const bool xor_clause_inverted, const uint group, const bool internal);
+
bool VarReplacer::alreadyIn(const Var var, const Lit lit)
{
Lit lit2 = table[var];
#ifdef VERBOSE_DEBUG
cout << "Inverted cycle in var-replacement -> UNSAT" << endl;
#endif
- S->ok = false;
+ solver.ok = false;
}
return true;
}
#ifdef VERBOSE_DEBUG
cout << "Inverted cycle in var-replacement -> UNSAT" << endl;
#endif
- S->ok = false;
+ solver.ok = false;
}
return true;
}
void VarReplacer::setAllThatPointsHereTo(const Var var, const Lit lit)
{
map<Var, vector<Var> >::iterator it = reverseTable.find(var);
- if (it == reverseTable.end())
- return;
-
- for(vector<Var>::const_iterator it2 = it->second.begin(), end = it->second.end(); it2 != end; it2++) {
- assert(table[*it2].var() == var);
- table[*it2] = lit ^ table[*it2].sign();
- if (lit.var() != *it2)
- reverseTable[lit.var()].push_back(*it2);
+ if (it != reverseTable.end()) {
+ for(vector<Var>::const_iterator it2 = it->second.begin(), end = it->second.end(); it2 != end; it2++) {
+ assert(table[*it2].var() == var);
+ if (lit.var() != *it2) {
+ table[*it2] = lit ^ table[*it2].sign();
+ reverseTable[lit.var()].push_back(*it2);
+ }
+ }
+ reverseTable.erase(it);
}
- reverseTable.erase(it);
+ table[var] = lit;
+ reverseTable[lit.var()].push_back(var);
}
void VarReplacer::newVar()
table.push_back(Lit(table.size(), false));
}
-void VarReplacer::newClause()
+void VarReplacer::reattachInternalClauses()
{
- addedNewClause = true;
+ Clause **i = clauses.getData();
+ Clause **j = i;
+ for (Clause **end = clauses.getDataEnd(); i != end; i++) {
+ if (solver.value((**i)[0]) == l_Undef &&
+ solver.value((**i)[1]) == l_Undef) {
+ solver.attachClause(**i);
+ *j++ = *i;
+ }
+ }
+ clauses.shrink(i-j);
}
-};
+
+}; //NAMESPACE MINISAT
#ifndef VARREPLACER_H
#define VARREPLACER_H
-#include "SolverTypes.h"
-#include "Clause.h"
-#include "mtl/Vec.h"
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
-#include <sys/types.h>
#include <map>
#include <vector>
-
-namespace MINISAT
-{
-
using std::map;
using std::vector;
-class Solver;
+#include "Solver.h"
+#include "SolverTypes.h"
+#include "Clause.h"
+#include "Vec.h"
+
+namespace MINISAT
+{
+using namespace MINISAT;
class VarReplacer
{
public:
- VarReplacer(Solver* S);
+ VarReplacer(Solver& solver);
~VarReplacer();
- void replace(vec<Lit>& ps, const bool xor_clause_inverted, const uint group);
- void extendModel() const;
- void performReplace();
+ const bool performReplace(const bool always = false);
+ const bool needsReplace();
+ template<class T>
+ const bool replace(T& ps, const bool xor_clause_inverted, const uint group);
+
+ void extendModelPossible() const;
+ void extendModelImpossible(Solver& solver2) const;
+ void reattachInternalClauses();
+
const uint getNumReplacedLits() const;
const uint getNumReplacedVars() const;
const uint getNumLastReplacedVars() const;
const vector<Var> getReplacingVars() const;
const vector<Lit>& getReplaceTable() const;
const vec<Clause*>& getClauses() const;
- void newClause();
+ const bool varHasBeenReplaced(const Var var) const;
+ const bool replacingVar(const Var var) const;
void newVar();
private:
- void replace_set(vec<Clause*>& set);
- void replace_set(vec<XorClause*>& cs, const bool isAttached);
+ const bool performReplaceInternal();
+
+ const bool replace_set(vec<Clause*>& set);
+ const bool replace_set(vec<XorClause*>& cs, const bool isAttached);
const bool handleUpdatedClause(Clause& c, const Lit origLit1, const Lit origLit2);
const bool handleUpdatedClause(XorClause& c, const Var origVar1, const Var origVar2);
- void addBinaryXorClause(vec<Lit>& ps, const bool xor_clause_inverted, const uint group, const bool internal = false);
+ template<class T>
+ void addBinaryXorClause(T& ps, const bool xor_clause_inverted, const uint group, const bool internal = false);
void setAllThatPointsHereTo(const Var var, const Lit lit);
bool alreadyIn(const Var var, const Lit lit);
vec<Clause*> clauses;
uint replacedLits;
- uint lastReplacedLits;
uint replacedVars;
uint lastReplacedVars;
- bool addedNewClause;
- Solver* S;
-};
+ Solver& solver;
};
+
+inline const bool VarReplacer::performReplace(const bool always)
+{
+ //uint32_t limit = std::min((uint32_t)((double)solver.order_heap.size()*PERCENTAGEPERFORMREPLACE), FIXCLEANREPLACE);
+ uint32_t limit = (uint32_t)((double)solver.order_heap.size()*PERCENTAGEPERFORMREPLACE);
+ if ((always && getNewToReplaceVars() > 0) || getNewToReplaceVars() > limit)
+ return performReplaceInternal();
+
+ return true;
+}
+
+inline const bool VarReplacer::needsReplace()
+{
+ uint32_t limit = (uint32_t)((double)solver.order_heap.size()*PERCENTAGEPERFORMREPLACE);
+ return (getNewToReplaceVars() > limit);
+}
+
+inline const uint VarReplacer::getNumReplacedLits() const
+{
+ return replacedLits;
+}
+
+inline const uint VarReplacer::getNumReplacedVars() const
+{
+ return replacedVars;
+}
+
+inline const uint VarReplacer::getNumLastReplacedVars() const
+{
+ return lastReplacedVars;
+}
+
+inline const uint VarReplacer::getNewToReplaceVars() const
+{
+ return replacedVars-lastReplacedVars;
+}
+
+inline const vector<Lit>& VarReplacer::getReplaceTable() const
+{
+ return table;
+}
+
+inline const vec<Clause*>& VarReplacer::getClauses() const
+{
+ return clauses;
+}
+
+inline const bool VarReplacer::varHasBeenReplaced(const Var var) const
+{
+ return table[var].var() != var;
+}
+
+inline const bool VarReplacer::replacingVar(const Var var) const
+{
+ return (reverseTable.find(var) != reverseTable.end());
+}
+
+}; //NAMESPACE MINISAT
+
#endif //VARREPLACER_H
--- /dev/null
+/**************************************************************************************************
+From: Solver.C -- (C) Niklas Een, Niklas Sorensson, 2004
+**************************************************************************************************/
+
+#ifndef XSET_H
+#define XSET_H
+
+#include "Vec.h"
+#include <limits>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+class XorClause;
+
+template <class T>
+uint32_t calcXorAbstraction(const T& ps) {
+ uint32_t abstraction = 0;
+ for (uint32_t i = 0; i != ps.size(); i++)
+ abstraction |= 1 << (ps[i].var() & 31);
+ return abstraction;
+}
+
+//#pragma pack(push)
+//#pragma pack(1)
+class XorClauseSimp
+{
+ public:
+ XorClauseSimp(XorClause* c, const uint32_t _index) :
+ clause(c)
+ , index(_index)
+ {}
+
+ XorClause* clause;
+ uint32_t index;
+};
+//#pragma pack(pop)
+
+class XSet {
+ vec<uint32_t> where; // Map clause ID to position in 'which'.
+ vec<XorClauseSimp> which; // List of clauses (for fast iteration). May contain 'Clause_NULL'.
+ vec<uint32_t> free; // List of positions holding 'Clause_NULL'.
+
+ public:
+ //XorClauseSimp& operator [] (uint32_t index) { return which[index]; }
+ void reserve(uint32_t size) { where.reserve(size);}
+ uint32_t size(void) const { return which.size(); }
+ uint32_t nElems(void) const { return which.size() - free.size(); }
+
+ bool add(const XorClauseSimp& c) {
+ assert(c.clause != NULL);
+ where.growTo(c.index+1, std::numeric_limits<uint32_t>::max());
+ if (where[c.index] != std::numeric_limits<uint32_t>::max()) {
+ return true;
+ }
+ if (free.size() > 0){
+ where[c.index] = free.last();
+ which[free.last()] = c;
+ free.pop();
+ }else{
+ where[c.index] = which.size();
+ which.push(c);
+ }
+ return false;
+ }
+
+ bool exclude(const XorClauseSimp& c) {
+ assert(c.clause != NULL);
+ if (c.index >= where.size() || where[c.index] == std::numeric_limits<uint32_t>::max()) {
+ //not inside
+ return false;
+ }
+ free.push(where[c.index]);
+ which[where[c.index]].clause = NULL;
+ where[c.index] = std::numeric_limits<uint32_t>::max();
+ return true;
+ }
+
+ void clear(void) {
+ for (uint32_t i = 0; i < which.size(); i++) {
+ if (which[i].clause != NULL) {
+ where[which[i].index] = std::numeric_limits<uint32_t>::max();
+ }
+ }
+ which.clear();
+ free.clear();
+ }
+
+ class iterator
+ {
+ public:
+ iterator(XorClauseSimp* _it) :
+ it(_it)
+ {}
+
+ void operator++()
+ {
+ it++;
+ }
+
+ const bool operator!=(const iterator& iter) const
+ {
+ return (it != iter.it);;
+ }
+
+ XorClauseSimp& operator*() {
+ return *it;
+ }
+
+ XorClauseSimp*& operator->() {
+ return it;
+ }
+ private:
+ XorClauseSimp* it;
+ };
+
+ iterator begin()
+ {
+ return iterator(which.getData());
+ }
+
+ iterator end()
+ {
+ return iterator(which.getData() + which.size());
+ }
+};
+
+}; //NAMESPACE MINISAT
+
+#endif //XSET_H
\ No newline at end of file
#include "ClauseCleaner.h"
#include "time_mem.h"
-namespace MINISAT
-{
-
-
//#define VERBOSE_DEBUG
+#ifdef _MSC_VER
+#define __builtin_prefetch(a,b)
+#endif //_MSC_VER
#ifdef VERBOSE_DEBUG
#include <iostream>
using std::endl;
#endif
+namespace MINISAT
+{
+using namespace MINISAT;
+
using std::make_pair;
XorFinder::XorFinder(Solver* _s, vec<Clause*>& _cls, ClauseCleaner::ClauseSetType _type) :
{
}
-uint XorFinder::doNoPart(const uint minSize, const uint maxSize)
+const bool XorFinder::doNoPart(const uint minSize, const uint maxSize)
{
uint sumLengths = 0;
double time = cpuTime();
-
+ foundXors = 0;
S->clauseCleaner->cleanClauses(cls, type);
+ if (S->ok == false)
+ return false;
toRemove.clear();
toRemove.resize(cls.size(), false);
table.clear();
- table.reserve(cls.size()/2);
+ table.reserve(cls.size());
+
+ ClauseTable unsortedTable;
+ unsortedTable.reserve(cls.size());
+ ClauseTable sortedTable;
+ sortedTable.reserve(cls.size());
+
+ for (Clause **it = cls.getData(), **end = it + cls.size(); it != end; it ++) {
+ if (it+1 != end)
+ __builtin_prefetch(*(it+1), 0);
+ //if ((**it)[0].toInt() < (**it)[1].toInt())
+ // std::swap((**it)[0], (**it)[1]);
+ Clause& c = (**it);
+ if ((*it)->size() != 2) {
+ bool sorted = true;
+ for (uint i = 0, size = c.size(); i+1 < size ; i++) {
+ sorted = (c[i].var() <= c[i+1].var());
+ if (!sorted) break;
+ }
+ if (!sorted) {
+ S->detachClause(c);
+ std::sort(c.getData(), c.getData()+c.size());
+ S->attachClause(c);
+ }
+ } else {
+ std::sort(c.getData(), c.getData()+c.size());
+ }
+ }
+
uint i = 0;
for (Clause **it = cls.getData(), **end = it + cls.size(); it != end; it++, i++) {
const uint size = (*it)->size();
if ( size > maxSize || size < minSize) continue;
- table.push_back(make_pair(*it, i));
+ if ((*it)->getSorted()) sortedTable.push_back(make_pair(*it, i));
+ else unsortedTable.push_back(make_pair(*it, i));
}
- uint found = findXors(sumLengths);
+ clause_sorter_primary sorter;
- if (S->verbosity >=1)
- printf("c | Finding XORs: %5.2lf s (found: %7d, avg size: %3.1lf) |\n", cpuTime()-time, found, (double)sumLengths/(double)found);
+ std::sort(unsortedTable.begin(), unsortedTable.end(), clause_sorter_primary());
+ //std::sort(sortedTable.begin(), sortedTable.end(), clause_sorter_primary());
+ #ifdef DEBUG_XORFIND
+ for (uint i = 0; i+1 < unsortedTable.size(); i++) {
+ assert(!sorter(unsortedTable[i+1], unsortedTable[i]));
+ }
+ for (uint i = 0; i+1 < sortedTable.size(); i++) {
+ assert(!sorter(sortedTable[i+1], sortedTable[i]));
+ }
+ #endif //DEBUG_XORFIND
- if (found > 0) {
- clearToRemove();
-
- if (S->ok != false)
- S->ok = (S->propagate() == NULL);
+ for (uint i = 0, j = 0; i < unsortedTable.size() || j < sortedTable.size();) {
+ if (j == sortedTable.size()) {
+ table.push_back(unsortedTable[i++]);
+ continue;
+ }
+ if (i == unsortedTable.size()) {
+ table.push_back(sortedTable[j++]);
+ continue;
+ }
+ if (sorter(unsortedTable[i], sortedTable[j])) {
+ table.push_back(unsortedTable[i++]);
+ } else {
+ table.push_back(sortedTable[j++]);
+ }
+ }
+ #ifdef DEBUG_XORFIND
+ for (uint i = 0; i+1 < table.size(); i++) {
+ assert(!sorter(table[i+1], table[i]));
+ //table[i].first->plainPrint();
+ }
+ #endif //DEBUG_XORFIND
+
+ if (findXors(sumLengths) == false)
+ return false;
+
+ if (S->verbosity >= 2) {
+ if (minSize == maxSize && minSize == 2)
+ printf("c | Finding binary XORs: %5.2lf s (found: %7d, avg size: %3.1lf) |\n", cpuTime()-time, foundXors, (double)sumLengths/(double)foundXors);
+ else
+ printf("c | Finding non-binary XORs: %5.2lf s (found: %7d, avg size: %3.1lf) |\n", cpuTime()-time, foundXors, (double)sumLengths/(double)foundXors);
}
- return found;
+ if (type == ClauseCleaner::binaryClauses) {
+ i = 0;
+ uint j = 0;
+ for (uint size = table.size(); i != size; i++) {
+ if (!toRemove[table[i].second]) {
+ table[i].first->setSorted();
+ cls[j++] = table[i].first;
+ }
+ }
+ cls.shrink(i-j);
+ } else if (foundXors > 0)
+ clearToRemove();
+
+ return S->ok = (S->propagate() == NULL);
}
-uint XorFinder::findXors(uint& sumLengths)
+const bool XorFinder::findXors(uint& sumLengths)
{
#ifdef VERBOSE_DEBUG
cout << "Finding Xors started" << endl;
#endif
- uint foundXors = 0;
sumLengths = 0;
- std::sort(table.begin(), table.end(), clause_sorter_primary());
ClauseTable::iterator begin = table.begin();
ClauseTable::iterator end = table.begin();
for (const Lit *it = &c[0], *cend = it+c.size() ; it != cend; it++) {
lits.push(Lit(it->var(), false));
}
- uint old_group = c.group;
+ uint old_group = c.getGroup();
#ifdef VERBOSE_DEBUG
cout << "- Found clauses:" << endl;
switch(lits.size()) {
case 2: {
- S->varReplacer->replace(lits, impair, old_group);
+ if (S->varReplacer->replace(lits, impair, old_group) == false)
+ return false;
#ifdef VERBOSE_DEBUG
XorClause* x = XorClause_new(lits, impair, old_group);
sumLengths += lits.size();
}
- return foundXors;
+ return true;
}
void XorFinder::clearToRemove()
while(begin != tableEnd && end != tableEnd) {
begin = end;
end++;
- while(end != tableEnd && clause_vareq(begin->first, end->first))
+ uint32_t size = (end == tableEnd ? 0:1);
+ while(end != tableEnd && clause_vareq(begin->first, end->first)) {
+ size++;
end++;
- if (isXor(begin, end, impair))
+ }
+ if (size > 0 && isXor(size, begin, end, impair))
return true;
}
return num % 2;
}
-bool XorFinder::isXor(const ClauseTable::iterator& begin, const ClauseTable::iterator& end, bool& impair)
+bool XorFinder::isXor(const uint32_t size, const ClauseTable::iterator& begin, const ClauseTable::iterator& end, bool& impair)
{
- uint size = &(*begin) - &(*end);
- assert(size > 0);
const uint requiredSize = 1 << (begin->first->size()-1);
if (size < requiredSize)
return false;
+ #ifdef DEBUG_XORFIND2
+ {
+ vec<Var> vars;
+ Clause& c = *begin->first;
+ for (uint i = 0; i < c.size(); i++)
+ vars.push(c[i].var());
+ for (ClauseTable::iterator it = begin; it != end; it++) {
+ Clause& c = *it->first;
+ for (uint i = 0; i < c.size(); i++)
+ assert(vars[i] == c[i].var());
+ }
+ clause_sorter_primary sorter;
+
+ for (ClauseTable::iterator it = begin; it != end; it++) {
+ ClauseTable::iterator it2 = it;
+ it2++;
+ if (it2 == end) break;
+ assert(!sorter(*it2, *it));
+ }
+ }
+ #endif //DEBUG_XORFIND
+
std::sort(begin, end, clause_sorter_secondary());
uint numPair = 0;
it2++;
}
}
-};
+
+}; //NAMESPACE MINISAT
#ifndef XORFINDER_H
#define XORFINDER_H
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#define DEBUG_XORFIND
+//#define DEBUG_XORFIND2
+
#include "Clause.h"
-#include <sys/types.h>
#include "VarReplacer.h"
#include "ClauseCleaner.h"
-namespace MINISAT
-{
-
class Solver;
using std::pair;
+namespace MINISAT
+{
+using namespace MINISAT;
+
class XorFinder
{
public:
XorFinder(Solver* S, vec<Clause*>& cls, ClauseCleaner::ClauseSetType _type);
- uint doNoPart(const uint minSize, const uint maxSize);
+ const bool doNoPart(const uint minSize, const uint maxSize);
private:
typedef vector<pair<Clause*, uint> > ClauseTable;
- uint findXors(uint& sumLengths);
+ const bool findXors(uint& sumLengths);
bool getNextXor(ClauseTable::iterator& begin, ClauseTable::iterator& end, bool& impair);
struct clause_hasher {
{
if (c11.first->size() != c22.first->size())
return (c11.first->size() < c22.first->size());
-
+
+ #ifdef DEBUG_XORFIND2
+ Clause& c1 = *c11.first;
+ for (uint i = 0; i+1 < c1.size(); i++)
+ assert(c1[i].var() <= c1[i+1].var());
+
+ Clause& c2 = *c22.first;
+ for (uint i = 0; i+1 < c2.size(); i++)
+ assert(c2[i].var() <= c2[i+1].var());
+ #endif //DEBUG_XORFIND2
+
for (a = c11.first->getData(), b = c22.first->getData(), end = a + c11.first->size(); a != end; a++, b++) {
if (a->var() != b->var())
- return (a->var() < b->var());
+ return (a->var() > b->var());
}
return false;
for (uint i = 0, size = c1.size(); i < size; i++) {
if (c1[i].sign() != c2[i].sign())
- return c2[i].sign();
+ return c1[i].sign();
}
return false;
ClauseTable table;
vector<bool> toRemove;
void clearToRemove();
+ uint32_t foundXors;
vec<Clause*>& cls;
ClauseCleaner::ClauseSetType type;
bool clauseEqual(const Clause& c1, const Clause& c2) const;
bool impairSigns(const Clause& c) const;
void countImpairs(const ClauseTable::iterator& begin, const ClauseTable::iterator& end, uint& numImpair, uint& numPair) const;
- bool isXor(const ClauseTable::iterator& begin, const ClauseTable::iterator& end, bool& impair);
+ bool isXor(const uint32_t size, const ClauseTable::iterator& begin, const ClauseTable::iterator& end, bool& impair);
Solver* S;
};
-};
+
+}; //NAMESPACE MINISAT
#endif //XORFINDER_H
--- /dev/null
+/**************************************************************************************************
+Originally From: Solver.C -- (C) Niklas Een, Niklas Sorensson, 2004
+Substantially modified by: Mate Soos (2010)
+**************************************************************************************************/
+
+#include "Solver.h"
+#include "XorSubsumer.h"
+#include "ClauseCleaner.h"
+#include "time_mem.h"
+#include "assert.h"
+#include <iomanip>
+#include "VarReplacer.h"
+
+#ifdef _MSC_VER
+#define __builtin_prefetch(a,b,c)
+#endif //_MSC_VER
+
+//#define VERBOSE_DEBUG
+#ifdef VERBOSE_DEBUG
+#define BIT_MORE_VERBOSITY
+#endif
+
+//#define BIT_MORE_VERBOSITY
+//#define TOUCH_LESS
+
+#ifdef VERBOSE_DEBUG
+using std::cout;
+using std::endl;
+#endif //VERBOSE_DEBUG
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+XorSubsumer::XorSubsumer(Solver& s):
+ solver(s)
+{
+};
+
+// Will put NULL in 'cs' if clause removed.
+void XorSubsumer::subsume0(XorClauseSimp& ps)
+{
+ assert(solver.xorclauses.size() == 0);
+ #ifdef VERBOSE_DEBUG
+ cout << "subsume0 orig clause:";
+ ps.clause->plainPrint();
+ cout << "pointer:" << &ps << endl;
+ #endif
+
+ vec<Lit> origClause(ps.clause->size());
+ std::copy(ps.clause->getData(), ps.clause->getDataEnd(), origClause.getData());
+ const bool origClauseInverted = ps.clause->xor_clause_inverted();
+
+ vec<Lit> unmatchedPart;
+ bool needUnlinkPS = false;
+
+ vec<XorClauseSimp> subs;
+ findSubsumed(*ps.clause, subs);
+ for (uint32_t i = 0; i < subs.size(); i++){
+ #ifdef VERBOSE_DEBUG
+ cout << "subsume0 removing:";
+ subs[i].clause->plainPrint();
+ #endif
+
+ XorClause* tmp = subs[i].clause;
+ findUnMatched(origClause, *tmp, unmatchedPart);
+ if (unmatchedPart.size() == 0) {
+ clauses_subsumed++;
+ assert(tmp->size() == origClause.size());
+ if (origClauseInverted == tmp->xor_clause_inverted()) {
+ unlinkClause(subs[i]);
+ free(tmp);
+ } else {
+ solver.ok = false;
+ return;
+ }
+ } else {
+ assert(unmatchedPart.size() > 0);
+ clauses_cut++;
+ //XorClause *c = solver.addXorClauseInt(unmatchedPart, tmp->xor_clause_inverted() ^ origClauseInverted, tmp->getGroup());
+ if (!solver.ok) return;
+ //if (c != NULL) {
+ //linkInClause(*c);
+ needUnlinkPS = true;
+ //}
+ }
+ unmatchedPart.clear();
+ }
+
+ /*if (needUnlinkPS) {
+ XorClause* tmp = ps.clause;
+ unlinkClause(ps);
+ free(tmp);
+ }*/
+}
+
+void XorSubsumer::findUnMatched(vec<Lit>& A, XorClause& B, vec<Lit>& unmatchedPart)
+{
+ for (uint32_t i = 0; i != B.size(); i++)
+ seen_tmp[B[i].var()] = 1;
+ for (uint32_t i = 0; i != A.size(); i++)
+ seen_tmp[A[i].var()] = 0;
+ for (uint32_t i = 0; i != B.size(); i++) {
+ if (seen_tmp[B[i].var()] == 1) {
+ unmatchedPart.push(Lit(B[i].var(), false));
+ seen_tmp[B[i].var()] = 0;
+ }
+ }
+}
+
+void XorSubsumer::unlinkClause(XorClauseSimp c)
+{
+ XorClause& cl = *c.clause;
+
+ for (uint32_t i = 0; i < cl.size(); i++) {
+ maybeRemove(occur[cl[i].var()], &cl);
+ }
+
+ solver.detachClause(cl);
+
+ clauses[c.index].clause = NULL;
+}
+
+void XorSubsumer::unlinkModifiedClause(vec<Lit>& origClause, XorClauseSimp c)
+{
+ for (uint32_t i = 0; i < origClause.size(); i++) {
+ maybeRemove(occur[origClause[i].var()], c.clause);
+ }
+
+ solver.detachModifiedClause(origClause[0].var(), origClause[1].var(), origClause.size(), c.clause);
+
+ clauses[c.index].clause = NULL;
+}
+
+void XorSubsumer::unlinkModifiedClauseNoDetachNoNULL(vec<Lit>& origClause, XorClauseSimp c)
+{
+ for (uint32_t i = 0; i < origClause.size(); i++) {
+ maybeRemove(occur[origClause[i].var()], c.clause);
+ }
+}
+
+XorClauseSimp XorSubsumer::linkInClause(XorClause& cl)
+{
+ XorClauseSimp c(&cl, clauseID++);
+ clauses.push(c);
+ for (uint32_t i = 0; i < cl.size(); i++) {
+ occur[cl[i].var()].push(c);
+ }
+
+ return c;
+}
+
+void XorSubsumer::linkInAlreadyClause(XorClauseSimp& c)
+{
+ XorClause& cl = *c.clause;
+
+ for (uint32_t i = 0; i < c.clause->size(); i++) {
+ occur[cl[i].var()].push(c);
+ }
+}
+
+void XorSubsumer::addFromSolver(vec<XorClause*>& cs)
+{
+ XorClause **i = cs.getData();
+ for (XorClause **end = i + cs.size(); i != end; i++) {
+ if (i+1 != end)
+ __builtin_prefetch(*(i+1), 1, 1);
+
+ linkInClause(**i);
+ if ((*i)->getVarChanged() || (*i)->getStrenghtened())
+ (*i)->calcXorAbstraction();
+ }
+ cs.clear();
+}
+
+void XorSubsumer::addBackToSolver()
+{
+ for (uint32_t i = 0; i < clauses.size(); i++) {
+ if (clauses[i].clause != NULL) {
+ solver.xorclauses.push(clauses[i].clause);
+ clauses[i].clause->unsetStrenghtened();
+ clauses[i].clause->unsetVarChanged();
+ }
+ }
+ for (Var var = 0; var < solver.nVars(); var++) {
+ occur[var].clear();
+ }
+ clauses.clear();
+ clauseID = 0;
+}
+
+const bool XorSubsumer::simplifyBySubsumption(const bool doFullSubsume)
+{
+ double myTime = cpuTime();
+ uint32_t origTrailSize = solver.trail.size();
+ clauses_subsumed = 0;
+ clauses_cut = 0;
+ clauseID = 0;
+
+ for (Var var = 0; var < solver.nVars(); var++) {
+ //occur[var].clear(true);
+ newVar();
+ }
+
+ while (solver.performReplace && solver.varReplacer->needsReplace()) {
+ if (!solver.varReplacer->performReplace())
+ return false;
+ }
+
+ solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses);
+ if (!solver.ok) return false;
+
+ clauses.clear();
+ clauses.reserve(solver.xorclauses.size());
+ addFromSolver(solver.xorclauses);
+ #ifdef BIT_MORE_VERBOSITY
+ std::cout << "c time to link in:" << cpuTime()-myTime << std::endl;
+ #endif
+
+ origNClauses = clauses.size();
+
+ if (!solver.ok) return false;
+ #ifdef VERBOSE_DEBUG
+ std::cout << "c clauses:" << clauses.size() << std::endl;
+ #endif
+
+ bool replaced = true;
+ bool propagated = false;
+ while (replaced || propagated) {
+ replaced = propagated = false;
+ for (uint32_t i = 0; i < clauses.size(); i++) {
+ if (clauses[i].clause != NULL) {
+ subsume0(clauses[i]);
+ if (!solver.ok) return false;
+ }
+ }
+
+ if (solver.qhead != solver.trail.size()) propagated = true;
+ solver.ok = solver.propagate() == NULL;
+ if (!solver.ok) {
+ std::cout << "c (contradiction during subsumption)" << std::endl;
+ return false;
+ }
+ solver.clauseCleaner->cleanXorClausesBewareNULL(clauses, ClauseCleaner::xorSimpClauses, *this);
+ if (!solver.ok) return false;
+
+ if (solver.performReplace && solver.varReplacer->needsReplace()) {
+ addBackToSolver();
+ while (solver.performReplace && solver.varReplacer->needsReplace()) {
+ replaced = true;
+ if (!solver.varReplacer->performReplace())
+ return false;
+ }
+ addFromSolver(solver.xorclauses);
+ }
+ }
+
+ if (solver.trail.size() - origTrailSize > 0)
+ solver.order_heap.filter(Solver::VarFilter(solver));
+
+ addBackToSolver();
+
+ if (solver.verbosity >= 1) {
+ std::cout << "c | xorclauses-subsumed: " << std::setw(9) << clauses_subsumed
+ << " xorclauses-cut: " << std::setw(9) << clauses_cut
+ << " vars fixed: " << std::setw(3) <<solver.trail.size() - origTrailSize
+ << " time: " << std::setw(5) << std::setprecision(2) << (cpuTime() - myTime)
+ << " |" << std::endl;
+ }
+
+ return true;
+}
+
+void XorSubsumer::findSubsumed(XorClause& ps, vec<XorClauseSimp>& out_subsumed)
+{
+ #ifdef VERBOSE_DEBUG
+ cout << "findSubsumed: ";
+ for (uint32_t i = 0; i < ps.size(); i++) {
+ if (ps[i].sign()) printf("-");
+ printf("%d ", ps[i].var() + 1);
+ }
+ printf("0\n");
+ #endif
+
+ uint32_t min_i = 0;
+ for (uint32_t i = 1; i < ps.size(); i++){
+ if (occur[ps[i].var()].size() < occur[ps[min_i].var()].size())
+ min_i = i;
+ }
+
+ vec<XorClauseSimp>& cs = occur[ps[min_i].var()];
+ for (XorClauseSimp *it = cs.getData(), *end = it + cs.size(); it != end; it++){
+ if (it+1 != end)
+ __builtin_prefetch((it+1)->clause, 1, 1);
+
+ if (it->clause != &ps && subsetAbst(ps.getAbst(), it->clause->getAbst()) && ps.size() <= it->clause->size() && subset(ps, *it->clause)) {
+ out_subsumed.push(*it);
+ #ifdef VERBOSE_DEBUG
+ cout << "subsumed: ";
+ it->clause->plainPrint();
+ #endif
+ }
+ }
+}
+
+}; //NAMESPACE MINISAT
--- /dev/null
+/**************************************************************************************************
+Originally From: Solver.C -- (C) Niklas Een, Niklas Sorensson, 2004
+Substantially modified by: Mate Soos (2010)
+**************************************************************************************************/
+
+#ifndef XORSIMPLIFIER_H
+#define XORSIMPLIFIER_H
+
+#include "Solver.h"
+#include "Vec.h"
+#include "XSet.h"
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+class ClauseCleaner;
+
+class XorSubsumer
+{
+public:
+
+ XorSubsumer(Solver& S2);
+ const bool simplifyBySubsumption(const bool doFullSubsume = false);
+ void unlinkModifiedClause(vec<Lit>& origClause, XorClauseSimp c);
+ void unlinkModifiedClauseNoDetachNoNULL(vec<Lit>& origClause, XorClauseSimp c);
+ void unlinkClause(XorClauseSimp cc);
+ XorClauseSimp linkInClause(XorClause& cl);
+ void linkInAlreadyClause(XorClauseSimp& c);
+ void newVar();
+
+private:
+
+ friend class ClauseCleaner;
+
+ //Main
+ vec<XorClauseSimp> clauses;
+ vec<vec<XorClauseSimp> > occur; // 'occur[index(lit)]' is a list of constraints containing 'lit'.
+ Solver& solver; // The Solver
+
+ // Temporaries (to reduce allocation overhead):
+ //
+ vec<char> seen_tmp; // (used in various places)
+
+ //Start-up
+ void addFromSolver(vec<XorClause*>& cs);
+ void addBackToSolver();
+
+ // Subsumption:
+ void findSubsumed(XorClause& ps, vec<XorClauseSimp>& out_subsumed);
+ bool isSubsumed(XorClause& ps);
+ void subsume0(XorClauseSimp& ps);
+ template<class T1, class T2>
+ bool subset(const T1& A, const T2& B);
+ bool subsetAbst(uint32_t A, uint32_t B);
+ void findUnMatched(vec<Lit>& A, XorClause& B, vec<Lit>& unmatchedPart);
+
+ uint32_t clauses_subsumed;
+ uint32_t clauses_cut;
+ uint32_t origNClauses;
+ uint32_t clauseID;
+};
+
+inline bool XorSubsumer::subsetAbst(uint32_t A, uint32_t B)
+{
+ return !(A & ~B);
+}
+
+// Assumes 'seen' is cleared (will leave it cleared)
+template<class T1, class T2>
+bool XorSubsumer::subset(const T1& A, const T2& B)
+{
+ for (uint32_t i = 0; i != B.size(); i++)
+ seen_tmp[B[i].var()] = 1;
+ for (uint32_t i = 0; i != A.size(); i++) {
+ if (!seen_tmp[A[i].var()]) {
+ for (uint32_t i = 0; i != B.size(); i++)
+ seen_tmp[B[i].var()] = 0;
+ return false;
+ }
+ }
+ for (uint32_t i = 0; i != B.size(); i++)
+ seen_tmp[B[i].var()] = 0;
+ return true;
+}
+
+inline void XorSubsumer::newVar()
+{
+ occur .push();
+ seen_tmp .push(0); // (one for each polarity)
+}
+
+}; //NAMESPACE MINISAT
+
+#endif //XORSIMPLIFIER_H
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
-#define RATIOREMOVECLAUSES 2
+#define RATIOREMOVECLAUSES 3
#define NBCLAUSESBEFOREREDUCE 20000
#define DYNAMICNBLEVEL
#define UPDATEVARACTIVITY
-#define PERCENTAGEPERFORMREPLACE 0.03
-#define STATS_NEEDED
-#define PERCENTAGECLEANCLAUSES 0.005
-#define MAX_CLAUSENUM_XORFIND 1000000
-#define BINARY_TO_XOR_APPROX 10.0
+#define FIXCLEANREPLACE 30U
+#define PERCENTAGEPERFORMREPLACE 0.01
+#define PERCENTAGECLEANCLAUSES 0.01
+#define MAX_CLAUSENUM_XORFIND 5000000
+#define BINARY_TO_XOR_APPROX 4.0
+#define FULLRESTART_MULTIPLIER 250.0
+#define FULLRESTART_MULTIPLIER_MULTIPLIER 3.5
+#define RESTART_TYPE_DECIDER_FROM 2
+#define RESTART_TYPE_DECIDER_UNTIL 7
//#define VERBOSE_DEBUG_XOR
//#define VERBOSE_DEBUG
--- /dev/null
+// ISO C9x compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+// Copyright (c) 2006-2008 Alexander Chemeris
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// 3. The name of the author may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include <limits.h>
+
+// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
+// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler give many errors like this:
+// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+#ifdef __cplusplus
+extern "C" {
+#endif
+# include <wchar.h>
+#ifdef __cplusplus
+}
+#endif
+
+// Define _W64 macros to mark types changing their size, like intptr_t.
+#ifndef _W64
+# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
+# define _W64 __w64
+# else
+# define _W64
+# endif
+#endif
+
+
+// 7.18.1 Integer types
+
+// 7.18.1.1 Exact-width integer types
+
+// Visual Studio 6 and Embedded Visual C++ 4 doesn't
+// realize that, e.g. char has the same size as __int8
+// so we give up on __intX for them.
+#if (_MSC_VER < 1300)
+ typedef signed char int8_t;
+ typedef signed short int16_t;
+ typedef signed int int32_t;
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+#else
+ typedef signed __int8 int8_t;
+ typedef signed __int16 int16_t;
+ typedef signed __int32 int32_t;
+ typedef unsigned __int8 uint8_t;
+ typedef unsigned __int16 uint16_t;
+ typedef unsigned __int32 uint32_t;
+#endif
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+
+
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t int_least8_t;
+typedef int16_t int_least16_t;
+typedef int32_t int_least32_t;
+typedef int64_t int_least64_t;
+typedef uint8_t uint_least8_t;
+typedef uint16_t uint_least16_t;
+typedef uint32_t uint_least32_t;
+typedef uint64_t uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t int_fast8_t;
+typedef int16_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef int64_t int_fast64_t;
+typedef uint8_t uint_fast8_t;
+typedef uint16_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+typedef uint64_t uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+#ifdef _WIN64 // [
+ typedef signed __int64 intptr_t;
+ typedef unsigned __int64 uintptr_t;
+#else // _WIN64 ][
+ typedef _W64 signed int intptr_t;
+ typedef _W64 unsigned int uintptr_t;
+#endif // _WIN64 ]
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t intmax_t;
+typedef uint64_t uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN ((int8_t)_I8_MIN)
+#define INT8_MAX _I8_MAX
+#define INT16_MIN ((int16_t)_I16_MIN)
+#define INT16_MAX _I16_MAX
+#define INT32_MIN ((int32_t)_I32_MIN)
+#define INT32_MAX _I32_MAX
+#define INT64_MIN ((int64_t)_I64_MIN)
+#define INT64_MAX _I64_MAX
+#define UINT8_MAX _UI8_MAX
+#define UINT16_MAX _UI16_MAX
+#define UINT32_MAX _UI32_MAX
+#define UINT64_MAX _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST8_MAX INT8_MAX
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST16_MAX INT16_MAX
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST32_MAX INT32_MAX
+#define INT_LEAST64_MIN INT64_MIN
+#define INT_LEAST64_MAX INT64_MAX
+#define UINT_LEAST8_MAX UINT8_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN INT8_MIN
+#define INT_FAST8_MAX INT8_MAX
+#define INT_FAST16_MIN INT16_MIN
+#define INT_FAST16_MAX INT16_MAX
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST32_MAX INT32_MAX
+#define INT_FAST64_MIN INT64_MIN
+#define INT_FAST64_MAX INT64_MAX
+#define UINT_FAST8_MAX UINT8_MAX
+#define UINT_FAST16_MAX UINT16_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+#define UINT_FAST64_MAX UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+# define INTPTR_MIN INT64_MIN
+# define INTPTR_MAX INT64_MAX
+# define UINTPTR_MAX UINT64_MAX
+#else // _WIN64 ][
+# define INTPTR_MIN INT32_MIN
+# define INTPTR_MAX INT32_MAX
+# define UINTPTR_MAX UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN INT64_MIN
+#define INTMAX_MAX INT64_MAX
+#define UINTMAX_MAX UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+# define PTRDIFF_MIN _I64_MIN
+# define PTRDIFF_MAX _I64_MAX
+#else // _WIN64 ][
+# define PTRDIFF_MIN _I32_MIN
+# define PTRDIFF_MAX _I32_MAX
+#endif // _WIN64 ]
+
+#define SIG_ATOMIC_MIN INT_MIN
+#define SIG_ATOMIC_MAX INT_MAX
+
+#ifndef SIZE_MAX // [
+# ifdef _WIN64 // [
+# define SIZE_MAX _UI64_MAX
+# else // _WIN64 ][
+# define SIZE_MAX _UI32_MAX
+# endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+# define WCHAR_MIN 0
+#endif // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+# define WCHAR_MAX _UI16_MAX
+#endif // WCHAR_MAX ]
+
+#define WINT_MIN 0
+#define WINT_MAX _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val) val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val) val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+#define INTMAX_C INT64_C
+#define UINTMAX_C UINT64_C
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+#ifndef uint
+#define uint unsigned int
+#endif
+
+#endif // _MSC_STDINT_H_ ]
#ifndef Alg_h
#define Alg_h
-#include "stdint.h"
-//=================================================================================================
-// Useful functions on vectors
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
namespace MINISAT
{
+using namespace MINISAT;
+
+//=================================================================================================
+// Useful functions on vectors
+
template<class V, class T>
static inline void remove(V& ts, const T& t)
return j < ts.size();
}
-};
+}; //NAMESPACE MINISAT
#endif
#ifndef BasicHeap_h
#define BasicHeap_h
-#include "Vec.h"
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VERs
+
+#include "Vec.h"
namespace MINISAT
{
+using namespace MINISAT;
//=================================================================================================
// A heap implementation with support for decrease/increase key.
int getmin () { return removeMin(); }
};
-};
+}; //NAMESPACE MINISAT
//=================================================================================================
#endif
namespace MINISAT
{
+using namespace MINISAT;
//=================================================================================================
// Automatically resizable arrays
};
-};
+}; //NAMESPACE MINISAT
#endif
#define Heap_h
#include "Vec.h"
+
#include "string.h"
+#include <limits>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
#include <stdint.h>
-#ifndef UINT32_MAX
-#define UINT32_MAX ((uint32_t)-1)
-#endif
+#endif //_MSC_VER
namespace MINISAT
{
+using namespace MINISAT;
//=================================================================================================
// A heap implementation with support for decrease/increase key.
indices.growTo(other.indices.size());
memcpy(indices.getData(), other.indices.getData(), sizeof(uint32_t)*other.indices.size());
}
+
+ void operator=(const Heap<Comp>& other)
+ {
+ if (other.heap.size() > heap.size())
+ heap.growTo(other.heap.size());
+ else
+ heap.shrink(other.heap.size()-heap.size());
+ memcpy(heap.getData(), other.heap.getData(), heap.size()*sizeof(uint32_t));
+
+ if (other.indices.size() > indices.size())
+ indices.growTo(other.indices.size());
+ else
+ indices.shrink(other.indices.size()-indices.size());
+ memcpy(indices.getData(), other.indices.getData(), indices.size()*sizeof(uint32_t));
+ }
uint32_t size () const { return heap.size(); }
bool empty () const { return heap.size() == 0; }
- bool inHeap (uint32_t n) const { return n < indices.size() && indices[n] != UINT32_MAX; }
+ bool inHeap (uint32_t n) const { return n < indices.size() && indices[n] != std::numeric_limits<uint32_t>::max(); }
uint32_t operator[](uint32_t index) const { assert(index < heap.size()); return heap[index]; }
void decrease (uint32_t n) { assert(inHeap(n)); percolateUp(indices[n]); }
void insert(uint32_t n)
{
- indices.growTo(n+1, UINT32_MAX);
+ indices.growTo(n+1, std::numeric_limits<uint32_t>::max());
assert(!inHeap(n));
indices[n] = heap.size();
uint32_t x = heap[0];
heap[0] = heap.last();
indices[heap[0]] = 0;
- indices[x] = UINT32_MAX;
+ indices[x] = std::numeric_limits<uint32_t>::max();
heap.pop();
if (heap.size() > 1) percolateDown(0);
return x;
void clear(bool dealloc = false)
{
for (uint32_t i = 0; i != heap.size(); i++)
- indices[heap[i]] = UINT32_MAX;
+ indices[heap[i]] = std::numeric_limits<uint32_t>::max();
#ifndef NDEBUG
for (uint32_t i = 0; i != indices.size(); i++)
- assert(indices[i] == UINT32_MAX);
+ assert(indices[i] == std::numeric_limits<uint32_t>::max());
#endif
heap.clear(dealloc);
}
heap[j] = heap[i];
indices[heap[i]] = j++;
}else
- indices[heap[i]] = UINT32_MAX;
+ indices[heap[i]] = std::numeric_limits<uint32_t>::max();
heap.shrink(i - j);
for (int i = heap.size() / 2 - 1; i >= 0; i--)
};
-};
-
//=================================================================================================
+
+}; //NAMESPACE MINISAT
+
#endif
#ifndef Map_h
#define Map_h
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
#include <stdint.h>
+#endif //_MSC_VER
+
#include "Vec.h"
namespace MINISAT
{
+using namespace MINISAT;
//=================================================================================================
// Default hash/equals functions
}
};
-};
+}; //NAMESPACE MINISAT
#endif
namespace MINISAT
{
+using namespace MINISAT;
//=================================================================================================
// }
//};
-};
-
//=================================================================================================
+
+}; //NAMESPACE MINISAT
+
#endif
#ifndef Vec_h
#define Vec_h
+
#include <cstdlib>
#include <cassert>
#include <new>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
#include <stdint.h>
+#endif //_MSC_VER
namespace MINISAT
{
+using namespace MINISAT;
+
//=================================================================================================
// Automatically resizable arrays
//
// Don't allow copying (error prone):
vec<T>& operator = (vec<T>& other) { assert(0); return *this; }
- vec (vec<T>& other) { assert(0); }
+ //vec (vec<T>& other) { assert(0); }
static inline uint32_t imax(int x, int y) {
int mask = (y-x) >> (sizeof(int)*8-1);
return (x&mask) + (y&(~mask)); }
+
+ void myCopy (const vec<T>& other);
public:
// Types:
vec(uint32_t size) : data(NULL) , sz(0) , cap(0) { growTo(size); }
vec(uint32_t size, const T& pad) : data(NULL) , sz(0) , cap(0) { growTo(size, pad); }
vec(T* array, uint32_t size) : data(array), sz(size), cap(size) { } // (takes ownership of array -- will be deallocated with 'free()')
+ vec(const vec<T>& other) : data(NULL) , sz(0) , cap(0) { myCopy(other); }
~vec(void) { clear(true); }
// Ownership of underlying array:
T* release (void) { T* ret = data; data = NULL; sz = 0; cap = 0; return ret; }
const T* getData() const {return data; }
+ const T* getDataEnd() const {return data + size(); }
T* getData() {return data; }
+ T* getDataEnd() {return data + size(); }
// Size operations:
uint32_t size (void) const { return sz; }
void capacity (uint32_t size) { grow(size); }
// Stack interface:
+ void reserve(uint32_t res) { if (cap < res) {cap = res; data = (T*)realloc(data, cap * sizeof(T));}}
void push (void) { if (sz == cap) { cap = imax(2, (cap*3+1)>>1); data = (T*)realloc(data, cap * sizeof(T)); } new (&data[sz]) T(); sz++; }
void push (const T& elem) { if (sz == cap) { cap = imax(2, (cap*3+1)>>1); data = (T*)realloc(data, cap * sizeof(T)); } data[sz++] = elem; }
void push_ (const T& elem) { assert(sz < cap); data[sz++] = elem; }
grow(size);
for (uint32_t i = sz; i != size; i++) new (&data[i]) T();
sz = size; }
+
+template<class T>
+void vec<T>::myCopy(const vec<T>& other) {
+ assert(sz == 0);
+ grow(other.size());
+ for (uint32_t i = sz; i != other.size(); i++) new (&data[i]) T(other[i]);
+ sz = other.size(); }
template<class T>
void vec<T>::clear(bool dealloc) {
sz = 0;
if (dealloc) free(data), data = NULL, cap = 0; } }
-};
+
+}; //NAMESPACE MINISAT
#endif
--- /dev/null
+// Copyright (C) 2000, 2001 Stephen Cleary
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#ifndef BOOST_POOL_HPP
+#define BOOST_POOL_HPP
+
+#include <boost/config.hpp> // for workarounds
+
+// std::less, std::less_equal, std::greater
+#include <functional>
+// new[], delete[], std::nothrow
+#include <new>
+// std::size_t, std::ptrdiff_t
+#include <cstddef>
+// std::malloc, std::free
+#include <cstdlib>
+// std::invalid_argument
+#include <exception>
+// std::max
+#include <algorithm>
+
+#include "poolfwd.hpp"
+
+// boost::details::pool::ct_lcm
+#include <boost/pool/detail/ct_gcd_lcm.hpp>
+// boost::details::pool::lcm
+#include <boost/pool/detail/gcd_lcm.hpp>
+// boost::simple_segregated_storage
+#include <boost/pool/simple_segregated_storage.hpp>
+
+#ifdef BOOST_NO_STDC_NAMESPACE
+ namespace std { using ::malloc; using ::free; }
+#endif
+
+// There are a few places in this file where the expression "this->m" is used.
+// This expression is used to force instantiation-time name lookup, which I am
+// informed is required for strict Standard compliance. It's only necessary
+// if "m" is a member of a base class that is dependent on a template
+// parameter.
+// Thanks to Jens Maurer for pointing this out!
+
+namespace boost {
+
+struct default_user_allocator_new_delete
+{
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ static char * malloc(const size_type bytes)
+ { return new (std::nothrow) char[bytes]; }
+ static void free(char * const block)
+ { delete [] block; }
+};
+
+struct default_user_allocator_malloc_free
+{
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ static char * malloc(const size_type bytes)
+ { return reinterpret_cast<char *>(std::malloc(bytes)); }
+ static void free(char * const block)
+ { std::free(block); }
+};
+
+namespace details {
+
+// PODptr is a class that pretends to be a "pointer" to different class types
+// that don't really exist. It provides member functions to access the "data"
+// of the "object" it points to. Since these "class" types are of variable
+// size, and contains some information at the *end* of its memory (for
+// alignment reasons), PODptr must contain the size of this "class" as well as
+// the pointer to this "object".
+template <typename SizeType>
+class PODptr
+{
+ public:
+ typedef SizeType size_type;
+
+ private:
+ char * ptr;
+ size_type sz;
+
+ char * ptr_next_size() const
+ { return (ptr + sz - sizeof(size_type)); }
+ char * ptr_next_ptr() const
+ {
+ return (ptr_next_size() -
+ pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value);
+ }
+
+ public:
+ PODptr(char * const nptr, const size_type nsize)
+ :ptr(nptr), sz(nsize) { }
+ PODptr()
+ :ptr(0), sz(0) { }
+
+ bool valid() const { return (begin() != 0); }
+ void invalidate() { begin() = 0; }
+ char * & begin() { return ptr; }
+ char * begin() const { return ptr; }
+ char * end() const { return ptr_next_ptr(); }
+ size_type total_size() const { return sz; }
+ size_type element_size() const
+ {
+ return (sz - sizeof(size_type) -
+ pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value);
+ }
+
+ size_type & next_size() const
+ { return *(reinterpret_cast<size_type *>(ptr_next_size())); }
+ char * & next_ptr() const
+ { return *(reinterpret_cast<char **>(ptr_next_ptr())); }
+
+ PODptr next() const
+ { return PODptr<size_type>(next_ptr(), next_size()); }
+ void next(const PODptr & arg) const
+ {
+ next_ptr() = arg.begin();
+ next_size() = arg.total_size();
+ }
+};
+
+} // namespace details
+
+template <typename UserAllocator>
+class pool: protected simple_segregated_storage<
+ typename UserAllocator::size_type>
+{
+ public:
+ typedef UserAllocator user_allocator;
+ typedef typename UserAllocator::size_type size_type;
+ typedef typename UserAllocator::difference_type difference_type;
+
+ private:
+ BOOST_STATIC_CONSTANT(unsigned, min_alloc_size =
+ (::boost::details::pool::ct_lcm<sizeof(void *), sizeof(size_type)>::value) );
+
+ // Returns 0 if out-of-memory
+ // Called if malloc/ordered_malloc needs to resize the free list
+ void * malloc_need_resize();
+ void * ordered_malloc_need_resize();
+
+ protected:
+ details::PODptr<size_type> list;
+
+ simple_segregated_storage<size_type> & store() { return *this; }
+ const simple_segregated_storage<size_type> & store() const { return *this; }
+ const size_type requested_size;
+ size_type next_size;
+ size_type start_size;
+
+ // finds which POD in the list 'chunk' was allocated from
+ details::PODptr<size_type> find_POD(void * const chunk) const;
+
+ // is_from() tests a chunk to determine if it belongs in a block
+ static bool is_from(void * const chunk, char * const i,
+ const size_type sizeof_i)
+ {
+ // We use std::less_equal and std::less to test 'chunk'
+ // against the array bounds because standard operators
+ // may return unspecified results.
+ // This is to ensure portability. The operators < <= > >= are only
+ // defined for pointers to objects that are 1) in the same array, or
+ // 2) subobjects of the same object [5.9/2].
+ // The functor objects guarantee a total order for any pointer [20.3.3/8]
+//WAS:
+// return (std::less_equal<void *>()(static_cast<void *>(i), chunk)
+// && std::less<void *>()(chunk,
+// static_cast<void *>(i + sizeof_i)));
+ std::less_equal<void *> lt_eq;
+ std::less<void *> lt;
+ return (lt_eq(i, chunk) && lt(chunk, i + sizeof_i));
+ }
+
+ size_type alloc_size() const
+ {
+ const unsigned min_size = min_alloc_size;
+ return details::pool::lcm<size_type>(requested_size, min_size);
+ }
+
+ // for the sake of code readability :)
+ static void * & nextof(void * const ptr)
+ { return *(static_cast<void **>(ptr)); }
+
+ public:
+ // The second parameter here is an extension!
+ // pre: npartition_size != 0 && nnext_size != 0
+ explicit pool(const size_type nrequested_size,
+ const size_type nnext_size = 32)
+ :list(0, 0), requested_size(nrequested_size), next_size(nnext_size), start_size(nnext_size)
+ { }
+
+ ~pool() { purge_memory(); }
+
+ // Releases memory blocks that don't have chunks allocated
+ // pre: lists are ordered
+ // Returns true if memory was actually deallocated
+ bool release_memory();
+
+ // Releases *all* memory blocks, even if chunks are still allocated
+ // Returns true if memory was actually deallocated
+ bool purge_memory();
+
+ // These functions are extensions!
+ size_type get_next_size() const { return next_size; }
+ void set_next_size(const size_type nnext_size) { next_size = start_size = nnext_size; }
+ size_type get_requested_size() const { return requested_size; }
+
+ // Both malloc and ordered_malloc do a quick inlined check first for any
+ // free chunks. Only if we need to get another memory block do we call
+ // the non-inlined *_need_resize() functions.
+ // Returns 0 if out-of-memory
+ void * malloc()
+ {
+ // Look for a non-empty storage
+ if (!store().empty())
+ return store().malloc();
+ return malloc_need_resize();
+ }
+
+ void * ordered_malloc()
+ {
+ // Look for a non-empty storage
+ if (!store().empty())
+ return store().malloc();
+ return ordered_malloc_need_resize();
+ }
+
+ // Returns 0 if out-of-memory
+ // Allocate a contiguous section of n chunks
+ void * ordered_malloc(size_type n);
+
+ // pre: 'chunk' must have been previously
+ // returned by *this.malloc().
+ void free(void * const chunk)
+ { store().free(chunk); }
+
+ // pre: 'chunk' must have been previously
+ // returned by *this.malloc().
+ void ordered_free(void * const chunk)
+ { store().ordered_free(chunk); }
+
+ // pre: 'chunk' must have been previously
+ // returned by *this.malloc(n).
+ void free(void * const chunks, const size_type n)
+ {
+ const size_type partition_size = alloc_size();
+ const size_type total_req_size = n * requested_size;
+ const size_type num_chunks = total_req_size / partition_size +
+ ((total_req_size % partition_size) ? true : false);
+
+ store().free_n(chunks, num_chunks, partition_size);
+ }
+
+ // pre: 'chunk' must have been previously
+ // returned by *this.malloc(n).
+ void ordered_free(void * const chunks, const size_type n)
+ {
+ const size_type partition_size = alloc_size();
+ const size_type total_req_size = n * requested_size;
+ const size_type num_chunks = total_req_size / partition_size +
+ ((total_req_size % partition_size) ? true : false);
+
+ store().ordered_free_n(chunks, num_chunks, partition_size);
+ }
+
+ // is_from() tests a chunk to determine if it was allocated from *this
+ bool is_from(void * const chunk) const
+ {
+ return (find_POD(chunk).valid());
+ }
+};
+
+template <typename UserAllocator>
+bool pool<UserAllocator>::release_memory()
+{
+ // This is the return value: it will be set to true when we actually call
+ // UserAllocator::free(..)
+ bool ret = false;
+
+ // This is a current & previous iterator pair over the memory block list
+ details::PODptr<size_type> ptr = list;
+ details::PODptr<size_type> prev;
+
+ // This is a current & previous iterator pair over the free memory chunk list
+ // Note that "prev_free" in this case does NOT point to the previous memory
+ // chunk in the free list, but rather the last free memory chunk before the
+ // current block.
+ void * free_p = this->first;
+ void * prev_free_p = 0;
+
+ const size_type partition_size = alloc_size();
+
+ // Search through all the all the allocated memory blocks
+ while (ptr.valid())
+ {
+ // At this point:
+ // ptr points to a valid memory block
+ // free_p points to either:
+ // 0 if there are no more free chunks
+ // the first free chunk in this or some next memory block
+ // prev_free_p points to either:
+ // the last free chunk in some previous memory block
+ // 0 if there is no such free chunk
+ // prev is either:
+ // the PODptr whose next() is ptr
+ // !valid() if there is no such PODptr
+
+ // If there are no more free memory chunks, then every remaining
+ // block is allocated out to its fullest capacity, and we can't
+ // release any more memory
+ if (free_p == 0)
+ break;
+
+ // We have to check all the chunks. If they are *all* free (i.e., present
+ // in the free list), then we can free the block.
+ bool all_chunks_free = true;
+
+ // Iterate 'i' through all chunks in the memory block
+ // if free starts in the memory block, be careful to keep it there
+ void * saved_free = free_p;
+ for (char * i = ptr.begin(); i != ptr.end(); i += partition_size)
+ {
+ // If this chunk is not free
+ if (i != free_p)
+ {
+ // We won't be able to free this block
+ all_chunks_free = false;
+
+ // free_p might have travelled outside ptr
+ free_p = saved_free;
+ // Abort searching the chunks; we won't be able to free this
+ // block because a chunk is not free.
+ break;
+ }
+
+ // We do not increment prev_free_p because we are in the same block
+ free_p = nextof(free_p);
+ }
+
+ // post: if the memory block has any chunks, free_p points to one of them
+ // otherwise, our assertions above are still valid
+
+ const details::PODptr<size_type> next = ptr.next();
+
+ if (!all_chunks_free)
+ {
+ if (is_from(free_p, ptr.begin(), ptr.element_size()))
+ {
+ std::less<void *> lt;
+ void * const end = ptr.end();
+ do
+ {
+ prev_free_p = free_p;
+ free_p = nextof(free_p);
+ } while (free_p && lt(free_p, end));
+ }
+ // This invariant is now restored:
+ // free_p points to the first free chunk in some next memory block, or
+ // 0 if there is no such chunk.
+ // prev_free_p points to the last free chunk in this memory block.
+
+ // We are just about to advance ptr. Maintain the invariant:
+ // prev is the PODptr whose next() is ptr, or !valid()
+ // if there is no such PODptr
+ prev = ptr;
+ }
+ else
+ {
+ // All chunks from this block are free
+
+ // Remove block from list
+ if (prev.valid())
+ prev.next(next);
+ else
+ list = next;
+
+ // Remove all entries in the free list from this block
+ if (prev_free_p != 0)
+ nextof(prev_free_p) = free_p;
+ else
+ this->first = free_p;
+
+ // And release memory
+ UserAllocator::free(ptr.begin());
+ ret = true;
+ }
+
+ // Increment ptr
+ ptr = next;
+ }
+
+ next_size = start_size;
+ return ret;
+}
+
+template <typename UserAllocator>
+bool pool<UserAllocator>::purge_memory()
+{
+ details::PODptr<size_type> iter = list;
+
+ if (!iter.valid())
+ return false;
+
+ do
+ {
+ // hold "next" pointer
+ const details::PODptr<size_type> next = iter.next();
+
+ // delete the storage
+ UserAllocator::free(iter.begin());
+
+ // increment iter
+ iter = next;
+ } while (iter.valid());
+
+ list.invalidate();
+ this->first = 0;
+ next_size = start_size;
+
+ return true;
+}
+
+template <typename UserAllocator>
+void * pool<UserAllocator>::malloc_need_resize()
+{
+ // No memory in any of our storages; make a new storage,
+ const size_type partition_size = alloc_size();
+ const size_type POD_size = next_size * partition_size +
+ details::pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type);
+ char * const ptr = UserAllocator::malloc(POD_size);
+ if (ptr == 0)
+ return 0;
+ const details::PODptr<size_type> node(ptr, POD_size);
+ next_size <<= 1;
+
+ // initialize it,
+ store().add_block(node.begin(), node.element_size(), partition_size);
+
+ // insert it into the list,
+ node.next(list);
+ list = node;
+
+ // and return a chunk from it.
+ return store().malloc();
+}
+
+template <typename UserAllocator>
+void * pool<UserAllocator>::ordered_malloc_need_resize()
+{
+ // No memory in any of our storages; make a new storage,
+ const size_type partition_size = alloc_size();
+ const size_type POD_size = next_size * partition_size +
+ details::pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type);
+ char * const ptr = UserAllocator::malloc(POD_size);
+ if (ptr == 0)
+ return 0;
+ const details::PODptr<size_type> node(ptr, POD_size);
+ next_size <<= 1;
+
+ // initialize it,
+ // (we can use "add_block" here because we know that
+ // the free list is empty, so we don't have to use
+ // the slower ordered version)
+ store().add_block(node.begin(), node.element_size(), partition_size);
+
+ // insert it into the list,
+ // handle border case
+ if (!list.valid() || std::greater<void *>()(list.begin(), node.begin()))
+ {
+ node.next(list);
+ list = node;
+ }
+ else
+ {
+ details::PODptr<size_type> prev = list;
+
+ while (true)
+ {
+ // if we're about to hit the end or
+ // if we've found where "node" goes
+ if (prev.next_ptr() == 0
+ || std::greater<void *>()(prev.next_ptr(), node.begin()))
+ break;
+
+ prev = prev.next();
+ }
+
+ node.next(prev.next());
+ prev.next(node);
+ }
+
+ // and return a chunk from it.
+ return store().malloc();
+}
+
+template <typename UserAllocator>
+void * pool<UserAllocator>::ordered_malloc(const size_type n)
+{
+ const size_type partition_size = alloc_size();
+ const size_type total_req_size = n * requested_size;
+ const size_type num_chunks = total_req_size / partition_size +
+ ((total_req_size % partition_size) ? true : false);
+
+ void * ret = store().malloc_n(num_chunks, partition_size);
+
+ if (ret != 0)
+ return ret;
+
+ // Not enougn memory in our storages; make a new storage,
+ BOOST_USING_STD_MAX();
+ next_size = max BOOST_PREVENT_MACRO_SUBSTITUTION(next_size, num_chunks);
+ const size_type POD_size = next_size * partition_size +
+ details::pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type);
+ char * const ptr = UserAllocator::malloc(POD_size);
+ if (ptr == 0)
+ return 0;
+ const details::PODptr<size_type> node(ptr, POD_size);
+
+ // Split up block so we can use what wasn't requested
+ // (we can use "add_block" here because we know that
+ // the free list is empty, so we don't have to use
+ // the slower ordered version)
+ if (next_size > num_chunks)
+ store().add_block(node.begin() + num_chunks * partition_size,
+ node.element_size() - num_chunks * partition_size, partition_size);
+
+ next_size <<= 1;
+
+ // insert it into the list,
+ // handle border case
+ if (!list.valid() || std::greater<void *>()(list.begin(), node.begin()))
+ {
+ node.next(list);
+ list = node;
+ }
+ else
+ {
+ details::PODptr<size_type> prev = list;
+
+ while (true)
+ {
+ // if we're about to hit the end or
+ // if we've found where "node" goes
+ if (prev.next_ptr() == 0
+ || std::greater<void *>()(prev.next_ptr(), node.begin()))
+ break;
+
+ prev = prev.next();
+ }
+
+ node.next(prev.next());
+ prev.next(node);
+ }
+
+ // and return it.
+ return node.begin();
+}
+
+template <typename UserAllocator>
+details::PODptr<typename pool<UserAllocator>::size_type>
+pool<UserAllocator>::find_POD(void * const chunk) const
+{
+ // We have to find which storage this chunk is from.
+ details::PODptr<size_type> iter = list;
+ while (iter.valid())
+ {
+ if (is_from(chunk, iter.begin(), iter.element_size()))
+ return iter;
+ iter = iter.next();
+ }
+
+ return iter;
+}
+
+} // namespace boost
+
+#endif
--- /dev/null
+// Copyright (C) 2000, 2001 Stephen Cleary
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#ifndef BOOST_POOLFWD_HPP
+#define BOOST_POOLFWD_HPP
+
+#include <boost/config.hpp> // for workarounds
+
+// std::size_t
+#include <cstddef>
+
+// boost::details::pool::default_mutex
+//#include <boost/pool/detail/mutex.hpp>
+
+namespace boost {
+
+//
+// Location: <boost/pool/simple_segregated_storage.hpp>
+//
+template <typename SizeType = std::size_t>
+class simple_segregated_storage;
+
+//
+// Location: <boost/pool/pool.hpp>
+//
+struct default_user_allocator_new_delete;
+struct default_user_allocator_malloc_free;
+
+template <typename UserAllocator = default_user_allocator_new_delete>
+class pool;
+
+//
+// Location: <boost/pool/object_pool.hpp>
+//
+template <typename T, typename UserAllocator = default_user_allocator_new_delete>
+class object_pool;
+
+//
+// Location: <boost/pool/singleton_pool.hpp>
+//
+template <typename Tag, unsigned RequestedSize,
+ typename UserAllocator = default_user_allocator_new_delete,
+ unsigned NextSize = 32>
+struct singleton_pool;
+
+//
+// Location: <boost/pool/pool_alloc.hpp>
+//
+struct pool_allocator_tag;
+
+template <typename T,
+ typename UserAllocator = default_user_allocator_new_delete,
+ unsigned NextSize = 32>
+class pool_allocator;
+
+struct fast_pool_allocator_tag;
+
+template <typename T,
+ typename UserAllocator = default_user_allocator_new_delete,
+ unsigned NextSize = 32>
+class fast_pool_allocator;
+
+} // namespace boost
+
+#endif
--- /dev/null
+// Copyright (C) 2000 Stephen Cleary
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#ifndef BOOST_POOL_SINGLETON_HPP
+#define BOOST_POOL_SINGLETON_HPP
+
+// The following code might be put into some Boost.Config header in a later revision
+#ifdef __BORLANDC__
+# pragma option push -w-inl
+#endif
+
+//
+// The following helper classes are placeholders for a generic "singleton"
+// class. The classes below support usage of singletons, including use in
+// program startup/shutdown code, AS LONG AS there is only one thread
+// running before main() begins, and only one thread running after main()
+// exits.
+//
+// This class is also limited in that it can only provide singleton usage for
+// classes with default constructors.
+//
+
+// The design of this class is somewhat twisted, but can be followed by the
+// calling inheritance. Let us assume that there is some user code that
+// calls "singleton_default<T>::instance()". The following (convoluted)
+// sequence ensures that the same function will be called before main():
+// instance() contains a call to create_object.do_nothing()
+// Thus, object_creator is implicitly instantiated, and create_object
+// must exist.
+// Since create_object is a static member, its constructor must be
+// called before main().
+// The constructor contains a call to instance(), thus ensuring that
+// instance() will be called before main().
+// The first time instance() is called (i.e., before main()) is the
+// latest point in program execution where the object of type T
+// can be created.
+// Thus, any call to instance() will auto-magically result in a call to
+// instance() before main(), unless already present.
+// Furthermore, since the instance() function contains the object, instead
+// of the singleton_default class containing a static instance of the
+// object, that object is guaranteed to be constructed (at the latest) in
+// the first call to instance(). This permits calls to instance() from
+// static code, even if that code is called before the file-scope objects
+// in this file have been initialized.
+
+namespace boost {
+
+namespace details {
+namespace pool {
+
+// T must be: no-throw default constructible and no-throw destructible
+template <typename T>
+struct singleton_default
+{
+ private:
+ struct object_creator
+ {
+ // This constructor does nothing more than ensure that instance()
+ // is called before main() begins, thus creating the static
+ // T object before multithreading race issues can come up.
+ object_creator() { singleton_default<T>::instance(); }
+ inline void do_nothing() const { }
+ };
+ static object_creator create_object;
+
+ singleton_default();
+
+ public:
+ typedef T object_type;
+
+ // If, at any point (in user code), singleton_default<T>::instance()
+ // is called, then the following function is instantiated.
+ static object_type & instance()
+ {
+ // This is the object that we return a reference to.
+ // It is guaranteed to be created before main() begins because of
+ // the next line.
+ static object_type obj;
+
+ // The following line does nothing else than force the instantiation
+ // of singleton_default<T>::create_object, whose constructor is
+ // called before main() begins.
+ create_object.do_nothing();
+
+ return obj;
+ }
+};
+template <typename T>
+typename singleton_default<T>::object_creator
+singleton_default<T>::create_object;
+
+} // namespace pool
+} // namespace details
+
+} // namespace boost
+
+// The following code might be put into some Boost.Config header in a later revision
+#ifdef __BORLANDC__
+# pragma option pop
+#endif
+
+#endif
#ifndef TIME_MEM_H
#define TIME_MEM_H
-namespace MINISAT
-{
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
#ifdef _MSC_VER
#include <ctime>
{
return (double)clock() / CLOCKS_PER_SEC;
}
-#else
+#else //_MSC_VER
#ifdef CROSS_COMPILE
#include <ctime>
{
return (double)clock() / CLOCKS_PER_SEC;
}
-#else
+#else //CROSS_COMPILE
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
getrusage(RUSAGE_SELF, &ru);
return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000;
}
-#endif
-#endif
+#endif //CROSS_COMPILE
+#endif //_MSC_VER
#if defined(__linux__)
}
#endif
-};
-
#endif //TIME_MEM_H
#endif
#if defined CRYPTOMINISAT2
- newSolver.set_gaussian_decision_until(100);
- newSolver.performReplace = true;
- newSolver.xorFinder = false;
+ newSolver.findNormalXors = false;
+ newSolver.doSubsumption = false;
+ newSolver.verbosity = 0;
+ newSolver.doPartHandler = false;
#endif
// if(enable_clausal_abstraction &&