Initial checkin of SAT solvers
authorbdemsky <bdemsky@uci.edu>
Thu, 25 Dec 2014 00:52:58 +0000 (16:52 -0800)
committerbdemsky <bdemsky@uci.edu>
Thu, 25 Dec 2014 00:52:58 +0000 (16:52 -0800)
79 files changed:
glucose-syrup/Changelog [new file with mode: 0644]
glucose-syrup/LICENCE [new file with mode: 0644]
glucose-syrup/README [new file with mode: 0644]
glucose-syrup/core/BoundedQueue.h [new file with mode: 0644]
glucose-syrup/core/Constants.h [new file with mode: 0644]
glucose-syrup/core/Dimacs.h [new file with mode: 0644]
glucose-syrup/core/Makefile [new file with mode: 0644]
glucose-syrup/core/Solver.cc [new file with mode: 0644]
glucose-syrup/core/Solver.h [new file with mode: 0644]
glucose-syrup/core/SolverTypes.h [new file with mode: 0644]
glucose-syrup/mtl/Alg.h [new file with mode: 0644]
glucose-syrup/mtl/Alloc.h [new file with mode: 0644]
glucose-syrup/mtl/Clone.h [new file with mode: 0644]
glucose-syrup/mtl/Heap.h [new file with mode: 0644]
glucose-syrup/mtl/IntTypes.h [new file with mode: 0644]
glucose-syrup/mtl/Map.h [new file with mode: 0644]
glucose-syrup/mtl/Queue.h [new file with mode: 0644]
glucose-syrup/mtl/Sort.h [new file with mode: 0644]
glucose-syrup/mtl/Vec.h [new file with mode: 0644]
glucose-syrup/mtl/XAlloc.h [new file with mode: 0644]
glucose-syrup/mtl/config.mk [new file with mode: 0644]
glucose-syrup/mtl/template.mk [new file with mode: 0644]
glucose-syrup/parallel/ClausesBuffer.cc [new file with mode: 0644]
glucose-syrup/parallel/ClausesBuffer.h [new file with mode: 0644]
glucose-syrup/parallel/Main.cc [new file with mode: 0644]
glucose-syrup/parallel/Makefile [new file with mode: 0644]
glucose-syrup/parallel/MultiSolvers.cc [new file with mode: 0644]
glucose-syrup/parallel/MultiSolvers.h [new file with mode: 0644]
glucose-syrup/parallel/ParallelSolver.cc [new file with mode: 0644]
glucose-syrup/parallel/ParallelSolver.h [new file with mode: 0644]
glucose-syrup/parallel/SharedCompanion.cc [new file with mode: 0644]
glucose-syrup/parallel/SharedCompanion.h [new file with mode: 0644]
glucose-syrup/parallel/SolverCompanion.cc [new file with mode: 0644]
glucose-syrup/parallel/SolverCompanion.h [new file with mode: 0644]
glucose-syrup/parallel/SolverConfiguration.cc [new file with mode: 0644]
glucose-syrup/parallel/SolverConfiguration.h [new file with mode: 0644]
glucose-syrup/simp/Main.cc [new file with mode: 0644]
glucose-syrup/simp/Makefile [new file with mode: 0644]
glucose-syrup/simp/SimpSolver.cc [new file with mode: 0644]
glucose-syrup/simp/SimpSolver.h [new file with mode: 0644]
glucose-syrup/utils/Makefile [new file with mode: 0644]
glucose-syrup/utils/Options.cc [new file with mode: 0644]
glucose-syrup/utils/Options.h [new file with mode: 0644]
glucose-syrup/utils/ParseUtils.h [new file with mode: 0644]
glucose-syrup/utils/System.cc [new file with mode: 0644]
glucose-syrup/utils/System.h [new file with mode: 0644]
lingeling/build.sh [new file with mode: 0755]
lingeling/code/COPYING [new file with mode: 0644]
lingeling/code/VERSION [new file with mode: 0644]
lingeling/code/configure.sh [new file with mode: 0755]
lingeling/code/lglbnr.c [new file with mode: 0644]
lingeling/code/lgldimacs.c [new file with mode: 0644]
lingeling/code/lgldimacs.h [new file with mode: 0644]
lingeling/code/lglib.c [new file with mode: 0644]
lingeling/code/lglib.h [new file with mode: 0644]
lingeling/code/lglmain.c [new file with mode: 0644]
lingeling/code/makefile.in [new file with mode: 0644]
lingeling/code/mkconfig.sh [new file with mode: 0755]
lingeling/license.txt [new file with mode: 0644]
lingeling/readme.txt [new file with mode: 0644]
zchaff64/Makefile [new file with mode: 0644]
zchaff64/README [new file with mode: 0644]
zchaff64/SAT.h [new file with mode: 0644]
zchaff64/cnf_stats.cpp [new file with mode: 0644]
zchaff64/run_till_fix.pl [new file with mode: 0755]
zchaff64/sat_solver.cpp [new file with mode: 0644]
zchaff64/zchaff_base.cpp [new file with mode: 0644]
zchaff64/zchaff_base.h [new file with mode: 0644]
zchaff64/zchaff_clsgen.h [new file with mode: 0644]
zchaff64/zchaff_dbase.cpp [new file with mode: 0644]
zchaff64/zchaff_dbase.h [new file with mode: 0644]
zchaff64/zchaff_header.h [new file with mode: 0644]
zchaff64/zchaff_solver.cpp [new file with mode: 0644]
zchaff64/zchaff_solver.h [new file with mode: 0644]
zchaff64/zchaff_utils.cpp [new file with mode: 0644]
zchaff64/zchaff_version.h [new file with mode: 0644]
zchaff64/zchaff_wrapper.wrp [new file with mode: 0644]
zchaff64/zminimal.cpp [new file with mode: 0644]
zchaff64/zverify_df.cpp [new file with mode: 0644]

