picosat (empty) → 0.1.0.0
raw patch · 6 files changed
+9379/−0 lines, 6 filesdep +basesetup-changed
Dependencies added: base
Files
- LICENSE +19/−0
- Setup.hs +2/−0
- cbits/picosat.c +8589/−0
- cbits/picosat.h +644/−0
- picosat.cabal +35/−0
- src/Picosat.hs +90/−0
+ LICENSE view
@@ -0,0 +1,19 @@+Copyright (c) 2013, Stephen Diehl++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.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ cbits/picosat.c view
@@ -0,0 +1,8589 @@+/****************************************************************************+Copyright (c) 2006 - 2012, Armin Biere, Johannes Kepler University.++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 <stdlib.h>+#include <stdio.h>+#include <string.h>+#include <assert.h>+#include <limits.h>+#include <ctype.h>+#include <stdarg.h>++#include "picosat.h"++/* By default code for 'all different constraints' is disabled, since 'NADC'+ * is defined.+ */+#define NADC++/* By default we enable failed literals, since 'NFL' is undefined.+ *+#define NFL+ */++/* By default we 'detach satisfied (large) clauses', e.g. NDSC undefined.+ *+#define NDSC+ */++/* Do not use luby restart schedule instead of inner/outer.+ *+#define NLUBY+ */++/* Enabling this define, will use gnuplot to visualize how the scores evolve.+ *+#define VISCORES+ */+#ifdef VISCORES+// #define WRITEGIF /* ... to generate a video */+#endif++#ifdef VISCORES+#ifndef WRITEGIF+#include <unistd.h> /* for 'usleep' */+#endif+#endif++#define MINRESTART 100 /* minimum restart interval */+#define MAXRESTART 1000000 /* maximum restart interval */+#define RDECIDE 1000 /* interval of random decisions */+#define FRESTART 110 /* restart increase factor in percent */+#define FREDUCE 110 /* reduce increase factor in percent */+#define FREDADJ 121 /* reduce increase adjustment factor */+#define MAXCILS 10 /* maximal number of unrecycled internals */+#define FFLIPPED 10000 /* flipped reduce factor */+#define FFLIPPEDPREC 10000000/* flipped reduce factor precision */++#ifndef TRACE+#define NO_BINARY_CLAUSES /* store binary clauses more compactly */+#endif++/* For debugging purposes you may want to define 'LOGGING', which actually+ * can be enforced by using the '--log' option for the configure script.+ */+#ifdef LOGGING+#define LOG(code) do { code; } while (0)+#else+#define LOG(code) do { } while (0)+#endif+#define NOLOG(code) do { } while (0) /* log exception */+#define ONLYLOG(code) do { code; } while (0) /* force logging */++#define FALSE ((Val)-1)+#define UNDEF ((Val)0)+#define TRUE ((Val)1)++#define COMPACT_TRACECHECK_TRACE_FMT 0+#define EXTENDED_TRACECHECK_TRACE_FMT 1+#define RUP_TRACE_FMT 2++#define NEWN(p,n) do { (p) = new (ps, sizeof (*(p)) * (n)); } while (0)+#define CLRN(p,n) do { memset ((p), 0, sizeof (*(p)) * (n)); } while (0)+#define CLR(p) CLRN(p,1)+#define DELETEN(p,n) \+ do { delete (ps, p, sizeof (*(p)) * (n)); (p) = 0; } while (0)++#define RESIZEN(p,old_num,new_num) \+ do { \+ size_t old_size = sizeof (*(p)) * (old_num); \+ size_t new_size = sizeof (*(p)) * (new_num); \+ (p) = resize (ps, (p), old_size, new_size) ; \+ } while (0)++#define ENLARGE(start,head,end) \+ do { \+ unsigned old_num = (unsigned)((end) - (start)); \+ size_t new_num = old_num ? (2 * old_num) : 1; \+ unsigned count = (head) - (start); \+ assert ((start) <= (end)); \+ RESIZEN((start),old_num,new_num); \+ (head) = (start) + count; \+ (end) = (start) + new_num; \+ } while (0)++#define NOTLIT(l) (ps->lits + (1 ^ ((l) - ps->lits)))++#define LIT2IDX(l) ((unsigned)((l) - ps->lits) / 2)+#define LIT2IMPLS(l) (ps->impls + (unsigned)((l) - ps->lits))+#define LIT2INT(l) ((int)(LIT2SGN(l) * LIT2IDX(l)))+#define LIT2SGN(l) (((unsigned)((l) - ps->lits) & 1) ? -1 : 1)+#define LIT2VAR(l) (ps->vars + LIT2IDX(l))+#define LIT2HTPS(l) (ps->htps + (unsigned)((l) - ps->lits))+#define LIT2JWH(l) (ps->jwh + ((l) - ps->lits))++#ifndef NDSC+#define LIT2DHTPS(l) (ps->dhtps + (unsigned)((l) - ps->lits))+#endif++#ifdef NO_BINARY_CLAUSES+typedef unsigned long Wrd;+#define ISLITREASON(C) (1&(Wrd)C)+#define LIT2REASON(L) \+ (assert (L->val==TRUE), ((Cls*)(1 + (2*(L - ps->lits)))))+#define REASON2LIT(C) ((Lit*)(ps->lits + ((Wrd)C)/2))+#endif++#define ENDOFCLS(c) ((void*)((c)->lits + (c)->size))++#define SOC ((ps->oclauses == ps->ohead) ? ps->lclauses : ps->oclauses)+#define EOC (ps->lhead)+#define NXC(p) (((p) + 1 == ps->ohead) ? ps->lclauses : (p) + 1)++#define OIDX2IDX(idx) (2 * ((idx) + 1))+#define LIDX2IDX(idx) (2 * (idx) + 1)++#define ISLIDX(idx) ((idx)&1)++#define IDX2OIDX(idx) (assert(!ISLIDX(idx)), (idx)/2 - 1)+#define IDX2LIDX(idx) (assert(ISLIDX(idx)), (idx)/2)++#define EXPORTIDX(idx) \+ ((ISLIDX(idx) ? (IDX2LIDX (idx) + (ps->ohead - ps->oclauses)) : IDX2OIDX(idx)) + 1)++#define IDX2CLS(i) \+ (assert(i), (ISLIDX(i) ? ps->lclauses : ps->oclauses)[(i)/2 - !ISLIDX(i)])++#define IDX2ZHN(i) (assert(i), (ISLIDX(i) ? ps->zhains[(i)/2] : 0))++#define CLS2TRD(c) (((Trd*)(c)) - 1)+#define CLS2IDX(c) ((((Trd*)(c)) - 1)->idx)++#define CLS2ACT(c) \+ ((Act*)((assert((c)->learned)),assert((c)->size>2),ENDOFCLS(c)))++#define VAR2LIT(v) (ps->lits + 2 * ((v) - ps->vars))+#define VAR2RNK(v) (ps->rnks + ((v) - ps->vars))++#define RNK2LIT(r) (ps->lits + 2 * ((r) - ps->rnks))+#define RNK2VAR(r) (ps->vars + ((r) - ps->rnks))++#define BLK_FILL_BYTES 8+#define SIZE_OF_BLK (sizeof (Blk) - BLK_FILL_BYTES)++#define PTR2BLK(void_ptr) \+ ((void_ptr) ? (Blk*)(((char*)(void_ptr)) - SIZE_OF_BLK) : 0)++#define AVERAGE(a,b) ((b) ? (((double)a) / (double)(b)) : 0.0)+#define PERCENT(a,b) (100.0 * AVERAGE(a,b))++#define ABORT(msg) \+ do { \+ fputs ("*** picosat: " msg "\n", stderr); \+ abort (); \+ } while (0)++#define ABORTIF(cond,msg) \+ do { \+ if (!(cond)) break; \+ ABORT (msg); \+ } while (0)++#define ZEROFLT (0x00000000u)+#define EPSFLT (0x00000001u)+#define INFFLT (0xffffffffu)++#define FLTCARRY (1u << 25)+#define FLTMSB (1u << 24)+#define FLTMAXMANTISSA (FLTMSB - 1)++#define FLTMANTISSA(d) ((d) & FLTMAXMANTISSA)+#define FLTEXPONENT(d) ((int)((d) >> 24) - 128)++#define FLTMINEXPONENT (-128)+#define FLTMAXEXPONENT (127)++#define CMPSWAPFLT(a,b) \+ do { \+ Flt tmp; \+ if (((a) < (b))) \+ { \+ tmp = (a); \+ (a) = (b); \+ (b) = tmp; \+ } \+ } while (0)++#define UNPACKFLT(u,m,e) \+ do { \+ (m) = FLTMANTISSA(u); \+ (e) = FLTEXPONENT(u); \+ (m) |= FLTMSB; \+ } while (0)++#define INSERTION_SORT_LIMIT 10++#define SORTING_SWAP(T,p,q) \+do { \+ T tmp = *(q); \+ *(q) = *(p); \+ *(p) = tmp; \+} while (0)++#define SORTING_CMP_SWAP(T,cmp,p,q) \+do { \+ if ((cmp) (ps, *(p), *(q)) > 0) \+ SORTING_SWAP (T, p, q); \+} while(0)++#define QUICKSORT_PARTITION(T,cmp,a,l,r) \+do { \+ T pivot; \+ int j; \+ i = (l) - 1; /* result in 'i' */ \+ j = (r); \+ pivot = (a)[j]; \+ for (;;) \+ { \+ while ((cmp) (ps, (a)[++i], pivot) < 0) \+ ; \+ while ((cmp) (ps, pivot, (a)[--j]) < 0) \+ if (j == (l)) \+ break; \+ if (i >= j) \+ break; \+ SORTING_SWAP (T, (a) + i, (a) + j); \+ } \+ SORTING_SWAP (T, (a) + i, (a) + (r)); \+} while(0)++#define QUICKSORT(T,cmp,a,n) \+do { \+ int l = 0, r = (n) - 1, m, ll, rr, i; \+ assert (ps->ihead == ps->indices); \+ if (r - l <= INSERTION_SORT_LIMIT) \+ break; \+ for (;;) \+ { \+ m = (l + r) / 2; \+ SORTING_SWAP (T, (a) + m, (a) + r - 1); \+ SORTING_CMP_SWAP (T, cmp, (a) + l, (a) + r - 1); \+ SORTING_CMP_SWAP (T, cmp, (a) + l, (a) + r); \+ SORTING_CMP_SWAP (T, cmp, (a) + r - 1, (a) + r); \+ QUICKSORT_PARTITION (T, cmp, (a), l + 1, r - 1); \+ if (i - l < r - i) \+ { \+ ll = i + 1; \+ rr = r; \+ r = i - 1; \+ } \+ else \+ { \+ ll = l; \+ rr = i - 1; \+ l = i + 1; \+ } \+ if (r - l > INSERTION_SORT_LIMIT) \+ { \+ assert (rr - ll > INSERTION_SORT_LIMIT); \+ if (ps->ihead == ps->eoi) \+ ENLARGE (ps->indices, ps->ihead, ps->eoi); \+ *ps->ihead++ = ll; \+ if (ps->ihead == ps->eoi) \+ ENLARGE (ps->indices, ps->ihead, ps->eoi); \+ *ps->ihead++ = rr; \+ } \+ else if (rr - ll > INSERTION_SORT_LIMIT) \+ { \+ l = ll; \+ r = rr; \+ } \+ else if (ps->ihead > ps->indices) \+ { \+ r = *--ps->ihead; \+ l = *--ps->ihead; \+ } \+ else \+ break; \+ } \+} while (0)++#define INSERTION_SORT(T,cmp,a,n) \+do { \+ T pivot; \+ int l = 0, r = (n) - 1, i, j; \+ for (i = r; i > l; i--) \+ SORTING_CMP_SWAP (T, cmp, (a) + i - 1, (a) + i); \+ for (i = l + 2; i <= r; i++) \+ { \+ j = i; \+ pivot = (a)[i]; \+ while ((cmp) (ps, pivot, (a)[j - 1]) < 0) \+ { \+ (a)[j] = (a)[j - 1]; \+ j--; \+ } \+ (a)[j] = pivot; \+ } \+} while (0)++#ifdef NDEBUG+#define CHECK_SORTED(cmp,a,n) do { } while(0)+#else+#define CHECK_SORTED(cmp,a,n) \+do { \+ int i; \+ for (i = 0; i < (n) - 1; i++) \+ assert ((cmp) (ps, (a)[i], (a)[i + 1]) <= 0); \+} while(0)+#endif++#define SORT(T,cmp,a,n) \+do { \+ T * aa = (a); \+ int nn = (n); \+ QUICKSORT (T, cmp, aa, nn); \+ INSERTION_SORT (T, cmp, aa, nn); \+ assert (ps->ihead == ps->indices); \+ CHECK_SORTED (cmp, aa, nn); \+} while (0)++#define WRDSZ (sizeof (long) * 8)++typedef unsigned Flt; /* 32 bit deterministic soft float */+typedef Flt Act; /* clause and variable activity */+typedef struct Blk Blk; /* allocated memory block */+typedef struct Cls Cls; /* clause */+typedef struct Lit Lit; /* literal */+typedef struct Rnk Rnk; /* variable to score mapping */+typedef signed char Val; /* TRUE, UNDEF, FALSE */+typedef struct Var Var; /* variable */+#ifdef TRACE+typedef struct Trd Trd; /* trace data for clauses */+typedef struct Zhn Zhn; /* compressed chain (=zain) data */+typedef unsigned char Znt; /* compressed antecedent data */+#endif++#ifdef NO_BINARY_CLAUSES+typedef struct Ltk Ltk;++struct Ltk+{+ Lit ** start;+ unsigned count : WRDSZ == 32 ? 27 : 32;+ unsigned ldsize : WRDSZ == 32 ? 5 : 32;+};+#endif++struct Lit+{+ Val val;+};++struct Var+{+ unsigned mark : 1; /*bit 1*/+ unsigned resolved : 1; /*bit 2*/+ unsigned phase : 1; /*bit 3*/+ unsigned assigned : 1; /*bit 4*/+ unsigned used : 1; /*bit 5*/+ unsigned failed : 1; /*bit 6*/+ unsigned internal : 1; /*bit 7*/+ unsigned usedefphase : 1; /*bit 8*/+ unsigned defphase : 1; /*bit 9*/+ unsigned msspos : 1; /*bit 10*/+ unsigned mssneg : 1; /*bit 11*/+ unsigned humuspos : 1; /*bit 12*/+ unsigned humusneg : 1; /*bit 13*/+ unsigned partial : 1; /*bit 14*/+#ifdef TRACE+ unsigned core : 1; /*bit 15*/+#endif+ unsigned level;+ Cls *reason;+#ifndef NADC+ Lit ** inado;+ Lit ** ado;+ Lit *** adotabpos;+#endif+};++struct Rnk+{+ Act score;+ unsigned pos : 30; /* 0 iff not on heap */+ unsigned moreimportant : 1;+ unsigned lessimportant : 1;+};++struct Cls+{+ unsigned size;++ unsigned collect:1; /* bit 1 */+ unsigned learned:1; /* bit 2 */+ unsigned locked:1; /* bit 3 */+ unsigned used:1; /* bit 4 */+#ifndef NDEBUG+ unsigned connected:1; /* bit 5 */+#endif+#ifdef TRACE+ unsigned collected:1; /* bit 6 */+ unsigned core:1; /* bit 7 */+#endif++#define LDMAXGLUE 25 /* 32 - 7 */+#define MAXGLUE ((1<<LDMAXGLUE)-1)++ unsigned glue:LDMAXGLUE;++ Cls *next[2];+ Lit *lits[2];+};++#ifdef TRACE+struct Zhn+{+ unsigned ref:31;+ unsigned core:1;+ Znt * liz;+ Znt znt[0];+};++struct Trd+{+ unsigned idx;+ Cls cls[0];+};+#endif++struct Blk+{+#ifndef NDEBUG+ union+ {+ size_t size; /* this is what we really use */+ void *as_two_ptrs[2]; /* 2 * sizeof (void*) alignment of data */+ }+ header;+#endif+ char data[BLK_FILL_BYTES];+};++enum State+{+ RESET = 0,+ READY = 1,+ SAT = 2,+ UNSAT = 3,+ UNKNOWN = 4,+};++enum Phase+{+ POSPHASE,+ NEGPHASE,+ JWLPHASE,+ RNDPHASE,+};++struct PicoSAT+{+ enum State state;+ enum Phase defaultphase;+ int last_sat_call_result;++ FILE *out;+ char * prefix;+ int verbosity;+ int plain;+ unsigned LEVEL;+ unsigned max_var;+ unsigned size_vars;++ Lit *lits;+ Var *vars;+ Rnk *rnks;+ Flt *jwh;+ Cls **htps;+#ifndef NDSC+ Cls **dhtps;+#endif+#ifdef NO_BINARY_CLAUSES+ Ltk *impls;+ Cls impl, cimpl;+ int implvalid, cimplvalid;+#else+ Cls **impls;+#endif+ Lit **trail, **thead, **eot, **ttail, ** ttail2;+#ifndef NADC+ Lit **ttailado;+#endif+ unsigned adecidelevel;+ Lit **als, **alshead, **alstail, **eoals;+ Lit **CLS, **clshead, **eocls;+ int *rils, *rilshead, *eorils;+ int *cils, *cilshead, *eocils;+ int *fals, *falshead, *eofals;+ int *mass, szmass;+ int *mssass, szmssass;+ int *mcsass, nmcsass, szmcsass;+ int *humus, szhumus;+ Lit *failed_assumption;+ int extracted_all_failed_assumptions;+ Rnk **heap, **hhead, **eoh;+ Cls **oclauses, **ohead, **eoo; /* original clauses */+ Cls **lclauses, **lhead, ** EOL; /* learned clauses */+ int * soclauses, * sohead, * eoso; /* saved original clauses */+ int saveorig;+ int partial;+#ifdef TRACE+ int trace;+ Zhn **zhains, **zhead, **eoz;+ int ocore;+#endif+ FILE * rup;+ int rupstarted;+ int rupvariables;+ int rupclauses;+ Cls *mtcls;+ Cls *conflict;+ Lit **added, **ahead, **eoa;+ Var **marked, **mhead, **eom;+ Var **dfs, **dhead, **eod;+ Cls **resolved, **rhead, **eor;+ unsigned char *levels, *levelshead, *eolevels;+ unsigned *dused, *dusedhead, *eodused;+ unsigned char *buffer, *bhead, *eob;+ Act vinc, lscore, ilvinc, ifvinc;+#ifdef VISCORES+ Act fvinc, nvinc;+#endif+ Act cinc, lcinc, ilcinc, fcinc;+ unsigned srng;+ size_t current_bytes;+ size_t max_bytes;+ size_t recycled;+ double seconds, flseconds;+ double entered;+ unsigned nentered;+ int measurealltimeinlib;+ char *rline[2];+ int szrline, RCOUNT;+ double levelsum;+ unsigned iterations;+ int reports;+ int lastrheader;+ unsigned calls;+ unsigned decisions;+ unsigned restarts;+ unsigned simps;+ unsigned fsimplify;+ unsigned isimplify;+ unsigned reductions;+ unsigned lreduce;+ unsigned lreduceadjustcnt;+ unsigned lreduceadjustinc;+ unsigned lastreduceconflicts;+ unsigned llocked; /* locked large learned clauses */+ unsigned lrestart;+#ifdef NLUBY+ unsigned drestart;+ unsigned ddrestart;+#else+ unsigned lubycnt;+ unsigned lubymaxdelta;+ int waslubymaxdelta;+#endif+ unsigned long long lsimplify;+ unsigned long long propagations;+ unsigned long long lpropagations;+ unsigned fixed; /* top level assignments */+#ifndef NFL+ unsigned failedlits;+ unsigned ifailedlits;+ unsigned efailedlits;+ unsigned flcalls;+#ifdef STATS+ unsigned flrounds;+ unsigned long long flprops;+ unsigned long long floopsed, fltried, flskipped;+#endif+ unsigned long long fllimit;+ int simplifying;+ Lit ** saved;+ unsigned saved_size;+#endif+ unsigned conflicts;+ unsigned contexts;+ unsigned internals;+ unsigned noclauses; /* current number large original clauses */+ unsigned nlclauses; /* current number large learned clauses */+ unsigned olits; /* current literals in large original clauses */+ unsigned llits; /* current literals in large learned clauses */+ unsigned oadded; /* added original clauses */+ unsigned ladded; /* added learned clauses */+ unsigned loadded; /* added original large clauses */+ unsigned lladded; /* added learned large clauses */+ unsigned addedclauses; /* oadded + ladded */+ unsigned vused; /* used variables */+ unsigned llitsadded; /* added learned literals */+ unsigned long long visits;+#ifdef STATS+ unsigned loused; /* used large original clauses */+ unsigned llused; /* used large learned clauses */+ unsigned long long bvisits;+ unsigned long long tvisits;+ unsigned long long lvisits;+ unsigned long long othertrue;+ unsigned long long othertrue2;+ unsigned long long othertruel;+ unsigned long long othertrue2u;+ unsigned long long othertruelu;+ unsigned long long ltraversals;+ unsigned long long traversals;+#ifdef TRACE+ unsigned long long antecedents;+#endif+ unsigned uips;+ unsigned znts;+ unsigned assumptions;+ unsigned rdecisions;+ unsigned sdecisions;+ size_t srecycled;+ size_t rrecycled;+ unsigned long long derefs;+#endif+ unsigned minimizedllits;+ unsigned nonminimizedllits;+#ifndef NADC+ Lit *** ados, *** hados, *** eados;+ Lit *** adotab;+ unsigned nadotab;+ unsigned szadotab;+ Cls * adoconflict;+ unsigned adoconflicts;+ unsigned adoconflictlimit;+ int addingtoado;+ int adodisabled;+#endif+ unsigned long long flips;+#ifdef STATS+ unsigned long long FORCED;+ unsigned long long assignments;+ unsigned inclreduces;+ unsigned staticphasedecisions;+ unsigned skippedrestarts;+#endif+ int * indices, * ihead, *eoi;+ unsigned sdflips;++ unsigned long long saved_flips;+ unsigned saved_max_var;+ unsigned min_flipped;++ void * emgr;+ picosat_malloc enew;+ picosat_realloc eresize;+ picosat_free edelete;++#ifdef VISCORES+ FILE * fviscores;+#endif+};++typedef PicoSAT PS;++static Flt+packflt (unsigned m, int e)+{+ Flt res;+ assert (m < FLTMSB);+ assert (FLTMINEXPONENT <= e);+ assert (e <= FLTMAXEXPONENT);+ res = m | ((e + 128) << 24);+ return res;+}++static Flt+base2flt (unsigned m, int e)+{+ if (!m)+ return ZEROFLT;++ if (m < FLTMSB)+ {+ do+ {+ if (e <= FLTMINEXPONENT)+ return EPSFLT;++ e--;+ m <<= 1;++ }+ while (m < FLTMSB);+ }+ else+ {+ while (m >= FLTCARRY)+ {+ if (e >= FLTMAXEXPONENT)+ return INFFLT;++ e++;+ m >>= 1;+ }+ }++ m &= ~FLTMSB;+ return packflt (m, e);+}++static Flt+addflt (Flt a, Flt b)+{+ unsigned ma, mb, delta;+ int ea, eb;++ CMPSWAPFLT (a, b);+ if (!b)+ return a;++ UNPACKFLT (a, ma, ea);+ UNPACKFLT (b, mb, eb);++ assert (ea >= eb);+ delta = ea - eb;+ mb >>= delta;+ if (!mb)+ return a;++ ma += mb;+ if (ma & FLTCARRY)+ {+ if (ea == FLTMAXEXPONENT)+ return INFFLT;++ ea++;+ ma >>= 1;+ }++ assert (ma < FLTCARRY);+ ma &= FLTMAXMANTISSA;++ return packflt (ma, ea);+}++static Flt+mulflt (Flt a, Flt b)+{+ unsigned ma, mb;+ unsigned long long accu;+ int ea, eb;++ CMPSWAPFLT (a, b);+ if (!b)+ return ZEROFLT;++ UNPACKFLT (a, ma, ea);+ UNPACKFLT (b, mb, eb);++ ea += eb;+ ea += 24;+ if (ea > FLTMAXEXPONENT)+ return INFFLT;++ if (ea < FLTMINEXPONENT)+ return EPSFLT;++ accu = ma;+ accu *= mb;+ accu >>= 24;++ if (accu >= FLTCARRY)+ {+ if (ea == FLTMAXEXPONENT)+ return INFFLT;++ ea++;+ accu >>= 1;++ if (accu >= FLTCARRY)+ return INFFLT;+ }++ assert (accu < FLTCARRY);+ assert (accu & FLTMSB);++ ma = accu;+ ma &= ~FLTMSB;++ return packflt (ma, ea);+}++static Flt+ascii2flt (const char *str)+{+ Flt ten = base2flt (10, 0);+ Flt onetenth = base2flt (26843546, -28);+ Flt res = ZEROFLT, tmp, base;+ const char *p = str;+ char ch;++ ch = *p++;++ if (ch != '.')+ {+ if (!isdigit (ch))+ return INFFLT; /* better abort ? */++ res = base2flt (ch - '0', 0);++ while ((ch = *p++))+ {+ if (ch == '.')+ break;++ if (!isdigit (ch))+ return INFFLT; /* better abort? */++ res = mulflt (res, ten);+ tmp = base2flt (ch - '0', 0);+ res = addflt (res, tmp);+ }+ }++ if (ch == '.')+ {+ ch = *p++;+ if (!isdigit (ch))+ return INFFLT; /* better abort ? */++ base = onetenth;+ tmp = mulflt (base2flt (ch - '0', 0), base);+ res = addflt (res, tmp);++ while ((ch = *p++))+ {+ if (!isdigit (ch))+ return INFFLT; /* better abort? */++ base = mulflt (base, onetenth);+ tmp = mulflt (base2flt (ch - '0', 0), base);+ res = addflt (res, tmp);+ }+ }++ return res;+}++#if defined(VISCORES)++static double+flt2double (Flt f)+{+ double res;+ unsigned m;+ int e, i;++ UNPACKFLT (f, m, e);+ res = m;++ if (e < 0)+ {+ for (i = e; i < 0; i++)+ res *= 0.5;+ }+ else+ {+ for (i = 0; i < e; i++)+ res *= 2.0;+ }++ return res;+}++#endif++static int+log2flt (Flt a)+{+ return FLTEXPONENT (a) + 24;+}++static int+cmpflt (Flt a, Flt b)+{+ if (a < b)+ return -1;++ if (a > b)+ return 1;++ return 0;+}++static void *+new (PS * ps, size_t size)+{+ size_t bytes;+ Blk *b;++ if (!size)+ return 0;++ bytes = size + SIZE_OF_BLK;++ if (ps->enew)+ b = ps->enew (ps->emgr, bytes);+ else+ b = malloc (bytes);++ ABORTIF (!b, "out of memory in 'new'");+#ifndef NDEBUG+ b->header.size = size;+#endif+ ps->current_bytes += size;+ if (ps->current_bytes > ps->max_bytes)+ ps->max_bytes = ps->current_bytes;+ return b->data;+}++static void+delete (PS * ps, void *void_ptr, size_t size)+{+ size_t bytes;+ Blk *b;++ if (!void_ptr)+ {+ assert (!size);+ return;+ }++ assert (size);+ b = PTR2BLK (void_ptr);++ assert (size <= ps->current_bytes);+ ps->current_bytes -= size;++ assert (b->header.size == size);++ bytes = size + SIZE_OF_BLK;+ if (ps->edelete)+ ps->edelete (ps->emgr, b, bytes);+ else+ free (b);+}++static void *+resize (PS * ps, void *void_ptr, size_t old_size, size_t new_size)+{+ size_t old_bytes, new_bytes;+ Blk *b;++ b = PTR2BLK (void_ptr);++ assert (old_size <= ps->current_bytes);+ ps->current_bytes -= old_size;++ if ((old_bytes = old_size))+ {+ assert (old_size && b && b->header.size == old_size);+ old_bytes += SIZE_OF_BLK;+ }+ else+ assert (!b);++ if ((new_bytes = new_size))+ new_bytes += SIZE_OF_BLK;++ if (ps->eresize)+ b = ps->eresize (ps->emgr, b, old_bytes, new_bytes);+ else+ b = realloc (b, new_bytes);++ if (!new_size)+ {+ assert (!b);+ return 0;+ }++ ABORTIF (!b, "out of memory in 'resize'");+#ifndef NDEBUG+ b->header.size = new_size;+#endif++ ps->current_bytes += new_size;+ if (ps->current_bytes > ps->max_bytes)+ ps->max_bytes = ps->current_bytes;++ return b->data;+}++static unsigned+int2unsigned (int l)+{+ return (l < 0) ? 1 + 2 * -l : 2 * l;+}++static Lit *+int2lit (PS * ps, int l)+{+ return ps->lits + int2unsigned (l);+}++static Lit **+end_of_lits (Cls * c)+{+ return c->lits + c->size;+}++#if !defined(NDEBUG) || defined(LOGGING)++static void+dumplits (PS * ps, Lit ** l, Lit ** end)+{+ int first;+ Lit ** p;++ if (l == end)+ {+ /* empty clause */+ }+ else if (l + 1 == end)+ {+ fprintf (ps->out, "%d ", LIT2INT (l[0]));+ }+ else+ {+ assert (l + 2 <= end);+ first = (abs (LIT2INT (l[0])) > abs (LIT2INT (l[1])));+ fprintf (ps->out, "%d ", LIT2INT (l[first]));+ fprintf (ps->out, "%d ", LIT2INT (l[!first]));+ for (p = l + 2; p < end; p++)+ fprintf (ps->out, "%d ", LIT2INT (*p));+ }++ fputc ('0', ps->out);+}++static void+dumpcls (PS * ps, Cls * c)+{+ Lit **end;++ if (c)+ {+ end = end_of_lits (c);+ dumplits (ps, c->lits, end);+#ifdef TRACE+ if (ps->trace)+ fprintf (ps->out, " clause(%u)", CLS2IDX (c));+#endif+ }+ else+ fputs ("DECISION", ps->out);+}++static void+dumpclsnl (PS * ps, Cls * c)+{+ dumpcls (ps, c);+ fputc ('\n', ps->out);+}++void+dumpcnf (PS * ps)+{+ Cls **p, *c;++ for (p = SOC; p != EOC; p = NXC (p))+ {+ c = *p;++ if (!c)+ continue;++#ifdef TRACE+ if (c->collected)+ continue;+#endif++ dumpclsnl (ps, *p);+ }+}++#endif++static void+delete_prefix (PS * ps)+{+ if (!ps->prefix)+ return;++ delete (ps, ps->prefix, strlen (ps->prefix) + 1);+ ps->prefix = 0;+}++static void+new_prefix (PS * ps, const char * str)+{+ delete_prefix (ps);+ assert (str);+ ps->prefix = new (ps, strlen (str) + 1);+ strcpy (ps->prefix, str);+}++static PS *+init (void * pmgr,+ picosat_malloc pnew, picosat_realloc presize, picosat_free pdelete)+{+ PS * ps;++#if 0+ int count = 3 - !pnew - !presize - !pdelete;++ ABORTIF (count && !pnew, "API usage: missing 'picosat_set_new'");+ ABORTIF (count && !presize, "API usage: missing 'picosat_set_resize'");+ ABORTIF (count && !pdelete, "API usage: missing 'picosat_set_delete'");+#endif++ ps = pnew ? pnew (pmgr, sizeof *ps) : malloc (sizeof *ps);+ ABORTIF (!ps, "failed to allocate memory for PicoSAT manager");+ memset (ps, 0, sizeof *ps);++ ps->emgr = pmgr;+ ps->enew = pnew;+ ps->eresize = presize;+ ps->edelete = pdelete;++ ps->size_vars = 1;+ ps->state = RESET;+ ps->defaultphase = JWLPHASE;+#ifdef TRACE+ ps->ocore = -1;+#endif+ ps->lastrheader = -2;+#ifndef NADC+ ps->adoconflictlimit = UINT_MAX;+#endif+ ps->min_flipped = UINT_MAX;++ NEWN (ps->lits, 2 * ps->size_vars);+ NEWN (ps->jwh, 2 * ps->size_vars);+ NEWN (ps->htps, 2 * ps->size_vars);+#ifndef NDSC+ NEWN (ps->dhtps, 2 * ps->size_vars);+#endif+ NEWN (ps->impls, 2 * ps->size_vars);+ NEWN (ps->vars, ps->size_vars);+ NEWN (ps->rnks, ps->size_vars);++ /* because '0' pos denotes not on heap+ */+ ENLARGE (ps->heap, ps->hhead, ps->eoh);+ ps->hhead = ps->heap + 1;++ ps->vinc = base2flt (1, 0); /* initial var activity */+ ps->ifvinc = ascii2flt ("1.05"); /* var score rescore factor */+#ifdef VISCORES+ ps->fvinc = ascii2flt ("0.9523809"); /* 1/f = 1/1.05 */+ ps->nvinc = ascii2flt ("0.0476191"); /* 1 - 1/f = 1 - 1/1.05 */+#endif+ ps->lscore = base2flt (1, 90); /* var activity rescore limit */+ ps->ilvinc = base2flt (1, -90); /* inverse of 'lscore' */++ ps->cinc = base2flt (1, 0); /* initial clause activity */+ ps->fcinc = ascii2flt ("1.001"); /* cls activity rescore factor */+ ps->lcinc = base2flt (1, 90); /* cls activity rescore limit */+ ps->ilcinc = base2flt (1, -90); /* inverse of 'ilcinc' */++ ps->lreduceadjustcnt = ps->lreduceadjustinc = 100;+ ps->lpropagations = ~0ull;++ ps->out = stdout;+ new_prefix (ps, "c ");+ ps->verbosity = 0;+ ps->plain = 0;++#ifdef NO_BINARY_CLAUSES+ memset (&ps->impl, 0, sizeof (ps->impl));+ ps->impl.size = 2;++ memset (&ps->cimpl, 0, sizeof (ps->impl));+ ps->cimpl.size = 2;+#endif++#ifdef VISCORES+ ps->fviscores = popen (+ "/usr/bin/gnuplot -background black"+ " -xrm 'gnuplot*textColor:white'"+ " -xrm 'gnuplot*borderColor:white'"+ " -xrm 'gnuplot*axisColor:white'"+ , "w");+ fprintf (ps->fviscores, "unset key\n");+ // fprintf (ps->fviscores, "set log y\n");+ fflush (ps->fviscores);+ system ("rm -rf /tmp/picosat-viscores");+ system ("mkdir /tmp/picosat-viscores");+ system ("mkdir /tmp/picosat-viscores/data");+#ifdef WRITEGIF+ system ("mkdir /tmp/picosat-viscores/gif");+ fprintf (ps->fviscores,+ "set terminal gif giant animate opt size 1024,768 x000000 xffffff"+ "\n");++ fprintf (ps->fviscores,+ "set output \"/tmp/picosat-viscores/gif/animated.gif\"\n");+#endif+#endif+ ps->defaultphase = JWLPHASE;+ ps->state = READY;+ ps->last_sat_call_result = 0;++ return ps;+}++static size_t+bytes_clause (PS * ps, unsigned size, unsigned learned)+{+ size_t res;++ res = sizeof (Cls);+ res += size * sizeof (Lit *);+ res -= 2 * sizeof (Lit *);++ if (learned && size > 2)+ res += sizeof (Act); /* add activity */++#ifdef TRACE+ if (ps->trace)+ res += sizeof (Trd); /* add trace data */+#else+ (void) ps;+#endif++ return res;+}++static Cls *+new_clause (PS * ps, unsigned size, unsigned learned)+{+ size_t bytes;+ void * tmp;+#ifdef TRACE+ Trd *trd;+#endif+ Cls *res;++ bytes = bytes_clause (ps, size, learned);+ tmp = new (ps, bytes);++#ifdef TRACE+ if (ps->trace)+ {+ trd = tmp;++ if (learned)+ trd->idx = LIDX2IDX (ps->lhead - ps->lclauses);+ else+ trd->idx = OIDX2IDX (ps->ohead - ps->oclauses);++ res = trd->cls;+ }+ else+#endif+ res = tmp;++ res->size = size;+ res->learned = learned;++ res->collect = 0;+#ifndef NDEBUG+ res->connected = 0;+#endif+ res->locked = 0;+ res->used = 0;+#ifdef TRACE+ res->core = 0;+ res->collected = 0;+#endif++ if (learned && size > 2)+ *CLS2ACT (res) = ps->cinc;++ return res;+}++static void+delete_clause (PS * ps, Cls * c)+{+ size_t bytes;+#ifdef TRACE+ Trd *trd;+#endif++ bytes = bytes_clause (ps, c->size, c->learned);++#ifdef TRACE+ if (ps->trace)+ {+ trd = CLS2TRD (c);+ delete (ps, trd, bytes);+ }+ else+#endif+ delete (ps, c, bytes);+}++static void+delete_clauses (PS * ps)+{+ Cls **p;+ for (p = SOC; p != EOC; p = NXC (p))+ if (*p)+ delete_clause (ps, *p);++ DELETEN (ps->oclauses, ps->eoo - ps->oclauses);+ DELETEN (ps->lclauses, ps->EOL - ps->lclauses);++ ps->ohead = ps->eoo = ps->lhead = ps->EOL = 0;+}++#ifdef TRACE++static void+delete_zhain (PS * ps, Zhn * zhain)+{+ const Znt *p, *znt;++ assert (zhain);++ znt = zhain->znt;+ for (p = znt; *p; p++)+ ;++ delete (ps, zhain, sizeof (Zhn) + (p - znt) + 1);+}++static void+delete_zhains (PS * ps)+{+ Zhn **p, *z;+ for (p = ps->zhains; p < ps->zhead; p++)+ if ((z = *p))+ delete_zhain (ps, z);++ DELETEN (ps->zhains, ps->eoz - ps->zhains);+ ps->eoz = ps->zhead = 0;+}++#endif++#ifdef NO_BINARY_CLAUSES+static void+lrelease (PS * ps, Ltk * stk)+{+ if (stk->start)+ DELETEN (stk->start, (1 << (stk->ldsize)));+ memset (stk, 0, sizeof (*stk));+}+#endif++#ifndef NADC++static unsigned+llength (Lit ** a)+{+ Lit ** p;+ for (p = a; *p; p++)+ ;+ return p - a;+}++static void+resetadoconflict (PS * ps)+{+ assert (ps->adoconflict);+ delete_clause (ps->adoconflict);+ ps->adoconflict = 0;+}++static void+reset_ados (PS * ps)+{+ Lit *** p;++ for (p = ps->ados; p < ps->hados; p++)+ DELETEN (*p, llength (*p) + 1);++ DELETEN (ps->ados, ps->eados - ps->ados);+ ps->hados = ps->eados = 0;++ DELETEN (ps->adotab, ps->szadotab);+ ps->szadotab = ps->nadotab = 0;++ if (ps->adoconflict)+ resetadoconflict (ps);++ ps->adoconflicts = 0;+ ps->adoconflictlimit = UINT_MAX;+ ps->adodisabled = 0;+}++#endif++static void+reset (PS * ps)+{+ ABORTIF (!ps ||+ ps->state == RESET, "API usage: reset without initialization");++ delete_clauses (ps);+#ifdef TRACE+ delete_zhains (ps);+#endif+#ifdef NO_BINARY_CLAUSES+ ps->implvalid = 0;+ ps->cimplvalid = 0;+ {+ unsigned i;+ for (i = 2; i <= 2 * ps->max_var + 1; i++)+ lrelease (ps, ps->impls + i);+ }+#endif+#ifndef NADC+ reset_ados (ps);+#endif+#ifndef NFL+ DELETEN (ps->saved, ps->saved_size);+ ps->saved_size = 0;+#endif+ DELETEN (ps->htps, 2 * ps->size_vars);+#ifndef NDSC+ DELETEN (ps->dhtps, 2 * ps->size_vars);+#endif+ DELETEN (ps->impls, 2 * ps->size_vars);+ DELETEN (ps->lits, 2 * ps->size_vars);+ DELETEN (ps->jwh, 2 * ps->size_vars);+ DELETEN (ps->vars, ps->size_vars);+ DELETEN (ps->rnks, ps->size_vars);++ DELETEN (ps->trail, ps->eot - ps->trail);+ ps->trail = ps->ttail = ps->ttail2 = ps->thead = ps->eot = 0;+#ifndef NADC+ ps->ttailado = 0;+#endif++ DELETEN (ps->heap, ps->eoh - ps->heap);+ ps->heap = ps->hhead = ps->eoh = 0;++ DELETEN (ps->als, ps->eoals - ps->als);+ ps->als = ps->eoals = ps->alshead = ps->alstail = 0;+ ps->extracted_all_failed_assumptions = 0;+ ps->failed_assumption = 0;+ ps->adecidelevel = 0;+ DELETEN (ps->CLS, ps->eocls - ps->CLS);+ ps->CLS = ps->eocls = ps->clshead = 0;+ DELETEN (ps->rils, ps->eorils - ps->rils);+ ps->rils = ps->eorils = ps->rilshead = 0;+ DELETEN (ps->cils, ps->eocils - ps->cils);+ ps->cils = ps->eocils = ps->cilshead = 0;+ DELETEN (ps->fals, ps->eofals - ps->fals);+ ps->fals = ps->eofals = ps->falshead = 0;+ DELETEN (ps->mass, ps->szmass);+ ps->szmass = 0;+ ps->mass = 0;+ DELETEN (ps->mssass, ps->szmssass);+ ps->szmssass = 0;+ ps->mssass = 0;+ DELETEN (ps->mcsass, ps->szmcsass);+ ps->nmcsass = ps->szmcsass = 0;+ ps->mcsass = 0;+ DELETEN (ps->humus, ps->szhumus);+ ps->szhumus = 0;+ ps->humus = 0;++ ps->size_vars = 0;+ ps->max_var = 0;++ ps->mtcls = 0;+#ifdef TRACE+ ps->ocore = -1;+#endif+ ps->conflict = 0;++ DELETEN (ps->added, ps->eoa - ps->added);+ ps->eoa = ps->ahead = 0;++ DELETEN (ps->marked, ps->eom - ps->marked);+ ps->eom = ps->mhead = 0;++ DELETEN (ps->dfs, ps->eod - ps->dfs);+ ps->eod = ps->dhead = 0;++ DELETEN (ps->resolved, ps->eor - ps->resolved);+ ps->eor = ps->rhead = 0;++ DELETEN (ps->levels, ps->eolevels - ps->levels);+ ps->eolevels = ps->levelshead = 0;++ DELETEN (ps->dused, ps->eodused - ps->dused);+ ps->eodused = ps->dusedhead = 0;++ DELETEN (ps->buffer, ps->eob - ps->buffer);+ ps->eob = ps->bhead = 0;++ DELETEN (ps->indices, ps->eoi - ps->indices);+ ps->eoi = ps->ihead = 0;++ DELETEN (ps->soclauses, ps->eoso - ps->soclauses);+ ps->soclauses = ps->eoso = ps->sohead = 0;+ ps->saveorig = ps->partial = 0;++ delete_prefix (ps);++ delete (ps, ps->rline[0], ps->szrline);+ delete (ps, ps->rline[1], ps->szrline);+ ps->rline[0] = ps->rline[1] = 0;+ ps->szrline = ps->RCOUNT = 0;+ assert (getenv ("LEAK") || !ps->current_bytes); /* found leak if failing */+ ps->max_bytes = 0;+ ps->recycled = 0;+ ps->current_bytes = 0;++ ps->lrestart = 0;+ ps->lreduce = 0;+ ps->lastreduceconflicts = 0;+ ps->llocked = 0;+ ps->lsimplify = 0;+ ps->fsimplify = 0;++ ps->seconds = 0;+ ps->flseconds = 0;+ ps->entered = 0;+ ps->nentered = 0;+ ps->measurealltimeinlib = 0;++ ps->levelsum = 0.0;+ ps->calls = 0;+ ps->decisions = 0;+ ps->restarts = 0;+ ps->simps = 0;+ ps->iterations = 0;+ ps->reports = 0;+ ps->lastrheader = -2;+ ps->fixed = 0;+#ifndef NFL+ ps->failedlits = 0;+ ps->simplifying = 0;+ ps->fllimit = 0;+#ifdef STATS+ ps->efailedlits = ps->ifailedlits = 0;+ ps->fltried = ps->flskipped = ps->floopsed = 0;+ ps->flcalls = ps->flrounds = 0;+ ps->flprops = 0;+#endif+#endif+ ps->propagations = 0;+ ps->contexts = 0;+ ps->internals = 0;+ ps->conflicts = 0;+ ps->noclauses = 0;+ ps->oadded = 0;+ ps->lladded = 0;+ ps->loadded = 0;+ ps->olits = 0;+ ps->nlclauses = 0;+ ps->ladded = 0;+ ps->addedclauses = 0;+ ps->llits = 0;+ ps->out = 0;+#ifdef TRACE+ ps->trace = 0;+#endif+ ps->rup = 0;+ ps->rupstarted = 0;+ ps->rupclauses = 0;+ ps->rupvariables = 0;+ ps->LEVEL = 0;++ ps->reductions = 0;++ ps->vused = 0;+ ps->llitsadded = 0;+ ps->visits = 0;+#ifdef STATS+ ps->loused = 0;+ ps->llused = 0;+ ps->bvisits = 0;+ ps->tvisits = 0;+ ps->lvisits = 0;+ ps->othertrue = 0;+ ps->othertrue2 = 0;+ ps->othertruel = 0;+ ps->othertrue2u = 0;+ ps->othertruelu = 0;+ ps->ltraversals = 0;+ ps->traversals = 0;+#ifndef NO_BINARY_CLAUSES+ ps->antecedents = 0;+#endif+ ps->znts = 0;+ ps->uips = 0;+ ps->assumptions = 0;+ ps->rdecisions = 0;+ ps->sdecisions = 0;+ ps->srecycled = 0;+ ps->rrecycled = 0;+#endif+ ps->minimizedllits = 0;+ ps->nonminimizedllits = 0;+ ps->state = RESET;+ ps->srng = 0;++ ps->saved_flips = 0;+ ps->saved_max_var = 0;+ ps->min_flipped = UINT_MAX;++ ps->flips = 0;+#ifdef STATS+ ps->FORCED = 0;+ ps->assignments = 0;+#endif++ ps->sdflips = 0;+ ps->defaultphase = JWLPHASE;++#ifdef STATS+ ps->staticphasedecisions = 0;+ ps->inclreduces = 0;+ ps->skippedrestarts = 0;+#endif++#ifdef VISCORES+ pclose (ps->fviscores);+ ps->fviscores = 0;+#endif++ if (ps->edelete)+ ps->edelete (ps->emgr, ps, sizeof *ps);+ else+ free (ps);+}++inline static void+tpush (PS * ps, Lit * lit)+{+ assert (ps->lits < lit && lit <= ps->lits + 2* ps->max_var + 1);+ if (ps->thead == ps->eot)+ {+ unsigned ttail2count = ps->ttail2 - ps->trail;+ unsigned ttailcount = ps->ttail - ps->trail;+#ifndef NADC+ unsigned ttailadocount = ps->ttailado - ps->trail;+#endif+ ENLARGE (ps->trail, ps->thead, ps->eot);+ ps->ttail = ps->trail + ttailcount;+ ps->ttail2 = ps->trail + ttail2count;+#ifndef NADC+ ps->ttailado = ps->trail + ttailadocount;+#endif+ }++ *ps->thead++ = lit;+}++static void+assign_reason (PS * ps, Var * v, Cls * reason)+{+#if defined(NO_BINARY_CLAUSES) && !defined(NDEBUG)+ assert (reason != &ps->impl);+#else+ (void) ps;+#endif+ v->reason = reason;+}++static void+assign_phase (PS * ps, Lit * lit)+{+ unsigned new_phase, idx;+ Var * v = LIT2VAR (lit);++#ifndef NFL+ /* In 'simplifying' mode we only need to keep 'min_flipped' up to date if+ * we force assignments on the top level. The other assignments will be+ * undone and thus we can keep the old saved value of the phase.+ */+ if (!ps->LEVEL || !ps->simplifying)+#endif+ {+ new_phase = (LIT2SGN (lit) > 0);++ if (v->assigned)+ {+ ps->sdflips -= ps->sdflips/FFLIPPED;++ if (new_phase != v->phase)+ {+ assert (FFLIPPEDPREC >= FFLIPPED);+ ps->sdflips += FFLIPPEDPREC / FFLIPPED;+ ps->flips++;++ idx = LIT2IDX (lit);+ if (idx < ps->min_flipped)+ ps->min_flipped = idx;++ NOLOG (fprintf (ps->out,+ "%sflipped %d\n",+ ps->prefix, LIT2INT (lit)));+ }+ }++ v->phase = new_phase;+ v->assigned = 1;+ }++ lit->val = TRUE;+ NOTLIT (lit)->val = FALSE;+}++inline static void+assign (PS * ps, Lit * lit, Cls * reason)+{+ Var * v = LIT2VAR (lit);+ assert (lit->val == UNDEF);+#ifdef STATS+ ps->assignments++;+#endif+ v->level = ps->LEVEL;+ assign_phase (ps, lit);+ assign_reason (ps, v, reason);+ tpush (ps, lit);+}++inline static int+cmp_added (PS * ps, Lit * k, Lit * l)+{+ Val a = k->val, b = l->val;+ Var *u, *v;+ int res;++ if (a == UNDEF && b != UNDEF)+ return -1;++ if (a != UNDEF && b == UNDEF)+ return 1;++ u = LIT2VAR (k);+ v = LIT2VAR (l);++ if (a != UNDEF)+ {+ assert (b != UNDEF);+ res = v->level - u->level;+ if (res)+ return res; /* larger level first */+ }++ res = cmpflt (VAR2RNK (u)->score, VAR2RNK (v)->score);+ if (res)+ return res; /* smaller activity first */++ return u - v; /* smaller index first */+}++static void+sorttwolits (Lit ** v)+{+ Lit * a = v[0], * b = v[1];++ assert (a != b);++ if (a < b)+ return;++ v[0] = b;+ v[1] = a;+}++inline static void+sortlits (PS * ps, Lit ** v, unsigned size)+{+ if (size == 2)+ sorttwolits (v); /* same order with and with out 'NO_BINARY_CLAUSES' */+ else+ SORT (Lit *, cmp_added, v, size);+}++#ifdef NO_BINARY_CLAUSES+static Cls *+setimpl (PS * ps, Lit * a, Lit * b)+{+ assert (!ps->implvalid);+ assert (ps->impl.size == 2);++ ps->impl.lits[0] = a;+ ps->impl.lits[1] = b;++ sorttwolits (ps->impl.lits);+ ps->implvalid = 1;++ return &ps->impl;+}++static void+resetimpl (PS * ps)+{+ ps->implvalid = 0;+}++static Cls *+setcimpl (PS * ps, Lit * a, Lit * b)+{+ assert (!ps->cimplvalid);+ assert (ps->cimpl.size == 2);++ ps->cimpl.lits[0] = a;+ ps->cimpl.lits[1] = b;++ sorttwolits (ps->cimpl.lits);+ ps->cimplvalid = 1;++ return &ps->cimpl;+}++static void+resetcimpl (PS * ps)+{+ assert (ps->cimplvalid);+ ps->cimplvalid = 0;+}++#endif++static int+cmp_ptr (PS * ps, void *l, void *k)+{+ (void) ps;+ return ((char*)l) - (char*)k; /* arbitrarily already reverse */+}++static int+cmp_rnk (Rnk * r, Rnk * s)+{+ if (!r->moreimportant && s->moreimportant)+ return -1;++ if (r->moreimportant && !s->moreimportant)+ return 1;++ if (!r->lessimportant && s->lessimportant)+ return 1;++ if (r->lessimportant && !s->lessimportant)+ return -1;++ if (r->score < s->score)+ return -1;++ if (r->score > s->score)+ return 1;++ return -cmp_ptr (0, r, s);+}++static void+hup (PS * ps, Rnk * v)+{+ int upos, vpos;+ Rnk *u;++#ifndef NFL+ assert (!ps->simplifying);+#endif++ vpos = v->pos;++ assert (0 < vpos);+ assert (vpos < ps->hhead - ps->heap);+ assert (ps->heap[vpos] == v);++ while (vpos > 1)+ {+ upos = vpos / 2;++ u = ps->heap[upos];++ if (cmp_rnk (u, v) > 0)+ break;++ ps->heap[vpos] = u;+ u->pos = vpos;++ vpos = upos;+ }++ ps->heap[vpos] = v;+ v->pos = vpos;+}++static Cls *add_simplified_clause (PS *, int);++inline static void+add_antecedent (PS * ps, Cls * c)+{+ assert (c);++#ifdef NO_BINARY_CLAUSES+ if (ISLITREASON (c))+ return;++ if (c == &ps->impl)+ return;+#else+#ifdef STATS+ ps->antecedents++;+#endif+#endif+ if (ps->rhead == ps->eor)+ ENLARGE (ps->resolved, ps->rhead, ps->eor);++ assert (ps->rhead < ps->eor);+ *ps->rhead++ = c;+}++#ifdef TRACE++#ifdef NO_BINARY_CLAUSES+#error "can not combine TRACE and NO_BINARY_CLAUSES"+#endif++#endif /* TRACE */++static void+add_lit (PS * ps, Lit * lit)+{+ assert (lit);++ if (ps->ahead == ps->eoa)+ ENLARGE (ps->added, ps->ahead, ps->eoa);++ *ps->ahead++ = lit;+}++static void+push_var_as_marked (PS * ps, Var * v)+{+ if (ps->mhead == ps->eom)+ ENLARGE (ps->marked, ps->mhead, ps->eom);++ *ps->mhead++ = v;+}++static void+mark_var (PS * ps, Var * v)+{+ assert (!v->mark);+ v->mark = 1;+ push_var_as_marked (ps, v);+}++#ifdef NO_BINARY_CLAUSES++static Cls *+impl2reason (PS * ps, Lit * lit)+{+ Lit * other;+ Cls * res;+ other = ps->impl.lits[0];+ if (lit == other)+ other = ps->impl.lits[1];+ assert (other->val == FALSE);+ res = LIT2REASON (NOTLIT (other));+ resetimpl (ps);+ return res;+}++#endif++/* Whenever we have a top level derived unit we really should derive a unit+ * clause otherwise the resolutions in 'add_simplified_clause' become+ * incorrect.+ */+static Cls *+resolve_top_level_unit (PS * ps, Lit * lit, Cls * reason)+{+ unsigned count_resolved;+ Lit **p, **eol, *other;+ Var *u, *v;++ assert (ps->rhead == ps->resolved);+ assert (ps->ahead == ps->added);++ add_lit (ps, lit);+ add_antecedent (ps, reason);+ count_resolved = 1;+ v = LIT2VAR (lit);++ eol = end_of_lits (reason);+ for (p = reason->lits; p < eol; p++)+ {+ other = *p;+ u = LIT2VAR (other);+ if (u == v)+ continue;++ add_antecedent (ps, u->reason);+ count_resolved++;+ }++ /* Some of the literals could be assumptions. If at least one+ * variable is not an assumption, we should resolve.+ */+ if (count_resolved >= 2)+ {+#ifdef NO_BINARY_CLAUSES+ if (reason == &ps->impl)+ resetimpl (ps);+#endif+ reason = add_simplified_clause (ps, 1);+#ifdef NO_BINARY_CLAUSES+ if (reason->size == 2)+ {+ assert (reason == &ps->impl);+ reason = impl2reason (ps, lit);+ }+#endif+ assign_reason (ps, v, reason);+ }+ else+ {+ ps->ahead = ps->added;+ ps->rhead = ps->resolved;+ }++ return reason;+}++static void+fixvar (PS * ps, Var * v)+{+ Rnk * r;++ assert (VAR2LIT (v) != UNDEF);+ assert (!v->level);++ ps->fixed++;++ r = VAR2RNK (v);+ r->score = INFFLT;++#ifndef NFL+ if (ps->simplifying)+ return;+#endif++ if (!r->pos)+ return;++ hup (ps, r);+}++static void+use_var (PS * ps, Var * v)+{+ if (v->used)+ return;++ v->used = 1;+ ps->vused++;+}++static void+assign_forced (PS * ps, Lit * lit, Cls * reason)+{+ Var *v;++ assert (reason);+ assert (lit->val == UNDEF);++#ifdef STATS+ ps->FORCED++;+#endif+ assign (ps, lit, reason);++#ifdef NO_BINARY_CLAUSES+ assert (reason != &ps->impl);+ if (ISLITREASON (reason))+ {+ reason = setimpl (ps, lit, NOTLIT (REASON2LIT (reason)));+ assert (reason);+ }+#endif+ LOG ( fprintf (ps->out,+ "%sassign %d at level %d by ",+ ps->prefix, LIT2INT (lit), ps->LEVEL);+ dumpclsnl (ps, reason));++ v = LIT2VAR (lit);+ if (!ps->LEVEL)+ use_var (ps, v);++ if (!ps->LEVEL && reason->size > 1)+ {+ reason = resolve_top_level_unit (ps, lit, reason);+ assert (reason);+ }++#ifdef NO_BINARY_CLAUSES+ if (ISLITREASON (reason) || reason == &ps->impl)+ {+ /* DO NOTHING */+ }+ else+#endif+ {+ assert (!reason->locked);+ reason->locked = 1;+ if (reason->learned && reason->size > 2)+ ps->llocked++;+ }++#ifdef NO_BINARY_CLAUSES+ if (reason == &ps->impl)+ resetimpl (ps);+#endif++ if (!ps->LEVEL)+ fixvar (ps, v);+}++#ifdef NO_BINARY_CLAUSES++static void+lpush (PS * ps, Lit * lit, Cls * c)+{+ int pos = (c->lits[0] == lit);+ Ltk * s = LIT2IMPLS (lit);+ unsigned oldsize, newsize;++ assert (c->size == 2);++ if (!s->start)+ {+ assert (!s->count);+ assert (!s->ldsize);+ NEWN (s->start, 1);+ }+ else+ {+ oldsize = (1 << (s->ldsize));+ assert (s->count <= oldsize);+ if (s->count == oldsize)+ {+ newsize = 2 * oldsize;+ RESIZEN (s->start, oldsize, newsize);+ s->ldsize++;+ }+ }++ s->start[s->count++] = c->lits[pos];+}++#endif++static void+connect_head_tail (PS * ps, Lit * lit, Cls * c)+{+ Cls ** s;+ assert (c->size >= 1);+ if (c->size == 2)+ {+#ifdef NO_BINARY_CLAUSES+ lpush (ps, lit, c);+ return;+#else+ s = LIT2IMPLS (lit);+#endif+ }+ else+ s = LIT2HTPS (lit);++ if (c->lits[0] != lit)+ {+ assert (c->size >= 2);+ assert (c->lits[1] == lit);+ c->next[1] = *s;+ }+ else+ c->next[0] = *s;++ *s = c;+}++#ifdef TRACE+static void+zpush (PS * ps, Zhn * zhain)+{+ assert (ps->trace);++ if (ps->zhead == ps->eoz)+ ENLARGE (ps->zhains, ps->zhead, ps->eoz);++ *ps->zhead++ = zhain;+}++static int+cmp_resolved (PS * ps, Cls * c, Cls * d)+{+#ifndef NDEBUG+ assert (ps->trace);+#else+ (void) ps;+#endif+ return CLS2IDX (c) - CLS2IDX (d);+}++static void+bpushc (PS * ps, unsigned char ch)+{+ if (ps->bhead == ps->eob)+ ENLARGE (ps->buffer, ps->bhead, ps->eob);++ *ps->bhead++ = ch;+}++static void+bpushu (PS * ps, unsigned u)+{+ while (u & ~0x7f)+ {+ bpushc (ps, u | 0x80);+ u >>= 7;+ }++ bpushc (ps, u);+}++static void+bpushd (PS * ps, unsigned prev, unsigned this)+{+ unsigned delta;+ assert (prev < this);+ delta = this - prev;+ bpushu (ps, delta);+}++static void+add_zhain (PS * ps)+{+ unsigned prev, this, count, rcount;+ Cls **p, *c;+ Zhn *res;++ assert (ps->trace);+ assert (ps->bhead == ps->buffer);+ assert (ps->rhead > ps->resolved);++ rcount = ps->rhead - ps->resolved;+ SORT (Cls *, cmp_resolved, ps->resolved, rcount);++ prev = 0;+ for (p = ps->resolved; p < ps->rhead; p++)+ {+ c = *p;+ this = CLS2TRD (c)->idx;+ bpushd (ps, prev, this);+ prev = this;+ }+ bpushc (ps, 0);++ count = ps->bhead - ps->buffer;++ res = new (ps, sizeof (Zhn) + count);+ res->core = 0;+ res->ref = 0;+ memcpy (res->znt, ps->buffer, count);++ ps->bhead = ps->buffer;+#ifdef STATS+ ps->znts += count - 1;+#endif+ zpush (ps, res);+}++#endif++static void+add_resolved (PS * ps, int learned)+{+#if defined(STATS) || defined(TRACE)+ Cls **p, *c;++ for (p = ps->resolved; p < ps->rhead; p++)+ {+ c = *p;+ if (c->used)+ continue;++ c->used = 1;++ if (c->size <= 2)+ continue;++#ifdef STATS+ if (c->learned)+ ps->llused++;+ else+ ps->loused++;+#endif+ }+#endif++#ifdef TRACE+ if (learned && ps->trace)+ add_zhain (ps);+#else+ (void) learned;+#endif+ ps->rhead = ps->resolved;+}++static void+incjwh (PS * ps, Cls * c)+{+ Lit **p, *lit, ** eol;+ Flt * f, inc, sum;+ unsigned size = 0;+ Var * v;+ Val val;++ eol = end_of_lits (c);++ for (p = c->lits; p < eol; p++)+ {+ lit = *p;+ val = lit->val;++ if (val && ps->LEVEL > 0)+ {+ v = LIT2VAR (lit);+ if (v->level > 0)+ val = UNDEF;+ }++ if (val == TRUE)+ return;++ if (val != FALSE)+ size++;+ }++ inc = base2flt (1, -size);++ for (p = c->lits; p < eol; p++)+ {+ lit = *p;+ f = LIT2JWH (lit);+ sum = addflt (*f, inc);+ *f = sum;+ }+}++static void+write_rup_header (PS * ps, FILE * file)+{+ char line[80];+ int i;++ sprintf (line, "%%RUPD32 %u %u", ps->rupvariables, ps->rupclauses);++ fputs (line, file);+ for (i = 255 - strlen (line); i >= 0; i--)+ fputc (' ', file);++ fputc ('\n', file);+ fflush (file);+}++static Cls *+add_simplified_clause (PS * ps, int learned)+{+ unsigned num_true, num_undef, num_false, size, count_resolved;+ Lit **p, **q, *lit, ** end;+ unsigned litlevel, glue;+ Cls *res, * reason;+ int reentered;+ Val val;+ Var *v;+#if !defined(NDEBUG) && defined(TRACE)+ unsigned idx;+#endif++ reentered = 0;++REENTER:++ size = ps->ahead - ps->added;++ add_resolved (ps, learned);++ if (learned)+ {+ ps->ladded++;+ ps->llitsadded += size;+ if (size > 2)+ {+ ps->lladded++;+ ps->nlclauses++;+ ps->llits += size;+ }+ }+ else+ {+ ps->oadded++;+ if (size > 2)+ {+ ps->loadded++;+ ps->noclauses++;+ ps->olits += size;+ }+ }++ ps->addedclauses++;+ assert (ps->addedclauses == ps->ladded + ps->oadded);++#ifdef NO_BINARY_CLAUSES+ if (size == 2)+ res = setimpl (ps, ps->added[0], ps->added[1]);+ else+#endif+ {+ sortlits (ps, ps->added, size);++ if (learned)+ {+ if (ps->lhead == ps->EOL)+ {+ ENLARGE (ps->lclauses, ps->lhead, ps->EOL);++ /* A very difficult to find bug, which only occurs if the+ * learned clauses stack is immediately allocated before the+ * original clauses stack without padding. In this case, we+ * have 'SOC == EOC', which terminates all loops using the+ * idiom 'for (p = SOC; p != EOC; p = NXC(p))' immediately.+ * Unfortunately this occurred in 'fix_clause_lits' after+ * using a recent version of the memory allocator of 'Google'+ * perftools in the context of one large benchmark for+ * our SMT solver 'Boolector'.+ */+ if (ps->EOL == ps->oclauses)+ ENLARGE (ps->lclauses, ps->lhead, ps->EOL);+ }++#if !defined(NDEBUG) && defined(TRACE)+ idx = LIDX2IDX (ps->lhead - ps->lclauses);+#endif+ }+ else+ {+ if (ps->ohead == ps->eoo)+ {+ ENLARGE (ps->oclauses, ps->ohead, ps->eoo);+ if (ps->EOL == ps->oclauses)+ ENLARGE (ps->oclauses, ps->ohead, ps->eoo); /* ditto */+ }++#if !defined(NDEBUG) && defined(TRACE)+ idx = OIDX2IDX (ps->ohead - ps->oclauses);+#endif+ }++ assert (ps->EOL != ps->oclauses); /* ditto */++ res = new_clause (ps, size, learned);++ glue = 0;++ if (learned)+ {+ assert (ps->dusedhead == ps->dused);++ for (p = ps->added; p < ps->ahead; p++)+ {+ lit = *p;+ if (lit->val)+ {+ litlevel = LIT2VAR (lit)->level;+ assert (litlevel <= ps->LEVEL);+ while (ps->levels + litlevel >= ps->levelshead)+ {+ if (ps->levelshead >= ps->eolevels)+ ENLARGE (ps->levels, ps->levelshead, ps->eolevels);+ assert (ps->levelshead < ps->eolevels);+ *ps->levelshead++ = 0;+ }+ if (!ps->levels[litlevel])+ {+ if (ps->dusedhead >= ps->eodused)+ ENLARGE (ps->dused, ps->dusedhead, ps->eodused);+ assert (ps->dusedhead < ps->eodused);+ *ps->dusedhead++ = litlevel;+ ps->levels[litlevel] = 1;+ glue++;+ }+ }+ else+ glue++;+ }++ while (ps->dusedhead > ps->dused)+ {+ litlevel = *--ps->dusedhead;+ assert (ps->levels + litlevel < ps->levelshead);+ assert (ps->levels[litlevel]);+ ps->levels[litlevel] = 0;+ }+ }++ assert (glue <= MAXGLUE);+ res->glue = glue;++#if !defined(NDEBUG) && defined(TRACE)+ if (ps->trace)+ assert (CLS2IDX (res) == idx);+#endif+ if (learned)+ *ps->lhead++ = res;+ else+ *ps->ohead++ = res;++#if !defined(NDEBUG) && defined(TRACE)+ if (ps->trace && learned)+ assert (ps->zhead - ps->zhains == ps->lhead - ps->lclauses);+#endif+ assert (ps->lhead != ps->oclauses); /* ditto */+ }++ if (learned && ps->rup)+ {+ if (!ps->rupstarted)+ {+ write_rup_header (ps, ps->rup);+ ps->rupstarted = 1;+ }+ }++ num_true = num_undef = num_false = 0;++ q = res->lits;+ for (p = ps->added; p < ps->ahead; p++)+ {+ lit = *p;+ *q++ = lit;++ if (learned && ps->rup)+ fprintf (ps->rup, "%d ", LIT2INT (lit));++ val = lit->val;++ num_true += (val == TRUE);+ num_undef += (val == UNDEF);+ num_false += (val == FALSE);+ }+ assert (num_false + num_true + num_undef == size);++ if (learned && ps->rup)+ fputs ("0\n", ps->rup);++ ps->ahead = ps->added; /* reset */++ if (!reentered) // TODO merge+ if (size > 0)+ {+ assert (size <= 2 || !reentered); // TODO remove+ connect_head_tail (ps, res->lits[0], res);+ if (size > 1)+ connect_head_tail (ps, res->lits[1], res);+ }++ if (size == 0)+ {+ if (!ps->mtcls)+ ps->mtcls = res;+ }++#ifdef NO_BINARY_CLAUSES+ if (size != 2)+#endif+#ifndef NDEBUG+ res->connected = 1;+#endif++ LOG ( fprintf (ps->out, "%s%s ", ps->prefix, learned ? "learned" : "original");+ dumpclsnl (ps, res));++ /* Shrink clause by resolving it against top level assignments.+ */+ if (!ps->LEVEL && num_false > 0)+ {+ assert (ps->ahead == ps->added);+ assert (ps->rhead == ps->resolved);++ count_resolved = 1;+ add_antecedent (ps, res);++ end = end_of_lits (res);+ for (p = res->lits; p < end; p++)+ {+ lit = *p;+ v = LIT2VAR (lit);+ use_var (ps, v);++ if (lit->val == FALSE)+ {+ add_antecedent (ps, v->reason);+ count_resolved++;+ }+ else+ add_lit (ps, lit);+ }++ assert (count_resolved >= 2);++ learned = 1;+#ifdef NO_BINARY_CLAUSES+ if (res == &ps->impl)+ resetimpl (ps);+#endif+ reentered = 1;+ goto REENTER; /* and return simplified clause */+ }++ if (!num_true && num_undef == 1) /* unit clause */+ {+ lit = 0;+ for (p = res->lits; p < res->lits + size; p++)+ {+ if ((*p)->val == UNDEF)+ lit = *p;++ v = LIT2VAR (*p);+ use_var (ps, v);+ }+ assert (lit);++ reason = res;+#ifdef NO_BINARY_CLAUSES+ if (size == 2)+ {+ Lit * other = res->lits[0];+ if (other == lit)+ other = res->lits[1];++ assert (other->val == FALSE);+ reason = LIT2REASON (NOTLIT (other));+ }+#endif+ assign_forced (ps, lit, reason);+ num_true++;+ }++ if (num_false == size && !ps->conflict)+ {+#ifdef NO_BINARY_CLAUSES+ if (res == &ps->impl)+ ps->conflict = setcimpl (ps, res->lits[0], res->lits[1]);+ else+#endif+ ps->conflict = res;+ }++ if (!learned && !num_true && num_undef)+ incjwh (ps, res);++#ifdef NO_BINARY_CLAUSES+ if (res == &ps->impl)+ resetimpl (ps);+#endif+ return res;+}++static int+trivial_clause (PS * ps)+{+ Lit **p, **q, *prev;+ Var *v;++ SORT (Lit *, cmp_ptr, ps->added, ps->ahead - ps->added);++ prev = 0;+ q = ps->added;+ for (p = q; p < ps->ahead; p++)+ {+ Lit *this = *p;++ v = LIT2VAR (this);++ if (prev == this) /* skip repeated literals */+ continue;++ /* Top level satisfied ?+ */+ if (this->val == TRUE && !v->level)+ return 1;++ if (prev == NOTLIT (this))/* found pair of dual literals */+ return 1;++ *q++ = prev = this;+ }++ ps->ahead = q; /* shrink */++ return 0;+}++static void+simplify_and_add_original_clause (PS * ps)+{+#ifdef NO_BINARY_CLAUSES+ Cls * c;+#endif+ if (trivial_clause (ps))+ {+ ps->ahead = ps->added;++ if (ps->ohead == ps->eoo)+ ENLARGE (ps->oclauses, ps->ohead, ps->eoo);++ *ps->ohead++ = 0;++ ps->addedclauses++;+ ps->oadded++;+ }+ else+ {+ if (ps->CLS != ps->clshead)+ add_lit (ps, NOTLIT (ps->clshead[-1]));++#ifdef NO_BINARY_CLAUSES+ c =+#endif+ add_simplified_clause (ps, 0);+#ifdef NO_BINARY_CLAUSES+ if (c == &ps->impl) assert (!ps->implvalid);+#endif+ }+}++#ifndef NADC++static void+add_ado (PS * ps)+{+ unsigned len = ps->ahead - ps->added;+ Lit ** ado, ** p, ** q, *lit;+ Var * v, * u;++#ifdef TRACE+ assert (!ps->trace);+#endif++ ABORTIF (ps->ados < ps->hados && llength (ps->ados[0]) != len,+ "internal: non matching all different constraint object lengths");++ if (ps->hados == ps->eados)+ ENLARGE (ps->ados, ps->hados, ps->eados);++ NEWN (ado, len + 1);+ *hados++ = ado;++ p = ps->added;+ q = ado;+ u = 0;+ while (p < ps->ahead)+ {+ lit = *p++;+ v = LIT2VAR (lit);+ ABORTIF (v->inado,+ "internal: variable in multiple all different objects");+ v->inado = ado;+ if (!u && !lit->val)+ u = v;+ *q++ = lit;+ }++ assert (q == ado + len);+ *q++ = 0;++ /* TODO simply do a conflict test as in propado */++ ABORTIF (!u,+ "internal: "+ "adding fully instantiated all different object not implemented yet");++ assert (u);+ assert (u->inado == ado);+ assert (!u->ado);+ u->ado = ado;++ ps->ahead = ps->added;+}++#endif++static void+hdown (PS * ps, Rnk * r)+{+ unsigned end, rpos, cpos, opos;+ Rnk *child, *other;++ assert (r->pos > 0);+ assert (ps->heap[r->pos] == r);++ end = ps->hhead - ps->heap;+ rpos = r->pos;++ for (;;)+ {+ cpos = 2 * rpos;+ if (cpos >= end)+ break;++ opos = cpos + 1;+ child = ps->heap[cpos];++ if (cmp_rnk (r, child) < 0)+ {+ if (opos < end)+ {+ other = ps->heap[opos];++ if (cmp_rnk (child, other) < 0)+ {+ child = other;+ cpos = opos;+ }+ }+ }+ else if (opos < end)+ {+ child = ps->heap[opos];++ if (cmp_rnk (r, child) >= 0)+ break;++ cpos = opos;+ }+ else+ break;++ ps->heap[rpos] = child;+ child->pos = rpos;+ rpos = cpos;+ }++ r->pos = rpos;+ ps->heap[rpos] = r;+}++static Rnk *+htop (PS * ps)+{+ assert (ps->hhead > ps->heap + 1);+ return ps->heap[1];+}++static Rnk *+hpop (PS * ps)+{+ Rnk *res, *last;+ unsigned end;++ assert (ps->hhead > ps->heap + 1);++ res = ps->heap[1];+ res->pos = 0;++ end = --ps->hhead - ps->heap;+ if (end == 1)+ return res;++ last = ps->heap[end];++ ps->heap[last->pos = 1] = last;+ hdown (ps, last);++ return res;+}++inline static void+hpush (PS * ps, Rnk * r)+{+ assert (!r->pos);++ if (ps->hhead == ps->eoh)+ ENLARGE (ps->heap, ps->hhead, ps->eoh);++ r->pos = ps->hhead++ - ps->heap;+ ps->heap[r->pos] = r;+ hup (ps, r);+}++static void+fix_trail_lits (PS * ps, long delta)+{+ Lit **p;+ for (p = ps->trail; p < ps->thead; p++)+ *p += delta;+}++#ifdef NO_BINARY_CLAUSES+static void+fix_impl_lits (PS * ps, long delta)+{+ Ltk * s;+ Lit ** p;++ for (s = ps->impls + 2; s < ps->impls + 2 * ps->max_var; s++)+ for (p = s->start; p < s->start + s->count; p++)+ *p += delta;+}+#endif++static void+fix_clause_lits (PS * ps, long delta)+{+ Cls **p, *clause;+ Lit **q, *lit, **eol;++ for (p = SOC; p != EOC; p = NXC (p))+ {+ clause = *p;+ if (!clause)+ continue;++ q = clause->lits;+ eol = end_of_lits (clause);+ while (q < eol)+ {+ assert (q - clause->lits <= (int) clause->size);+ lit = *q;+ lit += delta;+ *q++ = lit;+ }+ }+}++static void+fix_added_lits (PS * ps, long delta)+{+ Lit **p;+ for (p = ps->added; p < ps->ahead; p++)+ *p += delta;+}++static void+fix_assumed_lits (PS * ps, long delta)+{+ Lit **p;+ for (p = ps->als; p < ps->alshead; p++)+ *p += delta;+}++static void+fix_cls_lits (PS * ps, long delta)+{+ Lit **p;+ for (p = ps->CLS; p < ps->clshead; p++)+ *p += delta;+}++static void+fix_heap_rnks (PS * ps, long delta)+{+ Rnk **p;++ for (p = ps->heap + 1; p < ps->hhead; p++)+ *p += delta;+}++#ifndef NADC++static void+fix_ado (long delta, Lit ** ado)+{+ Lit ** p;+ for (p = ado; *p; p++)+ *p += delta;+}++static void+fix_ados (PS * ps, long delta)+{+ Lit *** p;++ for (p = ps->ados; p < ps->hados; p++)+ fix_ado (delta, *p);+}++#endif++static void+enlarge (PS * ps, unsigned new_size_vars)+{+ long rnks_delta, lits_delta;+ Lit *old_lits = ps->lits;+ Rnk *old_rnks = ps->rnks;++ RESIZEN (ps->lits, 2 * ps->size_vars, 2 * new_size_vars);+ RESIZEN (ps->jwh, 2 * ps->size_vars, 2 * new_size_vars);+ RESIZEN (ps->htps, 2 * ps->size_vars, 2 * new_size_vars);+#ifndef NDSC+ RESIZEN (ps->dhtps, 2 * ps->size_vars, 2 * new_size_vars);+#endif+ RESIZEN (ps->impls, 2 * ps->size_vars, 2 * new_size_vars);+ RESIZEN (ps->vars, ps->size_vars, new_size_vars);+ RESIZEN (ps->rnks, ps->size_vars, new_size_vars);++ lits_delta = ps->lits - old_lits;+ rnks_delta = ps->rnks - old_rnks;++ fix_trail_lits (ps, lits_delta);+ fix_clause_lits (ps, lits_delta);+ fix_added_lits (ps, lits_delta);+ fix_assumed_lits (ps, lits_delta);+ fix_cls_lits (ps, lits_delta);+#ifdef NO_BINARY_CLAUSES+ fix_impl_lits (ps, lits_delta);+#endif+#ifndef NADC+ fix_ados (ps, lits_delta);+#endif+ fix_heap_rnks (ps, rnks_delta);+ assert (ps->mhead == ps->marked);++ ps->size_vars = new_size_vars;+}++static void+unassign (PS * ps, Lit * lit)+{+ Cls *reason;+ Var *v;+ Rnk *r;++ assert (lit->val == TRUE);++ LOG ( fprintf (ps->out, "%sunassign %d\n", ps->prefix, LIT2INT (lit)));++ v = LIT2VAR (lit);+ reason = v->reason;++#ifdef NO_BINARY_CLAUSES+ assert (reason != &ps->impl);+ if (ISLITREASON (reason))+ {+ /* DO NOTHING */+ }+ else+#endif+ if (reason)+ {+ assert (reason->locked);+ reason->locked = 0;+ if (reason->learned && reason->size > 2)+ {+ assert (ps->llocked > 0);+ ps->llocked--;+ }+ }++ lit->val = UNDEF;+ NOTLIT (lit)->val = UNDEF;++ r = VAR2RNK (v);+ if (!r->pos)+ hpush (ps, r);++#ifndef NDSC+ {+ Cls * p, * next, ** q;++ q = LIT2DHTPS (lit);+ p = *q;+ *q = 0;++ while (p)+ {+ Lit * other = p->lits[0];++ if (other == lit)+ {+ other = p->lits[1];+ q = p->next + 1;+ }+ else+ {+ assert (p->lits[1] == lit);+ q = p->next;+ }++ next = *q;+ *q = *LIT2HTPS (other);+ *LIT2HTPS (other) = p;+ p = next;+ }+ }+#endif++#ifndef NADC+ if (v->adotabpos)+ {+ assert (ps->nadotab);+ assert (*v->adotabpos == v->ado);++ *v->adotabpos = 0;+ v->adotabpos = 0;++ ps->nadotab--;+ }+#endif+}++static Cls *+var2reason (PS * ps, Var * var)+{+ Cls * res = var->reason;+#ifdef NO_BINARY_CLAUSES+ Lit * this, * other;+ if (ISLITREASON (res))+ {+ this = VAR2LIT (var);+ if (this->val == FALSE)+ this = NOTLIT (this);++ other = REASON2LIT (res);+ assert (other->val == TRUE);+ assert (this->val == TRUE);+ res = setimpl (ps, NOTLIT (other), this);+ }+#else+ (void) ps;+#endif+ return res;+}++static void+mark_clause_to_be_collected (Cls * c)+{+ assert (!c->collect);+ c->collect = 1;+}++static void+undo (PS * ps, unsigned new_level)+{+ Lit *lit;+ Var *v;++ while (ps->thead > ps->trail)+ {+ lit = *--ps->thead;+ v = LIT2VAR (lit);+ if (v->level == new_level)+ {+ ps->thead++; /* fix pre decrement */+ break;+ }++ unassign (ps, lit);+ }++ ps->LEVEL = new_level;+ ps->ttail = ps->thead;+ ps->ttail2 = ps->thead;+#ifndef NADC+ ps->ttailado = ps->thead;+#endif++#ifdef NO_BINARY_CLAUSES+ if (ps->conflict == &ps->cimpl)+ resetcimpl (ps);+#endif+#ifndef NADC+ if (ps->conflict && ps->conflict == ps->adoconflict)+ resetadoconflict (ps);+#endif+ ps->conflict = ps->mtcls;+ if (ps->LEVEL < ps->adecidelevel)+ {+ assert (ps->als < ps->alshead);+ ps->adecidelevel = 0;+ ps->alstail = ps->als;+ }+ LOG ( fprintf (ps->out, "%sback to level %u\n", ps->prefix, ps->LEVEL));+}++#ifndef NDEBUG++static int+clause_satisfied (Cls * c)+{+ Lit **p, **eol, *lit;++ eol = end_of_lits (c);+ for (p = c->lits; p < eol; p++)+ {+ lit = *p;+ if (lit->val == TRUE)+ return 1;+ }++ return 0;+}++static void+original_clauses_satisfied (PS * ps)+{+ Cls **p, *c;++ for (p = ps->oclauses; p < ps->ohead; p++)+ {+ c = *p;++ if (!c)+ continue;++ if (c->learned)+ continue;++ assert (clause_satisfied (c));+ }+}++static void+assumptions_satisfied (PS * ps)+{+ Lit *lit, ** p;++ for (p = ps->als; p < ps->alshead; p++)+ {+ lit = *p;+ assert (lit->val == TRUE);+ }+}++#endif++static void+sflush (PS * ps)+{+ double now = picosat_time_stamp ();+ double delta = now - ps->entered;+ delta = (delta < 0) ? 0 : delta;+ ps->seconds += delta;+ ps->entered = now;+}++static double+mb (PS * ps)+{+ return ps->current_bytes / (double) (1 << 20);+}++static double+avglevel (PS * ps)+{+ return ps->decisions ? ps->levelsum / ps->decisions : 0.0;+}++static void+rheader (PS * ps)+{+ assert (ps->lastrheader <= ps->reports);++ if (ps->lastrheader == ps->reports)+ return;++ ps->lastrheader = ps->reports;++ fprintf (ps->out, "%s\n", ps->prefix);+ fprintf (ps->out, "%s %s\n", ps->prefix, ps->rline[0]);+ fprintf (ps->out, "%s %s\n", ps->prefix, ps->rline[1]);+ fprintf (ps->out, "%s\n", ps->prefix);+}++static unsigned+dynamic_flips_per_assignment_per_mille (PS * ps)+{+ assert (FFLIPPEDPREC >= 1000);+ return ps->sdflips / (FFLIPPEDPREC / 1000);+}++#ifdef NLUBY++static int+high_agility (PS * ps)+{+ return dynamic_flips_per_assignment_per_mille (ps) >= 200;+}++static int+very_high_agility (PS * ps)+{+ return dynamic_flips_per_assignment_per_mille (ps) >= 250;+}++#else++static int+medium_agility (PS * ps)+{+ return dynamic_flips_per_assignment_per_mille (ps) >= 230;+}++#endif++static void+relemdata (PS * ps)+{+ char *p;+ int x;++ if (ps->reports < 0)+ {+ /* strip trailing white space+ */+ for (x = 0; x <= 1; x++)+ {+ p = ps->rline[x] + strlen (ps->rline[x]);+ while (p-- > ps->rline[x])+ {+ if (*p != ' ')+ break;++ *p = 0;+ }+ }++ rheader (ps);+ }+ else+ fputc ('\n', ps->out);++ ps->RCOUNT = 0;+}++static void+relemhead (PS * ps, const char * name, int fp, double val)+{+ int x, y, len, size;+ const char *fmt;+ unsigned tmp, e;++ if (ps->reports < 0)+ {+ x = ps->RCOUNT & 1;+ y = (ps->RCOUNT / 2) * 12 + x * 6;++ if (ps->RCOUNT == 1)+ sprintf (ps->rline[1], "%6s", "");++ len = strlen (name);+ while (ps->szrline <= len + y + 1)+ {+ size = ps->szrline ? 2 * ps->szrline : 128;+ ps->rline[0] = resize (ps, ps->rline[0], ps->szrline, size);+ ps->rline[1] = resize (ps, ps->rline[1], ps->szrline, size);+ ps->szrline = size;+ }++ fmt = (len <= 6) ? "%6s%10s" : "%-10s%4s";+ sprintf (ps->rline[x] + y, fmt, name, "");+ }+ else if (val < 0)+ {+ assert (fp);++ if (val > -100 && (tmp = val * 10.0 - 0.5) > -1000.0)+ {+ fprintf (ps->out, "-%4.1f ", -tmp / 10.0);+ }+ else+ {+ tmp = -val / 10.0 + 0.5;+ e = 1;+ while (tmp >= 100)+ {+ tmp /= 10;+ e++;+ }++ fprintf (ps->out, "-%2ue%u ", tmp, e);+ }+ }+ else+ {+ if (fp && val < 1000 && (tmp = val * 10.0 + 0.5) < 10000)+ {+ fprintf (ps->out, "%5.1f ", tmp / 10.0);+ }+ else if (!fp && (tmp = val) < 100000)+ {+ fprintf (ps->out, "%5u ", tmp);+ }+ else+ {+ tmp = val / 10.0 + 0.5;+ e = 1;++ while (tmp >= 1000)+ {+ tmp /= 10;+ e++;+ }++ fprintf (ps->out, "%3ue%u ", tmp, e);+ }+ }++ ps->RCOUNT++;+}++inline static void+relem (PS * ps, const char *name, int fp, double val)+{+ if (name)+ relemhead (ps, name, fp, val);+ else+ relemdata (ps);+}++static unsigned+reduce_limit_on_lclauses (PS * ps)+{+ unsigned res = ps->lreduce;+ res += ps->llocked;+ return res;+}++static void+report (PS * ps, int replevel, char type)+{+ int rounds;++ if (ps->verbosity < replevel)+ return;++ sflush (ps);++ if (!ps->reports)+ ps->reports = -1;++ for (rounds = (ps->reports < 0) ? 2 : 1; rounds; rounds--)+ {+ if (ps->reports >= 0)+ fprintf (ps->out, "%s%c ", ps->prefix, type);++ relem (ps, "seconds", 1, ps->seconds);+ relem (ps, "level", 1, avglevel (ps));+ assert (ps->fixed <= ps->max_var);+ relem (ps, "variables", 0, ps->max_var - ps->fixed);+ relem (ps, "used", 1, PERCENT (ps->vused, ps->max_var));+ relem (ps, "original", 0, ps->noclauses);+ relem (ps, "conflicts", 0, ps->conflicts);+ // relem (ps, "decisions", 0, ps->decisions);+ // relem (ps, "conf/dec", 1, PERCENT(ps->conflicts,ps->decisions));+ // relem (ps, "limit", 0, reduce_limit_on_lclauses (ps));+ relem (ps, "learned", 0, ps->nlclauses);+ // relem (ps, "limit", 1, PERCENT (ps->nlclauses, reduce_limit_on_lclauses (ps)));+ relem (ps, "limit", 0, ps->lreduce);+#ifdef STATS+ relem (ps, "learning", 1, PERCENT (ps->llused, ps->lladded));+#endif+ relem (ps, "agility", 1, dynamic_flips_per_assignment_per_mille (ps) / 10.0);+ // relem (ps, "original", 0, ps->noclauses);+ relem (ps, "MB", 1, mb (ps));+ // relem (ps, "lladded", 0, ps->lladded);+ // relem (ps, "llused", 0, ps->llused);++ relem (ps, 0, 0, 0);++ ps->reports++;+ }++ /* Adapt this to the number of rows in your terminal.+ */+ #define ROWS 25++ if (ps->reports % (ROWS - 3) == (ROWS - 4))+ rheader (ps);++ fflush (ps->out);+}++static int+bcp_queue_is_empty (PS * ps)+{+ if (ps->ttail != ps->thead)+ return 0;++ if (ps->ttail2 != ps->thead)+ return 0;++#ifndef NADC+ if (ps->ttailado != ps->thead)+ return 0;+#endif++ return 1;+}++static int+satisfied (PS * ps)+{+ assert (!ps->mtcls);+ assert (!ps->failed_assumption);+ if (ps->alstail < ps->alshead)+ return 0;+ assert (!ps->conflict);+ assert (bcp_queue_is_empty (ps));+ return ps->thead == ps->trail + ps->max_var; /* all assigned */+}++static void+vrescore (PS * ps)+{+ Rnk *p, *eor = ps->rnks + ps->max_var;+ for (p = ps->rnks + 1; p <= eor; p++)+ if (p->score != INFFLT)+ p->score = mulflt (p->score, ps->ilvinc);+ ps->vinc = mulflt (ps->vinc, ps->ilvinc);;+#ifdef VISCORES+ ps->nvinc = mulflt (ps->nvinc, ps->lscore);;+#endif+}++static void+inc_score (PS * ps, Var * v)+{+ Flt score;+ Rnk *r;++#ifndef NFL+ if (ps->simplifying)+ return;+#endif++ if (!v->level)+ return;++ if (v->internal)+ return;++ r = VAR2RNK (v);+ score = r->score;++ assert (score != INFFLT);++ score = addflt (score, ps->vinc);+ assert (score < INFFLT);+ r->score = score;+ if (r->pos > 0)+ hup (ps, r);++ if (score > ps->lscore)+ vrescore (ps);+}++static void+inc_activity (PS * ps, Cls * c)+{+ Act *p;++ if (!c->learned)+ return;++ if (c->size <= 2)+ return;++ p = CLS2ACT (c);+ *p = addflt (*p, ps->cinc);+}++static unsigned+hashlevel (unsigned l)+{+ return 1u << (l & 31);+}++static void+push (PS * ps, Var * v)+{+ if (ps->dhead == ps->eod)+ ENLARGE (ps->dfs, ps->dhead, ps->eod);++ *ps->dhead++ = v;+}++static Var *+pop (PS * ps)+{+ assert (ps->dfs < ps->dhead);+ return *--ps->dhead;+}++static void+analyze (PS * ps)+{+ unsigned open, minlevel, siglevels, l, old, i, orig;+ Lit *this, *other, **p, **q, **eol;+ Var *v, *u, **m, *start, *uip;+ Cls *c;++ assert (ps->conflict);++ assert (ps->ahead == ps->added);+ assert (ps->mhead == ps->marked);+ assert (ps->rhead == ps->resolved);++ /* First, search for First UIP variable and mark all resolved variables.+ * At the same time determine the minimum decision level involved.+ * Increase activities of resolved variables.+ */+ q = ps->thead;+ open = 0;+ minlevel = ps->LEVEL;+ siglevels = 0;+ uip = 0;++ c = ps->conflict;++ for (;;)+ {+ add_antecedent (ps, c);+ inc_activity (ps, c);+ eol = end_of_lits (c);+ for (p = c->lits; p < eol; p++)+ {+ other = *p;++ if (other->val == TRUE)+ continue;++ assert (other->val == FALSE);++ u = LIT2VAR (other);+ if (u->mark)+ continue;++ u->mark = 1;+ inc_score (ps, u);+ use_var (ps, u);++ if (u->level == ps->LEVEL)+ {+ open++;+ }+ else+ {+ push_var_as_marked (ps, u);++ if (u->level)+ {+ /* The statistics counter 'nonminimizedllits' sums up the+ * number of literals that would be added if only the+ * 'first UIP' scheme for learned clauses would be used+ * and no clause minimization.+ */+ ps->nonminimizedllits++;++ if (u->level < minlevel)+ minlevel = u->level;++ siglevels |= hashlevel (u->level);+ }+ else+ {+ assert (!u->level);+ assert (u->reason);+ }+ }+ }++ do+ {+ if (q == ps->trail)+ {+ uip = 0;+ goto DONE_FIRST_UIP;+ }++ this = *--q;+ uip = LIT2VAR (this);+ }+ while (!uip->mark);++ uip->mark = 0;++ c = var2reason (ps, uip);+#ifdef NO_BINARY_CLAUSES+ if (c == &ps->impl)+ resetimpl (ps);+#endif+ open--;+ if ((!open && ps->LEVEL) || !c)+ break;++ assert (c);+ }++DONE_FIRST_UIP:++ if (uip)+ {+ assert (ps->LEVEL);+ this = VAR2LIT (uip);+ this += (this->val == TRUE);+ ps->nonminimizedllits++;+ ps->minimizedllits++;+ add_lit (ps, this);+#ifdef STATS+ if (uip->reason)+ ps->uips++;+#endif+ }+ else+ assert (!ps->LEVEL);++ /* Second, try to mark more intermediate variables, with the goal to+ * minimize the conflict clause. This is a DFS from already marked+ * variables backward through the implication graph. It tries to reach+ * other marked variables. If the search reaches an unmarked decision+ * variable or a variable assigned below the minimum level of variables in+ * the first uip learned clause or a level on which no variable has been+ * marked, then the variable from which the DFS is started is not+ * redundant. Otherwise the start variable is redundant and will+ * eventually be removed from the learned clause in step 4. We initially+ * implemented BFS, but then profiling revelead that this step is a bottle+ * neck for certain incremental applications. After switching to DFS this+ * hot spot went away.+ */+ orig = ps->mhead - ps->marked;+ for (i = 0; i < orig; i++)+ {+ start = ps->marked[i];++ assert (start->mark);+ assert (start != uip);+ assert (start->level < ps->LEVEL);++ if (!start->reason)+ continue;++ old = ps->mhead - ps->marked;+ assert (ps->dhead == ps->dfs);+ push (ps, start);++ while (ps->dhead > ps->dfs)+ {+ u = pop (ps);+ assert (u->mark);++ c = var2reason (ps, u);+#ifdef NO_BINARY_CLAUSES+ if (c == &ps->impl)+ resetimpl (ps);+#endif+ if (!c ||+ ((l = u->level) &&+ (l < minlevel || ((hashlevel (l) & ~siglevels)))))+ {+ while (ps->mhead > ps->marked + old) /* reset all marked */+ (*--ps->mhead)->mark = 0;++ ps->dhead = ps->dfs; /* and DFS stack */+ break;+ }++ eol = end_of_lits (c);+ for (p = c->lits; p < eol; p++)+ {+ v = LIT2VAR (*p);+ if (v->mark)+ continue;++ mark_var (ps, v);+ push (ps, v);+ }+ }+ }++ for (m = ps->marked; m < ps->mhead; m++)+ {+ v = *m;++ assert (v->mark);+ assert (!v->resolved);++ use_var (ps, v);++ c = var2reason (ps, v);+ if (!c)+ continue;++#ifdef NO_BINARY_CLAUSES+ if (c == &ps->impl)+ resetimpl (ps);+#endif+ eol = end_of_lits (c);+ for (p = c->lits; p < eol; p++)+ {+ other = *p;++ u = LIT2VAR (other);+ if (!u->level)+ continue;++ if (!u->mark) /* 'MARKTEST' */+ break;+ }++ if (p != eol)+ continue;++ add_antecedent (ps, c);+ v->resolved = 1;+ }++ for (m = ps->marked; m < ps->mhead; m++)+ {+ v = *m;++ assert (v->mark);+ v->mark = 0;++ if (v->resolved)+ {+ v->resolved = 0;+ continue;+ }++ this = VAR2LIT (v);+ if (this->val == TRUE)+ this++; /* actually NOTLIT */++ add_lit (ps, this);+ ps->minimizedllits++;+ }++ assert (ps->ahead <= ps->eoa);+ assert (ps->rhead <= ps->eor);++ ps->mhead = ps->marked;+}++static void+fanalyze (PS * ps)+{+ Lit ** eol, ** p, * lit;+ Cls * c, * reason;+ Var * v, * u;+ int next;++ double start = picosat_time_stamp ();++ assert (ps->failed_assumption);+ assert (ps->failed_assumption->val == FALSE);++ v = LIT2VAR (ps->failed_assumption);+ reason = var2reason (ps, v);+ if (!reason) return;+#ifdef NO_BINARY_CLAUSES+ if (reason == &ps->impl)+ resetimpl (ps);+#endif++ eol = end_of_lits (reason);+ for (p = reason->lits; p != eol; p++)+ {+ lit = *p;+ u = LIT2VAR (lit);+ if (u == v) continue;+ if (u->reason) break;+ }+ if (p == eol) return;++ assert (ps->ahead == ps->added);+ assert (ps->mhead == ps->marked);+ assert (ps->rhead == ps->resolved);++ next = 0;+ mark_var (ps, v);+ add_lit (ps, NOTLIT (ps->failed_assumption));++ do+ {+ v = ps->marked[next++];+ use_var (ps, v);+ if (v->reason)+ {+ reason = var2reason (ps, v);+#ifdef NO_BINARY_CLAUSES+ if (reason == &ps->impl)+ resetimpl (ps);+#endif+ add_antecedent (ps, reason);+ eol = end_of_lits (reason);+ for (p = reason->lits; p != eol; p++)+ {+ lit = *p;+ u = LIT2VAR (lit);+ if (u == v) continue;+ if (u->mark) continue;+ mark_var (ps, u);+ }+ }+ else+ {+ lit = VAR2LIT (v);+ if (lit->val == TRUE) lit = NOTLIT (lit);+ add_lit (ps, lit);+ }+ }+ while (ps->marked + next < ps->mhead);++ c = add_simplified_clause (ps, 1);+ v = LIT2VAR (ps->failed_assumption);+ reason = v->reason;+#ifdef NO_BINARY_CLAUSES+ if (!ISLITREASON (reason))+#endif+ {+ assert (reason->locked);+ reason->locked = 0;+ if (reason->learned && reason->size > 2)+ {+ assert (ps->llocked > 0);+ ps->llocked--;+ }+ }++#ifdef NO_BINARY_CLAUSES+ if (c == &ps->impl)+ {+ c = impl2reason (ps, NOTLIT (ps->failed_assumption));+ }+ else+#endif+ {+ assert (c->learned);+ assert (!c->locked);+ c->locked = 1;+ if (c->size > 2)+ {+ ps->llocked++;+ assert (ps->llocked > 0);+ }+ }++ v->reason = c;++ while (ps->mhead > ps->marked)+ (*--ps->mhead)->mark = 0;++ if (ps->verbosity)+ fprintf (ps->out, "%sfanalyze took %.1f seconds\n",+ ps->prefix, picosat_time_stamp () - start);+}++/* Propagate assignment of 'this' to 'FALSE' by visiting all binary clauses in+ * which 'this' occurs.+ */+inline static void+prop2 (PS * ps, Lit * this)+{+#ifdef NO_BINARY_CLAUSES+ Lit ** l, ** start;+ Ltk * lstk;+#else+ Cls * c, ** p;+ Cls * next;+#endif+ Lit * other;+ Val tmp;++ assert (this->val == FALSE);++#ifdef NO_BINARY_CLAUSES+ lstk = LIT2IMPLS (this);+ start = lstk->start;+ l = start + lstk->count;+ while (l != start)+ {+ /* The counter 'visits' is the number of clauses that are+ * visited during propagations of assignments.+ */+ ps->visits++;+#ifdef STATS+ ps->bvisits++;+#endif+ other = *--l;+ tmp = other->val;++ if (tmp == TRUE)+ {+#ifdef STATS+ ps->othertrue++;+ ps->othertrue2++;+ if (LIT2VAR (other)->level < ps->LEVEL)+ ps->othertrue2u++;+#endif+ continue;+ }++ if (tmp != FALSE)+ {+ assign_forced (ps, other, LIT2REASON (NOTLIT(this)));+ continue;+ }++ if (ps->conflict == &ps->cimpl)+ resetcimpl (ps);+ ps->conflict = setcimpl (ps, this, other);+ }+#else+ /* Traverse all binary clauses with 'this'. Head/Tail pointers for binary+ * clauses do not have to be modified here.+ */+ p = LIT2IMPLS (this);+ for (c = *p; c; c = next)+ {+ ps->visits++;+#ifdef STATS+ ps->bvisits++;+#endif+ assert (!c->collect);+#ifdef TRACE+ assert (!c->collected);+#endif+ assert (c->size == 2);++ other = c->lits[0];+ if (other == this)+ {+ next = c->next[0];+ other = c->lits[1];+ }+ else+ next = c->next[1];++ tmp = other->val;++ if (tmp == TRUE)+ {+#ifdef STATS+ ps->othertrue++;+ ps->othertrue2++;+ if (LIT2VAR (other)->level < ps->LEVEL)+ ps->othertrue2u++;+#endif+ continue;+ }++ if (tmp == FALSE)+ ps->conflict = c;+ else+ assign_forced (ps, other, c); /* unit clause */+ }+#endif /* !defined(NO_BINARY_CLAUSES) */+}++#ifndef NDSC+static int+should_disconnect_head_tail (PS * ps, Lit * lit)+{+ unsigned litlevel;+ Var * v;++ assert (lit->val == TRUE);++ v = LIT2VAR (lit);+ litlevel = v->level;++ if (!litlevel)+ return 1;++#ifndef NFL+ if (ps->simplifying)+ return 0;+#endif++ return litlevel < ps->LEVEL;+}+#endif++inline static void+propl (PS * ps, Lit * this)+{+ Lit **l, *other, *prev, *new_lit, **eol;+ Cls *next, **htp_ptr, **new_htp_ptr;+ Cls *c;+#ifdef STATS+ unsigned size;+#endif++ htp_ptr = LIT2HTPS (this);+ assert (this->val == FALSE);++ /* Traverse all non binary clauses with 'this'. Head/Tail pointers are+ * updated as well.+ */+ for (c = *htp_ptr; c; c = next)+ {+ ps->visits++;+#ifdef STATS+ size = c->size;+ assert (size >= 3);+ ps->traversals++; /* other is dereferenced at least */++ if (size == 3)+ ps->tvisits++;+ else if (size >= 4)+ {+ ps->lvisits++;+ ps->ltraversals++;+ }+#endif+#ifdef TRACE+ assert (!c->collected);+#endif+ assert (c->size > 0);++ other = c->lits[0];+ if (other != this)+ {+ assert (c->size != 1);+ c->lits[0] = this;+ c->lits[1] = other;+ next = c->next[1];+ c->next[1] = c->next[0];+ c->next[0] = next;+ }+ else if (c->size == 1) /* With assumptions we need to+ * traverse unit clauses as well.+ */+ {+ assert (!ps->conflict);+ ps->conflict = c;+ break;+ }+ else+ {+ assert (other == this && c->size > 1);+ other = c->lits[1];+ next = c->next[0];+ }+ assert (other == c->lits[1]);+ assert (this == c->lits[0]);+ assert (next == c->next[0]);+ assert (!c->collect);++ if (other->val == TRUE)+ {+#ifdef STATS+ ps->othertrue++;+ ps->othertruel++;+#endif+#ifndef NDSC+ if (should_disconnect_head_tail (ps, other))+ {+ new_htp_ptr = LIT2DHTPS (other);+ c->next[0] = *new_htp_ptr;+ *new_htp_ptr = c;+#ifdef STATS+ ps->othertruelu++;+#endif+ *htp_ptr = next;+ continue;+ }+#endif+ htp_ptr = c->next;+ continue;+ }++ l = c->lits + 1;+ eol = c->lits + c->size;+ prev = this;++ while (++l != eol)+ {+#ifdef STATS+ if (size >= 3)+ {+ ps->traversals++;+ if (size > 3)+ ps->ltraversals++;+ }+#endif+ new_lit = *l;+ *l = prev;+ prev = new_lit;+ if (new_lit->val != FALSE) break;+ }++ if (l == eol)+ {+ while (l > c->lits + 2)+ {+ new_lit = *--l;+ *l = prev;+ prev = new_lit;+ }+ assert (c->lits[0] == this);++ assert (other == c->lits[1]);+ if (other->val == FALSE) /* found conflict */+ {+ assert (!ps->conflict);+ ps->conflict = c;+ return;+ }++ assign_forced (ps, other, c); /* unit clause */+ htp_ptr = c->next;+ }+ else+ {+ assert (new_lit->val == TRUE || new_lit->val == UNDEF);+ c->lits[0] = new_lit;+ // *l = this;+ new_htp_ptr = LIT2HTPS (new_lit);+ c->next[0] = *new_htp_ptr;+ *new_htp_ptr = c;+ *htp_ptr = next;+ }+ }+}++#ifndef NADC++static unsigned primes[] = { 996293, 330643, 753947, 500873 };++#define PRIMES ((sizeof primes)/sizeof *primes)++static unsigned+hash_ado (Lit ** ado, unsigned salt)+{+ unsigned i, res, tmp;+ Lit ** p, * lit;++ assert (salt < PRIMES);++ i = salt;+ res = 0;++ for (p = ado; (lit = *p); p++)+ {+ assert (lit->val);++ tmp = res >> 31;+ res <<= 1;++ if (lit->val > 0)+ res |= 1;++ assert (i < PRIMES);+ res *= primes[i++];+ if (i == PRIMES)+ i = 0;++ res += tmp;+ }++ return res & (ps->szadotab - 1);+}++static unsigned+cmp_ado (Lit ** a, Lit ** b)+{+ Lit ** p, ** q, * l, * k;+ int res;++ for (p = a, q = b; (l = *p); p++, q++)+ {+ k = *q;+ assert (k);+ if ((res = (l->val - k->val)))+ return res;+ }++ assert (!*q);++ return 0;+}++static Lit ***+find_ado (Lit ** ado)+{+ Lit *** res, ** other;+ unsigned pos, delta;++ pos = hash_ado (ado, 0);+ assert (pos < ps->szadotab);+ res = ps->adotab + pos;++ other = *res;+ if (!other || !cmp_ado (other, ado))+ return res;++ delta = hash_ado (ado, 1);+ if (!(delta & 1))+ delta++;++ assert (delta & 1);+ assert (delta < ps->szadotab);++ for (;;)+ {+ pos += delta;+ if (pos >= ps->szadotab)+ pos -= ps->szadotab;++ assert (pos < ps->szadotab);+ res = ps->adotab + pos;+ other = *res;+ if (!other || !cmp_ado (other, ado))+ return res;+ }+}++static void+enlarge_adotab (PS * ps)+{+ /* TODO make this generic */++ ABORTIF (ps->szadotab,+ "internal: all different objects table needs larger initial size");+ assert (!ps->nadotab);+ ps->szadotab = 10000;+ NEWN (ps->adotab, ps->szadotab);+ CLRN (ps->adotab, ps->szadotab);+}++static int+propado (Var * v)+{+ Lit ** p, ** q, *** adotabpos, **ado, * lit;+ Var * u;++ if (ps->level && ps->adodisabled)+ return 1;++ assert (!ps->conflict);+ assert (!ps->adoconflict);+ assert (VAR2LIT (v)->val != UNDEF);+ assert (!v->adotabpos);++ if (!v->ado)+ return 1;++ assert (v->inado);++ for (p = v->ado; (lit = *p); p++)+ if (lit->val == UNDEF)+ {+ u = LIT2VAR (lit);+ assert (!u->ado);+ u->ado = v->ado;+ v->ado = 0;++ return 1;+ }++ if (4 * ps->nadotab >= 3 * ps->szadotab) /* at least 75% filled */+ enlarge_adotab (ps);++ adotabpos = find_ado (v->ado);+ ado = *adotabpos;++ if (!ado)+ {+ ps->nadotab++;+ v->adotabpos = adotabpos;+ *adotabpos = v->ado;+ return 1;+ }++ assert (ado != v->ado);++ ps->adoconflict = new_clause (2 * llength (ado), 1);+ q = ps->adoconflict->lits;++ for (p = ado; (lit = *p); p++)+ *q++ = lit->val == FALSE ? lit : NOTLIT (lit);++ for (p = v->ado; (lit = *p); p++)+ *q++ = lit->val == FALSE ? lit : NOTLIT (lit);++ assert (q == ENDOFCLS (ps->adoconflict));+ ps->conflict = ps->adoconflict;+ ps->adoconflicts++;+ return 0;+}++#endif++static void+bcp (PS * ps)+{+ int props = 0;+ assert (!ps->conflict);++ if (ps->mtcls)+ return;++ for (;;)+ {+ if (ps->ttail2 < ps->thead) /* prioritize implications */+ {+ props++;+ prop2 (ps, NOTLIT (*ps->ttail2++));+ }+ else if (ps->ttail < ps->thead) /* unit clauses or clauses with length > 2 */+ {+ if (ps->conflict) break;+ propl (ps, NOTLIT (*ps->ttail++));+ if (ps->conflict) break;+ }+#ifndef NADC+ else if (ps->ttailado < ps->thead)+ {+ if (ps->conflict) break;+ propado (ps, LIT2VAR (*ps->ttailado++));+ if (ps->conflict) break;+ }+#endif+ else+ break; /* all assignments propagated, so break */+ }++ ps->propagations += props;+}++static unsigned+drive (PS * ps)+{+ unsigned res, vlevel;+ Lit **p;+ Var *v;++ res = 0;+ for (p = ps->added; p < ps->ahead; p++)+ {+ v = LIT2VAR (*p);+ vlevel = v->level;+ assert (vlevel <= ps->LEVEL);+ if (vlevel < ps->LEVEL && vlevel > res)+ res = vlevel;+ }++ return res;+}++#ifdef VISCORES++static void+viscores (PS * ps)+{+ Rnk *p, *eor = ps->rnks + ps->max_var;+ char name[100], cmd[200];+ FILE * data;+ Flt s;+ int i;++ for (p = ps->rnks + 1; p <= ps->eor; p++)+ {+ s = p->score;+ if (s == INFFLT)+ continue;+ s = mulflt (s, ps->nvinc);+ assert (flt2double (s) <= 1.0);+ }++ sprintf (name, "/tmp/picosat-viscores/data/%08u", ps->conflicts);+ sprintf (cmd, "sort -n|nl>%s", name);++ data = popen (cmd, "w");+ for (p = ps->rnks + 1; p <= ps->eor; p++)+ {+ s = p->score;+ if (s == INFFLT)+ continue;+ s = mulflt (s, ps->nvinc);+ fprintf (data, "%lf %d\n", 100.0 * flt2double (s), (int)(p - ps->rnks));+ }+ fflush (data);+ pclose (data);++ for (i = 0; i < 8; i++)+ {+ sprintf (cmd, "awk '$3%%8==%d' %s>%s.%d", i, name, name, i);+ system (cmd);+ }++ fprintf (ps->fviscores, "set title \"%u\"\n", ps->conflicts);+ fprintf (ps->fviscores, "plot [0:%u] 0, 100 * (1 - 1/1.1), 100", ps->max_var);++ for (i = 0; i < 8; i++)+ fprintf (ps->fviscores,+ ", \"%s.%d\" using 1:2:3 with labels tc lt %d",+ name, i, i + 1);++ fputc ('\n', ps->fviscores);+ fflush (ps->fviscores);+#ifndef WRITEGIF+ usleep (50000); /* refresh rate of 20 Hz */+#endif+}++#endif++static void+crescore (PS * ps)+{+ Cls **p, *c;+ Act *a;+ Flt factor;+ int l = log2flt (ps->cinc);+ assert (l > 0);+ factor = base2flt (1, -l);++ for (p = ps->lclauses; p != ps->lhead; p++)+ {+ c = *p;++ if (!c)+ continue;++#ifdef TRACE+ if (c->collected)+ continue;+#endif+ assert (c->learned);++ if (c->size <= 2)+ continue;++ a = CLS2ACT (c);+ *a = mulflt (*a, factor);+ }++ ps->cinc = mulflt (ps->cinc, factor);+}++static void+inc_vinc (PS * ps)+{+#ifdef VISCORES+ ps->nvinc = mulflt (ps->nvinc, ps->fvinc);+#endif+ ps->vinc = mulflt (ps->vinc, ps->ifvinc);+}++inline static void+inc_max_var (PS * ps)+{+ Lit *lit;+ Rnk *r;+ Var *v;++ assert (ps->max_var < ps->size_vars);++ ps->max_var++; /* new index of variable */+ assert (ps->max_var); /* no unsigned overflow */++ if (ps->max_var == ps->size_vars)+ enlarge (ps, ps->size_vars + (ps->size_vars + 3) / 4); /* +25% */++ assert (ps->max_var < ps->size_vars);++ lit = ps->lits + 2 * ps->max_var;+ lit[0].val = lit[1].val = UNDEF;++ memset (ps->htps + 2 * ps->max_var, 0, 2 * sizeof *ps->htps);+#ifndef NDSC+ memset (ps->dhtps + 2 * ps->max_var, 0, 2 * sizeof *ps->dhtps);+#endif+ memset (ps->impls + 2 * ps->max_var, 0, 2 * sizeof *ps->impls);+ memset (ps->jwh + 2 * ps->max_var, 0, 2 * sizeof *ps->jwh);++ v = ps->vars + ps->max_var; /* initialize variable components */+ CLR (v);++ r = ps->rnks + ps->max_var; /* initialize rank */+ CLR (r);++ hpush (ps, r);+}++static void+force (PS * ps, Cls * c)+{+ Lit ** p, ** eol, * lit, * forced;+ Cls * reason;++ forced = 0;+ reason = c;++ eol = end_of_lits (c);+ for (p = c->lits; p < eol; p++)+ {+ lit = *p;+ if (lit->val == UNDEF)+ {+ assert (!forced);+ forced = lit;+#ifdef NO_BINARY_CLAUSES+ if (c == &ps->impl)+ reason = LIT2REASON (NOTLIT (p[p == c->lits ? 1 : -1]));+#endif+ }+ else+ assert (lit->val == FALSE);+ }++#ifdef NO_BINARY_CLAUSES+ if (c == &ps->impl)+ resetimpl (ps);+#endif+ if (!forced)+ return;++ assign_forced (ps, forced, reason);+}++static void+inc_lreduce (PS * ps)+{+#ifdef STATS+ ps->inclreduces++;+#endif+ ps->lreduce *= FREDUCE;+ ps->lreduce /= 100;+ report (ps, 1, '+');+}++static void+backtrack (PS * ps)+{+ unsigned new_level;+ Cls * c;++ ps->conflicts++;+ LOG ( fprintf (ps->out, "%sconflict ", ps->prefix); dumpclsnl (ps, ps->conflict));++ analyze (ps);+ new_level = drive (ps);+ // TODO: why not? assert (new_level != 1 || (ps->ahead - ps->added) == 2);+ c = add_simplified_clause (ps, 1);+ undo (ps, new_level);+ force (ps, c);++ if (+#ifndef NFL+ !ps->simplifying &&+#endif+ !--ps->lreduceadjustcnt)+ {+ /* With FREDUCE==110 and FREDADJ=121 we stir 'lreduce' to be+ * proportional to 'sqrt(conflicts)'. In earlier version we actually+ * used 'FREDADJ=150', which results in 'lreduce' to approximate+ * 'conflicts^(log(1.1)/log(1.5))' which is close to the fourth root+ * of 'conflicts', since log(1.1)/log(1.5)=0.235 (as observed by+ * Donald Knuth). The square root is the same we get by a Glucose+ * style increase, which simply adds a constant at every reduction.+ * This would be way simpler to implement but for now we keep the more+ * complicated code using the adjust increments and counters.+ */+ ps->lreduceadjustinc *= FREDADJ; ps->lreduceadjustinc /= 100; ps->lreduceadjustcnt+ = ps->lreduceadjustinc;+ inc_lreduce (ps);+ }++ if (ps->verbosity >= 4 && !(ps->conflicts % 1000))+ report (ps, 4, 'C');+}++static void+inc_cinc (PS * ps)+{+ ps->cinc = mulflt (ps->cinc, ps->fcinc);+ if (ps->lcinc < ps->cinc)+ crescore (ps);+}++static void+incincs (PS * ps)+{+ inc_vinc (ps);+ inc_cinc (ps);+#ifdef VISCORES+ viscores (ps);+#endif+}++static void+disconnect_clause (PS * ps, Cls * c)+{+ assert (c->connected);++ if (c->size > 2)+ {+ if (c->learned)+ {+ assert (ps->nlclauses > 0);+ ps->nlclauses--;++ assert (ps->llits >= c->size);+ ps->llits -= c->size;+ }+ else+ {+ assert (ps->noclauses > 0);+ ps->noclauses--;++ assert (ps->olits >= c->size);+ ps->olits -= c->size;+ }+ }++#ifndef NDEBUG+ c->connected = 0;+#endif+}++static int+clause_is_toplevel_satisfied (PS * ps, Cls * c)+{+ Lit *lit, **p, **eol = end_of_lits (c);+ Var *v;++ for (p = c->lits; p < eol; p++)+ {+ lit = *p;+ if (lit->val == TRUE)+ {+ v = LIT2VAR (lit);+ if (!v->level)+ return 1;+ }+ }++ return 0;+}++static int+collect_clause (PS * ps, Cls * c)+{+ assert (c->collect);+ c->collect = 0;++#ifdef TRACE+ assert (!c->collected);+ c->collected = 1;+#endif+ disconnect_clause (ps, c);++#ifdef TRACE+ if (ps->trace && (!c->learned || c->used))+ return 0;+#endif+ delete_clause (ps, c);++ return 1;+}++static size_t+collect_clauses (PS * ps)+{+ Cls *c, **p, **q, * next;+ Lit * lit, * eol;+ size_t res;+ int i;++ res = ps->current_bytes;++ eol = ps->lits + 2 * ps->max_var + 1;+ for (lit = ps->lits + 2; lit <= eol; lit++)+ {+ for (i = 0; i <= 1; i++)+ {+ if (i)+ {+#ifdef NO_BINARY_CLAUSES+ Ltk * lstk = LIT2IMPLS (lit);+ Lit ** r, ** s;+ r = lstk->start;+ if (lit->val != TRUE || LIT2VAR (lit)->level)+ for (s = r; s < lstk->start + lstk->count; s++)+ {+ Lit * other = *s;+ Var *v = LIT2VAR (other);+ if (v->level || other->val != TRUE)+ *r++ = other;+ }+ lstk->count = r - lstk->start;+ continue;+#else+ p = LIT2IMPLS (lit);+#endif+ }+ else+ p = LIT2HTPS (lit);++ for (c = *p; c; c = next)+ {+ q = c->next;+ if (c->lits[0] != lit)+ q++;++ next = *q;+ if (c->collect)+ *p = next;+ else+ p = q;+ }+ }+ }++#ifndef NDSC+ for (lit = ps->lits + 2; lit <= eol; lit++)+ {+ p = LIT2DHTPS (lit);+ while ((c = *p))+ {+ Lit * other = c->lits[0];+ if (other == lit)+ {+ q = c->next + 1;+ }+ else+ {+ assert (c->lits[1] == lit);+ q = c->next;+ }++ if (c->collect)+ *p = *q;+ else+ p = q;+ }+ }+#endif++ for (p = SOC; p != EOC; p = NXC (p))+ {+ c = *p;++ if (!c)+ continue;++ if (!c->collect)+ continue;++ if (collect_clause (ps, c))+ *p = 0;+ }++#ifdef TRACE+ if (!ps->trace)+#endif+ {+ q = ps->oclauses;+ for (p = q; p < ps->ohead; p++)+ if ((c = *p))+ *q++ = c;+ ps->ohead = q;++ q = ps->lclauses;+ for (p = q; p < ps->lhead; p++)+ if ((c = *p))+ *q++ = c;+ ps->lhead = q;+ }++ assert (ps->current_bytes <= res);+ res -= ps->current_bytes;+ ps->recycled += res;++ LOG ( fprintf (ps->out, "%scollected %ld bytes\n", ps->prefix, (long)res));++ return res;+}++static int+need_to_reduce (PS * ps)+{+ return ps->nlclauses >= reduce_limit_on_lclauses (ps);+}++#ifdef NLUBY++static void+inc_drestart (PS * ps)+{+ ps->drestart *= FRESTART;+ ps->drestart /= 100;++ if (ps->drestart >= MAXRESTART)+ ps->drestart = MAXRESTART;+}++static void+inc_ddrestart (PS * ps)+{+ ps->ddrestart *= FRESTART;+ ps->ddrestart /= 100;++ if (ps->ddrestart >= MAXRESTART)+ ps->ddrestart = MAXRESTART;+}++#else++static int+luby (int i)+{+ int k;+ for (k = 1; k < 32; k++)+ if (i == (1 << k) - 1)+ return 1 << (k - 1);++ for (k = 1;; k++)+ if ((1 << (k - 1)) <= i && i < (1 << k) - 1)+ return luby (i - (1 << (k-1)) + 1);+}++#endif++#ifndef NLUBY+static void+inc_lrestart (PS * ps, int skip)+{+ unsigned delta;++ delta = 100 * luby (++ps->lubycnt);+ ps->lrestart = ps->conflicts + delta;++ if (ps->waslubymaxdelta)+ report (ps, 1, skip ? 'N' : 'R');+ else+ report (ps, 2, skip ? 'n' : 'r');++ if (delta > ps->lubymaxdelta)+ {+ ps->lubymaxdelta = delta;+ ps->waslubymaxdelta = 1;+ }+ else+ ps->waslubymaxdelta = 0;+}+#endif++static void+init_restart (PS * ps)+{+#ifdef NLUBY+ /* TODO: why is it better in incremental usage to have smaller initial+ * outer restart interval?+ */+ ps->ddrestart = ps->calls > 1 ? MINRESTART : 1000;+ ps->drestart = MINRESTART;+ ps->lrestart = ps->conflicts + ps->drestart;+#else+ ps->lubycnt = 0;+ ps->lubymaxdelta = 0;+ ps->waslubymaxdelta = 0;+ inc_lrestart (ps, 0);+#endif+}++static void+restart (PS * ps)+{+ int skip;+#ifdef NLUBY+ char kind;+ int outer;++ inc_drestart (ps);+ outer = (ps->drestart >= ps->ddrestart);++ if (outer)+ skip = very_high_agility (ps);+ else+ skip = high_agility (ps);+#else+ skip = medium_agility (ps);+#endif++#ifdef STATS+ if (skip)+ ps->skippedrestarts++;+#endif++ assert (ps->conflicts >= ps->lrestart);++ if (!skip)+ {+ ps->restarts++;+ assert (ps->LEVEL > 1);+ LOG ( fprintf (ps->out, "%srestart %u\n", ps->prefix, ps->restarts));+ undo (ps, 0);+ }++#ifdef NLUBY+ if (outer)+ {+ kind = skip ? 'N' : 'R';+ inc_ddrestart (ps);+ ps->drestart = MINRESTART;+ }+ else if (skip)+ {+ kind = 'n';+ }+ else+ {+ kind = 'r';+ }++ assert (ps->drestart <= MAXRESTART);+ ps->lrestart = ps->conflicts + ps->drestart;+ assert (ps->lrestart > ps->conflicts);++ report (outer ? 1 : 2, kind);+#else+ inc_lrestart (ps, skip);+#endif+}++inline static void+assign_decision (PS * ps, Lit * lit)+{+ assert (!ps->conflict);++ ps->LEVEL++;++ LOG ( fprintf (ps->out, "%snew level %u\n", ps->prefix, ps->LEVEL));+ LOG ( fprintf (ps->out,+ "%sassign %d at level %d <= DECISION\n",+ ps->prefix, LIT2INT (lit), ps->LEVEL));++ assign (ps, lit, 0);+}++#ifndef NFL++static int+lit_has_binary_clauses (PS * ps, Lit * lit)+{+#ifdef NO_BINARY_CLAUSES+ Ltk* lstk = LIT2IMPLS (lit);+ return lstk->count != 0;+#else+ return *LIT2IMPLS (lit) != 0;+#endif+}++static void+flbcp (PS * ps)+{+#ifdef STATS+ unsigned long long propagaions_before_bcp = ps->propagations;+#endif+ bcp (ps);+#ifdef STATS+ ps->flprops += ps->propagations - propagaions_before_bcp;+#endif+}++inline static int+cmp_inverse_rnk (PS * ps, Rnk * a, Rnk * b)+{+ (void) ps;+ return -cmp_rnk (a, b);+}++inline static Flt+rnk2jwh (PS * ps, Rnk * r)+{+ Flt res, sum, pjwh, njwh;+ Lit * plit, * nlit;++ plit = RNK2LIT (r);+ nlit = plit + 1;++ pjwh = *LIT2JWH (plit);+ njwh = *LIT2JWH (nlit);++ res = mulflt (pjwh, njwh);++ sum = addflt (pjwh, njwh);+ sum = mulflt (sum, base2flt (1, -10));+ res = addflt (res, sum);++ return res;+}++static int+cmp_inverse_jwh_rnk (PS * ps, Rnk * r, Rnk * s)+{+ Flt a = rnk2jwh (ps, r);+ Flt b = rnk2jwh (ps, s);+ int res = cmpflt (a, b);++ if (res)+ return -res;++ return cmp_inverse_rnk (ps, r, s);+}++static void+faillits (PS * ps)+{+ unsigned i, j, old_trail_count, common, saved_count;+ unsigned new_saved_size, oldladded = ps->ladded;+ unsigned long long limit, delta;+ Lit * lit, * other, * pivot;+ Rnk * r, ** p, ** q;+ int new_trail_count;+ double started;++ if (ps->plain)+ return;++ if (ps->heap + 1 >= ps->hhead)+ return;++ if (ps->propagations < ps->fllimit)+ return;++ sflush (ps);+ started = ps->seconds;++ ps->flcalls++;+#ifdef STATSA+ ps->flrounds++;+#endif+ delta = ps->propagations/10;+ if (delta >= 100*1000*1000) delta = 100*1000*1000;+ else if (delta <= 100*1000) delta = 100*1000;++ limit = ps->propagations + delta;+ ps->fllimit = ps->propagations;++ assert (!ps->LEVEL);+ assert (ps->simplifying);++ if (ps->flcalls <= 1)+ SORT (Rnk *, cmp_inverse_jwh_rnk, ps->heap + 1, ps->hhead - (ps->heap + 1));+ else+ SORT (Rnk *, cmp_inverse_rnk, ps->heap + 1, ps->hhead - (ps->heap + 1));++ i = 1; /* NOTE: heap starts at position '1' */++ while (ps->propagations < limit)+ {+ if (ps->heap + i == ps->hhead)+ {+ if (ps->ladded == oldladded)+ break;++ i = 1;+#ifdef STATS+ ps->flrounds++;+#endif+ oldladded = ps->ladded;+ }++ assert (ps->heap + i < ps->hhead);++ r = ps->heap[i++];+ lit = RNK2LIT (r);++ if (lit->val)+ continue;++ if (!lit_has_binary_clauses (ps, NOTLIT (lit)))+ {+#ifdef STATS+ ps->flskipped++;+#endif+ continue;+ }++#ifdef STATS+ ps->fltried++;+#endif+ LOG ( fprintf (ps->out, "%strying %d as failed literal\n",+ ps->prefix, LIT2INT (lit)));++ assign_decision (ps, lit);+ old_trail_count = ps->thead - ps->trail;+ flbcp (ps);++ if (ps->conflict)+ {+EXPLICITLY_FAILED_LITERAL:+ LOG ( fprintf (ps->out, "%sfound explicitly failed literal %d\n",+ ps->prefix, LIT2INT (lit)));++ ps->failedlits++;+ ps->efailedlits++;++ backtrack (ps);+ flbcp (ps);++ if (!ps->conflict)+ continue;++CONTRADICTION:+ assert (!ps->LEVEL);+ backtrack (ps);+ assert (ps->mtcls);++ goto RETURN;+ }++ if (ps->propagations >= limit)+ {+ undo (ps, 0);+ break;+ }++ lit = NOTLIT (lit);++ if (!lit_has_binary_clauses (ps, NOTLIT (lit)))+ {+#ifdef STATS+ ps->flskipped++;+#endif+ undo (ps, 0);+ continue;+ }++#ifdef STATS+ ps->fltried++;+#endif+ LOG ( fprintf (ps->out, "%strying %d as failed literals\n",+ ps->prefix, LIT2INT (lit)));++ new_trail_count = ps->thead - ps->trail;+ saved_count = new_trail_count - old_trail_count;++ if (saved_count > ps->saved_size)+ {+ new_saved_size = ps->saved_size ? 2 * ps->saved_size : 1;+ while (saved_count > new_saved_size)+ new_saved_size *= 2;++ RESIZEN (ps->saved, ps->saved_size, new_saved_size);+ ps->saved_size = new_saved_size;+ }++ for (j = 0; j < saved_count; j++)+ ps->saved[j] = ps->trail[old_trail_count + j];++ undo (ps, 0);++ assign_decision (ps, lit);+ flbcp (ps);++ if (ps->conflict)+ goto EXPLICITLY_FAILED_LITERAL;++ pivot = (ps->thead - ps->trail <= new_trail_count) ? lit : NOTLIT (lit);++ common = 0;+ for (j = 0; j < saved_count; j++)+ if ((other = ps->saved[j])->val == TRUE)+ ps->saved[common++] = other;++ undo (ps, 0);++ LOG (if (common)+ fprintf (ps->out,+ "%sfound %d literals implied by %d and %d\n",+ ps->prefix, common,+ LIT2INT (NOTLIT (lit)), LIT2INT (lit)));++#if 1 // set to zero to disable 'lifting'+ for (j = 0;+ j < common+ /* TODO: For some Velev benchmarks, extracting the common implicit+ * failed literals took quite some time. This needs to be fixed by+ * a dedicated analyzer. Up to then we bound the number of+ * propagations in this loop as well.+ */+ && ps->propagations < limit + delta+ ; j++)+ {+ other = ps->saved[j];++ if (other->val == TRUE)+ continue;++ assert (!other->val);++ LOG ( fprintf (ps->out,+ "%sforcing %d as forced implicitly failed literal\n",+ ps->prefix, LIT2INT (other)));++ assert (pivot != NOTLIT (other));+ assert (pivot != other);++ assign_decision (ps, NOTLIT (other));+ flbcp (ps);++ assert (ps->LEVEL == 1);++ if (ps->conflict)+ {+ backtrack (ps);+ assert (!ps->LEVEL);+ }+ else+ {+ assign_decision (ps, pivot);+ flbcp (ps);++ backtrack (ps);++ if (ps->LEVEL)+ {+ assert (ps->LEVEL == 1);++ flbcp (ps);++ if (ps->conflict)+ {+ backtrack (ps);+ assert (!ps->LEVEL);+ }+ else+ {+ assign_decision (ps, NOTLIT (pivot));+ flbcp (ps);+ backtrack (ps);++ if (ps->LEVEL)+ {+ assert (ps->LEVEL == 1);+ flbcp (ps);++ if (!ps->conflict)+ {+#ifdef STATS+ ps->floopsed++;+#endif+ undo (ps, 0);+ continue;+ }++ backtrack (ps);+ }++ assert (!ps->LEVEL);+ }++ assert (!ps->LEVEL);+ }+ }+ assert (!ps->LEVEL);+ flbcp (ps);++ ps->failedlits++;+ ps->ifailedlits++;++ if (ps->conflict)+ goto CONTRADICTION;+ }+#endif+ }++ ps->fllimit += 9 * (ps->propagations - ps->fllimit); /* 10% for failed literals */++RETURN:++ /* First flush top level assigned literals. Those are prohibited from+ * being pushed up the heap during 'faillits' since 'simplifying' is set.+ */+ assert (ps->heap < ps->hhead);+ for (p = q = ps->heap + 1; p < ps->hhead; p++)+ {+ r = *p;+ lit = RNK2LIT (r);+ if (lit->val)+ r->pos = 0;+ else+ *q++ = r;+ }++ /* Then resort with respect to EVSIDS score and fix positions.+ */+ SORT (Rnk *, cmp_inverse_rnk, ps->heap + 1, ps->hhead - (ps->heap + 1));+ for (p = ps->heap + 1; p < ps->hhead; p++)+ (*p)->pos = p - ps->heap;++ sflush (ps);+ ps->flseconds += ps->seconds - started;+}++#endif++static void+simplify (PS * ps, int forced)+{+ Lit * lit, * notlit, ** t;+ unsigned collect, delta;+#ifdef STATS+ size_t bytes_collected;+#endif+ int * q, ilit;+ Cls **p, *c;+ Var * v;++#ifndef NDEDBUG+ (void) forced;+#endif++ assert (!ps->mtcls);+ assert (!satisfied (ps));+ assert (forced || ps->lsimplify <= ps->propagations);+ assert (forced || ps->fsimplify <= ps->fixed);++ if (ps->LEVEL)+ undo (ps, 0);+#ifndef NFL+ ps->simplifying = 1;+ faillits (ps);+ ps->simplifying = 0;++ if (ps->mtcls)+ return;+#endif++ if (ps->cils != ps->cilshead)+ {+ assert (ps->ttail == ps->thead);+ assert (ps->ttail2 == ps->thead);+ ps->ttail = ps->trail;+ for (t = ps->trail; t < ps->thead; t++)+ {+ lit = *t;+ v = LIT2VAR (lit);+ if (v->internal)+ {+ assert (LIT2INT (lit) < 0);+ assert (lit->val == TRUE);+ unassign (ps, lit);+ }+ else+ *ps->ttail++ = lit;+ }+ ps->ttail2 = ps->thead = ps->ttail;++ for (q = ps->cils; q != ps->cilshead; q++)+ {+ ilit = *q;+ assert (0 < ilit && ilit <= (int) ps->max_var);+ v = ps->vars + ilit;+ assert (v->internal);+ v->level = 0;+ v->reason = 0;+ lit = int2lit (ps, -ilit);+ assert (lit->val == UNDEF);+ lit->val = TRUE;+ notlit = NOTLIT (lit);+ assert (notlit->val == UNDEF);+ notlit->val = FALSE;+ }+ }++ collect = 0;+ for (p = SOC; p != EOC; p = NXC (p))+ {+ c = *p;+ if (!c)+ continue;++#ifdef TRACE+ if (c->collected)+ continue;+#endif++ if (c->locked)+ continue;++ assert (!c->collect);+ if (clause_is_toplevel_satisfied (ps, c))+ {+ mark_clause_to_be_collected (c);+ collect++;+ }+ }++ LOG ( fprintf (ps->out, "%scollecting %d clauses\n", ps->prefix, collect));+#ifdef STATS+ bytes_collected =+#endif+ collect_clauses (ps);+#ifdef STATS+ ps->srecycled += bytes_collected;+#endif++ if (ps->cils != ps->cilshead)+ {+ for (q = ps->cils; q != ps->cilshead; q++)+ {+ ilit = *q;+ assert (0 < ilit && ilit <= (int) ps->max_var);+ assert (ps->vars[ilit].internal);+ if (ps->rilshead == ps->eorils)+ ENLARGE (ps->rils, ps->rilshead, ps->eorils);+ *ps->rilshead++ = ilit;+ lit = int2lit (ps, -ilit);+ assert (lit->val == TRUE);+ lit->val = UNDEF;+ notlit = NOTLIT (lit);+ assert (notlit->val == FALSE);+ notlit->val = UNDEF;+ }+ ps->cilshead = ps->cils;+ }++ delta = 10 * (ps->olits + ps->llits) + 100000;+ if (delta > 2000000)+ delta = 2000000;+ ps->lsimplify = ps->propagations + delta;+ ps->fsimplify = ps->fixed;+ ps->simps++;++ report (ps, 1, 's');+}++static void+iteration (PS * ps)+{+ assert (!ps->LEVEL);+ assert (bcp_queue_is_empty (ps));+ assert (ps->isimplify < ps->fixed);++ ps->iterations++;+ report (ps, 2, 'i');+#ifdef NLUBY+ ps->drestart = MINRESTART;+ ps->lrestart = ps->conflicts + ps->drestart;+#else+ init_restart (ps);+#endif+ ps->isimplify = ps->fixed;+}++static int+cmp_glue_activity_size (PS * ps, Cls * c, Cls * d)+{+ Act a;+ Act b;++ (void) ps;++ assert (c->learned);+ assert (d->learned);++ if (c->glue < d->glue) // smaller glue preferred+ return 1;++ if (c->glue > d->glue)+ return -1;++ a = *CLS2ACT (c);+ b = *CLS2ACT (d);++ if (a < b) // then higher activity+ return -1;++ if (b < a)+ return 1;++ if (c->size < d->size) // then smaller size+ return 1;++ if (c->size > d->size)+ return -1;++ return 0;+}++static void+reduce (PS * ps, unsigned percentage)+{+ unsigned redcount, lcollect, collect, target;+#ifdef STATS+ size_t bytes_collected;+#endif+ Cls **p, *c;++ assert (ps->rhead == ps->resolved);++ ps->lastreduceconflicts = ps->conflicts;++ assert (percentage <= 100);+ LOG ( fprintf (ps->out,+ "%sreducing %u%% learned clauses\n",+ ps->prefix, percentage));++ while (ps->nlclauses - ps->llocked > (unsigned)(ps->eor - ps->resolved))+ ENLARGE (ps->resolved, ps->rhead, ps->eor);++ collect = 0;+ lcollect = 0;++ for (p = ((ps->fsimplify < ps->fixed) ? SOC : ps->lclauses); p != EOC; p = NXC (p))+ {+ c = *p;+ if (!c)+ continue;++#ifdef TRACE+ if (c->collected)+ continue;+#endif++ if (c->locked)+ continue;++ assert (!c->collect);+ if (ps->fsimplify < ps->fixed && clause_is_toplevel_satisfied (ps, c))+ {+ mark_clause_to_be_collected (c);+ collect++;++ if (c->learned && c->size > 2)+ lcollect++;++ continue;+ }++ if (!c->learned)+ continue;++ if (c->size <= 2)+ continue;++ assert (ps->rhead < ps->eor);+ *ps->rhead++ = c;+ }+ assert (ps->rhead <= ps->eor);++ ps->fsimplify = ps->fixed;++ redcount = ps->rhead - ps->resolved;+ SORT (Cls *, cmp_glue_activity_size, ps->resolved, redcount);++ assert (ps->nlclauses >= lcollect);+ target = ps->nlclauses - lcollect + 1;++ target = (percentage * target + 99) / 100;++ if (target >= redcount)+ target = redcount;++ ps->rhead = ps->resolved + target;+ while (ps->rhead > ps->resolved)+ {+ c = *--ps->rhead;+ mark_clause_to_be_collected (c);++ collect++;+ if (c->learned && c->size > 2) /* just for consistency */+ lcollect++;+ }++ if (collect)+ {+ ps->reductions++;+#ifdef STATS+ bytes_collected =+#endif+ collect_clauses (ps);+#ifdef STATS+ ps->rrecycled += bytes_collected;+#endif+ report (ps, 2, '-');+ }++ if (!lcollect)+ inc_lreduce (ps); /* avoid dead lock */++ assert (ps->rhead == ps->resolved);+}++static void+init_reduce (PS * ps)+{+ // lreduce = loadded / 2;+ ps->lreduce = 1000;++ if (ps->lreduce < 100)+ ps->lreduce = 100;++ if (ps->verbosity)+ fprintf (ps->out,+ "%s\n%sinitial reduction limit %u clauses\n%s\n",+ ps->prefix, ps->prefix, ps->lreduce, ps->prefix);+}++static unsigned+rng (PS * ps)+{+ unsigned res = ps->srng;+ ps->srng *= 1664525u;+ ps->srng += 1013904223u;+ NOLOG ( fprintf (ps->out, "%srng () = %u\n", ps->prefix, res));+ return res;+}++static unsigned+rrng (PS * ps, unsigned low, unsigned high)+{+ unsigned long long tmp;+ unsigned res, elements;+ assert (low <= high);+ elements = high - low + 1;+ tmp = rng (ps);+ tmp *= elements;+ tmp >>= 32;+ tmp += low;+ res = tmp;+ NOLOG ( fprintf (ps->out, "%srrng (ps, %u, %u) = %u\n", ps->prefix, low, high, res));+ assert (low <= res);+ assert (res <= high);+ return res;+}++static Lit *+decide_phase (PS * ps, Lit * lit)+{+ Lit * not_lit = NOTLIT (lit);+ Var *v = LIT2VAR (lit);++ assert (LIT2SGN (lit) > 0);+ if (v->usedefphase)+ {+ if (v->defphase)+ {+ /* assign to TRUE */+ }+ else+ {+ /* assign to FALSE */+ lit = not_lit;+ }+ }+ else if (!v->assigned)+ {+#ifdef STATS+ ps->staticphasedecisions++;+#endif+ if (ps->defaultphase == POSPHASE)+ {+ /* assign to TRUE */+ }+ else if (ps->defaultphase == NEGPHASE)+ {+ /* assign to FALSE */+ lit = not_lit;+ }+ else if (ps->defaultphase == RNDPHASE)+ {+ /* randomly assign default phase */+ if (rrng (ps, 1, 2) != 2)+ lit = not_lit;+ }+ else if (*LIT2JWH(lit) <= *LIT2JWH (not_lit))+ {+ /* assign to FALSE (Jeroslow-Wang says there are more short+ * clauses with negative occurence of this variable, so satisfy+ * those, to minimize BCP)+ */+ lit = not_lit;+ }+ else+ {+ /* assign to TRUE (... but strictly more positive occurrences) */+ }+ }+ else+ {+ /* repeat last phase: phase saving heuristic */++ if (v->phase)+ {+ /* assign to TRUE (last phase was TRUE as well) */+ }+ else+ {+ /* assign to FALSE (last phase was FALSE as well) */+ lit = not_lit;+ }+ }++ return lit;+}++static unsigned+gcd (unsigned a, unsigned b)+{+ unsigned tmp;++ assert (a);+ assert (b);++ if (a < b)+ {+ tmp = a;+ a = b;+ b = tmp;+ }++ while (b)+ {+ assert (a >= b);+ tmp = b;+ b = a % b;+ a = tmp;+ }++ return a;+}++static Lit *+rdecide (PS * ps)+{+ unsigned idx, delta, spread;+ Lit * res;++ spread = RDECIDE;+ if (rrng (ps, 1, spread) != 2)+ return 0;++ assert (1 <= ps->max_var);+ idx = rrng (ps, 1, ps->max_var);+ res = int2lit (ps, idx);++ if (res->val != UNDEF)+ {+ delta = rrng (ps, 1, ps->max_var);+ while (gcd (delta, ps->max_var) != 1)+ delta--;++ assert (1 <= delta);+ assert (delta <= ps->max_var);++ do {+ idx += delta;+ if (idx > ps->max_var)+ idx -= ps->max_var;+ res = int2lit (ps, idx);+ } while (res->val != UNDEF);+ }++#ifdef STATS+ ps->rdecisions++;+#endif+ res = decide_phase (ps, res);+ LOG ( fprintf (ps->out, "%srdecide %d\n", ps->prefix, LIT2INT (res)));++ return res;+}++static Lit *+sdecide (PS * ps)+{+ Lit *res;+ Rnk *r;++ for (;;)+ {+ r = htop (ps);+ res = RNK2LIT (r);+ if (res->val == UNDEF) break;+ (void) hpop (ps);+ NOLOG ( fprintf (ps->out,+ "%shpop %u %u %u\n",+ ps->prefix, r - ps->rnks,+ FLTMANTISSA(r->score),+ FLTEXPONENT(r->score)));+ }++#ifdef STATS+ ps->sdecisions++;+#endif+ res = decide_phase (ps, res);++ LOG ( fprintf (ps->out, "%ssdecide %d\n", ps->prefix, LIT2INT (res)));++ return res;+}++static Lit *+adecide (PS * ps)+{+ Lit *lit;+ Var * v;++ assert (ps->als < ps->alshead);+ assert (!ps->failed_assumption);++ while (ps->alstail < ps->alshead)+ {+ lit = *ps->alstail++;++ if (lit->val == FALSE)+ {+ ps->failed_assumption = lit;+ v = LIT2VAR (lit);++ use_var (ps, v);++ LOG ( fprintf (ps->out, "%sfirst failed assumption %d\n",+ ps->prefix, LIT2INT (ps->failed_assumption)));+ fanalyze (ps);+ return 0;+ }++ if (lit->val == TRUE)+ {+ v = LIT2VAR (lit);+ if (v->level > ps->adecidelevel)+ ps->adecidelevel = v->level;+ continue;+ }++#ifdef STATS+ ps->assumptions++;+#endif+ LOG ( fprintf (ps->out, "%sadecide %d\n", ps->prefix, LIT2INT (lit)));+ ps->adecidelevel = ps->LEVEL + 1;++ return lit;+ }++ return 0;+}++static void+decide (PS * ps)+{+ Lit * lit;++ assert (!satisfied (ps));+ assert (!ps->conflict);++ if (ps->alstail < ps->alshead && (lit = adecide (ps)))+ ;+ else if (ps->failed_assumption)+ return;+ else if (satisfied (ps))+ return;+ else if (!(lit = rdecide (ps)))+ lit = sdecide (ps);++ assert (lit);+ assign_decision (ps, lit);++ ps->levelsum += ps->LEVEL;+ ps->decisions++;+}++static int+sat (PS * ps, int l)+{+ int count = 0, backtracked;++ if (!ps->conflict)+ bcp (ps);++ if (ps->conflict)+ backtrack (ps);++ if (ps->mtcls)+ return PICOSAT_UNSATISFIABLE;++ if (satisfied (ps))+ goto SATISFIED;++ if (ps->lsimplify <= ps->propagations)+ simplify (ps, 0);++ if (ps->mtcls)+ return PICOSAT_UNSATISFIABLE;++ if (satisfied (ps))+ goto SATISFIED;++ init_restart (ps);++ if (!ps->lreduce)+ init_reduce (ps);++ ps->isimplify = ps->fixed;+ backtracked = 0;++ for (;;)+ {+ if (!ps->conflict)+ bcp (ps);++ if (ps->conflict)+ {+ incincs (ps);+ backtrack (ps);++ if (ps->mtcls)+ return PICOSAT_UNSATISFIABLE;+ backtracked = 1;+ continue;+ }++ if (satisfied (ps))+ {+SATISFIED:+#ifndef NDEBUG+ original_clauses_satisfied (ps);+ assumptions_satisfied (ps);+#endif+ return PICOSAT_SATISFIABLE;+ }++ if (backtracked)+ {+ backtracked = 0;+ if (!ps->LEVEL && ps->isimplify < ps->fixed)+ iteration (ps);+ }++ if (l >= 0 && count >= l) /* decision limit reached ? */+ return PICOSAT_UNKNOWN;++ if (ps->propagations >= ps->lpropagations)/* propagation limit reached ? */+ return PICOSAT_UNKNOWN;++#ifndef NADC+ if (!ps->adodisabled && ps->adoconflicts >= ps->adoconflictlimit)+ {+ assert (bcp_queue_is_empty (ps));+ return PICOSAT_UNKNOWN;+ }+#endif++ if (ps->fsimplify < ps->fixed && ps->lsimplify <= ps->propagations)+ {+ simplify (ps, 0);+ if (!bcp_queue_is_empty (ps))+ continue;+#ifndef NFL+ if (ps->mtcls)+ return PICOSAT_UNSATISFIABLE;++ if (satisfied (ps))+ return PICOSAT_SATISFIABLE;++ assert (!ps->LEVEL);+#endif+ }++ if (need_to_reduce (ps))+ reduce (ps, 50);++ if (ps->conflicts >= ps->lrestart && ps->LEVEL > 2)+ restart (ps);++ decide (ps);+ if (ps->failed_assumption)+ return PICOSAT_UNSATISFIABLE;+ count++;+ }+}++static void+rebias (PS * ps)+{+ Cls ** p, * c;+ Var * v;++ for (v = ps->vars + 1; v <= ps->vars + ps->max_var; v++)+ v->assigned = 0;++ memset (ps->jwh, 0, 2 * (ps->max_var + 1) * sizeof *ps->jwh);++ for (p = ps->oclauses; p < ps->ohead; p++)+ {+ c = *p;++ if (!c)+ continue;++ if (c->learned)+ continue;++ incjwh (ps, c);+ }+}++#ifdef TRACE++static unsigned+core (PS * ps)+{+ unsigned idx, prev, this, delta, i, lcore, vcore;+ unsigned *stack, *shead, *eos;+ Lit **q, **eol, *lit;+ Cls *c, *reason;+ Znt *p, byte;+ Zhn *zhain;+ Var *v;++ assert (ps->trace);++ assert (ps->mtcls || ps->failed_assumption);+ if (ps->ocore >= 0)+ return ps->ocore;++ lcore = ps->ocore = vcore = 0;++ stack = shead = eos = 0;+ ENLARGE (stack, shead, eos);++ if (ps->mtcls)+ {+ idx = CLS2IDX (ps->mtcls);+ *shead++ = idx;+ }+ else+ {+ assert (ps->failed_assumption);+ v = LIT2VAR (ps->failed_assumption);+ reason = v->reason;+ assert (reason);+ idx = CLS2IDX (reason);+ *shead++ = idx;+ }++ while (shead > stack)+ {+ idx = *--shead;+ zhain = IDX2ZHN (idx);++ if (zhain)+ {+ if (zhain->core)+ continue;++ zhain->core = 1;+ lcore++;++ c = IDX2CLS (idx);+ if (c)+ {+ assert (!c->core);+ c->core = 1;+ }++ i = 0;+ delta = 0;+ prev = 0;+ for (p = zhain->znt; (byte = *p); p++, i += 7)+ {+ delta |= (byte & 0x7f) << i;+ if (byte & 0x80)+ continue;++ this = prev + delta;+ assert (prev < this); /* no overflow */++ if (shead == eos)+ ENLARGE (stack, shead, eos);+ *shead++ = this;++ prev = this;+ delta = 0;+ i = -7;+ }+ }+ else+ {+ c = IDX2CLS (idx);++ assert (c);+ assert (!c->learned);++ if (c->core)+ continue;++ c->core = 1;+ ps->ocore++;++ eol = end_of_lits (c);+ for (q = c->lits; q < eol; q++)+ {+ lit = *q;+ v = LIT2VAR (lit);+ if (v->core)+ continue;++ v->core = 1;+ vcore++;++ if (!ps->failed_assumption) continue;+ if (lit != ps->failed_assumption) continue;++ reason = v->reason;+ if (!reason) continue;+ if (reason->core) continue;++ idx = CLS2IDX (reason);+ if (shead == eos)+ ENLARGE (stack, shead, eos);+ *shead++ = idx;+ }+ }+ }++ DELETEN (stack, eos - stack);++ if (ps->verbosity)+ fprintf (ps->out,+ "%s%u core variables out of %u (%.1f%%)\n"+ "%s%u core original clauses out of %u (%.1f%%)\n"+ "%s%u core learned clauses out of %u (%.1f%%)\n",+ ps->prefix, vcore, ps->max_var, PERCENT (vcore, ps->max_var),+ ps->prefix, ps->ocore, ps->oadded, PERCENT (ps->ocore, ps->oadded),+ ps->prefix, lcore, ps->ladded, PERCENT (lcore, ps->ladded));++ return ps->ocore;+}++static void+trace_lits (PS * ps, Cls * c, FILE * file)+{+ Lit **p, **eol = end_of_lits (c);++ assert (c);+ assert (c->core);++ for (p = c->lits; p < eol; p++)+ fprintf (file, "%d ", LIT2INT (*p));++ fputc ('0', file);+}++static void+write_idx (PS * ps, unsigned idx, FILE * file)+{+ fprintf (file, "%ld", EXPORTIDX (idx));+}++static void+trace_clause (PS * ps, unsigned idx, Cls * c, FILE * file, int fmt)+{+ assert (c);+ assert (c->core);+ assert (fmt == RUP_TRACE_FMT || !c->learned);+ assert (CLS2IDX (c) == idx);++ if (fmt != RUP_TRACE_FMT)+ {+ write_idx (ps, idx, file);+ fputc (' ', file);+ }++ trace_lits (ps, c, file);++ if (fmt != RUP_TRACE_FMT)+ fputs (" 0", file);++ fputc ('\n', file);+}++static void+trace_zhain (PS * ps, unsigned idx, Zhn * zhain, FILE * file, int fmt)+{+ unsigned prev, this, delta, i;+ Znt *p, byte;+ Cls * c;++ assert (zhain);+ assert (zhain->core);++ write_idx (ps, idx, file);+ fputc (' ', file);++ if (fmt == EXTENDED_TRACECHECK_TRACE_FMT)+ {+ c = IDX2CLS (idx);+ assert (c);+ trace_lits (ps, c, file);+ }+ else+ {+ assert (fmt == COMPACT_TRACECHECK_TRACE_FMT);+ putc ('*', file);+ }++ i = 0;+ delta = 0;+ prev = 0;++ for (p = zhain->znt; (byte = *p); p++, i += 7)+ {+ delta |= (byte & 0x7f) << i;+ if (byte & 0x80)+ continue;++ this = prev + delta;++ putc (' ', file);+ write_idx (ps, this, file);++ prev = this;+ delta = 0;+ i = -7;+ }++ fputs (" 0\n", file);+}++static void+write_core (PS * ps, FILE * file)+{+ Lit **q, **eol;+ Cls **p, *c;++ fprintf (file, "p cnf %u %u\n", ps->max_var, core (ps));++ for (p = SOC; p != EOC; p = NXC (p))+ {+ c = *p;++ if (!c || c->learned || !c->core)+ continue;++ eol = end_of_lits (c);+ for (q = c->lits; q < eol; q++)+ fprintf (file, "%d ", LIT2INT (*q));++ fputs ("0\n", file);+ }+}++#endif++static void+write_trace (PS * ps, FILE * file, int fmt)+{+#ifdef TRACE+ Cls *c, ** p;+ Zhn *zhain;+ unsigned i;++ core (ps);++ if (fmt == RUP_TRACE_FMT)+ {+ ps->rupvariables = picosat_variables (ps),+ ps->rupclauses = picosat_added_original_clauses (ps);+ write_rup_header (ps, file);+ }++ for (p = SOC; p != EOC; p = NXC (p))+ {+ c = *p;++ if (ps->oclauses <= p && p < ps->eoo)+ {+ i = OIDX2IDX (p - ps->oclauses);+ assert (!c || CLS2IDX (c) == i);+ }+ else+ {+ assert (ps->lclauses <= p && p < ps->EOL);+ i = LIDX2IDX (p - ps->lclauses);+ }++ zhain = IDX2ZHN (i);++ if (zhain)+ {+ if (zhain->core)+ {+ if (fmt == RUP_TRACE_FMT)+ trace_clause (ps,i, c, file, fmt);+ else+ trace_zhain (ps, i, zhain, file, fmt);+ }+ }+ else if (c)+ {+ if (fmt != RUP_TRACE_FMT && c)+ {+ if (c->core)+ trace_clause (ps, i, c, file, fmt);+ }+ }+ }+#else+ (void) file;+ (void) fmt;+ (void) ps;+#endif+}++static void+write_core_wrapper (PS * ps, FILE * file, int fmt)+{+ (void) fmt;+#ifdef TRACE+ write_core (ps, file);+#else+ (void) ps;+ (void) file;+#endif+}++static Lit *+import_lit (PS * ps, int lit, int nointernal)+{+ Lit * res;+ Var * v;++ ABORTIF (lit == INT_MIN, "API usage: INT_MIN literal");+ ABORTIF (abs (lit) > (int) ps->max_var && ps->CLS != ps->clshead,+ "API usage: new variable index after 'picosat_push'");++ if (abs (lit) <= (int) ps->max_var)+ {+ res = int2lit (ps, lit);+ v = LIT2VAR (res);+ if (nointernal && v->internal)+ ABORT ("API usage: trying to import invalid literal");+ else if (!nointernal && !v->internal)+ ABORT ("API usage: trying to import invalid context");+ }+ else+ {+ while (abs (lit) > (int) ps->max_var)+ inc_max_var (ps);+ res = int2lit (ps, lit);+ }++ return res;+}++#ifdef TRACE+static void+reset_core (PS * ps)+{+ Cls ** p, * c;+ Zhn ** q, * z;+ unsigned i;++ for (i = 1; i <= ps->max_var; i++)+ ps->vars[i].core = 0;++ for (p = SOC; p != EOC; p = NXC (p))+ if ((c = *p))+ c->core = 0;++ for (q = ps->zhains; q != ps->zhead; q++)+ if ((z = *q))+ z->core = 0;++ ps->ocore = -1;+}+#endif++static void+reset_assumptions (PS * ps)+{+ Lit ** p;++ ps->failed_assumption = 0;++ if (ps->extracted_all_failed_assumptions)+ {+ for (p = ps->als; p < ps->alshead; p++)+ LIT2VAR (*p)->failed = 0;++ ps->extracted_all_failed_assumptions = 0;+ }++ ps->alstail = ps->alshead = ps->als;+ ps->adecidelevel = 0;+}++static void+check_ready (PS * ps)+{+ ABORTIF (!ps || ps->state == RESET, "API usage: uninitialized");+}++static void+check_sat_state (PS * ps)+{+ ABORTIF (ps->state != SAT, "API usage: expected to be in SAT state");+}++static void+check_unsat_state (PS * ps)+{+ ABORTIF (ps->state != UNSAT, "API usage: expected to be in UNSAT state");+}++static void+check_sat_or_unsat_or_unknown_state (PS * ps)+{+ ABORTIF (ps->state != SAT && ps->state != UNSAT && ps->state != UNKNOWN,+ "API usage: expected to be in SAT, UNSAT, or UNKNOWN state");+}++static void+reset_partial (PS * ps)+{+ unsigned idx;+ if (!ps->partial)+ return;+ for (idx = 1; idx <= ps->max_var; idx++)+ ps->vars[idx].partial = 0;+ ps->partial = 0;+}++static void+reset_incremental_usage (PS * ps)+{+ unsigned num_non_false;+ Lit * lit, ** q;++ check_sat_or_unsat_or_unknown_state (ps);++ LOG ( fprintf (ps->out, "%sRESET incremental usage\n", ps->prefix));++ if (ps->LEVEL)+ undo (ps, 0);++ reset_assumptions (ps);++ if (ps->conflict)+ {+ num_non_false = 0;+ for (q = ps->conflict->lits; q < end_of_lits (ps->conflict); q++)+ {+ lit = *q;+ if (lit->val != FALSE)+ num_non_false++;+ }++ // assert (num_non_false >= 2); // TODO: why this assertion?+#ifdef NO_BINARY_CLAUSES+ if (ps->conflict == &ps->cimpl)+ resetcimpl (ps);+#endif+#ifndef NADC+ if (ps->conflict == ps->adoconflict)+ resetadoconflict (ps);+#endif+ ps->conflict = 0;+ }++#ifdef TRACE+ reset_core (ps);+#endif++ reset_partial (ps);++ ps->saved_flips = ps->flips;+ ps->min_flipped = UINT_MAX;+ ps->saved_max_var = ps->max_var;++ ps->state = READY;+}++static void+enter (PS * ps)+{+ if (ps->nentered++)+ return;++ check_ready (ps);+ ps->entered = picosat_time_stamp ();+}++static void+leave (PS * ps)+{+ assert (ps->nentered);+ if (--ps->nentered)+ return;++ sflush (ps);+}++static void+check_trace_support_and_execute (PS * ps,+ FILE * file,+ void (*f)(PS*,FILE*,int), int fmt)+{+ check_ready (ps);+ check_unsat_state (ps);+#ifdef TRACE+ ABORTIF (!ps->trace, "API usage: tracing disabled");+ enter (ps);+ f (ps, file, fmt);+ leave (ps);+#else+ (void) file;+ (void) fmt;+ (void) f;+ ABORT ("compiled without trace support");+#endif+}++static void+extract_all_failed_assumptions (PS * ps)+{+ Lit ** p, ** eol;+ Var * v, * u;+ int pos;+ Cls * c;++ assert (!ps->extracted_all_failed_assumptions);++ assert (ps->failed_assumption);+ assert (ps->mhead == ps->marked);++ if (ps->marked == ps->eom)+ ENLARGE (ps->marked, ps->mhead, ps->eom);++ v = LIT2VAR (ps->failed_assumption);+ mark_var (ps, v);+ pos = 0;++ while (pos < ps->mhead - ps->marked)+ {+ v = ps->marked[pos++];+ assert (v->mark);+ c = var2reason (ps, v);+ if (!c)+ continue;+ eol = end_of_lits (c);+ for (p = c->lits; p < eol; p++)+ {+ u = LIT2VAR (*p);+ if (!u->mark)+ mark_var (ps, u);+ }+#ifdef NO_BINARY_CLAUSES+ if (c == &ps->impl)+ resetimpl (ps);+#endif+ }++ for (p = ps->als; p < ps->alshead; p++)+ {+ u = LIT2VAR (*p);+ if (!u->mark) continue;+ u->failed = 1;+ LOG ( fprintf (ps->out,+ "%sfailed assumption %d\n",+ ps->prefix, LIT2INT (*p)));+ }++ while (ps->mhead > ps->marked)+ (*--ps->mhead)->mark = 0;++ ps->extracted_all_failed_assumptions = 1;+}++const char *+picosat_copyright (void)+{+ return "Copyright (c) 2006 - 2012 Armin Biere JKU Linz";+}++PicoSAT *+picosat_init (void)+{+ return init (0, 0, 0, 0);+}++PicoSAT *+picosat_minit (void * pmgr,+ picosat_malloc pnew,+ picosat_realloc presize,+ picosat_free pfree)+{+ ABORTIF (!pnew, "API usage: zero 'picosat_malloc' argument");+ ABORTIF (!presize, "API usage: zero 'picosat_realloc' argument");+ ABORTIF (!pfree, "API usage: zero 'picosat_free' argument");+ return init (pmgr, pnew, presize, pfree);+}+++void+picosat_adjust (PS * ps, int new_max_var)+{+ unsigned new_size_vars;++ ABORTIF (abs (new_max_var) > (int) ps->max_var && ps->CLS != ps->clshead,+ "API usage: adjusting variable index after 'picosat_push'");+ enter (ps);++ new_max_var = abs (new_max_var);+ new_size_vars = new_max_var + 1;++ if (ps->size_vars < new_size_vars)+ enlarge (ps, new_size_vars);++ while (ps->max_var < (unsigned) new_max_var)+ inc_max_var (ps);++ leave (ps);+}++int+picosat_inc_max_var (PS * ps)+{+ if (ps->measurealltimeinlib)+ enter (ps);+ else+ check_ready (ps);++ inc_max_var (ps);++ if (ps->measurealltimeinlib)+ leave (ps);++ return ps->max_var;+}++int+picosat_context (PS * ps)+{+ return ps->clshead == ps->CLS ? 0 : LIT2INT (ps->clshead[-1]);+}++int+picosat_push (PS * ps)+{+ int res;+ Lit *lit;+ Var * v;++ if (ps->measurealltimeinlib)+ enter (ps);+ else+ check_ready (ps);++ if (ps->state != READY)+ reset_incremental_usage (ps);++ if (ps->rils != ps->rilshead)+ {+ res = *--ps->rilshead;+ assert (ps->vars[res].internal);+ }+ else+ {+ inc_max_var (ps);+ res = ps->max_var;+ v = ps->vars + res;+ assert (!v->internal);+ v->internal = 1;+ ps->internals++;+ LOG ( fprintf (ps->out, "%snew internal variable index %d\n", ps->prefix, res));+ }++ lit = int2lit (ps, res);++ if (ps->clshead == ps->eocls)+ ENLARGE (ps->CLS, ps->clshead, ps->eocls);+ *ps->clshead++ = lit;++ ps->contexts++;++ LOG ( fprintf (ps->out, "%snew context %d at depth %ld after push\n",+ ps->prefix, res, (long)(ps->clshead - ps->CLS)));++ if (ps->measurealltimeinlib)+ leave (ps);++ return res;+}++int+picosat_pop (PS * ps)+{+ Lit * lit;+ int res;+ ABORTIF (ps->CLS == ps->clshead, "API usage: too many 'picosat_pop'");+ ABORTIF (ps->added != ps->ahead, "API usage: incomplete clause");++ if (ps->measurealltimeinlib)+ enter (ps);+ else+ check_ready (ps);++ if (ps->state != READY)+ reset_incremental_usage (ps);++ assert (ps->CLS < ps->clshead);+ lit = *--ps->clshead;+ LOG ( fprintf (ps->out, "%sclosing context %d at depth %ld after pop\n",+ ps->prefix, LIT2INT (lit), (long)(ps->clshead - ps->CLS) + 1));++ if (ps->cilshead == ps->eocils)+ ENLARGE (ps->cils, ps->cilshead, ps->eocils);+ *ps->cilshead++ = LIT2INT (lit);++ if (ps->cilshead - ps->cils > MAXCILS) {+ LOG ( fprintf (ps->out,+ "%srecycling %ld interals with forced simplification\n",+ ps->prefix, (long)(ps->cilshead - ps->cils)));+ simplify (ps, 1);+ }++ res = picosat_context (ps);+ if (res)+ LOG ( fprintf (ps->out, "%snew context %d at depth %ld after pop\n",+ ps->prefix, res, (long)(ps->clshead - ps->CLS)));+ else+ LOG ( fprintf (ps->out, "%souter most context reached after pop\n", ps->prefix));++ if (ps->measurealltimeinlib)+ leave (ps);++ return res;+}++void+picosat_set_verbosity (PS * ps, int new_verbosity_level)+{+ check_ready (ps);+ ps->verbosity = new_verbosity_level;+}++void+picosat_set_plain (PS * ps, int new_plain_value)+{+ check_ready (ps);+ ps->plain = new_plain_value;+}++int+picosat_enable_trace_generation (PS * ps)+{+ int res = 0;+ check_ready (ps);+#ifdef TRACE+ ABORTIF (ps->addedclauses,+ "API usage: trace generation enabled after adding clauses");+ res = ps->trace = 1;+#endif+ return res;+}++void+picosat_set_incremental_rup_file (PS * ps, FILE * rup_file, int m, int n)+{+ check_ready (ps);+ assert (!ps->rupstarted);+ ps->rup = rup_file;+ ps->rupvariables = m;+ ps->rupclauses = n;+}++void+picosat_set_output (PS * ps, FILE * output_file)+{+ check_ready (ps);+ ps->out = output_file;+}++void+picosat_measure_all_calls (PS * ps)+{+ check_ready (ps);+ ps->measurealltimeinlib = 1;+}++void+picosat_set_prefix (PS * ps, const char * str)+{+ check_ready (ps);+ new_prefix (ps, str);+}++void+picosat_set_seed (PS * ps, unsigned s)+{+ check_ready (ps);+ ps->srng = s;+}++void+picosat_reset (PS * ps)+{+ check_ready (ps);+ reset (ps);+}++int+picosat_add (PS * ps, int int_lit)+{+ int res = ps->oadded;+ Lit *lit;++ if (ps->measurealltimeinlib)+ enter (ps);+ else+ check_ready (ps);++ ABORTIF (ps->rup && ps->rupstarted && ps->oadded >= (unsigned)ps->rupclauses,+ "API usage: adding too many clauses after RUP header written");+#ifndef NADC+ ABORTIF (ps->addingtoado,+ "API usage: 'picosat_add' and 'picosat_add_ado_lit' mixed");+#endif+ if (ps->state != READY)+ reset_incremental_usage (ps);++ if (ps->saveorig)+ {+ if (ps->sohead == ps->eoso)+ ENLARGE (ps->soclauses, ps->sohead, ps->eoso);++ *ps->sohead++ = int_lit;+ }++ if (int_lit)+ {+ lit = import_lit (ps, int_lit, 1);+ add_lit (ps, lit);+ }+ else+ simplify_and_add_original_clause (ps);++ if (ps->measurealltimeinlib)+ leave (ps);++ return res;+}++int+picosat_add_arg (PS * ps, ...)+{+ int lit;+ va_list ap;+ va_start (ap, ps);+ while ((lit = va_arg (ap, int)))+ (void) picosat_add (ps, lit);+ va_end (ap);+ return picosat_add (ps, 0);+}++int+picosat_add_lits (PS * ps, int * lits)+{+ const int * p;+ int lit;+ for (p = lits; (lit = *p); p++)+ (void) picosat_add (ps, lit);+ return picosat_add (ps, 0);+}++void+picosat_add_ado_lit (PS * ps, int external_lit)+{+#ifndef NADC+ Lit * internal_lit;++ if (ps->measurealltimeinlib)+ enter (ps);+ else+ check_ready (ps);++ if (ps->state != READY)+ reset_incremental_usage (ps);++ ABORTIF (!ps->addingtoado && ps->ahead > ps->added,+ "API usage: 'picosat_add' and 'picosat_add_ado_lit' mixed");++ if (external_lit)+ {+ ps->addingtoado = 1;+ internal_lit = import_lit (external_lit, 1);+ add_lit (internal_lit);+ }+ else+ {+ ps->addingtoado = 0;+ add_ado (ps);+ }+ if (ps->measurealltimeinlib)+ leave (ps);+#else+ (void) ps;+ (void) external_lit;+ ABORT ("compiled without all different constraint support");+#endif+}++static void+assume (PS * ps, Lit * lit)+{+ if (ps->alshead == ps->eoals)+ {+ assert (ps->alstail == ps->als);+ ENLARGE (ps->als, ps->alshead, ps->eoals);+ ps->alstail = ps->als;+ }++ *ps->alshead++ = lit;+ LOG ( fprintf (ps->out, "%sassumption %d\n", ps->prefix, LIT2INT (lit)));+}++static void+assume_contexts (PS * ps)+{+ Lit ** p;+ if (ps->als != ps->alshead)+ return;+ for (p = ps->CLS; p != ps->clshead; p++)+ assume (ps, *p);+}++static const char * enumstr (int i) {+ int last = i % 10;+ if (last == 1) return "st";+ if (last == 2) return "nd";+ if (last == 3) return "rd";+ return "th";+}++static int+pderef (PS * ps, int int_lit)+{+ Lit * lit;+ Var * v;++ assert (abs (int_lit) <= (int) ps->max_var);++ v = ps->vars + abs (int_lit);+ if (!v->partial)+ return 0;++ lit = int2lit (ps, int_lit);++ if (lit->val == TRUE)+ return 1;++ if (lit->val == FALSE)+ return -1;++ return 0;+}++static void+minautarky (PS * ps)+{+ unsigned * occs, maxoccs, tmpoccs, npartial;+ int * p, * c, lit, best, val;++ assert (!ps->partial);++ npartial = 0;++ NEWN (occs, 2*ps->max_var + 1);+ CLRN (occs, 2*ps->max_var + 1);+ occs += ps->max_var;+ for (p = ps->soclauses; p < ps->sohead; p++)+ occs[*p]++;+ assert (occs[0] == ps->oadded);++ for (c = ps->soclauses; c < ps->sohead; c = p + 1)+ {+ best = 0;+ maxoccs = 0;+ for (p = c; (lit = *p); p++)+ {+ val = pderef (ps, lit);+ if (val > 0)+ break;+ if (val < 0)+ continue;+ val = int2lit (ps, lit)->val;+ assert (val);+ if (val < 0)+ continue;+ tmpoccs = occs[lit];+ if (best && tmpoccs <= maxoccs)+ continue;+ best = lit;+ maxoccs = tmpoccs;+ }+ if (!lit)+ {+ assert (best);+ LOG ( fprintf (ps->out, "%sautark %d with %d occs\n",+ ps->prefix, best, maxoccs));+ ps->vars[abs (best)].partial = 1;+ npartial++;+ }+ for (p = c; (lit = *p); p++)+ {+ assert (occs[lit] > 0);+ occs[lit]--;+ }+ }+ occs -= ps->max_var;+ DELETEN (occs, 2*ps->max_var + 1);+ ps->partial = 1;++ if (ps->verbosity)+ fprintf (ps->out,+ "%sautarky of size %u out of %u satisfying all clauses (%.1f%%)\n",+ ps->prefix, npartial, ps->max_var, PERCENT (npartial, ps->max_var));+}++void+picosat_assume (PS * ps, int int_lit)+{+ Lit *lit;++ if (ps->measurealltimeinlib)+ enter (ps);+ else+ check_ready (ps);++ if (ps->state != READY)+ reset_incremental_usage (ps);++ assume_contexts (ps);+ lit = import_lit (ps, int_lit, 1);+ assume (ps, lit);++ if (ps->measurealltimeinlib)+ leave (ps);+}++int+picosat_sat (PS * ps, int l)+{+ int res;+ char ch;++ enter (ps);++ ps->calls++;+ LOG ( fprintf (ps->out, "%sSTART call %u\n", ps->prefix, ps->calls));++ if (ps->added < ps->ahead)+ {+#ifndef NADC+ if (ps->addingtoado)+ ABORT ("API usage: incomplete all different constraint");+ else+#endif+ ABORT ("API usage: incomplete clause");+ }++ if (ps->state != READY)+ reset_incremental_usage (ps);++ assume_contexts (ps);++ res = sat (ps, l);++ assert (ps->state == READY);++ switch (res)+ {+ case PICOSAT_UNSATISFIABLE:+ ch = '0';+ ps->state = UNSAT;+ break;+ case PICOSAT_SATISFIABLE:+ ch = '1';+ ps->state = SAT;+ break;+ default:+ ch = '?';+ ps->state = UNKNOWN;+ break;+ }++ if (ps->verbosity)+ {+ report (ps, 1, ch);+ rheader (ps);+ }++ leave (ps);+ LOG ( fprintf (ps->out, "%sEND call %u result %d\n", ps->prefix, ps->calls, res));++ ps->last_sat_call_result = res;++ return res;+}++int+picosat_res (PS * ps)+{+ return ps->last_sat_call_result;+}++int+picosat_deref (PS * ps, int int_lit)+{+ Lit *lit;++ check_ready (ps);+ check_sat_state (ps);+ ABORTIF (!int_lit, "API usage: can not deref zero literal");+ ABORTIF (ps->mtcls, "API usage: deref after empty clause generated");++#ifdef STATS+ ps->derefs++;+#endif++ if (abs (int_lit) > (int) ps->max_var)+ return 0;++ lit = int2lit (ps, int_lit);++ if (lit->val == TRUE)+ return 1;++ if (lit->val == FALSE)+ return -1;++ return 0;+}++int+picosat_deref_toplevel (PS * ps, int int_lit)+{+ Lit *lit;+ Var * v;++ check_ready (ps);+ ABORTIF (!int_lit, "API usage: can not deref zero literal");++#ifdef STATS+ ps->derefs++;+#endif+ if (abs (int_lit) > (int) ps->max_var)+ return 0;++ lit = int2lit (ps, int_lit);++ v = LIT2VAR (lit);+ if (v->level > 0)+ return 0;++ if (lit->val == TRUE)+ return 1;++ if (lit->val == FALSE)+ return -1;++ return 0;+}++int+picosat_inconsistent (PS * ps)+{+ check_ready (ps);+ return ps->mtcls != 0;+}++int+picosat_corelit (PS * ps, int int_lit)+{+ check_ready (ps);+ check_unsat_state (ps);+ ABORTIF (!int_lit, "API usage: zero literal can not be in core");++ assert (ps->mtcls || ps->failed_assumption);++#ifdef TRACE+ {+ int res = 0;+ ABORTIF (!ps->trace, "tracing disabled");+ if (ps->measurealltimeinlib)+ enter (ps);+ core (ps);+ if (abs (int_lit) <= (int) ps->max_var)+ res = ps->vars[abs (int_lit)].core;+ assert (!res || ps->failed_assumption || ps->vars[abs (int_lit)].used);+ if (ps->measurealltimeinlib)+ leave (ps);+ return res;+ }+#else+ ABORT ("compiled without trace support");+ return 0;+#endif+}++int+picosat_coreclause (PS * ps, int ocls)+{+ check_ready (ps);+ check_unsat_state (ps);++ ABORTIF (ocls < 0, "API usage: negative original clause index");+ ABORTIF (ocls >= (int)ps->oadded, "API usage: original clause index exceeded");++ assert (ps->mtcls || ps->failed_assumption);++#ifdef TRACE+ {+ Cls ** clsptr, * c;+ int res = 0;++ ABORTIF (!ps->trace, "tracing disabled");+ if (ps->measurealltimeinlib)+ enter (ps);+ core (ps);+ clsptr = ps->oclauses + ocls;+ assert (clsptr < ps->ohead);+ c = *clsptr;+ if (c)+ res = c->core;+ if (ps->measurealltimeinlib)+ leave (ps);++ return res;+ }+#else+ ABORT ("compiled without trace support");+ return 0;+#endif+}++int+picosat_failed_assumption (PS * ps, int int_lit)+{+ Lit * lit;+ Var * v;+ ABORTIF (!int_lit, "API usage: zero literal as assumption");+ check_ready (ps);+ check_unsat_state (ps);+ if (ps->mtcls)+ return 0;+ assert (ps->failed_assumption);+ if (abs (int_lit) > (int) ps->max_var)+ return 0;+ if (!ps->extracted_all_failed_assumptions)+ extract_all_failed_assumptions (ps);+ lit = import_lit (ps, int_lit, 1);+ v = LIT2VAR (lit);+ return v->failed;+}++int+picosat_failed_context (PS * ps, int int_lit)+{+ Lit * lit;+ Var * v;+ ABORTIF (!int_lit, "API usage: zero literal as context");+ ABORTIF (abs (int_lit) > (int) ps->max_var, "API usage: invalid context");+ check_ready (ps);+ check_unsat_state (ps);+ assert (ps->failed_assumption);+ if (!ps->extracted_all_failed_assumptions)+ extract_all_failed_assumptions (ps);+ lit = import_lit (ps, int_lit, 0);+ v = LIT2VAR (lit);+ return v->failed;+}++const int *+picosat_failed_assumptions (PS * ps)+{+ Lit ** p, * lit;+ Var * v;+ int ilit;++ ps->falshead = ps->fals;+ check_ready (ps);+ check_unsat_state (ps);+ if (!ps->mtcls)+ {+ assert (ps->failed_assumption);+ if (!ps->extracted_all_failed_assumptions)+ extract_all_failed_assumptions (ps);++ for (p = ps->als; p < ps->alshead; p++)+ {+ lit = *p;+ v = LIT2VAR (*p);+ if (!v->failed)+ continue;+ ilit = LIT2INT (lit);+ if (ps->falshead == ps->eofals)+ ENLARGE (ps->fals, ps->falshead, ps->eofals);+ *ps->falshead++ = ilit;+ }+ }+ if (ps->falshead == ps->eofals)+ ENLARGE (ps->fals, ps->falshead, ps->eofals);+ *ps->falshead++ = 0;+ return ps->fals;+}++const int *+picosat_mus_assumptions (PS * ps, void * s, void (*cb)(void*,const int*), int fix)+{+ int i, j, ilit, len, norig = ps->alshead - ps->als, nwork, * work, res;+ signed char * redundant;+ Lit ** p, * lit;+ int failed;+ Var * v;+#ifndef NDEBUG+ int oldlen;+#endif++ check_ready (ps);+ check_unsat_state (ps);+ len = 0;+ if (!ps->mtcls)+ {+ assert (ps->failed_assumption);+ if (!ps->extracted_all_failed_assumptions)+ extract_all_failed_assumptions (ps);++ for (p = ps->als; p < ps->alshead; p++)+ if (LIT2VAR (*p)->failed)+ len++;+ }++ if (ps->mass)+ DELETEN (ps->mass, ps->szmass);+ ps->szmass = len + 1;+ NEWN (ps->mass, ps->szmass);++ i = 0;+ for (p = ps->als; p < ps->alshead; p++)+ {+ lit = *p;+ v = LIT2VAR (lit);+ if (!v->failed)+ continue;+ ilit = LIT2INT (lit);+ assert (i < len);+ ps->mass[i++] = ilit;+ }+ assert (i == len);+ ps->mass[i] = 0;+ if (ps->verbosity)+ fprintf (ps->out,+ "%sinitial set of failed assumptions of size %d out of %d (%.0f%%)\n",+ ps->prefix, len, norig, PERCENT (len, norig));+ if (cb)+ cb (s, ps->mass);++ nwork = len;+ NEWN (work, nwork);+ for (i = 0; i < len; i++)+ work[i] = ps->mass[i];++ NEWN (redundant, nwork);+ CLRN (redundant, nwork);++ for (i = 0; i < nwork; i++)+ {+ if (redundant[i])+ continue;++ if (ps->verbosity > 1)+ fprintf (ps->out,+ "%strying to drop %d%s assumption %d\n",+ ps->prefix, i, enumstr (i), work[i]);+ for (j = 0; j < nwork; j++)+ {+ if (i == j) continue;+ if (j < i && fix) continue;+ if (redundant[j]) continue;+ picosat_assume (ps, work[j]);+ }++ res = picosat_sat (ps, -1);+ if (res == 10)+ {+ if (ps->verbosity > 1)+ fprintf (ps->out,+ "%sfailed to drop %d%s assumption %d\n",+ ps->prefix, i, enumstr (i), work[i]);++ if (fix)+ {+ picosat_add (ps, work[i]);+ picosat_add (ps, 0);+ }+ }+ else+ {+ assert (res == 20);+ if (ps->verbosity > 1)+ fprintf (ps->out,+ "%ssuceeded to drop %d%s assumption %d\n",+ ps->prefix, i, enumstr (i), work[i]);+ redundant[i] = 1;+ for (j = 0; j < nwork; j++)+ {+ failed = picosat_failed_assumption (ps, work[j]);+ if (j <= i)+ {+ assert ((j < i && fix) || redundant[j] == !failed);+ continue;+ }++ if (!failed)+ {+ redundant[j] = -1;+ if (ps->verbosity > 1)+ fprintf (ps->out,+ "%salso suceeded to drop %d%s assumption %d\n",+ ps->prefix, j, enumstr (j), work[j]);+ }+ }++#ifndef NDEBUG+ oldlen = len;+#endif+ len = 0;+ for (j = 0; j < nwork; j++)+ if (!redundant[j])+ ps->mass[len++] = work[j];+ ps->mass[len] = 0;+ assert (len < oldlen);++ if (fix)+ {+ picosat_add (ps, -work[i]);+ picosat_add (ps, 0);+ }++#ifndef NDEBUG+ for (j = 0; j <= i; j++)+ assert (redundant[j] >= 0);+#endif+ for (j = i + 1; j < nwork; j++)+ {+ if (redundant[j] >= 0)+ continue;++ if (fix)+ {+ picosat_add (ps, -work[j]);+ picosat_add (ps, 0);+ }++ redundant[j] = 1;+ }++ if (ps->verbosity)+ fprintf (ps->out,+ "%sreduced set of failed assumptions of size %d out of %d (%.0f%%)\n",+ ps->prefix, len, norig, PERCENT (len, norig));+ if (cb)+ cb (s, ps->mass);+ }+ }++ DELETEN (work, nwork);+ DELETEN (redundant, nwork);++ if (ps->verbosity)+ {+ fprintf (ps->out, "%sreinitializing unsat state\n", ps->prefix);+ fflush (ps->out);+ }++ for (i = 0; i < len; i++)+ picosat_assume (ps, ps->mass[i]);++#ifndef NDEBUG+ res =+#endif+ picosat_sat (ps, -1);+ assert (res == 20);++ if (!ps->mtcls)+ {+ assert (!ps->extracted_all_failed_assumptions);+ extract_all_failed_assumptions (ps);+ }++ return ps->mass;+}++static const int *+mss (PS * ps, int * a, int size)+{+ int i, j, k, res;++ assert (!ps->mtcls);++ if (ps->szmssass)+ DELETEN (ps->mssass, ps->szmssass);++ ps->szmssass = 0;+ ps->mssass = 0;++ ps->szmssass = size + 1;+ NEWN (ps->mssass, ps->szmssass);++ LOG ( fprintf (ps->out, "%ssearch MSS over %d assumptions\n", ps->prefix, size));++ k = 0;+ for (i = k; i < size; i++)+ {+ for (j = 0; j < k; j++)+ picosat_assume (ps, ps->mssass[j]);++ LOG ( fprintf (ps->out,+ "%strying to add assumption %d to MSS : %d\n",+ ps->prefix, i, a[i]));++ picosat_assume (ps, a[i]);++ res = picosat_sat (ps, -1);+ if (res == 10)+ {+ LOG ( fprintf (ps->out,+ "%sadding assumption %d to MSS : %d\n", ps->prefix, i, a[i]));++ ps->mssass[k++] = a[i];++ for (j = i + 1; j < size; j++)+ {+ if (picosat_deref (ps, a[j]) <= 0)+ continue;++ LOG ( fprintf (ps->out,+ "%salso adding assumption %d to MSS : %d\n",+ ps->prefix, j, a[j]));++ ps->mssass[k++] = a[j];++ if (++i != j)+ {+ int tmp = a[i];+ a[i] = a[j];+ a[j] = tmp;+ }+ }+ }+ else+ {+ assert (res == 20);++ LOG ( fprintf (ps->out,+ "%signoring assumption %d in MSS : %d\n", ps->prefix, i, a[i]));+ }+ }+ ps->mssass[k] = 0;+ LOG ( fprintf (ps->out, "%sfound MSS of size %d\n", ps->prefix, k));++ return ps->mssass;+}++static void+reassume (PS * ps, const int * a, int size)+{+ int i;+ LOG ( fprintf (ps->out, "%sreassuming all assumptions\n", ps->prefix));+ for (i = 0; i < size; i++)+ picosat_assume (ps, a[i]);+}++const int *+picosat_maximal_satisfiable_subset_of_assumptions (PS * ps)+{+ const int * res;+ int i, *a, size;++ ABORTIF (ps->mtcls,+ "API usage: CNF inconsistent (use 'picosat_inconsistent')");++ enter (ps);++ size = ps->alshead - ps->als;+ NEWN (a, size);++ for (i = 0; i < size; i++)+ a[i] = LIT2INT (ps->als[i]);++ res = mss (ps, a, size);+ reassume (ps, a, size);++ DELETEN (a, size);++ leave (ps);++ return res;+}++static void+check_mss_flags_clean (PS * ps)+{+#ifndef NDEBUG+ unsigned i;+ for (i = 1; i <= ps->max_var; i++)+ {+ assert (!ps->vars[i].msspos);+ assert (!ps->vars[i].mssneg);+ }+#else+ (void) ps;+#endif+}++static void+push_mcsass (PS * ps, int lit)+{+ if (ps->nmcsass == ps->szmcsass)+ {+ ps->szmcsass = ps->szmcsass ? 2*ps->szmcsass : 1;+ RESIZEN (ps->mcsass, ps->nmcsass, ps->szmcsass);+ }++ ps->mcsass[ps->nmcsass++] = lit;+}++static const int *+next_mss (PS * ps, int mcs)+{+ int i, *a, size, mssize, mcsize, lit, inmss;+ const int * res, * p;+ Var * v;++ if (ps->mtcls) return 0;++ check_mss_flags_clean (ps);++ if (mcs && ps->mcsass)+ {+ DELETEN (ps->mcsass, ps->szmcsass);+ ps->nmcsass = ps->szmcsass = 0;+ ps->mcsass = 0;+ }++ size = ps->alshead - ps->als;+ NEWN (a, size);++ for (i = 0; i < size; i++)+ a[i] = LIT2INT (ps->als[i]);++ (void) picosat_sat (ps, -1);++ //TODO short cut for 'picosat_res () == 10'?++ if (ps->mtcls)+ {+ assert (picosat_res (ps) == 20);+ res = 0;+ goto DONE;+ }++ res = mss (ps, a, size);++ if (ps->mtcls)+ {+ res = 0;+ goto DONE;+ }++ for (p = res; (lit = *p); p++)+ {+ v = ps->vars + abs (lit);+ if (lit < 0)+ {+ assert (!v->msspos);+ v->mssneg = 1;+ }+ else+ {+ assert (!v->mssneg);+ v->msspos = 1;+ }+ }++ mssize = p - res;+ mcsize = INT_MIN;++ for (i = 0; i < size; i++)+ {+ lit = a[i];+ v = ps->vars + abs (lit);+ if (lit > 0 && v->msspos)+ inmss = 1;+ else if (lit < 0 && v->mssneg)+ inmss = 1;+ else+ inmss = 0;++ if (mssize < mcsize)+ {+ if (inmss)+ picosat_add (ps, -lit);+ }+ else+ {+ if (!inmss)+ picosat_add (ps, lit);+ }++ if (!inmss && mcs)+ push_mcsass (ps, lit);+ }+ picosat_add (ps, 0);+ if (mcs)+ push_mcsass (ps, 0);++ for (i = 0; i < size; i++)+ {+ lit = a[i];+ v = ps->vars + abs (lit);+ v->msspos = 0;+ v->mssneg = 0;+ }++DONE:++ reassume (ps, a, size);+ DELETEN (a, size);++ return res;+}++const int *+picosat_next_maximal_satisfiable_subset_of_assumptions (PS * ps)+{+ const int * res;+ enter (ps);+ res = next_mss (ps, 0);+ leave (ps);+ return res;+}++const int *+picosat_next_minimal_correcting_subset_of_assumptions (PS * ps)+{+ const int * res, * tmp;+ enter (ps);+ tmp = next_mss (ps, 1);+ res = tmp ? ps->mcsass : 0;+ leave (ps);+ return res;+}++const int *+picosat_humus (PS * ps,+ void (*callback)(void*state,int nmcs,int nhumus),+ void * state)+{+ int lit, nmcs, j, nhumus;+ const int * mcs, * p;+ unsigned i;+ Var * v;+ enter (ps);+#ifndef NDEBUG+ for (i = 1; i <= ps->max_var; i++)+ {+ v = ps->vars + i;+ assert (!v->humuspos);+ assert (!v->humusneg);+ }+#endif+ nhumus = nmcs = 0;+ while ((mcs = picosat_next_minimal_correcting_subset_of_assumptions (ps)))+ {+ for (p = mcs; (lit = *p); p++)+ {+ v = ps->vars + abs (lit);+ if (lit < 0)+ {+ if (!v->humusneg)+ {+ v->humusneg = 1;+ nhumus++;+ }+ }+ else+ {+ if (!v->humuspos)+ {+ v->humuspos = 1;+ nhumus++;+ }+ }+ }+ nmcs++;+ LOG ( fprintf (ps->out,+ "%smcs %d of size %d humus %d\n",+ ps->prefix, nmcs, (int)(p - mcs), nhumus));+ if (callback)+ callback (state, nmcs, nhumus);+ }+ assert (!ps->szhumus);+ ps->szhumus = 1;+ for (i = 1; i <= ps->max_var; i++)+ {+ v = ps->vars + i;+ if (v->humuspos)+ ps->szhumus++;+ if (v->humusneg)+ ps->szhumus++;+ }+ assert (nhumus + 1 == ps->szhumus);+ NEWN (ps->humus, ps->szhumus);+ j = 0;+ for (i = 1; i <= ps->max_var; i++)+ {+ v = ps->vars + i;+ if (v->humuspos)+ {+ assert (j < nhumus);+ ps->humus[j++] = (int) i;+ }+ if (v->humusneg)+ {+ assert (j < nhumus);+ assert (i < INT_MAX);+ ps->humus[j++] = - (int) i;+ }+ }+ assert (j == nhumus);+ assert (j < ps->szhumus);+ ps->humus[j] = 0;+ leave (ps);+ return ps->humus;+}++int+picosat_usedlit (PS * ps, int int_lit)+{+ int res;+ check_ready (ps);+ check_sat_or_unsat_or_unknown_state (ps);+ ABORTIF (!int_lit, "API usage: zero literal can not be used");+ int_lit = abs (int_lit);+ res = (int_lit <= (int) ps->max_var) ? ps->vars[int_lit].used : 0;+ return res;+}++void+picosat_write_clausal_core (PS * ps, FILE * file)+{+ check_trace_support_and_execute (ps, file, write_core_wrapper, 0);+}++void+picosat_write_compact_trace (PS * ps, FILE * file)+{+ check_trace_support_and_execute (ps, file, write_trace,+ COMPACT_TRACECHECK_TRACE_FMT);+}++void+picosat_write_extended_trace (PS * ps, FILE * file)+{+ check_trace_support_and_execute (ps, file, write_trace,+ EXTENDED_TRACECHECK_TRACE_FMT);+}++void+picosat_write_rup_trace (PS * ps, FILE * file)+{+ check_trace_support_and_execute (ps, file, write_trace, RUP_TRACE_FMT);+}++size_t+picosat_max_bytes_allocated (PS * ps)+{+ check_ready (ps);+ return ps->max_bytes;+}++void+picosat_set_propagation_limit (PS * ps, unsigned long long l)+{+ ps->lpropagations = l;+}++unsigned long long+picosat_propagations (PS * ps)+{+ return ps->propagations;+}++unsigned long long+picosat_visits (PS * ps)+{+ return ps->visits;+}++unsigned long long+picosat_decisions (PS * ps)+{+ return ps->decisions;+}++int+picosat_variables (PS * ps)+{+ check_ready (ps);+ return (int) ps->max_var;+}++int+picosat_added_original_clauses (PS * ps)+{+ check_ready (ps);+ return (int) ps->oadded;+}++void+picosat_stats (PS * ps)+{+ unsigned redlits;+#ifdef STATS+ check_ready (ps);+ assert (ps->sdecisions + ps->rdecisions + ps->assumptions == ps->decisions);+#endif+ if (ps->calls > 1)+ fprintf (ps->out, "%s%u calls\n", ps->prefix, ps->calls);+ if (ps->contexts)+ {+ fprintf (ps->out, "%s%u contexts", ps->prefix, ps->contexts);+#ifdef STATS+ fprintf (ps->out, " %u internal variables", ps->internals);+#endif+ fprintf (ps->out, "\n");+ }+ fprintf (ps->out, "%s%u iterations\n", ps->prefix, ps->iterations);+ fprintf (ps->out, "%s%u restarts", ps->prefix, ps->restarts);+#ifdef STATS+ fprintf (ps->out, " (%u skipped)", ps->skippedrestarts);+#endif+ fputc ('\n', ps->out);+#ifndef NFL+ fprintf (ps->out, "%s%u failed literals", ps->prefix, ps->failedlits);+#ifdef STATS+ fprintf (ps->out,+ ", %u calls, %u rounds, %llu propagations",+ ps->flcalls, ps->flrounds, ps->flprops);+#endif+ fputc ('\n', ps->out);+#ifdef STATS+ fprintf (ps->out,+ "%sfl: %u = %.1f%% implicit, %llu oopsed, %llu tried, %llu skipped\n",+ ps->prefix,+ ps->ifailedlits, PERCENT (ps->ifailedlits, ps->failedlits),+ ps->floopsed, ps->fltried, ps->flskipped);+#endif+#endif+ fprintf (ps->out, "%s%u conflicts", ps->prefix, ps->conflicts);+#ifdef STATS+ fprintf (ps->out, " (%u uips = %.1f%%)\n", ps->uips, PERCENT(ps->uips,ps->conflicts));+#else+ fputc ('\n', ps->out);+#endif+#ifndef NADC+ fprintf (ps->out, "%s%u adc conflicts\n", ps->prefix, ps->adoconflicts);+#endif+#ifdef STATS+ fprintf (ps->out, "%s%llu dereferenced literals\n", ps->prefix, ps->derefs);+#endif+ fprintf (ps->out, "%s%u decisions", ps->prefix, ps->decisions);+#ifdef STATS+ fprintf (ps->out, " (%u random = %.2f%%",+ ps->rdecisions, PERCENT (ps->rdecisions, ps->decisions));+ fprintf (ps->out, ", %u assumptions", ps->assumptions);+ fputc (')', ps->out);+#endif+ fputc ('\n', ps->out);+#ifdef STATS+ fprintf (ps->out,+ "%s%u static phase decisions (%.1f%% of all variables)\n",+ ps->prefix,+ ps->staticphasedecisions, PERCENT (ps->staticphasedecisions, ps->max_var));+#endif+ fprintf (ps->out, "%s%u fixed variables\n", ps->prefix, ps->fixed);+ assert (ps->nonminimizedllits >= ps->minimizedllits);+ redlits = ps->nonminimizedllits - ps->minimizedllits;+ fprintf (ps->out, "%s%u learned literals\n", ps->prefix, ps->llitsadded);+ fprintf (ps->out, "%s%.1f%% deleted literals\n",+ ps->prefix, PERCENT (redlits, ps->nonminimizedllits));++#ifdef STATS+#ifndef NO_BINARY_CLAUSES+ fprintf (ps->out,+ "%s%llu antecedents (%.1f antecedents per clause",+ ps->prefix, ps->antecedents, AVERAGE (ps->antecedents, ps->conflicts));+#endif+#ifdef TRACE+ if (ps->trace)+ fprintf (ps->out, ", %.1f bytes/antecedent)", AVERAGE (ps->znts, ps->antecedents));+#endif+#if !defined(NO_BINARY_CLAUSES) || defined(TRACE)+ fputs (")\n", ps->out);+#endif++ fprintf (ps->out, "%s%llu propagations (%.1f propagations per decision)\n",+ ps->prefix, ps->propagations, AVERAGE (ps->propagations, ps->decisions));+ fprintf (ps->out, "%s%llu visits (%.1f per propagation)\n",+ ps->prefix, ps->visits, AVERAGE (ps->visits, ps->propagations));+ fprintf (ps->out,+ "%s%llu binary clauses visited (%.1f%% %.1f per propagation)\n",+ ps->prefix, ps->bvisits,+ PERCENT (ps->bvisits, ps->visits),+ AVERAGE (ps->bvisits, ps->propagations));+ fprintf (ps->out,+ "%s%llu ternary clauses visited (%.1f%% %.1f per propagation)\n",+ ps->prefix, ps->tvisits,+ PERCENT (ps->tvisits, ps->visits),+ AVERAGE (ps->tvisits, ps->propagations));+ fprintf (ps->out,+ "%s%llu large clauses visited (%.1f%% %.1f per propagation)\n",+ ps->prefix, ps->lvisits,+ PERCENT (ps->lvisits, ps->visits),+ AVERAGE (ps->lvisits, ps->propagations));+ fprintf (ps->out, "%s%llu other true (%.1f%% of visited clauses)\n",+ ps->prefix, ps->othertrue, PERCENT (ps->othertrue, ps->visits));+ fprintf (ps->out,+ "%s%llu other true in binary clauses (%.1f%%)"+ ", %llu upper (%.1f%%)\n",+ ps->prefix, ps->othertrue2, PERCENT (ps->othertrue2, ps->othertrue),+ ps->othertrue2u, PERCENT (ps->othertrue2u, ps->othertrue2));+ fprintf (ps->out,+ "%s%llu other true in large clauses (%.1f%%)"+ ", %llu upper (%.1f%%)\n",+ ps->prefix, ps->othertruel, PERCENT (ps->othertruel, ps->othertrue),+ ps->othertruelu, PERCENT (ps->othertruelu, ps->othertruel));+ fprintf (ps->out, "%s%llu ternary and large traversals (%.1f per visit)\n",+ ps->prefix, ps->traversals, AVERAGE (ps->traversals, ps->visits));+ fprintf (ps->out, "%s%llu large traversals (%.1f per large visit)\n",+ ps->prefix, ps->ltraversals, AVERAGE (ps->ltraversals, ps->lvisits));+ fprintf (ps->out, "%s%llu assignments\n", ps->prefix, ps->assignments);+#else+ fprintf (ps->out, "%s%llu propagations\n", ps->prefix, picosat_propagations (ps));+ fprintf (ps->out, "%s%llu visits\n", ps->prefix, picosat_visits (ps));+#endif+ fprintf (ps->out, "%s%.1f%% variables used\n", ps->prefix, PERCENT (ps->vused, ps->max_var));++ sflush (ps);+ fprintf (ps->out, "%s%.1f seconds in library\n", ps->prefix, ps->seconds);+ fprintf (ps->out, "%s%.1f megaprops/second\n",+ ps->prefix, AVERAGE (ps->propagations / 1e6f, ps->seconds));+ fprintf (ps->out, "%s%.1f megavisits/second\n",+ ps->prefix, AVERAGE (ps->visits / 1e6f, ps->seconds));+ fprintf (ps->out, "%sprobing %.1f seconds %.0f%%\n",+ ps->prefix, ps->flseconds, PERCENT (ps->flseconds, ps->seconds));+#ifdef STATS+ fprintf (ps->out,+ "%srecycled %.1f MB in %u reductions\n",+ ps->prefix, ps->rrecycled / (double) (1 << 20), ps->reductions);+ fprintf (ps->out,+ "%srecycled %.1f MB in %u simplifications\n",+ ps->prefix, ps->srecycled / (double) (1 << 20), ps->simps);+#else+ fprintf (ps->out, "%s%u simplifications\n", ps->prefix, ps->simps);+ fprintf (ps->out, "%s%u reductions\n", ps->prefix, ps->reductions);+ fprintf (ps->out, "%s%.1f MB recycled\n", ps->prefix, ps->recycled / (double) (1 << 20));+#endif+ fprintf (ps->out, "%s%.1f MB maximally allocated\n",+ ps->prefix, picosat_max_bytes_allocated (ps) / (double) (1 << 20));+}++#ifndef NGETRUSAGE+#include <sys/time.h>+#include <sys/resource.h>+#include <sys/unistd.h>+#endif++double+picosat_time_stamp (void)+{+ double res = -1;+#ifndef NGETRUSAGE+ struct rusage u;+ res = 0;+ if (!getrusage (RUSAGE_SELF, &u))+ {+ res += u.ru_utime.tv_sec + 1e-6 * u.ru_utime.tv_usec;+ res += u.ru_stime.tv_sec + 1e-6 * u.ru_stime.tv_usec;+ }+#endif+ return res;+}++double+picosat_seconds (PS * ps)+{+ check_ready (ps);+ return ps->seconds;+}++void+picosat_print (PS * ps, FILE * file)+{+#ifdef NO_BINARY_CLAUSES+ Lit * lit, *other, * last;+ Ltk * stack;+#endif+ Lit **q, **eol;+ Cls **p, *c;+ unsigned n;++ if (ps->measurealltimeinlib)+ enter (ps);+ else+ check_ready (ps);++ n = 0;+ n += ps->alshead - ps->als;++ for (p = SOC; p != EOC; p = NXC (p))+ {+ c = *p;++ if (!c)+ continue;++#ifdef TRACE+ if (c->collected)+ continue;+#endif+ n++;+ }++#ifdef NO_BINARY_CLAUSES+ last = int2lit (ps, -ps->max_var);+ for (lit = int2lit (ps, 1); lit <= last; lit++)+ {+ stack = LIT2IMPLS (lit);+ eol = stack->start + stack->count;+ for (q = stack->start; q < eol; q++)+ if (*q >= lit)+ n++;+ }+#endif++ fprintf (file, "p cnf %d %u\n", ps->max_var, n);++ for (p = SOC; p != EOC; p = NXC (p))+ {+ c = *p;+ if (!c)+ continue;++#ifdef TRACE+ if (c->collected)+ continue;+#endif++ eol = end_of_lits (c);+ for (q = c->lits; q < eol; q++)+ fprintf (file, "%d ", LIT2INT (*q));++ fputs ("0\n", file);+ }++#ifdef NO_BINARY_CLAUSES+ last = int2lit (ps, -ps->max_var);+ for (lit = int2lit (ps, 1); lit <= last; lit++)+ {+ stack = LIT2IMPLS (lit);+ eol = stack->start + stack->count;+ for (q = stack->start; q < eol; q++)+ if ((other = *q) >= lit)+ fprintf (file, "%d %d 0\n", LIT2INT (lit), LIT2INT (other));+ }+#endif++ {+ Lit **r;+ for (r = ps->als; r < ps->alshead; r++)+ fprintf (file, "%d 0\n", LIT2INT (*r));+ }++ fflush (file);++ if (ps->measurealltimeinlib)+ leave (ps);+}++void+picosat_enter (PS * ps)+{+ enter (ps);+}++void+picosat_leave (PS * ps)+{+ leave (ps);+}++void+picosat_message (PS * ps, int vlevel, const char * fmt, ...)+{+ va_list ap;++ if (vlevel > ps->verbosity)+ return;++ fputs (ps->prefix, ps->out);+ va_start (ap, fmt);+ vfprintf (ps->out, fmt, ap);+ va_end (ap);+ fputc ('\n', ps->out);+}++int+picosat_changed (PS * ps)+{+ int res;++ check_ready (ps);+ check_sat_state (ps);++ res = (ps->min_flipped <= ps->saved_max_var);+ assert (!res || ps->saved_flips != ps->flips);++ return res;+}++void+picosat_reset_phases (PS * ps)+{+ rebias (ps);+}++void+picosat_reset_scores (PS * ps)+{+ Rnk * r;+ ps->hhead = ps->heap + 1;+ for (r = ps->rnks + 1; r <= ps->rnks + ps->max_var; r++)+ {+ CLR (r);+ hpush (ps, r);+ }+}++void+picosat_remove_learned (PS * ps, unsigned percentage)+{+ enter (ps);+ reset_incremental_usage (ps);+ reduce (ps, percentage);+ leave (ps);+}++void+picosat_set_global_default_phase (PS * ps, int phase)+{+ check_ready (ps);+ ABORTIF (phase < 0, "API usage: 'picosat_set_global_default_phase' "+ "with negative argument");+ ABORTIF (phase > 3, "API usage: 'picosat_set_global_default_phase' "+ "with argument > 3");+ ps->defaultphase = phase;+}++void+picosat_set_default_phase_lit (PS * ps, int int_lit, int phase)+{+ unsigned newphase;+ Lit * lit;+ Var * v;++ check_ready (ps);++ lit = import_lit (ps, int_lit, 1);+ v = LIT2VAR (lit);++ if (phase)+ {+ newphase = (int_lit < 0) == (phase < 0);+ v->defphase = v->phase = newphase;+ v->usedefphase = v->assigned = 1;+ }+ else+ {+ v->usedefphase = v->assigned = 0;+ }+}++void+picosat_set_more_important_lit (PS * ps, int int_lit)+{+ Lit * lit;+ Var * v;+ Rnk * r;++ check_ready (ps);++ lit = import_lit (ps, int_lit, 1);+ v = LIT2VAR (lit);+ r = VAR2RNK (v);++ ABORTIF (r->lessimportant, "can not mark variable more and less important");++ if (r->moreimportant)+ return;++ r->moreimportant = 1;++ if (r->pos)+ hup (ps, r);+}++void+picosat_set_less_important_lit (PS * ps, int int_lit)+{+ Lit * lit;+ Var * v;+ Rnk * r;++ check_ready (ps);++ lit = import_lit (ps, int_lit, 1);+ v = LIT2VAR (lit);+ r = VAR2RNK (v);++ ABORTIF (r->moreimportant, "can not mark variable more and less important");++ if (r->lessimportant)+ return;++ r->lessimportant = 1;++ if (r->pos)+ hdown (ps, r);+}++#ifndef NADC++unsigned+picosat_ado_conflicts (PS * ps)+{+ check_ready (ps);+ return ps->adoconflicts;+}++void+picosat_disable_ado (PS * ps)+{+ check_ready (ps);+ assert (!ps->adodisabled);+ ps->adodisabled = 1;+}++void+picosat_enable_ado (PS * ps)+{+ check_ready (ps);+ assert (ps->adodisabled);+ ps->adodisabled = 0;+}++void+picosat_set_ado_conflict_limit (unsigned newadoconflictlimit)+{+ check_ready (ps);+ ps->adoconflictlimit = newadoconflictlimit;+}++#endif++void+picosat_simplify (PS * ps)+{+ enter (ps);+ reset_incremental_usage (ps);+ simplify (ps, 1);+ leave (ps);+}++int+picosat_haveados (void)+{+#ifndef NADC+ return 1;+#else+ return 0;+#endif+}++void+picosat_save_original_clauses (PS * ps)+{+ if (ps->saveorig) return;+ ABORTIF (ps->oadded, "API usage: 'picosat_save_original_clauses' too late");+ ps->saveorig = 1;+}++int+picosat_deref_partial (PS * ps, int int_lit)+{+ check_ready (ps);+ check_sat_state (ps);+ ABORTIF (!int_lit, "API usage: can not partial deref zero literal");+ ABORTIF (ps->mtcls, "API usage: deref partial after empty clause generated");+ ABORTIF (!ps->saveorig, "API usage: 'picosat_save_original_clauses' missing");++#ifdef STATS+ ps->derefs++;+#endif++ if (!ps->partial)+ minautarky (ps);++ return pderef (ps, int_lit);+}
+ cbits/picosat.h view
@@ -0,0 +1,644 @@+/****************************************************************************+Copyright (c) 2006 - 2012, Armin Biere, Johannes Kepler University.++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 picosat_h_INCLUDED+#define picosat_h_INCLUDED++/*------------------------------------------------------------------------*/++#include <stdlib.h>+#include <stdio.h>++/*------------------------------------------------------------------------*/+/* The following macros allows for users to distiguish between different+ * versions of the API. The first 'PICOSAT_REENTRANT_API' is defined for+ * the new reentrant API which allows to generate multiple instances of+ * PicoSAT in one process. The second 'PICOSAT_API_VERSION' defines the+ * (smallest) version of PicoSAT to which this API conforms.+ */+#define PICOSAT_REENTRANT_API+#define PICOSAT_API_VERSION 953 /* API version */++/*------------------------------------------------------------------------*/+/* These are the return values for 'picosat_sat' as for instance+ * standardized by the output format of the SAT competition.+ */+#define PICOSAT_UNKNOWN 0+#define PICOSAT_SATISFIABLE 10+#define PICOSAT_UNSATISFIABLE 20++/*------------------------------------------------------------------------*/++typedef struct PicoSAT PicoSAT;++/*------------------------------------------------------------------------*/++const char *picosat_version (void);+const char *picosat_config (void);+const char *picosat_copyright (void);++/*------------------------------------------------------------------------*/+/* You can make picosat use an external memory manager instead of the one+ * provided by LIBC. But then you need to call these three function before+ * 'picosat_init'. The memory manager functions here all have an additional+ * first argument which is a pointer to the memory manager, but otherwise+ * are supposed to work as their LIBC counter parts 'malloc', 'realloc' and+ * 'free'. As exception the 'resize' and 'delete' function have as third+ * argument the number of bytes of the block given as second argument.+ */++typedef void * (*picosat_malloc)(void *, size_t);+typedef void * (*picosat_realloc)(void*, void *, size_t, size_t);+typedef void (*picosat_free)(void*, void*, size_t);++/*------------------------------------------------------------------------*/++PicoSAT * picosat_init (void); /* constructor */++PicoSAT * picosat_minit (void * state,+ picosat_malloc,+ picosat_realloc,+ picosat_free);++void picosat_reset (PicoSAT *); /* destructor */++/*------------------------------------------------------------------------*/+/* The following five functions are essentially parameters to 'init', and+ * thus should be called right after 'picosat_init' before doing anything+ * else. You should not call any of them after adding a literal.+ */++/* Set output file, default is 'stdout'.+ */+void picosat_set_output (PicoSAT *, FILE *);++/* Measure all time spent in all calls in the solver. By default only the+ * time spent in 'picosat_sat' is measured. Enabling this function may for+ * instance triple the time needed to add large CNFs, since every call to+ * 'picosat_add' will trigger a call to 'getrusage'.+ */+void picosat_measure_all_calls (PicoSAT *);++/* Set the prefix used for printing verbose messages and statistics.+ * Default is "c ".+ */+void picosat_set_prefix (PicoSAT *, const char *);++/* Set verbosity level. A verbosity level of 1 and above prints more and+ * more detailed progress reports on the output file, set by+ * 'picosat_set_output'. Verbose messages are prefixed with the string set+ * by 'picosat_set_prefix'.+ */+void picosat_set_verbosity (PicoSAT *, int new_verbosity_level);++/* Disable/Enable all pre-processing, currently only failed literal probing.+ *+ * new_plain_value != 0 only 'plain' solving, so no preprocessing+ * new_plain_value == 0 allow preprocessing+ */+void picosat_set_plain (PicoSAT *, int new_plain_value);++/* Set default initial phase: + *+ * 0 = false+ * 1 = true+ * 2 = Jeroslow-Wang (default)+ * 3 = random initial phase+ *+ * After a variable has been assigned the first time, it will always+ * be assigned the previous value if it is picked as decision variable.+ * The initial assignment can be chosen with this function.+ */+void picosat_set_global_default_phase (PicoSAT *, int);++/* Set next/initial phase of a particular variable if picked as decision+ * variable. Second argument 'phase' has the following meaning:+ *+ * negative = next value if picked as decision variable is false+ *+ * positive = next value if picked as decision variable is true+ *+ * 0 = use global default phase as next value and+ * assume 'lit' was never assigned+ *+ * Again if 'lit' is assigned afterwards through a forced assignment,+ * then this forced assignment is the next phase if this variable is+ * used as decision variable.+ */+void picosat_set_default_phase_lit (PicoSAT *, int lit, int phase);++/* You can reset all phases by the following function.+ */+void picosat_reset_phases (PicoSAT *);++/* Scores can be erased as well. Note, however, that even after erasing + * scores and phases, learned clauses are kept. In addition head tail+ * pointers for literals are not moved either. So expect a difference+ * between calling the solver in incremental mode or with a fresh copy of+ * the CNF.+ */+void picosat_reset_scores (PicoSAT *);++/* Reset assignment if in SAT state and then remove the given percentage of+ * less active (large) learned clauses. If you specify 100% all large+ * learned clauses are removed.+ */+void picosat_remove_learned (PicoSAT *, unsigned percentage);++/* Set some variables to be more important than others. These variables are+ * always used as decisions before other variables are used. Dually there+ * is a set of variables that is used last. The default is+ * to mark all variables as being indifferent only.+ */+void picosat_set_more_important_lit (PicoSAT *, int lit);+void picosat_set_less_important_lit (PicoSAT *, int lit);++/* Allows to print to internal 'out' file from client.+ */+void picosat_message (PicoSAT *, int verbosity_level, const char * fmt, ...);++/* Set a seed for the random number generator. The random number generator+ * is currently just used for generating random decisions. In our+ * experiments having random decisions did not really help on industrial+ * examples, but was rather helpful to randomize the solver in order to+ * do proper benchmarking of different internal parameter sets.+ */+void picosat_set_seed (PicoSAT *, unsigned random_number_generator_seed);++/* If you ever want to extract cores or proof traces with the current+ * instance of PicoSAT initialized with 'picosat_init', then make sure to+ * call 'picosat_enable_trace_generation' right after 'picosat_init'. This+ * is not necessary if you only use 'picosat_set_incremental_rup_file'.+ *+ * NOTE, trace generation code is not necessarily included, e.g. if you+ * configure picosat with full optimzation as './configure -O' or with+ + * you do not get any results by trying to generate traces.+ *+ * The return value is non-zero if code for generating traces is included+ * and it is zero if traces can not be generated.+ */+int picosat_enable_trace_generation (PicoSAT *);++/* You can dump proof traces in RUP format incrementally even without+ * keeping the proof trace in memory. The advantage is a reduction of+ * memory usage, but the dumped clauses do not necessarily belong to the+ * clausal core. Beside the file the additional parameters denotes the+ * maximal number of variables and the number of original clauses.+ */+void picosat_set_incremental_rup_file (PicoSAT *, FILE * file, int m, int n);++/* Save original clauses for 'picosat_deref_partial'. See comments to that+ * function further down.+ */+void picosat_save_original_clauses (PicoSAT *);++/*------------------------------------------------------------------------*/+/* This function returns the next available unused variable index and+ * allocates a variable for it even though this variable does not occur as+ * assumption, nor in a clause or any other constraints. In future calls to+ * 'picosat_sat', 'picosat_deref' and particularly for 'picosat_changed',+ * this variable is treated as if it had been used.+ */+int picosat_inc_max_var (PicoSAT *);++/*------------------------------------------------------------------------*/+/* Push/pop semantics for PicoSAT. 'picosat_push' opens up a new context.+ * All clauses added in this context are attached to it and discared when+ * the context is closed with 'picosat_pop'. It is also possible to+ * nest contexts.+ *+ * The current implementation uses a new internal variable for each context.+ * However, the indices for these internal variables are shared with+ * ordinary external variables. This means that after any call to+ * 'picosat_push', new variable indices should be obtained with+ * 'picosat_inc_max_var' and not just by incrementing the largest variable+ * index used so far.+ *+ * The return value is the index of the literal that assumes this context.+ * This literal can only be used for 'picosat_failed_context' otherwise+ * it will lead to an API usage error.+ */+int picosat_push (PicoSAT *);++/* This is as 'picosat_failed_assumption', but only for internal variables+ * generated by 'picosat_push'.+ */+int picosat_failed_context (PicoSAT *, int lit);++/* Returns the literal that assumes the current context or zero if the+ * outer context has been reached.+ */+int picosat_context (PicoSAT *); ++/* Closes the current context and recycles the literal generated for+ * assuming this context. The return value is the literal for the new+ * outer context or zero if the outer most context has been reached.+ */+int picosat_pop (PicoSAT *);++/* Force immmediate removal of all satisfied clauses and clauses that are+ * added or generated in closed contexts. This function is called+ * internally if enough units are learned or after a certain number of+ * contexts have been closed. This number is fixed at compile time+ * and defined as MAXCILS in 'picosat.c'.+ *+ * Note that learned clauses which only involve outer contexts are kept.+ */+void picosat_simplify (PicoSAT *);++/*------------------------------------------------------------------------*/+/* If you know a good estimate on how many variables you are going to use+ * then calling this function before adding literals will result in less+ * resizing of the variable table. But this is just a minor optimization.+ * Beside exactly allocating enough variables it has the same effect as+ * calling 'picosat_inc_max_var'.+ */+void picosat_adjust (PicoSAT *, int max_idx);++/*------------------------------------------------------------------------*/+/* Statistics.+ */+int picosat_variables (PicoSAT *); /* p cnf <m> n */+int picosat_added_original_clauses (PicoSAT *); /* p cnf m <n> */+size_t picosat_max_bytes_allocated (PicoSAT *);+double picosat_time_stamp (void); /* ... in process */+void picosat_stats (PicoSAT *); /* > output file */+unsigned long long picosat_propagations (PicoSAT *); /* #propagations */+unsigned long long picosat_decisions (PicoSAT *); /* #decisions */+unsigned long long picosat_visits (PicoSAT *); /* #visits */++/* The time spent in the library or in 'picosat_sat'. The former is only+ * returned if, right after initialization 'picosat_measure_all_calls'+ * is called.+ */+double picosat_seconds (PicoSAT *);++/*------------------------------------------------------------------------*/+/* Add a literal of the next clause. A zero terminates the clause. The+ * solver is incremental. Adding a new literal will reset the previous+ * assignment. The return value is the original clause index to which+ * this literal respectively the trailing zero belong starting at 0.+ */+int picosat_add (PicoSAT *, int lit);++/* As the previous function, but allows to add a full clause at once with an+ * at compiled time known size. The list of argument literals has to be+ * terminated with a zero literal. Literals beyond the first zero literal+ * are discarded.+ */+int picosat_add_arg (PicoSAT *, ...);++/* As the previous function but with an at compile time unknown size.+ */+int picosat_add_lits (PicoSAT *, int * lits);++/* Print the CNF to the given file in DIMACS format.+ */+void picosat_print (PicoSAT *, FILE *);++/* You can add arbitrary many assumptions before the next 'picosat_sat'.+ * This is similar to the using assumptions in MiniSAT, except that you do+ * not have to collect all your assumptions yourself. In PicoSAT you can+ * add one after the other before the next call to 'picosat_sat'.+ *+ * These assumptions can be seen as adding unit clauses with those+ * assumptions as literals. However these assumption clauses are only valid+ * for exactly the next call to 'picosat_sat'. And will be removed+ * afterwards, e.g. in future calls to 'picosat_sat' after the next one they+ * are not assumed, unless they are assumed again trough 'picosat_assume'.+ *+ * More precisely, assumptions actually remain valid even after the next+ * call to 'picosat_sat' returns. Valid means they remain 'assumed' until a+ * call to 'picosat_add', 'picosat_assume', or another 'picosat_sat,+ * following the first 'picosat_sat'. They need to stay valid for+ * 'picosat_failed_assumption' to return correct values. + *+ * Example:+ *+ * picosat_assume (1); // assume unit clause '1 0'+ * picosat_assume (-2); // additionally assume clause '-2 0'+ * res = picosat_sat (1000); // assumes 1 and -2 to hold+ * // 1000 decisions max.+ *+ * if (res == PICOSAT_UNSATISFIABLE) + * {+ * if (picosat_failed_assumption (1))+ * // unit clause '1 0' was necessary to derive UNSAT+ *+ * if (picosat_failed_assumption (-2))+ * // unit clause '-2 0' was necessary to derive UNSAT+ *+ * // at least one but also both could be necessary+ *+ * picosat_assume (17); // previous assumptions are removed+ * // now assume unit clause '17 0' for+ * // the next call to 'picosat_sat'+ *+ * // adding a new clause, actually the first literal of+ * // a clause would also make the assumptions used in the previous+ * // call to 'picosat_sat' invalid.+ *+ * // The first two assumptions above are not assumed anymore. Only+ * // the assumptions, since the last call to 'picosat_sat' returned+ * // are assumed, e.g. the unit clause '17 0'.+ *+ * res = picosat_sat (-1);+ * }+ * else if (res == PICOSAT_SATISFIABLE)+ * {+ * // now the assignment is valid and we can call 'picosat_deref'+ *+ * assert (picosat_deref (1) == 1));+ * assert (picosat_deref (-2) == 1));+ *+ * val = picosat_deref (15);+ *+ * // previous two assumptions are still valid+ *+ * // would become invalid if 'picosat_add' or 'picosat_assume' is+ * // called here, but we immediately call 'picosat_sat'. Now when+ * // entering 'picosat_sat' the solver knows that the previous call+ * // returned SAT and it can safely reset the previous assumptions+ *+ * res = picosat_sat (-1);+ * }+ * else+ * {+ * assert (res == PICOSAT_UNKNOWN);+ *+ * // assumptions valid, but assignment invalid+ * // except for top level assigned literals which+ * // necessarily need to have this value if the formula is SAT+ *+ * // as above the solver nows that the previous call returned UNKWOWN+ * // and will before doing anything else reset assumptions+ *+ * picosat_sat (-1);+ * }+ */+void picosat_assume (PicoSAT *, int lit);++/*------------------------------------------------------------------------*/+/* This is an experimental feature for handling 'all different constraints'+ * (ADC). Currently only one global ADC can be handled. The bit-width of+ * all the bit-vectors entered in this ADC (stored in 'all different+ * objects' or ADOs) has to be identical.+ *+ * TODO: also handle top level assigned literals here.+ */+void picosat_add_ado_lit (PicoSAT *, int);++/*------------------------------------------------------------------------*/+/* Call the main SAT routine. A negative decision limit sets no limit on+ * the number of decisions. The return values are as above, e.g.+ * 'PICOSAT_UNSATISFIABLE', 'PICOSAT_SATISFIABLE', or 'PICOSAT_UNKNOWN'.+ */+int picosat_sat (PicoSAT *, int decision_limit);++/* As alternative to a decision limit you can use the number of propagations+ * as limit. This is more linearly related to execution time. This has to+ * be called after 'picosat_init' and before 'picosat_sat'.+ */+void picosat_set_propagation_limit (PicoSAT *, unsigned long long limit);++/* Return last result of calling 'picosat_sat' or '0' if not called.+ */+int picosat_res (PicoSAT *);++/* After 'picosat_sat' was called and returned 'PICOSAT_SATISFIABLE', then+ * the satisfying assignment can be obtained by 'dereferencing' literals.+ * The value of the literal is return as '1' for 'true', '-1' for 'false'+ * and '0' for an unknown value.+ */+int picosat_deref (PicoSAT *, int lit);++/* Same as before but just returns true resp. false if the literals is+ * forced to this assignment at the top level. This function does not+ * require that 'picosat_sat' was called and also does not internally reset+ * incremental usage.+ */+int picosat_deref_toplevel (PicoSAT *, int lit);++/* After 'picosat_sat' was called and returned 'PICOSAT_SATISFIABLE' a+ * partial satisfying assignment can be obtained as well. It satisfies all+ * original clauses. The value of the literal is return as '1' for 'true',+ * '-1' for 'false' and '0' for an unknown value. In order to make this+ * work all original clauses have to be saved internally, which has to be+ * enabled by 'picosat_save_original_clauses' right after initialization.+ */+int picosat_deref_partial (PicoSAT *, int lit);++/* Returns non zero if the CNF is unsatisfiable because an empty clause was+ * added or derived.+ */+int picosat_inconsistent (PicoSAT *);++/* Returns non zero if the literal is a failed assumption, which is defined+ * as an assumption used to derive unsatisfiability. This is as accurate as+ * generating core literals, but still of course is an overapproximation of+ * the set of assumptions really necessary. The technique does not need+ * clausal core generation nor tracing to be enabled and thus can be much+ * more effective. The function can only be called as long the current+ * assumptions are valid. See 'picosat_assume' for more details.+ */+int picosat_failed_assumption (PicoSAT *, int lit);++/* Returns a zero terminated list of failed assumption in the last call to+ * 'picosat_sat'. The pointer is valid until the next call to+ * 'picosat_sat' or 'picosat_failed_assumptions'. It only makes sense if the+ * last call to 'picosat_sat' returned 'PICOSAT_UNSATISFIABLE'.+ */+const int * picosat_failed_assumptions (PicoSAT *);++/* Returns a zero terminated minimized list of failed assumption for the last+ * call to 'picosat_sat'. The pointer is valid until the next call to this+ * function or 'picosat_sat' or 'picosat_mus_assumptions'. It only makes sense+ * if the last call to 'picosat_sat' returned 'PICOSAT_UNSATISFIABLE'.+ *+ * The call back function is called for all successful simplification+ * attempts. The first argument of the call back function is the state+ * given as first argument to 'picosat_mus_assumptions'. The second+ * argument to the call back function is the new reduced list of failed+ * assumptions.+ *+ * This function will call 'picosat_assume' and 'picosat_sat' internally but+ * before returning reestablish a proper UNSAT state, e.g.+ * 'picosat_failed_assumption' will work afterwards as expected.+ *+ * The last argument if non zero fixes assumptions. In particular, if an+ * assumption can not be removed it is permanently assigned true, otherwise+ * if it turns out to be redundant it is permanently assumed to be false.+ */+const int * picosat_mus_assumptions (PicoSAT *, void *,+ void(*)(void*,const int*),int);++/* Compute one maximal subset of satisfiable assumptions. You need to set+ * the assumptions, call 'picosat_sat' and check for 'picosat_inconsistent',+ * before calling this function. The result is a zero terminated array of+ * assumptions that consistently can be asserted at the same time. Before+ * returing the library 'reassumes' all assumptions.+ *+ * It could be beneficial to set the default phase of assumptions+ * to true (positive). This can speed up the computation.+ */+const int * picosat_maximal_satisfiable_subset_of_assumptions (PicoSAT *);++/* This function assumes that you have set up all assumptions with+ * 'picosat_assume'. Then it calls 'picosat_sat' internally unless the+ * formula is already inconsistent without assumptions, i.e. it contains+ * the empty clause. After that it extracts a maximal satisfiable subset of+ * assumptions.+ *+ * The result is a zero terminated maximal subset of consistent assumptions+ * or a zero pointer if the formula contains the empty clause and thus no+ * more maximal consistent subsets of assumptions can be extracted. In the+ * first case, before returning, a blocking clause is added, that rules out+ * the result for the next call.+ *+ * NOTE: adding the blocking clause changes the CNF.+ *+ * So the following idiom+ *+ * const int * mss;+ * picosat_assume (a1);+ * picosat_assume (a2);+ * picosat_assume (a3);+ * picosat_assume (a4);+ * while ((mss = picosat_next_maximal_satisfiable_subset_of_assumptions ()))+ * process_mss (mss);+ *+ * can be used to iterate over all maximal consistent subsets of+ * the set of assumptions {a1,a2,a3,a4}.+ *+ *+ * It could be beneficial to set the default phase of assumptions+ * to true (positive). This can speed up the computation.+ */+const int * +picosat_next_maximal_satisfiable_subset_of_assumptions (PicoSAT *);++/* Similarly we can iterate over all minimal correcting assumption sets.+ * See the CAMUS literature [M. Liffiton, K. Sakallah JAR 2008].+ *+ * The result contains each assumed literal only once, even if it+ * was assumed multiple times (in contrast to the maximal consistent+ * subset functions above).+ *+ * It could be beneficial to set the default phase of assumptions+ * to true (positive). This may speed up the computation.+ */+const int *+picosat_next_minimal_correcting_subset_of_assumptions (PicoSAT *);++/* Compute the union of all minmal correcting sets, which is called+ * the 'high level union of all minimal unsatisfiable subset sets'.+ *+ * It uses 'picosat_next_minimal_correcting_subset_of_assumptions' and+ * the same notes and advices apply. In particular, this implies that+ * after calling the function once, the current CNF becomes inconsistent,+ * and PicoSAT has to be reset. So even this function internally uses+ * PicoSAT incrementally, it can not be used incrementally itself at this+ * point.+ *+ * The 'callback' can be used for progress logging and is called after+ * each extracted minimal correcting set if non zero. The 'nhumus'+ * parameter of 'callback' denotes the number of assumptions found to be+ * part of the HUMUS sofar.+ */+const int *+picosat_humus (PicoSAT *,+ void (*callback)(void * state, int nmcs, int nhumus),+ void * state);++/*------------------------------------------------------------------------*/+/* Assume that a previous call to 'picosat_sat' in incremental usage,+ * returned 'SATISFIABLE'. Then a couple of clauses and optionally new+ * variables were added (a new variable is a variable that has an index+ * larger then the maximum variable added so far). The next call to+ * 'picosat_sat' also returns 'SATISFIABLE'. If this function+ * 'picosat_changed' returns '0', then the assignment to the old variables+ * did not change. Otherwise it may have changed. The return value to+ * this function is only valid until new clauses are added through+ * 'picosat_add', an assumption is made through 'picosat_assume', or again+ * 'picosat_sat' is called. This is the same assumption as for+ * 'picosat_deref'.+ *+ * TODO currently this function may also return a non zero value even if the+ * old assignment did not change, because it only checks whether the+ * assignment of at least one old variable was flipped at least once during+ * the search. In principle it should be possible to be exact in the other+ * direcetion as well by using a counter of variables that have an odd+ * number of flips. But this is not implemented yet.+ */+int picosat_changed (PicoSAT *);++/*------------------------------------------------------------------------*/+/* The following six functions internally extract the variable and clausal+ * core and thus require trace generation to be enabled with+ * 'picosat_enable_trace_generation' right after calling 'picosat_init'.+ *+ * TODO: using these functions in incremental mode with failed assumptions+ * has only been tested for 'picosat_corelit' thoroughly. The others may+ * only work in non-incremental mode or without using 'picosat_assume'.+ */++/* This function determines whether the i'th added original clause is in the+ * core. The 'i' is the return value of 'picosat_add', which starts at zero+ * and is incremented by one after a original clause is added (that is after+ * 'picosat_add (0)'). For the index 'i' the following has to hold: + *+ * 0 <= i < picosat_added_original_clauses ()+ */+int picosat_coreclause (PicoSAT *, int i);++/* This function gives access to the variable core, which is made up of the+ * variables that were resolved in deriving the empty clause.+ */+int picosat_corelit (PicoSAT *, int lit);++/* Write the clauses that were used in deriving the empty clause to a file+ * in DIMACS format.+ */+void picosat_write_clausal_core (PicoSAT *, FILE * core_file);++/* Write a proof trace in TraceCheck format to a file.+ */+void picosat_write_compact_trace (PicoSAT *, FILE * trace_file);+void picosat_write_extended_trace (PicoSAT *, FILE * trace_file);++/* Write a RUP trace to a file. This trace file contains only the learned+ * core clauses while this is not necessarily the case for the RUP file+ * obtained with 'picosat_set_incremental_rup_file'.+ */+void picosat_write_rup_trace (PicoSAT *, FILE * trace_file);++/*------------------------------------------------------------------------*/+/* Keeping the proof trace around is not necessary if an over-approximation+ * of the core is enough. A literal is 'used' if it was involved in a+ * resolution to derive a learned clause. The core literals are necessarily+ * a subset of the 'used' literals.+ */++int picosat_usedlit (PicoSAT *, int lit);+/*------------------------------------------------------------------------*/+#endif
+ picosat.cabal view
@@ -0,0 +1,35 @@+name: picosat+version: 0.1.0.0+synopsis: Bindings to the PicoSAT solver+homepage: http://www.stephendiehl.com+license: MIT+license-file: LICENSE+author: Stephen Diehl+maintainer: stephen.m.diehl@gmail.com+copyright: 2012 Stephen Diehl+category: Math+build-type: Simple+cabal-version: >=1.10+extra-source-files: + cbits/picosat.h+Bug-Reports: https://github.com/sdiehl/haskell-picosat/issues++Category: Logic+Description:+ `picosat` provides bindings for the fast PicoSAT solver library.+Source-Repository head+ Type: git+ Location: https://github.com/sdiehl/haskell-picosat++library+ exposed-modules: Picosat++ Cc-options: + Ghc-options: -Wall+ build-depends: base >=4.6 && <4.7+ default-language: Haskell2010+ Hs-source-dirs: src+ Include-dirs: cbits++ C-sources:+ cbits/picosat.c
+ src/Picosat.hs view
@@ -0,0 +1,90 @@+{-# LANGUAGE ForeignFunctionInterface #-}++module Picosat (+ solve,+ solveST,+ unsafeSolve,+ Solution(..)+) where++import Control.Monad++import System.IO.Unsafe (unsafePerformIO)++import Control.Monad.ST (ST)+import Control.Monad.ST.Unsafe (unsafeIOToST)++import Foreign.Ptr+import Foreign.C.Types++default (Int)++foreign import ccall unsafe "picosat_init" picosat_init+ :: IO (Ptr a)++foreign import ccall unsafe "picosat_reset" picosat_reset+ :: Ptr a -> IO ()++foreign import ccall unsafe "picosat_add" picosat_add+ :: Ptr a -> CInt -> IO CInt++foreign import ccall unsafe "picosat_variables" picosat_variables+ :: Ptr a -> IO CInt++foreign import ccall unsafe "picosat_sat" picosat_sat+ :: Ptr a -> CInt -> IO CInt++foreign import ccall unsafe "picosat_deref" picosat_deref+ :: Ptr a -> CInt -> IO CInt++unknown, satisfiable, unsatisfiable :: CInt+unknown = 0+satisfiable = 10+unsatisfiable = 20++data Solution = Solution [Int]+ | Unsatisfiable+ | Unknown deriving (Show, Eq)++addClause :: Ptr a -> [CInt] -> IO ()+addClause pico cl = mapM_ (picosat_add pico) (cl ++ [0])++addClauses :: Ptr a -> [[CInt]] -> IO ()+addClauses pico = mapM_ (addClause pico)++getSolution :: Ptr a -> IO Solution+getSolution pico = do+ vars <- picosat_variables pico+ sol <- forM [1..vars] $ \i -> do+ s <- picosat_deref pico i+ return $ i * s+ return $ Solution $ map fromIntegral sol++solution :: Ptr a -> IO Solution+solution pico = do+ res <- picosat_sat pico (-1)+ case res of+ a | a == unknown -> return Unknown+ | a == unsatisfiable -> return Unsatisfiable+ | a == satisfiable -> getSolution pico+ | otherwise -> error "Picosat error."++toCIntegers :: Integral a => [[a]] -> [[CInt]]+toCIntegers = map $ map fromIntegral++solve :: Integral a => [[a]] -> IO Solution+solve cls = do+ let ccls = toCIntegers cls+ pico <- picosat_init+ _ <- addClauses pico ccls+ sol <- solution pico+ picosat_reset pico+ return sol++{-# NOINLINE solveST #-}+solveST :: Integral a => [[a]] -> ST t Solution+solveST = unsafeIOToST . solve++{-# NOINLINE unsafeSolve #-}+unsafeSolve :: Integral a => [[a]] -> Solution+unsafeSolve = unsafePerformIO . solve