/precosat.cc
C++ | 4619 lines | 4292 code | 285 blank | 42 comment | 1877 complexity | b1229db92acdb3e22002814499f67276 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /***************************************************************************
- Copyright (c) 2009, 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 "precosat.hh"
- #include "precobnr.hh"
- #include <cstdio>
- #include <cstring>
- #include <cstdarg>
- extern "C" {
- #include <ctype.h>
- #include <sys/time.h>
- #include <sys/resource.h>
- #include <sys/unistd.h>
- #if !defined(__APPLE__)
- #include <malloc.h>
- #endif
- #include <unistd.h>
- };
- #ifndef NLOGPRECO
- #include <iostream>
- #define LOG(code) \
- do { std::cout << prfx << "LOG " << code << std::endl; } while (false)
- #else
- #define LOG(code) do { } while (false)
- #endif
- #if 0
- #include <iostream>
- #define COVER(code) \
- do { std::cout << prfx << "COVER " << __FUNCTION__ << ' ' \
- << __LINE__ << ' ' << code << std::endl; } while (false)
- #else
- #define COVER(code) do { } while (false)
- #endif
- //#define PRECOCHECK
- #ifdef PRECOCHECK
- #warning "PRECOCHECK enabled"
- #endif
- #ifndef NSTATSPRECO
- #define INC(s) do { stats.s++; } while (0)
- #else
- #define INC(s) do { } while (0)
- #endif
- namespace PrecoSat {
- template<class T> inline static void swap (T & a, T & b)
- { T tmp = a; a = b; b = tmp; }
- template<class T> inline static const T min (const T a, const T b)
- { return a < b ? a : b; }
- template<class T> inline static const T max (const T a, const T b)
- { return a > b ? a : b; }
- template<class T> inline static void fix (T * & p, long moved)
- { char * q = (char*) p; q += moved; p = (T*) q; }
- inline static int logsize (int size) { return (128 >> size) + 1; }
- static inline Val lit2val (int lit) { return (lit & 1) ? -1 : 1; }
- static inline Cls * lit2conflict (Cls & bins, int a, int b) {
- bins.lits[0] = a;
- bins.lits[1] = b;
- assert (!bins.lits[2]);
- return &bins;
- }
- static inline unsigned ggt (unsigned a, unsigned b)
- { while (b) { unsigned r = a % b; a = b, b = r; } return a; }
- inline static unsigned minuscap (unsigned a, unsigned b)
- { return (a <= b) ? 0 : (a - b); }
- static inline double mb (size_t bytes)
- { return bytes / (double) (1<<20); }
- static inline bool sigsubs (unsigned s, unsigned t)
- { return !(s&~t); }
- static inline unsigned listig (int lit)
- { return (1u << (31u & (unsigned)(lit/2))); }
- static inline double average (double a, double b) { return b ? a/b : 0; }
- static inline double percent (double a, double b) { return 100*average(a,b); }
- static bool parity (unsigned x)
- { bool res = false; while (x) res = !res, x &= x-1; return res; }
- }
- using namespace PrecoSat;
- inline unsigned RNG::next () {
- unsigned res = state;
- state *= 1664525u;
- state += 1013904223u;
- return res;
- }
- inline bool RNG::oneoutof (unsigned spread) {
- return spread ? !(next () % spread) : true;
- }
- inline size_t Cls::bytes (int n) {
- return sizeof (Cls) + (n - 3 + 1) * sizeof (int);
- }
- inline size_t Cls::bytes () const { return bytes (size); }
- inline Anchor<Cls> & Solver::anchor (Cls * c) {
- if (c->binary) return binary;
- if (!c->lnd) return original;
- if (c->fresh) return fresh;
- return learned[c->glue];
- }
- inline int Cls::minlit () const {
- int res = INT_MAX, other;
- for (const int * p = lits; (other = *p); p++)
- if (other < res) res = other;
- return res;
- }
- inline bool Cls::contains (int lit) const {
- if (!(sig & listig (lit))) return false;
- for (const int * p = lits; *p; p++)
- if (*p == lit) return true;
- return false;
- }
- inline void Solver::setsig (Cls * cls) {
- int except = cls->minlit (), lit;
- unsigned fwsig = 0, bwsig = 0;
- for (const int * p = cls->lits; (lit = *p); p++) {
- unsigned sig = listig (lit);
- bwsig |= sig;
- if (lit != except) fwsig |= sig;
- }
- cls->sig = bwsig;
- for (const int * p = cls->lits; (lit = *p); p++)
- bwsigs[lit] |= bwsig;
- if (fwsigs)
- fwsigs[except] |= fwsig;
- }
- inline unsigned Solver::litsig () {
- unsigned res = 0;
- for (int i = 0; i < lits; i++)
- res |= listig (lits[i]);
- return res;
- }
- inline bool Solver::clt (int a, int b) const {
- Var & u = vars[a/2], &v = vars[b/2];
- int l = u.dlevel, k = v.dlevel;
- if (l < 0) return false;
- if (k < 0) return true;
- if (l < k) return true;
- if (l > k) return false;
- Val r = vals[a], s = vals[b];
- if (r < s) return true;
- return false;
- }
- inline void Solver::connect (Cls * c) {
- for (int i = 0; i <= 1; i++) {
- int lit, * r = c->lits + i, * q = r, best = *q;
- for (int * p = q + 1; (lit = *p); p++)
- if (clt (best, lit)) q = p, best = lit;
- *q = *r, *r = best;
- }
- assert (c->lits[0] && c->lits[1]);
- Anchor<Cls> & a = anchor (c);
- if (!connected (a, c)) push (a, c);
- if (c->binary) {
- for (int i = 0; i <= 1; i++)
- occs[c->lits[i]].bins.push (mem, c->lits[!i]);
- } else {
- for (int i = 0; i <= 1; i++)
- occs[c->lits[i]].large.push (mem, Occ (c->lits[!i], c));
- }
- if (orgs)
- for (const int * p = c->lits; *p; p++)
- orgs[*p].push (mem, c);
- if (fwds) fwds[c->minlit ()].push (mem, c);
- setsig (c);
- }
- inline void Solver::disconnect (Cls * c) {
- assert (!c->locked && !c->dirty && !c->trash);
- int l0 = c->lits[0], l1 = c->lits[1];
- assert (l0 && l1);
- Anchor<Cls> & a = anchor (c);
- if (connected (a, c)) dequeue (a, c);
- if (c->binary) {
- occs[l0].bins.remove(l1);
- occs[l1].bins.remove(l0);
- } else {
- occs[l0].large.remove(Occ(0,c));
- occs[l1].large.remove(Occ(0,c));
- }
- if (fwds) fwds[c->minlit ()].remove (c);
- if (!orgs || c->lnd) return;
- for (const int * p = c->lits; *p; p++)
- orgs[*p].remove (c);
- }
- inline Rnk * Solver::prb (const Rnk * r) { return prbs + (r - rnks); }
- inline Rnk * Solver::rnk (const Var * v) { return rnks + (v - vars); }
- inline Var * Solver::var (const Rnk * r) { return vars + (r - rnks); }
- inline Val Solver::fixed (int lit) const {
- return vars[lit/2].dlevel ? 0 : vals[lit];
- }
- inline void Solver::collect (Cls * cls) {
- assert (!cls->locked && !cls->dirty && !cls->trash && !cls->gate);
- if (cls->binary) assert (stats.clauses.bin), stats.clauses.bin--;
- else if (cls->lnd) assert (stats.clauses.lnd), stats.clauses.lnd--;
- else assert (stats.clauses.orig), stats.clauses.orig--;
- if (!cls->lnd) assert (stats.clauses.irr), stats.clauses.irr--;
- size_t bytes = cls->bytes ();
- #ifdef PRECOCHECK
- if (!cls->lnd) {
- for (const int * p = cls->lits; *p; p++)
- check.push (mem, *p);
- check.push (mem, 0);
- }
- #endif
- #ifndef NLOGPRECO
- dbgprint ("LOG recycle clause ", cls);
- #endif
- mem.deallocate (cls, bytes);
- stats.collected += bytes;
- simplified = true;
- }
- void Solver::touchblkd (int lit) {
- assert (blkmode);
- int idx = lit/2, notlit = lit^1;
- Var * v = vars + idx;
- if (v->type != FREE) return;
- assert (!val (lit) && !repr[lit]);
- Rnk * r = blks + notlit;
- assert (orgs);
- int nh = -orgs[lit], oh = r->heat; r->heat = nh;
- if (oh == nh && schedule.block.contains (r)) return;
- if (oh == nh) LOG ("touchblkd " << notlit << " again " << nh);
- else LOG ("touchblkd " << notlit << " from " << oh << " to " << nh);
- if (!schedule.block.contains (r)) schedule.block.push (mem, r);
- else if (nh > oh) schedule.block.up (r);
- else if (nh < oh) schedule.block.down (r);
- }
- void Solver::touchelim (int lit) {
- assert (elimode);
- lit &= ~1;
- int idx = lit/2;
- Var * v = vars + idx;
- if (v->type != FREE) return;
- assert (!val (lit) && !repr[lit]);
- if (idx == elimvar) return;
- Rnk * r = elms + idx;
- assert (orgs);
- int pos = orgs[lit];
- int neg = orgs[1^lit];
- long long tmp = -(((long long)pos) * (long long) neg);
- int nh = (tmp >= INT_MIN) ? (int) tmp : INT_MIN;
- int oh = r->heat; r->heat = nh;
- if (oh == nh && schedule.elim.contains (r)) return;
- if (oh == nh) LOG ("touchelim " << lit << " again " << nh);
- else LOG ("touchelim " << lit << " from " << oh << " to " << nh);
- if (pos > 1 && neg > 1 && nh <= opts.elimin) {
- if (schedule.elim.contains (r)) {
- schedule.elim.remove (r);
- }
- } else if (!schedule.elim.contains (r)) schedule.elim.push (mem, r);
- else if (nh > oh) schedule.elim.up (r);
- else if (nh < oh) schedule.elim.down (r);
- }
- void Solver::touchpure (int lit) {
- assert (puremode);
- int idx = lit/2;
- Var * v = vars + idx;
- if (v->onplits) return;
- LOG ("touchpure " << lit);
- v->onplits = true;
- plits.push (mem, idx);
- }
- void Solver::touch (int lit) {
- assert (elimode + blkmode == 1);
- if (elimode) touchelim (lit);
- else touchblkd (lit);
- if (puremode) touchpure (lit);
- }
- void Solver::touch (Cls * c) {
- assert (asymode || !c->lnd);
- assert (elimode || blkmode);
- for (int * p = c->lits; *p; p++)
- touch (*p);
- }
- inline void Solver::recycle (Cls * c) {
- stats.clauses.gc++;
- disconnect (c);
- if (c->trash) trash.remove (c);
- if (c->gate) cleangate ();
- if (c->str) strnd.remove (c);
- if (elimode || blkmode) touch (c);
- collect (c);
- }
- inline void Solver::dump (Cls * c) {
- assert (!c->dirty);
- if (c->trash) return;
- c->trash = true;
- trash.push (mem, c);
- }
- inline void Solver::cleantrash () {
- if (!trash) return;
- int old = stats.clauses.orig;
- while (trash) {
- Cls * cls = trash.pop ();
- assert (cls->trash);
- cls->trash = false;
- recycle (cls);
- }
- shrink (old);
- }
- inline void Solver::gcls (Cls * c) {
- assert (!c->gate);
- c->gate = true;
- gate.push (mem, c);
- }
- inline void Solver::strcls (Cls * c) {
- assert (!c->str);
- c->str = true;
- strnd.push (mem, c);
- }
- inline void Solver::cleangate () {
- while (gate) {
- Cls * cls = gate.pop ();
- assert (cls->gate); cls->gate = false;
- }
- gatepivot = 0;
- gatestats = 0;
- gatelen = 0;
- }
- inline void Solver::recycle (int lit) {
- LOG ("recycle literal " << lit);
- assert (!level);
- #ifndef NDEBUG
- Var * v = vars + (lit/2); Vrt t = v->type;
- assert (t == FIXED || t == PURE || t == ZOMBIE || t == ELIM);
- #endif
- if (!orgs) return;
- while (int size = orgs[lit]) recycle (orgs[lit][size - 1]);
- orgs[lit].release (mem);
- occs[lit].bins.release (mem);
- occs[lit].large.release (mem);
- }
- Opt::Opt (const char * n, int v, int * vp, int mi, int ma) :
- name (n), valptr (vp), min (mi), max (ma)
- {
- assert (min <= v);
- assert (v <= max);
- *vp = v;
- }
- bool Opts::set (const char * opt, int val) {
- for (Opt * o = opts.begin (); o < opts.end (); o++)
- if (!strcmp (o->name, opt)) {
- if (val < o->min) return false;
- if (val > o->max) return false;
- *o->valptr = val;
- return true;
- }
- return false;
- }
- bool Opts::set (const char * opt, const char * val) {
- if (strcmp (opt, "output")) return false;
- output = val;
- return true;
- }
- void Opts::add (Mem & mem, const char * n, int v, int * vp, int mi, int ma) {
- opts.push (mem, Opt (n, v, vp, mi, ma));
- }
- void Opts::printoptions (FILE * file, const char * prfx) const {
- assert (prfx);
- int lenprfx = strlen (prfx);
- fputs (prfx, file); int pos = 0;
- const Opt * o = opts.begin ();
- while (o < opts.end ()) {
- char line[80];
- sprintf (line, " --%s=%d", o->name, *o->valptr);
- int len = strlen (line); assert (len < 80);
- if (len + pos >= 77 - lenprfx) {
- fprintf (file, "\n%s", prfx);
- pos = lenprfx;
- }
- fputs (line, file);
- pos += len;
- o++;
- }
- fputc ('\n', file);
- if (output)
- fprintf (file, "%s\n%s --output=%s\n", prfx, prfx, output);
- }
- void Solver::initbwsigs () {
- assert (!bwsigs);
- size_t bytes = 2 * size * sizeof *bwsigs;
- bwsigs = (unsigned*) mem.callocate (bytes);
- }
- void Solver::rszbwsigs (int newsize) {
- assert (bwsigs);
- size_t old_bytes = 2 * size * sizeof *bwsigs;
- size_t new_bytes = 2 * newsize * sizeof *bwsigs;
- bwsigs = (unsigned*) mem.recallocate (bwsigs, old_bytes, new_bytes);
- }
- void Solver::clrbwsigs () {
- size_t bytes = 2 * size * sizeof *bwsigs;
- memset (bwsigs, 0, bytes);
- }
- void Solver::delbwsigs () {
- size_t bytes = 2 * size * sizeof *bwsigs;
- mem.deallocate (bwsigs, bytes);
- bwsigs = 0;
- }
- void Solver::initorgs () {
- size_t bytes = 2 * (maxvar + 1) * sizeof *orgs;
- orgs = (Orgs*) mem.callocate (bytes);
- }
- void Solver::delorgs () {
- for (int lit = 2; lit <= 2*maxvar+1; lit++) orgs[lit].release (mem);
- size_t bytes = 2 * (maxvar + 1) * sizeof *orgs;
- mem.deallocate (orgs, bytes);
- orgs = 0;
- }
- void Solver::initfwds () {
- size_t bytes = 2 * (maxvar + 1) * sizeof *fwds;
- fwds = (Fwds*) mem.callocate (bytes);
- }
- void Solver::delfwds () {
- for (int lit = 2; lit <= 2*maxvar+1; lit++) fwds[lit].release (mem);
- size_t bytes = 2 * (maxvar + 1) * sizeof *fwds;
- mem.deallocate (fwds, bytes);
- fwds = 0;
- }
- void Solver::initfwsigs () {
- assert (!fwsigs);
- size_t bytes = 2 * (maxvar + 1) * sizeof *fwsigs;
- fwsigs = (unsigned*) mem.callocate (bytes);
- }
- void Solver::delfwsigs () {
- size_t bytes = 2 * (maxvar + 1) * sizeof *fwsigs;
- mem.deallocate (fwsigs, bytes);
- fwsigs = 0;
- }
- void Solver::initprfx (const char * newprfx) {
- prfx = (char*) mem.allocate (strlen (newprfx) + 1);
- strcpy (prfx, newprfx);
- }
- void Solver::delprfx () {
- assert (prfx);
- mem.deallocate (prfx, strlen (prfx) + 1);
- }
- #define OPT(n,v,mi,ma) \
- do { opts.add (mem, # n, v, &opts.n, mi, ma); } while (0)
- void Solver::initerm (void) {
- terminal = (out == stdout) && isatty(1);
- }
- void Solver::init (int initialmaxvar)
- {
- maxvar = initialmaxvar;
- size = 1;
- while (maxvar >= size)
- size *= 2;
- queue = 0;
- queue2 = 0;
- level = 0;
- conflict = 0;
- hinc = 128;
- agility = 0;
- typecount = 1;
- lastype = 0;
- out = stdout;
- initerm ();
- measure = true;
- iterating = false;
- elimode = false;
- blkmode = false;
- puremode = false;
- asymode = false;
- extending = false;
- assert (!initialized);
- vars = (Var*) mem.callocate (size * sizeof *vars);
- for (int i = 1; i <= maxvar; i++)
- vars[i].dlevel = -1;
- iirfs = 0;
- repr = (int*) mem.callocate (2 * size * sizeof *repr);
- jwhs = (int*) mem.callocate (2 * size * sizeof *jwhs);
- vals = (Val*) mem.callocate (2 * size * sizeof *vals);
- occs = (Occs*) mem.callocate (2 * size * sizeof *occs);
- rnks = (Rnk*) mem.allocate (size * sizeof *rnks);
- prbs = (Rnk*) mem.allocate (size * sizeof *prbs);
- elms = (Rnk*) mem.allocate (size * sizeof *elms);
- blks = (Rnk*) mem.allocate (2 * size * sizeof *blks);
- for (Rnk * p = rnks + maxvar; p > rnks; p--)
- p->heat = 0, p->pos = -1, schedule.decide.push (mem, p);
- for (Rnk * p = prbs + maxvar; p > prbs; p--) p->heat = 0, p->pos = -1;
- for (Rnk * p = elms + maxvar; p > elms; p--) p->heat = 0, p->pos = -1;
- for (Rnk * p = blks + 2*maxvar+1; p > blks+1; p--) p->heat = 0, p->pos = -1;
- bwsigs = 0;
- initbwsigs ();
- orgs = 0;
- fwds = 0;
- fwsigs = 0;
- frames.push (mem, Frame (trail));
- empty.lits[0] = 0;
- dummy.lits[2] = 0;
- int m = INT_MIN, M = INT_MAX;
- OPT (plain,0,0,1);
- OPT (rtc,0,0,2);
- OPT (quiet,0,0,1);
- OPT (verbose,0,0,2);
- OPT (print,0,0,1);
- OPT (check,0,0,2);
- OPT (order,3,1,9);
- OPT (simprd,20,0,M); OPT (simpinc,26,0,100); OPT (simprtc,0,0,2);
- OPT (merge,1,0,1);
- OPT (dominate,1,0,1);
- OPT (maxdoms,5*1000*1000,0,M);
- OPT (otfs,1,0,1);
- OPT (block,1,0,1);
- OPT (blockrtc,0,0,2); OPT (blockimpl,1,0,1);
- OPT (blockprd,10,1,M); OPT (blockint,300*1000,0,M);
- OPT (blockotfs,1,0,1);
- OPT (blockreward,100,0,10000);
- OPT (blockboost,3,0,100);
- OPT (heatinc,10,0,100);
- OPT (luby,1,0,1);
- OPT (restart,1,0,1); OPT (restartint,100,1,M);
- OPT (restartinner,10,0,1000); OPT (restartouter,10,0,1000);
- OPT (rebias,1,0,1); OPT (rebiasint,1000,1,M);
- OPT (probe,1,0,1);
- OPT (probeint,100*1000,1000,M); OPT (probeprd,10,1,M);
- OPT (probertc,0,0,2); OPT (probereward,2000,0,10000);
- OPT (probeboost,5,0,10000);
- OPT (decompose,1,0,1);
- OPT (inverse,0,0,1); OPT (inveager,0,0,1);
- OPT (mtfall,0,0,1); OPT (mtfrev,1,0,1);
- OPT (bumpuip,1,0,1);
- OPT (bumpsort,1,0,1); OPT (bumprev,1,0,1);
- OPT (bumpturbo,0,0,1); OPT (bumpbulk,0,0,1);
- OPT (fresh,50,0,100);
- OPT (glue,Cls::MAXGLUE,0,Cls::MAXGLUE);
- OPT (slim,1,0,1); OPT (sticky,1,0,Cls::MAXGLUE);
- OPT (redsub,2,0,M);
- OPT (minimize,4,0,4); OPT (maxdepth,1000,2,10000); OPT (strength,100,0,M);
- OPT (elim,1,0,1);
- OPT (elimgain,0,m/2,M/2);
- OPT (elimint,300*1000,0,M); OPT (elimprd,20,1,M);
- OPT (elimrtc,0,0,2);
- OPT (elimin,-10000,-m,M);
- OPT (elimclim,20,0,M);
- OPT (elimboost,1,0,100);
- OPT (elimreward,100,0,10000);
- OPT (elimasym,2,1,100);
- OPT (elimasymint,100000,100,M);
- OPT (elimasymreward,1000,0,M);
- OPT (fwmaxlen,100,0,M);OPT (bwmaxlen,1000,0,M); OPT (reslim,20,0,M);
- OPT (blkmaxlen,1000,0,M);
- OPT (subst,1,0,1); OPT (ands,1,0,1); OPT (xors,1,0,1); OPT (ites,1,0,1);
- OPT (minlimit,500,10,10000); OPT (maxlimit,3*1000*1000,100,M);
- OPT (dynred,4,-1,100000);
- OPT (liminitmode,1,0,1);
- OPT (limincmode,0,0,1);
- OPT (liminitconst,2000,0,1000*1000);
- OPT (liminitmax,20000,0,10*1000*1000);
- OPT (liminitpercent,10,0,1000);
- OPT (liminconst1,2000,0,100*1000);
- OPT (liminconst2,1000,0,100*1000);
- OPT (limincpercent,10,0,1000);
- OPT (enlinc,20,0,1000);
- OPT (shrink,2,0,2); OPT (shrinkfactor,100,1,1000);
- OPT (random,1,0,1); OPT (spread,2000,0,M); OPT (seed,0,0,M);
- OPT (skip,25,0,100);
- opts.set ("output", (const char*) 0);
- initprfx ("c ");
- initialized = true;
- }
- void Solver::initiirfs () {
- if (opts.order < 2) return;
- size_t bytes = size * (opts.order - 1) * sizeof *iirfs;
- iirfs = (int *) mem.allocate (bytes);
- for (Var * v = vars + 1; v <= vars + maxvar; v++)
- for (int i = 1; i < opts.order; i++)
- iirf (v, i) = -1;
- }
- void Solver::rsziirfs (int newsize) {
- if (opts.order < 2) return;
- size_t old_bytes = size * (opts.order - 1) * sizeof *iirfs;
- size_t new_bytes = newsize * (opts.order - 1) * sizeof *iirfs;
- iirfs = (int *) mem.reallocate (iirfs, old_bytes, new_bytes);
- }
- void Solver::deliirfs () {
- assert (iirfs);
- assert (opts.order >= 2);
- size_t bytes = size * (opts.order - 1) * sizeof *iirfs;
- mem.deallocate (iirfs, bytes);
- iirfs = 0;
- }
- void Solver::delclauses (Anchor<Cls> & anchor) {
- Cls * prev;
- for (Cls * p = anchor.head; p; p = prev) {
- p->bytes (); prev = p->prev; mem.deallocate (p, p->bytes ());
- }
- anchor.head = anchor.tail = 0;
- }
- void Solver::reset () {
- assert (initialized);
- initialized = false;
- #ifndef NDEBUG
- delprfx ();
- size_t bytes;
- for (int lit = 2; lit <= 2 * maxvar + 1; lit++) occs[lit].bins.release (mem);
- for (int lit = 2; lit <= 2 * maxvar + 1; lit++) occs[lit].large.release (mem);
- bytes = 2 * size * sizeof *occs; mem.deallocate (occs, bytes);
- bytes = 2 * size * sizeof *vals; mem.deallocate (vals, bytes);
- bytes = 2 * size * sizeof *repr; mem.deallocate (repr, bytes);
- bytes = 2 * size * sizeof *jwhs; mem.deallocate (jwhs, bytes);
- bytes = 2 * size * sizeof *blks; mem.deallocate (blks, bytes);
- bytes = size * sizeof *vars; mem.deallocate (vars, bytes);
- bytes = size * sizeof *prbs; mem.deallocate (prbs, bytes);
- bytes = size * sizeof *rnks; mem.deallocate (rnks, bytes);
- bytes = size * sizeof *elms; mem.deallocate (elms, bytes);
- delclauses (original);
- delclauses (binary);
- for (int glue = 0; glue <= opts.glue; glue++)
- delclauses (learned[glue]);
- delclauses (fresh);
- if (iirfs) deliirfs ();
- if (orgs) delorgs ();
- if (fwds) delfwds ();
- if (bwsigs) delbwsigs ();
- if (fwsigs) delfwsigs ();
- schedule.block.release (mem);
- schedule.elim.release (mem);
- schedule.decide.release (mem);
- schedule.probe.release (mem);
- opts.opts.release (mem);
- trail.release (mem);
- frames.release (mem);
- levels.release (mem);
- trash.release (mem);
- gate.release (mem);
- strnd.release (mem);
- saved.release (mem);
- elits.release (mem);
- plits.release (mem);
- #ifdef PRECOCHECK
- check.release (mem);
- #endif
- units.release (mem);
- lits.release (mem);
- seen.release (mem);
- assert (!mem);
- #endif
- }
- void Solver::fxopts () {
- assert (!opts.fixed);
- opts.fixed = true;
- initiirfs ();
- if (!opts.plain) return;
- opts.merge = 0;
- opts.block = 0;
- opts.dominate = 0;
- opts.rebias = 0;
- opts.probe = 0;
- opts.decompose = 0;
- opts.minimize = 2;
- opts.elim = 0;
- opts.random = 0;
- }
- void Solver::propts () {
- assert (opts.fixed);
- opts.printoptions (out, prfx);
- fflush (out);
- }
- void Solver::prstats () {
- double overalltime = stats.seconds ();
- fprintf (out, "%s%d conflicts, %d decisions, %d random\n", prfx,
- stats.conflicts, stats.decisions, stats.random);
- fprintf (out, "%s%d iterations, %d restarts, %d skipped\n", prfx,
- stats.iter, stats.restart.count, stats.restart.skipped);
- fprintf (out, "%s%d enlarged, %d shrunken, %d rescored, %d rebiased\n", prfx,
- stats.enlarged, stats.shrunken, stats.rescored, stats.rebias.count);
- fprintf (out, "%s%d simplifications, %d reductions\n", prfx,
- stats.simps, stats.reductions);
- fprintf (out, "%s\n", prfx);
- fprintf (out, "%svars: %d fixed, %d equiv, %d elim, %d pure, %d zombies\n",
- prfx,
- stats.vars.fixed, stats.vars.equiv,
- stats.vars.elim, stats.vars.pure, stats.vars.zombies);
- fprintf (out, "%selim: %lld resolutions, %d phases, %d rounds\n", prfx,
- stats.elim.resolutions, stats.elim.phases, stats.elim.rounds);
- fprintf (out, "%sextd: %d forced, %d assumed, %d flipped\n", prfx,
- stats.extend.forced, stats.extend.assumed, stats.extend.flipped);
- fprintf (out, "%ssbst: %.0f%% subst, "
- "%.1f%% nots, %.1f%% ands, %.1f%% xors, %.1f%% ites\n", prfx,
- percent (stats.vars.subst,stats.vars.elim),
- percent (stats.subst.nots.count,stats.vars.subst),
- percent (stats.subst.ands.count,stats.vars.subst),
- percent (stats.subst.xors.count,stats.vars.subst),
- percent (stats.subst.ites.count,stats.vars.subst));
- fprintf (out, "%sarty: %.2f ands %.2f xors average arity\n", prfx,
- average (stats.subst.ands.len, stats.subst.ands.count),
- average (stats.subst.xors.len, stats.subst.xors.count));
- fprintf (out, "%sprbe: %d probed, %d phases, %d rounds\n", prfx,
- stats.probe.variables, stats.probe.phases, stats.probe.rounds);
- fprintf (out, "%sprbe: %d failed, %d lifted, %d merged\n", prfx,
- stats.probe.failed, stats.probe.lifted, stats.probe.merged);
- fprintf (out, "%ssccs: %d non trivial, %d fixed, %d merged\n", prfx,
- stats.sccs.nontriv, stats.sccs.fixed, stats.sccs.merged);
- #ifndef NSTATSPRECO
- long long l1s = stats.sigs.bw.l1.srch + stats.sigs.fw.l1.srch;
- long long l1h = stats.sigs.bw.l1.hits + stats.sigs.fw.l1.hits;
- long long l2s = stats.sigs.bw.l2.srch + stats.sigs.fw.l2.srch;
- long long l2h = stats.sigs.bw.l2.hits + stats.sigs.fw.l2.hits;
- long long bws = stats.sigs.bw.l1.srch + stats.sigs.bw.l2.srch;
- long long bwh = stats.sigs.bw.l1.hits + stats.sigs.bw.l2.hits;
- long long fws = stats.sigs.fw.l1.srch + stats.sigs.fw.l2.srch;
- long long fwh = stats.sigs.fw.l1.hits + stats.sigs.fw.l2.hits;
- long long hits = bwh + fwh, srch = bws + fws;
- if (opts.verbose > 1) {
- fprintf (out, "%ssigs: %13lld srch %3.0f%% hits, %3.0f%% L1, %3.0f%% L2\n",
- prfx,
- srch, percent (hits,srch), percent (l1h,l1s), percent(l2h,l2s));
- fprintf (out,
- "%s fw: %13lld %3.0f%% %3.0f%% hits, %3.0f%% L1, %3.0f%% L2\n",
- prfx,
- fws, percent (fws,srch), percent (fwh,fws),
- percent (stats.sigs.fw.l1.hits, stats.sigs.fw.l1.srch),
- percent (stats.sigs.fw.l2.hits, stats.sigs.fw.l2.srch));
- fprintf (out,
- "%s bw: %13lld %3.0f%% %3.0f%% hits, %3.0f%% L1, %3.0f%% L2\n",
- prfx,
- bws, percent (bws,srch), percent (bwh,bws),
- percent (stats.sigs.bw.l1.hits, stats.sigs.bw.l1.srch),
- percent (stats.sigs.bw.l2.hits, stats.sigs.bw.l2.srch));
- } else
- fprintf (out,
- "%ssigs: %lld searched, %.0f%% hits, %.0f%% L1, %.0f%% L2\n",
- prfx,
- srch, percent (hits,srch), percent (l1h,l1s), percent(l2h,l2s));
- #endif
- long long alllits = stats.lits.added + stats.mins.deleted;
- fprintf (out,
- "%smins: %lld lrnd, %.0f%% del, %lld strng, %lld inv, %d dpth\n",
- prfx,
- stats.lits.added,
- percent (stats.mins.deleted, alllits),
- stats.mins.strong, stats.mins.inverse, stats.mins.depth);
- fprintf (out,
- "%ssubs: %d fw, %d bw, %d dynamic, %d org, %d doms, %d gc\n",
- prfx,
- stats.subs.fw, stats.subs.bw,
- stats.subs.dyn, stats.subs.org,
- stats.subs.doms, stats.subs.red);
- fprintf (out,
- "%sblkd: %lld resolutions, %d phases, %d rounds\n",
- prfx,
- stats.blkd.resolutions,
- stats.blkd.phases, stats.blkd.rounds);
- fprintf (out,
- "%sblkd: %d = %d implicit + %d explicit\n",
- prfx,
- stats.blkd.impl + stats.blkd.expl,
- stats.blkd.impl, stats.blkd.expl);
- assert (stats.vars.pure ==
- stats.pure.elim + stats.pure.blkd + stats.pure.expl);
- fprintf (out, "%spure: %d = %d explicit + %d elim + %d blkd\n",
- prfx,
- stats.vars.pure,
- stats.pure.expl, stats.pure.elim, stats.pure.blkd);
- assert (stats.vars.zombies ==
- stats.zombies.elim + stats.zombies.blkd + stats.zombies.expl);
- fprintf (out, "%szmbs: %d = %d explicit + %d elim + %d blkd\n",
- prfx,
- stats.vars.zombies,
- stats.zombies.expl, stats.zombies.elim, stats.zombies.blkd);
- fprintf (out,
- "%sstrs: %d forward, %d backward, %d dynamic, %d org, %d asym\n",
- prfx,
- stats.str.fw, stats.str.bw, stats.str.dyn,
- stats.str.org, stats.str.asym);
- fprintf (out, "%sotfs: dynamic %d = %d bin + %d trn + %d large\n",
- prfx,
- stats.otfs.dyn.bin + stats.otfs.dyn.trn + stats.otfs.dyn.large,
- stats.otfs.dyn.bin, stats.otfs.dyn.trn, stats.otfs.dyn.large);
- fprintf (out, "%sotfs: static %d = %d bin + %d trn + %d large\n",
- prfx,
- stats.otfs.stat.bin + stats.otfs.stat.trn + stats.otfs.stat.large,
- stats.otfs.stat.bin, stats.otfs.stat.trn, stats.otfs.stat.large);
- fprintf (out,
- "%sglue: %.2f avg, %lld slimmed = %.2f per conflict\n",
- prfx,
- average (stats.glue.sum, stats.glue.count),
- stats.glue.slimmed,
- average (stats.glue.slimmed, stats.conflicts));
- assert (stats.doms.count >= stats.doms.level1);
- assert (stats.doms.level1 >= stats.doms.probing);
- fprintf (out, "%sdoms: %d dominators, %d high, %d low\n", prfx,
- stats.doms.count,
- stats.doms.count - stats.doms.level1,
- stats.doms.level1 - stats.doms.probing);
- long long props = stats.props.srch + stats.props.simp;
- fprintf (out, "%svsts: %lld visits, %.2f per prop, %.0f%% blkd",
- prfx,
- stats.visits, average (stats.visits, props),
- percent (stats.blocked, stats.visits));
- #ifndef NSTATSPRECO
- fprintf (out, ", %.0f%% trn",
- percent (stats.ternaryvisits, stats.visits));
- #endif
- fputc ('\n', out);
- double othrtime = overalltime - stats.simptime - stats.srchtime;
- fprintf (out, "%stime: "
- "%.1f = "
- "%.1f srch (%.0f%%) + "
- "%.1f simp (%.0f%%) + "
- "%.1f othr (%.0f%%)\n",
- prfx,
- overalltime,
- stats.srchtime, percent (stats.srchtime, overalltime),
- stats.simptime, percent (stats.simptime, overalltime),
- othrtime, percent (othrtime, overalltime));
- fprintf (out, "%sprps: %lld srch props, %.2f megaprops per second\n",
- prfx, stats.props.srch,
- (stats.srchtime>0) ? stats.props.srch/1e6/stats.srchtime : 0);
- fprintf (out, "%sclss: %d recycled\n", prfx,
- stats.clauses.gc);
- fprintf (out, "%s\n", prfx);
- fprintf (out, "%s%.1f seconds, %.0f MB max, %.0f MB recycled\n", prfx,
- overalltime, mb (mem.getMax ()), mb (stats.collected));
- fflush (out);
- }
- inline void Solver::assign (int lit) {
- assert (!vals [lit]);
- vals[lit] = 1; vals[lit^1] = -1;
- Var & v = vars[lit/2];
- assert ((v.type == ELIM) == extending);
- if (!(v.dlevel = level)) {
- if (v.type == EQUIV) {
- assert (repr[lit]);
- assert (stats.vars.equiv);
- stats.vars.equiv--;
- stats.vars.fixed++;
- v.type = FIXED;
- } else {
- assert (!repr[lit]);
- if (v.type == FREE) {
- stats.vars.fixed++;
- v.type = FIXED;
- } else assert (v.type == ZOMBIE || v.type == PURE);
- }
- simplified = true;
- }
- if (measure) {
- Val val = lit2val (lit);
- agility -= agility/10000;
- if (v.phase && v.phase != val) agility += 1000;
- v.phase = val;
- }
- v.tlevel = trail;
- trail.push (mem, lit);
- #ifndef NLOGPRECO
- printf ("%sLOG assign %d at level %d <=", prfx, lit, level);
- if (v.binary) printf (" %d %d\n", lit, v.reason.lit);
- else if (v.reason.cls)
- printf (" %d %d %d%s\n",
- v.reason.cls->lits[0],
- v.reason.cls->lits[1],
- v.reason.cls->lits[2],
- v.reason.cls->size > 3 ? " ..." : "");
- else if (!level) printf (" top level\n");
- else printf (" decision\n");
- #endif
- }
- inline void Solver::assume (int lit, bool inclevel) {
- if (inclevel) {
- frames.push (mem, Frame (trail));
- level++;
- LOG ("assume new level " << level);
- assert (level + 1 == frames);
- LOG ("assuming " << lit);
- } else {
- assert (!level);
- LOG ("permanently assume " << lit << " on top level");
- }
- Var & v = vars[lit/2]; v.binary = false; v.reason.cls = 0;
- v.dominator = lit;
- assign (lit);
- }
- inline void Solver::imply (int lit, int reason) {
- assert (lit/2 != reason/2);
- assert (vals[reason] < 0);
- assert (vars[reason/2].dlevel == level);
- Var & v = vars[lit/2];
- if (level) v.binary = true, v.reason.lit = reason;
- else v.binary = false, v.reason.lit = 0;
- if (level) v.dominator = vars[reason/2].dominator;
- assign (lit);
- }
- inline int Solver::dominator (int lit, Cls * reason, bool & contained) {
- if (!opts.dominate) return 0;
- if (asymode) return 0;
- if (opts.maxdoms <= stats.doms.count) return 0;
- contained = false;
- assert (level > 0);
- int vdom = 0, other, oldvdom;
- Var * u;
- for (const int * p = reason->lits; vdom >= 0 && (other = *p); p++) {
- if (other == lit) continue;
- u = vars + (other/2);
- if (!u->dlevel) continue;
- if (u->dlevel < level) { vdom = -1; break; }
- int udom = u->dominator;
- assert (udom);
- if (vdom) {
- assert (vdom > 0);
- if (udom != vdom) vdom = -1;
- } else vdom = udom;
- }
- assert (vdom);
- if (vdom <= 0) return vdom;
- assert (vals[vdom] > 0);
- LOG (vdom << " dominates " << lit);
- for (const int * p = reason->lits; !contained && (other = *p); p++)
- contained = (other^1) == vdom;
- if (contained) goto DONE;
- oldvdom = vdom; vdom = 0;
- for (const int * p = reason->lits; (other = *p); p++) {
- if (other == lit) continue;
- assert (vals[other] < 0);
- u = vars + other/2;
- if (!u->dlevel) continue;
- assert (u->dlevel == level);
- assert (u->dominator == oldvdom);
- other ^= 1;
- assert (other != oldvdom);
- if (other == vdom) continue;
- if (vdom) {
- while (!u->mark &&
- (other = (assert (u->binary), 1^u->reason.lit)) != oldvdom &&
- other != vdom) {
- assert (vals[other] > 0);
- u = vars + other/2;
- assert (u->dlevel == level);
- assert (u->dominator == oldvdom);
- }
- while (vdom != other) {
- u = vars + (vdom/2);
- assert (u->mark);
- u->mark = 0;
- assert (u->binary);
- vdom = 1^u->reason.lit;
- }
- if (vdom == oldvdom) break;
- } else {
- vdom = 1^u->reason.lit;
- if (vdom == oldvdom) break;
- assert (vals[vdom] > 0);
- other = vdom;
- do {
- u = vars + other/2;
- assert (u->dlevel == level);
- assert (u->dominator == oldvdom);
- assert (!u->mark);
- u->mark = 1;
- assert (u->binary);
- other = 1^u->reason.lit;
- assert (vals[other] > 0);
- } while (other != oldvdom);
- }
- }
- other = vdom;
- while (other != oldvdom) {
- u = vars + other/2;
- assert (u->dlevel == level);
- assert (u->dominator == oldvdom);
- assert (u->mark);
- u->mark = 0;
- assert (u->binary);
- other = 1^u->reason.lit;
- assert (vals[other] > 0);
- }
- if (vdom == oldvdom) goto DONE;
- assert (vdom);
- LOG (vdom << " also dominates " << lit);
- assert (!contained);
- for (const int * p = reason->lits; !contained && (other = *p); p++)
- contained = (other^1) == vdom;
- DONE:
- stats.doms.count++;
- if (level == 1) stats.doms.level1++;
- if (!measure) { assert (level == 1); stats.doms.probing++; }
- if (contained) {
- reason->garbage = true;
- stats.subs.doms++;
- LOG ("dominator clause is subsuming");
- }
- return vdom;
- }
- inline void Solver::unit (int lit) {
- Var * v;
- Val val = vals[lit];
- assert (!level);
- if (val < 0) {
- LOG ("conflict after adding unit"); conflict = ∅ return;
- }
- if (!val) {
- v = vars + (lit/2);
- v->binary = false, v->reason.cls = 0;
- assign (lit);
- }
- int other = find (lit);
- if (other == lit) return;
- val = vals[other];
- if (val < 0) {
- LOG ("conflict after adding unit"); conflict = ∅ return;
- }
- if (val) return;
- v = vars + (other/2);
- v->binary = false, v->reason.cls = 0;
- assign (other);
- }
- inline unsigned Solver::gluelits () {
- const int * eol = lits.end ();
- int lit, found = 0;
- unsigned res = 0;
- assert (uip);
- for (const int * p = lits.begin (); p < eol; p++) {
- lit = *p;
- assert (val (lit) < 0);
- Var * v = vars + (lit/2);
- int dlevel = v->dlevel;
- if (dlevel == level) { assert (!found); found = lit; continue; }
- assert (dlevel > 0);
- Frame * f = &frames[dlevel];
- if (f->contained) continue;
- f->contained = true;
- res++;
- }
- assert (found == uip);
- for (const int * p = lits.begin (); p < eol; p++)
- frames[vars[*p/2].dlevel].contained = false;
- return res;
- }
- inline void Solver::slim (Cls * cls) {
- if (!opts.slim) return;
- if (!level) return;
- assert (cls);
- if (!cls->lnd) return;
- assert (!cls->binary);
- unsigned oldglue = cls->glue;
- if (!oldglue) return;
- const int * p = cls->lits;
- unsigned newglue = 0;
- int lit, nonfalse = 0;
- while ((lit = *p++)) {
- Val val = vals[lit];
- if (val >= 0 && nonfalse++) { newglue = oldglue; break; }
- Var * v = vars + (lit/2);
- int dlevel = v->dlevel;
- if (dlevel <= 0) continue;
- assert (dlevel < frames);
- Frame * f = &frames[dlevel];
- if (f->contained) continue;
- if (++newglue >= oldglue) break;
- f->contained = true;
- }
- while (p > cls->lits) {
- lit = *--p;
- if (!lit) continue;
- Var * v = vars + (lit/2);
- int dlevel = v->dlevel;
- if (dlevel <= 0) continue;
- assert (dlevel < frames);
- Frame * f = &frames[dlevel];
- f->contained = false;
- }
- if (cls->glued) {
- assert (oldglue >= newglue);
- if (oldglue == newglue) return;
- assert (newglue >= 1);
- LOG ("slimmed glue from " << oldglue << " to " << newglue);
- } else LOG ("new glue " << newglue);
- assert (newglue <= (unsigned) opts.glue);
- if (!cls->fresh) dequeue (anchor (cls), cls);
- cls->glue = newglue;
- if (!cls->fresh) push (anchor (cls), cls);
- if (cls->glued) stats.glue.slimmed++;
- stats.glue.count++;
- stats.glue.sum += newglue;
- cls->glued = true;
- }
- inline void Solver::force (int lit, Cls * reason) {
- assert (reason);
- assert (!reason->binary);
- Val val = vals[lit];
- if (val < 0) { LOG ("conflict forcing literal"); conflict = reason; }
- if (val) return;
- #ifndef NDEBUG
- for (const int * p = reason->lits; *p; p++)
- if (*p != lit) assert (vals[*p] < 0);
- #endif
- Var * v = vars + (lit/2);
- int vdom;
- bool sub;
- if (!level) {
- v->binary = false, v->reason.cls = 0;
- } else if (!lits && (vdom = dominator (lit, reason, sub)) > 0) {
- v->dominator = vdom;
- assert (vals[vdom] > 0);
- vdom ^= 1;
- LOG ("dominating learned clause " << vdom << ' ' << lit);
- assert (!lits);
- lits.push (mem, vdom);
- lits.push (mem, lit);
- bool lnd = reason->lnd || !sub;
- clause (lnd, lnd);
- v->binary = true, v->reason.lit = vdom;
- } else {
- v->binary = false, v->reason.cls = reason;
- reason->locked = true;
- if (reason->lnd) stats.clauses.lckd++;
- v->dominator = lit;
- }
- assign (lit);
- }
- inline void Solver::jwh (Cls * cls) {
- //if (cls->lnd) return; // TODO better not ?
- int * p;
- for (p = cls->lits; *p; p++)
- ;
- int size = p - cls->lits;
- int inc = logsize (size);
- while (p > cls->lits) {
- int l = *--p;
- jwhs[l] += inc;
- if (jwhs[l] < 0) die ("maximum large JWH score exceeded");
- }
- }
- int Solver::find (int a) {
- assert (2 <= a && a <= 2 * maxvar + 1);
- int res, tmp;
- for (res = a; (tmp = repr[res]); res = tmp)
- ;
- for (int fix = a; (tmp = repr[fix]) && tmp != res; fix = tmp)
- repr[fix] = res, repr[fix^1] = res^1;
- return res;
- }
- inline void Solver::merge (int l, int k, int & merged) {
- int a, b;
- if (!opts.merge) return;
- assert (!elimode);
- assert (!blkmode);
- if ((a = find (l)) == (b = find (k))) return;
- assert (a/2 != b/2);
- #ifndef NLOGPRECO
- int m = min (a, b);
- LOG ("merge " << l << " and " << k << " to " << m);
- if (k != m) LOG ("learned clause " << k << ' ' << (m^1));
- if (k != m) LOG ("learned clause " << (k^1) << ' ' << m);
- if (l != m) LOG ("learned clause " << l << ' ' << (m^1));
- if (l != m) LOG ("learned clause " << (l^1) << ' ' << m);
- #endif
- if (a < b) repr[k] = repr[b] = a, repr[k^1] = repr[b^1] = a^1;
- else repr[l] = repr[a] = b, repr[l^1] = repr[a^1] = b^1;
- assert (vars[a/2].type == FREE && vars[b/2].type == FREE);
- vars[max (a,b)/2].type = EQUIV;
- stats.vars.merged++;
- stats.vars.equiv++;
- simplified = true;
- merged++;
- }
- Cls * Solver::clause (bool lnd, unsigned glue) {
- assert (asymode || !elimode || !lnd);
- assert (lnd || !glue);
- Cls * res = 0;
- #ifndef NLOGPRECO
- std::cout << prfx << "LOG " << (lnd ? "learned" : "original") << " clause";
- for (const int * p = lits.begin (); p < lits.end (); p++)
- std::cout << ' ' << *p;
- std::cout << std::endl;
- #endif
- #ifndef NDEBUG
- for (int i = 0; i < lits; i++)
- assert (vars[lits[i]/2].type != ELIM);
- #endif
- if (lits == 0) {
- LOG ("conflict after added empty clause");
- conflict = ∅
- } else if (lits == 1) {
- int lit = lits[0];
- Val val;
- if ((val = vals[lit]) < 0) {
- LOG ("conflict after adding falsified unit clause");
- conflict = ∅
- } else if (!val) unit (lit);
- } else {
- if (lits >= (int)Cls::MAXSZ) die ("maximal clause size exceeded");
- size_t bytes = Cls::bytes (lits);
- res = (Cls *) mem.callocate (bytes);
- res->lnd = lnd;
- if (!lnd) stats.clauses.irr++;
- res->size = lits;
- int * q = res->lits, * eol = lits.end ();
- for (const int * p = lits.begin (); p < eol; p++)
- *q++ = *p;
- *q = 0;
- if (lits == 2) res->binary = true, stats.clauses.bin++;
- else {
- res->glue = min ((unsigned)opts.glue,glue);
- res->fresh = res->lnd;
- if (lnd) stats.clauses.lnd++;
- else stats.clauses.orig++;
- }
- connect (res);
- }
- lits.shrink ();
- simplified = true;
- return res;
- }
- inline void Solver::marklits () {
- for (const int * p = lits.begin (); p < lits.end (); p++)
- vars[*p/2].mark = lit2val (*p);
- }
- inline void Solver::unmarklits () {
- for (const int * p = lits.begin (); p < lits.end (); p++)
- vars[*p/2].mark = 0;
- }
- inline bool Solver::bwsub (unsigned sig, Cls * c) {
- assert (!c->trash && !c->dirty && !c->garbage);
- limit.budget.bw.sub--;
- int count = lits;
- if (c->size < (unsigned) count) return false;
- INC (sigs.bw.l1.srch);
- if (!sigsubs (sig, c->sig)) { INC (sigs.bw.l1.hits); return false; }
- int lit;
- for (int * p = c->lits; count && (lit = *p); p++) {
- Val u = lit2val (lit), v = vars[lit/2].mark;
- if (u == v) count--;
- }
- return !count;
- }
- int Solver::bwstr (unsigned sig, Cls * c) {
- assert (!c->trash && !c->dirty && !c->garbage);
- limit.budget.bw.str--;
- int count = lits;
- if (c->size < (unsigned) count) return 0;
- INC (sigs.bw.l1.srch);
- if (!sigsubs (sig, c->sig)) { INC (sigs.bw.l1.hits); return 0; }
- int lit, res = 0;
- for (int * p = c->lits; count && (lit = *p); p++) {
- Val u = lit2val (lit), v = vars[lit/2].mark;
- if (abs (u) != abs (v)) continue;
- if (u == -v) { if (res) return 0; res = lit; }
- count--;
- }
- assert (count >= 0);
- res = count ? 0 : res;
- return res;
- }
- void Solver::remove (int del, Cls * c) {
- assert (!c->trash && !c->garbage && !c->dirty && !c->gate);
- assert (c->lits[0] && c->lits[1]);
- if (c->binary) {
- int pos = (c->lits[1] == del);
- assert (c->lits[pos] == del);
- LOG ("will not remove " << del << " but will simply produce unit instead");
- unit (c->lits[!pos]);
- } else {
- disconnect (c);
- int * p = c->lits, lit;
- while ((lit = *p) != del) assert (lit), p++;
- while ((lit = *++p)) p[-1] = lit;
- p[-1] = 0;
- assert (p - c->lits >= 3);
- if (p - c->lits == 3) {
- if (c->lnd) {
- assert (stats.clauses.lnd > 0);
- stats.clauses.lnd--;
- } else {
- assert (stats.clauses.orig > 0);
- stats.clauses.orig--;
- }
- c->binary = true;
- stats.clauses.bin++;
- }
- setsig (c);
- connect (c);
- if (elimode || blkmode) touch (del);
- simplified = true;
- #ifndef NLOGPRECO
- LOG ("removed " << del << " and got");
- dbgprint ("LOG learned clause ", c);
- #endif
- }
- }
- void Solver::bworgs () {
- if (lits <= 1) return;
- limit.budget.bw.str += 2;
- limit.budget.bw.sub += 4;
- marklits ();
- int first = 0;
- int minlen = INT_MAX;
- for (int i = 0; i < lits; i++) {
- int other = lits[i];
- int len = orgs[other];
- if (len < minlen) first = other, minlen = len;
- }
- unsigned sig = litsig ();
- assert (first);
- INC (sigs.bw.l2.srch);
- if (!sigsubs (sig, bwsigs[first])) INC (sigs.bw.l2.hits);
- else if (orgs[first] <= opts.bwmaxlen)
- for (int i = 0; limit.budget.bw.sub >= 0 && i < orgs[first]; i++) {
- Cls * other = orgs[first][i];
- assert (!other->locked);
- if (other->trash || other->dirty || other->garbage) continue;
- if (!bwsub (sig, other)) continue;
- #ifndef NLOGPRECO
- dbgprint ("LOG static backward subsumed clause ", other);
- #endif
- stats.subs.bw++;
- limit.budget.bw.sub += 12;
- dump (other);
- }
- int second = 0;
- minlen = INT_MAX;
- for (int i = 0; i < lits; i++) {
- int other = lits[i];
- if (other == first) continue;
- int len = orgs[other];
- if (len < minlen) second = other, minlen = len;
- }
- assert (second);
- if (orgs[first^1] < minlen) second = (first^1);
- for (int round = 0; round <= 1; round++) {
- int start = round ? second : first;
- INC (sigs.bw.l2.srch);
- if (!sigsubs (sig, bwsigs[start])) { INC (sigs.bw.l2.hits); continue; }
- Orgs & org = orgs[start];
- if (org > opts.bwmaxlen) continue;
- for (int i = 0; limit.budget.bw.str >= 0 && i < org; i++) {
- Cls * other = org[i];
- assert (!other->locked);
- if (other->trash || other->dirty || other->garbage) continue;
- int del = bwstr (sig, other);
- if (!del) continue;
- LOG ("static backward strengthened clause by removing " << del);
- stats.str.bw++;
- limit.budget.bw.str += 10;
- remove (del, other);
- assert (litsig () == sig);
- }
- }
- unmarklits ();
- }
- void Solver::bwoccs (bool & lnd) {
- if (lits <= 1) return;
- limit.budget.bw.sub += lnd ? 30 : 10;
- limit.budget.bw.str += lnd ? 20 : 8;
- marklits ();
- unsigned sig = litsig ();
- for (int i = 0; i < lits; i++) {
- int first = lits[i];
- if (limit.budget.bw.sub >= 0) {
- INC (sigs.bw.l2.srch);
- if (!sigsubs (sig, bwsigs[first])) INC (sigs.bw.l2.hits);
- else if (occs[first].large <= opts.bwmaxlen) {
- for (int i = 0;
- limit.budget.bw.sub >= 0 && i < occs[first].large; i++) {
- Cls * other = occs[first].large[i].cls;
- assert (!other->dirty && !other->trash);
- if (other->garbage) continue;
- if (!bwsub (sig, other)) continue;
- if (!other->lnd && lnd) lnd = false;
- LOG ((level ? "dynamic" : "static")
- << " backward subsumed "
- << (other->lnd ? "learned" : "original")
- << " clause");
- #ifndef NLOGPRECO
- {
- std::cout << prfx << "LOG subsumed clause";
- for (const int * p = other->lits; *p; p++)
- std::cout << ' ' << *p;
- std::cout << std::endl;
- }
- #endif
- if (level) {
- stats.subs.dyn++;
- if (!other->lnd) stats.subs.org++;
- } else stats.subs.bw++;
- limit.budget.bw.sub += 20;
- if (other->locked) other->garbage = true; else recycle (other);
- }
- }
- }
- if (limit.budget.bw.str >= 0) {
- INC (sigs.bw.l2.srch);
- if (!sigsubs (sig, bwsigs[first])) INC (sigs.bw.l2.hits);
- else if (occs[first].large <= opts.bwmaxlen) {
- for (int i = 0;
- limit.budget.bw.sub >= 0 && i < occs[first].large;
- i++) {
- Cls* other = occs[first].large[i].cls;
- assert (!other->dirty && !other->trash);
- if (other->locked || other->garbage) continue;
- int del = bwstr (sig, other);
- if (!del) continue;
- LOG ((level ? "dynamic" : "static")
- << " backward strengthened "
- << (other->lnd ? "learned" : "original")
- << " clause by removing "
- << del);
- #ifndef NLOGPRECO
- {
- std::cout << prfx << "LOG strengthened clause";
- for (const int * p = other->lits; *p; p++)
- std::cout << ' ' << *p;
- std::cout << std::endl;
- }
- #endif
- if (level) {
- stats.str.dyn++;
- if (!other->lnd) stats.str.org++;
- } else stats.str.bw++;
- limit.budget.bw.str += 15;
- remove (del, other);
- if (level) strcls (other);
- }
- }
- }
- }
- unmarklits ();
- }
- inline bool Solver::fwsub (unsigned sig, Cls * c) {
- assert (!c->trash && !c->dirty && !c->garbage);
- limit.budget.fw.sub--;
- INC (sigs.fw.l1.srch);
- if (!sigsubs (c->sig, sig)) { INC (sigs.fw.l1.hits); return false; }
- int lit;
- for (const int * p = c->lits; (lit = *p); p++) {
- Val u = lit2val (lit), v = vars[lit/2].mark;
- if (u != v) return false;
- }
- return true;
- }
- inline int Solver::fwstr (unsigned sig, Cls * c) {
- assert (!c->trash && !c->dirty && !c->garbage);
- limit.budget.fw.str--;
- INC (sigs.fw.l1.srch);
- if (!sigsubs (c->sig, sig)) { INC (sigs.fw.l1.hits); return 0; }
- int res = 0, lit;
- for (const int * p = c->lits; (lit = *p); p++) {
- Val u = lit2val (lit), v = vars[lit/2].mark;
- if (u == v) continue;
- if (u != -v) return 0;
- if (res) return 0;
- res = (lit^1);
- }
- return res;
- }
- bool Solver::fworgs () {
- if (lits <= 1) return false;
- limit.budget.fw.str += 3;
- limit.budget.fw.sub += 5;
- assert (fwds);
- marklits ();
- unsigned sig = litsig ();
- bool res = false;
- if (lits >= 2) {
- for (int i = 0; !res && limit.budget.fw.sub >= 0 && i < lits; i++) {
- int lit = lits[i];
- INC (sigs.fw.l2.srch);
- if (!(fwsigs[lit] & sig)) { INC (sigs.fw.l2.hits); continue; }
- Fwds & f = fwds[lit];
- if (f > opts.fwmaxlen) continue;
- for (int j = 0; !res && limit.budget.fw.sub >= 0 && j < f; j++) {
- Cls * c = f[j];
- if (c->trash || c->dirty || c->garbage) continue;
- res = fwsub (sig, c);
- }
- }
- if (res) {
- LOG ("new clause is subsumed");
- stats.subs.fw++;
- limit.budget.fw.sub += 5;
- }
- }
- if (!res)
- for (int sign = 0; sign <= 1; sign++)
- for (int i = 0; limit.budget.fw.str >= 0 && i < lits; i++) {
- int lit = lits[i];
- INC (sigs.fw.l2.srch);
- if (!(fwsigs[lit] & sig)) { INC (sigs.fw.l2.hits); continue; }
- lit ^= sign;
- Fwds & f = fwds[lit];
- if (f > opts.fwmaxlen) continue;
- int del = 0;
- for (int j = 0; !del && limit.budget.fw.str >= 0 && j < f; j++) {
- Cls * c = f[j];
- if (c->trash || c->dirty || c->garbage) continue;
- del = fwstr (sig, c);
- }
- if (!del) continue;
- assert (sign || del/2 != lit/2);
- LOG ("strengthen new clause by removing " << del);
- stats.str.fw++;
- limit.budget.fw.str += 8;
- assert (vars[del/2].mark == lit2val (del));
- vars[del/2].mark = 0;
- lits.remove (del);
- sig = litsig ();
- i = -1;
- }
- unmarklits ();
- return res;
- }
- void Solver::resize (int newmaxvar) {
- assert (maxvar < size);
- assert (newmaxvar > maxvar);
- int newsize = size;
- while (newsize <= newmaxvar)
- newsize *= 2;
- if (newsize > size) {
- size_t o, n;
- o = size * sizeof * vars;
- n = newsize * sizeof * vars;
- vars = (Var *) mem.recallocate (vars, o, n);
- o = 2 * size * sizeof *repr;
- n = 2 * newsize * sizeof *repr;
- repr = (int*) mem.recallocate (repr, o, n);
- o = 2 * size * sizeof *jwhs;
- n = 2 * newsize * sizeof *jwhs;
- jwhs = (int*) mem.recallocate (jwhs, o, n);
- o = 2 * size * sizeof *vals;
- n = 2 * newsize * sizeof *vals;
- vals = (Val*) mem.recallocate (vals, o, n);
- o = 2 * size * sizeof *occs;
- n = 2 * newsize * sizeof *occs;
- occs = (Occs*) mem.recallocate (occs, o, n);
- ptrdiff_t diff;
- char * c;
- o = size * sizeof *rnks;
- n = newsize * sizeof *rnks;
- c = (char *) rnks;
- rnks = (Rnk*) mem.reallocate (rnks, o, n);
- diff = c - (char *) rnks;
- schedule.decide.fix (diff);
- o = size * sizeof *prbs;
- n = newsize * sizeof *prbs;
- c = (char *) prbs;
- prbs = (Rnk*) mem.reallocate (prbs, o, n);
- diff = c - (char *) prbs;
- schedule.probe.fix (diff);
- o = size * sizeof *elms;
- n = newsize * sizeof *elms;
- c = (char *) elms;
- elms = (Rnk*) mem.reallocate (elms, o, n);
- diff = c - (char *) elms;
- schedule.elim.fix (diff);
- rszbwsigs (newsize);
- rsziirfs (newsize);
- size = newsize;
- }
- assert (newmaxvar < size);
- while (maxvar < newmaxvar) {
- …
Large files files are truncated, but you can click here to view the full file