diff --git a/glucose-syrup/Changelog b/glucose-syrup/Changelog
new file mode 100644 (file)
index 0000000..b894c73
--- /dev/null
@@ -0,0 +1,27 @@
+Version 4.0
+ - Add a Multithread version, called syrup (many glucose ;-)
+   See SAT14 paper: Lazy Clause Exchange Policy for parallel SAT solvers.
+
+ - Can work indepentently in sequential or with many cores
+
+Version 3.0 (2013)
+ - Add incremental features. 
+    See SAT13 paper: Improving Glucose for Incremental SAT Solving with Assumptions: Application to MUS Extraction
+
+ - Add certified UNSAT proof.
+
+Version 2.3 (2012)
+ - Add new restart strategy 
+    See CP12 paper: Refining Restarts Strategies For SAT and UNSAT
+
+ - Add additionnal features to speed the search
+
+Version 2.0 (2011) 
+ - Add additionnal features (freeze potential good clauses for one turn)
+
+ - Based on Minisat 2.2
+
+Version 1.0 (2009)
+ - Based on Minisat 2.0
+    First release of glucose.
+    See ijcai 2009 paper: Predicting Learnt Clauses Quality in Modern SAT Solver
\ No newline at end of file
diff --git a/glucose-syrup/LICENCE b/glucose-syrup/LICENCE
new file mode 100644 (file)
index 0000000..6fa3b63
--- /dev/null
@@ -0,0 +1,47 @@
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/glucose-syrup/README b/glucose-syrup/README
new file mode 100644 (file)
index 0000000..19cd95f
--- /dev/null
@@ -0,0 +1,24 @@
+Directory overview:
+==================
+
+mtl/            Minisat Template Library
+core/           A core version of the solver glucose (no main here)
+simp/           An extended solver with simplification capabilities
+parallel/       A multicore version of glucose
+README
+LICENSE
+Changelog
+
+To build (release version: without assertions, statically linked, etc):
+======================================================================
+Like minisat....
+
+cd { simp | parallel }
+make rs
+
+Usage:
+======
+
+in simp directory:      ./glucose --help
+
+in parallel directory:  ./glucose-syrup --help
\ No newline at end of file
diff --git a/glucose-syrup/core/BoundedQueue.h b/glucose-syrup/core/BoundedQueue.h
new file mode 100644 (file)
index 0000000..5269c9b
--- /dev/null
@@ -0,0 +1,148 @@
+/***************************************************************************************[BoundedQueue.h]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+
+#ifndef BoundedQueue_h
+#define BoundedQueue_h
+
+#include "mtl/Vec.h"
+
+//=================================================================================================
+
+namespace Glucose {
+
+template <class T>
+class bqueue {
+    vec<T>  elems;
+    int     first;
+       int             last;
+       unsigned long long sumofqueue;
+       int     maxsize;
+       int     queuesize; // Number of current elements (must be < maxsize !)
+       bool expComputed;
+       double exp,value;
+public:
+ bqueue(void) : first(0), last(0), sumofqueue(0), maxsize(0), queuesize(0),expComputed(false) { } 
+       
+       void initSize(int size) {growTo(size);exp = 2.0/(size+1);} // Init size of bounded size queue
+       
+       void push(T x) {
+         expComputed = false;
+               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;last = 0;}
+       }
+
+       T peek() { assert(queuesize>0); return elems[last]; }
+       void pop() {sumofqueue-=elems[last]; queuesize--; if ((++last) == maxsize) last = 0;}
+       
+       unsigned long long getsum() const {return sumofqueue;}
+       unsigned int getavg() const {return (unsigned int)(sumofqueue/((unsigned long long)queuesize));}
+       int maxSize() const {return maxsize;}
+       double getavgDouble() const {
+         double tmp = 0;
+         for(int i=0;i<elems.size();i++) {
+           tmp+=elems[i];
+         }
+         return tmp/elems.size();
+       }
+       int isvalid() const {return (queuesize==maxsize);}
+       
+       void growTo(int size) {
+               elems.growTo(size); 
+               first=0; maxsize=size; queuesize = 0;last = 0;
+               for(int i=0;i<size;i++) elems[i]=0; 
+       }
+       
+       double getAvgExp() {
+         if(expComputed) return value;
+         double a=exp;
+         value = elems[first];
+         for(int i  = first;i<maxsize;i++) {
+           value+=a*((double)elems[i]);
+           a=a*exp;
+         }
+         for(int i  = 0;i<last;i++) {
+           value+=a*((double)elems[i]);
+           a=a*exp;
+         }
+         value = value*(1-exp)/(1-a);
+         expComputed = true;
+         return value;
+         
+
+       }
+       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;}
+
+    void copyTo(bqueue &dest) const {
+        dest.last = last;
+        dest.sumofqueue = sumofqueue;
+        dest.maxsize = maxsize;
+        dest.queuesize = queuesize;
+        dest.expComputed = expComputed;
+        dest.exp = exp;
+        dest.value = value;
+        dest.first = first;        
+        elems.copyTo(dest.elems);
+    }
+};
+}
+//=================================================================================================
+
+#endif
diff --git a/glucose-syrup/core/Constants.h b/glucose-syrup/core/Constants.h
new file mode 100644 (file)
index 0000000..259f1b3
--- /dev/null
@@ -0,0 +1,59 @@
+/***************************************************************************************[Constants.h]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+#define DYNAMICNBLEVEL
+#define CONSTANTREMOVECLAUSE
+
+// Constants for clauses reductions
+#define RATIOREMOVECLAUSES 2
+
+
+// Constants for restarts
+#define LOWER_BOUND_FOR_BLOCKING_RESTART 10000
+
diff --git a/glucose-syrup/core/Dimacs.h b/glucose-syrup/core/Dimacs.h
new file mode 100644 (file)
index 0000000..a2065f6
--- /dev/null
@@ -0,0 +1,89 @@
+/****************************************************************************************[Dimacs.h]
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef Glucose_Dimacs_h
+#define Glucose_Dimacs_h
+
+#include <stdio.h>
+
+#include "utils/ParseUtils.h"
+#include "core/SolverTypes.h"
+
+namespace Glucose {
+
+//=================================================================================================
+// DIMACS Parser:
+
+template<class B, class Solver>
+static void readClause(B& in, Solver& S, vec<Lit>& lits) {
+    int     parsed_lit, var;
+    lits.clear();
+    for (;;){
+        parsed_lit = parseInt(in);
+        if (parsed_lit == 0) break;
+        var = abs(parsed_lit)-1;
+        while (var >= S.nVars()) S.newVar();
+        lits.push( (parsed_lit > 0) ? mkLit(var) : ~mkLit(var) );
+    }
+}
+
+template<class B, class Solver>
+static void parse_DIMACS_main(B& in, Solver& S) {
+    vec<Lit> lits;
+    int vars    = 0;
+    int clauses = 0;
+    int cnt     = 0;
+    for (;;){
+        skipWhitespace(in);
+        if (*in == EOF) break;
+        else if (*in == 'p'){
+            if (eagerMatch(in, "p cnf")){
+                vars    = parseInt(in);
+                clauses = parseInt(in);
+                // SATRACE'06 hack
+                // if (clauses > 4000000)
+                //     S.eliminate(true);
+            }else{
+                printf("PARSE ERROR! Unexpected char: %c\n", *in), exit(3);
+            }
+        } else if (*in == 'c' || *in == 'p')
+            skipLine(in);
+        else{
+            cnt++;
+            readClause(in, S, lits);
+            S.addClause_(lits); }
+    }
+    if (vars != S.nVars())
+        fprintf(stderr, "WARNING! DIMACS header mismatch: wrong number of variables.\n");
+    if (cnt  != clauses)
+        fprintf(stderr, "WARNING! DIMACS header mismatch: wrong number of clauses.\n");
+}
+
+// Inserts problem into solver.
+//
+template<class Solver>
+static void parse_DIMACS(gzFile input_stream, Solver& S) {
+    StreamBuffer in(input_stream);
+    parse_DIMACS_main(in, S); }
+
+//=================================================================================================
+}
+
+#endif
diff --git a/glucose-syrup/core/Makefile b/glucose-syrup/core/Makefile
new file mode 100644 (file)
index 0000000..14c4e9c
--- /dev/null
@@ -0,0 +1,3 @@
+PHONY:
+       @echo "** Careful ** Since 4.0 you have to use the simp or parallel directory only for typing make"
+
diff --git a/glucose-syrup/core/Solver.cc b/glucose-syrup/core/Solver.cc
new file mode 100644 (file)
index 0000000..8346438
--- /dev/null
@@ -0,0 +1,1708 @@
+/***************************************************************************************[Solver.cc]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+#include <math.h>
+
+#include "utils/System.h"
+#include "mtl/Sort.h"
+#include "core/Solver.h"
+#include "core/Constants.h"
+
+using namespace Glucose;
+
+//=================================================================================================
+// Options:
+
+static const char* _cat = "CORE";
+static const char* _cr = "CORE -- RESTART";
+static const char* _cred = "CORE -- REDUCE";
+static const char* _cm = "CORE -- MINIMIZE";
+
+
+
+
+static DoubleOption opt_K(_cr, "K", "The constant used to force restart", 0.8, DoubleRange(0, false, 1, false));
+static DoubleOption opt_R(_cr, "R", "The constant used to block restart", 1.4, DoubleRange(1, false, 5, false));
+static IntOption opt_size_lbd_queue(_cr, "szLBDQueue", "The size of moving average for LBD (restarts)", 50, IntRange(10, INT32_MAX));
+static IntOption opt_size_trail_queue(_cr, "szTrailQueue", "The size of moving average for trail (block restarts)", 5000, IntRange(10, INT32_MAX));
+
+static IntOption opt_first_reduce_db(_cred, "firstReduceDB", "The number of conflicts before the first reduce DB", 2000, IntRange(0, INT32_MAX));
+static IntOption opt_inc_reduce_db(_cred, "incReduceDB", "Increment for reduce DB", 300, IntRange(0, INT32_MAX));
+static IntOption opt_spec_inc_reduce_db(_cred, "specialIncReduceDB", "Special increment for reduce DB", 1000, IntRange(0, INT32_MAX));
+static IntOption opt_lb_lbd_frozen_clause(_cred, "minLBDFrozenClause", "Protect clauses if their LBD decrease and is lower than (for one turn)", 30, IntRange(0, INT32_MAX));
+
+static IntOption opt_lb_size_minimzing_clause(_cm, "minSizeMinimizingClause", "The min size required to minimize clause", 30, IntRange(3, INT32_MAX));
+static IntOption opt_lb_lbd_minimzing_clause(_cm, "minLBDMinimizingClause", "The min LBD required to minimize clause", 6, IntRange(3, INT32_MAX));
+
+
+static DoubleOption opt_var_decay(_cat, "var-decay", "The variable activity decay factor (starting point)", 0.8, DoubleRange(0, false, 1, false));
+static DoubleOption opt_max_var_decay(_cat, "max-var-decay", "The variable activity decay factor", 0.95, DoubleRange(0, false, 1, false));
+static DoubleOption opt_clause_decay(_cat, "cla-decay", "The clause activity decay factor", 0.999, DoubleRange(0, false, 1, false));
+static DoubleOption opt_random_var_freq(_cat, "rnd-freq", "The frequency with which the decision heuristic tries to choose a random variable", 0, DoubleRange(0, true, 1, true));
+static DoubleOption opt_random_seed(_cat, "rnd-seed", "Used by the random variable selection", 91648253, DoubleRange(0, false, HUGE_VAL, false));
+static IntOption opt_ccmin_mode(_cat, "ccmin-mode", "Controls conflict clause minimization (0=none, 1=basic, 2=deep)", 2, IntRange(0, 2));
+static IntOption opt_phase_saving(_cat, "phase-saving", "Controls the level of phase saving (0=none, 1=limited, 2=full)", 2, IntRange(0, 2));
+static BoolOption opt_rnd_init_act(_cat, "rnd-init", "Randomize the initial activity", false);
+static DoubleOption opt_garbage_frac(_cat, "gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered", 0.20, DoubleRange(0, false, HUGE_VAL, false));
+
+
+//=================================================================================================
+// Constructor/Destructor:
+
+Solver::Solver() :
+
+// Parameters (user settable):
+//
+verbosity(0)
+, showModel(0)
+, K(opt_K)
+, R(opt_R)
+, sizeLBDQueue(opt_size_lbd_queue)
+, sizeTrailQueue(opt_size_trail_queue)
+, firstReduceDB(opt_first_reduce_db)
+, incReduceDB(opt_inc_reduce_db)
+, specialIncReduceDB(opt_spec_inc_reduce_db)
+, lbLBDFrozenClause(opt_lb_lbd_frozen_clause)
+, lbSizeMinimizingClause(opt_lb_size_minimzing_clause)
+, lbLBDMinimizingClause(opt_lb_lbd_minimzing_clause)
+, var_decay(opt_var_decay)
+, max_var_decay(opt_max_var_decay)
+, clause_decay(opt_clause_decay)
+, random_var_freq(opt_random_var_freq)
+, random_seed(opt_random_seed)
+, ccmin_mode(opt_ccmin_mode)
+, phase_saving(opt_phase_saving)
+, rnd_pol(false)
+, rnd_init_act(opt_rnd_init_act)
+, garbage_frac(opt_garbage_frac)
+, certifiedOutput(NULL)
+, certifiedUNSAT(false) // Not in the first parallel version 
+, panicModeLastRemoved(0), panicModeLastRemovedShared(0)
+, useUnaryWatched(false)
+, promoteOneWatchedClause(true)
+// Statistics: (formerly in 'SolverStats')
+//
+, nbPromoted(0)
+, originalClausesSeen(0)
+, sumDecisionLevels(0)
+, nbRemovedClauses(0), nbRemovedUnaryWatchedClauses(0), nbReducedClauses(0), nbDL2(0), nbBin(0), nbUn(0), nbReduceDB(0)
+, solves(0), starts(0), decisions(0), rnd_decisions(0), propagations(0), conflicts(0), conflictsRestarts(0)
+, nbstopsrestarts(0), nbstopsrestartssame(0), lastblockatrestart(0)
+, dec_vars(0), clauses_literals(0), learnts_literals(0), max_literals(0), tot_literals(0)
+, curRestart(1)
+
+, ok(true)
+, cla_inc(1)
+, var_inc(1)
+, watches(WatcherDeleted(ca))
+, watchesBin(WatcherDeleted(ca))
+, unaryWatches(WatcherDeleted(ca))
+, qhead(0)
+, simpDB_assigns(-1)
+, simpDB_props(0)
+, order_heap(VarOrderLt(activity))
+, progress_estimate(0)
+, remove_satisfied(true)
+, reduceOnSize(false) // 
+, reduceOnSizeSize(12) // Constant to use on size reductions
+,lastLearntClause(CRef_Undef)
+// Resource constraints:
+//
+, conflict_budget(-1)
+, propagation_budget(-1)
+, asynch_interrupt(false)
+, incremental(false)
+, nbVarsInitialFormula(INT32_MAX)
+, totalTime4Sat(0.)
+, totalTime4Unsat(0.)
+, nbSatCalls(0)
+, nbUnsatCalls(0)
+{
+    MYFLAG = 0;
+    // Initialize only first time. Useful for incremental solving (not in // version), useless otherwise
+    // Kept here for simplicity
+    lbdQueue.initSize(sizeLBDQueue);
+    trailQueue.initSize(sizeTrailQueue);
+    sumLBD = 0;
+    nbclausesbeforereduce = firstReduceDB;
+}
+
+//-------------------------------------------------------
+// Special constructor used for cloning solvers
+//-------------------------------------------------------
+
+Solver::Solver(const Solver &s) :
+  verbosity(s.verbosity)
+, showModel(s.showModel)
+, K(s.K)
+, R(s.R)
+, sizeLBDQueue(s.sizeLBDQueue)
+, sizeTrailQueue(s.sizeTrailQueue)
+, firstReduceDB(s.firstReduceDB)
+, incReduceDB(s.incReduceDB)
+, specialIncReduceDB(s.specialIncReduceDB)
+, lbLBDFrozenClause(s.lbLBDFrozenClause)
+, lbSizeMinimizingClause(s.lbSizeMinimizingClause)
+, lbLBDMinimizingClause(s.lbLBDMinimizingClause)
+, var_decay(s.var_decay)
+, max_var_decay(s.max_var_decay)
+, clause_decay(s.clause_decay)
+, random_var_freq(s.random_var_freq)
+, random_seed(s.random_seed)
+, ccmin_mode(s.ccmin_mode)
+, phase_saving(s.phase_saving)
+, rnd_pol(s.rnd_pol)
+, rnd_init_act(s.rnd_init_act)
+, garbage_frac(s.garbage_frac)
+, certifiedOutput(NULL)
+, certifiedUNSAT(false) // Not in the first parallel version 
+, panicModeLastRemoved(s.panicModeLastRemoved), panicModeLastRemovedShared(s.panicModeLastRemovedShared)
+, useUnaryWatched(s.useUnaryWatched)
+, promoteOneWatchedClause(s.promoteOneWatchedClause)
+// Statistics: (formerly in 'SolverStats')
+//
+, nbPromoted(s.nbPromoted)
+, originalClausesSeen(s.originalClausesSeen)
+, sumDecisionLevels(s.sumDecisionLevels)
+, nbRemovedClauses(s.nbRemovedClauses), nbRemovedUnaryWatchedClauses(s.nbRemovedUnaryWatchedClauses)
+, nbReducedClauses(s.nbReducedClauses), nbDL2(s.nbDL2), nbBin(s.nbBin), nbUn(s.nbUn), nbReduceDB(s.nbReduceDB)
+, solves(s.solves), starts(s.starts), decisions(s.decisions), rnd_decisions(s.rnd_decisions)
+, propagations(s.propagations), conflicts(s.conflicts), conflictsRestarts(s.conflictsRestarts)
+, nbstopsrestarts(s.nbstopsrestarts), nbstopsrestartssame(s.nbstopsrestartssame)
+, lastblockatrestart(s.lastblockatrestart)
+, dec_vars(s.dec_vars), clauses_literals(s.clauses_literals)
+, learnts_literals(s.learnts_literals), max_literals(s.max_literals), tot_literals(s.tot_literals)
+, curRestart(s.curRestart)
+
+, ok(true)
+, cla_inc(s.cla_inc)
+, var_inc(s.var_inc)
+, watches(WatcherDeleted(ca))
+, watchesBin(WatcherDeleted(ca))
+, unaryWatches(WatcherDeleted(ca))
+, qhead(s.qhead)
+, simpDB_assigns(s.simpDB_assigns)
+, simpDB_props(s.simpDB_props)
+, order_heap(VarOrderLt(activity))
+, progress_estimate(s.progress_estimate)
+, remove_satisfied(s.remove_satisfied)
+, reduceOnSize(s.reduceOnSize) // 
+, reduceOnSizeSize(s.reduceOnSizeSize) // Constant to use on size reductions
+,lastLearntClause(CRef_Undef)
+// Resource constraints:
+//
+, conflict_budget(s.conflict_budget)
+, propagation_budget(s.propagation_budget)
+, asynch_interrupt(s.asynch_interrupt)
+, incremental(s.incremental)
+, nbVarsInitialFormula(s.nbVarsInitialFormula)
+, totalTime4Sat(s.totalTime4Sat)
+, totalTime4Unsat(s.totalTime4Unsat)
+, nbSatCalls(s.nbSatCalls)
+, nbUnsatCalls(s.nbUnsatCalls)
+{
+    // Copy clauses.
+    s.ca.copyTo(ca);
+    ca.extra_clause_field = s.ca.extra_clause_field;
+
+    // Initialize  other variables
+     MYFLAG = 0;
+    // Initialize only first time. Useful for incremental solving (not in // version), useless otherwise
+    // Kept here for simplicity
+    sumLBD = s.sumLBD;
+    nbclausesbeforereduce = s.nbclausesbeforereduce;
+   
+    // Copy all search vectors
+    s.watches.copyTo(watches);
+    s.watchesBin.copyTo(watchesBin);
+    s.unaryWatches.copyTo(unaryWatches);
+    s.assigns.memCopyTo(assigns);
+    s.vardata.memCopyTo(vardata);
+    s.activity.memCopyTo(activity);
+    s.seen.memCopyTo(seen);
+    s.permDiff.memCopyTo(permDiff);
+    s.polarity.memCopyTo(polarity);
+    s.decision.memCopyTo(decision);
+    s.trail.memCopyTo(trail);
+    s.order_heap.copyTo(order_heap);
+    s.clauses.memCopyTo(clauses);
+    s.learnts.memCopyTo(learnts);
+
+    s.lbdQueue.copyTo(lbdQueue);
+    s.trailQueue.copyTo(trailQueue);
+
+}
+
+Solver::~Solver() {
+}
+
+/****************************************************************
+ Set the incremental mode
+****************************************************************/
+
+// This function set the incremental mode to true.
+// You can add special code for this mode here.
+
+void Solver::setIncrementalMode() {
+  incremental = true;
+}
+
+// Number of variables without selectors
+void Solver::initNbInitialVars(int nb) {
+  nbVarsInitialFormula = nb;
+}
+
+bool Solver::isIncremental() {
+  return incremental;
+}
+
+
+//=================================================================================================
+// Minor methods:
+
+
+// Creates a new SAT variable in the solver. If 'decision' is cleared, variable will not be
+// used as a decision variable (NOTE! This has effects on the meaning of a SATISFIABLE result).
+//
+
+Var Solver::newVar(bool sign, bool dvar) {
+    int v = nVars();
+    watches .init(mkLit(v, false));
+    watches .init(mkLit(v, true));
+    watchesBin .init(mkLit(v, false));
+    watchesBin .init(mkLit(v, true));
+    unaryWatches .init(mkLit(v, false));
+    unaryWatches .init(mkLit(v, true));
+    assigns .push(l_Undef);
+    vardata .push(mkVarData(CRef_Undef, 0));
+    activity .push(rnd_init_act ? drand(random_seed) * 0.00001 : 0);
+    seen .push(0);
+    permDiff .push(0);
+    polarity .push(sign);
+    decision .push();
+    trail .capacity(v + 1);
+    setDecisionVar(v, dvar);
+    return v;
+}
+
+bool Solver::addClause_(vec<Lit>& ps) {
+
+    assert(decisionLevel() == 0);
+    if (!ok) return false;
+
+    // Check if clause is satisfied and remove false/duplicate literals:
+    sort(ps);
+
+    vec<Lit> oc;
+    oc.clear();
+
+    Lit p;
+    int i, j, flag = 0;
+    if (certifiedUNSAT) {
+        for (i = j = 0, p = lit_Undef; i < ps.size(); i++) {
+            oc.push(ps[i]);
+            if (value(ps[i]) == l_True || ps[i] == ~p || value(ps[i]) == l_False)
+                flag = 1;
+        }
+    }
+
+    for (i = j = 0, p = lit_Undef; i < ps.size(); i++)
+        if (value(ps[i]) == l_True || ps[i] == ~p)
+            return true;
+        else if (value(ps[i]) != l_False && ps[i] != p)
+            ps[j++] = p = ps[i];
+    ps.shrink(i - j);
+
+    if (flag && (certifiedUNSAT)) {
+        for (i = j = 0, p = lit_Undef; i < ps.size(); i++)
+            fprintf(certifiedOutput, "%i ", (var(ps[i]) + 1) * (-2 * sign(ps[i]) + 1));
+        fprintf(certifiedOutput, "0\n");
+
+        fprintf(certifiedOutput, "d ");
+        for (i = j = 0, p = lit_Undef; i < oc.size(); i++)
+            fprintf(certifiedOutput, "%i ", (var(oc[i]) + 1) * (-2 * sign(oc[i]) + 1));
+        fprintf(certifiedOutput, "0\n");
+    }
+
+
+    if (ps.size() == 0)
+        return ok = false;
+    else if (ps.size() == 1) {
+        uncheckedEnqueue(ps[0]);
+        return ok = (propagate() == CRef_Undef);
+    } else {
+        CRef cr = ca.alloc(ps, false);
+        clauses.push(cr);
+        attachClause(cr);
+    }
+
+    return true;
+}
+
+void Solver::attachClause(CRef cr) {
+    const Clause& c = ca[cr];
+
+    assert(c.size() > 1);
+    if (c.size() == 2) {
+        watchesBin[~c[0]].push(Watcher(cr, c[1]));
+        watchesBin[~c[1]].push(Watcher(cr, c[0]));
+    } else {
+        watches[~c[0]].push(Watcher(cr, c[1]));
+        watches[~c[1]].push(Watcher(cr, c[0]));
+    }
+    if (c.learnt()) learnts_literals += c.size();
+    else clauses_literals += c.size();
+}
+
+void Solver::attachClausePurgatory(CRef cr) {
+    const Clause& c = ca[cr];
+
+    assert(c.size() > 1);
+    unaryWatches[~c[0]].push(Watcher(cr, c[1]));
+
+}
+
+void Solver::detachClause(CRef cr, bool strict) {
+    const Clause& c = ca[cr];
+
+    assert(c.size() > 1);
+    if (c.size() == 2) {
+        if (strict) {
+            remove(watchesBin[~c[0]], Watcher(cr, c[1]));
+            remove(watchesBin[~c[1]], Watcher(cr, c[0]));
+        } else {
+            // Lazy detaching: (NOTE! Must clean all watcher lists before garbage collecting this clause)
+            watchesBin.smudge(~c[0]);
+            watchesBin.smudge(~c[1]);
+        }
+    } else {
+        if (strict) {
+            remove(watches[~c[0]], Watcher(cr, c[1]));
+            remove(watches[~c[1]], Watcher(cr, c[0]));
+        } else {
+            // Lazy detaching: (NOTE! Must clean all watcher lists before garbage collecting this clause)
+            watches.smudge(~c[0]);
+            watches.smudge(~c[1]);
+        }
+    }
+    if (c.learnt()) learnts_literals -= c.size();
+    else clauses_literals -= c.size();
+}
+
+
+// The purgatory is the 1-Watched scheme for imported clauses
+
+void Solver::detachClausePurgatory(CRef cr, bool strict) {
+    const Clause& c = ca[cr];
+
+    assert(c.size() > 1);
+    if (strict)
+        remove(unaryWatches[~c[0]], Watcher(cr, c[1]));
+    else
+        unaryWatches.smudge(~c[0]);
+}
+
+void Solver::removeClause(CRef cr, bool inPurgatory) {
+
+    Clause& c = ca[cr];
+
+    if (certifiedUNSAT) {
+        fprintf(certifiedOutput, "d ");
+        for (int i = 0; i < c.size(); i++)
+            fprintf(certifiedOutput, "%i ", (var(c[i]) + 1) * (-2 * sign(c[i]) + 1));
+        fprintf(certifiedOutput, "0\n");
+    }
+
+    if (inPurgatory)
+        detachClausePurgatory(cr);
+    else
+        detachClause(cr);
+    // Don't leave pointers to free'd memory!
+    if (locked(c)) vardata[var(c[0])].reason = CRef_Undef;
+    c.mark(1);
+    ca.free(cr);
+}
+
+bool Solver::satisfied(const Clause& c) const {
+    if(incremental)     
+        return (value(c[0]) == l_True) || (value(c[1]) == l_True);
+    
+    // Default mode
+    for (int i = 0; i < c.size(); i++)
+        if (value(c[i]) == l_True)
+            return true;
+    return false;
+}
+
+/************************************************************
+ * Compute LBD functions
+ *************************************************************/
+
+inline unsigned int Solver::computeLBD(const vec<Lit> & lits,int end) {
+  int nblevels = 0;
+  MYFLAG++;
+
+  if(incremental) { // ----------------- INCREMENTAL MODE
+    if(end==-1) end = lits.size();
+    int nbDone = 0;
+    for(int i=0;i<lits.size();i++) {
+      if(nbDone>=end) break;
+      if(isSelector(var(lits[i]))) continue;
+      nbDone++;
+      int l = level(var(lits[i]));
+      if (permDiff[l] != MYFLAG) {
+       permDiff[l] = MYFLAG;
+       nblevels++;
+      }
+    }
+  } else { // -------- DEFAULT MODE. NOT A LOT OF DIFFERENCES... BUT EASIER TO READ
+    for(int i=0;i<lits.size();i++) {
+      int l = level(var(lits[i]));
+      if (permDiff[l] != MYFLAG) {
+       permDiff[l] = MYFLAG;
+       nblevels++;
+      }
+    }
+  }
+
+  if (!reduceOnSize)
+    return nblevels;
+  if (lits.size() < reduceOnSizeSize) return lits.size(); // See the XMinisat paper
+    return lits.size() + nblevels;
+}
+
+inline unsigned int Solver::computeLBD(const Clause &c) {
+  int nblevels = 0;
+  MYFLAG++;
+
+  if(incremental) { // ----------------- INCREMENTAL MODE
+     unsigned int nbDone = 0;
+    for(int i=0;i<c.size();i++) {
+      if(nbDone>=c.sizeWithoutSelectors()) break;
+      if(isSelector(var(c[i]))) continue;
+      nbDone++;
+      int l = level(var(c[i]));
+      if (permDiff[l] != MYFLAG) {
+       permDiff[l] = MYFLAG;
+       nblevels++;
+      }
+    }
+  } else { // -------- DEFAULT MODE. NOT A LOT OF DIFFERENCES... BUT EASIER TO READ
+    for(int i=0;i<c.size();i++) {
+      int l = level(var(c[i]));
+      if (permDiff[l] != MYFLAG) {
+       permDiff[l] = MYFLAG;
+       nblevels++;
+      }
+    }
+  }
+  
+  if (!reduceOnSize)
+    return nblevels;
+  if (c.size() < reduceOnSizeSize) return c.size(); // See the XMinisat paper
+    return c.size() + nblevels;
+
+}
+
+/******************************************************************
+ * Minimisation with binary reolution
+ ******************************************************************/
+void Solver::minimisationWithBinaryResolution(vec<Lit> &out_learnt) {
+
+    // Find the LBD measure                                                                                                         
+    unsigned int lbd = computeLBD(out_learnt);
+    Lit p = ~out_learnt[0];
+
+    if (lbd <= lbLBDMinimizingClause) {
+        MYFLAG++;
+
+        for (int i = 1; i < out_learnt.size(); i++) {
+            permDiff[var(out_learnt[i])] = MYFLAG;
+        }
+
+        vec<Watcher>& wbin = watchesBin[p];
+        int nb = 0;
+        for (int k = 0; k < wbin.size(); k++) {
+            Lit imp = wbin[k].blocker;
+            if (permDiff[var(imp)] == MYFLAG && value(imp) == l_True) {
+                nb++;
+                permDiff[var(imp)] = MYFLAG - 1;
+            }
+        }
+        int l = out_learnt.size() - 1;
+        if (nb > 0) {
+            nbReducedClauses++;
+            for (int i = 1; i < out_learnt.size() - nb; i++) {
+                if (permDiff[var(out_learnt[i])] != MYFLAG) {
+                    Lit p = out_learnt[l];
+                    out_learnt[l] = out_learnt[i];
+                    out_learnt[i] = p;
+                    l--;
+                    i--;
+                }
+            }
+
+            out_learnt.shrink(nb);
+
+        }
+    }
+}
+
+// Revert to the state at given level (keeping all assignment at 'level' but not beyond).
+//
+
+void Solver::cancelUntil(int level) {
+    if (decisionLevel() > level) {
+        for (int c = trail.size() - 1; c >= trail_lim[level]; c--) {
+            Var x = var(trail[c]);
+            assigns [x] = l_Undef;
+            if (phase_saving > 1 || ((phase_saving == 1) && c > trail_lim.last())) {
+                polarity[x] = sign(trail[c]);
+            }
+            insertVarOrder(x);
+        }
+        qhead = trail_lim[level];
+        trail.shrink(trail.size() - trail_lim[level]);
+        trail_lim.shrink(trail_lim.size() - level);
+    }
+}
+
+
+//=================================================================================================
+// Major methods:
+
+Lit Solver::pickBranchLit() {
+    Var next = var_Undef;
+
+    // Random decision:
+    if (drand(random_seed) < random_var_freq && !order_heap.empty()) {
+        next = order_heap[irand(random_seed, order_heap.size())];
+        if (value(next) == l_Undef && decision[next])
+            rnd_decisions++;
+    }
+
+    // Activity based decision:
+    while (next == var_Undef || value(next) != l_Undef || !decision[next])
+        if (order_heap.empty()) {
+            next = var_Undef;
+            break;
+        } else {
+            next = order_heap.removeMin();
+        }
+
+    return next == var_Undef ? lit_Undef : mkLit(next, rnd_pol ? drand(random_seed) < 0.5 : polarity[next]);
+}
+
+/*_________________________________________________________________________________________________
+|
+|  analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&)  ->  [void]
+|  
+|  Description:
+|    Analyze conflict and produce a reason clause.
+|  
+|    Pre-conditions:
+|      * 'out_learnt' is assumed to be cleared.
+|      * Current decision level must be greater than root level.
+|  
+|    Post-conditions:
+|      * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'.
+|      * If out_learnt.size() > 1 then 'out_learnt[1]' has the greatest decision level of the 
+|        rest of literals. There may be others from the same level though.
+|  
+|________________________________________________________________________________________________@*/
+void Solver::analyze(CRef confl, vec<Lit>& out_learnt,vec<Lit>&selectors, int& out_btlevel,unsigned int &lbd,unsigned int &szWithoutSelectors) {
+    int pathC = 0;
+    Lit p = lit_Undef;
+
+
+    // Generate conflict clause:
+    //
+    out_learnt.push(); // (leave room for the asserting literal)
+    int index = trail.size() - 1;
+    do {
+        assert(confl != CRef_Undef); // (otherwise should be UIP)
+        Clause& c = ca[confl];
+        // Special case for binary clauses
+        // The first one has to be SAT
+        if (p != lit_Undef && 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;
+        }
+
+        if (c.learnt()) {
+            parallelImportClauseDuringConflictAnalysis(c,confl);
+            claBumpActivity(c);
+         } else { // original clause
+            if (!c.getSeen()) {
+                originalClausesSeen++;
+                c.setSeen(true);
+            }
+        }
+
+        // DYNAMIC NBLEVEL trick (see competition'09 companion paper)
+        if (c.learnt() && c.lbd() > 2) {
+            unsigned int nblevels = computeLBD(c);
+            if (nblevels + 1 < c.lbd()) { // improve the LBD
+                if (c.lbd() <= lbLBDFrozenClause) {
+                    c.setCanBeDel(false);
+                }
+                // seems to be interesting : keep it for the next round
+                c.setLBD(nblevels); // Update it
+            }
+        }
+
+
+        for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++) {
+            Lit q = c[j];
+
+            if (!seen[var(q)]) {
+                if (level(var(q)) == 0) {
+                } else { // Here, the old case 
+                    if(!isSelector(var(q)))
+                        varBumpActivity(var(q));
+                    seen[var(q)] = 1;
+                    if (level(var(q)) >= decisionLevel()) {
+                        pathC++;
+                        // UPDATEVARACTIVITY trick (see competition'09 companion paper)
+                        if (!isSelector(var(q)) &&  (reason(var(q)) != CRef_Undef) && ca[reason(var(q))].learnt())
+                            lastDecisionLevel.push(q);
+                    } else {
+                        if(isSelector(var(q))) {
+                            assert(value(q) == l_False);
+                            selectors.push(q);
+                        } else 
+                            out_learnt.push(q);
+                   }
+                }
+            }
+        }
+
+        // Select next clause to look at:
+        while (!seen[var(trail[index--])]);
+        p = trail[index + 1];
+        confl = reason(var(p));
+        seen[var(p)] = 0;
+        pathC--;
+
+    } while (pathC > 0);
+    out_learnt[0] = ~p;
+
+    // Simplify conflict clause:
+    //
+    int i, j;
+
+    for (int i = 0; i < selectors.size(); i++)
+        out_learnt.push(selectors[i]);
+
+    out_learnt.copyTo(analyze_toclear);
+    if (ccmin_mode == 2) {
+        uint32_t abstract_level = 0;
+        for (i = 1; i < out_learnt.size(); i++)
+            abstract_level |= abstractLevel(var(out_learnt[i])); // (maintain an abstraction of levels involved in conflict)
+
+        for (i = j = 1; i < out_learnt.size(); i++)
+            if (reason(var(out_learnt[i])) == CRef_Undef || !litRedundant(out_learnt[i], abstract_level))
+                out_learnt[j++] = out_learnt[i];
+
+    } else if (ccmin_mode == 1) {
+        for (i = j = 1; i < out_learnt.size(); i++) {
+            Var x = var(out_learnt[i]);
+
+            if (reason(x) == CRef_Undef)
+                out_learnt[j++] = out_learnt[i];
+            else {
+                Clause& c = ca[reason(var(out_learnt[i]))];
+                // Thanks to Siert Wieringa for this bug fix!
+                for (int k = ((c.size() == 2) ? 0 : 1); k < c.size(); k++)
+                    if (!seen[var(c[k])] && level(var(c[k])) > 0) {
+                        out_learnt[j++] = out_learnt[i];
+                        break;
+                    }
+            }
+        }
+    } else
+        i = j = out_learnt.size();
+
+    max_literals += out_learnt.size();
+    out_learnt.shrink(i - j);
+    tot_literals += out_learnt.size();
+
+
+    /* ***************************************
+      Minimisation with binary clauses of the asserting clause
+      First of all : we look for small clauses
+      Then, we reduce clauses with small LBD.
+      Otherwise, this can be useless
+     */
+    if (!incremental && out_learnt.size() <= lbSizeMinimizingClause) {
+        minimisationWithBinaryResolution(out_learnt);
+    }
+    // Find correct backtrack level:
+    //
+    if (out_learnt.size() == 1)
+        out_btlevel = 0;
+    else {
+        int max_i = 1;
+        // Find the first literal assigned at the next-highest level:
+        for (int i = 2; i < out_learnt.size(); i++)
+            if (level(var(out_learnt[i])) > level(var(out_learnt[max_i])))
+                max_i = i;
+        // Swap-in this literal at index 1:
+        Lit p = out_learnt[max_i];
+        out_learnt[max_i] = out_learnt[1];
+        out_learnt[1] = p;
+        out_btlevel = level(var(p));
+    }
+   if(incremental) {
+      szWithoutSelectors = 0;
+      for(int i=0;i<out_learnt.size();i++) {
+       if(!isSelector(var((out_learnt[i])))) szWithoutSelectors++; 
+       else if(i>0) break;
+      }
+    } else 
+      szWithoutSelectors = out_learnt.size();
+    
+    // Compute LBD
+    lbd = computeLBD(out_learnt,out_learnt.size()-selectors.size());
+     
+    // UPDATEVARACTIVITY trick (see competition'09 companion paper)
+    if (lastDecisionLevel.size() > 0) {
+        for (int i = 0; i < lastDecisionLevel.size(); i++) {
+            if (ca[reason(var(lastDecisionLevel[i]))].lbd() < lbd)
+                varBumpActivity(var(lastDecisionLevel[i]));
+        }
+        lastDecisionLevel.clear();
+    }
+
+
+
+    for (int j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0; // ('seen[]' is now cleared)
+    for (int j = 0; j < selectors.size(); j++) seen[var(selectors[j])] = 0;
+}
+
+
+// Check if 'p' can be removed. 'abstract_levels' is used to abort early if the algorithm is
+// visiting literals at levels that cannot be removed later.
+
+bool Solver::litRedundant(Lit p, uint32_t abstract_levels) {
+    analyze_stack.clear();
+    analyze_stack.push(p);
+    int top = analyze_toclear.size();
+    while (analyze_stack.size() > 0) {
+        assert(reason(var(analyze_stack.last())) != CRef_Undef);
+        Clause& c = ca[reason(var(analyze_stack.last()))];
+        analyze_stack.pop(); // 
+        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;
+        }
+
+        for (int i = 1; i < c.size(); i++) {
+            Lit p = c[i];
+            if (!seen[var(p)]) {
+                if (level(var(p)) > 0) {
+                    if (reason(var(p)) != CRef_Undef && (abstractLevel(var(p)) & abstract_levels) != 0) {
+                        seen[var(p)] = 1;
+                        analyze_stack.push(p);
+                        analyze_toclear.push(p);
+                    } else {
+                        for (int j = top; j < analyze_toclear.size(); j++)
+                            seen[var(analyze_toclear[j])] = 0;
+                        analyze_toclear.shrink(analyze_toclear.size() - top);
+                        return false;
+                    }
+                }
+            }
+        }
+    }
+
+    return true;
+}
+
+
+/*_________________________________________________________________________________________________
+|
+|  analyzeFinal : (p : Lit)  ->  [void]
+|  
+|  Description:
+|    Specialized analysis procedure to express the final conflict in terms of assumptions.
+|    Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and
+|    stores the result in 'out_conflict'.
+|________________________________________________________________________________________________@*/
+void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict) {
+    out_conflict.clear();
+    out_conflict.push(p);
+
+    if (decisionLevel() == 0)
+        return;
+
+    seen[var(p)] = 1;
+
+    for (int i = trail.size() - 1; i >= trail_lim[0]; i--) {
+        Var x = var(trail[i]);
+        if (seen[x]) {
+            if (reason(x) == CRef_Undef) {
+                assert(level(x) > 0);
+                out_conflict.push(~trail[i]);
+            } else {
+                Clause& c = ca[reason(x)];
+                //                for (int j = 1; j < c.size(); j++) Minisat (glucose 2.0) loop 
+                // Bug in case of assumptions due to special data structures for Binary.
+                // Many thanks to Sam Bayless (sbayless@cs.ubc.ca) for discover this bug.
+                for (int j = ((c.size() == 2) ? 0 : 1); j < c.size(); j++)
+                    if (level(var(c[j])) > 0)
+                        seen[var(c[j])] = 1;
+            }
+
+            seen[x] = 0;
+        }
+    }
+
+    seen[var(p)] = 0;
+}
+
+void Solver::uncheckedEnqueue(Lit p, CRef from) {
+    assert(value(p) == l_Undef);
+    assigns[var(p)] = lbool(!sign(p));
+    vardata[var(p)] = mkVarData(from, decisionLevel());
+    trail.push_(p);
+}
+
+/*_________________________________________________________________________________________________
+|
+|  propagate : [void]  ->  [Clause*]
+|  
+|  Description:
+|    Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned,
+|    otherwise CRef_Undef.
+|  
+|    Post-conditions:
+|      * the propagation queue is empty, even if there was a conflict.
+|________________________________________________________________________________________________@*/
+CRef Solver::propagate() {
+    CRef confl = CRef_Undef;
+    int num_props = 0;
+    int previousqhead = qhead;
+    watches.cleanAll();
+    watchesBin.cleanAll();
+    unaryWatches.cleanAll();
+    while (qhead < trail.size()) {
+        Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate.
+        vec<Watcher>& ws = watches[p];
+        Watcher *i, *j, *end;
+        num_props++;
+
+
+        // First, Propagate binary clauses 
+        vec<Watcher>& wbin = watchesBin[p];
+
+        for (int k = 0; k < wbin.size(); k++) {
+
+            Lit imp = wbin[k].blocker;
+
+            if (value(imp) == l_False) {
+                return wbin[k].cref;
+            }
+
+            if (value(imp) == l_Undef) {
+                uncheckedEnqueue(imp, wbin[k].cref);
+            }
+        }
+
+        // Now propagate other 2-watched clauses
+        for (i = j = (Watcher*) ws, end = i + ws.size(); i != end;) {
+            // Try to avoid inspecting the clause:
+            Lit blocker = i->blocker;
+            if (value(blocker) == l_True) {
+                *j++ = *i++;
+                continue;
+            }
+
+            // Make sure the false literal is data[1]:
+            CRef cr = i->cref;
+            Clause& c = ca[cr];
+            assert(!c.getOneWatched());
+            Lit false_lit = ~p;
+            if (c[0] == false_lit)
+                c[0] = c[1], c[1] = false_lit;
+            assert(c[1] == false_lit);
+            i++;
+
+            // If 0th watch is true, then clause is already satisfied.
+            Lit first = c[0];
+            Watcher w = Watcher(cr, first);
+            if (first != blocker && value(first) == l_True) {
+
+                *j++ = w;
+                continue;
+            }
+           if(incremental) { // ----------------- INCREMENTAL MODE
+             int choosenPos = -1;
+             for (int k = 2; k < c.size(); k++) {
+               
+               if (value(c[k]) != l_False){
+                 if(decisionLevel()>assumptions.size()) {
+                   choosenPos = k;
+                   break;
+                 } else {
+                   choosenPos = k;
+                   
+                   if(value(c[k])==l_True || !isSelector(var(c[k]))) {
+                     break;
+                   }
+                 }
+
+               }
+             }
+             if(choosenPos!=-1) {
+               c[1] = c[choosenPos]; c[choosenPos] = false_lit;
+               watches[~c[1]].push(w);
+               goto NextClause; }
+           } else {  // ----------------- DEFAULT  MODE (NOT INCREMENTAL)
+             for (int k = 2; k < c.size(); k++) {
+               
+               if (value(c[k]) != l_False){
+                 c[1] = c[k]; c[k] = false_lit;
+                 watches[~c[1]].push(w);
+                 goto NextClause; }
+             }
+           }
+            
+            // Did not find watch -- clause is unit under assignment:
+            *j++ = w;
+            if (value(first) == l_False) {
+                confl = cr;
+                qhead = trail.size();
+                // Copy the remaining watches:
+                while (i < end)
+                    *j++ = *i++;
+            } else {
+                uncheckedEnqueue(first, cr);
+
+
+            }
+NextClause:
+            ;
+        }
+        ws.shrink(i - j);
+
+       // unaryWatches "propagation"
+        if (useUnaryWatched &&  confl == CRef_Undef) {
+            confl = propagateUnaryWatches(p);
+
+        }
+    }
+
+        
+
+    propagations += num_props;
+    simpDB_props -= num_props;
+
+    return confl;
+}
+
+/*_________________________________________________________________________________________________
+|
+|  propagateUnaryWatches : [Lit]  ->  [Clause*]
+|  
+|  Description:
+|    Propagates unary watches of Lit p, return a conflict 
+|    otherwise CRef_Undef
+|  
+|________________________________________________________________________________________________@*/
+
+CRef Solver::propagateUnaryWatches(Lit p) {
+    CRef confl= CRef_Undef;
+    Watcher *i, *j, *end;
+    vec<Watcher>& ws = unaryWatches[p];
+    for (i = j = (Watcher*) ws, end = i + ws.size(); i != end;) {
+        // Try to avoid inspecting the clause:
+        Lit blocker = i->blocker;
+        if (value(blocker) == l_True) {
+            *j++ = *i++;
+            continue;
+        }
+
+        // Make sure the false literal is data[1]:
+        CRef cr = i->cref;
+        Clause& c = ca[cr];
+        assert(c.getOneWatched());
+        Lit false_lit = ~p;
+        assert(c[0] == false_lit); // this is unary watch... No other choice if "propagated"
+        //if (c[0] == false_lit)
+        //c[0] = c[1], c[1] = false_lit;
+        //assert(c[1] == false_lit);
+        i++;
+        Watcher w = Watcher(cr, c[0]);
+        for (int k = 1; k < c.size(); k++) {
+            if (value(c[k]) != l_False) {
+                c[0] = c[k];
+                c[k] = false_lit;
+                unaryWatches[~c[0]].push(w);
+                goto NextClauseUnary;
+            }
+        }
+
+        // Did not find watch -- clause is empty under assignment:
+        *j++ = w;
+
+        confl = cr;
+        qhead = trail.size();
+        // Copy the remaining watches:
+        while (i < end)
+            *j++ = *i++;
+
+        // We can add it now to the set of clauses when backtracking
+        //printf("*");
+        if (promoteOneWatchedClause) {
+            nbPromoted++;
+            // Let's find the two biggest decision levels in the clause s.t. it will correctly be propagated when we'll backtrack
+            int maxlevel = -1;
+            int index = -1;
+            for (int k = 1; k < c.size(); k++) {
+                assert(value(c[k]) == l_False);
+                assert(level(var(c[k])) <= level(var(c[0])));
+                if (level(var(c[k])) > maxlevel) {
+                    index = k;
+                    maxlevel = level(var(c[k]));
+                }
+            }
+            detachClausePurgatory(cr, true); // TODO: check that the cleanAll is ok (use ",true" otherwise)
+            assert(index != -1);
+            Lit tmp = c[1];
+            c[1] = c[index], c[index] = tmp;
+            attachClause(cr);
+            // TODO used in function ParallelSolver::reportProgressArrayImports 
+            //Override :-(
+            //goodImportsFromThreads[ca[cr].importedFrom()]++;
+            ca[cr].setOneWatched(false);
+            ca[cr].setExported(2);  
+        }
+NextClauseUnary:
+        ;
+    }
+    ws.shrink(i - j);
+
+    return confl;
+}
+
+/*_________________________________________________________________________________________________
+|
+|  reduceDB : ()  ->  [void]
+|  
+|  Description:
+|    Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked
+|    clauses are clauses that are reason to some assignment. Binary clauses are never removed.
+|________________________________________________________________________________________________@*/
+
+
+void Solver::reduceDB()
+{
+  int     i, j;
+  nbReduceDB++;
+  sort(learnts, reduceDB_lt(ca));
+
+  // We have a lot of "good" clauses, it is difficult to compare them. Keep more !
+  if(ca[learnts[learnts.size() / RATIOREMOVECLAUSES]].lbd()<=3) nbclausesbeforereduce +=specialIncReduceDB; 
+  // Useless :-)
+  if(ca[learnts.last()].lbd()<=5)  nbclausesbeforereduce +=specialIncReduceDB; 
+  
+  
+  // Don't delete binary or locked clauses. From the rest, delete clauses from the first half
+  // Keep clauses which seem to be usefull (their lbd was reduce during this sequence)
+
+  int limit = learnts.size() / 2;
+
+  for (i = j = 0; i < learnts.size(); i++){
+    Clause& c = ca[learnts[i]];
+    if (c.lbd()>2 && c.size() > 2 && c.canBeDel() &&  !locked(c) && (i < limit)) {
+      removeClause(learnts[i]);
+      nbRemovedClauses++;
+    }
+    else {
+      if(!c.canBeDel()) limit++; //we keep c, so we can delete an other clause
+      c.setCanBeDel(true);       // At the next step, c can be delete
+      learnts[j++] = learnts[i];
+    }
+  }
+  learnts.shrink(i - j);
+  checkGarbage();
+}
+
+
+void Solver::removeSatisfied(vec<CRef>& cs) {
+
+    int i, j;
+    for (i = j = 0; i < cs.size(); i++) {
+        Clause& c = ca[cs[i]];
+
+
+        if (satisfied(c))
+            if (c.getOneWatched())
+                removeClause(cs[i], true);
+            else
+                removeClause(cs[i]);
+        else
+            cs[j++] = cs[i];
+    }
+    cs.shrink(i - j);
+}
+
+void Solver::rebuildOrderHeap() {
+    vec<Var> vs;
+    for (Var v = 0; v < nVars(); v++)
+        if (decision[v] && value(v) == l_Undef)
+            vs.push(v);
+    order_heap.build(vs);
+
+}
+
+/*_________________________________________________________________________________________________
+|
+|  simplify : [void]  ->  [bool]
+|  
+|  Description:
+|    Simplify the clause database according to the current top-level assigment. Currently, the only
+|    thing done here is the removal of satisfied clauses, but more things can be put here.
+|________________________________________________________________________________________________@*/
+bool Solver::simplify() {
+    assert(decisionLevel() == 0);
+
+    if (!ok) return ok = false;
+    else {
+        CRef cr = propagate();
+        if (cr != CRef_Undef) {
+            return ok = false;
+        }
+    }
+
+
+    if (nAssigns() == simpDB_assigns || (simpDB_props > 0))
+        return true;
+
+    // Remove satisfied clauses:
+    removeSatisfied(learnts);
+    removeSatisfied(unaryWatchedClauses);
+    if (remove_satisfied) // Can be turned off.
+        removeSatisfied(clauses);
+    checkGarbage();
+    rebuildOrderHeap();
+
+    simpDB_assigns = nAssigns();
+    simpDB_props = clauses_literals + learnts_literals; // (shouldn't depend on stats really, but it will do for now)
+
+    return true;
+}
+
+
+/*_________________________________________________________________________________________________
+|
+|  search : (nof_conflicts : int) (params : const SearchParams&)  ->  [lbool]
+|  
+|  Description:
+|    Search for a model the specified number of conflicts. 
+|    NOTE! Use negative value for 'nof_conflicts' indicate infinity.
+|  
+|  Output:
+|    'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If
+|    all variables are decision variables, this means that the clause set is satisfiable. 'l_False'
+|    if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached.
+|________________________________________________________________________________________________@*/
+lbool Solver::search(int nof_conflicts) {
+    assert(ok);
+    int backtrack_level;
+    int conflictC = 0;
+    vec<Lit> learnt_clause, selectors;
+    unsigned int nblevels,szWithoutSelectors = 0;
+    bool blocked = false;
+    starts++;
+    for (;;) {
+        if (decisionLevel() == 0) { // We import clauses FIXME: ensure that we will import clauses enventually (restart after some point)
+            parallelImportUnaryClauses();
+            
+            if (parallelImportClauses())
+                return l_False;
+
+        }
+        CRef confl = propagate();
+
+        if (confl != CRef_Undef) {
+            if(parallelJobIsFinished())
+                return l_Undef;
+            
+            
+            sumDecisionLevels += decisionLevel();
+            // CONFLICT
+            conflicts++;
+            conflictC++;
+            conflictsRestarts++;
+           if (conflicts % 5000 == 0 && var_decay < max_var_decay)
+                var_decay += 0.01;
+
+            if (verbosity >= 1 && conflicts % verbEveryConflicts == 0) {
+                printf("c | %8d   %7d    %5d | %7d %8d %8d | %5d %8d   %6d %8d | %6.3f %% |\n",
+                        (int) starts, (int) nbstopsrestarts, (int) (conflicts / starts),
+                        (int) dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]), nClauses(), (int) clauses_literals,
+                        (int) nbReduceDB, nLearnts(), (int) nbDL2, (int) nbRemovedClauses, progressEstimate()*100);
+            }
+            if (decisionLevel() == 0) {
+                return l_False;
+
+            }
+
+            trailQueue.push(trail.size());
+            // BLOCK RESTART (CP 2012 paper)
+            if (conflictsRestarts > LOWER_BOUND_FOR_BLOCKING_RESTART && lbdQueue.isvalid() && trail.size() > R * trailQueue.getavg()) {
+                lbdQueue.fastclear();
+                nbstopsrestarts++;
+                if (!blocked) {
+                    lastblockatrestart = starts;
+                    nbstopsrestartssame++;
+                    blocked = true;
+                }
+            }
+
+            learnt_clause.clear();
+            selectors.clear();
+
+            analyze(confl, learnt_clause, selectors, backtrack_level, nblevels,szWithoutSelectors);
+
+            lbdQueue.push(nblevels);
+            sumLBD += nblevels;
+
+            cancelUntil(backtrack_level);
+
+            if (certifiedUNSAT) {
+                for (int i = 0; i < learnt_clause.size(); i++)
+                    fprintf(certifiedOutput, "%i ", (var(learnt_clause[i]) + 1) *
+                        (-2 * sign(learnt_clause[i]) + 1));
+                fprintf(certifiedOutput, "0\n");
+            }
+
+
+            if (learnt_clause.size() == 1) {
+                uncheckedEnqueue(learnt_clause[0]);
+                nbUn++;
+                parallelExportUnaryClause(learnt_clause[0]);
+            } else {
+                CRef cr = ca.alloc(learnt_clause, true);
+                ca[cr].setLBD(nblevels);
+                ca[cr].setOneWatched(false);
+               ca[cr].setSizeWithoutSelectors(szWithoutSelectors);
+                if (nblevels <= 2) nbDL2++; // stats
+                if (ca[cr].size() == 2) nbBin++; // stats
+                learnts.push(cr);
+                attachClause(cr);
+                lastLearntClause = cr; // Use in multithread (to hard to put inside ParallelSolver)
+                parallelExportClauseDuringSearch(ca[cr]);
+                claBumpActivity(ca[cr]);
+                uncheckedEnqueue(learnt_clause[0], cr);
+
+            }
+            varDecayActivity();
+            claDecayActivity();
+
+
+        } else {
+            // Our dynamic restart, see the SAT09 competition compagnion paper 
+            if (
+                    (lbdQueue.isvalid() && ((lbdQueue.getavg() * K) > (sumLBD / conflictsRestarts)))) {
+                lbdQueue.fastclear();
+                progress_estimate = progressEstimate();
+                int bt = 0;
+                if(incremental) // DO NOT BACKTRACK UNTIL 0.. USELESS
+                    bt = (decisionLevel()<assumptions.size()) ? decisionLevel() : assumptions.size();
+                cancelUntil(bt);
+                return l_Undef;
+            }
+
+
+            // Simplify the set of problem clauses:
+            if (decisionLevel() == 0 && !simplify()) {
+                return l_False;
+            }
+            // Perform clause database reduction !
+            if (conflicts >= ((unsigned int) curRestart * nbclausesbeforereduce)) {
+
+                if (learnts.size() > 0) {
+                    curRestart = (conflicts / nbclausesbeforereduce) + 1;
+                    reduceDB();
+                    if (!panicModeIsEnabled())
+                        nbclausesbeforereduce += incReduceDB;
+                }
+            }
+
+            lastLearntClause = CRef_Undef;
+            Lit next = lit_Undef;
+            while (decisionLevel() < assumptions.size()) {
+                // Perform user provided assumption:
+                Lit p = assumptions[decisionLevel()];
+                if (value(p) == l_True) {
+                    // Dummy decision level:
+                    newDecisionLevel();
+                } else if (value(p) == l_False) {
+                    analyzeFinal(~p, conflict);
+                    return l_False;
+                } else {
+                    next = p;
+                    break;
+                }
+            }
+
+            if (next == lit_Undef) {
+                // New variable decision:
+                decisions++;
+                next = pickBranchLit();
+                if (next == lit_Undef) {
+                    printf("c last restart ## conflicts  :  %d %d \n", conflictC, decisionLevel());
+                    // Model found:
+                    return l_True;
+                }
+            }
+
+            // Increase decision level and enqueue 'next'
+            newDecisionLevel();
+            uncheckedEnqueue(next);
+        }
+    }
+}
+
+double Solver::progressEstimate() const {
+    double progress = 0;
+    double F = 1.0 / nVars();
+
+    for (int i = 0; i <= decisionLevel(); i++) {
+        int beg = i == 0 ? 0 : trail_lim[i - 1];
+        int end = i == decisionLevel() ? trail.size() : trail_lim[i];
+        progress += pow(F, i) * (end - beg);
+    }
+
+    return progress / nVars();
+}
+
+void Solver::printIncrementalStats() {
+
+    printf("c---------- Glucose Stats -------------------------\n");
+    printf("c restarts              : %" PRIu64"\n", starts);
+    printf("c nb ReduceDB           : %" PRIu64"\n", nbReduceDB);
+    printf("c nb removed Clauses    : %" PRIu64"\n", nbRemovedClauses);
+    printf("c nb learnts DL2        : %" PRIu64"\n", nbDL2);
+    printf("c nb learnts size 2     : %" PRIu64"\n", nbBin);
+    printf("c nb learnts size 1     : %" PRIu64"\n", nbUn);
+
+    printf("c conflicts             : %" PRIu64"\n", conflicts);
+    printf("c decisions             : %" PRIu64"\n", decisions);
+    printf("c propagations          : %" PRIu64"\n", propagations);
+
+  printf("\nc SAT Calls             : %d in %g seconds\n",nbSatCalls,totalTime4Sat);
+  printf("c UNSAT Calls           : %d in %g seconds\n",nbUnsatCalls,totalTime4Unsat);
+
+    printf("c--------------------------------------------------\n");
+}
+
+// NOTE: assumptions passed in member-variable 'assumptions'.
+
+lbool Solver::solve_(bool do_simp, bool turn_off_simp) // Parameters are useless in core but useful for SimpSolver....
+{
+
+    if(incremental && certifiedUNSAT) {
+    printf("Can not use incremental and certified unsat in the same time\n");
+    exit(-1);
+  }
+    model.clear();
+    conflict.clear();
+    if (!ok) return l_False;
+    double curTime = cpuTime();
+
+    solves++;
+            
+   
+    
+    lbool   status        = l_Undef;
+    if(!incremental && verbosity>=1) {
+      printf("c ========================================[ MAGIC CONSTANTS ]==============================================\n");
+      printf("c | Constants are supposed to work well together :-)                                                      |\n");
+      printf("c | however, if you find better choices, please let us known...                                           |\n");
+      printf("c |-------------------------------------------------------------------------------------------------------|\n");
+      printf("c |                                |                                |                                     |\n"); 
+      printf("c | - Restarts:                    | - Reduce Clause DB:            | - Minimize Asserting:               |\n");
+      printf("c |   * LBD Queue    : %6d      |   * First     : %6d         |    * size < %3d                     |\n",lbdQueue.maxSize(),nbclausesbeforereduce,lbSizeMinimizingClause);
+      printf("c |   * Trail  Queue : %6d      |   * Inc       : %6d         |    * lbd  < %3d                     |\n",trailQueue.maxSize(),incReduceDB,lbLBDMinimizingClause);
+      printf("c |   * K            : %6.2f      |   * Special   : %6d         |                                     |\n",K,specialIncReduceDB);
+      printf("c |   * R            : %6.2f      |   * Protected :  (lbd)< %2d     |                                     |\n",R,lbLBDFrozenClause);
+      printf("c |                                |                                |                                     |\n"); 
+      printf("c ==================================[ Search Statistics (every %6d conflicts) ]=========================\n",verbEveryConflicts);
+      printf("c |                                                                                                       |\n"); 
+
+      printf("c |          RESTARTS           |          ORIGINAL         |              LEARNT              | Progress |\n");
+      printf("c |       NB   Blocked  Avg Cfc |    Vars  Clauses Literals |   Red   Learnts    LBD2  Removed |          |\n");
+      printf("c =========================================================================================================\n");
+    }
+
+    // Search:
+    int curr_restarts = 0;
+    while (status == l_Undef){
+      status = search(0); // the parameter is useless in glucose, kept to allow modifications
+
+        if (!withinBudget()) break;
+        curr_restarts++;
+    }
+
+    if (!incremental && verbosity >= 1)
+      printf("c =========================================================================================================\n");
+
+    if (certifiedUNSAT){ // Want certified output
+      if (status == l_False)
+       fprintf(certifiedOutput, "0\n");
+      fclose(certifiedOutput);
+    }
+
+
+    if (status == l_True){
+        // Extend & copy model:
+        model.growTo(nVars());
+        for (int i = 0; i < nVars(); i++) model[i] = value(i);
+    }else if (status == l_False && conflict.size() == 0)
+        ok = false;
+
+
+
+    cancelUntil(0);
+
+
+    double finalTime = cpuTime();
+    if(status==l_True) {
+        nbSatCalls++; 
+        totalTime4Sat +=(finalTime-curTime);
+    }
+    if(status==l_False) {
+        nbUnsatCalls++; 
+        totalTime4Unsat +=(finalTime-curTime);
+    }
+    
+
+    return status;
+
+}
+
+
+
+
+
+//=================================================================================================
+// Writing CNF to DIMACS:
+// 
+// FIXME: this needs to be rewritten completely.
+
+static Var mapVar(Var x, vec<Var>& map, Var& max) {
+    if (map.size() <= x || map[x] == -1) {
+        map.growTo(x + 1, -1);
+        map[x] = max++;
+    }
+    return map[x];
+}
+
+void Solver::toDimacs(FILE* f, Clause& c, vec<Var>& map, Var& max) {
+    if (satisfied(c)) return;
+
+    for (int i = 0; i < c.size(); i++)
+        if (value(c[i]) != l_False)
+            fprintf(f, "%s%d ", sign(c[i]) ? "-" : "", mapVar(var(c[i]), map, max) + 1);
+    fprintf(f, "0\n");
+}
+
+void Solver::toDimacs(const char *file, const vec<Lit>& assumps) {
+    FILE* f = fopen(file, "wr");
+    if (f == NULL)
+        fprintf(stderr, "could not open file %s\n", file), exit(1);
+    toDimacs(f, assumps);
+    fclose(f);
+}
+
+void Solver::toDimacs(FILE* f, const vec<Lit>& assumps) {
+    // Handle case when solver is in contradictory state:
+    if (!ok) {
+        fprintf(f, "p cnf 1 2\n1 0\n-1 0\n");
+        return;
+    }
+
+    vec<Var> map;
+    Var max = 0;
+
+    // Cannot use removeClauses here because it is not safe
+    // to deallocate them at this point. Could be improved.
+    int cnt = 0;
+    for (int i = 0; i < clauses.size(); i++)
+        if (!satisfied(ca[clauses[i]]))
+            cnt++;
+
+    for (int i = 0; i < clauses.size(); i++)
+        if (!satisfied(ca[clauses[i]])) {
+            Clause& c = ca[clauses[i]];
+            for (int j = 0; j < c.size(); j++)
+                if (value(c[j]) != l_False)
+                    mapVar(var(c[j]), map, max);
+        }
+
+    // Assumptions are added as unit clauses:
+    cnt += assumptions.size();
+
+    fprintf(f, "p cnf %d %d\n", max, cnt);
+
+    for (int i = 0; i < assumptions.size(); i++) {
+        assert(value(assumptions[i]) != l_False);
+        fprintf(f, "%s%d 0\n", sign(assumptions[i]) ? "-" : "", mapVar(var(assumptions[i]), map, max) + 1);
+    }
+
+    for (int i = 0; i < clauses.size(); i++)
+        toDimacs(f, ca[clauses[i]], map, max);
+
+    if (verbosity > 0)
+        printf("Wrote %d clauses with %d variables.\n", cnt, max);
+}
+
+
+//=================================================================================================
+// Garbage Collection methods:
+
+void Solver::relocAll(ClauseAllocator& to) {
+    // All watchers:
+    //
+    // for (int i = 0; i < watches.size(); i++)
+    watches.cleanAll();
+    watchesBin.cleanAll();
+    unaryWatches.cleanAll();
+    for (int v = 0; v < nVars(); v++)
+        for (int s = 0; s < 2; s++) {
+            Lit p = mkLit(v, s);
+            // printf(" >>> RELOCING: %s%d\n", sign(p)?"-":"", var(p)+1);
+            vec<Watcher>& ws = watches[p];
+            for (int j = 0; j < ws.size(); j++)
+                ca.reloc(ws[j].cref, to);
+            vec<Watcher>& ws2 = watchesBin[p];
+            for (int j = 0; j < ws2.size(); j++)
+                ca.reloc(ws2[j].cref, to);
+            vec<Watcher>& ws3 = unaryWatches[p];
+            for (int j = 0; j < ws3.size(); j++)
+                ca.reloc(ws3[j].cref, to);
+        }
+
+    // All reasons:
+    //
+    for (int i = 0; i < trail.size(); i++) {
+        Var v = var(trail[i]);
+
+        if (reason(v) != CRef_Undef && (ca[reason(v)].reloced() || locked(ca[reason(v)])))
+            ca.reloc(vardata[v].reason, to);
+    }
+
+    // All learnt:
+    //
+    for (int i = 0; i < learnts.size(); i++)
+        ca.reloc(learnts[i], to);
+
+    // All original:
+    //
+    for (int i = 0; i < clauses.size(); i++)
+        ca.reloc(clauses[i], to);
+
+    for (int i = 0; i < unaryWatchedClauses.size(); i++)
+        ca.reloc(unaryWatchedClauses[i], to);
+}
+
+
+
+void Solver::garbageCollect() {
+    // Initialize the next region to a size corresponding to the estimated utilization degree. This
+    // is not precise but should avoid some unnecessary reallocations for the new region:
+    ClauseAllocator to(ca.size() - ca.wasted());
+
+    relocAll(to);
+    if (verbosity >= 2)
+        printf("|  Garbage collection:   %12d bytes => %12d bytes             |\n",
+            ca.size() * ClauseAllocator::Unit_Size, to.size() * ClauseAllocator::Unit_Size);
+    to.moveTo(ca);
+}
+
+//--------------------------------------------------------------
+// Functions related to MultiThread.
+// Useless in case of single core solver (aka original glucose)
+// Keep them empty if you just use core solver
+//--------------------------------------------------------------
+
+bool Solver::panicModeIsEnabled() {
+    return false;
+}
+
+void Solver::parallelImportUnaryClauses() {
+}
+
+bool Solver::parallelImportClauses() {
+    return false;
+}
+
+
+void Solver::parallelExportUnaryClause(Lit p) {
+}
+void Solver::parallelExportClauseDuringSearch(Clause &c) {
+}
+
+bool Solver::parallelJobIsFinished() { 
+    // Parallel: another job has finished let's quit
+    return false;
+}
+
+void Solver::parallelImportClauseDuringConflictAnalysis(Clause &c,CRef confl) {
+}
diff --git a/glucose-syrup/core/Solver.h b/glucose-syrup/core/Solver.h
new file mode 100644 (file)
index 0000000..63d5316
--- /dev/null
@@ -0,0 +1,581 @@
+/***************************************************************************************[Solver.h]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+#ifndef Glucose_Solver_h
+#define Glucose_Solver_h
+
+#include "mtl/Heap.h"
+#include "mtl/Alg.h"
+#include "utils/Options.h"
+#include "core/SolverTypes.h"
+#include "core/BoundedQueue.h"
+#include "core/Constants.h"
+#include "mtl/Clone.h"
+
+
+namespace Glucose {
+
+//=================================================================================================
+// Solver -- the main class:
+
+class Solver : public Clone {
+
+    friend class SolverConfiguration;
+
+public:
+
+    // Constructor/Destructor:
+    //
+    Solver();
+    Solver(const  Solver &s);
+    
+    virtual ~Solver();
+    
+    /**
+     * Clone function
+     */
+    virtual Clone* clone() const {
+        return  new Solver(*this);
+    }   
+
+    // Problem specification:
+    //
+    virtual Var     newVar    (bool polarity = true, bool dvar = true); // Add a new variable with parameters specifying variable mode.
+    bool    addClause (const vec<Lit>& ps);                     // Add a clause to the solver. 
+    bool    addEmptyClause();                                   // Add the empty clause, making the solver contradictory.
+    bool    addClause (Lit p);                                  // Add a unit clause to the solver. 
+    bool    addClause (Lit p, Lit q);                           // Add a binary clause to the solver. 
+    bool    addClause (Lit p, Lit q, Lit r);                    // Add a ternary clause to the solver. 
+    virtual bool    addClause_(      vec<Lit>& ps);                     // Add a clause to the solver without making superflous internal copy. Will
+                                                                // change the passed vector 'ps'.
+
+    // Solving:
+    //
+    bool    simplify     ();                        // Removes already satisfied clauses.
+    bool    solve        (const vec<Lit>& assumps); // Search for a model that respects a given set of assumptions.
+    lbool   solveLimited (const vec<Lit>& assumps); // Search for a model that respects a given set of assumptions (With resource constraints).
+    bool    solve        ();                        // Search without assumptions.
+    bool    solve        (Lit p);                   // Search for a model that respects a single assumption.
+    bool    solve        (Lit p, Lit q);            // Search for a model that respects two assumptions.
+    bool    solve        (Lit p, Lit q, Lit r);     // Search for a model that respects three assumptions.
+    bool    okay         () const;                  // FALSE means solver is in a conflicting state
+
+       // Convenience versions of 'toDimacs()':
+    void    toDimacs     (FILE* f, const vec<Lit>& assumps);            // Write CNF to file in DIMACS-format.
+    void    toDimacs     (const char *file, const vec<Lit>& assumps);
+    void    toDimacs     (FILE* f, Clause& c, vec<Var>& map, Var& max);
+    void    toDimacs     (const char* file);
+    void    toDimacs     (const char* file, Lit p);
+    void    toDimacs     (const char* file, Lit p, Lit q);
+    void    toDimacs     (const char* file, Lit p, Lit q, Lit r);
+    // Display clauses and literals
+    void printLit(Lit l);
+    void printClause(CRef c);
+    void printInitialClause(CRef c);
+    
+    // Variable mode:
+    // 
+    void    setPolarity    (Var v, bool b); // Declare which polarity the decision heuristic should use for a variable. Requires mode 'polarity_user'.
+    void    setDecisionVar (Var v, bool b); // Declare if a variable should be eligible for selection in the decision heuristic.
+
+    // Read state:
+    //
+    lbool   value      (Var x) const;       // The current value of a variable.
+    lbool   value      (Lit p) const;       // The current value of a literal.
+    lbool   modelValue (Var x) const;       // The value of a variable in the last model. The last call to solve must have been satisfiable.
+    lbool   modelValue (Lit p) const;       // The value of a literal in the last model. The last call to solve must have been satisfiable.
+    int     nAssigns   ()      const;       // The current number of assigned literals.
+    int     nClauses   ()      const;       // The current number of original clauses.
+    int     nLearnts   ()      const;       // The current number of learnt clauses.
+    int     nVars      ()      const;       // The current number of variables.
+    int     nFreeVars  ()      const;
+
+    inline char valuePhase(Var v) {return polarity[v];}
+
+    // Incremental mode
+    void setIncrementalMode();
+    void initNbInitialVars(int nb);
+    void printIncrementalStats();
+    bool isIncremental();
+    // Resource contraints:
+    //
+    void    setConfBudget(int64_t x);
+    void    setPropBudget(int64_t x);
+    void    budgetOff();
+    void    interrupt();          // Trigger a (potentially asynchronous) interruption of the solver.
+    void    clearInterrupt();     // Clear interrupt indicator flag.
+
+    // Memory managment:
+    //
+    virtual void garbageCollect();
+    void    checkGarbage(double gf);
+    void    checkGarbage();
+
+    // Extra results: (read-only member variable)
+    //
+    vec<lbool> model;             // If problem is satisfiable, this vector contains the model (if any).
+    vec<Lit>   conflict;          // If problem is unsatisfiable (possibly under assumptions),
+                                  // this vector represent the final conflict clause expressed in the assumptions.
+
+    // Mode of operation:
+    //
+    int       verbosity;
+    int       verbEveryConflicts;
+    int       showModel;
+    
+    // Constants For restarts
+    double    K;
+    double    R;
+    double    sizeLBDQueue;
+    double    sizeTrailQueue;
+
+    // Constants for reduce DB
+    int          firstReduceDB;
+    int          incReduceDB;
+    int          specialIncReduceDB;
+    unsigned int lbLBDFrozenClause;
+
+    // Constant for reducing clause
+    int          lbSizeMinimizingClause;
+    unsigned int lbLBDMinimizingClause;
+
+    // Constant for heuristic
+    double    var_decay;
+    double    max_var_decay;
+    double    clause_decay;
+    double    random_var_freq;
+    double    random_seed;
+    int       ccmin_mode;         // Controls conflict clause minimization (0=none, 1=basic, 2=deep).
+    int       phase_saving;       // Controls the level of phase saving (0=none, 1=limited, 2=full).
+    bool      rnd_pol;            // Use random polarities for branching heuristics.
+    bool      rnd_init_act;       // Initialize variable activities with a small random value.
+    
+    // Constant for Memory managment
+    double    garbage_frac;       // The fraction of wasted memory allowed before a garbage collection is triggered.
+
+    // Certified UNSAT ( Thanks to Marijn Heule)
+    FILE*               certifiedOutput;
+    bool                certifiedUNSAT;
+
+    // Panic mode. 
+    // Save memory
+    uint32_t panicModeLastRemoved, panicModeLastRemovedShared;
+    
+    bool useUnaryWatched;            // Enable unary watched literals
+    bool promoteOneWatchedClause;    // One watched clauses are promotted to two watched clauses if found empty
+    
+    // Functions useful for multithread solving
+    // Useless in the sequential case 
+    // Overide in ParallelSolver
+    virtual void parallelImportClauseDuringConflictAnalysis(Clause &c,CRef confl);
+    virtual bool parallelImportClauses(); // true if the empty clause was received
+    virtual void parallelImportUnaryClauses();
+    virtual void parallelExportUnaryClause(Lit p);
+    virtual void parallelExportClauseDuringSearch(Clause &c);
+    virtual bool parallelJobIsFinished();
+    virtual bool panicModeIsEnabled();
+    
+    
+
+    // Statistics: (read-only member variable)
+    uint64_t    nbPromoted;          // Number of clauses from unary to binary watch scheme
+    uint64_t    originalClausesSeen; // Number of original clauses seen
+    uint64_t    sumDecisionLevels;
+    //
+    uint64_t nbRemovedClauses,nbRemovedUnaryWatchedClauses, nbReducedClauses,nbDL2,nbBin,nbUn,nbReduceDB,solves, starts, decisions, rnd_decisions, propagations, conflicts,conflictsRestarts,nbstopsrestarts,nbstopsrestartssame,lastblockatrestart;
+    uint64_t dec_vars, clauses_literals, learnts_literals, max_literals, tot_literals;
+
+protected:
+
+    long curRestart;
+    // Helper structures:
+    //
+    struct VarData { CRef reason; int level; };
+    static inline VarData mkVarData(CRef cr, int l){ VarData d = {cr, l}; return d; }
+
+    struct Watcher {
+        CRef cref;
+        Lit  blocker;
+        Watcher(CRef cr, Lit p) : cref(cr), blocker(p) {}
+        bool operator==(const Watcher& w) const { return cref == w.cref; }
+        bool operator!=(const Watcher& w) const { return cref != w.cref; }
+/*        Watcher &operator=(Watcher w) {
+            this->cref = w.cref;
+            this->blocker = w.blocker;
+            return *this;
+        }
+*/
+    };
+
+    struct WatcherDeleted
+    {
+        const ClauseAllocator& ca;
+        WatcherDeleted(const ClauseAllocator& _ca) : ca(_ca) {}
+        bool operator()(const Watcher& w) const { return ca[w.cref].mark() == 1; }
+    };
+
+    struct VarOrderLt {
+        const vec<double>&  activity;
+        bool operator () (Var x, Var y) const { return activity[x] > activity[y]; }
+        VarOrderLt(const vec<double>&  act) : activity(act) { }
+    };
+
+
+    // Solver state:
+    //
+    int                lastIndexRed;
+    bool                ok;               // If FALSE, the constraints are already unsatisfiable. No part of the solver state may be used!
+    double              cla_inc;          // Amount to bump next clause with.
+    vec<double>         activity;         // A heuristic measurement of the activity of a variable.
+    double              var_inc;          // Amount to bump next variable with.
+    OccLists<Lit, vec<Watcher>, WatcherDeleted>
+                        watches;          // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true).
+    OccLists<Lit, vec<Watcher>, WatcherDeleted>
+                        watchesBin;          // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true).
+    OccLists<Lit, vec<Watcher>, WatcherDeleted>
+                        unaryWatches;       //  Unary watch scheme (clauses are seen when they become empty
+    vec<CRef>           clauses;          // List of problem clauses.
+    vec<CRef>           learnts;          // List of learnt clauses.
+    vec<CRef>           unaryWatchedClauses;  // List of imported clauses (after the purgatory) // TODO put inside ParallelSolver
+
+    vec<lbool>          assigns;          // The current assignments.
+    vec<char>           polarity;         // The preferred polarity of each variable.
+    vec<char>           decision;         // 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<int>            nbpos;
+    vec<int>            trail_lim;        // Separator indices for different decision levels in 'trail'.
+    vec<VarData>        vardata;          // Stores reason and level for each variable.
+    int                 qhead;            // Head of queue (as index into the trail -- no more explicit propagation queue in MiniSat).
+    int                 simpDB_assigns;   // Number of top-level assignments since last execution of 'simplify()'.
+    int64_t             simpDB_props;     // Remaining number of propagations that must be made before next execution of 'simplify()'.
+    vec<Lit>            assumptions;      // Current set of assumptions provided to solve by the user.
+    Heap<VarOrderLt>    order_heap;       // A priority queue of variables ordered with respect to the variable activity.
+    double              progress_estimate;// Set by 'search()'.
+    bool                remove_satisfied; // Indicates whether possibly inefficient linear scan for satisfied clauses should be performed in 'simplify'.
+    bool reduceOnSize;
+    int  reduceOnSizeSize;                // See XMinisat paper
+    vec<unsigned int>   permDiff;           // permDiff[var] contains the current conflict number... Used to count the number of  LBD
+    
+
+    // UPDATEVARACTIVITY trick (see competition'09 companion paper)
+    vec<Lit> lastDecisionLevel; 
+
+    ClauseAllocator     ca;
+
+    int nbclausesbeforereduce;            // To know when it is time to reduce clause database
+    
+    // Used for restart strategies
+    bqueue<unsigned int> trailQueue,lbdQueue; // Bounded queues for restarts.
+    float sumLBD; // used to compute the global average of LBD. Restarts...
+    int sumAssumptions;
+    CRef lastLearntClause;
+
+
+    // Temporaries (to reduce allocation overhead). Each variable is prefixed by the method in which it is
+    // used, exept 'seen' wich is used in several places.
+    //
+    vec<char>           seen;
+    vec<Lit>            analyze_stack;
+    vec<Lit>            analyze_toclear;
+    vec<Lit>            add_tmp;
+    unsigned int  MYFLAG;
+
+    // Initial reduceDB strategy
+    double              max_learnts;
+    double              learntsize_adjust_confl;
+    int                 learntsize_adjust_cnt;
+
+    // Resource contraints:
+    //
+    int64_t             conflict_budget;    // -1 means no budget.
+    int64_t             propagation_budget; // -1 means no budget.
+    bool                asynch_interrupt;
+
+    // Variables added for incremental mode
+    int incremental; // Use incremental SAT Solver
+    int nbVarsInitialFormula; // nb VAR in formula without assumptions (incremental SAT)
+    double totalTime4Sat,totalTime4Unsat;
+    int nbSatCalls,nbUnsatCalls;
+    vec<int> assumptionPositions,initialPositions;
+
+
+    // Main internal methods:
+    //
+    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, CRef from = CRef_Undef);                         // Enqueue a literal. Assumes value of literal is undefined.
+    bool     enqueue          (Lit p, CRef from = CRef_Undef);                         // Test if fact 'p' contradicts current state, enqueue otherwise.
+    CRef     propagate        ();                                                      // Perform unit propagation. Returns possibly conflicting clause.
+    CRef     propagateUnaryWatches(Lit p);                                                  // Perform propagation on unary watches of p, can find only conflicts
+    void     cancelUntil      (int level);                                             // Backtrack until a certain level.
+    void     analyze          (CRef confl, vec<Lit>& out_learnt, vec<Lit> & selectors, int& out_btlevel,unsigned int &nblevels,unsigned int &szWithoutSelectors);    // (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);                                     // Search for a given number of conflicts.
+    virtual lbool    solve_           (bool do_simp = true, bool turn_off_simp = false);                                                      // Main solve method (assumptions given in 'assumptions').
+    virtual void     reduceDB         ();                                                      // Reduce the set of learnt clauses.
+    void     removeSatisfied  (vec<CRef>& cs);                                         // Shrink 'cs' to contain only non-satisfied clauses.
+    void     rebuildOrderHeap ();
+
+    // Maintaining Variable/Clause activity:
+    //
+    void     varDecayActivity ();                      // Decay all variables with the specified factor. Implemented by increasing the 'bump' value instead.
+    void     varBumpActivity  (Var v, double inc);     // Increase a variable with the current 'bump' value.
+    void     varBumpActivity  (Var v);                 // Increase a variable with the current 'bump' value.
+    void     claDecayActivity ();                      // Decay all clauses with the specified factor. Implemented by increasing the 'bump' value instead.
+    void     claBumpActivity  (Clause& c);             // Increase a clause with the current 'bump' value.
+
+    // Operations on clauses:
+    //
+    void     attachClause     (CRef cr);               // Attach a clause to watcher lists.
+    void     detachClause     (CRef cr, bool strict = false); // Detach a clause to watcher lists.
+    void     detachClausePurgatory(CRef cr, bool strict = false);
+    void     attachClausePurgatory(CRef cr);
+    void     removeClause     (CRef cr, bool inPurgatory = false);               // 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.
+    bool     satisfied        (const Clause& c) const; // Returns TRUE if a clause is satisfied in the current state.
+
+    unsigned int computeLBD(const vec<Lit> & lits,int end=-1);
+    unsigned int computeLBD(const Clause &c);
+    void minimisationWithBinaryResolution(vec<Lit> &out_learnt);
+
+    virtual void     relocAll         (ClauseAllocator& to);
+
+    // Misc:
+    //
+    int      decisionLevel    ()      const; // Gives the current decisionlevel.
+    uint32_t abstractLevel    (Var x) const; // Used to represent an abstraction of sets of decision levels.
+    CRef     reason           (Var x) const;
+    int      level            (Var x) const;
+    double   progressEstimate ()      const; // DELETE THIS ?? IT'S NOT VERY USEFUL ...
+    bool     withinBudget     ()      const;
+    inline bool isSelector(Var v) {return (incremental && v>nbVarsInitialFormula);}
+
+    // Static helpers:
+    //
+
+    // Returns a random float 0 <= x < 1. Seed must never be 0.
+    static inline double drand(double& seed) {
+        seed *= 1389796;
+        int q = (int)(seed / 2147483647);
+        seed -= (double)q * 2147483647;
+        return seed / 2147483647; }
+
+    // Returns a random integer 0 <= x < size. Seed must never be 0.
+    static inline int irand(double& seed, int size) {
+        return (int)(drand(seed) * size); }
+};
+
+
+//=================================================================================================
+// Implementation of inline methods:
+
+inline CRef Solver::reason(Var x) const { return vardata[x].reason; }
+inline int  Solver::level (Var x) const { return vardata[x].level; }
+
+inline void Solver::insertVarOrder(Var x) {
+    if (!order_heap.inHeap(x) && decision[x]) order_heap.insert(x); }
+
+inline void Solver::varDecayActivity() { var_inc *= (1 / var_decay); }
+inline void Solver::varBumpActivity(Var v) { varBumpActivity(v, var_inc); }
+inline void Solver::varBumpActivity(Var v, double inc) {
+    if ( (activity[v] += inc) > 1e100 ) {
+        // Rescale:
+        for (int i = 0; i < nVars(); i++)
+            activity[i] *= 1e-100;
+        var_inc *= 1e-100; }
+
+    // Update order_heap with respect to new activity:
+    if (order_heap.inHeap(v))
+        order_heap.decrease(v); }
+
+inline void Solver::claDecayActivity() { cla_inc *= (1 / clause_decay); }
+inline void Solver::claBumpActivity (Clause& c) {
+        if ( (c.activity() += cla_inc) > 1e20 ) {
+            // Rescale:
+            for (int i = 0; i < learnts.size(); i++)
+                ca[learnts[i]].activity() *= 1e-20;
+            cla_inc *= 1e-20; } }
+
+inline void Solver::checkGarbage(void){ return checkGarbage(garbage_frac); }
+inline void Solver::checkGarbage(double gf){
+    if (ca.wasted() > ca.size() * gf)
+        garbageCollect(); }
+
+// NOTE: enqueue does not set the ok flag! (only public methods do)
+inline bool     Solver::enqueue         (Lit p, CRef from)      { return value(p) != l_Undef ? value(p) != l_False : (uncheckedEnqueue(p, from), true); }
+inline bool     Solver::addClause       (const vec<Lit>& ps)    { ps.copyTo(add_tmp); return addClause_(add_tmp); }
+inline bool     Solver::addEmptyClause  ()                      { add_tmp.clear(); return addClause_(add_tmp); }
+inline bool     Solver::addClause       (Lit p)                 { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp); }
+inline bool     Solver::addClause       (Lit p, Lit q)          { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp); }
+inline bool     Solver::addClause       (Lit p, Lit q, Lit r)   { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); }
+ inline bool     Solver::locked          (const Clause& c) const { 
+   if(c.size()>2) 
+     return value(c[0]) == l_True && reason(var(c[0])) != CRef_Undef && ca.lea(reason(var(c[0]))) == &c; 
+   return 
+     (value(c[0]) == l_True && reason(var(c[0])) != CRef_Undef && ca.lea(reason(var(c[0]))) == &c)
+     || 
+     (value(c[1]) == l_True && reason(var(c[1])) != CRef_Undef && ca.lea(reason(var(c[1]))) == &c);
+ }
+inline void     Solver::newDecisionLevel()                      { trail_lim.push(trail.size()); }
+
+inline int      Solver::decisionLevel ()      const   { return trail_lim.size(); }
+inline uint32_t Solver::abstractLevel (Var x) const   { return 1 << (level(x) & 31); }
+inline lbool    Solver::value         (Var x) const   { return assigns[x]; }
+inline lbool    Solver::value         (Lit p) const   { return assigns[var(p)] ^ sign(p); }
+inline lbool    Solver::modelValue    (Var x) const   { return model[x]; }
+inline lbool    Solver::modelValue    (Lit p) const   { return model[var(p)] ^ sign(p); }
+inline int      Solver::nAssigns      ()      const   { return trail.size(); }
+inline int      Solver::nClauses      ()      const   { return clauses.size(); }
+inline int      Solver::nLearnts      ()      const   { return learnts.size(); }
+inline int      Solver::nVars         ()      const   { return vardata.size(); }
+inline int      Solver::nFreeVars     ()      const   { return (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]); }
+inline void     Solver::setPolarity   (Var v, bool b) { polarity[v] = b; }
+inline void     Solver::setDecisionVar(Var v, bool b) 
+{ 
+    if      ( b && !decision[v]) dec_vars++;
+    else if (!b &&  decision[v]) dec_vars--;
+
+    decision[v] = b;
+    insertVarOrder(v);
+}
+inline void     Solver::setConfBudget(int64_t x){ conflict_budget    = conflicts    + x; }
+inline void     Solver::setPropBudget(int64_t x){ propagation_budget = propagations + x; }
+inline void     Solver::interrupt(){ asynch_interrupt = true; }
+inline void     Solver::clearInterrupt(){ asynch_interrupt = false; }
+inline void     Solver::budgetOff(){ conflict_budget = propagation_budget = -1; }
+inline bool     Solver::withinBudget() const {
+    return !asynch_interrupt &&
+           (conflict_budget    < 0 || conflicts < (uint64_t)conflict_budget) &&
+           (propagation_budget < 0 || propagations < (uint64_t)propagation_budget); }
+
+// FIXME: after the introduction of asynchronous interrruptions the solve-versions that return a
+// pure bool do not give a safe interface. Either interrupts must be possible to turn off here, or
+// all calls to solve must return an 'lbool'. I'm not yet sure which I prefer.
+inline bool     Solver::solve         ()                    { budgetOff(); assumptions.clear(); return solve_() == l_True; }
+inline bool     Solver::solve         (Lit p)               { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_() == l_True; }
+inline bool     Solver::solve         (Lit p, Lit q)        { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_() == l_True; }
+inline bool     Solver::solve         (Lit p, Lit q, Lit r) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_() == l_True; }
+inline bool     Solver::solve         (const vec<Lit>& assumps){ budgetOff(); assumps.copyTo(assumptions); return solve_() == l_True; }
+inline lbool    Solver::solveLimited  (const vec<Lit>& assumps){ assumps.copyTo(assumptions); return solve_(); }
+inline bool     Solver::okay          ()      const   { return ok; }
+
+inline void     Solver::toDimacs     (const char* file){ vec<Lit> as; toDimacs(file, as); }
+inline void     Solver::toDimacs     (const char* file, Lit p){ vec<Lit> as; as.push(p); toDimacs(file, as); }
+inline void     Solver::toDimacs     (const char* file, Lit p, Lit q){ vec<Lit> as; as.push(p); as.push(q); toDimacs(file, as); }
+inline void     Solver::toDimacs     (const char* file, Lit p, Lit q, Lit r){ vec<Lit> as; as.push(p); as.push(q); as.push(r); toDimacs(file, as); }
+
+
+
+//=================================================================================================
+// Debug etc:
+
+
+inline void Solver::printLit(Lit l)
+{
+    printf("%s%d:%c", sign(l) ? "-" : "", var(l)+1, value(l) == l_True ? '1' : (value(l) == l_False ? '0' : 'X'));
+}
+
+
+inline void Solver::printClause(CRef cr)
+{
+  Clause &c = ca[cr];
+    for (int i = 0; i < c.size(); i++){
+        printLit(c[i]);
+        printf(" ");
+    }
+}
+
+inline void Solver::printInitialClause(CRef cr)
+{
+  Clause &c = ca[cr];
+    for (int i = 0; i < c.size(); i++){
+      if(!isSelector(var(c[i]))) {
+       printLit(c[i]);
+        printf(" ");
+      }
+    }
+}
+
+//=================================================================================================
+
+struct reduceDB_lt {
+    ClauseAllocator& ca;
+
+    reduceDB_lt(ClauseAllocator& ca_) : ca(ca_) {
+    }
+
+    bool operator()(CRef x, CRef y) {
+
+        // Main criteria... Like in MiniSat we keep all binary clauses
+        if (ca[x].size() > 2 && ca[y].size() == 2) return 1;
+
+        if (ca[y].size() > 2 && ca[x].size() == 2) return 0;
+        if (ca[x].size() == 2 && ca[y].size() == 2) return 0;
+
+        // Second one  based on literal block distance
+        if (ca[x].lbd() > ca[y].lbd()) return 1;
+        if (ca[x].lbd() < ca[y].lbd()) return 0;
+
+
+        // Finally we can use old activity or size, we choose the last one
+        return ca[x].activity() < ca[y].activity();
+        //return x->size() < y->size();
+
+        //return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity()); } 
+    }
+};
+
+
+}
+
+
+#endif
diff --git a/glucose-syrup/core/SolverTypes.h b/glucose-syrup/core/SolverTypes.h
new file mode 100644 (file)
index 0000000..a905afb
--- /dev/null
@@ -0,0 +1,506 @@
+/***************************************************************************************[SolverTypes.h]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+
+#ifndef Glucose_SolverTypes_h
+#define Glucose_SolverTypes_h
+
+#include <assert.h>
+#include <stdint.h>
+#include <pthread.h>
+
+#include "mtl/IntTypes.h"
+#include "mtl/Alg.h"
+#include "mtl/Vec.h"
+#include "mtl/Map.h"
+#include "mtl/Alloc.h"
+
+
+namespace Glucose {
+
+//=================================================================================================
+// Variables, literals, lifted booleans, clauses:
+
+
+// NOTE! Variables are just integers. No abstraction here. They should be chosen from 0..N,
+// so that they can be used as array indices.
+
+typedef int Var;
+#define var_Undef (-1)
+
+
+struct Lit {
+    int     x;
+
+    // Use this as a constructor:
+    friend Lit mkLit(Var var, bool sign);
+
+    bool operator == (Lit p) const { return x == p.x; }
+    bool operator != (Lit p) const { return x != p.x; }
+    bool operator <  (Lit p) const { return x < p.x;  } // '<' makes p, ~p adjacent in the ordering.
+};
+
+
+inline  Lit  mkLit     (Var var, bool sign = false) { Lit p; p.x = var + var + (int)sign; return p; }
+inline  Lit  operator ~(Lit p)              { Lit q; q.x = p.x ^ 1; return q; }
+inline  Lit  operator ^(Lit p, bool b)      { Lit q; q.x = p.x ^ (unsigned int)b; return q; }
+inline  bool sign      (Lit p)              { return p.x & 1; }
+inline  int  var       (Lit p)              { return p.x >> 1; }
+
+// Mapping Literals to and from compact integers suitable for array indexing:
+inline  int  toInt     (Var v)              { return v; } 
+inline  int  toInt     (Lit p)              { return p.x; } 
+inline  Lit  toLit     (int i)              { Lit p; p.x = i; return p; } 
+
+//const Lit lit_Undef = mkLit(var_Undef, false);  // }- Useful special constants.
+//const Lit lit_Error = mkLit(var_Undef, true );  // }
+
+const Lit lit_Undef = { -2 };  // }- Useful special constants.
+const Lit lit_Error = { -1 };  // }
+
+
+//=================================================================================================
+// Lifted booleans:
+//
+// NOTE: this implementation is optimized for the case when comparisons between values are mostly
+//       between one variable and one constant. Some care had to be taken to make sure that gcc 
+//       does enough constant propagation to produce sensible code, and this appears to be somewhat
+//       fragile unfortunately.
+
+#define l_True  (Glucose::lbool((uint8_t)0)) // gcc does not do constant propagation if these are real constants.
+#define l_False (Glucose::lbool((uint8_t)1))
+#define l_Undef (Glucose::lbool((uint8_t)2))
+
+class lbool {
+    uint8_t value;
+
+public:
+    explicit lbool(uint8_t v) : value(v) { }
+
+    lbool()       : value(0) { }
+    explicit lbool(bool x) : value(!x) { }
+
+    bool  operator == (lbool b) const { return ((b.value&2) & (value&2)) | (!(b.value&2)&(value == b.value)); }
+    bool  operator != (lbool b) const { return !(*this == b); }
+    lbool operator ^  (bool  b) const { return lbool((uint8_t)(value^(uint8_t)b)); }
+
+    lbool operator && (lbool b) const { 
+        uint8_t sel = (this->value << 1) | (b.value << 3);
+        uint8_t v   = (0xF7F755F4 >> sel) & 3;
+        return lbool(v); }
+
+    lbool operator || (lbool b) const {
+        uint8_t sel = (this->value << 1) | (b.value << 3);
+        uint8_t v   = (0xFCFCF400 >> sel) & 3;
+        return lbool(v); }
+
+    friend int   toInt  (lbool l);
+    friend lbool toLbool(int   v);
+};
+inline int   toInt  (lbool l) { return l.value; }
+inline lbool toLbool(int   v) { return lbool((uint8_t)v);  }
+
+//=================================================================================================
+// Clause -- a simple class for representing a clause:
+
+class Clause;
+typedef RegionAllocator<uint32_t>::Ref CRef;
+
+#define BITS_LBD 13
+#define BITS_SIZEWITHOUTSEL 19
+#define BITS_REALSIZE 21
+class Clause {
+    struct {
+      unsigned mark       : 2;
+      unsigned learnt     : 1;
+      unsigned szWithoutSelectors : BITS_SIZEWITHOUTSEL;
+      unsigned canbedel   : 1;
+      unsigned extra_size : 2; // extra size (end of 32bits) 0..3       
+      unsigned size       : BITS_REALSIZE;
+      unsigned seen       : 1;
+      unsigned reloced    : 1;
+      unsigned exported   : 2; // Values to keep track of the clause status for exportations
+      unsigned oneWatched : 1;
+      unsigned lbd : BITS_LBD;
+    }  header;
+
+    union { Lit lit; float act; uint32_t abs; CRef rel; } data[0];
+
+    friend class ClauseAllocator;
+
+    // NOTE: This constructor cannot be used directly (doesn't allocate enough memory).
+    template<class V>
+    Clause(const V& ps, int _extra_size, bool learnt) {
+       assert(_extra_size < (1<<2));
+        header.mark      = 0;
+        header.learnt    = learnt;
+        header.extra_size = _extra_size;
+        header.reloced   = 0;
+        header.size      = ps.size();
+       header.lbd = 0;
+       header.canbedel = 1;
+       header.exported = 0; 
+       header.oneWatched = 0;
+       header.seen = 0;
+        for (int i = 0; i < ps.size(); i++) 
+            data[i].lit = ps[i];
+       
+        if (header.extra_size > 0){
+         if (header.learnt) 
+                data[header.size].act = 0; 
+            else 
+                calcAbstraction();
+         if (header.extra_size > 1) {
+             data[header.size+1].abs = 0; // learntFrom
+         }           
+       }
+    }
+
+public:
+    void calcAbstraction() {
+        assert(header.extra_size > 0);
+        uint32_t abstraction = 0;
+        for (int i = 0; i < size(); i++)
+            abstraction |= 1 << (var(data[i].lit) & 31);
+        data[header.size].abs = abstraction;  }
+
+    int          size        ()      const   { return header.size; }
+    void         shrink      (int i)         { assert(i <= size()); 
+                                               if (header.extra_size > 0) {
+                                                   data[header.size-i] = data[header.size];
+                                                   if (header.extra_size > 1) { // Special case for imported clauses
+                                                       data[header.size-i-1] = data[header.size-1];
+                                                   }
+                                               }
+    header.size -= i; }
+    void         pop         ()              { shrink(1); }
+    bool         learnt      ()      const   { return header.learnt; }
+    bool         has_extra   ()      const   { return header.extra_size > 0; }
+    uint32_t     mark        ()      const   { return header.mark; }
+    void         mark        (uint32_t m)    { header.mark = m; }
+    const Lit&   last        ()      const   { return data[header.size-1].lit; }
+
+    bool         reloced     ()      const   { return header.reloced; }
+    CRef         relocation  ()      const   { return data[0].rel; }
+    void         relocate    (CRef c)        { header.reloced = 1; data[0].rel = c; }
+
+    // NOTE: somewhat unsafe to change the clause in-place! Must manually call 'calcAbstraction' afterwards for
+    //       subsumption operations to behave correctly.
+    Lit&         operator [] (int i)         { return data[i].lit; }
+    Lit          operator [] (int i) const   { return data[i].lit; }
+    operator const Lit* (void) const         { return (Lit*)data; }
+
+    float&       activity    ()              { assert(header.extra_size > 0); return data[header.size].act; }
+    uint32_t     abstraction () const        { assert(header.extra_size > 0); return data[header.size].abs; }
+
+    // Handle imported clauses lazy sharing
+    bool        wasImported() const {return header.extra_size > 1;}
+    uint32_t    importedFrom () const       { assert(header.extra_size > 1); return data[header.size + 1].abs;}
+    void setImportedFrom(uint32_t ifrom) {assert(header.extra_size > 1); data[header.size+1].abs = ifrom;}
+
+    Lit          subsumes    (const Clause& other) const;
+    void         strengthen  (Lit p);
+    void         setLBD(int i)  {if (i < (1<<(BITS_LBD-1))) header.lbd = i; else header.lbd = (1<<(BITS_LBD-1));} 
+    // unsigned int&       lbd    ()              { return header.lbd; }
+    unsigned int        lbd    () const        { return header.lbd; }
+    void setCanBeDel(bool b) {header.canbedel = b;}
+    bool canBeDel() {return header.canbedel;}
+    void setSeen(bool b) {header.seen = b;}
+    bool getSeen() {return header.seen;}
+    void setExported(unsigned int b) {header.exported = b;}
+    unsigned int getExported() {return header.exported;}
+    void setOneWatched(bool b) {header.oneWatched = b;}
+    bool getOneWatched() {return header.oneWatched;}
+    void setSizeWithoutSelectors   (unsigned int n)              {header.szWithoutSelectors = n; }
+    unsigned int        sizeWithoutSelectors   () const        { return header.szWithoutSelectors; }
+
+};
+
+
+//=================================================================================================
+// ClauseAllocator -- a simple class for allocating memory for clauses:
+
+
+const CRef CRef_Undef = RegionAllocator<uint32_t>::Ref_Undef;
+class ClauseAllocator : public RegionAllocator<uint32_t>
+{
+    static int clauseWord32Size(int size, int extra_size){
+        return (sizeof(Clause) + (sizeof(Lit) * (size + extra_size))) / sizeof(uint32_t); }
+ public:
+    bool extra_clause_field;
+
+    ClauseAllocator(uint32_t start_cap) : RegionAllocator<uint32_t>(start_cap), extra_clause_field(false){}
+    ClauseAllocator() : extra_clause_field(false){}
+
+    void moveTo(ClauseAllocator& to){
+        to.extra_clause_field = extra_clause_field;
+        RegionAllocator<uint32_t>::moveTo(to); }
+
+    template<class Lits>
+    CRef alloc(const Lits& ps, bool learnt = false, bool imported = false)
+    {
+        assert(sizeof(Lit)      == sizeof(uint32_t));
+        assert(sizeof(float)    == sizeof(uint32_t));
+       
+        bool use_extra = learnt | extra_clause_field;
+        int extra_size = imported?3:(use_extra?1:0);
+        CRef cid = RegionAllocator<uint32_t>::alloc(clauseWord32Size(ps.size(), extra_size));
+        new (lea(cid)) Clause(ps, extra_size, learnt);
+
+        return cid;
+    }
+
+    // Deref, Load Effective Address (LEA), Inverse of LEA (AEL):
+    Clause&       operator[](Ref r)       { return (Clause&)RegionAllocator<uint32_t>::operator[](r); }
+    const Clause& operator[](Ref r) const { return (Clause&)RegionAllocator<uint32_t>::operator[](r); }
+    Clause*       lea       (Ref r)       { return (Clause*)RegionAllocator<uint32_t>::lea(r); }
+    const Clause* lea       (Ref r) const { return (Clause*)RegionAllocator<uint32_t>::lea(r); }
+    Ref           ael       (const Clause* t){ return RegionAllocator<uint32_t>::ael((uint32_t*)t); }
+
+    void free(CRef cid)
+    {
+        Clause& c = operator[](cid);
+        RegionAllocator<uint32_t>::free(clauseWord32Size(c.size(), c.has_extra()));
+    }
+
+    void reloc(CRef& cr, ClauseAllocator& to)
+    {
+        Clause& c = operator[](cr);
+        
+        if (c.reloced()) { cr = c.relocation(); return; }
+        
+        cr = to.alloc(c, c.learnt(), c.wasImported());
+        c.relocate(cr);
+        
+        // Copy extra data-fields: 
+        // (This could be cleaned-up. Generalize Clause-constructor to be applicable here instead?)
+        to[cr].mark(c.mark());
+        if (to[cr].learnt())        {
+         to[cr].activity() = c.activity();
+         to[cr].setLBD(c.lbd());
+         to[cr].setExported(c.getExported());
+         to[cr].setOneWatched(c.getOneWatched());
+         to[cr].setSeen(c.getSeen());
+         to[cr].setSizeWithoutSelectors(c.sizeWithoutSelectors());
+         to[cr].setCanBeDel(c.canBeDel());
+         if (c.wasImported()) {
+             to[cr].setImportedFrom(c.importedFrom());
+         }
+       }
+        else if (to[cr].has_extra()) to[cr].calcAbstraction();
+    }
+};
+
+
+//=================================================================================================
+// OccLists -- a class for maintaining occurence lists with lazy deletion:
+
+template<class Idx, class Vec, class Deleted>
+class OccLists
+{
+    vec<Vec>  occs;
+    vec<char> dirty;
+    vec<Idx>  dirties;
+    Deleted   deleted;
+
+ public:
+    OccLists(const Deleted& d) : deleted(d) {}
+    
+    void  init      (const Idx& idx){ occs.growTo(toInt(idx)+1); dirty.growTo(toInt(idx)+1, 0); }
+    // Vec&  operator[](const Idx& idx){ return occs[toInt(idx)]; }
+    Vec&  operator[](const Idx& idx){ return occs[toInt(idx)]; }
+    Vec&  lookup    (const Idx& idx){ if (dirty[toInt(idx)]) clean(idx); return occs[toInt(idx)]; }
+
+    void  cleanAll  ();
+    void copyTo(OccLists &copy) const {
+       
+       copy.occs.growTo(occs.size());
+       for(int i = 0;i<occs.size();i++)
+           occs[i].memCopyTo(copy.occs[i]);
+       dirty.memCopyTo(copy.dirty);
+       dirties.memCopyTo(copy.dirties);
+    }
+
+    void  clean     (const Idx& idx);
+    void  smudge    (const Idx& idx){
+        if (dirty[toInt(idx)] == 0){
+            dirty[toInt(idx)] = 1;
+            dirties.push(idx);
+        }
+    }
+
+    void  clear(bool free = true){
+        occs   .clear(free);
+        dirty  .clear(free);
+        dirties.clear(free);
+    }
+};
+
+
+template<class Idx, class Vec, class Deleted>
+void OccLists<Idx,Vec,Deleted>::cleanAll()
+{
+    for (int i = 0; i < dirties.size(); i++)
+        // Dirties may contain duplicates so check here if a variable is already cleaned:
+        if (dirty[toInt(dirties[i])])
+            clean(dirties[i]);
+    dirties.clear();
+}
+
+
+template<class Idx, class Vec, class Deleted>
+void OccLists<Idx,Vec,Deleted>::clean(const Idx& idx)
+{
+    Vec& vec = occs[toInt(idx)];
+    int  i, j;
+    for (i = j = 0; i < vec.size(); i++)
+        if (!deleted(vec[i]))
+            vec[j++] = vec[i];
+    vec.shrink(i - j);
+    dirty[toInt(idx)] = 0;
+}
+
+
+//=================================================================================================
+// CMap -- a class for mapping clauses to values:
+
+
+template<class T>
+class CMap
+{
+    struct CRefHash {
+        uint32_t operator()(CRef cr) const { return (uint32_t)cr; } };
+
+    typedef Map<CRef, T, CRefHash> HashTable;
+    HashTable map;
+        
+ public:
+    // Size-operations:
+    void     clear       ()                           { map.clear(); }
+    int      size        ()                const      { return map.elems(); }
+
+    
+    // Insert/Remove/Test mapping:
+    void     insert      (CRef cr, const T& t){ map.insert(cr, t); }
+    void     growTo      (CRef cr, const T& t){ map.insert(cr, t); } // NOTE: for compatibility
+    void     remove      (CRef cr)            { map.remove(cr); }
+    bool     has         (CRef cr, T& t)      { return map.peek(cr, t); }
+
+    // Vector interface (the clause 'c' must already exist):
+    const T& operator [] (CRef cr) const      { return map[cr]; }
+    T&       operator [] (CRef cr)            { return map[cr]; }
+
+    // Iteration (not transparent at all at the moment):
+    int  bucket_count() const { return map.bucket_count(); }
+    const vec<typename HashTable::Pair>& bucket(int i) const { return map.bucket(i); }
+
+    // Move contents to other map:
+    void moveTo(CMap& other){ map.moveTo(other.map); }
+
+    // TMP debug:
+    void debug(){
+        printf(" --- size = %d, bucket_count = %d\n", size(), map.bucket_count()); }
+};
+
+
+/*_________________________________________________________________________________________________
+|
+|  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)
+    //if (other.size() < size() || (!learnt() && !other.learnt() && (extra.abst & ~other.extra.abst) != 0))
+    assert(!header.learnt);   assert(!other.header.learnt);
+    assert(header.extra_size > 0); assert(other.header.extra_size > 0);
+    if (other.header.size < header.size || (data[header.size].abs & ~other.data[other.header.size].abs) != 0)
+        return lit_Error;
+
+    Lit        ret = lit_Undef;
+    const Lit* c   = (const Lit*)(*this);
+    const Lit* d   = (const Lit*)other;
+
+    for (unsigned i = 0; i < header.size; i++) {
+        // search for c[i] or ~c[i]
+        for (unsigned j = 0; j < other.header.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;
+}
+
+inline void Clause::strengthen(Lit p)
+{
+    remove(*this, p);
+    calcAbstraction();
+}
+//=================================================================================================
+}
+
+#endif
diff --git a/glucose-syrup/mtl/Alg.h b/glucose-syrup/mtl/Alg.h
new file mode 100644 (file)
index 0000000..9afb455
--- /dev/null
@@ -0,0 +1,84 @@
+/*******************************************************************************************[Alg.h]
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef Glucose_Alg_h
+#define Glucose_Alg_h
+
+#include "mtl/Vec.h"
+
+namespace Glucose {
+
+//=================================================================================================
+// Useful functions on vector-like types:
+
+//=================================================================================================
+// Removing and searching for elements:
+//
+
+template<class V, class T>
+static inline void remove(V& ts, const T& t)
+{
+    int j = 0;
+    for (; j < ts.size() && ts[j] != t; j++);
+    assert(j < ts.size());
+    for (; j < ts.size()-1; j++) ts[j] = ts[j+1];
+    ts.pop();
+}
+
+
+template<class V, class T>
+static inline bool find(V& ts, const T& t)
+{
+    int j = 0;
+    for (; j < ts.size() && ts[j] != t; j++);
+    return j < ts.size();
+}
+
+
+//=================================================================================================
+// Copying vectors with support for nested vector types:
+//
+
+// Base case:
+template<class T>
+static inline void copy(const T& from, T& to)
+{
+    to = from;
+}
+
+// Recursive case:
+template<class T>
+static inline void copy(const vec<T>& from, vec<T>& to, bool append = false)
+{
+    if (!append)
+        to.clear();
+    for (int i = 0; i < from.size(); i++){
+        to.push();
+        copy(from[i], to.last());
+    }
+}
+
+template<class T>
+static inline void append(const vec<T>& from, vec<T>& to){ copy(from, to, true); }
+
+//=================================================================================================
+}
+
+#endif
diff --git a/glucose-syrup/mtl/Alloc.h b/glucose-syrup/mtl/Alloc.h
new file mode 100644 (file)
index 0000000..baa6095
--- /dev/null
@@ -0,0 +1,142 @@
+/*****************************************************************************************[Alloc.h]
+Copyright (c) 2008-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+
+#ifndef Glucose_Alloc_h
+#define Glucose_Alloc_h
+
+#include "mtl/XAlloc.h"
+#include "mtl/Vec.h"
+
+namespace Glucose {
+
+//=================================================================================================
+// Simple Region-based memory allocator:
+
+template<class T>
+class RegionAllocator
+{
+    T*        memory;
+    uint32_t  sz;
+    uint32_t  cap;
+    uint32_t  wasted_;
+
+    void capacity(uint32_t min_cap);
+
+ public:
+    // TODO: make this a class for better type-checking?
+    typedef uint32_t Ref;
+    enum { Ref_Undef = UINT32_MAX };
+    enum { Unit_Size = sizeof(uint32_t) };
+
+    explicit RegionAllocator(uint32_t start_cap = 1024*1024) : memory(NULL), sz(0), cap(0), wasted_(0){ capacity(start_cap); }
+    ~RegionAllocator()
+    {
+        if (memory != NULL)
+            ::free(memory);
+    }
+
+
+    uint32_t size      () const      { return sz; }
+    uint32_t getCap    () const      { return cap;}
+    uint32_t wasted    () const      { return wasted_; }
+
+    Ref      alloc     (int size); 
+    void     free      (int size)    { wasted_ += size; }
+
+    // Deref, Load Effective Address (LEA), Inverse of LEA (AEL):
+    T&       operator[](Ref r)       { assert(r >= 0 && r < sz); return memory[r]; }
+    const T& operator[](Ref r) const { assert(r >= 0 && r < sz); return memory[r]; }
+
+    T*       lea       (Ref r)       { assert(r >= 0 && r < sz); return &memory[r]; }
+    const T* lea       (Ref r) const { assert(r >= 0 && r < sz); return &memory[r]; }
+    Ref      ael       (const T* t)  { assert((void*)t >= (void*)&memory[0] && (void*)t < (void*)&memory[sz-1]);
+        return  (Ref)(t - &memory[0]); }
+
+    void     moveTo(RegionAllocator& to) {
+        if (to.memory != NULL) ::free(to.memory);
+        to.memory = memory;
+        to.sz = sz;
+        to.cap = cap;
+        to.wasted_ = wasted_;
+
+        memory = NULL;
+        sz = cap = wasted_ = 0;
+    }
+
+    void copyTo(RegionAllocator& to) const {
+     //   if (to.memory != NULL) ::free(to.memory);
+        to.memory = (T*)xrealloc(to.memory, sizeof(T)*cap);
+        memcpy(to.memory,memory,sizeof(T)*cap);        
+        to.sz = sz;
+        to.cap = cap;
+        to.wasted_ = wasted_;
+    }
+
+
+
+};
+
+template<class T>
+void RegionAllocator<T>::capacity(uint32_t min_cap)
+{
+    if (cap >= min_cap) return;
+
+    uint32_t prev_cap = cap;
+    while (cap < min_cap){
+        // NOTE: Multiply by a factor (13/8) without causing overflow, then add 2 and make the
+        // result even by clearing the least significant bit. The resulting sequence of capacities
+        // is carefully chosen to hit a maximum capacity that is close to the '2^32-1' limit when
+        // using 'uint32_t' as indices so that as much as possible of this space can be used.
+        uint32_t delta = ((cap >> 1) + (cap >> 3) + 2) & ~1;
+        cap += delta;
+
+        if (cap <= prev_cap)
+            throw OutOfMemoryException();
+    }
+    //printf(" .. (%p) cap = %u\n", this, cap);
+
+    assert(cap > 0);
+    memory = (T*)xrealloc(memory, sizeof(T)*cap);
+}
+
+
+template<class T>
+typename RegionAllocator<T>::Ref
+RegionAllocator<T>::alloc(int size)
+{ 
+    //printf("ALLOC called (this = %p, size = %d)\n", this, size); fflush(stdout);
+    assert(size > 0);
+    capacity(sz + size);
+
+    uint32_t prev_sz = sz;
+    sz += size;
+    
+    // Handle overflow:
+    if (sz < prev_sz)
+        throw OutOfMemoryException();
+
+    return prev_sz;
+}
+
+
+//=================================================================================================
+}
+
+#endif
diff --git a/glucose-syrup/mtl/Clone.h b/glucose-syrup/mtl/Clone.h
new file mode 100644 (file)
index 0000000..c0ec225
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef Glucose_Clone_h
+#define Glucose_Clone_h
+
+
+namespace Glucose {
+
+    class Clone {
+        public:
+          virtual Clone* clone() const = 0;
+    };
+};
+
+#endif
\ No newline at end of file
diff --git a/glucose-syrup/mtl/Heap.h b/glucose-syrup/mtl/Heap.h
new file mode 100644 (file)
index 0000000..0c40c4f
--- /dev/null
@@ -0,0 +1,150 @@
+/******************************************************************************************[Heap.h]
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef Glucose_Heap_h
+#define Glucose_Heap_h
+
+#include "mtl/Vec.h"
+
+namespace Glucose {
+
+//=================================================================================================
+// A heap implementation with support for decrease/increase key.
+
+
+template<class Comp>
+class Heap {
+    Comp     lt;       // The heap is a minimum-heap with respect to this comparator
+    vec<int> heap;     // Heap of integers
+    vec<int> indices;  // Each integers position (index) in the Heap
+
+    // Index "traversal" functions
+    static inline int left  (int i) { return i*2+1; }
+    static inline int right (int i) { return (i+1)*2; }
+    static inline int parent(int i) { return (i-1) >> 1; }
+
+
+
+    void percolateUp(int i)
+    {
+        int x  = heap[i];
+        int p  = parent(i);
+        
+        while (i != 0 && lt(x, heap[p])){
+            heap[i]          = heap[p];
+            indices[heap[p]] = i;
+            i                = p;
+            p                = parent(p);
+        }
+        heap   [i] = x;
+        indices[x] = i;
+    }
+
+
+    void percolateDown(int i)
+    {
+        int x = heap[i];
+        while (left(i) < heap.size()){
+            int child = right(i) < heap.size() && lt(heap[right(i)], heap[left(i)]) ? right(i) : left(i);
+            if (!lt(heap[child], x)) break;
+            heap[i]          = heap[child];
+            indices[heap[i]] = i;
+            i                = child;
+        }
+        heap   [i] = x;
+        indices[x] = i;
+    }
+
+
+  public:
+    Heap(const Comp& c) : lt(c) { }
+
+    int  size      ()          const { return heap.size(); }
+    bool empty     ()          const { return heap.size() == 0; }
+    bool inHeap    (int n)     const { return n < indices.size() && indices[n] >= 0; }
+    int  operator[](int index) const { assert(index < heap.size()); return heap[index]; }
+
+
+    void decrease  (int n) { assert(inHeap(n)); percolateUp  (indices[n]); }
+    void increase  (int n) { assert(inHeap(n)); percolateDown(indices[n]); }
+
+    void copyTo(Heap& copy) const {heap.copyTo(copy.heap);indices.copyTo(copy.indices);}
+
+    // Safe variant of insert/decrease/increase:
+    void update(int n)
+    {
+        if (!inHeap(n))
+            insert(n);
+        else {
+            percolateUp(indices[n]);
+            percolateDown(indices[n]); }
+    }
+
+
+    void insert(int n)
+    {
+        indices.growTo(n+1, -1);
+        assert(!inHeap(n));
+
+        indices[n] = heap.size();
+        heap.push(n);
+        percolateUp(indices[n]); 
+    }
+
+
+    int  removeMin()
+    {
+        int x            = heap[0];
+        heap[0]          = heap.last();
+        indices[heap[0]] = 0;
+        indices[x]       = -1;
+        heap.pop();
+        if (heap.size() > 1) percolateDown(0);
+        return x; 
+    }
+
+
+    // Rebuild the heap from scratch, using the elements in 'ns':
+    void build(vec<int>& ns) {
+        for (int i = 0; i < heap.size(); i++)
+            indices[heap[i]] = -1;
+        heap.clear();
+
+        for (int i = 0; i < ns.size(); i++){
+            indices[ns[i]] = i;
+            heap.push(ns[i]); }
+
+        for (int i = heap.size() / 2 - 1; i >= 0; i--)
+            percolateDown(i);
+    }
+
+    void clear(bool dealloc = false) 
+    { 
+        for (int i = 0; i < heap.size(); i++)
+            indices[heap[i]] = -1;
+        heap.clear(dealloc); 
+    }
+};
+
+
+//=================================================================================================
+}
+
+#endif
diff --git a/glucose-syrup/mtl/IntTypes.h b/glucose-syrup/mtl/IntTypes.h
new file mode 100644 (file)
index 0000000..2d8d4e8
--- /dev/null
@@ -0,0 +1,46 @@
+/**************************************************************************************[IntTypes.h]
+Copyright (c) 2009-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef Glucose_IntTypes_h
+#define Glucose_IntTypes_h
+
+#ifdef __sun
+    // Not sure if there are newer versions that support C99 headers. The
+    // needed features are implemented in the headers below though:
+
+#   include <sys/int_types.h>
+#   include <sys/int_fmtio.h>
+#   include <sys/int_limits.h>
+
+#else
+
+#   include <stdint.h>
+#   include <inttypes.h>
+
+#endif
+
+#include <limits.h>
+
+#ifndef PRIu64
+#define PRIu64 "lu"
+#define PRIi64 "ld"
+#endif
+//=================================================================================================
+
+#endif
diff --git a/glucose-syrup/mtl/Map.h b/glucose-syrup/mtl/Map.h
new file mode 100644 (file)
index 0000000..f29ae2d
--- /dev/null
@@ -0,0 +1,193 @@
+/*******************************************************************************************[Map.h]
+Copyright (c) 2006-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef Glucose_Map_h
+#define Glucose_Map_h
+
+#include "mtl/IntTypes.h"
+#include "mtl/Vec.h"
+
+namespace Glucose {
+
+//=================================================================================================
+// Default hash/equals functions
+//
+
+template<class K> struct Hash  { uint32_t operator()(const K& k)               const { return hash(k);  } };
+template<class K> struct Equal { bool     operator()(const K& k1, const K& k2) const { return k1 == k2; } };
+
+template<class K> struct DeepHash  { uint32_t operator()(const K* k)               const { return hash(*k);  } };
+template<class K> struct DeepEqual { bool     operator()(const K* k1, const K* k2) const { return *k1 == *k2; } };
+
+static inline uint32_t hash(uint32_t x){ return x; }
+static inline uint32_t hash(uint64_t x){ return (uint32_t)x; }
+static inline uint32_t hash(int32_t x) { return (uint32_t)x; }
+static inline uint32_t hash(int64_t x) { return (uint32_t)x; }
+
+
+//=================================================================================================
+// Some primes
+//
+
+static const int nprimes          = 25;
+static const int primes [nprimes] = { 31, 73, 151, 313, 643, 1291, 2593, 5233, 10501, 21013, 42073, 84181, 168451, 337219, 674701, 1349473, 2699299, 5398891, 10798093, 21596719, 43193641, 86387383, 172775299, 345550609, 691101253 };
+
+//=================================================================================================
+// Hash table implementation of Maps
+//
+
+template<class K, class D, class H = Hash<K>, class E = Equal<K> >
+class Map {
+ public:
+    struct Pair { K key; D data; };
+
+ private:
+    H          hash;
+    E          equals;
+
+    vec<Pair>* table;
+    int        cap;
+    int        size;
+
+    // Don't allow copying (error prone):
+    Map<K,D,H,E>&  operator = (Map<K,D,H,E>& other) { assert(0); }
+                   Map        (Map<K,D,H,E>& other) { assert(0); }
+
+    bool    checkCap(int new_size) const { return new_size > cap; }
+
+    int32_t index  (const K& k) const { return hash(k) % cap; }
+    void   _insert (const K& k, const D& d) { 
+        vec<Pair>& ps = table[index(k)];
+        ps.push(); ps.last().key = k; ps.last().data = d; }
+
+    void    rehash () {
+        const vec<Pair>* old = table;
+
+        int old_cap = cap;
+        int newsize = primes[0];
+        for (int i = 1; newsize <= cap && i < nprimes; i++)
+           newsize = primes[i];
+
+        table = new vec<Pair>[newsize];
+        cap   = newsize;
+
+        for (int i = 0; i < old_cap; i++){
+            for (int j = 0; j < old[i].size(); j++){
+                _insert(old[i][j].key, old[i][j].data); }}
+
+        delete [] old;
+
+        // printf(" --- rehashing, old-cap=%d, new-cap=%d\n", cap, newsize);
+    }
+
+    
+ public:
+
+    Map () : table(NULL), cap(0), size(0) {}
+    Map (const H& h, const E& e) : hash(h), equals(e), table(NULL), cap(0), size(0){}
+    ~Map () { delete [] table; }
+
+    // PRECONDITION: the key must already exist in the map.
+    const D& operator [] (const K& k) const
+    {
+        assert(size != 0);
+        const D*         res = NULL;
+        const vec<Pair>& ps  = table[index(k)];
+        for (int i = 0; i < ps.size(); i++)
+            if (equals(ps[i].key, k))
+                res = &ps[i].data;
+        assert(res != NULL);
+        return *res;
+    }
+
+    // PRECONDITION: the key must already exist in the map.
+    D& operator [] (const K& k)
+    {
+        assert(size != 0);
+        D*         res = NULL;
+        vec<Pair>& ps  = table[index(k)];
+        for (int i = 0; i < ps.size(); i++)
+            if (equals(ps[i].key, k))
+                res = &ps[i].data;
+        assert(res != NULL);
+        return *res;
+    }
+
+    // PRECONDITION: the key must *NOT* exist in the map.
+    void insert (const K& k, const D& d) { if (checkCap(size+1)) rehash(); _insert(k, d); size++; }
+    bool peek   (const K& k, D& d) const {
+        if (size == 0) return false;
+        const vec<Pair>& ps = table[index(k)];
+        for (int i = 0; i < ps.size(); i++)
+            if (equals(ps[i].key, k)){
+                d = ps[i].data;
+                return true; } 
+        return false;
+    }
+
+    bool has   (const K& k) const {
+        if (size == 0) return false;
+        const vec<Pair>& ps = table[index(k)];
+        for (int i = 0; i < ps.size(); i++)
+            if (equals(ps[i].key, k))
+                return true;
+        return false;
+    }
+
+    // PRECONDITION: the key must exist in the map.
+    void remove(const K& k) {
+        assert(table != NULL);
+        vec<Pair>& ps = table[index(k)];
+        int j = 0;
+        for (; j < ps.size() && !equals(ps[j].key, k); j++);
+        assert(j < ps.size());
+        ps[j] = ps.last();
+        ps.pop();
+        size--;
+    }
+
+    void clear  () {
+        cap = size = 0;
+        delete [] table;
+        table = NULL;
+    }
+
+    int  elems() const { return size; }
+    int  bucket_count() const { return cap; }
+
+    // NOTE: the hash and equality objects are not moved by this method:
+    void moveTo(Map& other){
+        delete [] other.table;
+
+        other.table = table;
+        other.cap   = cap;
+        other.size  = size;
+
+        table = NULL;
+        size = cap = 0;
+    }
+
+    // NOTE: given a bit more time, I could make a more C++-style iterator out of this:
+    const vec<Pair>& bucket(int i) const { return table[i]; }
+};
+
+//=================================================================================================
+}
+
+#endif
diff --git a/glucose-syrup/mtl/Queue.h b/glucose-syrup/mtl/Queue.h
new file mode 100644 (file)
index 0000000..c71e45b
--- /dev/null
@@ -0,0 +1,80 @@
+/*****************************************************************************************[Queue.h]
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef Glucose_Queue_h
+#define Glucose_Queue_h
+
+#include "mtl/Vec.h"
+
+namespace Glucose {
+
+//=================================================================================================
+
+template<class T>
+class Queue {
+    vec<T>  buf;
+    int     first;
+    int     end;
+
+public:
+    typedef T Key;
+
+    Queue() : buf(1), first(0), end(0) {}
+
+    void clear (bool dealloc = false) { buf.clear(dealloc); buf.growTo(1); first = end = 0; }
+    int  size  () const { return (end >= first) ? end - first : end - first + buf.size(); }
+
+    
+    
+    const T& operator [] (int index) const  { assert(index >= 0); assert(index < size()); return buf[(first + index) % buf.size()]; }
+    T&       operator [] (int index)        { assert(index >= 0); assert(index < size()); return buf[(first + index) % buf.size()]; }
+
+    T    peek  () const { assert(first != end); return buf[first]; }
+    void pop   () { assert(first != end); first++; if (first == buf.size()) first = 0; }
+    
+    
+    void copyTo(Queue<T>& copy) const {
+        copy.first = first;
+        copy.end = end;
+        buf.memCopyTo(copy.buf);
+    }
+    
+    
+    void insert(T elem) {   // INVARIANT: buf[end] is always unused
+        buf[end++] = elem;
+        if (end == buf.size()) end = 0;
+        if (first == end){  // Resize:
+            vec<T>  tmp((buf.size()*3 + 1) >> 1);
+            //**/printf("queue alloc: %d elems (%.1f MB)\n", tmp.size(), tmp.size() * sizeof(T) / 1000000.0);
+            int     i = 0;
+            for (int j = first; j < buf.size(); j++) tmp[i++] = buf[j];
+            for (int j = 0    ; j < end       ; j++) tmp[i++] = buf[j];
+            first = 0;
+            end   = buf.size();
+            tmp.moveTo(buf);
+        }
+    }
+};
+
+
+//=================================================================================================
+}
+
+#endif
diff --git a/glucose-syrup/mtl/Sort.h b/glucose-syrup/mtl/Sort.h
new file mode 100644 (file)
index 0000000..50cb448
--- /dev/null
@@ -0,0 +1,98 @@
+/******************************************************************************************[Sort.h]
+Copyright (c) 2003-2007, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef Glucose_Sort_h
+#define Glucose_Sort_h
+
+#include "mtl/Vec.h"
+
+//=================================================================================================
+// Some sorting algorithms for vec's
+
+
+namespace Glucose {
+
+template<class T>
+struct LessThan_default {
+    bool operator () (T x, T y) { return x < y; }
+};
+
+
+template <class T, class LessThan>
+void selectionSort(T* array, int size, LessThan lt)
+{
+    int     i, j, best_i;
+    T       tmp;
+
+    for (i = 0; i < size-1; i++){
+        best_i = i;
+        for (j = i+1; j < size; j++){
+            if (lt(array[j], array[best_i]))
+                best_i = j;
+        }
+        tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp;
+    }
+}
+template <class T> static inline void selectionSort(T* array, int size) {
+    selectionSort(array, size, LessThan_default<T>()); }
+
+template <class T, class LessThan>
+void sort(T* array, int size, LessThan lt)
+{
+    if (size <= 15)
+        selectionSort(array, size, lt);
+
+    else{
+        T           pivot = array[size / 2];
+        T           tmp;
+        int         i = -1;
+        int         j = size;
+
+        for(;;){
+            do i++; while(lt(array[i], pivot));
+            do j--; while(lt(pivot, array[j]));
+
+            if (i >= j) break;
+
+            tmp = array[i]; array[i] = array[j]; array[j] = tmp;
+        }
+
+        sort(array    , i     , lt);
+        sort(&array[i], size-i, lt);
+    }
+}
+template <class T> static inline void sort(T* array, int size) {
+    sort(array, size, LessThan_default<T>()); }
+
+
+//=================================================================================================
+// For 'vec's:
+
+
+template <class T, class LessThan> void sort(vec<T>& v, LessThan lt) {
+    sort((T*)v, v.size(), lt); }
+template <class T> void sort(vec<T>& v) {
+    sort(v, LessThan_default<T>()); }
+
+
+//=================================================================================================
+}
+
+#endif
diff --git a/glucose-syrup/mtl/Vec.h b/glucose-syrup/mtl/Vec.h
new file mode 100644 (file)
index 0000000..954eef7
--- /dev/null
@@ -0,0 +1,137 @@
+/*******************************************************************************************[Vec.h]
+Copyright (c) 2003-2007, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef Glucose_Vec_h
+#define Glucose_Vec_h
+
+#include <assert.h>
+#include <new>
+
+#include "mtl/IntTypes.h"
+#include "mtl/XAlloc.h"
+#include<string.h>
+
+namespace Glucose {
+
+//=================================================================================================
+// Automatically resizable arrays
+//
+// NOTE! Don't use this vector on datatypes that cannot be re-located in memory (with realloc)
+
+template<class T>
+class vec {
+    T*  data;
+    int sz;
+    int cap;
+
+    // Don't allow copying (error prone):
+    vec<T>&  operator = (vec<T>& other) { assert(0); return *this; }
+             vec        (vec<T>& other) { assert(0); }
+             
+    // Helpers for calculating next capacity:
+    static inline int  imax   (int x, int y) { int mask = (y-x) >> (sizeof(int)*8-1); return (x&mask) + (y&(~mask)); }
+    //static inline void nextCap(int& cap){ cap += ((cap >> 1) + 2) & ~1; }
+    static inline void nextCap(int& cap){ cap += ((cap >> 1) + 2) & ~1; }
+
+public:
+    // Constructors:
+    vec()                       : data(NULL) , sz(0)   , cap(0)    { }
+    explicit vec(int size)      : data(NULL) , sz(0)   , cap(0)    { growTo(size); }
+    vec(int size, const T& pad) : data(NULL) , sz(0)   , cap(0)    { growTo(size, pad); }
+   ~vec()                                                          { clear(true); }
+
+    // Pointer to first element:
+    operator T*       (void)           { return data; }
+
+    // Size operations:
+    int      size     (void) const     { return sz; }
+    void     shrink   (int nelems)     { assert(nelems <= sz); for (int i = 0; i < nelems; i++) sz--, data[sz].~T(); }
+    void     shrink_  (int nelems)     { assert(nelems <= sz); sz -= nelems; }
+    int      capacity (void) const     { return cap; }
+    void     capacity (int min_cap);
+    void     growTo   (int size);
+    void     growTo   (int size, const T& pad);
+    void     clear    (bool dealloc = false);
+
+    // Stack interface:
+    void     push  (void)              { if (sz == cap) capacity(sz+1); new (&data[sz]) T(); sz++; }
+    void     push  (const T& elem)     { if (sz == cap) capacity(sz+1); data[sz++] = elem; }
+    void     push_ (const T& elem)     { assert(sz < cap); data[sz++] = elem; }
+    void     pop   (void)              { assert(sz > 0); sz--, data[sz].~T(); }
+    // NOTE: it seems possible that overflow can happen in the 'sz+1' expression of 'push()', but
+    // in fact it can not since it requires that 'cap' is equal to INT_MAX. This in turn can not
+    // happen given the way capacities are calculated (below). Essentially, all capacities are
+    // even, but INT_MAX is odd.
+
+    const T& last  (void) const        { return data[sz-1]; }
+    T&       last  (void)              { return data[sz-1]; }
+
+    // Vector interface:
+    const T& operator [] (int index) const { return data[index]; }
+    T&       operator [] (int index)       { return data[index]; }
+
+    // Duplicatation (preferred instead):
+    void copyTo(vec<T>& copy) const { copy.clear(); copy.growTo(sz); for (int i = 0; i < sz; i++) copy[i] = data[i]; }
+    void moveTo(vec<T>& dest) { dest.clear(true); dest.data = data; dest.sz = sz; dest.cap = cap; data = NULL; sz = 0; cap = 0; }
+    void memCopyTo(vec<T>& copy) const{
+        copy.capacity(cap);
+        copy.sz = sz;
+        memcpy(copy.data,data,sizeof(T)*cap);
+    }
+
+};
+
+
+template<class T>
+void vec<T>::capacity(int min_cap) {
+    if (cap >= min_cap) return;
+    int add = imax((min_cap - cap + 1) & ~1, ((cap >> 1) + 2) & ~1);   // NOTE: grow by approximately 3/2
+    if (add > INT_MAX - cap || ((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM)
+        throw OutOfMemoryException();
+ }
+
+
+template<class T>
+void vec<T>::growTo(int size, const T& pad) {
+    if (sz >= size) return;
+    capacity(size);
+    for (int i = sz; i < size; i++) data[i] = pad;
+    sz = size; }
+
+
+template<class T>
+void vec<T>::growTo(int size) {
+    if (sz >= size) return;
+    capacity(size);
+    for (int i = sz; i < size; i++) new (&data[i]) T();
+    sz = size; }
+
+
+template<class T>
+void vec<T>::clear(bool dealloc) {
+    if (data != NULL){
+        for (int i = 0; i < sz; i++) data[i].~T();
+        sz = 0;
+        if (dealloc) free(data), data = NULL, cap = 0; } }
+
+//=================================================================================================
+}
+
+#endif
diff --git a/glucose-syrup/mtl/XAlloc.h b/glucose-syrup/mtl/XAlloc.h
new file mode 100644 (file)
index 0000000..f8ca4fe
--- /dev/null
@@ -0,0 +1,47 @@
+/****************************************************************************************[XAlloc.h]
+Copyright (c) 2009-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+
+#ifndef Glucose_XAlloc_h
+#define Glucose_XAlloc_h
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+namespace Glucose {
+
+//=================================================================================================
+// Simple layer on top of malloc/realloc to catch out-of-memory situtaions and provide some typing:
+
+class OutOfMemoryException{};
+static inline void* xrealloc(void *ptr, size_t size)
+{
+    void* mem = realloc(ptr, size);
+    if (mem == NULL && errno == ENOMEM){
+        throw OutOfMemoryException();
+    }else {
+        return mem;
+       }
+}
+
+//=================================================================================================
+}
+
+#endif
diff --git a/glucose-syrup/mtl/config.mk b/glucose-syrup/mtl/config.mk
new file mode 100644 (file)
index 0000000..b5c36fc
--- /dev/null
@@ -0,0 +1,6 @@
+##
+##  This file is for system specific configurations. For instance, on
+##  some systems the path to zlib needs to be added. Example:
+##
+##  CFLAGS += -I/usr/local/include
+##  LFLAGS += -L/usr/local/lib
diff --git a/glucose-syrup/mtl/template.mk b/glucose-syrup/mtl/template.mk
new file mode 100644 (file)
index 0000000..6727559
--- /dev/null
@@ -0,0 +1,107 @@
+##
+##  Template makefile for Standard, Profile, Debug, Release, and Release-static versions
+##
+##    eg: "make rs" for a statically linked release version.
+##        "make d"  for a debug version (no optimizations).
+##        "make"    for the standard version (optimized, but with debug information and assertions active)
+
+PWD        = $(shell pwd)
+EXEC      ?= $(notdir $(PWD))
+
+CSRCS      = $(wildcard $(PWD)/*.cc) 
+DSRCS      = $(foreach dir, $(DEPDIR), $(filter-out $(MROOT)/$(dir)/Main.cc, $(wildcard $(MROOT)/$(dir)/*.cc)))
+CHDRS      = $(wildcard $(PWD)/*.h)
+COBJS      = $(CSRCS:.cc=.o) $(DSRCS:.cc=.o)
+
+PCOBJS     = $(addsuffix p,  $(COBJS))
+DCOBJS     = $(addsuffix d,  $(COBJS))
+RCOBJS     = $(addsuffix r,  $(COBJS))
+
+#CXX        ?= /usr/gcc-/bin/g++-4.7.0
+CXX       ?= g++
+CFLAGS    ?= -Wall -Wno-parentheses -std=c++11
+LFLAGS    ?= -Wall -lpthread 
+
+COPTIMIZE ?= -O3
+
+CFLAGS    += -I$(MROOT) -D __STDC_LIMIT_MACROS -D __STDC_FORMAT_MACROS
+LFLAGS    += -lz
+
+.PHONY : s p d r rs clean 
+
+s:     $(EXEC)
+p:     $(EXEC)_profile
+d:     $(EXEC)_debug
+r:     $(EXEC)_release
+rs:    $(EXEC)_static
+
+libs:  lib$(LIB)_standard.a
+libp:  lib$(LIB)_profile.a
+libd:  lib$(LIB)_debug.a
+libr:  lib$(LIB)_release.a
+
+## Compile options
+%.o:                   CFLAGS +=$(COPTIMIZE) -g -D DEBUG
+%.op:                  CFLAGS +=$(COPTIMIZE) -pg -g -D NDEBUG
+%.od:                  CFLAGS +=-O0 -g -D DEBUG
+%.or:                  CFLAGS +=$(COPTIMIZE) -g -D NDEBUG
+
+## Link options
+$(EXEC):               LFLAGS += -g
+$(EXEC)_profile:       LFLAGS += -g -pg
+$(EXEC)_debug:         LFLAGS += -g
+#$(EXEC)_release:      LFLAGS += ...
+$(EXEC)_static:                LFLAGS += --static
+
+## Dependencies
+$(EXEC):               $(COBJS)
+$(EXEC)_profile:       $(PCOBJS)
+$(EXEC)_debug:         $(DCOBJS)
+$(EXEC)_release:       $(RCOBJS)
+$(EXEC)_static:                $(RCOBJS)
+
+lib$(LIB)_standard.a:  $(filter-out */Main.o,  $(COBJS))
+lib$(LIB)_profile.a:   $(filter-out */Main.op, $(PCOBJS))
+lib$(LIB)_debug.a:     $(filter-out */Main.od, $(DCOBJS))
+lib$(LIB)_release.a:   $(filter-out */Main.or, $(RCOBJS))
+
+
+## Build rule
+%.o %.op %.od %.or:    %.cc
+       @echo Compiling: $(subst $(MROOT)/,,$@)
+       @$(CXX) $(CFLAGS) -c -o $@ $<
+
+## Linking rules (standard/profile/debug/release)
+$(EXEC) $(EXEC)_profile $(EXEC)_debug $(EXEC)_release $(EXEC)_static:
+       @echo Linking: "$@ ( $(foreach f,$^,$(subst $(MROOT)/,,$f)) )"
+       @$(CXX) $^ $(LFLAGS) -o $@
+
+## Library rules (standard/profile/debug/release)
+lib$(LIB)_standard.a lib$(LIB)_profile.a lib$(LIB)_release.a lib$(LIB)_debug.a:
+       @echo Making library: "$@ ( $(foreach f,$^,$(subst $(MROOT)/,,$f)) )"
+       @$(AR) -rcsv $@ $^
+
+## Library Soft Link rule:
+libs libp libd libr:
+       @echo "Making Soft Link: $^ -> lib$(LIB).a"
+       @ln -sf $^ lib$(LIB).a
+
+## Clean rule
+clean:
+       @rm -f $(EXEC) $(EXEC)_profile $(EXEC)_debug $(EXEC)_release $(EXEC)_static \
+         $(COBJS) $(PCOBJS) $(DCOBJS) $(RCOBJS) *.core depend.mk 
+
+## Make dependencies
+depend.mk: $(CSRCS) $(CHDRS)
+       @echo Making dependencies
+       @$(CXX) $(CFLAGS) -I$(MROOT) \
+          $(CSRCS) -MM | sed 's|\(.*\):|$(PWD)/\1 $(PWD)/\1r $(PWD)/\1d $(PWD)/\1p:|' > depend.mk
+       @for dir in $(DEPDIR); do \
+             if [ -r $(MROOT)/$${dir}/depend.mk ]; then \
+                 echo Depends on: $${dir}; \
+                 cat $(MROOT)/$${dir}/depend.mk >> depend.mk; \
+             fi; \
+         done
+
+-include $(MROOT)/mtl/config.mk
+-include depend.mk
diff --git a/glucose-syrup/parallel/ClausesBuffer.cc b/glucose-syrup/parallel/ClausesBuffer.cc
new file mode 100644 (file)
index 0000000..5b18767
--- /dev/null
@@ -0,0 +1,235 @@
+/**********************************************************************************[ClausesBuffer.cc]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+/* ClausesBuffer
+ *
+ * This class is responsible for exchanging clauses between threads.
+ * It is based on a fixed-length FIFO array of literals.
+ * If the FIFO is full, then old clauses are removed (even if it was not yet sent to all threads)
+ *
+ * a clause " l1 l2 l3" is pushed in the FIFO with the following 6 unsigned integers
+ * 3 nseen origin l1 l2 l3
+ * + 3 is the size of the pushed clause
+ * + nseen is the number of thread which imported this clause (initialized with nthreads-1)
+ *       (when set to 0, the clause is removed from the fifo)
+ * + origin is the thread id of the thread which added this clause to the fifo
+ * + l1 l2 l3 are the literals of the clause
+ *
+ * **********************************************************************************************
+ * **CAREFUL** This class is not thread-safe. In glucose-syrup, the SharedCompanion is 
+ * responsible for ensuring atomicity of main functions
+ * **********************************************************************************************
+ *
+ * */
+
+#include "parallel/ClausesBuffer.h"
+
+//=================================================================================================
+
+using namespace Glucose;
+
+extern BoolOption opt_whenFullRemoveOlder;
+extern IntOption  opt_fifoSizeByCore;
+
+// index : size clause
+// index + 1 : nbSeen
+// index + 2 : threadId
+// index + 3 : .. index + 3 + size : Lit of clause
+ClausesBuffer::ClausesBuffer(int _nbThreads, unsigned int _maxsize) : first(0), last(_maxsize-1),  
+    maxsize(_maxsize), queuesize(0), 
+    removedClauses(0),
+    forcedRemovedClauses(0), nbThreads(_nbThreads), 
+    whenFullRemoveOlder(opt_whenFullRemoveOlder), fifoSizeByCore(opt_fifoSizeByCore) {
+       lastOfThread.growTo(_nbThreads);
+       for(int i=0;i<nbThreads;i++) lastOfThread[i] = _maxsize-1;
+       elems.growTo(maxsize);
+} 
+
+ClausesBuffer::ClausesBuffer() : first(0), last(0), maxsize(0), queuesize(0), removedClauses(0), forcedRemovedClauses(0), nbThreads(0),
+                                 whenFullRemoveOlder(opt_whenFullRemoveOlder), fifoSizeByCore(opt_fifoSizeByCore) {}
+
+void ClausesBuffer::setNbThreads(int _nbThreads) {
+    unsigned int _maxsize = fifoSizeByCore*_nbThreads;
+    last = _maxsize -1;
+    maxsize = _maxsize;
+    nbThreads = _nbThreads;
+    lastOfThread.growTo(_nbThreads);
+    for(int i=0;i<nbThreads;i++) lastOfThread[i] = _maxsize-1;
+    elems.growTo(maxsize);
+}
+
+uint32_t ClausesBuffer::getCap() {
+    return elems.capacity();
+}
+inline unsigned int ClausesBuffer::nextIndex(unsigned int i) {
+    i++;
+    if (i == maxsize)
+       return 0;
+    return i;
+}
+
+inline unsigned int ClausesBuffer::addIndex(unsigned int i, unsigned int a) {
+    i += a;
+    if (i >= maxsize)
+       return i - maxsize;
+    return i;
+}
+
+void ClausesBuffer::removeLastClause() {
+    assert(queuesize > 0);
+    do {
+       unsigned int size = (unsigned int) elems[nextIndex(last)];
+       unsigned int nextlast = addIndex(last, size+headerSize);
+
+       for(int i=0;i<nbThreads;i++) {
+           if (lastOfThread[i] == last)
+               lastOfThread[i] = nextlast;
+       }
+
+       // printf("Removing clause starting at %d of size %d.\n",nextIndex(last), size);
+       for(unsigned int i=0;i<size+headerSize;i++) {
+           last = nextIndex(last);
+           assert(queuesize > 0);
+           queuesize --;
+       }       
+       removedClauses ++;
+       assert(last >= 0);
+       assert(last < maxsize);
+       assert(last == nextlast);
+    } while (queuesize > 0 && (elems[addIndex(last,2)] == 0));         
+
+}
+
+
+// Pushes a single uint to the fifo
+inline void ClausesBuffer::noCheckPush(uint32_t x) {
+    elems[first] = x;
+    first = nextIndex(first);
+}
+
+// Pops a single uint from the fifo
+inline uint32_t ClausesBuffer::noCheckPop(uint32_t & index) {
+    index = nextIndex(index);
+    uint32_t ret = elems[index];
+    return ret;
+}
+
+
+
+// Return true if the clause was succesfully added
+bool ClausesBuffer::pushClause(int threadId, Clause & c) {
+    if (!whenFullRemoveOlder && (queuesize + c.size() + headerSize >= maxsize))
+       return false; // We need to remove some old clauses
+    while (queuesize + c.size() + headerSize >= maxsize) { // We need to remove some old clauses
+       forcedRemovedClauses ++;
+       removeLastClause();
+       assert(queuesize > 0);
+    }
+    noCheckPush(c.size());
+    noCheckPush(nbThreads>1?nbThreads-1:1);
+    noCheckPush(threadId);
+    for(int i=0;i<c.size();i++)
+       noCheckPush(toInt(c[i]));
+    queuesize += c.size()+headerSize;
+    return true;
+    //  printf(" -> (%d, %d)\n", first, last);
+}
+
+bool ClausesBuffer::getClause(int threadId, int & threadOrigin, vec<Lit> & resultClause,  bool firstFound) {
+    assert(lastOfThread.size() > threadId);
+    unsigned int thislast = lastOfThread[threadId];
+    assert(!firstFound || thislast == last); // FIXME: Gilles has this assertion on his cluster
+
+    // Early exiting
+    if (nextIndex(thislast) == first) return false;
+
+    if ( ( thislast < last && last < first) ||
+           ( first < thislast && thislast < last ) ||
+           ( last < first && first < thislast) ) {
+       // Special case where last has moved and lastOfThread[threadId] is no more valid (is behind)
+       thislast = last; 
+    }
+    assert(!firstFound);
+    // Go to next clause for this thread id
+    if (!firstFound) { 
+       while (nextIndex(thislast) != first && elems[addIndex(thislast,3)] == ((unsigned int)threadId)) { // 3 = 2 + 1 
+           thislast = addIndex(thislast, elems[nextIndex(thislast)] + headerSize); // 
+           assert(thislast >= 0);
+           assert(thislast < maxsize);
+       }
+       assert(nextIndex(thislast)==first || elems[addIndex(thislast,3)] != (unsigned int)threadId);
+    }
+
+    if (nextIndex(thislast) == first) {
+       lastOfThread[threadId] = thislast;
+       return false;
+    }  
+    assert(elems[addIndex(thislast,3)] != ((unsigned int) threadId));
+    unsigned int previouslast = thislast;
+    bool removeAfter = false;
+    int csize = noCheckPop(thislast);
+    removeAfter = (--elems[addIndex(thislast,1)] == 0); // We are sure this is not one of our own clause
+    thislast = nextIndex(thislast); // Skips the removeAfter fieldr
+    threadOrigin = noCheckPop(thislast);
+    assert(threadOrigin != threadId);
+    resultClause.clear();
+    for(int i=0;i<csize;i++) {
+       resultClause.push(toLit(noCheckPop(thislast)));
+    }
+    if (last == previouslast && removeAfter) {
+       removeLastClause();
+       thislast = last;
+    }
+    lastOfThread[threadId] = thislast;
+    return true;
+}
+
+
+//=================================================================================================
+
diff --git a/glucose-syrup/parallel/ClausesBuffer.h b/glucose-syrup/parallel/ClausesBuffer.h
new file mode 100644 (file)
index 0000000..171506d
--- /dev/null
@@ -0,0 +1,114 @@
+/***************************************************************************************[ClausesBuffer.h]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+#ifndef ClausesBuffer_h 
+#define ClausesBuffer_h
+
+#include "mtl/Vec.h"
+#include "core/SolverTypes.h"
+#include "core/Solver.h"
+
+//=================================================================================================
+
+namespace Glucose {
+    // index : size clause
+    // index + 1 : nbSeen
+    // index + 2 : threadId
+    // index + 3 : .. index + 3 + size : Lit of clause
+    class ClausesBuffer {
+       vec<uint32_t>  elems;
+       unsigned int     first;
+       unsigned int     last;
+       unsigned int     maxsize;
+       unsigned int     queuesize; // Number of current elements (must be < maxsize !)
+       unsigned int     removedClauses;
+       unsigned int     forcedRemovedClauses;
+        static const int  headerSize = 3;
+       int       nbThreads;
+       bool      whenFullRemoveOlder;
+       unsigned int fifoSizeByCore;
+       vec<unsigned int> lastOfThread; // Last value for a thread 
+
+       public:
+       ClausesBuffer(int _nbThreads, unsigned int _maxsize);
+       ClausesBuffer();
+
+       void setNbThreads(int _nbThreads);
+       unsigned int nextIndex(unsigned int i);
+       unsigned int addIndex(unsigned int i, unsigned int a); 
+       void removeLastClause(); 
+          
+       void noCheckPush(uint32_t x);
+       uint32_t noCheckPop(unsigned int & index);
+
+       // Return true if the clause was succesfully added
+        bool pushClause(int threadId, Clause & c);
+        bool getClause(int threadId, int & threadOrigin, vec<Lit> & resultClause, bool firstFound = false); 
+       
+       int maxSize() const {return maxsize;}
+        uint32_t getCap();
+       void growTo(int size) {
+           assert(0); // Not implemented (essentially for efficiency reasons)
+           elems.growTo(size); 
+           first=0; maxsize=size; queuesize = 0;last = 0;
+           for(int i=0;i<size;i++) elems[i]=0; 
+       }
+
+       void fastclear() {first = 0; last = 0; queuesize=0; } 
+
+       int  size(void)    { return queuesize; }
+
+       void clear(bool dealloc = false)   { elems.clear(dealloc); first = 0; maxsize=0; queuesize=0;}
+       inline  int  toInt     (Lit p)              { return p.x; } 
+
+    };
+}
+//=================================================================================================
+
+#endif
diff --git a/glucose-syrup/parallel/Main.cc b/glucose-syrup/parallel/Main.cc
new file mode 100644 (file)
index 0000000..d3ae7f7
--- /dev/null
@@ -0,0 +1,254 @@
+/***************************************************************************************[Main.cc]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+#include <errno.h>
+
+#include <signal.h>
+#include <zlib.h>
+
+
+#include "utils/System.h"
+#include "utils/ParseUtils.h"
+#include "utils/Options.h"
+#include "core/Dimacs.h"
+#include "core/SolverTypes.h"
+
+#include "simp/SimpSolver.h"
+#include "parallel/ParallelSolver.h"
+#include "parallel/MultiSolvers.h"
+
+using namespace Glucose;
+
+
+
+static MultiSolvers* pmsolver;
+
+// Terminate by notifying the solver and back out gracefully. This is mainly to have a test-case
+// for this feature of the Solver as it may take longer than an immediate call to '_exit()'.
+//static void SIGINT_interrupt(int signum) { pmsolver->interrupt(); }
+
+
+// Note that '_exit()' rather than 'exit()' has to be used. The reason is that 'exit()' calls
+// destructors and may cause deadlocks if a malloc/free function happens to be running (these
+// functions are guarded by locks for multithreaded use).
+static void SIGINT_exit(int signum) {
+    printf("\n"); printf("*** INTERRUPTED ***\n");
+    if (pmsolver->verbosity() > 0){
+        pmsolver->printFinalStats();
+        printf("\n"); printf("*** INTERRUPTED ***\n"); }
+    _exit(1); }
+
+
+//=================================================================================================
+// Main:
+
+
+int main(int argc, char** argv)
+{
+    double realTimeStart = realTime();
+  printf("c\nc This is glucose-syrup 4.0 (glucose in many threads) --  based on MiniSAT (Many thanks to MiniSAT team)\nc\n");
+    try {
+        setUsageHelp("c USAGE: %s [options] <input-file> <result-output-file>\n\n  where input may be either in plain or gzipped DIMACS.\n");
+        // printf("This is MiniSat 2.0 beta\n");
+        
+#if defined(__linux__)
+        fpu_control_t oldcw, newcw;
+        _FPU_GETCW(oldcw); newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE; _FPU_SETCW(newcw);
+        printf("c WARNING: for repeatability, setting FPU to use double precision\n");
+#endif
+        // Extra options:
+        //
+        IntOption    verb   ("MAIN", "verb",   "Verbosity level (0=silent, 1=some, 2=more).", 1, IntRange(0, 2));
+        BoolOption   mod   ("MAIN", "model",   "show model.", false);
+        IntOption    vv  ("MAIN", "vv",   "Verbosity every vv conflicts", 10000, IntRange(1,INT32_MAX));
+        IntOption    cpu_lim("MAIN", "cpu-lim","Limit on CPU time allowed in seconds.\n", INT32_MAX, IntRange(0, INT32_MAX));
+        IntOption    mem_lim("MAIN", "mem-lim","Limit on memory usage in megabytes.\n", INT32_MAX, IntRange(0, INT32_MAX));
+        
+        parseOptions(argc, argv, true);
+
+       MultiSolvers msolver;
+        pmsolver = & msolver;
+        msolver.setVerbosity(verb);
+        msolver.setVerbEveryConflicts(vv);
+        msolver.setShowModel(mod);
+
+        double initial_time = cpuTime();
+
+               // Use signal handlers that forcibly quit until the solver will be able to respond to
+        // interrupts:
+       signal(SIGINT, SIGINT_exit);
+        signal(SIGXCPU,SIGINT_exit);
+
+        // Set limit on CPU-time:
+        if (cpu_lim != INT32_MAX){
+            rlimit rl;
+            getrlimit(RLIMIT_CPU, &rl);
+            if (rl.rlim_max == RLIM_INFINITY || (rlim_t)cpu_lim < rl.rlim_max){
+                rl.rlim_cur = cpu_lim;
+                if (setrlimit(RLIMIT_CPU, &rl) == -1)
+                    printf("c WARNING! Could not set resource limit: CPU-time.\n");
+            } }
+
+        // Set limit on virtual memory:
+        if (mem_lim != INT32_MAX){
+            rlim_t new_mem_lim = (rlim_t)mem_lim * 1024*1024;
+            rlimit rl;
+            getrlimit(RLIMIT_AS, &rl);
+            if (rl.rlim_max == RLIM_INFINITY || new_mem_lim < rl.rlim_max){
+                rl.rlim_cur = new_mem_lim;
+                if (setrlimit(RLIMIT_AS, &rl) == -1)
+                    printf("c WARNING! Could not set resource limit: Virtual memory.\n");
+            } }
+        
+        if (argc == 1)
+            printf("c Reading from standard input... Use '--help' for help.\n");
+        
+        gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb");
+        if (in == NULL)
+            printf("c ERROR! Could not open file: %s\n", argc == 1 ? "<stdin>" : argv[1]), exit(1);
+        
+        if (msolver.verbosity() > 0){
+            printf("c ========================================[ Problem Statistics ]===========================================\n");
+            printf("c |                                                                                                       |\n"); }
+        
+        parse_DIMACS(in, msolver);
+        gzclose(in);
+        
+
+       
+        FILE* res = (argc >= 3) ? fopen(argv[argc-1], "wb") : NULL;
+
+        if (msolver.verbosity() > 0){
+            printf("c |  Number of variables:  %12d                                                                   |\n", msolver.nVars());
+            printf("c |  Number of clauses:    %12d                                                                   |\n", msolver.nClauses()); }
+        
+        double parsed_time = cpuTime();
+        if (msolver.verbosity() > 0){
+            printf("c |  Parse time:           %12.2f s                                                                 |\n", parsed_time - initial_time);
+            printf("c |                                                                                                       |\n"); }
+        // Change to signal-handlers that will only notify the solver and allow it to terminate
+        // voluntarily:
+        //signal(SIGINT, SIGINT_interrupt);
+        //signal(SIGXCPU,SIGINT_interrupt);
+        
+       int ret2 = msolver.simplify();          
+        if(ret2) 
+          msolver.eliminate();
+        double simplified_time = cpuTime();
+        if (msolver.verbosity() > 0){
+            printf("c |  Simplification time:  %12.2f s                                                                 |\n", simplified_time - parsed_time);
+            printf("c |                                                                                                       |\n"); }
+
+        if (!ret2 || !msolver.okay()){
+            //if (S.certifiedOutput != NULL) fprintf(S.certifiedOutput, "0\n"), fclose(S.certifiedOutput);
+            if (res != NULL) fprintf(res, "UNSAT\n"), fclose(res);
+            if (msolver.verbosity() > 0){
+               printf("c =========================================================================================================\n");
+                printf("Solved by unit propagation\n"); 
+               printf("c real time : %g s\n", realTime() - realTimeStart);
+               printf("c cpu time  : %g s\n", cpuTime());
+                printf("\n"); }
+            printf("s UNSATISFIABLE\n");
+            exit(20);
+        }
+
+      //  vec<Lit> dummy;
+        lbool ret = msolver.solve();
+       
+       
+        printf("c\n");
+       printf("c real time : %g s\n", realTime() - realTimeStart);
+       printf("c cpu time  : %g s\n", cpuTime());
+        if (msolver.verbosity() > 0){
+            msolver.printFinalStats();
+            printf("\n"); }
+
+       //-------------- Result is put in a external file
+       /* I must admit I have to print the model of one thread... But which one? FIXME !!
+         if (res != NULL){  
+         if (ret == l_True){
+           fprintf(res, "SAT\n");
+           for (int i = 0; i < S.nVars(); i++)
+             if (S.model[i] != l_Undef)
+               fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1);
+           fprintf(res, " 0\n");
+         }else if (ret == l_False)
+           fprintf(res, "UNSAT\n");
+         else
+           fprintf(res, "INDET\n");
+         fclose(res);
+       
+       //-------------- Want certified output
+        } else { 
+       */
+         printf(ret == l_True ? "s SATISFIABLE\n" : ret == l_False ? "s UNSATISFIABLE\n" : "s INDETERMINATE\n");
+         
+         if(msolver.getShowModel() && ret==l_True) {
+           printf("v ");
+           for (int i = 0; i < msolver.model.size() ; i++)
+             if (msolver.model[i] != l_Undef)
+               printf("%s%s%d", (i==0)?"":" ", (msolver.model[i]==l_True)?"":"-", i+1);
+           printf(" 0\n");
+         }
+
+     
+    
+#ifdef NDEBUG
+        exit(ret == l_True ? 10 : ret == l_False ? 20 : 0);     // (faster than "return", which will invoke the destructor for 'Solver')
+#else
+        return (ret == l_True ? 10 : ret == l_False ? 20 : 0);
+#endif
+    } catch (OutOfMemoryException&){
+      printf("c ===================================================================================================\n");
+        printf("INDETERMINATE\n");
+        exit(0);
+    }
+}
diff --git a/glucose-syrup/parallel/Makefile b/glucose-syrup/parallel/Makefile
new file mode 100644 (file)
index 0000000..0da6c25
--- /dev/null
@@ -0,0 +1,4 @@
+EXEC      = glucose-syrup
+DEPDIR    = mtl utils core simp
+MROOT = $(PWD)/..
+include $(MROOT)/mtl/template.mk
diff --git a/glucose-syrup/parallel/MultiSolvers.cc b/glucose-syrup/parallel/MultiSolvers.cc
new file mode 100644 (file)
index 0000000..b0c1949
--- /dev/null
@@ -0,0 +1,543 @@
+/***************************************************************************************[MultiSolvers.cc]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+#include <pthread.h>
+#include "parallel/MultiSolvers.h"
+#include "mtl/Sort.h"
+#include "utils/System.h"
+#include "simp/SimpSolver.h"
+#include <errno.h>
+#include <string.h>
+#include "parallel/SolverConfiguration.h"
+
+using namespace Glucose;
+
+extern const char* _parallel ;
+extern const char* _cunstable;
+// Options at the parallel solver level
+static IntOption opt_nbsolversmultithreads (_parallel, "nthreads", "Number of core threads for syrup (0 for automatic)", 0);
+static IntOption opt_maxnbsolvers (_parallel, "maxnbthreads", "Maximum number of core threads to ask for (when nbthreads=0)", 4);
+static IntOption opt_maxmemory    (_parallel, "maxmemory", "Maximum memory to use (in Mb, 0 for no software limit)", 3000);
+static IntOption opt_statsInterval (_parallel, "statsinterval", "Seconds (real time) between two stats reports", 5);
+//
+// Shared with ClausesBuffer.cc
+BoolOption opt_whenFullRemoveOlder (_parallel, "removeolder", "When the FIFO for exchanging clauses between threads is full, remove older clauses", false);
+IntOption opt_fifoSizeByCore(_parallel, "fifosize", "Size of the FIFO structure for exchanging clauses between threads, by threads", 100000);
+//
+// Shared options with Solver.cc 
+BoolOption    opt_dontExportDirectReusedClauses (_cunstable, "reusedClauses",    "Don't export directly reused clauses", false);
+BoolOption    opt_plingeling (_cunstable, "plingeling",    "plingeling strategy for sharing clauses (exploratory feature)", false);
+
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <unistd.h>
+
+static inline double cpuTime(void) {
+    struct rusage ru;
+    getrusage(RUSAGE_SELF, &ru);
+return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; }
+
+
+void MultiSolvers::informEnd(lbool res) {
+  result = res;
+  pthread_cond_broadcast(&cfinished);
+}
+
+MultiSolvers::MultiSolvers(ParallelSolver *s):
+  ok (true)
+  , maxnbthreads(4), nbthreads(opt_nbsolversmultithreads), nbsolvers(opt_nbsolversmultithreads)
+  , nbcompanions(4), nbcompbysolver(2)
+  , allClonesAreBuilt(0)
+  , showModel(false)
+  , winner(-1)
+  , var_decay(1 / 0.95), clause_decay(1 / 0.999),cla_inc(1), var_inc(1)
+  , random_var_freq(0.02)
+  , restart_first(100), restart_inc(1.5)
+  , learntsize_factor((double)1/(double)3), learntsize_inc(1.1)
+  , expensive_ccmin(true)
+  , polarity_mode    (polarity_false)
+  , maxmemory(opt_maxmemory), maxnbsolvers(opt_maxnbsolvers)
+  , verb(0) , verbEveryConflicts(10000)
+  , numvar(0), numclauses(0)
+
+{
+    result = l_Undef;
+    SharedCompanion *sc = new SharedCompanion();
+    this->sharedcomp = sc;
+
+    // Generate only solver 0.
+    // It loads the formula
+    // All others solvers are clone of this one
+    solvers.push(s);
+    s->verbosity = 0; // No reportf in solvers... All is done in MultiSolver
+    s->setThreadNumber(0);
+    //s->belongsto = this;
+    s->sharedcomp = sc;
+    sc->addSolver(s);
+    assert(solvers[0]->threadNumber() == 0);
+
+    pthread_mutex_init(&m,NULL);  //PTHREAD_MUTEX_INITIALIZER;
+    pthread_mutex_init(&mfinished,NULL); //PTHREAD_MUTEX_INITIALIZER;
+    pthread_cond_init(&cfinished,NULL);
+
+    if (nbsolvers > 0 ) 
+       fprintf(stdout,"c %d solvers engines and 1 companion as a blackboard created.\n", nbsolvers);
+}
+
+MultiSolvers::MultiSolvers() : MultiSolvers(new ParallelSolver(-1)) {
+
+}
+
+MultiSolvers::~MultiSolvers()
+{}
+
+/**
+ * Generate All solvers
+ */
+
+void MultiSolvers::generateAllSolvers() {
+    assert(solvers[0] != NULL);
+    assert(allClonesAreBuilt==0);
+
+    for(int i=1;i<nbsolvers;i++) {
+       ParallelSolver *s  = (ParallelSolver*)solvers[0]->clone();
+       solvers.push(s);
+       s->verbosity = 0; // No reportf in solvers... All is done in MultiSolver
+       s->setThreadNumber(i);
+       s->sharedcomp =   this->sharedcomp;
+       this->sharedcomp->addSolver(s);
+       assert(solvers[i]->threadNumber() == i);
+    }
+
+    adjustParameters(); 
+
+    allClonesAreBuilt = 1;
+}
+
+/**
+ * Choose solver for threads i (if no given in command line see above)
+ */
+
+
+ParallelSolver* MultiSolvers::retrieveSolver(int i) {
+    return new ParallelSolver(i);
+}
+
+Var MultiSolvers::newVar(bool sign, bool dvar)
+{
+  assert(solvers[0] != NULL);
+  numvar++;
+  int v;
+  sharedcomp->newVar(sign);
+  if(!allClonesAreBuilt) { // At the beginning we want to generate only solvers 0
+    v = solvers[0]->newVar(sign,dvar);
+    assert(numvar == v+1); // Just a useless check
+  } else {
+      for(int i=0;i<nbsolvers;i++) {
+         v = solvers[i]->newVar(sign,dvar);
+      }
+  }
+  return numvar;
+}
+
+bool MultiSolvers::addClause_(vec<Lit>&ps) {
+  assert(solvers[0] != NULL); // There is at least one solver.
+  // Check if clause is satisfied and remove false/duplicate literals:
+  if (!okay())  return false;
+
+  sort(ps);
+  Lit p; int i, j;
+  for (i = j = 0, p = lit_Undef; i < ps.size(); i++)
+    if (solvers[0]->value(ps[i]) == l_True || ps[i] == ~p)
+      return true;
+    else if (solvers[0]->value(ps[i]) != l_False && ps[i] != p)
+      ps[j++] = p = ps[i];
+  ps.shrink(i - j);
+  
+  
+  if (ps.size() == 0) {
+    return ok = false;
+  }
+  else if (ps.size() == 1){
+    assert(solvers[0]->value(ps[0]) == l_Undef); // TODO : Passes values to all threads
+    solvers[0]->uncheckedEnqueue(ps[0]);
+    if(!allClonesAreBuilt) {
+       return ok = ( (solvers[0]->propagate()) == CRef_Undef); // checks only main solver here for propagation constradiction
+    } 
+
+    // Here, all clones are built.
+    // Gives the unit clause to everybody
+    for(int i=0;i<nbsolvers;i++)
+      solvers[i]->uncheckedEnqueue(ps[0]);
+    return ok = ( (solvers[0]->propagate()) == CRef_Undef); // checks only main solver here for propagation constradiction
+  }else{
+    //         printf("Adding clause %0xd for solver %d.\n",(void*)c, thn);
+    // At the beginning only solver 0 load the formula
+    solvers[0]->addClause(ps);
+    
+    if(!allClonesAreBuilt) {
+       numclauses++;
+       return true;
+    }
+    // Clones are built, need to pass the clause to all the threads 
+    for(int i=1;i<nbsolvers;i++) {
+      solvers[i]->addClause(ps);
+    }
+    numclauses++;
+  }
+  return true;
+}
+
+
+bool MultiSolvers::simplify() {
+  assert(solvers[0] != NULL); // There is at least one solver.
+
+  if (!okay()) return false;
+  return ok = solvers[0]->simplify(); 
+}
+
+
+bool MultiSolvers::eliminate() {
+    
+    // TODO allow variable elimination when all threads are built!
+    assert(allClonesAreBuilt==false);
+    
+    SimpSolver * s = (SimpSolver*)getPrimarySolver();
+    return s->eliminate(true);
+}
+
+
+// TODO: Use a template here
+void *localLaunch(void*arg) {
+  ParallelSolver* s = (ParallelSolver*)arg;
+  
+  (void)s->solve();
+  
+  pthread_exit(NULL);
+}
+
+
+#define MAXIMUM_SLEEP_DURATION 5
+void MultiSolvers::printStats() {
+       static int nbprinted = 1;
+       double cpu_time = cpuTime();
+    printf("c\n");
+
+    printf("c |-------------------------------------------------------------------------------------------------------|\n");
+        printf("c | id | starts | decisions  |  confls    |  Init T  |  learnts | exported | imported | promoted |    %%   | \n");
+        printf("c |-------------------------------------------------------------------------------------------------------|\n");
+
+       //printf("%.0fs | ",cpu_time);
+       for(int i=0;i<solvers.size();i++) {
+           solvers[i]->reportProgress();
+    //printf(" %2d: %12ld confl. |", i,  (long int) solvers[i]->conflicts);
+    }
+       long long int totalconf = 0;
+       long long int totalprop = 0;
+       for(int i=0;i<solvers.size();i++) {
+               totalconf+=  (long int) solvers[i]->conflicts;
+               totalprop+= solvers[i]->propagations;
+    }
+    printf("c \n");
+   
+    printf("c synthesis %11lld conflicts %11lld propagations %8.0f conflicts/sec %8.0f propagations/sec\n",
+            totalconf, totalprop, (double)totalconf / cpu_time, (double) totalprop / cpu_time);
+
+
+       nbprinted ++;
+}
+
+// Still a ugly function... To be rewritten with some statistics class some day
+void MultiSolvers::printFinalStats() {
+    sharedcomp->printStats();
+    printf("c\nc\n");
+    printf("c\n");
+    printf("c |---------------------------------------- FINAL STATS --------------------------------------------------|\n");
+    printf("c\n");
+    
+    printf("c |---------------");
+    for(int i = 0;i<solvers.size();i++) 
+        printf("|------------");
+    printf("|-----------------|\n");    
+
+    printf("c | Threads       ");
+    for(int i = 0;i < solvers.size();i++) {
+        printf("| %10d ",i);
+    }
+    printf("|      Total      |\n");
+
+    printf("c |---------------");
+    for(int i = 0;i<solvers.size();i++) 
+        printf("|------------");
+    printf("|-----------------|\n");    
+
+    
+    printf("c | Conflicts     ");
+
+    long long int totalconf = 0;
+    for(int i=0;i<solvers.size();i++)  {
+       printf("| %10" PRIu64" ", solvers[i]->conflicts);
+       totalconf +=  solvers[i]->conflicts;
+    }
+    printf("| %15lld |\n",totalconf);
+   
+    printf("c | Exported      ");
+    uint64_t exported = 0;
+    for(int i=0;i<solvers.size();i++) {
+       printf("| %10" PRIu64" ", solvers[i]->nbexported);
+        exported += solvers[i]->nbexported;
+    }
+    printf("| %15" PRIu64" |\n", exported);
+
+    printf("c | Imported      ");
+    uint64_t imported = 0;
+    for(int i=0;i<solvers.size();i++) {
+       printf("| %10" PRIu64" ", solvers[i]->nbimported);
+        imported += solvers[i]->nbimported;
+    }
+    printf("| %15" PRIu64" |\n", imported);
+
+    printf("c | Good          ");
+    uint64_t importedGood = 0;
+    for(int i=0;i<solvers.size();i++) {
+       printf("| %10" PRIu64" ", solvers[i]->nbImportedGoodClauses);
+        importedGood += solvers[i]->nbImportedGoodClauses;
+    }
+    printf("| %15" PRIu64" |\n", importedGood);
+
+    printf("c | Purge         ");
+    uint64_t importedPurg = 0;
+    for(int i=0;i<solvers.size();i++) {
+       printf("| %10" PRIu64" ", solvers[i]->nbimportedInPurgatory);
+        importedPurg += solvers[i]->nbimportedInPurgatory;
+    }
+    printf("| %15" PRIu64" |\n", importedPurg);
+
+    printf("c | Promoted      ");
+    uint64_t promoted = 0;
+    for(int i=0;i<solvers.size();i++) {
+       printf("| %10" PRIu64" ", solvers[i]->nbPromoted);
+        promoted += solvers[i]->nbPromoted;
+    }
+    printf("| %15" PRIu64" |\n", promoted);
+
+    printf("c | Remove imp    ");
+    uint64_t removedimported = 0;
+    for(int i=0;i<solvers.size();i++) {
+       printf("| %10" PRIu64" ", solvers[i]->nbRemovedUnaryWatchedClauses);
+        removedimported += solvers[i]->nbRemovedUnaryWatchedClauses;
+    }
+    printf("| %15" PRIu64" |\n", removedimported);
+
+    printf("c | Blocked Reuse ");
+    uint64_t blockedreused = 0;
+    for(int i=0;i<solvers.size();i++) {
+       printf("| %10" PRIu64" ", solvers[i]->nbNotExportedBecauseDirectlyReused);
+        blockedreused += solvers[i]->nbNotExportedBecauseDirectlyReused;
+    }
+    printf("| %15" PRIu64" |\n",blockedreused);
+
+
+    printf("c | Orig seen     ");
+    for(int i=0;i<solvers.size();i++) {
+       printf("| %10" PRIu64" ", solvers[i]->originalClausesSeen);
+    }
+    printf("|                 |\n"); 
+
+    printf("c | Unaries       ");
+    for(int i=0;i<solvers.size();i++) {
+       printf("| %10" PRIu64" ", solvers[i]->nbUn);
+    }
+    printf("|                 |\n"); 
+
+    printf("c | Binaries      ");
+    for(int i=0;i<solvers.size();i++) {
+       printf("| %10" PRIu64" ", solvers[i]->nbBin);
+    }
+    printf("|                 |\n"); 
+
+    
+     printf("c | Glues         ");
+    for(int i=0;i<solvers.size();i++) {
+       printf("| %10" PRIu64" ", solvers[i]->nbDL2);
+    }
+    printf("|                 |\n"); 
+
+
+    int winner = -1;
+   for(int i=0;i<solvers.size();i++) {
+     if(sharedcomp->winner()==solvers[i])
+       winner = i;
+     }
+   
+   if(winner!=-1) {
+int sum = 0;
+   printf("c | Hamming       ");
+   for(int i = 0;i<solvers.size();i++) {
+     if(i==winner) {
+       printf("|      X     ");
+       continue;
+     }
+     int nb = 0;
+     for(int j = 0;j<nVars();j++) {
+       if(solvers[i]->valuePhase(j)!= solvers[winner]->valuePhase(j)) nb++;
+     }
+     printf("| %10d ",nb);
+     sum+=nb;
+
+   }
+   printf("| %15d |\n",sum/(solvers.size()>1?solvers.size()-1:1));
+   }
+   printf("c |---------------");
+   for(int i = 0;i<solvers.size();i++) 
+     printf("|------------");
+   printf("|-----------------|\n");    
+
+  
+
+}
+
+// Well, all those parameteres are just naive guesses... No experimental evidences for this.
+void MultiSolvers::adjustParameters() {
+    SolverConfiguration::configure(this,nbsolvers);
+}
+
+void MultiSolvers::adjustNumberOfCores() {
+ float mem = memUsed();
+  if (nbthreads==0) { // Automatic configuration
+      if(verb>=1) 
+          printf("c |  Automatic Adjustement of the number of solvers. MaxMemory=%5d, MaxCores=%3d.                       |\n", maxmemory, maxnbsolvers);
+      unsigned int tmpnbsolvers = maxmemory * 4 /  10 / mem;
+      if (tmpnbsolvers > maxnbsolvers) tmpnbsolvers = maxnbsolvers;
+      if (tmpnbsolvers < 1) tmpnbsolvers = 1;
+      if(verb>=1) 
+        printf("c |  One Solver is taking %.2fMb... Let's take %d solvers for this run (max 40%% of the maxmemory).       |\n", mem, tmpnbsolvers);
+      nbsolvers = tmpnbsolvers;
+      nbthreads = nbsolvers;
+  } else {
+      assert(nbthreads == nbsolvers);
+  }
+}
+
+lbool MultiSolvers::solve() {
+  pthread_attr_t thAttr; 
+  int i; 
+
+  adjustNumberOfCores();
+  sharedcomp->setNbThreads(nbsolvers); 
+  if(verb>=1) 
+    printf("c |  Generating clones                                                                                    |\n"); 
+  generateAllSolvers();
+  if(verb>=1) {
+    printf("c |  all clones generated. Memory = %6.2fMb.                                                             |\n", memUsed());
+    printf("c ========================================================================================================|\n");
+  }
+  
+  
+  model.clear();
+
+  /* Initialize and set thread detached attribute */
+  pthread_attr_init(&thAttr);
+  pthread_attr_setdetachstate(&thAttr, PTHREAD_CREATE_JOINABLE);
+  
+  
+  
+  // Launching all solvers
+  for (i = 0; i < nbsolvers; i++) {
+    pthread_t * pt = (pthread_t*)malloc(sizeof(pthread_t));
+    threads.push(pt);
+    solvers[i]->pmfinished = &mfinished;
+    solvers[i]->pcfinished = &cfinished;
+    pthread_create(threads[i], &thAttr, &localLaunch, (void*)solvers[i]); 
+  }
+  
+  bool done = false;
+  
+  (void)pthread_mutex_lock(&m);
+  while (!done) { 
+    struct timespec timeout;
+    time(&timeout.tv_sec);
+    timeout.tv_sec += MAXIMUM_SLEEP_DURATION;
+    timeout.tv_nsec = 0;
+    if (pthread_cond_timedwait(&cfinished, &mfinished, &timeout) != ETIMEDOUT) 
+           done = true;
+    else 
+      printStats();
+
+    float mem = memUsed();
+    if(verb>=1) printf("c Total Memory so far : %.2fMb\n",  mem);
+    if ( (maxmemory > 0) && (mem > maxmemory) && !sharedcomp->panicMode) 
+       printf("c ** reduceDB switching to Panic Mode due to memory limitations !\n"), sharedcomp->panicMode = true;
+    
+  }
+  (void)pthread_mutex_unlock(&m);
+  
+  for (i = 0; i < nbsolvers; i++) { // Wait for all threads to finish
+      pthread_join(*threads[i], NULL);
+  }
+  
+  assert(sharedcomp != NULL);
+  result = sharedcomp->jobStatus;
+  if (result == l_True) {
+      int n = sharedcomp->jobFinishedBy->nVars();
+       model.growTo(n);
+       for(int i = 0; i < n; i++)
+           model[i] = sharedcomp->jobFinishedBy->model[i];
+  }
+
+       
+  return result;
+  /*
+  for(int i=0;i<NBTHREADS;i++)
+    pthread_join(*threads[i],&status);
+  */
+
+}
+
diff --git a/glucose-syrup/parallel/MultiSolvers.h b/glucose-syrup/parallel/MultiSolvers.h
new file mode 100644 (file)
index 0000000..b44b75f
--- /dev/null
@@ -0,0 +1,182 @@
+/***************************************************************************************[MultiSolvers.h]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+#ifndef MultiSolvers_h
+#define MultiSolvers_h
+
+#include "parallel/ParallelSolver.h"
+
+namespace Glucose {
+    class SolverConfiguration;
+    
+class MultiSolvers {
+    friend class SolverConfiguration;
+
+public:
+  MultiSolvers(ParallelSolver *s);
+  MultiSolvers();
+  ~MultiSolvers();
+  void printFinalStats(); 
+
+  void setVerbosity(int i);
+  int verbosity();
+  void setVerbEveryConflicts(int i);
+  void setShowModel(int i) {showModel = i;}
+  int getShowModel() {return showModel;}
+  // Problem specification:
+  //
+  Var     newVar    (bool polarity = true, bool dvar = true); // Add a new variable with parameters specifying variable mode.
+  bool    addClause (const vec<Lit>& ps);                           // Add a clause to the solver. NOTE! 'ps' may be shrunk by this method!
+  bool    addClause_(      vec<Lit>& ps);       
+  
+  bool    simplify     ();                        // Removes already satisfied clauses.
+  
+  int     nVars      ()      const;       // The current number of variables.
+  int     nClauses      ()      const;       // The current number of variables.
+  ParallelSolver *getPrimarySolver();
+  
+  void generateAllSolvers();
+  
+  // Solving:
+  //
+  lbool    solve        ();                        // Search without assumptions.
+  bool eliminate();             // Perform variable elimination
+  void adjustParameters();
+  void adjustNumberOfCores();
+  void interrupt() {}
+  vec<lbool> model;             // If problem is satisfiable, this vector contains the model (if any).
+  inline bool okay() {
+    if(!ok) return ok;
+    for(int i = 0;i<solvers.size();i++) {
+       if(!((SimpSolver*)solvers[i])->okay()) {
+           ok = false;
+           return false;
+       }
+    }
+    return true;
+  }
+
+ protected:
+       friend class ParallelSolver;
+       friend class SolverCompanion;
+       
+struct Stats {
+    uint64_t min, max, avg, std, med;
+    Stats(uint64_t _min = 0,uint64_t _max = 0,uint64_t  _avg = 0,uint64_t  _std = 0,uint64_t  _med = 0) : 
+       min(_min), max(_max), avg(_avg), std(_std), med(_med) {} 
+};
+
+       void printStats(); 
+       int ok;
+       lbool result;
+       int maxnbthreads; // Maximal number of threads
+       int nbthreads; // Current number of threads
+       int nbsolvers; // Number of CDCL solvers
+       int nbcompanions; // Number of companions
+       int nbcompbysolver; // Number of companions by solvers
+       bool immediateSharingGlue ;
+       int allClonesAreBuilt;
+        bool showModel; // show model on/off
+
+       int winner;
+
+    vec<Lit>            add_tmp;
+       
+    double    var_decay;          // Inverse of the variable activity decay factor.                                            (default 1 / 0.95)
+    double    clause_decay;       // Inverse of the clause activity decay factor.                                              (1 / 0.999)
+    double    cla_inc;          // Amount to bump next clause with.
+    double    var_inc;          // Amount to bump next variable with.  
+    double    random_var_freq;    // The frequency with which the decision heuristic tries to choose a random variable.        (default 0.02)
+    int       restart_first;      // The initial restart limit.                                                                (default 100)
+    double    restart_inc;        // The factor with which the restart limit is multiplied in each restart.                    (default 1.5)
+    double    learntsize_factor;  // The intitial limit for learnt clauses is a factor of the original clauses.                (default 1 / 3)
+    double    learntsize_inc;     // The limit for learnt clauses is multiplied with this factor each restart.                 (default 1.1)
+    bool      expensive_ccmin;    // Controls conflict clause minimization.                                                    (default TRUE)
+    int       polarity_mode;      // Controls which polarity the decision heuristic chooses. See enum below for allowed modes. (default polarity_false)
+    unsigned int maxmemory;
+    unsigned int maxnbsolvers;
+    int verb; 
+    int verbEveryConflicts;
+    int numvar; // Number of variables
+    int numclauses; // Number of clauses
+
+    enum { polarity_true = 0, polarity_false = 1, polarity_user = 2, polarity_rnd = 3 };
+
+   //ClauseAllocator     ca;
+   SharedCompanion * sharedcomp;
+
+    void informEnd(lbool res);
+    ParallelSolver* retrieveSolver(int i);
+
+    pthread_mutex_t m; // mutex for any high level sync between all threads (like reportf)
+    pthread_mutex_t mfinished; // mutex on which main process may wait for... As soon as one process finishes it release the mutex
+    pthread_cond_t cfinished; // condition variable that says that a thread has finished
+       
+    vec<ParallelSolver*> solvers; // set of plain solvers
+    vec<SolverCompanion*> solvercompanions; // set of companion solvers
+    vec<pthread_t*> threads; // all threads of this process
+    vec<int> threadIndexOfSolver; // threadIndexOfSolver[solvers[i]] is the index in threads[] of the solver i
+    vec<int> threadIndexOfSolverCompanion; // threadIndexOfSolverCompanion[solvercompanions[i]] is the index in threads[] of the solvercompanion i
+};
+
+inline bool     MultiSolvers::addClause       (const vec<Lit>& ps)    { ps.copyTo(add_tmp); return addClause_(add_tmp); }
+
+inline void MultiSolvers::setVerbosity(int i) {verb = i;}
+inline void MultiSolvers::setVerbEveryConflicts(int i) {verbEveryConflicts=i;}
+inline int      MultiSolvers::nVars         ()      const   { return numvar; }
+inline int      MultiSolvers::nClauses      ()      const   { return numclauses; }
+inline int MultiSolvers::verbosity()  {return verb;}
+inline ParallelSolver* MultiSolvers::getPrimarySolver() {return solvers[0];}
+
+
+}
+#endif
+
diff --git a/glucose-syrup/parallel/ParallelSolver.cc b/glucose-syrup/parallel/ParallelSolver.cc
new file mode 100644 (file)
index 0000000..ff948e9
--- /dev/null
@@ -0,0 +1,490 @@
+/***************************************************************************************[ParallelSolver.cc]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+#include "parallel/ParallelSolver.h"
+#include "mtl/Sort.h"
+
+using namespace Glucose;
+
+const char* _cunstable = "CORE/PARALLEL -- UNSTABLE FEATURES";
+const char* _parallel = "PARALLEL";
+
+extern BoolOption opt_dontExportDirectReusedClauses; // (_cunstable, "reusedClauses",    "Don't export directly reused clauses", false);
+extern BoolOption opt_plingeling; // (_cunstable, "plingeling",    "plingeling strategy for sharing clauses (exploratory feature)", false);
+
+
+ParallelSolver::ParallelSolver(int threadId) :
+  SimpSolver()
+, thn(threadId) // The thread number of this solver
+, nbexported(0)
+, nbimported(0)
+, nbexportedunit(0), nbimportedunit(0), nbimportedInPurgatory(0), nbImportedGoodClauses(0)
+, goodlimitlbd(8)
+, goodlimitsize(30)
+, purgatory(true)
+, shareAfterProbation(!opt_plingeling) // only share clauses after probation 
+, plingeling(opt_plingeling)
+, firstSharing(5000) // Strong limit : do not share anything (except unary clauses) before this number of conflicts
+, limitSharingByGoodLBD(true) // Moving limit of what a good LBD is (median value of last learnt clauses set)
+, limitSharingByFixedLimitLBD(0) // No fixed bound (like 8 in plingeling)
+, limitSharingByFixedLimitSize(0) // No fixed boud (like 40 in plingeling) 
+, dontExportDirectReusedClauses(opt_dontExportDirectReusedClauses)
+, nbNotExportedBecauseDirectlyReused(0)
+{
+    useUnaryWatched = true; // We want to use promoted clauses here !
+}
+
+
+
+
+ParallelSolver::~ParallelSolver() {
+    printf("c Solver of thread %d ended.\n", thn);
+    fflush(stdout);
+}
+
+ParallelSolver::ParallelSolver(const ParallelSolver &s) : SimpSolver(s)
+, nbexported(s.nbexported)
+, nbimported(s.nbimported)
+, nbexportedunit(s.nbexportedunit), nbimportedunit(s.nbimportedunit), nbimportedInPurgatory(s.nbimportedInPurgatory)
+, nbImportedGoodClauses(s.nbImportedGoodClauses)
+, goodlimitlbd(s.goodlimitlbd)
+, goodlimitsize(s.goodlimitsize)
+, purgatory(s.purgatory)
+, shareAfterProbation(s.shareAfterProbation) // only share clauses after probation 
+, plingeling(s.plingeling)
+, firstSharing(s.firstSharing) // Strong limit : do not share anything (except unary clauses) before this number of conflicts
+, limitSharingByGoodLBD(s.limitSharingByGoodLBD) // Moving limit of what a good LBD is (median value of last learnt clauses set)
+, limitSharingByFixedLimitLBD(s.limitSharingByFixedLimitLBD) // No fixed bound (like 8 in plingeling)
+, limitSharingByFixedLimitSize(s.limitSharingByFixedLimitSize) // No fixed boud (like 40 in plingeling) 
+, dontExportDirectReusedClauses(s.dontExportDirectReusedClauses)
+, nbNotExportedBecauseDirectlyReused(s.nbNotExportedBecauseDirectlyReused) 
+{
+    s.goodImportsFromThreads.memCopyTo(goodImportsFromThreads);   
+    useUnaryWatched = s.useUnaryWatched;
+}
+
+
+// Strategy to reduce unary watches list
+struct reduceDB_oneWatched_lt {
+    ClauseAllocator& ca;
+
+    reduceDB_oneWatched_lt(ClauseAllocator& ca_) : ca(ca_) {
+    }
+
+    bool operator()(CRef x, CRef y) {
+
+        // Main criteria... Like in MiniSat we keep all binary clauses
+        if (ca[x].size() > 2 && ca[y].size() == 2) return 1;
+
+        if (ca[y].size() > 2 && ca[x].size() == 2) return 0;
+        if (ca[x].size() == 2 && ca[y].size() == 2) return 0;
+
+        // Second one  based on literal block distance
+        if (ca[x].size() > ca[y].size()) return 1;
+        if (ca[x].size() < ca[y].size()) return 0;
+
+        if (ca[x].lbd() > ca[y].lbd()) return 1;
+        if (ca[x].lbd() < ca[y].lbd()) return 0;
+
+        // Finally we can use old activity or size, we choose the last one
+        return ca[x].activity() < ca[y].activity();
+        //return x->size() < y->size();
+
+        //return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity()); } 
+    }
+};
+
+// @overide
+void ParallelSolver::reduceDB() {
+
+    int i, j;
+    nbReduceDB++;
+    sort(learnts, reduceDB_lt(ca));
+
+    int limit;
+
+    if (!panicModeIsEnabled()) {
+        // We have a lot of "good" clauses, it is difficult to compare them. Keep more !
+        if (ca[learnts[learnts.size() / RATIOREMOVECLAUSES]].lbd() <= 3) nbclausesbeforereduce += specialIncReduceDB;
+        // Useless :-)
+        if (ca[learnts.last()].lbd() <= 5) nbclausesbeforereduce += specialIncReduceDB;
+
+        // Don't delete binary or locked clauses. From the rest, delete clauses from the first half
+        // Keep clauses which seem to be usefull (their lbd was reduce during this sequence)
+
+        limit = learnts.size() / 2;
+    } else {
+        limit = panicModeLastRemoved;
+    }
+    panicModeLastRemoved = 0;
+
+    uint64_t sumsize = 0;
+    for (i = j = 0; i < learnts.size(); i++) {
+
+        Clause& c = ca[learnts[i]];
+        if (i == learnts.size() / 2)
+            goodlimitlbd = c.lbd();
+        sumsize += c.size();
+        if (c.lbd() > 2 && c.size() > 2 && c.canBeDel() && !locked(c) && (i < limit)) {
+            removeClause(learnts[i]);
+            nbRemovedClauses++;
+            panicModeLastRemoved++;
+        } else {
+            if (!c.canBeDel()) limit++; //we keep c, so we can delete an other clause
+            c.setCanBeDel(true); // At the next step, c can be delete
+            learnts[j++] = learnts[i];
+        }
+    }
+    learnts.shrink(i - j);
+
+    if (learnts.size() > 0)
+        goodlimitsize = 1 + (double) sumsize / (double) learnts.size();
+
+    // Special treatment for imported clauses
+    if (!panicModeIsEnabled())
+        limit = unaryWatchedClauses.size() - (learnts.size() * 2);
+    else
+        limit = panicModeLastRemovedShared;
+    panicModeLastRemovedShared = 0;
+    if ((unaryWatchedClauses.size() > 100) && (limit > 0)) {
+
+        sort(unaryWatchedClauses, reduceDB_oneWatched_lt(ca));
+
+        for (i = j = 0; i < unaryWatchedClauses.size(); i++) {
+            Clause& c = ca[unaryWatchedClauses[i]];
+            if (c.lbd() > 2 && c.size() > 2 && c.canBeDel() && !locked(c) && (i < limit)) {
+                removeClause(unaryWatchedClauses[i], c.getOneWatched()); // remove from the purgatory (or not)
+                nbRemovedUnaryWatchedClauses++;
+                panicModeLastRemovedShared++;
+            } else {
+                if (!c.canBeDel()) limit++; //we keep c, so we can delete an other clause
+                c.setCanBeDel(true); // At the next step, c can be delete
+                unaryWatchedClauses[j++] = unaryWatchedClauses[i];
+            }
+        }
+        unaryWatchedClauses.shrink(i - j);
+    }
+
+    checkGarbage();
+}
+
+
+/*_________________________________________________________________________________________________
+|
+|  parallelImportClauseDuringConflictAnalysis : (Clause &c,CRef confl)   ->  [void]
+|  
+|  Description:
+|    Verify if the clause using during conflict analysis is good for export
+|    @see : analyze
+|  Output:
+|________________________________________________________________________________________________@*/
+
+
+void ParallelSolver::parallelImportClauseDuringConflictAnalysis(Clause &c,CRef confl) {
+    if (dontExportDirectReusedClauses && (confl == lastLearntClause) && (c.getExported() < 2)) { // Experimental stuff
+        c.setExported(2);
+        nbNotExportedBecauseDirectlyReused++;
+    } else if (shareAfterProbation && c.getExported() != 2 && conflicts > firstSharing) {
+        c.setExported(c.getExported() + 1);
+        if (!c.wasImported() && c.getExported() == 2) { // It's a new interesting clause: 
+            if (c.lbd() == 2 || (c.size() < goodlimitsize && c.lbd() <= goodlimitlbd)) {
+                shareClause(c);
+            }
+        }
+    }
+
+}
+
+
+
+// These Two functions are useless here !!
+void ParallelSolver::reportProgress() {
+    printf("c | %2d | %6d | %10d | %10d | %8d | %8d | %8d | %8d | %8d | %6.3f |\n",(int)thn,(int)starts,(int)decisions,(int)conflicts,(int)originalClausesSeen,(int)learnts.size(),(int)nbexported,(int)nbimported,(int)nbPromoted,progressEstimate()*100);
+
+    //printf("c thread=%d confl=%lld starts=%llu reduceDB=%llu learnts=%d broadcast=%llu  blockedReuse=%lld imported=%llu promoted=%llu limitlbd=%llu limitsize=%llu\n", thn, conflicts, starts, nbReduceDB, learnts.size(), nbexported, nbNotExportedBecauseDirectlyReused, nbimported, nbPromoted, goodlimitlbd, goodlimitsize);
+}
+
+void ParallelSolver::reportProgressArrayImports(vec<unsigned int> &totalColumns) {
+    return ; // TODO : does not currently work
+    unsigned int totalImports = 0;
+    printf("c %3d | ", thn);
+    for (int i = 0; i <  sharedcomp->nbThreads; i++) {
+        totalImports += goodImportsFromThreads[i];
+        totalColumns[i] += goodImportsFromThreads[i];
+        printf(" %8d", goodImportsFromThreads[i]);
+    }
+    printf(" | %8d\n", totalImports);
+
+}
+
+
+/*_________________________________________________________________________________________________
+|
+|  shareClause : (Clause &c)   ->  [bool]
+|  
+|  Description:
+|  share a clause to other cores  
+| @see : analyze
+|  Output: true if the clause is indeed sent
+|________________________________________________________________________________________________@*/
+
+bool ParallelSolver::shareClause(Clause & c) {
+    bool sent = sharedcomp->addLearnt(this, c);
+    if (sent)
+        nbexported++;
+    return sent;
+}
+
+/*_________________________________________________________________________________________________
+|
+|  panicModeIsEnabled : ()   ->  [bool]
+|  
+|  Description:
+|  is panic mode (save memory) is enabled ?
+|________________________________________________________________________________________________@*/
+
+bool ParallelSolver::panicModeIsEnabled() {
+    return sharedcomp->panicMode;
+}
+
+/*_________________________________________________________________________________________________
+|
+|  parallelImportUnaryClauses : ()   ->  [void]
+|  
+|  Description:
+|  import all unary clauses from other cores
+|________________________________________________________________________________________________@*/
+
+void ParallelSolver::parallelImportUnaryClauses() {
+    Lit l;
+    while ((l = sharedcomp->getUnary(this)) != lit_Undef) {
+        if (value(var(l)) == l_Undef) {
+            uncheckedEnqueue(l);
+            nbimportedunit++;
+        }
+    }
+}
+
+/*_________________________________________________________________________________________________
+|
+|  parallelImportClauses : ()   ->  [bool]
+|  
+|  Description:
+|  import all clauses from other cores
+|  Output : if there is a final conflict
+|________________________________________________________________________________________________@*/
+
+bool ParallelSolver::parallelImportClauses() {
+
+    assert(decisionLevel() == 0);
+    int importedFromThread;
+    while (sharedcomp->getNewClause(this, importedFromThread, importedClause)) {
+        assert(importedFromThread <= sharedcomp->nbThreads);
+        assert(importedFromThread >= 0);
+
+        assert(importedFromThread != thn);
+
+        if (importedClause.size() == 0)
+            return true;
+
+        //printf("Thread %d imports clause from thread %d\n", threadNumber(), importedFromThread);
+        CRef cr = ca.alloc(importedClause, true, true);
+        ca[cr].setLBD(importedClause.size());
+        if (plingeling) // 0 means a broadcasted clause (good clause), 1 means a survivor clause, broadcasted
+            ca[cr].setExported(2); // A broadcasted clause (or a survivor clause) do not share it anymore
+        else {
+            ca[cr].setExported(1); // next time we see it in analyze, we share it (follow route / broadcast depending on the global strategy, part of an ongoing experimental stuff: a clause in one Watched will be set to exported 2 when promotted.
+        }
+        ca[cr].setImportedFrom(importedFromThread);
+        unaryWatchedClauses.push(cr);
+        if (plingeling || ca[cr].size() <= 2) {//|| importedRoute == 0) { // importedRoute == 0 means a glue clause in another thread (or any very good clause)
+            ca[cr].setOneWatched(false); // Warning: those clauses will never be promoted by a conflict clause (or rarely: they are propagated!)
+            attachClause(cr);
+            nbImportedGoodClauses++;
+        } else {
+            ca[cr].setOneWatched(true);
+            attachClausePurgatory(cr); // 
+            nbimportedInPurgatory++;
+        }
+        assert(ca[cr].learnt());
+        nbimported++;
+    }
+    return false;
+}
+
+
+/*_________________________________________________________________________________________________
+|
+|  parallelExportUnaryClause : (Lit p)   ->  [void]
+|  
+|  Description:
+|  export unary clauses to other cores
+|________________________________________________________________________________________________@*/
+
+void ParallelSolver::parallelExportUnaryClause(Lit p) {
+    // Multithread
+    sharedcomp->addLearnt(this,p ); // TODO: there can be a contradiction here (two theads proving a and -a)
+    nbexportedunit++;
+}
+
+
+/*_________________________________________________________________________________________________
+|
+|  parallelExportClauseDuringSearch : (Clause &c)   ->  [void]
+|  
+|  Description:
+|  Verify if a new learnt clause is useful for export
+|  @see search
+|  
+|________________________________________________________________________________________________@*/
+
+void ParallelSolver::parallelExportClauseDuringSearch(Clause &c) {
+    //
+    // Multithread
+    // Now I'm sharing the clause if seen in at least two conflicts analysis shareClause(ca[cr]);
+    if ((plingeling && !shareAfterProbation && c.lbd() < 8 && c.size() < 40) ||
+            (c.lbd() <= 2)) { // For this class of clauses, I'm sharing them asap (they are Glue CLauses, no probation for them)
+        shareClause(c);
+        c.setExported(2);
+    }
+
+}
+
+
+/*_________________________________________________________________________________________________
+|
+|  parallelJobIsFinished : ()   ->  [bool]
+|  
+|  Description:
+|  Is a core already finish the search
+|  
+|________________________________________________________________________________________________@*/
+
+bool ParallelSolver::parallelJobIsFinished() { 
+    // Parallel: another job has finished let's quit
+    return (sharedcomp->jobFinished());
+}
+
+// @overide
+lbool ParallelSolver::solve_(bool do_simp, bool turn_off_simp) {
+       vec<Var> extra_frozen;
+    lbool    result = l_True;
+    do_simp &= use_simplification;
+    if (do_simp){
+        // Assumptions must be temporarily frozen to run variable elimination:
+        for (int i = 0; i < assumptions.size(); i++){
+            Var v = var(assumptions[i]);
+
+            // If an assumption has been eliminated, remember it.
+            assert(!isEliminated(v));
+
+            if (!frozen[v]){
+                // Freeze and store.
+                setFrozen(v, true);
+                extra_frozen.push(v);
+            } }
+
+        result = lbool(eliminate(turn_off_simp));
+    }
+
+    model.clear();
+    conflict.clear();
+    if (!ok) return l_False;
+
+    solves++;
+
+
+    lbool status = l_Undef;
+
+    // Search:
+    int curr_restarts = 0;
+    while (status == l_Undef && !sharedcomp->jobFinished()) {
+        status = search(0); // the parameter is useless in glucose, kept to allow modifications
+        if (!withinBudget()) break;
+        curr_restarts++;
+    }
+
+    if (verbosity >= 1)
+        printf("c =========================================================================================================\n");
+
+
+/*    if (do_simp)
+        // Unfreeze the assumptions that were frozen:
+        for (int i = 0; i < extra_frozen.size(); i++)
+            setFrozen(extra_frozen[i], false);
+*/
+    
+    bool firstToFinish = false;
+    if (status != l_Undef)
+        firstToFinish = sharedcomp->IFinished(this);
+    if (firstToFinish) {
+        printf("c Thread %d is 100%% pure glucose! First thread to finish! (%s answer).\n", threadNumber(), status == l_True ? "SAT" : status == l_False ? "UNSAT" : "UNKOWN");
+        sharedcomp->jobStatus = status;
+    }
+    
+    if (firstToFinish && status == l_True) {
+        extendModel();
+
+
+        // Extend & copy model:
+        model.growTo(nVars());
+        for (int i = 0; i < nVars(); i++) model[i] = value(i);
+    } else if (status == l_False && conflict.size() == 0)
+        ok = false;
+
+
+    pthread_cond_signal(pcfinished);
+
+    //cancelUntil(0);
+
+
+    return status;
+
+}
diff --git a/glucose-syrup/parallel/ParallelSolver.h b/glucose-syrup/parallel/ParallelSolver.h
new file mode 100644 (file)
index 0000000..9701792
--- /dev/null
@@ -0,0 +1,144 @@
+/**************************************************************************************[ParallelSolver.h]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+#ifndef PARALLELSOLVER_H
+#define        PARALLELSOLVER_H
+
+#include "core/SolverTypes.h"
+#include "core/Solver.h"
+#include "simp/SimpSolver.h"
+#include "parallel/SharedCompanion.h"
+namespace Glucose {
+//=================================================================================================
+    //class MultiSolvers;
+    //class SolverCompanion;
+ //   class MultiSolvers;
+    
+class ParallelSolver : public SimpSolver {
+    friend class MultiSolvers;
+    friend class SolverCompanion;
+    friend class SharedCompanion;
+//    friend class ReasoningCompanion;
+//    friend class SolverConfiguration;
+
+protected : 
+          // Multithread :
+    int                thn; // internal thread number
+    //MultiSolvers* belongsto; // Not working (due to incomplete types)
+    SharedCompanion *sharedcomp;
+    bool coreFUIP; // true if one core is specialized for branching on all FUIP
+    bool ImTheSolverFUIP;
+    pthread_mutex_t *pmfinished; // mutex on which main process may wait for... As soon as one process finishes it release the mutex
+    pthread_cond_t *pcfinished; // condition variable that says that a thread as finished
+
+public:
+    // Constructor/Destructor:
+    //
+    ParallelSolver(int threadId);
+    ParallelSolver(const ParallelSolver &s);
+    ~ParallelSolver();
+    
+    /**
+     * Clone function
+     */
+    virtual Clone* clone() const {
+        return  new ParallelSolver(*this);
+    }   
+
+    int  threadNumber  ()      const;
+    void setThreadNumber (int i);
+    void reportProgress();
+    void reportProgressArrayImports(vec<unsigned int> &totalColumns);
+    virtual void reduceDB();
+    virtual lbool         solve_                   (bool do_simp = true, bool turn_off_simp = false);
+
+    vec<Lit>    importedClause; // Temporary clause used to copy each imported clause
+    uint64_t    nbexported;
+    uint64_t    nbimported; 
+    uint64_t    nbexportedunit, nbimportedunit , nbimportedInPurgatory, nbImportedGoodClauses;
+    unsigned int    goodlimitlbd; // LBD score of the "good" clauses, locally
+    int    goodlimitsize;
+    bool purgatory; // mode of operation
+    bool shareAfterProbation; // Share any none glue clause only after probation (seen 2 times in conflict analysis)
+    bool plingeling; // plingeling strategy for sharing clauses (experimental)
+
+    // Stats front end
+    uint64_t   getNbExported() { return nbexported;}
+    uint64_t   getNbImported() { return nbimported;}
+    uint64_t   getNbExportedUnit() {return nbexportedunit;}
+    
+    uint32_t  firstSharing, limitSharingByGoodLBD, limitSharingByFixedLimitLBD, limitSharingByFixedLimitSize;
+    uint32_t  probationByFollowingRoads, probationByFriend;
+    uint32_t  survivorLayers; // Number of layers for a common clause to survive
+    bool dontExportDirectReusedClauses ; // When true, directly reused clauses are not exported
+    uint64_t nbNotExportedBecauseDirectlyReused;
+    
+    
+    vec<uint32_t> goodImportsFromThreads; // Stats of good importations from other threads
+
+    virtual void parallelImportClauseDuringConflictAnalysis(Clause &c,CRef confl);
+    virtual bool parallelImportClauses(); // true if the empty clause was received
+    virtual void parallelImportUnaryClauses();
+    virtual void parallelExportUnaryClause(Lit p);
+    virtual void parallelExportClauseDuringSearch(Clause &c);
+    virtual bool parallelJobIsFinished();
+    virtual bool panicModeIsEnabled();
+    bool shareClause(Clause & c); // true if the clause was succesfully sent
+
+    
+
+};
+
+
+    inline int      ParallelSolver::threadNumber  ()      const   {return thn;}
+    inline void     ParallelSolver::setThreadNumber (int i)       {thn = i;}
+}
+#endif /* PARALLELSOLVER_H */
+
diff --git a/glucose-syrup/parallel/SharedCompanion.cc b/glucose-syrup/parallel/SharedCompanion.cc
new file mode 100644 (file)
index 0000000..dadc672
--- /dev/null
@@ -0,0 +1,167 @@
+/***************************************************************************************[SharedCompanion.cc]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+#include "core/Solver.h"
+#include "parallel/ParallelSolver.h"
+#include "core/SolverTypes.h"
+#include "parallel/ClausesBuffer.h"
+#include "parallel/SharedCompanion.h"
+
+
+using namespace Glucose;
+
+SharedCompanion::SharedCompanion(int _nbThreads) :
+    nbThreads(_nbThreads), 
+    bjobFinished(false),
+    jobFinishedBy(NULL),
+    panicMode(false), // The bug in the SAT2014 competition :)
+    jobStatus(l_Undef),
+    random_seed(9164825) {
+
+       pthread_mutex_init(&mutexSharedClauseCompanion,NULL); // This is the shared companion lock
+       pthread_mutex_init(&mutexSharedUnitCompanion,NULL); // This is the shared companion lock
+       pthread_mutex_init(&mutexSharedCompanion,NULL); // This is the shared companion lock
+       pthread_mutex_init(&mutexJobFinished,NULL); // This is the shared companion lock
+       if (_nbThreads> 0)  {
+           setNbThreads(_nbThreads);
+           fprintf(stdout,"c Shared companion initialized: handling of clauses of %d threads.\nc %d ints for the sharing clause buffer (not expandable) .\n", _nbThreads, clausesBuffer.maxSize());
+       }
+
+}
+
+void SharedCompanion::setNbThreads(int _nbThreads) {
+   nbThreads = _nbThreads;
+   clausesBuffer.setNbThreads(_nbThreads); 
+}
+
+void SharedCompanion::printStats() {
+}
+
+// No multithread safe
+bool SharedCompanion::addSolver(ParallelSolver* s) {
+       watchedSolvers.push(s);
+       pthread_mutex_t* mu = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
+       pthread_mutex_init(mu,NULL);
+       assert(s->thn == watchedSolvers.size()-1); // all solvers must have been registered in the good order
+       nextUnit.push(0);
+
+       return true;
+}
+void SharedCompanion::newVar(bool sign) {
+   isUnary .push(l_Undef);
+}
+
+void SharedCompanion::addLearnt(ParallelSolver *s,Lit unary) {
+  pthread_mutex_lock(&mutexSharedUnitCompanion);
+  if (isUnary[var(unary)]==l_Undef) {
+      unitLit.push(unary);
+      isUnary[var(unary)] = sign(unary)?l_False:l_True;
+  } 
+  pthread_mutex_unlock(&mutexSharedUnitCompanion);
+}
+
+Lit SharedCompanion::getUnary(ParallelSolver *s) {
+  int sn = s->thn;
+  Lit ret = lit_Undef;
+
+  pthread_mutex_lock(&mutexSharedUnitCompanion);
+  if (nextUnit[sn] < unitLit.size())
+      ret = unitLit[nextUnit[sn]++];
+  pthread_mutex_unlock(&mutexSharedUnitCompanion);
+ return ret;
+}
+
+// Specialized functions for this companion
+// must be multithread safe
+// Add a clause to the threads-wide clause database (all clauses, through)
+bool SharedCompanion::addLearnt(ParallelSolver *s, Clause & c) { 
+  int sn = s->thn; // thread number of the solver
+  bool ret = false;
+  assert(watchedSolvers.size()>sn);
+
+  pthread_mutex_lock(&mutexSharedClauseCompanion);
+  ret = clausesBuffer.pushClause(sn, c);
+  pthread_mutex_unlock(&mutexSharedClauseCompanion);
+  return ret;
+}
+
+
+bool SharedCompanion::getNewClause(ParallelSolver *s, int & threadOrigin, vec<Lit>& newclause) { // gets a new interesting clause for solver s 
+  int sn = s->thn;
+  
+    // First, let's get the clauses on the big blackboard
+    pthread_mutex_lock(&mutexSharedClauseCompanion);
+    bool b = clausesBuffer.getClause(sn, threadOrigin, newclause);
+    pthread_mutex_unlock(&mutexSharedClauseCompanion);
+  return b;
+}
+
+bool SharedCompanion::jobFinished() {
+    bool ret = false;
+    pthread_mutex_lock(&mutexJobFinished);
+    ret = bjobFinished;
+    pthread_mutex_unlock(&mutexJobFinished);
+    return ret;
+}
+
+bool SharedCompanion::IFinished(ParallelSolver *s) {
+    bool ret = false;
+    pthread_mutex_lock(&mutexJobFinished);
+    if (!bjobFinished) {
+       ret = true;
+       bjobFinished = true;
+       jobFinishedBy = s;
+    }
+    pthread_mutex_unlock(&mutexJobFinished);
+    return ret;
+}
+
+
+
diff --git a/glucose-syrup/parallel/SharedCompanion.h b/glucose-syrup/parallel/SharedCompanion.h
new file mode 100644 (file)
index 0000000..9ab3461
--- /dev/null
@@ -0,0 +1,122 @@
+/***************************************************************************************[SharedCompanion.h]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+/* This class is responsible for protecting (by mutex) information exchange between threads.
+ * It also allows each solver to send / receive clause / unary clauses.
+ *
+ * Only one sharedCompanion is created for all the solvers
+ */
+
+
+#ifndef SharedCompanion_h
+#define SharedCompanion_h
+#include "core/SolverTypes.h"
+#include "parallel/ParallelSolver.h"
+#include "parallel/SolverCompanion.h"
+#include "parallel/ClausesBuffer.h"
+
+namespace Glucose {
+
+    
+class SharedCompanion : public SolverCompanion {
+    friend class MultiSolvers;
+    friend class ParallelSolver;
+public:
+       SharedCompanion(int nbThreads=0);
+       void setNbThreads(int _nbThreads); // Sets the number of threads (cannot by changed once the solver is running)
+       void newVar(bool sign);            // Adds a var (used to keep track of unary variables)
+       void printStats();                 // Printing statistics of all solvers
+
+       bool jobFinished();                // True if the job is over
+       bool IFinished(ParallelSolver *s); // returns true if you are the first solver to finish
+       bool addSolver(ParallelSolver*);   // attach a solver to accompany 
+       void addLearnt(ParallelSolver *s,Lit unary);   // Add a unary clause to share
+       bool addLearnt(ParallelSolver *s, Clause & c); // Add a clause to the shared companion, as a database manager
+
+       bool getNewClause(ParallelSolver *s, int &th, vec<Lit> & nc); // gets a new interesting clause for solver s 
+       Lit getUnary(ParallelSolver *s);                              // Gets a new unary literal
+       inline ParallelSolver* winner(){return jobFinishedBy;}        // Gets the first solver that called IFinished()
+
+ protected:
+
+       ClausesBuffer clausesBuffer; // A big blackboard for all threads sharing non unary clauses
+       int nbThreads;               // Number of threads
+       
+       // A set of mutex variables
+       pthread_mutex_t mutexSharedCompanion; // mutex for any high level sync between all threads (like reportf)
+       pthread_mutex_t mutexSharedClauseCompanion; // mutex for reading/writing clauses on the blackboard
+       pthread_mutex_t mutexSharedUnitCompanion; // mutex for reading/writing unit clauses on the blackboard 
+        pthread_mutex_t mutexJobFinished;
+
+       bool bjobFinished;
+       ParallelSolver *jobFinishedBy;
+       bool panicMode;                        // panicMode means no more increasing space needed
+       lbool jobStatus;                       // globale status of the job
+
+        // Shared clauses are a queue of lits...
+       //      friend class wholearnt;
+       vec<int> nextUnit; // indice of next unit clause to retrieve for solver number i 
+       vec<Lit> unitLit;  // Set of unit literals found so far
+        vec<lbool> isUnary; // sign of the unary var (if proved, or l_Undef if not)    
+       double    random_seed;
+
+       // Returns a random float 0 <= x < 1. Seed must never be 0.
+       static inline double drand(double& seed) {
+           seed *= 1389796;
+           int q = (int)(seed / 2147483647);
+           seed -= (double)q * 2147483647;
+           return seed / 2147483647; }
+
+       // Returns a random integer 0 <= x < size. Seed must never be 0.
+       static inline int irand(double& seed, int size) {
+           return (int)(drand(seed) * size); }
+
+};
+}
+#endif
diff --git a/glucose-syrup/parallel/SolverCompanion.cc b/glucose-syrup/parallel/SolverCompanion.cc
new file mode 100644 (file)
index 0000000..8cd5c51
--- /dev/null
@@ -0,0 +1,87 @@
+/***************************************************************************************[SolverCompanion.cc]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+/* This class is a general companion for a solver.
+ * The idea is to be able to have different kind of companions:
+ * - SharedCompanion that shares clauses between threads
+ * - NetworkCompanion (Not in this version) that sends clauses over the network
+ *
+ * The implementaton is trivial. Just keep track of watched Solvers by the companion.
+ **/
+
+#include "parallel/SolverCompanion.h"
+
+using namespace Glucose;
+
+SolverCompanion::SolverCompanion()
+{}
+
+SolverCompanion::~SolverCompanion()
+{}
+
+
+bool SolverCompanion::addSolver(ParallelSolver* s) {
+       watchedSolvers.push(s);
+       return true;
+}
+
+int SolverCompanion::runOnceCompanion() {
+       int errcode = 0;
+       for(int indexSolver = 0; indexSolver<watchedSolvers.size();indexSolver++) {
+         errcode=runOnceCompanion(watchedSolvers[indexSolver]);
+               if (errcode<0) return errcode;
+       }
+       return errcode;
+}
+
+int SolverCompanion::runOnceCompanion(ParallelSolver*s) {
+       return 0;
+}
+
+
diff --git a/glucose-syrup/parallel/SolverCompanion.h b/glucose-syrup/parallel/SolverCompanion.h
new file mode 100644 (file)
index 0000000..c7dc895
--- /dev/null
@@ -0,0 +1,79 @@
+/***************************************************************************************[SolverCompanion.h]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+/* This class is a general companion for a solver.
+ * The idea is to be able to have different kind of companions:
+ * - SharedCompanion that shares clauses between threads
+ * - NetworkCompanion (Not in this version) that sends clauses over the network
+ **/
+
+#ifndef SolverCompanion_h
+#define SolverCompanion_h
+#include "mtl/Vec.h"
+namespace Glucose {
+    
+    class ParallelSolver;
+    
+class SolverCompanion {
+       public:
+       SolverCompanion();
+       ~SolverCompanion();
+       
+       bool addSolver(ParallelSolver* s); // attach a solver to accompany 
+       
+       int runOnceCompanion(); // run it as a thread, but run it just once... 
+       
+       protected:
+       int runOnceCompanion(ParallelSolver*s); // run it only on this watched solver
+       friend class ParallelSolver;
+       vec<ParallelSolver*> watchedSolvers; 
+};
+}
+#endif
+
diff --git a/glucose-syrup/parallel/SolverConfiguration.cc b/glucose-syrup/parallel/SolverConfiguration.cc
new file mode 100644 (file)
index 0000000..48127c2
--- /dev/null
@@ -0,0 +1,131 @@
+/***************************************************************************************[SolverConfiguration.cc]\r
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon\r
+                                CRIL - Univ. Artois, France\r
+                                LRI  - Univ. Paris Sud, France (2009-2013)\r
+                                Labri - Univ. Bordeaux, France\r
+\r
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon\r
+                                CRIL - Univ. Artois, France\r
+                                Labri - Univ. Bordeaux, France\r
+\r
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of\r
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it \r
+is based on. (see below).\r
+\r
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel\r
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software\r
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,\r
+sublicence, and/or sell copies of the Software, and to permit persons to whom the Software is \r
+furnished to do so, subject to the following conditions:\r
+\r
+- The above and below copyrights notices and this permission notice shall be included in all\r
+copies or substantial portions of the Software;\r
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot\r
+be used in any competitive event (sat competitions/evaluations) without the express permission of \r
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event\r
+using Glucose Parallel as an embedded SAT engine (single core or not).\r
+\r
+\r
+--------------- Original Minisat Copyrights\r
+\r
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson\r
+Copyright (c) 2007-2010, Niklas Sorensson\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r
+associated documentation files (the "Software"), to deal in the Software without restriction,\r
+including without limitation the rights to use, copy, modify, merge, publish, distribute,\r
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is\r
+furnished to do so, subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all copies or\r
+substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\r
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT\r
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ **************************************************************************************************/\r
+\r
+#include "parallel/MultiSolvers.h"\r
+#include "core/Solver.h"\r
+//#include "parallel/ParallelSolver.h"\r
+#include "parallel/SolverConfiguration.h"\r
+\r
+using namespace Glucose;\r
+\r
+  void SolverConfiguration::configure(MultiSolvers *ms, int nbsolvers) {\r
+\r
+   if (nbsolvers < 2 ) return;\r
+\r
+   ms->solvers[1]->var_decay = 0.94;\r
+   ms->solvers[1]->max_var_decay = 0.96;\r
+   ms->solvers[1]->firstReduceDB=600;\r
+\r
+   if (nbsolvers < 3 ) return;\r
+\r
+   ms->solvers[2]->var_decay = 0.90;\r
+   ms->solvers[2]->max_var_decay = 0.97;\r
+   ms->solvers[2]->firstReduceDB=500;\r
+\r
+   if (nbsolvers < 4 ) return;\r
+\r
+   ms->solvers[3]->var_decay = 0.85;\r
+   ms->solvers[3]->max_var_decay = 0.93;\r
+   ms->solvers[3]->firstReduceDB=400;\r
+\r
+   if (nbsolvers < 5 ) return;\r
+\r
+   // Glucose 2.0 (+ blocked restarts)\r
+   ms->solvers[4]->var_decay = 0.95;\r
+   ms->solvers[4]->max_var_decay = 0.95;\r
+   ms->solvers[4]->firstReduceDB=4000;\r
+   ms->solvers[4]->lbdQueue.growTo(100);\r
+   ms->solvers[4]->sizeLBDQueue = 100;\r
+   ms->solvers[4]->K = 0.7;\r
+   ms->solvers[4]->incReduceDB = 500;\r
+\r
+   if (nbsolvers < 6 ) return;\r
+\r
+   ms->solvers[5]->var_decay = 0.93;\r
+   ms->solvers[5]->max_var_decay = 0.96;\r
+   ms->solvers[5]->firstReduceDB=100;\r
+   ms->solvers[5]->incReduceDB = 500;\r
+\r
+   if (nbsolvers < 7 ) return;\r
+\r
+   ms->solvers[6]->var_decay = 0.75;\r
+   ms->solvers[6]->max_var_decay = 0.94;\r
+   ms->solvers[6]->firstReduceDB=2000;\r
+\r
+   if (nbsolvers < 8 ) return; \r
+\r
+   ms->solvers[7]->var_decay = 0.94;\r
+   ms->solvers[7]->max_var_decay = 0.96;\r
+   ms->solvers[7]->firstReduceDB=800;\r
+\r
+   if (nbsolvers < 9) return;\r
+\r
+   ms->solvers[8]->reduceOnSize = true;\r
+\r
+   if (nbsolvers < 10 ) return;\r
+\r
+   ms->solvers[9]->reduceOnSize = true;\r
+   ms->solvers[9]->reduceOnSizeSize = 14;\r
+\r
+   if (nbsolvers < 11 ) return;\r
+\r
+   double noisevar_decay = 0.005;\r
+   int noiseReduceDB = 50;\r
+   for (int i=10;i<nbsolvers;i++) {\r
+       ms->solvers[i]-> var_decay = ms->solvers[i%8]->var_decay;\r
+       ms->solvers[i]-> max_var_decay = ms->solvers[i%8]->max_var_decay;\r
+       ms->solvers[i]-> firstReduceDB= ms->solvers[i%8]->firstReduceDB;\r
+       ms->solvers[i]->var_decay += noisevar_decay;\r
+       ms->solvers[i]->firstReduceDB+=noiseReduceDB;\r
+       if ((i+1) % 8 == 0) {\r
+          noisevar_decay += 0.006;\r
+          noiseReduceDB += 25;\r
+       }\r
+   }\r
+ }\r
diff --git a/glucose-syrup/parallel/SolverConfiguration.h b/glucose-syrup/parallel/SolverConfiguration.h
new file mode 100644 (file)
index 0000000..475ec72
--- /dev/null
@@ -0,0 +1,68 @@
+/***************************************************************************************[SolverConfiguration.h]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+
+#ifndef SolverConfiguration_h
+#define SolverConfiguration_h
+
+
+
+namespace Glucose {
+
+class MultiSolvers;
+
+class SolverConfiguration {
+
+public : 
+    static void configure(MultiSolvers *ms, int nbsolvers);
+    
+};
+
+}
+#endif
diff --git a/glucose-syrup/simp/Main.cc b/glucose-syrup/simp/Main.cc
new file mode 100644 (file)
index 0000000..ca3bf42
--- /dev/null
@@ -0,0 +1,294 @@
+/***************************************************************************************[Main.cc]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+#include <errno.h>
+
+#include <signal.h>
+#include <zlib.h>
+#include <sys/resource.h>
+
+#include "utils/System.h"
+#include "utils/ParseUtils.h"
+#include "utils/Options.h"
+#include "core/Dimacs.h"
+#include "simp/SimpSolver.h"
+
+using namespace Glucose;
+
+//=================================================================================================
+
+static const char* _certified = "CORE -- CERTIFIED UNSAT";
+
+void printStats(Solver& solver)
+{
+    double cpu_time = cpuTime();
+    double mem_used = 0;//memUsedPeak();
+    printf("c restarts              : %" PRIu64" (%" PRIu64" conflicts in avg)\n", solver.starts,(solver.starts>0 ?solver.conflicts/solver.starts : 0));
+    printf("c blocked restarts      : %" PRIu64" (multiple: %" PRIu64") \n", solver.nbstopsrestarts,solver.nbstopsrestartssame);
+    printf("c last block at restart : %" PRIu64"\n",solver.lastblockatrestart);
+    printf("c nb ReduceDB           : %" PRIu64"\n", solver.nbReduceDB);
+    printf("c nb removed Clauses    : %" PRIu64"\n",solver.nbRemovedClauses);
+    printf("c nb learnts DL2        : %" PRIu64"\n", solver.nbDL2);
+    printf("c nb learnts size 2     : %" PRIu64"\n", solver.nbBin);
+    printf("c nb learnts size 1     : %" PRIu64"\n", solver.nbUn);
+
+    printf("c conflicts             : %-12" PRIu64"   (%.0f /sec)\n", solver.conflicts   , solver.conflicts   /cpu_time);
+    printf("c decisions             : %-12" PRIu64"   (%4.2f %% random) (%.0f /sec)\n", solver.decisions, (float)solver.rnd_decisions*100 / (float)solver.decisions, solver.decisions   /cpu_time);
+    printf("c propagations          : %-12" PRIu64"   (%.0f /sec)\n", solver.propagations, solver.propagations/cpu_time);
+    printf("c conflict literals     : %-12" PRIu64"   (%4.2f %% deleted)\n", solver.tot_literals, (solver.max_literals - solver.tot_literals)*100 / (double)solver.max_literals);
+    printf("c nb reduced Clauses    : %" PRIu64"\n",solver.nbReducedClauses);
+    
+    if (mem_used != 0) printf("Memory used           : %.2f MB\n", mem_used);
+    printf("c CPU time              : %g s\n", cpu_time);
+}
+
+
+
+static Solver* solver;
+// Terminate by notifying the solver and back out gracefully. This is mainly to have a test-case
+// for this feature of the Solver as it may take longer than an immediate call to '_exit()'.
+static void SIGINT_interrupt(int signum) { solver->interrupt(); }
+
+// Note that '_exit()' rather than 'exit()' has to be used. The reason is that 'exit()' calls
+// destructors and may cause deadlocks if a malloc/free function happens to be running (these
+// functions are guarded by locks for multithreaded use).
+static void SIGINT_exit(int signum) {
+    printf("\n"); printf("*** INTERRUPTED ***\n");
+    if (solver->verbosity > 0){
+        printStats(*solver);
+        printf("\n"); printf("*** INTERRUPTED ***\n"); }
+    _exit(1); }
+
+
+//=================================================================================================
+// Main:
+
+int main(int argc, char** argv)
+{
+    try {
+      printf("c\nc This is glucose 4.0 --  based on MiniSAT (Many thanks to MiniSAT team)\nc\n");
+
+      
+      setUsageHelp("c USAGE: %s [options] <input-file> <result-output-file>\n\n  where input may be either in plain or gzipped DIMACS.\n");
+        
+        
+#if defined(__linux__)
+        fpu_control_t oldcw, newcw;
+        _FPU_GETCW(oldcw); newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE; _FPU_SETCW(newcw);
+        //printf("c WARNING: for repeatability, setting FPU to use double precision\n");
+#endif
+        // Extra options:
+        //
+        IntOption    verb   ("MAIN", "verb",   "Verbosity level (0=silent, 1=some, 2=more).", 1, IntRange(0, 2));
+        BoolOption   mod   ("MAIN", "model",   "show model.", false);
+        IntOption    vv  ("MAIN", "vv",   "Verbosity every vv conflicts", 10000, IntRange(1,INT32_MAX));
+        BoolOption   pre    ("MAIN", "pre",    "Completely turn on/off any preprocessing.", true);
+        StringOption dimacs ("MAIN", "dimacs", "If given, stop after preprocessing and write the result to this file.");
+        IntOption    cpu_lim("MAIN", "cpu-lim","Limit on CPU time allowed in seconds.\n", INT32_MAX, IntRange(0, INT32_MAX));
+        IntOption    mem_lim("MAIN", "mem-lim","Limit on memory usage in megabytes.\n", INT32_MAX, IntRange(0, INT32_MAX));
+ //       BoolOption opt_incremental ("MAIN","incremental", "Use incremental SAT solving",false);
+
+         BoolOption    opt_certified      (_certified, "certified",    "Certified UNSAT using DRUP format", false);
+         StringOption  opt_certified_file      (_certified, "certified-output",    "Certified UNSAT output file", "NULL");
+         
+        parseOptions(argc, argv, true);
+        
+        SimpSolver  S;
+        double      initial_time = cpuTime();
+
+        S.parsing = 1;
+        //if (!pre) S.eliminate(true);
+
+        S.verbosity = verb;
+        S.verbEveryConflicts = vv;
+       S.showModel = mod;
+        
+        S.certifiedUNSAT = opt_certified;
+        if(S.certifiedUNSAT) {
+            if(!strcmp(opt_certified_file,"NULL")) {
+            S.certifiedOutput =  fopen("/dev/stdout", "wb");
+            } else {
+                S.certifiedOutput =  fopen(opt_certified_file, "wb");      
+            }
+            fprintf(S.certifiedOutput,"o proof DRUP\n");
+        }
+
+        solver = &S;
+        // Use signal handlers that forcibly quit until the solver will be able to respond to
+        // interrupts:
+        signal(SIGINT, SIGINT_exit);
+        signal(SIGXCPU,SIGINT_exit);
+
+
+        // Set limit on CPU-time:
+        if (cpu_lim != INT32_MAX){
+            rlimit rl;
+            getrlimit(RLIMIT_CPU, &rl);
+            if (rl.rlim_max == RLIM_INFINITY || (rlim_t)cpu_lim < rl.rlim_max){
+                rl.rlim_cur = cpu_lim;
+                if (setrlimit(RLIMIT_CPU, &rl) == -1)
+                    printf("c WARNING! Could not set resource limit: CPU-time.\n");
+            } }
+
+        // Set limit on virtual memory:
+        if (mem_lim != INT32_MAX){
+            rlim_t new_mem_lim = (rlim_t)mem_lim * 1024*1024;
+            rlimit rl;
+            getrlimit(RLIMIT_AS, &rl);
+            if (rl.rlim_max == RLIM_INFINITY || new_mem_lim < rl.rlim_max){
+                rl.rlim_cur = new_mem_lim;
+                if (setrlimit(RLIMIT_AS, &rl) == -1)
+                    printf("c WARNING! Could not set resource limit: Virtual memory.\n");
+            } }
+        
+        if (argc == 1)
+            printf("c Reading from standard input... Use '--help' for help.\n");
+
+        gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb");
+        if (in == NULL)
+            printf("ERROR! Could not open file: %s\n", argc == 1 ? "<stdin>" : argv[1]), exit(1);
+        
+      if (S.verbosity > 0){
+            printf("c ========================================[ Problem Statistics ]===========================================\n");
+            printf("c |                                                                                                       |\n"); }
+        
+        FILE* res = (argc >= 3) ? fopen(argv[argc-1], "wb") : NULL;
+        parse_DIMACS(in, S);
+        gzclose(in);
+
+       if (S.verbosity > 0){
+            printf("c |  Number of variables:  %12d                                                                   |\n", S.nVars());
+            printf("c |  Number of clauses:    %12d                                                                   |\n", S.nClauses()); }
+        
+        double parsed_time = cpuTime();
+        if (S.verbosity > 0){
+            printf("c |  Parse time:           %12.2f s                                                                 |\n", parsed_time - initial_time);
+            printf("c |                                                                                                       |\n"); }
+
+        // Change to signal-handlers that will only notify the solver and allow it to terminate
+        // voluntarily:
+        signal(SIGINT, SIGINT_interrupt);
+        signal(SIGXCPU,SIGINT_interrupt);
+
+        S.parsing = 0;
+        if(pre/* && !S.isIncremental()*/) {
+         printf("c | Preprocesing is fully done\n");
+         S.eliminate(true);
+        double simplified_time = cpuTime();
+        if (S.verbosity > 0){
+            printf("c |  Simplification time:  %12.2f s                                                                 |\n", simplified_time - parsed_time);
+ }
+       }
+       printf("c |                                                                                                       |\n");
+        if (!S.okay()){
+            if (S.certifiedUNSAT) fprintf(S.certifiedOutput, "0\n"), fclose(S.certifiedOutput);
+            if (res != NULL) fprintf(res, "UNSAT\n"), fclose(res);
+            if (S.verbosity > 0){
+               printf("c =========================================================================================================\n");
+               printf("Solved by simplification\n");
+                printStats(S);
+                printf("\n"); }
+            printf("s UNSATISFIABLE\n");        
+            exit(20);
+        }
+
+        if (dimacs){
+            if (S.verbosity > 0)
+                printf("c =======================================[ Writing DIMACS ]===============================================\n");
+            S.toDimacs((const char*)dimacs);
+            if (S.verbosity > 0)
+                printStats(S);
+            exit(0);
+        }
+
+        vec<Lit> dummy;
+        lbool ret = S.solveLimited(dummy);
+        
+        if (S.verbosity > 0){
+            printStats(S);
+            printf("\n"); }
+        printf(ret == l_True ? "s SATISFIABLE\n" : ret == l_False ? "s UNSATISFIABLE\n" : "s INDETERMINATE\n");
+
+        if (res != NULL){
+            if (ret == l_True){
+                printf("SAT\n");
+                for (int i = 0; i < S.nVars(); i++)
+                    if (S.model[i] != l_Undef)
+                        fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1);
+                fprintf(res, " 0\n");
+            } else {
+             if (ret == l_False){
+               fprintf(res, "UNSAT\n");
+             }
+           }
+            fclose(res);
+        } else {
+         if(S.showModel && ret==l_True) {
+           printf("v ");
+           for (int i = 0; i < S.nVars(); i++)
+             if (S.model[i] != l_Undef)
+               printf("%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1);
+           printf(" 0\n");
+         }
+
+       }
+
+        if (S.certifiedUNSAT) fprintf(S.certifiedOutput, "0\n"), fclose(S.certifiedOutput);
+
+#ifdef NDEBUG
+        exit(ret == l_True ? 10 : ret == l_False ? 20 : 0);     // (faster than "return", which will invoke the destructor for 'Solver')
+#else
+        return (ret == l_True ? 10 : ret == l_False ? 20 : 0);
+#endif
+    } catch (OutOfMemoryException&){
+               printf("c =========================================================================================================\n");
+        printf("INDETERMINATE\n");
+        exit(0);
+    }
+}
diff --git a/glucose-syrup/simp/Makefile b/glucose-syrup/simp/Makefile
new file mode 100644 (file)
index 0000000..f5d4481
--- /dev/null
@@ -0,0 +1,5 @@
+EXEC = glucose
+DEPDIR    = mtl utils core
+MROOT = $(PWD)/..
+
+include $(MROOT)/mtl/template.mk
diff --git a/glucose-syrup/simp/SimpSolver.cc b/glucose-syrup/simp/SimpSolver.cc
new file mode 100644 (file)
index 0000000..84bc725
--- /dev/null
@@ -0,0 +1,826 @@
+/***************************************************************************************[SimpSolver.cc]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+#include "mtl/Sort.h"
+#include "simp/SimpSolver.h"
+#include "utils/System.h"
+
+using namespace Glucose;
+
+//=================================================================================================
+// Options:
+
+
+static const char* _cat = "SIMP";
+
+static BoolOption   opt_use_asymm        (_cat, "asymm",        "Shrink clauses by asymmetric branching.", false);
+static BoolOption   opt_use_rcheck       (_cat, "rcheck",       "Check if a clause is already implied. (costly)", false);
+static BoolOption   opt_use_elim         (_cat, "elim",         "Perform variable elimination.", true);
+static IntOption    opt_grow             (_cat, "grow",         "Allow a variable elimination step to grow by a number of clauses.", 0);
+static IntOption    opt_clause_lim       (_cat, "cl-lim",       "Variables are not eliminated if it produces a resolvent with a length above this limit. -1 means no limit", 20,   IntRange(-1, INT32_MAX));
+static IntOption    opt_subsumption_lim  (_cat, "sub-lim",      "Do not check if subsumption against a clause larger than this. -1 means no limit.", 1000, IntRange(-1, INT32_MAX));
+static DoubleOption opt_simp_garbage_frac(_cat, "simp-gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered during simplification.",  0.5, DoubleRange(0, false, HUGE_VAL, false));
+
+
+//=================================================================================================
+// Constructor/Destructor:
+
+
+SimpSolver::SimpSolver() :
+   Solver()
+  , grow               (opt_grow)
+  , clause_lim         (opt_clause_lim)
+  , subsumption_lim    (opt_subsumption_lim)
+  , simp_garbage_frac  (opt_simp_garbage_frac)
+  , use_asymm          (opt_use_asymm)
+  , use_rcheck         (opt_use_rcheck)
+  , use_elim           (opt_use_elim)
+  , merges             (0)
+  , asymm_lits         (0)
+  , eliminated_vars    (0)
+  , elimorder          (1)
+  , use_simplification (true)
+  , occurs             (ClauseDeleted(ca))
+  , elim_heap          (ElimLt(n_occ))
+  , bwdsub_assigns     (0)
+  , n_touched          (0)
+{
+    vec<Lit> dummy(1,lit_Undef);
+    ca.extra_clause_field = true; // NOTE: must happen before allocating the dummy clause below.
+    bwdsub_tmpunit        = ca.alloc(dummy);
+    remove_satisfied      = false;
+}
+
+
+SimpSolver::~SimpSolver()
+{
+}
+
+
+
+SimpSolver::SimpSolver(const SimpSolver &s) : Solver(s)
+  , grow               (s.grow)
+  , clause_lim         (s.clause_lim)
+  , subsumption_lim    (s.subsumption_lim)
+  , simp_garbage_frac  (s.simp_garbage_frac)
+  , use_asymm          (s.use_asymm)
+  , use_rcheck         (s.use_rcheck)
+  , use_elim           (s.use_elim)
+  , merges             (s.merges)
+  , asymm_lits         (s.asymm_lits)
+  , eliminated_vars    (s.eliminated_vars)
+  , elimorder          (s.elimorder)
+  , use_simplification (s.use_simplification)
+  , occurs             (ClauseDeleted(ca))
+  , elim_heap          (ElimLt(n_occ))
+  , bwdsub_assigns     (s.bwdsub_assigns)
+  , n_touched          (s.n_touched)
+{
+    // TODO: Copy dummy... what is it???
+    vec<Lit> dummy(1,lit_Undef);
+    ca.extra_clause_field = true; // NOTE: must happen before allocating the dummy clause below.
+    bwdsub_tmpunit        = ca.alloc(dummy);
+    remove_satisfied      = false;
+    //End TODO  
+    
+    
+    s.elimclauses.memCopyTo(elimclauses);
+    s.touched.memCopyTo(touched);
+    s.occurs.copyTo(occurs);
+    s.n_occ.memCopyTo(n_occ);
+    s.elim_heap.copyTo(elim_heap);
+    s.subsumption_queue.copyTo(subsumption_queue);
+    s.frozen.memCopyTo(frozen);
+    s.eliminated.memCopyTo(eliminated);
+
+    use_simplification = s.use_simplification;
+    bwdsub_assigns = s.bwdsub_assigns;
+    n_touched = s.n_touched;
+    bwdsub_tmpunit = s.bwdsub_tmpunit;
+    qhead = s.qhead;
+    ok = s.ok;
+}
+
+
+
+Var SimpSolver::newVar(bool sign, bool dvar) {
+    Var v = Solver::newVar(sign, dvar);
+    frozen    .push((char)false);
+    eliminated.push((char)false);
+
+    if (use_simplification){
+        n_occ     .push(0);
+        n_occ     .push(0);
+        occurs    .init(v);
+        touched   .push(0);
+        elim_heap .insert(v);
+    }
+    return v; }
+
+lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp)
+{
+    vec<Var> extra_frozen;
+    lbool    result = l_True;
+    do_simp &= use_simplification;
+
+    if (do_simp){
+        // Assumptions must be temporarily frozen to run variable elimination:
+        for (int i = 0; i < assumptions.size(); i++){
+            Var v = var(assumptions[i]);
+
+            // If an assumption has been eliminated, remember it.
+            assert(!isEliminated(v));
+
+            if (!frozen[v]){
+                // Freeze and store.
+                setFrozen(v, true);
+                extra_frozen.push(v);
+            } }
+
+        result = lbool(eliminate(turn_off_simp));
+    }
+
+    if (result == l_True)
+        result = Solver::solve_();
+    else if (verbosity >= 1)
+        printf("===============================================================================\n");
+
+    if (result == l_True)
+        extendModel();
+
+    if (do_simp)
+        // Unfreeze the assumptions that were frozen:
+        for (int i = 0; i < extra_frozen.size(); i++)
+            setFrozen(extra_frozen[i], false);
+
+
+    return result;
+}
+
+
+
+bool SimpSolver::addClause_(vec<Lit>& ps)
+{
+#ifndef NDEBUG
+    for (int i = 0; i < ps.size(); i++)
+        assert(!isEliminated(var(ps[i])));
+#endif
+    int nclauses = clauses.size();
+
+    if (use_rcheck && implied(ps))
+        return true;
+
+    if (!Solver::addClause_(ps))
+        return false;
+
+    if(!parsing && certifiedUNSAT) {
+      for (int i = 0; i < ps.size(); i++)
+        fprintf(certifiedOutput, "%i " , (var(ps[i]) + 1) * (-2 * sign(ps[i]) + 1) );
+      fprintf(certifiedOutput, "0\n");
+    }
+
+    if (use_simplification && clauses.size() == nclauses + 1){
+        CRef          cr = clauses.last();
+        const Clause& c  = ca[cr];
+
+        // NOTE: the clause is added to the queue immediately and then
+        // again during 'gatherTouchedClauses()'. If nothing happens
+        // in between, it will only be checked once. Otherwise, it may
+        // be checked twice unnecessarily. This is an unfortunate
+        // consequence of how backward subsumption is used to mimic
+        // forward subsumption.
+        subsumption_queue.insert(cr);
+        for (int i = 0; i < c.size(); i++){
+            occurs[var(c[i])].push(cr);
+            n_occ[toInt(c[i])]++;
+            touched[var(c[i])] = 1;
+            n_touched++;
+            if (elim_heap.inHeap(var(c[i])))
+                elim_heap.increase(var(c[i]));
+        }
+    }
+
+    return true;
+}
+
+
+
+void SimpSolver::removeClause(CRef cr,bool inPurgatory)
+{
+    const Clause& c = ca[cr];
+
+    if (use_simplification)
+        for (int i = 0; i < c.size(); i++){
+            n_occ[toInt(c[i])]--;
+            updateElimHeap(var(c[i]));
+            occurs.smudge(var(c[i]));
+        }
+
+    Solver::removeClause(cr,inPurgatory);
+}
+
+
+bool SimpSolver::strengthenClause(CRef cr, Lit l)
+{
+    Clause& c = ca[cr];
+    assert(decisionLevel() == 0);
+    assert(use_simplification);
+
+    // FIX: this is too inefficient but would be nice to have (properly implemented)
+    // if (!find(subsumption_queue, &c))
+    subsumption_queue.insert(cr);
+
+    if (certifiedUNSAT) {
+      for (int i = 0; i < c.size(); i++)
+        if (c[i] != l) fprintf(certifiedOutput, "%i " , (var(c[i]) + 1) * (-2 * sign(c[i]) + 1) );
+      fprintf(certifiedOutput, "0\n");
+    }
+
+    if (c.size() == 2){
+        removeClause(cr);
+        c.strengthen(l);
+    }else{
+        if (certifiedUNSAT) {
+          fprintf(certifiedOutput, "d ");
+          for (int i = 0; i < c.size(); i++)
+            fprintf(certifiedOutput, "%i " , (var(c[i]) + 1) * (-2 * sign(c[i]) + 1) );
+          fprintf(certifiedOutput, "0\n");
+        }
+
+        detachClause(cr, true);
+        c.strengthen(l);
+        attachClause(cr);
+        remove(occurs[var(l)], cr);
+        n_occ[toInt(l)]--;
+        updateElimHeap(var(l));
+    }
+
+    return c.size() == 1 ? enqueue(c[0]) && propagate() == CRef_Undef : true;
+}
+
+
+// Returns FALSE if clause is always satisfied ('out_clause' should not be used).
+bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause)
+{
+    merges++;
+    out_clause.clear();
+
+    bool  ps_smallest = _ps.size() < _qs.size();
+    const Clause& ps  =  ps_smallest ? _qs : _ps;
+    const Clause& qs  =  ps_smallest ? _ps : _qs;
+
+    for (int i = 0; i < qs.size(); i++){
+        if (var(qs[i]) != v){
+            for (int j = 0; j < ps.size(); j++)
+                if (var(ps[j]) == var(qs[i]))
+                    if (ps[j] == ~qs[i])
+                        return false;
+                    else
+                        goto next;
+            out_clause.push(qs[i]);
+        }
+        next:;
+    }
+
+    for (int i = 0; i < ps.size(); i++)
+        if (var(ps[i]) != v)
+            out_clause.push(ps[i]);
+
+    return true;
+}
+
+
+// Returns FALSE if clause is always satisfied.
+bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, int& size)
+{
+    merges++;
+
+    bool  ps_smallest = _ps.size() < _qs.size();
+    const Clause& ps  =  ps_smallest ? _qs : _ps;
+    const Clause& qs  =  ps_smallest ? _ps : _qs;
+    const Lit*  __ps  = (const Lit*)ps;
+    const Lit*  __qs  = (const Lit*)qs;
+
+    size = ps.size()-1;
+
+    for (int i = 0; i < qs.size(); i++){
+        if (var(__qs[i]) != v){
+            for (int j = 0; j < ps.size(); j++)
+                if (var(__ps[j]) == var(__qs[i]))
+                    if (__ps[j] == ~__qs[i])
+                        return false;
+                    else
+                        goto next;
+            size++;
+        }
+        next:;
+    }
+
+    return true;
+}
+
+
+void SimpSolver::gatherTouchedClauses()
+{
+    if (n_touched == 0) return;
+
+    int i,j;
+    for (i = j = 0; i < subsumption_queue.size(); i++)
+        if (ca[subsumption_queue[i]].mark() == 0)
+            ca[subsumption_queue[i]].mark(2);
+
+    for (i = 0; i < touched.size(); i++)
+        if (touched[i]){
+            const vec<CRef>& cs = occurs.lookup(i);
+            for (j = 0; j < cs.size(); j++)
+                if (ca[cs[j]].mark() == 0){
+                    subsumption_queue.insert(cs[j]);
+                    ca[cs[j]].mark(2);
+                }
+            touched[i] = 0;
+        }
+
+    for (i = 0; i < subsumption_queue.size(); i++)
+        if (ca[subsumption_queue[i]].mark() == 2)
+            ca[subsumption_queue[i]].mark(0);
+
+    n_touched = 0;
+}
+
+
+bool SimpSolver::implied(const vec<Lit>& c)
+{
+    assert(decisionLevel() == 0);
+
+    trail_lim.push(trail.size());
+    for (int i = 0; i < c.size(); i++)
+        if (value(c[i]) == l_True){
+            cancelUntil(0);
+            return false;
+        }else if (value(c[i]) != l_False){
+            assert(value(c[i]) == l_Undef);
+            uncheckedEnqueue(~c[i]);
+        }
+
+    bool result = propagate() != CRef_Undef;
+    cancelUntil(0);
+    return result;
+}
+
+
+// Backward subsumption + backward subsumption resolution
+bool SimpSolver::backwardSubsumptionCheck(bool verbose)
+{
+    int cnt = 0;
+    int subsumed = 0;
+    int deleted_literals = 0;
+    assert(decisionLevel() == 0);
+
+    while (subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()){
+
+        // Empty subsumption queue and return immediately on user-interrupt:
+        if (asynch_interrupt){
+            subsumption_queue.clear();
+            bwdsub_assigns = trail.size();
+            break; }
+
+        // Check top-level assignments by creating a dummy clause and placing it in the queue:
+        if (subsumption_queue.size() == 0 && bwdsub_assigns < trail.size()){
+            Lit l = trail[bwdsub_assigns++];
+            ca[bwdsub_tmpunit][0] = l;
+            ca[bwdsub_tmpunit].calcAbstraction();
+            subsumption_queue.insert(bwdsub_tmpunit); }
+
+        CRef    cr = subsumption_queue.peek(); subsumption_queue.pop();
+        Clause& c  = ca[cr];
+
+        if (c.mark()) continue;
+
+        if (verbose && verbosity >= 2 && cnt++ % 1000 == 0)
+            printf("subsumption left: %10d (%10d subsumed, %10d deleted literals)\r", subsumption_queue.size(), subsumed, deleted_literals);
+
+        assert(c.size() > 1 || value(c[0]) == l_True);    // Unit-clauses should have been propagated before this point.
+
+        // Find best variable to scan:
+        Var best = var(c[0]);
+        for (int i = 1; i < c.size(); i++)
+            if (occurs[var(c[i])].size() < occurs[best].size())
+                best = var(c[i]);
+
+        // Search all candidates:
+        vec<CRef>& _cs = occurs.lookup(best);
+        CRef*       cs = (CRef*)_cs;
+
+        for (int j = 0; j < _cs.size(); j++)
+            if (c.mark())
+                break;
+            else if (!ca[cs[j]].mark() &&  cs[j] != cr && (subsumption_lim == -1 || ca[cs[j]].size() < subsumption_lim)){
+                Lit l = c.subsumes(ca[cs[j]]);
+
+                if (l == lit_Undef)
+                    subsumed++, removeClause(cs[j]);
+                else if (l != lit_Error){
+                    deleted_literals++;
+
+                    if (!strengthenClause(cs[j], ~l))
+                        return false;
+
+                    // Did current candidate get deleted from cs? Then check candidate at index j again:
+                    if (var(l) == best)
+                        j--;
+                }
+            }
+    }
+
+    return true;
+}
+
+
+bool SimpSolver::asymm(Var v, CRef cr)
+{
+    Clause& c = ca[cr];
+    assert(decisionLevel() == 0);
+
+    if (c.mark() || satisfied(c)) return true;
+
+    trail_lim.push(trail.size());
+    Lit l = lit_Undef;
+    for (int i = 0; i < c.size(); i++)
+        if (var(c[i]) != v && value(c[i]) != l_False)
+            uncheckedEnqueue(~c[i]);
+        else
+            l = c[i];
+
+    if (propagate() != CRef_Undef){
+        cancelUntil(0);
+        asymm_lits++;
+        if (!strengthenClause(cr, l))
+            return false;
+    }else
+        cancelUntil(0);
+
+    return true;
+}
+
+
+bool SimpSolver::asymmVar(Var v)
+{
+    assert(use_simplification);
+
+    const vec<CRef>& cls = occurs.lookup(v);
+
+    if (value(v) != l_Undef || cls.size() == 0)
+        return true;
+
+    for (int i = 0; i < cls.size(); i++)
+        if (!asymm(v, cls[i]))
+            return false;
+
+    return backwardSubsumptionCheck();
+}
+
+
+static void mkElimClause(vec<uint32_t>& elimclauses, Lit x)
+{
+    elimclauses.push(toInt(x));
+    elimclauses.push(1);
+}
+
+
+static void mkElimClause(vec<uint32_t>& elimclauses, Var v, Clause& c)
+{
+    int first = elimclauses.size();
+    int v_pos = -1;
+
+    // Copy clause to elimclauses-vector. Remember position where the
+    // variable 'v' occurs:
+    for (int i = 0; i < c.size(); i++){
+        elimclauses.push(toInt(c[i]));
+        if (var(c[i]) == v)
+            v_pos = i + first;
+    }
+    assert(v_pos != -1);
+
+    // Swap the first literal with the 'v' literal, so that the literal
+    // containing 'v' will occur first in the clause:
+    uint32_t tmp = elimclauses[v_pos];
+    elimclauses[v_pos] = elimclauses[first];
+    elimclauses[first] = tmp;
+
+    // Store the length of the clause last:
+    elimclauses.push(c.size());
+}
+
+
+
+bool SimpSolver::eliminateVar(Var v)
+{
+    assert(!frozen[v]);
+    assert(!isEliminated(v));
+    assert(value(v) == l_Undef);
+
+    // Split the occurrences into positive and negative:
+    //
+    const vec<CRef>& cls = occurs.lookup(v);
+    vec<CRef>        pos, neg;
+    for (int i = 0; i < cls.size(); i++)
+        (find(ca[cls[i]], mkLit(v)) ? pos : neg).push(cls[i]);
+
+    // Check wether the increase in number of clauses stays within the allowed ('grow'). Moreover, no
+    // clause must exceed the limit on the maximal clause size (if it is set):
+    //
+    int cnt         = 0;
+    int clause_size = 0;
+
+    for (int i = 0; i < pos.size(); i++)
+        for (int j = 0; j < neg.size(); j++)
+            if (merge(ca[pos[i]], ca[neg[j]], v, clause_size) && 
+                (++cnt > cls.size() + grow || (clause_lim != -1 && clause_size > clause_lim)))
+                return true;
+
+    // Delete and store old clauses:
+    eliminated[v] = true;
+    setDecisionVar(v, false);
+    eliminated_vars++;
+
+    if (pos.size() > neg.size()){
+        for (int i = 0; i < neg.size(); i++)
+            mkElimClause(elimclauses, v, ca[neg[i]]);
+        mkElimClause(elimclauses, mkLit(v));
+    }else{
+        for (int i = 0; i < pos.size(); i++)
+            mkElimClause(elimclauses, v, ca[pos[i]]);
+        mkElimClause(elimclauses, ~mkLit(v));
+    }
+
+
+    // Produce clauses in cross product:
+    vec<Lit>& resolvent = add_tmp;
+    for (int i = 0; i < pos.size(); i++)
+        for (int j = 0; j < neg.size(); j++)
+            if (merge(ca[pos[i]], ca[neg[j]], v, resolvent) && !addClause_(resolvent))
+                return false;
+
+    for (int i = 0; i < cls.size(); i++)
+        removeClause(cls[i]);
+
+    // Free occurs list for this variable:
+    occurs[v].clear(true);
+
+    // Free watchers lists for this variable, if possible:
+    if (watches[ mkLit(v)].size() == 0) watches[ mkLit(v)].clear(true);
+    if (watches[~mkLit(v)].size() == 0) watches[~mkLit(v)].clear(true);
+
+    return backwardSubsumptionCheck();
+}
+
+
+bool SimpSolver::substitute(Var v, Lit x)
+{
+    assert(!frozen[v]);
+    assert(!isEliminated(v));
+    assert(value(v) == l_Undef);
+
+    if (!ok) return false;
+
+    eliminated[v] = true;
+    setDecisionVar(v, false);
+    const vec<CRef>& cls = occurs.lookup(v);
+    
+    vec<Lit>& subst_clause = add_tmp;
+    for (int i = 0; i < cls.size(); i++){
+        Clause& c = ca[cls[i]];
+
+        subst_clause.clear();
+        for (int j = 0; j < c.size(); j++){
+            Lit p = c[j];
+            subst_clause.push(var(p) == v ? x ^ sign(p) : p);
+        }
+
+        if (!addClause_(subst_clause))
+            return ok = false;
+
+       removeClause(cls[i]);
+   }
+
+    return true;
+}
+
+
+void SimpSolver::extendModel()
+{
+    int i, j;
+    Lit x;
+
+    if(model.size()==0) model.growTo(nVars());
+    
+    for (i = elimclauses.size()-1; i > 0; i -= j){
+        for (j = elimclauses[i--]; j > 1; j--, i--)
+            if (modelValue(toLit(elimclauses[i])) != l_False)
+                goto next;
+
+        x = toLit(elimclauses[i]);
+        model[var(x)] = lbool(!sign(x));
+    next:;
+    }
+}
+
+
+bool SimpSolver::eliminate(bool turn_off_elim)
+{
+    if (!simplify()) {
+        ok = false;
+        return false;
+    }
+    else if (!use_simplification)
+        return true;
+
+    // Main simplification loop:
+    //
+
+    int toPerform = clauses.size()<=4800000;
+    
+    if(!toPerform) {
+      printf("c Too many clauses... No preprocessing\n");
+    }
+
+    while (toPerform && (n_touched > 0 || bwdsub_assigns < trail.size() || elim_heap.size() > 0)){
+
+        gatherTouchedClauses();
+        // printf("  ## (time = %6.2f s) BWD-SUB: queue = %d, trail = %d\n", cpuTime(), subsumption_queue.size(), trail.size() - bwdsub_assigns);
+        if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()) && 
+            !backwardSubsumptionCheck(true)){
+            ok = false; goto cleanup; }
+
+        // Empty elim_heap and return immediately on user-interrupt:
+        if (asynch_interrupt){
+            assert(bwdsub_assigns == trail.size());
+            assert(subsumption_queue.size() == 0);
+            assert(n_touched == 0);
+            elim_heap.clear();
+            goto cleanup; }
+
+        // printf("  ## (time = %6.2f s) ELIM: vars = %d\n", cpuTime(), elim_heap.size());
+        for (int cnt = 0; !elim_heap.empty(); cnt++){
+            Var elim = elim_heap.removeMin();
+            
+            if (asynch_interrupt) break;
+
+            if (isEliminated(elim) || value(elim) != l_Undef) continue;
+
+            if (verbosity >= 2 && cnt % 100 == 0)
+                printf("elimination left: %10d\r", elim_heap.size());
+
+            if (use_asymm){
+                // Temporarily freeze variable. Otherwise, it would immediately end up on the queue again:
+                bool was_frozen = frozen[elim];
+                frozen[elim] = true;
+                if (!asymmVar(elim)){
+                    ok = false; goto cleanup; }
+                frozen[elim] = was_frozen; }
+
+            // At this point, the variable may have been set by assymetric branching, so check it
+            // again. Also, don't eliminate frozen variables:
+            if (use_elim && value(elim) == l_Undef && !frozen[elim] && !eliminateVar(elim)){
+                ok = false; goto cleanup; }
+
+            checkGarbage(simp_garbage_frac);
+        }
+
+        assert(subsumption_queue.size() == 0);
+    }
+ cleanup:
+
+    // If no more simplification is needed, free all simplification-related data structures:
+    if (turn_off_elim){
+        touched  .clear(true);
+        occurs   .clear(true);
+        n_occ    .clear(true);
+        elim_heap.clear(true);
+        subsumption_queue.clear(true);
+
+        use_simplification    = false;
+        remove_satisfied      = true;
+        ca.extra_clause_field = false;
+
+        // Force full cleanup (this is safe and desirable since it only happens once):
+        rebuildOrderHeap();
+        garbageCollect();
+    }else{
+        // Cheaper cleanup:
+        cleanUpClauses(); // TODO: can we make 'cleanUpClauses()' not be linear in the problem size somehow?
+        checkGarbage();
+    }
+
+    if (verbosity >= 0 && elimclauses.size() > 0)
+        printf("c |  Eliminated clauses:     %10.2f Mb                                                                |\n", 
+               double(elimclauses.size() * sizeof(uint32_t)) / (1024*1024));
+
+               
+    return ok;
+
+    
+}
+
+
+void SimpSolver::cleanUpClauses()
+{
+    occurs.cleanAll();
+    int i,j;
+    for (i = j = 0; i < clauses.size(); i++)
+        if (ca[clauses[i]].mark() == 0)
+            clauses[j++] = clauses[i];
+    clauses.shrink(i - j);
+}
+
+
+//=================================================================================================
+// Garbage Collection methods:
+
+
+void SimpSolver::relocAll(ClauseAllocator& to)
+{
+    if (!use_simplification) return;
+
+    // All occurs lists:
+    //
+    for (int i = 0; i < nVars(); i++){
+        vec<CRef>& cs = occurs[i];
+        for (int j = 0; j < cs.size(); j++)
+            ca.reloc(cs[j], to);
+    }
+
+    // Subsumption queue:
+    //
+    for (int i = 0; i < subsumption_queue.size(); i++)
+        ca.reloc(subsumption_queue[i], to);
+
+    // Temporary clause:
+    //
+    ca.reloc(bwdsub_tmpunit, to);
+}
+
+
+void SimpSolver::garbageCollect()
+{
+    // Initialize the next region to a size corresponding to the estimated utilization degree. This
+    // is not precise but should avoid some unnecessary reallocations for the new region:
+    ClauseAllocator to(ca.size() - ca.wasted()); 
+
+    cleanUpClauses();
+    to.extra_clause_field = ca.extra_clause_field; // NOTE: this is important to keep (or lose) the extra fields.
+    relocAll(to);
+    Solver::relocAll(to);
+    if (verbosity >= 2)
+        printf("|  Garbage collection:   %12d bytes => %12d bytes             |\n", 
+               ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size);
+    to.moveTo(ca);
+}
diff --git a/glucose-syrup/simp/SimpSolver.h b/glucose-syrup/simp/SimpSolver.h
new file mode 100644 (file)
index 0000000..5f457a8
--- /dev/null
@@ -0,0 +1,237 @@
+/***************************************************************************************[SimpSolver.h]
+ Glucose -- Copyright (c) 2009-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                LRI  - Univ. Paris Sud, France (2009-2013)
+                                Labri - Univ. Bordeaux, France
+
+ Syrup (Glucose Parallel) -- Copyright (c) 2013-2014, Gilles Audemard, Laurent Simon
+                                CRIL - Univ. Artois, France
+                                Labri - Univ. Bordeaux, France
+
+Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
+Glucose (sources until 2013, Glucose 3.0, single core) are exactly the same as Minisat on which it 
+is based on. (see below).
+
+Glucose-Syrup sources are based on another copyright. Permissions and copyrights for the parallel
+version of Glucose-Syrup (the "Software") are granted, free of charge, to deal with the Software
+without restriction, including the rights to use, copy, modify, merge, publish, distribute,
+sublicence, 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 and below copyrights notices and this permission notice shall be included in all
+copies or substantial portions of the Software;
+- The parallel version of Glucose (all files modified since Glucose 3.0 releases, 2013) cannot
+be used in any competitive event (sat competitions/evaluations) without the express permission of 
+the authors (Gilles Audemard / Laurent Simon). This is also the case for any competitive event
+using Glucose Parallel as an embedded SAT engine (single core or not).
+
+
+--------------- Original Minisat Copyrights
+
+Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+Copyright (c) 2007-2010, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************************************/
+
+#ifndef Glucose_SimpSolver_h
+#define Glucose_SimpSolver_h
+
+#include "mtl/Queue.h"
+#include "core/Solver.h"
+#include "mtl/Clone.h"
+
+namespace Glucose {
+
+//=================================================================================================
+
+
+class SimpSolver : public Solver {
+ public:
+    // Constructor/Destructor:
+    //
+    SimpSolver();
+    ~SimpSolver();
+    
+    SimpSolver(const  SimpSolver &s);
+    
+
+    /**
+     * Clone function
+    */
+    virtual Clone* clone() const {
+        return  new SimpSolver(*this);
+    }   
+
+    
+    // Problem specification:
+    //
+    virtual Var     newVar    (bool polarity = true, bool dvar = true); // Add a new variable with parameters specifying variable mode.
+    bool    addClause (const vec<Lit>& ps);
+    bool    addEmptyClause();                // Add the empty clause to the solver.
+    bool    addClause (Lit p);               // Add a unit clause to the solver.
+    bool    addClause (Lit p, Lit q);        // Add a binary clause to the solver.
+    bool    addClause (Lit p, Lit q, Lit r); // Add a ternary clause to the solver.
+    virtual bool    addClause_(      vec<Lit>& ps);
+    bool    substitute(Var v, Lit x);  // Replace all occurences of v with x (may cause a contradiction).
+
+    // Variable mode:
+    // 
+    void    setFrozen (Var v, bool b); // If a variable is frozen it will not be eliminated.
+    bool    isEliminated(Var v) const;
+
+    // Solving:
+    //
+    bool    solve       (const vec<Lit>& assumps, bool do_simp = true, bool turn_off_simp = false);
+    lbool   solveLimited(const vec<Lit>& assumps, bool do_simp = true, bool turn_off_simp = false);
+    bool    solve       (                     bool do_simp = true, bool turn_off_simp = false);
+    bool    solve       (Lit p       ,        bool do_simp = true, bool turn_off_simp = false);       
+    bool    solve       (Lit p, Lit q,        bool do_simp = true, bool turn_off_simp = false);
+    bool    solve       (Lit p, Lit q, Lit r, bool do_simp = true, bool turn_off_simp = false);
+    bool    eliminate   (bool turn_off_elim = false);  // Perform variable elimination based simplification. 
+
+    // Memory managment:
+    //
+    virtual void garbageCollect();
+
+
+    // Generate a (possibly simplified) DIMACS file:
+    //
+#if 0
+    void    toDimacs  (const char* file, const vec<Lit>& assumps);
+    void    toDimacs  (const char* file);
+    void    toDimacs  (const char* file, Lit p);
+    void    toDimacs  (const char* file, Lit p, Lit q);
+    void    toDimacs  (const char* file, Lit p, Lit q, Lit r);
+#endif
+
+    // Mode of operation:
+    //
+    int     parsing;
+    int     grow;              // Allow a variable elimination step to grow by a number of clauses (default to zero).
+    int     clause_lim;        // Variables are not eliminated if it produces a resolvent with a length above this limit.
+                               // -1 means no limit.
+    int     subsumption_lim;   // Do not check if subsumption against a clause larger than this. -1 means no limit.
+    double  simp_garbage_frac; // A different limit for when to issue a GC during simplification (Also see 'garbage_frac').
+
+    bool    use_asymm;         // Shrink clauses by asymmetric branching.
+    bool    use_rcheck;        // Check if a clause is already implied. Prett costly, and subsumes subsumptions :)
+    bool    use_elim;          // Perform variable elimination.
+    // Statistics:
+    //
+    int     merges;
+    int     asymm_lits;
+    int     eliminated_vars;
+
+ protected:
+
+    // Helper structures:
+    //
+    struct ElimLt {
+        const vec<int>& n_occ;
+        explicit ElimLt(const vec<int>& no) : n_occ(no) {}
+
+        // TODO: are 64-bit operations here noticably bad on 32-bit platforms? Could use a saturating
+        // 32-bit implementation instead then, but this will have to do for now.
+        uint64_t cost  (Var x)        const { return (uint64_t)n_occ[toInt(mkLit(x))] * (uint64_t)n_occ[toInt(~mkLit(x))]; }
+        bool operator()(Var x, Var y) const { return cost(x) < cost(y); }
+        
+        // TODO: investigate this order alternative more.
+        // bool operator()(Var x, Var y) const { 
+        //     int c_x = cost(x);
+        //     int c_y = cost(y);
+        //     return c_x < c_y || c_x == c_y && x < y; }
+    };
+
+    struct ClauseDeleted {
+        const ClauseAllocator& ca;
+        explicit ClauseDeleted(const ClauseAllocator& _ca) : ca(_ca) {}
+        bool operator()(const CRef& cr) const { return ca[cr].mark() == 1; } };
+
+    // Solver state:
+    //
+    int                 elimorder;
+    bool                use_simplification;
+    vec<uint32_t>       elimclauses;
+    vec<char>           touched;
+    OccLists<Var, vec<CRef>, ClauseDeleted>
+                        occurs;
+    vec<int>            n_occ;
+    Heap<ElimLt>        elim_heap;
+    Queue<CRef>         subsumption_queue;
+    vec<char>           frozen;
+    vec<char>           eliminated;
+    int                 bwdsub_assigns;
+    int                 n_touched;
+
+    // Temporaries:
+    //
+    CRef                bwdsub_tmpunit;
+
+    // Main internal methods:
+    //
+    virtual lbool         solve_                   (bool do_simp = true, bool turn_off_simp = false);
+    bool          asymm                    (Var v, CRef cr);
+    bool          asymmVar                 (Var v);
+    void          updateElimHeap           (Var v);
+    void          gatherTouchedClauses     ();
+    bool          merge                    (const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause);
+    bool          merge                    (const Clause& _ps,