summaryrefslogtreecommitdiff
path: root/src/prop/cryptominisat/Solver
diff options
context:
space:
mode:
authorDejan Jovanović <dejan.jovanovic@gmail.com>2012-03-29 03:08:05 +0000
committerDejan Jovanović <dejan.jovanovic@gmail.com>2012-03-29 03:08:05 +0000
commit6ba22cdd0e38f9811daefd2aee8218b8b8cf9e0e (patch)
tree435b1c90d00fd4f6cd05e29ebbdf8e735d8aa68e /src/prop/cryptominisat/Solver
parent6e5f551507a2a9af33e7b56107471a096a495862 (diff)
bringing cryptominisat into the main branch
Diffstat (limited to 'src/prop/cryptominisat/Solver')
-rw-r--r--src/prop/cryptominisat/Solver/BitArray.h188
-rw-r--r--src/prop/cryptominisat/Solver/BothCache.cpp114
-rw-r--r--src/prop/cryptominisat/Solver/BothCache.h20
-rw-r--r--src/prop/cryptominisat/Solver/BoundedQueue.h96
-rw-r--r--src/prop/cryptominisat/Solver/CSet.h209
-rw-r--r--src/prop/cryptominisat/Solver/Clause.h344
-rw-r--r--src/prop/cryptominisat/Solver/ClauseAllocator.cpp572
-rw-r--r--src/prop/cryptominisat/Solver/ClauseAllocator.h146
-rw-r--r--src/prop/cryptominisat/Solver/ClauseCleaner.cpp261
-rw-r--r--src/prop/cryptominisat/Solver/ClauseCleaner.h86
-rw-r--r--src/prop/cryptominisat/Solver/ClauseOffset.h16
-rw-r--r--src/prop/cryptominisat/Solver/ClauseVivifier.cpp342
-rw-r--r--src/prop/cryptominisat/Solver/ClauseVivifier.h61
-rw-r--r--src/prop/cryptominisat/Solver/CompleteDetachReattacher.cpp198
-rw-r--r--src/prop/cryptominisat/Solver/CompleteDetachReattacher.h78
-rw-r--r--src/prop/cryptominisat/Solver/DataSync.cpp216
-rw-r--r--src/prop/cryptominisat/Solver/DataSync.h101
-rw-r--r--src/prop/cryptominisat/Solver/DimacsParser.cpp490
-rw-r--r--src/prop/cryptominisat/Solver/DimacsParser.h84
-rw-r--r--src/prop/cryptominisat/Solver/DoublePackedRow.h173
-rw-r--r--src/prop/cryptominisat/Solver/FailedLitSearcher.cpp768
-rw-r--r--src/prop/cryptominisat/Solver/FailedLitSearcher.h246
-rw-r--r--src/prop/cryptominisat/Solver/Gaussian.cpp1147
-rw-r--r--src/prop/cryptominisat/Solver/Gaussian.h243
-rw-r--r--src/prop/cryptominisat/Solver/GaussianConfig.h63
-rw-r--r--src/prop/cryptominisat/Solver/Main.cpp974
-rw-r--r--src/prop/cryptominisat/Solver/Main.h74
-rw-r--r--src/prop/cryptominisat/Solver/Makefile.am33
-rw-r--r--src/prop/cryptominisat/Solver/Makefile.in665
-rw-r--r--src/prop/cryptominisat/Solver/MatrixFinder.cpp248
-rw-r--r--src/prop/cryptominisat/Solver/MatrixFinder.h70
-rw-r--r--src/prop/cryptominisat/Solver/OnlyNonLearntBins.cpp84
-rw-r--r--src/prop/cryptominisat/Solver/OnlyNonLearntBins.h72
-rw-r--r--src/prop/cryptominisat/Solver/PackedMatrix.h221
-rw-r--r--src/prop/cryptominisat/Solver/PackedRow.cpp109
-rw-r--r--src/prop/cryptominisat/Solver/PackedRow.h252
-rw-r--r--src/prop/cryptominisat/Solver/PropBy.h257
-rw-r--r--src/prop/cryptominisat/Solver/RestartTypeChooser.cpp181
-rw-r--r--src/prop/cryptominisat/Solver/RestartTypeChooser.h81
-rw-r--r--src/prop/cryptominisat/Solver/SCCFinder.cpp142
-rw-r--r--src/prop/cryptominisat/Solver/SCCFinder.h72
-rw-r--r--src/prop/cryptominisat/Solver/SharedData.h37
-rw-r--r--src/prop/cryptominisat/Solver/Solver.cpp2924
-rw-r--r--src/prop/cryptominisat/Solver/Solver.h859
-rw-r--r--src/prop/cryptominisat/Solver/SolverConf.cpp91
-rw-r--r--src/prop/cryptominisat/Solver/SolverConf.h102
-rw-r--r--src/prop/cryptominisat/Solver/SolverDebug.cpp253
-rw-r--r--src/prop/cryptominisat/Solver/SolverMisc.cpp713
-rw-r--r--src/prop/cryptominisat/Solver/SolverTypes.h244
-rw-r--r--src/prop/cryptominisat/Solver/StateSaver.cpp50
-rw-r--r--src/prop/cryptominisat/Solver/StateSaver.h44
-rw-r--r--src/prop/cryptominisat/Solver/StreamBuffer.h78
-rw-r--r--src/prop/cryptominisat/Solver/Subsumer.cpp2141
-rw-r--r--src/prop/cryptominisat/Solver/Subsumer.h500
-rw-r--r--src/prop/cryptominisat/Solver/UselessBinRemover.cpp228
-rw-r--r--src/prop/cryptominisat/Solver/UselessBinRemover.h85
-rw-r--r--src/prop/cryptominisat/Solver/VarReplacer.cpp731
-rw-r--r--src/prop/cryptominisat/Solver/VarReplacer.h153
-rw-r--r--src/prop/cryptominisat/Solver/Watched.h278
-rw-r--r--src/prop/cryptominisat/Solver/XSet.h134
-rw-r--r--src/prop/cryptominisat/Solver/XorFinder.cpp462
-rw-r--r--src/prop/cryptominisat/Solver/XorFinder.h157
-rw-r--r--src/prop/cryptominisat/Solver/XorSubsumer.cpp622
-rw-r--r--src/prop/cryptominisat/Solver/XorSubsumer.h185
-rw-r--r--src/prop/cryptominisat/Solver/constants.h137
-rw-r--r--src/prop/cryptominisat/Solver/msvc/stdint.h246
-rw-r--r--src/prop/cryptominisat/Solver/time_mem.h102
67 files changed, 21353 insertions, 0 deletions
diff --git a/src/prop/cryptominisat/Solver/BitArray.h b/src/prop/cryptominisat/Solver/BitArray.h
new file mode 100644
index 000000000..2b67998ae
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/BitArray.h
@@ -0,0 +1,188 @@
+/***********************************************************************************
+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 BITARRAY_H
+#define BITARRAY_H
+
+//#define DEBUG_BITARRAY
+
+#include <string.h>
+#include <assert.h>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+namespace CMSat
+{
+
+class BitArray
+{
+public:
+ BitArray() :
+ size(0)
+ , mp(NULL)
+ {
+ }
+
+ BitArray(const BitArray& b) :
+ size(b.size)
+ {
+ mp = new uint64_t[size];
+ memcpy(mp, b.mp, sizeof(uint64_t)*size);
+ }
+
+ BitArray& operator=(const BitArray& b)
+ {
+ if (size != b.size) {
+ delete[] mp;
+ size = b.size;
+ mp = new uint64_t[size];
+ }
+ memcpy(mp, b.mp, sizeof(uint64_t)*size);
+
+ return *this;
+ }
+
+ BitArray& operator&=(const BitArray& b)
+ {
+ assert(size == b.size);
+ uint64_t* t1 = mp;
+ uint64_t* t2 = b.mp;
+ for (uint64_t i = 0; i < size; i++) {
+ *t1 &= *t2;
+ t1++;
+ t2++;
+ }
+
+ return *this;
+ }
+
+ BitArray& removeThese(const BitArray& b)
+ {
+ assert(size == b.size);
+ uint64_t* t1 = mp;
+ uint64_t* t2 = b.mp;
+ for (uint64_t i = 0; i < size; i++) {
+ *t1 &= ~(*t2);
+ t1++;
+ t2++;
+ }
+
+ return *this;
+ }
+
+ template<class T>
+ BitArray& removeThese(const T& rem)
+ {
+ for (uint32_t i = 0; i < rem.size(); i++) {
+ clearBit(rem[i]);
+ }
+
+ return *this;
+ }
+
+ template<class T>
+ BitArray& removeTheseLit(const T& rem)
+ {
+ for (uint32_t i = 0; i < rem.size(); i++) {
+ clearBit(rem[i].var());
+ }
+
+ return *this;
+ }
+
+ void resize(uint32_t _size, const bool fill)
+ {
+ _size = _size/64 + (bool)(_size%64);
+ if (size != _size) {
+ delete[] mp;
+ size = _size;
+ mp = new uint64_t[size];
+ }
+ if (fill) setOne();
+ else setZero();
+ }
+
+ ~BitArray()
+ {
+ delete[] mp;
+ }
+
+ inline bool isZero() const
+ {
+ const uint64_t* mp2 = (const uint64_t*)mp;
+
+ for (uint32_t i = 0; i < size; i++) {
+ if (mp2[i]) return false;
+ }
+ return true;
+ }
+
+ inline void setZero()
+ {
+ memset(mp, 0, size*sizeof(uint64_t));
+ }
+
+ inline void setOne()
+ {
+ memset(mp, 0xff, size*sizeof(uint64_t));
+ }
+
+ 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 uint32_t i)
+ {
+ #ifdef DEBUG_BITARRAY
+ assert(size*64 > i);
+ #endif
+
+ mp[i/64] |= ((uint64_t)1 << (i%64));
+ }
+
+ inline bool operator[](const uint32_t& i) const
+ {
+ #ifdef DEBUG_BITARRAY
+ assert(size*64 > i);
+ #endif
+
+ return (mp[i/64] >> (i%64)) & 1;
+ }
+
+ inline uint32_t getSize() const
+ {
+ return size*64;
+ }
+
+private:
+
+ uint32_t size;
+ uint64_t* mp;
+};
+
+}
+
+#endif //BITARRAY_H
+
diff --git a/src/prop/cryptominisat/Solver/BothCache.cpp b/src/prop/cryptominisat/Solver/BothCache.cpp
new file mode 100644
index 000000000..3ffc78f7e
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/BothCache.cpp
@@ -0,0 +1,114 @@
+/***************************************************************************
+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 "BothCache.h"
+#include "time_mem.h"
+#include <iomanip>
+#include "VarReplacer.h"
+#include "Subsumer.h"
+#include "XorSubsumer.h"
+
+namespace CMSat {
+
+BothCache::BothCache(Solver& _solver) :
+ solver(_solver)
+{}
+
+bool BothCache::tryBoth()
+{
+ vec<bool> seen(solver.nVars(), 0);
+ vec<bool> val(solver.nVars(), 0);
+ vec<Lit> tmp;
+ uint32_t bProp = 0;
+ uint32_t bXProp = 0;
+ double myTime = cpuTime();
+ uint32_t backupTrailSize = solver.trail.size();
+
+ for (Var var = 0; var < solver.nVars(); var++) {
+ if (solver.value(var) != l_Undef
+ || solver.subsumer->getVarElimed()[var]
+ || solver.xorSubsumer->getVarElimed()[var]
+ || solver.varReplacer->getReplaceTable()[var].var() != var)
+ continue;
+
+ Lit lit = Lit(var, false);
+ vector<Lit> const* cache1;
+ vector<Lit> const* cache2;
+
+ bool startWithTrue;
+ if (solver.transOTFCache[lit.toInt()].lits.size() < solver.transOTFCache[(~lit).toInt()].lits.size()) {
+ cache1 = &solver.transOTFCache[lit.toInt()].lits;
+ cache2 = &solver.transOTFCache[(~lit).toInt()].lits;
+ startWithTrue = false;
+ } else {
+ cache1 = &solver.transOTFCache[(~lit).toInt()].lits;
+ cache2 = &solver.transOTFCache[lit.toInt()].lits;
+ startWithTrue = true;
+ }
+
+ if (cache1->size() == 0) continue;
+
+ for (vector<Lit>::const_iterator it = cache1->begin(), end = cache1->end(); it != end; it++) {
+ seen[it->var()] = true;
+ val[it->var()] = it->sign();
+ }
+
+ for (vector<Lit>::const_iterator it = cache2->begin(), end = cache2->end(); it != end; it++) {
+ if (seen[it->var()]) {
+ Var var2 = it->var();
+ if (solver.subsumer->getVarElimed()[var2]
+ || solver.xorSubsumer->getVarElimed()[var2]
+ || solver.varReplacer->getReplaceTable()[var2].var() != var2)
+ continue;
+
+ if (val[it->var()] == it->sign()) {
+ tmp.clear();
+ tmp.push(*it);
+ solver.addClauseInt(tmp, true);
+ if (!solver.ok) goto end;
+ bProp++;
+ } else {
+ tmp.clear();
+ tmp.push(Lit(var, false));
+ tmp.push(Lit(it->var(), false));
+ bool sign = true ^ startWithTrue ^ it->sign();
+ solver.addXorClauseInt(tmp, sign);
+ if (!solver.ok) goto end;
+ bXProp++;
+ }
+ }
+ }
+
+ for (vector<Lit>::const_iterator it = cache1->begin(), end = cache1->end(); it != end; it++) {
+ seen[it->var()] = false;
+ }
+ }
+
+ end:
+ if (solver.conf.verbosity >= 1) {
+ std::cout << "c Cache " <<
+ " BProp: " << bProp <<
+ " Set: " << (solver.trail.size() - backupTrailSize) <<
+ " BXProp: " << bXProp <<
+ " T: " << (cpuTime() - myTime) <<
+ std::endl;
+ }
+
+ return solver.ok;
+}
+
+}
diff --git a/src/prop/cryptominisat/Solver/BothCache.h b/src/prop/cryptominisat/Solver/BothCache.h
new file mode 100644
index 000000000..72457319d
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/BothCache.h
@@ -0,0 +1,20 @@
+#ifndef BOTHCACHE_H
+#define BOTHCACHE_H
+
+#include "Solver.h"
+
+namespace CMSat {
+
+class BothCache
+{
+ public:
+ BothCache(Solver& solver);
+ bool tryBoth();
+
+ private:
+ Solver& solver;
+};
+
+}
+
+#endif //BOTHCACHE_H
diff --git a/src/prop/cryptominisat/Solver/BoundedQueue.h b/src/prop/cryptominisat/Solver/BoundedQueue.h
new file mode 100644
index 000000000..f7f40c158
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/BoundedQueue.h
@@ -0,0 +1,96 @@
+/*****************************************************************************************[Queue.h]
+MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+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
+
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include "Vec.h"
+
+namespace CMSat {
+
+template <class T>
+class bqueue {
+ vec<T> elems;
+ 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)
+ , 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
+ queuesize++;
+ sumofqueue += x;
+ sumOfAllElems += x;
+ totalNumElems++;
+ elems[first] = x;
+ if ((++first) == maxsize) first = 0;
+ }
+
+ const T peek() const { assert(queuesize>0); return elems[last]; }
+ void pop() {sumofqueue-=elems[last]; queuesize--; if ((++last) == maxsize) last = 0;}
+
+ 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(const uint32_t size) {
+ elems.growTo(size);
+ first=0; maxsize=size; queuesize = 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;
+ last = 0;
+ maxsize=0;
+ queuesize=0;
+ sumofqueue=0;
+
+ totalNumElems = 0;
+ sumOfAllElems = 0;
+ }
+};
+
+}
+
+#endif //BOUNDEDQUEUE_H
diff --git a/src/prop/cryptominisat/Solver/CSet.h b/src/prop/cryptominisat/Solver/CSet.h
new file mode 100644
index 000000000..de06ea38f
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/CSet.h
@@ -0,0 +1,209 @@
+/**************************************************************************************************
+From: Solver.C -- (C) Niklas Een, Niklas Sorensson, 2004
+**************************************************************************************************/
+
+#ifndef CSET_H
+#define CSET_H
+
+#include "Vec.h"
+#include <limits>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+namespace CMSat {
+
+class Clause;
+
+/**
+@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:
+ ClauseSimp(Clause* c, const uint32_t _index) :
+ clause(c)
+ , index(_index)
+ {}
+
+ Clause* clause; ///<The clause to be stored
+ uint32_t index; ///<The index of the clause in Subsumer::clauses
+};
+
+/**
+@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'.
+
+ 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(); }
+ ///@brief Number of elements in the set
+ uint32_t nElems(void) const { return which.size() - free.size(); }
+
+ /**
+ @brief Add a clause to the set
+ */
+ 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 false;
+ }
+ if (free.size() > 0){
+ where[c.index] = free.last();
+ which[free.last()] = c;
+ free.pop();
+ }else{
+ where[c.index] = which.size();
+ which.push(c);
+ }
+ return true;
+ }
+
+ 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()) {
+ //not inside
+ return false;
+ }
+ free.push(where[c.index]);
+ which[where[c.index]].clause = NULL;
+ where[c.index] = std::numeric_limits<uint32_t>::max();
+ return true;
+ }
+
+ /**
+ @brief Fully clear the set
+ */
+ void clear(void) {
+ for (uint32_t i = 0; i < which.size(); i++) {
+ if (which[i].clause != NULL) {
+ where[which[i].index] = std::numeric_limits<uint32_t>::max();
+ }
+ }
+ which.clear();
+ free.clear();
+ }
+
+ /**
+ @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++;
+ }
+
+ 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++;
+ }
+
+ 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
+
diff --git a/src/prop/cryptominisat/Solver/Clause.h b/src/prop/cryptominisat/Solver/Clause.h
new file mode 100644
index 000000000..e47857add
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/Clause.h
@@ -0,0 +1,344 @@
+/*****************************************************************************
+MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+glucose -- Gilles Audemard, Laurent Simon (2008)
+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 CLAUSE_H
+#define CLAUSE_H
+
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include <cstdio>
+#include <vector>
+#include <sys/types.h>
+#include <string.h>
+
+#include "SolverTypes.h"
+#include "constants.h"
+#include "Watched.h"
+#include "Alg.h"
+#include "constants.h"
+
+namespace CMSat {
+
+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].var() & 31);
+ return abstraction;
+}
+
+class MatrixFinder;
+class ClauseAllocator;
+
+/**
+@brief Holds a clause. Does not allocate space for literals
+
+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 changed:1; ///<Var inside clause has been changed
+ /**
+ @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:18; ///<The current size of the clause
+
+ float miniSatAct; ///<Clause activity according to MiniSat
+
+ uint32_t abst; //Abstraction of clause
+
+#ifdef _MSC_VER
+public:
+#endif //_MSC_VER
+ template<class V>
+ Clause(const V& ps, const bool learnt)
+ {
+ isFreed = false;
+ glue = 0; //To stop valgrind from complaining
+ isXorEqualFalse = false; //To stop valgrind from complaining
+ isXorClause = false;
+ assert(ps.size() > 2);
+ mySize = ps.size();
+ isLearnt = learnt;
+ isRemoved = false;
+
+ assert(ps.size() > 0);
+ memcpy(getData(), ps.getData(), ps.size()*sizeof(Lit));
+ miniSatAct = 0;
+ setChanged();
+ }
+
+public:
+ friend class ClauseAllocator;
+
+ uint32_t size() const
+ {
+ return mySize;
+ }
+
+ bool getChanged() const
+ {
+ return changed;
+ }
+
+ void setChanged()
+ {
+ changed = 1;
+ }
+
+ void unsetChanged()
+ {
+ changed = 0;
+ }
+
+ void shrink (const uint32_t i)
+ {
+ assert(i <= size());
+ mySize -= i;
+ if (i > 0)
+ setChanged();
+ }
+
+ void pop()
+ {
+ shrink(1);
+ }
+
+ bool isXor() const
+ {
+ return isXorClause;
+ }
+
+ bool learnt() const
+ {
+ return isLearnt;
+ }
+
+ float& getMiniSatAct()
+ {
+ return miniSatAct;
+ }
+
+ void setMiniSatAct(const float newMiniSatAct)
+ {
+ miniSatAct = newMiniSatAct;
+ }
+
+ const float& getMiniSatAct() const
+ {
+ return miniSatAct;
+ }
+
+ Lit& operator [] (const uint32_t i)
+ {
+ return *(getData() + i);
+ }
+
+ const Lit& operator [] (const uint32_t i) const
+ {
+ return *(getData() + i);
+ }
+
+ void setGlue(const uint32_t newGlue)
+ {
+ assert(newGlue <= MAX_THEORETICAL_GLUE);
+ glue = newGlue;
+ }
+
+ uint32_t getGlue() const
+ {
+ return glue;
+ }
+
+ void makeNonLearnt()
+ {
+ assert(isLearnt);
+ isLearnt = false;
+ }
+
+ void makeLearnt(const uint32_t newGlue, const float newMiniSatAct)
+ {
+ glue = newGlue;
+ miniSatAct = newMiniSatAct;
+ isLearnt = true;
+ }
+
+ inline void strengthen(const Lit p)
+ {
+ remove(*this, p);
+ setChanged();
+ }
+
+ void calcAbstractionClause()
+ {
+ abst = calcAbstraction(*this);
+ }
+
+ uint32_t getAbst() const
+ {
+ return abst;
+ }
+
+ const Lit* getData() const
+ {
+ return (Lit*)((char*)this + sizeof(Clause));
+ }
+
+ Lit* getData()
+ {
+ return (Lit*)((char*)this + sizeof(Clause));
+ }
+
+ const Lit* getDataEnd() const
+ {
+ return getData()+size();
+ }
+
+ Lit* getDataEnd()
+ {
+ return getData() + size();
+ }
+
+ void print(FILE* to = stdout) const
+ {
+ plainPrint(to);
+ fprintf(to, "c clause learnt %s glue %d miniSatAct %.3f\n", (learnt() ? "yes" : "no"), getGlue(), getMiniSatAct());
+ }
+
+ void plainPrint(FILE* to = stdout) const
+ {
+ for (uint32_t i = 0; i < size(); i++) {
+ if ((getData()+i)->sign()) fprintf(to, "-");
+ fprintf(to, "%d ", (getData()+i)->var() + 1);
+ }
+ fprintf(to, "0\n");
+ }
+
+ void setRemoved()
+ {
+ isRemoved = true;
+ }
+
+ bool getRemoved() const
+ {
+ return isRemoved;
+ }
+
+ void setFreed()
+ {
+ isFreed = true;
+ }
+
+ bool getFreed() const
+ {
+ return isFreed;
+ }
+
+ 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 xorEqualFalse) :
+ Clause(ps, false)
+ {
+ isXorEqualFalse = xorEqualFalse;
+ isXorClause = true;
+ }
+
+public:
+ friend class ClauseAllocator;
+
+ inline bool xorEqualFalse() const
+ {
+ return isXorEqualFalse;
+ }
+
+ inline void invert(const bool b)
+ {
+ isXorEqualFalse ^= b;
+ }
+
+ void print(FILE* to = stdout) const
+ {
+ plainPrint(to);
+ fprintf(to, "c clause learnt %s glue %d miniSatAct %.3f\n", (learnt() ? "yes" : "no"), getGlue(), getMiniSatAct());
+ }
+
+ void plainPrint(FILE* to = stdout) const
+ {
+ fprintf(to, "x");
+ if (xorEqualFalse())
+ fprintf(to, "-");
+ for (uint32_t i = 0; i < size(); i++) {
+ fprintf(to, "%d ", this->operator[](i).var() + 1);
+ }
+ fprintf(to, "0\n");
+ }
+
+ friend class MatrixFinder;
+};
+
+inline std::ostream& operator<<(std::ostream& cout, const Clause& cl)
+{
+ for (uint32_t i = 0; i < cl.size(); i++) {
+ cout << cl[i] << " ";
+ }
+ return cout;
+}
+
+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;
+}
+
+}
+
+#endif //CLAUSE_H
diff --git a/src/prop/cryptominisat/Solver/ClauseAllocator.cpp b/src/prop/cryptominisat/Solver/ClauseAllocator.cpp
new file mode 100644
index 000000000..f1576e7fe
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/ClauseAllocator.cpp
@@ -0,0 +1,572 @@
+/***********************************************************************
+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 "ClauseAllocator.h"
+
+#include <string.h>
+#include <limits>
+#include "assert.h"
+#include "SolverTypes.h"
+#include "Clause.h"
+#include "Solver.h"
+#include "time_mem.h"
+#include "Subsumer.h"
+#include "XorSubsumer.h"
+//#include "VarReplacer.h"
+#include "Gaussian.h"
+
+#ifndef _MSC_VER
+#include <sys/mman.h>
+#endif //_MSC_VER
+
+
+//For mild debug info:
+//#define DEBUG_CLAUSEALLOCATOR
+
+//For listing each and every clause location:
+//#define DEBUG_CLAUSEALLOCATOR2
+
+#define MIN_LIST_SIZE (300000 * (sizeof(Clause) + 4*sizeof(Lit))/sizeof(BASE_DATA_TYPE))
+//#define MIN_LIST_SIZE (100 * (sizeof(Clause) + 4*sizeof(Lit))/sizeof(BASE_DATA_TYPE))
+#define ALLOC_GROW_MULT 8
+//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)
+
+using namespace CMSat;
+
+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]);
+ }
+}
+
+/**
+@brief Allocates space&initializes a clause
+*/
+template<class T>
+Clause* ClauseAllocator::Clause_new(const T& ps, const bool learnt)
+{
+ assert(ps.size() > 2);
+ void* mem = allocEnough(ps.size());
+ Clause* real= new (mem) Clause(ps, learnt);
+ //assert(!(ps.size() == 2 && !real->wasBin()));
+
+ return real;
+}
+
+template Clause* ClauseAllocator::Clause_new(const vec<Lit>& ps, const bool learnt);
+template Clause* ClauseAllocator::Clause_new(const Clause& ps, const bool learnt);
+template Clause* ClauseAllocator::Clause_new(const XorClause& ps, const bool learnt);
+
+/**
+@brief Allocates space&initializes an xor clause
+*/
+template<class T>
+XorClause* ClauseAllocator::XorClause_new(const T& ps, const bool xorEqualFalse)
+{
+ assert(ps.size() > 2);
+ void* mem = allocEnough(ps.size());
+ XorClause* real= new (mem) XorClause(ps, xorEqualFalse);
+
+ return real;
+}
+template XorClause* ClauseAllocator::XorClause_new(const vec<Lit>& ps, const bool inverted);
+template XorClause* ClauseAllocator::XorClause_new(const XorClause& ps, const bool inverted);
+
+/**
+@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());
+
+ return (Clause*)mem;
+}
+
+/**
+@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) throw (std::bad_alloc)
+{
+ assert(sizes.size() == dataStarts.size());
+ assert(maxSizes.size() == dataStarts.size());
+ assert(origClauseSizes.size() == dataStarts.size());
+
+ assert(size > 2 && "Clause size cannot be 2 or less, those are stored natively");
+
+ const uint32_t needed = sizeof(Clause) + sizeof(Lit)*size;
+ bool found = false;
+ uint32_t which = std::numeric_limits<uint32_t>::max();
+ for (uint32_t i = 0; i < sizes.size(); i++) {
+ if (sizes[i] + needed < maxSizes[i]) {
+ found = true;
+ which = i;
+ break;
+ }
+ }
+
+ if (!found) {
+ //Checking whether we are out of memory, because the offset that we can
+ //store is too little
+ if (dataStarts.size() == (1<<NUM_BITS_OUTER_OFFSET))
+ throw std::bad_alloc();
+
+ uint32_t nextSize; //number of BYTES to allocate
+ 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);
+ assert(nextSize <= MAXSIZE);
+
+ #ifdef DEBUG_CLAUSEALLOCATOR
+ std::cout << "c New list in ClauseAllocator. Size: " << nextSize
+ << " (maxSize: " << MAXSIZE
+ << ")" << std::endl;
+ #endif //DEBUG_CLAUSEALLOCATOR
+
+ BASE_DATA_TYPE *dataStart;
+ dataStart = (BASE_DATA_TYPE *)malloc(sizeof(BASE_DATA_TYPE) * nextSize);
+
+ dataStarts.push(dataStart);
+ sizes.push(0);
+ maxSizes.push(nextSize);
+ origClauseSizes.push();
+ currentlyUsedSizes.push(0);
+ which = dataStarts.size()-1;
+ }
+ #ifdef DEBUG_CLAUSEALLOCATOR2
+ std::cout
+ << "selected list = " << which
+ << " size = " << sizes[which]
+ << " maxsize = " << maxSizes[which]
+ << " diff = " << maxSizes[which] - sizes[which] << std::endl;
+ #endif //DEBUG_CLAUSEALLOCATOR
+
+ assert(which != std::numeric_limits<uint32_t>::max());
+ Clause* pointer = (Clause*)(dataStarts[which] + sizes[which]);
+ 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
+*/
+ClauseOffset ClauseAllocator::getOffset(const Clause* ptr) const
+{
+ uint32_t outerOffset = getOuterOffset(ptr);
+ uint32_t interOffset = getInterOffset(ptr, outerOffset);
+ return combineOuterInterOffsets(outerOffset, interOffset);
+}
+
+/**
+@brief Combines the stack number and the internal offset into one 32-bit number
+*/
+inline ClauseOffset ClauseAllocator::combineOuterInterOffsets(const uint32_t outerOffset, const uint32_t interOffset) const
+{
+ 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 ((BASE_DATA_TYPE*)ptr >= dataStarts[i] && (BASE_DATA_TYPE*)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 ((BASE_DATA_TYPE*)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)
+{
+ assert(!c->getFreed());
+
+ c->setFreed();
+ uint32_t outerOffset = getOuterOffset(c);
+ //uint32_t interOffset = getInterOffset(c, outerOffset);
+ currentlyUsedSizes[outerOffset] -= sizeof(Clause) + c->size()*sizeof(Lit);
+ //above should be
+ //origClauseSizes[outerOffset][interOffset]
+ //but it cannot be :(
+}
+
+/**
+@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, const bool force) throw (std::bad_alloc)
+{
+ double myTime = cpuTime();
+ #ifdef DEBUG_PROPAGATEFROM
+ checkGoodPropBy(solver);
+ #endif
+
+ uint32_t sum = 0;
+ for (uint32_t i = 0; i < sizes.size(); i++) {
+ sum += currentlyUsedSizes[i];
+ }
+ uint32_t sumAlloc = 0;
+ for (uint32_t i = 0; i < sizes.size(); i++) {
+ sumAlloc += sizes[i];
+ }
+
+ #ifdef DEBUG_CLAUSEALLOCATOR
+ std::cout << "c ratio:" << (double)sum/(double)sumAlloc << std::endl;
+ #endif //DEBUG_CLAUSEALLOCATOR
+
+ //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 (!force
+ && ((double)sum/(double)sumAlloc > 0.7 && sizes.size() < 10)
+ ) {
+ if (solver->conf.verbosity >= 3) {
+ std::cout << "c Not consolidating memory." << std::endl;
+ }
+ return;
+ }
+
+ #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
+ }
+ #ifdef DEBUG_CLAUSEALLOCATOR
+ std::cout << "c ------------------" << std::endl;
+ #endif //DEBUG_CLAUSEALLOCATOR
+
+ if (newMaxSizeNeed > 0)
+ throw std::bad_alloc();
+
+ vec<uint32_t> newSizes;
+ vec<vec<uint32_t> > newOrigClauseSizes;
+ vec<BASE_DATA_TYPE*> newDataStartsPointers;
+ vec<BASE_DATA_TYPE*> newDataStarts;
+ for (uint32_t i = 0; i < newMaxSizes.size(); i++) {
+ newSizes.push(0);
+ newOrigClauseSizes.push();
+ BASE_DATA_TYPE* pointer;
+ pointer = (BASE_DATA_TYPE*)malloc(newMaxSizes[i]);
+ newDataStartsPointers.push(pointer);
+ newDataStarts.push(pointer);
+ }
+
+ vector<Clause*> clauses;
+ 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()) {
+ clauses.push_back(oldPointer);
+ } else {
+ (*((NewPointerAndOffset*)(oldPointer))).newOffset = std::numeric_limits<uint32_t>::max();
+ }
+ currentLoc += origClauseSizes[i][i2];
+ }
+ }
+
+ putClausesIntoDatastruct(clauses);
+
+ uint32_t outerPart = 0;
+ //uint64_t skippedNum = 0;
+ for (uint32_t i = 0; i < clauses.size(); i++) {
+ Clause* clause = getClause();
+
+ uint32_t sizeNeeded = (sizeof(Clause) + clause->size()*sizeof(Lit))/sizeof(BASE_DATA_TYPE);
+
+ //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(BASE_DATA_TYPE)));
+
+ if (newSizes[outerPart] + sizeNeeded > newMaxSizes[outerPart]) {
+ outerPart++;
+ assert(outerPart < newMaxSizes.size());
+ }
+ memcpy(newDataStartsPointers[outerPart], (BASE_DATA_TYPE*)clause, sizeNeeded*sizeof(BASE_DATA_TYPE));
+
+ NewPointerAndOffset& ptr = *((NewPointerAndOffset*)clause);
+ ptr.newOffset = combineOuterInterOffsets(outerPart, newSizes[outerPart]);
+ ptr.newPointer = (Clause*)newDataStartsPointers[outerPart];
+
+ newSizes[outerPart] += sizeNeeded;
+ newOrigClauseSizes[outerPart].push(sizeNeeded);
+ newDataStartsPointers[outerPart] += sizeNeeded;
+ }
+
+ updateAllOffsetsAndPointers(solver);
+
+ for (uint32_t i = 0; i < dataStarts.size(); i++)
+ free(dataStarts[i]);
+
+ dataStarts.clear();
+ maxSizes.clear();
+ sizes.clear();
+ origClauseSizes.clear();
+ currentlyUsedSizes.clear();
+ origClauseSizes.clear();
+
+ 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;
+ }
+}
+
+void ClauseAllocator::putClausesIntoDatastruct(std::vector<Clause*>& clauses)
+{
+ otherClauses.clear();
+ threeLongClauses.clear();
+ for (uint32_t i = 0; i < clauses.size(); i++) {
+ Clause* c = clauses[i];
+ if (c->size() <= 3) {
+ threeLongClauses.push_back(c);
+ } else {
+ otherClauses.push_back(c);
+ }
+ }
+}
+
+Clause* ClauseAllocator::getClause()
+{
+ if (!threeLongClauses.empty()) {
+ Clause* tmp = threeLongClauses[threeLongClauses.size()-1];
+ threeLongClauses.pop_back();
+ return tmp;
+ }
+
+ assert(!otherClauses.empty());
+ Clause* tmp = otherClauses[otherClauses.size()-1];
+ otherClauses.pop_back();
+ return tmp;
+}
+
+void ClauseAllocator::checkGoodPropBy(const Solver* solver)
+{
+ const vec<PropBy>& reason = solver->reason;
+ Var var = 0;
+ for (const 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
+ ) {
+ continue;
+ }
+
+ if (it->isClause() && !it->isNULL()) {
+ assert(!getPointer(it->getClause())->getFreed());
+ assert(!getPointer(it->getClause())->getRemoved());
+ }
+ }
+}
+
+
+void ClauseAllocator::updateAllOffsetsAndPointers(Solver* solver)
+{
+ updateOffsets(solver->watches);
+
+ updatePointers(solver->clauses);
+ updatePointers(solver->learnts);
+ updatePointers(solver->xorclauses);
+ updatePointers(solver->freeLater);
+ #ifdef ENABLE_UNWIND_GLUE
+ updatePointers(solver->unWindGlue);
+ #endif //ENABLE_UNWIND_GLUE
+
+ //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);
+
+ #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);
+ }
+ }
+}
+
+/**
+@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<Watched>& list = watches[i];
+ for (vec<Watched>::iterator 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)
+{
+ for (T **it = toUpdate.getData(), **end = toUpdate.getDataEnd(); it != end; it++) {
+ if (*it != NULL) {
+ *it = (T*)(((NewPointerAndOffset*)(*it))->newPointer);
+ }
+ }
+}
+
+/**
+@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++) {
+ *it = (((NewPointerAndOffset*)(*it))->newPointer);
+ }
+}
+
+/**
+@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++) {
+ *it = (XorClause*)(((NewPointerAndOffset*)(*it))->newPointer);
+ }
+}
+
+/**
+@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);
+ }
+}
diff --git a/src/prop/cryptominisat/Solver/ClauseAllocator.h b/src/prop/cryptominisat/Solver/ClauseAllocator.h
new file mode 100644
index 000000000..d20c1617b
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/ClauseAllocator.h
@@ -0,0 +1,146 @@
+/***********************************************************************
+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 CLAUSEALLOCATOR_H
+#define CLAUSEALLOCATOR_H
+
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include <stdlib.h>
+#include "Vec.h"
+#include <map>
+#include <vector>
+
+#include "ClauseOffset.h"
+#include "Watched.h"
+
+#define NUM_BITS_OUTER_OFFSET 4
+#define BASE_DATA_TYPE char
+
+namespace CMSat {
+
+using std::map;
+using std::vector;
+
+class Clause;
+class XorClause;
+class Solver;
+
+/**
+@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 bool learnt = false);
+ template<class T>
+ XorClause* XorClause_new(const T& ps, const bool xorEqualFalse);
+ Clause* Clause_new(Clause& c);
+
+ ClauseOffset getOffset(const Clause* ptr) const;
+
+ /**
+ @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&((1 << NUM_BITS_OUTER_OFFSET) - 1)]
+ +(offset >> NUM_BITS_OUTER_OFFSET));
+ }
+
+ void clauseFree(Clause* c);
+
+ void consolidate(Solver* solver, const bool force = false) throw (std::bad_alloc);
+
+ uint32_t getNewClauseNum();
+
+ private:
+ uint32_t getOuterOffset(const Clause* c) const;
+ uint32_t getInterOffset(const Clause* c, const uint32_t outerOffset) const;
+ ClauseOffset combineOuterInterOffsets(const uint32_t outerOffset, const uint32_t interOffset) const;
+
+ void updateAllOffsetsAndPointers(Solver* solver);
+ template<class T>
+ 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);
+ void checkGoodPropBy(const Solver* solver);
+
+ void releaseClauseNum(const uint32_t num);
+
+ vec<BASE_DATA_TYPE*> 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; ///<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) throw (std::bad_alloc);
+
+ /**
+ @brief The clause's data is replaced by this to aid updating
+
+ 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
+ };
+
+ vector<Clause*> otherClauses;
+ vector<Clause*> threeLongClauses;
+ Clause* getClause();
+ void putClausesIntoDatastruct(std::vector<Clause*>& clauses);
+};
+
+}
+
+#endif //CLAUSEALLOCATOR_H
diff --git a/src/prop/cryptominisat/Solver/ClauseCleaner.cpp b/src/prop/cryptominisat/Solver/ClauseCleaner.cpp
new file mode 100644
index 000000000..47dd675f4
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/ClauseCleaner.cpp
@@ -0,0 +1,261 @@
+/***************************************************************************
+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 "ClauseCleaner.h"
+#include "VarReplacer.h"
+#include "DataSync.h"
+
+//#define DEBUG_CLEAN
+//#define VERBOSE_DEBUG
+
+using namespace CMSat;
+
+ClauseCleaner::ClauseCleaner(Solver& _solver) :
+ solver(_solver)
+{
+ for (uint32_t i = 0; i < 6; i++) {
+ lastNumUnitarySat[i] = solver.get_unitary_learnts_num();
+ lastNumUnitaryClean[i] = solver.get_unitary_learnts_num();
+ }
+}
+
+bool ClauseCleaner::satisfied(const Watched& watched, Lit lit)
+{
+ assert(watched.isBinary());
+ if (solver.value(lit) == l_True) return true;
+ if (solver.value(watched.getOtherLit()) == l_True) return true;
+ return false;
+}
+
+void ClauseCleaner::removeSatisfiedBins(const uint32_t limit)
+{
+ #ifdef DEBUG_CLEAN
+ assert(solver.decisionLevel() == 0);
+ #endif
+
+ if (lastNumUnitarySat[binaryClauses] + limit >= solver.get_unitary_learnts_num())
+ return;
+
+ 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;
+
+ vec<Watched>::iterator i = ws.getData();
+ vec<Watched>::iterator j = i;
+ for (vec<Watched>::iterator 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);
+ }
+
+ //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 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; s++) {
+ if (s+1 != end) __builtin_prefetch(*(s+1));
+
+ if (cleanClause(*s)) {
+ solver.clauseAllocator.clauseFree(*s);
+ } else {
+ *ss++ = *s;
+ }
+ }
+ cs.shrink(s-ss);
+
+ lastNumUnitaryClean[type] = solver.get_unitary_learnts_num();
+
+ #ifdef VERBOSE_DEBUG
+ cout << "cleanClauses(Clause) useful ?? Removed: " << s-ss << endl;
+ #endif
+}
+
+inline 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);
+ if (val == l_Undef) {
+ *j++ = *i;
+ continue;
+ }
+
+ if (val == l_True) {
+ solver.detachModifiedClause(origLit1, origLit2, origLit3, origSize, &c);
+ return true;
+ }
+ }
+ c.shrink(i-j);
+
+ assert(c.size() != 1);
+ if (i != j) {
+ if (c.size() == 2) {
+ 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;
+ else
+ solver.clauses_literals -= i-j;
+ }
+ }
+
+ return false;
+}
+
+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_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_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
+}
+
+inline bool ClauseCleaner::cleanClause(XorClause& c)
+{
+ Lit *i, *j, *end;
+ Var origVar1 = c[0].var();
+ Var origVar2 = c[1].var();
+ uint32_t origSize = c.size();
+ for (i = j = c.getData(), end = i + c.size(); i != end; i++) {
+ const lbool& val = solver.assigns[i->var()];
+ if (val.isUndef()) {
+ *j = *i;
+ j++;
+ } else c.invert(val.getBool());
+ }
+ c.shrink(i-j);
+
+ assert(c.size() != 1);
+ switch (c.size()) {
+ case 0: {
+ solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
+ return true;
+ }
+ case 2: {
+ c[0] = c[0].unsign();
+ c[1] = c[1].unsign();
+ solver.varReplacer->replace(c, c.xorEqualFalse());
+ solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
+ return true;
+ }
+ default: {
+ if (i-j > 0) {
+ solver.clauses_literals -= i-j;
+ }
+ return false;
+ }
+ }
+
+ assert(false);
+ return false;
+}
+
+bool ClauseCleaner::satisfied(const Clause& c) const
+{
+ for (uint32_t i = 0; i != c.size(); i++)
+ if (solver.value(c[i]) == l_True)
+ return true;
+ return false;
+}
+
+bool ClauseCleaner::satisfied(const XorClause& c) const
+{
+ bool final = c.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();
+ }
+ return final;
+}
diff --git a/src/prop/cryptominisat/Solver/ClauseCleaner.h b/src/prop/cryptominisat/Solver/ClauseCleaner.h
new file mode 100644
index 000000000..11886e430
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/ClauseCleaner.h
@@ -0,0 +1,86 @@
+/***********************************************************************************
+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 CLAUSECLEANER_H
+#define CLAUSECLEANER_H
+
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include "Solver.h"
+#include "Subsumer.h"
+#include "XorSubsumer.h"
+
+namespace CMSat {
+
+/**
+@brief Cleans clauses from false literals & removes satisfied clauses
+*/
+class ClauseCleaner
+{
+ public:
+ ClauseCleaner(Solver& solver);
+
+ 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;
+
+ private:
+ bool satisfied(const Watched& watched, Lit lit);
+ bool cleanClause(XorClause& c);
+ bool cleanClause(Clause*& c);
+
+ 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)
+{
+ //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;
+
+ removeSatisfiedBins(limit);
+ cleanClauses(solver.clauses, ClauseCleaner::clauses, limit);
+ cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses, limit);
+ cleanClauses(solver.learnts, ClauseCleaner::learnts, limit);
+}
+
+}
+
+#endif //CLAUSECLEANER_H
diff --git a/src/prop/cryptominisat/Solver/ClauseOffset.h b/src/prop/cryptominisat/Solver/ClauseOffset.h
new file mode 100644
index 000000000..352cda45e
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/ClauseOffset.h
@@ -0,0 +1,16 @@
+#ifndef CLAUSEOFFSET_H
+#define CLAUSEOFFSET_H
+
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+namespace CMSat {
+
+typedef uint32_t ClauseOffset;
+
+}
+
+#endif //CLAUSEOFFSET_H
diff --git a/src/prop/cryptominisat/Solver/ClauseVivifier.cpp b/src/prop/cryptominisat/Solver/ClauseVivifier.cpp
new file mode 100644
index 000000000..ebe745f10
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/ClauseVivifier.cpp
@@ -0,0 +1,342 @@
+/**************************************************************************
+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
+
+using namespace CMSat;
+
+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.
+*/
+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) {
+ if (!vivifyClauses2(solver.clauses)) return false;
+ if (!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>(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);
+ #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;
+}
+
+
+bool ClauseVivifier::vivifyClauses2(vec<Clause*>& clauses)
+{
+ assert(solver.ok);
+
+ vec<char> seen;
+ seen.growTo(solver.nVars()*2, 0);
+ vec<char> seen_subs;
+ seen_subs.growTo(solver.nVars()*2, 0);
+
+ uint32_t litsRem = 0;
+ uint32_t clShrinked = 0;
+ uint64_t countTime = 0;
+ uint64_t maxCountTime = 800*1000*1000;
+ maxCountTime *= 6;
+ if (solver.clauses_literals + solver.learnts_literals < 500000)
+ maxCountTime *= 2;
+ uint32_t clTried = 0;
+ vec<Lit> lits;
+ bool needToFinish = false;
+ double myTime = cpuTime();
+ uint32_t subsumed_tri_num = 0;
+ uint32_t subsumed_bin_num = 0;
+
+ 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++;
+
+ bool subsumed = false;
+ const bool learnt = cl.learnt();
+ for (uint32_t i2 = 0; i2 < cl.size(); i2++) {
+ seen[cl[i2].toInt()] = 1; //for strengthening
+ seen_subs[cl[i2].toInt()] = 1; //for subsumption
+ }
+
+ for (const Lit *l = cl.getData(), *end = cl.getDataEnd(); l != end; l++) {
+ const Lit *l_other = l;
+ l_other++;
+ if (l_other != end)
+ __builtin_prefetch(solver.watches[(~*l_other).toInt()].getData());
+
+ const vec<Watched>& ws = solver.watches[(~*l).toInt()];
+ countTime += ws.size()*2;
+ for(vec<Watched>::const_iterator it = ws.getData(), end = ws.getDataEnd(); it != end; it++) {
+ //Handle tri clause
+ if (it->isTriClause() && cl.size() > 3)
+ {
+ if (learnt //we cannot decide if TRI is learnt or not
+ && seen_subs[it->getOtherLit().toInt()]
+ && seen_subs[it->getOtherLit2().toInt()]
+ ) {
+ subsumed_tri_num++;
+ subsumed = true;
+ }
+
+ if (seen[l->toInt()]) { //we may have removed it already
+ //one way
+ if (seen[(it->getOtherLit2()).toInt()])
+ seen[(~it->getOtherLit()).toInt()] = 0;
+
+ //other way
+ if (seen[(it->getOtherLit()).toInt()])
+ seen[(~it->getOtherLit2()).toInt()] = 0;
+ }
+ }
+
+ //Handle Binary clause
+ if (it->isBinary()) {
+ if (seen_subs[it->getOtherLit().toInt()])
+ {
+ if (!learnt && it->getLearnt())
+ makeNonLearntBin(*l, it->getOtherLit(), it->getLearnt());
+ subsumed_bin_num++;
+ subsumed = true;
+ }
+
+ if (seen[l->toInt()]) //we may have removed it already
+ seen[(~it->getOtherLit()).toInt()] = 0;
+
+ }
+ }
+
+ if (seen[l->toInt()] == 0)
+ continue;
+
+ 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;
+ seen_subs[it2->toInt()] = 0;
+ }
+
+ if (subsumed) {
+ solver.removeClause(cl);
+ } else if (lits.size() < cl.size()) {
+ solver.detachClause(cl);
+ clShrinked++;
+ Clause* c2 = solver.addClauseInt(lits, 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 rem " << std::setw(8) << (subsumed_bin_num + subsumed_tri_num)
+ << " cl shrink " << std::setw(8) << clShrinked
+ << " lits rem " << std::setw(10) << litsRem
+ << " time: " << cpuTime() - myTime
+ << std::endl;
+ }
+
+ return solver.ok;
+}
+
+void ClauseVivifier::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;
+}
diff --git a/src/prop/cryptominisat/Solver/ClauseVivifier.h b/src/prop/cryptominisat/Solver/ClauseVivifier.h
new file mode 100644
index 000000000..51a345e59
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/ClauseVivifier.h
@@ -0,0 +1,61 @@
+/**************************************************************************
+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"
+
+namespace CMSat {
+
+class ClauseVivifier {
+ public:
+ ClauseVivifier(Solver& solver);
+ bool vivifyClauses();
+ 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
+ {
+ bool operator () (const Clause* x, const Clause* y)
+ {
+ return (x->size() > y->size());
+ }
+ };
+
+ void makeNonLearntBin(const Lit lit1, const Lit lit2, const bool learnt);
+
+ uint32_t numCalls;
+ Solver& solver;
+};
+
+}
+
+#endif //CLAUSEVIVIFIER_H
diff --git a/src/prop/cryptominisat/Solver/CompleteDetachReattacher.cpp b/src/prop/cryptominisat/Solver/CompleteDetachReattacher.cpp
new file mode 100644
index 000000000..833f13c63
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/CompleteDetachReattacher.cpp
@@ -0,0 +1,198 @@
+/**************************************************************************
+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"
+
+using namespace CMSat;
+
+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;
+
+ vec<Watched>::iterator i = ws.getData();
+ vec<Watched>::iterator j = i;
+ for (vec<Watched>::iterator 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
+*/
+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<false>().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;
+ PolaritySorter sorter(solver.polarity);
+ for (Clause **end = cs.getDataEnd(); i != end; i++) {
+ std::sort((*i)->getData(), (*i)->getDataEnd(), sorter);
+ 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 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 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());
+ return false;
+ }
+
+ default:;
+ }
+
+ return true;
+}
diff --git a/src/prop/cryptominisat/Solver/CompleteDetachReattacher.h b/src/prop/cryptominisat/Solver/CompleteDetachReattacher.h
new file mode 100644
index 000000000..2d9dacfa0
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/CompleteDetachReattacher.h
@@ -0,0 +1,78 @@
+/**************************************************************************
+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"
+
+namespace CMSat {
+
+/**
+@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);
+ 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);
+ bool cleanClause(Clause*& ps);
+ bool cleanClause(XorClause& ps);
+
+ Solver& solver;
+};
+
+}
diff --git a/src/prop/cryptominisat/Solver/DataSync.cpp b/src/prop/cryptominisat/Solver/DataSync.cpp
new file mode 100644
index 000000000..3e7956a19
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/DataSync.cpp
@@ -0,0 +1,216 @@
+/*****************************************************************************
+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>
+
+using namespace CMSat;
+
+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);
+}
+
+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;
+}
+
+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;
+}
+
+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 (vec<Watched>::iterator 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, 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++;
+}
+
+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<false>().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;
+}
diff --git a/src/prop/cryptominisat/Solver/DataSync.h b/src/prop/cryptominisat/Solver/DataSync.h
new file mode 100644
index 000000000..96ac7a355
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/DataSync.h
@@ -0,0 +1,101 @@
+/*****************************************************************************
+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"
+
+namespace CMSat {
+
+class DataSync
+{
+ public:
+ DataSync(Solver& solver, SharedData* sharedData);
+ void newVar();
+ bool syncData();
+
+
+ template <class T> void signalNewBinClause(T& ps);
+ void signalNewBinClause(Lit lit1, Lit lit2);
+
+ uint32_t getSentUnitData() const;
+ uint32_t getRecvUnitData() const;
+ uint32_t getSentBinData() const;
+ uint32_t getRecvBinData() const;
+
+ private:
+ //functions
+ bool shareUnitData();
+ 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);
+ 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 uint32_t DataSync::getSentUnitData() const
+{
+ return sentUnitData;
+}
+
+inline uint32_t DataSync::getRecvUnitData() const
+{
+ return recvUnitData;
+}
+
+inline uint32_t DataSync::getSentBinData() const
+{
+ return sentBinData;
+}
+
+inline uint32_t DataSync::getRecvBinData() const
+{
+ return recvBinData;
+}
+
+template <class T>
+inline void DataSync::signalNewBinClause(T& ps)
+{
+ if (sharedData == NULL) return;
+ assert(ps.size() == 2);
+ signalNewBinClause(ps[0], ps[1]);
+}
+
+inline void DataSync::signalNewBinClause(Lit lit1, Lit lit2)
+{
+ if (sharedData == NULL) return;
+ if (lit1.toInt() > lit2.toInt()) std::swap(lit1, lit2);
+ newBinClauses.push_back(std::make_pair(lit1, lit2));
+}
+
+}
diff --git a/src/prop/cryptominisat/Solver/DimacsParser.cpp b/src/prop/cryptominisat/Solver/DimacsParser.cpp
new file mode 100644
index 000000000..0fc4d9d74
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/DimacsParser.cpp
@@ -0,0 +1,490 @@
+/*****************************************************************************
+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
+
+using namespace CMSat;
+
+DimacsParseError::DimacsParseError(const std::string& arg)
+ : std::runtime_error(arg) { }
+
+DimacsParseError::~DimacsParseError() throw() { }
+
+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)
+{}
+
+/**
+@brief Skips all whitespaces
+*/
+void DimacsParser::skipWhitespace(StreamBuffer& in)
+{
+ while ((*in >= 9 && *in <= 13 && *in != 10) || *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
+*/
+int32_t DimacsParser::parseInt(StreamBuffer& in, uint32_t& lenParsed) throw (DimacsParseError)
+{
+ lenParsed = 0;
+ int32_t val = 0;
+ bool neg = false;
+ skipWhitespace(in);
+ if (*in == '-') neg = true, ++in;
+ else if (*in == '+') ++in;
+ if (*in < '0' || *in > '9') {
+ std::ostringstream ostr;
+ ostr << "Unexpected char (parseInt): " << *in;
+ throw DimacsParseError(ostr.str());
+ }
+ while (*in >= '0' && *in <= '9') {
+ lenParsed++;
+ val = val*10 + (*in - '0'),
+ ++in;
+ }
+ return neg ? -val : val;
+}
+
+float DimacsParser::parseFloat(StreamBuffer& in) throw (DimacsParseError)
+{
+ uint32_t len;
+ uint32_t main = parseInt(in, len);
+ if (*in != '.') {
+ std::ostringstream ostr;
+ ostr << "Float does not contain a dot! Instead it contains: " << *in;
+ throw DimacsParseError(ostr.str());
+ }
+ ++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) throw (DimacsParseError)
+{
+ int32_t 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) {
+ if (var >= ((uint32_t)1)<<25) {
+ std::ostringstream ostr;
+ ostr << "Variable requested is far too large: " << var;
+ throw DimacsParseError(ostr.str());
+ }
+ 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) throw (DimacsParseError)
+{
+ 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 {
+ std::ostringstream ostr;
+ ostr << "Unexpected char: " << *in;
+ throw DimacsParseError(ostr.str());
+ }
+}
+
+/**
+@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) throw (DimacsParseError)
+{
+ 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)
+ throw DimacsParseError("Var number must be a positive integer");
+ std::string name = untilEnd(in);
+ //Don't do anythint with NAME, just forget it
+
+ #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);
+ if (str != "learnt") goto addTheClause;
+
+ ++in;
+ parseString(in, str);
+ 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;
+ }
+
+ //Parse in Glue value
+ ++in;
+ parseString(in, str);
+ if (str != "glue") goto addTheClause;
+ ++in;
+ glue = parseInt(in, len);
+
+ //Parse in MiniSat activity
+ ++in;
+ parseString(in, str);
+ if (str != "miniSatAct") goto addTheClause;
+ ++in;
+ miniSatAct = parseFloat(in);
+
+ 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) throw (DimacsParseError)
+{
+ 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) {
+ if (*in != 'c')
+ throw DimacsParseError("Group must be present after each clause ('c' missing after clause line)");
+ ++in;
+
+ parseString(in, str);
+ if (str != "g" && str != "group") {
+ std::ostringstream ostr;
+ ostr << "Group must be present after each clause('group' missing)!" << std:: endl
+ << "Instead of 'group' there was: " << str;
+ throw DimacsParseError(ostr.str());
+ }
+
+ int groupId = parseInt(in, len);
+ groupId++;
+ //Don't do anything with grupId
+
+ 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);
+ numXorClauses++;
+ } else {
+ if (addAsLearnt || learnt) {
+ solver->addLearntClause(lits, glue, miniSatAct);
+ numLearntClauses++;
+ } else {
+ solver->addClause(lits);
+ numNormClauses++;
+ }
+ }
+
+ if (needToParseComments) {
+ #ifdef DEBUG_COMMENT_PARSING
+ std::cout << "Need to parse comments:" << str << std::endl;
+ #endif //DEBUG_COMMENT_PARSING
+ parseComments(in, str);
+ }
+}
+
+void DimacsParser::readBranchingOrder(StreamBuffer& in)
+{
+ skipWhitespace(in);
+
+ while (1) {
+ int parsed_var;
+ uint32_t len;
+
+ parsed_var = parseInt(in, len);
+ if (parsed_var == 0)
+ break;
+
+ solver->addBranchingVariable(parsed_var - 1);
+ }
+}
+
+/**
+@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);
+ skipLine(in);
+ break;
+ case 'c':
+ ++in;
+ parseString(in, str);
+ parseComments(in, str);
+ break;
+ case 'b':
+ ++in;
+ readBranchingOrder(in);
+ break;
+ case '\n':
+ //Skipping empty line, even though empty lines are kind of out-of-spec
+ ++in;
+ break;
+ default:
+ readFullClause(in);
+ if (!solver->okay()) return;
+ 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/prop/cryptominisat/Solver/DimacsParser.h b/src/prop/cryptominisat/Solver/DimacsParser.h
new file mode 100644
index 000000000..c149214ba
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/DimacsParser.h
@@ -0,0 +1,84 @@
+/*****************************************************************************
+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 <stdexcept>
+#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
+
+namespace CMSat {
+
+class Solver;
+
+class DimacsParseError : public std::runtime_error
+{
+ public:
+ explicit DimacsParseError(const std::string& arg);
+ virtual ~DimacsParseError() throw();
+};
+
+/**
+@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);
+ int32_t parseInt(StreamBuffer& in, uint32_t& len) throw (DimacsParseError);
+ float parseFloat(StreamBuffer& in) throw (DimacsParseError);
+ void parseString(StreamBuffer& in, std::string& str);
+ void readClause(StreamBuffer& in, vec<Lit>& lits) throw (DimacsParseError);
+ void parseClauseParameters(StreamBuffer& in, bool& learnt, uint32_t& glue, float& miniSatAct);
+ void readFullClause(StreamBuffer& in) throw (DimacsParseError);
+ void readBranchingOrder(StreamBuffer& in);
+ bool match(StreamBuffer& in, const char* str);
+ void printHeader(StreamBuffer& in) throw (DimacsParseError);
+ void parseComments(StreamBuffer& in, const std::string str) throw (DimacsParseError);
+ 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
+ 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/prop/cryptominisat/Solver/DoublePackedRow.h b/src/prop/cryptominisat/Solver/DoublePackedRow.h
new file mode 100644
index 000000000..cbeee2f71
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/DoublePackedRow.h
@@ -0,0 +1,173 @@
+/***********************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************************************/
+
+#ifndef DOUBLEPACKEDROW_H
+#define DOUBLEPACKEDROW_H
+
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include <stdlib.h>
+
+#include "SolverTypes.h"
+
+namespace CMSat
+{
+using namespace CMSat;
+
+class DoublePackedRow
+{
+ private:
+ class BitIter {
+ public:
+ inline void operator=(const lbool toSet)
+ {
+ val &= ~((unsigned char)3 << offset);
+ val |= toSet.value << offset;
+ }
+
+ inline operator lbool() const
+ {
+ return lbool((val >> offset) & 3);
+ }
+
+ inline const bool isUndef() const {
+ return ((lbool)*this).isUndef();
+ }
+ inline const bool isDef() const {
+ return ((lbool)*this).isDef();
+ }
+ inline const bool getBool() const {
+ return ((lbool)*this).getBool();
+ }
+ inline const bool operator==(lbool b) const {
+ return ((lbool)*this) == b;
+ }
+ inline const bool operator!=(lbool b) const {
+ return ((lbool)*this) != b;
+ }
+ const lbool operator^(const bool b) const {
+ return ((lbool)*this) ^ b;
+ }
+
+ private:
+ friend class DoublePackedRow;
+ inline BitIter(unsigned char& mp, const uint32_t _offset) :
+ val(mp)
+ , offset(_offset)
+ {}
+
+ unsigned char& val;
+ const uint32_t offset;
+ };
+
+ class BitIterConst {
+ public:
+ inline operator lbool() const
+ {
+ return lbool((val >> offset) & 3);
+ }
+
+ inline const bool isUndef() const {
+ return ((lbool)*this).isUndef();
+ }
+ inline const bool isDef() const {
+ return ((lbool)*this).isDef();
+ }
+ inline const bool getBool() const {
+ return ((lbool)*this).getBool();
+ }
+ inline const bool operator==(lbool b) const {
+ return ((lbool)*this) == b;
+ }
+ inline const bool operator!=(lbool b) const {
+ return ((lbool)*this) != b;
+ }
+ const lbool operator^(const bool b) const {
+ return ((lbool)*this) ^ b;
+ }
+
+
+ private:
+ friend class DoublePackedRow;
+ inline BitIterConst(unsigned char& mp, const uint32_t _offset) :
+ val(mp)
+ , offset(_offset)
+ {}
+
+ const unsigned char& val;
+ const uint32_t offset;
+ };
+
+ public:
+ DoublePackedRow() :
+ numElems(0)
+ , mp(NULL)
+ {}
+
+ uint32_t size() const
+ {
+ return numElems;
+ }
+
+ void growTo(const uint32_t newNumElems)
+ {
+ uint32_t oldSize = numElems/4 + (bool)(numElems % 4);
+ uint32_t newSize = newNumElems/4 + (bool)(newNumElems % 4);
+
+ if (oldSize >= newSize) {
+ numElems = std::max(newNumElems, numElems);
+ return;
+ }
+
+ mp = (unsigned char*)realloc(mp, newSize*sizeof(unsigned char));
+ numElems = newNumElems;
+ }
+
+ inline BitIter operator[](const uint32_t at)
+ {
+ return BitIter(mp[at/4], (at%4)*2);
+ }
+
+ inline const BitIterConst operator[](const uint32_t at) const
+ {
+ return BitIterConst(mp[at/4], (at%4)*2);
+ }
+
+ inline void push(const lbool val)
+ {
+ growTo(numElems+1);
+ (*this)[numElems-1] = val;
+ }
+
+ /*void clear(const uint32_t at)
+ {
+ mp[at/32] &= ~((uint64_t)3 << ((at%32)*2));
+ }*/
+
+ private:
+
+ Var numElems;
+ unsigned char *mp;
+};
+
+}; //NAMESPACE MINISAT
+
+#endif //DOUBLEPACKEDROW_H
diff --git a/src/prop/cryptominisat/Solver/FailedLitSearcher.cpp b/src/prop/cryptominisat/Solver/FailedLitSearcher.cpp
new file mode 100644
index 000000000..a847c5e09
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/FailedLitSearcher.cpp
@@ -0,0 +1,768 @@
+/**************************************************************************
+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>
+
+#include "Solver.h"
+#include "ClauseCleaner.h"
+#include "time_mem.h"
+#include "VarReplacer.h"
+#include "ClauseCleaner.h"
+#include "StateSaver.h"
+#include "CompleteDetachReattacher.h"
+
+//#define VERBOSE_DEUBUG
+
+using namespace CMSat;
+using std::make_pair;
+using std::set;
+
+/**
+@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));
+
+ 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
+*/
+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.
+*/
+bool FailedLitSearcher::search()
+{
+ assert(solver.decisionLevel() == 0);
+ if (solver.nVars() == 0) return solver.ok;
+
+ uint64_t numProps = 130 * 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;
+ if (solver.order_heap.size() < 20000)
+ maxHyperBinProps*=2;
+ 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:
+ 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);
+ } 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.
+*/
+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.removeThese(propagatedBitSet);
+ #ifdef DEBUG_FAILEDLIT
+ assert(propagated.isZero());
+ #endif
+ propagatedBitSet.clear();
+ 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>(false).isNULL());
+ if (failed) {
+ solver.cancelUntilLight();
+ numFailed++;
+ solver.uncheckedEnqueue(~lit1);
+ solver.ok = (solver.propagate<false>(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);
+ propagatedBitSet.push_back(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>(false).isNULL());
+ if (failed) {
+ solver.cancelUntilLight();
+ numFailed++;
+ solver.uncheckedEnqueue(~lit2);
+ solver.ok = (solver.propagate<false>(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));
+ 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));
+ 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>(false).isNULL());
+ if (!solver.ok) return false;
+
+ if (solver.conf.doBXor) {
+ 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);
+ 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()].lev1Ancestor.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;
+ if (!solver.binPropData[l->var()].hasChildren) continue;
+ fillImplies(*l);
+ //addMyImpliesSetAsBins(*l, difference);
+ 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.removeTheseLit(toVisit);
+ break;
+ }
+ }
+ #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>(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();
+}
+
+/*void FailedLitSearcher::addMyImpliesSetAsBins(Lit lit, int32_t& difference)
+{
+ if (myImpliesSet.size() == 0) return;
+ if (myImpliesSet.size() == 1) {
+ Var var = myImpliesSet[0];
+ Lit l2 = Lit(var, !propValue[var]);
+ addBin(~lit, l2);
+ unPropagatedBin.clearBit(var);
+ difference--;
+ return;
+ }
+
+ uint64_t backupProps = solver.propagations;
+ vector<BinAddData> litsAddedEach;
+ uint32_t i = 0;
+ for (const Var *var = myImpliesSet.getData(), *end2 = myImpliesSet.getDataEnd(); var != end2; var++, i++) {
+ Lit l2 = Lit(*var, !propValue[*var]);
+ solver.newDecisionLevel();
+ solver.uncheckedEnqueueLight(l2);
+ failed = (!solver.propagateBin(uselessBin).isNULL());
+ assert(!failed);
+ uselessBin.clear();
+
+ BinAddData addData;
+ addData.lit = l2;
+ assert(solver.decisionLevel() > 0);
+ for (int sublevel = solver.trail.size()-1; sublevel > (int)solver.trail_lim[0]; sublevel--) {
+ Lit x = solver.trail[sublevel];
+ addData.lits.push_back(x);
+ }
+ solver.cancelUntilLight();
+ litsAddedEach.push_back(addData);
+ }
+ std::sort(litsAddedEach.begin(), litsAddedEach.end(), BinAddDataSorter());
+
+ while(!litsAddedEach.empty()) {
+ assert(!litsAddedEach.empty());
+ BinAddData b = *litsAddedEach.begin();
+ litsAddedEach.erase(litsAddedEach.begin());
+
+ addBin(~lit, b.lit);
+ assert(unPropagatedBin[b.lit.var()]);
+ unPropagatedBin.clearBit(b.lit.var());
+ difference--;
+ for (uint32_t i = 0; i < b.lits.size(); i++) {
+ Lit alsoAddedLit = b.lits[i];
+ if (unPropagatedBin[alsoAddedLit.var()]) {
+ unPropagatedBin.clearBit(alsoAddedLit.var());
+ difference--;
+ for (vector<BinAddData>::iterator it2 = litsAddedEach.begin(); it2 != litsAddedEach.end(); it2++) {
+ if (it2->lit == alsoAddedLit) {
+ litsAddedEach.erase(it2);
+ break;
+ }
+ }
+ }
+ }
+ }
+ assert(litsAddedEach.empty());
+ solver.propagations = backupProps;
+}*/
+
+
+/**
+@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, true);
+ tmpPs.clear();
+ tmpPs.growTo(2);
+ assert(solver.ok);
+ addedBin++;
+}
diff --git a/src/prop/cryptominisat/Solver/FailedLitSearcher.h b/src/prop/cryptominisat/Solver/FailedLitSearcher.h
new file mode 100644
index 000000000..e4bf5bd19
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/FailedLitSearcher.h
@@ -0,0 +1,246 @@
+/***************************************************************************
+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>
+
+#include "SolverTypes.h"
+#include "Clause.h"
+#include "BitArray.h"
+
+namespace CMSat {
+
+using std::set;
+using std::map;
+using std::vector;
+
+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);
+
+ bool search();
+ double getTotalTime() const;
+
+ private:
+ //Main
+ bool tryBoth(const Lit lit1, const Lit lit2);
+ 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
+ vector<uint32_t> propagatedBitSet;
+ 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:
+ bool operator==(const TwoLongXor& other) const
+ {
+ if (var[0] == other.var[0]
+ && var[1] == other.var[1]
+ && inverted == other.inverted)
+ return true;
+ return false;
+ }
+ 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) :
+ lit1(_lit1)
+ , lit2(_lit2)
+ , isEqualFalse(_isEqualFalse)
+ {}
+ Lit lit1;
+ Lit lit2;
+ bool isEqualFalse;
+ };
+ 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)
+ {}
+
+ bool operator () (const Lit x, const Lit y) const
+ {
+ return binPropData[x.var()].lev > binPropData[y.var()].lev;
+ }
+
+ const vec<BinPropData>& binPropData;
+ };
+ struct BinAddData
+ {
+ vector<Lit> lits;
+ Lit lit;
+ };
+ struct BinAddDataSorter
+ {
+ bool operator() (const BinAddData& a, const BinAddData& b) const
+ {
+ return (a.lits.size() > b.lits.size());
+ }
+ };
+ //void addMyImpliesSetAsBins(Lit lit, int32_t& difference);
+
+ 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 double FailedLitSearcher::getTotalTime() const
+{
+ return totalTime;
+}
+
+}
+
+#endif //FAILEDVARSEARCHER_H
diff --git a/src/prop/cryptominisat/Solver/Gaussian.cpp b/src/prop/cryptominisat/Solver/Gaussian.cpp
new file mode 100644
index 000000000..e186d5849
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/Gaussian.cpp
@@ -0,0 +1,1147 @@
+/***************************************************************************
+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 "Gaussian.h"
+
+#include <iostream>
+#include <iomanip>
+#include "Clause.h"
+#include <algorithm>
+#include "ClauseCleaner.h"
+#include "VarReplacer.h"
+#include "DataSync.h"
+
+//#define VERBOSE_DEBUG
+//#define DEBUG_GAUSS
+
+#ifdef VERBOSE_DEBUG
+#include <iterator>
+#endif
+
+using namespace CMSat;
+using std::ostream;
+using std::cout;
+using std::endl;
+
+static const uint16_t unassigned_col = std::numeric_limits<uint16_t>::max();
+static const Var unassigned_var = std::numeric_limits<Var>::max();
+
+Gaussian::Gaussian(Solver& _solver, const GaussConf& _config, const uint32_t _matrix_no, const vector<XorClause*>& _xorclauses) :
+ solver(_solver)
+ , config(_config)
+ , matrix_no(_matrix_no)
+ , xorclauses(_xorclauses)
+ , messed_matrix_vars_since_reversal(true)
+ , gauss_last_level(0)
+ , disabled(false)
+ , useful_prop(0)
+ , useful_confl(0)
+ , called(0)
+ , unit_truths(0)
+{
+}
+
+Gaussian::~Gaussian()
+{
+ for (uint32_t i = 0; i < clauses_toclear.size(); i++)
+ solver.clauseAllocator.clauseFree(clauses_toclear[i].first);
+}
+
+inline void Gaussian::set_matrixset_to_cur()
+{
+ 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
+ matrix_sets[level] = cur_matrixset;
+}
+
+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();
+ 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:
+ case propagation:
+ unit_truths += last_trail_size - solver.trail.size();
+ do_again_gauss = true;
+ solver.ok = (solver.propagate<true>().isNULL());
+ if (!solver.ok) return false;
+ break;
+ case nothing:
+ break;
+ }
+ }
+
+ return true;
+}
+
+void Gaussian::init()
+{
+ assert(solver.decisionLevel() == 0);
+
+ fill_matrix(cur_matrixset);
+ if (!cur_matrixset.num_rows || !cur_matrixset.num_cols) {
+ disabled = true;
+ badlevel = 0;
+ return;
+ }
+
+ matrix_sets.clear();
+ matrix_sets.push_back(cur_matrixset);
+ gauss_last_level = solver.trail.size();
+ messed_matrix_vars_since_reversal = false;
+ badlevel = UINT_MAX;
+
+ #ifdef VERBOSE_DEBUG
+ cout << "(" << matrix_no << ")Gaussian init finished." << endl;
+ #endif
+}
+
+uint32_t Gaussian::select_columnorder(vector<uint16_t>& var_to_col, matrixset& origMat)
+{
+ var_to_col.resize(solver.nVars(), unassigned_col);
+
+ uint32_t num_xorclauses = 0;
+ for (uint32_t i = 0; i != xorclauses.size(); i++) {
+ XorClause& c = *xorclauses[i];
+ if (c.getRemoved()) continue;
+ num_xorclauses++;
+
+ 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;
+ }
+ }
+
+ 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);
+
+ origMat.col_to_var.clear();
+ vector<Var> vars(solver.nVars());
+ if (!config.orderCols) {
+ for (uint32_t i = 0; i < solver.nVars(); i++) {
+ vars.push_back(i);
+ }
+ std::random_shuffle(vars.begin(), vars.end());
+ }
+
+ Heap<Solver::VarOrderLt> order_heap(solver.order_heap);
+ uint32_t iterReduceIt = 0;
+ while ((config.orderCols && !order_heap.empty()) || (!config.orderCols && iterReduceIt < vars.size()))
+ {
+ Var v;
+ if (config.orderCols) v = order_heap.removeMin();
+ else v = vars[iterReduceIt++];
+ if (var_to_col[v] == 1) {
+ #ifdef DEBUG_GAUSS
+ 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);
+ }
+ }
+
+ //for the ones that were not in the order_heap, but are marked in var_to_col
+ 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;
+ var_is_in.setBit(v);
+ }
+ }
+
+ #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<uint32_t>(cout, ","));
+ cout << endl;
+ #endif
+
+ return num_xorclauses;
+}
+
+void Gaussian::fill_matrix(matrixset& origMat)
+{
+ #ifdef VERBOSE_DEBUG
+ cout << "(" << matrix_no << ")Filling matrix" << endl;
+ #endif
+
+ vector<uint16_t> var_to_col;
+ origMat.num_rows = select_columnorder(var_to_col, origMat);
+ origMat.num_cols = origMat.col_to_var.size();
+ col_to_var_original = origMat.col_to_var;
+ changed_rows.resize(origMat.num_rows);
+ memset(&changed_rows[0], 0, sizeof(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);
+
+ #ifdef VERBOSE_DEBUG
+ cout << "(" << matrix_no << ")matrix size:" << origMat.num_rows << "," << origMat.num_cols << endl;
+ #endif
+
+ uint32_t matrix_row = 0;
+ for (uint32_t i = 0; i != xorclauses.size(); i++) {
+ const XorClause& c = *xorclauses[i];
+ 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);
+ matrix_row++;
+ }
+ assert(origMat.num_rows == matrix_row);
+}
+
+void Gaussian::update_matrix_col(matrixset& m, const Var var, const uint32_t col)
+{
+ #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();
+ uint32_t row_num = 0;
+
+ if (solver.assigns[var].getBool()) {
+ 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();
+ (*this_row).clearBit(col);
+ }
+ }
+ } else {
+ 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);
+ }
+ }
+ }
+
+ #ifdef DEBUG_GAUSS
+ bool c = false;
+ for(PackedMatrix::iterator r = m.matrix.beginMatrix(), end = r + m.matrix.getSize(); r != end; ++r)
+ c |= (*r)[col];
+ assert(!c);
+ #endif
+
+ m.removeable_cols++;
+ m.col_to_var[col] = unassigned_var;
+ m.var_is_set.setBit(var);
+}
+
+void Gaussian::update_matrix_by_col_all(matrixset& m)
+{
+ #ifdef VERBOSE_DEBUG
+ cout << "(" << matrix_no << ")Updating matrix." << endl;
+ #ifdef VERBOSE_DEBUG_MORE
+ print_matrix(m);
+ #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(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);
+ last++;
+ #ifdef VERBOSE_DEBUG
+ num_updated++;
+ #endif
+ } else
+ last = 0;
+ }
+ m.num_cols -= last;
+
+ #ifdef DEBUG_GAUSS
+ check_matrix_against_varset(m.matrix, m);
+ #endif
+
+ #ifdef VERBOSE_DEBUG
+ cout << "Matrix update finished, updated " << num_updated << " cols" << endl;
+ #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();
+ cout << " num_cols diff:" << col_to_var_original.size() - m.col_to_var.size() << endl;
+ cout << "removeable cols:" << m.removeable_cols << endl;*/
+}
+
+inline void Gaussian::update_last_one_in_col(matrixset& m)
+{
+ for (uint16_t* i = &m.last_one_in_col[0]+m.last_one_in_col.size()-1, *end = &m.last_one_in_col[0]-1; i != end && *i >= m.num_rows; i--)
+ *i = m.num_rows;
+}
+
+Gaussian::gaussian_ret Gaussian::gaussian(PropBy& confl)
+{
+ if (solver.decisionLevel() >= badlevel)
+ return nothing;
+
+ if (messed_matrix_vars_since_reversal) {
+ #ifdef VERBOSE_DEBUG
+ cout << "(" << matrix_no << ")matrix needs copy before update" << endl;
+ #endif
+
+ const uint32_t level = solver.decisionLevel() / config.only_nth_gauss_save;
+ assert(level < matrix_sets.size());
+ cur_matrixset = matrix_sets[level];
+ }
+ update_last_one_in_col(cur_matrixset);
+ update_matrix_by_col_all(cur_matrixset);
+
+ messed_matrix_vars_since_reversal = false;
+ gauss_last_level = solver.trail.size();
+ badlevel = UINT_MAX;
+
+ propagatable_rows.clear();
+ uint32_t last_row = eliminate(cur_matrixset);
+ #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) {
+ 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 || ret == unit_conflict || nothing_to_propagate(cur_matrixset));
+ #endif
+
+ if (!cur_matrixset.num_cols || !cur_matrixset.num_rows) {
+ badlevel = solver.decisionLevel();
+ return ret;
+ }
+
+ if (ret == nothing &&
+ solver.decisionLevel() % config.only_nth_gauss_save == 0)
+ set_matrixset_to_cur();
+
+ #ifdef VERBOSE_DEBUG
+ if (ret == nothing)
+ cout << "(" << matrix_no << ")Useless. ";
+ else
+ cout << "(" << matrix_no << ")Useful. ";
+ cout << "(" << matrix_no << ")Useful prop in " << ((double)useful_prop/(double)called)*100.0 << "%" << endl;
+ cout << "(" << matrix_no << ")Useful confl in " << ((double)useful_confl/(double)called)*100.0 << "%" << endl;
+ #endif
+
+ return ret;
+}
+
+uint32_t Gaussian::eliminate(matrixset& m)
+{
+ #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);
+ #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
+
+ 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])
+ until = m.num_rows;
+ for (;i != until; i++, ++rowIt) if (changed_rows[i] && (*rowIt).popcnt_is_one(m.first_one_in_row[i]))
+ propagatable_rows.push(i);
+ }
+
+ #ifdef VERBOSE_DEBUG
+ cout << "At while() start: i,j = " << i << ", " << j << endl;
+ cout << "num_rows:" << m.num_rows << " num_cols:" << m.num_cols << endl;
+ #endif
+
+ if (j > m.num_cols) {
+ #ifdef VERBOSE_DEBUG
+ cout << "Going straight to finish" << endl;
+ #endif
+ goto finish;
+ }
+
+ #ifdef DEBUG_GAUSS
+ assert(i <= m.num_rows && j <= m.num_cols);
+ #endif
+
+ while (i != m.num_rows && j != m.num_cols) {
+ //Find pivot in column j, starting in row i:
+
+ if (m.col_to_var[j] == unassigned_var) {
+ j++;
+ continue;
+ }
+
+ PackedMatrix::iterator this_matrix_row = rowIt;
+ PackedMatrix::iterator end = beginIt + m.last_one_in_col[j];
+ for (; this_matrix_row != end; ++this_matrix_row) {
+ if ((*this_matrix_row)[j])
+ break;
+ }
+
+ if (this_matrix_row != end) {
+
+ //swap rows i and maxi, but do not change the value of i;
+ if (this_matrix_row != rowIt) {
+ #ifdef VERBOSE_DEBUG
+ no_exchanged++;
+ #endif
+
+ //Would early abort, but would not find the best conflict (and would be expensive)
+ //if (matrix_row_i.is_true() && matrix_row_i.isZero()) {
+ // conflict_row = i;
+ // return 0;
+ //}
+ (*rowIt).swapBoth(*this_matrix_row);
+ }
+ #ifdef DEBUG_GAUSS
+ assert(m.matrix.getMatrixAt(i).popcnt(j) == m.matrix.getMatrixAt(i).popcnt());
+ assert(m.matrix.getMatrixAt(i)[j]);
+ #endif
+
+ if ((*rowIt).popcnt_is_one(j))
+ propagatable_rows.push(i);
+
+ //Now A[i,j] will contain the old value of A[maxi,j];
+ ++this_matrix_row;
+ for (; this_matrix_row != end; ++this_matrix_row) if ((*this_matrix_row)[j]) {
+ //subtract row i from row u;
+ //Now A[u,j] will be 0, since A[u,j] - A[i,j] = A[u,j] -1 = 0.
+ #ifdef VERBOSE_DEBUG
+ number_of_row_additions++;
+ #endif
+
+ (*this_matrix_row).xorBoth(*rowIt);
+ //Would early abort, but would not find the best conflict (and would be expensive)
+ //if (it->is_true() &&it->isZero()) {
+ // conflict_row = i2;
+ // return 0;
+ //}
+ }
+ m.first_one_in_row[i] = j;
+ i++;
+ ++rowIt;
+ m.last_one_in_col[j] = i;
+ } else {
+ m.first_one_in_row[i] = j;
+ m.last_one_in_col[j] = i + 1;
+ }
+ j++;
+ }
+
+ finish:
+
+ m.least_column_changed = INT_MAX;
+
+ #ifdef VERBOSE_DEBUG
+ cout << "Finished elimination" << endl;
+ cout << "Returning with i,j:" << i << ", " << j << "(" << m.num_rows << ", " << m.num_cols << ")" << endl;
+ #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));
+ 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_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);
+ continue;
+ }
+ row++;
+ }
+ #endif
+
+ return i;
+}
+
+Gaussian::gaussian_ret Gaussian::handle_matrix_confl(PropBy& confl, const matrixset& m, const uint32_t maxlevel, const uint32_t best_row)
+{
+ assert(best_row != UINT_MAX);
+
+ 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);
+ release_assert(!wasUndef);
+
+ #ifdef VERBOSE_DEBUG
+ 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]);
+ } else {
+ confl = PropBy();
+ solver.ok = false;
+ }
+ return unit_conflict;
+ }
+
+ if (maxlevel != solver.decisionLevel()) {
+ solver.cancelUntil(maxlevel);
+ }
+ const uint32_t curr_dec_level = solver.decisionLevel();
+ assert(maxlevel == curr_dec_level);
+
+ 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);
+ confl = solver.clauseAllocator.getOffset(conflPtr);
+ Clause& cla = *conflPtr;
+
+ 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;
+ }
+
+ cancel_until_sublevel(maxsublevel+1);
+ messed_matrix_vars_since_reversal = true;
+
+ return conflict;
+}
+
+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();
+ uint32_t size = UINT_MAX;
+ uint32_t best_row = UINT_MAX;
+
+ for (uint32_t row = last_row; row != m.num_rows; row++) {
+ #ifdef DEBUG_GAUSS
+ assert(m.matrix.getMatrixAt(row).isZero());
+ #endif
+ if (m.matrix.getMatrixAt(row).is_true())
+ analyse_confl(m, row, maxlevel, size, best_row);
+ }
+
+ if (maxlevel != std::numeric_limits<int32_t>::max())
+ return handle_matrix_confl(confl, m, maxlevel, best_row);
+
+ #ifdef DEBUG_GAUSS
+ assert(check_no_conflict(m));
+ assert(last_row == 0 || !m.matrix.getMatrixAt(last_row-1).isZero());
+ #endif
+
+ #ifdef VERBOSE_DEBUG
+ cout << "Resizing matrix to num_rows = " << last_row << endl;
+ #endif
+ m.num_rows = last_row;
+ m.matrix.resizeNumRows(m.num_rows);
+
+ gaussian_ret ret = nothing;
+
+ 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++;
+ if (ret == unit_propagation) {
+ #ifdef VERBOSE_DEBUG
+ cout << "(" << matrix_no << ")Unit prop! Breaking from prop examination" << endl;
+ #endif
+ return unit_propagation;
+ }
+ }
+ #ifdef VERBOSE_DEBUG
+ if (num_props > 0) cout << "(" << matrix_no << ")Number of props during gauss:" << num_props << endl;
+ #endif
+
+ return ret;
+}
+
+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 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);
+
+ for (int sublevel = solver.trail.size()-1; sublevel >= (int)until_sublevel; sublevel--) {
+ Var var = solver.trail[sublevel].var();
+ #ifdef VERBOSE_DEBUG
+ cout << "(" << matrix_no << ")Canceling var " << var+1 << endl;
+ #endif
+
+ solver.assigns[var] = l_Undef;
+ solver.insertVarOrder(var);
+ }
+ solver.trail.shrink(solver.trail.size() - until_sublevel);
+
+ #ifdef VERBOSE_DEBUG
+ cout << "(" << matrix_no << ")Canceling sublevel finished." << endl;
+ #endif
+}
+
+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);
+
+ //this is a "000...00000001" row. I.e. it indicates we are on the wrong branch
+ #ifdef VERBOSE_DEBUG
+ cout << "(" << matrix_no << ")matrix conflict found!" << endl;
+ cout << "(" << matrix_no << ")conflict clause's vars: ";
+ #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;
+ uint32_t this_size = 0;
+ while (true) {
+ var = m.matrix.getVarsetAt(row).scan(var);
+ if (var == ULONG_MAX) break;
+
+ const Var real_var = col_to_var_original[var];
+ assert(real_var < solver.nVars());
+
+ if (solver.level[real_var] > this_maxlevel)
+ this_maxlevel = solver.level[real_var];
+ var++;
+ this_size++;
+ }
+
+ //the maximum of all lit's level must be lower than the max. level of the current best clause (or this clause must be either empty or unit clause)
+ if (!(
+ (this_maxlevel < maxlevel)
+ || (this_maxlevel == maxlevel && this_size < size)
+ || (this_size <= 1)
+ )) {
+ assert(maxlevel != 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;
+ }
+
+
+ #ifdef VERBOSE_DEBUG
+ if (maxlevel != std::numeric_limits<int32_t>::max())
+ cout << "(" << matrix_no << ")Better conflict found.";
+ else
+ cout << "(" << matrix_no << ")Found a possible conflict.";
+
+ cout << "(" << matrix_no << ") || Old maxlevel:" << maxlevel << " new maxlevel:" << this_maxlevel;
+ cout << "(" << matrix_no << ") || Old size:" << size << " new size:" << this_size << endl;
+ #endif
+
+ maxlevel = this_maxlevel;
+ size = this_size;
+ best_row = row;
+}
+
+Gaussian::gaussian_ret Gaussian::handle_matrix_prop(matrixset& m, const uint32_t row)
+{
+ #ifdef VERBOSE_DEBUG
+ 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);
+ #ifdef VERBOSE_DEBUG
+ cout << "(" << matrix_no << ")matrix prop clause: " << tmp_clause << std::endl;
+ cout << endl;
+ #endif
+
+ 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);
+ release_assert(cl == NULL);
+ release_assert(solver.ok);
+ return unit_propagation;
+ }
+ default:
+ if (solver.decisionLevel() == 0) {
+ solver.uncheckedEnqueue(tmp_clause[0]);
+ return unit_propagation;
+ }
+ Clause& cla = *(Clause*)solver.clauseAllocator.XorClause_new(tmp_clause, xorEqualFalse);
+ 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));
+ solver.uncheckedEnqueue(cla[0], solver.clauseAllocator.getOffset(&cla));
+ return propagation;
+ }
+
+ return propagation;
+}
+
+void Gaussian::disable_if_necessary()
+{
+ if (//nof_conflicts >= 0
+ //&& conflictC >= nof_conflicts/8
+ !config.dontDisable
+ && called > 50
+ && useful_confl*2+useful_prop < (uint32_t)((double)called*0.05) )
+ disabled = true;
+}
+
+llbool Gaussian::find_truths(vec<Lit>& learnt_clause, uint64_t& conflictC)
+{
+ PropBy confl;
+
+ disable_if_necessary();
+ if (should_check_gauss(solver.decisionLevel())) {
+ called++;
+ gaussian_ret g = gaussian(confl);
+
+ switch (g) {
+ case conflict: {
+ useful_confl++;
+ llbool ret = solver.handle_conflict(learnt_clause, confl, conflictC, true);
+ if (confl.isClause())
+ solver.clauseAllocator.clauseFree(solver.clauseAllocator.getPointer(confl.getClause()));
+
+ if (ret != l_Nothing) return ret;
+ return l_Continue;
+ }
+ case unit_propagation:
+ unit_truths++;
+ case propagation:
+ useful_prop++;
+ return l_Continue;
+ case unit_conflict: {
+ unit_truths++;
+ useful_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.getOtherLit();
+ solver.cancelUntil(0);
+
+ #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);
+ return l_Continue;
+ }
+ case nothing:
+ break;
+ }
+ }
+
+ return l_Nothing;
+}
+
+template<class T>
+void Gaussian::print_matrix_row(const T& row) const
+{
+ unsigned long int var = 0;
+ while (true) {
+ var = row.scan(var);
+ if (var == ULONG_MAX) break;
+
+ else cout << col_to_var_original[var]+1 << ", ";
+ var++;
+ }
+ cout << "final:" << row.is_true() << endl;;
+}
+
+template<class T>
+void Gaussian::print_matrix_row_with_assigns(const T& row) const
+{
+ unsigned long int col = 0;
+ while (true) {
+ col = row.scan(col);
+ if (col == ULONG_MAX) break;
+
+ else {
+ Var var = col_to_var_original[col];
+ cout << var+1 << "(" << lbool_to_string(solver.assigns[var]) << ")";
+ cout << ", ";
+ }
+ col++;
+ }
+ if (!row.is_true()) cout << "xorEqualFalse";
+}
+
+string Gaussian::lbool_to_string(const lbool toprint)
+{
+ if (toprint == l_True)
+ return "true";
+ if (toprint == l_False)
+ return "false";
+ if (toprint == l_Undef)
+ return "undef";
+
+ assert(false);
+ return "";
+}
+
+
+void Gaussian::print_stats() const
+{
+ if (called > 0) {
+ cout.setf(std::ios::fixed);
+ std::cout << " Gauss(" << matrix_no << ") useful";
+ cout << " prop: " << std::setprecision(2) << std::setw(5) << ((double)useful_prop/(double)called)*100.0 << "% ";
+ cout << " confl: " << std::setprecision(2) << std::setw(5) << ((double)useful_confl/(double)called)*100.0 << "% ";
+ if (disabled) std::cout << "disabled";
+ } else
+ std::cout << " Gauss(" << matrix_no << ") not called.";
+}
+
+void Gaussian::print_matrix_stats() const
+{
+ cout << "matrix size: " << cur_matrixset.num_rows << " x " << cur_matrixset.num_cols << endl;
+}
+
+
+void Gaussian::reset_stats()
+{
+ useful_prop = 0;
+ useful_confl = 0;
+ called = 0;
+ disabled = false;
+}
+
+bool Gaussian::check_no_conflict(matrixset& m) const
+{
+ 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;
+ return false;
+ }
+ }
+ return true;
+}
+
+void Gaussian::print_matrix(matrixset& m) const
+{
+ 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)
+ cout << " (considered past the end)";
+ cout << endl;
+ }
+}
+
+void Gaussian::print_last_one_in_cols(matrixset& m) const
+{
+ 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;
+ }
+}
+
+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()) {
+ #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()) {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "row " << (*r) << " is a conflict, but we didn't catch it" << std::endl;
+ #endif
+ return false;
+ }
+ }
+ return true;
+}
+
+bool Gaussian::check_last_one_in_cols(matrixset& m) const
+{
+ 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;
+ }
+ if (real_last > last)
+ return false;
+ }
+
+ return true;
+}
+
+void Gaussian::check_matrix_against_varset(PackedMatrix& matrix, const matrixset& m) const
+{
+ 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);
+ assert(m.var_is_set[var]);
+ final = !final;
+ } else if (solver.assigns[var] == l_False) {
+ assert(!mat_row[col]);
+ assert(m.col_to_var[col] == unassigned_var);
+ assert(m.var_is_set[var]);
+ } else if (solver.assigns[var] == l_Undef) {
+ assert(m.col_to_var[col] != unassigned_var);
+ assert(!m.var_is_set[var]);
+ assert(mat_row[col]);
+ } else assert(false);
+
+ col++;
+ }
+ if ((final^!mat_row.is_true()) != !var_row.is_true()) {
+ cout << "problem with row:"; print_matrix_row_with_assigns(var_row); cout << endl;
+ assert(false);
+ }
+ }
+}
+
+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);
+ if (j-1 > m.first_one_in_row[m.num_rows-1]) {
+ until2 = m.num_rows;
+ #ifdef VERBOSE_DEBUG
+ cout << "j-1 > m.first_one_in_row[m.num_rows-1]" << "j:" << j << " m.first_one_in_row[m.num_rows-1]:" << m.first_one_in_row[m.num_rows-1] << endl;
+ #endif
+ }
+ for (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;
+ cout << " m.first_one_in_row[m.num_rows-1]:" << m.first_one_in_row[m.num_rows-1] << endl;
+ cout << "first_one_in_row:" << m.first_one_in_row[i2] << endl;
+ cout << "num_cols:" << m.num_cols << endl;
+ cout << "popcnt:" << m.matrix.getMatrixAt(i2).popcnt() << endl;
+ cout << "popcnt_is_one():" << m.matrix.getMatrixAt(i2).popcnt_is_one() << endl;
+ cout << "popcnt_is_one("<< m.first_one_in_row[i2] <<"): " << m.matrix.getMatrixAt(i2).popcnt_is_one(m.first_one_in_row[i2]) << endl;
+ #endif
+
+ for (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]]);
+ assert(m.matrix.getMatrixAt(i2).popcnt_is_one() ==
+ m.matrix.getMatrixAt(i2).popcnt_is_one(m.first_one_in_row[i2]));
+ }
+ }
+}
diff --git a/src/prop/cryptominisat/Solver/Gaussian.h b/src/prop/cryptominisat/Solver/Gaussian.h
new file mode 100644
index 000000000..6e4151811
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/Gaussian.h
@@ -0,0 +1,243 @@
+/***********************************************************************************
+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 GAUSSIAN_H
+#define GAUSSIAN_H
+
+#include <vector>
+#include <limits>
+#include <string>
+#include <utility>
+
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include "SolverTypes.h"
+#include "Solver.h"
+#include "GaussianConfig.h"
+#include "PackedMatrix.h"
+#include "BitArray.h"
+
+//#define VERBOSE_DEBUG
+//#define DEBUG_GAUSS
+
+namespace CMSat {
+
+using std::string;
+using std::pair;
+using std::vector;
+
+class Clause;
+
+class Gaussian
+{
+public:
+ Gaussian(Solver& solver, const GaussConf& config, const uint32_t matrix_no, const vector<XorClause*>& xorclauses);
+ ~Gaussian();
+
+ bool full_init();
+ llbool find_truths(vec<Lit>& learnt_clause, uint64_t& conflictC);
+
+ //statistics
+ void print_stats() const;
+ void print_matrix_stats() const;
+ uint32_t get_called() const;
+ uint32_t get_useful_prop() const;
+ uint32_t get_useful_confl() const;
+ bool get_disabled() const;
+ uint32_t get_unit_truths() const;
+ void set_disabled(const bool toset);
+
+ //functions used throughout the Solver
+ void canceling(const uint32_t sublevel);
+
+ friend class ClauseAllocator;
+
+protected:
+ Solver& solver;
+
+ //Gauss high-level configuration
+ const GaussConf& config;
+ const uint32_t matrix_no;
+ vector<XorClause*> xorclauses;
+
+ enum gaussian_ret {conflict, unit_conflict, propagation, unit_propagation, nothing};
+ 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]
+ uint32_t badlevel;
+
+ class matrixset
+ {
+ public:
+ PackedMatrix matrix; // The matrix, updated to reflect variable assignements
+ 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)
+ 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;
+ uint32_t removeable_cols; // the number of columns that have been zeroed out (i.e. assigned)
+ };
+
+ //Saved states
+ vector<matrixset> matrix_sets; // The matrixsets for depths 'decision_from' + 0, 'decision_from' + only_nth_gaussian_save, 'decision_from' + 2*only_nth_gaussian_save, ... 'decision_from' + 'decision_until'.
+ matrixset cur_matrixset; // The current matrixset, i.e. the one we are working on, or the last one we worked on
+
+ //Varibales to keep Gauss state
+ bool messed_matrix_vars_since_reversal;
+ int gauss_last_level;
+ vector<pair<Clause*, uint32_t> > clauses_toclear;
+ bool disabled; // Gauss is disabled
+
+ //State of current elimnation
+ 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
+ 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
+ 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
+ uint32_t eliminate(matrixset& matrix); //does the actual gaussian elimination
+
+ //matrix update functions
+ 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 uint32_t last_level) const;
+
+ //conflict&propagation handling
+ 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 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 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 uint32_t decisionlevel) 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?
+ bool nothing_to_propagate(matrixset& m) const; // Are there any conflicts of propagations that matrixset 'm' clauses?
+ template<class T>
+ void print_matrix_row(const T& row) const; // Print matrix row 'row'
+ template<class T>
+ void print_matrix_row_with_assigns(const T& row) const;
+ void check_matrix_against_varset(PackedMatrix& matrix,const matrixset& m) const;
+ bool check_last_one_in_cols(matrixset& m) 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 string lbool_to_string(const lbool toprint);
+};
+
+inline bool Gaussian::should_init() const
+{
+ return (config.decision_until > 0);
+}
+
+inline bool Gaussian::should_check_gauss(const uint32_t decisionlevel) const
+{
+ return (!disabled
+ && decisionlevel < config.decision_until);
+}
+
+inline void Gaussian::canceling(const uint32_t sublevel)
+{
+ if (disabled)
+ return;
+ 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);
+ for (; c >= (int)sublevel; c--) {
+ Var var = solver.trail[c].var();
+ if (var < var_is_in.getSize()
+ && var_is_in[var]
+ && cur_matrixset.var_is_set[var]) {
+ messed_matrix_vars_since_reversal = true;
+ return;
+ }
+ }
+}
+
+inline uint32_t Gaussian::get_unit_truths() const
+{
+ return unit_truths;
+}
+
+inline uint32_t Gaussian::get_called() const
+{
+ return called;
+}
+
+inline uint32_t Gaussian::get_useful_prop() const
+{
+ return useful_prop;
+}
+
+inline uint32_t Gaussian::get_useful_confl() const
+{
+ return useful_confl;
+}
+
+inline bool Gaussian::get_disabled() const
+{
+ return disabled;
+}
+
+inline void Gaussian::set_disabled(const bool toset)
+{
+ disabled = toset;
+}
+
+//std::ostream& operator << (std::ostream& os, const vec<Lit>& v);
+
+}
+
+#endif //GAUSSIAN_H
diff --git a/src/prop/cryptominisat/Solver/GaussianConfig.h b/src/prop/cryptominisat/Solver/GaussianConfig.h
new file mode 100644
index 000000000..afcdefbf1
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/GaussianConfig.h
@@ -0,0 +1,63 @@
+/***********************************************************************************
+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 GAUSSIANCONFIG_H
+#define GAUSSIANCONFIG_H
+
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include "PackedRow.h"
+
+namespace CMSat
+{
+
+class GaussConf
+{
+ public:
+
+ GaussConf() :
+ only_nth_gauss_save(2)
+ , decision_until(0)
+ , dontDisable(false)
+ , noMatrixFind(false)
+ , orderCols(true)
+ , iterativeReduce(true)
+ , maxMatrixRows(1000)
+ , minMatrixRows(20)
+ , maxNumMatrixes(3)
+ {
+ }
+
+ //tuneable gauss parameters
+ 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
+};
+
+}
+
+#endif //GAUSSIANCONFIG_H
diff --git a/src/prop/cryptominisat/Solver/Main.cpp b/src/prop/cryptominisat/Solver/Main.cpp
new file mode 100644
index 000000000..111683ee8
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/Main.cpp
@@ -0,0 +1,974 @@
+/*****************************************************************************
+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.
+******************************************************************************/
+
+/**
+@mainpage CryptoMiniSat
+@author Mate Soos, and collaborators
+
+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>
+#include <errno.h>
+#include <string.h>
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+#include <omp.h>
+#include <map>
+#include <set>
+#include "constants.h"
+
+#include <signal.h>
+
+#include "time_mem.h"
+#include "constants.h"
+#include "DimacsParser.h"
+
+#if defined(__linux__)
+#include <fpu_control.h>
+#endif
+
+#include "Main.h"
+
+using namespace CMSat;
+
+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)
+{
+}
+
+std::map<uint32_t, Solver*> solversToInterrupt;
+std::set<uint32_t> finished;
+
+void Main::readInAFile(const std::string& filename, Solver& solver)
+{
+ #pragma omp single
+ if (solver.conf.verbosity >= 1) {
+ std::cout << "c Reading file '" << filename << "'" << std::endl;
+ }
+ #ifdef DISABLE_ZLIB
+ FILE * in = fopen(filename.c_str(), "rb");
+ #else
+ gzFile in = gzopen(filename.c_str(), "rb");
+ #endif // DISABLE_ZLIB
+
+ #pragma omp single
+ 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);
+
+ #ifdef DISABLE_ZLIB
+ fclose(in);
+ #else
+ gzclose(in);
+ #endif // DISABLE_ZLIB
+}
+
+void Main::readInStandardInput(Solver& solver)
+{
+ 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
+
+ if (in == NULL) {
+ std::cout << "ERROR! Could not open standard input for reading" << std::endl;
+ exit(1);
+ }
+
+ DimacsParser parser(&solver, debugLib, debugNewVar, grouping);
+ parser.parse_DIMACS(in);
+
+ #ifndef DISABLE_ZLIB
+ gzclose(in);
+ #endif // DISABLE_ZLIB
+}
+
+
+
+void Main::parseInAllFiles(Solver& solver)
+{
+ double myTime = cpuTime();
+
+ //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);
+ }
+
+ //Then read the main file or standard input
+ if (!fileNamePresent) {
+ readInStandardInput(solver);
+ } else {
+ string filename = argv[(twoFileNamesPresent ? argc-2 : argc-1)];
+ readInAFile(filename, solver);
+ }
+
+ if (solver.conf.verbosity >= 1) {
+ std::cout << "c Parsing time: "
+ << std::fixed << std::setw(5) << std::setprecision(2) << (cpuTime() - myTime)
+ << " s" << std::endl;
+ }
+}
+
+
+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]);
+#else
+ printf("USAGE: %s [options] <input-file> <result-output-file>\n\n where input may be either in plain or gzipped DIMACS.\n\n", argv[0]);
+#endif // DISABLE_ZLIB
+ printf("OPTIONS:\n\n");
+ printf(" --polarity-mode = {true,false,rnd,auto} [default: auto]. Selects the default\n");
+ printf(" polarity mode. Auto is the Jeroslow&Wang method\n");
+ //printf(" -decay = <num> [ 0 - 1 ]\n");
+ printf(" --rnd-freq = <num> [ 0 - 1 ]\n");
+ printf(" --verbosity = {0,1,2}\n");
+ printf(" --randomize = <seed> [0 - 2^32-1] Sets random seed, used for picking\n");
+ printf(" decision variables (default = 0)\n");
+ printf(" --restrict = <num> [1 - varnum] when picking random variables to branch\n");
+ printf(" on, pick one that in the 'num' most active vars useful\n");
+ printf(" for cryptographic problems, where the question is the key,\n");
+ printf(" which is usually small (e.g. 80 bits)\n");
+ printf(" --gaussuntil = <num> Depth until which Gaussian elimination is active.\n");
+ printf(" Giving 0 switches off Gaussian elimination\n");
+ printf(" --restarts = <num> [1 - 2^32-1] No more than the given number of\n");
+ printf(" restarts will be performed during search\n");
+ printf(" --nonormxorfind Don't find and collect >2-long xor-clauses from\n");
+ printf(" regular clauses\n");
+ printf(" --nobinxorfind Don't find and collect 2-long xor-clauses from\n");
+ printf(" regular clauses\n");
+ printf(" --noregbxorfind Don't regularly find and collect 2-long xor-clauses\n");
+ printf(" from regular clauses\n");
+ printf(" --doextendedscc 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");
+ printf(" --debuglib Solve at specific 'c Solver::solve()' points in the CNF\n");
+ printf(" file. Used to debug file generated by Solver's\n");
+ printf(" needLibraryCNFFile() function\n");
+ printf(" --debugnewvar Add new vars at specific 'c Solver::newVar()' points in \n");
+ printf(" the CNF file. Used to debug file generated by Solver's\n");
+ printf(" needLibraryCNFFile() function.\n");
+ printf(" --novarreplace Don't perform variable replacement. Needed for programmable\n");
+ printf(" solver feature\n");
+ printf(" --restart = {auto, static, dynamic} Which kind of restart strategy to\n");
+ printf(" follow. Default is auto\n");
+ printf(" --dumplearnts = <filename> If interrupted or reached restart limit, dump\n");
+ printf(" the learnt clauses to the specified file. Maximum size of\n");
+ printf(" dumped clauses can be specified with next option.\n");
+ printf(" --maxdumplearnts = [0 - 2^32-1] When dumping the learnts to file, what\n");
+ 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(" 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(" --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");
+#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");
+ printf(" elimination. Effectively disables iterative reduction\n");
+ printf(" of the matrix\n");
+ 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", 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", gaussconfig.minMatrixRows);
+ printf(" --savematrix = [0 - 2^32-1] Save matrix every Nth decision level.\n");
+ 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(" --nohyperbinres Don't add binary clauses when doing failed lit probing.\n");
+ printf(" --noremovebins Don't remove useless binary clauses\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(" --nobxor Don't find equivalent lits during failed lit search\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(" --nootfsubsume Don't do on-the-fly subsumption after conf. gen.\n");
+ #ifdef ENABLE_UNWIND_GLUE
+ 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);
+ #endif //ENABLE_UNWIND_GLUE
+ printf(" throw the clause away on backtrack.\n");
+ printf(" --threads = Num threads (default is 1)\n");
+ printf(" --plain Get rid of all simplification algorithms\n");
+ printf(" --maxconfl = [0..2^63-1] Maximum number of conflicts to do\n");
+ printf("\n");
+}
+
+
+const char* Main::hasPrefix(const char* str, const char* prefix)
+{
+ int len = strlen(prefix);
+ if (strncmp(str, prefix, len) == 0)
+ return str + len;
+ else
+ return NULL;
+}
+
+void Main::printResultFunc(const Solver& S, const lbool ret, FILE* res)
+{
+ 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) {
+ if (!printResult) std::cout << "c SATISFIABLE" << std::endl;
+ else std::cout << "s SATISFIABLE" << std::endl;
+ } else if (ret == l_False) {
+ if (!printResult) std::cout << "c UNSATISFIABLE" << std::endl;
+ else 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;
+ 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)
+ conf.polarity_mode = polarity_true;
+ else if (strcmp(value, "false") == 0)
+ conf.polarity_mode = polarity_false;
+ else if (strcmp(value, "rnd") == 0)
+ conf.polarity_mode = polarity_rnd;
+ else if (strcmp(value, "auto") == 0)
+ conf.polarity_mode = polarity_auto;
+ else {
+ printf("ERROR! unknown polarity-mode %s\n", value);
+ exit(0);
+ }
+
+ } else if ((value = hasPrefix(argv[i], "--rnd-freq="))) {
+ double rnd;
+ if (sscanf(value, "%lf", &rnd) <= 0 || rnd < 0 || rnd > 1) {
+ printf("ERROR! illegal rnRSE ERROR!d-freq constant %s\n", value);
+ exit(0);
+ }
+ conf.random_var_freq = rnd;
+
+ /*} else if ((value = hasPrefix(argv[i], "--decay="))) {
+ double decay;
+ if (sscanf(value, "%lf", &decay) <= 0 || decay <= 0 || decay > 1) {
+ printf("ERROR! illegal decay constant %s\n", value);
+ exit(0);
+ }
+ conf.var_decay = 1 / decay;*/
+
+ } else if ((value = hasPrefix(argv[i], "--verbosity="))) {
+ int verbosity = (int)strtol(value, NULL, 10);
+ if (verbosity == EINVAL || verbosity == ERANGE) {
+ printf("ERROR! illegal verbosity level %s\n", value);
+ exit(0);
+ }
+ conf.verbosity = verbosity;
+ } else if ((value = hasPrefix(argv[i], "--randomize="))) {
+ int seed;
+ if (sscanf(value, "%d", &seed) < 0) {
+ printf("ERROR! illegal seed %s\n", value);
+ exit(0);
+ }
+ conf.origSeed = seed;
+ } else if ((value = hasPrefix(argv[i], "--restrict="))) {
+ int branchTo;
+ if (sscanf(value, "%d", &branchTo) < 0 || branchTo < 1) {
+ printf("ERROR! illegal restricted pick branch number %d\n", branchTo);
+ exit(0);
+ }
+ conf.restrictPickBranch = branchTo;
+ } else if ((value = hasPrefix(argv[i], "--gaussuntil="))) {
+ int until;
+ if (sscanf(value, "%d", &until) < 0) {
+ printf("ERROR! until %s\n", value);
+ exit(0);
+ }
+ gaussconfig.decision_until = until;
+ } else if ((value = hasPrefix(argv[i], "--restarts="))) {
+ int maxrest;
+ if (sscanf(value, "%d", &maxrest) < 0 || maxrest == 0) {
+ printf("ERROR! illegal maximum restart number %d\n", maxrest);
+ exit(0);
+ }
+ conf.maxRestarts = maxrest;
+ } else if ((value = hasPrefix(argv[i], "--dumplearnts="))) {
+ 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);
+ }
+ 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 (!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) {
+ std::cout << "ERROR! wrong maximum dumped learnt clause size is illegal: " << tmp << std::endl;
+ exit(0);
+ }
+ conf.maxDumpLearntsSize = (uint32_t)tmp;
+ } else if ((value = hasPrefix(argv[i], "--maxsolutions="))) {
+ int tmp;
+ if (sscanf(value, "%d", &tmp) < 0 || tmp < 0) {
+ 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"))) {
+ conf.greedyUnbound = true;
+ } else if ((value = hasPrefix(argv[i], "--nonormxorfind"))) {
+ conf.doFindXors = false;
+ } else if ((value = hasPrefix(argv[i], "--nobinxorfind"))) {
+ conf.doFindEqLits = false;
+ } else if ((value = hasPrefix(argv[i], "--noregbxorfind"))) {
+ conf.doRegFindEqLits = false;
+ } else if ((value = hasPrefix(argv[i], "--doextendedscc"))) {
+ conf.doExtendedSCC = true;
+ } else if ((value = hasPrefix(argv[i], "--noconglomerate"))) {
+ conf.doConglXors = false;
+ } else if ((value = hasPrefix(argv[i], "--nosimplify"))) {
+ 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"))) {
+ conf.doReplace = false;
+ } else if ((value = hasPrefix(argv[i], "--nofailedlit"))) {
+ conf.doFailedLit = false;
+ } else if ((value = hasPrefix(argv[i], "--nodisablegauss"))) {
+ gaussconfig.dontDisable = true;
+ } else if ((value = hasPrefix(argv[i], "--maxnummatrixes="))) {
+ int 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"))) {
+ conf.doHeuleProcess = false;
+ } else if ((value = hasPrefix(argv[i], "--nosatelite"))) {
+ conf.doSatELite = false;
+ } else if ((value = hasPrefix(argv[i], "--noxorsubs"))) {
+ conf.doXorSubsumption = false;
+ } else if ((value = hasPrefix(argv[i], "--nohyperbinres"))) {
+ conf.doHyperBinRes = false;
+ } else if ((value = hasPrefix(argv[i], "--novarelim"))) {
+ conf.doVarElim = false;
+ } else if ((value = hasPrefix(argv[i], "--nosubsume1"))) {
+ conf.doSubsume1 = false;
+ } else if ((value = hasPrefix(argv[i], "--nomatrixfind"))) {
+ gaussconfig.noMatrixFind = true;
+ } else if ((value = hasPrefix(argv[i], "--noiterreduce"))) {
+ gaussconfig.iterativeReduce = false;
+ } else if ((value = hasPrefix(argv[i], "--noordercol"))) {
+ 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);
+ }
+ 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);
+ }
+ gaussconfig.minMatrixRows = rows;
+ } else if ((value = hasPrefix(argv[i], "--savematrix"))) {
+ int every;
+ if (sscanf(value, "%d", &every) < 0) {
+ printf("ERROR! savematrix: %s\n", value);
+ exit(0);
+ }
+ 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);
+ exit(0);
+ } else if ((value = hasPrefix(argv[i], "--restart="))) {
+ if (strcmp(value, "auto") == 0)
+ conf.fixRestartType = auto_restart;
+ else if (strcmp(value, "static") == 0)
+ conf.fixRestartType = static_restart;
+ else if (strcmp(value, "dynamic") == 0)
+ conf.fixRestartType = dynamic_restart;
+ else {
+ printf("ERROR! unknown restart type %s\n", value);
+ exit(0);
+ }
+ } else if ((value = hasPrefix(argv[i], "--nosolprint"))) {
+ printResult = false;
+ //} else if ((value = hasPrefix(argv[i], "--addoldlearnts"))) {
+ // conf.readdOldLearnts = true;
+ } else if ((value = hasPrefix(argv[i], "--nohyperbinres"))) {
+ conf.doHyperBinRes= false;
+ } else if ((value = hasPrefix(argv[i], "--noremovebins"))) {
+ conf.doRemUselessBins = false;
+ } else if ((value = hasPrefix(argv[i], "--nosubswithnbins"))) {
+ conf.doSubsWNonExistBins = false;
+ } else if ((value = hasPrefix(argv[i], "--nosubswithbins"))) {
+ 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.doCacheOTFSSRSet = false;
+ conf.doCacheOTFSSR = false;
+ } else if ((value = hasPrefix(argv[i], "--nootfsubsume"))) {
+ conf.doOTFSubsume = false;
+ } else if ((value = hasPrefix(argv[i], "--noremlbins"))) {
+ conf.doRemUselessLBins = false;
+ } else if ((value = hasPrefix(argv[i], "--maxconfl="))) {
+ int maxconfl = 0;
+ if (sscanf(value, "%d", &maxconfl) < 0 || maxconfl < 2) {
+ printf("ERROR! max confl: %s\n", value);
+ exit(0);
+ }
+ conf.maxConfl = maxconfl;
+ } else if ((value = hasPrefix(argv[i], "--plain"))) {
+ conf.isPlain = true;
+ conf.doOTFSubsume = false;
+ conf.doFindXors = false;
+ conf.doFindEqLits = false;
+ conf.doRegFindEqLits = false;
+ conf.doExtendedSCC = false;
+ conf.doConglXors = false;
+ conf.doSchedSimp = false;
+ conf.doReplace = false;
+ conf.doFailedLit = false;
+ conf.doHeuleProcess = false;
+ conf.doSatELite = false;
+ conf.doXorSubsumption = false;
+ printResult = false;
+ conf.doVarElim = false;
+ //nomatrixfind
+ gaussconfig.orderCols = false;
+ gaussconfig.iterativeReduce = false;
+ conf.doHyperBinRes = false;
+ conf.doRemUselessBins = false;
+ conf.doRemUselessLBins = false;
+ conf.doSubsWBins = false;
+ conf.doSubsWNonExistBins = false;
+ conf.doClausVivif = false;
+ conf.doCalcReach = false;
+ conf.doBXor = false;
+ conf.doMinimLMoreRecur = false;
+ conf.doMinimLearntMore = false;
+ conf.doCacheOTFSSR = false;
+ } else if ((value = hasPrefix(argv[i], "--nobxor"))) {
+ conf.doBXor = false;
+ #ifdef ENABLE_UNWIND_GLUE
+ } 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;
+ #endif //ENABLE_UNWIND_GLUE
+ } 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 {
+ //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;
+ }
+ }
+
+ 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(_FPU_EXTENDED) && defined(_FPU_DOUBLE)
+ fpu_control_t oldcw, newcw;
+ _FPU_GETCW(oldcw);
+ newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
+ _FPU_SETCW(newcw);
+ #pragma omp single
+ if (verbosity >= 1) {
+ printf("c WARNING: for repeatability, setting FPU to use double precision\n");
+ }
+#endif
+}
+
+void Main::printVersionInfo(const uint32_t verbosity)
+{
+#pragma omp single
+ 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
+ }
+}
+
+int Main::singleThreadSolve()
+{
+ Solver solver(conf, gaussconfig);
+ solversToInterrupt[0] = &solver;
+
+ 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 (conf.needToDumpLearnts) {
+ if (solver.dumpSortedLearnts(conf.learntsFilename, conf.maxDumpLearntsSize))
+ std::cout << "c Sorted learnt clauses dumped to file '" << conf.learntsFilename << "'" << std::endl;
+ else {
+ std::cout << "Error: Cannot open file '" << conf.learntsFilename << "' to write learnt clauses!" << std::endl;;
+ exit(-1);
+ }
+ }
+ if (conf.needToDumpOrig) {
+ if (ret == l_False && conf.origFilename == "stdout") {
+ std::cout << "p cnf 0 1" << std::endl;
+ std::cout << "0";
+ } else if (ret == l_True && conf.origFilename == "stdout") {
+ std::cout << "p cnf " << solver.model.size() << " " << solver.model.size() << std::endl;
+ for (uint32_t i = 0; i < solver.model.size(); i++) {
+ std::cout << (solver.model[i] == l_True ? "" : "-") << i+1 << " 0" << std::endl;
+ }
+ } else {
+ if (!solver.dumpOrigClauses(conf.origFilename)) {
+ std::cout << "Error: Cannot open file '" << conf.origFilename << "' to write learnt clauses!" << std::endl;
+ exit(-1);
+ }
+ if (conf.verbosity >= 1)
+ 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);
+
+ return correctReturnValue(ret);
+}
+
+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);
+ }
+
+ #ifdef NDEBUG
+ // (faster than "return", which will invoke the destructor for 'Solver')
+ exit(retval);
+ #endif
+ return retval;
+}
+
+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;
+
+ Solver solver(myConf, gaussconfig, &sharedData);
+ #pragma omp critical (solversToInterr)
+ {
+ solversToInterrupt[num] = &solver;
+ //std::cout << "Solver num " << num << " is to be interrupted " << std::endl;
+ }
+
+ printVersionInfo(myConf.verbosity);
+ setDoublePrecision(myConf.verbosity);
+
+ parseInAllFiles(solver);
+ lbool ret = solver.solve();
+ #pragma omp critical (finished)
+ {
+ finished.insert(num);
+ }
+
+ 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++;
+ }
+ }
+ }
+ }
+ bool mustWait = true;
+ while (mustWait) {
+ #pragma omp critical (finished)
+ if (finished.size() == (unsigned)numThreads) mustWait = false;
+ }
+ if (conf.needToDumpLearnts) {
+ if (!solver.dumpSortedLearnts(conf.learntsFilename, conf.maxDumpLearntsSize)) {
+ std::cout << "Error: Cannot open file '" << conf.learntsFilename << "' to write learnt clauses!" << std::endl;;
+ exit(-1);
+ }
+ if (conf.verbosity >= 1) {
+ std::cout << "c Sorted learnt clauses dumped to file '"
+ << conf.learntsFilename << "'" << std::endl;
+ }
+ }
+ if (conf.needToDumpOrig) {
+ if (!solver.dumpOrigClauses(conf.origFilename)) {
+ std::cout << "Error: Cannot open file '" << conf.origFilename << "' to write learnt clauses!" << std::endl;
+ exit(-1);
+ }
+ if (conf.verbosity >= 1)
+ std::cout << "c Simplified original clauses dumped to file '"
+ << conf.origFilename << "'" << std::endl;
+ }
+
+ FILE* res = openOutputFile();
+ if (conf.verbosity >= 1) solver.printStats();
+ printResultFunc(solver, ret, res);
+
+ retval = correctReturnValue(ret);
+ exit(retval);
+ }
+ return retval;
+}
+
+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);
+ }
+
+ 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;
+ }
+ int retval = oneThreadSolve();
+
+ #pragma omp single
+ finalRetVal = retval;
+ }
+
+ return finalRetVal;
+}
+
+/**
+@brief For correctly and gracefully exiting
+
+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)
+{
+ #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);
+ }
+ }
+}
+
+int main(int argc, char** argv)
+{
+ Main main(argc, argv);
+ main.parseCommandLine();
+ signal(SIGINT, SIGINT_handler);
+ //signal(SIGHUP,SIGINT_handler);
+
+ try {
+ if (main.numThreads == 1)
+ return main.singleThreadSolve();
+ else
+ return main.multiThreadSolve();
+ } catch (std::bad_alloc) {
+ std::cerr << "Memory manager cannot handle the load. Sorry. Exiting." << std::endl;
+ exit(-1);
+ } catch (std::out_of_range oor) {
+ std::cerr << oor.what() << std::endl;
+ exit(-1);
+ } catch (CMSat::DimacsParseError dpe) {
+ std::cerr << "PARSE ERROR!" << dpe.what() << std::endl;
+ exit(3);
+ }
+ return 0;
+}
diff --git a/src/prop/cryptominisat/Solver/Main.h b/src/prop/cryptominisat/Solver/Main.h
new file mode 100644
index 000000000..a2af6dc34
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/Main.h
@@ -0,0 +1,74 @@
+/*****************************************************************************
+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>
+#include <vector>
+#ifndef DISABLE_ZLIB
+#include <zlib.h>
+#endif // DISABLE_ZLIB
+
+#include "Solver.h"
+#include "SharedData.h"
+
+namespace CMSat {
+
+using std::string;
+
+class Main
+{
+ public:
+ Main(int argc, char** argv);
+
+ void parseCommandLine();
+
+ int singleThreadSolve();
+ int oneThreadSolve();
+ 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
diff --git a/src/prop/cryptominisat/Solver/Makefile.am b/src/prop/cryptominisat/Solver/Makefile.am
new file mode 100644
index 000000000..72a0d2fab
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/Makefile.am
@@ -0,0 +1,33 @@
+#noinst_LTLIBRARIES = libcryptominisat.la
+lib_LTLIBRARIES = libcryptominisat.la
+
+libcryptominisat_la_LDFLAGS = -release 2.9.2 -no-undefined
+
+AM_CXXFLAGS = -Wall $(all_includes) -I$(srcdir) -I$(srcdir)/../MTRand -I$(srcdir)/../mtl $(OPENMP_CXXFLAGS)
+
+pkgincludesubdir = $(includedir)/cryptominisat/Solver
+pkgincludesub_HEADERS = BitArray.h Clause.h CSet.h MatrixFinder.h Solver.h Subsumer.h Watched.h \
+ BoundedQueue.h ClauseOffset.h DimacsParser.h GaussianConfig.h OnlyNonLearntBins.h SolverTypes.h \
+ time_mem.h XorFinder.h ClauseAllocator.h CompleteDetachReattacher.h DoublePackedRow.h Gaussian.h PackedMatrix.h \
+ PropBy.h StateSaver.h UselessBinRemover.h XorSubsumer.h ClauseCleaner.h constants.h FailedLitSearcher.h \
+ PackedRow.h RestartTypeChooser.h StreamBuffer.h VarReplacer.h XSet.h BothCache.h SolverConf.h \
+ SCCFinder.h SharedData.h ClauseVivifier.h DataSync.h Main.h \
+ msvc/stdint.h
+
+libcryptominisat_la_SOURCES = \
+ ClauseCleaner.cpp FailedLitSearcher.cpp \
+ VarReplacer.cpp \
+ MatrixFinder.cpp \
+ Solver.cpp XorFinder.cpp \
+ PackedRow.cpp Gaussian.cpp StateSaver.cpp \
+ RestartTypeChooser.cpp Subsumer.cpp XorSubsumer.cpp \
+ SolverMisc.cpp SolverDebug.cpp ClauseAllocator.cpp \
+ UselessBinRemover.cpp SCCFinder.cpp ClauseVivifier.cpp \
+ CompleteDetachReattacher.cpp DimacsParser.cpp \
+ OnlyNonLearntBins.cpp SolverConf.cpp DataSync.cpp \
+ BothCache.cpp
+
+bin_PROGRAMS = cryptominisat
+cryptominisat_LDADD = libcryptominisat.la
+cryptominisat_LDFLAGS = -static -lz $(OPENMP_CXXFLAGS)
+cryptominisat_SOURCES = Main.cpp
diff --git a/src/prop/cryptominisat/Solver/Makefile.in b/src/prop/cryptominisat/Solver/Makefile.in
new file mode 100644
index 000000000..dd524fba2
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/Makefile.in
@@ -0,0 +1,665 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+bin_PROGRAMS = cryptominisat$(EXEEXT)
+subdir = Solver
+DIST_COMMON = $(pkgincludesub_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
+ "$(DESTDIR)$(pkgincludesubdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libcryptominisat_la_LIBADD =
+am_libcryptominisat_la_OBJECTS = ClauseCleaner.lo FailedLitSearcher.lo \
+ VarReplacer.lo MatrixFinder.lo Solver.lo XorFinder.lo \
+ PackedRow.lo Gaussian.lo StateSaver.lo RestartTypeChooser.lo \
+ Subsumer.lo XorSubsumer.lo SolverMisc.lo SolverDebug.lo \
+ ClauseAllocator.lo UselessBinRemover.lo SCCFinder.lo \
+ ClauseVivifier.lo CompleteDetachReattacher.lo DimacsParser.lo \
+ OnlyNonLearntBins.lo SolverConf.lo DataSync.lo BothCache.lo
+libcryptominisat_la_OBJECTS = $(am_libcryptominisat_la_OBJECTS)
+libcryptominisat_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(libcryptominisat_la_LDFLAGS) $(LDFLAGS) -o $@
+PROGRAMS = $(bin_PROGRAMS)
+am_cryptominisat_OBJECTS = Main.$(OBJEXT)
+cryptominisat_OBJECTS = $(am_cryptominisat_OBJECTS)
+cryptominisat_DEPENDENCIES = libcryptominisat.la
+cryptominisat_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(cryptominisat_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libcryptominisat_la_SOURCES) $(cryptominisat_SOURCES)
+DIST_SOURCES = $(libcryptominisat_la_SOURCES) $(cryptominisat_SOURCES)
+HEADERS = $(pkgincludesub_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENMP_CXXFLAGS = @OPENMP_CXXFLAGS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+#noinst_LTLIBRARIES = libcryptominisat.la
+lib_LTLIBRARIES = libcryptominisat.la
+libcryptominisat_la_LDFLAGS = -release 2.9.2 -no-undefined
+AM_CXXFLAGS = -Wall $(all_includes) -I$(srcdir) -I$(srcdir)/../MTRand -I$(srcdir)/../mtl $(OPENMP_CXXFLAGS)
+pkgincludesubdir = $(includedir)/cryptominisat/Solver
+pkgincludesub_HEADERS = BitArray.h Clause.h CSet.h MatrixFinder.h Solver.h Subsumer.h Watched.h \
+ BoundedQueue.h ClauseOffset.h DimacsParser.h GaussianConfig.h OnlyNonLearntBins.h SolverTypes.h \
+ time_mem.h XorFinder.h ClauseAllocator.h CompleteDetachReattacher.h DoublePackedRow.h Gaussian.h PackedMatrix.h \
+ PropBy.h StateSaver.h UselessBinRemover.h XorSubsumer.h ClauseCleaner.h constants.h FailedLitSearcher.h \
+ PackedRow.h RestartTypeChooser.h StreamBuffer.h VarReplacer.h XSet.h BothCache.h SolverConf.h \
+ SCCFinder.h SharedData.h ClauseVivifier.h DataSync.h Main.h \
+ msvc/stdint.h
+
+libcryptominisat_la_SOURCES = \
+ ClauseCleaner.cpp FailedLitSearcher.cpp \
+ VarReplacer.cpp \
+ MatrixFinder.cpp \
+ Solver.cpp XorFinder.cpp \
+ PackedRow.cpp Gaussian.cpp StateSaver.cpp \
+ RestartTypeChooser.cpp Subsumer.cpp XorSubsumer.cpp \
+ SolverMisc.cpp SolverDebug.cpp ClauseAllocator.cpp \
+ UselessBinRemover.cpp SCCFinder.cpp ClauseVivifier.cpp \
+ CompleteDetachReattacher.cpp DimacsParser.cpp \
+ OnlyNonLearntBins.cpp SolverConf.cpp DataSync.cpp \
+ BothCache.cpp
+
+cryptominisat_LDADD = libcryptominisat.la
+cryptominisat_LDFLAGS = -static -lz $(OPENMP_CXXFLAGS)
+cryptominisat_SOURCES = Main.cpp
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Solver/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu Solver/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libcryptominisat.la: $(libcryptominisat_la_OBJECTS) $(libcryptominisat_la_DEPENDENCIES)
+ $(libcryptominisat_la_LINK) -rpath $(libdir) $(libcryptominisat_la_OBJECTS) $(libcryptominisat_la_LIBADD) $(LIBS)
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+cryptominisat$(EXEEXT): $(cryptominisat_OBJECTS) $(cryptominisat_DEPENDENCIES)
+ @rm -f cryptominisat$(EXEEXT)
+ $(cryptominisat_LINK) $(cryptominisat_OBJECTS) $(cryptominisat_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BothCache.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClauseAllocator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClauseCleaner.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClauseVivifier.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompleteDetachReattacher.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DataSync.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DimacsParser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FailedLitSearcher.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Gaussian.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MatrixFinder.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OnlyNonLearntBins.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PackedRow.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RestartTypeChooser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SCCFinder.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Solver.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SolverConf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SolverDebug.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SolverMisc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StateSaver.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Subsumer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UselessBinRemover.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VarReplacer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XorFinder.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XorSubsumer.Plo@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pkgincludesubHEADERS: $(pkgincludesub_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgincludesubdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgincludesubdir)"
+ @list='$(pkgincludesub_HEADERS)'; test -n "$(pkgincludesubdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludesubdir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludesubdir)" || exit $$?; \
+ done
+
+uninstall-pkgincludesubHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgincludesub_HEADERS)'; test -n "$(pkgincludesubdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(pkgincludesubdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(pkgincludesubdir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
+install-binPROGRAMS: install-libLTLIBRARIES
+
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgincludesubdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
+ clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pkgincludesubHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \
+ uninstall-pkgincludesubHEADERS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic clean-libLTLIBRARIES clean-libtool ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-binPROGRAMS \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-libLTLIBRARIES \
+ install-man install-pdf install-pdf-am \
+ install-pkgincludesubHEADERS install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-binPROGRAMS uninstall-libLTLIBRARIES \
+ uninstall-pkgincludesubHEADERS
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/prop/cryptominisat/Solver/MatrixFinder.cpp b/src/prop/cryptominisat/Solver/MatrixFinder.cpp
new file mode 100644
index 000000000..4a1522d80
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/MatrixFinder.cpp
@@ -0,0 +1,248 @@
+/***********************************************************************************
+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 "MatrixFinder.h"
+
+#include "Solver.h"
+#include "Gaussian.h"
+#include "GaussianConfig.h"
+#include "ClauseCleaner.h"
+#include "time_mem.h"
+
+#include <set>
+#include <map>
+#include <iomanip>
+#include <math.h>
+
+//#define VERBOSE_DEBUG
+//#define PART_FINDING
+
+using namespace CMSat;
+
+using std::set;
+using std::map;
+
+MatrixFinder::MatrixFinder(Solver& _solver) :
+ solver(_solver)
+{
+}
+
+inline 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 bool MatrixFinder::firstPartOfSecond(const XorClause& c1, const XorClause& c2) const
+{
+ uint32_t i1, i2;
+ for (i1 = 0, i2 = 0; i1 < c1.size() && i2 < c2.size();) {
+ if (c1[i1].var() != c2[i2].var())
+ i2++;
+ else {
+ i1++;
+ i2++;
+ }
+ }
+
+ return (i1 == c1.size());
+}
+
+bool MatrixFinder::findMatrixes()
+{
+ assert(solver.decisionLevel() == 0);
+ assert(solver.ok);
+
+ table.clear();
+ table.resize(solver.nVars(), var_Undef);
+ 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.conf.verbosity >=1)
+ std::cout << "c Matrix finding disabled through switch. Putting all xors into matrix." << std::endl;
+ vector<XorClause*> xorclauses;
+ xorclauses.reserve(solver.xorclauses.size());
+ for (uint32_t i = 0; i < solver.xorclauses.size(); i++)
+ xorclauses.push_back(solver.xorclauses[i]);
+ 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<uint32_t> tomerge;
+ vector<Var> newSet;
+ for (Lit *l = &(**c)[0], *end2 = l + (**c).size(); l != end2; l++) {
+ if (table[l->var()] != var_Undef)
+ tomerge.insert(table[l->var()]);
+ else
+ newSet.push_back(l->var());
+ }
+ if (tomerge.size() == 1) {
+ const 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<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]] = matrix_no;
+ reverseTable[matrix_no] = newSet;
+ matrix_no++;
+ }
+
+ #ifdef VERBOSE_DEBUG
+ for (map<uint32_t, vector<Var> >::iterator it = reverseTable.begin(), end = reverseTable.end(); it != end; it++) {
+ std::cout << "-- set begin --" << std::endl;
+ for (vector<Var>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
+ std::cout << *it2 << ", ";
+ }
+ std::cout << "-------" << std::endl;
+ }
+ #endif
+
+ uint32_t numMatrixes = setMatrixes();
+
+ if (solver.conf.verbosity >=1)
+ std::cout << "c Finding matrixes : " << cpuTime() - myTime
+ << " s (found " << numMatrixes << ")"
+ << std::endl;
+
+ for (vector<Gaussian*>::iterator gauss = solver.gauss_matrixes.begin(), end = solver.gauss_matrixes.end(); gauss != end; gauss++) {
+ if (!(*gauss)->full_init()) return false;
+ }
+
+ return true;
+}
+
+uint32_t MatrixFinder::setMatrixes()
+{
+ 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<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 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 (uint32_t i = 0; i < matrix_no; i++)
+ findParts(xorFingerprintInMatrix[i], xorsInMatrix[i]);
+ #endif //PART_FINDING
+
+ uint32_t realMatrixNum = 0;
+ for (int a = matrix_no-1; a != -1; a--) {
+ uint32_t i = numXorInMatrix[a].first;
+
+ if (numXorInMatrix[a].second < 3)
+ continue;
+
+ 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 (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 <= solver.gaussconfig.maxNumMatrixes)
+ {
+ if (solver.conf.verbosity >=1)
+ std::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.conf.verbosity >=1 /*&& numXorInMatrix[a].second >= 20*/)
+ std::cout << "c Unused Matrix ";
+ }
+ if (solver.conf.verbosity >=1 /*&& numXorInMatrix[a].second >= 20*/) {
+ std::cout << std::setw(7) << numXorInMatrix[a].second << " x" << std::setw(5) << reverseTable[i].size();
+ std::cout << " density:" << std::setw(5) << std::fixed << std::setprecision(1) << density << "%";
+ std::cout << " xorlen avg:" << std::setw(5) << std::fixed << std::setprecision(2) << avg;
+ std::cout << " stdev:" << std::setw(6) << std::fixed << std::setprecision(2) << stdDeviation << std::endl;
+ }
+ }
+
+ return realMatrixNum;
+}
+
+void MatrixFinder::findParts(vector<Var>& xorFingerprintInMatrix, vector<XorClause*>& xorsInMatrix)
+{
+ uint32_t ai = 0;
+ for (XorClause **a = &xorsInMatrix[0], **end = a + xorsInMatrix.size(); a != end; a++, ai++) {
+ const Var fingerprint = xorFingerprintInMatrix[ai];
+ uint32_t ai2 = 0;
+ for (XorClause **a2 = &xorsInMatrix[0]; a2 != end; a2++, ai2++) {
+ if (ai == ai2) continue;
+ const Var fingerprint2 = xorFingerprintInMatrix[ai2];
+ if (((fingerprint & fingerprint2) == fingerprint) && firstPartOfSecond(**a, **a2)) {
+ std::cout << "First part of second:" << std::endl;
+ (*a)->plainPrint();
+ (*a2)->plainPrint();
+ std::cout << "END" << std::endl;
+ }
+ }
+ }
+}
diff --git a/src/prop/cryptominisat/Solver/MatrixFinder.h b/src/prop/cryptominisat/Solver/MatrixFinder.h
new file mode 100644
index 000000000..21210b0f7
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/MatrixFinder.h
@@ -0,0 +1,70 @@
+/***********************************************************************************
+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 MATRIXFINDER_H
+#define MATRIXFINDER_H
+
+#include <vector>
+#include <map>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include "Clause.h"
+#include "Solver.h"
+
+namespace CMSat {
+
+class Solver;
+
+using std::map;
+using std::vector;
+using std::pair;
+
+class MatrixFinder {
+
+ public:
+ MatrixFinder(Solver& solver);
+ bool findMatrixes();
+
+ private:
+ uint32_t setMatrixes();
+
+ struct mysorter
+ {
+ bool operator () (const pair<uint32_t, uint32_t>& left, const pair<uint32_t, uint32_t>& right)
+ {
+ return left.second < right.second;
+ }
+ };
+
+ void findParts(vector<Var>& xorFingerprintInMatrix, vector<XorClause*>& xorsInMatrix);
+ inline Var fingerprint(const XorClause& c) const;
+ inline bool firstPartOfSecond(const XorClause& c1, const XorClause& c2) const;
+
+ map<uint32_t, vector<Var> > reverseTable; //matrix -> vars
+ vector<Var> table; //var -> matrix
+ uint32_t matrix_no;
+
+ Solver& solver;
+};
+
+}
+
+#endif //MATRIXFINDER_H
diff --git a/src/prop/cryptominisat/Solver/OnlyNonLearntBins.cpp b/src/prop/cryptominisat/Solver/OnlyNonLearntBins.cpp
new file mode 100644
index 000000000..021178b08
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/OnlyNonLearntBins.cpp
@@ -0,0 +1,84 @@
+/***********************************************************************
+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 "OnlyNonLearntBins.h"
+
+#include <iomanip>
+#include "Solver.h"
+#include "Clause.h"
+#include "VarReplacer.h"
+#include "ClauseCleaner.h"
+#include "time_mem.h"
+
+using namespace CMSat;
+
+OnlyNonLearntBins::OnlyNonLearntBins(Solver& _solver) :
+ solver(_solver)
+{}
+
+/**
+@brief Propagate recursively on non-learnt binaries
+*/
+bool OnlyNonLearntBins::propagate()
+{
+ while (solver.qhead < solver.trail.size()) {
+ Lit p = solver.trail[solver.qhead++];
+ vec<WatchedBin> & wbin = binwatches[p.toInt()];
+ 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()) {
+ solver.uncheckedEnqueueLight(k->impliedLit);
+ } else if (val == l_False) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/**
+@brief Fill internal watchlists with non-binary clauses
+*/
+bool OnlyNonLearntBins::fill()
+{
+ uint32_t numBins = 0;
+ double myTime = cpuTime();
+ binwatches.growTo(solver.nVars()*2);
+
+ uint32_t wsLit = 0;
+ for (const vec<Watched> *it = solver.watches.getData(), *end = solver.watches.getDataEnd(); it != end; it++, wsLit++) {
+ const vec<Watched>& ws = *it;
+ for (vec<Watched>::const_iterator it2 = ws.getData(), end2 = ws.getDataEnd(); it2 != end2; it2++) {
+ if (it2->isBinary() && !it2->getLearnt()) {
+ binwatches[wsLit].push(WatchedBin(it2->getOtherLit()));
+ numBins++;
+ }
+ }
+ }
+
+ 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"
+ << " num non-learnt bins: " << std::setw(10) << numBins
+ << std::endl;
+ }
+
+ return true;
+}
diff --git a/src/prop/cryptominisat/Solver/OnlyNonLearntBins.h b/src/prop/cryptominisat/Solver/OnlyNonLearntBins.h
new file mode 100644
index 000000000..7092331e6
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/OnlyNonLearntBins.h
@@ -0,0 +1,72 @@
+/***********************************************************************
+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 ONLYNONLEARNTBINS_H
+#define ONLYNONLEARNTBINS_H
+
+#include "Solver.h"
+
+namespace CMSat {
+
+/**
+@brief Handles propagation, addition&removal of non-learnt binary clauses
+
+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
+ bool propagate();
+
+ //Management of clauses
+ bool fill();
+
+ //helper
+ inline uint32_t getWatchSize(const Lit lit) const;
+ inline const vec<vec<WatchedBin> >& getBinWatches() const;
+
+ private:
+ vec<vec<WatchedBin> > binwatches; ///<Internal wathclists for non-learnt binary clauses
+
+ Solver& solver;
+};
+
+inline uint32_t OnlyNonLearntBins::getWatchSize(const Lit lit) const
+{
+ return binwatches[lit.toInt()].size();
+}
+
+inline const vec<vec<OnlyNonLearntBins::WatchedBin> >& OnlyNonLearntBins::getBinWatches() const
+{
+ return binwatches;
+}
+
+}
+
+#endif //ONLYNONLEARNTBINS_H
diff --git a/src/prop/cryptominisat/Solver/PackedMatrix.h b/src/prop/cryptominisat/Solver/PackedMatrix.h
new file mode 100644
index 000000000..2879a4b45
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/PackedMatrix.h
@@ -0,0 +1,221 @@
+/***********************************************************************************
+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 PACKEDMATRIX_H
+#define PACKEDMATRIX_H
+
+#include <algorithm>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include "PackedRow.h"
+
+//#define DEBUG_MATRIX
+
+namespace CMSat {
+
+class PackedMatrix
+{
+public:
+ PackedMatrix() :
+ mp(NULL)
+ , numRows(0)
+ , numCols(0)
+ {
+ }
+
+ PackedMatrix(const PackedMatrix& b) :
+ numRows(b.numRows)
+ , numCols(b.numCols)
+ {
+ #ifdef DEBUG_MATRIX
+ assert(b.numRows > 0 && b.numCols > 0);
+ #endif
+
+ mp = new uint64_t[numRows*2*(numCols+1)];
+ memcpy(mp, b.mp, sizeof(uint64_t)*numRows*2*(numCols+1));
+ }
+
+ ~PackedMatrix()
+ {
+ delete[] mp;
+ }
+
+ 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)) {
+ delete[] mp;
+ mp = new uint64_t[num_rows*2*(num_cols+1)];
+ }
+ numRows = num_rows;
+ numCols = num_cols;
+ }
+
+ void resizeNumRows(const uint32_t num_rows)
+ {
+ #ifdef DEBUG_MATRIX
+ assert(num_rows <= numRows);
+ #endif
+
+ numRows = num_rows;
+ }
+
+ PackedMatrix& operator=(const PackedMatrix& b)
+ {
+ #ifdef DEBUG_MATRIX
+ //assert(b.numRows > 0 && b.numCols > 0);
+ #endif
+
+ if (numRows*2*(numCols+1) < b.numRows*2*(b.numCols+1)) {
+ delete[] mp;
+ mp = new uint64_t[b.numRows*2*(b.numCols+1)];
+ }
+
+ numRows = b.numRows;
+ numCols = b.numCols;
+ memcpy(mp, b.mp, sizeof(uint64_t)*numRows*2*(numCols+1));
+
+ return *this;
+ }
+
+ inline PackedRow getMatrixAt(const uint32_t i)
+ {
+ #ifdef DEBUG_MATRIX
+ assert(i <= numRows);
+ #endif
+
+ return PackedRow(numCols, mp+i*2*(numCols+1));
+ }
+ inline PackedRow getVarsetAt(const uint32_t i)
+ {
+ #ifdef DEBUG_MATRIX
+ assert(i <= numRows);
+ #endif
+
+ return PackedRow(numCols, mp+i*2*(numCols+1)+(numCols+1));
+ }
+
+ inline PackedRow getMatrixAt(const uint32_t i) const
+ {
+ #ifdef DEBUG_MATRIX
+ assert(i <= numRows);
+ #endif
+
+ return PackedRow(numCols, mp+i*2*(numCols+1));
+ }
+
+ inline PackedRow getVarsetAt(const uint32_t i) const
+ {
+ #ifdef DEBUG_MATRIX
+ assert(i <= numRows);
+ #endif
+
+ return PackedRow(numCols, mp+i*2*(numCols+1)+(numCols+1));
+ }
+
+ class iterator
+ {
+ public:
+ friend class PackedMatrix;
+
+ PackedRow operator*()
+ {
+ return PackedRow(numCols, mp);
+ }
+
+ iterator& operator++()
+ {
+ mp += 2*(numCols+1);
+ return *this;
+ }
+
+ iterator operator+(const uint32_t num) const
+ {
+ iterator ret(*this);
+ ret.mp += 2*(numCols+1)*num;
+ return ret;
+ }
+
+ uint32_t operator-(const iterator& b) const
+ {
+ return (mp - b.mp)/(2*(numCols+1));
+ }
+
+ void operator+=(const uint32_t num)
+ {
+ mp += 2*(numCols+1)*num;
+ }
+
+ bool operator!=(const iterator& it) const
+ {
+ return mp != it.mp;
+ }
+
+ bool operator==(const iterator& it) const
+ {
+ return mp == it.mp;
+ }
+
+ private:
+ iterator(uint64_t* _mp, const uint32_t _numCols) :
+ mp(_mp)
+ , numCols(_numCols)
+ {}
+
+ uint64_t* mp;
+ const uint32_t numCols;
+ };
+
+ inline iterator beginMatrix()
+ {
+ return iterator(mp, numCols);
+ }
+
+ inline iterator endMatrix()
+ {
+ return iterator(mp+numRows*2*(numCols+1), numCols);
+ }
+
+ inline iterator beginVarset()
+ {
+ return iterator(mp+(numCols+1), numCols);
+ }
+
+ inline iterator endVarset()
+ {
+ return iterator(mp+(numCols+1)+numRows*2*(numCols+1), numCols);
+ }
+
+ inline uint32_t getSize() const
+ {
+ return numRows;
+ }
+
+private:
+
+ uint64_t* mp;
+ uint32_t numRows;
+ uint32_t numCols;
+};
+
+}
+
+#endif //PACKEDMATRIX_H
diff --git a/src/prop/cryptominisat/Solver/PackedRow.cpp b/src/prop/cryptominisat/Solver/PackedRow.cpp
new file mode 100644
index 000000000..8fd72dc25
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/PackedRow.cpp
@@ -0,0 +1,109 @@
+/***********************************************************************************
+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 "PackedRow.h"
+
+using namespace CMSat;
+
+bool PackedRow::operator ==(const PackedRow& b) const
+{
+ #ifdef DEBUG_ROW
+ assert(size > 0);
+ assert(b.size > 0);
+ assert(size == b.size);
+ #endif
+
+ return (std::equal(b.mp-1, b.mp+size, mp-1));
+}
+
+bool PackedRow::operator !=(const PackedRow& b) const
+{
+ #ifdef DEBUG_ROW
+ assert(size > 0);
+ assert(b.size > 0);
+ assert(size == b.size);
+ #endif
+
+ return (!std::equal(b.mp-1, b.mp+size, mp-1));
+}
+
+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 (uint32_t i2 = 0; i2 < 64; i2++) {
+ popcnt += (tmp & 1);
+ tmp >>= 1;
+ }
+ }
+ return popcnt;
+}
+
+uint32_t PackedRow::popcnt(const uint32_t from) const
+{
+ uint32_t popcnt = 0;
+ for (uint32_t i = from/64; i != size; i++) if (mp[i]) {
+ uint64_t tmp = mp[i];
+ uint32_t i2;
+ if (i == from/64) {
+ i2 = from%64;
+ tmp >>= i2;
+ } else
+ i2 = 0;
+ for (; i2 < 64; i2++) {
+ popcnt += (tmp & 1);
+ tmp >>= 1;
+ }
+ }
+ return popcnt;
+}
+
+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;
+ for (uint32_t i = 0; i < size; i++) for (uint32_t i2 = 0; i2 < 64; i2++) {
+ 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 bool val_bool = val.getBool();
+ tmp_clause.push(Lit(var, val_bool));
+ final ^= val_bool;
+ if (val.isUndef()) {
+ assert(!wasundef);
+ Lit tmp(tmp_clause[0]);
+ tmp_clause[0] = tmp_clause.last();
+ tmp_clause.last() = tmp;
+ wasundef = true;
+ }
+ }
+ col++;
+ }
+ if (wasundef) {
+ tmp_clause[0] ^= final;
+ //assert(ps != ps_first+1);
+ } else
+ assert(!final);
+
+ return wasundef;
+}
diff --git a/src/prop/cryptominisat/Solver/PackedRow.h b/src/prop/cryptominisat/Solver/PackedRow.h
new file mode 100644
index 000000000..a9d2d7134
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/PackedRow.h
@@ -0,0 +1,252 @@
+/***********************************************************************************
+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 PACKEDROW_H
+#define PACKEDROW_H
+
+//#define DEBUG_ROW
+
+#include <vector>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include "SolverTypes.h"
+#include "Vec.h"
+#include <string.h>
+#include <iostream>
+#include <algorithm>
+#include <limits>
+
+namespace CMSat {
+
+using std::vector;
+
+class PackedMatrix;
+
+class PackedRow
+{
+public:
+ bool operator ==(const PackedRow& b) const;
+ bool operator !=(const PackedRow& b) const;
+
+ PackedRow& operator=(const PackedRow& b)
+ {
+ #ifdef DEBUG_ROW
+ assert(size > 0);
+ 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
+ assert(size > 0);
+ 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
+ assert(size > 0);
+ 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
+ {
+ #if __GNUC__ >= 4
+ int ret = 0;
+ for (uint32_t i = 0; i != size; i++) {
+ ret += __builtin_popcount(mp[i]&0xffffffff);
+ ret += __builtin_popcount(mp[i]>>32);
+ if (ret > 1) return false;
+ }
+ return ret == 1;
+ #else
+ uint32_t popcount = 0;
+ for (uint32_t i = 0; i != size; i++) {
+ uint64_t tmp = mp[i];
+ while(tmp) {
+ popcount += tmp & 1;
+ tmp >>= 1;
+ }
+ }
+ return popcount == 1;
+ #endif
+ }
+
+ 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;
+ }
+
+ inline const uint64_t& is_true() const
+ {
+ return is_true_internal;
+ }
+
+ inline bool isZero() const
+ {
+ for (uint32_t i = 0; i != size; i++) {
+ if (mp[i]) return false;
+ }
+ return true;
+ }
+
+ inline void setZero()
+ {
+ memset(mp, 0, sizeof(uint64_t)*size);
+ }
+
+ inline void clearBit(const uint32_t i)
+ {
+ mp[i/64] &= ~((uint64_t)1 << (i%64));
+ }
+
+ inline void invert_is_true(const bool b = true)
+ {
+ is_true_internal ^= (uint64_t)b;
+ }
+
+ inline void setBit(const uint32_t i)
+ {
+ mp[i/64] |= ((uint64_t)1 << (i%64));
+ }
+
+ void swapBoth(PackedRow b)
+ {
+ #ifdef DEBUG_ROW
+ assert(size > 0);
+ 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++;
+ mp2++;
+ i--;
+ }
+ }
+
+ inline bool operator[](const uint32_t& i) const
+ {
+ #ifdef DEBUG_ROW
+ assert(size*64 > i);
+ #endif
+
+ return (mp[i/64] >> (i%64)) & 1;
+ }
+
+ template<class T>
+ void set(const T& v, const vector<uint16_t>& var_to_col, const uint32_t matrix_size)
+ {
+ assert(size == (matrix_size/64) + ((bool)(matrix_size % 64)));
+ //mp = new uint64_t[size];
+ setZero();
+ for (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.xorEqualFalse();
+ }
+
+ 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++) {
+ if (this->operator[](i)) return i;
+ }
+
+ return std::numeric_limits<unsigned long int>::max();
+ }
+
+private:
+ friend class PackedMatrix;
+ friend std::ostream& operator << (std::ostream& os, const PackedRow& m);
+
+ PackedRow(const uint32_t _size, uint64_t* const _mp) :
+ mp(_mp+1)
+ , is_true_internal(*_mp)
+ , size(_size)
+ {}
+
+ uint64_t* __restrict const mp;
+ uint64_t& is_true_internal;
+ const uint32_t size;
+};
+
+inline std::ostream& operator << (std::ostream& os, const PackedRow& m)
+{
+ for(uint32_t i = 0; i < m.size*64; i++) {
+ os << m[i];
+ }
+ os << " -- xor: " << m.is_true();
+ return os;
+}
+
+}
+
+#endif //PACKEDROW_H
diff --git a/src/prop/cryptominisat/Solver/PropBy.h b/src/prop/cryptominisat/Solver/PropBy.h
new file mode 100644
index 000000000..11e35cf2d
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/PropBy.h
@@ -0,0 +1,257 @@
+/***********************************************************************
+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"
+
+namespace CMSat {
+
+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())
+ {
+ }
+
+ bool isClause() const
+ {
+ return ((propType&2) == 0);
+ }
+
+ bool isBinary() const
+ {
+ return (propType == 2);
+ }
+
+ bool isTri() const
+ {
+ return (propType == 3);
+ }
+
+ Lit getOtherLit() const
+ {
+ #ifdef DEBUG_PROPAGATEFROM
+ assert(isBinary() || isTri());
+ #endif
+ return Lit::toLit(data1);
+ }
+
+ Lit getOtherLit2() const
+ {
+ #ifdef DEBUG_PROPAGATEFROM
+ assert(isTri());
+ #endif
+ return Lit::toLit(data2);
+ }
+
+ ClauseOffset getClause() const
+ {
+ #ifdef DEBUG_PROPAGATEFROM
+ assert(isClause());
+ #endif
+ return data2;
+ }
+
+ ClauseOffset getClause()
+ {
+ #ifdef DEBUG_PROPAGATEFROM
+ assert(isClause());
+ #endif
+ return data2;
+ }
+
+ bool isNULL() const
+ {
+ if (!isClause()) return false;
+ return propType == 0;
+ }
+};
+
+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(const PropByFull& other) :
+ type(other.type)
+ , clause(other.clause)
+ {
+ memcpy(lits, other.lits, sizeof(Lit)*3);
+ }
+
+ uint32_t size() const
+ {
+ switch (type) {
+ case 0 : return clause->size();
+ case 1 : return 2;
+ case 2 : return 3;
+ default:
+ assert(false);
+ return 0;
+ }
+ }
+
+ bool isNULL() const
+ {
+ return type == 0 && clause == NULL;
+ }
+
+ bool isClause() const
+ {
+ return type == 0;
+ }
+
+ bool isBinary() const
+ {
+ return type == 1;
+ }
+
+ bool isTri() const
+ {
+ return type == 2;
+ }
+
+ const Clause* getClause() const
+ {
+ return clause;
+ }
+
+ Clause* getClause()
+ {
+ return clause;
+ }
+
+ 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
diff --git a/src/prop/cryptominisat/Solver/RestartTypeChooser.cpp b/src/prop/cryptominisat/Solver/RestartTypeChooser.cpp
new file mode 100644
index 000000000..9432c374a
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/RestartTypeChooser.cpp
@@ -0,0 +1,181 @@
+/****************************************************************************
+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 "RestartTypeChooser.h"
+
+#include <utility>
+#include "Solver.h"
+
+//#define VERBOSE_DEBUG
+//#define PRINT_VARS
+
+using namespace CMSat;
+
+using std::pair;
+
+RestartTypeChooser::RestartTypeChooser(const Solver& s) :
+ solver(s)
+ , topX(100)
+ , limit(40)
+{
+}
+
+/**
+@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();
+ uint32_t sameIn = 0;
+ if (!firstVarsOld.empty()) {
+ 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++;
+ }
+ #ifdef VERBOSE_DEBUG
+ std::cout << " Same vars in first&second first 100: " << sameIn << std::endl;
+ #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
+*/
+RestartType RestartTypeChooser::choose()
+{
+ pair<double, double> mypair = countVarsDegreeStDev();
+ 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))
+ return static_restart;
+ else
+ return dynamic_restart;
+}
+
+/**
+@brief Calculates average for topx variable activity changes
+*/
+double RestartTypeChooser::avg() const
+{
+ double sum = 0.0;
+ 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
+*/
+double RestartTypeChooser::stdDeviation(vector<uint32_t>& measure) const
+{
+ double average = avg();
+ double variance = 0.0;
+ for (uint32_t i = 0; i != measure.size(); i++)
+ variance += pow((double)measure[i]-average, 2);
+ variance /= (double)measure.size();
+
+ return sqrt(variance);
+}
+
+void RestartTypeChooser::calcHeap()
+{
+ firstVars.clear();
+ firstVars.reserve(topX);
+ #ifdef PRINT_VARS
+ std::cout << "First vars:" << std::endl;
+ #endif
+ Heap<Solver::VarOrderLt> tmp(solver.order_heap);
+ uint32_t thisTopX = std::min(tmp.size(), topX);
+ for (uint32_t i = 0; i != thisTopX; i++) {
+ #ifdef PRINT_VARS
+ std::cout << tmp.removeMin()+1 << ", ";
+ #endif
+ firstVars.push_back(tmp.removeMin());
+ }
+ #ifdef PRINT_VARS
+ std::cout << std::endl;
+ #endif
+}
+
+std::pair<double, double> RestartTypeChooser::countVarsDegreeStDev() const
+{
+ vector<uint32_t> degrees;
+ degrees.resize(solver.nVars(), 0);
+ addDegrees(solver.clauses, degrees);
+ addDegreesBin(degrees);
+ addDegrees(solver.xorclauses, degrees);
+ uint32_t sum = 0;
+ uint32_t *i = &degrees[0], *j = i;
+ for (uint32_t *end = i + degrees.size(); i != end; i++) {
+ if (*i != 0) {
+ sum += *i;
+ *j++ = *i;
+ }
+ }
+ degrees.resize(degrees.size() - (i-j));
+
+ double avg = (double)sum/(double)degrees.size();
+ double stdDev = stdDeviation(degrees);
+
+ #ifdef VERBOSE_DEBUG
+ std::cout << "varsDegree avg:" << avg << " stdDev:" << stdDev << std::endl;
+ #endif
+
+ return std::make_pair(avg, stdDev);
+}
+
+template<class T>
+void RestartTypeChooser::addDegrees(const vec<T*>& cs, vector<uint32_t>& degrees) const
+{
+ for (T * const*c = cs.getData(), * const*end = c + cs.size(); c != end; c++) {
+ T& cl = **c;
+ if (cl.learnt()) continue;
+
+ for (const Lit *l = cl.getData(), *end2 = l + cl.size(); l != end2; l++) {
+ degrees[l->var()]++;
+ }
+ }
+}
+
+template void RestartTypeChooser::addDegrees(const vec<Clause*>& cs, vector<uint32_t>& degrees) const;
+template void RestartTypeChooser::addDegrees(const vec<XorClause*>& cs, vector<uint32_t>& degrees) const;
+
+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 (vec<Watched>::const_iterator it2 = ws.getData(), end2 = ws.getDataEnd(); it2 != end2; it2++) {
+ if (it2->isBinary() && lit.toInt() < it2->getOtherLit().toInt()) {
+ degrees[lit.var()]++;
+ degrees[it2->getOtherLit().var()]++;
+ }
+ }
+ }
+}
diff --git a/src/prop/cryptominisat/Solver/RestartTypeChooser.h b/src/prop/cryptominisat/Solver/RestartTypeChooser.h
new file mode 100644
index 000000000..6279b07a5
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/RestartTypeChooser.h
@@ -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/>.
+**************************************************************************************************/
+
+#ifndef RESTARTTYPECHOOSER_H
+#define RESTARTTYPECHOOSER_H
+
+#include "Solver.h"
+#include <vector>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include "SolverTypes.h"
+
+namespace CMSat {
+
+using std::vector;
+
+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:
+ RestartTypeChooser(const Solver& s);
+ void addInfo();
+ RestartType choose();
+ void reset();
+
+ private:
+ void calcHeap();
+ double avg() const;
+ std::pair<double, double> countVarsDegreeStDev() 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;
+ uint32_t topX; ///<The how many is the top X? 100 is default
+ uint32_t limit; ///<If top x contains on average this many common varables, we select MiniSat-type
+ vector<Var> sameIns;
+
+ 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()
+{
+ sameIns.clear();
+}
+
+}
+
+#endif //RESTARTTYPECHOOSER_H
diff --git a/src/prop/cryptominisat/Solver/SCCFinder.cpp b/src/prop/cryptominisat/Solver/SCCFinder.cpp
new file mode 100644
index 000000000..896566cad
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/SCCFinder.cpp
@@ -0,0 +1,142 @@
+/*****************************************************************************
+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 "../Solver/SolverTypes.h"
+#include "SCCFinder.h"
+#include "VarReplacer.h"
+#include <iomanip>
+#include "time_mem.h"
+#include "Subsumer.h"
+#include "XorSubsumer.h"
+
+using namespace CMSat;
+
+SCCFinder::SCCFinder(Solver& _solver) :
+ solver(_solver)
+ , varElimed1(_solver.subsumer->getVarElimed())
+ , varElimed2(_solver.xorSubsumer->getVarElimed())
+ , replaceTable(_solver.varReplacer->getReplaceTable())
+ , totalTime(0.0)
+{}
+
+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 >= 3 || (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 (vec<Watched>::const_iterator 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;
+ Lit prevLit = lit_Error;
+ for (vector<Lit>::iterator end = transCache.end(); it != end; it++) {
+ Lit lit = *it;
+ lit = replaceTable[lit.var()] ^ lit.sign();
+ if (lit == prevLit || lit == vertLit || varElimed1[lit.var()] || varElimed2[lit.var()])
+ continue;
+
+ *it2++ = lit;
+ prevLit = 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) {
+ //Cannot add to watchlists, because we are going THROUGH the watchlists (in a higher frame)
+ //so it might end up kicking the chair under ourselves
+ solver.varReplacer->replace(lits, xorEqualsFalse, true, false);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/prop/cryptominisat/Solver/SCCFinder.h b/src/prop/cryptominisat/Solver/SCCFinder.h
new file mode 100644
index 000000000..c1d876e2c
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/SCCFinder.h
@@ -0,0 +1,72 @@
+/*****************************************************************************
+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>
+
+namespace CMSat {
+
+class SCCFinder {
+ public:
+ SCCFinder(Solver& solver);
+ bool find2LongXors();
+ 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 double SCCFinder::getTotalTime() const
+{
+ return totalTime;
+}
+
+}
+
+#endif //SCCFINDER_H
diff --git a/src/prop/cryptominisat/Solver/SharedData.h b/src/prop/cryptominisat/Solver/SharedData.h
new file mode 100644
index 000000000..394b517f7
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/SharedData.h
@@ -0,0 +1,37 @@
+/**************************************************************************
+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>
+
+namespace CMSat {
+
+class SharedData
+{
+ public:
+ vec<lbool> value;
+ std::vector<std::vector<Lit> > bins;
+};
+
+}
+
+#endif //SHARED_DATA_H
diff --git a/src/prop/cryptominisat/Solver/Solver.cpp b/src/prop/cryptominisat/Solver/Solver.cpp
new file mode 100644
index 000000000..f73d6166e
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/Solver.cpp
@@ -0,0 +1,2924 @@
+/*****************************************************************************
+MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+glucose -- Gilles Audemard, Laurent Simon (2008)
+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.
+******************************************************************************/
+
+#include "Solver.h"
+#include <cmath>
+#include <string.h>
+#include <algorithm>
+#include <limits.h>
+#include <vector>
+#include <iomanip>
+#include <algorithm>
+
+#include "Clause.h"
+#include "time_mem.h"
+
+#include "VarReplacer.h"
+#include "XorFinder.h"
+#include "ClauseCleaner.h"
+#include "RestartTypeChooser.h"
+#include "FailedLitSearcher.h"
+#include "Subsumer.h"
+#include "XorSubsumer.h"
+#include "StateSaver.h"
+#include "SCCFinder.h"
+#include "SharedData.h"
+#include "ClauseVivifier.h"
+#include "Gaussian.h"
+#include "MatrixFinder.h"
+#include "DataSync.h"
+#include "BothCache.h"
+
+#ifdef VERBOSE_DEBUG
+#define UNWINDING_DEBUG
+#endif
+
+//#define DEBUG_UNCHECKEDENQUEUE_LEVEL0
+//#define VERBOSE_DEBUG_POLARITIES
+//#define DEBUG_DYNAMIC_RESTART
+//#define UNWINDING_DEBUG
+
+//**********************************
+// Constructor/Destructor:
+//**********************************
+
+using namespace CMSat;
+
+/**
+@brief Sets a sane default config and allocates handler classes
+*/
+Solver::Solver(const SolverConf& _conf, const GaussConf& _gaussconfig, SharedData* sharedData) :
+ // Parameters: (formerly in 'SearchParams')
+ 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)
+ , numBins (0)
+ , cla_inc (1)
+ , qhead (0)
+ , mtrand ((unsigned long int)0)
+
+ //variables
+ , order_heap (VarOrderLt(activity))
+ , var_inc (128)
+
+ //learnts
+ , numCleanedLearnts(1)
+ , nbClBeforeRed (NBCLAUSESBEFOREREDUCE)
+ , nbCompensateSubsumer (0)
+ , libraryCNFFile (NULL)
+ , restartType (static_restart)
+ , lastSelectedRestartType (static_restart)
+ , simplifying (false)
+ , totalSimplifyTime(0.0)
+ , simpDB_assigns (-1)
+ , simpDB_props (0)
+{
+ mtrand.seed(conf.origSeed);
+ #ifdef ENABLE_UNWIND_GLUE
+ assert(conf.maxGlue < MAX_THEORETICAL_GLUE);
+ #endif //ENABLE_UNWIND_GLUE
+ varReplacer = new VarReplacer(*this);
+ clauseCleaner = new ClauseCleaner(*this);
+ failedLitSearcher = new FailedLitSearcher(*this);
+ subsumer = new Subsumer(*this);
+ xorSubsumer = new XorSubsumer(*this);
+ restartTypeChooser = new RestartTypeChooser(*this);
+ sCCFinder = new SCCFinder(*this);
+ clauseVivifier = new ClauseVivifier(*this);
+ matrixFinder = new MatrixFinder(*this);
+ dataSync = new DataSync(*this, sharedData);
+
+}
+
+/**
+@brief Frees clauses and frees all allocated hander classes
+*/
+Solver::~Solver()
+{
+ clearGaussMatrixes();
+ delete matrixFinder;
+ delete varReplacer;
+ delete clauseCleaner;
+ delete failedLitSearcher;
+ delete subsumer;
+ delete xorSubsumer;
+ delete restartTypeChooser;
+
+ if (libraryCNFFile)
+ fclose(libraryCNFFile);
+}
+
+//**********************************
+// Minor methods
+//**********************************
+
+/**
+@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) throw (std::out_of_range)
+{
+ Var v = nVars();
+ if (v >= 1<<30)
+ throw std::out_of_range("ERROR! Variable requested is far too large");
+
+ watches .push(); // (list for positive literal)
+ watches .push(); // (list for negative literal)
+ reason .push(PropBy());
+ assigns .push(l_Undef);
+ level .push(-1);
+ binPropData.push();
+ activity .push(0);
+ seen .push_back(0);
+ seen .push_back(0);
+ #ifdef ENABLE_UNWIND_GLUE
+ unWindGlue.push(NULL);
+ #endif //ENABLE_UNWIND_GLUE
+
+ //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());
+
+ decision_var.push_back(dvar);
+ insertVarOrder(v);
+
+ varReplacer->newVar();
+ subsumer->newVar();
+ xorSubsumer->newVar();
+ dataSync->newVar();
+
+ insertVarOrder(v);
+
+ 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 xorEqualFalse, const bool learnt) throw (std::out_of_range)
+{
+ assert(qhead == trail.size());
+ assert(decisionLevel() == 0);
+
+ if (ps.size() > (0x01UL << 18))
+ throw std::out_of_range("Too long clause!");
+ std::sort(ps.getData(), ps.getDataEnd());
+ Lit p;
+ uint32_t i, j;
+ for (i = j = 0, p = lit_Undef; i != ps.size(); i++) {
+ if (ps[i].var() == p.var()) {
+ //added, but easily removed
+ j--;
+ p = lit_Undef;
+ if (!assigns[ps[i].var()].isUndef())
+ xorEqualFalse ^= assigns[ps[i].var()].getBool();
+ } else if (assigns[ps[i].var()].isUndef()) { //just add
+ ps[j++] = p = ps[i];
+ 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 (!xorEqualFalse) ok = false;
+ return NULL;
+ }
+ case 1: {
+ uncheckedEnqueue(Lit(ps[0].var(), xorEqualFalse));
+ ok = (propagate<false>().isNULL());
+ return NULL;
+ }
+ case 2: {
+ #ifdef VERBOSE_DEBUG
+ 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, xorEqualFalse, learnt);
+ return NULL;
+ }
+ default: {
+ assert(!learnt);
+ XorClause* c = clauseAllocator.XorClause_new(ps, xorEqualFalse);
+ attachClause(*c);
+ return c;
+ }
+ }
+}
+
+template XorClause* Solver::addXorClauseInt(vec<Lit>& ps, bool xorEqualFalse, const bool learnt);
+template XorClause* Solver::addXorClauseInt(XorClause& ps, bool xorEqualFalse, 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 xorEqualFalse) throw (std::out_of_range)
+{
+ assert(decisionLevel() == 0);
+ if (ps.size() > (0x01UL << 18))
+ throw std::out_of_range("Too long clause!");
+
+ if (libraryCNFFile) {
+ fprintf(libraryCNFFile, "x");
+ for (uint32_t i = 0; i < ps.size(); i++) ps[i].print(libraryCNFFile);
+ fprintf(libraryCNFFile, "0\n");
+ }
+
+ 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
+
+ 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;
+ }
+ }
+
+ XorClause* c = addXorClauseInt(ps, xorEqualFalse);
+ if (c != NULL) xorclauses.push(c);
+
+ return ok;
+}
+
+template bool Solver::addXorClause(vec<Lit>& ps, bool xorEqualFalse);
+template bool Solver::addXorClause(XorClause& ps, bool xorEqualFalse);
+
+/**
+@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
+ , const bool learnt, const uint32_t glue, const float miniSatActivity
+ , const bool inOriginalInput)
+{
+ assert(ok);
+#ifdef VERBOSE_DEBUG
+ std::cout << "Adding new clause: " << std::endl;
+ for(size_t i = 0; i< ps.size(); i++) {
+ printLit(ps[i]);
+ std::cout << " ";
+ }
+ std::cout << std::endl;
+#endif //VERBOSE_DEBUG
+
+ 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) {
+ 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;
+ } else if (ps.size() == 1) {
+ uncheckedEnqueue(ps[0]);
+ ok = (propagate<false>().isNULL());
+ return NULL;
+ }
+
+ if (ps.size() > 2) {
+ Clause* c = clauseAllocator.Clause_new(ps);
+ 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 bool learnt, const uint32_t glue, const float miniSatActivity, const bool inOriginalInput);
+template Clause* Solver::addClauseInt(vec<Lit>& ps, const bool learnt, const uint32_t glue, const float miniSatActivity, const bool inOriginalInput);
+
+template<class T> bool Solver::addClauseHelper(T& ps) throw (std::out_of_range)
+{
+ assert(decisionLevel() == 0);
+ if (ps.size() > (0x01UL << 18))
+ throw std::out_of_range("Too long clause!");
+
+ if (libraryCNFFile) {
+ for (uint32_t i = 0; i != ps.size(); i++) ps[i].print(libraryCNFFile);
+ fprintf(libraryCNFFile, "0\n");
+ }
+
+ 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()) {
+ for (uint32_t i = 0; i != ps.size(); i++) {
+ ps[i] = varReplacer->getReplaceTable()[ps[i].var()] ^ ps[i].sign();
+ if (subsumer->getVarElimed()[ps[i].var()] && !subsumer->unEliminate(ps[i].var()))
+ return false;
+ if (xorSubsumer->getVarElimed()[ps[i].var()] && !xorSubsumer->unEliminate(ps[i].var()))
+ return false;
+ }
+ }
+
+ for (uint32_t i = 0; i < ps.size(); i++) {
+ std::swap(ps[i], ps[(mtrand.randInt() % (ps.size()-i)) + i]);
+ }
+
+ 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)
+{
+ #ifdef VERBOSE_DEBUG
+ std::cout << "addClause() called with new clause: " << ps << std::endl;
+ #endif //VERBOSE_DEBUG
+ if (!addClauseHelper(ps)) return false;
+ Clause* c = addClauseInt(ps, false, 0, 0, true);
+ if (c != NULL) clauses.push(c);
+
+ return ok;
+}
+
+template bool Solver::addClause(vec<Lit>& ps);
+template bool Solver::addClause(Clause& ps);
+
+
+template<class T>
+bool Solver::addLearntClause(T& ps, const uint32_t glue, const float miniSatActivity)
+{
+ if (!addClauseHelper(ps)) return false;
+ Clause* c = addClauseInt(ps, true, glue, miniSatActivity, true);
+ if (c != NULL) learnts.push(c);
+
+ return ok;
+}
+
+template bool Solver::addLearntClause(vec<Lit>& ps, const uint32_t glue, const float miniSatActivity);
+template bool Solver::addLearntClause(Clause& ps, 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
+
+ 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));
+
+ #ifdef DUMP_STATS_FULL
+ if (learnt) {
+ watches[(~lit1).toInt()].last().glue = 2;
+ watches[(~lit2).toInt()].last().glue = 2;
+ } else {
+ watches[(~lit1).toInt()].last().glue = -1;
+ watches[(~lit2).toInt()].last().glue = -1;
+ }
+ #endif
+
+ 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() > 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]));
+
+ #ifdef DUMP_STATS_FULL
+ if (c.learnt()) {
+ watches[(~c[0]).toInt()].last().glue = 2;
+ watches[(~c[1]).toInt()].last().glue = 2;
+ watches[(~c[2]).toInt()].last().glue = 2;
+ } else {
+ watches[(~c[0]).toInt()].last().glue = -1;
+ watches[(~c[1]).toInt()].last().glue = -1;
+ watches[(~c[2]).toInt()].last().glue = -1;
+ }
+ #endif
+
+ } else {
+ ClauseOffset offset = clauseAllocator.getOffset(&c);
+ 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();
+}
+
+/**
+@brief Calls detachModifiedClause to do the heavy-lifting
+*/
+void Solver::detachClause(const XorClause& c)
+{
+ detachModifiedClause(c[0].var(), c[1].var(), c.size(), &c);
+}
+
+/**
+@brief Calls detachModifiedClause to do the heavy-lifting
+*/
+void Solver::detachClause(const Clause& c)
+{
+ detachModifiedClause(c[0], c[1], (c.size() == 3) ? c[2] : lit_Undef, c.size(), &c);
+}
+
+/**
+@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 > 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 {
+ fullClause:
+ removeWCl(watches[(~lit1).toInt()], offset);
+ removeWCl(watches[(~lit2).toInt()], offset);
+
+ }
+
+ if (address->learnt())
+ learnts_literals -= origSize;
+ else
+ clauses_literals -= origSize;
+}
+
+/**
+@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(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;
+}
+
+/**
+@brief Revert to the state at given level
+
+Also reverts all stuff in Gass-elimination
+*/
+void Solver::cancelUntil(int level)
+{
+ #ifdef VERBOSE_DEBUG
+ cout << "Canceling until level " << 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
+ cout << "Canceling var " << var+1 << " sublevel: " << sublevel << endl;
+ #endif
+ assigns[var] = l_Undef;
+ #ifdef ANIMATE3D
+ fprintf(stderr, "u %u\n", var);
+ #endif
+ insertVarOrder(var);
+ #ifdef ENABLE_UNWIND_GLUE
+ 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;
+ }
+ #endif //ENABLE_UNWIND_GLUE
+ }
+ qhead = trail_lim[level];
+ trail.shrink_(trail.size() - trail_lim[level]);
+ trail_lim.shrink_(trail_lim.size() - level);
+ }
+
+ #ifdef VERBOSE_DEBUG
+ cout << "Canceling finished. (now at level: " << decisionLevel() << " sublevel: " << trail.size()-1 << ")" << endl;
+ #endif
+}
+
+void Solver::cancelUntilLight()
+{
+ assert((int)decisionLevel() > 0);
+
+ 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.clear();
+}
+
+bool Solver::clearGaussMatrixes()
+{
+ 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;
+}
+
+/**
+@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(conf.polarity_mode) {
+ case polarity_false:
+ return true;
+ case polarity_true:
+ return false;
+ case polarity_rnd:
+ return mtrand.randInt(1);
+ case polarity_auto:
+ return true;
+ default:
+ assert(false);
+ }
+
+ return true;
+}
+
+/**
+@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.getData(), *end2 = c.getDataEnd(); it2 != end2; it2++) {
+ if (it2->sign()) votes[it2->var()] += divider;
+ else votes[it2->var()] -= divider;
+ }
+ }
+}
+
+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 (vec<Watched>::const_iterator 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.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 (conf.polarity_mode == polarity_auto) {
+ double myTime = cpuTime();
+
+ vec<double> votes(nVars(), 0.0);
+
+ tallyVotes(clauses, votes);
+ tallyVotesBin(votes);
+ tallyVotes(xorclauses, votes);
+
+ Var i = 0;
+ uint32_t posPolars = 0;
+ uint32_t undecidedPolars = 0;
+ 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);
+ #ifdef VERBOSE_DEBUG_POLARITIES
+ std::cout << !defaultPolarities[i] << ", ";
+ #endif //VERBOSE_DEBUG_POLARITIES
+ }
+
+ 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:: endl;
+ }
+ } else {
+ 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()]
+ || !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 Otherwise, we simply take the saved polarity
+*/
+Lit Solver::pickBranchLit()
+{
+ #ifdef VERBOSE_DEBUG
+ cout << "decision level: " << decisionLevel() << " ";
+ #endif
+
+ Var next = var_Undef;
+
+ /* Skip variables which have already been defined (this will usually happen
+ * because of propagations/implicit assignments) */
+ for (unsigned int i = decisionLevel(); i < branching_variables.size(); ++i) {
+ Var v = branching_variables[i];
+ if (v < nVars()
+ && !subsumer->getVarElimed()[v]
+ && !xorSubsumer->getVarElimed()[v]
+ && assigns[v] == l_Undef) {
+ next = v;
+ break;
+ }
+ }
+
+ bool random = mtrand.randDblExc() < conf.random_var_freq;
+
+ // Random decision:
+ if (next == var_Undef && random && !order_heap.empty()) {
+ 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]) {
+ if (order_heap.empty()) {
+ next = var_Undef;
+ break;
+ }
+
+ 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 (signSet) {
+ sign = signSetTo;
+ } else {
+ if (simplifying && random)
+ sign = mtrand.randInt(1);
+ else if (avgBranchDepth.isvalid())
+ sign = polarity[next] ^ (mtrand.randInt(avgBranchDepth.getAvgUInt() * ((lastSelectedRestartType == static_restart) ? 2 : 1) ) == 1);
+ else
+ sign = polarity[next];
+ }
+ }
+
+ assert(next == var_Undef || value(next) == l_Undef);
+
+ if (next == var_Undef) {
+ #ifdef VERBOSE_DEBUG
+ cout << "SAT!" << endl;
+ #endif
+ return lit_Undef;
+ } else {
+ Lit lit(next,sign);
+ #ifdef VERBOSE_DEBUG
+ assert(decision_var[lit.var()]);
+ cout << "decided on: " << lit.var()+1 << " to set:" << !lit.sign() << endl;
+ #endif
+ return lit;
+ }
+}
+
+/**
+@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<char>& seen)
+{
+ for (uint32_t i = 0; i != B.size(); i++)
+ seen[B[i].toInt()] = 1;
+ for (uint32_t i = 0; i != A.size(); i++) {
+ if (!seen[A[i].toInt()]) {
+ for (uint32_t i = 0; i != B.size(); i++)
+ seen[B[i].toInt()] = 0;
+ return false;
+ }
+ }
+ for (uint32_t i = 0; i != B.size(); i++)
+ seen[B[i].toInt()] = 0;
+ return true;
+}
+
+
+/**
+@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;
+
+ // Generate conflict clause:
+ //
+ out_learnt.push(); // (leave room for the asserting literal)
+ int index = trail.size() - 1;
+ out_btlevel = 0;
+
+ PropByFull confl(conflHalf, failBinLit, clauseAllocator);
+ PropByFull oldConfl;
+
+ do {
+ assert(!confl.isNULL()); // (otherwise should be UIP)
+
+ if (update && restartType == static_restart && confl.isClause() && confl.getClause()->learnt())
+ claBumpActivity(*confl.getClause());
+
+ 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++;
+ if (lastSelectedRestartType == dynamic_restart
+ && reason[q.var()].isClause()
+ && !reason[q.var()].isNULL()
+ && clauseAllocator.getPointer(reason[q.var()].getClause())->learnt())
+ lastDecisionLevel.push(q.var());
+ } else {
+ out_learnt.push(q);
+ if (level[my_var] > out_btlevel)
+ out_btlevel = level[my_var];
+ }
+ }
+ }
+
+ // Select next clause to look at:
+ while (!seen[trail[index--].var()]);
+ p = trail[index+1];
+ oldConfl = confl;
+ confl = PropByFull(reason[p.var()], failBinLit, clauseAllocator);
+ if (confl.isClause()) __builtin_prefetch(confl.getClause());
+ seen[p.var()] = 0;
+ pathC--;
+
+ } while (pathC > 0);
+ assert(pathC == 0);
+ out_learnt[0] = ~p;
+
+ // Simplify conflict clause:
+ //
+ uint32_t i, j;
+ 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)
+
+ out_learnt.copyTo(analyze_toclear);
+ for (i = j = 1; i < out_learnt.size(); i++)
+ if (reason[out_learnt[i].var()].isNULL() || !litRedundant(out_learnt[i], abstract_level))
+ out_learnt[j++] = out_learnt[i];
+ } else {
+ out_learnt.copyTo(analyze_toclear);
+ for (i = j = 1; i < out_learnt.size(); i++) {
+ PropByFull c(reason[out_learnt[i].var()], failBinLit, clauseAllocator);
+
+ 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;
+ }
+ }
+ }
+ }
+ 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:
+ //
+ if (out_learnt.size() == 1)
+ out_btlevel = 0;
+ else {
+ uint32_t max_i = 1;
+ 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;
+ std::swap(out_learnt[max_i], out_learnt[1]);
+ out_btlevel = level[out_learnt[1].var()];
+ }
+
+ if (lastSelectedRestartType == dynamic_restart) {
+ #ifdef UPDATE_VAR_ACTIVITY_BASED_ON_GLUE
+ for(uint32_t i = 0; i != lastDecisionLevel.size(); i++) {
+ PropBy cl = reason[lastDecisionLevel[i]];
+ if (cl.isClause() && clauseAllocator.getPointer(cl.getClause())->getGlue() < glue)
+ varBumpActivity(lastDecisionLevel[i]);
+ }
+ lastDecisionLevel.clear();
+ #endif
+ }
+
+ //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 (!conf.doOTFSubsume
+ || out_learnt.size() == 1
+ || !oldConfl.isClause()
+ || oldConfl.getClause()->isXor()
+ #ifdef ENABLE_UNWIND_GLUE
+ || (conf.doMaxGlueDel && oldConfl.getClause()->getGlue() > conf.maxGlue)
+ #endif //ENABLE_UNWIND_GLUE
+ || 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);
+ }
+ }
+
+ if (clDoMinLRec) moreRecurMinLDo++;
+ uint64_t thisUpdateTransOTFSSCache = UPDATE_TRANSOTFSSR_CACHE;
+ if (tot_literals > 80000000) thisUpdateTransOTFSSCache *= 2;
+
+ //To count the "amount of time" invested in doing transitive on-the-fly
+ //self-subsuming resolution
+ uint32_t moreRecurProp = 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 (vec<Watched>::iterator 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 (vec<Watched>::iterator 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);
+ analyze_toclear.push(p);
+ } else {
+ for (uint32_t j = top; j != analyze_toclear.size(); j++)
+ seen[analyze_toclear[j].var()] = 0;
+ analyze_toclear.shrink(analyze_toclear.size() - top);
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+
+/*_________________________________________________________________________________________________
+|
+| analyzeFinal : (p : Lit) -> [void]
+|
+| Description:
+| Specialized analysis procedure to express the final conflict in terms of assumptions.
+| Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and
+| stores the result in 'out_conflict'.
+|________________________________________________________________________________________________@*/
+void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict)
+{
+ out_conflict.clear();
+ out_conflict.push(p);
+
+ if (decisionLevel() == 0)
+ return;
+
+ seen[p.var()] = 1;
+
+ for (int32_t i = (int32_t)trail.size()-1; i >= (int32_t)trail_lim[0]; i--) {
+ Var x = trail[i].var();
+ if (seen[x]) {
+ if (reason[x].isNULL()) {
+ assert(level[x] > 0);
+ out_conflict.push(~trail[i]);
+ } else {
+ 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;
+ }
+ seen[x] = 0;
+ }
+ }
+
+ seen[p.var()] = 0;
+}
+
+/*_________________________________________________________________________________________________
+|
+| propagate : [void] -> [Clause*]
+|
+| Description:
+| Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned,
+| otherwise NULL.
+|
+| Post-conditions:
+| * the propagation queue is empty, even if there was a conflict.
+|________________________________________________________________________________________________@*/
+/**
+@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
+*/
+template<bool full>
+inline bool Solver::propBinaryClause(vec<Watched>::iterator &i, const Lit p, PropBy& confl)
+{
+ lbool val = value(i->getOtherLit());
+ if (val.isUndef()) {
+ if (full) uncheckedEnqueue(i->getOtherLit(), PropBy(p));
+ else uncheckedEnqueueLight(i->getOtherLit());
+ #ifdef DUMP_STATS_FULL
+ assert(((i->glue > 0) == i->getLearnt()));
+ if (full && i->glue > 0 && !simplifying) {
+ std::cout << "Prop by learnt size: " << 2 << std::endl;
+ std::cout << "Prop by learnt glue: " << i->glue << std::endl;
+ }
+ #endif //DUMP_STATS_FULL
+ } else if (val == l_False) {
+ confl = PropBy(p);
+ failBinLit = i->getOtherLit();
+ qhead = trail.size();
+ #ifdef DUMP_STATS_FULL
+ assert(((i->glue > 0) == i->getLearnt()));
+ if (full && i->glue > 0 && !simplifying) {
+ std::cout << "Confl by learnt size: " << 2 << std::endl;
+ std::cout << "Confl by learnt glue: " << i->glue << std::endl;
+ }
+ #endif //DUMP_STATS_FULL
+
+ 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
+*/
+template<bool full>
+inline bool Solver::propTriClause(vec<Watched>::iterator &i, const Lit p, PropBy& confl)
+{
+ lbool val = value(i->getOtherLit());
+ if (val == l_True) return true;
+
+ lbool val2 = value(i->getOtherLit2());
+ if (val.isUndef() && val2 == l_False) {
+ if (full) uncheckedEnqueue(i->getOtherLit(), PropBy(p, i->getOtherLit2()));
+ else uncheckedEnqueueLight(i->getOtherLit());
+ #ifdef DUMP_STATS_FULL
+ assert(conf.isPlain);
+ if (full && i->glue > 0 && !simplifying) {
+ std::cout << "Prop by learnt size: " << 3 << std::endl;
+ std::cout << "Prop by learnt glue: " << i->glue << std::endl;
+ }
+ #endif //DUMP_STATS_FULL
+ } else if (val == l_False && val2.isUndef()) {
+ if (full) uncheckedEnqueue(i->getOtherLit2(), PropBy(p, i->getOtherLit()));
+ else uncheckedEnqueueLight(i->getOtherLit2());
+ #ifdef DUMP_STATS_FULL
+ assert(conf.isPlain);
+ if (full && i->glue > 0 && !simplifying) {
+ std::cout << "Prop by learnt size: " << 3 << std::endl;
+ std::cout << "Prop by learnt glue: " << i->glue << std::endl;
+ }
+ #endif //DUMP_STATS_FULL
+ } else if (val == l_False && val2 == l_False) {
+ confl = PropBy(p, i->getOtherLit2());
+ failBinLit = i->getOtherLit();
+ qhead = trail.size();
+ #ifdef DUMP_STATS_FULL
+ assert(conf.isPlain);
+ if (full && i->glue > 0 && !simplifying) {
+ std::cout << "Confl by learnt size: " << 3 << std::endl;
+ std::cout << "Confl by learnt glue: " << i->glue << std::endl;
+ }
+ #endif //DUMP_STATS_FULL
+
+ 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.
+*/
+template<bool full>
+inline bool Solver::propNormalClause(vec<Watched>::iterator &i, vec<Watched>::iterator &j, const Lit p, PropBy& confl, const bool update)
+{
+ 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]:
+ if (c[0] == ~p) {
+ std::swap(c[0], c[1]);
+ }
+
+ assert(c[1] == ~p);
+
+ // If 0th watch is true, then clause is already satisfied.
+ if (value(c[0]).getBool()) {
+ *j = Watched(offset, c[0]);
+ j++;
+ return true;
+ }
+ // Look for new watch:
+ for (Lit *k = c.getData() + 2, *end2 = c.getDataEnd(); k != end2; k++) {
+ if (value(*k) != l_False) {
+ c[1] = *k;
+ *k = ~p;
+ watches[(~c[1]).toInt()].push(Watched(offset, c[0]));
+ return true;
+ }
+ }
+
+ // Did not find watch -- clause is unit under assignment:
+ *j++ = *i;
+ if (value(c[0]) == l_False) {
+ #ifdef DUMP_STATS_FULL
+ if (full && c.learnt() && !simplifying) {
+ std::cout << "Confl by learnt size: " << c.size() << std::endl;
+ std::cout << "Confl by learnt glue: " << c.getGlue() << std::endl;
+ assert(!conf.isPlain || c.getGlue() > 1);
+ }
+ #endif //DUMP_STATS_FULL
+ confl = PropBy(offset);
+ qhead = trail.size();
+ return false;
+ } else {
+ #ifdef DUMP_STATS_FULL
+ if (full && c.learnt() && !simplifying) {
+ std::cout << "Prop by learnt size: " << c.size() << std::endl;
+ std::cout << "Prop by learnt glue: " << c.getGlue() << std::endl;
+ assert(!conf.isPlain || c.getGlue() > 1);
+ }
+ #endif //DUMP_STATS_FULL
+
+ if (full) uncheckedEnqueue(c[0], offset);
+ else uncheckedEnqueueLight(c[0]);
+ #ifdef DYNAMICALLY_UPDATE_GLUE
+ if (update && full && c.learnt() && c.getGlue() > 2) {
+ uint32_t glue = calcNBLevels(c);
+ if (glue+1 < c.getGlue()) {
+ //c.setGlue(std::min(nbLevels, MAX_THEORETICAL_GLUE);
+ c.setGlue(glue);
+ }
+ }
+ #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
+*/
+template<bool full>
+inline bool Solver::propXorClause(vec<Watched>::iterator &i, vec<Watched>::iterator &j, 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;
+ }
+
+ c[k] = c[k].unsign() ^ val.getBool();
+ final ^= val.getBool();
+ }
+
+ // Did not find watch -- clause is unit under assignment:
+ *j++ = *i;
+
+ if (assigns[c[0].var()].isUndef()) {
+ c[0] = c[0].unsign()^final;
+ if (full) uncheckedEnqueue(c[0], offset);
+ else uncheckedEnqueueLight(c[0]);
+ } else if (!final) {
+ confl = PropBy(offset);
+ qhead = trail.size();
+ return false;
+ } else {
+ Lit tmp(c[0]);
+ c[0] = c[1];
+ c[1] = tmp;
+ }
+
+ return true;
+}
+
+/**
+@brief Does the propagation
+
+Basically, it goes through the watchlists recursively, and calls the appropirate
+propagaton function
+*/
+template<bool full>
+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()];
+ num_props += ws.size()/2 + 2;
+
+ #ifdef VERBOSE_DEBUG
+ cout << "Propagating lit " << p << endl;
+ cout << "ws origSize: "<< ws.size() << endl;
+ #endif
+
+ vec<Watched>::iterator i = ws.getData();
+ vec<Watched>::iterator j = i;
+
+ vec<Watched>::iterator end = ws.getDataEnd();
+ for (; i != end; i++) {
+ if (i->isBinary()) {
+ *j++ = *i;
+ if (!propBinaryClause<full>(i, p, confl)) break;
+ else continue;
+ } //end BINARY
+
+ if (i->isTriClause()) {
+ *j++ = *i;
+ if (!propTriClause<full>(i, p, confl)) break;
+ else continue;
+ } //end TRICLAUSE
+
+ if (i->isClause()) {
+ num_props += 4;
+ if (!propNormalClause<full>(i, j, p, confl, update)) break;
+ else continue;
+ } //end CLAUSE
+
+ if (i->isXorClause()) {
+ num_props += 10;
+ if (!propXorClause<full>(i, j, p, confl)) break;
+ else continue;
+ } //end XORCLAUSE
+ }
+ if (i != end) {
+ i++;
+ //copy remaining watches
+ vec<Watched>::iterator j2 = i;
+ vec<Watched>::iterator i2 = j;
+ for(i2 = i, j2 = j; i2 != end; i2++) {
+ *j2++ = *i2;
+ }
+ //memmove(j, i, sizeof(Watched)*(end-i));
+ }
+ //assert(i >= j);
+ ws.shrink_(i-j);
+ }
+ propagations += num_props;
+ simpDB_props -= num_props;
+
+ #ifdef VERBOSE_DEBUG
+ cout << "Propagation ended." << endl;
+ #endif
+
+ return confl;
+}
+template PropBy Solver::propagate<true>(const bool update);
+template PropBy Solver::propagate<false>(const bool update);
+
+PropBy Solver::propagateBin(vec<Lit>& uselessBin)
+{
+ #ifdef DEBUG_USELESS_LEARNT_BIN_REMOVAL
+ assert(uselessBin.empty());
+ #endif
+
+ while (qhead < trail.size()) {
+ Lit p = trail[qhead++];
+
+ //setting up binPropData
+ uint32_t lev = binPropData[p.var()].lev;
+ Lit lev1Ancestor;
+ switch (lev) {
+ case 0 :
+ lev1Ancestor = lit_Undef;
+ break;
+ case 1:
+ lev1Ancestor = p;
+ break;
+ default:
+ lev1Ancestor = binPropData[p.var()].lev1Ancestor;
+ }
+ lev++;
+ const bool learntLeadHere = binPropData[p.var()].learntLeadHere;
+ bool& hasChildren = binPropData[p.var()].hasChildren;
+ hasChildren = false;
+
+ //std::cout << "lev: " << lev << " ~p: " << ~p << std::endl;
+ const vec<Watched> & ws = watches[p.toInt()];
+ propagations += 2;
+ for(vec<Watched>::const_iterator k = ws.getData(), end = ws.getDataEnd(); k != end; k++) {
+ hasChildren = true;
+ if (!k->isBinary()) continue;
+
+ //std::cout << (~p) << ", " << k->getOtherLit() << " learnt: " << k->getLearnt() << std::endl;
+ lbool val = value(k->getOtherLit());
+ if (val.isUndef()) {
+ uncheckedEnqueueLight2(k->getOtherLit(), lev, lev1Ancestor, learntLeadHere || k->getLearnt());
+ } else if (val == l_False) {
+ return PropBy(p);
+ } else {
+ assert(val == l_True);
+ Lit lit2 = k->getOtherLit();
+ if (lev > 1
+ && level[lit2.var()] != 0
+ && binPropData[lit2.var()].lev == 1
+ && lev1Ancestor != lit2) {
+ //Was propagated at level 1, and again here, original level 1 binary clause is useless
+ binPropData[lit2.var()].lev = lev;
+ binPropData[lit2.var()].lev1Ancestor = lev1Ancestor;
+ binPropData[lit2.var()].learntLeadHere = learntLeadHere || k->getLearnt();
+ uselessBin.push(lit2);
+ }
+ }
+ }
+ }
+ //std::cout << " -----------" << std::endl;
+
+ return PropBy();
+}
+
+/**
+@brief Only propagates binary clauses
+
+This is used in special algorithms outside the main Solver class
+*/
+PropBy Solver::propagateNonLearntBin()
+{
+ 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(vec<Watched>::const_iterator 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 PropBy();
+}
+
+/**
+@brief Propagate recursively on non-learnt binaries, but do not propagate exceptLit if we reach it
+*/
+bool Solver::propagateBinExcept(const Lit exceptLit)
+{
+ while (qhead < trail.size()) {
+ Lit p = trail[qhead++];
+ const vec<Watched> & ws = watches[p.toInt()];
+ propagations += ws.size()/2 + 2;
+ for(vec<Watched>::const_iterator 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;
+ }
+ }
+ }
+
+ return true;
+}
+
+/**
+@brief Propagate only for one hop(=non-recursively) on non-learnt bins
+*/
+bool Solver::propagateBinOneLevel()
+{
+ Lit p = trail[qhead];
+ const vec<Watched> & ws = watches[p.toInt()];
+ propagations += ws.size()/2 + 2;
+ for(vec<Watched>::const_iterator i = ws.getData(), end = ws.getDataEnd(); i != end; i++) {
+ if (!i->isNonLearntBinary()) break;
+
+ lbool val = value(i->getOtherLit());
+ if (val.isUndef()) {
+ uncheckedEnqueueLight(i->getOtherLit());
+ } else if (val == l_False) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+struct LevelSorter
+{
+ LevelSorter(const vec<int32_t>& _level) :
+ level(_level)
+ {}
+
+ bool operator()(const Lit lit1, const Lit lit2) const {
+ return level[lit1.var()] < level[lit2.var()];
+ }
+
+ const vec<int32_t>& level;
+};
+
+/**
+@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 uint32_t Solver::calcNBLevels(const T& ps)
+{
+ uint32_t nbLevels = 0;
+ for(const Lit *l = ps.getData(), *end = ps.getDataEnd(); l != end; l++) {
+ int32_t lev = level[l->var()];
+ if (!seen[lev]) {
+ nbLevels++;
+ seen[lev] = 1;
+ }
+ }
+ for(const Lit *l = ps.getData(), *end = ps.getDataEnd(); l != end; l++) {
+ int32_t lev = level[l->var()];
+ seen[lev] = 0;
+ }
+ return nbLevels;
+}
+
+/*_________________________________________________________________________________________________
+|
+| reduceDB : () -> [void]
+|
+| Description:
+| Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked
+| 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 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->getMiniSatAct() < y->getMiniSatAct();
+}
+
+bool reduceDB_ltGlucose::operator () (const Clause* x, const Clause* y) {
+ 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.getDataEnd(), reduceDB_ltGlucose());
+ else
+ std::sort(learnts.getData(), learnts.getDataEnd(), reduceDB_ltMiniSat());
+
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Cleaning clauses" << std::endl;
+ 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 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++){
+ if (i+1 < removeNum) __builtin_prefetch(learnts[i+1]);
+ 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 {
+ 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);
+
+ 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;
+ }
+
+ clauseAllocator.consolidate(this);
+}
+
+inline int64_t abs64(int64_t a)
+{
+ if (a < 0) return -a;
+ return a;
+}
+
+/**
+@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.
+*/
+bool Solver::simplify()
+{
+ testAllClauseAttach();
+ assert(decisionLevel() == 0);
+
+ if (!ok || !propagate<false>().isNULL()) {
+ ok = false;
+ return false;
+ }
+
+ if (simpDB_props > 0) {
+ return true;
+ }
+ 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 (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->removeSatisfiedBins();
+ if (!ok) return false;
+
+ if (!sCCFinder->find2LongXors()) return false;
+
+ lastNbBin = numNewBin;
+ }
+
+ // Remove satisfied clauses:
+ clauseCleaner->removeAndCleanAll();
+ if (!ok) return false;
+
+ if (conf.doReplace && !varReplacer->performReplace())
+ return false;
+
+ // Remove fixed variables from the variable heap:
+ order_heap.filter(VarFilter(*this));
+
+ #ifdef USE_GAUSS
+ for (vector<Gaussian*>::iterator gauss = gauss_matrixes.begin(), end = gauss_matrixes.end(); gauss != end; gauss++) {
+ if (!(*gauss)->full_init()) return false;
+ }
+ #endif //USE_GAUSS
+
+ simpDB_assigns = nAssigns();
+ simpDB_props = 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
+
+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);
+ uint64_t conflictC = 0;
+ vec<Lit> learnt_clause;
+ llbool ret;
+
+ 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())
+ return l_False;
+ }
+ #endif //USE_GAUSS
+
+ testAllClauseAttach();
+ findAllAttach();
+ #ifdef VERBOSE_DEBUG
+ std::cout << "c started Solver::search()" << std::endl;
+ //printAllClauses();
+ #endif //VERBOSE_DEBUG
+ for (;;) {
+ assert(ok);
+ PropBy confl = propagate<true>(update);
+ #ifdef VERBOSE_DEBUG
+ std::cout << "c Solver::search() has finished propagation" << std::endl;
+ //printAllClauses();
+ #endif //VERBOSE_DEBUG
+
+ if (conflicts > conf.maxConfl) {
+ if (conf.verbosity >= 0) {
+ std::cout << "c Interrupting: limit on number of conflicts, "
+ << conf.maxConfl
+ << " reached! " << std::endl;
+ }
+ needToInterrupt = true;
+ return l_Undef;
+ }
+
+ if (!confl.isNULL()) {
+ ret = handle_conflict(learnt_clause, confl, conflictC, update);
+ if (ret != l_Nothing) return ret;
+ } else {
+ #ifdef USE_GAUSS
+ bool at_least_one_continue = false;
+ for (vector<Gaussian*>::iterator gauss = gauss_matrixes.begin(), end= gauss_matrixes.end(); gauss != end; gauss++) {
+ ret = (*gauss)->find_truths(learnt_clause, conflictC);
+ if (ret == l_Continue) at_least_one_continue = true;
+ else if (ret != l_Nothing) return ret;
+ }
+ if (at_least_one_continue) continue;
+ #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;
+ }
+ }
+}
+
+/**
+@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) {
+ cancelUntil(0);
+ return l_Undef;
+ }
+
+ // Reached bound on number of conflicts?
+ switch (restartType) {
+ case dynamic_restart:
+ if (glueHistory.isvalid() &&
+ 0.95*glueHistory.getAvgDouble() > glueHistory.getAvgAllDouble()) {
+
+ #ifdef DEBUG_DYNAMIC_RESTART
+ 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 << "compTotSumGlue:" << compTotSumGlue << std::endl;
+ std::cout << "conflicts-compTotSumGlue:" << conflicts-compTotSumGlue<< std::endl;
+ }
+ #endif
+
+ cancelUntil(0);
+ return l_Undef;
+ }
+ break;
+ case static_restart:
+ if (conflictC >= nof_conflicts) {
+ cancelUntil(0);
+ return l_Undef;
+ }
+ break;
+ case auto_restart:
+ assert(false);
+ break;
+ }
+
+ // Simplify the set of problem clauses:
+ if (decisionLevel() == 0) {
+ if (!dataSync->syncData()) return l_False;
+ if (!simplify()) return l_False;
+ }
+
+ // Reduce the set of learnt clauses:
+ if (conflicts >= numCleanedLearnts * nbClBeforeRed + nbCompensateSubsumer) {
+ numCleanedLearnts ++;
+ reduceDB();
+ nbClBeforeRed += 500;
+ }
+
+ Lit next = lit_Undef;
+ while (decisionLevel() < assumptions.size()) {
+ // Perform user provided assumption:
+ Lit p = assumptions[decisionLevel()];
+ if (value(p) == l_True) {
+ // Dummy decision level:
+ newDecisionLevel();
+ } else if (value(p) == l_False) {
+ analyzeFinal(~p, conflict);
+ return l_False;
+ } else {
+ next = p;
+ break;
+ }
+ }
+
+ if (next == lit_Undef) {
+ // New variable decision:
+ decisions++;
+ next = pickBranchLit();
+
+ if (next == lit_Undef)
+ return l_True;
+ }
+
+ // Increase decision level and enqueue 'next'
+ assert(value(next) == l_Undef);
+ newDecisionLevel();
+ uncheckedEnqueue(next);
+
+ return l_Nothing;
+}
+
+/**
+@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 (uint32_t i = 0; i < learnt_clause.size(); i++)
+ cout << learnt_clause[i].var()+1 << ",";
+ cout << endl;
+ #endif
+
+ int backtrack_level;
+ uint32_t glue;
+
+ conflicts++;
+ conflictC++;
+ if (decisionLevel() == 0)
+ return l_False;
+ learnt_clause.clear();
+ Clause* c = analyze(confl, learnt_clause, backtrack_level, glue, update);
+ if (update) {
+ avgBranchDepth.push(decisionLevel());
+ if (restartType == dynamic_restart) glueHistory.push(glue);
+ conflSizeHist.push(learnt_clause.size());
+ }
+ cancelUntil(backtrack_level);
+ #ifdef DUMP_STATS
+ std::cout << "Learnt clause: " << learnt_clause
+ << " glue: " << glue
+ << " declevel: " << decisionLevel()
+ << " traillen: " << trail.size()
+ << " abst: " << calcAbstraction(learnt_clause)
+ << std::endl;
+ assert(learnt_clause.size() == 1 || glue > 1);
+ #endif //#ifdef DUMP_STATS
+
+ #ifdef VERBOSE_DEBUG
+ cout << "Learning:";
+ 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 (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 (learnt_clause.size() > 3) {
+ std::sort(learnt_clause.getData()+1, learnt_clause.getDataEnd(), PolaritySorter(polarity));
+ }
+ 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->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
+ c = clauseAllocator.Clause_new(learnt_clause, true);
+ #ifdef ENABLE_UNWIND_GLUE
+ 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 {
+ #endif //ENABLE_UNWIND_GLUE
+ learnts.push(c);
+ #ifdef ENABLE_UNWIND_GLUE
+ }
+ #endif //ENABLE_UNWIND_GLUE
+ c->setGlue(std::min(glue, MAX_THEORETICAL_GLUE));
+ attachClause(*c);
+ uncheckedEnqueue(learnt_clause[0], clauseAllocator.getOffset(c));
+ }
+ end:;
+ }
+
+ varDecayActivity();
+ if (update && restartType == static_restart) claDecayActivity();
+
+ return l_Nothing;
+}
+
+/**
+@brief After a full restart, determines which restar type to use
+
+Uses class RestartTypeChooser to do the heavy-lifting
+*/
+bool Solver::chooseRestartType(const uint32_t& lastFullRestart)
+{
+ uint32_t relativeStart = starts - lastFullRestart;
+
+ if (relativeStart > RESTART_TYPE_DECIDER_FROM && relativeStart < RESTART_TYPE_DECIDER_UNTIL) {
+ if (conf.fixRestartType == auto_restart)
+ restartTypeChooser->addInfo();
+
+ if (relativeStart == (RESTART_TYPE_DECIDER_UNTIL-1)) {
+ RestartType tmp;
+ if (conf.fixRestartType == auto_restart)
+ tmp = restartTypeChooser->choose();
+ else
+ tmp = conf.fixRestartType;
+
+ if (tmp == dynamic_restart) {
+ glueHistory.fastclear();
+ if (conf.verbosity >= 3)
+ std::cout << "c Decided on dynamic restart strategy"
+ << std::endl;
+ } else {
+ if (conf.verbosity >= 1)
+ std::cout << "c Decided on static restart strategy"
+ << std::endl;
+
+ if (!matrixFinder->findMatrixes()) return false;
+ }
+ lastSelectedRestartType = tmp;
+ restartType = tmp;
+ restartTypeChooser->reset();
+ }
+ }
+
+ return true;
+}
+
+inline void Solver::setDefaultRestartType()
+{
+ if (conf.fixRestartType != auto_restart) restartType = conf.fixRestartType;
+ else restartType = static_restart;
+
+ 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.
+*/
+lbool Solver::simplifyProblem(const uint32_t numConfls)
+{
+ testAllClauseAttach();
+ bool gaussWasCleared = clearGaussMatrixes();
+
+ StateSaver savedState(*this);;
+
+ #ifdef BURST_SEARCH
+ 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 && needToInterrupt == false) {
+ status = search(100, std::numeric_limits<uint64_t>::max(), false);
+ }
+ if (needToInterrupt) return l_Undef;
+ printRestartStat("S");
+ if (status != l_Undef) goto end;
+ #endif //BURST_SEARCH
+
+ if (conf.doXorSubsumption && !xorSubsumer->simplifyBySubsumption()) goto end;
+
+ if (conf.doFailedLit && conf.doCacheOTFSSR) {
+ BothCache both(*this);
+ if (!both.tryBoth()) goto end;
+ }
+ if (conf.doCacheOTFSSR) cleanCache();
+ if (conf.doClausVivif && !clauseVivifier->vivifyClauses()) goto end;
+
+ if (conf.doCacheOTFSSRSet && order_heap.size() < 200000) {
+ if (conf.doCacheOTFSSR == false && conf.verbosity > 0) {
+ std::cout << "c turning cache ON because the number of active variables is lower now" << std::endl;
+ }
+ conf.doCacheOTFSSR = true;
+ }
+ if (conf.doFailedLit && !failedLitSearcher->search()) goto end;
+
+ if (conf.doSatELite && !subsumer->simplifyBySubsumption()) goto end;
+
+ /*if (findNormalXors && xorclauses.size() > 200 && clauses.size() < MAX_CLAUSENUM_XORFIND/8) {
+ XorFinder xorFinder(*this, clauses, ClauseCleaner::clauses);
+ if (!xorFinder.doNoPart(3, 7)) {
+ status = l_False;
+ goto end;
+ }
+ } else*/ if (xorclauses.size() <= 200 && xorclauses.size() > 0 && nClauses() > 10000) {
+ 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 (conf.verbosity >= 3)
+ std::cout << "c Simplifying finished" << std::endl;
+ #endif //#ifdef BURST_SEARCH
+
+ savedState.restore();
+ simplifying = false;
+
+ if (status == l_Undef && ok && gaussWasCleared && !matrixFinder->findMatrixes())
+ status = l_False;
+
+ testAllClauseAttach();
+
+ if (!ok) return l_False;
+ return status;
+}
+
+/**
+@brief Should we perform a full restart?
+
+If so, we also do the things to be done if the full restart is effected.
+*/
+bool Solver::checkFullRestart(uint64_t& nof_conflicts, uint64_t& nof_conflicts_fullrestart, uint32_t& lastFullRestart)
+{
+ if (nof_conflicts_fullrestart > 0 && conflicts >= nof_conflicts_fullrestart) {
+ #ifdef USE_GAUSS
+ clearGaussMatrixes();
+ #endif //USE_GAUSS
+ 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;
+ }*/
+
+ //calculateDefaultPolarities();
+ if (conf.polarity_mode != polarity_auto) {
+ for (uint32_t i = 0; i < polarity.size(); i++) {
+ polarity[i] = defaultPolarity();
+ }
+ }
+
+ fullStarts++;
+ }
+
+ return true;
+}
+
+/**
+@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();
+
+ printRestartStat();
+ if (conf.doReplace && !varReplacer->performReplace()) return;
+
+ order_heap.filter(Solver::VarFilter(*this));
+ if (order_heap.size() > 300000) {
+ if (conf.verbosity > 0) {
+ std::cout << "c turning cache OFF because there are too many active variables" << std::endl;
+ }
+ conf.doCacheOTFSSR = false;
+ }
+
+ bool saveDoHyperBin = conf.doHyperBinRes;
+ conf.doHyperBinRes = false;
+ clauseAllocator.consolidate(this, true);
+ if (conf.doFailedLit && !failedLitSearcher->search()) return;
+ conf.doHyperBinRes = saveDoHyperBin;
+ if (conf.doClausVivif && !conf.libraryUsage
+ && !clauseVivifier->vivifyClauses()) return;
+
+ #ifdef VERBOSE_DEBUG
+ printAllClauses();
+ #endif //VERBOSE_DEBUG
+ if (conf.doSatELite
+ && !conf.libraryUsage
+ && clauses.size() < 4800000
+ && !subsumer->simplifyBySubsumption())
+ return;
+
+ if (conf.doFindEqLits) {
+ if (!sCCFinder->find2LongXors()) return;
+ lastNbBin = numNewBin;
+ if (conf.doReplace && !varReplacer->performReplace(true)) return;
+ }
+
+ if (conf.doFindXors && clauses.size() < MAX_CLAUSENUM_XORFIND) {
+ XorFinder xorFinder(*this, clauses);
+ if (!xorFinder.fullFindXors(3, 7)) return;
+ }
+
+ if (xorclauses.size() > 1) {
+ if (conf.doXorSubsumption && !xorSubsumer->simplifyBySubsumption())
+ return;
+
+ if (conf.doReplace && !varReplacer->performReplace())
+ return;
+ }
+
+ if (conf.doSortWatched) sortWatched();
+ if (conf.doCacheOTFSSR && conf.doCalcReach) calcReachability();
+
+ testAllClauseAttach();
+}
+
+/**
+@brief Initialises model, restarts, learnt cluause cleaning, burst-search, etc.
+*/
+void Solver::initialiseSolver()
+{
+ //Clear up previous stuff like model, final conflict, matrixes
+ model.clear();
+ conflict.clear();
+ clearGaussMatrixes();
+
+ //Initialise restarts & dynamic restart datastructures
+ setDefaultRestartType();
+
+ //Initialise avg. branch depth
+ avgBranchDepth.clear();
+ avgBranchDepth.initSize(500);
+
+ //Initialise number of restarts&full restarts
+ starts = 0;
+ fullStarts = 0;
+
+ if (nClauses() * conf.learntsize_factor < nbClBeforeRed) {
+ if (nClauses() * conf.learntsize_factor < nbClBeforeRed/2)
+ nbClBeforeRed /= 4;
+ else
+ 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) {
+ if (conf.doPerformPreSimp) performStepsBeforeSolve();
+ if (!ok) return l_False;
+
+ calculateDefaultPolarities();
+ }
+
+ printStatHeader();
+ printRestartStat("B");
+ uint64_t lastConflPrint = conflicts;
+ // Search:
+ while (status == l_Undef && starts < conf.maxRestarts) {
+ #ifdef DEBUG_VARELIM
+ assert(subsumer->checkElimedUnassigned());
+ assert(xorSubsumer->checkElimedUnassigned());
+ #endif //DEBUG_VARELIM
+
+ 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;
+ }
+
+ 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))
+ return l_False;
+ if (!chooseRestartType(lastFullRestart))
+ return l_False;
+ }
+ printEndSearchStat();
+
+ #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) handleSATSolution();
+ else if (status == l_False) handleUNSATSolution();
+
+ cancelUntil(0);
+ restartTypeChooser->reset();
+ if (status == l_Undef) clauseCleaner->removeAndCleanAll(true);
+
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Solver::solve() finished" << std::endl;
+ #endif
+ return status;
+}
+
+/**
+@brief Extends a SAT solution to the full solution
+
+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()
+{
+
+ /*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());
+
+ varReplacer->extendModelPossible();
+ checkSolution();
+
+ if (subsumer->getNumElimed() || xorSubsumer->getNumElimed()) {
+ if (conf.verbosity >= 1) {
+ std::cout << "c Solution needs extension. Extending." << std::endl;
+ }
+ 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.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);
+ }
+ }
+ varReplacer->extendModelImpossible(s);
+ subsumer->extendModel(s);
+ xorSubsumer->extendModel(s);
+
+ 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
+ //need to start new decision level, otherwise uncheckedEnqueue will
+ //enqueue to decision level 0 in certain cases :S
+ newDecisionLevel();
+ 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<false>().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);
+}
+
+/**
+@brief When problem is decided to be UNSAT, this is called
+
+There is basically nothing to be handled for the moment, but this could be
+made extensible
+*/
+void Solver::handleUNSATSolution()
+{
+ if (conflict.size() == 0)
+ ok = false;
+}
+
+void Solver::cleanCache()
+{
+ for(uint32_t i = 0; i < nVars(); i++) {
+ if (subsumer->getVarElimed()[i] || value(i) != l_Undef) {
+ vector<Lit> tmp1;
+ transOTFCache[Lit(i, false).toInt()].lits.swap(tmp1);
+ vector<Lit> tmp2;
+ transOTFCache[Lit(i, true).toInt()].lits.swap(tmp2);
+ continue;
+ }
+
+ for(int which = 0; which < 2; which++) {
+ cleanCachePart(Lit(i, which));
+
+ }
+ }
+}
+
+void Solver::cleanCachePart(const Lit vertLit)
+{
+ vector<Lit>& transCache = transOTFCache[(~vertLit).toInt()].lits;
+ assert(seen_vec.empty());
+
+ vector<Lit>::iterator it = transCache.begin();
+ vector<Lit>::iterator it2 = it;
+
+ size_t newSize = 0;
+ for (vector<Lit>::iterator end = transCache.end(); it != end; it++) {
+ Lit lit = *it;
+ lit = varReplacer->getReplaceTable()[lit.var()] ^ lit.sign();
+ if (lit == vertLit
+ || seen[lit.toInt()]
+ || subsumer->getVarElimed()[lit.var()]
+ || subsumer->getVarElimed()[lit.var()]
+ ) continue;
+
+ *it2++ = lit;
+
+ //Don't allow the same value to be in the cache twice
+ seen[lit.toInt()] = 1;
+ seen_vec.push_back(lit);
+
+ //Increase valid size
+ newSize++;
+ }
+ transCache.resize(newSize);
+
+ //Clear up seen
+ for(vector<Lit>::const_iterator it = seen_vec.begin(), end = seen_vec.end(); it != end; it++) {
+ seen[it->toInt()] = 0;
+ }
+ seen_vec.clear();
+}
diff --git a/src/prop/cryptominisat/Solver/Solver.h b/src/prop/cryptominisat/Solver/Solver.h
new file mode 100644
index 000000000..9276823dd
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/Solver.h
@@ -0,0 +1,859 @@
+/****************************************************************************************[Solver.h]
+MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+glucose -- Gilles Audemard, Laurent Simon (2008)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef SOLVER_H
+#define SOLVER_H
+
+#include <cstdio>
+#include <string.h>
+#include <stdio.h>
+#include <stack>
+#include <stdexcept>
+
+//#define ANIMATE3D
+
+#include "PropBy.h"
+#include "Vec.h"
+#include "Heap.h"
+#include "Alg.h"
+#include "MersenneTwister.h"
+#include "SolverTypes.h"
+#include "Clause.h"
+#include "constants.h"
+#include "BoundedQueue.h"
+#include "GaussianConfig.h"
+#include "ClauseAllocator.h"
+#include "SolverConf.h"
+
+namespace CMSat {
+
+class Gaussian;
+class MatrixFinder;
+class Conglomerate;
+class VarReplacer;
+class XorFinder;
+class FindUndef;
+class ClauseCleaner;
+class FailedLitSearcher;
+class Subsumer;
+class XorSubsumer;
+class RestartTypeChooser;
+class StateSaver;
+class UselessBinRemover;
+class SCCFinder;
+class ClauseVivifier;
+class SharedData;
+class DataSync;
+class BothCache;
+
+#ifdef VERBOSE_DEBUG
+#define DEBUG_UNCHECKEDENQUEUE_LEVEL0
+using std::cout;
+using std::endl;
+#endif
+
+struct reduceDB_ltMiniSat
+{
+ bool operator () (const Clause* x, const Clause* y);
+};
+
+struct reduceDB_ltGlucose
+{
+ bool operator () (const Clause* x, const Clause* y);
+};
+
+struct PolaritySorter
+{
+ PolaritySorter(vector<char>& polarity) :
+ pol(polarity)
+ {}
+
+ bool operator()(const Lit lit1, const Lit lit2) const
+ {
+ return (((((bool)pol[lit1.var()])^(lit1.sign())) == false)
+ && ((((bool)pol[lit2.var()])^(lit2.sign())) == true));
+ }
+ vector<char>& pol;
+};
+
+/**
+@brief The main solver class
+
+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:
+
+ // Constructor/Destructor:
+ //
+ Solver(const SolverConf& conf = SolverConf(), const GaussConf& _gaussconfig = GaussConf(), SharedData* sharedUnitData = NULL);
+ ~Solver();
+
+ // Problem specification:
+ //
+ Var newVar (bool dvar = true) throw (std::out_of_range); // Add a new variable with parameters specifying variable mode.
+ template<class T>
+ bool addClause (T& ps); // Add a clause to the solver. NOTE! 'ps' may be shrunk by this method!
+ template<class T>
+ bool addLearntClause(T& ps, const uint32_t glue = 10, const float miniSatActivity = 10.0);
+ template<class T>
+ bool addXorClause (T& ps, bool xorEqualFalse) throw (std::out_of_range); // 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.
+ 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 setDecisionVar (Var v, bool b); ///<Declare if a variable should be eligible for selection in the decision heuristic.
+ void addBranchingVariable (Var v);
+
+ // 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.
+
+ // 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.
+
+ // Mode of operation:
+ //
+ 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
+ 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
+ vector<Lit> get_unitary_learnts() const; //return the set of unitary learnt clauses
+ uint32_t get_unitary_learnts_num() const; //return the number of unitary learnt clauses
+ bool dumpSortedLearnts(const std::string& fileName, const uint32_t maxSize); // Dumps all learnt clauses (including unitary ones) into the file; returns true for success, false for failure
+ bool needLibraryCNFFile(const std::string& fileName); //creates file in current directory with the filename indicated, and puts all calls from the library into the file.
+ bool dumpOrigClauses(const std::string& fileName) const;
+ void printBinClause(const Lit litP1, const Lit litP2, FILE* outfile) const;
+
+ uint32_t get_sum_gauss_called() const;
+ uint32_t get_sum_gauss_confl() const;
+ uint32_t get_sum_gauss_prop() const;
+ uint32_t get_sum_gauss_unit_truths() const;
+
+ //Printing statistics
+ void printStats();
+ uint32_t getNumElimSubsume() const; ///<Get number of variables eliminated
+ uint32_t getNumElimXorSubsume() const; ///<Get number of variables eliminated with xor-magic
+ 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
+ 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.
+ */
+ double getTotalTimeSubsumer() const;
+ double getTotalTimeFailedLitSearcher() 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)
+ */
+ double getTotalTimeXorSubsumer() const;
+
+protected:
+ //gauss
+ bool clearGaussMatrixes();
+ vector<Gaussian*> gauss_matrixes;
+ void print_gauss_sum_stats();
+ uint32_t sum_gauss_called;
+ uint32_t sum_gauss_confl;
+ uint32_t sum_gauss_prop;
+ uint32_t sum_gauss_unit_truths;
+
+ // Statistics
+ //
+ template<class T, class T2>
+ void printStatsLine(std::string left, T value, T2 value2, std::string extra);
+ template<class T>
+ 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 {
+ const vec<uint32_t>& activity;
+ bool operator () (Var x, Var y) const {
+ return activity[x] > activity[y];
+ }
+ VarOrderLt(const vec<uint32_t>& act) : activity(act) { }
+ };
+
+ struct VarFilter {
+ const Solver& s;
+ VarFilter(const Solver& _s) : s(_s) {}
+ bool operator()(Var v) const {
+ return s.assigns[v].isUndef() && s.decision_var[v];
+ }
+ };
+
+ // Solver state:
+ //
+ 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<char> 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.
+ bqueue<uint32_t> avgBranchDepth; ///< Avg branch depth. We collect this, and use it to do random look-around in the searchspace during simplifyProblem()
+ MTRand mtrand; ///< random number generator
+ vector<Var> branching_variables;
+
+ /////////////////
+ // 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>
+ 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 )
+ vec<Var> lastDecisionLevel;
+ bqueue<uint32_t> glueHistory; ///< Set of last decision levels in (glue of) conflict clauses. Used for dynamic restarting
+ #ifdef ENABLE_UNWIND_GLUE
+ vec<Clause*> unWindGlue;
+ #endif //ENABLE_UNWIND_GLUE
+
+ // 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<char> seen; ///<Used in multiple places. Contains 2 * numVars() elements, all zeroed out
+ vector<Lit> seen_vec;
+ vec<Lit> analyze_stack;
+ vec<Lit> analyze_toclear;
+
+ ////////////
+ // 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<char> 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();
+ void cleanCache();
+ void cleanCachePart(const Lit vertLit);
+
+ ////////////
+ //Logging
+ ///////////
+ FILE *libraryCNFFile; //The file that all calls from the library are logged
+
+ /////////////////
+ // Propagating
+ ////////////////
+ Lit pickBranchLit (); // Return the next decision variable.
+ void newDecisionLevel (); // Begins a new decision level.
+ void uncheckedEnqueue (const Lit p, const PropBy& from = PropBy()); // Enqueue a literal. Assumes value of literal is undefined.
+ void uncheckedEnqueueLight (const Lit p);
+ void uncheckedEnqueueLight2(const Lit p, const uint32_t binPropDatael, const Lit lev1Ancestor, const bool learntLeadHere);
+ PropBy propagateBin(vec<Lit>& uselessBin);
+ PropBy propagateNonLearntBin();
+ bool multiLevelProp;
+ bool propagateBinExcept(const Lit exceptLit);
+ bool propagateBinOneLevel();
+ template<bool full>
+ PropBy propagate(const bool update = true); // Perform unit propagation. Returns possibly conflicting clause.
+ template<bool full>
+ bool propTriClause (vec<Watched>::iterator &i, const Lit p, PropBy& confl);
+ template<bool full>
+ bool propBinaryClause(vec<Watched>::iterator &i, const Lit p, PropBy& confl);
+ template<bool full>
+ bool propNormalClause(vec<Watched>::iterator &i, vec<Watched>::iterator &j, const Lit p, PropBy& confl, const bool update);
+ template<bool full>
+ bool propXorClause (vec<Watched>::iterator &i, vec<Watched>::iterator &j, const Lit p, PropBy& confl);
+ void sortWatched();
+
+ ///////////////
+ // Conflicting
+ ///////////////
+ void cancelUntil (int level); // Backtrack until a certain level.
+ 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()')
+ 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:
+ /////////////////
+ template<class T> bool addClauseHelper(T& ps) throw (std::out_of_range);
+ template <class T>
+ Clause* addClauseInt(T& ps, 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 bool learnt = false) throw (std::out_of_range);
+ 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.
+
+ ///////////////////////////
+ // Debug clause attachment
+ ///////////////////////////
+ void testAllClauseAttach() const;
+ void findAllAttach() const;
+ bool findClause(XorClause* c) const;
+ bool findClause(Clause* c) const;
+ bool xorClauseIsAttached(const XorClause& c) 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.
+
+ /////////////////////////
+ //Classes that must be friends, since they accomplish things on our datastructures
+ /////////////////////////
+ friend class VarFilter;
+ friend class Gaussian;
+ friend class FindUndef;
+ friend class XorFinder;
+ friend class Conglomerate;
+ friend class MatrixFinder;
+ friend class VarReplacer;
+ friend class ClauseCleaner;
+ friend class RestartTypeChooser;
+ friend class FailedLitSearcher;
+ friend class Subsumer;
+ friend class XorSubsumer;
+ friend class StateSaver;
+ friend class UselessBinRemover;
+ friend class OnlyNonLearntBins;
+ friend class ClauseAllocator;
+ friend class CompleteDetachReatacher;
+ friend class SCCFinder;
+ friend class ClauseVivifier;
+ friend class DataSync;
+ friend class BothCache;
+ Conglomerate* conglomerate;
+ VarReplacer* varReplacer;
+ ClauseCleaner* clauseCleaner;
+ FailedLitSearcher* failedLitSearcher;
+ Subsumer* subsumer;
+ XorSubsumer* xorSubsumer;
+ RestartTypeChooser* restartTypeChooser;
+ MatrixFinder* matrixFinder;
+ SCCFinder* sCCFinder;
+ ClauseVivifier* clauseVivifier;
+
+ /////////////////////////
+ // Restart type handling
+ /////////////////////////
+ bool chooseRestartType(const uint32_t& lastFullRestart);
+ void setDefaultRestartType();
+ 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();
+ lbool simplifyProblem(const uint32_t numConfls);
+ void reduceDB(); // Reduce the set of learnt clauses.
+ 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 ();
+ bool verifyModel () const;
+ bool verifyBinClauses() const;
+ bool verifyClauses (const vec<Clause*>& cs) const;
+ bool verifyXorClauses () const;
+
+ // Debug & etc:
+ void printAllClauses();
+ void printLit (const Lit l) const;
+ void checkLiteralCount();
+ void printStatHeader () const;
+ void printRestartStat (const char* type = "N");
+ void printEndSearchStat();
+ void addSymmBreakClauses();
+ void initialiseSolver();
+
+ //Misc related binary clauses
+ void dumpBinClauses(const bool alsoLearnt, const bool alsoNonLearnt, FILE* outfile) const;
+ uint32_t countNumBinClauses(const bool alsoLearnt, const bool alsoNonLearnt) 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 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<char> polarity; // The preferred polarity of each variable.
+};
+
+
+
+//**********************************
+// Implementation of inline methods
+//**********************************
+
+inline void Solver::insertVarOrder(Var x)
+{
+ if (!order_heap.inHeap(x) && decision_var[x]) order_heap.insert(x);
+}
+
+inline void Solver::varDecayActivity()
+{
+ var_inc *= 11;
+ var_inc /= 10;
+}
+inline void Solver::varBumpActivity(Var v)
+{
+ if ( (activity[v] += var_inc) > (0x1U) << 24 ) {
+ //printf("RESCALE!!!!!!\n");
+ //std::cout << "var_inc: " << var_inc << std::endl;
+ // Rescale:
+ for (Var var = 0; var != nVars(); var++) {
+ activity[var] >>= 14;
+ }
+ 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();
+ if (decision_var[v])
+ std::cout << "var_" << v+1 << " act: " << activity[v] << std::endl;
+ }*/
+ }
+
+ // Update order_heap with respect to new activity:
+ if (order_heap.inHeap(v))
+ order_heap.decrease(v);
+}
+
+inline void Solver::claBumpActivity (Clause& c)
+{
+ if ( (c.getMiniSatAct() += cla_inc) > 1e20 ) {
+ // Rescale:
+ for (uint32_t i = 0; i < learnts.size(); i++)
+ learnts[i]->getMiniSatAct() *= 1e-17;
+ cla_inc *= 1e-20;
+ }
+}
+
+inline void Solver::claDecayActivity()
+{
+ //cla_inc *= clause_decay;
+}
+
+inline bool Solver::locked(const Clause& c) const
+{
+ 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());
+ #ifdef VERBOSE_DEBUG
+ cout << "New decision level: " << trail_lim.size() << endl;
+ #endif
+}
+/*inline int Solver::nbPropagated(int level) {
+ if (level == decisionLevel())
+ return trail.size() - trail_lim[level-1] - 1;
+ return trail_lim[level] - trail_lim[level-1] - 1;
+}*/
+inline uint32_t Solver::decisionLevel () const
+{
+ return trail_lim.size();
+}
+inline uint32_t Solver::abstractLevel (const Var x) const
+{
+ return 1 << (level[x] & 31);
+}
+inline lbool Solver::value (const Var x) const
+{
+ return assigns[x];
+}
+inline lbool Solver::value (const Lit p) const
+{
+ return assigns[p.var()] ^ p.sign();
+}
+inline lbool Solver::modelValue (const Lit p) const
+{
+ return model[p.var()] ^ p.sign();
+}
+inline uint32_t Solver::nAssigns () const
+{
+ return trail.size();
+}
+inline uint32_t Solver::nClauses () const
+{
+ return clauses.size() + xorclauses.size();
+}
+inline uint32_t Solver::nLiterals () const
+{
+ return clauses_literals + learnts_literals;
+}
+inline uint32_t Solver::nLearnts () const
+{
+ return learnts.size();
+}
+inline uint32_t Solver::nVars () const
+{
+ return assigns.size();
+}
+inline void Solver::setPolarity (Var v, bool b)
+{
+ polarity [v] = (char)b;
+}
+inline void Solver::setDecisionVar(Var v, bool b)
+{
+ decision_var[v] = b;
+ if (b) {
+ insertVarOrder(v);
+ }
+}
+inline void Solver::addBranchingVariable(Var v)
+{
+ branching_variables.push_back(v);
+}
+inline lbool Solver::solve ()
+{
+ vec<Lit> tmp;
+ return solve(tmp);
+}
+inline bool Solver::okay () const
+{
+ return ok;
+}
+
+inline uint32_t Solver::get_sum_gauss_unit_truths() const
+{
+ return sum_gauss_unit_truths;
+}
+
+inline uint32_t Solver::get_sum_gauss_called() const
+{
+ return sum_gauss_called;
+}
+
+inline uint32_t Solver::get_sum_gauss_confl() const
+{
+ return sum_gauss_confl;
+}
+
+inline uint32_t Solver::get_sum_gauss_prop() const
+{
+ return sum_gauss_prop;
+}
+
+inline 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::removeClause(T& c)
+{
+ detachClause(c);
+ clauseAllocator.clauseFree(&c);
+}
+
+//**********************************
+// Debug + etc:
+//**********************************
+
+static inline void logLit(FILE* f, Lit l)
+{
+ fprintf(f, "%sx%d", l.sign() ? "~" : "", l.var()+1);
+}
+
+static inline void logLits(FILE* f, const vec<Lit>& ls)
+{
+ fprintf(f, "[ ");
+ if (ls.size() > 0) {
+ logLit(f, ls[0]);
+ for (uint32_t i = 1; i < ls.size(); i++) {
+ fprintf(f, ", ");
+ logLit(f, ls[i]);
+ }
+ }
+ fprintf(f, "] ");
+}
+
+#ifndef DEBUG_ATTACH_FULL
+inline void Solver::testAllClauseAttach() const
+{
+ return;
+}
+inline void Solver::findAllAttach() const
+{
+ return;
+}
+#endif //DEBUG_ATTACH_FULL
+
+inline void Solver::uncheckedEnqueueLight(const Lit p)
+{
+ assert(value(p.var()) == l_Undef);
+ #if WATCHED_CACHE_NUM > 0
+ __builtin_prefetch(watches.getData() + p.toInt());
+ #else
+ if (watches[p.toInt()].size() > 0) __builtin_prefetch(watches[p.toInt()].getData());
+ #endif
+
+ assigns [p.var()] = boolToLBool(!p.sign());//lbool(!sign(p)); // <<== abstract but not uttermost effecient
+ trail.push(p);
+ if (decisionLevel() == 0) {
+ level[p.var()] = 0;
+ #ifdef ANIMATE3D
+ fprintf(stderr, "s %u %d\n", p.var(), p.sign());
+ #endif
+ }
+}
+
+inline void Solver::uncheckedEnqueueLight2(const Lit p, const uint32_t binSubLevel, const Lit lev1Ancestor, const bool learntLeadHere)
+{
+ assert(value(p.var()) == l_Undef);
+ #if WATCHED_CACHE_NUM > 0
+ __builtin_prefetch(watches.getData() + p.toInt());
+ #else
+ if (watches[p.toInt()].size() > 0) __builtin_prefetch(watches[p.toInt()].getData());
+ #endif
+
+ 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()].lev1Ancestor = lev1Ancestor;
+ binPropData[p.var()].learntLeadHere = learntLeadHere;
+}
+
+/**
+@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.
+
+@p p the fact to enqueue
+@p from Why was it propagated (binary clause, tertiary clause, normal clause)
+*/
+inline 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 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()]);
+
+ const Var v = p.var();
+ assert(value(v).isUndef());
+ #if WATCHED_CACHE_NUM > 0
+ __builtin_prefetch(watches.getData() + p.toInt());
+ #else
+ if (watches[p.toInt()].size() > 0) __builtin_prefetch(watches[p.toInt()].getData());
+ #endif
+
+ assigns [v] = boolToLBool(!p.sign());
+ #ifdef ANIMATE3D
+ fprintf(stderr, "s %u %d\n", v, p.sign());
+ #endif
+ level [v] = decisionLevel();
+ reason [v] = from;
+ polarity[v] = p.sign();
+ trail.push(p);
+}
+
+}
+
+#endif //SOLVER_H
diff --git a/src/prop/cryptominisat/Solver/SolverConf.cpp b/src/prop/cryptominisat/Solver/SolverConf.cpp
new file mode 100644
index 000000000..e7a5cfafa
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/SolverConf.cpp
@@ -0,0 +1,91 @@
+/*****************************************************************************
+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>
+
+using namespace CMSat;
+
+SolverConf::SolverConf() :
+ random_var_freq(0.001)
+ , 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)
+ , 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)
+ #ifdef ENABLE_UNWIND_GLUE
+ , doMaxGlueDel (false)
+ #endif //ENABLE_UNWIND_GLUE
+ , doPrintAvgBranch (false)
+ , doCacheOTFSSR (true)
+ , doCacheOTFSSRSet (true)
+ , doExtendedSCC (false)
+ , doCalcReach (true)
+ , doBXor (true)
+ , doOTFSubsume (true)
+ , maxConfl (std::numeric_limits<uint64_t>::max())
+ , isPlain (false)
+
+ , maxRestarts (std::numeric_limits<uint32_t>::max())
+ , needToDumpLearnts(false)
+ , needToDumpOrig (false)
+ , maxDumpLearntsSize(std::numeric_limits<uint32_t>::max())
+ , libraryUsage (true)
+ , greedyUnbound (false)
+ #ifdef ENABLE_UNWIND_GLUE
+ , maxGlue (DEFAULT_MAX_GLUE)
+ #endif //ENABLE_UNWIND_GLUE
+ , fixRestartType (auto_restart)
+ , origSeed(0)
+{
+}
diff --git a/src/prop/cryptominisat/Solver/SolverConf.h b/src/prop/cryptominisat/Solver/SolverConf.h
new file mode 100644
index 000000000..0edaf3745
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/SolverConf.h
@@ -0,0 +1,102 @@
+/*****************************************************************************
+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"
+
+namespace CMSat {
+
+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 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
+ #ifdef ENABLE_UNWIND_GLUE
+ bool doMaxGlueDel;
+ #endif //ENABLE_UNWIND_GLUE
+ bool doPrintAvgBranch;
+ bool doCacheOTFSSR;
+ bool doCacheOTFSSRSet;
+ bool doExtendedSCC;
+ bool doCalcReach; ///<Calculate reachability, and influence variable decisions with that
+ bool doBXor;
+ bool doOTFSubsume; ///On-the-fly subsumption
+ uint64_t maxConfl;
+ bool isPlain; ///<We are in 'plain' mode: glues can never be 1
+
+ //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
+ #ifdef ENABLE_UNWIND_GLUE
+ uint32_t maxGlue; ///< Learnt clauses (when doing dynamic restarts) with glue above this value will be removed immediately on backtracking
+ #endif //ENABLE_UNWIND_GLUE
+ 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/prop/cryptominisat/Solver/SolverDebug.cpp b/src/prop/cryptominisat/Solver/SolverDebug.cpp
new file mode 100644
index 000000000..a831a2779
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/SolverDebug.cpp
@@ -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"
+
+using namespace CMSat;
+
+#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));
+ }
+}
+
+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;
+}
+
+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()));
+ }
+ }
+}
+
+bool Solver::findClause(XorClause* c) const
+{
+ for (uint32_t i = 0; i < xorclauses.size(); i++) {
+ if (xorclauses[i] == c) return true;
+ }
+ return false;
+}
+
+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();
+}
+
+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;
+}
+
+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;
+
+ for (vec<Watched>::const_iterator i = ws.getData(), end = ws.getDataEnd() ; i != end; i++) {
+ if (i->isBinary()
+ && value(lit) != l_True
+ && value(i->getOtherLit()) != l_True
+ ) {
+ std::cout << "bin clause: " << lit << " , " << i->getOtherLit() << " not satisfied!" << std::endl;
+ std::cout << "value of unsat bin clause: " << value(lit) << " , " << value(i->getOtherLit()) << std::endl;
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+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;
+}
+
+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 (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 (vec<Watched>::const_iterator 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;
+ }
+ }
+ }
+
+}
diff --git a/src/prop/cryptominisat/Solver/SolverMisc.cpp b/src/prop/cryptominisat/Solver/SolverMisc.cpp
new file mode 100644
index 000000000..c2007af2e
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/SolverMisc.cpp
@@ -0,0 +1,713 @@
+/***************************************************************************
+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
+
+using namespace CMSat;
+
+static const int space = 10;
+
+bool Solver::dumpSortedLearnts(const std::string& fileName, const uint32_t maxSize)
+{
+ FILE* outfile = fopen(fileName.c_str(), "w");
+ if (!outfile)
+ return false;
+
+ 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);
+ }
+
+ 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);
+ }
+ }
+ 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);
+ return true;
+}
+
+void Solver::printStrangeBinLit(const Lit lit) const
+{
+ const vec<Watched>& ws = watches[(~lit).toInt()];
+ for (vec<Watched>::const_iterator 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;
+ }
+ }
+}
+
+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++) {
+ const vec<Watched>& ws = *it;
+ for (vec<Watched>::const_iterator 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 (vec<Watched>::const_iterator 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);
+ }
+ }
+ }
+}
+
+uint32_t Solver::getBinWatchSize(const bool alsoLearnt, const Lit lit)
+{
+ uint32_t num = 0;
+ const vec<Watched>& ws = watches[lit.toInt()];
+ for (vec<Watched>::const_iterator it2 = ws.getData(), end2 = ws.getDataEnd(); it2 != end2; it2++) {
+ if (it2->isBinary() && (alsoLearnt || !it2->getLearnt())) {
+ num++;
+ }
+ }
+
+ return num;
+}
+
+void Solver::printBinClause(const Lit litP1, const Lit litP2, FILE* outfile) const
+{
+ if (value(litP1) == l_True) {
+ litP1.printFull(outfile);
+ } else if (value(litP1) == l_False) {
+ litP2.printFull(outfile);
+ } else if (value(litP2) == l_True) {
+ litP2.printFull(outfile);
+ } else if (value(litP2) == l_False) {
+ litP1.printFull(outfile);
+ } else {
+ litP1.print(outfile);
+ litP2.printFull(outfile);
+ }
+}
+
+bool Solver::dumpOrigClauses(const std::string& fileName) const
+{
+ FILE* outfile;
+ if (fileName != std::string("stdout")) {
+ outfile = fopen(fileName.c_str(), "w");
+ if (!outfile)
+ return false;
+ } else {
+ outfile = stdout;
+ }
+
+ 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();
+ }
+
+ 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);
+ }
+
+ 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;
+
+ Lit litP1 = ~lit;
+ Lit litP2 = Lit(var, false);
+ printBinClause(litP1, litP2, outfile);
+ printBinClause(~litP1, ~litP2, outfile);
+ }
+
+ 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);
+ }
+ }
+
+ if (fileName != "stdout") fclose(outfile);
+ return true;
+}
+
+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;
+}
+
+uint32_t Solver::getNumElimSubsume() const
+{
+ return subsumer->getNumElimed();
+}
+
+uint32_t Solver::getNumElimXorSubsume() const
+{
+ return xorSubsumer->getNumElimed();
+}
+
+uint32_t Solver::getNumXorTrees() const
+{
+ return varReplacer->getNumTrees();
+}
+
+uint32_t Solver::getNumXorTreesCrownSize() const
+{
+ return varReplacer->getNumReplacedVars();
+}
+
+double Solver::getTotalTimeSubsumer() const
+{
+ return subsumer->getTotalTime();
+}
+
+double Solver::getTotalTimeFailedLitSearcher() const
+{
+ return failedLitSearcher->getTotalTime();
+}
+
+double Solver::getTotalTimeXorSubsumer() const
+{
+ return xorSubsumer->getTotalTime();
+}
+
+double Solver::getTotalTimeSCC() const
+{
+ return sCCFinder->getTotalTime();
+}
+
+void Solver::printStatHeader() const
+{
+ if (conf.verbosity >= 2) {
+ 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) << "XorCls"
+ << std::setw(space) << "BinCls"
+ << std::setw(space) << "Learnts"
+ << std::setw(space) << "ClLits"
+ << std::setw(space) << "LtLits"
+ << std::setw(space) << "LGlueHist"
+ << std::setw(space) << "SGlueHist"
+ << 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) << xorclauses.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()
+{
+ if (conf.verbosity >= 1) {
+ 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
+*/
+bool Solver::needLibraryCNFFile(const std::string& fileName)
+{
+ libraryCNFFile = fopen(fileName.c_str(), "w");
+ return libraryCNFFile != NULL;
+}
+
+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");
+ }
+}
diff --git a/src/prop/cryptominisat/Solver/SolverTypes.h b/src/prop/cryptominisat/Solver/SolverTypes.h
new file mode 100644
index 000000000..4228ba06a
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/SolverTypes.h
@@ -0,0 +1,244 @@
+/*****************************************************************************
+MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+glucose -- Gilles Audemard, Laurent Simon (2008)
+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 __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 <stdio.h>
+#include <vector>
+#include "constants.h"
+
+//**********************************
+// Variables, literals, lifted booleans, clauses:
+//**********************************
+
+// NOTE! Variables are just integers. No abstraction here. They should be chosen from 0..N,
+// so that they can be used as array indices.
+
+namespace CMSat {
+
+typedef uint32_t Var;
+static const uint32_t 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;
+ explicit Lit(uint32_t i) : x(i) { };
+public:
+ Lit() : x(2*var_Undef) {} // (lit_Undef)
+ explicit Lit(Var var, bool sign) : x((var+var) + (int)sign) { }
+
+ const uint32_t& toInt() const { // Guarantees small, positive integers suitable for array indexing.
+ return x;
+ }
+ Lit operator~() const {
+ return Lit(x ^ 1);
+ }
+ Lit operator^(const bool b) const {
+ return Lit(x ^ (uint32_t)b);
+ }
+ Lit& operator^=(const bool b) {
+ x ^= (uint32_t)b;
+ return *this;
+ }
+ bool sign() const {
+ return x & 1;
+ }
+ Var var() const {
+ return x >> 1;
+ }
+ Lit unsign() const {
+ return Lit(x & ~1);
+ }
+ bool operator==(const Lit& p) const {
+ return x == p.x;
+ }
+ 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);
+ }
+ inline void printFull(FILE* outfile = stdout) const
+ {
+ fprintf(outfile,"%s%d 0\n", sign() ? "-" : "", var()+1);
+ }
+ static Lit toLit(uint32_t data)
+ {
+ return Lit(data);
+ }
+};
+
+static const Lit lit_Undef(var_Undef, false); // Useful special constants.
+static 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
+//**********************************
+
+class llbool;
+
+class lbool
+{
+ char value;
+ explicit lbool(char v) : value(v) { }
+
+public:
+ lbool() : value(0) { };
+ inline char getchar() const {
+ return value;
+ }
+ inline lbool(llbool b);
+
+ inline bool isUndef() const {
+ return !value;
+ }
+ inline bool isDef() const {
+ return value;
+ }
+ inline bool getBool() const {
+ return value == 1;
+ }
+ inline bool operator==(lbool b) const {
+ return value == b.value;
+ }
+ inline bool operator!=(lbool b) const {
+ return value != b.value;
+ }
+ lbool operator^(const bool b) const {
+ return b ? lbool(-value) : lbool(value);
+ }
+
+ friend lbool toLbool(const char v);
+ friend lbool boolToLBool(const bool b);
+ friend class llbool;
+};
+inline lbool toLbool(const char v)
+{
+ return lbool(v);
+}
+inline lbool boolToLBool(const bool b)
+{
+ return lbool(2*b-1);
+}
+
+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;
+
+public:
+ llbool(): value(0) {};
+ llbool(lbool v) :
+ value(v.value) {};
+ llbool(char a) :
+ value(a) {}
+
+ inline bool operator!=(const llbool& v) const {
+ return (v.value != value);
+ }
+
+ inline bool operator==(const llbool& v) const {
+ return (v.value == value);
+ }
+
+ friend class lbool;
+};
+const llbool l_Nothing = toLbool(2);
+const llbool l_Continue = toLbool(3);
+
+lbool::lbool(llbool b) : value(b.value) {}
+
+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 lev1Ancestor;
+ bool learntLeadHere;
+ bool hasChildren;
+};
+
+}
+
+#endif //SOLVERTYPES_H
diff --git a/src/prop/cryptominisat/Solver/StateSaver.cpp b/src/prop/cryptominisat/Solver/StateSaver.cpp
new file mode 100644
index 000000000..379fec2c4
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/StateSaver.cpp
@@ -0,0 +1,50 @@
+/***********************************************************************************
+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 "StateSaver.h"
+
+using namespace CMSat;
+
+StateSaver::StateSaver(Solver& _solver) :
+ solver(_solver)
+ , backup_order_heap(Solver::VarOrderLt(solver.activity))
+{
+ //Saving Solver state
+ backup_var_inc = solver.var_inc;
+ backup_activity.growTo(solver.activity.size());
+ std::copy(solver.activity.getData(), solver.activity.getDataEnd(), backup_activity.getData());
+ backup_order_heap = solver.order_heap;
+ backup_polarities = solver.polarity;
+ backup_restartType = solver.restartType;
+ backup_propagations = solver.propagations;
+ backup_random_var_freq = solver.conf.random_var_freq;
+}
+
+void StateSaver::restore()
+{
+ //Restore Solver state
+ solver.var_inc = backup_var_inc;
+ std::copy(backup_activity.getData(), backup_activity.getDataEnd(), solver.activity.getData());
+ solver.order_heap = backup_order_heap;
+ solver.polarity = backup_polarities;
+ solver.restartType = backup_restartType;
+ solver.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));
+}
diff --git a/src/prop/cryptominisat/Solver/StateSaver.h b/src/prop/cryptominisat/Solver/StateSaver.h
new file mode 100644
index 000000000..3450a2364
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/StateSaver.h
@@ -0,0 +1,44 @@
+/***********************************************************************************
+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 STATESAVER__H
+#define STATESAVER__H
+
+#include "Solver.h"
+
+namespace CMSat {
+
+class StateSaver
+{
+ public:
+ StateSaver(Solver& _solver);
+ void restore();
+
+ private:
+ Solver& solver;
+ Heap<Solver::VarOrderLt> backup_order_heap;
+ vector<char> backup_polarities;
+ vec<uint32_t> backup_activity;
+ uint32_t backup_var_inc;
+ RestartType backup_restartType;
+ double backup_random_var_freq;
+ uint64_t backup_propagations;
+};
+
+}
+
+#endif //STATESAVER__H
diff --git a/src/prop/cryptominisat/Solver/StreamBuffer.h b/src/prop/cryptominisat/Solver/StreamBuffer.h
new file mode 100644
index 000000000..6dc390415
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/StreamBuffer.h
@@ -0,0 +1,78 @@
+/******************************************************************************************[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
+
+namespace CMSat
+{
+
+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
diff --git a/src/prop/cryptominisat/Solver/Subsumer.cpp b/src/prop/cryptominisat/Solver/Subsumer.cpp
new file mode 100644
index 000000000..4b7eb4b2d
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/Subsumer.cpp
@@ -0,0 +1,2141 @@
+/*****************************************************************************
+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"
+#include "ClauseCleaner.h"
+#include "time_mem.h"
+#include "assert.h"
+#include <iomanip>
+#include <cmath>
+#include <algorithm>
+#include "VarReplacer.h"
+#include "XorFinder.h"
+#include "CompleteDetachReattacher.h"
+#include "OnlyNonLearntBins.h"
+#include "UselessBinRemover.h"
+#include "DataSync.h"
+#include "constants.h"
+#include "ClauseVivifier.h"
+
+//#define VERBOSE_DEBUG
+#ifdef VERBOSE_DEBUG
+#define BIT_MORE_VERBOSITY
+#endif
+
+//#define BIT_MORE_VERBOSITY
+
+using namespace CMSat;
+
+Subsumer::Subsumer(Solver& s):
+ solver(s)
+ , totalTime(0.0)
+ , numElimed(0)
+ , numCalls(1)
+{
+}
+
+/**
+@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<vector<Lit> > > elimType;
+ for (elimType::iterator it = elimedOutVar.begin(), end = elimedOutVar.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<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(2);
+ tmp[0] = it2->first;
+ tmp[1] = it2->second;
+
+ #ifdef VERBOSE_DEBUG
+ 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
+*/
+bool Subsumer::unEliminate(const Var var)
+{
+ assert(var_elimed[var]);
+ vec<Lit> tmp;
+ 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() && it2 == elimedOutVarBin.end()) {
+ return solver.ok;
+ }
+
+ FILE* backup_libraryCNFfile = solver.libraryCNFFile;
+ solver.libraryCNFFile = NULL;
+
+ 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);
+ }
+ 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;
+}
+
+/**
+@brief Backward-subsumption using given clause: helper function
+
+Checks all clauses in the occurrence lists if they are subsumed by ps or not.
+
+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)
+{
+ #ifdef VERBOSE_DEBUG
+ cout << "subsume0-ing with clause: ";
+ ps.plainPrint();
+ #endif
+ 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();
+ }
+ }
+}
+
+/**
+@brief Backward-subsumption using given clause
+
+@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>
+Subsumer::subsume0Happened Subsumer::subsume0Orig(const T& ps, uint32_t abs)
+{
+ 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++){
+ #ifdef VERBOSE_DEBUG
+ cout << "-> subsume0 removing:";
+ subs[i].clause->plainPrint();
+ #endif
+
+ Clause* tmp = subs[i].clause;
+ 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]);
+ }
+
+ return ret;
+}
+
+/**
+@brief Backward subsumption and self-subsuming resolution
+
+Performs backward subsumption AND
+self-subsuming resolution using backward-subsumption
+
+@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
+
+ 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;
+ }
+ }
+}
+
+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 {
+ strenghten(c, subsLits[j]);
+ if (!solver.ok) return false;
+ }
+ }
+
+ return toMakeNonLearnt;
+}
+
+/**
+@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;
+
+ 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);
+ touchedVars.touch(cl[i], cl.learnt());
+ }
+
+ // Remove from iterator vectors/sets:
+ 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);
+
+ //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;
+}
+
+
+/**
+@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
+*/
+bool Subsumer::cleanClause(Clause& ps)
+{
+ 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) {
+ removeW(occur[i->toInt()], &ps);
+ numMaxSubsume1 -= occur[i->toInt()].size()/2;
+ touchedVars.touch(*i, ps.learnt());
+ continue;
+ }
+ if (val == l_True) {
+ *j++ = *i;
+ retval = true;
+ continue;
+ }
+ assert(false);
+ }
+ ps.shrink(i-j);
+
+ return retval;
+}
+
+bool Subsumer::cleanClause(vec<Lit>& ps) const
+{
+ 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;
+ }
+ assert(false);
+ }
+ ps.shrink(i-j);
+
+ return retval;
+}
+
+/**
+@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)
+{
+ #ifdef VERBOSE_DEBUG
+ cout << "-> Strenghtening clause :";
+ c.clause->plainPrint();
+ cout << " with lit: " << toRemoveLit << std::endl;
+ #endif
+
+ literals_removed++;
+ c.clause->strengthen(toRemoveLit);
+ removeW(occur[toRemoveLit.toInt()], c.clause);
+ numMaxSubsume1 -= occur[toRemoveLit.toInt()].size()/2;
+ touchedVars.touch(toRemoveLit, c.clause->learnt());
+
+ if (cleanClause(*c.clause)) {
+ unlinkClause(c);
+ c.clause = NULL;
+ return;
+ }
+
+ switch (c.clause->size()) {
+ case 0:
+ #ifdef VERBOSE_DEBUG
+ 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);
+ }
+}
+
+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);
+ }
+ }
+ if (!solver.ok) return false;
+ clBinSize++;
+ }
+ clBinTouched.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;
+ }
+
+ return true;
+}
+
+/**
+@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)
+{
+ if (solver.value(lit) == l_False) {
+ solver.ok = false;
+ } else if (solver.value(lit) == l_Undef) {
+ solver.uncheckedEnqueue(lit);
+ solver.ok = solver.propagate<false>().isNULL();
+ } else {
+ assert(solver.value(lit) == l_True);
+ }
+}
+
+/**
+@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.
+*/
+bool Subsumer::subsume0AndSubsume1()
+{
+ CSet s0, s1;
+
+ uint32_t clTouchedTodo = 2000;
+ if (addedClauseLits > 3000000) clTouchedTodo /= 2;
+ if (addedClauseLits > 10000000) clTouchedTodo /= 4;
+
+ registerIteration(s0);
+ registerIteration(s1);
+ vec<ClauseSimp> remClTouched;
+
+ // Fixed-point for 1-subsumption:
+ #ifdef BIT_MORE_VERBOSITY
+ std::cout << "c cl_touched.nElems() = " << cl_touched.nElems() << std::endl;
+ #endif
+ while ((cl_touched.nElems() > 10) && numMaxSubsume0 > 0) {
+ #ifdef VERBOSE_DEBUG
+ 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;
+ const bool doSubs1Next = (numMaxSubsume1 > 0);
+ for (CSet::iterator it = cl_touched.begin(), end = cl_touched.end(); it != end; ++it) {
+ if (it->clause == NULL) continue;
+ Clause& cl = *it->clause;
+
+ if (s1Added >= clTouchedTodo) {
+ break;
+ }
+
+ s0.add(*it);
+ s1Added += s1.add(*it);
+ bool unset = true;
+
+ for (uint32_t j = 0; j < cl.size(); j++) {
+ if (!ol_seenPos[cl[j].toInt()]) {
+ vec<ClauseSimp>& occs = occur[(cl[j]).toInt()];
+ for (uint32_t k = 0; k < occs.size(); k++) {
+ if (s1Added >= clTouchedTodo) {
+ unset = false;
+ break;
+ }
+ s0.add(occs[k]);
+ }
+ }
+ ol_seenPos[cl[j].toInt()] = 1;
+
+ if (s1Added >= clTouchedTodo) {
+ unset = false;
+ break;
+ }
+
+ if (!ol_seenNeg[(~cl[j]).toInt()]) {
+ vec<ClauseSimp>& occs = occur[(~cl[j]).toInt()];
+ for (uint32_t k = 0; k < occs.size(); k++) {
+ if (s1Added >= clTouchedTodo) {
+ unset = false;
+ break;
+ }
+
+ s1Added += s1.add(occs[k]);
+ }
+ }
+ ol_seenNeg[(~cl[j]).toInt()] = 1;
+
+ if (s1Added >= clTouchedTodo) {
+ unset = false;
+ break;
+ }
+ }
+
+ remClTouched.push(*it);
+ if (doSubs1Next && unset)
+ it->clause->unsetChanged();
+ }
+ //std::cout << "s0.nElems(): " << s0.nElems() << std::endl;
+ //std::cout << "s1.nElems(): " << s1.nElems() << std::endl;
+
+ for (uint32_t i = 0; i < remClTouched.size(); i++) {
+ cl_touched.exclude(remClTouched[i]);
+ }
+ remClTouched.clear();
+
+ for (CSet::iterator it = s0.begin(), end = s0.end(); it != end; ++it) {
+ if (it->clause == NULL) continue;
+ subsume0(*it->clause);
+ }
+ s0.clear();
+
+ if (doSubs1Next) {
+ for (CSet::iterator it = s1.begin(), end = s1.end(); it != end; ++it) {
+ if (it->clause == NULL) continue;
+ subsume1(*it->clause);
+ if (!solver.ok) goto end;
+ }
+ s1.clear();
+ }
+
+ if (!handleClBinTouched()) goto end;
+ }
+ cl_touched.clear();
+ end:
+
+ unregisterIteration(s1);
+ 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);
+ touchedVars.touch(cl[i], cl.learnt());
+ if (cl.getChanged()) {
+ ol_seenPos[cl[i].toInt()] = 0;
+ ol_seenNeg[(~cl[i]).toInt()] = 0;
+ }
+ }
+ if (cl.getChanged())
+ cl_touched.add(c);
+
+ return c;
+}
+
+/**
+@brief Adds clauses from the solver to here, and removes them from the solver
+
+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.
+*/
+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++) {
+ if (i+1 != end) __builtin_prefetch(*(i+1));
+
+ linkInClause(**i);
+ numLitsAdded += (*i)->size();
+ }
+ 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++) {
+ occur[i].clear(true);
+ }
+}
+
+/**
+@brief Adds clauses from here, back to the solver
+*/
+void Subsumer::addBackToSolver()
+{
+ assert(solver.clauses.size() == 0);
+ for (uint32_t i = 0; i < clauses.size(); i++) {
+ 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);
+ }
+}
+
+/**
+@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();
+ Clause **j = i;
+ for (Clause **end = i + cs.size(); i != end; i++) {
+ Clause& c = **i;
+ if (!c.learnt()) {
+ *j++ = *i;
+ continue;
+ }
+ bool remove = false;
+ for (Lit *l = c.getData(), *end2 = l+c.size(); l != end2; l++) {
+ if (var_elimed[l->var()]) {
+ remove = true;
+ //solver.detachClause(c);
+ solver.clauseAllocator.clauseFree(&c);
+ break;
+ }
+ }
+ if (!remove)
+ *j++ = *i;
+ }
+ 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;
+
+ vec<Watched>::iterator i = ws.getData();
+ vec<Watched>::iterator j = i;
+ for (vec<Watched>::iterator 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);
+ for (uint32_t i = 0; i < solver.xorclauses.size(); i++) {
+ const XorClause& c = *solver.xorclauses[i];
+ for (uint32_t i2 = 0; i2 < c.size(); i2++)
+ cannot_eliminate[c[i2].var()] = true;
+ }
+
+ 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++)
+ if (cannot_eliminate[i])
+ tmpNum++;
+ std::cout << "Cannot eliminate num:" << tmpNum << std::endl;
+ #endif
+}
+
+/**
+@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().
+*/
+/*bool Subsumer::subsumeWithBinTri()
+{
+ assert(solver.ok);
+
+ double mytime = cpuTime();
+ uint32_t subsumed_bin = 0;
+ uint32_t subsumed_tri = 0;
+ uint32_t lit_rem_bin = 0;
+ uint32_t lit_rem_tri = 0;
+ if (!subsumeWithBinTri(solver.clauses, false, subsumed_bin, subsumed_tri, lit_rem_bin, lit_rem_tri))
+ return false;
+
+ if (!subsumeWithBinTri(solver.learnts, true, subsumed_bin, subsumed_tri, lit_rem_bin, lit_rem_tri))
+ return false;
+
+ if (solver.conf.verbosity > 0) {
+ std::cout
+ << "c subs-w-b: " << subsumed_bin
+ << " subs-w-t: " << subsumed_tri
+ << " lit-rem-w-b: " << lit_rem_bin
+ << " lit-rem-w-t: " << lit_rem_tri
+ << " T: " << std::fixed << std::setprecision(2) << (cpuTime() - mytime)
+ << std::endl;
+ }
+ return true;
+}
+
+bool Subsumer::subsumeWithBinTri(
+ vec<Clause*>& cls
+ , bool learnt
+ , uint32_t& subsumed_bin_num
+ , uint32_t& subsumed_tri_num
+ , uint32_t& lit_rem_bin
+ , uint32_t& lit_rem_tri
+) {
+ //Temporaries
+ vector<Lit> lits_set;
+ vector<char> seen_tmp2;
+ seen_tmp2.resize(solver.nVars()*2);
+ uint32_t to_remove_bin = 0;
+ uint32_t to_remove_tri = 0;
+
+ Clause** cit = cls.getData();
+ Clause** cit2 = cit;
+ Clause** cend = cls.getDataEnd();
+
+ for(; cit2 != cend; cit2++) {
+ Clause& c = **cit2;
+
+ //Set up seen_tmp
+ lits_set.resize(c.size());
+ for(size_t i = 0; i < c.size(); i++) {
+ seen_tmp[c[i].toInt()] = 1;
+ seen_tmp2[c[i].toInt()] = 1;
+ lits_set[i] = c[i];
+ }
+
+ bool subsumed = false;
+
+
+ if (subsumed) {
+#ifdef VERBOSE_DEBUG
+ std::cout << "Removing: ";
+ c.plainPrint();
+#endif
+ solver.removeClause(c);
+ } else if (to_remove_bin > 0 || to_remove_tri > 0) {
+ lit_rem_bin += to_remove_bin;
+ lit_rem_tri += to_remove_tri;
+ solver.detachClause(c);
+
+#ifdef VERBOSE_DEBUG
+ std::cout << "Detached clause: (ptr: " << (&c) << " ) ";
+ c.plainPrint();;
+#endif
+
+ vec<Lit> lits;
+ for(size_t i = 0; i < c.size(); i++) {
+ if (seen_tmp2[c[i].toInt()])
+ lits.push(c[i]);
+ }
+
+ Clause *c2 = solver.addClauseInt(lits, c.learnt(), c.getGlue(), c.getMiniSatAct());
+ solver.clauseAllocator.clauseFree(&c);
+ if (c2 != NULL) {
+ *cit++ = c2;
+ }
+
+ if (!solver.ok) {
+ break;
+ }
+ } else {
+ *cit++ = *cit2;
+ }
+
+ for(vector<Lit>::const_iterator it = lits_set.begin(), end = lits_set.end(); it != end; it++) {
+ seen_tmp[it->toInt()] = 0;
+ seen_tmp2[it->toInt()] = 0;
+ }
+ lits_set.clear();
+ to_remove_bin = 0;
+ to_remove_tri = 0;
+ }
+ cls.shrink(cit2-cit);
+
+ return solver.ok;
+}*/
+
+/**
+@brief Clears and deletes (almost) everything in this class
+
+Clears touchlists, occurrance lists, clauses, and variable touched lists
+*/
+void Subsumer::clearAll()
+{
+ touchedVars.clear();
+ clauses.clear();
+ cl_touched.clear();
+ addedClauseLits = 0;
+ for (Var var = 0; var < solver.nVars(); var++) {
+ occur[2*var].clear();
+ occur[2*var+1].clear();
+ ol_seenNeg[2*var ] = 1;
+ ol_seenNeg[2*var + 1] = 1;
+ ol_seenPos[2*var ] = 1;
+ ol_seenPos[2*var + 1] = 1;
+ }
+}
+
+bool Subsumer::eliminateVars()
+{
+ #ifdef BIT_MORE_VERBOSITY
+ std::cout << "c VARIABLE ELIMINIATION -- touchedVars size:" << touchedVars.size() << std::endl;
+ #endif
+
+ uint32_t vars_elimed = 0;
+
+ vec<Var> order;
+ orderVarsForElim(order);
+
+ #ifdef VERBOSE_DEBUG
+ std::cout << "c #order size:" << order.size() << std::endl;
+ #endif
+
+ uint32_t numtry = 0;
+ for (uint32_t i = 0; i < order.size() && numMaxElim > 0 && numMaxElimVars > 0; i++) {
+ Var var = order[i];
+ if (!cannot_eliminate[var] && solver.decision_var[var]) {
+ numtry++;
+ if (maybeEliminate(order[i])) {
+ if (!solver.ok) return false;
+ vars_elimed++;
+ numMaxElimVars--;
+ }
+ }
+ }
+ numVarsElimed += vars_elimed;
+
+ #ifdef BIT_MORE_VERBOSITY
+ std::cout << "c #try to eliminate: " << numtry << std::endl;
+ std::cout << "c #var-elim: " << vars_elimed << std::endl;
+ #endif
+
+ 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());
+
+ vec<Watched>::iterator i = ws.getData();
+ vec<Watched>::iterator j = i;
+
+ Lit lastLit = lit_Undef;
+ bool lastLearnt = false;
+ for (vec<Watched>::iterator end = ws.getDataEnd(); i != end; i++) {
+ if (!i->isBinary()) {
+ *j++ = *i;
+ continue;
+ }
+ 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;
+ touchedVars.touch(lit, i->getLearnt());
+ touchedVars.touch(i->getOtherLit(), i->getLearnt());
+ }
+ solver.numBins--;
+ } else {
+ lastLit = i->getOtherLit();
+ lastLearnt = i->getLearnt();
+ *j++ = *i;
+ }
+ }
+ ws.shrink_(i-j);
+ }
+
+ 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;
+ clauses_subsumed += (numBinsBefore - solver.numBins);
+}
+
+/**
+@brief Main function in this class
+
+Performs, recursively:
+* backward-subsumption
+* self-subsuming resolution
+* variable elimination
+
+*/
+bool Subsumer::simplifyBySubsumption()
+{
+ if (solver.nClauses() > 50000000
+ || solver.clauses_literals > 500000000) return true;
+
+ double myTime = cpuTime();
+ clauseID = 0;
+ clearAll();
+
+ //touch all variables
+ for (Var var = 0; var < solver.nVars(); var++) {
+ if (solver.decision_var[var] && solver.assigns[var] == l_Undef) touchedVars.touch(var);
+ }
+
+ if (solver.conf.doReplace && !solver.varReplacer->performReplace(true))
+ return false;
+ /*if (solver.conf.doSubsWBins && !subsumeWithBinTri())
+ return false;*/
+
+ fillCannotEliminate();
+
+ uint32_t expected_size = solver.clauses.size() + solver.learnts.size();
+ if (expected_size > 10000000) return solver.ok;
+
+ clauses.reserve(expected_size);
+ cl_touched.reserve(expected_size);
+
+ solver.clauseCleaner->cleanClauses(solver.clauses, ClauseCleaner::clauses);
+ solver.clauseCleaner->cleanClauses(solver.learnts, ClauseCleaner::learnts);
+
+ if (solver.clauses.size() < 10000000)
+ std::sort(solver.clauses.getData(), solver.clauses.getDataEnd(), sortBySize());
+ addedClauseLits += addFromSolver(solver.clauses);
+
+ if (solver.learnts.size() < 300000)
+ std::sort(solver.learnts.getData(), solver.learnts.getDataEnd(), sortBySize());
+ addedClauseLits += addFromSolver(solver.learnts);
+
+ CompleteDetachReatacher reattacher(solver);
+ reattacher.detachNonBinsNonTris(false);
+ totalTime += myTime - cpuTime();
+
+ //Do stuff with binaries
+ subsumeBinsWithBins();
+ numMaxSubsume1 = 500*1000*1000;
+ if ((solver.conf.doBlockedClause)
+ && solver.conf.doVarElim) {
+ numMaxBlockToVisit = (int64_t)800*1000*1000;
+ blockedClauseRemoval();
+ }
+
+ numMaxSubsume1 = 2*1000*1000*1000;
+ //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
+
+ do {
+ if (!subsume0AndSubsume1()) return false;
+
+ if (!solver.conf.doVarElim) break;
+
+ if (!eliminateVars()) return false;
+
+ //subsumeBinsWithBins();
+ solver.clauseCleaner->removeSatisfiedBins();
+ } while (cl_touched.nElems() > 10);
+
+ 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.
+*/
+void Subsumer::setLimits()
+{
+ numMaxSubsume0 = 300*1000*1000;
+ numMaxSubsume1 = 30*1000*1000;
+
+ numMaxElim = 500*1000*1000;
+ numMaxElim *= 6;
+
+ #ifdef BIT_MORE_VERBOSITY
+ std::cout << "c addedClauseLits: " << addedClauseLits << std::endl;
+ #endif
+
+ if (addedClauseLits < 5000000) {
+ numMaxElim *= 2;
+ numMaxSubsume0 *= 2;
+ numMaxSubsume1 *= 2;
+ }
+
+ if (addedClauseLits < 1000000) {
+ numMaxElim *= 2;
+ numMaxSubsume0 *= 2;
+ numMaxSubsume1 *= 2;
+ }
+
+ numMaxElimVars = (uint64_t) (((double)solver.order_heap.size()*0.3) * sqrt((double)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;
+
+
+ numCalls++;
+
+ //For debugging
+
+ //numMaxSubsume0 = 0;
+ //numMaxSubsume1 = 0;
+ //numMaxSubsume0 = std::numeric_limits<int64_t>::max();
+ //numMaxSubsume1 = std::numeric_limits<int64_t>::max();
+ //numMaxElimVars = std::numeric_limits<int32_t>::max();
+ //numMaxElim = std::numeric_limits<int64_t>::max();
+
+ //numMaxBlockToVisit = std::numeric_limits<int64_t>::max();
+ //numMaxBlockVars = std::numeric_limits<uint32_t>::max();
+}
+
+/*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());
+ }
+ 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) << (cpuTime() - myTime) << " s"
+ << std::endl;
+ }
+ totalTime += cpuTime() - myTime;
+ return true;
+}
+
+#define MAX_BINARY_PROP 60000000
+
+bool Subsumer::subsWNonExistBinsFull()
+{
+ uint64_t oldProps = solver.propagations;
+ 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[(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.cancelUntilLight();
+ solver.uncheckedEnqueue(~lit);
+ solver.ok = solver.propagate<false>().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.cancelUntilLight();
+ solver.uncheckedEnqueue(~lit);
+ solver.ok = solver.propagate<false>().isNULL();
+ if (!solver.ok) return false;
+ continue;
+ }
+ extraTimeNonExist += 10;
+ }
+
+ if (onlyNonLearntBins) delete onlyNonLearntBins;
+
+ return true;
+}
+
+bool Subsumer::subsWNonExistBins(const Lit& lit, OnlyNonLearntBins* onlyNonLearntBins)
+{
+ #ifdef VERBOSE_DEBUG
+ std::cout << "subsWNonExistBins called with lit " << lit << std::endl;
+ #endif //VERBOSE_DEBUG
+ toVisit.clear();
+ solver.newDecisionLevel();
+ solver.uncheckedEnqueueLight(lit);
+ 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 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.cancelUntilLight();
+ subsume0BIN(~lit, toVisitAll, abst);
+
+ for (uint32_t i = 0; i < toVisit.size(); i++)
+ toVisitAll[toVisit[i].toInt()] = false;
+
+ return solver.ok;
+}
+
+void Subsumer::subsume0BIN(const Lit lit1, const vec<char>& lits, const uint32_t abst)
+{
+ vec<ClauseSimp> subs;
+ vec<ClauseSimp> subs2;
+ vec<Lit> subs2Lit;
+
+ 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);
+ 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 (!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++){
+ unlinkClause(subs[i]);
+ }
+
+ for (uint32_t i = 0; i < subs2.size(); i++) {
+ strenghten(subs2[i], subs2Lit[i]);
+ if (!solver.ok) break;
+ }
+
+ #ifdef VERBOSE_DEBUG
+ if (!solver.ok) {
+ std::cout << "solver.ok is false when returning from subsume0BIN()" << std::endl;
+ }
+ #endif //VERBOSE_DEBUG
+}*/
+
+
+
+/**
+@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: " << 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);
+
+ 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);
+
+ 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
+ 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));
+ touchedVars.touch(c.lit1, false);
+ touchedVars.touch(c.lit2, false);
+ }
+ }
+}
+
+/**
+@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)
+{
+ 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;
+}
+
+uint32_t Subsumer::numNonLearntBins(const Lit lit) const
+{
+ uint32_t num = 0;
+ const vec<Watched>& ws = solver.watches[(~lit).toInt()];
+ for (vec<Watched>::const_iterator it = ws.getData(), end = ws.getDataEnd(); it != end; it++) {
+ if (it->isBinary() && !it->getLearnt()) num++;
+ }
+
+ return num;
+}
+
+void Subsumer::fillClAndBin(vec<ClAndBin>& all, vec<ClauseSimp>& cs, const Lit lit)
+{
+ for (uint32_t i = 0; i < cs.size(); i++) {
+ if (!cs[i].clause->learnt()) all.push(ClAndBin(cs[i]));
+ }
+
+ const vec<Watched>& ws = solver.watches[(~lit).toInt()];
+ for (vec<Watched>::const_iterator it = ws.getData(), end = ws.getDataEnd(); it != end; it++) {
+ if (it->isBinary() &&!it->getLearnt()) all.push(ClAndBin(lit, it->getOtherLit()));
+ }
+}
+
+/**
+@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(!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;*/
+
+ vec<ClauseSimp>& poss = occur[lit.toInt()];
+ vec<ClauseSimp>& negs = occur[(~lit).toInt()];
+ const uint32_t numNonLearntPos = numNonLearntBins(lit);
+ const uint32_t numNonLearntNeg = numNonLearntBins(~lit);
+ uint32_t before_literals = numNonLearntNeg*2 + numNonLearntPos*2;
+
+ uint32_t posSize = 0;
+ for (uint32_t i = 0; i < poss.size(); i++)
+ if (!poss[i].clause->learnt()) {
+ posSize++;
+ before_literals += poss[i].clause->size();
+ }
+ posSize += numNonLearntPos;
+
+ uint32_t negSize = 0;
+ for (uint32_t i = 0; i < negs.size(); i++)
+ if (!negs[i].clause->learnt()) {
+ negSize++;
+ before_literals += negs[i].clause->size();
+ }
+ negSize += numNonLearntNeg;
+
+ numMaxElim -= posSize + negSize;
+
+ // Heuristic CUT OFF:
+ if (posSize >= 10 && negSize >= 10) return false;
+
+ // Heuristic CUT OFF2:
+ if ((posSize >= 3 && negSize >= 3 && before_literals > 300)
+ && clauses.size() > 700000)
+ return false;
+ if ((posSize >= 5 && negSize >= 5 && before_literals > 400)
+ && clauses.size() <= 700000 && clauses.size() > 100000)
+ return false;
+ 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);
+
+ // Count clauses/literals after elimination:
+ 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();
+ const bool ok = merge(posAll[i], negAll[j], lit, ~lit, dummy);
+ if (ok){
+ after_clauses++;
+ if (after_clauses > before_clauses)
+ return false;
+ }
+ }
+
+ //Eliminate
+ //removing clauses (both non-learnt and learnt)
+ vec<ClauseSimp> tmp1 = poss;
+ poss.clear();
+ for (uint32_t i = 0; i < tmp1.size(); i++) {
+ if (tmp1[i].clause->learnt()) unlinkClause(tmp1[i]);
+ }
+ vec<ClauseSimp> tmp2 = negs;
+ negs.clear();
+ for (uint32_t i = 0; i < tmp2.size(); i++) {
+ if (tmp2[i].clause->learnt()) unlinkClause(tmp2[i]);
+ }
+
+ removeClauses(posAll, negAll, var);
+
+ //check watchlists
+ #ifndef NDEBUG
+ const vec<Watched>& ws1 = solver.watches[lit.toInt()];
+ for (vec<Watched>::const_iterator i = ws1.getData(), end = ws1.getDataEnd(); i != end; i++) {
+ assert(i->isTriClause() || (i->isBinary() && i->getLearnt()));
+ }
+ const vec<Watched>& ws2 = solver.watches[(~lit).toInt()];
+ for (vec<Watched>::const_iterator i = ws2.getData(), end = ws2.getDataEnd(); i != end; i++) {
+ assert(i->isTriClause() || (i->isBinary() && i->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;
+
+ 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 (numMaxSubsume1 > 0)
+ subsume1(dummy, false);
+ break;
+ }
+ default: {
+ Clause* cl = solver.clauseAllocator.Clause_new(dummy);
+ ClauseSimp c = linkInClause(*cl);
+ if (numMaxSubsume1 > 0) subsume1(*c.clause);
+ else if (numMaxSubsume0) subsume0(*c.clause);
+ }
+ }
+ if (!solver.ok) return true;
+ }
+
+ assert(occur[lit.toInt()].size() == 0 && occur[(~lit).toInt()].size() == 0);
+ var_elimed[var] = true;
+ numElimed++;
+ solver.setDecisionVar(var, false);
+ return true;
+}
+
+/**
+@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)
+{
+ bool retval = true;
+ if (ps.isBin) {
+ numMaxElim -= 2;
+ 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()*5;
+ 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]);
+ }
+ }
+ }
+
+ if (qs.isBin) {
+ numMaxElim -= 2;
+ 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()*5;
+ 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]);
+ }
+ }
+ }
+
+ end:
+ if (ps.isBin) {
+ seen_tmp[ps.lit2.toInt()] = 0;
+ } else {
+ Clause& c = *ps.clsimp.clause;
+ for (uint32_t i = 0; i < c.size(); i++)
+ seen_tmp[c[i].toInt()] = 0;
+ }
+
+ 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 (vector<Var>::const_iterator it = touchedVars.begin(), end = touchedVars.end(); it != end ; it++){
+ Lit x = Lit(*it, false);
+
+ //Long non-learnt POS
+ uint32_t pos = 0;
+ const vec<ClauseSimp>& poss = occur[x.toInt()];
+ for (uint32_t i = 0; i < poss.size(); i++)
+ if (!poss[i].clause->learnt()) pos++;
+
+ //Long non-learnt NEG
+ uint32_t neg = 0;
+ const vec<ClauseSimp>& negs = occur[(~x).toInt()];
+ for (uint32_t i = 0; i < negs.size(); i++)
+ if (!negs[i].clause->learnt()) neg++;
+
+ //Short non-lerants
+ //uint32_t nNonLPos = numNonLearntBins(x);
+ //uint32_t nNonLNeg = numNonLearntBins(~x);
+
+ //uint32_t cost = pos*neg/2 + nNonLPos*neg*2 + nNonLNeg*pos*2 + nNonLNeg*nNonLPos*6;
+ uint32_t cost = pos*neg * 2 + numNonLearntBins(x) * neg + numNonLearntBins(~x) * pos;
+
+ cost_var.push(std::make_pair(cost, x.var()));
+ }
+ touchedVars.clear();
+
+ std::sort(cost_var.getData(), cost_var.getDataEnd(), myComp());
+ for (uint32_t x = 0; x < cost_var.size(); x++) {
+ order.push(cost_var[x].second);
+ }
+}
+
+/**
+@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
+*/
+bool Subsumer::verifyIntegrity()
+{
+ 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++) {
+ #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;
+}
+
+template<class T>
+bool Subsumer::allTautology(const T& ps, const Lit lit)
+{
+ #ifdef VERBOSE_DEBUG
+ cout << "allTautology: " << ps << std::endl;
+ #endif
+
+ numMaxBlockToVisit -= ps.size()*2;
+ for (const Lit *l = ps.getData(), *end = ps.getDataEnd(); l != end; l++) {
+ if (*l != ~lit) seen_tmp[l->toInt()] = true;
+ }
+
+ bool allIsTautology = true;
+ 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);
+
+ 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 (vec<Watched>::const_iterator 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.empty()) return;
+
+ double myTime = cpuTime();
+ 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++) {
+ //if (solver.order_heap.size() < 1) break;
+ //touchBlockedVar(solver.order_heap[solver.mtrand.randInt(solver.order_heap.size()-1)]);
+ touchBlockedVar(solver.order_heap[i]);
+ }
+
+ uint32_t triedToBlock = 0;
+ while (numMaxBlockToVisit > 0 && !touchedBlockedVars.empty()) {
+ VarOcc vo = touchedBlockedVars.top();
+ touchedBlockedVars.pop();
+ 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);
+
+ //if (!tryOneSetting(lit)) {
+ tryOneSetting(lit);
+ // }
+ }
+
+ 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;
+ }
+}
+
+bool Subsumer::tryOneSetting(const Lit lit)
+{
+ numMaxBlockToVisit -= occur[lit.toInt()].size();
+ for(ClauseSimp *it = occur[lit.toInt()].getData(), *end = occur[lit.toInt()].getDataEnd(); it != end; it++) {
+ if (!allTautology(*it->clause, ~lit)) {
+ return false;
+ }
+ }
+
+ vec<Lit> lits(1);
+ const vec<Watched>& ws = solver.watches[(~lit).toInt()];
+ numMaxBlockToVisit -= ws.size();
+ for (vec<Watched>::const_iterator it = ws.getData(), end = ws.getDataEnd(); it != end; it++) {
+ if (!it->isNonLearntBinary()) continue;
+ lits[0] = it->getOtherLit();
+ if (!allTautology(lits, ~lit)) return false;
+ }
+
+ blockedClauseElimAll(lit);
+ blockedClauseElimAll(~lit);
+
+ var_elimed[lit.var()] = true;
+ numElimed++;
+ numMaxElimVars--;
+ solver.setDecisionVar(lit.var(), false);
+
+ return true;
+}
+
+void Subsumer::blockedClauseElimAll(const Lit lit)
+{
+ 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++;
+ }
+
+ uint32_t removedNum = 0;
+ vec<Watched>& ws = solver.watches[(~lit).toInt()];
+ vec<Watched>::iterator i = ws.getData();
+ vec<Watched>::iterator j = i;
+ for (vec<Watched>::iterator end = ws.getDataEnd(); i != end; i++) {
+ if (!i->isNonLearntBinary()) {
+ *j++ = *i;
+ continue;
+ }
+ assert(!i->getLearnt());
+ removeWBin(solver.watches[(~i->getOtherLit()).toInt()], lit, false);
+ elimedOutVarBin[lit.var()].push_back(std::make_pair(lit, i->getOtherLit()));
+ touchedVars.touch(i->getOtherLit(), false);
+ removedNum++;
+ }
+ ws.shrink_(i-j);
+
+ 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
+*/
+bool Subsumer::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;
+}
diff --git a/src/prop/cryptominisat/Solver/Subsumer.h b/src/prop/cryptominisat/Solver/Subsumer.h
new file mode 100644
index 000000000..24a7da927
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/Subsumer.h
@@ -0,0 +1,500 @@
+/*****************************************************************************
+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
+
+#include "Solver.h"
+#include "CSet.h"
+#include "BitArray.h"
+#include <map>
+#include <vector>
+#include <list>
+#include <queue>
+
+namespace CMSat {
+
+using std::vector;
+using std::list;
+using std::map;
+using std::priority_queue;
+
+class ClauseCleaner;
+class OnlyNonLearntBins;
+
+class TouchList
+{
+ public:
+ void resize(uint32_t size)
+ {
+ touched.resize(size, 0);
+ }
+
+ void addOne(Var var)
+ {
+ assert(touched.size() == var);
+ touched.push_back(1);
+ touchedList.push_back(var);
+ }
+
+ void touch(Lit lit, const bool learnt)
+ {
+ if (!learnt) touch(lit.var());
+ }
+
+ void touch(Var var)
+ {
+ if (!touched[var]) {
+ touchedList.push_back(var);
+ touched[var]= 1;
+ }
+ }
+
+ void clear()
+ {
+ touchedList.clear();
+ std::fill(touched.begin(), touched.end(), 0);
+ }
+
+ uint32_t size() const
+ {
+ return touchedList.size();
+ }
+
+ vector<Var>::const_iterator begin() const
+ {
+ return touchedList.begin();
+ }
+
+ vector<Var>::const_iterator end() const
+ {
+ return touchedList.end();
+ }
+
+ private:
+ vector<Var> touchedList;
+ vector<char> touched;
+};
+
+/**
+@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);
+
+ //Called from main
+ bool simplifyBySubsumption();
+ void newVar();
+
+ //UnElimination
+ void extendModel(Solver& solver2);
+ bool unEliminate(const Var var);
+
+ //Get-functions
+ const vec<char>& getVarElimed() const;
+ uint32_t getNumElimed() const;
+ bool checkElimedUnassigned() const;
+ double getTotalTime() const;
+ const map<Var, vector<vector<Lit> > >& getElimedOutVar() const;
+ const map<Var, vector<std::pair<Lit, Lit> > >& getElimedOutVarBin() const;
+
+private:
+
+ /*bool subsumeWithBinTri();
+ bool subsumeWithBinTri(
+ vec<Clause*>& cls
+ , bool learnt
+ , uint32_t& subsumed_bin_num
+ , uint32_t& subsumed_tri_num
+ , uint32_t& lit_rem_bin
+ , uint32_t& lit_rem_tri
+ );*/
+
+ 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;
+ TouchList touchedVars; ///<Is set to true when a variable is part of a removed clause. Also true initially (upon variable creation).
+ 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; ///<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
+ 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
+ int32_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
+ uint64_t addFromSolver(vec<Clause*>& cs);
+ void fillCannotEliminate();
+ void clearAll();
+ void setLimits();
+ 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); }
+
+ //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);
+ template<class T>
+ void findSubsumed1(const T& ps, uint32_t abs, vec<ClauseSimp>& out_subsumed, vec<Lit>& out_lits);
+ template<class T>
+ 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>
+ Lit subset1(const T1& A, const T2& B);
+ bool subsetAbst(uint32_t A, uint32_t B);
+
+ //binary clause-subsumption
+ struct BinSorter {
+ 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
+ {
+ 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();
+
+ //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
+ bool handleClBinTouched();
+
+ void subsume1(Clause& ps);
+ bool subsume1(vec<Lit>& ps, const bool wasLearnt);
+ void strenghten(ClauseSimp& c, const Lit toRemoveLit);
+ bool cleanClause(Clause& ps);
+ bool cleanClause(vec<Lit>& ps) const;
+ void handleSize1Clause(const Lit lit);
+
+ /*bool subsWNonExitsBinsFullFull();
+ bool subsWNonExistBinsFull();
+ bool subsWNonExistBins(const Lit& lit, OnlyNonLearntBins* OnlyNonLearntBins);
+ uint64_t extraTimeNonExist;
+ bool subsNonExistentFinish;
+ vec<Lit> toVisit;
+ vec<char> toVisitAll;*/
+
+ //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;
+ }
+ };
+ 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);
+ uint32_t numNonLearntBins(const Lit lit) const;
+ bool maybeEliminate(Var x);
+ 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);
+ bool eliminateVars();
+ void fillClAndBin(vec<ClAndBin>& all, vec<ClauseSimp>& cs, const Lit lit);
+
+ //Subsume with Nonexistent Bins
+ struct BinSorter2 {
+ 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;
+ };
+ };
+ void subsume0BIN(const Lit lit, const vec<char>& lits, const uint32_t abst);
+ uint32_t doneNum;
+
+ //Blocked clause elimination
+ class VarOcc {
+ public:
+ VarOcc(const Var& v, const uint32_t num) :
+ var(v)
+ , occurnum(num)
+ {}
+ Var var;
+ uint32_t occurnum;
+ };
+ struct MyComp {
+ bool operator() (const VarOcc& l1, const VarOcc& l2) const {
+ return l1.occurnum > l2.occurnum;
+ }
+ };
+ void blockedClauseRemoval();
+ template<class T>
+ bool allTautology(const T& ps, const Lit lit);
+ uint32_t numblockedClauseRemoved;
+ bool tryOneSetting(const Lit lit);
+ priority_queue<VarOcc, vector<VarOcc>, MyComp> touchedBlockedVars;
+ vec<char> touchedBlockedVarsBool;
+ void touchBlockedVar(const Var x);
+ void blockedClauseElimAll(const Lit lit);
+
+
+ //validity checking
+ 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
+};
+
+template <class T, class T2>
+void maybeRemove(vec<T>& ws, const T2& elem)
+{
+ if (ws.size() > 0)
+ removeW(ws, elem);
+}
+
+/**
+@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]) {
+ touchedBlockedVars.push(VarOcc(x, occur[Lit(x, false).toInt()].size()*occur[Lit(x, true).toInt()].size()));
+ touchedBlockedVarsBool[x] = 1;
+ }
+}
+
+/**
+@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);
+}
+
+//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>
+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()]) {
+ 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 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);
+ touchedVars .addOne(solver.nVars()-1);
+ 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);
+}
+
+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
+{
+ return var_elimed;
+}
+
+inline uint32_t Subsumer::getNumElimed() const
+{
+ return numElimed;
+}
+
+inline double Subsumer::getTotalTime() const
+{
+ return totalTime;
+}
+
+}
+
+#endif //SIMPLIFIER_H
diff --git a/src/prop/cryptominisat/Solver/UselessBinRemover.cpp b/src/prop/cryptominisat/Solver/UselessBinRemover.cpp
new file mode 100644
index 000000000..1d848116e
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/UselessBinRemover.cpp
@@ -0,0 +1,228 @@
+/***************************************************************************
+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 <iomanip>
+#include "UselessBinRemover.h"
+#include "VarReplacer.h"
+#include "ClauseCleaner.h"
+#include "time_mem.h"
+
+//#define VERBOSE_DEBUG
+
+using namespace CMSat;
+
+UselessBinRemover::UselessBinRemover(Solver& _solver) :
+ solver(_solver)
+{
+}
+
+/**
+@brief Time limiting
+*/
+#define MAX_REMOVE_BIN_FULL_PROPS 20000000
+/**
+@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"
+*/
+bool UselessBinRemover::removeUslessBinFull()
+{
+ double myTime = cpuTime();
+ toDeleteSet.clear();
+ toDeleteSet.growTo(solver.nVars()*2, 0);
+ uint32_t origHeapSize = solver.order_heap.size();
+ uint64_t origProps = solver.propagations;
+ bool fixed = false;
+ 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++) {
+ Var var = solver.order_heap[(i+startFrom)%solver.order_heap.size()];
+ if (solver.propagations - origProps + extraTime > MAX_REMOVE_BIN_FULL_PROPS) break;
+ if (solver.assigns[var] != l_Undef || !solver.decision_var[var]) continue;
+
+ Lit lit(var, true);
+ if (!removeUselessBinaries(lit)) {
+ fixed = true;
+ solver.cancelUntilLight();
+ solver.uncheckedEnqueue(~lit);
+ solver.ok = (solver.propagate<false>().isNULL());
+ if (!solver.ok) return false;
+ continue;
+ }
+
+ lit = ~lit;
+ if (!removeUselessBinaries(lit)) {
+ fixed = true;
+ solver.cancelUntilLight();
+ solver.uncheckedEnqueue(~lit);
+ solver.ok = (solver.propagate<false>().isNULL());
+ if (!solver.ok) return false;
+ continue;
+ }
+ }
+
+ if (fixed) solver.order_heap.filter(Solver::VarFilter(solver));
+
+ if (solver.conf.verbosity >= 1) {
+ std::cout
+ << "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::endl;
+ }
+
+ return true;
+}
+
+/**
+@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.
+*/
+bool UselessBinRemover::removeUselessBinaries(const Lit lit)
+{
+ solver.newDecisionLevel();
+ solver.uncheckedEnqueueLight(lit);
+ //Propagate only one hop
+ failed = !solver.propagateBinOneLevel();
+ if (failed) return false;
+ bool ret = true;
+
+ oneHopAway.clear();
+ assert(solver.decisionLevel() > 0);
+ int c;
+ if (solver.trail.size()-solver.trail_lim[0] == 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];
+ toDeleteSet[x.toInt()] = true;
+ oneHopAway.push(x);
+ 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);
+
+ 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'
+ if (toDeleteSet[oneHopAway[i].toInt()]) {
+ if (!fillBinImpliesMinusLast(lit, oneHopAway[i], wrong)) {
+ ret = false;
+ goto end;
+ }
+ }
+ }
+
+ for (uint32_t i = 0; i < wrong.size(); i++) {
+ removeBin(~lit, wrong[i]);
+ }
+
+ end:
+ for(uint32_t i = 0; i < oneHopAway.size(); i++) {
+ toDeleteSet[oneHopAway[i].toInt()] = false;
+ }
+
+ return ret;
+}
+
+/**
+@brief Removes a binary clause (lit1 V lit2)
+
+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 << " " << lit2 << std::endl;
+ #endif //VERBOSE_DEBUG
+
+ 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;
+}
+
+/**
+@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
+*/
+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 = !solver.propagateBinExcept(origLit);
+ if (failed) return false;
+
+ assert(solver.decisionLevel() > 0);
+ int c;
+ 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];
+ if (toDeleteSet[x.toInt()]) {
+ wrong.push(x);
+ toDeleteSet[x.toInt()] = false;
+ };
+ 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;
+}
diff --git a/src/prop/cryptominisat/Solver/UselessBinRemover.h b/src/prop/cryptominisat/Solver/UselessBinRemover.h
new file mode 100644
index 000000000..37944b431
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/UselessBinRemover.h
@@ -0,0 +1,85 @@
+/***********************************************************************************
+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 USELESSBINREMOVER_H
+#define USELESSBINREMOVER_H
+
+#include "Vec.h"
+#include "Solver.h"
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+namespace CMSat {
+
+/**
+@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);
+ bool removeUslessBinFull();
+
+ private:
+ bool failed; ///<Has the previous propagation failed? (=conflict)
+ uint32_t extraTime; ///<Time that cannot be meausured in bogoprops (~propagation time)
+
+ //Remove useless binaries
+ bool fillBinImpliesMinusLast(const Lit origLit, const Lit lit, vec<Lit>& wrong);
+ 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; ///<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; ///<The solver class e want to remove useless binary clauses from
+};
+
+}
+
+#endif //USELESSBINREMOVER_H
diff --git a/src/prop/cryptominisat/Solver/VarReplacer.cpp b/src/prop/cryptominisat/Solver/VarReplacer.cpp
new file mode 100644
index 000000000..e89e66c51
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/VarReplacer.cpp
@@ -0,0 +1,731 @@
+/*****************************************************************************
+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 "VarReplacer.h"
+#include <iostream>
+#include <iomanip>
+#include <set>
+
+#include "ClauseCleaner.h"
+#include "time_mem.h"
+#include "DataSync.h"
+
+//#define VERBOSE_DEBUG
+//#define DEBUG_REPLACER
+//#define REPLACE_STATISTICS
+//#define DEBUG_BIN_REPLACER
+
+using namespace CMSat;
+
+VarReplacer::VarReplacer(Solver& _solver) :
+ replacedLits(0)
+ , replacedVars(0)
+ , lastReplacedVars(0)
+ , solver(_solver)
+{
+}
+
+VarReplacer::~VarReplacer()
+{
+}
+
+/**
+@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
+*/
+bool VarReplacer::performReplaceInternal()
+{
+ #ifdef VERBOSE_DEBUG
+ cout << "PerformReplacInternal started." << endl;
+ //solver.printAllClauses();
+ #endif
+ double time = cpuTime();
+
+ #ifdef REPLACE_STATISTICS
+ 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;
+ #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
+ {
+ 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 << endl;
+ }
+ }
+ #endif
+
+ Var var = 0;
+ const vec<char>& removedVars = solver.xorSubsumer->getVarElimed();
+ const vec<char>& removedVars3 = solver.subsumer->getVarElimed();
+ for (vector<Lit>::const_iterator it = table.begin(); it != table.end(); it++, var++) {
+ if (it->var() == var
+ || removedVars[it->var()]
+ || 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(!removedVars3[var]);
+
+ uint32_t& activity1 = solver.activity[var];
+ uint32_t& activity2 = solver.activity[it->var()];
+ if (wasDecisionVar && activity1 > activity2) {
+ activity2 = activity1;
+ solver.order_heap.update(it->var());
+ solver.polarity[it->var()] = ((bool)solver.polarity[var]) ^ it->sign();
+ }
+
+ activity1 = 0.0;
+ solver.order_heap.update(var);
+ }
+ assert(solver.order_heap.heapProperty());
+
+ uint32_t thisTimeReplaced = replacedVars -lastReplacedVars;
+ lastReplacedVars = replacedVars;
+
+ solver.testAllClauseAttach();
+ 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:
+ assert(solver.qhead == solver.trail.size() || !solver.ok);
+
+ if (solver.conf.verbosity >= 3) {
+ 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
+*/
+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());
+ 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 {
+ #ifdef SILENT_DEBUG
+ uint32_t numUndef = 0;
+ for (uint32_t i = 0; i < c.size(); i++) {
+ if (solver.value(c[i]) == l_Undef) numUndef++;
+ }
+ assert(numUndef >= 2 || numUndef == 0);
+ #endif
+ *a++ = *r;
+ }
+ }
+ cs.shrink(r-a);
+
+ return solver.ok;
+}
+
+/**
+@brief Helper function for replace_set()
+*/
+bool VarReplacer::handleUpdatedClause(XorClause& c, const Var origVar1, const Var origVar2)
+{
+ uint32_t origSize = c.size();
+ std::sort(c.getData(), c.getDataEnd());
+ Lit p;
+ uint32_t i, j;
+ for (i = j = 0, p = lit_Undef; i != c.size(); i++) {
+ if (c[i].var() == p.var()) {
+ //added, but easily removed
+ j--;
+ p = lit_Undef;
+ if (!solver.assigns[c[i].var()].isUndef())
+ c.invert(solver.assigns[c[i].var()].getBool());
+ } 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 xorEqualFalse instead of adding
+ }
+ c.shrink(i - j);
+
+ //Even if i==j, the clause *has* changed
+ c.setChanged();
+
+ #ifdef VERBOSE_DEBUG
+ cout << "xor-clause after replacing: ";
+ c.plainPrint();
+ #endif
+
+ switch (c.size()) {
+ case 0:
+ solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
+ if (!c.xorEqualFalse()) {
+ solver.ok = false;
+ }
+ return true;
+ case 1:
+ solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
+ solver.uncheckedEnqueue(Lit(c[0].var(), c.xorEqualFalse()));
+ solver.ok = (solver.propagate<false>().isNULL());
+ return true;
+ case 2: {
+ solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
+ c[0] = c[0].unsign() ^ c.xorEqualFalse();
+ c[1] = c[1].unsign();
+ addBinaryXorClause(c[0], c[1]);
+ return true;
+ }
+ default:
+ solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
+ solver.attachClause(c);
+ return false;
+ }
+
+ assert(false);
+ return false;
+}
+
+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;
+
+ vec<Watched>::iterator i = ws.getData();
+ vec<Watched>::iterator j = i;
+ for (vec<Watched>::iterator 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();
+ 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<false>().isNULL());
+ return solver.ok;
+}
+
+/**
+@brief Replaces variables in normal clauses
+*/
+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();
+ replacedLits++;
+ }
+ }
+
+ 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 {
+ *a++ = *r;
+ }
+ }
+ cs.shrink(r-a);
+
+ return solver.ok;
+}
+
+/**
+@brief Helper function for replace_set()
+*/
+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 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;
+ break;
+ }
+ else if (solver.value(c[i]) != l_False && c[i] != p)
+ c[j++] = p = c[i];
+ }
+ c.shrink(i - j);
+ c.setChanged();
+
+ 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.ok = false;
+ return true;
+ case 1 :
+ solver.uncheckedEnqueue(c[0]);
+ solver.ok = (solver.propagate<false>().isNULL());
+ return true;
+ case 2:
+ solver.attachBinClause(c[0], c[1], c.learnt());
+ solver.numNewBin++;
+ solver.dataSync->signalNewBinClause(c);
+ return true;
+ default:
+ solver.attachClause(c);
+ return false;
+ }
+
+ assert(false);
+ return false;
+}
+
+/**
+@brief Returns variables that have been replaced
+*/
+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
+ 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);
+ solver.uncheckedEnqueue(Lit(i, val ^ it->sign()));
+ } else {
+ assert(solver.assigns[i].getBool() == (solver.assigns[it->var()].getBool() ^ it->sign()));
+ }
+ }
+ solver.ok = (solver.propagate<false>().isNULL());
+ assert(solver.ok);
+ }
+}
+
+/**
+@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;
+ 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));
+ solver2.addClause(tmpClause);
+ assert(solver2.ok);
+ }
+ }
+}
+
+/**
+@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>
+bool VarReplacer::replace(T& ps, const bool xorEqualFalse, const bool addBinAsLearnt, const bool addToWatchLists)
+{
+ #ifdef VERBOSE_DEBUG
+ 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
+
+ //Detect circle
+ 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;
+ }
+ 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<false>().isNULL());
+ return solver.ok;
+ }
+
+ #ifdef DEBUG_REPLACER
+ assert(val1 == l_Undef && val2 == l_Undef);
+ #endif //DEBUG_REPLACER
+
+ if (addToWatchLists)
+ addBinaryXorClause(lit1, lit2 ^ true, addBinAsLearnt);
+
+ 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;
+ }
+
+ //both have children
+ setAllThatPointsHereTo(lit1.var(), lit2 ^ lit1.sign()); //erases reverseTable[lit1.var()]
+ replacedVars++;
+ return true;
+}
+
+template bool VarReplacer::replace(vec<Lit>& ps, const bool xorEqualFalse, const bool addBinAsLearnt, const bool addToWatchLists);
+template bool VarReplacer::replace(XorClause& ps, const bool xorEqualFalse, const bool addBinAsLearnt, const bool addToWatchLists);
+
+/**
+@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 bool addBinAsLearnt)
+{
+ solver.attachBinClause(lit1, lit2, addBinAsLearnt);
+ solver.dataSync->signalNewBinClause(lit1, lit2);
+
+ lit1 ^= true;
+ lit2 ^= true;
+ solver.attachBinClause(lit1, lit2, addBinAsLearnt);
+ solver.dataSync->signalNewBinClause(lit1, lit2);
+}
+
+/**
+@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];
+ if (lit2.var() == lit.var()) {
+ if (lit2.sign() != lit.sign()) {
+ #ifdef VERBOSE_DEBUG
+ cout << "Inverted cycle in var-replacement -> UNSAT" << endl;
+ #endif
+ solver.ok = false;
+ }
+ return true;
+ }
+
+ lit2 = table[lit.var()];
+ if (lit2.var() == var) {
+ if (lit2.sign() != lit.sign()) {
+ #ifdef VERBOSE_DEBUG
+ cout << "Inverted cycle in var-replacement -> UNSAT" << endl;
+ #endif
+ solver.ok = false;
+ }
+ 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);
+ if (it != reverseTable.end()) {
+ for(vector<Var>::const_iterator it2 = it->second.begin(), end = it->second.end(); it2 != end; it2++) {
+ assert(table[*it2].var() == var);
+ if (lit.var() != *it2) {
+ table[*it2] = lit ^ table[*it2].sign();
+ reverseTable[lit.var()].push_back(*it2);
+ }
+ }
+ reverseTable.erase(it);
+ }
+ table[var] = lit;
+ reverseTable[lit.var()].push_back(var);
+}
+
+void VarReplacer::newVar()
+{
+ table.push_back(Lit(table.size(), false));
+ cannot_eliminate.push(false);
+}
diff --git a/src/prop/cryptominisat/Solver/VarReplacer.h b/src/prop/cryptominisat/Solver/VarReplacer.h
new file mode 100644
index 000000000..db79aa3fe
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/VarReplacer.h
@@ -0,0 +1,153 @@
+/***********************************************************************************
+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 VARREPLACER_H
+#define VARREPLACER_H
+
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#include <map>
+#include <vector>
+
+#include "Solver.h"
+#include "SolverTypes.h"
+#include "Clause.h"
+#include "Vec.h"
+
+namespace CMSat {
+
+using std::map;
+using std::vector;
+
+/**
+@brief Replaces variables with their anti/equivalents
+*/
+class VarReplacer
+{
+ public:
+ VarReplacer(Solver& solver);
+ ~VarReplacer();
+ bool performReplace(const bool always = false);
+ bool needsReplace();
+ template<class T>
+ bool replace(T& ps, const bool xorEqualFalse, const bool addBinAsLearnt = false, const bool addToWatchLists = true);
+
+ void extendModelPossible() const;
+ void extendModelImpossible(Solver& solver2) const;
+
+ uint32_t getNumReplacedLits() const;
+ uint32_t getNumReplacedVars() const;
+ uint32_t getNumLastReplacedVars() const;
+ uint32_t getNewToReplaceVars() const;
+ uint32_t getNumTrees() const;
+ vector<Var> getReplacingVars() const;
+ const vector<Lit>& getReplaceTable() const;
+ bool varHasBeenReplaced(const Var var) 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:
+ bool performReplaceInternal();
+
+ bool replace_set(vec<Clause*>& cs);
+ bool replaceBins();
+ bool replace_set(vec<XorClause*>& cs);
+ bool handleUpdatedClause(Clause& c, const Lit origLit1, const Lit origLit2, const Lit origLit3);
+ bool handleUpdatedClause(XorClause& c, const Var origVar1, const Var origVar2);
+ void addBinaryXorClause(Lit lit1, Lit lit2, const bool addBinAsLearnt = false);
+
+ void setAllThatPointsHereTo(const Var var, const Lit lit);
+ bool alreadyIn(const Var var, const Lit lit);
+
+ 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 bool VarReplacer::performReplace(const bool always)
+{
+ //uint32_t limit = std::min((uint32_t)((double)solver.order_heap.size()*PERCENTAGEPERFORMREPLACE), FIXCLEANREPLACE);
+ uint32_t limit = (uint32_t)((double)solver.order_heap.size()*PERCENTAGEPERFORMREPLACE);
+ if ((always && getNewToReplaceVars() > 0) || getNewToReplaceVars() > limit)
+ return performReplaceInternal();
+
+ return true;
+}
+
+inline bool VarReplacer::needsReplace()
+{
+ uint32_t limit = (uint32_t)((double)solver.order_heap.size()*PERCENTAGEPERFORMREPLACE);
+ return (getNewToReplaceVars() > limit);
+}
+
+inline uint32_t VarReplacer::getNumReplacedLits() const
+{
+ return replacedLits;
+}
+
+inline uint32_t VarReplacer::getNumReplacedVars() const
+{
+ return replacedVars;
+}
+
+inline uint32_t VarReplacer::getNumLastReplacedVars() const
+{
+ return lastReplacedVars;
+}
+
+inline uint32_t VarReplacer::getNewToReplaceVars() const
+{
+ return replacedVars-lastReplacedVars;
+}
+
+inline const vector<Lit>& VarReplacer::getReplaceTable() const
+{
+ return table;
+}
+
+inline bool VarReplacer::varHasBeenReplaced(const Var var) const
+{
+ return table[var].var() != var;
+}
+
+inline bool VarReplacer::replacingVar(const Var var) const
+{
+ return (reverseTable.find(var) != reverseTable.end());
+}
+
+inline uint32_t VarReplacer::getNumTrees() const
+{
+ return reverseTable.size();
+}
+
+}
+
+#endif //VARREPLACER_H
diff --git a/src/prop/cryptominisat/Solver/Watched.h b/src/prop/cryptominisat/Solver/Watched.h
new file mode 100644
index 000000000..72075b56a
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/Watched.h
@@ -0,0 +1,278 @@
+/***************************************************************************
+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 <limits>
+#include "constants.h"
+
+namespace CMSat {
+
+/**
+@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);
+ }
+
+ Watched() :
+ data1 (std::numeric_limits<uint32_t>::max())
+ , data2(std::numeric_limits<uint32_t>::max())
+ {}
+
+ /**
+ @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();
+ }
+
+ bool isBinary() const
+ {
+ return ((data2&3) == 0);
+ }
+
+ bool isNonLearntBinary() const
+ {
+ return (data2 == 0);
+ }
+
+ bool isClause() const
+ {
+ return ((data2&3) == 1);
+ }
+
+ bool isXorClause() const
+ {
+ return ((data2&3) == 2);
+ }
+
+ bool isTriClause() const
+ {
+ return ((data2&3) == 3);
+ }
+
+ /**
+ @brief Get the sole other lit of the binary clause, or get lit2 of the tertiary clause
+ */
+ 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();
+ }
+
+ 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
+ */
+ Lit getOtherLit2() const
+ {
+ #ifdef DEBUG_WATCHED
+ assert(isTriClause());
+ #endif
+ return data2AsLit();
+ }
+
+ /**
+ @brief Get example literal (blocked lit) of a normal >3-long clause
+ */
+ 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)
+ */
+ ClauseOffset getNormOffset() const
+ {
+ #ifdef DEBUG_WATCHED
+ assert(isClause());
+ #endif
+ return (ClauseOffset)(data2 >> 2);
+ }
+
+ 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;
+ }
+
+ #ifdef DUMP_STATS_FULL
+ int glue;
+ #endif
+
+ private:
+ Lit data1AsLit() const
+ {
+ return (Lit::toLit(data1));
+ }
+
+ 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
diff --git a/src/prop/cryptominisat/Solver/XSet.h b/src/prop/cryptominisat/Solver/XSet.h
new file mode 100644
index 000000000..ab1cd00d1
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/XSet.h
@@ -0,0 +1,134 @@
+/**************************************************************************************************
+From: Solver.C -- (C) Niklas Een, Niklas Sorensson, 2004
+**************************************************************************************************/
+
+#ifndef XSET_H
+#define XSET_H
+
+#include "Vec.h"
+#include <limits>
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+namespace CMSat {
+
+class XorClause;
+
+template <class T>
+uint32_t calcXorAbstraction(const T& ps) {
+ uint32_t abstraction = 0;
+ for (uint32_t i = 0; i != ps.size(); i++)
+ abstraction |= 1 << (ps[i].var() & 31);
+ return abstraction;
+}
+
+//#pragma pack(push)
+//#pragma pack(1)
+class XorClauseSimp
+{
+ public:
+ XorClauseSimp(XorClause* c, const uint32_t _index) :
+ clause(c)
+ , index(_index)
+ {}
+
+ XorClause* clause;
+ uint32_t index;
+};
+//#pragma pack(pop)
+
+class XSet {
+ vec<uint32_t> where; // Map clause ID to position in 'which'.
+ vec<XorClauseSimp> which; // List of clauses (for fast iteration). May contain 'Clause_NULL'.
+ vec<uint32_t> free; // List of positions holding 'Clause_NULL'.
+
+ public:
+ //XorClauseSimp& operator [] (uint32_t index) { return which[index]; }
+ void reserve(uint32_t size) { where.reserve(size);}
+ uint32_t size(void) const { return which.size(); }
+ uint32_t nElems(void) const { return which.size() - free.size(); }
+
+ bool add(const XorClauseSimp& c) {
+ assert(c.clause != NULL);
+ where.growTo(c.index+1, std::numeric_limits<uint32_t>::max());
+ if (where[c.index] != std::numeric_limits<uint32_t>::max()) {
+ return true;
+ }
+ if (free.size() > 0){
+ where[c.index] = free.last();
+ which[free.last()] = c;
+ free.pop();
+ }else{
+ where[c.index] = which.size();
+ which.push(c);
+ }
+ return false;
+ }
+
+ bool exclude(const XorClauseSimp& c) {
+ assert(c.clause != NULL);
+ if (c.index >= where.size() || where[c.index] == std::numeric_limits<uint32_t>::max()) {
+ //not inside
+ return false;
+ }
+ free.push(where[c.index]);
+ which[where[c.index]].clause = NULL;
+ where[c.index] = std::numeric_limits<uint32_t>::max();
+ return true;
+ }
+
+ void clear(void) {
+ for (uint32_t i = 0; i < which.size(); i++) {
+ if (which[i].clause != NULL) {
+ where[which[i].index] = std::numeric_limits<uint32_t>::max();
+ }
+ }
+ which.clear();
+ free.clear();
+ }
+
+ class iterator
+ {
+ public:
+ iterator(XorClauseSimp* _it) :
+ it(_it)
+ {}
+
+ void operator++()
+ {
+ it++;
+ }
+
+ bool operator!=(const iterator& iter) const
+ {
+ return (it != iter.it);;
+ }
+
+ XorClauseSimp& operator*() {
+ return *it;
+ }
+
+ XorClauseSimp*& operator->() {
+ return it;
+ }
+ private:
+ XorClauseSimp* it;
+ };
+
+ iterator begin()
+ {
+ return iterator(which.getData());
+ }
+
+ iterator end()
+ {
+ return iterator(which.getData() + which.size());
+ }
+};
+
+#endif //XSET_H
+
+}
diff --git a/src/prop/cryptominisat/Solver/XorFinder.cpp b/src/prop/cryptominisat/Solver/XorFinder.cpp
new file mode 100644
index 000000000..1b82430e9
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/XorFinder.cpp
@@ -0,0 +1,462 @@
+/***********************************************************************************
+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 "XorFinder.h"
+
+#include <algorithm>
+#include <utility>
+#include <iostream>
+#include "Solver.h"
+#include "VarReplacer.h"
+#include "ClauseCleaner.h"
+#include "time_mem.h"
+
+//#define VERBOSE_DEBUG
+
+using namespace CMSat;
+using std::make_pair;
+
+XorFinder::XorFinder(Solver& _solver, vec<Clause*>& _cls) :
+ cls(_cls)
+ , solver(_solver)
+{
+}
+
+bool XorFinder::fullFindXors(const uint32_t minSize, const uint32_t maxSize)
+{
+ uint32_t sumLengths = 0;
+ double time = cpuTime();
+ foundXors = 0;
+ solver.clauseCleaner->cleanClauses(solver.clauses, ClauseCleaner::clauses);
+ 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());
+
+ for (Clause **it = cls.getData(), **end = cls.getDataEnd(); it != end; it ++) {
+ if (it+1 != end) __builtin_prefetch(*(it+1));
+ Clause& c = (**it);
+ 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);
+ }
+ }
+
+ 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;
+ }
+ table.push_back(make_pair(*it, i));
+ }
+ std::sort(table.begin(), table.end(), clause_sorter_primary());
+
+ if (!findXors(sumLengths)) goto end;
+ solver.ok = (solver.propagate<true>().isNULL());
+
+end:
+
+ if (solver.conf.verbosity >= 1 || (solver.conf.verbosity >= 1 && foundXors > 0)) {
+ printf("c Finding non-binary XORs: %5.2f s (found: %7d, avg size: %3.1f)\n", cpuTime()-time, foundXors, (double)sumLengths/(double)foundXors);
+ }
+
+ i = 0;
+ uint32_t j = 0;
+ uint32_t toSkip = 0;
+ for (uint32_t end = cls.size(); i != end; i++) {
+ if (toLeaveInPlace[i]) {
+ cls[j] = cls[i];
+ j++;
+ toSkip++;
+ continue;
+ }
+ if (!toRemove[table[i-toSkip].second]) {
+ cls[j] = table[i-toSkip].first;
+ j++;
+ }
+ }
+ cls.shrink(i-j);
+
+ return solver.ok;
+}
+
+
+/**
+@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.
+*/
+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;
+ bool impair;
+ while (getNextXor(begin, end, impair)) {
+ const Clause& c = *(begin->first);
+ lits.clear();
+ for (const Lit *it = &c[0], *cend = it+c.size() ; it != cend; it++) {
+ lits.push(Lit(it->var(), false));
+ }
+
+ #ifdef VERBOSE_DEBUG
+ cout << "- Found clauses:" << endl;
+ #endif
+
+ 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);
+ }
+ }
+
+ assert(lits.size() > 2);
+ XorClause* x = solver.addXorClauseInt(lits, impair);
+ 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;
+}
+
+/**
+@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();
+
+ while(begin != tableEnd && end != tableEnd) {
+ begin = end;
+ end++;
+ uint32_t size = (end == tableEnd ? 0:1);
+ while(end != tableEnd && clause_vareq(begin->first, end->first)) {
+ size++;
+ end++;
+ }
+ 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 (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
+{
+ 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 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 (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 (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++;
+ if (it2 == end) break;
+ assert(!sorter(*it2, *it));
+ }
+ }
+ #endif //DEBUG_XORFIND
+
+ //We now sort them according to literal content
+ std::sort(begin, end, clause_sorter_secondary());
+
+ 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;
+}
+
+/**
+@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);
+ numImpair += impair;
+ numPair += !impair;
+ }
+ it++;
+ it2++;
+ }
+}
+
+/**
+@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;
+ XorClause **i = solver.xorclauses.getData(), **j = i;
+ for (XorClause **end = solver.xorclauses.getDataEnd(); i != end; i++) {
+ if ((*i)->size() > 3) {
+ *j++ = *i;
+ continue;
+ }
+ added++;
+ if ((*i)->size() == 3) addXorAsNormal3(**i);
+ //if ((*i)->size() == 4) addXorAsNormal4(**i);
+ solver.removeClause(**i);
+ }
+ solver.xorclauses.shrink(i-j);
+ 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;
+ const bool inverted = c.xorEqualFalse();
+
+ for (uint32_t i = 0; i < c.size(); i++) {
+ vars.push(c[i].var());
+ }
+
+ vec<Lit> vars2;
+ vars2.growTo(3);
+ 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);
+ if (tmp) solver.clauses.push(tmp);
+
+ vars2.growTo(3);
+ 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);
+ if (tmp) solver.clauses.push(tmp);
+
+ vars2.growTo(3);
+ 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);
+ if (tmp) solver.clauses.push(tmp);
+
+ vars2.growTo(3);
+ vars2[0] = Lit(vars[0], false ^ inverted);
+ vars2[1] = Lit(vars[1], true ^ inverted);
+ vars2[2] = Lit(vars[2], true ^ inverted);
+ tmp = solver.addClauseInt(vars2);
+ 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.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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ if (tmp) solver.clauses.push(tmp);
+
+ vars2[0] = Lit(vars[0], true ^ inverted);
+ vars2[1] = Lit(vars[1], true ^ inverted);
+ vars2[2] = Lit(vars[2], true ^ inverted);
+ vars2[3] = Lit(vars[3], false ^ inverted);
+ tmp = solver.addClauseInt(vars2);
+ if (tmp) solver.clauses.push(tmp);
+}
diff --git a/src/prop/cryptominisat/Solver/XorFinder.h b/src/prop/cryptominisat/Solver/XorFinder.h
new file mode 100644
index 000000000..418dd00e3
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/XorFinder.h
@@ -0,0 +1,157 @@
+/***********************************************************************************
+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 XORFINDER_H
+#define XORFINDER_H
+
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#define DEBUG_XORFIND
+//#define DEBUG_XORFIND2
+
+#include "Clause.h"
+#include "VarReplacer.h"
+#include "ClauseCleaner.h"
+
+namespace CMSat {
+
+class Solver;
+
+using std::pair;
+
+/**
+@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);
+ bool fullFindXors(const uint32_t minSize, const uint32_t maxSize);
+ void addAllXorAsNorm();
+
+ private:
+ typedef vector<pair<Clause*, uint32_t> > ClauseTable;
+
+ bool findXors(uint32_t& sumLengths);
+ bool getNextXor(ClauseTable::iterator& begin, ClauseTable::iterator& end, bool& impair);
+
+ /**
+ @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*, 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 (uint32_t i = 0; i+1 < c1.size(); i++)
+ assert(c1[i].var() <= c1[i+1].var());
+
+ Clause& c2 = *c22.first;
+ 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 = 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*, 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 (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 (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 clause as normal clause
+ void addXorAsNormal3(XorClause& c);
+ void addXorAsNormal4(XorClause& c);
+
+ vec<Clause*>& cls;
+
+ 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, 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;
+};
+
+}
+
+#endif //XORFINDER_H
diff --git a/src/prop/cryptominisat/Solver/XorSubsumer.cpp b/src/prop/cryptominisat/Solver/XorSubsumer.cpp
new file mode 100644
index 000000000..f6776428e
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/XorSubsumer.cpp
@@ -0,0 +1,622 @@
+/*****************************************************************************
+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"
+#include "ClauseCleaner.h"
+#include "time_mem.h"
+#include "assert.h"
+#include <iomanip>
+#include "VarReplacer.h"
+
+//#define VERBOSE_DEBUG
+#ifdef VERBOSE_DEBUG
+#define VERBOSE_DEBUGSUBSUME0
+#define BIT_MORE_VERBOSITY
+#endif
+
+using namespace CMSat;
+
+XorSubsumer::XorSubsumer(Solver& s):
+ solver(s)
+ , totalTime(0.0)
+ , numElimed(0)
+ , localSubstituteUseful(0)
+{
+}
+
+// Will put NULL in 'cs' if clause removed.
+void XorSubsumer::subsume0(XorClauseSimp ps)
+{
+ #ifdef VERBOSE_DEBUGSUBSUME0
+ cout << "subsume0 orig clause:";
+ ps.clause->plainPrint();
+ #endif
+
+ vec<Lit> unmatchedPart;
+ vec<XorClauseSimp> subs;
+
+ findSubsumed(*ps.clause, subs);
+ for (uint32_t i = 0; i < subs.size(); i++){
+ XorClause* tmp = subs[i].clause;
+ findUnMatched(*ps.clause, *tmp, unmatchedPart);
+ if (unmatchedPart.size() == 0) {
+ #ifdef VERBOSE_DEBUGSUBSUME0
+ cout << "subsume0 removing:";
+ subs[i].clause->plainPrint();
+ #endif
+ clauses_subsumed++;
+ assert(tmp->size() == ps.clause->size());
+ if (ps.clause->xorEqualFalse() == tmp->xorEqualFalse()) {
+ unlinkClause(subs[i]);
+ } else {
+ solver.ok = false;
+ return;
+ }
+ } else {
+ assert(unmatchedPart.size() > 0);
+ clauses_cut++;
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Cutting xor-clause:";
+ subs[i].clause->plainPrint();
+ #endif //VERBOSE_DEBUG
+ XorClause *c = solver.addXorClauseInt(unmatchedPart, tmp->xorEqualFalse() ^ !ps.clause->xorEqualFalse());
+ if (c != NULL)
+ linkInClause(*c);
+ unlinkClause(subs[i]);
+ if (!solver.ok) return;
+ }
+ unmatchedPart.clear();
+ }
+}
+
+template<class T>
+void XorSubsumer::findUnMatched(const T& A, const T& B, vec<Lit>& unmatchedPart)
+{
+ for (uint32_t i = 0; i != B.size(); i++)
+ seen_tmp[B[i].var()] = 1;
+ for (uint32_t i = 0; i != A.size(); i++)
+ seen_tmp[A[i].var()] = 0;
+ for (uint32_t i = 0; i != B.size(); i++) {
+ if (seen_tmp[B[i].var()] == 1) {
+ unmatchedPart.push(Lit(B[i].var(), false));
+ seen_tmp[B[i].var()] = 0;
+ }
+ }
+}
+
+void XorSubsumer::unlinkClause(XorClauseSimp c, 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) {
+ 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;
+}
+
+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;
+}
+
+void XorSubsumer::unlinkModifiedClauseNoDetachNoNULL(vec<Lit>& origClause, XorClauseSimp c)
+{
+ for (uint32_t i = 0; i < origClause.size(); i++) {
+ removeW(occur[origClause[i].var()], c.clause);
+ }
+}
+
+XorClauseSimp XorSubsumer::linkInClause(XorClause& cl)
+{
+ XorClauseSimp c(&cl, clauseID++);
+ clauses.push(c);
+ for (uint32_t i = 0; i < cl.size(); i++) {
+ occur[cl[i].var()].push(c);
+ }
+
+ return c;
+}
+
+void XorSubsumer::linkInAlreadyClause(XorClauseSimp& c)
+{
+ XorClause& cl = *c.clause;
+
+ for (uint32_t i = 0; i < c.clause->size(); i++) {
+ occur[cl[i].var()].push(c);
+ }
+}
+
+void XorSubsumer::addFromSolver(vec<XorClause*>& cs)
+{
+ clauseID = 0;
+ clauses.clear();
+ XorClause **i = cs.getData();
+ for (XorClause **end = i + cs.size(); i != end; i++) {
+ if (i+1 != end) __builtin_prefetch(*(i+1));
+
+ linkInClause(**i);
+ }
+ cs.clear();
+ cs.push(NULL); //HACK --to force xor-propagation
+}
+
+void XorSubsumer::addBackToSolver()
+{
+ solver.xorclauses.pop(); //HACK --to force xor-propagation
+ for (uint32_t i = 0; i < clauses.size(); i++) {
+ if (clauses[i].clause != NULL) {
+ solver.xorclauses.push(clauses[i].clause);
+ clauses[i].clause->unsetChanged();
+ }
+ }
+ for (Var var = 0; var < solver.nVars(); var++) {
+ occur[var].clear();
+ }
+ clauses.clear();
+ clauseID = 0;
+}
+
+void XorSubsumer::fillCannotEliminate()
+{
+ std::fill(cannot_eliminate.getData(), cannot_eliminate.getDataEnd(), false);
+ for (uint32_t i = 0; i < solver.clauses.size(); i++)
+ addToCannotEliminate(solver.clauses[i]);
+
+ 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 (vec<Watched>::const_iterator 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++)
+ if (cannot_eliminate[i])
+ tmpNum++;
+ std::cout << "Cannot eliminate num:" << tmpNum << std::endl;
+ #endif
+}
+
+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<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<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.lits.size());
+ std::copy(c.lits.begin(), c.lits.end(), tmp.getData());
+ solver2.addXorClause(tmp, c.xorEqualFalse);
+ assert(solver2.ok);
+ }
+ }
+}
+
+bool XorSubsumer::localSubstitute()
+{
+ vec<Lit> tmp;
+ for (Var var = 0; var < occur.size(); var++) {
+ vec<XorClauseSimp>& occ = occur[var];
+
+ if (occ.size() <= 1) continue;
+ for (uint32_t i = 0; i < occ.size(); i++) {
+ XorClause& c1 = *occ[i].clause;
+ for (uint32_t i2 = i+1; i2 < occ.size(); i2++) {
+ XorClause& c2 = *occ[i2].clause;
+ tmp.clear();
+ xorTwoClauses(c1, c2, tmp);
+ if (tmp.size() <= 2) {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Local substiuting. Clause1:"; c1.plainPrint();
+ std::cout << "Clause 2:"; c2.plainPrint();
+ #endif //VERBOSE_DEBUG
+ localSubstituteUseful++;
+ XorClause* ret = solver.addXorClauseInt(tmp, c1.xorEqualFalse() ^ !c2.xorEqualFalse());
+ release_assert(ret == NULL);
+ if (!solver.ok) {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "solver.ok is false after local substitution" << std::endl;
+ #endif //VERBOSE_DEBUG
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+template<class T>
+void XorSubsumer::xorTwoClauses(const T& c1, const T& c2, vec<Lit>& xored)
+{
+ for (uint32_t i = 0; i != c1.size(); i++)
+ seen_tmp[c1[i].var()] = 1;
+ for (uint32_t i = 0; i != c2.size(); i++)
+ seen_tmp[c2[i].var()] ^= 1;
+
+ for (uint32_t i = 0; i != c1.size(); i++) {
+ if (seen_tmp[c1[i].var()] == 1) {
+ xored.push(Lit(c1[i].var(), false));
+ seen_tmp[c1[i].var()] = 0;
+ }
+ }
+ for (uint32_t i = 0; i != c2.size(); i++) {
+ if (seen_tmp[c2[i].var()] == 1) {
+ xored.push(Lit(c2[i].var(), false));
+ seen_tmp[c2[i].var()] = 0;
+ }
+ }
+}
+
+void XorSubsumer::removeWrong(vec<Clause*>& cs)
+{
+ Clause **i = cs.getData();
+ Clause **j = i;
+ for (Clause **end = i + cs.size(); i != end; i++) {
+ Clause& c = **i;
+ if (!c.learnt()) {
+ *j++ = *i;
+ continue;
+ }
+ bool remove = false;
+ for (Lit *l = c.getData(), *end2 = l+c.size(); l != end2; l++) {
+ if (var_elimed[l->var()]) {
+ remove = true;
+ solver.detachClause(c);
+ solver.clauseAllocator.clauseFree(&c);
+ break;
+ }
+ }
+ if (!remove)
+ *j++ = *i;
+ }
+ 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;
+
+ vec<Watched>::iterator i = ws.getData();
+ vec<Watched>::iterator j = i;
+ for (vec<Watched>::iterator 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;
+}
+
+
+bool XorSubsumer::removeDependent()
+{
+ for (Var var = 0; var < occur.size(); var++) {
+ if (cannot_eliminate[var] || !solver.decision_var[var] || solver.assigns[var] != l_Undef) continue;
+ vec<XorClauseSimp>& occ = occur[var];
+
+ if (occ.size() == 1) {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Eliminating dependent var " << var + 1 << std::endl;
+ std::cout << "-> Removing dependent clause "; occ[0].clause->plainPrint();
+ #endif //VERBOSE_DEBUG
+ unlinkClause(occ[0], var);
+ solver.setDecisionVar(var, false);
+ var_elimed[var] = true;
+ numElimed++;
+ } else if (occ.size() == 2) {
+ vec<Lit> lits;
+ XorClause& c1 = *(occ[0].clause);
+ lits.growTo(c1.size());
+ std::copy(c1.getData(), c1.getDataEnd(), lits.getData());
+ 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.xorEqualFalse();
+ 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;
+ std::cout << "-> Removing xor clause "; occ[0].clause->plainPrint();
+ std::cout << "-> Removing xor clause "; occ[1].clause->plainPrint();
+ #endif //VERBOSE_DEBUG
+ XorClauseSimp toUnlink0 = occ[0];
+ XorClauseSimp toUnlink1 = occ[1];
+ unlinkClause(toUnlink0);
+ unlinkClause(toUnlink1, var);
+ solver.setDecisionVar(var, false);
+ var_elimed[var] = true;
+ numElimed++;
+
+ for (uint32_t i = 0; i < lits.size(); i++)
+ cannot_eliminate[lits[i].var()] = true;
+ XorClause* c = solver.addXorClauseInt(lits, inverted);
+ #ifdef VERBOSE_DEBUG
+ if (c != NULL) {
+ std::cout << "-> Added combined xor clause:"; c->plainPrint();
+ } else
+ std::cout << "-> Combined xor clause is NULL" << std::endl;
+ #endif
+ if (c != NULL) linkInClause(*c);
+ if (!solver.ok) {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "solver.ok is false after var-elim through xor" << std::endl;
+ #endif //VERBOSE_DEBUG
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+inline void XorSubsumer::addToCannotEliminate(Clause* it)
+{
+ const Clause& c = *it;
+ for (uint32_t i2 = 0; i2 < c.size(); i2++)
+ cannot_eliminate[c[i2].var()] = true;
+}
+
+bool XorSubsumer::unEliminate(const Var var)
+{
+ assert(var_elimed[var]);
+ 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
+ //had it not been decision var
+ solver.setDecisionVar(var, true);
+ 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<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;
+}
+
+
+bool XorSubsumer::simplifyBySubsumption()
+{
+ double myTime = cpuTime();
+ uint32_t origTrailSize = solver.trail.size();
+ clauses_subsumed = 0;
+ clauses_cut = 0;
+ clauseID = 0;
+ uint32_t lastNumElimed = numElimed;
+ localSubstituteUseful = 0;
+ 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;
+
+ clauses.clear();
+ clauses.reserve(solver.xorclauses.size());
+ addFromSolver(solver.xorclauses);
+ #ifdef BIT_MORE_VERBOSITY
+ std::cout << "c time to link in:" << cpuTime()-myTime << std::endl;
+ #endif
+
+ origNClauses = clauses.size();
+
+ if (!solver.ok) return false;
+ #ifdef VERBOSE_DEBUG
+ std::cout << "c clauses:" << clauses.size() << std::endl;
+ #endif
+
+ bool replaced = true;
+ bool propagated = false;
+ while (replaced || propagated) {
+ replaced = propagated = false;
+ for (uint32_t i = 0; i < clauses.size(); i++) {
+ if (clauses[i].clause != NULL) {
+ subsume0(clauses[i]);
+ if (!solver.ok) {
+ addBackToSolver();
+ return false;
+ }
+ }
+ }
+
+ propagated = (solver.qhead != solver.trail.size());
+ solver.ok = (solver.propagate<false>().isNULL());
+ if (!solver.ok) {
+ return false;
+ }
+ if (!solver.ok) return false;
+
+ fillCannotEliminate();
+ if (solver.conf.doConglXors && !removeDependent()) {
+ addBackToSolver();
+ return false;
+ }
+
+ if (solver.conf.doHeuleProcess && !localSubstitute()) {
+ addBackToSolver();
+ return false;
+ }
+
+ /*if (solver.doReplace && solver.varReplacer->needsReplace()) {
+ addBackToSolver();
+ while (solver.doReplace && solver.varReplacer->needsReplace()) {
+ replaced = true;
+ if (!solver.varReplacer->performReplace())
+ return false;
+ }
+ addFromSolver(solver.xorclauses);
+ }*/
+ }
+
+ solver.order_heap.filter(Solver::VarFilter(solver));
+
+ removeWrong(solver.learnts);
+ removeWrongBins();
+ addBackToSolver();
+ 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::endl;
+ }
+ totalTime += cpuTime() - myTime;
+
+ solver.testAllClauseAttach();
+ return true;
+}
+
+void XorSubsumer::findSubsumed(XorClause& ps, vec<XorClauseSimp>& out_subsumed)
+{
+ #ifdef VERBOSE_DEBUGSUBSUME0
+ cout << "findSubsumed: ";
+ for (uint32_t i = 0; i < ps.size(); i++) {
+ if (ps[i].sign()) printf("-");
+ printf("%d ", ps[i].var() + 1);
+ }
+ printf("0\n");
+ #endif
+
+ uint32_t min_i = 0;
+ for (uint32_t i = 1; i < ps.size(); i++){
+ if (occur[ps[i].var()].size() < occur[ps[min_i].var()].size())
+ min_i = i;
+ }
+
+ vec<XorClauseSimp>& cs = occur[ps[min_i].var()];
+ for (XorClauseSimp *it = cs.getData(), *end = it + cs.size(); it != end; it++){
+ if (it+1 != end) __builtin_prefetch((it+1)->clause);
+
+ 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
+ cout << "subsumed: ";
+ it->clause->plainPrint();
+ #endif
+ }
+ }
+}
+
+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;
+}
+
+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);
+ }
+ }
+}
diff --git a/src/prop/cryptominisat/Solver/XorSubsumer.h b/src/prop/cryptominisat/Solver/XorSubsumer.h
new file mode 100644
index 000000000..67f9c6dd4
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/XorSubsumer.h
@@ -0,0 +1,185 @@
+/*****************************************************************************
+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
+
+#include "Solver.h"
+#include "Vec.h"
+#include "XSet.h"
+
+namespace CMSat {
+
+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);
+ bool simplifyBySubsumption();
+ void unlinkModifiedClause(vec<Lit>& origClause, XorClauseSimp c);
+ void unlinkModifiedClauseNoDetachNoNULL(vec<Lit>& origClause, XorClauseSimp c);
+ void unlinkClause(XorClauseSimp cc, Var elim = var_Undef);
+ XorClauseSimp linkInClause(XorClause& cl);
+ void linkInAlreadyClause(XorClauseSimp& c);
+ void newVar();
+ void extendModel(Solver& solver2);
+
+ uint32_t getNumElimed() const;
+ const vec<char>& getVarElimed() const;
+ bool unEliminate(const Var var);
+ bool checkElimedUnassigned() 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);
+ void subsume0(XorClauseSimp ps);
+ template<class T1, class T2>
+ bool subset(const T1& A, const T2& B);
+ bool subsetAbst(uint32_t A, uint32_t B);
+ template<class T>
+ void findUnMatched(const T& A, const T& B, vec<Lit>& unmatchedPart);
+
+ //helper
+ void testAllClauseAttach() const;
+
+ //dependent removal
+ 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<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);
+ bool localSubstitute();
+ uint32_t localSubstituteUseful;
+
+ uint32_t clauses_subsumed;
+ uint32_t clauses_cut;
+ uint32_t origNClauses;
+ uint32_t clauseID;
+};
+
+inline bool XorSubsumer::subsetAbst(uint32_t A, uint32_t B)
+{
+ return !(A & ~B);
+}
+
+// Assumes 'seen' is cleared (will leave it cleared)
+template<class T1, class T2>
+bool XorSubsumer::subset(const T1& A, const T2& B)
+{
+ for (uint32_t i = 0; i != B.size(); i++)
+ seen_tmp[B[i].var()] = 1;
+ for (uint32_t i = 0; i != A.size(); i++) {
+ if (!seen_tmp[A[i].var()]) {
+ for (uint32_t i = 0; i != B.size(); i++)
+ seen_tmp[B[i].var()] = 0;
+ return false;
+ }
+ }
+ for (uint32_t i = 0; i != B.size(); i++)
+ seen_tmp[B[i].var()] = 0;
+ return true;
+}
+
+inline void XorSubsumer::newVar()
+{
+ occur .push();
+ seen_tmp .push(0);
+ cannot_eliminate.push(0);
+ var_elimed.push(0);
+}
+
+inline const vec<char>& XorSubsumer::getVarElimed() const
+{
+ return var_elimed;
+}
+
+inline uint32_t XorSubsumer::getNumElimed() const
+{
+ return numElimed;
+}
+
+inline double XorSubsumer::getTotalTime() const
+{
+ return totalTime;
+}
+
+inline const map<Var, vector<XorSubsumer::XorElimedClause> >& XorSubsumer::getElimedOutVar() const
+{
+ return elimedOutVar;
+}
+
+}
+
+#endif //XORSIMPLIFIER_H
diff --git a/src/prop/cryptominisat/Solver/constants.h b/src/prop/cryptominisat/Solver/constants.h
new file mode 100644
index 000000000..e8f63bde2
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/constants.h
@@ -0,0 +1,137 @@
+/****************************************************************************************[Solver.h]
+MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+glucose -- Gilles Audemard, Laurent Simon (2008)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#define release_assert(a) \
+ do { \
+ if (!(a)) {\
+ fprintf(stderr, "*** ASSERTION FAILURE in %s() [%s:%d]: %s\n", \
+ __FUNCTION__, __FILE__, __LINE__, #a); \
+ abort(); \
+ } \
+ } while (0)
+
+///////////////////
+// Settings (magic constants)
+///////////////////
+
+//#define DUMP_STATS_FULL
+//#define DUMP_STATS
+
+//#define DEBUG_UNCHECKEDENQUEUE_LEVEL0
+
+#ifdef DUMP_STATS_FULL
+#define DUMP_STATS
+#endif //DUMP_STATS_FULL
+
+//Parameters for learnt-clause cleaning
+#define RATIOREMOVECLAUSES 1.0/2.0
+#define NBCLAUSESBEFOREREDUCE 20000
+
+#define FIXCLEANREPLACE 30U
+#define PERCENTAGEPERFORMREPLACE 0.003
+#define PERCENTAGECLEANCLAUSES 0.01
+
+//Parameters for xor-finding (binary and non-binary)
+#define MAX_CLAUSENUM_XORFIND 1500000
+#define BINARY_TO_XOR_APPROX 6.0
+
+#define UPDATE_TRANSOTFSSR_CACHE 200000
+
+//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
+
+//Gaussian elimination parameters
+#define MIN_GAUSS_XOR_CLAUSES 5
+#define MAX_GAUSS_XOR_CLAUSES 30000
+
+//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
+
+#ifndef DUMP_STATS_FULL
+#define DYNAMICALLY_UPDATE_GLUE
+#endif //DUMP_STATS_FULL
+
+//#define ENABLE_UNWIND_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_USELESS_LEARNT_BIN_REMOVAL
+#endif
+
+//#define MORE_DEBUG
+
+#ifdef MORE_DEBUG
+#define DEBUG_ATTACH_FULL
+#define DEBUG_FAILEDLIT
+#define DEBUG_HYPERBIN
+#endif
+
+///////////////////
+// For Automake tools
+///////////////////
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif //HAVE_CONFIG_H
+
+#ifdef _MSC_VER
+#define __builtin_prefetch
+#endif //_MSC_VER
diff --git a/src/prop/cryptominisat/Solver/msvc/stdint.h b/src/prop/cryptominisat/Solver/msvc/stdint.h
new file mode 100644
index 000000000..c8399d3de
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/msvc/stdint.h
@@ -0,0 +1,246 @@
+// ISO C9x compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+// Copyright (c) 2006-2008 Alexander Chemeris
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// 3. The name of the author may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include <limits.h>
+
+// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
+// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler give many errors like this:
+// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+#ifdef __cplusplus
+extern "C" {
+#endif
+# include <wchar.h>
+#ifdef __cplusplus
+}
+#endif
+
+// Define _W64 macros to mark types changing their size, like intptr_t.
+#ifndef _W64
+# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
+# define _W64 __w64
+# else
+# define _W64
+# endif
+#endif
+
+
+// 7.18.1 Integer types
+
+// 7.18.1.1 Exact-width integer types
+
+// Visual Studio 6 and Embedded Visual C++ 4 doesn't
+// realize that, e.g. char has the same size as __int8
+// so we give up on __intX for them.
+#if (_MSC_VER < 1300)
+ typedef signed char int8_t;
+ typedef signed short int16_t;
+ typedef signed int int32_t;
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+#else
+ typedef signed __int8 int8_t;
+ typedef signed __int16 int16_t;
+ typedef signed __int32 int32_t;
+ typedef unsigned __int8 uint8_t;
+ typedef unsigned __int16 uint16_t;
+ typedef unsigned __int32 uint32_t;
+#endif
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+
+
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t int_least8_t;
+typedef int16_t int_least16_t;
+typedef int32_t int_least32_t;
+typedef int64_t int_least64_t;
+typedef uint8_t uint_least8_t;
+typedef uint16_t uint_least16_t;
+typedef uint32_t uint_least32_t;
+typedef uint64_t uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t int_fast8_t;
+typedef int16_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef int64_t int_fast64_t;
+typedef uint8_t uint_fast8_t;
+typedef uint16_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+typedef uint64_t uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+#ifdef _WIN64 // [
+ typedef signed __int64 intptr_t;
+ typedef unsigned __int64 uintptr_t;
+#else // _WIN64 ][
+ typedef _W64 signed int intptr_t;
+ typedef _W64 unsigned int uintptr_t;
+#endif // _WIN64 ]
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t intmax_t;
+typedef uint64_t uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN ((int8_t)_I8_MIN)
+#define INT8_MAX _I8_MAX
+#define INT16_MIN ((int16_t)_I16_MIN)
+#define INT16_MAX _I16_MAX
+#define INT32_MIN ((int32_t)_I32_MIN)
+#define INT32_MAX _I32_MAX
+#define INT64_MIN ((int64_t)_I64_MIN)
+#define INT64_MAX _I64_MAX
+#define UINT8_MAX _UI8_MAX
+#define UINT16_MAX _UI16_MAX
+#define UINT32_MAX _UI32_MAX
+#define UINT64_MAX _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST8_MAX INT8_MAX
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST16_MAX INT16_MAX
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST32_MAX INT32_MAX
+#define INT_LEAST64_MIN INT64_MIN
+#define INT_LEAST64_MAX INT64_MAX
+#define UINT_LEAST8_MAX UINT8_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN INT8_MIN
+#define INT_FAST8_MAX INT8_MAX
+#define INT_FAST16_MIN INT16_MIN
+#define INT_FAST16_MAX INT16_MAX
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST32_MAX INT32_MAX
+#define INT_FAST64_MIN INT64_MIN
+#define INT_FAST64_MAX INT64_MAX
+#define UINT_FAST8_MAX UINT8_MAX
+#define UINT_FAST16_MAX UINT16_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+#define UINT_FAST64_MAX UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+# define INTPTR_MIN INT64_MIN
+# define INTPTR_MAX INT64_MAX
+# define UINTPTR_MAX UINT64_MAX
+#else // _WIN64 ][
+# define INTPTR_MIN INT32_MIN
+# define INTPTR_MAX INT32_MAX
+# define UINTPTR_MAX UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN INT64_MIN
+#define INTMAX_MAX INT64_MAX
+#define UINTMAX_MAX UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+# define PTRDIFF_MIN _I64_MIN
+# define PTRDIFF_MAX _I64_MAX
+#else // _WIN64 ][
+# define PTRDIFF_MIN _I32_MIN
+# define PTRDIFF_MAX _I32_MAX
+#endif // _WIN64 ]
+
+#define SIG_ATOMIC_MIN INT_MIN
+#define SIG_ATOMIC_MAX INT_MAX
+
+#ifndef SIZE_MAX // [
+# ifdef _WIN64 // [
+# define SIZE_MAX _UI64_MAX
+# else // _WIN64 ][
+# define SIZE_MAX _UI32_MAX
+# endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+# define WCHAR_MIN 0
+#endif // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+# define WCHAR_MAX _UI16_MAX
+#endif // WCHAR_MAX ]
+
+#define WINT_MIN 0
+#define WINT_MAX _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val) val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val) val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+#define INTMAX_C INT64_C
+#define UINTMAX_C UINT64_C
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+#endif // _MSC_STDINT_H_ ]
diff --git a/src/prop/cryptominisat/Solver/time_mem.h b/src/prop/cryptominisat/Solver/time_mem.h
new file mode 100644
index 000000000..c615eb33a
--- /dev/null
+++ b/src/prop/cryptominisat/Solver/time_mem.h
@@ -0,0 +1,102 @@
+/****************************************************************************************[Solver.h]
+MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef TIME_MEM_H
+#define TIME_MEM_H
+
+#ifdef _MSC_VER
+#include <msvc/stdint.h>
+#else
+#include <stdint.h>
+#endif //_MSC_VER
+
+#if defined (_MSC_VER) || defined(CROSS_COMPILE)
+#include <ctime>
+
+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)
+{
+ 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 cpuTimeTotal(void)
+{
+ struct rusage ru;
+ getrusage(RUSAGE_SELF, &ru);
+ 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];
+ pid_t pid = getpid();
+ sprintf(name, "/proc/%d/statm", pid);
+ FILE* in = fopen(name, "rb");
+ if (in == NULL) return 0;
+ int 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();
+}
+
+
+#elif defined(__FreeBSD__)
+static inline uint64_t memUsed(void)
+{
+ struct rusage ru;
+ getrusage(RUSAGE_SELF, &ru);
+ return ru.ru_maxrss*1024;
+}
+
+
+#else
+static inline uint64_t memUsed()
+{
+ return 0;
+}
+#endif
+
+#endif //TIME_MEM_H
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback