From 75f34888a5c43e0a7be5e036114fdd4ec5b0f34d Mon Sep 17 00:00:00 2001 From: msoos Date: Fri, 4 Jun 2010 17:56:12 +0000 Subject: [PATCH] Importing CryptoMiniSat version 'Cluster56'. git-svn-id: https://stp-fast-prover.svn.sourceforge.net/svnroot/stp-fast-prover/trunk/stp@812 e59a4935-1847-0410-ae03-e826735625c1 --- src/sat/cryptominisat2/BitArray.h | 141 --- src/sat/cryptominisat2/BoundedQueue.h | 88 -- src/sat/cryptominisat2/CSet.h | 136 -- src/sat/cryptominisat2/Clause.cpp | 3 - src/sat/cryptominisat2/Clause.h | 415 ------- src/sat/cryptominisat2/ClauseCleaner.cpp | 369 ------ src/sat/cryptominisat2/ClauseCleaner.h | 79 -- src/sat/cryptominisat2/Conglomerate.cpp | 526 -------- src/sat/cryptominisat2/Conglomerate.h | 125 -- src/sat/cryptominisat2/DoublePackedRow.h | 173 --- src/sat/cryptominisat2/FailedVarSearcher.cpp | 412 ------- src/sat/cryptominisat2/FailedVarSearcher.h | 90 -- src/sat/cryptominisat2/FindUndef.cpp | 176 --- src/sat/cryptominisat2/FindUndef.h | 59 - src/sat/cryptominisat2/Gaussian.cpp | 1160 ------------------ src/sat/cryptominisat2/Gaussian.h | 213 ---- src/sat/cryptominisat2/GaussianConfig.h | 52 - src/sat/cryptominisat2/Logger.cpp | 893 -------------- src/sat/cryptominisat2/Logger.h | 187 --- src/sat/cryptominisat2/Makefile | 27 - src/sat/cryptominisat2/MatrixFinder.cpp | 224 ---- src/sat/cryptominisat2/MatrixFinder.h | 72 -- src/sat/cryptominisat2/MersenneTwister.h | 427 ------- src/sat/cryptominisat2/PartFinder.cpp | 4 +- src/sat/cryptominisat2/PartHandler.cpp | 73 +- src/sat/cryptominisat2/Solver.cpp | 1000 ++++++++++----- src/sat/cryptominisat2/Solver.h | 146 ++- src/sat/cryptominisat2/SolverTypes.h | 15 +- src/sat/cryptominisat2/StateSaver.cpp | 54 + src/sat/cryptominisat2/StateSaver.h | 46 + src/sat/cryptominisat2/Subsumer.cpp | 961 ++++++++++----- src/sat/cryptominisat2/Subsumer.h | 86 +- src/sat/cryptominisat2/VarReplacer.cpp | 59 +- src/sat/cryptominisat2/VarReplacer.h | 8 +- src/sat/cryptominisat2/XorFinder.cpp | 12 +- src/sat/cryptominisat2/XorSubsumer.cpp | 387 +++++- src/sat/cryptominisat2/XorSubsumer.h | 48 +- src/sat/cryptominisat2/constants.h | 36 - 38 files changed, 2118 insertions(+), 6864 deletions(-) create mode 100644 src/sat/cryptominisat2/StateSaver.cpp create mode 100644 src/sat/cryptominisat2/StateSaver.h diff --git a/src/sat/cryptominisat2/BitArray.h b/src/sat/cryptominisat2/BitArray.h index 1e52009..e69de29 100644 --- a/src/sat/cryptominisat2/BitArray.h +++ b/src/sat/cryptominisat2/BitArray.h @@ -1,141 +0,0 @@ -/*********************************************************************************** -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 BITARRAY_H -#define BITARRAY_H - -//#define DEBUG_BITARRAY - -#include -#include -#ifdef _MSC_VER -#include -#else -#include -#endif //_MSC_VER - -namespace MINISAT -{ -using namespace MINISAT; - -class BitArray -{ -public: - BitArray() : - size(0) - , mp(NULL) - { - } - - BitArray(const BitArray& b) : - size(b.size) - { - mp = new uint64_t[size]; - memcpy(mp, b.mp, sizeof(uint64_t)*size); - } - - BitArray& operator=(const BitArray& b) - { - if (size != b.size) { - delete[] mp; - size = b.size; - mp = new uint64_t[size]; - } - memcpy(mp, b.mp, sizeof(uint64_t)*size); - - return *this; - } - - void resize(uint _size, const bool fill) - { - _size = _size/64 + (bool)(_size%64); - if (size != _size) { - delete[] mp; - size = _size; - mp = new uint64_t[size]; - } - if (fill) setOne(); - else setZero(); - } - - ~BitArray() - { - delete[] mp; - } - - inline const bool isZero() const - { - const uint64_t* mp2 = (const uint64_t*)mp; - - for (uint i = 0; i < size; i++) { - if (mp2[i]) return false; - } - return true; - } - - inline void setZero() - { - memset(mp, 0, size*sizeof(uint64_t)); - } - - inline void setOne() - { - memset(mp, 0, size*sizeof(uint64_t)); - } - - inline void clearBit(const uint i) - { - #ifdef DEBUG_BITARRAY - assert(size*64 > i); - #endif - - mp[i/64] &= ~((uint64_t)1 << (i%64)); - } - - inline void setBit(const uint i) - { - #ifdef DEBUG_BITARRAY - assert(size*64 > i); - #endif - - mp[i/64] |= ((uint64_t)1 << (i%64)); - } - - inline const bool operator[](const uint& i) const - { - #ifdef DEBUG_BITARRAY - assert(size*64 > i); - #endif - - return (mp[i/64] >> (i%64)) & 1; - } - - inline const uint getSize() const - { - return size*64; - } - -private: - - uint size; - uint64_t* mp; -}; - -}; //NAMESPACE MINISAT - -#endif //BITARRAY_H - diff --git a/src/sat/cryptominisat2/BoundedQueue.h b/src/sat/cryptominisat2/BoundedQueue.h index a705a6d..e69de29 100644 --- a/src/sat/cryptominisat2/BoundedQueue.h +++ b/src/sat/cryptominisat2/BoundedQueue.h @@ -1,88 +0,0 @@ -/*****************************************************************************************[Queue.h] -MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson - 2008 - Gilles Audemard, Laurent Simon - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************************************/ - -#ifndef BoundedQueue_h -#define BoundedQueue_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; - 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; - } - - T peek() { assert(queuesize>0); return elems[last]; } - void pop() {sumofqueue-=elems[last]; queuesize--; if ((++last) == maxsize) last = 0;} - - uint64_t getsum() const {return sumofqueue;} - uint32_t getavg() const {return (uint64_t)sumofqueue/(uint64_t)queuesize;} - int isvalid() const {return (queuesize==maxsize);} - - void growTo(int size) { - elems.growTo(size); - first=0; maxsize=size; queuesize = 0; - for(int i=0;i -#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 index b2bc8bc..e69de29 100644 --- a/src/sat/cryptominisat2/Clause.cpp +++ b/src/sat/cryptominisat2/Clause.cpp @@ -1,3 +0,0 @@ -#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 5969fd3..e69de29 100644 --- a/src/sat/cryptominisat2/Clause.h +++ b/src/sat/cryptominisat2/Clause.h @@ -1,415 +0,0 @@ -/***********************************************************************************[SolverTypes.h] -MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson -CryptoMiniSat -- Copyright (c) 2009 Mate Soos - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************************************/ - -#ifndef CLAUSE_H -#define CLAUSE_H - -#ifdef _MSC_VER -#include -#else -#include "SmallPtr.h" -#include -#endif //_MSC_VER -#include -#include -#include -#include "Vec.h" -#include "SolverTypes.h" -#include "PackedRow.h" -#include "constants.h" -//#include "pool.hpp" -#ifndef uint -#define uint unsigned int -#endif - -using std::vector; - -namespace MINISAT -{ -using namespace MINISAT; - -//================================================================================================= -// Clause -- a simple class for representing a clause: - -class MatrixFinder; - -class Clause -{ -protected: - - #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; - float oldActivityInter; - #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) - { - 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; - oldActivityInter = 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 - - const uint size () const { - return mySize; - } - void resize (const uint size) { - mySize = size; - } - void shrink (const uint i) { - assert(i <= size()); - mySize -= i; - } - void pop () { - shrink(1); - } - const bool isXor () { - return isXorClause; - } - const bool learnt () const { - return isLearnt; - } - float& oldActivity () { - return oldActivityInter; - } - - const float& oldActivity () const { - return oldActivityInter; - } - - - const bool getStrenghtened() const { - return strenghtened; - } - void setStrenghtened() { - strenghtened = true; - sorted = false; - subsume0Done = false; - } - void unsetStrenghtened() { - strenghtened = false; - } - const bool getVarChanged() const { - return varChanged; - } - void setVarChanged() { - varChanged = true; - sorted = false; - subsume0Done = false; - } - void unsetVarChanged() { - varChanged = false; - } - const bool getSorted() const { - return sorted; - } - void setSorted() { - sorted = true; - } - void setUnsorted() { - sorted = false; - } - void subsume0Finished() { - subsume0Done = 1; - } - const bool subsume0IsFinished() { - return subsume0Done; - } - - Lit& operator [] (uint32_t i) { - return data[i]; - } - const Lit& operator [] (uint32_t i) const { - return data[i]; - } - - void setActivity(int i) { - extra.act = i; - } - - const int& activity () const { - return extra.act; - } - - void makeNonLearnt() { - assert(isLearnt); - isLearnt = false; - calcAbstraction(); - } - - void makeLearnt(const uint32_t newActivity) { - extra.act = newActivity; - isLearnt = true; - } - - inline void strengthen(const Lit p) - { - remove(*this, p); - sorted = false; - calcAbstraction(); - } - - void calcAbstraction() { - extra.abst = 0; - for (uint32_t i = 0; i != size(); i++) - extra.abst |= 1 << (data[i].toInt() & 31); - } - - uint32_t getAbst() - { - return extra.abst; - } - - const Lit* getData () const { - return data; - } - 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: ", getGroup(), size(), learnt()); - plainPrint(); - } - void plainPrint(FILE* to = stdout) const { - for (uint i = 0; i < size(); i++) { - if (data[i].sign()) fprintf(to, "-"); - fprintf(to, "%d ", data[i].var() + 1); - } - fprintf(to, "0\n"); - } - #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 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) - { - 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 invertedXor; - } - inline void invert(bool b) - { - 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:\"", getGroup(), size(), learnt()); - plainPrint(); - } - - void plainPrint(FILE* to = stdout) const { - fprintf(to, "x"); - if (xor_clause_inverted()) - printf("-"); - for (uint i = 0; i < size(); i++) { - fprintf(to, "%d ", data[i].var() + 1); - } - fprintf(to, "0\n"); - } - - friend class MatrixFinder; -}; - -//extern boost::pool<> binaryClausePool; - -template -Clause* Clause_new(const T& ps, const uint group, const bool learnt = false) -{ - 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; -} - -template -XorClause* XorClause_new(const T& ps, const bool inverted, const uint group) -{ - void* mem = malloc(sizeof(XorClause) + sizeof(Lit)*(ps.size())); - XorClause* real= new (mem) XorClause(ps, inverted, group); - return real; -} - -inline void clauseFree(Clause* c) -{ - //if (binaryClausePool.is_from(c)) binaryClausePool.free(c); - //else - free(c); -} - -/*_________________________________________________________________________________________________ -| -| subsumes : (other : const Clause&) -> Lit -| -| Description: -| Checks if clause subsumes 'other', and at the same time, if it can be used to simplify 'other' -| by subsumption resolution. -| -| Result: -| lit_Error - No subsumption or simplification -| lit_Undef - Clause subsumes 'other' -| p - The literal p can be deleted from 'other' -|________________________________________________________________________________________________@*/ -/*inline Lit Clause::subsumes(const Clause& other) const -{ - if (other.size() < size() || (extra.abst & ~other.extra.abst) != 0) - return lit_Error; - - Lit ret = lit_Undef; - const Lit* c = this->getData(); - const Lit* d = other.getData(); - - for (uint32_t i = 0; i != size(); i++) { - // search for c[i] or ~c[i] - for (uint32_t j = 0; j != other.size(); j++) - if (c[i] == d[j]) - goto ok; - else if (ret == lit_Undef && c[i] == ~d[j]){ - ret = c[i]; - goto ok; - } - - // did not find it - return lit_Error; - ok:; - } - - return ret; -}*/ - -#ifdef _MSC_VER -typedef Clause* ClausePtr; -typedef XorClause* XorClausePtr; -#else -typedef sptr ClausePtr; -typedef sptr XorClausePtr; -#endif //_MSC_VER - -#pragma pack(push) -#pragma pack(1) -class WatchedBin { - public: - WatchedBin(Clause *_clause, Lit _impliedLit) : clause(_clause), impliedLit(_impliedLit) {}; - ClausePtr clause; - Lit impliedLit; -}; - -class Watched { - public: - Watched(Clause *_clause, Lit _blockedLit) : clause(_clause), blockedLit(_blockedLit) {}; - ClausePtr clause; - Lit blockedLit; -}; -#pragma pack(pop) - -}; //NAMESPACE MINISAT - -#endif //CLAUSE_H diff --git a/src/sat/cryptominisat2/ClauseCleaner.cpp b/src/sat/cryptominisat2/ClauseCleaner.cpp index 7f4610b..e69de29 100644 --- a/src/sat/cryptominisat2/ClauseCleaner.cpp +++ b/src/sat/cryptominisat2/ClauseCleaner.cpp @@ -1,369 +0,0 @@ -/*********************************************************************************** -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 "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; - -ClauseCleaner::ClauseCleaner(Solver& _solver) : - solver(_solver) -{ - for (uint i = 0; i < 6; i++) { - lastNumUnitarySat[i] = solver.get_unitary_learnts_num(); - lastNumUnitaryClean[i] = solver.get_unitary_learnts_num(); - } -} - -void ClauseCleaner::removeSatisfied(vec& cs, ClauseSetType type, const uint limit) -{ - #ifdef DEBUG_CLEAN - assert(solver.decisionLevel() == 0); - #endif - - if (lastNumUnitarySat[type] + limit >= solver.get_unitary_learnts_num()) - return; - - uint32_t i,j; - for (i = j = 0; i < cs.size(); i++) { - if (satisfied(*cs[i])) - solver.removeClause(*cs[i]); - else - cs[j++] = cs[i]; - } - cs.shrink(i - j); - - lastNumUnitarySat[type] = solver.get_unitary_learnts_num(); -} - -void ClauseCleaner::removeSatisfied(vec& cs, ClauseSetType type, const uint limit) -{ - #ifdef DEBUG_CLEAN - assert(solver.decisionLevel() == 0); - #endif - - if (lastNumUnitarySat[type] + limit >= solver.get_unitary_learnts_num()) - return; - - 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 - *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]; - Lit origLit2 = c[1]; - uint32_t origSize = 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) { - solver.detachModifiedClause(origLit1, origLit2, origSize, &c); - return true; - } - } - - if ((c.size() > 2) && (c.size() - (i-j) == 2)) { - solver.detachModifiedClause(origLit1, origLit2, c.size(), &c); - c.shrink(i-j); - c.setStrenghtened(); - solver.attachClause(c); - } else if (i != j) { - c.setStrenghtened(); - c.shrink(i-j); - if (c.learnt()) - solver.learnts_literals -= i-j; - else - solver.clauses_literals -= i-j; - } - - return false; -} - -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; - - 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); - s++; - } else { - *ss++ = *s++; - } - } - cs.shrink(s-ss); - - lastNumUnitaryClean[type] = solver.get_unitary_learnts_num(); - - #ifdef VERBOSE_DEBUG - cout << "cleanClauses(XorClause) useful: ?? Removed: " << s-ss << endl; - #endif -} - -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) -{ - assert(solver.decisionLevel() == 0); - assert(solver.qhead == solver.trail.size()); - - if (lastNumUnitaryClean[type] + limit >= solver.get_unitary_learnts_num()) - return; - - 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 { - 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); - } - - 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()); - - 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::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; - 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: { - 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.getGroup()); - subs.unlinkModifiedClause(origClause, cc); - free(cc.clause); - return true; - } - default: - if (i-j > 0) { - subs.unlinkModifiedClauseNoDetachNoNULL(origClause, cc); - subs.linkInAlreadyClause(cc); - c.calcXorAbstraction(); - } - } - - return false; -} - -bool ClauseCleaner::satisfied(const Clause& c) const -{ - for (uint i = 0; i != c.size(); i++) - if (solver.value(c[i]) == l_True) - return true; - return false; -} - -bool ClauseCleaner::satisfied(const XorClause& c) const -{ - bool final = c.xor_clause_inverted(); - for (uint k = 0; k != c.size(); k++ ) { - const lbool& val = solver.assigns[c[k].var()]; - if (val.isUndef()) return false; - final ^= val.getBool(); - } - return final; -} - -}; //NAMESPACE MINISAT diff --git a/src/sat/cryptominisat2/ClauseCleaner.h b/src/sat/cryptominisat2/ClauseCleaner.h index c099ae2..e69de29 100644 --- a/src/sat/cryptominisat2/ClauseCleaner.h +++ b/src/sat/cryptominisat2/ClauseCleaner.h @@ -1,79 +0,0 @@ -/*********************************************************************************** -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 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, 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(const bool nolimit = false); - bool satisfied(const Clause& c) const; - bool satisfied(const XorClause& c) const; - - private: - const bool cleanClause(XorClause& c); - const bool cleanClause(Clause& c); - - uint lastNumUnitarySat[6]; - uint lastNumUnitaryClean[6]; - - Solver& solver; -}; - -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 96855d7..e69de29 100644 --- a/src/sat/cryptominisat2/Conglomerate.cpp +++ b/src/sat/cryptominisat2/Conglomerate.cpp @@ -1,526 +0,0 @@ -/*********************************************************************************** -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 "Conglomerate.h" -#include "VarReplacer.h" -#include "ClauseCleaner.h" - -#include -#include -#include -#include "time_mem.h" -#include -using std::make_pair; - -//#define VERBOSE_DEBUG - -#ifdef VERBOSE_DEBUG -#include -using std::cout; -using std::endl; -#endif - -namespace MINISAT -{ -using namespace MINISAT; - -Conglomerate::Conglomerate(Solver& _solver) : - found(0) - , solver(_solver) -{} - -Conglomerate::~Conglomerate() -{ - for(uint i = 0; i < calcAtFinish.size(); i++) - free(calcAtFinish[i]); -} - -void Conglomerate::blockVars() -{ - 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 (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 = 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 = 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()]) - varToXor[a->var()].push_back(make_pair(*it, i)); - } - } -} - -void Conglomerate::removeVar(const Var var) -{ - solver.activity[var] = 0.0; - solver.order_heap.update(var); - removedVars[var] = true; - if (solver.decision_var[var]) { - madeVarNonDecision.push(var); - solver.setDecisionVar(var, false); - } - 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) { - 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)); - finder->second.erase(it); - } - } - } -} - -const bool Conglomerate::heuleProcessFull() -{ - #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 - - double time = cpuTime(); - found = 0; - uint32_t origNumClauses = solver.xorclauses.size(); - - 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()); - - 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(); - 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]) { - varToXor.erase(it); - continue; - } - - if (clauseSet.size() == 0) { - removeVar(var); - varToXor.erase(it); - continue; - } - - 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& firstXorClause = *(clauseSet[0].first); - bool first_inverted = !firstXorClause.xor_clause_inverted(); - removeVar(var); - - #ifdef VERBOSE_DEBUG - cout << "--- New conglomerate set ---" << endl; - cout << "- Removing: "; - firstXorClause.plainPrint(); - cout << "Adding var " << var+1 << " to calcAtFinish" << endl; - #endif - - 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 < clauseSet.size(); i++) { - XorClause& thisXorClause = *clauseSet[i].first; - #ifdef VERBOSE_DEBUG - cout << "- Removing: "; - thisXorClause.plainPrint(); - #endif - - 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(newSet[i], inverted, old_group)) - return false; - assert(newSet.size() == clauseSet.size()); - } - - varToXor.erase(it); - } - - return (solver.ok = (solver.propagate() == NULL)); -} - -bool Conglomerate::dealWithNewClause(vector& ps, const bool inverted, const uint old_group) -{ - switch(ps.size()) { - case 0: { - #ifdef VERBOSE_DEBUG - cout << "--> xor is 0-long" << endl; - #endif - - if (!inverted) { - solver.ok = false; - return false; - } - break; - } - case 1: { - #ifdef VERBOSE_DEBUG - cout << "--> xor is 1-long, attempting to set variable " << ps[0].var()+1 << endl; - #endif - - if (solver.assigns[ps[0].var()] == l_Undef) { - assert(solver.decisionLevel() == 0); - blocked[ps[0].var()] = true; - 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" << endl; - XorClause* newX = XorClause_new(ps, inverted, old_group); - newX->plainPrint(); - free(newX); - #endif - - 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; - } - - default: { - XorClause* newX = XorClause_new(ps, inverted, old_group); - - #ifdef VERBOSE_DEBUG - cout << "- Adding: "; - newX->plainPrint(); - #endif - - solver.xorclauses.push(newX); - toRemove.push_back(false); - 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, (uint32_t)(toRemove.size()-1))); - } - break; - } - } - - return true; -} - -void Conglomerate::clearDouble(vector& ps) const -{ - std::sort(ps.begin(), ps.end()); - Lit p; - 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 - ps[j++] = p = ps[i]; - } - ps.resize(ps.size() - (i - j)); -} - -void Conglomerate::clearToRemove() -{ - assert(toRemove.size() == solver.xorclauses.size()); - - XorClause **a = solver.xorclauses.getData(); - XorClause **r = a; - XorClause **end = a + solver.xorclauses.size(); - for (uint i = 0; r != end; i++) { - if (!toRemove[i]) - *a++ = *r++; - else { - r++; - } - } - solver.xorclauses.shrink(r-a); -} - -void Conglomerate::clearLearntsFromToRemove() -{ - Clause **a = solver.learnts.getData(); - Clause **r = a; - Clause **end = a + solver.learnts.size(); - for (; r != end;) { - const Clause& c = **r; - bool inside = false; - if (!solver.locked(c)) { - for (uint i = 0; i < c.size(); i++) { - if (removedVars[c[i].var()]) { - inside = true; - break; - } - } - } - if (!inside) - *a++ = *r++; - else { - solver.removeClause(**r); - r++; - } - } - solver.learnts.shrink(r-a); -} - -void Conglomerate::extendModel(Solver& solver2) -{ - #ifdef VERBOSE_DEBUG - cout << "Executing doCalcAtFinish" << endl; - #endif - - vec ps; - for (int i = (int)(calcAtFinish.size())-1; i >= 0; i--) { - XorClause& c = *calcAtFinish[i]; - assert(c.size() > 2); - - ps.clear(); - for (Lit *l = c.getData(), *end = c.getDataEnd(); l != end; l++) { - ps.push(l->unsign()); - } - - solver2.addXorClause(ps, c.xor_clause_inverted(), c.getGroup()); - assert(solver2.ok); - } -} - -const bool Conglomerate::addRemovedClauses() -{ - #ifdef VERBOSE_DEBUG - cout << "Executing addRemovedClauses" << endl; - #endif - - for(XorClause **it = calcAtFinish.getData(), **end = calcAtFinish.getDataEnd(); it != end; it++) - { - XorClause& c = **it; - #ifdef VERBOSE_DEBUG - cout << "readding already removed (conglomerated) clause: "; - c.plainPrint(); - #endif - - for(Lit *l = c.getData(), *end2 = c.getDataEnd(); l != end2 ; l++) - *l = l->unsign(); - - FILE* backup_libraryCNFfile = solver.libraryCNFFile; - solver.libraryCNFFile = NULL; - if (!solver.addXorClause(c, c.xor_clause_inverted(), c.getGroup())) { - for (;it != end; it++) free(*it); - calcAtFinish.clear(); - return false; - } - solver.libraryCNFFile = backup_libraryCNFfile; - free(&c); - } - calcAtFinish.clear(); - - std::fill(removedVars.getData(), removedVars.getDataEnd(), false); - for (Var *v = madeVarNonDecision.getData(), *end = madeVarNonDecision.getDataEnd(); v != end; v++) { - solver.setDecisionVar(*v, true); - } - madeVarNonDecision.clear(); - - return true; -} - -}; //NAMESPACE MINISAT diff --git a/src/sat/cryptominisat2/Conglomerate.h b/src/sat/cryptominisat2/Conglomerate.h index 50972d4..e69de29 100644 --- a/src/sat/cryptominisat2/Conglomerate.h +++ b/src/sat/cryptominisat2/Conglomerate.h @@ -1,125 +0,0 @@ -/*********************************************************************************** -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 CONGLOMERATE_H -#define CONGLOMERATE_H - -#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; - -namespace MINISAT -{ -using namespace MINISAT; - -class Solver; - -class Conglomerate -{ -public: - Conglomerate(Solver& solver); - ~Conglomerate(); - const bool conglomerateXorsFull(); - const bool heuleProcessFull(); - const bool addRemovedClauses(); ///& getCalcAtFinish() const; - vec& getCalcAtFinish(); - const vec& getRemovedVars() const; - const bool needCalcAtFinish() const; - - void newVar(); - -private: - - 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(vector& ps) const; - void clearToRemove(); - void clearLearntsFromToRemove(); - bool dealWithNewClause(vector& ps, const bool inverted, const uint old_group); - - typedef map > > varToXorMap; - varToXorMap varToXor; - vector blocked; - vector toRemove; - - vec removedVars; - vec madeVarNonDecision; - - vec calcAtFinish; - uint found; - - Solver& solver; -}; - -inline void Conglomerate::newVar() -{ - removedVars.push(false); -} - -inline const vec& Conglomerate::getRemovedVars() const -{ - return removedVars; -} - -inline const vec& Conglomerate::getCalcAtFinish() const -{ - return calcAtFinish; -} - -inline vec& Conglomerate::getCalcAtFinish() -{ - return calcAtFinish; -} - -inline const bool Conglomerate::needCalcAtFinish() const -{ - return calcAtFinish.size(); -} - -}; //NAMESPACE MINISAT - -#endif //CONGLOMERATE_H diff --git a/src/sat/cryptominisat2/DoublePackedRow.h b/src/sat/cryptominisat2/DoublePackedRow.h index 50cfd8a..e69de29 100644 --- a/src/sat/cryptominisat2/DoublePackedRow.h +++ b/src/sat/cryptominisat2/DoublePackedRow.h @@ -1,173 +0,0 @@ -/*********************************************************************************** -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 index 3d0e86f..e69de29 100644 --- a/src/sat/cryptominisat2/FailedVarSearcher.cpp +++ b/src/sat/cryptominisat2/FailedVarSearcher.cpp @@ -1,412 +0,0 @@ -/*********************************************************************************** -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" -#include "ClauseCleaner.h" - -#ifdef _MSC_VER -#define __builtin_prefetch(a,b,c) -#endif //_MSC_VER - -//#define VERBOSE_DEUBUG - -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), 0, 0); - - 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); - } - } - - #ifdef VERBOSE_DEUBUG - if (num != 2) { - std::cout << "Num:" << num << std::endl; - c.plainPrint(); - } - #endif - - 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(solver.activity.size()); - std::copy(solver.activity.getData(), solver.activity.getDataEnd(), backup_activity.getData()); - uint32_t 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.03) 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(), 0); - BitArray propValue; - propValue.resize(solver.nVars(), 0); - vector > bothSame; - - //For calculating how many variables have really been set - uint32_t origTrailSize = solver.trail.size(); - - //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) { - solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses); - addFromSolver(solver.xorclauses); - } - xorClauseTouched.resize(solver.xorclauses.size(), 0); - - 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 = investigateXor.getDataEnd(); 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() > (int)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 = solver.trail.size() - origTrailSize; - - 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 index 79ed82e..e69de29 100644 --- a/src/sat/cryptominisat2/FailedVarSearcher.h +++ b/src/sat/cryptominisat2/FailedVarSearcher.h @@ -1,90 +0,0 @@ -/*********************************************************************************** -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 836dc6b..e69de29 100644 --- a/src/sat/cryptominisat2/FindUndef.cpp +++ b/src/sat/cryptominisat2/FindUndef.cpp @@ -1,176 +0,0 @@ -/*********************************************************************************** -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 "FindUndef.h" - -#include "Solver.h" -#include "VarReplacer.h" -#include - -namespace MINISAT -{ -using namespace MINISAT; - -FindUndef::FindUndef(Solver& _solver) : - solver(_solver) - , isPotentialSum(0) -{ -} - -void FindUndef::fillPotential() -{ - int trail = solver.decisionLevel()-1; - - while(trail > 0) { - assert(trail < (int)solver.trail_lim.size()); - uint at = solver.trail_lim[trail]; - - assert(at > 0); - Var v = solver.trail[at].var(); - if (solver.assigns[v] != l_Undef) { - isPotential[v] = true; - isPotentialSum++; - } - - trail--; - } - - 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(!solver.value(*l).isUndef()); - } - } - - vector replacingVars = solver.varReplacer->getReplacingVars(); - for (Var *it = &replacingVars[0], *end = it + replacingVars.size(); it != end; it++) { - if (isPotential[*it]) { - isPotential[*it] = false; - isPotentialSum--; - } - } -} - -void FindUndef::unboundIsPotentials() -{ - for (uint i = 0; i < isPotential.size(); i++) - if (isPotential[i]) - 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); - - uint32_t maximum = 0; - Var v; - for (uint i = 0; i < isPotential.size(); i++) { - if (isPotential[i] && satisfies[i] >= maximum) { - maximum = satisfies[i]; - v = i; - } - } - - isPotential[v] = false; - isPotentialSum--; - - std::fill(satisfies.begin(), satisfies.end(), 0); - } - - unboundIsPotentials(); - moveBinFromNormal(); - - return isPotentialSum; -} - -bool FindUndef::updateTables() -{ - bool allSat = true; - - uint i = 0; - 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_Undef; - uint numTrue = 0; - for (Lit *l = c.getData(), *end = l + c.size(); l != end; l++) { - if (solver.value(*l) == l_True) { - if (!isPotential[l->var()]) { - dontLookAtClause[i] = true; - definitelyOK = true; - break; - } else { - numTrue ++; - v = l->var(); - } - } - } - if (definitelyOK) - 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 (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 d3612ac..e69de29 100644 --- a/src/sat/cryptominisat2/FindUndef.h +++ b/src/sat/cryptominisat2/FindUndef.h @@ -1,59 +0,0 @@ -/*********************************************************************************** -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 FINDUNDEF_H -#define FINDUNDEF_H - -#ifdef _MSC_VER -#include -#else -#include -#endif //_MSC_VER -#include -using std::vector; - -#include "Solver.h" - -namespace MINISAT -{ -using namespace MINISAT; - -class FindUndef { - public: - FindUndef(Solver& _solver); - const uint unRoll(); - - private: - Solver& solver; - - void moveBinToNormal(); - void moveBinFromNormal(); - bool updateTables(); - void fillPotential(); - void unboundIsPotentials(); - - vector dontLookAtClause; //If set to TRUE, then that clause already has only 1 lit that is true, so it can be skipped during updateFixNeed() - vector satisfies; - vector isPotential; - uint32_t isPotentialSum; - uint32_t binPosition; - -}; - -}; //NAMESPACE MINISAT - -#endif // \ No newline at end of file diff --git a/src/sat/cryptominisat2/Gaussian.cpp b/src/sat/cryptominisat2/Gaussian.cpp index e7c31ff..e69de29 100644 --- a/src/sat/cryptominisat2/Gaussian.cpp +++ b/src/sat/cryptominisat2/Gaussian.cpp @@ -1,1160 +0,0 @@ -/*********************************************************************************** -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 "Gaussian.h" - -#include -#include -#include "Clause.h" -#include -#include "ClauseCleaner.h" - -using std::ostream; -using std::cout; -using std::endl; - -#ifdef VERBOSE_DEBUG -#include -#endif - -namespace MINISAT -{ -using namespace MINISAT; - -ostream& operator << (ostream& os, const vec& v) -{ - for (uint32_t i = 0; i != v.size(); i++) { - if (v[i].sign()) os << "-"; - os << v[i].var()+1 << " "; - } - - return os; -} - -Gaussian::Gaussian(Solver& _solver, const GaussianConfig& _config, const uint _matrix_no, const vector& _xorclauses) : - solver(_solver) - , config(_config) - , matrix_no(_matrix_no) - , xorclauses(_xorclauses) - , messed_matrix_vars_since_reversal(true) - , gauss_last_level(0) - , disabled(false) - , useful_prop(0) - , useful_confl(0) - , called(0) -{ -} - -Gaussian::~Gaussian() -{ - for (uint i = 0; i < clauses_toclear.size(); i++) - clauseFree(clauses_toclear[i].first); -} - -inline void Gaussian::set_matrixset_to_cur() -{ - uint level = solver.decisionLevel() / config.only_nth_gauss_save; - assert(level <= matrix_sets.size()); - - if (level == matrix_sets.size()) - matrix_sets.push_back(cur_matrixset); - else - matrix_sets[level] = cur_matrixset; -} - -llbool Gaussian::full_init() -{ - if (!should_init()) return l_Nothing; - reset_stats(); - - bool do_again_gauss = true; - 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); - switch (g) { - case unit_conflict: - case conflict: - return l_False; - case unit_propagation: - case propagation: - do_again_gauss=true; - if (solver.propagate() != NULL) return l_False; - break; - case nothing: - break; - } - } - - return l_Nothing; -} - -void Gaussian::init() -{ - assert(solver.decisionLevel() == 0); - - fill_matrix(cur_matrixset); - if (!cur_matrixset.num_rows || !cur_matrixset.num_cols) { - disabled = true; - badlevel = 0; - return; - } - - matrix_sets.clear(); - matrix_sets.push_back(cur_matrixset); - gauss_last_level = solver.trail.size(); - messed_matrix_vars_since_reversal = false; - badlevel = UINT_MAX; - - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")Gaussian init finished." << endl; - #endif -} - -uint Gaussian::select_columnorder(vector& var_to_col, matrixset& origMat) -{ - var_to_col.resize(solver.nVars(), unassigned_col); - - uint num_xorclauses = 0; - for (uint32_t i = 0; i != xorclauses.size(); i++) { - 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; - } - } - - uint largest_used_var = 0; - for (uint i = 0; i < var_to_col.size(); i++) - if (var_to_col[i] != unassigned_col) - largest_used_var = i; - var_to_col.resize(largest_used_var + 1); - - var_is_in.resize(var_to_col.size(), 0); - origMat.var_is_set.resize(var_to_col.size(), 0); - - origMat.col_to_var.clear(); - Heap order_heap(solver.order_heap); - while (!order_heap.empty()) - { - Var v = order_heap.removeMin(); - - if (var_to_col[v] == 1) { - #ifdef DEBUG_GAUSS - vector::iterator it = - std::find(origMat.col_to_var.begin(), origMat.col_to_var.end(), v); - assert(it == origMat.col_to_var.end()); - #endif - - origMat.col_to_var.push_back(v); - var_to_col[v] = origMat.col_to_var.size()-1; - var_is_in.setBit(v); - } - } - - //for the ones that were not in the order_heap, but are marked in var_to_col - for (uint v = 0; v != var_to_col.size(); v++) { - if (var_to_col[v] == unassigned_col - 1) { - origMat.col_to_var.push_back(v); - var_to_col[v] = origMat.col_to_var.size() -1; - var_is_in.setBit(v); - } - } - - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")col_to_var:"; - std::copy(origMat.col_to_var.begin(), origMat.col_to_var.end(), std::ostream_iterator(cout, ",")); - cout << endl; - #endif - - return num_xorclauses; -} - -void Gaussian::fill_matrix(matrixset& origMat) -{ - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")Filling matrix" << endl; - #endif - - vector var_to_col; - origMat.num_rows = select_columnorder(var_to_col, origMat); - origMat.num_cols = origMat.col_to_var.size(); - col_to_var_original = origMat.col_to_var; - changed_rows.resize(origMat.num_rows); - memset(&changed_rows[0], 0, sizeof(char)*changed_rows.size()); - - origMat.last_one_in_col.resize(origMat.num_cols); - std::fill(origMat.last_one_in_col.begin(), origMat.last_one_in_col.end(), origMat.num_rows); - origMat.first_one_in_row.resize(origMat.num_rows); - - origMat.removeable_cols = 0; - origMat.least_column_changed = -1; - origMat.matrix.resize(origMat.num_rows, origMat.num_cols); - - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")matrix size:" << origMat.num_rows << "," << origMat.num_cols << endl; - #endif - - uint matrix_row = 0; - for (uint32_t i = 0; i != xorclauses.size(); i++) { - const XorClause& c = *xorclauses[i]; - - 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); -} - -void Gaussian::update_matrix_col(matrixset& m, const Var var, const uint col) -{ - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")Updating matrix var " << var+1 << " (col " << col << ", m.last_one_in_col[col]: " << m.last_one_in_col[col] << ")" << endl; - cout << "m.num_rows:" << m.num_rows << endl; - #endif - - #ifdef DEBUG_GAUSS - assert(col < m.num_cols); - #endif - - m.least_column_changed = std::min(m.least_column_changed, (int)col); - PackedMatrix::iterator this_row = m.matrix.beginMatrix(); - uint row_num = 0; - - if (solver.assigns[var].getBool()) { - for (uint end = m.last_one_in_col[col]; row_num != end; ++this_row, row_num++) { - if ((*this_row)[col]) { - changed_rows[row_num] = true; - (*this_row).invert_is_true(); - (*this_row).clearBit(col); - } - } - } else { - for (uint end = m.last_one_in_col[col]; row_num != end; ++this_row, row_num++) { - if ((*this_row)[col]) { - changed_rows[row_num] = true; - (*this_row).clearBit(col); - } - } - } - - #ifdef DEBUG_GAUSS - bool c = false; - for(PackedMatrix::iterator r = m.matrix.beginMatrix(), end = r + m.matrix.getSize(); r != end; ++r) - c |= (*r)[col]; - assert(!c); - #endif - - m.removeable_cols++; - m.col_to_var[col] = unassigned_var; - m.var_is_set.setBit(var); -} - -void Gaussian::update_matrix_by_col_all(matrixset& m) -{ - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")Updating matrix." << endl; - print_matrix(m); - uint num_updated = 0; - #endif - - #ifdef DEBUG_GAUSS - assert(nothing_to_propagate(cur_matrixset)); - assert(solver.decisionLevel() == 0 || check_last_one_in_cols(m)); - #endif - - memset(&changed_rows[0], 0, sizeof(char)*changed_rows.size()); - - uint last = 0; - uint col = 0; - for (const Var *it = &m.col_to_var[0], *end = it + m.num_cols; it != end; col++, it++) { - if (*it != unassigned_var && solver.assigns[*it].isDef()) { - update_matrix_col(m, *it, col); - last++; - #ifdef VERBOSE_DEBUG - num_updated++; - #endif - } else - last = 0; - } - m.num_cols -= last; - - #ifdef DEBUG_GAUSS - check_matrix_against_varset(m.matrix, m); - #endif - - #ifdef VERBOSE_DEBUG - cout << "Matrix update finished, updated " << num_updated << " cols" << endl; - print_matrix(m); - #endif - - /*cout << "num_rows:" << m.num_rows; - cout << " num_rows diff:" << origMat.num_rows - m.num_rows << endl; - cout << "num_cols:" << col_to_var_original.size(); - cout << " num_cols diff:" << col_to_var_original.size() - m.col_to_var.size() << endl; - cout << "removeable cols:" << m.removeable_cols << endl;*/ -} - -inline void Gaussian::update_last_one_in_col(matrixset& m) -{ - for (uint16_t* i = &m.last_one_in_col[0]+m.last_one_in_col.size()-1, *end = &m.last_one_in_col[0]-1; i != end && *i >= m.num_rows; i--) - *i = m.num_rows; -} - -Gaussian::gaussian_ret Gaussian::gaussian(Clause*& confl) -{ - if (solver.decisionLevel() >= badlevel) - return nothing; - - if (messed_matrix_vars_since_reversal) { - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")matrix needs copy before update" << endl; - #endif - - const uint level = solver.decisionLevel() / config.only_nth_gauss_save; - assert(level < matrix_sets.size()); - cur_matrixset = matrix_sets[level]; - } - update_last_one_in_col(cur_matrixset); - update_matrix_by_col_all(cur_matrixset); - - messed_matrix_vars_since_reversal = false; - gauss_last_level = solver.trail.size(); - badlevel = UINT_MAX; - - propagatable_rows.clear(); - uint conflict_row = UINT_MAX; - uint last_row = eliminate(cur_matrixset, conflict_row); - #ifdef DEBUG_GAUSS - check_matrix_against_varset(cur_matrixset.matrix, cur_matrixset); - #endif - - gaussian_ret ret; - //There is no early abort, so this is unneeded - /*if (conflict_row != UINT_MAX) { - uint maxlevel = UINT_MAX; - uint size = UINT_MAX; - uint best_row = UINT_MAX; - analyse_confl(cur_matrixset, conflict_row, maxlevel, size, best_row); - ret = handle_matrix_confl(confl, cur_matrixset, size, maxlevel, best_row); - } else {*/ - ret = handle_matrix_prop_and_confl(cur_matrixset, last_row, confl); - //} - #ifdef DEBUG_GAUSS - assert(ret == conflict || nothing_to_propagate(cur_matrixset)); - #endif - - if (!cur_matrixset.num_cols || !cur_matrixset.num_rows) { - badlevel = solver.decisionLevel(); - return nothing; - } - - if (ret == nothing && - solver.decisionLevel() % config.only_nth_gauss_save == 0) - set_matrixset_to_cur(); - - #ifdef VERBOSE_DEBUG - if (ret == nothing) - cout << "(" << matrix_no << ")Useless. "; - else - cout << "(" << matrix_no << ")Useful. "; - cout << "(" << matrix_no << ")Useful prop in " << ((double)useful_prop/(double)called)*100.0 << "%" << endl; - cout << "(" << matrix_no << ")Useful confl in " << ((double)useful_confl/(double)called)*100.0 << "%" << endl; - #endif - - return ret; -} - -uint Gaussian::eliminate(matrixset& m, uint& conflict_row) -{ - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")"; - cout << "Starting elimination" << endl; - cout << "m.least_column_changed:" << m.least_column_changed << endl; - print_last_one_in_cols(m); - - uint number_of_row_additions = 0; - uint no_exchanged = 0; - #endif - - if (m.least_column_changed == INT_MAX) { - #ifdef VERBOSE_DEBUG - cout << "Nothing to eliminate" << endl; - #endif - - return m.num_rows; - } - - - #ifdef DEBUG_GAUSS - assert(solver.decisionLevel() == 0 || check_last_one_in_cols(m)); - #endif - - uint i = 0; - uint j = m.least_column_changed + 1; - PackedMatrix::iterator beginIt = m.matrix.beginMatrix(); - PackedMatrix::iterator rowIt = m.matrix.beginMatrix(); - - #ifdef DEBUG_GAUSS - check_first_one_in_row(m, j); - #endif - - if (j) { - uint16_t until = std::min(m.last_one_in_col[m.least_column_changed] - 1, (int)m.num_rows); - if (j-1 > m.first_one_in_row[m.num_rows-1]) - until = m.num_rows; - for (;i != until; i++, ++rowIt) if (changed_rows[i] && (*rowIt).popcnt_is_one(m.first_one_in_row[i])) - propagatable_rows.push(i); - } - - #ifdef VERBOSE_DEBUG - cout << "At while() start: i,j = " << i << ", " << j << endl; - cout << "num_rows:" << m.num_rows << " num_cols:" << m.num_cols << endl; - #endif - - if (j > m.num_cols) { - #ifdef VERBOSE_DEBUG - cout << "Going straight to finish" << endl; - #endif - goto finish; - } - - #ifdef DEBUG_GAUSS - assert(i <= m.num_rows && j <= m.num_cols); - #endif - - while (i != m.num_rows && j != m.num_cols) { - //Find pivot in column j, starting in row i: - - if (m.col_to_var[j] == unassigned_var) { - j++; - continue; - } - - PackedMatrix::iterator this_matrix_row = rowIt; - PackedMatrix::iterator end = beginIt + m.last_one_in_col[j]; - for (; this_matrix_row != end; ++this_matrix_row) { - if ((*this_matrix_row)[j]) - break; - } - - if (this_matrix_row != end) { - - //swap rows i and maxi, but do not change the value of i; - if (this_matrix_row != rowIt) { - #ifdef VERBOSE_DEBUG - no_exchanged++; - #endif - - //Would early abort, but would not find the best conflict (and would be expensive) - //if (matrix_row_i.is_true() && matrix_row_i.isZero()) { - // conflict_row = i; - // return 0; - //} - (*rowIt).swapBoth(*this_matrix_row); - } - #ifdef DEBUG_GAUSS - assert(m.matrix.getMatrixAt(i).popcnt(j) == m.matrix.getMatrixAt(i).popcnt()); - assert(m.matrix.getMatrixAt(i)[j]); - #endif - - if ((*rowIt).popcnt_is_one(j)) - propagatable_rows.push(i); - - //Now A[i,j] will contain the old value of A[maxi,j]; - ++this_matrix_row; - for (; this_matrix_row != end; ++this_matrix_row) if ((*this_matrix_row)[j]) { - //subtract row i from row u; - //Now A[u,j] will be 0, since A[u,j] - A[i,j] = A[u,j] -1 = 0. - #ifdef VERBOSE_DEBUG - number_of_row_additions++; - #endif - - (*this_matrix_row).xorBoth(*rowIt); - //Would early abort, but would not find the best conflict (and would be expensive) - //if (it->is_true() &&it->isZero()) { - // conflict_row = i2; - // return 0; - //} - } - m.first_one_in_row[i] = j; - i++; - ++rowIt; - m.last_one_in_col[j] = i; - } else { - m.first_one_in_row[i] = j; - m.last_one_in_col[j] = i + 1; - } - j++; - } - - finish: - - m.least_column_changed = INT_MAX; - - #ifdef VERBOSE_DEBUG - cout << "Finished elimination" << endl; - cout << "Returning with i,j:" << i << ", " << j << "(" << m.num_rows << ", " << m.num_cols << ")" << endl; - print_matrix(m); - print_last_one_in_cols(m); - cout << "(" << matrix_no << ")Exchanged:" << no_exchanged << " row additions:" << number_of_row_additions << endl; - #endif - - #ifdef DEBUG_GAUSS - assert(check_last_one_in_cols(m)); - uint row = 0; - uint col = 0; - for (; col < m.num_cols && row < m.num_rows && row < i ; col++) { - assert(m.matrix.getMatrixAt(row).popcnt() == m.matrix.getMatrixAt(row).popcnt(col)); - assert(!(m.col_to_var[col] == unassigned_var && m.matrix.getMatrixAt(row)[col])); - if (m.col_to_var[col] == unassigned_var || !m.matrix.getMatrixAt(row)[col]) { - #ifdef VERBOSE_DEBUG - cout << "row:" << row << " col:" << col << " m.last_one_in_col[col]-1: " << m.last_one_in_col[col]-1 << endl; - #endif - assert(m.col_to_var[col] == unassigned_var || std::min((uint16_t)(m.last_one_in_col[col]-1), m.num_rows) == row); - continue; - } - row++; - } - #endif - - return i; -} - -Gaussian::gaussian_ret Gaussian::handle_matrix_confl(Clause*& confl, const matrixset& m, const uint size, const uint maxlevel, const uint best_row) -{ - assert(best_row != UINT_MAX); - - m.matrix.getVarsetAt(best_row).fill(tmp_clause, solver.assigns, col_to_var_original); - 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->getGroup(), "learnt gauss clause"); - #endif - - if (cla.size() <= 1) - return unit_conflict; - - assert(cla.size() >= 2); - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")Found conflict:"; - cla.plainPrint(); - #endif - - if (maxlevel != solver.decisionLevel()) { - #ifdef STATS_NEEDED - if (solver.dynamic_behaviour_analysis) - solver.logger.conflict(Logger::gauss_confl_type, maxlevel, confl->getGroup(), *confl); - #endif - solver.cancelUntil(maxlevel); - } - const uint curr_dec_level = solver.decisionLevel(); - assert(maxlevel == curr_dec_level); - - uint maxsublevel = 0; - uint maxsublevel_at = UINT_MAX; - for (uint i = 0, size = cla.size(); i != size; i++) if (solver.level[cla[i].var()] == curr_dec_level) { - uint tmp = find_sublevel(cla[i].var()); - if (tmp >= maxsublevel) { - maxsublevel = tmp; - maxsublevel_at = i; - } - } - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ") || Sublevel of confl: " << maxsublevel << " (due to var:" << cla[maxsublevel_at].var()-1 << ")" << endl; - #endif - - Lit tmp(cla[maxsublevel_at]); - cla[maxsublevel_at] = cla[1]; - cla[1] = tmp; - - cancel_until_sublevel(maxsublevel+1); - messed_matrix_vars_since_reversal = true; - return conflict; -} - -Gaussian::gaussian_ret Gaussian::handle_matrix_prop_and_confl(matrixset& m, uint last_row, Clause*& confl) -{ - uint maxlevel = UINT_MAX; - uint size = UINT_MAX; - uint best_row = UINT_MAX; - - for (uint row = last_row; row != m.num_rows; row++) { - #ifdef DEBUG_GAUSS - assert(m.matrix.getMatrixAt(row).isZero()); - #endif - if (m.matrix.getMatrixAt(row).is_true()) - analyse_confl(m, row, maxlevel, size, best_row); - } - - if (maxlevel != UINT_MAX) - return handle_matrix_confl(confl, m, size, maxlevel, best_row); - - #ifdef DEBUG_GAUSS - assert(check_no_conflict(m)); - assert(last_row == 0 || !m.matrix.getMatrixAt(last_row-1).isZero()); - #endif - - #ifdef VERBOSE_DEBUG - cout << "Resizing matrix to num_rows = " << last_row << endl; - #endif - m.num_rows = last_row; - m.matrix.resizeNumRows(m.num_rows); - - gaussian_ret ret = nothing; - - uint num_props = 0; - for (const uint* prop_row = propagatable_rows.getData(), *end = prop_row + propagatable_rows.size(); prop_row != end; prop_row++ ) { - //this is a "000..1..0000000X" row. I.e. it indicates a propagation - ret = handle_matrix_prop(m, *prop_row); - num_props++; - if (ret == unit_propagation) { - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")Unit prop! Breaking from prop examination" << endl; - #endif - return unit_propagation; - } - } - #ifdef VERBOSE_DEBUG - if (num_props > 0) cout << "(" << matrix_no << ")Number of props during gauss:" << num_props << endl; - #endif - - return ret; -} - -uint Gaussian::find_sublevel(const Var v) const -{ - for (int i = solver.trail.size()-1; i >= 0; i --) - if (solver.trail[i].var() == v) return i; - - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")Oooops! Var " << v+1 << " does not have a sublevel!! (so it must be undefined)" << endl; - #endif - - assert(false); - return 0; -} - -void Gaussian::cancel_until_sublevel(const uint sublevel) -{ - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")Canceling until sublevel " << sublevel << endl; - #endif - - 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--) { - Var var = solver.trail[level].var(); - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")Canceling var " << var+1 << endl; - #endif - - solver.assigns[var] = l_Undef; - solver.insertVarOrder(var); - } - solver.trail.shrink(solver.trail.size() - sublevel); - - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")Canceling sublevel finished." << endl; - #endif -} - -void Gaussian::analyse_confl(const matrixset& m, const uint row, uint& maxlevel, uint& size, uint& best_row) const -{ - assert(row < m.num_rows); - - //this is a "000...00000001" row. I.e. it indicates we are on the wrong branch - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")matrix conflict found!" << endl; - cout << "(" << matrix_no << ")conflict clause's vars: "; - print_matrix_row_with_assigns(m.matrix.getVarsetAt(row)); - cout << endl; - - cout << "(" << matrix_no << ")corresponding matrix's row (should be empty): "; - print_matrix_row(m.matrix.getMatrixAt(row)); - cout << endl; - #endif - - uint this_maxlevel = 0; - unsigned long int var = 0; - uint this_size = 0; - while (true) { - var = m.matrix.getVarsetAt(row).scan(var); - if (var == ULONG_MAX) break; - - const Var real_var = col_to_var_original[var]; - assert(real_var < solver.nVars()); - - if (solver.level[real_var] > this_maxlevel) - this_maxlevel = solver.level[real_var]; - var++; - this_size++; - } - - //the maximum of all lit's level must be lower than the max. level of the current best clause (or this clause must be either empty or unit clause) - if (!( - (this_maxlevel < maxlevel) - || (this_maxlevel == maxlevel && this_size < size) - || (this_size <= 1) - )) { - assert(maxlevel != UINT_MAX); - - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")Other found conflict just as good or better."; - cout << "(" << matrix_no << ") || Old maxlevel:" << maxlevel << " new maxlevel:" << this_maxlevel; - cout << "(" << matrix_no << ") || Old size:" << size << " new size:" << this_size << endl; - //assert(!(maxlevel != UINT_MAX && maxlevel != this_maxlevel)); //NOTE: only holds if gauss is executed at each level - #endif - - return; - } - - - #ifdef VERBOSE_DEBUG - if (maxlevel != UINT_MAX) - cout << "(" << matrix_no << ")Better conflict found."; - else - cout << "(" << matrix_no << ")Found a possible conflict."; - - cout << "(" << matrix_no << ") || Old maxlevel:" << maxlevel << " new maxlevel:" << this_maxlevel; - cout << "(" << matrix_no << ") || Old size:" << size << " new size:" << this_size << endl; - #endif - - maxlevel = this_maxlevel; - size = this_size; - best_row = row; -} - -Gaussian::gaussian_ret Gaussian::handle_matrix_prop(matrixset& m, const uint row) -{ - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")matrix prop found!" << endl; - cout << m.matrix.getMatrixAt(row) << endl; - cout << "(" << matrix_no << ")matrix row:"; - print_matrix_row(m.matrix.getMatrixAt(row)); - cout << endl; - #endif - - m.matrix.getVarsetAt(row).fill(tmp_clause, solver.assigns, col_to_var_original); - Clause& cla = *(Clause*)XorClause_new(tmp_clause, false, solver.learnt_clause_group++); - #ifdef VERBOSE_DEBUG - cout << "(" << matrix_no << ")matrix prop clause: "; - cla.plainPrint(); - cout << endl; - #endif - - assert(m.matrix.getMatrixAt(row).is_true() == !cla[0].sign()); - assert(solver.assigns[cla[0].var()].isUndef()); - if (cla.size() == 1) { - const Lit lit = cla[0]; - - solver.cancelUntil(0); - solver.uncheckedEnqueue(lit); - free(&cla); - return unit_propagation; - } - - 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.getGroup(), "gauss prop clause"); - #endif - solver.uncheckedEnqueue(cla[0], &cla); - - return propagation; -} - -void Gaussian::disable_if_necessary() -{ - if (//nof_conflicts >= 0 - //&& conflictC >= nof_conflicts/8 - !config.dontDisable - && called > 50 - && useful_confl*2+useful_prop < (uint)((double)called*0.05) ) - disabled = true; -} - -llbool Gaussian::find_truths(vec& learnt_clause, int& conflictC) -{ - Clause* confl; - - disable_if_necessary(); - if (should_check_gauss(solver.decisionLevel(), solver.starts)) { - called++; - gaussian_ret g = gaussian(confl); - - switch (g) { - case conflict: { - useful_confl++; - llbool ret = solver.handle_conflict(learnt_clause, confl, conflictC, true); - clauseFree(confl); - - if (ret != l_Nothing) return ret; - return l_Continue; - } - case propagation: - case unit_propagation: - useful_prop++; - return l_Continue; - case unit_conflict: { - useful_confl++; - if (confl->size() == 0) { - free(confl); - return l_False; - } - - Lit lit = (*confl)[0]; - #ifdef STATS_NEEDED - if (solver.dynamic_behaviour_analysis) - solver.logger.conflict(Logger::gauss_confl_type, 0, confl->getGroup(), *confl); - #endif - - solver.cancelUntil(0); - - if (solver.assigns[lit.var()].isDef()) { - clauseFree(confl); - return l_False; - } - - solver.uncheckedEnqueue(lit); - - clauseFree(confl); - return l_Continue; - } - case nothing: - break; - } - } - - return l_Nothing; -} - -template -void Gaussian::print_matrix_row(const T& row) const -{ - unsigned long int var = 0; - while (true) { - var = row.scan(var); - if (var == ULONG_MAX) break; - - else cout << col_to_var_original[var]+1 << ", "; - var++; - } - cout << "final:" << row.is_true() << endl;; -} - -template -void Gaussian::print_matrix_row_with_assigns(const T& row) const -{ - unsigned long int col = 0; - while (true) { - col = row.scan(col); - if (col == ULONG_MAX) break; - - else { - Var var = col_to_var_original[col]; - cout << var+1 << "(" << lbool_to_string(solver.assigns[var]) << ")"; - cout << ", "; - } - col++; - } - if (!row.is_true()) cout << "xor_clause_inverted"; -} - -const string Gaussian::lbool_to_string(const lbool toprint) -{ - if (toprint == l_True) - return "true"; - if (toprint == l_False) - return "false"; - if (toprint == l_Undef) - return "undef"; - - assert(false); - return ""; -} - - -void Gaussian::print_stats() const -{ - if (called > 0) { - cout.setf(std::ios::fixed); - std::cout << " Gauss(" << matrix_no << ") useful"; - cout << " prop: " << std::setprecision(2) << std::setw(5) << ((double)useful_prop/(double)called)*100.0 << "% "; - cout << " confl: " << std::setprecision(2) << std::setw(5) << ((double)useful_confl/(double)called)*100.0 << "% "; - if (disabled) std::cout << "disabled"; - } else - std::cout << " Gauss(" << matrix_no << ") not called."; -} - -void Gaussian::print_matrix_stats() const -{ - cout << "matrix size: " << cur_matrixset.num_rows << " x " << cur_matrixset.num_cols << endl; -} - - -void Gaussian::reset_stats() -{ - useful_prop = 0; - useful_confl = 0; - called = 0; - disabled = false; -} - -bool Gaussian::check_no_conflict(matrixset& m) const -{ - uint row = 0; - for(PackedMatrix::iterator r = m.matrix.beginMatrix(), end = m.matrix.endMatrix(); r != end; ++r, ++row) { - if ((*r).is_true() && (*r).isZero()) { - cout << "Conflict at row " << row << endl; - return false; - } - } - return true; -} - -void Gaussian::print_matrix(matrixset& m) const -{ - uint row = 0; - for (PackedMatrix::iterator it = m.matrix.beginMatrix(); it != m.matrix.endMatrix(); ++it, row++) { - cout << *it << " -- row:" << row; - if (row >= m.num_rows) - cout << " (considered past the end)"; - cout << endl; - } -} - -void Gaussian::print_last_one_in_cols(matrixset& m) const -{ - for (uint i = 0; i < m.num_cols; i++) { - cout << "last_one_in_col[" << i << "]-1 = " << m.last_one_in_col[i]-1 << endl; - } -} - -const bool Gaussian::nothing_to_propagate(matrixset& m) const -{ - for(PackedMatrix::iterator r = m.matrix.beginMatrix(), end = m.matrix.endMatrix(); r != end; ++r) { - if ((*r).popcnt_is_one() - && solver.assigns[m.col_to_var[(*r).scan(0)]].isUndef()) - return false; - } - for(PackedMatrix::iterator r = m.matrix.beginMatrix(), end = m.matrix.endMatrix(); r != end; ++r) { - if ((*r).isZero() && (*r).is_true()) - return false; - } - return true; -} - -const bool Gaussian::check_last_one_in_cols(matrixset& m) const -{ - for(uint i = 0; i < m.num_cols; i++) { - const uint last = std::min(m.last_one_in_col[i] - 1, (int)m.num_rows); - uint real_last = 0; - uint i2 = 0; - for (PackedMatrix::iterator it = m.matrix.beginMatrix(); it != m.matrix.endMatrix(); ++it, i2++) { - if ((*it)[i]) - real_last = i2; - } - if (real_last > last) - return false; - } - - return true; -} - -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); - const PackedRow var_row = matrix.getVarsetAt(i); - - unsigned long int col = 0; - bool final = false; - while (true) { - col = var_row.scan(col); - if (col == ULONG_MAX) break; - - const Var var = col_to_var_original[col]; - assert(var < solver.nVars()); - - if (solver.assigns[var] == l_True) { - assert(!mat_row[col]); - assert(m.col_to_var[col] == unassigned_var); - assert(m.var_is_set[var]); - final = !final; - } else if (solver.assigns[var] == l_False) { - assert(!mat_row[col]); - assert(m.col_to_var[col] == unassigned_var); - assert(m.var_is_set[var]); - } else if (solver.assigns[var] == l_Undef) { - assert(m.col_to_var[col] != unassigned_var); - assert(!m.var_is_set[var]); - assert(mat_row[col]); - } else assert(false); - - col++; - } - if ((final^!mat_row.is_true()) != !var_row.is_true()) { - cout << "problem with row:"; print_matrix_row_with_assigns(var_row); cout << endl; - assert(false); - } - } -} - -const void Gaussian::check_first_one_in_row(matrixset& m, const uint j) -{ - if (j) { - uint16_t until2 = std::min(m.last_one_in_col[m.least_column_changed] - 1, (int)m.num_rows); - if (j-1 > m.first_one_in_row[m.num_rows-1]) { - until2 = m.num_rows; - #ifdef VERBOSE_DEBUG - cout << "j-1 > m.first_one_in_row[m.num_rows-1]" << "j:" << j << " m.first_one_in_row[m.num_rows-1]:" << m.first_one_in_row[m.num_rows-1] << endl; - #endif - } - for (uint i2 = 0; i2 != until2; i2++) { - #ifdef VERBOSE_DEBUG - cout << endl << "row " << i2 << " (num rows:" << m.num_rows << ")" << endl; - cout << m.matrix.getMatrixAt(i2) << endl; - cout << " m.first_one_in_row[m.num_rows-1]:" << m.first_one_in_row[m.num_rows-1] << endl; - cout << "first_one_in_row:" << m.first_one_in_row[i2] << endl; - cout << "num_cols:" << m.num_cols << endl; - cout << "popcnt:" << m.matrix.getMatrixAt(i2).popcnt() << endl; - cout << "popcnt_is_one():" << m.matrix.getMatrixAt(i2).popcnt_is_one() << endl; - cout << "popcnt_is_one("<< m.first_one_in_row[i2] <<"): " << m.matrix.getMatrixAt(i2).popcnt_is_one(m.first_one_in_row[i2]) << endl; - #endif - - for (uint i3 = 0; i3 < m.first_one_in_row[i2]; i3++) { - assert(m.matrix.getMatrixAt(i2)[i3] == 0); - } - assert(m.matrix.getMatrixAt(i2)[m.first_one_in_row[i2]]); - assert(m.matrix.getMatrixAt(i2).popcnt_is_one() == - m.matrix.getMatrixAt(i2).popcnt_is_one(m.first_one_in_row[i2])); - } - } -} - -const uint Gaussian::get_called() const -{ - return called; -} - -const uint Gaussian::get_useful_prop() const -{ - return useful_prop; -} - -const uint Gaussian::get_useful_confl() const -{ - return useful_confl; -} - -const bool Gaussian::get_disabled() const -{ - return disabled; -} - -void Gaussian::set_disabled(const bool toset) -{ - disabled = toset; -} - -//old functions - -/*void Gaussian::update_matrix_by_row(matrixset& m) const -{ -#ifdef VERBOSE_DEBUG - cout << "Updating matrix." << endl; - uint num_updated = 0; -#endif -#ifdef DEBUG_GAUSS - assert(nothing_to_propagate(cur_matrixset)); -#endif - - mpz_class toclear, tocount; - uint last_col = 0; - - for (uint col = 0; col < m.num_cols; col ++) { - Var var = m.col_to_var[col]; - - if (var != UINT_MAX && !solver.assigns[var].isUndef()) { - toclear.setBit(col); - if (solver.assigns[var].getBool()) tocount.setBit(col); - -#ifdef DEBUG_GAUSS - assert(m.var_to_col[var] < UINT_MAX-1); -#endif - last_col = col; - m.least_column_changed = std::min(m.least_column_changed, (int)col); - - m.removeable_cols++; - m.col_to_var[col] = UINT_MAX; - m.var_to_col[var] = UINT_MAX-1; -#ifdef VERBOSE_DEBUG - num_updated++; -#endif - } - } - - toclear.invert(); - mpz_class tmp; - mpz_class* this_row = &m.matrix[0]; - for(uint i = 0, until = std::min(m.num_rows, m.last_one_in_col[last_col]+1); i < until; i++, this_row++) { - mpz_class& r = *this_row; - mpz_and(tmp.get_mp(), tocount.get_mp(), r.get_mp()); - r.invert_is_true(tmp.popcnt() % 2); - r &= toclear; -} - -#ifdef VERBOSE_DEBUG - cout << "Updated " << num_updated << " matrix cols. Could remove " << m.removeable_cols << " cols " <= last_level; level--){ - Var var = solver.trail[level].var(); - const uint col = m.var_to_col[var]; - if ( col < UINT_MAX-1) { - update_matrix_col(m, var, col); -#ifdef VERBOSE_DEBUG - num_updated++; -#endif - } - } - -#ifdef VERBOSE_DEBUG - cout << "Updated " << num_updated << " matrix cols. Could remove " << m.removeable_cols << " cols (out of " << m.num_cols << " )" <. -**************************************************************************************************/ - -#ifndef GAUSSIAN_H -#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" - -//#define VERBOSE_DEBUG -//#define DEBUG_GAUSS - -#ifdef VERBOSE_DEBUG -using std::vector; -using std::cout; -using std::endl; -#endif - -namespace MINISAT -{ -using namespace MINISAT; - -class Clause; - -static const uint16_t unassigned_col = std::numeric_limits::max(); -static const Var unassigned_var = std::numeric_limits::max(); - -class Gaussian -{ -public: - Gaussian(Solver& solver, const GaussianConfig& config, const uint matrix_no, const vector& xorclauses); - ~Gaussian(); - - llbool full_init(); - llbool find_truths(vec& learnt_clause, int& conflictC); - - //statistics - void print_stats() const; - void print_matrix_stats() const; - const uint get_called() const; - const uint get_useful_prop() const; - const uint get_useful_confl() const; - const bool get_disabled() const; - void set_disabled(const bool toset); - - //functions used throughout the Solver - void canceling(const uint sublevel); - -protected: - Solver& solver; - - //Gauss high-level configuration - const GaussianConfig& config; - const uint matrix_no; - vector xorclauses; - - enum gaussian_ret {conflict, unit_conflict, propagation, unit_propagation, nothing}; - gaussian_ret gaussian(Clause*& confl); - - vector col_to_var_original; //Matches columns to variables - BitArray var_is_in; //variable is part of the the matrix. var_is_in's size is _minimal_ so you should check whether var_is_in.getSize() < var before issuing var_is_in[var] - uint badlevel; - - class matrixset - { - public: - PackedMatrix matrix; // The matrix, updated to reflect variable assignements - BitArray var_is_set; - vector col_to_var; // col_to_var[COL] tells which variable is at a given column in the matrix. Gives unassigned_var if the COL has been zeroed (i.e. the variable assigned) - uint16_t num_rows; // number of active rows in the matrix. Unactive rows are rows that contain only zeros (and if they are conflicting, then the conflict has been treated) - uint num_cols; // number of active columns in the matrix. The columns at the end that have all be zeroed are no longer active - int least_column_changed; // when updating the matrix, this value contains the smallest column number that has been updated (Gauss elim. can start from here instead of from column 0) - vector last_one_in_col; //last_one_in_col[COL] tells the last row+1 that has a '1' in that column. Used to reduce the burden of Gauss elim. (it only needs to look until that row) - vector first_one_in_row; - uint removeable_cols; // the number of columns that have been zeroed out (i.e. assigned) - }; - - //Saved states - vector matrix_sets; // The matrixsets for depths 'decision_from' + 0, 'decision_from' + only_nth_gaussian_save, 'decision_from' + 2*only_nth_gaussian_save, ... 'decision_from' + 'decision_until'. - matrixset cur_matrixset; // The current matrixset, i.e. the one we are working on, or the last one we worked on - - //Varibales to keep Gauss state - bool messed_matrix_vars_since_reversal; - int gauss_last_level; - vector > clauses_toclear; - bool disabled; // Gauss is disabled - - //State of current elimnation - vec propagatable_rows; //used to store which rows were deemed propagatable during elimination - vector changed_rows; //used to store which rows were deemed propagatable during elimination - - //Statistics - uint useful_prop; //how many times Gauss gave propagation as a result - uint useful_confl; //how many times Gauss gave conflict as a result - uint called; //how many times called the Gauss - - //gauss init functions - void init(); // Initalise gauss state - void fill_matrix(matrixset& origMat); // Fills the origMat matrix - uint select_columnorder(vector& var_to_col, matrixset& origMat); // Fills var_to_col and col_to_var of the origMat matrix. - - //Main function - uint eliminate(matrixset& matrix, uint& conflict_row); //does the actual gaussian elimination - - //matrix update functions - void update_matrix_col(matrixset& matrix, const Var x, const uint col); // Update one matrix column - void update_matrix_by_col_all(matrixset& m); // Update all columns, column-by-column (and not row-by-row) - void set_matrixset_to_cur(); // Save the current matrixset, the cur_matrixset to matrix_sets - //void update_matrix_by_row(matrixset& matrix) const; - //void update_matrix_by_col(matrixset& matrix, const uint last_level) const; - - //conflict&propagation handling - gaussian_ret handle_matrix_prop_and_confl(matrixset& m, uint row, Clause*& confl); - void analyse_confl(const matrixset& m, const uint row, uint& maxlevel, uint& size, uint& best_row) const; // analyse conflcit to find the best conflict. Gets & returns the best one in 'maxlevel', 'size' and 'best row' (these are all UINT_MAX when calling this function first, i.e. when there is no other possible conflict to compare to the new in 'row') - gaussian_ret handle_matrix_confl(Clause*& confl, const matrixset& m, const uint size, const uint maxlevel, const uint best_row); - gaussian_ret handle_matrix_prop(matrixset& m, const uint row); // Handle matrix propagation at row 'row' - vec tmp_clause; - - //propagation&conflict handling - void cancel_until_sublevel(const uint sublevel); // cancels until sublevel 'sublevel'. The var 'sublevel' must NOT go over the current level. I.e. this function is ONLY for moving inside the current level - uint find_sublevel(const Var v) const; // find the sublevel (i.e. trail[X]) of a given variable - - //helper functions - bool at_first_init() const; - bool should_init() const; - bool should_check_gauss(const uint decisionlevel, const uint starts) const; - void disable_if_necessary(); - void reset_stats(); - void update_last_one_in_col(matrixset& m); - -private: - - //debug functions - bool check_no_conflict(matrixset& m) const; // Are there any conflicts that the matrixset 'm' causes? - const bool nothing_to_propagate(matrixset& m) const; // Are there any conflicts of propagations that matrixset 'm' clauses? - template - void print_matrix_row(const T& row) const; // Print matrix row 'row' - template - void print_matrix_row_with_assigns(const T& row) 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; - void print_last_one_in_cols(matrixset& m) const; - static const string lbool_to_string(const lbool toprint); -}; - -inline bool Gaussian::should_init() const -{ - return (config.decision_until > 0); -} - -inline bool Gaussian::should_check_gauss(const uint decisionlevel, const uint starts) const -{ - return (!disabled - && decisionlevel < config.decision_until); -} - -inline void Gaussian::canceling(const uint sublevel) -{ - if (disabled) - return; - uint a = 0; - for (int i = clauses_toclear.size()-1; i >= 0 && clauses_toclear[i].second > sublevel; i--) { - clauseFree(clauses_toclear[i].first); - a++; - } - clauses_toclear.resize(clauses_toclear.size()-a); - - if (messed_matrix_vars_since_reversal) - return; - int c = std::min((int)gauss_last_level, (int)(solver.trail.size())-1); - for (; c >= (int)sublevel; c--) { - Var var = solver.trail[c].var(); - if (var < var_is_in.getSize() - && var_is_in[var] - && cur_matrixset.var_is_set[var]) { - messed_matrix_vars_since_reversal = true; - return; - } - } -} - -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 f98ec17..e69de29 100644 --- a/src/sat/cryptominisat2/GaussianConfig.h +++ b/src/sat/cryptominisat2/GaussianConfig.h @@ -1,52 +0,0 @@ -/*********************************************************************************** -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 GAUSSIANCONFIG_H -#define GAUSSIANCONFIG_H - -#ifdef _MSC_VER -#include -#else -#include -#endif //_MSC_VER - -#include "PackedRow.h" - -namespace MINISAT -{ -using namespace MINISAT; - -class GaussianConfig -{ - public: - - GaussianConfig() : - only_nth_gauss_save(2) - , decision_until(0) - , 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 - 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 94b0d0a..e69de29 100644 --- a/src/sat/cryptominisat2/Logger.cpp +++ b/src/sat/cryptominisat2/Logger.cpp @@ -1,893 +0,0 @@ -/*********************************************************************************** -CryptoMiniSat -- Copyright (c) 2009 Mate Soos - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -using std::cout; -using std::endl; -using std::ofstream; - -#include "Logger.h" -#include "SolverTypes.h" -#include "Solver.h" -#include "Gaussian.h" - -#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) - , statistics_on(false) - - , max_print_lines(20) - , uniqueid(1) - - , proof(NULL) - - , sum_conflict_depths(0) - , no_conflicts(0) - , no_decisions(0) - , no_propagations(0) - , sum_decisions_on_branches(0) - , sum_propagations_on_branches(0) - - , verbosity(_verbosity) - , begin_called(false) - , proofStarts(0) -{ - runid /= 10; - runid = time(NULL) % 10000; - if (verbosity >= 1) printf("c RunID is: #%d\n",runid); -} - -void Logger::setSolver(const Solver* _s) -{ - S = _s; -} - -// Adds a new variable to the knowledge of the logger -void Logger::new_var(const Var var) -{ - if (!statistics_on && !proof_graph_on) - return; - - if (varnames.size() <= var) { - varnames.resize(var+1, "Noname"); - 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); - } -} - -// Resizes the groupnames and other, related vectors to accomodate for a new group -void Logger::new_group(const uint group) -{ - if (groupnames.size() <= group) { - groupnames.resize(group+1, "Noname"); - 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); - } -} - -void Logger::cut_name_to_size(string& name) const -{ - uint len = name.length(); - while(len > 0 && (name[len-1] == ' ' || name[len-1] == 0x0A || name[len-1] == 0x0D)) { - name[len-1] = '\0'; - name.resize(len-1); - len--; - } - - if (len > SND_WIDTH-2) { - name[SND_WIDTH-2] = '\0'; - name[SND_WIDTH-3] = '.'; - name[SND_WIDTH-4] = '.'; - } -} - -// Adds the new clause group's name to the information stored -void Logger::set_group_name(const uint group, char* name_tmp) -{ - if (!statistics_on && !proof_graph_on) - return; - - string name; - if (name_tmp == NULL) return; - else name = name_tmp; - - new_group(group); - cut_name_to_size(name); - - if (name == "Noname") return; - - if (groupnames[group] == "Noname") { - groupnames[group] = name; - } else if (groupnames[group] != name) { - std::cout << "Error! Group no. " << group << "has been named twice. First, as '" << groupnames[group] << "', then second as '" << name << "'. Name the same group the same always, or don't give a name to the second iteration of the same group (i.e just write 'c g groupnumber' on the line" << std::endl; - exit(-1); - } -} - -// sets the variable's name -void Logger::set_variable_name(const uint var, char* name_tmp) -{ - if (!statistics_on && !proof_graph_on) - return; - - new_var(var); - - string name; - if (name_tmp == NULL) - name = ""; - else - name = name_tmp; - - cut_name_to_size(name); - - if (varnames[var] == "Noname") { - varnames[var] = name; - } else if (varnames[var] != name) { - printf("Error! Variable no. %d has been named twice. First, as '%s', then second as '%s'. Name the same group the same always, or don't give a name to the second iteration of the same group (i.e just write 'c g groupnumber' on the line\n", var+1, varnames[var].c_str(), name.c_str()); - exit(-1); - } -} - -void Logger::first_begin() -{ - if (begin_called) - return; - - begin(); -} - -void Logger::begin() -{ - begin_called = true; - if (proof_graph_on) { - std::stringstream filename; - filename << "proofs/" << runid << "-proof" << proofStarts++ << "-" << S->starts << ".dot"; - - if (S->starts == 0) - history.push_back(uniqueid); - else { - if (mini_proof) - history.resize(S->decisionLevel()+1); - else - history.resize(S->trail.size()+1); - } - - proof = fopen(filename.str().c_str(),"w"); - if (!proof) printf("Couldn't open proof file '%s' for writing\n", filename.str().c_str()), exit(-1); - fprintf(proof, "digraph G {\n"); - fprintf(proof,"node%d [shape=circle, label=\"BEGIN\", root];\n", history[history.size()-1]); - } - - if (statistics_on) - reset_statistics(); -} - -// For noting conflicts. Updates the proof graph and the statistics. -template -void Logger::conflict(const confl_type type, const uint goback_level, const uint group, const T& learnt_clause) -{ - first_begin(); - assert(!(proof == NULL && proof_graph_on)); - - const uint goback_sublevel = S->trail_lim[goback_level]; - - if (proof_graph_on) { - uniqueid++; - fprintf(proof,"node%d [shape=polygon,sides=5,label=\"",uniqueid); - - if (!mini_proof) { - for (uint32_t i = 0; i != learnt_clause.size(); i++) { - if (learnt_clause[i].sign()) fprintf(proof,"-"); - int myvar = learnt_clause[i].var(); - if (varnames[myvar] != "Noname") - fprintf(proof,"%s\\n",varnames[myvar].c_str()); - else - fprintf(proof,"Var: %d\\n",myvar); - } - } - fprintf(proof,"\"];\n"); - - fprintf(proof,"node%d -> node%d [label=\"",history[history.size()-1],uniqueid); - if (type == gauss_confl_type) - fprintf(proof,"Gauss\",style=bold"); - else - fprintf(proof,"%s\"", groupnames[group].c_str()); - fprintf(proof,"];\n"); - - if (!mini_proof) - history.resize(goback_sublevel+1); - else - history.resize(goback_level+1); - fprintf(proof,"node%d -> node%d [style=dotted];\n",uniqueid,history[history.size()-1]); - } - - if (statistics_on) { - times_group_caused_conflict[group]++; - 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(); - - if (branch_depth_distrib.size() <= S->decisionLevel()) - branch_depth_distrib.resize(S->decisionLevel()+1, 0); - branch_depth_distrib[S->decisionLevel()]++; - } -} - -template void Logger::conflict(const confl_type type, const uint goback_level, const uint group, const Clause& learnt_clause); - -template void Logger::conflict(const confl_type type, const uint goback_level, const uint group, const vec& learnt_clause); - -// Propagating a literal. Type of literal and the (learned clause's)/(propagating clause's)/(etc) group must be given. Updates the proof graph and the statistics. note: the meaning of the variable 'group' depends on the type -void Logger::propagation(const Lit lit, Clause* c) -{ - first_begin(); - assert(!(proof == NULL && proof_graph_on)); - - uint group; - prop_type type; - if (c == NULL) { - if (S->decisionLevel() == 0) - type = add_clause_type; - else - type = guess_type; - group = std::numeric_limits::max(); - } else { - type = simple_propagation_type; - group = c->getGroup(); - } - - //graph - if (proof_graph_on && (!mini_proof || type == guess_type)) { - uniqueid++; - - fprintf(proof,"node%d [shape=box, label=\"",uniqueid);; - if (lit.sign()) - fprintf(proof,"-"); - if (varnames[lit.var()] != "Noname") - fprintf(proof,"%s\"];\n",varnames[lit.var()].c_str()); - else - fprintf(proof,"Var: %d\"];\n",lit.var()); - - fprintf(proof,"node%d -> node%d [label=\"",history[history.size()-1],uniqueid); - - switch (type) { - case simple_propagation_type: - fprintf(proof,"%s\"];\n", groupnames[group].c_str()); - break; - - case add_clause_type: - fprintf(proof,"red. from clause\"];\n"); - break; - - case guess_type: - fprintf(proof,"guess\",style=bold];\n"); - break; - } - history.push_back(uniqueid); - } - - if (statistics_on) { - switch (type) { - case simple_propagation_type: - 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()].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()].sum += S->decisionLevel(); - depths_of_assigns_for_var[lit.var()].num ++; - break; - } - } -} - -// Ending of a restart iteration -void Logger::end(const finish_type finish) -{ - first_begin(); - assert(!(proof == NULL && proof_graph_on)); - - if (proof_graph_on) { - uniqueid++; - switch (finish) { - case model_found: - fprintf(proof,"node%d [shape=doublecircle, label=\"MODEL\"];\n",uniqueid); - break; - case unsat_model_found: - fprintf(proof,"node%d [shape=doublecircle, label=\"UNSAT\"];\n",uniqueid); - break; - case restarting: - fprintf(proof,"node%d [shape=doublecircle, label=\"Re-starting\\nsearch\"];\n",uniqueid); - break; - } - - fprintf(proof,"node%d -> node%d;\n",history[history.size()-1],uniqueid); - fprintf(proof,"}\n"); - history.push_back(uniqueid); - - proof = (FILE*)fclose(proof); - assert(proof == NULL); - } - - if (statistics_on) { - printstats(); - if (finish == restarting) - reset_statistics(); - } - - if (model_found || unsat_model_found) - begin_called = false; -} - -void Logger::print_footer() const -{ - cout << "+" << std::setfill('-') << std::setw(FST_WIDTH+SND_WIDTH+TRD_WIDTH+4) << "-" << std::setfill(' ') << "+" << endl; -} - -void Logger::print_assign_var_order() const -{ - vector > prop_ordered; - for (uint i = 0; i < depths_of_assigns_for_var.size(); i++) { - 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()) { - print_footer(); - print_simple_line(" Variables are assigned in the following order"); - print_simple_line(" (unitary clauses not shown)"); - print_header("var", "var name", "avg order"); - std::sort(prop_ordered.begin(), prop_ordered.end()); - print_vars(prop_ordered); - } -} - -void Logger::print_prop_order() const -{ - vector > prop_ordered; - for (uint i = 0; i < depths_of_propagations_for_group.size(); i++) { - 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()) { - print_footer(); - print_simple_line(" Propagation depth order of clause groups"); - print_simple_line(" (unitary clauses not shown)"); - print_header("group", "group name", "avg order"); - std::sort(prop_ordered.begin(), prop_ordered.end()); - print_groups(prop_ordered); - } -} - -void Logger::print_confl_order() const -{ - vector > confl_ordered; - for (uint i = 0; i < depths_of_conflicts_for_group.size(); i++) { - 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()) { - print_footer(); - print_simple_line(" Avg. conflict depth order of clause groups"); - print_header("groupno", "group name", "avg. depth"); - std::sort(confl_ordered.begin(), confl_ordered.end()); - print_groups(confl_ordered); - } -} - - -void Logger::print_times_var_guessed() const -{ - vector > times_var_ordered; - for (uint32_t i = 0; i != varnames.size(); i++) if (times_var_guessed[i] > 0) - times_var_ordered.push_back(std::make_pair(times_var_guessed[i], i)); - - if (!times_var_ordered.empty()) { - print_footer(); - print_simple_line(" No. times variable branched on"); - print_header("var", "var name", "no. times"); - std::sort(times_var_ordered.rbegin(), times_var_ordered.rend()); - print_vars(times_var_ordered); - } -} - -void Logger::print_times_group_caused_propagation() const -{ - vector > props_group_ordered; - for (uint i = 0; i < times_group_caused_propagation.size(); i++) - if (times_group_caused_propagation[i] > 0) - props_group_ordered.push_back(std::make_pair(times_group_caused_propagation[i], i)); - - if (!props_group_ordered.empty()) { - print_footer(); - print_simple_line(" No. propagations made by clause groups"); - print_header("group", "group name", "no. props"); - std::sort(props_group_ordered.rbegin(),props_group_ordered.rend()); - print_groups(props_group_ordered); - } -} - -void Logger::print_times_group_caused_conflict() const -{ - vector > confls_group_ordered; - for (uint i = 0; i < times_group_caused_conflict.size(); i++) - if (times_group_caused_conflict[i] > 0) - confls_group_ordered.push_back(std::make_pair(times_group_caused_conflict[i], i)); - - if (!confls_group_ordered.empty()) { - print_footer(); - print_simple_line(" No. conflicts made by clause groups"); - print_header("group", "group name", "no. confl"); - std::sort(confls_group_ordered.rbegin(), confls_group_ordered.rend()); - print_groups(confls_group_ordered); - } -} - -template -void Logger::print_line(const uint& number, const string& name, const T& value) const -{ - cout << "|" << std::setw(FST_WIDTH) << number << " " << std::setw(SND_WIDTH) << name << " " << std::setw(TRD_WIDTH) << value << "|" << endl; -} - -void Logger::print_header(const string& first, const string& second, const string& third) const -{ - cout << "|" << std::setw(FST_WIDTH) << first << " " << std::setw(SND_WIDTH) << second << " " << std::setw(TRD_WIDTH) << third << "|" << endl; - print_footer(); -} - -void Logger::print_groups(const vector >& to_print) const -{ - uint i = 0; - typedef vector >::const_iterator myiterator; - for (myiterator it = to_print.begin(); it != to_print.end() && i < max_print_lines; it++, i++) { - print_line(it->second+1, groupnames[it->second], it->first); - } - print_footer(); -} - -void Logger::print_groups(const vector >& to_print) const -{ - uint i = 0; - typedef vector >::const_iterator myiterator; - for (myiterator it = to_print.begin(); it != to_print.end() && i < max_print_lines; it++, i++) { - print_line(it->second+1, groupnames[it->second], it->first); - } - print_footer(); -} - -void Logger::print_vars(const vector >& to_print) const -{ - uint i = 0; - for (vector >::const_iterator it = to_print.begin(); it != to_print.end() && i < max_print_lines; it++, i++) - print_line(it->second+1, varnames[it->second], it->first); - - print_footer(); -} - -void Logger::print_vars(const vector >& to_print) const -{ - uint i = 0; - for (vector >::const_iterator it = to_print.begin(); it != to_print.end() && i < max_print_lines; it++, i++) { - print_line(it->second+1, varnames[it->second], it->first); - } - - print_footer(); -} - -template -void Logger::print_line(const string& str, const T& num) const -{ - cout << "|" << std::setw(FST_WIDTH+SND_WIDTH+4) << str << std::setw(TRD_WIDTH) << num << "|" << endl; -} - -void Logger::print_simple_line(const string& str) const -{ - cout << "|" << std::setw(FST_WIDTH+SND_WIDTH+TRD_WIDTH+4) << str << "|" << endl; -} - -void Logger::print_center_line(const string& str) const -{ - uint middle = (FST_WIDTH+SND_WIDTH+TRD_WIDTH+4-str.size())/2; - int rest = FST_WIDTH+SND_WIDTH+TRD_WIDTH+4-middle*2-str.size(); - cout << "|" << std::setw(middle) << " " << str << std::setw(middle + rest) << " " << "|" << endl; -} - -void Logger::print_branch_depth_distrib() const -{ - //cout << "--- Branch depth stats ---" << endl; - - const uint range = 20; - map range_stat; - - uint i = 0; - for (vector::const_iterator it = branch_depth_distrib.begin(); it != branch_depth_distrib.end(); it++, i++) { - range_stat[i/range] += *it; - } - - print_footer(); - print_simple_line(" No. search branches with branch depth between"); - print_line("Branch depth between", "no. br.-s"); - print_footer(); - - std::stringstream ss; - ss << "branch_depths/branch_depth_file" << runid << "-" << S->starts << ".txt"; - ofstream branch_depth_file; - branch_depth_file.open(ss.str().c_str()); - i = 0; - - 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); - - if (branch_depth_file.is_open()) { - branch_depth_file << i << "\t" << it->second << "\t"; - if (i % 5 == 0) - branch_depth_file << "\"" << it->first*range << "\""; - else - branch_depth_file << "\"\""; - branch_depth_file << endl; - } - } - if (branch_depth_file.is_open()) - branch_depth_file.close(); - print_footer(); - -} - -void Logger::print_learnt_clause_distrib() const -{ - map learnt_sizes; - const vec& learnts = S->get_learnts(); - - uint maximum = 0; - - for (uint i = 0; i < learnts.size(); i++) - { - uint size = learnts[i]->size(); - maximum = std::max(maximum, size); - - map::iterator it = learnt_sizes.find(size); - if (it == learnt_sizes.end()) - learnt_sizes[size] = 1; - else - it->second++; - } - - learnt_sizes[0] = S->get_unitary_learnts_num(); - - uint slice = (maximum+1)/max_print_lines + (bool)((maximum+1)%max_print_lines); - - print_footer(); - print_simple_line(" Learnt clause length distribution"); - print_line("Length between", "no. cl."); - print_footer(); - - uint until = slice; - uint from = 0; - while(until < maximum+1) { - std::stringstream ss2; - ss2 << from << " - " << until-1; - - uint sum = 0; - for (; from < until; from++) { - map::const_iterator it = learnt_sizes.find(from); - if (it != learnt_sizes.end()) - sum += it->second; - } - - print_line(ss2.str(), sum); - - until += slice; - } - - print_footer(); - - print_leearnt_clause_graph_distrib(maximum, learnt_sizes); -} - -void Logger::print_leearnt_clause_graph_distrib(const uint maximum, const map& learnt_sizes) const -{ - uint no_slices = FST_WIDTH + SND_WIDTH + TRD_WIDTH + 4-3; - uint slice = (maximum+1)/no_slices + (bool)((maximum+1)%no_slices); - uint until = slice; - uint from = 0; - vector slices; - uint hmax = 0; - while(until < maximum+1) { - uint sum = 0; - for (; from < until; from++) { - map::const_iterator it = learnt_sizes.find(from); - if (it != learnt_sizes.end()) - sum += it->second; - } - slices.push_back(sum); - until += slice; - hmax = std::max(hmax, sum); - } - slices.resize(no_slices, 0); - - uint height = max_print_lines; - uint hslice = (hmax+1)/height + (bool)((hmax+1)%height); - if (hslice == 0) return; - - print_simple_line(" Learnt clause distribution in graph form"); - print_footer(); - string yaxis = "Number"; - uint middle = (height-yaxis.size())/2; - - for (int i = height-1; i > 0; i--) { - cout << "| "; - if (height-1-i >= middle && height-1-i-middle < yaxis.size()) - cout << yaxis[height-1-i-middle] << " "; - else - cout << " "; - for (uint i2 = 0; i2 != no_slices; i2++) { - if (slices[i2]/hslice >= (uint)i) cout << "+"; - else cout << " "; - } - cout << "|" << endl; - } - print_center_line(" Learnt clause size"); - print_footer(); -} - -void Logger::print_general_stats() const -{ - print_footer(); - print_simple_line(" Standard MiniSat stats -- for all restarts until now"); - print_footer(); - print_line("Restart number", S->starts); - print_line("Number of conflicts", S->conflicts); - print_line("Number of decisions", S->decisions); - print_line("Number of variables", S->order_heap.size()); - print_line("Number of clauses", S->nClauses()); - print_line("Number of literals in clauses",S->clauses_literals); - print_line("Avg. literals per learnt clause",(double)S->learnts_literals/(double)S->nLearnts()); - print_line("Progress estimate (%):", S->progress_estimate*100.0); - print_line("All unitary learnts until now", S->get_unitary_learnts_num()); - print_footer(); -} - -void Logger::print_learnt_unitaries(const uint from, const string display) const -{ - print_footer(); - print_simple_line(display); - print_header("var", "name", "value"); - 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 value = !(S->trail[i].sign()); - print_line(var+1, varnames[var], value); - } - print_footer(); -} - - -// Prints statistics on the console -void Logger::printstats() const -{ - assert(statistics_on); - assert(varnames.size() == times_var_guessed.size()); - assert(varnames.size() == times_var_propagated.size()); - - const uint fullwidth = FST_WIDTH+SND_WIDTH+TRD_WIDTH+4; - cout << endl; - cout << "+" << std::setfill('=') << std::setw(fullwidth) << "=" << "+" << endl; - std::stringstream tmp; - tmp << " STATS FOR RESTART NO. " << std::setw(3) << S->starts << " BEGIN "; - uint len = (fullwidth-2)/2-tmp.str().length()/2; - uint len2 = len + tmp.str().length()%2 + (fullwidth-2)%2; - cout << "||" << std::setfill('*') << std::setw(len) << "*" << tmp.str() << std::setw(len2) << "*" << "||" << endl; - cout << "+" << std::setfill('=') << std::setw(fullwidth) << "=" << std::setfill(' ') << "+" << endl; - - cout.setf(std::ios_base::left); - cout.precision(2); - print_statistics_note(); - print_times_var_guessed(); - print_times_group_caused_propagation(); - print_times_group_caused_conflict(); - print_prop_order(); - print_confl_order(); - print_assign_var_order(); - print_branch_depth_distrib(); - print_learnt_clause_distrib(); - #ifdef USE_GAUSS - print_matrix_stats(); - #endif //USE_GAUSS - print_learnt_unitaries(0," Unitary clauses learnt until now"); - print_learnt_unitaries(last_unitary_learnt_clauses, " Unitary clauses during this restart"); - print_advanced_stats(); - print_general_stats(); -} - -#ifdef USE_GAUSS -void Logger::print_matrix_stats() const -{ - print_footer(); - print_simple_line(" Matrix statistics"); - print_footer(); - - uint i = 0; - for (vector::const_iterator it = S->gauss_matrixes.begin(), end = S->gauss_matrixes.end(); it != end; it++, i++) { - std::stringstream s; - s << "Matrix " << i << " enabled"; - std::stringstream tmp; - tmp << std::boolalpha << !(*it)->get_disabled(); - print_line(s.str(), tmp.str()); - - s.str(""); - s << "Matrix " << i << " called"; - print_line(s.str(), (*it)->get_called()); - - s.str(""); - s << "Matrix " << i << " propagations"; - print_line(s.str(), (*it)->get_useful_prop()); - - s.str(""); - s << "Matrix " << i << " conflicts"; - print_line(s.str(), (*it)->get_useful_confl()); - } - - print_footer(); -} -#endif //USE_GAUSS - -void Logger::print_advanced_stats() const -{ - print_footer(); - print_simple_line(" Advanced statistics - for only this restart"); - print_footer(); - print_line("Unitary learnts", S->get_unitary_learnts_num() - last_unitary_learnt_clauses); - print_line("No. branches visited", no_conflicts); - print_line("Avg. branch depth", (double)sum_conflict_depths/(double)no_conflicts); - print_line("No. decisions", no_decisions); - print_line("No. propagations",no_propagations); - - //printf("no progatations/no decisions (i.e. one decision gives how many propagations on average *for the whole search graph*): %f\n", (double)no_propagations/(double)no_decisions); - //printf("no propagations/sum decisions on branches (if you look at one specific branch, what is the average number of propagations you will find?): %f\n", (double)no_propagations/(double)sum_decisions_on_branches); - - print_simple_line("sum decisions on branches/no. branches"); - print_simple_line(" (in a given branch, what is the avg."); - print_line(" no. of decisions?)",(double)sum_decisions_on_branches/(double)no_conflicts); - - print_simple_line("sum propagations on branches/no. branches"); - print_simple_line(" (in a given branch, what is the"); - print_line(" avg. no. of propagations?)",(double)sum_propagations_on_branches/(double)no_conflicts); - - print_footer(); -} - -void Logger::print_statistics_note() const -{ - print_footer(); - print_simple_line("Statistics note: If you used CryptoMiniSat as"); - print_simple_line("a library then vars are all shifted by 1 here"); - print_simple_line("and in every printed output of the solver."); - print_simple_line("This does not apply when you use CryptoMiniSat"); - print_simple_line("as a stand-alone program."); - print_footer(); -} - -// resets all stored statistics. Might be useful, to generate statistics for each restart and not for the whole search in general -void Logger::reset_statistics() -{ - assert(S->decisionLevel() == 0); - assert(times_var_guessed.size() == times_var_propagated.size()); - assert(times_group_caused_conflict.size() == times_group_caused_propagation.size()); - - typedef vector::iterator vecit; - for (vecit it = times_var_guessed.begin(); it != times_var_guessed.end(); it++) - *it = 0; - - for (vecit it = times_var_propagated.begin(); it != times_var_propagated.end(); it++) - *it = 0; - - for (vecit it = times_group_caused_conflict.begin(); it != times_group_caused_conflict.end(); it++) - *it = 0; - - for (vecit it = times_group_caused_propagation.begin(); it != times_group_caused_propagation.end(); it++) - *it = 0; - - for (vecit it = confls_by_group.begin(); it != confls_by_group.end(); it++) - *it = 0; - - for (vecit it = props_by_group.begin(); it != props_by_group.end(); it++) - *it = 0; - - typedef vector::iterator avgIt; - - for (avgIt it = depths_of_propagations_for_group.begin(); it != depths_of_propagations_for_group.end(); it++) { - it->sum = 0; - it->num = 0; - } - - for (avgIt it = depths_of_conflicts_for_group.begin(); it != depths_of_conflicts_for_group.end(); it++) { - it->sum = 0; - it->num = 0; - } - - 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; - no_decisions = 0; - no_propagations = 0; - sum_decisions_on_branches = 0; - sum_propagations_on_branches = 0; - branch_depth_distrib.clear(); - 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 a00c785..e69de29 100644 --- a/src/sat/cryptominisat2/Logger.h +++ b/src/sat/cryptominisat2/Logger.h @@ -1,187 +0,0 @@ -/*********************************************************************************** -CryptoMiniSat -- Copyright (c) 2009 Mate Soos - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************************************/ - -#ifndef LOGGER_H -#define LOGGER_H - -#include -#include -#include -#include -#include -#ifdef _MSC_VER -#include -#else -#include -#endif //_MSC_VER - -#include "Vec.h" -#include "Heap.h" -#include "Alg.h" -#include "SolverTypes.h" -#include "limits.h" -#include "Clause.h" - -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: - Logger(int& vebosity); - void setSolver(const Solver* S); - - //types of props, confl, and finish - enum prop_type { add_clause_type, guess_type, simple_propagation_type}; - enum confl_type { simple_confl_type, gauss_confl_type }; - enum finish_type { model_found, unsat_model_found, restarting}; - - //Conflict and propagation(guess is also a proapgation...) - template - void conflict(const confl_type type, const uint goback_level, const uint group, const T& learnt_clause); - void propagation(const Lit lit, Clause* c); - - //functions to add/name variables - void new_var(const Var var); - void set_variable_name(const uint var, char* name_tmp); - - //function to name clause groups - void set_group_name(const uint group, char* name_tmp); - - void begin(); - void end(const finish_type finish); - - void newclause(const vec& ps, const bool xor_clause, const uint group); - - bool proof_graph_on; - bool mini_proof; - bool statistics_on; - -private: - void new_group(const uint group); - void cut_name_to_size(string& name) const; - - void print_groups(const vector >& to_print) const; - void print_groups(const vector >& to_print) const; - void print_vars(const vector >& to_print) const; - void print_vars(const vector >& to_print) const; - void print_times_var_guessed() const; - void print_times_group_caused_propagation() const; - void print_times_group_caused_conflict() const; - void print_branch_depth_distrib() const; - void print_learnt_clause_distrib() const; - void print_leearnt_clause_graph_distrib(const uint maximum, const map& learnt_sizes) const; - void print_advanced_stats() const; - void print_statistics_note() const; - void print_matrix_stats() const; - void print_general_stats() const; - void print_learnt_unitaries(const uint from, const string display) const; - - uint max_print_lines; - template - void print_line(const uint& number, const string& name, const T& value) const; - void print_header(const string& first, const string& second, const string& third) const; - void print_footer() const; - template - void print_line(const string& str, const T& num) const; - void print_simple_line(const string& str) const; - void print_center_line(const string& str) const; - - void print_confl_order() const; - void print_prop_order() const; - void print_assign_var_order() const; - void printstats() const; - void reset_statistics(); - - //internal data structures - uint uniqueid; //used to store the last unique ID given to a node - vector history; //stores the node uniqueIDs - - //graph drawing - FILE* proof; //The file to store the proof - uint runid; - - //--------------------- - //statistics collection - //--------------------- - - //group and var names - vector groupnames; - vector varnames; - - //confls and props grouped by clause groups - vector confls_by_group; - vector props_by_group; - - //props and guesses grouped by vars - vector times_var_guessed; - vector times_var_propagated; - - vector times_group_caused_conflict; - vector times_group_caused_propagation; - - 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 - vector branch_depth_distrib; - - uint sum_conflict_depths; - uint no_conflicts; - uint no_decisions; - uint no_propagations; - uint sum_decisions_on_branches; - uint sum_propagations_on_branches; - uint last_unitary_learnt_clauses; - - //message display properties - const int& verbosity; - - const Solver* S; - - void first_begin(); - bool begin_called; - uint proofStarts; -}; - -}; //NAMESPACE MINISAT - -#endif //LOGGER_H diff --git a/src/sat/cryptominisat2/Makefile b/src/sat/cryptominisat2/Makefile index a38b19e..e69de29 100644 --- a/src/sat/cryptominisat2/Makefile +++ b/src/sat/cryptominisat2/Makefile @@ -1,27 +0,0 @@ -TOP = ../../.. -include $(TOP)/scripts/Makefile.common - -MTL = mtl -MTRAND = MTRand -SOURCES = Logger.cpp Solver.cpp PackedRow.cpp XorFinder.cpp Conglomerate.cpp VarReplacer.cpp FindUndef.cpp ClauseCleaner.cpp RestartTypeChooser.cpp Clause.cpp FailedVarSearcher.cpp PartFinder.cpp Subsumer.cpp PartHandler.cpp XorSubsumer.cpp SmallPtr.cpp -OBJECTS = $(SOURCES:.cpp=.o) -LIB = libminisat.a -CFLAGS += -I$(MTL) -I$(MTRAND) -DEXT_HASH_MAP -ffloat-store $(CFLAGS_M32) -c -EXEC = minisat -LFLAGS = -lz - -all: $(LIB) #$(EXEC) -lib: $(LIB) - -$(LIB): $(OBJECTS) - rm -f $@ - ar cq $@ $(OBJECTS) - ranlib $@ - cp $(LIB) ../ - cp $(OBJECTS) ../ - -clean: - rm -f $(OBJECTS) $(LIB) - -.cpp.o: - $(CC) $(CFLAGS) $< -o $@ diff --git a/src/sat/cryptominisat2/MatrixFinder.cpp b/src/sat/cryptominisat2/MatrixFinder.cpp index 1f08a2c..e69de29 100644 --- a/src/sat/cryptominisat2/MatrixFinder.cpp +++ b/src/sat/cryptominisat2/MatrixFinder.cpp @@ -1,224 +0,0 @@ -/*********************************************************************************** -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 "MatrixFinder.h" - -#include "Solver.h" -#include "Gaussian.h" -#include "GaussianConfig.h" -#include "ClauseCleaner.h" - -#include -#include -#include -#include -using std::set; -using std::map; - -//#define VERBOSE_DEBUG - -using std::cout; -using std::endl; - -namespace MINISAT -{ -using namespace MINISAT; - -//#define PART_FINDING - -MatrixFinder::MatrixFinder(Solver& _solver) : - solver(_solver) -{ -} - -inline const Var MatrixFinder::fingerprint(const XorClause& c) const -{ - Var fingerprint = 0; - - for (const Lit* a = &c[0], *end = a + c.size(); a != end; a++) - fingerprint |= a->var(); - - return fingerprint; -} - -inline const bool MatrixFinder::firstPartOfSecond(const XorClause& c1, const XorClause& c2) const -{ - uint i1, i2; - for (i1 = 0, i2 = 0; i1 < c1.size() && i2 < c2.size();) { - if (c1[i1].var() != c2[i2].var()) - i2++; - else { - i1++; - i2++; - } - } - - return (i1 == c1.size()); -} - -const uint MatrixFinder::findMatrixes() -{ - table.clear(); - table.resize(solver.nVars(), var_Undef); - reverseTable.clear(); - matrix_no = 0; - - if (solver.xorclauses.size() == 0) - return 0; - - solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses); - //TODO check for solver.ok == false - - 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()] != var_Undef) - tomerge.insert(table[l->var()]); - else - newSet.push_back(l->var()); - } - if (tomerge.size() == 1) { - 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]] = matrix_no; - reverseTable[matrix_no] = newSet; - matrix_no++; - } - - #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 setMatrixes(); -} - -const uint MatrixFinder::setMatrixes() -{ - vector > numXorInMatrix; - for (uint i = 0; i < matrix_no; i++) - numXorInMatrix.push_back(std::make_pair(i, 0)); - - vector sumXorSizeInMatrix(matrix_no, 0); - vector > xorSizesInMatrix(matrix_no); - vector > xorsInMatrix(matrix_no); - - #ifdef PART_FINDING - vector > xorFingerprintInMatrix(matrix_no); - #endif - - 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); - - //for stats - numXorInMatrix[matrix].second++; - sumXorSizeInMatrix[matrix] += x.size(); - xorSizesInMatrix[matrix].push_back(x.size()); - xorsInMatrix[matrix].push_back(&x); - - #ifdef PART_FINDING - xorFingerprintInMatrix[matrix].push_back(fingerprint(x)); - #endif //PART_FINDING - } - - std::sort(numXorInMatrix.begin(), numXorInMatrix.end(), mysorter()); - - #ifdef PART_FINDING - for (uint i = 0; i < matrix_no; i++) - findParts(xorFingerprintInMatrix[i], xorsInMatrix[i]); - #endif //PART_FINDING - - uint realMatrixNum = 0; - for (int a = matrix_no-1; a != -1; a--) { - uint i = numXorInMatrix[a].first; - - if (numXorInMatrix[a].second < 3) - continue; - - const uint totalSize = reverseTable[i].size()*numXorInMatrix[a].second; - const double density = (double)sumXorSizeInMatrix[i]/(double)totalSize*100.0; - double avg = (double)sumXorSizeInMatrix[i]/(double)numXorInMatrix[a].second; - double variance = 0.0; - for (uint i2 = 0; i2 < xorSizesInMatrix[i].size(); i2++) - variance += pow((double)xorSizesInMatrix[i][i2]-avg, 2); - variance /= (double)xorSizesInMatrix.size(); - const double stdDeviation = sqrt(variance); - - if (numXorInMatrix[a].second >= 20 - && numXorInMatrix[a].second <= 1000 - && realMatrixNum < 3) - { - if (solver.verbosity >=1) - cout << "c | Matrix no " << std::setw(4) << realMatrixNum; - solver.gauss_matrixes.push_back(new Gaussian(solver, solver.gaussconfig, realMatrixNum, xorsInMatrix[i])); - realMatrixNum++; - - } else { - if (solver.verbosity >=1 /*&& numXorInMatrix[a].second >= 20*/) - cout << "c | Unused Matrix "; - } - 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; - cout << " stdev:" << std::setw(6) << std::fixed << std::setprecision(2) << stdDeviation << " |" << endl; - } - } - - return realMatrixNum; -} - -void MatrixFinder::findParts(vector& xorFingerprintInMatrix, vector& xorsInMatrix) -{ - uint ai = 0; - for (XorClause **a = &xorsInMatrix[0], **end = a + xorsInMatrix.size(); a != end; a++, ai++) { - const Var fingerprint = xorFingerprintInMatrix[ai]; - uint ai2 = 0; - for (XorClause **a2 = &xorsInMatrix[0]; a2 != end; a2++, ai2++) { - if (ai == ai2) continue; - const Var fingerprint2 = xorFingerprintInMatrix[ai2]; - if (((fingerprint & fingerprint2) == fingerprint) && firstPartOfSecond(**a, **a2)) { - cout << "First part of second:" << endl; - (*a)->plainPrint(); - (*a2)->plainPrint(); - cout << "END" << endl; - } - } - } -} - -}; //NAMESPACE MINISAT diff --git a/src/sat/cryptominisat2/MatrixFinder.h b/src/sat/cryptominisat2/MatrixFinder.h index 7be3506..e69de29 100644 --- a/src/sat/cryptominisat2/MatrixFinder.h +++ b/src/sat/cryptominisat2/MatrixFinder.h @@ -1,72 +0,0 @@ -/*********************************************************************************** -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 MATRIXFINDER_H -#define MATRIXFINDER_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; - -using std::map; -using std::vector; -using std::pair; - -class MatrixFinder { - - public: - MatrixFinder(Solver& solver); - const uint findMatrixes(); - - private: - const uint setMatrixes(); - - struct mysorter - { - bool operator () (const pair& left, const pair& right) - { - return left.second < right.second; - } - }; - - void findParts(vector& xorFingerprintInMatrix, vector& xorsInMatrix); - inline const Var fingerprint(const XorClause& c) const; - inline const bool firstPartOfSecond(const XorClause& c1, const XorClause& c2) const; - - map > reverseTable; //matrix -> vars - vector table; //var -> matrix - uint matrix_no; - - Solver& solver; -}; - -}; //NAMESPACE MINISAT - -#endif //MATRIXFINDER_H diff --git a/src/sat/cryptominisat2/MersenneTwister.h b/src/sat/cryptominisat2/MersenneTwister.h index 964ecc7..e69de29 100644 --- a/src/sat/cryptominisat2/MersenneTwister.h +++ b/src/sat/cryptominisat2/MersenneTwister.h @@ -1,427 +0,0 @@ -// 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/PartFinder.cpp b/src/sat/cryptominisat2/PartFinder.cpp index 5ab39cd..534032f 100644 --- a/src/sat/cryptominisat2/PartFinder.cpp +++ b/src/sat/cryptominisat2/PartFinder.cpp @@ -60,12 +60,12 @@ const bool PartFinder::findParts() part_no = 0; solver.clauseCleaner->removeAndCleanAll(true); - if (solver.ok == false) return false; + if (!solver.ok) 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; + if (!solver.ok) return false; } assert(solver.varReplacer->getClauses().size() == 0); diff --git a/src/sat/cryptominisat2/PartHandler.cpp b/src/sat/cryptominisat2/PartHandler.cpp index c1773bd..27c5674 100644 --- a/src/sat/cryptominisat2/PartHandler.cpp +++ b/src/sat/cryptominisat2/PartHandler.cpp @@ -38,8 +38,12 @@ const bool PartHandler::handle() return true; PartFinder partFinder(solver); - if (!partFinder.findParts()) + if (!partFinder.findParts()) { + #ifdef VERBOSE_DEBUG + std::cout << "c findParts() found UNSAT. Whole problem is unsat." << std::endl; + #endif //VERBOSE_DEBUG return false; + } uint32_t num_parts = partFinder.getReverseTable().size(); if (num_parts == 1) @@ -80,19 +84,23 @@ const bool PartHandler::handle() newSolver.doPartHandler = solver.doPartHandler; newSolver.fixRestartType = solver.fixRestartType; newSolver.var_inc = solver.var_inc; - newSolver.polarity_mode = Solver::polarity_manual; + newSolver.polarity_mode = solver.polarity_mode; 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) { + #ifdef VERBOSE_DEBUG + if (!solver.decision_var[var]) { + std::cout << "var " << var + 1 << " is non-decision, but in part... strange." << std::endl; + } + #endif //VERBOSE_DEBUG 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); + decisionVarRemoved.push(var); } i2++; } else { @@ -111,8 +119,12 @@ const bool PartHandler::handle() assert(checkClauseMovement(newSolver, part, partFinder)); lbool status = newSolver.solve(); - if (status == l_False) + if (status == l_False) { + #ifdef VERBOSE_DEBUG + std::cout << "c One of the sub-problems was UNSAT. Whole problem is unsat." << std::endl; + #endif //VERBOSE_DEBUG return false; + } assert(status != l_Undef); for (Var var = 0; var < newSolver.nVars(); var++) { @@ -130,9 +142,13 @@ const bool PartHandler::handle() for (Var var = 0; var < newSolver.nVars(); var++) { if (newSolver.model[var] != l_Undef) { + //Must have been decision var in the old solver!?? + //assert(std::find(decisionVarRemoved.getData(), decisionVarRemoved.getDataEnd(), var) != decisionVarRemoved.getDataEnd()); assert(savedState[var] == l_Undef); assert(partFinder.getVarPart(var) == part); - savedState[var] = newSolver.model[var]; + if (newSolver.assigns[var] == l_Undef) { + savedState[var] = newSolver.model[var]; + } } } @@ -194,9 +210,14 @@ void PartHandler::moveClauses(vec& cs, Solver& newSolver, const uint32_ continue; } solver.detachClause(**i); - vec cs((*i)->size()); - std::copy((**i).getData(), (**i).getDataEnd(), cs.getData()); - newSolver.addClause(cs, (**i).getGroup()); + #ifdef VERBOSE_DEBUG + std::cout << "clause in this part:"; (**i).plainPrint(); + #endif + + Clause& c = **i; + vec tmp(c.size()); + std::copy(c.getData(), c.getDataEnd(), tmp.getData()); + newSolver.addClause(tmp, c.getGroup()); //NOTE: we need the CS because otherwise, the addClause could have changed **i, which we need to re-add later! clausesRemoved.push(*i); } @@ -212,10 +233,14 @@ void PartHandler::moveClauses(vec& cs, Solver& newSolver, const uint 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()); + #ifdef VERBOSE_DEBUG + std::cout << "xor clause in this part:"; (**i).plainPrint(); + #endif + + XorClause& c = **i; + vec tmp(c.size()); + std::copy(c.getData(), c.getDataEnd(), tmp.getData()); + newSolver.addXorClause(tmp, c.xor_clause_inverted(), c.getGroup()); //NOTE: we need the CS because otherwise, the addXorClause could have changed **i, which we need to re-add later! xorClausesRemoved.push(*i); } @@ -238,7 +263,7 @@ void PartHandler::moveLearntClauses(vec& cs, Solver& newSolver, const u 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; + std::cout << "Learnt clause in both parts:"; c.plainPrint(); #endif removed = true; @@ -249,15 +274,15 @@ void PartHandler::moveLearntClauses(vec& cs, Solver& newSolver, const u if (removed) continue; if (clause_part == part) { #ifdef VERBOSE_DEBUG - std::cout << "Learnt clause in this part!" << std::endl; + //std::cout << "Learnt clause in this part:"; c.plainPrint(); #endif solver.detachClause(c); newSolver.addLearntClause(c, c.getGroup(), c.activity()); - free(*i); + clauseFree(&c); } else { #ifdef VERBOSE_DEBUG - std::cout << "Learnt clause in other part!" << std::endl; + std::cout << "Learnt clause in other part:"; c.plainPrint(); #endif *j++ = *i; @@ -268,10 +293,11 @@ void PartHandler::moveLearntClauses(vec& cs, Solver& newSolver, const u void PartHandler::addSavedState() { + //Don't add these (non-0-decison-level!) solutions to the 0th decision level + solver.newDecisionLevel(); 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 + assert(solver.assigns[var] == l_Undef); solver.uncheckedEnqueue(Lit(var, savedState[var] == l_False)); assert(solver.assigns[var] == savedState[var]); savedState[var] = l_Undef; @@ -279,8 +305,8 @@ void PartHandler::addSavedState() } } - for (uint32_t var = 0; var < decisionVarRemoved.size(); var++) - solver.setDecisionVar(var, true); + for (uint32_t i = 0; i < decisionVarRemoved.size(); i++) + solver.setDecisionVar(decisionVarRemoved[i], true); decisionVarRemoved.clear(); } @@ -295,10 +321,7 @@ void PartHandler::readdRemovedClauses() 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()); + solver.addXorClause(**it, (**it).xor_clause_inverted(), (*it)->getGroup()); assert(solver.ok); } xorClausesRemoved.clear(); diff --git a/src/sat/cryptominisat2/Solver.cpp b/src/sat/cryptominisat2/Solver.cpp index 1c877a8..2da63b2 100644 --- a/src/sat/cryptominisat2/Solver.cpp +++ b/src/sat/cryptominisat2/Solver.cpp @@ -32,7 +32,6 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "VarReplacer.h" #include "FindUndef.h" -#include "Conglomerate.h" #include "XorFinder.h" #include "ClauseCleaner.h" #include "RestartTypeChooser.h" @@ -40,6 +39,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "Subsumer.h" #include "PartHandler.h" #include "XorSubsumer.h" +#include "StateSaver.h" #ifdef USE_GAUSS #include "Gaussian.h" @@ -51,6 +51,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA //#define __builtin_prefetch(a,b) #endif //_MSC_VER +//#define DEBUG_UNCHECKEDENQUEUE_LEVEL0 //#define VERBOSE_DEBUG_POLARITIES //#define DEBUG_DYNAMIC_RESTART @@ -89,6 +90,12 @@ Solver::Solver() : , doVarElim (true) , doSubsume1 (true) , failedVarSearch (true) + , readdOldLearnts (false) + , addExtraBins (true) + , removeUselessBins(true) + , regularRemoveUselessBins(true) + , subsumeWithNonExistBinaries(true) + , regularSubsumeWithNonExistBinaries(true) , libraryUsage (true) , greedyUnbound (false) , fixRestartType (auto_restart) @@ -101,6 +108,10 @@ Solver::Solver() : , improvedClauseNo(0), improvedClauseSize(0) + , sum_gauss_called (0) + , sum_gauss_confl (0) + , sum_gauss_prop (0) + , sum_gauss_unit_truths (0) , ok (true) , var_inc (128) , cla_inc (1) @@ -129,12 +140,15 @@ Solver::Solver() : , simplifying (false) { varReplacer = new VarReplacer(*this); - conglomerate = new Conglomerate(*this); clauseCleaner = new ClauseCleaner(*this); failedVarSearcher = new FailedVarSearcher(*this); partHandler = new PartHandler(*this); subsumer = new Subsumer(*this); + xorSubsumer = new XorSubsumer(*this); restartTypeChooser = new RestartTypeChooser(*this); + #ifdef USE_GAUSS + matrixFinder = new MatrixFinder(*this); + #endif //USE_GAUSS #ifdef STATS_NEEDED logger.setSolver(this); @@ -146,16 +160,20 @@ Solver::~Solver() 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]); + for (uint32_t i = 0; i != xorclauses.size(); i++) clauseFree(xorclauses[i]); + for (uint32_t i = 0; i != removedLearnts.size(); i++) clauseFree(removedLearnts[i]); #ifdef USE_GAUSS clearGaussMatrixes(); + delete matrixFinder; #endif + for (uint32_t i = 0; i != freeLater.size(); i++) clauseFree(freeLater[i]); + delete varReplacer; - delete conglomerate; delete clauseCleaner; delete failedVarSearcher; delete partHandler; delete subsumer; + delete xorSubsumer; delete restartTypeChooser; if (libraryCNFFile) @@ -184,16 +202,18 @@ Var Solver::newVar(bool dvar) seen .push_back(0); permDiff .push(0); - polarity .push_back(true); - defaultPolarities.push_back(true); + polarity .push_back(defaultPolarity()); + #ifdef USE_OLD_POLARITIES + oldPolarity.push_back(defaultPolarity()); + #endif //USE_OLD_POLARITIES decision_var.push_back(dvar); insertVarOrder(v); varReplacer->newVar(); - conglomerate->newVar(); partHandler->newVar(); subsumer->newVar(); + xorSubsumer->newVar(); insertVarOrder(v); @@ -211,18 +231,18 @@ Var Solver::newVar(bool dvar) template XorClause* Solver::addXorClauseInt(T& ps, bool xor_clause_inverted, const uint32_t group) { + assert(qhead == trail.size()); + assert(decisionLevel() == 0); + if (ps.size() > (0x01UL << 18)) { std::cout << "Too long clause!" << std::endl; exit(-1); } - std::sort(ps.getData(), ps.getData()+ps.size()); + std::sort(ps.getData(), ps.getDataEnd()); 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) { + if (ps[i].var() == p.var()) { //added, but easily removed j--; p = lit_Undef; @@ -241,8 +261,7 @@ XorClause* Solver::addXorClauseInt(T& ps, bool xor_clause_inverted, const uint32 return NULL; } case 1: { - assert(assigns[ps[0].var()].isUndef()); - uncheckedEnqueue(ps[0] ^ xor_clause_inverted); + uncheckedEnqueue(Lit(ps[0].var(), xor_clause_inverted)); ok = (propagate() == NULL); return NULL; } @@ -250,7 +269,10 @@ XorClause* Solver::addXorClauseInt(T& ps, bool xor_clause_inverted, const uint32 #ifdef VERBOSE_DEBUG cout << "--> xor is 2-long, replacing var " << ps[0].var()+1 << " with " << (!xor_clause_inverted ? "-" : "") << ps[1].var()+1 << endl; #endif - + + learnt_clause_group = std::max(group+1, learnt_clause_group); + ps[0] = ps[0].unsign(); + ps[1] = ps[1].unsign(); varReplacer->replace(ps, xor_clause_inverted, group); return NULL; } @@ -277,9 +299,7 @@ bool Solver::addXorClause(T& ps, bool xor_clause_inverted, const uint group, cha if (libraryCNFFile) { fprintf(libraryCNFFile, "x"); - for (uint i = 0; i < ps.size(); i++) { - fprintf(libraryCNFFile, "%s%d ", ps[i].sign() ? "-" : "", ps[i].var()+1); - } + for (uint32_t i = 0; i < ps.size(); i++) ps[i].print(libraryCNFFile); fprintf(libraryCNFFile, "0\n"); } @@ -293,11 +313,19 @@ bool Solver::addXorClause(T& ps, bool xor_clause_inverted, const uint group, cha assert(qhead == trail.size()); // Check if clause is satisfied and remove false/duplicate literals: - if (varReplacer->getNumLastReplacedVars() || subsumer->getNumElimed()) { + if (varReplacer->getNumLastReplacedVars() || subsumer->getNumElimed() || xorSubsumer->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; + else if (xorSubsumer->getVarElimed()[ps[i].var()] && !xorSubsumer->unEliminate(ps[i].var())) + return false; + else { + Lit otherLit = varReplacer->getReplaceTable()[ps[i].var()]; + if (otherLit.var() != ps[i].var()) { + ps[i] = Lit(otherLit.var(), false); + xor_clause_inverted ^= otherLit.sign(); + } + } } } @@ -315,14 +343,19 @@ template bool Solver::addLearntClause(T& ps, const uint group, const uint32_t activity) { Clause* c = addClauseInt(ps, group); - if (c == NULL) - return ok; - + if (c == NULL) return ok; + + //compensate for addClauseInt's attachClause, which doesn't know + //that this is a learnt clause. clauses_literals -= c->size(); + learnts_literals += c->size(); c->makeLearnt(activity); - learnts.push(c); - learnts_literals += c->size(); + if (c->size() > 2) learnts.push(c); + else { + nbBin++; + binaryClauses.push(c); + } return ok; } template bool Solver::addLearntClause(Clause& ps, const uint group, const uint32_t activity); @@ -333,7 +366,7 @@ Clause* Solver::addClauseInt(T& ps, uint group) { assert(ok); - std::sort(ps.getData(), ps.getData()+ps.size()); + std::sort(ps.getData(), ps.getDataEnd()); Lit p = lit_Undef; uint32_t i, j; for (i = j = 0; i != ps.size(); i++) { @@ -373,9 +406,7 @@ bool Solver::addClause(T& ps, const uint group, char* group_name) } if (libraryCNFFile) { - for (uint32_t i = 0; i != ps.size(); i++) { - fprintf(libraryCNFFile, "%s%d ", ps[i].sign() ? "-" : "", ps[i].var()+1); - } + for (uint32_t i = 0; i != ps.size(); i++) ps[i].print(libraryCNFFile); fprintf(libraryCNFFile, "0\n"); } @@ -389,11 +420,13 @@ bool Solver::addClause(T& ps, const uint group, char* group_name) assert(qhead == trail.size()); // Check if clause is satisfied and remove false/duplicate literals: - if (varReplacer->getNumLastReplacedVars() || subsumer->getNumElimed()) { + if (varReplacer->getNumLastReplacedVars() || subsumer->getNumElimed() || xorSubsumer->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; + if (xorSubsumer->getVarElimed()[ps[i].var()] && !xorSubsumer->unEliminate(ps[i].var())) + return false; } } @@ -414,6 +447,10 @@ template bool Solver::addClause(Clause& ps, const uint group, char* group_name); void Solver::attachClause(XorClause& c) { assert(c.size() > 2); + #ifdef DEBUG_ATTACH + assert(assigns[c[0].var()] == l_Undef); + assert(assigns[c[1].var()] == l_Undef); + #endif //DEBUG_ATTACH xorwatches[c[0].var()].push(&c); xorwatches[c[1].var()].push(&c); @@ -513,24 +550,27 @@ void Solver::cancelUntil(int level) cout << endl; #endif - if (decisionLevel() > level) { + if ((int)decisionLevel() > level) { #ifdef USE_GAUSS for (vector::iterator gauss = gauss_matrixes.begin(), end= gauss_matrixes.end(); gauss != end; gauss++) (*gauss)->canceling(trail_lim[level]); #endif //USE_GAUSS - for (int c = trail.size()-1; c >= (int)trail_lim[level]; c--) { - Var x = trail[c].var(); + for (int sublevel = trail.size()-1; sublevel >= (int)trail_lim[level]; sublevel--) { + Var var = trail[sublevel].var(); #ifdef VERBOSE_DEBUG - cout << "Canceling var " << x+1 << " sublevel: " << c << endl; + cout << "Canceling var " << var+1 << " sublevel: " << sublevel << endl; #endif - assigns[x] = l_Undef; - insertVarOrder(x); + #ifdef USE_OLD_POLARITIES + polarity[var] = oldPolarity[var]; + #endif //USE_OLD_POLARITIES + assigns[var] = l_Undef; + insertVarOrder(var); } qhead = trail_lim[level]; - trail.shrink(trail.size() - trail_lim[level]); - trail_lim.shrink(trail_lim.size() - level); + trail.shrink_(trail.size() - trail_lim[level]); + trail_lim.shrink_(trail_lim.size() - level); } #ifdef VERBOSE_DEBUG @@ -567,6 +607,8 @@ inline bool Solver::defaultPolarity() return false; case polarity_rnd: return mtrand.randInt(1); + case polarity_auto: + return true; default: assert(false); } @@ -574,72 +616,57 @@ inline bool Solver::defaultPolarity() return true; } -void tallyVotes(const vec& cs, vector& votes, vector& positiveLiteral, vector& negativeLiteral) +void Solver::tallyVotes(const vec& cs, vector& votes) const { 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)); + 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; - } + if (it2->sign()) votes[it2->var()] += divider; + else votes[it2->var()] -= divider; } } } -void tallyVotes(const vec& cs, vector& votes, vector& positiveLiteral, vector& negativeLiteral) +void Solver::tallyVotes(const vec& cs, vector& votes) const { 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++) { + 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() +void 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); + tallyVotes(clauses, votes); + tallyVotes(binaryClauses, votes); + tallyVotes(varReplacer->getClauses(), votes); + tallyVotes(xorclauses, votes); Var i = 0; for (vector::const_iterator it = votes.begin(), end = votes.end(); it != end; it++, i++) { - defaultPolarities[i] = (*it >= 0.0); + polarity[i] = (*it >= 0.0); #ifdef VERBOSE_DEBUG_POLARITIES std::cout << !defaultPolarities[i] << ", "; #endif //VERBOSE_DEBUG_POLARITIES @@ -650,27 +677,13 @@ const lbool Solver::calculateDefaultPolarities() << 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 - } + } else { + std::fill(polarity.begin(), polarity.end(), defaultPolarity()); } + #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]; } //================================================================================================= @@ -710,10 +723,10 @@ Lit Solver::pickBranchLit() if (next != var_Undef) { if (simplifying && random) sign = mtrand.randInt(1); - /*else - sign = polarity[next] ^ (mtrand.randInt(200) == 1);*/ + #ifdef RANDOM_LOOKAROUND_SEARCHSPACE else if (avgBranchDepth.isvalid()) - sign = polarity[next] ^ (mtrand.randInt(avgBranchDepth.getavg()) == 1); + sign = polarity[next] ^ (mtrand.randInt(avgBranchDepth.getavg() * ((lastSelectedRestartType == static_restart) ? 2 : 1) ) == 1); + #endif else sign = polarity[next]; } @@ -771,7 +784,7 @@ bool subset(const T1& A, const T2& B, vector& seen) | Effect: | Will undo part of the trail, upto but not beyond the assumption of the current decision level. |________________________________________________________________________________________________@*/ -Clause* Solver::analyze(Clause* confl, vec& out_learnt, int& out_btlevel, int &nbLevels, const bool update) +Clause* Solver::analyze(Clause* confl, vec& out_learnt, int& out_btlevel, uint32_t &nbLevels, const bool update) { int pathC = 0; Lit p = lit_Undef; @@ -799,11 +812,11 @@ Clause* Solver::analyze(Clause* confl, vec& out_learnt, int& out_btlevel, i if (!seen[my_var] && level[my_var] > 0) { varBumpActivity(my_var); seen[my_var] = 1; - if (level[my_var] >= decisionLevel()) { + if (level[my_var] >= (int)decisionLevel()) { pathC++; #ifdef UPDATEVARACTIVITY - if ( reason[q.var()] != NULL && reason[q.var()]->learnt() ) - lastDecisionLevel.push(q); + if (lastSelectedRestartType == dynamic_restart && reason[q.var()] != NULL && reason[q.var()]->learnt()) + lastDecisionLevel.push(q.var()); #endif } else { out_learnt.push(q); @@ -869,26 +882,18 @@ Clause* Solver::analyze(Clause* confl, vec& out_learnt, int& out_btlevel, i out_btlevel = level[p.var()]; } - nbLevels = 0; - MYFLAG++; - for(uint32_t i = 0; i != out_learnt.size(); i++) { - int lev = level[out_learnt[i].var()]; - if (permDiff[lev] != MYFLAG) { - permDiff[lev] = MYFLAG; - nbLevels++; - //merged += nbPropagated(lev); - } - } - - #ifdef UPDATEVARACTIVITY - if (lastDecisionLevel.size() > 0) { + if (lastSelectedRestartType == dynamic_restart) { + nbLevels = calcNBLevels(out_learnt); + #ifdef UPDATEVARACTIVITY for(uint32_t i = 0; i != lastDecisionLevel.size(); i++) { - if (reason[lastDecisionLevel[i].var()]->activity() < nbLevels) - varBumpActivity(lastDecisionLevel[i].var()); + if (reason[lastDecisionLevel[i]]->activity() < nbLevels) + varBumpActivity(lastDecisionLevel[i]); } lastDecisionLevel.clear(); + #endif + } else { + nbLevels = 1000; } - #endif for (uint32_t j = 0; j != analyze_toclear.size(); j++) seen[analyze_toclear[j].var()] = 0; // ('seen[]' is now cleared) @@ -983,15 +988,24 @@ void Solver::analyzeFinal(Lit p, vec& out_conflict) 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; - #endif + + #ifdef DEBUG_UNCHECKEDENQUEUE_LEVEL0 + #ifndef VERBOSE_DEBUG + if (decisionLevel() == 0) + #endif //VERBOSE_DEBUG + std::cout << "uncheckedEnqueue var " << p.var()+1 << " to " << !p.sign() << " level: " << decisionLevel() << " sublevel: " << trail.size() << std::endl; + #endif //DEBUG_UNCHECKEDENQUEUE_LEVEL0 + + //assert(decisionLevel() == 0 || !subsumer->getVarElimed()[p.var()]); assert(assigns[p.var()].isUndef()); const Var v = p.var(); assigns [v] = boolToLBool(!p.sign());//lbool(!sign(p)); // <<== abstract but not uttermost effecient level [v] = decisionLevel(); reason [v] = from; + #ifdef USE_OLD_POLARITIES + oldPolarity[p.var()] = polarity[p.var()]; + #endif //USE_OLD_POLARITIES polarity[p.var()] = p.sign(); trail.push(p); @@ -1001,7 +1015,6 @@ void Solver::uncheckedEnqueue(Lit p, ClausePtr from) #endif } - /*_________________________________________________________________________________________________ | | propagate : [void] -> [Clause*] @@ -1025,16 +1038,12 @@ Clause* Solver::propagate(const bool update) while (qhead < trail.size()) { - Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate. - vec& ws = watches[p.toInt()]; - Watched *i, *j, *end; - //First propagate binary clauses 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++) { + num_props += wbin.size()/2; + for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) { lbool val = value(k->impliedLit); if (val.isUndef()) { uncheckedEnqueue(k->impliedLit, k->clause); @@ -1046,14 +1055,18 @@ Clause* Solver::propagate(const bool update) } if (confl != NULL) goto EndPropagate; - + //Next, propagate normal clauses + Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate. + vec& ws = watches[p.toInt()]; + Watched *i, *j, *end; + num_props += ws.size(); #ifdef VERBOSE_DEBUG cout << "Propagating lit " << (p.sign() ? '-' : ' ') << p.var()+1 << endl; #endif - for (i = j = ws.getData(), end = i + ws.size(); i != end;) { + for (i = j = ws.getData(), end = ws.getDataEnd(); i != end;) { if (i+1 != end) __builtin_prefetch((i+1)->clause, 1, 0); @@ -1080,7 +1093,7 @@ Clause* Solver::propagate(const bool update) j++; } else { // Look for new watch: - for (Lit *k = &c[2], *end2 = c.getData()+c.size(); k != end2; k++) { + for (Lit *k = &c[2], *end2 = c.getDataEnd(); k != end2; k++) { if (value(*k) != l_False) { c[1] = *k; *k = false_lit; @@ -1103,17 +1116,8 @@ Clause* Solver::propagate(const bool update) uncheckedEnqueue(first, &c); #ifdef DYNAMICNBLEVEL if (update && c.learnt() && c.activity() > 2) { // GA - MYFLAG++; - int nbLevels =0; - 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++; - } - - } - if(nbLevels+1 < c.activity()) + uint32_t nbLevels = calcNBLevels(c); + if (nbLevels+1 < c.activity()) c.setActivity(nbLevels); } #endif @@ -1122,7 +1126,7 @@ Clause* Solver::propagate(const bool update) FoundWatch: ; } - ws.shrink(i - j); + ws.shrink_(i - j); //Finally, propagate XOR-clauses if (xorclauses.size() > 0 && !confl) confl = propagate_xors(p); @@ -1138,6 +1142,205 @@ EndPropagate: return confl; } +Clause* Solver::propagateLight() +{ + Clause* confl = NULL; + uint32_t num_props = 0; + uint32_t qheadBin = qhead; + + while (qhead < trail.size()) { + + //First propagate binary clauses + while (qheadBin < trail.size()) { + Lit p = trail[qheadBin++]; + vec & wbin = binwatches[p.toInt()]; + num_props += wbin.size()/2; + for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) { + lbool val = value(k->impliedLit); + if (val.isUndef()) { + uncheckedEnqueueLight(k->impliedLit); + } else if (val == l_False) { + confl = k->clause; + goto EndPropagate; + } + } + } + + //Next, propagate normal clauses + Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate. + vec& ws = watches[p.toInt()]; + Watched *i, *j, *end; + num_props += ws.size(); + + for (i = j = ws.getData(), end = ws.getDataEnd(); i != end;) { + if (i+1 != end) + __builtin_prefetch((i+1)->clause, 1, 0); + + if(value(i->blockedLit).getBool()) { // Clause is sat + *j++ = *i++; + continue; + } + Lit bl = i->blockedLit; + Clause& c = *(i->clause); + i++; + + // Make sure the false literal is data[1]: + const Lit false_lit(~p); + if (c[0] == false_lit) + c[0] = c[1], c[1] = false_lit; + + assert(c[1] == false_lit); + + // If 0th watch is true, then clause is already satisfied. + const Lit& first = c[0]; + if (value(first).getBool()) { + j->clause = &c; + j->blockedLit = first; + j++; + } else { + // Look for new watch: + for (Lit *k = &c[2], *end2 = c.getDataEnd(); 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; + j->blockedLit = bl; + j++; + if (value(first) == l_False) { + confl = &c; + qhead = trail.size(); + // Copy the remaining watches: + while (i < end) + *j++ = *i++; + } else { + uncheckedEnqueueLight(first); + } + } + FoundWatch: + ; + } + ws.shrink_(i - j); + + //Finally, propagate XOR-clauses + if (xorclauses.size() > 0 && !confl) confl = propagate_xors(p); + } + EndPropagate: + propagations += num_props; + simpDB_props -= num_props; + + return confl; +} + +Clause* Solver::propagateBin() +{ + while (qhead < trail.size()) { + Lit p = trail[qhead++]; + vec & wbin = binwatches[p.toInt()]; + propagations += wbin.size()/2; + for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) { + lbool val = value(k->impliedLit); + if (val.isUndef()) { + //uncheckedEnqueue(k->impliedLit, k->clause); + uncheckedEnqueueLight(k->impliedLit); + } else if (val == l_False) { + return k->clause; + } + } + } + + return NULL; +} + +Clause* Solver::propagateBinNoLearnts() +{ + while (qhead < trail.size()) { + Lit p = trail[qhead++]; + vec & wbin = binwatches[p.toInt()]; + propagations += wbin.size()/2; + for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) { + if (k->clause->learnt()) continue; + lbool val = value(k->impliedLit); + if (val.isUndef()) { + //uncheckedEnqueue(k->impliedLit, k->clause); + uncheckedEnqueueLight(k->impliedLit); + } else if (val == l_False) { + return k->clause; + } + } + } + + return NULL; +} + +template +Clause* Solver::propagateBinExcept(const Lit& exceptLit) +{ + while (qhead < trail.size()) { + Lit p = trail[qhead++]; + vec & wbin = binwatches[p.toInt()]; + propagations += wbin.size()/2; + for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) { + if (!dontCareLearnt && k->clause->learnt()) continue; + lbool val = value(k->impliedLit); + if (val.isUndef() && k->impliedLit != exceptLit) { + //uncheckedEnqueue(k->impliedLit, k->clause); + uncheckedEnqueueLight(k->impliedLit); + } else if (val == l_False) { + return k->clause; + } + } + } + + return NULL; +} + +template Clause* Solver::propagateBinExcept (const Lit& exceptLit); +template Clause* Solver::propagateBinExcept (const Lit& exceptLit); + +template +Clause* Solver::propagateBinOneLevel() +{ + Lit p = trail[qhead]; + vec & wbin = binwatches[p.toInt()]; + propagations += wbin.size()/2; + for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) { + if (!dontCareLearnt && k->clause->learnt()) continue; + lbool val = value(k->impliedLit); + if (val.isUndef()) { + //uncheckedEnqueue(k->impliedLit, k->clause); + uncheckedEnqueueLight(k->impliedLit); + } else if (val == l_False) { + return k->clause; + } + } + + return NULL; +} + +template Clause* Solver::propagateBinOneLevel (); +template Clause* Solver::propagateBinOneLevel (); + +template +inline const uint32_t Solver::calcNBLevels(const T& ps) +{ + MYFLAG++; + uint32_t nbLevels = 0; + for(const Lit *l = ps.getData(), *end = ps.getDataEnd(); l != end; l++) { + int32_t lev = level[l->var()]; + if (permDiff[lev] != MYFLAG) { + permDiff[lev] = MYFLAG; + nbLevels++; + } + } + return nbLevels; +} + Clause* Solver::propagate_xors(const Lit& p) { #ifdef VERBOSE_DEBUG_XOR @@ -1231,7 +1434,7 @@ Clause* Solver::propagate_xors(const Lit& p) FoundWatch: ; } - ws.shrink(i - j); + ws.shrink_(i - j); return confl; } @@ -1252,8 +1455,10 @@ bool reduceDB_ltMiniSat::operator () (const Clause* x, const Clause* y) { // First criteria if (xsize > 2 && ysize == 2) return 1; if (ysize > 2 && xsize == 2) return 0; - - return x->oldActivity() < y->oldActivity(); + + if (x->oldActivity() == y->oldActivity()) + return xsize > ysize; + else return x->oldActivity() < y->oldActivity(); } bool reduceDB_ltGlucose::operator () (const Clause* x, const Clause* y) { @@ -1280,20 +1485,27 @@ void Solver::reduceDB() std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_ltMiniSat()); #ifdef VERBOSE_DEBUG - std::cout << "Cleaning clauses" << endl; + std::cout << "Cleaning clauses" << std::endl; for (uint i = 0; i != learnts.size(); i++) { - std::cout << "activity:" << learnts[i]->activity() << " \tsize:" << learnts[i]->size() << std::endl; + std::cout << "activity:" << learnts[i]->activity() + << " \toldActivity:" << learnts[i]->oldActivity() + << " \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 + if (learnts[i]->size() > 2 && !locked(*learnts[i]) && learnts[i]->activity() > 2) { + if (readdOldLearnts) { + detachClause(*learnts[i]); + removedLearnts.push(learnts[i]); + } else { + removeClause(*learnts[i]); + } + } else learnts[j++] = learnts[i]; } for (; i < learnts.size(); i++) { @@ -1335,54 +1547,95 @@ void Solver::dumpSortedLearnts(const char* file, const uint32_t maxSize) printf("Error: Cannot open file '%s' to write learnt clauses!\n", file); exit(-1); } - + + fprintf(outfile, "c \nc ---------\n"); 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 ---------\n"); + for (uint32_t i = 0, end = (trail_lim.size() > 0) ? trail_lim[0] : trail.size() ; i < end; i++) { + trail[i].printFull(outfile); + #ifdef STATS_NEEDED + if (dynamic_behaviour_analysis) + fprintf(outfile, "c name of var: %s\n", logger.get_var_name(trail[i].var()).c_str()); + #endif //STATS_NEEDED } - - fprintf(outfile, "c clauses from binaryClauses\n"); + + fprintf(outfile, "c conflicts %lu\n", conflicts); + + fprintf(outfile, "c \nc ---------------------------------\n"); + fprintf(outfile, "c learnt clauses from binaryClauses\n"); + fprintf(outfile, "c ---------------------------------\n"); if (maxSize >= 2) { for (uint i = 0; i != binaryClauses.size(); i++) { - if (binaryClauses[i]->learnt()) - binaryClauses[i]->plainPrint(outfile); + if (binaryClauses[i]->learnt()) { + binaryClauses[i]->print(outfile); + } } } - - fprintf(outfile, "c clauses from learnts\n"); - - if (lastSelectedRestartType == dynamic_restart) - std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_ltGlucose()); - else - std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_ltMiniSat()); - for (int i = learnts.size()-1; i >= 0 ; i--) { - if (learnts[i]->size() <= maxSize) - learnts[i]->plainPrint(outfile); - } - + + fprintf(outfile, "c \nc ---------------------------------------\n"); fprintf(outfile, "c clauses representing 2-long XOR clauses\n"); + fprintf(outfile, "c ---------------------------------------\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); + #ifdef STATS_NEEDED + if (dynamic_behaviour_analysis) + fprintf(outfile, "c name of two vars that are anti/equivalent: '%s' and '%s'\n", logger.get_var_name(lit.var()).c_str(), logger.get_var_name(var).c_str()); + #endif //STATS_NEEDED + } + + fprintf(outfile, "c \nc --------------------n"); + fprintf(outfile, "c clauses from learnts\n"); + fprintf(outfile, "c --------------------n"); + if (lastSelectedRestartType == dynamic_restart) + std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_ltGlucose()); + else + std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_ltMiniSat()); + for (int i = learnts.size()-1; i >= 0 ; i--) { + if (learnts[i]->size() <= maxSize) { + learnts[i]->print(outfile); + } } fclose(outfile); } +const uint32_t Solver::getNumElimSubsume() const +{ + return subsumer->getNumElimed(); +} + +const uint32_t Solver::getNumElimXorSubsume() const +{ + return xorSubsumer->getNumElimed(); +} + +const uint32_t Solver::getNumXorTrees() const +{ + return varReplacer->getNumTrees(); +} + +const uint32_t Solver::getNumXorTreesCrownSize() const +{ + return varReplacer->getNumReplacedVars(); +} + +const double Solver::getTotalTimeSubsumer() const +{ + return subsumer->getTotalTime(); +} + +const double Solver::getTotalTimeXorSubsumer() const +{ + return xorSubsumer->getTotalTime(); +} + + void Solver::setMaxRestarts(const uint num) { maxRestarts = num; @@ -1402,17 +1655,18 @@ inline int64_t abs64(int64_t a) | Simplify the clause database according to the current top-level assigment. Currently, the only | thing done here is the removal of satisfied clauses, but more things can be put here. |________________________________________________________________________________________________@*/ -lbool Solver::simplify() +const bool Solver::simplify() { + testAllClauseAttach(); assert(decisionLevel() == 0); if (!ok || propagate() != NULL) { ok = false; - return l_False; + return false; } if (simpDB_props > 0) { - return l_Undef; + return true; } double slowdown = (100000.0/(double)binaryClauses.size()); @@ -1431,34 +1685,43 @@ lbool Solver::simplify() (((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; - + if (!ok) return false; + testAllClauseAttach(); + XorFinder xorFinder(*this, binaryClauses, ClauseCleaner::binaryClauses); - if (xorFinder.doNoPart(2, 2) == false) - return l_False; + if (!xorFinder.doNoPart(2, 2)) return false; + testAllClauseAttach(); lastNbBin = nbBin; becameBinary = 0; } - + // Remove satisfied clauses: clauseCleaner->removeAndCleanAll(); - if (ok == false) - return l_False; - if (performReplace && varReplacer->performReplace() == false) - return l_False; + testAllClauseAttach(); + if (!ok) return false; + + if (performReplace && !varReplacer->performReplace()) + return false; // Remove fixed variables from the variable heap: order_heap.filter(VarFilter(*this)); + #ifdef USE_GAUSS + for (vector::iterator gauss = gauss_matrixes.begin(), end = gauss_matrixes.end(); gauss != end; gauss++) { + if (!(*gauss)->full_init()) return false; + } + #endif //USE_GAUSS + simpDB_assigns = nAssigns(); simpDB_props = clauses_literals + learnts_literals; // (shouldn't depend on stats really, but it will do for now) - return l_Undef; + testAllClauseAttach(); + return true; } @@ -1490,12 +1753,14 @@ lbool Solver::search(int nof_conflicts, int nof_conflicts_fullrestart, const boo dynStarts++; #ifdef USE_GAUSS - 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 (vector::iterator gauss = gauss_matrixes.begin(), end = gauss_matrixes.end(); gauss != end; gauss++) { + if (!(*gauss)->full_init()) + return l_False; } #endif //USE_GAUSS + testAllClauseAttach(); + findAllAttach(); for (;;) { Clause* confl = propagate(update); @@ -1562,7 +1827,7 @@ llbool Solver::new_decision(const int& nof_conflicts, const int& nof_conflicts_f assert(false); break; } - if (nof_conflicts_fullrestart >= 0 && conflicts >= nof_conflicts_fullrestart) { + if (nof_conflicts_fullrestart >= 0 && (int)conflicts >= nof_conflicts_fullrestart) { #ifdef STATS_NEEDED if (dynamic_behaviour_analysis) progress_estimate = progressEstimate(); @@ -1572,7 +1837,7 @@ llbool Solver::new_decision(const int& nof_conflicts, const int& nof_conflicts_f } // Simplify the set of problem clauses: - if (decisionLevel() == 0 && simplify() == l_False) { + if (decisionLevel() == 0 && !simplify()) { return l_False; } @@ -1626,7 +1891,7 @@ llbool Solver::handle_conflict(vec& learnt_clause, Clause* confl, int& conf #endif int backtrack_level; - int nbLevels; + uint32_t nbLevels; conflicts++; conflictC++; @@ -1635,9 +1900,12 @@ llbool Solver::handle_conflict(vec& learnt_clause, Clause* confl, int& conf learnt_clause.clear(); Clause* c = analyze(confl, learnt_clause, backtrack_level, nbLevels, update); if (update) { + #ifdef RANDOM_LOOKAROUND_SEARCHSPACE avgBranchDepth.push(decisionLevel()); + #endif //RANDOM_LOOKAROUND_SEARCHSPACE if (restartType == dynamic_restart) nbDecisionLevelHistory.push(nbLevels); + totalSumOfDecisionLevel += nbLevels; } else { conflictsAtLastSolve++; @@ -1669,11 +1937,15 @@ llbool Solver::handle_conflict(vec& learnt_clause, Clause* confl, int& conf } else { if (c) { detachClause(*c); - for (uint i = 0; i != learnt_clause.size(); i++) + for (uint32_t 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 + if (c->learnt()) { + if (c->activity() > nbLevels) + c->setActivity(nbLevels); // LS + if (c->size() == 2) + nbBin++; + } c->setStrenghtened(); } else { c = Clause_new(learnt_clause, learnt_clause_group++, true); @@ -1715,9 +1987,9 @@ double Solver::progressEstimate() const } #ifdef USE_GAUSS -void Solver::print_gauss_sum_stats() const +void Solver::print_gauss_sum_stats() { - if (gauss_matrixes.size() == 0) { + if (gauss_matrixes.size() == 0 && verbosity >= 2) { printf(" no matrixes found |\n"); return; } @@ -1731,21 +2003,27 @@ void Solver::print_gauss_sum_stats() const called += (*gauss)->get_called(); useful_prop += (*gauss)->get_useful_prop(); useful_confl += (*gauss)->get_useful_confl(); + sum_gauss_unit_truths += (*gauss)->get_unit_truths(); //gauss->print_stats(); //gauss->print_matrix_stats(); } + sum_gauss_called += called; + sum_gauss_confl += useful_confl; + sum_gauss_prop += useful_prop; - if (called == 0) { - printf(" disabled |\n"); - } else { - printf(" %3.0lf%% |", (double)useful_prop/(double)called*100.0); - printf(" %3.0lf%% |", (double)useful_confl/(double)called*100.0); - printf(" %3.0lf%% |\n", 100.0-(double)disabled/(double)gauss_matrixes.size()*100.0); + if (verbosity >= 2) { + if (called == 0) { + printf(" disabled |\n"); + } else { + printf(" %3.0lf%% |", (double)useful_prop/(double)called*100.0); + printf(" %3.0lf%% |", (double)useful_confl/(double)called*100.0); + printf(" %3.0lf%% |\n", 100.0-(double)disabled/(double)gauss_matrixes.size()*100.0); + } } } #endif //USE_GAUSS -inline void Solver::chooseRestartType(const uint& lastFullRestart) +const bool Solver::chooseRestartType(const uint& lastFullRestart) { uint relativeStart = starts - lastFullRestart; @@ -1761,30 +2039,25 @@ inline void Solver::chooseRestartType(const uint& lastFullRestart) tmp = fixRestartType; if (tmp == dynamic_restart) { - lastSelectedRestartType = dynamic_restart; nbDecisionLevelHistory.fastclear(); nbDecisionLevelHistory.initSize(100); if (verbosity >= 2) printf("c | Decided on dynamic restart strategy |\n"); } else { - lastSelectedRestartType = static_restart; if (verbosity >= 2) printf("c | Decided on static restart strategy |\n"); #ifdef USE_GAUSS - 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 (!matrixFinder->findMatrixes()) return false; #endif //USE_GAUSS } + lastSelectedRestartType = tmp; restartType = tmp; restartTypeChooser->reset(); } } + + return true; } inline void Solver::setDefaultRestartType() @@ -1800,16 +2073,17 @@ inline void Solver::setDefaultRestartType() lastSelectedRestartType = restartType; } -const lbool Solver::simplifyProblem(const uint32_t numConfls, const uint64_t numProps) +const lbool Solver::simplifyProblem(const uint32_t numConfls) { - Heap backup_order_heap(order_heap); - vector backup_polarities = polarity; - RestartType backup_restartType= restartType; - uint32_t backup_random_var_freq = random_var_freq; - vec backup_activity(activity.size()); - std::copy(activity.getData(), activity.getDataEnd(), backup_activity.getData()); - uint32_t backup_var_inc = var_inc; - + testAllClauseAttach(); + #ifdef USE_GAUSS + bool gauss_was_cleared = (gauss_matrixes.size() == 0); + clearGaussMatrixes(); + #endif //USE_GAUSS + + StateSaver savedState(*this);; + + #ifdef BURST_SEARCH if (verbosity >= 2) std::cout << "c | " << std::setw(24) << " " << "Simplifying problem for " << std::setw(8) << numConfls << " confls" @@ -1817,8 +2091,11 @@ const lbool Solver::simplifyProblem(const uint32_t numConfls, const uint64_t num random_var_freq = 1; simplifying = true; uint64_t origConflicts = conflicts; + #endif //BURST_SEARCH lbool status = l_Undef; + + #ifdef BURST_SEARCH restartType = static_restart; while(status == l_Undef && conflicts-origConflicts < numConfls) { @@ -1829,44 +2106,37 @@ const lbool Solver::simplifyProblem(const uint32_t numConfls, const uint64_t num if (status != l_Undef) goto end; printRestartStat(); - - if (heuleProcess && xorclauses.size() > 1) { - if (!conglomerate->heuleProcessFull()) { - status = l_False; - goto end; - } - - while (performReplace && varReplacer->needsReplace()) { - if (!varReplacer->performReplace()) { - status = l_False; - goto end; - } - if (!conglomerate->heuleProcessFull()) { - status = l_False; - goto end; - } - } + #endif //BURST_SEARCH + + if (doXorSubsumption && !xorSubsumer->simplifyBySubsumption()) { + status = l_False; + goto end; } - - if (failedVarSearch && !failedVarSearcher->search((nClauses() < 500000 && order_heap.size() < 50000) ? 6000000 : 2000000)) { + testAllClauseAttach(); + + if (failedVarSearch && !failedVarSearcher->search((nClauses() < 500000 && order_heap.size() < 50000) ? 9000000 : 3000000)) { status = l_False; goto end; } - - if (doXorSubsumption && xorclauses.size() > 1) { - XorSubsumer xsub(*this); - if (!xsub.simplifyBySubsumption()) { - status = l_False; - goto end; - } + testAllClauseAttach(); + + if (regularRemoveUselessBins + && !failedVarSearcher->removeUslessBinFull()) { + status = l_False; + goto end; } - - if (doSubsumption) { - if (!subsumer->simplifyBySubsumption()) { - status = l_False; - goto end; - } + + if (regularSubsumeWithNonExistBinaries + && !subsumer->subsumeWithBinaries(false)) { + status = l_False; + goto end; } + + if (doSubsumption && !subsumer->simplifyBySubsumption()) { + status = l_False; + goto end; + } + testAllClauseAttach(); /*if (findNormalXors && xorclauses.size() > 200 && clauses.size() < MAX_CLAUSENUM_XORFIND/8) { XorFinder xorFinder(*this, clauses, ClauseCleaner::clauses); @@ -1880,24 +2150,27 @@ const lbool Solver::simplifyProblem(const uint32_t numConfls, const uint64_t num } end: - random_var_freq = backup_random_var_freq; + #ifdef BURST_SEARCH 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; + #endif //#ifdef BURST_SEARCH + + + savedState.restore(); simplifying = false; - order_heap.filter(VarFilter(*this)); - polarity = backup_polarities; - restartType = backup_restartType; + #ifdef USE_GAUSS + if (status == l_Undef && !gauss_was_cleared && !matrixFinder->findMatrixes()) + status = l_False; + #endif //USE_GAUSS + + testAllClauseAttach(); return status; } const bool Solver::checkFullRestart(int& nof_conflicts, int& nof_conflicts_fullrestart, uint& lastFullRestart) { - if (nof_conflicts_fullrestart > 0 && conflicts >= nof_conflicts_fullrestart) { + if (nof_conflicts_fullrestart > 0 && (int)conflicts >= nof_conflicts_fullrestart) { #ifdef USE_GAUSS clearGaussMatrixes(); #endif //USE_GAUSS @@ -1917,9 +2190,7 @@ const bool Solver::checkFullRestart(int& nof_conflicts, int& nof_conflicts_fullr if (doPartHandler && !partHandler->handle()) return false; - /*if (calculateDefaultPolarities() == l_False) - return false; - setDefaultPolarities();*/ + //calculateDefaultPolarities(); fullStarts++; } @@ -1930,46 +2201,48 @@ const bool Solver::checkFullRestart(int& nof_conflicts, int& nof_conflicts_fullr inline void Solver::performStepsBeforeSolve() { assert(qhead == trail.size()); + testAllClauseAttach(); + if (performReplace && !varReplacer->performReplace()) return; + + if (conflicts == 0 && learnts.size() == 0 + && noLearntBinaries()) { + if (subsumeWithNonExistBinaries && !subsumer->subsumeWithBinaries(true)) return; + if (removeUselessBins && !failedVarSearcher->removeUslessBinFull()) return; + } - + testAllClauseAttach(); if (doSubsumption && !libraryUsage && clauses.size() + binaryClauses.size() + learnts.size() < 4800000 && !subsumer->simplifyBySubsumption()) return; + + if (conflicts == 0 && learnts.size() == 0 + && noLearntBinaries()) { + if (subsumeWithNonExistBinaries && !subsumer->subsumeWithBinaries(true)) return; + if (removeUselessBins && !failedVarSearcher->removeUslessBinFull()) return; + } + testAllClauseAttach(); 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; } + testAllClauseAttach(); if (findNormalXors && clauses.size() < MAX_CLAUSENUM_XORFIND) { XorFinder xorFinder(*this, clauses, ClauseCleaner::clauses); if (!xorFinder.doNoPart(3, 7)) 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()) + testAllClauseAttach(); + if (doXorSubsumption && !xorSubsumer->simplifyBySubsumption()) return; - if (doXorSubsumption && xorclauses.size() > 1) { - XorSubsumer xsub(*this); - if (!xsub.simplifyBySubsumption()) - return; - } - + testAllClauseAttach(); if (performReplace && !varReplacer->performReplace()) return; } @@ -2003,20 +2276,20 @@ lbool Solver::solve(const vec& assumps) setDefaultRestartType(); totalSumOfDecisionLevel = 0; conflictsAtLastSolve = conflicts; + #ifdef RANDOM_LOOKAROUND_SEARCHSPACE avgBranchDepth.fastclear(); avgBranchDepth.initSize(500); - - if (!conglomerate->addRemovedClauses()) return l_False; + #endif //RANDOM_LOOKAROUND_SEARCHSPACE starts = 0; assumps.copyTo(assumptions); int nof_conflicts = restart_first; - int nof_conflicts_fullrestart = (double)restart_first * (double)FULLRESTART_MULTIPLIER + conflicts; + int nof_conflicts_fullrestart = restart_first * FULLRESTART_MULTIPLIER + conflicts; //nof_conflicts_fullrestart = -1; uint lastFullRestart = starts; lbool status = l_Undef; - uint64_t nextSimplify = 30000 + conflicts; + uint64_t nextSimplify = restart_first * SIMPLIFY_MULTIPLIER + conflicts; if (nClauses() * learntsize_factor < nbclausesbeforereduce) { if (nClauses() * learntsize_factor < nbclausesbeforereduce/2) @@ -2024,22 +2297,26 @@ lbool Solver::solve(const vec& assumps) else nbclausesbeforereduce = (nClauses() * learntsize_factor)/2; } + testAllClauseAttach(); + findAllAttach(); if (conflicts == 0) { performStepsBeforeSolve(); if (!ok) return l_False; printStatHeader(); - if (calculateDefaultPolarities() == l_False) - return l_False; - setDefaultPolarities(); } + calculateDefaultPolarities(); // Search: while (status == l_Undef && starts < maxRestarts) { + #ifdef DEBUG_VARELIM + assert(subsumer->checkElimedUnassigned()); + assert(xorSubsumer->checkElimedUnassigned()); + #endif //DEBUG_VARELIM if (schedSimplification && conflicts >= nextSimplify) { - status = simplifyProblem(500, 7000000); + status = simplifyProblem(500); nextSimplify = conflicts * 1.5; if (status != l_Undef) break; } @@ -2054,11 +2331,15 @@ lbool Solver::solve(const vec& assumps) status = search(nof_conflicts, nof_conflicts_fullrestart); nof_conflicts = (double)nof_conflicts * restart_inc; + if (status != l_Undef) break; if (!checkFullRestart(nof_conflicts, nof_conflicts_fullrestart, lastFullRestart)) return l_False; - chooseRestartType(lastFullRestart); + if (!chooseRestartType(lastFullRestart)) + return l_False; + #ifdef RANDOM_LOOKAROUND_SEARCHSPACE //if (avgBranchDepth.isvalid()) // std::cout << "avg branch depth:" << avgBranchDepth.getavg() << std::endl; + #endif //RANDOM_LOOKAROUND_SEARCHSPACE } printEndSearchStat(); @@ -2085,14 +2366,14 @@ lbool Solver::solve(const vec& assumps) if (verbosity >= 1) printf("c Greedy unbounding :%5.2lf s, unbounded: %7d vars\n", cpuTime()-time, unbounded); } - + partHandler->addSavedState(); varReplacer->extendModelPossible(); #ifndef NDEBUG //checkSolution(); #endif - if (subsumer->getNumElimed() > 0 || conglomerate->needCalcAtFinish()) { + if (subsumer->getNumElimed() || xorSubsumer->getNumElimed()) { #ifdef VERBOSE_DEBUG std::cout << "Solution needs extension. Extending." << std::endl; #endif //VERBOSE_DEBUG @@ -2105,12 +2386,11 @@ lbool Solver::solve(const vec& assumps) s.conglomerateXors = false; s.greedyUnbound = greedyUnbound; for (Var var = 0; var < nVars(); var++) { - s.newVar(decision_var[var] || subsumer->getVarElimed()[var] || varReplacer->varHasBeenReplaced(var) || conglomerate->getRemovedVars()[var]); + s.newVar(decision_var[var] || subsumer->getVarElimed()[var] || varReplacer->varHasBeenReplaced(var) || xorSubsumer->getVarElimed()[var]); - assert(!(conglomerate->getRemovedVars()[var] && (decision_var[var] || subsumer->getVarElimed()[var] || varReplacer->varHasBeenReplaced(var)))); + //assert(!(xorSubsumer->getVarElimed()[var] && (decision_var[var] || subsumer->getVarElimed()[var] || varReplacer->varHasBeenReplaced(var)))); if (value(var) != l_Undef) { - assert(!conglomerate->getRemovedVars()[var]); vec tmp; tmp.push(Lit(var, value(var) == l_False)); s.addClause(tmp); @@ -2118,7 +2398,7 @@ lbool Solver::solve(const vec& assumps) } varReplacer->extendModelImpossible(s); subsumer->extendModel(s); - conglomerate->extendModel(s); + xorSubsumer->extendModel(s); status = s.solve(); if (status != l_True) { @@ -2198,7 +2478,7 @@ bool Solver::verifyXorClauses(const vec& cs) const XorClause* c2 = XorClause_new(c, c.xor_clause_inverted(), c.getGroup()); std::sort(c2->getData(), c2->getData()+ c2->size()); c2->plainPrint(); - free(c2); + clauseFree(c2); #endif for (uint j = 0; j < c.size(); j++) { @@ -2243,12 +2523,10 @@ 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()); + printf("c Verified %d clauses.\n", clauses.size() + xorclauses.size()); } @@ -2282,23 +2560,22 @@ void Solver::printStatHeader() const } } -void Solver::printRestartStat() const +void Solver::printRestartStat() { - #ifdef STATS_NEEDED - if (verbosity >= 2 && !(dynamic_behaviour_analysis && logger.statistics_on)) { - #else 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+nbCompensateSubsumer), (int)nLearnts(), (double)learnts_literals/nLearnts()); - #ifdef USE_GAUSS - print_gauss_sum_stats(); - #else //USE_GAUSS + printf("c | %9d | %7d %8d %8d | %8d %8d %6.0f |", (int)conflicts, (int)order_heap.size(), (int)(nClauses()-nbBin), (int)clauses_literals, (int)(nbclausesbeforereduce*curRestart+nbCompensateSubsumer), (int)(nLearnts()+nbBin), (double)learnts_literals/(double)(nLearnts()+nbBin)); + } + + #ifdef USE_GAUSS + print_gauss_sum_stats(); + #else //USE_GAUSS + if (verbosity >= 2) { printf(" |\n"); - #endif //USE_GAUSS } + #endif //USE_GAUSS } -void Solver::printEndSearchStat() const +void Solver::printEndSearchStat() { #ifdef STATS_NEEDED if (verbosity >= 1 && !(dynamic_behaviour_analysis && logger.statistics_on)) { @@ -2314,5 +2591,94 @@ void Solver::printEndSearchStat() const } } -}; //NAMESPACE MINISAT +#ifdef DEBUG_ATTACH +void Solver::testAllClauseAttach() const +{ + for (Clause *const*it = clauses.getData(), *const*end = clauses.getDataEnd(); it != end; it++) { + const Clause& c = **it; + if (c.size() > 2) { + assert(findWatchedCl(watches[(~c[0]).toInt()], &c)); + assert(findWatchedCl(watches[(~c[1]).toInt()], &c)); + } else { + assert(findWatchedBinCl(binwatches[(~c[0]).toInt()], &c)); + assert(findWatchedBinCl(binwatches[(~c[1]).toInt()], &c)); + } + } + + for (Clause *const*it = binaryClauses.getData(), *const*end = binaryClauses.getDataEnd(); it != end; it++) { + const Clause& c = **it; + assert(c.size() == 2); + assert(findWatchedBinCl(binwatches[(~c[0]).toInt()], &c)); + assert(findWatchedBinCl(binwatches[(~c[1]).toInt()], &c)); + } + + for (XorClause *const*it = xorclauses.getData(), *const*end = xorclauses.getDataEnd(); it != end; it++) { + const XorClause& c = **it; + assert(find(xorwatches[c[0].var()], &c)); + assert(find(xorwatches[c[1].var()], &c)); + if (assigns[c[0].var()]!=l_Undef || assigns[c[1].var()]!=l_Undef) { + for (uint i = 0; i < c.size();i++) { + assert(assigns[c[i].var()] != l_Undef); + } + } + } +} + +void Solver::findAllAttach() const +{ + for (uint32_t i = 0; i < binwatches.size(); i++) { + for (uint32_t i2 = 0; i2 < binwatches[i].size(); i2++) { + assert(findClause(binwatches[i][i2].clause)); + } + } + for (uint32_t i = 0; i < watches.size(); i++) { + for (uint32_t i2 = 0; i2 < watches[i].size(); i2++) { + assert(findClause(watches[i][i2].clause)); + } + } + + for (uint32_t i = 0; i < xorwatches.size(); i++) { + for (uint32_t i2 = 0; i2 < xorwatches[i].size(); i2++) { + assert(findClause(xorwatches[i][i2])); + } + } +} + +const bool Solver::findClause(XorClause* c) const +{ + for (uint32_t i = 0; i < xorclauses.size(); i++) { + if (xorclauses[i] == c) return true; + } + return false; +} + +const bool Solver::findClause(Clause* c) const +{ + for (uint32_t i = 0; i < binaryClauses.size(); i++) { + if (binaryClauses[i] == c) return true; + } + for (uint32_t i = 0; i < clauses.size(); i++) { + if (clauses[i] == c) return true; + } + for (uint32_t i = 0; i < learnts.size(); i++) { + if (learnts[i] == c) return true; + } + vec cs = varReplacer->getClauses(); + for (uint32_t i = 0; i < cs.size(); i++) { + if (cs[i] == c) return true; + } + + return false; +} +#endif //DEBUG_ATTACH +const bool Solver::noLearntBinaries() const +{ + for (uint32_t i = 0; i < binaryClauses.size(); i++) { + if (binaryClauses[i]->learnt()) return false; + } + + return true; +} + +}; //NAMESPACE MINISAT diff --git a/src/sat/cryptominisat2/Solver.h b/src/sat/cryptominisat2/Solver.h index 7947c86..5f477ab 100644 --- a/src/sat/cryptominisat2/Solver.h +++ b/src/sat/cryptominisat2/Solver.h @@ -56,10 +56,13 @@ class FindUndef; class ClauseCleaner; class FailedVarSearcher; class Subsumer; +class XorSubsumer; class PartHandler; class RestartTypeChooser; +class StateSaver; #ifdef VERBOSE_DEBUG +#define DEBUG_UNCHECKEDENQUEUE_LEVEL0 using std::cout; using std::endl; #endif @@ -152,6 +155,12 @@ public: bool doVarElim; // Perform variable elimination bool doSubsume1; // Perform clause contraction through resolution bool failedVarSearch; // Should search for failed vars and doulbly propagated vars + bool readdOldLearnts; // Should re-add old learnts for failed variable searching + bool addExtraBins; // Should add extra binaries in failed literal probing + bool removeUselessBins; // Should try to remove useless binary clauses + bool regularRemoveUselessBins; // Should try to remove useless binary clauses regularly + bool subsumeWithNonExistBinaries; + bool regularSubsumeWithNonExistBinaries; bool libraryUsage; // Set true if not used as a library friend class FindUndef; bool greedyUnbound; //If set, then variables will be greedily unbounded (set to l_Undef) @@ -159,7 +168,7 @@ public: GaussianConfig gaussconfig; - enum { polarity_true = 0, polarity_false = 1, polarity_rnd = 3, polarity_auto = 4, polarity_manual = 5}; + enum { polarity_true = 0, polarity_false = 1, polarity_rnd = 3, polarity_auto = 4}; // Statistics: (read-only member variable) // @@ -179,13 +188,34 @@ public: 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. + #ifdef USE_GAUSS + const uint32_t get_sum_gauss_called() const; + const uint32_t get_sum_gauss_confl() const; + const uint32_t get_sum_gauss_prop() const; + const uint32_t get_sum_gauss_unit_truths() const; + #endif //USE_GAUSS + + //Printing statistics + const uint32_t getNumElimSubsume() const; // Get variable elimination stats from Subsumer + const uint32_t getNumElimXorSubsume() const; // Get variable elimination stats from XorSubsumer + const uint32_t getNumXorTrees() const; // Get the number of trees built from 2-long XOR-s. This is effectively the number of variables that replace other variables + const uint32_t getNumXorTreesCrownSize() const; // Get the number of variables being replaced by other variables + const double getTotalTimeSubsumer() const; + const double getTotalTimeXorSubsumer() const; + protected: #ifdef USE_GAUSS - void print_gauss_sum_stats() const; + void print_gauss_sum_stats(); void clearGaussMatrixes(); vector gauss_matrixes; - #endif //USE_GAUSS + + //stats + uint32_t sum_gauss_called; + uint32_t sum_gauss_confl; + uint32_t sum_gauss_prop; + uint32_t sum_gauss_unit_truths; friend class Gaussian; + #endif //USE_GAUSS template Clause* addClauseInt(T& ps, uint group); @@ -196,11 +226,11 @@ protected: template void removeWatchedCl(vec &ws, const Clause *c); template - bool findWatchedCl(vec& ws, const Clause *c); + bool findWatchedCl(const vec& ws, const Clause *c) const; template void removeWatchedBinCl(vec &ws, const Clause *c); template - bool findWatchedBinCl(vec& ws, const Clause *c); + bool findWatchedBinCl(const vec& ws, const Clause *c) const; // Helper structures: // @@ -228,6 +258,8 @@ protected: 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 removedLearnts; // Clauses that have been learnt, then removed + vec freeLater; // xor clauses that need to be freed later due to Gauss vec activity; // A heuristic measurement of the activity of a variable. uint32_t var_inc; // Amount to bump next variable with. double cla_inc; // Amount to bump learnt clause oldActivity with @@ -236,15 +268,14 @@ protected: vec > binwatches; vec assigns; // The current assignments vector polarity; // The preferred polarity of each variable. + #ifdef USE_OLD_POLARITIES + vector oldPolarity; // The polarity before the last setting. Good for unsetting polairties that have been changed since the last conflict + #endif //USE_OLD_POLARITIES 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 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; uint32_t nbclausesbeforereduce; uint32_t nbCompensateSubsumer; // Number of learnt clauses that subsumed normal clauses last time subs. was executed @@ -258,7 +289,9 @@ protected: bqueue nbDecisionLevelHistory; // Set of last decision level in conflict clauses double totalSumOfDecisionLevel; uint64_t conflictsAtLastSolve; + #ifdef RANDOM_LOOKAROUND_SEARCHSPACE bqueue avgBranchDepth; // Avg branch depth + #endif //RANDOM_LOOKAROUND_SEARCHSPACE MTRand mtrand; // random number generaton RestartType restartType; // Used internally to determine which restart strategy to choose RestartType lastSelectedRestartType; //the last selected restart type @@ -276,7 +309,15 @@ protected: vec analyze_stack; vec analyze_toclear; vec add_tmp; - unsigned long int MYFLAG; + + + uint64_t MYFLAG; + template + const uint32_t calcNBLevels(const T& ps); + 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 //Logging uint learnt_clause_group; //the group number of learnt clauses. Incremented at each added learnt clause @@ -284,17 +325,25 @@ protected: // Main internal methods: // - lbool simplify (); // Removes already satisfied clauses. + const bool simplify (); // Removes already satisfied clauses. //int nbPropagated (int level); void insertVarOrder (Var x); // Insert a variable in the decision order priority queue. Lit pickBranchLit (); // Return the next decision variable. void newDecisionLevel (); // Begins a new decision level. void uncheckedEnqueue (Lit p, ClausePtr from = (Clause*)NULL); // Enqueue a literal. Assumes value of literal is undefined. + void uncheckedEnqueueLight (const Lit p); bool enqueue (Lit p, Clause* from = NULL); // Test if fact 'p' contradicts current state, enqueue otherwise. Clause* propagate (const bool update = true); // Perform unit propagation. Returns possibly conflicting clause. + Clause* propagateLight(); + Clause* propagateBin(); + Clause* propagateBinNoLearnts(); + template + Clause* propagateBinExcept(const Lit& exceptLit); + template + Clause* propagateBinOneLevel(); Clause* propagate_xors (const Lit& p); void cancelUntil (int level); // Backtrack until a certain level. - Clause* analyze (Clause* confl, vec& out_learnt, int& out_btlevel, int &nblevels, const bool update); // (bt = backtrack) + Clause* analyze (Clause* confl, vec& out_learnt, int& out_btlevel, uint32_t &nblevels, const bool update); // (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, int nof_conflicts_fullrestart, const bool update = true); // Search for a given number of conflicts. @@ -321,6 +370,10 @@ protected: void removeClause(T& c); // Detach and free a clause. bool locked (const Clause& c) const; // Returns TRUE if a clause is a reason for some implication in the current state. void reverse_binary_clause(Clause& c) const; // Binary clauses --- the first Lit has to be true + void testAllClauseAttach() const; + void findAllAttach() const; + const bool findClause(XorClause* c) const; + const bool findClause(Clause* c) const; // Misc: // @@ -339,18 +392,21 @@ protected: friend class Subsumer; friend class XorSubsumer; friend class PartHandler; + friend class StateSaver; Conglomerate* conglomerate; VarReplacer* varReplacer; ClauseCleaner* clauseCleaner; FailedVarSearcher* failedVarSearcher; PartHandler* partHandler; Subsumer* subsumer; + XorSubsumer* xorSubsumer; RestartTypeChooser* restartTypeChooser; - void chooseRestartType(const uint& lastFullRestart); + MatrixFinder* matrixFinder; + const bool 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); + const lbool simplifyProblem(const uint32_t numConfls); bool simplifying; // Debug & etc: @@ -361,15 +417,16 @@ protected: void checkSolution(); void checkLiteralCount(); void printStatHeader () const; - void printRestartStat () const; - void printEndSearchStat() const; + void printRestartStat (); + void printEndSearchStat(); double progressEstimate () const; // DELETE THIS ?? IT'S NOT VERY USEFUL ... + const bool noLearntBinaries() const; // 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[] + void 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 tallyVotes(const vec& cs, vector& votes) const; + void tallyVotes(const vec& cs, vector& votes) const; }; @@ -425,7 +482,7 @@ inline void Solver::claBumpActivity (Clause& c) inline void Solver::claDecayActivity() { - cla_inc *= clause_decay; + //cla_inc *= clause_decay; } inline bool Solver::enqueue (Lit p, Clause* from) @@ -534,6 +591,28 @@ inline void Solver::setVariableName(Var var, char* name) {} #endif +#ifdef USE_GAUSS +inline const uint32_t Solver::get_sum_gauss_unit_truths() const +{ + return sum_gauss_unit_truths; +} + +inline const uint32_t Solver::get_sum_gauss_called() const +{ + return sum_gauss_called; +} + +inline const uint32_t Solver::get_sum_gauss_confl() const +{ + return sum_gauss_confl; +} + +inline const uint32_t Solver::get_sum_gauss_prop() const +{ + return sum_gauss_prop; +} +#endif + inline const uint Solver::get_unitary_learnts_num() const { if (decisionLevel() > 0) @@ -558,14 +637,14 @@ inline void Solver::removeWatchedBinCl(vec &ws, const Clause *c) { ws.pop(); } template -inline bool Solver::findWatchedCl(vec& ws, const Clause *c) +inline bool Solver::findWatchedCl(const vec& ws, const Clause *c) const { uint32_t j = 0; for (; j < ws.size() && ws[j].clause != c; j++); return j < ws.size(); } template -inline bool Solver::findWatchedBinCl(vec& ws, const Clause *c) +inline bool Solver::findWatchedBinCl(const vec& ws, const Clause *c) const { uint32_t j = 0; for (; j < ws.size() && ws[j].clause != c; j++); @@ -574,8 +653,7 @@ inline bool Solver::findWatchedBinCl(vec& ws, const Clause *c) inline void Solver::reverse_binary_clause(Clause& c) const { if (c.size() == 2 && value(c[0]) == l_False) { assert(value(c[1]) == l_True); - Lit tmp = c[0]; - c[0] = c[1], c[1] = tmp; + std::swap(c[0], c[1]); } } /*inline void Solver::calculate_xor_clause(Clause& c2) const { @@ -603,7 +681,6 @@ inline void Solver::removeClause(T& c) clauseFree(&c); } - //================================================================================================= // Debug + etc: @@ -637,6 +714,23 @@ static inline void check(bool expr) assert(expr); } +#ifndef DEBUG_ATTACH +inline void Solver::testAllClauseAttach() const +{ + return; +} +inline void Solver::findAllAttach() const +{ + return; +} +#endif //DEBUG_ATTACH + +inline void Solver::uncheckedEnqueueLight(const Lit p) +{ + assigns [p.var()] = boolToLBool(!p.sign());//lbool(!sign(p)); // <<== abstract but not uttermost effecient + trail.push(p); +} + //================================================================================================= }; //NAMESPACE MINISAT diff --git a/src/sat/cryptominisat2/SolverTypes.h b/src/sat/cryptominisat2/SolverTypes.h index 5c64d7b..452097c 100644 --- a/src/sat/cryptominisat2/SolverTypes.h +++ b/src/sat/cryptominisat2/SolverTypes.h @@ -30,6 +30,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #endif //_MSC_VER #include "Alg.h" +#include namespace MINISAT { @@ -85,10 +86,18 @@ public: bool operator < (const Lit& p) const { return x < p.x; // '<' guarantees that p, ~p are adjacent in the ordering. } -}; + inline void print(FILE* outfile = stdout) const + { + fprintf(outfile,"%s%d", sign() ? "-" : "", var()+1); + } + inline void printFull(FILE* outfile = stdout) const + { + fprintf(outfile,"%s%d 0\n", sign() ? "-" : "", var()+1); + } +}; -const Lit lit_Undef(var_Undef, false); // }- Useful special constants. -const Lit lit_Error(var_Undef, true ); // } +const Lit lit_Undef(var_Undef, false); // Useful special constants. +const Lit lit_Error(var_Undef, true ); // //================================================================================================= // Lifted booleans: diff --git a/src/sat/cryptominisat2/StateSaver.cpp b/src/sat/cryptominisat2/StateSaver.cpp new file mode 100644 index 0000000..ceb5eab --- /dev/null +++ b/src/sat/cryptominisat2/StateSaver.cpp @@ -0,0 +1,54 @@ +/*********************************************************************************** +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 "StateSaver.h" + +namespace MINISAT +{ +using namespace MINISAT; + +StateSaver::StateSaver(Solver& _solver) : + solver(_solver) + , backup_order_heap(Solver::VarOrderLt(solver.activity)) +{ + //Saving Solver state + backup_var_inc = solver.var_inc; + backup_activity.growTo(solver.activity.size()); + std::copy(solver.activity.getData(), solver.activity.getDataEnd(), backup_activity.getData()); + backup_order_heap = solver.order_heap; + backup_polarities = solver.polarity; + backup_restartType = solver.restartType; + backup_random_var_freq = solver.random_var_freq; + backup_propagations = solver.propagations; +} + +void StateSaver::restore() +{ + //Restore Solver state + 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.restartType = backup_restartType; + solver.random_var_freq = backup_random_var_freq; + + //Finally, clear the order_heap from variables set/non-decisionned + solver.order_heap.filter(Solver::VarFilter(solver)); + solver.propagations = backup_propagations; +} + +}; //NAMESPACE MINISAT diff --git a/src/sat/cryptominisat2/StateSaver.h b/src/sat/cryptominisat2/StateSaver.h new file mode 100644 index 0000000..7d1f1c3 --- /dev/null +++ b/src/sat/cryptominisat2/StateSaver.h @@ -0,0 +1,46 @@ +/*********************************************************************************** +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 STATESAVER__H +#define STATESAVER__H + +#include "Solver.h" + +namespace MINISAT +{ +using namespace MINISAT; + +class StateSaver +{ + public: + StateSaver(Solver& _solver); + void restore(); + + private: + Solver& solver; + Heap backup_order_heap; + vector backup_polarities; + vec backup_activity; + uint32_t backup_var_inc; + RestartType backup_restartType; + uint32_t backup_random_var_freq; + uint64_t backup_propagations; +}; + +}; //NAMESPACE MINISAT + +#endif //STATESAVER__H diff --git a/src/sat/cryptominisat2/Subsumer.cpp b/src/sat/cryptominisat2/Subsumer.cpp index fff5ddb..f6cda31 100644 --- a/src/sat/cryptominisat2/Subsumer.cpp +++ b/src/sat/cryptominisat2/Subsumer.cpp @@ -12,14 +12,12 @@ Substantially modified by: Mate Soos (2010) #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 @@ -41,8 +39,9 @@ using namespace MINISAT; Subsumer::Subsumer(Solver& s): solver(s) - , numCalls(0) + , totalTime(0.0) , numElimed(0) + , numCalls(0) { }; @@ -52,25 +51,29 @@ Subsumer::~Subsumer() void Subsumer::extendModel(Solver& solver2) { + assert(checkElimedUnassigned()); vec tmp; - typedef map > > elimType; + typedef map > elimType; for (elimType::iterator it = elimedOutVar.begin(), end = elimedOutVar.end(); it != end; it++) { - #ifdef VERBOSE_DEBUG + #ifndef NDEBUG Var var = it->first; + #ifdef VERBOSE_DEBUG std::cout << "Reinserting elimed var: " << var+1 << std::endl; #endif + assert(!solver.decision_var[var]); + assert(solver.assigns[var] == l_Undef); + assert(!solver.order_heap.inHeap(var)); + #endif - for (vector >::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) { + for (vector::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) { + Clause& c = **it2; tmp.clear(); - tmp.growTo(it2->size()); - std::copy(it2->begin(), it2->end(), tmp.getData()); + tmp.growTo(c.size()); + std::copy(c.getData(), c.getDataEnd(), 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; + c.plainPrint(); #endif solver2.addClause(tmp); @@ -81,10 +84,13 @@ void Subsumer::extendModel(Solver& solver2) const bool Subsumer::unEliminate(const Var var) { + assert(var_elimed[var]); vec tmp; - typedef map > > elimType; + typedef map > elimType; elimType::iterator it = elimedOutVar.find(var); - + + //it MUST have been decision var, otherwise we would + //never have removed it solver.setDecisionVar(var, true); var_elimed[var] = false; numElimed--; @@ -96,11 +102,9 @@ const bool Subsumer::unEliminate(const Var var) FILE* backup_libraryCNFfile = solver.libraryCNFFile; solver.libraryCNFFile = NULL; - 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()); - solver.addClause(tmp); + for (vector::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) { + solver.addClause(**it2); + clauseFree(*it2); } solver.libraryCNFFile = backup_libraryCNFfile; elimedOutVar.erase(it); @@ -139,63 +143,165 @@ bool selfSubset(Clause& A, Clause& B, vec& seen) return flip; } -// Will put NULL in 'cs' if clause removed. -uint32_t Subsumer::subsume0(Clause& ps) +template <> +inline 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:"; + cout << "subsume0 orig clause: "; ps.plainPrint(); #endif - + return subsume0Orig(ps, abs); +} + +template +inline uint32_t Subsumer::subsume0(T& ps, uint32_t abs) +{ + #ifdef VERBOSE_DEBUG + cout << "subsume0 orig vec: "; + ps[0].print(); std::cout << " "; + ps[1].printFull(); + #endif + return subsume0Orig(ps, abs); +} + +// Will put NULL in 'cs' if clause removed. +template +uint32_t Subsumer::subsume0Orig(const T& ps, uint32_t abs) +{ + uint32_t retIndex = std::numeric_limits::max(); vec subs; - findSubsumed(ps, subs); + findSubsumed(ps, abs, subs); for (uint32_t i = 0; i < subs.size(); i++){ clauses_subsumed++; #ifdef VERBOSE_DEBUG - cout << "subsume0 removing:"; + cout << "-> subsume0 removing:"; subs[i].clause->plainPrint(); #endif Clause* tmp = subs[i].clause; - unlinkClause(subs[i]); - free(tmp); retIndex = subs[i].index; + unlinkClause(subs[i]); + clauseFree(tmp); } return retIndex; } -// Will put NULL in 'cs' if clause removed. -uint32_t Subsumer::subsume0(Clause& ps, uint32_t abs) +void Subsumer::subsume0BIN(const Lit lit1, const vec& lits) { - 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); + vec subs2; + vec subs2Lit; + + vec& cs = occur[lit1.toInt()]; + for (ClauseSimp *it = cs.getData(), *end = it + cs.size(); it != end; it++){ + if (it+1 != end) + __builtin_prefetch((it+1)->clause, 0, 1); + if (it->clause == NULL) continue; + Clause& c = *it->clause; + bool removed = false; + for (uint32_t i = 0; i < c.size(); i++) { + if (lits[c[i].toInt()]) { + subs.push(*it); + removed = true; + break; + } + } + if (!removed) { + for (uint32_t i = 0; i < c.size(); i++) { + if (lits[(~c[i]).toInt()]) { + subs2.push(*it); + subs2Lit.push(c[i]); + break; + } + } + } + } + for (uint32_t i = 0; i < subs.size(); i++){ clauses_subsumed++; #ifdef VERBOSE_DEBUG - cout << "subsume0 removing:"; + cout << "-> subsume0 removing:"; subs[i].clause->plainPrint(); #endif Clause* tmp = subs[i].clause; - retIndex = subs[i].index; unlinkClause(subs[i]); - free(tmp); + clauseFree(tmp); } - - return retIndex; + + if (subs2.size() == 0) return; + registerIteration(subs2); + for (uint32_t j = 0; j < subs2.size(); j++){ + if (subs2[j].clause == NULL) continue; + ClauseSimp c = subs2[j]; + Clause& cl = *c.clause; + #ifdef VERBOSE_DEBUG + cout << "-> Strenghtening clause :"; + cl.plainPrint(); + #endif + unlinkClause(c); + + literals_removed++; + cl.strengthen(subs2Lit[j]); + 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) { + #ifdef VERBOSE_DEBUG + std::cout << "--> Clause was satisfied." << std::endl; + #endif + clauseFree(&cl); + goto endS; + } + } + cl.shrink(a-b); + cl.setStrenghtened(); + + #ifdef VERBOSE_DEBUG + cout << "--> Strenghtened clause:"; + cl.plainPrint(); + #endif + + if (cl.size() == 0) { + solver.ok = false; + unregisterIteration(subs2); + clauseFree(&cl); + return; + } + if (cl.size() > 2) { + cl.calcAbstraction(); + linkInAlreadyClause(c); + clauses[c.index] = c; + solver.attachClause(cl); + updateClause(c); + } else if (cl.size() == 2) { + cl.calcAbstraction(); + solver.attachClause(cl); + solver.becameBinary++; + addBinaryClauses.push(&cl); + //updateClause(c); + } else { + assert(cl.size() == 1); + solver.uncheckedEnqueue(cl[0]); + solver.ok = (solver.propagate() == NULL); + if (!solver.ok) { + unregisterIteration(subs2); + return; + } + #ifdef VERBOSE_DEBUG + cout << "--> Found that var " << cl[0].var()+1 << " must be " << std::boolalpha << !cl[0].sign() << endl; + #endif + clauseFree(&cl); + } + endS:; + } + unregisterIteration(subs2); } void Subsumer::unlinkClause(ClauseSimp c, Var elim) @@ -204,19 +310,18 @@ void Subsumer::unlinkClause(ClauseSimp c, Var elim) if (elim != var_Undef) { assert(!cl.learnt()); - io_tmp.clear(); - for (uint32_t i = 0; i < cl.size(); i++) - io_tmp.push_back(cl[i]); - elimedOutVar[elim].push_back(io_tmp); + #ifdef VERBOSE_DEBUG + std::cout << "Eliminating clause: "; c.clause->plainPrint(); + std::cout << "On variable: " << elim+1 << std::endl; + #endif //VERBOSE_DEBUG + elimedOutVar[elim].push_back(c.clause); } - - 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 - } + + 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); @@ -234,23 +339,19 @@ void Subsumer::unlinkClause(ClauseSimp c, Var elim) } // Remove clause from clause touched set: - if (updateOccur(cl)) { - cl_touched.exclude(c); - cl_added.exclude(c); - } + 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 - } + 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); @@ -268,23 +369,19 @@ void Subsumer::unlinkModifiedClause(vec& origClause, ClauseSimp c) } // Remove clause from clause touched set: - if (updateOccur(*c.clause)) { - cl_touched.exclude(c); - cl_added.exclude(c); - } + 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 - } + 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: @@ -300,10 +397,8 @@ void Subsumer::unlinkModifiedClauseNoDetachNoNULL(vec& origClause, ClauseSi } // Remove clause from clause touched set: - if (updateOccur(*c.clause)) { - cl_touched.exclude(c); - cl_added.exclude(c); - } + cl_touched.exclude(c); + cl_added.exclude(c); } void Subsumer::subsume1(ClauseSimp& ps) @@ -322,7 +417,7 @@ void Subsumer::subsume1(ClauseSimp& ps) while (q < Q.size()){ if (Q[q].clause == NULL) { q++; continue; } #ifdef VERBOSE_DEBUG - cout << "subsume1 orig clause:"; + cout << "subsume1 with clause:"; Q[q].clause->plainPrint(); #endif @@ -350,10 +445,10 @@ void Subsumer::subsume1(ClauseSimp& ps) ClauseSimp c = subs[j]; Clause& cl = *c.clause; #ifdef VERBOSE_DEBUG - cout << "orig clause :"; + cout << "-> Strenghtening clause :"; cl.plainPrint(); #endif - unlinkClause(subs[j]); + unlinkClause(c); literals_removed++; cl.strengthen(qs[i]); @@ -364,7 +459,10 @@ void Subsumer::subsume1(ClauseSimp& ps) *b++ = *a; if (val == l_True) { - free(&cl); + #ifdef VERBOSE_DEBUG + std::cout << "--> Clause was satisfied." << std::endl; + #endif + clauseFree(&cl); goto endS; } } @@ -372,15 +470,15 @@ void Subsumer::subsume1(ClauseSimp& ps) cl.setStrenghtened(); #ifdef VERBOSE_DEBUG - cout << "strenghtened :"; - c.clause->plainPrint(); + cout << "--> Strenghtened clause:"; + cl.plainPrint(); #endif if (cl.size() == 0) { solver.ok = false; unregisterIteration(Q); unregisterIteration(subs); - free(&cl); + clauseFree(&cl); return; } if (cl.size() > 1) { @@ -401,9 +499,9 @@ void Subsumer::subsume1(ClauseSimp& ps) return; } #ifdef VERBOSE_DEBUG - cout << "Found that var " << cl[0].var()+1 << " must be " << std::boolalpha << !cl[0].sign() << endl; + cout << "--> Found that var " << cl[0].var()+1 << " must be " << std::boolalpha << !cl[0].sign() << endl; #endif - free(&cl); + clauseFree(&cl); } endS:; } @@ -418,9 +516,106 @@ void Subsumer::subsume1(ClauseSimp& ps) unregisterIteration(subs); } +template +void Subsumer::subsume1Partial(const T& ps) +{ + assert(solver.decisionLevel() == 0); + registerIteration(subsume1PartialSubs); + + #ifdef VERBOSE_DEBUG + cout << "-> Strenghtening using clause :"; + ps[0].print(); std::cout << " "; + ps[1].printFull(); + #endif + + assert(ps.size() == 2); + subsume1PartialQs.clear(); + for (uint8_t i = 0; i < 2; i++) + subsume1PartialQs.push(ps[i]); + + for (uint8_t i = 0; i < 2; i++){ + subsume1PartialQs[i] = ~subsume1PartialQs[i]; + + uint32_t abst = calcAbstraction(subsume1PartialQs); + + findSubsumed(subsume1PartialQs, abst, subsume1PartialSubs); + for (uint32_t j = 0; j < subsume1PartialSubs.size(); j++){ + if (subsume1PartialSubs[j].clause == NULL) continue; + ClauseSimp c = subsume1PartialSubs[j]; + Clause& cl = *c.clause; + #ifdef VERBOSE_DEBUG + cout << "-> Strenghtening clause :"; + cl.plainPrint(); + #endif + unlinkClause(subsume1PartialSubs[j]); + + literals_removed++; + cl.strengthen(subsume1PartialQs[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) { + #ifdef VERBOSE_DEBUG + std::cout << "--> Clause was satisfied." << std::endl; + #endif + clauseFree(&cl); + goto endS; + } + } + cl.shrink(a-b); + cl.setStrenghtened(); + + #ifdef VERBOSE_DEBUG + cout << "--> Strenghtened clause:"; + cl.plainPrint(); + #endif + + if (cl.size() == 0) { + solver.ok = false; + unregisterIteration(subsume1PartialSubs); + clauseFree(&cl); + return; + } + if (cl.size() > 2) { + cl.calcAbstraction(); + linkInAlreadyClause(c); + clauses[c.index] = c; + solver.attachClause(cl); + updateClause(c); + } else if (cl.size() == 2) { + cl.calcAbstraction(); + solver.attachClause(cl); + solver.becameBinary++; + addBinaryClauses.push(&cl); + //updateClause(c); + } else { + assert(cl.size() == 1); + solver.uncheckedEnqueue(cl[0]); + solver.ok = (solver.propagate() == NULL); + if (!solver.ok) { + unregisterIteration(subsume1PartialSubs); + return; + } + #ifdef VERBOSE_DEBUG + cout << "--> Found that var " << cl[0].var()+1 << " must be " << std::boolalpha << !cl[0].sign() << endl; + #endif + clauseFree(&cl); + } + endS:; + } + + subsume1PartialQs[i] = ~subsume1PartialQs[i]; + subsume1PartialSubs.clear(); + } + unregisterIteration(subsume1PartialSubs); +} + void Subsumer::updateClause(ClauseSimp c) { - if (!c.clause->learnt()) subsume0(*c.clause); + if (!c.clause->learnt()) subsume0(*c.clause, c.clause->getAbst()); cl_touched.add(c); } @@ -436,7 +631,7 @@ void Subsumer::almost_all_database() for (uint32_t i = 0; i < clauses.size(); i++) { if (numMaxSubsume1 == 0) break; - if (clauses[i].clause != NULL && updateOccur(*clauses[i].clause)) { + if (clauses[i].clause != NULL) { subsume1(clauses[i]); numMaxSubsume1--; if (!solver.ok) return; @@ -579,7 +774,7 @@ void Subsumer::smaller_database() // Iteration pass for 0-subsumption: for (CSet::iterator it = s0.begin(), end = s0.end(); it != end; ++it) { if (it->clause != NULL) - subsume0(*it->clause); + subsume0(*it->clause, it->clause->getAbst()); } s0.clear(); unregisterIteration(s0); @@ -589,11 +784,9 @@ 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()); - } + for (uint32_t i = 0; i < cl.size(); i++) { + occur[cl[i].toInt()].push(c); + touch(cl[i].var()); } cl_added.add(c); @@ -603,42 +796,48 @@ ClauseSimp Subsumer::linkInClause(Clause& cl) void Subsumer::linkInAlreadyClause(ClauseSimp& 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()); - } + for (uint32_t i = 0; i < cl.size(); i++) { + occur[cl[i].toInt()].push(c); + touch(cl[i].var()); } } -void Subsumer::addFromSolver(vec& cs) +template +void Subsumer::addFromSolver(vec& cs, bool alsoLearnt) { 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()) { + + if (!alsoLearnt && (*i)->learnt()) { + *j++ = *i; + (*i)->setUnsorted(); + continue; + } + + if (!UseCL && (*i)->size() == 2) { + //don't add binary clauses in this case *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()); - } + for (uint32_t i = 0; i < cl.size(); i++) { + occur[cl[i].toInt()].push(c); + touch(cl[i].var()); + } + if (UseCL) { if (fullSubsume || cl.getVarChanged()) cl_added.add(c); else if (cl.getStrenghtened()) cl_touched.add(c); - - if (cl.getVarChanged() || cl.getStrenghtened()) - cl.calcAbstraction(); } + + if (cl.getVarChanged() || cl.getStrenghtened()) + cl.calcAbstraction(); } cs.shrink(i-j); } @@ -687,7 +886,7 @@ void Subsumer::removeWrong(vec& cs) if (var_elimed[l->var()]) { remove = true; solver.detachClause(c); - free(&c); + clauseFree(&c); break; } } @@ -706,11 +905,6 @@ void Subsumer::fillCannotEliminate() cannot_eliminate[c[i2].var()] = true; } - const vec& 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]; @@ -737,6 +931,7 @@ void Subsumer::subsume0LearntSet(vec& cs) uint32_t index = subsume0(**a, calcAbstraction(**a)); if (index != std::numeric_limits::max()) { (*a)->makeNonLearnt(); + //solver.nbBin--; clauses[index].clause = *a; linkInAlreadyClause(clauses[index]); solver.learnts_literals -= (*a)->size(); @@ -749,8 +944,8 @@ void Subsumer::subsume0LearntSet(vec& cs) ((*a)->size() <= 3 && clauses.size() < 300000) || ((*a)->size() <= 4 && clauses.size() < 60000))) { ClauseSimp c(*a, clauseID++); - (*a)->calcAbstraction(); - clauses.push(c); + //(*a)->calcAbstraction(); + //clauses.push(c); subsume1(c); numMaxSubsume1--; if (!solver.ok) { @@ -759,8 +954,8 @@ void Subsumer::subsume0LearntSet(vec& cs) cs.shrink(a-b); return; } - assert(clauses[c.index].clause != NULL); - clauses.pop(); + //assert(clauses[c.index].clause != NULL); + //clauses.pop(); clauseID--; } } @@ -784,6 +979,189 @@ const bool Subsumer::treatLearnts() return true; } +const bool Subsumer::subsumeWithBinaries(const bool startUp) +{ + clearAll(); + clauseID = 0; + fullSubsume = true; + addBinaryClauses.clear(); + + //Clearing stats + subsNonExistentumFailed = 0; + clauses_subsumed = 0; + literals_removed = 0; + double myTime = cpuTime(); + uint32_t origTrailSize = solver.trail.size(); + + clauses.reserve(solver.clauses.size()); + solver.clauseCleaner->cleanClauses(solver.clauses, ClauseCleaner::clauses); + addFromSolver(solver.clauses); + #ifdef DEBUG_BINARIES + for (uint32_t i = 0; i < clauses.size(); i++) { + assert(clauses[i].clause->size() != 2); + } + #endif //DEBUG_BINARIES + + for (uint32_t i = 0; i < solver.binaryClauses.size(); i++) { + if (startUp || !solver.binaryClauses[i]->learnt()) { + Clause& c = *solver.binaryClauses[i]; + subsume0(c, c.getAbst()); + } + } + for (uint32_t i = 0; i < solver.binaryClauses.size(); i++) { + Clause& c = *solver.binaryClauses[i]; + subsume1Partial(c); + if (!solver.ok) return false; + } + if (solver.verbosity >= 1) { + std::cout << "c subs with bin: " << std::setw(8) << clauses_subsumed + << " lits-rem: " << std::setw(9) << literals_removed + << " v-fix: " << std::setw(4) <size() != 2); + } + #endif //DEBUG_BINARIES + addBackToSolver(); + for (uint32_t i = 0; i < addBinaryClauses.size(); i++) { + solver.binaryClauses.push(addBinaryClauses[i]); + } + addBinaryClauses.clear(); + + if (solver.verbosity >= 1) { + std::cout << "c Subs w/ non-existent bins: " << subsNonExistentNum + << " lits-rem: " << subsNonExistentLitsRemoved + << " v-fix: " << subsNonExistentumFailed + << " done: " << doneNum + << " time: " << std::fixed << std::setprecision(2) << std::setw(5) << subsNonExistentTime + << std::endl; + } + totalTime += cpuTime() - myTime; + solver.order_heap.filter(Solver::VarFilter(solver)); + + return true; +} + +#define MAX_BINARY_PROP 40000000 + +const bool Subsumer::subsWNonExistBinsFull(const bool startUp) +{ + uint32_t oldClausesSubusmed = clauses_subsumed; + uint32_t oldLitsRemoved = literals_removed; + double myTime = cpuTime(); + uint64_t oldProps = solver.propagations; + uint32_t oldTrailSize = solver.trail.size(); + uint64_t maxProp = MAX_BINARY_PROP; + if (!startUp) maxProp /= 3; + ps2.clear(); + ps2.growTo(2); + toVisitAll.growTo(solver.nVars()*2, false); + + doneNum = 0; + uint32_t startFrom = solver.mtrand.randInt(solver.order_heap.size()); + for (uint32_t i = 0; i < solver.order_heap.size(); i++) { + Var var = solver.order_heap[(i+startFrom)%solver.order_heap.size()]; + if (solver.propagations - oldProps > maxProp) break; + if (solver.assigns[var] != l_Undef || !solver.decision_var[var]) continue; + doneNum++; + + Lit lit(var, true); + if (!subsWNonExistBins(lit, startUp)) { + if (!solver.ok) return false; + solver.cancelUntil(0); + solver.uncheckedEnqueue(~lit); + solver.ok = (solver.propagate() == NULL); + if (!solver.ok) return false; + continue; + } + + //in the meantime it could have got assigned + if (solver.assigns[var] != l_Undef) continue; + lit = ~lit; + if (!subsWNonExistBins(lit, startUp)) { + if (!solver.ok) return false; + solver.cancelUntil(0); + solver.uncheckedEnqueue(~lit); + solver.ok = (solver.propagate() == NULL); + if (!solver.ok) return false; + continue; + } + } + subsNonExistentNum = clauses_subsumed - oldClausesSubusmed; + subsNonExistentTime = cpuTime() - myTime; + subsNonExistentumFailed = solver.trail.size() - oldTrailSize; + subsNonExistentLitsRemoved = literals_removed - oldLitsRemoved; + + return true; +} + +const bool Subsumer::subsWNonExistBins(const Lit& lit, const bool startUp) +{ + #ifdef VERBOSE_DEBUG + std::cout << "subsWNonExistBins called with lit "; lit.print(); + std::cout << " startUp: " << startUp << std::endl; + #endif //VERBOSE_DEBUG + toVisit.clear(); + solver.newDecisionLevel(); + solver.uncheckedEnqueueLight(lit); + bool failed; + if (startUp) { + failed = (solver.propagateBin() != NULL); + } else { + failed = (solver.propagateBinNoLearnts() != NULL); + } + if (failed) return false; + + assert(solver.decisionLevel() > 0); + for (int c = solver.trail.size()-1; c > (int)solver.trail_lim[0]; c--) { + Lit x = solver.trail[c]; + toVisit.push(x); + toVisitAll[x.toInt()] = true; + } + solver.cancelUntil(0); + + if (toVisit.size() <= 1) { + ps2[0] = ~lit; + for (Lit *l = toVisit.getData(), *end = toVisit.getDataEnd(); l != end; l++) { + ps2[1] = *l; + assert(ps2[0] != ps2[1]); + #ifdef VERBOSE_DEBUG + std::cout << "Non-existent bin. lit1: "; ps2[0].print(); + std::cout << " lit2: "; ps2[1].print(); std::cout << std::endl; + #endif //VERBOSE_DEBUG + subsume0(ps2, calcAbstraction(ps2)); + subsume1Partial(ps2); + } + } else { + subsume0BIN(~lit, toVisitAll); + } + for (uint32_t i = 0; i < toVisit.size(); i++) + toVisitAll[toVisit[i].toInt()] = false; + + return true; +} + +void Subsumer::clearAll() +{ + 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(); + } + clauses.clear(); + cl_added.clear(); + cl_touched.clear(); +} + const bool Subsumer::simplifyBySubsumption() { if (solver.nClauses() > 20000000) return true; @@ -797,26 +1175,15 @@ const bool Subsumer::simplifyBySubsumption() clauseID = 0; numVarsElimed = 0; blockTime = 0.0; + clearAll(); //if (solver.xorclauses.size() < 30000 && solver.clauses.size() < MAX_CLAUSENUM_XORFIND/10) 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(); - } - + + solver.testAllClauseAttach(); if (solver.performReplace && !solver.varReplacer->performReplace(true)) return false; fillCannotEliminate(); - - clauses.clear(); - cl_added.clear(); - cl_touched.clear(); + solver.testAllClauseAttach(); clauses.reserve(solver.clauses.size() + solver.binaryClauses.size()); cl_added.reserve(solver.clauses.size() + solver.binaryClauses.size()); @@ -828,41 +1195,40 @@ const bool Subsumer::simplifyBySubsumption() fullSubsume = false; solver.clauseCleaner->cleanClauses(solver.clauses, ClauseCleaner::clauses); - addFromSolver(solver.clauses); - solver.clauseCleaner->cleanClauses(solver.binaryClauses, ClauseCleaner::binaryClauses); - addFromSolver(solver.binaryClauses); + addFromSolver(solver.clauses); + solver.clauseCleaner->removeSatisfied(solver.binaryClauses, ClauseCleaner::binaryClauses); + addFromSolver(solver.binaryClauses); //Limits - if (clauses.size() > 3500000) + if (clauses.size() > 3500000) { numMaxSubsume0 = 900000 * (1+numCalls/2); - else - numMaxSubsume0 = 2000000 * (1+numCalls/2); - - if (solver.doSubsume1) { - if (clauses.size() > 3500000) - numMaxSubsume1 = 100000 * (1+numCalls/2); - else - numMaxSubsume1 = 500000 * (1+numCalls/2); - } else { - numMaxSubsume1 = 0; - } - - 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) + numMaxSubsume1 = 100000 * (1+numCalls/2); numMaxBlockToVisit = (int64_t)(30000.0 * (0.8+(double)(numCalls)/3.0)); - else + } + if (clauses.size() <= 3500000 && clauses.size() > 1500000) { + numMaxSubsume0 = 2000000 * (1+numCalls/2); + numMaxElim = (uint32_t)((double)solver.order_heap.size() / 2.0 * (0.8+(double)(numCalls)/4.0)); + numMaxSubsume1 = 300000 * (1+numCalls/2); numMaxBlockToVisit = (int64_t)(50000.0 * (0.8+(double)(numCalls)/3.0)); + } + if (clauses.size() <= 1500000) { + numMaxSubsume0 = 4000000 * (1+numCalls/2); + numMaxElim = (uint32_t)((double)solver.order_heap.size() / 2.0 * (0.8+(double)(numCalls)/2.0)); + numMaxSubsume1 = 400000 * (1+numCalls/2); + numMaxBlockToVisit = (int64_t)(80000.0 * (0.8+(double)(numCalls)/3.0)); + } + if (numCalls == 1) numMaxSubsume1 = 0; + + if (!solver.doSubsume1) numMaxSubsume1 = 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)); - //For debugging post-c32s-gcdm16-22.cnf --- an instance that is turned SAT to UNSAT if a bug is in the code + //For debugging //numMaxBlockToVisit = std::numeric_limits::max(); //numMaxElim = std::numeric_limits::max(); //numMaxSubsume0 = std::numeric_limits::max(); @@ -880,7 +1246,7 @@ const bool Subsumer::simplifyBySubsumption() (fullSubsume || !clauses[i].clause->subsume0IsFinished()) ) { - subsume0(*clauses[i].clause); + subsume0(*clauses[i].clause, clauses[i].clause->getAbst()); numMaxSubsume0--; } } @@ -1002,15 +1368,13 @@ const bool Subsumer::simplifyBySubsumption() //vector var_merged = merge(); removeWrong(solver.learnts); removeWrong(solver.binaryClauses); + removeAssignedVarsFromEliminated(); - 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.clauseCleaner->cleanClausesBewareNULL(clauses, ClauseCleaner::simpClauses, *this); + addFromSolver(solver.learnts, true); + addFromSolver(solver.binaryClauses, true); + if (solver.doHyperBinRes && clauses.size() < 1000000 && numCalls > 1 && !hyperBinRes()) + return false;*/ solver.order_heap.filter(Solver::VarFilter(solver)); addBackToSolver(); @@ -1032,75 +1396,30 @@ const bool Subsumer::simplifyBySubsumption() << " |" << std::endl; } } - - return true; -} + totalTime += cpuTime() - myTime; -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 - } - } + solver.testAllClauseAttach(); + return true; } -void Subsumer::findSubsumed(Clause& ps, uint32_t abs, vec& out_subsumed) +void Subsumer::removeAssignedVarsFromEliminated() { - #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 + for (Var var = 0; var < var_elimed.size(); var++) { + if (var_elimed[var] && solver.assigns[var] != l_Undef) { + var_elimed[var] = false; + solver.setDecisionVar(var, true); + numElimed--; + map >::iterator it = elimedOutVar.find(var); + if (it != elimedOutVar.end()) { + //TODO memory loss here + elimedOutVar.erase(it); + } } } } -void Subsumer::findSubsumed(const vec& ps, const uint32_t abst, vec& out_subsumed) +template +void Subsumer::findSubsumed(const T& ps, uint32_t abs, vec& out_subsumed) { #ifdef VERBOSE_DEBUG cout << "findSubsumed: "; @@ -1122,7 +1441,7 @@ void Subsumer::findSubsumed(const vec& ps, const uint32_t abst, vecclause, 1, 1); - if (subsetAbst(abst, it->clause->getAbst()) && ps.size() <= it->clause->size() && subset(ps, *it->clause)) { + if (it->clause != (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: "; @@ -1146,12 +1465,12 @@ void inline Subsumer::MigrateToPsNs(vec& poss, vec& negs 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); + //clauses[ps[i].index].clause = NULL; + //clauseFree(ps[i].clause); } for (uint32_t i = 0; i < ns.size(); i++) { - clauses[ns[i].index].clause = NULL; - free(ns[i].clause); + //clauses[ns[i].index].clause = NULL; + //clauseFree(ns[i].clause); } } @@ -1204,7 +1523,7 @@ bool Subsumer::maybeEliminate(const Var x) } Abort:; - // Maybe eliminate: + //Eliminate: if (after_clauses <= before_clauses) { vec ps, ns; MigrateToPsNs(poss, negs, ps, ns, x); @@ -1212,10 +1531,18 @@ bool Subsumer::maybeEliminate(const Var x) 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); + uint32_t group_num = 0; + #ifdef STATS_NEEDED + group_num = solver.learnt_clause_group++; + if (solver.dynamic_behaviour_analysis) { + string name = solver.logger.get_group_name(ps[i].clause->getGroup()) + " " + solver.logger.get_group_name(ns[j].clause->getGroup()); + solver.logger.set_group_name(group_num, name); + } + #endif + Clause* cl = solver.addClauseInt(dummy, group_num); if (cl != NULL) { ClauseSimp c = linkInClause(*cl); - subsume0(*cl); + subsume0(*cl, cl->getAbst()); } if (!solver.ok) return true; } @@ -1228,14 +1555,14 @@ bool Subsumer::maybeEliminate(const Var x) Eliminated: assert(occur[Lit(x, false).toInt()].size() + occur[Lit(x, true).toInt()].size() == 0); - var_elimed[x] = 1; + var_elimed[x] = true; 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) +bool Subsumer::merge(const Clause& ps, const Clause& qs, const Lit without_p, const Lit without_q, vec& out_clause) { for (uint32_t i = 0; i < ps.size(); i++){ if (ps[i] != without_p){ @@ -1289,45 +1616,39 @@ void Subsumer::orderVarsForElim(vec& order) } } -const bool Subsumer::hyperUtility(vec& iter, const Lit lit, BitArray& inside, vec& addToClauses, uint32_t& hyperBinAdded, uint32_t& hyperBinUnitary) +const bool Subsumer::hyperUtility(vec& iter, const Lit lit, BitArray& inside, vec& addToClauses) { 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); + Lit notInLit = lit_Undef; - Clause& cl2 = *it->clause; - for (uint32_t i = 0; i < cl2.size(); i++) { - if (cl2[i].var() == lit.var()) { - notIn = 2; - break; + Clause& cl = *it->clause; + for (uint32_t i = 0; i < cl.size(); i++) { + if (cl[i].var() == lit.var() || cl.size() == 2) { + goto next; } - if (!inside[cl2[i].toInt()]) { + if (!inside[cl[i].toInt()]) { notIn++; - notInLit = cl2[i]; + if (notIn > 1) goto next; + notInLit = cl[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; - } + vec lits(1); + lits[0] = lit; + solver.addClauseInt(lits, cl.getGroup()); + if (!solver.ok) 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()) { + //uint32_t index = subsume0(cs, calcAbstraction(cs)); + /*if (index != std::numeric_limits::max()) { + Clause *cl3 = Clause_new(cs, cl.getGroup()); ClauseSimp c(cl3, index); addToClauses.push(c); inside.setBit((~notInLit).toInt()); @@ -1335,9 +1656,13 @@ const bool Subsumer::hyperUtility(vec& iter, const Lit lit, BitArray std::cout << "HyperBinRes adding clause: "; cl3->plainPrint(); #endif - hyperBinAdded++; - } + } else {*/ + Clause *cl3 = Clause_new(cs, cl.getGroup()); + addToClauses.push(cl3); + inside.setBit((~notInLit).toInt()); + //} } + next:; } return true; @@ -1350,15 +1675,16 @@ const bool Subsumer::hyperBinRes() BitArray inside; inside.resize(solver.nVars()*2, 0); uint32_t hyperBinAdded = 0; - uint32_t hyperBinUnitary = 0; - vec addToClauses; + uint32_t oldTrailSize = solver.trail.size(); + vec addToClauses; + vec addedToInside; uint64_t totalClausesChecked = 0; vec varsToCheck; - if (clauses.size() > 100000 || solver.order_heap.size() > 30000) { + if (clauses.size() > 500000 || solver.order_heap.size() > 50000) { Heap tmp(solver.order_heap); - uint32_t thisTopX = std::min(tmp.size(), 1000U); + uint32_t thisTopX = std::min(tmp.size(), 5000U); for (uint32_t i = 0; i != thisTopX; i++) varsToCheck.push(tmp.removeMin()); } else { @@ -1366,29 +1692,38 @@ const bool Subsumer::hyperBinRes() 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) + for (uint32_t test = 0; test < 2*varsToCheck.size(); test++) if (solver.assigns[test/2] == l_Undef && solver.decision_var[test/2]) { + if (totalClausesChecked > 1000000) break; inside.setZero(); + addToClauses.clear(); + addedToInside.clear(); + 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; + + //fill inside with binary clauses' literals that this lit is in + //addedToInside now contains the list vec& set = occur[lit.toInt()]; + totalClausesChecked += occur.size(); 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]); + if (!inside[(~cl2[1]).toInt()]) { + inside.setBit((~cl2[1]).toInt()); + addedToInside.push(~cl2[1]); + } } else { - inside.setBit((~cl2[0]).toInt()); - addedToInside.push(~cl2[0]); + if (!inside[(~cl2[0]).toInt()]) { + inside.setBit((~cl2[0]).toInt()); + addedToInside.push(~cl2[0]); + } } } @@ -1401,33 +1736,30 @@ const bool Subsumer::hyperBinRes() 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)) + if (!hyperUtility(iter, lit, inside, addToClauses)) return false; } } else { totalClausesChecked += clauses.size(); - if (!hyperUtility(clauses, lit, inside, addToClauses, hyperBinAdded, hyperBinUnitary)) + if (!hyperUtility(clauses, lit, inside, addToClauses)) return false; } - + + hyperBinAdded += addToClauses.size(); for (uint32_t i = 0; i < addToClauses.size(); i++) { - Clause *c = solver.addClauseInt(*addToClauses[i].clause, 0); - free(addToClauses[i].clause); + Clause *c = solver.addClauseInt(*addToClauses[i], addToClauses[i]->getGroup()); + clauseFree(addToClauses[i]); 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. + ClauseSimp cc = linkInClause(*c); 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 + << " unitaries: " << std::setw(5) << solver.trail.size() - oldTrailSize << " time: " << std::setprecision(2) << std::setw(5)<< cpuTime() - myTime << " s" << " |" << std::endl; } @@ -1497,17 +1829,6 @@ class varDataStruct 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); @@ -1631,12 +1952,18 @@ const bool Subsumer::tryOneSetting(const Lit lit, const Lit negLit) solver.setDecisionVar(lit.var(), false); vec toRemove(occur[lit.toInt()]); for (ClauseSimp *it = toRemove.getData(), *end = toRemove.getDataEnd(); it != end; it++) { + #ifdef VERBOSE_DEBUG + std::cout << "Next varelim because of block clause elim" << std::endl; + #endif //VERBOSE_DEBUG unlinkClause(*it, lit.var()); numblockedClauseRemoved++; } vec toRemove2(occur[negLit.toInt()]); for (ClauseSimp *it = toRemove2.getData(), *end = toRemove2.getDataEnd(); it != end; it++) { + #ifdef VERBOSE_DEBUG + std::cout << "Next varelim because of block clause elim" << std::endl; + #endif //VERBOSE_DEBUG unlinkClause(*it, lit.var()); numblockedClauseRemoved++; } @@ -1646,7 +1973,31 @@ const bool Subsumer::tryOneSetting(const Lit lit, const Lit negLit) return returnVal; } -/*vector Subsumer::merge() +const bool Subsumer::checkElimedUnassigned() const +{ + for (uint32_t i = 0; i < var_elimed.size(); i++) { + if (var_elimed[i]) { + assert(solver.assigns[i] == l_Undef); + if (solver.assigns[i] != l_Undef) return false; + } + } + + return true; +} + +/* +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; +} + +vector Subsumer::merge() { vector var_merged(solver.nVars(), false); double myTime = cpuTime(); @@ -1864,7 +2215,7 @@ void Subsumer::reAddPureLitClauses() { for (Clause **it = pureLitClauseRemoved.getData(), **end = pureLitClauseRemoved.getDataEnd(); it != end; it++) { solver.addClause(**it, (*it)->getGroup()); - free(*it); + clauseFree(*it); assert(solver.ok); } pureLitClauseRemoved.clear(); diff --git a/src/sat/cryptominisat2/Subsumer.h b/src/sat/cryptominisat2/Subsumer.h index 2d3e95a..098faa9 100644 --- a/src/sat/cryptominisat2/Subsumer.h +++ b/src/sat/cryptominisat2/Subsumer.h @@ -26,21 +26,35 @@ class ClauseCleaner; class Subsumer { public: - + + //Construct-destruct Subsumer(Solver& S2); ~Subsumer(); + + //Called from main const bool simplifyBySubsumption(); + const bool subsumeWithBinaries(const bool startUp); + void newVar(); + + //Used by cleaner 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(); + + + //UnElimination void extendModel(Solver& solver2); const bool unEliminate(const Var var); + + + //Get-functions const vec& getVarElimed() const; const uint32_t getNumElimed() const; + const bool checkElimedUnassigned() const; + const double getTotalTime() const; private: @@ -56,17 +70,18 @@ private: 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; + + //Global stats + Solver& solver; + vec var_elimed; //TRUE if var has been eliminated + double totalTime; + uint32_t numElimed; + 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 @@ -78,14 +93,14 @@ private: uint32_t numMaxBlockVars; //Start-up - void addFromSolver(vec& cs); + template + void addFromSolver(vec& cs, bool alsoLearnt = false); void addBackToSolver(); void removeWrong(vec& cs); + void removeAssignedVarsFromEliminated(); void fillCannotEliminate(); const bool treatLearnts(); - void addAllXorAsNorm(); - void addXorAsNormal3(XorClause& c); - void addXorAsNormal4(XorClause& c); + void clearAll(); //Iterations void registerIteration (CSet& iter_set) { iter_sets.push(&iter_set); } @@ -96,13 +111,14 @@ private: // 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); + template + void findSubsumed(const T& ps, const uint32_t abst, vec& out_subsumed); bool isSubsumed(Clause& ps); - uint32_t subsume0(Clause& ps); - uint32_t subsume0(Clause& ps, uint32_t abs); + template + uint32_t subsume0(T& ps, uint32_t abs); + template + uint32_t subsume0Orig(const T& ps, uint32_t abs); + void subsume0BIN(const Lit lit, const vec& lits); void subsume0LearntSet(vec& cs); void subsume1(ClauseSimp& ps); void smaller_database(); @@ -116,13 +132,30 @@ private: 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); - + bool merge(const Clause& ps, const Clause& qs, const Lit without_p, const Lit without_q, vec& out_clause); + + //Subsume with Nonexistent Bins + const bool subsWNonExistBinsFull(const bool startUp); + const bool subsWNonExistBins(const Lit& lit, const bool startUp); + template + void subsume1Partial(const T& ps); + uint32_t subsNonExistentNum; + uint32_t subsNonExistentumFailed; + bool subsNonExistentFinish; + double subsNonExistentTime; + uint32_t subsNonExistentLitsRemoved; + vec addBinaryClauses; + uint32_t doneNum; + vec subsume1PartialSubs; + vec subsume1PartialQs; + vec toVisit; + vec toVisitAll; + vec ps2; //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); + const bool hyperUtility(vec& iter, const Lit lit, BitArray& inside, vec& addToClauses); //merging //vector merge(); @@ -163,7 +196,6 @@ private: uint32_t numCalls; bool fullSubsume; uint32_t clauseID; - uint32_t numElimed; }; template @@ -194,11 +226,6 @@ 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); @@ -244,6 +271,11 @@ inline const uint32_t Subsumer::getNumElimed() const return numElimed; } +inline const double Subsumer::getTotalTime() const +{ + return totalTime; +} + }; //NAMESPACE MINISAT #endif //SIMPLIFIER_H diff --git a/src/sat/cryptominisat2/VarReplacer.cpp b/src/sat/cryptominisat2/VarReplacer.cpp index 93239f9..8e966d1 100644 --- a/src/sat/cryptominisat2/VarReplacer.cpp +++ b/src/sat/cryptominisat2/VarReplacer.cpp @@ -19,7 +19,6 @@ along with this program. If not, see . #include #include -#include "Conglomerate.h" #include "ClauseCleaner.h" #include "PartHandler.h" #include "time_mem.h" @@ -49,8 +48,7 @@ VarReplacer::VarReplacer(Solver& _solver) : VarReplacer::~VarReplacer() { for (uint i = 0; i != clauses.size(); i++) - //binaryClausePool.free(clauses[i]); - free(clauses[i]); + clauseFree(clauses[i]); } const bool VarReplacer::performReplaceInternal() @@ -76,7 +74,8 @@ const bool VarReplacer::performReplaceInternal() #endif //REPLACE_STATISTICS solver.clauseCleaner->removeAndCleanAll(true); - if (solver.ok == false) return false; + if (!solver.ok) return false; + solver.testAllClauseAttach(); #ifdef VERBOSE_DEBUG { @@ -89,7 +88,7 @@ const bool VarReplacer::performReplaceInternal() #endif Var var = 0; - const vec& removedVars = solver.conglomerate->getRemovedVars(); + const vec& removedVars = solver.xorSubsumer->getVarElimed(); const vec& removedVars2 = solver.partHandler->getSavedState(); const vec& removedVars3 = solver.subsumer->getVarElimed(); for (vector::const_iterator it = table.begin(); it != table.end(); it++, var++) { @@ -119,10 +118,12 @@ const bool VarReplacer::performReplaceInternal() lastReplacedVars = replacedVars; - if (!replace_set(solver.clauses)) goto end; - if (!replace_set(solver.learnts)) goto end; - if (!replace_set(solver.binaryClauses)) goto end; + solver.testAllClauseAttach(); + if (!replace_set(solver.binaryClauses, true)) goto end; + if (!replace_set(solver.clauses, false)) goto end; + if (!replace_set(solver.learnts, false)) goto end; if (!replace_set(solver.xorclauses)) goto end; + solver.testAllClauseAttach(); end: for (uint i = 0; i != clauses.size(); i++) @@ -152,6 +153,7 @@ const bool VarReplacer::replace_set(vec& cs) bool changed = false; Var origVar1 = c[0].var(); Var origVar2 = c[1].var(); + for (Lit *l = &c[0], *end2 = l + c.size(); l != end2; l++) { Lit newlit = table[l->var()]; if (newlit.var() != l->var()) { @@ -164,11 +166,13 @@ const bool VarReplacer::replace_set(vec& cs) } if (changed && handleUpdatedClause(c, origVar1, origVar2)) { - if (solver.ok == false) { - for(;r != end; r++) free(*r); + if (!solver.ok) { + for(;r != end; r++) clauseFree(*r); cs.shrink(r-a); return false; } + c.setRemoved(); + solver.freeLater.push(&c); } else { *a++ = *r; } @@ -181,18 +185,16 @@ const bool VarReplacer::replace_set(vec& cs) const bool VarReplacer::handleUpdatedClause(XorClause& c, const Var origVar1, const Var origVar2) { uint origSize = c.size(); - std::sort(c.getData(), c.getData() + c.size()); + std::sort(c.getData(), c.getDataEnd()); Lit p; uint32_t i, j; for (i = j = 0, p = lit_Undef; i != c.size(); i++) { - c[i] = c[i].unsign(); - if (c[i] == p) { + if (c[i].var() == p.var()) { //added, but easily removed j--; p = lit_Undef; 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(solver.assigns[c[i].var()].getBool()); //modify xor_clause_inverted instead of adding @@ -212,15 +214,14 @@ const bool VarReplacer::handleUpdatedClause(XorClause& c, const Var origVar1, co return true; case 1: solver.detachModifiedClause(origVar1, origVar2, origSize, &c); - solver.uncheckedEnqueue(c[0] ^ c.xor_clause_inverted()); + solver.uncheckedEnqueue(Lit(c[0].var(), c.xor_clause_inverted())); solver.ok = (solver.propagate() == NULL); return true; case 2: { solver.detachModifiedClause(origVar1, origVar2, origSize, &c); - vec ps(2); - ps[0] = c[0]; - ps[1] = c[1]; - addBinaryXorClause(ps, c.xor_clause_inverted(), c.getGroup(), true); + c[0] = c[0].unsign(); + c[1] = c[1].unsign(); + addBinaryXorClause(c, c.xor_clause_inverted(), c.getGroup(), true); return true; } default: @@ -233,7 +234,7 @@ const bool VarReplacer::handleUpdatedClause(XorClause& c, const Var origVar1, co return false; } -const bool VarReplacer::replace_set(vec& cs) +const bool VarReplacer::replace_set(vec& cs, const bool binClauses) { Clause **a = cs.getData(); Clause **r = a; @@ -252,13 +253,17 @@ const bool VarReplacer::replace_set(vec& cs) } if (changed && handleUpdatedClause(c, origLit1, origLit2)) { - if (solver.ok == false) { - for(;r != end; r++) free(*r); + if (!solver.ok) { + for(;r != end; r++) clauseFree(*r); cs.shrink(r-a); return false; } } else { - *a++ = *r; + if (!binClauses && c.size() == 2) { + solver.becameBinary++; + solver.binaryClauses.push(&c); + } else + *a++ = *r; } } cs.shrink(r-a); @@ -322,6 +327,9 @@ const vector VarReplacer::getReplacingVars() const void VarReplacer::extendModelPossible() const { + #ifdef VERBOSE_DEBUG + std::cout << "extendModelPossible() called" << std::endl; + #endif //VERBOSE_DEBUG uint i = 0; for (vector::const_iterator it = table.begin(); it != table.end(); it++, i++) { if (it->var() == i) continue; @@ -347,6 +355,11 @@ void VarReplacer::extendModelPossible() const void VarReplacer::extendModelImpossible(Solver& solver2) const { + + #ifdef VERBOSE_DEBUG + std::cout << "extendModelImpossible() called" << std::endl; + #endif //VERBOSE_DEBUG + vec tmpClause; uint i = 0; for (vector::const_iterator it = table.begin(); it != table.end(); it++, i++) { diff --git a/src/sat/cryptominisat2/VarReplacer.h b/src/sat/cryptominisat2/VarReplacer.h index 1a6e7b7..6c7abff 100644 --- a/src/sat/cryptominisat2/VarReplacer.h +++ b/src/sat/cryptominisat2/VarReplacer.h @@ -56,6 +56,7 @@ class VarReplacer const uint getNumReplacedVars() const; const uint getNumLastReplacedVars() const; const uint getNewToReplaceVars() const; + const uint32_t getNumTrees() const; const vector getReplacingVars() const; const vector& getReplaceTable() const; const vec& getClauses() const; @@ -66,7 +67,7 @@ class VarReplacer private: const bool performReplaceInternal(); - const bool replace_set(vec& set); + const bool replace_set(vec& cs, const bool binClauses); const bool replace_set(vec& cs); const bool handleUpdatedClause(Clause& c, const Lit origLit1, const Lit origLit2); const bool handleUpdatedClause(XorClause& c, const Var origVar1, const Var origVar2); @@ -142,6 +143,11 @@ inline const bool VarReplacer::replacingVar(const Var var) const return (reverseTable.find(var) != reverseTable.end()); } +inline const uint32_t VarReplacer::getNumTrees() const +{ + return reverseTable.size(); +} + }; //NAMESPACE MINISAT #endif //VARREPLACER_H diff --git a/src/sat/cryptominisat2/XorFinder.cpp b/src/sat/cryptominisat2/XorFinder.cpp index c2186fd..53c00db 100644 --- a/src/sat/cryptominisat2/XorFinder.cpp +++ b/src/sat/cryptominisat2/XorFinder.cpp @@ -54,9 +54,11 @@ const bool XorFinder::doNoPart(const uint minSize, const uint maxSize) uint sumLengths = 0; double time = cpuTime(); foundXors = 0; - solver.clauseCleaner->cleanClauses(cls, type); - if (solver.ok == false) - return false; + solver.clauseCleaner->cleanClauses(solver.clauses, ClauseCleaner::clauses); + if (type == ClauseCleaner::binaryClauses) { + solver.clauseCleaner->cleanClauses(solver.binaryClauses, ClauseCleaner::binaryClauses); + } + if (!solver.ok) return false; toRemove.clear(); toRemove.resize(cls.size(), false); @@ -85,7 +87,7 @@ const bool XorFinder::doNoPart(const uint minSize, const uint maxSize) } if (!sorted) { solver.detachClause(c); - std::sort(c.getData(), c.getData()+c.size()); + std::sort(c.getData(), c.getDataEnd()); solver.attachClause(c); } } else { @@ -215,7 +217,7 @@ const bool XorFinder::findXors(uint& sumLengths) XorClause* x = XorClause_new(lits, impair, old_group); cout << "- Final 2-long xor-clause: "; x->plainPrint(); - free(x); + clauseFree(x); #endif break; } diff --git a/src/sat/cryptominisat2/XorSubsumer.cpp b/src/sat/cryptominisat2/XorSubsumer.cpp index 8ec7140..f7e7fe9 100644 --- a/src/sat/cryptominisat2/XorSubsumer.cpp +++ b/src/sat/cryptominisat2/XorSubsumer.cpp @@ -17,12 +17,10 @@ Substantially modified by: Mate Soos (2010) //#define VERBOSE_DEBUG #ifdef VERBOSE_DEBUG +#define VERBOSE_DEBUGSUBSUME0 #define BIT_MORE_VERBOSITY #endif -//#define BIT_MORE_VERBOSITY -//#define TOUCH_LESS - #ifdef VERBOSE_DEBUG using std::cout; using std::endl; @@ -34,17 +32,18 @@ using namespace MINISAT; XorSubsumer::XorSubsumer(Solver& s): solver(s) + , totalTime(0.0) + , numElimed(0) + , localSubstituteUseful(0) { }; // Will put NULL in 'cs' if clause removed. void XorSubsumer::subsume0(XorClauseSimp& ps) { - assert(solver.xorclauses.size() == 0); - #ifdef VERBOSE_DEBUG + #ifdef VERBOSE_DEBUGSUBSUME0 cout << "subsume0 orig clause:"; ps.clause->plainPrint(); - cout << "pointer:" << &ps << endl; #endif vec origClause(ps.clause->size()); @@ -57,19 +56,18 @@ void XorSubsumer::subsume0(XorClauseSimp& ps) 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) { + #ifdef VERBOSE_DEBUGSUBSUME0 + cout << "subsume0 removing:"; + subs[i].clause->plainPrint(); + #endif clauses_subsumed++; assert(tmp->size() == origClause.size()); if (origClauseInverted == tmp->xor_clause_inverted()) { unlinkClause(subs[i]); - free(tmp); + clauseFree(tmp); } else { solver.ok = false; return; @@ -77,21 +75,25 @@ void XorSubsumer::subsume0(XorClauseSimp& ps) } 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); + #ifdef VERBOSE_DEBUG + std::cout << "Cutting xor-clause:"; + subs[i].clause->plainPrint(); + #endif //VERBOSE_DEBUG + XorClause *c = solver.addXorClauseInt(unmatchedPart, tmp->xor_clause_inverted() ^ !origClauseInverted, tmp->getGroup()); + if (c != NULL) { + linkInClause(*c); needUnlinkPS = true; - //} + } + if (!solver.ok) return; } unmatchedPart.clear(); } - /*if (needUnlinkPS) { + if (needUnlinkPS) { XorClause* tmp = ps.clause; unlinkClause(ps); - free(tmp); - }*/ + clauseFree(tmp); + } } void XorSubsumer::findUnMatched(vec& A, XorClause& B, vec& unmatchedPart) @@ -108,7 +110,7 @@ void XorSubsumer::findUnMatched(vec& A, XorClause& B, vec& unmatchedPa } } -void XorSubsumer::unlinkClause(XorClauseSimp c) +void XorSubsumer::unlinkClause(XorClauseSimp c, const Var elim) { XorClause& cl = *c.clause; @@ -116,6 +118,9 @@ void XorSubsumer::unlinkClause(XorClauseSimp c) maybeRemove(occur[cl[i].var()], &cl); } + if (elim != var_Undef) + elimedOutVar[elim].push_back(c.clause); + solver.detachClause(cl); clauses[c.index].clause = NULL; @@ -161,6 +166,8 @@ void XorSubsumer::linkInAlreadyClause(XorClauseSimp& c) void XorSubsumer::addFromSolver(vec& cs) { + clauseID = 0; + clauses.clear(); XorClause **i = cs.getData(); for (XorClause **end = i + cs.size(); i != end; i++) { if (i+1 != end) @@ -171,10 +178,12 @@ void XorSubsumer::addFromSolver(vec& cs) (*i)->calcXorAbstraction(); } cs.clear(); + cs.push(NULL); //HACK --to force xor-propagation } void XorSubsumer::addBackToSolver() { + solver.xorclauses.pop(); //HACK --to force xor-propagation for (uint32_t i = 0; i < clauses.size(); i++) { if (clauses[i].clause != NULL) { solver.xorclauses.push(clauses[i].clause); @@ -189,6 +198,236 @@ void XorSubsumer::addBackToSolver() clauseID = 0; } +void XorSubsumer::fillCannotEliminate() +{ + std::fill(cannot_eliminate.getData(), cannot_eliminate.getDataEnd(), false); + for (uint32_t i = 0; i < solver.clauses.size(); i++) + addToCannotEliminate(solver.clauses[i]); + + for (uint32_t i = 0; i < solver.binaryClauses.size(); i++) + if (!(*solver.binaryClauses[i]).learnt()) addToCannotEliminate(solver.binaryClauses[i]); + + const vec& tmp = solver.varReplacer->getClauses(); + for (uint32_t i = 0; i < tmp.size(); i++) + addToCannotEliminate(tmp[i]); + + #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 XorSubsumer::extendModel(Solver& solver2) +{ + assert(checkElimedUnassigned()); + vec tmp; + typedef map > elimType; + for (elimType::iterator it = elimedOutVar.begin(), end = elimedOutVar.end(); it != end; it++) { + #ifdef VERBOSE_DEBUG + Var var = it->first; + std::cout << "Reinserting elimed var: " << var+1 << std::endl; + #endif + + for (vector::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) { + XorClause& c = **it2; + #ifdef VERBOSE_DEBUG + std::cout << "Reinserting Clause: "; + c.plainPrint(); + #endif + tmp.clear(); + tmp.growTo(c.size()); + std::copy(c.getData(), c.getDataEnd(), tmp.getData()); + bool inverted = c.xor_clause_inverted(); + solver2.addXorClause(tmp, inverted); + assert(solver2.ok); + } + } +} + +const bool XorSubsumer::localSubstitute() +{ + vec tmp; + for (Var var = 0; var < occur.size(); var++) { + vec& occ = occur[var]; + + if (occ.size() <= 1) continue; + for (uint32_t i = 0; i < occ.size(); i++) { + XorClause& c1 = *occ[i].clause; + for (uint32_t i2 = i+1; i2 < occ.size(); i2++) { + XorClause& c2 = *occ[i2].clause; + tmp.clear(); + tmp.growTo(c1.size() + c2.size()); + std::copy(c1.getData(), c1.getDataEnd(), tmp.getData()); + std::copy(c2.getData(), c2.getDataEnd(), tmp.getData() + c1.size()); + clearDouble(tmp); + if (tmp.size() <= 2) { + #ifdef VERBOSE_DEBUG + std::cout << "Local substiuting. Clause1:"; c1.plainPrint(); + std::cout << "Clause 2:"; c2.plainPrint(); + #endif //VERBOSE_DEBUG + localSubstituteUseful++; + uint32_t lastSize = solver.varReplacer->getClauses().size(); + solver.addXorClauseInt(tmp, c1.xor_clause_inverted() ^ !c2.xor_clause_inverted(), c1.getGroup()); + for (uint32_t i = lastSize; i < solver.varReplacer->getClauses().size(); i++) + addToCannotEliminate(solver.varReplacer->getClauses()[i]); + if (!solver.ok) { + #ifdef VERBOSE_DEBUG + std::cout << "solver.ok is false after local substitution" << std::endl; + #endif //VERBOSE_DEBUG + return false; + } + } + } + } + } + + return true; +} + +void XorSubsumer::clearDouble(vec& ps) const +{ + std::sort(ps.getData(), ps.getDataEnd()); + Lit p; + uint32_t i, j; + for (i = j = 0, p = lit_Undef; i != ps.size(); i++) { + if (ps[i].var() == p.var()) { + //added, but easily removed + j--; + p = lit_Undef; + } else + ps[j++] = p = ps[i]; + } + ps.shrink(i - j); +} + +void XorSubsumer::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); + clauseFree(&c); + break; + } + } + if (!remove) + *j++ = *i; + } + cs.shrink(i-j); +} + + +const bool XorSubsumer::removeDependent() +{ + for (Var var = 0; var < occur.size(); var++) { + if (cannot_eliminate[var] || !solver.decision_var[var] || solver.assigns[var] != l_Undef) continue; + vec& occ = occur[var]; + + if (occ.size() == 1) { + #ifdef VERBOSE_DEBUG + std::cout << "Eliminating dependent var " << var + 1 << std::endl; + std::cout << "-> Removing dependent clause "; occ[0].clause->plainPrint(); + #endif //VERBOSE_DEBUG + unlinkClause(occ[0], var); + solver.setDecisionVar(var, false); + var_elimed[var] = true; + numElimed++; + } else if (occ.size() == 2) { + vec lits; + XorClause& c1 = *(occ[0].clause); + lits.growTo(c1.size()); + std::copy(c1.getData(), c1.getDataEnd(), lits.getData()); + bool inverted = c1.xor_clause_inverted(); + + XorClause& c2 = *(occ[1].clause); + lits.growTo(lits.size() + c2.size()); + std::copy(c2.getData(), c2.getDataEnd(), lits.getData() + c1.size()); + inverted ^= !c2.xor_clause_inverted(); + uint32_t group = c2.getGroup(); + + #ifdef VERBOSE_DEBUG + std::cout << "Eliminating var " << var + 1 << " present in 2 xor-clauses" << std::endl; + std::cout << "-> Removing xor clause "; occ[0].clause->plainPrint(); + std::cout << "-> Removing xor clause "; occ[1].clause->plainPrint(); + #endif //VERBOSE_DEBUG + XorClauseSimp toUnlink0 = occ[0]; + XorClauseSimp toUnlink1 = occ[1]; + unlinkClause(toUnlink0); + clauseFree(toUnlink0.clause); + unlinkClause(toUnlink1, var); + solver.setDecisionVar(var, false); + var_elimed[var] = true; + numElimed++; + + uint32_t lastSize = solver.varReplacer->getClauses().size(); + XorClause* c = solver.addXorClauseInt(lits, inverted, group); + #ifdef VERBOSE_DEBUG + if (c != NULL) { + std::cout << "-> Added combined xor clause:"; c->plainPrint(); + } else + std::cout << "-> Combined xor clause is NULL" << std::endl; + #endif + if (c != NULL) linkInClause(*c); + for (uint32_t i = lastSize; i < solver.varReplacer->getClauses().size(); i++) + addToCannotEliminate(solver.varReplacer->getClauses()[i]); + if (!solver.ok) { + #ifdef VERBOSE_DEBUG + std::cout << "solver.ok is false after var-elim through xor" << std::endl; + #endif //VERBOSE_DEBUG + return false; + } + } + } + + return true; +} + +inline void XorSubsumer::addToCannotEliminate(Clause* it) +{ + const Clause& c = *it; + for (uint32_t i2 = 0; i2 < c.size(); i2++) + cannot_eliminate[c[i2].var()] = true; +} + +const bool XorSubsumer::unEliminate(const Var var) +{ + assert(var_elimed[var]); + typedef map > elimType; + elimType::iterator it = elimedOutVar.find(var); + + //MUST set to decision, since it would never have been eliminated + //had it not been decision var + solver.setDecisionVar(var, true); + var_elimed[var] = false; + numElimed--; + assert(it != elimedOutVar.end()); + + FILE* backup_libraryCNFfile = solver.libraryCNFFile; + solver.libraryCNFFile = NULL; + for (vector::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) { + XorClause& c = **it2; + solver.addXorClause(c, c.xor_clause_inverted()); + clauseFree(&c); + } + solver.libraryCNFFile = backup_libraryCNFfile; + elimedOutVar.erase(it); + + return solver.ok; +} + + const bool XorSubsumer::simplifyBySubsumption(const bool doFullSubsume) { double myTime = cpuTime(); @@ -196,19 +435,21 @@ const bool XorSubsumer::simplifyBySubsumption(const bool doFullSubsume) clauses_subsumed = 0; clauses_cut = 0; clauseID = 0; - - for (Var var = 0; var < solver.nVars(); var++) { - //occur[var].clear(true); - newVar(); - } - + uint32_t lastNumElimed = numElimed; + localSubstituteUseful = 0; while (solver.performReplace && solver.varReplacer->needsReplace()) { if (!solver.varReplacer->performReplace()) return false; } + for (Var var = 0; var < solver.nVars(); var++) { + occur[var].clear(); + } + solver.findAllAttach(); + solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses); if (!solver.ok) return false; + solver.testAllClauseAttach(); clauses.clear(); clauses.reserve(solver.xorclauses.size()); @@ -231,20 +472,37 @@ const bool XorSubsumer::simplifyBySubsumption(const bool doFullSubsume) for (uint32_t i = 0; i < clauses.size(); i++) { if (clauses[i].clause != NULL) { subsume0(clauses[i]); - if (!solver.ok) return false; + if (!solver.ok) { + addBackToSolver(); + return false; + } } } - if (solver.qhead != solver.trail.size()) propagated = true; - solver.ok = solver.propagate() == NULL; + propagated = (solver.qhead != solver.trail.size()); + 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()) { + testAllClauseAttach(); + + fillCannotEliminate(); + if (solver.conglomerateXors && !removeDependent()) { + addBackToSolver(); + return false; + } + testAllClauseAttach(); + + if (solver.heuleProcess && !localSubstitute()) { + addBackToSolver(); + return false; + } + testAllClauseAttach(); + + /*if (solver.performReplace && solver.varReplacer->needsReplace()) { addBackToSolver(); while (solver.performReplace && solver.varReplacer->needsReplace()) { replaced = true; @@ -252,28 +510,55 @@ const bool XorSubsumer::simplifyBySubsumption(const bool doFullSubsume) return false; } addFromSolver(solver.xorclauses); - } + }*/ } - - if (solver.trail.size() - origTrailSize > 0) - solver.order_heap.filter(Solver::VarFilter(solver)); - + + solver.order_heap.filter(Solver::VarFilter(solver)); + + removeWrong(solver.learnts); + removeWrong(solver.binaryClauses); 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) <clause == NULL) continue; + const XorClause& c = *it->clause; + assert(find(solver.xorwatches[c[0].var()], &c)); + assert(find(solver.xorwatches[c[1].var()], &c)); + if (solver.assigns[c[0].var()]!=l_Undef || solver.assigns[c[1].var()]!=l_Undef) { + for (uint i = 0; i < c.size();i++) { + assert(solver.assigns[c[i].var()] != l_Undef); + } + } + } +} +#else +inline void XorSubsumer::testAllClauseAttach() const +{ + return; +} +#endif //DEBUG_ATTACH + void XorSubsumer::findSubsumed(XorClause& ps, vec& out_subsumed) { - #ifdef VERBOSE_DEBUG + #ifdef VERBOSE_DEBUGSUBSUME0 cout << "findSubsumed: "; for (uint32_t i = 0; i < ps.size(); i++) { if (ps[i].sign()) printf("-"); @@ -295,7 +580,7 @@ void XorSubsumer::findSubsumed(XorClause& ps, vec& out_subsumed) 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 + #ifdef VERBOSE_DEBUGSUBSUME0 cout << "subsumed: "; it->clause->plainPrint(); #endif @@ -303,4 +588,16 @@ void XorSubsumer::findSubsumed(XorClause& ps, vec& out_subsumed) } } -}; //NAMESPACE MINISAT +const bool XorSubsumer::checkElimedUnassigned() const +{ + for (uint32_t i = 0; i < var_elimed.size(); i++) { + if (var_elimed[i]) { + assert(solver.assigns[i] == l_Undef); + if (solver.assigns[i] != l_Undef) return false; + } + } + + return true; +} + +}; //NAMESPACE MINISAT \ No newline at end of file diff --git a/src/sat/cryptominisat2/XorSubsumer.h b/src/sat/cryptominisat2/XorSubsumer.h index 1876bce..b603a94 100644 --- a/src/sat/cryptominisat2/XorSubsumer.h +++ b/src/sat/cryptominisat2/XorSubsumer.h @@ -24,10 +24,16 @@ public: const bool simplifyBySubsumption(const bool doFullSubsume = false); void unlinkModifiedClause(vec& origClause, XorClauseSimp c); void unlinkModifiedClauseNoDetachNoNULL(vec& origClause, XorClauseSimp c); - void unlinkClause(XorClauseSimp cc); + void unlinkClause(XorClauseSimp cc, Var elim = var_Undef); XorClauseSimp linkInClause(XorClause& cl); void linkInAlreadyClause(XorClauseSimp& c); void newVar(); + void extendModel(Solver& solver2); + const uint32_t getNumElimed() const; + const vec& getVarElimed() const; + const bool unEliminate(const Var var); + const bool checkElimedUnassigned() const; + const double getTotalTime() const; private: @@ -54,6 +60,27 @@ private: bool subset(const T1& A, const T2& B); bool subsetAbst(uint32_t A, uint32_t B); void findUnMatched(vec& A, XorClause& B, vec& unmatchedPart); + + //helper + void testAllClauseAttach() const; + + //dependent removal + const bool removeDependent(); + void fillCannotEliminate(); + vec cannot_eliminate; + void addToCannotEliminate(Clause* it); + void removeWrong(vec& cs); + + //Global stats + double totalTime; + map > elimedOutVar; + vec var_elimed; + uint32_t numElimed; + + //Heule-process + void clearDouble(vec& ps) const; + const bool localSubstitute(); + uint32_t localSubstituteUseful; uint32_t clauses_subsumed; uint32_t clauses_cut; @@ -87,7 +114,24 @@ bool XorSubsumer::subset(const T1& A, const T2& B) inline void XorSubsumer::newVar() { occur .push(); - seen_tmp .push(0); // (one for each polarity) + seen_tmp .push(0); + cannot_eliminate.push(0); + var_elimed.push(0); +} + +inline const vec& XorSubsumer::getVarElimed() const +{ + return var_elimed; +} + +inline const uint32_t XorSubsumer::getNumElimed() const +{ + return numElimed; +} + +inline const double XorSubsumer::getTotalTime() const +{ + return totalTime; } }; //NAMESPACE MINISAT diff --git a/src/sat/cryptominisat2/constants.h b/src/sat/cryptominisat2/constants.h index 4c94beb..e69de29 100644 --- a/src/sat/cryptominisat2/constants.h +++ b/src/sat/cryptominisat2/constants.h @@ -1,36 +0,0 @@ -/****************************************************************************************[Solver.h] -MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson -glucose -- Gilles Audemard, Laurent Simon (2008) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************************************/ - -#define RATIOREMOVECLAUSES 3 -#define NBCLAUSESBEFOREREDUCE 20000 -#define DYNAMICNBLEVEL -#define UPDATEVARACTIVITY -#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 -//#define USE_GAUSS -- 2.47.3