]> git.unchartedbackwaters.co.uk Git - francis/stp.git/commitdiff
Integrate CryptoMiniSat 2.9.0.
authorFrancis Russell <francis@unchartedbackwaters.co.uk>
Tue, 19 Apr 2011 02:09:37 +0000 (03:09 +0100)
committerFrancis Russell <francis@unchartedbackwaters.co.uk>
Tue, 19 Apr 2011 02:09:37 +0000 (03:09 +0100)
87 files changed:
scripts/Makefile.common
src/sat/CryptoMinisat.cpp
src/sat/CryptoMinisat.h
src/sat/cryptominisat2/BitArray.h
src/sat/cryptominisat2/BoundedQueue.h
src/sat/cryptominisat2/CMakeLists.txt
src/sat/cryptominisat2/CSet.h
src/sat/cryptominisat2/Clause.h
src/sat/cryptominisat2/ClauseAllocator.cpp
src/sat/cryptominisat2/ClauseAllocator.h
src/sat/cryptominisat2/ClauseCleaner.cpp
src/sat/cryptominisat2/ClauseCleaner.h
src/sat/cryptominisat2/ClauseOffset.h [new file with mode: 0644]
src/sat/cryptominisat2/ClauseVivifier.cpp [new file with mode: 0644]
src/sat/cryptominisat2/ClauseVivifier.h [new file with mode: 0644]
src/sat/cryptominisat2/CompleteDetachReattacher.cpp [new file with mode: 0644]
src/sat/cryptominisat2/CompleteDetachReattacher.h [new file with mode: 0644]
src/sat/cryptominisat2/DataSync.cpp [new file with mode: 0644]
src/sat/cryptominisat2/DataSync.h [new file with mode: 0644]
src/sat/cryptominisat2/DimacsParser.cpp [new file with mode: 0644]
src/sat/cryptominisat2/DimacsParser.h [new file with mode: 0644]
src/sat/cryptominisat2/FailedLitSearcher.cpp [new file with mode: 0644]
src/sat/cryptominisat2/FailedLitSearcher.h [new file with mode: 0644]
src/sat/cryptominisat2/FailedVarSearcher.cpp [deleted file]
src/sat/cryptominisat2/FailedVarSearcher.h [deleted file]
src/sat/cryptominisat2/FindUndef.cpp
src/sat/cryptominisat2/FindUndef.h
src/sat/cryptominisat2/Gaussian.cpp
src/sat/cryptominisat2/Gaussian.h
src/sat/cryptominisat2/GaussianConfig.h
src/sat/cryptominisat2/Logger.cpp
src/sat/cryptominisat2/Logger.h
src/sat/cryptominisat2/MTRand/MersenneTwister.h
src/sat/cryptominisat2/Main.cpp
src/sat/cryptominisat2/Main.h [new file with mode: 0644]
src/sat/cryptominisat2/Makefile
src/sat/cryptominisat2/MatrixFinder.cpp
src/sat/cryptominisat2/MatrixFinder.h
src/sat/cryptominisat2/MersenneTwister.h [deleted file]
src/sat/cryptominisat2/OnlyNonLearntBins.cpp
src/sat/cryptominisat2/OnlyNonLearntBins.h
src/sat/cryptominisat2/PackedMatrix.h
src/sat/cryptominisat2/PackedRow.cpp
src/sat/cryptominisat2/PackedRow.h
src/sat/cryptominisat2/PartFinder.cpp
src/sat/cryptominisat2/PartFinder.h
src/sat/cryptominisat2/PartHandler.cpp
src/sat/cryptominisat2/PartHandler.h
src/sat/cryptominisat2/PropBy.h [new file with mode: 0644]
src/sat/cryptominisat2/RestartTypeChooser.cpp
src/sat/cryptominisat2/RestartTypeChooser.h
src/sat/cryptominisat2/SCCFinder.cpp [new file with mode: 0644]
src/sat/cryptominisat2/SCCFinder.h [new file with mode: 0644]
src/sat/cryptominisat2/SharedData.h [new file with mode: 0644]
src/sat/cryptominisat2/Solver.cpp
src/sat/cryptominisat2/Solver.h
src/sat/cryptominisat2/SolverConf.cpp [new file with mode: 0644]
src/sat/cryptominisat2/SolverConf.h [new file with mode: 0644]
src/sat/cryptominisat2/SolverDebug.cpp [new file with mode: 0644]
src/sat/cryptominisat2/SolverMisc.cpp [new file with mode: 0644]
src/sat/cryptominisat2/SolverTypes.h
src/sat/cryptominisat2/StateSaver.cpp
src/sat/cryptominisat2/StateSaver.h
src/sat/cryptominisat2/StreamBuffer.h [new file with mode: 0644]
src/sat/cryptominisat2/Subsumer.cpp
src/sat/cryptominisat2/Subsumer.h
src/sat/cryptominisat2/UselessBinRemover.cpp
src/sat/cryptominisat2/UselessBinRemover.h
src/sat/cryptominisat2/VERSION
src/sat/cryptominisat2/VarReplacer.cpp
src/sat/cryptominisat2/VarReplacer.h
src/sat/cryptominisat2/Watched.h [new file with mode: 0644]
src/sat/cryptominisat2/XSet.h
src/sat/cryptominisat2/XorFinder.cpp
src/sat/cryptominisat2/XorFinder.h
src/sat/cryptominisat2/XorSubsumer.cpp
src/sat/cryptominisat2/XorSubsumer.h
src/sat/cryptominisat2/constants.h
src/sat/cryptominisat2/msvc/stdint.h
src/sat/cryptominisat2/mtl/Alg.h
src/sat/cryptominisat2/mtl/BasicHeap.h
src/sat/cryptominisat2/mtl/BoxedVec.h
src/sat/cryptominisat2/mtl/Heap.h
src/sat/cryptominisat2/mtl/Map.h
src/sat/cryptominisat2/mtl/Queue.h
src/sat/cryptominisat2/mtl/Vec.h
src/sat/cryptominisat2/time_mem.h

index f5b0930d35f58e7e1000353e146d2ff0f71dbdc4..d5b47af4bb9d4f2325636b21e0947872cb839984 100644 (file)
@@ -47,7 +47,7 @@ ifdef STATIC
 endif
 
 
-LDFLAGS = $(LDFLAGS_BASE)
+LDFLAGS = $(LDFLAGS_BASE) -lz -fopenmp
 CFLAGS = $(CFLAGS_BASE) $(CFLAGS_M32)
 
 
index 14be064f31fb7a23646062e0c5436386369201fd..c89339e3dac8681068d620e0799beb631aa33d0f 100644 (file)
@@ -15,7 +15,7 @@ namespace BEEV
 
   CryptoMinisat::CryptoMinisat()
   {
-     s = new MINISAT::Solver();
+     s = new Solver();
   }
 
   CryptoMinisat::~CryptoMinisat()
@@ -30,9 +30,9 @@ namespace BEEV
     // Cryptominisat uses a slightly different Lit class too.
 
     // VERY SLOW>
-    MINISAT::vec<MINISAT::Lit>  v;
+    vec<Lit>  v;
     for (int i =0; i<ps.size();i++)
-      v.push(MINISAT::Lit(var(ps[i]), sign(ps[i])));
+      v.push(Lit(var(ps[i]), sign(ps[i])));
 
     s->addClause(v);
   }
@@ -63,7 +63,7 @@ namespace BEEV
 
   int CryptoMinisat::setVerbosity(int v)
   {
-    s->verbosity = v;
+    s->conf.verbosity = v;
   }
 
   int CryptoMinisat::nVars()
index c7832e0c885bf13a52e8968b08d06c79973a7c4d..33c8ab63e9065a2ffcc43b4c3a70e4ecf54e30c4 100644 (file)
@@ -6,16 +6,13 @@
 
 #include "SATSolver.h"
 
-namespace MINISAT
-{
-   class Solver;
-}
+class Solver;
 
 namespace BEEV
 {
   class CryptoMinisat : public SATSolver
   {
-    MINISAT::Solver* s;
+    Solver* s;
 
   public:
     CryptoMinisat();
index aa58b620164a93c54e752cb34846565b29ae891b..c9e0b376056f06f678c6fa024942617686032df0 100644 (file)
@@ -28,10 +28,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <stdint.h>
 #endif //_MSC_VER
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 class BitArray
 {
 public:
@@ -40,14 +36,14 @@ public:
         , 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) {
@@ -56,10 +52,10 @@ public:
             mp = new uint64_t[size];
         }
         memcpy(mp, b.mp, sizeof(uint64_t)*size);
-        
+
         return *this;
     }
-    
+
     BitArray& operator&=(const BitArray& b)
     {
         assert(size == b.size);
@@ -70,22 +66,8 @@ public:
             t1++;
             t2++;
         }
-        
-        return *this;
-    }
 
-    const bool nothingInCommon(const BitArray& b) const
-    {
-        assert(size == b.size);
-        const uint64_t* t1 = mp;
-        const uint64_t* t2 = b.mp;
-        for (uint64_t i = 0; i < size; i++) {
-            if ((*t1)&(*t2)) return false;
-            t1++;
-            t2++;
-        }
-        
-        return true;
+        return *this;
     }
 
     BitArray& removeThese(const BitArray& b)
@@ -111,8 +93,8 @@ public:
 
         return *this;
     }
-    
-    void resize(uint _size, const bool fill)
+
+    void resize(uint32_t _size, const bool fill)
     {
         _size = _size/64 + (bool)(_size%64);
         if (size != _size) {
@@ -123,7 +105,7 @@ public:
         if (fill) setOne();
         else setZero();
     }
-    
+
     ~BitArray()
     {
         delete[] mp;
@@ -132,8 +114,8 @@ public:
     inline const bool isZero() const
     {
         const uint64_t*  mp2 = (const uint64_t*)mp;
-        
-        for (uint i = 0; i < size; i++) {
+
+        for (uint32_t i = 0; i < size; i++) {
             if (mp2[i]) return false;
         }
         return true;
@@ -143,51 +125,49 @@ public:
     {
         memset(mp, 0, size*sizeof(uint64_t));
     }
-    
+
     inline void setOne()
     {
-        memset(mp, 0, size*sizeof(uint64_t));
+        memset(mp, 0xff, size*sizeof(uint64_t));
     }
 
-    inline void clearBit(const uint i)
+    inline void clearBit(const uint32_t i)
     {
         #ifdef DEBUG_BITARRAY
         assert(size*64 > i);
         #endif
-        
+
         mp[i/64] &= ~((uint64_t)1 << (i%64));
     }
 
-    inline void setBit(const uint i)
+    inline void setBit(const uint32_t 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
+    inline const bool operator[](const uint32_t& i) const
     {
         #ifdef DEBUG_BITARRAY
         assert(size*64 > i);
         #endif
-        
+
         return (mp[i/64] >> (i%64)) & 1;
     }
-    
-    inline const uint getSize() const
+
+    inline const uint32_t getSize() const
     {
         return size*64;
     }
 
 private:
-    
-    uint size;
+
+    uint32_t size;
     uint64_t* mp;
 };
 
-}; //NAMESPACE MINISAT
-
 #endif //BITARRAY_H
 
index a705a6dc0fe41ce4863fa61e574f6e418583ddd5..83ccf0050e653e2cf7feb55e7a911d2d6bdddc58 100644 (file)
@@ -1,25 +1,14 @@
 /*****************************************************************************************[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.
+2008 - Gilles Audemard, Laurent Simon
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+Original code by MiniSat and glucose authors are under an MIT licence.
+Modifications for CryptoMiniSat are under GPLv3 licence.
 **************************************************************************************************/
 
-#ifndef BoundedQueue_h
-#define BoundedQueue_h
+#ifndef BOUNDEDQUEUE_H
+#define BOUNDEDQUEUE_H
 
 #ifdef _MSC_VER
 #include <msvc/stdint.h>
@@ -29,60 +18,75 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
 
 #include "Vec.h"
 
-//=================================================================================================
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
 template <class T>
 class bqueue {
     vec<T>  elems;
-    int     first;
-    int     last;
-    uint64_t sumofqueue;
-    int     maxsize;
-    int     queuesize; // Number of current elements (must be < maxsize !)
-    
+    uint32_t first;
+    uint32_t last;
+    int64_t  sumofqueue;
+    int64_t  sumOfAllElems;
+    uint64_t totalNumElems;
+    uint32_t maxsize;
+    uint32_t 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) {
+    bqueue(void) :
+        first(0)
+        , last(0)
+        , sumofqueue(0)
+        , sumOfAllElems(0)
+        , totalNumElems(0)
+        , maxsize(0)
+        , queuesize(0)
+    {}
+
+    void initSize(const uint32_t size) {growTo(size);} // Init size of bounded size queue
+
+    void push(const 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 
+        } else
             queuesize++;
         sumofqueue += x;
+        sumOfAllElems += x;
+        totalNumElems++;
         elems[first] = x;
         if ((++first) == maxsize) first = 0;
     }
 
-    T peek() { assert(queuesize>0); return elems[last]; }
+    const T peek() const { 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;}
+
+    int64_t getsum() const {return sumofqueue;}
+    uint32_t getAvgUInt() const {return (uint64_t)sumofqueue/(uint64_t)queuesize;}
+    double getAvgDouble() const {return (double)sumofqueue/(double)queuesize;}
+    double getAvgAllDouble() const {return (double)sumOfAllElems/(double)totalNumElems;}
+    uint64_t getTotalNumeElems() const {return totalNumElems;}
     int isvalid() const {return (queuesize==maxsize);}
-    
-    void growTo(int size) {
-        elems.growTo(size); 
+
+    void growTo(const uint32_t size) {
+        elems.growTo(size);
         first=0; maxsize=size; queuesize = 0;
-        for(int i=0;i<size;i++) elems[i]=0; 
+        for(uint32_t i=0;i<size;i++) elems[i]=0;
     }
 
     void fastclear() {first = 0; last = 0; queuesize=0; sumofqueue=0;} // to be called after restarts... Discard the queue
-    
-    int  size(void)    { return queuesize; }
 
-    void clear(bool dealloc = false)   { elems.clear(dealloc); first = 0; maxsize=0; queuesize=0;sumofqueue=0;}
-};
+    int  size(void)    { return queuesize; }
 
-//=================================================================================================
+    void clear(bool dealloc = false)   {
+        elems.clear(dealloc);
+        first = 0;
+        last = 0;
+        maxsize=0;
+        queuesize=0;
+        sumofqueue=0;
 
-}; //namespace MINISAT
+        totalNumElems = 0;
+        sumOfAllElems = 0;
+    }
+};
 
-#endif
+#endif //BOUNDEDQUEUE_H
index 0760f7b934ad760feda5815b5a3228a726e6d03f..a9353cb9cc016485e4f2cb74dd58fdbad9950edb 100644 (file)
@@ -1,43 +1,28 @@
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+include_directories(${cryptoms_SOURCE_DIR}/mtl)
+include_directories(${cryptoms_SOURCE_DIR}/Solver)
+include_directories(${cryptoms_SOURCE_DIR}/MTRand)
 
-IF(DEFINED CMAKE_BUILD_TYPE)
-    SET(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
-ELSE()
-  SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
-ENDIF()
+# cmake_minimum_required( VERSION 2.6 FATAL_ERROR )
+# find_package( Boost 1.34 COMPONENTS REQUIRED thread )
+# link_directories ( ${Boost_LIBRARY_DIRS} )
+# include_directories ( ${Boost_INCLUDE_DIRS} )
 
-#set(CMAKE_C_COMPILER "gcc-4.4")
-#set(CMAKE_CXX_COMPILER "/usr/bin/g++-4.4")
-
-PROJECT(cryptoms)
-SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -Wall -Werror -g -mtune=native")
-SET(CMAKE_CXX_FLAGS_DEBUG "-Wall -Werror -O0 -ggdb")
-SET(CMAKE_CXX_FLAGS_RELEASE "-Wall -fprofile-use -Werror -O3 -g0 -fno-exceptions -DNDEBUG -mtune=native -fomit-frame-pointer")
-SET(CMAKE_EXE_LINKER_FLAGS "-static")
-
-find_package( ZLIB )
-link_directories( ${ZLIB_LIBRARY} )
-include_directories( ${ZLIB_INCLUDE_DIR} )
-
-find_package(Boost REQUIRED)
-
-add_definitions(-DVERSION="STP version")
-
-include_directories(mtl)
-include_directories(MTRand)
 
 add_executable(cryptominisat
+    Main.cpp
     Logger.cpp
     Solver.cpp
+    SolverDebug.cpp
+    SolverMisc.cpp
     Gaussian.cpp
     PackedRow.cpp
     XorFinder.cpp
     MatrixFinder.cpp
     VarReplacer.cpp
-    FindUndef.cpp
+#   FindUndef.cpp
     ClauseCleaner.cpp
     RestartTypeChooser.cpp
-    FailedVarSearcher.cpp
+    FailedLitSearcher.cpp
     PartFinder.cpp
     Subsumer.cpp
     PartHandler.cpp
@@ -46,12 +31,17 @@ add_executable(cryptominisat
     ClauseAllocator.cpp
     UselessBinRemover.cpp
     OnlyNonLearntBins.cpp
-    Main.cpp
+    CompleteDetachReattacher.cpp
+    DimacsParser.cpp
+    SCCFinder.cpp
+    SolverConf.cpp
+    ClauseVivifier.cpp
+    DataSync.cpp
 )
 
 target_link_libraries(cryptominisat
     ${ZLIB_LIBRARY}
-    ${Boost_LIBRARIES}
+    ${Perftools_LIBRARIES}
+#    ${Boost_LIBRARIES}
+#    ${CMAKE_THREAD_LIBS_INIT}
 )
-
-
index fb6f84bcb64ac9c191b23ddcf39c8dd0d41a5d9d..6ad2f7854ae992fb721fdaca05700a235ab7386c 100644 (file)
@@ -13,14 +13,17 @@ From: Solver.C -- (C) Niklas Een, Niklas Sorensson, 2004
 #include <stdint.h>
 #endif //_MSC_VER
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 class Clause;
 
-//#pragma pack(push)
-//#pragma pack(1)
+
+/**
+@brief A class to hold a clause and a related index
+
+This class is used in Subsumer. Basically, the index could be added to the
+Clause class, but it would take space, and that would slow down the solving.
+
+NOTE: On 64-bit systems, this datastructure needs 128 bits :O
+*/
 class ClauseSimp
 {
     public:
@@ -28,28 +31,36 @@ class ClauseSimp
         clause(c)
         , index(_index)
         {}
-        
-        Clause* clause;
-        uint32_t index;
+
+        Clause* clause; ///<The clause to be stored
+        uint32_t index; ///<The index of the clause in Subsumer::clauses
 };
-//#pragma pack(pop)
 
+/**
+@brief Used to quicky add, remove and iterate through a clause set
+
+Used in Subsumer to put into a set all clauses that need to be treated
+*/
 class CSet {
-    vec<uint32_t>       where;  // Map clause ID to position in 'which'.
-    vec<ClauseSimp> which;  // List of clauses (for fast iteration). May contain 'Clause_NULL'.
-    vec<uint32_t>       free;   // List of positions holding 'Clause_NULL'.
-    
+    vec<uint32_t>       where;  ///<Map clause ID to position in 'which'.
+    vec<ClauseSimp>     which;  ///< List of clauses (for fast iteration). May contain 'Clause_NULL'.
+    vec<uint32_t>       free;   ///<List of positions holding 'Clause_NULL'.
+
     public:
         //ClauseSimp& operator [] (uint32_t index) { return which[index]; }
         void reserve(uint32_t size) { where.reserve(size);}
-        uint32_t size(void) const { return which.size(); }
+        //uint32_t size(void) const { return which.size(); }
+        ///@brief Number of elements in the set
         uint32_t nElems(void) const { return which.size() - free.size(); }
-        
-        bool add(const ClauseSimp& c) {
+
+        /**
+        @brief Add a clause to the set
+        */
+        const bool add(const ClauseSimp& c) {
             assert(c.clause != NULL);
             where.growTo(c.index+1, std::numeric_limits<uint32_t>::max());
             if (where[c.index] != std::numeric_limits<uint32_t>::max()) {
-                return true;
+                return false;
             }
             if (free.size() > 0){
                 where[c.index] = free.last();
@@ -59,9 +70,22 @@ class CSet {
                 where[c.index] = which.size();
                 which.push(c);
             }
+            return true;
+        }
+
+        const bool alreadyIn(const ClauseSimp& c) const {
+            assert(c.clause != NULL);
+            if (where.size() < c.index+1) return false;
+            if (where[c.index] != std::numeric_limits<uint32_t>::max())
+                return true;
             return false;
         }
-        
+
+        /**
+        @brief Remove clause from set
+
+        Handles it correctly if the clause was not in the set anyway
+        */
         bool exclude(const ClauseSimp& c) {
             assert(c.clause != NULL);
             if (c.index >= where.size() || where[c.index] == std::numeric_limits<uint32_t>::max()) {
@@ -73,7 +97,10 @@ class CSet {
             where[c.index] = std::numeric_limits<uint32_t>::max();
             return true;
         }
-        
+
+        /**
+        @brief Fully clear the set
+        */
         void clear(void) {
             for (uint32_t i = 0; i < which.size(); i++)  {
                 if (which[i].clause != NULL) {
@@ -83,47 +110,97 @@ class CSet {
             which.clear();
             free.clear();
         }
-        
+
+        /**
+        @brief A normal iterator to iterate through the set
+
+        No other way exists of iterating correctly.
+        */
         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;
         };
-        
+
+        /**
+        @brief A constant iterator to iterate through the set
+
+        No other way exists of iterating correctly.
+        */
+        class const_iterator
+        {
+            public:
+                const_iterator(const ClauseSimp* _it) :
+                it(_it)
+                {}
+
+                void operator++()
+                {
+                    it++;
+                }
+
+                const bool operator!=(const const_iterator& iter) const
+                {
+                    return (it != iter.it);;
+                }
+
+                const ClauseSimp& operator*() {
+                    return *it;
+                }
+
+                const ClauseSimp*& operator->() {
+                    return it;
+                }
+            private:
+                const ClauseSimp* it;
+        };
+
+        ///@brief Get starting iterator
         iterator begin()
         {
             return iterator(which.getData());
         }
-        
+
+        ///@brief Get ending iterator
         iterator end()
         {
             return iterator(which.getData() + which.size());
         }
+
+        ///@brief Get starting iterator (constant version)
+        const_iterator begin() const
+        {
+            return const_iterator(which.getData());
+        }
+
+        ///@brief Get ending iterator (constant version)
+        const_iterator end() const
+        {
+            return const_iterator(which.getData() + which.size());
+        }
 };
 
 #endif //CSET_H
 
-}; //NAMESPACE MINISAT
-
index 42d55d7ce42f86a0ac9238348b03ee0fae3a7719..eb99785125035e549263a26e16b40e31a9d55a9c 100644 (file)
@@ -1,22 +1,11 @@
-/***********************************************************************************[SolverTypes.h]
+/*****************************************************************************
 MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+glucose -- Gilles Audemard, Laurent Simon (2008)
 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.
-**************************************************************************************************/
+Original code by MiniSat and glucose authors are under an MIT licence.
+Modifications for CryptoMiniSat are under GPLv3 licence.
+******************************************************************************/
 
 #ifndef CLAUSE_H
 #define CLAUSE_H
@@ -30,54 +19,77 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
 #include <cstdio>
 #include <vector>
 #include <sys/types.h>
-#include "Vec.h"
+#include <string.h>
+
 #include "SolverTypes.h"
-#include "PackedRow.h"
 #include "constants.h"
-#include "ClauseAllocator.h"
+#include "Watched.h"
+#include "Alg.h"
+#include "constants.h"
 
 template <class T>
 uint32_t calcAbstraction(const T& ps) {
     uint32_t abstraction = 0;
     for (uint32_t i = 0; i != ps.size(); i++)
-        abstraction |= 1 << (ps[i].toInt() & 31);
+        abstraction |= 1 << (ps[i].var() & 31);
     return abstraction;
 }
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 //=================================================================================================
 // Clause -- a simple class for representing a clause:
 
 class MatrixFinder;
+class ClauseAllocator;
+
+/**
+@brief Holds a clause. Does not allocate space for literals
 
-class Clause
+Literals are allocated by an external allocator that allocates enough space
+for the class that it can hold the literals as well. I.e. it malloc()-s
+    sizeof(Clause)+LENGHT*sizeof(Lit)
+to hold the clause.
+*/
+struct Clause
 {
 protected:
-    
+
+    uint32_t isLearnt:1; ///<Is the clause a learnt clause?
+    uint32_t strenghtened:1; ///<Has the clause been strenghtened since last SatELite-like work?
+    /**
+    @brief Is the XOR equal to 1 or 0?
+
+    i.e. "a + b" = TRUE or FALSE? -- we only have variables inside xor clauses,
+    so this is important to know
+
+    NOTE: ONLY set if the clause is an xor clause.
+    */
+    uint32_t isXorEqualFalse:1;
+    uint32_t isXorClause:1; ///< Is the clause an XOR clause?
+    uint32_t isRemoved:1; ///<Is this clause queued for removal because of usless binary removal?
+    uint32_t isFreed:1; ///<Has this clause been marked as freed by the ClauseAllocator ?
+    uint32_t glue:MAX_GLUE_BITS;    ///<Clause glue -- clause activity according to GLUCOSE
+    uint32_t mySize:19; ///<The current size of the clause
+
+    float miniSatAct; ///<Clause activity according to MiniSat
+
+    uint32_t abst; //Abstraction of clause
+
     #ifdef STATS_NEEDED
-    uint group;
+    uint32_t 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 isRemoved:1;
-    uint32_t isFreed:1;
-    uint32_t wasBinInternal:1;
-    uint32_t mySize:20;
-    
-    union  {uint32_t act; uint32_t abst;} extra;
-    float oldActivityInter;
+
     #ifdef _MSC_VER
     Lit     data[1];
     #else
+    /**
+    @brief Stores the literals in the clause
+
+    This is the reason why we cannot have an instance of this class as it is:
+    it cannot hold any literals in that case! This is a trick so that the
+    literals are at the same place as the data of the clause, i.e. its size,
+    glue, etc. We allocate therefore the clause manually, taking care that
+    there is enough space for data[] to hold the literals
+    */
     Lit     data[0];
     #endif //_MSC_VER
 
@@ -85,166 +97,167 @@ protected:
 public:
 #endif //_MSC_VER
     template<class V>
-    Clause(const V& ps, const uint _group, const bool learnt)
+    Clause(const V& ps, const uint32_t _group, const bool learnt)
     {
-        wasBinInternal = (ps.size() == 2);
         isFreed = false;
         isXorClause = false;
-        strenghtened = false;
-        sorted = false;
-        varChanged = true;
-        subsume0Done = false;
+        assert(ps.size() > 2);
         mySize = ps.size();
         isLearnt = learnt;
         isRemoved = false;
         setGroup(_group);
 
         memcpy(data, ps.getData(), ps.size()*sizeof(Lit));
-        if (learnt) {
-            extra.act = 0;
-            oldActivityInter = 0;
-        } else
-            calcAbstractionClause();
+        miniSatAct = 0;
+        setStrenghtened();
     }
 
 public:
     friend class ClauseAllocator;
 
-    const uint   size        ()      const {
+    const uint32_t size() const
+    {
         return mySize;
     }
-    void         resize      (const uint size) {
-        mySize = size;
-    }
-    void         shrink      (const uint i) {
+
+    void shrink (const uint32_t i)
+    {
         assert(i <= size());
         mySize -= i;
+        if (i > 0) setStrenghtened();
     }
-    void         pop         () {
+
+    void pop()
+    {
         shrink(1);
     }
-    const bool   isXor       () {
+
+    const bool isXor()
+    {
         return isXorClause;
     }
-    const bool   learnt      ()      const {
+
+    const bool learnt() const
+    {
         return isLearnt;
     }
-    float&       oldActivity    () {
-        return oldActivityInter;
+
+    float& getMiniSatAct()
+    {
+        return miniSatAct;
     }
-    
-    const float&       oldActivity    () const {
-        return oldActivityInter;
+
+    void setMiniSatAct(const float newMiniSatAct)
+    {
+        miniSatAct = newMiniSatAct;
+    }
+
+    const float& getMiniSatAct() const
+    {
+        return miniSatAct;
     }
-    
-    const bool getStrenghtened() const {
+
+    const bool getStrenghtened() const
+    {
         return strenghtened;
     }
-    void setStrenghtened() {
+
+    void setStrenghtened()
+    {
         strenghtened = true;
-        sorted = false;
-        subsume0Done = false;
+        calcAbstractionClause();
     }
-    void unsetStrenghtened() {
+
+    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) {
+    Lit& operator [] (uint32_t i)
+    {
         return data[i];
     }
-    const Lit& operator [] (uint32_t i) const {
+
+    const Lit& operator [] (uint32_t i) const
+    {
         return data[i];
     }
 
-    void setActivity(uint32_t i)  {
-        extra.act = i;
+    void setGlue(const uint32_t newGlue)
+    {
+        assert(newGlue <= MAX_THEORETICAL_GLUE);
+        glue = newGlue;
     }
-    
-    const uint32_t&   activity   () const {
-        return extra.act;
+
+    const uint32_t getGlue() const
+    {
+        return glue;
     }
-    
-    void makeNonLearnt()  {
+
+    void makeNonLearnt()
+    {
         assert(isLearnt);
         isLearnt = false;
-        calcAbstractionClause();
     }
-    
-    void makeLearnt(const uint32_t newActivity)  {
-        extra.act = newActivity;
-        oldActivityInter = 0;
+
+    void makeLearnt(const uint32_t newGlue, const float newMiniSatAct)
+    {
+        glue = newGlue;
+        miniSatAct = newMiniSatAct;
         isLearnt = true;
     }
-    
-    inline void  strengthen(const Lit p)
+
+    inline void strengthen(const Lit p)
     {
         remove(*this, p);
-        sorted = false;
-        calcAbstractionClause();
+        setStrenghtened();
     }
-    
-    void calcAbstractionClause() {
-        assert(!learnt());
-        extra.abst = calcAbstraction(*this);;
+
+    void calcAbstractionClause()
+    {
+        abst = calcAbstraction(*this);
     }
-    
+
     uint32_t getAbst()
     {
-        if (learnt())
-            return calcAbstraction(*this);
-        else
-            return extra.abst;
+        return abst;
     }
 
-    const Lit*     getData     () const {
+    const Lit* getData() const
+    {
         return data;
     }
-    Lit*    getData     () {
+
+    Lit* getData()
+    {
         return data;
     }
-    const Lit*     getDataEnd     () const {
+
+    const Lit* getDataEnd() const
+    {
         return data+size();
     }
-    Lit*    getDataEnd     () {
+
+    Lit* getDataEnd()
+    {
         return data+size();
     }
-    void print(FILE* to = stdout) {
+
+    void print(FILE* to = stdout) const
+    {
         plainPrint(to);
-        fprintf(to, "c clause learnt %s group %d act %d oldAct %f\n", (learnt() ? "yes" : "no"), getGroup(), activity(), oldActivity());
+        fprintf(to, "c clause learnt %s glue %d miniSatAct %.3f group %d\n", (learnt() ? "yes" : "no"), getGlue(), getMiniSatAct(), getGroup());
     }
-    void plainPrint(FILE* to = stdout) const {
-        for (uint i = 0; i < size(); i++) {
+
+    void plainPrint(FILE* to = stdout) const
+    {
+        for (uint32_t 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
     {
@@ -255,7 +268,7 @@ public:
         group = _group;
     }
     #else
-    const uint getGroup() const
+    const uint32_t getGroup() const
     {
         return 0;
     }
@@ -264,92 +277,104 @@ public:
         return;
     }
     #endif //STATS_NEEDED
-    void setRemoved() {
+    void setRemoved()
+    {
         isRemoved = true;
     }
 
-    const bool removed() const {
+    const bool getRemoved() const
+    {
         return isRemoved;
     }
 
-    void setFreed() {
+    void setFreed()
+    {
         isFreed = true;
     }
 
-    const bool freed() const {
+    const bool getFreed() const
+    {
         return isFreed;
     }
 
-    const bool wasBin() const {
-        return wasBinInternal;
-    }
-
-    void setWasBin(const bool toSet) {
-        wasBinInternal = toSet;
+    void takeMaxOfStats(Clause& other)
+    {
+        if (other.getGlue() < getGlue())
+            setGlue(other.getGlue());
+        if (other.getMiniSatAct() > getMiniSatAct())
+            setMiniSatAct(other.getMiniSatAct());
     }
 };
 
+/**
+@brief Holds an xor clause. Similarly to Clause, it cannot be directly used
+
+The space is not allocated for the literals. See Clause for details
+*/
 class XorClause : public Clause
 {
 protected:
     // NOTE: This constructor cannot be used directly (doesn't allocate enough memory).
     template<class V>
-    XorClause(const V& ps, const bool inverted, const uint _group) :
+    XorClause(const V& ps, const bool xorEqualFalse, const uint32_t _group) :
         Clause(ps, _group, false)
     {
-        invertedXor = inverted;
+        isXorEqualFalse = xorEqualFalse;
         isXorClause = true;
-        calcXorAbstraction();
     }
 
 public:
     friend class ClauseAllocator;
 
-    inline bool xor_clause_inverted() const
+    inline const bool xorEqualFalse() const
     {
-        return invertedXor;
+        return isXorEqualFalse;
     }
-    inline void invert(bool b)
+
+    inline void invert(const bool b)
     {
-        invertedXor ^= b;
-    }
-    void calcXorAbstraction() {
-        extra.abst = 0;
-        for (uint32_t i = 0; i != size(); i++)
-            extra.abst |= 1 << (data[i].var() & 31);
+        isXorEqualFalse ^= b;
     }
 
-    void print() {
-        printf("XOR Clause   group: %d, size: %d, learnt:%d, lits:\"", getGroup(), size(), learnt());
-        plainPrint();
+    void print(FILE* to = stdout) const
+    {
+        plainPrint(to);
+        fprintf(to, "c clause learnt %s glue %d miniSatAct %.3f group %d\n", (learnt() ? "yes" : "no"), getGlue(), getMiniSatAct(), getGroup());
     }
-    
-    void plainPrint(FILE* to = stdout) const {
+
+    void plainPrint(FILE* to = stdout) const
+    {
         fprintf(to, "x");
-        if (xor_clause_inverted())
-            printf("-");
-        for (uint i = 0; i < size(); i++) {
+        if (xorEqualFalse())
+            fprintf(to, "-");
+        for (uint32_t i = 0; i < size(); i++) {
             fprintf(to, "%d ", data[i].var() + 1);
         }
         fprintf(to, "0\n");
     }
-    
+
     friend class MatrixFinder;
 };
 
-class WatchedBin {
-    public:
-        WatchedBin(Lit _impliedLit) : impliedLit(_impliedLit) {};
-        Lit impliedLit;
-};
+inline std::ostream& operator<<(std::ostream& cout, const Clause& cl)
+{
+    for (uint32_t i = 0; i < cl.size(); i++) {
+        cout << cl[i] << " ";
+    }
+    return cout;
+}
 
-class Watched {
-    public:
-        Watched(ClauseOffset _clause, Lit _blockedLit) : clause(_clause), blockedLit(_blockedLit) {};
-        ClauseOffset clause;
-        Lit blockedLit;
-};
+inline std::ostream& operator<<(std::ostream& cout, const XorClause& cl)
+{
+    cout << "x";
+    for (uint32_t i = 0; i < cl.size(); i++) {
+        cout << cl[i].var() + 1 << " ";
+    }
+    if (cl.xorEqualFalse()) cout << " =  false";
+    else cout << " = true";
+
+    return cout;
+}
 
-}; //NAMESPACE MINISAT
 
 #endif //CLAUSE_H
index 99bfaed636c3e80beca336a80402dadf938c5e99..b1d58d86cfc0ee6a65fb7c8bca2449c34f5f2e4c 100644 (file)
@@ -28,42 +28,64 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "XorSubsumer.h"
 //#include "VarReplacer.h"
 #include "PartHandler.h"
+#include "Gaussian.h"
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
+//For mild debug info:
 //#define DEBUG_CLAUSEALLOCATOR
 
-ClauseAllocator::ClauseAllocator() :
-    clausePoolBin(sizeof(Clause) + 2*sizeof(Lit))
-{}
+//For listing each and every clause location:
+//#define DEBUG_CLAUSEALLOCATOR2
+
+#define MIN_LIST_SIZE (300000 * (sizeof(Clause) + 4*sizeof(Lit))/sizeof(uint32_t))
+//#define MIN_LIST_SIZE (100 * (sizeof(Clause) + 4*sizeof(Lit))/sizeof(uint32_t))
+#define ALLOC_GROW_MULT 4
+//We shift stuff around in Watched, so not all of 32 bits are useable.
+#define EFFECTIVELY_USEABLE_BITS 30
+#define MAXSIZE ((1 << (EFFECTIVELY_USEABLE_BITS-NUM_BITS_OUTER_OFFSET))-1)
+
+ClauseAllocator::ClauseAllocator()
+{
+    assert(MIN_LIST_SIZE < MAXSIZE);
+    assert(sizeof(Clause) + 2*sizeof(Lit) > sizeof(NewPointerAndOffset));
+}
 
+/**
+@brief Frees all stacks
+*/
 ClauseAllocator::~ClauseAllocator()
 {
     for (uint32_t i = 0; i < dataStarts.size(); i++) {
-        free(dataStarts[i]);
+        delete [] dataStarts[i];
     }
 }
 
+/**
+@brief Allocates space&initializes a clause
+*/
 template<class T>
 Clause* ClauseAllocator::Clause_new(const T& ps, const unsigned int group, const bool learnt)
 {
+    assert(ps.size() > 2);
     void* mem = allocEnough(ps.size());
     Clause* real= new (mem) Clause(ps, group, learnt);
     //assert(!(ps.size() == 2 && !real->wasBin()));
 
     return real;
 }
+
 template Clause* ClauseAllocator::Clause_new(const vec<Lit>& ps, const unsigned int group, const bool learnt);
 template Clause* ClauseAllocator::Clause_new(const Clause& ps, const unsigned int group, const bool learnt);
 template Clause* ClauseAllocator::Clause_new(const XorClause& ps, const unsigned int group, const bool learnt);
 
+/**
+@brief Allocates space&initializes an xor clause
+*/
 template<class T>
-XorClause* ClauseAllocator::XorClause_new(const T& ps, const bool inverted, const unsigned int group)
+XorClause* ClauseAllocator::XorClause_new(const T& ps, const bool xorEqualFalse, const unsigned int group)
 {
+    assert(ps.size() > 0);
     void* mem = allocEnough(ps.size());
-    XorClause* real= new (mem) XorClause(ps, inverted, group);
+    XorClause* real= new (mem) XorClause(ps, xorEqualFalse, group);
     //assert(!(ps.size() == 2 && !real->wasBin()));
 
     return real;
@@ -71,19 +93,25 @@ XorClause* ClauseAllocator::XorClause_new(const T& ps, const bool inverted, cons
 template XorClause* ClauseAllocator::XorClause_new(const vec<Lit>& ps, const bool inverted, const unsigned int group);
 template XorClause* ClauseAllocator::XorClause_new(const XorClause& ps, const bool inverted, const unsigned int group);
 
+/**
+@brief Allocates space for a new clause & copies a give clause to it
+*/
 Clause* ClauseAllocator::Clause_new(Clause& c)
 {
+    assert(c.size() > 2);
     void* mem = allocEnough(c.size());
     memcpy(mem, &c, sizeof(Clause)+sizeof(Lit)*c.size());
     Clause& c2 = *(Clause*)mem;
-    c2.setWasBin(c.size() == 2);
-    //assert(!(c.size() == 2 && !c2.wasBin()));
-    
+
     return &c2;
 }
 
-#define MIN_LIST_SIZE (300000 * (sizeof(Clause) + 4*sizeof(Lit)))
+/**
+@brief Allocates enough space for a new clause
 
+It tries to add the clause to the end of any already created stacks
+if that is impossible, it creates a new stack, and adds the clause there
+*/
 void* ClauseAllocator::allocEnough(const uint32_t size)
 {
     assert(sizes.size() == dataStarts.size());
@@ -93,11 +121,13 @@ void* ClauseAllocator::allocEnough(const uint32_t size)
     assert(sizeof(Clause)%sizeof(uint32_t) == 0);
     assert(sizeof(Lit)%sizeof(uint32_t) == 0);
 
-    if (size == 2) {
-        return clausePoolBin.malloc();
+    if (dataStarts.size() == (1<<NUM_BITS_OUTER_OFFSET)) {
+        std::cerr << "Memory manager cannot handle the load. Sorry. Exiting." << std::endl;
+        exit(-1);
     }
-    
-    uint32_t needed = sizeof(Clause)+sizeof(Lit)*size;
+    assert(size > 2);
+
+    uint32_t needed = (sizeof(Clause)+sizeof(Lit)*size)/sizeof(uint32_t);
     bool found = false;
     uint32_t which = std::numeric_limits<uint32_t>::max();
     for (uint32_t i = 0; i < sizes.size(); i++) {
@@ -109,27 +139,32 @@ void* ClauseAllocator::allocEnough(const uint32_t size)
     }
 
     if (!found) {
-        #ifdef DEBUG_CLAUSEALLOCATOR
-        std::cout << "c New list in ClauseAllocator" << std::endl;
-        #endif //DEBUG_CLAUSEALLOCATOR
-        
         uint32_t nextSize; //number of BYTES to allocate
-        if (maxSizes.size() != 0)
-            nextSize = maxSizes[maxSizes.size()-1]*3*sizeof(uint32_t);
-        else
-            nextSize = MIN_LIST_SIZE;
+        if (maxSizes.size() != 0) {
+            nextSize = std::min((uint32_t)(maxSizes[maxSizes.size()-1]*ALLOC_GROW_MULT), (uint32_t)MAXSIZE);
+            nextSize = std::max(nextSize, (uint32_t)MIN_LIST_SIZE*2);
+        } else {
+            nextSize = (uint32_t)MIN_LIST_SIZE;
+        }
         assert(needed <  nextSize);
-        
-        uint32_t *dataStart = (uint32_t*)malloc(nextSize);
+        assert(nextSize <= MAXSIZE);
+
+        #ifdef DEBUG_CLAUSEALLOCATOR
+        std::cout << "c New list in ClauseAllocator. Size: " << nextSize
+        << " (maxSize: " << MAXSIZE
+        << ")" << std::endl;
+        #endif //DEBUG_CLAUSEALLOCATOR
+
+        uint32_t *dataStart = new uint32_t[nextSize];
         assert(dataStart != NULL);
         dataStarts.push(dataStart);
         sizes.push(0);
-        maxSizes.push(nextSize/sizeof(uint32_t));
+        maxSizes.push(nextSize);
         origClauseSizes.push();
-        currentlyUsedSize.push(0);
+        currentlyUsedSizes.push(0);
         which = dataStarts.size()-1;
     }
-    #ifdef DEBUG_CLAUSEALLOCATOR
+    #ifdef DEBUG_CLAUSEALLOCATOR2
     std::cout
     << "selected list = " << which
     << " size = " << sizes[which]
@@ -139,13 +174,19 @@ void* ClauseAllocator::allocEnough(const uint32_t size)
 
     assert(which != std::numeric_limits<uint32_t>::max());
     Clause* pointer = (Clause*)(dataStarts[which] + sizes[which]);
-    sizes[which] += needed/sizeof(uint32_t);
-    currentlyUsedSize[which] += needed/sizeof(uint32_t);
-    origClauseSizes[which].push(needed/sizeof(uint32_t));
+    sizes[which] += needed;
+    currentlyUsedSizes[which] += needed;
+    origClauseSizes[which].push(needed);
 
     return pointer;
 }
 
+/**
+@brief Given the pointer of the clause it finds a 32-bit offset for it
+
+Calculates the stack frame and the position of the pointer in the stack, and
+rerturns a 32-bit value that is a concatenation of these two
+*/
 const ClauseOffset ClauseAllocator::getOffset(const Clause* ptr) const
 {
     uint32_t outerOffset = getOuterOffset(ptr);
@@ -153,56 +194,80 @@ const ClauseOffset ClauseAllocator::getOffset(const Clause* ptr) const
     return combineOuterInterOffsets(outerOffset, interOffset);
 }
 
+/**
+@brief Combines the stack number and the internal offset into one 32-bit number
+*/
 inline const ClauseOffset ClauseAllocator::combineOuterInterOffsets(const uint32_t outerOffset, const uint32_t interOffset) const
 {
-    return (outerOffset | (interOffset<<4));
+    return (outerOffset | (interOffset << NUM_BITS_OUTER_OFFSET));
 }
 
+/**
+@brief Given a pointer, finds which stack it's in
+*/
 inline uint32_t ClauseAllocator::getOuterOffset(const Clause* ptr) const
 {
     uint32_t which = std::numeric_limits<uint32_t>::max();
     for (uint32_t i = 0; i < sizes.size(); i++) {
-        if ((uint32_t*)ptr >= dataStarts[i] && (uint32_t*)ptr < dataStarts[i] + maxSizes[i])
+        if ((uint32_t*)ptr >= dataStarts[i] && (uint32_t*)ptr < dataStarts[i] + maxSizes[i]) {
             which = i;
+            break;
+        }
     }
     assert(which != std::numeric_limits<uint32_t>::max());
 
     return which;
 }
 
+/**
+@brief Given a pointer and its stack number, returns its position inside the stack
+*/
 inline uint32_t ClauseAllocator::getInterOffset(const Clause* ptr, uint32_t outerOffset) const
 {
     return ((uint32_t*)ptr - dataStarts[outerOffset]);
 }
 
+/**
+@brief Frees a clause
+
+If clause was binary, it frees it in quite a normal way. If it isn't, then it
+needs to set the data in the Clause that it has been freed, and updates the
+stack it belongs to such that the stack can now that its effectively used size
+is smaller
+
+NOTE: The size of claues can change. Therefore, currentlyUsedSizes can in fact
+be incorrect, since it was incremented by the ORIGINAL size of the clause, but
+when the clause is "freed", it is decremented by the POTENTIALLY SMALLER size
+of the clause. Therefore, the "currentlyUsedSizes" is an overestimation!!
+*/
 void ClauseAllocator::clauseFree(Clause* c)
 {
-    if (c->wasBin()) {
-        clausePoolBin.free(c);
-    } else {
-        c->setFreed();
-        uint32_t outerOffset = getOuterOffset(c);
-        //uint32_t interOffset = getInterOffset(c, outerOffset);
-        currentlyUsedSize[outerOffset] -= (sizeof(Clause) + c->size()*sizeof(Lit))/sizeof(uint32_t);
-        //above should be
-        //origClauseSizes[outerOffset][interOffset]
-        //but it cannot be :(
-    }
+    assert(!c->getFreed());
+    c->setFreed();
+    uint32_t outerOffset = getOuterOffset(c);
+    //uint32_t interOffset = getInterOffset(c, outerOffset);
+    currentlyUsedSizes[outerOffset] -= (sizeof(Clause) + c->size()*sizeof(Lit))/sizeof(uint32_t);
+    //above should be
+    //origClauseSizes[outerOffset][interOffset]
+    //but it cannot be :(
 }
 
-struct NewPointerAndOffset {
-    Clause* newPointer;
-    uint32_t newOffset;
-};
+/**
+@brief If needed, compacts stacks, removing unused clauses
 
+Firstly, the algorithm determines if the number of useless slots is large or
+small compared to the problem size. If it is small, it does nothing. If it is
+large, then it allocates new stacks, copies the non-freed clauses to these new
+stacks, updates all pointers and offsets, and frees the original stacks.
+*/
 void ClauseAllocator::consolidate(Solver* solver)
 {
     double myTime = cpuTime();
-    
+
     //if (dataStarts.size() > 2) {
     uint32_t sum = 0;
     for (uint32_t i = 0; i < sizes.size(); i++) {
-        sum += currentlyUsedSize[i];
+        sum += currentlyUsedSizes[i];
     }
     uint32_t sumAlloc = 0;
     for (uint32_t i = 0; i < sizes.size(); i++) {
@@ -212,166 +277,232 @@ void ClauseAllocator::consolidate(Solver* solver)
     #ifdef DEBUG_CLAUSEALLOCATOR
     std::cout << "c ratio:" << (double)sum/(double)sumAlloc << std::endl;
     #endif //DEBUG_CLAUSEALLOCATOR
-    
-    if ((double)sum/(double)sumAlloc > 0.7 /*&& sum > 10000000*/) {
-        if (solver->verbosity >= 2) {
+
+    //If re-allocation is not really neccessary, don't do it
+    //Neccesities:
+    //1) There is too much memory allocated. Re-allocation will save space
+    //   Avoiding segfault (max is 16 outerOffsets, more than 10 is near)
+    //2) There is too much empty, unused space (>30%)
+    if ((double)sum/(double)sumAlloc > 0.7 && sizes.size() < 10) {
+        if (solver->conf.verbosity >= 3) {
             std::cout << "c Not consolidating memory." << std::endl;
         }
         return;
     }
 
-    
-    uint32_t newMaxSize = std::max(sum*2*sizeof(uint32_t), MIN_LIST_SIZE);
-    uint32_t* newDataStarts = (uint32_t*)malloc(newMaxSize);
-    newMaxSize /= sizeof(uint32_t);
-    uint32_t newSize = 0;
-    vec<uint32_t> newOrigClauseSizes;
-    //}
-
-    map<Clause*, Clause*> oldToNewPointer;
-    map<uint32_t, uint32_t> oldToNewOffset;
-    
-    uint32_t* newDataStartsPointer = newDataStarts;
-    for (uint32_t i = 0; i < dataStarts.size(); i++) {
-        uint32_t currentLoc = 0;
-        for (uint32_t i2 = 0; i2 < origClauseSizes[i].size(); i2++) {
-            Clause* oldPointer = (Clause*)(dataStarts[i] + currentLoc);
-            if (!oldPointer->freed()) {
-                uint32_t sizeNeeded = sizeof(Clause) + oldPointer->size()*sizeof(Lit);
-                memcpy(newDataStartsPointer, dataStarts[i] + currentLoc, sizeNeeded);
-                
-                oldToNewPointer[oldPointer] = (Clause*)newDataStartsPointer;
-                oldToNewOffset[combineOuterInterOffsets(i, currentLoc)] = combineOuterInterOffsets(0, newSize);
-
-                newSize += sizeNeeded/sizeof(uint32_t);
-                newOrigClauseSizes.push(sizeNeeded/sizeof(uint32_t));
-                newDataStartsPointer += sizeNeeded/sizeof(uint32_t);
-            }
-            
-            currentLoc += origClauseSizes[i][i2];
+    #ifdef DEBUG_CLAUSEALLOCATOR
+    std::cout << "c ------ Consolidating Memory ------------" << std::endl;
+    #endif //DEBUG_CLAUSEALLOCATOR
+    int64_t newMaxSizeNeed = (double)sum*1.2 + MIN_LIST_SIZE;
+    #ifdef DEBUG_CLAUSEALLOCATOR
+    std::cout << "c newMaxSizeNeed = " << newMaxSizeNeed << std::endl;
+    #endif //DEBUG_CLAUSEALLOCATOR
+    vec<uint32_t> newMaxSizes;
+    for (uint32_t i = 0; i < (1 << NUM_BITS_OUTER_OFFSET); i++) {
+        if (newMaxSizeNeed <= 0) break;
+
+        uint32_t thisMaxSize = std::min(newMaxSizeNeed, (int64_t)MAXSIZE);
+        if (i == 0) {
+            thisMaxSize = std::max(thisMaxSize, (uint32_t)MIN_LIST_SIZE);
+        } else {
+            assert(i > 0);
+            thisMaxSize = std::max(thisMaxSize, newMaxSizes[i-1]/2);
+            thisMaxSize = std::max(thisMaxSize, (uint32_t)MIN_LIST_SIZE*2);
         }
+        newMaxSizeNeed -= thisMaxSize;
+        assert(thisMaxSize <= MAXSIZE);
+        newMaxSizes.push(thisMaxSize);
+        //because the clauses don't always fit
+        //it might occur that there is enough place in total
+        //but the very last clause would need to be fragmented
+        //over multiple lists' ends :O
+        //So this "magic" constant could take care of that....
+        //or maybe not (if _very_ large clauses are used, always
+        //bad chance, etc. :O )
+        //NOTE: the + MIN_LIST_SIZE should take care of this above at
+        // newMaxSizeNeed = sum + MIN_LIST_SIZE;
+        #ifdef DEBUG_CLAUSEALLOCATOR
+        std::cout << "c NEW MaxSizes:" << newMaxSizes[i] << std::endl;
+        #endif //DEBUG_CLAUSEALLOCATOR
     }
-    assert(newSize < newMaxSize);
-    assert(newSize <= newMaxSize/2);
-
-    updateOffsets(solver->watches, oldToNewOffset);
-    updateOffsetsXor(solver->xorwatches, oldToNewOffset);
-
-    updatePointers(solver->clauses, oldToNewPointer);
-    updatePointers(solver->learnts, oldToNewPointer);
-    updatePointers(solver->binaryClauses, oldToNewPointer);
-    updatePointers(solver->xorclauses, oldToNewPointer);
+    #ifdef DEBUG_CLAUSEALLOCATOR
+    std::cout << "c ------------------" << std::endl;
+    #endif //DEBUG_CLAUSEALLOCATOR
 
-    //No need to update varreplacer, since it only stores binary clauses that
-    //must have been allocated such as to use the pool
-    //updatePointers(solver->varReplacer->clauses, oldToNewPointer);
-    updatePointers(solver->partHandler->clausesRemoved, oldToNewPointer);
-    updatePointers(solver->partHandler->xorClausesRemoved, oldToNewPointer);
-    for(map<Var, vector<Clause*> >::iterator it = solver->subsumer->elimedOutVar.begin(); it != solver->subsumer->elimedOutVar.end(); it++) {
-        updatePointers(it->second, oldToNewPointer);
+    if (newMaxSizeNeed > 0) {
+        std::cerr << "We cannot handle the memory need load. Exiting." << std::endl;
+        exit(-1);
     }
-    for(map<Var, vector<XorClause*> >::iterator it = solver->xorSubsumer->elimedOutVar.begin(); it != solver->xorSubsumer->elimedOutVar.end(); it++) {
-        updatePointers(it->second, oldToNewPointer);
+
+    vec<uint32_t> newSizes;
+    vec<vec<uint32_t> > newOrigClauseSizes;
+    vec<uint32_t*> newDataStartsPointers;
+    vec<uint32_t*> newDataStarts;
+    for (uint32_t i = 0; i < newMaxSizes.size(); i++) {
+        newSizes.push(0);
+        newOrigClauseSizes.push();
+        uint32_t* pointer;
+        pointer = new uint32_t[newMaxSizes[i]];
+        newDataStartsPointers.push(pointer);
+        newDataStarts.push(pointer);
     }
-    
-
-    vec<PropagatedFrom>& reason = solver->reason;
-    for (PropagatedFrom *it = reason.getData(), *end = reason.getDataEnd(); it != end; it++) {
-        if (!it->isBinary() && !it->isNULL()) {
-            /*if ((it == reason.getData() + (*it->getClause())[0].var())
-                && (solver->value((*it->getClause())[0]) == l_True)) {
-                assert(oldToNewPointer.find(it->getClause()) != oldToNewPointer.end());
-                *it = PropagatedFrom(oldToNewPointer[it->getClause()]);
+
+    uint32_t outerPart = 0;
+    for (uint32_t i = 0; i < dataStarts.size(); i++) {
+        uint32_t currentLoc = 0;
+        for (uint32_t i2 = 0; i2 < origClauseSizes[i].size(); i2++) {
+            Clause* oldPointer = (Clause*)(dataStarts[i] + currentLoc);
+            if (!oldPointer->getFreed()) {
+                uint32_t sizeNeeded = (sizeof(Clause) + oldPointer->size()*sizeof(Lit))/sizeof(uint32_t);
+
+                //Next line is needed, because in case of isRemoved()
+                //, the size of the clause could become 0, thus having less
+                // than enough space to carry the NewPointerAndOffset info
+                sizeNeeded = std::max(sizeNeeded, (uint32_t)((sizeof(Clause) + 2*sizeof(Lit))/sizeof(uint32_t)));
+
+                if (newSizes[outerPart] + sizeNeeded > newMaxSizes[outerPart]) {
+                    outerPart++;
+                    assert(outerPart < newMaxSizes.size());
+                }
+                memcpy(newDataStartsPointers[outerPart], dataStarts[i] + currentLoc, sizeNeeded*sizeof(uint32_t));
+
+                (*((NewPointerAndOffset*)(dataStarts[i] + currentLoc))).newOffset = combineOuterInterOffsets(outerPart, newSizes[outerPart]);
+                (*((NewPointerAndOffset*)(dataStarts[i] + currentLoc))).newPointer = (Clause*)newDataStartsPointers[outerPart];
+
+                newSizes[outerPart] += sizeNeeded;
+                newOrigClauseSizes[outerPart].push(sizeNeeded);
+                newDataStartsPointers[outerPart] += sizeNeeded;
             } else {
-                *it = PropagatedFrom();
-            }*/
-            if (oldToNewPointer.find(it->getClause()) != oldToNewPointer.end()) {
-                *it = PropagatedFrom(oldToNewPointer[it->getClause()]);
+                (*((NewPointerAndOffset*)(dataStarts[i] + currentLoc))).newOffset = std::numeric_limits<uint32_t>::max();
             }
+
+            currentLoc += origClauseSizes[i][i2];
         }
     }
 
+    updateAllOffsetsAndPointers(solver);
+
     for (uint32_t i = 0; i < dataStarts.size(); i++)
-        free(dataStarts[i]);
+        delete [] dataStarts[i];
 
     dataStarts.clear();
     maxSizes.clear();
     sizes.clear();
     origClauseSizes.clear();
-
-    dataStarts.push(newDataStarts);
-    maxSizes.push(newMaxSize);
-    sizes.push(newSize);
-    currentlyUsedSize.clear();
-    currentlyUsedSize.push(newSize);
+    currentlyUsedSizes.clear();
     origClauseSizes.clear();
-    origClauseSizes.push();
-    newOrigClauseSizes.moveTo(origClauseSizes[0]);
 
-    if (solver->verbosity >= 1) {
+    for (uint32_t i = 0; i < newMaxSizes.size(); i++) {
+        dataStarts.push(newDataStarts[i]);
+        maxSizes.push(newMaxSizes[i]);
+        sizes.push(newSizes[i]);
+        currentlyUsedSizes.push(newSizes[i]);
+    }
+    newOrigClauseSizes.moveTo(origClauseSizes);
+
+    if (solver->conf.verbosity >= 3) {
         std::cout << "c Consolidated memory. Time: "
         << cpuTime() - myTime << std::endl;
     }
 }
 
-template<class T>
-void ClauseAllocator::updateOffsets(vec<vec<T> >& watches, const map<ClauseOffset, ClauseOffset>& oldToNewOffset)
+void ClauseAllocator::updateAllOffsetsAndPointers(Solver* solver)
 {
-    for (uint32_t i = 0;  i < watches.size(); i++) {
-        vec<T>& list = watches[i];
-        for (T *it = list.getData(), *end = list.getDataEnd(); it != end; it++) {
-            map<ClauseOffset, ClauseOffset>::const_iterator it2 = oldToNewOffset.find(it->clause);
-            assert(it2 != oldToNewOffset.end());
-            it->clause = it2->second;
+    updateOffsets(solver->watches);
+
+    updatePointers(solver->clauses);
+    updatePointers(solver->learnts);
+    updatePointers(solver->xorclauses);
+    updatePointers(solver->freeLater);
+    updatePointers(solver->unWindGlue);
+
+    //No need to update varreplacer, since it only stores binary clauses that
+    //must have been allocated such as to use the pool
+    //updatePointers(solver->varReplacer->clauses, oldToNewPointer);
+    updatePointers(solver->partHandler->clausesRemoved);
+    updatePointers(solver->partHandler->xorClausesRemoved);
+
+    #ifdef USE_GAUSS
+    for (uint32_t i = 0; i < solver->gauss_matrixes.size(); i++) {
+        updatePointers(solver->gauss_matrixes[i]->xorclauses);
+        updatePointers(solver->gauss_matrixes[i]->clauses_toclear);
+    }
+    #endif //USE_GAUSS
+
+    vec<PropBy>& reason = solver->reason;
+    Var var = 0;
+    for (PropBy *it = reason.getData(), *end = reason.getDataEnd(); it != end; it++, var++) {
+        if ((uint32_t)solver->level[var] > solver->decisionLevel()
+            || solver->level[var] == 0
+            || solver->value(var) == l_Undef) {
+            *it = PropBy();
+            continue;
+        }
+
+        if (it->isClause() && !it->isNULL()) {
+            assert(((NewPointerAndOffset*)(getPointer(it->getClause())))->newOffset != std::numeric_limits<uint32_t>::max());
+            *it = PropBy(((NewPointerAndOffset*)(getPointer(it->getClause())))->newOffset);
         }
     }
 }
 
-template<class T>
-void ClauseAllocator::updateOffsetsXor(vec<vec<T> >& watches, const map<ClauseOffset, ClauseOffset>& oldToNewOffset)
+/**
+@brief A dumb helper function to update offsets
+*/
+void ClauseAllocator::updateOffsets(vec<vec<Watched> >& watches)
 {
     for (uint32_t i = 0;  i < watches.size(); i++) {
-        vec<T>& list = watches[i];
-        for (T *it = list.getData(), *end = list.getDataEnd(); it != end; it++) {
-            map<ClauseOffset, ClauseOffset>::const_iterator it2 = oldToNewOffset.find(*it);
-            assert(it2 != oldToNewOffset.end());
-            *it = it2->second;
+        vec<Watched>& list = watches[i];
+        for (Watched *it = list.getData(), *end = list.getDataEnd(); it != end; it++) {
+            if (!it->isClause() && !it->isXorClause()) continue;
+            if (it->isClause()) {
+                it->setNormOffset(((NewPointerAndOffset*)(getPointer(it->getNormOffset())))->newOffset);
+            } else {
+                it->setXorOffset(((NewPointerAndOffset*)(getPointer(it->getXorOffset())))->newOffset);
+            }
         }
     }
 }
 
+/**
+@brief A dumb helper function to update pointers
+*/
 template<class T>
-void ClauseAllocator::updatePointers(vec<T*>& toUpdate, const map<Clause*, Clause*>& oldToNewPointer)
+void ClauseAllocator::updatePointers(vec<T*>& toUpdate)
 {
     for (T **it = toUpdate.getData(), **end = toUpdate.getDataEnd(); it != end; it++) {
-        if (!(*it)->wasBin()) {
-            //assert(oldToNewPointer.find((TT*)*it) != oldToNewPointer.end());
-            map<Clause*, Clause*>::const_iterator it2 = oldToNewPointer.find((Clause*)*it);
-            *it = (T*)it2->second;
+        if (*it != NULL) {
+            *it = (T*)(((NewPointerAndOffset*)(*it))->newPointer);
         }
     }
 }
 
-void ClauseAllocator::updatePointers(vector<Clause*>& toUpdate, const map<Clause*, Clause*>& oldToNewPointer)
+/**
+@brief A dumb helper function to update pointers
+*/
+void ClauseAllocator::updatePointers(vector<Clause*>& toUpdate)
 {
     for (vector<Clause*>::iterator it = toUpdate.begin(), end = toUpdate.end(); it != end; it++) {
-        if (!(*it)->wasBin()) {
-            //assert(oldToNewPointer.find((TT*)*it) != oldToNewPointer.end());
-            map<Clause*, Clause*>::const_iterator it2 = oldToNewPointer.find((Clause*)*it);
-            *it = it2->second;
-        }
+        *it = (((NewPointerAndOffset*)(*it))->newPointer);
     }
 }
 
-void ClauseAllocator::updatePointers(vector<XorClause*>& toUpdate, const map<Clause*, Clause*>& oldToNewPointer)
+/**
+@brief A dumb helper function to update pointers
+*/
+void ClauseAllocator::updatePointers(vector<XorClause*>& toUpdate)
 {
     for (vector<XorClause*>::iterator it = toUpdate.begin(), end = toUpdate.end(); it != end; it++) {
-        if (!(*it)->wasBin()) {
-            //assert(oldToNewPointer.find((TT*)*it) != oldToNewPointer.end());
-            map<Clause*, Clause*>::const_iterator it2 = oldToNewPointer.find((Clause*)*it);
-            *it = (XorClause*)it2->second;
-        }
+        *it = (XorClause*)(((NewPointerAndOffset*)(*it))->newPointer);
     }
 }
 
-}; //NAMESPACE MINISAT
+/**
+@brief A dumb helper function to update pointers
+*/
+void ClauseAllocator::updatePointers(vector<pair<Clause*, uint32_t> >& toUpdate)
+{
+    for (vector<pair<Clause*, uint32_t> >::iterator it = toUpdate.begin(), end = toUpdate.end(); it != end; it++) {
+        it->first = (((NewPointerAndOffset*)(it->first))->newPointer);
+    }
+}
index 4bf378a913d0d2e6c2bc9d79c01687491e81a905..69f8f07d44d54aa707b6dc0cc32601a2b885a74b 100644 (file)
@@ -24,39 +24,57 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <stdint.h>
 #endif //_MSC_VER
 
+#include <stdlib.h>
 #include "Vec.h"
-#include <boost/pool/pool.hpp>
 #include <map>
 #include <vector>
 using std::map;
 using std::vector;
 
-namespace MINISAT
-{
-using namespace MINISAT;
+#include "ClauseOffset.h"
+#include "Watched.h"
+
+#define NUM_BITS_OUTER_OFFSET 4
+
 
 class Clause;
 class XorClause;
 class Solver;
 
-typedef uint32_t ClauseOffset;
 
+/**
+@brief Allocates memory for (xor) clauses
+
+This class allocates memory in large chunks, then distributes it to clauses when
+needed. When instructed, it consolidates the unused space (i.e. clauses free()-ed).
+Essentially, it is a stack-like allocator for clauses. It is useful to have
+this, because this way, we can address clauses according to their number,
+which is 32-bit, instead of their address, which might be 64-bit
+*/
 class ClauseAllocator {
     public:
         ClauseAllocator();
         ~ClauseAllocator();
-        
+
         template<class T>
         Clause* Clause_new(const T& ps, const uint32_t group, const bool learnt = false);
         template<class T>
-        XorClause* XorClause_new(const T& ps, const bool inverted, const uint32_t group);
+        XorClause* XorClause_new(const T& ps, const bool xorEqualFalse, const uint32_t group);
         Clause* Clause_new(Clause& c);
 
         const ClauseOffset getOffset(const Clause* ptr) const;
 
-        inline Clause* getPointer(const uint32_t offset)
+        /**
+        @brief Returns the pointer of a clause given its offset
+
+        Takes the "dataStart" of the correct stack, and adds the offset,
+        returning the thus created pointer. Used a LOT in propagation, thus this
+        is very important to be fast (therefore, it is an inlined method)
+        */
+        inline Clause* getPointer(const uint32_t offset) const
         {
-            return (Clause*)(dataStarts[offset&15]+(offset>>4));
+            return (Clause*)(dataStarts[offset&((1 << NUM_BITS_OUTER_OFFSET) - 1)]
+                            +(offset >> NUM_BITS_OUTER_OFFSET));
         }
 
         void clauseFree(Clause* c);
@@ -68,29 +86,48 @@ class ClauseAllocator {
         uint32_t getInterOffset(const Clause* c, const uint32_t outerOffset) const;
         const ClauseOffset combineOuterInterOffsets(const uint32_t outerOffset, const uint32_t interOffset) const;
 
+        void updateAllOffsetsAndPointers(Solver* solver);
         template<class T>
-        void updatePointers(vec<T*>& toUpdate, const map<Clause*, Clause*>& oldToNewPointer);
-        void updatePointers(vector<Clause*>& toUpdate, const map<Clause*, Clause*>& oldToNewPointer);
-        void updatePointers(vector<XorClause*>& toUpdate, const map<Clause*, Clause*>& oldToNewPointer);
-        
-        template<class T>
-        void updateOffsets(vec<vec<T> >& watches, const map<ClauseOffset, ClauseOffset>& oldToNewOffset);
-        template<class T>
-        void updateOffsetsXor(vec<vec<T> >& watches, const map<ClauseOffset, ClauseOffset>& oldToNewOffset);
-        
-        vec<uint32_t*> dataStarts;
-        vec<size_t> sizes;
+        void updatePointers(vec<T*>& toUpdate);
+        void updatePointers(vector<Clause*>& toUpdate);
+        void updatePointers(vector<XorClause*>& toUpdate);
+        void updatePointers(vector<std::pair<Clause*, uint32_t> >& toUpdate);
+
+        void updateOffsets(vec<vec<Watched> >& watches);
+
+        vec<uint32_t*> dataStarts; ///<Stacks start at these positions
+        vec<size_t> sizes; ///<The number of 32-bit datapieces currently used in each stack
+        /**
+        @brief Clauses in the stack had this size when they were allocated
+        This my NOT be their current size: the clauses may be shrinked during
+        the running of the solver. Therefore, it is imperative that their orignal
+        size is saved. This way, we can later move clauses around.
+        */
         vec<vec<uint32_t> > origClauseSizes;
-        vec<size_t> maxSizes;
-        vec<size_t> currentlyUsedSize;
-        vec<uint32_t> origSizes;
-
-        boost::pool<> clausePoolBin;
+        vec<size_t> maxSizes; ///<The number of 32-bit datapieces allocated in each stack
+        /**
+        @brief The estimated used size of the stack
+        This is incremented by clauseSize each time a clause is allocated, and
+        decremetented by clauseSize each time a clause is deallocated. The
+        problem is, that clauses can shrink, and thus this value will be an
+        overestimation almost all the time
+        */
+        vec<size_t> currentlyUsedSizes;
 
         void* allocEnough(const uint32_t size);
-};
 
-}; //NAMESPACE MINISAT
+        /**
+        @brief The clause's data is replaced by this to aid updating
 
-#endif //CLAUSEALLOCATOR_H
+        We need to update the pointer or offset that points to the clause
+        The best way to do that is to simply fill the original place of the clause
+        with the pointer/offset of the new location.
+        */
+        struct NewPointerAndOffset
+        {
+            uint32_t newOffset; ///<The new offset where the clause now resides
+            Clause* newPointer; ///<The new place
+        };
+};
 
+#endif //CLAUSEALLOCATOR_H
index 65e01e9da821e15b8fa5d23e164640d28ea0d18b..e9ff0509493d266c4ac16a9bcb0896e005ece021 100644 (file)
@@ -1,4 +1,4 @@
-/***********************************************************************************
+/***************************************************************************
 CryptoMiniSat -- Copyright (c) 2009 Mate Soos
 
 This program is free software: you can redistribute it and/or modify
@@ -13,10 +13,11 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
-**************************************************************************************************/
+****************************************************************************/
 
 #include "ClauseCleaner.h"
 #include "VarReplacer.h"
+#include "DataSync.h"
 
 #ifdef _MSC_VER
 #define __builtin_prefetch(a,b,c)
@@ -25,94 +26,91 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //#define DEBUG_CLEAN
 //#define VERBOSE_DEBUG
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 ClauseCleaner::ClauseCleaner(Solver& _solver) :
     solver(_solver)
 {
-    for (uint i = 0; i < 6; i++) {
+    for (uint32_t i = 0; i < 6; i++) {
         lastNumUnitarySat[i] = solver.get_unitary_learnts_num();
         lastNumUnitaryClean[i] = solver.get_unitary_learnts_num();
     }
 }
 
-void ClauseCleaner::removeSatisfied(vec<XorClause*>& cs, ClauseSetType type, const uint limit)
+const bool ClauseCleaner::satisfied(const Watched& watched, Lit lit)
 {
-    #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();
+    assert(watched.isBinary());
+    if (solver.value(lit) == l_True) return true;
+    if (solver.value(watched.getOtherLit()) == l_True) return true;
+    return false;
 }
 
-void ClauseCleaner::removeSatisfied(vec<Clause*>& cs, ClauseSetType type, const uint limit)
+void ClauseCleaner::removeSatisfiedBins(const uint32_t limit)
 {
     #ifdef DEBUG_CLEAN
     assert(solver.decisionLevel() == 0);
     #endif
-    
-    if (lastNumUnitarySat[type] + limit >= solver.get_unitary_learnts_num())
+
+    if (lastNumUnitarySat[binaryClauses] + 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;
+
+    uint32_t numRemovedHalfNonLearnt = 0;
+    uint32_t numRemovedHalfLearnt = 0;
+    uint32_t wsLit = 0;
+    for (vec<Watched> *it = solver.watches.getData(), *end = solver.watches.getDataEnd(); it != end; it++, wsLit++) {
+        Lit lit = ~Lit::toLit(wsLit);
+        vec<Watched>& ws = *it;
+
+        Watched* i = ws.getData();
+        Watched* j = i;
+        for (Watched *end2 = ws.getDataEnd(); i != end2; i++) {
+            if (i->isBinary() && satisfied(*i, lit)) {
+                if (i->getLearnt()) numRemovedHalfLearnt++;
+                else {
+                    numRemovedHalfNonLearnt++;
+                }
+            } else {
+                *j++ = *i;
+            }
+        }
+        ws.shrink_(i - j);
     }
-    cs.shrink(i - j);
-    
-    lastNumUnitarySat[type] = solver.get_unitary_learnts_num();
+
+    //std::cout << "removedHalfLeart: " << numRemovedHalfLearnt << std::endl;
+    //std::cout << "removedHalfNonLeart: " << numRemovedHalfNonLearnt << std::endl;
+    assert(numRemovedHalfLearnt % 2 == 0);
+    assert(numRemovedHalfNonLearnt % 2 == 0);
+    solver.clauses_literals -= numRemovedHalfNonLearnt;
+    solver.learnts_literals -= numRemovedHalfLearnt;
+    solver.numBins -= (numRemovedHalfLearnt + numRemovedHalfNonLearnt)/2;
+
+    lastNumUnitarySat[binaryClauses] = solver.get_unitary_learnts_num();
 }
 
-void ClauseCleaner::cleanClauses(vec<Clause*>& cs, ClauseSetType type, const uint limit)
+void ClauseCleaner::cleanClauses(vec<Clause*>& cs, ClauseSetType type, const uint32_t limit)
 {
     assert(solver.decisionLevel() == 0);
     assert(solver.qhead == solver.trail.size());
-    
+
     if (lastNumUnitaryClean[type] + limit >= solver.get_unitary_learnts_num())
         return;
 
     #ifdef VERBOSE_DEBUG
     std::cout << "Cleaning " << (type==binaryClauses ? "binaryClauses" : "normal clauses" ) << std::endl;
     #endif //VERBOSE_DEBUG
-    
+
     Clause **s, **ss, **end;
-    for (s = ss = cs.getData(), end = s + cs.size();  s != end;) {
+    for (s = ss = cs.getData(), end = s + cs.size();  s != end; s++) {
         if (s+1 != end)
             __builtin_prefetch(*(s+1), 1, 0);
         if (cleanClause(*s)) {
             solver.clauseAllocator.clauseFree(*s);
-            s++;
-        } else if (type != ClauseCleaner::binaryClauses && (*s)->size() == 2) {
-            solver.binaryClauses.push(*s);
-            solver.becameBinary++;
-            s++;
         } else {
-            *ss++ = *s++;
+            *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
@@ -121,11 +119,12 @@ void ClauseCleaner::cleanClauses(vec<Clause*>& cs, ClauseSetType type, const uin
 inline const bool ClauseCleaner::cleanClause(Clause*& cc)
 {
     Clause& c = *cc;
-    
+
     Lit origLit1 = c[0];
     Lit origLit2 = c[1];
     uint32_t origSize = c.size();
-    
+    Lit origLit3 = (origSize == 3) ? c[2] : lit_Undef;
+
     Lit *i, *j, *end;
     for (i = j = c.getData(), end = i + c.size();  i != end; i++) {
         lbool val = solver.value(*i);
@@ -133,9 +132,9 @@ inline const bool ClauseCleaner::cleanClause(Clause*& cc)
             *j++ = *i;
             continue;
         }
-        
+
         if (val == l_True) {
-            solver.detachModifiedClause(origLit1, origLit2, origSize, &c);
+            solver.detachModifiedClause(origLit1, origLit2, origLit3, origSize, &c);
             return true;
         }
     }
@@ -143,13 +142,15 @@ inline const bool ClauseCleaner::cleanClause(Clause*& cc)
 
     assert(c.size() != 1);
     if (i != j) {
-        c.setStrenghtened();
         if (c.size() == 2) {
-            solver.detachModifiedClause(origLit1, origLit2, origSize, &c);
-            Clause *c2 = solver.clauseAllocator.Clause_new(c);
-            solver.clauseAllocator.clauseFree(&c);
-            cc = c2;
-            solver.attachClause(*c2);
+            solver.detachModifiedClause(origLit1, origLit2, origLit3, origSize, &c);
+            solver.attachBinClause(c[0], c[1], c.learnt());
+            solver.numNewBin++;
+            solver.dataSync->signalNewBinClause(c);
+            return true;
+        } else if (c.size() == 3) {
+            solver.detachModifiedClause(origLit1, origLit2, origLit3, origSize, &c);
+            solver.attachClause(c);
         } else {
             if (c.learnt())
                 solver.learnts_literals -= i-j;
@@ -157,46 +158,46 @@ inline const bool ClauseCleaner::cleanClause(Clause*& cc)
                 solver.clauses_literals -= i-j;
         }
     }
-    
+
     return false;
 }
 
-void ClauseCleaner::cleanClauses(vec<XorClause*>& cs, ClauseSetType type, const uint limit)
+void ClauseCleaner::cleanClauses(vec<XorClause*>& cs, ClauseSetType type, const uint32_t 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; s++) {
         if (s+1 != end)
             __builtin_prefetch(*(s+1), 1, 0);
 
-        #ifdef DEBUG_ATTACH
-        assert(find(solver.xorwatches[(**s)[0].var()], *s));
-        assert(find(solver.xorwatches[(**s)[1].var()], *s));
-        if (solver.assigns[(**s)[0].var()]!=l_Undef || solver.assigns[(**s)[1].var()]!=l_Undef) {
+        #ifdef DEBUG_ATTACH_FULL
+        XorClause& c = **s;
+        assert(solver.xorClauseIsAttached(c));
+        if (solver.assigns[c[0].var()]!=l_Undef || solver.assigns[c[1].var()]!=l_Undef) {
             satisfied(**s);
         }
         #endif //DEBUG_ATTACH
-        
+
         if (cleanClause(**s)) {
+            //solver.clauseAllocator.clauseFree(*s);
             solver.freeLater.push(*s);
             (*s)->setRemoved();
         } else {
-            #ifdef DEBUG_ATTACH
-            assert(find(solver.xorwatches[(**s)[0].var()], *s));
-            assert(find(solver.xorwatches[(**s)[1].var()], *s));
+            #ifdef DEBUG_ATTACH_FULL
+            assert(solver.xorClauseIsAttached(c));
             #endif //DEBUG_ATTACH
             *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
@@ -216,7 +217,7 @@ inline const bool ClauseCleaner::cleanClause(XorClause& c)
         } else c.invert(val.getBool());
     }
     c.shrink(i-j);
-    
+
     assert(c.size() != 1);
     switch (c.size()) {
         case 0: {
@@ -226,13 +227,12 @@ inline const bool ClauseCleaner::cleanClause(XorClause& c)
         case 2: {
             c[0] = c[0].unsign();
             c[1] = c[1].unsign();
-            solver.varReplacer->replace(c, c.xor_clause_inverted(), c.getGroup());
+            solver.varReplacer->replace(c, c.xorEqualFalse(), c.getGroup());
             solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
             return true;
         }
         default: {
             if (i-j > 0) {
-                c.setStrenghtened();
                 solver.clauses_literals -= i-j;
             }
             return false;
@@ -243,141 +243,9 @@ inline const bool ClauseCleaner::cleanClause(XorClause& c)
     return false;
 }
 
-void ClauseCleaner::cleanClausesBewareNULL(vec<ClauseSimp>& 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<Lit> origClause(c.size());
-    memcpy(origClause.getData(), c.getData(), sizeof(Lit)*c.size());
-    
-    Lit *i, *j, *end;
-    for (i = j = c.getData(), end = i + c.size();  i != end; i++) {
-        lbool val = solver.value(*i);
-        if (val == l_Undef) {
-            *j++ = *i;
-            continue;
-        }
-        
-        if (val == l_True) {
-            subs.unlinkModifiedClause(origClause, cc, true);
-            solver.clauseAllocator.clauseFree(cc.clause);
-            return true;
-        }
-    }
-    
-    if (i != j) {
-        c.setStrenghtened();
-        if (origClause.size() > 2 && origClause.size()-(i-j) == 2) {
-            subs.unlinkModifiedClause(origClause, cc, true);
-            subs.clauses[cc.index] = cc;
-            c.shrink(i-j);
-            solver.attachClause(c);
-            subs.linkInAlreadyClause(cc);
-        } else {
-            c.shrink(i-j);
-            subs.unlinkModifiedClause(origClause, cc, false);
-            subs.linkInAlreadyClause(cc);
-            if (c.learnt())
-                solver.learnts_literals -= i-j;
-            else
-                solver.clauses_literals -= i-j;
-        }
-        if (!c.learnt()) c.calcAbstractionClause();
-        subs.updateClause(cc);
-    }
-    
-    return false;
-}
-
-void ClauseCleaner::cleanXorClausesBewareNULL(vec<XorClauseSimp>& cs, ClauseCleaner::ClauseSetType type, XorSubsumer& subs, const uint limit)
-{
-    assert(solver.decisionLevel() == 0);
-    assert(solver.qhead == solver.trail.size());
-    
-    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<Lit> origClause(c.size());
-    memcpy(origClause.getData(), c.getData(), sizeof(Lit)*c.size());
-    
-    Lit *i, *j, *end;
-    for (i = j = c.getData(), end = i + c.size();  i != end; i++) {
-        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);
-            solver.clauseAllocator.clauseFree(cc.clause);
-            return true;
-        }
-        case 2: {
-            vec<Lit> ps(2);
-            ps[0] = c[0].unsign();
-            ps[1] = c[1].unsign();
-            solver.varReplacer->replace(ps, c.xor_clause_inverted(), c.getGroup());
-            subs.unlinkModifiedClause(origClause, cc);
-            solver.clauseAllocator.clauseFree(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++)
+    for (uint32_t i = 0; i != c.size(); i++)
         if (solver.value(c[i]) == l_True)
             return true;
         return false;
@@ -385,8 +253,8 @@ bool ClauseCleaner::satisfied(const Clause& c) const
 
 bool ClauseCleaner::satisfied(const XorClause& c) const
 {
-    bool final = c.xor_clause_inverted();
-    for (uint k = 0; k != c.size(); k++ ) {
+    bool final = c.xorEqualFalse();
+    for (uint32_t k = 0; k != c.size(); k++ ) {
         const lbool& val = solver.assigns[c[k].var()];
         if (val.isUndef()) return false;
         final ^= val.getBool();
@@ -394,28 +262,48 @@ bool ClauseCleaner::satisfied(const XorClause& c) const
     return final;
 }
 
-void ClauseCleaner::moveBinClausesToBinClauses()
+
+
+/*void ClauseCleaner::removeSatisfied(vec<XorClause*>& cs, ClauseSetType type, const uint32_t limit)
 {
+    #ifdef DEBUG_CLEAN
     assert(solver.decisionLevel() == 0);
-    assert(solver.qhead == solver.trail.size());
+    #endif
 
-    vec<Clause*>& cs = solver.clauses;
-    Clause **s, **ss, **end;
-    for (s = ss = cs.getData(), end = s + cs.size();  s != end; s++) {
-        if (s+1 != end)
-            __builtin_prefetch(*(s+1), 1, 0);
+    if (lastNumUnitarySat[type] + limit >= solver.get_unitary_learnts_num())
+        return;
 
-        if ((**s).size() == 2) {
-            solver.detachClause(**s);
-            Clause *c2 = solver.clauseAllocator.Clause_new(**s);
-            solver.clauseAllocator.clauseFree(*s);
-            solver.attachClause(*c2);
-            solver.becameBinary++;
-            solver.binaryClauses.push(c2);
-        } else
-            *ss++ = *s;
+    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(s-ss);
-}
+    cs.shrink(i - j);
+
+    lastNumUnitarySat[type] = solver.get_unitary_learnts_num();
+}*/
 
-}; //NAMESPACE MINISAT
+/*void ClauseCleaner::removeSatisfied(vec<Clause*>& cs, ClauseSetType type, const uint32_t 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();
+}*/
index d4c2adfc8c8bd5f771295eab41ed7defe32f5059..c55496be3addaa7387ec03c843baf3ee54cbdb33 100644 (file)
@@ -28,54 +28,55 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "Subsumer.h"
 #include "XorSubsumer.h"
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
+/**
+@brief Cleans clauses from false literals & removes satisfied clauses
+*/
 class ClauseCleaner
 {
     public:
         ClauseCleaner(Solver& solver);
-        
-        enum ClauseSetType {clauses, xorclauses, learnts, binaryClauses, simpClauses, xorSimpClauses};
-        
-        void cleanClauses(vec<Clause*>& cs, ClauseSetType type, const uint limit = 0);
-        void cleanClausesBewareNULL(vec<ClauseSimp>& cs, ClauseSetType type, Subsumer& subs, const uint limit = 0);
-        void cleanXorClausesBewareNULL(vec<XorClauseSimp>& cs, ClauseSetType type, XorSubsumer& subs, const uint limit = 0);
-        const bool cleanClauseBewareNULL(ClauseSimp c, Subsumer& subs);
-        const bool cleanXorClauseBewareNULL(XorClauseSimp c, XorSubsumer& subs);
-        
-        void cleanClauses(vec<XorClause*>& cs, ClauseSetType type, const uint limit = 0);
-        void removeSatisfied(vec<Clause*>& cs, ClauseSetType type, const uint limit = 0);
-        void removeSatisfied(vec<XorClause*>& cs, ClauseSetType type, const uint limit = 0);
+
+        enum ClauseSetType {clauses, binaryClauses, xorclauses, learnts};
+
+        void cleanClauses(vec<Clause*>& cs, ClauseSetType type, const uint32_t limit = 0);
+
+        void cleanClauses(vec<XorClause*>& cs, ClauseSetType type, const uint32_t limit = 0);
+        void removeSatisfiedBins(const uint32_t limit = 0);
+        //void removeSatisfied(vec<Clause*>& cs, ClauseSetType type, const uint32_t limit = 0);
+        //void removeSatisfied(vec<XorClause*>& cs, ClauseSetType type, const uint32_t limit = 0);
         void removeAndCleanAll(const bool nolimit = false);
         bool satisfied(const Clause& c) const;
         bool satisfied(const XorClause& c) const;
 
-        void moveBinClausesToBinClauses();
-        
     private:
+        const bool satisfied(const Watched& watched, Lit lit);
         const bool cleanClause(XorClause& c);
         const bool cleanClause(Clause*& c);
-        
-        uint lastNumUnitarySat[6];
-        uint lastNumUnitaryClean[6];
-        
+
+        uint32_t lastNumUnitarySat[6]; ///<Last time we cleaned from satisfied clauses, this many unitary clauses were known
+        uint32_t lastNumUnitaryClean[6]; ///<Last time we cleaned from satisfied clauses&false literals, this many unitary clauses were known
+
         Solver& solver;
 };
 
+/**
+@brief Removes all satisfied clauses, and cleans false literals
+
+There is a heuristic in place not to try to clean all the time. However,
+this limit can be overridden with "nolimit"
+@p nolimit set this to force cleaning&removing. Useful if a really clean
+state is needed, which is important for certain algorithms
+*/
 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;
+    //uint32_t limit = std::min((uint32_t)((double)solver.order_heap.size() * PERCENTAGECLEANCLAUSES), FIXCLEANREPLACE);
+    uint32_t limit = (double)solver.order_heap.size() * PERCENTAGECLEANCLAUSES;
     if (nolimit) limit = 0;
-    
-    removeSatisfied(solver.binaryClauses, ClauseCleaner::binaryClauses, limit);
+
+    removeSatisfiedBins(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/ClauseOffset.h b/src/sat/cryptominisat2/ClauseOffset.h
new file mode 100644 (file)
index 0000000..d328677
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef CLAUSEOFFSET_H
+#define CLAUSEOFFSET_H
+
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+typedef uint32_t ClauseOffset;
+
+#endif //CLAUSEOFFSET_H
diff --git a/src/sat/cryptominisat2/ClauseVivifier.cpp b/src/sat/cryptominisat2/ClauseVivifier.cpp
new file mode 100644 (file)
index 0000000..b2413e3
--- /dev/null
@@ -0,0 +1,271 @@
+/**************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#include "ClauseVivifier.h"
+#include "ClauseCleaner.h"
+#include "time_mem.h"
+#include <iomanip>
+
+//#define ASSYM_DEBUG
+
+ClauseVivifier::ClauseVivifier(Solver& _solver) :
+    lastTimeWentUntil(0)
+    , numCalls(0)
+    , solver(_solver)
+{}
+
+
+/**
+@brief Performs clause vivification (by Hamadi et al.)
+
+This is the only thing that does not fit under the aegis of tryBoth(), since
+it is not part of failed literal probing, really. However, it is here because
+it seems to be a function that fits into the idology of failed literal probing.
+Maybe I am off-course and it should be in another class, or a class of its own.
+*/
+const bool ClauseVivifier::vivifyClauses()
+{
+    assert(solver.ok);
+    #ifdef VERBOSE_DEBUG
+    std::cout << "c clauseVivifier started" << std::endl;
+    //solver.printAllClauses();
+    #endif //VERBOSE_DEBUG
+    
+    
+    solver.clauseCleaner->cleanClauses(solver.clauses, ClauseCleaner::clauses);
+    numCalls++;
+
+    if (solver.ok && solver.conf.doCacheOTFSSR) {
+        if (!vivifyClauses2(solver.clauses)) return false;
+        if (/*solver.lastSelectedRestartType == static_restart &&*/ !vivifyClauses2(solver.learnts)) return false;
+    }
+
+    bool failed;
+    uint32_t effective = 0;
+    uint32_t effectiveLit = 0;
+    double myTime = cpuTime();
+    uint64_t maxNumProps = 20*1000*1000;
+    if (solver.clauses_literals + solver.learnts_literals < 500000)
+        maxNumProps *=2;
+    uint64_t extraDiff = 0;
+    uint64_t oldProps = solver.propagations;
+    bool needToFinish = false;
+    uint32_t checkedClauses = 0;
+    uint32_t potentialClauses = solver.clauses.size();
+    if (lastTimeWentUntil + 500 > solver.clauses.size())
+        lastTimeWentUntil = 0;
+    uint32_t thisTimeWentUntil = 0;
+    vec<Lit> lits;
+    vec<Lit> unused;
+
+    if (solver.clauses.size() < 1000000) {
+        //if too many clauses, random order will do perfectly well
+        std::sort(solver.clauses.getData(), solver.clauses.getDataEnd(), sortBySize());
+    }
+
+    uint32_t queueByBy = 2;
+    if (numCalls > 8
+        && (solver.clauses_literals + solver.learnts_literals < 4000000)
+        && (solver.clauses.size() < 50000))
+        queueByBy = 1;
+
+    Clause **i, **j;
+    i = j = solver.clauses.getData();
+    for (Clause **end = solver.clauses.getDataEnd(); i != end; i++) {
+        if (needToFinish || lastTimeWentUntil > 0) {
+            if (!needToFinish) {
+                lastTimeWentUntil--;
+                thisTimeWentUntil++;
+            }
+            *j++ = *i;
+            continue;
+        }
+
+        //if done enough, stop doing it
+        if (solver.propagations-oldProps + extraDiff > maxNumProps) {
+            //std::cout << "Need to finish -- ran out of prop" << std::endl;
+            needToFinish = true;
+        }
+
+        //if bad performance, stop doing it
+        /*if ((i-solver.clauses.getData() > 5000 && effectiveLit < 300)) {
+            std::cout << "Need to finish -- not effective" << std::endl;
+            needToFinish = true;
+        }*/
+
+        Clause& c = **i;
+        extraDiff += c.size();
+        checkedClauses++;
+        thisTimeWentUntil++;
+
+        assert(c.size() > 2);
+        assert(!c.learnt());
+
+        unused.clear();
+        lits.clear();
+        lits.growTo(c.size());
+        memcpy(lits.getData(), c.getData(), c.size() * sizeof(Lit));
+
+        failed = false;
+        uint32_t done = 0;
+        solver.newDecisionLevel();
+        for (; done < lits.size();) {
+            uint32_t i2 = 0;
+            for (; (i2 < queueByBy) && ((done+i2) < lits.size()); i2++) {
+                lbool val = solver.value(lits[done+i2]);
+                if (val == l_Undef) {
+                    solver.uncheckedEnqueueLight(~lits[done+i2]);
+                } else if (val == l_False) {
+                    unused.push(lits[done+i2]);
+                }
+            }
+            done += i2;
+            failed = (!solver.propagate(false).isNULL());
+            if (numCalls > 3 && failed) break;
+        }
+        solver.cancelUntilLight();
+        assert(solver.ok);
+
+        if (unused.size() > 0 || (failed && done < lits.size())) {
+            effective++;
+            uint32_t origSize = lits.size();
+            #ifdef ASSYM_DEBUG
+            std::cout << "Assym branch effective." << std::endl;
+            std::cout << "-- Orig clause:"; c.plainPrint();
+            #endif
+            solver.detachClause(c);
+
+            lits.shrink(lits.size() - done);
+            for (uint32_t i2 = 0; i2 < unused.size(); i2++) {
+                remove(lits, unused[i2]);
+            }
+
+            Clause *c2 = solver.addClauseInt(lits, c.getGroup());
+            #ifdef ASSYM_DEBUG
+            std::cout << "-- Origsize:" << origSize << " newSize:" << (c2 == NULL ? 0 : c2->size()) << " toRemove:" << c.size() - done << " unused.size():" << unused.size() << std::endl;
+            #endif
+            extraDiff += 20;
+            //TODO cheating here: we don't detect a NULL return that is in fact a 2-long clause
+            effectiveLit += origSize - (c2 == NULL ? 0 : c2->size());
+            solver.clauseAllocator.clauseFree(&c);
+
+            if (c2 != NULL) {
+                #ifdef ASSYM_DEBUG
+                std::cout << "-- New clause:"; c2->plainPrint();
+                #endif
+                *j++ = c2;
+            }
+
+            if (!solver.ok) needToFinish = true;
+        } else {
+            *j++ = *i;
+        }
+    }
+    solver.clauses.shrink(i-j);
+
+    lastTimeWentUntil = thisTimeWentUntil;
+
+    if (solver.conf.verbosity  >= 1) {
+        std::cout << "c asymm "
+        << " cl-useful: " << effective << "/" << checkedClauses << "/" << potentialClauses
+        << " lits-rem:" << effectiveLit
+        << " time: " << cpuTime() - myTime
+        << std::endl;
+    }
+
+    return solver.ok;
+}
+
+
+const bool ClauseVivifier::vivifyClauses2(vec<Clause*>& clauses)
+{
+    assert(solver.ok);
+
+    vec<char> seen;
+    seen.growTo(solver.nVars()*2, 0);
+    uint32_t litsRem = 0;
+    uint32_t clShrinked = 0;
+    uint64_t countTime = 0;
+    uint64_t maxCountTime = 500000000;
+    if (solver.clauses_literals + solver.learnts_literals < 500000)
+        maxCountTime *= 2;
+    if (numCalls >= 5) maxCountTime*= 3;
+    uint32_t clTried = 0;
+    vec<Lit> lits;
+    bool needToFinish = false;
+    double myTime = cpuTime();
+
+    if (numCalls < 3) return true;
+
+    Clause** i = clauses.getData();
+    Clause** j = i;
+    for (Clause** end = clauses.getDataEnd(); i != end; i++) {
+        if (needToFinish) {
+            *j++ = *i;
+            continue;
+        }
+        if (countTime > maxCountTime) needToFinish = true;
+
+        Clause& cl = **i;
+        countTime += cl.size()*2;
+        clTried++;
+
+        for (uint32_t i2 = 0; i2 < cl.size(); i2++) seen[cl[i2].toInt()] = 1;
+        for (const Lit *l = cl.getData(), *end = cl.getDataEnd(); l != end; l++) {
+            if (seen[l->toInt()] == 0) continue;
+            Lit lit = *l;
+
+            countTime += solver.transOTFCache[l->toInt()].lits.size();
+            for (vector<Lit>::const_iterator it2 = solver.transOTFCache[l->toInt()].lits.begin()
+                , end2 = solver.transOTFCache[l->toInt()].lits.end(); it2 != end2; it2++) {
+                seen[(~(*it2)).toInt()] = 0;
+            }
+        }
+
+        lits.clear();
+        for (const Lit *it2 = cl.getData(), *end2 = cl.getDataEnd(); it2 != end2; it2++) {
+            if (seen[it2->toInt()]) lits.push(*it2);
+            else litsRem++;
+            seen[it2->toInt()] = 0;
+        }
+        if (lits.size() < cl.size()) {
+            countTime += cl.size()*10;
+            solver.detachClause(cl);
+            clShrinked++;
+            Clause* c2 = solver.addClauseInt(lits, cl.getGroup(), cl.learnt(), cl.getGlue(), cl.getMiniSatAct());
+            solver.clauseAllocator.clauseFree(&cl);
+
+            if (c2 != NULL) *j++ = c2;
+            if (!solver.ok) needToFinish = true;
+        } else {
+            *j++ = *i;
+        }
+    }
+
+    clauses.shrink(i-j);
+
+    if (solver.conf.verbosity >= 1) {
+        std::cout << "c vivif2 -- "
+        << " cl tried " << std::setw(8) << clTried
+        << " cl shrink " << std::setw(8) << clShrinked
+        << " lits rem " << std::setw(10) << litsRem
+        << " time: " << cpuTime() - myTime
+        << std::endl;
+    }
+
+    return solver.ok;
+}
diff --git a/src/sat/cryptominisat2/ClauseVivifier.h b/src/sat/cryptominisat2/ClauseVivifier.h
new file mode 100644 (file)
index 0000000..d890e40
--- /dev/null
@@ -0,0 +1,55 @@
+/**************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#ifndef CLAUSEVIVIFIER_H
+#define CLAUSEVIVIFIER_H
+
+#include "Solver.h"
+
+class ClauseVivifier {
+    public:
+        ClauseVivifier(Solver& solver);
+        const bool vivifyClauses();
+        const bool vivifyClauses2(vec<Clause*>& clauses);
+
+    private:
+
+        /**
+        @brief Records data for asymmBranch()
+
+        Clauses are ordered accurding to sze in asymmBranch() and then some are
+        checked if we could shorten them. This value records that between calls
+        to asymmBranch() where we stopped last time in the list
+        */
+        uint32_t lastTimeWentUntil;
+
+        /**
+        @brief Sort clauses according to size
+        */
+        struct sortBySize
+        {
+            const bool operator () (const Clause* x, const Clause* y)
+            {
+              return (x->size() > y->size());
+            }
+        };
+
+        uint32_t numCalls;
+        Solver& solver;
+};
+
+#endif //CLAUSEVIVIFIER_H
diff --git a/src/sat/cryptominisat2/CompleteDetachReattacher.cpp b/src/sat/cryptominisat2/CompleteDetachReattacher.cpp
new file mode 100644 (file)
index 0000000..97a53e2
--- /dev/null
@@ -0,0 +1,194 @@
+/**************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#include "CompleteDetachReattacher.h"
+#include "VarReplacer.h"
+#include "ClauseCleaner.h"
+
+CompleteDetachReatacher::CompleteDetachReatacher(Solver& _solver) :
+    solver(_solver)
+{
+}
+
+/**
+@brief Completely detach all non-binary clauses
+*/
+void CompleteDetachReatacher::detachNonBinsNonTris(const bool removeTri)
+{
+    uint32_t oldNumBins = solver.numBins;
+    ClausesStay stay;
+
+    for (vec<Watched> *it = solver.watches.getData(), *end = solver.watches.getDataEnd(); it != end; it++) {
+        stay += clearWatchNotBinNotTri(*it, removeTri);
+    }
+
+    solver.learnts_literals = stay.learntBins;
+    solver.clauses_literals = stay.nonLearntBins;
+    solver.numBins = (stay.learntBins + stay.nonLearntBins)/2;
+    release_assert(solver.numBins == oldNumBins);
+}
+
+/**
+@brief Helper function for detachPointerUsingClauses()
+*/
+const CompleteDetachReatacher::ClausesStay CompleteDetachReatacher::clearWatchNotBinNotTri(vec<Watched>& ws, const bool removeTri)
+{
+    ClausesStay stay;
+
+    Watched* i = ws.getData();
+    Watched* j = i;
+    for (Watched *end = ws.getDataEnd(); i != end; i++) {
+        if (i->isBinary()) {
+            if (i->getLearnt()) stay.learntBins++;
+            else stay.nonLearntBins++;
+            *j++ = *i;
+        } else if (!removeTri && i->isTriClause()) {
+            stay.tris++;
+            *j++ = *i;
+        }
+    }
+    ws.shrink_(i-j);
+
+    return stay;
+}
+
+/**
+@brief Completely attach all clauses
+*/
+const bool CompleteDetachReatacher::reattachNonBins()
+{
+    assert(solver.ok);
+
+    cleanAndAttachClauses(solver.clauses);
+    cleanAndAttachClauses(solver.learnts);
+    cleanAndAttachClauses(solver.xorclauses);
+    solver.clauseCleaner->removeSatisfiedBins();
+
+    if (solver.ok) solver.ok = (solver.propagate().isNULL());
+
+    return solver.ok;
+}
+
+/**
+@brief Cleans clauses from failed literals/removes satisfied clauses from cs
+
+May change solver.ok to FALSE (!)
+*/
+inline void CompleteDetachReatacher::cleanAndAttachClauses(vec<Clause*>& cs)
+{
+    Clause **i = cs.getData();
+    Clause **j = i;
+    for (Clause **end = cs.getDataEnd(); i != end; i++) {
+        if (cleanClause(*i)) {
+            solver.attachClause(**i);
+            *j++ = *i;
+        } else {
+            solver.clauseAllocator.clauseFree(*i);
+        }
+    }
+    cs.shrink(i-j);
+}
+
+/**
+@brief Cleans clauses from failed literals/removes satisfied clauses from cs
+*/
+inline void CompleteDetachReatacher::cleanAndAttachClauses(vec<XorClause*>& cs)
+{
+    XorClause **i = cs.getData();
+    XorClause **j = i;
+    for (XorClause **end = cs.getDataEnd(); i != end; i++) {
+        if (cleanClause(**i)) {
+            solver.attachClause(**i);
+            *j++ = *i;
+        } else {
+            solver.clauseAllocator.clauseFree(*i);
+        }
+    }
+    cs.shrink(i-j);
+}
+
+/**
+@brief Not only cleans a clause from false literals, but if clause is satisfied, it reports it
+*/
+inline const bool CompleteDetachReatacher::cleanClause(Clause*& cl)
+{
+    Clause& ps = *cl;
+    assert(ps.size() > 2);
+
+    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);
+
+    switch (ps.size()) {
+        case 0:
+            solver.ok = false;
+            return false;
+        case 1:
+            solver.uncheckedEnqueue(ps[0]);
+            return false;
+
+        case 2: {
+            solver.attachBinClause(ps[0], ps[1], ps.learnt());
+            return false;
+        }
+
+        default:;
+    }
+
+    return true;
+}
+
+/**
+@brief Not only cleans a clause from false literals, but if clause is satisfied, it reports it
+*/
+inline const bool CompleteDetachReatacher::cleanClause(XorClause& ps)
+{
+    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);
+
+    switch (ps.size()) {
+        case 0:
+            if (ps.xorEqualFalse() == false) solver.ok = false;
+            return false;
+        case 1:
+            solver.uncheckedEnqueue(Lit(ps[0].var(), ps.xorEqualFalse()));
+            return false;
+
+        case 2: {
+            ps[0] = ps[0].unsign();
+            ps[1] = ps[1].unsign();
+            solver.varReplacer->replace(ps, ps.xorEqualFalse(), ps.getGroup());
+            return false;
+        }
+
+        default:;
+    }
+
+    return true;
+}
diff --git a/src/sat/cryptominisat2/CompleteDetachReattacher.h b/src/sat/cryptominisat2/CompleteDetachReattacher.h
new file mode 100644 (file)
index 0000000..b45949d
--- /dev/null
@@ -0,0 +1,74 @@
+/**************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#include "Solver.h"
+
+/**
+@brief Helper class to completely detaches all(or only non-native) clauses, and then re-attach all
+
+Used in classes that (may) do a lot of clause-changning, in which case
+detaching&reattaching of clauses would be neccessary to do
+individually, which is \b very slow
+
+A main use-case is the following:
+-# detach all clauses
+-# play around with all clauses as desired. Cannot call solver.propagate() here
+-# attach all clauses again
+
+A somewhat more complicated, but more interesting use-case is the following:
+-# detach only non-natively stored clauses from watchlists
+-# play around wil all clauses as desired. 2- and 3-long clauses can still
+be propagated with solver.propagate() -- this is quite a nice trick, in fact
+-# detach all clauses (i.e. also native ones)
+-# attach all clauses
+*/
+class CompleteDetachReatacher
+{
+    public:
+        CompleteDetachReatacher(Solver& solver);
+        const bool reattachNonBins();
+        void detachNonBinsNonTris(const bool removeTri);
+
+    private:
+        class ClausesStay {
+            public:
+                ClausesStay() :
+                    learntBins(0)
+                    , nonLearntBins(0)
+                    , tris(0)
+                {}
+
+                ClausesStay& operator+=(const ClausesStay& other) {
+                    learntBins += other.learntBins;
+                    nonLearntBins += other.nonLearntBins;
+                    tris += other.tris;
+                    return *this;
+                }
+
+                uint32_t learntBins;
+                uint32_t nonLearntBins;
+                uint32_t tris;
+        };
+        const ClausesStay clearWatchNotBinNotTri(vec<Watched>& ws, const bool removeTri = false);
+
+        void cleanAndAttachClauses(vec<Clause*>& cs);
+        void cleanAndAttachClauses(vec<XorClause*>& cs);
+        const bool cleanClause(Clause*& ps);
+        const bool cleanClause(XorClause& ps);
+
+        Solver& solver;
+};
diff --git a/src/sat/cryptominisat2/DataSync.cpp b/src/sat/cryptominisat2/DataSync.cpp
new file mode 100644 (file)
index 0000000..1c927e1
--- /dev/null
@@ -0,0 +1,231 @@
+/*****************************************************************************
+CryptoMiniSat -- Copyright (c) 2010 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+#include "DataSync.h"
+#include "Subsumer.h"
+#include "VarReplacer.h"
+#include "XorSubsumer.h"
+#include <iomanip>
+
+DataSync::DataSync(Solver& _solver, SharedData* _sharedData) :
+    lastSyncConf(0)
+    , sentUnitData(0)
+    , recvUnitData(0)
+    , sharedData(_sharedData)
+    , solver(_solver)
+{}
+
+void DataSync::newVar()
+{
+    syncFinish.push(0);
+    syncFinish.push(0);
+    seen.push(false);
+    seen.push(false);
+}
+
+const bool DataSync::syncData()
+{
+    if (sharedData == NULL
+        || lastSyncConf + SYNC_EVERY_CONFL >= solver.conflicts) return true;
+
+    assert(sharedData != NULL);
+    assert(solver.decisionLevel() == 0);
+
+    bool ok;
+    #pragma omp critical (unitData)
+    ok = shareUnitData();
+    if (!ok) return false;
+
+    #pragma omp critical (binData)
+    ok = shareBinData();
+    if (!ok) return false;
+
+    lastSyncConf = solver.conflicts;
+
+    return true;
+}
+
+const bool DataSync::shareBinData()
+{
+    uint32_t oldRecvBinData = recvBinData;
+    uint32_t oldSentBinData = sentBinData;
+
+    SharedData& shared = *sharedData;
+    if (shared.bins.size() != solver.nVars()*2)
+        shared.bins.resize(solver.nVars()*2);
+
+    for (uint32_t wsLit = 0; wsLit < solver.nVars()*2; wsLit++) {
+        Lit lit1 = ~Lit::toLit(wsLit);
+        lit1 = solver.varReplacer->getReplaceTable()[lit1.var()] ^ lit1.sign();
+        if (solver.subsumer->getVarElimed()[lit1.var()]
+            || solver.xorSubsumer->getVarElimed()[lit1.var()]
+            || solver.value(lit1.var()) != l_Undef
+            ) continue;
+
+        vector<Lit>& bins = shared.bins[wsLit];
+        vec<Watched>& ws = solver.watches[wsLit];
+
+        if (bins.size() > syncFinish[wsLit]
+            && !syncBinFromOthers(lit1, bins, syncFinish[wsLit], ws)) return false;
+    }
+
+    syncBinToOthers();
+
+    if (solver.conf.verbosity >= 3) {
+        std::cout << "c got bins " << std::setw(10) << (recvBinData - oldRecvBinData)
+        << std::setw(10) << " sent bins " << (sentBinData - oldSentBinData) << std::endl;
+    }
+
+    return true;
+}
+
+template <class T>
+void DataSync::signalNewBinClause(T& ps)
+{
+    assert(ps.size() == 2);
+    signalNewBinClause(ps[0], ps[1]);
+}
+
+void DataSync::signalNewBinClause(Lit lit1, Lit lit2)
+{
+    if (lit1.toInt() > lit2.toInt()) std::swap(lit1, lit2);
+    newBinClauses.push_back(std::make_pair(lit1, lit2));
+}
+
+template void DataSync::signalNewBinClause(Clause& ps);
+template void DataSync::signalNewBinClause(XorClause& ps);
+template void DataSync::signalNewBinClause(vec<Lit>& ps);
+
+const bool DataSync::syncBinFromOthers(const Lit lit, const vector<Lit>& bins, uint32_t& finished, vec<Watched>& ws)
+{
+    assert(solver.varReplacer->getReplaceTable()[lit.var()].var() == lit.var());
+    assert(solver.subsumer->getVarElimed()[lit.var()] == false);
+    assert(solver.xorSubsumer->getVarElimed()[lit.var()] == false);
+
+    vec<Lit> addedToSeen;
+    for (Watched *it = ws.getData(), *end = ws.getDataEnd(); it != end; it++) {
+        if (it->isBinary()) {
+            addedToSeen.push(it->getOtherLit());
+            seen[it->getOtherLit().toInt()] = true;
+        }
+    }
+
+    vec<Lit> lits(2);
+    for (uint32_t i = finished; i < bins.size(); i++) {
+        if (!seen[bins[i].toInt()]) {
+            Lit otherLit = bins[i];
+            otherLit = solver.varReplacer->getReplaceTable()[otherLit.var()] ^ otherLit.sign();
+            if (solver.subsumer->getVarElimed()[otherLit.var()]
+                || solver.xorSubsumer->getVarElimed()[otherLit.var()]
+                || solver.value(otherLit.var()) != l_Undef
+                ) continue;
+
+            recvBinData++;
+            lits[0] = lit;
+            lits[1] = otherLit;
+            solver.addClauseInt(lits, 0, true, 2, 0, true);
+            lits.clear();
+            lits.growTo(2);
+            if (!solver.ok) goto end;
+        }
+    }
+    finished = bins.size();
+
+    end:
+    for (uint32_t i = 0; i < addedToSeen.size(); i++)
+        seen[addedToSeen[i].toInt()] = false;
+
+    return solver.ok;
+}
+
+void DataSync::syncBinToOthers()
+{
+    for(vector<std::pair<Lit, Lit> >::const_iterator it = newBinClauses.begin(), end = newBinClauses.end(); it != end; it++) {
+        addOneBinToOthers(it->first, it->second);
+    }
+
+    newBinClauses.clear();
+}
+
+void DataSync::addOneBinToOthers(const Lit lit1, const Lit lit2)
+{
+    assert(lit1.toInt() < lit2.toInt());
+
+    vector<Lit>& bins = sharedData->bins[(~lit1).toInt()];
+    for (vector<Lit>::const_iterator it = bins.begin(), end = bins.end(); it != end; it++) {
+        if (*it == lit2) return;
+    }
+
+    bins.push_back(lit2);
+    sentBinData++;
+}
+
+const bool DataSync::shareUnitData()
+{
+    uint32_t thisGotUnitData = 0;
+    uint32_t thisSentUnitData = 0;
+
+    SharedData& shared = *sharedData;
+    shared.value.growTo(solver.nVars(), l_Undef);
+    for (uint32_t var = 0; var < solver.nVars(); var++) {
+        Lit thisLit = Lit(var, false);
+        thisLit = solver.varReplacer->getReplaceTable()[thisLit.var()] ^ thisLit.sign();
+        const lbool thisVal = solver.value(thisLit);
+        const lbool otherVal = shared.value[var];
+
+        if (thisVal == l_Undef && otherVal == l_Undef) continue;
+        if (thisVal != l_Undef && otherVal != l_Undef) {
+            if (thisVal != otherVal) {
+                solver.ok = false;
+                return false;
+            } else {
+                continue;
+            }
+        }
+
+        if (otherVal != l_Undef) {
+            assert(thisVal == l_Undef);
+            Lit litToEnqueue = thisLit ^ (otherVal == l_False);
+            if (solver.subsumer->getVarElimed()[litToEnqueue.var()]
+                || solver.xorSubsumer->getVarElimed()[litToEnqueue.var()]
+                ) continue;
+
+            solver.uncheckedEnqueue(litToEnqueue);
+            solver.ok = solver.propagate().isNULL();
+            if (!solver.ok) return false;
+            thisGotUnitData++;
+            continue;
+        }
+
+        if (thisVal != l_Undef) {
+            assert(otherVal == l_Undef);
+            shared.value[var] = thisVal;
+            thisSentUnitData++;
+            continue;
+        }
+    }
+
+    if (solver.conf.verbosity >= 3 && (thisGotUnitData > 0 || thisSentUnitData > 0)) {
+        std::cout << "c got units " << std::setw(8) << thisGotUnitData
+        << " sent units " << std::setw(8) << thisSentUnitData << std::endl;
+    }
+
+    recvUnitData += thisGotUnitData;
+    sentUnitData += thisSentUnitData;
+
+    return true;
+}
\ No newline at end of file
diff --git a/src/sat/cryptominisat2/DataSync.h b/src/sat/cryptominisat2/DataSync.h
new file mode 100644 (file)
index 0000000..b049fc4
--- /dev/null
@@ -0,0 +1,83 @@
+/*****************************************************************************
+CryptoMiniSat -- Copyright (c) 2010 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+#include "SharedData.h"
+#include "Solver.h"
+
+class DataSync
+{
+    public:
+        DataSync(Solver& solver, SharedData* sharedData);
+        void newVar();
+        const bool syncData();
+
+
+        template <class T> void signalNewBinClause(T& ps);
+        void signalNewBinClause(Lit lit1, Lit lit2);
+
+        const uint32_t getSentUnitData() const;
+        const uint32_t getRecvUnitData() const;
+        const uint32_t getSentBinData() const;
+        const uint32_t getRecvBinData() const;
+
+    private:
+        //functions
+        const bool shareUnitData();
+        const bool syncBinFromOthers(const Lit lit, const vector<Lit>& bins, uint32_t& finished, vec<Watched>& ws);
+        void syncBinToOthers();
+        void addOneBinToOthers(const Lit lit1, const Lit lit2);
+        const bool shareBinData();
+
+        //stuff to sync
+        vector<std::pair<Lit, Lit> > newBinClauses;
+
+        //stats
+        uint64_t lastSyncConf;
+        vec<uint32_t> syncFinish;
+        uint32_t sentUnitData;
+        uint32_t recvUnitData;
+        uint32_t sentBinData;
+        uint32_t recvBinData;
+
+        //misc
+        vec<char> seen;
+
+        //main data
+        SharedData* sharedData;
+        Solver& solver;
+};
+
+inline const uint32_t DataSync::getSentUnitData() const
+{
+    return sentUnitData;
+}
+
+inline const uint32_t DataSync::getRecvUnitData() const
+{
+    return recvUnitData;
+}
+
+inline const uint32_t DataSync::getSentBinData() const
+{
+    return sentBinData;
+}
+
+inline const uint32_t DataSync::getRecvBinData() const
+{
+    return recvBinData;
+}
+
diff --git a/src/sat/cryptominisat2/DimacsParser.cpp b/src/sat/cryptominisat2/DimacsParser.cpp
new file mode 100644 (file)
index 0000000..e8c4671
--- /dev/null
@@ -0,0 +1,455 @@
+/*****************************************************************************
+MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+Original code by MiniSat authors are under an MIT licence.
+Modifications for CryptoMiniSat are under GPLv3 licence.
+******************************************************************************/
+
+#include "DimacsParser.h"
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+#include "Solver.h"
+
+#ifdef VERBOSE_DEBUG
+#define DEBUG_COMMENT_PARSING
+#endif //VERBOSE_DEBUG
+
+//#define DEBUG_COMMENT_PARSING
+
+DimacsParser::DimacsParser(Solver* _solver, const bool _debugLib, const bool _debugNewVar, const bool _grouping, const bool _addAsLearnt):
+    solver(_solver)
+    , debugLib(_debugLib)
+    , debugNewVar(_debugNewVar)
+    , grouping(_grouping)
+    , addAsLearnt(_addAsLearnt)
+    , groupId(0)
+{}
+
+/**
+@brief Skips all whitespaces
+*/
+void DimacsParser::skipWhitespace(StreamBuffer& in)
+{
+    while ((*in >= 9 && *in <= 13) || *in == 32)
+        ++in;
+}
+
+/**
+@brief Skips until the end of the line
+*/
+void DimacsParser::skipLine(StreamBuffer& in)
+{
+    for (;;) {
+        if (*in == EOF || *in == '\0') return;
+        if (*in == '\n') {
+            ++in;
+            return;
+        }
+        ++in;
+    }
+}
+
+/**
+@brief Returns line until the end of line
+*/
+std::string DimacsParser::untilEnd(StreamBuffer& in)
+{
+    std::string ret;
+
+    while(*in != EOF && *in != '\0' && *in != '\n') {
+        ret += *in;
+        ++in;
+    }
+
+    return ret;
+}
+
+/**
+@brief Parses in an integer
+*/
+int DimacsParser::parseInt(StreamBuffer& in, uint32_t& lenParsed)
+{
+    lenParsed = 0;
+    int     val = 0;
+    bool    neg = false;
+    skipWhitespace(in);
+    if      (*in == '-') neg = true, ++in;
+    else if (*in == '+') ++in;
+    if (*in < '0' || *in > '9') printf("PARSE ERROR! Unexpected char: %c\n", *in), exit(3);
+    while (*in >= '0' && *in <= '9') {
+        lenParsed++;
+        val = val*10 + (*in - '0'),
+              ++in;
+    }
+    return neg ? -val : val;
+}
+
+float DimacsParser::parseFloat(StreamBuffer& in)
+{
+    uint32_t len;
+    uint32_t main = parseInt(in, len);
+    if (*in != '.') {
+        printf("PARSE ERROR! Float does not contain a dot! Instead it contains: %c\n", *in);
+        exit(3);
+    }
+    ++in;
+    uint32_t sub = parseInt(in, len);
+
+    uint32_t exp = 1;
+    for (uint32_t i = 0;i < len; i++) exp *= 10;
+    return (float)main + ((float)sub/exp);
+}
+
+
+std::string DimacsParser::stringify(uint32_t x)
+{
+    std::ostringstream o;
+    o << x;
+    return o.str();
+}
+
+/**
+@brief Parse a continious set of characters from "in" to "str".
+
+\todo EOF is not checked for!!
+*/
+void DimacsParser::parseString(StreamBuffer& in, std::string& str)
+{
+    str.clear();
+    skipWhitespace(in);
+    while (*in != ' ' && *in != '\n') {
+        str += *in;
+        ++in;
+    }
+}
+
+/**
+@brief Reads in a clause and puts it in lit
+@p[out] lits
+*/
+void DimacsParser::readClause(StreamBuffer& in, vec<Lit>& lits)
+{
+    int     parsed_lit;
+    Var     var;
+    uint32_t len;
+    lits.clear();
+    for (;;) {
+        parsed_lit = parseInt(in, len);
+        if (parsed_lit == 0) break;
+        var = abs(parsed_lit)-1;
+        if (!debugNewVar) {
+            while (var >= solver->nVars()) solver->newVar();
+        }
+        lits.push( (parsed_lit > 0) ? Lit(var, false) : Lit(var, true) );
+    }
+}
+
+/**
+@brief Matches parameter "str" to content in "in"
+*/
+bool DimacsParser::match(StreamBuffer& in, const char* str)
+{
+    for (; *str != 0; ++str, ++in)
+        if (*str != *in)
+            return false;
+    return true;
+}
+
+/**
+@brief Prints the data in "p cnf VARS CLAUSES" header in DIMACS
+
+We don't actually do \b anything with these. It's just printed for user
+happyness. However, I think it's useless to print it, since it might mislead
+users to think that their headers are correct, even though a lot of headers are
+completely wrong, thanks to MiniSat printing the header, but not checking it.
+Not checking it is \b not a problem. The problem is printing it such that
+people believe it's validated
+*/
+void DimacsParser::printHeader(StreamBuffer& in)
+{
+    uint32_t len;
+
+    if (match(in, "p cnf")) {
+        int vars    = parseInt(in, len);
+        int clauses = parseInt(in, len);
+        if (solver->conf.verbosity >= 1) {
+            std::cout << "c -- header says num vars:   " << std::setw(12) << vars << std::endl;
+            std::cout << "c -- header says num clauses:" <<  std::setw(12) << clauses << std::endl;
+        }
+    } else {
+        printf("PARSE ERROR! Unexpected char: %c\n", *in), exit(3);
+    }
+}
+
+/**
+@brief Parse up comment lines which could contain important information
+
+In CryptoMiniSat we save quite a bit of information in the comment lines.
+These need to be parsed up. This function achieves that. Informations that
+can be given:
+\li "c Solver::newVar() called" -- we execute Solver::newVar()
+\li "c Solver::solve() called" -- we execute Solver::solve() and dump the
+solution to debugLibPartX.out, where X is a number that starts with 1 and
+increases to N, where N is the number of solve() instructions
+\li variable names in the form of "c var VARNUM NAME"
+*/
+void DimacsParser::parseComments(StreamBuffer& in, const std::string str)
+{
+    uint32_t len;
+    #ifdef DEBUG_COMMENT_PARSING
+    std::cout << "Parsing comments" << std::endl;
+    #endif //DEBUG_COMMENT_PARSING
+
+    if (str == "v" || str == "var") {
+        int var = parseInt(in, len);
+        skipWhitespace(in);
+        if (var <= 0) std::cout << "PARSE ERROR! Var number must be a positive integer" << std::endl, exit(3);
+        std::string name = untilEnd(in);
+        solver->setVariableName(var-1, name.c_str());
+
+        #ifdef DEBUG_COMMENT_PARSING
+        std::cout << "Parsed 'c var'" << std::endl;
+        #endif //DEBUG_COMMENT_PARSING
+    } else if (debugLib && str == "Solver::solve()") {
+        lbool ret = solver->solve();
+        std::string s = "debugLibPart" + stringify(debugLibPart) +".output";
+        FILE* res = fopen(s.c_str(), "w");
+        if (ret == l_True) {
+            fprintf(res, "SAT\n");
+            for (Var i = 0; i != solver->nVars(); i++) {
+                if (solver->model[i] != l_Undef)
+                    fprintf(res, "%s%d ", (solver->model[i]==l_True)?"":"-", i+1);
+            }
+            fprintf(res, "0\n");
+        } else if (ret == l_False) {
+            fprintf(res, "UNSAT\n");
+        } else if (ret == l_Undef) {
+            assert(false);
+        } else {
+            assert(false);
+        }
+        fclose(res);
+        debugLibPart++;
+
+        #ifdef DEBUG_COMMENT_PARSING
+        std::cout << "Parsed Solver::solve()" << std::endl;
+        #endif //DEBUG_COMMENT_PARSING
+    } else if (debugNewVar && str == "Solver::newVar()") {
+        solver->newVar();
+
+        #ifdef DEBUG_COMMENT_PARSING
+        std::cout << "Parsed Solver::newVar()" << std::endl;
+        #endif //DEBUG_COMMENT_PARSING
+    } else {
+        #ifdef DEBUG_COMMENT_PARSING
+        std::cout << "didn't understand in CNF file: 'c " << str << std::endl;
+        #endif //DEBUG_COMMENT_PARSING
+    }
+    skipLine(in);
+}
+
+/**
+@brief Parses clause parameters given as e.g. "c clause learnt yes glue 4 miniSatAct 5.2"
+*/
+void DimacsParser::parseClauseParameters(StreamBuffer& in, bool& learnt, uint32_t& glue, float& miniSatAct)
+{
+    std::string str;
+    uint32_t len;
+
+    //Parse in if we are a learnt clause or not
+    ++in;
+    parseString(in, str);
+    //std::cout << str<< std::endl;
+    if (str != "learnt") goto addTheClause;
+
+    ++in;
+    parseString(in, str);
+    //std::cout << str<< std::endl;
+    if (str == "yes") learnt = true;
+    else if (str == "no") {
+        learnt = false;
+        goto addTheClause;
+    }
+    else {
+        std::cout << "parsed in instead of yes/no: '" << str << "'" << std::endl;
+        goto addTheClause;
+        //std::cout << "PARSE ERROR: line contains \"c learnt\" but is not followed by yes/no" << std::endl;
+        //exit(-1);
+    }
+    //std::std::cout << "Learnt? " << learnt << std::endl;
+
+    //Parse in Glue value
+    ++in;
+    parseString(in, str);
+    if (str != "glue") goto addTheClause;
+    //std::std::cout << "read GLUE" << std::endl;
+    ++in;
+    glue = parseInt(in, len);
+    //std::cout << "glue: " << glue << std::endl;
+
+    //Parse in MiniSat activity
+    ++in;
+    parseString(in, str);
+    if (str != "miniSatAct") goto addTheClause;
+    //std::cout << "read MINISATACT" << std::endl;
+    ++in;
+    miniSatAct = parseFloat(in);
+    //std::cout << "MiniSatAct:" << miniSatAct << std::endl;
+
+    addTheClause:
+    skipLine(in);
+    return;
+}
+
+/**
+@brief Parses in a clause and its optional attributes
+
+We might have lines like:
+\li "c clause learnt yes glue 4 miniSatAct 5.2" which we need to parse up and
+make the clause learnt.
+\li Also, groupings can be given with "c group NUM NAME" after the clause.
+\li Furthermore, we need to take care, since comments might mean orders like
+"c Solver::newVar() called", which needs to be parsed with parseComments()
+-- this, we delegate
+*/
+void DimacsParser::readFullClause(StreamBuffer& in)
+{
+    bool xor_clause = false;
+    bool learnt = false;
+    uint32_t glue = 100.0;
+    float miniSatAct = 10.0;
+    std::string name;
+    std::string str;
+    uint32_t len;
+    bool needToParseComments = false;
+
+    //read in the actual clause
+    if ( *in == 'x') xor_clause = true, ++in;
+    readClause(in, lits);
+    skipLine(in);
+
+    //now read in grouping information, etc.
+    if (!grouping) groupId++;
+    else {
+        if (*in != 'c') {
+            std::cout << "PARSE ERROR! Group must be present after earch clause ('c' missing after clause line)" << std::endl;
+            exit(3);
+        }
+        ++in;
+
+        parseString(in, str);
+        if (str != "g" && str != "group") {
+            std::cout << "PARSE ERROR! Group must be present after each clause('group' missing)!" << std::endl;
+            std::cout << "Instead of 'group' there was:" << str << std::endl;
+            exit(3);
+        }
+
+        groupId = parseInt(in, len);
+        if (groupId <= 0) printf("PARSE ERROR! Group number must be a positive integer\n"), exit(3);
+
+        skipWhitespace(in);
+        name = untilEnd(in);
+    }
+
+    //Parse comments or parse clause type (learnt, glue value, etc.)
+    if (*in == 'c') {
+        ++in;
+        parseString(in, str);
+        if (str == "clause") {
+            parseClauseParameters(in, learnt, glue, miniSatAct);
+        } else {
+            needToParseComments = true;
+        }
+    }
+
+    if (xor_clause) {
+        bool xorEqualFalse = false;
+        for (uint32_t i = 0; i < lits.size(); i++)
+            xorEqualFalse ^= lits[i].sign();
+
+        solver->addXorClause(lits, xorEqualFalse, groupId, name.c_str());
+        numXorClauses++;
+    } else {
+        if (addAsLearnt || learnt) {
+            solver->addLearntClause(lits, groupId, NULL, glue, miniSatAct);
+            numLearntClauses++;
+        } else {
+            solver->addClause(lits, groupId, name.c_str());
+            numNormClauses++;
+        }
+    }
+
+    if (needToParseComments) {
+        #ifdef DEBUG_COMMENT_PARSING
+        std::cout << "Need to parse comments:" << str << std::endl;
+        #endif //DEBUG_COMMENT_PARSING
+        parseComments(in, str);
+    }
+}
+
+/**
+@brief The main function: parses in a full DIMACS file
+
+Parses in header, the clauses, and special comment lines that define clause
+groups, clause group names, and variable names, plus it parses up special
+comments that have to do with debugging Solver::newVar() and Solver::solve()
+calls for library-debugging
+*/
+void DimacsParser::parse_DIMACS_main(StreamBuffer& in)
+{
+    std::string str;
+
+    for (;;) {
+        skipWhitespace(in);
+        switch (*in) {
+        case EOF:
+            return;
+        case 'p':
+            printHeader(in);
+            break;
+        case 'c':
+            ++in;
+            parseString(in, str);
+            parseComments(in, str);
+            break;
+        default:
+            readFullClause(in);
+            break;
+        }
+    }
+}
+
+template <class T>
+void DimacsParser::parse_DIMACS(T input_stream)
+{
+    debugLibPart = 1;
+    numLearntClauses = 0;
+    numNormClauses = 0;
+    numXorClauses = 0;
+    uint32_t origNumVars = solver->nVars();
+
+    StreamBuffer in(input_stream);
+    parse_DIMACS_main(in);
+
+    if (solver->conf.verbosity >= 1) {
+        std::cout << "c -- clauses added: "
+        << std::setw(12) << numLearntClauses
+        << " learnts, "
+        << std::setw(12) << numNormClauses
+        << " normals, "
+        << std::setw(12) << numXorClauses
+        << " xors"
+        << std::endl;
+
+        std::cout << "c -- vars added " << std::setw(10) << (solver->nVars() - origNumVars)
+        << std::endl;
+    }
+}
+
+#ifndef DISABLE_ZLIB
+template void DimacsParser::parse_DIMACS(gzFile input_stream);
+#endif
+template void DimacsParser::parse_DIMACS(FILE* input_stream);
diff --git a/src/sat/cryptominisat2/DimacsParser.h b/src/sat/cryptominisat2/DimacsParser.h
new file mode 100644 (file)
index 0000000..f264637
--- /dev/null
@@ -0,0 +1,76 @@
+/*****************************************************************************
+MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+Original code by MiniSat authors are under an MIT licence.
+Modifications for CryptoMiniSat are under GPLv3 licence.
+******************************************************************************/
+
+#ifndef DIMACSPARSER_H
+#define DIMACSPARSER_H
+
+#include <string>
+#include "SolverTypes.h"
+#include "constants.h"
+#include "StreamBuffer.h"
+#include "Vec.h"
+
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#ifndef DISABLE_ZLIB
+#include <zlib.h>
+#endif // DISABLE_ZLIB
+
+#ifdef STATS_NEEDED
+#include "Logger.h"
+#endif //STATS_NEEDED
+
+class Solver;
+
+/**
+@brief Parses up a DIMACS file that my be zipped
+*/
+class DimacsParser
+{
+    public:
+        DimacsParser(Solver* solver, const bool debugLib, const bool debugNewVar, const bool grouping, const bool addAsLearnt = false);
+
+        template <class T>
+        void parse_DIMACS(T input_stream);
+
+    private:
+        void parse_DIMACS_main(StreamBuffer& in);
+        void skipWhitespace(StreamBuffer& in);
+        void skipLine(StreamBuffer& in);
+        std::string untilEnd(StreamBuffer& in);
+        int parseInt(StreamBuffer& in, uint32_t& len);
+        float parseFloat(StreamBuffer& in);
+        void parseString(StreamBuffer& in, std::string& str);
+        void readClause(StreamBuffer& in, vec<Lit>& lits);
+        void parseClauseParameters(StreamBuffer& in, bool& learnt, uint32_t& glue, float& miniSatAct);
+        void readFullClause(StreamBuffer& in);
+        bool match(StreamBuffer& in, const char* str);
+        void printHeader(StreamBuffer& in);
+        void parseComments(StreamBuffer& in, const std::string str);
+        std::string stringify(uint32_t x);
+
+
+        Solver *solver;
+        const bool debugLib;
+        const bool debugNewVar;
+        const bool grouping;
+        const bool addAsLearnt;
+
+        uint32_t debugLibPart; ///<printing partial solutions to debugLibPart1..N.output when "debugLib" is set to TRUE
+        uint32_t groupId;
+        vec<Lit> lits; ///<To reduce temporary creation overhead
+        uint32_t numLearntClauses; ///<Number of learnt non-xor clauses added
+        uint32_t numNormClauses; ///<Number of non-learnt, non-xor claues added
+        uint32_t numXorClauses; ///<Number of non-learnt xor clauses added
+};
+
+#endif //DIMACSPARSER_H
diff --git a/src/sat/cryptominisat2/FailedLitSearcher.cpp b/src/sat/cryptominisat2/FailedLitSearcher.cpp
new file mode 100644 (file)
index 0000000..b9faf14
--- /dev/null
@@ -0,0 +1,699 @@
+/**************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#include "FailedLitSearcher.h"
+
+#include <iomanip>
+#include <utility>
+#include <set>
+using std::make_pair;
+using std::set;
+
+#include "Solver.h"
+#include "ClauseCleaner.h"
+#include "time_mem.h"
+#include "VarReplacer.h"
+#include "ClauseCleaner.h"
+#include "StateSaver.h"
+#include "CompleteDetachReattacher.h"
+
+#ifdef _MSC_VER
+#define __builtin_prefetch(a,b,c)
+#endif //_MSC_VER
+
+//#define VERBOSE_DEUBUG
+
+/**
+@brief Sets up variables that are used between calls to search()
+*/
+FailedLitSearcher::FailedLitSearcher(Solver& _solver):
+    solver(_solver)
+    , tmpPs(2)
+    , totalTime(0)
+    , numPropsMultiplier(1.0)
+    , lastTimeFoundTruths(0)
+    , numCalls(0)
+{
+    lastTimeStopped = solver.mtrand.randInt(solver.nVars());
+}
+
+/**
+@brief Initialises datastructures for 2-long xor finding by shortening longer xors
+*/
+void FailedLitSearcher::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);
+        }
+    }
+}
+
+/**
+@brief Remove the assinged vars from the xors added by addFromSolver()
+
+The thus shortened xors are then treated if they are 2-long and if they
+appear twice: by propagating "var" and by propagating "~var"
+*/
+inline void FailedLitSearcher::removeVarFromXors(const Var var)
+{
+    vector<uint32_t>& occ = occur[var];
+    if (occ.empty()) return;
+
+    for (uint32_t *it = &occ[0], *end = it + occ.size(); it != end; it++) {
+        xorClauseSizes[*it]--;
+        if (!xorClauseTouched[*it]) {
+            xorClauseTouched.setBit(*it);
+            investigateXor.push(*it);
+        }
+    }
+}
+
+/**
+@brief Undoes what removeVarFromXors() has done
+*/
+inline void FailedLitSearcher::addVarFromXors(const Var var)
+{
+    vector<uint32_t>& occ = occur[var];
+    if (occ.empty()) return;
+
+    for (uint32_t *it = &occ[0], *end = it + occ.size(); it != end; it++) {
+        xorClauseSizes[*it]++;
+    }
+}
+
+/**
+@brief Returns the 2-long xor clause that has been made of the longer xor-clause under current assignement
+
+We KNOW that the xorclause "c" passed as a parameter must be 2-long. We just
+need it so that we can work with it. We KNOW it's 2-long because of the
+data structures and functions in place
+
+@p[in] c MUST be a 2-long xor clause under current assignement
+*/
+const FailedLitSearcher::TwoLongXor FailedLitSearcher::getTwoLongXor(const XorClause& c)
+{
+    TwoLongXor tmp;
+    uint32_t num = 0;
+    tmp.inverted = c.xorEqualFalse();
+
+    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;
+}
+
+/**
+@brief The main function. Initialises data and calls tryBoth() for heavy-lifting
+
+It sets up the ground for tryBoth() and calls it as many times as it sees fit.
+One afther the other, the different optimisations' data structures are
+initialised, and their limits are set. Then tryBoth is called in two different
+forms: somewhat sequentially on varaibles x...z and then on randomly picked
+variables.
+*/
+const bool FailedLitSearcher::search()
+{
+    assert(solver.decisionLevel() == 0);
+    if (solver.nVars() == 0) return solver.ok;
+
+    uint64_t numProps = 100 * 1000000;
+    uint64_t numPropsDifferent = (double)numProps*2.0;
+
+    solver.testAllClauseAttach();
+    double myTime = cpuTime();
+    uint32_t origHeapSize = solver.order_heap.size();
+    StateSaver savedState(solver);
+    Heap<Solver::VarOrderLt> order_heap_copy(solver.order_heap); //for hyperbin
+
+    //General Stats
+    numFailed = 0;
+    goodBothSame = 0;
+    numCalls++;
+
+    //If failed var searching is going good, do successively more and more of it
+    if ((double)lastTimeFoundTruths > (double)solver.order_heap.size() * 0.10) numPropsMultiplier = std::max(numPropsMultiplier*1.3, 2.0);
+    else numPropsMultiplier = 1.0;
+    numProps = (uint64_t) ((double)numProps * numPropsMultiplier * solver.conf.failedLitMultiplier);
+
+    //For BothSame
+    propagated.resize(solver.nVars(), 0);
+    propValue.resize(solver.nVars(), 0);
+
+    //For calculating how many variables have really been set
+    origTrailSize = solver.trail.size();
+
+    //For 2-long xor (rule 6 of  Equivalent literal propagation in the DLL procedure by Chu-Min Li)
+    toReplaceBefore = solver.varReplacer->getNewToReplaceVars();
+    lastTrailSize = solver.trail.size();
+    binXorFind = true;
+    twoLongXors.clear();
+    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);
+    newBinXor = 0;
+
+    //For 2-long xor through Le Berre paper
+    bothInvert = 0;
+
+    //For HyperBin
+    addedBin = 0;
+    unPropagatedBin.resize(solver.nVars(), 0);
+    needToVisit.resize(solver.nVars(), 0);
+    dontRemoveAncestor.resize(solver.nVars(), 0);
+    hyperbinProps = 0;
+    maxHyperBinProps = numProps/4;
+    removedUselessLearnt = 0;
+    removedUselessNonLearnt = 0;
+
+    //uint32_t fromBin;
+    origProps = solver.propagations;
+    uint32_t i;
+    for (i = 0; i < solver.nVars(); i++) {
+        Var var = (lastTimeStopped + i) % solver.nVars();
+        if (solver.assigns[var] != l_Undef || !solver.decision_var[var])
+            continue;
+        if (solver.propagations >= origProps + numProps)
+            break;
+        if (!tryBoth(Lit(var, false), Lit(var, true)))
+            goto end;
+    }
+    lastTimeStopped = (lastTimeStopped + i) % solver.nVars();
+
+    origProps = solver.propagations;
+    while (!order_heap_copy.empty()) {
+        Var var = order_heap_copy.removeMin();
+        if (solver.assigns[var] != l_Undef || !solver.decision_var[var])
+            continue;
+        if (solver.propagations >= origProps + numPropsDifferent)  {
+            break;
+        }
+        if (!tryBoth(Lit(var, false), Lit(var, true)))
+            goto end;
+    }
+
+    if (solver.conf.verbosity  >= 1) printResults(myTime);
+
+
+end:
+    bool removedOldLearnts = false;
+
+    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) {
+            CompleteDetachReatacher reattacher(solver);
+            reattacher.detachNonBinsNonTris(true);
+            const bool ret = reattacher.reattachNonBins();
+            release_assert(ret == true);
+            removedOldLearnts = true;
+        } else {
+            solver.clauseCleaner->removeAndCleanAll();
+        }
+        if (solver.conf.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::endl;
+        }
+    }
+
+    lastTimeFoundTruths = solver.trail.size() - origTrailSize;
+    totalTime += cpuTime() - myTime;
+
+    savedState.restore();
+
+    solver.testAllClauseAttach();
+    return solver.ok;
+}
+
+
+/**
+@brief Prints results of failed litaral probing
+
+Printed:
+1) Num failed lits
+2) Num lits that have been propagated by both "var" and "~var"
+3) 2-long Xor clauses that have been found because when propagating "var" and
+   "~var", they have been produced by normal xor-clauses shortening to this xor
+   clause
+4) If var1 propagates var2 and ~var1 propagates ~var2, then var=var2, and this
+   is a 2-long XOR clause
+5) Number of propagations
+6) Time in seconds
+*/
+void FailedLitSearcher::printResults(const double myTime) const
+{
+    std::cout << "c Flit: "<< std::setw(5) << numFailed <<
+    " Blit: " << std::setw(6) << goodBothSame <<
+    " bXBeca: " << std::setw(4) << newBinXor <<
+    " bXProp: " << std::setw(4) << bothInvert <<
+    " Bins:" << std::setw(7) << addedBin <<
+    " BRemL:" << std::setw(7) << removedUselessLearnt <<
+    " BRemN:" << std::setw(7) << removedUselessNonLearnt <<
+    " P: " << std::setw(4) << std::fixed << std::setprecision(1) << (double)(solver.propagations - origProps)/1000000.0  << "M"
+    " T: " << std::setw(5) << std::fixed << std::setprecision(2) << cpuTime() - myTime
+    << std::endl;
+}
+
+/**
+@brief The main function of search() doing almost everything in this class
+
+Tries to branch on both lit1 and lit2 and then both-propagates them, fail-lits
+them, and hyper-bin resolves them, etc. It is imperative that from the
+SAT point of view, EITHER lit1 or lit2 MUST hold. So, if lit1 = ~lit2, it's OK.
+Also, if there is a binary clause 'lit1 or lit2' it's also OK.
+*/
+const bool FailedLitSearcher::tryBoth(const Lit lit1, const Lit lit2)
+{
+    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();
+    bothSame.clear();
+    binXorToAdd.clear();
+    #ifdef DEBUG_HYPERBIN
+    assert(propagatedVars.empty());
+    assert(unPropagatedBin.isZero());
+    #endif //DEBUG_HYPERBIN
+    #ifdef DEBUG_USELESS_LEARNT_BIN_REMOVAL
+    dontRemoveAncestor.isZero();
+    assert(uselessBin.empty());
+    #endif
+
+    solver.newDecisionLevel();
+    solver.uncheckedEnqueueLight(lit1);
+    failed = (!solver.propagate(false).isNULL());
+    if (failed) {
+        solver.cancelUntilLight();
+        numFailed++;
+        solver.uncheckedEnqueue(~lit1);
+        solver.ok = (solver.propagate(false).isNULL());
+        if (!solver.ok) return false;
+        return true;
+    }
+
+    assert(solver.decisionLevel() > 0);
+    Solver::TransCache& lit1OTFCache = solver.transOTFCache[(~lit1).toInt()];
+    if (solver.conf.doCacheOTFSSR) {
+        lit1OTFCache.conflictLastUpdated = solver.conflicts;
+        lit1OTFCache.lits.clear();
+    }
+    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.conf.doHyperBinRes) {
+            unPropagatedBin.setBit(x);
+            propagatedVars.push(x);
+        }
+
+        if (solver.assigns[x].getBool()) propValue.setBit(x);
+        else propValue.clearBit(x);
+
+        if (binXorFind) removeVarFromXors(x);
+        if (solver.conf.doCacheOTFSSR && c != (int)solver.trail_lim[0]) {
+            lit1OTFCache.lits.push_back(solver.trail[c]);
+        }
+    }
+
+    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.cancelUntilLight();
+
+    //Hyper-binary resolution, and its accompanying data-structure cleaning
+    if (solver.conf.doHyperBinRes) {
+        if (hyperbinProps < maxHyperBinProps) hyperBinResolution(lit1);
+        unPropagatedBin.removeThese(propagatedVars);
+        propagatedVars.clear();
+    }
+
+    #ifdef DEBUG_HYPERBIN
+    assert(propagatedVars.empty());
+    assert(unPropagatedBin.isZero());
+    #endif //DEBUG_HYPERBIN
+
+    solver.newDecisionLevel();
+    solver.uncheckedEnqueueLight(lit2);
+    failed = (!solver.propagate(false).isNULL());
+    if (failed) {
+        solver.cancelUntilLight();
+        numFailed++;
+        solver.uncheckedEnqueue(~lit2);
+        solver.ok = (solver.propagate(false).isNULL());
+        if (!solver.ok) return false;
+        return true;
+    }
+
+    assert(solver.decisionLevel() > 0);
+    Solver::TransCache& lit2OTFCache = solver.transOTFCache[(~lit2).toInt()];
+    if (solver.conf.doCacheOTFSSR) {
+        lit2OTFCache.conflictLastUpdated = solver.conflicts;
+        lit2OTFCache.lits.clear();
+    }
+    for (int c = solver.trail.size()-1; c >= (int)solver.trail_lim[0]; c--) {
+        Var x  = solver.trail[c].var();
+        if (propagated[x]) {
+            if (propValue[x] == solver.assigns[x].getBool()) {
+                //they both imply the same
+                bothSame.push(Lit(x, !propValue[x]));
+            } else if (c != (int)solver.trail_lim[0]) {
+                bool invert;
+                if (lit1.var() == lit2.var()) {
+                    assert(lit1.sign() == false && lit2.sign() == true);
+                    tmpPs[0] = Lit(lit1.var(), false);
+                    tmpPs[1] = Lit(x, false);
+                    invert = propValue[x];
+                } else {
+                    tmpPs[0] = Lit(lit1.var(), false);
+                    tmpPs[1] = Lit(lit2.var(), false);
+                    invert = lit1.sign() ^ lit2.sign();
+                }
+                binXorToAdd.push_back(BinXorToAdd(tmpPs[0], tmpPs[1], invert, 0));
+                bothInvert += solver.varReplacer->getNewToReplaceVars() - toReplaceBefore;
+                toReplaceBefore = solver.varReplacer->getNewToReplaceVars();
+            }
+        }
+
+        if (solver.conf.doHyperBinRes) {
+            unPropagatedBin.setBit(x);
+            propagatedVars.push(x);
+        }
+
+        if (solver.assigns[x].getBool()) propValue.setBit(x);
+        else propValue.clearBit(x);
+
+        if (binXorFind) removeVarFromXors(x);
+        if (solver.conf.doCacheOTFSSR && c != (int)solver.trail_lim[0]) {
+            lit2OTFCache.lits.push_back(solver.trail[c]);
+        }
+    }
+
+    //We now add the two-long xors that have been found through longer
+    //xor-shortening
+    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()) {
+                        tmpPs[0] = Lit(tmp.var[0], false);
+                        tmpPs[1] = Lit(tmp.var[1], false);
+                        binXorToAdd.push_back(BinXorToAdd(tmpPs[0], tmpPs[1], tmp.inverted, solver.xorclauses[*it]->getGroup()));
+                        newBinXor += solver.varReplacer->getNewToReplaceVars() - toReplaceBefore;
+                        toReplaceBefore = solver.varReplacer->getNewToReplaceVars();
+                    }
+                }
+            }
+        }
+        for (int c = solver.trail.size()-1; c >= (int)solver.trail_lim[0]; c--) {
+            addVarFromXors(solver.trail[c].var());
+        }
+    }
+    solver.cancelUntilLight();
+
+    if (solver.conf.doHyperBinRes) {
+        if (hyperbinProps < maxHyperBinProps) hyperBinResolution(lit2);
+        unPropagatedBin.removeThese(propagatedVars);
+        propagatedVars.clear();
+    }
+
+    for(uint32_t i = 0; i != bothSame.size(); i++) {
+        solver.uncheckedEnqueue(bothSame[i]);
+    }
+    goodBothSame += bothSame.size();
+    solver.ok = (solver.propagate(false).isNULL());
+    if (!solver.ok) return false;
+
+    for (uint32_t i = 0; i < binXorToAdd.size(); i++) {
+        tmpPs[0] = binXorToAdd[i].lit1;
+        tmpPs[1] = binXorToAdd[i].lit2;
+        solver.addXorClauseInt(tmpPs, binXorToAdd[i].isEqualFalse, binXorToAdd[i].group);
+        tmpPs.clear();
+        tmpPs.growTo(2);
+        if (!solver.ok) return false;
+    }
+
+    return true;
+}
+
+/**
+@brief Adds hyper-binary clauses
+
+At this point, unPropagatedBin is set, and propagatedVars is filled with lits
+that have been propagated. Here, we propagate ONLY at the binary level,
+and compare with propagatedVars and unPropagatedBin. If they match, it's OK. If
+not, then we add the relevant binary clauses at the right point. The "right"
+point is the point which has the highest in-degree. We approximated the degrees
+beforehand with orderLits()
+*/
+void FailedLitSearcher::hyperBinResolution(const Lit lit)
+{
+    #ifdef VERBOSE_DEBUG
+    std::cout << "Checking one BTC vs UP" << std::endl;
+    #endif //VERBOSE_DEBUG
+
+    #ifdef DEBUG_HYPERBIN
+    assert(needToVisit.isZero());
+    #endif //DEBUG_HYPERBIN
+
+    uint64_t oldProps = solver.propagations;
+    vec<Lit> toVisit;
+    uint64_t extraTime = 0;
+
+    solver.newDecisionLevel();
+    solver.uncheckedEnqueueLight2(lit, 0, lit_Undef, false);
+    failed = (!solver.propagateBin(uselessBin).isNULL());
+    assert(!failed);
+
+    if (solver.conf.doRemUselessLBins && !uselessBin.empty()) {
+        for (const Lit *it = uselessBin.getData(), *end = uselessBin.getDataEnd(); it != end; it++) {
+            if (dontRemoveAncestor[it->var()]) continue;
+
+            extraTime += solver.watches[lit.toInt()].size()/2;
+            extraTime += solver.watches[(~*it).toInt()].size()/2;
+            if (findWBin(solver.watches, ~lit, *it, true)) {
+                removeWBin(solver.watches[lit.toInt()], *it, true);
+                removeWBin(solver.watches[(~*it).toInt()], ~lit, true);
+                solver.learnts_literals -= 2;
+                solver.numBins--;
+                removedUselessLearnt++;
+            } else if (!solver.binPropData[it->var()].learntLeadHere) {
+                removeWBin(solver.watches[lit.toInt()], *it, false);
+                removeWBin(solver.watches[(~*it).toInt()], ~lit, false);
+                solver.clauses_literals -= 2;
+                solver.numBins--;
+                removedUselessNonLearnt++;
+            } else {
+                continue;
+            }
+
+            Var ancestorVar = solver.binPropData[it->var()].lev2Ancestor.var();
+            dontRemoveAncestor.setBit(ancestorVar);
+            toClearDontRemoveAcestor.push(ancestorVar);
+        }
+        dontRemoveAncestor.removeThese(toClearDontRemoveAcestor);
+        toClearDontRemoveAcestor.clear();
+    }
+    uselessBin.clear();
+    #ifdef DEBUG_USELESS_LEARNT_BIN_REMOVAL
+    dontRemoveAncestor.isZero();
+    uint64_t backupProps;
+    #endif
+
+    assert(solver.decisionLevel() > 0);
+    int32_t difference = propagatedVars.size() - (solver.trail.size()-solver.trail_lim[0]);
+    #ifdef DEBUG_USELESS_LEARNT_BIN_REMOVAL
+    uint32_t propagated = solver.trail.size()-solver.trail_lim[0];
+    #endif
+    assert(difference >= 0);
+    if (difference == 0) {
+        solver.cancelUntilLight();
+        goto end;
+    }
+    for (int c = solver.trail.size()-1; c >= (int)solver.trail_lim[0]; c--) {
+        Lit x = solver.trail[c];
+        unPropagatedBin.clearBit(x.var());
+        toVisit.push(x);
+        needToVisit.setBit(x.var());
+    }
+    std::sort(toVisit.getData(), toVisit.getDataEnd(), LitOrder2(solver.binPropData));
+    solver.cancelUntilLight();
+
+    #ifdef DEBUG_USELESS_LEARNT_BIN_REMOVAL
+    backupProps = solver.propagations;
+    if (solver.conf.doRemUselessLBins) {
+        solver.newDecisionLevel();
+        solver.uncheckedEnqueueLight2(lit, 0, lit_Undef, false);
+        failed = (!solver.propagateBin(uselessBin).isNULL());
+        uselessBin.clear();
+        for (int c = solver.trail.size()-1; c >= (int)solver.trail_lim[0]; c--) {
+            Lit x = solver.trail[c];
+        }
+        assert(!failed);
+        assert(propagated == solver.trail.size()-solver.trail_lim[0]);
+        solver.cancelUntilLight();
+    }
+    solver.propagations = backupProps;
+    #endif
+
+    /*************************
+    //To check that the ordering is the right way
+    // --> i.e. to avoid mistake present in Glucose's ordering*/
+    /*std::cout << "--------------------" << std::endl;
+    for (uint32_t i = 0; i < toVisit.size(); i++) {
+        std::cout << "i:" << std::setw(8) << i
+        << " level:" << std::setw(3) << solver.binPropData[toVisit[i].var()].lev
+        << " lit : " << toVisit[i]
+        << std::endl;
+    }
+    std::cout << "difference: " << difference << std::endl;
+    std::cout << "--------------------" << std::endl;*/
+    /***************************/
+
+    //difference between UP and BTC is in unPropagatedBin
+    for (Lit *l = toVisit.getData(), *end = toVisit.getDataEnd(); l != end; l++) {
+        if (!needToVisit[l->var()]) continue;
+        fillImplies(*l);
+        for (const Var *var = myImpliesSet.getData(), *end2 = myImpliesSet.getDataEnd(); var != end2; var++) {
+
+            /*Lit otherLit = Lit(*var, !propValue[*var]);
+            std::cout << "adding Bin:" << (~*l) << " , " << otherLit << std::endl;
+            std::cout << PropByFull(solver.reason[otherLit.var()], solver.failBinLit, solver.clauseAllocator) << std::endl;*/
+
+            addBin(~*l, Lit(*var, !propValue[*var]));
+            unPropagatedBin.clearBit(*var);
+            difference--;
+        }
+        assert(difference >= 0);
+        myImpliesSet.clear();
+
+        if (difference == 0) {
+            needToVisit.setZero();
+            goto end;
+        }
+    }
+    #ifdef DEBUG_HYPERBIN
+    assert(unPropagatedBin.isZero());
+    assert(needToVisit.isZero());
+    #endif //DEBUG_HYPERBIN
+
+    end:
+    hyperbinProps += solver.propagations - oldProps + extraTime;
+}
+
+/**
+@brief Fills myimplies and myimpliesSet by propagating lit at a binary level
+
+Used to check which variables are propagated by a certain literal when
+propagating it only at the binary level
+@p[in] the literal to be propagated at the binary level
+*/
+void FailedLitSearcher::fillImplies(const Lit lit)
+{
+    solver.newDecisionLevel();
+    solver.uncheckedEnqueueLight(lit);
+    failed = (!solver.propagate(false).isNULL());
+    assert(!failed);
+
+    assert(solver.decisionLevel() > 0);
+    for (int sublevel = solver.trail.size()-1; sublevel >= (int)solver.trail_lim[0]; sublevel--) {
+        Var x = solver.trail[sublevel].var();
+        needToVisit.clearBit(x);
+        if (unPropagatedBin[x]) {
+            myImpliesSet.push(x);
+        }
+    }
+    solver.cancelUntilLight();
+}
+
+/**
+@brief Adds a learnt binary clause to the solver
+
+Used by hyperBinResolution() to add the newly discovered clauses
+*/
+void FailedLitSearcher::addBin(const Lit lit1, const Lit lit2)
+{
+    #ifdef VERBOSE_DEBUG
+    std::cout << "Adding extra bin: " << lit1 << " " << lit2 << std::endl;
+    #endif //VERBOSE_DEBUG
+
+    assert(solver.value(lit1) == l_Undef);
+    assert(solver.value(lit2) == l_Undef);
+    tmpPs[0] = lit1;
+    tmpPs[1] = lit2;
+
+    solver.addClauseInt(tmpPs, 0 , true);
+    tmpPs.clear();
+    tmpPs.growTo(2);
+    assert(solver.ok);
+    addedBin++;
+}
diff --git a/src/sat/cryptominisat2/FailedLitSearcher.h b/src/sat/cryptominisat2/FailedLitSearcher.h
new file mode 100644 (file)
index 0000000..b092497
--- /dev/null
@@ -0,0 +1,229 @@
+/***************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+****************************************************************************/
+
+#ifndef FAILEDLITSEARCHER_H
+#define FAILEDLITSEARCHER_H
+
+#include <set>
+#include <map>
+#include <vector>
+using std::set;
+using std::map;
+using std::vector;
+
+#include "SolverTypes.h"
+#include "Clause.h"
+#include "BitArray.h"
+class Solver;
+
+/**
+@brief Responsible for doing failed var searching and related algorithms
+
+Performs in seach():
+1) Failed lit searching
+2) Searching for lits that have been propagated by both "var" and "~var"
+3) 2-long Xor clauses that have been found because when propagating "var" and
+   "~var", they have been produced by normal xor-clauses shortening to this xor
+   clause
+4) If var1 propagates var2 and ~var1 propagates ~var2, then var=var2, and this
+   is a 2-long XOR clause, this 2-long xor is added
+5) Hyper-binary resolution
+
+Perfoms in asymmBranch(): asymmetric branching, heuristically. Best paper
+on this is 'Vivifying Propositional Clausal Formulae', though we do it much
+more heuristically
+*/
+class FailedLitSearcher {
+    public:
+        FailedLitSearcher(Solver& _solver);
+
+        const bool search();
+        const double getTotalTime() const;
+
+    private:
+        //Main
+        const bool tryBoth(const Lit lit1, const Lit lit2);
+        const bool tryAll(const Lit* begin, const Lit* end);
+        void printResults(const double myTime) const;
+
+        Solver& solver; ///<The solver we are updating&working with
+
+        bool failed; ///<For checking that a specific propagation failed (=conflict). It is used in many places
+
+        //bothprop finding
+        BitArray propagated; ///<These lits have been propagated by propagating the lit picked
+        BitArray propValue; ///<The value (0 or 1) of the lits propagated set in "propagated"
+        /**
+        @brief Lits that have been propagated to the same value both by "var" and "~var"
+
+        value that the literal has been propagated to is available in propValue
+        */
+        vec<Lit> bothSame;
+
+        //2-long xor-finding
+        /**
+        @brief used to find 2-long xor by shortening longer xors to this size
+
+        -# We propagate "var" and record all xors that become 2-long
+        -# We propagate "~var" and record all xors that become 2-long
+        -# if (1) and (2) have something in common, we add it as a variable
+        replacement instruction
+
+        We must be able to order these 2-long xors, so that we can search
+        for matching couples fast. This class is used for that
+        */
+        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 BinXorToAdd
+        {
+            public:
+                BinXorToAdd(const Lit _lit1, const Lit _lit2, const bool _isEqualFalse, const uint32_t _group) :
+                    lit1(_lit1)
+                    , lit2(_lit2)
+                    , isEqualFalse(_isEqualFalse)
+                    , group(_group)
+                {}
+                Lit lit1;
+                Lit lit2;
+                bool isEqualFalse;
+                uint32_t group;
+        };
+        const TwoLongXor getTwoLongXor(const XorClause& c);
+        void addFromSolver(const vec<XorClause*>& cs);
+        void removeVarFromXors(const Var var);
+        void addVarFromXors(const Var var);
+
+        uint32_t newBinXor;
+        vec<uint32_t> xorClauseSizes;
+        vector<vector<uint32_t> > occur; ///<Occurence list for XORs. Indexed by variables
+        BitArray xorClauseTouched;
+        vec<uint32_t> investigateXor;
+        std::set<TwoLongXor> twoLongXors;
+        bool binXorFind;
+        uint32_t lastTrailSize;
+        vector<BinXorToAdd> binXorToAdd;
+
+        /**
+        @brief Num. 2-long xor-found through Le Berre paper
+
+        In case:
+        -# (a->b, ~a->~b) -> a=b
+        -#  binary clause (a,c) exists:  (a->g, c->~g) -> a = ~c
+        */
+        uint32_t bothInvert;
+
+        //finding HyperBins
+        struct LitOrder2
+        {
+            LitOrder2(const vec<BinPropData>& _binPropData) :
+            binPropData(_binPropData)
+            {}
+
+            const bool operator () (const Lit x, const Lit y) const
+            {
+                return binPropData[x.var()].lev > binPropData[y.var()].lev;
+            }
+
+            const vec<BinPropData>& binPropData;
+        };
+        uint32_t addedBin;
+        void hyperBinResolution(const Lit lit);
+        BitArray unPropagatedBin;
+        BitArray needToVisit;
+        vec<Var> propagatedVars;
+        void addBin(const Lit lit1, const Lit lit2);
+        void fillImplies(const Lit lit);
+        vec<Var> myImpliesSet; ///<variables set in myimplies
+        uint64_t hyperbinProps; ///<Number of bogoprops done by the hyper-binary resolution function hyperBinResolution()
+
+        //bin-removal within hyper-bin-res
+        vec<Lit> uselessBin;
+        uint32_t removedUselessLearnt;
+        uint32_t removedUselessNonLearnt;
+        BitArray dontRemoveAncestor;
+        vec<Var> toClearDontRemoveAcestor;
+        /**
+        @brief Controls hyper-binary resolution's time-usage
+
+        Don't do more than this many propagations within hyperBinResolution()
+        */
+        uint64_t maxHyperBinProps;
+
+        //Temporaries
+        vec<Lit> tmpPs;
+
+        //State for this run
+        /**
+        @brief Records num. var-replacement istructions between 2-long xor findings through longer xor shortening
+
+        Finding 2-long xor claues by shortening is fine, but sometimes we find
+        the same thing, or find something that is trivially a consequence of
+        other 2-long xors that we already know. To filter out these bogus
+        "findigs" from the statistics reported, we save in this value the
+        real var-replacement insturctions before and after the 2-long xor
+        finding through longer xor-shortening, and then compare the changes
+        made
+        */
+        uint32_t toReplaceBefore;
+        uint32_t origTrailSize; ///<Records num. of 0-depth assignments at the start-up of search()
+        uint64_t origProps;     ///<Records num. of bogoprops at the start-up of search()
+        uint32_t numFailed;     ///<Records num. of failed literals during search()
+        uint32_t goodBothSame;  ///<Records num. of literals that have been propagated to the same value by both "var" and "~var"
+
+        //State between runs
+        double totalTime;
+        double numPropsMultiplier; ///<If last time we called search() all went fine, then this is incremented, so we do more searching this time
+        uint32_t lastTimeFoundTruths; ///<Records how many unit clauses we found last time we called search()
+        uint32_t numCalls; ///<Number of times search() has been called
+        uint32_t lastTimeStopped;
+};
+
+inline const double FailedLitSearcher::getTotalTime() const
+{
+    return totalTime;
+}
+
+
+#endif //FAILEDVARSEARCHER_H
+
diff --git a/src/sat/cryptominisat2/FailedVarSearcher.cpp b/src/sat/cryptominisat2/FailedVarSearcher.cpp
deleted file mode 100644 (file)
index 0b98a12..0000000
+++ /dev/null
@@ -1,765 +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 <http://www.gnu.org/licenses/>.
-**************************************************************************************************/
-
-#include "FailedVarSearcher.h"
-
-#include <iomanip>
-#include <utility>
-#include <set>
-using std::make_pair;
-using std::set;
-
-#include "Solver.h"
-#include "ClauseCleaner.h"
-#include "time_mem.h"
-#include "VarReplacer.h"
-#include "ClauseCleaner.h"
-#include "StateSaver.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)
-    , tmpPs(2)
-    , finishedLastTimeVar(true)
-    , lastTimeWentUntilVar(0)
-    , finishedLastTimeBin(true)
-    , lastTimeWentUntilBin(0)
-    , numPropsMultiplier(1.0)
-    , lastTimeFoundTruths(0)
-    , numCalls(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<uint32_t>& occ = occur[var];
-    if (occ.empty()) return;
-    
-    for (uint32_t *it = &occ[0], *end = it + occ.size(); it != end; it++) {
-        xorClauseSizes[*it]--;
-        if (!xorClauseTouched[*it]) {
-            xorClauseTouched.setBit(*it);
-            investigateXor.push(*it);
-        }
-    }
-}
-
-inline void FailedVarSearcher::addVarFromXors(const Var var)
-{
-    vector<uint32_t>& occ = occur[var];
-    if (occ.empty()) return;
-    
-    for (uint32_t *it = &occ[0], *end = it + occ.size(); it != end; it++) {
-        xorClauseSizes[*it]++;
-    }
-}
-
-const TwoLongXor FailedVarSearcher::getTwoLongXor(const XorClause& c)
-{
-    TwoLongXor tmp;
-    uint32_t num = 0;
-    tmp.inverted = c.xor_clause_inverted();
-    
-    for(const Lit *l = c.getData(), *end = l + c.size(); l != end; l++) {
-        if (solver.assigns[l->var()] == l_Undef) {
-            assert(num < 2);
-            tmp.var[num] = l->var();
-            num++;
-        } else {
-            tmp.inverted ^= (solver.assigns[l->var()] == l_True);
-        }
-    }
-    
-    #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);
-    solver.testAllClauseAttach();
-    double myTime = cpuTime();
-    uint32_t origHeapSize = solver.order_heap.size();
-    StateSaver savedState(solver);
-    Heap<Solver::VarOrderLt> order_heap_copy(solver.order_heap); //for hyperbin
-    uint64_t origBinClauses = solver.binaryClauses.size();
-    
-    //General Stats
-    numFailed = 0;
-    goodBothSame = 0;
-    numCalls++;
-    
-    //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 *3);
-    
-    //For BothSame
-    propagated.resize(solver.nVars(), 0);
-    propValue.resize(solver.nVars(), 0);
-    
-    //For calculating how many variables have really been set
-    origTrailSize = solver.trail.size();
-    
-    //For 2-long xor (rule 6 of  Equivalent literal propagation in the DLL procedure by Chu-Min Li)
-    toReplaceBefore = solver.varReplacer->getNewToReplaceVars();
-    lastTrailSize = solver.trail.size();
-    binXorFind = true;
-    twoLongXors.clear();
-    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);
-    newBinXor = 0;
-    
-    //For 2-long xor through Le Berre paper
-    bothInvert = 0;
-
-    //For HyperBin
-    unPropagatedBin.resize(solver.nVars(), 0);
-    myimplies.resize(solver.nVars(), 0);
-    hyperbinProps = 0;
-    if (solver.addExtraBins && !orderLits()) return false;
-    maxHyperBinProps = numProps/8;
-    
-    //uint32_t fromBin;
-    uint32_t fromVar;
-    if (finishedLastTimeVar || lastTimeWentUntilVar >= solver.nVars())
-        fromVar = 0;
-    else
-        fromVar = lastTimeWentUntilVar;
-    finishedLastTimeVar = true;
-    lastTimeWentUntilVar = solver.nVars();
-    origProps = solver.propagations;
-    for (Var var = fromVar; var < solver.nVars(); var++) {
-        if (solver.assigns[var] != l_Undef || !solver.decision_var[var])
-            continue;
-        if (solver.propagations - origProps >= numProps)  {
-            finishedLastTimeVar = false;
-            lastTimeWentUntilVar = var;
-            break;
-        }
-        if (!tryBoth(Lit(var, false), Lit(var, true)))
-            goto end;
-    }
-
-    numProps = (double)numProps * 1.2;
-    hyperbinProps = 0;
-    while (!order_heap_copy.empty()) {
-        Var var = order_heap_copy.removeMin();
-        if (solver.assigns[var] != l_Undef || !solver.decision_var[var])
-            continue;
-        if (solver.propagations - origProps >= numProps)  {
-            finishedLastTimeVar = false;
-            lastTimeWentUntilVar = var;
-            break;
-        }
-        if (!tryBoth(Lit(var, false), Lit(var, true)))
-            goto end;
-    }
-    
-    /*if (solver.verbosity >= 1) printResults(myTime);
-    if (finishedLastTimeBin || lastTimeWentUntilBin >= solver.binaryClauses.size())
-        fromBin = 0;
-    else
-        fromBin = lastTimeWentUntilBin;
-    finishedLastTimeBin = true;
-    lastTimeWentUntilBin = solver.nVars();
-    for (uint32_t binCl = 0; binCl < solver.binaryClauses.size(); binCl++) {
-        if ((double)(solver.propagations - origProps) >= 1.1*(double)numProps)  {
-            finishedLastTimeBin = false;
-            lastTimeWentUntilBin = binCl;
-            break;
-        }
-        
-        Clause& cl = *solver.binaryClauses[binCl];
-        if (solver.value(cl[0]) == l_Undef && solver.value(cl[1]) == l_Undef) {
-            if (!tryBoth(cl[0], cl[1]))
-                goto end;
-        }
-    }*/
-    
-    /*for (Clause **it = solver.clauses.getData(), **end = solver.clauses.getDataEnd(); it != end; it++) {
-        Clause& c = **it;
-        for (uint i = 0; i < c.size(); i++) {
-            if (solver.value(c[i]) != l_Undef) goto next;
-        }
-        if (!tryAll(c.getData(), c.getDataEnd()))
-            goto end;
-        
-        next:;
-    }
-    
-    for (Clause **it = solver.learnts.getData(), **end = solver.learnts.getDataEnd(); it != end; it++) {
-        Clause& c = **it;
-        for (uint i = 0; i < c.size(); i++) {
-            if (solver.value(c[i]) != l_Undef) goto next2;
-        }
-        if (!tryAll(c.getData(), c.getDataEnd()))
-            goto end;
-        
-        next2:;
-    }*/
-
-end:
-    bool removedOldLearnts = false;
-    binClauseAdded = solver.binaryClauses.size() - origBinClauses;
-    //Print results
-    if (solver.verbosity >= 1) printResults(myTime);
-    
-    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) {
-            completelyDetachAndReattach();
-            removedOldLearnts = true;
-        } 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(39) << " | " << std::endl;
-        }
-    }
-    
-    lastTimeFoundTruths = solver.trail.size() - origTrailSize;
-
-    savedState.restore();
-    
-    solver.testAllClauseAttach();
-    return solver.ok;
-}
-
-void FailedVarSearcher::completelyDetachAndReattach()
-{
-    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);
-}
-
-void FailedVarSearcher::printResults(const double myTime) const
-{
-    std::cout << "c |  Flit: "<< std::setw(5) << numFailed <<
-    " Blit: " << std::setw(6) << goodBothSame <<
-    " bXBeca: " << std::setw(4) << newBinXor <<
-    " bXProp: " << std::setw(4) << bothInvert <<
-    " Bins:" << std::setw(7) << binClauseAdded <<
-    " P: " << std::setw(4) << std::fixed << std::setprecision(1) << (double)(solver.propagations - origProps)/1000000.0  << "M"
-    " T: " << std::setw(5) << std::fixed << std::setprecision(2) << cpuTime() - myTime <<
-    std::setw(5) << " |" << std::endl;
-}
-
-const bool FailedVarSearcher::orderLits()
-{
-    uint64_t oldProps = solver.propagations;
-    double myTime = cpuTime();
-    uint32_t numChecked = 0;
-    if (litDegrees.size() != solver.nVars())
-        litDegrees.resize(solver.nVars()*2, 0);
-    BitArray alreadyTested;
-    alreadyTested.resize(solver.nVars()*2, 0);
-    uint32_t i;
-    
-    for (i = 0; i < 3*solver.order_heap.size(); i++) {
-        if (solver.propagations - oldProps > 1500000) break;
-        Var var = solver.order_heap[solver.mtrand.randInt(solver.order_heap.size()-1)];
-        if (solver.assigns[var] != l_Undef || !solver.decision_var[var]) continue;
-
-        Lit randLit(var, solver.mtrand.randInt(1));
-        if (alreadyTested[randLit.toInt()]) continue;
-        alreadyTested.setBit(randLit.toInt());
-
-        numChecked++;
-        solver.newDecisionLevel();
-        solver.uncheckedEnqueueLight(randLit);
-        failed = (!solver.propagateBin().isNULL());
-        if (failed) {
-            solver.cancelUntil(0);
-            solver.uncheckedEnqueue(~randLit);
-            solver.ok = (solver.propagate().isNULL());
-            if (!solver.ok) return false;
-            continue;
-        }
-        assert(solver.decisionLevel() > 0);
-        for (int c = solver.trail.size()-1; c > (int)solver.trail_lim[0]; c--) {
-            Lit x = solver.trail[c];
-            litDegrees[x.toInt()]++;
-        }
-        solver.cancelUntil(0);
-    }
-    if (solver.verbosity >= 1) {
-        std::cout << "c binary deg approx."
-        << " time: " << std::fixed << std::setw(5) << std::setprecision(2) << cpuTime() - myTime << " s"
-        << " num checked: " << std::setw(6) << numChecked
-        << " i: " << std::setw(7) << i
-        << " props: " << std::setw(4) << (solver.propagations - oldProps)/1000 << "k"
-        << std::setw(13) << " |" << std::endl;
-    }
-    solver.propagations = oldProps;
-
-    return true;
-}
-
-const bool FailedVarSearcher::tryBoth(const Lit lit1, const Lit lit2)
-{
-    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();
-    propagatedVars.clear();
-    unPropagatedBin.setZero();
-    bothSame.clear();
-    
-    solver.newDecisionLevel();
-    solver.uncheckedEnqueueLight(lit1);
-    failed = (!solver.propagate().isNULL());
-    if (failed) {
-        solver.cancelUntil(0);
-        numFailed++;
-        solver.uncheckedEnqueue(~lit1);
-        solver.ok = (solver.propagate(false).isNULL());
-        if (!solver.ok) return false;
-        return true;
-    } 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.addExtraBins) {
-                unPropagatedBin.setBit(x);
-                propagatedVars.push(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);
-    }
-
-    if (solver.addExtraBins && hyperbinProps < maxHyperBinProps) addBinClauses(lit1);
-    propagatedVars.clear();
-    unPropagatedBin.setZero();
-    
-    solver.newDecisionLevel();
-    solver.uncheckedEnqueueLight(lit2);
-    failed = (!solver.propagate().isNULL());
-    if (failed) {
-        solver.cancelUntil(0);
-        numFailed++;
-        solver.uncheckedEnqueue(~lit2);
-        solver.ok = (solver.propagate(false).isNULL());
-        if (!solver.ok) return false;
-        return true;
-    } 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]) {
-                if (solver.addExtraBins) {
-                    unPropagatedBin.setBit(x);
-                    propagatedVars.push(x);
-                }
-                if (propValue[x] == solver.assigns[x].getBool()) {
-                    //they both imply the same
-                    bothSame.push(Lit(x, !propValue[x]));
-                } else if (c != (int)solver.trail_lim[0]) {
-                    bool invert;
-                    if (lit1.var() == lit2.var()) {
-                        assert(lit1.sign() == false && lit2.sign() == true);
-                        tmpPs[0] = Lit(lit1.var(), false);
-                        tmpPs[1] = Lit(x, false);
-                        invert = propValue[x];
-                    } else {
-                        tmpPs[0] = Lit(lit1.var(), false);
-                        tmpPs[1] = Lit(lit2.var(), false);
-                        invert = lit1.sign() ^ lit2.sign();
-                    }
-                    if (!solver.varReplacer->replace(tmpPs, invert, 0))
-                        return false;
-                    bothInvert += solver.varReplacer->getNewToReplaceVars() - toReplaceBefore;
-                    toReplaceBefore = solver.varReplacer->getNewToReplaceVars();
-                }
-            }
-            if (solver.assigns[x].getBool()) propValue.setBit(x);
-            else propValue.clearBit(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()) {
-                            tmpPs[0] = Lit(tmp.var[0], false);
-                            tmpPs[1] = Lit(tmp.var[1], false);
-                            if (!solver.varReplacer->replace(tmpPs, tmp.inverted, solver.xorclauses[*it]->getGroup()))
-                                return false;
-                            newBinXor += solver.varReplacer->getNewToReplaceVars() - toReplaceBefore;
-                            toReplaceBefore = solver.varReplacer->getNewToReplaceVars();
-                        }
-                    }
-                }
-            }
-            for (int c = solver.trail.size()-1; c >= (int)solver.trail_lim[0]; c--) {
-                addVarFromXors(solver.trail[c].var());
-            }
-        }
-        
-        solver.cancelUntil(0);
-    }
-
-    if (solver.addExtraBins && hyperbinProps < maxHyperBinProps) addBinClauses(lit2);
-    
-    for(uint32_t i = 0; i != bothSame.size(); i++) {
-        solver.uncheckedEnqueue(bothSame[i]);
-    }
-    goodBothSame += bothSame.size();
-    solver.ok = (solver.propagate(false).isNULL());
-    if (!solver.ok) return false;
-    
-    return true;
-}
-
-struct litOrder
-{
-    litOrder(const vector<uint32_t>& _litDegrees) :
-    litDegrees(_litDegrees)
-    {}
-    
-    bool operator () (const Lit& x, const Lit& y) {
-        return litDegrees[x.toInt()] > litDegrees[y.toInt()];
-    }
-    
-    const vector<uint32_t>& litDegrees;
-};
-
-void FailedVarSearcher::addBinClauses(const Lit& lit)
-{
-    uint64_t oldProps = solver.propagations;
-    #ifdef VERBOSE_DEBUG
-    std::cout << "Checking one BTC vs UP" << std::endl;
-    #endif //VERBOSE_DEBUG
-    vec<Lit> toVisit;
-    
-    solver.newDecisionLevel();
-    solver.uncheckedEnqueueLight(lit);
-    failed = (!solver.propagateBin().isNULL());
-    assert(!failed);
-
-    assert(solver.decisionLevel() > 0);
-    if (propagatedVars.size() - (solver.trail.size()-solver.trail_lim[0]) == 0) {
-        solver.cancelUntil(0);
-        goto end;
-    }
-    for (int c = solver.trail.size()-1; c >= (int)solver.trail_lim[0]; c--) {
-        Lit x = solver.trail[c];
-        unPropagatedBin.clearBit(x.var());
-        toVisit.push(x);
-    }
-    solver.cancelUntil(0);
-
-    std::sort(toVisit.getData(), toVisit.getDataEnd(), litOrder(litDegrees));
-    /*************************
-    //To check that the ordering is the right way
-    // --> i.e. to avoid mistake present in Glucose's ordering
-    for (uint32_t i = 0; i < toVisit.size(); i++) {
-        std::cout << "i:" << std::setw(8) << i << " degree:" << litDegrees[toVisit[i].toInt()] << std::endl;
-    }
-    std::cout << std::endl;
-    ***************************/
-
-    //difference between UP and BTC is in unPropagatedBin
-    for (Lit *l = toVisit.getData(), *end = toVisit.getDataEnd(); l != end; l++) {
-        #ifdef VERBOSE_DEBUG
-        std::cout << "Checking visit level " << end-l-1 << std::endl;
-        uint32_t thisLevel = 0;
-        #endif //VERBOSE_DEBUG
-        fillImplies(*l);
-        if (unPropagatedBin.nothingInCommon(myimplies)) goto next;
-        for (const Var *var = propagatedVars.getData(), *end2 = propagatedVars.getDataEnd(); var != end2; var++) {
-            if (unPropagatedBin[*var] && myimplies[*var]) {
-                #ifdef VERBOSE_DEBUG
-                thisLevel++;
-                #endif //VERBOSE_DEBUG
-                addBin(~*l, Lit(*var, !propValue[*var]));
-                unPropagatedBin.removeThese(myImpliesSet);
-                if (unPropagatedBin.isZero()) {
-                    myimplies.removeThese(myImpliesSet);
-                    myImpliesSet.clear();
-                    goto end;
-                }
-            }
-        }
-        next:
-        myimplies.removeThese(myImpliesSet);
-        myImpliesSet.clear();
-        #ifdef VERBOSE_DEBUG
-        if (thisLevel > 0) {
-            std::cout << "Added " << thisLevel << " level diff:" << end-l-1 << std::endl;
-        }
-        #endif //VERBOSE_DEBUG
-    }
-    assert(unPropagatedBin.isZero());
-
-    end:
-    hyperbinProps += solver.propagations - oldProps;
-}
-
-void FailedVarSearcher::fillImplies(const Lit& lit)
-{
-    solver.newDecisionLevel();
-    solver.uncheckedEnqueue(lit);
-    failed = (!solver.propagate().isNULL());
-    assert(!failed);
-    
-    assert(solver.decisionLevel() > 0);
-    for (int c = solver.trail.size()-1; c >= (int)solver.trail_lim[0]; c--) {
-        Lit x = solver.trail[c];
-        myimplies.setBit(x.var());
-        myImpliesSet.push(x.var());
-    }
-    solver.cancelUntil(0);
-}
-
-void FailedVarSearcher::addBin(const Lit& lit1, const Lit& lit2)
-{
-    #ifdef VERBOSE_DEBUG
-    std::cout << "Adding extra bin: ";
-    lit1.print(); std::cout << " "; lit2.printFull();
-    #endif //VERBOSE_DEBUG
-
-    tmpPs[0] = lit1;
-    tmpPs[1] = lit2;
-    solver.addLearntClause(tmpPs, 0, 0);
-    tmpPs.growTo(2);
-    assert(solver.ok);
-}
-
-template<class T>
-inline void FailedVarSearcher::cleanAndAttachClauses(vec<T*>& cs)
-{
-    T **i = cs.getData();
-    T **j = i;
-    for (T **end = cs.getDataEnd(); i != end; i++) {
-        if (cleanClause(**i)) {
-            solver.attachClause(**i);
-            *j++ = *i;
-        } else {
-            solver.clauseAllocator.clauseFree(*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) {
-        ps[0] = ps[0].unsign();
-        ps[1] = ps[1].unsign();
-        solver.varReplacer->replace(ps, ps.xor_clause_inverted(), ps.getGroup());
-        return false;
-    }
-    
-    return true;
-}
-
-/***************
-UNTESTED CODE
-*****************
-const bool FailedVarSearcher::tryAll(const Lit* begin, const Lit* end)
-{
-    propagated.setZero();
-    BitArray propagated2;
-    propagated2.resize(solver.nVars(), 0);
-    propValue.resize(solver.nVars(), 0);
-    bool first = true;
-    bool last = false;
-
-    for (const Lit *it = begin; it != end; it++, first = false) {
-        if (it+1 == end) last = true;
-
-        if (!first && !last) propagated2.setZero();
-        solver.newDecisionLevel();
-        solver.uncheckedEnqueue(*it);
-        failed = (solver.propagate(false) != NULL);
-        if (failed) {
-            solver.cancelUntil(0);
-            numFailed++;
-            solver.uncheckedEnqueue(~(*it));
-            solver.ok = (solver.propagate(false) == NULL);
-            if (!solver.ok) return false;
-            return true;
-        } 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 (last) {
-                    if (propagated[x] && propValue[x] == solver.assigns[x].getBool())
-                        bothSame.push_back(make_pair(x, !propValue[x]));
-                } else {
-                    if (first) {
-                        propagated.setBit(x);
-                        if (solver.assigns[x].getBool())
-                            propValue.setBit(x);
-                        else
-                            propValue.clearBit(x);
-                    } else if (propValue[x] == solver.assigns[x].getBool()) {
-                        propagated2.setBit(x);
-                    }
-                }
-            }
-            solver.cancelUntil(0);
-        }
-        if (!last && !first) {
-            propagated &= propagated2;
-            if (propagated.isZero()) return true;
-        }
-    }
-
-    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) return false;
-
-    return true;
-}
-**************
-Untested code end
-**************/
-
-}; //NAMESPACE MINISAT
diff --git a/src/sat/cryptominisat2/FailedVarSearcher.h b/src/sat/cryptominisat2/FailedVarSearcher.h
deleted file mode 100644 (file)
index 5ea4c1e..0000000
+++ /dev/null
@@ -1,155 +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 <http://www.gnu.org/licenses/>.
-**************************************************************************************************/
-
-#ifndef FAILEDVARSEARCHER_H
-#define FAILEDVARSEARCHER_H
-
-#include <set>
-#include <map>
-using std::map;
-
-#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:
-        //For 2-long xor
-        const TwoLongXor getTwoLongXor(const XorClause& c);
-        void addFromSolver(const vec<XorClause*>& cs);
-        uint32_t newBinXor;
-        
-        //For detach&re-attach (when lots of vars found)
-        template<class T>
-        void cleanAndAttachClauses(vec<T*>& cs);
-        const bool cleanClause(Clause& ps);
-        const bool cleanClause(XorClause& ps);
-        void completelyDetachAndReattach();
-
-        //For re-adding old removed learnt clauses
-        const bool readdRemovedLearnts();
-        void removeOldLearnts();
-        
-        //Main
-        const bool tryBoth(const Lit lit1, const Lit lit2);
-        const bool tryAll(const Lit* begin, const Lit* end);
-        void printResults(const double myTime) const;
-        
-        Solver& solver;
-        
-        //For failure
-        bool failed;
-        
-        //bothprop finding
-        BitArray propagated;
-        BitArray propValue;
-        vec<Lit> bothSame;
-        
-        //2-long xor-finding
-        vec<uint32_t> xorClauseSizes;
-        vector<vector<uint32_t> > occur;
-        void removeVarFromXors(const Var var);
-        void addVarFromXors(const Var var);
-        BitArray xorClauseTouched;
-        vec<uint32_t> investigateXor;
-        std::set<TwoLongXor> twoLongXors;
-        bool binXorFind;
-        uint32_t lastTrailSize;
-        
-        //2-long xor-finding no.2 through
-        // 1) (a->b, ~a->~b) -> a=b
-        // 2) binary clause (a,c):  (a->g, c->~g) -> a = ~c
-        uint32_t bothInvert;
-
-        //finding HyperBins
-        void addBinClauses(const Lit& lit);
-        BitArray unPropagatedBin;
-        vec<Var> propagatedVars;
-        void addBin(const Lit& lit1, const Lit& lit2);
-        void fillImplies(const Lit& lit);
-        BitArray myimplies;
-        vec<Var> myImpliesSet;
-        uint64_t hyperbinProps;
-        vector<uint32_t> litDegrees;
-        const bool orderLits();
-        uint64_t maxHyperBinProps;
-        uint64_t binClauseAdded;
-
-        //Temporaries
-        vec<Lit> tmpPs;
-        
-        //State for this run
-        uint32_t toReplaceBefore;
-        uint32_t origTrailSize;
-        uint64_t origProps;
-        uint32_t numFailed;
-        uint32_t goodBothSame;
-        
-        //State between runs
-        bool finishedLastTimeVar;
-        uint32_t lastTimeWentUntilVar;
-        bool finishedLastTimeBin;
-        uint32_t lastTimeWentUntilBin;
-        
-        double numPropsMultiplier;
-        uint32_t lastTimeFoundTruths;
-
-        uint32_t numCalls;
-};
-
-}; //NAMESPACE MINISAT
-
-#endif //FAILEDVARSEARCHER_H
-
index 84d8a6c49231f97cb288b6b15258b40621a8a0fb..95f2e4ef9f4f915a6bdd3aedcc31e95a62678794 100644 (file)
@@ -21,10 +21,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "VarReplacer.h"
 #include <algorithm>
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 FindUndef::FindUndef(Solver& _solver) :
     solver(_solver)
     , isPotentialSum(0)
@@ -37,7 +33,7 @@ void FindUndef::fillPotential()
     
     while(trail > 0) {
         assert(trail < (int)solver.trail_lim.size());
-        uint at = solver.trail_lim[trail];
+        uint32_t at = solver.trail_lim[trail];
         
         assert(at > 0);
         Var v = solver.trail[at].var();
@@ -71,7 +67,7 @@ void FindUndef::fillPotential()
 
 void FindUndef::unboundIsPotentials()
 {
-    for (uint i = 0; i < isPotential.size(); i++)
+    for (uint32_t i = 0; i < isPotential.size(); i++)
         if (isPotential[i])
             solver.assigns[i] = l_Undef;
 }
@@ -79,19 +75,19 @@ void FindUndef::unboundIsPotentials()
 void FindUndef::moveBinToNormal()
 {
     binPosition = solver.clauses.size();
-    for (uint i = 0; i != solver.binaryClauses.size(); i++)
+    for (uint32_t 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++)
+    for (uint32_t i = binPosition; i != solver.clauses.size(); i++)
         solver.binaryClauses.push(solver.clauses[i]);
     solver.clauses.shrink(solver.clauses.size() - binPosition);
 }
 
-const uint FindUndef::unRoll()
+const uint32_t FindUndef::unRoll()
 {
     if (solver.decisionLevel() == 0) return 0;
     
@@ -107,7 +103,7 @@ const uint FindUndef::unRoll()
         
         uint32_t maximum = 0;
         Var v = var_Undef;
-        for (uint i = 0; i < isPotential.size(); i++) {
+        for (uint32_t i = 0; i < isPotential.size(); i++) {
             if (isPotential[i] && satisfies[i] >= maximum) {
                 maximum = satisfies[i];
                 v = i;
@@ -131,7 +127,7 @@ bool FindUndef::updateTables()
 {
     bool allSat = true;
     
-    uint i = 0;
+    uint32_t i = 0;
     for (Clause** it = solver.clauses.getData(), **end = it + solver.clauses.size(); it != end; it++, i++) {
         if (dontLookAtClause[i])
             continue;
@@ -139,7 +135,7 @@ bool FindUndef::updateTables()
         Clause& c = **it;
         bool definitelyOK = false;
         Var v = var_Undef;
-        uint numTrue = 0;
+        uint32_t numTrue = 0;
         for (Lit *l = c.getData(), *end = l + c.size(); l != end; l++) {
             if (solver.value(*l) == l_True) {
                 if (!isPotential[l->var()]) {
@@ -174,4 +170,3 @@ bool FindUndef::updateTables()
     return allSat;
 }
 
-}; //NAMESPACE MINISAT
index d3612ac6ff315030cd3ac0222dda70fc123f63f9..e9a1bca2772b65784f2412d69e164a72207db4e1 100644 (file)
@@ -28,14 +28,10 @@ using std::vector;
 
 #include "Solver.h"
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 class FindUndef {
     public:
         FindUndef(Solver& _solver);
-        const uint unRoll();
+        const uint32_t unRoll();
         
     private:
         Solver& solver;
@@ -54,6 +50,4 @@ class FindUndef {
         
 };
 
-}; //NAMESPACE MINISAT
-
-#endif //
\ No newline at end of file
+#endif //
index e5edc506f4737f2b6b5ec13cdb220d7c5f271163..3088a0f82060193a1e6b61557ab74f1bba32123c 100644 (file)
@@ -1,4 +1,4 @@
-/***********************************************************************************
+/***************************************************************************
 CryptoMiniSat -- Copyright (c) 2009 Mate Soos
 
 This program is free software: you can redistribute it and/or modify
@@ -13,7 +13,7 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
-**************************************************************************************************/
+*****************************************************************************/
 
 #include "Gaussian.h"
 
@@ -22,32 +22,24 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "Clause.h"
 #include <algorithm>
 #include "ClauseCleaner.h"
+#include "VarReplacer.h"
+#include "DataSync.h"
 
 using std::ostream;
 using std::cout;
 using std::endl;
 
+//#define VERBOSE_DEBUG
+//#define DEBUG_GAUSS
+
 #ifdef VERBOSE_DEBUG
 #include <iterator>
 #endif
 
-namespace MINISAT
-{
-using namespace MINISAT;
 static const uint16_t unassigned_col = std::numeric_limits<uint16_t>::max();
 static const Var unassigned_var = std::numeric_limits<Var>::max();
 
-ostream& operator << (ostream& os, const vec<Lit>& 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<XorClause*>& _xorclauses) :
+Gaussian::Gaussian(Solver& _solver, const GaussConf& _config, const uint32_t _matrix_no, const vector<XorClause*>& _xorclauses) :
         solver(_solver)
         , config(_config)
         , matrix_no(_matrix_no)
@@ -64,15 +56,15 @@ Gaussian::Gaussian(Solver& _solver, const GaussianConfig& _config, const uint _m
 
 Gaussian::~Gaussian()
 {
-    for (uint i = 0; i < clauses_toclear.size(); i++)
+    for (uint32_t i = 0; i < clauses_toclear.size(); i++)
         solver.clauseAllocator.clauseFree(clauses_toclear[i].first);
 }
 
 inline void Gaussian::set_matrixset_to_cur()
 {
-    uint level = solver.decisionLevel() / config.only_nth_gauss_save;
+    uint32_t 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
@@ -82,22 +74,26 @@ inline void Gaussian::set_matrixset_to_cur()
 const bool Gaussian::full_init()
 {
     assert(solver.ok);
-    
+    assert(solver.decisionLevel() == 0);
+
     if (!should_init()) return true;
     reset_stats();
     uint32_t last_trail_size = solver.trail.size();
-    
+
     bool do_again_gauss = true;
     while (do_again_gauss) {
         do_again_gauss = false;
         solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses);
         if (!solver.ok) return false;
         init();
-        Clause* confl;
+        PropBy confl;
         gaussian_ret g = gaussian(confl);
         switch (g) {
         case unit_conflict:
         case conflict:
+            #ifdef VERBOSE_DEBUG
+            cout << "(" << matrix_no << ")conflict at level 0" << std::endl;
+            #endif
             solver.ok = false;
             return false;
         case unit_propagation:
@@ -125,7 +121,7 @@ void Gaussian::init()
         badlevel = 0;
         return;
     }
-    
+
     matrix_sets.clear();
     matrix_sets.push_back(cur_matrixset);
     gauss_last_level = solver.trail.size();
@@ -137,28 +133,28 @@ void Gaussian::init()
     #endif
 }
 
-uint Gaussian::select_columnorder(vector<uint16_t>& var_to_col, matrixset& origMat)
+uint32_t Gaussian::select_columnorder(vector<uint16_t>& var_to_col, matrixset& origMat)
 {
     var_to_col.resize(solver.nVars(), unassigned_col);
 
-    uint num_xorclauses  = 0;
+    uint32_t num_xorclauses  = 0;
     for (uint32_t i = 0; i != xorclauses.size(); i++) {
         XorClause& c = *xorclauses[i];
-        if (c.removed()) continue;
+        if (c.getRemoved()) continue;
         num_xorclauses++;
-        
-        for (uint i2 = 0; i2 < c.size(); i2++) {
+
+        for (uint32_t 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++)
+
+    uint32_t largest_used_var = 0;
+    for (uint32_t 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);
 
@@ -180,11 +176,11 @@ uint Gaussian::select_columnorder(vector<uint16_t>& var_to_col, matrixset& origM
         else v = vars[iterReduceIt++];
         if (var_to_col[v] == 1) {
             #ifdef DEBUG_GAUSS
-            vector<uint>::iterator it =
+            vector<uint32_t>::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);
@@ -192,7 +188,7 @@ uint Gaussian::select_columnorder(vector<uint16_t>& var_to_col, matrixset& origM
     }
 
     //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++) {
+    for (uint32_t 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;
@@ -200,9 +196,9 @@ uint Gaussian::select_columnorder(vector<uint16_t>& var_to_col, matrixset& origM
         }
     }
 
-    #ifdef VERBOSE_DEBUG
+    #ifdef VERBOSE_DEBUG_MORE
     cout << "(" << matrix_no << ")col_to_var:";
-    std::copy(origMat.col_to_var.begin(), origMat.col_to_var.end(), std::ostream_iterator<uint>(cout, ","));
+    std::copy(origMat.col_to_var.begin(), origMat.col_to_var.end(), std::ostream_iterator<uint32_t>(cout, ","));
     cout << endl;
     #endif
 
@@ -220,12 +216,12 @@ void Gaussian::fill_matrix(matrixset& 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());
+    memset(&changed_rows[0], 0, sizeof(unsigned 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);
@@ -234,10 +230,10 @@ void Gaussian::fill_matrix(matrixset& origMat)
     cout << "(" << matrix_no << ")matrix size:" << origMat.num_rows << "," << origMat.num_cols << endl;
     #endif
 
-    uint matrix_row = 0;
+    uint32_t matrix_row = 0;
     for (uint32_t i = 0; i != xorclauses.size(); i++) {
         const XorClause& c = *xorclauses[i];
-        if (c.removed()) continue;
+        if (c.getRemoved()) continue;
 
         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);
@@ -246,23 +242,23 @@ void Gaussian::fill_matrix(matrixset& origMat)
     assert(origMat.num_rows == matrix_row);
 }
 
-void Gaussian::update_matrix_col(matrixset& m, const Var var, const uint col)
+void Gaussian::update_matrix_col(matrixset& m, const Var var, const uint32_t col)
 {
-    #ifdef VERBOSE_DEBUG
+    #ifdef VERBOSE_DEBUG_MORE
     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;
+    uint32_t row_num = 0;
 
     if (solver.assigns[var].getBool()) {
-        for (uint end = m.last_one_in_col[col];  row_num != end; ++this_row, row_num++) {
+        for (uint32_t 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();
@@ -270,7 +266,7 @@ void Gaussian::update_matrix_col(matrixset& m, const Var var, const uint col)
             }
         }
     } else {
-        for (uint end = m.last_one_in_col[col];  row_num != end; ++this_row, row_num++) {
+        for (uint32_t 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);
@@ -294,19 +290,21 @@ void Gaussian::update_matrix_by_col_all(matrixset& m)
 {
     #ifdef VERBOSE_DEBUG
     cout << "(" << matrix_no << ")Updating matrix." << endl;
+    #ifdef VERBOSE_DEBUG_MORE
     print_matrix(m);
-    uint num_updated = 0;
     #endif
-    
+    uint32_t 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;
+    memset(&changed_rows[0], 0, sizeof(unsigned char)*changed_rows.size());
+
+    uint32_t last = 0;
+    uint32_t 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);
@@ -318,16 +316,18 @@ void Gaussian::update_matrix_by_col_all(matrixset& m)
             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;
+    #ifdef VERBOSE_DEBUG_MORE
     print_matrix(m);
     #endif
-    
+    #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();
@@ -341,7 +341,7 @@ inline void Gaussian::update_last_one_in_col(matrixset& m)
         *i = m.num_rows;
 }
 
-Gaussian::gaussian_ret Gaussian::gaussian(Clause*& confl)
+Gaussian::gaussian_ret Gaussian::gaussian(PropBy& confl)
 {
     if (solver.decisionLevel() >= badlevel)
         return nothing;
@@ -350,8 +350,8 @@ Gaussian::gaussian_ret Gaussian::gaussian(Clause*& confl)
         #ifdef VERBOSE_DEBUG
         cout << "(" << matrix_no << ")matrix needs copy before update" << endl;
         #endif
-        
-        const uint level = solver.decisionLevel() / config.only_nth_gauss_save;
+
+        const uint32_t level = solver.decisionLevel() / config.only_nth_gauss_save;
         assert(level < matrix_sets.size());
         cur_matrixset = matrix_sets[level];
     }
@@ -363,32 +363,32 @@ Gaussian::gaussian_ret Gaussian::gaussian(Clause*& confl)
     badlevel = UINT_MAX;
 
     propagatable_rows.clear();
-    uint conflict_row = UINT_MAX;
-    uint last_row = eliminate(cur_matrixset, conflict_row);
+    uint32_t conflict_row = UINT_MAX;
+    uint32_t 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;
+        uint32_t maxlevel = UINT_MAX;
+        uint32_t size = UINT_MAX;
+        uint32_t 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));
+    assert(ret == conflict || ret == unit_conflict || nothing_to_propagate(cur_matrixset));
     #endif
-    
+
     if (!cur_matrixset.num_cols || !cur_matrixset.num_rows) {
         badlevel = solver.decisionLevel();
-        return nothing;
+        return ret;
     }
-    
+
     if (ret == nothing &&
         solver.decisionLevel() % config.only_nth_gauss_save == 0)
         set_matrixset_to_cur();
@@ -405,40 +405,42 @@ Gaussian::gaussian_ret Gaussian::gaussian(Clause*& confl)
     return ret;
 }
 
-uint Gaussian::eliminate(matrixset& m, uint& conflict_row)
+uint32_t Gaussian::eliminate(matrixset& m, uint32_t& conflict_row)
 {
     #ifdef VERBOSE_DEBUG
     cout << "(" << matrix_no << ")";
     cout << "Starting elimination" << endl;
     cout << "m.least_column_changed:" << m.least_column_changed << endl;
+    #ifdef VERBOSE_DEBUG_MORE
     print_last_one_in_cols(m);
-    
-    uint number_of_row_additions = 0;
-    uint no_exchanged = 0;
     #endif
-    
+
+    uint32_t number_of_row_additions = 0;
+    uint32_t 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 = (config.iterativeReduce) ? m.least_column_changed + 1 : 0;
+    uint32_t i = 0;
+    uint32_t j = (config.iterativeReduce) ? m.least_column_changed + 1 : 0;
     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])
@@ -446,19 +448,19 @@ uint Gaussian::eliminate(matrixset& m, uint& conflict_row)
         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
@@ -485,7 +487,7 @@ uint Gaussian::eliminate(matrixset& m, uint& conflict_row)
                 #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;
@@ -509,7 +511,7 @@ uint Gaussian::eliminate(matrixset& m, uint& conflict_row)
                 #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()) {
@@ -527,7 +529,7 @@ uint Gaussian::eliminate(matrixset& m, uint& conflict_row)
         }
         j++;
     }
-    
+
     finish:
 
     m.least_column_changed = INT_MAX;
@@ -535,20 +537,22 @@ uint Gaussian::eliminate(matrixset& m, uint& conflict_row)
     #ifdef VERBOSE_DEBUG
     cout << "Finished elimination" << endl;
     cout << "Returning with i,j:" << i << ", " << j << "(" << m.num_rows << ", " << m.num_cols << ")" << endl;
+    #ifdef VERBOSE_DEBUG_MORE
     print_matrix(m);
     print_last_one_in_cols(m);
+    #endif
     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;
+    uint32_t row = 0;
+    uint32_t 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
+            #ifdef VERBOSE_DEBUG_MORE
             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);
@@ -561,29 +565,28 @@ uint Gaussian::eliminate(matrixset& m, uint& conflict_row)
     return i;
 }
 
-Gaussian::gaussian_ret Gaussian::handle_matrix_confl(Clause*& confl, const matrixset& m, const uint size, const uint maxlevel, const uint best_row)
+Gaussian::gaussian_ret Gaussian::handle_matrix_confl(PropBy& confl, const matrixset& m, const uint32_t size, const uint32_t maxlevel, const uint32_t best_row)
 {
     assert(best_row != UINT_MAX);
 
-    m.matrix.getVarsetAt(best_row).fill(tmp_clause, solver.assigns, col_to_var_original);
-    confl = (Clause*)solver.clauseAllocator.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) {
-        solver.ok = false;
-        return unit_conflict;
-    }
+    const bool xorEqualFalse = !m.matrix.getVarsetAt(best_row).is_true();
+    const bool wasUndef = m.matrix.getVarsetAt(best_row).fill(tmp_clause, solver.assigns, col_to_var_original);
+    assert(!wasUndef);
 
-    assert(cla.size() >= 2);
     #ifdef VERBOSE_DEBUG
-    cout << "(" << matrix_no << ")Found conflict:";
-    cla.plainPrint();
+    cout << "(" << matrix_no << ")matrix confl clause:"
+    << tmp_clause << " , "
+    << "xorEqualFalse:" << xorEqualFalse << std::endl;
     #endif
 
+    if (tmp_clause.size() <= 1) {
+        if (!tmp_clause.empty()) {
+            confl = PropBy(tmp_clause[0]);
+            solver.ok = false;
+        } else confl = PropBy();
+        return unit_conflict;
+    }
+
     if (maxlevel != solver.decisionLevel()) {
         #ifdef STATS_NEEDED
         if (solver.dynamic_behaviour_analysis)
@@ -591,38 +594,81 @@ Gaussian::gaussian_ret Gaussian::handle_matrix_confl(Clause*& confl, const matri
         #endif
         solver.cancelUntil(maxlevel);
     }
-    const uint curr_dec_level = solver.decisionLevel();
+    const uint32_t 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()] == (int32_t)curr_dec_level) {
-        uint tmp = find_sublevel(cla[i].var());
-        if (tmp >= maxsublevel) {
-            maxsublevel = tmp;
-            maxsublevel_at = i;
+
+    uint32_t maxsublevel = 0;
+    if (tmp_clause.size() == 2) {
+        Lit lit1 = tmp_clause[0];
+        Lit lit2 = tmp_clause[1];
+
+        solver.watches[(~lit1).toInt()].push(Watched(lit2, true));
+        solver.watches[(~lit2).toInt()].push(Watched(lit1, true));
+        solver.numBins++;
+        solver.learnts_literals += 2;
+        solver.dataSync->signalNewBinClause(lit1, lit2);
+
+        lit1 = ~lit1;
+        lit2 = ~lit2;
+        solver.watches[(~lit2).toInt()].push(Watched(lit1, true));
+        solver.watches[(~lit1).toInt()].push(Watched(lit2, true));
+        solver.numBins++;
+        solver.learnts_literals += 2;
+        solver.dataSync->signalNewBinClause(lit1, lit2);
+
+        lit1 = ~lit1;
+        lit2 = ~lit2;
+        uint32_t sublevel1 = find_sublevel(lit1.var());
+        uint32_t sublevel2 = find_sublevel(lit2.var());
+        if (sublevel1 > sublevel2) {
+            maxsublevel = sublevel1;
+            std::swap(lit1, lit2);
+        } else {
+            maxsublevel = sublevel2;
+        }
+
+        confl = PropBy(lit1);
+        solver.failBinLit = lit2;
+    } else {
+        Clause* conflPtr = (Clause*)solver.clauseAllocator.XorClause_new(tmp_clause, xorEqualFalse, solver.learnt_clause_group++);
+        confl = solver.clauseAllocator.getOffset(conflPtr);
+        Clause& cla = *conflPtr;
+
+        #ifdef STATS_NEEDED
+        if (solver.dynamic_behaviour_analysis)
+            solver.logger.set_group_name(cla.getGroup(), "learnt gauss clause");
+        #endif
+
+        uint32_t maxsublevel_at = UINT_MAX;
+        for (uint32_t i = 0, size = cla.size(); i != size; i++) if (solver.level[cla[i].var()] == (int32_t)curr_dec_level) {
+            uint32_t 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;
     }
-    #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)
+Gaussian::gaussian_ret Gaussian::handle_matrix_prop_and_confl(matrixset& m, uint32_t last_row, PropBy& confl)
 {
     int32_t maxlevel = std::numeric_limits<int32_t>::max();
-    uint size = UINT_MAX;
-    uint best_row = UINT_MAX;
+    uint32_t size = UINT_MAX;
+    uint32_t best_row = UINT_MAX;
 
-    for (uint row = last_row; row != m.num_rows; row++) {
+    for (uint32_t row = last_row; row != m.num_rows; row++) {
         #ifdef DEBUG_GAUSS
         assert(m.matrix.getMatrixAt(row).isZero());
         #endif
@@ -637,7 +683,7 @@ Gaussian::gaussian_ret Gaussian::handle_matrix_prop_and_confl(matrixset& m, uint
     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
@@ -646,8 +692,8 @@ Gaussian::gaussian_ret Gaussian::handle_matrix_prop_and_confl(matrixset& m, uint
 
     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++ ) {
+    uint32_t num_props = 0;
+    for (const uint32_t* 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++;
@@ -665,25 +711,25 @@ Gaussian::gaussian_ret Gaussian::handle_matrix_prop_and_confl(matrixset& m, uint
     return ret;
 }
 
-uint Gaussian::find_sublevel(const Var v) const
+uint32_t 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 until_sublevel)
+void Gaussian::cancel_until_sublevel(const uint32_t until_sublevel)
 {
     #ifdef VERBOSE_DEBUG
     cout << "(" << matrix_no << ")Canceling until sublevel " << until_sublevel << endl;
     #endif
-    
+
     for (vector<Gaussian*>::iterator gauss = solver.gauss_matrixes.begin(), end= solver.gauss_matrixes.end(); gauss != end; gauss++)
         if (*gauss != this) (*gauss)->canceling(until_sublevel);
 
@@ -700,13 +746,13 @@ void Gaussian::cancel_until_sublevel(const uint until_sublevel)
         solver.insertVarOrder(var);
     }
     solver.trail.shrink(solver.trail.size() - until_sublevel);
-    
+
     #ifdef VERBOSE_DEBUG
     cout << "(" << matrix_no << ")Canceling sublevel finished." << endl;
     #endif
 }
 
-void Gaussian::analyse_confl(const matrixset& m, const uint row, int32_t& maxlevel, uint& size, uint& best_row) const
+void Gaussian::analyse_confl(const matrixset& m, const uint32_t row, int32_t& maxlevel, uint32_t& size, uint32_t& best_row) const
 {
     assert(row < m.num_rows);
 
@@ -714,17 +760,19 @@ void Gaussian::analyse_confl(const matrixset& m, const uint row, int32_t& maxlev
     #ifdef VERBOSE_DEBUG
     cout << "(" << matrix_no << ")matrix conflict found!" << endl;
     cout << "(" << matrix_no << ")conflict clause's vars: ";
+    #ifdef VERBOSE_DEBUG_MORE
     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
+    #endif
 
     int32_t this_maxlevel = 0;
     unsigned long int var = 0;
-    uint this_size = 0;
+    uint32_t this_size = 0;
     while (true) {
         var = m.matrix.getVarsetAt(row).scan(var);
         if (var == ULONG_MAX) break;
@@ -745,14 +793,14 @@ void Gaussian::analyse_confl(const matrixset& m, const uint row, int32_t& maxlev
                 || (this_size <= 1)
             )) {
         assert(maxlevel != std::numeric_limits<int32_t>::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;
     }
 
@@ -772,39 +820,54 @@ void Gaussian::analyse_confl(const matrixset& m, const uint row, int32_t& maxlev
     best_row = row;
 }
 
-Gaussian::gaussian_ret Gaussian::handle_matrix_prop(matrixset& m, const uint row)
+Gaussian::gaussian_ret Gaussian::handle_matrix_prop(matrixset& m, const uint32_t 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;
+    cout << "(" << matrix_no << ")matrix prop" << endl;
+    #ifdef VERBOSE_DEBUG_MORE
+    cout << "(" << matrix_no << ")matrix row:" << m.matrix.getMatrixAt(row) << endl;
+    #endif
     #endif
 
+    bool xorEqualFalse = !m.matrix.getVarsetAt(row).is_true();
     m.matrix.getVarsetAt(row).fill(tmp_clause, solver.assigns, col_to_var_original);
-    Clause& cla = *(Clause*)solver.clauseAllocator.XorClause_new(tmp_clause, false, solver.learnt_clause_group++);
     #ifdef VERBOSE_DEBUG
-    cout << "(" << matrix_no << ")matrix prop clause: ";
-    cla.plainPrint();
+    cout << "(" << matrix_no << ")matrix prop clause: " << tmp_clause << std::endl;
     cout << endl;
     #endif
-    
-    assert(m.matrix.getMatrixAt(row).is_true() == !cla[0].sign());
-    assert(solver.assigns[cla[0].var()].isUndef());
-    if (cla.size() == 1) {
-        solver.cancelUntil(0);
-        solver.uncheckedEnqueue(cla[0]);
-        solver.clauseAllocator.clauseFree(&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);
+    switch(tmp_clause.size()) {
+        case 0:
+            //This would mean nothing, empty = true, always true in xors
+            assert(false);
+            break;
+        case 1:
+            solver.cancelUntil(0);
+            solver.uncheckedEnqueue(tmp_clause[0]);
+            return unit_propagation;
+        case 2: {
+            solver.cancelUntil(0);
+            tmp_clause[0] = tmp_clause[0].unsign();
+            tmp_clause[1] = tmp_clause[1].unsign();
+            XorClause* cl = solver.addXorClauseInt(tmp_clause, xorEqualFalse, 0);
+            assert(cl == NULL);
+            assert(solver.ok);
+            return unit_propagation;
+            break;
+        }
+        default:
+            Clause& cla = *(Clause*)solver.clauseAllocator.XorClause_new(tmp_clause, xorEqualFalse, solver.learnt_clause_group++);
+            assert(m.matrix.getMatrixAt(row).is_true() == !cla[0].sign());
+            assert(solver.assigns[cla[0].var()].isUndef());
+
+            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], solver.clauseAllocator.getOffset(&cla));
+            return propagation;
+    }
 
     return propagation;
 }
@@ -815,25 +878,26 @@ void Gaussian::disable_if_necessary()
         //&& conflictC >= nof_conflicts/8
         !config.dontDisable
         && called > 50
-        && useful_confl*2+useful_prop < (uint)((double)called*0.05) )
+        && useful_confl*2+useful_prop < (uint32_t)((double)called*0.05) )
             disabled = true;
 }
 
-llbool Gaussian::find_truths(vec<Lit>& learnt_clause, int& conflictC)
+llbool Gaussian::find_truths(vec<Lit>& learnt_clause, uint64_t& conflictC)
 {
-    Clause* confl;
+    PropBy 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);
-            solver.clauseAllocator.clauseFree(confl);
-            
+            if (confl.isClause())
+                solver.clauseAllocator.clauseFree(solver.clauseAllocator.getPointer(confl.getClause()));
+
             if (ret != l_Nothing) return ret;
             return l_Continue;
         }
@@ -845,27 +909,37 @@ llbool Gaussian::find_truths(vec<Lit>& learnt_clause, int& conflictC)
         case unit_conflict: {
             unit_truths++;
             useful_confl++;
-            if (confl->size() == 0) {
-                solver.clauseAllocator.clauseFree(confl);
+            if (confl.isNULL()) {
+                #ifdef VERBOSE_DEBUG
+                std::cout << "(" << matrix_no << ")zero-length conflict. UNSAT" << std::endl;
+                #endif
+                solver.ok = false;
                 return l_False;
             }
 
-            Lit lit = (*confl)[0];
+            Lit lit = confl.getOtherLit();
             #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()) {
-                solver.clauseAllocator.clauseFree(confl);
+
+            #ifdef VERBOSE_DEBUG
+            std::cout << "(" << matrix_no << ")one-length conflict" << std::endl;
+            #endif
+            if (solver.value(lit) != l_Undef) {
+                assert(solver.value(lit) == l_False);
+                #ifdef VERBOSE_DEBUG
+                std::cout << "(" << matrix_no << ") -> UNSAT" << std::endl;
+                #endif
+                solver.ok = false;
                 return l_False;
             }
-            
+            #ifdef VERBOSE_DEBUG
+            std::cout << "(" << matrix_no << ") -> setting to correct value" << std::endl;
+            #endif
             solver.uncheckedEnqueue(lit);
-            
-            solver.clauseAllocator.clauseFree(confl);
             return l_Continue;
         }
         case nothing:
@@ -897,7 +971,7 @@ void Gaussian::print_matrix_row_with_assigns(const T& row) const
     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]) << ")";
@@ -905,7 +979,7 @@ void Gaussian::print_matrix_row_with_assigns(const T& row) const
         }
         col++;
     }
-    if (!row.is_true()) cout << "xor_clause_inverted";
+    if (!row.is_true()) cout << "xorEqualFalse";
 }
 
 const string Gaussian::lbool_to_string(const lbool toprint)
@@ -916,7 +990,7 @@ const string Gaussian::lbool_to_string(const lbool toprint)
             return "false";
     if (toprint == l_Undef)
             return "undef";
-    
+
     assert(false);
     return "";
 }
@@ -950,7 +1024,7 @@ void Gaussian::reset_stats()
 
 bool Gaussian::check_no_conflict(matrixset& m) const
 {
-    uint row = 0;
+    uint32_t 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;
@@ -962,7 +1036,7 @@ bool Gaussian::check_no_conflict(matrixset& m) const
 
 void Gaussian::print_matrix(matrixset& m) const
 {
-    uint row = 0;
+    uint32_t row = 0;
     for (PackedMatrix::iterator it = m.matrix.beginMatrix(); it != m.matrix.endMatrix(); ++it, row++) {
         cout << *it << " -- row:" << row;
         if (row >= m.num_rows)
@@ -973,7 +1047,7 @@ void Gaussian::print_matrix(matrixset& m) const
 
 void Gaussian::print_last_one_in_cols(matrixset& m) const
 {
-    for (uint i = 0; i < m.num_cols; i++) {
+    for (uint32_t i = 0; i < m.num_cols; i++) {
         cout << "last_one_in_col[" << i << "]-1 = " << m.last_one_in_col[i]-1 << endl;
     }
 }
@@ -982,22 +1056,30 @@ 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())
+            && solver.assigns[m.col_to_var[(*r).scan(0)]].isUndef()) {
+            #ifdef VERBOSE_DEBUG
+            std::cout << "row " << (*r) << " is a propagation, but we didn't catch it" << std::endl;
+            #endif
             return false;
+        }
     }
     for(PackedMatrix::iterator r = m.matrix.beginMatrix(), end = m.matrix.endMatrix(); r != end; ++r) {
-        if ((*r).isZero() && (*r).is_true())
+        if ((*r).isZero() && (*r).is_true()) {
+            #ifdef VERBOSE_DEBUG
+            std::cout << "row " << (*r) << " is a conflict, but we didn't catch it" << std::endl;
+            #endif
             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(uint32_t i = 0; i < m.num_cols; i++) {
+        const uint32_t last = std::min(m.last_one_in_col[i] - 1, (int)m.num_rows);
+        uint32_t real_last = 0;
+        uint32_t i2 = 0;
         for (PackedMatrix::iterator it = m.matrix.beginMatrix(); it != m.matrix.endMatrix(); ++it, i2++) {
             if ((*it)[i])
                 real_last = i2;
@@ -1005,25 +1087,25 @@ const bool Gaussian::check_last_one_in_cols(matrixset& m) const
         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++) {
+    for (uint32_t 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);
@@ -1038,7 +1120,7 @@ void Gaussian::check_matrix_against_varset(PackedMatrix& matrix, const matrixset
                 assert(!m.var_is_set[var]);
                 assert(mat_row[col]);
             } else assert(false);
-            
+
             col++;
         }
         if ((final^!mat_row.is_true()) != !var_row.is_true()) {
@@ -1048,7 +1130,7 @@ void Gaussian::check_matrix_against_varset(PackedMatrix& matrix, const matrixset
     }
 }
 
-const void Gaussian::check_first_one_in_row(matrixset& m, const uint j)
+const void Gaussian::check_first_one_in_row(matrixset& m, const uint32_t j)
 {
     if (j) {
         uint16_t until2 = std::min(m.last_one_in_col[m.least_column_changed] - 1, (int)m.num_rows);
@@ -1058,7 +1140,7 @@ const void Gaussian::check_first_one_in_row(matrixset& m, const uint j)
             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++) {
+        for (uint32_t i2 = 0; i2 != until2; i2++) {
             #ifdef VERBOSE_DEBUG
             cout << endl << "row " << i2 << " (num rows:" << m.num_rows << ")" << endl;
             cout << m.matrix.getMatrixAt(i2) << endl;
@@ -1069,8 +1151,8 @@ const void Gaussian::check_first_one_in_row(matrixset& m, const uint j)
             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++) {
+
+            for (uint32_t 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]]);
@@ -1086,16 +1168,16 @@ const void Gaussian::check_first_one_in_row(matrixset& m, const uint j)
 {
 #ifdef VERBOSE_DEBUG
     cout << "Updating matrix." << endl;
-    uint num_updated = 0;
+    uint32_t num_updated = 0;
 #endif
 #ifdef DEBUG_GAUSS
     assert(nothing_to_propagate(cur_matrixset));
 #endif
 
     mpz_class toclear, tocount;
-    uint last_col = 0;
+    uint32_t last_col = 0;
 
-    for (uint col = 0; col < m.num_cols; col ++) {
+    for (uint32_t col = 0; col < m.num_cols; col ++) {
         Var var = m.col_to_var[col];
 
         if (var != UINT_MAX && !solver.assigns[var].isUndef()) {
@@ -1120,7 +1202,7 @@ const void Gaussian::check_first_one_in_row(matrixset& m, const uint j)
     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++) {
+    for(uint32_t 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);
@@ -1132,11 +1214,11 @@ const void Gaussian::check_first_one_in_row(matrixset& m, const uint j)
 #endif
 }*/
 
-/*void Gaussian::update_matrix_by_col(matrixset& m, const uint last_level) const
+/*void Gaussian::update_matrix_by_col(matrixset& m, const uint32_t last_level) const
 {
 #ifdef VERBOSE_DEBUG
     cout << "Updating matrix." << endl;
-    uint num_updated = 0;
+    uint32_t num_updated = 0;
 #endif
 #ifdef DEBUG_GAUSS
     assert(nothing_to_propagate(cur_matrixset));
@@ -1144,7 +1226,7 @@ const void Gaussian::check_first_one_in_row(matrixset& m, const uint j)
 
     for (int level = solver.trail.size()-1; level >= last_level; level--){
         Var var = solver.trail[level].var();
-        const uint col = m.var_to_col[var];
+        const uint32_t col = m.var_to_col[var];
         if ( col < UINT_MAX-1) {
             update_matrix_col(m, var, col);
 #ifdef VERBOSE_DEBUG
@@ -1157,5 +1239,3 @@ const void Gaussian::check_first_one_in_row(matrixset& m, const uint j)
     cout << "Updated " << num_updated << " matrix cols. Could remove " << m.removeable_cols << " cols (out of " << m.num_cols << " )" <<endl;
 #endif
 }*/
-
-}; //NAMESPACE MINISAT
index 6dc8b0d737dc6c78a38f5916712a3bb77a7d37da..f3c27ea0fbd6d802f6154242e4c6cbacee75694b 100644 (file)
@@ -20,6 +20,11 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include <vector>
 #include <limits>
+#include <string>
+#include <utility>
+using std::string;
+using std::pair;
+
 #ifdef _MSC_VER
 #include <msvc/stdint.h>
 #else
@@ -41,48 +46,46 @@ using std::cout;
 using std::endl;
 #endif
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 class Clause;
 
 class Gaussian
 {
 public:
-    Gaussian(Solver& solver, const GaussianConfig& config, const uint matrix_no, const vector<XorClause*>& xorclauses);
+    Gaussian(Solver& solver, const GaussConf& config, const uint32_t matrix_no, const vector<XorClause*>& xorclauses);
     ~Gaussian();
 
     const bool full_init();
-    llbool find_truths(vec<Lit>& learnt_clause, int& conflictC);
+    llbool find_truths(vec<Lit>& learnt_clause, uint64_t& 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 uint32_t get_called() const;
+    const uint32_t get_useful_prop() const;
+    const uint32_t get_useful_confl() const;
     const bool get_disabled() const;
     const uint32_t get_unit_truths() const;
     void set_disabled(const bool toset);
 
     //functions used throughout the Solver
-    void canceling(const uint sublevel);
+    void canceling(const uint32_t sublevel);
+
+    friend class ClauseAllocator;
 
 protected:
     Solver& solver;
-    
+
     //Gauss high-level configuration
-    const GaussianConfig& config;
-    const uint matrix_no;
+    const GaussConf& config;
+    const uint32_t matrix_no;
     vector<XorClause*> xorclauses;
 
     enum gaussian_ret {conflict, unit_conflict, propagation, unit_propagation, nothing};
-    gaussian_ret gaussian(Clause*& confl);
+    gaussian_ret gaussian(PropBy& confl);
 
     vector<Var> 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;
+    uint32_t badlevel;
 
     class matrixset
     {
@@ -91,11 +94,11 @@ protected:
         BitArray var_is_set;
         vector<Var> 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
+        uint32_t 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<uint16_t> 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<uint16_t> first_one_in_row;
-        uint removeable_cols; // the number of columns that have been zeroed out (i.e. assigned)
+        uint32_t removeable_cols; // the number of columns that have been zeroed out (i.e. assigned)
     };
 
     //Saved states
@@ -105,55 +108,55 @@ protected:
     //Varibales to keep Gauss state
     bool messed_matrix_vars_since_reversal;
     int gauss_last_level;
-    vector<pair<Clause*, uint> > clauses_toclear;
+    vector<pair<Clause*, uint32_t> > clauses_toclear;
     bool disabled; // Gauss is disabled
-    
+
     //State of current elimnation
-    vec<uint> propagatable_rows; //used to store which rows were deemed propagatable during elimination
+    vec<uint32_t> propagatable_rows; //used to store which rows were deemed propagatable during elimination
     vector<unsigned char> 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
+    uint32_t useful_prop; //how many times Gauss gave propagation as a result
+    uint32_t useful_confl; //how many times Gauss gave conflict as a result
+    uint32_t called; //how many times called the Gauss
     uint32_t unit_truths; //how many unitary (i.e. decisionLevel 0) truths have been found
 
     //gauss init functions
     void init(); // Initalise gauss state
     void fill_matrix(matrixset& origMat); // Fills the origMat matrix
-    uint select_columnorder(vector<uint16_t>& var_to_col, matrixset& origMat); // Fills var_to_col and col_to_var of the origMat matrix.
+    uint32_t select_columnorder(vector<uint16_t>& 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
+    uint32_t eliminate(matrixset& matrix, uint32_t& 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_col(matrixset& matrix, const Var x, const uint32_t 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;
+    //void update_matrix_by_col(matrixset& matrix, const uint32_t 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, int32_t& 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'
+    gaussian_ret handle_matrix_prop_and_confl(matrixset& m, uint32_t row, PropBy& confl);
+    void analyse_confl(const matrixset& m, const uint32_t row, int32_t& maxlevel, uint32_t& size, uint32_t& 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(PropBy& confl, const matrixset& m, const uint32_t size, const uint32_t maxlevel, const uint32_t best_row);
+    gaussian_ret handle_matrix_prop(matrixset& m, const uint32_t row); // Handle matrix propagation at row 'row'
     vec<Lit> tmp_clause;
 
     //propagation&conflict handling
-    void cancel_until_sublevel(const uint until_sublevel); // cancels until sublevel 'until_sublevel'. The var 'until_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
+    void cancel_until_sublevel(const uint32_t until_sublevel); // cancels until sublevel 'until_sublevel'. The var 'until_sublevel' must NOT go over the current level. I.e. this function is ONLY for moving inside the current level
+    uint32_t 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;
+    bool should_check_gauss(const uint32_t decisionlevel, const uint32_t 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?
@@ -163,7 +166,7 @@ private:
     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);
+    const void check_first_one_in_row(matrixset& m, const uint32_t 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);
@@ -174,23 +177,23 @@ inline bool Gaussian::should_init() const
     return (config.decision_until > 0);
 }
 
-inline bool Gaussian::should_check_gauss(const uint decisionlevel, const uint starts) const
+inline bool Gaussian::should_check_gauss(const uint32_t decisionlevel, const uint32_t starts) const
 {
     return (!disabled
             && decisionlevel < config.decision_until);
 }
 
-inline void Gaussian::canceling(const uint sublevel)
+inline void Gaussian::canceling(const uint32_t sublevel)
 {
     if (disabled)
         return;
-    uint a = 0;
+    uint32_t a = 0;
     for (int i = clauses_toclear.size()-1; i >= 0 && clauses_toclear[i].second > sublevel; i--) {
         solver.clauseAllocator.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);
@@ -210,17 +213,17 @@ inline const uint32_t Gaussian::get_unit_truths() const
     return unit_truths;
 }
 
-inline const uint Gaussian::get_called() const
+inline const uint32_t Gaussian::get_called() const
 {
     return called;
 }
 
-inline const uint Gaussian::get_useful_prop() const
+inline const uint32_t Gaussian::get_useful_prop() const
 {
     return useful_prop;
 }
 
-inline const uint Gaussian::get_useful_confl() const
+inline const uint32_t Gaussian::get_useful_confl() const
 {
     return useful_confl;
 }
@@ -237,6 +240,4 @@ inline void Gaussian::set_disabled(const bool toset)
 
 std::ostream& operator << (std::ostream& os, const vec<Lit>& v);
 
-}; //NAMESPACE MINISAT
-
 #endif //GAUSSIAN_H
index 0806f83e0f40811563de4e0f96766d5fafbcc38d..40c4522df7ee6c62f6212c2a4b77872b0088c859 100644 (file)
@@ -26,15 +26,11 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include "PackedRow.h"
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
-class GaussianConfig
+class GaussConf
 {
     public:
-    
-    GaussianConfig() :
+
+    GaussConf() :
         only_nth_gauss_save(2)
         , decision_until(0)
         , dontDisable(false)
@@ -43,20 +39,20 @@ class GaussianConfig
         , iterativeReduce(true)
         , maxMatrixRows(1000)
         , minMatrixRows(20)
+        , maxNumMatrixes(3)
     {
     }
-        
+
     //tuneable gauss parameters
-    uint only_nth_gauss_save;  //save only every n-th gauss matrix
-    uint decision_until; //do Gauss until this level
+    uint32_t only_nth_gauss_save;  //save only every n-th gauss matrix
+    uint32_t decision_until; //do Gauss until this level
     bool dontDisable; //If activated, gauss elimination is never disabled
     bool noMatrixFind; //Put all xor-s into one matrix, don't find matrixes
     bool orderCols; //Order columns according to activity
     bool iterativeReduce; //Don't minimise matrix work
     uint32_t maxMatrixRows; //The maximum matrix size -- no. of rows
     uint32_t minMatrixRows; //The minimum matrix size -- no. of rows
+    uint32_t maxNumMatrixes; //Maximum number of matrixes
 };
 
-}; //NAMESPACE MINISAT
-
 #endif //GAUSSIANCONFIG_H
index 59013e51c24ada0084be64ae36c3d781ca1e5a83..f76fbb79c7d8e35558f1e9e9ad54da79897d4913 100644 (file)
@@ -39,10 +39,6 @@ using std::ofstream;
 #define SND_WIDTH 35
 #define TRD_WIDTH 10
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 Logger::Logger(int& _verbosity) :
     proof_graph_on(false)
     , mini_proof(false)
@@ -719,7 +715,6 @@ void Logger::print_general_stats() const
     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();
 }
@@ -906,4 +901,3 @@ void Logger::reset_statistics()
     last_unitary_learnt_clauses = S->get_unitary_learnts_num();
 }
 
-}; //NAMESPACE MINISAT
index 7567c7a3842789365f2944bc093f37447f98a5f6..a7c4dc3720453aeafec44dd05c992fc29a392703 100644 (file)
@@ -43,10 +43,6 @@ using std::pair;
 using std::string;
 using std::map;
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 class Solver;
 
 class MyAvg {
@@ -185,6 +181,4 @@ private:
     uint proofStarts;
 };
 
-}; //NAMESPACE MINISAT
-
 #endif //LOGGER_H
index 964ecc736f57f6808e199be3e2501ec34646f590..16e64581ad1edec0740ff129eebfd0d185acaf37 100644 (file)
 #ifndef MERSENNETWISTER_H
 #define MERSENNETWISTER_H
 
+// Not thread safe (unless auto-initialization is avoided and each thread has
+// its own MTRand object)
+
 #include <iostream>
 #include <limits.h>
 #include <stdio.h>
 #include <time.h>
 #include <math.h>
 
-namespace MINISAT
-{
-
-// Not thread safe (unless auto-initialization is avoided and each thread has
-// its own MTRand object)
-
 class MTRand {
 // Data
 public:
@@ -382,7 +379,6 @@ inline std::istream& operator>>( std::istream& is, MTRand& mtrand )
        mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left];
        return is;
 }
-};
 
 #endif  // MERSENNETWISTER_H
 
index 393961192370a886773770611af5836504d40da8..7433cae245fcd2a760b0f5a813deaaea7a6ae4e0 100644 (file)
@@ -1,22 +1,34 @@
-/******************************************************************************************[Main.C]
+/*****************************************************************************
 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:
+Original code by MiniSat authors are under an MIT licence.
+Modifications for CryptoMiniSat are under GPLv3 licence.
+******************************************************************************/
 
-The above copyright notice and this permission notice shall be included in all copies or
-substantial portions of the Software.
+/**
+@mainpage CryptoMiniSat
+@author Mate Soos, and collaborators
 
-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.
-**************************************************************************************************/
+CryptoMiniSat is an award-winning SAT solver based on MiniSat. It brings a
+number of benefits relative to MiniSat, among them XOR clauses, extensive
+failed literal probing, and better random search.
+
+The solver basically performs the following steps:
+
+1) parse CNF file into clause database
+
+2) run Conflict-Driven Clause-Learning DPLL on the clauses
+
+3) regularly run simplification passes on the clause-set
+
+4) display solution and if not used as a library, exit
+
+Here is a picture of of the above process in more detail:
+
+\image html "main_flowgraph.png"
+
+*/
 
 #include <ctime>
 #include <cstring>
@@ -25,403 +37,164 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
 #include <sstream>
 #include <iostream>
 #include <iomanip>
-#include <vector>
+#include <omp.h>
 #ifdef _MSC_VER
 #include <msvc/stdint.h>
 #else
 #include <stdint.h>
 #endif //_MSC_VER
+#include <map>
+#include <set>
 
 #include <signal.h>
 
-#ifndef DISABLE_ZLIB
-#include <zlib.h>
-#endif // DISABLE_ZLIB
-
+#ifdef STATS_NEEDED
 #include "Logger.h"
-#include "Solver.h"
+#endif //STATS_NEEDED
+
 #include "time_mem.h"
 #include "constants.h"
+#include "DimacsParser.h"
 
-using std::cout;
-using std::endl;
-
-/*************************************************************************************/
 #if defined(__linux__)
 #include <fpu_control.h>
 #endif
 
-using namespace MINISAT;
-
-namespace MINISAT
+#include "Main.h"
+
+Main::Main(int _argc, char** _argv) :
+        numThreads(1)
+        , grouping(false)
+        , debugLib (false)
+        , debugNewVar (false)
+        , printResult (true)
+        , max_nr_of_solutions (1)
+        , fileNamePresent (false)
+        , twoFileNamesPresent (false)
+        , argc(_argc)
+        , argv(_argv)
 {
+}
 
-static bool grouping = false;
-static bool debugLib = false;
-static bool debugNewVar = false;
-static char learnts_filename[500];
-static bool dumpLearnts = false;
-static uint32_t maxLearntsSize = std::numeric_limits<uint32_t>::max();
-static bool printResult = true;
-
-//=================================================================================================
-// DIMACS Parser:
+std::map<uint32_t, Solver*> solversToInterrupt;
+std::set<uint32_t> finished;
 
-#define CHUNK_LIMIT 1048576
-#define MAX_NAMES_SIZE 1000
+/**
+@brief For correctly and gracefully exiting
 
-class StreamBuffer
+It can happen that the user requests a dump of the learnt clauses. In this case,
+the program must wait until it gets to a state where the learnt clauses are in
+a correct state, then dump these and quit normally. This interrupt hander
+is used to achieve this
+*/
+void SIGINT_handler(int signum)
 {
-#ifdef DISABLE_ZLIB
-    FILE *  in;
-#else
-    gzFile  in;
-#endif // DISABLE_ZLIB
-    char    buf[CHUNK_LIMIT];
-    int     pos;
-    int     size;
-
-    void assureLookahead() {
-        if (pos >= size) {
-            pos  = 0;
-#ifdef DISABLE_ZLIB
-            #ifdef VERBOSE_DEBUG
-            printf("buf = %08X\n", buf);
-            printf("sizeof(buf) = %u\n", sizeof(buf));
-            #endif //VERBOSE_DEBUG
-            size = fread(buf, 1, sizeof(buf), in);
-#else
-            size = gzread(in, buf, sizeof(buf));
-#endif // DISABLE_ZLIB
+    #pragma omp critical
+    {
+        Solver& solver = *solversToInterrupt.begin()->second;
+        printf("\n");
+        std::cerr << "*** INTERRUPTED ***" << std::endl;
+        if (solver.conf.needToDumpLearnts || solver.conf.needToDumpOrig) {
+            solver.needToInterrupt = true;
+            std::cerr << "*** Please wait. We need to interrupt cleanly" << std::endl;
+            std::cerr << "*** This means we might need to finish some calculations" << std::endl;
+        } else {
+            if (solver.conf.verbosity >= 1) solver.printStats();
+            exit(1);
         }
     }
-
-public:
-#ifdef DISABLE_ZLIB
-    StreamBuffer(FILE * i) : in(i), pos(0), size(0) {
-#else
-    StreamBuffer(gzFile i) : in(i), pos(0), size(0) {
-#endif // DISABLE_ZLIB
-        assureLookahead();
-    }
-
-    int  operator *  () {
-        return (pos >= size) ? EOF : buf[pos];
-    }
-    void operator ++ () {
-        pos++;
-        assureLookahead();
-    }
-};
-
-//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-template<class B>
-static void skipWhitespace(B& in)
-{
-    while ((*in >= 9 && *in <= 13) || *in == 32)
-        ++in;
 }
 
-template<class B>
-static void skipLine(B& in)
+void Main::readInAFile(const std::string& filename, Solver& solver)
 {
-    for (;;) {
-        if (*in == EOF || *in == '\0') return;
-        if (*in == '\n') {
-            ++in;
-            return;
-        }
-        ++in;
+    if (solver.conf.verbosity >= 1) {
+        std::cout << "c Reading file '" << filename << "'" << std::endl;
     }
-}
 
-template<class B>
-static void untilEnd(B& in, char* ret)
-{
-    uint32_t sizeRead = 0;
-    for (;sizeRead < MAX_NAMES_SIZE-1; sizeRead++) {
-        if (*in == EOF || *in == '\0') return;
-        if (*in == '\n') {
-            return;
-        }
-        *ret = *in;
-        ret++;
-        *ret = '\0';
-        ++in;
+    char* fname = (char*)calloc(filename.length()+1, sizeof(char));
+    assert(fname != NULL);
+    memcpy(fname, filename.c_str(), filename.length());
+    fname[filename.length()] = '\0';
+    #ifdef DISABLE_ZLIB
+        FILE * in = fopen(fname, "rb");
+    #else
+        gzFile in = gzopen(fname, "rb");
+    #endif // DISABLE_ZLIB
+    free(fname);
+
+    if (in == NULL) {
+        std::cout << "ERROR! Could not open file '" << filename << "' for reading" << std::endl;
+        exit(1);
     }
-}
 
+    DimacsParser parser(&solver, debugLib, debugNewVar, grouping);
+    parser.parse_DIMACS(in);
 
-template<class B>
-static int parseInt(B& in)
-{
-    int     val = 0;
-    bool    neg = false;
-    skipWhitespace(in);
-    if      (*in == '-') neg = true, ++in;
-    else if (*in == '+') ++in;
-    if (*in < '0' || *in > '9') printf("PARSE ERROR! Unexpected char: %c\n", *in), exit(3);
-    while (*in >= '0' && *in <= '9')
-        val = val*10 + (*in - '0'),
-              ++in;
-    return neg ? -val : val;
+    #ifdef DISABLE_ZLIB
+        fclose(in);
+    #else
+        gzclose(in);
+    #endif // DISABLE_ZLIB
 }
 
-inline std::string stringify(uint x)
+void Main::readInStandardInput(Solver& solver)
 {
-    std::ostringstream o;
-    o << x;
-    return o.str();
-}
-
-template<class B>
-static void parseString(B& in, std::string& str)
-{
-    str.clear();
-    skipWhitespace(in);
-    while (*in != ' ' && *in != '\n') {
-        str += *in;
-        ++in;
+    if (solver.conf.verbosity >= 1) {
+        std::cout << "c Reading from standard input... Use '-h' or '--help' for help." << std::endl;
     }
-}
+    #ifdef DISABLE_ZLIB
+        FILE * in = stdin;
+    #else
+        gzFile in = gzdopen(fileno(stdin), "rb");
+    #endif // DISABLE_ZLIB
 
-template<class B>
-static void readClause(B& in, Solver& S, vec<Lit>& lits)
-{
-    int     parsed_lit;
-    Var     var;
-    lits.clear();
-    for (;;) {
-        parsed_lit = parseInt(in);
-        if (parsed_lit == 0) break;
-        var = abs(parsed_lit)-1;
-        if (!debugNewVar) {
-            while (var >= S.nVars()) S.newVar();
-        }
-        lits.push( (parsed_lit > 0) ? Lit(var, false) : Lit(var, true) );
+    if (in == NULL) {
+        std::cout << "ERROR! Could not open standard input for reading" << std::endl;
+        exit(1);
     }
-}
-
-template<class B>
-static bool match(B& in, const char* str)
-{
-    for (; *str != 0; ++str, ++in)
-        if (*str != *in)
-            return false;
-    return true;
-}
 
+    DimacsParser parser(&solver, debugLib, debugNewVar, grouping);
+    parser.parse_DIMACS(in);
 
-template<class B>
-static void parse_DIMACS_main(B& in, Solver& S)
-{
-    vec<Lit> lits;
-    int group = 0;
-    string str;
-    uint debugLibPart = 1;
-    char name[MAX_NAMES_SIZE];
-
-
-    for (;;) {
-        skipWhitespace(in);
-        switch (*in) {
-        case EOF:
-            return;
-        case 'p':
-            if (match(in, "p cnf")) {
-                int vars    = parseInt(in);
-                int clauses = parseInt(in);
-                if (S.verbosity >= 1) {
-                    printf("c |  Number of variables:  %-12d                                                   |\n", vars);
-                    printf("c |  Number of clauses:    %-12d                                                   |\n", clauses);
-                }
-            } else {
-                printf("PARSE ERROR! Unexpected char: %c\n", *in), exit(3);
-            }
-            break;
-        case 'c':
-            ++in;
-            parseString(in, str);
-            if (str == "v" || str == "var") {
-                int var = parseInt(in);
-                skipWhitespace(in);
-                if (var <= 0) cout << "PARSE ERROR! Var number must be a positive integer" << endl, exit(3);
-                name[0] = '\0';
-                untilEnd(in, name);
-                S.setVariableName(var-1, name);
-            } else if (debugLib && str == "Solver::solve()") {
-                lbool ret = S.solve();
-                std::string s = "debugLibPart" + stringify(debugLibPart) +".output";
-                FILE* res = fopen(s.c_str(), "w");
-                if (ret == l_True) {
-                    fprintf(res, "SAT\n");
-                    for (Var i = 0; i != S.nVars(); i++)
-                        if (S.model[i] != l_Undef)
-                            fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1);
-                        fprintf(res, " 0\n");
-                } else if (ret == l_False) {
-                    fprintf(res, "UNSAT\n");
-                } else if (ret == l_Undef) {
-                    assert(false);
-                } else {
-                    assert(false);
-                }
-                fclose(res);
-                debugLibPart++;
-            } else if (debugNewVar && str == "Solver::newVar()") {
-                S.newVar();
-            } else {
-                //printf("didn't understand in CNF file: 'c %s'\n", str.c_str());
-                skipLine(in);
-            }
-            break;
-        default:
-            bool xor_clause = false;
-            if ( *in == 'x') xor_clause = true, ++in;
-            readClause(in, S, lits);
-            skipLine(in);
-
-            name[0] = '\0';
-
-            if (!grouping) group++;
-            else {
-                if (*in != 'c') {
-                    cout << "PARSE ERROR! Group must be present after earch clause ('c' missing after clause line)" << endl;
-                    exit(3);
-                }
-                ++in;
-
-                parseString(in, str);
-                if (str != "g" && str != "group") {
-                    cout << "PARSE ERROR! Group must be present after each clause('group' missing)!" << endl;
-                    cout << "Instead of 'group' there was:" << str << endl;
-                    exit(3);
-                }
-
-                group = parseInt(in);
-                if (group <= 0) printf("PARSE ERROR! Group number must be a positive integer\n"), exit(3);
-
-                skipWhitespace(in);
-                untilEnd(in, name);
-            }
-
-            if (xor_clause) {
-                bool xor_clause_inverted = false;
-                for (uint32_t i = 0; i < lits.size(); i++) {
-                    xor_clause_inverted ^= lits[i].sign();
-                }
-                S.addXorClause(lits, xor_clause_inverted, group, name);
-            } else
-                S.addClause(lits, group, name);
-            break;
-        }
-    }
+    #ifndef DISABLE_ZLIB
+        gzclose(in);
+    #endif // DISABLE_ZLIB
 }
 
-// Inserts problem into solver.
-//
-#ifdef DISABLE_ZLIB
-static void parse_DIMACS(FILE * input_stream, Solver& S)
-#else
-static void parse_DIMACS(gzFile input_stream, Solver& S)
-#endif // DISABLE_ZLIB
-{
-    StreamBuffer in(input_stream);
-    parse_DIMACS_main(in, S);
-}
-
-
-//=================================================================================================
 
-template<class T, class T2>
-inline void printStatsLine(string left, T value, T2 value2, string extra)
-{
-    cout << std::fixed << std::left << std::setw(24) << left << ": " << std::setw(11) << std::setprecision(2) << value << " (" << std::left << std::setw(9) << std::setprecision(2) << value2 << " " << extra << ")" << std::endl;
-}
 
-template<class T>
-inline void printStatsLine(string left, T value, string extra = "")
+void Main::parseInAllFiles(Solver& solver)
 {
-    cout << std::fixed << std::left << std::setw(24) << left << ": " << std::setw(11) << std::setprecision(2) << value << extra << std::endl;
-}
+    double myTime = cpuTime();
 
-
-void printStats(Solver& solver)
-{
-    double   cpu_time = cpuTime();
-    uint64_t mem_used = memUsed();
-
-    //Restarts stats
-    printStatsLine("c restarts", solver.starts);
-    printStatsLine("c dynamic restarts", solver.dynStarts);
-    printStatsLine("c static restarts", solver.staticStarts);
-    printStatsLine("c full restarts", solver.fullStarts);
-
-    //Learnts stats
-    printStatsLine("c learnts DL2", solver.nbDL2);
-    printStatsLine("c learnts size 2", solver.nbBin);
-    printStatsLine("c learnts size 1", solver.get_unitary_learnts_num(), (double)solver.get_unitary_learnts_num()/(double)solver.nVars()*100.0, "% of vars");
-
-    //Subsumer stats
-    printStatsLine("c v-elim SatELite", solver.getNumElimSubsume(), (double)solver.getNumElimSubsume()/(double)solver.nVars()*100.0, "% vars");
-    printStatsLine("c SatELite time", solver.getTotalTimeSubsumer(), solver.getTotalTimeSubsumer()/cpu_time*100.0, "% time");
-
-    //XorSubsumer stats
-    printStatsLine("c v-elim xor", solver.getNumElimXorSubsume(), (double)solver.getNumElimXorSubsume()/(double)solver.nVars()*100.0, "% vars");
-    printStatsLine("c xor elim time", solver.getTotalTimeXorSubsumer(), solver.getTotalTimeXorSubsumer()/cpu_time*100.0, "% time");
-
-    //VarReplacer stats
-    printStatsLine("c num binary xor trees", solver.getNumXorTrees());
-    printStatsLine("c binxor trees' crown", solver.getNumXorTreesCrownSize(), (double)solver.getNumXorTreesCrownSize()/(double)solver.getNumXorTrees(), "leafs/tree");
-
-    //OTF clause improvement stats
-    printStatsLine("c OTF clause improved", solver.improvedClauseNo, (double)solver.improvedClauseNo/(double)solver.conflicts, "clauses/conflict");
-    printStatsLine("c OTF impr. size diff", solver.improvedClauseSize, (double)solver.improvedClauseSize/(double)solver.improvedClauseNo, " lits/clause");
-
-    #ifdef USE_GAUSS
-    if (solver.gaussconfig.decision_until > 0) {
-        std::cout << "c " << std::endl;
-        printStatsLine("c gauss unit truths ", solver.get_sum_gauss_unit_truths());
-        printStatsLine("c gauss called", solver.get_sum_gauss_called());
-        printStatsLine("c gauss conflicts ", solver.get_sum_gauss_confl(), (double)solver.get_sum_gauss_confl() / (double)solver.get_sum_gauss_called() * 100.0, " %");
-        printStatsLine("c gauss propagations ", solver.get_sum_gauss_prop(), (double)solver.get_sum_gauss_prop() / (double)solver.get_sum_gauss_called() * 100.0, " %");
-        printStatsLine("c gauss useful", ((double)solver.get_sum_gauss_prop() + (double)solver.get_sum_gauss_confl())/ (double)solver.get_sum_gauss_called() * 100.0, " %");
-        std::cout << "c " << std::endl;
+    //First read normal extra files
+    if ((debugLib || debugNewVar) && filesToRead.size() > 0) {
+        std::cout << "debugNewVar and debugLib must both be OFF to parse in extra files" << std::endl;
+        exit(-1);
+    }
+    for (uint32_t i = 0; i < filesToRead.size(); i++) {
+        readInAFile(filesToRead[i].c_str(), solver);
     }
-    #endif
-
-    //Search stats
-    printStatsLine("c conflicts", solver.conflicts, (double)solver.conflicts/cpu_time, "/ sec");
-    printStatsLine("c decisions", solver.decisions, (double)solver.rnd_decisions*100.0/(double)solver.decisions, "% random");
-    printStatsLine("c propagations", solver.propagations, (double)solver.propagations/cpu_time, "/ sec");
-    printStatsLine("c conflict literals", solver.tot_literals, (double)(solver.max_literals - solver.tot_literals)*100.0/ (double)solver.max_literals, "% deleted");
 
-    //General stats
-    printStatsLine("c Memory used", (double)mem_used / 1048576.0, " MB");
-    printStatsLine("c CPU time", cpu_time, " s");
-}
+    //Then read the main file or standard input
+    if (!fileNamePresent) {
+        readInStandardInput(solver);
+    } else {
+        string filename = argv[(twoFileNamesPresent ? argc-2 : argc-1)];
+        readInAFile(filename, solver);
+    }
 
-Solver* solver;
-static void SIGINT_handler(int signum)
-{
-    printf("\n");
-    printf("*** INTERRUPTED ***\n");
-    printStats(*solver);
-    if (dumpLearnts) {
-        solver->dumpSortedLearnts(learnts_filename, maxLearntsSize);
-        cout << "c Sorted learnt clauses dumped to file '" << learnts_filename << "'" << endl;
+    if (solver.conf.verbosity >= 1) {
+        std::cout << "c Parsing time: "
+        << std::fixed << std::setw(5) << std::setprecision(2) << (cpuTime() - myTime)
+        << " s" << std::endl;
     }
-    printf("\n");
-    printf("*** INTERRUPTED ***\n");
-    exit(1);
 }
 
-
 //=================================================================================================
 // Main:
 
-void printUsage(char** argv, Solver& S)
+void Main::printUsage(char** argv)
 {
 #ifdef DISABLE_ZLIB
     printf("USAGE: %s [options] <input-file> <result-output-file>\n\n  where input is plain DIMACS.\n\n", argv[0]);
@@ -458,6 +231,7 @@ void printUsage(char** argv, Solver& S)
     printf("                     regular clauses\n");
     printf("  --noregbxorfind  = Don't regularly find and collect 2-long xor-clauses\n");
     printf("                     from regular clauses\n");
+    printf("  --noextendedscc  = Don't do strongly conn. comp. finding using non-exist. bins\n");
     printf("  --noconglomerate = Don't conglomerate 2 xor clauses when one var is dependent\n");
     printf("  --nosimplify     = Don't do regular simplification rounds\n");
     printf("  --greedyunbound  = Greedily unbound variables that are not needed for SAT\n");
@@ -478,20 +252,27 @@ void printUsage(char** argv, Solver& S)
     printf("                     should be maximum length of the clause dumped. Useful\n");
     printf("                     to make the resulting file smaller. Default is 2^32-1\n");
     printf("                     note: 2-long XOR-s are always dumped.\n");
+    printf("  --dumporig       = <filename> If interrupted or reached restart limit, dump\n");
+    printf("                     the original problem instance, simplified to the\n");
+    printf("                     current point.\n");
+    printf("  --alsoread       = <filename> Also read this file in\n");
+    printf("                     Can be used to re-read dumped learnts, for example\n");
     printf("  --maxsolutions   = Search for given amount of solutions\n");
-    printf("  --nofailedvar    = Don't search for failed vars, and don't search for vars\n");
-    printf("                     doubly propagated to the same value\n");
+    printf("                     Can only be used in single-threaded more (\"--threads=1\")\n");
+    printf("  --pavgbranch     = Print average branch depth\n");
+    printf("  --nofailedlit    = Don't search for failed literals, and don't search for lits\n");
+    printf("                     propagated both by 'varX' and '-varX'\n");
     printf("  --noheuleprocess = Don't try to minimise XORs by XOR-ing them together.\n");
     printf("                     Algo. as per global/local substitution in Heule's thesis\n");
     printf("  --nosatelite     = Don't do clause subsumption, clause strengthening and\n");
     printf("                     variable elimination (implies -novarelim and -nosubsume1).\n");
     printf("  --noxorsubs      = Don't try to subsume xor-clauses.\n");
-    printf("  --nohyperbinres  = Don't carry out hyper-binary resolution\n");
     printf("  --nosolprint     = Don't print the satisfying assignment if the solution\n");
     printf("                     is SAT\n");
     printf("  --novarelim      = Don't perform variable elimination as per Een and Biere\n");
     printf("  --nosubsume1     = Don't perform clause contraction through resolution\n");
-    printf("  --noparthander   = Don't find and solve subroblems with subsolvers\n");
+    printf("  --noparthandler  = Don't find and solve subroblems with subsolvers\n");
+#ifdef USE_GAUSS
     printf("  --nomatrixfind   = Don't find distinct matrixes. Put all xors into one\n");
     printf("                     big matrix\n");
     printf("  --noordercol     = Don't order variables in the columns of Gaussian\n");
@@ -500,24 +281,41 @@ void printUsage(char** argv, Solver& S)
     printf("  --noiterreduce   = Don't reduce iteratively the matrix that is updated\n");
     printf("  --maxmatrixrows  = [0 - 2^32-1] Set maximum no. of rows for gaussian matrix.\n");
     printf("                     Too large matrixes should bee discarded for\n");
-    printf("                     reasons of efficiency. Default: %d\n", S.gaussconfig.maxMatrixRows);
+    printf("                     reasons of efficiency. Default: %d\n", gaussconfig.maxMatrixRows);
     printf("  --minmatrixrows  = [0 - 2^32-1] Set minimum no. of rows for gaussian matrix.\n");
     printf("                     Normally, too small matrixes are discarded for\n");
-    printf("                     reasons of efficiency. Default: %d\n", S.gaussconfig.minMatrixRows);
+    printf("                     reasons of efficiency. Default: %d\n", gaussconfig.minMatrixRows);
     printf("  --savematrix     = [0 - 2^32-1] Save matrix every Nth decision level.\n");
-    printf("                     Default: %d\n", S.gaussconfig.only_nth_gauss_save);
+    printf("                     Default: %d\n", gaussconfig.only_nth_gauss_save);
+    printf("  --maxnummatrixes = [0 - 2^32-1] Maximum number of matrixes to treat.\n");
+    printf("                     Default: %d\n", gaussconfig.maxNumMatrixes);
+#endif //USE_GAUSS
     //printf("  --addoldlearnts  = Readd old learnts for failed variable searching.\n");
     //printf("                     These learnts are usually deleted, but may help\n");
-    printf("  --noextrabins    = Don't add binary clauses when doing failed lit probing.\n");
+    printf("  --nohyperbinres  = Don't add binary clauses when doing failed lit probing.\n");
     printf("  --noremovebins   = Don't remove useless binary clauses\n");
-    printf("  --noregremovebins= Don't remove useless binary clauses regularly\n");
-    printf("  --nosubswithbins = Don't subsume with non-existent bins\n");
-    printf("  --norsubswithbins= Don't subsume regularly with non-existent bins\n");
+    printf("  --noremlbins     = Don't remove useless learnt binary clauses\n");
+    printf("  --nosubswithbins = Don't subsume with binary clauses\n");
+    printf("  --nosubswithnbins= Don't subsume with non-existent binary clauses\n");
+    printf("  --noclausevivif  = Don't do perform clause vivification\n");
+    printf("  --nosortwatched  = Don't sort watches according to size: bin, tri, etc.\n");
+    printf("  --nolfminim      = Don't do on-the-fly self-subsuming resolution\n");
+    printf("                     (called 'strong minimisation' in PrecoSat)\n");
+    printf("  --nocalcreach    = Don't calculate reachability and interfere with\n");
+    printf("                     variable decisions accordingly\n");
+    printf("  --norecotfssr    = Don't perform recursive/transitive OTF self-\n");
+    printf("                     subsuming resolution\n");
+    printf("  --nocacheotfssr  = Don't cache 1-level equeue. Less memory used, but\n");
+    printf("                     disables trans OTFSSR, adv. clause vivifier, etc.\n");
+    printf("  --maxgluedel     = Automatically delete clauses over max glue. See '--maxglue'\n");
+    printf("  --maxglue        = [0 - 2^%d-1] default: %d. Glue value above which we\n", MAX_GLUE_BITS, conf.maxGlue);
+    printf("                     throw the clause away on backtrack.\n");
+    printf("  --threads        = Num threads (default is 1)\n");
     printf("\n");
 }
 
 
-const char* hasPrefix(const char* str, const char* prefix)
+const char* Main::hasPrefix(const char* str, const char* prefix)
 {
     int len = strlen(prefix);
     if (strncmp(str, prefix, len) == 0)
@@ -526,28 +324,63 @@ const char* hasPrefix(const char* str, const char* prefix)
         return NULL;
 }
 
-}; //NAMESPACE MINISAT
-
-int main(int argc, char** argv)
+void Main::printResultFunc(const Solver& S, const lbool ret, FILE* res)
 {
-    Solver      S;
-    S.verbosity = 2;
+    if (res != NULL) {
+        if (ret == l_True) {
+            std::cout << "c SAT" << std::endl;
+            fprintf(res, "SAT\n");
+            if (printResult) {
+                for (Var var = 0; var != S.nVars(); var++)
+                    if (S.model[var] != l_Undef)
+                        fprintf(res, "%s%d ", (S.model[var] == l_True)? "" : "-", var+1);
+                    fprintf(res, "0\n");
+            }
+        } else if (ret == l_False) {
+            std::cout << "c UNSAT" << std::endl;
+            fprintf(res, "UNSAT\n");
+        } else {
+            std::cout << "c INCONCLUSIVE" << std::endl;
+            fprintf(res, "INCONCLUSIVE\n");
+        }
+        fclose(res);
+    } else {
+        if (ret == l_True)
+            std::cout << "s SATISFIABLE" << std::endl;
+        else if (ret == l_False)
+            std::cout << "s UNSATISFIABLE" << std::endl;
 
+        if(ret == l_True && printResult) {
+            std::stringstream toPrint;
+            toPrint << "v ";
+            for (Var var = 0; var != S.nVars(); var++)
+                if (S.model[var] != l_Undef)
+                    toPrint << ((S.model[var] == l_True)? "" : "-") << var+1 << " ";
+                toPrint << "0" << std::endl;
+            std::cout << toPrint.str();
+        }
+    }
+}
+
+void Main::parseCommandLine()
+{
     const char* value;
-    int j = 0;
-    unsigned long max_nr_of_solutions = 1;
-    unsigned long current_nr_of_solutions = 1;
+    char tmpFilename[201];
+    tmpFilename[0] = '\0';
+    uint32_t unparsedOptions = 0;
+    bool needTwoFileNames = false;
+    conf.verbosity = 2;
 
     for (int i = 0; i < argc; i++) {
         if ((value = hasPrefix(argv[i], "--polarity-mode="))) {
             if (strcmp(value, "true") == 0)
-                S.polarity_mode = Solver::polarity_true;
+                conf.polarity_mode = polarity_true;
             else if (strcmp(value, "false") == 0)
-                S.polarity_mode = Solver::polarity_false;
+                conf.polarity_mode = polarity_false;
             else if (strcmp(value, "rnd") == 0)
-                S.polarity_mode = Solver::polarity_rnd;
+                conf.polarity_mode = polarity_rnd;
             else if (strcmp(value, "auto") == 0)
-                S.polarity_mode = Solver::polarity_auto;
+                conf.polarity_mode = polarity_auto;
             else {
                 printf("ERROR! unknown polarity-mode %s\n", value);
                 exit(0);
@@ -556,10 +389,10 @@ int main(int argc, char** argv)
         } else if ((value = hasPrefix(argv[i], "--rnd-freq="))) {
             double rnd;
             if (sscanf(value, "%lf", &rnd) <= 0 || rnd < 0 || rnd > 1) {
-                printf("ERROR! illegal rnd-freq constant %s\n", value);
+                printf("ERROR! illegal rnRSE ERROR!d-freq constant %s\n", value);
                 exit(0);
             }
-            S.random_var_freq = rnd;
+            conf.random_var_freq = rnd;
 
         /*} else if ((value = hasPrefix(argv[i], "--decay="))) {
             double decay;
@@ -567,7 +400,7 @@ int main(int argc, char** argv)
                 printf("ERROR! illegal decay constant %s\n", value);
                 exit(0);
             }
-            S.var_decay = 1 / decay;*/
+            conf.var_decay = 1 / decay;*/
 
         } else if ((value = hasPrefix(argv[i], "--verbosity="))) {
             int verbosity = (int)strtol(value, NULL, 10);
@@ -575,15 +408,15 @@ int main(int argc, char** argv)
                 printf("ERROR! illegal verbosity level %s\n", value);
                 exit(0);
             }
-            S.verbosity = verbosity;
+            conf.verbosity = verbosity;
         #ifdef STATS_NEEDED
         } else if ((value = hasPrefix(argv[i], "--grouping"))) {
             grouping = true;
         } else if ((value = hasPrefix(argv[i], "--proof-log"))) {
-            S.needProofGraph();
+            conf.needProofGraph();
 
         } else if ((value = hasPrefix(argv[i], "--stats"))) {
-            S.needStats();
+            conf.needStats();
         #endif
 
         } else if ((value = hasPrefix(argv[i], "--randomize="))) {
@@ -592,131 +425,153 @@ int main(int argc, char** argv)
                 printf("ERROR! illegal seed %s\n", value);
                 exit(0);
             }
-            cout << "c seed:" << seed << endl;
-            S.setSeed(seed);
+            conf.origSeed = seed;
         } else if ((value = hasPrefix(argv[i], "--restrict="))) {
-            uint branchTo;
+            uint32_t branchTo;
             if (sscanf(value, "%d", &branchTo) < 0 || branchTo < 1) {
                 printf("ERROR! illegal restricted pick branch number %d\n", branchTo);
                 exit(0);
             }
-            S.restrictedPickBranch = branchTo;
+            conf.restrictPickBranch = branchTo;
         } else if ((value = hasPrefix(argv[i], "--gaussuntil="))) {
             uint32_t until;
             if (sscanf(value, "%d", &until) < 0) {
                 printf("ERROR! until %s\n", value);
                 exit(0);
             }
-            S.gaussconfig.decision_until = until;
+            gaussconfig.decision_until = until;
         } else if ((value = hasPrefix(argv[i], "--restarts="))) {
-            uint maxrest;
+            uint32_t maxrest;
             if (sscanf(value, "%d", &maxrest) < 0 || maxrest == 0) {
                 printf("ERROR! illegal maximum restart number %d\n", maxrest);
                 exit(0);
             }
-            S.setMaxRestarts(maxrest);
+            conf.maxRestarts = maxrest;
         } else if ((value = hasPrefix(argv[i], "--dumplearnts="))) {
-            if (sscanf(value, "%400s", learnts_filename) < 0 || strlen(learnts_filename) == 0) {
-                printf("ERROR! wrong filename '%s'\n", learnts_filename);
+            if (sscanf(value, "%200s", tmpFilename) < 0 || strlen(tmpFilename) == 0) {
+                printf("ERROR! wrong filename '%s'\n", tmpFilename);
+                exit(0);
+            }
+            conf.learntsFilename.assign(tmpFilename);
+            conf.needToDumpLearnts = true;
+        } else if ((value = hasPrefix(argv[i], "--dumporig="))) {
+            if (sscanf(value, "%200s", tmpFilename) < 0 || strlen(tmpFilename) == 0) {
+                printf("ERROR! wrong filename '%s'\n", tmpFilename);
                 exit(0);
             }
-            dumpLearnts = true;
+            conf.origFilename.assign(tmpFilename);
+            conf.needToDumpOrig = true;
+        } else if ((value = hasPrefix(argv[i], "--alsoread="))) {
+            if (sscanf(value, "%400s", tmpFilename) < 0 || strlen(tmpFilename) == 0) {
+                printf("ERROR! wrong filename '%s'\n", tmpFilename);
+                exit(0);
+            }
+            filesToRead.push_back(tmpFilename);
         } else if ((value = hasPrefix(argv[i], "--maxdumplearnts="))) {
-            if (!dumpLearnts) {
+            if (!conf.needToDumpLearnts) {
                 printf("ERROR! -dumplearnts=<filename> must be first activated before issuing -maxdumplearnts=<size>\n");
                 exit(0);
             }
             int tmp;
             if (sscanf(value, "%d", &tmp) < 0 || tmp < 0) {
-                cout << "ERROR! wrong maximum dumped learnt clause size is illegal: " << tmp << endl;
+                std::cout << "ERROR! wrong maximum dumped learnt clause size is illegal: " << tmp << std::endl;
                 exit(0);
             }
-            maxLearntsSize = (uint32_t)tmp;
+            conf.maxDumpLearntsSize = (uint32_t)tmp;
         } else if ((value = hasPrefix(argv[i], "--maxsolutions="))) {
             int tmp;
             if (sscanf(value, "%d", &tmp) < 0 || tmp < 0) {
-                cout << "ERROR! wrong maximum number of solutions is illegal: " << tmp << endl;
+                std::cout << "ERROR! wrong maximum number of solutions is illegal: " << tmp << std::endl;
                 exit(0);
             }
             max_nr_of_solutions = (uint32_t)tmp;
+
+        } else if ((value = hasPrefix(argv[i], "--pavgbranch"))) {
+            conf.doPrintAvgBranch = true;
         } else if ((value = hasPrefix(argv[i], "--greedyunbound"))) {
-            S.greedyUnbound = true;
+            conf.greedyUnbound = true;
         } else if ((value = hasPrefix(argv[i], "--nonormxorfind"))) {
-            S.findNormalXors = false;
+            conf.doFindXors = false;
         } else if ((value = hasPrefix(argv[i], "--nobinxorfind"))) {
-            S.findBinaryXors = false;
+            conf.doFindEqLits = false;
         } else if ((value = hasPrefix(argv[i], "--noregbxorfind"))) {
-            S.regularlyFindBinaryXors = false;
+            conf.doRegFindEqLits = false;
+        } else if ((value = hasPrefix(argv[i], "--noextendedscc"))) {
+            conf.doExtendedSCC = false;
         } else if ((value = hasPrefix(argv[i], "--noconglomerate"))) {
-            S.conglomerateXors = false;
+            conf.doConglXors = false;
         } else if ((value = hasPrefix(argv[i], "--nosimplify"))) {
-            S.schedSimplification = false;
+            conf.doSchedSimp = false;
         } else if ((value = hasPrefix(argv[i], "--debuglib"))) {
             debugLib = true;
         } else if ((value = hasPrefix(argv[i], "--debugnewvar"))) {
             debugNewVar = true;
         } else if ((value = hasPrefix(argv[i], "--novarreplace"))) {
-            S.performReplace = false;
-        } else if ((value = hasPrefix(argv[i], "--nofailedvar"))) {
-            S.failedVarSearch = false;
+            conf.doReplace = false;
+        } else if ((value = hasPrefix(argv[i], "--nofailedlit"))) {
+            conf.doFailedLit = false;
         } else if ((value = hasPrefix(argv[i], "--nodisablegauss"))) {
-            S.gaussconfig.dontDisable = true;
+            gaussconfig.dontDisable = true;
+        } else if ((value = hasPrefix(argv[i], "--maxnummatrixes="))) {
+            uint32_t maxNumMatrixes;
+            if (sscanf(value, "%d", &maxNumMatrixes) < 0) {
+                printf("ERROR! maxnummatrixes: %s\n", value);
+                exit(0);
+            }
+            gaussconfig.maxNumMatrixes = maxNumMatrixes;
         } else if ((value = hasPrefix(argv[i], "--noheuleprocess"))) {
-            S.heuleProcess = false;
+            conf.doHeuleProcess = false;
         } else if ((value = hasPrefix(argv[i], "--nosatelite"))) {
-            S.doSubsumption = false;
+            conf.doSatELite = false;
         } else if ((value = hasPrefix(argv[i], "--noparthandler"))) {
-            S.doPartHandler = false;
+            conf.doPartHandler = false;
         } else if ((value = hasPrefix(argv[i], "--noxorsubs"))) {
-            S.doXorSubsumption = false;
+            conf.doXorSubsumption = false;
         } else if ((value = hasPrefix(argv[i], "--nohyperbinres"))) {
-            S.doHyperBinRes = false;
-        } else if ((value = hasPrefix(argv[i], "--noblockedclause"))) {
-            S.doBlockedClause = false;
+            conf.doHyperBinRes = false;
         } else if ((value = hasPrefix(argv[i], "--novarelim"))) {
-            S.doVarElim = false;
+            conf.doVarElim = false;
         } else if ((value = hasPrefix(argv[i], "--nosubsume1"))) {
-            S.doSubsume1 = false;
+            conf.doSubsume1 = false;
         } else if ((value = hasPrefix(argv[i], "--nomatrixfind"))) {
-            S.gaussconfig.noMatrixFind = true;
+            gaussconfig.noMatrixFind = true;
         } else if ((value = hasPrefix(argv[i], "--noiterreduce"))) {
-            S.gaussconfig.iterativeReduce = false;
+            gaussconfig.iterativeReduce = false;
         } else if ((value = hasPrefix(argv[i], "--noiterreduce"))) {
-            S.gaussconfig.iterativeReduce = false;
+            gaussconfig.iterativeReduce = false;
         } else if ((value = hasPrefix(argv[i], "--noordercol"))) {
-            S.gaussconfig.orderCols = false;
-        } else if ((value = hasPrefix(argv[i], "--maxmatrixrows"))) {
-            uint32_t rows;
-            if (sscanf(value, "%d", &rows) < 0) {
+            gaussconfig.orderCols = false;
+        } else if ((value = hasPrefix(argv[i], "--maxmatrixrows="))) {
+            int rows;
+            if (sscanf(value, "%d", &rows) < 0 || rows < 0) {
                 printf("ERROR! maxmatrixrows: %s\n", value);
                 exit(0);
             }
-            S.gaussconfig.maxMatrixRows = rows;
-        } else if ((value = hasPrefix(argv[i], "--minmatrixrows"))) {
-            uint32_t rows;
-            if (sscanf(value, "%d", &rows) < 0) {
+            gaussconfig.maxMatrixRows = (uint32_t)rows;
+        } else if ((value = hasPrefix(argv[i], "--minmatrixrows="))) {
+            int rows;
+            if (sscanf(value, "%d", &rows) < 0 || rows < 0) {
                 printf("ERROR! minmatrixrows: %s\n", value);
                 exit(0);
             }
-            S.gaussconfig.minMatrixRows = rows;
+            gaussconfig.minMatrixRows = rows;
         } else if ((value = hasPrefix(argv[i], "--savematrix"))) {
             uint32_t every;
             if (sscanf(value, "%d", &every) < 0) {
                 printf("ERROR! savematrix: %s\n", value);
                 exit(0);
             }
-            cout << "c Matrix saved every " <<  every << " decision levels" << endl;
-            S.gaussconfig.only_nth_gauss_save = every;
+            gaussconfig.only_nth_gauss_save = every;
         } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "--help") == 0) {
-            printUsage(argv, S);
+            printUsage(argv);
             exit(0);
         } else if ((value = hasPrefix(argv[i], "--restart="))) {
             if (strcmp(value, "auto") == 0)
-                S.fixRestartType = auto_restart;
+                conf.fixRestartType = auto_restart;
             else if (strcmp(value, "static") == 0)
-                S.fixRestartType = static_restart;
+                conf.fixRestartType = static_restart;
             else if (strcmp(value, "dynamic") == 0)
-                S.fixRestartType = dynamic_restart;
+                conf.fixRestartType = dynamic_restart;
             else {
                 printf("ERROR! unknown restart type %s\n", value);
                 exit(0);
@@ -724,159 +579,336 @@ int main(int argc, char** argv)
         } else if ((value = hasPrefix(argv[i], "--nosolprint"))) {
             printResult = false;
         //} else if ((value = hasPrefix(argv[i], "--addoldlearnts"))) {
-        //    S.readdOldLearnts = true;
-        } else if ((value = hasPrefix(argv[i], "--noextrabins"))) {
-            S.addExtraBins = false;
+        //    conf.readdOldLearnts = true;
+        } else if ((value = hasPrefix(argv[i], "--nohyperbinres"))) {
+            conf.doHyperBinRes= false;
         } else if ((value = hasPrefix(argv[i], "--noremovebins"))) {
-            S.removeUselessBins = false;
-        } else if ((value = hasPrefix(argv[i], "--noregremovebins"))) {
-            S.regularRemoveUselessBins = false;
+            conf.doRemUselessBins = false;
+        } else if ((value = hasPrefix(argv[i], "--nosubswithnbins"))) {
+            conf.doSubsWNonExistBins = false;
         } else if ((value = hasPrefix(argv[i], "--nosubswithbins"))) {
-            S.subsumeWithNonExistBinaries = false;
-        } else if ((value = hasPrefix(argv[i], "--norsubswithbins"))) {
-            S.regularSubsumeWithNonExistBinaries = false;
+            conf.doSubsWBins = false;
+        } else if ((value = hasPrefix(argv[i], "--noclausevivif"))) {
+            conf.doClausVivif = false;
+        } else if ((value = hasPrefix(argv[i], "--nosortwatched"))) {
+            conf.doSortWatched = false;
+        } else if ((value = hasPrefix(argv[i], "--nolfminim"))) {
+            conf.doMinimLearntMore = false;
+        } else if ((value = hasPrefix(argv[i], "--nocalcreach"))) {
+            conf.doCalcReach = false;
+        } else if ((value = hasPrefix(argv[i], "--norecotfssr"))) {
+            conf.doMinimLMoreRecur = false;
+        } else if ((value = hasPrefix(argv[i], "--nocacheotfssr"))) {
+            conf.doCacheOTFSSR = false;
+        } else if ((value = hasPrefix(argv[i], "--noremlbins"))) {
+            conf.doRemUselessLBins = false;
+        } else if ((value = hasPrefix(argv[i], "--maxglue="))) {
+            int glue = 0;
+            if (sscanf(value, "%d", &glue) < 0 || glue < 2) {
+                printf("ERROR! maxGlue: %s\n", value);
+                exit(0);
+            }
+            if (glue >= (1<< MAX_GLUE_BITS)-1) {
+                std::cout << "Due to memory-packing limitations, max glue cannot be more than "
+                << ((1<< MAX_GLUE_BITS)-2) << std::endl;
+                exit(-1);
+            }
+            conf.maxGlue = (uint32_t)glue;
+        } else if ((value = hasPrefix(argv[i], "--maxgluedel"))) {
+            conf.doMaxGlueDel = true;
+        } else if ((value = hasPrefix(argv[i], "--threads="))) {
+            numThreads = 0;
+            if (sscanf(value, "%d", &numThreads) < 0 || numThreads < 1) {
+                printf("ERROR! numThreads: %s\n", value);
+                exit(0);
+            }
         } else if (strncmp(argv[i], "-", 1) == 0 || strncmp(argv[i], "--", 2) == 0) {
             printf("ERROR! unknown flag %s\n", argv[i]);
             exit(0);
-        } else
-            argv[j++] = argv[i];
+        } else {
+            //std::std::cout << "argc:" << argc << " i:" << i << ", value:" << argv[i] << std::endl;
+            unparsedOptions++;
+            if (unparsedOptions == 2) {
+                if (!(argc <= i+2)) {
+                    std::cout << "You must give the input file as either:" << std::endl;
+                    std::cout << " -- last option if you want the output to the console" << std::endl;
+                    std::cout << " -- or one before the last option" << std::endl;
+                    std::cout << "It appears that you did neither. Maybe you forgot the '--' from an option?" << std::endl;
+                    exit(-1);
+                }
+                fileNamePresent = true;
+                if (argc == i+2) needTwoFileNames = true;
+            }
+            if (unparsedOptions == 3) {
+                if (!(argc <= i+1)) {
+                    std::cout << "You must give the output file as the last option. Exiting" << std::endl;
+                    exit(-1);
+                }
+                twoFileNamesPresent = true;
+            }
+            if (unparsedOptions == 4) {
+                std::cout << "You gave more than two filenames as parameters." << std::endl;
+                std::cout << "The first one is interpreted as the input, the second is the output." << std::endl;
+                std::cout << "However, the third one I cannot do anything with. EXITING" << std::endl;
+                exit(-1);
+            }
+        }
+    }
+    if (conf.verbosity >= 1) {
+        if (twoFileNamesPresent) {
+            std::cout << "c Outputting solution to file: " << argv[argc-1] << std::endl;
+        } else {
+            std::cout << "c Outputting solution to console" << std::endl;
+        }
     }
-    argc = j;
-    if (!debugLib) S.libraryUsage = false;
 
-    if (S.verbosity >= 1)
-        printf("c This is CryptoMiniSat %s\n", VERSION);
-#if defined(__linux__)
+    if (unparsedOptions == 2 && needTwoFileNames == true) {
+        std::cout << "Command line wrong. You probably frogot to add "<< std::endl
+        << "the '--'  in front of one of the options, or you started" << std::endl
+        << "your output file with a hyphen ('-'). Exiting." << std::endl;
+        exit(-1);
+    }
+    if (!debugLib) conf.libraryUsage = false;
+}
+
+FILE* Main::openOutputFile()
+{
+    FILE* res = NULL;
+    if (twoFileNamesPresent) {
+        char* filename = argv[argc-1];
+        res = fopen(filename, "wb");
+        if (res == NULL) {
+            int backup_errno = errno;
+            printf("Cannot open %s for writing. Problem: %s", filename, strerror(backup_errno));
+            exit(1);
+        }
+    }
+
+    return res;
+}
+
+void Main::setDoublePrecision(const uint32_t verbosity)
+{
+    #if defined(__linux__)
     fpu_control_t oldcw, newcw;
     _FPU_GETCW(oldcw);
     newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
     _FPU_SETCW(newcw);
-    if (S.verbosity >= 1) printf("c WARNING: for repeatability, setting FPU to use double precision\n");
+    if (verbosity >= 1) printf("c WARNING: for repeatability, setting FPU to use double precision\n");
 #endif
-    double cpu_time = cpuTime();
+}
 
-    solver = &S;
-    signal(SIGINT,SIGINT_handler);
-    //signal(SIGHUP,SIGINT_handler);
+void Main::printVersionInfo(const uint32_t verbosity)
+{
+    if (verbosity >= 1) {
+        printf("c This is CryptoMiniSat %s\n", VERSION);
+        #ifdef __GNUC__
+        printf("c compiled with gcc version %s\n",  __VERSION__);
+        #else
+        printf("c compiled with non-gcc compiler\n");
+        #endif
+    }
+}
 
-    if (argc == 1)
-        printf("c Reading from standard input... Use '-h' or '--help' for help.\n");
+const int Main::singleThreadSolve()
+{
+    Solver solver(conf, gaussconfig);
+    solversToInterrupt[0] = &solver;
 
-#ifdef DISABLE_ZLIB
-    FILE * in = (argc == 1) ? fopen(0, "rb") : fopen(argv[1], "rb");
-#else
-    gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb");
-#endif // DISABLE_ZLIB
-    if (in == NULL) {
-        printf("ERROR! Could not open file: %s\n", argc == 1 ? "<stdin>" : argv[1]);
-        exit(1);
+    printVersionInfo(conf.verbosity);
+    setDoublePrecision(conf.verbosity);
+
+    parseInAllFiles(solver);
+    FILE* res = openOutputFile();
+
+    unsigned long current_nr_of_solutions = 0;
+    lbool ret = l_True;
+    while(current_nr_of_solutions < max_nr_of_solutions && ret == l_True) {
+        ret = solver.solve();
+        current_nr_of_solutions++;
+
+        if (ret == l_True && current_nr_of_solutions < max_nr_of_solutions) {
+            if (conf.verbosity >= 1) std::cout << "c Prepare for next run..." << std::endl;
+            printResultFunc(solver, ret, res);
+
+            vec<Lit> lits;
+            for (Var var = 0; var != solver.nVars(); var++) {
+                if (solver.model[var] != l_Undef) {
+                    lits.push( Lit(var, (solver.model[var] == l_True)? true : false) );
+                }
+            }
+            solver.addClause(lits);
+        }
     }
 
-    if (S.verbosity >= 1) {
-        printf("c =================================[ Problem Statistics ]==================================\n");
-        printf("c |                                                                                       |\n");
+    if (conf.needToDumpLearnts) {
+        solver.dumpSortedLearnts(conf.learntsFilename, conf.maxDumpLearntsSize);
+        std::cout << "c Sorted learnt clauses dumped to file '" << conf.learntsFilename << "'" << std::endl;
+    }
+    if (conf.needToDumpOrig) {
+        solver.dumpOrigClauses(conf.origFilename);
+        std::cout << "c Simplified original clauses dumped to file '" << conf.origFilename << "'" << std::endl;
     }
+    if (ret == l_Undef && conf.verbosity >= 1) {
+        std::cout << "c Not finished running -- signal caught or maximum restart reached" << std::endl;
+    }
+    if (conf.verbosity >= 1) solver.printStats();
+    printResultFunc(solver, ret, res);
 
-    parse_DIMACS(in, S);
+    return correctReturnValue(ret);
+}
 
-#ifdef DISABLE_ZLIB
-    fclose(in);
-#else
-    gzclose(in);
-#endif // DISABLE_ZLIB
-    if (argc >= 3)
-        printf("c Outputting solution to file: %s\n" , argv[2]);
+int Main::correctReturnValue(const lbool ret) const
+{
+    int retval = -1;
+    if      (ret == l_True)  retval = 10;
+    else if (ret == l_False) retval = 20;
+    else if (ret == l_Undef) retval = 15;
+    else {
+        std::cerr << "Something is very wrong, output is neither l_Undef, nor l_False, nor l_True" << std::endl;
+        exit(-1);
+    }
 
-    double parse_time = cpuTime() - cpu_time;
-    if (S.verbosity >= 1)
-        printf("c |  Parsing time:         %-12.2f s                                                 |\n", parse_time);
+    #ifdef NDEBUG
+    // (faster than "return", which will invoke the destructor for 'Solver')
+    exit(retval);
+    #endif
+    return retval;
+}
 
-    lbool ret;
+const int Main::oneThreadSolve()
+{
+    int numThreads = omp_get_num_threads();
+    SolverConf myConf = conf;
+    int num = omp_get_thread_num();
+    myConf.origSeed = num;
+    if (num > 0) {
+        if (num % 4 == 3) myConf.fixRestartType = dynamic_restart;
+        if (num % 4 == 2) myConf.doCalcReach = false;
+        //else myConf.fixRestartType = static_restart;
+        myConf.simpBurstSConf *= 1 + num;
+        myConf.simpStartMult *= 1.0 + 0.2*(double)num;
+        myConf.simpStartMMult *= 1.0 + 0.2*(double)num;
+        if (num == numThreads-1) {
+            //myConf.doVarElim = false;
+            myConf.doPerformPreSimp = false;
+            myConf.polarity_mode = polarity_false;
+        }
+    }
+    if (num != 0) myConf.verbosity = 0;
 
-    while(1)
+    Solver solver(myConf, gaussconfig, &sharedData);
+    #pragma omp critical (solversToInterr)
     {
-        ret = S.solve();
-        if ( ret != l_True ) break;
+        solversToInterrupt[num] = &solver;
+        //std::cout << "Solver num " << num << " is to be interrupted " << std::endl;
+    }
 
-        std::cout << "c " << std::setw(8) << current_nr_of_solutions++ << " solution(s) found" << std::endl;
+    printVersionInfo(myConf.verbosity);
+    setDoublePrecision(myConf.verbosity);
 
-        if (current_nr_of_solutions > max_nr_of_solutions) break;
-        printf("c Prepare for next run...\n");
+    parseInAllFiles(solver);
+    lbool ret = solver.solve();
+    #pragma omp critical (finished)
+    {
+        finished.insert(num);
+    }
 
-        vec<Lit> lits;
-        if (printResult) printf("v ");
-        for (Var var = 0; var != S.nVars(); var++) {
-            if (S.model[var] != l_Undef) {
-                lits.push( Lit(var, (S.model[var] == l_True)? true : false) );
-                if (printResult) printf("%s%d ", (S.model[var] == l_True)? "" : "-", var+1);
+    int retval = 0;
+    #pragma omp single
+    {
+        int numNeededInterrupt = 0;
+        while(numNeededInterrupt != numThreads-1) {
+            #pragma omp critical (solversToInterr)
+            {
+                for(int i = 0; i < numThreads; i++) {
+                    if (i != num
+                        && solversToInterrupt.find(i) != solversToInterrupt.end()
+                        && solversToInterrupt[i]->needToInterrupt == false
+                        ) {
+                        solversToInterrupt[i]->needToInterrupt = true;
+                        numNeededInterrupt++;
+                    }
+                }
             }
         }
-        if (printResult) printf("\n");
-        
-        S.addClause(lits);
-    }
+        bool mustWait = true;
+        while (mustWait) {
+            #pragma omp critical (finished)
+            if (finished.size() == (unsigned)numThreads) mustWait = false;
+        }
+        if (conf.needToDumpLearnts) {
+            solver.dumpSortedLearnts(conf.learntsFilename, conf.maxDumpLearntsSize);
+            if (conf.verbosity >= 1) {
+                std::cout << "c Sorted learnt clauses dumped to file '"
+                << conf.learntsFilename << "'" << std::endl;
+            }
+        }
+        if (conf.needToDumpOrig) {
+            solver.dumpOrigClauses(conf.origFilename);
+            if (conf.verbosity >= 1)
+                std::cout << "c Simplified original clauses dumped to file '"
+                << conf.origFilename << "'" << std::endl;
+        }
 
-    printStats(S);
-    printf("c \n");
-    if (dumpLearnts) {
-        S.dumpSortedLearnts(learnts_filename, maxLearntsSize);
-        cout << "c Sorted learnt clauses dumped to file '" << learnts_filename << "'" << endl;
+        FILE* res = openOutputFile();
+        if (conf.verbosity >= 1) solver.printStats();
+        printResultFunc(solver, ret, res);
+
+        retval = correctReturnValue(ret);
+        exit(retval);
     }
-    if (ret == l_Undef)
-        printf("c Not finished running -- maximum restart reached\n");
+    return retval;
+}
 
-    FILE* res = NULL;
-    if (argc >= 3) {
-        res = fopen(argv[2], "wb");
-        if (res == NULL) {
-            int backup_errno = errno;
-            printf("Cannot open %s for writing. Problem: %s", argv[2], strerror(backup_errno));
-            exit(1);
-        }
+const int Main::multiThreadSolve()
+{
+    bool exitHere = false;
+    if (max_nr_of_solutions > 1) {
+        std::cerr << "ERROR: When multi-threading, only one solution can be found" << std::endl;
+        exitHere = true;
+    }
+    if (debugLib) {
+        std::cerr << "ERROR: When multi-threading, --debuglib cannot be used" << std::endl;
+        exitHere = true;
+    }
+    if (exitHere) {
+        std::cerr << "libarary in this version of CryptoMS is not multi-threaded :(" << std::endl;
+        std::cerr << "Please set option '--threads=1' on the command line." << std::endl;
+        exit(-1);
     }
 
-    if (res != NULL) {
-        if (ret == l_True) {
-            printf("c SAT\n");
-            fprintf(res, "SAT\n");
-            if (printResult) {
-                for (Var var = 0; var != S.nVars(); var++)
-                    if (S.model[var] != l_Undef)
-                        fprintf(res, "%s%d ", (S.model[var] == l_True)? "" : "-", var+1);
-                    fprintf(res, "0\n");
-            }
-        } else if (ret == l_False) {
-            printf("c UNSAT\n");
-            fprintf(res, "UNSAT\n");
-        } else {
-            printf("c INCONCLUSIVE\n");
-            fprintf(res, "INCONCLUSIVE\n");
+    int finalRetVal;
+    if (numThreads != -1) {
+        assert(numThreads > 0);
+        omp_set_num_threads(numThreads);
+    }
+    #pragma omp parallel
+    {
+        #pragma omp single
+        {
+            if (conf.verbosity >= 1)
+                std::cout << "c Using " << omp_get_num_threads()
+                << " threads" << std::endl;
         }
-        fclose(res);
-    } else {
-        if (ret == l_True)
-            printf("s SATISFIABLE\n");
-        else if (ret == l_False)
-            printf("s UNSATISFIABLE\n");
+        int retval = oneThreadSolve();
 
-        if(ret == l_True && printResult) {
-            printf("v ");
-            for (Var var = 0; var != S.nVars(); var++)
-                if (S.model[var] != l_Undef)
-                    printf("%s%d ", (S.model[var] == l_True)? "" : "-", var+1);
-                printf("0\n");
-        }
+        #pragma omp single
+        finalRetVal = retval;
     }
 
-#ifdef NDEBUG
-    exit(ret == l_True ? 10 : 20);     // (faster than "return", which will invoke the destructor for 'Solver')
-#endif
+    return finalRetVal;
+}
 
-    if (ret == l_True) return 10;
-    if (ret == l_False) return 20;
-    if (ret == l_Undef) return 15;
-    assert(false);
+int main(int argc, char** argv)
+{
+    Main main(argc, argv);
+    main.parseCommandLine();
+    signal(SIGINT, SIGINT_handler);
+    //signal(SIGHUP,SIGINT_handler);
 
-    return 0;
+    if (main.numThreads == 1)
+        return main.singleThreadSolve();
+    else
+        return main.multiThreadSolve();
 }
-
diff --git a/src/sat/cryptominisat2/Main.h b/src/sat/cryptominisat2/Main.h
new file mode 100644 (file)
index 0000000..f3d56a7
--- /dev/null
@@ -0,0 +1,69 @@
+/*****************************************************************************
+MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+Original code by MiniSat authors are under an MIT licence.
+Modifications for CryptoMiniSat are under GPLv3 licence.
+******************************************************************************/
+
+#ifndef MAIN_H
+#define MAIN_H
+
+#include <string>
+using std::string;
+#include <vector>
+#ifndef DISABLE_ZLIB
+#include <zlib.h>
+#endif // DISABLE_ZLIB
+
+#include "Solver.h"
+#include "SharedData.h"
+
+class Main
+{
+    public:
+        Main(int argc, char** argv);
+
+        void parseCommandLine();
+
+        const int singleThreadSolve();
+        const int oneThreadSolve();
+        const int multiThreadSolve();
+
+        int numThreads;
+
+    private:
+
+        void printUsage(char** argv);
+        const char* hasPrefix(const char* str, const char* prefix);
+        void printResultFunc(const Solver& S, const lbool ret, FILE* res);
+
+        //File reading
+        void readInAFile(const std::string& filename, Solver& solver);
+        void readInStandardInput(Solver& solver);
+        void parseInAllFiles(Solver& solver);
+        FILE* openOutputFile();
+
+        void setDoublePrecision(const uint32_t verbosity);
+        void printVersionInfo(const uint32_t verbosity);
+        int correctReturnValue(const lbool ret) const;
+
+        SolverConf conf;
+        GaussConf gaussconfig;
+
+        bool grouping;
+        bool debugLib;
+        bool debugNewVar;
+        bool printResult;
+        uint32_t max_nr_of_solutions;
+        bool fileNamePresent;
+        bool twoFileNamesPresent;
+        std::vector<std::string> filesToRead;
+
+        SharedData sharedData;
+
+        int argc;
+        char** argv;
+};
+
+#endif //MAIN_H
index dbe77b45091f12347ba7c78a8091450cddae311a..c00c033aa530907b528f28436423254bd7df45ed 100644 (file)
@@ -5,15 +5,20 @@ MTL       = mtl
 MTRAND    = MTRand
 SOURCES   = Logger.cpp Solver.cpp PackedRow.cpp \
            XorFinder.cpp VarReplacer.cpp \
-           FindUndef.cpp ClauseCleaner.cpp RestartTypeChooser.cpp \
-           FailedVarSearcher.cpp PartFinder.cpp \
+           ClauseCleaner.cpp RestartTypeChooser.cpp \
+           PartFinder.cpp \
            Subsumer.cpp PartHandler.cpp XorSubsumer.cpp \
            Gaussian.cpp MatrixFinder.cpp StateSaver.cpp \
            ClauseAllocator.cpp UselessBinRemover.cpp \
-           OnlyNonLearntBins.cpp
+           OnlyNonLearntBins.cpp DataSync.cpp \
+            SolverConf.cpp FailedLitSearcher.cpp \
+            CompleteDetachReattacher.cpp \
+            ClauseVivifier.cpp SolverMisc.cpp \
+            DimacsParser.cpp SolverDebug.cpp \
+            SCCFinder.cpp
 OBJECTS   = $(SOURCES:.cpp=.o)
 LIB       = libminisat.a
-CFLAGS    += -I../.. -I$(MTL) -I$(MTRAND) -DEXT_HASH_MAP -ffloat-store $(CFLAGS_M32) -c
+CFLAGS    += -I../.. -I$(MTL) -I$(MTRAND) -fopenmp -DEXT_HASH_MAP -ffloat-store $(CFLAGS_M32) -c
 EXEC      = minisat
 LFLAGS    = -lz
 
index 35443a7bafc2bb21c437a9903cbf412a9f67353e..e4cb3679990ddd90a66c1b1b85f7d4550894243b 100644 (file)
@@ -35,10 +35,6 @@ using std::map;
 using std::cout;
 using std::endl;
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 //#define PART_FINDING
 
 MatrixFinder::MatrixFinder(Solver& _solver) :
@@ -49,16 +45,16 @@ MatrixFinder::MatrixFinder(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;
+    uint32_t i1, i2;
     for (i1 = 0, i2 = 0; i1 < c1.size() && i2 < c2.size();) {
         if (c1[i1].var() != c2[i2].var())
             i2++;
@@ -67,7 +63,7 @@ inline const bool MatrixFinder::firstPartOfSecond(const XorClause& c1, const Xor
             i2++;
         }
     }
-    
+
     return (i1 == c1.size());
 }
 
@@ -78,19 +74,20 @@ const bool MatrixFinder::findMatrixes()
     reverseTable.clear();
     matrix_no = 0;
     double myTime = cpuTime();
-    
+
     if (solver.xorclauses.size() < MIN_GAUSS_XOR_CLAUSES ||
         solver.gaussconfig.decision_until <= 0 ||
         solver.xorclauses.size() > MAX_GAUSS_XOR_CLAUSES
-        )
+        ) {
         return true;
-    
+    }
+
     solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses);
     if (!solver.ok) return false;
 
     if (solver.gaussconfig.noMatrixFind) {
-        if (solver.verbosity >=1)
-            cout << "c |  Matrix finding disabled through switch. Putting all xors into matrix." << endl;
+        if (solver.conf.verbosity >=1)
+            cout << "c Matrix finding disabled through switch. Putting all xors into matrix." << endl;
         vector<XorClause*> xorclauses;
         xorclauses.reserve(solver.xorclauses.size());
         for (uint32_t i = 0; i < solver.xorclauses.size(); i++)
@@ -98,9 +95,9 @@ const bool MatrixFinder::findMatrixes()
         solver.gauss_matrixes.push_back(new Gaussian(solver, solver.gaussconfig, 0, xorclauses));
         return true;
     }
-    
+
     for (XorClause** c = solver.xorclauses.getData(), **end = c + solver.xorclauses.size(); c != end; c++) {
-        set<uint> tomerge;
+        set<uint32_t> tomerge;
         vector<Var> newSet;
         for (Lit *l = &(**c)[0], *end2 = l + (**c).size(); l != end2; l++) {
             if (table[l->var()] != var_Undef)
@@ -109,27 +106,27 @@ const bool MatrixFinder::findMatrixes()
                 newSet.push_back(l->var());
         }
         if (tomerge.size() == 1) {
-            const uint into = *tomerge.begin();
-            map<uint, vector<Var> >::iterator intoReverse = reverseTable.find(into);
-            for (uint i = 0; i < newSet.size(); i++) {
+            const uint32_t into = *tomerge.begin();
+            map<uint32_t, vector<Var> >::iterator intoReverse = reverseTable.find(into);
+            for (uint32_t i = 0; i < newSet.size(); i++) {
                 intoReverse->second.push_back(newSet[i]);
                 table[newSet[i]] = into;
             }
             continue;
         }
-        
-        for (set<uint>::iterator it = tomerge.begin(); it != tomerge.end(); it++) {
+
+        for (set<uint32_t>::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++)
+        for (uint32_t i = 0; i < newSet.size(); i++)
             table[newSet[i]] = matrix_no;
         reverseTable[matrix_no] = newSet;
         matrix_no++;
     }
-    
+
     #ifdef VERBOSE_DEBUG
-    for (map<uint, vector<Var> >::iterator it = reverseTable.begin(), end = reverseTable.end(); it != end; it++) {
+    for (map<uint32_t, vector<Var> >::iterator it = reverseTable.begin(), end = reverseTable.end(); it != end; it++) {
         cout << "-- set begin --" << endl;
         for (vector<Var>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
             cout << *it2 << ", ";
@@ -137,11 +134,13 @@ const bool MatrixFinder::findMatrixes()
         cout << "-------" << endl;
     }
     #endif
-    
+
     uint32_t numMatrixes = setMatrixes();
-    
-    if (solver.verbosity >=1)
-        std::cout << "c |  Finding matrixes :    " << cpuTime() - myTime << " s (found  " << numMatrixes << ")                                |" << endl;
+
+    if (solver.conf.verbosity >=1)
+        std::cout << "c Finding matrixes :    " << cpuTime() - myTime
+        << " s (found  " << numMatrixes << ")"
+        << endl;
 
     for (vector<Gaussian*>::iterator gauss = solver.gauss_matrixes.begin(), end = solver.gauss_matrixes.end(); gauss != end; gauss++) {
         if (!(*gauss)->full_init()) return false;
@@ -150,89 +149,89 @@ const bool MatrixFinder::findMatrixes()
     return true;
 }
 
-const uint MatrixFinder::setMatrixes()
+const uint32_t MatrixFinder::setMatrixes()
 {
-    vector<pair<uint, uint> > numXorInMatrix;
-    for (uint i = 0; i < matrix_no; i++)
+    vector<pair<uint32_t, uint32_t> > numXorInMatrix;
+    for (uint32_t i = 0; i < matrix_no; i++)
         numXorInMatrix.push_back(std::make_pair(i, 0));
-    
-    vector<uint> sumXorSizeInMatrix(matrix_no, 0);
-    vector<vector<uint> > xorSizesInMatrix(matrix_no);
+
+    vector<uint32_t> sumXorSizeInMatrix(matrix_no, 0);
+    vector<vector<uint32_t> > xorSizesInMatrix(matrix_no);
     vector<vector<XorClause*> > xorsInMatrix(matrix_no);
-    
+
     #ifdef PART_FINDING
     vector<vector<Var> > 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()];
+        const uint32_t 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++)
+    for (uint32_t i = 0; i < matrix_no; i++)
         findParts(xorFingerprintInMatrix[i], xorsInMatrix[i]);
     #endif //PART_FINDING
-    
-    uint realMatrixNum = 0;
+
+    uint32_t realMatrixNum = 0;
     for (int a = matrix_no-1; a != -1; a--) {
-        uint i = numXorInMatrix[a].first;
-        
+        uint32_t i = numXorInMatrix[a].first;
+
         if (numXorInMatrix[a].second < 3)
             continue;
-        
-        const uint totalSize = reverseTable[i].size()*numXorInMatrix[a].second;
+
+        const uint32_t 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++)
+        for (uint32_t 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 >= solver.gaussconfig.minMatrixRows
             && numXorInMatrix[a].second <= solver.gaussconfig.maxMatrixRows
-            && realMatrixNum < 3)
+            && realMatrixNum <= solver.gaussconfig.maxNumMatrixes)
         {
-            if (solver.verbosity >=1)
-                cout << "c |  Matrix no " << std::setw(2) << realMatrixNum;
+            if (solver.conf.verbosity >=1)
+                cout << "c Matrix no " << std::setw(2) << 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.conf.verbosity >=1  /*&& numXorInMatrix[a].second >= 20*/)
+                cout << "c Unused Matrix ";
         }
-        if (solver.verbosity >=1 /*&& numXorInMatrix[a].second >= 20*/) {
+        if (solver.conf.verbosity >=1 /*&& numXorInMatrix[a].second >= 20*/) {
             cout << std::setw(7) << 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;
+            cout << " stdev:" << std::setw(6) << std::fixed << std::setprecision(2) << stdDeviation << endl;
         }
     }
-    
+
     return realMatrixNum;
 }
 
 void MatrixFinder::findParts(vector<Var>& xorFingerprintInMatrix, vector<XorClause*>& xorsInMatrix)
 {
-    uint ai = 0;
+    uint32_t ai = 0;
     for (XorClause **a = &xorsInMatrix[0], **end = a + xorsInMatrix.size(); a != end; a++, ai++) {
         const Var fingerprint = xorFingerprintInMatrix[ai];
-        uint ai2 = 0;
+        uint32_t ai2 = 0;
         for (XorClause **a2 = &xorsInMatrix[0]; a2 != end; a2++, ai2++) {
             if (ai == ai2) continue;
             const Var fingerprint2 = xorFingerprintInMatrix[ai2];
@@ -245,5 +244,3 @@ void MatrixFinder::findParts(vector<Var>& xorFingerprintInMatrix, vector<XorClau
         }
     }
 }
-
-}; //NAMESPACE MINISAT
index 293630bd7e12cb9e8c8cd721f6b3c8287ee0d09b..9258c1ce41d8867f1fe5e3cd602b107e763b3e40 100644 (file)
@@ -29,10 +29,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "Clause.h"
 #include "Solver.h"
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 class Solver;
 
 using std::map;
@@ -46,11 +42,11 @@ class MatrixFinder {
         const bool findMatrixes();
     
     private:
-        const uint setMatrixes();
+        const uint32_t setMatrixes();
         
         struct mysorter
         {
-            bool operator () (const pair<uint, uint>& left, const pair<uint, uint>& right)
+            bool operator () (const pair<uint32_t, uint32_t>& left, const pair<uint32_t, uint32_t>& right)
             {
                 return left.second < right.second;
             }
@@ -60,13 +56,12 @@ class MatrixFinder {
         inline const Var fingerprint(const XorClause& c) const;
         inline const bool firstPartOfSecond(const XorClause& c1, const XorClause& c2) const;
         
-        map<uint, vector<Var> > reverseTable; //matrix -> vars
+        map<uint32_t, vector<Var> > reverseTable; //matrix -> vars
         vector<Var> table; //var -> matrix
-        uint matrix_no;
+        uint32_t matrix_no;
         
         Solver& solver;
 };
 
-}; //NAMESPACE MINISAT
 
 #endif //MATRIXFINDER_H
diff --git a/src/sat/cryptominisat2/MersenneTwister.h b/src/sat/cryptominisat2/MersenneTwister.h
deleted file mode 100644 (file)
index 964ecc7..0000000
+++ /dev/null
@@ -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 <iostream>
-#include <limits.h>
-#include <stdio.h>
-#include <time.h>
-#include <math.h>
-
-namespace MINISAT
-{
-
-// Not thread safe (unless auto-initialization is avoided and each thread has
-// its own MTRand object)
-
-class MTRand {
-// Data
-public:
-       typedef unsigned long uint32;  // unsigned integer type, at least 32 bits
-       
-       enum { N = 624 };       // length of state vector
-       enum { SAVE = N + 1 };  // length of array for save()
-
-protected:
-       enum { M = 397 };  // period parameter
-       
-       uint32 state[N];   // internal state
-       uint32 *pNext;     // next value to get from state
-       int left;          // number of values left before reload needed
-
-
-//Methods
-public:
-       MTRand( const uint32& oneSeed );  // initialize with a simple uint32
-       MTRand( uint32 *const bigSeed, uint32 const seedLength = N );  // or an array
-       MTRand();  // auto-initialize with /dev/urandom or time() and clock()
-       
-       // Do NOT use for CRYPTOGRAPHY without securely hashing several returned
-       // values together, otherwise the generator state can be learned after
-       // reading 624 consecutive values.
-       
-       // Access to 32-bit random numbers
-       double rand();                          // real number in [0,1]
-       double rand( const double& n );         // real number in [0,n]
-       double randExc();                       // real number in [0,1)
-       double randExc( const double& n );      // real number in [0,n)
-       double randDblExc();                    // real number in (0,1)
-       double randDblExc( const double& n );   // real number in (0,n)
-       uint32 randInt();                       // integer in [0,2^32-1]
-       uint32 randInt( const uint32& n );      // integer in [0,n] for n < 2^32
-       double operator()() { return rand(); }  // same as rand()
-       
-       // Access to 53-bit random numbers (capacity of IEEE double precision)
-       double rand53();  // real number in [0,1)
-       
-       // Access to nonuniform random number distributions
-       double randNorm( const double& mean = 0.0, const double& variance = 0.0 );
-       
-       // Re-seeding functions with same behavior as initializers
-       void seed( const uint32 oneSeed );
-       void seed( uint32 *const bigSeed, const uint32 seedLength = N );
-       void seed();
-       
-       // Saving and loading generator state
-       void save( uint32* saveArray ) const;  // to array of size SAVE
-       void load( uint32 *const loadArray );  // from such array
-       friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand );
-       friend std::istream& operator>>( std::istream& is, MTRand& mtrand );
-
-protected:
-       void initialize( const uint32 oneSeed );
-       void reload();
-       uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; }
-       uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; }
-       uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; }
-       uint32 mixBits( const uint32& u, const uint32& v ) const
-               { return hiBit(u) | loBits(v); }
-       uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const
-               { return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL); }
-       static uint32 hash( time_t t, clock_t c );
-};
-
-
-inline MTRand::MTRand( const uint32& oneSeed )
-       { seed(oneSeed); }
-
-inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength )
-       { seed(bigSeed,seedLength); }
-
-inline MTRand::MTRand()
-       { seed(); }
-
-inline double MTRand::rand()
-       { return double(randInt()) * (1.0/4294967295.0); }
-
-inline double MTRand::rand( const double& n )
-       { return rand() * n; }
-
-inline double MTRand::randExc()
-       { return double(randInt()) * (1.0/4294967296.0); }
-
-inline double MTRand::randExc( const double& n )
-       { return randExc() * n; }
-
-inline double MTRand::randDblExc()
-       { return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); }
-
-inline double MTRand::randDblExc( const double& n )
-       { return randDblExc() * n; }
-
-inline double MTRand::rand53()
-{
-       uint32 a = randInt() >> 5, b = randInt() >> 6;
-       return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0);  // by Isaku Wada
-}
-
-inline double MTRand::randNorm( const double& mean, const double& variance )
-{
-       // Return a real number from a normal (Gaussian) distribution with given
-       // mean and variance by Box-Muller method
-       double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance;
-       double phi = 2.0 * 3.14159265358979323846264338328 * randExc();
-       return mean + r * cos(phi);
-}
-
-inline MTRand::uint32 MTRand::randInt()
-{
-       // Pull a 32-bit integer from the generator state
-       // Every other access function simply transforms the numbers extracted here
-       
-       if( left == 0 ) reload();
-       --left;
-               
-       register uint32 s1;
-       s1 = *pNext++;
-       s1 ^= (s1 >> 11);
-       s1 ^= (s1 <<  7) & 0x9d2c5680UL;
-       s1 ^= (s1 << 15) & 0xefc60000UL;
-       return ( s1 ^ (s1 >> 18) );
-}
-
-inline MTRand::uint32 MTRand::randInt( const uint32& n )
-{
-       // Find which bits are used in n
-       // Optimized by Magnus Jonsson (magnus@smartelectronix.com)
-       uint32 used = n;
-       used |= used >> 1;
-       used |= used >> 2;
-       used |= used >> 4;
-       used |= used >> 8;
-       used |= used >> 16;
-       
-       // Draw numbers until one is found in [0,n]
-       uint32 i;
-       do
-               i = randInt() & used;  // toss unused bits to shorten search
-       while( i > n );
-       return i;
-}
-
-
-inline void MTRand::seed( const uint32 oneSeed )
-{
-       // Seed the generator with a simple uint32
-       initialize(oneSeed);
-       reload();
-}
-
-
-inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength )
-{
-       // Seed the generator with an array of uint32's
-       // There are 2^19937-1 possible initial states.  This function allows
-       // all of those to be accessed by providing at least 19937 bits (with a
-       // default seed length of N = 624 uint32's).  Any bits above the lower 32
-       // in each element are discarded.
-       // Just call seed() if you want to get array from /dev/urandom
-       initialize(19650218UL);
-       register int i = 1;
-       register uint32 j = 0;
-       register int k = ( N > seedLength ? N : seedLength );
-       for( ; k; --k )
-       {
-               state[i] =
-                       state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
-               state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
-               state[i] &= 0xffffffffUL;
-               ++i;  ++j;
-               if( i >= N ) { state[0] = state[N-1];  i = 1; }
-               if( j >= seedLength ) j = 0;
-       }
-       for( k = N - 1; k; --k )
-       {
-               state[i] =
-                       state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
-               state[i] -= i;
-               state[i] &= 0xffffffffUL;
-               ++i;
-               if( i >= N ) { state[0] = state[N-1];  i = 1; }
-       }
-       state[0] = 0x80000000UL;  // MSB is 1, assuring non-zero initial array
-       reload();
-}
-
-
-inline void MTRand::seed()
-{
-       // Seed the generator with an array from /dev/urandom if available
-       // Otherwise use a hash of time() and clock() values
-       
-       // First try getting an array from /dev/urandom
-       FILE* urandom = fopen( "/dev/urandom", "rb" );
-       if( urandom )
-       {
-               uint32 bigSeed[N];
-               register uint32 *s = bigSeed;
-               register int i = N;
-               register bool success = true;
-               while( success && i-- )
-                       success = fread( s++, sizeof(uint32), 1, urandom );
-               fclose(urandom);
-               if( success ) { seed( bigSeed, N );  return; }
-       }
-       
-       // Was not successful, so use time() and clock() instead
-       seed( hash( time(NULL), clock() ) );
-}
-
-
-inline void MTRand::initialize( const uint32 seed )
-{
-       // Initialize generator state with seed
-       // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
-       // In previous versions, most significant bits (MSBs) of the seed affect
-       // only MSBs of the state array.  Modified 9 Jan 2002 by Makoto Matsumoto.
-       register uint32 *s = state;
-       register uint32 *r = state;
-       register int i = 1;
-       *s++ = seed & 0xffffffffUL;
-       for( ; i < N; ++i )
-       {
-               *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
-               r++;
-       }
-}
-
-
-inline void MTRand::reload()
-{
-       // Generate N new values in state
-       // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
-       register uint32 *p = state;
-       register int i;
-       for( i = N - M; i--; ++p )
-               *p = twist( p[M], p[0], p[1] );
-       for( i = M; --i; ++p )
-               *p = twist( p[M-N], p[0], p[1] );
-       *p = twist( p[M-N], p[0], state[0] );
-
-       left = N, pNext = state;
-}
-
-
-inline MTRand::uint32 MTRand::hash( time_t t, clock_t c )
-{
-       // Get a uint32 from t and c
-       // Better than uint32(x) in case x is floating point in [0,1]
-       // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk)
-
-       static uint32 differ = 0;  // guarantee time-based seeds will change
-
-       uint32 h1 = 0;
-       unsigned char *p = (unsigned char *) &t;
-       for( size_t i = 0; i < sizeof(t); ++i )
-       {
-               h1 *= UCHAR_MAX + 2U;
-               h1 += p[i];
-       }
-       uint32 h2 = 0;
-       p = (unsigned char *) &c;
-       for( size_t j = 0; j < sizeof(c); ++j )
-       {
-               h2 *= UCHAR_MAX + 2U;
-               h2 += p[j];
-       }
-       return ( h1 + differ++ ) ^ h2;
-}
-
-
-inline void MTRand::save( uint32* saveArray ) const
-{
-       register uint32 *sa = saveArray;
-       register const uint32 *s = state;
-       register int i = N;
-       for( ; i--; *sa++ = *s++ ) {}
-       *sa = left;
-}
-
-
-inline void MTRand::load( uint32 *const loadArray )
-{
-       register uint32 *s = state;
-       register uint32 *la = loadArray;
-       register int i = N;
-       for( ; i--; *s++ = *la++ ) {}
-       left = *la;
-       pNext = &state[N-left];
-}
-
-
-inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand )
-{
-       register const MTRand::uint32 *s = mtrand.state;
-       register int i = mtrand.N;
-       for( ; i--; os << *s++ << "\t" ) {}
-       return os << mtrand.left;
-}
-
-
-inline std::istream& operator>>( std::istream& is, MTRand& mtrand )
-{
-       register MTRand::uint32 *s = mtrand.state;
-       register int i = mtrand.N;
-       for( ; i--; is >> *s++ ) {}
-       is >> mtrand.left;
-       mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left];
-       return is;
-}
-};
-
-#endif  // MERSENNETWISTER_H
-
-// Change log:
-//
-// v0.1 - First release on 15 May 2000
-//      - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
-//      - Translated from C to C++
-//      - Made completely ANSI compliant
-//      - Designed convenient interface for initialization, seeding, and
-//        obtaining numbers in default or user-defined ranges
-//      - Added automatic seeding from /dev/urandom or time() and clock()
-//      - Provided functions for saving and loading generator state
-//
-// v0.2 - Fixed bug which reloaded generator one step too late
-//
-// v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
-//
-// v0.4 - Removed trailing newline in saved generator format to be consistent
-//        with output format of built-in types
-//
-// v0.5 - Improved portability by replacing static const int's with enum's and
-//        clarifying return values in seed(); suggested by Eric Heimburg
-//      - Removed MAXINT constant; use 0xffffffffUL instead
-//
-// v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
-//      - Changed integer [0,n] generator to give better uniformity
-//
-// v0.7 - Fixed operator precedence ambiguity in reload()
-//      - Added access for real numbers in (0,1) and (0,n)
-//
-// v0.8 - Included time.h header to properly support time_t and clock_t
-//
-// v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
-//      - Allowed for seeding with arrays of any length
-//      - Added access for real numbers in [0,1) with 53-bit resolution
-//      - Added access for real numbers from normal (Gaussian) distributions
-//      - Increased overall speed by optimizing twist()
-//      - Doubled speed of integer [0,n] generation
-//      - Fixed out-of-range number generation on 64-bit machines
-//      - Improved portability by substituting literal constants for long enum's
-//      - Changed license from GNU LGPL to BSD
index 785d7e92e55eb65611b3cb485f74741968d754f1..fd955d287c78f3c18d68cd6f1247778fa7b8aa62 100644 (file)
@@ -24,20 +24,19 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "ClauseCleaner.h"
 #include "time_mem.h"
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 OnlyNonLearntBins::OnlyNonLearntBins(Solver& _solver) :
     solver(_solver)
 {}
 
+/**
+@brief Propagate recursively on non-learnt binaries
+*/
 const bool OnlyNonLearntBins::propagate()
 {
     while (solver.qhead < solver.trail.size()) {
-        Lit p   = solver.trail[solver.qhead++];
+        Lit p = solver.trail[solver.qhead++];
         vec<WatchedBin> & wbin = binwatches[p.toInt()];
-        solver.propagations += wbin.size()/2;
+        solver.propagations += wbin.size()/2 + 2;
         for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) {
             lbool val = solver.value(k->impliedLit);
             if (val.isUndef()) {
@@ -51,105 +50,34 @@ const bool OnlyNonLearntBins::propagate()
     return true;
 }
 
-const bool OnlyNonLearntBins::propagateBinExcept(const Lit& exceptLit)
-{
-    while (solver.qhead < solver.trail.size()) {
-        Lit p   = solver.trail[solver.qhead++];
-        vec<WatchedBin> & wbin = binwatches[p.toInt()];
-        solver.propagations += wbin.size()/2;
-        for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) {
-            lbool val = solver.value(k->impliedLit);
-            if (val.isUndef() && k->impliedLit != exceptLit) {
-                solver.uncheckedEnqueueLight(k->impliedLit);
-            } else if (val == l_False) {
-                return false;
-            }
-        }
-    }
-
-    return true;
-}
-
-const bool OnlyNonLearntBins::propagateBinOneLevel()
-{
-    Lit p   = solver.trail[solver.qhead];
-    vec<WatchedBin> & wbin = binwatches[p.toInt()];
-    solver.propagations += wbin.size()/2;
-    for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) {
-        lbool val = solver.value(k->impliedLit);
-        if (val.isUndef()) {
-            solver.uncheckedEnqueueLight(k->impliedLit);
-        } else if (val == l_False) {
-            return false;
-        }
-    }
-
-    return true;
-}
-
+/**
+@brief Fill internal watchlists with non-binary clauses
+*/
 const bool OnlyNonLearntBins::fill()
 {
+    uint32_t numBins = 0;
     double myTime = cpuTime();
-    assert(solver.performReplace);
-    while (solver.performReplace && solver.varReplacer->getClauses().size() > 0) {
-        if (!solver.varReplacer->performReplace(true)) return false;
-        solver.clauseCleaner->removeAndCleanAll(true);
-    }
-    assert(solver.varReplacer->getClauses().size() == 0);
-    solver.clauseCleaner->moveBinClausesToBinClauses();
     binwatches.growTo(solver.nVars()*2);
 
-    for(Clause **i = solver.binaryClauses.getData(), **end = solver.binaryClauses.getDataEnd(); i != end; i++) {
-        Clause& c = **i;
-        if (c.learnt()) continue;
-
-        binwatches[(~c[0]).toInt()].push(WatchedBin(c[1]));
-        binwatches[(~c[1]).toInt()].push(WatchedBin(c[0]));
+    uint32_t wsLit = 0;
+    for (const vec<Watched> *it = solver.watches.getData(), *end = solver.watches.getDataEnd(); it != end; it++, wsLit++) {
+        Lit lit = ~Lit::toLit(wsLit);
+        const vec<Watched>& ws = *it;
+        for (const Watched *it2 = ws.getData(), *end2 = ws.getDataEnd(); it2 != end2; it2++) {
+            if (it2->isBinary() && !it2->getLearnt()) {
+                binwatches[wsLit].push(WatchedBin(it2->getOtherLit()));
+                numBins++;
+            }
+        }
     }
 
-    if (solver.verbosity >= 2) {
+    if (solver.conf.verbosity >= 3) {
         std::cout << "c Time to fill non-learnt binary watchlists:"
         << std::fixed << std::setprecision(2) << std::setw(5)
-        << cpuTime() - myTime << " s" << std::endl;
+        << cpuTime() - myTime << " s"
+        << " num non-learnt bins: " << std::setw(10) << numBins
+        << std::endl;
     }
 
     return true;
 }
-
-void OnlyNonLearntBins::removeBin(Lit lit1, Lit lit2)
-{
-    uint32_t index0 = lit1.toInt();
-    uint32_t index1 = lit2.toInt();
-    if (index1 > index0) std::swap(index0, index1);
-    uint64_t final = index0;
-    final |= ((uint64_t)index1) << 32;
-    toRemove.insert(final);
-
-    solver.removeWatchedBinClAll(binwatches[(~lit1).toInt()], lit2);
-    solver.removeWatchedBinClAll(binwatches[(~lit2).toInt()], lit1);
-}
-
-const uint32_t OnlyNonLearntBins::removeBins()
-{
-    Clause **i, **j;
-    i = j = solver.binaryClauses.getData();
-    uint32_t num = 0;
-    for (Clause **end = solver.binaryClauses.getDataEnd(); i != end; i++, num++) {
-        Clause& c = **i;
-        uint32_t index0 = c[0].toInt();
-        uint32_t index1 = c[1].toInt();
-        if (index1 > index0) std::swap(index0, index1);
-        uint64_t final = index0;
-        final |= ((uint64_t)index1) << 32;
-        
-        if (toRemove.find(final) == toRemove.end()) {
-            *j++ = *i;
-        } else {
-            solver.clauseAllocator.clauseFree(*i);
-        }
-    }
-    solver.binaryClauses.shrink(i-j);
-    return (i - j);
-}
-
-}; //NAMESPACE MINISAT
index ed73cc2ca9264b26b02ea9c33c653e1deae94fe4..8c755b93e092dbe92f7d6d45dd9c9e20f6ec51e9 100644 (file)
@@ -19,36 +19,50 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define ONLYNONLEARNTBINS_H
 
 #include "Solver.h"
-#include <set>
-using std::set;
 
-namespace MINISAT
-{
-using namespace MINISAT;
+/**
+@brief Handles propagation, addition&removal of non-learnt binary clauses
 
-class OnlyNonLearntBins {
+It takes a snapshot of Solver's non-learnt binary clauses, builds its own
+watchlists, and does everything itself.*/
+class OnlyNonLearntBins
+{
     public:
         OnlyNonLearntBins(Solver& solver);
 
+        /**
+        @brief For storing a binary clause
+        */
+        class WatchedBin {
+        public:
+            WatchedBin(Lit _impliedLit) : impliedLit(_impliedLit) {};
+            Lit impliedLit;
+        };
+
         //propagation
         const bool propagate();
-        const bool propagateBinExcept(const Lit& exceptLit);
-        const bool propagateBinOneLevel();
 
         //Management of clauses
         const bool fill();
-        void removeBin(Lit lit1, Lit lit2);
-        void removeClause(Clause& c);
-        const uint32_t removeBins();
+
+        //helper
+        inline const uint32_t getWatchSize(const Lit lit) const;
+        inline const vec<vec<WatchedBin> >& getBinWatches() const;
 
     private:
-        vec<vec<WatchedBin> > binwatches;
-        set<uint64_t> toRemove;
-        
+        vec<vec<WatchedBin> > binwatches; ///<Internal wathclists for non-learnt binary clauses
+
         Solver& solver;
 };
 
-}; //NAMESPACE MINISAT
+inline const uint32_t OnlyNonLearntBins::getWatchSize(const Lit lit) const
+{
+    return binwatches[lit.toInt()].size();
+}
 
-#endif //ONLYNONLEARNTBINS_H
+inline const vec<vec<OnlyNonLearntBins::WatchedBin> >& OnlyNonLearntBins::getBinWatches() const
+{
+    return binwatches;
+}
 
+#endif //ONLYNONLEARNTBINS_H
index 9c7f117d15762fec3ea80b3a7adfce4443f3166f..a6945d24c1f3e4826b5df81b464c93190ae8acb1 100644 (file)
@@ -29,10 +29,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 //#define DEBUG_MATRIX
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 class PackedMatrix
 {
 public:
@@ -60,7 +56,7 @@ public:
         delete[] mp;
     }
     
-    void resize(const uint num_rows, uint num_cols)
+    void resize(const uint32_t num_rows, uint32_t num_cols)
     {
         num_cols = num_cols / 64 + (bool)(num_cols % 64);
         if (numRows*2*(numCols+1) < num_rows*2*(num_cols+1)) {
@@ -71,7 +67,7 @@ public:
         numCols = num_cols;
     }
     
-    void resizeNumRows(const uint num_rows)
+    void resizeNumRows(const uint32_t num_rows)
     {
         #ifdef DEBUG_MATRIX
         assert(num_rows <= numRows);
@@ -98,7 +94,7 @@ public:
         return *this;
     }
 
-    inline PackedRow getMatrixAt(const uint i)
+    inline PackedRow getMatrixAt(const uint32_t i)
     {
         #ifdef DEBUG_MATRIX
         assert(i <= numRows);
@@ -106,7 +102,7 @@ public:
         
         return PackedRow(numCols, mp+i*2*(numCols+1));
     }
-    inline PackedRow getVarsetAt(const uint i)
+    inline PackedRow getVarsetAt(const uint32_t i)
     {
         #ifdef DEBUG_MATRIX
         assert(i <= numRows);
@@ -115,7 +111,7 @@ public:
         return PackedRow(numCols, mp+i*2*(numCols+1)+(numCols+1));
     }
     
-    inline const PackedRow getMatrixAt(const uint i) const
+    inline const PackedRow getMatrixAt(const uint32_t i) const
     {
         #ifdef DEBUG_MATRIX
         assert(i <= numRows);
@@ -124,7 +120,7 @@ public:
         return PackedRow(numCols, mp+i*2*(numCols+1));
     }
     
-    inline const PackedRow getVarsetAt(const uint i) const
+    inline const PackedRow getVarsetAt(const uint32_t i) const
     {
         #ifdef DEBUG_MATRIX
         assert(i <= numRows);
@@ -147,19 +143,19 @@ public:
             return *this;
         }
         
-        iterator operator+(const uint num) const
+        iterator operator+(const uint32_t num) const
         {
             iterator ret(*this);
             ret.mp += 2*(numCols+1)*num;
             return ret;
         }
         
-        const uint operator-(const iterator& b) const
+        const uint32_t operator-(const iterator& b) const
         {
             return (mp - b.mp)/(2*(numCols+1));
         }
         
-        void operator+=(const uint num)
+        void operator+=(const uint32_t num)
         {
             mp += 2*(numCols+1)*num;
         }
@@ -177,13 +173,13 @@ public:
     private:
         friend class PackedMatrix;
         
-        iterator(uint64_t* _mp, const uint _numCols) :
+        iterator(uint64_t* _mp, const uint32_t _numCols) :
             mp(_mp)
             , numCols(_numCols)
         {}
         
         uint64_t* mp;
-        const uint numCols;
+        const uint32_t numCols;
     };
     
     inline iterator beginMatrix()
@@ -206,7 +202,7 @@ public:
         return iterator(mp+(numCols+1)+numRows*2*(numCols+1), numCols);
     }
     
-    inline const uint getSize() const
+    inline const uint32_t getSize() const
     {
         return numRows;
     }
@@ -214,11 +210,9 @@ public:
 private:
     
     uint64_t* mp;
-    uint numRows;
-    uint numCols;
+    uint32_t numRows;
+    uint32_t numCols;
 };
 
-}; //NAMESPACE MINISAT
-
 #endif //PACKEDMATRIX_H
 
index 59a4e4332e9be6bfed26abc427a76c36a8907313..890f0e0da0afbdd88b0acffd18a2e7a2a013fac0 100644 (file)
@@ -17,10 +17,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include "PackedRow.h"
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 std::ostream& operator << (std::ostream& os, const PackedRow& m)
 {
     for(uint32_t i = 0; i < m.size*64; i++) {
@@ -37,7 +33,7 @@ bool PackedRow::operator ==(const PackedRow& b) const
     assert(b.size > 0);
     assert(size == b.size);
     #endif
-    
+
     return (std::equal(b.mp-1, b.mp+size, mp-1));
 }
 
@@ -48,7 +44,7 @@ bool PackedRow::operator !=(const PackedRow& b) const
     assert(b.size > 0);
     assert(size == b.size);
     #endif
-    
+
     return (!std::equal(b.mp-1, b.mp+size, mp-1));
 }
 
@@ -57,7 +53,7 @@ uint32_t PackedRow::popcnt() const
     uint32_t popcnt = 0;
     for (uint32_t i = 0; i < size; i++) if (mp[i]) {
         uint64_t tmp = mp[i];
-        for (uint i2 = 0; i2 < 64; i2++) {
+        for (uint32_t i2 = 0; i2 < 64; i2++) {
             popcnt += (tmp & 1);
             tmp >>= 1;
         }
@@ -84,10 +80,10 @@ uint32_t PackedRow::popcnt(const uint32_t from) const
     return popcnt;
 }
 
-void PackedRow::fill(vec<Lit>& tmp_clause, const vec<lbool>& assigns, const vector<Var>& col_to_var_original) const
+const bool PackedRow::fill(vec<Lit>& tmp_clause, const vec<lbool>& assigns, const vector<Var>& col_to_var_original) const
 {
     bool final = !is_true_internal;
-    
+
     tmp_clause.clear();
     uint32_t col = 0;
     bool wasundef = false;
@@ -95,8 +91,8 @@ void PackedRow::fill(vec<Lit>& tmp_clause, const vec<lbool>& assigns, const vect
         if ((mp[i] >> i2) &1) {
             const Var& var = col_to_var_original[col];
             assert(var != std::numeric_limits<Var>::max());
-            
-            const lbool& val = assigns[var];
+
+            const lbool val = assigns[var];
             const bool val_bool = val.getBool();
             tmp_clause.push(Lit(var, val_bool));
             final ^= val_bool;
@@ -115,6 +111,7 @@ void PackedRow::fill(vec<Lit>& tmp_clause, const vec<lbool>& assigns, const vect
         //assert(ps != ps_first+1);
     } else
         assert(!final);
+
+    return wasundef;
 }
 
-}; //NAMESPACE MINISAT
index 876099886af970d35f0236ac357dfbd277250611..87a8a057745a8d7ccd0066f8e94ffa3d0cd29236 100644 (file)
@@ -33,16 +33,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <iostream>
 #include <algorithm>
 #include <limits>
-#ifndef uint
-#define uint unsigned int
-#endif
 
 using std::vector;
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 
 class PackedMatrix;
 
@@ -51,7 +44,7 @@ class PackedRow
 public:
     bool operator ==(const PackedRow& b) const;
     bool operator !=(const PackedRow& b) const;
-    
+
     PackedRow& operator=(const PackedRow& b)
     {
         #ifdef DEBUG_ROW
@@ -59,11 +52,11 @@ public:
         assert(b.size > 0);
         assert(size == b.size);
         #endif
-        
+
         memcpy(mp-1, b.mp-1, size+1);
         return *this;
     }
-    
+
     PackedRow& operator^=(const PackedRow& b)
     {
         #ifdef DEBUG_ROW
@@ -71,15 +64,15 @@ public:
         assert(b.size > 0);
         assert(b.size == size);
         #endif
-        
+
         for (uint32_t i = 0; i != size; i++) {
             *(mp + i) ^= *(b.mp + i);
         }
-        
+
         is_true_internal ^= b.is_true_internal;
         return *this;
     }
-    
+
     void xorBoth(const PackedRow& b)
     {
         #ifdef DEBUG_ROW
@@ -87,21 +80,21 @@ public:
         assert(b.size > 0);
         assert(b.size == size);
         #endif
-        
+
         for (uint32_t i = 0; i != 2*size+1; i++) {
             *(mp + i) ^= *(b.mp + i);
         }
-        
+
         is_true_internal ^= b.is_true_internal;
     }
-    
-    
+
+
     uint32_t popcnt() const;
     uint32_t popcnt(uint32_t from) const;
-    
+
     bool popcnt_is_one() const
     {
-        char popcount = 0;
+        uint32_t popcount = 0;
         for (uint32_t i = 0; i != size; i++) {
             uint64_t tmp = mp[i];
             while(tmp) {
@@ -111,15 +104,15 @@ public:
         }
         return popcount == 1;
     }
-    
+
     bool popcnt_is_one(uint32_t from) const
     {
         from++;
-        
+
         uint64_t tmp = mp[from/64];
         tmp >>= from%64;
         if (tmp) return false;
-        
+
         for (uint32_t i = from/64+1; i != size; i++)
             if (mp[i]) return false;
         return true;
@@ -157,7 +150,7 @@ public:
     {
         mp[i/64] |= ((uint64_t)1 << (i%64));
     }
-    
+
     void swapBoth(PackedRow b)
     {
         #ifdef DEBUG_ROW
@@ -165,12 +158,12 @@ public:
         assert(b.size > 0);
         assert(b.size == size);
         #endif
-        
+
         uint64_t * __restrict mp1 = mp-1;
         uint64_t * __restrict mp2 = b.mp-1;
-        
+
         uint32_t i = 2*(size+1);
-        
+
         while(i != 0) {
             std::swap(*mp1, *mp2);
             mp1++;
@@ -184,7 +177,7 @@ public:
         #ifdef DEBUG_ROW
         assert(size*64 > i);
         #endif
-        
+
         return (mp[i/64] >> (i%64)) & 1;
     }
 
@@ -197,44 +190,38 @@ public:
         for (uint32_t i = 0; i != v.size(); i++) {
             const uint32_t toset_var = var_to_col[v[i].var()];
             assert(toset_var != std::numeric_limits<uint32_t>::max());
-            
+
             setBit(toset_var);
         }
-        
-        is_true_internal = !v.xor_clause_inverted();
+
+        is_true_internal = !v.xorEqualFalse();
     }
-    
-    void fill(vec<Lit>& tmp_clause, const vec<lbool>& assigns, const vector<Var>& col_to_var_original) const;
-    
+
+    const bool fill(vec<Lit>& tmp_clause, const vec<lbool>& assigns, const vector<Var>& col_to_var_original) const;
+
     inline unsigned long int scan(const unsigned long int var) const
     {
         #ifdef DEBUG_ROW
         assert(size > 0);
         #endif
-        
-        for(uint32_t i = var; i != size*64; i++)
+
+        for(uint32_t i = var; i != size*64; i++) {
             if (this->operator[](i)) return i;
-            return std::numeric_limits<unsigned long int>::max();
+        }
+
+        return std::numeric_limits<unsigned long int>::max();
     }
 
     friend std::ostream& operator << (std::ostream& os, const PackedRow& m);
 
-#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 0))
-// Workaround for GCC 4.0 which doesn't extend friendship to nested classes. See
-// http://stackoverflow.com/questions/3584385/friend-access-to-protected-nested-class
-// for details.
-public:
-#else
 private:
     friend class PackedMatrix;
-#endif
     PackedRow(const uint32_t _size, uint64_t*  const _mp) :
         mp(_mp+1)
         , is_true_internal(*_mp)
         , size(_size)
     {}
 
-private:
     uint64_t* __restrict const mp;
     uint64_t& is_true_internal;
     const uint32_t size;
@@ -242,7 +229,5 @@ private:
 
 std::ostream& operator << (std::ostream& os, const PackedRow& m);
 
-}; //NAMESPACE MINISAT
-
 #endif //PACKEDROW_H
 
index 969afe6d232fb762626030930a9376fb650f008f..325b5ecdca6a8bfe814c74038517556186840073 100644 (file)
@@ -28,7 +28,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <map>
 #include <iomanip>
 #include <math.h>
-#include "FailedVarSearcher.h"
+#include "FailedLitSearcher.h"
 using std::set;
 using std::map;
 
@@ -39,10 +39,6 @@ using std::endl;
 
 //#define PART_FINDING
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 PartFinder::PartFinder(Solver& _solver) :
     solver(_solver)
 {
@@ -50,112 +46,134 @@ PartFinder::PartFinder(Solver& _solver) :
 
 const bool PartFinder::findParts()
 {
-    assert(solver.performReplace);
-    
+    assert(solver.conf.doReplace);
+
     double time = cpuTime();
-    
+
     table.clear();
     table.resize(solver.nVars(), std::numeric_limits<uint32_t>::max());
     reverseTable.clear();
     part_no = 0;
-    
+
     solver.clauseCleaner->removeAndCleanAll(true);
     if (!solver.ok) return false;
     while (solver.varReplacer->getNewToReplaceVars() > 0) {
-        if (solver.performReplace && !solver.varReplacer->performReplace(true))
+        if (solver.conf.doReplace && !solver.varReplacer->performReplace(true))
             return false;
         solver.clauseCleaner->removeAndCleanAll(true);
         if (!solver.ok) return false;
     }
-    assert(solver.varReplacer->getClauses().size() == 0);
-    
+
     addToPart(solver.clauses);
-    addToPart(solver.binaryClauses);
+    addToPartBins();
     addToPart(solver.xorclauses);
-    
-    const uint parts = setParts();
-    
+
+    const uint32_t parts = setParts();
+
     #ifndef NDEBUG
-    for (map<uint, vector<Var> >::const_iterator it = reverseTable.begin(); it != reverseTable.end(); it++) {
-        for (uint i2 = 0; i2 < it->second.size(); i2++) {
+    for (map<uint32_t, vector<Var> >::const_iterator it = reverseTable.begin(); it != reverseTable.end(); it++) {
+        for (uint32_t i2 = 0; i2 < it->second.size(); i2++) {
             assert(table[(it->second)[i2]] == it->first);
         }
     }
     #endif
-    
-    if (solver.verbosity >= 2 || (solver.verbosity >=1 && parts > 1)) {
-        std::cout << "c Found parts: " << std::setw(10) <<  parts
+
+    if (solver.conf.verbosity  >= 3 || (solver.conf.verbosity  >=1 && parts > 1)) {
+        std::cout << "c Found parts: " << std::setw(10) <<  parts
         << " time: " << std::setprecision(2) << std::setw(4) << cpuTime() - time
-        << " s" << std::setw(51) << " |" << std::endl;
+        << " s"
+        << std::endl;
     }
-    
+
     return true;
 }
 
 template<class T>
 void PartFinder::addToPart(const vec<T*>& cs)
 {
-    set<uint> tomerge;
-    vector<Var> newSet;
     for (T* const* c = cs.getData(), * const*end = c + cs.size(); c != end; c++) {
         if ((*c)->learnt()) continue;
-        tomerge.clear();
-        newSet.clear();
-        for (const Lit *l = (*c)->getData(), *end2 = l + (*c)->size(); l != end2; l++) {
-            if (table[l->var()] != std::numeric_limits<uint32_t>::max())
-                tomerge.insert(table[l->var()]);
-            else
-                newSet.push_back(l->var());
-        }
-        if (tomerge.size() == 1) {
-            //no trees to merge, only merge the clause into one tree
-            
-            const uint into = *tomerge.begin();
-            map<uint, vector<Var> >::iterator intoReverse = reverseTable.find(into);
-            for (uint i = 0; i < newSet.size(); i++) {
-                intoReverse->second.push_back(newSet[i]);
-                table[newSet[i]] = into;
+        addToPartClause(**c);
+    }
+}
+
+void PartFinder::addToPartBins()
+{
+    vec<Lit> lits(2);
+    uint32_t wsLit = 0;
+    for (const vec<Watched> *it = solver.watches.getData(), *end = solver.watches.getDataEnd(); it != end; it++, wsLit++) {
+        Lit lit = ~Lit::toLit(wsLit);
+        lits[0] = lit;
+        const vec<Watched>& ws = *it;
+        for (const Watched *it2 = ws.getData(), *end2 = ws.getDataEnd(); it2 != end2; it2++) {
+            if (it2->isBinary() && lit.toInt() < it2->getOtherLit().toInt()) {
+                if (it2->getLearnt()) continue;
+                lits[1] = it2->getOtherLit();
+                addToPartClause(lits);
             }
-            continue;
         }
-        
-        for (set<uint>::iterator it = tomerge.begin(); it != tomerge.end(); it++) {
-            newSet.insert(newSet.end(), reverseTable[*it].begin(), reverseTable[*it].end());
-            reverseTable.erase(*it);
+    }
+}
+
+template<class T>
+void PartFinder::addToPartClause(T& cl)
+{
+    set<uint32_t> tomerge;
+    vector<Var> newSet;
+    for (const Lit *l = cl.getData(), *end2 = cl.getDataEnd(); l != end2; l++) {
+        if (table[l->var()] != std::numeric_limits<uint32_t>::max())
+            tomerge.insert(table[l->var()]);
+        else
+            newSet.push_back(l->var());
+    }
+    if (tomerge.size() == 1) {
+        //no trees to merge, only merge the clause into one tree
+
+        const uint32_t into = *tomerge.begin();
+        map<uint32_t, vector<Var> >::iterator intoReverse = reverseTable.find(into);
+        for (uint32_t i = 0; i < newSet.size(); i++) {
+            intoReverse->second.push_back(newSet[i]);
+            table[newSet[i]] = into;
         }
-        
-        for (uint i = 0; i < newSet.size(); i++)
-            table[newSet[i]] = part_no;
-        reverseTable[part_no] = newSet;
-        part_no++;
+        return;
     }
+
+    for (set<uint32_t>::iterator it = tomerge.begin(); it != tomerge.end(); it++) {
+        newSet.insert(newSet.end(), reverseTable[*it].begin(), reverseTable[*it].end());
+        reverseTable.erase(*it);
+    }
+
+    for (uint32_t i = 0; i < newSet.size(); i++)
+        table[newSet[i]] = part_no;
+    reverseTable[part_no] = newSet;
+    part_no++;
 }
 
-const uint PartFinder::setParts()
+const uint32_t PartFinder::setParts()
 {
-    vector<uint> numClauseInPart(part_no, 0);
-    vector<uint> sumLitsInPart(part_no, 0);
-    
+    vector<uint32_t> numClauseInPart(part_no, 0);
+    vector<uint32_t> sumLitsInPart(part_no, 0);
+
     calcIn(solver.clauses, numClauseInPart, sumLitsInPart);
-    calcIn(solver.binaryClauses, numClauseInPart, sumLitsInPart);
+    calcInBins(numClauseInPart, sumLitsInPart);
     calcIn(solver.xorclauses, numClauseInPart, sumLitsInPart);
-    uint parts = 0;
-    for (uint i = 0; i < numClauseInPart.size(); i++) {
+
+    uint32_t parts = 0;
+    for (uint32_t i = 0; i < numClauseInPart.size(); i++) {
         if (sumLitsInPart[i] == 0) continue;
-        if (solver.verbosity >= 2 || ( solver.verbosity >= 1 && reverseTable.size() > 1) ) {
-            std::cout << "c Found part " << std::setw(8) << i
+        if (solver.conf.verbosity  >= 3 || ( solver.conf.verbosity  >= 1 && reverseTable.size() > 1) ) {
+            std::cout << "c Found part " << std::setw(8) << i
             << " vars: " << std::setw(10) << reverseTable[i].size()
             << " clauses:" << std::setw(10) << numClauseInPart[i]
             << " lits size:" << std::setw(10) << sumLitsInPart[i]
-            << std::setw(12) << " | " << std::endl;
+            << std::endl;
         }
         parts++;
     }
-    
+
     if (parts > 1) {
         #ifdef VERBOSE_DEBUG
-        for (map<uint, vector<Var> >::iterator it = reverseTable.begin(), end = reverseTable.end(); it != end; it++) {
+        for (map<uint32_t, vector<Var> >::iterator it = reverseTable.begin(), end = reverseTable.end(); it != end; it++) {
             cout << "-- set begin --" << endl;
             for (vector<Var>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
                 cout << *it2 << ", ";
@@ -164,23 +182,41 @@ const uint PartFinder::setParts()
         }
         #endif
     }
-    
+
     return parts;
 }
 
+void PartFinder::calcInBins(vector<uint32_t>& numClauseInPart, vector<uint32_t>& sumLitsInPart)
+{
+    uint32_t wsLit = 0;
+    for (const vec<Watched> *it = solver.watches.getData(), *end = solver.watches.getDataEnd(); it != end; it++, wsLit++) {
+        Lit lit = ~Lit::toLit(wsLit);
+        const vec<Watched>& ws = *it;
+        for (const Watched *it2 = ws.getData(), *end2 = ws.getDataEnd(); it2 != end2; it2++) {
+            if (it2->isBinary() && lit.toInt() < it2->getOtherLit().toInt()) {
+                if (it2->getLearnt()) continue;
+
+                const uint32_t part = table[lit.var()];
+                assert(part < part_no);
+                numClauseInPart[part]++;
+                sumLitsInPart[part] += 2;
+            }
+        }
+    }
+}
+
 template<class T>
-void PartFinder::calcIn(const vec<T*>& cs, vector<uint>& numClauseInPart, vector<uint>& sumLitsInPart)
+void PartFinder::calcIn(const vec<T*>& cs, vector<uint32_t>& numClauseInPart, vector<uint32_t>& sumLitsInPart)
 {
     for (T*const* c = cs.getData(), *const*end = c + cs.size(); c != end; c++) {
         if ((*c)->learnt()) continue;
         T& x = **c;
-        const uint part = table[x[0].var()];
+        const uint32_t part = table[x[0].var()];
         assert(part < part_no);
-        
+
         //for stats
         numClauseInPart[part]++;
         sumLitsInPart[part] += x.size();
     }
 }
 
-}; //NAMESPACE MINISAT
index a3261d74b107ccadd0627e06db08587edc29830e..27a79217ac027442068c3212938d6201391c640b 100644 (file)
@@ -28,10 +28,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include "Clause.h"
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 class Solver;
 
 using std::map;
@@ -39,37 +35,39 @@ using std::vector;
 using std::pair;
 
 class PartFinder {
-    
+
     public:
         PartFinder(Solver& solver);
         const bool findParts();
-        
+
         const map<uint32_t, vector<Var> >& getReverseTable() const; // part->var
         const uint32_t getVarPart(const Var var) const;
         const vector<uint32_t>& getTable() const; //var -> part
         const vector<Var>& getPartVars(const uint32_t part);
-    
+
     private:
-        const uint setParts();
-        template<class T>
-        void addToPart(const vec<T*>& cs);
-        
+        const uint32_t setParts();
+        void addToPartBins();
+        template<class T> void addToPartClause(T& cl);
+        template<class T> void addToPart(const vec<T*>& cs);
+
         struct mysorter
         {
-            bool operator () (const pair<uint, uint>& left, const pair<uint, uint>& right)
+            bool operator () (const pair<uint32_t, uint32_t>& left, const pair<uint32_t, uint32_t>& right)
             {
                 return left.second < right.second;
             }
         };
-        
+
         //const bool findParts(vector<Var>& xorFingerprintInMatrix, vector<XorClause*>& xorsInMatrix);
         template<class T>
-        void calcIn(const vec<T*>& cs, vector<uint>& numClauseInPart, vector<uint>& sumLitsInPart);
-        
+        void calcIn(const vec<T*>& cs, vector<uint32_t>& numClauseInPart, vector<uint32_t>& sumLitsInPart);
+        void calcInBins(vector<uint32_t>& numClauseInPart, vector<uint32_t>& sumLitsInPart);
+
         map<uint32_t, vector<Var> > reverseTable; //part -> vars
         vector<uint32_t> table; //var -> part
         uint32_t part_no;
-        
+
         Solver& solver;
 };
 
@@ -93,6 +91,4 @@ inline const vector<Var>& PartFinder::getPartVars(const uint32_t part)
     return reverseTable[part];
 }
 
-}; //NAMESPACE MINISAT
-
 #endif //PARTFINDER_H
index 75032fe2c8772a93cc9b151c5a8f5cfc3a005db7..0bba7108de6a2b7d074fa740f1583f742ba7e06b 100644 (file)
@@ -1,4 +1,4 @@
-/***********************************************************************************
+/*****************************************************************************
 CryptoMiniSat -- Copyright (c) 2009 Mate Soos
 
 This program is free software: you can redistribute it and/or modify
@@ -13,7 +13,7 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
-**************************************************************************************************/
+******************************************************************************/
 
 #include "PartHandler.h"
 #include "VarReplacer.h"
@@ -23,10 +23,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 //#define VERBOSE_DEBUG
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 PartHandler::PartHandler(Solver& s) :
     solver(s)
 {
@@ -35,9 +31,9 @@ PartHandler::PartHandler(Solver& s) :
 
 const bool PartHandler::handle()
 {
-    if (solver.performReplace == false)
+    if (solver.conf.doReplace == false)
         return true;
-    
+
     PartFinder partFinder(solver);
     if (!partFinder.findParts()) {
         #ifdef VERBOSE_DEBUG
@@ -45,111 +41,61 @@ const bool PartHandler::handle()
         #endif //VERBOSE_DEBUG
         return false;
     }
-    
+
     uint32_t num_parts = partFinder.getReverseTable().size();
     if (num_parts == 1)
         return true;
-    
+
     map<uint32_t, vector<Var> > reverseTable = partFinder.getReverseTable();
     assert(num_parts == partFinder.getReverseTable().size());
-    
+
     vector<pair<uint32_t, uint32_t> > sizes;
     for (map<uint32_t, vector<Var> >::iterator it = reverseTable.begin(); it != reverseTable.end(); it++)
         sizes.push_back(std::make_pair(it->first, (uint32_t)it->second.size()));
-    
+
     std::sort(sizes.begin(), sizes.end(), sort_pred());
     assert(sizes.size() > 1);
-    
+
     for (uint32_t it = 0; it < sizes.size()-1; it++) {
         uint32_t part = sizes[it].first;
         vector<Var> vars = reverseTable[part];
-        if (solver.verbosity >= 1)
+        if (solver.conf.verbosity  >= 1)
             std::cout << "c Solving part " << part << std::endl;
-        
+
         Solver newSolver;
-        newSolver.mtrand.seed(solver.mtrand.randInt());
-        newSolver.random_var_freq = solver.random_var_freq;
-        newSolver.verbosity = solver.verbosity;
-        newSolver.restrictedPickBranch = solver.restrictedPickBranch;
-        newSolver.greedyUnbound = solver.greedyUnbound;
-        newSolver.findNormalXors = solver.findNormalXors;
-        newSolver.findBinaryXors = solver.findBinaryXors;
-        newSolver.regularlyFindBinaryXors = solver.regularlyFindBinaryXors;
-        newSolver.conglomerateXors = solver.conglomerateXors;
-        newSolver.schedSimplification = solver.schedSimplification;
-        newSolver.performReplace = solver.performReplace;
-        newSolver.failedVarSearch = solver.failedVarSearch;
-        newSolver.gaussconfig.dontDisable = solver.gaussconfig.dontDisable;
-        newSolver.heuleProcess = solver.heuleProcess;
-        newSolver.doSubsumption = solver.doSubsumption;
-        newSolver.doPartHandler = solver.doPartHandler;
-        newSolver.fixRestartType = solver.fixRestartType;
-        newSolver.var_inc = solver.var_inc;
-        newSolver.polarity_mode = solver.polarity_mode;
-
-        //Memory-usage reduction
-        newSolver.schedSimplification = false;
-        newSolver.doSubsumption = false;
-        newSolver.doXorSubsumption = false;
-        newSolver.doPartHandler = false;
-        newSolver.subsumeWithNonExistBinaries = false;
-        newSolver.regularSubsumeWithNonExistBinaries = false;
-
-        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.order_heap.update(var);
-                assert(partFinder.getVarPart(var) == part);
-                if (solver.decision_var[var]) {
-                    solver.setDecisionVar(var, false);
-                    decisionVarRemoved.push(var);
-                }
-                i2++;
-            } else {
-                assert(partFinder.getVarPart(var) != part);
-                newSolver.newVar(false);
-            }
-        }
-        solver.order_heap.filter(Solver::VarFilter(solver));
-        
-        assert(solver.varReplacer->getClauses().size() == 0);
+        configureNewSolver(newSolver);
+        moveVariablesBetweenSolvers(newSolver, vars, part, partFinder);
+
+        moveBinClauses(newSolver, part, partFinder);
         moveClauses(solver.clauses, newSolver, part, partFinder);
-        moveClauses(solver.binaryClauses, newSolver, part, partFinder);
         moveClauses(solver.xorclauses, newSolver, part, partFinder);
-        moveLearntClauses(solver.binaryClauses, newSolver, part, partFinder);
         moveLearntClauses(solver.learnts, newSolver, part, partFinder);
         assert(checkClauseMovement(newSolver, part, partFinder));
-        
+
         lbool status = newSolver.solve();
+        assert(status != l_Undef);
         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);
-        
+
+        //Check that the newly found solution is really unassigned in the
+        //original solver
         for (Var var = 0; var < newSolver.nVars(); var++) {
             if (newSolver.model[var] != l_Undef) {
                 assert(solver.assigns[var] == l_Undef);
             }
         }
-        
+
         assert(newSolver.decisionLevel() == 0);
         for (uint32_t i = 0; i < newSolver.trail.size(); i++) {
             solver.uncheckedEnqueue(newSolver.trail[i]);
         }
         solver.ok = (solver.propagate().isNULL());
         assert(solver.ok);
-        
+
         for (Var var = 0; var < newSolver.nVars(); var++) {
             if (newSolver.model[var] != l_Undef) {
                 //Must have been decision var in the old solver!??
@@ -161,44 +107,118 @@ const bool PartHandler::handle()
                 }
             }
         }
-        
-        if (solver.verbosity >= 1)
+
+        if (solver.conf.verbosity  >= 1) {
             std::cout << "c Solved part" << std::endl;
+            std::cout << "c "
+            << "========================================================================================="
+            << std::endl;
+        }
     }
-    if (solver.verbosity >= 1)
+    if (solver.conf.verbosity  >= 1) {
         std::cout << "c Coming back to original instance"
-        << std::setw(57) << " |" << std::endl;
-    
+        << std::endl;
+        std::cout << "c "
+        << "========================================================================================="
+        << std::endl;
+    }
+
     solver.order_heap.filter(Solver::VarFilter(solver));
-    
-    //Checking that all variables that are not in the remaining part are all non-decision vars, and none have been set
+
+    //Checking that all variables that are not in the remaining part are all
+    //non-decision vars, and none have been assigned
     for (Var var = 0; var < solver.nVars(); var++) {
         if (savedState[var] != l_Undef) {
             assert(solver.decision_var[var] == false);
             assert(solver.assigns[var] == l_Undef || solver.level[var] == 0);
         }
     }
-    
+
     //Checking that all remaining clauses contain only variables that are in the remaining part
     assert(checkClauseMovement(solver, sizes[sizes.size()-1].first, partFinder));
-    
+
     return true;
 }
 
+/**
+@brief Sets up the sub-solver with a specific configuration
+
+We need to save on memory, since there might be many subsolvers. We also
+need to pass all configurations from the original solver to the sub-solver.
+*/
+void PartHandler::configureNewSolver(Solver& newSolver) const
+{
+    newSolver.mtrand.seed(solver.mtrand.randInt());
+    newSolver.conf = solver.conf;
+    newSolver.gaussconfig = solver.gaussconfig;
+
+    //Memory-usage reduction
+    newSolver.conf.doSchedSimp = false;
+    newSolver.conf.doSatELite = false;
+    newSolver.conf.doXorSubsumption = false;
+    newSolver.conf.doPartHandler = false;
+    newSolver.conf.doSubsWNonExistBins = false;
+}
+
+/**
+@brief Moves the variables to the new solver, and removes it from the original one
+
+This implies making the right variables decision in the new solver,
+and making it non-decision in the old solver.
+*/
+void PartHandler::moveVariablesBetweenSolvers(Solver& newSolver, vector<Var>& vars, const uint32_t part, const PartFinder& partFinder)
+{
+    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.order_heap.update(var);
+            assert(partFinder.getVarPart(var) == part);
+            if (solver.decision_var[var]) {
+                solver.setDecisionVar(var, false);
+                decisionVarRemoved.push(var);
+            }
+            i2++;
+        } else {
+            assert(partFinder.getVarPart(var) != part);
+            newSolver.newVar(false);
+        }
+    }
+    solver.order_heap.filter(Solver::VarFilter(solver));
+}
+
+/**
+@brief Check that when we moved the clauses, we did a good job
+
+I.e. we did not move clauses into a part where they don't belong
+*/
 const bool PartHandler::checkClauseMovement(const Solver& thisSolver, const uint32_t part, const PartFinder& partFinder) const
 {
     if (!checkOnlyThisPart(thisSolver.clauses, part, partFinder))
         return false;
     if (!checkOnlyThisPart(thisSolver.learnts, part, partFinder))
         return false;
-    if (!checkOnlyThisPart(thisSolver.binaryClauses, part, partFinder))
+    if (!checkOnlyThisPartBin(thisSolver, part, partFinder))
         return false;
     if (!checkOnlyThisPart(thisSolver.xorclauses, part, partFinder))
         return false;
-    
+
     return true;
 }
 
+/**
+@brief Check that clauses only contain variables belonging to this partFinder
+
+@p cs The clause-list to check
+@p part The part that we should check that the clauses belong to
+*/
 template<class T>
 const bool PartHandler::checkOnlyThisPart(const vec<T*>& cs, const uint32_t part, const PartFinder& partFinder) const
 {
@@ -208,33 +228,151 @@ const bool PartHandler::checkOnlyThisPart(const vec<T*>& cs, const uint32_t part
             if (partFinder.getVarPart(l->var()) != part) return false;
         }
     }
-    
+
     return true;
 }
 
+const bool PartHandler::checkOnlyThisPartBin(const Solver& thisSolver, const uint32_t part, const PartFinder& partFinder) const
+{
+    bool retval = true;
+    uint32_t wsLit = 0;
+    for (const vec<Watched> *it = thisSolver.watches.getData(), *end = thisSolver.watches.getDataEnd(); it != end; it++, wsLit++) {
+        const Lit lit = ~Lit::toLit(wsLit);
+        const vec<Watched>& ws = *it;
+        for (const Watched *it2 = ws.getData(), *end2 = ws.getDataEnd(); it2 != end2; it2++) {
+            if (it2->isBinary()) {
+                if (partFinder.getVarPart(lit.var()) != part
+                    || partFinder.getVarPart(it2->getOtherLit().var()) != part
+                    ) {
+                    std::cout << "bin incorrectly moved to this part:" << lit << " , " << it2->getOtherLit() << std::endl;
+                    retval = false;
+                }
+            }
+        }
+    }
+
+    return retval;
+}
+
+/**
+@brief Move clauses from original to the part
+
+The variables that form part of the part will determine if the clause is in the
+part or not
+*/
 void PartHandler::moveClauses(vec<Clause*>& cs, Solver& newSolver, const uint32_t part, PartFinder& partFinder)
 {
     Clause **i, **j, **end;
     for (i = j = cs.getData(), j = i , end = i + cs.size(); i != end; i++) {
-        if ((**i).learnt() || partFinder.getVarPart((**i)[0].var()) != part) {
-            *j++ = *i;
-            continue;
+        Clause& c = **i;
+        if (!c.learnt()) {
+            if (partFinder.getVarPart(c[0].var()) != part) {
+                //different part, move along
+                *j++ = *i;
+                continue;
+            }
+            //later we will move it
         }
-        solver.detachClause(**i);
+        if (c.learnt()) {
+            bool thisPart = false;
+            bool otherPart = false;
+            for (Lit* l = c.getData(), *end2 = c.getDataEnd(); l != end2; l++) {
+                if (partFinder.getVarPart(l->var()) == part) thisPart = true;
+                if (partFinder.getVarPart(l->var()) != part) otherPart = true;
+            }
+            //in both parts, remove it
+            if (thisPart && otherPart) {
+                solver.detachClause(c);
+                solver.clauseAllocator.clauseFree(&c);
+                continue;
+            }
+            if (!thisPart) {
+                //different part, move along
+                *j++ = *i;
+                continue;
+            }
+            assert(thisPart && !otherPart);
+        }
+
+        solver.detachClause(c);
         #ifdef VERBOSE_DEBUG
         std::cout << "clause in this part:"; (**i).plainPrint();
         #endif
 
-        Clause& c = **i;
         vec<Lit> 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!
+        //NOTE: we need the tmp because otherwise, the addClause could have changed "c", which we need to re-add later!
         clausesRemoved.push(*i);
     }
     cs.shrink(i-j);
 }
 
+void PartHandler::moveBinClauses(Solver& newSolver, const uint32_t part, PartFinder& partFinder)
+{
+    uint32_t numRemovedHalfNonLearnt = 0;
+    uint32_t numRemovedHalfLearnt = 0;
+
+    uint32_t wsLit = 0;
+    for (vec<Watched> *it = solver.watches.getData(), *end = solver.watches.getDataEnd(); it != end; it++, wsLit++) {
+        const Lit lit = ~Lit::toLit(wsLit);
+        vec<Watched>& ws = *it;
+
+        Watched *i = ws.getData();
+        Watched *j = i;
+        for (Watched *end2 = ws.getDataEnd(); i != end2; i++) {
+            if (i->isBinary()
+                && (partFinder.getVarPart(lit.var()) == part || partFinder.getVarPart(i->getOtherLit().var()) == part))
+            {
+                const Lit lit2 = i->getOtherLit();
+                assert((partFinder.getVarPart(lit2.var()) == part && partFinder.getVarPart(lit.var()) == part) || i->getLearnt());
+
+                //If it's learnt and the lits are in different parts, remove it.
+                if (partFinder.getVarPart(lit.var()) != part
+                    || partFinder.getVarPart(lit2.var()) != part
+                    ) {
+                    assert(i->getLearnt());
+                    numRemovedHalfLearnt++;
+                    continue;
+                }
+
+                assert(lit != lit2);
+                if (lit < lit2) { //don't add the same clause twice
+                    vec<Lit> lits(2);
+                    lits[0] = lit;
+                    lits[1] = lit2;
+                    assert(partFinder.getVarPart(lit.var()) == part);
+                    assert(partFinder.getVarPart(lit2.var()) == part);
+                    if (i->getLearnt()) {
+                        newSolver.addLearntClause(lits);
+                        binClausesRemoved.push_back(std::make_pair(lit, lit2));
+                        numRemovedHalfLearnt++;
+                    } else {
+                        newSolver.addClause(lits);
+                        numRemovedHalfNonLearnt++;
+                    }
+                } else {
+                    if (i->getLearnt()) numRemovedHalfLearnt++;
+                    else numRemovedHalfNonLearnt++;
+                }
+            } else {
+                *j++ = *i;
+            }
+        }
+        ws.shrink_(i-j);
+    }
+
+    solver.learnts_literals -= numRemovedHalfLearnt;
+    solver.clauses_literals -= numRemovedHalfNonLearnt;
+    solver.numBins -= (numRemovedHalfLearnt + numRemovedHalfNonLearnt)/2;
+}
+
+/**
+@brief Move xor clauses from original to the part
+
+The variables that form part of the part will determine if the clause is in the
+part or not
+*/
 void PartHandler::moveClauses(vec<XorClause*>& cs, Solver& newSolver, const uint32_t part, PartFinder& partFinder)
 {
     XorClause **i, **j, **end;
@@ -251,13 +389,23 @@ void PartHandler::moveClauses(vec<XorClause*>& cs, Solver& newSolver, const uint
         XorClause& c = **i;
         vec<Lit> 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!
+        newSolver.addXorClause(tmp, c.xorEqualFalse(), c.getGroup());
+        //NOTE: we need the tmp because otherwise, the addXorClause could have changed "c", which we need to re-add later!
         xorClausesRemoved.push(*i);
     }
     cs.shrink(i-j);
 }
 
+/**
+@brief Move learnt clauses from original to the part
+
+The variables that form part of the part will determine if the clause is in the
+part or not.
+
+Note that learnt clauses might be in both the orignal and the sub-part. In this
+case, the learnt clause is deleted, since it unneccesarily connects two
+components that otherwise would be distinct
+*/
 void PartHandler::moveLearntClauses(vec<Clause*>& cs, Solver& newSolver, const uint32_t part, PartFinder& partFinder)
 {
     Clause **i, **j, **end;
@@ -266,7 +414,7 @@ void PartHandler::moveLearntClauses(vec<Clause*>& cs, Solver& newSolver, const u
             *j++ = *i;
             continue;
         }
-        
+
         Clause& c = **i;
         assert(c.size() > 0);
         uint32_t clause_part = partFinder.getVarPart(c[0].var());
@@ -276,7 +424,7 @@ void PartHandler::moveLearntClauses(vec<Clause*>& cs, Solver& newSolver, const u
                 #ifdef VERBOSE_DEBUG
                 std::cout << "Learnt clause in both parts:"; c.plainPrint();
                 #endif
-                
+
                 removed = true;
                 solver.removeClause(c);
                 break;
@@ -287,21 +435,30 @@ void PartHandler::moveLearntClauses(vec<Clause*>& cs, Solver& newSolver, const u
             #ifdef VERBOSE_DEBUG
             //std::cout << "Learnt clause in this part:"; c.plainPrint();
             #endif
-            
+
             solver.detachClause(c);
-            newSolver.addLearntClause(c, c.getGroup(), c.activity());
+            newSolver.addLearntClause(c, c.getGroup(), NULL, c.getGlue(), c.getMiniSatAct());
             solver.clauseAllocator.clauseFree(&c);
         } else {
             #ifdef VERBOSE_DEBUG
             std::cout << "Learnt clause in other part:"; c.plainPrint();
             #endif
-            
+
             *j++ = *i;
         }
     }
     cs.shrink(i-j);
 }
 
+/**
+@brief Adds the saved states to the final solutions
+
+It is only called if the solution of the main part was SAT, and the parts
+have all been SAT. We now basically extend the main part with the solutions
+of the sub-parts.
+
+Sets all saved states to l_Undef, i.e. unassigns them
+*/
 void PartHandler::addSavedState()
 {
     //Don't add these (non-0-decison-level!) solutions to the 0th decision level
@@ -315,12 +472,23 @@ void PartHandler::addSavedState()
             solver.polarity[var] = (solver.assigns[var] == l_False);
         }
     }
-    
+
     for (uint32_t i = 0; i < decisionVarRemoved.size(); i++)
         solver.setDecisionVar(decisionVarRemoved[i], true);
     decisionVarRemoved.clear();
 }
 
+/**
+@brief Re-add the clauses that have been removed because they were in a part
+
+We remove the clauses that are are in a part. Then, at the very end of the
+solving, we must re-add them, since if the program is used a library, then
+solve() might be called again, at which point we would be missing our clauses!
+
+(Furhtermore, clauses might be added between the end of solving and the
+next solve() command, so we cannot keep in memory which parts were what, because
+parts might be connected through the added clauses)
+*/
 void PartHandler::readdRemovedClauses()
 {
     FILE* backup_libraryCNFfile = solver.libraryCNFFile;
@@ -330,13 +498,22 @@ void PartHandler::readdRemovedClauses()
         assert(solver.ok);
     }
     clausesRemoved.clear();
-    
+
     for (XorClause **it = xorClausesRemoved.getData(), **end = xorClausesRemoved.getDataEnd(); it != end; it++) {
-        solver.addXorClause(**it, (**it).xor_clause_inverted(), (*it)->getGroup());
+        solver.addXorClause(**it, (**it).xorEqualFalse(), (*it)->getGroup());
         assert(solver.ok);
     }
     xorClausesRemoved.clear();
+
+    for (vector<pair<Lit, Lit> >::const_iterator it = binClausesRemoved.begin(), end = binClausesRemoved.end(); it != end; it++) {
+        vec<Lit> lits(2);
+        lits[0] = it->first;
+        lits[1] = it->second;
+        solver.addClause(lits);
+        assert(solver.ok);
+    }
+    binClausesRemoved.clear();
+
     solver.libraryCNFFile = backup_libraryCNFfile;
 }
 
-}; //NAMESPACE MINISAT
index f73bc98f134feab50567165ba2fa131b8374df24..7751d2bed21715d5b4f86936662103c397ea978b 100644 (file)
@@ -29,10 +29,14 @@ using std::map;
 using std::vector;
 using std::pair;
 
-namespace MINISAT
-{
-using namespace MINISAT;
+/**
+@brief Disconnected components are treated here
 
+Uses PartFinder to find disconnected components and treats them using
+subsolvers. The solutions (if SAT) are aggregated, and at then end, the
+solution is extended with the sub-solutions, and the removed clauses are
+added back to the problem.
+*/
 class PartHandler
 {
     public:
@@ -44,41 +48,64 @@ class PartHandler
         void readdRemovedClauses();
 
         friend class ClauseAllocator;
-        
+
     private:
         struct sort_pred {
             bool operator()(const std::pair<int,int> &left, const std::pair<int,int> &right) {
                 return left.second < right.second;
             }
         };
-        
+
+        void configureNewSolver(Solver& newSolver) const;
+        void moveVariablesBetweenSolvers(Solver& newSolver, vector<Var>& vars, const uint32_t part, const PartFinder& partFinder);
+
         //For moving clauses
+        void moveBinClauses(Solver& newSolver, const uint32_t part, PartFinder& partFinder);
         void moveClauses(vec<XorClause*>& cs, Solver& newSolver, const uint32_t part, PartFinder& partFinder);
         void moveClauses(vec<Clause*>& cs, Solver& newSolver, const uint32_t part, PartFinder& partFinder);
         void moveLearntClauses(vec<Clause*>& cs, Solver& newSolver, const uint32_t part, PartFinder& partFinder);
-        
+
         //Checking moved clauses
         const bool checkClauseMovement(const Solver& thisSolver, const uint32_t part, const PartFinder& partFinder) const;
         template<class T>
         const bool checkOnlyThisPart(const vec<T*>& cs, const uint32_t part, const PartFinder& partFinder) const;
-        
-        Solver& solver;
+        const bool checkOnlyThisPartBin(const Solver& thisSolver, const uint32_t part, const PartFinder& partFinder) const;
+
+        Solver& solver; ///<The base solver
+        /**
+        @brief The SAT solutions that have been found by the parts
+
+        When a part finishes with SAT, its soluton is saved here. In th end
+        the solutions are aggregaed using addSavedState()
+        */
         vec<lbool> savedState;
-        vec<Var> decisionVarRemoved; //variables whose decision-ness has been removed
+        vec<Var> decisionVarRemoved; ///<List of variables whose decision-ness has been removed (set to FALSE)
+
+        //Clauses that have been moved to other parts
         vec<Clause*> clausesRemoved;
+        vector<pair<Lit, Lit> > binClausesRemoved;
         vec<XorClause*> xorClausesRemoved;
 };
 
+/**
+@brief Returns the saved state of a variable
+*/
 inline const vec<lbool>& PartHandler::getSavedState()
 {
     return savedState;
 }
 
+/**
+@brief Creates a space in savedState
+
+So that the solution can eventually be saved here (if parts are used). By
+default the value is l_Undef, i.e. no solution has been saved there.
+*/
 inline void PartHandler::newVar()
 {
     savedState.push(l_Undef);
 }
 
-}; //NAMESPACE MINISAT
+
 
 #endif //PARTHANDLER_H
diff --git a/src/sat/cryptominisat2/PropBy.h b/src/sat/cryptominisat2/PropBy.h
new file mode 100644 (file)
index 0000000..92f8464
--- /dev/null
@@ -0,0 +1,288 @@
+/***********************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+************************************************************************/
+
+#ifndef PROPBY_H
+#define PROPBY_H
+
+#include "SolverTypes.h"
+#include "Clause.h"
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+#include <stdio.h>
+
+//#define DEBUG_PROPAGATEFROM
+
+#include "ClauseOffset.h"
+#include "ClauseAllocator.h"
+
+class PropBy
+{
+    private:
+        uint64_t propType:2;
+        //0: clause, NULL
+        //1: clause, non-null
+        //2: binary
+        //3: tertiary
+        uint64_t data1:30;
+        uint64_t data2:32;
+
+    public:
+        PropBy() :
+            propType(0)
+            , data1(0)
+            , data2(0)
+        {}
+
+        PropBy(ClauseOffset offset) :
+            propType(1)
+            , data2(offset)
+        {
+        }
+
+        PropBy(const Lit lit) :
+            propType(2)
+            , data1(lit.toInt())
+        {
+        }
+
+        PropBy(const Lit lit1, const Lit lit2) :
+            propType(3)
+            , data1(lit1.toInt())
+            , data2(lit2.toInt())
+        {
+        }
+
+        const bool isClause() const
+        {
+            return ((propType&2) == 0);
+        }
+
+        const bool isBinary() const
+        {
+            return (propType == 2);
+        }
+
+        const bool isTri() const
+        {
+            return (propType == 3);
+        }
+
+        const Lit getOtherLit() const
+        {
+            #ifdef DEBUG_PROPAGATEFROM
+            assert(isBinary() || isTri());
+            #endif
+            return Lit::toLit(data1);
+        }
+
+        const Lit getOtherLit2() const
+        {
+            #ifdef DEBUG_PROPAGATEFROM
+            assert(isTri());
+            #endif
+            return Lit::toLit(data2);
+        }
+
+        const ClauseOffset getClause() const
+        {
+            #ifdef DEBUG_PROPAGATEFROM
+            assert(isClause());
+            #endif
+            return data2;
+        }
+
+        ClauseOffset getClause()
+        {
+            #ifdef DEBUG_PROPAGATEFROM
+            assert(isClause());
+            #endif
+            return data2;
+        }
+
+        const bool isNULL() const
+        {
+            if (!isClause()) return false;
+            return propType == 0;
+        }
+
+        /*const uint32_t size() const
+        {
+            if (isBinary()) return 2;
+            if (isTri()) return 3;
+
+            #ifdef DEBUG_PROPAGATEFROM
+            assert(!isNULL());
+            #endif
+
+            return getClause()->size();
+        }*/
+
+        /*const Lit operator[](uint32_t i) const
+        {
+            if (isBinary()) {
+                #ifdef DEBUG_PROPAGATEFROM
+                assert(i == 1);
+                #endif
+                return getOtherLit();
+            }
+
+            if (isTriClause()) {
+                #ifdef DEBUG_PROPAGATEFROM
+                assert(i <= 2);
+                #endif
+                if (i == 1) return getOtherLit();
+                if (i == 2) return getOtherLit2();
+            }
+
+            #ifdef DEBUG_PROPAGATEFROM
+            assert(!isNULL());
+            #endif
+            return (*getClause())[i];
+        }*/
+};
+
+inline std::ostream& operator<<(std::ostream& os, const PropBy& pb)
+{
+    if (pb.isBinary()) {
+        os << " binary, other lit= " << pb.getOtherLit();
+    } else if (pb.isClause()) {
+        os << " clause, num= " << pb.getClause();
+    } else if (pb.isNULL()) {
+        os << " NULL";
+    } else if (pb.isTri()) {
+        os << " tri, other 2 lits= " << pb.getOtherLit() << " , "<< pb.getOtherLit2();
+    }
+    return os;
+}
+
+class PropByFull
+{
+    private:
+        uint32_t type;
+        Clause* clause;
+        Lit lits[3];
+
+    public:
+        PropByFull(PropBy orig, Lit otherLit, ClauseAllocator& alloc) :
+            type(10)
+            , clause(NULL)
+        {
+            if (orig.isBinary() || orig.isTri()) {
+                lits[0] = otherLit;
+                lits[1] = orig.getOtherLit();
+                if (orig.isTri()) {
+                    lits[2] = orig.getOtherLit2();
+                    type = 2;
+                } else {
+                    type = 1;
+                }
+            }
+            if (orig.isClause()) {
+                type = 0;
+                if (orig.isNULL()) {
+                    clause = NULL;
+                } else {
+                    clause = alloc.getPointer(orig.getClause());
+                }
+            }
+        }
+
+        PropByFull() :
+            type(10)
+        {}
+
+        PropByFull(PropByFull& other) :
+            type(other.type)
+            , clause(other.clause)
+        {
+            memcpy(lits, other.lits, sizeof(Lit)*3);
+        }
+
+        const uint32_t size() const
+        {
+            switch (type) {
+                case 0 : return clause->size();
+                case 1 : return 2;
+                case 2 : return 3;
+                default:
+                    assert(false);
+                    return 0;
+            }
+        }
+
+        const bool isNULL() const
+        {
+            return type == 0 && clause == NULL;
+        }
+
+        const bool isClause() const
+        {
+            return type == 0;
+        }
+
+        const bool isBinary() const
+        {
+            return type == 1;
+        }
+
+        const bool isTri() const
+        {
+            return type == 2;
+        }
+
+        const Clause* getClause() const
+        {
+            return clause;
+        }
+
+        Clause* getClause()
+        {
+            return clause;
+        }
+
+        const Lit operator[](const uint32_t i) const
+        {
+            switch (type) {
+                case 0: {
+                    assert(clause != NULL);
+                    return (*clause)[i];
+                }
+                default : {
+                    return lits[i];
+                }
+            }
+        }
+};
+
+inline std::ostream& operator<<(std::ostream& cout, const PropByFull& propByFull)
+{
+
+    if (propByFull.isBinary()) {
+        cout << "binary: " << " ? , " << propByFull[1];
+    } else if (propByFull.isTri()) {
+        cout << "tri: " << " ? , " <<propByFull[1] << " , " << propByFull[2];
+    } else if (propByFull.isClause()) {
+        if (propByFull.isNULL()) cout << "null clause";
+        else cout << "clause:" << *propByFull.getClause();
+    }
+    return cout;
+}
+
+#endif //PROPBY_H
index 739c4499c799ce4b8b65fe9726cff4fb331533b3..dcda986f53dda17f33c56b6d71530606ac22672b 100644 (file)
@@ -1,4 +1,4 @@
-/***********************************************************************************
+/****************************************************************************
 CryptoMiniSat -- Copyright (c) 2009 Mate Soos
 
 This program is free software: you can redistribute it and/or modify
@@ -13,18 +13,17 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
-**************************************************************************************************/
+*****************************************************************************/
 
 #include "RestartTypeChooser.h"
+
+#include <utility>
 #include "Solver.h"
+using std::pair;
 
 //#define VERBOSE_DEBUG
 //#define PRINT_VARS
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 RestartTypeChooser::RestartTypeChooser(const Solver& s) :
     solver(s)
     , topX(100)
@@ -32,14 +31,20 @@ RestartTypeChooser::RestartTypeChooser(const Solver& s) :
 {
 }
 
+/**
+@brief Adds info at the end of a restart to the internal datastructures
+
+It is called a number of times after a full restart has been done, to
+accumulate data. Finally, choose() is called to choose the restart type
+*/
 void RestartTypeChooser::addInfo()
 {
     firstVarsOld = firstVars;
     calcHeap();
-    uint sameIn = 0;
+    uint32_t sameIn = 0;
     if (!firstVarsOld.empty()) {
-        uint thisTopX = std::min(firstVarsOld.size(), (size_t)topX);
-        for (uint i = 0; i != thisTopX; i++) {
+        uint32_t thisTopX = std::min(firstVarsOld.size(), (size_t)topX);
+        for (uint32_t i = 0; i != thisTopX; i++) {
             if (std::find(firstVars.begin(), firstVars.end(), firstVarsOld[i]) != firstVars.end())
                 sameIn++;
         }
@@ -48,16 +53,19 @@ void RestartTypeChooser::addInfo()
         #endif
         sameIns.push_back(sameIn);
     }
-    
+
     #ifdef VERBOSE_DEBUG
     std::cout << "Avg same vars in first&second first 100: " << avg() << " standard Deviation:" << stdDeviation(sameIns) <<std::endl;
     #endif
 }
 
+/**
+@brief After accumulation of data, this function finally decides which type to choose
+*/
 const RestartType RestartTypeChooser::choose()
 {
     pair<double, double> mypair = countVarsDegreeStDev();
-    if ((mypair.second  < 80 && 
+    if ((mypair.second  < 80 &&
         (avg() > (double)limit || ((avg() > (double)(limit*0.9) && stdDeviation(sameIns) < 5))))
         ||
         (mypair.second  < 80 && (double)solver.xorclauses.size() > (double)solver.nClauses()*0.1))
@@ -66,22 +74,28 @@ const RestartType RestartTypeChooser::choose()
         return dynamic_restart;
 }
 
+/**
+@brief Calculates average for topx variable activity changes
+*/
 const double RestartTypeChooser::avg() const
 {
     double sum = 0.0;
-    for (uint i = 0; i != sameIns.size(); i++)
+    for (uint32_t i = 0; i != sameIns.size(); i++)
         sum += sameIns[i];
     return (sum/(double)sameIns.size());
 }
 
+/**
+@brief Calculates standard deviation for topx variable activity changes
+*/
 const double RestartTypeChooser::stdDeviation(vector<uint32_t>& measure) const
 {
     double average = avg();
     double variance = 0.0;
-    for (uint i = 0; i != measure.size(); i++)
+    for (uint32_t i = 0; i != measure.size(); i++)
         variance += pow((double)measure[i]-average, 2);
     variance /= (double)measure.size();
-    
+
     return sqrt(variance);
 }
 
@@ -110,7 +124,7 @@ const std::pair<double, double> RestartTypeChooser::countVarsDegreeStDev() const
     vector<uint32_t> degrees;
     degrees.resize(solver.nVars(), 0);
     addDegrees(solver.clauses, degrees);
-    addDegrees(solver.binaryClauses, degrees);
+    addDegreesBin(degrees);
     addDegrees(solver.xorclauses, degrees);
     uint32_t sum = 0;
     uint32_t *i = &degrees[0], *j = i;
@@ -121,14 +135,14 @@ const std::pair<double, double> RestartTypeChooser::countVarsDegreeStDev() const
         }
     }
     degrees.resize(degrees.size() - (i-j));
-    
+
     double avg = (double)sum/(double)degrees.size();
     double stdDev = stdDeviation(degrees);
-    
+
     #ifdef VERBOSE_DEBUG
     std::cout << "varsDegree avg:" << avg << " stdDev:" << stdDev << std::endl;
     #endif
-    
+
     return std::make_pair(avg, stdDev);
 }
 
@@ -138,7 +152,7 @@ void RestartTypeChooser::addDegrees(const vec<T*>& cs, vector<uint32_t>& degrees
     for (T * const*c = cs.getData(), * const*end = c + cs.size(); c != end; c++) {
         T& cl = **c;
         if (cl.learnt()) continue;
-        
+
         for (const Lit *l = cl.getData(), *end2 = l + cl.size(); l != end2; l++) {
             degrees[l->var()]++;
         }
@@ -148,5 +162,18 @@ void RestartTypeChooser::addDegrees(const vec<T*>& cs, vector<uint32_t>& degrees
 template void RestartTypeChooser::addDegrees(const vec<Clause*>& cs, vector<uint32_t>& degrees) const;
 template void RestartTypeChooser::addDegrees(const vec<XorClause*>& cs, vector<uint32_t>& degrees) const;
 
-}; //NAMESPACE MINISAT
+void RestartTypeChooser::addDegreesBin(vector<uint32_t>& degrees) const
+{
+    uint32_t wsLit = 0;
+    for (const vec<Watched> *it = solver.watches.getData(), *end = solver.watches.getDataEnd(); it != end; it++, wsLit++) {
+        Lit lit = ~Lit::toLit(wsLit);
+        const vec<Watched>& ws = *it;
+        for (const Watched *it2 = ws.getData(), *end2 = ws.getDataEnd(); it2 != end2; it2++) {
+            if (it2->isBinary() && lit.toInt() < it2->getOtherLit().toInt()) {
+                degrees[lit.var()]++;
+                degrees[it2->getOtherLit().var()]++;
+            }
+        }
+    }
+}
 
index 4c0628d481520f5c4c141e921ad89414972efc14..446b1e9a82c22575f9cb68d6cd5c765f960f38b6 100644 (file)
@@ -30,12 +30,18 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 using std::vector;
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 class Solver;
 
+/**
+@brief Chooses between MiniSat and GLUCOSE restart types&learnt clause evaluation
+
+MiniSat style restart is geometric, and glucose-type is dynamic. MiniSat-type
+learnt clause staistic is activity-based, glucose-type is glue-based. This
+class takes as input a number of MiniSat restart's end results, computes some
+statistics on them, and at the end, tells if we should use one type or the
+other. Basically, it masures variable activity stability, number of xors
+in the problem, and variable degrees.
+*/
 class RestartTypeChooser
 {
     public:
@@ -43,22 +49,24 @@ class RestartTypeChooser
         void addInfo();
         const RestartType choose();
         void reset();
-        
+
     private:
         void calcHeap();
         const double avg() const;
         const std::pair<double, double> countVarsDegreeStDev() const;
         const double stdDeviation(vector<uint32_t>& measure) const;
-        
+
         template<class T>
         void addDegrees(const vec<T*>& cs, vector<uint32_t>& degrees) const;
-        
+        void addDegreesBin(vector<uint32_t>& degrees) const;
+
         const Solver& solver;
-        const uint32_t topX;
-        const uint32_t limit;
+        const uint32_t topX; ///<The how many is the top X? 100 is default
+        const uint32_t limit; ///<If top x contains on average this many common varables, we select MiniSat-type
         vector<Var> sameIns;
-        
-        vector<Var> firstVars, firstVarsOld;
+
+        vector<Var> firstVars; ///<The top x variables (in terms of var activity)
+        vector<Var> firstVarsOld; ///<The previous top x variables (in terms of var activity)
 };
 
 inline void RestartTypeChooser::reset()
@@ -66,6 +74,4 @@ inline void RestartTypeChooser::reset()
     sameIns.clear();
 }
 
-}; //NAMESPACE MINISAT
-
 #endif //RESTARTTYPECHOOSER_H
diff --git a/src/sat/cryptominisat2/SCCFinder.cpp b/src/sat/cryptominisat2/SCCFinder.cpp
new file mode 100644 (file)
index 0000000..226eb50
--- /dev/null
@@ -0,0 +1,134 @@
+/*****************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+#include <iostream>
+#include <vector>
+#include "SolverTypes.h"
+#include "SCCFinder.h"
+#include "VarReplacer.h"
+#include <iomanip>
+#include "time_mem.h"
+#include "Subsumer.h"
+#include "XorSubsumer.h"
+
+SCCFinder::SCCFinder(Solver& _solver) :
+    solver(_solver)
+    , varElimed1(_solver.subsumer->getVarElimed())
+    , varElimed2(_solver.xorSubsumer->getVarElimed())
+    , replaceTable(_solver.varReplacer->getReplaceTable())
+    , totalTime(0.0)
+{}
+
+const bool SCCFinder::find2LongXors()
+{
+    double myTime = cpuTime();
+    uint32_t oldNumReplace = solver.varReplacer->getNewToReplaceVars();
+
+    globalIndex = 0;
+    index.clear();
+    index.resize(solver.nVars()*2, std::numeric_limits<uint32_t>::max());
+    lowlink.clear();
+    lowlink.resize(solver.nVars()*2, std::numeric_limits<uint32_t>::max());
+    stackIndicator.clear();
+    stackIndicator.growTo(solver.nVars()*2, false);
+    assert(stack.empty());
+
+    for (uint32_t vertex = 0; vertex < solver.nVars()*2; vertex++) {
+        //Start a DFS at each node we haven't visited yet
+        if (index[vertex] == std::numeric_limits<uint32_t>::max()) {
+            recurDepth = 0;
+            tarjan(vertex);
+            assert(stack.empty());
+        }
+    }
+
+    if (solver.conf.verbosity >= 2 || (solver.conflicts == 0 && solver.conf.verbosity  >= 1)) {
+        std::cout << "c Finding binary XORs  T: "
+        << std::fixed << std::setprecision(2) << std::setw(8) <<  (cpuTime() - myTime) << " s"
+        << "  found: " << std::setw(7) << solver.varReplacer->getNewToReplaceVars() - oldNumReplace
+        << std::endl;
+    }
+    totalTime += (cpuTime() - myTime);
+
+    return solver.ok;
+}
+
+void SCCFinder::tarjan(const uint32_t vertex)
+{
+    recurDepth++;
+    index[vertex] = globalIndex;  // Set the depth index for v
+    lowlink[vertex] = globalIndex;
+    globalIndex++;
+    stack.push(vertex); // Push v on the stack
+    stackIndicator[vertex] = true;
+
+    Var vertexVar = Lit::toLit(vertex).var();
+    if (!varElimed1[vertexVar] && !varElimed2[vertexVar]) {
+        const vec<Watched>& ws = solver.watches[vertex];
+        for (const Watched *it = ws.getData(), *end = ws.getDataEnd(); it != end; it++) {
+            if (!it->isBinary()) continue;
+            const Lit lit = it->getOtherLit();
+
+            doit(lit, vertex);
+        }
+
+        if (solver.conf.doExtendedSCC) {
+            Lit vertLit = Lit::toLit(vertex);
+            vector<Lit>& transCache = solver.transOTFCache[(~Lit::toLit(vertex)).toInt()].lits;
+            vector<Lit>::iterator it = transCache.begin();
+            vector<Lit>::iterator it2 = it;
+            uint32_t newSize = 0;
+            for (vector<Lit>::iterator end = transCache.end(); it != end; it++) {
+                Lit lit = *it;
+                lit = replaceTable[lit.var()] ^ lit.sign();
+                if (lit == vertLit || varElimed1[lit.var()] || varElimed2[lit.var()]) continue;
+                *it2++ = lit;
+                newSize++;
+
+                doit(lit, vertex);
+            }
+            transCache.resize(newSize);
+        }
+    }
+
+    // Is v the root of an SCC?
+    if (lowlink[vertex] == index[vertex]) {
+        uint32_t vprime;
+        tmp.clear();
+        do {
+            assert(!stack.empty());
+            vprime = stack.top();
+            stack.pop();
+            stackIndicator[vprime] = false;
+            tmp.push(vprime);
+        } while (vprime != vertex);
+        if (tmp.size() >= 2) {
+            for (uint32_t i = 1; i < tmp.size(); i++) {
+                if (!solver.ok) break;
+                vec<Lit> lits(2);
+                lits[0] = Lit::toLit(tmp[0]).unsign();
+                lits[1] = Lit::toLit(tmp[i]).unsign();
+                const bool xorEqualsFalse = Lit::toLit(tmp[0]).sign()
+                                            ^ Lit::toLit(tmp[i]).sign()
+                                            ^ true;
+                if (solver.value(lits[0]) == l_Undef && solver.value(lits[1]) == l_Undef) {
+                    solver.varReplacer->replace(lits, xorEqualsFalse, 0);
+                }
+            }
+        }
+    }
+}
diff --git a/src/sat/cryptominisat2/SCCFinder.h b/src/sat/cryptominisat2/SCCFinder.h
new file mode 100644 (file)
index 0000000..9b60b35
--- /dev/null
@@ -0,0 +1,68 @@
+/*****************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+#ifndef SCCFINDER_H
+#define SCCFINDER_H
+
+#include "Vec.h"
+#include "Clause.h"
+#include "Solver.h"
+#include <stack>
+
+class SCCFinder {
+    public:
+        SCCFinder(Solver& solver);
+        const bool find2LongXors();
+        const double getTotalTime() const;
+
+    private:
+        void tarjan(const uint32_t vertex);
+        void doit(const Lit lit, const uint32_t vertex);
+
+        uint32_t globalIndex;
+        vector<uint32_t> index;
+        vector<uint32_t> lowlink;
+        std::stack<uint32_t> stack;
+        vec<char> stackIndicator;
+        vec<uint32_t> tmp;
+
+        uint32_t recurDepth;
+
+        Solver& solver;
+        const vec<char>& varElimed1;
+        const vec<char>& varElimed2;
+        const vector<Lit>& replaceTable;
+        double totalTime;
+};
+
+inline void SCCFinder::doit(const Lit lit, const uint32_t vertex) {
+    // Was successor v' visited?
+    if (index[lit.toInt()] ==  std::numeric_limits<uint32_t>::max()) {
+        tarjan(lit.toInt());
+        recurDepth--;
+        lowlink[vertex] = std::min(lowlink[vertex], lowlink[lit.toInt()]);
+    } else if (stackIndicator[lit.toInt()])  {
+        lowlink[vertex] = std::min(lowlink[vertex], lowlink[lit.toInt()]);
+    }
+}
+
+inline const double SCCFinder::getTotalTime() const
+{
+    return totalTime;
+}
+
+#endif //SCCFINDER_H
diff --git a/src/sat/cryptominisat2/SharedData.h b/src/sat/cryptominisat2/SharedData.h
new file mode 100644 (file)
index 0000000..8688f98
--- /dev/null
@@ -0,0 +1,33 @@
+/**************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#ifndef SHARED_DATA_H
+#define SHARED_DATA_H
+
+#include "Vec.h"
+#include "SolverTypes.h"
+
+#include <vector>
+
+class SharedData
+{
+    public:
+        vec<lbool> value;
+        std::vector<std::vector<Lit> > bins;
+};
+
+#endif //SHARED_DATA_H
index d3c353f95d01cf669175393591f24929db4802b9..79fe687701ca0398b62eae30959a48f7fe45874f 100644 (file)
@@ -1,23 +1,11 @@
-/****************************************************************************************[Solver.C]
+/*****************************************************************************
 MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
-CryptoMiniSat -- Copyright (c) 2009 Mate Soos
 glucose -- Gilles Audemard, Laurent Simon (2008)
+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.
-**************************************************************************************************/
+Original code by MiniSat and glucose authors are under an MIT licence.
+Modifications for CryptoMiniSat are under GPLv3 licence.
+******************************************************************************/
 
 #include "Solver.h"
 #include <cmath>
@@ -26,6 +14,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
 #include <limits.h>
 #include <vector>
 #include <iomanip>
+#include <algorithm>
 
 #include "Clause.h"
 #include "time_mem.h"
@@ -35,143 +24,124 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
 #include "XorFinder.h"
 #include "ClauseCleaner.h"
 #include "RestartTypeChooser.h"
-#include "FailedVarSearcher.h"
+#include "FailedLitSearcher.h"
 #include "Subsumer.h"
 #include "PartHandler.h"
 #include "XorSubsumer.h"
 #include "StateSaver.h"
-#include "UselessBinRemover.h"
-#include "OnlyNonLearntBins.h"
-
-#ifdef USE_GAUSS
+#include "SCCFinder.h"
+#include "SharedData.h"
+#include "ClauseVivifier.h"
 #include "Gaussian.h"
 #include "MatrixFinder.h"
-#endif //USE_GAUSS
+#include "DataSync.h"
 
 #ifdef _MSC_VER
 #define __builtin_prefetch(a,b,c)
 //#define __builtin_prefetch(a,b)
 #endif //_MSC_VER
 
+#ifdef VERBOSE_DEBUG
+#define UNWINDING_DEBUG
+#endif
+
 //#define DEBUG_UNCHECKEDENQUEUE_LEVEL0
 //#define VERBOSE_DEBUG_POLARITIES
 //#define DEBUG_DYNAMIC_RESTART
-
-namespace MINISAT
-{
-using namespace MINISAT;
+//#define UNWINDING_DEBUG
 
 //=================================================================================================
 // Constructor/Destructor:
 
 
-Solver::Solver() :
+/**
+@brief Sets a sane default config and allocates handler classes
+*/
+Solver::Solver(const SolverConf& _conf, const GaussConf& _gaussconfig, SharedData* sharedData) :
         // Parameters: (formerly in 'SearchParams')
-        random_var_freq(0.02)
-        , clause_decay (1 / 0.999)
-        , restart_first(100), restart_inc(1.5), learntsize_factor((double)1/(double)3), learntsize_inc(1)
-
-        // More parameters:
-        //
-        , expensive_ccmin  (true)
-        , polarity_mode    (polarity_auto)
-        , verbosity        (0)
-        , restrictedPickBranch(0)
-        , findNormalXors   (true)
-        , findBinaryXors   (true)
-        , regularlyFindBinaryXors(true)
-        , performReplace   (true)
-        , conglomerateXors (true)
-        , heuleProcess     (true)
-        , schedSimplification(true)
-        , doSubsumption    (true)
-        , doXorSubsumption (true)
-        , doPartHandler    (true)
-        , doHyperBinRes    (true)
-        , doBlockedClause  (true)
-        , doVarElim        (true)
-        , doSubsume1       (true)
-        , failedVarSearch  (true)
-        , addExtraBins     (true)
-        , removeUselessBins(true)
-        , regularRemoveUselessBins(true)
-        , subsumeWithNonExistBinaries(true)
-        , regularSubsumeWithNonExistBinaries(true)
-        , libraryUsage     (true)
-        , greedyUnbound    (false)
-        , fixRestartType   (auto_restart)
-
-        // Statistics: (formerly in 'SolverStats')
-        //
-        , starts(0), dynStarts(0), staticStarts(0), fullStarts(0), decisions(0), rnd_decisions(0), propagations(0), conflicts(0)
-        , clauses_literals(0), learnts_literals(0), max_literals(0), tot_literals(0)
-        , nbDL2(0), nbBin(0), lastNbBin(0), becameBinary(0), lastSearchForBinaryXor(0), nbReduceDB(0)
-        , improvedClauseNo(0), improvedClauseSize(0)
-        
+        conf(_conf)
+        , gaussconfig(_gaussconfig)
+        , needToInterrupt  (false)
         #ifdef USE_GAUSS
         , sum_gauss_called (0)
         , sum_gauss_confl  (0)
         , sum_gauss_prop   (0)
         , sum_gauss_unit_truths (0)
         #endif //USE_GAUSS
+
+        // Stats
+        , starts(0), dynStarts(0), staticStarts(0), fullStarts(0), decisions(0), rnd_decisions(0), propagations(0), conflicts(0)
+        , clauses_literals(0), learnts_literals(0), max_literals(0), tot_literals(0)
+        , nbGlue2(0), numNewBin(0), lastNbBin(0), lastSearchForBinaryXor(0), nbReduceDB(0)
+        , improvedClauseNo(0), improvedClauseSize(0)
+        , numShrinkedClause(0), numShrinkedClauseLits(0)
+        , moreRecurMinLDo(0)
+        , updateTransCache(0)
+        , nbClOverMaxGlue(0)
+
         , ok               (true)
-        , var_inc          (128)
+        , numBins          (0)
         , cla_inc          (1)
-        
-        , curRestart       (1)
-        , nbclausesbeforereduce (NBCLAUSESBEFOREREDUCE)
-        , nbCompensateSubsumer (0)
-        
         , qhead            (0)
-        , simpDB_assigns   (-1)
-        , simpDB_props     (0)
+        , mtrand           ((unsigned long int)0)
+
+        //variables
         , order_heap       (VarOrderLt(activity))
-        , progress_estimate(0)
-        , remove_satisfied (true)
-        , mtrand((unsigned long int)0)
-        , restartType      (static_restart)
-        , lastSelectedRestartType (static_restart)
+        , var_inc          (128)
+
+        //learnts
+        , numCleanedLearnts(1)
+        , nbClBeforeRed    (NBCLAUSESBEFOREREDUCE)
+        , nbCompensateSubsumer (0)
+
+        , MYFLAG           (0)
         #ifdef STATS_NEEDED
-        , logger(verbosity)
+        , logger(conf.verbosity)
         , dynamic_behaviour_analysis(false) //do not document the proof as default
         #endif
-        , maxRestarts(UINT_MAX)
-        , MYFLAG           (0)
         , learnt_clause_group(0)
         , libraryCNFFile   (NULL)
+        , restartType      (static_restart)
+        , lastSelectedRestartType (static_restart)
         , simplifying      (false)
+        , totalSimplifyTime(0.0)
+        , simpDB_assigns   (-1)
+        , simpDB_props     (0)
 {
+    mtrand.seed(conf.origSeed);
+    assert(conf.maxGlue < MAX_THEORETICAL_GLUE);
     varReplacer = new VarReplacer(*this);
     clauseCleaner = new ClauseCleaner(*this);
-    failedVarSearcher = new FailedVarSearcher(*this);
+    failedLitSearcher = new FailedLitSearcher(*this);
     partHandler = new PartHandler(*this);
     subsumer = new Subsumer(*this);
     xorSubsumer = new XorSubsumer(*this);
     restartTypeChooser = new RestartTypeChooser(*this);
-    #ifdef USE_GAUSS
+    sCCFinder = new SCCFinder(*this);
+    clauseVivifier = new ClauseVivifier(*this);
     matrixFinder = new MatrixFinder(*this);
-    #endif //USE_GAUSS
-    
+    dataSync = new DataSync(*this, sharedData);
+
     #ifdef STATS_NEEDED
     logger.setSolver(this);
     #endif
 }
 
+/**
+@brief Frees clauses and frees all allocated hander classes
+*/
 Solver::~Solver()
 {
-    #ifdef USE_GAUSS
     clearGaussMatrixes();
     delete matrixFinder;
-    #endif
-    
     delete varReplacer;
     delete clauseCleaner;
-    delete failedVarSearcher;
+    delete failedLitSearcher;
     delete partHandler;
     delete subsumer;
     delete xorSubsumer;
     delete restartTypeChooser;
-    
+
     if (libraryCNFFile)
         fclose(libraryCNFFile);
 }
@@ -180,24 +150,39 @@ Solver::~Solver()
 // Minor methods:
 
 
-// Creates a new SAT variable in the solver. If 'decision_var' is cleared, variable will not be
-// used as a decision variable (NOTE! This has effects on the meaning of a SATISFIABLE result).
+/**
+@brief Creates a new SAT variable in the solver
+
+This entails making the datastructures large enough to fit the new variable
+in all internal datastructures as well as all datastructures used in
+classes used inside Solver
+
+@p dvar The new variable should be used as a decision variable?
+   NOTE: this has effects on the meaning of a SATISFIABLE result
+*/
 Var Solver::newVar(bool dvar)
 {
     Var v = nVars();
     watches   .push();          // (list for positive literal)
     watches   .push();          // (list for negative literal)
-    binwatches.push();          // (list for positive literal)
-    binwatches.push();          // (list for negative literal)
-    xorwatches.push();          // (list for variables in xors)
-    reason    .push(PropagatedFrom());
+    reason    .push(PropBy());
     assigns   .push(l_Undef);
     level     .push(-1);
+    binPropData.push();
     activity  .push(0);
     seen      .push_back(0);
     seen      .push_back(0);
     permDiff  .push(0);
-    
+    unWindGlue.push(NULL);
+
+    //Transitive OTF self-subsuming resolution
+    seen2     .push_back(0);
+    seen2     .push_back(0);
+    transOTFCache.push_back(TransCache());
+    transOTFCache.push_back(TransCache());
+    litReachable.push_back(LitReachData());
+    litReachable.push_back(LitReachData());
+
     polarity  .push_back(defaultPolarity());
     #ifdef USE_OLD_POLARITIES
     oldPolarity.push_back(defaultPolarity());
@@ -205,31 +190,39 @@ Var Solver::newVar(bool dvar)
 
     decision_var.push_back(dvar);
     insertVarOrder(v);
-    
+
     varReplacer->newVar();
-    if (doPartHandler) partHandler->newVar();
-    if (doSubsumption || subsumeWithNonExistBinaries || regularSubsumeWithNonExistBinaries) subsumer->newVar();
-    if (doXorSubsumption) xorSubsumer->newVar();
+    partHandler->newVar();
+    subsumer->newVar();
+    xorSubsumer->newVar();
+    dataSync->newVar();
 
     insertVarOrder(v);
-    
+
     #ifdef STATS_NEEDED
     if (dynamic_behaviour_analysis)
         logger.new_var(v);
     #endif
-    
+
     if (libraryCNFFile)
         fprintf(libraryCNFFile, "c Solver::newVar() called\n");
 
     return v;
 }
 
+/**
+@brief Adds an xor clause to the problem
+
+Should ONLY be called from internally. This is different from the extenal
+xor clause-adding function addXorClause() in that it assumes that the variables
+inside are decision variables, have not been replaced, eliminated, etc.
+*/
 template<class T>
-XorClause* Solver::addXorClauseInt(T& ps, bool xor_clause_inverted, const uint32_t group)
+XorClause* Solver::addXorClauseInt(T& ps, bool xorEqualFalse, const uint32_t group, const bool learnt)
 {
     assert(qhead == trail.size());
     assert(decisionLevel() == 0);
-    
+
     if (ps.size() > (0x01UL << 18)) {
         std::cout << "Too long clause!" << std::endl;
         exit(-1);
@@ -243,60 +236,76 @@ XorClause* Solver::addXorClauseInt(T& ps, bool xor_clause_inverted, const uint32
             j--;
             p = lit_Undef;
             if (!assigns[ps[i].var()].isUndef())
-                xor_clause_inverted ^= assigns[ps[i].var()].getBool();
-        } else if (assigns[ps[i].var()].isUndef()) //just add
+                xorEqualFalse ^= assigns[ps[i].var()].getBool();
+        } else if (assigns[ps[i].var()].isUndef()) //just add
             ps[j++] = p = ps[i];
-        else //modify xor_clause_inverted instead of adding
-            xor_clause_inverted ^= (assigns[ps[i].var()].getBool());
+            assert(!subsumer->getVarElimed()[p.var()]);
+            assert(!xorSubsumer->getVarElimed()[p.var()]);
+        } else //modify xorEqualFalse instead of adding
+            xorEqualFalse ^= (assigns[ps[i].var()].getBool());
     }
     ps.shrink(i - j);
-    
+
     switch(ps.size()) {
         case 0: {
-            if (!xor_clause_inverted) ok = false;
+            if (!xorEqualFalse) ok = false;
             return NULL;
         }
         case 1: {
-            uncheckedEnqueue(Lit(ps[0].var(), xor_clause_inverted));
+            uncheckedEnqueue(Lit(ps[0].var(), xorEqualFalse));
             ok = (propagate().isNULL());
             return NULL;
         }
         case 2: {
             #ifdef VERBOSE_DEBUG
-            cout << "--> xor is 2-long, replacing var " << ps[0].var()+1 << " with " << (!xor_clause_inverted ? "-" : "") << ps[1].var()+1 << endl;
+            cout << "--> xor is 2-long, replacing var " << ps[0].var()+1 << " with " << (!xorEqualFalse ? "-" : "") << ps[1].var()+1 << endl;
             #endif
 
             ps[0] = ps[0].unsign();
             ps[1] = ps[1].unsign();
-            varReplacer->replace(ps, xor_clause_inverted, group);
+            varReplacer->replace(ps, xorEqualFalse, group);
             return NULL;
         }
         default: {
-            XorClause* c = clauseAllocator.XorClause_new(ps, xor_clause_inverted, group);
+            assert(!learnt);
+            XorClause* c = clauseAllocator.XorClause_new(ps, xorEqualFalse, group);
             attachClause(*c);
             return c;
         }
     }
 }
 
-template XorClause* Solver::addXorClauseInt(vec<Lit>& ps, bool xor_clause_inverted, const uint32_t group);
-template XorClause* Solver::addXorClauseInt(XorClause& ps, bool xor_clause_inverted, const uint32_t group);
+template XorClause* Solver::addXorClauseInt(vec<Lit>& ps, bool xorEqualFalse, const uint32_t group, const bool learnt);
+template XorClause* Solver::addXorClauseInt(XorClause& ps, bool xorEqualFalse, const uint32_t group, const bool learnt);
 
+/**
+@brief Adds an xor clause to the problem
+
+Calls addXorClauseInt() for the heavy-lifting. Basically, this does a bit
+of debug-related stuff (see "libraryCNFFile"), and then checks if any of the
+variables have been eliminated, replaced, etc. If so, it treats it correctly,
+and then calls addXorClauseInt() to actually add the xor clause.
+
+@p ps[inout] The VARIABLES in the xor clause. Beware, there must be NO signs
+            here: ALL must be unsigned (.sign() == false). Values passed here
+            WILL be changed, ordered, removed, etc!
+@p xorEqualFalse The xor must be equal to TRUE or false?
+*/
 template<class T>
-bool Solver::addXorClause(T& ps, bool xor_clause_inverted, const uint group, char* group_name)
+bool Solver::addXorClause(T& ps, bool xorEqualFalse, const uint32_t group, const char* group_name)
 {
     assert(decisionLevel() == 0);
     if (ps.size() > (0x01UL << 18)) {
         std::cout << "Too long clause!" << std::endl;
         exit(-1);
     }
-    
+
     if (libraryCNFFile) {
         fprintf(libraryCNFFile, "x");
         for (uint32_t i = 0; i < ps.size(); i++) ps[i].print(libraryCNFFile);
         fprintf(libraryCNFFile, "0\n");
     }
-    
+
     #ifdef STATS_NEEDED
     if (dynamic_behaviour_analysis) {
         logger.set_group_name(group, group_name);
@@ -307,72 +316,64 @@ bool Solver::addXorClause(T& ps, bool xor_clause_inverted, const uint group, cha
     if (!ok)
         return false;
     assert(qhead == trail.size());
+    #ifndef NDEBUG
+    for (Lit *l = ps.getData(), *end = ps.getDataEnd(); l != end; l++) {
+        assert(l->var() < nVars() && "Clause inserted, but variable inside has not been declared with newVar()!");
+    }
+    #endif
 
-    // Check if clause is satisfied and remove false/duplicate literals:
     if (varReplacer->getNumLastReplacedVars() || subsumer->getNumElimed() || xorSubsumer->getNumElimed()) {
         for (uint32_t i = 0; i != ps.size(); i++) {
+            Lit otherLit = varReplacer->getReplaceTable()[ps[i].var()];
+            if (otherLit.var() != ps[i].var()) {
+                ps[i] = Lit(otherLit.var(), false);
+                xorEqualFalse ^= otherLit.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();
-                }
-            }
         }
     }
-    
-    XorClause* c = addXorClauseInt(ps, xor_clause_inverted, group);
+
+    XorClause* c = addXorClauseInt(ps, xorEqualFalse, group);
     if (c != NULL) xorclauses.push(c);
 
     return ok;
 }
 
-template bool Solver::addXorClause(vec<Lit>& ps, bool xor_clause_inverted, const uint group, char* group_name);
-template bool Solver::addXorClause(XorClause& ps, bool xor_clause_inverted, const uint group, char* group_name);
-
+template bool Solver::addXorClause(vec<Lit>& ps, bool xorEqualFalse, const uint32_t group, const char* group_name);
+template bool Solver::addXorClause(XorClause& ps, bool xorEqualFalse, const uint32_t group, const char* group_name);
 
-template<class T>
-bool Solver::addLearntClause(T& ps, const uint group, const uint32_t activity)
-{
-    Clause* c = addClauseInt(ps, group);
-    if (c == NULL) return ok;
-
-    //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);
-    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);
-template bool Solver::addLearntClause(vec<Lit>& ps, const uint group, const uint32_t activity);
+/**
+@brief Adds a clause to the problem. Should ONLY be called internally
 
+This code is very specific in that it must NOT be called with varibles in
+"ps" that have been replaced, eliminated, etc. Also, it must not be called
+when the solver is in an UNSAT (!ok) state, for example. Use it carefully,
+and only internally
+*/
 template <class T>
-Clause* Solver::addClauseInt(T& ps, uint group)
+Clause* Solver::addClauseInt(T& ps, uint32_t group
+                            , const bool learnt, const uint32_t glue, const float miniSatActivity
+                            , const bool inOriginalInput)
 {
     assert(ok);
-    
+
     std::sort(ps.getData(), ps.getDataEnd());
     Lit p = lit_Undef;
     uint32_t i, j;
     for (i = j = 0; i != ps.size(); i++) {
         if (value(ps[i]).getBool() || ps[i] == ~p)
             return NULL;
-        else if (value(ps[i]) != l_False && ps[i] != p)
+        else if (value(ps[i]) != l_False && ps[i] != p) {
             ps[j++] = p = ps[i];
+            assert(!subsumer->getVarElimed()[p.var()]);
+            assert(!xorSubsumer->getVarElimed()[p.var()]);
+        }
     }
     ps.shrink(i - j);
-    
+
     if (ps.size() == 0) {
         ok = false;
         return NULL;
@@ -382,29 +383,35 @@ Clause* Solver::addClauseInt(T& ps, uint group)
         return NULL;
     }
 
-    Clause* c = clauseAllocator.Clause_new(ps, group);
-    attachClause(*c);
-    
-    return c;
+    if (ps.size() > 2) {
+        Clause* c = clauseAllocator.Clause_new(ps, group);
+        if (learnt) c->makeLearnt(glue, miniSatActivity);
+        attachClause(*c);
+        return c;
+    } else {
+        attachBinClause(ps[0], ps[1], learnt);
+        if (!inOriginalInput) dataSync->signalNewBinClause(ps);
+        numNewBin++;
+        return NULL;
+    }
 }
 
-template Clause* Solver::addClauseInt(Clause& ps, const uint group);
-template Clause* Solver::addClauseInt(vec<Lit>& ps, const uint group);
+template Clause* Solver::addClauseInt(Clause& ps, const uint32_t group, const bool learnt, const uint32_t glue, const float miniSatActivity, const bool inOriginalInput);
+template Clause* Solver::addClauseInt(vec<Lit>& ps, const uint32_t group, const bool learnt, const uint32_t glue, const float miniSatActivity, const bool inOriginalInput);
 
-template<class T>
-bool Solver::addClause(T& ps, const uint group, char* group_name)
+template<class T> const bool Solver::addClauseHelper(T& ps, const uint32_t group, const char* group_name)
 {
     assert(decisionLevel() == 0);
     if (ps.size() > (0x01UL << 18)) {
         std::cout << "Too long clause!" << std::endl;
         exit(-1);
     }
-    
+
     if (libraryCNFFile) {
         for (uint32_t i = 0; i != ps.size(); i++) ps[i].print(libraryCNFFile);
         fprintf(libraryCNFFile, "0\n");
     }
-    
+
     #ifdef STATS_NEEDED
     if (dynamic_behaviour_analysis) {
         logger.set_group_name(group, group_name);
@@ -412,9 +419,13 @@ bool Solver::addClause(T& ps, const uint group, char* group_name)
     }
     #endif
 
-    if (!ok)
-        return false;
+    if (!ok) return false;
     assert(qhead == trail.size());
+    #ifndef NDEBUG
+    for (Lit *l = ps.getData(), *end = ps.getDataEnd(); l != end; l++) {
+        assert(l->var() < nVars() && "Clause inserted, but variable inside has not been declared with Solver::newVar() !");
+    }
+    #endif
 
     // Check if clause is satisfied and remove false/duplicate literals:
     if (varReplacer->getNumLastReplacedVars() || subsumer->getNumElimed() || xorSubsumer->getNumElimed()) {
@@ -426,125 +437,215 @@ bool Solver::addClause(T& ps, const uint group, char* group_name)
                 return false;
         }
     }
-    
-    Clause* c = addClauseInt(ps, group);
-    if (c != NULL) {
-        if (c->size() > 2)
-            clauses.push(c);
-        else
-            binaryClauses.push(c);
-    }
+
+    return true;
+}
+
+
+/**
+@brief Adds a clause to the problem. Calls addClauseInt() for heavy-lifting
+
+Does some debug-related stuff (see "libraryCNFFile"), and checks whether the
+variables of the literals in "ps" have been eliminated/replaced etc. If so,
+it acts on them such that they are correct, and calls addClauseInt() to do
+the heavy-lifting
+*/
+template<class T>
+bool Solver::addClause(T& ps, const uint32_t group, const char* group_name)
+{
+    #ifdef VERBOSE_DEBUG
+    std::cout << "addClause() called with new clause: " << ps << std::endl;
+    #endif //VERBOSE_DEBUG
+    if (!addClauseHelper(ps, group, group_name)) return false;
+    Clause* c = addClauseInt(ps, group, false, 0, 0, true);
+    if (c != NULL) clauses.push(c);
+
+    return ok;
+}
+
+template bool Solver::addClause(vec<Lit>& ps, const uint32_t group, const char* group_name);
+template bool Solver::addClause(Clause& ps, const uint32_t group, const char* group_name);
+
+
+template<class T>
+bool Solver::addLearntClause(T& ps, const uint32_t group, const char* group_name, const uint32_t glue, const float miniSatActivity)
+{
+    if (!addClauseHelper(ps, group, group_name)) return false;
+    Clause* c = addClauseInt(ps, group, true, glue, miniSatActivity, true);
+    if (c != NULL) learnts.push(c);
 
     return ok;
 }
 
-template bool Solver::addClause(vec<Lit>& ps, const uint group, char* group_name);
-template bool Solver::addClause(Clause& ps, const uint group, char* group_name);
+template bool Solver::addLearntClause(vec<Lit>& ps, const uint32_t group, const char* group_name, const uint32_t glue, const float miniSatActivity);
+template bool Solver::addLearntClause(Clause& ps, const uint32_t group, const char* group_name, const uint32_t glue, const float miniSatActivity);
+
 
+/**
+@brief Attaches an xor clause to the watchlists
+
+The xor clause must be larger than 2, since a 2-long XOR clause is a varible
+replacement instruction, really.
+*/
 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);
+
+    for (uint32_t i = 0; i < c.size(); i++) {
+        assert(!subsumer->getVarElimed()[c[i].var()]);
+        assert(!xorSubsumer->getVarElimed()[c[i].var()]);
+    }
     #endif //DEBUG_ATTACH
 
-    xorwatches[c[0].var()].push(clauseAllocator.getOffset((Clause*)&c));
-    xorwatches[c[1].var()].push(clauseAllocator.getOffset((Clause*)&c));
+    watches[Lit(c[0].var(), false).toInt()].push(clauseAllocator.getOffset((Clause*)&c));
+    watches[Lit(c[0].var(), true).toInt()].push(clauseAllocator.getOffset((Clause*)&c));
+    watches[Lit(c[1].var(), false).toInt()].push(clauseAllocator.getOffset((Clause*)&c));
+    watches[Lit(c[1].var(), true).toInt()].push(clauseAllocator.getOffset((Clause*)&c));
 
     clauses_literals += c.size();
 }
 
+void Solver::attachBinClause(const Lit lit1, const Lit lit2, const bool learnt)
+{
+    #ifdef DEBUG_ATTACH
+    assert(lit1.var() != lit2.var());
+    assert(assigns[lit1.var()] == l_Undef);
+    assert(value(lit2) == l_Undef || value(lit2) == l_False);
+
+    assert(!subsumer->getVarElimed()[lit1.var()]);
+    assert(!subsumer->getVarElimed()[lit2.var()]);
+
+    assert(!xorSubsumer->getVarElimed()[lit1.var()]);
+    assert(!xorSubsumer->getVarElimed()[lit2.var()]);
+    #endif //DEBUG_ATTACH
+
+    watches[(~lit1).toInt()].push(Watched(lit2, learnt));
+    watches[(~lit2).toInt()].push(Watched(lit1, learnt));
+
+    numBins++;
+    if (learnt) learnts_literals += 2;
+    else clauses_literals += 2;
+}
+
+/**
+@brief Attach normal a clause to the watchlists
+
+Handles 2, 3 and >3 clause sizes differently and specially
+*/
 void Solver::attachClause(Clause& c)
 {
-    assert(c.size() > 1);
-    uint32_t index0 = (~c[0]).toInt();
-    uint32_t index1 = (~c[1]).toInt();
-    
-    if (c.size() == 2) {
-        binwatches[index0].push(WatchedBin(c[1]));
-        binwatches[index1].push(WatchedBin(c[0]));
+    assert(c.size() > 2);
+    #ifdef DEBUG_ATTACH
+    assert(c[0].var() != c[1].var());
+    assert(assigns[c[0].var()] == l_Undef);
+    assert(value(c[1]) == l_Undef || value(c[1]) == l_False);
+
+    for (uint32_t i = 0; i < c.size(); i++) {
+        assert(!subsumer->getVarElimed()[c[i].var()]);
+        assert(!xorSubsumer->getVarElimed()[c[i].var()]);
+    }
+    #endif //DEBUG_ATTACH
+
+    if (c.size() == 3) {
+        watches[(~c[0]).toInt()].push(Watched(c[1], c[2]));
+        watches[(~c[1]).toInt()].push(Watched(c[0], c[2]));
+        watches[(~c[2]).toInt()].push(Watched(c[0], c[1]));
     } else {
         ClauseOffset offset = clauseAllocator.getOffset(&c);
-        watches[index0].push(Watched(offset, c[c.size()/2]));
-        watches[index1].push(Watched(offset, c[c.size()/2]));
+        watches[(~c[0]).toInt()].push(Watched(offset, c[c.size()/2]));
+        watches[(~c[1]).toInt()].push(Watched(offset, c[c.size()/2]));
     }
 
-    if (c.learnt()) learnts_literals += c.size();
-    else            clauses_literals += c.size();
+    if (c.learnt())
+        learnts_literals += c.size();
+    else
+        clauses_literals += c.size();
 }
 
-
+/**
+@brief Calls detachModifiedClause to do the heavy-lifting
+*/
 void Solver::detachClause(const XorClause& c)
 {
-    assert(c.size() > 1);
-    ClauseOffset offset = clauseAllocator.getOffset(&c);
-    assert(find(xorwatches[c[0].var()], offset));
-    assert(find(xorwatches[c[1].var()], offset));
-    remove(xorwatches[c[0].var()], offset);
-    remove(xorwatches[c[1].var()], offset);
-
-    clauses_literals -= c.size();
+    detachModifiedClause(c[0].var(), c[1].var(), c.size(), &c);
 }
 
+/**
+@brief Calls detachModifiedClause to do the heavy-lifting
+*/
 void Solver::detachClause(const Clause& c)
 {
-    assert(c.size() > 1);
-    if (c.size() == 2) {
-        assert(findWatchedBinCl(binwatches[(~c[0]).toInt()], c[1]));
-        assert(findWatchedBinCl(binwatches[(~c[1]).toInt()], c[0]));
-        
-        removeWatchedBinCl(binwatches[(~c[0]).toInt()], c[1]);
-        removeWatchedBinCl(binwatches[(~c[1]).toInt()], c[0]);
-    } else {
-        ClauseOffset offset = clauseAllocator.getOffset(&c);
-        
-        assert(findWatchedCl(watches[(~c[0]).toInt()], offset));
-        assert(findWatchedCl(watches[(~c[1]).toInt()], offset));
-        
-        removeWatchedCl(watches[(~c[0]).toInt()], offset);
-        removeWatchedCl(watches[(~c[1]).toInt()], offset);
-    }
-    
-    if (c.learnt()) learnts_literals -= c.size();
-    else            clauses_literals -= c.size();
+    detachModifiedClause(c[0], c[1], (c.size() == 3) ? c[2] : lit_Undef,  c.size(), &c);
 }
 
-void Solver::detachModifiedClause(const Lit lit1, const Lit lit2, const uint origSize, const Clause* address)
+/**
+@brief Detaches a (potentially) modified clause
+
+The first two literals might have chaned through modification, so they are
+passed along as arguments -- they are needed to find the correct place where
+the clause is
+*/
+void Solver::detachModifiedClause(const Lit lit1, const Lit lit2, const Lit lit3, const uint32_t origSize, const Clause* address)
 {
-    assert(origSize > 1);
-    
-    if (origSize == 2) {
-        assert(findWatchedBinCl(binwatches[(~lit1).toInt()], lit2));
-        assert(findWatchedBinCl(binwatches[(~lit2).toInt()], lit1));
-        removeWatchedBinCl(binwatches[(~lit1).toInt()], lit2);
-        removeWatchedBinCl(binwatches[(~lit2).toInt()], lit1);
+    assert(origSize > 2);
+
+    ClauseOffset offset = clauseAllocator.getOffset(address);
+    if (origSize == 3) {
+        //The clause might have been longer, and has only recently
+        //became 3-long. Check, and detach accordingly
+        if (findWCl(watches[(~lit1).toInt()], offset)) goto fullClause;
+
+        removeWTri(watches[(~lit1).toInt()], lit2, lit3);
+        removeWTri(watches[(~lit2).toInt()], lit1, lit3);
+        removeWTri(watches[(~lit3).toInt()], lit1, lit2);
+
     } else {
-        ClauseOffset offset = clauseAllocator.getOffset(address);
-        assert(findW(watches[(~lit1).toInt()], offset));
-        assert(findW(watches[(~lit2).toInt()], offset));
-        removeW(watches[(~lit1).toInt()], offset);
-        removeW(watches[(~lit2).toInt()], offset);
-    }
-    if (address->learnt()) learnts_literals -= origSize;
-    else            clauses_literals -= origSize;
+        fullClause:
+        removeWCl(watches[(~lit1).toInt()], offset);
+        removeWCl(watches[(~lit2).toInt()], offset);
+
+    }
+
+    if (address->learnt())
+        learnts_literals -= origSize;
+    else
+        clauses_literals -= origSize;
 }
 
-void Solver::detachModifiedClause(const Var var1, const Var var2, const uint origSize, const XorClause* address)
+/**
+@brief Detaches a (potentially) modified xor clause
+
+The first two vars might have chaned through modification, so they are passed
+along as arguments.
+*/
+void Solver::detachModifiedClause(const Var var1, const Var var2, const uint32_t origSize, const XorClause* address)
 {
     assert(origSize > 2);
 
     ClauseOffset offset = clauseAllocator.getOffset(address);
-    assert(find(xorwatches[var1], offset));
-    assert(find(xorwatches[var2], offset));
-    remove(xorwatches[var1], offset);
-    remove(xorwatches[var2], offset);
-    
+    assert(findWXCl(watches[Lit(var1, false).toInt()], offset));
+    assert(findWXCl(watches[Lit(var1, true).toInt()], offset));
+    assert(findWXCl(watches[Lit(var2, false).toInt()], offset));
+    assert(findWXCl(watches[Lit(var2, true).toInt()], offset));
+
+    removeWXCl(watches[Lit(var1, false).toInt()], offset);
+    removeWXCl(watches[Lit(var1, true).toInt()], offset);
+    removeWXCl(watches[Lit(var2, false).toInt()], offset);
+    removeWXCl(watches[Lit(var2, true).toInt()], offset);
+
+    assert(!address->learnt());
     clauses_literals -= origSize;
 }
 
-// Revert to the state at given level (keeping all assignment at 'level' but not beyond).
-//
+/**
+@brief Revert to the state at given level
+
+Also reverts all stuff in Gass-elimination, as well as resetting the old
+default polarities if USE_OLD_POLARITIES is set (which is by default NOT set).
+*/
 void Solver::cancelUntil(int level)
 {
     #ifdef VERBOSE_DEBUG
@@ -552,14 +653,14 @@ void Solver::cancelUntil(int level)
     if (level > 0) cout << " sublevel: " << trail_lim[level];
     cout << endl;
     #endif
-    
+
     if ((int)decisionLevel() > level) {
-        
+
         #ifdef USE_GAUSS
         for (vector<Gaussian*>::iterator gauss = gauss_matrixes.begin(), end= gauss_matrixes.end(); gauss != end; gauss++)
             (*gauss)->canceling(trail_lim[level]);
         #endif //USE_GAUSS
-        
+
         for (int sublevel = trail.size()-1; sublevel >= (int)trail_lim[level]; sublevel--) {
             Var var = trail[sublevel].var();
             #ifdef VERBOSE_DEBUG
@@ -570,6 +671,21 @@ void Solver::cancelUntil(int level)
             #endif //USE_OLD_POLARITIES
             assigns[var] = l_Undef;
             insertVarOrder(var);
+            if (unWindGlue[var] != NULL) {
+                #ifdef UNWINDING_DEBUG
+                std::cout << "unwind, var:" << var
+                << " sublevel:" << sublevel
+                << " coming from:" << (trail.size()-1)
+                << " going until:" << (int)trail_lim[level]
+                << std::endl;
+                unWindGlue[var]->plainPrint();
+                #endif //UNWINDING_DEBUG
+
+                Clause*& clauseToFree = unWindGlue[var];
+                detachClause(*clauseToFree);
+                clauseAllocator.clauseFree(clauseToFree);
+                clauseToFree = NULL;
+            }
         }
         qhead = trail_lim[level];
         trail.shrink_(trail.size() - trail_lim[level]);
@@ -581,29 +697,46 @@ void Solver::cancelUntil(int level)
     #endif
 }
 
-void Solver::printLit(const Lit l) const
+void Solver::cancelUntilLight()
 {
-    printf("%s%d:%c", l.sign() ? "-" : "", l.var()+1, value(l) == l_True ? '1' : (value(l) == l_False ? '0' : 'X'));
-}
+    assert((int)decisionLevel() > 0);
 
-void Solver::needLibraryCNFFile(const char* fileName)
-{
-    libraryCNFFile = fopen(fileName, "w");
-    assert(libraryCNFFile != NULL);
+    for (int sublevel = trail.size()-1; sublevel >= (int)trail_lim[0]; sublevel--) {
+        Var var = trail[sublevel].var();
+        assigns[var] = l_Undef;
+    }
+    qhead = trail_lim[0];
+    trail.shrink_(trail.size() - trail_lim[0]);
+    trail_lim.shrink_(trail_lim.size());
 }
 
-#ifdef USE_GAUSS
-void Solver::clearGaussMatrixes()
+const bool Solver::clearGaussMatrixes()
 {
-    for (uint i = 0; i < gauss_matrixes.size(); i++)
+    assert(decisionLevel() == 0);
+    #ifdef USE_GAUSS
+    bool ret = gauss_matrixes.size() > 0;
+    for (uint32_t i = 0; i < gauss_matrixes.size(); i++)
         delete gauss_matrixes[i];
     gauss_matrixes.clear();
+
+    for (uint32_t i = 0; i != freeLater.size(); i++)
+        clauseAllocator.clauseFree(freeLater[i]);
+    freeLater.clear();
+
+    return ret;
+    #endif //USE_GAUSS
+    return false;
 }
-#endif //USE_GAUSS
 
+/**
+@brief Returns what polarity[] should be set as default based on polarity_mode
+
+since polarity is filled with Lit::sign() , "true" here means an inverted
+signed-ness, i.e. a FALSE default value. And vice-versa
+*/
 inline bool Solver::defaultPolarity()
 {
-    switch(polarity_mode) {
+    switch(conf.polarity_mode) {
         case polarity_false:
             return true;
         case polarity_true:
@@ -615,62 +748,100 @@ inline bool Solver::defaultPolarity()
         default:
             assert(false);
     }
-    
+
     return true;
 }
 
-void Solver::tallyVotes(const vec<Clause*>& cs, vector<double>& votes) const
+/**
+@brief Tally votes for a default TRUE or FALSE value for the variable using the Jeroslow-Wang method
+
+@p votes[inout] Votes are tallied at this place for each variable
+@p cs The clause to tally votes for
+*/
+void Solver::tallyVotes(const vec<Clause*>& cs, vec<double>& 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));
-        
-        for (const Lit *it2 = &c[0], *end2 = it2 + c.size(); it2 != end2; it2++) {
+
+        for (const Lit *it2 = c.getData(), *end2 = c.getDataEnd(); it2 != end2; it2++) {
             if (it2->sign()) votes[it2->var()] += divider;
             else votes[it2->var()] -= divider;
         }
     }
 }
 
-void Solver::tallyVotes(const vec<XorClause*>& cs, vector<double>& votes) const
+void Solver::tallyVotesBin(vec<double>& votes) const
+{
+    uint32_t wsLit = 0;
+    for (const vec<Watched> *it = watches.getData(), *end = watches.getDataEnd(); it != end; it++, wsLit++) {
+        Lit lit = ~Lit::toLit(wsLit);
+        const vec<Watched>& ws = *it;
+        for (const Watched *it2 = ws.getData(), *end2 = ws.getDataEnd(); it2 != end2; it2++) {
+            if (it2->isBinary() && lit.toInt() < it2->getOtherLit().toInt()) {
+                if (!it2->getLearnt()) {
+                    if (lit.sign()) votes[lit.var()] += 0.5;
+                    else votes[lit.var()] -= 0.5;
+
+                    Lit lit2 = it2->getOtherLit();
+                    if (lit2.sign()) votes[lit2.var()] += 0.5;
+                    else votes[lit2.var()] -= 0.5;
+                }
+            }
+        }
+    }
+}
+
+/**
+@brief Tally votes a default TRUE or FALSE value for the variable using the Jeroslow-Wang method
+
+For XOR clause, we simply add some weight for a FALSE default, i.e. being in
+xor clauses makes the variabe more likely to be FALSE by default
+*/
+void Solver::tallyVotes(const vec<XorClause*>& cs, vec<double>& 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++)
+
+        for (const Lit *it2 = c.getData(), *end2 = c.getDataEnd(); it2 != end2; it2++) {
             votes[it2->var()] += divider;
+        }
     }
 }
 
+/**
+@brief Tallies votes for a TRUE/FALSE default polarity using Jeroslow-Wang
+
+Voting is only used if polarity_mode is "polarity_auto". This is the default.
+Uses the tallyVotes() functions to tally the votes
+*/
 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<double> votes;
-        votes.resize(nVars(), 0.0);
-        
+    if (conf.polarity_mode == polarity_auto) {
+        double myTime = cpuTime();
+
+        vec<double> votes(nVars(), 0.0);
+
         tallyVotes(clauses, votes);
-        tallyVotes(binaryClauses, votes);
-        tallyVotes(varReplacer->getClauses(), votes);
+        tallyVotesBin(votes);
         tallyVotes(xorclauses, votes);
-        
+
         Var i = 0;
         uint32_t posPolars = 0;
         uint32_t undecidedPolars = 0;
-        for (vector<double>::const_iterator it = votes.begin(), end = votes.end(); it != end; it++, i++) {
+        for (const double *it = votes.getData(), *end = votes.getDataEnd(); it != end; it++, i++) {
             polarity[i] = (*it >= 0.0);
             posPolars += (*it < 0.0);
             undecidedPolars += (*it == 0.0);
@@ -678,67 +849,176 @@ void Solver::calculateDefaultPolarities()
             std::cout << !defaultPolarities[i] << ", ";
             #endif //VERBOSE_DEBUG_POLARITIES
         }
-        
-        if (verbosity >= 2) {
-            std::cout << "c |  Calc default polars - "
-            << " time: " << std::fixed << std::setw(6) << std::setprecision(2) << cpuTime()-time << " s"
+
+        if (conf.verbosity >= 2) {
+            std::cout << "c Calc default polars - "
+            << " time: " << std::fixed << std::setw(6) << std::setprecision(2) << (cpuTime() - myTime) << " s"
             << " pos: " << std::setw(7) << posPolars
             << " undec: " << std::setw(7) << undecidedPolars
             << " neg: " << std::setw(7) << nVars()-  undecidedPolars - posPolars
-            << std::setw(8) << "    |" << std:: endl;
+            << std:: endl;
         }
     } else {
-        std::fill(polarity.begin(), polarity.end(), defaultPolarity());
+        for (uint32_t i = 0; i < polarity.size(); i++) {
+            polarity[i] = defaultPolarity();
+        }
     }
-    
+
     #ifdef VERBOSE_DEBUG_POLARITIES
     std::cout << std::endl;
     #endif //VERBOSE_DEBUG_POLARITIES
 }
 
+void Solver::calcReachability()
+{
+    double myTime = cpuTime();
+
+    for (uint32_t i = 0; i < nVars()*2; i++) {
+        litReachable[i] = LitReachData();
+    }
+
+    for (uint32_t i = 0; i < order_heap.size(); i++) for (uint32_t sig1 = 0; sig1 < 2; sig1++)  {
+        Lit lit = Lit(order_heap[i], sig1);
+        if (value(lit.var()) != l_Undef
+            || subsumer->getVarElimed()[lit.var()]
+            || xorSubsumer->getVarElimed()[lit.var()]
+            || partHandler->getSavedState()[lit.var()] != l_Undef
+            || !decision_var[lit.var()])
+            continue;
+
+        vector<Lit>& cache = transOTFCache[(~lit).toInt()].lits;
+        uint32_t cacheSize = cache.size();
+        for (vector<Lit>::const_iterator it = cache.begin(), end = cache.end(); it != end; it++) {
+            /*if (solver.value(it->var()) != l_Undef
+            || solver.subsumer->getVarElimed()[it->var()]
+            || solver.xorSubsumer->getVarElimed()[it->var()])
+            continue;*/
+            if ((*it == lit) || (*it == ~lit)) continue;
+            if (litReachable[it->toInt()].lit == lit_Undef || litReachable[it->toInt()].numInCache < cacheSize) {
+                litReachable[it->toInt()].lit = lit;
+                litReachable[it->toInt()].numInCache = cacheSize;
+            }
+        }
+    }
+
+    /*for (uint32_t i = 0; i < nVars()*2; i++) {
+        std::sort(litReachable[i].begin(), litReachable[i].end(), MySorterX(transOTFCache));
+    }*/
+
+    /*for (uint32_t i = 0; i < nVars()*2; i++) {
+        vector<Lit>& myset = litReachable[i];
+        for (uint32_t i2 = 0; i2 < myset.size(); i2++) {
+            std::cout << transOTFCache[myset[i2].toInt()].lits.size() << " , ";
+        }
+        std::cout << std::endl;
+    }*/
+
+    if (conf.verbosity >= 1) {
+        std::cout << "c calculated reachability. Time: " << (cpuTime() - myTime) << std::endl;
+    }
+}
+
+void Solver::saveOTFData()
+{
+    assert(decisionLevel() == 1);
+
+    Lit lev0Lit = trail[trail_lim[0]];
+    Solver::TransCache& oTFCache = transOTFCache[(~lev0Lit).toInt()];
+    oTFCache.conflictLastUpdated = conflicts;
+    oTFCache.lits.clear();
+
+    for (int sublevel = trail.size()-1; sublevel > (int)trail_lim[0]; sublevel--) {
+        Lit lit = trail[sublevel];
+        oTFCache.lits.push_back(lit);
+    }
+}
+
 //=================================================================================================
 // Major methods:
 
 
+/**
+@brief Picks a branching variable and its value (True/False)
+
+We do three things here:
+-# Try to do random decision (rare, less than 2%)
+-# Try acitivity-based decision
+
+Then, we pick a sign (True/False):
+\li If we are in search-burst mode ("simplifying" is set), we pick a sign
+totally randomly
+\li If RANDOM_LOOKAROUND_SEARCHSPACE is set, we take the previously saved
+polarity, and with some chance, flip it
+\li Otherwise, we simply take the saved polarity
+*/
 Lit Solver::pickBranchLit()
 {
     #ifdef VERBOSE_DEBUG
     cout << "decision level: " << decisionLevel() << " ";
     #endif
-    
+
     Var next = var_Undef;
 
-    
-    bool random = mtrand.randDblExc() < random_var_freq;
-    
+    bool random = mtrand.randDblExc() < conf.random_var_freq;
+
     // Random decision:
     if (random && !order_heap.empty()) {
-        if (restrictedPickBranch == 0) next = order_heap[mtrand.randInt(order_heap.size()-1)];
-        else next = order_heap[mtrand.randInt(std::min((uint32_t)order_heap.size()-1, restrictedPickBranch))];
+        if (conf.restrictPickBranch == 0)
+            next = order_heap[mtrand.randInt(order_heap.size()-1)];
+        else
+            next = order_heap[mtrand.randInt(std::min((uint32_t)order_heap.size()-1, conf.restrictPickBranch))];
 
         if (assigns[next] == l_Undef && decision_var[next])
             rnd_decisions++;
     }
 
+    bool signSet = false;
+    bool signSetTo = false;
     // Activity based decision:
-    while (next == var_Undef || assigns[next] != l_Undef || !decision_var[next])
+    while (next == var_Undef
+      || assigns[next] != l_Undef
+      || !decision_var[next]) {
         if (order_heap.empty()) {
             next = var_Undef;
             break;
-        } else {
-            next = order_heap.removeMin();
         }
 
+        next = order_heap.removeMin();
+        if (!simplifying && value(next) == l_Undef && decision_var[next]) {
+            signSet = true;
+            if (avgBranchDepth.isvalid())
+                signSetTo = polarity[next] ^ (mtrand.randInt(avgBranchDepth.getAvgUInt() * ((lastSelectedRestartType == static_restart) ? 2 : 1) ) == 1);
+            else
+                signSetTo = polarity[next];
+            Lit nextLit = Lit(next, signSetTo);
+            Lit lit2 = litReachable[nextLit.toInt()].lit;
+            if (lit2 != lit_Undef && value(lit2.var()) == l_Undef && decision_var[lit2.var()] && mtrand.randInt(1) == 1) {
+                insertVarOrder(next);
+                next = litReachable[nextLit.toInt()].lit.var();
+                signSetTo = litReachable[nextLit.toInt()].lit.sign();
+            }
+        }
+    }
+
+    //if "simplifying" is set, i.e. if we are in a burst-search mode, then
+    //randomly pick a sign. Otherwise, if RANDOM_LOOKAROUND_SEARCHSPACE is
+    //defined, we check the default polarity, and we may change it a bit
+    //randomly based on the average branch depth. Otherwise, we just go for the
+    //polarity that has been saved
     bool sign;
-    if (next != var_Undef) {
-        if (simplifying && random)
-            sign = mtrand.randInt(1);
-        #ifdef RANDOM_LOOKAROUND_SEARCHSPACE
-        else if (avgBranchDepth.isvalid())
-            sign = polarity[next] ^ (mtrand.randInt(avgBranchDepth.getavg() * ((lastSelectedRestartType == static_restart) ? 2 : 1) ) == 1);
-        #endif
-        else
-            sign = polarity[next];
+    if (next != var_Undef)  {
+        if (signSet) {
+            sign = signSetTo;
+        } else {
+            if (simplifying && random)
+                sign = mtrand.randInt(1);
+            #ifdef RANDOM_LOOKAROUND_SEARCHSPACE
+            else if (avgBranchDepth.isvalid())
+                sign = polarity[next] ^ (mtrand.randInt(avgBranchDepth.getAvgUInt() * ((lastSelectedRestartType == static_restart) ? 2 : 1) ) == 1);
+            #endif
+            else
+                sign = polarity[next];
+        }
     }
 
     assert(next == var_Undef || value(next) == l_Undef);
@@ -758,43 +1038,46 @@ Lit Solver::pickBranchLit()
     }
 }
 
-// Assumes 'seen' is cleared (will leave it cleared)
+/**
+@brief Checks subsumption. Used in on-the-fly subsumption code
+
+Assumes 'seen' is cleared (will leave it cleared)
+*/
 template<class T1, class T2>
 bool subset(const T1& A, const T2& B, vector<bool>& seen)
 {
-    for (uint i = 0; i != B.size(); i++)
+    for (uint32_t i = 0; i != B.size(); i++)
         seen[B[i].toInt()] = 1;
-    for (uint i = 0; i != A.size(); i++) {
+    for (uint32_t i = 0; i != A.size(); i++) {
         if (!seen[A[i].toInt()]) {
-            for (uint i = 0; i != B.size(); i++)
+            for (uint32_t i = 0; i != B.size(); i++)
                 seen[B[i].toInt()] = 0;
             return false;
         }
     }
-    for (uint i = 0; i != B.size(); i++)
+    for (uint32_t i = 0; i != B.size(); i++)
         seen[B[i].toInt()] = 0;
     return true;
 }
 
 
-/*_________________________________________________________________________________________________
-|
-|  analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&)  ->  [void]
-|
-|  Description:
-|    Analyze conflict and produce a reason clause.
-|
-|    Pre-conditions:
-|      * 'out_learnt' is assumed to be cleared.
-|      * Current decision level must be greater than root level.
-|
-|    Post-conditions:
-|      * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'.
-|
-|  Effect:
-|    Will undo part of the trail, upto but not beyond the assumption of the current decision level.
-|________________________________________________________________________________________________@*/
-Clause* Solver::analyze(PropagatedFrom confl, vec<Lit>& out_learnt, int& out_btlevel, uint32_t &nbLevels, const bool update)
+/**
+@brief    Analyze conflict and produce a reason clause.
+
+Pre-conditions:
+\li  'out_learnt' is assumed to be cleared.
+\li Current decision level must be greater than root level.
+
+Post-conditions:
+\li 'out_learnt[0]' is the asserting literal at level 'out_btlevel'.
+
+Effect: Will undo part of the trail, upto but not beyond the assumption of the
+current decision level.
+
+@return NULL if the conflict doesn't on-the-fly subsume the last clause, and
+the pointer of the clause if it does
+*/
+Clause* Solver::analyze(PropBy conflHalf, vec<Lit>& out_learnt, int& out_btlevel, uint32_t &glue, const bool update)
 {
     int pathC = 0;
     Lit p     = lit_Undef;
@@ -805,32 +1088,32 @@ Clause* Solver::analyze(PropagatedFrom confl, vec<Lit>& out_learnt, int& out_btl
     int index   = trail.size() - 1;
     out_btlevel = 0;
 
-    PropagatedFrom oldConfl;
+    PropByFull confl(conflHalf, failBinLit, clauseAllocator);
+    PropByFull oldConfl;
 
     do {
         assert(!confl.isNULL());          // (otherwise should be UIP)
-        
-        if (update && restartType == static_restart && !confl.isBinary() && confl.getClause()->learnt())
+
+        if (update && restartType == static_restart && confl.isClause() && confl.getClause()->learnt())
             claBumpActivity(*confl.getClause());
 
-        for (uint j = (p == lit_Undef) ? 0 : 1, size = confl.size(); j != size; j++) {
-            Lit q;
-            if (j == 0 && confl.isBinary()) q = failBinLit;
-            else q = confl[j];
+        for (uint32_t j = (p == lit_Undef) ? 0 : 1, size = confl.size(); j != size; j++) {
+            Lit q = confl[j];
             const Var my_var = q.var();
 
             if (!seen[my_var] && level[my_var] > 0) {
                 varBumpActivity(my_var);
                 seen[my_var] = 1;
+                assert(level[my_var] <= (int)decisionLevel());
                 if (level[my_var] >= (int)decisionLevel()) {
                     pathC++;
-                    #ifdef UPDATEVARACTIVITY
+                    #ifdef UPDATE_VAR_ACTIVITY_BASED_ON_GLUE
                     if (lastSelectedRestartType == dynamic_restart
-                        && !reason[q.var()].isBinary()
+                        && reason[q.var()].isClause()
                         && !reason[q.var()].isNULL()
-                        && reason[q.var()].getClause()->learnt())
+                        && clauseAllocator.getPointer(reason[q.var()].getClause())->learnt())
                         lastDecisionLevel.push(q.var());
-                    #endif
+                    #endif //#define UPDATEVARACTIVITY
                 } else {
                     out_learnt.push(q);
                     if (level[my_var] > out_btlevel)
@@ -843,18 +1126,19 @@ Clause* Solver::analyze(PropagatedFrom confl, vec<Lit>& out_learnt, int& out_btl
         while (!seen[trail[index--].var()]);
         p     = trail[index+1];
         oldConfl = confl;
-        confl = reason[p.var()];
-        if (!confl.isBinary()) __builtin_prefetch(confl.getClause(), 1, 0);
+        confl = PropByFull(reason[p.var()], failBinLit, clauseAllocator);
+        if (confl.isClause()) __builtin_prefetch(confl.getClause(), 1, 0);
         seen[p.var()] = 0;
         pathC--;
 
     } while (pathC > 0);
+    assert(pathC == 0);
     out_learnt[0] = ~p;
 
     // Simplify conflict clause:
     //
     uint32_t i, j;
-    if (expensive_ccmin) {
+    if (conf.expensive_ccmin) {
         uint32_t abstract_level = 0;
         for (i = 1; i < out_learnt.size(); i++)
             abstract_level |= abstractLevel(out_learnt[i].var()); // (maintain an abstraction of levels involved in conflict)
@@ -866,9 +1150,9 @@ Clause* Solver::analyze(PropagatedFrom confl, vec<Lit>& out_learnt, int& out_btl
     } else {
         out_learnt.copyTo(analyze_toclear);
         for (i = j = 1; i < out_learnt.size(); i++) {
-            PropagatedFrom c(reason[out_learnt[i].var()]);
+            PropByFull c(reason[out_learnt[i].var()], failBinLit, clauseAllocator);
 
-            for (uint k = 1, size = c.size(); k < size; k++) {
+            for (uint32_t k = 1, size = c.size(); k < size; k++) {
                 if (!seen[c[k].var()] && level[c[k].var()] > 0) {
                     out_learnt[j++] = out_learnt[i];
                     break;
@@ -878,6 +1162,11 @@ Clause* Solver::analyze(PropagatedFrom confl, vec<Lit>& out_learnt, int& out_btl
     }
     max_literals += out_learnt.size();
     out_learnt.shrink(i - j);
+    for (uint32_t j = 0; j != analyze_toclear.size(); j++)
+        seen[analyze_toclear[j].var()] = 0;    // ('seen[]' is now cleared)
+
+    if (conf.doMinimLearntMore && out_learnt.size() > 1) minimiseLeartFurther(out_learnt, calcNBLevels(out_learnt));
+    glue = calcNBLevels(out_learnt);
     tot_literals += out_learnt.size();
 
     // Find correct backtrack level:
@@ -889,60 +1178,187 @@ Clause* Solver::analyze(PropagatedFrom confl, vec<Lit>& out_learnt, int& out_btl
         for (uint32_t i = 2; i < out_learnt.size(); i++)
             if (level[out_learnt[i].var()] > level[out_learnt[max_i].var()])
                 max_i = i;
-        Lit p             = out_learnt[max_i];
-        out_learnt[max_i] = out_learnt[1];
-        out_learnt[1]     = p;
-        out_btlevel       = level[p.var()];
+        std::swap(out_learnt[max_i], out_learnt[1]);
+        out_btlevel = level[out_learnt[1].var()];
     }
 
     if (lastSelectedRestartType == dynamic_restart) {
-        nbLevels = calcNBLevels(out_learnt);
-        #ifdef UPDATEVARACTIVITY
+        #ifdef UPDATE_VAR_ACTIVITY_BASED_ON_GLUE
         for(uint32_t i = 0; i != lastDecisionLevel.size(); i++) {
-            PropagatedFrom cl = reason[lastDecisionLevel[i]];
-            if (!cl.isBinary() && cl.getClause()->activity() < nbLevels)
+            PropBy cl = reason[lastDecisionLevel[i]];
+            if (cl.isClause() && clauseAllocator.getPointer(cl.getClause())->getGlue() < glue)
                 varBumpActivity(lastDecisionLevel[i]);
         }
         lastDecisionLevel.clear();
         #endif
-    } else {
-        nbLevels = 1000;
     }
 
-    for (uint32_t j = 0; j != analyze_toclear.size(); j++)
-        seen[analyze_toclear[j].var()] = 0;    // ('seen[]' is now cleared)
-    
-    if (out_learnt.size() == 1) return NULL;
-    
-    if (!oldConfl.isBinary() && !oldConfl.getClause()->isXor()
-        && out_learnt.size() < oldConfl.getClause()->size()) {
-        if (!subset(out_learnt, *oldConfl.getClause(), seen))
-            return NULL;
-        improvedClauseNo++;
-        improvedClauseSize += oldConfl.getClause()->size() - out_learnt.size();
-        return oldConfl.getClause();
+    //We can only on-the-fly subsume clauses that are not 2- or 3-long
+    //furthermore, we cannot subsume a clause that is marked for deletion
+    //due to its high glue value
+    if (out_learnt.size() == 1
+        || !oldConfl.isClause()
+        || oldConfl.getClause()->isXor()
+        || (conf.doMaxGlueDel && oldConfl.getClause()->getGlue() > conf.maxGlue)
+        || out_learnt.size() >= oldConfl.getClause()->size()) return NULL;
+
+    if (!subset(out_learnt, *oldConfl.getClause(), seen)) return NULL;
+
+    improvedClauseNo++;
+    improvedClauseSize += oldConfl.getClause()->size() - out_learnt.size();
+    return oldConfl.getClause();
+}
+
+/**
+@brief Performs on-the-fly self-subsuming resolution
+
+Only uses binary and tertiary clauses already in the watchlists in native
+form to carry out the forward-self-subsuming resolution
+*/
+void Solver::minimiseLeartFurther(vec<Lit>& cl, const uint32_t glue)
+{
+    //80 million is kind of a hack. It seems that the longer the solving
+    //the slower this operation gets. So, limiting the "time" with total
+    //number of conflict literals is maybe a good way of doing this
+    bool clDoMinLRec = false;
+    if (conf.doCacheOTFSSR && conf.doMinimLMoreRecur) {
+        switch(lastSelectedRestartType) {
+            case dynamic_restart :
+                clDoMinLRec |= glue < 0.6*glueHistory.getAvgAllDouble();
+                //NOTE: No "break;" here on purpose
+            case static_restart :
+                clDoMinLRec |= cl.size() < 0.6*conflSizeHist.getAvgDouble();
+                break;
+            default :
+                assert(false);
+        }
     }
-    
-    return NULL;
-}
 
+    if (clDoMinLRec) moreRecurMinLDo++;
+    uint64_t thisUpdateTransOTFSSCache = UPDATE_TRANSOTFSSR_CACHE;
+    if (tot_literals > 80000000) thisUpdateTransOTFSSCache *= 2;
 
-// Check if 'p' can be removed. 'abstract_levels' is used to abort early if the algorithm is
-// visiting literals at levels that cannot be removed later.
-bool Solver::litRedundant(Lit p, uint32_t abstract_levels)
-{
-    analyze_stack.clear();
-    analyze_stack.push(p);
-    int top = analyze_toclear.size();
-    while (analyze_stack.size() > 0) {
-        assert(!reason[analyze_stack.last().var()].isNULL());
-        PropagatedFrom c(reason[analyze_stack.last().var()]);
-        
-        analyze_stack.pop();
+    //To count the "amount of time" invested in doing transitive on-the-fly
+    //self-subsuming resolution
+    uint32_t moreRecurProp = 0;
 
-        for (uint i = 1, size = c.size(); i < size; i++) {
-            Lit p  = c[i];
-            if (!seen[p.var()] && level[p.var()] > 0) {
+    for (uint32_t i = 0; i < cl.size(); i++) seen[cl[i].toInt()] = 1;
+    for (Lit *l = cl.getData(), *end = cl.getDataEnd(); l != end; l++) {
+        if (seen[l->toInt()] == 0) continue;
+        Lit lit = *l;
+
+        if (clDoMinLRec) {
+            if (moreRecurProp > 450
+                || (transOTFCache[l->toInt()].conflictLastUpdated != std::numeric_limits<uint64_t>::max()
+                && (transOTFCache[l->toInt()].conflictLastUpdated + thisUpdateTransOTFSSCache >= conflicts))) {
+                for (vector<Lit>::const_iterator it = transOTFCache[l->toInt()].lits.begin(), end2 = transOTFCache[l->toInt()].lits.end(); it != end2; it++) {
+                    seen[(~(*it)).toInt()] = 0;
+                }
+            } else {
+                updateTransCache++;
+                transMinimAndUpdateCache(lit, moreRecurProp);
+            }
+        }
+
+        //watched is messed: lit is in watched[~lit]
+        vec<Watched>& ws = watches[(~lit).toInt()];
+        for (Watched* i = ws.getData(), *end = ws.getDataEnd(); i != end; i++) {
+            if (i->isBinary()) {
+                seen[(~i->getOtherLit()).toInt()] = 0;
+                continue;
+            }
+
+            if (i->isTriClause()) {
+                if (seen[(~i->getOtherLit()).toInt()] && seen[i->getOtherLit2().toInt()]) {
+                    seen[(~i->getOtherLit()).toInt()] = 0;
+                }
+                if (seen[(~i->getOtherLit2()).toInt()] && seen[i->getOtherLit().toInt()]) {
+                    seen[(~i->getOtherLit2()).toInt()] = 0;
+                }
+                continue;
+            }
+
+            //watches are mostly sorted, so it's more-or-less OK to break
+            //  if non-bi or non-tri is encountered
+            break;
+        }
+    }
+
+    uint32_t removedLits = 0;
+    Lit *i = cl.getData();
+    Lit *j= i;
+    //never remove the 0th literal
+    seen[cl[0].toInt()] = 1;
+    for (Lit* end = cl.getDataEnd(); i != end; i++) {
+        if (seen[i->toInt()]) *j++ = *i;
+        else removedLits++;
+        seen[i->toInt()] = 0;
+    }
+    numShrinkedClause += (removedLits > 0);
+    numShrinkedClauseLits += removedLits;
+    cl.shrink_(i-j);
+
+    #ifdef VERBOSE_DEBUG
+    std::cout << "c Removed further " << removedLits << " lits" << std::endl;
+    #endif
+}
+
+void Solver::transMinimAndUpdateCache(const Lit lit, uint32_t& moreRecurProp)
+{
+    vector<Lit>& allAddedToSeen2 = transOTFCache[lit.toInt()].lits;
+    allAddedToSeen2.clear();
+
+    toRecursiveProp.push(lit);
+    while(!toRecursiveProp.empty()) {
+        Lit thisLit = toRecursiveProp.top();
+        toRecursiveProp.pop();
+        //watched is messed: lit is in watched[~lit]
+        vec<Watched>& ws = watches[(~thisLit).toInt()];
+        moreRecurProp += ws.size() +10;
+        for (Watched* i = ws.getData(), *end = ws.getDataEnd(); i != end; i++) {
+            if (i->isBinary()) {
+                moreRecurProp += 5;
+                Lit otherLit = i->getOtherLit();
+                //don't do indefinite recursion, and don't remove "a" when doing self-subsuming-resolution with 'a OR b'
+                if (seen2[otherLit.toInt()] != 0 || otherLit == ~lit) break;
+                seen2[otherLit.toInt()] = 1;
+                allAddedToSeen2.push_back(otherLit);
+                toRecursiveProp.push(~otherLit);
+            } else {
+                break;
+            }
+        }
+    }
+    assert(toRecursiveProp.empty());
+
+    for (vector<Lit>::const_iterator it = allAddedToSeen2.begin(), end = allAddedToSeen2.end(); it != end; it++) {
+        seen[(~(*it)).toInt()] = 0;
+        seen2[it->toInt()] = 0;
+    }
+
+    transOTFCache[lit.toInt()].conflictLastUpdated = conflicts;
+}
+
+/**
+@brief Check if 'p' can be removed from a learnt clause
+
+'abstract_levels' is used to abort early if the algorithm is
+visiting literals at levels that cannot be removed later.
+*/
+bool Solver::litRedundant(Lit p, uint32_t abstract_levels)
+{
+    analyze_stack.clear();
+    analyze_stack.push(p);
+    int top = analyze_toclear.size();
+    while (analyze_stack.size() > 0) {
+        assert(!reason[analyze_stack.last().var()].isNULL());
+        PropByFull c(reason[analyze_stack.last().var()], failBinLit, clauseAllocator);
+
+        analyze_stack.pop();
+
+        for (uint32_t i = 1, size = c.size(); i < size; i++) {
+            Lit p  = c[i];
+            if (!seen[p.var()] && level[p.var()] > 0) {
                 if (!reason[p.var()].isNULL() && (abstractLevel(p.var()) & abstract_levels) != 0) {
                     seen[p.var()] = 1;
                     analyze_stack.push(p);
@@ -987,8 +1403,8 @@ void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict)
                 assert(level[x] > 0);
                 out_conflict.push(~trail[i]);
             } else {
-                PropagatedFrom c = reason[x];
-                for (uint j = 1, size = c.size(); j < size; j++)
+                PropByFull c(reason[x], failBinLit, clauseAllocator);
+                for (uint32_t j = 1, size = c.size(); j < size; j++)
                     if (level[c[j].var()] > 0)
                         seen[c[j].var()] = 1;
             }
@@ -1000,18 +1416,36 @@ void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict)
 }
 
 
-void Solver::uncheckedEnqueue(const Lit p, const PropagatedFrom& from)
-{
+/**
+@brief Enqueues&sets a new fact that has been found
+
+Call this when a fact has been found. Sets the value, enqueues it for
+propagation, sets its level, sets why it was propagated, saves the polarity,
+and does some logging if logging is enabled. May also save the "old" polarity
+(i.e. polarity that was in polarities[] at p.var()] of the variable if
+USE_OLD_POLARITIES is set
 
+@p p the fact to enqueue
+@p from Why was it propagated (binary clause, tertiary clause, normal clause)
+*/
+void Solver::uncheckedEnqueue(const Lit p, const PropBy& from)
+{
     #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;
+    std::cout << "uncheckedEnqueue var " << p.var()+1
+    << " to val " << !p.sign()
+    << " level: " << decisionLevel()
+    << " sublevel: " << trail.size()
+    << " by: " << from << std::endl;
+    if (from.isClause() && !from.isNULL()) {
+        std::cout << "by clause: " << *clauseAllocator.getPointer(from.getClause()) << 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
@@ -1022,7 +1456,7 @@ void Solver::uncheckedEnqueue(const Lit p, const PropagatedFrom& from)
     #endif //USE_OLD_POLARITIES
     polarity[p.var()] = p.sign();
     trail.push(p);
-    
+
     #ifdef STATS_NEEDED
     if (dynamic_behaviour_analysis)
         logger.propagation(p, from);
@@ -1040,118 +1474,271 @@ void Solver::uncheckedEnqueue(const Lit p, const PropagatedFrom& from)
 |    Post-conditions:
 |      * the propagation queue is empty, even if there was a conflict.
 |________________________________________________________________________________________________@*/
-PropagatedFrom Solver::propagate(const bool update)
+/**
+@brief Propagates a binary clause
+
+Need to be somewhat tricky if the clause indicates that current assignement
+is incorrect (i.e. both literals evaluate to FALSE). If conflict if found,
+sets failBinLit
+*/
+inline const bool Solver::propBinaryClause(Watched* &i, Watched* &j, Watched *end, const Lit p, PropBy& confl)
+{
+    *j++ = *i;
+    lbool val = value(i->getOtherLit());
+    if (val.isUndef()) {
+        uncheckedEnqueue(i->getOtherLit(), PropBy(p));
+    } else if (val == l_False) {
+        confl = PropBy(p);
+        failBinLit = i->getOtherLit();
+        qhead = trail.size();
+        return false;
+    }
+
+    return true;
+}
+
+/**
+@brief Propagates a tertiary (3-long) clause
+
+Need to be somewhat tricky if the clause indicates that current assignement
+is incorrect (i.e. all 3 literals evaluate to FALSE). If conflict is found,
+sets failBinLit
+*/
+inline const bool Solver::propTriClause(Watched* &i, Watched* &j, Watched *end, const Lit p, PropBy& confl)
+{
+    *j++ = *i;
+    lbool val = value(i->getOtherLit());
+    lbool val2 = value(i->getOtherLit2());
+    if (val.isUndef() && val2 == l_False) {
+        uncheckedEnqueue(i->getOtherLit(), PropBy(p, i->getOtherLit2()));
+    } else if (val == l_False && val2.isUndef()) {
+        uncheckedEnqueue(i->getOtherLit2(), PropBy(p, i->getOtherLit()));
+    } else if (val == l_False && val2 == l_False) {
+        confl = PropBy(p, i->getOtherLit2());
+        failBinLit = i->getOtherLit();
+        qhead = trail.size();
+        return false;
+    }
+
+    return true;
+}
+
+/**
+@brief Propagates a tertiary (3-long) clause
+
+We have blocked literals in this case in the watchlist. That must be checked
+and updated.
+*/
+inline const bool Solver::propNormalClause(Watched* &i, Watched* &j, Watched *end, const Lit p, PropBy& confl, const bool update)
 {
-    PropagatedFrom confl;
-    uint32_t num_props = 0;
-    
+    if (value(i->getBlockedLit()).getBool()) {
+        // Clause is sat
+        *j++ = *i;
+        return true;
+    }
+    const uint32_t offset = i->getNormOffset();
+    Clause& c = *clauseAllocator.getPointer(offset);
+
+    // Make sure the false literal is data[1]:
+    //const Lit lit2 = c.size()>2 ? c[2] : c[0];
+    if (c[0] == ~p) {
+        std::swap(c[0], c[1]);
+    }
+    //if (c.size() > 2) assert(lit2 == c[2]);
+
+    assert(c[1] == ~p);
+
+    // If 0th watch is true, then clause is already satisfied.
+    if (value(c[0]).getBool()) {
+        #ifdef VERBOSE_DEBUG
+        printf("Zeroth watch is true\n");
+        #endif
+        j->setNormClause();
+        j->setNormOffset(offset);
+        j->setBlockedLit(c[0]);
+        j++;
+        return true;
+    }
+    // Look for new watch:
+    for (Lit *k = c.getData() + 2, *end2 = c.getDataEnd(); k != end2; k++) {
+        #ifdef VERBOSE_DEBUG
+        printf("Skip watch\n");
+        #endif
+        if (value(*k) != l_False) {
+            #ifdef VERBOSE_DEBUG
+            printf("new watch\n");
+            #endif
+            c[1] = *k;
+            *k = ~p;
+            watches[(~c[1]).toInt()].push(Watched(offset, c[0]));
+            return true;
+        }
+    }
+
     #ifdef VERBOSE_DEBUG
-    cout << "Propagation started" << endl;
+    printf("Did not find watch\n");
     #endif
-    uint32_t qheadBin = qhead;
-
-    while (qhead < trail.size()) {
-        
-        //First propagate binary clauses
-        while (qheadBin < trail.size()) {
-            Lit p   = trail[qheadBin++];
-            vec<WatchedBin> & 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()) {
-                    uncheckedEnqueue(k->impliedLit, PropagatedFrom(p));
-                } else if (val == l_False) {
-                    confl = PropagatedFrom(p);
-                    failBinLit = k->impliedLit;
-                    //goto EndPropagate;
-                }
+    // Did not find watch -- clause is unit under assignment:
+    *j++ = *i;
+    if (value(c[0]) == l_False) {
+        confl = PropBy(offset);
+        qhead = trail.size();
+        return false;
+    } else {
+        uncheckedEnqueue(c[0], offset);
+        #ifdef DYNAMICALLY_UPDATE_GLUE
+        if (update && c.learnt() && c.getGlue() > 2) { // GA
+            uint32_t glue = calcNBLevels(c);
+            if (glue+1 < c.getGlue()) {
+                //c.setGlue(std::min(nbLevels, MAX_THEORETICAL_GLUE);
+                c.setGlue(glue);
             }
         }
-        if (!confl.isNULL()) {
-            goto EndPropagate;
+        #endif
+    }
+
+    return true;
+}
+
+/**
+@brief Propagates a tertiary (3-long) clause
+
+Strangely enough, we need to have 4 literals in the wathclists:
+for the first two varialbles, BOTH negations (v and ~v). This means quite some
+pain, since we need to remove v when moving ~v and vica-versa. However, it means
+better memory-accesses since the watchlist is already in the memory...
+
+\todo maybe not worth it, and a variable-based watchlist should be used
+*/
+inline const bool Solver::propXorClause(Watched* &i, Watched* &j, Watched *end, const Lit p, PropBy& confl)
+{
+    ClauseOffset offset = i->getXorOffset();
+    XorClause& c = *(XorClause*)clauseAllocator.getPointer(offset);
+
+    // Make sure the false literal is data[1]:
+    if (c[0].var() == p.var()) {
+        Lit tmp(c[0]);
+        c[0] = c[1];
+        c[1] = tmp;
+    }
+    assert(c[1].var() == p.var());
+
+    bool final = c.xorEqualFalse();
+    for (uint32_t k = 0, size = c.size(); k != size; k++ ) {
+        const lbool& val = assigns[c[k].var()];
+        if (val.isUndef() && k >= 2) {
+            Lit tmp(c[1]);
+            c[1] = c[k];
+            c[k] = tmp;
+            removeWXCl(watches[(~p).toInt()], offset);
+            watches[Lit(c[1].var(), false).toInt()].push(offset);
+            watches[Lit(c[1].var(), true).toInt()].push(offset);
+            return true;
         }
 
-        //Next, propagate normal clauses
-        Lit            p   = trail[qhead++];     // 'p' is enqueued fact to propagate.
-        vec<Watched>&  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
+        c[k] = c[k].unsign() ^ val.getBool();
+        final ^= val.getBool();
+    }
 
-        for (i = j = ws.getData(), end = ws.getDataEnd();  i != end;) {
-            if (i+1 != end && !value((i+1)->blockedLit).getBool())
-                __builtin_prefetch(clauseAllocator.getPointer((i+1)->clause), 1, 0);
-            
-            if(value(i->blockedLit).getBool()) { // Clause is sat
-                *j++ = *i++;
-                continue;
-            }
-            Lit bl = i->blockedLit;
-            Clause& c = *clauseAllocator.getPointer(i->clause);
-            ClauseOffset origClauseOffset = i->clause;
-            i++;
+    // Did not find watch -- clause is unit under assignment:
+    *j++ = *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;
+    if (assigns[c[0].var()].isUndef()) {
+        c[0] = c[0].unsign()^final;
+        uncheckedEnqueue(c[0], offset);
+    } else if (!final) {
+        confl = PropBy(offset);
+        qhead = trail.size();
+        return false;
+    } else {
+        Lit tmp(c[0]);
+        c[0] = c[1];
+        c[1] = tmp;
+    }
 
-            assert(c[1] == false_lit);
+    return true;
+}
 
-            // If 0th watch is true, then clause is already satisfied.
-            const Lit& first = c[0];
-            if (value(first).getBool()) {
-                j->clause = origClauseOffset;
-                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(origClauseOffset, c[0]));
-                        goto FoundWatch;
-                    }
-                }
+/**
+@brief Does the propagation
 
-                // Did not find watch -- clause is unit under assignment:
-                j->clause = origClauseOffset;
-                j->blockedLit = bl;
-                j++;
-                if (value(first) == l_False) {
-                    confl = PropagatedFrom(&c);
-                    qhead = trail.size();
-                    // Copy the remaining watches:
-                    while (i < end)
-                        *j++ = *i++;
-                } else {
-                    uncheckedEnqueue(first, &c);
-                    #ifdef DYNAMICNBLEVEL
-                    if (update && c.learnt() && c.activity() > 2) { // GA
-                        uint32_t nbLevels = calcNBLevels(c);
-                        if (nbLevels+1 < c.activity())
-                            c.setActivity(nbLevels);
-                    }
+Basically, it goes through the watchlists recursively, and calls the appropirate
+propagaton function
+*/
+PropBy Solver::propagate(const bool update)
+{
+    PropBy confl;
+    uint32_t num_props = 0;
+
+    #ifdef VERBOSE_DEBUG
+    cout << "Propagation started" << endl;
+    #endif
+
+    while (qhead < trail.size()) {
+        Lit            p   = trail[qhead++];     // 'p' is enqueued fact to propagate.
+        vec<Watched>&  ws  = watches[p.toInt()];
+        __builtin_prefetch(ws.getData(), 1, 0);
+        Watched        *i, *j;
+        num_props += ws.size()/2 + 2;
+        if (qhead < trail.size()) {
+            __builtin_prefetch(watches[trail[qhead].toInt()].getData(), 1, 1);
+        }
+
+        #ifdef VERBOSE_DEBUG
+        cout << "Propagating lit " << p << endl;
+        cout << "ws origSize: "<< ws.size() << endl;
+        #endif
+
+        i = j = ws.getData();
+        Watched *end = ws.getDataEnd();
+        for (; i != end; i++) {
+            #ifdef VERBOSE_DEBUG
+            cout << "end-i: " << end-i << endl;
+            cout << "end-j: " << end-j << endl;
+            cout << "i-j: " << i-j << endl;
+            if (i->isClause())
+                std::cout << "clause num " << i->getNormOffset()
+                << " as i of prop: " << *clauseAllocator.getPointer(i->getNormOffset())
+                << std::endl;
+            #endif
+            if (i->isBinary()) {
+                if (!propBinaryClause(i, j, end, p, confl)) break;
+                else continue;
+            } //end BINARY
+
+            if (i->isTriClause()) {
+                if (!propTriClause(i, j, end, p, confl)) break;
+                else continue;
+            } //end TRICLAUSE
+
+            if (i->isClause()) {
+                num_props += 4;
+                if (!propNormalClause(i, j, end, p, confl, update)) break;
+                else {
+                    #ifdef VERBOSE_DEBUG
+                    std::cout << "clause num " << i->getNormOffset() << " after propNorm: " << *clauseAllocator.getPointer(i->getNormOffset()) << std::endl;
                     #endif
+                    continue;
                 }
-            }
-FoundWatch:
-            ;
-        }
-        ws.shrink_(i - j);
+            } //end CLAUSE
 
-        //Finally, propagate XOR-clauses
-        if (xorclauses.size() > 0 && confl.isNULL()) confl = propagate_xors(p);
+            if (i->isXorClause()) {
+                num_props += 10;
+                if (!propXorClause(i, j, end, p, confl)) break;
+                else continue;
+            } //end XORCLAUSE
+        }
+        if (i != end) {
+            i++;
+            //copy remaining watches
+            memmove(j, i, sizeof(Watched)*(end-i));
+        }
+        assert(i >= j);
+        ws.shrink_(i-j);
     }
-EndPropagate:
     propagations += num_props;
     simpDB_props -= num_props;
-    
+
     #ifdef VERBOSE_DEBUG
     cout << "Propagation ended." << endl;
     #endif
@@ -1159,141 +1746,158 @@ EndPropagate:
     return confl;
 }
 
-PropagatedFrom Solver::propagateBin()
+/**
+@brief Only propagates binary clauses
+
+This is used in special algorithms outside the main Solver class
+*/
+PropBy Solver::propagateBin(vec<Lit>& uselessBin)
 {
+    #ifdef DEBUG_USELESS_LEARNT_BIN_REMOVAL
+    assert(uselessBin.empty());
+    #endif
+
     while (qhead < trail.size()) {
-        Lit p   = trail[qhead++];
-        vec<WatchedBin> & wbin = binwatches[p.toInt()];
-        propagations += wbin.size()/2;
-        for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) {
-            lbool val = value(k->impliedLit);
+        Lit p = trail[qhead++];
+
+        uint32_t lev = binPropData[p.var()].lev + 1;
+
+        Lit lev2Ancestor;
+        if (lev == 2) lev2Ancestor = p;
+        else if (lev < 1) lev2Ancestor = lit_Undef;
+        else binPropData[p.var()].lev2Ancestor;
+        const bool learntLeadHere = binPropData[p.var()].learntLeadHere;
+
+        //std::cout << "lev: " << lev << " ~p: "  << ~p << std::endl;
+        const vec<Watched> & ws = watches[p.toInt()];
+        propagations += ws.size()/2 + 2;
+        for(const Watched *k = ws.getData(), *end = ws.getDataEnd(); k != end; k++) {
+            if (!k->isBinary()) continue;
+
+            //std::cout << (~p) << ", " << k->getOtherLit() << " learnt: " << k->getLearnt() << std::endl;
+            lbool val = value(k->getOtherLit());
             if (val.isUndef()) {
-                //uncheckedEnqueue(k->impliedLit, k->clause);
-                uncheckedEnqueueLight(k->impliedLit);
+                uncheckedEnqueueLight2(k->getOtherLit(), lev, lev2Ancestor, learntLeadHere || k->getLearnt());
             } else if (val == l_False) {
-                return PropagatedFrom(p);
+                return PropBy(p);
+            } else {
+                assert(val == l_True);
+                Lit lit2 = k->getOtherLit();
+                if (lev > 1
+                    && level[lit2.var()] != 0
+                    && binPropData[lit2.var()].lev == 1
+                    && binPropData[lit2.var()].lev2Ancestor != lev2Ancestor) {
+                    //Was propagated at level 1, and again here, this binary clause is useless
+                    binPropData[lit2.var()].lev = lev;
+                    binPropData[lit2.var()].lev2Ancestor = lev2Ancestor;
+                    binPropData[lit2.var()].learntLeadHere = learntLeadHere || k->getLearnt();
+                    uselessBin.push(lit2);
+                }
             }
         }
     }
+    //std::cout << " -----------" << std::endl;
 
-    return PropagatedFrom();
+    return PropBy();
 }
 
-template<class T>
-inline const uint32_t Solver::calcNBLevels(const T& ps)
+/**
+@brief Only propagates binary clauses
+
+This is used in special algorithms outside the main Solver class
+*/
+PropBy Solver::propagateNonLearntBin()
 {
-    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++;
+    multiLevelProp = false;
+    uint32_t origQhead = qhead + 1;
+
+    while (qhead < trail.size()) {
+        Lit p = trail[qhead++];
+        const vec<Watched> & ws = watches[p.toInt()];
+        propagations += ws.size()/2 + 2;
+        for(const Watched *k = ws.getData(), *end = ws.getDataEnd(); k != end; k++) {
+            if (!k->isNonLearntBinary()) break;
+
+            lbool val = value(k->getOtherLit());
+            if (val.isUndef()) {
+                if (qhead != origQhead) multiLevelProp = true;
+                uncheckedEnqueueLight(k->getOtherLit());
+            } else if (val == l_False) {
+                return PropBy(p);
+            }
         }
     }
-    return nbLevels;
+
+    return PropBy();
 }
 
-PropagatedFrom Solver::propagate_xors(const Lit& p)
+/**
+@brief Propagate recursively on non-learnt binaries, but do not propagate exceptLit if we reach it
+*/
+const bool Solver::propagateBinExcept(const Lit exceptLit)
 {
-    #ifdef VERBOSE_DEBUG_XOR
-    cout << "Xor-Propagating variable " <<  p.var()+1 << endl;
-    #endif
-    
-    PropagatedFrom confl;
-
-    vec<ClauseOffset>& ws = xorwatches[p.var()];
-    ClauseOffset *i, *j, *end;
-    for (i = j = ws.getData(), end = i + ws.size();  i != end;) {
-        XorClause& c = *(XorClause*)clauseAllocator.getPointer(*i);
-        ClauseOffset origClauseOffset = *i;
-        i++;
-        if (i != end)
-            __builtin_prefetch(clauseAllocator.getPointer(*i), 1, 0);
-
-        // Make sure the false literal is data[1]:
-        if (c[0].var() == p.var()) {
-            Lit tmp(c[0]);
-            c[0] = c[1];
-            c[1] = tmp;
-        }
-        assert(c[1].var() == p.var());
-        
-        #ifdef VERBOSE_DEBUG_XOR
-        cout << "--> xor thing -- " << endl;
-        printClause(c);
-        cout << endl;
-        #endif
-        bool final = c.xor_clause_inverted();
-        for (uint32_t k = 0, size = c.size(); k != size; k++ ) {
-            const lbool& val = assigns[c[k].var()];
-            if (val.isUndef() && k >= 2) {
-                Lit tmp(c[1]);
-                c[1] = c[k];
-                c[k] = tmp;
-                #ifdef VERBOSE_DEBUG_XOR
-                cout << "new watch set" << endl << endl;
-                #endif
-                xorwatches[c[1].var()].push(origClauseOffset);
-                goto FoundWatch;
+    while (qhead < trail.size()) {
+        Lit p   = trail[qhead++];
+        const vec<Watched> & ws = watches[p.toInt()];
+        propagations += ws.size()/2 + 2;
+        for(const Watched *i = ws.getData(), *end = ws.getDataEnd(); i != end; i++) {
+            if (!i->isNonLearntBinary()) break;
+
+            lbool val = value(i->getOtherLit());
+            if (val.isUndef() && i->getOtherLit() != exceptLit) {
+                uncheckedEnqueueLight(i->getOtherLit());
+            } else if (val == l_False) {
+                return false;
             }
-
-            c[k] = c[k].unsign() ^ val.getBool();
-            final ^= val.getBool();
         }
+    }
 
+    return true;
+}
 
-        {
-            // Did not find watch -- clause is unit under assignment:
-            *j++ = origClauseOffset;
+/**
+@brief Propagate only for one hop(=non-recursively) on non-learnt bins
+*/
+const bool Solver::propagateBinOneLevel()
+{
+    Lit p   = trail[qhead];
+    const vec<Watched> & ws = watches[p.toInt()];
+    propagations += ws.size()/2 + 2;
+    for(const Watched *i = ws.getData(), *end = ws.getDataEnd(); i != end; i++) {
+        if (!i->isNonLearntBinary()) break;
 
-            #ifdef VERBOSE_DEBUG_XOR
-            cout << "final: " << std::boolalpha << final << " - ";
-            #endif
-            if (assigns[c[0].var()].isUndef()) {
-                c[0] = c[0].unsign()^final;
-                
-                #ifdef VERBOSE_DEBUG_XOR
-                cout << "propagating ";
-                printLit(c[0]);
-                cout << endl;
-                cout << "propagation clause -- ";
-                printClause(*(Clause*)&c);
-                cout << endl << endl;
-                #endif
-                
-                uncheckedEnqueue(c[0], (Clause*)&c);
-            } else if (!final) {
-                
-                #ifdef VERBOSE_DEBUG_XOR
-                printf("conflict clause -- ");
-                printClause(*(Clause*)&c);
-                cout << endl << endl;
-                #endif
-                
-                confl = PropagatedFrom((Clause*)&c);
-                qhead = trail.size();
-                // Copy the remaining watches:
-                while (i < end)
-                    *j++ = *i++;
-            } else {
-                #ifdef VERBOSE_DEBUG_XOR
-                printf("xor satisfied\n");
-                #endif
-                
-                Lit tmp(c[0]);
-                c[0] = c[1];
-                c[1] = tmp;
-            }
+        lbool val = value(i->getOtherLit());
+        if (val.isUndef()) {
+            uncheckedEnqueueLight(i->getOtherLit());
+        } else if (val == l_False) {
+            return false;
         }
-FoundWatch:
-        ;
     }
-    ws.shrink_(i - j);
 
-    return confl;
+    return true;
 }
 
+/**
+@brief Calculates the glue of a clause
+
+Used to calculate the Glue of a new clause, or to update the glue of an
+existing clause. Only used if the glue-based activity heuristic is enabled,
+i.e. if we are in GLUCOSE mode (not MiniSat mode)
+*/
+template<class T>
+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;
+}
 
 /*_________________________________________________________________________________________________
 |
@@ -1304,195 +1908,99 @@ FoundWatch:
 |    clauses are clauses that are reason to some assignment. Binary clauses are never removed.
 |________________________________________________________________________________________________@*/
 bool  reduceDB_ltMiniSat::operator () (const Clause* x, const Clause* y) {
-    const uint xsize = x->size();
-    const uint ysize = y->size();
-    
-    // First criteria
-    if (xsize > 2 && ysize == 2) return 1;
-    if (ysize > 2 && xsize == 2) return 0;
-
-    if (x->oldActivity() == y->oldActivity())
+    const uint32_t xsize = x->size();
+    const uint32_t ysize = y->size();
+
+    assert(xsize > 2 && ysize > 2);
+    if (x->getMiniSatAct() == y->getMiniSatAct())
         return xsize > ysize;
-    else return x->oldActivity() < y->oldActivity();
+    else return x->getMiniSatAct() < y->getMiniSatAct();
 }
-    
+
 bool  reduceDB_ltGlucose::operator () (const Clause* x, const Clause* y) {
-    const uint xsize = x->size();
-    const uint ysize = y->size();
-    
-    // First criteria
-    if (xsize > 2 && ysize == 2) return 1;
-    if (ysize > 2 && xsize == 2) return 0;
-    
-    if (x->activity() > y->activity()) return 1;
-    if (x->activity() < y->activity()) return 0;
+    const uint32_t xsize = x->size();
+    const uint32_t ysize = y->size();
+
+    assert(xsize > 2 && ysize > 2);
+    if (x->getGlue() > y->getGlue()) return 1;
+    if (x->getGlue() < y->getGlue()) return 0;
     return xsize > ysize;
 }
 
+/**
+@brief Removes learnt clauses that have been found not to be too good
+
+Either based on glue or MiniSat-style learnt clause activities, the clauses are
+sorted and then removed
+*/
 void Solver::reduceDB()
 {
     uint32_t     i, j;
 
     nbReduceDB++;
     if (lastSelectedRestartType == dynamic_restart)
-        std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_ltGlucose());
+        std::sort(learnts.getData(), learnts.getDataEnd(), reduceDB_ltGlucose());
     else
-        std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_ltMiniSat());
-    
+        std::sort(learnts.getData(), learnts.getDataEnd(), reduceDB_ltMiniSat());
+
     #ifdef VERBOSE_DEBUG
     std::cout << "Cleaning clauses" << std::endl;
-    for (uint i = 0; i != learnts.size(); i++) {
-        std::cout << "activity:" << learnts[i]->activity()
-        << " \toldActivity:" << learnts[i]->oldActivity()
+    for (uint32_t i = 0; i != learnts.size(); i++) {
+        std::cout << "activity:" << learnts[i]->getGlue()
+        << " \toldActivity:" << learnts[i]->getMiniSatAct()
         << " \tsize:" << learnts[i]->size() << std::endl;
     }
     #endif
-    
 
-    const uint removeNum = (double)learnts.size() / (double)RATIOREMOVECLAUSES;
+
+    const uint32_t removeNum = (double)learnts.size() * (double)RATIOREMOVECLAUSES;
+    uint32_t totalNumRemoved = 0;
+    uint32_t totalNumNonRemoved = 0;
+    uint64_t totalGlueOfRemoved = 0;
+    uint64_t totalSizeOfRemoved = 0;
+    uint64_t totalGlueOfNonRemoved = 0;
+    uint64_t totalSizeOfNonRemoved = 0;
     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) {
+        if (i+1 < removeNum) __builtin_prefetch(learnts[i+1], 0, 0);
+        assert(learnts[i]->size() > 2);
+        if (!locked(*learnts[i])
+            && (lastSelectedRestartType == static_restart || learnts[i]->getGlue() > 2)
+            && learnts[i]->size() > 3) { //we cannot update activity of 3-longs because of wathclists
+
+            totalGlueOfRemoved += learnts[i]->getGlue();
+            totalSizeOfRemoved += learnts[i]->size();
+            totalNumRemoved++;
             removeClause(*learnts[i]);
-        } else
+        } else {
+            totalGlueOfNonRemoved += learnts[i]->getGlue();
+            totalSizeOfNonRemoved += learnts[i]->size();
+            totalNumNonRemoved++;
             learnts[j++] = learnts[i];
+        }
     }
     for (; i < learnts.size(); i++) {
+        totalGlueOfNonRemoved += learnts[i]->getGlue();
+        totalSizeOfNonRemoved += learnts[i]->size();
+        totalNumNonRemoved++;
         learnts[j++] = learnts[i];
     }
-    learnts.shrink(i - j);
-
-    clauseAllocator.consolidate(this);
-}
+    learnts.shrink_(i - j);
 
-const vec<Clause*>& Solver::get_learnts() const
-{
-    return learnts;
-}
-
-const vec<Clause*>& Solver::get_sorted_learnts()
-{
-    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());
-    return learnts;
-}
-
-const vector<Lit> Solver::get_unitary_learnts() const
-{
-    vector<Lit> unitaries;
-    if (decisionLevel() > 0) {
-        for (uint32_t i = 0; i != trail_lim[0]; i++) {
-            unitaries.push_back(trail[i]);
-        }
+    if (conf.verbosity >= 3) {
+        std::cout << "c rem-learnts " << std::setw(6) << totalNumRemoved
+        << "  avgGlue "
+        << std::fixed << std::setw(5) << std::setprecision(2)  << ((double)totalGlueOfRemoved/(double)totalNumRemoved)
+        << "  avgSize "
+        << std::fixed << std::setw(6) << std::setprecision(2) << ((double)totalSizeOfRemoved/(double)totalNumRemoved)
+        << "  || remain " << std::setw(6) << totalNumNonRemoved
+        << "  avgGlue "
+        << std::fixed << std::setw(5) << std::setprecision(2)  << ((double)totalGlueOfNonRemoved/(double)totalNumNonRemoved)
+        << "  avgSize "
+        << std::fixed << std::setw(6) << std::setprecision(2) << ((double)totalSizeOfNonRemoved/(double)totalNumNonRemoved)
+        << std::endl;
     }
-    
-    return unitaries;
-}
-
-void Solver::dumpSortedLearnts(const char* file, const uint32_t maxSize)
-{
-    FILE* outfile = fopen(file, "w");
-    if (!outfile) {
-        printf("Error: Cannot open file '%s' to write learnt clauses!\n", file);
-        exit(-1);
-    }
-
-    fprintf(outfile, "c \nc ---------\n");
-    fprintf(outfile, "c unitaries\n");
-    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 conflicts %lu\n", (unsigned long)conflicts);
-    if (maxSize == 1) goto end;
 
-    fprintf(outfile, "c \nc ---------------------------------\n");
-    fprintf(outfile, "c learnt clauses from binaryClauses\n");
-    fprintf(outfile, "c ---------------------------------\n");
-    for (uint i = 0; i != binaryClauses.size(); i++) {
-        if (binaryClauses[i]->learnt()) {
-            binaryClauses[i]->print(outfile);
-        }
-    }
-
-    fprintf(outfile, "c \nc ---------------------------------------\n");
-    fprintf(outfile, "c clauses representing 2-long XOR clauses\n");
-    fprintf(outfile, "c ---------------------------------------\n");
-    {
-        const vector<Lit>& table = varReplacer->getReplaceTable();
-        for (Var var = 0; var != table.size(); var++) {
-            Lit lit = table[var];
-            if (lit.var() == var)
-                continue;
-
-            fprintf(outfile, "%s%d %d 0\n", (!lit.sign() ? "-" : ""), lit.var()+1, var+1);
-            fprintf(outfile, "%s%d -%d 0\n", (lit.sign() ? "-" : ""), lit.var()+1, var+1);
-            #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);
-        }
-    }
-
-    end:
-    
-    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;
+    clauseAllocator.consolidate(this);
 }
 
 inline int64_t abs64(int64_t a)
@@ -1501,14 +2009,13 @@ inline int64_t abs64(int64_t a)
     return a;
 }
 
-/*_________________________________________________________________________________________________
-|
-|  simplify : [void]  ->  [bool]
-|
-|  Description:
-|    Simplify the clause database according to the current top-level assigment. Currently, the only
-|    thing done here is the removal of satisfied clauses, but more things can be put here.
-|________________________________________________________________________________________________@*/
+/**
+@brief Simplify the clause database according to the current top-level assigment.
+
+We remove satisfied clauses, clean clauses from assigned literals, find
+binary xor-clauses and replace variables with one another. Heuristics are
+used to check if we need to find binary xor clauses or not.
+*/
 const bool Solver::simplify()
 {
     testAllClauseAttach();
@@ -1522,44 +2029,40 @@ const bool Solver::simplify()
     if (simpDB_props > 0) {
         return true;
     }
-    
-    double slowdown = (100000.0/(double)binaryClauses.size());
-    slowdown = std::min(3.5, slowdown);
-    slowdown = std::max(0.2, slowdown);
-    
-    double speedup = 50000000.0/(double)(propagations-lastSearchForBinaryXor);
+    double myTime = cpuTime();
+
+    double slowdown = (100000.0/((double)numBins * 30000.0/((double)order_heap.size())));
+    slowdown = std::min(1.5, slowdown);
+    slowdown = std::max(0.01, slowdown);
+
+    double speedup = 200000000.0/(double)(propagations-lastSearchForBinaryXor);
     speedup = std::min(3.5, speedup);
     speedup = std::max(0.2, speedup);
-    
+
     /*std::cout << "new:" << nbBin - lastNbBin + becameBinary << std::endl;
     std::cout << "left:" << ((double)(nbBin - lastNbBin + becameBinary)/BINARY_TO_XOR_APPROX) * slowdown  << std::endl;
     std::cout << "right:" << (double)order_heap.size() * PERCENTAGEPERFORMREPLACE * speedup << std::endl;*/
-    
-    if (findBinaryXors && regularlyFindBinaryXors &&
-        (((double)abs64((int64_t)nbBin - (int64_t)lastNbBin + (int64_t)becameBinary)/BINARY_TO_XOR_APPROX) * slowdown) >
+
+    if (conf.doFindEqLits && conf.doRegFindEqLits &&
+        (((double)abs64((int64_t)numNewBin - (int64_t)lastNbBin)/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);
+        clauseCleaner->removeSatisfiedBins();
         if (!ok) return false;
-        testAllClauseAttach();
 
-        XorFinder xorFinder(*this, binaryClauses, ClauseCleaner::binaryClauses);
-        if (!xorFinder.doNoPart(2, 2)) return false;
-        testAllClauseAttach();
-        
-        lastNbBin = nbBin;
-        becameBinary = 0;
+        if (!sCCFinder->find2LongXors()) return false;
+
+        lastNbBin = numNewBin;
     }
-    
+
     // Remove satisfied clauses:
     clauseCleaner->removeAndCleanAll();
-    testAllClauseAttach();
     if (!ok) return false;
-    
-    if (performReplace && !varReplacer->performReplace())
+
+    if (conf.doReplace && !varReplacer->performReplace())
         return false;
 
     // Remove fixed variables from the variable heap:
@@ -1570,42 +2073,43 @@ const bool Solver::simplify()
         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)
+    simpDB_props = std::min((uint64_t)80000000, 4*clauses_literals + 4*learnts_literals); //at most 6 sec wait
+    simpDB_props = std::max((int64_t)30000000, simpDB_props); //at least 2 sec wait
+    totalSimplifyTime += cpuTime() - myTime;
 
     testAllClauseAttach();
     return true;
 }
 
+/**
+@brief Search for a model
 
-/*_________________________________________________________________________________________________
-|
-|  search : (nof_conflicts : int) (nof_learnts : int) (params : const SearchParams&)  ->  [lbool]
-|
-|  Description:
-|    Search for a model the specified number of conflicts, keeping the number of learnt clauses
-|    below the provided limit. NOTE! Use negative value for 'nof_conflicts' or 'nof_learnts' to
-|    indicate infinity.
-|
-|  Output:
-|    'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If
-|    all variables are decision variables, this means that the clause set is satisfiable. 'l_False'
-|    if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached.
-|________________________________________________________________________________________________@*/
-lbool Solver::search(int nof_conflicts, int nof_conflicts_fullrestart, const bool update)
+Limits: must be below the specified number of conflicts and must keep the
+number of learnt clauses below the provided limit
+
+Use negative value for 'nof_conflicts' or 'nof_learnts' to indicate infinity.
+
+Output: 'l_True' if a partial assigment that is consistent with respect to the
+clauseset is found. If all variables are decision variables, this means
+that the clause set is satisfiable. 'l_False' if the clause set is
+unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached.
+*/
+lbool Solver::search(const uint64_t nof_conflicts, const uint64_t nof_conflicts_fullrestart, const bool update)
 {
     assert(ok);
-    int         conflictC = 0;
+    uint64_t    conflictC = 0;
     vec<Lit>    learnt_clause;
     llbool      ret;
 
-    starts++;
-    if (restartType == static_restart)
-        staticStarts++;
-    else
-        dynStarts++;
-    
+    if (!simplifying && update) {
+        starts++;
+        if (restartType == static_restart) staticStarts++;
+        else dynStarts++;
+    }
+    glueHistory.fastclear();
+
     #ifdef USE_GAUSS
     for (vector<Gaussian*>::iterator gauss = gauss_matrixes.begin(), end = gauss_matrixes.end(); gauss != end; gauss++) {
         if (!(*gauss)->full_init())
@@ -1615,8 +2119,17 @@ lbool Solver::search(int nof_conflicts, int nof_conflicts_fullrestart, const boo
 
     testAllClauseAttach();
     findAllAttach();
+    #ifdef VERBOSE_DEBUG
+    std::cout << "c started Solver::search()" << std::endl;
+    //printAllClauses();
+    #endif //VERBOSE_DEBUG
     for (;;) {
-        PropagatedFrom confl = propagate(update);
+        assert(ok);
+        PropBy confl = propagate(update);
+        #ifdef VERBOSE_DEBUG
+        std::cout << "c Solver::search() has finished propagation" << std::endl;
+        //printAllClauses();
+        #endif //VERBOSE_DEBUG
 
         if (!confl.isNULL()) {
             ret = handle_conflict(learnt_clause, confl, conflictC, update);
@@ -1631,34 +2144,49 @@ lbool Solver::search(int nof_conflicts, int nof_conflicts_fullrestart, const boo
             }
             if (at_least_one_continue) continue;
             #endif //USE_GAUSS
+
+            assert(ok);
+            if (conf.doCacheOTFSSR  && decisionLevel() == 1) saveOTFData();
             ret = new_decision(nof_conflicts, nof_conflicts_fullrestart, conflictC);
             if (ret != l_Nothing) return ret;
         }
     }
 }
 
-llbool Solver::new_decision(const int& nof_conflicts, const int& nof_conflicts_fullrestart, int& conflictC)
+/**
+@brief Picks a new decision variable to branch on
+
+@returns l_Undef if it should restart instead. l_False if it reached UNSAT
+         (through simplification)
+*/
+llbool Solver::new_decision(const uint64_t nof_conflicts, const uint64_t nof_conflicts_fullrestart, const uint64_t conflictC)
 {
-    
+
+    if (conflicts >= nof_conflicts_fullrestart || needToInterrupt)  {
+        #ifdef STATS_NEEDED
+        if (dynamic_behaviour_analysis)
+            progress_estimate = progressEstimate();
+        #endif
+        cancelUntil(0);
+        return l_Undef;
+    }
+
     // Reached bound on number of conflicts?
     switch (restartType) {
     case dynamic_restart:
-        if (nbDecisionLevelHistory.isvalid() &&
-            ((nbDecisionLevelHistory.getavg()) > (totalSumOfDecisionLevel / (double)(conflicts - conflictsAtLastSolve)))) {
-            
+        if (glueHistory.isvalid() &&
+            0.95*glueHistory.getAvgDouble() > glueHistory.getAvgAllDouble()) {
+
             #ifdef DEBUG_DYNAMIC_RESTART
-            if (nbDecisionLevelHistory.isvalid()) {
-                std::cout << "nbDecisionLevelHistory.getavg():" << nbDecisionLevelHistory.getavg() <<std::endl;
-                //std::cout << "calculated limit:" << ((double)(nbDecisionLevelHistory.getavg())*0.9*((double)fullStarts + 20.0)/20.0) << std::endl;
-                std::cout << "totalSumOfDecisionLevel:" << totalSumOfDecisionLevel << std::endl;
+            if (glueHistory.isvalid()) {
+                std::cout << "glueHistory.getavg():" << glueHistory.getavg() <<std::endl;
+                std::cout << "totalSumOfGlue:" << totalSumOfGlue << std::endl;
                 std::cout << "conflicts:" << conflicts<< std::endl;
-                std::cout << "conflictsAtLastSolve:" << conflictsAtLastSolve << std::endl;
-                std::cout << "conflicts-conflictsAtLastSolve:" << conflicts-conflictsAtLastSolve<< std::endl;
-                std::cout << "fullStarts:" << fullStarts << std::endl;
+                std::cout << "compTotSumGlue:" << compTotSumGlue << std::endl;
+                std::cout << "conflicts-compTotSumGlue:" << conflicts-compTotSumGlue<< std::endl;
             }
             #endif
-            
-            nbDecisionLevelHistory.fastclear();
+
             #ifdef STATS_NEEDED
             if (dynamic_behaviour_analysis)
                 progress_estimate = progressEstimate();
@@ -1668,7 +2196,7 @@ llbool Solver::new_decision(const int& nof_conflicts, const int& nof_conflicts_f
         }
         break;
     case static_restart:
-        if (nof_conflicts >= 0 && conflictC >= nof_conflicts) {
+        if (conflictC >= nof_conflicts) {
             #ifdef STATS_NEEDED
             if (dynamic_behaviour_analysis)
                 progress_estimate = progressEstimate();
@@ -1681,25 +2209,18 @@ llbool Solver::new_decision(const int& nof_conflicts, const int& nof_conflicts_f
         assert(false);
         break;
     }
-    if (nof_conflicts_fullrestart >= 0 && (int)conflicts >= nof_conflicts_fullrestart)  {
-        #ifdef STATS_NEEDED
-        if (dynamic_behaviour_analysis)
-            progress_estimate = progressEstimate();
-        #endif
-        cancelUntil(0);
-        return l_Undef;
-    }
 
     // Simplify the set of problem clauses:
-    if (decisionLevel() == 0 && !simplify()) {
-        return l_False;
+    if (decisionLevel() == 0) {
+        if (!dataSync->syncData()) return l_False;
+        if (!simplify()) return l_False;
     }
 
     // Reduce the set of learnt clauses:
-    if (conflicts >= curRestart * nbclausesbeforereduce + nbCompensateSubsumer) {
-        curRestart ++;
+    if (conflicts >= numCleanedLearnts * nbClBeforeRed + nbCompensateSubsumer) {
+        numCleanedLearnts ++;
         reduceDB();
-        nbclausesbeforereduce += 500;
+        nbClBeforeRed += 500;
     }
 
     Lit next = lit_Undef;
@@ -1735,89 +2256,104 @@ llbool Solver::new_decision(const int& nof_conflicts, const int& nof_conflicts_f
     return l_Nothing;
 }
 
-llbool Solver::handle_conflict(vec<Lit>& learnt_clause, PropagatedFrom confl, int& conflictC, const bool update)
+/**
+@brief Handles a conflict that we reached through propagation
+
+Handles on-the-fly subsumption: the OTF subsumption check is done in
+conflict analysis, but this is the code that actually replaces the original
+clause with that of the shorter one
+@returns l_False if UNSAT
+*/
+llbool Solver::handle_conflict(vec<Lit>& learnt_clause, PropBy confl, uint64_t& conflictC, const bool update)
 {
     #ifdef VERBOSE_DEBUG
     cout << "Handling conflict: ";
-    for (uint i = 0; i < learnt_clause.size(); i++)
+    for (uint32_t i = 0; i < learnt_clause.size(); i++)
         cout << learnt_clause[i].var()+1 << ",";
     cout << endl;
     #endif
-    
+
     int backtrack_level;
-    uint32_t nbLevels;
+    uint32_t glue;
 
     conflicts++;
     conflictC++;
     if (decisionLevel() == 0)
         return l_False;
     learnt_clause.clear();
-    Clause* c = analyze(confl, learnt_clause, backtrack_level, nbLevels, update);
+    Clause* c = analyze(confl, learnt_clause, backtrack_level, glue, 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++;
+        #endif //RANDOM_LOOKAROUND_SEARCHSPACE
+        if (restartType == dynamic_restart) glueHistory.push(glue);
+        conflSizeHist.push(learnt_clause.size());
     }
-    
+
     #ifdef STATS_NEEDED
     if (dynamic_behaviour_analysis)
         logger.conflict(Logger::simple_confl_type, backtrack_level, confl->getGroup(), learnt_clause);
     #endif
     cancelUntil(backtrack_level);
-    
+
     #ifdef VERBOSE_DEBUG
     cout << "Learning:";
-    for (uint i = 0; i < learnt_clause.size(); i++) printLit(learnt_clause[i]), cout << " ";
+    for (uint32_t i = 0; i < learnt_clause.size(); i++) printLit(learnt_clause[i]), cout << " ";
     cout << endl;
     cout << "reverting var " << learnt_clause[0].var()+1 << " to " << !learnt_clause[0].sign() << endl;
     #endif
-    
+
     assert(value(learnt_clause[0]) == l_Undef);
     //Unitary learnt
     if (learnt_clause.size() == 1) {
         uncheckedEnqueue(learnt_clause[0]);
         assert(backtrack_level == 0 && "Unit clause learnt, so must cancel until level 0, right?");
-        
+
         #ifdef VERBOSE_DEBUG
         cout << "Unit clause learnt." << endl;
         #endif
     //Normal learnt
     } else {
-        if (c) {
+        if (learnt_clause.size() == 2) {
+            attachBinClause(learnt_clause[0], learnt_clause[1], true);
+            numNewBin++;
+            dataSync->signalNewBinClause(learnt_clause);
+            uncheckedEnqueue(learnt_clause[0], PropBy(learnt_clause[1]));
+            goto end;
+        }
+
+        if (c) { //On-the-fly subsumption
+            uint32_t origSize = c->size();
             detachClause(*c);
             for (uint32_t i = 0; i != learnt_clause.size(); i++)
                 (*c)[i] = learnt_clause[i];
-            c->resize(learnt_clause.size());
-            if (c->learnt()) {
-                if (c->activity() > nbLevels)
-                    c->setActivity(nbLevels); // LS
-                if (c->size() == 2)
-                    nbBin++;
-            }
-            c->setStrenghtened();
-        } else {
-            c = clauseAllocator.Clause_new(learnt_clause, learnt_clause_group++, true);
+            c->shrink(origSize - learnt_clause.size());
+            if (c->learnt() && c->getGlue() > glue)
+                c->setGlue(glue); // LS
+            attachClause(*c);
+            uncheckedEnqueue(learnt_clause[0], clauseAllocator.getOffset(c));
+        } else {  //no on-the-fly subsumption
             #ifdef STATS_NEEDED
             if (dynamic_behaviour_analysis)
                 logger.set_group_name(c->getGroup(), "learnt clause");
             #endif
-            if (c->size() > 2) {
-                learnts.push(c);
-                c->setActivity(nbLevels); // LS
+            c = clauseAllocator.Clause_new(learnt_clause, learnt_clause_group++, true);
+            if (conf.doMaxGlueDel && glue > conf.maxGlue) {
+                nbClOverMaxGlue++;
+                nbCompensateSubsumer++;
+                unWindGlue[learnt_clause[0].var()] = c;
+                #ifdef UNWINDING_DEBUG
+                std::cout << "unwind, var:" << learnt_clause[0].var() << std::endl;
+                c->plainPrint();
+                #endif //VERBOSE_DEBUG
             } else {
-                binaryClauses.push(c);
-                nbBin++;
+                learnts.push(c);
             }
+            c->setGlue(std::min(glue, MAX_THEORETICAL_GLUE));
+            attachClause(*c);
+            uncheckedEnqueue(learnt_clause[0], clauseAllocator.getOffset(c));
         }
-        if (nbLevels <= 2) nbDL2++;
-        attachClause(*c);
-        uncheckedEnqueue(learnt_clause[0], c);
+        end:;
     }
 
     varDecayActivity();
@@ -1826,84 +2362,37 @@ llbool Solver::handle_conflict(vec<Lit>& learnt_clause, PropagatedFrom confl, in
     return l_Nothing;
 }
 
-double Solver::progressEstimate() const
-{
-    double  progress = 0;
-    double  F = 1.0 / nVars();
-
-    for (uint32_t i = 0; i <= decisionLevel(); i++) {
-        int beg = i == 0 ? 0 : trail_lim[i - 1];
-        int end = i == decisionLevel() ? trail.size() : trail_lim[i];
-        progress += pow(F, (int)i) * (end - beg);
-    }
-
-    return progress / nVars();
-}
+/**
+@brief After a full restart, determines which restar type to use
 
-#ifdef USE_GAUSS
-void Solver::print_gauss_sum_stats()
+Uses class RestartTypeChooser to do the heavy-lifting
+*/
+const bool Solver::chooseRestartType(const uint32_t& lastFullRestart)
 {
-    if (gauss_matrixes.size() == 0 && verbosity >= 2) {
-        printf("  no matrixes found |\n");
-        return;
-    }
-    
-    uint called = 0;
-    uint useful_prop = 0;
-    uint useful_confl = 0;
-    uint disabled = 0;
-    for (vector<Gaussian*>::const_iterator gauss = gauss_matrixes.begin(), end= gauss_matrixes.end(); gauss != end; gauss++) {
-        disabled += (*gauss)->get_disabled();
-        called += (*gauss)->get_called();
-        useful_prop += (*gauss)->get_useful_prop();
-        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 (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
+    uint32_t relativeStart = starts - lastFullRestart;
 
-const bool Solver::chooseRestartType(const uint& lastFullRestart)
-{
-    uint relativeStart = starts - lastFullRestart;
-    
     if (relativeStart > RESTART_TYPE_DECIDER_FROM  && relativeStart < RESTART_TYPE_DECIDER_UNTIL) {
-        if (fixRestartType == auto_restart)
+        if (conf.fixRestartType == auto_restart)
             restartTypeChooser->addInfo();
-        
+
         if (relativeStart == (RESTART_TYPE_DECIDER_UNTIL-1)) {
             RestartType tmp;
-            if (fixRestartType == auto_restart)
+            if (conf.fixRestartType == auto_restart)
                 tmp = restartTypeChooser->choose();
             else
-                tmp = fixRestartType;
-            
+                tmp = conf.fixRestartType;
+
             if (tmp == dynamic_restart) {
-                nbDecisionLevelHistory.fastclear();
-                nbDecisionLevelHistory.initSize(100);
-                if (verbosity >= 2)
-                    printf("c |                           Decided on dynamic restart strategy                         |\n");
+                glueHistory.fastclear();
+                if (conf.verbosity >= 3)
+                    std::cout << "c Decided on dynamic restart strategy"
+                    << std::endl;
             } else  {
-                if (verbosity >= 2)
-                    printf("c |                            Decided on static restart strategy                         |\n");
-                
-                #ifdef USE_GAUSS
+                if (conf.verbosity >= 1)
+                    std::cout << "c Decided on static restart strategy"
+                    << std::endl;
+
                 if (!matrixFinder->findMatrixes()) return false;
-                #endif //USE_GAUSS
             }
             lastSelectedRestartType = tmp;
             restartType = tmp;
@@ -1916,94 +2405,61 @@ const bool Solver::chooseRestartType(const uint& lastFullRestart)
 
 inline void Solver::setDefaultRestartType()
 {
-    if (fixRestartType != auto_restart) restartType = fixRestartType;
+    if (conf.fixRestartType != auto_restart) restartType = conf.fixRestartType;
     else restartType = static_restart;
-    
-    if (restartType == dynamic_restart) {
-        nbDecisionLevelHistory.fastclear();
-        nbDecisionLevelHistory.initSize(100);
-    }
-    
+
+    glueHistory.clear();
+    glueHistory.initSize(MIN_GLUE_RESTART);
+    conflSizeHist.clear();
+    conflSizeHist.initSize(1000);
+
     lastSelectedRestartType = restartType;
 }
 
+/**
+@brief The function that brings together almost all CNF-simplifications
+
+It burst-searches for given number of conflicts, then it tries all sorts of
+things like variable elimination, subsumption, failed literal probing, etc.
+to try to simplifcy the problem at hand.
+*/
 const lbool Solver::simplifyProblem(const uint32_t numConfls)
 {
     testAllClauseAttach();
-    #ifdef USE_GAUSS
-    bool gauss_was_cleared = (gauss_matrixes.size() == 0);
-    clearGaussMatrixes();
-    #endif //USE_GAUSS
+    bool gaussWasCleared = clearGaussMatrixes();
 
     StateSaver savedState(*this);;
 
     #ifdef BURST_SEARCH
-    if (verbosity >= 2)
-        std::cout << "c | " << std::setw(24) << " " 
-        << "Simplifying problem for " << std::setw(8) << numConfls << " confls" 
-        << std::setw(24) << " |" << std::endl;
-    random_var_freq = 1;
+    if (conf.verbosity >= 3)
+        std::cout << "c " << std::setw(24) << " "
+        << "Simplifying problem for " << std::setw(8) << numConfls << " confls"
+        << std::endl;
+    conf.random_var_freq = 1;
     simplifying = true;
     uint64_t origConflicts = conflicts;
     #endif //BURST_SEARCH
-    
+
     lbool status = l_Undef;
 
     #ifdef BURST_SEARCH
     restartType = static_restart;
-    
+
+    printRestartStat("S");
     while(status == l_Undef && conflicts-origConflicts < numConfls) {
-        printRestartStat();
-        status = search(100, -1, false);
-        starts--;
+        status = search(100, std::numeric_limits<uint64_t>::max(), false);
     }
-    if (status != l_Undef)
-        goto end;
-    printRestartStat();
+    printRestartStat("S");
+    if (status != l_Undef) goto end;
     #endif //BURST_SEARCH
 
-    if (doXorSubsumption && !xorSubsumer->simplifyBySubsumption()) {
-        status = l_False;
-        goto end;
-    }
-    testAllClauseAttach();
+    if (conf.doXorSubsumption && !xorSubsumer->simplifyBySubsumption()) goto end;
 
-    if (failedVarSearch && !failedVarSearcher->search((nClauses() < 500000 && order_heap.size() < 50000) ? 9000000 : 3000000))  {
-        status = l_False;
-        goto end;
-    }
-    testAllClauseAttach();
+    if (conf.doFailedLit && !failedLitSearcher->search()) goto end;
 
-    if (performReplace && (regularRemoveUselessBins || regularSubsumeWithNonExistBinaries)) {
-        OnlyNonLearntBins onlyNonLearntBins(*this);
-        if (!onlyNonLearntBins.fill()) {
-            status = l_False;
-            goto end;
-        }
-        if (regularRemoveUselessBins) {
-            UselessBinRemover uselessBinRemover(*this, onlyNonLearntBins);
-            if (!uselessBinRemover.removeUslessBinFull()) {
-                status = l_False;
-                goto end;
-            }
-        }
-        if (regularSubsumeWithNonExistBinaries
-            && !subsumer->subsumeWithBinaries(&onlyNonLearntBins)) {
-            status = l_False;
-            goto end;
-        }
-    }
+    if (conf.doSatELite && !subsumer->simplifyBySubsumption(false)) goto end;
+    if (conf.doSatELite && !subsumer->simplifyBySubsumption(true)) goto end;
 
-    if (doSubsumption && !subsumer->simplifyBySubsumption(false)) {
-        status = l_False;
-        goto end;
-    }
-    if (doSubsumption && !subsumer->simplifyBySubsumption(true)) {
-        status = l_False;
-        goto end;
-    }
-    testAllClauseAttach();
-    
     /*if (findNormalXors && xorclauses.size() > 200 && clauses.size() < MAX_CLAUSENUM_XORFIND/8) {
         XorFinder xorFinder(*this, clauses, ClauseCleaner::clauses);
         if (!xorFinder.doNoPart(3, 7)) {
@@ -2011,558 +2467,377 @@ const lbool Solver::simplifyProblem(const uint32_t numConfls)
             goto end;
         }
     } else*/ if (xorclauses.size() <= 200 && xorclauses.size() > 0 && nClauses() > 10000) {
-        XorFinder x(*this, clauses, ClauseCleaner::clauses);
+        XorFinder x(*this, clauses);
         x.addAllXorAsNorm();
     }
-    
+
+    if (conf.doClausVivif && !clauseVivifier->vivifyClauses()) goto end;
+
+    //addSymmBreakClauses();
+
+    if (conf.doSortWatched) sortWatched();
+    if (conf.doCacheOTFSSR &&  conf.doCalcReach) calcReachability();
+
 end:
     #ifdef BURST_SEARCH
-    if (verbosity >= 2)
-        printf("c                                      Simplifying finished                               |\n");
+    if (conf.verbosity >= 3)
+        std::cout << "c Simplifying finished" << std::endl;
     #endif //#ifdef BURST_SEARCH
 
-
     savedState.restore();
     simplifying = false;
-    
-    #ifdef USE_GAUSS
-    if (status == l_Undef && !gauss_was_cleared && !matrixFinder->findMatrixes())
+
+    if (status == l_Undef && gaussWasCleared && !matrixFinder->findMatrixes())
         status = l_False;
-    #endif //USE_GAUSS
 
     testAllClauseAttach();
+
+    if (!ok) return l_False;
     return status;
 }
 
-const bool Solver::checkFullRestart(int& nof_conflicts, int& nof_conflicts_fullrestart, uint& lastFullRestart)
+/**
+@brief Should we perform a full restart?
+
+If so, we also do the things to be done if the full restart is effected.
+Currently, this means we try to find disconnected components and solve
+them with sub-solvers using class PartHandler
+*/
+const bool Solver::checkFullRestart(uint64_t& nof_conflicts, uint64_t& nof_conflicts_fullrestart, uint32_t& lastFullRestart)
 {
-    if (nof_conflicts_fullrestart > 0 && (int)conflicts >= nof_conflicts_fullrestart) {
+    if (nof_conflicts_fullrestart > 0 && conflicts >= nof_conflicts_fullrestart) {
         #ifdef USE_GAUSS
         clearGaussMatrixes();
         #endif //USE_GAUSS
-        if (verbosity >= 2)
-            printf("c |                                      Fully restarting                                 |\n");
-        nof_conflicts = restart_first + (double)restart_first*restart_inc;
+        nof_conflicts = conf.restart_first + (double)conf.restart_first*conf.restart_inc;
         nof_conflicts_fullrestart = (double)nof_conflicts_fullrestart * FULLRESTART_MULTIPLIER_MULTIPLIER;
         restartType = static_restart;
         lastFullRestart = starts;
-        
+
+        if (conf.verbosity >= 3)
+            std::cout << "c Fully restarting" << std::endl;
+        printRestartStat("F");
+
         /*if (findNormalXors && clauses.size() < MAX_CLAUSENUM_XORFIND) {
             XorFinder xorFinder(this, clauses, ClauseCleaner::clauses);
             if (!xorFinder.doNoPart(3, 10))
                 return false;
         }*/
-        
-        if (doPartHandler && !partHandler->handle())
+
+        if (conf.doPartHandler && !partHandler->handle())
             return false;
-        
+
         //calculateDefaultPolarities();
-        
+        if (conf.polarity_mode != polarity_auto) {
+            for (uint32_t i = 0; i < polarity.size(); i++) {
+                polarity[i] = defaultPolarity();
+            }
+        }
+
         fullStarts++;
     }
-    
+
     return true;
 }
 
-inline void Solver::performStepsBeforeSolve()
+/**
+@brief Performs a set of pre-optimisations before the beggining of solving
+
+This is somewhat different than the set of optimisations carried out during
+solving in simplifyProblem(). For instance, binary xors are searched fully
+here, while there, no search for them is carried out. Also, the ordering
+is different.
+
+\todo experiment to use simplifyProblem() instead of this, with the only
+addition of binary clause search. Maybe it will do just as good (or better).
+*/
+void Solver::performStepsBeforeSolve()
 {
     assert(qhead == trail.size());
     testAllClauseAttach();
 
-    if (performReplace && !varReplacer->performReplace()) return;
+    printRestartStat();
+    if (conf.doReplace && !varReplacer->performReplace()) return;
 
-    if (doSubsumption && !subsumer->simplifyBySubsumption(true)) {
-        return;
-    }
+    if (conf.doClausVivif && !conf.libraryUsage
+        && !clauseVivifier->vivifyClauses()) return;
 
-    if (performReplace) {
-        OnlyNonLearntBins onlyNonLearntBins(*this);
-        if (!onlyNonLearntBins.fill()) return;
-        if (regularRemoveUselessBins) {
-            UselessBinRemover uselessBinRemover(*this, onlyNonLearntBins);
-            if (!uselessBinRemover.removeUslessBinFull()) return;
-        }
-        if (subsumeWithNonExistBinaries
-            && !subsumer->subsumeWithBinaries(&onlyNonLearntBins)) return;
-    }
+    bool saveDoHyperBin = conf.doHyperBinRes;
+    conf.doHyperBinRes = false;
+    if (conf.doFailedLit && !failedLitSearcher->search()) return;
+    conf.doHyperBinRes = saveDoHyperBin;
 
-    if (doSubsumption
-        && !libraryUsage
-        && clauses.size() + binaryClauses.size() + learnts.size() < 4800000
+    #ifdef VERBOSE_DEBUG
+    printAllClauses();
+    #endif //VERBOSE_DEBUG
+    if (conf.doSatELite
+        && !conf.libraryUsage
+        && clauses.size() < 4800000
         && !subsumer->simplifyBySubsumption())
         return;
 
-    /*
-    if (conflicts == 0 && learnts.size() == 0
-        && noLearntBinaries()) {
-        if (subsumeWithNonExistBinaries && !subsumer->subsumeWithBinaries(true)) return;
-        OnlyNonLearntBins onlyNonLearntBins(*this);
-        if (!onlyNonLearntBins.fill()) return;
-        if (regularRemoveUselessBins) {
-            UselessBinRemover uselessBinRemover(*this, onlyNonLearntBins);
-            if (!uselessBinRemover.removeUslessBinFull()) return;
-        }
+    if (conf.doFindEqLits) {
+        if (!sCCFinder->find2LongXors()) return;
+        lastNbBin = numNewBin;
+        if (conf.doReplace && !varReplacer->performReplace(true)) return;
     }
-    */
 
-    if (findBinaryXors && binaryClauses.size() < MAX_CLAUSENUM_XORFIND) {
-        XorFinder xorFinder(*this, binaryClauses, ClauseCleaner::binaryClauses);
-        if (!xorFinder.doNoPart(2, 2)) return;
-        if (performReplace && !varReplacer->performReplace(true)) return;
+    if (conf.doFindXors && clauses.size() < MAX_CLAUSENUM_XORFIND) {
+        XorFinder xorFinder(*this, clauses);
+        if (!xorFinder.fullFindXors(3, 7)) return;
     }
 
-    if (findNormalXors && clauses.size() < MAX_CLAUSENUM_XORFIND) {
-        XorFinder xorFinder(*this, clauses, ClauseCleaner::clauses);
-        if (!xorFinder.doNoPart(3, 7)) return;
-    }
-    
     if (xorclauses.size() > 1) {
-        testAllClauseAttach();
-        if (doXorSubsumption && !xorSubsumer->simplifyBySubsumption())
+        if (conf.doXorSubsumption && !xorSubsumer->simplifyBySubsumption())
             return;
-        
-        testAllClauseAttach();
-        if (performReplace && !varReplacer->performReplace())
+
+        if (conf.doReplace && !varReplacer->performReplace())
             return;
     }
-}
 
-void Solver::checkSolution()
-{
-    // Extend & check:
-    model.growTo(nVars());
-    for (Var var = 0; var != nVars(); var++) model[var] = value(var);
-    verifyModel();
-    model.clear();
+    if (conf.doSortWatched) sortWatched();
+    if (conf.doCacheOTFSSR && conf.doCalcReach) calcReachability();
+
+    testAllClauseAttach();
 }
 
-lbool Solver::solve(const vec<Lit>& assumps)
+/**
+@brief Initialises model, restarts, learnt cluause cleaning, burst-search, etc.
+*/
+void Solver::initialiseSolver()
 {
-#ifdef VERBOSE_DEBUG
-    std::cout << "Solver::solve() called" << std::endl;
-#endif
-    if (!ok) return l_False;
-    assert(qhead == trail.size());
-    
-    if (libraryCNFFile)
-        fprintf(libraryCNFFile, "c Solver::solve() called\n");
-    
+    //Clear up previous stuff like model, final conflict, matrixes
     model.clear();
     conflict.clear();
-    #ifdef USE_GAUSS
     clearGaussMatrixes();
-    #endif //USE_GAUSS
+
+    //Initialise restarts & dynamic restart datastructures
     setDefaultRestartType();
-    totalSumOfDecisionLevel = 0;
-    conflictsAtLastSolve = conflicts;
+
+    //Initialise avg. branch depth
     #ifdef RANDOM_LOOKAROUND_SEARCHSPACE
-    avgBranchDepth.fastclear();
+    avgBranchDepth.clear();
     avgBranchDepth.initSize(500);
     #endif //RANDOM_LOOKAROUND_SEARCHSPACE
-    starts = 0;
 
-    assumps.copyTo(assumptions);
+    //Initialise number of restarts&full restarts
+    starts = 0;
+    fullStarts = 0;
 
-    int  nof_conflicts = restart_first;
-    int  nof_conflicts_fullrestart = restart_first * FULLRESTART_MULTIPLIER + conflicts;
-    //nof_conflicts_fullrestart = -1;
-    uint    lastFullRestart  = starts;
-    lbool   status        = l_Undef;
-    uint64_t nextSimplify = restart_first * SIMPLIFY_MULTIPLIER + conflicts;
-    
-    if (nClauses() * learntsize_factor < nbclausesbeforereduce) {
-        if (nClauses() * learntsize_factor < nbclausesbeforereduce/2)
-            nbclausesbeforereduce = nbclausesbeforereduce/4;
+    if (nClauses() * conf.learntsize_factor < nbClBeforeRed) {
+        if (nClauses() * conf.learntsize_factor < nbClBeforeRed/2)
+            nbClBeforeRed /= 4;
         else
-            nbclausesbeforereduce = (nClauses() * learntsize_factor)/2;
+            nbClBeforeRed = (nClauses() * conf.learntsize_factor)/2;
     }
+
     testAllClauseAttach();
     findAllAttach();
-    
+}
+
+/**
+@brief The main solve loop that glues everything together
+
+We clear everything needed, pre-simplify the problem, calculate default
+polarities, and start the loop. Finally, we either report UNSAT or extend the
+found solution with all the intermediary simplifications (e.g. variable
+elimination, etc.) and output the solution.
+*/
+lbool Solver::solve(const vec<Lit>& assumps)
+{
+    #ifdef VERBOSE_DEBUG
+    std::cout << "Solver::solve() called" << std::endl;
+    #endif
+    if (!ok) return l_False;
+    assert(qhead == trail.size());
+    assert(subsumer->checkElimedUnassigned());
+    assert(xorSubsumer->checkElimedUnassigned());
+
+    if (libraryCNFFile)
+        fprintf(libraryCNFFile, "c Solver::solve() called\n");
+
+    assumps.copyTo(assumptions);
+    initialiseSolver();
+    uint64_t  nof_conflicts = conf.restart_first; //Geometric restart policy, start with this many
+    uint64_t  nof_conflicts_fullrestart = conf.restart_first * FULLRESTART_MULTIPLIER + conflicts; //at this point, do a full restart
+    uint32_t  lastFullRestart = starts; //last time a full restart was made was at this number of restarts
+    lbool     status = l_Undef; //Current status
+    uint64_t  nextSimplify = conf.restart_first * conf.simpStartMult + conflicts; //Do simplifyProblem() at this number of conflicts
+    if (!conf.doSchedSimp) nextSimplify = std::numeric_limits<uint64_t>::max();
+
     if (conflicts == 0) {
-        performStepsBeforeSolve();
+        if (conf.doPerformPreSimp) performStepsBeforeSolve();
         if (!ok) return l_False;
-    
-        printStatHeader();
     }
     calculateDefaultPolarities();
-    
+
+    printStatHeader();
+    printRestartStat("B");
+    uint64_t lastConflPrint = conflicts;
     // Search:
-    while (status == l_Undef && starts < maxRestarts) {
+    while (status == l_Undef && starts < conf.maxRestarts) {
         #ifdef DEBUG_VARELIM
         assert(subsumer->checkElimedUnassigned());
         assert(xorSubsumer->checkElimedUnassigned());
         #endif //DEBUG_VARELIM
-        
-        if (schedSimplification && conflicts >= nextSimplify) {
-            status = simplifyProblem(500);
-            nextSimplify = conflicts * 1.5;
+
+        if ((conflicts - lastConflPrint) > std::min(std::max(conflicts/100*6, (uint64_t)4000), (uint64_t)20000)) {
+            printRestartStat("N");
+            lastConflPrint = conflicts;
+        }
+
+        if (conf.doSchedSimp && conflicts >= nextSimplify) {
+            status = simplifyProblem(conf.simpBurstSConf);
+            printRestartStat();
+            lastConflPrint = conflicts;
+            nextSimplify = std::min((uint64_t)((double)conflicts * conf.simpStartMMult), conflicts + MAX_CONFL_BETWEEN_SIMPLIFY);
             if (status != l_Undef) break;
         }
-        
-        printRestartStat();
+
         #ifdef STATS_NEEDED
         if (dynamic_behaviour_analysis) {
             logger.end(Logger::restarting);
             logger.begin();
         }
         #endif
-        
-        status = search(nof_conflicts, nof_conflicts_fullrestart);
-        nof_conflicts = (double)nof_conflicts * restart_inc;
+
+        status = search(nof_conflicts, std::min(nof_conflicts_fullrestart, nextSimplify));
+        if (needToInterrupt) {
+            cancelUntil(0);
+            return l_Undef;
+        }
+
+        nof_conflicts = (double)nof_conflicts * conf.restart_inc;
         if (status != l_Undef) break;
-        if (!checkFullRestart(nof_conflicts, nof_conflicts_fullrestart, lastFullRestart))
+        if (!checkFullRestart(nof_conflicts, nof_conflicts_fullrestart , lastFullRestart))
             return l_False;
         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();
-    
-    #ifdef USE_GAUSS
-    for (uint i = 0; i < gauss_matrixes.size(); i++)
-        delete gauss_matrixes[i];
-    gauss_matrixes.clear();
-    #endif //USE_GAUSS
 
-#ifdef VERBOSE_DEBUG
+    #ifdef VERBOSE_DEBUG
     if (status == l_True)
         std::cout << "Solution  is SAT" << std::endl;
     else if (status == l_False)
         std::cout << "Solution is UNSAT" << std::endl;
     else
         std::cout << "Solutions is UNKNOWN" << std::endl;
-#endif //VERBOSE_DEBUG
-
-    if (status == l_True) {
-        if (greedyUnbound) {
-            double time = cpuTime();
-            FindUndef finder(*this);
-            const uint unbounded = finder.unRoll();
-            if (verbosity >= 1)
-                printf("c Greedy unbounding     :%5.2lf s, unbounded: %7d vars\n", cpuTime()-time, unbounded);
-        }
+    #endif //VERBOSE_DEBUG
+
+    if (status == l_True) handleSATSolution();
+    else if (status == l_False) handleUNSATSolution();
 
-        partHandler->addSavedState();
-        varReplacer->extendModelPossible();
-#ifndef NDEBUG
-        //checkSolution();
-#endif
-        
-        if (subsumer->getNumElimed() || xorSubsumer->getNumElimed()) {
-            if (verbosity >= 1) {
-                std::cout << "c Solution needs extension. Extending." << std::endl;
-            }
-            Solver s;
-            s.doSubsumption = false;
-            s.performReplace = false;
-            s.findBinaryXors = false;
-            s.findNormalXors = false;
-            s.failedVarSearch = false;
-            s.conglomerateXors = false;
-            s.subsumeWithNonExistBinaries = false;
-            s.regularSubsumeWithNonExistBinaries = false;
-            s.removeUselessBins = false;
-            s.regularRemoveUselessBins = false;
-            s.greedyUnbound = greedyUnbound;
-            for (Var var = 0; var < nVars(); var++) {
-                s.newVar(decision_var[var] || subsumer->getVarElimed()[var] || varReplacer->varHasBeenReplaced(var) || xorSubsumer->getVarElimed()[var]);
-                
-                //assert(!(xorSubsumer->getVarElimed()[var] && (decision_var[var] || subsumer->getVarElimed()[var] || varReplacer->varHasBeenReplaced(var))));
-                
-                if (value(var) != l_Undef) {
-                    vec<Lit> tmp;
-                    tmp.push(Lit(var, value(var) == l_False));
-                    s.addClause(tmp);
-                }
-            }
-            varReplacer->extendModelImpossible(s);
-            subsumer->extendModel(s);
-            xorSubsumer->extendModel(s);
-            
-            status = s.solve();
-            if (status != l_True) {
-                printf("c ERROR! Extension of model failed!\n");
-                assert(status == l_True);
-                exit(-1);
-            }
-#ifdef VERBOSE_DEBUG
-            std::cout << "Solution extending finished." << std::endl;
-#endif
-            for (Var var = 0; var < nVars(); var++) {
-                if (assigns[var] == l_Undef && s.model[var] != l_Undef) uncheckedEnqueue(Lit(var, s.model[var] == l_False));
-            }
-            ok = (propagate().isNULL());
-            if (!ok) {
-                printf("c ERROR! Extension of model failed!\n");
-                assert(ok);
-                exit(-1);
-            }
-        }
-#ifndef NDEBUG
-        //checkSolution();
-#endif
-        //Copy model:
-        model.growTo(nVars());
-        for (Var var = 0; var != nVars(); var++) model[var] = value(var);
-    }
-    
-    if (status == l_False) {
-        if (conflict.size() == 0)
-            ok = false;
-    }
-    
     #ifdef STATS_NEEDED
     if (dynamic_behaviour_analysis) {
         if (status == l_True)
             logger.end(Logger::model_found);
         else if (status == l_False)
-                logger.end(Logger::unsat_model_found);
+            logger.end(Logger::unsat_model_found);
         else if (status == l_Undef)
             logger.end(Logger::restarting);
     }
     #endif
-    
-    #ifdef LS_STATS_NBBUMP
-    for(int i=0;i<learnts.size();i++)
-        printf("## %d %d %d\n", learnts[i]->size(),learnts[i]->activity(),
-               (uint)learnts[i]->nbBump());
-    #endif
 
     cancelUntil(0);
-    if (doPartHandler && status != l_False) partHandler->readdRemovedClauses();
+    if (conf.doPartHandler && status != l_False) partHandler->readdRemovedClauses();
     restartTypeChooser->reset();
-    
-#ifdef VERBOSE_DEBUG
-    std::cout << "Solver::solve() finished" << std::endl;
-#endif
-    return status;
-}
-
-//=================================================================================================
-// Debug methods:
 
-bool Solver::verifyXorClauses(const vec<XorClause*>& cs) const
-{
-    #ifdef VERBOSE_DEBUG
-    cout << "Checking xor-clauses whether they have been properly satisfied." << endl;;
-    #endif
-    
-    bool failed = false;
-    
-    for (uint32_t i = 0; i != xorclauses.size(); i++) {
-        XorClause& c = *xorclauses[i];
-        bool final = c.xor_clause_inverted();
-        
-        #ifdef VERBOSE_DEBUG
-        XorClause* c2 = XorClause_new(c, c.xor_clause_inverted(), c.getGroup());
-        std::sort(c2->getData(), c2->getData()+ c2->size());
-        c2->plainPrint();
-        clauseFree(c2);
-        #endif
-        
-        for (uint j = 0; j < c.size(); j++) {
-            assert(modelValue(c[j].unsign()) != l_Undef);
-            final ^= (modelValue(c[j].unsign()) == l_True);
-        }
-        if (!final) {
-            printf("unsatisfied clause: ");
-            xorclauses[i]->plainPrint();
-            failed = true;
-        }
-    }
-    
-    return failed;
-}
-
-bool Solver::verifyClauses(const vec<Clause*>& cs) const
-{
     #ifdef VERBOSE_DEBUG
-    cout << "Checking clauses whether they have been properly satisfied." << endl;;
-    #endif
-    
-    bool failed = false;
-    
-    for (uint32_t i = 0; i != cs.size(); i++) {
-        Clause& c = *cs[i];
-        for (uint j = 0; j < c.size(); j++)
-            if (modelValue(c[j]) == l_True)
-                goto next;
-            
-        printf("unsatisfied clause: ");
-        cs[i]->plainPrint();
-        failed = true;
-    next:
-        ;
-    }
-    
-    return failed;
-}
-
-void Solver::verifyModel()
-{
-    assert(!verifyClauses(clauses));
-    assert(!verifyClauses(binaryClauses));
-    assert(!verifyXorClauses(xorclauses));
-
-    if (verbosity >=1)
-        printf("c Verified %d clauses.\n", clauses.size() + xorclauses.size());
-}
-
-
-void Solver::checkLiteralCount()
-{
-    // Check that sizes are calculated correctly:
-    int cnt = 0;
-    for (uint32_t i = 0; i != clauses.size(); i++)
-        cnt += clauses[i]->size();
-
-    for (uint32_t i = 0; i != xorclauses.size(); i++)
-        cnt += xorclauses[i]->size();
-
-    if ((int)clauses_literals != cnt) {
-        fprintf(stderr, "literal count: %d, real value = %d\n", (int)clauses_literals, cnt);
-        assert((int)clauses_literals == cnt);
-    }
-}
-
-void Solver::printStatHeader() const
-{
-    #ifdef STATS_NEEDED
-    if (verbosity >= 1 && !(dynamic_behaviour_analysis && logger.statistics_on)) {
-    #else
-    if (verbosity >= 1) {
+    std::cout << "Solver::solve() finished" << std::endl;
     #endif
-        printf("c ============================[ Search Statistics ]========================================\n");
-        printf("c | Conflicts |          ORIGINAL         |          LEARNT          |        GAUSS       |\n");
-        printf("c |           |    Vars  Clauses Literals |    Limit  Clauses Lit/Cl | Prop   Confl   On  |\n");
-        printf("c =========================================================================================\n");
-    }
+    return status;
 }
 
-void Solver::printRestartStat()
-{
-    if (verbosity >= 2) {
-        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
-}
+/**
+@brief Extends a SAT solution to the full solution
 
-void Solver::printEndSearchStat()
+variable elimination, variable replacement, sub-part solving, etc. all need to
+be handled correctly to arrive at a solution that is a solution to ALL of the
+original problem, not just of what remained of it at the end inside this class
+(i.e. we need to combine things from the helper classes)
+*/
+void Solver::handleSATSolution()
 {
-    #ifdef STATS_NEEDED
-    if (verbosity >= 1 && !(dynamic_behaviour_analysis && logger.statistics_on)) {
-    #else
-    if (verbosity >= 1) {
-    #endif //STATS_NEEDED
-        printf("c ====================================================================");
-        #ifdef USE_GAUSS
-        print_gauss_sum_stats();
-        if (verbosity == 1) printf("=====================\n");
-        #else //USE_GAUSS
-        printf("\n");
-        #endif //USE_GAUSS
-    }
-}
 
-#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));
+    /*if (greedyUnbound) {
+        double time = cpuTime();
+        FindUndef finder(*this);
+        const uint32_t unbounded = finder.unRoll();
+        if (conf.verbosity >= 1)
+            printf("c Greedy unbounding     :%5.2lf s, unbounded: %7d vars\n", cpuTime()-time, unbounded);
+    }*/
+    assert(subsumer->checkElimedUnassigned());
+    assert(xorSubsumer->checkElimedUnassigned());
+
+    partHandler->addSavedState();
+    varReplacer->extendModelPossible();
+    checkSolution();
+
+    if (subsumer->getNumElimed() || xorSubsumer->getNumElimed()) {
+        if (conf.verbosity >= 1) {
+            std::cout << "c Solution needs extension. Extending." << std::endl;
         }
-    }
-    
-    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);
+        Solver s;
+        s.conf = conf;
+        s.conf.doSatELite = false;
+        s.conf.doReplace = false;
+        s.conf.doFindEqLits = false;
+        s.conf.doRegFindEqLits = false;
+        s.conf.doFailedLit= false;
+        s.conf.doConglXors = false;
+        s.conf.doSubsWNonExistBins = false;
+        s.conf.doRemUselessBins = false;
+        s.conf.doClausVivif = false;
+        s.conf.doPartHandler = false;
+        s.conf.doSortWatched = false;
+        s.conf.verbosity = 0;
+
+        vec<Lit> tmp;
+        for (Var var = 0; var < nVars(); var++) {
+            s.newVar(decision_var[var] || subsumer->getVarElimed()[var] || varReplacer->varHasBeenReplaced(var) || xorSubsumer->getVarElimed()[var]);
+
+            //assert(!(xorSubsumer->getVarElimed()[var] && (decision_var[var] || subsumer->getVarElimed()[var] || varReplacer->varHasBeenReplaced(var))));
+
+            if (value(var) != l_Undef) {
+                #ifdef VERBOSE_DEBUG
+                std::cout << "Setting var " << var + 1
+                << " in extend-solver to " << value(var) << std::endl;
+                #endif
+                tmp.clear();
+                tmp.push(Lit(var, value(var) == l_False));
+                s.addClause(tmp);
             }
         }
-    }
-}
-
-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));
-        }
-    }
+        varReplacer->extendModelImpossible(s);
+        subsumer->extendModel(s);
+        xorSubsumer->extendModel(s);
 
-    for (uint32_t i = 0; i < xorwatches.size(); i++) {
-        for (uint32_t i2 = 0; i2 < xorwatches[i].size(); i2++) {
-            assert(findClause(xorwatches[i][i2]));
+        lbool status = s.solve();
+        release_assert(status == l_True && "c ERROR! Extension of model failed!");
+#ifdef VERBOSE_DEBUG
+        std::cout << "Solution extending finished. Enqueuing results" << std::endl;
+#endif
+        for (Var var = 0; var < nVars(); var++) {
+            if (assigns[var] == l_Undef && s.model[var] != l_Undef) uncheckedEnqueue(Lit(var, s.model[var] == l_False));
         }
+        ok = (propagate().isNULL());
+        release_assert(ok && "c ERROR! Extension of model failed!");
     }
+    checkSolution();
+    //Copy model:
+    model.growTo(nVars());
+    for (Var var = 0; var != nVars(); var++) model[var] = value(var);
 }
 
-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<Clause*> cs = varReplacer->getClauses();
-    for (uint32_t i = 0; i < cs.size(); i++) {
-        if (cs[i] == c) return true;
-    }
-    
-    return false;
-}
-#endif //DEBUG_ATTACH
+/**
+@brief When problem is decided to be UNSAT, this is called
 
-const bool Solver::noLearntBinaries() const
+There is basically nothing to be handled for the moment, but this could be
+made extensible
+*/
+void Solver::handleUNSATSolution()
 {
-    for (uint32_t i = 0; i < binaryClauses.size(); i++) {
-        if (binaryClauses[i]->learnt()) return false;
-    }
-
-    return true;
+    if (conflict.size() == 0)
+        ok = false;
 }
-
-}; //NAMESPACE MINISAT
index 75daea63fbb2691cee87f1cdf28937e12ebace85..97d291a92822f01b81fd4c513803fa5daaa64583 100644 (file)
@@ -25,27 +25,40 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
 #include <cstdio>
 #include <string.h>
 #include <stdio.h>
+#include <stack>
+
 #ifdef _MSC_VER
 #include <msvc/stdint.h>
 #else
 #include <stdint.h>
 #endif //_MSC_VER
 
-#include "time_mem.h"
+#ifdef STATS_NEEDED
+#include "Logger.h"
+#endif //STATS_NEEDED
+
+
+#include "PropBy.h"
 #include "Vec.h"
 #include "Heap.h"
 #include "Alg.h"
-#include "MersenneTwister.h"
+#include "MTRand/MersenneTwister.h"
 #include "SolverTypes.h"
 #include "Clause.h"
-#include "Logger.h"
 #include "constants.h"
 #include "BoundedQueue.h"
 #include "GaussianConfig.h"
-
-namespace MINISAT
-{
-using namespace MINISAT;
+#include "ClauseAllocator.h"
+#include "SolverConf.h"
+
+#define release_assert(a) \
+    do { \
+        if (!(a)) {\
+            fprintf(stderr, "*** ASSERTION FAILURE in %s() [%s:%d]: %s\n", \
+            __FUNCTION__, __FILE__, __LINE__, #a); \
+            abort(); \
+        } \
+    } while (0)
 
 class Gaussian;
 class MatrixFinder;
@@ -54,13 +67,22 @@ class VarReplacer;
 class XorFinder;
 class FindUndef;
 class ClauseCleaner;
-class FailedVarSearcher;
+class FailedLitSearcher;
 class Subsumer;
 class XorSubsumer;
 class PartHandler;
 class RestartTypeChooser;
 class StateSaver;
 class UselessBinRemover;
+class SCCFinder;
+class ClauseVivifier;
+class SharedData;
+class DataSync;
+
+namespace BEEV
+{
+  class CryptoMinisat;
+}
 
 #ifdef VERBOSE_DEBUG
 #define DEBUG_UNCHECKEDENQUEUE_LEVEL0
@@ -81,197 +103,85 @@ struct reduceDB_ltGlucose
     bool operator () (const Clause* x, const Clause* y);
 };
 
-//#define DEBUG_PROPAGATEFROM
-
-class PropagatedFrom
-{
-    private:
-        union {Clause* clause; uint32_t otherLit;};
-        
-    public:
-        PropagatedFrom(Clause* c)
-        {
-            #ifdef DEBUG_PROPAGATEFROM
-            assert(c != NULL);
-            #endif
-            clause = c;
-        }
-
-        PropagatedFrom(const Lit& _other)
-        {
-            otherLit = _other.toInt() << 1;
-            otherLit |= 1;
-        }
-
-        PropagatedFrom() :
-            clause(NULL)
-        {
-        }
-
-        const bool isBinary() const
-        {
-            return (otherLit&1);
-        }
-
-        const Lit getOtherLit() const
-        {
-            #ifdef DEBUG_PROPAGATEFROM
-            assert(isBinary());
-            #endif
-            return Lit::toLit(otherLit>>1);
-        }
-
-        const Clause* getClause() const
-        {
-            #ifdef DEBUG_PROPAGATEFROM
-            assert(!isBinary());
-            #endif
-            return clause;
-        }
-
-        Clause* getClause()
-        {
-            return clause;
-        }
-
-        const bool isNULL() const
-        {
-            if (isBinary()) return false;
-            return clause == NULL;
-        }
-
-        const uint32_t size() const
-        {
-            if (isBinary()) return 2;
-            
-            #ifdef DEBUG_PROPAGATEFROM
-            assert(!isNULL());
-            #endif
-            
-            return getClause()->size();
-        }
+/**
+@brief The main solver class
 
-        const Lit operator[](uint32_t i) const
-        {
-            if (isBinary()) {
-                #ifdef DEBUG_PROPAGATEFROM
-                assert(i == 1);
-                #endif
-                return getOtherLit();
-            }
-
-            #ifdef DEBUG_PROPAGATEFROM
-            assert(!isNULL());
-            #endif
-            return (*getClause())[i];
-        }
-};
+This class creates and manages all the others. It is here that settings must
+be set, and it is here that all data enter and leaves the system. The basic
+use is to add normal and XOR clauses, and then solve(). The solver will then
+solve the problem, and return with either a SAT solution with corresponding
+variable settings, or report that the problem in UNSATisfiable.
 
+The prolbem-solving can be interrupted with the "interrupt" varible, and can
+also be pre-set to stop after a certain number of restarts. The data until the
+interruption can be dumped by previously setting parameters like
+dumpSortedLearnts
+*/
 class Solver
 {
 public:
+    friend class BEEV::CryptoMinisat;
 
     // Constructor/Destructor:
     //
-    Solver();
+    Solver(const SolverConf& conf = SolverConf(), const GaussConf& _gaussconfig = GaussConf(), SharedData* sharedUnitData = NULL);
     ~Solver();
 
     // Problem specification:
     //
-    Var     newVar    (bool dvar = true); // Add a new variable with parameters specifying variable mode.
+    Var     newVar    (bool dvar = true);           // Add a new variable with parameters specifying variable mode.
+    template<class T>
+    bool    addClause (T& ps, const uint32_t group = 0, const char* group_name = NULL);  // Add a clause to the solver. NOTE! 'ps' may be shrunk by this method!
     template<class T>
-    bool    addClause (T& ps, const uint group = 0, char* group_name = NULL);  // Add a clause to the solver. NOTE! 'ps' may be shrunk by this method!
+    bool    addLearntClause(T& ps, const uint32_t group = 0, const char* group_name = NULL, const uint32_t glue = 10, const float miniSatActivity = 10.0);
     template<class T>
-    bool    addXorClause (T& ps, bool xor_clause_inverted, const uint group = 0, char* group_name = NULL);  // Add a xor-clause to the solver. NOTE! 'ps' may be shrunk by this method!
+    bool    addXorClause (T& ps, bool xorEqualFalse, const uint32_t group = 0, const char* group_name = NULL);  // Add a xor-clause to the solver. NOTE! 'ps' may be shrunk by this method!
 
     // Solving:
     //
-    lbool    solve       (const vec<Lit>& assumps); // Search for a model that respects a given set of assumptions.
-    lbool    solve       ();                        // Search without assumptions.
-    bool    okay         () const;                  // FALSE means solver is in a conflicting state
+    lbool    solve       (const vec<Lit>& assumps); ///<Search for a model that respects a given set of assumptions.
+    lbool    solve       ();                        ///<Search without assumptions.
+    void     handleSATSolution();                   ///<Extends model, if needed, and fills "model"
+    void     handleUNSATSolution();                 ///<If conflict really was zero-length, sets OK to false
+    bool     okay         () const;                 ///<FALSE means solver is in a conflicting state
 
     // Variable mode:
     //
-    void    setPolarity    (Var v, bool b); // Declare which polarity the decision heuristic should use for a variable. Requires mode 'polarity_user'.
-    void    setDecisionVar (Var v, bool b); // Declare if a variable should be eligible for selection in the decision heuristic.
-    void    setSeed (const uint32_t seed);  // Sets the seed to be the given number
-    void    setMaxRestarts(const uint num); //sets the maximum number of restarts to given value
+    void    setDecisionVar (Var v, bool b);         ///<Declare if a variable should be eligible for selection in the decision heuristic.
 
     // Read state:
     //
-    lbool   value      (const Var& x) const;       // The current value of a variable.
-    lbool   value      (const Lit& p) const;       // The current value of a literal.
-    lbool   modelValue (const Lit& p) const;       // The value of a literal in the last model. The last call to solve must have been satisfiable.
-    uint32_t     nAssigns   ()      const;       // The current number of assigned literals.
-    uint32_t     nClauses   ()      const;       // The current number of original clauses.
-    uint32_t     nLiterals  ()      const;       // The current number of total literals.
-    uint32_t     nLearnts   ()      const;       // The current number of learnt clauses.
-    uint32_t     nVars      ()      const;       // The current number of variables.
+    lbool   value      (const Var x) const;       ///<The current value of a variable.
+    lbool   value      (const Lit p) const;       ///<The current value of a literal.
+    lbool   modelValue (const Lit p) const;       ///<The value of a literal in the last model. The last call to solve must have been satisfiable.
+    uint32_t     nAssigns   ()      const;         ///<The current number of assigned literals.
+    uint32_t     nClauses   ()      const;         ///<The current number of original clauses.
+    uint32_t     nLiterals  ()      const;         ///<The current number of total literals.
+    uint32_t     nLearnts   ()      const;         ///<The current number of learnt clauses.
+    uint32_t     nVars      ()      const;         ///<The current number of variables.
 
     // Extra results: (read-only member variable)
     //
-    vec<lbool> model;             // If problem is satisfiable, this vector contains the model (if any).
-    vec<Lit>   conflict;          // If problem is unsatisfiable (possibly under assumptions),
-    // this vector represent the final conflict clause expressed in the assumptions.
+    vec<lbool> model;             ///<If problem is satisfiable, this vector contains the model (if any).
+    vec<Lit>   conflict;          ///<If problem is unsatisfiable (possibly under assumptions), this vector represent the final conflict clause expressed in the assumptions.
 
     // Mode of operation:
     //
-    double    random_var_freq;    // The frequency with which the decision heuristic tries to choose a random variable.        (default 0.02)
-    double    clause_decay;       // Inverse of the clause activity decay factor.                                              (1 / 0.999)
-    int       restart_first;      // The initial restart limit.                                                                (default 100)
-    double    restart_inc;        // The factor with which the restart limit is multiplied in each restart.                    (default 1.5)
-    double    learntsize_factor;  // The intitial limit for learnt clauses is a factor of the original clauses.                (default 1 / 3)
-    double    learntsize_inc;     // The limit for learnt clauses is multiplied with this factor each restart.                 (default 1.1)
-    bool      expensive_ccmin;    // Controls conflict clause minimization.                                                    (default TRUE)
-    int       polarity_mode;      // Controls which polarity the decision heuristic chooses. See enum below for allowed modes. (default polarity_false)
-    int       verbosity;          // Verbosity level. 0=silent, 1=some progress report                                         (default 0)
-    Var       restrictedPickBranch; // Pick variables to branch on preferentally from the highest [0, restrictedPickBranch]. If set to 0, preferentiality is turned off (i.e. picked randomly between [0, all])
-    bool      findNormalXors;     // Automatically find non-binary xor-clauses and convert them
-    bool      findBinaryXors;     // Automatically find binary xor-clauses and convert them
-    bool      regularlyFindBinaryXors; // Regularly find binary xor-clauses and convert them
-    bool      performReplace;       // Should var-replacing be performed?
-    bool      conglomerateXors;   // Conglomerate XORs
-    bool      heuleProcess;       // Process XORs according to Heule
-    bool      schedSimplification;// Schedule simplification
-    bool      doSubsumption;        // Should try to subsume clauses
-    bool      doXorSubsumption;     // Should try to subsume xor clauses
-    bool      doPartHandler;        // Should try to subsume clauses
-    bool      doHyperBinRes;        // Should try carry out hyper-binary resolution
-    bool      doBlockedClause;      // Should try to remove blocked clauses
-    bool      doVarElim;            // Perform variable elimination
-    bool      doSubsume1;           // Perform clause contraction through resolution
-    bool      failedVarSearch;      // Should search for failed vars and doulbly propagated vars
-    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)
-    RestartType fixRestartType;     // If set, the solver will always choose the given restart strategy
-    GaussianConfig gaussconfig;
-    
-
-    enum { polarity_true = 0, polarity_false = 1, polarity_rnd = 3, polarity_auto = 4};
-
-    // Statistics: (read-only member variable)
-    //
-    uint64_t starts, dynStarts, staticStarts, fullStarts, decisions, rnd_decisions, propagations, conflicts;
-    uint64_t clauses_literals, learnts_literals, max_literals, tot_literals;
-    uint64_t nbDL2, nbBin, lastNbBin, becameBinary, lastSearchForBinaryXor, nbReduceDB;
-    uint64_t improvedClauseNo, improvedClauseSize;
+    SolverConf conf;
+    GaussConf gaussconfig;   ///<Configuration for the gaussian elimination can be set here
+    bool      needToInterrupt;    ///<Used internally mostly. If set to TRUE, we will interrupt cleanly ASAP. The important thing is "cleanly", since we need to wait until a point when all datastructures are in a sane state (i.e. not in the middle of some algorithm)
 
     //Logging
     void needStats();              // Prepares the solver to output statistics
     void needProofGraph();         // Prepares the solver to output proof graphs during solving
-    void setVariableName(Var var, char* name); // Sets the name of the variable 'var' to 'name'. Useful for statistics and proof logs (i.e. used by 'logger')
+    void setVariableName(const Var var, const char* name); // Sets the name of the variable 'var' to 'name'. Useful for statistics and proof logs (i.e. used by 'logger')
     const vec<Clause*>& get_sorted_learnts(); //return the set of learned clauses, sorted according to the logic used in MiniSat to distinguish between 'good' and 'bad' clauses
     const vec<Clause*>& get_learnts() const; //Get all learnt clauses that are >1 long
     const vector<Lit> get_unitary_learnts() const; //return the set of unitary learnt clauses
-    const uint get_unitary_learnts_num() const; //return the number of unitary learnt clauses
-    void 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.
+    const uint32_t get_unitary_learnts_num() const; //return the number of unitary learnt clauses
+    void dumpSortedLearnts(const std::string& fileName, const uint32_t maxSize); // Dumps all learnt clauses (including unitary ones) into the file
+    void needLibraryCNFFile(const std::string& fileName); //creates file in current directory with the filename indicated, and puts all calls from the library into the file.
+    void dumpOrigClauses(const std::string& fileName) const;
 
     #ifdef USE_GAUSS
     const uint32_t get_sum_gauss_called() const;
@@ -281,44 +191,96 @@ public:
     #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
+    void printStats();
+    const uint32_t getNumElimSubsume() const;       ///<Get number of variables eliminated
+    const uint32_t getNumElimXorSubsume() const;    ///<Get number of variables eliminated with xor-magic
+    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
+    /**
+    @brief Get total time spent in Subsumer.
+
+    This includes: subsumption, self-subsuming resolution, variable elimination,
+    blocked clause elimination, subsumption and self-subsuming resolution
+    using non-existent binary clauses.
+    */
     const double getTotalTimeSubsumer() const;
-    const double getTotalTimeXorSubsumer() const;
-    
+    const double getTotalTimeFailedLitSearcher() const;
+    const double getTotalTimeSCC() const;
+
+    /**
+    @brief Get total time spent in XorSubsumer.
+
+    This included subsumption, variable elimination through XOR, and local
+    substitution (see Heule's Thesis)
+    */
+    const double   getTotalTimeXorSubsumer() const;
+
 protected:
+    //gauss
+    const bool clearGaussMatrixes();
+    vector<Gaussian*> gauss_matrixes;
     #ifdef USE_GAUSS
     void print_gauss_sum_stats();
-    void clearGaussMatrixes();
-    vector<Gaussian*> gauss_matrixes;
-
-    //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 <class T>
-    Clause* addClauseInt(T& ps, uint group);
-    template<class T>
-    XorClause* addXorClauseInt(T& ps, bool xor_clause_inverted, const uint32_t group);
-    template<class T>
-    bool addLearntClause(T& ps, const uint group, const uint32_t activity);
-    template<class T>
-    void    removeWatchedCl(vec<T> &ws, const ClauseOffset c);
-    template<class T>
-    bool    findWatchedCl(const vec<T>& ws, const ClauseOffset c) const;
-    template<class T>
-    void    removeWatchedBinCl(vec<T> &ws, const Lit impliedLit);
-    template<class T>
-    void    removeWatchedBinClAll(vec<T> &ws, const Lit impliedLit);
+
+    // Statistics
+    //
+    template<class T, class T2>
+    void printStatsLine(std::string left, T value, T2 value2, std::string extra);
     template<class T>
-    bool    findWatchedBinCl(const vec<T>& ws, const Lit impliedLit) const;
-    
+    void printStatsLine(std::string left, T value, std::string extra = "");
+    uint64_t starts; ///<Num restarts
+    uint64_t dynStarts; ///<Num dynamic restarts
+    uint64_t staticStarts; ///<Num static restarts: note that after full restart, we do a couple of static restarts always
+    /**
+    @brief Num full restarts
+
+    Full restarts are restarts that are made always, no matter what, after
+    a certan number of conflicts have passed. The problem will tried to be
+    decomposed into multiple parts, and then there will be a couple of static
+    restarts made. Finally, the problem will be determined to be MiniSat-type
+    or Glucose-type.
+
+    NOTE: I belive there is a point in having full restarts even if the
+    glue-clause vs. MiniSat clause can be fully resolved
+    */
+    uint64_t fullStarts;    ///<Number of full restarts made
+    uint64_t decisions;     ///<Number of decisions made
+    uint64_t rnd_decisions; ///<Numer of random decisions made
+    /**
+    @brief An approximation of accumulated propagation difficulty
+
+    It does not hold the number of propagations made. Rather, it holds a
+    value that is approximate of the difficulty of the propagations made
+    This makes sense, since it is not at all the same difficulty to proapgate
+    a 2-long clause than to propagate a 20-long clause. In certain algorihtms,
+    there is a need to know how difficult the propagation part was. This value
+    can be used in these algorihms. However, the reported "statistic" will be
+    bogus.
+    */
+    uint64_t propagations;
+    uint64_t conflicts; ///<Num conflicts
+    uint64_t clauses_literals, learnts_literals, max_literals, tot_literals;
+    uint64_t nbGlue2; ///<Num learnt clauses that had a glue of 2 when created
+    uint64_t numNewBin; ///<new binary clauses that have been found through some form of resolution (shrinking, conflicts, etc.)
+    uint64_t lastNbBin; ///<Last time we seached for SCCs, numBins was this much
+    uint64_t lastSearchForBinaryXor; ///<Last time we looked for binary xors, this many bogoprops(=propagations) has been done
+    uint64_t nbReduceDB; ///<Number of times learnt clause have been cleaned
+    uint64_t improvedClauseNo; ///<Num clauses improved using on-the-fly subsumption
+    uint64_t improvedClauseSize; ///<Num literals removed using on-the-fly subsumption
+    uint64_t numShrinkedClause; ///<Num clauses improved using on-the-fly self-subsuming resolution
+    uint64_t numShrinkedClauseLits; ///<Num literals removed by on-the-fly self-subsuming resolution
+    uint64_t moreRecurMinLDo; ///<Decided to carry out transitive on-the-fly self-subsuming resolution on this many clauses
+    uint64_t updateTransCache; ///<Number of times the transitive OTF-reduction cache has been updated
+    uint64_t nbClOverMaxGlue; ///<Number or clauses over maximum glue defined in maxGlue
+
+    //Multi-threading
+    DataSync* dataSync;
+
     // Helper structures:
     //
     struct VarOrderLt {
@@ -329,7 +291,6 @@ protected:
         VarOrderLt(const vec<uint32_t>&  act) : activity(act) { }
     };
 
-    friend class VarFilter;
     struct VarFilter {
         const Solver& s;
         VarFilter(const Solver& _s) : s(_s) {}
@@ -340,134 +301,192 @@ protected:
 
     // Solver state:
     //
-    bool                ok;               // If FALSE, the constraints are already unsatisfiable. No part of the solver state may be used!
-    ClauseAllocator     clauseAllocator;
-    vec<Clause*>        clauses;          // List of problem clauses.
-    vec<Clause*>        binaryClauses;    // Binary clauses are regularly moved here
-    vec<XorClause*>     xorclauses;       // List of problem xor-clauses. Will be freed
-    vec<Clause*>        learnts;          // List of learnt clauses.
-    vec<XorClause*>     freeLater;        // xor clauses that need to be freed later due to Gauss
-    vec<uint32_t>       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
-    vec<vec<Watched> >  watches;          // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true).
-    vec<vec<ClauseOffset> > xorwatches;   // 'xorwatches[var]' is a list of constraints watching var in XOR clauses.
-    vec<vec<WatchedBin> >  binwatches;
-    vec<lbool>          assigns;          // The current assignments
-    vector<bool>        polarity;         // The preferred polarity of each variable.
-    #ifdef USE_OLD_POLARITIES
-    vector<bool>        oldPolarity;      // The polarity before the last setting. Good for unsetting polairties that have been changed since the last conflict
-    #endif //USE_OLD_POLARITIES
-    vector<bool>        decision_var;     // Declares if a variable is eligible for selection in the decision heuristic.
-    vec<Lit>            trail;            // Assignment stack; stores all assigments made in the order they were made.
-    vec<uint32_t>       trail_lim;        // Separator indices for different decision levels in 'trail'.
-    vec<PropagatedFrom> reason;           // 'reason[var]' is the clause that implied the variables current value, or 'NULL' if none.
-    vec<int32_t>        level;            // 'level[var]' contains the level at which the assignment was made.
-    uint64_t            curRestart;
-    uint32_t            nbclausesbeforereduce;
-    uint32_t            nbCompensateSubsumer; // Number of learnt clauses that subsumed normal clauses last time subs. was executed
-    uint32_t            qhead;            // Head of queue (as index into the trail -- no more explicit propagation queue in MiniSat).
-    Lit                 failBinLit;
-    uint32_t            simpDB_assigns;   // Number of top-level assignments since last execution of 'simplify()'.
-    int64_t             simpDB_props;     // Remaining number of propagations that must be made before next execution of 'simplify()'.
-    vec<Lit>            assumptions;      // Current set of assumptions provided to solve by the user.
-    Heap<VarOrderLt>    order_heap;       // A priority queue of variables ordered with respect to the variable activity.
-    double              progress_estimate;// Set by 'search()'.
-    bool                remove_satisfied; // Indicates whether possibly inefficient linear scan for satisfied clauses should be performed in 'simplify'.
-    bqueue<uint>        nbDecisionLevelHistory; // Set of last decision level in conflict clauses
-    double              totalSumOfDecisionLevel;
-    uint64_t            conflictsAtLastSolve;
+    bool                ok;               ///< If FALSE, the constraints are already unsatisfiable. No part of the solver state may be used!
+    ClauseAllocator     clauseAllocator;  ///< Handles memory allocation for claues
+    vec<Clause*>        clauses;          ///< List of problem clauses that are normally larger than 2. Sometimes, due to on-the-fly self-subsuming resoulution, clauses here become 2-long. They are never purposfully put here such that they are long
+    vec<XorClause*>     xorclauses;       ///< List of problem xor-clauses. Will be freed
+    vec<Clause*>        learnts;          ///< List of learnt clauses.
+    uint32_t            numBins;
+    vec<XorClause*>     freeLater;        ///< xor clauses that need to be freed later (this is needed due to Gauss) \todo Get rid of this
+    float               cla_inc;          ///< Amount to bump learnt clause oldActivity with
+    vec<vec<Watched> >  watches;          ///< 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true).
+    vec<lbool>          assigns;          ///< The current assignments
+    vector<bool>        decision_var;     ///< Declares if a variable is eligible for selection in the decision heuristic.
+    vec<Lit>            trail;            ///< Assignment stack; stores all assigments made in the order they were made.
+    vec<uint32_t>       trail_lim;        ///< Separator indices for different decision levels in 'trail'.
+    vec<PropBy>         reason;           ///< 'reason[var]' is the clause that implied the variables current value, or 'NULL' if none.
+    vec<int32_t>        level;            ///< 'level[var]' contains the level at which the assignment was made.
+    vec<BinPropData>    binPropData;
+    uint32_t            qhead;            ///< Head of queue (as index into the trail)
+    Lit                 failBinLit;       ///< Used to store which watches[~lit] we were looking through when conflict occured
+    vec<Lit>            assumptions;      ///< Current set of assumptions provided to solve by the user.
     #ifdef RANDOM_LOOKAROUND_SEARCHSPACE
-    bqueue<uint>        avgBranchDepth; // Avg branch depth
+    bqueue<uint32_t>    avgBranchDepth;   ///< Avg branch depth. We collect this, and use it to do random look-around in the searchspace during simplifyProblem()
     #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
-    friend class        Logger;
-    #ifdef STATS_NEEDED
-    Logger logger;                        // dynamic logging, statistics
-    bool                dynamic_behaviour_analysis; // Is logger running?
+    MTRand              mtrand;           ///< random number generator
+
+    /////////////////
+    // Variable activities
+    /////////////////
+    Heap<VarOrderLt>    order_heap;       ///< A priority queue of variables ordered with respect to the variable activity. All variables here MUST be decision variables. If you changed the decision variables, you MUST filter this
+    vec<uint32_t>       activity;         ///< A heuristic measurement of the activity of a variable.
+    uint32_t            var_inc;          ///< Amount to bump next variable with.
+
+    /////////////////
+    // Learnt clause cleaning
+    /////////////////
+    uint64_t  numCleanedLearnts;    ///< Number of times learnt clauses have been removed through simplify() up until now
+    uint32_t  nbClBeforeRed;        ///< Number of learnt clauses before learnt-clause cleaning
+    uint32_t  nbCompensateSubsumer; ///< Number of learnt clauses that subsumed normal clauses last time subs. was executed (used to delay learnt clause-cleaning)
+
+    /////////////////////////
+    // For glue calculation & dynamic restarts
+    /////////////////////////
+    uint64_t            MYFLAG; ///<For glue calculation
+    template<class T>
+    const uint32_t      calcNBLevels(const T& ps);
+    vec<uint64_t>       permDiff;  ///<permDiff[var] is used to count the number of different decision level variables in learnt clause (filled with data from MYFLAG )
+    #ifdef UPDATE_VAR_ACTIVITY_BASED_ON_GLUE
+    vec<Var>            lastDecisionLevel;
     #endif
-    uint                maxRestarts;      // More than this number of restarts will not be performed
+    bqueue<uint32_t>    glueHistory;  ///< Set of last decision levels in (glue of) conflict clauses. Used for dynamic restarting
+    vec<Clause*>        unWindGlue;
 
     // Temporaries (to reduce allocation overhead). Each variable is prefixed by the method in which it is
     // used, exept 'seen' wich is used in several places.
     //
-    vector<bool>        seen;
+    vector<bool>        seen; ///<Used in multiple places. Contains 2 * numVars() elements, all zeroed out
     vec<Lit>            analyze_stack;
     vec<Lit>            analyze_toclear;
-    vec<Lit>            add_tmp;
-
-    
-    uint64_t MYFLAG;
-    template<class T>
-    const uint32_t calcNBLevels(const T& ps);
-    vec<uint64_t> 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<Var> lastDecisionLevel;
-    #endif
 
+    ////////////
+    // Transitive on-the-fly self-subsuming resolution
+    ///////////
+    class TransCache {
+        public:
+            TransCache() :
+                conflictLastUpdated(std::numeric_limits<uint64_t>::max())
+            {};
+
+            vector<Lit> lits;
+            uint64_t conflictLastUpdated;
+    };
+    class LitReachData {
+        public:
+            LitReachData() :
+                lit(lit_Undef)
+                , numInCache(0)
+            {}
+            Lit lit;
+            uint32_t numInCache;
+    };
+    vector<bool>        seen2;            ///<To reduce temoprary data creation overhead. Used in minimiseLeartFurther(). contains 2 * numVars() elements, all zeroed out
+    vec<Lit>            allAddedToSeen2;  ///<To reduce temoprary data creation overhead. Used in minimiseLeartFurther()
+    std::stack<Lit>     toRecursiveProp;  ///<To reduce temoprary data creation overhead. Used in minimiseLeartFurther()
+    vector<TransCache>  transOTFCache;
+    bqueue<uint32_t>    conflSizeHist;
+    void                minimiseLeartFurther(vec<Lit>& cl, const uint32_t glue);
+    void                transMinimAndUpdateCache(const Lit lit, uint32_t& moreRecurProp);
+    void                saveOTFData();
+    vector<LitReachData>litReachable;
+    void                calcReachability();
+
+    ////////////
     //Logging
-    uint                learnt_clause_group; //the group number of learnt clauses. Incremented at each added learnt clause
-    FILE                *libraryCNFFile; //The file that all calls from the library are logged
+    ///////////
+    #ifdef STATS_NEEDED
+    Logger   logger;                     // dynamic logging, statistics
+    bool     dynamic_behaviour_analysis; // Is logger running?
+    #endif
+    uint32_t learnt_clause_group;       //the group number of learnt clauses. Incremented at each added learnt clause
+    FILE     *libraryCNFFile;           //The file that all calls from the library are logged
 
-    // Main internal methods:
-    //
-    const bool simplify    ();                                                           // Removes already satisfied clauses.
-    //int      nbPropagated     (int level);
-    void     insertVarOrder   (Var x);                                                 // Insert a variable in the decision order priority queue.
+    /////////////////
+    // Propagating
+    ////////////////
     Lit      pickBranchLit    ();                                                      // Return the next decision variable.
     void     newDecisionLevel ();                                                      // Begins a new decision level.
-    void     uncheckedEnqueue (const Lit p, const PropagatedFrom& from = PropagatedFrom());                 // Enqueue a literal. Assumes value of literal is undefined.
+    void     uncheckedEnqueue (const Lit p, const PropBy& from = PropBy()); // Enqueue a literal. Assumes value of literal is undefined.
     void     uncheckedEnqueueLight (const Lit p);
-    bool     enqueue          (Lit p, PropagatedFrom from = PropagatedFrom());                            // Test if fact 'p' contradicts current state, enqueue otherwise.
-    PropagatedFrom  propagate (const bool update = true);                         // Perform unit propagation. Returns possibly conflicting clause.
-    PropagatedFrom  propagateBin();
-    PropagatedFrom  propagateBinNoLearnts();
-    template<bool dontCareLearnt>
-    PropagatedFrom  propagateBinExcept(const Lit& exceptLit);
-    template<bool dontCareLearnt>
-    PropagatedFrom  propagateBinOneLevel();
-    PropagatedFrom  propagate_xors   (const Lit& p);
+    void     uncheckedEnqueueLight2(const Lit p, const uint32_t binPropDatael, const Lit lev2Ancestor, const bool learntLeadHere);
+    PropBy   propagateBin(vec<Lit>& uselessBin);
+    PropBy   propagateNonLearntBin();
+    bool     multiLevelProp;
+    const bool propagateBinExcept(const Lit exceptLit);
+    const bool propagateBinOneLevel();
+    PropBy   propagate(const bool update = true); // Perform unit propagation. Returns possibly conflicting clause.
+    const bool propTriClause   (Watched* &i, Watched* &j, Watched *end, const Lit p, PropBy& confl);
+    const bool propBinaryClause(Watched* &i, Watched* &j, Watched *end, const Lit p, PropBy& confl);
+    const bool propNormalClause(Watched* &i, Watched* &j, Watched *end, const Lit p, PropBy& confl, const bool update);
+    const bool propXorClause   (Watched* &i, Watched* &j, Watched *end, const Lit p, PropBy& confl);
+    void     sortWatched();
+
+    ///////////////
+    // Conflicting
+    ///////////////
     void     cancelUntil      (int level);                                             // Backtrack until a certain level.
-    Clause*  analyze          (PropagatedFrom confl, vec<Lit>& out_learnt, int& out_btlevel, uint32_t &nblevels, const bool update); // (bt = backtrack)
+    void     cancelUntilLight();
+    Clause*  analyze          (PropBy confl, vec<Lit>& out_learnt, int& out_btlevel, uint32_t &nblevels, const bool update);
     void     analyzeFinal     (Lit p, vec<Lit>& out_conflict);                         // COULD THIS BE IMPLEMENTED BY THE ORDINARIY "analyze" BY SOME REASONABLE GENERALIZATION?
     bool     litRedundant     (Lit p, uint32_t abstract_levels);                       // (helper method for 'analyze()')
-    lbool    search           (int nof_conflicts, int nof_conflicts_fullrestart, const bool update = true);      // Search for a given number of conflicts.
-    void     reduceDB         ();                                                      // Reduce the set of learnt clauses.
-    llbool   handle_conflict  (vec<Lit>& learnt_clause, PropagatedFrom confl, int& conflictC, const bool update);// Handles the conflict clause
-    llbool   new_decision     (const int& nof_conflicts, const int& nof_conflicts_fullrestart, int& conflictC);  // Handles the case when all propagations have been made, and now a decision must be made
+    void     insertVarOrder   (Var x);                                                 // Insert a variable in the decision order priority queue.
 
+    /////////////////
+    // Searching
+    /////////////////
+    lbool    search           (const uint64_t nof_conflicts, const uint64_t nof_conflicts_fullrestart, const bool update = true);      // Search for a given number of conflicts.
+    llbool   handle_conflict  (vec<Lit>& learnt_clause, PropBy confl, uint64_t& conflictC, const bool update);// Handles the conflict clause
+    llbool   new_decision     (const uint64_t nof_conflicts, const uint64_t nof_conflicts_fullrestart, const uint64_t conflictC);  // Handles the case when all propagations have been made, and now a decision must be made
+
+    /////////////////
     // Maintaining Variable/Clause activity:
-    //
+    /////////////////
     void     claBumpActivity (Clause& c);
     void     varDecayActivity ();                      // Decay all variables with the specified factor. Implemented by increasing the 'bump' value instead.
     void     varBumpActivity  (Var v);                 // Increase a variable with the current 'bump' value.
     void     claDecayActivity ();                      // Decay all clauses with the specified factor. Implemented by increasing the 'bump' value instead.
 
+    /////////////////
     // Operations on clauses:
-    //
-    void     attachClause     (XorClause& c);
-    void     attachClause     (Clause& c);             // Attach a clause to watcher lists.
-    void     detachClause     (const XorClause& c);
-    void     detachClause     (const Clause& c);       // Detach a clause to watcher lists.
-    void     detachModifiedClause(const Lit lit1, const Lit lit2, const uint size, const Clause* address);
-    void     detachModifiedClause(const Var var1, const Var var2, const uint origSize, const XorClause* address);
+    /////////////////
+    template<class T> const bool addClauseHelper(T& ps, const uint32_t group, const char* group_name);
+    template <class T>
+    Clause*    addClauseInt(T& ps, uint32_t group, const bool learnt = false, const uint32_t glue = 10, const float miniSatActivity = 10.0, const bool inOriginalInput = false);
+    template<class T>
+    XorClause* addXorClauseInt(T& ps, bool xorEqualFalse, const uint32_t group, const bool learnt = false);
+    void       attachBinClause(const Lit lit1, const Lit lit2, const bool learnt);
+    void       attachClause     (XorClause& c);
+    void       attachClause     (Clause& c);             // Attach a clause to watcher lists.
+    void       detachClause     (const XorClause& c);
+    void       detachClause     (const Clause& c);       // Detach a clause to watcher lists.
+    void       detachModifiedClause(const Lit lit1, const Lit lit2, const Lit lit3, const uint32_t origSize, const Clause* address);
+    void       detachModifiedClause(const Var var1, const Var var2, const uint32_t origSize, const XorClause* address);
     template<class T>
-    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;
+    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.
+
+    ///////////////////////////
+    // Debug clause attachment
+    ///////////////////////////
+    void       testAllClauseAttach() const;
+    void       findAllAttach() const;
     const bool findClause(XorClause* c) const;
     const bool findClause(Clause* c) const;
+    const bool xorClauseIsAttached(const XorClause& c) const;
+    const bool normClauseIsAttached(const Clause& c) const;
 
     // Misc:
     //
     uint32_t decisionLevel    ()      const; // Gives the current decisionlevel.
-    uint32_t abstractLevel    (const Var& x) const; // Used to represent an abstraction of sets of decision levels.
-    
-    //Xor-finding related stuff
+    uint32_t abstractLevel    (const Var x) const; // Used to represent an abstraction of sets of decision levels.
+
+    /////////////////////////
+    //Classes that must be friends, since they accomplish things on our datastructures
+    /////////////////////////
+    friend class VarFilter;
+    friend class Gaussian;
+    friend class FindUndef;
+    friend class Logger;
     friend class XorFinder;
     friend class Conglomerate;
     friend class MatrixFinder;
@@ -475,7 +494,7 @@ protected:
     friend class VarReplacer;
     friend class ClauseCleaner;
     friend class RestartTypeChooser;
-    friend class FailedVarSearcher;
+    friend class FailedLitSearcher;
     friend class Subsumer;
     friend class XorSubsumer;
     friend class PartHandler;
@@ -483,40 +502,81 @@ protected:
     friend class UselessBinRemover;
     friend class OnlyNonLearntBins;
     friend class ClauseAllocator;
-    Conglomerate* conglomerate;
-    VarReplacer* varReplacer;
-    ClauseCleaner* clauseCleaner;
-    FailedVarSearcher* failedVarSearcher;
-    PartHandler* partHandler;
-    Subsumer* subsumer;
-    XorSubsumer* xorSubsumer;
+    friend class CompleteDetachReatacher;
+    friend class SCCFinder;
+    friend class ClauseVivifier;
+    friend class DataSync;
+    Conglomerate*       conglomerate;
+    VarReplacer*        varReplacer;
+    ClauseCleaner*      clauseCleaner;
+    FailedLitSearcher*  failedLitSearcher;
+    PartHandler*        partHandler;
+    Subsumer*           subsumer;
+    XorSubsumer*        xorSubsumer;
     RestartTypeChooser* restartTypeChooser;
-    MatrixFinder* matrixFinder;
-    const bool chooseRestartType(const uint& lastFullRestart);
-    void setDefaultRestartType();
-    const bool checkFullRestart(int& nof_conflicts, int& nof_conflicts_fullrestart, uint& lastFullRestart);
-    void performStepsBeforeSolve();
+    MatrixFinder*       matrixFinder;
+    SCCFinder*          sCCFinder;
+    ClauseVivifier*     clauseVivifier;
+
+    /////////////////////////
+    // Restart type handling
+    /////////////////////////
+    const bool  chooseRestartType(const uint32_t& lastFullRestart);
+    void        setDefaultRestartType();
+    const bool  checkFullRestart(uint64_t& nof_conflicts, uint64_t& nof_conflicts_fullrestart, uint32_t& lastFullRestart);
+    RestartType restartType;             ///<Used internally to determine which restart strategy is currently in use
+    RestartType lastSelectedRestartType; ///<The last selected restart type. Used when we are just after a full restart, and need to know how to really act
+
+    //////////////////////////
+    // Problem simplification
+    //////////////////////////
+    void        performStepsBeforeSolve();
     const lbool simplifyProblem(const uint32_t numConfls);
-    bool simplifying;
+    void        reduceDB();       // Reduce the set of learnt clauses.
+    const bool  simplify();       // Removes satisfied clauses and finds binary xors
+    bool        simplifying;      ///<We are currently doing burst search
+    double      totalSimplifyTime;
+    uint32_t    simpDB_assigns;   ///< Number of top-level assignments since last execution of 'simplify()'.
+    int64_t     simpDB_props;     ///< Remaining number of propagations that must be made before next execution of 'simplify()'.
+
+    /////////////////////////////
+    // SAT solution verification
+    /////////////////////////////
+    void       checkSolution    ();
+    const bool verifyModel      () const;
+    const bool verifyBinClauses() const;
+    const bool verifyClauses    (const vec<Clause*>& cs) const;
+    const bool verifyXorClauses () const;
 
     // Debug & etc:
+    void     printAllClauses();
     void     printLit         (const Lit l) const;
-    void     verifyModel      ();
-    bool     verifyClauses    (const vec<Clause*>& cs) const;
-    bool     verifyXorClauses (const vec<XorClause*>& cs) const;
-    void     checkSolution();
     void     checkLiteralCount();
     void     printStatHeader  () const;
-    void     printRestartStat ();
+    void     printRestartStat (const char* type = "N");
     void     printEndSearchStat();
-    double   progressEstimate () const; // DELETE THIS ?? IT'S NOT VERY USEFUL ...
-    const bool noLearntBinaries() const;
-    
+    void     addSymmBreakClauses();
+    void     initialiseSolver();
+
+    //Misc related binary clauses
+    void     dumpBinClauses(const bool alsoLearnt, const bool alsoNonLearnt, FILE* outfile) const;
+    const uint32_t countNumBinClauses(const bool alsoLearnt, const bool alsoNonLearnt) const;
+    const uint32_t getBinWatchSize(const bool alsoLearnt, const Lit lit);
+    void  printStrangeBinLit(const Lit lit) const;
+
+    /////////////////////
     // Polarity chooser
+    /////////////////////
     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<Clause*>& cs, vector<double>& votes) const;
-    void tallyVotes(const vec<XorClause*>& cs, vector<double>& votes) const;
+    void tallyVotesBin(vec<double>& votes) const;
+    void tallyVotes(const vec<Clause*>& cs, vec<double>& votes) const;
+    void tallyVotes(const vec<XorClause*>& cs, vec<double>& votes) const;
+    void setPolarity(Var v, bool b); // Declare which polarity the decision heuristic should use for a variable. Requires mode 'polarity_user'.
+    vector<bool> polarity;      // The preferred polarity of each variable.
+    #ifdef USE_OLD_POLARITIES
+    vector<bool> oldPolarity;   // The polarity before the last setting. Good for unsetting polairties that have been changed since the last conflict
+    #endif //USE_OLD_POLARITIES
 };
 
 
@@ -546,7 +606,7 @@ inline void Solver::varBumpActivity(Var v)
         var_inc >>= 14;
         //var_inc = 1;
         //std::cout << "var_inc: " << var_inc << std::endl;
-        
+
         /*Heap<VarOrderLt> copy_order_heap2(order_heap);
         while(!copy_order_heap2.empty()) {
             Var v = copy_order_heap2.getmin();
@@ -562,10 +622,10 @@ inline void Solver::varBumpActivity(Var v)
 
 inline void Solver::claBumpActivity (Clause& c)
 {
-    if ( (c.oldActivity() += cla_inc) > 1e20 ) {
+    if ( (c.getMiniSatAct() += cla_inc) > 1e20 ) {
         // Rescale:
         for (uint32_t i = 0; i < learnts.size(); i++)
-            learnts[i]->oldActivity() *= 1e-17;
+            learnts[i]->getMiniSatAct() *= 1e-17;
         cla_inc *= 1e-20;
     }
 }
@@ -575,16 +635,13 @@ inline void Solver::claDecayActivity()
     //cla_inc *= clause_decay;
 }
 
-inline bool     Solver::enqueue         (Lit p, PropagatedFrom from)
+inline bool Solver::locked(const Clause& c) const
 {
-    return value(p) != l_Undef ? value(p) != l_False : (uncheckedEnqueue(p, from), true);
-}
-inline bool     Solver::locked          (const Clause& c) const
-{
-    if (c.size() == 2) return true; //we don't know in this case :I
-    PropagatedFrom from(reason[c[0].var()]);
-    return !from.isBinary() && from.getClause() == &c && value(c[0]) == l_True;
+    if (c.size() <= 3) return true; //we don't know in this case :I
+    PropBy from(reason[c[0].var()]);
+    return from.isClause() && !from.isNULL() && from.getClause() == clauseAllocator.getOffset(&c) && value(c[0]) == l_True;
 }
+
 inline void     Solver::newDecisionLevel()
 {
     trail_lim.push(trail.size());
@@ -601,19 +658,19 @@ inline uint32_t      Solver::decisionLevel ()      const
 {
     return trail_lim.size();
 }
-inline uint32_t Solver::abstractLevel (const Var& x) const
+inline uint32_t Solver::abstractLevel (const Var x) const
 {
     return 1 << (level[x] & 31);
 }
-inline lbool    Solver::value         (const Var& x) const
+inline lbool    Solver::value         (const Var x) const
 {
     return assigns[x];
 }
-inline lbool    Solver::value         (const Lit& p) const
+inline lbool    Solver::value         (const Lit p) const
 {
     return assigns[p.var()] ^ p.sign();
 }
-inline lbool    Solver::modelValue    (const Lit& p) const
+inline lbool    Solver::modelValue    (const Lit p) const
 {
     return model[p.var()] ^ p.sign();
 }
@@ -623,7 +680,7 @@ inline uint32_t      Solver::nAssigns      ()      const
 }
 inline uint32_t      Solver::nClauses      ()      const
 {
-    return clauses.size() + xorclauses.size()+binaryClauses.size();
+    return clauses.size() + xorclauses.size();
 }
 inline uint32_t      Solver::nLiterals      ()      const
 {
@@ -657,10 +714,6 @@ inline bool     Solver::okay          ()      const
 {
     return ok;
 }
-inline void     Solver::setSeed (const uint32_t seed)
-{
-    mtrand.seed(seed);    // Set seed of the variable-selection and clause-permutation(if applicable)
-}
 #ifdef STATS_NEEDED
 inline void     Solver::needStats()
 {
@@ -672,14 +725,14 @@ inline void     Solver::needProofGraph()
     dynamic_behaviour_analysis = true;    // Sets the solver and the logger up to generate proof graphs during solving
     logger.proof_graph_on = true;
 }
-inline void     Solver::setVariableName(Var var, char* name)
+inline void     Solver::setVariableName(const Var var, const char* name)
 {
     while (var >= nVars()) newVar();
     if (dynamic_behaviour_analysis)
         logger.set_variable_name(var, name);
 } // Sets the varible 'var'-s name to 'name' in the logger
 #else
-inline void     Solver::setVariableName(Var var, char* name)
+inline void     Solver::setVariableName(const Var var, const char* name)
 {}
 #endif
 
@@ -705,77 +758,33 @@ inline const uint32_t Solver::get_sum_gauss_prop() const
 }
 #endif
 
-inline const uint Solver::get_unitary_learnts_num() const
+inline const uint32_t Solver::get_unitary_learnts_num() const
 {
     if (decisionLevel() > 0)
         return trail_lim[0];
     else
         return trail.size();
 }
-template <class T>
-inline void Solver::removeWatchedCl(vec<T> &ws, const ClauseOffset c) {
-    uint32_t j = 0;
-    for (; j < ws.size() && ws[j].clause != c; j++);
-    assert(j < ws.size());
-    for (; j < ws.size()-1; j++) ws[j] = ws[j+1];
-    ws.pop();
-}
-template <class T>
-inline void Solver::removeWatchedBinCl(vec<T> &ws, const Lit impliedLit) {
-    uint32_t j = 0;
-    for (; j < ws.size() && ws[j].impliedLit != impliedLit; j++);
-    assert(j < ws.size());
-    for (; j < ws.size()-1; j++) ws[j] = ws[j+1];
-    ws.pop();
-}
-template <class T>
-inline void Solver::removeWatchedBinClAll(vec<T> &ws, const Lit impliedLit) {
-    T *i = ws.getData();
-    T *j = i;
-    for (T* end = ws.getDataEnd(); i != end; i++) {
-        if (i->impliedLit != impliedLit)
-            *j++ = *i;
-    }
-    ws.shrink(i-j);
-}
-template<class T>
-inline bool Solver::findWatchedCl(const vec<T>& ws, const ClauseOffset c) const
-{
-    uint32_t j = 0;
-    for (; j < ws.size() && ws[j].clause != c; j++);
-    return j < ws.size();
-}
-template<class T>
-inline bool Solver::findWatchedBinCl(const vec<T>& ws, const Lit impliedLit) const
-{
-    uint32_t j = 0;
-    for (; j < ws.size() && ws[j].impliedLit != impliedLit; j++);
-    return j < ws.size();
-}
 
-/*
-inline void Solver::reverse_binary_clause(Clause& c) const {
-    if (c.size() == 2 && value(c[0]) == l_False) {
-        assert(value(c[1]) == l_True);
-        std::swap(c[0], c[1]);
-    }
-}
-*/
+//////////////////
+// Xor Clause
+//////////////////
+
 
 /*inline void Solver::calculate_xor_clause(Clause& c2) const {
     if (c2.isXor() && ((XorClause*)&c2)->updateNeeded())  {
         XorClause& c = *((XorClause*)&c2);
-        bool final = c.xor_clause_inverted();
+        bool final = c.xorEqualFalse();
         for (int k = 0, size = c.size(); k != size; k++ ) {
             const lbool& val = assigns[c[k].var()];
             assert(val != l_Undef);
-            
+
             c[k] = c[k].unsign() ^ val.getBool();
             final ^= val.getBool();
         }
         if (final)
             c[0] = c[0].unsign() ^ !assigns[c[0].var()].getBool();
-        
+
         c.setUpdateNeeded(false);
     }
 }*/
@@ -808,19 +817,7 @@ static inline void logLits(FILE* f, const vec<Lit>& ls)
     fprintf(f, "] ");
 }
 
-static inline const char* showBool(bool b)
-{
-    return b ? "true" : "false";
-}
-
-
-// Just like 'assert()' but expression will be evaluated in the release version as well.
-static inline void check(bool expr)
-{
-    assert(expr);
-}
-
-#ifndef DEBUG_ATTACH
+#ifndef DEBUG_ATTACH_FULL
 inline void Solver::testAllClauseAttach() const
 {
     return;
@@ -829,16 +826,26 @@ inline void Solver::findAllAttach() const
 {
     return;
 }
-#endif //DEBUG_ATTACH
+#endif //DEBUG_ATTACH_FULL
 
 inline void Solver::uncheckedEnqueueLight(const Lit p)
 {
+    assert(assigns[p.var()] == l_Undef);
+
     assigns [p.var()] = boolToLBool(!p.sign());//lbool(!sign(p));  // <<== abstract but not uttermost effecient
     trail.push(p);
 }
 
-//=================================================================================================
+inline void Solver::uncheckedEnqueueLight2(const Lit p, const uint32_t binSubLevel, const Lit lev2Ancestor, const bool learntLeadHere)
+{
+    assert(assigns[p.var()] == l_Undef);
 
-}; //NAMESPACE MINISAT
+    assigns [p.var()] = boolToLBool(!p.sign());//lbool(!sign(p));  // <<== abstract but not uttermost effecient
+    trail.push(p);
+    binPropData[p.var()].lev = binSubLevel;
+    binPropData[p.var()].lev2Ancestor = lev2Ancestor;
+    binPropData[p.var()].learntLeadHere = learntLeadHere;
+}
 
+//=================================================================================================
 #endif //SOLVER_H
diff --git a/src/sat/cryptominisat2/SolverConf.cpp b/src/sat/cryptominisat2/SolverConf.cpp
new file mode 100644 (file)
index 0000000..b4d7eaf
--- /dev/null
@@ -0,0 +1,81 @@
+/*****************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+#include "SolverConf.h"
+#include <limits>
+
+SolverConf::SolverConf() :
+        random_var_freq(0.02)
+        , clause_decay (1 / 0.999)
+        , restart_first(100)
+        , restart_inc(1.5)
+        , learntsize_factor((double)1/(double)3)
+
+        , expensive_ccmin  (true)
+        , polarity_mode    (polarity_auto)
+        , verbosity        (0)
+        , restrictPickBranch(0)
+
+        //Simplification
+        , simpBurstSConf(NUM_CONFL_BURST_SEARCH)
+        , simpStartMult(SIMPLIFY_MULTIPLIER)
+        , simpStartMMult(SIMPLIFY_MULTIPLIER_MULTIPLIER)
+
+        , doPerformPreSimp (true)
+        , failedLitMultiplier(2.0)
+
+        //optimisations to do
+        , doFindXors       (true)
+        , doFindEqLits     (true)
+        , doRegFindEqLits  (true)
+        , doReplace        (true)
+        , doConglXors      (true)
+        , doHeuleProcess   (true)
+        , doSchedSimp      (true)
+        , doSatELite       (true)
+        , doXorSubsumption (true)
+        , doPartHandler    (true)
+        , doHyperBinRes    (true)
+        , doBlockedClause  (false)
+        , doVarElim        (true)
+        , doSubsume1       (true)
+        , doClausVivif     (true)
+        , doSortWatched    (true)
+        , doMinimLearntMore(true)
+        , doMinimLMoreRecur(true)
+        , doFailedLit      (true)
+        , doRemUselessBins (true)
+        , doSubsWBins      (true)
+        , doSubsWNonExistBins(true)
+        , doRemUselessLBins(true)
+        , doMaxGlueDel     (false)
+        , doPrintAvgBranch (false)
+        , doCacheOTFSSR    (true)
+        , doExtendedSCC    (true)
+        , doCalcReach      (true)
+
+        , maxRestarts      (std::numeric_limits<uint32_t>::max())
+        , needToDumpLearnts(false)
+        , needToDumpOrig   (false)
+        , maxDumpLearntsSize(std::numeric_limits<uint32_t>::max())
+        , libraryUsage     (true)
+        , greedyUnbound    (false)
+        , maxGlue          (DEFAULT_MAX_GLUE)
+        , fixRestartType   (auto_restart)
+        , origSeed(0)
+{
+}
diff --git a/src/sat/cryptominisat2/SolverConf.h b/src/sat/cryptominisat2/SolverConf.h
new file mode 100644 (file)
index 0000000..2abf702
--- /dev/null
@@ -0,0 +1,90 @@
+/*****************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+#ifndef SOLVERCONF_H
+#define SOLVERCONF_H
+
+#include "SolverTypes.h"
+#include "constants.h"
+
+class SolverConf
+{
+    public:
+        SolverConf();
+
+        double    random_var_freq;    ///<The frequency with which the decision heuristic tries to choose a random variable.        (default 0.02) NOTE: This is really strange. If the number of variables set is large, then the random chance is in fact _far_ lower than this value. This is because the algorithm tries to set one variable randomly, but if that variable is already set, then it _silently_ fails, and moves on (doing non-random flip)!
+        double    clause_decay;       ///<Inverse of the clause activity decay factor. Only applies if using MiniSat-style clause activities  (default: 1 / 0.999)
+        int       restart_first;      ///<The initial restart limit.                                                                (default 100)
+        double    restart_inc;        ///<The factor with which the restart limit is multiplied in each restart.                    (default 1.5)
+        double    learntsize_factor;  ///<The intitial limit for learnt clauses is a factor of the original clauses.                (default 1 / 3)
+        double    learntsize_inc;     ///<The limit for learnt clauses is multiplied with this factor each restart.                 (default 1.1)
+        bool      expensive_ccmin;    ///<Should clause minimisation by Sorensson&Biere be used?                                    (default TRUE)
+        int       polarity_mode;      ///<Controls which polarity the decision heuristic chooses. Auto means Jeroslow-Wang          (default: polarity_auto)
+        int       verbosity;          ///<Verbosity level. 0=silent, 1=some progress report, 2=lots of report, 3 = all report       (default 2)
+        Var       restrictPickBranch; ///<Pick variables to branch on preferentally from the highest [0, restrictedPickBranch]. If set to 0, preferentiality is turned off (i.e. picked randomly between [0, all])
+        uint32_t simpBurstSConf;
+        double simpStartMult;
+        double simpStartMMult;
+        bool doPerformPreSimp;
+        double failedLitMultiplier;
+
+        //Optimisations to do
+        bool      doFindXors;         ///<Automatically find non-binary xor clauses and convert them to xor clauses
+        bool      doFindEqLits;       ///<Automatically find binary xor clauses (i.e. variable equi- and antivalences)
+        bool      doRegFindEqLits;    ///<Regularly find binary xor clauses (i.e. variable equi- and antivalences)
+        bool      doReplace;          ///<Should var-replacing be performed? If set to FALSE, equi- and antivalent variables will not be replaced with one another. NOTE: This precludes using a lot of the algorithms!
+        bool      doConglXors;        ///<Do variable elimination at the XOR-level (xor-ing 2 xor clauses thereby removing a variable)
+        bool      doHeuleProcess;     ///<Perform local subsitutuion as per Heule's theis
+        bool      doSchedSimp;        ///<Should simplifyProblem() be scheduled regularly? (if set to FALSE, a lot of opmitisations are disabled)
+        bool      doSatELite;         ///<Should try to subsume & self-subsuming resolve & variable-eliminate & block-clause eliminate?
+        bool      doXorSubsumption;   ///<Should try to subsume & local-subsitute xor clauses
+        bool      doPartHandler;      ///<Should try to find disconnected components and solve them individually?
+        bool      doHyperBinRes;      ///<Should try carry out hyper-binary resolution
+        bool      doBlockedClause;    ///<Should try to remove blocked clauses
+        bool      doVarElim;          ///<Perform variable elimination
+        bool      doSubsume1;         ///<Perform self-subsuming resolution
+        bool      doClausVivif;      ///<Perform asymmetric branching at the beginning of the solving
+        bool      doSortWatched;      ///<Sort watchlists according to size&type: binary, tertiary, normal (>3-long), xor clauses
+        bool      doMinimLearntMore;  ///<Perform learnt-clause minimisation using watchists' binary and tertiary clauses? ("strong minimization" in PrecoSat)
+        bool      doMinimLMoreRecur;  ///<Always perform recursive/transitive on-the-fly self self-subsuming resolution --> an enhancement of "strong minimization" of PrecoSat
+        bool      doFailedLit;        ///<Carry out Failed literal probing + doubly propagated literal detection + 2-long xor clause detection during failed literal probing + hyper-binary resoolution
+        bool      doRemUselessBins;   ///<Should try to remove useless binary clauses at the beginning of solving?
+        bool      doSubsWBins;
+        bool      doSubsWNonExistBins;  ///<Try to do subsumption and self-subsuming resolution with non-existent binary clauses (i.e. binary clauses that don't exist but COULD exists)
+        bool      doRemUselessLBins; ///<Try to remove useless learnt binary clauses
+        bool      doMaxGlueDel;
+        bool      doPrintAvgBranch;
+        bool      doCacheOTFSSR;
+        bool      doExtendedSCC;
+        bool      doCalcReach; ///<Calculate reachability, and influence variable decisions with that
+
+        //interrupting & dumping
+        uint32_t  maxRestarts;
+        bool      needToDumpLearnts;  ///<If set to TRUE, learnt clauses will be dumped to the file speified by "learntsFilename"
+        bool      needToDumpOrig;     ///<If set to TRUE, a simplified version of the original clause-set will be dumped to the file speified by "origFilename". The solution to this file should perfectly satisfy the problem
+        std::string learntsFilename;    ///<Dump sorted learnt clauses to this file. Only active if "needToDumpLearnts" is set to TRUE
+        std::string origFilename;       ///<Dump simplified original problem CNF to this file. Only active if "needToDumpOrig" is set to TRUE
+        uint32_t  maxDumpLearntsSize; ///<When dumping the learnt clauses, this is the maximum clause size that should be dumped
+        bool      libraryUsage;       ///<Set to true if not used as a library. In fact, this is TRUE by default, and Main.cpp sets it to "FALSE". Disables some simplifications at the beginning of solving (mostly performStepsBeforeSolve() )
+        bool      greedyUnbound;      ///<If set, then variables will be greedily unbounded (set to l_Undef). This is EXPERIMENTAL
+        uint32_t  maxGlue;            ///< Learnt clauses (when doing dynamic restarts) with glue above this value will be removed immediately on backtracking
+        RestartType fixRestartType;   ///<If set, the solver will always choose the given restart strategy instead of automatically trying to guess a strategy. Note that even if set to dynamic_restart, there will be a few restarts made statically after each full restart.
+
+        uint32_t origSeed;
+};
+
+#endif //SOLVERCONF_H
diff --git a/src/sat/cryptominisat2/SolverDebug.cpp b/src/sat/cryptominisat2/SolverDebug.cpp
new file mode 100644 (file)
index 0000000..02e34ed
--- /dev/null
@@ -0,0 +1,253 @@
+/***************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+****************************************************************************/
+
+#include "Solver.h"
+
+#include "VarReplacer.h"
+
+#ifdef DEBUG_ATTACH_FULL
+void Solver::testAllClauseAttach() const
+{
+    for (Clause *const*it = clauses.getData(), *const*end = clauses.getDataEnd(); it != end; it++) {
+        const Clause& c = **it;
+        assert(normClauseIsAttached(c));
+    }
+
+    for (XorClause *const*it = xorclauses.getData(), *const*end = xorclauses.getDataEnd(); it != end; it++) {
+        const XorClause& c = **it;
+        assert(xorClauseIsAttached(c));
+    }
+}
+
+const bool Solver::normClauseIsAttached(const Clause& c) const
+{
+    bool attached = true;
+    assert(c.size() > 2);
+
+    ClauseOffset offset = clauseAllocator.getOffset(&c);
+    if (c.size() == 3) {
+        //The clause might have been longer, and has only recently
+        //became 3-long. Check, and detach accordingly
+        if (findWCl(watches[(~c[0]).toInt()], offset)) goto fullClause;
+
+        Lit lit1 = c[0];
+        Lit lit2 = c[1];
+        Lit lit3 = c[2];
+        attached &= findWTri(watches[(~lit1).toInt()], lit2, lit3);
+        attached &= findWTri(watches[(~lit2).toInt()], lit1, lit3);
+        attached &= findWTri(watches[(~lit3).toInt()], lit1, lit2);
+    } else {
+        fullClause:
+        attached &= findWCl(watches[(~c[0]).toInt()], offset);
+        attached &= findWCl(watches[(~c[1]).toInt()], offset);
+    }
+
+    return attached;
+}
+
+const bool Solver::xorClauseIsAttached(const XorClause& c) const
+{
+    ClauseOffset offset = clauseAllocator.getOffset(&c);
+    bool attached = true;
+    attached &= findWXCl(watches[(c[0]).toInt()], offset);
+    attached &= findWXCl(watches[(~c[0]).toInt()], offset);
+    attached &= findWXCl(watches[(c[1]).toInt()], offset);
+    attached &= findWXCl(watches[(~c[1]).toInt()], offset);
+
+    return attached;
+}
+
+void Solver::findAllAttach() const
+{
+    for (uint32_t i = 0; i < watches.size(); i++) {
+        for (uint32_t i2 = 0; i2 < watches[i].size(); i2++) {
+            const Watched& w = watches[i][i2];
+            if (w.isClause()) findClause(clauseAllocator.getPointer(w.getNormOffset()));
+            if (w.isXorClause()) findClause(clauseAllocator.getPointer(w.getXorOffset()));
+        }
+    }
+}
+
+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 < clauses.size(); i++) {
+        if (clauses[i] == c) return true;
+    }
+    for (uint32_t i = 0; i < learnts.size(); i++) {
+        if (learnts[i] == c) return true;
+    }
+
+    return false;
+}
+#endif //DEBUG_ATTACH_FULL
+
+void Solver::checkSolution()
+{
+    model.growTo(nVars());
+    for (Var var = 0; var != nVars(); var++) model[var] = value(var);
+    release_assert(verifyModel());
+    model.clear();
+}
+
+const bool Solver::verifyXorClauses() const
+{
+    #ifdef VERBOSE_DEBUG
+    cout << "Checking xor-clauses whether they have been properly satisfied." << endl;;
+    #endif
+
+    bool verificationOK = true;
+
+    for (uint32_t i = 0; i != xorclauses.size(); i++) {
+        XorClause& c = *xorclauses[i];
+        bool final = c.xorEqualFalse();
+
+        #ifdef VERBOSE_DEBUG
+        std::cout << "verifying xor clause: " << c << std::endl;
+        #endif
+
+        for (uint32_t j = 0; j < c.size(); j++) {
+            assert(modelValue(c[j].unsign()) != l_Undef);
+            final ^= (modelValue(c[j].unsign()) == l_True);
+        }
+        if (!final) {
+            printf("unsatisfied clause: ");
+            xorclauses[i]->plainPrint();
+            verificationOK = false;
+        }
+    }
+
+    return verificationOK;
+}
+
+const bool Solver::verifyBinClauses() const
+{
+    uint32_t wsLit = 0;
+    for (const vec<Watched> *it = watches.getData(), *end = watches.getDataEnd(); it != end; it++, wsLit++) {
+        Lit lit = ~Lit::toLit(wsLit);
+        const vec<Watched>& ws = *it;
+
+        uint32_t i;
+        for (i = 0; i < ws.size(); i++) {
+            if (ws[i].isBinary()
+                && value(lit) != l_True
+                && value(ws[i].getOtherLit()) != l_True
+            ) {
+                std::cout << "bin clause: " << lit << " , " << ws[i].getOtherLit() << " not satisfied!" << std::endl;
+                std::cout << "value of unsat bin clause: " << value(lit) << " , " << value(ws[i].getOtherLit()) << std::endl;
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+const bool Solver::verifyClauses(const vec<Clause*>& cs) const
+{
+    #ifdef VERBOSE_DEBUG
+    cout << "Checking clauses whether they have been properly satisfied." << endl;;
+    #endif
+
+    bool verificationOK = true;
+
+    for (uint32_t i = 0; i != cs.size(); i++) {
+        Clause& c = *cs[i];
+        for (uint32_t j = 0; j < c.size(); j++)
+            if (modelValue(c[j]) == l_True)
+                goto next;
+
+        printf("unsatisfied clause: ");
+        cs[i]->plainPrint();
+        verificationOK = false;
+        next:
+        ;
+    }
+
+    return verificationOK;
+}
+
+const bool Solver::verifyModel() const
+{
+    bool verificationOK = true;
+    verificationOK &= verifyClauses(clauses);
+    verificationOK &= verifyClauses(learnts);
+    verificationOK &= verifyBinClauses();
+    verificationOK &= verifyXorClauses();
+
+    if (conf.verbosity >=1 && verificationOK)
+        printf("c Verified %d clauses.\n", clauses.size() + xorclauses.size());
+
+    return verificationOK;
+}
+
+
+void Solver::checkLiteralCount()
+{
+    // Check that sizes are calculated correctly:
+    int cnt = 0;
+    for (uint32_t i = 0; i != clauses.size(); i++)
+        cnt += clauses[i]->size();
+
+    for (uint32_t i = 0; i != xorclauses.size(); i++)
+        cnt += xorclauses[i]->size();
+
+    if ((int)clauses_literals != cnt) {
+        fprintf(stderr, "literal count: %d, real value = %d\n", (int)clauses_literals, cnt);
+        assert((int)clauses_literals == cnt);
+    }
+}
+
+void Solver::printAllClauses()
+{
+    for (uint32_t i = 0; i < clauses.size(); i++) {
+        std::cout << "Normal clause num " << clauseAllocator.getOffset(clauses[i]) << " cl: " << *clauses[i] << std::endl;
+    }
+
+    for (uint32_t i = 0; i < xorclauses.size(); i++) {
+        std::cout << "xorclause num " << *xorclauses[i] << std::endl;
+    }
+
+    uint32_t wsLit = 0;
+    for (const vec<Watched> *it = watches.getData(), *end = watches.getDataEnd(); it != end; it++, wsLit++) {
+        Lit lit = ~Lit::toLit(wsLit);
+        const vec<Watched>& ws = *it;
+        std::cout << "watches[" << lit << "]" << std::endl;
+        for (const Watched *it2 = ws.getData(), *end2 = ws.getDataEnd(); it2 != end2; it2++) {
+            if (it2->isBinary()) {
+                std::cout << "Binary clause part: " << lit << " , " << it2->getOtherLit() << std::endl;
+            } else if (it2->isClause()) {
+                std::cout << "Normal clause num " << it2->getNormOffset() << std::endl;
+            } else if (it2->isXorClause()) {
+                std::cout << "Xor clause num " << it2->getXorOffset() << std::endl;
+            } else if (it2->isTriClause()) {
+                std::cout << "Tri clause:"
+                << lit << " , "
+                << it2->getOtherLit() << " , "
+                << it2->getOtherLit2() << std::endl;
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/sat/cryptominisat2/SolverMisc.cpp b/src/sat/cryptominisat2/SolverMisc.cpp
new file mode 100644 (file)
index 0000000..e457704
--- /dev/null
@@ -0,0 +1,715 @@
+/***************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+****************************************************************************/
+
+#include "Solver.h"
+#include "VarReplacer.h"
+#include "Subsumer.h"
+#include "XorSubsumer.h"
+#include "time_mem.h"
+#include "DimacsParser.h"
+#include "FailedLitSearcher.h"
+#include "DataSync.h"
+#include "SCCFinder.h"
+#include <iomanip>
+#include <omp.h>
+
+#ifdef USE_GAUSS
+#include "Gaussian.h"
+#endif
+
+#ifndef _MSC_VER
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+
+static const int space = 10;
+
+void Solver::dumpSortedLearnts(const std::string& fileName, const uint32_t maxSize)
+{
+    FILE* outfile = fopen(fileName.c_str(), "w");
+    if (!outfile) {
+        std::cout << "Error: Cannot open file '" << fileName << "' to write learnt clauses!" << std::endl;;
+        exit(-1);
+    }
+
+    fprintf(outfile, "c \nc ---------\n");
+    fprintf(outfile, "c unitaries\n");
+    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 conflicts %lu\n", (unsigned long)conflicts);
+    if (maxSize == 1) goto end;
+
+    fprintf(outfile, "c \nc ---------------------------------\n");
+    fprintf(outfile, "c learnt binary clauses (extracted from watchlists)\n");
+    fprintf(outfile, "c ---------------------------------\n");
+    dumpBinClauses(true, false, outfile);
+
+    fprintf(outfile, "c \nc ---------------------------------------\n");
+    fprintf(outfile, "c clauses representing 2-long XOR clauses\n");
+    fprintf(outfile, "c ---------------------------------------\n");
+    {
+        const vector<Lit>& table = varReplacer->getReplaceTable();
+        for (Var var = 0; var != table.size(); var++) {
+            Lit lit = table[var];
+            if (lit.var() == var)
+                continue;
+
+            fprintf(outfile, "%s%d %d 0\n", (!lit.sign() ? "-" : ""), lit.var()+1, var+1);
+            fprintf(outfile, "%s%d -%d 0\n", (lit.sign() ? "-" : ""), lit.var()+1, var+1);
+            #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);
+        }
+    }
+
+    end:
+
+    fclose(outfile);
+}
+
+void Solver::printStrangeBinLit(const Lit lit) const
+{
+    const vec<Watched>& ws = watches[(~lit).toInt()];
+    for (const Watched *it2 = ws.getData(), *end2 = ws.getDataEnd(); it2 != end2; it2++) {
+        if (it2->isBinary()) {
+            std::cout << "bin: " << lit << " , " << it2->getOtherLit() << " learnt : " <<  (it2->getLearnt()) << std::endl;
+        } else if (it2->isTriClause()) {
+            std::cout << "tri: " << lit << " , " << it2->getOtherLit() << " , " <<  (it2->getOtherLit2()) << std::endl;
+        } else if (it2->isClause()) {
+            std::cout << "cla:" << it2->getNormOffset() << std::endl;
+        } else {
+            assert(it2->isXorClause());
+            std::cout << "xor:" << it2->getXorOffset() << std::endl;
+        }
+    }
+}
+
+const uint32_t Solver::countNumBinClauses(const bool alsoLearnt, const bool alsoNonLearnt) const
+{
+    uint32_t num = 0;
+
+    uint32_t wsLit = 0;
+    for (const vec<Watched> *it = watches.getData(), *end = watches.getDataEnd(); it != end; it++, wsLit++) {
+        Lit lit = ~Lit::toLit(wsLit);
+        const vec<Watched>& ws = *it;
+        for (const Watched *it2 = ws.getData(), *end2 = ws.getDataEnd(); it2 != end2; it2++) {
+            if (it2->isBinary()) {
+                if (it2->getLearnt()) num += alsoLearnt;
+                else num+= alsoNonLearnt;
+            }
+        }
+    }
+
+    assert(num % 2 == 0);
+    return num/2;
+}
+
+void Solver::dumpBinClauses(const bool alsoLearnt, const bool alsoNonLearnt, FILE* outfile) const
+{
+    uint32_t wsLit = 0;
+    for (const vec<Watched> *it = watches.getData(), *end = watches.getDataEnd(); it != end; it++, wsLit++) {
+        Lit lit = ~Lit::toLit(wsLit);
+        const vec<Watched>& ws = *it;
+        for (const Watched *it2 = ws.getData(), *end2 = ws.getDataEnd(); it2 != end2; it2++) {
+            if (it2->isBinary() && lit.toInt() < it2->getOtherLit().toInt()) {
+                bool toDump = false;
+                if (it2->getLearnt() && alsoLearnt) toDump = true;
+                if (!it2->getLearnt() && alsoNonLearnt) toDump = true;
+
+                if (toDump) it2->dump(outfile, lit);
+            }
+        }
+    }
+}
+
+const uint32_t Solver::getBinWatchSize(const bool alsoLearnt, const Lit lit)
+{
+    uint32_t num = 0;
+    const vec<Watched>& ws = watches[lit.toInt()];
+    for (const Watched *it2 = ws.getData(), *end2 = ws.getDataEnd(); it2 != end2; it2++) {
+        if (it2->isBinary() && (alsoLearnt || !it2->getLearnt())) {
+            num++;
+        }
+    }
+
+    return num;
+}
+
+void Solver::dumpOrigClauses(const std::string& fileName) const
+{
+    FILE* outfile = fopen(fileName.c_str(), "w");
+    if (!outfile) {
+        std::cout << "Error: Cannot open file '" << fileName << "' to write learnt clauses!" << std::endl;
+        exit(-1);
+    }
+
+    uint32_t numClauses = 0;
+    //unitary clauses
+    for (uint32_t i = 0, end = (trail_lim.size() > 0) ? trail_lim[0] : trail.size() ; i < end; i++)
+        numClauses++;
+
+    //binary XOR clauses
+    const vector<Lit>& table = varReplacer->getReplaceTable();
+    for (Var var = 0; var != table.size(); var++) {
+        Lit lit = table[var];
+        if (lit.var() == var)
+            continue;
+        numClauses += 2;
+    }
+
+    //binary normal clauses
+    numClauses += countNumBinClauses(false, true);
+
+    //normal clauses
+    numClauses += clauses.size();
+
+    //xor clauses
+    numClauses += xorclauses.size();
+
+    //previously eliminated clauses
+    const map<Var, vector<vector<Lit> > >& elimedOutVar = subsumer->getElimedOutVar();
+    for (map<Var, vector<vector<Lit> > >::const_iterator it = elimedOutVar.begin(); it != elimedOutVar.end(); it++) {
+        const vector<vector<Lit> >& cs = it->second;
+        numClauses += cs.size();
+    }
+    const map<Var, vector<std::pair<Lit, Lit> > >& elimedOutVarBin = subsumer->getElimedOutVarBin();
+    for (map<Var, vector<std::pair<Lit, Lit> > >::const_iterator it = elimedOutVarBin.begin(); it != elimedOutVarBin.end(); it++) {
+        numClauses += it->second.size()*2;
+    }
+
+    const map<Var, vector<XorSubsumer::XorElimedClause> >& xorElimedOutVar = xorSubsumer->getElimedOutVar();
+    for (map<Var, vector<XorSubsumer::XorElimedClause> >::const_iterator it = xorElimedOutVar.begin(); it != xorElimedOutVar.end(); it++) {
+        const vector<XorSubsumer::XorElimedClause>& cs = it->second;
+        numClauses += cs.size();
+    }
+
+    fprintf(outfile, "p cnf %d %d\n", nVars(), numClauses);
+
+    ////////////////////////////////////////////////////////////////////
+
+    fprintf(outfile, "c \nc ---------\n");
+    fprintf(outfile, "c unitaries\n");
+    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 \nc ---------------------------------------\n");
+    fprintf(outfile, "c clauses representing 2-long XOR clauses\n");
+    fprintf(outfile, "c ---------------------------------------\n");
+    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 binary clauses\n");
+    fprintf(outfile, "c ---------------\n");
+    dumpBinClauses(false, true, outfile);
+
+    fprintf(outfile, "c \nc ------------\n");
+    fprintf(outfile, "c normal clauses\n");
+    fprintf(outfile, "c ---------------\n");
+    for (Clause *const *i = clauses.getData(); i != clauses.getDataEnd(); i++) {
+        assert(!(*i)->learnt());
+        (*i)->print(outfile);
+    }
+
+    fprintf(outfile, "c \nc ------------\n");
+    fprintf(outfile, "c xor clauses\n");
+    fprintf(outfile, "c ---------------\n");
+    for (XorClause *const *i = xorclauses.getData(); i != xorclauses.getDataEnd(); i++) {
+        assert(!(*i)->learnt());
+        (*i)->print(outfile);
+    }
+
+    fprintf(outfile, "c -------------------------------\n");
+    fprintf(outfile, "c previously eliminated variables\n");
+    fprintf(outfile, "c -------------------------------\n");
+    for (map<Var, vector<vector<Lit> > >::const_iterator it = elimedOutVar.begin(); it != elimedOutVar.end(); it++) {
+        fprintf(outfile, "c ########### cls for eliminated var %d ### start\n", it->first + 1);
+        const vector<vector<Lit> >& cs = it->second;
+        for (vector<vector<Lit> >::const_iterator it2 = cs.begin(); it2 != cs.end(); it2++) {
+            printClause(outfile, *it2);
+        }
+        fprintf(outfile, "c ########### cls for eliminated var %d ### finish\n", it->first + 1);
+    }
+    for (map<Var, vector<std::pair<Lit, Lit> > >::const_iterator it = elimedOutVarBin.begin(); it != elimedOutVarBin.end(); it++) {
+        for (uint32_t i = 0; i < it->second.size(); i++) {
+            it->second[i].first.print(outfile);
+            it->second[i].second.printFull(outfile);
+        }
+    }
+
+    fprintf(outfile, "c -------------------------------\n");
+    fprintf(outfile, "c previously xor-eliminated variables\n");
+    fprintf(outfile, "c -------------------------------\n");
+    for (map<Var, vector<XorSubsumer::XorElimedClause> >::const_iterator it = xorElimedOutVar.begin(); it != xorElimedOutVar.end(); it++) {
+        for (vector<XorSubsumer::XorElimedClause>::const_iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
+            it2->plainPrint(outfile);
+        }
+    }
+
+    fclose(outfile);
+}
+
+const vector<Lit> Solver::get_unitary_learnts() const
+{
+    vector<Lit> unitaries;
+    if (decisionLevel() > 0) {
+        for (uint32_t i = 0; i != trail_lim[0]; i++) {
+            unitaries.push_back(trail[i]);
+        }
+    }
+
+    return unitaries;
+}
+
+const vec<Clause*>& Solver::get_learnts() const
+{
+    return learnts;
+}
+
+const vec<Clause*>& Solver::get_sorted_learnts()
+{
+    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());
+    return learnts;
+}
+
+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::getTotalTimeFailedLitSearcher() const
+{
+    return failedLitSearcher->getTotalTime();
+}
+
+const double Solver::getTotalTimeXorSubsumer() const
+{
+    return xorSubsumer->getTotalTime();
+}
+
+const double Solver::getTotalTimeSCC() const
+{
+    return  sCCFinder->getTotalTime();
+}
+
+void Solver::printStatHeader() const
+{
+    #ifdef STATS_NEEDED
+    if (conf.verbosity >= 2 && !(dynamic_behaviour_analysis && logger.statistics_on)) {
+    #else
+    if (conf.verbosity >= 2) {
+    #endif
+        std::cout << "c "
+        << "========================================================================================="
+        << std::endl;
+        std::cout << "c"
+        << " types(t): F = full restart, N = normal restart" << std::endl;
+        std::cout << "c"
+        << " types(t): S = simplification begin/end, E = solution found" << std::endl;
+        std::cout << "c"
+        << " restart types(rt): st = static, dy = dynamic" << std::endl;
+
+        std::cout << "c "
+        << std::setw(2) << "t"
+        << std::setw(3) << "rt"
+        << std::setw(6) << "Rest"
+        << std::setw(space) << "Confl"
+        << std::setw(space) << "Vars"
+        << std::setw(space) << "NormCls"
+        << std::setw(space) << "BinCls"
+        << std::setw(space) << "Learnts"
+        << std::setw(space) << "ClLits"
+        << std::setw(space) << "LtLits"
+        << std::endl;
+    }
+}
+
+void Solver::printRestartStat(const char* type)
+{
+    if (conf.verbosity >= 2) {
+        //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));
+
+        std::cout << "c "
+        << std::setw(2) << type
+        << std::setw(3) << ((restartType == static_restart) ? "st" : "dy")
+        << std::setw(6) << starts
+        << std::setw(space) << conflicts
+        << std::setw(space) << order_heap.size()
+        << std::setw(space) << clauses.size()
+        << std::setw(space) << numBins
+        << std::setw(space) << learnts.size()
+        << std::setw(space) << clauses_literals
+        << std::setw(space) << learnts_literals;
+
+        if (glueHistory.getTotalNumeElems() > 0) {
+            std::cout << std::setw(space) << std::fixed << std::setprecision(2) << glueHistory.getAvgAllDouble();
+        } else {
+            std::cout << std::setw(space) << "no data";
+        }
+        if (glueHistory.isvalid()) {
+            std::cout << std::setw(space) << std::fixed << std::setprecision(2) << glueHistory.getAvgDouble();
+        } else {
+            std::cout << std::setw(space) << "no data";
+        }
+
+        #ifdef RANDOM_LOOKAROUND_SEARCHSPACE
+        if (conf.doPrintAvgBranch) {
+            if (avgBranchDepth.isvalid())
+                std::cout << std::setw(space) << avgBranchDepth.getAvgUInt();
+            else
+                std::cout << std::setw(space) << "no data";
+        }
+        #endif //RANDOM_LOOKAROUND_SEARCHSPACE
+
+        #ifdef USE_GAUSS
+        print_gauss_sum_stats();
+        #endif //USE_GAUSS
+
+        std::cout << std::endl;
+    }
+}
+
+void Solver::printEndSearchStat()
+{
+    #ifdef STATS_NEEDED
+    if (conf.verbosity >= 1 && !(dynamic_behaviour_analysis && logger.statistics_on)) {
+    #else
+    if (conf.verbosity >= 1) {
+    #endif //STATS_NEEDED
+        printRestartStat("E");
+    }
+}
+
+#ifdef USE_GAUSS
+void Solver::print_gauss_sum_stats()
+{
+    if (gauss_matrixes.size() == 0 && conf.verbosity >= 2) {
+        std::cout << "  --";
+        return;
+    }
+
+    uint32_t called = 0;
+    uint32_t useful_prop = 0;
+    uint32_t useful_confl = 0;
+    uint32_t disabled = 0;
+    for (vector<Gaussian*>::const_iterator gauss = gauss_matrixes.begin(), end= gauss_matrixes.end(); gauss != end; gauss++) {
+        disabled += (*gauss)->get_disabled();
+        called += (*gauss)->get_called();
+        useful_prop += (*gauss)->get_useful_prop();
+        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 (conf.verbosity >= 2) {
+        if (called == 0) {
+            std::cout << " --";
+        } else {
+            std::cout << " "
+            << std::fixed << std::setprecision(1) << std::setw(5)
+            << ((double)useful_prop/(double)called*100.0) << "% "
+            << std::fixed << std::setprecision(1) << std::setw(5)
+            << ((double)useful_confl/(double)called*100.0) << "% "
+            << std::fixed << std::setprecision(1) << std::setw(5)
+            << (100.0-(double)disabled/(double)gauss_matrixes.size()*100.0) << "%";
+        }
+    }
+}
+#endif //USE_GAUSS
+
+/**
+@brief Sorts the watchlists' clauses as: binary, tertiary, normal, xor
+*/
+void Solver::sortWatched()
+{
+    #ifdef VERBOSE_DEBUG
+    std::cout << "Sorting watchlists:" << std::endl;
+    #endif
+    double myTime = cpuTime();
+    for (vec<Watched> *i = watches.getData(), *end = watches.getDataEnd(); i != end; i++) {
+        if (i->size() == 0) continue;
+        #ifdef VERBOSE_DEBUG
+        vec<Watched>& ws = *i;
+        std::cout << "Before sorting:" << std::endl;
+        for (uint32_t i2 = 0; i2 < ws.size(); i2++) {
+            if (ws[i2].isBinary()) std::cout << "Binary,";
+            if (ws[i2].isTriClause()) std::cout << "Tri,";
+            if (ws[i2].isClause()) std::cout << "Normal,";
+            if (ws[i2].isXorClause()) std::cout << "Xor,";
+        }
+        std::cout << std::endl;
+        #endif //VERBOSE_DEBUG
+
+        std::sort(i->getData(), i->getDataEnd(), WatchedSorter());
+
+        #ifdef VERBOSE_DEBUG
+        std::cout << "After sorting:" << std::endl;
+        for (uint32_t i2 = 0; i2 < ws.size(); i2++) {
+            if (ws[i2].isBinary()) std::cout << "Binary,";
+            if (ws[i2].isTriClause()) std::cout << "Tri,";
+            if (ws[i2].isClause()) std::cout << "Normal,";
+            if (ws[i2].isXorClause()) std::cout << "Xor,";
+        }
+        std::cout << std::endl;
+        #endif //VERBOSE_DEBUG
+    }
+
+    if (conf.verbosity >= 3) {
+        std::cout << "c watched "
+        << "sorting time: " << cpuTime() - myTime
+        << std::endl;
+    }
+}
+
+void Solver::addSymmBreakClauses()
+{
+    if (xorclauses.size() > 0) {
+        std::cout << "c xor clauses present -> no saucy" << std::endl;
+        return;
+    }
+    double myTime = cpuTime();
+    std::cout << "c Doing saucy" << std::endl;
+    dumpOrigClauses("origProblem.cnf");
+
+    int rvalue;
+    rvalue= system("grep -v \"^c\" origProblem.cnf > origProblem2.cnf");
+    if (rvalue >= 2) { // unsuccessful grep in POSIX standard
+        std::cout << "c impossible to complete saucy" << std::endl;
+        return;
+    }
+    rvalue= system("python saucyReader.py origProblem2.cnf > output");
+    if (rvalue != 0) { // unsuccessful saucyReader.py
+        std::cout << "c impossible to complete saucy" << std::endl;
+        return;
+    }
+
+
+    DimacsParser parser(this, false, false, false, true);
+
+    #ifdef DISABLE_ZLIB
+    FILE * in = fopen("output", "rb");
+    #else
+    gzFile in = gzopen("output", "rb");
+    #endif // DISABLE_ZLIB
+    parser.parse_DIMACS(in);
+    #ifdef DISABLE_ZLIB
+    fclose(in);
+    #else
+    gzclose(in);
+    #endif // DISABLE_ZLIB
+    std::cout << "c Finished saucy, time: " << (cpuTime() - myTime) << std::endl;
+}
+
+/**
+@brief Pretty-prints a literal
+*/
+void Solver::printLit(const Lit l) const
+{
+    printf("%s%d:%c", l.sign() ? "-" : "", l.var()+1, value(l) == l_True ? '1' : (value(l) == l_False ? '0' : 'X'));
+}
+
+/**
+@brief Sets that we need a CNF file that documents all commands
+
+newVar() and addClause(), addXorClause() commands are logged to this CNF
+file and then can be re-read with special arguments to the main program. This
+can help simulate a segfaulting library-call
+*/
+void Solver::needLibraryCNFFile(const std::string& fileName)
+{
+    libraryCNFFile = fopen(fileName.c_str(), "w");
+    if (libraryCNFFile == NULL) {
+        std::cout << "Couldn't open library-call dump file "
+        << libraryCNFFile << std::endl;
+        exit(-1);
+    }
+}
+
+template<class T, class T2>
+void Solver::printStatsLine(std::string left, T value, T2 value2, std::string extra)
+{
+    std::cout << std::fixed << std::left << std::setw(27) << left << ": " << std::setw(11) << std::setprecision(2) << value << " (" << std::left << std::setw(9) << std::setprecision(2) << value2 << " " << extra << ")" << std::endl;
+}
+
+template<class T>
+void Solver::printStatsLine(std::string left, T value, std::string extra)
+{
+    std::cout << std::fixed << std::left << std::setw(27) << left << ": " << std::setw(11) << std::setprecision(2) << value << extra << std::endl;
+}
+
+/**
+@brief prints the statistics line at the end of solving
+
+Prints all sorts of statistics, like number of restarts, time spent in
+SatELite-type simplification, number of unit claues found, etc.
+*/
+void Solver::printStats()
+{
+    double   cpu_time = cpuTime();
+    uint64_t mem_used = memUsed();
+
+    int numThreads = omp_get_num_threads();
+    if (numThreads > 1) {
+        std::cout << "c Following stats are for *FIRST FINISHED THREAD ONLY*" << std::endl;
+        #if !defined(_MSC_VER) && !defined(RUSAGE_THREAD)
+        std::cout << "c There is no platform-independent way to measure time per thread" << std::endl;
+        std::cout << "c All times indicated are sum of ALL threads" << std::endl;
+        std::cout << "c Use a utilty provided by your platform to get total thread time, etc." << std::endl;
+        #endif
+    }
+    printStatsLine("c num threads" , numThreads);
+
+    //Restarts stats
+    printStatsLine("c restarts", starts);
+    printStatsLine("c dynamic restarts", dynStarts);
+    printStatsLine("c static restarts", staticStarts);
+    printStatsLine("c full restarts", fullStarts);
+    printStatsLine("c total simplify time", totalSimplifyTime);
+
+    //Learnts stats
+    printStatsLine("c learnts DL2", nbGlue2);
+    printStatsLine("c learnts size 2", numNewBin);
+    printStatsLine("c learnts size 1", get_unitary_learnts_num(), (double)get_unitary_learnts_num()/(double)nVars()*100.0, "% of vars");
+    printStatsLine("c filedLit time", getTotalTimeFailedLitSearcher(), getTotalTimeFailedLitSearcher()/cpu_time*100.0, "% time");
+
+    //Subsumer stats
+    printStatsLine("c v-elim SatELite", getNumElimSubsume(), (double)getNumElimSubsume()/(double)nVars()*100.0, "% vars");
+    printStatsLine("c SatELite time", getTotalTimeSubsumer(), getTotalTimeSubsumer()/cpu_time*100.0, "% time");
+
+    //XorSubsumer stats
+    printStatsLine("c v-elim xor", getNumElimXorSubsume(), (double)getNumElimXorSubsume()/(double)nVars()*100.0, "% vars");
+    printStatsLine("c xor elim time", getTotalTimeXorSubsumer(), getTotalTimeXorSubsumer()/cpu_time*100.0, "% time");
+
+    //VarReplacer stats
+    printStatsLine("c num binary xor trees", getNumXorTrees());
+    printStatsLine("c binxor trees' crown", getNumXorTreesCrownSize(), (double)getNumXorTreesCrownSize()/(double)getNumXorTrees(), "leafs/tree");
+    printStatsLine("c bin xor find time", getTotalTimeSCC());
+
+    //OTF clause improvement stats
+    printStatsLine("c OTF clause improved", improvedClauseNo, (double)improvedClauseNo/(double)conflicts, "clauses/conflict");
+    printStatsLine("c OTF impr. size diff", improvedClauseSize, (double)improvedClauseSize/(double)improvedClauseNo, " lits/clause");
+
+    //Clause-shrinking through watchlists
+    printStatsLine("c OTF cl watch-shrink", numShrinkedClause, (double)numShrinkedClause/(double)conflicts, "clauses/conflict");
+    printStatsLine("c OTF cl watch-sh-lit", numShrinkedClauseLits, (double)numShrinkedClauseLits/(double)numShrinkedClause, " lits/clause");
+    printStatsLine("c tried to recurMin cls", moreRecurMinLDo, (double)moreRecurMinLDo/(double)conflicts*100.0, " % of conflicts");
+    printStatsLine("c updated cache", updateTransCache, updateTransCache/(double)moreRecurMinLDo, " lits/tried recurMin");
+
+    //Multi-threading
+    if (numThreads > 1) {
+        printStatsLine("c unit cls received", dataSync->getRecvUnitData(), (double)dataSync->getRecvUnitData()/(double)get_unitary_learnts_num()*100.0, "% of units");
+        printStatsLine("c unit cls sent", dataSync->getSentUnitData(), (double)dataSync->getSentUnitData()/(double)get_unitary_learnts_num()*100.0, "% of units");
+        printStatsLine("c bin cls received", dataSync->getRecvBinData());
+        printStatsLine("c bin cls sent", dataSync->getSentBinData());
+    }
+
+    #ifdef USE_GAUSS
+    if (gaussconfig.decision_until > 0) {
+        std::cout << "c " << std::endl;
+        printStatsLine("c gauss unit truths ", get_sum_gauss_unit_truths());
+        printStatsLine("c gauss called", get_sum_gauss_called());
+        printStatsLine("c gauss conflicts ", get_sum_gauss_confl(), (double)get_sum_gauss_confl() / (double)get_sum_gauss_called() * 100.0, " %");
+        printStatsLine("c gauss propagations ", get_sum_gauss_prop(), (double)get_sum_gauss_prop() / (double)get_sum_gauss_called() * 100.0, " %");
+        printStatsLine("c gauss useful", ((double)get_sum_gauss_prop() + (double)get_sum_gauss_confl())/ (double)get_sum_gauss_called() * 100.0, " %");
+        std::cout << "c " << std::endl;
+    }
+    #endif
+
+    printStatsLine("c clauses over max glue", nbClOverMaxGlue, (double)nbClOverMaxGlue/(double)conflicts*100.0, "% of all clauses");
+
+    //Search stats
+    printStatsLine("c conflicts", conflicts, (double)conflicts/cpu_time, "/ sec");
+    printStatsLine("c decisions", decisions, (double)rnd_decisions*100.0/(double)decisions, "% random");
+    printStatsLine("c bogo-props", propagations, (double)propagations/cpu_time, "/ sec");
+    printStatsLine("c conflict literals", tot_literals, (double)(max_literals - tot_literals)*100.0/ (double)max_literals, "% deleted");
+
+    //General stats
+    printStatsLine("c Memory used", (double)mem_used / 1048576.0, " MB");
+    if (numThreads > 1) {
+        #if !defined(_MSC_VER) && defined(RUSAGE_THREAD)
+        printStatsLine("c single-thread CPU time", cpu_time, " s");
+        printStatsLine("c all-threads sum CPU time", cpuTimeTotal(), " s");
+        #else
+        printStatsLine("c all-threads sum CPU time", cpu_time, " s");
+        #endif
+    } else {
+        printStatsLine("c CPU time", cpu_time, " s");
+    }
+}
index 6f38ed593bca648c9345f188a3db25fb509fa1e6..f7fc751877928ea49026456fe12efa45700f12c9 100644 (file)
@@ -1,40 +1,28 @@
-/***********************************************************************************[SolverTypes.h]
+/*****************************************************************************
 MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+glucose -- Gilles Audemard, Laurent Simon (2008)
 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.
-**************************************************************************************************/
+Original code by MiniSat and glucose authors are under an MIT licence.
+Modifications for CryptoMiniSat are under GPLv3 licence.
+******************************************************************************/
 
 
 #ifndef SOLVERTYPES_H
 #define SOLVERTYPES_H
 
 #include <cassert>
+#include <iostream>
+#include <Vec.h>
 #ifdef _MSC_VER
 #include <msvc/stdint.h>
 #else
 #include <stdint.h>
 #endif //_MSC_VER
 
-#include "Alg.h"
 #include <stdio.h>
-
-namespace MINISAT
-{
-using namespace MINISAT;
+#include <vector>
+#include "constants.h"
 
 //=================================================================================================
 // Variables, literals, lifted booleans, clauses:
@@ -47,6 +35,9 @@ typedef uint32_t Var;
 #define var_Undef (0xffffffffU >>1)
 enum RestartType {dynamic_restart, static_restart, auto_restart};
 
+/**
+@brief A Literal, i.e. a variable with a sign
+*/
 class Lit
 {
     uint32_t     x;
@@ -83,12 +74,15 @@ public:
     bool operator!= (const Lit& p) const {
         return x != p.x;
     }
+    /**
+    @brief ONLY to be used for ordering such as: a, b, ~b, etc.
+    */
     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);
+        fprintf(outfile,"%s%d ", sign() ? "-" : "", var()+1);
     }
     inline void printFull(FILE* outfile = stdout) const
     {
@@ -103,6 +97,36 @@ public:
 const Lit lit_Undef(var_Undef, false);  // Useful special constants.
 const Lit lit_Error(var_Undef, true );  //
 
+inline std::ostream& operator<<(std::ostream& cout, const Lit& lit)
+{
+    cout << (lit.sign() ? "-" : "") << (lit.var() + 1);
+    return cout;
+}
+
+inline std::ostream& operator<<(std::ostream& cout, const vec<Lit>& lits)
+{
+    for (uint32_t i = 0; i < lits.size(); i++) {
+        cout << lits[i] << " ";
+    }
+    return cout;
+}
+
+inline void printClause(FILE* outFile, const std::vector<Lit>& clause)
+{
+    for (size_t i = 0; i < clause.size(); i++) {
+        fprintf(outFile,"%s%d ", clause[i].sign() ? "-" : "", clause[i].var()+1);
+    }
+    fprintf(outFile, "0\n");
+}
+
+inline void printClause(FILE* outFile, const vec<Lit>& clause)
+{
+    for (uint32_t i = 0; i < clause.size(); i++) {
+        fprintf(outFile,"%s%d ", clause[i].sign() ? "-" : "", clause[i].var()+1);
+    }
+    fprintf(outFile, "0\n");
+}
+
 //=================================================================================================
 // Lifted booleans:
 
@@ -157,7 +181,18 @@ const lbool l_True  = toLbool( 1);
 const lbool l_False = toLbool(-1);
 const lbool l_Undef = toLbool( 0);
 
+inline std::ostream& operator<<(std::ostream& cout, const lbool val)
+{
+    if (val == l_True) cout << "l_True";
+    if (val == l_False) cout << "l_False";
+    if (val == l_Undef) cout << "l_Undef";
+    return cout;
+}
+
 
+/**
+@brief A very hackish lbool that also supports l_Nothing and l_Continue
+*/
 class llbool
 {
     char value;
@@ -184,6 +219,23 @@ const llbool l_Continue = toLbool(3);
 
 lbool::lbool(llbool b) : value(b.value) {};
 
-}; //NAMESPACE MINISAT
+inline std::ostream& operator<<(std::ostream& os, const llbool val)
+{
+    if (val == l_True) os << "l_True";
+    if (val == l_False) os << "l_False";
+    if (val == l_Undef) os << "l_Undef";
+    if (val == l_Nothing) os << "l_Nothing";
+    if (val == l_Continue) os << "l_Continue";
+    return os;
+}
+
+enum { polarity_true = 0, polarity_false = 1, polarity_rnd = 3, polarity_auto = 4};
+
+struct BinPropData {
+    uint32_t lev;
+    Lit lev2Ancestor;
+    bool learntLeadHere;
+};
+
 
 #endif //SOLVERTYPES_H
index ceb5eab7d699c26fca4006d014fa1808cc4ac9e6..22b7cc168d405835b333ddce9fa017be0ae8b763 100644 (file)
@@ -17,10 +17,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include "StateSaver.h"
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 StateSaver::StateSaver(Solver& _solver) :
     solver(_solver)
     , backup_order_heap(Solver::VarOrderLt(solver.activity))
@@ -32,8 +28,8 @@ StateSaver::StateSaver(Solver& _solver) :
     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;
+    backup_random_var_freq = solver.conf.random_var_freq;
 }
 
 void StateSaver::restore()
@@ -44,11 +40,9 @@ void StateSaver::restore()
     solver.order_heap = backup_order_heap;
     solver.polarity = backup_polarities;
     solver.restartType = backup_restartType;
-    solver.random_var_freq = backup_random_var_freq;
-    
+    solver.propagations = backup_propagations;
+    solver.conf.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
index 7d1f1c37798b45bfab7afc64bc3fd1974e60ea56..120388a96ab05df28dd09a35c5f5e5e6c19ab648 100644 (file)
@@ -20,10 +20,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include "Solver.h"
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 class StateSaver
 {
     public:
@@ -41,6 +37,4 @@ class StateSaver
         uint64_t backup_propagations;
 };
 
-}; //NAMESPACE MINISAT
-
 #endif //STATESAVER__H
diff --git a/src/sat/cryptominisat2/StreamBuffer.h b/src/sat/cryptominisat2/StreamBuffer.h
new file mode 100644 (file)
index 0000000..1d6298a
--- /dev/null
@@ -0,0 +1,73 @@
+/******************************************************************************************[Main.C]
+MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef STREAMBUFFER_H
+#define STREAMBUFFER_H
+
+#define CHUNK_LIMIT 1048576
+
+#ifndef DISABLE_ZLIB
+#include <zlib.h>
+#endif // DISABLE_ZLIB
+
+class StreamBuffer
+{
+    #ifdef DISABLE_ZLIB
+    FILE *  in;
+    #else
+    gzFile  in;
+    #endif // DISABLE_ZLIB
+    char    buf[CHUNK_LIMIT];
+    int     pos;
+    int     size;
+
+    void assureLookahead() {
+        if (pos >= size) {
+            pos  = 0;
+            #ifdef DISABLE_ZLIB
+            #ifdef VERBOSE_DEBUG
+            printf("buf = %08X\n", buf);
+            printf("sizeof(buf) = %u\n", sizeof(buf));
+            #endif //VERBOSE_DEBUG
+            size = fread(buf, 1, sizeof(buf), in);
+            #else
+            size = gzread(in, buf, sizeof(buf));
+            #endif // DISABLE_ZLIB
+        }
+    }
+
+public:
+    #ifdef DISABLE_ZLIB
+    StreamBuffer(FILE * i) : in(i), pos(0), size(0) {
+    #else
+    StreamBuffer(gzFile i) : in(i), pos(0), size(0) {
+    #endif // DISABLE_ZLIB
+        assureLookahead();
+    }
+
+    int  operator *  () {
+        return (pos >= size) ? EOF : buf[pos];
+    }
+    void operator ++ () {
+        pos++;
+        assureLookahead();
+    }
+};
+
+#endif //STREAMBUFFER_H
index 149e57971ad7f578e872e7e66bf18ef50caf6dad..d511e7f61e66418b75c8c8f53d6b9f5f17d24c39 100644 (file)
@@ -1,7 +1,10 @@
-/**************************************************************************************************
-Originally From: Solver.C -- (C) Niklas Een, Niklas Sorensson, 2004
-Substantially modified by: Mate Soos (2010)
-**************************************************************************************************/
+/*****************************************************************************
+SatELite -- (C) Niklas Een, Niklas Sorensson, 2004
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+Original code by SatELite authors are under an MIT licence.
+Modifications for CryptoMiniSat are under GPLv3 licence.
+******************************************************************************/
 
 #include "Solver.h"
 #include "Subsumer.h"
@@ -13,7 +16,10 @@ Substantially modified by: Mate Soos (2010)
 #include <algorithm>
 #include "VarReplacer.h"
 #include "XorFinder.h"
+#include "CompleteDetachReattacher.h"
 #include "OnlyNonLearntBins.h"
+#include "UselessBinRemover.h"
+#include "DataSync.h"
 
 #ifdef _MSC_VER
 #define __builtin_prefetch(a,b,c)
@@ -32,27 +38,32 @@ using std::cout;
 using std::endl;
 #endif //VERBOSE_DEBUG
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 Subsumer::Subsumer(Solver& s):
     solver(s)
     , totalTime(0.0)
     , numElimed(0)
-    , numCalls(0)
+    , numCalls(1)
+    , alsoLearnt(false)
 {
 };
 
-Subsumer::~Subsumer()
-{
-}
+/**
+@brief Extends the model to include eliminated variables
+
+Adds the clauses to the parameter solver2, and then relies on the
+caller to call solver2.solve().
 
+@p solver2 The external solver the variables' clauses are added to
+*/
 void Subsumer::extendModel(Solver& solver2)
 {
+    #ifdef VERBOSE_DEBUG
+    std::cout << "Subsumer::extendModel(Solver& solver2) called" << std::endl;
+    #endif
+
     assert(checkElimedUnassigned());
     vec<Lit> tmp;
-    typedef map<Var, vector<Clause*> > elimType;
+    typedef map<Var, vector<vector<Lit> > > elimType;
     for (elimType::iterator it = elimedOutVar.begin(), end = elimedOutVar.end(); it != end; it++) {
         #ifndef NDEBUG
         Var var = it->first;
@@ -63,134 +74,206 @@ void Subsumer::extendModel(Solver& solver2)
         assert(solver.assigns[var] == l_Undef);
         assert(!solver.order_heap.inHeap(var));
         #endif
-        
-        for (vector<Clause*>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
-            Clause& c = **it2;
+
+        for (vector<vector<Lit> >::const_iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
+            tmp.clear();
+            tmp.growTo(it2->size());
+            std::copy(it2->begin(), it2->end(), tmp.getData());
+
+            #ifdef VERBOSE_DEBUG
+            std::cout << "Reinserting elimed clause: " << tmp << std::endl;;
+            #endif
+
+            solver2.addClause(tmp);
+            assert(solver2.ok);
+        }
+    }
+
+    typedef map<Var, vector<std::pair<Lit, Lit> > > elimType2;
+    for (elimType2::iterator it = elimedOutVarBin.begin(), end = elimedOutVarBin.end(); it != end; it++) {
+        #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<std::pair<Lit, Lit> >::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
             tmp.clear();
-            tmp.growTo(c.size());
-            std::copy(c.getData(), c.getDataEnd(), tmp.getData());
-            
+            tmp.growTo(2);
+            tmp[0] = it2->first;
+            tmp[1] = it2->second;
+
             #ifdef VERBOSE_DEBUG
-            std::cout << "Reinserting Clause: ";
-            c.plainPrint();
+            std::cout << "Reinserting bin clause: " << it2->first << " , " << it2->second << std::endl;
             #endif
-            
+
             solver2.addClause(tmp);
             assert(solver2.ok);
         }
     }
 }
 
+/**
+@brief Adds to the solver the clauses representing variable var
+
+This function is useful if a variable was eliminated, but now needs to be
+added back again.
+
+@p var The variable to be added back again
+*/
 const bool Subsumer::unEliminate(const Var var)
 {
     assert(var_elimed[var]);
     vec<Lit> tmp;
-    typedef map<Var, vector<Clause*> > elimType;
+    typedef map<Var, vector<vector<Lit> > > elimType;
+    typedef map<Var, vector<std::pair<Lit, Lit> > > elimType2;
     elimType::iterator it = elimedOutVar.find(var);
+    elimType2::iterator it2 = elimedOutVarBin.find(var);
 
     //it MUST have been decision var, otherwise we would
     //never have removed it
     solver.setDecisionVar(var, true);
     var_elimed[var] = false;
     numElimed--;
-    
+    #ifdef VERBOSE_DEBUG
+    std::cout << "Reinserting normal (non-xor) elimed var: " << var+1 << std::endl;
+    #endif
+
     //If the variable was removed because of
     //pure literal removal (by blocked clause
     //elimination, there are no clauses to re-insert
-    if (it == elimedOutVar.end()) return solver.ok;
-    
+    if (it == elimedOutVar.end() && it2 == elimedOutVarBin.end()) return solver.ok;
+
     FILE* backup_libraryCNFfile = solver.libraryCNFFile;
     solver.libraryCNFFile = NULL;
-    for (vector<Clause*>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
-        solver.addClause(**it2);
-        solver.clauseAllocator.clauseFree(*it2);
+
+    if (it == elimedOutVar.end()) goto next;
+    for (vector<vector<Lit> >::iterator itt = it->second.begin(), end2 = it->second.end(); itt != end2; itt++) {
+        #ifdef VERBOSE_DEBUG
+        std::cout << "Reinserting elimed clause: ";
+        for (uint32_t i = 0; i < itt->size(); i++) {
+            std::cout << (*itt)[i] << " , ";
+        }
+        std::cout << std::endl;
+        #endif
+        tmp.clear();
+        tmp.growTo(itt->size());
+        std::copy(itt->begin(), itt->end(), tmp.getData());
+        solver.addClause(tmp);
     }
-    solver.libraryCNFFile = backup_libraryCNFfile;
     elimedOutVar.erase(it);
-    
+
+    next:
+    if (it2 == elimedOutVarBin.end()) goto next2;
+    for (vector<std::pair<Lit, Lit> >::iterator itt = it2->second.begin(), end2 = it2->second.end(); itt != end2; itt++) {
+        tmp.clear();
+        tmp.growTo(2);
+        tmp[0] = itt->first;
+        tmp[1] = itt->second;
+        #ifdef VERBOSE_DEBUG
+        std::cout << "Reinserting bin clause: " << itt->first << " , " << itt->second << std::endl;
+        #endif
+        solver.addClause(tmp);
+    }
+    elimedOutVarBin.erase(it2);
+
+    next2:
+    solver.libraryCNFFile = backup_libraryCNFfile;
+
     return solver.ok;
 }
 
-bool selfSubset(uint32_t A, uint32_t B)
-{
-    uint32_t B_tmp = B | ((B & 0xAAAAAAAALL) >> 1) | ((B & 0x55555555LL) << 1);
-    if ((A & ~B_tmp) == 0){
-        uint32_t C = A & ~B;
-        return (C & (C-1)) == 0;
-    }else
-        return false;
-}
+/**
+@brief Backward-subsumption using given clause: helper function
 
-// Assumes 'seen' is cleared (will leave it cleared)
-bool selfSubset(Clause& A, Clause& B, vec<char>& seen)
-{
-    for (uint32_t i = 0; i < B.size(); i++)
-        seen[B[i].toInt()] = 1;
-    
-    bool    flip = false;
-    for (uint32_t i = 0; i < A.size(); i++) {
-        if (!seen[A[i].toInt()]) {
-            if (flip == true || !seen[(~A[i]).toInt()]) {
-                for (uint32_t i = 0; i < B.size(); i++) seen[B[i].toInt()] = 0;
-                return false;
-            }
-            flip = true;
-        }
-    }
-    for (uint32_t i = 0; i < B.size(); i++)
-        seen[B[i].toInt()] = 0;
-    return flip;
-}
+Checks all clauses in the occurrence lists if they are subsumed by ps or not.
 
-template <>
-inline uint32_t Subsumer::subsume0(Clause& ps, uint32_t abs)
+The input clause can be learnt. In that case, if it subsumes non-learnt clauses,
+it will become non-learnt.
+
+Handles it well if the subsumed clause has a higher activity than the subsuming
+clause (will take the max() of the two)
+
+@p ps The clause to use
+
+*/
+void Subsumer::subsume0(Clause& ps)
 {
-    ps.subsume0Finished();
-    ps.unsetVarChanged();
     #ifdef VERBOSE_DEBUG
-    cout << "subsume0 orig clause: ";
+    cout << "subsume0-ing with clause: ";
     ps.plainPrint();
     #endif
-    return subsume0Orig(ps, abs);
+    subsume0Happened ret = subsume0Orig(ps, ps.getAbst());
+
+    if (ps.learnt()) {
+        if (!ret.subsumedNonLearnt) {
+            if (ps.getGlue() > ret.glue)
+                ps.setGlue(ret.glue);
+            if (ps.getMiniSatAct() < ret.act)
+                ps.setMiniSatAct(ret.act);
+        } else {
+            solver.nbCompensateSubsumer++;
+            ps.makeNonLearnt();
+        }
+    }
 }
 
-template <class T>
-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);
-}
+/**
+@brief Backward-subsumption using given clause
 
-// Will put NULL in 'cs' if clause removed.
+@note Use helper function
+
+@param ps The clause to use to backward-subsume
+@param[in] abs The abstraction of the clause
+@return Subsumed anything? If so, what was the max activity? Was it non-learnt?
+*/
 template<class T>
-uint32_t Subsumer::subsume0Orig(const T& ps, uint32_t abs)
+Subsumer::subsume0Happened Subsumer::subsume0Orig(const T& ps, uint32_t abs)
 {
-    subsumedNonLearnt = false;
-    uint32_t retIndex = std::numeric_limits<uint32_t>::max();
+    subsume0Happened ret;
+    ret.subsumedNonLearnt = false;
+    ret.glue = std::numeric_limits<uint32_t>::max();
+    ret.act = std::numeric_limits< float >::min();
+
     vec<ClauseSimp> subs;
     findSubsumed(ps, abs, subs);
     for (uint32_t i = 0; i < subs.size(); i++){
-        clauses_subsumed++;
         #ifdef VERBOSE_DEBUG
         cout << "-> subsume0 removing:";
         subs[i].clause->plainPrint();
         #endif
-        
+
         Clause* tmp = subs[i].clause;
-        subsumedNonLearnt |= !tmp->learnt();
-        retIndex = subs[i].index;
+        if (tmp->learnt()) {
+            ret.glue = std::min(ret.glue, tmp->getGlue());
+            ret.act = std::max(ret.act, tmp->getMiniSatAct());
+        } else {
+            ret.subsumedNonLearnt = true;
+        }
         unlinkClause(subs[i]);
-        solver.clauseAllocator.clauseFree(tmp);
     }
-    
-    return retIndex;
-}
 
-void Subsumer::subsume0BIN(const Lit lit1, const vec<char>& lits)
+    return ret;
+}
+/**
+@brief Backward-subsumption&self-subsuming resolution for binary clause sets
+
+Takes in a set of binary clauses:
+lit1 OR lits[0]
+lit1 OR lits[1]
+...
+and backward-subsumes clauses in the occurence lists with it, as well as
+performing self-subsuming resolution using these binary clauses on clauses in
+the occurrence lists.
+
+@param[in] lit1 As defined above
+@param[in] lits The abstraction of the clause
+*/
+void Subsumer::subsume0BIN(const Lit lit1, const vec<char>& lits, const uint32_t abst)
 {
     vec<ClauseSimp> subs;
     vec<ClauseSimp> subs2;
@@ -198,590 +281,537 @@ void Subsumer::subsume0BIN(const Lit lit1, const vec<char>& lits)
 
     vec<ClauseSimp>& 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+1 != end) __builtin_prefetch((it+1)->clause, 0, 1);
         if (it->clause == NULL) continue;
+
         Clause& c = *it->clause;
+        if ((c.getAbst() & abst) == 0) continue;
+        extraTimeNonExist += c.size()*2;
         bool removed = false;
+        bool removedLit = 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;
-                }
+
+            if (!removedLit && lits[(~c[i]).toInt()]) {
+                subs2.push(*it);
+                subs2Lit.push(c[i]);
+                removedLit = true;
             }
         }
+
+        if (removed && removedLit) {
+            subs2.pop();
+            subs2Lit.pop();
+        }
     }
-    
+
     for (uint32_t i = 0; i < subs.size(); i++){
-        clauses_subsumed++;
-        #ifdef VERBOSE_DEBUG
-        cout << "-> subsume0 removing:";
-        subs[i].clause->plainPrint();
-        #endif
-        
-        Clause* tmp = subs[i].clause;
         unlinkClause(subs[i]);
-        solver.clauseAllocator.clauseFree(tmp);
     }
 
-    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);
+    for (uint32_t i = 0; i < subs2.size(); i++) {
+        strenghten(subs2[i], subs2Lit[i]);
+        if (!solver.ok) break;
+    }
 
-        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;
+    #ifdef VERBOSE_DEBUG
+    if (!solver.ok) {
+        std::cout << "solver.ok is false when returning from subsume0BIN()" << std::endl;
+    }
+    #endif //VERBOSE_DEBUG
+}
+/**
+@brief Backward subsumption and self-subsuming resolution
 
-            if (val == l_True) {
-                #ifdef VERBOSE_DEBUG
-                std::cout << "--> Clause was satisfied." << std::endl;
-                #endif
-                solver.clauseAllocator.clauseFree(&cl);
-                goto endS;
-            }
-        }
-        cl.shrink(a-b);
-        cl.setStrenghtened();
+Performs backward subsumption AND
+self-subsuming resolution using backward-subsumption
 
-        #ifdef VERBOSE_DEBUG
-        cout << "--> Strenghtened clause:";
-        cl.plainPrint();
-        #endif
+@param[in] ps The clause to use for backw-subsumption and self-subs. resolution
+*/
+void Subsumer::subsume1(Clause& ps)
+{
+    vec<ClauseSimp>    subs;
+    vec<Lit>           subsLits;
+    #ifdef VERBOSE_DEBUG
+    cout << "subsume1-ing with clause:";
+    ps.plainPrint();
+    #endif
 
-        if (cl.size() == 0) {
-            solver.ok = false;
-            unregisterIteration(subs2);
-            solver.clauseAllocator.clauseFree(&cl);
-            return;
+    findSubsumed1(ps, ps.getAbst(), subs, subsLits);
+    for (uint32_t j = 0; j < subs.size(); j++) {
+        if (subs[j].clause == NULL) continue;
+        ClauseSimp c = subs[j];
+        if (subsLits[j] == lit_Undef) {
+            if (ps.learnt()) {
+                if (c.clause->learnt()) ps.takeMaxOfStats(*c.clause);
+                else {
+                    solver.nbCompensateSubsumer++;
+                    ps.makeNonLearnt();
+                }
+            }
+            unlinkClause(c);
+        } else {
+            strenghten(c, subsLits[j]);
+            if (!solver.ok) return;
         }
-        if (cl.size() > 2) {
-            cl.calcAbstractionClause();
-            linkInAlreadyClause(c);
-            clauses[c.index] = c;
-            solver.attachClause(cl);
-            updateClause(c);
-        } else if (cl.size() == 2) {
-            cl.calcAbstractionClause();
-            solver.attachClause(cl);
-            solver.becameBinary++;
-            addBinaryClauses.push(&cl);
-            //updateClause(c);
+    }
+}
+
+const bool Subsumer::subsume1(vec<Lit>& ps, const bool wasLearnt)
+{
+    vec<ClauseSimp>    subs;
+    vec<Lit>           subsLits;
+    bool toMakeNonLearnt = false;
+
+    findSubsumed1(ps, calcAbstraction(ps), subs, subsLits);
+    for (uint32_t j = 0; j < subs.size(); j++) {
+        if (subs[j].clause == NULL) continue;
+        ClauseSimp c = subs[j];
+        if (subsLits[j] == lit_Undef) {
+            if (wasLearnt && !c.clause->learnt()) toMakeNonLearnt = true;
+            unlinkClause(c);
         } else {
-            assert(cl.size() == 1);
-            solver.uncheckedEnqueue(cl[0]);
-            solver.ok = (solver.propagate().isNULL());
-            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
-            solver.clauseAllocator.clauseFree(&cl);
+            strenghten(c, subsLits[j]);
+            if (!solver.ok) return false;
         }
-        endS:;
     }
-    unregisterIteration(subs2);
+
+    return toMakeNonLearnt;
 }
 
-void Subsumer::unlinkClause(ClauseSimp c, Var elim)
+/**
+@brief Removes&free-s a clause from everywhere
+
+Removes clause from occurence lists, from Subsumer::clauses, and iter_sets.
+
+If clause is to be removed because the variable in it is eliminated, the clause
+is saved in elimedOutVar[] before it is fully removed.
+
+@param[in] c The clause to remove
+@param[in] elim If the clause is removed because of variable elmination, this
+parameter is different from var_Undef.
+*/
+void Subsumer::unlinkClause(ClauseSimp c, const Var elim)
 {
     Clause& cl = *c.clause;
-    
-    if (elim != var_Undef) {
-        assert(!cl.learnt());
-        #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);
-    }
 
     for (uint32_t i = 0; i < cl.size(); i++) {
+        if (elim != var_Undef) numMaxElim -= occur[cl[i].toInt()].size()/2;
+        else {
+            numMaxSubsume0 -= occur[cl[i].toInt()].size()/2;
+            numMaxSubsume1 -= occur[cl[i].toInt()].size()/2;
+        }
         maybeRemove(occur[cl[i].toInt()], &cl);
         #ifndef TOUCH_LESS
-        touch(cl[i]);
+        touch(cl[i], cl.learnt());
         #endif
     }
-    
-    solver.detachClause(cl);
-    
+
     // Remove from iterator vectors/sets:
-    for (uint32_t i = 0; i < iter_vecs.size(); i++) {
-        vec<ClauseSimp>& cs = *iter_vecs[i];
-        for (uint32_t j = 0; j < cs.size(); j++)
-            if (cs[j].clause == &cl)
-                cs[j].clause = NULL;
-    }
     for (uint32_t i = 0; i < iter_sets.size(); i++) {
         CSet& cs = *iter_sets[i];
         cs.exclude(c);
     }
-    
+
     // Remove clause from clause touched set:
     cl_touched.exclude(c);
-    cl_added.exclude(c);
-    
+
+    //Compensate if removing learnt
+    if (cl.learnt()) solver.nbCompensateSubsumer++;
+
+    if (elim != var_Undef) {
+        assert(!cl.learnt());
+        #ifdef VERBOSE_DEBUG
+        std::cout << "Eliminating non-bin clause: " << *c.clause << std::endl;
+        std::cout << "On variable: " << elim+1 << std::endl;
+        #endif //VERBOSE_DEBUG
+        vector<Lit> lits(c.clause->size());
+        std::copy(c.clause->getData(), c.clause->getDataEnd(), lits.begin());
+        elimedOutVar[elim].push_back(lits);
+    } else {
+        clauses_subsumed++;
+    }
+    solver.clauseAllocator.clauseFree(c.clause);
+
     clauses[c.index].clause = NULL;
 }
 
-void Subsumer::unlinkModifiedClause(vec<Lit>& origClause, ClauseSimp c, bool detachAndNull)
+
+/**
+@brief Cleans clause from false literals
+
+This does NOT re-implement the feature of  ClauseCleaner because
+here we need to remove the literals from the occurrence lists as well. Further-
+more, we need propagate if needed, which is never assumed to be a need in
+ClauseCleaner since there the clauses are always attached to the watch-
+lists.
+
+@param ps Clause to be cleaned
+*/
+const bool Subsumer::cleanClause(Clause& ps)
 {
-    for (uint32_t i = 0; i < origClause.size(); i++) {
-        maybeRemove(occur[origClause[i].toInt()], c.clause);
-        #ifndef TOUCH_LESS
-        touch(origClause[i]);
-        #endif
-    }
-    
-    // Remove from iterator vectors/sets:
-    for (uint32_t i = 0; i < iter_vecs.size(); i++){
-        vec<ClauseSimp>& cs = *iter_vecs[i];
-        for (uint32_t j = 0; j < cs.size(); j++)
-            if (cs[j].clause == c.clause)
-                cs[j].clause = NULL;
-    }
-    for (uint32_t i = 0; i < iter_sets.size(); i++){
-        CSet& cs = *iter_sets[i];
-        cs.exclude(c);
-    }
-    
-    // Remove clause from clause touched set:
-    cl_touched.exclude(c);
-    cl_added.exclude(c);
+    bool retval = false;
 
-    if (detachAndNull) {
-        solver.detachModifiedClause(origClause[0], origClause[1], origClause.size(), c.clause);
-        clauses[c.index].clause = NULL;
+    Lit *i = ps.getData();
+    Lit *j = i;
+    for (Lit *end = ps.getDataEnd(); i != end; i++) {
+        lbool val = solver.value(*i);
+        if (val == l_Undef) {
+            *j++ = *i;
+            continue;
+        }
+        if (val == l_False) {
+            removeW(occur[i->toInt()], &ps);
+            numMaxSubsume1 -= occur[i->toInt()].size()/2;
+            #ifndef TOUCH_LESS
+            touch(*i, ps.learnt());
+            #endif
+            continue;
+        }
+        if (val == l_True) {
+            *j++ = *i;
+            retval = true;
+            continue;
+        }
+        assert(false);
     }
+    ps.shrink(i-j);
+
+    return retval;
 }
 
-void Subsumer::subsume1(ClauseSimp& ps)
+const bool Subsumer::cleanClause(vec<Lit>& ps) const
 {
-    vec<ClauseSimp>    Q;
-    vec<ClauseSimp>    subs;
-    vec<Lit>        qs;
-    uint32_t        q;
-    
-    ps.clause->unsetStrenghtened();
-    registerIteration(Q);
-    registerIteration(subs);
-    
-    Q.push(ps);
-    q = 0;
-    while (q < Q.size()){
-        if (Q[q].clause == NULL) { q++; continue; }
-        #ifdef VERBOSE_DEBUG
-        cout << "subsume1 with clause:";
-        Q[q].clause->plainPrint();
-        #endif
-        
-        qs.clear();
-        for (uint32_t i = 0; i < Q[q].clause->size(); i++)
-            qs.push((*Q[q].clause)[i]);
-        
-        for (uint32_t i = 0; i < qs.size(); i++){
-            qs[i] = ~qs[i];
-            
-            uint32_t abst = calcAbstraction(qs);
-            
-            findSubsumed(qs, abst, subs);
-            for (uint32_t j = 0; j < subs.size(); j++){
-                /*#ifndef NDEBUG
-                if (&counter != NULL && counter == -1){
-                    dump(*subs[j].clause);
-                    qs[i] = ~qs[i];
-                    dump(qs);
-                    printf(L_LIT"\n", L_lit(qs[i]));
-                    exit(0);
-                }
-                #endif*/
-                if (subs[j].clause == NULL) continue;
-                ClauseSimp c = subs[j];
-                Clause& cl = *c.clause;
-                #ifdef VERBOSE_DEBUG
-                cout << "-> Strenghtening clause :";
-                cl.plainPrint();
-                #endif
-                unlinkClause(c);
-                
-                literals_removed++;
-                cl.strengthen(qs[i]);
-                Lit *a, *b, *end;
-                for (a = b = cl.getData(), end = a + cl.size();  a != end; a++) {
-                    lbool val = solver.value(*a);
-                    if (val == l_Undef)
-                        *b++ = *a;
-                    
-                    if (val == l_True) {
-                        #ifdef VERBOSE_DEBUG
-                        std::cout << "--> Clause was satisfied." << std::endl;
-                        #endif
-                        solver.clauseAllocator.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(Q);
-                    unregisterIteration(subs);
-                    solver.clauseAllocator.clauseFree(&cl);
-                    return;
-                }
-                if (cl.size() > 1) {
-                    cl.calcAbstractionClause();
-                    linkInAlreadyClause(c);
-                    clauses[c.index] = c;
-                    solver.attachClause(cl);
-                    if (cl.size() == 2) solver.becameBinary++;
-                    updateClause(c);
-                    Q.push(c);
-                } else {
-                    assert(cl.size() == 1);
-                    solver.uncheckedEnqueue(cl[0]);
-                    solver.ok = (solver.propagate().isNULL());
-                    if (!solver.ok) {
-                        unregisterIteration(Q);
-                        unregisterIteration(subs);
-                        return;
-                    }
-                    #ifdef VERBOSE_DEBUG
-                    cout << "--> Found that var " << cl[0].var()+1 << " must be " << std::boolalpha << !cl[0].sign() << endl;
-                    #endif
-                    solver.clauseAllocator.clauseFree(&cl);
-                }
-                endS:;
-            }
-            
-            qs[i] = ~qs[i];
-            subs.clear();
+    bool retval = false;
+
+    Lit *i = ps.getData();
+    Lit *j = i;
+    for (Lit *end = ps.getDataEnd(); i != end; i++) {
+        lbool val = solver.value(*i);
+        if (val == l_Undef) {
+            *j++ = *i;
+            continue;
+        }
+        if (val == l_False)
+            continue;
+        if (val == l_True) {
+            *j++ = *i;
+            retval = true;
+            continue;
         }
-        q++;
+        assert(false);
     }
-    
-    unregisterIteration(Q);
-    unregisterIteration(subs);
+    ps.shrink(i-j);
+
+    return retval;
 }
 
-template<class T>
-void Subsumer::subsume1Partial(const T& ps)
+/**
+@brief Removes a literal from a clause
+
+May return with solver.ok being FALSE, and may set&propagate variable values.
+
+@param c Clause to be cleaned of the literal
+@param[in] toRemoveLit The literal to be removed from the clause
+*/
+void Subsumer::strenghten(ClauseSimp& c, const Lit toRemoveLit)
 {
-    assert(solver.decisionLevel() == 0);
-    registerIteration(subsume1PartialSubs);
-    
     #ifdef VERBOSE_DEBUG
-    cout << "-> Strenghtening using clause :";
-    ps[0].print(); std::cout << " ";
-    ps[1].printFull();
+    cout << "-> Strenghtening clause :";
+    c.clause->plainPrint();
+    cout << " with lit: " << toRemoveLit << std::endl;
     #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
-                    solver.clauseAllocator.clauseFree(&cl);
-                    goto endS;
-                }
-            }
-            cl.shrink(a-b);
-            cl.setStrenghtened();
+    literals_removed++;
+    c.clause->strengthen(toRemoveLit);
+    removeW(occur[toRemoveLit.toInt()], c.clause);
+    numMaxSubsume1 -= occur[toRemoveLit.toInt()].size()/2;
+    #ifndef TOUCH_LESS
+    touch(toRemoveLit, c.clause->learnt());
+    #endif
+    if (cleanClause(*c.clause)) {
+        unlinkClause(c);
+        c.clause = NULL;
+        return;
+    }
 
+    switch (c.clause->size()) {
+        case 0:
             #ifdef VERBOSE_DEBUG
-            cout << "--> Strenghtened clause:";
-            cl.plainPrint();
-            #endif
+            std::cout << "Strenghtened clause to 0-size -> UNSAT"<< std::endl;
+            #endif //VERBOSE_DEBUG
+            solver.ok = false;
+            break;
+        case 1: {
+            handleSize1Clause((*c.clause)[0]);
+            unlinkClause(c);
+            c.clause = NULL;
+            break;
+        }
+        case 2: {
+            solver.attachBinClause((*c.clause)[0], (*c.clause)[1], (*c.clause).learnt());
+            solver.numNewBin++;
+            solver.dataSync->signalNewBinClause(*c.clause);
+            clBinTouched.push_back(NewBinaryClause((*c.clause)[0], (*c.clause)[1], (*c.clause).learnt()));
+            unlinkClause(c);
+            c.clause = NULL;
+            break;
+        }
+        default:
+            cl_touched.add(c);
+    }
+}
 
-            if (cl.size() == 0) {
-                solver.ok = false;
-                unregisterIteration(subsume1PartialSubs);
-                solver.clauseAllocator.clauseFree(&cl);
-                return;
-            }
-            if (cl.size() > 2) {
-                cl.calcAbstractionClause();
-                linkInAlreadyClause(c);
-                clauses[c.index] = c;
-                solver.attachClause(cl);
-                updateClause(c);
-            } else if (cl.size() == 2) {
-                cl.calcAbstractionClause();
-                solver.attachClause(cl);
-                solver.becameBinary++;
-                addBinaryClauses.push(&cl);
-                //updateClause(c);
-            } else {
-                assert(cl.size() == 1);
-                solver.uncheckedEnqueue(cl[0]);
-                solver.ok = (solver.propagate().isNULL());
-                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
-                solver.clauseAllocator.clauseFree(&cl);
+const bool Subsumer::handleClBinTouched()
+{
+    assert(solver.ok);
+    uint32_t clauses_subsumed_before = clauses_subsumed;
+    uint32_t literals_removed_before = literals_removed;
+    uint32_t clBinSize = 0;
+
+    vec<Lit> lits(2);
+    for (list<NewBinaryClause>::const_iterator it = clBinTouched.begin(); it != clBinTouched.end(); it++) {
+        lits[0] = it->lit1;
+        lits[1] = it->lit2;
+        const bool learnt = it->learnt;
+
+        if (subsume1(lits, learnt)) {
+            //if we can't find it, that must be because it has been made non-learnt
+            //note: if it has been removed through elimination, it must't
+            //be able to subsume any non-learnt clauses, so we never enter here
+            if (findWBin(solver.watches, lits[0], lits[1], true)) {
+                findWatchedOfBin(solver.watches, lits[0], lits[1], learnt).setLearnt(false);
+                findWatchedOfBin(solver.watches, lits[1], lits[0], learnt).setLearnt(false);
             }
-            endS:;
         }
+        if (!solver.ok) return false;
+        clBinSize++;
+    }
+    clBinTouched.clear();
 
-        subsume1PartialQs[i] = ~subsume1PartialQs[i];
-        subsume1PartialSubs.clear();
+    if (solver.conf.verbosity >= 3) {
+        std::cout << "c subs-w-newbins " << clauses_subsumed - clauses_subsumed_before
+        << " lits rem " << literals_removed - literals_removed_before
+        << " went through: " << clBinSize << std::endl;
     }
-    unregisterIteration(subsume1PartialSubs);
+
+    return true;
 }
 
-void Subsumer::updateClause(ClauseSimp c)
+/**
+@brief Handles if a clause became 1-long (unitary)
+
+Either sets&propagates the value, ignores the value (if already set),
+or sets solver.ok = FALSE
+
+@param[in] lit The single literal the clause has
+*/
+inline void Subsumer::handleSize1Clause(const Lit lit)
 {
-    subsume0(*c.clause, c.clause->getAbst());
-    if (c.clause->learnt() && subsumedNonLearnt)
-        c.clause->makeNonLearnt();
-    
-    cl_touched.add(c);
+    if (solver.value(lit) == l_False) {
+        solver.ok = false;
+    } else if (solver.value(lit) == l_Undef) {
+        solver.uncheckedEnqueue(lit);
+        solver.ok = solver.propagate().isNULL();
+    } else {
+        assert(solver.value(lit) == l_True);
+    }
 }
 
-void Subsumer::almost_all_database()
+/**
+@brief Executes subsume1() recursively on all clauses
+
+This function requires cl_touched to have been set. Then, it manages cl_touched.
+The clauses are called to perform subsume1() or subsume0() when appropriate, and
+when there is enough numMaxSubume1 and numMaxSubume0 is available.
+*/
+const bool Subsumer::subsume0AndSubsume1()
 {
+    CSet s0, s1;
+
+    //uint32_t clTouchedTodo = cl_touched.nElems();
+    uint32_t clTouchedTodo = 100000;
+    if (addedClauseLits > 1500000) clTouchedTodo /= 2;
+    if (addedClauseLits > 3000000) clTouchedTodo /= 2;
+    if (addedClauseLits > 10000000) clTouchedTodo /= 2;
+    if (alsoLearnt) {
+        clTouchedTodo /= 2;
+        /*clTouchedTodo = std::max(clTouchedTodo, (uint32_t)20000);
+        clTouchedTodo = std::min(clTouchedTodo, (uint32_t)5000);*/
+    } else {
+        /*clTouchedTodo = std::max(clTouchedTodo, (uint32_t)20000);
+        clTouchedTodo = std::min(clTouchedTodo, (uint32_t)5000);*/
+    }
+
+    if (!solver.conf.doSubsume1) clTouchedTodo = 0;
+
+    registerIteration(s0);
+    registerIteration(s1);
+    vec<ClauseSimp> remClTouched;
+
+    // Fixed-point for 1-subsumption:
     #ifdef BIT_MORE_VERBOSITY
-    std::cout << "c Larger database" << std::endl;
+    std::cout << "c  cl_touched.nElems() = " << cl_touched.nElems() << std::endl;
     #endif
-    // Optimized variant when virtually whole database is involved:
-    cl_added  .clear();
-    cl_touched.clear();
-    
-    for (uint32_t i = 0; i < clauses.size(); i++) {
-        if (numMaxSubsume1 == 0) break;
-        if (clauses[i].clause != NULL) {
-            subsume1(clauses[i]);
-            numMaxSubsume1--;
-            if (!solver.ok) return;
-        }
-    }
-    
-    assert(solver.ok);
-    solver.ok = (solver.propagate().isNULL());
-    if (!solver.ok) {
-        return;
-    }
-    solver.clauseCleaner->cleanClausesBewareNULL(clauses, ClauseCleaner::simpClauses, *this);
-    
-    #ifdef VERBOSE_DEBUG
-    cout << "subsume1 part 1 finished" << endl;
-    #endif
-    
-    CSet s1;
-    registerIteration(s1);
-    while (cl_touched.size() > 0 && numMaxSubsume1 > 0){
+    do {
         #ifdef VERBOSE_DEBUG
-        std::cout << "c cl_touched was > 0, new iteration" << std::endl;
-        #endif
+        std::cout << "c  -- subsume0AndSubsume1() round --" << std::endl;
+        std::cout << "c  cl_touched.nElems() = " << cl_touched.nElems() << std::endl;
+        std::cout << "c  clauses.size() = " << clauses.size() << std::endl;
+        std::cout << "c  numMaxSubsume0:" << numMaxSubsume0 << std::endl;
+        std::cout << "c  numMaxSubsume1:" << numMaxSubsume1 << std::endl;
+        std::cout << "c  numMaxElim:" << numMaxElim << std::endl;
+        #endif //VERBOSE_DEBUG
+
+        uint32_t s1Added = 0;
+        vec<Lit> setNeg;
         for (CSet::iterator it = cl_touched.begin(), end = cl_touched.end(); it != end; ++it) {
-            if (it->clause != NULL)
-                s1.add(*it);
-        }
-        cl_touched.clear();
-        
-        for (CSet::iterator it = s1.begin(), end = s1.end(); it != end; ++it) {
-            if (numMaxSubsume1 == 0) break;
-            if (it->clause != NULL) {
-                subsume1(*it);
-                numMaxSubsume1--;
-                if (!solver.ok) return;
+
+            if (it->clause == NULL) continue;
+            Clause& cl = *it->clause;
+
+            bool tooMuch = s1Added >= clTouchedTodo;
+            if (numMaxSubsume1 <= 0) tooMuch = false;
+            bool addedAnyway = true;
+
+            uint32_t smallestPosSize = std::numeric_limits<uint32_t>::max();
+            Lit smallestPos = lit_Undef;
+
+            if (!tooMuch) s1Added += s1.add(*it);
+            else if (!s1.alreadyIn(*it)) addedAnyway = false;
+            s0.add(*it);
+
+            for (uint32_t j = 0; j < cl.size() && addedAnyway; j++) {
+                if (ol_seenPos[cl[j].toInt()] || smallestPos == lit_Error) {
+                    smallestPos = lit_Error;
+                    goto next;
+                }
+                if (occur[cl[j].toInt()].size() < smallestPosSize) {
+                    smallestPos = cl[j];
+                    smallestPosSize = occur[cl[j].toInt()].size();
+                }
+
+                next:
+                if (ol_seenNeg[(~cl[j]).toInt()]) continue;
+                vec<ClauseSimp>& n_occs = occur[(~cl[j]).toInt()];
+                for (uint32_t k = 0; k < n_occs.size(); k++) {
+                    if (tooMuch && !s1.alreadyIn(n_occs[k])) {
+                        addedAnyway = false;
+                        goto next2;
+                    }
+                    s1Added += s1.add(n_occs[k]);
+                }
+                ol_seenNeg[(~cl[j]).toInt()] = 1;
+                setNeg.push(~cl[j]);
             }
+            next2:;
+
+            if (smallestPos != lit_Undef && smallestPos != lit_Error && addedAnyway) {
+                vec<ClauseSimp>& p_occs = occur[smallestPos.toInt()];
+                for (uint32_t k = 0; k < p_occs.size(); k++) {
+                    if (tooMuch && !s0.alreadyIn(p_occs[k])) {
+                        addedAnyway = false;
+                        goto next3;
+                    }
+                    s0.add(p_occs[k]);
+                }
+                ol_seenPos[smallestPos.toInt()] = 1;
+            }
+
+            next3:
+            if (addedAnyway) remClTouched.push(*it);
         }
-        s1.clear();
-        
-        if (!solver.ok) return;
-        solver.ok = (solver.propagate().isNULL());
-        if (!solver.ok) {
-            unregisterIteration(s1);
-            return;
-        }
-        solver.clauseCleaner->cleanClausesBewareNULL(clauses, ClauseCleaner::simpClauses, *this);
-    }
-    unregisterIteration(s1);
-}
+        //std::cout << "s0.nElems(): " << s0.nElems() << std::endl;
+        //std::cout << "s1.nElems(): " << s1.nElems() << std::endl;
 
-void Subsumer::smaller_database()
-{
-    #ifdef BIT_MORE_VERBOSITY
-    std::cout << "c Smaller database" << std::endl;
-    #endif
-    //  Set used in 1-subs:
-    //      (1) clauses containing a negated literal of an added clause.
-    //      (2) all added or strengthened ("touched") clauses.
-    //
-    //  Set used in 0-subs:
-    //      (1) clauses containing a (non-negated) literal of an added clause, including the added clause itself.
-    //      (2) all strenghtened clauses -- REMOVED!! We turned on eager backward subsumption which supersedes this.
-    
-    #ifdef BIT_MORE_VERBOSITY
-    printf("  PREPARING\n");
-    #endif
-    
-    CSet s0, s1;     // 's0' is used for 0-subsumption, 's1' for 1-subsumption
-    vec<char>   ol_seen(solver.nVars()*2, 0);
-    for (CSet::iterator it = cl_added.begin(), end = cl_added.end(); it != end; ++it) {
-        if (it->clause == NULL) continue;
-        ClauseSimp& c = *it;
-        Clause& cl = *it->clause;
-        
-        s1.add(c);
-        for (uint32_t j = 0; j < cl.size(); j++){
-            if (ol_seen[cl[j].toInt()]) continue;
-            ol_seen[cl[j].toInt()] = 1;
-            
-            vec<ClauseSimp>& n_occs = occur[(~cl[j]).toInt()];
-            for (uint32_t k = 0; k < n_occs.size(); k++)
-                if (n_occs[k].clause != c.clause && n_occs[k].clause->size() <= cl.size() && selfSubset(n_occs[k].clause->getAbst(), c.clause->getAbst()) && selfSubset(*n_occs[k].clause, cl, seen_tmp))
-                    s1.add(n_occs[k]);
-                
-            vec<ClauseSimp>& p_occs = occur[cl[j].toInt()];
-            for (uint32_t k = 0; k < p_occs.size(); k++)
-                if (subsetAbst(p_occs[k].clause->getAbst(), c.clause->getAbst()))
-                    s0.add(p_occs[k]);
+
+        bool doneAll = (numMaxSubsume1 > 0);
+        for (CSet::iterator it = s0.begin(), end = s0.end(); it != end; ++it) {
+            if (it->clause == NULL) continue;
+            subsume0(*it->clause);
+            if (!doneAll && numMaxSubsume0 < 0) break;
         }
-    }
-    cl_added.clear();
-    
-    registerIteration(s0);
-    registerIteration(s1);
-    
-    #ifdef BIT_MORE_VERBOSITY
-    printf("c FIXED-POINT\n");
-    #endif
-    
-    // Fixed-point for 1-subsumption:
-    while (s1.size() > 0 || cl_touched.size() > 0){
-        for (CSet::iterator it = cl_touched.begin(), end = cl_touched.end(); it != end; ++it) {
-            if (it->clause != NULL) {
-                s1.add(*it);
-                s0.add(*it);
+        s0.clear();
+
+        if (doneAll) {
+            for (CSet::iterator it = s1.begin(), end = s1.end(); it != end; ++it) {
+                if (it->clause == NULL) continue;
+                subsume1(*it->clause);
+                /*if (numMaxSubsume1 < 0) {
+                    doneAll = false;
+                    break;
+                }*/
+                //s0.exclude(*it);
+                if (!solver.ok) goto end;
             }
+            s1.clear();
         }
-        
-        cl_touched.clear();
-        assert(solver.qhead == solver.trail.size());
-        
-        #ifdef BIT_MORE_VERBOSITY
-        printf("c s1.size()=%d  cl_touched.size()=%d\n", s1.size(), cl_touched.size());
-        #endif
-        
-        for (CSet::iterator it = s1.begin(), end = s1.end(); it != end; ++it) {
-            if (numMaxSubsume1 == 0) break;
-            if (it->clause != NULL) {
-                subsume1(*it);
-                numMaxSubsume1--;
-                if (!solver.ok) return;
-            }
+
+        if (!handleClBinTouched()) goto end;
+        for (ClauseSimp *it = remClTouched.getData(), *end = remClTouched.getDataEnd(); it != end; it++) {
+            if (it->clause == NULL) continue;
+            if (doneAll) it->clause->unsetStrenghtened();
+            cl_touched.exclude(*it);
         }
-        s1.clear();
-        
-        if (!solver.ok) return;
-        solver.ok = (solver.propagate().isNULL());
-        if (!solver.ok){
-            unregisterIteration(s1);
-            unregisterIteration(s0);
-            return; 
+        if (!doneAll) {
+            for (Lit *l = setNeg.getData(), *end = setNeg.getDataEnd(); l != end; l++)
+                ol_seenNeg[l->toInt()] = 0;
         }
-        solver.clauseCleaner->cleanClausesBewareNULL(clauses, ClauseCleaner::simpClauses, *this);
-    }
+
+        #ifdef BIT_MORE_VERBOSITY
+        if (doneAll)
+            std::cout << "c Success with " << remClTouched.size() << " clauses, s1Added: " << s1Added << std::endl;
+        else
+            std::cout << "c No success with " << remClTouched.size() << " clauses, s1Added: " << s1Added << std::endl;
+        #endif //BIT_MORE_VERBOSITY
+        remClTouched.clear();
+    } while ((cl_touched.nElems() > 100) && numMaxSubsume0 > 0);
+
+    end:
+    cl_touched.clear();
     unregisterIteration(s1);
-    
-    // Iteration pass for 0-subsumption:
-    for (CSet::iterator it = s0.begin(), end = s0.end(); it != end; ++it) {
-        if (it->clause != NULL) {
-            subsume0(*it->clause, it->clause->getAbst());
-            if (subsumedNonLearnt && it->clause->learnt()) it->clause->makeNonLearnt();
-        }
-    }
-    s0.clear();
     unregisterIteration(s0);
+
+    return solver.ok;
 }
 
+/**
+@brief Links in a clause into the occurrence lists and the clauses[]
+
+Increments clauseID
+
+@param[in] cl The clause to link in
+*/
 ClauseSimp Subsumer::linkInClause(Clause& cl)
 {
     ClauseSimp c(&cl, clauseID++);
     clauses.push(c);
     for (uint32_t i = 0; i < cl.size(); i++) {
         occur[cl[i].toInt()].push(c);
-        touch(cl[i].var());
+        touch(cl[i], cl.learnt());
     }
-    cl_added.add(c);
-    
+    cl_touched.add(c);
+
     return c;
 }
 
-void Subsumer::linkInAlreadyClause(ClauseSimp& c)
-{
-    Clause& cl = *c.clause;
-    for (uint32_t i = 0; i < cl.size(); i++) {
-        occur[cl[i].toInt()].push(c);
-        touch(cl[i].var());
-    }
-}
+/**
+@brief Adds clauses from the solver to here, and removes them from the solver
 
-template<bool UseCL>
-void Subsumer::addFromSolver(vec<Clause*>& cs, bool alsoLearnt)
+Which clauses are needed can be controlled by the parameters
+
+@param[in] cs The clause-set to use, e.g. solver.binaryClauses, solver.learnts
+@param[in] alsoLearnt Also add learnt clauses?
+@param[in] addBinAndAddToCL If set to FALSE, binary clauses are not added, and
+clauses are never added to the cl_touched set.
+*/
+const uint64_t Subsumer::addFromSolver(vec<Clause*>& cs)
 {
+    uint64_t numLitsAdded = 0;
     Clause **i = cs.getData();
     Clause **j = i;
     for (Clause **end = i + cs.size(); i !=  end; i++) {
@@ -790,14 +820,6 @@ void Subsumer::addFromSolver(vec<Clause*>& cs, bool alsoLearnt)
 
         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;
         }
 
@@ -806,19 +828,20 @@ void Subsumer::addFromSolver(vec<Clause*>& cs, bool alsoLearnt)
         Clause& cl = *c.clause;
         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.getStrenghtened()) touch(cl[i], cl.learnt());
         }
+        numLitsAdded += cl.size();
 
-        if (!cl.learnt() && (cl.getVarChanged() || cl.getStrenghtened()))
-            cl.calcAbstractionClause();
+        if (cl.getStrenghtened()) cl_touched.add(c);
     }
     cs.shrink(i-j);
+
+    return numLitsAdded;
 }
 
+/**
+@brief Frees memory occupied by occurrence lists
+*/
 void Subsumer::freeMemory()
 {
     for (uint32_t i = 0; i < occur.size(); i++) {
@@ -826,45 +849,29 @@ void Subsumer::freeMemory()
     }
 }
 
+/**
+@brief Adds clauses from here, back to the solver
+*/
 void Subsumer::addBackToSolver()
 {
-    #ifdef HYPER_DEBUG2
-    uint32_t binaryLearntAdded = 0;
-    #endif
-
     assert(solver.clauses.size() == 0);
     for (uint32_t i = 0; i < clauses.size(); i++) {
-        if (clauses[i].clause != NULL) {
-            assert(clauses[i].clause->size() > 1);
-            if (clauses[i].clause->size() == 2) {
-                #ifdef HYPER_DEBUG2
-                if (clauses[i].clause->learnt())
-                    binaryLearntAdded++;
-                #endif
-                Clause* c = clauses[i].clause;
-                if (!c->wasBin()) {
-                    solver.detachClause(*c);
-                    Clause *c2 = solver.clauseAllocator.Clause_new(*c);
-                    solver.clauseAllocator.clauseFree(c);
-                    solver.attachClause(*c2);
-                    solver.becameBinary++;
-                    c = c2;
-                }
-                solver.binaryClauses.push(c);
-            } else {
-                if (clauses[i].clause->learnt())
-                    solver.learnts.push(clauses[i].clause);
-                else
-                    solver.clauses.push(clauses[i].clause);
-            }
-        }
+        if (clauses[i].clause == NULL) continue;
+        assert(clauses[i].clause->size() > 2);
+
+        if (clauses[i].clause->learnt())
+            solver.learnts.push(clauses[i].clause);
+        else
+            solver.clauses.push(clauses[i].clause);
     }
-    
-    #ifdef HYPER_DEBUG2
-    std::cout << "Binary learnt added:" << binaryLearntAdded << std::endl;
-    #endif
 }
 
+/**
+@brief Remove clauses from input that contain eliminated variables
+
+Used to remove learnt clauses that still reference a variable that has been
+eliminated.
+*/
 void Subsumer::removeWrong(vec<Clause*>& cs)
 {
     Clause **i = cs.getData();
@@ -879,7 +886,7 @@ void Subsumer::removeWrong(vec<Clause*>& cs)
         for (Lit *l = c.getData(), *end2 = l+c.size(); l != end2; l++) {
             if (var_elimed[l->var()]) {
                 remove = true;
-                solver.detachClause(c);
+                //solver.detachClause(c);
                 solver.clauseAllocator.clauseFree(&c);
                 break;
             }
@@ -890,6 +897,44 @@ void Subsumer::removeWrong(vec<Clause*>& cs)
     cs.shrink(i-j);
 }
 
+void Subsumer::removeWrongBinsAndAllTris()
+{
+    uint32_t numRemovedHalfLearnt = 0;
+    uint32_t wsLit = 0;
+    for (vec<Watched> *it = solver.watches.getData(), *end = solver.watches.getDataEnd(); it != end; it++, wsLit++) {
+        Lit lit = ~Lit::toLit(wsLit);
+        vec<Watched>& ws = *it;
+
+        Watched* i = ws.getData();
+        Watched* j = i;
+        for (Watched *end2 = ws.getDataEnd(); i != end2; i++) {
+            if (i->isTriClause()) continue;
+
+            if (i->isBinary()
+                && (var_elimed[lit.var()] || var_elimed[i->getOtherLit().var()])
+                ) {
+                assert(i->getLearnt());
+                numRemovedHalfLearnt++;
+            } else {
+                *j++ = *i;
+            }
+        }
+        ws.shrink_(i - j);
+    }
+
+    assert(numRemovedHalfLearnt % 2 == 0);
+    solver.learnts_literals -= numRemovedHalfLearnt;
+    solver.numBins -= numRemovedHalfLearnt/2;
+}
+
+/**
+@brief Fills the vector cannot_eliminate
+
+Variables that are:
+* also present in XOR-clauses, or
+* have been replaced
+cannot be eliminated. This is enforced by the vector cannot_elimnate
+*/
 void Subsumer::fillCannotEliminate()
 {
     std::fill(cannot_eliminate.getData(), cannot_eliminate.getDataEnd(), false);
@@ -898,14 +943,11 @@ void Subsumer::fillCannotEliminate()
         for (uint32_t i2 = 0; i2 < c.size(); i2++)
             cannot_eliminate[c[i2].var()] = true;
     }
-    
-    const vec<Clause*>& tmp = solver.varReplacer->getClauses();
-    for (uint32_t i = 0; i < tmp.size(); i++) {
-        const Clause& c = *tmp[i];
-        for (uint32_t i2 = 0; i2 < c.size(); i2++)
-            cannot_eliminate[c[i2].var()] = true;
+
+    for (Var var = 0; var < solver.nVars(); var++) {
+        cannot_eliminate[var] |= solver.varReplacer->cannot_eliminate[var];
     }
-    
+
     #ifdef VERBOSE_DEBUG
     uint32_t tmpNum = 0;
     for (uint32_t i = 0; i < cannot_eliminate.size(); i++)
@@ -915,975 +957,1254 @@ void Subsumer::fillCannotEliminate()
     #endif
 }
 
-const bool Subsumer::subsumeWithBinaries(OnlyNonLearntBins* onlyNonLearntBins)
-{
-    clearAll();
-    clauseID = 0;
-    fullSubsume = true;
-    addBinaryClauses.clear();
+/**
+@brief Subsumes&strenghtens normal clauses with (non-existing) binary clauses
 
+First, it backward-subsumes and performs self-subsuming resolution using binary
+clauses on non-binary clauses. Then, it generates non-existing binary clauses
+(that could exist, but would be redundant), and performs self-subsuming
+resolution with them on the normal clauses using \function subsume0BIN().
+*/
+const bool Subsumer::subsumeWithBinaries()
+{
     //Clearing stats
-    subsNonExistentumFailed = 0;
+    double myTime = cpuTime();
     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<false>(solver.clauses);
-    #ifdef DEBUG_BINARIES
-    for (uint32_t i = 0; i < clauses.size(); i++) {
-        assert(clauses[i].clause->size() != 2);
-    }
-    #endif //DEBUG_BINARIES
-
-    numMaxSubsume0 = 300000 * (1+numCalls/2);
-    numMaxSubsume1 = 10000 * (1+numCalls);
-
-    for (uint32_t i = 0; i < solver.binaryClauses.size(); i++) {
-        if (!solver.binaryClauses[i]->learnt() && numMaxSubsume0 > 0) {
-            Clause& c = *solver.binaryClauses[i];
-            subsume0(c, c.getAbst());
-            numMaxSubsume0--;
-        }
-    }
-    for (uint32_t i = 0; i < solver.binaryClauses.size(); i++) {
-        if (numMaxSubsume1 > 0) {
-            Clause& c = *solver.binaryClauses[i];
-            subsume1Partial(c);
-            if (!solver.ok) return false;
-            numMaxSubsume1--;
+    vec<Lit> lits(2);
+    uint32_t counter = 0;
+    uint32_t thisRand = solver.mtrand.randInt();
+    for (const vec<Watched> *it = solver.watches.getData(); counter != solver.nVars()*2; counter++) {
+        uint32_t wsLit = (counter + thisRand) % (solver.nVars()*2);
+        Lit lit = ~Lit::toLit(wsLit);
+        lits[0] = lit;
+        const vec<Watched> ws_backup = *(it + wsLit);
+        for (const Watched *it2 = ws_backup.getData(), *end2 = ws_backup.getDataEnd(); it2 != end2; it2++) {
+            if (it2->isBinary() && lit.toInt() < it2->getOtherLit().toInt()) {
+                lits[1] = it2->getOtherLit();
+                bool toMakeNonLearnt = subsume1(lits, it2->getLearnt());
+                if (toMakeNonLearnt) makeNonLearntBin(lit, it2->getOtherLit(), it2->getLearnt());
+                if (!solver.ok) return false;
+            }
         }
+        if (numMaxSubsume1 < 0) break;
     }
-    if (solver.verbosity >= 1) {
+
+    if (solver.conf.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) <<solver.trail.size() - origTrailSize
         << "  time: " << std::setprecision(2) << std::setw(5) <<  cpuTime() - myTime << " s"
-        << std::setw(17)  << "   |" << std::endl;
+        << std::endl;
     }
-    
-    if (!subsWNonExistBinsFull(onlyNonLearntBins)) return false;
 
-    #ifdef DEBUG_BINARIES
-    for (uint32_t i = 0; i < clauses.size(); i++) {
-        assert(clauses[i].clause == NULL || clauses[i].clause->size() != 2);
+    return true;
+}
+
+const bool Subsumer::subsWNonExitsBinsFullFull()
+{
+    double myTime = cpuTime();
+    clauses_subsumed = 0;
+    literals_removed = 0;
+    for (vec<Watched> *it = solver.watches.getData(), *end = solver.watches.getDataEnd(); it != end; it++) {
+        if (it->size() < 2) continue;
+        std::sort(it->getData(), it->getDataEnd(), BinSorter2());
     }
-    #endif //DEBUG_BINARIES
-    addBackToSolver();
-    for (uint32_t i = 0; i < addBinaryClauses.size(); i++) {
-        Clause& c = *addBinaryClauses[i];
-        solver.detachClause(c);
-        Clause *c2 = solver.clauseAllocator.Clause_new(c);
-        solver.clauseAllocator.clauseFree(&c);
-        solver.attachClause(*c2);
-        solver.becameBinary++;
-        solver.binaryClauses.push(c2);
-    }
-    addBinaryClauses.clear();
-    freeMemory();
-
-    if (solver.verbosity >= 1) {
-        std::cout << "c Subs w/ non-existent bins: " << std::setw(6) << subsNonExistentNum
-        << " l-rem: " << std::setw(6) << subsNonExistentLitsRemoved
-        << " v-fix: " << std::setw(5) << subsNonExistentumFailed
+
+    uint32_t oldTrailSize = solver.trail.size();
+    if (!subsWNonExistBinsFull()) return false;
+
+    if (solver.conf.verbosity  >= 1) {
+        std::cout << "c Subs w/ non-existent bins: " << std::setw(6) << clauses_subsumed
+        << " l-rem: " << std::setw(6) << literals_removed
+        << " v-fix: " << std::setw(5) << solver.trail.size() - oldTrailSize
         << " done: " << std::setw(6) << doneNum
-        << " time: " << std::fixed << std::setprecision(2) << std::setw(5) << subsNonExistentTime << " s"
-        << std::setw(2)  << " |" << std::endl;
+        << " time: " << std::fixed << std::setprecision(2) << std::setw(5) << (cpuTime() - myTime) << " s"
+        << std::endl;
     }
-    totalTime += cpuTime() - myTime;
-    solver.order_heap.filter(Solver::VarFilter(solver));
 
+    totalTime += cpuTime() - myTime;
     return true;
 }
 
-#define MAX_BINARY_PROP 40000000
+void Subsumer::makeNonLearntBin(const Lit lit1, const Lit lit2, const bool learnt)
+{
+    assert(learnt == true);
+    findWatchedOfBin(solver.watches, lit1 ,lit2, learnt).setLearnt(false);
+    findWatchedOfBin(solver.watches, lit2 ,lit1, learnt).setLearnt(false);
+    solver.learnts_literals -= 2;
+    solver.clauses_literals += 2;
+}
+
+#define MAX_BINARY_PROP 60000000
+
+/**
+@brief Call subsWNonExistBins with randomly picked starting literals
 
-const bool Subsumer::subsWNonExistBinsFull(OnlyNonLearntBins* onlyNonLearntBins)
+This is the function that overviews the deletion of all clauses that could be
+inferred from non-existing binary clauses, and the strenghtening (through self-
+subsuming resolution) of clauses that could be strenghtened using non-existent
+binary clauses.
+*/
+const bool Subsumer::subsWNonExistBinsFull()
 {
-    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;
-    if (clauses.size() > 2000000) maxProp /= 2;
-    ps2.clear();
-    ps2.growTo(2);
+    uint64_t maxProp = MAX_BINARY_PROP*7;
+    toVisitAll.clear();
     toVisitAll.growTo(solver.nVars()*2, false);
+    extraTimeNonExist = 0;
+    OnlyNonLearntBins* onlyNonLearntBins = NULL;
+    if (solver.clauses_literals < 10*1000*1000) {
+        onlyNonLearntBins = new OnlyNonLearntBins(solver);
+        onlyNonLearntBins->fill();
+        solver.multiLevelProp = true;
+    }
 
     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;
+        Var var = solver.order_heap[(startFrom + i) % solver.order_heap.size()];
+        if (solver.propagations + extraTimeNonExist*150 > oldProps + maxProp) break;
         if (solver.assigns[var] != l_Undef || !solver.decision_var[var]) continue;
         doneNum++;
+        extraTimeNonExist += 5;
 
         Lit lit(var, true);
+        if (onlyNonLearntBins != NULL && onlyNonLearntBins->getWatchSize(lit) == 0) goto next;
         if (!subsWNonExistBins(lit, onlyNonLearntBins)) {
             if (!solver.ok) return false;
-            solver.cancelUntil(0);
+            solver.cancelUntilLight();
             solver.uncheckedEnqueue(~lit);
-            solver.ok = (solver.propagate().isNULL());
+            solver.ok = solver.propagate().isNULL();
             if (!solver.ok) return false;
             continue;
         }
+        extraTimeNonExist += 10;
+        next:
 
         //in the meantime it could have got assigned
         if (solver.assigns[var] != l_Undef) continue;
         lit = ~lit;
+        if (onlyNonLearntBins != NULL && onlyNonLearntBins->getWatchSize(lit) == 0) continue;
         if (!subsWNonExistBins(lit, onlyNonLearntBins)) {
             if (!solver.ok) return false;
-            solver.cancelUntil(0);
+            solver.cancelUntilLight();
             solver.uncheckedEnqueue(~lit);
-            solver.ok = (solver.propagate().isNULL());
+            solver.ok = solver.propagate().isNULL();
             if (!solver.ok) return false;
             continue;
         }
+        extraTimeNonExist += 10;
     }
-    subsNonExistentNum = clauses_subsumed - oldClausesSubusmed;
-    subsNonExistentTime = cpuTime() - myTime;
-    subsNonExistentumFailed = solver.trail.size() - oldTrailSize;
-    subsNonExistentLitsRemoved = literals_removed - oldLitsRemoved;
+
+    if (onlyNonLearntBins) delete onlyNonLearntBins;
 
     return true;
 }
 
+/**
+@brief Subsumes&strenghtens clauses with non-existent binary clauses
+
+Generates binary clauses that could exist, then calls \function subsume0BIN()
+with them, thus performing self-subsuming resolution and subsumption on the
+clauses.
+
+@param[in] lit This literal is the starting point of this set of non-existent
+binary clauses (this literal is the starting point in the binary graph)
+@param onlyNonLearntBins This class is initialised before calling this function
+and contains all the non-learnt binary clauses
+*/
 const bool Subsumer::subsWNonExistBins(const Lit& lit, OnlyNonLearntBins* onlyNonLearntBins)
 {
     #ifdef VERBOSE_DEBUG
-    std::cout << "subsWNonExistBins called with lit "; lit.print();
-    std::cout << std::endl;
+    std::cout << "subsWNonExistBins called with lit " << lit << std::endl;
     #endif //VERBOSE_DEBUG
     toVisit.clear();
     solver.newDecisionLevel();
     solver.uncheckedEnqueueLight(lit);
-    bool failed = !onlyNonLearntBins->propagate();
+    bool failed;
+    if (onlyNonLearntBins == NULL)
+        failed = (!solver.propagateNonLearntBin().isNULL());
+    else
+        failed = !onlyNonLearntBins->propagate();
     if (failed) return false;
+    uint32_t abst = 0;
 
     assert(solver.decisionLevel() > 0);
-    for (int c = solver.trail.size()-1; c > (int)solver.trail_lim[0]; c--) {
-        Lit x = solver.trail[c];
+    for (int sublevel = solver.trail.size()-1; sublevel > (int)solver.trail_lim[0]; sublevel--) {
+        Lit x = solver.trail[sublevel];
         toVisit.push(x);
+        abst |= 1 << (x.var() & 31);
         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);
-            if (!solver.ok) goto end;
-        }
+        solver.assigns[x.var()] = l_Undef;
+    }
+    solver.assigns[solver.trail[solver.trail_lim[0]].var()] = l_Undef;
+    solver.qhead = solver.trail_lim[0];
+    solver.trail.shrink_(solver.trail.size() - solver.trail_lim[0]);
+    solver.trail_lim.shrink_(solver.trail_lim.size());
+    //solver.cancelUntilLight();
+
+    if ((onlyNonLearntBins != NULL && toVisit.size() <= onlyNonLearntBins->getWatchSize(lit))
+        || (!solver.multiLevelProp)) {
+        //This has been performed above, with subsume1Partial of binary clauses:
+        //this toVisit.size()<=1, there mustn't have been more than 1 binary
+        //clause in the watchlist, so this has been performed above.
     } else {
-        subsume0BIN(~lit, toVisitAll);
-        if (!solver.ok) goto end;
+        subsume0BIN(~lit, toVisitAll, abst);
     }
 
-    end:
     for (uint32_t i = 0; i < toVisit.size(); i++)
         toVisitAll[toVisit[i].toInt()] = false;
 
     return solver.ok;
 }
+/**
+@brief Clears and deletes (almost) everything in this class
 
+Clears touchlists, occurrance lists, clauses, and variable touched lists
+*/
 void Subsumer::clearAll()
 {
-    touched_list.clear();
-    touched.clear();
-    touched.growTo(solver.nVars(), false);
+    touchedVarsList.clear();
+    touchedVars.clear();
+    touchedVars.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();
+    addedClauseLits = 0;
 }
 
-const bool Subsumer::simplifyBySubsumption(const bool alsoLearnt)
+const bool Subsumer::eliminateVars()
 {
-    if (solver.nClauses() > 20000000)  return true;
-    
-    double myTime = cpuTime();
-    uint32_t origTrailSize = solver.trail.size();
-    clauses_subsumed = 0;
-    literals_removed = 0;
-    numblockedClauseRemoved = 0;
-    numCalls++;
-    clauseID = 0;
-    numVarsElimed = 0;
-    blockTime = 0.0;
-    clearAll();
-    
-    //if (solver.xorclauses.size() < 30000 && solver.clauses.size() < MAX_CLAUSENUM_XORFIND/10) addAllXorAsNorm();
-
-    if (solver.performReplace && !solver.varReplacer->performReplace(true))
-        return false;
-    fillCannotEliminate();
-
-    uint32_t expected_size;
-    if (!alsoLearnt)
-        expected_size = solver.clauses.size() + solver.binaryClauses.size();
-    else
-        expected_size = solver.clauses.size() + solver.binaryClauses.size() + solver.learnts.size();
-    clauses.reserve(expected_size);
-    cl_added.reserve(expected_size);
-    cl_touched.reserve(expected_size);
-    
-    if (clauses.size() < 200000) fullSubsume = true;
-    else fullSubsume = false;
-    if (alsoLearnt) fullSubsume = true;
-
-    //solver.clauseCleaner->cleanClauses(solver.learnts, ClauseCleaner::learnts);
-    //addFromSolver<true>(solver.learnts, alsoLearnt);
-    solver.clauseCleaner->cleanClauses(solver.clauses, ClauseCleaner::clauses);
-    addFromSolver<true>(solver.clauses, alsoLearnt);
-
-    //It is IMPERATIVE to add binaryClauses last. The non-binary clauses can
-    //move to binaryClauses during cleaning!!!!
-    solver.clauseCleaner->removeSatisfied(solver.binaryClauses, ClauseCleaner::binaryClauses);
-    addFromSolver<true>(solver.binaryClauses, alsoLearnt);
-    
-    //Limits
-    if (clauses.size() > 3500000) {
-        numMaxSubsume0 = 900000 * (1+numCalls/2);
-        numMaxElim = (uint32_t)((double)solver.order_heap.size() / 5.0 * (0.8+(double)(numCalls)/4.0));
-        numMaxSubsume1 = 100000 * (1+numCalls/2);
-        numMaxBlockToVisit = (int64_t)(30000.0 * (0.8+(double)(numCalls)/3.0));
-    }
-    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 (solver.order_heap.size() > 200000)
-        numMaxBlockVars = (uint32_t)((double)solver.order_heap.size() / 3.5 * (0.8+(double)(numCalls)/4.0));
-    else
-        numMaxBlockVars = (uint32_t)((double)solver.order_heap.size() / 1.5 * (0.8+(double)(numCalls)/4.0));
-
-    if (numCalls == 1) numMaxSubsume1 = 0;
-    if (!solver.doSubsume1) numMaxSubsume1 = 0;
-    if (alsoLearnt) {
-        numMaxElim = 0;
-        numMaxSubsume1 = 0;
-        numMaxBlockVars = 0;
-        numMaxBlockToVisit = 0;
-        fullSubsume = true;
-    }
-    
-    //For debugging
-    //numMaxBlockToVisit = std::numeric_limits<int64_t>::max();
-    //numMaxElim = std::numeric_limits<uint32_t>::max();
-    //numMaxSubsume0 = std::numeric_limits<uint32_t>::max();
-    //numMaxSubsume1 = std::numeric_limits<uint32_t>::max();
-    //numMaxBlockVars = std::numeric_limits<uint32_t>::max();
-    
     #ifdef BIT_MORE_VERBOSITY
-    std::cout << "c  num clauses:" << clauses.size() << std::endl;
-    std::cout << "c  time to link in:" << cpuTime()-myTime << std::endl;
+    std::cout << "c VARIABLE ELIMINIATION -- touchedVarsList size:" << touchedVarsList.size() << std::endl;
     #endif
-    
-    for (uint32_t i = 0; i < clauses.size(); i++) {
-        if (numMaxSubsume0 == 0) break;
-        if (clauses[i].clause != NULL && 
-            (fullSubsume
-            || !clauses[i].clause->subsume0IsFinished())
-            )
-        {
-            subsume0(*clauses[i].clause, clauses[i].clause->getAbst());
-            if (subsumedNonLearnt && clauses[i].clause->learnt()) clauses[i].clause->makeNonLearnt();
-            numMaxSubsume0--;
+    vec<Var> init_order;
+    orderVarsForElim(init_order);   // (will untouch all variables)
+
+    for (bool first = true; numMaxElim > 0 && numMaxElimVars > 0; first = false) {
+        uint32_t vars_elimed = 0;
+        vec<Var> order;
+
+        if (first) {
+            for (uint32_t i = 0; i < init_order.size(); i++) {
+                const Var var = init_order[i];
+                if (!cannot_eliminate[var] && solver.decision_var[var])
+                    order.push(var);
+                //no need to set touched[var] to false -- orderVarsForElim did that already
+            }
+        } else {
+            for (Var *it = touchedVarsList.getData(), *end = touchedVarsList.getDataEnd(); it != end; it++) {
+                const Var var = *it;
+                if (!cannot_eliminate[var] && solver.decision_var[var])
+                    order.push(var);
+                touchedVars[var] = false;
+            }
+            touchedVarsList.clear();
         }
-    }
-    
-    origNClauses = clauses.size();
-    
-    #ifdef BIT_MORE_VERBOSITY
-    std::cout << "c  time until pre-subsume0 clauses and subsume1 2-learnts:" << cpuTime()-myTime << std::endl;
-    #endif
-    
-    if (!solver.ok) return false;
-    #ifdef VERBOSE_DEBUG
-    std::cout << "c   pre-subsumed:" << clauses_subsumed << std::endl;
-    std::cout << "c   cl_added:" << cl_added.size() << std::endl;
-    std::cout << "c   cl_touched:" << cl_touched.size() << std::endl;
-    std::cout << "c   clauses:" << clauses.size() << std::endl;
-    std::cout << "c   origNClauses:" << origNClauses << std::endl;
-    #endif
-    
-    if (clauses.size() > 10000000)  goto endSimplifyBySubsumption;
-    if (solver.doBlockedClause && numCalls % 3 == 1) blockedClauseRemoval();
-    do{
-        #ifdef BIT_MORE_VERBOSITY
-        std::cout << "c time before the start of almost_all/smaller: " << cpuTime() - myTime << std::endl;
+        #ifdef VERBOSE_DEBUG
+        std::cout << "Order size:" << order.size() << std::endl;
         #endif
-        if (numMaxSubsume0 > 0) {
-            if (cl_added.size() > origNClauses / 2) {
-                almost_all_database();
-                if (!solver.ok) return false;
-            } else {
-                smaller_database();
+
+        for (uint32_t i = 0; i < order.size() && numMaxElim > 0 && numMaxElimVars > 0; i++) {
+            if (maybeEliminate(order[i])) {
                 if (!solver.ok) return false;
+                vars_elimed++;
+                numMaxElimVars--;
             }
         }
-        cl_added.clear();
-        assert(cl_added.size() == 0);
-        assert(solver.ok);
-        solver.ok = (solver.propagate().isNULL());
-        if (!solver.ok) {
-            return false;
-        }
-        solver.clauseCleaner->cleanClausesBewareNULL(clauses, ClauseCleaner::simpClauses, *this);
-        
-        #ifdef BIT_MORE_VERBOSITY
-        std::cout << "c time until the end of almost_all/smaller: " << cpuTime() - myTime << std::endl;
-        #endif
-        
-        if (!solver.doVarElim) break;
-        
+        if (vars_elimed == 0) break;
+
+        numVarsElimed += vars_elimed;
         #ifdef BIT_MORE_VERBOSITY
-        printf("c VARIABLE ELIMINIATION\n");
-        std::cout << "c  toucheds list size:" << touched_list.size() << std::endl;
+        std::cout << "c  #var-elim: " << vars_elimed << std::endl;
         #endif
-        vec<Var> init_order;
-        orderVarsForElim(init_order);   // (will untouch all variables)
-        
-        for (bool first = true; numMaxElim > 0; first = false){
-            uint32_t vars_elimed = 0;
-            vec<Var> order;
-            
-            if (first) {
-                //init_order.copyTo(order);
-                for (uint32_t i = 0; i < init_order.size(); i++) {
-                    const Var var = init_order[i];
-                    if (!cannot_eliminate[var] && solver.decision_var[var])
-                        order.push(var);
-                }
-            } else {
-                for (uint32_t i = 0; i < touched_list.size(); i++) {
-                    const Var var = touched_list[i];
-                    if (!cannot_eliminate[var] && solver.decision_var[var])
-                        order.push(var);
-                    touched[var] = false;
-                }
-                touched_list.clear();
+    }
+
+    return true;
+}
+
+void Subsumer::subsumeBinsWithBins()
+{
+    double myTime = cpuTime();
+    uint32_t numBinsBefore = solver.numBins;
+
+    uint32_t wsLit = 0;
+    for (vec<Watched> *it = solver.watches.getData(), *end = solver.watches.getDataEnd(); it != end; it++, wsLit++) {
+        vec<Watched>& ws = *it;
+        Lit lit = ~Lit::toLit(wsLit);
+        if (ws.size() < 2) continue;
+
+        std::sort(ws.getData(), ws.getDataEnd(), BinSorter());
+
+        Watched* i = ws.getData();
+        Watched* j = i;
+
+        Lit lastLit = lit_Undef;
+        bool lastLearnt = false;
+        for (Watched *end = ws.getDataEnd(); i != end; i++) {
+            if (!i->isBinary()) {
+                *j++ = *i;
+                continue;
             }
-            #ifdef VERBOSE_DEBUG
-            std::cout << "Order size:" << order.size() << std::endl;
-            #endif
-            
-            assert(solver.qhead == solver.trail.size());
-            for (uint32_t i = 0; i < order.size() && numMaxElim > 0; i++, numMaxElim--) {
-                if (maybeEliminate(order[i])) {
-                    if (!solver.ok) {
-                        return false;
-                    }
-                    vars_elimed++;
+            if (i->getOtherLit() == lastLit) {
+                //The sorting algorithm prefers non-learnt to learnt, so it is
+                //impossible to have non-learnt before learnt
+                assert(!(i->getLearnt() == false && lastLearnt == true));
+
+                assert(i->getOtherLit().var() != lit.var());
+                removeWBin(solver.watches[(~(i->getOtherLit())).toInt()], lit, i->getLearnt());
+                if (i->getLearnt()) solver.learnts_literals -= 2;
+                else {
+                    solver.clauses_literals -= 2;
+                    touch(lit, i->getLearnt());
+                    touch(i->getOtherLit(), i->getLearnt());
                 }
+                solver.numBins--;
+            } else {
+                lastLit = i->getOtherLit();
+                lastLearnt = i->getLearnt();
+                *j++ = *i;
             }
-            assert(solver.qhead == solver.trail.size());
-            
-            if (vars_elimed == 0) break;
-            
-            numVarsElimed += vars_elimed;
-            #ifdef BIT_MORE_VERBOSITY
-            printf("c  #var-elim: %d\n", vars_elimed);
-            std::cout << "c time until the end of varelim: " << cpuTime() - myTime << std::endl;
-            #endif
         }
-    }while (cl_added.size() > 100 && numMaxElim > 0);
-    endSimplifyBySubsumption:
-    
-    if (!solver.ok) return false;
-    solver.ok = (solver.propagate().isNULL());
-    if (!solver.ok) {
-        return false;
+        ws.shrink_(i-j);
     }
-    
-    #ifndef NDEBUG
-    verifyIntegrity();
-    #endif
-
-    removeWrong(solver.learnts);
-    removeWrong(solver.binaryClauses);
-    removeAssignedVarsFromEliminated();
 
-    solver.order_heap.filter(Solver::VarFilter(solver));
-    
-    addBackToSolver();
-    freeMemory();
-    
-    if (solver.verbosity >= 1) {
-        std::cout << "c |  lits-rem: " << std::setw(9) << literals_removed
-        << "  cl-subs: " << std::setw(8) << clauses_subsumed
-        << "  v-elim: " << std::setw(6) << numVarsElimed
-        << "  v-fix: " << std::setw(4) <<solver.trail.size() - origTrailSize
-        << "  time: " << std::setprecision(2) << std::setw(5) << (cpuTime() - myTime) << " s"
-        //<< " blkClRem: " << std::setw(5) << numblockedClauseRemoved
-        << "   |" << std::endl;
-        
-        if (numblockedClauseRemoved > 0 || blockTime > 0.0) {
-            std::cout 
-            << "c |  Blocked clauses removed: " << std::setw(8) << numblockedClauseRemoved 
-            << "    Time: " << std::fixed << std::setprecision(2) << std::setw(4) << blockTime << " s" 
-            << "                                    |" << std::endl;
-        }
+    if (solver.conf.verbosity  >= 1) {
+        std::cout << "c bin-w-bin subsume rem   "
+        << std::setw(10) << (numBinsBefore - solver.numBins) << " bins "
+        << " time: "
+        << std::fixed << std::setprecision(2) << std::setw(5) << (cpuTime() - myTime)
+        << " s" << std::endl;
     }
     totalTime += cpuTime() - myTime;
-
-    solver.testAllClauseAttach();
-    return true;
+    clauses_subsumed += (numBinsBefore - solver.numBins);
 }
 
-void Subsumer::removeAssignedVarsFromEliminated()
+/**
+@brief Main function in this class
+
+Performs, recursively:
+* backward-subsumption
+* self-subsuming resolution
+* variable elimination
+
+@param[in] alsoLearnt Should learnt clauses be also hooked into the occurrence
+lists? If so, variable elimination cannot take place.
+*/
+const bool Subsumer::simplifyBySubsumption(const bool _alsoLearnt)
 {
-    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<Var, vector<Clause*> >::iterator it = elimedOutVar.find(var);
-            if (it != elimedOutVar.end()) {
-                //TODO memory loss here
-                elimedOutVar.erase(it);
-            }
-        }
-    }
-}
+    alsoLearnt = _alsoLearnt;
+    if (solver.nClauses() > 50000000
+        || solver.clauses_literals > 500000000)  return true;
 
-template<class T>
+    double myTime = cpuTime();
+    clauseID = 0;
+    clearAll();
+
+    //if (solver.xorclauses.size() < 30000 && solver.clauses.size() < MAX_CLAUSENUM_XORFIND/10) addAllXorAsNorm();
+
+    if (solver.conf.doReplace && !solver.varReplacer->performReplace(true))
+        return false;
+    fillCannotEliminate();
+
+    uint32_t expected_size = solver.clauses.size();
+    if (alsoLearnt) expected_size += solver.learnts.size();
+    clauses.reserve(expected_size);
+    cl_touched.reserve(expected_size);
+
+    solver.clauseCleaner->cleanClauses(solver.clauses, ClauseCleaner::clauses);
+    if (alsoLearnt) {
+        solver.clauseCleaner->cleanClauses(solver.learnts, ClauseCleaner::learnts);
+
+        if (solver.learnts.size() < 10000000)
+            std::sort(solver.learnts.getData(), solver.learnts.getDataEnd(), sortBySize());
+        addedClauseLits += addFromSolver(solver.learnts);
+    } else {
+        if (solver.clauses.size() < 10000000)
+            std::sort(solver.clauses.getData(), solver.clauses.getDataEnd(), sortBySize());
+        addedClauseLits += addFromSolver(solver.clauses);
+    }
+
+    CompleteDetachReatacher reattacher(solver);
+    reattacher.detachNonBinsNonTris(false);
+    totalTime += myTime - cpuTime();
+
+    //Do stuff with binaries
+    if (alsoLearnt) {
+        numMaxSubsume1 = 500*1000*1000;
+        if (solver.conf.doSubsWBins && !subsumeWithBinaries()) return false;
+        addedClauseLits += addFromSolver(solver.clauses);
+    } else {
+        if ((solver.conf.doBlockedClause || numCalls == 2)
+            && solver.conf.doVarElim) {
+            numMaxBlockToVisit = (int64_t)800*1000*1000;
+            blockedClauseRemoval();
+        }
+
+        subsumeBinsWithBins();
+        numMaxSubsume1 = 2*1000*1000*1000;
+        if (solver.conf.doSubsWBins && !subsumeWithBinaries()) return false;
+        if (solver.conf.doSubsWNonExistBins && !subsWNonExitsBinsFullFull()) return false;
+        if (!handleClBinTouched()) return false;
+
+        if (solver.conf.doReplace && solver.conf.doRemUselessBins) {
+            UselessBinRemover uselessBinRemover(solver);
+            if (!uselessBinRemover.removeUslessBinFull()) return false;
+        }
+    }
+
+    myTime = cpuTime();
+    setLimits();
+    clauses_subsumed = 0;
+    literals_removed = 0;
+    numVarsElimed = 0;
+    uint32_t origTrailSize = solver.trail.size();
+
+    #ifdef BIT_MORE_VERBOSITY
+    std::cout << "c  time until pre-subsume0 clauses and subsume1 2-learnts:" << cpuTime()-myTime << std::endl;
+    std::cout << "c  pre-subsumed:" << clauses_subsumed << std::endl;
+    std::cout << "c  cl_touched:" << cl_touched.nElems() << std::endl;
+    std::cout << "c  clauses:" << clauses.size() << std::endl;
+    std::cout << "c  numMaxSubsume0:" << numMaxSubsume0 << std::endl;
+    std::cout << "c  numMaxSubsume1:" << numMaxSubsume1 << std::endl;
+    std::cout << "c  numMaxElim:" << numMaxElim << std::endl;
+    #endif
+
+    /*for (ClauseSimp *it = clauses.getData(), *end = clauses.getDataEnd(); it != end; ++it) {
+        if (it->clause == NULL) continue;
+        //if (!it->clause->learnt()) continue;
+        subsume1(*it->clause);
+    }*/
+    //setLimits(alsoLearnt);
+
+    if (clauses.size() > 10000000 ||
+        (numMaxSubsume1 < 0 && numMaxElim == 0 && numMaxBlockVars == 0))
+        goto endSimplifyBySubsumption;
+
+    do {
+        if (!subsume0AndSubsume1()) return false;
+
+        if (!solver.conf.doVarElim) break;
+
+        if (!eliminateVars()) return false;
+
+        //subsumeBinsWithBins();
+        //if (solver.conf.doSubsWBins && !subsumeWithBinaries()) return false;
+        solver.clauseCleaner->removeSatisfiedBins();
+    } while (cl_touched.nElems() > 100);
+    endSimplifyBySubsumption:
+
+    if (!solver.ok) return false;
+
+    assert(verifyIntegrity());
+
+    removeWrong(solver.learnts);
+    removeWrongBinsAndAllTris();
+    removeAssignedVarsFromEliminated();
+
+    solver.order_heap.filter(Solver::VarFilter(solver));
+
+    addBackToSolver();
+    if (!reattacher.reattachNonBins()) return false;
+
+    if (solver.conf.verbosity  >= 1) {
+        std::cout << "c lits-rem: " << std::setw(9) << literals_removed
+        << "  cl-subs: " << std::setw(8) << clauses_subsumed
+        << "  v-elim: " << std::setw(6) << numVarsElimed
+        << "  v-fix: " << std::setw(4) <<solver.trail.size() - origTrailSize
+        << "  time: " << std::setprecision(2) << std::setw(5) << (cpuTime() - myTime) << " s"
+        //<< " blkClRem: " << std::setw(5) << numblockedClauseRemoved
+        << std::endl;
+    }
+    totalTime += cpuTime() - myTime;
+
+    solver.testAllClauseAttach();
+    return true;
+}
+
+/**
+@brief Calculate limits for backw-subsumption, var elim, etc.
+
+It is important to have limits, otherwise the time taken to perfom these tasks
+could be huge. Furthermore, it seems that there is a benefit in doing these
+simplifications slowly, instead of trying to use them as much as possible
+from the beginning.
+
+@param[in] alsoLearnt Have learnt clauses also been hooked in? If so, variable
+elimination must be excluded, for example (i.e. its limit must be 0)
+*/
+void Subsumer::setLimits()
+{
+    numMaxSubsume0 = 130*1000*1000;
+    numMaxSubsume1 = 80*1000*1000;
+
+    numMaxElim = 500*1000*1000;
+
+    //numMaxElim = 0;
+    //numMaxElim = std::numeric_limits<int64_t>::max();
+
+    #ifdef BIT_MORE_VERBOSITY
+    std::cout << "c addedClauseLits: " << addedClauseLits << std::endl;
+    #endif
+    if (addedClauseLits < 10000000) {
+        numMaxElim *= 3;
+        numMaxSubsume0 *= 3;
+        numMaxSubsume1 *= 3;
+    }
+
+    if (addedClauseLits < 5000000) {
+        numMaxElim *= 4;
+        numMaxSubsume0 *= 4;
+        numMaxSubsume1 *= 4;
+    }
+
+    if (addedClauseLits < 3000000) {
+        numMaxElim *= 4;
+        numMaxSubsume0 *= 4;
+        numMaxSubsume1 *= 4;
+    }
+
+    if (addedClauseLits < 1000000) {
+        numMaxElim *= 4;
+        numMaxSubsume0 *= 4;
+        numMaxSubsume1 *= 4;
+    }
+
+    numMaxElimVars = (solver.order_heap.size()/3)*numCalls;
+
+    if (solver.order_heap.size() > 200000)
+        numMaxBlockVars = (uint32_t)((double)solver.order_heap.size() / 3.5 * (0.8+(double)(numCalls)/4.0));
+    else
+        numMaxBlockVars = (uint32_t)((double)solver.order_heap.size() / 1.5 * (0.8+(double)(numCalls)/4.0));
+
+    if (!solver.conf.doSubsume1)
+        numMaxSubsume1 = 0;
+
+    if (numCalls == 1) {
+        numMaxSubsume1 = 10*1000*1000;
+    }
+
+    if (alsoLearnt) {
+        numMaxElim = 0;
+        numMaxElimVars = 0;
+        numMaxSubsume0 /= 2;
+        numMaxSubsume1 /= 2;
+        numMaxBlockVars = 0;
+    } else {
+        numCalls++;
+    }
+
+    //For debugging
+
+    //numMaxSubsume0 = 0;
+    //numMaxSubsume1 = 0;
+    //numMaxSubsume0 = std::numeric_limits<int64_t>::max();
+    //numMaxSubsume1 = std::numeric_limits<int64_t>::max();
+
+    //numMaxBlockToVisit = std::numeric_limits<int64_t>::max();
+    //numMaxBlockVars = std::numeric_limits<uint32_t>::max();
+}
+
+/**
+@brief Remove variables from var_elimed if it has been set
+
+While doing, e.g. self-subsuming resolution, it might happen that the variable
+that we JUST eliminated has been assigned a value. This could happen for example
+if due to clause-cleaning some variable value got propagated that we just set.
+Therefore, we must check at the very end if any variables that we eliminated
+got set, and if so, the clauses linked to these variables can be fully removed
+from elimedOutVar[].
+*/
+void Subsumer::removeAssignedVarsFromEliminated()
+{
+    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<Var, vector<vector<Lit> > >::iterator it = elimedOutVar.find(var);
+            if (it != elimedOutVar.end()) elimedOutVar.erase(it);
+
+            map<Var, vector<std::pair<Lit, Lit> > >::iterator it2 = elimedOutVarBin.find(var);
+            if (it2 != elimedOutVarBin.end()) elimedOutVarBin.erase(it2);
+        }
+    }
+}
+
+/**
+@brief Finds clauses that are backward-subsumed by given clause
+
+Only handles backward-subsumption. Uses occurrence lists
+
+@param[in] ps The clause to backward-subsume with.
+@param[in] abs Abstraction of the clause ps
+@param[out] out_subsumed The set of clauses subsumed by this clause
+*/
+template<class T>
 void Subsumer::findSubsumed(const T& ps, uint32_t abs, vec<ClauseSimp>& out_subsumed)
 {
     #ifdef VERBOSE_DEBUG
-    cout << "findSubsumed: ";
-    for (uint32_t i = 0; i < ps.size(); i++) {
-        if (ps[i].sign()) printf("-");
-        printf("%d ", ps[i].var() + 1);
-    }
-    printf("0\n");
+    cout << "findSubsumed: " << ps << std::endl;
     #endif
-    
+
+    for (uint32_t i = 0; i != ps.size(); i++)
+        seen_tmp[ps[i].toInt()] = 1;
+
     uint32_t min_i = 0;
     for (uint32_t i = 1; i < ps.size(); i++){
         if (occur[ps[i].toInt()].size() < occur[ps[min_i].toInt()].size())
             min_i = i;
     }
-    
+
     vec<ClauseSimp>& cs = occur[ps[min_i].toInt()];
+    numMaxSubsume0 -= cs.size()*10 + 5;
     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 != (Clause*)&ps && subsetAbst(abs, it->clause->getAbst()) && ps.size() <= it->clause->size() && subset(ps, *it->clause)) {
-            out_subsumed.push(*it);
+
+        if (it->clause != (Clause*)&ps
+            && subsetAbst(abs, it->clause->getAbst())
+            && ps.size() <= it->clause->size()) {
+                numMaxSubsume0 -= (*it).clause->size() + ps.size();
+                if (subset(ps.size(), *it->clause)) {
+                out_subsumed.push(*it);
+                #ifdef VERBOSE_DEBUG
+                cout << "subsumed: ";
+                it->clause->plainPrint();
+                #endif
+            }
+        }
+    }
+
+    for (uint32_t i = 0; i != ps.size(); i++)
+        seen_tmp[ps[i].toInt()] = 0;
+}
+
+/**
+@brief Checks if clauses are subsumed or could be strenghtened with given clause
+
+Checks if:
+* any clause is subsumed with given clause
+* the given clause could perform self-subsuming resolution on any other clause
+
+Only takes into consideration clauses that are in the occurrence lists.
+
+@param[in] ps The clause to perform the above listed algos with
+@param[in] abs The abstraction of clause ps
+@param[out] out_subsumed The clauses that could be modified by ps
+@param[out] out_lits Defines HOW these clauses could be modified. By removing
+literal, or by subsumption (in this case, there is lit_Undef here)
+*/
+template<class T>
+void Subsumer::findSubsumed1(const T& ps, uint32_t abs, vec<ClauseSimp>& out_subsumed, vec<Lit>& out_lits)
+{
+    #ifdef VERBOSE_DEBUG
+    cout << "findSubsumed1: " << ps << std::endl;
+    #endif
+
+    Var minVar = var_Undef;
+    uint32_t bestSize = std::numeric_limits<uint32_t>::max();
+    for (uint32_t i = 0; i < ps.size(); i++){
+        uint32_t newSize = occur[ps[i].toInt()].size()+ occur[(~ps[i]).toInt()].size();
+        if (newSize < bestSize) {
+            minVar = ps[i].var();
+            bestSize = newSize;
+        }
+    }
+    assert(minVar != var_Undef);
+
+    numMaxSubsume1 -= bestSize*10 + 10;
+    fillSubs(ps, abs, out_subsumed, out_lits, Lit(minVar, true));
+    fillSubs(ps, abs, out_subsumed, out_lits, Lit(minVar, false));
+}
+
+/**
+@brief Helper function for findSubsumed1
+
+Used to avoid duplication of code
+*/
+template<class T>
+void inline Subsumer::fillSubs(const T& ps, uint32_t abs, vec<ClauseSimp>& out_subsumed, vec<Lit>& out_lits, const Lit lit)
+{
+    Lit litSub;
+    vec<ClauseSimp>& cs = occur[lit.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 != (Clause*)&ps
+            && subsetAbst(abs, it->clause->getAbst())
+            && ps.size() <= it->clause->size()) {
+            numMaxSubsume1 -= (*it).clause->size() + ps.size();
+            litSub = subset1(ps, *it->clause);
+            if (litSub != lit_Error) {
+                out_subsumed.push(*it);
+                out_lits.push(litSub);
+                #ifdef VERBOSE_DEBUG
+                if (litSub == lit_Undef) cout << "subsume0-d: ";
+                else cout << "subsume1-ed (lit: " << litSub << "): ";
+                it->clause->plainPrint();
+                #endif
+            }
+        }
+    }
+}
+
+
+void Subsumer::removeClausesHelper(vec<ClAndBin>& todo, const Var var, std::pair<uint32_t, uint32_t>& removed)
+{
+     pair<uint32_t, uint32_t>  tmp;
+     for (uint32_t i = 0; i < todo.size(); i++) {
+        ClAndBin& c = todo[i];
+        if (!c.isBin) {
+            unlinkClause(c.clsimp, var);
+        } else {
             #ifdef VERBOSE_DEBUG
-            cout << "subsumed: ";
-            it->clause->plainPrint();
+            std::cout << "Eliminating bin clause: " << c.lit1 << " , " << c.lit2 << std::endl;
+            std::cout << "On variable: " << var+1 << std::endl;
+            #endif
+            assert(var == c.lit1.var() || var == c.lit2.var());
+            tmp = removeWBinAll(solver.watches[(~c.lit1).toInt()], c.lit2);
+            //assert(tmp.first > 0 || tmp.second > 0);
+            removed.first += tmp.first;
+            removed.second += tmp.second;
+
+            tmp = removeWBinAll(solver.watches[(~c.lit2).toInt()], c.lit1);
+            //assert(tmp.first > 0 || tmp.second > 0);
+            removed.first += tmp.first;
+            removed.second += tmp.second;
+
+            elimedOutVarBin[var].push_back(std::make_pair(c.lit1, c.lit2));
+            #ifndef TOUCH_LESS
+            touch(c.lit1, false);
+            touch(c.lit2, false);
             #endif
         }
     }
 }
 
-void inline Subsumer::MigrateToPsNs(vec<ClauseSimp>& poss, vec<ClauseSimp>& negs, vec<ClauseSimp>& ps, vec<ClauseSimp>& ns, const Var x)
+/**
+@brief Used for variable elimination
+
+Migrates clauses in poss to ps, and negs to ns
+Also unlinks ass clauses is ps and ns. This is special unlinking, since it
+actually saves the clauses for later re-use when extending the model, or re-
+introducing the eliminated variables.
+
+@param[in] poss The occurrence list of var where it is positive
+@param[in] negs The occurrence list of var where it is negavite
+@param[out] ps Where thre clauses from poss have been moved
+@param[out] ns Where thre clauses from negs have been moved
+@param[in] var The variable that is being eliminated
+*/
+void Subsumer::removeClauses(vec<ClAndBin>& posAll, vec<ClAndBin>& negAll, const Var var)
 {
-    poss.moveTo(ps);
-    negs.moveTo(ns);
-    
-    for (uint32_t i = 0; i < ps.size(); i++)
-        unlinkClause(ps[i], x);
-    for (uint32_t i = 0; i < ns.size(); i++)
-        unlinkClause(ns[i], x);
+    pair<uint32_t, uint32_t> removed;
+    removed.first = 0;
+    removed.second = 0;
+
+    removeClausesHelper(posAll, var, removed);
+    removeClausesHelper(negAll, var, removed);
+
+    solver.learnts_literals -= removed.first;
+    solver.clauses_literals -= removed.second;
+    solver.numBins -= (removed.first + removed.second)/2;
 }
 
-void inline Subsumer::DeallocPsNs(vec<ClauseSimp>& ps, vec<ClauseSimp>& ns)
+const uint32_t Subsumer::numNonLearntBins(const Lit lit) const
 {
-    for (uint32_t i = 0; i < ps.size(); i++) {
-        //clauses[ps[i].index].clause = NULL;
-        //clauseFree(ps[i].clause);
+    uint32_t num = 0;
+    const vec<Watched>& ws = solver.watches[(~lit).toInt()];
+    for (const Watched *it = ws.getData(), *end = ws.getDataEnd(); it != end; it++) {
+        if (it->isBinary() && !it->getLearnt()) num++;
     }
-    for (uint32_t i = 0; i < ns.size(); i++) {
-        //clauses[ns[i].index].clause = NULL;
-        //clauseFree(ns[i].clause);
+
+    return num;
+}
+
+void Subsumer::fillClAndBin(vec<ClAndBin>& all, vec<ClauseSimp>& cs, const Lit lit)
+{
+    for (uint32_t i = 0; i < cs.size(); i++)
+        all.push(ClAndBin(cs[i]));
+
+    const vec<Watched>& ws = solver.watches[(~lit).toInt()];
+    for (const Watched *it = ws.getData(), *end = ws.getDataEnd(); it != end; it++) {
+        if (it->isBinary() &&!it->getLearnt()) all.push(ClAndBin(lit, it->getOtherLit()));
     }
 }
 
-// Returns TRUE if variable was eliminated.
-bool Subsumer::maybeEliminate(const Var x)
+/**
+@brief Tries to eliminate variable
+
+Tries to eliminate a variable. It uses heuristics to decide whether it's a good
+idea to eliminate a variable or not.
+
+@param[in] var The variable that is being eliminated
+@return TRUE if variable was eliminated
+*/
+bool Subsumer::maybeEliminate(const Var var)
 {
-    assert(solver.qhead == solver.trail.size());
-    assert(!var_elimed[x]);
-    assert(!cannot_eliminate[x]);
-    assert(solver.decision_var[x]);
-    if (solver.value(x) != l_Undef) return false;
-    if (occur[Lit(x, false).toInt()].size() == 0 && occur[Lit(x, true).toInt()].size() == 0)
-        return false;
-    
-    vec<ClauseSimp>&   poss = occur[Lit(x, false).toInt()];
-    vec<ClauseSimp>&   negs = occur[Lit(x, true).toInt()];
-    
+    assert(!var_elimed[var]);
+    assert(!cannot_eliminate[var]);
+    assert(solver.decision_var[var]);
+    if (solver.value(var) != l_Undef) return false;
+
+    Lit lit = Lit(var, false);
+
+    //Only exists in binary clauses -- don't delete it then
+    /*if (occur[lit.toInt()].size() == 0 && occur[(~lit).toInt()].size() == 0)
+        return false;*/
+
+    const uint32_t numNonLearntPos = numNonLearntBins(lit);
+    const uint32_t posSize = occur[lit.toInt()].size() + numNonLearntPos;
+    const uint32_t numNonLearntNeg = numNonLearntBins(~lit);
+    const uint32_t negSize = occur[(~lit).toInt()].size() + numNonLearntNeg;
+    vec<ClauseSimp>& poss = occur[lit.toInt()];
+    vec<ClauseSimp>& negs = occur[(~lit).toInt()];
+    numMaxElim -= posSize + negSize;
+
     // Heuristic CUT OFF:
-    if (poss.size() >= 10 && negs.size() >= 10)
-        return false;
-    
+    if (posSize >= 10 && negSize >= 10) return false;
+
     // Count clauses/literals before elimination:
-    int before_clauses  = poss.size() + negs.size();
-    uint32_t before_literals = 0;
+    uint32_t before_literals = numNonLearntNeg*2 + numNonLearntPos*2;
     for (uint32_t i = 0; i < poss.size(); i++) before_literals += poss[i].clause->size();
     for (uint32_t i = 0; i < negs.size(); i++) before_literals += negs[i].clause->size();
-    
+
     // Heuristic CUT OFF2:
-    if ((poss.size() >= 3 && negs.size() >= 3 && before_literals > 300)
-        && clauses.size() > 1500000)
+    if ((posSize >= 3 && negSize >= 3 && before_literals > 300)
+        && clauses.size() > 700000)
         return false;
-    if ((poss.size() >= 5 && negs.size() >= 5 && before_literals > 400)
-        && clauses.size() <= 1500000 && clauses.size() > 200000)
+    if ((posSize >= 5 && negSize >= 5 && before_literals > 400)
+        && clauses.size() <= 700000 && clauses.size() > 100000)
         return false;
-    if ((poss.size() >= 8 && negs.size() >= 8 && before_literals > 700)
-        && clauses.size() <= 200000)
+    if ((posSize >= 8 && negSize >= 8 && before_literals > 700)
+        && clauses.size() <= 100000)
         return false;
-    
+
+    vec<ClAndBin> posAll, negAll;
+    fillClAndBin(posAll, poss, lit);
+    fillClAndBin(negAll, negs, ~lit);
+    assert(posAll.size() == posSize);
+    assert(negAll.size() == negSize);
+
     // Count clauses/literals after elimination:
-    int after_clauses  = 0;
-    vec<Lit>  dummy;
-    for (uint32_t i = 0; i < poss.size(); i++) for (uint32_t j = 0; j < negs.size(); j++){
+    numMaxElim -= posSize * negSize + before_literals;
+    uint32_t before_clauses = posSize + negSize;
+    uint32_t after_clauses = 0;
+    vec<Lit> dummy; //to reduce temporary data allocation
+    for (uint32_t i = 0; i < posAll.size(); i++) for (uint32_t j = 0; j < negAll.size(); j++){
         // Merge clauses. If 'y' and '~y' exist, clause will not be created.
         dummy.clear();
-        bool ok = merge(*poss[i].clause, *negs[j].clause, Lit(x, false), Lit(x, true), dummy);
+        bool ok = merge(posAll[i], negAll[j], lit, ~lit, dummy);
         if (ok){
             after_clauses++;
-            if (after_clauses > before_clauses) goto Abort;
+            if (after_clauses > before_clauses) return false;
         }
     }
-    Abort:;
-    
+
     //Eliminate:
-    if (after_clauses  <= before_clauses) {
-        vec<ClauseSimp> ps, ns;
-        MigrateToPsNs(poss, negs, ps, ns, x);
-        for (uint32_t i = 0; i < ps.size(); i++) for (uint32_t j = 0; j < ns.size(); j++){
-            dummy.clear();
-            bool ok = merge(*ps[i].clause, *ns[j].clause, Lit(x, false), Lit(x, true), dummy);
-            if (ok){
-                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, cl->getAbst());
+    numMaxElim -= posSize * negSize + before_literals;
+    poss.clear();
+    negs.clear();
+    removeClauses(posAll, negAll, var);
+
+    #ifndef NDEBUG
+    for (uint32_t i = 0; i < solver.watches[lit.toInt()].size(); i++) {
+        Watched& w = solver.watches[lit.toInt()][i];
+        assert(w.isTriClause() || (w.isBinary() && w.getLearnt()));
+    }
+    for (uint32_t i = 0; i < solver.watches[(~lit).toInt()].size(); i++) {
+        Watched& w = solver.watches[(~lit).toInt()][i];
+        assert(w.isTriClause() || (w.isBinary() && w.getLearnt()));
+    }
+    #endif
+
+    for (uint32_t i = 0; i < posAll.size(); i++) for (uint32_t j = 0; j < negAll.size(); j++){
+        dummy.clear();
+        bool ok = merge(posAll[i], negAll[j], lit, ~lit, dummy);
+        if (!ok) continue;
+
+        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
+
+        if (cleanClause(dummy)) continue;
+        #ifdef VERBOSE_DEBUG
+        std::cout << "Adding new clause due to varelim: " << dummy << std::endl;
+        #endif
+        switch (dummy.size()) {
+            case 0:
+                solver.ok = false;
+                break;
+            case 1: {
+                handleSize1Clause(dummy[0]);
+                break;
+            }
+            case 2: {
+                if (findWBin(solver.watches, dummy[0], dummy[1])) {
+                    Watched& w = findWatchedOfBin(solver.watches, dummy[0], dummy[1]);
+                    if (w.getLearnt()) {
+                        w.setLearnt(false);
+                        findWatchedOfBin(solver.watches, dummy[1], dummy[0], true).setLearnt(false);
+                        solver.learnts_literals -= 2;
+                        solver.clauses_literals += 2;
+                    }
+                } else {
+                    solver.attachBinClause(dummy[0], dummy[1], false);
+                    solver.numNewBin++;
                 }
-                if (!solver.ok) return true;
+                subsume1(dummy, false);
+                break;
+            }
+            default: {
+                Clause* cl = solver.clauseAllocator.Clause_new(dummy, group_num);
+                ClauseSimp c = linkInClause(*cl);
+                if (numMaxSubsume1 > 0) subsume1(*c.clause);
+                else subsume0(*c.clause);
             }
         }
-        DeallocPsNs(ps, ns);
-        goto Eliminated;
-    }
-    
-    return false;
-    
-    Eliminated:
-    assert(occur[Lit(x, false).toInt()].size() + occur[Lit(x, true).toInt()].size() == 0);
-    var_elimed[x] = true;
+        if (!solver.ok) return true;
+    }
+
+    assert(occur[lit.toInt()].size() == 0 &&  occur[(~lit).toInt()].size() == 0);
+    var_elimed[var] = true;
     numElimed++;
-    solver.setDecisionVar(x, false);
+    solver.setDecisionVar(var, 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(const Clause& ps, const Clause& qs, const Lit without_p, const Lit without_q, vec<Lit>& out_clause)
+/**
+@brief Resolves two clauses on a variable
+
+Clause ps must contain without_p
+Clause ps must contain without_q
+And without_p = ~without_q
+
+@note: 'seen' is assumed to be cleared.
+
+@param[in] var The variable that is being eliminated
+@return FALSE if clause is always satisfied ('out_clause' should not be used)
+*/
+bool Subsumer::merge(const ClAndBin& ps, const ClAndBin& qs, const Lit without_p, const Lit without_q, vec<Lit>& out_clause)
 {
-    for (uint32_t i = 0; i < ps.size(); i++){
-        if (ps[i] != without_p){
-            seen_tmp[ps[i].toInt()] = 1;
-            out_clause.push(ps[i]);
+    bool retval = true;
+    if (ps.isBin) {
+        assert(ps.lit1 == without_p);
+        assert(ps.lit2 != without_p);
+
+        seen_tmp[ps.lit2.toInt()] = 1;
+        out_clause.push(ps.lit2);
+    } else {
+        Clause& c = *ps.clsimp.clause;
+        numMaxElim -= c.size();
+        for (uint32_t i = 0; i < c.size(); i++){
+            if (c[i] != without_p){
+                seen_tmp[c[i].toInt()] = 1;
+                out_clause.push(c[i]);
+            }
         }
     }
-    
-    for (uint32_t i = 0; i < qs.size(); i++){
-        if (qs[i] != without_q){
-            if (seen_tmp[(~qs[i]).toInt()]){
-                for (uint32_t i = 0; i < ps.size(); i++)
-                    seen_tmp[ps[i].toInt()] = 0;
-                return false;
+
+    if (qs.isBin) {
+        assert(qs.lit1 == without_q);
+        assert(qs.lit2 != without_q);
+
+        if (seen_tmp[(~qs.lit2).toInt()]) {
+            retval = false;
+            goto end;
+        }
+        if (!seen_tmp[qs.lit2.toInt()])
+            out_clause.push(qs.lit2);
+    } else {
+        Clause& c = *qs.clsimp.clause;
+        numMaxElim -= c.size();
+        for (uint32_t i = 0; i < c.size(); i++){
+            if (c[i] != without_q) {
+                if (seen_tmp[(~c[i]).toInt()]) {
+                    retval = false;
+                    goto end;
+                }
+                if (!seen_tmp[c[i].toInt()])
+                    out_clause.push(c[i]);
             }
-            if (!seen_tmp[qs[i].toInt()])
-                out_clause.push(qs[i]);
         }
     }
-    
-    for (uint32_t i = 0; i < ps.size(); i++)
-        seen_tmp[ps[i].toInt()] = 0;
-    
-    return true;
-}
 
-struct myComp {
-    bool operator () (const pair<int, Var>& x, const pair<int, Var>& y) {
-        return x.first < y.first ||
-            (!(y.first < x.first) && x.second < y.second);
+    end:
+    if (ps.isBin) {
+        seen_tmp[ps.lit2.toInt()] = 0;
+    } else {
+        Clause& c = *ps.clsimp.clause;
+        numMaxElim -= c.size();
+        for (uint32_t i = 0; i < c.size(); i++)
+            seen_tmp[c[i].toInt()] = 0;
     }
-};
-    
-// Side-effect: Will untouch all variables.
+
+    return retval;
+}
+
+/**
+@brief Orders variables for elimination
+
+Variables are ordered according to their occurrances. If a variable occurs far
+less than others, it should be prioritised for elimination. The more difficult
+variables are OK to try later.
+
+@note: Will untouch all variables.
+
+@param[out] order The order to try to eliminate the variables
+*/
 void Subsumer::orderVarsForElim(vec<Var>& order)
 {
     order.clear();
     vec<pair<int, Var> > cost_var;
-    for (uint32_t i = 0; i < touched_list.size(); i++){
-        Var x = touched_list[i];
-        touched[x] = 0;
-        cost_var.push(std::make_pair( occur[Lit(x, false).toInt()].size() * occur[Lit(x, true).toInt()].size() , x ));
+    for (uint32_t i = 0; i < touchedVarsList.size(); i++){
+        Lit x = Lit(touchedVarsList[i], false);
+        touchedVars[x.var()] = false;
+        //this is not perfect -- solver.watches[] is an over-approximation
+        uint32_t pos = occur[x.toInt()].size();
+        uint32_t neg = occur[(~x).toInt()].size();
+        uint32_t cost = pos * neg * 2 + numNonLearntBins(x) * neg + numNonLearntBins(~x) * pos;
+        cost_var.push(std::make_pair(cost, x.var()));
     }
-    
-    touched_list.clear();
+    touchedVarsList.clear();
+
     std::sort(cost_var.getData(), cost_var.getData()+cost_var.size(), myComp());
-    
     for (uint32_t x = 0; x < cost_var.size(); x++) {
         if (cost_var[x].first != 0)
             order.push(cost_var[x].second);
     }
 }
 
-void Subsumer::verifyIntegrity()
+/**
+@brief Verifies that occurrence lists are OK
+
+Calculates how many occurences are of the varible in clauses[], and if that is
+less than occur[var].size(), returns FALSE
+
+@return TRUE if they are OK
+*/
+const bool Subsumer::verifyIntegrity()
 {
-    vector<uint> occurNum(solver.nVars()*2, 0);
-    
+    vector<uint32_t> occurNum(solver.nVars()*2, 0);
+
     for (uint32_t i = 0; i < clauses.size(); i++) {
         if (clauses[i].clause == NULL) continue;
         Clause& c = *clauses[i].clause;
         for (uint32_t i2 = 0; i2 < c.size(); i2++)
             occurNum[c[i2].toInt()]++;
     }
-    
+
     for (uint32_t i = 0; i < occurNum.size(); i++) {
-        assert(occurNum[i] == occur[i].size());
+        #ifdef VERBOSE_DEBUG
+        std::cout << "occurNum[i]:" << occurNum[i]
+        << " occur[i]:" << occur[i].size()
+        << "  --- i:" << i << std::endl;
+        #endif //VERBOSE_DEBUG
+
+        if (occurNum[i] != occur[i].size()) return false;
     }
+
+    return true;
 }
 
-const bool Subsumer::allTautology(const vec<Lit>& ps, const Lit lit)
+template<class T>
+const bool Subsumer::allTautology(const T& ps, const Lit lit)
 {
     #ifdef VERBOSE_DEBUG
-    cout << "allTautology: ";
-    for (uint32_t i = 0; i < ps.size(); i++) {
-        if (ps[i].sign()) printf("-");
-        printf("%d ", ps[i].var() + 1);
-    }
-    printf("0\n");
+    cout << "allTautology: " << ps << std::endl;
     #endif
-    
-    vec<ClauseSimp>& cs = occur[lit.toInt()];
-    if (cs.size() == 0) return true;
-    
+
+    numMaxBlockToVisit -= ps.size()*2;
     for (const Lit *l = ps.getData(), *end = ps.getDataEnd(); l != end; l++) {
-        seen_tmp[l->toInt()] = true;
+        if (*l != ~lit) seen_tmp[l->toInt()] = true;
     }
-    
+
     bool allIsTautology = true;
-    for (ClauseSimp *it = cs.getData(), *end = cs.getDataEnd(); it != end; it++){
-        if (it+1 != end)
-            __builtin_prefetch((it+1)->clause, 1, 1);
-        
-        Clause& c = *it->clause;
-        for (Lit *l = c.getData(), *end2 = l + c.size(); l != end2; l++) {
-            if (*l != lit && seen_tmp[(~(*l)).toInt()]) {
+    const vec<ClauseSimp>& cs = occur[lit.toInt()];
+    const vec<Watched>& ws = solver.watches[(~lit).toInt()];
+
+    for (const ClauseSimp *it = cs.getData(), *end = cs.getDataEnd(); it != end; it++){
+        if (it+1 != end) __builtin_prefetch((it+1)->clause, 1, 1);
+
+        const Clause& c = *it->clause;
+        numMaxBlockToVisit -= c.size();
+        for (const Lit *l = c.getData(), *end2 = c.getDataEnd(); l != end2; l++) {
+            if (seen_tmp[(~(*l)).toInt()]) {
                 goto next;
             }
         }
         allIsTautology = false;
         break;
-        
+
         next:;
     }
-    
+    if (!allIsTautology) goto end;
+
+    numMaxBlockToVisit -= ws.size();
+    for (const Watched *it = ws.getData(), *end = ws.getDataEnd(); it != end; it++) {
+        if (!it->isNonLearntBinary()) continue;
+        if (seen_tmp[(~it->getOtherLit()).toInt()]) continue;
+        else {
+            allIsTautology = false;
+            break;
+        }
+    }
+
+    end:
     for (const Lit *l = ps.getData(), *end = ps.getDataEnd(); l != end; l++) {
         seen_tmp[l->toInt()] = false;
     }
-    
+
     return allIsTautology;
 }
 
 void Subsumer::blockedClauseRemoval()
 {
     if (numMaxBlockToVisit < 0) return;
-    if (solver.order_heap.size() < 1) return;
+    if (solver.order_heap.empty()) return;
+
     double myTime = cpuTime();
-    vec<ClauseSimp> toRemove;
-    
+    numblockedClauseRemoved = 0;
+    uint32_t numElimedBefore = numElimed;
+
     touchedBlockedVars = priority_queue<VarOcc, vector<VarOcc>, MyComp>();
     touchedBlockedVarsBool.clear();
     touchedBlockedVarsBool.growTo(solver.nVars(), false);
-    for (uint32_t i =  0; i < solver.order_heap.size() && i < numMaxBlockVars; i++) {
-        touchBlockedVar(solver.order_heap[solver.mtrand.randInt(solver.order_heap.size()-1)]);
+    for (uint32_t i =  0; i < solver.order_heap.size(); i++) {
+        //if (solver.order_heap.size() < 1) break;
+        //touchBlockedVar(solver.order_heap[solver.mtrand.randInt(solver.order_heap.size()-1)]);
+        touchBlockedVar(solver.order_heap[i]);
     }
-    
-    while (touchedBlockedVars.size() > 100  && numMaxBlockToVisit > 0) {
+
+    uint32_t triedToBlock = 0;
+    while (numMaxBlockToVisit > 0 && !touchedBlockedVars.empty()) {
         VarOcc vo = touchedBlockedVars.top();
         touchedBlockedVars.pop();
-        
-        if (solver.assigns[vo.var] != l_Undef || !solver.decision_var[vo.var] || cannot_eliminate[vo.var])
-            continue;
         touchedBlockedVarsBool[vo.var] = false;
+
+        if (solver.value(vo.var) != l_Undef
+            || !solver.decision_var[vo.var]
+            || cannot_eliminate[vo.var])
+            continue;
+
+        triedToBlock++;
         Lit lit = Lit(vo.var, false);
-        Lit negLit = Lit(vo.var, true);
-        
-        numMaxBlockToVisit -= (int64_t)occur[lit.toInt()].size();
-        numMaxBlockToVisit -= (int64_t)occur[negLit.toInt()].size();
-        //if (!tryOneSetting(lit, negLit)) {
-            tryOneSetting(negLit, lit);
+
+        //if (!tryOneSetting(lit)) {
+            tryOneSetting(lit);
        // }
     }
-    blockTime += cpuTime() - myTime;
-    
-    #ifdef BIT_MORE_VERBOSITY
-    std::cout << "c  Total fime for block until now: " << blockTime << std::endl;
-    #endif
+
+    removeWrongBinsAndAllTris();
+
+    if (solver.conf.verbosity >= 1) {
+        std::cout
+        << "c spec. var-rem cls: " << std::setw(8) << numblockedClauseRemoved
+        << " vars: " << std::setw(6) << numElimed - numElimedBefore
+        << " tried: " << std::setw(11) << triedToBlock
+        << " T: " << std::fixed << std::setprecision(2) << std::setw(4) << cpuTime() - myTime
+        << " s" << std::endl;
+    }
 }
 
-const bool Subsumer::tryOneSetting(const Lit lit, const Lit negLit)
+const bool Subsumer::tryOneSetting(const Lit lit)
 {
-    uint32_t toRemove = 0;
-    bool returnVal = false;
-    vec<Lit> cl;
-    
+    numMaxBlockToVisit -= occur[lit.toInt()].size();
     for(ClauseSimp *it = occur[lit.toInt()].getData(), *end = occur[lit.toInt()].getDataEnd(); it != end; it++) {
-        cl.clear();
-        cl.growTo(it->clause->size()-1);
-        for (uint32_t i = 0, i2 = 0; i < it->clause->size(); i++) {
-            if ((*it->clause)[i] != lit) {
-                cl[i2] = (*it->clause)[i];
-                i2++;
-            }
-        }
-        
-        if (allTautology(cl, negLit)) {
-            toRemove++;
-        } else {
-            break;
-        }
-    }
-    
-    if (toRemove == occur[lit.toInt()].size()) {
-        var_elimed[lit.var()] = true;
-        solver.setDecisionVar(lit.var(), false);
-        vec<ClauseSimp> toRemove(occur[lit.toInt()]);
-        for (ClauseSimp *it = toRemove.getData(), *end = toRemove.getDataEnd(); it != end; it++) {
-            #ifdef VERBOSE_DEBUG
-            std::cout << "Next varelim because of block clause elim" << std::endl;
-            #endif //VERBOSE_DEBUG
-            unlinkClause(*it, lit.var());
-            numblockedClauseRemoved++;
-        }
-        
-        vec<ClauseSimp> 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++;
+        if (!allTautology(*it->clause, ~lit)) {
+            return false;
         }
-        returnVal = true;
     }
-    
-    return returnVal;
-}
 
-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;
-        }
+    vec<Lit> lits(1);
+    const vec<Watched>& ws = solver.watches[(~lit).toInt()];
+    numMaxBlockToVisit -= ws.size();
+    for (const Watched *it = ws.getData(), *end = ws.getDataEnd(); it != end; it++) {
+        if (!it->isNonLearntBinary()) continue;
+        lits[0] = it->getOtherLit();
+        if (!allTautology(lits, ~lit)) return false;
     }
 
-    return true;
-}
+    blockedClauseElimAll(lit);
+    blockedClauseElimAll(~lit);
 
-/*
-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;
+    var_elimed[lit.var()] = true;
+    numElimed++;
+    numMaxElimVars--;
+    solver.setDecisionVar(lit.var(), false);
+
+    return true;
 }
 
-vector<char> Subsumer::merge()
+void Subsumer::blockedClauseElimAll(const Lit lit)
 {
-    vector<char> var_merged(solver.nVars(), false);
-    double myTime = cpuTime();
-    
-    vector<varDataStruct> varData(solver.nVars());
-    
-    for (Var var = 0; var < solver.nVars(); var++) if (solver.decision_var[var] && solver.assigns[var] == l_Undef && !cannot_eliminate[var]) {
-        varDataStruct thisVar;
-        
-        vec<ClauseSimp>& toCountPos = occur[Lit(var, false).toInt()];
-        thisVar.numPosClauses = toCountPos.size();
-        for (uint32_t i2 = 0; i2 < toCountPos.size(); i2++) {
-            thisVar.sumPosClauseSize += toCountPos[i2].clause->size();
-            for (Lit *l = toCountPos[i2].clause->getData(), *end = l + toCountPos[i2].clause->size(); l != end; l++) {
-                if (l->var() != var) thisVar.posHash ^= hash32shift(l->toInt());
-            }
-        }
-        
-        vec<ClauseSimp>& toCountNeg = occur[Lit(var, true).toInt()];
-        thisVar.numNegClauses = toCountNeg.size();
-        for (uint32_t i2 = 0; i2 < toCountNeg.size(); i2++) {
-            thisVar.sumNegClauseSize += toCountNeg[i2].clause->size();
-            for (Lit *l = toCountNeg[i2].clause->getData(), *end = l + toCountNeg[i2].clause->size(); l != end; l++) {
-                if (l->var() != var) thisVar.negHash ^= hash32shift(l->toInt());
-            }
-        }
-        
-        varData[var] = thisVar;
-    }
-    
-    map<varDataStruct, vector<Var> > dataToVar;
-    for (Var var = 0; var < solver.nVars(); var++) if (solver.decision_var[var] && solver.assigns[var] == l_Undef) {
-        dataToVar[varData[var]].push_back(var);
-        assert(dataToVar[varData[var]].size() > 0);
-    }
-    
-    for (map<varDataStruct, vector<Var> >::iterator it = dataToVar.begin(); it != dataToVar.end(); it++) {
-        //std::cout << "size: " << it->second.size() << std::endl;
-        for (uint i = 0; i < it->second.size()-1; i++) {
-            assert(it->second.size() > i+1);
-            assert(varData[it->second[i]] == varData[it->second[i+1]]);
-        }
+    vec<ClauseSimp> 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++;
     }
-    
-    uint64_t checked = 0;
-    uint64_t replaced = 0;
-    for (Var var = 0; var < solver.nVars(); var++) if (solver.decision_var[var] && solver.assigns[var] == l_Undef && !cannot_eliminate[var]) {
-        varDataStruct tmp = varData[var];
-        assert(dataToVar[tmp].size() > 0);
-        
-        if (dataToVar[tmp].size() > 0) {
-            map<varDataStruct, vector<Var> >::iterator it = dataToVar.find(tmp);
-            for (uint i = 0; i < it->second.size(); i++) if (it->second[i] != var) {
-                checked ++;
-                if (checkIfSame(Lit(var, false), Lit(it->second[i], false)) &&
-                    (checkIfSame(Lit(var, true), Lit(it->second[i], true))))
-                {
-                    vec<Lit> ps(2);
-                    ps[0] = Lit(var, false);
-                    ps[1] = Lit(it->second[i], false);
-                    solver.varReplacer->replace(ps, true, 0);
-                    replaced++;
-                    goto next;
-                    
-                }
-            }
-        }
-        
-        tmp.reversePolarity();
-        if (dataToVar[tmp].size() > 0) {
-            map<varDataStruct, vector<Var> >::iterator it = dataToVar.find(tmp);
-            for (uint i = 0; i < it->second.size(); i++) if (it->second[i] != var) {
-                checked ++;
-                if (checkIfSame(Lit(var, true), Lit(it->second[i], false)) &&
-                    (checkIfSame(Lit(var, false), Lit(it->second[i], true))))
-                {
-                    vec<Lit> ps(2);
-                    ps[0] = Lit(var, false);
-                    ps[1] = Lit(it->second[i], false);
-                    solver.varReplacer->replace(ps, false, 0);
-                    replaced++;
-                    goto next;
-                }
-            }
+
+    uint32_t removedNum = 0;
+    vec<Watched>& ws = solver.watches[(~lit).toInt()];
+    Watched *i = ws.getData();
+    Watched *j = i;
+    for (Watched *end = ws.getDataEnd(); i != end; i++) {
+        if (!i->isNonLearntBinary()) {
+            *j++ = *i;
+            continue;
         }
-        
-        next:;
+        assert(!i->getLearnt());
+        removeWBin(solver.watches[(~i->getOtherLit()).toInt()], lit, false);
+        elimedOutVarBin[lit.var()].push_back(std::make_pair(lit, i->getOtherLit()));
+        touch(i->getOtherLit(), false);
+        removedNum++;
     }
-        
-    std::cout << "c |  Merging vars in same clauses.  checked: " << std::setw(5) << checked << " replaced: " << std::setw(5) << replaced << " time: " << std::setprecision(2) << std::setw(5) << cpuTime()-myTime << std::endl;
-    
-    return var_merged;
-}*/
+    ws.shrink_(i-j);
 
-/*const bool Subsumer::checkIfSame(const Lit lit1, const Lit lit2)
+    solver.clauses_literals -= removedNum*2;
+    solver.numBins -= removedNum;
+}
+
+/**
+@brief Checks if eliminated variables are unassigned
+
+If there is a variable that has been assigned even though it's been eliminated
+that means that there were clauses that contained that variable, and where some-
+how inserted into the watchlists. That would be a grave bug, since that would
+mean that not all clauses containing the eliminated variable were removed during
+the running of this class.
+
+@return TRUE if they are all unassigned
+*/
+const bool Subsumer::checkElimedUnassigned() const
 {
-    assert(lit1.var() != lit2.var());
-    #ifdef VERBOSE_DEBUG
-    std::cout << "checking : " << lit1.var()+1 << " , " << lit2.var()+1 << std::endl;
-    #endif
-    
-    vec<ClauseSimp>& occSet1 = occur[lit1.toInt()];
-    vec<ClauseSimp>& occSet2 = occur[lit2.toInt()];
-    vec<Lit> tmp;
-    
-    for (ClauseSimp *it = occSet1.getData(), *end = it + occSet1.size(); it != end; it++) {
-        bool found = false;
-        tmp.clear();
-        uint32_t clauseSize = it->clause->size();
-        
-        for (Lit *l = it->clause->getData(), *end2 = l + it->clause->size(); l != end2; l++) {
-            if (l->var() != lit1.var()) {
-                tmp.push(*l);
-                seen_tmp[l->toInt()] = true;
-            }
-        }
-        #ifdef VERBOSE_DEBUG
-        std::cout << "orig: ";
-        it->clause->plainPrint();
-        #endif
-        
-        for (ClauseSimp *it2 = occSet2.getData(), *end2 = it2 + occSet2.size(); (it2 != end2 && !found); it2++) {
-            if (it2->clause->size() != clauseSize) continue;
-            
-            for (Lit *l = it2->clause->getData(), *end3 = l + tmp.size(); l != end3; l++) if (l->var() != lit1.var()) {
-                if (!seen_tmp[l->toInt()]) goto next;
-            }
-            found = true;
-            
-            #ifdef VERBOSE_DEBUG
-            std::cout << "OK:   ";
-            it2->clause->plainPrint();
-            #endif
-            next:;
-        }
-        
-        for (Lit *l = tmp.getData(), *end2 = l + tmp.size(); l != end2; l++) {
-            seen_tmp[l->toInt()] = false;
+    uint32_t checkNumElimed = 0;
+    for (uint32_t i = 0; i < var_elimed.size(); i++) {
+        if (var_elimed[i]) {
+            checkNumElimed++;
+            assert(solver.assigns[i] == l_Undef);
+            if (solver.assigns[i] != l_Undef) return false;
         }
-        
-        if (!found) return false;
     }
-    #ifdef VERBOSE_DEBUG
-    std::cout << "OK" << std::endl;
-    #endif
-    
-    return true;
-}*/
+    assert(numElimed == checkNumElimed);
 
-}; //NAMESPACE MINISAT
+    return true;
+}
index a36ea7a18d2d156aca66ec3c7056cbbe9a676a2a..19f44e4d6495e6ed38931d82f52a55ac54e808d6 100644 (file)
@@ -1,7 +1,10 @@
-/**************************************************************************************************
-Originally From: Solver.C -- (C) Niklas Een, Niklas Sorensson, 2004
-Substantially modified by: Mate Soos (2010)
-**************************************************************************************************/
+/*****************************************************************************
+SatELite -- (C) Niklas Een, Niklas Sorensson, 2004
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+Original code by SatELite authors are under an MIT licence.
+Modifications for CryptoMiniSat are under GPLv3.
+******************************************************************************/
 
 #ifndef SIMPLIFIER_H
 #define SIMPLIFIER_H
@@ -12,148 +15,266 @@ Substantially modified by: Mate Soos (2010)
 #include "BitArray.h"
 #include <map>
 #include <vector>
+#include <list>
 #include <queue>
 using std::vector;
+using std::list;
 using std::map;
 using std::priority_queue;
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 class ClauseCleaner;
 class OnlyNonLearntBins;
 
+/**
+@brief Handles subsumption, self-subsuming resolution, variable elimination, and related algorithms
+
+There are two main functions in this class, simplifyBySubsumption() and subsumeWithBinaries().
+The first one is the most important of the two: it performs everything, except manipuation
+with non-existing binary clauses. The second does self-subsuming resolution with existing binary
+clauses, and then does self-subsuming resolution and subsumption with binary clauses that don't exist
+and never will exist: they are temporarily "created" (memorised), and used by subsume0BIN().
+*/
 class Subsumer
 {
 public:
 
     //Construct-destruct
     Subsumer(Solver& S2);
-    ~Subsumer();
 
     //Called from main
     const bool simplifyBySubsumption(const bool alsoLearnt = false);
-    const bool subsumeWithBinaries(OnlyNonLearntBins* onlyNonLearntBins);
     void newVar();
 
-    //Used by cleaner
-    void unlinkModifiedClause(vec<Lit>& origClause, ClauseSimp c, const bool detachAndNull);
-    void unlinkClause(ClauseSimp cc, Var elim = var_Undef);
-    ClauseSimp linkInClause(Clause& cl);
-    void linkInAlreadyClause(ClauseSimp& c);
-    void updateClause(ClauseSimp c);
-
-
     //UnElimination
     void extendModel(Solver& solver2);
     const bool unEliminate(const Var var);
 
+    //touching
+    void touchChangeVars(const Lit p);
 
     //Get-functions
     const vec<char>& getVarElimed() const;
     const uint32_t getNumElimed() const;
     const bool checkElimedUnassigned() const;
     const double getTotalTime() const;
-    
+    const map<Var, vector<vector<Lit> > >& getElimedOutVar() const;
+    const map<Var, vector<std::pair<Lit, Lit> > >& getElimedOutVarBin() const;
+
 private:
-    
+
+    const bool subsumeWithBinaries();
+
     friend class ClauseCleaner;
     friend class ClauseAllocator;
-    
+
     //Main
+    /**
+    @brief Clauses to be treated are moved here ClauseSimp::index refers to the index of the clause here
+    */
     vec<ClauseSimp>        clauses;
-    CSet                   learntClauses;
-    vec<char>              touched;        // Is set to true when a variable is part of a removed clause. Also true initially (upon variable creation).
-    vec<Var>               touched_list;   // A list of the true elements in 'touched'.
-    CSet                   cl_touched;     // Clauses strengthened.
-    CSet                   cl_added;       // Clauses created.
-    vec<vec<ClauseSimp> >  occur;          // 'occur[index(lit)]' is a list of constraints containing 'lit'.
-    vec<vec<ClauseSimp>* > iter_vecs;      // Vectors currently used for iterations. Removed clauses will be looked up and replaced by 'Clause_NULL'.
-    vec<CSet* >            iter_sets;      // Sets currently used for iterations.
-    vec<char>              cannot_eliminate;//
+    vec<char>              touchedVars;        ///<Is set to true when a variable is part of a removed clause. Also true initially (upon variable creation).
+    vec<Var>               touchedVarsList;   ///<A list of the true elements in 'touched'.
+    CSet                   cl_touched;     ///<Clauses strengthened/added
+    vec<vec<ClauseSimp> >  occur;          ///<occur[index(lit)]' is a list of constraints containing 'lit'.
+    vec<CSet* >            iter_sets;      ///<Sets currently used in iterations.
+    vec<char>              cannot_eliminate;///<Variables that cannot be eliminated due to, e.g. XOR-clauses
+    vec<char>              seen_tmp;       ///<Used in various places to help perform algorithms
 
     //Global stats
-    Solver& solver;
-    vec<char> var_elimed; //TRUE if var has been eliminated
-    double totalTime;
-    uint32_t numElimed;
-    map<Var, vector<Clause*> > elimedOutVar;
-    
-    // Temporaries (to reduce allocation overhead):
-    //
-    vec<char>           seen_tmp;       // (used in various places)
-    
-    
+    Solver& solver;                        ///<The solver this simplifier is connected to
+    vec<char> var_elimed;                  ///<Contains TRUE if var has been eliminated
+    double totalTime;                      ///<Total time spent in this class
+    uint32_t numElimed;                    ///<Total number of variables eliminated
+    map<Var, vector<vector<Lit> > > elimedOutVar; ///<Contains the clauses to use to uneliminate a variable
+    map<Var, vector<std::pair<Lit, Lit> > > elimedOutVarBin; ///<Contains the clauses to use to uneliminate a variable
+
     //Limits
-    uint32_t numVarsElimed;
-    uint32_t numMaxSubsume1;
-    uint32_t numMaxSubsume0;
-    uint32_t numMaxElim;
-    int64_t numMaxBlockToVisit;
-    uint32_t numMaxBlockVars;
-    
+    uint64_t addedClauseLits;
+    uint32_t numVarsElimed;               ///<Number of variables elimed in this run
+    int64_t numMaxSubsume1;              ///<Max. number self-subsuming resolution tries to do this run
+    int64_t numMaxSubsume0;              ///<Max. number backward-subsumption tries to do this run
+    int64_t numMaxElim;                  ///<Max. number of variable elimination tries to do this run
+    uint32_t numMaxElimVars;
+    int64_t numMaxBlockToVisit;           ///<Max. number variable-blocking clauses to visit to do this run
+    uint32_t numMaxBlockVars;             ///<Max. number variable-blocking tries to do this run
+
     //Start-up
-    template<bool UseCL>
-    void addFromSolver(vec<Clause*>& cs, bool alsoLearnt = false);
+    const uint64_t addFromSolver(vec<Clause*>& cs);
     void fillCannotEliminate();
     void clearAll();
+    void setLimits();
+    const bool subsume0AndSubsume1();
+    vec<char> ol_seenPos;
+    vec<char> ol_seenNeg;
 
     //Finish-up
     void freeMemory();
     void addBackToSolver();
     void removeWrong(vec<Clause*>& cs);
+    void removeWrongBinsAndAllTris();
     void removeAssignedVarsFromEliminated();
-    
+
     //Iterations
     void registerIteration  (CSet& iter_set) { iter_sets.push(&iter_set); }
     void unregisterIteration(CSet& iter_set) { remove(iter_sets, &iter_set); }
-    void registerIteration  (vec<ClauseSimp>& iter_vec) { iter_vecs.push(&iter_vec); }
-    void unregisterIteration(vec<ClauseSimp>& iter_vec) { remove(iter_vecs, &iter_vec); }
-    
-    // Subsumption:
+
+    //Touching
     void touch(const Var x);
-    void touch(const Lit p);
+    void touch(const Lit p, const bool learnt);
+
+    //Used by cleaner
+    void unlinkClause(ClauseSimp cc, const Var elim = var_Undef);
+    ClauseSimp linkInClause(Clause& cl);
+
+    //Findsubsumed
     template<class T>
     void findSubsumed(const T& ps, const uint32_t abst, vec<ClauseSimp>& out_subsumed);
-    bool isSubsumed(Clause& ps);
     template<class T>
-    uint32_t subsume0(T& ps, uint32_t abs);
+    void findSubsumed1(const T& ps, uint32_t abs, vec<ClauseSimp>& out_subsumed, vec<Lit>& out_lits);
     template<class T>
-    uint32_t subsume0Orig(const T& ps, uint32_t abs);
-    bool subsumedNonLearnt;
-    void subsume0BIN(const Lit lit, const vec<char>& lits);
-    void subsume1(ClauseSimp& ps);
-    void smaller_database();
-    void almost_all_database();
+    void fillSubs(const T& ps, uint32_t abs, vec<ClauseSimp>& out_subsumed, vec<Lit>& out_lits, const Lit lit);
+    template<class T2>
+    bool subset(const uint32_t aSize, const T2& B);
     template<class T1, class T2>
-    bool subset(const T1& A, const T2& B);
+    const Lit subset1(const T1& A, const T2& B);
     bool subsetAbst(uint32_t A, uint32_t B);
-    
+
+    //binary clause-subsumption
+    struct BinSorter {
+        const bool operator()(const Watched& first, const Watched& second)
+        {
+            assert(first.isBinary() || first.isTriClause());
+            assert(second.isBinary() || second.isTriClause());
+
+            if (first.isTriClause() && second.isTriClause()) return false;
+            if (first.isBinary() && second.isTriClause()) return true;
+            if (second.isBinary() && first.isTriClause()) return false;
+
+            assert(first.isBinary() && second.isBinary());
+            if (first.getOtherLit().toInt() < second.getOtherLit().toInt()) return true;
+            if (first.getOtherLit().toInt() > second.getOtherLit().toInt()) return false;
+            if (first.getLearnt() == second.getLearnt()) return false;
+            if (!first.getLearnt()) return true;
+            return false;
+        };
+    };
+    void subsumeBinsWithBins();
+
+    //subsume0
+    struct subsume0Happened {
+        bool subsumedNonLearnt;
+        uint32_t glue;
+        float act;
+    };
+    /**
+    @brief Sort clauses according to size
+    */
+    struct sortBySize
+    {
+        const bool operator () (const Clause* x, const Clause* y)
+        {
+            return (x->size() < y->size());
+        }
+    };
+    void subsume0(Clause& ps);
+    template<class T>
+    subsume0Happened subsume0Orig(const T& ps, uint32_t abs);
+    void subsume0Touched();
+    void makeNonLearntBin(const Lit lit1, const Lit lit2, const bool learnt);
+
+    //subsume1
+    class NewBinaryClause
+    {
+        public:
+            NewBinaryClause(const Lit _lit1, const Lit _lit2, const bool _learnt) :
+                lit1(_lit1), lit2(_lit2), learnt(_learnt)
+            {};
+
+            const Lit lit1;
+            const Lit lit2;
+            const bool learnt;
+    };
+    list<NewBinaryClause> clBinTouched; ///<Binary clauses strengthened/added
+    const bool handleClBinTouched();
+
+    void subsume1(Clause& ps);
+    const bool subsume1(vec<Lit>& ps, const bool wasLearnt);
+    void strenghten(ClauseSimp& c, const Lit toRemoveLit);
+    const bool cleanClause(Clause& ps);
+    const bool cleanClause(vec<Lit>& ps) const;
+    void handleSize1Clause(const Lit lit);
+
+    //Variable elimination
+    /**
+    @brief Struct used to compare variable elimination difficulties
+
+    Used to order variables according to their difficulty of elimination. Used by
+    the std::sort() function. in \function orderVarsForElim()
+    */
+    struct myComp {
+        bool operator () (const std::pair<int, Var>& x, const std::pair<int, Var>& y) {
+            return x.first < y.first ||
+                (!(y.first < x.first) && x.second < y.second);
+        }
+    };
+    class ClAndBin {
+        public:
+            ClAndBin(ClauseSimp& cl) :
+                clsimp(cl)
+                , lit1(lit_Undef)
+                , lit2(lit_Undef)
+                , isBin(false)
+            {}
+
+            ClAndBin(const Lit _lit1, const Lit _lit2) :
+                clsimp(NULL, 0)
+                , lit1(_lit1)
+                , lit2(_lit2)
+                , isBin(true)
+            {}
+
+            ClauseSimp clsimp;
+            Lit lit1;
+            Lit lit2;
+            bool isBin;
+    };
     void orderVarsForElim(vec<Var>& order);
+    const uint32_t numNonLearntBins(const Lit lit) const;
     bool maybeEliminate(Var x);
-    void MigrateToPsNs(vec<ClauseSimp>& poss, vec<ClauseSimp>& negs, vec<ClauseSimp>& ps, vec<ClauseSimp>& ns, const Var x);
-    void DeallocPsNs(vec<ClauseSimp>& ps, vec<ClauseSimp>& ns);
-    bool merge(const Clause& ps, const Clause& qs, const Lit without_p, const Lit without_q, vec<Lit>& out_clause);
+    void removeClauses(vec<ClAndBin>& posAll, vec<ClAndBin>& negAll, const Var var);
+    void removeClausesHelper(vec<ClAndBin>& todo, const Var var, std::pair<uint32_t, uint32_t>& removed);
+    bool merge(const ClAndBin& ps, const ClAndBin& qs, const Lit without_p, const Lit without_q, vec<Lit>& out_clause);
+    const bool eliminateVars();
+    void fillClAndBin(vec<ClAndBin>& all, vec<ClauseSimp>& cs, const Lit lit);
 
     //Subsume with Nonexistent Bins
-    const bool subsWNonExistBinsFull(OnlyNonLearntBins* onlyNonLearntBins);
-    const bool subsWNonExistBins(const Lit& lit, OnlyNonLearntBins* onlyNonLearntBins);
-    template<class T>
-    void subsume1Partial(const T& ps);
-    uint32_t subsNonExistentNum;
-    uint32_t subsNonExistentumFailed;
+    struct BinSorter2 {
+        const bool operator()(const Watched& first, const Watched& second)
+        {
+            assert(first.isBinary() || first.isTriClause());
+            assert(second.isBinary() || second.isTriClause());
+
+            if (first.isTriClause() && second.isTriClause()) return false;
+            if (first.isBinary() && second.isTriClause()) return true;
+            if (second.isBinary() && first.isTriClause()) return false;
+
+            assert(first.isBinary() && second.isBinary());
+            if (first.getLearnt() && !second.getLearnt()) return true;
+            if (!first.getLearnt() && second.getLearnt()) return false;
+            return false;
+        };
+    };
+    const bool subsWNonExitsBinsFullFull();
+    const bool subsWNonExistBinsFull();
+    const bool subsWNonExistBins(const Lit& lit, OnlyNonLearntBins* OnlyNonLearntBins);
+    void subsume0BIN(const Lit lit, const vec<char>& lits, const uint32_t abst);
     bool subsNonExistentFinish;
-    double subsNonExistentTime;
-    uint32_t subsNonExistentLitsRemoved;
-    vec<Clause*> addBinaryClauses;
     uint32_t doneNum;
-    vec<ClauseSimp> subsume1PartialSubs;
-    vec<Lit> subsume1PartialQs;
-    vec<Lit> toVisit;
-    vec<char> toVisitAll;
-    vec<Lit> ps2;
-    
+    uint64_t extraTimeNonExist;
+    vec<Lit> toVisit;      ///<Literals that we have visited from a given literal during subsumption w/ non-existent binaries (list)
+    vec<char> toVisitAll;  ///<Literals that we have visited from a given literal during subsumption w/ non-existent binaries (contains '1' for literal.toInt() that we visited)
+
+    //Blocked clause elimination
     class VarOcc {
         public:
             VarOcc(const Var& v, const uint32_t num) :
@@ -163,32 +284,30 @@ private:
             Var var;
             uint32_t occurnum;
     };
-    
     struct MyComp {
         const bool operator() (const VarOcc& l1, const VarOcc& l2) const {
             return l1.occurnum > l2.occurnum;
         }
     };
-    
     void blockedClauseRemoval();
-    const bool allTautology(const vec<Lit>& ps, const Lit lit);
+    template<class T>
+    const bool allTautology(const T& ps, const Lit lit);
     uint32_t numblockedClauseRemoved;
-    const bool tryOneSetting(const Lit lit, const Lit negLit);
+    const bool tryOneSetting(const Lit lit);
     priority_queue<VarOcc, vector<VarOcc>, MyComp> touchedBlockedVars;
-    vec<bool> touchedBlockedVarsBool;
+    vec<char> touchedBlockedVarsBool;
     void touchBlockedVar(const Var x);
-    double blockTime;
-    
-    
+    void blockedClauseElimAll(const Lit lit);
+
+
     //validity checking
-    void verifyIntegrity();
-    
-    uint32_t clauses_subsumed;
-    uint32_t literals_removed;
-    uint32_t origNClauses;
-    uint32_t numCalls;
-    bool fullSubsume;
-    uint32_t clauseID;
+    const bool verifyIntegrity();
+
+    uint32_t clauses_subsumed; ///<Number of clauses subsumed in this run
+    uint32_t literals_removed; ///<Number of literals removed from clauses through self-subsuming resolution in this run
+    uint32_t numCalls;         ///<Number of times simplifyBySubsumption() has been called
+    uint32_t clauseID;         ///<We need to have clauseIDs since clauses don't natively have them. The ClauseID is stored by ClauseSimp, which also stores a pointer to the clause
+    bool alsoLearnt;
 };
 
 template <class T, class T2>
@@ -198,14 +317,32 @@ void maybeRemove(vec<T>& ws, const T2& elem)
         removeW(ws, elem);
 }
 
+/**
+@brief Put varible in touched_list
+
+call it when the number of occurrences of this variable changed.
+
+@param[in] x The varible that must be put into touched_list
+*/
 inline void Subsumer::touch(const Var x)
 {
-    if (!touched[x]) {
-        touched[x] = 1;
-        touched_list.push(x);
+    if (!touchedVars[x]) {
+        touchedVars[x] = 1;
+        touchedVarsList.push(x);
     }
 }
 
+inline void Subsumer::touchChangeVars(const Lit p)
+{
+    ol_seenNeg[(~p).toInt()] = false;
+    ol_seenPos[p.toInt()] = false;
+}
+
+/**
+@brief Put varible in touchedBlockedVars
+
+call it when the number of occurrences of this variable changed.
+*/
 inline void Subsumer::touchBlockedVar(const Var x)
 {
     if (!touchedBlockedVarsBool[x]) {
@@ -214,44 +351,114 @@ inline void Subsumer::touchBlockedVar(const Var x)
     }
 }
 
-inline void Subsumer::touch(const Lit p)
+/**
+@brief Put variable of literal in touched_list
+
+call it when the number of occurrences of this variable changed
+*/
+inline void Subsumer::touch(const Lit p, const bool learnt)
 {
-    touch(p.var());
+    if (!learnt) {
+        touch(p.var());
+        touchBlockedVar(p.var());
+    }
 }
 
-inline bool Subsumer::subsetAbst(uint32_t A, uint32_t B)
+/**
+@brief Decides only using abstraction if clause A could subsume clause B
+
+@note: It can give false positives. Never gives false negatives.
+
+For A to subsume B, everything that is in A MUST be in B. So, if (A & ~B)
+contains even one bit, it means that A contains something that B doesn't. So
+A may be a subset of B only if (A & ~B) == 0
+*/
+inline bool Subsumer::subsetAbst(const uint32_t A, const uint32_t B)
 {
     return !(A & ~B);
 }
 
-// Assumes 'seen' is cleared (will leave it cleared)
+//A subsumes B (A is <= B)
+template<class T2>
+bool Subsumer::subset(const uint32_t aSize, const T2& B)
+{
+    uint32_t num = 0;
+    for (uint32_t i = 0; i != B.size(); i++) {
+        num += seen_tmp[B[i].toInt()];
+    }
+    return num == aSize;
+}
+
+
+/**
+@brief Decides if A subsumes B, or if not, if A could strenghten B
+
+@note: Assumes 'seen' is cleared (will leave it cleared)
+
+Helper function findSubsumed1. Does two things in one go:
+1) decides if clause A could subsume clause B
+1) decides if clause A could be used to perform self-subsuming resoltuion on
+clause B
+
+@return lit_Error, if neither (1) or (2) is true. Returns lit_Undef (1) is true,
+and returns the literal to remove if (2) is true
+*/
 template<class T1, class T2>
-bool Subsumer::subset(const T1& A, const T2& B)
+const Lit Subsumer::subset1(const T1& A, const T2& B)
 {
+    Lit retLit = lit_Undef;
+
     for (uint32_t i = 0; i != B.size(); i++)
         seen_tmp[B[i].toInt()] = 1;
     for (uint32_t i = 0; i != A.size(); i++) {
         if (!seen_tmp[A[i].toInt()]) {
-            for (uint32_t i = 0; i != B.size(); i++)
-                seen_tmp[B[i].toInt()] = 0;
-            return false;
+            if (retLit == lit_Undef && seen_tmp[(~A[i]).toInt()])
+                retLit = ~A[i];
+            else {
+                retLit = lit_Error;
+                goto end;
+            }
         }
     }
+
+    end:
     for (uint32_t i = 0; i != B.size(); i++)
         seen_tmp[B[i].toInt()] = 0;
-    return true;
+    return retLit;
 }
 
+/**
+@brief New var has been added to the solver
+
+@note: MUST be called if a new var has been added to the solver
+
+Adds occurrence list places, increments seen_tmp, etc.
+*/
 inline void Subsumer::newVar()
 {
     occur       .push();
     occur       .push();
     seen_tmp    .push(0);       // (one for each polarity)
     seen_tmp    .push(0);
-    touched     .push(1);
+    touchedVars   .push(0);
     var_elimed  .push(0);
     touchedBlockedVarsBool.push(0);
     cannot_eliminate.push(0);
+    ol_seenPos.push(1);
+    ol_seenPos.push(1);
+    ol_seenNeg.push(1);
+    ol_seenNeg.push(1);
+    touch(solver.nVars()-1);
+}
+
+inline const map<Var, vector<vector<Lit> > >& Subsumer::getElimedOutVar() const
+{
+    return elimedOutVar;
+}
+
+inline const map<Var, vector<std::pair<Lit, Lit> > >& Subsumer::getElimedOutVarBin() const
+{
+    return elimedOutVarBin;
 }
 
 inline const vec<char>& Subsumer::getVarElimed() const
@@ -269,6 +476,4 @@ inline const double Subsumer::getTotalTime() const
     return totalTime;
 }
 
-}; //NAMESPACE MINISAT
-
 #endif //SIMPLIFIER_H
index 56fb654f1540b066147b80bcd3627f7da8f9cf56..4014df81b1d9881122f53f6a75d616c04b6aa136 100644 (file)
@@ -1,4 +1,4 @@
-/***********************************************************************************
+/***************************************************************************
 CryptoMiniSat -- Copyright (c) 2009 Mate Soos
 
 This program is free software: you can redistribute it and/or modify
@@ -13,28 +13,36 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
-**************************************************************************************************/
+****************************************************************************/
 
 #include <iomanip>
 #include "UselessBinRemover.h"
 #include "VarReplacer.h"
 #include "ClauseCleaner.h"
 #include "time_mem.h"
-#include "OnlyNonLearntBins.h"
 
-namespace MINISAT
-{
-using namespace MINISAT;
+//#define VERBOSE_DEBUG
 
-UselessBinRemover::UselessBinRemover(Solver& _solver, OnlyNonLearntBins& _onlyNonLearntBins) :
+UselessBinRemover::UselessBinRemover(Solver& _solver) :
     solver(_solver)
-    , onlyNonLearntBins(_onlyNonLearntBins)
 {
 }
 
+/**
+@brief Time limiting
+*/
 #define MAX_REMOVE_BIN_FULL_PROPS 20000000
-#define EXTRATIME_DIVIDER 2
+/**
+@brief We measure time in (bogo)propagations and "extra" time, time not accountable in (bogo)props
+*/
+#define EXTRATIME_DIVIDER 3
+
+/**
+@brief Removes useless binary non-learnt clauses. See definiton of class for details
 
+We pick variables starting randomly at a place and going on until we stop:
+we limit ourselves in time using (bogo)propagations and "extratime"
+*/
 const bool UselessBinRemover::removeUslessBinFull()
 {
     double myTime = cpuTime();
@@ -43,7 +51,9 @@ const bool UselessBinRemover::removeUslessBinFull()
     uint32_t origHeapSize = solver.order_heap.size();
     uint64_t origProps = solver.propagations;
     bool fixed = false;
-    uint32_t extraTime = solver.binaryClauses.size() / EXTRATIME_DIVIDER;
+    uint32_t extraTime = 0;
+    uint32_t numBinsBefore = solver.numBins;
+    solver.sortWatched(); //VERY important
 
     uint32_t startFrom = solver.mtrand.randInt(solver.order_heap.size());
     for (uint32_t i = 0; i != solver.order_heap.size(); i++) {
@@ -54,7 +64,7 @@ const bool UselessBinRemover::removeUslessBinFull()
         Lit lit(var, true);
         if (!removeUselessBinaries(lit)) {
             fixed = true;
-            solver.cancelUntil(0);
+            solver.cancelUntilLight();
             solver.uncheckedEnqueue(~lit);
             solver.ok = (solver.propagate().isNULL());
             if (!solver.ok) return false;
@@ -64,7 +74,7 @@ const bool UselessBinRemover::removeUslessBinFull()
         lit = ~lit;
         if (!removeUselessBinaries(lit)) {
             fixed = true;
-            solver.cancelUntil(0);
+            solver.cancelUntilLight();
             solver.uncheckedEnqueue(~lit);
             solver.ok = (solver.propagate().isNULL());
             if (!solver.ok) return false;
@@ -72,27 +82,40 @@ const bool UselessBinRemover::removeUslessBinFull()
         }
     }
 
-    uint32_t removedUselessBin = onlyNonLearntBins.removeBins();
-
     if (fixed) solver.order_heap.filter(Solver::VarFilter(solver));
 
-    if (solver.verbosity >= 1) {
+    if (solver.conf.verbosity >= 1) {
         std::cout
-        << "c Removed useless bin:" << std::setw(8) << removedUselessBin
+        << "c Removed useless bin:" << std::setw(8) << (numBinsBefore - solver.numBins)
         << "  fixed: " << std::setw(5) << (origHeapSize - solver.order_heap.size())
         << "  props: " << std::fixed << std::setprecision(2) << std::setw(6) << (double)(solver.propagations - origProps)/1000000.0 << "M"
         << "  time: " << std::fixed << std::setprecision(2) << std::setw(5) << cpuTime() - myTime << " s"
-        << std::setw(16)  << "   |" << std::endl;
+        << std::endl;
     }
 
     return true;
 }
 
-const bool UselessBinRemover::removeUselessBinaries(const Lit& lit)
+/**
+@brief Removes useless binaries of the graph portion that starts with lit
+
+We try binary-space propagation on lit. Then, we check that we cannot reach any
+of its one-hop neighboours from any of its other one-hope neighbours. If we can,
+we remove the one-hop neighbour from the neightbours (i.e. remove the binary
+clause). Example:
+
+\li a->b, a->c, b->c
+\li In claues: (-a V b), (-a V c), (-b V c)
+
+One-hop neighbours of a: b, c. But c can be reached through b! So, we remove
+a->c, the one-hop neighbour that is useless.
+*/
+const bool UselessBinRemover::removeUselessBinaries(const Lit lit)
 {
     solver.newDecisionLevel();
     solver.uncheckedEnqueueLight(lit);
-    failed = !onlyNonLearntBins.propagateBinOneLevel();
+    //Propagate only one hop
+    failed = !solver.propagateBinOneLevel();
     if (failed) return false;
     bool ret = true;
 
@@ -100,9 +123,10 @@ const bool UselessBinRemover::removeUselessBinaries(const Lit& lit)
     assert(solver.decisionLevel() > 0);
     int c;
     if (solver.trail.size()-solver.trail_lim[0] == 0) {
-        solver.cancelUntil(0);
+        solver.cancelUntilLight();
         goto end;
     }
+    //Fill oneHopAway and toDeleteSet with lits that are 1 hop away
     extraTime += (solver.trail.size() - solver.trail_lim[0]) / EXTRATIME_DIVIDER;
     for (c = solver.trail.size()-1; c > (int)solver.trail_lim[0]; c--) {
         Lit x = solver.trail[c];
@@ -118,6 +142,8 @@ const bool UselessBinRemover::removeUselessBinaries(const Lit& lit)
     //solver.cancelUntil(0);
 
     wrong.clear();
+    //We now try to reach the one-hop-away nodes from other one-hop-away
+    //nodes, but this time we propagate all the way
     for(uint32_t i = 0; i < oneHopAway.size(); i++) {
         //no need to visit it if it already queued for removal
         //basically, we check if it's in 'wrong'
@@ -141,40 +167,43 @@ const bool UselessBinRemover::removeUselessBinaries(const Lit& lit)
     return ret;
 }
 
-void UselessBinRemover::removeBin(const Lit& lit1, const Lit& lit2)
-{
-    /*******************
-    Lit litFind1 = lit_Undef;
-    Lit litFind2 = lit_Undef;
-
-    if (solver.binwatches[(~lit1).toInt()].size() < solver.binwatches[(~lit2).toInt()].size()) {
-        litFind1 = lit1;
-        litFind2 = lit2;
-    } else {
-        litFind1 = lit2;
-        litFind2 = lit1;
-    }
-    ********************/
+/**
+@brief Removes a binary clause (lit1 V lit2)
 
-    //Find AND remove from watches
+The binary clause might be in twice, three times, etc. Take care to remove
+all instances of it.
+*/
+void UselessBinRemover::removeBin(const Lit lit1, const Lit lit2)
+{
     #ifdef VERBOSE_DEBUG
-    std::cout << "Removing useless bin: ";
-    lit1.print(); lit2.printFull();
+    std::cout << "Removing useless bin: " << lit1 << " " << lit2 << std::endl;
     #endif //VERBOSE_DEBUG
-    
-    solver.removeWatchedBinClAll(solver.binwatches[(~lit1).toInt()], lit2);
-    solver.removeWatchedBinClAll(solver.binwatches[(~lit2).toInt()], lit1);
-    onlyNonLearntBins.removeBin(lit1, lit2);
+
+    std::pair<uint32_t, uint32_t> removed1 = removeWBinAll(solver.watches[(~lit1).toInt()], lit2);
+    std::pair<uint32_t, uint32_t> removed2 = removeWBinAll(solver.watches[(~lit2).toInt()], lit1);
+    assert(removed1 == removed2);
+
+    assert((removed1.first + removed2.first) % 2 == 0);
+    assert((removed1.second + removed2.second) % 2 == 0);
+    solver.learnts_literals -= (removed1.first + removed2.first);
+    solver.clauses_literals -= (removed1.second + removed2.second);
+    solver.numBins -= (removed1.first + removed2.first + removed1.second + removed2.second)/2;
 }
 
-const bool UselessBinRemover::fillBinImpliesMinusLast(const Lit& origLit, const Lit& lit, vec<Lit>& wrong)
+/**
+@brief Propagates all the way lit, but doesn't propagate origLit
+
+Removes adds to "wrong" the set of one-hop lits that can be reached from
+lit AND are one-hop away from origLit. These later need to be removed
+*/
+const bool UselessBinRemover::fillBinImpliesMinusLast(const Lit origLit, const Lit lit, vec<Lit>& wrong)
 {
     solver.newDecisionLevel();
     solver.uncheckedEnqueueLight(lit);
     //if it's a cycle, it doesn't work, so don't propagate origLit
-    failed = !onlyNonLearntBins.propagateBinExcept(origLit);
+    failed = !solver.propagateBinExcept(origLit);
     if (failed) return false;
-    
+
     assert(solver.decisionLevel() > 0);
     int c;
     extraTime += (solver.trail.size() - solver.trail_lim[0]) / EXTRATIME_DIVIDER;
@@ -187,13 +216,12 @@ const bool UselessBinRemover::fillBinImpliesMinusLast(const Lit& origLit, const
         solver.assigns[x.var()] = l_Undef;
     }
     solver.assigns[solver.trail[c].var()] = l_Undef;
-    
+
     solver.qhead = solver.trail_lim[0];
     solver.trail.shrink_(solver.trail.size() - solver.trail_lim[0]);
     solver.trail_lim.clear();
     //solver.cancelUntil(0);
-    
+
     return true;
 }
 
-}; //NAMESPACE MINISAT
index 771bd1b19ccc97f8ff7468f64d4642e80c69f161..6670aaf270b0dcd2e8022415d13e060d48a403a6 100644 (file)
@@ -20,34 +20,62 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include "Vec.h"
 #include "Solver.h"
-#include "OnlyNonLearntBins.h"
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
 #include <stdint.h>
+#endif //_MSC_VER
 
-namespace MINISAT
-{
-using namespace MINISAT;
+/**
+@brief Removes binary clauses that are effectively useless to have
 
+These binary clauses are useless, because for example clauses:
+a V b
+-b V c
+
+exist, so the binary clause:
+a V c
+
+is useless in every possible way. Here, we remove such claues. Unfortunately,
+currently we only remove useless non-learnt binary clauses. Learnt useless
+binary clauses are not removed.
+
+\todo Extend such that it removes learnt useless binary clauses as well
+*/
 class UselessBinRemover {
     public:
-        UselessBinRemover(Solver& solver, OnlyNonLearntBins& onlyNonLearntBins);
+        UselessBinRemover(Solver& solver);
         const bool removeUslessBinFull();
-        
+
     private:
-        bool failed;
-        uint32_t extraTime;
-        
+        bool failed; ///<Has the previous propagation failed? (=conflict)
+        uint32_t extraTime; ///<Time that cannot be meausured in bogoprops (~propagation time)
+
         //Remove useless binaries
-        const bool fillBinImpliesMinusLast(const Lit& origLit, const Lit& lit, vec<Lit>& wrong);
-        const bool removeUselessBinaries(const Lit& lit);
-        void removeBin(const Lit& lit1, const Lit& lit2);
+        const bool fillBinImpliesMinusLast(const Lit origLit, const Lit lit, vec<Lit>& wrong);
+        const bool removeUselessBinaries(const Lit lit);
+        void removeBin(const Lit lit1, const Lit lit2);
+        /**
+        @brief Don't delete the same binary twice, and don't assume that deleted binaries still exist
+
+        Not deleting the same binary twice is easy to understand. He hard part
+        is the second thought. Basically, once we set "a->b" to be deleted, for
+        instance, we should not check whether any one-hop neighbours of "a" can
+        be reached from "b", since the binary clause leading to "b" has already
+        been deleted (and, by the way, checked, since the place where we can
+        reach "b" from already checked for all places we can visit from "b")
+        */
         vec<char> toDeleteSet;
-        vec<Lit> oneHopAway;
+        vec<Lit> oneHopAway; ///<Lits that are one hop away from selected lit (sometimes called origLit)
+        /**
+        @brief Binary clauses to be removed are gathered here
+
+        We only gather the second lit, the one we can reach from selected lit
+        (calld origLit some places) see fillBinImpliesMinusLast() for details
+        */
         vec<Lit> wrong;
 
-        Solver& solver;
-        OnlyNonLearntBins& onlyNonLearntBins;
+        Solver& solver; ///<The solver class e want to remove useless binary clauses from
 };
 
 #endif //USELESSBINREMOVER_H
-
-}; //NAMESPACE MINISAT
index 92f1ee215d2557892dc55d040f1589a3022ff972..02151f1a4f37832e8d4205c9926db334f704cbe7 100644 (file)
@@ -1,2 +1,2 @@
 CryptoMiniSat
-GIT revision: e540792aa3a01ec047b005b6351247fa87ae6eb6
+GIT revision: 588152bb03adf98ffd581c4579e1d6c5eec92f8f
index fd82cdefa08dc3e961c4aa88dcc25a456a16941c..42b3280848ff7fa1d3cd159d45ca19b4e6f1a7f0 100644 (file)
@@ -1,4 +1,4 @@
-/***********************************************************************************
+/*****************************************************************************
 CryptoMiniSat -- Copyright (c) 2009 Mate Soos
 
 This program is free software: you can redistribute it and/or modify
@@ -13,19 +13,22 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
-**************************************************************************************************/
+******************************************************************************/
 
 #include "VarReplacer.h"
 #include <iostream>
 #include <iomanip>
+#include <set>
 
 #include "ClauseCleaner.h"
 #include "PartHandler.h"
 #include "time_mem.h"
+#include "DataSync.h"
 
 //#define VERBOSE_DEBUG
 //#define DEBUG_REPLACER
 //#define REPLACE_STATISTICS
+//#define DEBUG_BIN_REPLACER
 
 #ifdef VERBOSE_DEBUG
 #include <iostream>
@@ -33,10 +36,6 @@ using std::cout;
 using std::endl;
 #endif
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 VarReplacer::VarReplacer(Solver& _solver) :
     replacedLits(0)
     , replacedVars(0)
@@ -47,63 +46,74 @@ VarReplacer::VarReplacer(Solver& _solver) :
 
 VarReplacer::~VarReplacer()
 {
-    for (uint i = 0; i != clauses.size(); i++)
-        solver.clauseAllocator.clauseFree(clauses[i]);
 }
 
+/**
+@brief Replaces variables, clears internal clauses, and reports stats
+
+When replacing, it is imperative not to make variables decision variables
+which have been removed by other methods:
+\li variable removal at the xor-sphere
+\li disconnected component finding and solving
+\li variable elimination
+
+NOTE: If any new such algoirhtms are added, this part MUST be updated such
+that problems don't creep up
+*/
 const bool VarReplacer::performReplaceInternal()
 {
     #ifdef VERBOSE_DEBUG
-    cout << "Replacer started." << endl;
+    cout << "PerformReplacInternal started." << endl;
+    //solver.printAllClauses();
     #endif
     double time = cpuTime();
-    
+
     #ifdef REPLACE_STATISTICS
-    uint numRedir = 0;
-    for (uint i = 0; i < table.size(); i++) {
+    uint32_t numRedir = 0;
+    for (uint32_t i = 0; i < table.size(); i++) {
         if (table[i].var() != i)
             numRedir++;
     }
     std::cout << "Number of trees:" << reverseTable.size() << std::endl;
     std::cout << "Number of redirected nodes:" << numRedir << std::endl;
-    /*map<Var, vector<Var> >::iterator it = reverseTable.begin();
-    map<Var, vector<Var> >::iterator end = reverseTable.end();
-    for (;it != end; it++) {
-        std::cout << "Tree size: " << it->second.size() << std::endl;
-    }*/
     #endif //REPLACE_STATISTICS
-    
+
     solver.clauseCleaner->removeAndCleanAll(true);
     if (!solver.ok) return false;
     solver.testAllClauseAttach();
-    
+    std::fill(cannot_eliminate.getData(), cannot_eliminate.getDataEnd(), false);
+
     #ifdef VERBOSE_DEBUG
     {
-        uint i = 0;
+        uint32_t i = 0;
         for (vector<Lit>::const_iterator it = table.begin(); it != table.end(); it++, i++) {
             if (it->var() == i) continue;
-            cout << "Replacing var " << i+1 << " with Lit " << (it->sign() ? "-" : "") <<  it->var()+1 << endl;
+            cout << "Replacing var " << i+1 << " with Lit " << *it << endl;
         }
     }
     #endif
-    
+
     Var var = 0;
-    const vec<char>* removedVars = solver.doXorSubsumption ? &solver.xorSubsumer->getVarElimed() : NULL;
-    const vec<lbool>* removedVars2 = solver.doPartHandler ?  &solver.partHandler->getSavedState() : NULL;
-    const vec<char>* removedVars3 = solver.doSubsumption ? &solver.subsumer->getVarElimed() : NULL;
+    const vec<char>& removedVars = solver.xorSubsumer->getVarElimed();
+    const vec<lbool>& removedVars2 = solver.partHandler->getSavedState();
+    const vec<char>& removedVars3 = solver.subsumer->getVarElimed();
     for (vector<Lit>::const_iterator it = table.begin(); it != table.end(); it++, var++) {
         if (it->var() == var
-            || (removedVars != NULL && (*removedVars)[it->var()])
-            || (removedVars2 != NULL && (*removedVars2)[it->var()] != l_Undef)
-            || (removedVars3!= NULL && (*removedVars3)[it->var()])
+            || removedVars[it->var()]
+            || removedVars2[it->var()] != l_Undef
+            || removedVars3[it->var()]
         ) continue;
         #ifdef VERBOSE_DEBUG
         cout << "Setting var " << var+1 << " to a non-decision var" << endl;
         #endif
         bool wasDecisionVar = solver.decision_var[var];
         solver.setDecisionVar(var, false);
+        //cannot_eliminate[var] = true;
         solver.setDecisionVar(it->var(), true);
-        
+        assert(!removedVars[var]);
+        assert(removedVars2[var] == l_Undef);
+        assert(!removedVars3[var]);
+
         uint32_t& activity1 = solver.activity[var];
         uint32_t& activity2 = solver.activity[it->var()];
         if (wasDecisionVar && activity1 > activity2) {
@@ -111,70 +121,80 @@ const bool VarReplacer::performReplaceInternal()
             solver.order_heap.update(it->var());
             solver.polarity[it->var()] = solver.polarity[var]^it->sign();
         }
-        
+
         activity1 = 0.0;
         solver.order_heap.update(var);
     }
     assert(solver.order_heap.heapProperty());
-    
-    if (solver.verbosity >= 2)
-        std::cout << "c |  Replacing " << std::setw(8) << replacedVars-lastReplacedVars << " vars" << std::flush;
-    
+
+    uint32_t thisTimeReplaced = replacedVars -lastReplacedVars;
     lastReplacedVars = replacedVars;
-    
+
     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;
+    assert(solver.qhead == solver.trail.size());
+
+    solver.countNumBinClauses(true, false);
+    solver.countNumBinClauses(false, true);
+
+    if (!replaceBins()) goto end;
+    if (!replace_set(solver.clauses)) goto end;
+    if (!replace_set(solver.learnts)) goto end;
     if (!replace_set(solver.xorclauses)) goto end;
     solver.testAllClauseAttach();
-    
+
 end:
-    for (uint i = 0; i != clauses.size(); i++)
-        solver.removeClause(*clauses[i]);
-    clauses.clear();
-    
-    if (solver.verbosity >= 2) {
-        std::cout << "       Replaced " <<  std::setw(8) << replacedLits<< " lits"
-        << "       Time: " << std::setw(8) << std::fixed << std::setprecision(2) << cpuTime()-time << " s "
-        << std::setw(10) <<  " |" << std::endl;
+    assert(solver.qhead == solver.trail.size() || !solver.ok);
+
+    if (solver.conf.verbosity  >= 2) {
+        std::cout << "c Replacing "
+        << std::setw(8) << thisTimeReplaced << " vars"
+        << " Replaced " <<  std::setw(8) << replacedLits<< " lits"
+        << " Time: " << std::setw(8) << std::fixed << std::setprecision(2)
+        << cpuTime()-time << " s "
+        << std::endl;
     }
-    
+
     replacedLits = 0;
-    
+
     solver.order_heap.filter(Solver::VarFilter(solver));
-    
+
     return solver.ok;
 }
 
+/**
+@brief Replaces vars in xorclauses
+*/
 const bool VarReplacer::replace_set(vec<XorClause*>& cs)
 {
     XorClause **a = cs.getData();
     XorClause **r = a;
     for (XorClause **end = a + cs.size(); r != end; r++) {
         XorClause& c = **r;
-        
+
         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()) {
                 changed = true;
                 *l = Lit(newlit.var(), false);
                 c.invert(newlit.sign());
-                c.setVarChanged();
                 replacedLits++;
             }
         }
-        
+
         if (changed && handleUpdatedClause(c, origVar1, origVar2)) {
             if (!solver.ok) {
+                #ifdef VERBOSE_DEBUG
+                cout << "contradiction while replacing lits in xor clause" << std::endl;
+                #endif
                 for(;r != end; r++) solver.clauseAllocator.clauseFree(*r);
                 cs.shrink(r-a);
                 return false;
             }
+            //solver.clauseAllocator.clauseFree(&c);
             c.setRemoved();
             solver.freeLater.push(&c);
         } else {
@@ -182,13 +202,16 @@ const bool VarReplacer::replace_set(vec<XorClause*>& cs)
         }
     }
     cs.shrink(r-a);
-    
+
     return solver.ok;
 }
 
+/**
+@brief Helper function for replace_set()
+*/
 const bool VarReplacer::handleUpdatedClause(XorClause& c, const Var origVar1, const Var origVar2)
 {
-    uint origSize = c.size();
+    uint32_t origSize = c.size();
     std::sort(c.getData(), c.getDataEnd());
     Lit p;
     uint32_t i, j;
@@ -201,31 +224,33 @@ const bool VarReplacer::handleUpdatedClause(XorClause& c, const Var origVar1, co
                 c.invert(solver.assigns[c[i].var()].getBool());
         } 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
+        else c.invert(solver.assigns[c[i].var()].getBool()); //modify xorEqualFalse instead of adding
     }
     c.shrink(i - j);
-    
+    c.setStrenghtened();
+
     #ifdef VERBOSE_DEBUG
     cout << "xor-clause after replacing: ";
     c.plainPrint();
     #endif
-    
+
     switch (c.size()) {
     case 0:
         solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
-        if (!c.xor_clause_inverted())
+        if (!c.xorEqualFalse()) {
             solver.ok = false;
+        }
         return true;
     case 1:
         solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
-        solver.uncheckedEnqueue(Lit(c[0].var(), c.xor_clause_inverted()));
+        solver.uncheckedEnqueue(Lit(c[0].var(), c.xorEqualFalse()));
         solver.ok = (solver.propagate().isNULL());
         return true;
     case 2: {
         solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
-        c[0] = c[0].unsign();
+        c[0] = c[0].unsign() ^ c.xorEqualFalse();
         c[1] = c[1].unsign();
-        addBinaryXorClause(c, c.xor_clause_inverted(), c.getGroup(), true);
+        addBinaryXorClause(c[0], c[1], c.getGroup());
         return true;
     }
     default:
@@ -233,59 +258,162 @@ const bool VarReplacer::handleUpdatedClause(XorClause& c, const Var origVar1, co
         solver.attachClause(c);
         return false;
     }
-    
+
     assert(false);
     return false;
 }
 
-const bool VarReplacer::replace_set(vec<Clause*>& cs, const bool binClauses)
+const bool VarReplacer::replaceBins()
+{
+    #ifdef DEBUG_BIN_REPLACER
+    vec<uint32_t> removed(solver.nVars()*2, 0);
+    uint32_t replacedLitsBefore = replacedLits;
+    #endif
+
+    uint32_t removedLearnt = 0;
+    uint32_t removedNonLearnt = 0;
+    uint32_t wsLit = 0;
+    for (vec<Watched> *it = solver.watches.getData(), *end = solver.watches.getDataEnd(); it != end; it++, wsLit++) {
+        Lit lit1 = ~Lit::toLit(wsLit);
+        vec<Watched>& ws = *it;
+
+        Watched *i = ws.getData();
+        Watched *j = i;
+        for (Watched *end2 = ws.getDataEnd(); i != end2; i++) {
+            if (!i->isBinary()) {
+                *j++ = *i;
+                continue;
+            }
+            //std::cout << "bin: " << lit1 << " , " << i->getOtherLit() << " learnt : " <<  (i->isLearnt()) << std::endl;
+            Lit thisLit1 = lit1;
+            Lit lit2 = i->getOtherLit();
+            Lit origLit2 = lit2;
+            assert(thisLit1.var() != lit2.var());
+
+            if (table[lit2.var()].var() != lit2.var()) {
+                lit2 = table[lit2.var()] ^ lit2.sign();
+                i->setOtherLit(lit2);
+                replacedLits++;
+            }
+
+            bool changedMain = false;
+            if (table[thisLit1.var()].var() != thisLit1.var()) {
+                thisLit1 = table[thisLit1.var()] ^ thisLit1.sign();
+                replacedLits++;
+                changedMain = true;
+            }
+
+            if (thisLit1 == lit2) {
+                if (solver.value(lit2) == l_Undef) {
+                    solver.uncheckedEnqueue(lit2);
+                } else if (solver.value(lit2) == l_False) {
+                    #ifdef VERBOSE_DEBUG
+                    std::cout << "Contradiction during replacement of lits in binary clause" << std::endl;
+                    #endif
+                    solver.ok = false;
+                }
+                #ifdef DEBUG_BIN_REPLACER
+                removed[lit1.toInt()]++;
+                removed[origLit2.toInt()]++;
+                #endif
+
+                if (i->getLearnt()) removedLearnt++;
+                else removedNonLearnt++;
+                continue;
+            }
+
+            if (thisLit1 == ~lit2) {
+                #ifdef DEBUG_BIN_REPLACER
+                removed[lit1.toInt()]++;
+                removed[origLit2.toInt()]++;
+                #endif
+
+                if (i->getLearnt()) removedLearnt++;
+                else removedNonLearnt++;
+                continue;
+            }
+
+            if (changedMain) {
+                solver.watches[(~thisLit1).toInt()].push(*i);
+            } else {
+                *j++ = *i;
+            }
+        }
+        ws.shrink_(i-j);
+    }
+
+    #ifdef DEBUG_BIN_REPLACER
+    for (uint32_t i = 0; i < removed.size(); i++) {
+        if (removed[i] % 2 != 0) {
+            std::cout << "suspicious: " << Lit::toLit(i) << std::endl;
+            std::cout << "num: " << removed[i] << std::endl;
+        }
+    }
+    std::cout << "replacedLitsdiff: " << replacedLits - replacedLitsBefore << std::endl;
+    std::cout << "removedLearnt: " << removedLearnt << std::endl;
+    std::cout << "removedNonLearnt: " << removedNonLearnt << std::endl;
+    #endif
+
+    assert(removedLearnt % 2 == 0);
+    assert(removedNonLearnt % 2 == 0);
+    solver.learnts_literals -= removedLearnt;
+    solver.clauses_literals -= removedNonLearnt;
+    solver.numBins -= (removedLearnt + removedNonLearnt)/2;
+
+    if (solver.ok) solver.ok = (solver.propagate().isNULL());
+    return solver.ok;
+}
+
+/**
+@brief Replaces variables in normal clauses
+*/
+const bool VarReplacer::replace_set(vec<Clause*>& cs)
 {
     Clause **a = cs.getData();
     Clause **r = a;
     for (Clause **end = a + cs.size(); r != end; r++) {
         Clause& c = **r;
+        assert(c.size() > 2);
         bool changed = false;
         Lit origLit1 = c[0];
         Lit origLit2 = c[1];
+        Lit origLit3 = (c.size() == 3) ? c[2] : lit_Undef;
         for (Lit *l = c.getData(), *end2 = l + c.size();  l != end2; l++) {
             if (table[l->var()].var() != l->var()) {
                 changed = true;
                 *l = table[l->var()] ^ l->sign();
-                c.setVarChanged();
                 replacedLits++;
             }
         }
-        
-        if (changed && handleUpdatedClause(c, origLit1, origLit2)) {
+
+        if (changed && handleUpdatedClause(c, origLit1, origLit2, origLit3)) {
             if (!solver.ok) {
+                #ifdef VERBOSE_DEBUG
+                cout << "contradiction while replacing lits in normal clause" << std::endl;
+                #endif
                 for(;r != end; r++) solver.clauseAllocator.clauseFree(*r);
                 cs.shrink(r-a);
                 return false;
             }
         } else {
-            if (!binClauses && c.size() == 2) {
-                solver.detachClause(c);
-                Clause *c2 = solver.clauseAllocator.Clause_new(c);
-                solver.clauseAllocator.clauseFree(&c);
-                solver.attachClause(*c2);
-                solver.becameBinary++;
-                solver.binaryClauses.push(c2);
-            } else
-                *a++ = *r;
+            *a++ = *r;
         }
     }
     cs.shrink(r-a);
-    
+
     return solver.ok;
 }
 
-const bool VarReplacer::handleUpdatedClause(Clause& c, const Lit origLit1, const Lit origLit2)
+/**
+@brief Helper function for replace_set()
+*/
+const bool VarReplacer::handleUpdatedClause(Clause& c, const Lit origLit1, const Lit origLit2, const Lit origLit3)
 {
     bool satisfied = false;
     std::sort(c.getData(), c.getData() + c.size());
     Lit p;
     uint32_t i, j;
-    const uint origSize = c.size();
+    const uint32_t origSize = c.size();
     for (i = j = 0, p = lit_Undef; i != origSize; i++) {
         if (solver.value(c[i]) == l_True || c[i] == ~p) {
             satisfied = true;
@@ -295,59 +423,79 @@ const bool VarReplacer::handleUpdatedClause(Clause& c, const Lit origLit1, const
             c[j++] = p = c[i];
     }
     c.shrink(i - j);
-    
-    if (satisfied) {
-        solver.detachModifiedClause(origLit1, origLit2, origSize, &c);
-        return true;
+    c.setStrenghtened();
+
+    if (!c.learnt()) {
+        for (Lit *i2 = c.getData(), *end2 = c.getDataEnd(); i2 != end2; i2++)
+            solver.subsumer->touchChangeVars(*i2);
     }
-    
+
+    solver.detachModifiedClause(origLit1, origLit2, origLit3, origSize, &c);
+
+    #ifdef VERBOSE_DEBUG
+    cout << "clause after replacing: ";
+    c.plainPrint();
+    #endif
+
+    if (satisfied) return true;
+
     switch(c.size()) {
     case 0:
-        solver.detachModifiedClause(origLit1, origLit2, origSize, &c);
         solver.ok = false;
         return true;
     case 1 :
-        solver.detachModifiedClause(origLit1, origLit2, origSize, &c);
         solver.uncheckedEnqueue(c[0]);
         solver.ok = (solver.propagate().isNULL());
         return true;
+    case 2:
+        solver.attachBinClause(c[0], c[1], c.learnt());
+        solver.numNewBin++;
+        solver.dataSync->signalNewBinClause(c);
+        return true;
     default:
-        solver.detachModifiedClause(origLit1, origLit2, origSize, &c);
         solver.attachClause(c);
-        
         return false;
     }
-    
+
     assert(false);
     return false;
 }
 
+/**
+@brief Returns variables that have been replaced
+*/
 const vector<Var> VarReplacer::getReplacingVars() const
 {
     vector<Var> replacingVars;
-    
+
     for(map<Var, vector<Var> >::const_iterator it = reverseTable.begin(), end = reverseTable.end(); it != end; it++) {
         replacingVars.push_back(it->first);
     }
-    
+
     return replacingVars;
 }
 
+/**
+@brief Given a partial model, it tries to extend it to variables that have been replaced
+
+Cannot extend it fully, because it might be that a replaced d&f, but a was
+later variable-eliminated. That's where extendModelImpossible() comes in
+*/
 void VarReplacer::extendModelPossible() const
 {
     #ifdef VERBOSE_DEBUG
     std::cout << "extendModelPossible() called" << std::endl;
     #endif //VERBOSE_DEBUG
-    uint i = 0;
+    uint32_t i = 0;
     for (vector<Lit>::const_iterator it = table.begin(); it != table.end(); it++, i++) {
         if (it->var() == i) continue;
-        
+
         #ifdef VERBOSE_DEBUG
         cout << "Extending model: var "; solver.printLit(Lit(i, false));
         cout << " to "; solver.printLit(*it);
         cout << endl;
         #endif
-        
+
         if (solver.assigns[it->var()] != l_Undef) {
             if (solver.assigns[i] == l_Undef) {
                 bool val = (solver.assigns[it->var()] == l_False);
@@ -361,27 +509,34 @@ void VarReplacer::extendModelPossible() const
     }
 }
 
+/**
+@brief Used when a variable was eliminated, but it replaced some other variables
+
+This function will add to solver2 clauses that represent the relationship of
+the variables to their replaced cousins. Then, calling solver2.solve() should
+take care of everything
+*/
 void VarReplacer::extendModelImpossible(Solver& solver2) const
 {
 
     #ifdef VERBOSE_DEBUG
     std::cout << "extendModelImpossible() called" << std::endl;
     #endif //VERBOSE_DEBUG
-    
+
     vec<Lit> tmpClause;
-    uint i = 0;
+    uint32_t i = 0;
     for (vector<Lit>::const_iterator it = table.begin(); it != table.end(); it++, i++) {
         if (it->var() == i) continue;
         if (solver.assigns[it->var()] == l_Undef) {
             assert(solver.assigns[it->var()] == l_Undef);
             assert(solver.assigns[i] == l_Undef);
-            
+
             tmpClause.clear();
             tmpClause.push(Lit(it->var(), true));
             tmpClause.push(Lit(i, it->sign()));
             solver2.addClause(tmpClause);
             assert(solver2.ok);
-            
+
             tmpClause.clear();
             tmpClause.push(Lit(it->var(), false));
             tmpClause.push(Lit(i, it->sign()^true));
@@ -391,121 +546,141 @@ void VarReplacer::extendModelImpossible(Solver& solver2) const
     }
 }
 
+/**
+@brief Replaces two two vars in "ps" with one another. xorEqualFalse defines anti/equivalence
+
+It can be tricky to do this. For example, if:
+
+\li a replaces: b, c
+\li f replaces: f, h
+\li we just realised that c = h
+This is the most difficult case, but there are other cases, e.g. if we already
+know that c=h, in which case we don't do anything
+
+@p ps must contain 2 variables(!), i.e literals with no sign
+@p xorEqualFalse if True, the two variables are equivalent. Otherwise, they are antivalent
+@p group of clause they have been inspired from. Sometimes makes no sense...
+*/
 template<class T>
-const bool VarReplacer::replace(T& ps, const bool xor_clause_inverted, const uint group)
+const bool VarReplacer::replace(T& ps, const bool xorEqualFalse, const uint32_t group)
 {
     #ifdef VERBOSE_DEBUG
-    std::cout << "replace() called with var " << ps[0].var()+1 << " and var " << ps[1].var()+1 << " with xor_clause_inverted " << xor_clause_inverted << std::endl;
+    std::cout << "replace() called with var " << ps[0].var()+1 << " and var " << ps[1].var()+1 << " with xorEqualFalse " << xorEqualFalse << std::endl;
     #endif
-    
+
+    assert(solver.decisionLevel() == 0);
     assert(ps.size() == 2);
     assert(!ps[0].sign());
     assert(!ps[1].sign());
     #ifdef DEBUG_REPLACER
     assert(solver.assigns[ps[0].var()].isUndef());
     assert(solver.assigns[ps[1].var()].isUndef());
+
+    assert(!solver.subsumer->getVarElimed()[ps[0].var()]);
+    assert(!solver.xorSubsumer->getVarElimed()[ps[0].var()]);
+
+    assert(!solver.subsumer->getVarElimed()[ps[1].var()]);
+    assert(!solver.xorSubsumer->getVarElimed()[ps[1].var()]);
     #endif
-    
-    
-    Var var = ps[0].var();
-    Lit lit = Lit(ps[1].var(), !xor_clause_inverted);
-    assert(var != lit.var());
-    
+
     //Detect circle
-    if (alreadyIn(var, lit)) return solver.ok;
-    
-    Lit lit1 = table[var];
-    bool inverted = false;
-    
-    //This pointer is already set, try to invert
-    if (lit1.var() != var) {
-        Var tmp_var = var;
-        
-        var = lit.var();
-        lit = Lit(tmp_var, lit.sign());
-        inverted = true;
-    }
-    
-    if (inverted) {
-        Lit lit2 = table[var];
-        
-        //Inversion is also set, triangular cycle
-        //A->B, A->C, B->C. There is nothing to add
-        if (lit1.var() == lit2.var()) {
-            if ((lit1.sign() ^ lit2.sign()) != lit.sign()) {
-                #ifdef VERBOSE_DEBUG
-                cout << "Inverted cycle in var-replacement -> UNSAT" << endl;
-                #endif
-                return (solver.ok = false);
-            }
-            return true;
+    Lit lit1 = ps[0];
+    lit1 = table[lit1.var()];
+    Lit lit2 = ps[1];
+    lit2 = table[lit2.var()] ^ !xorEqualFalse;
+
+    //Already inside?
+    if (lit1.var() == lit2.var()) {
+        if (lit1.sign() != lit2.sign()) {
+            solver.ok = false;
+            return false;
         }
-        
-        //Inversion is also set
-        if (lit2.var() != var) {
-            assert(table[lit1.var()].var() == lit1.var());
-            setAllThatPointsHereTo(lit1.var(), Lit(lit.var(), lit1.sign()));
-            
-            assert(table[lit2.var()].var() == lit2.var());
-            setAllThatPointsHereTo(lit2.var(), lit ^ lit2.sign());
-            
-            table[lit.var()] = Lit(lit.var(), false);
-            replacedVars++;
-            addBinaryXorClause(ps, xor_clause_inverted, group);
-            return true;
+        return true;
+    }
+
+    #ifdef DEBUG_REPLACER
+    assert(!solver.subsumer->getVarElimed()[lit1.var()]);
+    assert(!solver.xorSubsumer->getVarElimed()[lit1.var()]);
+    assert(!solver.subsumer->getVarElimed()[lit2.var()]);
+    assert(!solver.xorSubsumer->getVarElimed()[lit2.var()]);
+    #endif
+
+    cannot_eliminate[lit1.var()] = true;
+    cannot_eliminate[lit2.var()] = true;
+    lbool val1 = solver.value(lit1);
+    lbool val2 = solver.value(lit2);
+    if (val1 != l_Undef && val2 != l_Undef) {
+        if (val1 != val2) {
+            solver.ok = false;
+            return false;
         }
+        return true;
+    }
+
+    if ((val1 != l_Undef && val2 == l_Undef) || (val2 != l_Undef && val1 == l_Undef)) {
+        //exactly one l_Undef, exectly one l_True/l_False
+        if (val1 != l_Undef) solver.uncheckedEnqueue(lit2 ^ (val1 == l_False));
+        else solver.uncheckedEnqueue(lit1 ^ (val2 == l_False));
+
+        if (solver.ok) solver.ok = (solver.propagate().isNULL());
+        return solver.ok;
+    }
+
+    #ifdef DEBUG_REPLACER
+    assert(val1 == l_Undef && val2 == l_Undef);
+    #endif //DEBUG_REPLACER
+
+    addBinaryXorClause(lit1, lit2 ^ true, group, false);
+
+    if (reverseTable.find(lit1.var()) == reverseTable.end()) {
+        reverseTable[lit2.var()].push_back(lit1.var());
+        table[lit1.var()] = lit2 ^ lit1.sign();
+        replacedVars++;
+        return true;
+    }
+
+    if (reverseTable.find(lit2.var()) == reverseTable.end()) {
+        reverseTable[lit1.var()].push_back(lit2.var());
+        table[lit2.var()] = lit1 ^ lit2.sign();
+        replacedVars++;
+        return true;
     }
-    
-    //Follow forwards
-    Lit litX = table[lit.var()];
-    if (litX.var() != lit.var())
-        lit = litX ^ lit.sign();
-    
-    //Follow backwards
-    setAllThatPointsHereTo(var, lit);
+
+    //both have children
+    setAllThatPointsHereTo(lit1.var(), lit2 ^ lit1.sign()); //erases reverseTable[lit1.var()]
     replacedVars++;
-    addBinaryXorClause(ps, xor_clause_inverted, group);
-    
     return true;
 }
 
-template const bool VarReplacer::replace(vec<Lit>& ps, const bool xor_clause_inverted, const uint group);
-template const bool VarReplacer::replace(XorClause& ps, const bool xor_clause_inverted, const uint group);
+template const bool VarReplacer::replace(vec<Lit>& ps, const bool xorEqualFalse, const uint32_t group);
+template const bool VarReplacer::replace(XorClause& ps, const bool xorEqualFalse, const uint32_t group);
 
-template<class T>
-void VarReplacer::addBinaryXorClause(T& ps, const bool xor_clause_inverted, const uint group, const bool internal)
+/**
+@brief Adds a binary xor to the internal/external clause set
+
+It is added externally ONLY if we are in the middle of replacing clauses,
+and a new binary xor just came up. That is a very strange and unfortunate
+experience, as we cannot change the datastructures in the middle of replacement
+so we add this to the binary clauses of Solver, and we recover it next time.
+
+\todo Clean this messy internal/external thing using a better datastructure.
+*/
+void VarReplacer::addBinaryXorClause(Lit lit1, Lit lit2, const uint32_t group, const bool addBinAsLearnt)
 {
-    assert(internal || (replacedVars > lastReplacedVars));
-    #ifdef DEBUG_REPLACER
-    assert(!ps[0].sign());
-    assert(!ps[1].sign());
-    #endif
-    
-    Clause* c;
-    ps[0] ^= xor_clause_inverted;
-    
-    c = solver.clauseAllocator.Clause_new(ps, group, false);
-    if (internal) {
-        solver.binaryClauses.push(c);
-        solver.becameBinary++;
-    } else
-        clauses.push(c);
-    solver.attachClause(*c);
-    
-    ps[0] ^= true;
-    ps[1] ^= true;
-    c = solver.clauseAllocator.Clause_new(ps, group, false);
-    if (internal) {
-        solver.binaryClauses.push(c);
-        solver.becameBinary++;
-    } else
-        clauses.push(c);
-    solver.attachClause(*c);
+    solver.attachBinClause(lit1, lit2, addBinAsLearnt);
+    solver.dataSync->signalNewBinClause(lit1, lit2);
+
+    lit1 ^= true;
+    lit2 ^= true;
+    solver.attachBinClause(lit1, lit2, addBinAsLearnt);
+    solver.dataSync->signalNewBinClause(lit1, lit2);
 }
 
-template void VarReplacer::addBinaryXorClause(vec<Lit>& ps, const bool xor_clause_inverted, const uint group, const bool internal);
-template void VarReplacer::addBinaryXorClause(XorClause& ps, const bool xor_clause_inverted, const uint group, const bool internal);
+/**
+@brief Returns if we already know that var = lit
 
+Also checks if var = ~lit, in which it sets solver.ok = false
+*/
 bool VarReplacer::alreadyIn(const Var var, const Lit lit)
 {
     Lit lit2 = table[var];
@@ -518,7 +693,7 @@ bool VarReplacer::alreadyIn(const Var var, const Lit lit)
         }
         return true;
     }
-    
+
     lit2 = table[lit.var()];
     if (lit2.var() == var) {
         if (lit2.sign() != lit.sign()) {
@@ -529,10 +704,13 @@ bool VarReplacer::alreadyIn(const Var var, const Lit lit)
         }
         return true;
     }
-    
+
     return false;
 }
 
+/**
+@brief Changes internal graph to set everything that pointed to var to point to lit
+*/
 void VarReplacer::setAllThatPointsHereTo(const Var var, const Lit lit)
 {
     map<Var, vector<Var> >::iterator it = reverseTable.find(var);
@@ -553,20 +731,5 @@ void VarReplacer::setAllThatPointsHereTo(const Var var, const Lit lit)
 void VarReplacer::newVar()
 {
     table.push_back(Lit(table.size(), false));
+    cannot_eliminate.push(false);
 }
-
-void VarReplacer::reattachInternalClauses()
-{
-    Clause **i = clauses.getData();
-    Clause **j = i;
-    for (Clause **end = clauses.getDataEnd(); i != end; i++) {
-        if (solver.value((**i)[0]) == l_Undef &&
-            solver.value((**i)[1]) == l_Undef) {
-            solver.attachClause(**i);
-            *j++ = *i;
-        }
-    }
-    clauses.shrink(i-j);
-}
-
-}; //NAMESPACE MINISAT
index 4d54d9d86079400b6a2a4a5f82abd4de51d7f75a..eebee7679b41e5bc38338a935c69dbdba5862486 100644 (file)
@@ -34,10 +34,9 @@ using std::vector;
 #include "Clause.h"
 #include "Vec.h"
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
+/**
+@brief Replaces variables with their anti/equivalents
+*/
 class VarReplacer
 {
     public:
@@ -46,49 +45,48 @@ class VarReplacer
         const bool performReplace(const bool always = false);
         const bool needsReplace();
         template<class T>
-        const bool replace(T& ps, const bool xor_clause_inverted, const uint group);
-        
+        const bool replace(T& ps, const bool xorEqualFalse, const uint32_t group);
+
         void extendModelPossible() const;
         void extendModelImpossible(Solver& solver2) const;
-        void reattachInternalClauses();
-        
-        const uint getNumReplacedLits() const;
-        const uint getNumReplacedVars() const;
-        const uint getNumLastReplacedVars() const;
-        const uint getNewToReplaceVars() const;
+
+        const uint32_t getNumReplacedLits() const;
+        const uint32_t getNumReplacedVars() const;
+        const uint32_t getNumLastReplacedVars() const;
+        const uint32_t getNewToReplaceVars() const;
         const uint32_t getNumTrees() const;
         const vector<Var> getReplacingVars() const;
         const vector<Lit>& getReplaceTable() const;
-        const vec<Clause*>& getClauses() const;
         const bool varHasBeenReplaced(const Var var) const;
         const bool replacingVar(const Var var) const;
         void newVar();
 
+        vec<char> cannot_eliminate;
+
         //No need to update, only stores binary clauses, that
         //have been allocated within pool
         //friend class ClauseAllocator;
-    
+
     private:
         const bool performReplaceInternal();
-        
-        const bool replace_set(vec<Clause*>& cs, const bool binClauses);
+
+        const bool replace_set(vec<Clause*>& cs);
+        const bool replaceBins();
         const bool replace_set(vec<XorClause*>& cs);
-        const bool handleUpdatedClause(Clause& c, const Lit origLit1, const Lit origLit2);
+        const bool handleUpdatedClause(Clause& c, const Lit origLit1, const Lit origLit2, const Lit origLit3);
         const bool handleUpdatedClause(XorClause& c, const Var origVar1, const Var origVar2);
-        template<class T>
-        void addBinaryXorClause(T& ps, const bool xor_clause_inverted, const uint group, const bool internal = false);
-        
+        void addBinaryXorClause(Lit lit1, Lit lit2, const uint32_t group, const bool addBinAsLearnt = false);
+
         void setAllThatPointsHereTo(const Var var, const Lit lit);
         bool alreadyIn(const Var var, const Lit lit);
-        
-        vector<Lit> table;
-        map<Var, vector<Var> > reverseTable;
-        vec<Clause*> clauses;
-        
-        uint replacedLits;
-        uint replacedVars;
-        uint lastReplacedVars;
-        Solver& solver;
+
+        vector<Lit> table; ///<Stores which variables have been replaced by which literals. Index by: table[VAR]
+        map<Var, vector<Var> > reverseTable; ///<mapping of variable to set of variables it replaces
+
+        uint32_t replacedLits; ///<Num literals replaced during var-replacement
+        uint32_t replacedVars; ///<Num vars replaced during var-replacement
+        uint32_t lastReplacedVars; ///<Last time performReplace() was called, "replacedVars" contained this
+        Solver& solver; ///<The solver we are working with
 };
 
 inline const bool VarReplacer::performReplace(const bool always)
@@ -97,7 +95,7 @@ inline const bool VarReplacer::performReplace(const bool always)
     uint32_t limit = (uint32_t)((double)solver.order_heap.size()*PERCENTAGEPERFORMREPLACE);
     if ((always && getNewToReplaceVars() > 0) || getNewToReplaceVars() > limit)
         return performReplaceInternal();
-    
+
     return true;
 }
 
@@ -107,22 +105,22 @@ inline const bool VarReplacer::needsReplace()
     return (getNewToReplaceVars() > limit);
 }
 
-inline const uint VarReplacer::getNumReplacedLits() const
+inline const uint32_t VarReplacer::getNumReplacedLits() const
 {
     return replacedLits;
 }
 
-inline const uint VarReplacer::getNumReplacedVars() const
+inline const uint32_t VarReplacer::getNumReplacedVars() const
 {
     return replacedVars;
 }
 
-inline const uint VarReplacer::getNumLastReplacedVars() const
+inline const uint32_t VarReplacer::getNumLastReplacedVars() const
 {
     return lastReplacedVars;
 }
 
-inline const uint VarReplacer::getNewToReplaceVars() const
+inline const uint32_t VarReplacer::getNewToReplaceVars() const
 {
     return replacedVars-lastReplacedVars;
 }
@@ -132,11 +130,6 @@ inline const vector<Lit>& VarReplacer::getReplaceTable() const
     return table;
 }
 
-inline const vec<Clause*>& VarReplacer::getClauses() const
-{
-    return clauses;
-}
-
 inline const bool VarReplacer::varHasBeenReplaced(const Var var) const
 {
     return table[var].var() != var;
@@ -152,6 +145,4 @@ inline const uint32_t VarReplacer::getNumTrees() const
     return reverseTable.size();
 }
 
-}; //NAMESPACE MINISAT
-
 #endif //VARREPLACER_H
diff --git a/src/sat/cryptominisat2/Watched.h b/src/sat/cryptominisat2/Watched.h
new file mode 100644 (file)
index 0000000..cd150f8
--- /dev/null
@@ -0,0 +1,264 @@
+/***************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#ifndef WATCHED_H
+#define WATCHED_H
+
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+//#define DEBUG_WATCHED
+
+#include "ClauseOffset.h"
+#include "SolverTypes.h"
+#include <stdio.h>
+#include "constants.h"
+
+/**
+@brief An element in the watchlist. Natively contains 2- and 3-long clauses, others are referenced by pointer
+
+This class contains two 32-bit datapieces. They are either used as:
+\li One literal, in the case of binary clauses
+\li Two literals, in the case of tertiary clauses
+\li One blocking literal (i.e. an example literal from the clause) and a clause
+offset (as per ClauseAllocator ), in the case of normal clauses
+\li A clause offset (as per ClauseAllocator) for xor clauses
+*/
+class Watched {
+    public:
+        /**
+        @brief Constructor for a long normal clause
+        */
+        Watched(const ClauseOffset offset, Lit blockedLit)
+        {
+            data1 = blockedLit.toInt();
+            data2 = (uint32_t)1 + ((uint32_t)offset << 2);
+        }
+
+        /**
+        @brief Constructor for an xor-clause
+        */
+        Watched(const ClauseOffset offset)
+        {
+            data1 = (uint32_t)offset;
+            data2 = (uint32_t)2;
+        }
+
+        /**
+        @brief Constructor for a binary clause
+        */
+        Watched(const Lit lit, const bool learnt)
+        {
+            data1 = lit.toInt();
+            data2 = (uint32_t)0 + (((uint32_t)learnt) << 2);
+        }
+
+        /**
+        @brief Constructor for a 3-long, non-xor clause
+        */
+        Watched(const Lit lit1, const Lit lit2)
+        {
+            data1 = lit1.toInt();
+            data2 = (uint32_t)3 + (lit2.toInt()<< 2);
+        }
+
+        void setNormOffset(const ClauseOffset offset)
+        {
+            #ifdef DEBUG_WATCHED
+            assert(isClause());
+            #endif
+            data2 = (uint32_t)1 + ((uint32_t)offset << 2);
+        }
+
+        void setXorOffset(const ClauseOffset offset)
+        {
+            #ifdef DEBUG_WATCHED
+            assert(isXorClause());
+            #endif
+            data1 = (uint32_t)offset;
+        }
+
+        /**
+        @brief To update the example literal (blocked literal) of a >3-long normal clause
+        */
+        void setBlockedLit(const Lit lit)
+        {
+            #ifdef DEBUG_WATCHED
+            assert(isClause());
+            #endif
+            data1 = lit.toInt();
+        }
+
+        const bool isBinary() const
+        {
+            return ((data2&3) == 0);
+        }
+
+        const bool isNonLearntBinary() const
+        {
+            return (data2 == 0);
+        }
+
+        const bool isClause() const
+        {
+            return ((data2&3) == 1);
+        }
+
+        const bool isXorClause() const
+        {
+            return ((data2&3) == 2);
+        }
+
+        const bool isTriClause() const
+        {
+            return ((data2&3) == 3);
+        }
+
+        /**
+        @brief Get the sole other lit of the binary clause, or get lit2 of the tertiary clause
+        */
+        const Lit getOtherLit() const
+        {
+            #ifdef DEBUG_WATCHED
+            assert(isBinary() || isTriClause());
+            #endif
+            return data1AsLit();
+        }
+
+        /**
+        @brief Set the sole other lit of the binary clause
+        */
+        void setOtherLit(const Lit lit)
+        {
+            #ifdef DEBUG_WATCHED
+            assert(isBinary() || isTriClause());
+            #endif
+            data1 = lit.toInt();
+        }
+
+        const bool getLearnt() const
+        {
+            #ifdef DEBUG_WATCHED
+            assert(isBinary());
+            #endif
+            return (bool)(data2 >> 2);
+        }
+
+        void setLearnt(const bool learnt)
+        {
+            #ifdef DEBUG_WATCHED
+            assert(isBinary());
+            assert(learnt == false);
+            #endif
+            data2 = (uint32_t)0 + (((uint32_t)learnt) << 2);
+        }
+
+        /**
+        @brief Get the 3rd literal of a 3-long clause
+        */
+        const Lit getOtherLit2() const
+        {
+            #ifdef DEBUG_WATCHED
+            assert(isTriClause());
+            #endif
+            return data2AsLit();
+        }
+
+        /**
+        @brief Get example literal (blocked lit) of a normal >3-long clause
+        */
+        const Lit getBlockedLit() const
+        {
+            #ifdef DEBUG_WATCHED
+            assert(isClause());
+            #endif
+            return data1AsLit();
+        }
+
+        /**
+        @brief Get offset of a >3-long normal clause or of an xor clause (which may be 3-long)
+        */
+        const ClauseOffset getNormOffset() const
+        {
+            #ifdef DEBUG_WATCHED
+            assert(isClause());
+            #endif
+            return (ClauseOffset)(data2 >> 2);
+        }
+
+        const ClauseOffset getXorOffset() const
+        {
+            #ifdef DEBUG_WATCHED
+            assert(isXorClause());
+            #endif
+            return (ClauseOffset)(data1);
+        }
+
+        void dump(FILE* outfile, const Lit lit) const
+        {
+            assert(isBinary());
+            lit.print(outfile);
+            getOtherLit().printFull(outfile);
+        }
+
+        void setNormClause()
+        {
+            data2 = 1;
+        }
+
+    private:
+        const Lit data1AsLit() const
+        {
+            return (Lit::toLit(data1));
+        }
+
+        const Lit data2AsLit() const
+        {
+            return (Lit::toLit(data2>>2));
+        }
+
+        uint32_t data1;
+        uint32_t data2;
+};
+
+/**
+@brief Orders the watchlists such that the order is binary, tertiary, normal, xor
+*/
+struct WatchedSorter
+{
+    bool operator () (const Watched& x, const Watched& y);
+};
+
+inline bool  WatchedSorter::operator () (const Watched& x, const Watched& y)
+{
+    if (y.isBinary()) return false;
+    //y is not binary, but x is, so x must be first
+    if (x.isBinary()) return true;
+
+    //from now on, none is binary.
+    if (y.isTriClause()) return false;
+    if (x.isTriClause()) return true;
+
+    //from now on, none is binary or tertiary
+    //don't bother sorting these
+    return false;
+}
+
+#endif //WATCHED_H
index 13fb3154f25f4e4b1a748a603615a2f9766bff1f..b898aa4b0e31fd0b338243be90bcdb7398edeb1f 100644 (file)
@@ -13,10 +13,6 @@ From: Solver.C -- (C) Niklas Een, Niklas Sorensson, 2004
 #include <stdint.h>
 #endif //_MSC_VER
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 class XorClause;
 
 template <class T>
@@ -131,6 +127,5 @@ class XSet {
         }
 };
 
-}; //NAMESPACE MINISAT
-
 #endif //XSET_H
+
index 13c1e6537843c339e0220eec27e6f87d52cb0273..e7983d4148ecda7d097f82b35932c75560f45c28 100644 (file)
@@ -36,129 +36,70 @@ using std::cout;
 using std::endl;
 #endif
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 using std::make_pair;
 
-XorFinder::XorFinder(Solver& _solver, vec<Clause*>& _cls, ClauseCleaner::ClauseSetType _type) :
+XorFinder::XorFinder(Solver& _solver, vec<Clause*>& _cls) :
     cls(_cls)
-    , type(_type)
     , solver(_solver)
 {
 }
 
-const bool XorFinder::doNoPart(const uint minSize, const uint maxSize)
+const bool XorFinder::fullFindXors(const uint32_t minSize, const uint32_t maxSize)
 {
-    uint sumLengths = 0;
+    uint32_t sumLengths = 0;
     double time = cpuTime();
     foundXors = 0;
     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);
     toLeaveInPlace.clear();
     toLeaveInPlace.resize(cls.size(), false);
-    
+
     table.clear();
     table.reserve(cls.size());
-    
-    ClauseTable unsortedTable;
-    unsortedTable.reserve(cls.size());
-    ClauseTable sortedTable;
-    sortedTable.reserve(cls.size());
-    
-    for (Clause **it = cls.getData(), **end = it + cls.size(); it != end; it ++) {
-        if (it+1 != end)
-            __builtin_prefetch(*(it+1), 0);
-        //if ((**it)[0].toInt() < (**it)[1].toInt())
-        //    std::swap((**it)[0], (**it)[1]);
+
+    for (Clause **it = cls.getData(), **end = cls.getDataEnd(); it != end; it ++) {
+        if (it+1 != end) __builtin_prefetch(*(it+1), 0);
         Clause& c = (**it);
-        if ((*it)->size() != 2) {
-            bool sorted = true;
-            for (uint i = 0, size = c.size(); i+1 < size ; i++) {
-                sorted = (c[i].var() <= c[i+1].var());
-                if (!sorted) break;
-            }
-            if (!sorted) {
-                solver.detachClause(c);
-                std::sort(c.getData(), c.getDataEnd());
-                solver.attachClause(c);
-            }
-        } else {
-            std::sort(c.getData(), c.getData()+c.size());
+        assert((*it)->size() > 2);
+        bool sorted = true;
+        for (uint32_t i = 0, size = c.size(); i+1 < size ; i++) {
+            sorted = (c[i].var() <= c[i+1].var());
+            if (!sorted) break;
+        }
+        if (!sorted) {
+            solver.detachClause(c);
+            std::sort(c.getData(), c.getDataEnd());
+            solver.attachClause(c);
         }
     }
-    
-    uint i = 0;
-    for (Clause **it = cls.getData(), **end = it + cls.size(); it != end; it++, i++) {
-        const uint size = (*it)->size();
+
+    uint32_t i = 0;
+    for (Clause **it = cls.getData(), **end = cls.getDataEnd(); it != end; it++, i++) {
+        const uint32_t size = (*it)->size();
         if ( size > maxSize || size < minSize) {
             toLeaveInPlace[i] = true;
             continue;
         }
-        if ((*it)->getSorted()) sortedTable.push_back(make_pair(*it, i));
-        else unsortedTable.push_back(make_pair(*it, i));
-    }
-    
-    clause_sorter_primary sorter;
-    
-    std::sort(unsortedTable.begin(), unsortedTable.end(), clause_sorter_primary());
-    //std::sort(sortedTable.begin(), sortedTable.end(), clause_sorter_primary());
-    #ifdef DEBUG_XORFIND
-    for (uint i = 0; i+1 < unsortedTable.size(); i++) {
-        assert(!sorter(unsortedTable[i+1], unsortedTable[i]));
-    }
-    for (uint i = 0; i+1 < sortedTable.size(); i++) {
-        assert(!sorter(sortedTable[i+1], sortedTable[i]));
-    }
-    #endif //DEBUG_XORFIND
-    
-    for (uint i = 0, j = 0; i < unsortedTable.size() || j <  sortedTable.size();) {
-        if (j == sortedTable.size()) {
-            table.push_back(unsortedTable[i++]);
-            continue;
-        }
-        if (i == unsortedTable.size()) {
-            table.push_back(sortedTable[j++]);
-            continue;
-        }
-        if (sorter(unsortedTable[i], sortedTable[j])) {
-            table.push_back(unsortedTable[i++]);
-        } else {
-            table.push_back(sortedTable[j++]);
-        }
-    }
-    #ifdef DEBUG_XORFIND
-    for (uint i = 0; i+1 < table.size(); i++) {
-        assert(!sorter(table[i+1], table[i]));
-        //table[i].first->plainPrint();
+        table.push_back(make_pair(*it, i));
     }
-    #endif //DEBUG_XORFIND
-    
-    if (findXors(sumLengths) == false) goto end;
+    std::sort(table.begin(), table.end(), clause_sorter_primary());
+
+    if (!findXors(sumLengths)) goto end;
     solver.ok = (solver.propagate().isNULL());
-    
+
 end:
-    if (minSize == maxSize && minSize == 2) {
-        if (solver.verbosity >= 2 || (solver.conflicts == 0 && solver.verbosity >= 1)) {
-            printf("c |  Finding binary XORs:        %5.2lf s (found: %7d, avg size: %3.1lf)                  |\n", cpuTime()-time, foundXors, (double)sumLengths/(double)foundXors);
-        }
-    } else {
-        if (solver.verbosity >= 2 || (solver.verbosity >= 1 && foundXors > 0)) {
-            printf("c |  Finding non-binary XORs:    %5.2lf s (found: %7d, avg size: %3.1lf)                  |\n", cpuTime()-time, foundXors, (double)sumLengths/(double)foundXors);
-        }
+
+    if (solver.conf.verbosity >= 1 || (solver.conf.verbosity >= 1 && foundXors > 0)) {
+        printf("c Finding non-binary XORs:    %5.2lf s (found: %7d, avg size: %3.1lf)\n", cpuTime()-time, foundXors, (double)sumLengths/(double)foundXors);
     }
-    
+
     i = 0;
     uint32_t j = 0;
     uint32_t toSkip = 0;
-    for (uint end = cls.size(); i != end; i++) {
+    for (uint32_t end = cls.size(); i != end; i++) {
         if (toLeaveInPlace[i]) {
             cls[j] = cls[i];
             j++;
@@ -166,24 +107,30 @@ end:
             continue;
         }
         if (!toRemove[table[i-toSkip].second]) {
-            table[i-toSkip].first->setSorted();
             cls[j] = table[i-toSkip].first;
             j++;
         }
     }
     cls.shrink(i-j);
-    
+
     return solver.ok;
 }
 
-const bool XorFinder::findXors(uint& sumLengths)
+
+/**
+@brief Finds xors in clauseTable -- datastructures must already be set up
+
+Identifies sets of clauses of the same length and variable content, and then
+tries to merge them into an XOR.
+*/
+const bool XorFinder::findXors(uint32_t& sumLengths)
 {
     #ifdef VERBOSE_DEBUG
     cout << "Finding Xors started" << endl;
     #endif
-    
+
     sumLengths = 0;
-    
+
     ClauseTable::iterator begin = table.begin();
     ClauseTable::iterator end = table.begin();
     vec<Lit> lits;
@@ -194,68 +141,46 @@ const bool XorFinder::findXors(uint& sumLengths)
         for (const Lit *it = &c[0], *cend = it+c.size() ; it != cend; it++) {
             lits.push(Lit(it->var(), false));
         }
-        uint old_group = c.getGroup();
-        
+        uint32_t old_group = c.getGroup();
+
         #ifdef VERBOSE_DEBUG
         cout << "- Found clauses:" << endl;
         #endif
-        
-        for (ClauseTable::iterator it = begin; it != end; it++)
+
+        for (ClauseTable::iterator it = begin; it != end; it++) {
+            //This clause belongs to the xor we found?
+            //(i.e. does it have the correct number of inverted literals?)
             if (impairSigns(*it->first) == impair){
-            #ifdef VERBOSE_DEBUG
-            it->first->plainPrint();
-            #endif
-            toRemove[it->second] = true;
-            solver.removeClause(*it->first);
-        }
-        
-        switch(lits.size()) {
-        case 2: {
-            solver.varReplacer->replace(lits, impair, old_group);
-            
-            #ifdef VERBOSE_DEBUG
-            XorClause* x = XorClause_new(lits, impair, old_group);
-            cout << "- Final 2-long xor-clause: ";
-            x->plainPrint();
-            clauseFree(x);
-            #endif
-            break;
-        }
-        default: {
-            XorClause* x = solver.clauseAllocator.XorClause_new(lits, impair, old_group);
-            solver.xorclauses.push(x);
-            solver.attachClause(*x);
-            
-            #ifdef VERBOSE_DEBUG
-            cout << "- Final xor-clause: ";
-            x->plainPrint();
-            #endif
-        }
+                #ifdef VERBOSE_DEBUG
+                it->first->plainPrint();
+                #endif
+                toRemove[it->second] = true;
+                solver.removeClause(*it->first);
+            }
         }
-        
+
+        assert(lits.size() > 2);
+        XorClause* x = solver.addXorClauseInt(lits, impair, old_group);
+        if (x != NULL) solver.xorclauses.push(x);
+        if (!solver.ok) return false;
+
+        #ifdef VERBOSE_DEBUG
+        cout << "- Final xor-clause: " << x << std::endl;;
+        #endif
+
         foundXors++;
         sumLengths += lits.size();
     }
-    
+
     return solver.ok;
 }
 
-void XorFinder::clearToRemove()
-{
-    assert(toRemove.size() == cls.size());
-    
-    Clause **a = cls.getData();
-    Clause **r = cls.getData();
-    Clause **cend = cls.getData() + cls.size();
-    for (uint i = 0; r != cend; i++) {
-        if (!toRemove[i])
-            *a++ = *r++;
-        else
-            r++;
-    }
-    cls.shrink(r-a);
-}
+/**
+@brief Moves to the next set of begin&end pointers that contain an xor
 
+@p begin[inout] start searching here in XorFinder::table
+@p end[inout] end iterator of XorFinder::table until which the xor spans
+*/
 bool XorFinder::getNextXor(ClauseTable::iterator& begin, ClauseTable::iterator& end, bool& impair)
 {
     ClauseTable::iterator tableEnd = table.end();
@@ -271,48 +196,66 @@ bool XorFinder::getNextXor(ClauseTable::iterator& begin, ClauseTable::iterator&
         if (size > 0 && isXor(size, begin, end, impair))
             return true;
     }
-    
+
     return false;
 }
 
+/**
+@brief Returns if the two clauses are equal
+
+NOTE: assumes that the clauses are of equal lenght AND contain the same
+variables (but the invertedness of the literals might differ)
+*/
 bool XorFinder::clauseEqual(const Clause& c1, const Clause& c2) const
 {
     assert(c1.size() == c2.size());
-    for (uint i = 0, size = c1.size(); i < size; i++)
+    for (uint32_t i = 0, size = c1.size(); i < size; i++)
         if (c1[i].sign() !=  c2[i].sign()) return false;
-    
+
     return true;
 }
 
+/**
+@brief Returns whether the number of inverted literals in the clause is pair or impair
+*/
 bool XorFinder::impairSigns(const Clause& c) const
 {
-    uint num = 0;
+    uint32_t num = 0;
     for (const Lit *it = &c[0], *end = it + c.size(); it != end; it++)
         num += it->sign();
-        
+
     return num % 2;
 }
 
+/**
+@brief Gets as input a set of clauses of equal size and variable content, decides if there is an XOR in them
+
+@param impair If there is an XOR, this tells if that XOR contains an impair
+number of inverted literal or not
+@return True, if ther is an XOR, and False if not
+*/
 bool XorFinder::isXor(const uint32_t size, const ClauseTable::iterator& begin, const ClauseTable::iterator& end, bool& impair)
 {
-    const uint requiredSize = 1 << (begin->first->size()-1);
-    
-    if (size < requiredSize)
-        return false;
-    
+    const uint32_t requiredSize = 1 << (begin->first->size()-1);
+
+    //Note: "size" can be larger than requiredSize, since there might be
+    //a mix of imparied and paired num. inverted literals, and furthermore,
+    //clauses might be repeated
+    if (size < requiredSize) return false;
+
     #ifdef DEBUG_XORFIND2
     {
         vec<Var> vars;
         Clause& c = *begin->first;
-        for (uint i = 0; i < c.size(); i++)
+        for (uint32_t i = 0; i < c.size(); i++)
             vars.push(c[i].var());
         for (ClauseTable::iterator it = begin; it != end; it++) {
             Clause& c = *it->first;
-            for (uint i = 0; i < c.size(); i++)
+            for (uint32_t i = 0; i < c.size(); i++)
                 assert(vars[i] == c[i].var());
         }
         clause_sorter_primary sorter;
-        
+
         for (ClauseTable::iterator it = begin; it != end; it++) {
             ClauseTable::iterator it2 = it;
             it2++;
@@ -321,41 +264,51 @@ bool XorFinder::isXor(const uint32_t size, const ClauseTable::iterator& begin, c
         }
     }
     #endif //DEBUG_XORFIND
-    
+
+    //We now sort them according to literal content
     std::sort(begin, end, clause_sorter_secondary());
-    
-    uint numPair = 0;
-    uint numImpair = 0;
+
+    uint32_t numPair = 0;
+    uint32_t numImpair = 0;
     countImpairs(begin, end, numImpair, numPair);
-    
+
+    //if there are two XORs with equal variable sets, but different invertedness
+    //that leads to direct UNSAT result.
+    if (numImpair == requiredSize && numPair == requiredSize) {
+        solver.ok = false;
+        impair = true;
+        return true;
+    }
+
     if (numImpair == requiredSize) {
         impair = true;
-        
         return true;
     }
-    
+
     if (numPair == requiredSize) {
         impair = false;
-        
         return true;
     }
-    
+
     return false;
 }
 
-void XorFinder::countImpairs(const ClauseTable::iterator& begin, const ClauseTable::iterator& end, uint& numImpair, uint& numPair) const
+/**
+@brief Counts number of negations in the literals in clauses between begin&end, and returns the number of clauses with pair, and impair literals
+*/
+void XorFinder::countImpairs(const ClauseTable::iterator& begin, const ClauseTable::iterator& end, uint32_t& numImpair, uint32_t& numPair) const
 {
     numImpair = 0;
     numPair = 0;
-    
+
     ClauseTable::const_iterator it = begin;
     ClauseTable::const_iterator it2 = begin;
     it2++;
-    
+
     bool impair = impairSigns(*it->first);
     numImpair += impair;
     numPair += !impair;
-    
+
     for (; it2 != end;) {
         if (!clauseEqual(*it->first, *it2->first)) {
             bool impair = impairSigns(*it2->first);
@@ -367,6 +320,16 @@ void XorFinder::countImpairs(const ClauseTable::iterator& begin, const ClauseTab
     }
 }
 
+/**
+@brief Converts all xor clauses to normal clauses
+
+Sometimes it's not worth the hassle of having xor clauses and normal clauses.
+This function converts xor clauses to normal clauses, and removes the normal
+clauses.
+
+\todo It currently only works for 3- and 4-long clauses. Larger clauses should
+also be handled.
+*/
 void XorFinder::addAllXorAsNorm()
 {
     uint32_t added = 0;
@@ -382,41 +345,46 @@ void XorFinder::addAllXorAsNorm()
         solver.removeClause(**i);
     }
     solver.xorclauses.shrink(i-j);
-    if (solver.verbosity >= 1) {
-        std::cout << "c |  Added XOR as norm:" << added << std::endl;
+    if (solver.conf.verbosity >= 1) {
+        std::cout << "c Added XOR as norm:" << added << std::endl;
     }
 }
 
+/**
+@brief Utility function for addAllXorAsNorm() for converting 3-long xor clauses to normal clauses
+
+\todo clean this up, it's ugly
+*/
 void XorFinder::addXorAsNormal3(XorClause& c)
 {
     assert(c.size() == 3);
     Clause *tmp;
     vec<Var> vars;
     vec<Lit> vars2(c.size());
-    const bool inverted = c.xor_clause_inverted();
-    
+    const bool inverted = c.xorEqualFalse();
+
     for (uint32_t i = 0; i < c.size(); i++) {
         vars.push(c[i].var());
     }
-    
+
     vars2[0] = Lit(vars[0], false ^ inverted);
     vars2[1] = Lit(vars[1], false ^ inverted);
     vars2[2] = Lit(vars[2], false ^ inverted);
     tmp = solver.addClauseInt(vars2, c.getGroup());
     if (tmp) solver.clauses.push(tmp);
-    
+
     vars2[0] = Lit(vars[0], true ^ inverted);
     vars2[1] = Lit(vars[1], true ^ inverted);
     vars2[2] = Lit(vars[2], false ^ inverted);
     tmp = solver.addClauseInt(vars2, c.getGroup());
     if (tmp) solver.clauses.push(tmp);
-    
+
     vars2[0] = Lit(vars[0], true ^ inverted);
     vars2[1] = Lit(vars[1], false ^ inverted);
     vars2[2] = Lit(vars[2], true ^ inverted);
     tmp = solver.addClauseInt(vars2, c.getGroup());
     if (tmp) solver.clauses.push(tmp);
-    
+
     vars2[0] = Lit(vars[0], false ^ inverted);
     vars2[1] = Lit(vars[1], true ^ inverted);
     vars2[2] = Lit(vars[2], true ^ inverted);
@@ -424,67 +392,72 @@ void XorFinder::addXorAsNormal3(XorClause& c)
     if (tmp) solver.clauses.push(tmp);
 }
 
+/**
+@brief Utility function for addAllXorAsNorm() for converting 4-long xor clauses to normal clauses
+
+\todo clean this up, it's ugly
+*/
 void XorFinder::addXorAsNormal4(XorClause& c)
 {
     assert(c.size() == 4);
     Clause *tmp;
     vec<Var> vars;
     vec<Lit> vars2(c.size());
-    const bool inverted = !c.xor_clause_inverted();
-    
+    const bool inverted = !c.xorEqualFalse();
+
     for (uint32_t i = 0; i < c.size(); i++) {
         vars.push(c[i].var());
     }
-    
+
     vars2[0] = Lit(vars[0], false ^ inverted);
     vars2[1] = Lit(vars[1], false ^ inverted);
     vars2[2] = Lit(vars[2], false ^ inverted);
     vars2[3] = Lit(vars[3], true ^ inverted);
     tmp = solver.addClauseInt(vars2, c.getGroup());
     if (tmp) solver.clauses.push(tmp);
-    
+
     vars2[0] = Lit(vars[0], false ^ inverted);
     vars2[1] = Lit(vars[1], true ^ inverted);
     vars2[2] = Lit(vars[2], false ^ inverted);
     vars2[3] = Lit(vars[3], false ^ inverted);
     tmp = solver.addClauseInt(vars2, c.getGroup());
     if (tmp) solver.clauses.push(tmp);
-    
+
     vars2[0] = Lit(vars[0], false ^ inverted);
     vars2[1] = Lit(vars[1], false ^ inverted);
     vars2[2] = Lit(vars[2], true ^ inverted);
     vars2[3] = Lit(vars[3], false ^ inverted);
     tmp = solver.addClauseInt(vars2, c.getGroup());
     if (tmp) solver.clauses.push(tmp);
-    
+
     vars2[0] = Lit(vars[0], false ^ inverted);
     vars2[1] = Lit(vars[1], false ^ inverted);
     vars2[2] = Lit(vars[2], false ^ inverted);
     vars2[3] = Lit(vars[3], true ^ inverted);
     tmp = solver.addClauseInt(vars2, c.getGroup());
     if (tmp) solver.clauses.push(tmp);
-    
+
     vars2[0] = Lit(vars[0], false ^ inverted);
     vars2[1] = Lit(vars[1], true ^ inverted);
     vars2[2] = Lit(vars[2], true ^ inverted);
     vars2[3] = Lit(vars[3], true ^ inverted);
     tmp = solver.addClauseInt(vars2, c.getGroup());
     if (tmp) solver.clauses.push(tmp);
-    
+
     vars2[0] = Lit(vars[0], true ^ inverted);
     vars2[1] = Lit(vars[1], false ^ inverted);
     vars2[2] = Lit(vars[2], true ^ inverted);
     vars2[3] = Lit(vars[3], true ^ inverted);
     tmp = solver.addClauseInt(vars2, c.getGroup());
     if (tmp) solver.clauses.push(tmp);
-    
+
     vars2[0] = Lit(vars[0], true ^ inverted);
     vars2[1] = Lit(vars[1], true ^ inverted);
     vars2[2] = Lit(vars[2], false ^ inverted);
     vars2[3] = Lit(vars[3], true ^ inverted);
     tmp = solver.addClauseInt(vars2, c.getGroup());
     if (tmp) solver.clauses.push(tmp);
-    
+
     vars2[0] = Lit(vars[0], true ^ inverted);
     vars2[1] = Lit(vars[1], true ^ inverted);
     vars2[2] = Lit(vars[2], true ^ inverted);
@@ -493,5 +466,3 @@ void XorFinder::addXorAsNormal4(XorClause& c)
     if (tmp) solver.clauses.push(tmp);
 }
 
-
-}; //NAMESPACE MINISAT
index 038afa07fb4bf15c2622ece045d3c5e7496982f2..c038b09098be645b8be9d46db5acbad0d0abc87e 100644 (file)
@@ -35,113 +35,119 @@ class Solver;
 
 using std::pair;
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
+/**
+@brief Finds xors given a set of clauses
+
+It basically sorts clauses' literals, sorts clauses according to size and
+variable content, then idetifies continious reagions that could be an XOR
+clause, finds the xor clause by counting the number of unique negation
+permutations of the literals, then removes the clauses, and inserts the xor
+clause
+*/
 class XorFinder
 {
     public:
-        
-        XorFinder(Solver& _solver, vec<Clause*>& cls, ClauseCleaner::ClauseSetType _type);
-        const bool doNoPart(const uint minSize, const uint maxSize);
+        XorFinder(Solver& _solver, vec<Clause*>& cls);
+        const bool fullFindXors(const uint32_t minSize, const uint32_t maxSize);
         void addAllXorAsNorm();
-        
+
     private:
-        typedef vector<pair<Clause*, uint> > ClauseTable;
-        
-        const bool findXors(uint& sumLengths);
+        typedef vector<pair<Clause*, uint32_t> > ClauseTable;
+
+        const bool findXors(uint32_t& sumLengths);
         bool getNextXor(ClauseTable::iterator& begin, ClauseTable::iterator& end, bool& impair);
-        
-        struct clause_hasher {
-            size_t operator()(const Clause* c) const
-            {
-                size_t hash = 5381;
-                hash = ((hash << 5) + hash) ^ c->size();
-                for (uint i = 0, size = c->size(); i < size; i++)
-                    hash = ((hash << 5) + hash) ^ (*c)[i].var();
-                
-                return hash;
-            }
-        };
-        
+
+        /**
+        @brief For sorting clauses according to their size&their var content. Clauses' variables must already be sorted
+        */
         struct clause_sorter_primary {
-            bool operator()(const pair<Clause*, uint>& c11, const pair<Clause*, uint>& c22)
+            bool operator()(const pair<Clause*, uint32_t>& c11, const pair<Clause*, uint32_t>& c22)
             {
                 if (c11.first->size() != c22.first->size())
                     return (c11.first->size() < c22.first->size());
-                
+
                 #ifdef DEBUG_XORFIND2
                 Clause& c1 = *c11.first;
-                for (uint i = 0; i+1 < c1.size(); i++)
+                for (uint32_t i = 0; i+1 < c1.size(); i++)
                     assert(c1[i].var() <= c1[i+1].var());
-                
+
                 Clause& c2 = *c22.first;
-                for (uint i = 0; i+1 < c2.size(); i++)
+                for (uint32_t i = 0; i+1 < c2.size(); i++)
                     assert(c2[i].var() <= c2[i+1].var());
                 #endif //DEBUG_XORFIND2
-                
-                for (a = c11.first->getData(), b = c22.first->getData(), end = a + c11.first->size(); a != end; a++, b++) {
+
+                for (a = c11.first->getData(), b = c22.first->getData(), end = c11.first->getDataEnd(); a != end; a++, b++) {
                     if (a->var() != b->var())
                         return (a->var() > b->var());
                 }
 
                 return false;
             }
-            
+
             Lit const *a;
             Lit const *b;
             Lit const *end;
         };
-        
+
+        /**
+        @brief Sorts clauses with equal length and variable content according to their literals' signs
+
+        NOTE: the length and variable content of c11 and c22 MUST be the same
+
+        Used to avoid the problem of having 2 clauses with exactly the same
+        content being counted as two different clauses (when counting the
+        (im)pairedness of XOR being searched)
+        */
         struct clause_sorter_secondary {
-            bool operator()(const pair<Clause*, uint>& c11, const pair<Clause*, uint>& c22) const
+            bool operator()(const pair<Clause*, uint32_t>& c11, const pair<Clause*, uint32_t>& c22) const
             {
                 const Clause& c1 = *(c11.first);
                 const Clause& c2 = *(c22.first);
+                assert(c1.size() == c2.size());
 
-                for (uint i = 0, size = c1.size(); i < size; i++) {
+                for (uint32_t i = 0, size = c1.size(); i < size; i++) {
+                    assert(c1[i].var() == c2[i].var());
                     if (c1[i].sign() !=  c2[i].sign())
                         return c1[i].sign();
                 }
-                
+
                 return false;
             }
         };
-         
+
+        /**
+        @brief Returns whether vars in clauses are the same -- clauses' literals must be identically sorted
+        */
         bool clause_vareq(const Clause* c1, const Clause* c2) const
         {
             if (c1->size() != c2->size())
                 return false;
 
-            for (uint i = 0, size = c1->size(); i < size; i++)
+            for (uint32_t i = 0, size = c1->size(); i < size; i++)
                 if ((*c1)[i].var() != (*c2)[i].var())
                     return false;
 
             return true;
         }
-        
+
         ClauseTable table;
         vector<bool> toRemove;
         vector<bool> toLeaveInPlace;
         void clearToRemove();
         uint32_t foundXors;
-        
-        //For adding xor as norm
+
+        //For adding xor clause as normal clause
         void addXorAsNormal3(XorClause& c);
         void addXorAsNormal4(XorClause& c);
-        
+
         vec<Clause*>& cls;
-        ClauseCleaner::ClauseSetType type;
-        
+
         bool clauseEqual(const Clause& c1, const Clause& c2) const;
         bool impairSigns(const Clause& c) const;
-        void countImpairs(const ClauseTable::iterator& begin, const ClauseTable::iterator& end, uint& numImpair, uint& numPair) const;
+        void countImpairs(const ClauseTable::iterator& begin, const ClauseTable::iterator& end, uint32_t& numImpair, uint32_t& numPair) const;
         bool isXor(const uint32_t size, const ClauseTable::iterator& begin, const ClauseTable::iterator& end, bool& impair);
-        
+
         Solver& solver;
 };
 
-}; //NAMESPACE MINISAT
-
 #endif //XORFINDER_H
index dc5c4fbbe43ba75b4a446a7c0dda46ada0c2f6d8..8509ee29da682e453b702fd3fa3d2903afe1ba74 100644 (file)
@@ -1,7 +1,10 @@
-/**************************************************************************************************
-Originally From: Solver.C -- (C) Niklas Een, Niklas Sorensson, 2004
-Substantially modified by: Mate Soos (2010)
-**************************************************************************************************/
+/*****************************************************************************
+SatELite -- (C) Niklas Een, Niklas Sorensson, 2004
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+Original code by SatELite authors are under an MIT licence.
+Modifications for CryptoMiniSat are under GPLv3.
+******************************************************************************/
 
 #include "Solver.h"
 #include "XorSubsumer.h"
@@ -26,10 +29,6 @@ using std::cout;
 using std::endl;
 #endif //VERBOSE_DEBUG
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 XorSubsumer::XorSubsumer(Solver& s):
     solver(s)
     , totalTime(0.0)
@@ -60,9 +59,8 @@ void XorSubsumer::subsume0(XorClauseSimp ps)
             #endif
             clauses_subsumed++;
             assert(tmp->size() == ps.clause->size());
-            if (ps.clause->xor_clause_inverted() == tmp->xor_clause_inverted()) {
+            if (ps.clause->xorEqualFalse() == tmp->xorEqualFalse()) {
                 unlinkClause(subs[i]);
-                solver.clauseAllocator.clauseFree(tmp);
             } else {
                 solver.ok = false;
                 return;
@@ -74,7 +72,7 @@ void XorSubsumer::subsume0(XorClauseSimp ps)
             std::cout << "Cutting xor-clause:";
             subs[i].clause->plainPrint();
             #endif //VERBOSE_DEBUG
-            XorClause *c = solver.addXorClauseInt(unmatchedPart, tmp->xor_clause_inverted() ^ !ps.clause->xor_clause_inverted(), tmp->getGroup());
+            XorClause *c = solver.addXorClauseInt(unmatchedPart, tmp->xorEqualFalse() ^ !ps.clause->xorEqualFalse(), tmp->getGroup());
             if (c != NULL)
                 linkInClause(*c);
             unlinkClause(subs[i]);
@@ -102,16 +100,22 @@ void XorSubsumer::findUnMatched(const T& A, const T& B, vec<Lit>& unmatchedPart)
 void XorSubsumer::unlinkClause(XorClauseSimp c, const Var elim)
 {
     XorClause& cl = *c.clause;
-    
+
     for (uint32_t i = 0; i < cl.size(); i++) {
         removeW(occur[cl[i].var()], &cl);
     }
-    
-    if (elim != var_Undef)
-        elimedOutVar[elim].push_back(c.clause);
-    
+
+    if (elim != var_Undef) {
+        XorElimedClause data;
+        for (Lit *it = cl.getData(), *end = cl.getDataEnd(); it != end; it++) {
+            data.lits.push_back(it->unsign());
+        }
+        data.xorEqualFalse = cl.xorEqualFalse();
+        elimedOutVar[elim].push_back(data);
+    }
     solver.detachClause(cl);
-    
+    solver.clauseAllocator.clauseFree(c.clause);
+
     clauses[c.index].clause = NULL;
 }
 
@@ -120,9 +124,9 @@ void XorSubsumer::unlinkModifiedClause(vec<Lit>& origClause, XorClauseSimp c)
     for (uint32_t i = 0; i < origClause.size(); i++) {
         removeW(occur[origClause[i].var()], c.clause);
     }
-    
+
     solver.detachModifiedClause(origClause[0].var(), origClause[1].var(), origClause.size(), c.clause);
-    
+
     clauses[c.index].clause = NULL;
 }
 
@@ -140,14 +144,14 @@ XorClauseSimp XorSubsumer::linkInClause(XorClause& cl)
     for (uint32_t i = 0; i < cl.size(); i++) {
         occur[cl[i].var()].push(c);
     }
-    
+
     return c;
 }
 
 void XorSubsumer::linkInAlreadyClause(XorClauseSimp& c)
 {
     XorClause& cl = *c.clause;
-    
+
     for (uint32_t i = 0; i < c.clause->size(); i++) {
         occur[cl[i].var()].push(c);
     }
@@ -161,10 +165,8 @@ void XorSubsumer::addFromSolver(vec<XorClause*>& cs)
     for (XorClause **end = i + cs.size(); i !=  end; i++) {
         if (i+1 != end)
             __builtin_prefetch(*(i+1), 1, 1);
-        
+
         linkInClause(**i);
-        if ((*i)->getVarChanged() || (*i)->getStrenghtened())
-            (*i)->calcXorAbstraction();
     }
     cs.clear();
     cs.push(NULL); //HACK --to force xor-propagation
@@ -177,7 +179,6 @@ void XorSubsumer::addBackToSolver()
         if (clauses[i].clause != NULL) {
             solver.xorclauses.push(clauses[i].clause);
             clauses[i].clause->unsetStrenghtened();
-            clauses[i].clause->unsetVarChanged();
         }
     }
     for (Var var = 0; var < solver.nVars(); var++) {
@@ -193,13 +194,22 @@ void XorSubsumer::fillCannotEliminate()
     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<Clause*>& tmp = solver.varReplacer->getClauses();
-    for (uint32_t i = 0; i < tmp.size(); i++)
-        addToCannotEliminate(tmp[i]);
-    
+    uint32_t wsLit = 0;
+    for (const vec<Watched> *it = solver.watches.getData(), *end = solver.watches.getDataEnd(); it != end; it++, wsLit++) {
+        Lit lit = ~Lit::toLit(wsLit);
+        const vec<Watched>& ws = *it;
+        for (const Watched *it2 = ws.getData(), *end2 = ws.getDataEnd(); it2 != end2; it2++) {
+            if (it2->isBinary() && !it2->getLearnt()) {
+                cannot_eliminate[lit.var()] = true;
+                cannot_eliminate[it2->getOtherLit().var()] = true;
+            }
+        }
+    }
+
+    for (Var var = 0; var < solver.nVars(); var++) {
+        cannot_eliminate[var] |= solver.varReplacer->cannot_eliminate[var];
+    }
+
     #ifdef VERBOSE_DEBUG
     uint32_t tmpNum = 0;
     for (uint32_t i = 0; i < cannot_eliminate.size(); i++)
@@ -211,26 +221,29 @@ void XorSubsumer::fillCannotEliminate()
 
 void XorSubsumer::extendModel(Solver& solver2)
 {
+    #ifdef VERBOSE_DEBUG
+    std::cout << "XorSubsumer::extendModel(Solver& solver2) called" << std::endl;
+    #endif
+
     assert(checkElimedUnassigned());
     vec<Lit> tmp;
-    typedef map<Var, vector<XorClause*> > elimType;
+    typedef map<Var, vector<XorElimedClause> > 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<XorClause*>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
-            XorClause& c = **it2;
+
+        for (vector<XorElimedClause>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
+            XorElimedClause& 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);
+            tmp.growTo(c.lits.size());
+            std::copy(c.lits.begin(), c.lits.end(), tmp.getData());
+            solver2.addXorClause(tmp, c.xorEqualFalse);
             assert(solver2.ok);
         }
     }
@@ -255,10 +268,8 @@ const bool XorSubsumer::localSubstitute()
                     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]);
+                    XorClause* ret = solver.addXorClauseInt(tmp, c1.xorEqualFalse() ^ !c2.xorEqualFalse(), c1.getGroup());
+                    release_assert(ret == NULL);
                     if (!solver.ok) {
                         #ifdef VERBOSE_DEBUG
                         std::cout << "solver.ok is false after local substitution" << std::endl;
@@ -269,7 +280,7 @@ const bool XorSubsumer::localSubstitute()
             }
         }
     }
-    
+
     return true;
 }
 
@@ -320,6 +331,35 @@ void XorSubsumer::removeWrong(vec<Clause*>& cs)
     cs.shrink(i-j);
 }
 
+void XorSubsumer::removeWrongBins()
+{
+    uint32_t numRemovedHalfLearnt = 0;
+    uint32_t wsLit = 0;
+    for (vec<Watched> *it = solver.watches.getData(), *end = solver.watches.getDataEnd(); it != end; it++, wsLit++) {
+        Lit lit = ~Lit::toLit(wsLit);
+        vec<Watched>& ws = *it;
+
+        Watched* i = ws.getData();
+        Watched* j = i;
+        for (Watched *end2 = ws.getDataEnd(); i != end2; i++) {
+            if (i->isBinary()
+                && i->getLearnt()
+                && (var_elimed[lit.var()] || var_elimed[i->getOtherLit().var()])
+                ) {
+                numRemovedHalfLearnt++;
+            } else {
+                assert(!i->isBinary() || (!var_elimed[lit.var()] && !var_elimed[i->getOtherLit().var()]));
+                *j++ = *i;
+            }
+        }
+        ws.shrink_(i - j);
+    }
+
+    assert(numRemovedHalfLearnt % 2 == 0);
+    solver.learnts_literals -= numRemovedHalfLearnt;
+    solver.numBins -= numRemovedHalfLearnt/2;
+}
+
 
 const bool XorSubsumer::removeDependent()
 {
@@ -341,13 +381,15 @@ const bool XorSubsumer::removeDependent()
             XorClause& c1 = *(occ[0].clause);
             lits.growTo(c1.size());
             std::copy(c1.getData(), c1.getDataEnd(), lits.getData());
-            bool inverted = c1.xor_clause_inverted();
-            
+            bool inverted = c1.xorEqualFalse();
+
             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();
+            inverted ^= !c2.xorEqualFalse();
             uint32_t group = c2.getGroup();
+            uint32_t ret = removeAll(lits, var);
+            release_assert(ret == 2);
 
             #ifdef VERBOSE_DEBUG
             std::cout << "Eliminating var " << var + 1 << " present in 2 xor-clauses" << std::endl;
@@ -357,13 +399,13 @@ const bool XorSubsumer::removeDependent()
             XorClauseSimp toUnlink0 = occ[0];
             XorClauseSimp toUnlink1 = occ[1];
             unlinkClause(toUnlink0);
-            solver.clauseAllocator.clauseFree(toUnlink0.clause);
             unlinkClause(toUnlink1, var);
             solver.setDecisionVar(var, false);
             var_elimed[var] = true;
             numElimed++;
-            
-            uint32_t lastSize =  solver.varReplacer->getClauses().size();
+
+            for (uint32_t i = 0; i < lits.size(); i++)
+                cannot_eliminate[lits[i].var()] = true;
             XorClause* c = solver.addXorClauseInt(lits, inverted, group);
             #ifdef VERBOSE_DEBUG
             if (c != NULL) {
@@ -372,8 +414,6 @@ const bool XorSubsumer::removeDependent()
                 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;
@@ -382,7 +422,7 @@ const bool XorSubsumer::removeDependent()
             }
         }
     }
-    
+
     return true;
 }
 
@@ -396,7 +436,8 @@ inline void XorSubsumer::addToCannotEliminate(Clause* it)
 const bool XorSubsumer::unEliminate(const Var var)
 {
     assert(var_elimed[var]);
-    typedef map<Var, vector<XorClause*> > elimType;
+    vec<Lit> tmp;
+    typedef map<Var, vector<XorElimedClause> > elimType;
     elimType::iterator it = elimedOutVar.find(var);
 
     //MUST set to decision, since it would never have been eliminated
@@ -405,22 +446,30 @@ const bool XorSubsumer::unEliminate(const Var var)
     var_elimed[var] = false;
     numElimed--;
     assert(it != elimedOutVar.end());
-    
+    #ifdef VERBOSE_DEBUG
+    std::cout << "Reinserting xor elimed var: " << var+1 << std::endl;
+    #endif
+
     FILE* backup_libraryCNFfile = solver.libraryCNFFile;
     solver.libraryCNFFile = NULL;
-    for (vector<XorClause*>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
-        XorClause& c = **it2;
-        solver.addXorClause(c, c.xor_clause_inverted());
-        solver.clauseAllocator.clauseFree(&c);
+    for (vector<XorElimedClause>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
+        XorElimedClause& c = *it2;
+        tmp.clear();
+        tmp.growTo(c.lits.size());
+        std::copy(c.lits.begin(), c.lits.end(), tmp.getData());
+        #ifdef VERBOSE_DEBUG
+        std::cout << "Reinserting elimed clause: " << tmp << std::endl;;
+        #endif
+        solver.addXorClause(tmp, c.xorEqualFalse);
     }
     solver.libraryCNFFile = backup_libraryCNFfile;
     elimedOutVar.erase(it);
-    
+
     return solver.ok;
 }
 
 
-const bool XorSubsumer::simplifyBySubsumption(const bool doFullSubsume)
+const bool XorSubsumer::simplifyBySubsumption()
 {
     double myTime = cpuTime();
     uint32_t origTrailSize = solver.trail.size();
@@ -429,34 +478,33 @@ const bool XorSubsumer::simplifyBySubsumption(const bool doFullSubsume)
     clauseID = 0;
     uint32_t lastNumElimed = numElimed;
     localSubstituteUseful = 0;
-    while (solver.performReplace && solver.varReplacer->needsReplace()) {
+    while (solver.conf.doReplace && 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());
     addFromSolver(solver.xorclauses);
     #ifdef BIT_MORE_VERBOSITY
     std::cout << "c time to link in:" << cpuTime()-myTime << std::endl;
     #endif
-    
+
     origNClauses = clauses.size();
-    
+
     if (!solver.ok) return false;
     #ifdef VERBOSE_DEBUG
     std::cout << "c   clauses:" << clauses.size() << std::endl;
     #endif
-    
+
     bool replaced = true;
     bool propagated = false;
     while (replaced || propagated) {
@@ -470,32 +518,28 @@ const bool XorSubsumer::simplifyBySubsumption(const bool doFullSubsume)
                 }
             }
         }
-        
+
         propagated =  (solver.qhead != solver.trail.size());
         solver.ok = (solver.propagate().isNULL());
         if (!solver.ok) {
             return false;
         }
-        solver.clauseCleaner->cleanXorClausesBewareNULL(clauses, ClauseCleaner::xorSimpClauses, *this);
         if (!solver.ok) return false;
-        testAllClauseAttach();
 
         fillCannotEliminate();
-        if (solver.conglomerateXors && !removeDependent()) {
+        if (solver.conf.doConglXors && !removeDependent()) {
             addBackToSolver();
             return false;
         }
-        testAllClauseAttach();
 
-        if (solver.heuleProcess && !localSubstitute()) {
+        if (solver.conf.doHeuleProcess && !localSubstitute()) {
             addBackToSolver();
             return false;
         }
-        testAllClauseAttach();
 
-        /*if (solver.performReplace && solver.varReplacer->needsReplace()) {
+        /*if (solver.doReplace && solver.varReplacer->needsReplace()) {
             addBackToSolver();
-            while (solver.performReplace && solver.varReplacer->needsReplace()) {
+            while (solver.doReplace && solver.varReplacer->needsReplace()) {
                 replaced = true;
                 if (!solver.varReplacer->performReplace())
                     return false;
@@ -507,46 +551,25 @@ const bool XorSubsumer::simplifyBySubsumption(const bool doFullSubsume)
     solver.order_heap.filter(Solver::VarFilter(solver));
 
     removeWrong(solver.learnts);
-    removeWrong(solver.binaryClauses);
+    removeWrongBins();
     addBackToSolver();
-    
-    if (solver.verbosity >= 1) {
-        std::cout << "c |  x-sub: " << std::setw(5) << clauses_subsumed
+    removeAssignedVarsFromEliminated();
+
+    if (solver.conf.verbosity >= 1) {
+        std::cout << "c x-sub: " << std::setw(5) << clauses_subsumed
         << " x-cut: " << std::setw(6) << clauses_cut
         << " vfix: " << std::setw(6) <<solver.trail.size() - origTrailSize
         << " v-elim: " <<std::setw(6) << numElimed - lastNumElimed
         << " locsubst:" << std::setw(6) << localSubstituteUseful
         << " time: " << std::setw(6) << std::setprecision(2) << (cpuTime() - myTime)
-        << std::setw(3) << " |" << std::endl;
+        << std::endl;
     }
     totalTime += cpuTime() - myTime;
-    
+
     solver.testAllClauseAttach();
     return true;
 }
 
-#ifdef DEBUG_ATTACH
-void XorSubsumer::testAllClauseAttach() const
-{
-    for (const XorClauseSimp *it = clauses.getData(), *end = clauses.getDataEnd(); it != end; it++) {
-        if (it->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<XorClauseSimp>& out_subsumed)
 {
     #ifdef VERBOSE_DEBUGSUBSUME0
@@ -557,18 +580,18 @@ void XorSubsumer::findSubsumed(XorClause& ps, vec<XorClauseSimp>& out_subsumed)
     }
     printf("0\n");
     #endif
-    
+
     uint32_t min_i = 0;
     for (uint32_t i = 1; i < ps.size(); i++){
         if (occur[ps[i].var()].size() < occur[ps[min_i].var()].size())
             min_i = i;
     }
-    
+
     vec<XorClauseSimp>& cs = occur[ps[min_i].var()];
     for (XorClauseSimp *it = cs.getData(), *end = it + cs.size(); it != end; it++){
         if (it+1 != end)
             __builtin_prefetch((it+1)->clause, 1, 1);
-        
+
         if (it->clause != &ps && subsetAbst(ps.getAbst(), it->clause->getAbst()) && ps.size() <= it->clause->size() && subset(ps, *it->clause)) {
             out_subsumed.push(*it);
             #ifdef VERBOSE_DEBUGSUBSUME0
@@ -581,14 +604,28 @@ void XorSubsumer::findSubsumed(XorClause& ps, vec<XorClauseSimp>& out_subsumed)
 
 const bool XorSubsumer::checkElimedUnassigned() const
 {
+    uint32_t checkNumElimed = 0;
     for (uint32_t i = 0; i < var_elimed.size(); i++) {
         if (var_elimed[i]) {
+            checkNumElimed++;
             assert(solver.assigns[i] == l_Undef);
             if (solver.assigns[i] != l_Undef) return false;
         }
     }
+    assert(numElimed == checkNumElimed);
 
     return true;
 }
 
-}; //NAMESPACE MINISAT
+void XorSubsumer::removeAssignedVarsFromEliminated()
+{
+    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<Var, vector<XorElimedClause> >::iterator it = elimedOutVar.find(var);
+            if (it != elimedOutVar.end()) elimedOutVar.erase(it);
+        }
+    }
+}
index 43867fa523d26ffcb50323be4b2218983296313b..e03fa36564345830f7fb09745749349a1cb8b4d4 100644 (file)
@@ -1,7 +1,10 @@
-/**************************************************************************************************
-Originally From: Solver.C -- (C) Niklas Een, Niklas Sorensson, 2004
-Substantially modified by: Mate Soos (2010)
-**************************************************************************************************/
+/*****************************************************************************
+SatELite -- (C) Niklas Een, Niklas Sorensson, 2004
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+Original code by SatELite authors are under an MIT licence.
+Modifications for CryptoMiniSat are under GPLv3.
+******************************************************************************/
 
 #ifndef XORSIMPLIFIER_H
 #define XORSIMPLIFIER_H
@@ -10,18 +13,30 @@ Substantially modified by: Mate Soos (2010)
 #include "Vec.h"
 #include "XSet.h"
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 class ClauseCleaner;
 
+/**
+@brief Handles xor-subsumption and variable elimination at the XOR level
+
+This class achieves three things:
+
+1) it removes variables though XOR-ing of two xors thereby removing their common
+variable. If that variable is not used anywere else, the variable is now removed
+from the problem
+
+2) It tries to XOR clauses together to get 1-long or 2-long XOR clauses. These
+force variables to certain values or replace variables with other variables,
+respectively
+
+3) It tries to subsume XOR clauses with other XOR clauses (making 2 XOR clauses
+in the process, but one of them is going to be much smaller than it was originally)
+*/
 class XorSubsumer
 {
 public:
-    
+
     XorSubsumer(Solver& S2);
-    const bool simplifyBySubsumption(const bool doFullSubsume = false);
+    const bool simplifyBySubsumption();
     void unlinkModifiedClause(vec<Lit>& origClause, XorClauseSimp c);
     void unlinkModifiedClauseNoDetachNoNULL(vec<Lit>& origClause, XorClauseSimp c);
     void unlinkClause(XorClauseSimp cc, Var elim = var_Undef);
@@ -29,30 +44,49 @@ public:
     void linkInAlreadyClause(XorClauseSimp& c);
     void newVar();
     void extendModel(Solver& solver2);
+
     const uint32_t getNumElimed() const;
     const vec<char>& getVarElimed() const;
     const bool unEliminate(const Var var);
     const bool checkElimedUnassigned() const;
     const double getTotalTime() const;
-    
+
+    struct XorElimedClause
+    {
+        vector<Lit> lits;
+        bool xorEqualFalse;
+
+        void plainPrint(FILE* to = stdout) const
+        {
+            fprintf(to, "x");
+            if (xorEqualFalse) fprintf(to, "-");
+            for (size_t i = 0; i < lits.size(); i++) {
+                assert(!lits[i].sign());
+                fprintf(to, "%d ", lits[i].var() + 1);
+            }
+            fprintf(to, "0\n");
+        }
+    };
+    const map<Var, vector<XorElimedClause> >& getElimedOutVar() const;
+
 private:
-    
+
     friend class ClauseCleaner;
     friend class ClauseAllocator;
-    
+
     //Main
     vec<XorClauseSimp>        clauses;
     vec<vec<XorClauseSimp> >  occur;          // 'occur[index(lit)]' is a list of constraints containing 'lit'.
     Solver&                   solver;         // The Solver
-    
+
     // Temporaries (to reduce allocation overhead):
     //
     vec<char>                 seen_tmp;       // (used in various places)
-    
+
     //Start-up
     void addFromSolver(vec<XorClause*>& cs);
     void addBackToSolver();
-    
+
     // Subsumption:
     void findSubsumed(XorClause& ps, vec<XorClauseSimp>& out_subsumed);
     bool isSubsumed(XorClause& ps);
@@ -65,26 +99,28 @@ private:
 
     //helper
     void testAllClauseAttach() const;
-    
+
     //dependent removal
     const bool removeDependent();
     void fillCannotEliminate();
     vec<char> cannot_eliminate;
     void addToCannotEliminate(Clause* it);
     void removeWrong(vec<Clause*>& cs);
+    void removeWrongBins();
+    void removeAssignedVarsFromEliminated();
 
     //Global stats
     double totalTime;
-    map<Var, vector<XorClause*> > elimedOutVar;
+    map<Var, vector<XorElimedClause> > elimedOutVar;
     vec<char> var_elimed;
     uint32_t numElimed;
-    
+
     //Heule-process
     template<class T>
     void xorTwoClauses(const T& c1, const T& c2, vec<Lit>& xored);
     const bool localSubstitute();
     uint32_t localSubstituteUseful;
-    
+
     uint32_t clauses_subsumed;
     uint32_t clauses_cut;
     uint32_t origNClauses;
@@ -137,6 +173,9 @@ inline const double XorSubsumer::getTotalTime() const
     return totalTime;
 }
 
-}; //NAMESPACE MINISAT
+inline const map<Var, vector<XorSubsumer::XorElimedClause> >& XorSubsumer::getElimedOutVar() const
+{
+    return elimedOutVar;
+}
 
 #endif //XORSIMPLIFIER_H
index 436128d18dce2929126ac8d831c221f679ef3aac..d1ec2b21c3153d6ac788d2db5fbcffaee2a043a4 100644 (file)
@@ -18,32 +18,90 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 **************************************************************************************************/
 
-#define RATIOREMOVECLAUSES 2
+///////////////////
+// Settings (magic constants)
+///////////////////
+
+//Parameters for learnt-clause cleaning
+#define RATIOREMOVECLAUSES 1.0/2.0
 #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
+
+//Parameters for xor-finding (binary and non-binary)
+#define MAX_CLAUSENUM_XORFIND 1500000
+#define BINARY_TO_XOR_APPROX 12.0
+
+#define RANDOM_LOOKAROUND_SEARCHSPACE
+#define UPDATE_TRANSOTFSSR_CACHE 200000
+//#define USE_OLD_POLARITIES
+
+//Parameters controlling simplification rounds
 #define SIMPLIFY_MULTIPLIER 300
+#define SIMPLIFY_MULTIPLIER_MULTIPLIER 1.5
+#define MAX_CONFL_BETWEEN_SIMPLIFY 500000
+#define BURST_SEARCH
+#define NUM_CONFL_BURST_SEARCH 500
+
+//Parameters controlling full restarts
+#define FULLRESTART_MULTIPLIER 250
 #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
+
+//Gaussian elimination parameters
 #define MIN_GAUSS_XOR_CLAUSES 5
 #define MAX_GAUSS_XOR_CLAUSES 30000
-#define MAX_OLD_LEARNTS 2000000
-//#define DEBUG_ATTACH
-#define RANDOM_LOOKAROUND_SEARCHSPACE
-//#define USE_OLD_POLARITIES
-//#define DEBUG_VARELIM
-#define BURST_SEARCH
-//#define DEBUG_PROPAGATEFROM
+
+//Parameters regarding glues
+#define DEFAULT_MAX_GLUE 24
+#define MAX_GLUE_BITS 7
+#define MAX_THEORETICAL_GLUE ((uint32_t)((1 << MAX_GLUE_BITS)-1))
+#define MIN_GLUE_RESTART 100
+#define DYNAMICALLY_UPDATE_GLUE
+#define UPDATE_VAR_ACTIVITY_BASED_ON_GLUE
+
+//Parameters for syncing between threads
+#define SYNC_EVERY_CONFL 6000
+
+///////////////////
+// Verbose Debug
+///////////////////
+
+//#define VERBOSE_DEBUG_XOR
+//#define VERBOSE_DEBUG
+#ifdef VERBOSE_DEBUG
+#define SILENT_DEBUG
+#define DEBUG_USELESS_LEARNT_BIN_REMOVAL
+#define DEBUG_ATTACH_FULL
+#endif
+
+
+///////////////////
+// Silent Debug
+///////////////////
+
+#ifndef NDEBUG
+#define SILENT_DEBUG
+#endif
+
+#ifdef SILENT_DEBUG
+#define DEBUG_VARELIM
+#define DEBUG_PROPAGATEFROM
+#define DEBUG_WATCHED
+#define DEBUG_ATTACH
+#define DEBUG_REPLACER
+#define DEBUG_HYPERBIN
+//#define DEBUG_USELESS_LEARNT_BIN_REMOVAL
+#endif
+
+//#define DEBUG_ATTACH_FULL
+
+///////////////////
+//  For Automake tools
+///////////////////
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
index fee624db1b4ce52f2a430f7f7c04debef48d20dd..c8399d3debad1dcae282ec716d864451034cf3f7 100644 (file)
@@ -243,8 +243,4 @@ typedef uint64_t  uintmax_t;
 
 #endif // __STDC_CONSTANT_MACROS ]
 
-#ifndef uint
-#define uint unsigned int
-#endif
-
 #endif // _MSC_STDINT_H_ ]
index 2825a9c17f3f8b1c578edc68e70e7b5f1323751e..711dd872553a36bbc2d01e523fe6f430e0779138 100644 (file)
@@ -20,20 +20,20 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
 #ifndef Alg_h
 #define Alg_h
 
+#include <iostream>
+#include "Vec.h"
+#include "../SolverTypes.h"
+#include "../Watched.h"
+
 #ifdef _MSC_VER
 #include <msvc/stdint.h>
 #else
 #include <stdint.h>
 #endif //_MSC_VER
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 //=================================================================================================
 // Useful functions on vectors
 
-
 template<class V, class T>
 static inline void remove(V& ts, const T& t)
 {
@@ -44,6 +44,21 @@ static inline void remove(V& ts, const T& t)
     ts.pop();
 }
 
+template<class V>
+static inline const uint32_t removeAll(V& ts, const Var t)
+{
+    Lit* i = ts.getData();
+    Lit* j = i;
+    for (Lit *end = ts.getDataEnd(); i != end; i++) {
+        if (i->var() != t) {
+            *j++ = *i;
+        }
+    }
+    ts.shrink(i-j);
+
+    return (i-j);
+}
+
 template<class V, class T>
 static inline void removeW(V& ts, const T& t)
 {
@@ -70,6 +85,154 @@ static inline bool findW(V& ts, const T& t)
     return j < ts.size();
 }
 
-}; //NAMESPACE MINISAT
+
+//Normal clause
+static bool    findWCl(const vec<Watched>& ws, const ClauseOffset c);
+static void    removeWCl(vec<Watched> &ws, const ClauseOffset c);
+
+//Binary clause
+static bool    findWBin(const vec<vec<Watched> >& wsFull, const Lit lit1, const Lit impliedLit);
+static bool    findWBin(const vec<vec<Watched> >& wsFull, const Lit lit1, const Lit impliedLit, const bool learnt);
+static void    removeWBin(vec<Watched> &ws, const Lit impliedLit, const bool learnt);
+static void    removeWTri(vec<Watched> &ws, const Lit lit1, Lit lit2);
+static const std::pair<uint32_t, uint32_t>  removeWBinAll(vec<Watched> &ws, const Lit impliedLit);
+static Watched& findWatchedOfBin(vec<vec<Watched> >& wsFull, const Lit lit1, const Lit lit2, const bool learnt);
+static Watched& findWatchedOfBin(vec<vec<Watched> >& wsFull, const Lit lit1, const Lit lit2);
+
+//Xor Clause
+static bool    findWXCl(const vec<Watched>& ws, const ClauseOffset c);
+static void    removeWXCl(vec<Watched> &ws, const ClauseOffset c);
+
+//////////////////
+// NORMAL Clause
+//////////////////
+static inline bool findWCl(const vec<Watched>& ws, const ClauseOffset c)
+{
+    uint32_t j = 0;
+    for (; j < ws.size() && (!ws[j].isClause() || ws[j].getNormOffset() != c); j++);
+    return j < ws.size();
+}
+
+static inline void removeWCl(vec<Watched> &ws, const ClauseOffset c)
+{
+    uint32_t j = 0;
+    for (; j < ws.size() && (!ws[j].isClause() || ws[j].getNormOffset() != c); j++);
+    assert(j < ws.size());
+    for (; j < ws.size()-1; j++) ws[j] = ws[j+1];
+    ws.pop();
+}
+
+//////////////////
+// XOR Clause
+//////////////////
+static inline bool findWXCl(const vec<Watched>& ws, const ClauseOffset c)
+{
+    uint32_t j = 0;
+    for (; j < ws.size() && (!ws[j].isXorClause() || ws[j].getXorOffset() != c); j++);
+    return j < ws.size();
+}
+
+static inline void removeWXCl(vec<Watched> &ws, const ClauseOffset c)
+{
+    uint32_t j = 0;
+    for (; j < ws.size() && (!ws[j].isXorClause() || ws[j].getXorOffset() != c); j++);
+    assert(j < ws.size());
+    for (; j < ws.size()-1; j++) ws[j] = ws[j+1];
+    ws.pop();
+}
+
+//////////////////
+// TRI Clause
+//////////////////
+
+static inline const bool findWTri(const vec<Watched> &ws, const Lit lit1, const Lit lit2)
+{
+    uint32_t j = 0;
+    for (; j < ws.size() && (!ws[j].isTriClause() || ws[j].getOtherLit() != lit1 || ws[j].getOtherLit2() != lit2); j++);
+    return(j < ws.size());
+}
+
+static inline void removeWTri(vec<Watched> &ws, const Lit lit1, const Lit lit2)
+{
+    uint32_t j = 0;
+    for (; j < ws.size() && (!ws[j].isTriClause() || ws[j].getOtherLit() != lit1 || ws[j].getOtherLit2() != lit2); j++);
+    assert(j < ws.size());
+    for (; j < ws.size()-1; j++) ws[j] = ws[j+1];
+    ws.pop();
+}
+
+//////////////////
+// BINARY Clause
+//////////////////
+static inline bool findWBin(const vec<vec<Watched> >& wsFull, const Lit lit1, const Lit impliedLit)
+{
+    uint32_t j = 0;
+    const vec<Watched>& ws = wsFull[(~lit1).toInt()];
+    for (; j < ws.size() && (!ws[j].isBinary() || ws[j].getOtherLit() != impliedLit); j++);
+    return j < ws.size();
+}
+
+static inline bool findWBin(const vec<vec<Watched> >& wsFull, const Lit lit1, const Lit impliedLit, const bool learnt)
+{
+    uint32_t j = 0;
+    const vec<Watched>& ws = wsFull[(~lit1).toInt()];
+    for (; j < ws.size() && (!ws[j].isBinary() || ws[j].getOtherLit() != impliedLit || ws[j].getLearnt() != learnt); j++);
+    return j < ws.size();
+}
+
+static inline void removeWBin(vec<Watched> &ws, const Lit impliedLit, const bool learnt)
+{
+    uint32_t j = 0;
+    for (; j < ws.size() && (!ws[j].isBinary() || ws[j].getOtherLit() != impliedLit || ws[j].getLearnt() != learnt); j++);
+    assert(j < ws.size());
+    for (; j < ws.size()-1; j++) ws[j] = ws[j+1];
+    ws.pop();
+}
+
+static inline const std::pair<uint32_t, uint32_t>  removeWBinAll(vec<Watched> &ws, const Lit impliedLit)
+{
+    uint32_t removedLearnt = 0;
+    uint32_t removedNonLearnt = 0;
+
+    Watched *i = ws.getData();
+    Watched *j = i;
+    for (Watched* end = ws.getDataEnd(); i != end; i++) {
+        if (!i->isBinary() || i->getOtherLit() != impliedLit)
+            *j++ = *i;
+        else {
+            if (i->getLearnt())
+                removedLearnt++;
+            else
+                removedNonLearnt++;
+        }
+    }
+    ws.shrink_(i-j);
+
+    return std::make_pair(removedLearnt, removedNonLearnt);
+}
+
+static inline Watched& findWatchedOfBin(vec<vec<Watched> >& wsFull, const Lit lit1, const Lit lit2, const bool learnt)
+{
+    vec<Watched>& ws = wsFull[(~lit1).toInt()];
+    for (Watched *i = ws.getData(), *end = ws.getDataEnd(); i != end; i++) {
+        if (i->isBinary() && i->getOtherLit() == lit2 && i->getLearnt() == learnt)
+            return *i;
+    }
+    assert(false);
+
+    return wsFull[0][0];
+}
+
+static inline Watched& findWatchedOfBin(vec<vec<Watched> >& wsFull, const Lit lit1, const Lit lit2)
+{
+    vec<Watched>& ws = wsFull[(~lit1).toInt()];
+    for (Watched *i = ws.getData(), *end = ws.getDataEnd(); i != end; i++) {
+        if (i->isBinary() && i->getOtherLit() == lit2)
+            return *i;
+    }
+    assert(false);
+
+    return wsFull[0][0];
+}
 
 #endif
index 8748d2a3d83dcc02455a204f07d3d32fa3fe8e8d..85775e85db30ce189e33d507b3f75905124ace5f 100644 (file)
@@ -28,10 +28,6 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
 
 #include "Vec.h"
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 //=================================================================================================
 // A heap implementation with support for decrease/increase key.
 
@@ -103,7 +99,6 @@ class BasicHeap {
     int  getmin    ()      { return removeMin(); }
 };
 
-}; //NAMESPACE MINISAT
 
 //=================================================================================================
 #endif
index 63b8c6d4acee00708b8b43f3811f9568c88d6666..bddf410083724188d1a2853cb8fb51d26a54600c 100644 (file)
@@ -24,10 +24,6 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
 #include <cassert>
 #include <new>
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 //=================================================================================================
 // Automatically resizable arrays
 //
@@ -147,6 +143,5 @@ public:
 
 };
 
-}; //NAMESPACE MINISAT
 
 #endif
index a2ae468fa407f1e27a0baf639c27e0f7c9b09c17..8a9c004d2c7b965ba368fa3981fbaf4dfad2a42c 100644 (file)
@@ -31,10 +31,6 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
 #include <stdint.h>
 #endif //_MSC_VER
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 //=================================================================================================
 // A heap implementation with support for decrease/increase key.
 
@@ -179,7 +175,7 @@ class Heap {
                 indices[heap[i]] = std::numeric_limits<uint32_t>::max();
 
         heap.shrink(i - j);
-        for (int i = heap.size() / 2 - 1; i >= 0; i--)
+        for (int i = ((int)heap.size()) / 2 - 1; i >= 0; i--)
             percolateDown(i);
 
         assert(heapProperty());
@@ -198,8 +194,6 @@ class Heap {
 
 };
 
-//=================================================================================================
-
-}; //NAMESPACE MINISAT
 
+//=================================================================================================
 #endif
index bd791c3e9af6004f57a2afd6f5351511337b2f91..b855c3b555c12f22c8095dde07453d214e25a288 100644 (file)
@@ -28,10 +28,6 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
 
 #include "Vec.h"
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 //=================================================================================================
 // Default hash/equals functions
 //
@@ -123,6 +119,4 @@ class Map {
     }
 };
 
-}; //NAMESPACE MINISAT
-
 #endif
index 4138559211145624a38e9a82915b6edc1f0375fb..2cc110ce9fa8c59c22383ffeaff088bc92613c9b 100644 (file)
@@ -22,10 +22,6 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
 
 #include "Vec.h"
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 //=================================================================================================
 
 
@@ -83,7 +79,4 @@ public:
 //};
 
 //=================================================================================================
-
-}; //NAMESPACE MINISAT
-
 #endif
index 1c6c1aedaf229e91cd3cecfbfbd404c52bedabf5..193eccd4c72444ae29ca3c4a032d658bb8234a29 100644 (file)
@@ -22,6 +22,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
 
 #include <cstdlib>
 #include <cassert>
+#include <iostream>
 #include <new>
 #ifdef _MSC_VER
 #include <msvc/stdint.h>
@@ -29,10 +30,6 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
 #include <stdint.h>
 #endif //_MSC_VER
 
-namespace MINISAT
-{
-using namespace MINISAT;
-
 //=================================================================================================
 // Automatically resizable arrays
 //
@@ -54,7 +51,7 @@ class vec {
     static inline uint32_t imax(int x, int y) {
         int mask = (y-x) >> (sizeof(int)*8-1);
         return (x&mask) + (y&(~mask)); }
-    
+
     void     myCopy (const vec<T>& other);
 
 public:
@@ -86,11 +83,27 @@ public:
     void     growTo (uint32_t size, const T& pad);
     void     clear  (bool dealloc = false);
     void     capacity (uint32_t size) { grow(size); }
+    const bool empty() const {return size() == 0;}
 
     // Stack interface:
     void     reserve(uint32_t res)     { if (cap < res) {cap = res; data = (T*)realloc(data, cap * sizeof(T));}}
-    void     push  (void)              { if (sz == cap) { cap = imax(2, (cap*3+1)>>1); data = (T*)realloc(data, cap * sizeof(T)); } new (&data[sz]) T(); sz++; }
-    void     push  (const T& elem)     { if (sz == cap) { cap = imax(2, (cap*3+1)>>1); data = (T*)realloc(data, cap * sizeof(T)); } data[sz++] = elem; }
+    void     push  (void)
+    {
+        if (sz == cap) {
+            cap = imax(2, (cap*3+1)>>1);
+            data = (T*)realloc(data, cap * sizeof(T));
+        }
+        new (&data[sz]) T();
+        sz++;
+    }
+    void     push  (const T& elem)
+    {
+        if (sz == cap) {
+            cap = imax(2, (cap*3+1)>>1);
+            data = (T*)realloc(data, cap * sizeof(T));
+        }
+        data[sz++] = elem;
+    }
     void     push_ (const T& elem)     { assert(sz < cap); data[sz++] = elem; }
 
     const T& last  (void) const        { return data[sz-1]; }
@@ -126,7 +139,7 @@ void vec<T>::growTo(uint32_t size) {
     grow(size);
     for (uint32_t i = sz; i != size; i++) new (&data[i]) T();
     sz = size; }
-    
+
 template<class T>
 void vec<T>::myCopy(const vec<T>& other) {
     assert(sz == 0);
@@ -139,9 +152,13 @@ void vec<T>::clear(bool dealloc) {
     if (data != NULL){
         for (uint32_t i = 0; i != sz; i++) data[i].~T();
         sz = 0;
-        if (dealloc) free(data), data = NULL, cap = 0; } }
-
+        if (dealloc) {
+            free(data);
+            data = NULL;
+            cap = 0;
+        }
+    }
+}
 
-}; //NAMESPACE MINISAT
 
 #endif
index f923c9a072a0fd1a9ceee869af190390724d6ba4..c615eb33a3a352838711081c04025a32d5153dc4 100644 (file)
@@ -22,33 +22,45 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
 #define TIME_MEM_H
 
 #ifdef _MSC_VER
-  #include <ctime>
-  #include <msvc/stdint.h>
+#include <msvc/stdint.h>
 #else
-  #include <sys/time.h>
-  #include <sys/resource.h>
-  #include <unistd.h>
-  #include <stdint.h>
-#endif
+#include <stdint.h>
+#endif //_MSC_VER
 
-namespace MINISAT
-{
-using namespace MINISAT;
+#if defined (_MSC_VER) || defined(CROSS_COMPILE)
+#include <ctime>
 
-/*************************************************************************************/
-#ifdef _MSC_VER
+static inline double cpuTime(void)
+{
+    return (double)clock() / CLOCKS_PER_SEC;
+}
+#else //_MSC_VER
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <unistd.h>
 
-static inline double cpuTime(void) {
-    return (double)clock() / CLOCKS_PER_SEC; }
-#else
+static inline double cpuTime(void)
+{
+    struct rusage ru;
+    #ifdef RUSAGE_THREAD
+    getrusage(RUSAGE_THREAD, &ru);
+    #else
+    getrusage(RUSAGE_SELF, &ru);
+    #endif
+    return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000.0;
+}
 
-static inline double cpuTime(void) {
+static inline double cpuTimeTotal(void)
+{
     struct rusage ru;
     getrusage(RUSAGE_SELF, &ru);
-    return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; }
-#endif
+    return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000.0;
+}
+#endif //CROSS_COMPILE
+
 
 #if defined(__linux__)
+#include <stdio.h>
 static inline int memReadStat(int field)
 {
     char    name[256];
@@ -57,29 +69,34 @@ static inline int memReadStat(int field)
     FILE*   in = fopen(name, "rb");
     if (in == NULL) return 0;
     int     value;
-    for (; field >= 0; field--)
-        fscanf(in, "%d", &value);
+
+    int rvalue= 1;
+    for (; (field >= 0) && (rvalue == 1); field--)
+        rvalue = fscanf(in, "%d", &value);
+
     fclose(in);
     return value;
 }
-static inline uint64_t memUsed() { return (uint64_t)memReadStat(0) * (uint64_t)getpagesize(); }
+static inline uint64_t memUsed()
+{
+    return (uint64_t)memReadStat(0) * (uint64_t)getpagesize();
+}
 
 
 #elif defined(__FreeBSD__)
-static inline uint64_t memUsed(void) {
+static inline uint64_t memUsed(void)
+{
     struct rusage ru;
     getrusage(RUSAGE_SELF, &ru);
-    return ru.ru_maxrss*1024; }
+    return ru.ru_maxrss*1024;
+}
 
 
 #else
-static inline uint64_t memUsed() { return 0; }
-#endif
-
-#if defined(__linux__)
-#include <fpu_control.h>
+static inline uint64_t memUsed()
+{
+    return 0;
+}
 #endif
 
-};
-
 #endif //TIME_MEM_H