PageRenderTime 70ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/precosat.cc

https://github.com/damelang/precosat
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

  1. /***************************************************************************
  2. Copyright (c) 2009, Armin Biere, Johannes Kepler University.
  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to
  5. deal in the Software without restriction, including without limitation the
  6. rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  7. sell copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:
  9. The above copyright notice and this permission notice shall be included in
  10. all copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  16. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  17. IN THE SOFTWARE.
  18. ****************************************************************************/
  19. #include "precosat.hh"
  20. #include "precobnr.hh"
  21. #include <cstdio>
  22. #include <cstring>
  23. #include <cstdarg>
  24. extern "C" {
  25. #include <ctype.h>
  26. #include <sys/time.h>
  27. #include <sys/resource.h>
  28. #include <sys/unistd.h>
  29. #if !defined(__APPLE__)
  30. #include <malloc.h>
  31. #endif
  32. #include <unistd.h>
  33. };
  34. #ifndef NLOGPRECO
  35. #include <iostream>
  36. #define LOG(code) \
  37. do { std::cout << prfx << "LOG " << code << std::endl; } while (false)
  38. #else
  39. #define LOG(code) do { } while (false)
  40. #endif
  41. #if 0
  42. #include <iostream>
  43. #define COVER(code) \
  44. do { std::cout << prfx << "COVER " << __FUNCTION__ << ' ' \
  45. << __LINE__ << ' ' << code << std::endl; } while (false)
  46. #else
  47. #define COVER(code) do { } while (false)
  48. #endif
  49. //#define PRECOCHECK
  50. #ifdef PRECOCHECK
  51. #warning "PRECOCHECK enabled"
  52. #endif
  53. #ifndef NSTATSPRECO
  54. #define INC(s) do { stats.s++; } while (0)
  55. #else
  56. #define INC(s) do { } while (0)
  57. #endif
  58. namespace PrecoSat {
  59. template<class T> inline static void swap (T & a, T & b)
  60. { T tmp = a; a = b; b = tmp; }
  61. template<class T> inline static const T min (const T a, const T b)
  62. { return a < b ? a : b; }
  63. template<class T> inline static const T max (const T a, const T b)
  64. { return a > b ? a : b; }
  65. template<class T> inline static void fix (T * & p, long moved)
  66. { char * q = (char*) p; q += moved; p = (T*) q; }
  67. inline static int logsize (int size) { return (128 >> size) + 1; }
  68. static inline Val lit2val (int lit) { return (lit & 1) ? -1 : 1; }
  69. static inline Cls * lit2conflict (Cls & bins, int a, int b) {
  70. bins.lits[0] = a;
  71. bins.lits[1] = b;
  72. assert (!bins.lits[2]);
  73. return &bins;
  74. }
  75. static inline unsigned ggt (unsigned a, unsigned b)
  76. { while (b) { unsigned r = a % b; a = b, b = r; } return a; }
  77. inline static unsigned minuscap (unsigned a, unsigned b)
  78. { return (a <= b) ? 0 : (a - b); }
  79. static inline double mb (size_t bytes)
  80. { return bytes / (double) (1<<20); }
  81. static inline bool sigsubs (unsigned s, unsigned t)
  82. { return !(s&~t); }
  83. static inline unsigned listig (int lit)
  84. { return (1u << (31u & (unsigned)(lit/2))); }
  85. static inline double average (double a, double b) { return b ? a/b : 0; }
  86. static inline double percent (double a, double b) { return 100*average(a,b); }
  87. static bool parity (unsigned x)
  88. { bool res = false; while (x) res = !res, x &= x-1; return res; }
  89. }
  90. using namespace PrecoSat;
  91. inline unsigned RNG::next () {
  92. unsigned res = state;
  93. state *= 1664525u;
  94. state += 1013904223u;
  95. return res;
  96. }
  97. inline bool RNG::oneoutof (unsigned spread) {
  98. return spread ? !(next () % spread) : true;
  99. }
  100. inline size_t Cls::bytes (int n) {
  101. return sizeof (Cls) + (n - 3 + 1) * sizeof (int);
  102. }
  103. inline size_t Cls::bytes () const { return bytes (size); }
  104. inline Anchor<Cls> & Solver::anchor (Cls * c) {
  105. if (c->binary) return binary;
  106. if (!c->lnd) return original;
  107. if (c->fresh) return fresh;
  108. return learned[c->glue];
  109. }
  110. inline int Cls::minlit () const {
  111. int res = INT_MAX, other;
  112. for (const int * p = lits; (other = *p); p++)
  113. if (other < res) res = other;
  114. return res;
  115. }
  116. inline bool Cls::contains (int lit) const {
  117. if (!(sig & listig (lit))) return false;
  118. for (const int * p = lits; *p; p++)
  119. if (*p == lit) return true;
  120. return false;
  121. }
  122. inline void Solver::setsig (Cls * cls) {
  123. int except = cls->minlit (), lit;
  124. unsigned fwsig = 0, bwsig = 0;
  125. for (const int * p = cls->lits; (lit = *p); p++) {
  126. unsigned sig = listig (lit);
  127. bwsig |= sig;
  128. if (lit != except) fwsig |= sig;
  129. }
  130. cls->sig = bwsig;
  131. for (const int * p = cls->lits; (lit = *p); p++)
  132. bwsigs[lit] |= bwsig;
  133. if (fwsigs)
  134. fwsigs[except] |= fwsig;
  135. }
  136. inline unsigned Solver::litsig () {
  137. unsigned res = 0;
  138. for (int i = 0; i < lits; i++)
  139. res |= listig (lits[i]);
  140. return res;
  141. }
  142. inline bool Solver::clt (int a, int b) const {
  143. Var & u = vars[a/2], &v = vars[b/2];
  144. int l = u.dlevel, k = v.dlevel;
  145. if (l < 0) return false;
  146. if (k < 0) return true;
  147. if (l < k) return true;
  148. if (l > k) return false;
  149. Val r = vals[a], s = vals[b];
  150. if (r < s) return true;
  151. return false;
  152. }
  153. inline void Solver::connect (Cls * c) {
  154. for (int i = 0; i <= 1; i++) {
  155. int lit, * r = c->lits + i, * q = r, best = *q;
  156. for (int * p = q + 1; (lit = *p); p++)
  157. if (clt (best, lit)) q = p, best = lit;
  158. *q = *r, *r = best;
  159. }
  160. assert (c->lits[0] && c->lits[1]);
  161. Anchor<Cls> & a = anchor (c);
  162. if (!connected (a, c)) push (a, c);
  163. if (c->binary) {
  164. for (int i = 0; i <= 1; i++)
  165. occs[c->lits[i]].bins.push (mem, c->lits[!i]);
  166. } else {
  167. for (int i = 0; i <= 1; i++)
  168. occs[c->lits[i]].large.push (mem, Occ (c->lits[!i], c));
  169. }
  170. if (orgs)
  171. for (const int * p = c->lits; *p; p++)
  172. orgs[*p].push (mem, c);
  173. if (fwds) fwds[c->minlit ()].push (mem, c);
  174. setsig (c);
  175. }
  176. inline void Solver::disconnect (Cls * c) {
  177. assert (!c->locked && !c->dirty && !c->trash);
  178. int l0 = c->lits[0], l1 = c->lits[1];
  179. assert (l0 && l1);
  180. Anchor<Cls> & a = anchor (c);
  181. if (connected (a, c)) dequeue (a, c);
  182. if (c->binary) {
  183. occs[l0].bins.remove(l1);
  184. occs[l1].bins.remove(l0);
  185. } else {
  186. occs[l0].large.remove(Occ(0,c));
  187. occs[l1].large.remove(Occ(0,c));
  188. }
  189. if (fwds) fwds[c->minlit ()].remove (c);
  190. if (!orgs || c->lnd) return;
  191. for (const int * p = c->lits; *p; p++)
  192. orgs[*p].remove (c);
  193. }
  194. inline Rnk * Solver::prb (const Rnk * r) { return prbs + (r - rnks); }
  195. inline Rnk * Solver::rnk (const Var * v) { return rnks + (v - vars); }
  196. inline Var * Solver::var (const Rnk * r) { return vars + (r - rnks); }
  197. inline Val Solver::fixed (int lit) const {
  198. return vars[lit/2].dlevel ? 0 : vals[lit];
  199. }
  200. inline void Solver::collect (Cls * cls) {
  201. assert (!cls->locked && !cls->dirty && !cls->trash && !cls->gate);
  202. if (cls->binary) assert (stats.clauses.bin), stats.clauses.bin--;
  203. else if (cls->lnd) assert (stats.clauses.lnd), stats.clauses.lnd--;
  204. else assert (stats.clauses.orig), stats.clauses.orig--;
  205. if (!cls->lnd) assert (stats.clauses.irr), stats.clauses.irr--;
  206. size_t bytes = cls->bytes ();
  207. #ifdef PRECOCHECK
  208. if (!cls->lnd) {
  209. for (const int * p = cls->lits; *p; p++)
  210. check.push (mem, *p);
  211. check.push (mem, 0);
  212. }
  213. #endif
  214. #ifndef NLOGPRECO
  215. dbgprint ("LOG recycle clause ", cls);
  216. #endif
  217. mem.deallocate (cls, bytes);
  218. stats.collected += bytes;
  219. simplified = true;
  220. }
  221. void Solver::touchblkd (int lit) {
  222. assert (blkmode);
  223. int idx = lit/2, notlit = lit^1;
  224. Var * v = vars + idx;
  225. if (v->type != FREE) return;
  226. assert (!val (lit) && !repr[lit]);
  227. Rnk * r = blks + notlit;
  228. assert (orgs);
  229. int nh = -orgs[lit], oh = r->heat; r->heat = nh;
  230. if (oh == nh && schedule.block.contains (r)) return;
  231. if (oh == nh) LOG ("touchblkd " << notlit << " again " << nh);
  232. else LOG ("touchblkd " << notlit << " from " << oh << " to " << nh);
  233. if (!schedule.block.contains (r)) schedule.block.push (mem, r);
  234. else if (nh > oh) schedule.block.up (r);
  235. else if (nh < oh) schedule.block.down (r);
  236. }
  237. void Solver::touchelim (int lit) {
  238. assert (elimode);
  239. lit &= ~1;
  240. int idx = lit/2;
  241. Var * v = vars + idx;
  242. if (v->type != FREE) return;
  243. assert (!val (lit) && !repr[lit]);
  244. if (idx == elimvar) return;
  245. Rnk * r = elms + idx;
  246. assert (orgs);
  247. int pos = orgs[lit];
  248. int neg = orgs[1^lit];
  249. long long tmp = -(((long long)pos) * (long long) neg);
  250. int nh = (tmp >= INT_MIN) ? (int) tmp : INT_MIN;
  251. int oh = r->heat; r->heat = nh;
  252. if (oh == nh && schedule.elim.contains (r)) return;
  253. if (oh == nh) LOG ("touchelim " << lit << " again " << nh);
  254. else LOG ("touchelim " << lit << " from " << oh << " to " << nh);
  255. if (pos > 1 && neg > 1 && nh <= opts.elimin) {
  256. if (schedule.elim.contains (r)) {
  257. schedule.elim.remove (r);
  258. }
  259. } else if (!schedule.elim.contains (r)) schedule.elim.push (mem, r);
  260. else if (nh > oh) schedule.elim.up (r);
  261. else if (nh < oh) schedule.elim.down (r);
  262. }
  263. void Solver::touchpure (int lit) {
  264. assert (puremode);
  265. int idx = lit/2;
  266. Var * v = vars + idx;
  267. if (v->onplits) return;
  268. LOG ("touchpure " << lit);
  269. v->onplits = true;
  270. plits.push (mem, idx);
  271. }
  272. void Solver::touch (int lit) {
  273. assert (elimode + blkmode == 1);
  274. if (elimode) touchelim (lit);
  275. else touchblkd (lit);
  276. if (puremode) touchpure (lit);
  277. }
  278. void Solver::touch (Cls * c) {
  279. assert (asymode || !c->lnd);
  280. assert (elimode || blkmode);
  281. for (int * p = c->lits; *p; p++)
  282. touch (*p);
  283. }
  284. inline void Solver::recycle (Cls * c) {
  285. stats.clauses.gc++;
  286. disconnect (c);
  287. if (c->trash) trash.remove (c);
  288. if (c->gate) cleangate ();
  289. if (c->str) strnd.remove (c);
  290. if (elimode || blkmode) touch (c);
  291. collect (c);
  292. }
  293. inline void Solver::dump (Cls * c) {
  294. assert (!c->dirty);
  295. if (c->trash) return;
  296. c->trash = true;
  297. trash.push (mem, c);
  298. }
  299. inline void Solver::cleantrash () {
  300. if (!trash) return;
  301. int old = stats.clauses.orig;
  302. while (trash) {
  303. Cls * cls = trash.pop ();
  304. assert (cls->trash);
  305. cls->trash = false;
  306. recycle (cls);
  307. }
  308. shrink (old);
  309. }
  310. inline void Solver::gcls (Cls * c) {
  311. assert (!c->gate);
  312. c->gate = true;
  313. gate.push (mem, c);
  314. }
  315. inline void Solver::strcls (Cls * c) {
  316. assert (!c->str);
  317. c->str = true;
  318. strnd.push (mem, c);
  319. }
  320. inline void Solver::cleangate () {
  321. while (gate) {
  322. Cls * cls = gate.pop ();
  323. assert (cls->gate); cls->gate = false;
  324. }
  325. gatepivot = 0;
  326. gatestats = 0;
  327. gatelen = 0;
  328. }
  329. inline void Solver::recycle (int lit) {
  330. LOG ("recycle literal " << lit);
  331. assert (!level);
  332. #ifndef NDEBUG
  333. Var * v = vars + (lit/2); Vrt t = v->type;
  334. assert (t == FIXED || t == PURE || t == ZOMBIE || t == ELIM);
  335. #endif
  336. if (!orgs) return;
  337. while (int size = orgs[lit]) recycle (orgs[lit][size - 1]);
  338. orgs[lit].release (mem);
  339. occs[lit].bins.release (mem);
  340. occs[lit].large.release (mem);
  341. }
  342. Opt::Opt (const char * n, int v, int * vp, int mi, int ma) :
  343. name (n), valptr (vp), min (mi), max (ma)
  344. {
  345. assert (min <= v);
  346. assert (v <= max);
  347. *vp = v;
  348. }
  349. bool Opts::set (const char * opt, int val) {
  350. for (Opt * o = opts.begin (); o < opts.end (); o++)
  351. if (!strcmp (o->name, opt)) {
  352. if (val < o->min) return false;
  353. if (val > o->max) return false;
  354. *o->valptr = val;
  355. return true;
  356. }
  357. return false;
  358. }
  359. bool Opts::set (const char * opt, const char * val) {
  360. if (strcmp (opt, "output")) return false;
  361. output = val;
  362. return true;
  363. }
  364. void Opts::add (Mem & mem, const char * n, int v, int * vp, int mi, int ma) {
  365. opts.push (mem, Opt (n, v, vp, mi, ma));
  366. }
  367. void Opts::printoptions (FILE * file, const char * prfx) const {
  368. assert (prfx);
  369. int lenprfx = strlen (prfx);
  370. fputs (prfx, file); int pos = 0;
  371. const Opt * o = opts.begin ();
  372. while (o < opts.end ()) {
  373. char line[80];
  374. sprintf (line, " --%s=%d", o->name, *o->valptr);
  375. int len = strlen (line); assert (len < 80);
  376. if (len + pos >= 77 - lenprfx) {
  377. fprintf (file, "\n%s", prfx);
  378. pos = lenprfx;
  379. }
  380. fputs (line, file);
  381. pos += len;
  382. o++;
  383. }
  384. fputc ('\n', file);
  385. if (output)
  386. fprintf (file, "%s\n%s --output=%s\n", prfx, prfx, output);
  387. }
  388. void Solver::initbwsigs () {
  389. assert (!bwsigs);
  390. size_t bytes = 2 * size * sizeof *bwsigs;
  391. bwsigs = (unsigned*) mem.callocate (bytes);
  392. }
  393. void Solver::rszbwsigs (int newsize) {
  394. assert (bwsigs);
  395. size_t old_bytes = 2 * size * sizeof *bwsigs;
  396. size_t new_bytes = 2 * newsize * sizeof *bwsigs;
  397. bwsigs = (unsigned*) mem.recallocate (bwsigs, old_bytes, new_bytes);
  398. }
  399. void Solver::clrbwsigs () {
  400. size_t bytes = 2 * size * sizeof *bwsigs;
  401. memset (bwsigs, 0, bytes);
  402. }
  403. void Solver::delbwsigs () {
  404. size_t bytes = 2 * size * sizeof *bwsigs;
  405. mem.deallocate (bwsigs, bytes);
  406. bwsigs = 0;
  407. }
  408. void Solver::initorgs () {
  409. size_t bytes = 2 * (maxvar + 1) * sizeof *orgs;
  410. orgs = (Orgs*) mem.callocate (bytes);
  411. }
  412. void Solver::delorgs () {
  413. for (int lit = 2; lit <= 2*maxvar+1; lit++) orgs[lit].release (mem);
  414. size_t bytes = 2 * (maxvar + 1) * sizeof *orgs;
  415. mem.deallocate (orgs, bytes);
  416. orgs = 0;
  417. }
  418. void Solver::initfwds () {
  419. size_t bytes = 2 * (maxvar + 1) * sizeof *fwds;
  420. fwds = (Fwds*) mem.callocate (bytes);
  421. }
  422. void Solver::delfwds () {
  423. for (int lit = 2; lit <= 2*maxvar+1; lit++) fwds[lit].release (mem);
  424. size_t bytes = 2 * (maxvar + 1) * sizeof *fwds;
  425. mem.deallocate (fwds, bytes);
  426. fwds = 0;
  427. }
  428. void Solver::initfwsigs () {
  429. assert (!fwsigs);
  430. size_t bytes = 2 * (maxvar + 1) * sizeof *fwsigs;
  431. fwsigs = (unsigned*) mem.callocate (bytes);
  432. }
  433. void Solver::delfwsigs () {
  434. size_t bytes = 2 * (maxvar + 1) * sizeof *fwsigs;
  435. mem.deallocate (fwsigs, bytes);
  436. fwsigs = 0;
  437. }
  438. void Solver::initprfx (const char * newprfx) {
  439. prfx = (char*) mem.allocate (strlen (newprfx) + 1);
  440. strcpy (prfx, newprfx);
  441. }
  442. void Solver::delprfx () {
  443. assert (prfx);
  444. mem.deallocate (prfx, strlen (prfx) + 1);
  445. }
  446. #define OPT(n,v,mi,ma) \
  447. do { opts.add (mem, # n, v, &opts.n, mi, ma); } while (0)
  448. void Solver::initerm (void) {
  449. terminal = (out == stdout) && isatty(1);
  450. }
  451. void Solver::init (int initialmaxvar)
  452. {
  453. maxvar = initialmaxvar;
  454. size = 1;
  455. while (maxvar >= size)
  456. size *= 2;
  457. queue = 0;
  458. queue2 = 0;
  459. level = 0;
  460. conflict = 0;
  461. hinc = 128;
  462. agility = 0;
  463. typecount = 1;
  464. lastype = 0;
  465. out = stdout;
  466. initerm ();
  467. measure = true;
  468. iterating = false;
  469. elimode = false;
  470. blkmode = false;
  471. puremode = false;
  472. asymode = false;
  473. extending = false;
  474. assert (!initialized);
  475. vars = (Var*) mem.callocate (size * sizeof *vars);
  476. for (int i = 1; i <= maxvar; i++)
  477. vars[i].dlevel = -1;
  478. iirfs = 0;
  479. repr = (int*) mem.callocate (2 * size * sizeof *repr);
  480. jwhs = (int*) mem.callocate (2 * size * sizeof *jwhs);
  481. vals = (Val*) mem.callocate (2 * size * sizeof *vals);
  482. occs = (Occs*) mem.callocate (2 * size * sizeof *occs);
  483. rnks = (Rnk*) mem.allocate (size * sizeof *rnks);
  484. prbs = (Rnk*) mem.allocate (size * sizeof *prbs);
  485. elms = (Rnk*) mem.allocate (size * sizeof *elms);
  486. blks = (Rnk*) mem.allocate (2 * size * sizeof *blks);
  487. for (Rnk * p = rnks + maxvar; p > rnks; p--)
  488. p->heat = 0, p->pos = -1, schedule.decide.push (mem, p);
  489. for (Rnk * p = prbs + maxvar; p > prbs; p--) p->heat = 0, p->pos = -1;
  490. for (Rnk * p = elms + maxvar; p > elms; p--) p->heat = 0, p->pos = -1;
  491. for (Rnk * p = blks + 2*maxvar+1; p > blks+1; p--) p->heat = 0, p->pos = -1;
  492. bwsigs = 0;
  493. initbwsigs ();
  494. orgs = 0;
  495. fwds = 0;
  496. fwsigs = 0;
  497. frames.push (mem, Frame (trail));
  498. empty.lits[0] = 0;
  499. dummy.lits[2] = 0;
  500. int m = INT_MIN, M = INT_MAX;
  501. OPT (plain,0,0,1);
  502. OPT (rtc,0,0,2);
  503. OPT (quiet,0,0,1);
  504. OPT (verbose,0,0,2);
  505. OPT (print,0,0,1);
  506. OPT (check,0,0,2);
  507. OPT (order,3,1,9);
  508. OPT (simprd,20,0,M); OPT (simpinc,26,0,100); OPT (simprtc,0,0,2);
  509. OPT (merge,1,0,1);
  510. OPT (dominate,1,0,1);
  511. OPT (maxdoms,5*1000*1000,0,M);
  512. OPT (otfs,1,0,1);
  513. OPT (block,1,0,1);
  514. OPT (blockrtc,0,0,2); OPT (blockimpl,1,0,1);
  515. OPT (blockprd,10,1,M); OPT (blockint,300*1000,0,M);
  516. OPT (blockotfs,1,0,1);
  517. OPT (blockreward,100,0,10000);
  518. OPT (blockboost,3,0,100);
  519. OPT (heatinc,10,0,100);
  520. OPT (luby,1,0,1);
  521. OPT (restart,1,0,1); OPT (restartint,100,1,M);
  522. OPT (restartinner,10,0,1000); OPT (restartouter,10,0,1000);
  523. OPT (rebias,1,0,1); OPT (rebiasint,1000,1,M);
  524. OPT (probe,1,0,1);
  525. OPT (probeint,100*1000,1000,M); OPT (probeprd,10,1,M);
  526. OPT (probertc,0,0,2); OPT (probereward,2000,0,10000);
  527. OPT (probeboost,5,0,10000);
  528. OPT (decompose,1,0,1);
  529. OPT (inverse,0,0,1); OPT (inveager,0,0,1);
  530. OPT (mtfall,0,0,1); OPT (mtfrev,1,0,1);
  531. OPT (bumpuip,1,0,1);
  532. OPT (bumpsort,1,0,1); OPT (bumprev,1,0,1);
  533. OPT (bumpturbo,0,0,1); OPT (bumpbulk,0,0,1);
  534. OPT (fresh,50,0,100);
  535. OPT (glue,Cls::MAXGLUE,0,Cls::MAXGLUE);
  536. OPT (slim,1,0,1); OPT (sticky,1,0,Cls::MAXGLUE);
  537. OPT (redsub,2,0,M);
  538. OPT (minimize,4,0,4); OPT (maxdepth,1000,2,10000); OPT (strength,100,0,M);
  539. OPT (elim,1,0,1);
  540. OPT (elimgain,0,m/2,M/2);
  541. OPT (elimint,300*1000,0,M); OPT (elimprd,20,1,M);
  542. OPT (elimrtc,0,0,2);
  543. OPT (elimin,-10000,-m,M);
  544. OPT (elimclim,20,0,M);
  545. OPT (elimboost,1,0,100);
  546. OPT (elimreward,100,0,10000);
  547. OPT (elimasym,2,1,100);
  548. OPT (elimasymint,100000,100,M);
  549. OPT (elimasymreward,1000,0,M);
  550. OPT (fwmaxlen,100,0,M);OPT (bwmaxlen,1000,0,M); OPT (reslim,20,0,M);
  551. OPT (blkmaxlen,1000,0,M);
  552. OPT (subst,1,0,1); OPT (ands,1,0,1); OPT (xors,1,0,1); OPT (ites,1,0,1);
  553. OPT (minlimit,500,10,10000); OPT (maxlimit,3*1000*1000,100,M);
  554. OPT (dynred,4,-1,100000);
  555. OPT (liminitmode,1,0,1);
  556. OPT (limincmode,0,0,1);
  557. OPT (liminitconst,2000,0,1000*1000);
  558. OPT (liminitmax,20000,0,10*1000*1000);
  559. OPT (liminitpercent,10,0,1000);
  560. OPT (liminconst1,2000,0,100*1000);
  561. OPT (liminconst2,1000,0,100*1000);
  562. OPT (limincpercent,10,0,1000);
  563. OPT (enlinc,20,0,1000);
  564. OPT (shrink,2,0,2); OPT (shrinkfactor,100,1,1000);
  565. OPT (random,1,0,1); OPT (spread,2000,0,M); OPT (seed,0,0,M);
  566. OPT (skip,25,0,100);
  567. opts.set ("output", (const char*) 0);
  568. initprfx ("c ");
  569. initialized = true;
  570. }
  571. void Solver::initiirfs () {
  572. if (opts.order < 2) return;
  573. size_t bytes = size * (opts.order - 1) * sizeof *iirfs;
  574. iirfs = (int *) mem.allocate (bytes);
  575. for (Var * v = vars + 1; v <= vars + maxvar; v++)
  576. for (int i = 1; i < opts.order; i++)
  577. iirf (v, i) = -1;
  578. }
  579. void Solver::rsziirfs (int newsize) {
  580. if (opts.order < 2) return;
  581. size_t old_bytes = size * (opts.order - 1) * sizeof *iirfs;
  582. size_t new_bytes = newsize * (opts.order - 1) * sizeof *iirfs;
  583. iirfs = (int *) mem.reallocate (iirfs, old_bytes, new_bytes);
  584. }
  585. void Solver::deliirfs () {
  586. assert (iirfs);
  587. assert (opts.order >= 2);
  588. size_t bytes = size * (opts.order - 1) * sizeof *iirfs;
  589. mem.deallocate (iirfs, bytes);
  590. iirfs = 0;
  591. }
  592. void Solver::delclauses (Anchor<Cls> & anchor) {
  593. Cls * prev;
  594. for (Cls * p = anchor.head; p; p = prev) {
  595. p->bytes (); prev = p->prev; mem.deallocate (p, p->bytes ());
  596. }
  597. anchor.head = anchor.tail = 0;
  598. }
  599. void Solver::reset () {
  600. assert (initialized);
  601. initialized = false;
  602. #ifndef NDEBUG
  603. delprfx ();
  604. size_t bytes;
  605. for (int lit = 2; lit <= 2 * maxvar + 1; lit++) occs[lit].bins.release (mem);
  606. for (int lit = 2; lit <= 2 * maxvar + 1; lit++) occs[lit].large.release (mem);
  607. bytes = 2 * size * sizeof *occs; mem.deallocate (occs, bytes);
  608. bytes = 2 * size * sizeof *vals; mem.deallocate (vals, bytes);
  609. bytes = 2 * size * sizeof *repr; mem.deallocate (repr, bytes);
  610. bytes = 2 * size * sizeof *jwhs; mem.deallocate (jwhs, bytes);
  611. bytes = 2 * size * sizeof *blks; mem.deallocate (blks, bytes);
  612. bytes = size * sizeof *vars; mem.deallocate (vars, bytes);
  613. bytes = size * sizeof *prbs; mem.deallocate (prbs, bytes);
  614. bytes = size * sizeof *rnks; mem.deallocate (rnks, bytes);
  615. bytes = size * sizeof *elms; mem.deallocate (elms, bytes);
  616. delclauses (original);
  617. delclauses (binary);
  618. for (int glue = 0; glue <= opts.glue; glue++)
  619. delclauses (learned[glue]);
  620. delclauses (fresh);
  621. if (iirfs) deliirfs ();
  622. if (orgs) delorgs ();
  623. if (fwds) delfwds ();
  624. if (bwsigs) delbwsigs ();
  625. if (fwsigs) delfwsigs ();
  626. schedule.block.release (mem);
  627. schedule.elim.release (mem);
  628. schedule.decide.release (mem);
  629. schedule.probe.release (mem);
  630. opts.opts.release (mem);
  631. trail.release (mem);
  632. frames.release (mem);
  633. levels.release (mem);
  634. trash.release (mem);
  635. gate.release (mem);
  636. strnd.release (mem);
  637. saved.release (mem);
  638. elits.release (mem);
  639. plits.release (mem);
  640. #ifdef PRECOCHECK
  641. check.release (mem);
  642. #endif
  643. units.release (mem);
  644. lits.release (mem);
  645. seen.release (mem);
  646. assert (!mem);
  647. #endif
  648. }
  649. void Solver::fxopts () {
  650. assert (!opts.fixed);
  651. opts.fixed = true;
  652. initiirfs ();
  653. if (!opts.plain) return;
  654. opts.merge = 0;
  655. opts.block = 0;
  656. opts.dominate = 0;
  657. opts.rebias = 0;
  658. opts.probe = 0;
  659. opts.decompose = 0;
  660. opts.minimize = 2;
  661. opts.elim = 0;
  662. opts.random = 0;
  663. }
  664. void Solver::propts () {
  665. assert (opts.fixed);
  666. opts.printoptions (out, prfx);
  667. fflush (out);
  668. }
  669. void Solver::prstats () {
  670. double overalltime = stats.seconds ();
  671. fprintf (out, "%s%d conflicts, %d decisions, %d random\n", prfx,
  672. stats.conflicts, stats.decisions, stats.random);
  673. fprintf (out, "%s%d iterations, %d restarts, %d skipped\n", prfx,
  674. stats.iter, stats.restart.count, stats.restart.skipped);
  675. fprintf (out, "%s%d enlarged, %d shrunken, %d rescored, %d rebiased\n", prfx,
  676. stats.enlarged, stats.shrunken, stats.rescored, stats.rebias.count);
  677. fprintf (out, "%s%d simplifications, %d reductions\n", prfx,
  678. stats.simps, stats.reductions);
  679. fprintf (out, "%s\n", prfx);
  680. fprintf (out, "%svars: %d fixed, %d equiv, %d elim, %d pure, %d zombies\n",
  681. prfx,
  682. stats.vars.fixed, stats.vars.equiv,
  683. stats.vars.elim, stats.vars.pure, stats.vars.zombies);
  684. fprintf (out, "%selim: %lld resolutions, %d phases, %d rounds\n", prfx,
  685. stats.elim.resolutions, stats.elim.phases, stats.elim.rounds);
  686. fprintf (out, "%sextd: %d forced, %d assumed, %d flipped\n", prfx,
  687. stats.extend.forced, stats.extend.assumed, stats.extend.flipped);
  688. fprintf (out, "%ssbst: %.0f%% subst, "
  689. "%.1f%% nots, %.1f%% ands, %.1f%% xors, %.1f%% ites\n", prfx,
  690. percent (stats.vars.subst,stats.vars.elim),
  691. percent (stats.subst.nots.count,stats.vars.subst),
  692. percent (stats.subst.ands.count,stats.vars.subst),
  693. percent (stats.subst.xors.count,stats.vars.subst),
  694. percent (stats.subst.ites.count,stats.vars.subst));
  695. fprintf (out, "%sarty: %.2f ands %.2f xors average arity\n", prfx,
  696. average (stats.subst.ands.len, stats.subst.ands.count),
  697. average (stats.subst.xors.len, stats.subst.xors.count));
  698. fprintf (out, "%sprbe: %d probed, %d phases, %d rounds\n", prfx,
  699. stats.probe.variables, stats.probe.phases, stats.probe.rounds);
  700. fprintf (out, "%sprbe: %d failed, %d lifted, %d merged\n", prfx,
  701. stats.probe.failed, stats.probe.lifted, stats.probe.merged);
  702. fprintf (out, "%ssccs: %d non trivial, %d fixed, %d merged\n", prfx,
  703. stats.sccs.nontriv, stats.sccs.fixed, stats.sccs.merged);
  704. #ifndef NSTATSPRECO
  705. long long l1s = stats.sigs.bw.l1.srch + stats.sigs.fw.l1.srch;
  706. long long l1h = stats.sigs.bw.l1.hits + stats.sigs.fw.l1.hits;
  707. long long l2s = stats.sigs.bw.l2.srch + stats.sigs.fw.l2.srch;
  708. long long l2h = stats.sigs.bw.l2.hits + stats.sigs.fw.l2.hits;
  709. long long bws = stats.sigs.bw.l1.srch + stats.sigs.bw.l2.srch;
  710. long long bwh = stats.sigs.bw.l1.hits + stats.sigs.bw.l2.hits;
  711. long long fws = stats.sigs.fw.l1.srch + stats.sigs.fw.l2.srch;
  712. long long fwh = stats.sigs.fw.l1.hits + stats.sigs.fw.l2.hits;
  713. long long hits = bwh + fwh, srch = bws + fws;
  714. if (opts.verbose > 1) {
  715. fprintf (out, "%ssigs: %13lld srch %3.0f%% hits, %3.0f%% L1, %3.0f%% L2\n",
  716. prfx,
  717. srch, percent (hits,srch), percent (l1h,l1s), percent(l2h,l2s));
  718. fprintf (out,
  719. "%s fw: %13lld %3.0f%% %3.0f%% hits, %3.0f%% L1, %3.0f%% L2\n",
  720. prfx,
  721. fws, percent (fws,srch), percent (fwh,fws),
  722. percent (stats.sigs.fw.l1.hits, stats.sigs.fw.l1.srch),
  723. percent (stats.sigs.fw.l2.hits, stats.sigs.fw.l2.srch));
  724. fprintf (out,
  725. "%s bw: %13lld %3.0f%% %3.0f%% hits, %3.0f%% L1, %3.0f%% L2\n",
  726. prfx,
  727. bws, percent (bws,srch), percent (bwh,bws),
  728. percent (stats.sigs.bw.l1.hits, stats.sigs.bw.l1.srch),
  729. percent (stats.sigs.bw.l2.hits, stats.sigs.bw.l2.srch));
  730. } else
  731. fprintf (out,
  732. "%ssigs: %lld searched, %.0f%% hits, %.0f%% L1, %.0f%% L2\n",
  733. prfx,
  734. srch, percent (hits,srch), percent (l1h,l1s), percent(l2h,l2s));
  735. #endif
  736. long long alllits = stats.lits.added + stats.mins.deleted;
  737. fprintf (out,
  738. "%smins: %lld lrnd, %.0f%% del, %lld strng, %lld inv, %d dpth\n",
  739. prfx,
  740. stats.lits.added,
  741. percent (stats.mins.deleted, alllits),
  742. stats.mins.strong, stats.mins.inverse, stats.mins.depth);
  743. fprintf (out,
  744. "%ssubs: %d fw, %d bw, %d dynamic, %d org, %d doms, %d gc\n",
  745. prfx,
  746. stats.subs.fw, stats.subs.bw,
  747. stats.subs.dyn, stats.subs.org,
  748. stats.subs.doms, stats.subs.red);
  749. fprintf (out,
  750. "%sblkd: %lld resolutions, %d phases, %d rounds\n",
  751. prfx,
  752. stats.blkd.resolutions,
  753. stats.blkd.phases, stats.blkd.rounds);
  754. fprintf (out,
  755. "%sblkd: %d = %d implicit + %d explicit\n",
  756. prfx,
  757. stats.blkd.impl + stats.blkd.expl,
  758. stats.blkd.impl, stats.blkd.expl);
  759. assert (stats.vars.pure ==
  760. stats.pure.elim + stats.pure.blkd + stats.pure.expl);
  761. fprintf (out, "%spure: %d = %d explicit + %d elim + %d blkd\n",
  762. prfx,
  763. stats.vars.pure,
  764. stats.pure.expl, stats.pure.elim, stats.pure.blkd);
  765. assert (stats.vars.zombies ==
  766. stats.zombies.elim + stats.zombies.blkd + stats.zombies.expl);
  767. fprintf (out, "%szmbs: %d = %d explicit + %d elim + %d blkd\n",
  768. prfx,
  769. stats.vars.zombies,
  770. stats.zombies.expl, stats.zombies.elim, stats.zombies.blkd);
  771. fprintf (out,
  772. "%sstrs: %d forward, %d backward, %d dynamic, %d org, %d asym\n",
  773. prfx,
  774. stats.str.fw, stats.str.bw, stats.str.dyn,
  775. stats.str.org, stats.str.asym);
  776. fprintf (out, "%sotfs: dynamic %d = %d bin + %d trn + %d large\n",
  777. prfx,
  778. stats.otfs.dyn.bin + stats.otfs.dyn.trn + stats.otfs.dyn.large,
  779. stats.otfs.dyn.bin, stats.otfs.dyn.trn, stats.otfs.dyn.large);
  780. fprintf (out, "%sotfs: static %d = %d bin + %d trn + %d large\n",
  781. prfx,
  782. stats.otfs.stat.bin + stats.otfs.stat.trn + stats.otfs.stat.large,
  783. stats.otfs.stat.bin, stats.otfs.stat.trn, stats.otfs.stat.large);
  784. fprintf (out,
  785. "%sglue: %.2f avg, %lld slimmed = %.2f per conflict\n",
  786. prfx,
  787. average (stats.glue.sum, stats.glue.count),
  788. stats.glue.slimmed,
  789. average (stats.glue.slimmed, stats.conflicts));
  790. assert (stats.doms.count >= stats.doms.level1);
  791. assert (stats.doms.level1 >= stats.doms.probing);
  792. fprintf (out, "%sdoms: %d dominators, %d high, %d low\n", prfx,
  793. stats.doms.count,
  794. stats.doms.count - stats.doms.level1,
  795. stats.doms.level1 - stats.doms.probing);
  796. long long props = stats.props.srch + stats.props.simp;
  797. fprintf (out, "%svsts: %lld visits, %.2f per prop, %.0f%% blkd",
  798. prfx,
  799. stats.visits, average (stats.visits, props),
  800. percent (stats.blocked, stats.visits));
  801. #ifndef NSTATSPRECO
  802. fprintf (out, ", %.0f%% trn",
  803. percent (stats.ternaryvisits, stats.visits));
  804. #endif
  805. fputc ('\n', out);
  806. double othrtime = overalltime - stats.simptime - stats.srchtime;
  807. fprintf (out, "%stime: "
  808. "%.1f = "
  809. "%.1f srch (%.0f%%) + "
  810. "%.1f simp (%.0f%%) + "
  811. "%.1f othr (%.0f%%)\n",
  812. prfx,
  813. overalltime,
  814. stats.srchtime, percent (stats.srchtime, overalltime),
  815. stats.simptime, percent (stats.simptime, overalltime),
  816. othrtime, percent (othrtime, overalltime));
  817. fprintf (out, "%sprps: %lld srch props, %.2f megaprops per second\n",
  818. prfx, stats.props.srch,
  819. (stats.srchtime>0) ? stats.props.srch/1e6/stats.srchtime : 0);
  820. fprintf (out, "%sclss: %d recycled\n", prfx,
  821. stats.clauses.gc);
  822. fprintf (out, "%s\n", prfx);
  823. fprintf (out, "%s%.1f seconds, %.0f MB max, %.0f MB recycled\n", prfx,
  824. overalltime, mb (mem.getMax ()), mb (stats.collected));
  825. fflush (out);
  826. }
  827. inline void Solver::assign (int lit) {
  828. assert (!vals [lit]);
  829. vals[lit] = 1; vals[lit^1] = -1;
  830. Var & v = vars[lit/2];
  831. assert ((v.type == ELIM) == extending);
  832. if (!(v.dlevel = level)) {
  833. if (v.type == EQUIV) {
  834. assert (repr[lit]);
  835. assert (stats.vars.equiv);
  836. stats.vars.equiv--;
  837. stats.vars.fixed++;
  838. v.type = FIXED;
  839. } else {
  840. assert (!repr[lit]);
  841. if (v.type == FREE) {
  842. stats.vars.fixed++;
  843. v.type = FIXED;
  844. } else assert (v.type == ZOMBIE || v.type == PURE);
  845. }
  846. simplified = true;
  847. }
  848. if (measure) {
  849. Val val = lit2val (lit);
  850. agility -= agility/10000;
  851. if (v.phase && v.phase != val) agility += 1000;
  852. v.phase = val;
  853. }
  854. v.tlevel = trail;
  855. trail.push (mem, lit);
  856. #ifndef NLOGPRECO
  857. printf ("%sLOG assign %d at level %d <=", prfx, lit, level);
  858. if (v.binary) printf (" %d %d\n", lit, v.reason.lit);
  859. else if (v.reason.cls)
  860. printf (" %d %d %d%s\n",
  861. v.reason.cls->lits[0],
  862. v.reason.cls->lits[1],
  863. v.reason.cls->lits[2],
  864. v.reason.cls->size > 3 ? " ..." : "");
  865. else if (!level) printf (" top level\n");
  866. else printf (" decision\n");
  867. #endif
  868. }
  869. inline void Solver::assume (int lit, bool inclevel) {
  870. if (inclevel) {
  871. frames.push (mem, Frame (trail));
  872. level++;
  873. LOG ("assume new level " << level);
  874. assert (level + 1 == frames);
  875. LOG ("assuming " << lit);
  876. } else {
  877. assert (!level);
  878. LOG ("permanently assume " << lit << " on top level");
  879. }
  880. Var & v = vars[lit/2]; v.binary = false; v.reason.cls = 0;
  881. v.dominator = lit;
  882. assign (lit);
  883. }
  884. inline void Solver::imply (int lit, int reason) {
  885. assert (lit/2 != reason/2);
  886. assert (vals[reason] < 0);
  887. assert (vars[reason/2].dlevel == level);
  888. Var & v = vars[lit/2];
  889. if (level) v.binary = true, v.reason.lit = reason;
  890. else v.binary = false, v.reason.lit = 0;
  891. if (level) v.dominator = vars[reason/2].dominator;
  892. assign (lit);
  893. }
  894. inline int Solver::dominator (int lit, Cls * reason, bool & contained) {
  895. if (!opts.dominate) return 0;
  896. if (asymode) return 0;
  897. if (opts.maxdoms <= stats.doms.count) return 0;
  898. contained = false;
  899. assert (level > 0);
  900. int vdom = 0, other, oldvdom;
  901. Var * u;
  902. for (const int * p = reason->lits; vdom >= 0 && (other = *p); p++) {
  903. if (other == lit) continue;
  904. u = vars + (other/2);
  905. if (!u->dlevel) continue;
  906. if (u->dlevel < level) { vdom = -1; break; }
  907. int udom = u->dominator;
  908. assert (udom);
  909. if (vdom) {
  910. assert (vdom > 0);
  911. if (udom != vdom) vdom = -1;
  912. } else vdom = udom;
  913. }
  914. assert (vdom);
  915. if (vdom <= 0) return vdom;
  916. assert (vals[vdom] > 0);
  917. LOG (vdom << " dominates " << lit);
  918. for (const int * p = reason->lits; !contained && (other = *p); p++)
  919. contained = (other^1) == vdom;
  920. if (contained) goto DONE;
  921. oldvdom = vdom; vdom = 0;
  922. for (const int * p = reason->lits; (other = *p); p++) {
  923. if (other == lit) continue;
  924. assert (vals[other] < 0);
  925. u = vars + other/2;
  926. if (!u->dlevel) continue;
  927. assert (u->dlevel == level);
  928. assert (u->dominator == oldvdom);
  929. other ^= 1;
  930. assert (other != oldvdom);
  931. if (other == vdom) continue;
  932. if (vdom) {
  933. while (!u->mark &&
  934. (other = (assert (u->binary), 1^u->reason.lit)) != oldvdom &&
  935. other != vdom) {
  936. assert (vals[other] > 0);
  937. u = vars + other/2;
  938. assert (u->dlevel == level);
  939. assert (u->dominator == oldvdom);
  940. }
  941. while (vdom != other) {
  942. u = vars + (vdom/2);
  943. assert (u->mark);
  944. u->mark = 0;
  945. assert (u->binary);
  946. vdom = 1^u->reason.lit;
  947. }
  948. if (vdom == oldvdom) break;
  949. } else {
  950. vdom = 1^u->reason.lit;
  951. if (vdom == oldvdom) break;
  952. assert (vals[vdom] > 0);
  953. other = vdom;
  954. do {
  955. u = vars + other/2;
  956. assert (u->dlevel == level);
  957. assert (u->dominator == oldvdom);
  958. assert (!u->mark);
  959. u->mark = 1;
  960. assert (u->binary);
  961. other = 1^u->reason.lit;
  962. assert (vals[other] > 0);
  963. } while (other != oldvdom);
  964. }
  965. }
  966. other = vdom;
  967. while (other != oldvdom) {
  968. u = vars + other/2;
  969. assert (u->dlevel == level);
  970. assert (u->dominator == oldvdom);
  971. assert (u->mark);
  972. u->mark = 0;
  973. assert (u->binary);
  974. other = 1^u->reason.lit;
  975. assert (vals[other] > 0);
  976. }
  977. if (vdom == oldvdom) goto DONE;
  978. assert (vdom);
  979. LOG (vdom << " also dominates " << lit);
  980. assert (!contained);
  981. for (const int * p = reason->lits; !contained && (other = *p); p++)
  982. contained = (other^1) == vdom;
  983. DONE:
  984. stats.doms.count++;
  985. if (level == 1) stats.doms.level1++;
  986. if (!measure) { assert (level == 1); stats.doms.probing++; }
  987. if (contained) {
  988. reason->garbage = true;
  989. stats.subs.doms++;
  990. LOG ("dominator clause is subsuming");
  991. }
  992. return vdom;
  993. }
  994. inline void Solver::unit (int lit) {
  995. Var * v;
  996. Val val = vals[lit];
  997. assert (!level);
  998. if (val < 0) {
  999. LOG ("conflict after adding unit"); conflict = &empty; return;
  1000. }
  1001. if (!val) {
  1002. v = vars + (lit/2);
  1003. v->binary = false, v->reason.cls = 0;
  1004. assign (lit);
  1005. }
  1006. int other = find (lit);
  1007. if (other == lit) return;
  1008. val = vals[other];
  1009. if (val < 0) {
  1010. LOG ("conflict after adding unit"); conflict = &empty; return;
  1011. }
  1012. if (val) return;
  1013. v = vars + (other/2);
  1014. v->binary = false, v->reason.cls = 0;
  1015. assign (other);
  1016. }
  1017. inline unsigned Solver::gluelits () {
  1018. const int * eol = lits.end ();
  1019. int lit, found = 0;
  1020. unsigned res = 0;
  1021. assert (uip);
  1022. for (const int * p = lits.begin (); p < eol; p++) {
  1023. lit = *p;
  1024. assert (val (lit) < 0);
  1025. Var * v = vars + (lit/2);
  1026. int dlevel = v->dlevel;
  1027. if (dlevel == level) { assert (!found); found = lit; continue; }
  1028. assert (dlevel > 0);
  1029. Frame * f = &frames[dlevel];
  1030. if (f->contained) continue;
  1031. f->contained = true;
  1032. res++;
  1033. }
  1034. assert (found == uip);
  1035. for (const int * p = lits.begin (); p < eol; p++)
  1036. frames[vars[*p/2].dlevel].contained = false;
  1037. return res;
  1038. }
  1039. inline void Solver::slim (Cls * cls) {
  1040. if (!opts.slim) return;
  1041. if (!level) return;
  1042. assert (cls);
  1043. if (!cls->lnd) return;
  1044. assert (!cls->binary);
  1045. unsigned oldglue = cls->glue;
  1046. if (!oldglue) return;
  1047. const int * p = cls->lits;
  1048. unsigned newglue = 0;
  1049. int lit, nonfalse = 0;
  1050. while ((lit = *p++)) {
  1051. Val val = vals[lit];
  1052. if (val >= 0 && nonfalse++) { newglue = oldglue; break; }
  1053. Var * v = vars + (lit/2);
  1054. int dlevel = v->dlevel;
  1055. if (dlevel <= 0) continue;
  1056. assert (dlevel < frames);
  1057. Frame * f = &frames[dlevel];
  1058. if (f->contained) continue;
  1059. if (++newglue >= oldglue) break;
  1060. f->contained = true;
  1061. }
  1062. while (p > cls->lits) {
  1063. lit = *--p;
  1064. if (!lit) continue;
  1065. Var * v = vars + (lit/2);
  1066. int dlevel = v->dlevel;
  1067. if (dlevel <= 0) continue;
  1068. assert (dlevel < frames);
  1069. Frame * f = &frames[dlevel];
  1070. f->contained = false;
  1071. }
  1072. if (cls->glued) {
  1073. assert (oldglue >= newglue);
  1074. if (oldglue == newglue) return;
  1075. assert (newglue >= 1);
  1076. LOG ("slimmed glue from " << oldglue << " to " << newglue);
  1077. } else LOG ("new glue " << newglue);
  1078. assert (newglue <= (unsigned) opts.glue);
  1079. if (!cls->fresh) dequeue (anchor (cls), cls);
  1080. cls->glue = newglue;
  1081. if (!cls->fresh) push (anchor (cls), cls);
  1082. if (cls->glued) stats.glue.slimmed++;
  1083. stats.glue.count++;
  1084. stats.glue.sum += newglue;
  1085. cls->glued = true;
  1086. }
  1087. inline void Solver::force (int lit, Cls * reason) {
  1088. assert (reason);
  1089. assert (!reason->binary);
  1090. Val val = vals[lit];
  1091. if (val < 0) { LOG ("conflict forcing literal"); conflict = reason; }
  1092. if (val) return;
  1093. #ifndef NDEBUG
  1094. for (const int * p = reason->lits; *p; p++)
  1095. if (*p != lit) assert (vals[*p] < 0);
  1096. #endif
  1097. Var * v = vars + (lit/2);
  1098. int vdom;
  1099. bool sub;
  1100. if (!level) {
  1101. v->binary = false, v->reason.cls = 0;
  1102. } else if (!lits && (vdom = dominator (lit, reason, sub)) > 0) {
  1103. v->dominator = vdom;
  1104. assert (vals[vdom] > 0);
  1105. vdom ^= 1;
  1106. LOG ("dominating learned clause " << vdom << ' ' << lit);
  1107. assert (!lits);
  1108. lits.push (mem, vdom);
  1109. lits.push (mem, lit);
  1110. bool lnd = reason->lnd || !sub;
  1111. clause (lnd, lnd);
  1112. v->binary = true, v->reason.lit = vdom;
  1113. } else {
  1114. v->binary = false, v->reason.cls = reason;
  1115. reason->locked = true;
  1116. if (reason->lnd) stats.clauses.lckd++;
  1117. v->dominator = lit;
  1118. }
  1119. assign (lit);
  1120. }
  1121. inline void Solver::jwh (Cls * cls) {
  1122. //if (cls->lnd) return; // TODO better not ?
  1123. int * p;
  1124. for (p = cls->lits; *p; p++)
  1125. ;
  1126. int size = p - cls->lits;
  1127. int inc = logsize (size);
  1128. while (p > cls->lits) {
  1129. int l = *--p;
  1130. jwhs[l] += inc;
  1131. if (jwhs[l] < 0) die ("maximum large JWH score exceeded");
  1132. }
  1133. }
  1134. int Solver::find (int a) {
  1135. assert (2 <= a && a <= 2 * maxvar + 1);
  1136. int res, tmp;
  1137. for (res = a; (tmp = repr[res]); res = tmp)
  1138. ;
  1139. for (int fix = a; (tmp = repr[fix]) && tmp != res; fix = tmp)
  1140. repr[fix] = res, repr[fix^1] = res^1;
  1141. return res;
  1142. }
  1143. inline void Solver::merge (int l, int k, int & merged) {
  1144. int a, b;
  1145. if (!opts.merge) return;
  1146. assert (!elimode);
  1147. assert (!blkmode);
  1148. if ((a = find (l)) == (b = find (k))) return;
  1149. assert (a/2 != b/2);
  1150. #ifndef NLOGPRECO
  1151. int m = min (a, b);
  1152. LOG ("merge " << l << " and " << k << " to " << m);
  1153. if (k != m) LOG ("learned clause " << k << ' ' << (m^1));
  1154. if (k != m) LOG ("learned clause " << (k^1) << ' ' << m);
  1155. if (l != m) LOG ("learned clause " << l << ' ' << (m^1));
  1156. if (l != m) LOG ("learned clause " << (l^1) << ' ' << m);
  1157. #endif
  1158. if (a < b) repr[k] = repr[b] = a, repr[k^1] = repr[b^1] = a^1;
  1159. else repr[l] = repr[a] = b, repr[l^1] = repr[a^1] = b^1;
  1160. assert (vars[a/2].type == FREE && vars[b/2].type == FREE);
  1161. vars[max (a,b)/2].type = EQUIV;
  1162. stats.vars.merged++;
  1163. stats.vars.equiv++;
  1164. simplified = true;
  1165. merged++;
  1166. }
  1167. Cls * Solver::clause (bool lnd, unsigned glue) {
  1168. assert (asymode || !elimode || !lnd);
  1169. assert (lnd || !glue);
  1170. Cls * res = 0;
  1171. #ifndef NLOGPRECO
  1172. std::cout << prfx << "LOG " << (lnd ? "learned" : "original") << " clause";
  1173. for (const int * p = lits.begin (); p < lits.end (); p++)
  1174. std::cout << ' ' << *p;
  1175. std::cout << std::endl;
  1176. #endif
  1177. #ifndef NDEBUG
  1178. for (int i = 0; i < lits; i++)
  1179. assert (vars[lits[i]/2].type != ELIM);
  1180. #endif
  1181. if (lits == 0) {
  1182. LOG ("conflict after added empty clause");
  1183. conflict = &empty;
  1184. } else if (lits == 1) {
  1185. int lit = lits[0];
  1186. Val val;
  1187. if ((val = vals[lit]) < 0) {
  1188. LOG ("conflict after adding falsified unit clause");
  1189. conflict = &empty;
  1190. } else if (!val) unit (lit);
  1191. } else {
  1192. if (lits >= (int)Cls::MAXSZ) die ("maximal clause size exceeded");
  1193. size_t bytes = Cls::bytes (lits);
  1194. res = (Cls *) mem.callocate (bytes);
  1195. res->lnd = lnd;
  1196. if (!lnd) stats.clauses.irr++;
  1197. res->size = lits;
  1198. int * q = res->lits, * eol = lits.end ();
  1199. for (const int * p = lits.begin (); p < eol; p++)
  1200. *q++ = *p;
  1201. *q = 0;
  1202. if (lits == 2) res->binary = true, stats.clauses.bin++;
  1203. else {
  1204. res->glue = min ((unsigned)opts.glue,glue);
  1205. res->fresh = res->lnd;
  1206. if (lnd) stats.clauses.lnd++;
  1207. else stats.clauses.orig++;
  1208. }
  1209. connect (res);
  1210. }
  1211. lits.shrink ();
  1212. simplified = true;
  1213. return res;
  1214. }
  1215. inline void Solver::marklits () {
  1216. for (const int * p = lits.begin (); p < lits.end (); p++)
  1217. vars[*p/2].mark = lit2val (*p);
  1218. }
  1219. inline void Solver::unmarklits () {
  1220. for (const int * p = lits.begin (); p < lits.end (); p++)
  1221. vars[*p/2].mark = 0;
  1222. }
  1223. inline bool Solver::bwsub (unsigned sig, Cls * c) {
  1224. assert (!c->trash && !c->dirty && !c->garbage);
  1225. limit.budget.bw.sub--;
  1226. int count = lits;
  1227. if (c->size < (unsigned) count) return false;
  1228. INC (sigs.bw.l1.srch);
  1229. if (!sigsubs (sig, c->sig)) { INC (sigs.bw.l1.hits); return false; }
  1230. int lit;
  1231. for (int * p = c->lits; count && (lit = *p); p++) {
  1232. Val u = lit2val (lit), v = vars[lit/2].mark;
  1233. if (u == v) count--;
  1234. }
  1235. return !count;
  1236. }
  1237. int Solver::bwstr (unsigned sig, Cls * c) {
  1238. assert (!c->trash && !c->dirty && !c->garbage);
  1239. limit.budget.bw.str--;
  1240. int count = lits;
  1241. if (c->size < (unsigned) count) return 0;
  1242. INC (sigs.bw.l1.srch);
  1243. if (!sigsubs (sig, c->sig)) { INC (sigs.bw.l1.hits); return 0; }
  1244. int lit, res = 0;
  1245. for (int * p = c->lits; count && (lit = *p); p++) {
  1246. Val u = lit2val (lit), v = vars[lit/2].mark;
  1247. if (abs (u) != abs (v)) continue;
  1248. if (u == -v) { if (res) return 0; res = lit; }
  1249. count--;
  1250. }
  1251. assert (count >= 0);
  1252. res = count ? 0 : res;
  1253. return res;
  1254. }
  1255. void Solver::remove (int del, Cls * c) {
  1256. assert (!c->trash && !c->garbage && !c->dirty && !c->gate);
  1257. assert (c->lits[0] && c->lits[1]);
  1258. if (c->binary) {
  1259. int pos = (c->lits[1] == del);
  1260. assert (c->lits[pos] == del);
  1261. LOG ("will not remove " << del << " but will simply produce unit instead");
  1262. unit (c->lits[!pos]);
  1263. } else {
  1264. disconnect (c);
  1265. int * p = c->lits, lit;
  1266. while ((lit = *p) != del) assert (lit), p++;
  1267. while ((lit = *++p)) p[-1] = lit;
  1268. p[-1] = 0;
  1269. assert (p - c->lits >= 3);
  1270. if (p - c->lits == 3) {
  1271. if (c->lnd) {
  1272. assert (stats.clauses.lnd > 0);
  1273. stats.clauses.lnd--;
  1274. } else {
  1275. assert (stats.clauses.orig > 0);
  1276. stats.clauses.orig--;
  1277. }
  1278. c->binary = true;
  1279. stats.clauses.bin++;
  1280. }
  1281. setsig (c);
  1282. connect (c);
  1283. if (elimode || blkmode) touch (del);
  1284. simplified = true;
  1285. #ifndef NLOGPRECO
  1286. LOG ("removed " << del << " and got");
  1287. dbgprint ("LOG learned clause ", c);
  1288. #endif
  1289. }
  1290. }
  1291. void Solver::bworgs () {
  1292. if (lits <= 1) return;
  1293. limit.budget.bw.str += 2;
  1294. limit.budget.bw.sub += 4;
  1295. marklits ();
  1296. int first = 0;
  1297. int minlen = INT_MAX;
  1298. for (int i = 0; i < lits; i++) {
  1299. int other = lits[i];
  1300. int len = orgs[other];
  1301. if (len < minlen) first = other, minlen = len;
  1302. }
  1303. unsigned sig = litsig ();
  1304. assert (first);
  1305. INC (sigs.bw.l2.srch);
  1306. if (!sigsubs (sig, bwsigs[first])) INC (sigs.bw.l2.hits);
  1307. else if (orgs[first] <= opts.bwmaxlen)
  1308. for (int i = 0; limit.budget.bw.sub >= 0 && i < orgs[first]; i++) {
  1309. Cls * other = orgs[first][i];
  1310. assert (!other->locked);
  1311. if (other->trash || other->dirty || other->garbage) continue;
  1312. if (!bwsub (sig, other)) continue;
  1313. #ifndef NLOGPRECO
  1314. dbgprint ("LOG static backward subsumed clause ", other);
  1315. #endif
  1316. stats.subs.bw++;
  1317. limit.budget.bw.sub += 12;
  1318. dump (other);
  1319. }
  1320. int second = 0;
  1321. minlen = INT_MAX;
  1322. for (int i = 0; i < lits; i++) {
  1323. int other = lits[i];
  1324. if (other == first) continue;
  1325. int len = orgs[other];
  1326. if (len < minlen) second = other, minlen = len;
  1327. }
  1328. assert (second);
  1329. if (orgs[first^1] < minlen) second = (first^1);
  1330. for (int round = 0; round <= 1; round++) {
  1331. int start = round ? second : first;
  1332. INC (sigs.bw.l2.srch);
  1333. if (!sigsubs (sig, bwsigs[start])) { INC (sigs.bw.l2.hits); continue; }
  1334. Orgs & org = orgs[start];
  1335. if (org > opts.bwmaxlen) continue;
  1336. for (int i = 0; limit.budget.bw.str >= 0 && i < org; i++) {
  1337. Cls * other = org[i];
  1338. assert (!other->locked);
  1339. if (other->trash || other->dirty || other->garbage) continue;
  1340. int del = bwstr (sig, other);
  1341. if (!del) continue;
  1342. LOG ("static backward strengthened clause by removing " << del);
  1343. stats.str.bw++;
  1344. limit.budget.bw.str += 10;
  1345. remove (del, other);
  1346. assert (litsig () == sig);
  1347. }
  1348. }
  1349. unmarklits ();
  1350. }
  1351. void Solver::bwoccs (bool & lnd) {
  1352. if (lits <= 1) return;
  1353. limit.budget.bw.sub += lnd ? 30 : 10;
  1354. limit.budget.bw.str += lnd ? 20 : 8;
  1355. marklits ();
  1356. unsigned sig = litsig ();
  1357. for (int i = 0; i < lits; i++) {
  1358. int first = lits[i];
  1359. if (limit.budget.bw.sub >= 0) {
  1360. INC (sigs.bw.l2.srch);
  1361. if (!sigsubs (sig, bwsigs[first])) INC (sigs.bw.l2.hits);
  1362. else if (occs[first].large <= opts.bwmaxlen) {
  1363. for (int i = 0;
  1364. limit.budget.bw.sub >= 0 && i < occs[first].large; i++) {
  1365. Cls * other = occs[first].large[i].cls;
  1366. assert (!other->dirty && !other->trash);
  1367. if (other->garbage) continue;
  1368. if (!bwsub (sig, other)) continue;
  1369. if (!other->lnd && lnd) lnd = false;
  1370. LOG ((level ? "dynamic" : "static")
  1371. << " backward subsumed "
  1372. << (other->lnd ? "learned" : "original")
  1373. << " clause");
  1374. #ifndef NLOGPRECO
  1375. {
  1376. std::cout << prfx << "LOG subsumed clause";
  1377. for (const int * p = other->lits; *p; p++)
  1378. std::cout << ' ' << *p;
  1379. std::cout << std::endl;
  1380. }
  1381. #endif
  1382. if (level) {
  1383. stats.subs.dyn++;
  1384. if (!other->lnd) stats.subs.org++;
  1385. } else stats.subs.bw++;
  1386. limit.budget.bw.sub += 20;
  1387. if (other->locked) other->garbage = true; else recycle (other);
  1388. }
  1389. }
  1390. }
  1391. if (limit.budget.bw.str >= 0) {
  1392. INC (sigs.bw.l2.srch);
  1393. if (!sigsubs (sig, bwsigs[first])) INC (sigs.bw.l2.hits);
  1394. else if (occs[first].large <= opts.bwmaxlen) {
  1395. for (int i = 0;
  1396. limit.budget.bw.sub >= 0 && i < occs[first].large;
  1397. i++) {
  1398. Cls* other = occs[first].large[i].cls;
  1399. assert (!other->dirty && !other->trash);
  1400. if (other->locked || other->garbage) continue;
  1401. int del = bwstr (sig, other);
  1402. if (!del) continue;
  1403. LOG ((level ? "dynamic" : "static")
  1404. << " backward strengthened "
  1405. << (other->lnd ? "learned" : "original")
  1406. << " clause by removing "
  1407. << del);
  1408. #ifndef NLOGPRECO
  1409. {
  1410. std::cout << prfx << "LOG strengthened clause";
  1411. for (const int * p = other->lits; *p; p++)
  1412. std::cout << ' ' << *p;
  1413. std::cout << std::endl;
  1414. }
  1415. #endif
  1416. if (level) {
  1417. stats.str.dyn++;
  1418. if (!other->lnd) stats.str.org++;
  1419. } else stats.str.bw++;
  1420. limit.budget.bw.str += 15;
  1421. remove (del, other);
  1422. if (level) strcls (other);
  1423. }
  1424. }
  1425. }
  1426. }
  1427. unmarklits ();
  1428. }
  1429. inline bool Solver::fwsub (unsigned sig, Cls * c) {
  1430. assert (!c->trash && !c->dirty && !c->garbage);
  1431. limit.budget.fw.sub--;
  1432. INC (sigs.fw.l1.srch);
  1433. if (!sigsubs (c->sig, sig)) { INC (sigs.fw.l1.hits); return false; }
  1434. int lit;
  1435. for (const int * p = c->lits; (lit = *p); p++) {
  1436. Val u = lit2val (lit), v = vars[lit/2].mark;
  1437. if (u != v) return false;
  1438. }
  1439. return true;
  1440. }
  1441. inline int Solver::fwstr (unsigned sig, Cls * c) {
  1442. assert (!c->trash && !c->dirty && !c->garbage);
  1443. limit.budget.fw.str--;
  1444. INC (sigs.fw.l1.srch);
  1445. if (!sigsubs (c->sig, sig)) { INC (sigs.fw.l1.hits); return 0; }
  1446. int res = 0, lit;
  1447. for (const int * p = c->lits; (lit = *p); p++) {
  1448. Val u = lit2val (lit), v = vars[lit/2].mark;
  1449. if (u == v) continue;
  1450. if (u != -v) return 0;
  1451. if (res) return 0;
  1452. res = (lit^1);
  1453. }
  1454. return res;
  1455. }
  1456. bool Solver::fworgs () {
  1457. if (lits <= 1) return false;
  1458. limit.budget.fw.str += 3;
  1459. limit.budget.fw.sub += 5;
  1460. assert (fwds);
  1461. marklits ();
  1462. unsigned sig = litsig ();
  1463. bool res = false;
  1464. if (lits >= 2) {
  1465. for (int i = 0; !res && limit.budget.fw.sub >= 0 && i < lits; i++) {
  1466. int lit = lits[i];
  1467. INC (sigs.fw.l2.srch);
  1468. if (!(fwsigs[lit] & sig)) { INC (sigs.fw.l2.hits); continue; }
  1469. Fwds & f = fwds[lit];
  1470. if (f > opts.fwmaxlen) continue;
  1471. for (int j = 0; !res && limit.budget.fw.sub >= 0 && j < f; j++) {
  1472. Cls * c = f[j];
  1473. if (c->trash || c->dirty || c->garbage) continue;
  1474. res = fwsub (sig, c);
  1475. }
  1476. }
  1477. if (res) {
  1478. LOG ("new clause is subsumed");
  1479. stats.subs.fw++;
  1480. limit.budget.fw.sub += 5;
  1481. }
  1482. }
  1483. if (!res)
  1484. for (int sign = 0; sign <= 1; sign++)
  1485. for (int i = 0; limit.budget.fw.str >= 0 && i < lits; i++) {
  1486. int lit = lits[i];
  1487. INC (sigs.fw.l2.srch);
  1488. if (!(fwsigs[lit] & sig)) { INC (sigs.fw.l2.hits); continue; }
  1489. lit ^= sign;
  1490. Fwds & f = fwds[lit];
  1491. if (f > opts.fwmaxlen) continue;
  1492. int del = 0;
  1493. for (int j = 0; !del && limit.budget.fw.str >= 0 && j < f; j++) {
  1494. Cls * c = f[j];
  1495. if (c->trash || c->dirty || c->garbage) continue;
  1496. del = fwstr (sig, c);
  1497. }
  1498. if (!del) continue;
  1499. assert (sign || del/2 != lit/2);
  1500. LOG ("strengthen new clause by removing " << del);
  1501. stats.str.fw++;
  1502. limit.budget.fw.str += 8;
  1503. assert (vars[del/2].mark == lit2val (del));
  1504. vars[del/2].mark = 0;
  1505. lits.remove (del);
  1506. sig = litsig ();
  1507. i = -1;
  1508. }
  1509. unmarklits ();
  1510. return res;
  1511. }
  1512. void Solver::resize (int newmaxvar) {
  1513. assert (maxvar < size);
  1514. assert (newmaxvar > maxvar);
  1515. int newsize = size;
  1516. while (newsize <= newmaxvar)
  1517. newsize *= 2;
  1518. if (newsize > size) {
  1519. size_t o, n;
  1520. o = size * sizeof * vars;
  1521. n = newsize * sizeof * vars;
  1522. vars = (Var *) mem.recallocate (vars, o, n);
  1523. o = 2 * size * sizeof *repr;
  1524. n = 2 * newsize * sizeof *repr;
  1525. repr = (int*) mem.recallocate (repr, o, n);
  1526. o = 2 * size * sizeof *jwhs;
  1527. n = 2 * newsize * sizeof *jwhs;
  1528. jwhs = (int*) mem.recallocate (jwhs, o, n);
  1529. o = 2 * size * sizeof *vals;
  1530. n = 2 * newsize * sizeof *vals;
  1531. vals = (Val*) mem.recallocate (vals, o, n);
  1532. o = 2 * size * sizeof *occs;
  1533. n = 2 * newsize * sizeof *occs;
  1534. occs = (Occs*) mem.recallocate (occs, o, n);
  1535. ptrdiff_t diff;
  1536. char * c;
  1537. o = size * sizeof *rnks;
  1538. n = newsize * sizeof *rnks;
  1539. c = (char *) rnks;
  1540. rnks = (Rnk*) mem.reallocate (rnks, o, n);
  1541. diff = c - (char *) rnks;
  1542. schedule.decide.fix (diff);
  1543. o = size * sizeof *prbs;
  1544. n = newsize * sizeof *prbs;
  1545. c = (char *) prbs;
  1546. prbs = (Rnk*) mem.reallocate (prbs, o, n);
  1547. diff = c - (char *) prbs;
  1548. schedule.probe.fix (diff);
  1549. o = size * sizeof *elms;
  1550. n = newsize * sizeof *elms;
  1551. c = (char *) elms;
  1552. elms = (Rnk*) mem.reallocate (elms, o, n);
  1553. diff = c - (char *) elms;
  1554. schedule.elim.fix (diff);
  1555. rszbwsigs (newsize);
  1556. rsziirfs (newsize);
  1557. size = newsize;
  1558. }
  1559. assert (newmaxvar < size);
  1560. while (maxvar < newmaxvar) {

Large files files are truncated, but you can click here to view the full file