From 2248888f7686b68aea5fd0a9669320ee1108a460 Mon Sep 17 00:00:00 2001 From: msoos Date: Wed, 14 Apr 2010 18:18:39 +0000 Subject: [PATCH] Importing the new cryptominisat git-svn-id: https://stp-fast-prover.svn.sourceforge.net/svnroot/stp-fast-prover/trunk/stp@676 e59a4935-1847-0410-ae03-e826735625c1 --- src/AST/Makefile | 3 +- src/STPManager/Makefile | 2 +- src/main/Makefile | 5 +- src/main/main.cpp | 2 + src/sat/cryptominisat2/BitArray.h | 14 +- src/sat/cryptominisat2/BoundedQueue.h | 84 +- src/sat/cryptominisat2/CSet.h | 136 ++ src/sat/cryptominisat2/Clause.cpp | 3 + src/sat/cryptominisat2/Clause.h | 243 +- src/sat/cryptominisat2/ClauseCleaner.cpp | 236 +- src/sat/cryptominisat2/ClauseCleaner.h | 31 +- src/sat/cryptominisat2/Conglomerate.cpp | 378 ++- src/sat/cryptominisat2/Conglomerate.h | 62 +- src/sat/cryptominisat2/DoublePackedRow.h | 173 ++ src/sat/cryptominisat2/FailedVarSearcher.cpp | 395 ++++ src/sat/cryptominisat2/FailedVarSearcher.h | 90 + src/sat/cryptominisat2/FindUndef.cpp | 70 +- src/sat/cryptominisat2/FindUndef.h | 17 +- src/sat/cryptominisat2/Gaussian.cpp | 59 +- src/sat/cryptominisat2/Gaussian.h | 31 +- src/sat/cryptominisat2/GaussianConfig.h | 14 +- src/sat/cryptominisat2/Logger.cpp | 120 +- src/sat/cryptominisat2/Logger.h | 49 +- src/sat/cryptominisat2/Makefile | 2 +- src/sat/cryptominisat2/MatrixFinder.cpp | 38 +- src/sat/cryptominisat2/MatrixFinder.h | 21 +- src/sat/cryptominisat2/MersenneTwister.h | 427 ++++ src/sat/cryptominisat2/PackedMatrix.h | 22 +- src/sat/cryptominisat2/PackedRow.cpp | 29 +- src/sat/cryptominisat2/PackedRow.h | 71 +- src/sat/cryptominisat2/PartFinder.cpp | 185 ++ src/sat/cryptominisat2/PartFinder.h | 98 + src/sat/cryptominisat2/PartHandler.cpp | 305 +++ src/sat/cryptominisat2/PartHandler.h | 82 + src/sat/cryptominisat2/RestartTypeChooser.cpp | 87 +- src/sat/cryptominisat2/RestartTypeChooser.h | 30 +- src/sat/cryptominisat2/SmallPtr.cpp | 17 + src/sat/cryptominisat2/SmallPtr.h | 277 +++ src/sat/cryptominisat2/Solver.cpp | 1182 +++++++--- src/sat/cryptominisat2/Solver.h | 187 +- src/sat/cryptominisat2/SolverTypes.h | 18 +- src/sat/cryptominisat2/Subsumer.cpp | 2033 +++++++++++++++++ src/sat/cryptominisat2/Subsumer.h | 249 ++ src/sat/cryptominisat2/VERSION | 3 +- src/sat/cryptominisat2/VarReplacer.cpp | 365 +-- src/sat/cryptominisat2/VarReplacer.h | 112 +- src/sat/cryptominisat2/XSet.h | 136 ++ src/sat/cryptominisat2/XorFinder.cpp | 161 +- src/sat/cryptominisat2/XorFinder.h | 43 +- src/sat/cryptominisat2/XorSubsumer.cpp | 306 +++ src/sat/cryptominisat2/XorSubsumer.h | 95 + src/sat/cryptominisat2/constants.h | 16 +- src/sat/cryptominisat2/msvc/stdint.h | 250 ++ src/sat/cryptominisat2/mtl/Alg.h | 15 +- src/sat/cryptominisat2/mtl/BasicHeap.h | 11 +- src/sat/cryptominisat2/mtl/BoxedVec.h | 3 +- src/sat/cryptominisat2/mtl/Heap.h | 42 +- src/sat/cryptominisat2/mtl/Map.h | 8 +- src/sat/cryptominisat2/mtl/Queue.h | 6 +- src/sat/cryptominisat2/mtl/Vec.h | 25 +- src/sat/cryptominisat2/pool.hpp | 584 +++++ src/sat/cryptominisat2/poolfwd.hpp | 70 + src/sat/cryptominisat2/singleton.hpp | 107 + src/sat/cryptominisat2/time_mem.h | 17 +- src/to-sat/ToSAT.cpp | 7 +- 65 files changed, 8805 insertions(+), 1154 deletions(-) create mode 100644 src/sat/cryptominisat2/CSet.h create mode 100644 src/sat/cryptominisat2/Clause.cpp create mode 100644 src/sat/cryptominisat2/DoublePackedRow.h create mode 100644 src/sat/cryptominisat2/FailedVarSearcher.cpp create mode 100644 src/sat/cryptominisat2/FailedVarSearcher.h create mode 100644 src/sat/cryptominisat2/MersenneTwister.h create mode 100644 src/sat/cryptominisat2/PartFinder.cpp create mode 100644 src/sat/cryptominisat2/PartFinder.h create mode 100644 src/sat/cryptominisat2/PartHandler.cpp create mode 100644 src/sat/cryptominisat2/PartHandler.h create mode 100644 src/sat/cryptominisat2/SmallPtr.cpp create mode 100644 src/sat/cryptominisat2/SmallPtr.h create mode 100644 src/sat/cryptominisat2/Subsumer.cpp create mode 100644 src/sat/cryptominisat2/Subsumer.h create mode 100644 src/sat/cryptominisat2/XSet.h create mode 100644 src/sat/cryptominisat2/XorSubsumer.cpp create mode 100644 src/sat/cryptominisat2/XorSubsumer.h create mode 100644 src/sat/cryptominisat2/msvc/stdint.h create mode 100644 src/sat/cryptominisat2/pool.hpp create mode 100644 src/sat/cryptominisat2/poolfwd.hpp create mode 100644 src/sat/cryptominisat2/singleton.hpp diff --git a/src/AST/Makefile b/src/AST/Makefile index 29d485f..c801df6 100644 --- a/src/AST/Makefile +++ b/src/AST/Makefile @@ -5,7 +5,8 @@ SRCS=$(wildcard *.cpp) 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 diff --git a/src/STPManager/Makefile b/src/STPManager/Makefile index d60996a..06abd42 100644 --- a/src/STPManager/Makefile +++ b/src/STPManager/Makefile @@ -16,4 +16,4 @@ clean: depend: $(SRCS) @$(CXX) -MM $(CXXFLAGS) $(SRCS) > $@ -#-include depend \ No newline at end of file +#-include depend diff --git a/src/main/Makefile b/src/main/Makefile index ca818f1..83496cc 100644 --- a/src/main/Makefile +++ b/src/main/Makefile @@ -3,6 +3,7 @@ include $(TOP)/scripts/Makefile.common 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 \ @@ -17,7 +18,7 @@ LIBS = -L../to-sat -ltosat \ # 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 @@ -40,4 +41,4 @@ depend: $(SRCS) -#-include depend \ No newline at end of file +#-include depend diff --git a/src/main/main.cpp b/src/main/main.cpp index bc12946..afae20b 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -14,6 +14,8 @@ #include "../AST/NodeFactory/TypeChecker.h" #include "../AST/NodeFactory/SimplifyingNodeFactory.h" #include "../parser/ParserInterface.h" +#include + #ifdef EXT_HASH_MAP using namespace __gnu_cxx; diff --git a/src/sat/cryptominisat2/BitArray.h b/src/sat/cryptominisat2/BitArray.h index 74b3b8e..7edc6db 100644 --- a/src/sat/cryptominisat2/BitArray.h +++ b/src/sat/cryptominisat2/BitArray.h @@ -20,13 +20,17 @@ along with this program. If not, see . //#define DEBUG_BITARRAY -#include #include #include +#ifdef _MSC_VER +#include +#else +#include +#endif //_MSC_VER -#ifndef uint -#define uint unsigned int -#endif +namespace MINISAT +{ +using namespace MINISAT; class BitArray { @@ -124,5 +128,7 @@ private: uint64_t* mp; }; +}; //NAMESPACE MINISAT + #endif //BITARRAY_H diff --git a/src/sat/cryptominisat2/BoundedQueue.h b/src/sat/cryptominisat2/BoundedQueue.h index c4115fd..a705a6d 100644 --- a/src/sat/cryptominisat2/BoundedQueue.h +++ b/src/sat/cryptominisat2/BoundedQueue.h @@ -21,62 +21,68 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef BoundedQueue_h #define BoundedQueue_h -#include "../mtl/Vec.h" +#ifdef _MSC_VER +#include +#else +#include +#endif //_MSC_VER + +#include "Vec.h" //================================================================================================= namespace MINISAT { +using namespace MINISAT; template class bqueue { vec 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;i0); 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 +#ifdef _MSC_VER +#include +#else +#include +#endif //_MSC_VER + +namespace MINISAT +{ +using namespace MINISAT; + +class Clause; + +template +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 where; // Map clause ID to position in 'which'. + vec which; // List of clauses (for fast iteration). May contain 'Clause_NULL'. + vec 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::max()); + if (where[c.index] != std::numeric_limits::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::max()) { + //not inside + return false; + } + free.push(where[c.index]); + which[where[c.index]].clause = NULL; + where[c.index] = std::numeric_limits::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::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 diff --git a/src/sat/cryptominisat2/Clause.cpp b/src/sat/cryptominisat2/Clause.cpp new file mode 100644 index 0000000..b2bc8bc --- /dev/null +++ b/src/sat/cryptominisat2/Clause.cpp @@ -0,0 +1,3 @@ +#include "Clause.h" + +//boost::pool<> binaryClausePool(sizeof(Clause)+2*sizeof(Lit)); diff --git a/src/sat/cryptominisat2/Clause.h b/src/sat/cryptominisat2/Clause.h index 6983b96..730b62c 100644 --- a/src/sat/cryptominisat2/Clause.h +++ b/src/sat/cryptominisat2/Clause.h @@ -21,23 +21,28 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef CLAUSE_H #define CLAUSE_H +#ifdef _MSC_VER +#include +#else #include +#endif //_MSC_VER #include #include #include -#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: @@ -46,59 +51,109 @@ class MatrixFinder; 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 - 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 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) { @@ -116,19 +171,33 @@ public: 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 { @@ -137,8 +206,14 @@ public: 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 { @@ -148,41 +223,69 @@ public: } 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 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 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(); } @@ -197,18 +300,18 @@ public: } 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 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; } @@ -221,6 +324,13 @@ XorClause* XorClause_new(const T& ps, const bool inverted, const uint group) return real; } +inline void clauseFree(Clause* c) +{ + //if (binaryClausePool.is_from(c)) binaryClausePool.free(c); + //else + free(c); +} + /*_________________________________________________________________________________________________ | | subsumes : (other : const Clause&) -> Lit @@ -234,7 +344,7 @@ XorClause* XorClause_new(const T& ps, const bool inverted, const uint group) | 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; @@ -259,23 +369,30 @@ inline Lit Clause::subsumes(const Clause& other) const } return ret; -} +}*/ +//typedef sptr ClausePtr; +//typedef sptr 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 diff --git a/src/sat/cryptominisat2/ClauseCleaner.cpp b/src/sat/cryptominisat2/ClauseCleaner.cpp index 1a9abcc..b7d34f2 100644 --- a/src/sat/cryptominisat2/ClauseCleaner.cpp +++ b/src/sat/cryptominisat2/ClauseCleaner.cpp @@ -16,17 +16,22 @@ along with this program. If not, see . **************************************************************************************************/ #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(); } @@ -62,18 +67,52 @@ void ClauseCleaner::removeSatisfied(vec& cs, ClauseSetType type, const 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& 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]; @@ -84,9 +123,10 @@ inline const bool ClauseCleaner::cleanClause(Clause& c) 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; @@ -96,8 +136,10 @@ inline const bool ClauseCleaner::cleanClause(Clause& c) 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; @@ -108,19 +150,20 @@ inline const bool ClauseCleaner::cleanClause(Clause& c) return false; } -void ClauseCleaner::cleanClauses(vec& cs, ClauseSetType type, const uint limit) +void ClauseCleaner::cleanClauses(vec& 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++; @@ -131,44 +174,144 @@ void ClauseCleaner::cleanClauses(vec& cs, ClauseSetType type, const uin 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& 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 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& 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 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& 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 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()) { @@ -178,23 +321,30 @@ inline const bool ClauseCleaner::cleanClause(XorClause& c) } 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 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 @@ -216,4 +366,4 @@ bool ClauseCleaner::satisfied(const XorClause& c) const return final; } -}; +}; //NAMESPACE MINISAT diff --git a/src/sat/cryptominisat2/ClauseCleaner.h b/src/sat/cryptominisat2/ClauseCleaner.h index de05c74..c099ae2 100644 --- a/src/sat/cryptominisat2/ClauseCleaner.h +++ b/src/sat/cryptominisat2/ClauseCleaner.h @@ -18,45 +18,62 @@ along with this program. If not, see . #ifndef CLAUSECLEANER_H #define CLAUSECLEANER_H +#ifdef _MSC_VER +#include +#else +#include +#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& cs, ClauseSetType type, const uint limit = 0); + void cleanClausesBewareNULL(vec& cs, ClauseSetType type, Subsumer& subs, const uint limit = 0); + void cleanXorClausesBewareNULL(vec& 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& cs, ClauseSetType type, const uint limit = 0); void removeSatisfied(vec& cs, ClauseSetType type, const uint limit = 0); void removeSatisfied(vec& 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 diff --git a/src/sat/cryptominisat2/Conglomerate.cpp b/src/sat/cryptominisat2/Conglomerate.cpp index 49c12cd..43caf21 100644 --- a/src/sat/cryptominisat2/Conglomerate.cpp +++ b/src/sat/cryptominisat2/Conglomerate.cpp @@ -16,12 +16,14 @@ along with this program. If not, see . **************************************************************************************************/ #include "Conglomerate.h" -#include "Solver.h" #include "VarReplacer.h" #include "ClauseCleaner.h" #include #include +#include +#include "time_mem.h" +#include using std::make_pair; //#define VERBOSE_DEBUG @@ -32,13 +34,13 @@ using std::cout; 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() @@ -47,47 +49,39 @@ Conglomerate::~Conglomerate() free(calcAtFinish[i]); } -const vector& Conglomerate::getRemovedVars() const -{ - return removedVars; -} - -const vec& Conglomerate::getCalcAtFinish() const -{ - return calcAtFinish; -} - -vec& 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& clauses = S->varReplacer->getClauses(); + const vec& 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()]) @@ -96,42 +90,172 @@ void Conglomerate::fillVarToXor() } } -void Conglomerate::process_clause(XorClause& x, const uint num, Var remove_var, vec& 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 >::iterator it = - std::find(finder->second.begin(), finder->second.end(), make_pair(&x, num)); + vector >::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 >& newSet, vector >& 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 > newSet; + while(varToXor.begin() != varToXor.end()) { + varToXorMap::iterator it = varToXor.begin(); + vector >& 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 > newSet; while(varToXor.begin() != varToXor.end()) { varToXorMap::iterator it = varToXor.begin(); - const vector >& c = it->second; - const uint& var = it->first; + vector >& 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]) { @@ -139,73 +263,68 @@ uint Conglomerate::conglomerateXors() 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 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 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& ps, const bool inverted, const uint old_group) +bool Conglomerate::dealWithNewClause(vector& ps, const bool inverted, const uint old_group) { switch(ps.size()) { case 0: { @@ -213,8 +332,10 @@ bool Conglomerate::dealWithNewClause(vec& ps, const bool inverted, const ui cout << "--> xor is 0-long" << endl; #endif - if (!inverted) + if (!inverted) { + solver.ok = false; return false; + } break; } case 1: { @@ -222,28 +343,37 @@ bool Conglomerate::dealWithNewClause(vec& ps, const bool inverted, const ui 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 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; @@ -257,12 +387,12 @@ bool Conglomerate::dealWithNewClause(vec& ps, const bool inverted, const ui 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; } @@ -271,51 +401,49 @@ bool Conglomerate::dealWithNewClause(vec& ps, const bool inverted, const ui return true; } -void Conglomerate::clearDouble(vec& ps) const -{ - std::sort(ps.getData(), ps.getData() + ps.size()); +void Conglomerate::clearDouble(vector& 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; @@ -326,11 +454,11 @@ void Conglomerate::clearLearntsFromToRemove() 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() @@ -352,7 +480,7 @@ 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 @@ -362,7 +490,7 @@ void Conglomerate::doCalcAtFinish() 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) { @@ -375,14 +503,14 @@ void Conglomerate::doCalcAtFinish() 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; @@ -403,16 +531,22 @@ void Conglomerate::addRemovedClauses() 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() @@ -420,4 +554,4 @@ void Conglomerate::newVar() removedVars.resize(removedVars.size()+1, false); } -}; +}; //NAMESPACE MINISAT diff --git a/src/sat/cryptominisat2/Conglomerate.h b/src/sat/cryptominisat2/Conglomerate.h index 6fe7556..15fcb0b 100644 --- a/src/sat/cryptominisat2/Conglomerate.h +++ b/src/sat/cryptominisat2/Conglomerate.h @@ -21,52 +21,92 @@ along with this program. If not, see . #include #include #include +#ifdef _MSC_VER +#include +#else +#include +#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(); ///& getCalcAtFinish() const; vec& getCalcAtFinish(); const vector& getRemovedVars() const; + void newVar(); private: - void process_clause(XorClause& x, const uint num, Var remove_var, vec& vars); + struct ClauseSetSorter { + bool operator () (const pair& a, const pair& b) { + return a.first->size() < b.first->size(); + } + }; + + const bool conglomerateXors(); + const bool heuleProcess(); + + void fillNewSet(vector >& newSet, vector >& clauseSet) const; + + void removeVar(const Var var); + void processClause(XorClause& x, uint32_t num, Var remove_var); + void blockVars(); void fillVarToXor(); - void clearDouble(vec& ps) const; + void clearDouble(vector& ps) const; void clearToRemove(); void clearLearntsFromToRemove(); - bool dealWithNewClause(vec& ps, const bool inverted, const uint old_group); + bool dealWithNewClause(vector& ps, const bool inverted, const uint old_group); - typedef map > > varToXorMap; + typedef map > > varToXorMap; varToXorMap varToXor; vector blocked; vector toRemove; vector removedVars; vec calcAtFinish; + uint found; - Solver* S; -}; + Solver& solver; }; +inline const vector& Conglomerate::getRemovedVars() const +{ + return removedVars; +} + +inline const vec& Conglomerate::getCalcAtFinish() const +{ + return calcAtFinish; +} + +inline vec& Conglomerate::getCalcAtFinish() +{ + return calcAtFinish; +} + +}; //NAMESPACE MINISAT + #endif //CONGLOMERATE_H diff --git a/src/sat/cryptominisat2/DoublePackedRow.h b/src/sat/cryptominisat2/DoublePackedRow.h new file mode 100644 index 0000000..50cfd8a --- /dev/null +++ b/src/sat/cryptominisat2/DoublePackedRow.h @@ -0,0 +1,173 @@ +/*********************************************************************************** +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 . +**************************************************************************************************/ + +#ifndef DOUBLEPACKEDROW_H +#define DOUBLEPACKEDROW_H + +#ifdef _MSC_VER +#include +#else +#include +#endif //_MSC_VER + +#include + +#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 diff --git a/src/sat/cryptominisat2/FailedVarSearcher.cpp b/src/sat/cryptominisat2/FailedVarSearcher.cpp new file mode 100644 index 0000000..7699b69 --- /dev/null +++ b/src/sat/cryptominisat2/FailedVarSearcher.cpp @@ -0,0 +1,395 @@ +/*********************************************************************************** +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 . +**************************************************************************************************/ + +#include "FailedVarSearcher.h" + +#include +#include +#include +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& 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& 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 backup_order_heap(solver.order_heap); + vector backup_polarities = solver.polarity; + vec 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 > bothSame; + + //For 2-long xor (rule 6 of Equivalent literal propagation in the DLL procedure by Chu-Min Li) + set 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 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 +inline void FailedVarSearcher::cleanAndAttachClauses(vec& 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 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 diff --git a/src/sat/cryptominisat2/FailedVarSearcher.h b/src/sat/cryptominisat2/FailedVarSearcher.h new file mode 100644 index 0000000..79ed82e --- /dev/null +++ b/src/sat/cryptominisat2/FailedVarSearcher.h @@ -0,0 +1,90 @@ +/*********************************************************************************** +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 . +**************************************************************************************************/ + +#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& cs); + + template + void cleanAndAttachClauses(vec& cs); + const bool cleanClause(Clause& ps); + const bool cleanClause(XorClause& ps); + + Solver& solver; + + vec xorClauseSizes; + vector > occur; + void removeVarFromXors(const Var var); + void addVarFromXors(const Var var); + BitArray xorClauseTouched; + vec investigateXor; + + bool finishedLastTime; + uint32_t lastTimeWentUntil; + double numPropsMultiplier; + uint32_t lastTimeFoundTruths; +}; + +}; //NAMESPACE MINISAT + +#endif //FAILEDVARSEARCHER_H \ No newline at end of file diff --git a/src/sat/cryptominisat2/FindUndef.cpp b/src/sat/cryptominisat2/FindUndef.cpp index 8710ee3..4e35dc1 100644 --- a/src/sat/cryptominisat2/FindUndef.cpp +++ b/src/sat/cryptominisat2/FindUndef.cpp @@ -18,49 +18,49 @@ along with this program. If not, see . #include "FindUndef.h" #include "Solver.h" +#include "VarReplacer.h" #include 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 replacingVars = S.varReplacer->getReplacingVars(); + vector replacingVars = solver.varReplacer->getReplacingVars(); for (Var *it = &replacingVars[0], *end = it + replacingVars.size(); it != end; it++) { if (isPotential[*it]) { isPotential[*it] = false; @@ -73,11 +73,35 @@ void FindUndef::unboundIsPotentials() { 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); @@ -97,6 +121,7 @@ const uint FindUndef::unRoll() } unboundIsPotentials(); + moveBinFromNormal(); return isPotentialSum; } @@ -106,16 +131,16 @@ bool FindUndef::updateTables() 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; @@ -130,19 +155,22 @@ bool FindUndef::updateTables() 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 diff --git a/src/sat/cryptominisat2/FindUndef.h b/src/sat/cryptominisat2/FindUndef.h index 59835c2..d3612ac 100644 --- a/src/sat/cryptominisat2/FindUndef.h +++ b/src/sat/cryptominisat2/FindUndef.h @@ -18,6 +18,11 @@ along with this program. If not, see . #ifndef FINDUNDEF_H #define FINDUNDEF_H +#ifdef _MSC_VER +#include +#else +#include +#endif //_MSC_VER #include using std::vector; @@ -25,15 +30,18 @@ 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(); @@ -42,9 +50,10 @@ class FindUndef { vector satisfies; vector isPotential; uint32_t isPotentialSum; + uint32_t binPosition; }; -}; -#endif // +}; //NAMESPACE MINISAT +#endif // \ No newline at end of file diff --git a/src/sat/cryptominisat2/Gaussian.cpp b/src/sat/cryptominisat2/Gaussian.cpp index 3a64273..2b1938f 100644 --- a/src/sat/cryptominisat2/Gaussian.cpp +++ b/src/sat/cryptominisat2/Gaussian.cpp @@ -62,7 +62,7 @@ Gaussian::Gaussian(Solver& _solver, const GaussianConfig& _config, const uint _m 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() @@ -85,6 +85,8 @@ llbool Gaussian::full_init() 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); @@ -133,16 +135,11 @@ uint Gaussian::select_columnorder(vector& var_to_col, matrixset& origM 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; } } @@ -223,11 +220,9 @@ void Gaussian::fill_matrix(matrixset& origMat) 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); } @@ -552,11 +547,11 @@ Gaussian::gaussian_ret Gaussian::handle_matrix_confl(Clause*& confl, const matri 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) @@ -571,7 +566,7 @@ Gaussian::gaussian_ret Gaussian::handle_matrix_confl(Clause*& confl, const matri 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); } @@ -668,7 +663,7 @@ void Gaussian::cancel_until_sublevel(const uint sublevel) 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::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--) { @@ -764,7 +759,7 @@ Gaussian::gaussian_ret Gaussian::handle_matrix_prop(matrixset& m, const uint row #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(); @@ -785,7 +780,7 @@ Gaussian::gaussian_ret Gaussian::handle_matrix_prop(matrixset& m, const uint row 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); @@ -796,9 +791,9 @@ void Gaussian::disable_if_necessary() { 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; } @@ -814,8 +809,8 @@ llbool Gaussian::find_truths(vec& learnt_clause, int& conflictC) 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; @@ -834,19 +829,19 @@ llbool Gaussian::find_truths(vec& learnt_clause, int& conflictC) 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: @@ -990,7 +985,7 @@ const bool Gaussian::check_last_one_in_cols(matrixset& m) const 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); @@ -1164,4 +1159,4 @@ void Gaussian::set_disabled(const bool toset) #endif }*/ -}; +}; //NAMESPACE MINISAT diff --git a/src/sat/cryptominisat2/Gaussian.h b/src/sat/cryptominisat2/Gaussian.h index 242a156..5fb66aa 100644 --- a/src/sat/cryptominisat2/Gaussian.h +++ b/src/sat/cryptominisat2/Gaussian.h @@ -19,16 +19,19 @@ along with this program. If not, see . #define GAUSSIAN_H #include +#include +#ifdef _MSC_VER +#include +#else +#include +#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 @@ -38,10 +41,14 @@ using std::cout; 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::max(); +static const Var unassigned_var = std::numeric_limits::max(); class Gaussian { @@ -155,7 +162,7 @@ private: void print_matrix_row(const T& row) const; // Print matrix row 'row' template 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; @@ -165,13 +172,12 @@ private: 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); } @@ -181,7 +187,7 @@ inline void Gaussian::canceling(const uint sublevel) 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); @@ -189,7 +195,7 @@ inline void Gaussian::canceling(const uint sublevel) 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] @@ -201,6 +207,7 @@ inline void Gaussian::canceling(const uint sublevel) } std::ostream& operator << (std::ostream& os, const vec& v); -}; + +}; //NAMESPACE MINISAT #endif //GAUSSIAN_H diff --git a/src/sat/cryptominisat2/GaussianConfig.h b/src/sat/cryptominisat2/GaussianConfig.h index 595dff4..f98ec17 100644 --- a/src/sat/cryptominisat2/GaussianConfig.h +++ b/src/sat/cryptominisat2/GaussianConfig.h @@ -18,7 +18,12 @@ along with this program. If not, see . #ifndef GAUSSIANCONFIG_H #define GAUSSIANCONFIG_H -#include +#ifdef _MSC_VER +#include +#else +#include +#endif //_MSC_VER + #include "PackedRow.h" namespace MINISAT @@ -32,15 +37,16 @@ class GaussianConfig 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 diff --git a/src/sat/cryptominisat2/Logger.cpp b/src/sat/cryptominisat2/Logger.cpp index a74f12c..9677b5c 100644 --- a/src/sat/cryptominisat2/Logger.cpp +++ b/src/sat/cryptominisat2/Logger.cpp @@ -25,6 +25,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #include #include +#include using std::cout; using std::endl; using std::ofstream; @@ -34,13 +35,14 @@ 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) @@ -83,6 +85,7 @@ void Logger::new_var(const Var var) 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); } } @@ -94,6 +97,7 @@ void Logger::new_group(const uint group) 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); } } @@ -227,18 +231,17 @@ void Logger::conflict(const confl_type type, const uint goback_level, const uint 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::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()]++; } } @@ -259,10 +262,10 @@ void Logger::propagation(const Lit lit, Clause* c) type = add_clause_type; else type = guess_type; - group = UINT_MAX; + group = std::numeric_limits::max(); } else { type = simple_propagation_type; - group = c->group; + group = c->getGroup(); } //graph @@ -298,18 +301,23 @@ void Logger::propagation(const Lit lit, Clause* c) 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; } } @@ -362,16 +370,10 @@ void Logger::print_assign_var_order() const { vector > prop_ordered; for (uint i = 0; i < depths_of_assigns_for_var.size(); i++) { - double avg = 0.0; - bool was_unit = false; - for (vector::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()) { @@ -388,16 +390,10 @@ void Logger::print_prop_order() const { vector > prop_ordered; for (uint i = 0; i < depths_of_propagations_for_group.size(); i++) { - double avg = 0.0; - bool was_unit = false; - for (vector::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()) { @@ -414,13 +410,10 @@ void Logger::print_confl_order() const { vector > confl_ordered; for (uint i = 0; i < depths_of_conflicts_for_group.size(); i++) { - double avg = 0.0; - for (vector::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()) { @@ -556,11 +549,10 @@ void Logger::print_branch_depth_distrib() const const uint range = 20; map range_stat; - for (map::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::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"); @@ -571,9 +563,9 @@ void Logger::print_branch_depth_distrib() const 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::iterator it = range_stat.begin(); it != range_stat.end(); it++) { + for (map::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); @@ -586,7 +578,6 @@ void Logger::print_branch_depth_distrib() const branch_depth_file << "\"\""; branch_depth_file << endl; } - i++; } if (branch_depth_file.is_open()) branch_depth_file.close(); @@ -713,11 +704,15 @@ void Logger::print_learnt_unitaries(const uint from, const string display) const 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(); } @@ -850,16 +845,27 @@ void Logger::reset_statistics() for (vecit it = props_by_group.begin(); it != props_by_group.end(); it++) *it = 0; - typedef vector >::iterator vecvecit; + typedef vector::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; @@ -871,4 +877,4 @@ void Logger::reset_statistics() last_unitary_learnt_clauses = S->get_unitary_learnts_num(); } -}; +}; //NAMESPACE MINISAT diff --git a/src/sat/cryptominisat2/Logger.h b/src/sat/cryptominisat2/Logger.h index f0dca86..3e87fab 100644 --- a/src/sat/cryptominisat2/Logger.h +++ b/src/sat/cryptominisat2/Logger.h @@ -25,29 +25,41 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #include #include - -#include "mtl/Vec.h" -#include "mtl/Heap.h" -#include "mtl/Alg.h" +#ifdef _MSC_VER +#include +#else +#include +#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: @@ -143,12 +155,14 @@ private: vector times_group_caused_conflict; vector times_group_caused_propagation; - vector > depths_of_propagations_for_group; - vector > depths_of_conflicts_for_group; - vector > depths_of_assigns_for_var; + vector depths_of_propagations_for_group; + vector depths_of_propagations_unit; + vector depths_of_conflicts_for_group; + vector depths_of_assigns_for_var; + vector depths_of_assigns_unit; //the distribution of branch depths. first = depth, second = number of occurances - map branch_depth_distrib; + vector branch_depth_distrib; uint sum_conflict_depths; uint no_conflicts; @@ -168,5 +182,6 @@ private: uint proofStarts; }; -}; +}; //NAMESPACE MINISAT + #endif //LOGGER_H diff --git a/src/sat/cryptominisat2/Makefile b/src/sat/cryptominisat2/Makefile index 954e0e7..8315c29 100644 --- a/src/sat/cryptominisat2/Makefile +++ b/src/sat/cryptominisat2/Makefile @@ -3,7 +3,7 @@ include $(TOP)/scripts/Makefile.common 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 diff --git a/src/sat/cryptominisat2/MatrixFinder.cpp b/src/sat/cryptominisat2/MatrixFinder.cpp index b196a55..1f08a2c 100644 --- a/src/sat/cryptominisat2/MatrixFinder.cpp +++ b/src/sat/cryptominisat2/MatrixFinder.cpp @@ -26,9 +26,6 @@ along with this program. If not, see . #include #include #include -namespace MINISAT -{ - using std::set; using std::map; @@ -37,11 +34,14 @@ 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) { } @@ -73,20 +73,21 @@ inline const bool MatrixFinder::firstPartOfSecond(const XorClause& c1, const Xor 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 tomerge; vector 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()); @@ -138,7 +139,7 @@ const uint MatrixFinder::setMatrixes() vector > 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); @@ -174,23 +175,23 @@ const uint MatrixFinder::setMatrixes() 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; @@ -219,4 +220,5 @@ void MatrixFinder::findParts(vector& xorFingerprintInMatrix, vector. #ifndef MATRIXFINDER_H #define MATRIXFINDER_H -#include -#include "Clause.h" #include #include +#ifdef _MSC_VER +#include +#else +#include +#endif //_MSC_VER + +#include "Clause.h" +#include "Solver.h" namespace MINISAT { +using namespace MINISAT; class Solver; @@ -35,7 +42,7 @@ using std::pair; class MatrixFinder { public: - MatrixFinder(Solver* S); + MatrixFinder(Solver& solver); const uint findMatrixes(); private: @@ -54,12 +61,12 @@ class MatrixFinder { inline const bool firstPartOfSecond(const XorClause& c1, const XorClause& c2) const; map > reverseTable; //matrix -> vars - vector table; //var -> matrix + vector table; //var -> matrix uint matrix_no; - const uint unAssigned; - Solver* S; -}; + Solver& solver; }; +}; //NAMESPACE MINISAT + #endif //MATRIXFINDER_H diff --git a/src/sat/cryptominisat2/MersenneTwister.h b/src/sat/cryptominisat2/MersenneTwister.h new file mode 100644 index 0000000..964ecc7 --- /dev/null +++ b/src/sat/cryptominisat2/MersenneTwister.h @@ -0,0 +1,427 @@ +// 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 +#include +#include +#include +#include + +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 diff --git a/src/sat/cryptominisat2/PackedMatrix.h b/src/sat/cryptominisat2/PackedMatrix.h index 0edf1e0..9c7f117 100644 --- a/src/sat/cryptominisat2/PackedMatrix.h +++ b/src/sat/cryptominisat2/PackedMatrix.h @@ -18,25 +18,28 @@ along with this program. If not, see . #ifndef PACKEDMATRIX_H #define PACKEDMATRIX_H -#include "PackedRow.h" #include +#ifdef _MSC_VER +#include +#else +#include +#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) { } @@ -210,11 +213,12 @@ public: private: + uint64_t* mp; uint numRows; uint numCols; - uint64_t* mp; -}; }; +}; //NAMESPACE MINISAT + #endif //PACKEDMATRIX_H diff --git a/src/sat/cryptominisat2/PackedRow.cpp b/src/sat/cryptominisat2/PackedRow.cpp index e9356eb..59a4e43 100644 --- a/src/sat/cryptominisat2/PackedRow.cpp +++ b/src/sat/cryptominisat2/PackedRow.cpp @@ -16,12 +16,14 @@ along with this program. If not, see . **************************************************************************************************/ #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(); @@ -50,10 +52,10 @@ bool PackedRow::operator !=(const PackedRow& b) const 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); @@ -63,12 +65,12 @@ uint PackedRow::popcnt() const 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; @@ -87,12 +89,12 @@ void PackedRow::fill(vec& tmp_clause, const vec& assigns, const vect 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::max()); const lbool& val = assigns[var]; const bool val_bool = val.getBool(); @@ -114,4 +116,5 @@ void PackedRow::fill(vec& tmp_clause, const vec& assigns, const vect } else assert(!final); } -}; + +}; //NAMESPACE MINISAT diff --git a/src/sat/cryptominisat2/PackedRow.h b/src/sat/cryptominisat2/PackedRow.h index 4c2d67d..e59ff9b 100644 --- a/src/sat/cryptominisat2/PackedRow.h +++ b/src/sat/cryptominisat2/PackedRow.h @@ -21,21 +21,27 @@ along with this program. If not, see . //#define DEBUG_ROW #include -#include +#ifdef _MSC_VER +#include +#else +#include +#endif //_MSC_VER + #include "SolverTypes.h" -#include "mtl/Vec.h" +#include "Vec.h" #include #include #include - +#include #ifndef uint #define uint unsigned int #endif +using std::vector; + namespace MINISAT { - -using std::vector; +using namespace MINISAT; class PackedMatrix; @@ -66,7 +72,7 @@ public: 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); } @@ -82,7 +88,7 @@ public: 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); } @@ -90,13 +96,13 @@ public: } - 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; @@ -106,7 +112,7 @@ public: return popcount == 1; } - bool popcnt_is_one(uint from) const + bool popcnt_is_one(uint32_t from) const { from++; @@ -114,7 +120,7 @@ public: 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; } @@ -126,7 +132,7 @@ public: 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; @@ -137,17 +143,17 @@ public: 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)); } @@ -163,7 +169,7 @@ public: 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); @@ -173,7 +179,7 @@ public: } } - inline const bool operator[](const uint& i) const + inline const bool operator[](const uint32_t& i) const { #ifdef DEBUG_ROW assert(size*64 > i); @@ -183,14 +189,14 @@ public: } template - void set(const T& v, const vector& var_to_col, const uint matrix_size) + void set(const T& v, const vector& 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::max()); setBit(toset_var); } @@ -206,28 +212,29 @@ public: 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::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 diff --git a/src/sat/cryptominisat2/PartFinder.cpp b/src/sat/cryptominisat2/PartFinder.cpp new file mode 100644 index 0000000..5ab39cd --- /dev/null +++ b/src/sat/cryptominisat2/PartFinder.cpp @@ -0,0 +1,185 @@ +/*********************************************************************************** +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 . +**************************************************************************************************/ + +#include "PartFinder.h" + +#include "Solver.h" +#include "Gaussian.h" +#include "GaussianConfig.h" +#include "ClauseCleaner.h" +#include "time_mem.h" +#include "VarReplacer.h" + +#include +#include +#include +#include +#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::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 >::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 +void PartFinder::addToPart(const vec& cs) +{ + set tomerge; + vector 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::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 >::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::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 numClauseInPart(part_no, 0); + vector 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 >::iterator it = reverseTable.begin(), end = reverseTable.end(); it != end; it++) { + cout << "-- set begin --" << endl; + for (vector::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) { + cout << *it2 << ", "; + } + cout << "-------" << endl; + } + #endif + } + + return parts; +} + +template +void PartFinder::calcIn(const vec& cs, vector& numClauseInPart, vector& 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 diff --git a/src/sat/cryptominisat2/PartFinder.h b/src/sat/cryptominisat2/PartFinder.h new file mode 100644 index 0000000..a3261d7 --- /dev/null +++ b/src/sat/cryptominisat2/PartFinder.h @@ -0,0 +1,98 @@ +/*********************************************************************************** +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 . +**************************************************************************************************/ + +#ifndef PARTFINDER_H +#define PARTFINDER_H + +#include +#include +#ifdef _MSC_VER +#include +#else +#include +#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 >& getReverseTable() const; // part->var + const uint32_t getVarPart(const Var var) const; + const vector& getTable() const; //var -> part + const vector& getPartVars(const uint32_t part); + + private: + const uint setParts(); + template + void addToPart(const vec& cs); + + struct mysorter + { + bool operator () (const pair& left, const pair& right) + { + return left.second < right.second; + } + }; + + //const bool findParts(vector& xorFingerprintInMatrix, vector& xorsInMatrix); + template + void calcIn(const vec& cs, vector& numClauseInPart, vector& sumLitsInPart); + + map > reverseTable; //part -> vars + vector table; //var -> part + uint32_t part_no; + + Solver& solver; +}; + +inline const map >& PartFinder::getReverseTable() const +{ + return reverseTable; +} + +inline const vector& PartFinder::getTable() const +{ + return table; +} + +inline const uint32_t PartFinder::getVarPart(const Var var) const +{ + return table[var]; +} + +inline const vector& PartFinder::getPartVars(const uint32_t part) +{ + return reverseTable[part]; +} + +}; //NAMESPACE MINISAT + +#endif //PARTFINDER_H diff --git a/src/sat/cryptominisat2/PartHandler.cpp b/src/sat/cryptominisat2/PartHandler.cpp new file mode 100644 index 0000000..8fb9771 --- /dev/null +++ b/src/sat/cryptominisat2/PartHandler.cpp @@ -0,0 +1,305 @@ +/*********************************************************************************** +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 . +**************************************************************************************************/ + +#include "PartHandler.h" +#include "VarReplacer.h" +#include +#include + +//#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 > reverseTable = partFinder.getReverseTable(); + assert(num_parts == partFinder.getReverseTable().size()); + + vector > sizes; + for (map >::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 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 +const bool PartHandler::checkOnlyThisPart(const vec& 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& 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 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& 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 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& 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 diff --git a/src/sat/cryptominisat2/PartHandler.h b/src/sat/cryptominisat2/PartHandler.h new file mode 100644 index 0000000..a1fe6c1 --- /dev/null +++ b/src/sat/cryptominisat2/PartHandler.h @@ -0,0 +1,82 @@ +/*********************************************************************************** +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 . +**************************************************************************************************/ + +#ifndef PARTHANDLER_H +#define PARTHANDLER_H + +#include "Solver.h" +#include "PartFinder.h" +#include "Vec.h" +#include "SolverTypes.h" + +#include +#include +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& getSavedState(); + void newVar(); + void addSavedState(); + void readdRemovedClauses(); + + private: + struct sort_pred { + bool operator()(const std::pair &left, const std::pair &right) { + return left.second < right.second; + } + }; + + //For moving clauses + void moveClauses(vec& cs, Solver& newSolver, const uint32_t part, PartFinder& partFinder); + void moveClauses(vec& cs, Solver& newSolver, const uint32_t part, PartFinder& partFinder); + void moveLearntClauses(vec& 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 + const bool checkOnlyThisPart(const vec& cs, const uint32_t part, const PartFinder& partFinder) const; + + Solver& solver; + vec savedState; + vec decisionVarRemoved; //variables whose decision-ness has been removed + vec clausesRemoved; + vec xorClausesRemoved; +}; + +inline const vec& PartHandler::getSavedState() +{ + return savedState; +} + +inline void PartHandler::newVar() +{ + savedState.push(l_Undef); +} + +}; //NAMESPACE MINISAT + +#endif //PARTHANDLER_H diff --git a/src/sat/cryptominisat2/RestartTypeChooser.cpp b/src/sat/cryptominisat2/RestartTypeChooser.cpp index 0509b34..9130a1d 100644 --- a/src/sat/cryptominisat2/RestartTypeChooser.cpp +++ b/src/sat/cryptominisat2/RestartTypeChooser.cpp @@ -19,19 +19,20 @@ along with this program. If not, see . #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(); @@ -46,14 +47,17 @@ const RestartType RestartTypeChooser::choose() 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) < (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; @@ -67,24 +71,79 @@ const double RestartTypeChooser::avg() const return (sum/(double)sameIns.size()); } +const double RestartTypeChooser::stdDeviation(vector& 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 tmp(S->order_heap); + Heap 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 RestartTypeChooser::countVarsDegreeStDev() const +{ + vector 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 +void RestartTypeChooser::addDegrees(const vec& cs, vector& 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& cs, vector& degrees) const; +template void RestartTypeChooser::addDegrees(const vec& cs, vector& degrees) const; + +}; //NAMESPACE MINISAT + diff --git a/src/sat/cryptominisat2/RestartTypeChooser.h b/src/sat/cryptominisat2/RestartTypeChooser.h index b328225..4c0628d 100644 --- a/src/sat/cryptominisat2/RestartTypeChooser.h +++ b/src/sat/cryptominisat2/RestartTypeChooser.h @@ -18,27 +18,42 @@ along with this program. If not, see . #ifndef RESTARTTYPECHOOSER_H #define RESTARTTYPECHOOSER_H -#include "SolverTypes.h" +#include "Solver.h" #include -#include +#ifdef _MSC_VER +#include +#else +#include +#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 countVarsDegreeStDev() const; + const double stdDeviation(vector& measure) const; - const Solver* const S; + template + void addDegrees(const vec& cs, vector& degrees) const; + + const Solver& solver; const uint32_t topX; const uint32_t limit; vector sameIns; @@ -46,6 +61,11 @@ class RestartTypeChooser vector firstVars, firstVarsOld; }; -}; +inline void RestartTypeChooser::reset() +{ + sameIns.clear(); +} + +}; //NAMESPACE MINISAT #endif //RESTARTTYPECHOOSER_H diff --git a/src/sat/cryptominisat2/SmallPtr.cpp b/src/sat/cryptominisat2/SmallPtr.cpp new file mode 100644 index 0000000..6fca7bc --- /dev/null +++ b/src/sat/cryptominisat2/SmallPtr.cpp @@ -0,0 +1,17 @@ +/* +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 diff --git a/src/sat/cryptominisat2/SmallPtr.h b/src/sat/cryptominisat2/SmallPtr.h new file mode 100644 index 0000000..a530c54 --- /dev/null +++ b/src/sat/cryptominisat2/SmallPtr.h @@ -0,0 +1,277 @@ +/* +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 + +#include +#include +#include "singleton.hpp" +//#include +//#include + +#ifdef _MSC_VER +#include +#else +#include +#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 + +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< 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 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& 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 + sptr(const sptr& o) + : _ptr(encode(static_cast(o.get()))) + { + } + + template + sptr(const O* p) + : _ptr(encode(static_cast(p))) + { + } + + sptr& operator=(const sptr& o) throw() + { + _ptr = o._ptr; + return *this; + } + + template + sptr& operator=(const sptr& o) + { + _ptr = encode(static_cast(o.get())); + return *this; + } + +private: + inline uint32_t encode(const_native_pointer_type ptr) const + { +#ifdef USE64 + + uintptr_t p = reinterpret_cast(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(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(ptr); +#else + return reinterpret_cast(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 + bool operator==(const sptr& o) const + { + return o._ptr == this->_ptr; + } + + operator TYPE*() const { return get(); } + + sptr& operator++( ) + { + inc_sptr(_ptr); + return *this; + } + + sptr operator++( int ) + { + sptr p = *this; + inc_sptr(_ptr); + return p; + } + + sptr& operator--( ) + { + dec_sptr(_ptr); + return *this; + } + sptr operator--( int ) + { + sptr p = *this; + dec_sptr(_ptr); + return p; + } + + sptr& operator+=(size_t offset) + { + inc_sptr(_ptr, offset); + return *this; + } + + sptr& operator-=(size_t offset) + { + dec_sptr(_ptr, offset); + return *this; + } + +private: + uint32_t _ptr; +}; + +}; //NAMESPACE MINISAT + +#endif + diff --git a/src/sat/cryptominisat2/Solver.cpp b/src/sat/cryptominisat2/Solver.cpp index e27a86d..b98ef36 100644 --- a/src/sat/cryptominisat2/Solver.cpp +++ b/src/sat/cryptominisat2/Solver.cpp @@ -25,10 +25,11 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #include #include -#include +#include #include "Clause.h" #include "time_mem.h" + #include "VarReplacer.h" #include "FindUndef.h" #include "Gaussian.h" @@ -37,6 +38,18 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #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 { @@ -54,27 +67,40 @@ Solver::Solver() : // 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) @@ -83,7 +109,6 @@ Solver::Solver() : , 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) @@ -93,10 +118,15 @@ Solver::Solver() : , 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); @@ -105,14 +135,19 @@ Solver::Solver() : 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); @@ -124,7 +159,7 @@ Solver::~Solver() // 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) @@ -132,17 +167,24 @@ Var Solver::newVar(bool sign, bool dvar) 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); @@ -157,39 +199,16 @@ Var Solver::newVar(bool sign, bool dvar) return v; } -bool Solver::addXorClause(vec& ps, bool xor_clause_inverted, const uint group, char* group_name, const bool internal) +template +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--; @@ -201,48 +220,51 @@ bool Solver::addXorClause(vec& ps, bool xor_clause_inverted, const uint gro 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& ps, const uint group, char* group_name) +template XorClause* Solver::addXorClauseInt(vec& ps, bool xor_clause_inverted, const uint32_t group); +template XorClause* Solver::addXorClauseInt(XorClause& ps, bool xor_clause_inverted, const uint32_t group); + +template +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"); @@ -255,43 +277,127 @@ bool Solver::addClause(vec& ps, const uint group, char* group_name) 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& 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 +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& ps, const uint group, const uint32_t activity); + +template +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& ps, const uint group); + +template +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& 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); @@ -396,9 +502,10 @@ void Solver::cancelUntil(int level) if (decisionLevel() > level) { - for (Gaussian **gauss = &gauss_matrixes[0], **end= gauss + gauss_matrixes.size(); gauss != end; gauss++) + for (vector::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 @@ -428,11 +535,6 @@ void Solver::needLibraryCNFFile(const char* fileName) 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++) @@ -440,11 +542,126 @@ void Solver::clearGaussMatrixes() 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& cs, vector& votes, vector& positiveLiteral, vector& 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& cs, vector& votes, vector& positiveLiteral, vector& 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 votes; + vector positiveLiteral; + vector 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::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() << " "; @@ -452,8 +669,11 @@ Lit Solver::pickBranchLit(int polarity_mode) 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))]; @@ -462,8 +682,6 @@ Lit Solver::pickBranchLit(int polarity_mode) } // 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; @@ -472,23 +690,16 @@ Lit Solver::pickBranchLit(int polarity_mode) 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); @@ -508,6 +719,24 @@ Lit Solver::pickBranchLit(int polarity_mode) } } +// Assumes 'seen' is cleared (will leave it cleared) +template +bool subset(const T1& A, const T2& B, vector& 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; +} + /*_________________________________________________________________________________________________ | @@ -526,10 +755,11 @@ Lit Solver::pickBranchLit(int polarity_mode) | Effect: | Will undo part of the trail, upto but not beyond the assumption of the current decision level. |________________________________________________________________________________________________@*/ -void Solver::analyze(Clause* confl, vec& out_learnt, int& out_btlevel, int &nbLevels/*, int &merged*/) +Clause* Solver::analyze(Clause* confl, vec& out_learnt, int& out_btlevel, int &nbLevels/*, int &merged*/) { int pathC = 0; Lit p = lit_Undef; + Clause* oldConfl = NULL; // Generate conflict clause: // @@ -543,9 +773,9 @@ void Solver::analyze(Clause* confl, vec& out_learnt, int& out_btlevel, int 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); @@ -567,7 +797,9 @@ void Solver::analyze(Clause* confl, vec& out_learnt, int& out_btlevel, int // 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--; @@ -630,17 +862,27 @@ void Solver::analyze(Clause* confl, vec& out_learnt, int& out_btlevel, int } #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; } @@ -718,7 +960,7 @@ void Solver::analyzeFinal(Lit p, vec& out_conflict) } -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; @@ -750,31 +992,39 @@ void Solver::uncheckedEnqueue(Lit p, Clause* from) | 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& ws = watches[p.toInt()]; - Watched *i, *j, *end; - num_props++; + Watched *i, *j, *end; //First propagate binary clauses - vec & 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 & 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 @@ -783,6 +1033,9 @@ Clause* Solver::propagate(const bool xor_as_well) #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; @@ -806,13 +1059,14 @@ Clause* Solver::propagate(const bool xor_as_well) 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; @@ -827,13 +1081,13 @@ Clause* Solver::propagate(const bool xor_as_well) } 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++; } @@ -850,8 +1104,9 @@ FoundWatch: 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; @@ -870,10 +1125,12 @@ Clause* Solver::propagate_xors(const Lit& p) Clause* confl = NULL; - vec& ws = xorwatches[p.var()]; - XorClause **i, **j, **end; + vec& 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()) { @@ -889,7 +1146,7 @@ Clause* Solver::propagate_xors(const Lit& p) 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]); @@ -975,14 +1232,13 @@ struct reduceDB_lt { // 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; } }; @@ -992,7 +1248,19 @@ void Solver::reduceDB() 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 @@ -1019,14 +1287,15 @@ const vector Solver::get_unitary_learnts() const { vector 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) { @@ -1034,15 +1303,46 @@ void Solver::dump_sorted_learnts(const char* file) 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& 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); } @@ -1051,6 +1351,12 @@ void Solver::setMaxRestarts(const uint num) maxRestarts = num; } +inline int64_t abs64(int64_t a) +{ + if (a < 0) return -a; + return a; +} + /*_________________________________________________________________________________________________ | | simplify : [void] -> [bool] @@ -1068,24 +1374,46 @@ lbool Solver::simplify() 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)); @@ -1111,7 +1439,7 @@ lbool Solver::simplify() | 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; @@ -1119,48 +1447,72 @@ lbool Solver::search(int nof_conflicts) 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::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::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() <= 0 && conflictC >= nof_conflicts) { - progress_estimate = progressEstimate(); + #ifdef STATS_NEEDED + if (dynamic_behaviour_analysis) + progress_estimate = progressEstimate(); + #endif cancelUntil(0); return l_Undef; } @@ -1169,6 +1521,14 @@ llbool Solver::new_decision(int& nof_conflicts, int& conflictC) 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) { @@ -1176,7 +1536,7 @@ llbool Solver::new_decision(int& nof_conflicts, int& conflictC) } // Reduce the set of learnt clauses: - if (conflicts >= curRestart * nbclausesbeforereduce) { + if (conflicts >= curRestart * nbclausesbeforereduce + nbCompensateSubsumer) { curRestart ++; reduceDB(); nbclausesbeforereduce += 500; @@ -1201,7 +1561,7 @@ llbool Solver::new_decision(int& nof_conflicts, int& conflictC) if (next == lit_Undef) { // New variable decision: decisions++; - next = pickBranchLit(polarity_mode); + next = pickBranchLit(); if (next == lit_Undef) return l_True; @@ -1215,7 +1575,7 @@ llbool Solver::new_decision(int& nof_conflicts, int& conflictC) return l_Nothing; } -llbool Solver::handle_conflict(vec& learnt_clause, Clause* confl, int& conflictC) +llbool Solver::handle_conflict(vec& learnt_clause, Clause* confl, int& conflictC, const bool update) { #ifdef VERBOSE_DEBUG cout << "Handling conflict: "; @@ -1232,16 +1592,19 @@ llbool Solver::handle_conflict(vec& learnt_clause, Clause* confl, int& conf 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); @@ -1263,15 +1626,29 @@ llbool Solver::handle_conflict(vec& learnt_clause, Clause* confl, int& conf #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); } @@ -1289,7 +1666,7 @@ double Solver::progressEstimate() const 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(); @@ -1306,7 +1683,7 @@ void Solver::print_gauss_sum_stats() const 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::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(); @@ -1324,113 +1701,255 @@ void Solver::print_gauss_sum_stats() const } } -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 backup_order_heap(order_heap); + vector backup_polarities = polarity; + RestartType backup_restartType= restartType; + double backup_random_var_freq = random_var_freq; + vec 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& 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) @@ -1439,15 +1958,25 @@ lbool Solver::solve(const vec& assumps) 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) { @@ -1456,10 +1985,13 @@ lbool Solver::solve(const vec& assumps) } #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(); @@ -1471,14 +2003,6 @@ lbool Solver::solve(const vec& assumps) 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); @@ -1486,7 +2010,48 @@ lbool Solver::solve(const vec& assumps) 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 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; } @@ -1505,10 +2070,12 @@ lbool Solver::solve(const vec& assumps) #ifdef LS_STATS_NBBUMP for(int i=0;isize(),learnts[i]->activity(), - (unsigned int)learnts[i]->nbBump()); + (uint)learnts[i]->nbBump()); #endif cancelUntil(0); + if (doPartHandler && status != l_False) partHandler->readdRemovedClauses(); + return status; } @@ -1528,7 +2095,7 @@ bool Solver::verifyXorClauses(const vec& cs) const 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); @@ -1548,26 +2115,37 @@ bool Solver::verifyXorClauses(const vec& cs) const return failed; } -void Solver::verifyModel() +bool Solver::verifyClauses(const vec& 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()); @@ -1607,11 +2185,11 @@ void Solver::printStatHeader() const 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(); } } @@ -1628,5 +2206,5 @@ void Solver::printEndSearchStat() const } } +}; //NAMESPACE MINISAT -}; diff --git a/src/sat/cryptominisat2/Solver.h b/src/sat/cryptominisat2/Solver.h index 58e2f23..3cab2f9 100644 --- a/src/sat/cryptominisat2/Solver.h +++ b/src/sat/cryptominisat2/Solver.h @@ -25,27 +25,22 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #include #include +#ifdef _MSC_VER +#include +#else +#include +#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 -#else - #include - #include - #include -#endif namespace MINISAT { @@ -58,16 +53,20 @@ class VarReplacer; 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: @@ -79,9 +78,11 @@ public: // Problem specification: // - Var newVar (bool polarity = true, bool dvar = true); // Add a new variable with parameters specifying variable mode. - bool addClause (vec& ps, const uint group, char* group_name); // Add a clause to the solver. NOTE! 'ps' may be shrunk by this method! - bool addXorClause (vec& 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 + 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 + 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: // @@ -95,15 +96,6 @@ public: 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 - void removeWatchedCl(vec &ws, const Clause *c); - template - bool findWatchedCl(vec& ws, const Clause *c); - template - void removeWatchedBinCl(vec &ws, const Clause *c); - template - bool findWatchedBinCl(vec& ws, const Clause *c); // Read state: // @@ -112,6 +104,7 @@ public: 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. @@ -133,20 +126,34 @@ public: 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 @@ -156,16 +163,29 @@ public: const vec& get_learnts() const; //Get all learnt clauses that are >1 long const vector 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 gauss_matrixes; - GaussianConfig gaussconfig; void print_gauss_sum_stats() const; void clearGaussMatrixes(); friend class Gaussian; + template + Clause* addClauseInt(T& ps, uint group); + template + XorClause* addXorClauseInt(T& ps, bool xor_clause_inverted, const uint32_t group); + template + bool addLearntClause(T& ps, const uint group, const uint32_t activity); + template + void removeWatchedCl(vec &ws, const Clause *c); + template + bool findWatchedCl(vec& ws, const Clause *c); + template + void removeWatchedBinCl(vec &ws, const Clause *c); + template + bool findWatchedBinCl(vec& ws, const Clause *c); // Helper structures: // @@ -190,28 +210,29 @@ protected: // bool ok; // If FALSE, the constraints are already unsatisfiable. No part of the solver state may be used! vec clauses; // List of problem clauses. + vec binaryClauses; // Binary clauses are regularly moved here vec xorclauses; // List of problem xor-clauses. Will be freed vec learnts; // List of learnt clauses. vec freeLater; // List of xorclauses to free at the end (due to matrixes, they cannot be freed immediately) vec activity; // A heuristic measurement of the activity of a variable. double var_inc; // Amount to bump next variable with. vec > watches; // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true). - vec > xorwatches; // 'xorwatches[var]' is a list of constraints watching var in XOR clauses. + vec > xorwatches; // 'xorwatches[var]' is a list of constraints watching var in XOR clauses. vec > binwatches; vec assigns; // The current assignments vector polarity; // The preferred polarity of each variable. vector decision_var; // Declares if a variable is eligible for selection in the decision heuristic. vec trail; // Assignment stack; stores all assigments made in the order they were made. vec trail_lim; // Separator indices for different decision levels in 'trail'. - vec reason; // 'reason[var]' is the clause that implied the variables current value, or 'NULL' if none. + vec reason; // 'reason[var]' is the clause that implied the variables current value, or 'NULL' if none. vec level; // 'level[var]' contains the level at which the assignment was made. vec 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 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()'. @@ -219,8 +240,10 @@ protected: Heap 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 nbDecisionLevelHistory; // Set of last decision level in conflict clauses - float totalSumOfDecisionLevel; + bqueue nbDecisionLevelHistory; // Set of last decision level in conflict clauses + double totalSumOfDecisionLevel; + uint64_t conflictsAtLastSolve; + bqueue avgBranchDepth; // Avg branch depth MTRand mtrand; // random number generaton RestartType restartType; // Used internally to determine which restart strategy to choose friend class Logger; @@ -233,7 +256,7 @@ protected: // 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 seen; + vector seen; vec analyze_stack; vec analyze_toclear; vec add_tmp; @@ -248,20 +271,20 @@ protected: 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& out_learnt, int& out_btlevel, int &nblevels); // (bt = backtrack) + Clause* analyze (Clause* confl, vec& out_learnt, int& out_btlevel, int &nblevels); // (bt = backtrack) void analyzeFinal (Lit p, vec& 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& 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& 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: // @@ -291,24 +314,45 @@ protected: 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& cs) const; bool verifyXorClauses (const vec& 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 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[] }; @@ -328,10 +372,22 @@ inline void Solver::varDecayActivity() 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 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: @@ -385,7 +441,11 @@ inline uint32_t Solver::nAssigns () const } 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 { @@ -440,6 +500,7 @@ inline void Solver::setVariableName(Var var, char* name) inline void Solver::setVariableName(Var var, char* name) {} #endif + inline const uint Solver::get_unitary_learnts_num() const { if (decisionLevel() > 0) @@ -484,16 +545,33 @@ inline void Solver::reverse_binary_clause(Clause& c) const { 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); } @@ -531,6 +609,7 @@ static inline void check(bool expr) } //================================================================================================= -}; + +}; //NAMESPACE MINISAT #endif //SOLVER_H diff --git a/src/sat/cryptominisat2/SolverTypes.h b/src/sat/cryptominisat2/SolverTypes.h index 58f61c6..5c64d7b 100644 --- a/src/sat/cryptominisat2/SolverTypes.h +++ b/src/sat/cryptominisat2/SolverTypes.h @@ -23,8 +23,13 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #define SOLVERTYPES_H #include +#ifdef _MSC_VER +#include +#else #include -#include "mtl/Alg.h" +#endif //_MSC_VER + +#include "Alg.h" namespace MINISAT { @@ -56,10 +61,10 @@ public: 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 { @@ -109,7 +114,7 @@ public: 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; @@ -118,7 +123,7 @@ public: 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); } @@ -165,6 +170,7 @@ const llbool l_Nothing = toLbool(2); const llbool l_Continue = toLbool(3); lbool::lbool(llbool b) : value(b.value) {}; -}; + +}; //NAMESPACE MINISAT #endif //SOLVERTYPES_H diff --git a/src/sat/cryptominisat2/Subsumer.cpp b/src/sat/cryptominisat2/Subsumer.cpp new file mode 100644 index 0000000..0295fd8 --- /dev/null +++ b/src/sat/cryptominisat2/Subsumer.cpp @@ -0,0 +1,2033 @@ +/************************************************************************************************** +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 +#include +#include +#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 tmp; + typedef map > > 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 >::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 tmp; + typedef map > > elimType; + elimType::iterator it = elimedOutVar.find(var); + assert(it != elimedOutVar.end()); + + solver.setDecisionVar(var, true); + var_elimed[var] = false; + numElimed--; + for (vector >::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& 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::max(); + #ifdef VERBOSE_DEBUG + cout << "subsume0 orig clause:"; + ps.plainPrint(); + cout << "pointer:" << &ps << endl; + #endif + + vec 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::max(); + #ifdef VERBOSE_DEBUG + cout << "subsume0 orig clause:"; + ps.plainPrint(); + cout << "pointer:" << &ps << endl; + #endif + + vec 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& 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& 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& 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& 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& 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 Q; + vec subs; + vec 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 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& 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& 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& 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& 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& tmp2 = solver.conglomerate->getRemovedVars(); + for (uint32_t i = 0; i < tmp2.size(); i++) { + if (tmp2[i]) cannot_eliminate[i] = true; + } + + const vec& 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& 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::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 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 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 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) < 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& 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& 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& 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& 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& ps, const uint32_t abst, vec& 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& 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& poss, vec& negs, vec& ps, vec& 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& ps, vec& 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& poss = occur[Lit(x, false).toInt()]; + vec& 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 dummy; + //vec 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 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 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& 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& x, const pair& y) { + return x.first < y.first || + (!(y.first < x.first) && x.second < y.second); + } +}; + +// Side-effect: Will untouch all variables. +void Subsumer::orderVarsForElim(vec& order) +{ + order.clear(); + vec > 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& iter, const Lit lit, BitArray& inside, vec& 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 cs(2); + cs[0] = lit; + cs[1] = notInLit; + Clause *cl3 = Clause_new(cs, 0); + uint32_t index = subsume0(*cl3); + if (index != std::numeric_limits::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 addToClauses; + uint64_t totalClausesChecked = 0; + + vec varsToCheck; + + if (clauses.size() > 100000 || solver.order_heap.size() > 30000) { + Heap 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 addedToInside; + vec& 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& 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 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& 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& 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 toRemove; + + touchedBlockedVars = priority_queue, 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 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 toRemove(occur[lit.toInt()]); + for (ClauseSimp *it = toRemove.getData(), *end = toRemove.getDataEnd(); it != end; it++) { + unlinkClause(*it, lit.var()); + numblockedClauseRemoved++; + } + + vec 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 vars; + vec 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 vars; + vec 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 Subsumer::merge() +{ + vector var_merged(solver.nVars(), false); + double myTime = cpuTime(); + + vector 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& 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& 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 > 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 >::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 >::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 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 >::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 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& occSet1 = occur[lit1.toInt()]; + vec& occSet2 = occur[lit2.toInt()]; + vec 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 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 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 diff --git a/src/sat/cryptominisat2/Subsumer.h b/src/sat/cryptominisat2/Subsumer.h new file mode 100644 index 0000000..2d3e95a --- /dev/null +++ b/src/sat/cryptominisat2/Subsumer.h @@ -0,0 +1,249 @@ +/************************************************************************************************** +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 +#include +#include +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& origClause, ClauseSimp c); + void unlinkModifiedClauseNoDetachNoNULL(vec& 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& getVarElimed() const; + const uint32_t getNumElimed() const; + +private: + + friend class ClauseCleaner; + + //Main + vec clauses; + CSet learntClauses; + vec touched; // Is set to true when a variable is part of a removed clause. Also true initially (upon variable creation). + vec touched_list; // A list of the true elements in 'touched'. + CSet cl_touched; // Clauses strengthened. + CSet cl_added; // Clauses created. + vec > occur; // 'occur[index(lit)]' is a list of constraints containing 'lit'. + vec* > iter_vecs; // Vectors currently used for iterations. Removed clauses will be looked up and replaced by 'Clause_NULL'. + vec iter_sets; // Sets currently used for iterations. + Solver& solver; // The Solver + + + vec var_elimed; // 'eliminated[var]' is TRUE if variable has been eliminated. + vec cannot_eliminate;// + map > > elimedOutVar; + + // Temporaries (to reduce allocation overhead): + // + vec seen_tmp; // (used in various places) + vector 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& cs); + void addBackToSolver(); + void removeWrong(vec& 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& iter_vec) { iter_vecs.push(&iter_vec); } + void unregisterIteration(vec& 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& out_subsumed); + void findSubsumed(const vec& ps, const uint32_t abst, vec& out_subsumed); + void findSubsumed(Clause& ps, uint32_t abs, vec& out_subsumed); + bool isSubsumed(Clause& ps); + uint32_t subsume0(Clause& ps); + uint32_t subsume0(Clause& ps, uint32_t abs); + void subsume0LearntSet(vec& cs); + void subsume1(ClauseSimp& ps); + void smaller_database(); + void almost_all_database(); + template + bool subset(const T1& A, const T2& B); + bool subsetAbst(uint32_t A, uint32_t B); + + void orderVarsForElim(vec& order); + int substitute(Lit x, Clause& def, vec& poss, vec& negs, vec& new_clauses); + bool maybeEliminate(Var x); + void MigrateToPsNs(vec& poss, vec& negs, vec& ps, vec& ns, const Var x); + void DeallocPsNs(vec& ps, vec& ns); + bool merge(Clause& ps, Clause& qs, Lit without_p, Lit without_q, vec& out_clause); + + + //hyperBinRes + void addFromSolverAll(vec& cs); + const bool hyperBinRes(); + const bool hyperUtility(vec& iter, const Lit lit, BitArray& inside, vec& addToClauses, uint32_t& hyperBinAdded, uint32_t& hyperBinUnitary); + + //merging + //vector 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& ps, const Lit lit); + uint32_t numblockedClauseRemoved; + const bool tryOneSetting(const Lit lit, const Lit negLit); + priority_queue, MyComp> touchedBlockedVars; + vec 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 +void maybeRemove(vec& 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 +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& Subsumer::getVarElimed() const +{ + return var_elimed; +} + +inline const uint32_t Subsumer::getNumElimed() const +{ + return numElimed; +} + +}; //NAMESPACE MINISAT + +#endif //SIMPLIFIER_H diff --git a/src/sat/cryptominisat2/VERSION b/src/sat/cryptominisat2/VERSION index c006938..9f06d3b 100644 --- a/src/sat/cryptominisat2/VERSION +++ b/src/sat/cryptominisat2/VERSION @@ -1,3 +1,2 @@ CryptoMiniSat -SVN revision: 686 -GIT revision: 30b79471e85e0dde20440ea5c51c78246d14c8ab +GIT revision: e2b5fe1abd1777f753c775026d905a10006ce79b diff --git a/src/sat/cryptominisat2/VarReplacer.cpp b/src/sat/cryptominisat2/VarReplacer.cpp index 575a347..6a23e22 100644 --- a/src/sat/cryptominisat2/VarReplacer.cpp +++ b/src/sat/cryptominisat2/VarReplacer.cpp @@ -16,13 +16,17 @@ along with this program. If not, see . **************************************************************************************************/ #include "VarReplacer.h" +#include +#include -#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 @@ -32,34 +36,51 @@ using std::endl; 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 >::iterator it = reverseTable.begin(); + map >::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 { @@ -71,42 +92,62 @@ void VarReplacer::performReplace() } #endif - uint i = 0; - const vector& removedVars = S->conglomerate->getRemovedVars(); - for (vector::const_iterator it = table.begin(); it != table.end(); it++, i++) { - if (it->var() == i) continue; + Var var = 0; + const vector& removedVars = solver.conglomerate->getRemovedVars(); + const vec& removedVars2 = solver.partHandler->getSavedState(); + const vec& removedVars3 = solver.subsumer->getVarElimed(); + for (vector::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& cs, const bool isAttached) +const bool VarReplacer::replace_set(vec& cs, const bool isAttached) { XorClause **a = cs.getData(); XorClause **r = a; @@ -122,19 +163,22 @@ void VarReplacer::replace_set(vec& cs, const bool isAttached) 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) @@ -149,11 +193,12 @@ const bool VarReplacer::handleUpdatedClause(XorClause& c, const Var origVar1, co //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); @@ -164,27 +209,26 @@ const bool VarReplacer::handleUpdatedClause(XorClause& c, const Var origVar1, co 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 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; } @@ -192,7 +236,7 @@ const bool VarReplacer::handleUpdatedClause(XorClause& c, const Var origVar1, co return false; } -void VarReplacer::replace_set(vec& cs) +const bool VarReplacer::replace_set(vec& cs) { Clause **a = cs.getData(); Clause **r = a; @@ -205,18 +249,22 @@ void VarReplacer::replace_set(vec& cs) 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) @@ -227,38 +275,34 @@ const bool VarReplacer::handleUpdatedClause(Clause& c, const Lit origLit1, const 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; } @@ -266,31 +310,6 @@ const bool VarReplacer::handleUpdatedClause(Clause& c, const Lit origLit1, const 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& VarReplacer::getReplaceTable() const -{ - return table; -} - const vector VarReplacer::getReplacingVars() const { vector replacingVars; @@ -302,56 +321,78 @@ const vector VarReplacer::getReplacingVars() const return replacingVars; } -const vec& VarReplacer::getClauses() const -{ - return clauses; -} - -void VarReplacer::extendModel() const +void VarReplacer::extendModelPossible() const { uint i = 0; for (vector::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 tmpClause; + uint i = 0; + for (vector::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& ps, const bool xor_clause_inverted, const uint group) +template +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; @@ -366,48 +407,55 @@ void VarReplacer::replace(vec& ps, const bool xor_clause_inverted, const ui } 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& ps, const bool xor_clause_inverted, const uint group, const bool internal) +template const bool VarReplacer::replace(vec& 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 +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()); @@ -417,22 +465,27 @@ void VarReplacer::addBinaryXorClause(vec& ps, const bool xor_clause_inverte 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& 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]; @@ -441,7 +494,7 @@ bool VarReplacer::alreadyIn(const Var var, const Lit lit) #ifdef VERBOSE_DEBUG cout << "Inverted cycle in var-replacement -> UNSAT" << endl; #endif - S->ok = false; + solver.ok = false; } return true; } @@ -452,7 +505,7 @@ bool VarReplacer::alreadyIn(const Var var, const Lit lit) #ifdef VERBOSE_DEBUG cout << "Inverted cycle in var-replacement -> UNSAT" << endl; #endif - S->ok = false; + solver.ok = false; } return true; } @@ -463,16 +516,18 @@ bool VarReplacer::alreadyIn(const Var var, const Lit lit) void VarReplacer::setAllThatPointsHereTo(const Var var, const Lit lit) { map >::iterator it = reverseTable.find(var); - if (it == reverseTable.end()) - return; - - for(vector::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::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() @@ -480,8 +535,18 @@ 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 diff --git a/src/sat/cryptominisat2/VarReplacer.h b/src/sat/cryptominisat2/VarReplacer.h index 36f38fd..3669b84 100644 --- a/src/sat/cryptominisat2/VarReplacer.h +++ b/src/sat/cryptominisat2/VarReplacer.h @@ -18,30 +18,40 @@ along with this program. If not, see . #ifndef VARREPLACER_H #define VARREPLACER_H -#include "SolverTypes.h" -#include "Clause.h" -#include "mtl/Vec.h" +#ifdef _MSC_VER +#include +#else +#include +#endif //_MSC_VER -#include #include #include - -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& 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 + 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; @@ -49,15 +59,19 @@ class VarReplacer const vector getReplacingVars() const; const vector& getReplaceTable() const; const vec& 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& set); - void replace_set(vec& cs, const bool isAttached); + const bool performReplaceInternal(); + + const bool replace_set(vec& set); + const bool replace_set(vec& 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& ps, const bool xor_clause_inverted, const uint group, const bool internal = false); + template + 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); @@ -67,11 +81,67 @@ class VarReplacer vec 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& VarReplacer::getReplaceTable() const +{ + return table; +} + +inline const vec& 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 diff --git a/src/sat/cryptominisat2/XSet.h b/src/sat/cryptominisat2/XSet.h new file mode 100644 index 0000000..cfe0c19 --- /dev/null +++ b/src/sat/cryptominisat2/XSet.h @@ -0,0 +1,136 @@ +/************************************************************************************************** +From: Solver.C -- (C) Niklas Een, Niklas Sorensson, 2004 +**************************************************************************************************/ + +#ifndef XSET_H +#define XSET_H + +#include "Vec.h" +#include +#ifdef _MSC_VER +#include +#else +#include +#endif //_MSC_VER + +namespace MINISAT +{ +using namespace MINISAT; + +class XorClause; + +template +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 where; // Map clause ID to position in 'which'. + vec which; // List of clauses (for fast iteration). May contain 'Clause_NULL'. + vec 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::max()); + if (where[c.index] != std::numeric_limits::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::max()) { + //not inside + return false; + } + free.push(where[c.index]); + which[where[c.index]].clause = NULL; + where[c.index] = std::numeric_limits::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::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 diff --git a/src/sat/cryptominisat2/XorFinder.cpp b/src/sat/cryptominisat2/XorFinder.cpp index c410157..3c1e045 100644 --- a/src/sat/cryptominisat2/XorFinder.cpp +++ b/src/sat/cryptominisat2/XorFinder.cpp @@ -25,11 +25,10 @@ along with this program. If not, see . #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 @@ -37,6 +36,10 @@ using std::cout; using std::endl; #endif +namespace MINISAT +{ +using namespace MINISAT; + using std::make_pair; XorFinder::XorFinder(Solver* _s, vec& _cls, ClauseCleaner::ClauseSetType _type) : @@ -46,49 +49,124 @@ XorFinder::XorFinder(Solver* _s, vec& _cls, ClauseCleaner::ClauseSetTyp { } -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(); @@ -100,7 +178,7 @@ uint XorFinder::findXors(uint& sumLengths) 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; @@ -117,7 +195,8 @@ uint XorFinder::findXors(uint& sumLengths) 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); @@ -143,7 +222,7 @@ uint XorFinder::findXors(uint& sumLengths) sumLengths += lits.size(); } - return foundXors; + return true; } void XorFinder::clearToRemove() @@ -169,9 +248,12 @@ bool XorFinder::getNextXor(ClauseTable::iterator& begin, ClauseTable::iterator& 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; } @@ -196,15 +278,35 @@ bool XorFinder::impairSigns(const Clause& c) const 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 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; @@ -249,4 +351,5 @@ void XorFinder::countImpairs(const ClauseTable::iterator& begin, const ClauseTab it2++; } } -}; + +}; //NAMESPACE MINISAT diff --git a/src/sat/cryptominisat2/XorFinder.h b/src/sat/cryptominisat2/XorFinder.h index bee1e81..7140a5c 100644 --- a/src/sat/cryptominisat2/XorFinder.h +++ b/src/sat/cryptominisat2/XorFinder.h @@ -18,29 +18,38 @@ along with this program. If not, see . #ifndef XORFINDER_H #define XORFINDER_H +#ifdef _MSC_VER +#include +#else +#include +#endif //_MSC_VER + +#define DEBUG_XORFIND +//#define DEBUG_XORFIND2 + #include "Clause.h" -#include #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& cls, ClauseCleaner::ClauseSetType _type); - uint doNoPart(const uint minSize, const uint maxSize); + const bool doNoPart(const uint minSize, const uint maxSize); private: typedef vector > ClauseTable; - uint findXors(uint& sumLengths); + const bool findXors(uint& sumLengths); bool getNextXor(ClauseTable::iterator& begin, ClauseTable::iterator& end, bool& impair); struct clause_hasher { @@ -60,10 +69,20 @@ class XorFinder { 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; @@ -82,7 +101,7 @@ class XorFinder 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; @@ -104,6 +123,7 @@ class XorFinder ClauseTable table; vector toRemove; void clearToRemove(); + uint32_t foundXors; vec& cls; ClauseCleaner::ClauseSetType type; @@ -111,10 +131,11 @@ class XorFinder 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 diff --git a/src/sat/cryptominisat2/XorSubsumer.cpp b/src/sat/cryptominisat2/XorSubsumer.cpp new file mode 100644 index 0000000..8ec7140 --- /dev/null +++ b/src/sat/cryptominisat2/XorSubsumer.cpp @@ -0,0 +1,306 @@ +/************************************************************************************************** +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 +#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 origClause(ps.clause->size()); + std::copy(ps.clause->getData(), ps.clause->getDataEnd(), origClause.getData()); + const bool origClauseInverted = ps.clause->xor_clause_inverted(); + + vec unmatchedPart; + bool needUnlinkPS = false; + + vec 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& A, XorClause& B, vec& 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& 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& 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& 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) <& 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& 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 diff --git a/src/sat/cryptominisat2/XorSubsumer.h b/src/sat/cryptominisat2/XorSubsumer.h new file mode 100644 index 0000000..1876bce --- /dev/null +++ b/src/sat/cryptominisat2/XorSubsumer.h @@ -0,0 +1,95 @@ +/************************************************************************************************** +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& origClause, XorClauseSimp c); + void unlinkModifiedClauseNoDetachNoNULL(vec& origClause, XorClauseSimp c); + void unlinkClause(XorClauseSimp cc); + XorClauseSimp linkInClause(XorClause& cl); + void linkInAlreadyClause(XorClauseSimp& c); + void newVar(); + +private: + + friend class ClauseCleaner; + + //Main + vec clauses; + vec > occur; // 'occur[index(lit)]' is a list of constraints containing 'lit'. + Solver& solver; // The Solver + + // Temporaries (to reduce allocation overhead): + // + vec seen_tmp; // (used in various places) + + //Start-up + void addFromSolver(vec& cs); + void addBackToSolver(); + + // Subsumption: + void findSubsumed(XorClause& ps, vec& out_subsumed); + bool isSubsumed(XorClause& ps); + void subsume0(XorClauseSimp& ps); + template + bool subset(const T1& A, const T2& B); + bool subsetAbst(uint32_t A, uint32_t B); + void findUnMatched(vec& A, XorClause& B, vec& 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 +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 diff --git a/src/sat/cryptominisat2/constants.h b/src/sat/cryptominisat2/constants.h index d063651..a223c7c 100644 --- a/src/sat/cryptominisat2/constants.h +++ b/src/sat/cryptominisat2/constants.h @@ -18,14 +18,18 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 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 diff --git a/src/sat/cryptominisat2/msvc/stdint.h b/src/sat/cryptominisat2/msvc/stdint.h new file mode 100644 index 0000000..fee624d --- /dev/null +++ b/src/sat/cryptominisat2/msvc/stdint.h @@ -0,0 +1,250 @@ +// 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 + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap 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 +#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 +#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_ ] diff --git a/src/sat/cryptominisat2/mtl/Alg.h b/src/sat/cryptominisat2/mtl/Alg.h index 0e4d000..2825a9c 100644 --- a/src/sat/cryptominisat2/mtl/Alg.h +++ b/src/sat/cryptominisat2/mtl/Alg.h @@ -19,13 +19,20 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Alg_h #define Alg_h -#include "stdint.h" -//================================================================================================= -// Useful functions on vectors +#ifdef _MSC_VER +#include +#else +#include +#endif //_MSC_VER namespace MINISAT { +using namespace MINISAT; + +//================================================================================================= +// Useful functions on vectors + template static inline void remove(V& ts, const T& t) @@ -63,6 +70,6 @@ static inline bool findW(V& ts, const T& t) return j < ts.size(); } -}; +}; //NAMESPACE MINISAT #endif diff --git a/src/sat/cryptominisat2/mtl/BasicHeap.h b/src/sat/cryptominisat2/mtl/BasicHeap.h index 4a34e77..8748d2a 100644 --- a/src/sat/cryptominisat2/mtl/BasicHeap.h +++ b/src/sat/cryptominisat2/mtl/BasicHeap.h @@ -19,11 +19,18 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef BasicHeap_h #define BasicHeap_h -#include "Vec.h" +#ifdef _MSC_VER +#include +#else +#include +#endif //_MSC_VERs + +#include "Vec.h" namespace MINISAT { +using namespace MINISAT; //================================================================================================= // A heap implementation with support for decrease/increase key. @@ -96,7 +103,7 @@ class BasicHeap { int getmin () { return removeMin(); } }; -}; +}; //NAMESPACE MINISAT //================================================================================================= #endif diff --git a/src/sat/cryptominisat2/mtl/BoxedVec.h b/src/sat/cryptominisat2/mtl/BoxedVec.h index 3178856..63b8c6d 100644 --- a/src/sat/cryptominisat2/mtl/BoxedVec.h +++ b/src/sat/cryptominisat2/mtl/BoxedVec.h @@ -26,6 +26,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA namespace MINISAT { +using namespace MINISAT; //================================================================================================= // Automatically resizable arrays @@ -146,6 +147,6 @@ public: }; -}; +}; //NAMESPACE MINISAT #endif diff --git a/src/sat/cryptominisat2/mtl/Heap.h b/src/sat/cryptominisat2/mtl/Heap.h index e5b2035..24d2df1 100644 --- a/src/sat/cryptominisat2/mtl/Heap.h +++ b/src/sat/cryptominisat2/mtl/Heap.h @@ -21,14 +21,18 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #define Heap_h #include "Vec.h" + #include "string.h" +#include +#ifdef _MSC_VER +#include +#else #include -#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. @@ -87,10 +91,25 @@ class Heap { indices.growTo(other.indices.size()); memcpy(indices.getData(), other.indices.getData(), sizeof(uint32_t)*other.indices.size()); } + + void operator=(const Heap& 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::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]); } @@ -101,7 +120,7 @@ class Heap { void insert(uint32_t n) { - indices.growTo(n+1, UINT32_MAX); + indices.growTo(n+1, std::numeric_limits::max()); assert(!inHeap(n)); indices[n] = heap.size(); @@ -115,7 +134,7 @@ class Heap { uint32_t x = heap[0]; heap[0] = heap.last(); indices[heap[0]] = 0; - indices[x] = UINT32_MAX; + indices[x] = std::numeric_limits::max(); heap.pop(); if (heap.size() > 1) percolateDown(0); return x; @@ -125,10 +144,10 @@ class Heap { 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::max(); #ifndef NDEBUG for (uint32_t i = 0; i != indices.size(); i++) - assert(indices[i] == UINT32_MAX); + assert(indices[i] == std::numeric_limits::max()); #endif heap.clear(dealloc); } @@ -156,7 +175,7 @@ class Heap { heap[j] = heap[i]; indices[heap[i]] = j++; }else - indices[heap[i]] = UINT32_MAX; + indices[heap[i]] = std::numeric_limits::max(); heap.shrink(i - j); for (int i = heap.size() / 2 - 1; i >= 0; i--) @@ -178,7 +197,8 @@ class Heap { }; -}; - //================================================================================================= + +}; //NAMESPACE MINISAT + #endif diff --git a/src/sat/cryptominisat2/mtl/Map.h b/src/sat/cryptominisat2/mtl/Map.h index 302069a..bd791c3 100644 --- a/src/sat/cryptominisat2/mtl/Map.h +++ b/src/sat/cryptominisat2/mtl/Map.h @@ -20,11 +20,17 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Map_h #define Map_h +#ifdef _MSC_VER +#include +#else #include +#endif //_MSC_VER + #include "Vec.h" namespace MINISAT { +using namespace MINISAT; //================================================================================================= // Default hash/equals functions @@ -117,6 +123,6 @@ class Map { } }; -}; +}; //NAMESPACE MINISAT #endif diff --git a/src/sat/cryptominisat2/mtl/Queue.h b/src/sat/cryptominisat2/mtl/Queue.h index 52f8fb2..4138559 100644 --- a/src/sat/cryptominisat2/mtl/Queue.h +++ b/src/sat/cryptominisat2/mtl/Queue.h @@ -24,6 +24,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA namespace MINISAT { +using namespace MINISAT; //================================================================================================= @@ -81,7 +82,8 @@ public: // } //}; -}; - //================================================================================================= + +}; //NAMESPACE MINISAT + #endif diff --git a/src/sat/cryptominisat2/mtl/Vec.h b/src/sat/cryptominisat2/mtl/Vec.h index 3e84bca..1c6c1ae 100644 --- a/src/sat/cryptominisat2/mtl/Vec.h +++ b/src/sat/cryptominisat2/mtl/Vec.h @@ -19,13 +19,20 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Vec_h #define Vec_h + #include #include #include +#ifdef _MSC_VER +#include +#else #include +#endif //_MSC_VER namespace MINISAT { +using namespace MINISAT; + //================================================================================================= // Automatically resizable arrays // @@ -42,11 +49,13 @@ class vec { // Don't allow copying (error prone): vec& operator = (vec& other) { assert(0); return *this; } - vec (vec& other) { assert(0); } + //vec (vec& 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& other); public: // Types: @@ -58,12 +67,15 @@ public: 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& 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; } @@ -76,6 +88,7 @@ public: 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; } @@ -113,6 +126,13 @@ void vec::growTo(uint32_t size) { grow(size); for (uint32_t i = sz; i != size; i++) new (&data[i]) T(); sz = size; } + +template +void vec::myCopy(const vec& 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 void vec::clear(bool dealloc) { @@ -121,6 +141,7 @@ void vec::clear(bool dealloc) { sz = 0; if (dealloc) free(data), data = NULL, cap = 0; } } -}; + +}; //NAMESPACE MINISAT #endif diff --git a/src/sat/cryptominisat2/pool.hpp b/src/sat/cryptominisat2/pool.hpp new file mode 100644 index 0000000..be1137a --- /dev/null +++ b/src/sat/cryptominisat2/pool.hpp @@ -0,0 +1,584 @@ +// 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 // for workarounds + +// std::less, std::less_equal, std::greater +#include +// new[], delete[], std::nothrow +#include +// std::size_t, std::ptrdiff_t +#include +// std::malloc, std::free +#include +// std::invalid_argument +#include +// std::max +#include + +#include "poolfwd.hpp" + +// boost::details::pool::ct_lcm +#include +// boost::details::pool::lcm +#include +// boost::simple_segregated_storage +#include + +#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(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 +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::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::value); + } + + size_type & next_size() const + { return *(reinterpret_cast(ptr_next_size())); } + char * & next_ptr() const + { return *(reinterpret_cast(ptr_next_ptr())); } + + PODptr next() const + { return PODptr(next_ptr(), next_size()); } + void next(const PODptr & arg) const + { + next_ptr() = arg.begin(); + next_size() = arg.total_size(); + } +}; + +} // namespace details + +template +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::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 list; + + simple_segregated_storage & store() { return *this; } + const simple_segregated_storage & 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 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()(static_cast(i), chunk) +// && std::less()(chunk, +// static_cast(i + sizeof_i))); + std::less_equal lt_eq; + std::less 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(requested_size, min_size); + } + + // for the sake of code readability :) + static void * & nextof(void * const ptr) + { return *(static_cast(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 +bool pool::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 ptr = list; + details::PODptr 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 next = ptr.next(); + + if (!all_chunks_free) + { + if (is_from(free_p, ptr.begin(), ptr.element_size())) + { + std::less 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 +bool pool::purge_memory() +{ + details::PODptr iter = list; + + if (!iter.valid()) + return false; + + do + { + // hold "next" pointer + const details::PODptr 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 +void * pool::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::value + sizeof(size_type); + char * const ptr = UserAllocator::malloc(POD_size); + if (ptr == 0) + return 0; + const details::PODptr 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 +void * pool::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::value + sizeof(size_type); + char * const ptr = UserAllocator::malloc(POD_size); + if (ptr == 0) + return 0; + const details::PODptr 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()(list.begin(), node.begin())) + { + node.next(list); + list = node; + } + else + { + details::PODptr 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()(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 +void * pool::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::value + sizeof(size_type); + char * const ptr = UserAllocator::malloc(POD_size); + if (ptr == 0) + return 0; + const details::PODptr 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()(list.begin(), node.begin())) + { + node.next(list); + list = node; + } + else + { + details::PODptr 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()(prev.next_ptr(), node.begin())) + break; + + prev = prev.next(); + } + + node.next(prev.next()); + prev.next(node); + } + + // and return it. + return node.begin(); +} + +template +details::PODptr::size_type> +pool::find_POD(void * const chunk) const +{ + // We have to find which storage this chunk is from. + details::PODptr iter = list; + while (iter.valid()) + { + if (is_from(chunk, iter.begin(), iter.element_size())) + return iter; + iter = iter.next(); + } + + return iter; +} + +} // namespace boost + +#endif diff --git a/src/sat/cryptominisat2/poolfwd.hpp b/src/sat/cryptominisat2/poolfwd.hpp new file mode 100644 index 0000000..52964f7 --- /dev/null +++ b/src/sat/cryptominisat2/poolfwd.hpp @@ -0,0 +1,70 @@ +// 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 // for workarounds + +// std::size_t +#include + +// boost::details::pool::default_mutex +//#include + +namespace boost { + +// +// Location: +// +template +class simple_segregated_storage; + +// +// Location: +// +struct default_user_allocator_new_delete; +struct default_user_allocator_malloc_free; + +template +class pool; + +// +// Location: +// +template +class object_pool; + +// +// Location: +// +template +struct singleton_pool; + +// +// Location: +// +struct pool_allocator_tag; + +template +class pool_allocator; + +struct fast_pool_allocator_tag; + +template +class fast_pool_allocator; + +} // namespace boost + +#endif diff --git a/src/sat/cryptominisat2/singleton.hpp b/src/sat/cryptominisat2/singleton.hpp new file mode 100644 index 0000000..db7ca67 --- /dev/null +++ b/src/sat/cryptominisat2/singleton.hpp @@ -0,0 +1,107 @@ +// 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::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 +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::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::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::create_object, whose constructor is + // called before main() begins. + create_object.do_nothing(); + + return obj; + } +}; +template +typename singleton_default::object_creator +singleton_default::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 diff --git a/src/sat/cryptominisat2/time_mem.h b/src/sat/cryptominisat2/time_mem.h index a4c6552..c76b445 100644 --- a/src/sat/cryptominisat2/time_mem.h +++ b/src/sat/cryptominisat2/time_mem.h @@ -21,8 +21,11 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef TIME_MEM_H #define TIME_MEM_H -namespace MINISAT -{ +#ifdef _MSC_VER +#include +#else +#include +#endif //_MSC_VER #ifdef _MSC_VER #include @@ -31,7 +34,7 @@ static inline double cpuTime(void) { return (double)clock() / CLOCKS_PER_SEC; } -#else +#else //_MSC_VER #ifdef CROSS_COMPILE #include @@ -39,7 +42,7 @@ static inline double cpuTime(void) { return (double)clock() / CLOCKS_PER_SEC; } -#else +#else //CROSS_COMPILE #include #include #include @@ -50,8 +53,8 @@ static inline double cpuTime(void) 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__) @@ -90,6 +93,4 @@ static inline uint64_t memUsed() } #endif -}; - #endif //TIME_MEM_H diff --git a/src/to-sat/ToSAT.cpp b/src/to-sat/ToSAT.cpp index 477dbd1..d20df58 100644 --- a/src/to-sat/ToSAT.cpp +++ b/src/to-sat/ToSAT.cpp @@ -140,9 +140,10 @@ namespace BEEV #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 && -- 2.47.3