-/***********************************************************************************
-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 MINISAT
-{
-using namespace MINISAT;
-
-class BitArray
-{
-public:
- BitArray() :
- size(0)
- , mp(NULL)
- {
- }
-
- BitArray(const BitArray& b) :
- size(b.size)
- {
- mp = new uint64_t[size];
- memcpy(mp, b.mp, sizeof(uint64_t)*size);
- }
-
- BitArray& operator=(const BitArray& b)
- {
- if (size != b.size) {
- delete[] mp;
- size = b.size;
- mp = new uint64_t[size];
- }
- memcpy(mp, b.mp, sizeof(uint64_t)*size);
-
- return *this;
- }
-
- void resize(uint _size, const bool fill)
- {
- _size = _size/64 + (bool)(_size%64);
- if (size != _size) {
- delete[] mp;
- size = _size;
- mp = new uint64_t[size];
- }
- if (fill) setOne();
- else setZero();
- }
-
- ~BitArray()
- {
- delete[] mp;
- }
-
- inline const bool isZero() const
- {
- const uint64_t* mp2 = (const uint64_t*)mp;
-
- for (uint i = 0; i < size; i++) {
- if (mp2[i]) return false;
- }
- return true;
- }
-
- inline void setZero()
- {
- memset(mp, 0, size*sizeof(uint64_t));
- }
-
- inline void setOne()
- {
- memset(mp, 0, size*sizeof(uint64_t));
- }
-
- inline void clearBit(const uint i)
- {
- #ifdef DEBUG_BITARRAY
- assert(size*64 > i);
- #endif
-
- mp[i/64] &= ~((uint64_t)1 << (i%64));
- }
-
- inline void setBit(const uint i)
- {
- #ifdef DEBUG_BITARRAY
- assert(size*64 > i);
- #endif
-
- mp[i/64] |= ((uint64_t)1 << (i%64));
- }
-
- inline const bool operator[](const uint& i) const
- {
- #ifdef DEBUG_BITARRAY
- assert(size*64 > i);
- #endif
-
- return (mp[i/64] >> (i%64)) & 1;
- }
-
- inline const uint getSize() const
- {
- return size*64;
- }
-
-private:
-
- uint size;
- uint64_t* mp;
-};
-
-}; //NAMESPACE MINISAT
-
-#endif //BITARRAY_H
-
-/*****************************************************************************************[Queue.h]
-MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
- 2008 - Gilles Audemard, Laurent Simon
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
-associated documentation files (the "Software"), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge, publish, distribute,
-sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or
-substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
-NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
-OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-**************************************************************************************************/
-
-#ifndef BoundedQueue_h
-#define BoundedQueue_h
-
-#ifdef _MSC_VER
-#include <msvc/stdint.h>
-#else
-#include <stdint.h>
-#endif //_MSC_VER
-
-#include "Vec.h"
-
-//=================================================================================================
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
-template <class T>
-class bqueue {
- vec<T> elems;
- int first;
- int last;
- uint64_t sumofqueue;
- int maxsize;
- int queuesize; // Number of current elements (must be < maxsize !)
-
-public:
- bqueue(void) : first(0), last(0), sumofqueue(0), maxsize(0), queuesize(0) { }
-
- void initSize(int size) {growTo(size);} // Init size of bounded size queue
-
- void push(T x) {
- if (queuesize==maxsize) {
- assert(last==first); // The queue is full, next value to enter will replace oldest one
- sumofqueue -= elems[last];
- if ((++last) == maxsize) last = 0;
- } else
- queuesize++;
- sumofqueue += x;
- elems[first] = x;
- if ((++first) == maxsize) first = 0;
- }
-
- T peek() { assert(queuesize>0); return elems[last]; }
- void pop() {sumofqueue-=elems[last]; queuesize--; if ((++last) == maxsize) last = 0;}
-
- uint64_t getsum() const {return sumofqueue;}
- uint32_t getavg() const {return (uint64_t)sumofqueue/(uint64_t)queuesize;}
- int isvalid() const {return (queuesize==maxsize);}
-
- void growTo(int size) {
- elems.growTo(size);
- first=0; maxsize=size; queuesize = 0;
- for(int i=0;i<size;i++) elems[i]=0;
- }
-
- void fastclear() {first = 0; last = 0; queuesize=0; sumofqueue=0;} // to be called after restarts... Discard the queue
-
- int size(void) { return queuesize; }
-
- void clear(bool dealloc = false) { elems.clear(dealloc); first = 0; maxsize=0; queuesize=0;sumofqueue=0;}
-};
-
-//=================================================================================================
-
-}; //namespace MINISAT
-
-#endif
-/**************************************************************************************************
-From: Solver.C -- (C) Niklas Een, Niklas Sorensson, 2004
-**************************************************************************************************/
-
-#ifndef CSET_H
-#define CSET_H
-
-#include "Vec.h"
-#include <limits>
-#ifdef _MSC_VER
-#include <msvc/stdint.h>
-#else
-#include <stdint.h>
-#endif //_MSC_VER
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
-class Clause;
-
-template <class T>
-uint32_t calcAbstraction(const T& ps) {
- uint32_t abstraction = 0;
- for (uint32_t i = 0; i != ps.size(); i++)
- abstraction |= 1 << (ps[i].toInt() & 31);
- return abstraction;
-}
-
-//#pragma pack(push)
-//#pragma pack(1)
-class ClauseSimp
-{
- public:
- ClauseSimp(Clause* c, const uint32_t _index) :
- clause(c)
- , index(_index)
- {}
-
- Clause* clause;
- uint32_t index;
-};
-//#pragma pack(pop)
-
-class CSet {
- vec<uint32_t> where; // Map clause ID to position in 'which'.
- vec<ClauseSimp> which; // List of clauses (for fast iteration). May contain 'Clause_NULL'.
- vec<uint32_t> free; // List of positions holding 'Clause_NULL'.
-
- public:
- //ClauseSimp& operator [] (uint32_t index) { return which[index]; }
- void reserve(uint32_t size) { where.reserve(size);}
- uint32_t size(void) const { return which.size(); }
- uint32_t nElems(void) const { return which.size() - free.size(); }
-
- bool add(const ClauseSimp& c) {
- assert(c.clause != NULL);
- where.growTo(c.index+1, std::numeric_limits<uint32_t>::max());
- if (where[c.index] != std::numeric_limits<uint32_t>::max()) {
- return true;
- }
- if (free.size() > 0){
- where[c.index] = free.last();
- which[free.last()] = c;
- free.pop();
- }else{
- where[c.index] = which.size();
- which.push(c);
- }
- return false;
- }
-
- bool exclude(const ClauseSimp& c) {
- assert(c.clause != NULL);
- if (c.index >= where.size() || where[c.index] == std::numeric_limits<uint32_t>::max()) {
- //not inside
- return false;
- }
- free.push(where[c.index]);
- which[where[c.index]].clause = NULL;
- where[c.index] = std::numeric_limits<uint32_t>::max();
- return true;
- }
-
- void clear(void) {
- for (uint32_t i = 0; i < which.size(); i++) {
- if (which[i].clause != NULL) {
- where[which[i].index] = std::numeric_limits<uint32_t>::max();
- }
- }
- which.clear();
- free.clear();
- }
-
- class iterator
- {
- public:
- iterator(ClauseSimp* _it) :
- it(_it)
- {}
-
- void operator++()
- {
- it++;
- }
-
- const bool operator!=(const iterator& iter) const
- {
- return (it != iter.it);;
- }
-
- ClauseSimp& operator*() {
- return *it;
- }
-
- ClauseSimp*& operator->() {
- return it;
- }
- private:
- ClauseSimp* it;
- };
-
- iterator begin()
- {
- return iterator(which.getData());
- }
-
- iterator end()
- {
- return iterator(which.getData() + which.size());
- }
-};
-
-}; //NAMESPACE MINISAT
-
-#endif //CSET_H
\ No newline at end of file
-#include "Clause.h"
-
-//boost::pool<> binaryClausePool(sizeof(Clause)+2*sizeof(Lit));
-/***********************************************************************************[SolverTypes.h]
-MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
-CryptoMiniSat -- Copyright (c) 2009 Mate Soos
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
-associated documentation files (the "Software"), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge, publish, distribute,
-sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or
-substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
-NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
-OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-**************************************************************************************************/
-
-#ifndef CLAUSE_H
-#define CLAUSE_H
-
-#ifdef _MSC_VER
-#include <msvc/stdint.h>
-#else
-#include "SmallPtr.h"
-#include <stdint.h>
-#endif //_MSC_VER
-#include <cstdio>
-#include <vector>
-#include <sys/types.h>
-#include "Vec.h"
-#include "SolverTypes.h"
-#include "PackedRow.h"
-#include "constants.h"
-//#include "pool.hpp"
-#ifndef uint
-#define uint unsigned int
-#endif
-
-using std::vector;
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
-//=================================================================================================
-// Clause -- a simple class for representing a clause:
-
-class MatrixFinder;
-
-class Clause
-{
-protected:
-
- #ifdef STATS_NEEDED
- uint group;
- #endif
-
- uint32_t isLearnt:1;
- uint32_t strenghtened:1;
- uint32_t varChanged:1;
- uint32_t sorted:1;
- uint32_t invertedXor:1;
- uint32_t isXorClause:1;
- uint32_t subsume0Done:1;
- uint32_t mySize:20;
-
- union {int32_t act; uint32_t abst;} extra;
- float oldActivityInter;
- #ifdef _MSC_VER
- Lit data[1];
- #else
- Lit data[0];
- #endif //_MSC_VER
-
-#ifdef _MSC_VER
-public:
-#endif //_MSC_VER
- template<class V>
- Clause(const V& ps, const uint _group, const bool learnt)
- {
- isXorClause = false;
- strenghtened = false;
- sorted = false;
- varChanged = true;
- subsume0Done = false;
- mySize = ps.size();
- isLearnt = learnt;
- setGroup(_group);
- for (uint i = 0; i < ps.size(); i++) data[i] = ps[i];
- if (learnt) {
- extra.act = 0;
- oldActivityInter = 0;
- } else
- calcAbstraction();
- }
-
-public:
- #ifndef _MSC_VER
- // -- use this function instead:
- template<class T>
- friend Clause* Clause_new(const T& ps, const uint group, const bool learnt = false);
- #endif //_MSC_VER
-
- const uint size () const {
- return mySize;
- }
- void resize (const uint size) {
- mySize = size;
- }
- void shrink (const uint i) {
- assert(i <= size());
- mySize -= i;
- }
- void pop () {
- shrink(1);
- }
- const bool isXor () {
- return isXorClause;
- }
- const bool learnt () const {
- return isLearnt;
- }
- float& oldActivity () {
- return oldActivityInter;
- }
-
- const float& oldActivity () const {
- return oldActivityInter;
- }
-
-
- const bool getStrenghtened() const {
- return strenghtened;
- }
- void setStrenghtened() {
- strenghtened = true;
- sorted = false;
- subsume0Done = false;
- }
- void unsetStrenghtened() {
- strenghtened = false;
- }
- const bool getVarChanged() const {
- return varChanged;
- }
- void setVarChanged() {
- varChanged = true;
- sorted = false;
- subsume0Done = false;
- }
- void unsetVarChanged() {
- varChanged = false;
- }
- const bool getSorted() const {
- return sorted;
- }
- void setSorted() {
- sorted = true;
- }
- void setUnsorted() {
- sorted = false;
- }
- void subsume0Finished() {
- subsume0Done = 1;
- }
- const bool subsume0IsFinished() {
- return subsume0Done;
- }
-
- Lit& operator [] (uint32_t i) {
- return data[i];
- }
- const Lit& operator [] (uint32_t i) const {
- return data[i];
- }
-
- void setActivity(int i) {
- extra.act = i;
- }
-
- const int& activity () const {
- return extra.act;
- }
-
- void makeNonLearnt() {
- assert(isLearnt);
- isLearnt = false;
- calcAbstraction();
- }
-
- void makeLearnt(const uint32_t newActivity) {
- extra.act = newActivity;
- isLearnt = true;
- }
-
- inline void strengthen(const Lit p)
- {
- remove(*this, p);
- sorted = false;
- calcAbstraction();
- }
-
- void calcAbstraction() {
- extra.abst = 0;
- for (uint32_t i = 0; i != size(); i++)
- extra.abst |= 1 << (data[i].toInt() & 31);
- }
-
- uint32_t getAbst()
- {
- return extra.abst;
- }
-
- const Lit* getData () const {
- return data;
- }
- Lit* getData () {
- return data;
- }
- const Lit* getDataEnd () const {
- return data+size();
- }
- Lit* getDataEnd () {
- return data+size();
- }
- void print() {
- printf("Clause group: %d, size: %d, learnt:%d, lits: ", getGroup(), size(), learnt());
- plainPrint();
- }
- void plainPrint(FILE* to = stdout) const {
- for (uint i = 0; i < size(); i++) {
- if (data[i].sign()) fprintf(to, "-");
- fprintf(to, "%d ", data[i].var() + 1);
- }
- fprintf(to, "0\n");
- }
- #ifdef STATS_NEEDED
- const uint32_t getGroup() const
- {
- return group;
- }
- void setGroup(const uint32_t _group)
- {
- group = _group;
- }
- #else
- const uint getGroup() const
- {
- return 0;
- }
- void setGroup(const uint32_t _group)
- {
- return;
- }
- #endif //STATS_NEEDED
-};
-
-class XorClause : public Clause
-{
-
-#ifdef _MSC_VER
-public:
-#else //_MSC_VER
-protected:
-#endif //_MSC_VER
-
- // NOTE: This constructor cannot be used directly (doesn't allocate enough memory).
- template<class V>
- XorClause(const V& ps, const bool inverted, const uint _group) :
- Clause(ps, _group, false)
- {
- invertedXor = inverted;
- isXorClause = true;
- calcXorAbstraction();
- }
-
-public:
- #ifndef _MSC_VER
- // -- use this function instead:
- template<class V>
- friend XorClause* XorClause_new(const V& ps, const bool inverted, const uint group);
- #endif //_MSC_VER
-
- inline bool xor_clause_inverted() const
- {
- return invertedXor;
- }
- inline void invert(bool b)
- {
- invertedXor ^= b;
- }
- void calcXorAbstraction() {
- extra.abst = 0;
- for (uint32_t i = 0; i != size(); i++)
- extra.abst |= 1 << (data[i].var() & 31);
- }
-
- void print() {
- printf("XOR Clause group: %d, size: %d, learnt:%d, lits:\"", getGroup(), size(), learnt());
- plainPrint();
- }
-
- void plainPrint(FILE* to = stdout) const {
- fprintf(to, "x");
- if (xor_clause_inverted())
- printf("-");
- for (uint i = 0; i < size(); i++) {
- fprintf(to, "%d ", data[i].var() + 1);
- }
- fprintf(to, "0\n");
- }
-
- friend class MatrixFinder;
-};
-
-//extern boost::pool<> binaryClausePool;
-
-template<class T>
-Clause* Clause_new(const T& ps, const uint group, const bool learnt = false)
-{
- void* mem;
- //if (ps.size() != 2)
- mem = malloc(sizeof(Clause) + sizeof(Lit)*(ps.size()));
- //else
- // mem = binaryClausePool.malloc();
- Clause* real= new (mem) Clause(ps, group, learnt);
- return real;
-}
-
-template<class T>
-XorClause* XorClause_new(const T& ps, const bool inverted, const uint group)
-{
- void* mem = malloc(sizeof(XorClause) + sizeof(Lit)*(ps.size()));
- XorClause* real= new (mem) XorClause(ps, inverted, group);
- return real;
-}
-
-inline void clauseFree(Clause* c)
-{
- //if (binaryClausePool.is_from(c)) binaryClausePool.free(c);
- //else
- free(c);
-}
-
-/*_________________________________________________________________________________________________
-|
-| subsumes : (other : const Clause&) -> Lit
-|
-| Description:
-| Checks if clause subsumes 'other', and at the same time, if it can be used to simplify 'other'
-| by subsumption resolution.
-|
-| Result:
-| lit_Error - No subsumption or simplification
-| lit_Undef - Clause subsumes 'other'
-| p - The literal p can be deleted from 'other'
-|________________________________________________________________________________________________@*/
-/*inline Lit Clause::subsumes(const Clause& other) const
-{
- if (other.size() < size() || (extra.abst & ~other.extra.abst) != 0)
- return lit_Error;
-
- Lit ret = lit_Undef;
- const Lit* c = this->getData();
- const Lit* d = other.getData();
-
- for (uint32_t i = 0; i != size(); i++) {
- // search for c[i] or ~c[i]
- for (uint32_t j = 0; j != other.size(); j++)
- if (c[i] == d[j])
- goto ok;
- else if (ret == lit_Undef && c[i] == ~d[j]){
- ret = c[i];
- goto ok;
- }
-
- // did not find it
- return lit_Error;
- ok:;
- }
-
- return ret;
-}*/
-
-#ifdef _MSC_VER
-typedef Clause* ClausePtr;
-typedef XorClause* XorClausePtr;
-#else
-typedef sptr<Clause> ClausePtr;
-typedef sptr<XorClause> XorClausePtr;
-#endif //_MSC_VER
-
-#pragma pack(push)
-#pragma pack(1)
-class WatchedBin {
- public:
- WatchedBin(Clause *_clause, Lit _impliedLit) : clause(_clause), impliedLit(_impliedLit) {};
- ClausePtr clause;
- Lit impliedLit;
-};
-
-class Watched {
- public:
- Watched(Clause *_clause, Lit _blockedLit) : clause(_clause), blockedLit(_blockedLit) {};
- ClausePtr clause;
- Lit blockedLit;
-};
-#pragma pack(pop)
-
-}; //NAMESPACE MINISAT
-
-#endif //CLAUSE_H
-/***********************************************************************************
-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"
-
-#ifdef _MSC_VER
-#define __builtin_prefetch(a,b,c)
-#endif //_MSC_VER
-
-//#define DEBUG_CLEAN
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
-ClauseCleaner::ClauseCleaner(Solver& _solver) :
- solver(_solver)
-{
- for (uint i = 0; i < 6; i++) {
- lastNumUnitarySat[i] = solver.get_unitary_learnts_num();
- lastNumUnitaryClean[i] = solver.get_unitary_learnts_num();
- }
-}
-
-void ClauseCleaner::removeSatisfied(vec<XorClause*>& cs, ClauseSetType type, const uint limit)
-{
- #ifdef DEBUG_CLEAN
- assert(solver.decisionLevel() == 0);
- #endif
-
- if (lastNumUnitarySat[type] + limit >= solver.get_unitary_learnts_num())
- return;
-
- uint32_t i,j;
- for (i = j = 0; i < cs.size(); i++) {
- if (satisfied(*cs[i]))
- solver.removeClause(*cs[i]);
- else
- cs[j++] = cs[i];
- }
- cs.shrink(i - j);
-
- lastNumUnitarySat[type] = solver.get_unitary_learnts_num();
-}
-
-void ClauseCleaner::removeSatisfied(vec<Clause*>& cs, ClauseSetType type, const uint limit)
-{
- #ifdef DEBUG_CLEAN
- assert(solver.decisionLevel() == 0);
- #endif
-
- if (lastNumUnitarySat[type] + limit >= solver.get_unitary_learnts_num())
- return;
-
- Clause **i,**j, **end;
- for (i = j = cs.getData(), end = i + cs.size(); i != end; i++) {
- if (i+1 != end)
- __builtin_prefetch(*(i+1), 0, 0);
- if (satisfied(**i))
- solver.removeClause(**i);
- else
- *j++ = *i;
- }
- cs.shrink(i - j);
-
- lastNumUnitarySat[type] = solver.get_unitary_learnts_num();
-}
-
-void ClauseCleaner::cleanClauses(vec<Clause*>& cs, ClauseSetType type, const uint limit)
-{
- assert(solver.decisionLevel() == 0);
- assert(solver.qhead == solver.trail.size());
-
- if (lastNumUnitaryClean[type] + limit >= solver.get_unitary_learnts_num())
- return;
-
- Clause **s, **ss, **end;
- for (s = ss = cs.getData(), end = s + cs.size(); s != end;) {
- if (s+1 != end)
- __builtin_prefetch(*(s+1), 1, 0);
- if (cleanClause(**s)) {
- clauseFree(*s);
- s++;
- } else if (type != ClauseCleaner::binaryClauses && (*s)->size() == 2) {
- solver.binaryClauses.push(*s);
- solver.becameBinary++;
- s++;
- } else {
- *ss++ = *s++;
- }
- }
- cs.shrink(s-ss);
-
- lastNumUnitaryClean[type] = solver.get_unitary_learnts_num();
-
- #ifdef VERBOSE_DEBUG
- cout << "cleanClauses(Clause) useful ?? Removed: " << s-ss << endl;
- #endif
-}
-
-inline const bool ClauseCleaner::cleanClause(Clause& c)
-{
- Lit origLit1 = c[0];
- Lit origLit2 = c[1];
- uint32_t origSize = c.size();
-
- Lit *i, *j, *end;
- for (i = j = c.getData(), end = i + c.size(); i != end; i++) {
- lbool val = solver.value(*i);
- if (val == l_Undef) {
- *j++ = *i;
- continue;
- }
-
- if (val == l_True) {
- solver.detachModifiedClause(origLit1, origLit2, origSize, &c);
- return true;
- }
- }
-
- if ((c.size() > 2) && (c.size() - (i-j) == 2)) {
- solver.detachModifiedClause(origLit1, origLit2, c.size(), &c);
- c.shrink(i-j);
- c.setStrenghtened();
- solver.attachClause(c);
- } else if (i != j) {
- c.setStrenghtened();
- c.shrink(i-j);
- if (c.learnt())
- solver.learnts_literals -= i-j;
- else
- solver.clauses_literals -= i-j;
- }
-
- return false;
-}
-
-void ClauseCleaner::cleanClauses(vec<XorClause*>& cs, ClauseSetType type, const uint limit)
-{
- assert(solver.decisionLevel() == 0);
- assert(solver.qhead == solver.trail.size());
-
- if (lastNumUnitaryClean[type] + limit >= solver.get_unitary_learnts_num())
- return;
-
- XorClause **s, **ss, **end;
- for (s = ss = cs.getData(), end = s + cs.size(); s != end;) {
- if (s+1 != end)
- __builtin_prefetch(*(s+1), 1, 0);
- if (cleanClause(**s)) {
- free(*s);
- s++;
- } else {
- *ss++ = *s++;
- }
- }
- cs.shrink(s-ss);
-
- lastNumUnitaryClean[type] = solver.get_unitary_learnts_num();
-
- #ifdef VERBOSE_DEBUG
- cout << "cleanClauses(XorClause) useful: ?? Removed: " << s-ss << endl;
- #endif
-}
-
-inline const bool ClauseCleaner::cleanClause(XorClause& c)
-{
- Lit *i, *j, *end;
- Var origVar1 = c[0].var();
- Var origVar2 = c[1].var();
- uint32_t origSize = c.size();
- for (i = j = c.getData(), end = i + c.size(); i != end; i++) {
- const lbool& val = solver.assigns[i->var()];
- if (val.isUndef()) {
- *j = *i;
- j++;
- } else c.invert(val.getBool());
- }
- c.shrink(i-j);
-
- switch (c.size()) {
- case 0: {
- solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
- return true;
- }
- case 2: {
- vec<Lit> ps(2);
- ps[0] = c[0].unsign();
- ps[1] = c[1].unsign();
- solver.varReplacer->replace(ps, c.xor_clause_inverted(), c.getGroup());
- solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
- return true;
- }
- default:
- if (i-j > 0) {
- c.setStrenghtened();
- solver.clauses_literals -= i-j;
- }
- return false;
- }
-}
-
-void ClauseCleaner::cleanClausesBewareNULL(vec<ClauseSimp>& cs, ClauseCleaner::ClauseSetType type, Subsumer& subs, const uint limit)
-{
- assert(solver.decisionLevel() == 0);
- assert(solver.qhead == solver.trail.size());
-
- if (lastNumUnitaryClean[type] + limit >= solver.get_unitary_learnts_num())
- return;
-
- ClauseSimp *s, *end;
- for (s = cs.getData(), end = s + cs.size(); s != end; s++) {
- if (s+1 != end)
- __builtin_prefetch((s+1)->clause, 1, 0);
- if (s->clause == NULL)
- continue;
-
- if (cleanClauseBewareNULL(*s, subs)) {
- continue;
- } else if (s->clause->size() == 2)
- solver.becameBinary++;
- }
-
- lastNumUnitaryClean[type] = solver.get_unitary_learnts_num();
-}
-
-inline const bool ClauseCleaner::cleanClauseBewareNULL(ClauseSimp cc, Subsumer& subs)
-{
- Clause& c = *cc.clause;
- vec<Lit> origClause(c.size());
- memcpy(origClause.getData(), c.getData(), sizeof(Lit)*c.size());
-
- Lit *i, *j, *end;
- for (i = j = c.getData(), end = i + c.size(); i != end; i++) {
- lbool val = solver.value(*i);
- if (val == l_Undef) {
- *j++ = *i;
- continue;
- }
-
- if (val == l_True) {
- subs.unlinkModifiedClause(origClause, cc);
- free(cc.clause);
- return true;
- }
- }
-
- if (i != j) {
- c.setStrenghtened();
- if (origClause.size() > 2 && origClause.size()-(i-j) == 2) {
- subs.unlinkModifiedClause(origClause, cc);
- subs.clauses[cc.index] = cc;
- c.shrink(i-j);
- solver.attachClause(c);
- subs.linkInAlreadyClause(cc);
- } else {
- c.shrink(i-j);
- subs.unlinkModifiedClauseNoDetachNoNULL(origClause, cc);
- subs.linkInAlreadyClause(cc);
- if (c.learnt())
- solver.learnts_literals -= i-j;
- else
- solver.clauses_literals -= i-j;
- }
- c.calcAbstraction();
- subs.updateClause(cc);
- }
-
- return false;
-}
-
-void ClauseCleaner::cleanXorClausesBewareNULL(vec<XorClauseSimp>& cs, ClauseCleaner::ClauseSetType type, XorSubsumer& subs, const uint limit)
-{
- assert(solver.decisionLevel() == 0);
- assert(solver.qhead == solver.trail.size());
-
- if (lastNumUnitaryClean[type] + limit >= solver.get_unitary_learnts_num())
- return;
-
- XorClauseSimp *s, *end;
- for (s = cs.getData(), end = s + cs.size(); s != end; s++) {
- if (s+1 != end)
- __builtin_prefetch((s+1)->clause, 1, 0);
- if (s->clause == NULL)
- continue;
-
- cleanXorClauseBewareNULL(*s, subs);
- }
-
- lastNumUnitaryClean[type] = solver.get_unitary_learnts_num();
-}
-
-inline const bool ClauseCleaner::cleanXorClauseBewareNULL(XorClauseSimp cc, XorSubsumer& subs)
-{
- XorClause& c = *cc.clause;
- vec<Lit> origClause(c.size());
- memcpy(origClause.getData(), c.getData(), sizeof(Lit)*c.size());
-
- Lit *i, *j, *end;
- for (i = j = c.getData(), end = i + c.size(); i != end; i++) {
- const lbool& val = solver.assigns[i->var()];
- if (val.isUndef()) {
- *j = *i;
- j++;
- } else c.invert(val.getBool());
- }
- c.shrink(i-j);
-
- switch(c.size()) {
- case 0: {
- subs.unlinkModifiedClause(origClause, cc);
- free(cc.clause);
- return true;
- }
- case 2: {
- vec<Lit> ps(2);
- ps[0] = c[0].unsign();
- ps[1] = c[1].unsign();
- solver.varReplacer->replace(ps, c.xor_clause_inverted(), c.getGroup());
- subs.unlinkModifiedClause(origClause, cc);
- free(cc.clause);
- return true;
- }
- default:
- if (i-j > 0) {
- subs.unlinkModifiedClauseNoDetachNoNULL(origClause, cc);
- subs.linkInAlreadyClause(cc);
- c.calcXorAbstraction();
- }
- }
-
- return false;
-}
-
-bool ClauseCleaner::satisfied(const Clause& c) const
-{
- for (uint i = 0; i != c.size(); i++)
- if (solver.value(c[i]) == l_True)
- return true;
- return false;
-}
-
-bool ClauseCleaner::satisfied(const XorClause& c) const
-{
- bool final = c.xor_clause_inverted();
- for (uint k = 0; k != c.size(); k++ ) {
- const lbool& val = solver.assigns[c[k].var()];
- if (val.isUndef()) return false;
- final ^= val.getBool();
- }
- return final;
-}
-
-}; //NAMESPACE MINISAT
-/***********************************************************************************
-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 MINISAT
-{
-using namespace MINISAT;
-
-class ClauseCleaner
-{
- public:
- ClauseCleaner(Solver& solver);
-
- enum ClauseSetType {clauses, xorclauses, learnts, binaryClauses, simpClauses, xorSimpClauses};
-
- void cleanClauses(vec<Clause*>& cs, ClauseSetType type, const uint limit = 0);
- void cleanClausesBewareNULL(vec<ClauseSimp>& cs, ClauseSetType type, Subsumer& subs, const uint limit = 0);
- void cleanXorClausesBewareNULL(vec<XorClauseSimp>& cs, ClauseSetType type, XorSubsumer& subs, const uint limit = 0);
- const bool cleanClauseBewareNULL(ClauseSimp c, Subsumer& subs);
- const bool cleanXorClauseBewareNULL(XorClauseSimp c, XorSubsumer& subs);
-
- void cleanClauses(vec<XorClause*>& cs, ClauseSetType type, const uint limit = 0);
- void removeSatisfied(vec<Clause*>& cs, ClauseSetType type, const uint limit = 0);
- void removeSatisfied(vec<XorClause*>& cs, ClauseSetType type, const uint limit = 0);
- void removeAndCleanAll(const bool nolimit = false);
- bool satisfied(const Clause& c) const;
- bool satisfied(const XorClause& c) const;
-
- private:
- const bool cleanClause(XorClause& c);
- const bool cleanClause(Clause& c);
-
- uint lastNumUnitarySat[6];
- uint lastNumUnitaryClean[6];
-
- Solver& solver;
-};
-
-inline void ClauseCleaner::removeAndCleanAll(const bool nolimit)
-{
- //uint limit = std::min((uint)((double)solver.order_heap.size() * PERCENTAGECLEANCLAUSES), FIXCLEANREPLACE);
- uint limit = (double)solver.order_heap.size() * PERCENTAGECLEANCLAUSES;
- if (nolimit) limit = 0;
-
- removeSatisfied(solver.binaryClauses, ClauseCleaner::binaryClauses, limit);
- cleanClauses(solver.clauses, ClauseCleaner::clauses, limit);
- cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses, limit);
- cleanClauses(solver.learnts, ClauseCleaner::learnts, limit);
-}
-
-}; //NAMESPACE MINISAT
-
-#endif //CLAUSECLEANER_H
-/***********************************************************************************
-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 "Conglomerate.h"
-#include "VarReplacer.h"
-#include "ClauseCleaner.h"
-
-#include <utility>
-#include <algorithm>
-#include <cstring>
-#include "time_mem.h"
-#include <iomanip>
-using std::make_pair;
-
-//#define VERBOSE_DEBUG
-
-#ifdef VERBOSE_DEBUG
-#include <iostream>
-using std::cout;
-using std::endl;
-#endif
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
-Conglomerate::Conglomerate(Solver& _solver) :
- found(0)
- , solver(_solver)
-{}
-
-Conglomerate::~Conglomerate()
-{
- for(uint i = 0; i < calcAtFinish.size(); i++)
- free(calcAtFinish[i]);
-}
-
-void Conglomerate::blockVars()
-{
- for (Clause *const*it = solver.clauses.getData(), *const*end = it + solver.clauses.size(); it != end; it++) {
- const Clause& c = **it;
- for (const Lit* a = &c[0], *end = a + c.size(); a != end; a++) {
- blocked[a->var()] = true;
- }
- }
-
- for (Clause *const*it = solver.binaryClauses.getData(), *const*end = it + solver.binaryClauses.size(); it != end; it++) {
- const Clause& c = **it;
- blocked[c[0].var()] = true;
- blocked[c[1].var()] = true;
- }
-
- for (Lit* it = &(solver.trail[0]), *end = it + solver.trail.size(); it != end; it++)
- blocked[it->var()] = true;
-
- const vec<Clause*>& clauses = solver.varReplacer->getClauses();
- for (Clause *const*it = clauses.getData(), *const*end = it + clauses.size(); it != end; it++) {
- const Clause& c = **it;
- for (const Lit* a = &c[0], *end = a + c.size(); a != end; a++) {
- blocked[a->var()] = true;
- }
- }
-}
-
-void Conglomerate::fillVarToXor()
-{
- varToXor.clear();
-
- uint i = 0;
- for (XorClause* const* it = solver.xorclauses.getData(), *const*end = it + solver.xorclauses.size(); it != end; it++, i++) {
- const XorClause& c = **it;
- for (const Lit * a = &c[0], *end = a + c.size(); a != end; a++) {
- if (!blocked[a->var()])
- varToXor[a->var()].push_back(make_pair(*it, i));
- }
- }
-}
-
-void Conglomerate::removeVar(const Var var)
-{
- solver.activity[var] = 0.0;
- solver.order_heap.update(var);
- removedVars[var] = true;
- if (solver.decision_var[var]) {
- madeVarNonDecision.push(var);
- solver.setDecisionVar(var, false);
- }
- found++;
-}
-
-void Conglomerate::processClause(XorClause& x, uint32_t num, Var remove_var)
-{
- for (const Lit* a = &x[0], *end = a + x.size(); a != end; a++) {
- Var var = a->var();
- if (var != remove_var) {
- varToXorMap::iterator finder = varToXor.find(var);
- if (finder != varToXor.end()) {
- vector<pair<XorClause*, uint32_t> >::iterator it =
- std::find(finder->second.begin(), finder->second.end(), make_pair(&x, num));
- finder->second.erase(it);
- }
- }
- }
-}
-
-const bool Conglomerate::heuleProcessFull()
-{
- #ifdef VERBOSE_DEBUG
- cout << "Heule XOR-ing started" << endl;
- #endif
-
- double time = cpuTime();
- found = 0;
- uint oldToReplaceVars = solver.varReplacer->getNewToReplaceVars();
- solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses);
- if (solver.ok == false)
- return false;
-
- toRemove.clear();
- toRemove.resize(solver.xorclauses.size(), false);
- blocked.clear();
- blocked.resize(solver.nVars(), false);
- fillVarToXor();
- if (!heuleProcess())
- goto end;
-
- if (solver.verbosity >=1) {
- std::cout << "c | Heule-processings XORs:" << std::setw(8) << std::setprecision(2) << std::fixed << cpuTime()-time
- << " Found smaller XOR-s: " << std::setw(6) << found
- << " New bin anti/eq-s: " << std::setw(3) << solver.varReplacer->getNewToReplaceVars() - oldToReplaceVars
- << std::setw(0) << " |" << std::endl;
- }
-
-end:
-
- clearToRemove();
-
- return solver.ok;
-}
-
-const bool Conglomerate::conglomerateXorsFull()
-{
- #ifdef VERBOSE_DEBUG
- cout << "Finding conglomerate xors started" << endl;
- #endif
-
- double time = cpuTime();
- found = 0;
- uint32_t origNumClauses = solver.xorclauses.size();
-
- solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses);
- if (solver.ok == false)
- return false;
-
- toRemove.clear();
- toRemove.resize(solver.xorclauses.size(), false);
- blocked.clear();
- blocked.resize(solver.nVars(), false);
- blockVars();
- fillVarToXor();
- if (conglomerateXors() == false)
- goto end;
-
-end:
-
- clearToRemove();
- assert(origNumClauses >= solver.xorclauses.size());
- if (solver.verbosity >=1) {
- std::cout << "c | Conglomerating XORs:" << std::setw(8) << std::setprecision(2) << std::fixed << cpuTime()-time << " s "
- << " removed " << std::setw(8) << found << " vars"
- << " removed " << std::setw(8) << origNumClauses-solver.xorclauses.size() << " clauses"
- << std::setw(0) << " |" << std::endl;
- }
-
- clearLearntsFromToRemove();
- solver.order_heap.filter(Solver::VarFilter(solver));
-
- return solver.ok;
-}
-
-void Conglomerate::fillNewSet(vector<vector<Lit> >& newSet, vector<pair<XorClause*, uint32_t> >& clauseSet) const
-{
- newSet.clear();
- newSet.resize(clauseSet.size());
-
- XorClause& firstXorClause = *(clauseSet[0].first);
- newSet[0].resize(firstXorClause.size());
- memcpy(&newSet[0][0], firstXorClause.getData(), sizeof(Lit)*firstXorClause.size());
-
- for (uint i = 1; i < clauseSet.size(); i++) {
- XorClause& thisXorClause = *clauseSet[i].first;
- newSet[i] = newSet[0];
- newSet[i].resize(firstXorClause.size()+thisXorClause.size());
- memcpy(&newSet[i][firstXorClause.size()], thisXorClause.getData(), sizeof(Lit)*thisXorClause.size());
- clearDouble(newSet[i]);
- }
-}
-
-const bool Conglomerate::heuleProcess()
-{
- vector<vector<Lit> > newSet;
- while(varToXor.begin() != varToXor.end()) {
- varToXorMap::iterator it = varToXor.begin();
- vector<pair<XorClause*, uint32_t> >& clauseSet = it->second;
- const Var var = it->first;
-
- if (blocked[var] || clauseSet.size() == 1) {
- varToXor.erase(it);
- blocked[var] = true;
- continue;
- }
- blocked[var] = true;
-
- std::sort(clauseSet.begin(), clauseSet.end(), ClauseSetSorter());
- fillNewSet(newSet, clauseSet);
-
- for (uint i = 1; i < newSet.size(); i++) if (newSet[i].size() <= 2) {
- found++;
- XorClause& thisXorClause = *clauseSet[i].first;
- const bool inverted = !clauseSet[0].first->xor_clause_inverted() ^ thisXorClause.xor_clause_inverted();
- const uint old_group = thisXorClause.getGroup();
-
- #ifdef VERBOSE_DEBUG
- cout << "- XOR1:";
- clauseSet[0].first->plainPrint();
- cout << "- XOR2:";
- thisXorClause.plainPrint();
- #endif
-
- if (!dealWithNewClause(newSet[i], inverted, old_group))
- return false;
- assert(newSet.size() == clauseSet.size());
- }
-
- varToXor.erase(it);
- }
-
- return (solver.ok = (solver.propagate() == NULL));
-}
-
-const bool Conglomerate::conglomerateXors()
-{
- vector<vector<Lit> > newSet;
- while(varToXor.begin() != varToXor.end()) {
- varToXorMap::iterator it = varToXor.begin();
- vector<pair<XorClause*, uint32_t> >& clauseSet = it->second;
- const Var var = it->first;
-
- //We blocked the var during dealWithNewClause (it was in a 2-long xor-clause)
- if (blocked[var]) {
- varToXor.erase(it);
- continue;
- }
-
- if (clauseSet.size() == 0) {
- removeVar(var);
- varToXor.erase(it);
- continue;
- }
-
- std::sort(clauseSet.begin(), clauseSet.end(), ClauseSetSorter());
- fillNewSet(newSet, clauseSet);
-
- int diff = 0;
- for (size_t i = 1; i < newSet.size(); i++)
- diff += (int)newSet[i].size()-(int)clauseSet[i].first->size();
-
- if (newSet.size() > 2) {
- blocked[var] = true;
- varToXor.erase(it);
- continue;
- }
-
- XorClause& firstXorClause = *(clauseSet[0].first);
- bool first_inverted = !firstXorClause.xor_clause_inverted();
- removeVar(var);
-
- #ifdef VERBOSE_DEBUG
- cout << "--- New conglomerate set ---" << endl;
- cout << "- Removing: ";
- firstXorClause.plainPrint();
- cout << "Adding var " << var+1 << " to calcAtFinish" << endl;
- #endif
-
- assert(!toRemove[clauseSet[0].second]);
- toRemove[clauseSet[0].second] = true;
- processClause(firstXorClause, clauseSet[0].second, var);
- solver.detachClause(firstXorClause);
- calcAtFinish.push(&firstXorClause);
-
- for (uint i = 1; i < clauseSet.size(); i++) {
- XorClause& thisXorClause = *clauseSet[i].first;
- #ifdef VERBOSE_DEBUG
- cout << "- Removing: ";
- thisXorClause.plainPrint();
- #endif
-
- const uint old_group = thisXorClause.getGroup();
- const bool inverted = first_inverted ^ thisXorClause.xor_clause_inverted();
- assert(!toRemove[clauseSet[i].second]);
- toRemove[clauseSet[i].second] = true;
- processClause(thisXorClause, clauseSet[i].second, var);
- solver.removeClause(thisXorClause);
-
- if (!dealWithNewClause(newSet[i], inverted, old_group))
- return false;
- assert(newSet.size() == clauseSet.size());
- }
-
- varToXor.erase(it);
- }
-
- return (solver.ok = (solver.propagate() == NULL));
-}
-
-bool Conglomerate::dealWithNewClause(vector<Lit>& ps, const bool inverted, const uint old_group)
-{
- switch(ps.size()) {
- case 0: {
- #ifdef VERBOSE_DEBUG
- cout << "--> xor is 0-long" << endl;
- #endif
-
- if (!inverted) {
- solver.ok = false;
- return false;
- }
- break;
- }
- case 1: {
- #ifdef VERBOSE_DEBUG
- cout << "--> xor is 1-long, attempting to set variable " << ps[0].var()+1 << endl;
- #endif
-
- if (solver.assigns[ps[0].var()] == l_Undef) {
- assert(solver.decisionLevel() == 0);
- blocked[ps[0].var()] = true;
- solver.uncheckedEnqueue(Lit(ps[0].var(), inverted));
- } else if (solver.assigns[ps[0].var()] != boolToLBool(!inverted)) {
- #ifdef VERBOSE_DEBUG
- cout << "Conflict. Aborting.";
- #endif
- solver.ok = false;
- return false;
- } else {
- #ifdef VERBOSE_DEBUG
- cout << "Variable already set to correct value";
- #endif
- }
- break;
- }
-
- case 2: {
- #ifdef VERBOSE_DEBUG
- cout << "--> xor is 2-long, must later replace variable" << endl;
- XorClause* newX = XorClause_new(ps, inverted, old_group);
- newX->plainPrint();
- free(newX);
- #endif
-
- vec<Lit> tmpPS(2);
- tmpPS[0] = ps[0];
- tmpPS[1] = ps[1];
- if (solver.varReplacer->replace(tmpPS, inverted, old_group) == false)
- return false;
- blocked[ps[0].var()] = true;
- blocked[ps[1].var()] = true;
- break;
- }
-
- default: {
- XorClause* newX = XorClause_new(ps, inverted, old_group);
-
- #ifdef VERBOSE_DEBUG
- cout << "- Adding: ";
- newX->plainPrint();
- #endif
-
- solver.xorclauses.push(newX);
- toRemove.push_back(false);
- solver.attachClause(*newX);
- for (const Lit * a = &((*newX)[0]), *end = a + newX->size(); a != end; a++) {
- if (!blocked[a->var()])
- varToXor[a->var()].push_back(make_pair(newX, (uint32_t)(toRemove.size()-1)));
- }
- break;
- }
- }
-
- return true;
-}
-
-void Conglomerate::clearDouble(vector<Lit>& ps) const
-{
- std::sort(ps.begin(), ps.end());
- Lit p;
- uint32_t i, j;
- for (i = j = 0, p = lit_Undef; i != ps.size(); i++) {
- ps[i] = ps[i].unsign();
- if (ps[i] == p) {
- //added, but easily removed
- j--;
- p = lit_Undef;
- } else
- ps[j++] = p = ps[i];
- }
- ps.resize(ps.size() - (i - j));
-}
-
-void Conglomerate::clearToRemove()
-{
- assert(toRemove.size() == solver.xorclauses.size());
-
- XorClause **a = solver.xorclauses.getData();
- XorClause **r = a;
- XorClause **end = a + solver.xorclauses.size();
- for (uint i = 0; r != end; i++) {
- if (!toRemove[i])
- *a++ = *r++;
- else {
- r++;
- }
- }
- solver.xorclauses.shrink(r-a);
-}
-
-void Conglomerate::clearLearntsFromToRemove()
-{
- Clause **a = solver.learnts.getData();
- Clause **r = a;
- Clause **end = a + solver.learnts.size();
- for (; r != end;) {
- const Clause& c = **r;
- bool inside = false;
- if (!solver.locked(c)) {
- for (uint i = 0; i < c.size(); i++) {
- if (removedVars[c[i].var()]) {
- inside = true;
- break;
- }
- }
- }
- if (!inside)
- *a++ = *r++;
- else {
- solver.removeClause(**r);
- r++;
- }
- }
- solver.learnts.shrink(r-a);
-}
-
-void Conglomerate::extendModel(Solver& solver2)
-{
- #ifdef VERBOSE_DEBUG
- cout << "Executing doCalcAtFinish" << endl;
- #endif
-
- vec<Lit> ps;
- for (int i = (int)(calcAtFinish.size())-1; i >= 0; i--) {
- XorClause& c = *calcAtFinish[i];
- assert(c.size() > 2);
-
- ps.clear();
- for (Lit *l = c.getData(), *end = c.getDataEnd(); l != end; l++) {
- ps.push(l->unsign());
- }
-
- solver2.addXorClause(ps, c.xor_clause_inverted(), c.getGroup());
- assert(solver2.ok);
- }
-}
-
-const bool Conglomerate::addRemovedClauses()
-{
- #ifdef VERBOSE_DEBUG
- cout << "Executing addRemovedClauses" << endl;
- #endif
-
- for(XorClause **it = calcAtFinish.getData(), **end = calcAtFinish.getDataEnd(); it != end; it++)
- {
- XorClause& c = **it;
- #ifdef VERBOSE_DEBUG
- cout << "readding already removed (conglomerated) clause: ";
- c.plainPrint();
- #endif
-
- for(Lit *l = c.getData(), *end2 = c.getDataEnd(); l != end2 ; l++)
- *l = l->unsign();
-
- FILE* backup_libraryCNFfile = solver.libraryCNFFile;
- solver.libraryCNFFile = NULL;
- if (!solver.addXorClause(c, c.xor_clause_inverted(), c.getGroup())) {
- for (;it != end; it++) free(*it);
- calcAtFinish.clear();
- return false;
- }
- solver.libraryCNFFile = backup_libraryCNFfile;
- free(&c);
- }
- calcAtFinish.clear();
-
- std::fill(removedVars.getData(), removedVars.getDataEnd(), false);
- for (Var *v = madeVarNonDecision.getData(), *end = madeVarNonDecision.getDataEnd(); v != end; v++) {
- solver.setDecisionVar(*v, true);
- }
- madeVarNonDecision.clear();
-
- return true;
-}
-
-}; //NAMESPACE MINISAT
-/***********************************************************************************
-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 CONGLOMERATE_H
-#define CONGLOMERATE_H
-
-#include <vector>
-#include <map>
-#include <set>
-#ifdef _MSC_VER
-#include <msvc/stdint.h>
-#else
-#include <stdint.h>
-#endif //_MSC_VER
-
-#include "Clause.h"
-#include "VarReplacer.h"
-#include "Solver.h"
-
-using std::vector;
-using std::pair;
-using std::map;
-using std::set;
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
-class Solver;
-
-class Conglomerate
-{
-public:
- Conglomerate(Solver& solver);
- ~Conglomerate();
- const bool conglomerateXorsFull();
- const bool heuleProcessFull();
- const bool addRemovedClauses(); ///<Add clauses that have been removed. Used if solve() is called multiple times
- void extendModel(Solver& solver2); ///<Calculate variables removed during conglomeration
-
- const vec<XorClause*>& getCalcAtFinish() const;
- vec<XorClause*>& getCalcAtFinish();
- const vec<bool>& getRemovedVars() const;
- const bool needCalcAtFinish() const;
-
- void newVar();
-
-private:
-
- struct ClauseSetSorter {
- bool operator () (const pair<XorClause*, uint32_t>& a, const pair<XorClause*, uint32_t>& b) {
- return a.first->size() < b.first->size();
- }
- };
-
- const bool conglomerateXors();
- const bool heuleProcess();
-
- void fillNewSet(vector<vector<Lit> >& newSet, vector<pair<XorClause*, uint32_t> >& clauseSet) const;
-
- void removeVar(const Var var);
- void processClause(XorClause& x, uint32_t num, Var remove_var);
- void blockVars();
- void fillVarToXor();
- void clearDouble(vector<Lit>& ps) const;
- void clearToRemove();
- void clearLearntsFromToRemove();
- bool dealWithNewClause(vector<Lit>& ps, const bool inverted, const uint old_group);
-
- typedef map<uint, vector<pair<XorClause*, uint32_t> > > varToXorMap;
- varToXorMap varToXor;
- vector<bool> blocked;
- vector<bool> toRemove;
-
- vec<bool> removedVars;
- vec<Var> madeVarNonDecision;
-
- vec<XorClause*> calcAtFinish;
- uint found;
-
- Solver& solver;
-};
-
-inline void Conglomerate::newVar()
-{
- removedVars.push(false);
-}
-
-inline const vec<bool>& Conglomerate::getRemovedVars() const
-{
- return removedVars;
-}
-
-inline const vec<XorClause*>& Conglomerate::getCalcAtFinish() const
-{
- return calcAtFinish;
-}
-
-inline vec<XorClause*>& Conglomerate::getCalcAtFinish()
-{
- return calcAtFinish;
-}
-
-inline const bool Conglomerate::needCalcAtFinish() const
-{
- return calcAtFinish.size();
-}
-
-}; //NAMESPACE MINISAT
-
-#endif //CONGLOMERATE_H
-/***********************************************************************************
-CryptoMiniSat -- Copyright (c) 2009 Mate Soos
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-**************************************************************************************************/
-
-#ifndef DOUBLEPACKEDROW_H
-#define DOUBLEPACKEDROW_H
-
-#ifdef _MSC_VER
-#include <msvc/stdint.h>
-#else
-#include <stdint.h>
-#endif //_MSC_VER
-
-#include <stdlib.h>
-
-#include "SolverTypes.h"
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
-class DoublePackedRow
-{
- private:
- class BitIter {
- public:
- inline void operator=(const lbool toSet)
- {
- val &= ~((unsigned char)3 << offset);
- val |= toSet.value << offset;
- }
-
- inline operator lbool() const
- {
- return lbool((val >> offset) & 3);
- }
-
- inline const bool isUndef() const {
- return ((lbool)*this).isUndef();
- }
- inline const bool isDef() const {
- return ((lbool)*this).isDef();
- }
- inline const bool getBool() const {
- return ((lbool)*this).getBool();
- }
- inline const bool operator==(lbool b) const {
- return ((lbool)*this) == b;
- }
- inline const bool operator!=(lbool b) const {
- return ((lbool)*this) != b;
- }
- const lbool operator^(const bool b) const {
- return ((lbool)*this) ^ b;
- }
-
- private:
- friend class DoublePackedRow;
- inline BitIter(unsigned char& mp, const uint32_t _offset) :
- val(mp)
- , offset(_offset)
- {}
-
- unsigned char& val;
- const uint32_t offset;
- };
-
- class BitIterConst {
- public:
- inline operator lbool() const
- {
- return lbool((val >> offset) & 3);
- }
-
- inline const bool isUndef() const {
- return ((lbool)*this).isUndef();
- }
- inline const bool isDef() const {
- return ((lbool)*this).isDef();
- }
- inline const bool getBool() const {
- return ((lbool)*this).getBool();
- }
- inline const bool operator==(lbool b) const {
- return ((lbool)*this) == b;
- }
- inline const bool operator!=(lbool b) const {
- return ((lbool)*this) != b;
- }
- const lbool operator^(const bool b) const {
- return ((lbool)*this) ^ b;
- }
-
-
- private:
- friend class DoublePackedRow;
- inline BitIterConst(unsigned char& mp, const uint32_t _offset) :
- val(mp)
- , offset(_offset)
- {}
-
- const unsigned char& val;
- const uint32_t offset;
- };
-
- public:
- DoublePackedRow() :
- numElems(0)
- , mp(NULL)
- {}
-
- uint32_t size() const
- {
- return numElems;
- }
-
- void growTo(const uint32_t newNumElems)
- {
- uint32_t oldSize = numElems/4 + (bool)(numElems % 4);
- uint32_t newSize = newNumElems/4 + (bool)(newNumElems % 4);
-
- if (oldSize >= newSize) {
- numElems = std::max(newNumElems, numElems);
- return;
- }
-
- mp = (unsigned char*)realloc(mp, newSize*sizeof(unsigned char));
- numElems = newNumElems;
- }
-
- inline BitIter operator[](const uint32_t at)
- {
- return BitIter(mp[at/4], (at%4)*2);
- }
-
- inline const BitIterConst operator[](const uint32_t at) const
- {
- return BitIterConst(mp[at/4], (at%4)*2);
- }
-
- inline void push(const lbool val)
- {
- growTo(numElems+1);
- (*this)[numElems-1] = val;
- }
-
- /*void clear(const uint32_t at)
- {
- mp[at/32] &= ~((uint64_t)3 << ((at%32)*2));
- }*/
-
- private:
-
- Var numElems;
- unsigned char *mp;
-};
-
-}; //NAMESPACE MINISAT
-
-#endif //DOUBLEPACKEDROW_H
-/***********************************************************************************
-CryptoMiniSat -- Copyright (c) 2009 Mate Soos
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-**************************************************************************************************/
-
-#include "FailedVarSearcher.h"
-
-#include <iomanip>
-#include <utility>
-#include <set>
-using std::make_pair;
-using std::set;
-
-#include "Solver.h"
-#include "ClauseCleaner.h"
-#include "time_mem.h"
-#include "VarReplacer.h"
-#include "ClauseCleaner.h"
-
-#ifdef _MSC_VER
-#define __builtin_prefetch(a,b,c)
-#endif //_MSC_VER
-
-//#define VERBOSE_DEUBUG
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
-FailedVarSearcher::FailedVarSearcher(Solver& _solver):
- solver(_solver)
- , finishedLastTime(true)
- , lastTimeWentUntil(0)
- , numPropsMultiplier(1.0)
- , lastTimeFoundTruths(0)
-{
-}
-
-void FailedVarSearcher::addFromSolver(const vec< XorClause* >& cs)
-{
- xorClauseSizes.clear();
- xorClauseSizes.growTo(cs.size());
- occur.resize(solver.nVars());
- for (Var var = 0; var < solver.nVars(); var++) {
- occur[var].clear();
- }
-
- uint32_t i = 0;
- for (XorClause * const*it = cs.getData(), * const*end = it + cs.size(); it != end; it++, i++) {
- if (it+1 != end)
- __builtin_prefetch(*(it+1), 0, 0);
-
- const XorClause& cl = **it;
- xorClauseSizes[i] = cl.size();
- for (const Lit *l = cl.getData(), *end2 = l + cl.size(); l != end2; l++) {
- occur[l->var()].push_back(i);
- }
- }
-}
-
-inline void FailedVarSearcher::removeVarFromXors(const Var var)
-{
- vector<uint32_t>& occ = occur[var];
- if (occ.empty()) return;
-
- for (uint32_t *it = &occ[0], *end = it + occ.size(); it != end; it++) {
- xorClauseSizes[*it]--;
- if (!xorClauseTouched[*it]) {
- xorClauseTouched.setBit(*it);
- investigateXor.push(*it);
- }
- }
-}
-
-inline void FailedVarSearcher::addVarFromXors(const Var var)
-{
- vector<uint32_t>& occ = occur[var];
- if (occ.empty()) return;
-
- for (uint32_t *it = &occ[0], *end = it + occ.size(); it != end; it++) {
- xorClauseSizes[*it]++;
- }
-}
-
-const TwoLongXor FailedVarSearcher::getTwoLongXor(const XorClause& c)
-{
- TwoLongXor tmp;
- uint32_t num = 0;
- tmp.inverted = c.xor_clause_inverted();
-
- for(const Lit *l = c.getData(), *end = l + c.size(); l != end; l++) {
- if (solver.assigns[l->var()] == l_Undef) {
- assert(num < 2);
- tmp.var[num] = l->var();
- num++;
- } else {
- tmp.inverted ^= (solver.assigns[l->var()] == l_True);
- }
- }
-
- #ifdef VERBOSE_DEUBUG
- if (num != 2) {
- std::cout << "Num:" << num << std::endl;
- c.plainPrint();
- }
- #endif
-
- std::sort(&tmp.var[0], &tmp.var[0]+2);
- assert(num == 2);
- return tmp;
-}
-
-const bool FailedVarSearcher::search(uint64_t numProps)
-{
- assert(solver.decisionLevel() == 0);
-
- //Saving Solver state
- Heap<Solver::VarOrderLt> backup_order_heap(solver.order_heap);
- vector<bool> backup_polarities = solver.polarity;
- vec<uint32_t> backup_activity(solver.activity.size());
- std::copy(solver.activity.getData(), solver.activity.getDataEnd(), backup_activity.getData());
- uint32_t backup_var_inc = solver.var_inc;
- uint32_t origHeapSize = solver.order_heap.size();
-
- //General Stats
- double time = cpuTime();
- uint32_t numFailed = 0;
- uint32_t goodBothSame = 0;
- uint32_t from;
- if (finishedLastTime || lastTimeWentUntil >= solver.nVars())
- from = 0;
- else
- from = lastTimeWentUntil;
- uint64_t origProps = solver.propagations;
-
- //If failed var searching is going good, do successively more and more of it
- if (lastTimeFoundTruths > 500 || (double)lastTimeFoundTruths > (double)solver.order_heap.size() * 0.03) std::max(numPropsMultiplier*1.7, 5.0);
- else numPropsMultiplier = 1.0;
- numProps = (uint64_t) ((double)numProps * numPropsMultiplier);
-
- //For failure
- bool failed;
-
- //For BothSame
- BitArray propagated;
- propagated.resize(solver.nVars(), 0);
- BitArray propValue;
- propValue.resize(solver.nVars(), 0);
- vector<pair<Var, bool> > bothSame;
-
- //For calculating how many variables have really been set
- uint32_t origTrailSize = solver.trail.size();
-
- //For 2-long xor (rule 6 of Equivalent literal propagation in the DLL procedure by Chu-Min Li)
- set<TwoLongXor> twoLongXors;
- uint32_t toReplaceBefore = solver.varReplacer->getNewToReplaceVars();
- uint32_t lastTrailSize = solver.trail.size();
- bool binXorFind = true;
- if (solver.xorclauses.size() < 5 ||
- solver.xorclauses.size() > 30000 ||
- solver.order_heap.size() > 30000 ||
- solver.nClauses() > 100000)
- binXorFind = false;
- if (binXorFind) {
- solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses);
- addFromSolver(solver.xorclauses);
- }
- xorClauseTouched.resize(solver.xorclauses.size(), 0);
-
- finishedLastTime = true;
- lastTimeWentUntil = solver.nVars();
- for (Var var = from; var < solver.nVars(); var++) {
- if (solver.assigns[var] == l_Undef && solver.order_heap.inHeap(var)) {
- if ((int)solver.propagations - (int)origProps >= (int)numProps) {
- finishedLastTime = false;
- lastTimeWentUntil = var;
- break;
- }
-
- if (binXorFind) {
- if (lastTrailSize < solver.trail.size()) {
- for (uint32_t i = lastTrailSize; i != solver.trail.size(); i++) {
- removeVarFromXors(solver.trail[i].var());
- }
- }
- lastTrailSize = solver.trail.size();
- xorClauseTouched.setZero();
- investigateXor.clear();
- }
-
- propagated.setZero();
- twoLongXors.clear();
-
- solver.newDecisionLevel();
- solver.uncheckedEnqueue(Lit(var, false));
- failed = (solver.propagate(false) != NULL);
- if (failed) {
- solver.cancelUntil(0);
- numFailed++;
- solver.uncheckedEnqueue(Lit(var, true));
- solver.ok = (solver.propagate(false) == NULL);
- if (!solver.ok) goto end;
- continue;
- } else {
- assert(solver.decisionLevel() > 0);
- for (int c = solver.trail.size()-1; c >= (int)solver.trail_lim[0]; c--) {
- Var x = solver.trail[c].var();
- propagated.setBit(x);
- if (solver.assigns[x].getBool())
- propValue.setBit(x);
- else
- propValue.clearBit(x);
-
- if (binXorFind) removeVarFromXors(x);
- }
-
- if (binXorFind) {
- for (uint32_t *it = investigateXor.getData(), *end = investigateXor.getDataEnd(); it != end; it++) {
- if (xorClauseSizes[*it] == 2)
- twoLongXors.insert(getTwoLongXor(*solver.xorclauses[*it]));
- }
- for (int c = solver.trail.size()-1; c >= (int)solver.trail_lim[0]; c--) {
- addVarFromXors(solver.trail[c].var());
- }
- xorClauseTouched.setZero();
- investigateXor.clear();
- }
-
- solver.cancelUntil(0);
- }
-
- solver.newDecisionLevel();
- solver.uncheckedEnqueue(Lit(var, true));
- failed = (solver.propagate(false) != NULL);
- if (failed) {
- solver.cancelUntil(0);
- numFailed++;
- solver.uncheckedEnqueue(Lit(var, false));
- solver.ok = (solver.propagate(false) == NULL);
- if (!solver.ok) goto end;
- continue;
- } else {
- assert(solver.decisionLevel() > 0);
- for (int c = solver.trail.size()-1; c >= (int)solver.trail_lim[0]; c--) {
- Var x = solver.trail[c].var();
- if (propagated[x] && propValue[x] == solver.assigns[x].getBool())
- bothSame.push_back(make_pair(x, !propValue[x]));
- if (binXorFind) removeVarFromXors(x);
- }
-
- if (binXorFind) {
- if (twoLongXors.size() > 0) {
- for (uint32_t *it = investigateXor.getData(), *end = it + investigateXor.size(); it != end; it++) {
- if (xorClauseSizes[*it] == 2) {
- TwoLongXor tmp = getTwoLongXor(*solver.xorclauses[*it]);
- if (twoLongXors.find(tmp) != twoLongXors.end()) {
- vec<Lit> ps(2);
- ps[0] = Lit(tmp.var[0], false);
- ps[1] = Lit(tmp.var[1], false);
- if (!solver.varReplacer->replace(ps, tmp.inverted, 0))
- goto end;
- }
- }
- }
- }
- for (int c = solver.trail.size()-1; c >= (int)solver.trail_lim[0]; c--) {
- addVarFromXors(solver.trail[c].var());
- }
- }
-
- solver.cancelUntil(0);
- }
-
- for(uint32_t i = 0; i != bothSame.size(); i++) {
- solver.uncheckedEnqueue(Lit(bothSame[i].first, bothSame[i].second));
- }
- goodBothSame += bothSame.size();
- bothSame.clear();
- solver.ok = (solver.propagate(false) == NULL);
- if (!solver.ok) goto end;
- }
- }
-
-end:
- //Restoring Solver state
- if (solver.verbosity >= 1) {
- std::cout << "c | Failvars: "<< std::setw(5) << numFailed <<
- " Bprop vars: " << std::setw(6) << goodBothSame <<
- " Replaced: " << std::setw(3) << (solver.varReplacer->getNewToReplaceVars() - toReplaceBefore) <<
- " Props: " << std::setw(8) << std::setprecision(2) << (int)solver.propagations - (int)origProps <<
- " Time: " << std::setw(6) << std::fixed << std::setprecision(2) << cpuTime() - time <<
- std::setw(5) << " |" << std::endl;
- }
-
- solver.order_heap.filter(Solver::VarFilter(solver));
-
- if (solver.ok && (numFailed || goodBothSame)) {
- double time = cpuTime();
- if ((int)origHeapSize - (int)solver.order_heap.size() > (int)origHeapSize/15 && solver.nClauses() + solver.learnts.size() > 500000) {
- solver.clauses_literals = 0;
- solver.learnts_literals = 0;
- for (uint32_t i = 0; i < solver.nVars(); i++) {
- solver.binwatches[i*2].clear();
- solver.binwatches[i*2+1].clear();
- solver.watches[i*2].clear();
- solver.watches[i*2+1].clear();
- solver.xorwatches[i].clear();
- }
- solver.varReplacer->reattachInternalClauses();
- cleanAndAttachClauses(solver.binaryClauses);
- cleanAndAttachClauses(solver.clauses);
- cleanAndAttachClauses(solver.learnts);
- cleanAndAttachClauses(solver.xorclauses);
- } else {
- solver.clauseCleaner->removeAndCleanAll();
- }
- if (solver.verbosity >= 1 && numFailed + goodBothSame > 100) {
- std::cout << "c | Cleaning up after failed var search: " << std::setw(8) << std::fixed << std::setprecision(2) << cpuTime() - time << " s "
- << std::setw(33) << " | " << std::endl;
- }
- }
-
- lastTimeFoundTruths = solver.trail.size() - origTrailSize;
-
- solver.var_inc = backup_var_inc;
- std::copy(backup_activity.getData(), backup_activity.getDataEnd(), solver.activity.getData());
- solver.order_heap = backup_order_heap;
- solver.polarity = backup_polarities;
- solver.order_heap.filter(Solver::VarFilter(solver));
-
- return solver.ok;
-}
-
-template<class T>
-inline void FailedVarSearcher::cleanAndAttachClauses(vec<T*>& cs)
-{
- T **i = cs.getData();
- T **j = i;
- for (T **end = cs.getDataEnd(); i != end; i++) {
- if (cleanClause(**i)) {
- solver.attachClause(**i);
- *j++ = *i;
- } else {
- free(*i);
- }
- }
- cs.shrink(i-j);
-}
-
-inline const bool FailedVarSearcher::cleanClause(Clause& ps)
-{
- uint32_t origSize = ps.size();
-
- Lit *i = ps.getData();
- Lit *j = i;
- for (Lit *end = ps.getDataEnd(); i != end; i++) {
- if (solver.value(*i) == l_True) return false;
- if (solver.value(*i) == l_Undef) {
- *j++ = *i;
- }
- }
- ps.shrink(i-j);
- assert(ps.size() > 1);
-
- if (ps.size() != origSize) ps.setStrenghtened();
- if (origSize != 2 && ps.size() == 2)
- solver.becameBinary++;
-
- return true;
-}
-
-inline const bool FailedVarSearcher::cleanClause(XorClause& ps)
-{
- uint32_t origSize = ps.size();
-
- Lit *i = ps.getData(), *j = i;
- for (Lit *end = ps.getDataEnd(); i != end; i++) {
- if (solver.assigns[i->var()] == l_True) ps.invert(true);
- if (solver.assigns[i->var()] == l_Undef) {
- *j++ = *i;
- }
- }
- ps.shrink(i-j);
-
- if (ps.size() == 0) return false;
- assert(ps.size() > 1);
-
- if (ps.size() != origSize) ps.setStrenghtened();
- if (ps.size() == 2) {
- vec<Lit> tmp(2);
- tmp[0] = ps[0].unsign();
- tmp[1] = ps[1].unsign();
- solver.varReplacer->replace(tmp, ps.xor_clause_inverted(), ps.getGroup());
- return false;
- }
-
- return true;
-}
-
-}; //NAMESPACE MINISAT
-/***********************************************************************************
-CryptoMiniSat -- Copyright (c) 2009 Mate Soos
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-**************************************************************************************************/
-
-#ifndef FAILEDVARSEARCHER_H
-#define FAILEDVARSEARCHER_H
-
-#include "SolverTypes.h"
-#include "Clause.h"
-#include "BitArray.h"
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
-class Solver;
-
-class TwoLongXor
-{
- public:
- const bool operator==(const TwoLongXor& other) const
- {
- if (var[0] == other.var[0] && var[1] == other.var[1] && inverted == other.inverted)
- return true;
- return false;
- }
- const bool operator<(const TwoLongXor& other) const
- {
- if (var[0] < other.var[0]) return true;
- if (var[0] > other.var[0]) return false;
-
- if (var[1] < other.var[1]) return true;
- if (var[1] > other.var[1]) return false;
-
- if (inverted < other.inverted) return true;
- if (inverted > other.inverted) return false;
-
- return false;
- }
-
- Var var[2];
- bool inverted;
-};
-
-class FailedVarSearcher {
- public:
- FailedVarSearcher(Solver& _solver);
-
- const bool search(uint64_t numProps);
-
- private:
- const TwoLongXor getTwoLongXor(const XorClause& c);
- void addFromSolver(const vec<XorClause*>& cs);
-
- template<class T>
- void cleanAndAttachClauses(vec<T*>& cs);
- const bool cleanClause(Clause& ps);
- const bool cleanClause(XorClause& ps);
-
- Solver& solver;
-
- vec<uint32_t> xorClauseSizes;
- vector<vector<uint32_t> > occur;
- void removeVarFromXors(const Var var);
- void addVarFromXors(const Var var);
- BitArray xorClauseTouched;
- vec<uint32_t> investigateXor;
-
- bool finishedLastTime;
- uint32_t lastTimeWentUntil;
- double numPropsMultiplier;
- uint32_t lastTimeFoundTruths;
-};
-
-}; //NAMESPACE MINISAT
-
-#endif //FAILEDVARSEARCHER_H
\ No newline at end of file
-/***********************************************************************************
-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 "FindUndef.h"
-
-#include "Solver.h"
-#include "VarReplacer.h"
-#include <algorithm>
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
-FindUndef::FindUndef(Solver& _solver) :
- solver(_solver)
- , isPotentialSum(0)
-{
-}
-
-void FindUndef::fillPotential()
-{
- int trail = solver.decisionLevel()-1;
-
- while(trail > 0) {
- assert(trail < (int)solver.trail_lim.size());
- uint at = solver.trail_lim[trail];
-
- assert(at > 0);
- Var v = solver.trail[at].var();
- if (solver.assigns[v] != l_Undef) {
- isPotential[v] = true;
- isPotentialSum++;
- }
-
- trail--;
- }
-
- for (XorClause** it = solver.xorclauses.getData(), **end = it + solver.xorclauses.size(); it != end; it++) {
- XorClause& c = **it;
- for (Lit *l = c.getData(), *end = l + c.size(); l != end; l++) {
- if (isPotential[l->var()]) {
- isPotential[l->var()] = false;
- isPotentialSum--;
- }
- assert(!solver.value(*l).isUndef());
- }
- }
-
- vector<Var> replacingVars = solver.varReplacer->getReplacingVars();
- for (Var *it = &replacingVars[0], *end = it + replacingVars.size(); it != end; it++) {
- if (isPotential[*it]) {
- isPotential[*it] = false;
- isPotentialSum--;
- }
- }
-}
-
-void FindUndef::unboundIsPotentials()
-{
- for (uint i = 0; i < isPotential.size(); i++)
- if (isPotential[i])
- solver.assigns[i] = l_Undef;
-}
-
-void FindUndef::moveBinToNormal()
-{
- binPosition = solver.clauses.size();
- for (uint i = 0; i != solver.binaryClauses.size(); i++)
- solver.clauses.push(solver.binaryClauses[i]);
- solver.binaryClauses.clear();
-}
-
-void FindUndef::moveBinFromNormal()
-{
- for (uint i = binPosition; i != solver.clauses.size(); i++)
- solver.binaryClauses.push(solver.clauses[i]);
- solver.clauses.shrink(solver.clauses.size() - binPosition);
-}
-
-const uint FindUndef::unRoll()
-{
- if (solver.decisionLevel() == 0) return 0;
-
- moveBinToNormal();
-
- dontLookAtClause.resize(solver.clauses.size(), false);
- isPotential.resize(solver.nVars(), false);
- fillPotential();
- satisfies.resize(solver.nVars(), 0);
-
- while(!updateTables()) {
- assert(isPotentialSum > 0);
-
- uint32_t maximum = 0;
- Var v;
- for (uint i = 0; i < isPotential.size(); i++) {
- if (isPotential[i] && satisfies[i] >= maximum) {
- maximum = satisfies[i];
- v = i;
- }
- }
-
- isPotential[v] = false;
- isPotentialSum--;
-
- std::fill(satisfies.begin(), satisfies.end(), 0);
- }
-
- unboundIsPotentials();
- moveBinFromNormal();
-
- return isPotentialSum;
-}
-
-bool FindUndef::updateTables()
-{
- bool allSat = true;
-
- uint i = 0;
- for (Clause** it = solver.clauses.getData(), **end = it + solver.clauses.size(); it != end; it++, i++) {
- if (dontLookAtClause[i])
- continue;
-
- Clause& c = **it;
- bool definitelyOK = false;
- Var v = var_Undef;
- uint numTrue = 0;
- for (Lit *l = c.getData(), *end = l + c.size(); l != end; l++) {
- if (solver.value(*l) == l_True) {
- if (!isPotential[l->var()]) {
- dontLookAtClause[i] = true;
- definitelyOK = true;
- break;
- } else {
- numTrue ++;
- v = l->var();
- }
- }
- }
- if (definitelyOK)
- continue;
-
- if (numTrue == 1) {
- assert(v != var_Undef);
- isPotential[v] = false;
- isPotentialSum--;
- dontLookAtClause[i] = true;
- continue;
- }
-
- //numTrue > 1
- allSat = false;
- for (Lit *l = c.getData(), *end = l + c.size(); l != end; l++) {
- if (solver.value(*l) == l_True)
- satisfies[l->var()]++;
- }
- }
-
- return allSat;
-}
-
-}; //NAMESPACE MINISAT
-/***********************************************************************************
-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 FINDUNDEF_H
-#define FINDUNDEF_H
-
-#ifdef _MSC_VER
-#include <msvc/stdint.h>
-#else
-#include <stdint.h>
-#endif //_MSC_VER
-#include <vector>
-using std::vector;
-
-#include "Solver.h"
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
-class FindUndef {
- public:
- FindUndef(Solver& _solver);
- const uint unRoll();
-
- private:
- Solver& solver;
-
- void moveBinToNormal();
- void moveBinFromNormal();
- bool updateTables();
- void fillPotential();
- void unboundIsPotentials();
-
- vector<bool> dontLookAtClause; //If set to TRUE, then that clause already has only 1 lit that is true, so it can be skipped during updateFixNeed()
- vector<uint32_t> satisfies;
- vector<bool> isPotential;
- uint32_t isPotentialSum;
- uint32_t binPosition;
-
-};
-
-}; //NAMESPACE MINISAT
-
-#endif //
\ No newline at end of file
-/***********************************************************************************
-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"
-
-using std::ostream;
-using std::cout;
-using std::endl;
-
-#ifdef VERBOSE_DEBUG
-#include <iterator>
-#endif
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
-ostream& operator << (ostream& os, const vec<Lit>& v)
-{
- for (uint32_t i = 0; i != v.size(); i++) {
- if (v[i].sign()) os << "-";
- os << v[i].var()+1 << " ";
- }
-
- return os;
-}
-
-Gaussian::Gaussian(Solver& _solver, const GaussianConfig& _config, const uint _matrix_no, const vector<XorClause*>& _xorclauses) :
- solver(_solver)
- , config(_config)
- , matrix_no(_matrix_no)
- , xorclauses(_xorclauses)
- , messed_matrix_vars_since_reversal(true)
- , gauss_last_level(0)
- , disabled(false)
- , useful_prop(0)
- , useful_confl(0)
- , called(0)
-{
-}
-
-Gaussian::~Gaussian()
-{
- for (uint i = 0; i < clauses_toclear.size(); i++)
- clauseFree(clauses_toclear[i].first);
-}
-
-inline void Gaussian::set_matrixset_to_cur()
-{
- uint level = solver.decisionLevel() / config.only_nth_gauss_save;
- assert(level <= matrix_sets.size());
-
- if (level == matrix_sets.size())
- matrix_sets.push_back(cur_matrixset);
- else
- matrix_sets[level] = cur_matrixset;
-}
-
-llbool Gaussian::full_init()
-{
- if (!should_init()) return l_Nothing;
- reset_stats();
-
- bool do_again_gauss = true;
- while (do_again_gauss) {
- do_again_gauss = false;
- solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses);
- if (solver.ok == false)
- return l_False;
- init();
- Clause* confl;
- gaussian_ret g = gaussian(confl);
- switch (g) {
- case unit_conflict:
- case conflict:
- return l_False;
- case unit_propagation:
- case propagation:
- do_again_gauss=true;
- if (solver.propagate() != NULL) return l_False;
- break;
- case nothing:
- break;
- }
- }
-
- return l_Nothing;
-}
-
-void Gaussian::init()
-{
- assert(solver.decisionLevel() == 0);
-
- fill_matrix(cur_matrixset);
- if (!cur_matrixset.num_rows || !cur_matrixset.num_cols) {
- disabled = true;
- badlevel = 0;
- return;
- }
-
- matrix_sets.clear();
- matrix_sets.push_back(cur_matrixset);
- gauss_last_level = solver.trail.size();
- messed_matrix_vars_since_reversal = false;
- badlevel = UINT_MAX;
-
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")Gaussian init finished." << endl;
- #endif
-}
-
-uint Gaussian::select_columnorder(vector<uint16_t>& var_to_col, matrixset& origMat)
-{
- var_to_col.resize(solver.nVars(), unassigned_col);
-
- uint num_xorclauses = 0;
- for (uint32_t i = 0; i != xorclauses.size(); i++) {
- num_xorclauses++;
- XorClause& c = *xorclauses[i];
- for (uint i2 = 0; i2 < c.size(); i2++) {
- assert(solver.assigns[c[i2].var()].isUndef());
- var_to_col[c[i2].var()] = unassigned_col - 1;
- }
- }
-
- uint largest_used_var = 0;
- for (uint i = 0; i < var_to_col.size(); i++)
- if (var_to_col[i] != unassigned_col)
- largest_used_var = i;
- var_to_col.resize(largest_used_var + 1);
-
- var_is_in.resize(var_to_col.size(), 0);
- origMat.var_is_set.resize(var_to_col.size(), 0);
-
- origMat.col_to_var.clear();
- Heap<Solver::VarOrderLt> order_heap(solver.order_heap);
- while (!order_heap.empty())
- {
- Var v = order_heap.removeMin();
-
- if (var_to_col[v] == 1) {
- #ifdef DEBUG_GAUSS
- vector<uint>::iterator it =
- std::find(origMat.col_to_var.begin(), origMat.col_to_var.end(), v);
- assert(it == origMat.col_to_var.end());
- #endif
-
- origMat.col_to_var.push_back(v);
- var_to_col[v] = origMat.col_to_var.size()-1;
- var_is_in.setBit(v);
- }
- }
-
- //for the ones that were not in the order_heap, but are marked in var_to_col
- for (uint v = 0; v != var_to_col.size(); v++) {
- if (var_to_col[v] == unassigned_col - 1) {
- origMat.col_to_var.push_back(v);
- var_to_col[v] = origMat.col_to_var.size() -1;
- var_is_in.setBit(v);
- }
- }
-
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")col_to_var:";
- std::copy(origMat.col_to_var.begin(), origMat.col_to_var.end(), std::ostream_iterator<uint>(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(char)*changed_rows.size());
-
- origMat.last_one_in_col.resize(origMat.num_cols);
- std::fill(origMat.last_one_in_col.begin(), origMat.last_one_in_col.end(), origMat.num_rows);
- origMat.first_one_in_row.resize(origMat.num_rows);
-
- origMat.removeable_cols = 0;
- origMat.least_column_changed = -1;
- origMat.matrix.resize(origMat.num_rows, origMat.num_cols);
-
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")matrix size:" << origMat.num_rows << "," << origMat.num_cols << endl;
- #endif
-
- uint matrix_row = 0;
- for (uint32_t i = 0; i != xorclauses.size(); i++) {
- const XorClause& c = *xorclauses[i];
-
- origMat.matrix.getVarsetAt(matrix_row).set(c, var_to_col, origMat.num_cols);
- origMat.matrix.getMatrixAt(matrix_row).set(c, var_to_col, origMat.num_cols);
- matrix_row++;
- }
- assert(origMat.num_rows == matrix_row);
-}
-
-void Gaussian::update_matrix_col(matrixset& m, const Var var, const uint col)
-{
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")Updating matrix var " << var+1 << " (col " << col << ", m.last_one_in_col[col]: " << m.last_one_in_col[col] << ")" << endl;
- cout << "m.num_rows:" << m.num_rows << endl;
- #endif
-
- #ifdef DEBUG_GAUSS
- assert(col < m.num_cols);
- #endif
-
- m.least_column_changed = std::min(m.least_column_changed, (int)col);
- PackedMatrix::iterator this_row = m.matrix.beginMatrix();
- uint row_num = 0;
-
- if (solver.assigns[var].getBool()) {
- for (uint end = m.last_one_in_col[col]; row_num != end; ++this_row, row_num++) {
- if ((*this_row)[col]) {
- changed_rows[row_num] = true;
- (*this_row).invert_is_true();
- (*this_row).clearBit(col);
- }
- }
- } else {
- for (uint end = m.last_one_in_col[col]; row_num != end; ++this_row, row_num++) {
- if ((*this_row)[col]) {
- changed_rows[row_num] = true;
- (*this_row).clearBit(col);
- }
- }
- }
-
- #ifdef DEBUG_GAUSS
- bool c = false;
- for(PackedMatrix::iterator r = m.matrix.beginMatrix(), end = r + m.matrix.getSize(); r != end; ++r)
- c |= (*r)[col];
- assert(!c);
- #endif
-
- m.removeable_cols++;
- m.col_to_var[col] = unassigned_var;
- m.var_is_set.setBit(var);
-}
-
-void Gaussian::update_matrix_by_col_all(matrixset& m)
-{
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")Updating matrix." << endl;
- print_matrix(m);
- uint num_updated = 0;
- #endif
-
- #ifdef DEBUG_GAUSS
- assert(nothing_to_propagate(cur_matrixset));
- assert(solver.decisionLevel() == 0 || check_last_one_in_cols(m));
- #endif
-
- memset(&changed_rows[0], 0, sizeof(char)*changed_rows.size());
-
- uint last = 0;
- uint col = 0;
- for (const Var *it = &m.col_to_var[0], *end = it + m.num_cols; it != end; col++, it++) {
- if (*it != unassigned_var && solver.assigns[*it].isDef()) {
- update_matrix_col(m, *it, col);
- last++;
- #ifdef VERBOSE_DEBUG
- num_updated++;
- #endif
- } else
- last = 0;
- }
- m.num_cols -= last;
-
- #ifdef DEBUG_GAUSS
- check_matrix_against_varset(m.matrix, m);
- #endif
-
- #ifdef VERBOSE_DEBUG
- cout << "Matrix update finished, updated " << num_updated << " cols" << endl;
- print_matrix(m);
- #endif
-
- /*cout << "num_rows:" << m.num_rows;
- cout << " num_rows diff:" << origMat.num_rows - m.num_rows << endl;
- cout << "num_cols:" << col_to_var_original.size();
- cout << " num_cols diff:" << col_to_var_original.size() - m.col_to_var.size() << endl;
- cout << "removeable cols:" << m.removeable_cols << endl;*/
-}
-
-inline void Gaussian::update_last_one_in_col(matrixset& m)
-{
- for (uint16_t* i = &m.last_one_in_col[0]+m.last_one_in_col.size()-1, *end = &m.last_one_in_col[0]-1; i != end && *i >= m.num_rows; i--)
- *i = m.num_rows;
-}
-
-Gaussian::gaussian_ret Gaussian::gaussian(Clause*& confl)
-{
- if (solver.decisionLevel() >= badlevel)
- return nothing;
-
- if (messed_matrix_vars_since_reversal) {
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")matrix needs copy before update" << endl;
- #endif
-
- const uint level = solver.decisionLevel() / config.only_nth_gauss_save;
- assert(level < matrix_sets.size());
- cur_matrixset = matrix_sets[level];
- }
- update_last_one_in_col(cur_matrixset);
- update_matrix_by_col_all(cur_matrixset);
-
- messed_matrix_vars_since_reversal = false;
- gauss_last_level = solver.trail.size();
- badlevel = UINT_MAX;
-
- propagatable_rows.clear();
- uint conflict_row = UINT_MAX;
- uint last_row = eliminate(cur_matrixset, conflict_row);
- #ifdef DEBUG_GAUSS
- check_matrix_against_varset(cur_matrixset.matrix, cur_matrixset);
- #endif
-
- gaussian_ret ret;
- //There is no early abort, so this is unneeded
- /*if (conflict_row != UINT_MAX) {
- uint maxlevel = UINT_MAX;
- uint size = UINT_MAX;
- uint best_row = UINT_MAX;
- analyse_confl(cur_matrixset, conflict_row, maxlevel, size, best_row);
- ret = handle_matrix_confl(confl, cur_matrixset, size, maxlevel, best_row);
- } else {*/
- ret = handle_matrix_prop_and_confl(cur_matrixset, last_row, confl);
- //}
- #ifdef DEBUG_GAUSS
- assert(ret == conflict || nothing_to_propagate(cur_matrixset));
- #endif
-
- if (!cur_matrixset.num_cols || !cur_matrixset.num_rows) {
- badlevel = solver.decisionLevel();
- return nothing;
- }
-
- if (ret == nothing &&
- solver.decisionLevel() % config.only_nth_gauss_save == 0)
- set_matrixset_to_cur();
-
- #ifdef VERBOSE_DEBUG
- if (ret == nothing)
- cout << "(" << matrix_no << ")Useless. ";
- else
- cout << "(" << matrix_no << ")Useful. ";
- cout << "(" << matrix_no << ")Useful prop in " << ((double)useful_prop/(double)called)*100.0 << "%" << endl;
- cout << "(" << matrix_no << ")Useful confl in " << ((double)useful_confl/(double)called)*100.0 << "%" << endl;
- #endif
-
- return ret;
-}
-
-uint Gaussian::eliminate(matrixset& m, uint& conflict_row)
-{
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")";
- cout << "Starting elimination" << endl;
- cout << "m.least_column_changed:" << m.least_column_changed << endl;
- print_last_one_in_cols(m);
-
- uint number_of_row_additions = 0;
- uint no_exchanged = 0;
- #endif
-
- if (m.least_column_changed == INT_MAX) {
- #ifdef VERBOSE_DEBUG
- cout << "Nothing to eliminate" << endl;
- #endif
-
- return m.num_rows;
- }
-
-
- #ifdef DEBUG_GAUSS
- assert(solver.decisionLevel() == 0 || check_last_one_in_cols(m));
- #endif
-
- uint i = 0;
- uint j = m.least_column_changed + 1;
- PackedMatrix::iterator beginIt = m.matrix.beginMatrix();
- PackedMatrix::iterator rowIt = m.matrix.beginMatrix();
-
- #ifdef DEBUG_GAUSS
- check_first_one_in_row(m, j);
- #endif
-
- if (j) {
- uint16_t until = std::min(m.last_one_in_col[m.least_column_changed] - 1, (int)m.num_rows);
- if (j-1 > m.first_one_in_row[m.num_rows-1])
- until = m.num_rows;
- for (;i != until; i++, ++rowIt) if (changed_rows[i] && (*rowIt).popcnt_is_one(m.first_one_in_row[i]))
- propagatable_rows.push(i);
- }
-
- #ifdef VERBOSE_DEBUG
- cout << "At while() start: i,j = " << i << ", " << j << endl;
- cout << "num_rows:" << m.num_rows << " num_cols:" << m.num_cols << endl;
- #endif
-
- if (j > m.num_cols) {
- #ifdef VERBOSE_DEBUG
- cout << "Going straight to finish" << endl;
- #endif
- goto finish;
- }
-
- #ifdef DEBUG_GAUSS
- assert(i <= m.num_rows && j <= m.num_cols);
- #endif
-
- while (i != m.num_rows && j != m.num_cols) {
- //Find pivot in column j, starting in row i:
-
- if (m.col_to_var[j] == unassigned_var) {
- j++;
- continue;
- }
-
- PackedMatrix::iterator this_matrix_row = rowIt;
- PackedMatrix::iterator end = beginIt + m.last_one_in_col[j];
- for (; this_matrix_row != end; ++this_matrix_row) {
- if ((*this_matrix_row)[j])
- break;
- }
-
- if (this_matrix_row != end) {
-
- //swap rows i and maxi, but do not change the value of i;
- if (this_matrix_row != rowIt) {
- #ifdef VERBOSE_DEBUG
- no_exchanged++;
- #endif
-
- //Would early abort, but would not find the best conflict (and would be expensive)
- //if (matrix_row_i.is_true() && matrix_row_i.isZero()) {
- // conflict_row = i;
- // return 0;
- //}
- (*rowIt).swapBoth(*this_matrix_row);
- }
- #ifdef DEBUG_GAUSS
- assert(m.matrix.getMatrixAt(i).popcnt(j) == m.matrix.getMatrixAt(i).popcnt());
- assert(m.matrix.getMatrixAt(i)[j]);
- #endif
-
- if ((*rowIt).popcnt_is_one(j))
- propagatable_rows.push(i);
-
- //Now A[i,j] will contain the old value of A[maxi,j];
- ++this_matrix_row;
- for (; this_matrix_row != end; ++this_matrix_row) if ((*this_matrix_row)[j]) {
- //subtract row i from row u;
- //Now A[u,j] will be 0, since A[u,j] - A[i,j] = A[u,j] -1 = 0.
- #ifdef VERBOSE_DEBUG
- number_of_row_additions++;
- #endif
-
- (*this_matrix_row).xorBoth(*rowIt);
- //Would early abort, but would not find the best conflict (and would be expensive)
- //if (it->is_true() &&it->isZero()) {
- // conflict_row = i2;
- // return 0;
- //}
- }
- m.first_one_in_row[i] = j;
- i++;
- ++rowIt;
- m.last_one_in_col[j] = i;
- } else {
- m.first_one_in_row[i] = j;
- m.last_one_in_col[j] = i + 1;
- }
- j++;
- }
-
- finish:
-
- m.least_column_changed = INT_MAX;
-
- #ifdef VERBOSE_DEBUG
- cout << "Finished elimination" << endl;
- cout << "Returning with i,j:" << i << ", " << j << "(" << m.num_rows << ", " << m.num_cols << ")" << endl;
- print_matrix(m);
- print_last_one_in_cols(m);
- cout << "(" << matrix_no << ")Exchanged:" << no_exchanged << " row additions:" << number_of_row_additions << endl;
- #endif
-
- #ifdef DEBUG_GAUSS
- assert(check_last_one_in_cols(m));
- uint row = 0;
- uint col = 0;
- for (; col < m.num_cols && row < m.num_rows && row < i ; col++) {
- assert(m.matrix.getMatrixAt(row).popcnt() == m.matrix.getMatrixAt(row).popcnt(col));
- assert(!(m.col_to_var[col] == unassigned_var && m.matrix.getMatrixAt(row)[col]));
- if (m.col_to_var[col] == unassigned_var || !m.matrix.getMatrixAt(row)[col]) {
- #ifdef VERBOSE_DEBUG
- cout << "row:" << row << " col:" << col << " m.last_one_in_col[col]-1: " << m.last_one_in_col[col]-1 << endl;
- #endif
- assert(m.col_to_var[col] == unassigned_var || std::min((uint16_t)(m.last_one_in_col[col]-1), m.num_rows) == row);
- continue;
- }
- row++;
- }
- #endif
-
- return i;
-}
-
-Gaussian::gaussian_ret Gaussian::handle_matrix_confl(Clause*& confl, const matrixset& m, const uint size, const uint maxlevel, const uint best_row)
-{
- assert(best_row != UINT_MAX);
-
- m.matrix.getVarsetAt(best_row).fill(tmp_clause, solver.assigns, col_to_var_original);
- confl = (Clause*)XorClause_new(tmp_clause, false, solver.learnt_clause_group++);
- Clause& cla = *confl;
- #ifdef STATS_NEEDED
- if (solver.dynamic_behaviour_analysis)
- solver.logger.set_group_name(confl->getGroup(), "learnt gauss clause");
- #endif
-
- if (cla.size() <= 1)
- return unit_conflict;
-
- assert(cla.size() >= 2);
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")Found conflict:";
- cla.plainPrint();
- #endif
-
- if (maxlevel != solver.decisionLevel()) {
- #ifdef STATS_NEEDED
- if (solver.dynamic_behaviour_analysis)
- solver.logger.conflict(Logger::gauss_confl_type, maxlevel, confl->getGroup(), *confl);
- #endif
- solver.cancelUntil(maxlevel);
- }
- const uint curr_dec_level = solver.decisionLevel();
- assert(maxlevel == curr_dec_level);
-
- uint maxsublevel = 0;
- uint maxsublevel_at = UINT_MAX;
- for (uint i = 0, size = cla.size(); i != size; i++) if (solver.level[cla[i].var()] == curr_dec_level) {
- uint tmp = find_sublevel(cla[i].var());
- if (tmp >= maxsublevel) {
- maxsublevel = tmp;
- maxsublevel_at = i;
- }
- }
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ") || Sublevel of confl: " << maxsublevel << " (due to var:" << cla[maxsublevel_at].var()-1 << ")" << endl;
- #endif
-
- Lit tmp(cla[maxsublevel_at]);
- cla[maxsublevel_at] = cla[1];
- cla[1] = tmp;
-
- cancel_until_sublevel(maxsublevel+1);
- messed_matrix_vars_since_reversal = true;
- return conflict;
-}
-
-Gaussian::gaussian_ret Gaussian::handle_matrix_prop_and_confl(matrixset& m, uint last_row, Clause*& confl)
-{
- uint maxlevel = UINT_MAX;
- uint size = UINT_MAX;
- uint best_row = UINT_MAX;
-
- for (uint row = last_row; row != m.num_rows; row++) {
- #ifdef DEBUG_GAUSS
- assert(m.matrix.getMatrixAt(row).isZero());
- #endif
- if (m.matrix.getMatrixAt(row).is_true())
- analyse_confl(m, row, maxlevel, size, best_row);
- }
-
- if (maxlevel != UINT_MAX)
- return handle_matrix_confl(confl, m, size, maxlevel, best_row);
-
- #ifdef DEBUG_GAUSS
- assert(check_no_conflict(m));
- assert(last_row == 0 || !m.matrix.getMatrixAt(last_row-1).isZero());
- #endif
-
- #ifdef VERBOSE_DEBUG
- cout << "Resizing matrix to num_rows = " << last_row << endl;
- #endif
- m.num_rows = last_row;
- m.matrix.resizeNumRows(m.num_rows);
-
- gaussian_ret ret = nothing;
-
- uint num_props = 0;
- for (const uint* prop_row = propagatable_rows.getData(), *end = prop_row + propagatable_rows.size(); prop_row != end; prop_row++ ) {
- //this is a "000..1..0000000X" row. I.e. it indicates a propagation
- ret = handle_matrix_prop(m, *prop_row);
- num_props++;
- if (ret == unit_propagation) {
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")Unit prop! Breaking from prop examination" << endl;
- #endif
- return unit_propagation;
- }
- }
- #ifdef VERBOSE_DEBUG
- if (num_props > 0) cout << "(" << matrix_no << ")Number of props during gauss:" << num_props << endl;
- #endif
-
- return ret;
-}
-
-uint Gaussian::find_sublevel(const Var v) const
-{
- for (int i = solver.trail.size()-1; i >= 0; i --)
- if (solver.trail[i].var() == v) return i;
-
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")Oooops! Var " << v+1 << " does not have a sublevel!! (so it must be undefined)" << endl;
- #endif
-
- assert(false);
- return 0;
-}
-
-void Gaussian::cancel_until_sublevel(const uint sublevel)
-{
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")Canceling until sublevel " << sublevel << endl;
- #endif
-
- for (vector<Gaussian*>::iterator gauss = solver.gauss_matrixes.begin(), end= solver.gauss_matrixes.end(); gauss != end; gauss++)
- if (*gauss != this) (*gauss)->canceling(sublevel);
-
- for (int level = solver.trail.size()-1; level >= (int)sublevel; level--) {
- Var var = solver.trail[level].var();
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")Canceling var " << var+1 << endl;
- #endif
-
- solver.assigns[var] = l_Undef;
- solver.insertVarOrder(var);
- }
- solver.trail.shrink(solver.trail.size() - sublevel);
-
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")Canceling sublevel finished." << endl;
- #endif
-}
-
-void Gaussian::analyse_confl(const matrixset& m, const uint row, uint& maxlevel, uint& size, uint& best_row) const
-{
- assert(row < m.num_rows);
-
- //this is a "000...00000001" row. I.e. it indicates we are on the wrong branch
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")matrix conflict found!" << endl;
- cout << "(" << matrix_no << ")conflict clause's vars: ";
- print_matrix_row_with_assigns(m.matrix.getVarsetAt(row));
- cout << endl;
-
- cout << "(" << matrix_no << ")corresponding matrix's row (should be empty): ";
- print_matrix_row(m.matrix.getMatrixAt(row));
- cout << endl;
- #endif
-
- uint this_maxlevel = 0;
- unsigned long int var = 0;
- uint this_size = 0;
- while (true) {
- var = m.matrix.getVarsetAt(row).scan(var);
- if (var == ULONG_MAX) break;
-
- const Var real_var = col_to_var_original[var];
- assert(real_var < solver.nVars());
-
- if (solver.level[real_var] > this_maxlevel)
- this_maxlevel = solver.level[real_var];
- var++;
- this_size++;
- }
-
- //the maximum of all lit's level must be lower than the max. level of the current best clause (or this clause must be either empty or unit clause)
- if (!(
- (this_maxlevel < maxlevel)
- || (this_maxlevel == maxlevel && this_size < size)
- || (this_size <= 1)
- )) {
- assert(maxlevel != UINT_MAX);
-
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")Other found conflict just as good or better.";
- cout << "(" << matrix_no << ") || Old maxlevel:" << maxlevel << " new maxlevel:" << this_maxlevel;
- cout << "(" << matrix_no << ") || Old size:" << size << " new size:" << this_size << endl;
- //assert(!(maxlevel != UINT_MAX && maxlevel != this_maxlevel)); //NOTE: only holds if gauss is executed at each level
- #endif
-
- return;
- }
-
-
- #ifdef VERBOSE_DEBUG
- if (maxlevel != UINT_MAX)
- cout << "(" << matrix_no << ")Better conflict found.";
- else
- cout << "(" << matrix_no << ")Found a possible conflict.";
-
- cout << "(" << matrix_no << ") || Old maxlevel:" << maxlevel << " new maxlevel:" << this_maxlevel;
- cout << "(" << matrix_no << ") || Old size:" << size << " new size:" << this_size << endl;
- #endif
-
- maxlevel = this_maxlevel;
- size = this_size;
- best_row = row;
-}
-
-Gaussian::gaussian_ret Gaussian::handle_matrix_prop(matrixset& m, const uint row)
-{
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")matrix prop found!" << endl;
- cout << m.matrix.getMatrixAt(row) << endl;
- cout << "(" << matrix_no << ")matrix row:";
- print_matrix_row(m.matrix.getMatrixAt(row));
- cout << endl;
- #endif
-
- m.matrix.getVarsetAt(row).fill(tmp_clause, solver.assigns, col_to_var_original);
- Clause& cla = *(Clause*)XorClause_new(tmp_clause, false, solver.learnt_clause_group++);
- #ifdef VERBOSE_DEBUG
- cout << "(" << matrix_no << ")matrix prop clause: ";
- cla.plainPrint();
- cout << endl;
- #endif
-
- assert(m.matrix.getMatrixAt(row).is_true() == !cla[0].sign());
- assert(solver.assigns[cla[0].var()].isUndef());
- if (cla.size() == 1) {
- const Lit lit = cla[0];
-
- solver.cancelUntil(0);
- solver.uncheckedEnqueue(lit);
- free(&cla);
- return unit_propagation;
- }
-
- clauses_toclear.push_back(std::make_pair(&cla, solver.trail.size()-1));
- #ifdef STATS_NEEDED
- if (solver.dynamic_behaviour_analysis)
- solver.logger.set_group_name(cla.getGroup(), "gauss prop clause");
- #endif
- solver.uncheckedEnqueue(cla[0], &cla);
-
- return propagation;
-}
-
-void Gaussian::disable_if_necessary()
-{
- if (//nof_conflicts >= 0
- //&& conflictC >= nof_conflicts/8
- !config.dontDisable
- && called > 50
- && useful_confl*2+useful_prop < (uint)((double)called*0.05) )
- disabled = true;
-}
-
-llbool Gaussian::find_truths(vec<Lit>& learnt_clause, int& conflictC)
-{
- Clause* confl;
-
- disable_if_necessary();
- if (should_check_gauss(solver.decisionLevel(), solver.starts)) {
- called++;
- gaussian_ret g = gaussian(confl);
-
- switch (g) {
- case conflict: {
- useful_confl++;
- llbool ret = solver.handle_conflict(learnt_clause, confl, conflictC, true);
- clauseFree(confl);
-
- if (ret != l_Nothing) return ret;
- return l_Continue;
- }
- case propagation:
- case unit_propagation:
- useful_prop++;
- return l_Continue;
- case unit_conflict: {
- useful_confl++;
- if (confl->size() == 0) {
- free(confl);
- return l_False;
- }
-
- Lit lit = (*confl)[0];
- #ifdef STATS_NEEDED
- if (solver.dynamic_behaviour_analysis)
- solver.logger.conflict(Logger::gauss_confl_type, 0, confl->getGroup(), *confl);
- #endif
-
- solver.cancelUntil(0);
-
- if (solver.assigns[lit.var()].isDef()) {
- clauseFree(confl);
- return l_False;
- }
-
- solver.uncheckedEnqueue(lit);
-
- clauseFree(confl);
- return l_Continue;
- }
- case nothing:
- break;
- }
- }
-
- return l_Nothing;
-}
-
-template<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 << "xor_clause_inverted";
-}
-
-const string Gaussian::lbool_to_string(const lbool toprint)
-{
- if (toprint == l_True)
- return "true";
- if (toprint == l_False)
- return "false";
- if (toprint == l_Undef)
- return "undef";
-
- assert(false);
- return "";
-}
-
-
-void Gaussian::print_stats() const
-{
- if (called > 0) {
- cout.setf(std::ios::fixed);
- std::cout << " Gauss(" << matrix_no << ") useful";
- cout << " prop: " << std::setprecision(2) << std::setw(5) << ((double)useful_prop/(double)called)*100.0 << "% ";
- cout << " confl: " << std::setprecision(2) << std::setw(5) << ((double)useful_confl/(double)called)*100.0 << "% ";
- if (disabled) std::cout << "disabled";
- } else
- std::cout << " Gauss(" << matrix_no << ") not called.";
-}
-
-void Gaussian::print_matrix_stats() const
-{
- cout << "matrix size: " << cur_matrixset.num_rows << " x " << cur_matrixset.num_cols << endl;
-}
-
-
-void Gaussian::reset_stats()
-{
- useful_prop = 0;
- useful_confl = 0;
- called = 0;
- disabled = false;
-}
-
-bool Gaussian::check_no_conflict(matrixset& m) const
-{
- uint row = 0;
- for(PackedMatrix::iterator r = m.matrix.beginMatrix(), end = m.matrix.endMatrix(); r != end; ++r, ++row) {
- if ((*r).is_true() && (*r).isZero()) {
- cout << "Conflict at row " << row << endl;
- return false;
- }
- }
- return true;
-}
-
-void Gaussian::print_matrix(matrixset& m) const
-{
- uint row = 0;
- for (PackedMatrix::iterator it = m.matrix.beginMatrix(); it != m.matrix.endMatrix(); ++it, row++) {
- cout << *it << " -- row:" << row;
- if (row >= m.num_rows)
- cout << " (considered past the end)";
- cout << endl;
- }
-}
-
-void Gaussian::print_last_one_in_cols(matrixset& m) const
-{
- for (uint i = 0; i < m.num_cols; i++) {
- cout << "last_one_in_col[" << i << "]-1 = " << m.last_one_in_col[i]-1 << endl;
- }
-}
-
-const bool Gaussian::nothing_to_propagate(matrixset& m) const
-{
- for(PackedMatrix::iterator r = m.matrix.beginMatrix(), end = m.matrix.endMatrix(); r != end; ++r) {
- if ((*r).popcnt_is_one()
- && solver.assigns[m.col_to_var[(*r).scan(0)]].isUndef())
- return false;
- }
- for(PackedMatrix::iterator r = m.matrix.beginMatrix(), end = m.matrix.endMatrix(); r != end; ++r) {
- if ((*r).isZero() && (*r).is_true())
- return false;
- }
- return true;
-}
-
-const bool Gaussian::check_last_one_in_cols(matrixset& m) const
-{
- for(uint i = 0; i < m.num_cols; i++) {
- const uint last = std::min(m.last_one_in_col[i] - 1, (int)m.num_rows);
- uint real_last = 0;
- uint i2 = 0;
- for (PackedMatrix::iterator it = m.matrix.beginMatrix(); it != m.matrix.endMatrix(); ++it, i2++) {
- if ((*it)[i])
- real_last = i2;
- }
- if (real_last > last)
- return false;
- }
-
- return true;
-}
-
-void Gaussian::check_matrix_against_varset(PackedMatrix& matrix, const matrixset& m) const
-{
- for (uint i = 0; i < matrix.getSize(); i++) {
- const PackedRow mat_row = matrix.getMatrixAt(i);
- const PackedRow var_row = matrix.getVarsetAt(i);
-
- unsigned long int col = 0;
- bool final = false;
- while (true) {
- col = var_row.scan(col);
- if (col == ULONG_MAX) break;
-
- const Var var = col_to_var_original[col];
- assert(var < solver.nVars());
-
- if (solver.assigns[var] == l_True) {
- assert(!mat_row[col]);
- assert(m.col_to_var[col] == unassigned_var);
- assert(m.var_is_set[var]);
- final = !final;
- } else if (solver.assigns[var] == l_False) {
- assert(!mat_row[col]);
- assert(m.col_to_var[col] == unassigned_var);
- assert(m.var_is_set[var]);
- } else if (solver.assigns[var] == l_Undef) {
- assert(m.col_to_var[col] != unassigned_var);
- assert(!m.var_is_set[var]);
- assert(mat_row[col]);
- } else assert(false);
-
- col++;
- }
- if ((final^!mat_row.is_true()) != !var_row.is_true()) {
- cout << "problem with row:"; print_matrix_row_with_assigns(var_row); cout << endl;
- assert(false);
- }
- }
-}
-
-const void Gaussian::check_first_one_in_row(matrixset& m, const uint j)
-{
- if (j) {
- uint16_t until2 = std::min(m.last_one_in_col[m.least_column_changed] - 1, (int)m.num_rows);
- if (j-1 > m.first_one_in_row[m.num_rows-1]) {
- until2 = m.num_rows;
- #ifdef VERBOSE_DEBUG
- cout << "j-1 > m.first_one_in_row[m.num_rows-1]" << "j:" << j << " m.first_one_in_row[m.num_rows-1]:" << m.first_one_in_row[m.num_rows-1] << endl;
- #endif
- }
- for (uint i2 = 0; i2 != until2; i2++) {
- #ifdef VERBOSE_DEBUG
- cout << endl << "row " << i2 << " (num rows:" << m.num_rows << ")" << endl;
- cout << m.matrix.getMatrixAt(i2) << endl;
- cout << " m.first_one_in_row[m.num_rows-1]:" << m.first_one_in_row[m.num_rows-1] << endl;
- cout << "first_one_in_row:" << m.first_one_in_row[i2] << endl;
- cout << "num_cols:" << m.num_cols << endl;
- cout << "popcnt:" << m.matrix.getMatrixAt(i2).popcnt() << endl;
- cout << "popcnt_is_one():" << m.matrix.getMatrixAt(i2).popcnt_is_one() << endl;
- cout << "popcnt_is_one("<< m.first_one_in_row[i2] <<"): " << m.matrix.getMatrixAt(i2).popcnt_is_one(m.first_one_in_row[i2]) << endl;
- #endif
-
- for (uint i3 = 0; i3 < m.first_one_in_row[i2]; i3++) {
- assert(m.matrix.getMatrixAt(i2)[i3] == 0);
- }
- assert(m.matrix.getMatrixAt(i2)[m.first_one_in_row[i2]]);
- assert(m.matrix.getMatrixAt(i2).popcnt_is_one() ==
- m.matrix.getMatrixAt(i2).popcnt_is_one(m.first_one_in_row[i2]));
- }
- }
-}
-
-const uint Gaussian::get_called() const
-{
- return called;
-}
-
-const uint Gaussian::get_useful_prop() const
-{
- return useful_prop;
-}
-
-const uint Gaussian::get_useful_confl() const
-{
- return useful_confl;
-}
-
-const bool Gaussian::get_disabled() const
-{
- return disabled;
-}
-
-void Gaussian::set_disabled(const bool toset)
-{
- disabled = toset;
-}
-
-//old functions
-
-/*void Gaussian::update_matrix_by_row(matrixset& m) const
-{
-#ifdef VERBOSE_DEBUG
- cout << "Updating matrix." << endl;
- uint num_updated = 0;
-#endif
-#ifdef DEBUG_GAUSS
- assert(nothing_to_propagate(cur_matrixset));
-#endif
-
- mpz_class toclear, tocount;
- uint last_col = 0;
-
- for (uint col = 0; col < m.num_cols; col ++) {
- Var var = m.col_to_var[col];
-
- if (var != UINT_MAX && !solver.assigns[var].isUndef()) {
- toclear.setBit(col);
- if (solver.assigns[var].getBool()) tocount.setBit(col);
-
-#ifdef DEBUG_GAUSS
- assert(m.var_to_col[var] < UINT_MAX-1);
-#endif
- last_col = col;
- m.least_column_changed = std::min(m.least_column_changed, (int)col);
-
- m.removeable_cols++;
- m.col_to_var[col] = UINT_MAX;
- m.var_to_col[var] = UINT_MAX-1;
-#ifdef VERBOSE_DEBUG
- num_updated++;
-#endif
- }
- }
-
- toclear.invert();
- mpz_class tmp;
- mpz_class* this_row = &m.matrix[0];
- for(uint i = 0, until = std::min(m.num_rows, m.last_one_in_col[last_col]+1); i < until; i++, this_row++) {
- mpz_class& r = *this_row;
- mpz_and(tmp.get_mp(), tocount.get_mp(), r.get_mp());
- r.invert_is_true(tmp.popcnt() % 2);
- r &= toclear;
-}
-
-#ifdef VERBOSE_DEBUG
- cout << "Updated " << num_updated << " matrix cols. Could remove " << m.removeable_cols << " cols " <<endl;
-#endif
-}*/
-
-/*void Gaussian::update_matrix_by_col(matrixset& m, const uint last_level) const
-{
-#ifdef VERBOSE_DEBUG
- cout << "Updating matrix." << endl;
- uint num_updated = 0;
-#endif
-#ifdef DEBUG_GAUSS
- assert(nothing_to_propagate(cur_matrixset));
-#endif
-
- for (int level = solver.trail.size()-1; level >= last_level; level--){
- Var var = solver.trail[level].var();
- const uint col = m.var_to_col[var];
- if ( col < UINT_MAX-1) {
- update_matrix_col(m, var, col);
-#ifdef VERBOSE_DEBUG
- num_updated++;
-#endif
- }
- }
-
-#ifdef VERBOSE_DEBUG
- cout << "Updated " << num_updated << " matrix cols. Could remove " << m.removeable_cols << " cols (out of " << m.num_cols << " )" <<endl;
-#endif
-}*/
-
-}; //NAMESPACE MINISAT
-/***********************************************************************************
-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>
-#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
-
-#ifdef VERBOSE_DEBUG
-using std::vector;
-using std::cout;
-using std::endl;
-#endif
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
-class Clause;
-
-static const uint16_t unassigned_col = std::numeric_limits<uint16_t>::max();
-static const Var unassigned_var = std::numeric_limits<Var>::max();
-
-class Gaussian
-{
-public:
- Gaussian(Solver& solver, const GaussianConfig& config, const uint matrix_no, const vector<XorClause*>& xorclauses);
- ~Gaussian();
-
- llbool full_init();
- llbool find_truths(vec<Lit>& learnt_clause, int& conflictC);
-
- //statistics
- void print_stats() const;
- void print_matrix_stats() const;
- const uint get_called() const;
- const uint get_useful_prop() const;
- const uint get_useful_confl() const;
- const bool get_disabled() const;
- void set_disabled(const bool toset);
-
- //functions used throughout the Solver
- void canceling(const uint sublevel);
-
-protected:
- Solver& solver;
-
- //Gauss high-level configuration
- const GaussianConfig& config;
- const uint matrix_no;
- vector<XorClause*> xorclauses;
-
- enum gaussian_ret {conflict, unit_conflict, propagation, unit_propagation, nothing};
- gaussian_ret gaussian(Clause*& confl);
-
- vector<Var> col_to_var_original; //Matches columns to variables
- BitArray var_is_in; //variable is part of the the matrix. var_is_in's size is _minimal_ so you should check whether var_is_in.getSize() < var before issuing var_is_in[var]
- uint badlevel;
-
- 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)
- uint num_cols; // number of active columns in the matrix. The columns at the end that have all be zeroed are no longer active
- int least_column_changed; // when updating the matrix, this value contains the smallest column number that has been updated (Gauss elim. can start from here instead of from column 0)
- vector<uint16_t> last_one_in_col; //last_one_in_col[COL] tells the last row+1 that has a '1' in that column. Used to reduce the burden of Gauss elim. (it only needs to look until that row)
- vector<uint16_t> first_one_in_row;
- uint removeable_cols; // the number of columns that have been zeroed out (i.e. assigned)
- };
-
- //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*, uint> > clauses_toclear;
- bool disabled; // Gauss is disabled
-
- //State of current elimnation
- vec<uint> propagatable_rows; //used to store which rows were deemed propagatable during elimination
- vector<unsigned char> changed_rows; //used to store which rows were deemed propagatable during elimination
-
- //Statistics
- uint useful_prop; //how many times Gauss gave propagation as a result
- uint useful_confl; //how many times Gauss gave conflict as a result
- uint called; //how many times called the Gauss
-
- //gauss init functions
- void init(); // Initalise gauss state
- void fill_matrix(matrixset& origMat); // Fills the origMat matrix
- uint select_columnorder(vector<uint16_t>& var_to_col, matrixset& origMat); // Fills var_to_col and col_to_var of the origMat matrix.
-
- //Main function
- uint eliminate(matrixset& matrix, uint& conflict_row); //does the actual gaussian elimination
-
- //matrix update functions
- void update_matrix_col(matrixset& matrix, const Var x, const uint col); // Update one matrix column
- void update_matrix_by_col_all(matrixset& m); // Update all columns, column-by-column (and not row-by-row)
- void set_matrixset_to_cur(); // Save the current matrixset, the cur_matrixset to matrix_sets
- //void update_matrix_by_row(matrixset& matrix) const;
- //void update_matrix_by_col(matrixset& matrix, const uint last_level) const;
-
- //conflict&propagation handling
- gaussian_ret handle_matrix_prop_and_confl(matrixset& m, uint row, Clause*& confl);
- void analyse_confl(const matrixset& m, const uint row, uint& maxlevel, uint& size, uint& best_row) const; // analyse conflcit to find the best conflict. Gets & returns the best one in 'maxlevel', 'size' and 'best row' (these are all UINT_MAX when calling this function first, i.e. when there is no other possible conflict to compare to the new in 'row')
- gaussian_ret handle_matrix_confl(Clause*& confl, const matrixset& m, const uint size, const uint maxlevel, const uint best_row);
- gaussian_ret handle_matrix_prop(matrixset& m, const uint row); // Handle matrix propagation at row 'row'
- vec<Lit> tmp_clause;
-
- //propagation&conflict handling
- void cancel_until_sublevel(const uint sublevel); // cancels until sublevel 'sublevel'. The var 'sublevel' must NOT go over the current level. I.e. this function is ONLY for moving inside the current level
- uint find_sublevel(const Var v) const; // find the sublevel (i.e. trail[X]) of a given variable
-
- //helper functions
- bool at_first_init() const;
- bool should_init() const;
- bool should_check_gauss(const uint decisionlevel, const uint starts) const;
- void disable_if_necessary();
- void reset_stats();
- void update_last_one_in_col(matrixset& m);
-
-private:
-
- //debug functions
- bool check_no_conflict(matrixset& m) const; // Are there any conflicts that the matrixset 'm' causes?
- const bool nothing_to_propagate(matrixset& m) const; // Are there any conflicts of propagations that matrixset 'm' clauses?
- template<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;
- const bool check_last_one_in_cols(matrixset& m) const;
- const void check_first_one_in_row(matrixset& m, const uint j);
- void print_matrix(matrixset& m) const;
- void print_last_one_in_cols(matrixset& m) const;
- static const string lbool_to_string(const lbool toprint);
-};
-
-inline bool Gaussian::should_init() const
-{
- return (config.decision_until > 0);
-}
-
-inline bool Gaussian::should_check_gauss(const uint decisionlevel, const uint starts) const
-{
- return (!disabled
- && decisionlevel < config.decision_until);
-}
-
-inline void Gaussian::canceling(const uint sublevel)
-{
- if (disabled)
- return;
- uint a = 0;
- for (int i = clauses_toclear.size()-1; i >= 0 && clauses_toclear[i].second > sublevel; i--) {
- clauseFree(clauses_toclear[i].first);
- a++;
- }
- clauses_toclear.resize(clauses_toclear.size()-a);
-
- if (messed_matrix_vars_since_reversal)
- return;
- int c = std::min((int)gauss_last_level, (int)(solver.trail.size())-1);
- for (; c >= (int)sublevel; c--) {
- Var var = solver.trail[c].var();
- if (var < var_is_in.getSize()
- && var_is_in[var]
- && cur_matrixset.var_is_set[var]) {
- messed_matrix_vars_since_reversal = true;
- return;
- }
- }
-}
-
-std::ostream& operator << (std::ostream& os, const vec<Lit>& v);
-
-}; //NAMESPACE MINISAT
-
-#endif //GAUSSIAN_H
-/***********************************************************************************
-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 MINISAT
-{
-using namespace MINISAT;
-
-class GaussianConfig
-{
- public:
-
- GaussianConfig() :
- only_nth_gauss_save(2)
- , decision_until(0)
- , dontDisable(false)
- {
- }
-
- //tuneable gauss parameters
- uint only_nth_gauss_save; //save only every n-th gauss matrix
- uint decision_until; //do Gauss until this level
- bool dontDisable; //If activated, gauss elimination is never disabled
-};
-
-}; //NAMESPACE MINISAT
-
-#endif //GAUSSIANCONFIG_H
-/***********************************************************************************
-CryptoMiniSat -- Copyright (c) 2009 Mate Soos
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
-associated documentation files (the "Software"), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge, publish, distribute,
-sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or
-substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
-NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
-OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-**************************************************************************************************/
-
-#include <time.h>
-#include <cstring>
-#include <algorithm>
-#include <vector>
-#include <iostream>
-#include <iomanip>
-#include <fstream>
-#include <sstream>
-#include <limits>
-using std::cout;
-using std::endl;
-using std::ofstream;
-
-#include "Logger.h"
-#include "SolverTypes.h"
-#include "Solver.h"
-#include "Gaussian.h"
-
-#define FST_WIDTH 10
-#define SND_WIDTH 35
-#define TRD_WIDTH 10
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
-Logger::Logger(int& _verbosity) :
- proof_graph_on(false)
- , mini_proof(false)
- , statistics_on(false)
-
- , max_print_lines(20)
- , uniqueid(1)
-
- , proof(NULL)
-
- , sum_conflict_depths(0)
- , no_conflicts(0)
- , no_decisions(0)
- , no_propagations(0)
- , sum_decisions_on_branches(0)
- , sum_propagations_on_branches(0)
-
- , verbosity(_verbosity)
- , begin_called(false)
- , proofStarts(0)
-{
- runid /= 10;
- runid = time(NULL) % 10000;
- if (verbosity >= 1) printf("c RunID is: #%d\n",runid);
-}
-
-void Logger::setSolver(const Solver* _s)
-{
- S = _s;
-}
-
-// Adds a new variable to the knowledge of the logger
-void Logger::new_var(const Var var)
-{
- if (!statistics_on && !proof_graph_on)
- return;
-
- if (varnames.size() <= var) {
- varnames.resize(var+1, "Noname");
- times_var_propagated.resize(var+1, 0);
- times_var_guessed.resize(var+1, 0);
- depths_of_assigns_for_var.resize(var+1);
- depths_of_assigns_unit.resize(var+1, false);
- }
-}
-
-// Resizes the groupnames and other, related vectors to accomodate for a new group
-void Logger::new_group(const uint group)
-{
- if (groupnames.size() <= group) {
- groupnames.resize(group+1, "Noname");
- times_group_caused_conflict.resize(group+1, 0);
- times_group_caused_propagation.resize(group+1, 0);
- depths_of_propagations_for_group.resize(group+1);
- depths_of_propagations_unit.resize(group+1, false);
- depths_of_conflicts_for_group.resize(group+1);
- }
-}
-
-void Logger::cut_name_to_size(string& name) const
-{
- uint len = name.length();
- while(len > 0 && (name[len-1] == ' ' || name[len-1] == 0x0A || name[len-1] == 0x0D)) {
- name[len-1] = '\0';
- name.resize(len-1);
- len--;
- }
-
- if (len > SND_WIDTH-2) {
- name[SND_WIDTH-2] = '\0';
- name[SND_WIDTH-3] = '.';
- name[SND_WIDTH-4] = '.';
- }
-}
-
-// Adds the new clause group's name to the information stored
-void Logger::set_group_name(const uint group, char* name_tmp)
-{
- if (!statistics_on && !proof_graph_on)
- return;
-
- string name;
- if (name_tmp == NULL) return;
- else name = name_tmp;
-
- new_group(group);
- cut_name_to_size(name);
-
- if (name == "Noname") return;
-
- if (groupnames[group] == "Noname") {
- groupnames[group] = name;
- } else if (groupnames[group] != name) {
- std::cout << "Error! Group no. " << group << "has been named twice. First, as '" << groupnames[group] << "', then second as '" << name << "'. Name the same group the same always, or don't give a name to the second iteration of the same group (i.e just write 'c g groupnumber' on the line" << std::endl;
- exit(-1);
- }
-}
-
-// sets the variable's name
-void Logger::set_variable_name(const uint var, char* name_tmp)
-{
- if (!statistics_on && !proof_graph_on)
- return;
-
- new_var(var);
-
- string name;
- if (name_tmp == NULL)
- name = "";
- else
- name = name_tmp;
-
- cut_name_to_size(name);
-
- if (varnames[var] == "Noname") {
- varnames[var] = name;
- } else if (varnames[var] != name) {
- printf("Error! Variable no. %d has been named twice. First, as '%s', then second as '%s'. Name the same group the same always, or don't give a name to the second iteration of the same group (i.e just write 'c g groupnumber' on the line\n", var+1, varnames[var].c_str(), name.c_str());
- exit(-1);
- }
-}
-
-void Logger::first_begin()
-{
- if (begin_called)
- return;
-
- begin();
-}
-
-void Logger::begin()
-{
- begin_called = true;
- if (proof_graph_on) {
- std::stringstream filename;
- filename << "proofs/" << runid << "-proof" << proofStarts++ << "-" << S->starts << ".dot";
-
- if (S->starts == 0)
- history.push_back(uniqueid);
- else {
- if (mini_proof)
- history.resize(S->decisionLevel()+1);
- else
- history.resize(S->trail.size()+1);
- }
-
- proof = fopen(filename.str().c_str(),"w");
- if (!proof) printf("Couldn't open proof file '%s' for writing\n", filename.str().c_str()), exit(-1);
- fprintf(proof, "digraph G {\n");
- fprintf(proof,"node%d [shape=circle, label=\"BEGIN\", root];\n", history[history.size()-1]);
- }
-
- if (statistics_on)
- reset_statistics();
-}
-
-// For noting conflicts. Updates the proof graph and the statistics.
-template<class T>
-void Logger::conflict(const confl_type type, const uint goback_level, const uint group, const T& learnt_clause)
-{
- first_begin();
- assert(!(proof == NULL && proof_graph_on));
-
- const uint goback_sublevel = S->trail_lim[goback_level];
-
- if (proof_graph_on) {
- uniqueid++;
- fprintf(proof,"node%d [shape=polygon,sides=5,label=\"",uniqueid);
-
- if (!mini_proof) {
- for (uint32_t i = 0; i != learnt_clause.size(); i++) {
- if (learnt_clause[i].sign()) fprintf(proof,"-");
- int myvar = learnt_clause[i].var();
- if (varnames[myvar] != "Noname")
- fprintf(proof,"%s\\n",varnames[myvar].c_str());
- else
- fprintf(proof,"Var: %d\\n",myvar);
- }
- }
- fprintf(proof,"\"];\n");
-
- fprintf(proof,"node%d -> node%d [label=\"",history[history.size()-1],uniqueid);
- if (type == gauss_confl_type)
- fprintf(proof,"Gauss\",style=bold");
- else
- fprintf(proof,"%s\"", groupnames[group].c_str());
- fprintf(proof,"];\n");
-
- if (!mini_proof)
- history.resize(goback_sublevel+1);
- else
- history.resize(goback_level+1);
- fprintf(proof,"node%d -> node%d [style=dotted];\n",uniqueid,history[history.size()-1]);
- }
-
- if (statistics_on) {
- times_group_caused_conflict[group]++;
- depths_of_conflicts_for_group[group].sum += S->decisionLevel();
- depths_of_conflicts_for_group[group].num ++;
-
- no_conflicts++;
- sum_conflict_depths += S->trail.size() - S->trail_lim[0];
- sum_decisions_on_branches += S->decisionLevel();
- sum_propagations_on_branches += S->trail.size() - S->trail_lim[0] - S->decisionLevel();
-
- if (branch_depth_distrib.size() <= S->decisionLevel())
- branch_depth_distrib.resize(S->decisionLevel()+1, 0);
- branch_depth_distrib[S->decisionLevel()]++;
- }
-}
-
-template void Logger::conflict(const confl_type type, const uint goback_level, const uint group, const Clause& learnt_clause);
-
-template void Logger::conflict(const confl_type type, const uint goback_level, const uint group, const vec<Lit>& learnt_clause);
-
-// Propagating a literal. Type of literal and the (learned clause's)/(propagating clause's)/(etc) group must be given. Updates the proof graph and the statistics. note: the meaning of the variable 'group' depends on the type
-void Logger::propagation(const Lit lit, Clause* c)
-{
- first_begin();
- assert(!(proof == NULL && proof_graph_on));
-
- uint group;
- prop_type type;
- if (c == NULL) {
- if (S->decisionLevel() == 0)
- type = add_clause_type;
- else
- type = guess_type;
- group = std::numeric_limits<uint>::max();
- } else {
- type = simple_propagation_type;
- group = c->getGroup();
- }
-
- //graph
- if (proof_graph_on && (!mini_proof || type == guess_type)) {
- uniqueid++;
-
- fprintf(proof,"node%d [shape=box, label=\"",uniqueid);;
- if (lit.sign())
- fprintf(proof,"-");
- if (varnames[lit.var()] != "Noname")
- fprintf(proof,"%s\"];\n",varnames[lit.var()].c_str());
- else
- fprintf(proof,"Var: %d\"];\n",lit.var());
-
- fprintf(proof,"node%d -> node%d [label=\"",history[history.size()-1],uniqueid);
-
- switch (type) {
- case simple_propagation_type:
- fprintf(proof,"%s\"];\n", groupnames[group].c_str());
- break;
-
- case add_clause_type:
- fprintf(proof,"red. from clause\"];\n");
- break;
-
- case guess_type:
- fprintf(proof,"guess\",style=bold];\n");
- break;
- }
- history.push_back(uniqueid);
- }
-
- if (statistics_on) {
- switch (type) {
- case simple_propagation_type:
- depths_of_propagations_for_group[group].sum += S->decisionLevel();
- depths_of_propagations_for_group[group].num ++;
- if (S->decisionLevel() == 0) depths_of_propagations_unit[group] = true;
- times_group_caused_propagation[group]++;
- case add_clause_type:
- no_propagations++;
- times_var_propagated[lit.var()]++;
- depths_of_assigns_for_var[lit.var()].sum += S->decisionLevel();
- depths_of_assigns_for_var[lit.var()].num ++;
- if (S->decisionLevel() == 0) depths_of_assigns_unit[lit.var()] = true;
- break;
- case guess_type:
- no_decisions++;
- times_var_guessed[lit.var()]++;
-
- depths_of_assigns_for_var[lit.var()].sum += S->decisionLevel();
- depths_of_assigns_for_var[lit.var()].num ++;
- break;
- }
- }
-}
-
-// Ending of a restart iteration
-void Logger::end(const finish_type finish)
-{
- first_begin();
- assert(!(proof == NULL && proof_graph_on));
-
- if (proof_graph_on) {
- uniqueid++;
- switch (finish) {
- case model_found:
- fprintf(proof,"node%d [shape=doublecircle, label=\"MODEL\"];\n",uniqueid);
- break;
- case unsat_model_found:
- fprintf(proof,"node%d [shape=doublecircle, label=\"UNSAT\"];\n",uniqueid);
- break;
- case restarting:
- fprintf(proof,"node%d [shape=doublecircle, label=\"Re-starting\\nsearch\"];\n",uniqueid);
- break;
- }
-
- fprintf(proof,"node%d -> node%d;\n",history[history.size()-1],uniqueid);
- fprintf(proof,"}\n");
- history.push_back(uniqueid);
-
- proof = (FILE*)fclose(proof);
- assert(proof == NULL);
- }
-
- if (statistics_on) {
- printstats();
- if (finish == restarting)
- reset_statistics();
- }
-
- if (model_found || unsat_model_found)
- begin_called = false;
-}
-
-void Logger::print_footer() const
-{
- cout << "+" << std::setfill('-') << std::setw(FST_WIDTH+SND_WIDTH+TRD_WIDTH+4) << "-" << std::setfill(' ') << "+" << endl;
-}
-
-void Logger::print_assign_var_order() const
-{
- vector<pair<double, uint> > prop_ordered;
- for (uint i = 0; i < depths_of_assigns_for_var.size(); i++) {
- double avg = (double)depths_of_assigns_for_var[i].sum
- /(double)depths_of_assigns_for_var[i].num;
- if (depths_of_assigns_for_var[i].num > 0 && !depths_of_assigns_unit[i])
- prop_ordered.push_back(std::make_pair(avg, i));
- }
-
- if (!prop_ordered.empty()) {
- print_footer();
- print_simple_line(" Variables are assigned in the following order");
- print_simple_line(" (unitary clauses not shown)");
- print_header("var", "var name", "avg order");
- std::sort(prop_ordered.begin(), prop_ordered.end());
- print_vars(prop_ordered);
- }
-}
-
-void Logger::print_prop_order() const
-{
- vector<pair<double, uint> > prop_ordered;
- for (uint i = 0; i < depths_of_propagations_for_group.size(); i++) {
- double avg = (double)depths_of_propagations_for_group[i].sum
- /(double)depths_of_propagations_for_group[i].num;
- if (depths_of_propagations_for_group[i].num > 0 && !depths_of_propagations_unit[i])
- prop_ordered.push_back(std::make_pair(avg, i));
- }
-
- if (!prop_ordered.empty()) {
- print_footer();
- print_simple_line(" Propagation depth order of clause groups");
- print_simple_line(" (unitary clauses not shown)");
- print_header("group", "group name", "avg order");
- std::sort(prop_ordered.begin(), prop_ordered.end());
- print_groups(prop_ordered);
- }
-}
-
-void Logger::print_confl_order() const
-{
- vector<pair<double, uint> > confl_ordered;
- for (uint i = 0; i < depths_of_conflicts_for_group.size(); i++) {
- double avg = (double)depths_of_conflicts_for_group[i].sum
- /(double)depths_of_conflicts_for_group[i].num;
- if (depths_of_conflicts_for_group[i].num > 0)
- confl_ordered.push_back(std::make_pair(avg, i));
- }
-
- if (!confl_ordered.empty()) {
- print_footer();
- print_simple_line(" Avg. conflict depth order of clause groups");
- print_header("groupno", "group name", "avg. depth");
- std::sort(confl_ordered.begin(), confl_ordered.end());
- print_groups(confl_ordered);
- }
-}
-
-
-void Logger::print_times_var_guessed() const
-{
- vector<pair<uint, uint> > times_var_ordered;
- for (uint32_t i = 0; i != varnames.size(); i++) if (times_var_guessed[i] > 0)
- times_var_ordered.push_back(std::make_pair(times_var_guessed[i], i));
-
- if (!times_var_ordered.empty()) {
- print_footer();
- print_simple_line(" No. times variable branched on");
- print_header("var", "var name", "no. times");
- std::sort(times_var_ordered.rbegin(), times_var_ordered.rend());
- print_vars(times_var_ordered);
- }
-}
-
-void Logger::print_times_group_caused_propagation() const
-{
- vector<pair<uint, uint> > props_group_ordered;
- for (uint i = 0; i < times_group_caused_propagation.size(); i++)
- if (times_group_caused_propagation[i] > 0)
- props_group_ordered.push_back(std::make_pair(times_group_caused_propagation[i], i));
-
- if (!props_group_ordered.empty()) {
- print_footer();
- print_simple_line(" No. propagations made by clause groups");
- print_header("group", "group name", "no. props");
- std::sort(props_group_ordered.rbegin(),props_group_ordered.rend());
- print_groups(props_group_ordered);
- }
-}
-
-void Logger::print_times_group_caused_conflict() const
-{
- vector<pair<uint, uint> > confls_group_ordered;
- for (uint i = 0; i < times_group_caused_conflict.size(); i++)
- if (times_group_caused_conflict[i] > 0)
- confls_group_ordered.push_back(std::make_pair(times_group_caused_conflict[i], i));
-
- if (!confls_group_ordered.empty()) {
- print_footer();
- print_simple_line(" No. conflicts made by clause groups");
- print_header("group", "group name", "no. confl");
- std::sort(confls_group_ordered.rbegin(), confls_group_ordered.rend());
- print_groups(confls_group_ordered);
- }
-}
-
-template<class T>
-void Logger::print_line(const uint& number, const string& name, const T& value) const
-{
- cout << "|" << std::setw(FST_WIDTH) << number << " " << std::setw(SND_WIDTH) << name << " " << std::setw(TRD_WIDTH) << value << "|" << endl;
-}
-
-void Logger::print_header(const string& first, const string& second, const string& third) const
-{
- cout << "|" << std::setw(FST_WIDTH) << first << " " << std::setw(SND_WIDTH) << second << " " << std::setw(TRD_WIDTH) << third << "|" << endl;
- print_footer();
-}
-
-void Logger::print_groups(const vector<pair<double, uint> >& to_print) const
-{
- uint i = 0;
- typedef vector<pair<double, uint> >::const_iterator myiterator;
- for (myiterator it = to_print.begin(); it != to_print.end() && i < max_print_lines; it++, i++) {
- print_line(it->second+1, groupnames[it->second], it->first);
- }
- print_footer();
-}
-
-void Logger::print_groups(const vector<pair<uint, uint> >& to_print) const
-{
- uint i = 0;
- typedef vector<pair<uint, uint> >::const_iterator myiterator;
- for (myiterator it = to_print.begin(); it != to_print.end() && i < max_print_lines; it++, i++) {
- print_line(it->second+1, groupnames[it->second], it->first);
- }
- print_footer();
-}
-
-void Logger::print_vars(const vector<pair<double, uint> >& to_print) const
-{
- uint i = 0;
- for (vector<pair<double, uint> >::const_iterator it = to_print.begin(); it != to_print.end() && i < max_print_lines; it++, i++)
- print_line(it->second+1, varnames[it->second], it->first);
-
- print_footer();
-}
-
-void Logger::print_vars(const vector<pair<uint, uint> >& to_print) const
-{
- uint i = 0;
- for (vector<pair<uint, uint> >::const_iterator it = to_print.begin(); it != to_print.end() && i < max_print_lines; it++, i++) {
- print_line(it->second+1, varnames[it->second], it->first);
- }
-
- print_footer();
-}
-
-template<class T>
-void Logger::print_line(const string& str, const T& num) const
-{
- cout << "|" << std::setw(FST_WIDTH+SND_WIDTH+4) << str << std::setw(TRD_WIDTH) << num << "|" << endl;
-}
-
-void Logger::print_simple_line(const string& str) const
-{
- cout << "|" << std::setw(FST_WIDTH+SND_WIDTH+TRD_WIDTH+4) << str << "|" << endl;
-}
-
-void Logger::print_center_line(const string& str) const
-{
- uint middle = (FST_WIDTH+SND_WIDTH+TRD_WIDTH+4-str.size())/2;
- int rest = FST_WIDTH+SND_WIDTH+TRD_WIDTH+4-middle*2-str.size();
- cout << "|" << std::setw(middle) << " " << str << std::setw(middle + rest) << " " << "|" << endl;
-}
-
-void Logger::print_branch_depth_distrib() const
-{
- //cout << "--- Branch depth stats ---" << endl;
-
- const uint range = 20;
- map<uint, uint> range_stat;
-
- uint i = 0;
- for (vector<uint>::const_iterator it = branch_depth_distrib.begin(); it != branch_depth_distrib.end(); it++, i++) {
- range_stat[i/range] += *it;
- }
-
- print_footer();
- print_simple_line(" No. search branches with branch depth between");
- print_line("Branch depth between", "no. br.-s");
- print_footer();
-
- std::stringstream ss;
- ss << "branch_depths/branch_depth_file" << runid << "-" << S->starts << ".txt";
- ofstream branch_depth_file;
- branch_depth_file.open(ss.str().c_str());
- i = 0;
-
- for (map<uint, uint>::iterator it = range_stat.begin(); it != range_stat.end(); it++, i++) {
- std::stringstream ss2;
- ss2 << it->first*range << " - " << it->first*range + range-1;
- print_line(ss2.str(), it->second);
-
- if (branch_depth_file.is_open()) {
- branch_depth_file << i << "\t" << it->second << "\t";
- if (i % 5 == 0)
- branch_depth_file << "\"" << it->first*range << "\"";
- else
- branch_depth_file << "\"\"";
- branch_depth_file << endl;
- }
- }
- if (branch_depth_file.is_open())
- branch_depth_file.close();
- print_footer();
-
-}
-
-void Logger::print_learnt_clause_distrib() const
-{
- map<uint, uint> learnt_sizes;
- const vec<Clause*>& learnts = S->get_learnts();
-
- uint maximum = 0;
-
- for (uint i = 0; i < learnts.size(); i++)
- {
- uint size = learnts[i]->size();
- maximum = std::max(maximum, size);
-
- map<uint, uint>::iterator it = learnt_sizes.find(size);
- if (it == learnt_sizes.end())
- learnt_sizes[size] = 1;
- else
- it->second++;
- }
-
- learnt_sizes[0] = S->get_unitary_learnts_num();
-
- uint slice = (maximum+1)/max_print_lines + (bool)((maximum+1)%max_print_lines);
-
- print_footer();
- print_simple_line(" Learnt clause length distribution");
- print_line("Length between", "no. cl.");
- print_footer();
-
- uint until = slice;
- uint from = 0;
- while(until < maximum+1) {
- std::stringstream ss2;
- ss2 << from << " - " << until-1;
-
- uint sum = 0;
- for (; from < until; from++) {
- map<uint, uint>::const_iterator it = learnt_sizes.find(from);
- if (it != learnt_sizes.end())
- sum += it->second;
- }
-
- print_line(ss2.str(), sum);
-
- until += slice;
- }
-
- print_footer();
-
- print_leearnt_clause_graph_distrib(maximum, learnt_sizes);
-}
-
-void Logger::print_leearnt_clause_graph_distrib(const uint maximum, const map<uint, uint>& learnt_sizes) const
-{
- uint no_slices = FST_WIDTH + SND_WIDTH + TRD_WIDTH + 4-3;
- uint slice = (maximum+1)/no_slices + (bool)((maximum+1)%no_slices);
- uint until = slice;
- uint from = 0;
- vector<uint> slices;
- uint hmax = 0;
- while(until < maximum+1) {
- uint sum = 0;
- for (; from < until; from++) {
- map<uint, uint>::const_iterator it = learnt_sizes.find(from);
- if (it != learnt_sizes.end())
- sum += it->second;
- }
- slices.push_back(sum);
- until += slice;
- hmax = std::max(hmax, sum);
- }
- slices.resize(no_slices, 0);
-
- uint height = max_print_lines;
- uint hslice = (hmax+1)/height + (bool)((hmax+1)%height);
- if (hslice == 0) return;
-
- print_simple_line(" Learnt clause distribution in graph form");
- print_footer();
- string yaxis = "Number";
- uint middle = (height-yaxis.size())/2;
-
- for (int i = height-1; i > 0; i--) {
- cout << "| ";
- if (height-1-i >= middle && height-1-i-middle < yaxis.size())
- cout << yaxis[height-1-i-middle] << " ";
- else
- cout << " ";
- for (uint i2 = 0; i2 != no_slices; i2++) {
- if (slices[i2]/hslice >= (uint)i) cout << "+";
- else cout << " ";
- }
- cout << "|" << endl;
- }
- print_center_line(" Learnt clause size");
- print_footer();
-}
-
-void Logger::print_general_stats() const
-{
- print_footer();
- print_simple_line(" Standard MiniSat stats -- for all restarts until now");
- print_footer();
- print_line("Restart number", S->starts);
- print_line("Number of conflicts", S->conflicts);
- print_line("Number of decisions", S->decisions);
- print_line("Number of variables", S->order_heap.size());
- print_line("Number of clauses", S->nClauses());
- print_line("Number of literals in clauses",S->clauses_literals);
- print_line("Avg. literals per learnt clause",(double)S->learnts_literals/(double)S->nLearnts());
- print_line("Progress estimate (%):", S->progress_estimate*100.0);
- print_line("All unitary learnts until now", S->get_unitary_learnts_num());
- print_footer();
-}
-
-void Logger::print_learnt_unitaries(const uint from, const string display) const
-{
- print_footer();
- print_simple_line(display);
- print_header("var", "name", "value");
- uint32_t until;
- if (S->decisionLevel() > 0)
- until = S->trail_lim[0];
- else
- until = S->trail.size();
- for (uint i = from; i < until; i++) {
- Var var = S->trail[i].var();
- bool value = !(S->trail[i].sign());
- print_line(var+1, varnames[var], value);
- }
- print_footer();
-}
-
-
-// Prints statistics on the console
-void Logger::printstats() const
-{
- assert(statistics_on);
- assert(varnames.size() == times_var_guessed.size());
- assert(varnames.size() == times_var_propagated.size());
-
- const uint fullwidth = FST_WIDTH+SND_WIDTH+TRD_WIDTH+4;
- cout << endl;
- cout << "+" << std::setfill('=') << std::setw(fullwidth) << "=" << "+" << endl;
- std::stringstream tmp;
- tmp << " STATS FOR RESTART NO. " << std::setw(3) << S->starts << " BEGIN ";
- uint len = (fullwidth-2)/2-tmp.str().length()/2;
- uint len2 = len + tmp.str().length()%2 + (fullwidth-2)%2;
- cout << "||" << std::setfill('*') << std::setw(len) << "*" << tmp.str() << std::setw(len2) << "*" << "||" << endl;
- cout << "+" << std::setfill('=') << std::setw(fullwidth) << "=" << std::setfill(' ') << "+" << endl;
-
- cout.setf(std::ios_base::left);
- cout.precision(2);
- print_statistics_note();
- print_times_var_guessed();
- print_times_group_caused_propagation();
- print_times_group_caused_conflict();
- print_prop_order();
- print_confl_order();
- print_assign_var_order();
- print_branch_depth_distrib();
- print_learnt_clause_distrib();
- #ifdef USE_GAUSS
- print_matrix_stats();
- #endif //USE_GAUSS
- print_learnt_unitaries(0," Unitary clauses learnt until now");
- print_learnt_unitaries(last_unitary_learnt_clauses, " Unitary clauses during this restart");
- print_advanced_stats();
- print_general_stats();
-}
-
-#ifdef USE_GAUSS
-void Logger::print_matrix_stats() const
-{
- print_footer();
- print_simple_line(" Matrix statistics");
- print_footer();
-
- uint i = 0;
- for (vector<Gaussian*>::const_iterator it = S->gauss_matrixes.begin(), end = S->gauss_matrixes.end(); it != end; it++, i++) {
- std::stringstream s;
- s << "Matrix " << i << " enabled";
- std::stringstream tmp;
- tmp << std::boolalpha << !(*it)->get_disabled();
- print_line(s.str(), tmp.str());
-
- s.str("");
- s << "Matrix " << i << " called";
- print_line(s.str(), (*it)->get_called());
-
- s.str("");
- s << "Matrix " << i << " propagations";
- print_line(s.str(), (*it)->get_useful_prop());
-
- s.str("");
- s << "Matrix " << i << " conflicts";
- print_line(s.str(), (*it)->get_useful_confl());
- }
-
- print_footer();
-}
-#endif //USE_GAUSS
-
-void Logger::print_advanced_stats() const
-{
- print_footer();
- print_simple_line(" Advanced statistics - for only this restart");
- print_footer();
- print_line("Unitary learnts", S->get_unitary_learnts_num() - last_unitary_learnt_clauses);
- print_line("No. branches visited", no_conflicts);
- print_line("Avg. branch depth", (double)sum_conflict_depths/(double)no_conflicts);
- print_line("No. decisions", no_decisions);
- print_line("No. propagations",no_propagations);
-
- //printf("no progatations/no decisions (i.e. one decision gives how many propagations on average *for the whole search graph*): %f\n", (double)no_propagations/(double)no_decisions);
- //printf("no propagations/sum decisions on branches (if you look at one specific branch, what is the average number of propagations you will find?): %f\n", (double)no_propagations/(double)sum_decisions_on_branches);
-
- print_simple_line("sum decisions on branches/no. branches");
- print_simple_line(" (in a given branch, what is the avg.");
- print_line(" no. of decisions?)",(double)sum_decisions_on_branches/(double)no_conflicts);
-
- print_simple_line("sum propagations on branches/no. branches");
- print_simple_line(" (in a given branch, what is the");
- print_line(" avg. no. of propagations?)",(double)sum_propagations_on_branches/(double)no_conflicts);
-
- print_footer();
-}
-
-void Logger::print_statistics_note() const
-{
- print_footer();
- print_simple_line("Statistics note: If you used CryptoMiniSat as");
- print_simple_line("a library then vars are all shifted by 1 here");
- print_simple_line("and in every printed output of the solver.");
- print_simple_line("This does not apply when you use CryptoMiniSat");
- print_simple_line("as a stand-alone program.");
- print_footer();
-}
-
-// resets all stored statistics. Might be useful, to generate statistics for each restart and not for the whole search in general
-void Logger::reset_statistics()
-{
- assert(S->decisionLevel() == 0);
- assert(times_var_guessed.size() == times_var_propagated.size());
- assert(times_group_caused_conflict.size() == times_group_caused_propagation.size());
-
- typedef vector<uint>::iterator vecit;
- for (vecit it = times_var_guessed.begin(); it != times_var_guessed.end(); it++)
- *it = 0;
-
- for (vecit it = times_var_propagated.begin(); it != times_var_propagated.end(); it++)
- *it = 0;
-
- for (vecit it = times_group_caused_conflict.begin(); it != times_group_caused_conflict.end(); it++)
- *it = 0;
-
- for (vecit it = times_group_caused_propagation.begin(); it != times_group_caused_propagation.end(); it++)
- *it = 0;
-
- for (vecit it = confls_by_group.begin(); it != confls_by_group.end(); it++)
- *it = 0;
-
- for (vecit it = props_by_group.begin(); it != props_by_group.end(); it++)
- *it = 0;
-
- typedef vector<MyAvg>::iterator avgIt;
-
- for (avgIt it = depths_of_propagations_for_group.begin(); it != depths_of_propagations_for_group.end(); it++) {
- it->sum = 0;
- it->num = 0;
- }
-
- for (avgIt it = depths_of_conflicts_for_group.begin(); it != depths_of_conflicts_for_group.end(); it++) {
- it->sum = 0;
- it->num = 0;
- }
-
- for (avgIt it = depths_of_assigns_for_var.begin(); it != depths_of_assigns_for_var.end(); it++) {
- it->sum = 0;
- it->num = 0;
- }
- for (uint i = 0; i < depths_of_assigns_unit.size(); i++)
- depths_of_assigns_unit[i] = false;
-
- for (uint i = 0; i < depths_of_propagations_unit.size(); i++)
- depths_of_propagations_unit[i] = false;
-
- sum_conflict_depths = 0;
- no_conflicts = 0;
- no_decisions = 0;
- no_propagations = 0;
- sum_decisions_on_branches = 0;
- sum_propagations_on_branches = 0;
- branch_depth_distrib.clear();
- last_unitary_learnt_clauses = S->get_unitary_learnts_num();
-}
-
-}; //NAMESPACE MINISAT
-/***********************************************************************************
-CryptoMiniSat -- Copyright (c) 2009 Mate Soos
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
-associated documentation files (the "Software"), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge, publish, distribute,
-sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or
-substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
-NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
-OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-**************************************************************************************************/
-
-#ifndef LOGGER_H
-#define LOGGER_H
-
-#include <stdio.h>
-#include <set>
-#include <vector>
-#include <string>
-#include <map>
-#ifdef _MSC_VER
-#include <msvc/stdint.h>
-#else
-#include <stdint.h>
-#endif //_MSC_VER
-
-#include "Vec.h"
-#include "Heap.h"
-#include "Alg.h"
-#include "SolverTypes.h"
-#include "limits.h"
-#include "Clause.h"
-
-using std::vector;
-using std::pair;
-using std::string;
-using std::map;
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
-class Solver;
-
-class MyAvg {
-public:
- MyAvg() :
- sum(0)
- , num(0)
- {}
-
- uint sum;
- uint num;
-};
-
-class Logger
-{
-public:
- Logger(int& vebosity);
- void setSolver(const Solver* S);
-
- //types of props, confl, and finish
- enum prop_type { add_clause_type, guess_type, simple_propagation_type};
- enum confl_type { simple_confl_type, gauss_confl_type };
- enum finish_type { model_found, unsat_model_found, restarting};
-
- //Conflict and propagation(guess is also a proapgation...)
- template<class T>
- void conflict(const confl_type type, const uint goback_level, const uint group, const T& learnt_clause);
- void propagation(const Lit lit, Clause* c);
-
- //functions to add/name variables
- void new_var(const Var var);
- void set_variable_name(const uint var, char* name_tmp);
-
- //function to name clause groups
- void set_group_name(const uint group, char* name_tmp);
-
- void begin();
- void end(const finish_type finish);
-
- void newclause(const vec<Lit>& ps, const bool xor_clause, const uint group);
-
- bool proof_graph_on;
- bool mini_proof;
- bool statistics_on;
-
-private:
- void new_group(const uint group);
- void cut_name_to_size(string& name) const;
-
- void print_groups(const vector<pair<uint, uint> >& to_print) const;
- void print_groups(const vector<pair<double, uint> >& to_print) const;
- void print_vars(const vector<pair<uint, uint> >& to_print) const;
- void print_vars(const vector<pair<double, uint> >& to_print) const;
- void print_times_var_guessed() const;
- void print_times_group_caused_propagation() const;
- void print_times_group_caused_conflict() const;
- void print_branch_depth_distrib() const;
- void print_learnt_clause_distrib() const;
- void print_leearnt_clause_graph_distrib(const uint maximum, const map<uint, uint>& learnt_sizes) const;
- void print_advanced_stats() const;
- void print_statistics_note() const;
- void print_matrix_stats() const;
- void print_general_stats() const;
- void print_learnt_unitaries(const uint from, const string display) const;
-
- uint max_print_lines;
- template<class T>
- void print_line(const uint& number, const string& name, const T& value) const;
- void print_header(const string& first, const string& second, const string& third) const;
- void print_footer() const;
- template<class T>
- void print_line(const string& str, const T& num) const;
- void print_simple_line(const string& str) const;
- void print_center_line(const string& str) const;
-
- void print_confl_order() const;
- void print_prop_order() const;
- void print_assign_var_order() const;
- void printstats() const;
- void reset_statistics();
-
- //internal data structures
- uint uniqueid; //used to store the last unique ID given to a node
- vector<uint> history; //stores the node uniqueIDs
-
- //graph drawing
- FILE* proof; //The file to store the proof
- uint runid;
-
- //---------------------
- //statistics collection
- //---------------------
-
- //group and var names
- vector<string> groupnames;
- vector<string> varnames;
-
- //confls and props grouped by clause groups
- vector<uint> confls_by_group;
- vector<uint> props_by_group;
-
- //props and guesses grouped by vars
- vector<uint> times_var_guessed;
- vector<uint> times_var_propagated;
-
- vector<uint> times_group_caused_conflict;
- vector<uint> times_group_caused_propagation;
-
- vector<MyAvg> depths_of_propagations_for_group;
- vector<bool> depths_of_propagations_unit;
- vector<MyAvg> depths_of_conflicts_for_group;
- vector<MyAvg> depths_of_assigns_for_var;
- vector<bool> depths_of_assigns_unit;
-
- //the distribution of branch depths. first = depth, second = number of occurances
- vector<uint> branch_depth_distrib;
-
- uint sum_conflict_depths;
- uint no_conflicts;
- uint no_decisions;
- uint no_propagations;
- uint sum_decisions_on_branches;
- uint sum_propagations_on_branches;
- uint last_unitary_learnt_clauses;
-
- //message display properties
- const int& verbosity;
-
- const Solver* S;
-
- void first_begin();
- bool begin_called;
- uint proofStarts;
-};
-
-}; //NAMESPACE MINISAT
-
-#endif //LOGGER_H
-TOP = ../../..
-include $(TOP)/scripts/Makefile.common
-
-MTL = mtl
-MTRAND = MTRand
-SOURCES = Logger.cpp Solver.cpp PackedRow.cpp XorFinder.cpp Conglomerate.cpp VarReplacer.cpp FindUndef.cpp ClauseCleaner.cpp RestartTypeChooser.cpp Clause.cpp FailedVarSearcher.cpp PartFinder.cpp Subsumer.cpp PartHandler.cpp XorSubsumer.cpp SmallPtr.cpp
-OBJECTS = $(SOURCES:.cpp=.o)
-LIB = libminisat.a
-CFLAGS += -I$(MTL) -I$(MTRAND) -DEXT_HASH_MAP -ffloat-store $(CFLAGS_M32) -c
-EXEC = minisat
-LFLAGS = -lz
-
-all: $(LIB) #$(EXEC)
-lib: $(LIB)
-
-$(LIB): $(OBJECTS)
- rm -f $@
- ar cq $@ $(OBJECTS)
- ranlib $@
- cp $(LIB) ../
- cp $(OBJECTS) ../
-
-clean:
- rm -f $(OBJECTS) $(LIB)
-
-.cpp.o:
- $(CC) $(CFLAGS) $< -o $@
-/***********************************************************************************
-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 <set>
-#include <map>
-#include <iomanip>
-#include <math.h>
-using std::set;
-using std::map;
-
-//#define VERBOSE_DEBUG
-
-using std::cout;
-using std::endl;
-
-namespace MINISAT
-{
-using namespace MINISAT;
-
-//#define PART_FINDING
-
-MatrixFinder::MatrixFinder(Solver& _solver) :
- solver(_solver)
-{
-}
-
-inline const Var MatrixFinder::fingerprint(const XorClause& c) const
-{
- Var fingerprint = 0;
-
- for (const Lit* a = &c[0], *end = a + c.size(); a != end; a++)
- fingerprint |= a->var();
-
- return fingerprint;
-}
-
-inline const bool MatrixFinder::firstPartOfSecond(const XorClause& c1, const XorClause& c2) const
-{
- uint i1, i2;
- for (i1 = 0, i2 = 0; i1 < c1.size() && i2 < c2.size();) {
- if (c1[i1].var() != c2[i2].var())
- i2++;
- else {
- i1++;
- i2++;
- }
- }
-
- return (i1 == c1.size());
-}
-
-const uint MatrixFinder::findMatrixes()
-{
- table.clear();
- table.resize(solver.nVars(), var_Undef);
- reverseTable.clear();
- matrix_no = 0;
-
- if (solver.xorclauses.size() == 0)
- return 0;
-
- solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses);
- //TODO check for solver.ok == false
-
- for (XorClause** c = solver.xorclauses.getData(), **end = c + solver.xorclauses.size(); c != end; c++) {
- set<uint> 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 uint into = *tomerge.begin();
- map<uint, vector<Var> >::iterator intoReverse = reverseTable.find(into);
- for (uint i = 0; i < newSet.size(); i++) {
- intoReverse->second.push_back(newSet[i]);
- table[newSet[i]] = into;
- }
- continue;
- }
-
- for (set<uint>::iterator it = tomerge.begin(); it != tomerge.end(); it++) {
- newSet.insert(newSet.end(), reverseTable[*it].begin(), reverseTable[*it].end());
- reverseTable.erase(*it);
- }
- for (uint i = 0; i < newSet.size(); i++)
- table[newSet[i]] = matrix_no;
- reverseTable[matrix_no] = newSet;
- matrix_no++;
- }
-
- #ifdef VERBOSE_DEBUG
- for (map<uint, vector<Var> >::iterator it = reverseTable.begin(), end = reverseTable.end(); it != end; it++) {
- cout << "-- set begin --" << endl;
- for (vector<Var>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
- cout << *it2 << ", ";
- }
- cout << "-------" << endl;
- }
- #endif
-
- return setMatrixes();
-}
-
-const uint MatrixFinder::setMatrixes()
-{
- vector<pair<uint, uint> > numXorInMatrix;
- for (uint i = 0; i < matrix_no; i++)
- numXorInMatrix.push_back(std::make_pair(i, 0));
-
- vector<uint> sumXorSizeInMatrix(matrix_no, 0);
- vector<vector<uint> > xorSizesInMatrix(matrix_no);
- vector<vector<XorClause*> > xorsInMatrix(matrix_no);
-
- #ifdef PART_FINDING
- vector<vector<Var> > xorFingerprintInMatrix(matrix_no);
- #endif
-
- for (XorClause** c = solver.xorclauses.getData(), **end = c + solver.xorclauses.size(); c != end; c++) {
- XorClause& x = **c;
- const uint matrix = table[x[0].var()];
- assert(matrix < matrix_no);
-
- //for stats
- numXorInMatrix[matrix].second++;
- sumXorSizeInMatrix[matrix] += x.size();
- xorSizesInMatrix[matrix].push_back(x.size());
- xorsInMatrix[matrix].push_back(&x);
-
- #ifdef PART_FINDING
- xorFingerprintInMatrix[matrix].push_back(fingerprint(x));
- #endif //PART_FINDING
- }
-
- std::sort(numXorInMatrix.begin(), numXorInMatrix.end(), mysorter());
-
- #ifdef PART_FINDING
- for (uint i = 0; i < matrix_no; i++)
- findParts(xorFingerprintInMatrix[i], xorsInMatrix[i]);
- #endif //PART_FINDING
-
- uint realMatrixNum = 0;
- for (int a = matrix_no-1; a != -1; a--) {
- uint i = numXorInMatrix[a].first;
-
- if (numXorInMatrix[a].second < 3)
- continue;
-
- const uint totalSize = reverseTable[i].size()*numXorInMatrix[a].second;
- const double density = (double)sumXorSizeInMatrix[i]/(double)totalSize*100.0;
- double avg = (double)sumXorSizeInMatrix[i]/(double)numXorInMatrix[a].second;
- double variance = 0.0;
- for (uint i2 = 0; i2 < xorSizesInMatrix[i].size(); i2++)
- variance += pow((double)xorSizesInMatrix[i][i2]-avg, 2);
- variance /= (double)xorSizesInMatrix.size();
- const double stdDeviation = sqrt(variance);
-
- if (numXorInMatrix[a].second >= 20
- && numXorInMatrix[a].second <= 1000
- && realMatrixNum < 3)
- {
- if (solver.verbosity >=1)
- cout << "c | Matrix no " << std::setw(4) << realMatrixNum;
- solver.gauss_matrixes.push_back(new Gaussian(solver, solver.gaussconfig, realMatrixNum, xorsInMatrix[i]));
- realMatrixNum++;
-
- } else {
- if (solver.verbosity >=1 /*&& numXorInMatrix[a].second >= 20*/)
- cout << "c | Unused Matrix ";
- }
- if (solver.verbosity >=1 /*&& numXorInMatrix[a].second >= 20*/) {
- cout << std::setw(5) << numXorInMatrix[a].second << " x" << std::setw(5) << reverseTable[i].size();
- cout << " density:" << std::setw(5) << std::fixed << std::setprecision(1) << density << "%";
- cout << " xorlen avg:" << std::setw(5) << std::fixed << std::setprecision(2) << avg;
- cout << " stdev:" << std::setw(6) << std::fixed << std::setprecision(2) << stdDeviation << " |" << endl;
- }
- }
-
- return realMatrixNum;
-}
-
-void MatrixFinder::findParts(vector<Var>& xorFingerprintInMatrix, vector<XorClause*>& xorsInMatrix)
-{
- uint ai = 0;
- for (XorClause **a = &xorsInMatrix[0], **end = a + xorsInMatrix.size(); a != end; a++, ai++) {
- const Var fingerprint = xorFingerprintInMatrix[ai];
- uint ai2 = 0;
- for (XorClause **a2 = &xorsInMatrix[0]; a2 != end; a2++, ai2++) {
- if (ai == ai2) continue;
- const Var fingerprint2 = xorFingerprintInMatrix[ai2];
- if (((fingerprint & fingerprint2) == fingerprint) && firstPartOfSecond(**a, **a2)) {
- cout << "First part of second:" << endl;
- (*a)->plainPrint();
- (*a2)->plainPrint();
- cout << "END" << endl;
- }
- }
- }
-}
-
-}; //NAMESPACE MINISAT
-/***********************************************************************************
-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 MINISAT
-{
-using namespace MINISAT;
-
-class Solver;
-
-using std::map;
-using std::vector;
-using std::pair;
-
-class MatrixFinder {
-
- public:
- MatrixFinder(Solver& solver);
- const uint findMatrixes();
-
- private:
- const uint setMatrixes();
-
- struct mysorter
- {
- bool operator () (const pair<uint, uint>& left, const pair<uint, uint>& right)
- {
- return left.second < right.second;
- }
- };
-
- void findParts(vector<Var>& xorFingerprintInMatrix, vector<XorClause*>& xorsInMatrix);
- inline const Var fingerprint(const XorClause& c) const;
- inline const bool firstPartOfSecond(const XorClause& c1, const XorClause& c2) const;
-
- map<uint, vector<Var> > reverseTable; //matrix -> vars
- vector<Var> table; //var -> matrix
- uint matrix_no;
-
- Solver& solver;
-};
-
-}; //NAMESPACE MINISAT
-
-#endif //MATRIXFINDER_H
-// MersenneTwister.h
-// Mersenne Twister random number generator -- a C++ class MTRand
-// Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
-// Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com
-
-// The Mersenne Twister is an algorithm for generating random numbers. It
-// was designed with consideration of the flaws in various other generators.
-// The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
-// are far greater. The generator is also fast; it avoids multiplication and
-// division, and it benefits from caches and pipelines. For more information
-// see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html
-
-// Reference
-// M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
-// Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on
-// Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.
-
-// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
-// Copyright (C) 2000 - 2003, Richard J. Wagner
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-//
-// 1. Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// 3. The names of its contributors may not be used to endorse or promote
-// products derived from this software without specific prior written
-// permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The original code included the following notice:
-//
-// When you use this, send an email to: matumoto@math.keio.ac.jp
-// with an appropriate reference to your work.
-//
-// It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu
-// when you write.
-
-#ifndef MERSENNETWISTER_H
-#define MERSENNETWISTER_H
-
-#include <iostream>
-#include <limits.h>
-#include <stdio.h>
-#include <time.h>
-#include <math.h>
-
-namespace MINISAT
-{
-
-// Not thread safe (unless auto-initialization is avoided and each thread has
-// its own MTRand object)
-
-class MTRand {
-// Data
-public:
- typedef unsigned long uint32; // unsigned integer type, at least 32 bits
-
- enum { N = 624 }; // length of state vector
- enum { SAVE = N + 1 }; // length of array for save()
-
-protected:
- enum { M = 397 }; // period parameter
-
- uint32 state[N]; // internal state
- uint32 *pNext; // next value to get from state
- int left; // number of values left before reload needed
-
-
-//Methods
-public:
- MTRand( const uint32& oneSeed ); // initialize with a simple uint32
- MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or an array
- MTRand(); // auto-initialize with /dev/urandom or time() and clock()
-
- // Do NOT use for CRYPTOGRAPHY without securely hashing several returned
- // values together, otherwise the generator state can be learned after
- // reading 624 consecutive values.
-
- // Access to 32-bit random numbers
- double rand(); // real number in [0,1]
- double rand( const double& n ); // real number in [0,n]
- double randExc(); // real number in [0,1)
- double randExc( const double& n ); // real number in [0,n)
- double randDblExc(); // real number in (0,1)
- double randDblExc( const double& n ); // real number in (0,n)
- uint32 randInt(); // integer in [0,2^32-1]
- uint32 randInt( const uint32& n ); // integer in [0,n] for n < 2^32
- double operator()() { return rand(); } // same as rand()
-
- // Access to 53-bit random numbers (capacity of IEEE double precision)
- double rand53(); // real number in [0,1)
-
- // Access to nonuniform random number distributions
- double randNorm( const double& mean = 0.0, const double& variance = 0.0 );
-
- // Re-seeding functions with same behavior as initializers
- void seed( const uint32 oneSeed );
- void seed( uint32 *const bigSeed, const uint32 seedLength = N );
- void seed();
-
- // Saving and loading generator state
- void save( uint32* saveArray ) const; // to array of size SAVE
- void load( uint32 *const loadArray ); // from such array
- friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand );
- friend std::istream& operator>>( std::istream& is, MTRand& mtrand );
-
-protected:
- void initialize( const uint32 oneSeed );
- void reload();
- uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; }
- uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; }
- uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; }
- uint32 mixBits( const uint32& u, const uint32& v ) const
- { return hiBit(u) | loBits(v); }
- uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const
- { return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL); }
- static uint32 hash( time_t t, clock_t c );
-};
-
-
-inline MTRand::MTRand( const uint32& oneSeed )
- { seed(oneSeed); }
-
-inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength )
- { seed(bigSeed,seedLength); }
-
-inline MTRand::MTRand()
- { seed(); }
-
-inline double MTRand::rand()
- { return double(randInt()) * (1.0/4294967295.0); }
-
-inline double MTRand::rand( const double& n )
- { return rand() * n; }
-
-inline double MTRand::randExc()
- { return double(randInt()) * (1.0/4294967296.0); }
-
-inline double MTRand::randExc( const double& n )
- { return randExc() * n; }
-
-inline double MTRand::randDblExc()
- { return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); }
-
-inline double MTRand::randDblExc( const double& n )
- { return randDblExc() * n; }
-
-inline double MTRand::rand53()
-{
- uint32 a = randInt() >> 5, b = randInt() >> 6;
- return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada
-}
-
-inline double MTRand::randNorm( const double& mean, const double& variance )
-{
- // Return a real number from a normal (Gaussian) distribution with given
- // mean and variance by Box-Muller method
- double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance;
- double phi = 2.0 * 3.14159265358979323846264338328 * randExc();
- return mean + r * cos(phi);
-}
-
-inline MTRand::uint32 MTRand::randInt()
-{
- // Pull a 32-bit integer from the generator state
- // Every other access function simply transforms the numbers extracted here
-
- if( left == 0 ) reload();
- --left;
-
- register uint32 s1;
- s1 = *pNext++;
- s1 ^= (s1 >> 11);
- s1 ^= (s1 << 7) & 0x9d2c5680UL;
- s1 ^= (s1 << 15) & 0xefc60000UL;
- return ( s1 ^ (s1 >> 18) );
-}
-
-inline MTRand::uint32 MTRand::randInt( const uint32& n )
-{
- // Find which bits are used in n
- // Optimized by Magnus Jonsson (magnus@smartelectronix.com)
- uint32 used = n;
- used |= used >> 1;
- used |= used >> 2;
- used |= used >> 4;
- used |= used >> 8;
- used |= used >> 16;
-
- // Draw numbers until one is found in [0,n]
- uint32 i;
- do
- i = randInt() & used; // toss unused bits to shorten search
- while( i > n );
- return i;
-}
-
-
-inline void MTRand::seed( const uint32 oneSeed )
-{
- // Seed the generator with a simple uint32
- initialize(oneSeed);
- reload();
-}
-
-
-inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength )
-{
- // Seed the generator with an array of uint32's
- // There are 2^19937-1 possible initial states. This function allows
- // all of those to be accessed by providing at least 19937 bits (with a
- // default seed length of N = 624 uint32's). Any bits above the lower 32
- // in each element are discarded.
- // Just call seed() if you want to get array from /dev/urandom
- initialize(19650218UL);
- register int i = 1;
- register uint32 j = 0;
- register int k = ( N > seedLength ? N : seedLength );
- for( ; k; --k )
- {
- state[i] =
- state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
- state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
- state[i] &= 0xffffffffUL;
- ++i; ++j;
- if( i >= N ) { state[0] = state[N-1]; i = 1; }
- if( j >= seedLength ) j = 0;
- }
- for( k = N - 1; k; --k )
- {
- state[i] =
- state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
- state[i] -= i;
- state[i] &= 0xffffffffUL;
- ++i;
- if( i >= N ) { state[0] = state[N-1]; i = 1; }
- }
- state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array
- reload();
-}
-
-
-inline void MTRand::seed()
-{
- // Seed the generator with an array from /dev/urandom if available
- // Otherwise use a hash of time() and clock() values
-
- // First try getting an array from /dev/urandom
- FILE* urandom = fopen( "/dev/urandom", "rb" );
- if( urandom )
- {
- uint32 bigSeed[N];
- register uint32 *s = bigSeed;
- register int i = N;
- register bool success = true;
- while( success && i-- )
- success = fread( s++, sizeof(uint32), 1, urandom );
- fclose(urandom);
- if( success ) { seed( bigSeed, N ); return; }
- }
-
- // Was not successful, so use time() and clock() instead
- seed( hash( time(NULL), clock() ) );
-}
-
-
-inline void MTRand::initialize( const uint32 seed )
-{
- // Initialize generator state with seed
- // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
- // In previous versions, most significant bits (MSBs) of the seed affect
- // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
- register uint32 *s = state;
- register uint32 *r = state;
- register int i = 1;
- *s++ = seed & 0xffffffffUL;
- for( ; i < N; ++i )
- {
- *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
- r++;
- }
-}
-
-
-inline void MTRand::reload()
-{
- // Generate N new values in state
- // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
- register uint32 *p = state;
- register int i;
- for( i = N - M; i--; ++p )
- *p = twist( p[M], p[0], p[1] );
- for( i = M; --i; ++p )
- *p = twist( p[M-N], p[0], p[1] );
- *p = twist( p[M-N], p[0], state[0] );
-
- left = N, pNext = state;
-}
-
-
-inline MTRand::uint32 MTRand::hash( time_t t, clock_t c )
-{
- // Get a uint32 from t and c
- // Better than uint32(x) in case x is floating point in [0,1]
- // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk)
-
- static uint32 differ = 0; // guarantee time-based seeds will change
-
- uint32 h1 = 0;
- unsigned char *p = (unsigned char *) &t;
- for( size_t i = 0; i < sizeof(t); ++i )
- {
- h1 *= UCHAR_MAX + 2U;
- h1 += p[i];
- }
- uint32 h2 = 0;
- p = (unsigned char *) &c;
- for( size_t j = 0; j < sizeof(c); ++j )
- {
- h2 *= UCHAR_MAX + 2U;
- h2 += p[j];
- }
- return ( h1 + differ++ ) ^ h2;
-}
-
-
-inline void MTRand::save( uint32* saveArray ) const
-{
- register uint32 *sa = saveArray;
- register const uint32 *s = state;
- register int i = N;
- for( ; i--; *sa++ = *s++ ) {}
- *sa = left;
-}
-
-
-inline void MTRand::load( uint32 *const loadArray )
-{
- register uint32 *s = state;
- register uint32 *la = loadArray;
- register int i = N;
- for( ; i--; *s++ = *la++ ) {}
- left = *la;
- pNext = &state[N-left];
-}
-
-
-inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand )
-{
- register const MTRand::uint32 *s = mtrand.state;
- register int i = mtrand.N;
- for( ; i--; os << *s++ << "\t" ) {}
- return os << mtrand.left;
-}
-
-
-inline std::istream& operator>>( std::istream& is, MTRand& mtrand )
-{
- register MTRand::uint32 *s = mtrand.state;
- register int i = mtrand.N;
- for( ; i--; is >> *s++ ) {}
- is >> mtrand.left;
- mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left];
- return is;
-}
-};
-
-#endif // MERSENNETWISTER_H
-
-// Change log:
-//
-// v0.1 - First release on 15 May 2000
-// - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
-// - Translated from C to C++
-// - Made completely ANSI compliant
-// - Designed convenient interface for initialization, seeding, and
-// obtaining numbers in default or user-defined ranges
-// - Added automatic seeding from /dev/urandom or time() and clock()
-// - Provided functions for saving and loading generator state
-//
-// v0.2 - Fixed bug which reloaded generator one step too late
-//
-// v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
-//
-// v0.4 - Removed trailing newline in saved generator format to be consistent
-// with output format of built-in types
-//
-// v0.5 - Improved portability by replacing static const int's with enum's and
-// clarifying return values in seed(); suggested by Eric Heimburg
-// - Removed MAXINT constant; use 0xffffffffUL instead
-//
-// v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
-// - Changed integer [0,n] generator to give better uniformity
-//
-// v0.7 - Fixed operator precedence ambiguity in reload()
-// - Added access for real numbers in (0,1) and (0,n)
-//
-// v0.8 - Included time.h header to properly support time_t and clock_t
-//
-// v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
-// - Allowed for seeding with arrays of any length
-// - Added access for real numbers in [0,1) with 53-bit resolution
-// - Added access for real numbers from normal (Gaussian) distributions
-// - Increased overall speed by optimizing twist()
-// - Doubled speed of integer [0,n] generation
-// - Fixed out-of-range number generation on 64-bit machines
-// - Improved portability by substituting literal constants for long enum's
-// - Changed license from GNU LGPL to BSD
part_no = 0;
solver.clauseCleaner->removeAndCleanAll(true);
- if (solver.ok == false) return false;
+ if (!solver.ok) return false;
while (solver.varReplacer->getNewToReplaceVars() > 0) {
if (solver.performReplace && !solver.varReplacer->performReplace(true))
return false;
solver.clauseCleaner->removeAndCleanAll(true);
- if (solver.ok == false) return false;
+ if (!solver.ok) return false;
}
assert(solver.varReplacer->getClauses().size() == 0);
return true;
PartFinder partFinder(solver);
- if (!partFinder.findParts())
+ if (!partFinder.findParts()) {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "c findParts() found UNSAT. Whole problem is unsat." << std::endl;
+ #endif //VERBOSE_DEBUG
return false;
+ }
uint32_t num_parts = partFinder.getReverseTable().size();
if (num_parts == 1)
newSolver.doPartHandler = solver.doPartHandler;
newSolver.fixRestartType = solver.fixRestartType;
newSolver.var_inc = solver.var_inc;
- newSolver.polarity_mode = Solver::polarity_manual;
+ newSolver.polarity_mode = solver.polarity_mode;
std::sort(vars.begin(), vars.end());
uint32_t i2 = 0;
for (Var var = 0; var < solver.nVars(); var++) {
if (i2 < vars.size() && vars[i2] == var) {
+ #ifdef VERBOSE_DEBUG
+ if (!solver.decision_var[var]) {
+ std::cout << "var " << var + 1 << " is non-decision, but in part... strange." << std::endl;
+ }
+ #endif //VERBOSE_DEBUG
newSolver.newVar(solver.decision_var[var]);
newSolver.activity[var] = solver.activity[var];
- newSolver.defaultPolarities[var] = solver.polarity[var];
newSolver.order_heap.update(var);
assert(partFinder.getVarPart(var) == part);
if (solver.decision_var[var]) {
solver.setDecisionVar(var, false);
- if (solver.decision_var[var]) decisionVarRemoved.push(var);
+ decisionVarRemoved.push(var);
}
i2++;
} else {
assert(checkClauseMovement(newSolver, part, partFinder));
lbool status = newSolver.solve();
- if (status == l_False)
+ if (status == l_False) {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "c One of the sub-problems was UNSAT. Whole problem is unsat." << std::endl;
+ #endif //VERBOSE_DEBUG
return false;
+ }
assert(status != l_Undef);
for (Var var = 0; var < newSolver.nVars(); var++) {
for (Var var = 0; var < newSolver.nVars(); var++) {
if (newSolver.model[var] != l_Undef) {
+ //Must have been decision var in the old solver!??
+ //assert(std::find(decisionVarRemoved.getData(), decisionVarRemoved.getDataEnd(), var) != decisionVarRemoved.getDataEnd());
assert(savedState[var] == l_Undef);
assert(partFinder.getVarPart(var) == part);
- savedState[var] = newSolver.model[var];
+ if (newSolver.assigns[var] == l_Undef) {
+ savedState[var] = newSolver.model[var];
+ }
}
}
continue;
}
solver.detachClause(**i);
- vec<Lit> cs((*i)->size());
- std::copy((**i).getData(), (**i).getDataEnd(), cs.getData());
- newSolver.addClause(cs, (**i).getGroup());
+ #ifdef VERBOSE_DEBUG
+ std::cout << "clause in this part:"; (**i).plainPrint();
+ #endif
+
+ Clause& c = **i;
+ vec<Lit> tmp(c.size());
+ std::copy(c.getData(), c.getDataEnd(), tmp.getData());
+ newSolver.addClause(tmp, c.getGroup());
//NOTE: we need the CS because otherwise, the addClause could have changed **i, which we need to re-add later!
clausesRemoved.push(*i);
}
continue;
}
solver.detachClause(**i);
- vec<Lit> cs((*i)->size());
- for (uint32_t i2 = 0; i2 < (*i)->size(); i2++)
- cs[i2] = (**i)[i2].unsign();
- newSolver.addXorClause(cs, (**i).xor_clause_inverted(), (**i).getGroup());
+ #ifdef VERBOSE_DEBUG
+ std::cout << "xor clause in this part:"; (**i).plainPrint();
+ #endif
+
+ XorClause& c = **i;
+ vec<Lit> tmp(c.size());
+ std::copy(c.getData(), c.getDataEnd(), tmp.getData());
+ newSolver.addXorClause(tmp, c.xor_clause_inverted(), c.getGroup());
//NOTE: we need the CS because otherwise, the addXorClause could have changed **i, which we need to re-add later!
xorClausesRemoved.push(*i);
}
for (const Lit* l = c.getData(), *end = l + c.size(); l != end; l++) {
if (partFinder.getVarPart(l->var()) != clause_part) {
#ifdef VERBOSE_DEBUG
- std::cout << "Learnt clause in both parts!" << std::endl;
+ std::cout << "Learnt clause in both parts:"; c.plainPrint();
#endif
removed = true;
if (removed) continue;
if (clause_part == part) {
#ifdef VERBOSE_DEBUG
- std::cout << "Learnt clause in this part!" << std::endl;
+ //std::cout << "Learnt clause in this part:"; c.plainPrint();
#endif
solver.detachClause(c);
newSolver.addLearntClause(c, c.getGroup(), c.activity());
- free(*i);
+ clauseFree(&c);
} else {
#ifdef VERBOSE_DEBUG
- std::cout << "Learnt clause in other part!" << std::endl;
+ std::cout << "Learnt clause in other part:"; c.plainPrint();
#endif
*j++ = *i;
void PartHandler::addSavedState()
{
+ //Don't add these (non-0-decison-level!) solutions to the 0th decision level
+ solver.newDecisionLevel();
for (Var var = 0; var < savedState.size(); var++) {
if (savedState[var] != l_Undef) {
- assert(solver.assigns[var] == l_Undef || (solver.assigns[var] == savedState[var] && solver.level[var] == 0));
- //decision level should NOT be 0.... TODO
+ assert(solver.assigns[var] == l_Undef);
solver.uncheckedEnqueue(Lit(var, savedState[var] == l_False));
assert(solver.assigns[var] == savedState[var]);
savedState[var] = l_Undef;
}
}
- for (uint32_t var = 0; var < decisionVarRemoved.size(); var++)
- solver.setDecisionVar(var, true);
+ for (uint32_t i = 0; i < decisionVarRemoved.size(); i++)
+ solver.setDecisionVar(decisionVarRemoved[i], true);
decisionVarRemoved.clear();
}
clausesRemoved.clear();
for (XorClause **it = xorClausesRemoved.getData(), **end = xorClausesRemoved.getDataEnd(); it != end; it++) {
- for (Lit *l = (*it)->getData(), *end2 = (*it)->getDataEnd(); l != end2; l++) {
- *l = l->unsign();
- }
- solver.addXorClause(**it, (*it)->getGroup());
+ solver.addXorClause(**it, (**it).xor_clause_inverted(), (*it)->getGroup());
assert(solver.ok);
}
xorClausesRemoved.clear();
#include "VarReplacer.h"
#include "FindUndef.h"
-#include "Conglomerate.h"
#include "XorFinder.h"
#include "ClauseCleaner.h"
#include "RestartTypeChooser.h"
#include "Subsumer.h"
#include "PartHandler.h"
#include "XorSubsumer.h"
+#include "StateSaver.h"
#ifdef USE_GAUSS
#include "Gaussian.h"
//#define __builtin_prefetch(a,b)
#endif //_MSC_VER
+//#define DEBUG_UNCHECKEDENQUEUE_LEVEL0
//#define VERBOSE_DEBUG_POLARITIES
//#define DEBUG_DYNAMIC_RESTART
, doVarElim (true)
, doSubsume1 (true)
, failedVarSearch (true)
+ , readdOldLearnts (false)
+ , addExtraBins (true)
+ , removeUselessBins(true)
+ , regularRemoveUselessBins(true)
+ , subsumeWithNonExistBinaries(true)
+ , regularSubsumeWithNonExistBinaries(true)
, libraryUsage (true)
, greedyUnbound (false)
, fixRestartType (auto_restart)
, improvedClauseNo(0), improvedClauseSize(0)
+ , sum_gauss_called (0)
+ , sum_gauss_confl (0)
+ , sum_gauss_prop (0)
+ , sum_gauss_unit_truths (0)
, ok (true)
, var_inc (128)
, cla_inc (1)
, simplifying (false)
{
varReplacer = new VarReplacer(*this);
- conglomerate = new Conglomerate(*this);
clauseCleaner = new ClauseCleaner(*this);
failedVarSearcher = new FailedVarSearcher(*this);
partHandler = new PartHandler(*this);
subsumer = new Subsumer(*this);
+ xorSubsumer = new XorSubsumer(*this);
restartTypeChooser = new RestartTypeChooser(*this);
+ #ifdef USE_GAUSS
+ matrixFinder = new MatrixFinder(*this);
+ #endif //USE_GAUSS
#ifdef STATS_NEEDED
logger.setSolver(this);
for (uint32_t i = 0; i != learnts.size(); i++) clauseFree(learnts[i]);
for (uint32_t i = 0; i != clauses.size(); i++) clauseFree(clauses[i]);
for (uint32_t i = 0; i != binaryClauses.size(); i++) clauseFree(binaryClauses[i]);
- for (uint32_t i = 0; i != xorclauses.size(); i++) free(xorclauses[i]);
+ for (uint32_t i = 0; i != xorclauses.size(); i++) clauseFree(xorclauses[i]);
+ for (uint32_t i = 0; i != removedLearnts.size(); i++) clauseFree(removedLearnts[i]);
#ifdef USE_GAUSS
clearGaussMatrixes();
+ delete matrixFinder;
#endif
+ for (uint32_t i = 0; i != freeLater.size(); i++) clauseFree(freeLater[i]);
+
delete varReplacer;
- delete conglomerate;
delete clauseCleaner;
delete failedVarSearcher;
delete partHandler;
delete subsumer;
+ delete xorSubsumer;
delete restartTypeChooser;
if (libraryCNFFile)
seen .push_back(0);
permDiff .push(0);
- polarity .push_back(true);
- defaultPolarities.push_back(true);
+ polarity .push_back(defaultPolarity());
+ #ifdef USE_OLD_POLARITIES
+ oldPolarity.push_back(defaultPolarity());
+ #endif //USE_OLD_POLARITIES
decision_var.push_back(dvar);
insertVarOrder(v);
varReplacer->newVar();
- conglomerate->newVar();
partHandler->newVar();
subsumer->newVar();
+ xorSubsumer->newVar();
insertVarOrder(v);
template<class T>
XorClause* Solver::addXorClauseInt(T& ps, bool xor_clause_inverted, const uint32_t group)
{
+ assert(qhead == trail.size());
+ assert(decisionLevel() == 0);
+
if (ps.size() > (0x01UL << 18)) {
std::cout << "Too long clause!" << std::endl;
exit(-1);
}
- std::sort(ps.getData(), ps.getData()+ps.size());
+ std::sort(ps.getData(), ps.getDataEnd());
Lit p;
uint32_t i, j;
for (i = j = 0, p = lit_Undef; i != ps.size(); i++) {
- xor_clause_inverted ^= ps[i].sign();
- ps[i] ^= ps[i].sign();
-
- if (ps[i] == p) {
+ if (ps[i].var() == p.var()) {
//added, but easily removed
j--;
p = lit_Undef;
return NULL;
}
case 1: {
- assert(assigns[ps[0].var()].isUndef());
- uncheckedEnqueue(ps[0] ^ xor_clause_inverted);
+ uncheckedEnqueue(Lit(ps[0].var(), xor_clause_inverted));
ok = (propagate() == NULL);
return NULL;
}
#ifdef VERBOSE_DEBUG
cout << "--> xor is 2-long, replacing var " << ps[0].var()+1 << " with " << (!xor_clause_inverted ? "-" : "") << ps[1].var()+1 << endl;
#endif
-
+
+ learnt_clause_group = std::max(group+1, learnt_clause_group);
+ ps[0] = ps[0].unsign();
+ ps[1] = ps[1].unsign();
varReplacer->replace(ps, xor_clause_inverted, group);
return NULL;
}
if (libraryCNFFile) {
fprintf(libraryCNFFile, "x");
- for (uint i = 0; i < ps.size(); i++) {
- fprintf(libraryCNFFile, "%s%d ", ps[i].sign() ? "-" : "", ps[i].var()+1);
- }
+ for (uint32_t i = 0; i < ps.size(); i++) ps[i].print(libraryCNFFile);
fprintf(libraryCNFFile, "0\n");
}
assert(qhead == trail.size());
// Check if clause is satisfied and remove false/duplicate literals:
- if (varReplacer->getNumLastReplacedVars() || subsumer->getNumElimed()) {
+ if (varReplacer->getNumLastReplacedVars() || subsumer->getNumElimed() || xorSubsumer->getNumElimed()) {
for (uint32_t i = 0; i != ps.size(); i++) {
- ps[i] = varReplacer->getReplaceTable()[ps[i].var()] ^ ps[i].sign();
if (subsumer->getVarElimed()[ps[i].var()] && !subsumer->unEliminate(ps[i].var()))
return false;
+ else if (xorSubsumer->getVarElimed()[ps[i].var()] && !xorSubsumer->unEliminate(ps[i].var()))
+ return false;
+ else {
+ Lit otherLit = varReplacer->getReplaceTable()[ps[i].var()];
+ if (otherLit.var() != ps[i].var()) {
+ ps[i] = Lit(otherLit.var(), false);
+ xor_clause_inverted ^= otherLit.sign();
+ }
+ }
}
}
bool Solver::addLearntClause(T& ps, const uint group, const uint32_t activity)
{
Clause* c = addClauseInt(ps, group);
- if (c == NULL)
- return ok;
-
+ if (c == NULL) return ok;
+
+ //compensate for addClauseInt's attachClause, which doesn't know
+ //that this is a learnt clause.
clauses_literals -= c->size();
+ learnts_literals += c->size();
c->makeLearnt(activity);
- learnts.push(c);
- learnts_literals += c->size();
+ if (c->size() > 2) learnts.push(c);
+ else {
+ nbBin++;
+ binaryClauses.push(c);
+ }
return ok;
}
template bool Solver::addLearntClause(Clause& ps, const uint group, const uint32_t activity);
{
assert(ok);
- std::sort(ps.getData(), ps.getData()+ps.size());
+ std::sort(ps.getData(), ps.getDataEnd());
Lit p = lit_Undef;
uint32_t i, j;
for (i = j = 0; i != ps.size(); i++) {
}
if (libraryCNFFile) {
- for (uint32_t i = 0; i != ps.size(); i++) {
- fprintf(libraryCNFFile, "%s%d ", ps[i].sign() ? "-" : "", ps[i].var()+1);
- }
+ for (uint32_t i = 0; i != ps.size(); i++) ps[i].print(libraryCNFFile);
fprintf(libraryCNFFile, "0\n");
}
assert(qhead == trail.size());
// Check if clause is satisfied and remove false/duplicate literals:
- if (varReplacer->getNumLastReplacedVars() || subsumer->getNumElimed()) {
+ if (varReplacer->getNumLastReplacedVars() || subsumer->getNumElimed() || xorSubsumer->getNumElimed()) {
for (uint32_t i = 0; i != ps.size(); i++) {
ps[i] = varReplacer->getReplaceTable()[ps[i].var()] ^ ps[i].sign();
if (subsumer->getVarElimed()[ps[i].var()] && !subsumer->unEliminate(ps[i].var()))
return false;
+ if (xorSubsumer->getVarElimed()[ps[i].var()] && !xorSubsumer->unEliminate(ps[i].var()))
+ return false;
}
}
void Solver::attachClause(XorClause& c)
{
assert(c.size() > 2);
+ #ifdef DEBUG_ATTACH
+ assert(assigns[c[0].var()] == l_Undef);
+ assert(assigns[c[1].var()] == l_Undef);
+ #endif //DEBUG_ATTACH
xorwatches[c[0].var()].push(&c);
xorwatches[c[1].var()].push(&c);
cout << endl;
#endif
- if (decisionLevel() > level) {
+ 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 c = trail.size()-1; c >= (int)trail_lim[level]; c--) {
- Var x = trail[c].var();
+ for (int sublevel = trail.size()-1; sublevel >= (int)trail_lim[level]; sublevel--) {
+ Var var = trail[sublevel].var();
#ifdef VERBOSE_DEBUG
- cout << "Canceling var " << x+1 << " sublevel: " << c << endl;
+ cout << "Canceling var " << var+1 << " sublevel: " << sublevel << endl;
#endif
- assigns[x] = l_Undef;
- insertVarOrder(x);
+ #ifdef USE_OLD_POLARITIES
+ polarity[var] = oldPolarity[var];
+ #endif //USE_OLD_POLARITIES
+ assigns[var] = l_Undef;
+ insertVarOrder(var);
}
qhead = trail_lim[level];
- trail.shrink(trail.size() - trail_lim[level]);
- trail_lim.shrink(trail_lim.size() - level);
+ trail.shrink_(trail.size() - trail_lim[level]);
+ trail_lim.shrink_(trail_lim.size() - level);
}
#ifdef VERBOSE_DEBUG
return false;
case polarity_rnd:
return mtrand.randInt(1);
+ case polarity_auto:
+ return true;
default:
assert(false);
}
return true;
}
-void tallyVotes(const vec<Clause*>& cs, vector<double>& votes, vector<bool>& positiveLiteral, vector<bool>& negativeLiteral)
+void Solver::tallyVotes(const vec<Clause*>& cs, vector<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));
+ if (c.size() > 63) divider = 0.0;
+ else divider = 1.0/(double)((uint64_t)1<<(c.size()-1));
+
for (const Lit *it2 = &c[0], *end2 = it2 + c.size(); it2 != end2; it2++) {
- if (it2->sign()) {
- negativeLiteral[it2->var()] = true;
- votes[it2->var()] += divider;
- } else {
- positiveLiteral[it2->var()] = true;
- votes[it2->var()] -= divider;
- }
+ if (it2->sign()) votes[it2->var()] += divider;
+ else votes[it2->var()] -= divider;
}
}
}
-void tallyVotes(const vec<XorClause*>& cs, vector<double>& votes, vector<bool>& positiveLiteral, vector<bool>& negativeLiteral)
+void Solver::tallyVotes(const vec<XorClause*>& cs, vector<double>& votes) const
{
for (const XorClause * const*it = cs.getData(), * const*end = it + cs.size(); it != end; it++) {
const XorClause& c = **it;
double divider;
- if (c.size() > 63)
- divider = 0.0;
- else
- divider = 1.0/(double)((uint64_t)1<<(c.size()-1));
- for (const Lit *it2 = &c[0], *end2 = it2 + c.size(); it2 != end2; it2++) {
+ if (c.size() > 63) divider = 0.0;
+ else divider = 1.0/(double)((uint64_t)1<<(c.size()-1));
+
+ for (const Lit *it2 = &c[0], *end2 = it2 + c.size(); it2 != end2; it2++)
votes[it2->var()] += divider;
- negativeLiteral[it2->var()] = true;
- positiveLiteral[it2->var()] = true;
- }
}
}
-const lbool Solver::calculateDefaultPolarities()
+void Solver::calculateDefaultPolarities()
{
#ifdef VERBOSE_DEBUG_POLARITIES
std::cout << "Default polarities: " << std::endl;
#endif
assert(decisionLevel() == 0);
-
if (polarity_mode == polarity_auto) {
double time = cpuTime();
vector<double> votes;
- vector<bool> positiveLiteral;
- vector<bool> negativeLiteral;
votes.resize(nVars(), 0.0);
- positiveLiteral.resize(nVars(), false);
- negativeLiteral.resize(nVars(), false);
- tallyVotes(clauses, votes, positiveLiteral, negativeLiteral);
- tallyVotes(binaryClauses, votes, positiveLiteral, negativeLiteral);
- tallyVotes(varReplacer->getClauses(), votes, positiveLiteral, negativeLiteral);
- tallyVotes(xorclauses, votes, positiveLiteral, negativeLiteral);
+ tallyVotes(clauses, votes);
+ tallyVotes(binaryClauses, votes);
+ tallyVotes(varReplacer->getClauses(), votes);
+ tallyVotes(xorclauses, votes);
Var i = 0;
for (vector<double>::const_iterator it = votes.begin(), end = votes.end(); it != end; it++, i++) {
- defaultPolarities[i] = (*it >= 0.0);
+ polarity[i] = (*it >= 0.0);
#ifdef VERBOSE_DEBUG_POLARITIES
std::cout << !defaultPolarities[i] << ", ";
#endif //VERBOSE_DEBUG_POLARITIES
<< std::fixed << std::setw(6) << std::setprecision(2) << cpuTime()-time << " s"
<< " |" << std:: endl;
}
- } else if (polarity_mode != polarity_manual){
- for (uint i = 0; i != defaultPolarities.size(); i++) {
- defaultPolarities[i] = defaultPolarity();
- #ifdef VERBOSE_DEBUG_POLARITIES
- std::cout << !defaultPolarities[i] << ", ";
- #endif //VERBOSE_DEBUG_POLARITIES
- }
+ } else {
+ std::fill(polarity.begin(), polarity.end(), defaultPolarity());
}
+
#ifdef VERBOSE_DEBUG_POLARITIES
std::cout << std::endl;
#endif //VERBOSE_DEBUG_POLARITIES
-
- return l_Undef;
-}
-
-void Solver::setDefaultPolarities()
-{
- assert(polarity.size() == defaultPolarities.size());
-
- for (uint i = 0; i != polarity.size(); i++)
- polarity[i] = defaultPolarities[i];
}
//=================================================================================================
if (next != var_Undef) {
if (simplifying && random)
sign = mtrand.randInt(1);
- /*else
- sign = polarity[next] ^ (mtrand.randInt(200) == 1);*/
+ #ifdef RANDOM_LOOKAROUND_SEARCHSPACE
else if (avgBranchDepth.isvalid())
- sign = polarity[next] ^ (mtrand.randInt(avgBranchDepth.getavg()) == 1);
+ sign = polarity[next] ^ (mtrand.randInt(avgBranchDepth.getavg() * ((lastSelectedRestartType == static_restart) ? 2 : 1) ) == 1);
+ #endif
else
sign = polarity[next];
}
| Effect:
| Will undo part of the trail, upto but not beyond the assumption of the current decision level.
|________________________________________________________________________________________________@*/
-Clause* Solver::analyze(Clause* confl, vec<Lit>& out_learnt, int& out_btlevel, int &nbLevels, const bool update)
+Clause* Solver::analyze(Clause* confl, vec<Lit>& out_learnt, int& out_btlevel, uint32_t &nbLevels, const bool update)
{
int pathC = 0;
Lit p = lit_Undef;
if (!seen[my_var] && level[my_var] > 0) {
varBumpActivity(my_var);
seen[my_var] = 1;
- if (level[my_var] >= decisionLevel()) {
+ if (level[my_var] >= (int)decisionLevel()) {
pathC++;
#ifdef UPDATEVARACTIVITY
- if ( reason[q.var()] != NULL && reason[q.var()]->learnt() )
- lastDecisionLevel.push(q);
+ if (lastSelectedRestartType == dynamic_restart && reason[q.var()] != NULL && reason[q.var()]->learnt())
+ lastDecisionLevel.push(q.var());
#endif
} else {
out_learnt.push(q);
out_btlevel = level[p.var()];
}
- nbLevels = 0;
- MYFLAG++;
- for(uint32_t i = 0; i != out_learnt.size(); i++) {
- int lev = level[out_learnt[i].var()];
- if (permDiff[lev] != MYFLAG) {
- permDiff[lev] = MYFLAG;
- nbLevels++;
- //merged += nbPropagated(lev);
- }
- }
-
- #ifdef UPDATEVARACTIVITY
- if (lastDecisionLevel.size() > 0) {
+ if (lastSelectedRestartType == dynamic_restart) {
+ nbLevels = calcNBLevels(out_learnt);
+ #ifdef UPDATEVARACTIVITY
for(uint32_t i = 0; i != lastDecisionLevel.size(); i++) {
- if (reason[lastDecisionLevel[i].var()]->activity() < nbLevels)
- varBumpActivity(lastDecisionLevel[i].var());
+ if (reason[lastDecisionLevel[i]]->activity() < nbLevels)
+ varBumpActivity(lastDecisionLevel[i]);
}
lastDecisionLevel.clear();
+ #endif
+ } else {
+ nbLevels = 1000;
}
- #endif
for (uint32_t j = 0; j != analyze_toclear.size(); j++)
seen[analyze_toclear[j].var()] = 0; // ('seen[]' is now cleared)
void Solver::uncheckedEnqueue(Lit p, ClausePtr from)
{
- #ifdef VERBOSE_DEBUG
- cout << "uncheckedEnqueue var " << p.var()+1 << " to " << !p.sign() << " level: " << decisionLevel() << " sublevel: " << trail.size() << endl;
- #endif
+
+ #ifdef DEBUG_UNCHECKEDENQUEUE_LEVEL0
+ #ifndef VERBOSE_DEBUG
+ if (decisionLevel() == 0)
+ #endif //VERBOSE_DEBUG
+ std::cout << "uncheckedEnqueue var " << p.var()+1 << " to " << !p.sign() << " level: " << decisionLevel() << " sublevel: " << trail.size() << std::endl;
+ #endif //DEBUG_UNCHECKEDENQUEUE_LEVEL0
+
+ //assert(decisionLevel() == 0 || !subsumer->getVarElimed()[p.var()]);
assert(assigns[p.var()].isUndef());
const Var v = p.var();
assigns [v] = boolToLBool(!p.sign());//lbool(!sign(p)); // <<== abstract but not uttermost effecient
level [v] = decisionLevel();
reason [v] = from;
+ #ifdef USE_OLD_POLARITIES
+ oldPolarity[p.var()] = polarity[p.var()];
+ #endif //USE_OLD_POLARITIES
polarity[p.var()] = p.sign();
trail.push(p);
#endif
}
-
/*_________________________________________________________________________________________________
|
| propagate : [void] -> [Clause*]
while (qhead < trail.size()) {
- Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate.
- vec<Watched>& ws = watches[p.toInt()];
- Watched *i, *j, *end;
-
//First propagate binary clauses
while (qheadBin < trail.size()) {
Lit p = trail[qheadBin++];
vec<WatchedBin> & wbin = binwatches[p.toInt()];
- num_props++;
- for(WatchedBin *k = wbin.getData(), *end = k + wbin.size(); k != end; k++) {
+ num_props += wbin.size()/2;
+ for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) {
lbool val = value(k->impliedLit);
if (val.isUndef()) {
uncheckedEnqueue(k->impliedLit, k->clause);
}
if (confl != NULL)
goto EndPropagate;
-
+
//Next, propagate normal clauses
+ Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate.
+ vec<Watched>& ws = watches[p.toInt()];
+ Watched *i, *j, *end;
+ num_props += ws.size();
#ifdef VERBOSE_DEBUG
cout << "Propagating lit " << (p.sign() ? '-' : ' ') << p.var()+1 << endl;
#endif
- for (i = j = ws.getData(), end = i + ws.size(); i != end;) {
+ for (i = j = ws.getData(), end = ws.getDataEnd(); i != end;) {
if (i+1 != end)
__builtin_prefetch((i+1)->clause, 1, 0);
j++;
} else {
// Look for new watch:
- for (Lit *k = &c[2], *end2 = c.getData()+c.size(); k != end2; k++) {
+ for (Lit *k = &c[2], *end2 = c.getDataEnd(); k != end2; k++) {
if (value(*k) != l_False) {
c[1] = *k;
*k = false_lit;
uncheckedEnqueue(first, &c);
#ifdef DYNAMICNBLEVEL
if (update && c.learnt() && c.activity() > 2) { // GA
- MYFLAG++;
- int nbLevels =0;
- for(Lit *l = c.getData(), *end2 = l+c.size(); l != end2; l++) {
- int lev = level[l->var()];
- if (permDiff[lev] != MYFLAG) {
- permDiff[lev] = MYFLAG;
- nbLevels++;
- }
-
- }
- if(nbLevels+1 < c.activity())
+ uint32_t nbLevels = calcNBLevels(c);
+ if (nbLevels+1 < c.activity())
c.setActivity(nbLevels);
}
#endif
FoundWatch:
;
}
- ws.shrink(i - j);
+ ws.shrink_(i - j);
//Finally, propagate XOR-clauses
if (xorclauses.size() > 0 && !confl) confl = propagate_xors(p);
return confl;
}
+Clause* Solver::propagateLight()
+{
+ Clause* confl = NULL;
+ uint32_t num_props = 0;
+ uint32_t qheadBin = qhead;
+
+ while (qhead < trail.size()) {
+
+ //First propagate binary clauses
+ while (qheadBin < trail.size()) {
+ Lit p = trail[qheadBin++];
+ vec<WatchedBin> & wbin = binwatches[p.toInt()];
+ num_props += wbin.size()/2;
+ for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) {
+ lbool val = value(k->impliedLit);
+ if (val.isUndef()) {
+ uncheckedEnqueueLight(k->impliedLit);
+ } else if (val == l_False) {
+ confl = k->clause;
+ goto EndPropagate;
+ }
+ }
+ }
+
+ //Next, propagate normal clauses
+ Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate.
+ vec<Watched>& ws = watches[p.toInt()];
+ Watched *i, *j, *end;
+ num_props += ws.size();
+
+ for (i = j = ws.getData(), end = ws.getDataEnd(); i != end;) {
+ if (i+1 != end)
+ __builtin_prefetch((i+1)->clause, 1, 0);
+
+ if(value(i->blockedLit).getBool()) { // Clause is sat
+ *j++ = *i++;
+ continue;
+ }
+ Lit bl = i->blockedLit;
+ Clause& c = *(i->clause);
+ i++;
+
+ // Make sure the false literal is data[1]:
+ const Lit false_lit(~p);
+ if (c[0] == false_lit)
+ c[0] = c[1], c[1] = false_lit;
+
+ assert(c[1] == false_lit);
+
+ // If 0th watch is true, then clause is already satisfied.
+ const Lit& first = c[0];
+ if (value(first).getBool()) {
+ j->clause = &c;
+ j->blockedLit = first;
+ j++;
+ } else {
+ // Look for new watch:
+ for (Lit *k = &c[2], *end2 = c.getDataEnd(); k != end2; k++) {
+ if (value(*k) != l_False) {
+ c[1] = *k;
+ *k = false_lit;
+ watches[(~c[1]).toInt()].push(Watched(&c, c[0]));
+ goto FoundWatch;
+ }
+ }
+
+ // Did not find watch -- clause is unit under assignment:
+ j->clause = &c;
+ j->blockedLit = bl;
+ j++;
+ if (value(first) == l_False) {
+ confl = &c;
+ qhead = trail.size();
+ // Copy the remaining watches:
+ while (i < end)
+ *j++ = *i++;
+ } else {
+ uncheckedEnqueueLight(first);
+ }
+ }
+ FoundWatch:
+ ;
+ }
+ ws.shrink_(i - j);
+
+ //Finally, propagate XOR-clauses
+ if (xorclauses.size() > 0 && !confl) confl = propagate_xors(p);
+ }
+ EndPropagate:
+ propagations += num_props;
+ simpDB_props -= num_props;
+
+ return confl;
+}
+
+Clause* Solver::propagateBin()
+{
+ while (qhead < trail.size()) {
+ Lit p = trail[qhead++];
+ vec<WatchedBin> & wbin = binwatches[p.toInt()];
+ propagations += wbin.size()/2;
+ for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) {
+ lbool val = value(k->impliedLit);
+ if (val.isUndef()) {
+ //uncheckedEnqueue(k->impliedLit, k->clause);
+ uncheckedEnqueueLight(k->impliedLit);
+ } else if (val == l_False) {
+ return k->clause;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+Clause* Solver::propagateBinNoLearnts()
+{
+ while (qhead < trail.size()) {
+ Lit p = trail[qhead++];
+ vec<WatchedBin> & wbin = binwatches[p.toInt()];
+ propagations += wbin.size()/2;
+ for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) {
+ if (k->clause->learnt()) continue;
+ lbool val = value(k->impliedLit);
+ if (val.isUndef()) {
+ //uncheckedEnqueue(k->impliedLit, k->clause);
+ uncheckedEnqueueLight(k->impliedLit);
+ } else if (val == l_False) {
+ return k->clause;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+template<bool dontCareLearnt>
+Clause* Solver::propagateBinExcept(const Lit& exceptLit)
+{
+ while (qhead < trail.size()) {
+ Lit p = trail[qhead++];
+ vec<WatchedBin> & wbin = binwatches[p.toInt()];
+ propagations += wbin.size()/2;
+ for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) {
+ if (!dontCareLearnt && k->clause->learnt()) continue;
+ lbool val = value(k->impliedLit);
+ if (val.isUndef() && k->impliedLit != exceptLit) {
+ //uncheckedEnqueue(k->impliedLit, k->clause);
+ uncheckedEnqueueLight(k->impliedLit);
+ } else if (val == l_False) {
+ return k->clause;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+template Clause* Solver::propagateBinExcept <true>(const Lit& exceptLit);
+template Clause* Solver::propagateBinExcept <false>(const Lit& exceptLit);
+
+template<bool dontCareLearnt>
+Clause* Solver::propagateBinOneLevel()
+{
+ Lit p = trail[qhead];
+ vec<WatchedBin> & wbin = binwatches[p.toInt()];
+ propagations += wbin.size()/2;
+ for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) {
+ if (!dontCareLearnt && k->clause->learnt()) continue;
+ lbool val = value(k->impliedLit);
+ if (val.isUndef()) {
+ //uncheckedEnqueue(k->impliedLit, k->clause);
+ uncheckedEnqueueLight(k->impliedLit);
+ } else if (val == l_False) {
+ return k->clause;
+ }
+ }
+
+ return NULL;
+}
+
+template Clause* Solver::propagateBinOneLevel <true>();
+template Clause* Solver::propagateBinOneLevel <false>();
+
+template<class T>
+inline const uint32_t Solver::calcNBLevels(const T& ps)
+{
+ MYFLAG++;
+ uint32_t nbLevels = 0;
+ for(const Lit *l = ps.getData(), *end = ps.getDataEnd(); l != end; l++) {
+ int32_t lev = level[l->var()];
+ if (permDiff[lev] != MYFLAG) {
+ permDiff[lev] = MYFLAG;
+ nbLevels++;
+ }
+ }
+ return nbLevels;
+}
+
Clause* Solver::propagate_xors(const Lit& p)
{
#ifdef VERBOSE_DEBUG_XOR
FoundWatch:
;
}
- ws.shrink(i - j);
+ ws.shrink_(i - j);
return confl;
}
// First criteria
if (xsize > 2 && ysize == 2) return 1;
if (ysize > 2 && xsize == 2) return 0;
-
- return x->oldActivity() < y->oldActivity();
+
+ if (x->oldActivity() == y->oldActivity())
+ return xsize > ysize;
+ else return x->oldActivity() < y->oldActivity();
}
bool reduceDB_ltGlucose::operator () (const Clause* x, const Clause* y) {
std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_ltMiniSat());
#ifdef VERBOSE_DEBUG
- std::cout << "Cleaning clauses" << endl;
+ std::cout << "Cleaning clauses" << std::endl;
for (uint i = 0; i != learnts.size(); i++) {
- std::cout << "activity:" << learnts[i]->activity() << " \tsize:" << learnts[i]->size() << std::endl;
+ std::cout << "activity:" << learnts[i]->activity()
+ << " \toldActivity:" << learnts[i]->oldActivity()
+ << " \tsize:" << learnts[i]->size() << std::endl;
}
#endif
-
+
const uint removeNum = (double)learnts.size() / (double)RATIOREMOVECLAUSES;
for (i = j = 0; i != removeNum; i++){
//NOTE: The next instruciton only works if removeNum < learnts.size() (strictly smaller!!)
__builtin_prefetch(learnts[i+1], 0, 0);
- if (learnts[i]->size() > 2 && !locked(*learnts[i]) && learnts[i]->activity() > 2)
- removeClause(*learnts[i]);
- else
+ if (learnts[i]->size() > 2 && !locked(*learnts[i]) && learnts[i]->activity() > 2) {
+ if (readdOldLearnts) {
+ detachClause(*learnts[i]);
+ removedLearnts.push(learnts[i]);
+ } else {
+ removeClause(*learnts[i]);
+ }
+ } else
learnts[j++] = learnts[i];
}
for (; i < learnts.size(); i++) {
printf("Error: Cannot open file '%s' to write learnt clauses!\n", file);
exit(-1);
}
-
+
+ fprintf(outfile, "c \nc ---------\n");
fprintf(outfile, "c unitaries\n");
- if (maxSize > 0) {
- if (trail_lim.size() > 0) {
- for (uint32_t i = 0; i != trail_lim[0]; i++) {
- fprintf(outfile,"%s%d 0\n", trail[i].sign() ? "-" : "", trail[i].var()+1);
- }
- }
- else {
- for (uint32_t i = 0; i != trail.size(); i++) {
- fprintf(outfile,"%s%d 0\n", trail[i].sign() ? "-" : "", trail[i].var()+1);
- }
- }
+ fprintf(outfile, "c ---------\n");
+ for (uint32_t i = 0, end = (trail_lim.size() > 0) ? trail_lim[0] : trail.size() ; i < end; i++) {
+ trail[i].printFull(outfile);
+ #ifdef STATS_NEEDED
+ if (dynamic_behaviour_analysis)
+ fprintf(outfile, "c name of var: %s\n", logger.get_var_name(trail[i].var()).c_str());
+ #endif //STATS_NEEDED
}
-
- fprintf(outfile, "c clauses from binaryClauses\n");
+
+ fprintf(outfile, "c conflicts %lu\n", conflicts);
+
+ fprintf(outfile, "c \nc ---------------------------------\n");
+ fprintf(outfile, "c learnt clauses from binaryClauses\n");
+ fprintf(outfile, "c ---------------------------------\n");
if (maxSize >= 2) {
for (uint i = 0; i != binaryClauses.size(); i++) {
- if (binaryClauses[i]->learnt())
- binaryClauses[i]->plainPrint(outfile);
+ if (binaryClauses[i]->learnt()) {
+ binaryClauses[i]->print(outfile);
+ }
}
}
-
- fprintf(outfile, "c clauses from learnts\n");
-
- if (lastSelectedRestartType == dynamic_restart)
- std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_ltGlucose());
- else
- std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_ltMiniSat());
- for (int i = learnts.size()-1; i >= 0 ; i--) {
- if (learnts[i]->size() <= maxSize)
- learnts[i]->plainPrint(outfile);
- }
-
+
+ fprintf(outfile, "c \nc ---------------------------------------\n");
fprintf(outfile, "c clauses representing 2-long XOR clauses\n");
+ fprintf(outfile, "c ---------------------------------------\n");
const vector<Lit>& table = varReplacer->getReplaceTable();
for (Var var = 0; var != table.size(); var++) {
Lit lit = table[var];
if (lit.var() == var)
continue;
-
+
fprintf(outfile, "%s%d %d 0\n", (!lit.sign() ? "-" : ""), lit.var()+1, var+1);
fprintf(outfile, "%s%d -%d 0\n", (lit.sign() ? "-" : ""), lit.var()+1, var+1);
+ #ifdef STATS_NEEDED
+ if (dynamic_behaviour_analysis)
+ fprintf(outfile, "c name of two vars that are anti/equivalent: '%s' and '%s'\n", logger.get_var_name(lit.var()).c_str(), logger.get_var_name(var).c_str());
+ #endif //STATS_NEEDED
+ }
+
+ fprintf(outfile, "c \nc --------------------n");
+ fprintf(outfile, "c clauses from learnts\n");
+ fprintf(outfile, "c --------------------n");
+ if (lastSelectedRestartType == dynamic_restart)
+ std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_ltGlucose());
+ else
+ std::sort(learnts.getData(), learnts.getData()+learnts.size(), reduceDB_ltMiniSat());
+ for (int i = learnts.size()-1; i >= 0 ; i--) {
+ if (learnts[i]->size() <= maxSize) {
+ learnts[i]->print(outfile);
+ }
}
fclose(outfile);
}
+const uint32_t Solver::getNumElimSubsume() const
+{
+ return subsumer->getNumElimed();
+}
+
+const uint32_t Solver::getNumElimXorSubsume() const
+{
+ return xorSubsumer->getNumElimed();
+}
+
+const uint32_t Solver::getNumXorTrees() const
+{
+ return varReplacer->getNumTrees();
+}
+
+const uint32_t Solver::getNumXorTreesCrownSize() const
+{
+ return varReplacer->getNumReplacedVars();
+}
+
+const double Solver::getTotalTimeSubsumer() const
+{
+ return subsumer->getTotalTime();
+}
+
+const double Solver::getTotalTimeXorSubsumer() const
+{
+ return xorSubsumer->getTotalTime();
+}
+
+
void Solver::setMaxRestarts(const uint num)
{
maxRestarts = num;
| Simplify the clause database according to the current top-level assigment. Currently, the only
| thing done here is the removal of satisfied clauses, but more things can be put here.
|________________________________________________________________________________________________@*/
-lbool Solver::simplify()
+const bool Solver::simplify()
{
+ testAllClauseAttach();
assert(decisionLevel() == 0);
if (!ok || propagate() != NULL) {
ok = false;
- return l_False;
+ return false;
}
if (simpDB_props > 0) {
- return l_Undef;
+ return true;
}
double slowdown = (100000.0/(double)binaryClauses.size());
(((double)abs64((int64_t)nbBin - (int64_t)lastNbBin + (int64_t)becameBinary)/BINARY_TO_XOR_APPROX) * slowdown) >
((double)order_heap.size() * PERCENTAGEPERFORMREPLACE * speedup)) {
lastSearchForBinaryXor = propagations;
+
clauseCleaner->cleanClauses(clauses, ClauseCleaner::clauses);
clauseCleaner->cleanClauses(learnts, ClauseCleaner::learnts);
clauseCleaner->removeSatisfied(binaryClauses, ClauseCleaner::binaryClauses);
- if (ok == false)
- return l_False;
-
+ if (!ok) return false;
+ testAllClauseAttach();
+
XorFinder xorFinder(*this, binaryClauses, ClauseCleaner::binaryClauses);
- if (xorFinder.doNoPart(2, 2) == false)
- return l_False;
+ if (!xorFinder.doNoPart(2, 2)) return false;
+ testAllClauseAttach();
lastNbBin = nbBin;
becameBinary = 0;
}
-
+
// Remove satisfied clauses:
clauseCleaner->removeAndCleanAll();
- if (ok == false)
- return l_False;
- if (performReplace && varReplacer->performReplace() == false)
- return l_False;
+ testAllClauseAttach();
+ if (!ok) return false;
+
+ if (performReplace && !varReplacer->performReplace())
+ return false;
// Remove fixed variables from the variable heap:
order_heap.filter(VarFilter(*this));
+ #ifdef USE_GAUSS
+ for (vector<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 = clauses_literals + learnts_literals; // (shouldn't depend on stats really, but it will do for now)
- return l_Undef;
+ testAllClauseAttach();
+ return true;
}
dynStarts++;
#ifdef USE_GAUSS
- for (vector<Gaussian*>::iterator gauss = gauss_matrixes.begin(), end= gauss_matrixes.end(); gauss != end; gauss++) {
- ret = (*gauss)->full_init();
- if (ret != l_Nothing) return ret;
+ for (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();
for (;;) {
Clause* confl = propagate(update);
assert(false);
break;
}
- if (nof_conflicts_fullrestart >= 0 && conflicts >= nof_conflicts_fullrestart) {
+ if (nof_conflicts_fullrestart >= 0 && (int)conflicts >= nof_conflicts_fullrestart) {
#ifdef STATS_NEEDED
if (dynamic_behaviour_analysis)
progress_estimate = progressEstimate();
}
// Simplify the set of problem clauses:
- if (decisionLevel() == 0 && simplify() == l_False) {
+ if (decisionLevel() == 0 && !simplify()) {
return l_False;
}
#endif
int backtrack_level;
- int nbLevels;
+ uint32_t nbLevels;
conflicts++;
conflictC++;
learnt_clause.clear();
Clause* c = analyze(confl, learnt_clause, backtrack_level, nbLevels, update);
if (update) {
+ #ifdef RANDOM_LOOKAROUND_SEARCHSPACE
avgBranchDepth.push(decisionLevel());
+ #endif //RANDOM_LOOKAROUND_SEARCHSPACE
if (restartType == dynamic_restart)
nbDecisionLevelHistory.push(nbLevels);
+
totalSumOfDecisionLevel += nbLevels;
} else {
conflictsAtLastSolve++;
} else {
if (c) {
detachClause(*c);
- for (uint i = 0; i != learnt_clause.size(); i++)
+ for (uint32_t i = 0; i != learnt_clause.size(); i++)
(*c)[i] = learnt_clause[i];
c->resize(learnt_clause.size());
- if (c->learnt() && c->activity() > nbLevels)
- c->setActivity(nbLevels); // LS
+ if (c->learnt()) {
+ if (c->activity() > nbLevels)
+ c->setActivity(nbLevels); // LS
+ if (c->size() == 2)
+ nbBin++;
+ }
c->setStrenghtened();
} else {
c = Clause_new(learnt_clause, learnt_clause_group++, true);
}
#ifdef USE_GAUSS
-void Solver::print_gauss_sum_stats() const
+void Solver::print_gauss_sum_stats()
{
- if (gauss_matrixes.size() == 0) {
+ if (gauss_matrixes.size() == 0 && verbosity >= 2) {
printf(" no matrixes found |\n");
return;
}
called += (*gauss)->get_called();
useful_prop += (*gauss)->get_useful_prop();
useful_confl += (*gauss)->get_useful_confl();
+ sum_gauss_unit_truths += (*gauss)->get_unit_truths();
//gauss->print_stats();
//gauss->print_matrix_stats();
}
+ sum_gauss_called += called;
+ sum_gauss_confl += useful_confl;
+ sum_gauss_prop += useful_prop;
- if (called == 0) {
- printf(" disabled |\n");
- } else {
- printf(" %3.0lf%% |", (double)useful_prop/(double)called*100.0);
- printf(" %3.0lf%% |", (double)useful_confl/(double)called*100.0);
- printf(" %3.0lf%% |\n", 100.0-(double)disabled/(double)gauss_matrixes.size()*100.0);
+ if (verbosity >= 2) {
+ if (called == 0) {
+ printf(" disabled |\n");
+ } else {
+ printf(" %3.0lf%% |", (double)useful_prop/(double)called*100.0);
+ printf(" %3.0lf%% |", (double)useful_confl/(double)called*100.0);
+ printf(" %3.0lf%% |\n", 100.0-(double)disabled/(double)gauss_matrixes.size()*100.0);
+ }
}
}
#endif //USE_GAUSS
-inline void Solver::chooseRestartType(const uint& lastFullRestart)
+const bool Solver::chooseRestartType(const uint& lastFullRestart)
{
uint relativeStart = starts - lastFullRestart;
tmp = fixRestartType;
if (tmp == dynamic_restart) {
- lastSelectedRestartType = dynamic_restart;
nbDecisionLevelHistory.fastclear();
nbDecisionLevelHistory.initSize(100);
if (verbosity >= 2)
printf("c | Decided on dynamic restart strategy |\n");
} else {
- lastSelectedRestartType = static_restart;
if (verbosity >= 2)
printf("c | Decided on static restart strategy |\n");
#ifdef USE_GAUSS
- if (gaussconfig.decision_until > 0 && xorclauses.size() > 1 && xorclauses.size() < 20000) {
- double time = cpuTime();
- MatrixFinder m(*this);
- const uint numMatrixes = m.findMatrixes();
- if (verbosity >=1)
- printf("c | Finding matrixes : %4.2lf s (found %5d) |\n", cpuTime()-time, numMatrixes);
- }
+ if (!matrixFinder->findMatrixes()) return false;
#endif //USE_GAUSS
}
+ lastSelectedRestartType = tmp;
restartType = tmp;
restartTypeChooser->reset();
}
}
+
+ return true;
}
inline void Solver::setDefaultRestartType()
lastSelectedRestartType = restartType;
}
-const lbool Solver::simplifyProblem(const uint32_t numConfls, const uint64_t numProps)
+const lbool Solver::simplifyProblem(const uint32_t numConfls)
{
- Heap<VarOrderLt> backup_order_heap(order_heap);
- vector<bool> backup_polarities = polarity;
- RestartType backup_restartType= restartType;
- uint32_t backup_random_var_freq = random_var_freq;
- vec<uint32_t> backup_activity(activity.size());
- std::copy(activity.getData(), activity.getDataEnd(), backup_activity.getData());
- uint32_t backup_var_inc = var_inc;
-
+ testAllClauseAttach();
+ #ifdef USE_GAUSS
+ bool gauss_was_cleared = (gauss_matrixes.size() == 0);
+ clearGaussMatrixes();
+ #endif //USE_GAUSS
+
+ StateSaver savedState(*this);;
+
+ #ifdef BURST_SEARCH
if (verbosity >= 2)
std::cout << "c | " << std::setw(24) << " "
<< "Simplifying problem for " << std::setw(8) << numConfls << " confls"
random_var_freq = 1;
simplifying = true;
uint64_t origConflicts = conflicts;
+ #endif //BURST_SEARCH
lbool status = l_Undef;
+
+ #ifdef BURST_SEARCH
restartType = static_restart;
while(status == l_Undef && conflicts-origConflicts < numConfls) {
if (status != l_Undef)
goto end;
printRestartStat();
-
- if (heuleProcess && xorclauses.size() > 1) {
- if (!conglomerate->heuleProcessFull()) {
- status = l_False;
- goto end;
- }
-
- while (performReplace && varReplacer->needsReplace()) {
- if (!varReplacer->performReplace()) {
- status = l_False;
- goto end;
- }
- if (!conglomerate->heuleProcessFull()) {
- status = l_False;
- goto end;
- }
- }
+ #endif //BURST_SEARCH
+
+ if (doXorSubsumption && !xorSubsumer->simplifyBySubsumption()) {
+ status = l_False;
+ goto end;
}
-
- if (failedVarSearch && !failedVarSearcher->search((nClauses() < 500000 && order_heap.size() < 50000) ? 6000000 : 2000000)) {
+ testAllClauseAttach();
+
+ if (failedVarSearch && !failedVarSearcher->search((nClauses() < 500000 && order_heap.size() < 50000) ? 9000000 : 3000000)) {
status = l_False;
goto end;
}
-
- if (doXorSubsumption && xorclauses.size() > 1) {
- XorSubsumer xsub(*this);
- if (!xsub.simplifyBySubsumption()) {
- status = l_False;
- goto end;
- }
+ testAllClauseAttach();
+
+ if (regularRemoveUselessBins
+ && !failedVarSearcher->removeUslessBinFull<false>()) {
+ status = l_False;
+ goto end;
}
-
- if (doSubsumption) {
- if (!subsumer->simplifyBySubsumption()) {
- status = l_False;
- goto end;
- }
+
+ if (regularSubsumeWithNonExistBinaries
+ && !subsumer->subsumeWithBinaries(false)) {
+ status = l_False;
+ goto end;
}
+
+ if (doSubsumption && !subsumer->simplifyBySubsumption()) {
+ status = l_False;
+ goto end;
+ }
+ testAllClauseAttach();
/*if (findNormalXors && xorclauses.size() > 200 && clauses.size() < MAX_CLAUSENUM_XORFIND/8) {
XorFinder xorFinder(*this, clauses, ClauseCleaner::clauses);
}
end:
- random_var_freq = backup_random_var_freq;
+ #ifdef BURST_SEARCH
if (verbosity >= 2)
printf("c Simplifying finished |\n");
-
- var_inc = backup_var_inc;
- std::copy(backup_activity.getData(), backup_activity.getDataEnd(), activity.getData());
- order_heap = backup_order_heap;
+ #endif //#ifdef BURST_SEARCH
+
+
+ savedState.restore();
simplifying = false;
- order_heap.filter(VarFilter(*this));
- polarity = backup_polarities;
- restartType = backup_restartType;
+ #ifdef USE_GAUSS
+ if (status == l_Undef && !gauss_was_cleared && !matrixFinder->findMatrixes())
+ status = l_False;
+ #endif //USE_GAUSS
+
+ testAllClauseAttach();
return status;
}
const bool Solver::checkFullRestart(int& nof_conflicts, int& nof_conflicts_fullrestart, uint& lastFullRestart)
{
- if (nof_conflicts_fullrestart > 0 && conflicts >= nof_conflicts_fullrestart) {
+ if (nof_conflicts_fullrestart > 0 && (int)conflicts >= nof_conflicts_fullrestart) {
#ifdef USE_GAUSS
clearGaussMatrixes();
#endif //USE_GAUSS
if (doPartHandler && !partHandler->handle())
return false;
- /*if (calculateDefaultPolarities() == l_False)
- return false;
- setDefaultPolarities();*/
+ //calculateDefaultPolarities();
fullStarts++;
}
inline void Solver::performStepsBeforeSolve()
{
assert(qhead == trail.size());
+ testAllClauseAttach();
+
if (performReplace && !varReplacer->performReplace()) return;
+
+ if (conflicts == 0 && learnts.size() == 0
+ && noLearntBinaries()) {
+ if (subsumeWithNonExistBinaries && !subsumer->subsumeWithBinaries(true)) return;
+ if (removeUselessBins && !failedVarSearcher->removeUslessBinFull<true>()) return;
+ }
-
+ testAllClauseAttach();
if (doSubsumption
&& !libraryUsage
&& clauses.size() + binaryClauses.size() + learnts.size() < 4800000
&& !subsumer->simplifyBySubsumption())
return;
+
+ if (conflicts == 0 && learnts.size() == 0
+ && noLearntBinaries()) {
+ if (subsumeWithNonExistBinaries && !subsumer->subsumeWithBinaries(true)) return;
+ if (removeUselessBins && !failedVarSearcher->removeUslessBinFull<true>()) return;
+ }
+ testAllClauseAttach();
if (findBinaryXors && binaryClauses.size() < MAX_CLAUSENUM_XORFIND) {
XorFinder xorFinder(*this, binaryClauses, ClauseCleaner::binaryClauses);
if (!xorFinder.doNoPart(2, 2)) return;
-
if (performReplace && !varReplacer->performReplace(true)) return;
}
+ testAllClauseAttach();
if (findNormalXors && clauses.size() < MAX_CLAUSENUM_XORFIND) {
XorFinder xorFinder(*this, clauses, ClauseCleaner::clauses);
if (!xorFinder.doNoPart(3, 7)) return;
}
-
+
if (xorclauses.size() > 1) {
- if (heuleProcess) {
- if (!conglomerate->heuleProcessFull()) return;
-
- while (performReplace && varReplacer->needsReplace()) {
- if (!varReplacer->performReplace()) return;
- if (!conglomerate->heuleProcessFull()) return;
- }
- }
-
- if (conglomerateXors && !conglomerate->conglomerateXorsFull())
+ testAllClauseAttach();
+ if (doXorSubsumption && !xorSubsumer->simplifyBySubsumption())
return;
- if (doXorSubsumption && xorclauses.size() > 1) {
- XorSubsumer xsub(*this);
- if (!xsub.simplifyBySubsumption())
- return;
- }
-
+ testAllClauseAttach();
if (performReplace && !varReplacer->performReplace())
return;
}
setDefaultRestartType();
totalSumOfDecisionLevel = 0;
conflictsAtLastSolve = conflicts;
+ #ifdef RANDOM_LOOKAROUND_SEARCHSPACE
avgBranchDepth.fastclear();
avgBranchDepth.initSize(500);
-
- if (!conglomerate->addRemovedClauses()) return l_False;
+ #endif //RANDOM_LOOKAROUND_SEARCHSPACE
starts = 0;
assumps.copyTo(assumptions);
int nof_conflicts = restart_first;
- int nof_conflicts_fullrestart = (double)restart_first * (double)FULLRESTART_MULTIPLIER + conflicts;
+ int nof_conflicts_fullrestart = restart_first * FULLRESTART_MULTIPLIER + conflicts;
//nof_conflicts_fullrestart = -1;
uint lastFullRestart = starts;
lbool status = l_Undef;
- uint64_t nextSimplify = 30000 + conflicts;
+ uint64_t nextSimplify = restart_first * SIMPLIFY_MULTIPLIER + conflicts;
if (nClauses() * learntsize_factor < nbclausesbeforereduce) {
if (nClauses() * learntsize_factor < nbclausesbeforereduce/2)
else
nbclausesbeforereduce = (nClauses() * learntsize_factor)/2;
}
+ testAllClauseAttach();
+ findAllAttach();
if (conflicts == 0) {
performStepsBeforeSolve();
if (!ok) return l_False;
printStatHeader();
- if (calculateDefaultPolarities() == l_False)
- return l_False;
- setDefaultPolarities();
}
+ calculateDefaultPolarities();
// Search:
while (status == l_Undef && starts < maxRestarts) {
+ #ifdef DEBUG_VARELIM
+ assert(subsumer->checkElimedUnassigned());
+ assert(xorSubsumer->checkElimedUnassigned());
+ #endif //DEBUG_VARELIM
if (schedSimplification && conflicts >= nextSimplify) {
- status = simplifyProblem(500, 7000000);
+ status = simplifyProblem(500);
nextSimplify = conflicts * 1.5;
if (status != l_Undef) break;
}
status = search(nof_conflicts, nof_conflicts_fullrestart);
nof_conflicts = (double)nof_conflicts * restart_inc;
+ if (status != l_Undef) break;
if (!checkFullRestart(nof_conflicts, nof_conflicts_fullrestart, lastFullRestart))
return l_False;
- chooseRestartType(lastFullRestart);
+ if (!chooseRestartType(lastFullRestart))
+ return l_False;
+ #ifdef RANDOM_LOOKAROUND_SEARCHSPACE
//if (avgBranchDepth.isvalid())
// std::cout << "avg branch depth:" << avgBranchDepth.getavg() << std::endl;
+ #endif //RANDOM_LOOKAROUND_SEARCHSPACE
}
printEndSearchStat();
if (verbosity >= 1)
printf("c Greedy unbounding :%5.2lf s, unbounded: %7d vars\n", cpuTime()-time, unbounded);
}
-
+
partHandler->addSavedState();
varReplacer->extendModelPossible();
#ifndef NDEBUG
//checkSolution();
#endif
- if (subsumer->getNumElimed() > 0 || conglomerate->needCalcAtFinish()) {
+ if (subsumer->getNumElimed() || xorSubsumer->getNumElimed()) {
#ifdef VERBOSE_DEBUG
std::cout << "Solution needs extension. Extending." << std::endl;
#endif //VERBOSE_DEBUG
s.conglomerateXors = false;
s.greedyUnbound = greedyUnbound;
for (Var var = 0; var < nVars(); var++) {
- s.newVar(decision_var[var] || subsumer->getVarElimed()[var] || varReplacer->varHasBeenReplaced(var) || conglomerate->getRemovedVars()[var]);
+ s.newVar(decision_var[var] || subsumer->getVarElimed()[var] || varReplacer->varHasBeenReplaced(var) || xorSubsumer->getVarElimed()[var]);
- assert(!(conglomerate->getRemovedVars()[var] && (decision_var[var] || subsumer->getVarElimed()[var] || varReplacer->varHasBeenReplaced(var))));
+ //assert(!(xorSubsumer->getVarElimed()[var] && (decision_var[var] || subsumer->getVarElimed()[var] || varReplacer->varHasBeenReplaced(var))));
if (value(var) != l_Undef) {
- assert(!conglomerate->getRemovedVars()[var]);
vec<Lit> tmp;
tmp.push(Lit(var, value(var) == l_False));
s.addClause(tmp);
}
varReplacer->extendModelImpossible(s);
subsumer->extendModel(s);
- conglomerate->extendModel(s);
+ xorSubsumer->extendModel(s);
status = s.solve();
if (status != l_True) {
XorClause* c2 = XorClause_new(c, c.xor_clause_inverted(), c.getGroup());
std::sort(c2->getData(), c2->getData()+ c2->size());
c2->plainPrint();
- free(c2);
+ clauseFree(c2);
#endif
for (uint j = 0; j < c.size(); j++) {
{
assert(!verifyClauses(clauses));
assert(!verifyClauses(binaryClauses));
-
assert(!verifyXorClauses(xorclauses));
- assert(!verifyXorClauses(conglomerate->getCalcAtFinish()));
if (verbosity >=1)
- printf("c Verified %d clauses.\n", clauses.size() + xorclauses.size() + conglomerate->getCalcAtFinish().size());
+ printf("c Verified %d clauses.\n", clauses.size() + xorclauses.size());
}
}
}
-void Solver::printRestartStat() const
+void Solver::printRestartStat()
{
- #ifdef STATS_NEEDED
- if (verbosity >= 2 && !(dynamic_behaviour_analysis && logger.statistics_on)) {
- #else
if (verbosity >= 2) {
- #endif
- printf("c | %9d | %7d %8d %8d | %8d %8d %6.0f |", (int)conflicts, (int)order_heap.size(), (int)nClauses(), (int)clauses_literals, (int)(nbclausesbeforereduce*curRestart+nbCompensateSubsumer), (int)nLearnts(), (double)learnts_literals/nLearnts());
- #ifdef USE_GAUSS
- print_gauss_sum_stats();
- #else //USE_GAUSS
+ printf("c | %9d | %7d %8d %8d | %8d %8d %6.0f |", (int)conflicts, (int)order_heap.size(), (int)(nClauses()-nbBin), (int)clauses_literals, (int)(nbclausesbeforereduce*curRestart+nbCompensateSubsumer), (int)(nLearnts()+nbBin), (double)learnts_literals/(double)(nLearnts()+nbBin));
+ }
+
+ #ifdef USE_GAUSS
+ print_gauss_sum_stats();
+ #else //USE_GAUSS
+ if (verbosity >= 2) {
printf(" |\n");
- #endif //USE_GAUSS
}
+ #endif //USE_GAUSS
}
-void Solver::printEndSearchStat() const
+void Solver::printEndSearchStat()
{
#ifdef STATS_NEEDED
if (verbosity >= 1 && !(dynamic_behaviour_analysis && logger.statistics_on)) {
}
}
-}; //NAMESPACE MINISAT
+#ifdef DEBUG_ATTACH
+void Solver::testAllClauseAttach() const
+{
+ for (Clause *const*it = clauses.getData(), *const*end = clauses.getDataEnd(); it != end; it++) {
+ const Clause& c = **it;
+ if (c.size() > 2) {
+ assert(findWatchedCl(watches[(~c[0]).toInt()], &c));
+ assert(findWatchedCl(watches[(~c[1]).toInt()], &c));
+ } else {
+ assert(findWatchedBinCl(binwatches[(~c[0]).toInt()], &c));
+ assert(findWatchedBinCl(binwatches[(~c[1]).toInt()], &c));
+ }
+ }
+
+ for (Clause *const*it = binaryClauses.getData(), *const*end = binaryClauses.getDataEnd(); it != end; it++) {
+ const Clause& c = **it;
+ assert(c.size() == 2);
+ assert(findWatchedBinCl(binwatches[(~c[0]).toInt()], &c));
+ assert(findWatchedBinCl(binwatches[(~c[1]).toInt()], &c));
+ }
+
+ for (XorClause *const*it = xorclauses.getData(), *const*end = xorclauses.getDataEnd(); it != end; it++) {
+ const XorClause& c = **it;
+ assert(find(xorwatches[c[0].var()], &c));
+ assert(find(xorwatches[c[1].var()], &c));
+ if (assigns[c[0].var()]!=l_Undef || assigns[c[1].var()]!=l_Undef) {
+ for (uint i = 0; i < c.size();i++) {
+ assert(assigns[c[i].var()] != l_Undef);
+ }
+ }
+ }
+}
+
+void Solver::findAllAttach() const
+{
+ for (uint32_t i = 0; i < binwatches.size(); i++) {
+ for (uint32_t i2 = 0; i2 < binwatches[i].size(); i2++) {
+ assert(findClause(binwatches[i][i2].clause));
+ }
+ }
+ for (uint32_t i = 0; i < watches.size(); i++) {
+ for (uint32_t i2 = 0; i2 < watches[i].size(); i2++) {
+ assert(findClause(watches[i][i2].clause));
+ }
+ }
+
+ for (uint32_t i = 0; i < xorwatches.size(); i++) {
+ for (uint32_t i2 = 0; i2 < xorwatches[i].size(); i2++) {
+ assert(findClause(xorwatches[i][i2]));
+ }
+ }
+}
+
+const bool Solver::findClause(XorClause* c) const
+{
+ for (uint32_t i = 0; i < xorclauses.size(); i++) {
+ if (xorclauses[i] == c) return true;
+ }
+ return false;
+}
+
+const bool Solver::findClause(Clause* c) const
+{
+ for (uint32_t i = 0; i < binaryClauses.size(); i++) {
+ if (binaryClauses[i] == c) return true;
+ }
+ for (uint32_t i = 0; i < clauses.size(); i++) {
+ if (clauses[i] == c) return true;
+ }
+ for (uint32_t i = 0; i < learnts.size(); i++) {
+ if (learnts[i] == c) return true;
+ }
+ vec<Clause*> cs = varReplacer->getClauses();
+ for (uint32_t i = 0; i < cs.size(); i++) {
+ if (cs[i] == c) return true;
+ }
+
+ return false;
+}
+#endif //DEBUG_ATTACH
+const bool Solver::noLearntBinaries() const
+{
+ for (uint32_t i = 0; i < binaryClauses.size(); i++) {
+ if (binaryClauses[i]->learnt()) return false;
+ }
+
+ return true;
+}
+
+}; //NAMESPACE MINISAT
class ClauseCleaner;
class FailedVarSearcher;
class Subsumer;
+class XorSubsumer;
class PartHandler;
class RestartTypeChooser;
+class StateSaver;
#ifdef VERBOSE_DEBUG
+#define DEBUG_UNCHECKEDENQUEUE_LEVEL0
using std::cout;
using std::endl;
#endif
bool doVarElim; // Perform variable elimination
bool doSubsume1; // Perform clause contraction through resolution
bool failedVarSearch; // Should search for failed vars and doulbly propagated vars
+ bool readdOldLearnts; // Should re-add old learnts for failed variable searching
+ bool addExtraBins; // Should add extra binaries in failed literal probing
+ bool removeUselessBins; // Should try to remove useless binary clauses
+ bool regularRemoveUselessBins; // Should try to remove useless binary clauses regularly
+ bool subsumeWithNonExistBinaries;
+ bool regularSubsumeWithNonExistBinaries;
bool libraryUsage; // Set true if not used as a library
friend class FindUndef;
bool greedyUnbound; //If set, then variables will be greedily unbounded (set to l_Undef)
GaussianConfig gaussconfig;
- enum { polarity_true = 0, polarity_false = 1, polarity_rnd = 3, polarity_auto = 4, polarity_manual = 5};
+ enum { polarity_true = 0, polarity_false = 1, polarity_rnd = 3, polarity_auto = 4};
// Statistics: (read-only member variable)
//
void dumpSortedLearnts(const char* file, const uint32_t maxSize); // Dumps all learnt clauses (including unitary ones) into the file
void needLibraryCNFFile(const char* fileName); //creates file in current directory with the filename indicated, and puts all calls from the library into the file.
+ #ifdef USE_GAUSS
+ const uint32_t get_sum_gauss_called() const;
+ const uint32_t get_sum_gauss_confl() const;
+ const uint32_t get_sum_gauss_prop() const;
+ const uint32_t get_sum_gauss_unit_truths() const;
+ #endif //USE_GAUSS
+
+ //Printing statistics
+ const uint32_t getNumElimSubsume() const; // Get variable elimination stats from Subsumer
+ const uint32_t getNumElimXorSubsume() const; // Get variable elimination stats from XorSubsumer
+ const uint32_t getNumXorTrees() const; // Get the number of trees built from 2-long XOR-s. This is effectively the number of variables that replace other variables
+ const uint32_t getNumXorTreesCrownSize() const; // Get the number of variables being replaced by other variables
+ const double getTotalTimeSubsumer() const;
+ const double getTotalTimeXorSubsumer() const;
+
protected:
#ifdef USE_GAUSS
- void print_gauss_sum_stats() const;
+ void print_gauss_sum_stats();
void clearGaussMatrixes();
vector<Gaussian*> gauss_matrixes;
- #endif //USE_GAUSS
+
+ //stats
+ uint32_t sum_gauss_called;
+ uint32_t sum_gauss_confl;
+ uint32_t sum_gauss_prop;
+ uint32_t sum_gauss_unit_truths;
friend class Gaussian;
+ #endif //USE_GAUSS
template <class T>
Clause* addClauseInt(T& ps, uint group);
template<class T>
void removeWatchedCl(vec<T> &ws, const Clause *c);
template<class T>
- bool findWatchedCl(vec<T>& ws, const Clause *c);
+ bool findWatchedCl(const vec<T>& ws, const Clause *c) const;
template<class T>
void removeWatchedBinCl(vec<T> &ws, const Clause *c);
template<class T>
- bool findWatchedBinCl(vec<T>& ws, const Clause *c);
+ bool findWatchedBinCl(const vec<T>& ws, const Clause *c) const;
// Helper structures:
//
vec<Clause*> binaryClauses; // Binary clauses are regularly moved here
vec<XorClause*> xorclauses; // List of problem xor-clauses. Will be freed
vec<Clause*> learnts; // List of learnt clauses.
+ vec<Clause*> removedLearnts; // Clauses that have been learnt, then removed
+ vec<XorClause*> freeLater; // xor clauses that need to be freed later due to Gauss
vec<uint32_t> activity; // A heuristic measurement of the activity of a variable.
uint32_t var_inc; // Amount to bump next variable with.
double cla_inc; // Amount to bump learnt clause oldActivity with
vec<vec<WatchedBin> > binwatches;
vec<lbool> assigns; // The current assignments
vector<bool> polarity; // The preferred polarity of each variable.
+ #ifdef USE_OLD_POLARITIES
+ vector<bool> oldPolarity; // The polarity before the last setting. Good for unsetting polairties that have been changed since the last conflict
+ #endif //USE_OLD_POLARITIES
vector<bool> decision_var; // Declares if a variable is eligible for selection in the decision heuristic.
vec<Lit> trail; // Assignment stack; stores all assigments made in the order they were made.
vec<uint32_t> trail_lim; // Separator indices for different decision levels in 'trail'.
vec<ClausePtr> reason; // 'reason[var]' is the clause that implied the variables current value, or 'NULL' if none.
vec<int32_t> level; // 'level[var]' contains the level at which the assignment was made.
- vec<Var> permDiff; // LS: permDiff[var] contains the current conflict number... Used to count the number of different decision level variables in learnt clause
- #ifdef UPDATEVARACTIVITY
- vec<Lit> lastDecisionLevel;
- #endif
uint64_t curRestart;
uint32_t nbclausesbeforereduce;
uint32_t nbCompensateSubsumer; // Number of learnt clauses that subsumed normal clauses last time subs. was executed
bqueue<uint> nbDecisionLevelHistory; // Set of last decision level in conflict clauses
double totalSumOfDecisionLevel;
uint64_t conflictsAtLastSolve;
+ #ifdef RANDOM_LOOKAROUND_SEARCHSPACE
bqueue<uint> avgBranchDepth; // Avg branch depth
+ #endif //RANDOM_LOOKAROUND_SEARCHSPACE
MTRand mtrand; // random number generaton
RestartType restartType; // Used internally to determine which restart strategy to choose
RestartType lastSelectedRestartType; //the last selected restart type
vec<Lit> analyze_stack;
vec<Lit> analyze_toclear;
vec<Lit> add_tmp;
- unsigned long int MYFLAG;
+
+
+ uint64_t MYFLAG;
+ template<class T>
+ const uint32_t calcNBLevels(const T& ps);
+ vec<uint64_t> permDiff; // LS: permDiff[var] contains the current conflict number... Used to count the number of different decision level variables in learnt clause
+ #ifdef UPDATEVARACTIVITY
+ vec<Var> lastDecisionLevel;
+ #endif
//Logging
uint learnt_clause_group; //the group number of learnt clauses. Incremented at each added learnt clause
// Main internal methods:
//
- lbool simplify (); // Removes already satisfied clauses.
+ const bool simplify (); // Removes already satisfied clauses.
//int nbPropagated (int level);
void insertVarOrder (Var x); // Insert a variable in the decision order priority queue.
Lit pickBranchLit (); // Return the next decision variable.
void newDecisionLevel (); // Begins a new decision level.
void uncheckedEnqueue (Lit p, ClausePtr from = (Clause*)NULL); // Enqueue a literal. Assumes value of literal is undefined.
+ void uncheckedEnqueueLight (const Lit p);
bool enqueue (Lit p, Clause* from = NULL); // Test if fact 'p' contradicts current state, enqueue otherwise.
Clause* propagate (const bool update = true); // Perform unit propagation. Returns possibly conflicting clause.
+ Clause* propagateLight();
+ Clause* propagateBin();
+ Clause* propagateBinNoLearnts();
+ template<bool dontCareLearnt>
+ Clause* propagateBinExcept(const Lit& exceptLit);
+ template<bool dontCareLearnt>
+ Clause* propagateBinOneLevel();
Clause* propagate_xors (const Lit& p);
void cancelUntil (int level); // Backtrack until a certain level.
- Clause* analyze (Clause* confl, vec<Lit>& out_learnt, int& out_btlevel, int &nblevels, const bool update); // (bt = backtrack)
+ Clause* analyze (Clause* confl, vec<Lit>& out_learnt, int& out_btlevel, uint32_t &nblevels, const bool update); // (bt = backtrack)
void analyzeFinal (Lit p, vec<Lit>& out_conflict); // COULD THIS BE IMPLEMENTED BY THE ORDINARIY "analyze" BY SOME REASONABLE GENERALIZATION?
bool litRedundant (Lit p, uint32_t abstract_levels); // (helper method for 'analyze()')
lbool search (int nof_conflicts, int nof_conflicts_fullrestart, const bool update = true); // Search for a given number of conflicts.
void removeClause(T& c); // Detach and free a clause.
bool locked (const Clause& c) const; // Returns TRUE if a clause is a reason for some implication in the current state.
void reverse_binary_clause(Clause& c) const; // Binary clauses --- the first Lit has to be true
+ void testAllClauseAttach() const;
+ void findAllAttach() const;
+ const bool findClause(XorClause* c) const;
+ const bool findClause(Clause* c) const;
// Misc:
//
friend class Subsumer;
friend class XorSubsumer;
friend class PartHandler;
+ friend class StateSaver;
Conglomerate* conglomerate;
VarReplacer* varReplacer;
ClauseCleaner* clauseCleaner;
FailedVarSearcher* failedVarSearcher;
PartHandler* partHandler;
Subsumer* subsumer;
+ XorSubsumer* xorSubsumer;
RestartTypeChooser* restartTypeChooser;
- void chooseRestartType(const uint& lastFullRestart);
+ MatrixFinder* matrixFinder;
+ const bool chooseRestartType(const uint& lastFullRestart);
void setDefaultRestartType();
const bool checkFullRestart(int& nof_conflicts, int& nof_conflicts_fullrestart, uint& lastFullRestart);
void performStepsBeforeSolve();
- const lbool simplifyProblem(const uint32_t numConfls, const uint64_t numProps);
+ const lbool simplifyProblem(const uint32_t numConfls);
bool simplifying;
// Debug & etc:
void checkSolution();
void checkLiteralCount();
void printStatHeader () const;
- void printRestartStat () const;
- void printEndSearchStat() const;
+ void printRestartStat ();
+ void printEndSearchStat();
double progressEstimate () const; // DELETE THIS ?? IT'S NOT VERY USEFUL ...
+ const bool noLearntBinaries() const;
// Polarity chooser
- vector<bool> defaultPolarities; //The default polarity to set the var polarity when doing a full restart
- const lbool calculateDefaultPolarities(); //Calculates the default polarity for each var, and fills defaultPolarities[] with it
- bool defaultPolarity(); //if polarity_mode is not polarity_auto, this returns the default polarity of the variable
- void setDefaultPolarities(); //sets the polarity[] to that indicated by defaultPolarities[]
+ void calculateDefaultPolarities(); //Calculates the default polarity for each var, and fills defaultPolarities[] with it
+ bool defaultPolarity(); //if polarity_mode is not polarity_auto, this returns the default polarity of the variable
+ void tallyVotes(const vec<Clause*>& cs, vector<double>& votes) const;
+ void tallyVotes(const vec<XorClause*>& cs, vector<double>& votes) const;
};
inline void Solver::claDecayActivity()
{
- cla_inc *= clause_decay;
+ //cla_inc *= clause_decay;
}
inline bool Solver::enqueue (Lit p, Clause* from)
{}
#endif
+#ifdef USE_GAUSS
+inline const uint32_t Solver::get_sum_gauss_unit_truths() const
+{
+ return sum_gauss_unit_truths;
+}
+
+inline const uint32_t Solver::get_sum_gauss_called() const
+{
+ return sum_gauss_called;
+}
+
+inline const uint32_t Solver::get_sum_gauss_confl() const
+{
+ return sum_gauss_confl;
+}
+
+inline const uint32_t Solver::get_sum_gauss_prop() const
+{
+ return sum_gauss_prop;
+}
+#endif
+
inline const uint Solver::get_unitary_learnts_num() const
{
if (decisionLevel() > 0)
ws.pop();
}
template<class T>
-inline bool Solver::findWatchedCl(vec<T>& ws, const Clause *c)
+inline bool Solver::findWatchedCl(const vec<T>& ws, const Clause *c) const
{
uint32_t j = 0;
for (; j < ws.size() && ws[j].clause != c; j++);
return j < ws.size();
}
template<class T>
-inline bool Solver::findWatchedBinCl(vec<T>& ws, const Clause *c)
+inline bool Solver::findWatchedBinCl(const vec<T>& ws, const Clause *c) const
{
uint32_t j = 0;
for (; j < ws.size() && ws[j].clause != c; j++);
inline void Solver::reverse_binary_clause(Clause& c) const {
if (c.size() == 2 && value(c[0]) == l_False) {
assert(value(c[1]) == l_True);
- Lit tmp = c[0];
- c[0] = c[1], c[1] = tmp;
+ std::swap(c[0], c[1]);
}
}
/*inline void Solver::calculate_xor_clause(Clause& c2) const {
clauseFree(&c);
}
-
//=================================================================================================
// Debug + etc:
assert(expr);
}
+#ifndef DEBUG_ATTACH
+inline void Solver::testAllClauseAttach() const
+{
+ return;
+}
+inline void Solver::findAllAttach() const
+{
+ return;
+}
+#endif //DEBUG_ATTACH
+
+inline void Solver::uncheckedEnqueueLight(const Lit p)
+{
+ assigns [p.var()] = boolToLBool(!p.sign());//lbool(!sign(p)); // <<== abstract but not uttermost effecient
+ trail.push(p);
+}
+
//=================================================================================================
}; //NAMESPACE MINISAT
#endif //_MSC_VER
#include "Alg.h"
+#include <stdio.h>
namespace MINISAT
{
bool operator < (const Lit& p) const {
return x < p.x; // '<' guarantees that p, ~p are adjacent in the ordering.
}
-};
+ inline void print(FILE* outfile = stdout) const
+ {
+ fprintf(outfile,"%s%d", sign() ? "-" : "", var()+1);
+ }
+ inline void printFull(FILE* outfile = stdout) const
+ {
+ fprintf(outfile,"%s%d 0\n", sign() ? "-" : "", var()+1);
+ }
+};
-const Lit lit_Undef(var_Undef, false); // }- Useful special constants.
-const Lit lit_Error(var_Undef, true ); // }
+const Lit lit_Undef(var_Undef, false); // Useful special constants.
+const Lit lit_Error(var_Undef, true ); //
//=================================================================================================
// Lifted booleans:
--- /dev/null
+/***********************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************************************/
+
+#include "StateSaver.h"
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+StateSaver::StateSaver(Solver& _solver) :
+ solver(_solver)
+ , backup_order_heap(Solver::VarOrderLt(solver.activity))
+{
+ //Saving Solver state
+ backup_var_inc = solver.var_inc;
+ backup_activity.growTo(solver.activity.size());
+ std::copy(solver.activity.getData(), solver.activity.getDataEnd(), backup_activity.getData());
+ backup_order_heap = solver.order_heap;
+ backup_polarities = solver.polarity;
+ backup_restartType = solver.restartType;
+ backup_random_var_freq = solver.random_var_freq;
+ backup_propagations = solver.propagations;
+}
+
+void StateSaver::restore()
+{
+ //Restore Solver state
+ solver.var_inc = backup_var_inc;
+ std::copy(backup_activity.getData(), backup_activity.getDataEnd(), solver.activity.getData());
+ solver.order_heap = backup_order_heap;
+ solver.polarity = backup_polarities;
+ solver.restartType = backup_restartType;
+ solver.random_var_freq = backup_random_var_freq;
+
+ //Finally, clear the order_heap from variables set/non-decisionned
+ solver.order_heap.filter(Solver::VarFilter(solver));
+ solver.propagations = backup_propagations;
+}
+
+}; //NAMESPACE MINISAT
--- /dev/null
+/***********************************************************************************
+CryptoMiniSat -- Copyright (c) 2009 Mate Soos
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************************************/
+
+#ifndef STATESAVER__H
+#define STATESAVER__H
+
+#include "Solver.h"
+
+namespace MINISAT
+{
+using namespace MINISAT;
+
+class StateSaver
+{
+ public:
+ StateSaver(Solver& _solver);
+ void restore();
+
+ private:
+ Solver& solver;
+ Heap<Solver::VarOrderLt> backup_order_heap;
+ vector<bool> backup_polarities;
+ vec<uint32_t> backup_activity;
+ uint32_t backup_var_inc;
+ RestartType backup_restartType;
+ uint32_t backup_random_var_freq;
+ uint64_t backup_propagations;
+};
+
+}; //NAMESPACE MINISAT
+
+#endif //STATESAVER__H
#include <cmath>
#include <algorithm>
#include "VarReplacer.h"
-#include "Conglomerate.h"
#include "XorFinder.h"
#ifdef _MSC_VER
#define __builtin_prefetch(a,b,c)
#endif //_MSC_VER
-
//#define VERBOSE_DEBUG
#ifdef VERBOSE_DEBUG
#define BIT_MORE_VERBOSITY
Subsumer::Subsumer(Solver& s):
solver(s)
- , numCalls(0)
+ , totalTime(0.0)
, numElimed(0)
+ , numCalls(0)
{
};
void Subsumer::extendModel(Solver& solver2)
{
+ assert(checkElimedUnassigned());
vec<Lit> tmp;
- typedef map<Var, vector<vector<Lit> > > elimType;
+ typedef map<Var, vector<Clause*> > elimType;
for (elimType::iterator it = elimedOutVar.begin(), end = elimedOutVar.end(); it != end; it++) {
- #ifdef VERBOSE_DEBUG
+ #ifndef NDEBUG
Var var = it->first;
+ #ifdef VERBOSE_DEBUG
std::cout << "Reinserting elimed var: " << var+1 << std::endl;
#endif
+ assert(!solver.decision_var[var]);
+ assert(solver.assigns[var] == l_Undef);
+ assert(!solver.order_heap.inHeap(var));
+ #endif
- for (vector<vector<Lit> >::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
+ for (vector<Clause*>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
+ Clause& c = **it2;
tmp.clear();
- tmp.growTo(it2->size());
- std::copy(it2->begin(), it2->end(), tmp.getData());
+ tmp.growTo(c.size());
+ std::copy(c.getData(), c.getDataEnd(), tmp.getData());
#ifdef VERBOSE_DEBUG
std::cout << "Reinserting Clause: ";
- for (uint32_t i = 0; i < tmp.size(); i++) {
- std::cout << (tmp[i].sign() ? "-" : "")<< tmp[i].var()+1 << " ";
- }
- std::cout << std::endl;
+ c.plainPrint();
#endif
solver2.addClause(tmp);
const bool Subsumer::unEliminate(const Var var)
{
+ assert(var_elimed[var]);
vec<Lit> tmp;
- typedef map<Var, vector<vector<Lit> > > elimType;
+ typedef map<Var, vector<Clause*> > elimType;
elimType::iterator it = elimedOutVar.find(var);
-
+
+ //it MUST have been decision var, otherwise we would
+ //never have removed it
solver.setDecisionVar(var, true);
var_elimed[var] = false;
numElimed--;
FILE* backup_libraryCNFfile = solver.libraryCNFFile;
solver.libraryCNFFile = NULL;
- for (vector<vector<Lit> >::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
- tmp.clear();
- tmp.growTo(it2->size());
- std::copy(it2->begin(), it2->end(), tmp.getData());
- solver.addClause(tmp);
+ for (vector<Clause*>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
+ solver.addClause(**it2);
+ clauseFree(*it2);
}
solver.libraryCNFFile = backup_libraryCNFfile;
elimedOutVar.erase(it);
return flip;
}
-// Will put NULL in 'cs' if clause removed.
-uint32_t Subsumer::subsume0(Clause& ps)
+template <>
+inline uint32_t Subsumer::subsume0(Clause& ps, uint32_t abs)
{
ps.subsume0Finished();
ps.unsetVarChanged();
- uint32_t retIndex = std::numeric_limits<uint32_t>::max();
#ifdef VERBOSE_DEBUG
- cout << "subsume0 orig clause:";
+ cout << "subsume0 orig clause: ";
ps.plainPrint();
#endif
-
+ return subsume0Orig(ps, abs);
+}
+
+template <class T>
+inline uint32_t Subsumer::subsume0(T& ps, uint32_t abs)
+{
+ #ifdef VERBOSE_DEBUG
+ cout << "subsume0 orig vec: ";
+ ps[0].print(); std::cout << " ";
+ ps[1].printFull();
+ #endif
+ return subsume0Orig(ps, abs);
+}
+
+// Will put NULL in 'cs' if clause removed.
+template<class T>
+uint32_t Subsumer::subsume0Orig(const T& ps, uint32_t abs)
+{
+ uint32_t retIndex = std::numeric_limits<uint32_t>::max();
vec<ClauseSimp> subs;
- findSubsumed(ps, subs);
+ findSubsumed(ps, abs, subs);
for (uint32_t i = 0; i < subs.size(); i++){
clauses_subsumed++;
#ifdef VERBOSE_DEBUG
- cout << "subsume0 removing:";
+ cout << "-> subsume0 removing:";
subs[i].clause->plainPrint();
#endif
Clause* tmp = subs[i].clause;
- unlinkClause(subs[i]);
- free(tmp);
retIndex = subs[i].index;
+ unlinkClause(subs[i]);
+ clauseFree(tmp);
}
return retIndex;
}
-// Will put NULL in 'cs' if clause removed.
-uint32_t Subsumer::subsume0(Clause& ps, uint32_t abs)
+void Subsumer::subsume0BIN(const Lit lit1, const vec<char>& lits)
{
- ps.subsume0Finished();
- ps.unsetVarChanged();
- uint32_t retIndex = std::numeric_limits<uint32_t>::max();
- #ifdef VERBOSE_DEBUG
- cout << "subsume0 orig clause:";
- ps.plainPrint();
- cout << "pointer:" << &ps << endl;
- #endif
-
vec<ClauseSimp> subs;
- findSubsumed(ps, abs, subs);
+ 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, 0, 1);
+ if (it->clause == NULL) continue;
+ Clause& c = *it->clause;
+ bool removed = false;
+ for (uint32_t i = 0; i < c.size(); i++) {
+ if (lits[c[i].toInt()]) {
+ subs.push(*it);
+ removed = true;
+ break;
+ }
+ }
+ if (!removed) {
+ for (uint32_t i = 0; i < c.size(); i++) {
+ if (lits[(~c[i]).toInt()]) {
+ subs2.push(*it);
+ subs2Lit.push(c[i]);
+ break;
+ }
+ }
+ }
+ }
+
for (uint32_t i = 0; i < subs.size(); i++){
clauses_subsumed++;
#ifdef VERBOSE_DEBUG
- cout << "subsume0 removing:";
+ cout << "-> subsume0 removing:";
subs[i].clause->plainPrint();
#endif
Clause* tmp = subs[i].clause;
- retIndex = subs[i].index;
unlinkClause(subs[i]);
- free(tmp);
+ clauseFree(tmp);
}
-
- return retIndex;
+
+ if (subs2.size() == 0) return;
+ registerIteration(subs2);
+ for (uint32_t j = 0; j < subs2.size(); j++){
+ if (subs2[j].clause == NULL) continue;
+ ClauseSimp c = subs2[j];
+ Clause& cl = *c.clause;
+ #ifdef VERBOSE_DEBUG
+ cout << "-> Strenghtening clause :";
+ cl.plainPrint();
+ #endif
+ unlinkClause(c);
+
+ literals_removed++;
+ cl.strengthen(subs2Lit[j]);
+ Lit *a, *b, *end;
+ for (a = b = cl.getData(), end = a + cl.size(); a != end; a++) {
+ lbool val = solver.value(*a);
+ if (val == l_Undef)
+ *b++ = *a;
+
+ if (val == l_True) {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "--> Clause was satisfied." << std::endl;
+ #endif
+ clauseFree(&cl);
+ goto endS;
+ }
+ }
+ cl.shrink(a-b);
+ cl.setStrenghtened();
+
+ #ifdef VERBOSE_DEBUG
+ cout << "--> Strenghtened clause:";
+ cl.plainPrint();
+ #endif
+
+ if (cl.size() == 0) {
+ solver.ok = false;
+ unregisterIteration(subs2);
+ clauseFree(&cl);
+ return;
+ }
+ if (cl.size() > 2) {
+ cl.calcAbstraction();
+ linkInAlreadyClause(c);
+ clauses[c.index] = c;
+ solver.attachClause(cl);
+ updateClause(c);
+ } else if (cl.size() == 2) {
+ cl.calcAbstraction();
+ solver.attachClause(cl);
+ solver.becameBinary++;
+ addBinaryClauses.push(&cl);
+ //updateClause(c);
+ } else {
+ assert(cl.size() == 1);
+ solver.uncheckedEnqueue(cl[0]);
+ solver.ok = (solver.propagate() == NULL);
+ if (!solver.ok) {
+ unregisterIteration(subs2);
+ return;
+ }
+ #ifdef VERBOSE_DEBUG
+ cout << "--> Found that var " << cl[0].var()+1 << " must be " << std::boolalpha << !cl[0].sign() << endl;
+ #endif
+ clauseFree(&cl);
+ }
+ endS:;
+ }
+ unregisterIteration(subs2);
}
void Subsumer::unlinkClause(ClauseSimp c, Var elim)
if (elim != var_Undef) {
assert(!cl.learnt());
- io_tmp.clear();
- for (uint32_t i = 0; i < cl.size(); i++)
- io_tmp.push_back(cl[i]);
- elimedOutVar[elim].push_back(io_tmp);
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Eliminating clause: "; c.clause->plainPrint();
+ std::cout << "On variable: " << elim+1 << std::endl;
+ #endif //VERBOSE_DEBUG
+ elimedOutVar[elim].push_back(c.clause);
}
-
- if (updateOccur(cl)) {
- for (uint32_t i = 0; i < cl.size(); i++) {
- maybeRemove(occur[cl[i].toInt()], &cl);
- #ifndef TOUCH_LESS
- touch(cl[i]);
- #endif
- }
+
+ for (uint32_t i = 0; i < cl.size(); i++) {
+ maybeRemove(occur[cl[i].toInt()], &cl);
+ #ifndef TOUCH_LESS
+ touch(cl[i]);
+ #endif
}
solver.detachClause(cl);
}
// Remove clause from clause touched set:
- if (updateOccur(cl)) {
- cl_touched.exclude(c);
- cl_added.exclude(c);
- }
+ cl_touched.exclude(c);
+ cl_added.exclude(c);
clauses[c.index].clause = NULL;
}
void Subsumer::unlinkModifiedClause(vec<Lit>& origClause, ClauseSimp c)
{
- if (updateOccur(*c.clause)) {
- for (uint32_t i = 0; i < origClause.size(); i++) {
- maybeRemove(occur[origClause[i].toInt()], c.clause);
- #ifndef TOUCH_LESS
- touch(origClause[i]);
- #endif
- }
+ for (uint32_t i = 0; i < origClause.size(); i++) {
+ maybeRemove(occur[origClause[i].toInt()], c.clause);
+ #ifndef TOUCH_LESS
+ touch(origClause[i]);
+ #endif
}
solver.detachModifiedClause(origClause[0], origClause[1], origClause.size(), c.clause);
}
// Remove clause from clause touched set:
- if (updateOccur(*c.clause)) {
- cl_touched.exclude(c);
- cl_added.exclude(c);
- }
+ cl_touched.exclude(c);
+ cl_added.exclude(c);
clauses[c.index].clause = NULL;
}
void Subsumer::unlinkModifiedClauseNoDetachNoNULL(vec<Lit>& origClause, ClauseSimp c)
{
- if (updateOccur(*c.clause)) {
- for (uint32_t i = 0; i < origClause.size(); i++) {
- maybeRemove(occur[origClause[i].toInt()], c.clause);
- #ifndef TOUCH_LESS
- touch(origClause[i]);
- #endif
- }
+ for (uint32_t i = 0; i < origClause.size(); i++) {
+ maybeRemove(occur[origClause[i].toInt()], c.clause);
+ #ifndef TOUCH_LESS
+ touch(origClause[i]);
+ #endif
}
// Remove from iterator vectors/sets:
}
// Remove clause from clause touched set:
- if (updateOccur(*c.clause)) {
- cl_touched.exclude(c);
- cl_added.exclude(c);
- }
+ cl_touched.exclude(c);
+ cl_added.exclude(c);
}
void Subsumer::subsume1(ClauseSimp& ps)
while (q < Q.size()){
if (Q[q].clause == NULL) { q++; continue; }
#ifdef VERBOSE_DEBUG
- cout << "subsume1 orig clause:";
+ cout << "subsume1 with clause:";
Q[q].clause->plainPrint();
#endif
ClauseSimp c = subs[j];
Clause& cl = *c.clause;
#ifdef VERBOSE_DEBUG
- cout << "orig clause :";
+ cout << "-> Strenghtening clause :";
cl.plainPrint();
#endif
- unlinkClause(subs[j]);
+ unlinkClause(c);
literals_removed++;
cl.strengthen(qs[i]);
*b++ = *a;
if (val == l_True) {
- free(&cl);
+ #ifdef VERBOSE_DEBUG
+ std::cout << "--> Clause was satisfied." << std::endl;
+ #endif
+ clauseFree(&cl);
goto endS;
}
}
cl.setStrenghtened();
#ifdef VERBOSE_DEBUG
- cout << "strenghtened :";
- c.clause->plainPrint();
+ cout << "--> Strenghtened clause:";
+ cl.plainPrint();
#endif
if (cl.size() == 0) {
solver.ok = false;
unregisterIteration(Q);
unregisterIteration(subs);
- free(&cl);
+ clauseFree(&cl);
return;
}
if (cl.size() > 1) {
return;
}
#ifdef VERBOSE_DEBUG
- cout << "Found that var " << cl[0].var()+1 << " must be " << std::boolalpha << !cl[0].sign() << endl;
+ cout << "--> Found that var " << cl[0].var()+1 << " must be " << std::boolalpha << !cl[0].sign() << endl;
#endif
- free(&cl);
+ clauseFree(&cl);
}
endS:;
}
unregisterIteration(subs);
}
+template<class T>
+void Subsumer::subsume1Partial(const T& ps)
+{
+ assert(solver.decisionLevel() == 0);
+ registerIteration(subsume1PartialSubs);
+
+ #ifdef VERBOSE_DEBUG
+ cout << "-> Strenghtening using clause :";
+ ps[0].print(); std::cout << " ";
+ ps[1].printFull();
+ #endif
+
+ assert(ps.size() == 2);
+ subsume1PartialQs.clear();
+ for (uint8_t i = 0; i < 2; i++)
+ subsume1PartialQs.push(ps[i]);
+
+ for (uint8_t i = 0; i < 2; i++){
+ subsume1PartialQs[i] = ~subsume1PartialQs[i];
+
+ uint32_t abst = calcAbstraction(subsume1PartialQs);
+
+ findSubsumed(subsume1PartialQs, abst, subsume1PartialSubs);
+ for (uint32_t j = 0; j < subsume1PartialSubs.size(); j++){
+ if (subsume1PartialSubs[j].clause == NULL) continue;
+ ClauseSimp c = subsume1PartialSubs[j];
+ Clause& cl = *c.clause;
+ #ifdef VERBOSE_DEBUG
+ cout << "-> Strenghtening clause :";
+ cl.plainPrint();
+ #endif
+ unlinkClause(subsume1PartialSubs[j]);
+
+ literals_removed++;
+ cl.strengthen(subsume1PartialQs[i]);
+ Lit *a, *b, *end;
+ for (a = b = cl.getData(), end = a + cl.size(); a != end; a++) {
+ lbool val = solver.value(*a);
+ if (val == l_Undef)
+ *b++ = *a;
+
+ if (val == l_True) {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "--> Clause was satisfied." << std::endl;
+ #endif
+ clauseFree(&cl);
+ goto endS;
+ }
+ }
+ cl.shrink(a-b);
+ cl.setStrenghtened();
+
+ #ifdef VERBOSE_DEBUG
+ cout << "--> Strenghtened clause:";
+ cl.plainPrint();
+ #endif
+
+ if (cl.size() == 0) {
+ solver.ok = false;
+ unregisterIteration(subsume1PartialSubs);
+ clauseFree(&cl);
+ return;
+ }
+ if (cl.size() > 2) {
+ cl.calcAbstraction();
+ linkInAlreadyClause(c);
+ clauses[c.index] = c;
+ solver.attachClause(cl);
+ updateClause(c);
+ } else if (cl.size() == 2) {
+ cl.calcAbstraction();
+ solver.attachClause(cl);
+ solver.becameBinary++;
+ addBinaryClauses.push(&cl);
+ //updateClause(c);
+ } else {
+ assert(cl.size() == 1);
+ solver.uncheckedEnqueue(cl[0]);
+ solver.ok = (solver.propagate() == NULL);
+ if (!solver.ok) {
+ unregisterIteration(subsume1PartialSubs);
+ return;
+ }
+ #ifdef VERBOSE_DEBUG
+ cout << "--> Found that var " << cl[0].var()+1 << " must be " << std::boolalpha << !cl[0].sign() << endl;
+ #endif
+ clauseFree(&cl);
+ }
+ endS:;
+ }
+
+ subsume1PartialQs[i] = ~subsume1PartialQs[i];
+ subsume1PartialSubs.clear();
+ }
+ unregisterIteration(subsume1PartialSubs);
+}
+
void Subsumer::updateClause(ClauseSimp c)
{
- if (!c.clause->learnt()) subsume0(*c.clause);
+ if (!c.clause->learnt()) subsume0(*c.clause, c.clause->getAbst());
cl_touched.add(c);
}
for (uint32_t i = 0; i < clauses.size(); i++) {
if (numMaxSubsume1 == 0) break;
- if (clauses[i].clause != NULL && updateOccur(*clauses[i].clause)) {
+ if (clauses[i].clause != NULL) {
subsume1(clauses[i]);
numMaxSubsume1--;
if (!solver.ok) return;
// Iteration pass for 0-subsumption:
for (CSet::iterator it = s0.begin(), end = s0.end(); it != end; ++it) {
if (it->clause != NULL)
- subsume0(*it->clause);
+ subsume0(*it->clause, it->clause->getAbst());
}
s0.clear();
unregisterIteration(s0);
{
ClauseSimp c(&cl, clauseID++);
clauses.push(c);
- if (updateOccur(cl)) {
- for (uint32_t i = 0; i < cl.size(); i++) {
- occur[cl[i].toInt()].push(c);
- touch(cl[i].var());
- }
+ for (uint32_t i = 0; i < cl.size(); i++) {
+ occur[cl[i].toInt()].push(c);
+ touch(cl[i].var());
}
cl_added.add(c);
void Subsumer::linkInAlreadyClause(ClauseSimp& c)
{
Clause& cl = *c.clause;
-
- if (updateOccur(cl)) {
- for (uint32_t i = 0; i < cl.size(); i++) {
- occur[cl[i].toInt()].push(c);
- touch(cl[i].var());
- }
+ for (uint32_t i = 0; i < cl.size(); i++) {
+ occur[cl[i].toInt()].push(c);
+ touch(cl[i].var());
}
}
-void Subsumer::addFromSolver(vec<Clause*>& cs)
+template<bool UseCL>
+void Subsumer::addFromSolver(vec<Clause*>& cs, bool alsoLearnt)
{
Clause **i = cs.getData();
Clause **j = i;
for (Clause **end = i + cs.size(); i != end; i++) {
if (i+1 != end)
__builtin_prefetch(*(i+1), 1, 1);
-
- if ((*i)->learnt()) {
+
+ if (!alsoLearnt && (*i)->learnt()) {
+ *j++ = *i;
+ (*i)->setUnsorted();
+ continue;
+ }
+
+ if (!UseCL && (*i)->size() == 2) {
+ //don't add binary clauses in this case
*j++ = *i;
(*i)->setUnsorted();
continue;
}
+
ClauseSimp c(*i, clauseID++);
clauses.push(c);
Clause& cl = *c.clause;
- if (updateOccur(cl)) {
- for (uint32_t i = 0; i < cl.size(); i++) {
- occur[cl[i].toInt()].push(c);
- touch(cl[i].var());
- }
+ for (uint32_t i = 0; i < cl.size(); i++) {
+ occur[cl[i].toInt()].push(c);
+ touch(cl[i].var());
+ }
+ if (UseCL) {
if (fullSubsume || cl.getVarChanged()) cl_added.add(c);
else if (cl.getStrenghtened()) cl_touched.add(c);
-
- if (cl.getVarChanged() || cl.getStrenghtened())
- cl.calcAbstraction();
}
+
+ if (cl.getVarChanged() || cl.getStrenghtened())
+ cl.calcAbstraction();
}
cs.shrink(i-j);
}
if (var_elimed[l->var()]) {
remove = true;
solver.detachClause(c);
- free(&c);
+ clauseFree(&c);
break;
}
}
cannot_eliminate[c[i2].var()] = true;
}
- const vec<bool>& tmp2 = solver.conglomerate->getRemovedVars();
- for (uint32_t i = 0; i < tmp2.size(); i++) {
- if (tmp2[i]) cannot_eliminate[i] = true;
- }
-
const vec<Clause*>& tmp = solver.varReplacer->getClauses();
for (uint32_t i = 0; i < tmp.size(); i++) {
const Clause& c = *tmp[i];
uint32_t index = subsume0(**a, calcAbstraction(**a));
if (index != std::numeric_limits<uint32_t>::max()) {
(*a)->makeNonLearnt();
+ //solver.nbBin--;
clauses[index].clause = *a;
linkInAlreadyClause(clauses[index]);
solver.learnts_literals -= (*a)->size();
((*a)->size() <= 3 && clauses.size() < 300000) ||
((*a)->size() <= 4 && clauses.size() < 60000))) {
ClauseSimp c(*a, clauseID++);
- (*a)->calcAbstraction();
- clauses.push(c);
+ //(*a)->calcAbstraction();
+ //clauses.push(c);
subsume1(c);
numMaxSubsume1--;
if (!solver.ok) {
cs.shrink(a-b);
return;
}
- assert(clauses[c.index].clause != NULL);
- clauses.pop();
+ //assert(clauses[c.index].clause != NULL);
+ //clauses.pop();
clauseID--;
}
}
return true;
}
+const bool Subsumer::subsumeWithBinaries(const bool startUp)
+{
+ clearAll();
+ clauseID = 0;
+ fullSubsume = true;
+ addBinaryClauses.clear();
+
+ //Clearing stats
+ subsNonExistentumFailed = 0;
+ clauses_subsumed = 0;
+ literals_removed = 0;
+ double myTime = cpuTime();
+ uint32_t origTrailSize = solver.trail.size();
+
+ clauses.reserve(solver.clauses.size());
+ solver.clauseCleaner->cleanClauses(solver.clauses, ClauseCleaner::clauses);
+ addFromSolver<false>(solver.clauses);
+ #ifdef DEBUG_BINARIES
+ for (uint32_t i = 0; i < clauses.size(); i++) {
+ assert(clauses[i].clause->size() != 2);
+ }
+ #endif //DEBUG_BINARIES
+
+ for (uint32_t i = 0; i < solver.binaryClauses.size(); i++) {
+ if (startUp || !solver.binaryClauses[i]->learnt()) {
+ Clause& c = *solver.binaryClauses[i];
+ subsume0(c, c.getAbst());
+ }
+ }
+ for (uint32_t i = 0; i < solver.binaryClauses.size(); i++) {
+ Clause& c = *solver.binaryClauses[i];
+ subsume1Partial(c);
+ if (!solver.ok) return false;
+ }
+ if (solver.verbosity >= 1) {
+ std::cout << "c subs with bin: " << std::setw(8) << clauses_subsumed
+ << " lits-rem: " << std::setw(9) << literals_removed
+ << " v-fix: " << std::setw(4) <<solver.trail.size() - origTrailSize
+ << " time: " << std::setprecision(2) << std::setw(5) << cpuTime() - myTime << " s"
+ << " |" << std::endl;
+ }
+
+ if (!subsWNonExistBinsFull(startUp)) return false;
+
+ #ifdef DEBUG_BINARIES
+ for (uint32_t i = 0; i < clauses.size(); i++) {
+ assert(clauses[i].clause == NULL || clauses[i].clause->size() != 2);
+ }
+ #endif //DEBUG_BINARIES
+ addBackToSolver();
+ for (uint32_t i = 0; i < addBinaryClauses.size(); i++) {
+ solver.binaryClauses.push(addBinaryClauses[i]);
+ }
+ addBinaryClauses.clear();
+
+ if (solver.verbosity >= 1) {
+ std::cout << "c Subs w/ non-existent bins: " << subsNonExistentNum
+ << " lits-rem: " << subsNonExistentLitsRemoved
+ << " v-fix: " << subsNonExistentumFailed
+ << " done: " << doneNum
+ << " time: " << std::fixed << std::setprecision(2) << std::setw(5) << subsNonExistentTime
+ << std::endl;
+ }
+ totalTime += cpuTime() - myTime;
+ solver.order_heap.filter(Solver::VarFilter(solver));
+
+ return true;
+}
+
+#define MAX_BINARY_PROP 40000000
+
+const bool Subsumer::subsWNonExistBinsFull(const bool startUp)
+{
+ uint32_t oldClausesSubusmed = clauses_subsumed;
+ uint32_t oldLitsRemoved = literals_removed;
+ double myTime = cpuTime();
+ uint64_t oldProps = solver.propagations;
+ uint32_t oldTrailSize = solver.trail.size();
+ uint64_t maxProp = MAX_BINARY_PROP;
+ if (!startUp) maxProp /= 3;
+ ps2.clear();
+ ps2.growTo(2);
+ toVisitAll.growTo(solver.nVars()*2, false);
+
+ doneNum = 0;
+ uint32_t startFrom = solver.mtrand.randInt(solver.order_heap.size());
+ for (uint32_t i = 0; i < solver.order_heap.size(); i++) {
+ Var var = solver.order_heap[(i+startFrom)%solver.order_heap.size()];
+ if (solver.propagations - oldProps > maxProp) break;
+ if (solver.assigns[var] != l_Undef || !solver.decision_var[var]) continue;
+ doneNum++;
+
+ Lit lit(var, true);
+ if (!subsWNonExistBins(lit, startUp)) {
+ if (!solver.ok) return false;
+ solver.cancelUntil(0);
+ solver.uncheckedEnqueue(~lit);
+ solver.ok = (solver.propagate() == NULL);
+ if (!solver.ok) return false;
+ continue;
+ }
+
+ //in the meantime it could have got assigned
+ if (solver.assigns[var] != l_Undef) continue;
+ lit = ~lit;
+ if (!subsWNonExistBins(lit, startUp)) {
+ if (!solver.ok) return false;
+ solver.cancelUntil(0);
+ solver.uncheckedEnqueue(~lit);
+ solver.ok = (solver.propagate() == NULL);
+ if (!solver.ok) return false;
+ continue;
+ }
+ }
+ subsNonExistentNum = clauses_subsumed - oldClausesSubusmed;
+ subsNonExistentTime = cpuTime() - myTime;
+ subsNonExistentumFailed = solver.trail.size() - oldTrailSize;
+ subsNonExistentLitsRemoved = literals_removed - oldLitsRemoved;
+
+ return true;
+}
+
+const bool Subsumer::subsWNonExistBins(const Lit& lit, const bool startUp)
+{
+ #ifdef VERBOSE_DEBUG
+ std::cout << "subsWNonExistBins called with lit "; lit.print();
+ std::cout << " startUp: " << startUp << std::endl;
+ #endif //VERBOSE_DEBUG
+ toVisit.clear();
+ solver.newDecisionLevel();
+ solver.uncheckedEnqueueLight(lit);
+ bool failed;
+ if (startUp) {
+ failed = (solver.propagateBin() != NULL);
+ } else {
+ failed = (solver.propagateBinNoLearnts() != NULL);
+ }
+ if (failed) return false;
+
+ assert(solver.decisionLevel() > 0);
+ for (int c = solver.trail.size()-1; c > (int)solver.trail_lim[0]; c--) {
+ Lit x = solver.trail[c];
+ toVisit.push(x);
+ toVisitAll[x.toInt()] = true;
+ }
+ solver.cancelUntil(0);
+
+ if (toVisit.size() <= 1) {
+ ps2[0] = ~lit;
+ for (Lit *l = toVisit.getData(), *end = toVisit.getDataEnd(); l != end; l++) {
+ ps2[1] = *l;
+ assert(ps2[0] != ps2[1]);
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Non-existent bin. lit1: "; ps2[0].print();
+ std::cout << " lit2: "; ps2[1].print(); std::cout << std::endl;
+ #endif //VERBOSE_DEBUG
+ subsume0(ps2, calcAbstraction(ps2));
+ subsume1Partial(ps2);
+ }
+ } else {
+ subsume0BIN(~lit, toVisitAll);
+ }
+ for (uint32_t i = 0; i < toVisit.size(); i++)
+ toVisitAll[toVisit[i].toInt()] = false;
+
+ return true;
+}
+
+void Subsumer::clearAll()
+{
+ touched_list.clear();
+ touched.clear();
+ touched.growTo(solver.nVars(), false);
+ for (Var var = 0; var < solver.nVars(); var++) {
+ if (solver.decision_var[var] && solver.assigns[var] == l_Undef) touch(var);
+ occur[2*var].clear();
+ occur[2*var+1].clear();
+ }
+ clauses.clear();
+ cl_added.clear();
+ cl_touched.clear();
+}
+
const bool Subsumer::simplifyBySubsumption()
{
if (solver.nClauses() > 20000000) return true;
clauseID = 0;
numVarsElimed = 0;
blockTime = 0.0;
+ clearAll();
//if (solver.xorclauses.size() < 30000 && solver.clauses.size() < MAX_CLAUSENUM_XORFIND/10) addAllXorAsNorm();
-
- //For VE
- touched_list.clear();
- touched.clear();
- touched.growTo(solver.nVars(), false);
- for (Var var = 0; var < solver.nVars(); var++) {
- if (solver.decision_var[var] && solver.assigns[var] == l_Undef) touch(var);
- occur[2*var].clear();
- occur[2*var+1].clear();
- }
-
+
+ solver.testAllClauseAttach();
if (solver.performReplace && !solver.varReplacer->performReplace(true))
return false;
fillCannotEliminate();
-
- clauses.clear();
- cl_added.clear();
- cl_touched.clear();
+ solver.testAllClauseAttach();
clauses.reserve(solver.clauses.size() + solver.binaryClauses.size());
cl_added.reserve(solver.clauses.size() + solver.binaryClauses.size());
fullSubsume = false;
solver.clauseCleaner->cleanClauses(solver.clauses, ClauseCleaner::clauses);
- addFromSolver(solver.clauses);
- solver.clauseCleaner->cleanClauses(solver.binaryClauses, ClauseCleaner::binaryClauses);
- addFromSolver(solver.binaryClauses);
+ addFromSolver<true>(solver.clauses);
+ solver.clauseCleaner->removeSatisfied(solver.binaryClauses, ClauseCleaner::binaryClauses);
+ addFromSolver<true>(solver.binaryClauses);
//Limits
- if (clauses.size() > 3500000)
+ if (clauses.size() > 3500000) {
numMaxSubsume0 = 900000 * (1+numCalls/2);
- else
- numMaxSubsume0 = 2000000 * (1+numCalls/2);
-
- if (solver.doSubsume1) {
- if (clauses.size() > 3500000)
- numMaxSubsume1 = 100000 * (1+numCalls/2);
- else
- numMaxSubsume1 = 500000 * (1+numCalls/2);
- } else {
- numMaxSubsume1 = 0;
- }
-
- if (clauses.size() > 3500000)
numMaxElim = (uint32_t)((double)solver.order_heap.size() / 5.0 * (0.8+(double)(numCalls)/4.0));
- else
- numMaxElim = (uint32_t)((double)solver.order_heap.size() / 2.0 * (0.8+(double)(numCalls)/4.0));
-
- if (clauses.size() > 3500000)
+ numMaxSubsume1 = 100000 * (1+numCalls/2);
numMaxBlockToVisit = (int64_t)(30000.0 * (0.8+(double)(numCalls)/3.0));
- else
+ }
+ if (clauses.size() <= 3500000 && clauses.size() > 1500000) {
+ numMaxSubsume0 = 2000000 * (1+numCalls/2);
+ numMaxElim = (uint32_t)((double)solver.order_heap.size() / 2.0 * (0.8+(double)(numCalls)/4.0));
+ numMaxSubsume1 = 300000 * (1+numCalls/2);
numMaxBlockToVisit = (int64_t)(50000.0 * (0.8+(double)(numCalls)/3.0));
+ }
+ if (clauses.size() <= 1500000) {
+ numMaxSubsume0 = 4000000 * (1+numCalls/2);
+ numMaxElim = (uint32_t)((double)solver.order_heap.size() / 2.0 * (0.8+(double)(numCalls)/2.0));
+ numMaxSubsume1 = 400000 * (1+numCalls/2);
+ numMaxBlockToVisit = (int64_t)(80000.0 * (0.8+(double)(numCalls)/3.0));
+ }
+ if (numCalls == 1) numMaxSubsume1 = 0;
+
+ if (!solver.doSubsume1) numMaxSubsume1 = 0;
+
if (solver.order_heap.size() > 200000)
numMaxBlockVars = (uint32_t)((double)solver.order_heap.size() / 3.5 * (0.8+(double)(numCalls)/4.0));
else
numMaxBlockVars = (uint32_t)((double)solver.order_heap.size() / 1.5 * (0.8+(double)(numCalls)/4.0));
- //For debugging post-c32s-gcdm16-22.cnf --- an instance that is turned SAT to UNSAT if a bug is in the code
+ //For debugging
//numMaxBlockToVisit = std::numeric_limits<int64_t>::max();
//numMaxElim = std::numeric_limits<uint32_t>::max();
//numMaxSubsume0 = std::numeric_limits<uint32_t>::max();
(fullSubsume
|| !clauses[i].clause->subsume0IsFinished())
) {
- subsume0(*clauses[i].clause);
+ subsume0(*clauses[i].clause, clauses[i].clause->getAbst());
numMaxSubsume0--;
}
}
//vector<char> var_merged = merge();
removeWrong(solver.learnts);
removeWrong(solver.binaryClauses);
+ removeAssignedVarsFromEliminated();
- solver.clauseCleaner->cleanClausesBewareNULL(clauses, ClauseCleaner::simpClauses, *this);
-// if (solver.doHyperBinRes && clauses.size() < 1000000 && numCalls > 1 && !hyperBinRes())
-// return false;
-//
-// solver.ok = (solver.propagate() == NULL);
-// if (!solver.ok) return false;
-// solver.clauseCleaner->cleanClausesBewareNULL(clauses, ClauseCleaner::simpClauses, *this);
-
+ /*solver.clauseCleaner->cleanClausesBewareNULL(clauses, ClauseCleaner::simpClauses, *this);
+ addFromSolver(solver.learnts, true);
+ addFromSolver(solver.binaryClauses, true);
+ if (solver.doHyperBinRes && clauses.size() < 1000000 && numCalls > 1 && !hyperBinRes())
+ return false;*/
solver.order_heap.filter(Solver::VarFilter(solver));
addBackToSolver();
<< " |" << std::endl;
}
}
-
- return true;
-}
+ totalTime += cpuTime() - myTime;
-void Subsumer::findSubsumed(Clause& ps, vec<ClauseSimp>& out_subsumed)
-{
- #ifdef VERBOSE_DEBUG
- cout << "findSubsumed: ";
- for (uint32_t i = 0; i < ps.size(); i++) {
- if (ps[i].sign()) printf("-");
- printf("%d ", ps[i].var() + 1);
- }
- printf("0\n");
- #endif
-
- int min_i = 0;
- for (uint32_t i = 1; i < ps.size(); i++){
- if (occur[ps[i].toInt()].size() < occur[ps[min_i].toInt()].size())
- min_i = i;
- }
-
- vec<ClauseSimp>& cs = occur[ps[min_i].toInt()];
- for (ClauseSimp *it = cs.getData(), *end = it + cs.size(); it != end; it++){
- if (it+1 != end)
- __builtin_prefetch((it+1)->clause, 1, 1);
-
- if (it->clause != &ps && subsetAbst(ps.getAbst(), it->clause->getAbst()) && ps.size() <= it->clause->size() && subset(ps, *it->clause)) {
- out_subsumed.push(*it);
- #ifdef VERBOSE_DEBUG
- cout << "subsumed: ";
- it->clause->plainPrint();
- #endif
- }
- }
+ solver.testAllClauseAttach();
+ return true;
}
-void Subsumer::findSubsumed(Clause& ps, uint32_t abs, vec<ClauseSimp>& out_subsumed)
+void Subsumer::removeAssignedVarsFromEliminated()
{
- #ifdef VERBOSE_DEBUG
- cout << "findSubsumed: ";
- for (uint32_t i = 0; i < ps.size(); i++) {
- if (ps[i].sign()) printf("-");
- printf("%d ", ps[i].var() + 1);
- }
- printf("0\n");
- #endif
-
- int min_i = 0;
- for (uint32_t i = 1; i < ps.size(); i++){
- if (occur[ps[i].toInt()].size() < occur[ps[min_i].toInt()].size())
- min_i = i;
- }
-
- vec<ClauseSimp>& cs = occur[ps[min_i].toInt()];
- for (ClauseSimp *it = cs.getData(), *end = it + cs.size(); it != end; it++){
- if (it+1 != end)
- __builtin_prefetch((it+1)->clause, 1, 1);
-
- if (it->clause != &ps && subsetAbst(abs, it->clause->getAbst()) && ps.size() <= it->clause->size() && subset(ps, *it->clause)) {
- out_subsumed.push(*it);
- #ifdef VERBOSE_DEBUG
- cout << "subsumed: ";
- it->clause->plainPrint();
- #endif
+ for (Var var = 0; var < var_elimed.size(); var++) {
+ if (var_elimed[var] && solver.assigns[var] != l_Undef) {
+ var_elimed[var] = false;
+ solver.setDecisionVar(var, true);
+ numElimed--;
+ map<Var, vector<Clause*> >::iterator it = elimedOutVar.find(var);
+ if (it != elimedOutVar.end()) {
+ //TODO memory loss here
+ elimedOutVar.erase(it);
+ }
}
}
}
-void Subsumer::findSubsumed(const vec<Lit>& ps, const uint32_t abst, vec<ClauseSimp>& out_subsumed)
+template<class T>
+void Subsumer::findSubsumed(const T& ps, uint32_t abs, vec<ClauseSimp>& out_subsumed)
{
#ifdef VERBOSE_DEBUG
cout << "findSubsumed: ";
if (it+1 != end)
__builtin_prefetch((it+1)->clause, 1, 1);
- if (subsetAbst(abst, it->clause->getAbst()) && ps.size() <= it->clause->size() && subset(ps, *it->clause)) {
+ if (it->clause != (Clause*)&ps && subsetAbst(abs, it->clause->getAbst()) && ps.size() <= it->clause->size() && subset(ps, *it->clause)) {
out_subsumed.push(*it);
#ifdef VERBOSE_DEBUG
cout << "subsumed: ";
void inline Subsumer::DeallocPsNs(vec<ClauseSimp>& ps, vec<ClauseSimp>& ns)
{
for (uint32_t i = 0; i < ps.size(); i++) {
- clauses[ps[i].index].clause = NULL;
- free(ps[i].clause);
+ //clauses[ps[i].index].clause = NULL;
+ //clauseFree(ps[i].clause);
}
for (uint32_t i = 0; i < ns.size(); i++) {
- clauses[ns[i].index].clause = NULL;
- free(ns[i].clause);
+ //clauses[ns[i].index].clause = NULL;
+ //clauseFree(ns[i].clause);
}
}
}
Abort:;
- // Maybe eliminate:
+ //Eliminate:
if (after_clauses <= before_clauses) {
vec<ClauseSimp> ps, ns;
MigrateToPsNs(poss, negs, ps, ns, x);
dummy.clear();
bool ok = merge(*ps[i].clause, *ns[j].clause, Lit(x, false), Lit(x, true), dummy);
if (ok){
- Clause* cl = solver.addClauseInt(dummy, 0);
+ uint32_t group_num = 0;
+ #ifdef STATS_NEEDED
+ group_num = solver.learnt_clause_group++;
+ if (solver.dynamic_behaviour_analysis) {
+ string name = solver.logger.get_group_name(ps[i].clause->getGroup()) + " " + solver.logger.get_group_name(ns[j].clause->getGroup());
+ solver.logger.set_group_name(group_num, name);
+ }
+ #endif
+ Clause* cl = solver.addClauseInt(dummy, group_num);
if (cl != NULL) {
ClauseSimp c = linkInClause(*cl);
- subsume0(*cl);
+ subsume0(*cl, cl->getAbst());
}
if (!solver.ok) return true;
}
Eliminated:
assert(occur[Lit(x, false).toInt()].size() + occur[Lit(x, true).toInt()].size() == 0);
- var_elimed[x] = 1;
+ var_elimed[x] = true;
numElimed++;
solver.setDecisionVar(x, false);
return true;
}
// Returns FALSE if clause is always satisfied ('out_clause' should not be used). 'seen' is assumed to be cleared.
-bool Subsumer::merge(Clause& ps, Clause& qs, Lit without_p, Lit without_q, vec<Lit>& out_clause)
+bool Subsumer::merge(const Clause& ps, const Clause& qs, const Lit without_p, const Lit without_q, vec<Lit>& out_clause)
{
for (uint32_t i = 0; i < ps.size(); i++){
if (ps[i] != without_p){
}
}
-const bool Subsumer::hyperUtility(vec<ClauseSimp>& iter, const Lit lit, BitArray& inside, vec<ClauseSimp>& addToClauses, uint32_t& hyperBinAdded, uint32_t& hyperBinUnitary)
+const bool Subsumer::hyperUtility(vec<ClauseSimp>& iter, const Lit lit, BitArray& inside, vec<Clause*>& addToClauses)
{
for (ClauseSimp *it = iter.getData(), *end = it + iter.size() ; it != end; it++) {
if (it->clause == NULL) continue;
uint32_t notIn = 0;
- Lit notInLit = Lit(0,false);
+ Lit notInLit = lit_Undef;
- Clause& cl2 = *it->clause;
- for (uint32_t i = 0; i < cl2.size(); i++) {
- if (cl2[i].var() == lit.var()) {
- notIn = 2;
- break;
+ Clause& cl = *it->clause;
+ for (uint32_t i = 0; i < cl.size(); i++) {
+ if (cl[i].var() == lit.var() || cl.size() == 2) {
+ goto next;
}
- if (!inside[cl2[i].toInt()]) {
+ if (!inside[cl[i].toInt()]) {
notIn++;
- notInLit = cl2[i];
+ if (notIn > 1) goto next;
+ notInLit = cl[i];
}
- if (notIn > 1) break;
}
if (notIn == 0) {
- if (solver.assigns[lit.var()] == l_Undef) {
- solver.uncheckedEnqueue(lit);
- solver.ok = (solver.propagate() == NULL);
- if (!solver.ok) return false;
- hyperBinUnitary++;
- } else if (solver.assigns[lit.var()] != boolToLBool(!lit.sign())) {
- solver.ok = false;
- return false;
- }
+ vec<Lit> lits(1);
+ lits[0] = lit;
+ solver.addClauseInt(lits, cl.getGroup());
+ if (!solver.ok) return false;
}
if (notIn == 1 && !inside[(~notInLit).toInt()]) {
vec<Lit> cs(2);
cs[0] = lit;
cs[1] = notInLit;
- Clause *cl3 = Clause_new(cs, 0);
- uint32_t index = subsume0(*cl3);
- if (index != std::numeric_limits<uint32_t>::max()) {
+ //uint32_t index = subsume0(cs, calcAbstraction(cs));
+ /*if (index != std::numeric_limits<uint32_t>::max()) {
+ Clause *cl3 = Clause_new(cs, cl.getGroup());
ClauseSimp c(cl3, index);
addToClauses.push(c);
inside.setBit((~notInLit).toInt());
std::cout << "HyperBinRes adding clause: ";
cl3->plainPrint();
#endif
- hyperBinAdded++;
- }
+ } else {*/
+ Clause *cl3 = Clause_new(cs, cl.getGroup());
+ addToClauses.push(cl3);
+ inside.setBit((~notInLit).toInt());
+ //}
}
+ next:;
}
return true;
BitArray inside;
inside.resize(solver.nVars()*2, 0);
uint32_t hyperBinAdded = 0;
- uint32_t hyperBinUnitary = 0;
- vec<ClauseSimp> addToClauses;
+ uint32_t oldTrailSize = solver.trail.size();
+ vec<Clause*> addToClauses;
+ vec<Lit> addedToInside;
uint64_t totalClausesChecked = 0;
vec<Var> varsToCheck;
- if (clauses.size() > 100000 || solver.order_heap.size() > 30000) {
+ if (clauses.size() > 500000 || solver.order_heap.size() > 50000) {
Heap<Solver::VarOrderLt> tmp(solver.order_heap);
- uint32_t thisTopX = std::min(tmp.size(), 1000U);
+ uint32_t thisTopX = std::min(tmp.size(), 5000U);
for (uint32_t i = 0; i != thisTopX; i++)
varsToCheck.push(tmp.removeMin());
} else {
varsToCheck.push(i);
}
- for (Var test = 0; test < 2*varsToCheck.size(); test++) if (solver.assigns[test/2] == l_Undef && solver.decision_var[test/2]) {
- if (totalClausesChecked > 5000000)
+ for (uint32_t test = 0; test < 2*varsToCheck.size(); test++) if (solver.assigns[test/2] == l_Undef && solver.decision_var[test/2]) {
+ if (totalClausesChecked > 1000000)
break;
inside.setZero();
+ addToClauses.clear();
+ addedToInside.clear();
+
Lit lit(varsToCheck[test/2], test&1);
#ifdef HYPER_DEBUG
std::cout << "Resolving with literal:" << (lit.sign() ? "-" : "") << lit.var()+1 << std::endl;
#endif
-
- vec<Lit> addedToInside;
+
+ //fill inside with binary clauses' literals that this lit is in
+ //addedToInside now contains the list
vec<ClauseSimp>& set = occur[lit.toInt()];
+ totalClausesChecked += occur.size();
for (ClauseSimp *it = set.getData(), *end = it + set.size() ; it != end; it++) {
if (it->clause == NULL) continue;
Clause& cl2 = *it->clause;
if (cl2.size() > 2) continue;
assert(cl2[0] == lit || cl2[1] == lit);
if (cl2[0] == lit) {
- inside.setBit((~cl2[1]).toInt());
- addedToInside.push(~cl2[1]);
+ if (!inside[(~cl2[1]).toInt()]) {
+ inside.setBit((~cl2[1]).toInt());
+ addedToInside.push(~cl2[1]);
+ }
} else {
- inside.setBit((~cl2[0]).toInt());
- addedToInside.push(~cl2[0]);
+ if (!inside[(~cl2[0]).toInt()]) {
+ inside.setBit((~cl2[0]).toInt());
+ addedToInside.push(~cl2[0]);
+ }
}
}
totalClausesChecked += sum;
for (uint32_t add = 0; add < addedToInside.size(); add++) {
vec<ClauseSimp>& iter = occur[addedToInside[add].toInt()];
- if (!hyperUtility(iter, lit, inside, addToClauses, hyperBinAdded, hyperBinUnitary))
+ if (!hyperUtility(iter, lit, inside, addToClauses))
return false;
}
} else {
totalClausesChecked += clauses.size();
- if (!hyperUtility(clauses, lit, inside, addToClauses, hyperBinAdded, hyperBinUnitary))
+ if (!hyperUtility(clauses, lit, inside, addToClauses))
return false;
}
-
+
+ hyperBinAdded += addToClauses.size();
for (uint32_t i = 0; i < addToClauses.size(); i++) {
- Clause *c = solver.addClauseInt(*addToClauses[i].clause, 0);
- free(addToClauses[i].clause);
+ Clause *c = solver.addClauseInt(*addToClauses[i], addToClauses[i]->getGroup());
+ clauseFree(addToClauses[i]);
if (c != NULL) {
- ClauseSimp cc(c, addToClauses[i].index);
- clauses[cc.index] = cc;
- linkInAlreadyClause(cc);
- solver.becameBinary++; //since this binary did not exist, and now it exists.
+ ClauseSimp cc = linkInClause(*c);
subsume1(cc);
}
if (!solver.ok) return false;
}
- addToClauses.clear();
}
if (solver.verbosity >= 1) {
std::cout << "c | Hyper-binary res binary added: " << std::setw(5) << hyperBinAdded
- << " unitaries: " << std::setw(5) << hyperBinUnitary
+ << " unitaries: " << std::setw(5) << solver.trail.size() - oldTrailSize
<< " time: " << std::setprecision(2) << std::setw(5)<< cpuTime() - myTime << " s"
<< " |" << std::endl;
}
int negHash;
};
-int hash32shift(int key)
-{
- key = ~key + (key << 15); // key = (key << 15) - key - 1;
- key = key ^ (key >> 12);
- key = key + (key << 2);
- key = key ^ (key >> 4);
- key = key * 2057; // key = (key + (key << 3)) + (key << 11);
- key = key ^ (key >> 16);
- return key;
-}
-
void Subsumer::verifyIntegrity()
{
vector<uint> occurNum(solver.nVars()*2, 0);
solver.setDecisionVar(lit.var(), false);
vec<ClauseSimp> toRemove(occur[lit.toInt()]);
for (ClauseSimp *it = toRemove.getData(), *end = toRemove.getDataEnd(); it != end; it++) {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Next varelim because of block clause elim" << std::endl;
+ #endif //VERBOSE_DEBUG
unlinkClause(*it, lit.var());
numblockedClauseRemoved++;
}
vec<ClauseSimp> toRemove2(occur[negLit.toInt()]);
for (ClauseSimp *it = toRemove2.getData(), *end = toRemove2.getDataEnd(); it != end; it++) {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Next varelim because of block clause elim" << std::endl;
+ #endif //VERBOSE_DEBUG
unlinkClause(*it, lit.var());
numblockedClauseRemoved++;
}
return returnVal;
}
-/*vector<char> Subsumer::merge()
+const bool Subsumer::checkElimedUnassigned() const
+{
+ for (uint32_t i = 0; i < var_elimed.size(); i++) {
+ if (var_elimed[i]) {
+ assert(solver.assigns[i] == l_Undef);
+ if (solver.assigns[i] != l_Undef) return false;
+ }
+ }
+
+ return true;
+}
+
+/*
+int hash32shift(int key)
+{
+ key = ~key + (key << 15); // key = (key << 15) - key - 1;
+ key = key ^ (key >> 12);
+ key = key + (key << 2);
+ key = key ^ (key >> 4);
+ key = key * 2057; // key = (key + (key << 3)) + (key << 11);
+ key = key ^ (key >> 16);
+ return key;
+}
+
+vector<char> Subsumer::merge()
{
vector<char> var_merged(solver.nVars(), false);
double myTime = cpuTime();
{
for (Clause **it = pureLitClauseRemoved.getData(), **end = pureLitClauseRemoved.getDataEnd(); it != end; it++) {
solver.addClause(**it, (*it)->getGroup());
- free(*it);
+ clauseFree(*it);
assert(solver.ok);
}
pureLitClauseRemoved.clear();
class Subsumer
{
public:
-
+
+ //Construct-destruct
Subsumer(Solver& S2);
~Subsumer();
+
+ //Called from main
const bool simplifyBySubsumption();
+ const bool subsumeWithBinaries(const bool startUp);
+ void newVar();
+
+ //Used by cleaner
void unlinkModifiedClause(vec<Lit>& origClause, ClauseSimp c);
void unlinkModifiedClauseNoDetachNoNULL(vec<Lit>& origClause, ClauseSimp c);
void unlinkClause(ClauseSimp cc, Var elim = var_Undef);
ClauseSimp linkInClause(Clause& cl);
void linkInAlreadyClause(ClauseSimp& c);
void updateClause(ClauseSimp c);
- void newVar();
+
+
+ //UnElimination
void extendModel(Solver& solver2);
const bool unEliminate(const Var var);
+
+
+ //Get-functions
const vec<char>& getVarElimed() const;
const uint32_t getNumElimed() const;
+ const bool checkElimedUnassigned() const;
+ const double getTotalTime() const;
private:
vec<vec<ClauseSimp> > occur; // 'occur[index(lit)]' is a list of constraints containing 'lit'.
vec<vec<ClauseSimp>* > iter_vecs; // Vectors currently used for iterations. Removed clauses will be looked up and replaced by 'Clause_NULL'.
vec<CSet* > iter_sets; // Sets currently used for iterations.
- Solver& solver; // The Solver
-
-
- vec<char> var_elimed; // 'eliminated[var]' is TRUE if variable has been eliminated.
vec<char> cannot_eliminate;//
- map<Var, vector<vector<Lit> > > elimedOutVar;
+
+ //Global stats
+ Solver& solver;
+ vec<char> var_elimed; //TRUE if var has been eliminated
+ double totalTime;
+ uint32_t numElimed;
+ map<Var, vector<Clause*> > elimedOutVar;
// Temporaries (to reduce allocation overhead):
//
vec<char> seen_tmp; // (used in various places)
- vector<Lit> io_tmp; // (used for reading/writing clauses from/to disk)
//Limits
uint32_t numMaxBlockVars;
//Start-up
- void addFromSolver(vec<Clause*>& cs);
+ template<bool UseCL>
+ void addFromSolver(vec<Clause*>& cs, bool alsoLearnt = false);
void addBackToSolver();
void removeWrong(vec<Clause*>& cs);
+ void removeAssignedVarsFromEliminated();
void fillCannotEliminate();
const bool treatLearnts();
- void addAllXorAsNorm();
- void addXorAsNormal3(XorClause& c);
- void addXorAsNormal4(XorClause& c);
+ void clearAll();
//Iterations
void registerIteration (CSet& iter_set) { iter_sets.push(&iter_set); }
// Subsumption:
void touch(const Var x);
void touch(const Lit p);
- bool updateOccur(Clause& c);
- void findSubsumed(Clause& ps, vec<ClauseSimp>& out_subsumed);
- void findSubsumed(const vec<Lit>& ps, const uint32_t abst, vec<ClauseSimp>& out_subsumed);
- void findSubsumed(Clause& ps, uint32_t abs, vec<ClauseSimp>& out_subsumed);
+ template<class T>
+ void findSubsumed(const T& ps, const uint32_t abst, vec<ClauseSimp>& out_subsumed);
bool isSubsumed(Clause& ps);
- uint32_t subsume0(Clause& ps);
- uint32_t subsume0(Clause& ps, uint32_t abs);
+ template<class T>
+ uint32_t subsume0(T& ps, uint32_t abs);
+ template<class T>
+ uint32_t subsume0Orig(const T& ps, uint32_t abs);
+ void subsume0BIN(const Lit lit, const vec<char>& lits);
void subsume0LearntSet(vec<Clause*>& cs);
void subsume1(ClauseSimp& ps);
void smaller_database();
bool maybeEliminate(Var x);
void MigrateToPsNs(vec<ClauseSimp>& poss, vec<ClauseSimp>& negs, vec<ClauseSimp>& ps, vec<ClauseSimp>& ns, const Var x);
void DeallocPsNs(vec<ClauseSimp>& ps, vec<ClauseSimp>& ns);
- bool merge(Clause& ps, Clause& qs, Lit without_p, Lit without_q, vec<Lit>& out_clause);
-
+ bool merge(const Clause& ps, const Clause& qs, const Lit without_p, const Lit without_q, vec<Lit>& out_clause);
+
+ //Subsume with Nonexistent Bins
+ const bool subsWNonExistBinsFull(const bool startUp);
+ const bool subsWNonExistBins(const Lit& lit, const bool startUp);
+ template<class T>
+ void subsume1Partial(const T& ps);
+ uint32_t subsNonExistentNum;
+ uint32_t subsNonExistentumFailed;
+ bool subsNonExistentFinish;
+ double subsNonExistentTime;
+ uint32_t subsNonExistentLitsRemoved;
+ vec<Clause*> addBinaryClauses;
+ uint32_t doneNum;
+ vec<ClauseSimp> subsume1PartialSubs;
+ vec<Lit> subsume1PartialQs;
+ vec<Lit> toVisit;
+ vec<char> toVisitAll;
+ vec<Lit> ps2;
//hyperBinRes
void addFromSolverAll(vec<Clause*>& cs);
const bool hyperBinRes();
- const bool hyperUtility(vec<ClauseSimp>& iter, const Lit lit, BitArray& inside, vec<ClauseSimp>& addToClauses, uint32_t& hyperBinAdded, uint32_t& hyperBinUnitary);
+ const bool hyperUtility(vec<ClauseSimp>& iter, const Lit lit, BitArray& inside, vec<Clause*>& addToClauses);
//merging
//vector<char> merge();
uint32_t numCalls;
bool fullSubsume;
uint32_t clauseID;
- uint32_t numElimed;
};
template <class T, class T2>
touch(p.var());
}
-inline bool Subsumer::updateOccur(Clause& c)
-{
- return !c.learnt();
-}
-
inline bool Subsumer::subsetAbst(uint32_t A, uint32_t B)
{
return !(A & ~B);
return numElimed;
}
+inline const double Subsumer::getTotalTime() const
+{
+ return totalTime;
+}
+
}; //NAMESPACE MINISAT
#endif //SIMPLIFIER_H
#include <iostream>
#include <iomanip>
-#include "Conglomerate.h"
#include "ClauseCleaner.h"
#include "PartHandler.h"
#include "time_mem.h"
VarReplacer::~VarReplacer()
{
for (uint i = 0; i != clauses.size(); i++)
- //binaryClausePool.free(clauses[i]);
- free(clauses[i]);
+ clauseFree(clauses[i]);
}
const bool VarReplacer::performReplaceInternal()
#endif //REPLACE_STATISTICS
solver.clauseCleaner->removeAndCleanAll(true);
- if (solver.ok == false) return false;
+ if (!solver.ok) return false;
+ solver.testAllClauseAttach();
#ifdef VERBOSE_DEBUG
{
#endif
Var var = 0;
- const vec<bool>& removedVars = solver.conglomerate->getRemovedVars();
+ const vec<char>& removedVars = solver.xorSubsumer->getVarElimed();
const vec<lbool>& removedVars2 = solver.partHandler->getSavedState();
const vec<char>& removedVars3 = solver.subsumer->getVarElimed();
for (vector<Lit>::const_iterator it = table.begin(); it != table.end(); it++, var++) {
lastReplacedVars = replacedVars;
- if (!replace_set(solver.clauses)) goto end;
- if (!replace_set(solver.learnts)) goto end;
- if (!replace_set(solver.binaryClauses)) goto end;
+ solver.testAllClauseAttach();
+ if (!replace_set(solver.binaryClauses, true)) goto end;
+ if (!replace_set(solver.clauses, false)) goto end;
+ if (!replace_set(solver.learnts, false)) goto end;
if (!replace_set(solver.xorclauses)) goto end;
+ solver.testAllClauseAttach();
end:
for (uint i = 0; i != clauses.size(); i++)
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()) {
}
if (changed && handleUpdatedClause(c, origVar1, origVar2)) {
- if (solver.ok == false) {
- for(;r != end; r++) free(*r);
+ if (!solver.ok) {
+ for(;r != end; r++) clauseFree(*r);
cs.shrink(r-a);
return false;
}
+ c.setRemoved();
+ solver.freeLater.push(&c);
} else {
*a++ = *r;
}
const bool VarReplacer::handleUpdatedClause(XorClause& c, const Var origVar1, const Var origVar2)
{
uint origSize = c.size();
- std::sort(c.getData(), c.getData() + c.size());
+ std::sort(c.getData(), c.getDataEnd());
Lit p;
uint32_t i, j;
for (i = j = 0, p = lit_Undef; i != c.size(); i++) {
- c[i] = c[i].unsign();
- if (c[i] == p) {
+ if (c[i].var() == p.var()) {
//added, but easily removed
j--;
p = lit_Undef;
if (!solver.assigns[c[i].var()].isUndef())
c.invert(solver.assigns[c[i].var()].getBool());
- solver.clauses_literals -= 2;
} else if (solver.assigns[c[i].var()].isUndef()) //just add
c[j++] = p = c[i];
else c.invert(solver.assigns[c[i].var()].getBool()); //modify xor_clause_inverted instead of adding
return true;
case 1:
solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
- solver.uncheckedEnqueue(c[0] ^ c.xor_clause_inverted());
+ solver.uncheckedEnqueue(Lit(c[0].var(), c.xor_clause_inverted()));
solver.ok = (solver.propagate() == NULL);
return true;
case 2: {
solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
- vec<Lit> ps(2);
- ps[0] = c[0];
- ps[1] = c[1];
- addBinaryXorClause(ps, c.xor_clause_inverted(), c.getGroup(), true);
+ c[0] = c[0].unsign();
+ c[1] = c[1].unsign();
+ addBinaryXorClause(c, c.xor_clause_inverted(), c.getGroup(), true);
return true;
}
default:
return false;
}
-const bool VarReplacer::replace_set(vec<Clause*>& cs)
+const bool VarReplacer::replace_set(vec<Clause*>& cs, const bool binClauses)
{
Clause **a = cs.getData();
Clause **r = a;
}
if (changed && handleUpdatedClause(c, origLit1, origLit2)) {
- if (solver.ok == false) {
- for(;r != end; r++) free(*r);
+ if (!solver.ok) {
+ for(;r != end; r++) clauseFree(*r);
cs.shrink(r-a);
return false;
}
} else {
- *a++ = *r;
+ if (!binClauses && c.size() == 2) {
+ solver.becameBinary++;
+ solver.binaryClauses.push(&c);
+ } else
+ *a++ = *r;
}
}
cs.shrink(r-a);
void VarReplacer::extendModelPossible() const
{
+ #ifdef VERBOSE_DEBUG
+ std::cout << "extendModelPossible() called" << std::endl;
+ #endif //VERBOSE_DEBUG
uint i = 0;
for (vector<Lit>::const_iterator it = table.begin(); it != table.end(); it++, i++) {
if (it->var() == i) continue;
void VarReplacer::extendModelImpossible(Solver& solver2) const
{
+
+ #ifdef VERBOSE_DEBUG
+ std::cout << "extendModelImpossible() called" << std::endl;
+ #endif //VERBOSE_DEBUG
+
vec<Lit> tmpClause;
uint i = 0;
for (vector<Lit>::const_iterator it = table.begin(); it != table.end(); it++, i++) {
const uint getNumReplacedVars() const;
const uint getNumLastReplacedVars() const;
const uint getNewToReplaceVars() const;
+ const uint32_t getNumTrees() const;
const vector<Var> getReplacingVars() const;
const vector<Lit>& getReplaceTable() const;
const vec<Clause*>& getClauses() const;
private:
const bool performReplaceInternal();
- const bool replace_set(vec<Clause*>& set);
+ const bool replace_set(vec<Clause*>& cs, const bool binClauses);
const bool replace_set(vec<XorClause*>& cs);
const bool handleUpdatedClause(Clause& c, const Lit origLit1, const Lit origLit2);
const bool handleUpdatedClause(XorClause& c, const Var origVar1, const Var origVar2);
return (reverseTable.find(var) != reverseTable.end());
}
+inline const uint32_t VarReplacer::getNumTrees() const
+{
+ return reverseTable.size();
+}
+
}; //NAMESPACE MINISAT
#endif //VARREPLACER_H
uint sumLengths = 0;
double time = cpuTime();
foundXors = 0;
- solver.clauseCleaner->cleanClauses(cls, type);
- if (solver.ok == false)
- return false;
+ solver.clauseCleaner->cleanClauses(solver.clauses, ClauseCleaner::clauses);
+ if (type == ClauseCleaner::binaryClauses) {
+ solver.clauseCleaner->cleanClauses(solver.binaryClauses, ClauseCleaner::binaryClauses);
+ }
+ if (!solver.ok) return false;
toRemove.clear();
toRemove.resize(cls.size(), false);
}
if (!sorted) {
solver.detachClause(c);
- std::sort(c.getData(), c.getData()+c.size());
+ std::sort(c.getData(), c.getDataEnd());
solver.attachClause(c);
}
} else {
XorClause* x = XorClause_new(lits, impair, old_group);
cout << "- Final 2-long xor-clause: ";
x->plainPrint();
- free(x);
+ clauseFree(x);
#endif
break;
}
//#define VERBOSE_DEBUG
#ifdef VERBOSE_DEBUG
+#define VERBOSE_DEBUGSUBSUME0
#define BIT_MORE_VERBOSITY
#endif
-//#define BIT_MORE_VERBOSITY
-//#define TOUCH_LESS
-
#ifdef VERBOSE_DEBUG
using std::cout;
using std::endl;
XorSubsumer::XorSubsumer(Solver& s):
solver(s)
+ , totalTime(0.0)
+ , numElimed(0)
+ , localSubstituteUseful(0)
{
};
// Will put NULL in 'cs' if clause removed.
void XorSubsumer::subsume0(XorClauseSimp& ps)
{
- assert(solver.xorclauses.size() == 0);
- #ifdef VERBOSE_DEBUG
+ #ifdef VERBOSE_DEBUGSUBSUME0
cout << "subsume0 orig clause:";
ps.clause->plainPrint();
- cout << "pointer:" << &ps << endl;
#endif
vec<Lit> origClause(ps.clause->size());
vec<XorClauseSimp> subs;
findSubsumed(*ps.clause, subs);
for (uint32_t i = 0; i < subs.size(); i++){
- #ifdef VERBOSE_DEBUG
- cout << "subsume0 removing:";
- subs[i].clause->plainPrint();
- #endif
-
XorClause* tmp = subs[i].clause;
findUnMatched(origClause, *tmp, unmatchedPart);
if (unmatchedPart.size() == 0) {
+ #ifdef VERBOSE_DEBUGSUBSUME0
+ cout << "subsume0 removing:";
+ subs[i].clause->plainPrint();
+ #endif
clauses_subsumed++;
assert(tmp->size() == origClause.size());
if (origClauseInverted == tmp->xor_clause_inverted()) {
unlinkClause(subs[i]);
- free(tmp);
+ clauseFree(tmp);
} else {
solver.ok = false;
return;
} else {
assert(unmatchedPart.size() > 0);
clauses_cut++;
- //XorClause *c = solver.addXorClauseInt(unmatchedPart, tmp->xor_clause_inverted() ^ origClauseInverted, tmp->getGroup());
- if (!solver.ok) return;
- //if (c != NULL) {
- //linkInClause(*c);
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Cutting xor-clause:";
+ subs[i].clause->plainPrint();
+ #endif //VERBOSE_DEBUG
+ XorClause *c = solver.addXorClauseInt(unmatchedPart, tmp->xor_clause_inverted() ^ !origClauseInverted, tmp->getGroup());
+ if (c != NULL) {
+ linkInClause(*c);
needUnlinkPS = true;
- //}
+ }
+ if (!solver.ok) return;
}
unmatchedPart.clear();
}
- /*if (needUnlinkPS) {
+ if (needUnlinkPS) {
XorClause* tmp = ps.clause;
unlinkClause(ps);
- free(tmp);
- }*/
+ clauseFree(tmp);
+ }
}
void XorSubsumer::findUnMatched(vec<Lit>& A, XorClause& B, vec<Lit>& unmatchedPart)
}
}
-void XorSubsumer::unlinkClause(XorClauseSimp c)
+void XorSubsumer::unlinkClause(XorClauseSimp c, const Var elim)
{
XorClause& cl = *c.clause;
maybeRemove(occur[cl[i].var()], &cl);
}
+ if (elim != var_Undef)
+ elimedOutVar[elim].push_back(c.clause);
+
solver.detachClause(cl);
clauses[c.index].clause = NULL;
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)
(*i)->calcXorAbstraction();
}
cs.clear();
+ cs.push(NULL); //HACK --to force xor-propagation
}
void XorSubsumer::addBackToSolver()
{
+ solver.xorclauses.pop(); //HACK --to force xor-propagation
for (uint32_t i = 0; i < clauses.size(); i++) {
if (clauses[i].clause != NULL) {
solver.xorclauses.push(clauses[i].clause);
clauseID = 0;
}
+void XorSubsumer::fillCannotEliminate()
+{
+ std::fill(cannot_eliminate.getData(), cannot_eliminate.getDataEnd(), false);
+ for (uint32_t i = 0; i < solver.clauses.size(); i++)
+ addToCannotEliminate(solver.clauses[i]);
+
+ for (uint32_t i = 0; i < solver.binaryClauses.size(); i++)
+ if (!(*solver.binaryClauses[i]).learnt()) addToCannotEliminate(solver.binaryClauses[i]);
+
+ const vec<Clause*>& tmp = solver.varReplacer->getClauses();
+ for (uint32_t i = 0; i < tmp.size(); i++)
+ addToCannotEliminate(tmp[i]);
+
+ #ifdef VERBOSE_DEBUG
+ uint32_t tmpNum = 0;
+ for (uint32_t i = 0; i < cannot_eliminate.size(); i++)
+ if (cannot_eliminate[i])
+ tmpNum++;
+ std::cout << "Cannot eliminate num:" << tmpNum << std::endl;
+ #endif
+}
+
+void XorSubsumer::extendModel(Solver& solver2)
+{
+ assert(checkElimedUnassigned());
+ vec<Lit> tmp;
+ typedef map<Var, vector<XorClause*> > elimType;
+ for (elimType::iterator it = elimedOutVar.begin(), end = elimedOutVar.end(); it != end; it++) {
+ #ifdef VERBOSE_DEBUG
+ Var var = it->first;
+ std::cout << "Reinserting elimed var: " << var+1 << std::endl;
+ #endif
+
+ for (vector<XorClause*>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
+ XorClause& c = **it2;
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Reinserting Clause: ";
+ c.plainPrint();
+ #endif
+ tmp.clear();
+ tmp.growTo(c.size());
+ std::copy(c.getData(), c.getDataEnd(), tmp.getData());
+ bool inverted = c.xor_clause_inverted();
+ solver2.addXorClause(tmp, inverted);
+ assert(solver2.ok);
+ }
+ }
+}
+
+const bool XorSubsumer::localSubstitute()
+{
+ vec<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();
+ tmp.growTo(c1.size() + c2.size());
+ std::copy(c1.getData(), c1.getDataEnd(), tmp.getData());
+ std::copy(c2.getData(), c2.getDataEnd(), tmp.getData() + c1.size());
+ clearDouble(tmp);
+ if (tmp.size() <= 2) {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Local substiuting. Clause1:"; c1.plainPrint();
+ std::cout << "Clause 2:"; c2.plainPrint();
+ #endif //VERBOSE_DEBUG
+ localSubstituteUseful++;
+ uint32_t lastSize = solver.varReplacer->getClauses().size();
+ solver.addXorClauseInt(tmp, c1.xor_clause_inverted() ^ !c2.xor_clause_inverted(), c1.getGroup());
+ for (uint32_t i = lastSize; i < solver.varReplacer->getClauses().size(); i++)
+ addToCannotEliminate(solver.varReplacer->getClauses()[i]);
+ if (!solver.ok) {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "solver.ok is false after local substitution" << std::endl;
+ #endif //VERBOSE_DEBUG
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+void XorSubsumer::clearDouble(vec<Lit>& ps) const
+{
+ std::sort(ps.getData(), ps.getDataEnd());
+ Lit p;
+ uint32_t i, j;
+ for (i = j = 0, p = lit_Undef; i != ps.size(); i++) {
+ if (ps[i].var() == p.var()) {
+ //added, but easily removed
+ j--;
+ p = lit_Undef;
+ } else
+ ps[j++] = p = ps[i];
+ }
+ ps.shrink(i - j);
+}
+
+void XorSubsumer::removeWrong(vec<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);
+ clauseFree(&c);
+ break;
+ }
+ }
+ if (!remove)
+ *j++ = *i;
+ }
+ cs.shrink(i-j);
+}
+
+
+const bool XorSubsumer::removeDependent()
+{
+ for (Var var = 0; var < occur.size(); var++) {
+ if (cannot_eliminate[var] || !solver.decision_var[var] || solver.assigns[var] != l_Undef) continue;
+ vec<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.xor_clause_inverted();
+
+ XorClause& c2 = *(occ[1].clause);
+ lits.growTo(lits.size() + c2.size());
+ std::copy(c2.getData(), c2.getDataEnd(), lits.getData() + c1.size());
+ inverted ^= !c2.xor_clause_inverted();
+ uint32_t group = c2.getGroup();
+
+ #ifdef VERBOSE_DEBUG
+ std::cout << "Eliminating var " << var + 1 << " present in 2 xor-clauses" << std::endl;
+ std::cout << "-> Removing xor clause "; occ[0].clause->plainPrint();
+ std::cout << "-> Removing xor clause "; occ[1].clause->plainPrint();
+ #endif //VERBOSE_DEBUG
+ XorClauseSimp toUnlink0 = occ[0];
+ XorClauseSimp toUnlink1 = occ[1];
+ unlinkClause(toUnlink0);
+ clauseFree(toUnlink0.clause);
+ unlinkClause(toUnlink1, var);
+ solver.setDecisionVar(var, false);
+ var_elimed[var] = true;
+ numElimed++;
+
+ uint32_t lastSize = solver.varReplacer->getClauses().size();
+ XorClause* c = solver.addXorClauseInt(lits, inverted, group);
+ #ifdef VERBOSE_DEBUG
+ if (c != NULL) {
+ std::cout << "-> Added combined xor clause:"; c->plainPrint();
+ } else
+ std::cout << "-> Combined xor clause is NULL" << std::endl;
+ #endif
+ if (c != NULL) linkInClause(*c);
+ for (uint32_t i = lastSize; i < solver.varReplacer->getClauses().size(); i++)
+ addToCannotEliminate(solver.varReplacer->getClauses()[i]);
+ if (!solver.ok) {
+ #ifdef VERBOSE_DEBUG
+ std::cout << "solver.ok is false after var-elim through xor" << std::endl;
+ #endif //VERBOSE_DEBUG
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+inline void XorSubsumer::addToCannotEliminate(Clause* it)
+{
+ const Clause& c = *it;
+ for (uint32_t i2 = 0; i2 < c.size(); i2++)
+ cannot_eliminate[c[i2].var()] = true;
+}
+
+const bool XorSubsumer::unEliminate(const Var var)
+{
+ assert(var_elimed[var]);
+ typedef map<Var, vector<XorClause*> > elimType;
+ elimType::iterator it = elimedOutVar.find(var);
+
+ //MUST set to decision, since it would never have been eliminated
+ //had it not been decision var
+ solver.setDecisionVar(var, true);
+ var_elimed[var] = false;
+ numElimed--;
+ assert(it != elimedOutVar.end());
+
+ FILE* backup_libraryCNFfile = solver.libraryCNFFile;
+ solver.libraryCNFFile = NULL;
+ for (vector<XorClause*>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) {
+ XorClause& c = **it2;
+ solver.addXorClause(c, c.xor_clause_inverted());
+ clauseFree(&c);
+ }
+ solver.libraryCNFFile = backup_libraryCNFfile;
+ elimedOutVar.erase(it);
+
+ return solver.ok;
+}
+
+
const bool XorSubsumer::simplifyBySubsumption(const bool doFullSubsume)
{
double myTime = cpuTime();
clauses_subsumed = 0;
clauses_cut = 0;
clauseID = 0;
-
- for (Var var = 0; var < solver.nVars(); var++) {
- //occur[var].clear(true);
- newVar();
- }
-
+ uint32_t lastNumElimed = numElimed;
+ localSubstituteUseful = 0;
while (solver.performReplace && solver.varReplacer->needsReplace()) {
if (!solver.varReplacer->performReplace())
return false;
}
+ for (Var var = 0; var < solver.nVars(); var++) {
+ occur[var].clear();
+ }
+ solver.findAllAttach();
+
solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses);
if (!solver.ok) return false;
+ solver.testAllClauseAttach();
clauses.clear();
clauses.reserve(solver.xorclauses.size());
for (uint32_t i = 0; i < clauses.size(); i++) {
if (clauses[i].clause != NULL) {
subsume0(clauses[i]);
- if (!solver.ok) return false;
+ if (!solver.ok) {
+ addBackToSolver();
+ return false;
+ }
}
}
- if (solver.qhead != solver.trail.size()) propagated = true;
- solver.ok = solver.propagate() == NULL;
+ propagated = (solver.qhead != solver.trail.size());
+ solver.ok = (solver.propagate() == NULL);
if (!solver.ok) {
std::cout << "c (contradiction during subsumption)" << std::endl;
return false;
}
solver.clauseCleaner->cleanXorClausesBewareNULL(clauses, ClauseCleaner::xorSimpClauses, *this);
if (!solver.ok) return false;
-
- if (solver.performReplace && solver.varReplacer->needsReplace()) {
+ testAllClauseAttach();
+
+ fillCannotEliminate();
+ if (solver.conglomerateXors && !removeDependent()) {
+ addBackToSolver();
+ return false;
+ }
+ testAllClauseAttach();
+
+ if (solver.heuleProcess && !localSubstitute()) {
+ addBackToSolver();
+ return false;
+ }
+ testAllClauseAttach();
+
+ /*if (solver.performReplace && solver.varReplacer->needsReplace()) {
addBackToSolver();
while (solver.performReplace && solver.varReplacer->needsReplace()) {
replaced = true;
return false;
}
addFromSolver(solver.xorclauses);
- }
+ }*/
}
-
- if (solver.trail.size() - origTrailSize > 0)
- solver.order_heap.filter(Solver::VarFilter(solver));
-
+
+ solver.order_heap.filter(Solver::VarFilter(solver));
+
+ removeWrong(solver.learnts);
+ removeWrong(solver.binaryClauses);
addBackToSolver();
if (solver.verbosity >= 1) {
- std::cout << "c | xorclauses-subsumed: " << std::setw(9) << clauses_subsumed
- << " xorclauses-cut: " << std::setw(9) << clauses_cut
- << " vars fixed: " << std::setw(3) <<solver.trail.size() - origTrailSize
- << " time: " << std::setw(5) << std::setprecision(2) << (cpuTime() - myTime)
- << " |" << std::endl;
+ std::cout << "c | x-sub: " << std::setw(5) << clauses_subsumed
+ << " x-cut: " << std::setw(6) << clauses_cut
+ << " vfix: " << std::setw(6) <<solver.trail.size() - origTrailSize
+ << " v-elim: " <<std::setw(6) << numElimed - lastNumElimed
+ << " locsubst:" << std::setw(6) << localSubstituteUseful
+ << " time: " << std::setw(6) << std::setprecision(2) << (cpuTime() - myTime)
+ << std::setw(3) << " |" << std::endl;
}
+ totalTime += cpuTime() - myTime;
+ solver.testAllClauseAttach();
return true;
}
+#ifdef DEBUG_ATTACH
+void XorSubsumer::testAllClauseAttach() const
+{
+ for (const XorClauseSimp *it = clauses.getData(), *end = clauses.getDataEnd(); it != end; it++) {
+ if (it->clause == NULL) continue;
+ const XorClause& c = *it->clause;
+ assert(find(solver.xorwatches[c[0].var()], &c));
+ assert(find(solver.xorwatches[c[1].var()], &c));
+ if (solver.assigns[c[0].var()]!=l_Undef || solver.assigns[c[1].var()]!=l_Undef) {
+ for (uint i = 0; i < c.size();i++) {
+ assert(solver.assigns[c[i].var()] != l_Undef);
+ }
+ }
+ }
+}
+#else
+inline void XorSubsumer::testAllClauseAttach() const
+{
+ return;
+}
+#endif //DEBUG_ATTACH
+
void XorSubsumer::findSubsumed(XorClause& ps, vec<XorClauseSimp>& out_subsumed)
{
- #ifdef VERBOSE_DEBUG
+ #ifdef VERBOSE_DEBUGSUBSUME0
cout << "findSubsumed: ";
for (uint32_t i = 0; i < ps.size(); i++) {
if (ps[i].sign()) printf("-");
if (it->clause != &ps && subsetAbst(ps.getAbst(), it->clause->getAbst()) && ps.size() <= it->clause->size() && subset(ps, *it->clause)) {
out_subsumed.push(*it);
- #ifdef VERBOSE_DEBUG
+ #ifdef VERBOSE_DEBUGSUBSUME0
cout << "subsumed: ";
it->clause->plainPrint();
#endif
}
}
-}; //NAMESPACE MINISAT
+const bool XorSubsumer::checkElimedUnassigned() const
+{
+ for (uint32_t i = 0; i < var_elimed.size(); i++) {
+ if (var_elimed[i]) {
+ assert(solver.assigns[i] == l_Undef);
+ if (solver.assigns[i] != l_Undef) return false;
+ }
+ }
+
+ return true;
+}
+
+}; //NAMESPACE MINISAT
\ No newline at end of file
const bool simplifyBySubsumption(const bool doFullSubsume = false);
void unlinkModifiedClause(vec<Lit>& origClause, XorClauseSimp c);
void unlinkModifiedClauseNoDetachNoNULL(vec<Lit>& origClause, XorClauseSimp c);
- void unlinkClause(XorClauseSimp cc);
+ void unlinkClause(XorClauseSimp cc, Var elim = var_Undef);
XorClauseSimp linkInClause(XorClause& cl);
void linkInAlreadyClause(XorClauseSimp& c);
void newVar();
+ void extendModel(Solver& solver2);
+ const uint32_t getNumElimed() const;
+ const vec<char>& getVarElimed() const;
+ const bool unEliminate(const Var var);
+ const bool checkElimedUnassigned() const;
+ const double getTotalTime() const;
private:
bool subset(const T1& A, const T2& B);
bool subsetAbst(uint32_t A, uint32_t B);
void findUnMatched(vec<Lit>& A, XorClause& B, vec<Lit>& unmatchedPart);
+
+ //helper
+ void testAllClauseAttach() const;
+
+ //dependent removal
+ const bool removeDependent();
+ void fillCannotEliminate();
+ vec<char> cannot_eliminate;
+ void addToCannotEliminate(Clause* it);
+ void removeWrong(vec<Clause*>& cs);
+
+ //Global stats
+ double totalTime;
+ map<Var, vector<XorClause*> > elimedOutVar;
+ vec<char> var_elimed;
+ uint32_t numElimed;
+
+ //Heule-process
+ void clearDouble(vec<Lit>& ps) const;
+ const bool localSubstitute();
+ uint32_t localSubstituteUseful;
uint32_t clauses_subsumed;
uint32_t clauses_cut;
inline void XorSubsumer::newVar()
{
occur .push();
- seen_tmp .push(0); // (one for each polarity)
+ seen_tmp .push(0);
+ cannot_eliminate.push(0);
+ var_elimed.push(0);
+}
+
+inline const vec<char>& XorSubsumer::getVarElimed() const
+{
+ return var_elimed;
+}
+
+inline const uint32_t XorSubsumer::getNumElimed() const
+{
+ return numElimed;
+}
+
+inline const double XorSubsumer::getTotalTime() const
+{
+ return totalTime;
}
}; //NAMESPACE MINISAT
-/****************************************************************************************[Solver.h]
-MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
-glucose -- Gilles Audemard, Laurent Simon (2008)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
-associated documentation files (the "Software"), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge, publish, distribute,
-sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or
-substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
-NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
-OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-**************************************************************************************************/
-
-#define RATIOREMOVECLAUSES 3
-#define NBCLAUSESBEFOREREDUCE 20000
-#define DYNAMICNBLEVEL
-#define UPDATEVARACTIVITY
-#define FIXCLEANREPLACE 30U
-#define PERCENTAGEPERFORMREPLACE 0.01
-#define PERCENTAGECLEANCLAUSES 0.01
-#define MAX_CLAUSENUM_XORFIND 5000000
-#define BINARY_TO_XOR_APPROX 4.0
-#define FULLRESTART_MULTIPLIER 250.0
-#define FULLRESTART_MULTIPLIER_MULTIPLIER 3.5
-#define RESTART_TYPE_DECIDER_FROM 2
-#define RESTART_TYPE_DECIDER_UNTIL 7
-//#define VERBOSE_DEBUG_XOR
-//#define VERBOSE_DEBUG
-//#define USE_GAUSS