1 /*-------------------------------------------------------------------------*/
2 /* Copyright 2010-2015 Armin Biere Johannes Kepler University Linz Austria */
3 /*-------------------------------------------------------------------------*/
4 
5 #include "lglib.h"
6 
7 /*------------------------------------------------------------------------*/
8 
9 #include "lglconst.h"
10 #include "lglopts.h"
11 
12 /*-------------------------------------------------------------------------*/
13 
14 #include <assert.h>
15 #include <ctype.h>
16 #include <limits.h>
17 #include <math.h>
18 #include <stdarg.h>
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/resource.h>
24 #include <sys/time.h>
25 #include <unistd.h>
26 
27 /*-------------------------------------------------------------------------*/
28 
29 #define NLGLYALSAT // MS: what the hack is yals?
30 
31 #ifndef NLGLYALSAT
32 #include "yals.h"
33 #endif
34 
35 #define NLGLDRUPLIG // MS: what the hack is druplig?
36 
37 #ifndef NLGLDRUPLIG
38 #include "druplig.h"
39 #endif
40 
41 /*------------------------------------------------------------------------*/
42 #ifndef NLGLOG
43 /*------------------------------------------------------------------------*/
44 
45 #define MAPLOGLEVEL(LEVEL) (LEVEL)
46 
47 #define LOG(LEVEL,FMT,ARGS...) \
48 do { \
49   if (MAPLOGLEVEL(LEVEL) > lgl->opts->log.val) break; \
50   lglogstart (lgl, MAPLOGLEVEL(LEVEL), FMT, ##ARGS); \
51   lglogend (lgl); \
52 } while (0)
53 
54 #define LOGCLS(LEVEL,CLS,FMT,ARGS...) \
55 do { \
56   const int * P; \
57   if (MAPLOGLEVEL(LEVEL) > lgl->opts->log.val) break; \
58   lglogstart (lgl, MAPLOGLEVEL(LEVEL), FMT, ##ARGS); \
59   for (P = (CLS); *P; P++) fprintf (lgl->out, " %d", *P); \
60   lglogend (lgl); \
61 } while (0)
62 
63 #define LOGMCLS(LEVEL,CLS,FMT,ARGS...) \
64 do { \
65   const int * P; \
66   if (MAPLOGLEVEL(LEVEL) > lgl->opts->log.val) break; \
67   lglogstart (lgl, MAPLOGLEVEL(LEVEL), FMT, ##ARGS); \
68   for (P = (CLS); *P; P++) fprintf (lgl->out, " %d", lglm2i (lgl, *P)); \
69   lglogend (lgl); \
70 } while (0)
71 
72 #define LOGRESOLVENT(LEVEL,FMT,ARGS...) \
73 do { \
74   const int * P; \
75   if (MAPLOGLEVEL(LEVEL) > lgl->opts->log.val) break; \
76   lglogstart (lgl, MAPLOGLEVEL(LEVEL), FMT, ##ARGS); \
77   for (P = lgl->resolvent.start; P < lgl->resolvent.top; P++) \
78     fprintf (lgl->out, " %d", *P); \
79   lglogend (lgl); \
80 } while (0)
81 
82 #define LOGREASON(LEVEL,LIT,REASON0,REASON1,FMT,ARGS...) \
83 do { \
84   int TAG, TMP, RED, G; \
85   const int * C, * P; \
86   if (MAPLOGLEVEL(LEVEL) > lgl->opts->log.val) break; \
87   lglogstart (lgl, MAPLOGLEVEL(LEVEL), FMT, ##ARGS); \
88   TMP = ((REASON0) >> RMSHFT); \
89   RED = ((REASON0) & REDCS); \
90   TAG = ((REASON0) & MASKCS); \
91   if (TAG == DECISION) fputs (" decision", lgl->out); \
92   else if (TAG == UNITCS) fprintf (lgl->out, " unit %d", (LIT)); \
93   else if (TAG == BINCS) { \
94     fprintf (lgl->out, \
95        " %s binary clause %d %d", lglred2str (RED), (LIT), TMP); \
96   } else if (TAG == TRNCS) { \
97     fprintf (lgl->out, " %s ternary clause %d %d %d", \
98 	    lglred2str (RED), (LIT), TMP, (REASON1)); \
99   } else { \
100     assert (TAG == LRGCS); \
101     C = lglidx2lits (lgl, RED, (REASON1)); \
102     for (P = C; *P; P++) \
103       ; \
104     fprintf (lgl->out, " size %ld", (long)(P - C)); \
105     if (RED) { \
106       G = ((REASON1) & GLUEMASK); \
107       fprintf (lgl->out, " glue %d redundant", G); \
108     } else fputs (" irredundant", lgl->out); \
109     fputs (" clause", lgl->out); \
110     for (P = C; *P; P++) { \
111       fprintf (lgl->out, " %d", *P); \
112     } \
113   } \
114   lglogend (lgl); \
115 } while (0)
116 
117 #define LOGDSCHED(LEVEL,LIT,FMT,ARGS...) \
118   do { \
119     int POS; \
120     if (MAPLOGLEVEL(LEVEL) > lgl->opts->log.val) break; \
121     POS = *lgldpos (lgl, LIT); \
122     lglogstart (lgl, MAPLOGLEVEL(LEVEL), "dsched[%d] = %d ", POS, LIT); \
123     fprintf (lgl->out, FMT, ##ARGS); \
124     fprintf (lgl->out, \
125       " score %s", lglscr2str (lgl, lglqvar (lgl, LIT)->score)); \
126     lglogend (lgl); \
127   } while (0)
128 
129 #define LOGESCHED(LEVEL,LIT,FMT,ARGS...) \
130 do { \
131   int POS; \
132   EVar * EV; \
133   if (MAPLOGLEVEL(LEVEL) > lgl->opts->log.val) break; \
134   POS = *lglepos (lgl, LIT); \
135   EV = lglevar (lgl, LIT); \
136   lglogstart (lgl, MAPLOGLEVEL(LEVEL), "esched[%d] = %d ", POS, LIT); \
137   fprintf (lgl->out, FMT, ##ARGS); \
138   fprintf (lgl->out, " score"); \
139   fprintf (lgl->out, " occ %d %d", EV->occ[0], EV->occ[1]); \
140   lglogend (lgl); \
141 } while (0)
142 
143 #define LOGEQN(LEVEL,EQN,FMT,ARGS...) \
144 do { \
145   const int * P, * START; \
146   if (MAPLOGLEVEL(LEVEL) > lgl->opts->log.val) break; \
147   lglogstart (lgl, MAPLOGLEVEL(LEVEL), FMT, ##ARGS); \
148   START = lgl->gauss->xors.start + (EQN); \
149   assert (START < lgl->gauss->xors.top); \
150   for (P = START; *P > 1; P++) fprintf (lgl->out, " %d", *P); \
151   fprintf (lgl->out, " = %d", *P); \
152   lglogend (lgl); \
153 } while (0)
154 
155 /*------------------------------------------------------------------------*/
156 #else /* end of then start of else part of 'ifndef NLGLOG' */
157 /*------------------------------------------------------------------------*/
158 
159 #define LOG(ARGS...) do { } while (0)
160 #define LOGCLS(ARGS...) do { } while (0)
161 #define LOGMCLS(ARGS...) do { } while (0)
162 #define LOGRESOLVENT(ARGS...) do { } while (0)
163 #define LOGREASON(ARGS...) do { } while (0)
164 #define LOGDSCHED(ARGS...) do { } while (0)
165 #define LOGESCHED(ARGS...) do { } while (0)
166 #define LOGEQN(ARGS...) do { } while (0)
167 
168 /*------------------------------------------------------------------------*/
169 #endif /* end of else part of 'ifndef NLGLOG' */
170 /*------------------------------------------------------------------------*/
171 
172 #define ABORTIF(COND,FMT,ARGS...) \
173 do { \
174   if (!(COND)) break; \
175   fprintf (stderr, "*** API usage error of '%s' in '%s'", \
176 	   __FILE__, __FUNCTION__); \
177   if (lgl && lgl->tid >= 0) fprintf (stderr, " (tid %d)", lgl->tid); \
178   fputs (": ", stderr); \
179   fprintf (stderr, FMT, ##ARGS); \
180   fputc ('\n', stderr); \
181   fflush (stderr); \
182   lglabort (lgl); \
183   exit (1); \
184 } while (0)
185 
186 // Useful for using our 'sleeponabort' and other hooks 'on abort' ...
187 
188 #ifndef NDEBUG
189 #define ASSERT(COND) \
190 do { \
191   if ((COND)) break; \
192   fprintf (stderr, \
193     "liblgl.a: %s:%d: %s: Lingeling Assertion `%s' failed.", \
194     __FUNCTION__, __LINE__, __FILE__, # COND); \
195   if (lgl && lgl->tid >= 0) fprintf (stderr, " (tid %d)", lgl->tid); \
196   fputc ('\n', stderr); \
197   fflush (stderr); \
198   lglabort (lgl); \
199   exit (1); \
200 } while (0)
201 #else
202 #define ASSERT(COND) do { } while (0)
203 #endif
204 
205 #define COVER(COND) \
206 do { \
207   if (!(COND)) break; \
208   fprintf (stderr, \
209     "liblgl.a: %s:%d: %s: Coverage target `%s' reached.", \
210     __FUNCTION__, __LINE__, __FILE__, # COND); \
211   if (lgl && lgl->tid >= 0) fprintf (stderr, " (tid %d)", lgl->tid); \
212   fputc ('\n', stderr); \
213   fflush (stderr); \
214   abort (); /* TODO: why not 'lglabort'? */ \
215 } while (0)
216 
217 #define REQINIT() \
218 do { \
219   ABORTIF (!lgl, "uninitialized manager"); \
220 } while (0)
221 
222 #define REQINITNOTFORKED() \
223 do { \
224   REQINIT (); \
225   ABORTIF (lgl->forked, "forked manager"); \
226 } while (0)
227 
228 #define REQUIRE(STATE) \
229 do { \
230   REQINIT (); \
231   ABORTIF(!(lgl->state & (STATE)), "!(%s)", #STATE); \
232 } while (0)
233 
234 #define TRANS(STATE) \
235 do { \
236   assert (lgl->state != STATE); \
237   LOG (1, "transition to state " #STATE); \
238   lgl->state = STATE; \
239 } while (0)
240 
241 /*------------------------------------------------------------------------*/
242 
243 #if !defined(NDEBUG) || !defined(NLGLOG)
244 #define RESOLVENT
245 #endif
246 
247 /*------------------------------------------------------------------------*/
248 
249 #define TRAPI(MSG,ARGS...) \
250 do { \
251   if (!lgl->apitrace) break; \
252   lgltrapi (lgl, MSG, ##ARGS); \
253 } while (0)
254 
255 #define LGLCHKACT(ACT) \
256 do { assert (NOTALIT <= (ACT) && (ACT) < REMOVED - 1); } while (0)
257 
258 /*------------------------------------------------------------------------*/
259 
260 #define NEW(P,N) \
261 do { (P) = lglnew (lgl, (N) * sizeof *(P)); } while (0)
262 
263 #define DEL(P,N) \
264 do { lgldel (lgl, (P), (N) * sizeof *(P)); (P) = 0; } while (0)
265 
266 #define RSZ(P,O,N) \
267 do { (P) = lglrsz (lgl, (P), (O)*sizeof*(P), (N)*sizeof*(P)); } while (0)
268 
269 #define CLN(P,N) \
270 do { memset ((P), 0, (N) * sizeof *(P)); } while (0)
271 
272 #define CLRPTR(P) \
273 do { memset ((P), 0, sizeof *(P)); } while (0)
274 
275 #define CLR(P) \
276 do { memset (&(P), 0, sizeof (P)); } while (0)
277 
278 /*------------------------------------------------------------------------*/
279 
280 #define SWAP(TYPE,A,B) \
281 do { TYPE TMP = (A); (A) = (B); (B) = TMP; } while (0)
282 
283 #define ISORTLIM 10
284 
285 #define CMPSWAP(TYPE,CMP,P,Q) \
286 do { if (CMP (&(P), &(Q)) > 0) SWAP (TYPE, P, Q); } while(0)
287 
288 #define QPART(TYPE,CMP,A,L,R) \
289 do { \
290   TYPE PIVOT; \
291   int J = (R); \
292   I = (L) - 1; \
293   PIVOT = (A)[J]; \
294   for (;;) { \
295     while (CMP (&(A)[++I], &PIVOT) < 0) \
296       ; \
297     while (CMP (&PIVOT, &(A)[--J]) < 0) \
298       if (J == (L)) break; \
299     if (I >= J) break; \
300     SWAP (TYPE, (A)[I], (A)[J]); \
301   } \
302   SWAP (TYPE, (A)[I], (A)[R]); \
303 } while(0)
304 
305 #define QSORT(TYPE,CMP,A,N) \
306 do { \
307   int L = 0, R = (N) - 1, M, LL, RR, I; \
308   assert (lglmtstk (&lgl->sortstk)); \
309   if (R - L <= ISORTLIM) break; \
310   for (;;) { \
311     M = (L + R) / 2; \
312     SWAP (TYPE, (A)[M], (A)[R - 1]); \
313     CMPSWAP (TYPE, CMP, (A)[L], (A)[R - 1]); \
314     CMPSWAP (TYPE, CMP, (A)[L], (A)[R]); \
315     CMPSWAP (TYPE, CMP, (A)[R - 1], (A)[R]); \
316     QPART (TYPE, CMP, (A), L + 1, R - 1); \
317     if (I - L < R - I) { LL = I + 1; RR = R; R = I - 1; } \
318     else { LL = L; RR = I - 1; L = I + 1; } \
319     if (R - L > ISORTLIM) { \
320       assert (RR - LL > ISORTLIM); \
321       lglpushstk (lgl, &lgl->sortstk, LL); \
322       lglpushstk (lgl, &lgl->sortstk, RR); \
323     } else if (RR - LL > ISORTLIM) L = LL, R = RR; \
324     else if (!lglmtstk (&lgl->sortstk)) { \
325       R = lglpopstk (&lgl->sortstk); \
326       L = lglpopstk (&lgl->sortstk); \
327     } else break; \
328   } \
329 } while (0)
330 
331 #define ISORT(TYPE,CMP,A,N) \
332 do { \
333   TYPE PIVOT; \
334   int L = 0, R = (N) - 1, I, J; \
335   for (I = R; I > L; I--) \
336     CMPSWAP (TYPE, CMP, (A)[I - 1], (A)[I]); \
337   for (I = L + 2; I <= R; I++) { \
338     J = I; \
339     PIVOT = (A)[I]; \
340     while (CMP (&PIVOT, &(A)[J - 1]) < 0) { \
341       (A)[J] = (A)[J - 1]; \
342       J--; \
343     } \
344     (A)[J] = PIVOT; \
345   } \
346 } while (0)
347 
348 #ifdef NDEBUG
349 #define CHKSORT(CMP,A,N) do { } while(0)
350 #else
351 #define CHKSORT(CMP,A,N) \
352 do { \
353   int I; \
354   for (I = 0; I < (N) - 1; I++) \
355     assert (CMP (&(A)[I], &(A)[I + 1]) <= 0); \
356 } while(0)
357 #endif
358 
359 #define SORT(TYPE,A,N,CMP) \
360 do { \
361   TYPE * AA = (A); \
362   const int NN = (N); \
363   QSORT (TYPE, CMP, AA, NN); \
364   ISORT (TYPE, CMP, AA, NN); \
365   CHKSORT (CMP, AA, NN); \
366 } while (0)
367 
368 #define SORTSTK(TYPE,S,CMP) \
369 do { \
370   TYPE * A = (S)->start; \
371   const int N = lglcntstk (S); \
372   SORT (TYPE, A, N, CMP); \
373 } while (0)
374 
375 /*------------------------------------------------------------------------*/
376 
377 #define LGLPOPWTK(WTK,WRAG,LIT,OTHER,RED,REMOVED) \
378 do { \
379   assert (!lglmtwtk (WTK)); \
380   (WTK)->top--; \
381   (WRAG) = (WTK)->top->wrag; \
382   (LIT) = (WTK)->top->lit; \
383   (OTHER) = (WTK)->top->other; \
384   (RED) = (WTK)->top->red ? REDCS : 0; \
385   (REMOVED) = (WTK)->top->removed; \
386 } while (0)
387 
388 /*------------------------------------------------------------------------*/
389 
390 #define CLONE(FIELD,SIZE) \
391 do { \
392   NEW (lgl->FIELD, (SIZE)); \
393   memcpy (lgl->FIELD, orig->FIELD, (SIZE) * sizeof *(lgl->FIELD)); \
394 } while (0)
395 
396 #define CLONESTK(NAME) \
397 do { \
398   size_t COUNT = orig->NAME.top - orig->NAME.start; \
399   size_t SIZE = orig->NAME.end - orig->NAME.start; \
400   size_t BYTES = SIZE * sizeof *lgl->NAME.start; \
401   NEW (lgl->NAME.start, SIZE); \
402   memcpy (lgl->NAME.start, orig->NAME.start, BYTES); \
403   lgl->NAME.top = lgl->NAME.start + COUNT; \
404   lgl->NAME.end = lgl->NAME.start + SIZE; \
405 } while (0)
406 
407 /*------------------------------------------------------------------------*/
408 
409 #define INCSTEPS(NAME) \
410  ((lgl->stats->steps++), (lgl->stats->NAME++))
411 
412 #define ADDSTEPS(NAME,INC) \
413  ((lgl->stats->steps += INC), (lgl->stats->NAME += INC))
414 
415 /*------------------------------------------------------------------------*/
416 
417 #define LGLUPDPEN(NAME,SUCCESS) \
418 do { \
419   assert (!lgl->limits->NAME.del.rem); \
420   if ((SUCCESS) && lgl->limits->NAME.pen) \
421     lgl->limits->NAME.pen--; \
422   if (!(SUCCESS) && lgl->limits->NAME.pen < lgl->opts->penmax.val) \
423     lgl->limits->NAME.pen++; \
424   if ((SUCCESS) && lgl->limits->NAME.del.cur) \
425     lgl->limits->NAME.del.cur /= 2; \
426   if (!(SUCCESS) && lgl->limits->NAME.del.cur < lgl->opts->delmax.val) \
427     lgl->limits->NAME.del.cur++; \
428   lgl->limits->NAME.del.rem = lgl->limits->NAME.del.cur; \
429 } while (0)
430 
431 /*-------------------------------------------------------------------------*/
432 
433 #define RMSHFTLIT(LIT)		((int)(((unsigned)LIT)<<RMSHFT))
434 
435 /*-------------------------------------------------------------------------*/
436 
437 #define LGLL long long
438 
439 /*-------------------------------------------------------------------------*/
440 
441 typedef enum Tag {
442   FREEVAR = 0,
443   FIXEDVAR = 1,
444   EQUIVAR = 2,
445   ELIMVAR = 3,
446 
447   DECISION = 0,
448   UNITCS = 1,
449   OCCS = 1,
450   BINCS = 2,
451   TRNCS = 3,
452   LRGCS = 4,
453   MASKCS = 7,
454 
455   REDCS = 8,
456   RMSHFT = 4,
457 } Tag;
458 
459 typedef enum State {
460   UNUSED 	= (1<<0),
461   OPTSET 	= (1<<1),
462   USED 		= (1<<2),
463   READY		= (1<<3),
464   UNKNOWN	= (1<<4),
465   SATISFIED	= (1<<5),
466   EXTENDED      = (1<<6),
467   UNSATISFIED	= (1<<7),
468   FAILED        = (1<<8),
469   LOOKED        = (1<<9),
470   RESET		= (1<<10),
471 } State;
472 
473 typedef enum Wrag {
474   PREFIX = 0,
475   BEFORE = 1,
476   AFTER = 2,
477   POSTFIX = 3,
478 } Wrag;
479 
480 typedef enum GTag { ANDTAG, ITETAG, XORTAG } GTag;
481 
482 /*------------------------------------------------------------------------*/
483 
484 typedef int Exp;
485 typedef uint64_t Mnt;
486 typedef int64_t Flt;
487 typedef int64_t Cnf;
488 typedef uint64_t Fun[FUNQUADS];
489 typedef signed char Val;
490 typedef Flt LKHD;
491 
492 /*------------------------------------------------------------------------*/
493 
494 typedef struct Conf { int lit, rsn[2]; } Conf;
495 typedef struct Ctk { struct Ctr * start, * top, * end; } Ctk;
496 typedef struct DFOPF { int observed, pushed, flag; } DFOPF;
497 typedef struct DFPR { int discovered, finished, parent, root; } DFPR;
498 typedef struct EVar { int occ[2], pos, score; } EVar;
499 typedef struct Ftk { Flt * start, * top, * end; } Ftk;
500 typedef struct HTS { int offset, count; }  HTS;
501 typedef struct Lim { int64_t confs, decs, props; } Lim;
502 typedef struct PAGSL { int psm, act, glue, size, lidx; } PAGSL;
503 typedef struct PSz { int pos, size; } PSz;
504 typedef struct RNG { unsigned z, w; } RNG;
505 typedef struct Stk { int * start, * top, * end; } Stk;
506 typedef struct Timer { double start; int idx, ign; } Timer;
507 typedef struct Timers { Timer stk[MAXPHN]; int nest; } Timers;
508 typedef struct Trv { void * state; void (*trav)(void *, int); } Trv;
509 typedef struct TVar { signed int val : 30; unsigned mark : 2; } TVar;
510 typedef struct Wtk { struct Work * start, * top, * end; } Wtk;
511 
512 /*------------------------------------------------------------------------*/
513 
514 typedef struct EMA {
515   int shift, count;
516   int64_t val;
517 } EMA;
518 
519 typedef struct AVG {
520   int64_t val, count;
521 } AVG;
522 
523 #ifndef NLGLDEMA
524 
525 typedef struct DEMA {
526   EMA ema[2];
527   int64_t val;
528 } DEMA;
529 
530 #define MACDEMA DEMA
531 #define lglinitmacdema lglinitdema
532 #define lglupdatemacdema lglupdatedema
533 
534 #else
535 
536 #define MACDEMA EMA
537 #define lglinitmacdema lglinitema
538 #define lglupdatemacdema(A,B,C) lglupdatema(A,B,C,1)
539 
540 #endif
541 
542 typedef struct MACD {
543   MACDEMA fast, slow;
544   struct { int64_t actual; EMA smoothed; } diff;
545 } MACD;
546 
547 /*------------------------------------------------------------------------*/
548 
549 typedef struct Ctr {
550   signed int decision : 28;
551   unsigned used : 2;
552   unsigned used2 : 2;
553 } Ctr;
554 
555 typedef struct DVar { HTS hts[2]; } DVar;
556 
557 #define GLAGBITS 31
558 #define MAXGLAG ((1<<(GLAGBITS-1)) - 1)
559 
560 typedef struct QVar {
561   Flt score;
562   unsigned enqueued:1;
563   signed int glag:GLAGBITS;
564   int pos;
565 } QVar;
566 
567 typedef struct TD {
568   signed int level:30;
569   unsigned lrglue:1, irr:1;
570   int rsn[2];
571 } TD;
572 
573 typedef struct AVar {
574   unsigned type : 4;
575 #ifndef NDEBUG
576   unsigned simp:1, wasfalse:1;
577 #endif
578   unsigned equiv:1, lcamark:4;
579   signed int phase:2, bias:2, fase:2;
580   unsigned inred:2, poisoned:1, assumed:2, failed:2;
581   unsigned donotelm:1, donotblk:1, donoternres:1;
582   unsigned donotbasicprobe:1, donotsimpleprobe:1, donotreelook:1, donotsweep:1;
583 #ifndef NLGLYALSAT
584   signed int locsval:2;
585 #endif
586   int mark, trail;
587 } AVar;
588 
589 typedef struct Ext {
590   unsigned equiv:1,melted:1,blocking:2,eliminated:1,tmpfrozen:1,imported:1;
591   unsigned assumed:2,failed:2,aliased:1;
592   signed int val:2, oldval:2;
593   int repr, frozen;
594 } Ext;
595 
596 typedef struct Work {
597   unsigned wrag : 2;
598   signed int lit : 30, other : 30;
599   unsigned red : 1, removed : 1;
600 } Work;
601 
602 typedef struct DFL {
603   int discovered, finished;
604   union { int lit, sign; };
605 #ifndef NLGLOG
606   int lit4logging;
607 #endif
608 } DFL;
609 
610 /*------------------------------------------------------------------------*/
611 
612 #define FEATURES \
613 FEATURE(n) \
614 FEATURE(s) \
615 FEATURE(vo) \
616 FEATURE(vc) \
617 FEATURE(co) \
618 FEATURE(cc) \
619 FEATURE(b) \
620 FEATURE(t) \
621 FEATURE(q) \
622 FEATURE(c1) \
623 FEATURE(c2) \
624 FEATURE(c3) \
625 FEATURE(c4) \
626 FEATURE(x) \
627 FEATURE(a1) \
628 FEATURE(a2) \
629 FEATURE(g) \
630 FEATURE(j) \
631 FEATURE(c) \
632 FEATURE(o)
633 
634 typedef struct Features {
635 #define FEATURE(NAME) int NAME;
636 FEATURES
637 } Features;
638 
639 #define NFEATURES (sizeof (Features) / sizeof (int))
640 
641 #undef FEATURE
642 #define FEATURE(NAME) #NAME,
643 
644 static const char * featurenames[] = {
645   FEATURES
646 };
647 
648 /*------------------------------------------------------------------------*/
649 
650 typedef struct Stats {
651   int64_t agility;
652   int64_t steps, trims, bins, trns, times;
653   int defrags, reported, features, repcntdown, gcs, decomps;
654   struct { int clauses, vars; } rescored;
655   struct { int64_t count, checked, skipped, forced;
656 	   int64_t agile, delayed, blocked, notforced, reused;
657 	   struct { int64_t count, pen, delta; } delta;
658 	   struct { int64_t count, sum; } kept; } restarts;
659   struct { int count, arith, memlim;
660            int64_t collected, retired; } reduced;
661   int64_t prgss, irrprgss, enlwchs, pshwchs, dense, sparse;
662   int64_t confs, decisions, hdecs, qdecs, randecs, uips, decflipped;
663   MACD glue, jlevel;
664   EMA tlevel;
665   AVG avglue;
666   struct { MACD avg; int count; } its;
667   struct {
668     struct { int cur, max; int64_t add; } clauses, lits;
669     int64_t maxbytes;
670   } irr;
671   struct { int64_t sat, mosat, simp, deref, fixed, freeze, lkhd;
672 	   int64_t melt, add, assume, cassume, failed, repr; } calls;
673   struct { int64_t search, simp, lkhd; } props, visits;
674   struct { size_t current, max; } bytes;
675   struct { int bin, trn, lrg; } red;
676   struct { int cnt, simple, trn, lrg, sub; } hbr;
677   struct { int current, sum; } fixed, equiv;
678   struct { int count, bin, trn; int64_t steps; } ternres;
679   struct { int count, clauses, lits, pure; int64_t res, steps; } blk;
680   struct {
681     struct { int count, failed, eqs; int64_t probed, steps; } simple;
682     struct { int count, failed, lifted;
683              int64_t probed, steps, lastate;
684 	     struct { int trnr, lrg, count; } ate; } basic;
685     struct { int count, failed, lifted; int64_t probed, steps; } treelook;
686   } prb;
687   struct { int count, red, failed; int64_t lits, bins, steps; } trd;
688   struct { int removed, red; } bindup;
689   struct { int count, rounds;
690 	   struct { int trds, failed, sccs; int64_t sumsccsizes; } stamp;
691 	   struct { int lits, bin, trn, lrg; } failed;
692 	   struct { int bin, trn, lrg, red; } tauts;
693 	   struct { int bin, trn, lrg; } units;
694 	   struct { int trn, lrg, red; } hbrs, str;
695 	   int64_t steps; } unhd;
696   struct {
697     int count, elmd, pure, large, sub, str, blkd, rounds;
698     struct { int elm, tried, failed; } small;
699     int64_t resolutions, copies, subchks, strchks, ipos, steps; } elm;
700   struct {
701     int sub2, sub3, subl, str2, str3, str3self, strl, strlself;
702     struct { int64_t lits, clauses, occs; } tried;
703     int64_t steps;
704   } bkwd;
705   struct {
706     struct { int64_t irr, red, bin, trn, lrg; } sub, str;
707     int64_t driving, restarting, total; } otfs;
708   struct { int64_t nonmin, learned; } lits;
709   struct {
710     int64_t learned, glue, realglue, nonmaxglue, scglue;
711     struct { int64_t count, kept; } maxglue;
712   } clauses;
713   struct {
714     int clauses;
715     int64_t added, reduced, retired, resolved, forcing, conflicts;
716     int64_t maxbytes;
717   } lir[POW2GLUE];
718   struct { int count; int64_t set, pos, neg; } phase;
719   struct {
720     int count;
721     struct { int confs, irr, vars, its, bin, trn; } limhit;
722   } simp;
723   struct { int count, gcs, units, equivs, trneqs;
724            struct { struct { int total, last; } max; int64_t sum; } arity;
725 	   struct { int64_t extr, elim; } steps;
726 	   struct { int64_t total, last; } extracted; } gauss;
727   struct { int count, eliminated, ate, abce, failed, lifted;
728            int64_t steps, probed;
729 	   struct { int64_t search, hits, cols, ins, rsz; } cache; } cce;
730   struct {
731     int count, units, expam1, resched;
732     int64_t steps, eliminated, resolved, subsumed;
733     struct {
734       struct {
735 	struct { int64_t sum, cnt; int max; } total;
736 	struct { int cnt, max; } last;
737       } am1, am2;
738     } found;
739     struct { struct { int64_t sum, cnt; } am1, am2; } used;
740     } card;
741   struct { int64_t bin, trn; } moved;
742   struct { int count; int64_t added, skipped, steps; } bca;
743   struct {
744     struct {
745       int64_t produced;
746       struct { int64_t actual, tried, calls; } consumed;
747     } cls, units;
748   } sync;
749   struct { struct { int64_t orig, red; } sum; } deco;
750   struct {
751     int64_t min, bin, size, deco;
752     struct { int64_t search, hits; } poison;
753     struct { int64_t search, hits; } usedtwice;
754   } mincls;
755   struct {
756      struct { int64_t tried, red, sat; } cls, lits;
757      struct { int64_t red, sum; } jlevel; } redcls;
758   int64_t drupped, druplig;
759   struct { int64_t count, tried, cands, sub; } subl;
760   struct { int count; int64_t flips, mems; int min; } locs;
761   struct {
762     int count, failed, impls, equivs;
763     int64_t rounds, steps, cached, sat, unsat, decs, confs;
764     struct { int64_t classes, envs; } sumsize;
765     struct { int64_t total;
766 	     struct { int64_t count, sat, unsat; } type[3]; } queries;
767   } sweep;
768   struct { int64_t count; int max, min; } setscincf;
769   struct { int64_t tried, locked; } promote;
770   struct { int count; int64_t quat, self1, self2, dup; } quatres;
771   struct { int64_t flushed, sorted; } queue;
772   struct { int64_t count, lits; } bump;
773   struct { int64_t count; EMA avg; int changed, level; } stability;
774 } Stats;
775 
776 /*------------------------------------------------------------------------*/
777 
778 typedef struct Times {
779     double all, search, preprocessing, inprocessing;            // level 0
780     double lookahead;///PUT NOTHING HERE!                       // level 0
781 #define TIMESLEVEL0     lookahead
782     double elim, transred, block, unhide, ternres;              // level 1
783     double gauss, quatres, card, cce, bca, locs, sweep;         // level 1
784     double showscoredist, showfeatures;                         // level 1
785     double probe;///////PUT NOTHING HERE!                       // level 1
786 #define TIMESLEVEL1     probe
787     struct { double simple, basic, treelook; } prb;             // level 2
788     double quatres1, quatres2;                                  // level 2
789     double gc, decompose, queuesort, phase;                     // level 2
790     double backward;////PUT NOTHING HERE!                       // level 2
791 #define TIMESLEVEL2     backward
792     double restart, defrag;                                     // level 3
793     double reduce;//////PUT NOTHING HERE!                       // level 3
794 #define TIMESLEVEL3     reduce
795     double analysis, decide, bump, mincls, druplig;             // level 4
796     double redcls, queuedecision, heapdecision, subl;           // level 4
797 } Times;
798 
799 #define TIMESLEVEL0IDX (&(((Times*)0)->TIMESLEVEL0)- &((Times*)0)->all)
800 #define TIMESLEVEL1IDX (&(((Times*)0)->TIMESLEVEL1)- &((Times*)0)->all)
801 #define TIMESLEVEL2IDX (&(((Times*)0)->TIMESLEVEL2)- &((Times*)0)->all)
802 #define TIMESLEVEL3IDX (&(((Times*)0)->TIMESLEVEL3)- &((Times*)0)->all)
803 
804 /*------------------------------------------------------------------------*/
805 
806 typedef struct Del { int cur, rem; } Del;
807 
808 typedef struct Limits {
809   int lkhdpen;
810   int64_t randec, dfg;
811   struct {
812     int64_t visits;
813     struct { int64_t add; int start; } clauses;
814     struct { int start; } vars;
815   } inc;
816   struct { struct { int64_t otfs, confs; } vars; } rescore;
817   struct { int pen; Del del; int64_t steps, irrprgss; } elm, blk;
818   struct { int pen; Del del; int64_t steps; }
819     trd, unhd, ternres, quatres, cce, card, sweep;
820   struct { int pen; Del del; struct { int64_t extr, elim; } steps; } gauss;
821   struct { int64_t confs; } restart;
822   struct { int64_t steps;
823            struct { int pen; Del del; } simple, basic, treelook; } prb;
824   struct {
825     int64_t confs, hard, vars, its, bin, trn;
826     int cinc, itinc, binc, tinc; } simp;
827   struct { int64_t steps, confs; } sync;
828   struct { int64_t steps; } term;
829   struct { int64_t fixed; } gc;
830   struct { Del del; int64_t steps, added; } bca;
831   struct { int64_t steps, time; } trep;
832   struct { int64_t confs, inc; int vars; } locs;
833   struct { int redlarge; } reduce;
834 } Limits;
835 
836 /*------------------------------------------------------------------------*/
837 
838 typedef struct Cbs {
839   struct { int (*fun)(void*); void * state; int done; } term;
840   struct {
841     struct { void (*fun)(void*,int); void * state; } produce, consumed;
842     struct { void(*fun)(void*,int**,int**); void*state; } consume;
843   } units;
844   struct {
845     struct { void (*fun)(void*,int*,int); void * state; } produce;
846     struct { void(*fun)(void*,int**,int*); void*state; } consume;
847     struct { void (*fun)(void*,int); void * state; } consumed;
848   } cls;
849   struct {
850     struct { int * (*fun)(void*); void * state; } lock;
851     struct { void (*fun)(void*,int,int); void * state; } unlock;
852   } eqs;
853   struct { void(*lock)(void*); void (*unlock)(void*); void*state; } msglock;
854   double (*getime)(void);
855   void (*onabort)(void *); void * abortstate;
856 } Cbs;
857 
858 typedef struct BCA { Stk covered; } BCA;
859 
860 typedef struct Dis { struct { Stk bin, trn; } red, irr; } Dis;
861 
862 typedef struct Elm {
863   int64_t oldsteps;
864   int pivot, negcls, necls, neglidx, round, oldelmd;
865   Stk lits, next, clv, csigs, sizes, occs, noccs, mark, m2i;
866   struct { Stk stk; int * pos, mt, nvars; } touched;
867   int bkwdocclim;
868 } Elm;
869 
870 typedef struct Card {
871   Stk atmost1, atmost2, cards, elim, * occs, units, expam1;
872   char * eliminated, * lit2used, * marked;
873   signed char * count;
874   int * lit2count;
875 } Card;
876 
877 typedef struct FltStr { int current; char str[MAXFLTSTR][100]; } FltStr;
878 
879 typedef struct SPE { signed int count : 31; unsigned mark : 1, sum; } SPE;
880 
881 typedef struct SPrb {
882   Stk units, impls, eqs, counted, marked;
883   SPE * spes;
884 } SPrb;
885 
886 typedef struct Gauss {
887   Stk xors, order, * occs;
888   signed char * eliminated;
889   int garbage, next;
890 } Gauss;
891 
892 typedef struct CCE {
893   Stk cla, extend, clauses;
894   int * rem, bin, trn;
895 } CCE;
896 
897 typedef struct SWP {
898   int partitions, round, query, sat, type;
899   Stk partition;
900   struct { int64_t classes, envs; } sumsize;
901   struct { int count; struct { int a, b; } cached; Stk stk; } decision;
902 } SWP;
903 
904 typedef struct Tlk { Stk stk, seen; TVar * tvars; LKHD * lkhd; } Tlk;
905 
906 typedef struct Mem {
907   void * state;
908   lglalloc alloc; lglrealloc realloc; lgldealloc dealloc;
909 } Mem;
910 
911 typedef struct Wchs { Stk stk; int start[MAXLDFW], free; } Wchs;
912 
913 typedef struct Wrk {
914   Stk queue;
915   int count, head, size, posonly, fifo, * pos;
916 } Wrk;
917 
918 typedef struct Queue { Stk stk; int mt, next, sorted; } Queue;
919 
920 /*------------------------------------------------------------------------*/
921 
922 struct LGL {
923   State state;
924 
925   int probing, tid, tids;
926   int nvars, szvars, maxext, szext, changed, mt, repcntdown;
927   int szdrail, next, next2, flushed, level, alevel, wait, glag;
928   int unassigned, lrgluereasons, failed, assumed;
929 
930   Flt scinc, scincf, maxscore, minscore;
931   int scincinc;
932 
933   char cceing, gaussing, bcaing, repforcehead, quatres, notrim;
934   char searching, simp, allphaseset, flushphases, occs;
935   char unhiding, basicprobing, simpleprobing, treelooking, setuponce;
936   char eliminating, donotsched, blocking, ternresing, lkhd, allfrozen;
937   char blkall, blkrem, blkrtc, elmall, elmrem, elmrtc, sweeprtc, decomposing;
938   char frozen, dense, rmredbintrn, notfullyconnected, forcegc, allowforce;
939   char ccertc, touching, sweeping;
940 
941   int64_t confatlastit;
942 
943   LGL * parent;
944   int forked;
945 
946   Conf conf;
947   RNG rng;
948 
949   // the state above this line is copied during 'clone' with 'memcpy'
950 
951   Mem * mem;
952   Opts * opts;
953   Stats * stats;
954   Times * times;
955   Timers * timers;
956   Limits * limits;
957   Ext * ext;
958   int * i2e;
959   int * doms;
960   DVar * dvars;
961   QVar * qvars;
962   AVar * avars;
963   Val * vals;
964   Flt * jwh;
965   TD * drail;
966   Stk * red;
967   Wchs * wchs;
968 
969   Ctk control;
970 #ifndef NDEBUG
971   Stk prevclause;
972   int prevglue;
973 #endif
974   Stk clause, eclause, extend, irr, trail, frames, promote;
975   Stk eassume, assume, learned;
976   Stk dsched;
977 #ifndef NCHKSOL
978   Stk orig;
979 #endif
980   Queue queue;
981 
982   union {
983     Elm * elm; SPrb * sprb; Tlk * tlk; Gauss * gauss;
984     CCE * cce; BCA * bca; Card * card; SWP * swp;
985   };
986   union { Stk lcaseen, sortstk; };
987   Stk poisoned, seen, esched, minstk, resolvent;
988   struct { Stk bin, trn; } saved;
989   EVar * evars;
990   Dis * dis;
991   Wrk * wrk;
992   int * repr;
993 
994   char closeapitrace;
995   FILE * out, * apitrace;
996   char * prefix;
997   Cbs * cbs;
998 
999   LGL * clone;
1000 
1001   FltStr * fltstr;
1002 #if !defined(NLGLDRUPLIG)
1003   Druplig * druplig;
1004   int drupligunit;
1005 #endif
1006 };
1007 
1008 /*-------------------------------------------------------------------------*/
1009 
1010 #define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
1011 
1012 static const char lglfloorldtab[256] =
1013 {
1014 // 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
1015   -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
1016   LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
1017   LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
1018 };
1019 
1020 static const uint64_t lglbasevar2funtab[6] = {
1021   0xaaaaaaaaaaaaaaaaull, 0xccccccccccccccccull, 0xf0f0f0f0f0f0f0f0ull,
1022   0xff00ff00ff00ff00ull, 0xffff0000ffff0000ull, 0xffffffff00000000ull,
1023 };
1024 
1025 /*-------------------------------------------------------------------------*/
1026 
lglfloorld(int n)1027 static int lglfloorld (int n) {
1028   assert (n >= 0);
1029   if (n < (1<<8)) return lglfloorldtab[n];
1030   if (n < (1<<16)) return 8 + lglfloorldtab[n>>8];
1031   if (n < (1<<24)) return 16 + lglfloorldtab[n>>16];
1032   return 24 + lglfloorldtab[n>>24];
1033 }
1034 
lglispow2(int n)1035 static int lglispow2 (int n) {
1036   assert (0 <= n && n <= INT_MAX);
1037   return !(n & (n - 1));
1038 }
1039 
lglceild(int n)1040 static int lglceild (int n) {
1041   int res = lglfloorld (n);
1042   if (!lglispow2 (n)) res++;
1043   return res;
1044 }
1045 
lglchkflt(Flt a)1046 static void lglchkflt (Flt a) {
1047 #ifndef NDEBUG
1048   assert (a >= 0);
1049   assert (FLTMAX >= (uint64_t) a);
1050 #else
1051   (void) a;
1052 #endif
1053 }
1054 
lglexp(Flt a)1055 static Exp lglexp (Flt a) {
1056   Flt tmp = a >> FLTPRC;
1057   Exp res = tmp;
1058   assert (0 <= res && res <= EXPMAX);
1059   res -= EXPZRO;
1060   return res;
1061 }
1062 
lglmnt(Flt a)1063 static Mnt lglmnt (Flt a) {
1064   Mnt res = a & MNTMAX;
1065   res |= MNTBIT;
1066   assert (res <= MNTMAX);
1067   return res;
1068 }
1069 
lglflt(Exp e,Mnt m)1070 static Flt lglflt (Exp e, Mnt m) {
1071   Flt res;
1072   if (!m) return FLTMIN;
1073   if (m < MNTBIT) {
1074     while (!(m & MNTBIT)) {
1075       m <<= 1;
1076       if (e > INT_MIN) e--;
1077       else break;
1078     }
1079   } else {
1080     while (m > MNTMAX) {
1081        m >>= 1;
1082        if (e > INT_MIN) e++;
1083        else break;
1084     }
1085   }
1086   if (e < -EXPZRO) return FLTMIN;
1087   if (e > EXPMAX - EXPZRO) return FLTMAX;
1088   e += EXPZRO;
1089   assert (0 <= e && e <= EXPMAX);
1090   assert (m <= MNTMAX);
1091   assert (m & MNTBIT);
1092   res = m & ~MNTBIT;
1093   res |= ((Flt)e) << FLTPRC;
1094   return res;
1095 }
1096 
lglrat(unsigned n,unsigned d)1097 static Flt lglrat (unsigned n, unsigned d) {
1098   Mnt m;
1099   Exp e;
1100   if (!n) return FLTMIN;
1101   if (!d) return FLTMAX;
1102   m = n;
1103   e = 0;
1104   while (!(m & (1ull << 63))) m <<= 1, e--;
1105   m /= d;
1106   return lglflt (e, m);
1107 }
1108 
1109 #ifndef NDEBUG
lglflt2dbl(Flt a)1110 double lglflt2dbl (Flt a) {
1111   return lglmnt (a) * pow (2.0, lglexp (a));
1112 }
1113 #endif
1114 
lglflt2str(LGL * lgl,Flt a)1115 static const char * lglflt2str (LGL * lgl, Flt a) {
1116   double d, e;
1117   assert (lgl->fltstr);
1118   if (a == FLTMIN) return "0";
1119   if (a == FLTMAX) return "inf";
1120   d = lglmnt (a);
1121   d /= 4294967296ll;
1122   e = lglexp (a);
1123   e += 32;
1124   lgl->fltstr->current++;
1125   if (lgl->fltstr->current == MAXFLTSTR) lgl->fltstr->current = 0;
1126   sprintf (lgl->fltstr->str[lgl->fltstr->current], "%.6fd%+03.0f", d, e);
1127   return lgl->fltstr->str[lgl->fltstr->current];
1128 }
1129 
lgladdflt(Flt a,Flt b)1130 static Flt lgladdflt (Flt a, Flt b) {
1131   Exp e, f, g;
1132   Mnt m, n, o;
1133   lglchkflt (a);
1134   lglchkflt (b);
1135   if (a == FLTMAX) return FLTMAX;
1136   if (b == FLTMAX) return FLTMAX;
1137   if (a == FLTMIN) return b;
1138   if (b == FLTMIN) return a;
1139   e = lglexp (a);
1140   f = lglexp (b);
1141   if (e < f) g = e, e = f, f = g, o = a, a = b, b = o;
1142   m = lglmnt (a);
1143   n = lglmnt (b);
1144   if (e - f < sizeof (m) * 8) m += n >> (e - f);
1145   return lglflt (e, m);
1146 }
1147 
lglmulflt(Flt a,Flt b)1148 static Flt lglmulflt (Flt a, Flt b) {
1149   Exp e, ea, eb;
1150   Mnt m, ma, mb;
1151   lglchkflt (a);
1152   lglchkflt (b);
1153   if (a == FLTMAX) return FLTMAX;
1154   if (b == FLTMAX) return FLTMAX;
1155   if (a == FLTMIN) return FLTMIN;
1156   if (b == FLTMIN) return FLTMIN;
1157   ea = lglexp (a); eb = lglexp (b);
1158   if (ea > 0 && eb > 0 && (INT_MAX - ea < eb)) return FLTMAX;
1159   e = ea + eb;
1160   if (e > EXPMAX - EXPZRO - 32) return FLTMAX;
1161   e += 32;
1162   ma = lglmnt (a); mb = lglmnt (b);
1163   ma >>= 1; mb >>= 1;
1164   m = ma * mb;
1165   assert (3ull << 62);
1166   m >>= 30;
1167   return lglflt (e, m);
1168 }
1169 
lglshflt(Flt a,int s)1170 static Flt lglshflt (Flt a, int s) {
1171   Exp e;
1172   Mnt m;
1173   if (a == FLTMAX) return FLTMAX;
1174   if (a == FLTMIN) return FLTMIN;
1175   assert (0 <= s);
1176   e = lglexp (a);
1177   if (e < INT_MIN + s) return FLTMIN;
1178   e -= s;
1179   m = lglmnt (a);
1180   return lglflt (e, m);
1181 }
1182 
lglscr2str(LGL * lgl,Flt scr)1183 static const char * lglscr2str (LGL * lgl, Flt scr) {
1184   return lglflt2str (lgl, scr);
1185 }
1186 
lglwrn(LGL * lgl,const char * msg,...)1187 static void lglwrn (LGL * lgl, const char * msg, ...) {
1188   va_list ap;
1189   fprintf (lgl->out, "*** warning in '%s': ", __FILE__);
1190   va_start (ap, msg);
1191   vfprintf (lgl->out, msg, ap);
1192   va_end (ap);
1193   fputc ('\n', lgl->out);
1194   fflush (lgl->out);
1195 }
1196 
lgldie(LGL * lgl,const char * msg,...)1197 static void lgldie (LGL * lgl, const char * msg, ...) {
1198   va_list ap;
1199   fprintf (lgl->out, "*** internal error in '%s': ", __FILE__);
1200   va_start (ap, msg);
1201   vfprintf (lgl->out, msg, ap);
1202   va_end (ap);
1203   fputc ('\n', lgl->out);
1204   fflush (lgl->out);
1205   exit (0);
1206 }
1207 
lglabort(LGL * lgl)1208 static void lglabort (LGL * lgl) {
1209   if (!lgl) exit (1);
1210   if (lgl->opts && lgl->opts->sleeponabort.val) {
1211     fprintf (stderr,
1212 "liblgl.a: Process %d will sleep for %d seconds "
1213 " before continuing with 'lglabort' procedure.\n",
1214       getpid (), lgl->opts->sleeponabort.val);
1215     fflush (stderr);
1216     sleep (lgl->opts->sleeponabort.val);
1217   }
1218   if (lgl->cbs && lgl->cbs->onabort)
1219     lgl->cbs->onabort (lgl->cbs->abortstate);
1220   if (lgl->opts && lgl->opts->exitonabort.val) exit (1);
1221   abort ();
1222 }
1223 
lglprefix(LGL * lgl)1224 static const char * lglprefix (LGL * lgl) {
1225   return lgl && lgl->prefix ? lgl->prefix : "c (LGL HAS NO PREFIX YET) ";
1226 }
1227 
lglmsgstart(LGL * lgl,int level)1228 static int lglmsgstart (LGL * lgl, int level) {
1229 #ifndef NLGLOG
1230   if (lgl->opts->log.val <= 0)
1231 #endif
1232   if (lgl->opts->verbose.val < level) return 0;
1233   if (lgl->cbs && lgl->cbs->msglock.lock)
1234     lgl->cbs->msglock.lock (lgl->cbs->msglock.state);
1235   fputs (lglprefix (lgl), lgl->out);
1236   if (lgl->tid >= 0) fprintf (lgl->out, "%d ", lgl->tid);
1237   return 1;
1238 }
1239 
lglmsgend(LGL * lgl)1240 static void lglmsgend (LGL * lgl) {
1241   fputc ('\n', lgl->out);
1242   fflush (lgl->out);
1243   if (lgl->cbs && lgl->cbs->msglock.unlock)
1244     lgl->cbs->msglock.unlock (lgl->cbs->msglock.state);
1245 }
1246 
lglprt(LGL * lgl,int level,const char * msg,...)1247 static void lglprt (LGL * lgl, int level, const char * msg, ...) {
1248   va_list ap;
1249 #ifndef NLGLOG
1250   if (lgl->opts->log.val <= 0)
1251 #endif
1252   if (lgl->opts->verbose.val < level) return;
1253   lglmsgstart (lgl, level);
1254   va_start (ap, msg);
1255   vfprintf (lgl->out, msg, ap);
1256   va_end (ap);
1257   lglmsgend (lgl);
1258 }
1259 
1260 #ifndef NLGLOG
lglogstart(LGL * lgl,int level,const char * msg,...)1261 static void lglogstart (LGL * lgl, int level, const char * msg, ...) {
1262   va_list ap;
1263   assert (lgl->opts->log.val >= level);
1264   if (lgl->cbs && lgl->cbs->msglock.lock)
1265     lgl->cbs->msglock.lock (lgl->cbs->msglock.state);
1266   fputs (lglprefix (lgl), lgl->out);
1267   if (lgl->tid >= 0) fprintf (lgl->out, "%d ", lgl->tid);
1268   fprintf (lgl->out, "LOG%d %d ", level, lgl->level);
1269   va_start (ap, msg);
1270   vfprintf (lgl->out, msg, ap);
1271   va_end (ap);
1272 }
1273 
1274 #define lglogend lglmsgend
1275 #endif
1276 
1277 /*------------------------------------------------------------------------*/
1278 
lglprocesstime(void)1279 double lglprocesstime (void) {
1280   struct rusage u;
1281   double res;
1282   if (getrusage (RUSAGE_SELF, &u)) return 0;
1283   res = u.ru_utime.tv_sec + 1e-6 * u.ru_utime.tv_usec;
1284   res += u.ru_stime.tv_sec + 1e-6 * u.ru_stime.tv_usec;
1285   return res;
1286 }
1287 
lglgetime(LGL * lgl)1288 static double lglgetime (LGL * lgl) {
1289   lgl->stats->times++;
1290   if (lgl->cbs && lgl->cbs->getime) return lgl->cbs->getime ();
1291   else return lglprocesstime ();
1292 }
1293 
lglprofidx(LGL * lgl,double * timestatsptr)1294 static int lglprofidx (LGL * lgl, double * timestatsptr) {
1295   int res;
1296   assert ((double*) lgl->times <= timestatsptr);
1297   assert (timestatsptr < (double*)(sizeof *lgl->times + (char*) lgl->times));
1298   res = timestatsptr - (double*) lgl->times;
1299   return res;
1300 }
1301 
lglignprofidx(LGL * lgl,int idx)1302 static int lglignprofidx (LGL * lgl, int idx) {
1303   int res;
1304   assert (0 <= idx);
1305   assert (idx < sizeof (Times)/sizeof(double));
1306   switch (lgl->opts->profile.val) {
1307     case 0:  res = (TIMESLEVEL0IDX < idx); break;
1308     case 1:  res = (TIMESLEVEL1IDX < idx); break;
1309     case 2:  res = (TIMESLEVEL2IDX < idx); break;
1310     case 3:  res = (TIMESLEVEL3IDX < idx); break;
1311     default: res = 0;                      break;
1312   }
1313   return res;
1314 }
1315 
lglignprofptr(LGL * lgl,double * timestatsptr)1316 static int lglignprofptr (LGL * lgl, double * timestatsptr) {
1317   return lglignprofidx (lgl, lglprofidx (lgl, timestatsptr));
1318 }
1319 
lglstart(LGL * lgl,double * timestatsptr)1320 static void lglstart (LGL * lgl, double * timestatsptr) {
1321   Timer * timer;
1322   int ign, idx;
1323   idx = lglprofidx (lgl, timestatsptr);
1324   ign = lglignprofidx (lgl, idx);
1325   assert (lgl->timers->nest < MAXPHN);
1326   timer = lgl->timers->stk + lgl->timers->nest++;
1327   timer->idx = idx;
1328   if ((timer->ign = ign)) timer->start = 0;
1329   else timer->start = lglgetime (lgl);
1330 }
1331 
lglflushtimers(LGL * lgl)1332 void lglflushtimers (LGL * lgl) {
1333   double time = lglgetime (lgl), delta, entered, * ptr;
1334   Timer * timer;
1335   int nest;
1336   for (nest = 0; nest < lgl->timers->nest; nest++) {
1337     timer = lgl->timers->stk + nest;
1338     if (timer->ign) continue;
1339     entered = timer->start;
1340     timer->start = time;
1341     delta = time - entered;
1342     if (delta < 0) delta = 0;
1343     ptr = timer->idx + (double*)lgl->times;
1344     *ptr += delta;
1345   }
1346 }
1347 
lglsec(LGL * lgl)1348 double lglsec (LGL * lgl) {
1349   REQINIT ();
1350   lglflushtimers (lgl);
1351   return lgl->times->all;
1352 }
1353 
lglstop(LGL * lgl)1354 static void lglstop (LGL * lgl) {
1355   Timer * timer;
1356   assert (lgl->timers->nest > 0);
1357   timer = lgl->timers->stk + lgl->timers->nest - 1;
1358   if (!timer->ign) lglflushtimers (lgl);
1359   lgl->timers->nest--;
1360   assert (lgl->timers->nest >= 0);
1361 }
1362 
1363 /*------------------------------------------------------------------------*/
1364 
lglsetid(LGL * lgl,int tid,int tids)1365 void lglsetid (LGL * lgl, int tid, int tids) {
1366   REQINITNOTFORKED ();
1367   ABORTIF (tid < 0, "negative id");
1368   ABORTIF (tid >= tids, "id exceed number of ids");
1369   lgl->tid = tid;
1370   lgl->tids = tids;
1371 }
1372 
1373 /*------------------------------------------------------------------------*/
1374 
lglinc(LGL * lgl,size_t bytes)1375 static void lglinc (LGL * lgl, size_t bytes) {
1376   lgl->stats->bytes.current += bytes;
1377   if (lgl->stats->bytes.max < lgl->stats->bytes.current) {
1378     lgl->stats->bytes.max = lgl->stats->bytes.current;
1379     LOG (5, "maximum allocated %ld bytes", lgl->stats->bytes.max);
1380   }
1381 }
1382 
lgldec(LGL * lgl,size_t bytes)1383 static void lgldec (LGL * lgl, size_t bytes) {
1384   assert (lgl->stats->bytes.current >= bytes);
1385   lgl->stats->bytes.current -= bytes;
1386 }
1387 
lglnew(LGL * lgl,size_t bytes)1388 static void * lglnew (LGL * lgl, size_t bytes) {
1389   void * res;
1390   if (!bytes) return 0;
1391   if (lgl->mem->alloc) res = lgl->mem->alloc (lgl->mem->state, bytes);
1392   else res = malloc (bytes);
1393   if (!res) lgldie (lgl, "out of memory allocating %ld bytes", bytes);
1394   assert (res);
1395   LOG (5, "allocating %p with %ld bytes", res, bytes);
1396   lglinc (lgl, bytes);
1397   if (res) memset (res, 0, bytes);
1398   return res;
1399 }
1400 
lgldel(LGL * lgl,void * ptr,size_t bytes)1401 static void lgldel (LGL * lgl, void * ptr, size_t bytes) {
1402   if (!ptr) { assert (!bytes); return; }
1403   lgldec (lgl, bytes);
1404   LOG (5, "freeing %p with %ld bytes", ptr, bytes);
1405   if (lgl->mem->dealloc) lgl->mem->dealloc (lgl->mem->state, ptr, bytes);
1406   else free (ptr);
1407 }
1408 
lglrsz(LGL * lgl,void * ptr,size_t old,size_t new)1409 static void * lglrsz (LGL * lgl, void * ptr, size_t old, size_t new) {
1410   void * res;
1411   assert (!ptr == !old);
1412   if (!ptr) return lglnew (lgl, new);
1413   if (!new) { lgldel (lgl, ptr, old); return 0; }
1414   if (old == new) return ptr;
1415   lgldec (lgl, old);
1416   if (lgl->mem->realloc)
1417     res = lgl->mem->realloc (lgl->mem->state, ptr, old, new);
1418   else res = realloc (ptr, new);
1419   if (!res)
1420     lgldie (lgl, "out of memory reallocating %ld to %ld bytes", old, new);
1421   assert (res);
1422   LOG (5, "reallocating %p to %p from %ld to %ld bytes", ptr, res, old, new);
1423   lglinc (lgl, new);
1424   if (new > old) memset (res + old, 0, new - old);
1425   return res;
1426 }
1427 
1428 /*------------------------------------------------------------------------*/
1429 
lglstrdup(LGL * lgl,const char * str)1430 static char * lglstrdup (LGL * lgl, const char * str) {
1431   char * res;
1432   NEW (res, strlen (str) + 1);
1433   return strcpy (res, str);
1434 }
1435 
lgldelstr(LGL * lgl,char * str)1436 static void lgldelstr (LGL * lgl, char * str) {
1437   DEL (str, strlen (str) + 1);
1438 }
1439 
1440 /*------------------------------------------------------------------------*/
1441 
lglinitcbs(LGL * lgl)1442 static void lglinitcbs (LGL * lgl) {
1443   if (!lgl->cbs) NEW (lgl->cbs, 1);
1444 }
1445 
lglonabort(LGL * lgl,void * abortstate,void (* onabort)(void *))1446 void lglonabort (LGL * lgl, void * abortstate, void (*onabort)(void*)) {
1447   REQINITNOTFORKED ();
1448   lglinitcbs (lgl);
1449   lgl->cbs->abortstate = abortstate;
1450   lgl->cbs->onabort = onabort;
1451 }
1452 
lglseterm(LGL * lgl,int (* fun)(void *),void * state)1453 void lglseterm (LGL * lgl, int (*fun)(void*), void * state) {
1454   REQINITNOTFORKED ();
1455   lglinitcbs (lgl);
1456   lgl->cbs->term.fun = fun;
1457   lgl->cbs->term.state = state;
1458 }
1459 
lglsetproduceunit(LGL * lgl,void (* fun)(void *,int),void * state)1460 void lglsetproduceunit (LGL * lgl, void (*fun) (void*, int), void * state) {
1461   REQINITNOTFORKED ();
1462   lglinitcbs (lgl);
1463   lgl->cbs->units.produce.fun = fun;
1464   lgl->cbs->units.produce.state = state;
1465 }
1466 
lglsetconsumeunits(LGL * lgl,void (* fun)(void *,int **,int **),void * state)1467 void lglsetconsumeunits (LGL * lgl,
1468 			 void (*fun) (void*, int **, int **),
1469 			 void * state) {
1470   REQINITNOTFORKED ();
1471   lglinitcbs (lgl);
1472   lgl->cbs->units.consume.fun =  fun;
1473   lgl->cbs->units.consume.state = state;
1474 }
1475 
lglsetconsumedunits(LGL * lgl,void (* fun)(void *,int),void * state)1476 void lglsetconsumedunits (LGL * lgl,
1477 			  void (*fun) (void*, int), void * state) {
1478   REQINITNOTFORKED ();
1479   lglinitcbs (lgl);
1480   lgl->cbs->units.consumed.fun = fun;
1481   lgl->cbs->units.consumed.state = state;
1482 }
1483 
lglsetproducecls(LGL * lgl,void (* fun)(void *,int *,int),void * state)1484 void lglsetproducecls (LGL * lgl,
1485                        void (*fun) (void*, int *, int), void * state) {
1486   REQINITNOTFORKED ();
1487   lglinitcbs (lgl);
1488   lgl->cbs->cls.produce.fun = fun;
1489   lgl->cbs->cls.produce.state = state;
1490 }
1491 
lglsetconsumecls(LGL * lgl,void (* fun)(void *,int **,int *),void * state)1492 void lglsetconsumecls (LGL * lgl,
1493 		       void (*fun) (void*, int **, int *),
1494 		       void * state) {
1495   REQINITNOTFORKED ();
1496   lglinitcbs (lgl);
1497   lgl->cbs->cls.consume.fun =  fun;
1498   lgl->cbs->cls.consume.state = state;
1499 }
1500 
lglsetconsumedcls(LGL * lgl,void (* fun)(void *,int),void * state)1501 void lglsetconsumedcls (LGL * lgl,
1502 			void (*fun) (void*, int), void * state) {
1503   REQINITNOTFORKED ();
1504   lglinitcbs (lgl);
1505   lgl->cbs->cls.consumed.fun = fun;
1506   lgl->cbs->cls.consumed.state = state;
1507 }
1508 
lglsetlockeq(LGL * lgl,int * (* fun)(void *),void * state)1509 void lglsetlockeq (LGL * lgl, int * (*fun)(void*), void * state) {
1510   REQINITNOTFORKED ();
1511   lglinitcbs (lgl);
1512   lgl->cbs->eqs.lock.fun = fun;
1513   lgl->cbs->eqs.lock.state = state;
1514 }
1515 
lglsetunlockeq(LGL * lgl,void (* fun)(void *,int,int),void * state)1516 void lglsetunlockeq (LGL * lgl, void (*fun)(void*,int,int), void * state) {
1517   REQINITNOTFORKED ();
1518   lglinitcbs (lgl);
1519   lgl->cbs->eqs.unlock.fun = fun;
1520   lgl->cbs->eqs.unlock.state = state;
1521 }
1522 
lglsetmsglock(LGL * lgl,void (* lock)(void *),void (* unlock)(void *),void * state)1523 void lglsetmsglock (LGL * lgl,
1524 		    void (*lock)(void*), void (*unlock)(void*),
1525 		    void * state) {
1526   REQINITNOTFORKED ();
1527   lglinitcbs (lgl);
1528   lgl->cbs->msglock.lock = lock;
1529   lgl->cbs->msglock.unlock = unlock;
1530   lgl->cbs->msglock.state = state;
1531 }
1532 
lglsetime(LGL * lgl,double (* time)(void))1533 void lglsetime (LGL * lgl, double (*time)(void)) {
1534   REQINITNOTFORKED ();
1535   lglinitcbs (lgl);
1536   lgl->cbs->getime = time;
1537 }
1538 
1539 /*------------------------------------------------------------------------*/
1540 
lglfullstk(Stk * s)1541 static int lglfullstk (Stk * s) { return s->top == s->end; }
lglmtstk(Stk * s)1542 static int lglmtstk (Stk * s) { return s->top == s->start; }
lglcntstk(Stk * s)1543 static size_t lglcntstk (Stk * s) { return s->top - s->start; }
lglszstk(Stk * s)1544 static size_t lglszstk (Stk * s) { return s->end - s->start; }
1545 
lglpeek(Stk * s,int pos)1546 static int lglpeek (Stk * s, int pos) {
1547   assert (0 <= pos && pos < lglszstk (s));
1548   return s->start[pos];
1549 }
1550 
lglpoke(Stk * s,int pos,int val)1551 static void lglpoke (Stk * s, int pos, int val) {
1552   assert (0 <= pos && pos <= lglszstk (s));
1553   s->start[pos] = val;
1554 }
1555 
lglenlstk(LGL * lgl,Stk * s)1556 static void lglenlstk (LGL * lgl, Stk * s) {
1557   size_t old_size = lglszstk (s);
1558   size_t new_size = old_size ? 2 * old_size : 1;
1559   size_t count = lglcntstk (s);
1560   RSZ (s->start, old_size, new_size);
1561   s->top = s->start + count;
1562   s->end = s->start + new_size;
1563 }
1564 
lglrelstk(LGL * lgl,Stk * s)1565 static void lglrelstk (LGL * lgl, Stk * s) {
1566   DEL (s->start, lglszstk (s));
1567   CLRPTR (s);
1568 }
1569 
lglshrstk(LGL * lgl,Stk * s,int new_size)1570 static void lglshrstk (LGL * lgl, Stk * s, int new_size) {
1571   size_t old_size, count = lglcntstk (s);
1572   assert (new_size >= 0);
1573   assert (count <= new_size);
1574   if (new_size > 0) {
1575     old_size = lglszstk (s);
1576     RSZ (s->start, old_size, new_size);
1577     s->top = s->start + count;
1578     s->end = s->start + new_size;
1579   } else lglrelstk (lgl, s);
1580 }
1581 
lglfitstk(LGL * lgl,Stk * s)1582 static void lglfitstk (LGL * lgl, Stk * s) {
1583   lglshrstk (lgl, s, lglcntstk (s));
1584 }
1585 
lglpushstk(LGL * lgl,Stk * s,int elem)1586 static void lglpushstk (LGL * lgl, Stk * s, int elem) {
1587   if (lglfullstk (s)) lglenlstk (lgl, s);
1588   *s->top++ = elem;
1589 }
1590 
lglrmstk(Stk * s,int elem)1591 static void lglrmstk (Stk * s, int elem) {
1592   int * p, * q;
1593   for (p = s->start; p < s->top; p++)
1594     if (*p == elem) break;
1595   assert (p < s->top);
1596   q = p++;
1597   while (p < s->top)
1598     *q++ = *p++;
1599   s->top = q;
1600 }
1601 
lglpopstk(Stk * s)1602 static int lglpopstk (Stk * s) { assert (!lglmtstk (s)); return *--s->top; }
1603 
lgltopstk(Stk * s)1604 static int lgltopstk (Stk * s) { assert (!lglmtstk (s)); return s->top[-1]; }
1605 
lglrststk(Stk * s,int newsz)1606 static void lglrststk (Stk * s, int newsz) {
1607   assert (0 <= newsz && newsz <= lglcntstk (s));
1608   s->top = s->start + newsz;
1609 }
1610 
lglclnstk(Stk * s)1611 static void lglclnstk (Stk * s) { lglrststk (s, 0); }
1612 
1613 /*------------------------------------------------------------------------*/
1614 
lgltrapi(LGL * lgl,const char * msg,...)1615 static void lgltrapi (LGL * lgl, const char * msg, ...) {
1616   va_list ap;
1617   assert (lgl->apitrace);
1618   va_start (ap, msg);
1619   vfprintf (lgl->apitrace, msg, ap);
1620   va_end (ap);
1621   fputc ('\n', lgl->apitrace);
1622   if (lgl->opts->trapiflush.val) fflush (lgl->apitrace);
1623 }
1624 
lglopenapitrace(LGL * lgl,const char * name)1625 static void lglopenapitrace (LGL * lgl, const char * name) {
1626   FILE * file;
1627   char * cmd;
1628   int len;
1629   len = strlen (name);
1630   if (len >= 3 && !strcmp (name + len - 3, ".gz")) {
1631     len += 20;
1632     NEW (cmd, len);
1633     sprintf (cmd, "gzip -c > %s", name);
1634     file = popen (cmd, "w");
1635     DEL (cmd, len);
1636     if (file) lgl->closeapitrace = 2;
1637   } else {
1638     file = fopen (name, "w");
1639     if (file) lgl->closeapitrace = 1;
1640   }
1641   if (file) lgl->apitrace = file;
1642   else lglwrn (lgl, "can not write API trace to '%s'", name);
1643   TRAPI ("init");
1644 }
1645 
lglwtrapi(LGL * lgl,FILE * apitrace)1646 void lglwtrapi (LGL * lgl, FILE * apitrace) {
1647   REQUIRE (UNUSED);
1648   ABORTIF (lgl->apitrace, "can only write one API trace");
1649   lgl->apitrace = apitrace;
1650   TRAPI ("init");
1651 }
1652 
1653 /*------------------------------------------------------------------------*/
1654 
lglrand(LGL * lgl)1655 static unsigned lglrand (LGL * lgl) {
1656   unsigned res;
1657   lgl->rng.z = 36969 * (lgl->rng.z & 65535) + (lgl->rng.z >> 16);
1658   lgl->rng.w = 18000 * (lgl->rng.w & 65535) + (lgl->rng.w >> 16);
1659   res = (lgl->rng.z << 16) + lgl->rng.w;
1660   LOG (5, "rng %u", res);
1661   return res;
1662 }
1663 
1664 /*------------------------------------------------------------------------*/
1665 
lglmtftk(Ftk * ftk)1666 static int lglmtftk (Ftk * ftk) { return ftk->top == ftk->start; }
1667 
lglfullftk(Ftk * ftk)1668 static int lglfullftk (Ftk * ftk) { return ftk->top == ftk->end; }
1669 
lglsizeftk(Ftk * ftk)1670 static int lglsizeftk (Ftk * ftk) { return ftk->end - ftk->start; }
1671 
lglcntftk(Ftk * ftk)1672 static int lglcntftk (Ftk * ftk) { return ftk->top - ftk->start; }
1673 
lglrelftk(LGL * lgl,Ftk * ftk)1674 static void lglrelftk (LGL * lgl, Ftk * ftk) {
1675   DEL (ftk->start, lglsizeftk (ftk));
1676   memset (ftk, 0, sizeof *ftk);
1677 }
1678 
lglenlftk(LGL * lgl,Ftk * ftk)1679 static void lglenlftk (LGL * lgl, Ftk * ftk) {
1680   int oldsize = lglsizeftk (ftk);
1681   int newsize = oldsize ? 2*oldsize : 1;
1682   int count = lglcntftk (ftk);
1683   RSZ (ftk->start, oldsize, newsize);
1684   ftk->top = ftk->start + count;
1685   ftk->end = ftk->start + newsize;
1686 }
1687 
lglpushftk(LGL * lgl,Ftk * ftk,Flt f)1688 static void lglpushftk (LGL * lgl, Ftk * ftk, Flt f) {
1689   if (lglfullftk (ftk)) lglenlftk (lgl, ftk);
1690   *ftk->top++ = f;
1691 }
1692 
lgltopftk(Ftk * ftk)1693 static Flt lgltopftk (Ftk * ftk) {
1694   assert (!lglmtftk (ftk));
1695   return ftk->top[-1];
1696 }
1697 
lglpopftk(Ftk * ftk)1698 static Flt lglpopftk (Ftk * ftk) {
1699   assert (!lglmtftk (ftk));
1700   return *--ftk->top;
1701 }
1702 
1703 /*------------------------------------------------------------------------*/
1704 
lglfullctk(Ctk * ctk)1705 static int lglfullctk (Ctk * ctk) { return ctk->top == ctk->end; }
1706 
lglsizectk(Ctk * ctk)1707 static int lglsizectk (Ctk * ctk) { return ctk->end - ctk->start; }
1708 
lglcntctk(Ctk * ctk)1709 static int lglcntctk (Ctk * ctk) { return ctk->top - ctk->start; }
1710 
lglrelctk(LGL * lgl,Ctk * ctk)1711 static void lglrelctk (LGL * lgl, Ctk * ctk) {
1712   DEL (ctk->start, lglsizectk (ctk));
1713   memset (ctk, 0, sizeof *ctk);
1714 }
1715 
lglenlctk(LGL * lgl,Ctk * ctk)1716 static void lglenlctk (LGL * lgl, Ctk * ctk) {
1717   int oldsize = lglsizectk (ctk);
1718   int newsize = oldsize ? 2*oldsize : 1;
1719   int count = lglcntctk (ctk);
1720   RSZ (ctk->start, oldsize, newsize);
1721   ctk->top = ctk->start + count;
1722   ctk->end = ctk->start + newsize;
1723 }
1724 
lglpushcontrol(LGL * lgl,int decision)1725 static void lglpushcontrol (LGL * lgl, int decision) {
1726   Ctk * ctk = &lgl->control;
1727   Ctr * ctr;
1728   if (lglfullctk (ctk)) lglenlctk (lgl, ctk);
1729   ctr = ctk->top++;
1730   ctr->decision = decision;
1731   ctr->used = 0;
1732   ctr->used2 = 0;
1733 }
1734 
lglpopcontrol(LGL * lgl)1735 static void lglpopcontrol (LGL * lgl) {
1736   assert (lgl->control.top > lgl->control.start);
1737   --lgl->control.top;
1738 }
1739 
lglrstcontrol(LGL * lgl,int count)1740 static void lglrstcontrol (LGL * lgl, int count) {
1741   while (lglcntctk (&lgl->control) > count)
1742     lglpopcontrol (lgl);
1743 }
1744 
lglctr(LGL * lgl,int level)1745 static Ctr * lglctr (LGL * lgl, int level) {
1746   Ctk * ctk = &lgl->control;
1747   Ctr * res;
1748   assert (0 < level && level < lglsizectk (ctk));
1749   res = ctk->start + level;
1750   return res;
1751 }
1752 
lglevelused(LGL * lgl,int level)1753 static unsigned lglevelused (LGL * lgl, int level) {
1754   return lglctr (lgl, level)->used;
1755 }
1756 
lgluselevel(LGL * lgl,int level)1757 static void lgluselevel (LGL * lgl, int level) {
1758   Ctk * ctk = &lgl->control;
1759   Ctr * ctr;
1760   assert (0 < level && level < lglsizectk (ctk));
1761   ctr = ctk->start + level;
1762   if (!ctr->used) {
1763     lglpushstk (lgl, &lgl->frames, level);
1764     LOG (2, "pulled in decision level %d", level);
1765     ctr->used = 1;
1766   } else if (ctr->used == 1) {
1767     LOG (2, "pulled in decision level %d a second time", level);
1768     ctr->used = 2;
1769   }
1770 }
1771 
lglunuselevel(LGL * lgl,int level)1772 static void lglunuselevel (LGL * lgl, int level) {
1773   Ctk * ctk = &lgl->control;
1774   Ctr * ctr;
1775   assert (0 < level);
1776   if (level >= lglcntctk (ctk)) return;
1777   ctr = ctk->start + level;
1778   assert (ctr->used > 0);
1779   ctr->used = 0;
1780 }
1781 
1782 /*------------------------------------------------------------------------*/
1783 
lglgetenv(LGL * lgl,Opt * opt,const char * lname)1784 void lglgetenv (LGL * lgl, Opt * opt, const char * lname) {
1785   const char * q, * valstr;
1786   char uname[40], * p;
1787   int newval, oldval;
1788   assert (strlen (lname) + 3 + 1 < sizeof (uname));
1789   uname[0] = 'L'; uname[1] = 'G'; uname[2] = 'L';
1790   p = uname + 3;
1791   for (q = lname; *q; q++) {
1792     assert (p < uname + sizeof uname);
1793     *p++ = toupper (*q);
1794   }
1795   assert (p < uname + sizeof uname);
1796   *p = 0;
1797   valstr = getenv (uname);
1798   if (!valstr) return;
1799   oldval = opt->val;
1800   newval = atoi (valstr);
1801   if (newval < opt->min) newval = opt->min;
1802   if (newval > opt->max) newval = opt->max;
1803   if (newval == oldval) return;
1804   opt->val = newval;
1805   TRAPI ("option %s %d", lname, newval);
1806   COVER (lgl->clone);
1807   if (lgl->clone) lglsetopt (lgl->clone, lname, newval);
1808 }
1809 
lglchkenv(LGL * lgl)1810 static void lglchkenv (LGL * lgl) {
1811   extern char ** environ;
1812   char * src, *eos, * dst;
1813   char ** p, * s, * d;
1814   int len;
1815   for (p = environ; (src = *p); p++) {
1816     if (src[0] != 'L' || src[1] != 'G' || src[2] != 'L') continue;
1817     for (eos = src; *eos && *eos != '='; eos++)
1818       ;
1819     len = eos - (src + 3);
1820     NEW (dst, len + 1);
1821     d = dst;
1822     for (s = src + 3; s < eos; s++) *d++ = tolower (*s);
1823     *d = 0;
1824     if (!lglhasopt (lgl, dst) && strcmp (dst, "apitrace"))
1825       lglwrn (lgl, "invalid 'LGL...' environment '%s'", src);
1826     DEL (dst, len + 1);
1827   }
1828 }
1829 
1830 #define SETPLAIN(NAME) \
1831 do { \
1832   if (val) lgl->opts->NAME.val = 0; \
1833   else lgl->opts->NAME.val = lgl->opts->NAME.dflt; \
1834 } while (0)
1835 
1836 #define SETDRUP SETPLAIN
1837 
lglforcedruplig(LGL * lgl,int val)1838 static void lglforcedruplig (LGL * lgl, int val) {
1839   SETDRUP (bca);
1840   SETDRUP (card);
1841   SETDRUP (gauss);
1842   SETDRUP (smallve);
1843   SETDRUP (unhide);
1844 }
1845 
lglsetdruplig(LGL * lgl,int val)1846 static void lglsetdruplig (LGL * lgl, int val) {
1847   lglforcedruplig (lgl, val);
1848   lglprt (lgl, 1,
1849     "[druplig] druplig checking switched %s",
1850     val ? "on" : "off");
1851 }
1852 
lglsetplain(LGL * lgl,int val)1853 static void lglsetplain (LGL * lgl, int val) {
1854   SETPLAIN (bca);
1855   SETPLAIN (block);
1856   SETPLAIN (card);
1857   SETPLAIN (cce);
1858   SETPLAIN (decompose);
1859   SETPLAIN (elim);
1860   SETPLAIN (gauss);
1861   SETPLAIN (locs);
1862   SETPLAIN (probe);
1863   SETPLAIN (quatres);
1864   SETPLAIN (sweep);
1865   SETPLAIN (ternres);
1866   SETPLAIN (transred);
1867   SETPLAIN (unhide);
1868   lglprt (lgl, 1, "[plain] plain solving switched %s", val ? "on" : "off");
1869 }
1870 
1871 #define SETWAIT(NAME) \
1872 do { \
1873   if (val) lgl->opts->NAME.val = lgl->opts->NAME.dflt; \
1874   else lgl->opts->NAME.val = 0; \
1875 } while (0)
1876 
lglsetwait(LGL * lgl,int val)1877 static void lglsetwait (LGL * lgl, int val) {
1878   SETWAIT (batewait);
1879   SETWAIT (bcawait);
1880   SETWAIT (blockwait);
1881   SETWAIT (ccewait);
1882   SETWAIT (elmblkwait);
1883   SETWAIT (gausswait);
1884   SETWAIT (smallvewait);
1885   SETWAIT (sweepwait);
1886   SETWAIT (ternreswait);
1887   SETWAIT (transredwait);
1888   SETWAIT (unhidewait);
1889   lglprt (lgl, 1, "[wait] waiting %s", val ? "enabled" : "disabled");
1890 }
1891 
lglnewlgl(void * mem,lglalloc alloc,lglrealloc realloc,lgldealloc dealloc)1892 static LGL * lglnewlgl (void * mem,
1893 			lglalloc alloc,
1894 			lglrealloc realloc,
1895 			lgldealloc dealloc) {
1896   LGL * lgl = alloc ? alloc (mem, sizeof *lgl) : malloc (sizeof *lgl);
1897   ABORTIF (!lgl, "out of memory allocating main solver object");
1898   CLRPTR (lgl);
1899 
1900   lgl->mem = alloc ? alloc (mem, sizeof *lgl->mem) : malloc (sizeof *lgl->mem);
1901   ABORTIF (!lgl->mem, "out of memory allocating memory manager object");
1902 
1903   lgl->mem->state = mem;
1904   lgl->mem->alloc = alloc;
1905   lgl->mem->realloc = realloc;
1906   lgl->mem->dealloc = dealloc;
1907 
1908   lgl->opts = alloc ? alloc (mem, sizeof (Opts)) : malloc (sizeof (Opts));
1909   ABORTIF (!lgl->opts, "out of memory allocating option manager object");
1910   CLRPTR (lgl->opts);
1911 
1912   lgl->stats = alloc ? alloc (mem, sizeof (Stats)) : malloc (sizeof (Stats));
1913   ABORTIF (!lgl->stats, "out of memory allocating statistic counters");
1914   CLRPTR (lgl->stats);
1915 
1916   lglinc (lgl, sizeof *lgl);
1917   lglinc (lgl, sizeof *lgl->mem);
1918   lglinc (lgl, sizeof *lgl->opts);
1919   lglinc (lgl, sizeof *lgl->stats);
1920 
1921   return lgl;
1922 }
1923 
lglsetmaxminscore(LGL * lgl)1924 static void lglsetmaxminscore (LGL * lgl) {
1925   Flt oldmaxscore = lgl->maxscore, oldminscore = lgl->minscore;
1926   lgl->maxscore = lglflt (DEFSCOREXP, 1);
1927   lgl->minscore = lglflt (-DEFSCOREXP, 1);
1928   if (oldmaxscore != lgl->maxscore)
1929     lglprt (lgl, 1,
1930       "[set-maximum-score] maximum score limit %s",
1931       lglscr2str (lgl, lgl->maxscore));
1932   if (oldminscore != lgl->minscore)
1933     lglprt (lgl, 1,
1934       "[set-minimum-score] minimum score limit %s",
1935       lglscr2str (lgl, lgl->minscore));
1936 }
1937 
lglsetscincf(LGL * lgl,int scincinc)1938 static void lglsetscincf (LGL * lgl, int scincinc) {
1939   if (scincinc == lgl->scincinc) return;
1940   lgl->scincf = lglrat (1000 + scincinc, 1000);
1941   if (!lgl->stats->setscincf.count++)
1942     lgl->stats->setscincf.min = lgl->stats->setscincf.max = scincinc;
1943   else {
1944     if (scincinc < lgl->stats->setscincf.min)
1945       lgl->stats->setscincf.min = scincinc;
1946     if (scincinc > lgl->stats->setscincf.max)
1947       lgl->stats->setscincf.max = scincinc;
1948   }
1949   lglprt (lgl, 2,
1950     "[set-score-increment-%d] factor %s (%d/1000) after %lld conflicts",
1951     lgl->stats->setscincf.count,
1952     lglscr2str (lgl, lgl->scincf), scincinc, (LGLL) lgl->stats->confs);
1953   lgl->scincinc = scincinc;
1954 }
1955 
lglinitscores(LGL * lgl)1956 static void lglinitscores (LGL * lgl) {
1957   lglsetmaxminscore (lgl);
1958   lglsetscincf (lgl, lgl->opts->scincinc.val);
1959 }
1960 
lglminit(void * mem,lglalloc alloc,lglrealloc realloc,lgldealloc dealloc)1961 LGL * lglminit (void * mem,
1962 		lglalloc alloc,
1963 		lglrealloc realloc,
1964 		lgldealloc dealloc) {
1965   const char * apitracename;
1966   LGL * lgl;
1967   int i;
1968 
1969   lgl = 0;
1970   ABORTIF (!alloc+!realloc+!dealloc != 0 && !alloc+!realloc+!dealloc != 3,
1971 	   "inconsistent set of external memory handlers");
1972 
1973   assert (sizeof (long) == sizeof (void*));
1974 
1975   assert (REMOVED > (RMSHFTLIT (MAXVAR) | MASKCS | REDCS));
1976   assert (REMOVED > MAXREDLIDX);
1977   assert (REMOVED > MAXIRRLIDX);
1978 
1979   assert (MAXREDLIDX == MAXIRRLIDX);
1980   assert (GLUESHFT == RMSHFT);
1981 
1982   assert (INT_MAX > ((MAXREDLIDX << GLUESHFT) | GLUEMASK));
1983   assert (INT_MAX > ((MAXIRRLIDX << RMSHFT) | MASKCS | REDCS));
1984 
1985   assert (MAXGLUE < POW2GLUE);
1986 
1987   lgl = lglnewlgl (mem, alloc, realloc, dealloc);
1988   lgl->tid = -1;
1989 
1990   lglpushcontrol (lgl, 0);
1991   assert (lglcntctk (&lgl->control) == lgl->level + 1);
1992 
1993   lgl->out = stdout;
1994   lgl->prefix = lglstrdup (lgl, "c ");
1995 
1996   apitracename = getenv ("LGLAPITRACE");
1997   if (apitracename) lglopenapitrace (lgl, apitracename);
1998 
1999   lglinitopts (lgl, lgl->opts);
2000 
2001   if (lgl->opts->plain.val) lglsetplain (lgl, 1);
2002   if (lgl->opts->druplig.val) lglsetdruplig (lgl, 1);
2003   if (!lgl->opts->wait.val) lglsetwait (lgl, 0);
2004 
2005   NEW (lgl->times, 1);
2006   NEW (lgl->timers, 1);
2007   NEW (lgl->limits, 1);
2008   NEW (lgl->fltstr, 1);
2009   NEW (lgl->red, MAXGLUE+1);
2010   NEW (lgl->wchs, 1);
2011   for (i = 0; i < MAXLDFW; i++) lgl->wchs->start[i] = INT_MAX;
2012   lglpushstk (lgl, &lgl->wchs->stk, INT_MAX);
2013   lglpushstk (lgl, &lgl->wchs->stk, INT_MAX);
2014 
2015   lgl->scinc = lglflt (0, 1);
2016 
2017   TRANS (UNUSED);
2018 
2019   return lgl;
2020 }
2021 
lglcopyclonenfork(LGL * dst,LGL * src)2022 static void lglcopyclonenfork (LGL * dst, LGL * src) {
2023   memcpy (dst->opts, src->opts, sizeof *src->opts);
2024   dst->out = src->out;
2025   if (dst->prefix) lgldelstr (dst, dst->prefix);
2026   dst->prefix = lglstrdup (dst, src->prefix);
2027   if (src->cbs) {
2028     lglinitcbs (dst);
2029     if (src->cbs->onabort) {
2030       dst->cbs->abortstate = src->cbs->abortstate;
2031       dst->cbs->onabort = src->cbs->onabort;
2032     }
2033     if (src->cbs->getime) dst->cbs->getime = src->cbs->getime;
2034   }
2035 }
2036 
2037 static void lglcompact (LGL *);
2038 
lglmclone(LGL * orig,void * mem,lglalloc alloc,lglrealloc realloc,lgldealloc dealloc)2039 LGL * lglmclone (LGL * orig,
2040 		 void * mem,
2041 		 lglalloc alloc,
2042 		 lglrealloc realloc,
2043 		 lgldealloc dealloc) {
2044   size_t max_bytes, current_bytes;
2045   LGL * lgl = orig;
2046   int glue;
2047 
2048   if (!orig) return 0;
2049   lglcompact (orig);
2050   LOG (1, "cloning");
2051   lgl = lglnewlgl (mem, alloc, realloc, dealloc);
2052   memcpy (lgl, orig, ((char*)&orig->mem) - (char*) orig);
2053   max_bytes = lgl->stats->bytes.max;
2054   current_bytes = lgl->stats->bytes.current;
2055   memcpy (lgl->stats, orig->stats, sizeof *orig->stats);
2056   lgl->stats->bytes.current = current_bytes;
2057   lgl->stats->bytes.max = max_bytes;
2058 
2059   lglcopyclonenfork (lgl, orig);
2060 
2061   CLONE (limits, 1);
2062   CLONE (times, 1);
2063   CLONE (timers, 1);		assert (!lgl->timers->nest);
2064   CLONE (fltstr, 1);
2065   CLONE (ext, orig->szext);
2066   CLONE (i2e, orig->szvars);
2067   CLONE (doms, 2*orig->szvars);
2068   CLONE (dvars, orig->szvars);
2069   CLONE (qvars, orig->szvars);
2070   CLONE (avars, orig->szvars);
2071   CLONE (vals, orig->szvars);
2072   CLONE (jwh, 2*orig->szvars);
2073   CLONE (drail, orig->szdrail);
2074 
2075   NEW (lgl->red, MAXGLUE+1);
2076   for (glue = 0; glue <= MAXGLUE; glue++) CLONESTK (red[glue]);
2077 
2078   NEW (lgl->wchs, 1);
2079   memcpy (lgl->wchs, orig->wchs, sizeof *orig->wchs);
2080   CLONESTK (wchs->stk);
2081 
2082   CLONESTK (control);
2083 #ifndef NDEBUG
2084   CLONESTK (prevclause);
2085   lgl->prevglue = orig->prevglue;
2086 #endif
2087   CLONESTK (clause);
2088   CLONESTK (eclause);
2089   CLONESTK (extend);
2090   CLONESTK (irr);
2091   CLONESTK (trail);
2092   CLONESTK (frames);
2093   CLONESTK (promote);
2094   CLONESTK (eassume);
2095   CLONESTK (assume);
2096   CLONESTK (learned);
2097   CLONESTK (dsched);
2098 
2099   CLONESTK (queue.stk);
2100   lgl->queue.mt = orig->queue.mt;
2101   lgl->queue.next = orig->queue.next;
2102 
2103 #ifndef NCHKSOL
2104   CLONESTK (orig);
2105 #endif
2106 #ifndef NDEBUG
2107   {
2108     const char * p;
2109     for (p = (char*)&orig->elm; p < (char*)(&orig->repr+1); p++) assert (!*p);
2110   }
2111 #endif
2112   assert (lgl->stats->bytes.current == orig->stats->bytes.current);
2113   assert (lgl->stats->bytes.max <= orig->stats->bytes.max);
2114   lgl->stats->bytes.max = orig->stats->bytes.max;
2115   return lgl;
2116 }
2117 
lglclone(LGL * lgl)2118 LGL * lglclone (LGL * lgl) {
2119   REQINIT ();
2120   ABORTIF (lgl->opts->druplig.val,
2121     "can not clone if Druplig checking is enabled");
2122   return lglmclone (lgl,
2123                     lgl->mem->state,
2124                     lgl->mem->alloc,
2125                     lgl->mem->realloc,
2126                     lgl->mem->dealloc);
2127 }
2128 
lglchkclone(LGL * lgl)2129 void lglchkclone (LGL * lgl) {
2130   REQINITNOTFORKED ();
2131   TRAPI ("chkclone");
2132 }
2133 
lglinit(void)2134 LGL * lglinit (void) { return lglminit (0, 0, 0, 0); }
2135 
lglmaxoptnamelen(LGL * lgl)2136 static int lglmaxoptnamelen (LGL * lgl) {
2137   int res = 0, len;
2138   Opt * o;
2139   for (o = FIRSTOPT (lgl); o <= LASTOPT (lgl); o++)
2140     if ((len = strlen (o->lng)) > res)
2141       res = len;
2142   return res;
2143 }
2144 
lglusage(LGL * lgl)2145 void lglusage (LGL * lgl) {
2146   char fmt[20];
2147   int len;
2148   Opt * o;
2149   REQINITNOTFORKED ();
2150   len = lglmaxoptnamelen (lgl);
2151   sprintf (fmt, "--%%-%ds", len);
2152   for (o = FIRSTOPT (lgl); o <= LASTOPT (lgl); o++) {
2153     fprintf (lgl->out, "   ");
2154     fprintf (lgl->out, fmt, o->lng);
2155     fprintf (lgl->out, " %s [%d]\n", o->descrp, o->val);
2156   }
2157 }
2158 
lglstrhasprefix(const char * str,const char * prefix)2159 static int lglstrhasprefix (const char * str, const char * prefix) {
2160   const char * p, * q;
2161   for (p = str, q = prefix; *q && *p == *q; p++, q++)
2162     ;
2163   return !*q;
2164 }
2165 
lglignopt(const char * name)2166 static int lglignopt (const char * name) {
2167   if (!strcmp (name, "abstime")) return 1;
2168   if (!strcmp (name, "check")) return 1;
2169   if (lglstrhasprefix (name, "drup")) return 1;
2170   if (!strcmp (name, "exitonabort")) return 1;
2171   if (!strcmp (name, "log")) return 1;
2172   if (!strcmp (name, "sleeponabort")) return 1;
2173   if (!strcmp (name, "verbose")) return 1;
2174   if (!strcmp (name, "witness")) return 1;
2175   return 0;
2176 }
2177 
lglopts(LGL * lgl,const char * prefix,int ignsome)2178 void lglopts (LGL * lgl, const char * prefix, int ignsome) {
2179   Opt * o;
2180   REQINITNOTFORKED ();
2181   for (o = FIRSTOPT (lgl); o <= LASTOPT (lgl); o++) {
2182     if (ignsome && lglignopt (o->lng)) continue;
2183     fprintf (lgl->out, "%s--%s=%d\n", prefix, o->lng, o->val);
2184   }
2185 }
2186 
lglrgopts(LGL * lgl)2187 void lglrgopts (LGL * lgl) {
2188   Opt * o;
2189   REQINITNOTFORKED ();
2190   for (o = FIRSTOPT (lgl); o <= LASTOPT (lgl); o++)
2191     fprintf (lgl->out, "%s %d %d %d\n", o->lng, o->val, o->min, o->max);
2192 }
2193 
lglpcs(LGL * lgl,int mixed)2194 void lglpcs (LGL * lgl, int mixed) {
2195   int i, printi, printl;
2196   int64_t range;
2197   Opt * o;
2198   REQINITNOTFORKED ();
2199   for (o = FIRSTOPT (lgl); o <= LASTOPT (lgl); o++) {
2200     if (lglignopt (o->lng)) continue;
2201     range = o->max; range -= o->min;
2202     if (range >= 7 && mixed < 0) continue;
2203     printi = printl = 0;
2204     printf ("%s ", o->lng);
2205     if (range < 7) {
2206       printf ("{%d", o->min);
2207       for (i = o->min + 1; i <= o->max; i++) printf (",%d", i);
2208       printf ("}");
2209     } else if (!mixed) {
2210       printf ("[%d,%d]", o->min, o->max);
2211       printi = 1;
2212       printl = (o->min > 0 && range >= 100);
2213     } else if (o->dflt == o->min || o->dflt == o->max) {
2214       printf ("{%d,%d,%d,%d,%d}",
2215         o->min,
2216         (int)(o->min + (1*range + 3)/4),
2217         (int)(o->min + (2*range + 3)/4),
2218         (int)(o->min + (3*range + 3)/4),
2219         o->max);
2220     } else if (o->dflt == o->min + 1) {
2221       printf ("{%d,%d,%d,%d}",
2222         o->min,
2223 	o->dflt,
2224 	(int)(o->dflt + (o->max - (int64_t) o->dflt)/2),
2225 	o->max);
2226     } else if (o->dflt + 1 == o->max) {
2227       printf ("{%d,%d,%d,%d}",
2228         o->min,
2229 	(int)(o->min + (o->dflt - (int64_t) o->min)/2),
2230 	o->dflt,
2231 	o->max);
2232     } else {
2233       assert (o->dflt - o->min >= 2);
2234       assert (o->max - o->dflt >= 2);
2235       printf ("{%d,%d,%d,%d,%d}",
2236         o->min,
2237 	(int)(o->min + (o->dflt - (int64_t) o->min)/2),
2238         o->dflt,
2239         (int)(o->dflt + (o->max - (int64_t) o->min)/2),
2240 	o->max);
2241     }
2242     printf ("[%d]", o->dflt);
2243     if (printi) printf ("i");
2244     if (printl) printf ("l");
2245     printf (" # %s\n",o->descrp);
2246   }
2247 }
2248 
lglhasopt(LGL * lgl,const char * opt)2249 int lglhasopt (LGL * lgl, const char * opt) {
2250   Opt * o;
2251   REQINITNOTFORKED ();
2252   for (o = FIRSTOPT (lgl); o <= LASTOPT (lgl); o++)
2253     if (!strcmp (o->lng, opt)) return 1;
2254   return 0;
2255 }
2256 
lglfirstopt(LGL * lgl)2257 void * lglfirstopt (LGL * lgl) { return FIRSTOPT (lgl); }
2258 
lglnextopt(LGL * lgl,void * current,const char ** nameptr,int * valptr,int * minptr,int * maxptr)2259 void * lglnextopt (LGL * lgl,
2260 		   void * current,
2261 		   const char **nameptr,
2262 		   int *valptr, int *minptr, int *maxptr) {
2263   Opt * opt = current, * res = opt + 1;
2264   if (res > LASTOPT (lgl)) return 0;
2265   if (nameptr) *nameptr = opt->lng;
2266   if (valptr) *valptr = opt->val;
2267   if (minptr) *minptr = opt->min;
2268   if (maxptr) *maxptr = opt->max;
2269   return res;
2270 }
2271 
lglsetopt(LGL * lgl,const char * opt,int val)2272 void lglsetopt (LGL * lgl, const char * opt, int val) {
2273   int oldval;
2274   Opt * o;
2275   REQINITNOTFORKED ();
2276   for (o = FIRSTOPT (lgl); o <= LASTOPT (lgl); o++)
2277     if (!strcmp (o->lng, opt)) break;
2278   if (o > LASTOPT (lgl)) return;
2279   if (val < o->min) val = o->min;
2280   if (o->max < val) val = o->max;
2281   oldval = o->val;
2282   o->val = val;
2283   if (o == &lgl->opts->plain) {
2284     if (val > 0 && !oldval) lglsetplain (lgl, 1);
2285     if (!val && oldval) lglsetplain (lgl, 0);
2286   }
2287   if (o == &lgl->opts->druplig) {
2288     if (val > 0 && !oldval) lglsetdruplig (lgl, 1);
2289     if (!val && oldval) lglsetdruplig (lgl, 0);
2290   }
2291   if (o == &lgl->opts->wait) {
2292     if (val > 0 && !oldval) lglsetwait (lgl, 1);
2293     if (!val && oldval) lglsetwait (lgl, 0);
2294   }
2295   if (o == &lgl->opts->phase && val != oldval) lgl->flushphases = 1;
2296   if (lgl->state == UNUSED) TRANS (OPTSET);
2297   TRAPI ("option %s %d", opt, val);
2298 
2299   if (lgl->opts->druplig.val)
2300     lglforcedruplig (lgl, 1);
2301 }
2302 
lglws(int ch)2303 static int lglws (int ch) {
2304   return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
2305 }
2306 
lglreadopts(LGL * lgl,FILE * file)2307 int lglreadopts (LGL * lgl, FILE * file) {
2308   int res, ch, val, nvalbuf, noptbuf;
2309   char optbuf[40], valbuf[40];
2310   const char * opt;
2311   res = 0;
2312   for (;;) {
2313     while (lglws (ch = getc (file)))
2314       ;
2315     if (ch == EOF) break;
2316     noptbuf = 0;
2317     optbuf[noptbuf++] = ch;
2318     while ((ch = getc (file)) != EOF && !lglws (ch)) {
2319       if (noptbuf + 1 >= sizeof optbuf) { ch = EOF; break; }
2320       optbuf[noptbuf++] = ch;
2321     }
2322     if (ch == EOF) break;
2323     assert (noptbuf < sizeof optbuf);
2324     optbuf[noptbuf++] = 0;
2325     assert (lglws (ch));
2326     while (lglws (ch = getc (file)))
2327       ;
2328     if (ch == EOF) break;
2329     nvalbuf = 0;
2330     valbuf[nvalbuf++] = ch;
2331     while ((ch = getc (file)) != EOF && !lglws (ch)) {
2332       if (nvalbuf + 1 >= sizeof valbuf) break;
2333       valbuf[nvalbuf++] = ch;
2334     }
2335     assert (nvalbuf < sizeof valbuf);
2336     valbuf[nvalbuf++] = 0;
2337     opt = optbuf;
2338     val = atoi (valbuf);
2339     lglprt (lgl, 1, "read option --%s=%d", opt, val);
2340     lglsetopt (lgl, opt, val);
2341     res++;
2342   }
2343   return res;
2344 }
2345 
lglsetout(LGL * lgl,FILE * out)2346 void lglsetout (LGL * lgl, FILE * out) { lgl->out = out; }
2347 
lglgetout(LGL * lgl)2348 FILE * lglgetout (LGL * lgl) { return lgl->out; }
2349 
lglsetprefix(LGL * lgl,const char * prefix)2350 void lglsetprefix (LGL * lgl, const char * prefix) {
2351   lgldelstr (lgl, lgl->prefix);
2352   lgl->prefix = lglstrdup (lgl, prefix);
2353 }
2354 
lglgetprefix(LGL * lgl)2355 const char * lglgetprefix (LGL * lgl) { return lgl->prefix; }
2356 
lgligetopt(LGL * lgl,const char * opt)2357 static Opt * lgligetopt (LGL * lgl, const char * opt) {
2358   Opt * o;
2359   REQINITNOTFORKED ();
2360   for (o = FIRSTOPT (lgl); o <= LASTOPT (lgl); o++)
2361     if (!strcmp (o->lng, opt)) return o;
2362   return 0;
2363 }
2364 
lglgetopt(LGL * lgl,const char * opt)2365 int lglgetopt (LGL * lgl, const char * opt) {
2366   Opt * o = lgligetopt (lgl, opt);
2367   return o ? o->val : 0;
2368 }
2369 
lgldefopt(LGL * lgl,const char * opt)2370 int lgldefopt (LGL * lgl, const char * opt) {
2371   Opt * o = lgligetopt (lgl, opt);
2372   return o ? o->dflt : 0;
2373 }
2374 
lglgetoptminmax(LGL * lgl,const char * opt,int * min_ptr,int * max_ptr)2375 int lglgetoptminmax (LGL * lgl, const char * opt,
2376                      int * min_ptr, int * max_ptr) {
2377   Opt * o = lgligetopt (lgl, opt);
2378   if (!o) return 0;
2379   if (min_ptr) *min_ptr = o->min;
2380   if (max_ptr) *max_ptr = o->max;
2381   return o->val;
2382 }
2383 
2384 /*------------------------------------------------------------------------*/
2385 
lglrszvars(LGL * lgl,int new_size)2386 static void lglrszvars (LGL * lgl, int new_size) {
2387   int old_size = lgl->szvars;
2388   assert (lgl->nvars <= new_size);
2389   RSZ (lgl->vals, old_size, new_size);
2390   RSZ (lgl->i2e, old_size, new_size);
2391   RSZ (lgl->doms, 2*old_size, 2*new_size);
2392   RSZ (lgl->dvars, old_size, new_size);
2393   RSZ (lgl->avars, old_size, new_size);
2394   RSZ (lgl->qvars, old_size, new_size);
2395   RSZ (lgl->jwh, 2*old_size, 2*new_size);
2396   lgl->szvars = new_size;
2397 }
2398 
lglenlvars(LGL * lgl)2399 static void lglenlvars (LGL * lgl) {
2400   size_t old_size, new_size;
2401   old_size = lgl->szvars;
2402   new_size = old_size ? 2 * old_size : 4;
2403   LOG (3, "enlarging internal variables from %ld to %ld", old_size, new_size);
2404   lglrszvars (lgl, new_size);
2405 }
2406 
lglredvars(LGL * lgl)2407 static void lglredvars (LGL * lgl) {
2408   size_t old_size, new_size;
2409   old_size = lgl->szvars;
2410   new_size = lgl->nvars;
2411   if (new_size == old_size) return;
2412   LOG (3, "reducing variables from %ld to %ld", old_size, new_size);
2413   lglrszvars (lgl, new_size);
2414 }
2415 
lglmax(int a,int b)2416 static int lglmax (int a, int b) { return a > b ? a : b; }
2417 
2418 /*------------------------------------------------------------------------*/
2419 
lgldvar(LGL * lgl,int lit)2420 static DVar * lgldvar (LGL * lgl, int lit) {
2421   assert (2 <= abs (lit) && abs (lit) < lgl->nvars);
2422   return lgl->dvars + abs (lit);
2423 }
2424 
2425 /*------------------------------------------------------------------------*/
2426 
lglavar(LGL * lgl,int lit)2427 static AVar * lglavar (LGL * lgl, int lit) {
2428   assert (2 <= abs (lit) && abs (lit) < lgl->nvars);
2429   return lgl->avars + abs (lit);
2430 }
2431 
lglval(LGL * lgl,int lit)2432 static Val lglval (LGL * lgl, int lit) {
2433   int idx = abs (lit);
2434   Val res;
2435   ASSERT (2 <= idx && idx < lgl->nvars);
2436   res = lgl->vals[idx];
2437   if (lit < 0) res = -res;
2438   return res;
2439 }
2440 
lgltrail(LGL * lgl,int lit)2441 static int lgltrail (LGL * lgl, int lit) { return lglavar (lgl, lit)->trail; }
2442 
lglevel2trail(LGL * lgl,int level)2443 static int lglevel2trail (LGL * lgl, int level) {
2444   return lgltrail (lgl, lglctr (lgl, level)->decision);
2445 }
2446 
2447 
lgltd(LGL * lgl,int lit)2448 static TD * lgltd (LGL * lgl, int lit) {
2449   int pos = lgltrail (lgl, lit);
2450   assert (0 <= pos && pos < lgl->szdrail);
2451   return lgl->drail + pos;
2452 }
2453 
lglevel(LGL * lgl,int lit)2454 static int lglevel (LGL * lgl, int lit) { return lgltd (lgl, lit)->level; }
2455 
lglisfree(LGL * lgl,int lit)2456 static int lglisfree (LGL * lgl, int lit) {
2457   return lglavar (lgl, lit)->type == FREEVAR;
2458 }
2459 
2460 /*------------------------------------------------------------------------*/
2461 
lglqvar(LGL * lgl,int lit)2462 static QVar * lglqvar (LGL * lgl, int lit) {
2463   assert (2 <= abs (lit) && abs (lit) < lgl->nvars);
2464   return lgl->qvars + abs (lit);
2465 }
2466 
lgldpos(LGL * lgl,int lit)2467 static int * lgldpos (LGL * lgl, int lit) {
2468   QVar * qv;
2469   int * res;
2470   qv = lglqvar (lgl, lit);
2471   res = &qv->pos;
2472   return res;
2473 }
2474 
lglscrcmp(LGL * lgl,Flt a,Flt b)2475 static int lglscrcmp (LGL * lgl, Flt a, Flt b) {
2476   const int shift = lgl->opts->scoreshift.val;
2477   a >>= shift; assert (a >= 0);
2478   b >>= shift; assert (b >= 0);
2479   if (a < b) return -1;
2480   if (a > b) return 1;
2481   return 0;
2482 }
2483 
lgldcmp(LGL * lgl,int l,int k)2484 static int lgldcmp (LGL * lgl, int l, int k) {
2485   QVar * pv = lglqvar (lgl, l);
2486   QVar * qv = lglqvar (lgl, k);
2487   int res;
2488   if ((res = lglscrcmp (lgl, pv->score, qv->score))) return res;
2489   return 0;
2490 }
2491 
2492 #ifndef NDEBUG
lglchkdsched(LGL * lgl)2493 static void lglchkdsched (LGL * lgl) {
2494   int * p, parent, child, ppos, cpos, size, i, tmp;
2495   Stk * s = &lgl->dsched;
2496   size = lglcntstk (s);
2497   p = s->start;
2498   for (ppos = 0; ppos < size; ppos++) {
2499     parent = p[ppos];
2500     assert (parent > 1);
2501     tmp = *lgldpos (lgl, parent);
2502     assert (ppos == tmp);
2503     for (i = 0; i <= 1; i++) {
2504       cpos = 2*ppos + 1 + i;
2505       if (cpos >= size) continue;
2506       child = p[cpos];
2507       assert (child > 1);
2508       tmp = *lgldpos (lgl, child);
2509       assert (cpos == tmp);
2510       assert (lgldcmp (lgl, parent, child) >= 0);
2511     }
2512   }
2513 }
2514 #endif
2515 
lgldup(LGL * lgl,int lit)2516 static void lgldup (LGL * lgl, int lit) {
2517   int child = lit, parent, cpos, ppos, * p, * cposptr, * pposptr;
2518   Stk * s = &lgl->dsched;
2519   assert (lit > 1);
2520   p = s->start;
2521   cposptr = lgldpos (lgl, child);
2522   cpos = *cposptr;
2523   assert (cpos >= 0);
2524   while (cpos > 0) {
2525     ppos = (cpos - 1)/2;
2526     parent = p[ppos];
2527     if (lgldcmp (lgl, parent, lit) >= 0) break;
2528     pposptr = lgldpos (lgl, parent);
2529     assert (*pposptr == ppos);
2530     p[cpos] = parent;
2531     *pposptr = cpos;
2532     LOGDSCHED (5, parent, "down from %d", ppos);
2533     cpos = ppos;
2534   }
2535   if (*cposptr == cpos) return;
2536 #ifndef NLGLOG
2537   ppos = *cposptr;
2538 #endif
2539   *cposptr = cpos;
2540   p[cpos] = lit;
2541   LOGDSCHED (5, lit, "up from %d", ppos);
2542 #ifndef NDEBUG
2543   if (lgl->opts->check.val >= 2) lglchkdsched (lgl);
2544 #endif
2545 }
2546 
lglddown(LGL * lgl,int lit)2547 static void lglddown (LGL * lgl, int lit) {
2548   int parent = lit, child, right, ppos, cpos;
2549   int * p, * pposptr, * cposptr, size;
2550   Stk * s = &lgl->dsched;
2551   assert (lit > 1);
2552   size = lglcntstk (s);
2553   p = s->start;
2554   pposptr = lgldpos (lgl, parent);
2555   ppos = *pposptr;
2556   assert (0 <= ppos);
2557   for (;;) {
2558     cpos = 2*ppos + 1;
2559     if (cpos >= size) break;
2560     child = p[cpos];
2561     if (cpos + 1 < size) {
2562       right = p[cpos + 1];
2563       if (lgldcmp (lgl, child, right) < 0) cpos++, child = right;
2564     }
2565     if (lgldcmp (lgl, child, lit) <= 0) break;
2566     cposptr = lgldpos (lgl, child);
2567     assert (*cposptr = cpos);
2568     p[ppos] = child;
2569     *cposptr = ppos;
2570     LOGDSCHED (5, child, "up from %d", cpos);
2571     ppos = cpos;
2572   }
2573   if (*pposptr == ppos) return;
2574 #ifndef NLGLOG
2575   cpos = *pposptr;
2576 #endif
2577   *pposptr = ppos;
2578   p[ppos] = lit;
2579   LOGDSCHED (5, lit, "down from %d", cpos);
2580 #ifndef NDEBUG
2581   if (lgl->opts->check.val >= 2) lglchkdsched (lgl);
2582 #endif
2583 }
2584 
lgldsched(LGL * lgl,int lit)2585 static void lgldsched (LGL * lgl, int lit) {
2586   int * p = lgldpos (lgl, lit);
2587   Stk * s = &lgl->dsched;
2588   assert (lit > 1);
2589   assert (!lglqvar (lgl, lit)->enqueued);
2590   assert (*p < 0);
2591   *p = lglcntstk (s);
2592   lglpushstk (lgl, s, lit);
2593   lgldup (lgl, lit);
2594   lglddown (lgl, lit);
2595   LOGDSCHED (4, lit, "pushed");
2596 }
2597 
lgltopdsched(LGL * lgl)2598 static int lgltopdsched (LGL * lgl) {
2599   assert (!lglmtstk (&lgl->dsched));
2600   return lgl->dsched.start[0];
2601 }
2602 
lglpopdsched(LGL * lgl)2603 static int lglpopdsched (LGL * lgl) {
2604   Stk * s = &lgl->dsched;
2605   int res, last, cnt, * p;
2606   QVar * qv;
2607   assert (!lglmtstk (s));
2608   res = *s->start;
2609   LOGDSCHED (4, res, "popped");
2610   qv = lglqvar (lgl, res);
2611   assert (!qv->pos);
2612   qv->pos = -1;
2613   last = lglpopstk (s);
2614   cnt = lglcntstk (s);
2615   if (!cnt) { assert (last == res); return res; }
2616   p = lgldpos (lgl, last);
2617   assert (*p == cnt);
2618   *p = 0;
2619   *s->start = last;
2620   lglddown (lgl, last);
2621   return res;
2622 }
2623 
2624 #if 0
2625 static void lgldunsched (LGL * lgl, int lit) {
2626   Stk * s = &lgl->dsched;
2627   int last, cnt, * p, pos;
2628   QVar * qv;
2629   if (lit < 0) lit = -lit;
2630   assert (!lglmtstk (s));
2631   LOGDSCHED (4, lit, "unschedule");
2632   qv = lglqvar (lgl, lit);
2633   pos = qv->pos;
2634   qv->pos = -1;
2635   assert (lglpeek (s, pos) == lit);
2636   last = lglpopstk (s);
2637   cnt = lglcntstk (s);
2638   if (cnt == pos) { assert (last == lit); return; }
2639   p = lgldpos (lgl, last);
2640   assert (*p == cnt);
2641   lglpoke (s, pos, last);
2642   *p = pos;
2643   lgldup (lgl, last);
2644   lglddown (lgl, last);
2645 }
2646 #endif
2647 
lgldreschedule(LGL * lgl)2648 static void lgldreschedule (LGL * lgl) {
2649   Stk * s = &lgl->dsched;
2650   int idx, i, pos, cnt = lglcntstk (s);
2651   QVar * qv;
2652   LOG (1, "rescheduling %d variables", cnt);
2653   for (idx = 2; idx < lgl->nvars; idx++) {
2654     qv= lglqvar (lgl, idx);
2655     if (qv->enqueued) continue;
2656     qv->pos = -1;
2657   }
2658   pos = 0;
2659   s->top = s->start;
2660   for (i = 0; i < cnt; i++) {
2661     assert (pos <= i);
2662     assert (s->start + pos == s->top);
2663     idx = s->start[i];
2664     if (abs (idx) <= 1) continue;
2665     qv = lglqvar (lgl, idx);
2666     assert (!qv->enqueued);
2667     if (!lglisfree (lgl, idx)) { qv->pos = -1; continue; }
2668     assert (qv->pos == -1);
2669     s->start[pos] = idx;
2670     qv->pos = pos++;
2671     s->top++;
2672     lgldup (lgl, idx);
2673     lglddown (lgl, idx);
2674   }
2675   LOG (1, "new schedule with %d variables", lglcntstk (s));
2676   lglfitstk (lgl, s);
2677 #ifndef NDEBUG
2678   if (lgl->opts->check.val >= 1) lglchkdsched (lgl);
2679 #endif
2680 }
2681 
lglenq(LGL * lgl,int idx,int updatequeuenext)2682 static void lglenq (LGL * lgl, int idx, int updatequeuenext) {
2683   QVar * qv = lglqvar (lgl, idx);
2684   assert (!qv->enqueued);
2685   assert (qv->pos < 0);
2686   qv->enqueued = 1;
2687   qv->pos = lglcntstk (&lgl->queue.stk);
2688   lglpushstk (lgl, &lgl->queue.stk, idx);
2689   if (updatequeuenext || lgl->queue.next < 0) lgl->queue.next = qv->pos;
2690 }
lglrescorevars(LGL * lgl)2691 static void lglrescorevars (LGL * lgl) {
2692   Flt oldscinc, oldscore, newscore, oldmaxscore = 0, newmaxscore = 0;
2693   int64_t newotfs;
2694   QVar * qv;
2695   int idx;
2696   lgl->stats->rescored.vars++;
2697   for (idx = 2; idx < lgl->nvars; idx++) {
2698     qv = lglqvar (lgl, idx);
2699     if (qv->enqueued) continue;
2700     oldscore = qv->score;
2701     if (oldscore > oldmaxscore) oldmaxscore = oldscore;
2702     if (oldscore == FLTMIN) newscore = oldscore;
2703     else if (oldscore <= lgl->minscore) newscore = lgl->minscore;
2704     else {
2705       newscore = lglshflt (oldscore, DEFSCOREXP);
2706       if (newscore < lgl->minscore) newscore = lgl->minscore;
2707     }
2708     if (newscore <= lgl->minscore) {
2709       assert (newscore == FLTMIN || newscore == lgl->minscore);
2710       assert (!qv->enqueued);
2711     } else newscore = (oldscore >> 32);
2712     qv->score = newscore;
2713     if (qv->score > newmaxscore) newmaxscore = qv->score;
2714     LOG (3, "rescored variable %d from %s to %s",
2715 	 idx, lglscr2str (lgl, oldscore), lglscr2str (lgl, qv->score));
2716   }
2717   lgldreschedule (lgl);
2718   newotfs = lgl->stats->otfs.driving + lgl->stats->otfs.restarting;
2719   assert (newotfs >= lgl->limits->rescore.vars.otfs);
2720   assert (lgl->stats->confs >= lgl->limits->rescore.vars.confs);
2721   lglprt (lgl, 3,
2722     "[rescored-vars-%d] after %lld conflicts and %lld OTFS",
2723     lgl->stats->rescored.vars,
2724     lgl->stats->confs - lgl->limits->rescore.vars.confs,
2725     newotfs - lgl->limits->rescore.vars.otfs);
2726   lgl->limits->rescore.vars.confs = lgl->stats->confs;
2727   lgl->limits->rescore.vars.otfs = newotfs;
2728   lglprt (lgl, 3,
2729     "[rescored-vars-%d] old maximum score %s",
2730     lgl->stats->rescored.vars, lglscr2str (lgl, oldmaxscore));
2731   lglprt (lgl, 3,
2732     "[rescored-vars-%d] new maximum score %s",
2733     lgl->stats->rescored.vars, lglscr2str (lgl, newmaxscore));
2734   oldscinc = lgl->scinc;
2735   lgl->scinc = lglshflt (oldscinc, DEFSCOREXP);
2736   assert (lgl->scinc > 0);
2737   lglprt (lgl, 3,
2738     "[rescored-vars-%d] old score increment %s",
2739     lgl->stats->rescored.vars, lglscr2str (lgl, oldscinc));
2740   lglprt (lgl, 3,
2741     "[rescored-vars-%d] new score increment %s",
2742     lgl->stats->rescored.vars, lglscr2str (lgl, lgl->scinc));
2743 }
2744 
lglbumpscinc(LGL * lgl)2745 static void lglbumpscinc (LGL * lgl) {
2746   Flt oldscinc;
2747   if (lgl->simp && !lgl->opts->bumpsimp.val) return;
2748   oldscinc = lgl->scinc;
2749   lgl->scinc = lglmulflt (oldscinc, lgl->scincf);
2750   LOG (3, "bumped variable score increment from %s to %s",
2751        lglscr2str (lgl, oldscinc), lglscr2str (lgl, lgl->scinc));
2752   if (lgl->scinc >= lgl->maxscore) {
2753     LOG (2, "variable max score %s hit", lglscr2str (lgl, lgl->maxscore));
2754     lglrescorevars (lgl);
2755   }
2756   if (!lgl->simp &&
2757       !(lgl->stats->confs % lgl->opts->scincincincint.val)) {
2758     int newscincinc = lgl->scincinc;
2759     if (lgl->opts->scincincmode.val == 1)
2760       newscincinc -= lgl->opts->scincincdelta.val;
2761     else if (lgl->opts->scincincmode.val == 2)
2762       newscincinc = (lgl->opts->scincincmin.val + newscincinc)/2;
2763     if (newscincinc < lgl->opts->scincincmin.val)
2764       newscincinc = lgl->opts->scincincmin.val;
2765     if (newscincinc != lgl->scincinc) lglsetscincf (lgl, newscincinc);
2766   }
2767 }
2768 
2769 /*------------------------------------------------------------------------*/
2770 
lglnewvar(LGL * lgl)2771 static int lglnewvar (LGL * lgl) {
2772   AVar * av;
2773   DVar * dv;
2774   QVar * qv;
2775   int res;
2776   assert (!lgl->dense);
2777   if (lgl->nvars == lgl->szvars) lglenlvars (lgl);
2778   if (lgl->nvars) res = lgl->nvars++;
2779   else res = 2, lgl->nvars = 3;
2780   assert (res < lgl->szvars);
2781   if (res > MAXVAR) lgldie (lgl, "more than %d variables", MAXVAR - 1);
2782   assert (res <= MAXVAR);
2783   assert ((RMSHFTLIT(res) >> RMSHFT) == res);
2784   assert ((RMSHFTLIT(-res) >> RMSHFT) == -res);
2785   LOG (3, "new internal variable %d", res);
2786   dv = lgl->dvars + res;
2787   CLRPTR (dv);
2788   av = lgl->avars + res;
2789   CLRPTR (av);
2790   qv = lgl->qvars + res;
2791   CLRPTR (qv);
2792   qv->glag = -1;
2793   qv->pos = -1;
2794   lglenq (lgl, res, 1);
2795   lgl->unassigned++;
2796   lgl->allphaseset = 0;
2797   return res;
2798 }
2799 
lglsgn(int lit)2800 static int lglsgn (int lit) { return (lit < 0) ? -1 : 1; }
2801 
lglelit2ext(LGL * lgl,int elit)2802 static Ext * lglelit2ext (LGL * lgl, int elit) {
2803   int idx = abs (elit);
2804   assert (0 < idx), assert (idx <= lgl->maxext);
2805   return lgl->ext + idx;
2806 }
2807 
lglerepr(LGL * lgl,int elit)2808 static int lglerepr (LGL * lgl, int elit) {
2809   int res, next, tmp;
2810   Ext * ext;
2811   assert (0 < abs (elit)), assert (abs (elit) <= lgl->maxext);
2812   res = elit;
2813   for (;;) {
2814     ext = lglelit2ext (lgl, res);
2815     if (!ext->equiv) break;
2816     next = ext->repr;
2817     if (res < 0) next = -next;
2818     res = next;
2819   }
2820   tmp = elit;
2821   for (;;) {
2822     ext = lglelit2ext (lgl, tmp);
2823     if (!ext->equiv) { assert (tmp == res); break; }
2824     next = ext->repr;
2825     ext->repr = (tmp < 0) ? -res : res;
2826     if (tmp < 0) next = -next;
2827     tmp = next;
2828   }
2829   return res;
2830 }
2831 
lgladjext(LGL * lgl,int eidx)2832 static void lgladjext (LGL * lgl, int eidx) {
2833   size_t old, new;
2834   assert (eidx >= lgl->szext);
2835   assert (eidx > lgl->maxext);
2836   assert (lgl->szext >= lgl->maxext);
2837   old = lgl->szext;
2838   new = old ? 2*old : 2;
2839   while (eidx >= new) new *= 2;
2840   assert (eidx < new), assert (new >= lgl->szext);
2841   LOG (3, "enlarging external variables from %ld to %ld", old, new);
2842   RSZ (lgl->ext, old, new);
2843   lgl->szext = new;
2844 }
2845 
lglmelter(LGL * lgl)2846 static void lglmelter (LGL * lgl) {
2847   if (lgl->allfrozen) {
2848     lglprt (lgl, 1,
2849       "[melter] not all literals assumed to be frozen anymore");
2850     lgl->allfrozen = 0;
2851   }
2852   if (lgl->limits->elm.pen || lgl->limits->blk.pen || lgl->limits->cce.pen) {
2853     lglprt (lgl, 1,
2854       "[melter] reset penalties: %d elm, %d blk, %d cce",
2855       lgl->limits->elm.pen, lgl->limits->blk.pen, lgl->limits->cce.pen);
2856     lgl->limits->elm.pen = lgl->limits->blk.pen = lgl->limits->cce.pen = 0;
2857   }
2858   lgl->frozen = lgl->allfrozen = 0;
2859   LOG (2, "melted solver");
2860 }
2861 
lglimportaux(LGL * lgl,int elit)2862 static int lglimportaux (LGL * lgl, int elit) {
2863   int res, repr, eidx = abs (elit);
2864   Ext * ext;
2865   assert (elit);
2866   if (eidx >= lgl->szext) lgladjext (lgl, eidx);
2867   if (eidx > lgl->maxext) {
2868     lgl->maxext = eidx;
2869     lglmelter (lgl);
2870   }
2871   repr = lglerepr (lgl, elit);
2872   ext = lglelit2ext (lgl, repr);
2873   assert (!ext->equiv);
2874   res = ext->repr;
2875   if (!ext->imported) {
2876     res = lglnewvar (lgl);
2877     assert (!ext->equiv);
2878     ext->repr = res;
2879     ext->imported = 1;
2880     assert (eidx <= INT_MAX/2);
2881     lgl->i2e[res] = 2*eidx;
2882     LOG (3, "mapping external variable %d to %d", eidx, res);
2883     lglmelter (lgl);
2884   }
2885   if (repr < 0) res = -res;
2886   LOG (2, "importing %d as %d", elit, res);
2887   return res;
2888 }
2889 
lglimport(LGL * lgl,int elit)2890 static int lglimport (LGL * lgl, int elit) {
2891   assert (elit);
2892   if (!lgl->opts->import.val) {
2893     if (!lgl->maxext) (void) lglimportaux (lgl, 1);
2894     while (lgl->maxext < abs (elit))
2895       (void) lglimportaux (lgl, lgl->maxext + 1);
2896   }
2897   return lglimportaux (lgl, elit);
2898 }
2899 
lglidx2stk(LGL * lgl,int red,int lidx)2900 static Stk * lglidx2stk (LGL * lgl, int red, int lidx) {
2901   int glue = 0;
2902   Stk * s;
2903   assert (red == 0 || red == REDCS);
2904   assert (0 <= lidx);
2905   if (!red) s = &lgl->irr;
2906   else {
2907     glue = lidx & GLUEMASK;
2908     lidx >>= GLUESHFT;
2909     assert (lidx <= MAXREDLIDX);
2910     s = &lgl->red[glue];
2911   }
2912   return s;
2913 }
2914 
lglidx2lits(LGL * lgl,int red,int lidx)2915 static int * lglidx2lits (LGL * lgl, int red, int lidx) {
2916   Stk * s = lglidx2stk (lgl, red, lidx);
2917   int * res;
2918   assert (red == 0 || red == REDCS);
2919   assert (0 <= lidx);
2920   res = s->start + (red ? (lidx >> GLUESHFT) : lidx);
2921 #ifndef NDEBUG
2922   if (red && (lidx & GLUEMASK) == MAXGLUE) assert (res < s->end);
2923   else assert (res < s->top);
2924 #endif
2925   return res;
2926 }
2927 
2928 #ifndef NLGLOG
lglred2str(int red)2929 static const char * lglred2str (int red) {
2930   assert (!red || red == REDCS);
2931   return red ? "redundant" : "irredundant";
2932 }
2933 #endif
2934 
lgliselim(LGL * lgl,int lit)2935 static int lgliselim (LGL * lgl, int lit) {
2936   Tag tag = lglavar (lgl, lit)->type;
2937   return tag == ELIMVAR;
2938 }
2939 
lglexport(LGL * lgl,int ilit)2940 static int lglexport (LGL * lgl, int ilit) {
2941   int iidx, tidx, eidx, def, res;
2942   iidx = abs (ilit);
2943   assert (2 <= iidx), assert (iidx < lgl->nvars);
2944   tidx = lgl->i2e[iidx];
2945   def = tidx & 1;
2946   tidx >>= 1;
2947   assert (tidx);
2948   eidx = tidx;
2949   if (def) eidx += lgl->maxext;
2950   res = eidx;
2951   if (ilit < 0) res = -res;
2952   return res;
2953 }
2954 
lglrsn(LGL * lgl,int lit)2955 static int * lglrsn (LGL * lgl, int lit) { return lgltd (lgl, lit)->rsn; }
2956 
lglulit(int lit)2957 static int lglulit (int lit) { return 2*abs (lit) + (lit < 0); }
2958 
lglsetdom(LGL * lgl,int lit,int dom)2959 static void lglsetdom (LGL * lgl, int lit, int dom) {
2960   assert (2 <= abs (lit)  && abs (lit) < lgl->nvars);
2961   assert (2 <= abs (dom)  && abs (dom) < lgl->nvars);
2962   ASSERT (lglval (lgl, lit) >= 0);
2963   ASSERT (lglval (lgl, dom) >= 0);
2964   lgl->doms[lglulit (lit)] = dom;
2965   LOG (3, "literal %d dominated by %d", lit, dom);
2966 }
2967 
lglgetdom(LGL * lgl,int lit)2968 static int lglgetdom (LGL * lgl, int lit) {
2969   int res;
2970   assert (2 <= abs (lit)  && abs (lit) < lgl->nvars);
2971   assert (lglval (lgl, lit) >= 0);
2972   res = lgl->doms[lglulit (lit)];
2973   return res;
2974 }
2975 
lglhts(LGL * lgl,int lit)2976 static HTS * lglhts (LGL * lgl, int lit) {
2977   return lgldvar (lgl, lit)->hts + (lit < 0);
2978 }
2979 
lglhts2wchs(LGL * lgl,HTS * hts)2980 static int * lglhts2wchs (LGL * lgl, HTS * hts) {
2981   int * res = lgl->wchs->stk.start + hts->offset;
2982   assert (res < lgl->wchs->stk.top);
2983   assert (res + hts->count < lgl->wchs->stk.top);
2984   assert (res + hts->count < lgl->wchs->stk.top);
2985   return res;
2986 }
2987 
2988 /*------------------------------------------------------------------------*/
2989 
2990 #ifndef NLGLDRUPLIG
2991 
lgldruplig(LGL * lgl)2992 static int lgldruplig (LGL * lgl) {
2993   if (!lgl->opts->druplig.val) return 0;
2994   if (!lgl->druplig) {
2995     lgl->druplig = druplig_minit (lgl,
2996 		     (druplig_malloc) lglnew,
2997 		     (druplig_realloc) lglrsz,
2998 		     (druplig_free) lgldel);
2999     druplig_set_check (lgl->druplig, lgl->opts->drupligcheck.val);
3000     if (lgl->opts->drupligtrace.val)
3001       druplig_set_trace (lgl->druplig, lgl->out);
3002     else druplig_set_trace (lgl->druplig, 0);
3003     druplig_set_traceorig (lgl->druplig, lgl->opts->drupligtraceorig.val);
3004     if (lgl->opts->verbose.val > 0) {
3005       druplig_banner (lgl->out);
3006       druplig_options (lgl->druplig, lgl->out);
3007     }
3008   }
3009   return 1;
3010 }
3011 
lgldrupligreallyadd(LGL * lgl,int red)3012 static void lgldrupligreallyadd (LGL * lgl, int red) {
3013   assert (!red || red == REDCS);
3014   assert (lgl->opts->druplig.val);
3015   assert (lgl->druplig);
3016   lglstart (lgl, &lgl->times->druplig);
3017   if (red) druplig_check_and_add_redundant_clause (lgl->druplig);
3018   else druplig_add_original_clause (lgl->druplig);
3019   lglstop (lgl);
3020 }
3021 
lgldrupligreallydel(LGL * lgl)3022 static void lgldrupligreallydel (LGL * lgl) {
3023   assert (lgl->opts->druplig.val);
3024   assert (lgl->druplig);
3025   lglstart (lgl, &lgl->times->druplig);
3026   druplig_forget_clause (lgl->druplig);
3027   lglstop (lgl);
3028 }
3029 
lglialiased(LGL * lgl,int ilit)3030 static int lglialiased (LGL * lgl, int ilit) {
3031   int elit = lglexport (lgl, ilit);
3032   Ext * ext = lglelit2ext (lgl, elit);
3033   return ext->aliased;
3034 }
3035 
3036 #endif
3037 
lgldrupligaddclsaux(LGL * lgl,int red,const int * c)3038 static void lgldrupligaddclsaux (LGL * lgl, int red, const int * c) {
3039 #ifndef NLGLDRUPLIG
3040   assert (!red || red == REDCS);
3041   if (lgldruplig (lgl)) {
3042     const int * p;
3043     int lit;
3044     for (p = c; (lit = *p); p++)
3045       druplig_add_literal (lgl->druplig, lglexport (lgl, lit));
3046     lgldrupligreallyadd (lgl, red);
3047   }
3048 #else
3049   (void) lgl, (void) c;
3050 #endif
3051 }
3052 
lgldrupligaddclsarg(LGL * lgl,int red,...)3053 static void lgldrupligaddclsarg (LGL * lgl, int red, ...) {
3054 #ifndef NLGLDRUPLIG
3055   assert (!red || red == REDCS);
3056   if (lgldruplig (lgl)) {
3057     va_list ap;
3058     int unit = 0;
3059 #ifndef NLGLOG
3060     int logging = (lgl->opts->log.val > 1);
3061     if (logging) lglogstart (lgl, 2, "druplig adding internal clause");
3062 #endif
3063     va_start (ap, red);
3064     for (;;) {
3065       int lit = va_arg (ap, int);
3066       if (!lit) break;
3067       if (unit) unit = INT_MAX; else unit = lit;
3068       druplig_add_literal (lgl->druplig, lglexport (lgl, lit));
3069 #ifndef NLGLOG
3070       if (logging) fprintf (lgl->out, " %d", lit);
3071 #endif
3072     }
3073     va_end (ap);
3074 #ifndef NLGLOG
3075     if (logging) lglogend (lgl);
3076 #endif
3077     lgldrupligreallyadd (lgl, red);
3078     if (unit && unit != INT_MAX) lgl->drupligunit = unit;
3079     else lgl->drupligunit = 0;
3080   }
3081 #else
3082   (void) lgl, (void) red;
3083 #endif
3084 }
3085 
lgldrupligaddcls(LGL * lgl,int red)3086 static void lgldrupligaddcls (LGL * lgl, int red) {
3087 #ifndef NLGLDRUPLIG
3088   assert (!red || red == REDCS);
3089   if (lgldruplig (lgl)) {
3090     int lit, size = 0;
3091     const int * p;
3092     for (p = lgl->clause.start; p < lgl->clause.top; p++)
3093       if ((lit = *p)) {
3094 	druplig_add_literal (lgl->druplig, lglexport (lgl, lit));
3095 	size++;
3096       }
3097     lgldrupligreallyadd (lgl, red);
3098     if (size == 1) lgl->drupligunit = lgl->clause.start[0];
3099     else lgl->drupligunit = 0;
3100   }
3101 #else
3102   (void) lgl, (void) red;
3103 #endif
3104 }
3105 
lgldrupligdelclsarg(LGL * lgl,...)3106 static void lgldrupligdelclsarg (LGL * lgl, ...) {
3107 #ifndef NLGLDRUPLIG
3108   if (lgldruplig (lgl)) {
3109     int aliased = 0;
3110     va_list ap;
3111 #ifndef NDEBUG
3112     int size = 0;
3113 #endif
3114 #ifndef NLGLOG
3115     int logging = (lgl->opts->log.val > 1);
3116     if (logging) lglogstart (lgl, 2, "druplig forgetting internal clause");
3117 #endif
3118     va_start (ap, lgl);
3119     for (;;) {
3120       int lit = va_arg (ap, int);
3121       if (!lit) break;
3122       if (lglialiased (lgl, lit)) aliased = 1;
3123 #ifndef NDEBUG
3124       size++;
3125 #endif
3126 #ifndef NLGLOG
3127       if (logging) fprintf (lgl->out, " %d", lit);
3128 #endif
3129     }
3130     va_end (ap);
3131 #ifndef NLGLOG
3132     if (logging) {
3133       if (aliased) fprintf (lgl->out, " (but aliased)");
3134       lglogend (lgl);
3135     }
3136 #endif
3137     assert (size > 1);
3138     if (aliased) return;
3139     va_start (ap, lgl);
3140     for (;;) {
3141       int lit = va_arg (ap, int);
3142       if (!lit) break;
3143       druplig_add_literal (lgl->druplig, lglexport (lgl, lit));
3144     }
3145     va_end (ap);
3146     lgldrupligreallydel (lgl);
3147   }
3148 #else
3149   (void) lgl;
3150 #endif
3151 }
3152 
lgldrupligdelclsaux(LGL * lgl,const int * c)3153 static void lgldrupligdelclsaux (LGL * lgl, const int * c) {
3154 #ifndef NLGLDRUPLIG
3155   if (lgldruplig (lgl)) {
3156     const int * p;
3157     int lit;
3158     for (p = c; (lit = *p); p++)
3159       if (lglialiased (lgl, lit)) return;
3160     for (p = c; (lit = *p); p++)
3161       druplig_add_literal (lgl->druplig, lglexport (lgl, lit));
3162     lgldrupligreallydel (lgl);
3163     assert (p - c > 1);
3164   }
3165 #else
3166   (void) lgl, (void) c;
3167 #endif
3168 }
3169 
lgldrupligunit(LGL * lgl,int lit)3170 static void lgldrupligunit (LGL * lgl, int lit) {
3171 #ifndef NLGLDRUPLIG
3172   if (!lgldruplig (lgl)) return;
3173   if (lit == lgl->drupligunit) return;
3174   druplig_add_literal (lgl->druplig, lglexport (lgl, lit));
3175   druplig_check_and_add_redundant_clause (lgl->druplig);
3176   lgl->drupligunit = lit;
3177 #else
3178   (void) lgl, (void) lit;
3179 #endif
3180 }
3181 
3182 /*------------------------------------------------------------------------*/
3183 
3184 #ifndef NDEBUG
lglrgforcing(LGL * lgl,int red,int lidx)3185 static int lglrgforcing (LGL * lgl, int red, int lidx) {
3186   int lit, val, level, truelevel, unit;
3187   const int * p, * c;
3188   int * rsn, r0, r1;
3189   assert (!red || red == REDCS);
3190   c = lglidx2lits (lgl, red, lidx);
3191   truelevel = INT_MAX;
3192   unit = 0;
3193   for (p = c; (lit = *p); p++) {
3194     assert (abs (lit) < NOTALIT);
3195     val = lglval (lgl, lit);
3196     if (!val) return 0;
3197     level = lglevel (lgl, lit);
3198     if (val > 0) {
3199       if (unit) return 0;
3200       truelevel = level;
3201       unit = lit;
3202     } else if (level > truelevel) return 0;
3203   }
3204   if (!unit) return 0;
3205   rsn = lglrsn (lgl, unit);
3206   r0 = rsn[0];
3207   if ((r0 & MASKCS) != LRGCS) return 0;
3208   if ((r0 & REDCS) != red) return 0;
3209   r1 = rsn[1];
3210   if (r1 != lidx) return 0;
3211   return 1;
3212 }
3213 #endif
3214 
lglassign(LGL * lgl,int lit,int r0,int r1)3215 static void lglassign (LGL * lgl, int lit, int r0, int r1) {
3216   int * p, other, other2, * c, lidx, found;
3217   int idx, phase, glue, tag, dom, red, irr;
3218   AVar * av = lglavar (lgl, lit);
3219   TD * td;
3220   LOGREASON (2, lit, r0, r1, "assign %d through", lit);
3221   av->trail = lglcntstk (&lgl->trail);
3222   if (av->trail >= lgl->szdrail) {
3223     int newszdrail = lgl->szdrail ? 2*lgl->szdrail : 1;
3224     RSZ (lgl->drail, lgl->szdrail, newszdrail);
3225     lgl->szdrail = newszdrail;
3226   }
3227   td = lgltd (lgl, lit);
3228   tag = r0 & MASKCS;
3229   dom = (tag == BINCS) ? lglgetdom (lgl, -(r0 >> RMSHFT)) : lit;
3230   lglsetdom (lgl, lit, dom);
3231 #ifndef NDEBUG
3232   {
3233     if (tag == BINCS || tag == TRNCS) {
3234       other = r0 >> RMSHFT;
3235       assert (lglval (lgl, other) < 0);
3236       if (tag == TRNCS) {
3237 	other2 = r1;
3238 	assert (lglval (lgl, other2) < 0);
3239       }
3240     } else if (tag == LRGCS) {
3241       red = r0 & REDCS;
3242       lidx = r1;
3243       c = lglidx2lits (lgl, red, lidx);
3244       found = 0;
3245       for (p = c; (other = *p); p++)
3246 	if (other == lit) found++;
3247 	else assert (lglval (lgl, other) < 0);
3248       assert (found == 1);
3249     } else assert (tag == DECISION || tag == UNITCS);
3250   }
3251   assert (!lglval (lgl, lit));
3252   assert (lgl->unassigned > 0);
3253   assert (!lgliselim (lgl, lit));
3254 #endif
3255   idx = abs (lit);
3256   phase = lglsgn (lit);
3257   lgl->vals[idx] = phase;
3258   if (!lgl->simp) {
3259     lgl->stats->agility -= lgl->stats->agility >> 13;
3260     if (av->phase != phase) {
3261       av->phase = phase;
3262       lgl->stats->agility += ((int64_t)1) << 19;
3263       lgl->stats->stability.changed++;
3264     }
3265   }
3266 #ifndef NDEBUG
3267   if (phase < 0) av->wasfalse = 1; else av->wasfalse = 0;
3268 #endif
3269   td->level = lgl->level;
3270   if (!lgl->level) {
3271     lgldrupligunit (lgl, lit);
3272     td->irr = 1;
3273     if (av->type == EQUIVAR) {
3274       assert (lgl->stats->equiv.current > 0);
3275       lgl->stats->equiv.current--;
3276       assert (lgl->stats->equiv.sum > 0);
3277       lgl->stats->equiv.sum--;
3278     } else {
3279       assert (av->type == FREEVAR);
3280       av->type = FIXEDVAR;
3281     }
3282     lgl->stats->fixed.sum++;
3283     lgl->stats->fixed.current++;
3284     lgl->stats->prgss++;
3285     lgl->stats->irrprgss++;
3286     td->rsn[0] = UNITCS | RMSHFTLIT (lit);
3287     td->rsn[1] = 0;
3288     if (lgl->cbs && lgl->cbs->units.produce.fun) {
3289       LOG (2, "trying to export internal unit %d external %d\n",
3290 	   lgl->tid, lit, lglexport (lgl, lit));
3291       lgl->stats->sync.units.produced++;
3292       lgl->cbs->units.produce.fun (lgl->cbs->units.produce.state,
3293                                   lglexport (lgl, lit));
3294       LOG (2, "exporting internal unit %d external %d\n",
3295 	      lgl->tid, lit, lglexport (lgl, lit));
3296     }
3297   } else {
3298     td->rsn[0] = r0;
3299     td->rsn[1] = r1;
3300     if (lgl->level == 1) {
3301       assert (tag != UNITCS);
3302       if (tag == DECISION) irr = 1;
3303       else if ((irr = !(red = (r0 & REDCS)))) {
3304 	if (tag == BINCS) {
3305 	  other = r0 >> RMSHFT;
3306 	  irr = lgltd (lgl, other)->irr;
3307 	} else if (tag == TRNCS) {
3308 	  other = r0 >> RMSHFT;
3309 	  if ((irr = lgltd (lgl, other)->irr)) {
3310 	    other2 = r1;
3311 	    irr = lgltd (lgl, other2)->irr;
3312 	  }
3313 	} else {
3314 	  assert (tag == LRGCS);
3315 	  lidx = r1;
3316 	  c = lglidx2lits (lgl, red, lidx);
3317 	  found = 0;
3318 	  for (p = c; irr && (other = *p); p++)
3319 	    if (other == lit) found++;
3320 	    else irr = lgltd (lgl, other)->irr;
3321 	  assert (!irr || found == 1);
3322 	}
3323       }
3324     } else irr = 0;
3325     td->irr = irr;
3326   }
3327 
3328   lglpushstk (lgl, &lgl->trail, lit);
3329   if (!lgl->simp && !lgl->failed && (av->assumed & (1u << (lit > 0)))) {
3330     LOG (2, "failed assumption %d", -lit);
3331     lgl->failed = -lit;
3332   }
3333   lgl->unassigned--;
3334   td->lrglue = 0;
3335   if ((r0 & REDCS) && (r0 & MASKCS) == LRGCS) {
3336     glue = r1 & GLUEMASK;
3337     lgl->stats->lir[glue].forcing++;
3338     assert (lgl->stats->lir[glue].forcing > 0);
3339     if (lgl->level && 0 < glue && glue < MAXGLUE) {
3340       lgl->lrgluereasons++;
3341       assert (lgl->lrgluereasons > 0);
3342       td->lrglue = 1;
3343     }
3344 #ifndef NDEBUG
3345     if (glue == MAXGLUE)
3346       assert ((r1 >> GLUESHFT) + 4 < lglcntstk (&lgl->red[MAXGLUE]));
3347 #endif
3348   }
3349 #ifndef NDEBUG
3350   if (tag == LRGCS) {
3351     lidx = r1;
3352     red = r0 & REDCS;
3353     if (lgl->level) assert (lglrgforcing (lgl, red, lidx));
3354     else assert (((*lglrsn (lgl, lit)) & MASKCS) == UNITCS);
3355   }
3356 #endif
3357 }
3358 
lglf2rce(LGL * lgl,int lit,int other,int red)3359 static void lglf2rce (LGL * lgl, int lit, int other, int red) {
3360   assert (lglval (lgl, other) < 0);
3361   assert (!red || red == REDCS);
3362   assert (!lgliselim (lgl, other));
3363   lglassign (lgl, lit, (RMSHFTLIT (other) | BINCS | red), 0);
3364 }
3365 
lglf3rce(LGL * lgl,int lit,int other,int other2,int red)3366 static void lglf3rce (LGL * lgl, int lit, int other, int other2, int red) {
3367   assert (lglval (lgl, other) < 0);
3368   assert (lglval (lgl, other2) < 0);
3369   assert (!lgliselim (lgl, other));
3370   assert (!lgliselim (lgl, other2));
3371   assert (!red || red == REDCS);
3372   lglassign (lgl, lit, (RMSHFTLIT (other) | TRNCS | red), other2);
3373 }
3374 
lglflrce(LGL * lgl,int lit,int red,int lidx)3375 static void lglflrce (LGL * lgl, int lit, int red, int lidx) {
3376 #ifndef NDEBUG
3377   int * p = lglidx2lits (lgl, red, lidx), other;
3378   while ((other = *p++)) {
3379     assert (!lgliselim (lgl, other));
3380     if (other != lit) assert (lglval (lgl, other) < 0);
3381   }
3382   assert (red == 0 || red == REDCS);
3383 #endif
3384   lglassign (lgl, lit, red | LRGCS, lidx);
3385 }
3386 
lgldscheduled(LGL * lgl,int lit)3387 static int lgldscheduled (LGL * lgl, int lit) {
3388   QVar * qv = lglqvar (lgl, lit);
3389   if (qv->enqueued) return 1;
3390   return qv->pos >= 0;
3391 }
3392 
lglunassign(LGL * lgl,int lit)3393 static void lglunassign (LGL * lgl, int lit) {
3394   int idx = abs (lit), r0, r1, tag, lidx, glue;
3395   QVar * qv;
3396   TD *  td;
3397   LOG (2, "unassign %d", lit);
3398   assert (lglval (lgl, lit) > 0);
3399   assert (lgl->vals[idx] == lglsgn (lit));
3400   lgl->vals[idx] = 0;
3401   lgl->unassigned++;
3402   assert (lgl->unassigned > 0);
3403   qv = lglqvar (lgl, idx);
3404   if (qv->enqueued) assert (qv->pos >= 0);
3405   else if (qv->pos < 0) lgldsched (lgl, idx);
3406   td = lgltd (lgl, idx);
3407   r0 = td->rsn[0];
3408   if (!(r0 & REDCS)) return;
3409   tag = r0 & MASKCS;
3410   if (tag != LRGCS) return;
3411   r1 = td->rsn[1];
3412   glue = r1 & GLUEMASK;
3413   if (td->lrglue) {
3414     assert (lgl->lrgluereasons > 0);
3415     lgl->lrgluereasons--;
3416   }
3417   if (glue < MAXGLUE) return;
3418   lidx = r1 >> GLUESHFT;
3419   LOG (2, "eagerly deleting maximum glue clause at %d", lidx);
3420   lglrststk (&lgl->red[glue], lidx);
3421 }
3422 
lglifixed(LGL * lgl,int lit)3423 static Val lglifixed (LGL * lgl, int lit) {
3424   int res;
3425   if (!(res = lglval (lgl, lit))) return 0;
3426   if (lglevel (lgl, lit) > 0) return 0;
3427   return res;
3428 }
3429 
lglbacktrack(LGL * lgl,int level)3430 static void lglbacktrack (LGL * lgl, int level) {
3431   int lit;
3432   assert (level >= 0);
3433   assert (lgl->level > level);
3434   if (lgl->stats->stability.level > 0) {
3435     LOG (2, "cancelling restart stability computation");
3436     lgl->stats->stability.level = 0;
3437   }
3438   LOG (2, "backtracking to level %d", level);
3439   assert (level <= lgl->level);
3440   assert (abs (lgl->failed) != 1 || lgl->failed == -1);
3441   if (lgl->failed &&
3442       lgl->failed != -1 &&
3443       lglevel (lgl, lgl->failed) > level) {
3444     LOG (2, "resetting failed assumption %d", lgl->failed);
3445     lgl->failed = 0;
3446   }
3447   while (!lglmtstk (&lgl->trail)) {
3448     lit = lgltopstk (&lgl->trail);
3449     assert (abs (lit) > 1);
3450     if (lglevel (lgl, lit) <= level) break;
3451     lglunassign (lgl, lit);
3452     lgl->trail.top--;
3453   }
3454   if (!level) {
3455     assert (!lgl->lrgluereasons);
3456     while (!lglmtstk (&lgl->red[MAXGLUE])) {
3457       int tmp = lglpopstk (&lgl->red[MAXGLUE]);
3458       assert (tmp >= NOTALIT);
3459       (void) tmp;
3460     }
3461   }
3462   if (lgl->alevel > level) {
3463     LOG (2,
3464 	 "resetting assumption decision level to %d from %d",
3465 	 level, lgl->alevel);
3466     lgl->alevel = level;
3467     if (lgl->assumed) {
3468       LOG (2,
3469 	   "resetting assumption queue level to 0 from %d",
3470 	   lgl->assumed);
3471       lgl->assumed = 0;
3472     }
3473   }
3474   lgl->level = level;
3475   lglrstcontrol (lgl, level + 1);
3476   assert (lglcntctk (&lgl->control) == lgl->level + 1);
3477   lgl->conf.lit = 0;
3478   lgl->conf.rsn[0] = lgl->conf.rsn[1] = 0;
3479   lgl->next2 = lgl->next = lglcntstk (&lgl->trail);
3480 #ifndef NDEBUG
3481   if (lgl->prevglue == MAXGLUE) {
3482     lglclnstk (&lgl->prevclause);
3483     lgl->prevglue = -1;
3484   }
3485 #endif
3486   LOG (2, "backtracked ");
3487 }
3488 
lglmarked(LGL * lgl,int lit)3489 static int lglmarked (LGL * lgl, int lit) {
3490   int res = lglavar (lgl, lit)->mark;
3491   if (lit < 0) res = -res;
3492   return res;
3493 }
3494 
3495 /*------------------------------------------------------------------------*/
3496 
lglunit(LGL * lgl,int lit)3497 static void lglunit (LGL * lgl, int lit) {
3498   ASSERT (!lgl->level);
3499   LOG (1, "unit %d", lit);
3500   lglassign (lgl, lit, RMSHFTLIT (lit) | UNITCS, 0);
3501 }
3502 
lglmark(LGL * lgl,int lit)3503 static void lglmark (LGL * lgl, int lit) {
3504   lglavar (lgl, lit)->mark = lglsgn (lit);
3505 }
3506 
lglmarkunmarked(LGL * lgl,int lit)3507 static void lglmarkunmarked (LGL * lgl, int lit) {
3508   AVar * av = lglavar (lgl, lit);
3509   assert (!av->mark);
3510   av->mark = lglsgn (lit);
3511 }
3512 
lglunmark(LGL * lgl,int lit)3513 static void lglunmark (LGL * lgl, int lit) { lglavar (lgl, lit)->mark = 0; }
3514 
lglchksimpcls(LGL * lgl)3515 static void lglchksimpcls (LGL * lgl) {
3516 #ifndef NDEBUG
3517   int *p, tmp, lit;
3518   AVar * av;
3519   for (p = lgl->clause.start; (lit = *p); p++) {
3520     tmp = lglifixed (lgl, lit);
3521     assert (!tmp);
3522     av = lglavar (lgl, lit);
3523     assert (!av->simp);
3524     av->simp = 1;
3525   }
3526   while (p > lgl->clause.start)
3527     lglavar (lgl,  *--p)->simp = 0;
3528 #endif
3529 }
3530 
lglcval(LGL * lgl,int litorval)3531 static int lglcval (LGL * lgl, int litorval) {
3532   assert (litorval);
3533   if (litorval == 1 || litorval == -1) return litorval;
3534   return lglval (lgl, litorval);
3535 }
3536 
3537 /*------------------------------------------------------------------------*/
3538 
lglisimpcls(LGL * lgl)3539 static int lglisimpcls (LGL * lgl) {
3540   int * p, * q = lgl->clause.start, lit, satisfied, val, mark;
3541 #ifndef NLGLOG
3542   int simplified;
3543 #endif
3544 
3545   satisfied = 0;
3546 
3547 #ifndef NDEBUG
3548   for (p = q; (lit = *p); p++) assert (!lglmarked (lgl, lit));
3549 #endif
3550 
3551   for (p = q; (lit = *p); p++) {
3552     if (satisfied) continue;
3553     val = lglval (lgl, lit);
3554     if (val > 0) {
3555       LOG (4, "literal %d satisfies clauses", lit);
3556       satisfied = 1;
3557       continue;
3558     }
3559     if (val < 0) {
3560       LOG (4, "removing false literal %d", lit);
3561       continue;
3562     }
3563     mark = lglmarked (lgl, lit);
3564     if (mark > 0) {
3565       LOG (4, "removing duplicated literal %d", lit);
3566       continue;
3567     }
3568     if (mark < 0) {
3569       LOG (4, "literals %d and %d occur both", -lit, lit);
3570       satisfied = 1;
3571       continue;
3572     }
3573     *q++ = lit;
3574     lglmark (lgl, lit);
3575   }
3576 
3577   *q = 0;
3578   lgl->clause.top = q + 1;
3579 #ifndef NLGLOG
3580   simplified = (lgl->clause.top != q + 1);
3581 #endif
3582 
3583   if (satisfied) LOG (2, "simplified clause is trivial");
3584   else
3585     LOGCLS (2, lgl->clause.start,
3586       "%s simplified clause", simplified ? "changed" : "unchanged");
3587 
3588   while (q > lgl->clause.start) lglunmark (lgl, *--q);
3589 
3590   return satisfied;
3591 }
3592 
lglesimpcls(LGL * lgl)3593 static int lglesimpcls (LGL * lgl) {
3594   int * p, * q = lgl->clause.start, lit, satisfied, val, mark;
3595 #if !defined(NLGLOG) || (!defined(NLGLDRUPLIG) && !defined(NDEBUG))
3596   int simplified;
3597 #endif
3598 
3599   satisfied = 0;
3600 
3601 #ifndef NDEBUG
3602   for (p = q; (lit = *p); p++)
3603     assert (abs (lit) == 1 || !lglmarked (lgl, lit));
3604 #endif
3605 
3606   for (p = q; !satisfied && (lit = *p); p++) {
3607     val = lglcval (lgl, lit);
3608     if (val > 0) {
3609       LOG (4, "literal %d satisfies clauses", lit);
3610       satisfied = 1;
3611       continue;
3612     }
3613     if (val < 0) {
3614       LOG (4, "removing false literal %d", lit);
3615       continue;
3616     }
3617     mark = lglmarked (lgl, lit);
3618     if (mark > 0) {
3619       LOG (4, "removing duplicated literal %d", lit);
3620       continue;
3621     }
3622     if (mark < 0) {
3623       LOG (4, "literals %d and %d occur both", -lit, lit);
3624       satisfied = 1;
3625       continue;
3626     }
3627     *q++ = lit;
3628     lglmark (lgl, lit);
3629   }
3630 
3631   *q = 0;
3632   lgl->clause.top = q + 1;
3633 #if !defined(NLGLOG) || (!defined(NLGLDRUPLIG) && !defined(NDEBUG))
3634   simplified = (lgl->clause.top != q + 1);
3635 #endif
3636 
3637   if (satisfied) LOG (2, "simplified clause is trivial");
3638   else
3639     LOGCLS (2, lgl->clause.start,
3640       "%s simplified clause", simplified ? "changed" : "unchanged");
3641 
3642   while (q > lgl->clause.start) lglunmark (lgl, *--q);
3643 
3644 #ifndef NLGLDRUPLIG
3645   if (lgldruplig (lgl)) {
3646     int different = (lglcntstk (&lgl->eclause) != lglcntstk (&lgl->clause));
3647     assert (!simplified || different);
3648     if (!satisfied && different) lgldrupligaddcls (lgl, REDCS);
3649     if (satisfied || different) {
3650       const int * p;
3651       int elit;
3652       for (p = lgl->eclause.start; (elit = *p); p++)
3653 	druplig_add_literal (lgl->druplig, elit);
3654       lgldrupligreallydel (lgl);
3655     }
3656   }
3657 #endif
3658 
3659   return satisfied;
3660 }
3661 
lglorderclsaux(LGL * lgl,int * start)3662 static void lglorderclsaux (LGL * lgl, int * start) {
3663   int * p, max = 0, level, lit, val;
3664   for (p = start; (lit = *p); p++) {
3665     if ((val = lglval (lgl, lit)) < 0) level = lglevel (lgl, lit);
3666     else if (val > 0) level = INT_MAX - 1;
3667     else assert (!val), level = INT_MAX;
3668     if (level <= max) continue;
3669     max = level;
3670     *p = start[0];
3671     start[0] = lit;
3672   }
3673 }
3674 
lglordercls(LGL * lgl)3675 static void lglordercls (LGL * lgl) {
3676   assert (lglcntstk (&lgl->clause) > 2);
3677   lglorderclsaux (lgl, lgl->clause.start);
3678   LOG (3, "head literal %d", lgl->clause.start[0]);
3679   lglorderclsaux (lgl, lgl->clause.start  + 1);
3680   LOG (3, "tail literal %d", lgl->clause.start[1]);
3681   LOGCLS (3, lgl->clause.start, "ordered clause");
3682 }
3683 /*------------------------------------------------------------------------*/
3684 
3685 
lglfreewch(LGL * lgl,int oldoffset,int oldhcount)3686 static void lglfreewch (LGL * lgl, int oldoffset, int oldhcount) {
3687   int ldoldhcount = lglceild (oldhcount);
3688   lgl->wchs->stk.start[oldoffset] = lgl->wchs->start[ldoldhcount];
3689   assert (oldoffset);
3690   lgl->wchs->start[ldoldhcount] = oldoffset;
3691   lgl->wchs->free++;
3692   assert (lgl->wchs->free > 0);
3693   LOG (5, "saving watch stack at %d of size %d on free list %d",
3694        oldoffset, oldhcount, ldoldhcount);
3695 }
3696 
lglshrinkhts(LGL * lgl,HTS * hts,int newcount)3697 static void lglshrinkhts (LGL * lgl, HTS * hts, int newcount) {
3698   int * p, i, oldcount = hts->count;
3699   assert (newcount <= oldcount);
3700   if (newcount == oldcount) return;
3701   p = lglhts2wchs (lgl, hts);
3702   for (i = newcount; i < oldcount; i++) p[i] = 0;
3703   hts->count = newcount;
3704   if (newcount) return;
3705   lglfreewch (lgl, hts->offset, oldcount);
3706   hts->offset = 0;
3707 }
3708 
lglenlwchs(LGL * lgl,HTS * hts)3709 static long lglenlwchs (LGL * lgl, HTS * hts) {
3710   int oldhcount = hts->count, oldoffset = hts->offset, newoffset;
3711   int oldwcount, newwcount, oldwsize, newwsize, i, j;
3712   int newhcount = oldhcount ? 2*oldhcount : 1;
3713   int * oldwstart, * newwstart, * start;
3714   int ldnewhcount = lglfloorld (newhcount);
3715   long res = 0;
3716 
3717   newhcount = (1<<ldnewhcount);
3718   assert (newhcount > oldhcount);
3719 
3720   LOG (5, "increasing watch stack at %d from %d to %d",
3721        oldoffset, oldhcount, newhcount);
3722 
3723   assert (!oldoffset == !oldhcount);
3724 
3725   lgl->stats->enlwchs++;
3726 
3727   newoffset = lgl->wchs->start[ldnewhcount];
3728   start = lgl->wchs->stk.start;
3729   if (newoffset != INT_MAX) {
3730     lgl->wchs->start[ldnewhcount] = start[newoffset];
3731     start[newoffset] = 0;
3732     assert (lgl->wchs->free > 0);
3733     lgl->wchs->free--;
3734     LOG (5, "reusing free watch stack at %d of size %d",
3735 	 newoffset, (1 << ldnewhcount));
3736   } else {
3737     assert (lgl->wchs->stk.start[hts->offset]);
3738     assert (lgl->wchs->stk.top[-1] == INT_MAX);
3739 
3740     oldwcount = lglcntstk (&lgl->wchs->stk);
3741     newwcount = oldwcount + newhcount;
3742     oldwsize = lglszstk (&lgl->wchs->stk);
3743     newwsize = oldwsize;
3744 
3745     assert (lgl->wchs->stk.top == lgl->wchs->stk.start + oldwcount);
3746     assert (oldwcount > 0);
3747 
3748     while (newwsize < newwcount) newwsize *= 2;
3749     if (newwsize > oldwsize) {
3750       newwstart = oldwstart = lgl->wchs->stk.start;
3751       RSZ (newwstart, oldwsize, newwsize);
3752       LOG (3, "resized global watcher stack from %d to %d",
3753 	   oldwsize, newwsize);
3754       res = newwstart - oldwstart;
3755       if (res) {
3756 	LOG (3, "moved global watcher stack by %ld", res);
3757 	start = lgl->wchs->stk.start = newwstart;
3758       }
3759       lgl->wchs->stk.end = start + newwsize;
3760     }
3761     lgl->wchs->stk.top = start + newwcount;
3762     lgl->wchs->stk.top[-1] = INT_MAX;
3763     newoffset = oldwcount - 1;
3764     LOG (5,
3765 	 "new watch stack of size %d at end of global watcher stack at %d",
3766 	 newhcount, newoffset);
3767   }
3768   assert (start == lgl->wchs->stk.start);
3769   assert (start[0]);
3770   j = newoffset;
3771   for (i = oldoffset; i < oldoffset + oldhcount; i++) {
3772     start[j++] = start[i];
3773     start[i] = 0;
3774   }
3775   while (j < newoffset + newhcount)
3776     start[j++] = 0;
3777   assert (start + j <= lgl->wchs->stk.top);
3778   hts->offset = newoffset;
3779   if (oldhcount > 0) lglfreewch (lgl, oldoffset, oldhcount);
3780   return res;
3781 }
3782 
lglpushwch(LGL * lgl,HTS * hts,int wch)3783 static long lglpushwch (LGL * lgl, HTS * hts, int wch) {
3784   long res = 0;
3785   int * wchs = lglhts2wchs (lgl, hts);
3786   assert (sizeof (res) == sizeof (void*));
3787   assert (hts->count >= 0);
3788   if (wchs[hts->count]) {
3789     res = lglenlwchs (lgl, hts);
3790     wchs = lglhts2wchs (lgl, hts);
3791   }
3792   assert (!wchs[hts->count]);
3793   assert (wch != INT_MAX);
3794   wchs[hts->count++] = wch;
3795   lgl->stats->pshwchs++;
3796   assert (lgl->stats->pshwchs > 0);
3797   return res;
3798 }
3799 
lglwchbin(LGL * lgl,int lit,int other,int red)3800 static long lglwchbin (LGL * lgl, int lit, int other, int red) {
3801   HTS * hts = lglhts (lgl, lit);
3802   int cs = (RMSHFTLIT (other) | BINCS | red);
3803   long res;
3804   assert (red == 0 || red == REDCS);
3805   res = lglpushwch (lgl, hts, cs);
3806   LOG (3, "new %s binary watch %d blit %d", lglred2str (red), lit, other);
3807   return res;
3808 }
3809 
lglwchtrn(LGL * lgl,int a,int b,int c,int red)3810 static long lglwchtrn (LGL * lgl, int a, int b, int c, int red) {
3811   HTS * hts = lglhts (lgl, a);
3812   int cs = (RMSHFTLIT (b) | TRNCS | red);
3813   long res;
3814   assert (red == 0 || red == REDCS);
3815   res = lglpushwch (lgl, hts, cs);
3816   res += lglpushwch (lgl, hts, c);
3817   LOG (3, "new %s ternary watch %d blits %d %d", lglred2str (red), a, b, c);
3818   return res;
3819 }
3820 
lglwchlrg(LGL * lgl,int lit,int other,int red,int lidx)3821 static long lglwchlrg (LGL * lgl, int lit, int other, int red, int lidx) {
3822   HTS * hts = lglhts (lgl, lit);
3823   int blit = (RMSHFTLIT (other) | LRGCS | red);
3824   long res = 0;
3825   assert (red == 0 || red == REDCS);
3826   res += lglpushwch (lgl, hts, blit);
3827   res += lglpushwch (lgl, hts, lidx);
3828 #ifndef NLGLOG
3829   {
3830     int * p = lglidx2lits (lgl, red, lidx);
3831     if (red)
3832       LOG (3,
3833 	   "watching %d with blit %d in red[%d][%d] %d %d %d %d%s",
3834 	   lit, other, (lidx & GLUEMASK), (lidx >> GLUESHFT),
3835 	   p[0], p[1], p[2], p[3], (p[4] ? " ..." : ""));
3836     else
3837       LOG (3,
3838        "watching %d with blit %d in irr[%d] %d %d %d %d%s",
3839        lit, other, lidx, p[0], p[1], p[2], p[3], (p[4] ? " ..." : ""));
3840   }
3841 #endif
3842   assert (sizeof (res) == sizeof (void*));
3843   return res;
3844 }
3845 
3846 /*------------------------------------------------------------------------*/
3847 
lglevar(LGL * lgl,int lit)3848 static EVar * lglevar (LGL * lgl, int lit) {
3849   int idx = abs (lit);
3850   assert (1 <= idx && idx < lgl->nvars);
3851   return lgl->evars + idx;
3852 }
3853 
lglepos(LGL * lgl,int lit)3854 static int * lglepos (LGL * lgl, int lit) {
3855   EVar * ev;
3856   int * res;
3857   ev = lglevar (lgl, lit);
3858   res = &ev->pos;
3859   return res;
3860 }
3861 
lglecmp(LGL * lgl,int l,int k)3862 static int lglecmp (LGL * lgl, int l, int k) {
3863   return lglevar (lgl,k)->score - lglevar (lgl,l)->score;
3864 }
3865 
3866 #ifndef NDEBUG
lglchkesched(LGL * lgl)3867 static void lglchkesched (LGL * lgl) {
3868   int * p, parent, child, ppos, cpos, size, i, tmp;
3869   Stk * s = &lgl->esched;
3870   size = lglcntstk (s);
3871   p = s->start;
3872   for (ppos = 0; ppos < size; ppos++) {
3873     parent = p[ppos];
3874     tmp = *lglepos (lgl, parent);
3875     assert (ppos == tmp);
3876     for (i = 0; i <= 1; i++) {
3877       cpos = 2*ppos + 1 + i;
3878       if (cpos >= size) continue;
3879       child = p[cpos];
3880       tmp = *lglepos (lgl, child);
3881       assert (cpos == tmp);
3882       assert (lglecmp (lgl, parent, child) >= 0);
3883     }
3884   }
3885 }
3886 #endif
3887 
lgleup(LGL * lgl,int lit)3888 static void lgleup (LGL * lgl, int lit) {
3889   int child = lit, parent, cpos, ppos, * p, * cposptr, * pposptr;
3890   Stk * s = &lgl->esched;
3891   p = s->start;
3892   cposptr = lglepos (lgl, child);
3893   cpos = *cposptr;
3894   assert (cpos >= 0);
3895   while (cpos > 0) {
3896     ppos = (cpos - 1)/2;
3897     parent = p[ppos];
3898     if (lglecmp (lgl, parent, lit) >= 0) break;
3899     pposptr = lglepos (lgl, parent);
3900     assert (*pposptr == ppos);
3901     p[cpos] = parent;
3902     *pposptr = cpos;
3903     LOGESCHED (5, parent, "down from %d", ppos);
3904     cpos = ppos;
3905   }
3906   if (*cposptr == cpos) return;
3907 #ifndef NLGLOG
3908   ppos = *cposptr;
3909 #endif
3910   *cposptr = cpos;
3911   p[cpos] = lit;
3912   LOGESCHED (5, lit, "up from %d", ppos);
3913 #ifndef NDEBUG
3914   if (lgl->opts->check.val >= 2) lglchkesched (lgl);
3915 #endif
3916 }
3917 
lgledown(LGL * lgl,int lit)3918 static void lgledown (LGL * lgl, int lit) {
3919   int parent = lit, child, right, ppos, cpos;
3920   int * p, * pposptr, * cposptr, size;
3921   Stk * s = &lgl->esched;
3922   size = lglcntstk (s);
3923   p = s->start;
3924   pposptr = lglepos (lgl, parent);
3925   ppos = *pposptr;
3926   assert (0 <= ppos);
3927   for (;;) {
3928     cpos = 2*ppos + 1;
3929     if (cpos >= size) break;
3930     child = p[cpos];
3931     if (cpos + 1 < size) {
3932       right = p[cpos + 1];
3933       if (lglecmp (lgl, child, right) < 0)
3934 	cpos++, child = right;
3935     }
3936     if (lglecmp (lgl, child, lit) <= 0) break;
3937     cposptr = lglepos (lgl, child);
3938     assert (*cposptr = cpos);
3939     p[ppos] = child;
3940     *cposptr = ppos;
3941     LOGESCHED (5, child, "up from %d", cpos);
3942     ppos = cpos;
3943   }
3944   if (*pposptr == ppos) return;
3945 #ifndef NLGLOG
3946   cpos = *pposptr;
3947 #endif
3948   *pposptr = ppos;
3949   p[ppos] = lit;
3950   LOGESCHED (5, lit, "down from %d", cpos);
3951 #ifndef NDEBUG
3952   if (lgl->opts->check.val >= 2) lglchkesched (lgl);
3953 #endif
3954 }
3955 
lglifrozen(LGL * lgl,int ilit)3956 static int lglifrozen (LGL * lgl, int ilit) {
3957   int elit = lglexport (lgl, ilit);
3958   Ext * ext = lglelit2ext (lgl, elit);
3959   return ext->frozen || ext->tmpfrozen;
3960 }
3961 
lglesched(LGL * lgl,int lit)3962 static void lglesched (LGL * lgl, int lit) {
3963   AVar * av;
3964   int * p;
3965   Stk * s;
3966   if (lgl->cceing) return;
3967   if (lglifrozen (lgl, lit)) return;
3968   if (!lglisfree (lgl, lit)) return;
3969   if (lgl->donotsched) {
3970     av = lglavar (lgl, lit);
3971     if (lgl->eliminating && av->donotelm) return;
3972     if (lgl->blocking && av->donotblk) return;
3973   }
3974   p = lglepos (lgl, lit);
3975   s = &lgl->esched;
3976   if (*p >= 0) return;
3977   *p = lglcntstk (s);
3978   lglpushstk (lgl, s, lit);
3979   lgleup (lgl, lit);
3980   lgledown (lgl, lit);
3981   LOGESCHED (4, lit, "pushed");
3982 }
3983 
3984 /*------------------------------------------------------------------------*/
3985 
lglgcd(unsigned a,unsigned b)3986 static unsigned lglgcd (unsigned a, unsigned b) {
3987   unsigned tmp;
3988   assert (a), assert (b);
3989   if (a < b) SWAP (unsigned, a, b);
3990   while (b) tmp = b, b = a % b, a = tmp;
3991   return a;
3992 }
3993 
lglrandidxtrav(LGL * lgl,int (* fun)(LGL *,int idx))3994 static int lglrandidxtrav (LGL * lgl, int (*fun)(LGL*,int idx)) {
3995   int idx, delta, mod, prev, first, res;
3996   first = mod = lglmax (lgl->nvars, 2);
3997   idx = lglrand (lgl) % mod;
3998   delta = lglrand (lgl) % mod;
3999   if (!delta) delta++;
4000   while (lglgcd (delta, mod) > 1)
4001     if (++delta == mod) delta = 1;
4002   res = 1;
4003   LOG (2,
4004     "random index traversal start %d delta %d mod %d",
4005      idx, delta, mod);
4006   while (res) {
4007     if (idx >= 2 && !fun (lgl, idx)) res = 0;
4008     else {
4009       prev = idx;
4010       idx += delta;
4011       if (idx >= mod) idx -= mod;
4012       if (idx == first) break;
4013       if (first == mod) first = prev;
4014     }
4015   }
4016   return res;
4017 }
4018 
lglrem(LGL * lgl)4019 static int lglrem (LGL * lgl) {
4020   int res = lgl->nvars;
4021   if (!res) return 0;
4022   assert (res >= 2);
4023   res -= lgl->stats->fixed.current + 2;
4024   assert (res >= 0);
4025   return res;
4026 }
4027 
lglpcnt(double n,double d)4028 static double lglpcnt (double n, double d) {
4029   if (d <= 0 || !n) return 0.0;
4030   return 100.0 * n / d;
4031 }
4032 
lglecalc(LGL * lgl,EVar * ev)4033 static int lglecalc (LGL * lgl, EVar * ev) {
4034   int oldscore = ev->score, o0 = ev->occ[0], o1 = ev->occ[1], newscore;
4035   if (!o0 || !o1) newscore = 0;
4036   else newscore = o0 + o1;
4037   ev->score = newscore;
4038   return newscore - oldscore;
4039 }
4040 
lglocc(LGL * lgl,int lit)4041 static int lglocc (LGL * lgl, int lit) {
4042   if (!lgl->occs) return lglhts (lgl, lit)->count;
4043   return lglevar (lgl, lit)->occ[lit < 0];
4044 }
4045 
lglflushtouched(LGL * lgl)4046 static void lglflushtouched (LGL * lgl) {
4047   int * q, idx, mt = 0, * pos = lgl->elm->touched.pos, newpos = 0;
4048   Stk * touched = &lgl->elm->touched.stk;
4049   const int * p;
4050   for (p = q = touched->start; p < touched->top; p++) {
4051     if ((idx = *p)) {
4052       assert (1 < idx), assert (idx < lgl->elm->touched.nvars);
4053       pos[idx] = newpos++;
4054       *q++ = idx;
4055     } else mt++;
4056   }
4057   LOG (2, "flushed %d empty entries on touched stack kept %d", mt, newpos);
4058   assert (lgl->elm->touched.mt == mt);
4059   lgl->elm->touched.mt = 0;
4060   touched->top = q;
4061 }
4062 
lgltouch(LGL * lgl,int lit)4063 static void lgltouch (LGL * lgl, int lit) {
4064   int idx = abs (lit), * posptr, oldpos, newpos;
4065   assert (lgl->elm);
4066   posptr = lgl->elm->touched.pos + idx;
4067   newpos = lglcntstk (&lgl->elm->touched.stk);
4068   oldpos = *posptr;
4069   assert (oldpos < 0 || lglpeek (&lgl->elm->touched.stk, oldpos) == idx);
4070   LOG (4, "touching %d (moved to %d from %d)", idx, newpos, oldpos);
4071   lglpushstk (lgl, &lgl->elm->touched.stk, idx);
4072   *posptr = newpos;
4073   if (oldpos >= 0) {
4074     lglpoke (&lgl->elm->touched.stk, oldpos, 0);
4075     lgl->elm->touched.mt++;
4076     if (lgl->elm->touched.mt > lgl->elm->touched.nvars)
4077       lglflushtouched (lgl);
4078   }
4079 }
4080 
lglpoptouched(LGL * lgl)4081 static int lglpoptouched (LGL * lgl) {
4082 #if !defined(NDEBUG) || !defined(NLGLOG)
4083   int pos;
4084 #endif
4085   int res, * posptr;
4086   assert (lgl->elm);
4087   for (;;) {
4088     if (lglmtstk (&lgl->elm->touched.stk)) return 0;
4089     if ((res = lglpopstk (&lgl->elm->touched.stk))) break;
4090     assert (lgl->elm->touched.mt > 0);
4091     lgl->elm->touched.mt--;
4092   }
4093 #if !defined(NDEBUG) || !defined(NLGLOG)
4094   pos = lglcntstk (&lgl->elm->touched.stk);
4095 #endif
4096   assert (1 < res), assert (res < lgl->elm->touched.nvars);
4097   posptr = lgl->elm->touched.pos + res;
4098   assert (*posptr >= 0), assert (*posptr == pos);
4099   *posptr = -1;
4100   LOG (4, "popped touched %d at position %d", res, pos);
4101   return res;
4102 }
4103 
lgltouched(LGL * lgl,int lit)4104 static int lgltouched (LGL * lgl, int lit) {
4105   int idx = abs (lit);
4106   assert (1 < idx), assert (idx < lgl->elm->touched.nvars);
4107   return lgl->elm->touched.pos[idx] >= 0;
4108 }
4109 
lglincocc(LGL * lgl,int lit)4110 static void lglincocc (LGL * lgl, int lit) {
4111   int idx, sign, change;
4112   EVar * ev;
4113   if (!lgl->occs) return;
4114   idx = abs (lit), sign = (lit < 0);
4115   ev = lglevar (lgl, lit);
4116   assert (lglisfree (lgl, lit));
4117   ev->occ[sign] += 1;
4118   assert (ev->occ[sign] > 0);
4119   change = lglecalc (lgl, ev);
4120   LOG (3,
4121     "inc occ of %d now occs[%d] = %d %d",
4122     lit, idx, ev->occ[0], ev->occ[1]);
4123   if (ev->pos < 0) lglesched (lgl, idx);
4124   else if (change > 0) lgledown (lgl, idx);
4125   else if (change < 0) lgleup (lgl, idx);
4126   if (lgl->touching) lgltouch (lgl, lit);
4127 }
4128 
lglisact(int act)4129 static int lglisact (int act) { return NOTALIT <= act && act < REMOVED-1; }
4130 
lglrescoreglue(LGL * lgl,int glue)4131 static int lglrescoreglue (LGL * lgl, int glue) {
4132   int * c, * p, oldact, newact, count = 0;
4133   const int retireint = lgl->opts->retireint.val;
4134   Stk * lir = lgl->red + glue;
4135   for (c = lir->start; c < lir->top; c = p + 1) {
4136     oldact = *c;
4137     if (oldact == REMOVED) {
4138       for (p = c + 1; p < lir->top && *p == REMOVED; p++)
4139 	;
4140       assert (p >= lir->top || *p < NOTALIT || lglisact (*p));
4141       p--;
4142     } else if (NOTALIT + retireint < oldact) {
4143       assert (NOTALIT + retireint <= oldact && oldact <= REMOVED - 1);
4144       newact = (oldact - NOTALIT - retireint + 1) / 2;
4145       newact += NOTALIT + retireint;
4146       assert (newact < REMOVED);
4147       *c++ = newact;
4148       LOGCLS (5, c,
4149         "rescoring activity from %d to %d of clause",
4150 	oldact - NOTALIT, newact - NOTALIT);
4151       for (p = c; *p; p++)
4152 	;
4153       count++;
4154     } else {
4155       for (p = c + 1; *p; p++)
4156 	;
4157     }
4158   }
4159   return count;
4160 }
4161 
lglrescoreclauses(LGL * lgl)4162 static void lglrescoreclauses (LGL * lgl) {
4163   int glue, count = 0;
4164   lgl->stats->rescored.clauses++;
4165   for (glue = 0; glue < MAXGLUE; glue++)
4166     count += lglrescoreglue (lgl, glue);
4167   lglprt (lgl, 3,
4168     "[rescored-clauses-%d] rescored activity of %d clauses",
4169     lgl->stats->rescored.clauses, count);
4170 }
4171 
lglchkirrstats(LGL * lgl)4172 static void lglchkirrstats (LGL * lgl) {
4173 #if  0
4174   int idx, sign, lit, blit, tag, red, other, other2, clauses, lits;
4175   const int * p, * w, * eow, * c, * top;
4176   HTS * hts;
4177   clauses = lits = 0;
4178   for (idx = 2; idx < lgl->nvars; idx++)
4179     for (sign = -1; sign <= 1; sign += 2) {
4180       lit = sign * idx;
4181       hts = lglhts (lgl, lit);
4182       w = lglhts2wchs (lgl, hts);
4183       eow = w + hts->count;
4184       for (p = w; p < eow; p++) {
4185 	blit = *p;
4186 	tag = blit & MASKCS;
4187 	if (tag == TRNCS || tag == LRGCS) p++;
4188 	red = blit & REDCS;
4189 	if (red) continue;
4190 	if (tag == BINCS) {
4191 	  other = blit >> RMSHFT;
4192 	  if (abs (other) < idx) continue;
4193 	  lits += 2;
4194 	} else if (tag == TRNCS) {
4195 	  other = blit >> RMSHFT;
4196 	  if (abs (other) < idx) continue;
4197 	  other2 = *p;
4198 	  if (abs (other2) < idx) continue;
4199 	  lits += 3;
4200 	} else continue;
4201 	clauses++;
4202       }
4203     }
4204   top = lgl->irr.top;
4205   for (c = lgl->irr.start; c < top; c = p + 1) {
4206     if (*(p = c) >= NOTALIT) continue;
4207     while (*++p)
4208       ;
4209     lits += p - c;
4210     clauses++;
4211   }
4212   assert (clauses == lgl->stats->irr.clauses.cur);
4213   assert (lits == lgl->stats->irr.lits.cur);
4214 #else
4215   (void) lgl;
4216 #endif
4217 }
4218 
lglincirr(LGL * lgl,int size)4219 static void lglincirr (LGL * lgl, int size) {
4220   if (size < 2) return;
4221   lgl->stats->irr.clauses.cur++;
4222   assert (lgl->stats->irr.clauses.cur > 0);
4223   if (lgl->stats->irr.clauses.cur > lgl->stats->irr.clauses.max)
4224     lgl->stats->irr.clauses.max = lgl->stats->irr.clauses.cur;
4225   lgl->stats->irr.lits.cur += size;
4226   assert (lgl->stats->irr.lits.cur >= size);
4227   if (lgl->stats->irr.lits.cur > lgl->stats->irr.lits.max)
4228     lgl->stats->irr.lits.max = lgl->stats->irr.lits.cur;
4229   lgl->stats->irrprgss++;
4230 }
4231 
lgldecirr(LGL * lgl,int size)4232 static void lgldecirr (LGL * lgl, int size) {
4233   assert (size >= 2);
4234   assert (lgl->stats->irr.clauses.cur > 0);
4235   lgl->stats->irr.clauses.cur--;
4236   assert (lgl->stats->irr.lits.cur >= size);
4237   lgl->stats->irr.lits.cur -= size;
4238   assert (!lgl->stats->irr.clauses.cur == !lgl->stats->irr.lits.cur);
4239   lgl->stats->irrprgss++;
4240 }
4241 
lglincglag(LGL * lgl)4242 static void lglincglag (LGL * lgl) {
4243   if (lgl->glag == MAXGLAG) {
4244     int idx;
4245     for (idx = 2; idx < lgl->nvars; idx++)
4246       lglqvar (lgl, idx)->glag = -1;
4247     lgl->glag = 0;
4248   } else lgl->glag++;
4249   LOG (4, "new glue flag %d", lgl->glag);
4250 }
4251 
lglaged(LGL * lgl,int lit)4252 static int lglaged (LGL * lgl, int lit) {
4253   int level = lglevel (lgl, lit);
4254   QVar * qv;
4255   if (!level++) return 1;
4256   assert (2 <= level), assert (level < lgl->nvars);
4257   qv = lglqvar (lgl, level);
4258   assert (qv->glag <= lgl->glag);
4259   if (qv->glag >= lgl->glag) return 1;
4260   assert (0 <= lgl->glag), assert (lgl->glag <= MAXGLAG);
4261   qv->glag = lgl->glag;
4262   assert (0 <= qv->glag);
4263   return 0;
4264 }
4265 
4266 static const int lglar1scalegluetab[POW2GLUE] =
4267 {
4268 // 0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15
4269    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
4270 };
4271 
4272 static const int lglar2scalegluetab[POW2GLUE] =
4273 {
4274 // 0  1  2  3   4   5   6   7   8   9  10  11  12  13   14   15
4275    0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120
4276 };
4277 
4278 static const int lglsqrtscalegluetab[POW2GLUE] =
4279 {
4280 // 0  1  2  3   4   5   6   7   8   9  10  11    12   13   14   15
4281    0, 1, 2, 5, 10, 17, 26, 37, 50, 65, 82, 101, 122, 145, 170, 197
4282 };
4283 
4284 static const int lglsqrtldscalegluetab[POW2GLUE] =
4285 {
4286 // 0  1  2  3   4   5   6   7   8   9  10   11   12   13    14    15
4287    0, 1, 2, 5, 10, 17, 26, 37, 50, 65, 82, 122, 226, 530, 1522, 5042
4288 };
4289 
4290 static const int lglldscalegluetab[POW2GLUE] =
4291 {
4292 // 0  1  2  3   4   5   6    7    8    9    10    11    12    13     14     15
4293    0, 1, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768
4294 };
4295 
4296 
lglsearchscaleglue(int unscaled,const int * tab)4297 static int lglsearchscaleglue (int unscaled, const int * tab) {
4298   int res;
4299   for (res = 0; res < POW2GLUE && tab[res + 1] <= unscaled; res++)
4300     ;
4301   return res;
4302 }
4303 
4304 #define LGLSEARCHSCALEGLUE(NAME,GLUE) \
4305   lglsearchscaleglue (GLUE, lgl ## NAME ## scalegluetab)
4306 
lglunboundedscaleglue(LGL * lgl,int origlue)4307 static int lglunboundedscaleglue (LGL * lgl, int origlue) {
4308   int res, red;
4309   assert (0 <= origlue);
4310   if (origlue <= lgl->opts->gluekeep.val) res = 0;
4311   else {
4312     red = origlue - lgl->opts->gluekeep.val;
4313     assert (red >= 1);
4314     switch (lgl->opts->gluescale.val) {
4315       default:
4316       case 1: res = LGLSEARCHSCALEGLUE (ar1, red); break;
4317       case 2: res = LGLSEARCHSCALEGLUE (ar2, red); break;
4318       case 3: res = LGLSEARCHSCALEGLUE (sqrt, red); break;
4319       case 4: res = LGLSEARCHSCALEGLUE (sqrtld, red); break;
4320       case 5: res = LGLSEARCHSCALEGLUE (ld, red); break;
4321     }
4322     assert (res > 0);
4323     if (res > MAXGLUE) res = MAXGLUE;
4324   }
4325   assert (0 <= res), assert (res <= MAXGLUE);
4326   return res;
4327 }
4328 
lglscaleglue(LGL * lgl,int origlue)4329 static int lglscaleglue (LGL * lgl, int origlue) {
4330   int res = lglunboundedscaleglue (lgl, origlue);
4331   if (lgl->opts->maxscaledglue.val <= res)
4332     res = MAXGLUE;
4333   assert (0 <= res), assert (res <= MAXGLUE);
4334   return res;
4335 }
4336 
lglunscaleglue(LGL * lgl,int scaledglue)4337 static int lglunscaleglue (LGL * lgl, int scaledglue) {
4338   int res = 0;
4339   assert (0 <= scaledglue), assert (scaledglue <= MAXGLUE);
4340   if (!scaledglue) res = 0;
4341   else {
4342     switch (lgl->opts->gluescale.val) {
4343       default:
4344       case 1: res = lglar1scalegluetab[scaledglue]; break;
4345       case 2: res = lglar2scalegluetab[scaledglue]; break;
4346       case 3: res = lglsqrtldscalegluetab[scaledglue]; break;
4347       case 4: res = lglsqrtldscalegluetab[scaledglue]; break;
4348       case 5: res = lglldscalegluetab[scaledglue]; break;
4349     }
4350     res += lgl->opts->gluekeep.val;
4351   }
4352   assert (lglunboundedscaleglue (lgl, res) == scaledglue);
4353   assert (!res || lglunboundedscaleglue (lgl, res - 1) == scaledglue - 1);
4354   return res;
4355 }
4356 
lglcheckgluereduced(LGL * lgl,int lidx,int gluelim,int sizelim,int * newunscaledglueptr)4357 static int lglcheckgluereduced (LGL * lgl, int lidx,
4358                                int gluelim, int sizelim,
4359 			       int * newunscaledglueptr) {
4360   int oldscaledglue, newunscaledglue, newscaledglue, lit, pos, size;
4361   const int * c;
4362   Stk * lir;
4363   oldscaledglue = (lidx & GLUEMASK);
4364   if (!oldscaledglue) return 0;
4365   if (oldscaledglue >= MAXGLUE) return 0;
4366   lglincglag (lgl);
4367   lir = lgl->red + oldscaledglue;
4368   pos = lidx >> GLUESHFT;
4369   assert (pos > 0);
4370   c = lir->start + pos;
4371   if (c > lir->top) return 0;
4372   if (c[0] >= REMOVED) return 0;
4373   assert (lir->start < c && c < lir->end);
4374   size = newunscaledglue = 0;
4375   while ((lit = c[size])) {
4376     if (++size > sizelim) return 0;
4377     if (lglaged (lgl, lit)) continue;
4378     if (++newunscaledglue > gluelim) return 0;
4379   }
4380   newscaledglue = lglscaleglue (lgl, newunscaledglue);
4381   if (oldscaledglue <= newscaledglue) return 0;
4382   LOG (4,
4383     "old scaled glue %d size %d clause at %d has new scaled glue %d"
4384     " (unscaled %d)",
4385     oldscaledglue, size, pos, newscaledglue, newunscaledglue);
4386   if (newunscaledglueptr) *newunscaledglueptr = newunscaledglue;
4387   return 1;
4388 }
4389 
lglcheckpromotion(LGL * lgl,int lidx)4390 static void lglcheckpromotion (LGL * lgl, int lidx) {
4391   const int gluelim = lgl->opts->promotegluelim.val;
4392   int glue;
4393   if (!lgl->opts->promote.val) return;
4394   glue = lidx & GLUEMASK;
4395   if (!glue) return;
4396   if (glue >= MAXGLUE) return;
4397   if (!lglcheckgluereduced (lgl, lidx, gluelim, INT_MAX, 0)) return;
4398   LOG (4,
4399     "saving clause idx red[%d][%d] on promotion stack",
4400     glue, (lidx >> GLUESHFT));
4401   lglpushstk (lgl, &lgl->promote, lidx);
4402   lgl->stats->promote.tried++;
4403 }
4404 
lglbumplidx(LGL * lgl,int lidx)4405 static void lglbumplidx (LGL * lgl, int lidx) {
4406   int glue = (lidx & GLUEMASK), * c, *ap, act, pos;
4407   const int retirenb = lgl->opts->retirenb.val;
4408   const int retireint = lgl->opts->retireint.val;
4409   Stk * lir = lgl->red + glue;
4410   if (lgl->simp && !lgl->opts->bumpsimp.val) return;
4411   if (glue >= MAXGLUE) return;
4412   pos = lidx >> GLUESHFT;
4413   c = lir->start + pos;
4414   assert (lir->start < c && c < lir->end);
4415   ap = c - 1;
4416   act = *ap;
4417   if (act < REMOVED - 1) {
4418     LGLCHKACT (act);
4419     act += 1;
4420     if (retirenb && act < NOTALIT + retireint) act = NOTALIT + retireint;
4421     LGLCHKACT (act);
4422     *ap = act;
4423   }
4424   LOGCLS (4, c, "bumped activity to %d of glue %d clause", act-NOTALIT, glue);
4425   lgl->stats->lir[glue].resolved++;
4426   assert (lgl->stats->lir[glue].resolved > 0);
4427   if (act >= REMOVED - 1) lglrescoreclauses (lgl);
4428 }
4429 
lglbumpnupdatelidx(LGL * lgl,int lidx)4430 static void lglbumpnupdatelidx (LGL * lgl, int lidx) {
4431   lglbumplidx (lgl, lidx);
4432   lglcheckpromotion (lgl, lidx);
4433 }
4434 
lglincjwh(LGL * lgl,int lit,Flt inc)4435 static void lglincjwh (LGL * lgl, int lit, Flt inc) {
4436   int ulit = lglulit (lit);
4437   Flt old = lgl->jwh[ulit];
4438   Flt new = lgladdflt (old, inc);
4439   lgl->jwh[ulit] = new;
4440 }
4441 
lglmtaux(LGL * lgl,int red)4442 static void lglmtaux (LGL * lgl, int red) {
4443   assert (!red || red == REDCS);
4444   if (lgl->mt) return;
4445   LOG (1, "adding empty clause");
4446   lgl->mt = 1;
4447   lgldrupligaddclsarg (lgl, red, 0);
4448 }
4449 
lglmt(LGL * lgl)4450 static void lglmt (LGL * lgl) { lglmtaux (lgl, REDCS); }
4451 
lgladdcls(LGL * lgl,int red,int origlue,int force)4452 static int lgladdcls (LGL * lgl, int red, int origlue, int force) {
4453   int size, lit, other, other2, * p, lidx, unit, blit;
4454   int64_t * maxbytesptr, bytes;
4455   int scaledglue, prevglue;
4456   Flt inc;
4457   Val val;
4458   Stk * w;
4459   lgl->stats->prgss++;
4460   if (lgl->eliminating) {
4461     size = lglcntstk (&lgl->clause);
4462     ADDSTEPS (elm.steps, size);
4463   }
4464   if (!red) lgl->stats->irrprgss++;
4465   assert (!lglmtstk (&lgl->clause));
4466   assert (!lgl->clause.top[-1]);
4467   if (force) lglchksimpcls (lgl);
4468   size = lglcntstk (&lgl->clause) - 1;
4469   if (!red) lglincirr (lgl, size);
4470   else if (size == 2) lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
4471   else if (size == 3) lgl->stats->red.trn++, assert (lgl->stats->red.trn > 0);
4472   assert (size >= 0);
4473   if (!size) {
4474     lglmtaux (lgl, red);
4475     return 0;
4476   }
4477   lit = lgl->clause.start[0];
4478   if (size == 1) {
4479     assert (lglval (lgl, lit) >= 0);
4480     if (!lglval (lgl, lit)) lglunit (lgl, lit);
4481     return 0;
4482   }
4483   inc = lglflt (-size, 1);
4484   other = lgl->clause.start[1];
4485   if (size == 2) {
4486     lglwchbin (lgl, lit, other, red);
4487     lglwchbin (lgl, other, lit, red);
4488     if (red) {
4489       if (force && lglval (lgl, lit) < 0) lglf2rce (lgl, other, lit, REDCS);
4490       if (force && lglval (lgl, other) < 0) lglf2rce (lgl, lit, other, REDCS);
4491     } else if (lgl->dense) {
4492       assert (!red);
4493       lglincocc (lgl, lit);
4494       lglincocc (lgl, other);
4495     }
4496     if (!red) lglincjwh (lgl, lit, inc), lglincjwh (lgl, other, inc);
4497     return 0;
4498   }
4499   lglordercls (lgl);
4500   lit = lgl->clause.start[0];
4501   other = lgl->clause.start[1];
4502   if (size == 3) {
4503     other2 = lgl->clause.start[2];
4504     lglwchtrn (lgl, lit, other, other2, red);
4505     lglwchtrn (lgl, other, lit, other2, red);
4506     lglwchtrn (lgl, other2, lit, other, red);
4507     if (red) {
4508       if (force && lglval (lgl, lit) < 0 && lglval (lgl, other) < 0)
4509 	lglf3rce (lgl, other2, lit, other, REDCS);
4510       if (force && lglval (lgl, lit) < 0 && lglval (lgl, other2) < 0)
4511 	lglf3rce (lgl, other, lit, other2, REDCS);
4512       if (force && lglval (lgl, other) < 0 && lglval (lgl, other2) < 0)
4513 	lglf3rce (lgl, lit, other, other2, REDCS);
4514     } else if (lgl->dense) {
4515       assert (!red);
4516       lglincocc (lgl, lit);
4517       lglincocc (lgl, other);
4518       lglincocc (lgl, other2);
4519     }
4520     if (!red) lglincjwh (lgl, lit, inc),
4521               lglincjwh (lgl, other, inc),
4522 	      lglincjwh (lgl, other2, inc);
4523     return 0;
4524   }
4525   assert (size > 3);
4526   if (red) {
4527     scaledglue = lglscaleglue (lgl, origlue);
4528     if (scaledglue == MAXGLUE &&
4529 	lgl->opts->keepmaxglue.val &&
4530   !(lgl->stats->clauses.maxglue.count % lgl->opts->keepmaxglueint.val)) {
4531       lgl->stats->clauses.maxglue.count++;
4532       lgl->stats->clauses.maxglue.kept++;
4533       scaledglue = MAXGLUE-1;
4534       LOG (2,
4535         "reducing maximum glue %d to %d to keep clause",
4536 	MAXGLUE, scaledglue);
4537     }
4538     lgl->stats->clauses.scglue += scaledglue;
4539     if (scaledglue == MAXGLUE) {
4540       lgl->stats->clauses.maxglue.count++;
4541 #ifndef NDEBUG
4542       lglclnstk (&lgl->prevclause);
4543       lgl->prevglue = -1;
4544 #endif
4545     } else lgl->stats->clauses.nonmaxglue++;
4546     w = lgl->red + scaledglue;
4547     lidx = lglcntstk (w) + 1;
4548     if (lidx > MAXREDLIDX) {
4549       prevglue = scaledglue;
4550       if (lidx > MAXREDLIDX) {
4551 	scaledglue = prevglue;
4552 	while (scaledglue + 1 < MAXGLUE && lidx > MAXREDLIDX) {
4553 	  w = lgl->red + ++scaledglue;
4554 	  lidx = lglcntstk (w) + 1;
4555 	}
4556       }
4557       if (lidx > MAXREDLIDX) {
4558 	scaledglue = prevglue;
4559 	while (scaledglue > 0 && lidx > MAXREDLIDX) {
4560 	  w = lgl->red + --scaledglue;
4561 	  lidx = lglcntstk (w) + 1;
4562 	}
4563       }
4564       if (lidx > MAXREDLIDX && scaledglue < MAXGLUE) {
4565 	w = lgl->red + (scaledglue = MAXGLUE);
4566 	lidx = lglcntstk (w) + 1;
4567       }
4568       if (lidx > MAXREDLIDX && scaledglue == MAXGLUE) {
4569 	lglbacktrack (lgl, 0);
4570 	lidx = lglcntstk (w);
4571 	assert (!lidx);
4572       }
4573       if (lidx > MAXREDLIDX)
4574 	lgldie (lgl, "number of redundant large clause literals exhausted");
4575     }
4576     assert (w == lgl->red + scaledglue);
4577     maxbytesptr = &lgl->stats->lir[scaledglue].maxbytes;
4578     lglpushstk (lgl, w, NOTALIT);
4579     assert (lidx == lglcntstk (w));
4580     lidx <<= GLUESHFT;
4581     assert (0 <= lidx);
4582     lidx |= scaledglue;
4583     if (scaledglue < MAXGLUE) {
4584       lgl->stats->lir[scaledglue].clauses++;
4585       assert (lgl->stats->lir[scaledglue].clauses > 0);
4586     }
4587     lgl->stats->lir[scaledglue].added++;
4588     assert (lgl->stats->lir[scaledglue].added > 0);
4589   } else {
4590     w = &lgl->irr;
4591     maxbytesptr = &lgl->stats->irr.maxbytes;
4592     lidx = lglcntstk (w);
4593     scaledglue = 0;
4594     if (lidx <= 0 && !lglmtstk (w))
4595       lgldie (lgl, "number of irredundant large clause literals exhausted");
4596   }
4597   for (p = lgl->clause.start; (other2 = *p); p++)
4598     lglpushstk (lgl, w, other2), lglincjwh (lgl, other2, inc);
4599   lglpushstk (lgl, w, 0);
4600   bytes = sizeof (int) * (int64_t) lglcntstk (w);
4601   if (bytes > *maxbytesptr) *maxbytesptr = bytes;
4602   if (red) {
4603     unit = 0;
4604     for (p = lgl->clause.start; (other2 = *p); p++) {
4605       val = lglval (lgl, other2);
4606       assert (!force || val <= 0);
4607       if (val < 0) continue;
4608       if (unit) unit = INT_MAX;
4609       else unit = other2;
4610     }
4611     if (force && unit && unit != INT_MAX) lglflrce (lgl, unit, red, lidx);
4612   }
4613   assert (red == 0 || red == REDCS);
4614   if (!red || (red && scaledglue < MAXGLUE)) {
4615     (void) lglwchlrg (lgl, lit, other, red, lidx);
4616     (void) lglwchlrg (lgl, other, lit, red, lidx);
4617   }
4618   if (red && scaledglue != MAXGLUE) {
4619     // lglbumplidx (lgl, lidx); 		// TODO why was this here?
4620     lgl->stats->red.lrg++;
4621   }
4622   if (!red && lgl->dense) {
4623     if (lidx > MAXIRRLIDX)
4624       lgldie (lgl, "number of irredundant large clause literals exhausted");
4625     blit = (lidx << RMSHFT) | OCCS;
4626     for (p = lgl->clause.start; (other2 = *p); p++) {
4627       lglincocc (lgl, other2);
4628       lglpushwch (lgl, lglhts (lgl, other2), blit);
4629     }
4630   }
4631   lglchkirrstats (lgl);
4632   return lidx;
4633 }
4634 
lgliadd(LGL * lgl,int ilit)4635 static void lgliadd (LGL * lgl, int ilit) {
4636   int size;
4637 #ifndef NLGLOG
4638   if (lglmtstk (&lgl->clause)) LOG (4, "opening irredundant clause");
4639 #endif
4640   assert (abs (ilit) < 2 || abs (ilit) < lgl->nvars);
4641   lglpushstk (lgl, &lgl->clause, ilit);
4642   if (ilit) {
4643     LOG (4, "added literal %d", ilit);
4644   } else {
4645     LOG (4, "closing irredundant clause");
4646     LOGCLS (3, lgl->eclause.start, "external irredundant clause");
4647     LOGCLS (3, lgl->clause.start, "internal unsimplified irredundant clause");
4648 #ifndef NLGLDRUPLIG
4649     if (lgldruplig (lgl)) {
4650       const int * p;
4651       int other;
4652       for (p = lgl->eclause.start; (other = *p); p++)
4653 	druplig_add_literal (lgl->druplig, other);
4654       lgldrupligreallyadd (lgl, 0);
4655     }
4656 #endif
4657     if (!lglesimpcls (lgl)) {
4658       lgladdcls (lgl, 0, 0, 1);
4659       lgl->stats->irr.clauses.add++;
4660       size = lglcntstk (&lgl->clause) - 1;
4661       assert (size >= 0);
4662       lgl->stats->irr.lits.add += size;
4663     }
4664     lglclnstk (&lgl->clause);
4665     lglclnstk (&lgl->eclause);
4666   }
4667 }
4668 
lgleunassignall(LGL * lgl)4669 static void lgleunassignall (LGL * lgl) {
4670   int eidx;
4671   for (eidx = 1; eidx <= lgl->maxext; eidx++)
4672     lglelit2ext (lgl, eidx)->val = 0;
4673 }
4674 
lglchkeassumeclean(LGL * lgl)4675 static void lglchkeassumeclean (LGL * lgl) {
4676   assert (lglmtstk (&lgl->eassume));
4677 #ifndef NDEBUG
4678   int eidx;
4679   for (eidx = 1; eidx <= lgl->maxext; eidx++) {
4680     Ext * ext = lglelit2ext (lgl, eidx);
4681     assert (!ext->assumed);
4682     assert (!ext->failed);
4683   }
4684 #endif
4685 }
4686 
lglchkassumeclean(LGL * lgl)4687 static void lglchkassumeclean (LGL * lgl) {
4688   assert (!lgl->failed);
4689   assert (!lgl->assumed);
4690   assert (lglmtstk (&lgl->assume));
4691 #ifndef NDEBUG
4692   if (lgl->opts->check.val >= 1) {
4693     int idx;
4694     for (idx = 2; idx < lgl->nvars; idx++) {
4695       AVar * av = lglavar (lgl, idx);
4696       assert (!av->assumed);
4697       assert (!av->failed);
4698     }
4699   }
4700 #endif
4701 }
4702 
lglreset(LGL * lgl)4703 static void lglreset (LGL * lgl) {
4704   int elit, ilit, erepr;
4705   Ext * ext, * rext;
4706   unsigned bit;
4707   AVar * av;
4708   if (lgl->state == RESET) return;
4709   if (lgl->state <= USED) return;
4710   assert (lgl->state & (UNKNOWN|SATISFIED|EXTENDED|UNSATISFIED|FAILED|LOOKED));
4711   if (lgl->level > 0) lglbacktrack (lgl, 0);
4712   if (!lglmtstk (&lgl->eassume)) {
4713     LOG (2, "resetting %d external assumptions", lglcntstk (&lgl->eassume));
4714     while (!lglmtstk (&lgl->eassume)) {
4715       elit = lglpopstk (&lgl->eassume);
4716       ext = lglelit2ext (lgl, elit);
4717       ext->assumed = 0;
4718       if (ext->failed) {
4719 	ext->failed = 0;
4720 	erepr = lglerepr (lgl, elit);
4721 	if (erepr != elit) {
4722 	  rext = lglelit2ext (lgl, erepr);
4723 	  rext->failed = 0;
4724 	}
4725       }
4726     }
4727   }
4728   lglchkeassumeclean (lgl);
4729   if (!lglmtstk (&lgl->assume)) {
4730     LOG (2, "resetting %d internal assumptions", lglcntstk (&lgl->assume));
4731     while (!lglmtstk (&lgl->assume)) {
4732       ilit = lglpopstk (&lgl->assume);
4733       av = lglavar (lgl, ilit);
4734       bit = (1u << (ilit < 0));
4735       assert (av->assumed & bit);
4736       av->assumed &= ~bit;
4737       av->failed &= ~bit;
4738     }
4739   }
4740   if (lgl->failed) {
4741     LOG (2, "resetting internal failed assumption %d", lgl->failed);
4742     lgl->failed = 0;
4743   }
4744   if (lgl->assumed) {
4745     LOG (2, "resetting assumption queue level to 0 from %d", lgl->assumed);
4746     lgl->assumed = 0;
4747   }
4748   lglchkassumeclean (lgl);
4749   lgleunassignall (lgl);
4750   if (lgl->cbs && lgl->cbs->term.done) {
4751     LOG (2, "resetting forced termination done flag");
4752     lgl->cbs->term.done = 0;
4753   }
4754   TRANS (RESET);
4755 }
4756 
lgluse(LGL * lgl)4757 static void lgluse (LGL * lgl) {
4758   if (lgl->state >= USED) return;
4759   assert (lgl->state == UNUSED || lgl->state == OPTSET);
4760   TRANS (USED);
4761 }
4762 
lglupdatealiased(LGL * lgl,int elit)4763 static void lglupdatealiased (LGL * lgl, int elit) {
4764   Ext * ext;
4765   int erepr;
4766   assert (elit), assert (elit != INT_MIN);
4767   if (abs (elit) > lgl->maxext) return;
4768   erepr = lglerepr (lgl, elit);
4769   if (erepr == elit) return;
4770   ext = lglelit2ext (lgl, erepr);
4771   if (ext->aliased) return;
4772   LOG (4,
4773     "external literal %d aliased by external literal %d",
4774     erepr, elit);
4775   ext->aliased = 1;
4776 }
4777 
lgleadd(LGL * lgl,int elit)4778 static void lgleadd (LGL * lgl, int elit) {
4779   int ilit;
4780   lglreset (lgl);
4781   if (elit) {
4782     lglupdatealiased (lgl, elit);
4783     ilit = lglimport (lgl, elit);
4784     LOG (4, "adding external literal %d as %d", elit, ilit);
4785   } else {
4786     ilit = 0;
4787     LOG (4, "closing external clause");
4788   }
4789   lglpushstk (lgl, &lgl->eclause, elit);
4790   lgliadd (lgl, ilit);
4791 #ifndef NCHKSOL
4792   lglpushstk (lgl, &lgl->orig, elit);
4793 #endif
4794 }
4795 
lgladd(LGL * lgl,int elit)4796 void lgladd (LGL * lgl, int elit) {
4797   int eidx = abs (elit);
4798   Ext * ext;
4799   REQINITNOTFORKED ();
4800   TRAPI ("add %d", elit);
4801   if (0 < eidx && eidx <= lgl->maxext) {
4802     ext = lglelit2ext (lgl, elit);
4803     ABORTIF (ext->melted, "adding melted literal %d", elit);
4804   }
4805   lgl->stats->calls.add++;
4806   lgleadd (lgl, elit);
4807   lgluse (lgl);
4808   if (lgl->clone) lgladd (lgl->clone, elit);
4809 }
4810 
lglisetphase(LGL * lgl,int lit,int phase)4811 static void lglisetphase (LGL * lgl, int lit, int phase) {
4812   AVar * av;
4813   if (lit < 0) lit = -lit, phase = -phase;
4814   av = lglavar (lgl, lit);
4815   av->fase = phase;
4816   LOG (2, "setting phase of internal literal %d to %d", lit, phase);
4817 }
4818 
lglesetphase(LGL * lgl,int elit,int phase)4819 static void lglesetphase (LGL * lgl, int elit, int phase) {
4820   int ilit = lglimport (lgl, elit);
4821   if (abs (ilit) >= 2) {
4822     LOG (2, "setting phase of external literal %d to %d", elit, phase);
4823     lglisetphase (lgl, ilit, phase);
4824   } else LOG (2, "setting phase of external literal %d skipped", elit);
4825 }
4826 
lglsetphase(LGL * lgl,int elit)4827 void lglsetphase (LGL * lgl, int elit) {
4828   REQINITNOTFORKED ();
4829   TRAPI ("setphase %d", elit);
4830   ABORTIF (!elit, "invalid literal argument");
4831   if (elit < 0) lglesetphase (lgl, -elit, -1);
4832   else lglesetphase (lgl, elit, 1);
4833   if (lgl->clone) lglsetphase (lgl->clone, elit);
4834 }
4835 
lglresetphase(LGL * lgl,int elit)4836 void lglresetphase (LGL * lgl, int elit) {
4837   REQINITNOTFORKED ();
4838   TRAPI ("resetphase %d", elit);
4839   ABORTIF (!elit, "invalid literal argument");
4840   lglesetphase (lgl, elit, 0);
4841   if (lgl->clone) lglresetphase (lgl->clone, elit);
4842 }
4843 
lgleassume(LGL * lgl,int elit)4844 static void lgleassume (LGL * lgl, int elit) {
4845   int ilit, val;
4846   unsigned bit;
4847   AVar * av;
4848   Ext * ext;
4849   lglreset (lgl);
4850   ilit = lglimport (lgl, elit);
4851   LOG (2, "assuming external literal %d", elit);
4852   bit = 1u << (elit < 0);
4853   ext = lglelit2ext (lgl, elit);
4854   if (!(ext->assumed & bit)) {
4855     ext->assumed |= bit;
4856     lglpushstk (lgl, &lgl->eassume, elit);
4857   }
4858   assert (!lgl->level);
4859   if (!(val = lglcval (lgl, ilit))) {
4860     av = lglavar (lgl, ilit);
4861     bit = (1u << (ilit < 0));
4862     if (av->assumed & bit) {
4863       LOG (2, "internal literal %d already assumed", ilit);
4864     } else {
4865       av->assumed |= bit;
4866       if (av->assumed & (bit^3))
4867 	LOG (2, "negation %d was also already assumed", -ilit);
4868       lglpushstk (lgl, &lgl->assume, ilit);
4869     }
4870   } else if (val > 0) {
4871     LOG (2, "externally assumed literal %d already fixed to true", elit);
4872   } else {
4873     assert (val < 0);
4874     LOG (2, "externally assumed literal %d already fixed to false", elit);
4875     if (ilit != -1) {
4876       av = lglavar (lgl, ilit);
4877       bit = (1u << (ilit < 0));
4878       if (!(av->assumed & bit)) {
4879 	av->assumed |= bit;
4880 	lglpushstk (lgl, &lgl->assume, ilit);
4881       }
4882     }
4883     if (!lgl->failed) lgl->failed = ilit;
4884   }
4885 }
4886 
lglecassume(LGL * lgl,int elit)4887 static void lglecassume (LGL * lgl, int elit) {
4888   LOG (2, "adding external literal %d to assumed clause", elit);
4889 }
4890 
lglassume(LGL * lgl,int elit)4891 void lglassume (LGL * lgl, int elit) {
4892   int eidx = abs (elit);
4893   Ext * ext;
4894   REQINITNOTFORKED ();
4895   TRAPI ("assume %d", elit);
4896   lgl->stats->calls.assume++;
4897   ABORTIF (!elit, "can not assume invalid literal 0");
4898   if (0 < eidx && eidx <= lgl->maxext) {
4899     ext = lglelit2ext (lgl, elit);
4900     ABORTIF (ext->melted, "assuming melted literal %d", elit);
4901   }
4902   lgleassume (lgl, elit);
4903   lgluse (lgl);
4904   lglmelter (lgl);
4905   if (lgl->clone) lglassume (lgl->clone, elit);
4906 }
4907 
lglcassume(LGL * lgl,int elit)4908 void lglcassume (LGL * lgl, int elit) {
4909   int eidx = abs (elit);
4910   Ext * ext;
4911   REQINITNOTFORKED ();
4912   TRAPI ("cassume %d", elit);
4913   lgl->stats->calls.cassume++;
4914   if (0 < eidx && eidx <= lgl->maxext) {
4915     ext = lglelit2ext (lgl, elit);
4916     ABORTIF (ext->melted, "assuming melted literal %d", elit);
4917   }
4918   lglecassume (lgl, elit);
4919   lgluse (lgl);
4920   if (lgl->clone) lglcassume (lgl->clone, elit);
4921 }
4922 
lglfixate(LGL * lgl)4923 void lglfixate (LGL * lgl) {
4924   const int  * p;
4925   Stk eassume;
4926   REQINITNOTFORKED ();
4927   TRAPI ("fixate");
4928   if (lgl->mt) return;
4929   CLR (eassume);
4930   for (p = lgl->eassume.start; p < lgl->eassume.top; p++)
4931     lglpushstk (lgl, &eassume, *p);
4932   for (p = eassume.start; p < eassume.top; p++)
4933     lgleadd (lgl, *p), lgleadd (lgl, 0);
4934   lglrelstk (lgl, &eassume);
4935   lgluse (lgl);
4936   if (lgl->clone) lglfixate (lgl->clone);
4937 }
4938 
lglbonflict(LGL * lgl,int lit,int blit)4939 static void lglbonflict (LGL * lgl, int lit, int blit) {
4940   assert (lglevel (lgl, lit) >= lglevel (lgl, blit >> RMSHFT));
4941   assert (!lgliselim (lgl, blit >> RMSHFT));
4942   assert (!lgliselim (lgl, lit));
4943   lgl->conf.lit = lit;
4944   lgl->conf.rsn[0] = blit;
4945   LOG (2, "inconsistent %s binary clause %d %d",
4946        lglred2str (blit & REDCS), lit, (blit >> RMSHFT));
4947 }
4948 
lgltonflict(LGL * lgl,int lit,int blit,int other2)4949 static void lgltonflict (LGL * lgl, int lit, int blit, int other2) {
4950   assert ((blit & MASKCS) == TRNCS);
4951   assert (lglevel (lgl, lit) >= lglevel (lgl, blit >> RMSHFT));
4952   assert (lglevel (lgl, lit) >= lglevel (lgl, other2));
4953   assert (!lgliselim (lgl, blit >> RMSHFT));
4954   assert (!lgliselim (lgl, other2));
4955   assert (!lgliselim (lgl, lit));
4956   lgl->conf.lit = lit;
4957   lgl->conf.rsn[0] = blit;
4958   lgl->conf.rsn[1] = other2;
4959   LOG (2, "inconsistent %s ternary clause %d %d %d",
4960        lglred2str (blit & REDCS), lit, (blit>>RMSHFT), other2);
4961 }
4962 
lglonflict(LGL * lgl,int check,int lit,int red,int lidx)4963 static void lglonflict (LGL * lgl, int check, int lit, int red, int lidx) {
4964   int glue;
4965 #if !defined (NLGLOG) || !defined (NDEBUG)
4966   int * p, * c = lglidx2lits (lgl, red, lidx);
4967 #endif
4968   assert (red == REDCS || !red);
4969 #ifndef NDEBUG
4970   {
4971     int found = 0;
4972     for (p = c; *p; p++) {
4973       if(*p == lit) found++;
4974       assert (lglval (lgl, *p) <= -check);
4975       assert (lglevel (lgl, lit) >= lglevel (lgl, *p));
4976       assert (!lgliselim (lgl, lit));
4977     }
4978     assert (found == 1);
4979   }
4980 #endif
4981   lgl->conf.lit = lit;
4982   lgl->conf.rsn[0] = red | LRGCS;
4983   lgl->conf.rsn[1] = lidx;
4984 #ifndef NLGLOG
4985   if (lgl->opts->log.val >= 2) {
4986     lglogstart (lgl, 2, "inconsistent %s large clause", lglred2str (red));
4987     for (p = c ; *p; p++)
4988       fprintf (lgl->out, " %d", *p);
4989     lglogend (lgl);
4990   }
4991 #endif
4992   if (red) {
4993     glue = lidx & GLUEMASK;
4994     lgl->stats->lir[glue].conflicts++;
4995     assert (lgl->stats->lir[glue].conflicts > 0);
4996   }
4997 }
4998 
lgldeclscnt(LGL * lgl,int size,int red,int glue)4999 static void lgldeclscnt (LGL * lgl, int size, int red, int glue) {
5000   assert (!red || red == REDCS);
5001   if (!red) lgldecirr (lgl, size);
5002   else if (size == 2) assert (lgl->stats->red.bin), lgl->stats->red.bin--;
5003   else if (size == 3) assert (lgl->stats->red.trn), lgl->stats->red.trn--;
5004   else {
5005     assert (lgl->stats->red.lrg > 0);
5006     lgl->stats->red.lrg--;
5007     assert (lgl->stats->lir[glue].clauses > 0);
5008     lgl->stats->lir[glue].clauses--;
5009   }
5010 }
5011 
lglrminc(LGL * lgl,const int * w,const int * eow)5012 static void lglrminc (LGL * lgl, const int * w, const int * eow) {
5013   int inc;
5014   assert (w <= eow);
5015   assert (sizeof w < 8 || eow <= w + INT_MAX);
5016   inc = eow - w;
5017   assert (inc >= 0);
5018   inc >>= lgl->opts->rmincpen.val;
5019   inc++;
5020   assert (lgl->blocking + lgl->eliminating + lgl->simpleprobing <= 1);
5021   if (lgl->blocking) ADDSTEPS (blk.steps, inc);
5022   else if (lgl->eliminating) ADDSTEPS (elm.steps, inc);
5023   else if (lgl->simpleprobing) ADDSTEPS (prb.simple.steps, inc);
5024 }
5025 
lglrmtwch(LGL * lgl,int lit,int other1,int other2,int red)5026 static void lglrmtwch (LGL * lgl, int lit, int other1, int other2, int red) {
5027   int * p, blit, other, blit1, blit2, * w, * eow, tag;
5028   HTS * hts;
5029   assert (!red || red == REDCS);
5030   LOG (3, "removing %s ternary watch %d blits %d %d",
5031        lglred2str (red), lit, other1, other2);
5032   hts = lglhts (lgl, lit);
5033   assert (hts->count >= 2);
5034   p = w = lglhts2wchs (lgl, hts);
5035   eow = w + hts->count;
5036   lglrminc (lgl, w, eow);
5037   blit1 = RMSHFTLIT (other1) | red | TRNCS;
5038   blit2 = RMSHFTLIT (other2) | red | TRNCS;
5039   for (;;) {
5040     assert (p < eow);
5041     blit = *p++;
5042     tag = blit & MASKCS;
5043     if (tag == BINCS || tag == OCCS) continue;
5044     other = *p++;
5045     if (tag == LRGCS) continue;
5046     assert (tag == TRNCS);
5047     if (blit == blit1 && other == other2) break;
5048     if (blit == blit2 && other == other1) break;
5049   }
5050   while (p < eow) p[-2] = p[0], p++;
5051   lglshrinkhts (lgl, hts, p - w - 2);
5052 }
5053 
lglpopnunmarkstk(LGL * lgl,Stk * stk)5054 static void lglpopnunmarkstk (LGL * lgl, Stk * stk) {
5055   while (!lglmtstk (stk)) {
5056     int lit = lglpopstk (stk);
5057     if (!lit) continue;
5058     lglavar (lgl, lit)->mark = 0;
5059   }
5060 }
5061 
lglpopnunlcamarkstk(LGL * lgl,Stk * stk)5062 static void lglpopnunlcamarkstk (LGL * lgl, Stk * stk) {
5063   while (!lglmtstk (stk))
5064     lglavar (lgl, lglpopstk (stk))->lcamark = 0;
5065 }
5066 
lglcamarked(LGL * lgl,int lit)5067 static int lglcamarked (LGL * lgl, int lit) {
5068   switch (lglavar (lgl, lit)->lcamark) {
5069     case 1: return (lit < 0) ? -1 : 1;
5070     case 2: return (lit < 0) ? -2 : 2;
5071     case 4: return (lit < 0) ? 1 : -1;
5072     case 8: return (lit < 0) ? 2 : -2;
5073     default: assert (!lglavar (lgl, lit)->lcamark); return 0;
5074   }
5075 }
5076 
lglcamark(LGL * lgl,int lit,int mark)5077 static void lglcamark (LGL * lgl, int lit, int mark) {
5078   int newmark;
5079   AVar * av;
5080   assert (mark == 1 || mark == 2);
5081   av = lglavar (lgl, lit);
5082   assert (!av->lcamark);
5083   newmark = mark;
5084   if (lit < 0) newmark <<= 2;
5085   av->lcamark = newmark;
5086   lglpushstk (lgl, &lgl->lcaseen, lit);
5087   assert (lglcamarked (lgl, lit) == mark);
5088   assert (lglcamarked (lgl, -lit) == -mark);
5089 }
5090 
lgbiglca(LGL * lgl,int a,int b,int64_t * stepsptr)5091 static int lgbiglca (LGL * lgl, int a, int b, int64_t * stepsptr) {
5092   int blit, tag, mark, negmark, prevmark, c, res, prev, next;
5093   const int * p, * w, * eow;
5094   int64_t steps;
5095   HTS * hts;
5096   assert (a), assert (b);
5097   assert (abs (a) != abs (b));
5098   assert (lglevel (lgl, a));
5099   assert (lglevel (lgl, b));
5100   assert (lglval (lgl, a) > 0);
5101   assert (lglval (lgl, b) > 0);
5102   assert (lglgetdom (lgl, a) == lglgetdom (lgl, b));
5103   assert (lglmtstk (&lgl->lcaseen));
5104   lglcamark (lgl, a, 1);
5105   lglcamark (lgl, b, 2);
5106   res = next = 0;
5107   steps = 0;
5108   while (next < lglcntstk (&lgl->lcaseen)) {
5109     c = lglpeek (&lgl->lcaseen, next++);
5110     assert (lglval (lgl, c) > 0);
5111     assert (lglevel (lgl, c) > 0);
5112     mark = lglcamarked (lgl, c);
5113     assert (mark == 1 || mark == 2);
5114     negmark = mark ^ 3;
5115     hts = lglhts (lgl, c);
5116     if (!hts->count) continue;
5117     w = lglhts2wchs (lgl, hts);
5118     eow = w + hts->count;
5119     steps++;
5120     for (p = w; p < eow; p++) {
5121       blit = *p;
5122       tag = blit & MASKCS;
5123       if (tag == TRNCS || tag == LRGCS) p++;
5124       if (tag != BINCS) continue;
5125       prev = -(blit >> RMSHFT);
5126       if (!lglevel (lgl, prev)) continue;
5127       if (lglval (lgl, prev) <= 0) continue;
5128       if ((prevmark = lglcamarked (lgl, prev)) < 0) continue;
5129       if (mark == prevmark) continue;
5130       if (prevmark == negmark) { res = prev; goto DONE; }
5131       lglcamark (lgl, prev, mark);
5132     }
5133   }
5134 DONE:
5135   lglpopnunlcamarkstk (lgl, &lgl->lcaseen);
5136   LOG (3, "least common ancestor of %d and %d is %d", a, b, res);
5137   *stepsptr += steps;
5138   return res;
5139 }
5140 
lglimplca(LGL * lgl,int a,int b,int64_t * stepsptr)5141 static int lglimplca (LGL * lgl, int a, int b, int64_t * stepsptr) {
5142   int r0, tag, mark, negmark, prevmark, c, res, prev, next;
5143   int64_t steps;
5144   assert (a), assert (b);
5145   assert (abs (a) != abs (b));
5146   assert (lglevel (lgl, a));
5147   assert (lglevel (lgl, b));
5148   assert (lglval (lgl, a) > 0);
5149   assert (lglval (lgl, b) > 0);
5150   assert (lglgetdom (lgl, a) == lglgetdom (lgl, b));
5151   assert (lglmtstk (&lgl->lcaseen));
5152   lglcamark (lgl, a, 1);
5153   lglcamark (lgl, b, 2);
5154   res = next = 0;
5155   steps = 0;
5156   while (next < lglcntstk (&lgl->lcaseen)) {
5157     c = lglpeek (&lgl->lcaseen, next++);
5158     assert (lglval (lgl, c) > 0);
5159     assert (lglevel (lgl, c) > 0);
5160     mark = lglcamarked (lgl, c);
5161     assert (mark == 1 || mark == 2);
5162     negmark = mark ^ 3;
5163     steps++;
5164     r0 = *lglrsn (lgl, c);
5165     tag = r0 & MASKCS;
5166     if (tag != BINCS) continue;
5167     prev = -(r0 >> RMSHFT);
5168     if (!lglevel (lgl, prev)) continue;
5169     if (lglval (lgl, prev) <= 0) continue;
5170     if ((prevmark = lglcamarked (lgl, prev)) < 0) continue;
5171     if (mark == prevmark) continue;
5172     if (prevmark == negmark) { res = prev; goto DONE; }
5173     lglcamark (lgl, prev, mark);
5174   }
5175 DONE:
5176   lglpopnunlcamarkstk (lgl, &lgl->lcaseen);
5177   LOG (3, "least common ancestor of %d and %d is %d", a, b, res);
5178   *stepsptr += steps;
5179   return res;
5180 }
5181 
5182 
lglhbrdom(LGL * lgl,int a,int b,int64_t * stepsptr)5183 static int lglhbrdom (LGL * lgl, int a, int b, int64_t * stepsptr) {
5184   assert (lglgetdom (lgl, a) == lglgetdom (lgl, b));
5185   switch (lgl->opts->hbrdom.val) {
5186     case 2: return lgbiglca (lgl, a, b, stepsptr);
5187     case 1: return lglimplca (lgl, a, b, stepsptr);
5188     default: return lglgetdom (lgl, a);
5189   }
5190 }
5191 
lglrmlwch(LGL * lgl,int lit,int red,int lidx)5192 static void lglrmlwch (LGL * lgl, int lit, int red, int lidx) {
5193   int blit, tag, * p, * q, * w, * eow, ored, olidx;
5194   HTS * hts;
5195 #ifndef NLGLOG
5196   p = lglidx2lits (lgl, red, lidx);
5197   if (red)
5198     LOG (3, "removing watch %d in red[%d][%d] %d %d %d %d%s",
5199 	 lit, (lidx & GLUEMASK), (lidx >> GLUESHFT), p[0], p[1], p[2], p[3],
5200 	 (p[4] ? " ..." : ""));
5201   else
5202     LOG (3, "removing watch %d in irr[%d] %d %d %d %d%s",
5203 	 lit, lidx, p[0], p[1], p[2], p[3], (p[4] ? " ..." : ""));
5204 #endif
5205   hts = lglhts (lgl, lit);
5206   assert (hts->count >= 2);
5207   p = w = lglhts2wchs (lgl, hts);
5208   eow = w + hts->count;
5209   lglrminc (lgl, w, eow);
5210   for (;;) {
5211     assert (p < eow);
5212     blit = *p++;
5213     tag = blit & MASKCS;
5214     if (tag == BINCS) continue;
5215     if (tag == OCCS) { assert (lgl->dense); continue; }
5216     olidx = *p++;
5217     if (tag == TRNCS) continue;
5218     assert (tag == LRGCS);
5219     ored = blit & REDCS;
5220     if (ored != red) continue;
5221     if (olidx == lidx) break;
5222   }
5223   assert ((p[-2] & REDCS) == red);
5224   assert (p[-1] == lidx);
5225   for (q = p; q < eow; q++)
5226     q[-2] = q[0];
5227   lglshrinkhts (lgl, hts, q - w - 2);
5228 }
5229 
lglpropsearch(LGL * lgl,int lit)5230 static void lglpropsearch (LGL * lgl, int lit) {
5231   int * q, * eos, blit, other, other2, other3, red, prev;
5232   int tag, val, val2, lidx, * c, * l;
5233   const int * p;
5234   int visits;
5235   long delta;
5236   HTS * hts;
5237 
5238   LOG (3, "propagating %d in search", lit);
5239 
5240   assert (!lgl->simp);
5241   assert (!lgl->lkhd);
5242   assert (!lgl->probing);
5243   assert (!lgl->dense);
5244   assert (!lgliselim (lgl, lit));
5245   assert (lglval (lgl, lit) == 1);
5246 
5247   hts = lglhts (lgl, -lit);
5248   if (!hts->offset) return;
5249   q = lglhts2wchs (lgl, hts);
5250   assert (hts->count >= 0);
5251   eos = q + hts->count;
5252   visits = 0;
5253   for (p = q; p < eos; p++) {
5254     visits++;
5255     *q++ = blit = *p;
5256     tag = blit & MASKCS;
5257     if (tag != BINCS) {
5258       assert (tag == TRNCS || tag == LRGCS);
5259       *q++ = *++p;
5260     }
5261     other = (blit >> RMSHFT);
5262     assert (abs (other) != abs (lit));
5263     val = lglval (lgl, other);
5264     if (val > 0) continue;
5265     red = blit & REDCS;
5266     if (tag == BINCS) {
5267       if (val < 0) { lglbonflict (lgl, -lit, blit); p++; break; }
5268       lglf2rce (lgl, other, -lit, red);
5269     } else if (tag == TRNCS) {
5270       other2 = *p;
5271       val2 = lglval (lgl, other2);
5272       if (val2 > 0) continue;
5273       if (!val && !val2) continue;
5274       if (val < 0 && val2 < 0) {
5275 	lgltonflict (lgl, -lit, blit, other2);
5276 	p++;
5277 	break;
5278       }
5279       if (!val) SWAP (int, other, other2);
5280       else assert (val < 0);
5281       lglf3rce (lgl, other2, -lit, other, red);
5282     } else {
5283       assert (tag == LRGCS);
5284       assert (val <= 0);
5285       lidx = *p;
5286       c = lglidx2lits (lgl, red, lidx);
5287       other2 = c[0];
5288       if (other2 == -lit) other2 = c[0] = c[1], c[1] = -lit;
5289       else assert (c[1] == -lit);
5290       if (other2 != other) {
5291 	other = other2;
5292 	val = lglval (lgl, other);
5293 	if (val > 0) {
5294 	  q[-2] = LRGCS | RMSHFTLIT (other2) | red;
5295 	  continue;
5296 	}
5297       }
5298       assert (!red || !lgliselim (lgl, other));
5299       val2 = 0;
5300       prev = -lit;
5301       for (l = c + 2; (other2 = *l); l++) {
5302 	*l = prev;
5303 	val2 = lglval (lgl, other2);
5304 	if (val2 >= 0) break;
5305 	assert (!red || !lgliselim (lgl, other2));
5306 	prev = other2;
5307       }
5308       assert (!other2 || val2 >= 0);
5309       if (other2) {
5310 	c[1] = other2;
5311 	assert (other == c[0]);
5312 	delta = lglwchlrg (lgl, other2, other, red, lidx);
5313 	if (delta) p += delta, q += delta, eos += delta;
5314 	q -= 2;
5315 	continue;
5316       }
5317       while (l > c + 2) {
5318 	other3 = *--l;
5319 	*l = prev;
5320 	prev = other3;
5321       }
5322       if (val < 0) {
5323 	lglonflict (lgl, 1, -lit, red, lidx);
5324 	p++;
5325 	break;
5326       }
5327       assert (!val);
5328       lglflrce (lgl, other, red, lidx);
5329     }
5330   }
5331   while (p < eos) *q++ = *p++;
5332   lglshrinkhts (lgl, hts, hts->count - (p - q));
5333   assert (!lgl->simp);
5334 
5335   lgl->stats->visits.search += visits;
5336 }
5337 
lglhbred(LGL * lgl,int subsumed,int red)5338 static int lglhbred (LGL * lgl, int subsumed, int red) {
5339   int res = subsumed ? red : REDCS;
5340   LOG (3, "hyber binary learned clause becomes %s", lglred2str (res));
5341   return res;
5342 }
5343 
5344 static void lgldecocc (LGL *, int);	//TODO move scheduling ...
5345 
lglrmlocc(LGL * lgl,int lit,int red,int lidx)5346 static void lglrmlocc (LGL * lgl, int lit, int red, int lidx) {
5347   int search, blit, tag, * p, * q, * w, * eow;
5348   HTS * hts;
5349 #ifndef NLGLOG
5350   if (red) LOG (3, "removing occurrence %d in red[0][%d]", lit, lidx);
5351   else LOG (3, "removing occurrence %d in irr[%d]", lit, lidx);
5352 #endif
5353   assert (!red || red == REDCS);
5354   hts = lglhts (lgl, lit);
5355   assert (hts->count >= 1);
5356   assert (lidx <= MAXIRRLIDX);
5357   search = (lidx << RMSHFT) | OCCS | red;
5358   assert (search >= 0);
5359   p = w = lglhts2wchs (lgl, hts);
5360   eow = w + hts->count;
5361   lglrminc (lgl, w, eow);
5362   do {
5363     assert (p < eow);
5364     blit = *p++;
5365     tag = blit & MASKCS;
5366     if (tag == TRNCS || tag == LRGCS) p++;
5367   } while (blit != search);
5368   assert (p[-1] == search);
5369   for (q = p ; q < eow; q++)
5370     q[-1] = q[0];
5371   lglshrinkhts (lgl, hts, q - w - 1);
5372 }
5373 
lglflushremovedoccs(LGL * lgl,int lit)5374 static void lglflushremovedoccs (LGL * lgl, int lit) {
5375   HTS * hts = lglhts (lgl, lit);
5376   int * w = lglhts2wchs (lgl, hts);
5377   int * eow = w + hts->count;
5378   int blit, tag, red, lidx;
5379   int * p, * q, * c;
5380   lglrminc (lgl, w, eow);
5381   for (p = q = w; p < eow; p++) {
5382     blit = *p;
5383     tag = blit & MASKCS;
5384     red = blit & REDCS;
5385     if (tag == TRNCS || tag == LRGCS) p++;
5386     if (tag == BINCS) *q++ = blit;
5387     else if (tag == TRNCS) *q++ = blit, *q++ = *p;
5388     else {
5389       assert (tag == LRGCS || tag == OCCS);
5390       if (!red) {
5391 	lidx = (tag == LRGCS) ? *p : (blit >> RMSHFT);
5392 	c = lglidx2lits (lgl, red, lidx);
5393 	if (c[0] == REMOVED) continue;
5394       }
5395       *q++ = blit;
5396       if (tag == LRGCS) *q++ = *p;
5397     }
5398   }
5399   lglshrinkhts (lgl, hts, q - w);
5400 }
5401 
lglpropupdvisits(LGL * lgl,int visits,int64_t steps)5402 static void lglpropupdvisits (LGL * lgl, int visits, int64_t steps) {
5403   if (lgl->lkhd) lgl->stats->visits.lkhd += visits;
5404   else if (lgl->simp) lgl->stats->visits.simp += visits;
5405   else lgl->stats->visits.search += visits;
5406 
5407   if (lgl->simp) {
5408          if (lgl->basicprobing) ADDSTEPS (prb.basic.steps, visits + steps);
5409     else if (lgl->simpleprobing) ADDSTEPS (prb.simple.steps, visits + steps);
5410     else if (lgl->treelooking) ADDSTEPS (prb.treelook.steps, visits + steps);
5411     else if (lgl->sweeping) ADDSTEPS (sweep.steps, visits + steps);
5412   } else {
5413     assert (!lgl->basicprobing);
5414     assert (!lgl->simpleprobing);
5415     assert (!lgl->treelooking);
5416     assert (!lgl->sweeping);
5417   }
5418 }
5419 
lglprop(LGL * lgl,int lit)5420 static void lglprop (LGL * lgl, int lit) {
5421   int * p, * q, * eos, blit, other, other2, other3, red, prev;
5422   int tag, val, val2, lidx, * c, * l, dom, hbred, subsumed;
5423   int glue, flushoccs, visits;
5424   int64_t steps;
5425   long delta;
5426   HTS * hts;
5427   LOG (3, "propagating %d over ternary and large clauses", lit);
5428   assert (!lgliselim (lgl, lit));
5429   assert (lglval (lgl, lit) == 1);
5430   hts = lglhts (lgl, -lit);
5431   if (!hts->offset) return;
5432   flushoccs = 0;
5433   q = lglhts2wchs (lgl, hts);
5434   assert (hts->count >= 0);
5435   eos = q + hts->count;
5436   visits = 0;
5437   steps = 0;
5438   for (p = q; p < eos; p++) {
5439     blit = *p;
5440     tag = blit & MASKCS;
5441     red = blit & REDCS;
5442     if (tag == OCCS) {
5443       assert (lgl->dense);
5444       assert (!red);
5445       *q++ = blit;
5446       continue;
5447     }
5448     visits++;
5449     other = (blit >> RMSHFT);
5450     val = lglval (lgl, other);
5451     if (tag == BINCS) {
5452       *q++ = blit;
5453       if (val > 0) continue;
5454       if (red && lgliselim (lgl, other)) continue;
5455       if (val < 0) {
5456 	lglbonflict (lgl, -lit, blit);
5457 	p++;
5458 	break;
5459       }
5460       assert (!val);
5461       lglf2rce (lgl, other, -lit, red);
5462     } else if (tag == TRNCS) {
5463       *q++ = blit;
5464       other2 = *++p;
5465       *q++ = other2;
5466       if (val > 0) continue;
5467       if (red && lgliselim (lgl, other)) continue;
5468       val2 = lglval (lgl, other2);
5469       if (val2 > 0) continue;
5470       if (!val && !val2) continue;
5471       if (red && lgliselim (lgl, other2)) continue;
5472       if (val < 0 && val2 < 0) {
5473 	lgltonflict (lgl, -lit, blit, other2);
5474 	p++;
5475 	break;
5476       }
5477       if (!val) SWAP (int, other, other2); else assert (val < 0);
5478       if (lgl->level &&
5479 	  lgl->simp &&
5480 	  lgl->opts->lhbr.val) {
5481 	assert (lgl->simp);
5482 	dom = lglgetdom (lgl, lit);
5483 	if (lglgetdom (lgl, -other) != dom) goto NO_HBR_JUST_F3RCE;
5484 	dom = lglhbrdom (lgl, lit, -other, &steps);
5485 	if (!dom) goto NO_HBR_JUST_F3RCE;
5486 	subsumed = (dom == lit || dom == -other);
5487 	hbred = lglhbred (lgl, subsumed, red);
5488 	LOG (2, "hyper binary resolved %s clause %d %d",
5489 	     lglred2str (hbred), -dom, other2);
5490         lgldrupligaddclsarg (lgl, REDCS, -dom, other2, 0);
5491 	if (subsumed) {
5492 	  LOG (2, "subsumes %s ternary clause %d %d %d",
5493 	       lglred2str (red), -lit, other, other2);
5494 	  lglrmtwch (lgl, other2, other, -lit, red);
5495 	  lglrmtwch (lgl, other, other2, -lit, red);
5496 	  lgl->stats->hbr.sub++;
5497 	  if (red) assert (lgl->stats->red.trn), lgl->stats->red.trn--;
5498 	  else {
5499 	    lgldecirr (lgl, 3);
5500 	    if (lgl->dense) {
5501 	      if (-dom == -lit) lgldecocc (lgl, other);
5502 	      else { assert (-dom == other); lgldecocc (lgl, -lit); }
5503 	    }
5504 	  }
5505 	  lgldrupligdelclsarg (lgl, -lit, other, other2, 0);
5506 	}
5507 	delta = 0;
5508 	if (dom == lit) {
5509 	  LOG (3,
5510     "replacing %s ternary watch %d blits %d %d with binary %d blit %d",
5511 	  lglred2str (red), -lit, other, other2, -dom, other2);
5512 	  assert (subsumed);
5513 	  blit = RMSHFTLIT (other2) | BINCS | hbred;
5514 	  q[-2] = blit;
5515 	  q--;
5516 	} else {
5517 	  if (dom == -other) {
5518 	    LOG (3, "removing %s ternary watch %d blits %d %d",
5519 		 lglred2str (red), -lit, other, other2);
5520 	    assert (subsumed);
5521 	    q -= 2;
5522 	  } else {
5523 	    LOG (2, "replaces %s ternary clause %d %d %d as reason for %d",
5524 		 lglred2str (red), -lit, other, other2, other2);
5525 	    assert (!subsumed);
5526 	    assert (abs (dom) != abs (lit));
5527 	    assert (abs (other2) != abs (lit));
5528 	  }
5529 	  delta += lglwchbin (lgl, -dom, other2, hbred);
5530 	}
5531 	delta += lglwchbin (lgl, other2, -dom, hbred);
5532 	if (delta) p += delta, q += delta, eos += delta;
5533 	if (hbred) lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
5534 	else lglincirr (lgl, 2);
5535 	lglf2rce (lgl, other2, -dom, hbred);
5536 	lgl->stats->hbr.trn++;
5537 	lgl->stats->hbr.cnt++;
5538 	lgl->stats->prgss++;
5539       } else {
5540 NO_HBR_JUST_F3RCE:
5541        lglf3rce (lgl, other2, -lit, other, red);
5542       }
5543     } else {
5544       assert (tag == LRGCS);
5545       if (val > 0) goto COPYL;
5546       lidx = p[1];
5547       c = lglidx2lits (lgl, red, lidx);
5548       other2 = c[0];
5549       if (other2 >= NOTALIT) {
5550 	p++;
5551 	continue;
5552       }
5553       if (other2 == -lit) other2 = c[0] = c[1], c[1] = -lit;
5554       if (other2 != other) {
5555 	other = other2;
5556 	val = lglval (lgl, other);
5557 	blit = red;
5558 	blit |= LRGCS;
5559 	blit |= RMSHFTLIT (other2);
5560 	if (val > 0) goto COPYL;
5561       }
5562       if (red && lgliselim (lgl, other)) goto COPYL;
5563       val2 = INT_MAX;
5564       prev = -lit;
5565       for (l = c + 2; (other2 = *l); l++) {
5566 	*l = prev;
5567 	val2 = lglval (lgl, other2);
5568 	if (val2 >= 0) break;
5569 	if (red && lgliselim (lgl, other2)) break;
5570 	prev = other2;
5571       }
5572       assert (val2 != INT_MAX);
5573       if (other2 && val2 >= 0) {
5574 	c[1] = other2;
5575 	assert (other == c[0]);
5576 	delta = lglwchlrg (lgl, other2, other, red, lidx);
5577 	if (delta) p += delta, q += delta, eos += delta;
5578 	p++;
5579 	continue;
5580       }
5581 
5582       while (l > c + 2) {
5583 	other3 = *--l;
5584 	*l = prev;
5585 	prev = other3;
5586       }
5587 
5588       if (other2 && val2 < 0) goto COPYL;
5589 
5590       if (val < 0) {
5591 	lglonflict (lgl, 1, -lit, red, lidx);
5592 	break;
5593       }
5594 
5595       assert (!val);
5596       if (lgl->level &&
5597 	  lgl->simp &&
5598 	  lgl->opts->lhbr.val) {
5599 	assert (lgl->simp);
5600 	dom = 0;
5601 	for (l = c; (other2 = *l); l++) {
5602 	  if (other2 == other) continue;
5603 	  if (!lglevel (lgl, other2)) continue;
5604 	  assert (lglval (lgl, other2) < 0);
5605 	  if (!dom) dom = lglgetdom (lgl, -other);
5606 	  if (dom != lglgetdom (lgl, -other2)) goto NO_HBR_JUST_FLRCE;
5607 	}
5608 	LOGCLS (2, c, "dominator %d for %s clause", dom, lglred2str (red));
5609 	dom = 0;
5610 	for (l = c; (other2 = *l); l++) {
5611 	  if (other2 == other) continue;
5612 	  if (!lglevel (lgl, other2)) continue;
5613 	  dom = lglhbrdom (lgl, dom, -other2, &steps);
5614 	}
5615 	if (!dom) goto NO_HBR_JUST_FLRCE;
5616 	LOGCLS (2, c, "closest dominator %d", dom);
5617 	subsumed = 0;
5618 	for (l = c; !subsumed && (other2 = *l); l++)
5619 	  subsumed = (dom == -other2);
5620 	assert (lit != dom || subsumed);
5621 	hbred = lglhbred (lgl, subsumed, red);
5622 	LOG (2, "hyper binary resolved %s clause %d %d",
5623 	     lglred2str (hbred), -dom, other);
5624         lgldrupligaddclsarg (lgl, REDCS, -dom, other, 0);
5625 	if (subsumed) {
5626 	  LOGCLS (2, c, "subsumes %s large clause", lglred2str (red));
5627 	  lglrmlwch (lgl, other, red, lidx);
5628 	  lgl->stats->hbr.sub++;
5629 	  if (red) {
5630 	    glue = lidx & GLUEMASK;
5631 	    if (glue != MAXGLUE) {
5632 	      assert (lgl->stats->red.lrg);
5633 	      lgl->stats->red.lrg--;
5634 	      assert (lgl->stats->lir[glue].clauses > 0);
5635 	      lgl->stats->lir[glue].clauses--;
5636 	    }
5637 	  }
5638 	  if (!red && lgl->dense) {
5639 	    for (l = c; (other2 = *l); l++) {
5640 	      if (other2 != -lit) lglrmlocc (lgl, other2, 0, lidx);
5641 	      if (other2 == -dom) continue;
5642 	      if (other2 == other) continue;
5643 	      lgldecocc (lgl, other2);
5644 	    }
5645 	    flushoccs++;
5646 	  }
5647 	  if (red && glue < MAXGLUE) { LGLCHKACT (c[-1]); c[-1] = REMOVED; }
5648 	  lgldrupligdelclsaux (lgl, c);
5649 	  for (l = c; *l; l++) *l = REMOVED;
5650 	  if (!red) lgldecirr (lgl, l - c);
5651 	  *l = REMOVED;
5652 	}
5653 	delta = 0;
5654 	if (dom == lit) {
5655 	  assert (subsumed);
5656 	  LOG (3,
5657 	       "replacing %s large watch %d with binary watch %d blit %d",
5658 	       lglred2str (red), -lit, -lit, -dom);
5659 	  blit = RMSHFTLIT (other) | BINCS | hbred;
5660 	  *q++ = blit, p++;
5661 	} else {
5662 	  if (subsumed) {
5663 	    LOG (3, "removing %s large watch %d", lglred2str (red), -lit);
5664 	    p++;
5665 	  } else {
5666 	    LOGCLS (2, c,
5667 		    "%s binary clause %d %d becomes reasons "
5668 		    "for %d instead of %s large clause",
5669 		    lglred2str (hbred), -dom, other, other, lglred2str (red));
5670 	    assert (hbred == REDCS);
5671 	  }
5672 	  delta += lglwchbin (lgl, -dom, other, hbred);
5673 	}
5674 	delta += lglwchbin (lgl, other, -dom, hbred);
5675 	if (delta) p += delta, q += delta, eos += delta;
5676 	if (hbred) lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
5677 	else lglincirr (lgl, 2);
5678 	lglf2rce (lgl, other, -dom, hbred);
5679 	lgl->stats->hbr.lrg++;
5680 	lgl->stats->hbr.cnt++;
5681 	lgl->stats->prgss++;
5682 	if (subsumed) continue;
5683       } else {
5684 NO_HBR_JUST_FLRCE:
5685 	lglflrce (lgl, other, red, lidx);
5686       }
5687 COPYL:
5688       *q++ = blit;
5689       *q++ = *++p;
5690     }
5691   }
5692   while (p < eos) *q++ = *p++;
5693   lglshrinkhts (lgl, hts, hts->count - (p - q));
5694   if (flushoccs) lglflushremovedoccs (lgl, -lit);
5695   lglpropupdvisits (lgl, visits, steps);
5696 }
5697 
lglprop2(LGL * lgl,int lit)5698 static void lglprop2 (LGL * lgl, int lit) {
5699   int other, blit, tag, val, red, visits;
5700   const int * p, * w, * eow;
5701   int64_t travs;
5702   HTS * hts;
5703   LOG (3, "propagating %d over binary clauses", lit);
5704   assert (!lgliselim (lgl, lit));
5705   assert (lglval (lgl, lit) == 1);
5706   visits = 0;
5707   travs = 0;
5708   hts = lglhts (lgl, -lit);
5709   w = lglhts2wchs (lgl, hts);
5710   eow = w + hts->count;
5711   for (p = w; p < eow; p++) {
5712     blit = *p;
5713     tag = blit & MASKCS;
5714     if (tag == TRNCS || tag == LRGCS) p++;
5715     if (tag != BINCS) continue;
5716     visits++;
5717     red = blit & REDCS;
5718     other = blit >> RMSHFT;
5719     travs++;
5720     if (lgliselim (lgl, other)) { assert (red); continue; }
5721     val = lglval (lgl, other);
5722     if (val > 0) continue;
5723     if (val < 0) { lglbonflict (lgl, -lit, blit); break; }
5724     lglf2rce (lgl, other, -lit, red);
5725   }
5726 
5727   lglpropupdvisits (lgl, visits, travs);
5728 }
5729 
lglhasconflict(LGL * lgl)5730 static int lglhasconflict (LGL * lgl) {
5731   return lgl->conf.lit != 0;
5732 }
5733 
lglbcpcomplete(LGL * lgl)5734 static int lglbcpcomplete (LGL * lgl) {
5735   assert (lgl->next2 <= lgl->next);
5736   assert (lgl->next <= lglcntstk (&lgl->trail));
5737   if (lgl->next2 < lgl->next) return 0;
5738   if (lgl->next < lglcntstk (&lgl->trail)) return 0;
5739   return 1;
5740 }
5741 
lglchkbcpclean(LGL * lgl,const char * where)5742 static void lglchkbcpclean (LGL * lgl, const char * where) {
5743   ASSERT (lglbcpcomplete (lgl));
5744   ASSERT (!lgl->conf.lit);
5745   ASSERT (!lgl->mt);
5746 }
5747 
lglbcp(LGL * lgl)5748 static int lglbcp (LGL * lgl) {
5749   int lit, trail, count;
5750   assert (!lgl->mt);
5751   assert (!lgl->conf.lit);
5752   assert (!lgl->notfullyconnected);
5753   count = 0;
5754   while (!lgl->conf.lit) {
5755     trail = lglcntstk (&lgl->trail);
5756     if (lgl->next2 < trail) {
5757       lit = lglpeek (&lgl->trail, lgl->next2++);
5758       lglprop2 (lgl, lit);
5759       continue;			// TODO try to optionally uncomment
5760     }
5761     if (lgl->next >= trail) break;
5762     count++;
5763     lit = lglpeek (&lgl->trail, lgl->next++);
5764     lglprop (lgl, lit);
5765   }
5766   if (lgl->lkhd) ADDSTEPS (props.lkhd, count);
5767   else if (lgl->simp) ADDSTEPS (props.simp, count);
5768   else ADDSTEPS (props.search, count);
5769   assert (lglhasconflict (lgl) || lglbcpcomplete (lgl));
5770   return !lglhasconflict (lgl);
5771 }
5772 
lglbcpsearch(LGL * lgl)5773 static int lglbcpsearch (LGL * lgl) {
5774   int lit, count = 0;
5775   assert (!lgl->simp);
5776   assert (!lgl->notfullyconnected);
5777   while ((!lgl->failed || !lgl->level) &&
5778 	 !lgl->conf.lit &&
5779 	 lgl->next < lglcntstk (&lgl->trail)) {
5780     lit = lglpeek (&lgl->trail, lgl->next++);
5781     lglpropsearch (lgl, lit);
5782     count++;
5783   }
5784   ADDSTEPS (props.search, count);
5785   lgl->next2 = lgl->next;
5786   if (lgl->conf.lit && lgl->failed) {
5787     LOG (2, "inconsistency overwrites failed assumption %d", lgl->failed);
5788     lgl->failed = 0;
5789   }
5790   assert (lglhasconflict (lgl) || lgl->failed || lglbcpcomplete (lgl));
5791   return !lgl->conf.lit && !lgl->failed;
5792 }
5793 
5794 #ifndef NDEBUG
lglchkclnvar(LGL * lgl)5795 static void lglchkclnvar (LGL * lgl) {
5796   AVar * av;
5797   int i;
5798   for (i = 2; i < lgl->nvars; i++) {
5799     av = lglavar (lgl, i);
5800     assert (!av->mark);
5801   }
5802 }
5803 #endif
5804 
5805 #ifdef RESOLVENT
lglmaintainresolvent(LGL * lgl)5806 static int lglmaintainresolvent (LGL * lgl) {
5807 #ifndef NDEBUG
5808   if (lgl->opts->check.val >= 1) return 1;
5809 #endif
5810 #ifndef NLGLOG
5811   if (lgl->opts->log.val >= 2) return 1;
5812 #endif
5813   return 0;
5814 }
5815 #endif
5816 
lgldecision(LGL * lgl,int lit)5817 static int lgldecision (LGL * lgl, int lit) {
5818   int * rsn = lglrsn (lgl, lit);
5819   int tag = rsn[0] & MASKCS;
5820   return tag == DECISION;
5821 }
5822 
lglassumption(LGL * lgl,int lit)5823 static int lglassumption (LGL * lgl, int lit) {
5824   return lglavar (lgl, lit)->assumed;
5825 }
5826 
lglpull(LGL * lgl,int lit)5827 static int lglpull (LGL * lgl, int lit) {
5828   AVar * av = lglavar (lgl, lit);
5829   int level, res;
5830   level = lglevel (lgl, lit);
5831   if (!level) return 0;
5832   if (av->mark) return 0;
5833   av->mark = 1;
5834   lglpushstk (lgl, &lgl->seen, lit);
5835 #ifdef RESOLVENT
5836   if (lglmaintainresolvent (lgl)) {
5837     lglpushstk (lgl, &lgl->resolvent, lit);
5838     LOG (2, "adding %d to resolvent", lit);
5839     LOGRESOLVENT (3, "resolvent after adding %d is", lit);
5840   }
5841 #endif
5842   if (level == lgl->level) {
5843     LOG (2, "reason literal %d at same level %d", lit, lgl->level);
5844     res = 1;
5845   } else {
5846     lglpushstk (lgl, &lgl->clause, lit);
5847     LOG (2, "adding literal %d at upper level %d to 1st UIP clause",
5848 	 lit, lglevel (lgl, lit));
5849     lgluselevel (lgl, level);
5850     res = 0;
5851   }
5852   return res;
5853 }
5854 
lglusedtwice(LGL * lgl,int lit)5855 static int lglusedtwice (LGL * lgl, int lit) {
5856   int level;
5857   if (!lgl->opts->usedtwice.val) return 1;
5858   level = lglevel (lgl, lit);
5859   lgl->stats->mincls.usedtwice.search++;
5860   if (lglevelused (lgl, level) >= 2) return 1;
5861   lgl->stats->mincls.usedtwice.hits++;
5862   return 0;
5863 }
5864 
lglpoison(LGL * lgl,int lit,Stk * stk,int local)5865 static int lglpoison (LGL * lgl, int lit, Stk * stk, int local) {
5866   AVar * av = lglavar (lgl, lit);
5867   int level, res;
5868   if (av->mark) res = 0;
5869   else {
5870     level = lglevel (lgl, lit);
5871     if (!level) res = 0;
5872     else {
5873       assert (level < lgl->level);
5874       if (lgldecision (lgl, lit)) res = 1;
5875       else if (lglevelused (lgl, level) < 2) res = 1;
5876       else {
5877 	if (lgl->opts->poison.val) lgl->stats->mincls.poison.search++;
5878 	if (av->poisoned) {
5879 	  assert (lgl->opts->poison.val);
5880 	  lgl->stats->mincls.poison.hits++;
5881 	  res = 1;
5882 	} else if (local) res = 1;
5883 	else if (lglusedtwice (lgl, lit)) {
5884 	  av->mark = 1;
5885 	  lglpushstk (lgl, &lgl->seen, lit);
5886 	  lglpushstk (lgl, stk, lit);
5887 	  res = 0;
5888 	} else res = 1;
5889       }
5890     }
5891   }
5892   if (res && lgl->opts->poison.val && !av->poisoned) {
5893     av->poisoned = 1;
5894     lglpushstk (lgl, &lgl->poisoned, lit);
5895   }
5896   return res;
5897 }
5898 
lglminclslit(LGL * lgl,int start,int local)5899 static int lglminclslit (LGL * lgl, int start, int local) {
5900   int lit, tag, r0, r1, other, * p, * q, *top, old, level;
5901   int poisoned, * rsn, found;
5902   AVar * av, * bv;
5903   assert (lglmarked (lgl, start));
5904   lit = start;
5905   level = lglevel (lgl, lit);
5906   assert (level > 0);
5907   if (level == lgl->level) return 0;
5908   if (!lglusedtwice (lgl, lit)) return 0;
5909   rsn = lglrsn (lgl, lit);
5910   r0 = rsn[0];
5911   tag = (r0 & MASKCS);
5912   if (tag == DECISION) return 0;
5913   old = lglcntstk (&lgl->seen);
5914   assert (lglmtstk (&lgl->minstk));
5915   for (;;) {
5916     r1 = rsn[1];
5917     if (tag == BINCS || tag == TRNCS) {
5918       other = r0 >> RMSHFT;
5919       if (lglpoison (lgl, other, &lgl->minstk, local)) goto FAILED;
5920       if (tag == TRNCS && lglpoison (lgl, r1, &lgl->minstk, local))
5921 	goto FAILED;
5922     } else {
5923       assert (tag == LRGCS);
5924       p = lglidx2lits (lgl, (r0 & REDCS), r1);
5925       found = 0;
5926       while ((other = *p++)) {
5927 	if (other == -lit) found++;
5928 	else if (lglpoison (lgl, other, &lgl->minstk, local)) goto FAILED;
5929       }
5930       assert (found == 1);
5931     }
5932     if (lglmtstk (&lgl->minstk)) { lglrelstk (lgl, &lgl->minstk); return 1; }
5933     lit = lglpopstk (&lgl->minstk);
5934     assert (lglavar (lgl, lit)->mark);
5935     rsn = lglrsn (lgl, lit);
5936     r0 = rsn[0];
5937     tag = (r0 & MASKCS);
5938   }
5939 FAILED:
5940   lglclnstk (&lgl->minstk);
5941   p = lgl->seen.top;
5942   top = lgl->seen.top = lgl->seen.start + old;
5943   while (p > top) {
5944     lit = *--p;
5945     av = lglavar (lgl, lit);
5946     assert (av->mark);
5947     av->mark = 0;
5948     if (!lgl->opts->poison.val) continue;
5949     poisoned = av->poisoned;
5950     if (poisoned) continue;
5951     rsn = lglrsn (lgl, lit);
5952     r0 = rsn[0];
5953     tag = (r0 & MASKCS);
5954     assert (tag != DECISION);
5955     r1 = rsn[1];
5956     if (tag == BINCS || tag == TRNCS) {
5957       other = r0 >> RMSHFT;
5958       bv = lglavar (lgl, other);
5959       if (bv->poisoned) poisoned = 1;
5960       else if (tag == TRNCS) {
5961 	bv = lglavar (lgl, r1);
5962 	if (bv->poisoned) poisoned = 1;
5963       }
5964     } else {
5965       assert (tag == LRGCS);
5966       q = lglidx2lits (lgl, (r0 & REDCS), r1);
5967       while (!poisoned && (other = *q++))
5968 	poisoned = lglavar (lgl, other)->poisoned;
5969     }
5970     if (!poisoned) continue;
5971     assert (!av->poisoned);
5972     av->poisoned = 1;
5973     lglpushstk (lgl, &lgl->poisoned, lit);
5974   }
5975   return 0;
5976 }
5977 
lglmaxmb(LGL * lgl)5978 double lglmaxmb (LGL * lgl) {
5979   REQINIT ();
5980   return (lgl->stats->bytes.max + sizeof *lgl) / (double)(1<<20);
5981 }
5982 
lglbytes(LGL * lgl)5983 size_t lglbytes (LGL * lgl) {
5984   REQINIT ();
5985   return lgl->stats->bytes.current;
5986 }
5987 
lglmb(LGL * lgl)5988 double lglmb (LGL * lgl) {
5989   REQINIT ();
5990   return (lgl->stats->bytes.current + sizeof *lgl) / (double)(1<<20);
5991 }
5992 
lglavg(double n,double d)5993 static double lglavg (double n, double d) {
5994   return d != 0 ? n / d : 0.0;
5995 }
5996 
lglheight(LGL * lgl)5997 static double lglheight (LGL * lgl) {
5998   return lgl->stats->jlevel.slow.val / (double)(1ull<<32);
5999 }
6000 
lgltlevel(LGL * lgl)6001 static double lgltlevel (LGL * lgl) {
6002   return lgl->stats->tlevel.val / (double)(1ull<<32);
6003 }
6004 
lglglue(LGL * lgl)6005 static double lglglue (LGL * lgl) {
6006   return lgl->stats->glue.slow.val / (double)(1ull<<32);
6007 }
6008 
lglrephead(LGL * lgl)6009 static void lglrephead (LGL * lgl) {
6010   if (lgl->tid > 0) return;
6011   lgl->repforcehead = 0;
6012   lgl->repcntdown = REPMOD;
6013   if (lgl->tid > 0) return;
6014   if (lgl->cbs && lgl->cbs->msglock.lock)
6015     lgl->cbs->msglock.lock (lgl->cbs->msglock.state);
6016   assert (lgl->prefix);
6017   fprintf (lgl->out, "%s\n", lgl->prefix);
6018   fprintf (lgl->out, "%s%s"
6019 " seconds         irredundant            redundant clauses   glue"
6020 "   iterations\"      MB    stability\n",
6021     lgl->prefix, !lgl->tid ? "  " : "");
6022   fprintf (lgl->out, "%s%s"
6023 "         variables clauses conflicts  large ternary binary "
6024 "    jlevel       jlevel'  agility     tlevel\n",
6025     lgl->prefix, !lgl->tid ? "  " : "");
6026   fprintf (lgl->out, "%s\n", lgl->prefix);
6027   fflush (lgl->out);
6028   if (lgl->cbs && lgl->cbs->msglock.unlock)
6029     lgl->cbs->msglock.unlock (lgl->cbs->msglock.state);
6030 }
6031 
6032 #ifndef NLGLOG
lglitavg(LGL * lgl)6033 static double lglitavg (LGL * lgl) {
6034   return lgl->stats->its.avg.slow.val / (double)(1ull<<32);
6035 }
6036 #endif
6037 
lglitder(LGL * lgl)6038 static double lglitder (LGL * lgl) {
6039   return 10000.0 * lglavg (lgl->stats->its.avg.diff.smoothed.val / (double)(1ull<<32), lgl->stats->confs);
6040 }
6041 
lgljlevelder(LGL * lgl)6042 static double lgljlevelder (LGL * lgl) {
6043   return lgl->stats->jlevel.diff.smoothed.val / (double)(1ll<<32);
6044 }
6045 
lglrep(LGL * lgl,int level,char type)6046 static void lglrep (LGL * lgl, int level, char type) {
6047   if (lgl->opts->verbose.val < level) return;
6048   if ((level > 0 && lgl->repforcehead) || !lgl->repcntdown--)
6049     lglrephead (lgl);
6050   lglprt (lgl, level,
6051     " %c"	// type
6052     " %6.1f"	// time
6053     " %7d"	// rem
6054     " %8d"	// irr
6055     " %9lld"	// confs
6056     " %7d"	// lrg
6057     " %6d"	// trn
6058     " %5d"	// bin
6059     " %4.0f"	// glue
6060     " %5.0f"	// height
6061     " %6.0f"	// it"
6062     " %5.0f"	// jl'
6063     " %4.0f"	// mb
6064     " %3.0f"	// agility
6065     " %5.0f"	// stability
6066     " %6.0f"	// trail
6067     ,
6068     type,
6069     lgl->opts->abstime.val ? lglgetime (lgl) : lglsec (lgl),
6070     lglrem (lgl),
6071     lgl->stats->irr.clauses.cur,
6072     (LGLL) lgl->stats->confs,
6073     lgl->stats->red.lrg,
6074     lgl->stats->red.trn,
6075     lgl->stats->red.bin,
6076     lglglue (lgl),
6077     lglheight (lgl),
6078     lglitder (lgl),
6079     lgljlevelder (lgl),
6080     lglmb (lgl),
6081     100.0*(lgl->stats->agility/(double)(1ll<<32)),
6082     1000.0*(lgl->stats->stability.avg.val/(double)(1ll<<32)),
6083     lgltlevel (lgl)
6084     );
6085   lgl->stats->reported++;
6086 }
6087 
lglflshrep(LGL * lgl)6088 static void lglflshrep (LGL * lgl) {
6089   if (!lgl->stats->reported) return;
6090   if (lgl->stats->reported % REPMOD) lglrephead (lgl);
6091   else lglprt (lgl, 1, "");
6092 }
6093 
lglfitlir(LGL * lgl,Stk * lir)6094 static void lglfitlir (LGL * lgl, Stk * lir) {
6095   lglfitstk (lgl, lir);
6096 }
6097 
lglchkred(LGL * lgl)6098 static void lglchkred (LGL * lgl) {
6099 #ifndef NDEBUG
6100   int glue, idx, sign, lit, thisum, sum, sum2, sum3;
6101   int blit, tag, red, other, other2;
6102   int * p, * c, * w, * eow;
6103   HTS * hts;
6104   Stk * lir;
6105   if (lgl->mt) return;
6106   sum = 0;
6107   for (glue = 0; glue < MAXGLUE; glue++) {
6108     lir = lgl->red + glue;
6109     thisum = 0;
6110     for (c = lir->start; c < lir->top; c = p + 1) {
6111       p = c;
6112       if (*p >= NOTALIT) continue;
6113       while (*p) p++;
6114       assert (p - c >= 4);
6115       thisum++;
6116     }
6117     assert (thisum == lgl->stats->lir[glue].clauses);
6118     sum += thisum;
6119   }
6120   assert (sum == lgl->stats->red.lrg);
6121   sum2 = sum3 = 0;
6122   for (idx = 2; idx < lgl->nvars; idx++)
6123     for (sign = -1; sign <= 1; sign += 2) {
6124       lit = sign * idx;
6125       hts = lglhts (lgl, lit);
6126       w = lglhts2wchs (lgl, hts);
6127       eow = w + hts->count;
6128       for (p = w; p < eow; p++) {
6129 	blit = *p;
6130 	tag = blit & MASKCS;
6131 	red = blit & REDCS;
6132 	if (tag == TRNCS || tag == LRGCS) p++;
6133 	if (!red || tag == LRGCS || tag == OCCS) continue;
6134 	other = blit >> RMSHFT;
6135 	if (abs (other) < idx) continue;
6136 	if (tag == BINCS) sum2++;
6137 	else {
6138 	  assert (tag == TRNCS);
6139 	  other2 = *p;
6140 	  if (abs (other2) < idx) continue;
6141 	  sum3++;
6142 	}
6143       }
6144     }
6145   assert (sum2 == lgl->stats->red.bin);
6146   assert (sum3 == lgl->stats->red.trn);
6147 #endif
6148 }
6149 
lglinitredl(LGL * lgl)6150 static void lglinitredl (LGL * lgl) {
6151   lgl->limits->reduce.redlarge = lgl->opts->reduceinit.val;
6152   lglprt (lgl, 2,
6153     "[set-reduce-limit] initial reduce limit of %lld after %lld conflicts",
6154     (LGLL) lgl->limits->reduce.redlarge, (LGLL) lgl->stats->confs);
6155 }
6156 
lglmemout(LGL * lgl)6157 static int lglmemout (LGL * lgl) {
6158   size_t cur;
6159   int res;
6160   if (lgl->opts->memlim.val < 0) return 0;
6161   cur = lgl->stats->bytes.current;
6162   cur >>= 20;
6163   res = (cur >= lgl->opts->memlim.val);
6164   if (res)
6165     lglprt (lgl, 2, "memory limit of %d MB hit after allocating %lld MB",
6166       lgl->opts->memlim.val, (LGLL) cur);
6167   return res;
6168 }
6169 
lgliphase(LGL * lgl,int lit)6170 static Val lgliphase (LGL * lgl, int lit) {
6171   Val res = lglavar (lgl, lit)->phase;
6172   if (lit < 0) res = -res;
6173   return res;
6174 }
6175 
lglretire(LGL * lgl)6176 static void lglretire (LGL * lgl) {
6177   int count, ready, inactive, glue, * p, * c, act;
6178   const int retireint = lgl->opts->retireint.val;
6179   Stk * s;
6180   assert (lgl->opts->retirenb.val);
6181   count = ready = inactive = 0;
6182   for (glue = 0; glue < MAXGLUE; glue++) {
6183     s = lgl->red + glue;
6184     for (c = s->start; c < s->top; c = p + 1) {
6185       act = *(p = c);
6186       if (act <= NOTALIT + retireint) {
6187 	count++;
6188 	inactive++;
6189 	assert (lglisact (act));
6190 	if (act <= NOTALIT + 1) { act = NOTALIT; ready++; } else act--;
6191 	assert (lglisact (act));
6192 	*p++ = act;
6193       }
6194       else if (act < REMOVED) {
6195 	count++;
6196 	act = NOTALIT + retireint + (act - NOTALIT - retireint)/2;
6197 	assert (lglisact (act));
6198 	*p++ = act;
6199       }
6200       while (*p) p++;
6201     }
6202   }
6203   lglprt (lgl, 2,
6204     "[reduce-%d] %d ready to retire %.0f%%, %d inactive %.0f%%",
6205     lgl->stats->reduced.count,
6206     ready, lglpcnt (ready, count),
6207     inactive, lglpcnt (inactive, count));
6208 }
6209 
lglcmpagsl(LGL * lgl,PAGSL * a,PAGSL * b)6210 static int lglcmpagsl (LGL * lgl, PAGSL * a, PAGSL * b) {
6211   int res;
6212   if ((res = b->psm - a->psm)) return res;
6213   if ((res = b->glue - a->glue)) return res;
6214   if ((res = a->act - b->act)) return res;
6215   if ((res = b->size - a->size)) return res;
6216   if ((res = a->lidx - b->lidx)) return res;
6217   return 0;
6218 }
6219 
6220 #define LGLCMPAGSL(A,B) lglcmpagsl (lgl, (A), (B))
6221 
lglreduce(LGL * lgl,int forced)6222 static void lglreduce (LGL * lgl, int forced) {
6223   int * p, * q, * start, * c, ** maps, * sizes, * map, * eow, * rsn;
6224   int nlocked, collected, sumcollected, nunlocked, moved, act, psm;
6225   int glue, target, nkeep, retired, sumretired;
6226   PAGSL * pagsls, * pagsl; int npagsls, szpagsls;
6227   const int retirenb = lgl->opts->retirenb.val;
6228   const int retiremin = lgl->opts->retiremin.val;
6229   int size, idx, tag, red, i, blit;
6230   int r0, lidx, src, dst, lit;
6231   int inc, delta, npromoted;
6232   char type = '-';
6233   HTS * hts;
6234   DVar * dv;
6235   Stk * lir;
6236   lglchkred (lgl);
6237   lglstart (lgl, &lgl->times->reduce);
6238   lgl->stats->reduced.count++;
6239   if (retirenb) lglretire (lgl);
6240   LOG (1, "starting reduction %d", lgl->stats->reduced.count);
6241   delta = lgl->stats->red.lrg;
6242   delta -= lgl->lrgluereasons;
6243   delta -= lgl->stats->lir[0].clauses;
6244   assert (delta >= 0);
6245   if (delta > 3*lgl->limits->reduce.redlarge/2)
6246     target = delta - lgl->limits->reduce.redlarge/2;
6247   else target = delta/2;
6248   if (target < 0) target = 0;
6249   lglprt (lgl, 2,
6250     "[reduce-%d] target is to collect %d clauses %.0f%%",
6251     lgl->stats->reduced.count, target,
6252     lglpcnt (target, lgl->stats->red.lrg));
6253   NEW (maps, MAXGLUE);
6254   NEW (sizes, MAXGLUE);
6255   for (glue = 0; glue < MAXGLUE; glue++) {
6256     lir = lgl->red + glue;
6257     size = lglcntstk (lir);
6258     assert (!size || size >= 6);
6259     size = (size + 5)/6;
6260     sizes[glue] = size;
6261     lglfitstk (lgl, lir);
6262     NEW (maps[glue], size);
6263     map = maps[glue];
6264     for (i = 0; i < size; i++) map[i] = -2;
6265   }
6266   nlocked = 0;
6267   for (i = 0; i < lglcntstk (&lgl->trail); i++) {
6268     lit = lglpeek (&lgl->trail, i);
6269     idx = abs (lit);
6270     rsn = lglrsn (lgl, idx);
6271     r0 = rsn[0];
6272     red = r0 & REDCS;
6273     if (!red) continue;
6274     tag = r0 & MASKCS;
6275     if (tag != LRGCS) continue;
6276     lidx = rsn[1];
6277     glue = lidx & GLUEMASK;
6278     if (glue == MAXGLUE) continue;
6279     lidx >>= GLUESHFT;
6280 #ifndef NLGLOG
6281     lir = lgl->red + glue;
6282     assert (lglpeek (lir, lidx) < REMOVED);
6283     LOGCLS (5, lir->start + lidx,
6284       "locking reason of literal %d glue %d clause",
6285       lit, glue);
6286 #endif
6287     lidx /= 6;
6288     assert (maps);
6289     assert (maps[glue]);
6290     assert (lidx < sizes[glue]);
6291     assert (maps[glue][lidx] == -2);
6292     maps[glue][lidx] = -1;
6293     nlocked++;
6294   }
6295   lglprt (lgl, 2,
6296     "[reduce-%d] locked %d learned reason clauses %.0f%%",
6297      lgl->stats->reduced.count,
6298      nlocked, lglpcnt (nlocked, lgl->stats->red.lrg));
6299   npromoted = 0;
6300   while (!lglmtstk (&lgl->promote)) {
6301     lidx = lglpopstk (&lgl->promote);
6302     glue = lidx & GLUEMASK;
6303     assert (glue < MAXGLUE);
6304     if (!maps[glue]) { assert (!sizes[glue]); continue; }
6305     assert (0 < glue), assert (glue < MAXGLUE);
6306     lidx >>= GLUESHFT;
6307     assert (lidx > 0);
6308     lir = lgl->red + glue;
6309     p = lir->start + lidx;
6310     if (p >= lir->top) continue;
6311     if (*p >= NOTALIT) continue;
6312     if (!lglisact (p[-1])) continue;
6313     if (maps[glue][lidx/6] == -1) continue;
6314 #ifndef NLGLOG
6315     LOGCLS (5, lir->start + lidx,
6316       "locking promoted glue %d clause",
6317       glue);
6318 #endif
6319     assert (lidx/6 < sizes[glue]);
6320     maps[glue][lidx/6] = -1;
6321     lgl->stats->promote.locked++;
6322     npromoted++;
6323   }
6324   lglprt (lgl, 2,
6325     "[reduce-%d] locked %d promoted learned clauses %.0f%%",
6326     lgl->stats->reduced.count,
6327     npromoted, lglpcnt (npromoted, lgl->stats->red.lrg));
6328 
6329   szpagsls = lgl->stats->red.lrg;
6330   NEW (pagsls, szpagsls);
6331   retired = npagsls = 0;
6332   for (glue = 0; glue < MAXGLUE; glue++) {
6333     lir = lgl->red + glue;
6334     start = lir->start;
6335     for (c = start; c < lir->top; c = p + 1) {
6336       if ((act = *c++) == REMOVED) {
6337 	for (p = c; p < lir->top && *p == REMOVED; p++)
6338 	  ;
6339 	p--;
6340 	continue;
6341       }
6342       LGLCHKACT (act);
6343       lidx = c - start;
6344       act -= NOTALIT;
6345       psm = 0;
6346       for (p = c; (lit = *p); p++)
6347 	if (lgliphase (lgl, lit) >= 0) psm++;
6348       size = p - c;
6349       LOG (5,
6350          "clause red[%d][%d] has: psm %d, act %d, size %d",
6351 	 glue, lidx, psm, act, size);
6352 
6353       if (maps[glue][lidx/6] == -1) continue;
6354       assert (maps[glue][lidx/6] == -2);
6355 
6356       if (retirenb && !act && glue >= retiremin) {
6357 	retired++;
6358 	maps[glue][lidx/6] = -3;
6359 	LOG (5, "retiring this inactive clause");
6360 	continue;
6361       }
6362 
6363       if (!glue && size <= lgl->opts->gluekeepsize.val) {
6364         LOG (5, "keeping this glue 0 size %d clause", size);
6365         maps[glue][lidx/6] = -1;
6366         continue;
6367       }
6368 
6369       assert (npagsls < szpagsls);
6370       pagsl = pagsls + npagsls++;
6371       pagsl->psm = psm;
6372       pagsl->act = act;
6373       pagsl->glue = glue;
6374       pagsl->size = size;
6375       pagsl->lidx = lidx;
6376     }
6377   }
6378   assert (npagsls <= szpagsls);
6379   LOG (2,
6380     "retiring %d learned clauses %.0f%%",
6381     retired, lglpcnt (retired, lgl->stats->red.lrg));
6382 
6383   SORT (PAGSL, pagsls, npagsls, LGLCMPAGSL);
6384   LOG (1, "copied and sorted %d activities", npagsls);
6385 
6386   nkeep = 0;
6387   for (idx = target; idx < npagsls; idx++) {
6388     pagsl = pagsls + idx;
6389     lidx = pagsl->lidx;
6390     glue = pagsl->glue;
6391     assert (lidx/6 < sizes[glue]);
6392     maps[glue][lidx/6] = -1;
6393     nkeep++;
6394     LOG (5,
6395       "marked clause red[%d][%d] to keep with psm %d, act %d, size %d",
6396       glue, lidx, pagsl->psm, pagsl->act, pagsl->size);
6397   }
6398   DEL (pagsls, szpagsls);
6399   LOG (1, "explicity marked %d additional clauses to keep", nkeep);
6400   sumcollected = sumretired = 0;
6401   for (glue = 0; glue < MAXGLUE; glue++) {
6402     lir = lgl->red + glue;
6403     map = maps[glue];
6404 #ifndef NDEBUG
6405     size = sizes[glue];
6406 #endif
6407     q = start = lir->start;
6408     collected = retired = 0;
6409     for (c = start; c < lir->top; c = p + 1) {
6410       act = *c++;
6411       if (act == REMOVED) {
6412 	for (p = c; p < lir->top && *p == REMOVED; p++)
6413 	  ;
6414 	assert (p >= lir->top || *p < NOTALIT || lglisact (*p));
6415 	p--;
6416 	continue;
6417       }
6418       p = c;
6419       LGLCHKACT (act);
6420       src = (c - start)/6;
6421       assert (src < size);
6422       if (map[src] <= -2) {
6423 	assert (collected + retired < lgl->stats->lir[glue].clauses);
6424 	if (map[src] == -2) {
6425 	  collected++;
6426 	  LOGCLS (5, c, "collecting glue %d clause", glue);
6427 	} else {
6428 	  assert (map[src] == -3);
6429 	  retired++;
6430 	  LOGCLS (5, c, "retiring glue %d clause", glue);
6431 	}
6432 	lgldrupligdelclsaux (lgl, c);
6433 	while (*p) p++;
6434       } else {
6435 	dst = q - start + 1;
6436 	map[src] = dst;
6437 	if (p == q) {
6438 	  while (*p) p++;
6439 	  q = p + 1;
6440 	} else {
6441 	  *q++ = act;
6442 	  LOGCLS (5, c, "moving from %d to %d glue %d clause",
6443 		  (c - start), dst, glue);
6444 	  while (*p) *q++ = *p++;
6445 	  *q++ = 0;
6446 	}
6447       }
6448     }
6449     LOG (2, "collected %d glue %d clauses", collected, glue);
6450     assert (sumcollected + sumretired <= lgl->stats->red.lrg);
6451     assert (lgl->stats->lir[glue].clauses >= collected + retired);
6452     lgl->stats->lir[glue].clauses -= collected + retired;
6453     lgl->stats->lir[glue].reduced += collected;
6454     lgl->stats->lir[glue].retired += retired;
6455     sumcollected += collected;
6456     sumretired += retired;
6457     lir->top = q;
6458     lglfitlir  (lgl, lir);
6459   }
6460   lglprt (lgl, 2,
6461     "[reduce-%d] collected %d clauses %.0f%%, retired %d clauses %.0f%%",
6462     lgl->stats->reduced.count,
6463     sumcollected, lglpcnt (sumcollected, lgl->stats->red.lrg),
6464     sumretired, lglpcnt (sumretired, lgl->stats->red.lrg));
6465   assert (sumcollected + sumretired <= lgl->stats->red.lrg);
6466   lgl->stats->red.lrg -= sumcollected + sumretired;
6467   lgl->stats->reduced.collected += sumcollected;
6468   lgl->stats->reduced.retired += sumretired;
6469   nunlocked = 0;
6470   for (idx = 2; idx < lgl->nvars; idx++) {
6471     if (!lglval (lgl, idx)) continue;
6472     rsn = lglrsn (lgl, idx);
6473     r0 = rsn[0];
6474     red = r0 & REDCS;
6475     if (!red) continue;
6476     tag = r0 & MASKCS;
6477     if (tag != LRGCS) continue;
6478     lidx = rsn[1];
6479     glue = lidx & GLUEMASK;
6480     if (glue == MAXGLUE) continue;
6481     src = (lidx >> GLUESHFT);
6482     assert (src/6 < sizes[glue]);
6483     dst = maps[glue][src/6];
6484     assert (dst >= 0);
6485     dst <<= GLUESHFT;
6486     dst |= lidx & GLUEMASK;
6487     rsn[1] = dst;
6488     nunlocked++;
6489   }
6490   LOG (2, "unlocked %d reasons", nunlocked);
6491   assert (nlocked == nunlocked);
6492   collected = moved = 0;
6493   for (idx = 2; idx < lgl->nvars; idx++) {
6494     dv = lgldvar (lgl, idx);
6495     for (i = 0; i <= 1; i++) {
6496       hts = dv->hts + i;
6497       if (!hts->offset) continue;
6498       q = lglhts2wchs (lgl, hts);
6499       assert (hts->count >= 0);
6500       eow = q + hts->count;
6501       for (p = q; p < eow; p++) {
6502 	blit = *p;
6503 	red = blit & REDCS;
6504 	tag = blit & MASKCS;
6505 	if (red && tag == LRGCS) {
6506 	  lidx = *++p;
6507 	  glue = lidx & GLUEMASK;
6508 	  if (glue == MAXGLUE) {
6509 	    dst = lidx >> GLUESHFT;
6510 	  } else {
6511 	    src = lidx >> GLUESHFT;
6512 	    assert (src/6 < sizes[glue]);
6513 	    dst = maps[glue][src/6];
6514 	  }
6515 	  if (dst >= 0) {
6516 	    moved++;
6517 	    *q++ = blit;
6518 	    *q++ = (dst << GLUESHFT) | (lidx & GLUEMASK);
6519 	  } else collected++;
6520 	} else {
6521 	  *q++ = blit;
6522 	  if (tag != BINCS) {
6523 	    assert (tag == TRNCS || tag == LRGCS);
6524 	    *q++ = *++p;
6525 	  }
6526 	}
6527       }
6528       lglshrinkhts (lgl, hts, hts->count - (p - q));
6529     }
6530   }
6531   LOG (1, "moved %d and collected %d occurrences", moved, collected);
6532   for (glue = 0; glue < MAXGLUE; glue++)
6533     DEL (maps[glue], sizes[glue]);
6534   DEL (sizes, MAXGLUE);
6535   DEL (maps, MAXGLUE);
6536   if (lgl->opts->reducefixed.val) goto NOINC;
6537   if (lglmemout (lgl)) {
6538     inc = 0;
6539     lglprt (lgl, 2,
6540       "[reduce-%d] no increase of reduce limit since memory limit was hit",
6541       lgl->stats->reduced.count);
6542     lgl->stats->reduced.memlim++;
6543   } else {
6544     inc = lgl->opts->reduceinc.val;
6545     lglprt (lgl, 2,
6546       "[reduce-%d] increase of reduce limit by %d to %d",
6547       lgl->stats->reduced.count, inc, lgl->limits->reduce.redlarge + inc);
6548     lgl->stats->reduced.arith++;
6549   }
6550   LOG (1, "reduce increment %d", inc);
6551   lgl->limits->reduce.redlarge += inc;
6552   assert (forced || lgl->opts->reduce.val);
6553 NOINC:
6554   lglrelstk (lgl, &lgl->learned);
6555   lglrep (lgl, 1, type);
6556   lglchkred (lgl);
6557   lglstop (lgl);
6558 #ifndef NDEBUG
6559   lglclnstk (&lgl->prevclause);
6560   lgl->prevglue = -1;
6561 #endif
6562 }
6563 
lglreducecache(LGL * lgl)6564 void lglreducecache (LGL * lgl) {
6565   REQINITNOTFORKED ();
6566   TRAPI ("reduce");
6567   if (lgl->mt) return;
6568   lglinitredl (lgl);
6569   lglreduce (lgl, 1);
6570   lglinitredl (lgl);
6571   lglprt (lgl, 1, "[reduce-cache] new limit %d", lgl->limits->reduce.redlarge);
6572   if (lgl->clone) lglreducecache (lgl->clone);
6573 }
6574 
lgliflushcache(LGL * lgl,int keep)6575 static void lgliflushcache (LGL * lgl, int keep) {
6576   int idx, sign, lit, blit, tag, red, * w, * q, lidx, glue;
6577   const int druplig = lgl->opts->druplig.val;
6578   int bin, trn, lrg, start;
6579   const int * p, * eow;
6580   HTS * hts;
6581   assert (1 <= keep), assert (keep <= 4);
6582   if (lgl->level) lglbacktrack (lgl, 0);
6583   bin = trn = lrg = 0;
6584   for (idx = 2; idx < lgl->nvars; idx++) {
6585     for (sign = -1; sign <= 1; sign += 2) {
6586       lit = sign * idx;
6587       hts = lglhts (lgl, lit);
6588       w = lglhts2wchs (lgl, hts);
6589       eow = w + hts->count;
6590       q = w;
6591       for (p = q; p < eow; p++) {
6592 	blit = *p;
6593 	tag = blit & MASKCS;
6594 	if (tag == TRNCS || tag == LRGCS) p++;
6595 	red = blit & REDCS;
6596 	if (red) {
6597 	  if (tag == BINCS) {
6598 	    if (keep < 2) {
6599 	      if (druplig) {
6600 		int other = blit >> RMSHFT;
6601 		if (idx < abs (other))
6602 		  lgldrupligdelclsarg (lgl, lit, other, 0);
6603 	      }
6604 	      continue;
6605 	    }
6606 	  } else if (tag == TRNCS) {
6607 	    if (keep < 3) {
6608 	      if (druplig) {
6609 		int other = blit >> RMSHFT;
6610 		if (idx < abs (other)) {
6611 		  int other2 = *p;
6612 		  if (idx < abs (other2))
6613 		    lgldrupligdelclsarg (lgl, lit, other, other2, 0);
6614 		}
6615 	      }
6616 	      continue;
6617 	    }
6618 	  } else {
6619 	    assert (tag == LRGCS);
6620 	    lidx = *p;
6621 	    glue = lidx & GLUEMASK;
6622 	    if (keep < 4 || glue > 0) {
6623 	      if (druplig) {
6624                 const int * c = lglidx2lits (lgl, red, lidx);
6625 		if (*c == lit)
6626 		  lgldrupligdelclsaux (lgl, c);
6627 	      }
6628 	      continue;
6629 	    }
6630 	  }
6631 	}
6632 	*q++ = blit;
6633 	if (tag == TRNCS || tag == LRGCS) *q++ = *p;
6634       }
6635       lglshrinkhts (lgl, hts, q - w);
6636     }
6637   }
6638   if (keep < 2) bin = lgl->stats->red.bin, lgl->stats->red.bin = 0;
6639   if (keep < 3) trn = lgl->stats->red.trn, lgl->stats->red.trn = 0;
6640   start = (keep >= 4);
6641   for (glue = start; glue < MAXGLUE; glue++) {
6642     lrg += lgl->stats->lir[glue].clauses;
6643     lgl->stats->lir[glue].clauses = 0;
6644   }
6645   assert (lrg <= lgl->stats->red.lrg), lgl->stats->red.lrg -= lrg;
6646   lglrelstk (lgl, &lgl->learned);
6647   for (glue = start; glue < MAXGLUE; glue++)
6648     lglrelstk (lgl, lgl->red + glue);
6649   lglprt (lgl, 1,
6650     "[flush-cache] %d binary, %d ternary, %d large",
6651     bin, trn, lrg);
6652 #ifndef NDEBUG
6653   lglclnstk (&lgl->prevclause);
6654   lgl->prevglue = -1;
6655 #endif
6656 }
6657 
lglflushcache(LGL * lgl)6658 void lglflushcache (LGL * lgl) {
6659   REQINITNOTFORKED ();
6660   TRAPI ("flush");
6661   if (lgl->mt) return;
6662   lglinitredl (lgl);
6663   lgliflushcache (lgl, 3);
6664   lglinitscores (lgl);
6665   lglinitredl (lgl);
6666   lglprt (lgl, 1, "[flush-cache] new limit %d", lgl->limits->reduce.redlarge);
6667   if (lgl->clone) lglflushcache (lgl->clone);
6668 }
6669 
6670 
lglrmbwch(LGL * lgl,int lit,int other,int red)6671 static void lglrmbwch (LGL * lgl, int lit, int other, int red) {
6672   int * p, blit, blit1, * w, * eow, tag;
6673   HTS * hts;
6674   assert (!red || red == REDCS);
6675   LOG (3, "removing %s binary watch %d blit %d",
6676        lglred2str (red), lit, other);
6677   hts = lglhts (lgl, lit);
6678   assert (hts->count >= 1);
6679   p = w = lglhts2wchs (lgl, hts);
6680   eow = w + hts->count;
6681   lglrminc (lgl, w, eow);
6682   blit1 = RMSHFTLIT (other) | red | BINCS;
6683   for (;;) {
6684     assert (p < eow);
6685     blit = *p++;
6686     tag = blit & MASKCS;
6687     if (tag == TRNCS || tag == LRGCS) { p++; continue; }
6688     if (tag == OCCS) { assert (lgl->dense); continue; }
6689     assert (tag == BINCS);
6690     if (blit == blit1) break;
6691   }
6692   while (p < eow) p[-1] = p[0], p++;
6693   lglshrinkhts (lgl, hts, p - w - 1);
6694 }
6695 
lglpopesched(LGL * lgl)6696 static int lglpopesched (LGL * lgl) {
6697   Stk * s = &lgl->esched;
6698   int res, last, cnt, * p;
6699   EVar * ev;
6700   assert (!lglmtstk (s));
6701   res = *s->start;
6702   assert (!lglifrozen (lgl, res));
6703   LOGESCHED (4, res, "popped");
6704   ev = lglevar (lgl, res);
6705   assert (!ev->pos);
6706   ev->pos = -1;
6707   last = lglpopstk (s);
6708   cnt = lglcntstk (s);
6709   if (!cnt) { assert (last == res); return res; }
6710   p = lglepos (lgl, last);
6711   assert (*p == cnt);
6712   *p = 0;
6713   *s->start = last;
6714   lgledown (lgl, last);
6715   return res;
6716 }
6717 
lgldecocc(LGL * lgl,int lit)6718 static void lgldecocc (LGL * lgl, int lit) {
6719   int idx, sign, change;
6720   EVar * ev;
6721   if (!lgl->occs) return;
6722   idx = abs (lit), sign = (lit < 0);
6723   ev = lglevar (lgl, lit);
6724   assert (ev->occ[sign] > 0);
6725   ev->occ[sign] -= 1;
6726   if (!lglisfree (lgl, lit)) return;
6727   change = lglecalc (lgl, ev);
6728   LOG (3, "dec occ of %d now occs[%d] = %d %d",
6729        lit, idx,  ev->occ[0], ev->occ[1]);
6730   if (ev->pos < 0) lglesched (lgl, idx);
6731   else if (change < 0) lgleup (lgl, idx);
6732   else if (change > 0) lgledown (lgl, idx);
6733 }
6734 
lglrmbcls(LGL * lgl,int a,int b,int red)6735 static void lglrmbcls (LGL * lgl, int a, int b, int red) {
6736   lglrmbwch (lgl, a, b, red);
6737   lglrmbwch (lgl, b, a, red);
6738   LOG (2, "removed %s binary clause %d %d", lglred2str (red), a, b);
6739   lgldeclscnt (lgl, 2, red, 0);
6740   if (!red && lgl->dense) lgldecocc (lgl, a), lgldecocc (lgl, b);
6741 }
6742 
lglrmtcls(LGL * lgl,int a,int b,int c,int red)6743 static void lglrmtcls (LGL * lgl, int a, int b, int c, int red) {
6744   lglrmtwch (lgl, a, b, c, red);
6745   lglrmtwch (lgl, b, a, c, red);
6746   lglrmtwch (lgl, c, a, b, red);
6747   LOG (2, "removed %s ternary clause %d %d %d", lglred2str (red), a, b, c);
6748   lgldeclscnt (lgl, 3, red, 0);
6749   if (!red && lgl->dense)
6750     lgldecocc (lgl, a), lgldecocc (lgl, b), lgldecocc (lgl, c);
6751 }
6752 
lgltrimlitstk(LGL * lgl,int red,int lidx)6753 static void lgltrimlitstk (LGL * lgl, int red, int lidx) {
6754   Stk * s;
6755   int * p;
6756   if (lgl->notrim) return;
6757   s = lglidx2stk (lgl, red, lidx);
6758   p = s->top;
6759   while (p > s->start && p[-1] == REMOVED)
6760     p--;
6761   if (p < s->top) {
6762     int64_t trimmed = s->top - p;
6763 #ifndef NLGLOG
6764     if (red)
6765        LOG (4,
6766          "trimmed 'red[%d]' by %lld",
6767          (lidx & GLUEMASK), (LGLL) trimmed);
6768     else LOG (4, "trimmed 'irr' by %lld", (LGLL) trimmed);
6769 #endif
6770     lgl->stats->trims += trimmed;
6771     s->top = p;
6772     if (red) {
6773       int glue = (lidx & GLUEMASK), maxlidx;
6774       assert (s == &lgl->red[glue]);
6775       maxlidx = (lglcntstk (s) << GLUESHFT) | glue;
6776       for (p = lgl->learned.start; p < lgl->learned.top; p += 3) {
6777        int olidx = *p, oglue = (olidx & GLUEMASK);
6778        if (oglue == glue && olidx >= maxlidx) *p = INT_MIN;
6779       }
6780     }
6781   }
6782 }
6783 
lglrmlcls(LGL * lgl,int lidx,int red)6784 static void lglrmlcls (LGL * lgl, int lidx, int red) {
6785   int * c, * p, glue, lit;
6786   assert (!red || red == REDCS);
6787   glue = red ? (lidx & GLUEMASK) : 0;
6788   c = lglidx2lits (lgl, red, lidx);
6789   if (!red || glue < MAXGLUE) {
6790     lglrmlwch (lgl, c[0], red, lidx);
6791     lglrmlwch (lgl, c[1], red, lidx);
6792   }
6793   if (!red && lgl->dense) {
6794     for (p = c; (lit = *p); p++) {
6795       lglrmlocc (lgl, lit, red, lidx);
6796       lgldecocc (lgl, lit);
6797     }
6798   }
6799   if (red && glue < MAXGLUE) { LGLCHKACT (c[-1]); c[-1] = REMOVED; }
6800   for (p = c; *p; p++) *p = REMOVED;
6801   *p = REMOVED;
6802   if (glue != MAXGLUE) lgldeclscnt (lgl, p - c, red, glue);
6803   lgltrimlitstk (lgl, red, lidx);
6804 }
6805 
lgldynsub(LGL * lgl,int lit,int r0,int r1)6806 static void lgldynsub (LGL * lgl, int lit, int r0, int r1) {
6807   int red, tag, other, other2;
6808   const int * c;
6809   tag = r0 & MASKCS;
6810   LOGREASON (2, lit, r0, r1, "removing on-the-fly subsumed");
6811   red = r0 & REDCS;
6812   if (red) lgl->stats->otfs.sub.red++;
6813   else lgl->stats->otfs.sub.irr++;
6814   if (tag == BINCS) {
6815     lgl->stats->otfs.sub.bin++;
6816     other = (r0 >> RMSHFT);
6817     lgldrupligdelclsarg (lgl, lit, other, 0);
6818     lglrmbcls (lgl, lit, other, red);
6819   } else if (tag == TRNCS) {
6820     lgl->stats->otfs.sub.trn++;
6821     other = (r0 >> RMSHFT), other2 = r1;
6822     lgldrupligdelclsarg (lgl, lit, other, other2, 0);
6823     lglrmtcls (lgl, lit, other, other2, red);
6824   } else {
6825     assert (tag == LRGCS);
6826     lgl->stats->otfs.sub.lrg++;
6827     c = lglidx2lits (lgl, red, r1);
6828     lgldrupligdelclsaux (lgl, c);
6829     lglrmlcls (lgl, r1, red);
6830   }
6831 }
6832 
6833 
lglunflict(LGL * lgl,int lit)6834 static void lglunflict (LGL * lgl, int lit) {
6835   lgl->conf.lit = lit;
6836   lgl->conf.rsn[0] = RMSHFTLIT (lit) | UNITCS;
6837   LOG (1, "inconsistent unary clause %d", lit);
6838 }
6839 
lgldynstr(LGL * lgl,int del,int lit,int r0,int r1)6840 static void lgldynstr (LGL * lgl, int del, int lit, int r0, int r1) {
6841   int * p, * c, lidx, other, red, tag, glue, other2, other3, blit;
6842   tag = r0 & MASKCS;
6843   LOGREASON (2, lit, r0, r1,
6844     "on-the-fly strengthening by removing %d from", del);
6845   red = r0 & REDCS;
6846   if (red) lgl->stats->otfs.str.red++;
6847   else lgl->stats->otfs.str.irr++;
6848   lgl->stats->otfs.total++;
6849   lgl->stats->prgss++;
6850   if (!red) lgl->stats->irrprgss++;
6851   if (tag == BINCS) {
6852     lgl->stats->otfs.str.bin++;
6853     other = (del == lit) ? (r0 >> RMSHFT) : lit;
6854     assert (other != del);
6855     lgldrupligaddclsarg (lgl, REDCS, other, 0);
6856     lgldrupligdelclsarg (lgl, del, other, 0);
6857     lglrmbcls (lgl, del, other, red);
6858     lglunflict (lgl, other);
6859     return;
6860   }
6861   if (tag == TRNCS) {
6862     lgl->stats->otfs.str.trn++;
6863     if (lit == del) other = (r0 >> RMSHFT), other2 = r1;
6864     else if (del == r1) other = lit, other2 = (r0 >> RMSHFT);
6865     else other = lit, other2 = r1;
6866     assert (del != other && del != other2);
6867     lgldrupligaddclsarg (lgl, REDCS, other, other2, 0);
6868     lgldrupligdelclsarg (lgl, del, other, other2, 0);
6869     lglrmtcls (lgl, del, other, other2, red);
6870     if (!red) lglincirr (lgl, 2);
6871     else lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
6872     lglwchbin (lgl, other, other2, red);
6873     lglwchbin (lgl, other2, other, red);
6874     if (lglevel (lgl, other) < lglevel (lgl, other2)) SWAP (int, other, other2);
6875     blit = RMSHFTLIT (other2) | BINCS | red;
6876     lglbonflict (lgl, other, blit);
6877     return;
6878   }
6879   assert (tag == LRGCS);
6880   lgl->stats->otfs.str.lrg++;
6881   lidx = r1;
6882   glue = red ? (lidx & GLUEMASK) : 0;
6883   c = lglidx2lits (lgl, red, lidx);
6884   for (p = c; *p != del; p++)
6885     assert (*p);
6886   if (glue < MAXGLUE) {
6887     lglrmlwch (lgl, c[0], red, lidx);
6888     lglrmlwch (lgl, c[1], red, lidx);
6889   }
6890   while ((other = *++p)) p[-1] = other;
6891   p[-1] = 0, *p = REMOVED;
6892   lgltrimlitstk (lgl, red, lidx);
6893   if (!red) assert (lgl->stats->irr.lits.cur), lgl->stats->irr.lits.cur--;
6894   lglorderclsaux (lgl, c + 0);
6895   lglorderclsaux (lgl, c + 1);
6896   lgldrupligaddclsaux (lgl, REDCS, c);
6897   assert (p - c > 3);
6898   if (p - c == 4) {
6899     assert (!c[3] && c[4] >= NOTALIT);
6900     other = c[0], other2 = c[1], other3 = c[2];
6901     if (red && glue < MAXGLUE) { LGLCHKACT (c[-1]); c[-1] = REMOVED; }
6902     c[0] = c[1] = c[2] = c[3] = REMOVED;
6903     lgltrimlitstk (lgl, red, lidx);
6904     if (lglevel (lgl, other2) < lglevel (lgl, other3))
6905       SWAP (int, other2, other3);
6906     if (lglevel (lgl, other) < lglevel (lgl, other2))
6907       SWAP (int, other, other2);
6908     lglwchtrn (lgl, other, other2, other3, red);
6909     lglwchtrn (lgl, other2, other, other3, red);
6910     lglwchtrn (lgl, other3, other, other2, red);
6911     if (red) {
6912       if (glue < MAXGLUE) {
6913 	assert (lgl->stats->red.lrg > 0);
6914 	lgl->stats->red.lrg--;
6915 	assert (lgl->stats->lir[glue].clauses > 0);
6916 	lgl->stats->lir[glue].clauses--;
6917       }
6918       lgl->stats->red.trn++;
6919       assert (lgl->stats->red.trn > 0);
6920     }
6921     lgltonflict (lgl, other, RMSHFTLIT (other2) | red | TRNCS, other3);
6922   } else {
6923     if (glue < MAXGLUE) {
6924       LOG (3, "new head literal %d", c[0]);
6925       (void) lglwchlrg (lgl, c[0], c[1], red, lidx);
6926       LOG (3, "new tail literal %d", c[1]);
6927       (void) lglwchlrg (lgl, c[1], c[0], red, lidx);
6928     }
6929     lglonflict (lgl, 0, c[0], red, lidx);
6930   }
6931 }
6932 
lglclnframes(LGL * lgl)6933 static void lglclnframes (LGL * lgl) {
6934   while (!lglmtstk (&lgl->frames))
6935     lglunuselevel (lgl, lglpopstk (&lgl->frames));
6936 }
6937 
lglclnpoisoned(LGL * lgl)6938 static void lglclnpoisoned (LGL * lgl) {
6939   while (!lglmtstk (&lgl->poisoned)) {
6940     int lit = lglpopstk (&lgl->poisoned);
6941     AVar * av = lglavar (lgl, lit);
6942     assert (!av->mark);
6943     assert (av->poisoned);
6944     av->poisoned = 0;
6945   }
6946 }
6947 
lglclnana(LGL * lgl)6948 static void lglclnana (LGL * lgl) {
6949 #ifdef RESOLVENT
6950   if (lglmaintainresolvent (lgl)) lglclnstk (&lgl->resolvent);
6951 #endif
6952   lglclnstk (&lgl->clause);
6953   lglpopnunmarkstk (lgl, &lgl->seen);
6954   lglclnframes (lgl);
6955 }
6956 
lglbumpdlit(LGL * lgl,int lit)6957 static void lglbumpdlit (LGL * lgl, int lit) {
6958   int idx = abs (lit), mightneedtorescore = 0;
6959   QVar * qv = lglqvar (lgl, idx);
6960   Flt oldscore, newscore;
6961   if (lgl->simp && !lgl->opts->bumpsimp.val) return;
6962   if (qv->enqueued) {
6963     assert (lglpeek (&lgl->queue.stk, qv->pos) == abs (lit));
6964     lglpoke (&lgl->queue.stk, qv->pos, 0);
6965     lgl->queue.mt++;
6966     qv->enqueued = 0;
6967     qv->pos = -1;
6968     if (!lglval (lgl, lit)) lgldsched (lgl, idx);
6969   }
6970   oldscore = qv->score;
6971   newscore = lgladdflt (oldscore, lgl->scinc);
6972   LOG (3,
6973     "bumping EVSIDS score of variable %d from %s to %s",
6974     idx, lglscr2str (lgl, oldscore), lglscr2str (lgl, newscore));
6975   assert (newscore > oldscore);
6976   mightneedtorescore = 1;
6977   qv->score = newscore;
6978   if (lgldscheduled (lgl, idx)) lgldup (lgl, idx);
6979   if (mightneedtorescore && newscore >= lgl->maxscore) lglrescorevars (lgl);
6980 }
6981 
lglcmpbump(LGL * lgl,int a,int b)6982 static int lglcmpbump (LGL * lgl, int a, int b) {
6983   return lgltrail (lgl, b) - lgltrail (lgl, a);
6984 }
6985 
6986 #define LGLCMPBUMP(P,Q) lglcmpbump (lgl, *(P), *(Q))
6987 
lglbumpseenlits(LGL * lgl)6988 static void lglbumpseenlits (LGL * lgl) {
6989   const int * p;
6990   if (lgl->simp && !lgl->opts->bumpsimp.val) return;
6991   lglstart (lgl, &lgl->times->bump);
6992   lgl->stats->bump.count++;
6993   SORT (int, lgl->seen.start, lglcntstk (&lgl->seen), LGLCMPBUMP);
6994   for (p = lgl->seen.start; p < lgl->seen.top; p++)
6995     lglbumpdlit (lgl, *p);
6996   LOG (2, "bumped %d literals", lglcntstk (&lgl->seen));
6997   lgl->stats->bump.lits += lglcntstk (&lgl->seen);
6998   lglstop (lgl);
6999 }
7000 
lglmincls(LGL * lgl,int uip,int glue)7001 static void lglmincls (LGL * lgl, int uip, int glue) {
7002   int origsize = lglcntstk (&lgl->clause) - 1;
7003   int * p, * q, other, minimized, local;
7004   if (!lgl->opts->minimize.val) return;
7005   if (glue > lgl->opts->minlocalgluelim.val) return;
7006   if (origsize > lgl->opts->minlocalsizelim.val) return;
7007   lglstart (lgl, &lgl->times->mincls);
7008   lgl->stats->mincls.min++;
7009   q = lgl->clause.start;
7010   minimized = 0;
7011   local = lgl->opts->minimize.val <= 1 ||
7012           glue > lgl->opts->minrecgluelim.val ||
7013           origsize > lgl->opts->minrecsizelim.val;
7014   assert (lglmtstk (&lgl->poisoned));
7015   for (p = q; (other = *p); p++)
7016     if (other != uip && lglminclslit (lgl, other, local)) {
7017       LOG (2, "minimized literal %d", other);
7018       minimized++;
7019     } else *q++ = other;
7020   *q++ = 0;
7021   lglclnpoisoned (lgl);
7022   assert (lgl->clause.top - q == minimized);
7023   COVER (glue + 1 >= origsize && minimized > 0);	// unreachable ...
7024   LOG (2, "clause minimized by %d literals", minimized);
7025   LOGCLS (2, lgl->clause.start, "minimized clause");
7026   lgl->clause.top = q;
7027   lglstop (lgl);
7028 }
7029 
7030 static void lglsignedmarknpushseen (LGL *, int);
7031 static int lglsignedmarked (LGL *, int);
7032 
lglcmpuiplitrail(LGL * lgl,int uip,int a,int b)7033 static int lglcmpuiplitrail (LGL * lgl, int uip, int a, int b) {
7034   if (a == uip) return -1;
7035   if (b == uip) return 1;
7036   return lgltrail (lgl, a) - lgltrail (lgl, b);
7037 }
7038 
7039 #define LGLCMPUIPLITRAIL(P,Q) lglcmpuiplitrail (lgl, uip, *(P), *(Q))
7040 
lglredclsassign(LGL * lgl,int lit)7041 static void lglredclsassign (LGL * lgl, int lit) {
7042   assert (!lglmarked (lgl, lit)), assert (!lglifixed (lgl, lit));
7043   lglmark (lgl, lit);
7044   lglpushstk (lgl, &lgl->seen, lit);
7045   LOG (3, "assigning literal %d for clause reduction", lit);
7046 }
7047 
lglredclsmarked(LGL * lgl,int lit)7048 static int lglredclsmarked (LGL * lgl, int lit) {
7049   int mark, val;
7050   mark = lglmarked (lgl, lit);
7051   if (mark) return mark;
7052   val = lglifixed (lgl, lit);
7053   if (val) return val;
7054   return 0;
7055 }
7056 
lglredcls(LGL * lgl,int uip,int glue,int * jlevelptr)7057 static void lglredcls (LGL * lgl, int uip, int glue, int * jlevelptr) {
7058   int lit, cand, blit, tag, other, other2, count, size, reduced;
7059   int * q, newjlevel, oldjlevel, level, sat, red, lidx, unit;
7060   int dec, depth, props, mark, mark2, markcand, lrg;
7061   const int * p, * w, * eow, * r, * l, * c;
7062   HTS * hts;
7063   const int maxdepth = lgl->opts->redclsmaxdepth.val;
7064   const int maxprops = lgl->opts->redclsmaxprops.val;
7065   const int maxlrg = lgl->opts->redclsmaxlrg.val;
7066   const int maxdec = lgl->opts->redclsmaxdec.val;
7067   const int type = lgl->opts->redclstype.val;
7068   if (!lgl->opts->redcls.val) return;
7069   if (glue > lgl->opts->redclsglue.val) return;
7070   if (lglcntstk (&lgl->clause) >= lgl->opts->redclsize.val) return;
7071   lglstart (lgl, &lgl->times->redcls);
7072   lgl->stats->redcls.cls.tried++;
7073   lglpopnunmarkstk (lgl, &lgl->seen);
7074   size = lglcntstk (&lgl->clause) - 1;
7075   assert (size >= 1);
7076   SORT (int, lgl->clause.start, size, LGLCMPUIPLITRAIL);
7077   assert (lglpeek (&lgl->clause, 0) == uip);
7078 #ifndef NLGLOG
7079   if (lgl->opts->log.val >= 2) {
7080     lglogstart (lgl, 2, "sorted clause before reducing");
7081     for (p = lgl->clause.start; p < lgl->clause.top; p++) {
7082       if (!(lit = *p)) continue;
7083       fprintf (lgl->out, " %d (l%d,t%d)",
7084         lit, lglevel (lgl, lit), lgltrail (lgl, lit));
7085     }
7086     lglogend (lgl);
7087   }
7088 #endif
7089   sat = reduced = 0;
7090   assert (lgl->clause.start < lgl->clause.top);
7091   assert (!lgl->clause.top[-1]);
7092   dec = 0;
7093   for (p = q = lgl->clause.start; p < lgl->clause.top; p++) {
7094     if (!(cand = *p)) *q++ = cand;
7095     else {
7096       lgl->stats->redcls.lits.tried++;
7097       markcand = lglredclsmarked (lgl, cand);
7098       if (markcand > 0) {
7099 	LOG (3, "skipping true literal %d for clause reduction", cand);
7100 	lgl->stats->redcls.lits.sat++;
7101 	*q++ = cand;
7102 	sat = 1;
7103       } else if (markcand < 0) {
7104 	LOG (3, "reducing clause by removing literal %d", cand);
7105 	lgl->stats->redcls.lits.red++;
7106 	reduced++;
7107       } else {
7108 	assert (!markcand);
7109 	*q++ = cand;
7110 	assert (p + 1 < lgl->clause.top);
7111 	if (!p[1]) continue;
7112 	if (++dec > maxdec) continue;
7113 	LOG (3, "decision literal %d for clause reduction", -cand);
7114 	depth = props = lrg = 0;
7115 	count = lglcntstk (&lgl->seen);
7116 	lglredclsassign (lgl, -cand);
7117 	while (count < lglcntstk (&lgl->seen)) {
7118 	  if (props >= maxprops) break;
7119 	  if (depth >= maxdepth) break;
7120 	  lit = lglpeek (&lgl->seen, count++);
7121 	  if (lit) props++; else { depth++; continue; }
7122 	  assert (lglredclsmarked (lgl, lit) > 0);
7123 	  LOG (4, "propagating literal %d for clause reduction", lit);
7124 	  hts = lglhts (lgl, -lit);
7125 	  w = lglhts2wchs (lgl, hts);
7126 	  eow = w + hts->count;
7127 	  for (r = w; r < eow; r++) {
7128 	    blit = *r;
7129 	    tag = blit & MASKCS;
7130 	    if (tag == TRNCS || tag == LRGCS) r++;
7131 	    if (tag == BINCS) {
7132 	      other = blit >> RMSHFT;
7133 	      if (lglredclsmarked (lgl, other)) continue;
7134 	      lglredclsassign (lgl, other);
7135 	    } else if (tag == TRNCS) {
7136 	      if (cand != uip || type < 3) continue;
7137 	      other = blit >> RMSHFT;
7138 	      mark = lglredclsmarked (lgl, (other));
7139 	      if (mark > 0) continue;
7140 	      other2 = *r;
7141 	      mark2 = lglredclsmarked (lgl, other2);
7142 	      if (mark2 > 0) continue;
7143 	      if (mark2 < 0 && !mark) lglredclsassign (lgl, other);
7144 	      if (mark < 0 && !mark2) lglredclsassign (lgl, other2);
7145 	    } else {
7146 	      assert (tag == LRGCS);
7147 	      if (type < 4 || cand != uip) continue;
7148 	      if (++lrg >= maxlrg) continue;
7149 	      other = blit >> RMSHFT;
7150 	      mark = lglredclsmarked (lgl, other);
7151 	      if (mark > 0) continue;
7152 	      red = blit & REDCS;
7153 	      lidx = *r;
7154 	      c = lglidx2lits (lgl, red, lidx);
7155 	      unit = 0;
7156 	      for (l = c; (other = *l); l++) {
7157 		if (other == -lit) continue;
7158 		mark = lglredclsmarked (lgl, other);
7159 		if (mark > 0) break;
7160 		if (mark < 0) continue;
7161 		if (unit) break;
7162 		unit = other;
7163 	      }
7164 	      if (other || !unit) continue;
7165 	      lglredclsassign (lgl, unit);
7166 	    }
7167 	  }
7168 	  lglpushstk (lgl, &lgl->seen, 0);
7169 	}
7170       }
7171     }
7172   }
7173   if (sat) lgl->stats->redcls.cls.sat++;
7174   lgl->clause.top = q;
7175   LOG (2, "reduced clause by %d literals", reduced);
7176   LOGCLS (2, lgl->clause.start, "reduced clause");
7177   if (reduced) lgl->stats->redcls.cls.red++;
7178   oldjlevel = *jlevelptr;
7179   newjlevel = 0;
7180   for (p = lgl->clause.start; p < lgl->clause.top; p++) {
7181     if (!(lit = *p) || lit == uip) continue;
7182     level = lglevel (lgl, lit);
7183     assert (level != lgl->level);
7184     if (level > newjlevel) newjlevel = level;
7185   }
7186   assert (newjlevel <= oldjlevel);
7187   if (oldjlevel == newjlevel)
7188     LOG (2, "jump level %d does not change", newjlevel);
7189   else {
7190     LOG (2, "jump level reduced to %d from %d", newjlevel, oldjlevel);
7191     *jlevelptr = newjlevel;
7192     lgl->stats->redcls.jlevel.red++;
7193     lgl->stats->redcls.jlevel.sum += oldjlevel - newjlevel;
7194   }
7195   lglstop (lgl);
7196 }
7197 
lgliassume(LGL * lgl,int lit)7198 static void lgliassume (LGL * lgl, int lit) {
7199   lgl->level++;
7200   lglpushcontrol (lgl, lit);
7201   assert (lglcntctk (&lgl->control) == lgl->level + 1);
7202   LOG (2, "internally assuming %d", lit);
7203   lglassign (lgl, lit, DECISION, 0);
7204 }
7205 
lgldassume(LGL * lgl,int lit)7206 static void lgldassume (LGL * lgl, int lit) {
7207   LOG (1, "next assumed decision %d external %d", lit, lglexport (lgl, lit));
7208   lgl->stats->decisions++;
7209   lgliassume (lgl, lit);
7210   assert (lgldecision (lgl, lit));
7211 }
7212 
lglsubl(LGL * lgl,int lidx,int size,int glue)7213 static int lglsubl (LGL * lgl, int lidx, int size, int glue) {
7214   const int * c, * p;
7215   int count, lit;
7216   assert (lidx);
7217   assert ((lidx & GLUEMASK) < MAXGLUE);
7218   c = lglidx2lits (lgl, REDCS, lidx);
7219   count = 0;
7220   for (p = c; count < size && (lit = *p); p++) {
7221     if (lit == REMOVED) return 1;
7222     if (lglmarked (lgl, lit) > 0) count++;
7223   }
7224   lgl->stats->subl.tried++;
7225   if (count < size) {
7226     LOGCLS (4, c, "only %d literals shared in clause", count);
7227     return 0;
7228   }
7229   assert (!lglrgforcing (lgl, REDCS, lidx));
7230   LOGCLS (2, c,
7231     "subsumed learned (scaled) glue %d clause",
7232     (int)(lidx & GLUEMASK));
7233   LOGCLS (2, lgl->clause.start,
7234     "subsumed by new size %d glue %d scaled glue %d clause",
7235     size, glue, lglscaleglue (lgl, glue));
7236   lgl->stats->subl.sub++;
7237   lgldrupligdelclsaux (lgl, c);
7238   lglrmlcls (lgl, lidx, REDCS);
7239   return 1;
7240 }
7241 
lgldrive(LGL * lgl,const char * type,int * forcedptr,int * glueptr,int * realglueptr,int * jlevelptr)7242 static void lgldrive (
7243   LGL * lgl, const char * type, int * forcedptr,
7244   int * glueptr, int * realglueptr, int * jlevelptr) {
7245   int lit, jlevel, level, minlevel, maxlevel, glue, realglue, forced;
7246   const int * p, * soc = lgl->clause.start, * eoc = lgl->clause.top - 1;
7247   Ctr * c;
7248   assert (soc <= eoc), assert (!*eoc);
7249   forced = forcedptr ? *forcedptr : 0;
7250 #ifndef NDEBUG
7251   for (p = soc; p < eoc; p++) {
7252     level = lglevel (lgl, lit = *p);
7253     assert (0 < level), assert (level <= lgl->level);
7254     c = lgl->control.start + level;
7255     assert (!c->used2);
7256   }
7257 #endif
7258 #ifndef NLGLOG
7259   if (lgl->opts->log.val >= 4) {
7260     lglogstart (lgl, 2, "driving using clause");
7261     for (p = soc; p < eoc; p++) {
7262       lit = *p;
7263       fprintf (lgl->out, " %d (l%d,t%d)",
7264         lit, lglevel (lgl, lit), lgltrail (lgl, lit));
7265     }
7266     lglogend (lgl);
7267   }
7268 #endif
7269   maxlevel = -1, minlevel = lgl->level + 1;
7270   for (p = soc; p < eoc; p++) {
7271     level = lglevel (lgl, *p);
7272     c = lgl->control.start + level;
7273     if (!c->used2) {
7274       if (level < minlevel) minlevel = level;
7275       if (level > maxlevel) maxlevel = level;
7276       c->used2 = 1;
7277       LOG (4, "level %d used in clause", level);
7278     } else if (c->used2 == 1) {
7279       c->used2 = 2;
7280       LOG (4, "level %d actually used (at least) twice in clause", level);
7281     }
7282   }
7283   if (maxlevel >= 0) {
7284     c = lgl->control.start + maxlevel;
7285     assert (c->used2);
7286     if (c->used2 > 1) {
7287       assert (c->used2 == 2);
7288       LOG (4, "maximum level %d used twice so no forced literal", maxlevel);
7289       jlevel = maxlevel;
7290       realglue = glue = -1;
7291       for (p = soc; p < eoc; p++) {
7292        level = lglevel (lgl, lit = *p);
7293        c = lgl->control.start + level;
7294        if (c->used2 || level == jlevel) {
7295          if (level >= lgl->alevel) realglue++;
7296          glue++;
7297        }
7298        c->used2 = 0;
7299       }
7300       assert (realglue >= 0);
7301       assert (glue >= 0);
7302     } else {
7303       assert (c->used2 == 1);
7304       LOG (4, "maximum level %d used only once", maxlevel);
7305       realglue = glue = jlevel = level = forced = 0;
7306       for (p = soc; p < eoc; p++) {
7307        level = lglevel (lgl, lit = *p);
7308        c = lgl->control.start + level;
7309        if (level == maxlevel) {
7310          assert (c->used2 == 1);
7311          forced = lit;
7312        } else if (c->used2) {
7313          if (level > jlevel) jlevel = level;
7314          if (level >= lgl->alevel) realglue++;
7315          glue++;
7316        }
7317        c->used2 = 0;
7318       }
7319       assert (!jlevel || minlevel <= jlevel);
7320       assert (jlevel < maxlevel);
7321       assert (forced);
7322     }
7323   } else glue = realglue = jlevel = forced = minlevel = maxlevel = 0;
7324 
7325   for (p = soc; p < eoc; p++) {
7326     level = lglevel (lgl, lit = *p);
7327     assert (0 < level), assert (level <= lgl->level);
7328     c = lgl->control.start + level;
7329     if (c->used2) c->used2 = 0;
7330   }
7331 
7332   LOG (2, "%s minimum level %d", type, minlevel);
7333   LOG (2, "%s maximum level %d", type, maxlevel);
7334   LOG (2, "%s glue %d (real %d) covers %.0f%%", type, glue, realglue,
7335        (float)(jlevel ? lglpcnt (glue, (jlevel - minlevel) + 1) : 100.0));
7336   LOG (2, "%s jump level %d", type, jlevel);
7337   LOG (2, "%s forced %d", type, forced);
7338 
7339   if (glueptr) *glueptr = glue;
7340   if (realglueptr) *realglueptr = realglue;
7341   if (jlevelptr) *jlevelptr = jlevel;
7342   if (forcedptr) *forcedptr = forced;
7343 }
7344 
lgldeco(LGL * lgl,int jlevel,int uip)7345 static void lgldeco (LGL * lgl, int jlevel, int uip) {
7346   int * q, * r, lit, level, limlevel;
7347 #ifndef NDEBUG
7348   int countabovejlevel = 0;
7349 #endif
7350   Ctr * p;
7351   assert (lgl->opts->deco.val == 1);
7352   if (lgl->opts->deco1opt.val) {
7353     for (limlevel = jlevel; limlevel > 1; limlevel--) {
7354       p = lgl->control.start + limlevel;
7355       if (p->used > 1) break;
7356     }
7357   } else limlevel = jlevel;
7358   LOG (4,
7359     "singly-used level limit %d for deco clause",
7360     limlevel);
7361   for (q = r = lgl->clause.start; q < lgl->clause.top; q++) {
7362     if (!(lit = *q)) continue;
7363     level = lglevel (lgl, lit);
7364     assert (0 < level);
7365     if (level > jlevel) {
7366 #ifndef NDEBUG
7367       assert (!countabovejlevel);      // only for UIP
7368       assert (lit == uip);
7369       countabovejlevel++;
7370 #else
7371       (void) uip;
7372 #endif
7373       continue;
7374     }
7375     p = lgl->control.start + level;
7376     assert (p->used >= 1);
7377     if (level > limlevel && p->used == 1) {
7378       LOG (4,
7379         "keep singly-used level %d literal %d in deco clause",
7380        level, lit);
7381       *r++ = lit;
7382     } else if (p->decision != -lit)
7383       LOG (4,
7384         "drop non-decision multi-used level %d literal %d in deco clause",
7385        level, lit);
7386   }
7387   lgl->clause.top = r;
7388   for (level = 1; level <= jlevel; level++) {
7389     p = lgl->control.start + level;
7390     assert (p < lgl->control.top);
7391     if (level > limlevel && p->used == 1) continue;
7392     lit = -p->decision;
7393     assert (lgldecision (lgl, lit));
7394     assert (lglevel (lgl, lit));
7395     assert (lglevel (lgl, lit) <= jlevel);
7396     lglpushstk (lgl, &lgl->clause, lit);
7397     LOG (4,
7398       "add level %d decision literal %d to deco clause",
7399       level, lit);
7400   }
7401 }
7402 
7403 /*------------------------------------------------------------------------*/
7404 
7405 static const int64_t INT64MIN = LLONG_MIN;
7406 static const int64_t INT64MAX = LLONG_MAX;
7407 
lgleftshiftint64(int64_t val,int shift)7408 static int64_t lgleftshiftint64 (int64_t val, int shift) {
7409   int64_t res;
7410   assert (shift >= 0);
7411        if (val == INT64MIN) res = INT64MIN;
7412   else if (val == INT64MAX) res = INT64MAX;
7413   else if (val > (INT64MAX >> shift)) res = INT64MAX;
7414   else if (val < (INT64MIN >> shift)) res = INT64MIN;
7415   else res = (int64_t)(((uint64_t) val) << shift);
7416   assert (val < 0 || res >= val);
7417   assert (val > 0 || res <= val);
7418   return res;
7419 }
7420 
lglrightshiftint64(int64_t val,int shift)7421 static int64_t lglrightshiftint64 (int64_t val, int shift) {
7422   int64_t res;
7423   assert (shift >= 0);
7424        if (val == INT64MIN) res = INT64MIN;
7425   else if (val == INT64MAX) res = INT64MAX;
7426   else res = val >> shift;
7427   assert (val > 0 || res >= val);
7428   assert (val < 0 || res <= val);
7429   return res;
7430 }
7431 
lgladdint64(int64_t a,int64_t b)7432 static int64_t lgladdint64 (int64_t a, int64_t b) {
7433   int64_t res;
7434        if (a == INT64MIN) res = INT64MIN;
7435   else if (b == INT64MIN) res = INT64MIN;
7436   else if (a == INT64MAX) res = INT64MAX;
7437   else if (b == INT64MAX) res = INT64MAX;
7438   else if (a >= 0 && b <= 0) res = a + b;
7439   else if (a <= 0 && b >= 0) res = a + b;
7440   else if (a < 0) {
7441     assert (b < 0);
7442     if (b < (INT64MIN - a)) res = INT64MIN;
7443     else res = a + b;
7444     assert (res <= a), assert (res <= b);
7445   } else {
7446     assert (a > 0), assert (b > 0);
7447     if (b > (INT64MAX - a)) res = INT64MAX;
7448     else res = a + b;
7449     assert (res >= a), assert (res >= b);
7450   }
7451   return res;
7452 }
7453 
lglsubint64(int64_t a,int64_t b)7454 static int64_t lglsubint64 (int64_t a, int64_t b) {
7455   int64_t res;
7456   if (b == INT64MIN) res = INT64MIN;
7457   else res = lgladdint64 (a, -b);
7458   return res;
7459 }
7460 
lglvalidint64(int64_t a)7461 static int lglvalidint64 (int64_t a) {
7462   return a != INT64MIN && a != INT64MAX;
7463 }
7464 
7465 /*------------------------------------------------------------------------*/
7466 
lglinitema(LGL * lgl,EMA * ema,int shift)7467 static void lglinitema (LGL * lgl, EMA * ema, int shift) {
7468   assert (0 <= shift), assert (shift <= 32);
7469   ema->shift = shift;
7470   ema->count = 0;
7471   LOG (2, "initialized EMA shift %d", shift);
7472 }
7473 
lglupdatema(LGL * lgl,EMA * ema,int64_t input,int left)7474 static void lglupdatema (LGL * lgl, EMA * ema, int64_t input, int left) {
7475   int64_t oldval, tmpval, newval, add, sub;
7476   const int shift = ema->count;
7477   oldval = ema->val;
7478   if (shift < ema->shift) ema->count++;
7479   assert (lglvalidint64 (oldval));
7480   if (!lglvalidint64 (input)) goto DONE;
7481   sub = lglrightshiftint64 (oldval, shift);
7482   if (!lglvalidint64 (sub)) goto DONE;
7483   tmpval = lglsubint64 (oldval, sub);
7484   if (!lglvalidint64 (tmpval)) goto DONE;
7485   if (left) add = lgleftshiftint64 (input, 32 - shift);
7486   else add = lglrightshiftint64 (input, shift);
7487   if (!lglvalidint64 (add)) goto DONE;
7488   newval = lgladdint64 (tmpval, add);
7489   if (!lglvalidint64 (newval)) goto DONE;
7490   ema->val = newval;
7491 DONE:
7492 #ifndef NLGLOG
7493   if (left)
7494     LOG (2,
7495       "EMA (left) input %lld old %g shift %d new %g",
7496       (LGLL) input,
7497       oldval/(double)(1ll<<32),
7498       ema->shift,
7499       ema->val/(double)(1ll<<32));
7500   else
7501     LOG (2,
7502       "EMA (right) input %g old %g shift %d new %g",
7503       input/(double)(1ll<<32),
7504       oldval/(double)(1ll<<32),
7505       ema->shift,
7506       ema->val/(double)(1ll<<32));
7507 #else
7508   ;
7509 #endif
7510 }
7511 
7512 #ifndef NLGLDEMA
7513 
lglinitdema(LGL * lgl,DEMA * dema,int shift)7514 static void lglinitdema (LGL * lgl, DEMA * dema, int shift) {
7515   lglinitema (lgl, &dema->ema[0], shift);
7516   lglinitema (lgl, &dema->ema[1], shift);
7517   LOG (2, "initialized DEMA shift %d", shift);
7518 }
7519 
lglupdatedema(LGL * lgl,DEMA * dema,int input)7520 static void lglupdatedema (LGL * lgl, DEMA * dema, int input) {
7521 #ifndef NLGLOG
7522   int64_t oldval = dema->val;
7523 #endif
7524   int64_t newval, val0, val1;
7525   lglupdatema (lgl, &dema->ema[0], input, 1);
7526   if (!lglvalidint64 (val0 = dema->ema[0].val)) goto DONE;
7527   lglupdatema (lgl, &dema->ema[1], val0, 0);
7528   if (!lglvalidint64 (val1 = dema->ema[1].val)) goto DONE;
7529   newval = lglsubint64 (lgleftshiftint64 (val0, 1), val1);
7530   if (!newval) goto DONE;
7531   dema->val = newval;
7532 DONE:
7533   LOG (2,
7534     "DEMA input %lld old %g shift %d new %g",
7535     (LGLL) input,
7536     oldval/(double)(1ll<<32),
7537     dema->ema[0].shift,
7538     dema->val/(double)(1ll<<32));
7539 }
7540 
7541 #endif
7542 
lglinitmacd(LGL * lgl,MACD * macd,int fast,int slow,int smooth)7543 static void lglinitmacd (LGL * lgl, MACD * macd,
7544                          int fast, int slow, int smooth) {
7545   assert (0 <= fast), assert (fast <= 32);
7546   assert (0 <= slow), assert (slow <= 32);
7547   assert (0 <= smooth), assert (smooth <= 32);
7548   lglinitmacdema (lgl, &macd->fast, fast);
7549   lglinitmacdema (lgl, &macd->slow, slow);
7550   lglinitema (lgl, &macd->diff.smoothed, smooth);
7551   LOG (2, "initialized MACD fast %d slow %d smooth %d", fast, slow, smooth);
7552 }
7553 
lglupdatemacd(LGL * lgl,MACD * macd,int64_t input)7554 static void lglupdatemacd (LGL * lgl, MACD * macd, int64_t input) {
7555 #if !defined(NDEBUG) || !defined(NLGLOG)
7556   int64_t oldactual = macd->diff.actual;
7557   int64_t oldsmoothed = macd->diff.smoothed.val;
7558 #endif
7559   int64_t newactual;
7560   assert (lglvalidint64 (oldsmoothed));
7561   assert (lglvalidint64 (oldactual));
7562   lglupdatemacdema (lgl, &macd->fast, input);
7563   lglupdatemacdema (lgl, &macd->slow, input);
7564   newactual = lglsubint64 (macd->fast.val, macd->slow.val);
7565   if (!lglvalidint64 (newactual)) goto DONE;
7566   macd->diff.actual = newactual;
7567   lglupdatema (lgl, &macd->diff.smoothed, newactual, 0);
7568 DONE:
7569   LOG (2,
7570 "updated MACD input %lld actual/smoothed: old %g/%g, new %g/%g",
7571     (LGLL) input,
7572     oldactual/(double)(1ll<<32),
7573     oldsmoothed/(double)(1ll<<32),
7574     macd->diff.actual/(double)(1ll<<32),
7575     macd->diff.smoothed.val/(double)(1ll<<32));
7576 }
7577 
lglupdstab(LGL * lgl)7578 static void lglupdstab (LGL * lgl) {
7579   int assigned = lglcntstk (&lgl->trail);
7580   int changed = lgl->stats->stability.changed;
7581   int topassigned = lglevel2trail (lgl, 1);
7582   int nontopassigned = assigned - topassigned;
7583   int64_t difference, shifted, fraction;
7584   lgl->stats->stability.count++;
7585   lglprt (lgl, 2,
7586     "[stability-%lld] %d assigned, %d non-top %.1f%%, %d changed %.2f%%",
7587     (LGLL) lgl->stats->stability.count,
7588     assigned,
7589     nontopassigned, lglpcnt (nontopassigned, assigned),
7590     changed, lglpcnt (changed, nontopassigned));
7591   assert (lgl->level > 0);
7592   assert (lgl->stats->stability.level > 0);
7593   assert (lgl->stats->stability.level <= lgl->level);
7594   assert (nontopassigned >= 0);
7595   if (!nontopassigned) fraction = 0;
7596   else {
7597     assert (nontopassigned >= changed);
7598     difference = nontopassigned - changed;
7599     shifted = difference << 32;
7600     fraction = shifted / nontopassigned;
7601   }
7602   lglupdatema (lgl, &lgl->stats->stability.avg, fraction, 0);
7603   lgl->stats->stability.level = 0;
7604   lglprt (lgl, 2,
7605     "[stability-%lld] unchanged fraction %.3f%% new stability %.3f%%",
7606     (LGLL) lgl->stats->stability.count,
7607     100.0 * fraction/(double)(1ll<<32),
7608     100.0 * lgl->stats->stability.avg.val / (double)(1ll<<32));
7609 }
7610 
lglinitavg(AVG * avg)7611 static void lglinitavg (AVG * avg) {
7612   avg->val = avg->count = 0;
7613 }
7614 
lglupdateavg(LGL * lgl,AVG * avg,int input)7615 static void lglupdateavg (LGL * lgl, AVG * avg, int input) {
7616   int64_t oldval = avg->val, newval = oldval, shifted, diff;
7617   shifted = lgleftshiftint64 (input, 32);
7618   if (!lglvalidint64 (shifted)) goto DONE;
7619   diff = lglsubint64 (shifted, oldval);
7620   if (!lglvalidint64 (diff)) goto DONE;
7621   diff /= ++avg->count;
7622   newval = lgladdint64 (oldval, diff);
7623   if (!lglvalidint64 (newval)) goto DONE;
7624   avg->val = newval;
7625 DONE:
7626   LOG (2,
7627     "AVG input %d old %g new %g count %lld",
7628     input,
7629     oldval/(double)(1ll<<32),
7630     newval/(double)(1ll<<32),
7631     avg->count);
7632 }
7633 
7634 /*------------------------------------------------------------------------*/
7635 
lglblockrestart(LGL * lgl)7636 static int lglblockrestart (LGL * lgl) {
7637   const int64_t   actual = ((int64_t)lglcntstk (&lgl->trail)) << 32;
7638   const int64_t smoothed = lgl->stats->tlevel.val;
7639   const int64_t  percent = lgl->opts->restartblocklim.val;
7640   int64_t limit;
7641   int blocking;
7642   if (lgl->stats->confs < lgl->limits->restart.confs) return 0;
7643   if (lgl->stats->confs < lgl->opts->restartblockbound.val) return 0;
7644   assert (percent);
7645   assert (lglvalidint64 (smoothed));
7646   limit = (smoothed < 0 ? -smoothed : smoothed);
7647   assert (limit >= 0);
7648   if (!lglvalidint64 (limit)) return 0;
7649   limit /= 100;
7650   if (INT64MAX/percent < limit) return 0;
7651   limit *= percent;
7652   blocking = (limit < actual);
7653   LOG (2,
7654     "%s restart MACD %g * %.2f = %g %s %g at %lld conflicts",
7655     (blocking ? "blocking" : "not blocking"),
7656     smoothed/(double)(1ll<<32),
7657     lgl->opts->restartblocklim.val/100.0,
7658     limit/(double)(1ll<<32),
7659     blocking ? "<" : ">=",
7660     actual/(double)(1ll<<32),
7661     (LGLL) lgl->stats->confs);
7662   return blocking;
7663 }
7664 
lglana(LGL * lgl)7665 static int lglana (LGL * lgl) {
7666   int open, resolved, tag, lit, uip, r0, r1, other, other2, * p, * q, lidx;
7667   int size, savedsize, resolventsize, level, red, glue, realglue;
7668   int jlevel, mlevel, nmlevel, origsize, redsize, tlevel;
7669   int64_t delta;
7670   int len, * rsn;
7671 #ifdef RESOLVENT
7672   AVar * av;
7673 #endif
7674   if (lgl->mt) return 0;
7675   if (lgl->failed) return 0;
7676   if (!lgl->conf.lit) return 1;
7677   if (!lgl->level) { lglmt (lgl); return 0; }
7678   lglstart (lgl, &lgl->times->analysis);
7679   if (lgl->sweeping) lgl->stats->sweep.confs++;
7680   else assert (!lgl->simp), lgl->stats->confs++;
7681 RESTART:
7682   tlevel = lglcntstk (&lgl->trail);
7683   assert (lgl->conf.lit);
7684   assert (lglmtstk (&lgl->seen));
7685   assert (lglmtstk (&lgl->clause));
7686   assert (lglmtstk (&lgl->resolvent));
7687 #ifndef NDEBUG
7688   if (lgl->opts->check.val > 0) lglchkclnvar (lgl);
7689 #endif
7690   open = 0;
7691   lit = lgl->conf.lit, r0 = lgl->conf.rsn[0], r1 = lgl->conf.rsn[1];
7692   savedsize = resolved = 0;
7693   open += lglpull (lgl, lit);
7694   LOG (2, "starting analysis with reason of literal %d", lit);
7695   for (;;) {
7696     LOGREASON (2, lit, r0, r1, "analyzing");
7697     if (resolved++) {
7698 #ifdef RESOLVENT
7699       if (lglmaintainresolvent (lgl)) {
7700 	LOG (2, "removing %d from resolvent", -lit);
7701 	lglrmstk (&lgl->resolvent, -lit);
7702 	LOGRESOLVENT (3, "resolvent after removing %d is", -lit);
7703       }
7704 #endif
7705     }
7706     assert (lglevel (lgl, lit) == lgl->level);
7707     tag = r0 & MASKCS;
7708     if (tag == BINCS || tag == TRNCS) {
7709       other = r0 >> RMSHFT;
7710       size = lglevel (lgl, other) ? 2 : 1;
7711       if (lglpull (lgl, other)) open++;
7712       if (tag == TRNCS) {
7713 	if (lglevel (lgl, r1)) size++;
7714 	if (lglpull (lgl, r1)) open++;
7715       }
7716     } else {
7717       assert (tag == LRGCS);
7718       red = r0 & REDCS;
7719       p = lglidx2lits (lgl, red, r1);
7720       size = 0;
7721       while ((other = *p++)) {
7722 	if (lglevel (lgl, other)) size++;
7723 	if (lglpull (lgl, other)) open++;
7724       }
7725       if (red) lglbumpnupdatelidx (lgl, r1);
7726     }
7727     LOG (3, "open %d antecendents %d learned %d resolved %d",
7728 	 open-1, size, lglcntstk (&lgl->clause), lglcntstk (&lgl->resolvent));
7729     assert (open > 0);
7730     resolventsize = open + lglcntstk (&lgl->clause);
7731 #ifdef RESOLVENT
7732     LOGRESOLVENT (2, "resolvent");
7733     if (lglmaintainresolvent (lgl))
7734       assert (lglcntstk (&lgl->resolvent) == resolventsize);
7735 #endif
7736     if (lgl->opts->otfs.val &&
7737 	(resolved >= 2) &&
7738 	resolventsize > 1 &&
7739 	(resolventsize < size || (resolved==2 && resolventsize<savedsize))) {
7740       int sl = 0, s0 = 0, s1 = 0, del;
7741       int cl = lgl->conf.lit;
7742       int c0 = lgl->conf.rsn[0];
7743       int c1 = lgl->conf.rsn[1];
7744       assert (resolved >= 2);
7745       del = lit;
7746       if (resolved > 2) ;
7747       else if (resolventsize >= size) del = -lit, lit = cl, r0 = c0, r1 = c1;
7748       else if (resolventsize >= savedsize) ;
7749       else {
7750 	if (r0 & REDCS) {
7751 	  sl = lit, s0 = r0, s1 = r1;
7752 	  del = -lit, lit = cl, r0 = c0, r1 = c1;
7753 	} else sl = cl, s0 = c0, s1 = c1;
7754       }
7755       lgldynstr (lgl, del, lit, r0, r1);
7756       if (sl) lgldynsub (lgl, sl, s0, s1);
7757       lit = lgl->conf.lit;
7758       r0 = lgl->conf.rsn[0];
7759       r1 = lgl->conf.rsn[1];
7760       assert (lglevel (lgl, lit) == lgl->level);
7761       tag = r0 & MASKCS;
7762       if (tag == UNITCS) {
7763 	mlevel = lglevel (lgl, lit);
7764 	nmlevel = 1;
7765 	jlevel = 0;
7766       } else if (tag == BINCS) {
7767 	jlevel = lglevel (lgl, lit);
7768 	other = r0 >> RMSHFT;
7769 	mlevel = lglevel (lgl, other);
7770 	if (jlevel > mlevel) { nmlevel = 1; SWAP (int, mlevel, jlevel); }
7771 	else if (jlevel == mlevel) nmlevel = 2;
7772 	else assert (jlevel < mlevel), nmlevel = 1;
7773       } else if (tag== TRNCS) {
7774 	jlevel = lglevel (lgl, lit);
7775 	other = r0 >> RMSHFT;
7776 	level = lglevel (lgl, other);
7777 	other2 = r1;
7778 	mlevel = lglevel (lgl, other2);
7779 	if (jlevel > mlevel) SWAP (int, jlevel, mlevel);
7780 	if (level > mlevel) SWAP (int, level, mlevel);
7781 	if (level > jlevel) SWAP (int, level, jlevel);
7782 	assert (mlevel >= jlevel);
7783 	assert (jlevel >= level);
7784 	if (mlevel == jlevel) nmlevel = 2 + (jlevel == level);
7785 	else assert (mlevel > jlevel), nmlevel = 1;
7786 	assert (nmlevel == 1 + (mlevel == jlevel) + (mlevel == level));
7787       } else {
7788 	mlevel = lglevel (lgl, lit), nmlevel = 1, jlevel = 0;
7789 	assert (tag == LRGCS);
7790 	red = r0 & REDCS;
7791 	p = lglidx2lits (lgl, red, r1);
7792 	while (jlevel < lgl->level && (other = *p++)) {
7793 	  if (other == lit) continue;
7794 	  assert (other != -lit);
7795 	  level = lglevel (lgl, other);
7796 	  if (level < mlevel) {
7797 	    if (level > jlevel) jlevel = level;
7798 	    continue;
7799 	  }
7800 	  if (level == mlevel) nmlevel++;
7801 	  else {
7802 	    assert (level > mlevel);
7803 	    jlevel = mlevel;
7804 	    mlevel = level;
7805 	    nmlevel = 1;
7806 	  }
7807 	}
7808 	if (red) lglbumpnupdatelidx (lgl, r1);
7809       }
7810       if (nmlevel >= 2) {
7811 	LOG (2, "restarting analysis after on-the-fly strengthening");
7812 	lgl->stats->otfs.restarting++;
7813 	lglclnana (lgl);
7814 	if (lgl->level > mlevel) lglbacktrack (lgl, mlevel);
7815 	goto RESTART;
7816       }
7817       assert (nmlevel == 1);
7818       assert (mlevel > jlevel);
7819       assert (lglevel (lgl, lit) == mlevel);
7820       LOGREASON (2, lit, r0, r1,
7821 	"driving %d at level %d through strengthened", lit, jlevel);
7822       lgl->stats->otfs.driving++;
7823       lglbacktrack (lgl, jlevel);
7824       if (tag == LRGCS && (r0 & REDCS) && (r1 & GLUEMASK) == MAXGLUE) {
7825 	// Note, that 'lit' is unassigned by 'backtrack' above and thus if
7826 	// it's reason is at the end of the MAXGLUE stack, then the reason
7827 	// becomes invalid.  See the corresponding 'assert' in 'lglassign'.
7828 	// Our original incorrect fix to this problem was to simply increase
7829 	// the size of the stack to point after the zero sentinel, which
7830 	// however produces garbage on the MAXGLUE stack and thus we only
7831 	// follow this idea if the reason of 'lit' is exactly after the
7832 	// current end of the MAXGLUE stack. If it starts before the end
7833 	// nothing has to be done.  Otherwise we have to move the reason
7834 	// literals and update the reason.
7835 	p = lglidx2lits (lgl, REDCS, r1);
7836 	if (p > lgl->red[MAXGLUE].top) {
7837 	  rsn = lglrsn (lgl, lit);
7838 	  r1 = lglcntstk (&lgl->red[MAXGLUE]);
7839 	  r1 <<= GLUESHFT;
7840 	  r1 |= MAXGLUE;
7841 	  rsn[1] = r1;
7842 	  for (q = lgl->red[MAXGLUE].top; *p; p++) {
7843 	    assert (q < p);
7844 	    *q++ = *p;
7845 	  }
7846 	  *q++ = 0;
7847 	  lgl->red[MAXGLUE].top = q;
7848 	} else if (p == lgl->red[MAXGLUE].top) {
7849 	  while (*p) { assert (*p < NOTALIT); p++; }
7850 	  if (++p > lgl->red[MAXGLUE].top) lgl->red[MAXGLUE].top = p;
7851 	}
7852       }
7853       lglassign (lgl, lit, r0, r1);
7854       len = INT_MAX;
7855       goto DONE;
7856     }
7857     savedsize = size;
7858     while (!lglmarked (lgl, lit = lglpopstk (&lgl->trail)))
7859       lglunassign (lgl, lit);
7860     lglunassign (lgl, lit);
7861     if (!--open) { uip = -lit; break; }
7862     LOG (2, "analyzing reason of literal %d next", lit);
7863     rsn = lglrsn (lgl, lit);
7864     r0 = rsn[0], r1 = rsn[1];
7865   }
7866   assert (uip);
7867   LOG (2, "adding UIP %d at same level %d to 1st UIP clause",
7868        uip, lgl->level);
7869   lglpushstk (lgl, &lgl->clause, uip);
7870   assert (lglmarked (lgl, uip));
7871 #ifdef RESOLVENT
7872   LOGRESOLVENT (3, "final resolvent before flushing fixed literals");
7873   if (lglmaintainresolvent  (lgl)) {
7874     int * q = lgl->resolvent.start;
7875     for (p = q; p < lgl->resolvent.top; p++)
7876       if (lglevel (lgl, (other = *p)))
7877 	*q++ = other;
7878     lgl->resolvent.top = q;
7879     LOGRESOLVENT (2, "final resolvent after flushing fixed literals");
7880     assert (lglcntstk (&lgl->resolvent) == lglcntstk (&lgl->clause));
7881     for (p = lgl->clause.start; p < lgl->clause.top; p++)
7882       assert (lglavar (lgl, *p)->mark > 0);
7883     for (p = lgl->resolvent.start; p < lgl->resolvent.top; p++) {
7884       av = lglavar (lgl, *p); assert (av->mark > 0); av->mark = -av->mark;
7885     }
7886     for (p = lgl->clause.start; p < lgl->clause.top; p++)
7887       assert (lglavar (lgl, *p)->mark < 0);
7888     for (p = lgl->resolvent.start; p < lgl->resolvent.top; p++) {
7889       av = lglavar (lgl, *p); assert (av->mark < 0); av->mark = -av->mark;
7890     }
7891     lglclnstk (&lgl->resolvent);
7892   }
7893 #endif
7894   lglpushstk (lgl, &lgl->clause, 0);
7895   LOGCLS (2, lgl->clause.start, "1st UIP clause");
7896 
7897   lgldrive (lgl, "preliminary", 0, &glue, 0, &jlevel);
7898   assert (glue == lglcntstk (&lgl->frames));
7899 
7900   origsize = lglcntstk (&lgl->clause) - 1;
7901   assert (glue + 1 <= origsize);
7902   lglbumpseenlits (lgl);
7903   lgl->stats->lits.nonmin += origsize;
7904   redsize = jlevel + 1;
7905   if (origsize == 2) {
7906     lgl->stats->mincls.bin++;
7907     LOGCLS (2, lgl->clause.start, "binary 1st UIP clause not minimized");
7908   } else if (glue + 1 == origsize) {
7909     lgl->stats->mincls.size++;
7910     LOGCLS (2, lgl->clause.start,
7911       "size %d 1st UIP clause with glue %d can not be minimized",
7912       origsize, glue);
7913   } else if (jlevel > 1 &&
7914       lgl->opts->deco.val &&
7915       redsize < 2*origsize/3 &&
7916       glue > lgl->opts->decolim.val) {
7917     assert (origsize > 2);
7918     lgl->stats->mincls.deco++;
7919     lgl->stats->deco.sum.orig += origsize;
7920     lgldeco (lgl, jlevel, uip);
7921     lglpushstk (lgl, &lgl->clause, uip);
7922     lgl->stats->deco.sum.red += lglcntstk (&lgl->clause);
7923     lglpushstk (lgl, &lgl->clause, 0);
7924     LOGCLS (2, lgl->clause.start,
7925       "size %d 1st UIP clause discarded for size %d decision-only clause",
7926       origsize, redsize);
7927   } else {
7928     lglmincls (lgl, uip, glue);
7929     lglredcls (lgl, uip, glue, &jlevel);
7930   }
7931 
7932   lgldrive (lgl, "final", &uip, &glue, &realglue, &jlevel);
7933 
7934   if (uip && lglrsn (lgl, uip)[0]) lgl->stats->uips++;
7935   else if (jlevel + 1 == lgl->level) lgl->stats->decflipped++;
7936 
7937   lglbumpscinc (lgl);
7938 
7939   lglbacktrack (lgl, jlevel);
7940 
7941   len = lglcntstk (&lgl->clause) - 1;
7942   lgl->stats->clauses.glue += glue;
7943   lgl->stats->clauses.realglue += realglue;
7944   lgl->stats->lits.learned += len;
7945   lgl->stats->clauses.learned++;
7946 
7947   if (!lgl->simp) {
7948     LOG (2, "updating AVG glue");
7949     lglupdateavg (lgl, &lgl->stats->avglue, realglue);
7950     LOG (2, "updating MACD restart glue");
7951     lglupdatemacd (lgl, &lgl->stats->glue, realglue);
7952     LOG (2, "updating MACD jump level");
7953     lglupdatemacd (lgl, &lgl->stats->jlevel, jlevel);
7954     LOG (2, "updating EMA trail level");
7955     lglupdatema (lgl, &lgl->stats->tlevel, tlevel, 1);
7956     if (lgl->opts->restartblock.val == 1 && lglblockrestart (lgl)) {
7957       lgl->limits->restart.confs =
7958         lgl->stats->confs + lgl->opts->restartint.val;
7959       lgl->stats->restarts.blocked++;
7960     }
7961 #ifndef NLGLFILES
7962     {
7963       static FILE * macdfile = 0;
7964       if (!macdfile) macdfile = fopen ("/tmp/macd", "w");
7965       fprintf (macdfile,
7966        "%lld %d"
7967        " %g %g %g %g"
7968        " %g %g %g %g"
7969        " %g %g"
7970        " %d %d"
7971        " %g"
7972        "\n",
7973        (LGLL) lgl->stats->confs,
7974        realglue,
7975 
7976        lgl->stats->glue.fast.val/(double)(1ll<<32),
7977        (!lgl->opts->restartforcemode.val ?
7978 	 lgl->stats->avglue.val :
7979 	 lgl->stats->glue.slow.val) /(double)(1ll<<32),
7980        lgl->stats->glue.diff.actual/(double)(1ll<<32),
7981        lgl->stats->glue.diff.smoothed.val/(double)(1ll<<32),
7982 
7983        lgl->stats->jlevel.fast.val/(double)(1ll<<32),
7984        lgl->stats->jlevel.slow.val/(double)(1ll<<32),
7985        lgl->stats->jlevel.diff.actual/(double)(1ll<<32),
7986        lgl->stats->jlevel.diff.smoothed.val/(double)(1ll<<32),
7987 
7988        100.0 * (lgl->stats->agility/(double)(1ll<<32)),
7989        100.0 * lgl->stats->stability.avg.val/(double)(1ll<<32),
7990 
7991        jlevel,
7992        tlevel,
7993 
7994        lgl->stats->tlevel.val/(double)(1ll<<32)
7995 
7996        );
7997 
7998       fflush (macdfile);
7999     }
8000 #endif
8001   }
8002 
8003   lgldrupligaddcls (lgl, REDCS);
8004   lidx = lgladdcls (lgl, REDCS, realglue, 1);
8005 
8006 #ifndef NDEBUG
8007   if (!lglmtstk (&lgl->prevclause)) {
8008     for (p = lgl->prevclause.start, q = lgl->clause.start; *p; p++, q++)
8009       if (*p != *q) break;
8010     assert (*q != *p);
8011   }
8012   lglclnstk (&lgl->prevclause);
8013   for (p = lgl->clause.start; *p; p++)
8014     lglpushstk (lgl, &lgl->prevclause, *p);
8015   lglpushstk (lgl, &lgl->prevclause, 0);
8016   lgl->prevglue = lglscaleglue (lgl, realglue);
8017 #endif
8018   if (lgl->opts->subl.val) {
8019     lglstart (lgl, &lgl->times->subl);
8020     lgl->stats->subl.count++;
8021     lglpopnunmarkstk (lgl, &lgl->seen);
8022     size = lglcntstk (&lgl->clause) - 1;
8023     if (size > 1) {
8024       unsigned sig = 0;
8025       p = lgl->clause.start;
8026       while ((lit = *p++)) {
8027        sig |= (1u << (lglulit (lit) & 31));
8028        lglmark (lgl, lit);
8029       }
8030       q = lgl->learned.start;
8031       for (p = q; p < lgl->learned.top; p += 3) {
8032        int olidx = p[0], osize = p[1];
8033        unsigned osig = (unsigned) p[2];
8034        if (olidx < 0) continue;
8035        if (osize <= size ||
8036            (sig & ~osig) ||
8037            !lglsubl (lgl, olidx, size, glue))
8038          *q++ = olidx, *q++ = osize, *q++ = (int) osig;
8039       }
8040       lgl->learned.top = q;
8041       if (lidx && (lidx & GLUEMASK) < MAXGLUE) {
8042        lgl->stats->subl.cands++;
8043        lglpushstk (lgl, &lgl->learned, lidx);
8044        lglpushstk (lgl, &lgl->learned, size);
8045        lglpushstk (lgl, &lgl->learned, (int) sig);
8046        if (lglcntstk (&lgl->learned) / 3 > lgl->opts->subl.val) {
8047          q = lgl->learned.start;
8048          for (p = q + 3; p < lgl->learned.top; p++) *q++ = *p;
8049          lgl->learned.top = q;
8050        }
8051       }
8052       p = lgl->clause.start;
8053       while ((lit = *p++)) lglunmark (lgl, lit);
8054     }
8055     lglstop (lgl);
8056   }
8057 
8058   if (lgl->cbs &&
8059       lgl->cbs->cls.produce.fun &&
8060       glue <= lgl->opts->synclsglue.val &&
8061       lglcntstk (&lgl->clause) - 1 <= lgl->opts->synclslen.val) {
8062     assert (lglmtstk (&lgl->eclause));
8063     for (p = lgl->clause.start; *p; p++)
8064       lglpushstk (lgl, &lgl->eclause, lglexport (lgl, *p));
8065     lglpushstk (lgl, &lgl->eclause, 0);
8066     LOGCLS (2, lgl->eclause.start,
8067       "exporting external redundant glue %d length %d clause",
8068       glue, lglcntstk (&lgl->clause) -1);
8069     lgl->stats->sync.cls.produced++;
8070     lgl->cbs->cls.produce.fun (lgl->cbs->cls.produce.state,
8071                                lgl->eclause.start, glue);
8072     lglclnstk (&lgl->eclause);
8073   }
8074 
8075 DONE:
8076 
8077   if (lgl->simp) goto SKIPNOSIMP;
8078 
8079   if (len == 2) {
8080     lglrep (lgl, 2, 'b');
8081     lgl->stats->bins++;
8082   }
8083 
8084   if (len == 3) {
8085     lglrep (lgl, 2, 't');
8086     lgl->stats->trns++;
8087   }
8088 
8089   delta = lgl->stats->confs - lgl->confatlastit;
8090   LOG (1, "iteration delta %d", delta);
8091   lglupdatemacd (lgl, &lgl->stats->its.avg, delta);
8092   if (len == 1) {
8093     int delay = lgl->opts->simpitdelay.val;
8094     lgl->confatlastit = lgl->stats->confs;
8095     lgl->stats->its.count++;
8096     lglrep (lgl, 1, 'i');
8097     if (delta > 0) delay /= delta;
8098     if (delay > 0) {
8099       lgl->limits->simp.confs += delay;
8100       LOG (1, "delaying simplification by %d conflicts", delay);
8101     }
8102   }
8103   LOG (1, "iteration interval average %.0f", lglitavg (lgl));
8104 
8105 SKIPNOSIMP:
8106 
8107   lglclnana (lgl);
8108   lglstop (lgl);
8109 
8110   return 1;
8111 }
8112 
lglincrestart(LGL * lgl)8113 static void lglincrestart (LGL * lgl) {
8114   Stats * s = lgl->stats;
8115   int64_t delta;
8116   int pen = 0;
8117   delta = lgl->opts->restartint.val;
8118   if (lgl->opts->restartfixed.val) goto NOPEN;
8119   LOG (2, "initial next restarting delta %lld", (LGLL) delta);
8120   if (lgl->opts->restartpen1.val && s->confs > 500000 &&
8121       (!s->its.count || s->confs/s->its.count > 100000)) {
8122     lglprt (lgl, 2,
8123       "[restart-%lld] few iterations after 500000 conflicts",
8124       (LGLL) lgl->stats->restarts.count);
8125     pen++;
8126   }
8127   if (lgl->opts->restartpen2.val && s->confs > 50000 &&
8128       (!s->bins || s->confs/s->bins > 10000)) {
8129     lglprt (lgl, 2,
8130       "[restart-%lld] few binaries after 50000 conflicts",
8131       (LGLL) lgl->stats->restarts.count);
8132     pen++;
8133   }
8134   if (lgl->opts->restartpen3.val && s->confs > 5000 &&
8135       (!s->trns || s->confs/s->trns > 1000)) {
8136     lglprt (lgl, 2,
8137       "[restart-%lld] few ternaries after 5000 conflicts",
8138       (LGLL) lgl->stats->restarts.count);
8139     pen++;
8140   }
8141   if (lgl->opts->restartpenstab.val && s->confs > 50000) {
8142     int64_t glue = (s->glue.slow.val >> 32);
8143     if (glue < 20) {
8144       int64_t stab = s->stability.avg.val;
8145       int peninc = 0;
8146       assert (stab <= (1ll << 32));
8147       stab *= 100000;
8148       stab >>= 32;
8149       if (stab > 98000) peninc++;
8150       if (stab > 99000) peninc++;
8151       if (stab > 99500) peninc++;
8152       if (stab > 99750) peninc++;
8153       if (stab > 99875) peninc++;
8154       pen += peninc;
8155       lglprt (lgl, 2,
8156 	"[restart-%lld] "
8157 	"stability %lld glue %d after 50000 conflicts (penalty increase %d)",
8158 	(LGLL) lgl->stats->restarts.count, stab, glue, peninc);
8159     }
8160   }
8161 NOPEN:
8162   delta <<= pen;
8163   lgl->stats->restarts.delta.pen += pen;
8164   lgl->stats->restarts.delta.delta += delta;
8165   lgl->stats->restarts.delta.count++;
8166   lgl->limits->restart.confs = lgl->stats->confs + delta;
8167   lglprt (lgl, 2,
8168     "[restart-%lld] next restart %lld delta %lld (penalty %d)",
8169     (LGLL) lgl->stats->restarts.count,
8170     (LGLL) lgl->limits->restart.confs, (LGLL) delta, pen);
8171   lglrep (lgl, 2, 'R');
8172 }
8173 
lglqueueflush(LGL * lgl)8174 static void lglqueueflush (LGL * lgl) {
8175   int before, mt, after, nonfree;
8176   const int * p, * start;
8177   int * q, lit, found;
8178   QVar * qv;
8179   lgl->stats->queue.flushed++;
8180   found = nonfree = mt = 0;
8181   before = lglcntstk (&lgl->queue.stk);
8182   assert (lgl->mt <= before);
8183   start = q = lgl->queue.stk.start;
8184   for (p = q; p < lgl->queue.stk.top; p++) {
8185     if (!(lit = *p)) {
8186       mt++;
8187       continue;
8188     }
8189     qv = lglqvar (lgl, lit);
8190     assert (qv->enqueued);
8191     assert (qv->pos == (p - start));
8192     if (!lglisfree (lgl, lit)) {
8193       qv->enqueued = 0;
8194       qv->pos = -1;
8195       nonfree++;
8196     } else {
8197       qv->pos = (q - start);
8198       if (!found && lgl->queue.next >= (p - start))
8199 	found = 1, lgl->queue.next = qv->pos;
8200       *q++ = lit;
8201     }
8202   }
8203   lgl->queue.stk.top = q;
8204   if (!found) lgl->queue.next = lglcntstk (&lgl->queue.stk) - 1;
8205   assert (mt == lgl->queue.mt);
8206   lgl->queue.mt = 0;
8207   after = lglcntstk (&lgl->queue.stk);
8208   assert (before == after + nonfree + mt);
8209   lglprt (lgl, 2,
8210     "[flush-queue-%d] flushed %d = %d mt + %d nonfree (resized %d to %d)",
8211     lgl->stats->queue.flushed, mt + nonfree, mt, nonfree, before, after);
8212 }
8213 
lglnextdecision(LGL * lgl,int updatestats)8214 static int lglnextdecision (LGL * lgl, int updatestats) {
8215   int res = 0;
8216 #ifndef NDEBUG
8217   int start;
8218 #endif
8219   QVar * qv;
8220   if (!lgl->unassigned) return 0;
8221   lglstart (lgl, &lgl->times->decide);
8222   lglstart (lgl, &lgl->times->heapdecision);
8223   while (!res && !lglmtstk (&lgl->dsched)) {
8224     int next = lgltopdsched (lgl);
8225     if (!lglval (lgl, next) && lglisfree (lgl, next)) res = next;
8226     else lglpopdsched (lgl);
8227   }
8228   lglstop (lgl);
8229   if (!res) {
8230     lglstart (lgl, &lgl->times->queuedecision);
8231     assert (!lglmtstk (&lgl->queue.stk));
8232     if (lglcntstk (&lgl->queue.stk) < 2*lgl->queue.mt) lglqueueflush (lgl);
8233 #ifndef NDEBUG
8234     start = lgl->queue.next;
8235 #endif
8236     for (;;) {
8237       res = lglpeek (&lgl->queue.stk, lgl->queue.next);
8238       if (res) {
8239 	qv = lglqvar (lgl, res);
8240 	assert (qv->enqueued);
8241 	assert (qv->pos == lgl->queue.next);
8242 	if (!lglisfree (lgl, res)) {
8243 	  lglpoke (&lgl->queue.stk, lgl->queue.next, 0);
8244 	  lgl->queue.mt++;
8245 	  qv->enqueued = 0;
8246 	  qv->pos = -1;
8247 	} else if (!lglval (lgl, res)) {
8248 	  if (updatestats) lgl->stats->qdecs++;
8249 	  break;
8250 	}
8251       }
8252       lgl->queue.next--;
8253       if (lgl->queue.next < 0)
8254 	lgl->queue.next = lglcntstk (&lgl->queue.stk) - 1;
8255       ASSERT (lgl->queue.next != start);
8256     }
8257     lglstop (lgl);
8258   } else if (updatestats) lgl->stats->hdecs++;
8259   assert (res);
8260   lglstop (lgl);
8261   LOG (2, "next decision would be %d", res);
8262   return res;
8263 }
8264 
lglreusetrail(LGL * lgl)8265 static int lglreusetrail (LGL * lgl) {
8266   int next = 0, res = 0, prev, level;
8267   const Ctr * p;
8268   if (!lgl->opts->reusetrail.val) return 0;
8269   if (!(next = lglnextdecision (lgl, 0))) return 0;
8270   for (p = lgl->control.start + 1; p < lgl->control.top; p++) {
8271     prev = p->decision;
8272     assert (lgldecision (lgl, prev));
8273     if (!lglassumption (lgl, prev) && lgldcmp (lgl, prev, next) < 0) break;
8274     level = lglevel (lgl, prev);
8275     assert (level == p - lgl->control.start);
8276     assert (res + 1 == level);
8277     res = level;
8278   }
8279   if (res)
8280     lglprt (lgl, 3,
8281       "[reuse-trail] reusing level %d from current level %d",
8282       res, lgl->level);
8283   else
8284     lglprt (lgl, 3,
8285       "[reuse-trail] can not reuse any level from current level %d",
8286       lgl->level);
8287   return res;
8288 }
8289 
lglrestart(LGL * lgl)8290 static void lglrestart (LGL * lgl) {
8291   int level, kept;
8292   assert (lgl->opts->restart.val);
8293   lglstart (lgl, &lgl->times->restart);
8294   level = lglreusetrail (lgl);
8295   if (level < lgl->alevel) level = lgl->alevel;
8296   else if (level > lgl->alevel) {
8297     kept = (100*level) / lgl->level;
8298     lgl->stats->restarts.kept.sum += kept;
8299     lgl->stats->restarts.kept.count++;
8300   }
8301   if (level < lgl->level) {
8302     int oldlevel = lgl->level;
8303     lglbacktrack (lgl, level);
8304     LOG (2, "setting stability level to %d", oldlevel);
8305     lgl->stats->stability.level = oldlevel;
8306     assert (lgl->stats->stability.level > 0);
8307     lgl->stats->stability.changed = 0;
8308     lgl->stats->restarts.count++;
8309   } else {
8310     lgl->stats->restarts.reused++;
8311     lgl->stats->restarts.skipped++;
8312   }
8313   lglincrestart (lgl);
8314   lglstop (lgl);
8315 }
8316 
lgldefrag(LGL * lgl)8317 static void lgldefrag (LGL * lgl) {
8318   int * wchs, nwchs, i, idx, bit, ldsize, size, offset, * start, * q, * end;
8319   const int * p, * eow, * w;
8320   HTS * hts;
8321   lglstart (lgl, &lgl->times->defrag);
8322   lgl->stats->defrags++;
8323   nwchs = lglcntstk (&lgl->wchs->stk);
8324   NEW (wchs, nwchs);
8325   memcpy (wchs, lgl->wchs->stk.start, nwchs * sizeof *wchs);
8326   for (i = 0; i < MAXLDFW; i++) lgl->wchs->start[i] = INT_MAX;
8327   lgl->wchs->free = 0;
8328   start = lgl->wchs->stk.start;
8329   assert (nwchs >= 1);
8330   assert (start[0] == INT_MAX);
8331   offset = 1;
8332   for (idx = 2; idx < lgl->nvars; idx++)
8333   for (bit = 0; bit <= 1; bit++) {
8334     hts = lgl->dvars[idx].hts + bit;
8335     if (!hts->offset) { assert (!hts->count); continue; }
8336     ldsize = lglceild (hts->count);
8337     size = (1 << ldsize);
8338     assert (size >= hts->count);
8339     w = wchs + hts->offset;
8340     hts->offset = offset;
8341     eow = w + hts->count;
8342     q = start + offset;
8343     for (p = w; p < eow; p++) *q++ = *p;
8344     offset += size;
8345     end = start + offset;
8346     while (q < end) *q++ = 0;
8347   }
8348   DEL (wchs, nwchs);
8349   q = start + offset;
8350   *q++ = INT_MAX;
8351   assert (q <= lgl->wchs->stk.top);
8352   lgl->wchs->stk.top = q;
8353   lglfitstk (lgl, &lgl->wchs->stk);
8354   lgl->limits->dfg = lgl->stats->pshwchs + lgl->opts->defragint.val;
8355   lglrep (lgl, 2, 'F');
8356   lglstop (lgl);
8357 }
8358 
lgldis(LGL * lgl)8359 static void lgldis (LGL * lgl) {
8360   int blit, nblit, tag, red, * p, * q, * eow, * w;
8361   int idx, sign, lit, other, other2;
8362   Stk bins, trns;
8363   Val val, val2;
8364   HTS * hts;
8365   assert (!lgl->level);
8366   CLR (bins); CLR (trns);
8367   for (idx = 2; idx < lgl->nvars; idx++)
8368     for (sign = -1; sign <= 1; sign += 2) {
8369       lit = idx * sign;
8370       hts = lglhts (lgl, lit);
8371       if (!hts->offset) continue;
8372       val = lglval (lgl, lit);
8373       assert (hts->count > 0);
8374       if (lgl->mt || val || lgliselim (lgl, lit)) {
8375 	lglshrinkhts (lgl, hts, 0);
8376 	continue;
8377       }
8378       assert (lglisfree (lgl, lit));
8379       assert (lglmtstk (&bins));
8380       assert (lglmtstk (&trns));
8381       w = lglhts2wchs (lgl, hts);
8382       eow = w + hts->count;
8383       for (p = w; p < eow; p++) {
8384 	blit = *p;
8385 	tag = blit & MASKCS;
8386 	red = blit & REDCS;
8387 	if (tag == OCCS) continue;
8388 	if (tag == TRNCS || tag == LRGCS) p++;
8389 	if (tag == LRGCS) continue;
8390 	other = blit >> RMSHFT;
8391 	val = lglval (lgl, other);
8392 	if (val > 0) continue;
8393 	if (lgliselim (lgl, other)) continue;
8394 	if (tag == BINCS) {
8395 	  assert (!val);
8396 	  lglpushstk (lgl, &bins, blit);
8397 	  continue;
8398 	}
8399 	assert (tag == TRNCS);
8400 	other2 = *p;
8401 	val2 = lglval (lgl, other2);
8402 	if (val2 > 0) continue;
8403 	if (lgliselim (lgl, other2)) continue;
8404 	if (val < 0) {
8405 	  assert (val < 0 && !val2);
8406 	  nblit = red | RMSHFTLIT (other2) | BINCS;
8407 	  lglpushstk (lgl, &bins, nblit);
8408 	  if (abs (lit) < abs (other2)) {
8409 	    lgldrupligaddclsarg (lgl, REDCS, lit, other2, 0);
8410 	    lgldrupligdelclsarg (lgl, lit, other, other2, 0);
8411 	  }
8412 	  continue;
8413 	}
8414 	if (val2 < 0) {
8415 	  assert (!val && val2 < 0);
8416 	  nblit = red | RMSHFTLIT (other) | BINCS;
8417 	  lglpushstk (lgl, &bins, nblit);
8418 	  if (abs (lit) < abs (other)) {
8419 	    lgldrupligaddclsarg (lgl, REDCS, lit, other, 0);
8420 	    lgldrupligdelclsarg (lgl, lit, other, other2, 0);
8421 	  }
8422 	  continue;
8423 	}
8424 	assert (!val && !val2);
8425 	lglpushstk (lgl, &trns, blit);
8426 	lglpushstk (lgl, &trns, other2);
8427       }
8428       q = w;
8429       for (p = bins.start; p != bins.top; p++) *q++ = *p;
8430       for (p = trns.start; p != trns.top; p++) *q++ = *p;
8431       lglshrinkhts (lgl, hts, q - w);
8432       lglclnstk (&bins);
8433       lglclnstk (&trns);
8434     }
8435   lglrelstk (lgl, &bins);
8436   lglrelstk (lgl, &trns);
8437   lglrelstk (lgl, &lgl->learned);
8438 }
8439 
lglcmphase(LGL * lgl,int a,int b)8440 static int lglcmphase (LGL * lgl, int a, int b) {
8441   return lgliphase (lgl, b) - lgliphase (lgl, a);
8442 }
8443 
8444 #define LGLCMPHASE(A,B) lglcmphase (lgl, *(A), *(B))
8445 
lglconnaux(LGL * lgl,int glue)8446 static void lglconnaux (LGL * lgl, int glue) {
8447   int lit, collect, lidx, size, origsize, red, act;
8448   const int druplig = lgl->opts->druplig.val;
8449   const int * p, * c, * start, * top;
8450   Stk * stk, saved;
8451   int * q, * d;
8452   Val val;
8453   if (glue >= 0) {
8454     assert (glue < MAXGLUE);
8455     red = REDCS;
8456     stk = lgl->red + glue;
8457   } else red = 0, stk = &lgl->irr;
8458   start = q = stk->start;
8459   top = stk->top;
8460   CLR (saved);
8461   for (c = q; c < top; c = p + 1) {
8462     act = *c;
8463     if (act == REMOVED) {
8464       for (p = c + 1; p < top && *p == REMOVED; p++)
8465 	;
8466       assert (p >= top || *p < NOTALIT || lglisact (*p));
8467       p--;
8468       continue;
8469     }
8470     if (lglisact (act)) assert (glue >= 0), *q++ = *c++;
8471     else assert (glue < 0), act = -1;
8472     d = q;
8473     collect = 0;
8474     lglclnstk (&saved);
8475     for (p = c; assert (p < top), (lit = *p); p++) {
8476       assert (lit < NOTALIT);
8477       if (druplig) lglpushstk (lgl, &saved, lit);
8478       if (collect) continue;
8479       val = lglval (lgl, lit);
8480       if (lgliselim (lgl, lit)) {
8481 	assert (lgl->eliminating || lgl->blocking);
8482 	collect = 1;
8483       } else if (val > 0) collect = 1;
8484       else if (!val) *q++ = lit;
8485     }
8486 
8487     size = q - d;
8488     origsize = p - c;
8489     assert (!druplig || origsize == lglcntstk (&saved));
8490     assert (size <= origsize);
8491 
8492     if (druplig && !collect && size > 1 && size < origsize)
8493       *q = 0, lgldrupligaddclsaux (lgl, REDCS, d);
8494 
8495     if (collect || p == c + 1) {
8496       q = d - (act >= 0);
8497     } else if (!size) {
8498       q = d - (act >= 0);
8499       if (!lgl->mt) {
8500 	LOG (1, "empty clause during connection garbage collection phase");
8501 	lglmt (lgl);
8502       }
8503     } else if (size == 1) {
8504       q = d - (act >= 0);
8505       LOG (1, "unit during garbage collection");
8506       lglunit (lgl, d[0]);
8507     } else if (size == 2) {
8508       q = d - (act >= 0);
8509       lglwchbin (lgl, d[0], d[1], red);
8510       lglwchbin (lgl, d[1], d[0], red);
8511     } else if (size == 3) {
8512       q = d - (act >= 0);
8513       lglwchtrn (lgl, d[0], d[1], d[2], red);
8514       lglwchtrn (lgl, d[1], d[0], d[2], red);
8515       lglwchtrn (lgl, d[2], d[0], d[1], red);
8516     } else {
8517       assert (size > 3);
8518       if (lgl->opts->sortlits.val) SORT (int, d, size, LGLCMPHASE);
8519       *q++ = 0;
8520       lidx = d - start;
8521       if (red) {
8522 	assert (lidx <= MAXREDLIDX);
8523 	lidx <<= GLUESHFT;
8524 	assert (0 <= lidx);
8525 	lidx |= glue;
8526       }
8527       (void) lglwchlrg (lgl, d[0], d[1], red, lidx);
8528       (void) lglwchlrg (lgl, d[1], d[0], red, lidx);
8529     }
8530     if (druplig && (collect || origsize != size)) {
8531       lglpushstk (lgl, &saved, 0);
8532       lgldrupligdelclsaux (lgl, saved.start);
8533     }
8534   }
8535   stk->top = q;
8536   lglrelstk (lgl, &saved);
8537 }
8538 
lglconsavedbin(LGL * lgl)8539 static void lglconsavedbin (LGL * lgl) {
8540   int satisfied, eliminated, size, val0, val1, nunits = 0, nmt = 0;
8541   const int druplig = lgl->opts->druplig.val, * p;
8542   assert (lgl->rmredbintrn);
8543   for (p = lgl->saved.bin.start; p < lgl->saved.bin.top; p += 2) {
8544     assert (p + 1 < lgl->saved.bin.top);
8545     satisfied = eliminated = val0 = val1 = 0;
8546          if ((val0 = lglval (lgl, p[0])) > 0) satisfied = 1;
8547     else if ((val1 = lglval (lgl, p[1])) > 0) satisfied = 1;
8548     else if (lgliselim (lgl, p[0])) eliminated = 1;
8549     else if (lgliselim (lgl, p[1])) eliminated = 1;
8550     assert (!eliminated || lgl->eliminating || lgl->blocking);
8551     if (satisfied || eliminated) size = INT_MAX;
8552     else if (val0 < 0 && val1 < 0) {
8553       nmt++;
8554       size = 0;
8555       if (!lgl->mt) {
8556 	LOG (1, "empty clause connecting saved binary clauses");
8557 	lglmt (lgl);
8558       }
8559     } else if (!val0 && val1 < 0) {
8560       size = 1;
8561       LOG (1, "unit during connecting saved binary clauses");
8562       lglunit (lgl, p[0]);
8563       nunits++;
8564     } else if (val0 < 0 && !val1) {
8565       size = 1;
8566       LOG (1, "unit during connecting saved binary clauses");
8567       lglunit (lgl, p[1]);
8568       nunits++;
8569     } else {
8570       assert (!val0), assert (!val1);
8571       size = 2;
8572       lglwchbin (lgl, p[0], p[1], REDCS);
8573       lglwchbin (lgl, p[1], p[0], REDCS);
8574     }
8575     if (druplig && (satisfied || eliminated || size < 2))
8576       lgldrupligdelclsarg (lgl, p[0], p[1], 0);
8577   }
8578   lglprt (lgl,
8579     2 - (nmt || nunits),
8580     "[gc-%d] reconnected %d binary clauses (produced %d empty %d units)",
8581     lgl->stats->gcs, lglcntstk (&lgl->saved.bin)/2, nmt, nunits);
8582   lglrelstk (lgl, &lgl->saved.bin);
8583 }
8584 
lglconsavedtrn(LGL * lgl)8585 static void lglconsavedtrn (LGL * lgl) {
8586   const int druplig = lgl->opts->druplig.val, * p;
8587   int satisfied, eliminated, size, val0, val1, val2;
8588   int nmt = 0, nunits = 0, nbins = 0;
8589   assert (lgl->rmredbintrn);
8590   for (p = lgl->saved.trn.start; p < lgl->saved.trn.top; p += 3) {
8591     assert (p + 1 < lgl->saved.trn.top);
8592     satisfied = eliminated = val0 = val1 = val2 = 0;
8593          if ((val0 = lglval (lgl, p[0])) > 0) satisfied = 1;
8594     else if ((val1 = lglval (lgl, p[1])) > 0) satisfied = 1;
8595     else if ((val2 = lglval (lgl, p[2])) > 0) satisfied = 1;
8596     else if (lgliselim (lgl, p[0])) eliminated = 1;
8597     else if (lgliselim (lgl, p[1])) eliminated = 1;
8598     else if (lgliselim (lgl, p[2])) eliminated = 1;
8599     assert (!eliminated || lgl->eliminating || lgl->blocking);
8600     if (satisfied || eliminated) size = INT_MAX;
8601     else if (val0 < 0 && val1 < 0 && val2 < 0) {
8602       nmt++;
8603       size = 0;
8604       if (!lgl->mt) {
8605 	LOG (1, "empty clause connecting saved ternary clauses");
8606 	lglmt (lgl);
8607       }
8608     } else if (!val0 && val1 < 0 && val2 < 0) {
8609       size = 1;
8610       LOG (1, "unit during connecing saved ternary clauses");
8611       lglunit (lgl, p[0]);
8612       nunits++;
8613     } else if (val0 < 0 && !val1 && val2 < 0) {
8614       size = 1;
8615       LOG (1, "unit during connecing saved ternary clauses");
8616       lglunit (lgl, p[1]);
8617       nunits++;
8618     } else if (val0 < 0 && val1 < 0 && !val2) {
8619       size = 1;
8620       LOG (1, "unit during connecing saved ternary clauses");
8621       lglunit (lgl, p[2]);
8622       nunits++;
8623     } else if (!val0 && !val1 && val2 < 0) {
8624       size = 2;
8625       nbins++;
8626       lglwchbin (lgl, p[0], p[1], REDCS);
8627       lglwchbin (lgl, p[1], p[0], REDCS);
8628       if (druplig) lgldrupligaddclsarg (lgl, REDCS, p[0], p[1], 0);
8629     } else if (!val0 && val1 < 0 && !val2) {
8630       size = 2;
8631       nbins++;
8632       lglwchbin (lgl, p[0], p[2], REDCS);
8633       lglwchbin (lgl, p[2], p[0], REDCS);
8634       if (druplig) lgldrupligaddclsarg (lgl, REDCS, p[0], p[2], 0);
8635     } else if (val0 < 0 && !val1 && !val2) {
8636       size = 2;
8637       nbins++;
8638       lglwchbin (lgl, p[1], p[2], REDCS);
8639       lglwchbin (lgl, p[2], p[1], REDCS);
8640       if (druplig) lgldrupligaddclsarg (lgl, REDCS, p[1], p[2], 0);
8641     } else {
8642       size = 3;
8643       assert (!val0), assert (!val1), assert (!val2);
8644       lglwchtrn (lgl, p[0], p[1], p[2], REDCS);
8645       lglwchtrn (lgl, p[1], p[0], p[2], REDCS);
8646       lglwchtrn (lgl, p[2], p[0], p[1], REDCS);
8647     }
8648     if (druplig && (satisfied || eliminated || size < 3))
8649       lgldrupligdelclsarg (lgl, p[0], p[1], p[2], 0);
8650   }
8651   lglprt (lgl,
8652     2 - (nmt || nunits), // || nbins), // NOTE would be too verbose ...
8653     "[gc-%d] reconnected %d ternary clauses "
8654     " (produced %d empty %d units %d binary)",
8655     lgl->stats->gcs, lglcntstk (&lgl->saved.trn)/3, nmt, nunits, nbins);
8656   lglrelstk (lgl, &lgl->saved.trn);
8657 }
8658 
lglfullyconnected(LGL * lgl)8659 static void lglfullyconnected (LGL * lgl) {
8660   if (!lgl->notfullyconnected) return;
8661   LOG (1, "switching to fully connected mode");
8662   lgl->notfullyconnected  = 0;
8663 }
8664 
lglcon(LGL * lgl)8665 static void lglcon (LGL * lgl) {
8666   int glue;
8667   for (glue = -1; glue < MAXGLUE; glue++) lglconnaux (lgl, glue);
8668   lglfullyconnected (lgl);
8669 }
8670 
lglconsaved(LGL * lgl)8671 static void lglconsaved (LGL * lgl) {
8672   if (lgl->rmredbintrn) {
8673     lglconsavedbin (lgl);
8674     lglconsavedtrn (lgl);
8675     lgl->rmredbintrn = 0;
8676     if (!lgl->mt && !lglbcpcomplete (lgl)) {
8677       lglfullyconnected (lgl);
8678       if (!lglbcp (lgl)) {
8679 	LOG (1, "empty clause generated propagating reconnected unit");
8680 	lglmt (lgl);
8681       }
8682     }
8683   } else
8684     assert (lglmtstk (&lgl->saved.bin)),
8685     assert (lglmtstk (&lgl->saved.trn));
8686 }
8687 
lglcount(LGL * lgl)8688 static void lglcount (LGL * lgl) {
8689   int idx, sign, lit, tag, blit, red, other, other2, glue, count;
8690   const int * p, * w, * c, * eow;
8691   HTS * hts;
8692   Stk * lir;
8693   lgl->stats->irr.clauses.cur = 0;
8694   lgl->stats->irr.lits.cur = 0;
8695   lgl->stats->red.bin = 0;
8696   lgl->stats->red.trn = 0;
8697   lgl->stats->red.lrg = 0;
8698   for (idx = 2; idx < lgl->nvars; idx++)
8699     for (sign = -1; sign <= 1; sign += 2) {
8700       lit = sign * idx;
8701       hts = lglhts (lgl, lit);
8702       if (!hts->offset) continue;
8703       w = lglhts2wchs (lgl, hts);
8704       eow = w + hts->count;
8705       for (p = w; p < eow; p++) {
8706 	blit = *p;
8707 	red = blit & REDCS;
8708 	tag = blit & MASKCS;
8709 	if (tag == LRGCS || tag == TRNCS) p++;
8710 	if (tag == LRGCS) continue;
8711 	assert (tag == BINCS || tag == TRNCS);
8712 	other = blit >> RMSHFT;
8713 	assert (abs (other) != abs (lit));
8714 	if (abs (lit) >= abs (other)) continue;
8715 	assert (2 == BINCS && 3 == TRNCS);
8716 	if (tag == TRNCS) {
8717 	  other2 = *p;
8718 	  assert (abs (other2) != abs (lit));
8719 	  assert (abs (other2) != abs (other));
8720 	  if (abs (lit) >= abs (other2)) continue;
8721 	}
8722 	if (!red) {
8723 	  lgl->stats->irr.clauses.cur++;
8724 	  if (tag == BINCS) lgl->stats->irr.lits.cur += 2;
8725 	  else assert (tag == TRNCS), lgl->stats->irr.lits.cur += 3;
8726 	} else if (tag == BINCS) lgl->stats->red.bin++;
8727 	else assert (tag == TRNCS), lgl->stats->red.trn++;
8728       }
8729     }
8730   assert (lgl->stats->red.bin >= 0 && lgl->stats->red.trn >= 0);
8731   for (c = lgl->irr.start; c < lgl->irr.top; c = p + 1) {
8732     if (*(p = c) >= REMOVED) continue;
8733     while (*p) p++;
8734     lgl->stats->irr.lits.cur += p - c;
8735     lgl->stats->irr.clauses.cur++;
8736   }
8737   LOG (1, "counted %d irredundant clauses with %d literals",
8738        lgl->stats->irr.clauses.cur, lgl->stats->irr.lits.cur);
8739   for (glue = 0; glue < MAXGLUE; glue++) {
8740     lir = lgl->red + glue;
8741     count = 0;
8742     for (c = lir->start; c < lir->top; c++)
8743       if (!*c) count++;
8744     if (count)
8745       LOG (1, "counted %d redundant clauses with glue %d", count, glue);
8746     lgl->stats->red.lrg += count;
8747     lgl->stats->lir[glue].clauses = count;
8748   }
8749   assert (lgl->stats->red.lrg >= 0);
8750   if (lgl->stats->red.bin)
8751     LOG (1, "counted %d binary redundant clauses altogether",
8752 	 lgl->stats->red.bin);
8753   if (lgl->stats->red.trn)
8754     LOG (1, "counted %d ternary redundant clauses altogether",
8755 	 lgl->stats->red.trn);
8756   if (lgl->stats->red.lrg)
8757     LOG (1, "counted %d large redundant clauses altogether",
8758 	 lgl->stats->red.lrg);
8759 }
8760 
lglilit(int ulit)8761 static int lglilit (int ulit) {
8762   int res = ulit/2;
8763   assert (res >= 1);
8764   if (ulit & 1) res = -res;
8765   return res;
8766 }
8767 
lgljwh(LGL * lgl)8768 static void lgljwh (LGL * lgl) {
8769   int idx, sign, lit, tag, blit, other, other2, red, size, glue;
8770   const int *p, * w, * eow, * c;
8771   Val val, tmp, tmp2;
8772   HTS * hts;
8773   Stk * s;
8774   Flt inc;
8775   CLN (lgl->jwh, 2*lgl->nvars);
8776   for (idx = 2; idx < lgl->nvars; idx++)
8777     for (sign = -1; sign <= 1; sign += 2) {
8778       lit = sign * idx;
8779       val = lglval (lgl, lit);
8780       if (val > 0) continue;
8781       hts = lglhts (lgl, lit);
8782       if (!hts->offset) continue;
8783       w = lglhts2wchs (lgl, hts);
8784       eow = w + hts->count;
8785       for (p = w; p < eow; p++) {
8786 	blit = *p;
8787 	tag = blit & MASKCS;
8788 	if (tag == TRNCS || tag == LRGCS) p++;
8789 	if (tag == LRGCS) continue;
8790 	red = blit & REDCS;
8791 	if (!lgl->opts->jwhred.val && red) continue;
8792 	if (lgl->opts->jwhred.val == 2 && !red) continue;
8793 	other = blit >> RMSHFT;
8794 	if (abs (other) < abs (lit)) continue;
8795 	tmp = lglval (lgl, other);
8796 	if (tmp > 0) continue;
8797 	if (tag == BINCS) {
8798 	  assert (!tmp);
8799 	  inc = lglflt (-2, 1);
8800 	  lglincjwh (lgl, lit, inc);
8801 	  lglincjwh (lgl, other, inc);
8802 	} else {
8803 	  assert (tag == TRNCS);
8804 	  other2 = *p;
8805 	  if (abs (other2) < abs (lit)) continue;
8806 	  tmp2 = lglval (lgl, other2);
8807 	  if (tmp2 > 0) continue;
8808 	  assert ((val > 0) + (tmp > 0) + (tmp2 > 0) == 0);
8809 	  assert ((val < 0) + (tmp < 0) + (tmp2 < 0) <= 1);
8810 	  size = 3 + val + tmp + tmp2;
8811 	  assert (2 <= size && size <= 3);
8812 	  inc = lglflt (-size, 1);
8813 	  if (!val) lglincjwh (lgl, lit, inc);
8814 	  if (!tmp) lglincjwh (lgl, other, inc);
8815 	  if (!tmp2) lglincjwh (lgl, other2, inc);
8816 	}
8817       }
8818     }
8819   for (glue = -1; glue < MAXGLUE; glue++) {
8820     if (!lgl->opts->jwhred.val && glue >= 0) continue;
8821     if (lgl->opts->jwhred.val == 2 && glue < 0) continue;
8822     if (glue < 0) s = &lgl->irr;
8823     else s = &lgl->red[glue];
8824     for (c = s->start; c < s->top; c = p + 1) {
8825       if (*(p = c) >= NOTALIT) continue;
8826       val = -1;
8827       size = 0;
8828       while ((other = *p)) {
8829 	tmp = lglval (lgl, other);
8830 	if (tmp > val) val = tmp;
8831 	if (!tmp) size++;
8832 	p++;
8833       }
8834       if (val > 0) continue;
8835       inc = lglflt (-size, 1);
8836       for (p = c; (other = *p); p++)
8837 	if (!lglval (lgl, other))
8838 	  lglincjwh (lgl, other, inc);
8839     }
8840   }
8841 }
8842 
lglis(LGL * lgl)8843 static int * lglis (LGL * lgl) {
8844   int idx, sign, lit, tag, blit, other, other2, red, * res;
8845   const int *p, * w, * eow, * c;
8846   Val val, tmp, tmp2;
8847   HTS * hts;
8848   Stk * s;
8849   NEW (res, 2*lgl->nvars);
8850   res += lgl->nvars;
8851   for (idx = 2; idx < lgl->nvars; idx++)
8852     for (sign = -1; sign <= 1; sign += 2) {
8853       lit = sign * idx;
8854       val = lglval (lgl, lit);
8855       if (val > 0) continue;
8856       hts = lglhts (lgl, lit);
8857       if (!hts->offset) continue;
8858       w = lglhts2wchs (lgl, hts);
8859       eow = w + hts->count;
8860       for (p = w; p < eow; p++) {
8861 	blit = *p;
8862 	tag = blit & MASKCS;
8863 	if (tag == TRNCS || tag == LRGCS) p++;
8864 	if (tag == LRGCS) continue;
8865 	red = blit & REDCS;
8866 	if (red) continue;
8867 	other = blit >> RMSHFT;
8868 	if (abs (other) < abs (lit)) continue;
8869 	tmp = lglval (lgl, other);
8870 	if (tmp > 0) continue;
8871 	if (tag == BINCS) {
8872 	  assert (!tmp);
8873 	  res[lit]++,
8874 	  res[other]++;
8875 	} else {
8876 	  assert (tag == TRNCS);
8877 	  other2 = *p;
8878 	  if (abs (other2) < abs (lit)) continue;
8879 	  tmp2 = lglval (lgl, other2);
8880 	  if (tmp2 > 0) continue;
8881 	  assert ((val > 0) + (tmp > 0) + (tmp2 > 0) == 0);
8882 	  assert ((val < 0) + (tmp < 0) + (tmp2 < 0) <= 1);
8883 	  if (!val) res[lit]++;
8884 	  if (!tmp) res[other]++;
8885 	  if (!tmp2) res[other2]++;
8886 	}
8887       }
8888     }
8889   s = &lgl->irr;
8890   for (c = s->start; c < s->top; c = p + 1) {
8891     p = c;
8892     if (*p >= NOTALIT) continue;
8893     val = -1;
8894     while ((other = *p)) {
8895       tmp = lglval (lgl, other);
8896       if (tmp > val) val = tmp;
8897       p++;
8898     }
8899     if (val > 0) continue;
8900     for (p = c; (other = *p); p++)
8901       if (!lglval (lgl, other))
8902 	res[other]++;
8903   }
8904   return res;
8905 }
8906 
lglsetjwhbias(LGL * lgl,int idx)8907 static int lglsetjwhbias (LGL * lgl, int idx) {
8908   AVar * av = lglavar (lgl, idx);
8909   Flt pos, neg;
8910   int bias;
8911   idx = abs (idx);
8912   pos = lgl->jwh[lglulit (idx)];
8913   neg = lgl->jwh[lglulit (-idx)];
8914   if (av->phase) return av->phase;
8915   bias = (pos > neg) ? 1 : -1;
8916   if (av->bias == bias) return bias;
8917   av->bias = bias;
8918   lgl->stats->phase.set++;
8919   if (bias > 0) lgl->stats->phase.pos++; else lgl->stats->phase.neg++;
8920   LOG (1, "JW bias %d (pos %s, neg %s)",
8921        bias * idx, lglflt2str (lgl, pos), lglflt2str (lgl, neg));
8922   return bias;
8923 }
8924 
lglsetbias(LGL * lgl,int idx,int bias)8925 static void lglsetbias (LGL * lgl, int idx, int bias) {
8926   AVar * av = lglavar (lgl, idx);
8927   assert (abs (bias) == 1);
8928   if (av->phase) return;
8929   av->bias = bias;
8930   lgl->stats->phase.set++;
8931   if (bias > 0) lgl->stats->phase.pos++; else lgl->stats->phase.neg++;
8932   LOG (1, "set bias %d explicitly", bias * idx);
8933 }
8934 
lglsetallphases(LGL * lgl)8935 static void lglsetallphases (LGL * lgl) {
8936   int res = 1, idx;
8937   for (idx = 2; res && idx < lgl->nvars; idx++)
8938     res = (!lglisfree (lgl, idx) || lglavar (lgl, idx)->phase);
8939   lgl->allphaseset = res;
8940 }
8941 
lglflushphases(LGL * lgl)8942 static void lglflushphases (LGL * lgl) {
8943   int idx, flushed = 0;
8944   AVar * av;
8945   for (idx = 2; idx < lgl->nvars; idx++) {
8946     if (!lglisfree (lgl, idx)) continue;
8947     av = lglavar (lgl, idx);
8948     av->phase = 0;
8949     flushed++;
8950   }
8951   lglprt (lgl, 1, "[flushphases] %d phases reset", flushed);
8952   lgl->allphaseset = !flushed;
8953   lgl->flushphases = 0;
8954 }
8955 
lgluckyphase(LGL * lgl)8956 static int lgluckyphase (LGL * lgl) {
8957   int pos = 0, neg = 0, lit, idx, count = 0, res = 0;
8958   int negrest, posrest;
8959   const int * p, * c;
8960   for (c = lgl->irr.start; c < lgl->irr.top; c = p + 1) {
8961     int foundpos = 0, foundneg = 0;
8962     if (*(p = c) >= NOTALIT) continue;
8963     while ((lit = *p)) {
8964       if (lit > 0) foundpos = 1;
8965       if (lit < 0) foundneg = 1;
8966       p++;
8967     }
8968     if (foundpos) pos++;
8969     if (foundneg) neg++;
8970     count++;
8971   }
8972   for (idx = 2; idx < lgl->nvars; idx++) {
8973     HTS * hts = lglhts (lgl, idx);
8974     const int * p, * w, * eow;
8975     w = lglhts2wchs (lgl, hts);
8976     eow = w + hts->count;
8977     for (p = w; p < eow; p++) {
8978       int blit = *p, red, other;
8979       int tag = blit & MASKCS;
8980       if (tag == TRNCS || tag == LRGCS) p++;
8981       if (tag == LRGCS) continue;
8982       red = blit & REDCS;
8983       if (red) continue;
8984       other = blit >> RMSHFT;
8985       if (abs (other) < idx) continue;
8986       if (tag == TRNCS) {
8987 	int other2 = *p;
8988 	if (abs (other2) < idx) continue;
8989 	if (other < 0 || other2 < 0) neg++;
8990       } else if (other < 0) neg++;
8991       count++;
8992       pos++;
8993     }
8994     hts = lglhts (lgl, -idx);
8995     w = lglhts2wchs (lgl, hts);
8996     eow = w + hts->count;
8997     for (p = w; p < eow; p++) {
8998       int blit = *p, red, other;
8999       int tag = blit & MASKCS;
9000       if (tag == TRNCS || tag == LRGCS) p++;
9001       if (tag == LRGCS) continue;
9002       red = blit & REDCS;
9003       if (red) continue;
9004       other = blit >> RMSHFT;
9005       if (abs (other) < idx) continue;
9006       if (tag == TRNCS) {
9007 	int other2 = *p;
9008 	if (abs (other2) < idx) continue;
9009 	if (other > 0 || other2 > 0) pos++;
9010       } else if (other > 0) pos++;
9011       count++;
9012       neg++;
9013     }
9014   }
9015   assert (count >= neg);
9016   negrest = count - neg;
9017   assert (count >= pos);
9018   posrest = count - pos;
9019   assert (count == lgl->stats->irr.clauses.cur);
9020   lglprt (lgl, 1,
9021     "[phase-count-%d] %d negative %.1f%% of %d except %d %.1f%%",
9022     lgl->stats->phase.count,
9023     neg, lglpcnt (neg, count), count, negrest, lglpcnt (negrest, count));
9024   lglprt (lgl, 1,
9025     "[phase-count-%d] %d positive %.1f%% of %d except %d %.1f%%",
9026     lgl->stats->phase.count,
9027     pos, lglpcnt (pos, count), count, posrest, lglpcnt (posrest, count));
9028   if (neg >= count) {
9029     res = -1;
9030     lglprt (lgl, 1,
9031       "[phase-count-%d] all clauses contain a negative literal",
9032       lgl->stats->phase.count);
9033   } else if (pos >= count) {
9034     res = 1;
9035     lglprt (lgl, 1,
9036       "[phase-count-%d] all clauses contain a positive literal",
9037       lgl->stats->phase.count);
9038   } else if (lgl->stats->phase.count <= lgl->opts->phaseluckmaxround.val) {
9039     int lim = lgl->opts->phaselucklim.val * (count / 1000);
9040     int fac = lgl->opts->phaseluckfactor.val;
9041     if (negrest <= lim &&
9042 	negrest <= posrest &&
9043 	posrest/fac >= negrest/100) {
9044       res = -1;
9045       lglprt (lgl, 1,
9046 	"[phase-count-%d] less non-negative clauses %d than limit %d (%.1f%%)",
9047 	lgl->stats->phase.count,
9048 	negrest, lim, lgl->opts->phaselucklim.val / 10.0);
9049       lglprt (lgl, 1,
9050 	"[phase-count-%d] non-pos/non-neg = %d/%d = %.2f >= %.2f = %d/100",
9051 	lgl->stats->phase.count,
9052 	posrest, negrest, posrest/(double)negrest, fac/100.0, fac);
9053     } else if (posrest <= lim &&
9054                posrest <= negrest &&
9055                negrest/fac >= posrest/100) {
9056       res = 1;
9057       lglprt (lgl, 1,
9058 	"[phase-count-%d] less non-positive clauses %d than limit %d (%.1f%%)",
9059 	lgl->stats->phase.count,
9060 	posrest, lim, lgl->opts->phaselucklim.val / 1000.0);
9061       lglprt (lgl, 1,
9062 	"[phase-count-%d] non-neg/non-pos = %d/%d = %.2f >= %.2f = %d/100",
9063 	lgl->stats->phase.count,
9064 	negrest, posrest, negrest/(double)posrest, fac/100.0, fac);
9065     }
9066   } else
9067       lglprt (lgl, 1,
9068 	"[phase-count-%d] skipping relative phase luck test",
9069         lgl->stats->phase.count);
9070   if (res)
9071     lglprt (lgl, 1,
9072       "[lucky-phase-%d] forcing lucky phase %d",
9073       lgl->stats->phase.count,
9074       res);
9075   return res;
9076 }
9077 
lglphase(LGL * lgl)9078 static void lglphase (LGL * lgl) {
9079   int64_t set = lgl->stats->phase.set;
9080   int64_t pos = lgl->stats->phase.pos;
9081   int64_t neg = lgl->stats->phase.neg;
9082   int idx, lucky;
9083   lglstart (lgl, &lgl->times->phase);
9084   if (lgl->flushphases) lglflushphases (lgl);
9085   if (lgl->opts->phase.val) goto DONE;
9086   lglsetallphases (lgl);
9087   if (lgl->allphaseset) goto DONE;
9088   lgl->stats->phase.count++;
9089   lgljwh (lgl);
9090   if ((lucky = lgluckyphase (lgl)))
9091     for (idx = 2; idx < lgl->nvars; idx++)
9092       lglsetbias (lgl, idx, lucky);
9093   else
9094     for (idx = 2; idx < lgl->nvars; idx++)
9095       lglsetjwhbias (lgl, idx);
9096   set = lgl->stats->phase.set - set;
9097   pos = lgl->stats->phase.pos - pos;
9098   neg = lgl->stats->phase.neg - neg;
9099   lglprt (lgl, 1,
9100      "[phase-%d] phase bias: %lld positive %.0f%%, %lld negative %.0f%%",
9101      lgl->stats->phase.count,
9102      (LGLL) pos, lglpcnt (pos, set),
9103      (LGLL) neg, lglpcnt (neg, set));
9104 DONE:
9105   lglstop (lgl);
9106 }
9107 
lglmaplit(int * map,int lit)9108 static int lglmaplit (int * map, int lit) {
9109   return map [ abs (lit) ] * lglsgn (lit);
9110 }
9111 
lglmapstk(LGL * lgl,int * map,Stk * lits)9112 static void lglmapstk (LGL * lgl, int * map, Stk * lits) {
9113   int * p, * eol;
9114   eol = lits->top;
9115   for (p = lits->start; p < eol; p++)
9116     *p = lglmaplit (map, *p);
9117 }
9118 
lglmapqueue(LGL * lgl,int * map)9119 static void lglmapqueue (LGL * lgl, int * map) {
9120   int idx, found, * q, src, dst;
9121   const int * p, * start;
9122   QVar * qv;
9123   for (idx = 2; idx < lgl->nvars; idx++) {
9124     qv = lglqvar (lgl, idx);
9125     if (!qv->enqueued) continue;
9126     qv->pos = -1;
9127   }
9128   found = 0;
9129   start = q = lgl->queue.stk.start;
9130   for (p = q; p < lgl->queue.stk.top; p++) {
9131     if (!(src = *p)) continue;
9132     assert (1 < src);
9133     dst = lglmaplit (map, src);
9134     if (dst < 0) dst = -dst;
9135     if (dst <= 1) continue;
9136     qv = lglqvar (lgl, dst);
9137     if (!qv->enqueued) continue;
9138     if (qv->pos >= 0) continue;
9139     qv->pos = (q - start);
9140     assert (qv->pos >= 0);
9141     if (!found && lgl->queue.next >= (p - start))
9142       found = 1, lgl->queue.next = qv->pos;
9143     *q++ = dst;
9144   }
9145   for (idx = 2; idx < lgl->nvars; idx++) {
9146     qv = lglqvar (lgl, idx);
9147     if (!qv->enqueued) continue;
9148     if (qv->pos >= 0) continue;
9149     assert (q < lgl->queue.stk.top);
9150     qv->pos = (q - start);
9151     assert (qv->pos >= 0);
9152     *q++ = idx;
9153   }
9154   lgl->queue.stk.top = q;
9155   lglfitstk (lgl, &lgl->queue.stk);
9156   if (!found) lgl->queue.next = lglcntstk (&lgl->queue.stk) - 1;
9157   lgl->queue.mt = 0;
9158 }
9159 
lglmapglue(LGL * lgl,int * map,Stk * lits)9160 static void lglmapglue (LGL * lgl, int * map, Stk * lits) {
9161   int * p, * eol;
9162   eol = lits->top;
9163   for (p = lits->start; p < eol; p++)
9164     if (!lglisact (*p)) *p = lglmaplit (map, *p);
9165 }
9166 
lglmaplits(LGL * lgl,int * map)9167 static void lglmaplits (LGL * lgl, int * map) {
9168   int glue;
9169   lglmapstk (lgl, map, &lgl->irr);
9170   for (glue = 0; glue < MAXGLUE; glue++)
9171     lglmapglue (lgl, map, &lgl->red[glue]);
9172 }
9173 
lglmapvars(LGL * lgl,int * map,int nvars)9174 static void lglmapvars (LGL * lgl, int * map, int nvars) {
9175   int i, oldnvars = lgl->nvars, sign, udst, idst, usrc, isrc;
9176   DVar * dvars;
9177   QVar * qvars;
9178   AVar * avars;
9179   Val * vals;
9180   int * i2e;
9181   Flt * jwh;
9182 
9183   if (nvars > 2) assert (nvars <= oldnvars);
9184   else nvars = 0;
9185 
9186   DEL (lgl->doms, 2*lgl->szvars);
9187   NEW (lgl->doms, 2*nvars);
9188 
9189   NEW (vals, nvars);
9190   for (i = 2; i < oldnvars; i++)
9191     if (lglisfree (lgl, i))
9192       vals[map[i]] = lgl->vals[i];
9193   DEL (lgl->vals, lgl->szvars);
9194   lgl->vals = vals;
9195 
9196   NEW (i2e, nvars);
9197   for (i = 2; i < oldnvars; i++)
9198     if (lglisfree (lgl, i))
9199       i2e[map[i]] = lgl->i2e[i];
9200   DEL (lgl->i2e, lgl->szvars);
9201   lgl->i2e = i2e;
9202 
9203   NEW (dvars, nvars);
9204   for (i = 2; i < oldnvars; i++)
9205     if (lglisfree (lgl, i))
9206       dvars[map[i]] = lgl->dvars[i];
9207   DEL (lgl->dvars, lgl->szvars);
9208   lgl->dvars = dvars;
9209 
9210   NEW (qvars, nvars);
9211   for (i = 2; i < oldnvars; i++)
9212     if (lglisfree (lgl, i))
9213       qvars[map[i]] = lgl->qvars[i];
9214   DEL (lgl->qvars, lgl->szvars);
9215   lgl->qvars = qvars;
9216 
9217   NEW (jwh, 2*nvars);
9218   for (i = 2; i < oldnvars; i++)
9219     if (lglisfree (lgl, i))
9220       for (sign = -1; sign <= 1; sign += 2) {
9221 	  isrc = sign * i;
9222 	  idst = sign * map[i];
9223 	  usrc = lglulit (isrc);
9224 	  udst = lglulit (idst);
9225 	  jwh[udst] = lgladdflt (jwh[udst], lgl->jwh[usrc]);
9226 	}
9227   DEL (lgl->jwh, 2*lgl->szvars);
9228   lgl->jwh = jwh;
9229 
9230   NEW (avars, nvars);
9231   for (i = 2; i < oldnvars; i++)
9232     if (lglisfree (lgl, i))
9233       avars[map[i]] = lgl->avars[i];
9234   DEL (lgl->avars, lgl->szvars);
9235   lgl->avars = avars;              // Last since 'lglisfree' depends on it !!!
9236 
9237   lgl->nvars = lgl->szvars = nvars;
9238   lgl->stats->fixed.current = 0;
9239 }
9240 
lglmaphts(LGL * lgl,int * map)9241 static void lglmaphts (LGL * lgl, int * map) {
9242   int idx, sign, lit, * w, *eow, * p, other, other2, blit, tag, red;
9243   int newblit, newother, newother2;
9244   HTS * hts;
9245   for (idx = 2; idx < lgl->nvars; idx++)
9246     for (sign = -1; sign <= 1; sign += 2) {
9247       lit = sign * idx;
9248       hts = lglhts (lgl, lit);
9249       if (!hts->count) continue;
9250       w = lglhts2wchs (lgl, hts);
9251       eow = w + hts->count;
9252       for (p = w; p < eow; p++) {
9253 	blit = *p;
9254 	tag = blit & MASKCS;
9255 	assert (tag == BINCS || tag == TRNCS || tag == LRGCS);
9256 	red = blit & REDCS;
9257 	other = blit >> RMSHFT;
9258 	newother = lglmaplit (map, other);
9259 	newblit = RMSHFTLIT (newother) | tag | red;
9260 	*p = newblit;
9261 	if (tag == BINCS) continue;
9262 	other2 = *++p;
9263 	if (tag == LRGCS) continue;
9264 	assert (tag == TRNCS);
9265 	newother2 = lglmaplit (map, other2);
9266 	*p = newother2;
9267       }
9268     }
9269 }
9270 
lglmaptrail(LGL * lgl,int * map)9271 static void lglmaptrail (LGL * lgl, int * map) {
9272   int * p, * q, src, dst;
9273   for (p = lgl->trail.start; p < lgl->trail.top; p++)
9274     if (lglevel (lgl, *p) > 0) break;
9275   for (q = lgl->trail.start; p < lgl->trail.top; p++) {
9276     src = *p;
9277     assert (lglevel (lgl, src) > 0);
9278     dst = lglmaplit (map, src);
9279     *q++ = dst;
9280   }
9281   lgl->trail.top = q;
9282   lgl->flushed = lgl->next2 = lgl->next = lglcntstk (&lgl->trail);
9283 }
9284 
lglptrjmp(int * repr,int max,int start)9285 static int lglptrjmp (int * repr, int max, int start) {
9286 #ifndef NDEBUG
9287   int prev = 0, count = 0;
9288 #endif
9289   int next, idx, res, sgn, tmp;
9290   assert (repr);
9291   next = start;
9292   do {
9293     res = next;
9294     idx = abs (res);
9295     assert (idx <= max);
9296     sgn = lglsgn (res);
9297     next = repr[idx];
9298     next *= sgn;
9299 #ifndef NDEBUG
9300     if (prev || next) assert (prev != next);
9301     prev = res;
9302     assert (count <= max);
9303 #endif
9304   } while (next);
9305   tmp = start;
9306   while (tmp != res) {
9307     idx = abs (tmp), sgn = lglsgn (tmp);
9308     next = repr[idx] * sgn;
9309     repr[idx] = sgn * res;
9310     tmp = next;
9311   }
9312   return res;
9313 }
9314 
lglirepr(LGL * lgl,int lit)9315 static int lglirepr (LGL * lgl, int lit) {
9316   assert (lgl->repr);
9317   return lglptrjmp (lgl->repr, lgl->nvars - 1, lit);
9318 }
9319 
lglmapext(LGL * lgl,int * map)9320 static void lglmapext (LGL * lgl, int * map) {
9321   int eidx, ilit, mlit;
9322   Ext * ext;
9323   for (eidx = 1; eidx <= lgl->maxext; eidx++) (void) lglerepr (lgl, eidx);
9324   for (eidx = 1; eidx <= lgl->maxext; eidx++) {
9325     ext = lgl->ext + eidx;
9326     if (!ext->imported) continue;
9327     if (ext->equiv) {
9328       LOG (3, "mapping external %d to equivalent external %d",
9329 	   eidx, ext->repr);
9330       continue;
9331     }
9332     ilit = ext->repr;
9333     mlit = lglmaplit (map, ilit);
9334     LOG (3, "mapping external %d to internal %d", eidx, mlit);
9335     ext->repr = mlit;
9336   }
9337 }
9338 
lglsignedmark(LGL * lgl,int lit)9339 static void lglsignedmark (LGL * lgl, int lit) {
9340   AVar * av = lglavar (lgl, lit);
9341   int bit = 1 << (lit < 0);
9342   if (av->mark & bit) return;
9343   av->mark |= bit;
9344 }
9345 
lglsignedunmark(LGL * lgl,int lit)9346 static void lglsignedunmark (LGL * lgl, int lit) {
9347   AVar * av = lglavar (lgl, lit);
9348   int bit = 1 << (lit < 0);
9349   if (!(av->mark & bit)) return;
9350   av->mark &= ~bit;
9351 }
9352 
lglsignedmarked(LGL * lgl,int lit)9353 static int lglsignedmarked (LGL * lgl, int lit) {
9354   AVar * av = lglavar (lgl, lit);
9355   int bit = 1 << (lit < 0);
9356   return av->mark & bit;
9357 }
9358 
lglmapass(LGL * lgl,int * map)9359 static void lglmapass (LGL * lgl, int * map) {
9360   int * p, * q, iass, mass, flushed;
9361   unsigned bit;
9362   AVar * av;
9363   if (abs (lgl->failed) != 1) lgl->failed = lglmaplit (map, lgl->failed);
9364   for (p = q = lgl->assume.start; p < lgl->assume.top; p++) {
9365     iass = *p;
9366     mass = lglmaplit (map, iass);
9367     if (mass == 1) continue;
9368     if (mass == -1) {
9369       if (lgl->failed != -1) {
9370 #ifndef NDEBUG
9371 	int * r;
9372 	for (r = lgl->eassume.start; r < lgl->eassume.top; r++)
9373 	  if (lglimport (lgl, *r) == -1) break;
9374 	assert (r < lgl->eassume.top);
9375 #endif
9376 	LOG (2, "enforcing a failed assumption");
9377 	lgl->failed = -1;
9378       }
9379       continue;
9380     }
9381     LOG (2, "mapping previous internal assumption %d to %d", iass, mass);
9382     av = lglavar (lgl, mass);
9383     bit = 1u << (mass < 0);
9384     if (!(av->assumed & bit)) {
9385       LOG (2, "assuming new representative %d instead of %d", mass, iass);
9386       av->assumed |= bit;
9387     }
9388     *q++ = mass;
9389   }
9390   lgl->assume.top = q;
9391   flushed = 0;
9392   for (p = q = lgl->assume.start; p < lgl->assume.top; p++) {
9393     iass = *p;
9394     if (lglsignedmarked (lgl, iass)) { flushed++; continue; }
9395     lglsignedmark (lgl, iass);
9396     *q++ = iass;
9397   }
9398   lgl->assume.top = q;
9399   for (p = lgl->assume.start; p < lgl->assume.top; p++) {
9400     iass = *p;
9401     assert (lglsignedmarked (lgl, iass));
9402     lglsignedunmark (lgl, iass);
9403   }
9404   if (flushed)
9405     LOG (2, "flushed %d duplicated internal assumptions", flushed);
9406 }
9407 
lglmaplkhdscore(LGL * lgl,int * map,int oldnvars)9408 static void lglmaplkhdscore (LGL * lgl, int * map, int oldnvars) {
9409   LKHD * oldlkhdscore = lgl->tlk->lkhd, score;
9410   int idx, src, sign, dst;
9411   NEW (lgl->tlk->lkhd, 2*lgl->nvars);
9412   lgl->tlk->lkhd += lgl->nvars;
9413   for (idx = oldnvars-1; idx >= 2; idx--) {
9414     for (sign = -1; sign <= 1; sign += 2) {
9415       src = sign * idx;
9416       dst = lglmaplit (map, src);
9417       if (abs (dst) <= 1) continue;
9418       score = oldlkhdscore[src];
9419       LOG (2, "mapping look-ahead score %s of %d as score of %d",
9420 	   lglflt2str (lgl, score), src, dst);
9421       lgl->tlk->lkhd[dst] = score;
9422     }
9423   }
9424   oldlkhdscore -= oldnvars;
9425   DEL (oldlkhdscore, 2*oldnvars);
9426 }
9427 
lglmapsize(LGL * lgl)9428 static int lglmapsize (LGL * lgl) {
9429   int size = 0, idx;
9430   for (idx = 2; idx < lgl->nvars; idx++)
9431     if (lglisfree (lgl, idx)) size++;
9432   LOG (1, "mapping %d remaining variables", size);
9433   return size;
9434 }
9435 
lglmapnonequiv(LGL * lgl,int * map,int size)9436 static void lglmapnonequiv (LGL * lgl, int * map, int size) {
9437   int count = 0, idx;
9438   AVar * av;
9439   Val val;
9440   map[0] = 0, map[1] = 1;
9441   for (idx = 2; idx < lgl->nvars; idx++) {
9442     if (map[idx]) continue;
9443     av = lglavar (lgl, idx);
9444     if (av->type == FREEVAR) {
9445       assert (idx > 0);
9446       if (map[idx]) { assert (map[idx] < idx); continue; }
9447       LOG (3, "mapping free %d to %d", idx, count + 2);
9448       map[idx] = count + 2;
9449       count++;
9450     } else if (av->type == EQUIVAR) {
9451       assert (lgl->repr);
9452       assert (!map[idx]);
9453     } else if (av->type == FIXEDVAR) {
9454       val = lgl->vals[idx];
9455       assert (val);
9456       LOG (3, "mapping assigned %d to %d", idx, (int) val);
9457       map[idx] = val;
9458     } else {
9459       assert (av->type == ELIMVAR);
9460       assert (!lglifrozen (lgl, idx));
9461       map[idx] = 0;
9462     }
9463   }
9464   assert (count == size);
9465 }
9466 
lglmapequiv(LGL * lgl,int * map)9467 static void lglmapequiv (LGL * lgl, int * map) {
9468   int idx, repr, dst;
9469   AVar * av;
9470   for (idx = 2; idx < lgl->nvars; idx++) {
9471     if (map[idx]) continue;
9472     av = lglavar (lgl, idx);
9473     if (av->type == ELIMVAR) continue;
9474     assert (av->type == EQUIVAR);
9475     assert (lgl->repr);
9476     assert (!map[idx]);
9477     repr = lglirepr (lgl, idx);
9478     assert (repr != idx);
9479     assert (map[abs (repr)]);
9480     dst = lglmaplit (map, repr);
9481     LOG (3, "mapping equivalent %d to %d", idx, dst);
9482     map[idx] = dst;
9483   }
9484 }
9485 
lglsteps(LGL * lgl)9486 static int64_t lglsteps (LGL * lgl) {
9487   int64_t res = lgl->stats->steps;
9488 #ifndef NDEBUG
9489   // Note, this would be bulky and slow ...
9490   int64_t steps = 0;
9491   steps += lgl->stats->bca.steps;
9492   steps += lgl->stats->blk.steps;
9493   steps += lgl->stats->card.steps;
9494   steps += lgl->stats->cce.steps;
9495   steps += lgl->stats->elm.copies;
9496   steps += lgl->stats->elm.resolutions;
9497   steps += lgl->stats->elm.steps;
9498   steps += lgl->stats->gauss.steps.elim;
9499   steps += lgl->stats->gauss.steps.extr;
9500   steps += lgl->stats->prb.basic.steps;
9501   steps += lgl->stats->prb.simple.steps;
9502   steps += lgl->stats->prb.treelook.steps;
9503   steps += lgl->stats->props.lkhd;
9504   steps += lgl->stats->props.search;
9505   steps += lgl->stats->props.simp;
9506   steps += lgl->stats->sweep.steps;
9507   steps += lgl->stats->trd.steps;
9508   steps += lgl->stats->ternres.steps;
9509   steps += lgl->stats->unhd.steps;
9510   assert (steps == res);
9511 #endif
9512   return res;
9513 }
9514 
lgltrep(LGL * lgl)9515 static void lgltrep (LGL * lgl) {
9516   int64_t steps, i;
9517   double t;
9518   if (!lgl->opts->trep.val) return;
9519   if (lgl->opts->verbose.val) return;
9520   steps = lglsteps (lgl);
9521   if (steps < lgl->limits->trep.steps) return;
9522   lgl->limits->trep.steps += lgl->opts->trepint.val;
9523   t = lgl->opts->abstime.val ? lglgetime (lgl) : lglsec (lgl);
9524   if (t < lgl->limits->trep.time) return;
9525   lglrep (lgl, 0, (lgl->simp ? 'P' : 'S'));
9526   i = lgl->limits->trep.time;
9527   do {
9528          if (!i)         i = 1;
9529     else if (i == 1)     i = 2;
9530     else if (i == 2)     i = 5;
9531     else if (i < 10)     i = 10;
9532     else if (i < 60)     i += 10;
9533     else if (i < 300)    i += 60;
9534     else if (i < 900)    i += 300;
9535     else if (i < 7200)   i += 900;
9536     else                 i += 3600;
9537   } while (i < t);
9538   lgl->limits->trep.time = i;
9539 }
9540 
lglterminate(LGL * lgl)9541 static int lglterminate (LGL * lgl) {
9542   int64_t steps;
9543   int res;
9544   lgltrep (lgl);
9545   if (!lgl->cbs) return 0;
9546   if (!lgl->cbs->term.fun) return 0;
9547   if (lgl->cbs->term.done) return 1;
9548   steps = lglsteps (lgl);
9549   if (steps < lgl->limits->term.steps) return 0;
9550   res = lgl->cbs->term.fun (lgl->cbs->term.state);
9551   if (res) lgl->cbs->term.done = res;
9552   else lgl->limits->term.steps = steps + lgl->opts->termint.val;
9553   return  res;
9554 }
9555 
lglmap(LGL * lgl)9556 static void lglmap (LGL * lgl) {
9557   int size, * map, oldnvars, mapsize;
9558 #ifndef NDEBUG
9559   lglrelstk (lgl, &lgl->prevclause);
9560 #endif
9561   lglrelstk (lgl, &lgl->promote);
9562   assert (!lgl->level);
9563   lgldreschedule (lgl);
9564   size = lglmapsize (lgl);
9565   oldnvars = lgl->nvars;
9566   mapsize = lglmax (oldnvars, 2);
9567   NEW (map, mapsize);
9568   lglmapnonequiv (lgl, map, size);
9569   lglmapequiv (lgl, map);
9570   lglmaptrail (lgl, map);
9571   lglmapvars (lgl, map, size + 2);
9572   lglmaplits (lgl, map);
9573   lglmapstk (lgl, map, &lgl->dsched);
9574   lglmapqueue (lgl, map);
9575   lglmapext (lgl, map);
9576   lglmapass (lgl, map);
9577   if (lgl->treelooking && lgl->tlk && lgl->tlk->lkhd)
9578     lglmaplkhdscore (lgl, map, oldnvars);
9579   assert (lglmtstk (&lgl->clause));
9580   lglmaphts (lgl, map);
9581   DEL (map, mapsize);
9582   if (lgl->repr) DEL (lgl->repr, oldnvars);
9583   lgl->unassigned = size;
9584   lgldreschedule (lgl);
9585 #ifndef NLGLDRUPLIG
9586   lgl->drupligunit = 0;
9587 #endif
9588 }
9589 
lglgcnotnecessary(LGL * lgl)9590 static int lglgcnotnecessary (LGL * lgl) {
9591   if (lgl->forcegc) return 0;
9592   if (lgl->notfullyconnected) return 0;
9593   return lgl->stats->fixed.sum <= lgl->limits->gc.fixed;
9594 }
9595 
lglcompact(LGL * lgl)9596 static void lglcompact (LGL * lgl) {
9597   int glue;
9598   lglfitstk (lgl, &lgl->assume);
9599 #ifndef NDEBUG
9600   lglfitstk (lgl, &lgl->prevclause);
9601 #endif
9602   lglfitstk (lgl, &lgl->clause);
9603   lglfitstk (lgl, &lgl->eclause);
9604   lglfitstk (lgl, &lgl->dsched);
9605   lglfitstk (lgl, &lgl->queue.stk);
9606   lglfitstk (lgl, &lgl->eassume);
9607   lglfitstk (lgl, &lgl->extend);
9608   lglfitstk (lgl, &lgl->learned);
9609   lglfitstk (lgl, &lgl->frames);
9610   lglfitstk (lgl, &lgl->promote);
9611 #ifndef NCHKSOL
9612   lglfitstk (lgl, &lgl->orig);
9613 #endif
9614   lglfitstk (lgl, &lgl->trail);
9615   lgldefrag (lgl);
9616   lglfitstk (lgl, &lgl->wchs->stk);
9617 
9618   lglfitstk (lgl, &lgl->irr);
9619   for (glue = 0; glue <= MAXGLUE; glue++)
9620     lglfitlir (lgl, lgl->red + glue);
9621   lglrelstk (lgl, &lgl->lcaseen);
9622   lglrelstk (lgl, &lgl->resolvent);
9623   lglrelstk (lgl, &lgl->minstk);
9624   lglrelstk (lgl, &lgl->poisoned);
9625   lglrelstk (lgl, &lgl->seen);
9626   lglrelstk (lgl, &lgl->esched);
9627   lglrelstk (lgl, &lgl->saved.bin);
9628   lglrelstk (lgl, &lgl->saved.trn);
9629 }
9630 
lglgc(LGL * lgl)9631 static void lglgc (LGL * lgl) {
9632   if (lgl->mt) return;
9633   lglchkred (lgl);
9634   if (lglgcnotnecessary (lgl)) return;
9635   lglstart (lgl, &lgl->times->gc);
9636   lglchkbcpclean (lgl, "gc");
9637   lglrep (lgl, 2, 'g');
9638   lgl->stats->gcs++;
9639   if (lgl->level > 0) lglbacktrack (lgl, 0);
9640   lglconsaved (lgl);
9641   do {			// Note, need to go into loop even if 'lgl->mt'!
9642     lgldis (lgl);
9643     lglcon (lgl);
9644     if (lgl->mt) break;
9645     if (lglbcpcomplete (lgl)) break;
9646     if (lglbcp (lgl)) continue;
9647     assert (!lgl->mt);
9648     LOG (1, "empty clause after propagating garbage collection unit");
9649     lglmt (lgl);
9650   } while (!lgl->mt);
9651   lglcount (lgl);
9652   lglmap (lgl);
9653 
9654   lglcompact (lgl);
9655 
9656   lgl->limits->gc.fixed = lgl->stats->fixed.sum;
9657 
9658   lglchkred (lgl);
9659   lglrep (lgl, 2, 'c');
9660   lglstop (lgl);
9661 }
9662 
lgltopgc(LGL * lgl)9663 static int lgltopgc (LGL * lgl) {
9664   if (lgl->mt) return 0;
9665   assert (!lgl->forcegc && !lgl->allowforce);
9666   lgl->forcegc = lgl->allowforce = 1;
9667   lglgc (lgl);
9668   assert (lgl->forcegc && lgl->allowforce);
9669   lgl->forcegc = lgl->allowforce = 0;
9670   return !lgl->mt;
9671 }
9672 
lglrandec(LGL * lgl)9673 static int lglrandec (LGL * lgl) {
9674   unsigned size, pos, start, delta;
9675   int lit;
9676   lgl->limits->randec = lgl->stats->decisions;
9677   lgl->limits->randec += lgl->opts->randecint.val/2;
9678   lgl->limits->randec += lglrand (lgl) % lgl->opts->randecint.val;
9679   assert (lgl->nvars > 2);
9680   size = lgl->nvars - 2;
9681   if (!size) return 0;
9682   pos = start = lglrand (lgl) % size;
9683   lit = 2 + pos;
9684   assert (2 <= lit && lit < lgl->nvars);
9685   if (lglval (lgl, lit)) {
9686     delta = lglrand (lgl) % size;
9687     if (size == 1) return 0;
9688     if (!delta) delta++;
9689     while (lglgcd (delta, size) != 1)
9690       if (++delta == size) delta = 1;
9691     do {
9692       pos += delta;
9693       if (pos >= size) pos -= size;
9694       if (pos == start) return 0;
9695       lit = pos + 2;
9696       assert (2 <= lit && lit < lgl->nvars);
9697     } while (lglval (lgl, lit));
9698   }
9699   lgl->stats->randecs++;
9700   return lit;
9701 }
9702 
lgladecide(LGL * lgl)9703 static int lgladecide (LGL * lgl) {
9704   int res, val;
9705   while (lgl->assumed < lglcntstk (&lgl->assume)) {
9706     res = lglpeek (&lgl->assume, lgl->assumed);
9707     val = lglcval (lgl, res);
9708     if (val > 0) LOG (3, "assumption %d already satisfied", res);
9709     lgl->assumed++;
9710     LOG (3, "new assumption queue level %d", lgl->assumed);
9711     assert (val >= 0);
9712     if (!val) return res;
9713   }
9714   return 0;
9715 }
9716 
lgldefphase(LGL * lgl,int idx)9717 static int lgldefphase (LGL * lgl, int idx) {
9718   int bias, res;
9719   AVar * av;
9720   assert (idx > 0);
9721   av = lglavar (lgl, idx);
9722   bias = lgl->opts->phase.val;
9723   if (!bias) bias = av->bias;
9724   if (!bias) bias = lglsetjwhbias (lgl, idx);
9725   if (lgl->opts->phasesave.val) {
9726     if (!(res = av->phase)) res = av->phase = bias;
9727     else if (lgl->opts->phasesave.val < 0) res = -res;
9728   } else res = bias;
9729   return res;
9730 }
9731 
lgldecidephase(LGL * lgl,int lit)9732 static int lgldecidephase (LGL * lgl, int lit) {
9733   int res = abs (lit);
9734   AVar * av = lglavar (lgl, lit);
9735   if (av->fase) return av->fase * res;
9736   if (lgldefphase (lgl, res) <= 0) res = -res;
9737   return res;
9738 }
9739 
lglhasbins(LGL * lgl,int lit)9740 static int lglhasbins (LGL * lgl, int lit) {
9741   int blit, tag, other, other2, val, val2, implied;
9742   const int * p, * w, * eos, * q;
9743   HTS * hts;
9744   assert (!lgl->level);
9745   assert (lglisfree (lgl, lit));
9746   hts = lglhts (lgl, lit);
9747   w = lglhts2wchs (lgl, hts);
9748   eos = w + hts->count;
9749   for (p = w; p < eos; p++) {
9750     if (lgl->treelooking) INCSTEPS (prb.treelook.steps);
9751     blit = *p;
9752     tag = blit & MASKCS;
9753     if (tag == BINCS) {
9754       other = blit >> RMSHFT;
9755       val = lglval (lgl, other);
9756       assert (val >= 0);
9757       if (!val) return 1;
9758     } else if (tag == TRNCS) {
9759       other = blit >> RMSHFT;
9760       other2= *++p;
9761       val = lglval (lgl, other);
9762       val2 = lglval (lgl, other2);
9763       assert (val >= 0 || val2 >= 0);
9764       if (val > 0 || val2 > 0) continue;
9765       if (!val && val2 < 0) return 1;
9766       if (val < 0 && !val2) return 1;
9767     } else {
9768       assert (tag == LRGCS);
9769       q = lglidx2lits (lgl, (blit & REDCS), *++p);
9770       implied = 0;
9771       while ((other = *q++)) {
9772 	if (other == lit) continue;
9773 	val = lglval (lgl, other);
9774 	if (val > 0) break;
9775 	if (val < 0) continue;
9776 	if (implied) break;
9777 	implied = other;
9778       }
9779       if (other) continue;
9780       if (implied) return 1;
9781     }
9782   }
9783   return 0;
9784 }
9785 
lgldecide(LGL * lgl)9786 static int lgldecide (LGL * lgl) {
9787   int lit;
9788   lglchkbcpclean (lgl, "decide");
9789   if (!lgl->unassigned) return 0;
9790   if ((lit = lgladecide (lgl))) {
9791     LOG (2, "using assumption %d as decision", lit);
9792     lgl->alevel = lgl->level + 1;
9793     LOG (2, "new assumption decision level %d", lgl->alevel);
9794   } else {
9795     if (lgl->stats->stability.level > 0 &&
9796         lgl->stats->stability.level <= lgl->level)
9797       lglupdstab (lgl);
9798     if (lgl->opts->randec.val &&
9799 	lgl->limits->randec <= lgl->stats->decisions) {
9800       lit = lglrandec (lgl);
9801       lit = lgldecidephase (lgl, lit);
9802       LOG (2, "random decision %d", lit);
9803     } else {
9804       lit = lglnextdecision (lgl, 1);
9805       lit = lgldecidephase (lgl, lit);
9806     }
9807   }
9808   if (lit) lgldassume (lgl, lit);
9809   return 1;
9810 }
9811 
lgldcpdis(LGL * lgl)9812 static void lgldcpdis (LGL * lgl) {
9813   int idx, sign, lit, tag, blit, red, other, other2, i;
9814   const int * w, * p, * eow;
9815   Val val;
9816   HTS * hts;
9817   Stk * s;
9818   NEW (lgl->dis, 1);
9819   for (idx = 2; idx < lgl->nvars; idx++)
9820     for (sign = -1; sign <= 1; sign += 2) {
9821       lit = sign * idx;
9822       hts = lglhts (lgl, lit);
9823       if (!hts->offset) continue;
9824       assert (hts->count > 0);
9825       w = lglhts2wchs (lgl, hts);
9826       eow = w + hts->count;
9827       hts->count = hts->offset = 0;
9828       val = lglval (lgl, lit);
9829       if (val > 0) continue;
9830       for (p = w; p < eow; p++) {
9831 	blit = *p;
9832 	tag = blit & MASKCS;
9833 	if (tag == TRNCS || tag == LRGCS) p++;
9834 	if (tag == LRGCS) continue;
9835 	other = blit >> RMSHFT;
9836 	if (abs (other) < idx) continue;
9837 	val = lglval (lgl, other);
9838 	if (val > 0) continue;
9839 	red = blit & REDCS;
9840 	if (red && !lglisfree (lgl, other)) continue;
9841 	if (tag == BINCS) {
9842 	  s = red ? &lgl->dis->red.bin : &lgl->dis->irr.bin;
9843 	} else {
9844 	  assert (tag == TRNCS);
9845 	  other2 = *p;
9846 	  if (abs (other2) < idx) continue;
9847 	  val = lglval (lgl, other2);
9848 	  if (val > 0) continue;
9849 	  if (red && !lglisfree (lgl, other2)) continue;
9850 	  s = red ? &lgl->dis->red.trn : &lgl->dis->irr.trn;
9851 	  lglpushstk (lgl, s, other2);
9852 	}
9853 	lglpushstk (lgl, s, other);
9854 	lglpushstk (lgl, s, lit);
9855 	lglpushstk (lgl, s, 0);
9856       }
9857     }
9858   lglrststk (&lgl->wchs->stk, 2);
9859   lgl->wchs->stk.top[-1] = INT_MAX;
9860   for (i = 0; i < MAXLDFW; i++) lgl->wchs->start[i] = INT_MAX;
9861   lgl->wchs->free = 0;
9862   lglrelstk (lgl, &lgl->learned);
9863 }
9864 
lgldcpclnstk(LGL * lgl,int red,Stk * s)9865 static void lgldcpclnstk (LGL * lgl, int red, Stk * s) {
9866   int oldsz, newsz, lit, mark, satisfied, repr, act, changed;
9867   const int druplig = lgl->opts->druplig.val;
9868   const int * p, * c, * eos = s->top;
9869   int * start, * q, * r, * d;
9870   Stk * t, saved;
9871   Val val;
9872   CLR (saved);
9873   q = start = s->start;
9874   for (c = q; c < eos; c = p + 1) {
9875     act = *c;
9876     if (act == REMOVED) {
9877       for (p = c + 1; p < eos && *p == REMOVED; p++)
9878 	;
9879       assert (p >= eos || *p < NOTALIT || lglisact (*p));
9880       p--;
9881       continue;
9882     }
9883     if (lglisact (act)) *q++ = *c++; else act = -1;
9884     d = q;
9885     satisfied = changed = 0;
9886 #ifndef NDEBUG
9887     for (p = c; assert (p < eos), (lit = *p); p++) {
9888       assert (!lglavar (lgl, lit)->mark);
9889       repr = lglirepr (lgl, lit);
9890       assert (abs (repr) == 1 || !lglavar (lgl, lit)->mark);
9891     }
9892 #endif
9893     lglclnstk (&saved);
9894     for (p = c; assert (p < eos), (lit = *p); p++) {
9895       assert (lit < NOTALIT);
9896       if (druplig) lglpushstk (lgl, &saved, lit);
9897       if (satisfied) continue;
9898       repr = lglirepr (lgl, lit);
9899       val = lglcval (lgl, repr);
9900       if (val > 0) { satisfied = 1; continue; }
9901       if (val < 0) { changed = 1; continue; }
9902       mark = lglmarked (lgl, repr);
9903       if (mark < 0) { satisfied = 1; continue; }
9904       if (mark > 0) { changed = 1; continue; }
9905       if (lit != repr) changed = 1;
9906       lglmark (lgl, repr);
9907       *q++ = repr;
9908     }
9909     oldsz = p - c;
9910     for (r = d; r < q; r++) lglunmark (lgl, *r);
9911     newsz = q - d;
9912     assert (satisfied || newsz == oldsz || changed);
9913     if (druplig && !satisfied && newsz > 1 && changed)
9914       *q = 0, lgldrupligaddclsaux (lgl, REDCS, d);
9915     if (satisfied || !oldsz) { q = d - (act >= 0); continue; }
9916     if (newsz >= 4) {
9917       assert (act < 0 || d[-1] == act);
9918       *q++ = 0;
9919       assert (d <= c);
9920     } else if (!newsz) {
9921       LOG (1, "found empty clause while cleaning decomposition");
9922       lglmt (lgl);
9923       q = d - (act >= 0);
9924     } else if (newsz == 1) {
9925       LOG (1, "new unit %d while cleaning decomposition", d[0]);
9926       lglunit (lgl, d[0]);
9927       q = d - (act >= 0);
9928     } else if (newsz == 2) {
9929       t = red ? &lgl->dis->red.bin : &lgl->dis->irr.bin;
9930       if (s != t) {
9931 	lglpushstk (lgl, t, d[0]);
9932 	lglpushstk (lgl, t, d[1]);
9933 	lglpushstk (lgl, t, 0);
9934 	q = d - (act >= 0);
9935       } else *q++ = 0;
9936     } else {
9937       assert (newsz == 3);
9938       t = red ? &lgl->dis->red.trn : &lgl->dis->irr.trn;
9939       if (s != t) {
9940 	lglpushstk (lgl, t, d[0]);
9941 	lglpushstk (lgl, t, d[1]);
9942 	lglpushstk (lgl, t, d[2]);
9943 	lglpushstk (lgl, t, 0);
9944 	q = d - (act >= 0);
9945       } else *q++ = 0;
9946     }
9947     if (druplig && (satisfied || changed)) {
9948       lglpushstk (lgl, &saved, 0);
9949       lgldrupligdelclsaux (lgl, saved.start);
9950     }
9951   }
9952   s->top = q;
9953   lglrelstk (lgl, &saved);
9954 }
9955 
lgldcpconnaux(LGL * lgl,int red,int glue,Stk * s)9956 static void lgldcpconnaux (LGL * lgl, int red, int glue, Stk * s) {
9957   int * start = s->start, * q, * d, lit, size, lidx, act;
9958   const int * p, * c, * eos = s->top;
9959   assert (red == 0 || red == REDCS);
9960   assert (!glue || red);
9961   q = start;
9962   for (c = q; c < eos; c = p + 1) {
9963     if (lglisact (act = *c)) *q++ = *c++; else act = -1;
9964     d = q;
9965     for (p = c; (lit = *p); p++) {
9966       assert (!lgl->repr[abs (lit)]);
9967       assert (!lgl->vals[abs (lit)]);
9968       *q++ = lit;
9969     }
9970     size = q - d;
9971     if (size == 2) {
9972       q = d - (act >= 0);
9973       lglwchbin (lgl, d[0], d[1], red);
9974       lglwchbin (lgl, d[1], d[0], red);
9975     } else if (size == 3) {
9976       q = d - (act >= 0);
9977       lglwchtrn (lgl, d[0], d[1], d[2], red);
9978       lglwchtrn (lgl, d[1], d[0], d[2], red);
9979       lglwchtrn (lgl, d[2], d[0], d[1], red);
9980     } else {
9981       assert (size > 3);
9982       *q++ = 0;
9983       lidx = d - start;
9984       if (red) {
9985 	assert (lidx <= MAXREDLIDX);
9986 	lidx <<= GLUESHFT;
9987 	assert (0 <= lidx);
9988 	lidx |= glue;
9989       }
9990       (void) lglwchlrg (lgl, d[0], d[1], red, lidx);
9991       (void) lglwchlrg (lgl, d[1], d[0], red, lidx);
9992     }
9993   }
9994   s->top = q;
9995 }
9996 
lgldcpcon(LGL * lgl)9997 static void lgldcpcon (LGL * lgl) {
9998   Stk * lir;
9999   int glue;
10000   lgldcpconnaux (lgl, 0, 0, &lgl->dis->irr.bin);
10001   lgldcpconnaux (lgl, REDCS, 0, &lgl->dis->red.bin);
10002   lgldcpconnaux (lgl, 0, 0, &lgl->dis->irr.trn);
10003   lgldcpconnaux (lgl, REDCS, 0, &lgl->dis->red.trn);
10004   lglrelstk (lgl, &lgl->dis->irr.bin);
10005   lglrelstk (lgl, &lgl->dis->irr.trn);
10006   lglrelstk (lgl, &lgl->dis->red.bin);
10007   lglrelstk (lgl, &lgl->dis->red.trn);
10008   DEL (lgl->dis, 1);
10009   lgldcpconnaux (lgl, 0, 0, &lgl->irr);
10010   for (glue = 0; glue < MAXGLUE; glue++) {
10011     lir = lgl->red + glue;
10012     lgldcpconnaux (lgl, REDCS, glue, lir);
10013   }
10014   lglfullyconnected (lgl);
10015 }
10016 
lgldcpcln(LGL * lgl)10017 static void lgldcpcln (LGL * lgl) {
10018   int glue, old, rounds = 0;
10019   Stk * lir;
10020   do {
10021     rounds++;
10022     old = lgl->stats->fixed.current;
10023     lgldcpclnstk (lgl, 0, &lgl->irr);
10024     lgldcpclnstk (lgl, 0, &lgl->dis->irr.bin);
10025     lgldcpclnstk (lgl, 0, &lgl->dis->irr.trn);
10026     lgldcpclnstk (lgl, REDCS, &lgl->dis->red.bin);
10027     lgldcpclnstk (lgl, REDCS, &lgl->dis->red.trn);
10028     for (glue = 0; glue < MAXGLUE; glue++) {
10029       lir = lgl->red + glue;
10030       lgldcpclnstk (lgl, REDCS, lir);
10031     }
10032   } while (old < lgl->stats->fixed.current);
10033   LOG (1, "iterated %d decomposition cleaning rounds", rounds);
10034 }
10035 
lglepush(LGL * lgl,int ilit)10036 static void lglepush (LGL * lgl, int ilit) {
10037   int elit = ilit ? lglexport (lgl, ilit) : 0;
10038   lglpushstk (lgl, &lgl->extend, elit);
10039   LOG (4, "pushing external %d internal %d", elit, ilit);
10040 }
10041 
lglemerge(LGL * lgl,int ilit0,int ilit1)10042 static void lglemerge (LGL * lgl, int ilit0, int ilit1) {
10043   int elit0 = lglexport (lgl, ilit0), elit1 = lglexport (lgl, ilit1);
10044   int repr0 = lglerepr (lgl, elit0), repr1 = lglerepr (lgl, elit1);
10045   Ext * ext0 = lglelit2ext (lgl, repr0);
10046   Ext * ext1 = lglelit2ext (lgl, repr1);
10047 #ifndef NDEBUG
10048   int repr = repr1;
10049 #endif
10050   assert (abs (repr0) != abs (repr1));
10051   if (repr0 < 0) {
10052 #ifndef NLGLOG
10053     repr0 *= -1;
10054 #endif
10055     repr1 *= -1;
10056   }
10057   ext0->equiv = 1;
10058   ext0->repr = repr1;
10059   if (ext1->aliased) ext0->aliased = 1;
10060   LOG (2, "merging external literals %d and %d", repr0, repr1);
10061   assert (lglerepr (lgl, elit0) == repr);
10062   assert (lglerepr (lgl, elit1) == repr);
10063   assert (!(ext0->frozen || ext0->tmpfrozen) ||
10064 	    ext1->frozen || ext1->tmpfrozen);
10065   lglepush (lgl, -ilit0); lglepush (lgl, ilit1); lglepush (lgl, 0);
10066   lglepush (lgl, ilit0); lglepush (lgl, -ilit1); lglepush (lgl, 0);
10067   lgldrupligaddclsarg (lgl, REDCS, -ilit0, ilit1, 0);
10068   lgldrupligaddclsarg (lgl, REDCS, ilit0, -ilit1, 0);
10069 }
10070 
lglimerge(LGL * lgl,int lit,int repr)10071 static void lglimerge (LGL * lgl, int lit, int repr) {
10072   int idx = abs (lit);
10073   AVar * av = lglavar (lgl, idx);
10074   assert (!lglifrozen (lgl, lit) || lglifrozen (lgl, repr));
10075   if (lit < 0) repr = -repr;
10076   assert (av->type == FREEVAR);
10077   assert (lgl->repr);
10078   av->type = EQUIVAR;
10079   lgl->repr[idx] = repr;
10080   lgl->stats->prgss++;
10081   lgl->stats->irrprgss++;
10082   lgl->stats->equiv.sum++;
10083   lgl->stats->equiv.current++;
10084   assert (lgl->stats->equiv.sum > 0);
10085   assert (lgl->stats->equiv.current > 0);
10086   lglemerge (lgl, idx, repr);
10087 }
10088 
lglfreezer(LGL * lgl)10089 static void lglfreezer (LGL * lgl) {
10090   int frozen, melted, tmpfrozen, elit, erepr, ilit;
10091   Ext * ext, * rext;
10092   int * p, eass;
10093   if (lgl->frozen) return;
10094   for (elit = 1; elit <= lgl->maxext; elit++)
10095     lgl->ext[elit].tmpfrozen = 0;
10096   tmpfrozen = frozen = 0;
10097   if (!lglmtstk (&lgl->eassume)) {
10098     for (p = lgl->eassume.start; p < lgl->eassume.top; p++) {
10099       eass = *p;
10100       ext = lglelit2ext (lgl, eass);
10101       assert (!ext->melted);
10102       assert (!ext->eliminated);
10103       assert (!ext->blocking);
10104       if (!ext->frozen && !ext->tmpfrozen) {
10105 	ext->tmpfrozen = 1;
10106 	tmpfrozen++;
10107 	LOG (2, "temporarily freezing external assumption %d", eass);
10108 	erepr = lglerepr (lgl, eass);
10109 	rext = lglelit2ext (lgl, erepr);
10110 	if (ext != rext && !rext->frozen && !rext->tmpfrozen) {
10111 	  assert (!rext->equiv);
10112 	  assert (!rext->eliminated);
10113 	  // assert (!rext->blocking);
10114 	  LOG (2,
10115 	    "temporarily freezing external assumption literal %d", erepr);
10116 	  rext->tmpfrozen = 1;
10117 	  tmpfrozen++;
10118 	}
10119       }
10120     }
10121   }
10122   for (elit = 1; elit <= lgl->maxext; elit++) {
10123     ext = lglelit2ext (lgl, elit);
10124     if (!ext->frozen) continue;
10125     frozen++;
10126     assert (!ext->melted);
10127     assert (!ext->eliminated);
10128     assert (!ext->blocking);
10129     erepr = lglerepr (lgl, elit);
10130     rext = lglelit2ext (lgl, erepr);
10131     if (ext == rext) continue;
10132     if (rext->frozen) continue;
10133     if (rext->tmpfrozen) continue;
10134     // assert (!rext->melted);
10135     assert (!rext->equiv);
10136     assert (!rext->eliminated);
10137     // assert (!rext->blocking);
10138     LOG (2, "temporarily freezing external literal %d", erepr);
10139     rext->tmpfrozen = 1;
10140     tmpfrozen++;
10141   }
10142   melted = 0;
10143   for (elit = 1; elit <= lgl->maxext; elit++) {
10144     ext = lglelit2ext (lgl, elit);
10145     if (ext->frozen) continue;
10146     if (ext->melted) continue;
10147     if (ext->tmpfrozen) continue;
10148     if (!ext->imported) continue;
10149     LOG (2, "permanently melted external %d", elit);
10150     ext->melted = 1;
10151     melted++;
10152   }
10153   LOG (2, "found %d frozen external variables", frozen);
10154   LOG (2, "temporarily frozen %d external variables", tmpfrozen);
10155   LOG (2, "permanently melted %d external variables", melted);
10156   lgl->frozen = 1;
10157   LOG (2, "frozen solver");
10158   melted = frozen = 0;
10159   for (ilit = 2; ilit < lgl->nvars; ilit++) {
10160     if (!lglisfree (lgl, ilit)) continue;
10161     if (lglifrozen (lgl, ilit)) frozen++; else melted++;
10162   }
10163   lgl->allfrozen = !melted;
10164   if (lgl->allfrozen)
10165     lglprt (lgl, 1, "[freezer] all %d free variables frozen", frozen);
10166   else
10167     lglprt (lgl, 1,
10168       "[freezer] frozen %d variables out of %d free variables %.0f%%",
10169       frozen, frozen + melted, lglpcnt (frozen, frozen + melted));
10170 }
10171 
lglcmprepr(LGL * lgl,int a,int b)10172 static int lglcmprepr (LGL * lgl, int a, int b) {
10173   int f = lglifrozen (lgl, a), g = lglifrozen (lgl, b), res;
10174   if ((res = g - f)) return res;
10175   if ((res = (abs (a) - abs (b)))) return res;
10176   return a - b;
10177 }
10178 
lgltarjan(LGL * lgl)10179 static int lgltarjan (LGL * lgl) {
10180   int * dfsimap, * mindfsimap, idx, oidx, sign, lit, blit, tag, other;
10181   int dfsi, mindfsi, ulit, uother, tmp, repr, res, sgn, frozen;
10182   const int * p, * w, * eow;
10183   Stk stk, component;
10184   AVar * av;
10185   HTS * hts;
10186   if (lgl->mt) return 0;
10187   if (!lgl->nvars) return 1;
10188   assert (lgl->frozen);
10189   dfsi = 0;
10190   NEW (dfsimap, 2*lgl->nvars);
10191   NEW (mindfsimap, 2*lgl->nvars);
10192   NEW (lgl->repr, lgl->nvars);
10193   CLR (stk); CLR (component);
10194   res = 1;
10195   for (idx = 2; idx < lgl->nvars; idx++) {
10196     for (sign = -1; sign <= 1; sign += 2) {
10197       lit = sign * idx;
10198       ulit = lglulit (lit);
10199       tmp = dfsimap[ulit];
10200       if (tmp) continue;
10201       lglpushstk (lgl, &stk, lit);
10202       while (!lglmtstk (&stk)) {
10203 	lit = lglpopstk (&stk);
10204 	if (lit) {
10205 	  ulit = lglulit (lit);
10206 	  if (dfsimap[ulit]) continue;
10207 	  dfsimap[ulit] = mindfsimap[ulit] = ++dfsi;
10208 	  lglpushstk (lgl, &component, lit);
10209 	  assert (dfsi > 0);
10210 	  lglpushstk (lgl, &stk, lit);
10211 	  lglpushstk (lgl, &stk, 0);
10212 	  hts = lglhts (lgl, -lit);
10213 	  if (!hts->offset) continue;
10214 	  assert (hts->count > 0);
10215 	  w = lglhts2wchs (lgl, hts);
10216 	  eow = w + hts->count;
10217 	  for (p = w; p < eow; p++) {
10218 	    blit = *p;
10219 	    tag = blit & MASKCS;
10220 	    if (tag != BINCS) { p++; continue; }
10221 	    other = blit >> RMSHFT;
10222 	    uother = lglulit (other);
10223 	    tmp = dfsimap[uother];
10224 	    if (tmp) continue;
10225 	    lglpushstk (lgl, &stk, other);
10226 	  }
10227 	} else {
10228 	  assert (!lglmtstk (&stk));
10229 	  lit = lglpopstk (&stk);
10230 	  ulit = lglulit (lit);
10231 	  mindfsi = dfsimap[ulit];
10232 	  assert (mindfsi);
10233 	  hts = lglhts (lgl, -lit);
10234 	  w = lglhts2wchs (lgl, hts);
10235 	  eow = w + hts->count;
10236 	  for (p = w; p < eow; p++) {
10237 	    blit = *p;
10238 	    tag = blit & MASKCS;
10239 	    if (tag != BINCS) { p++; continue; }
10240 	    other = blit >> RMSHFT;
10241 	    uother = lglulit (other);
10242 	    tmp = mindfsimap[uother];
10243 	    if (tmp >= mindfsi) continue;
10244 	    mindfsi = tmp;
10245 	  }
10246 	  if (mindfsi == dfsimap[ulit]) {
10247 	    repr = lit;
10248 	    frozen = lglifrozen (lgl, repr);
10249 	    for (p = component.top - 1; (other = *p) != lit; p--) {
10250 	      if (lglcmprepr (lgl, other, repr) < 0) repr = other;
10251 	      if (!frozen && lglifrozen (lgl, other)) frozen = 1;
10252 	    }
10253 	    while ((other = lglpopstk (&component)) != lit) {
10254 	      mindfsimap[lglulit (other)] = INT_MAX;
10255 	      if (other == repr) continue;
10256 	      if (other == -repr) {
10257 		LOG (1, "empty clause since repr[%d] = %d", repr, other);
10258 		lgldrupligaddclsarg (lgl, REDCS, repr, 0);
10259 		lglmt (lgl); res = 0; goto DONE;
10260 	      }
10261 	      sgn = lglsgn (other);
10262 	      oidx = abs (other);
10263 	      tmp = lgl->repr[oidx];
10264 	      if (tmp == sgn * repr) continue;
10265 	      LOG (2, "repr[%d] = %d", oidx, sgn * repr);
10266 	      if (tmp) {
10267 		LOG (1, "empty clause since repr[%d] = %d and repr[%d] = %d",
10268 		     oidx, tmp, oidx, sgn * repr);
10269 		lgldrupligaddclsarg (lgl, REDCS, repr, 0);
10270 		lglmt (lgl); res = 0; goto DONE;
10271 	      } else {
10272 		av = lglavar (lgl, oidx);
10273 		assert (sgn*oidx == other);
10274 		if (av->type == FREEVAR) lglimerge (lgl, other, repr);
10275 		else assert (av->type == FIXEDVAR);
10276 	      }
10277 	    }
10278 	    mindfsimap[lglulit (lit)] = INT_MAX;
10279 	    if (frozen) {
10280 	      LOG (2, "equivalence class of %d is frozen", repr);
10281 	      assert (lglifrozen (lgl, repr));
10282 	    }
10283 	  } else mindfsimap[ulit] = mindfsi;
10284 	}
10285       }
10286     }
10287   }
10288 DONE:
10289   lglrelstk (lgl, &stk);
10290   lglrelstk (lgl, &component);
10291   DEL (mindfsimap, 2*lgl->nvars);
10292   DEL (dfsimap, 2*lgl->nvars);
10293   if (!res) DEL (lgl->repr, lgl->nvars);
10294   if (lgl->mt) lgldrupligaddclsarg (lgl, REDCS, 0);
10295   return res;
10296 }
10297 
lglsyncunits(LGL * lgl)10298 static int lglsyncunits (LGL * lgl) {
10299   int * units, * eou, * p, elit, erepr, ilit, res, count = 0;
10300   void (*produce)(void*, int);
10301   int64_t steps;
10302   Ext * ext;
10303   Val val;
10304   if (lgl->mt) return 0;
10305   if (!lgl->cbs) return 1;
10306   if (!lgl->cbs->units.consume.fun) return 1;
10307   assert (!lgl->simp || !lgl->level);
10308   steps = lglsteps (lgl);
10309   if (steps < lgl->limits->sync.steps) return 1;
10310   lgl->limits->sync.steps = steps + lgl->opts->syncunint.val;
10311   lgl->stats->sync.units.consumed.calls++;
10312   lgl->cbs->units.consume.fun (lgl->cbs->units.consume.state, &units, &eou);
10313   if (units == eou) return 1;
10314   lgl->stats->sync.units.consumed.tried++;
10315   produce = lgl->cbs->units.produce.fun;
10316   lgl->cbs->units.produce.fun = 0;
10317   for (p = units; !lgl->mt && p < eou; p++) {
10318     elit = *p;
10319     erepr = lglerepr (lgl, elit);
10320     ext = lglelit2ext (lgl, erepr);
10321     assert (!ext->equiv);
10322     ilit = ext->repr;
10323     if (!ilit) continue;
10324     if (erepr < 0) ilit = -ilit;
10325     if (ilit == 1) continue;
10326     if (ilit == -1) val = -1;
10327     else {
10328       assert (abs (ilit) > 1);
10329       val = lglval (lgl, ilit);
10330       if (val && lglevel (lgl, ilit)) val = 0;
10331     }
10332     if (val == 1) continue;
10333     if (val == -1) {
10334       LOG (1, "mismatching synchronized external unit %d", elit);
10335       if (lgl->level > 0) lglbacktrack (lgl, 0);
10336       lglmt (lgl);
10337     } else if (!lglisfree (lgl, ilit)) continue;
10338     else {
10339       assert (!val);
10340       if (lgl->level > 0) lglbacktrack (lgl, 0);
10341       lglunit (lgl, ilit);
10342       LOG (2, "importing internal unit %d external %d",
10343 	   lgl->tid, ilit, elit);
10344       count++;
10345     }
10346   }
10347   lgl->cbs->units.produce.fun = produce;
10348   if (lgl->cbs->units.consumed.fun)
10349     lgl->cbs->units.consumed.fun (lgl->cbs->units.consumed.state, count);
10350   if (count) lgl->stats->sync.units.consumed.actual++;
10351   if (lgl->mt) return 0;
10352   if (count) LOG (1, "imported %d units", count);
10353   if (!count) return 1;
10354   assert (!lgl->level);
10355   res = lglbcp (lgl);
10356   if(!res && !lgl->mt) lglmt (lgl);
10357   return res;
10358 }
10359 
lglelitblockingoreliminated(LGL * lgl,int elit)10360 static int lglelitblockingoreliminated (LGL * lgl, int elit) {
10361   Ext * ext = lglelit2ext (lgl, elit);
10362   return ext->blocking || ext->eliminated;
10363 }
10364 
lglsynclsexist(LGL * lgl)10365 static int lglsynclsexist (LGL * lgl) {
10366   int len, lit, blit, tag, other, other2;
10367   int * s, * p, * w, * eow;
10368   HTS * hts;
10369   len = lglcntstk (&lgl->clause);
10370   assert (!len || lgl->clause.top[-1]);
10371   if (len <= 1) return 0;
10372   s = lgl->clause.start;
10373   for (p = s + 1; p + 1 < lgl->clause.top; p++) {
10374     assert (lglmarked (lgl, *p) > 0);
10375     if (lglhts (lgl, *s)->count > lglhts (lgl, *p)->count)
10376       SWAP (int, *s, *p);
10377   }
10378   hts = lglhts (lgl, (lit = *s));
10379   assert (lglmarked (lgl, lit) > 0);
10380   w = lglhts2wchs (lgl, hts);
10381   eow = w + hts->count;
10382   for (p = w; p < eow; p++) {
10383     blit = *p;
10384     tag = blit & MASKCS;
10385     if (tag == TRNCS || tag == LRGCS) p++;
10386     if (tag == LRGCS) continue;
10387     if (tag == BINCS) {
10388       other = blit >> RMSHFT;
10389       if (lglmarked (lgl, other) > 0) return 1;
10390     } else {
10391       assert (tag == TRNCS);
10392       if (len <= 2) continue;
10393       other = blit >> RMSHFT;
10394       if (lglmarked (lgl, other) > 0) return 1;
10395       other2 = *p;
10396       if (lglmarked (lgl, other2) > 0) return 1;
10397     }
10398   }
10399   return 0;
10400 }
10401 
lglsyncls(LGL * lgl)10402 static int lglsyncls (LGL * lgl) {
10403   int maxlevel, level, nonfalse, numtrue, res, delta, glue, consumed;
10404   int * cls, elit, erepr, tmp, ilit, len, newglue;
10405   const int * p;
10406   int64_t rate;
10407   if (lgl->mt) return 0;
10408   if (!lgl->cbs) return 1;
10409   if (!lgl->cbs->cls.consume.fun) return 1;
10410   assert (!lgl->simp);
10411   if (lgl->stats->confs < lgl->limits->sync.confs) return 1;
10412   delta = lgl->opts->synclsint.val;
10413   if (lgl->stats->sync.cls.consumed.calls) {
10414     rate = 100*lgl->stats->sync.cls.consumed.tried;
10415     rate /= lgl->stats->sync.cls.consumed.calls;
10416     LOG (2, "syncls tried/calls = %lld/%lld = %d%%",
10417       (LGLL) lgl->stats->sync.cls.consumed.tried,
10418       (LGLL) lgl->stats->sync.cls.consumed.calls,
10419       rate);
10420     if (rate) delta /= rate;
10421   }
10422   lgl->limits->sync.confs = lgl->stats->confs + delta;
10423   lgl->stats->sync.cls.consumed.calls++;
10424   consumed = 0;
10425 RESTART:
10426   lgl->cbs->cls.consume.fun (lgl->cbs->cls.consume.state, &cls, &glue);
10427   if (!cls) return 1;
10428   lgl->stats->sync.cls.consumed.tried++;
10429   LOGCLS (2, cls, "trying to import external clause");
10430   assert (lglmtstk (&lgl->clause));
10431   maxlevel = nonfalse = numtrue = 0;
10432 #ifndef NDEBUG
10433   for (p = cls; (elit = *p); p++) {
10434     ilit = lglimport (lgl, elit);
10435     if (abs (ilit) <= 1) continue;
10436     assert (!lglmarked (lgl, ilit));
10437   }
10438 #endif
10439   for (p = cls; (elit = *p); p++) {
10440     erepr = lglerepr (lgl, elit);
10441     if (lglelitblockingoreliminated (lgl, erepr)) break;
10442     ilit = lglimport (lgl, erepr);
10443     if (!ilit) break;
10444     if (ilit == 1) break;
10445     if (ilit == -1) continue;
10446     tmp = lglifixed (lgl, ilit);
10447     if (tmp > 0) break;
10448     if (tmp < 0) continue;
10449     tmp = lglmarked (lgl, ilit);
10450     if (tmp > 0) continue;
10451     if (tmp < 0) break;
10452     lglpushstk (lgl, &lgl->clause, ilit);
10453     lglmark (lgl, ilit);
10454     tmp = lglval (lgl, ilit);
10455     if (tmp > 0) numtrue++;
10456     else if (!tmp) nonfalse++;
10457     else if ((level = lglevel (lgl, ilit)) > maxlevel) maxlevel = level;
10458   }
10459   res = 1;
10460   if (!elit && lglsynclsexist (lgl)) elit = INT_MAX;
10461   for (p = lgl->clause.start; p < lgl->clause.top; p++)
10462     lglunmark (lgl, *p);
10463   if (elit) goto DONE;
10464   len = lglcntstk (&lgl->clause);
10465   if (!numtrue && nonfalse <= 1) {
10466     if (len <= 1 || maxlevel <= 1) level = 0;
10467     else {
10468       level = 0;
10469       for (p = lgl->clause.start; p < lgl->clause.top; p++) {
10470 	ilit = *p;
10471 	tmp = lglval (lgl, ilit);
10472 	assert (tmp <= 0);
10473 	if (!tmp) continue;
10474 	tmp = lglevel (lgl, ilit);
10475 	if (tmp < maxlevel && tmp > level) level = tmp;
10476       }
10477     }
10478     if (level < lgl->level) {
10479       LOG (2, "importing clause requires to backtrack to level %d", level);
10480       lglbacktrack (lgl, level);
10481     }
10482   }
10483   lglpushstk (lgl, &lgl->clause, 0);
10484   newglue = glue;
10485   LOGCLS (2, lgl->clause.start,
10486     "successfully imported as glue %d redundant glue %d length %d clause",
10487     newglue, glue, len);
10488   lgl->stats->sync.cls.consumed.actual++;
10489   lgldrupligaddcls (lgl, 0);			// TODO?
10490   lgladdcls (lgl, REDCS, newglue, !numtrue);
10491   consumed++;
10492   if (lgl->mt) res = 0;
10493   else res = lglbcpsearch (lgl);
10494 DONE:
10495   lglclnstk (&lgl->clause);
10496   if (res && lgl->opts->synclsall.val) goto RESTART;
10497   if (lgl->cbs->cls.consumed.fun)
10498     lgl->cbs->cls.consumed.fun (lgl->cbs->cls.consumed.state, consumed);
10499   return res;
10500 }
10501 
lglprbpull(LGL * lgl,int lit,int probe)10502 static int lglprbpull (LGL * lgl, int lit, int probe) {
10503   AVar * av;
10504   assert (lgl->level == 1);
10505   av = lglavar (lgl, lit);
10506   if (av->mark) return 0;
10507   if (!lglevel (lgl, lit)) return 0;
10508   assert (lglevel (lgl, lit) == 1);
10509   av->mark = 1;
10510   lglpushstk (lgl, &lgl->seen, -lit);
10511   LOG (3, "pulled in literal %d during probing analysis", -lit);
10512   return 1;
10513 }
10514 
lglprbana(LGL * lgl,int probe)10515 static int lglprbana (LGL * lgl, int probe) {
10516   int open, lit, r0, r1, tag, red, other, res, * p, * rsn;
10517   assert (lgl->level == 1);
10518   assert (lgl->conf.lit);
10519   assert (lglmtstk (&lgl->seen));
10520   lit = lgl->conf.lit;
10521   r0 = lgl->conf.rsn[0], r1 = lgl->conf.rsn[1];
10522   open = lglprbpull (lgl, lit, probe);
10523   LOG (2, "starting probing analysis with reason of literal %d", lit);
10524   for (;;) {
10525     assert (lglevel (lgl, lit) == 1);
10526     tag = r0 & MASKCS;
10527     if (tag == BINCS || tag == TRNCS) {
10528       other = r0 >> RMSHFT;
10529       if (lglprbpull (lgl, other, probe)) open++;
10530       if (tag == TRNCS && lglprbpull (lgl, r1, probe)) open++;
10531     } else {
10532       assert (tag == LRGCS);
10533       red = r0 & REDCS;
10534       p = lglidx2lits (lgl, red, r1);
10535       while ((other = *p++)) open += lglprbpull (lgl, other, probe);
10536     }
10537     LOG (3, "open %d antecedents in probing analysis", open-1);
10538     assert (open > 0);
10539     while (!lglmarked (lgl, lit = lglpopstk (&lgl->trail)))
10540       lglunassign (lgl, lit);
10541     lglunassign (lgl, lit);
10542     if (!--open) { res = lit; break; }
10543     LOG (2, "analyzing reason of literal %d in probing analysis next", lit);
10544     rsn = lglrsn (lgl, lit);
10545     r0 = rsn[0], r1 = rsn[1];
10546   }
10547   assert (res);
10548   if (res == probe)
10549     LOG (2, "probing analysis returns the probe %d as 1st UIP", probe);
10550   else
10551     LOG (2, "probing analysis returns different 1st UIP %d and not probe %d",
10552 	 res, probe);
10553   lglpopnunmarkstk (lgl, &lgl->seen);
10554   return res;
10555 }
10556 
lglederef(LGL * lgl,int elit)10557 static int lglederef (LGL * lgl, int elit) {
10558   int ilit, res;
10559   Ext * ext;
10560   assert (elit);
10561   if (abs (elit) > lgl->maxext) return -1;
10562   ext = lglelit2ext (lgl, elit);
10563   if (!(res = ext->val)) {
10564     assert (!ext->equiv);
10565     ilit = ext->repr;
10566     res = ilit ? lglcval (lgl, ilit) : -1;
10567   }
10568   if (elit < 0) res = -res;
10569   return res;
10570 }
10571 
10572 static int lgldecomp (LGL *); // TODO move
10573 
lglhasbin(LGL * lgl,int a,int b)10574 static int lglhasbin (LGL * lgl, int a, int b) {
10575   int blit, tag, other, res = 0;
10576   const int * w, * eow, * p;
10577   int64_t inc;
10578   HTS * ha, * hb;
10579   ha = lglhts (lgl, a);
10580   hb = lglhts (lgl, b);
10581   if (hb->count < ha->count) {
10582     SWAP (int, a, b); SWAP (HTS *, ha, hb);
10583   }
10584   w = lglhts2wchs (lgl, ha);
10585   eow = w + ha->count;
10586   for (p = w; !res && p < eow; p++) {
10587     blit = *p;
10588     tag = blit & MASKCS;
10589     if (tag == OCCS) continue;
10590     if (tag == TRNCS || tag == LRGCS) { p++; continue; }
10591     assert (tag == BINCS);
10592     other = blit >> RMSHFT;
10593     if (other == b) res = 1;
10594   }
10595   inc = 2 + (int)(p - w);
10596   if (lgl->card) ADDSTEPS (card.steps, inc);
10597   if (lgl->simpleprobing) ADDSTEPS (prb.simple.steps, inc);
10598   return res;
10599 }
10600 
lglwrkinit(LGL * lgl,int posonly,int fifo)10601 static void lglwrkinit (LGL * lgl, int posonly, int fifo) {
10602   int size, lit;
10603   NEW (lgl->wrk, 1);
10604   lgl->wrk->fifo = fifo;
10605   size = lgl->wrk->size = lgl->nvars;
10606   if (posonly) {
10607     NEW (lgl->wrk->pos, size);
10608     lgl->wrk->posonly = 1;
10609   } else {
10610     NEW (lgl->wrk->pos, 2*size);
10611     lgl->wrk->pos += size;
10612     for (lit = -size + 1; lit < -1; lit++) lgl->wrk->pos[lit] = -1;
10613   }
10614   for (lit = 2; lit < size; lit++) lgl->wrk->pos[lit] = -1;
10615 }
10616 
lglwrkreset(LGL * lgl)10617 static void lglwrkreset (LGL * lgl) {
10618   lglrelstk (lgl, &lgl->wrk->queue);
10619   if (lgl->wrk->posonly) DEL (lgl->wrk->pos, lgl->wrk->size);
10620   else {
10621     lgl->wrk->pos -= lgl->wrk->size;
10622     DEL (lgl->wrk->pos, 2*lgl->wrk->size);
10623   }
10624   DEL (lgl->wrk, 1);
10625 }
10626 
lglwrkcompact(LGL * lgl)10627 static void lglwrkcompact (LGL * lgl) {
10628   int i, j = 0, lit, tail = lglcntstk (&lgl->wrk->queue);
10629   for (i = lgl->wrk->head; i < tail; i++) {
10630     lit = lgl->wrk->queue.start[i];
10631     if (!lit) continue;
10632     assert (!lgl->wrk->posonly || 1 < lit);
10633     assert (1 < abs (lit) && abs (lit) < lgl->wrk->size);
10634     assert (lgl->wrk->pos[lit] == i);
10635     if (!lglisfree (lgl, lit)) {
10636       lgl->wrk->pos[lit] = -1;
10637       assert (lgl->wrk->count > 0);
10638       lgl->wrk->count--;
10639     } else {
10640       lgl->wrk->queue.start[j] = lit;
10641       lgl->wrk->pos[lit] = j++;
10642     }
10643   }
10644   lglrststk (&lgl->wrk->queue, j);
10645   lgl->wrk->head = 0;
10646 }
10647 
lglwrktouched(LGL * lgl,int lit)10648 static int lglwrktouched (LGL * lgl, int lit) {
10649   if (lgl->wrk->posonly) lit = abs (lit);
10650   return lgl->wrk->pos[lit] >= 0;
10651 }
10652 
lglwrktouch(LGL * lgl,int lit)10653 static int lglwrktouch (LGL * lgl, int lit) {
10654   int tail, pos;
10655   if (!lglisfree (lgl, lit)) return 1;
10656   if (lgl->donotsched) {
10657     if (lgl->ternresing && lglavar (lgl, lit)->donoternres) return 1;
10658     if (lgl->simpleprobing && lglavar (lgl, lit)->donotsimpleprobe) return 1;
10659   }
10660   if (lgl->wrk->posonly) lit = abs (lit);
10661   tail = lglcntstk (&lgl->wrk->queue);
10662   LOG (4, "work touch %d", lit);
10663   if ((pos = lgl->wrk->pos[lit]) >= 0) {
10664     assert (lgl->wrk->queue.start[pos] == lit);
10665     lgl->wrk->queue.start[pos] = 0;
10666   }
10667   lgl->wrk->count++;
10668   assert (lgl->wrk->count > 0);
10669   lgl->wrk->pos[lit] = tail;
10670   lglpushstk (lgl, &lgl->wrk->queue, lit);
10671   if (tail/2 > lgl->wrk->count) lglwrkcompact (lgl);
10672   return 1;
10673 }
10674 
lglwrkdeq(LGL * lgl)10675 static int lglwrkdeq (LGL * lgl) {
10676   int res, pos;
10677   while ((pos = lgl->wrk->head) < lglcntstk (&lgl->wrk->queue)) {
10678     lgl->wrk->head++;
10679     res = lgl->wrk->queue.start[pos];
10680     if (!res) continue;
10681     lgl->wrk->queue.start[pos] = 0;
10682     assert (lgl->wrk->count > 0);
10683     lgl->wrk->count--;
10684     assert (lgl->wrk->pos[res] == pos);
10685     lgl->wrk->pos[res] = -1;
10686     if (lglisfree (lgl, res)) return res;
10687   }
10688   return 0;
10689 }
10690 
lglwrkpop(LGL * lgl)10691 static int lglwrkpop (LGL * lgl) {
10692   int res;
10693   while (lglcntstk (&lgl->wrk->queue) > lgl->wrk->head) {
10694     res = lglpopstk (&lgl->wrk->queue);
10695     if (!res) continue;
10696 #ifndef NDEBUG
10697     {
10698       int pos = lglcntstk (&lgl->wrk->queue);
10699       assert (lgl->wrk->pos[res] == pos);
10700     }
10701 #endif
10702     lgl->wrk->pos[res] = -1;
10703     if (lglisfree (lgl, res)) return res;
10704   }
10705   return 0;
10706 }
10707 
lglwrknext(LGL * lgl)10708 static int lglwrknext (LGL * lgl) {
10709   return lgl->wrk->fifo ? lglwrkdeq (lgl) : lglwrkpop (lgl);
10710 }
10711 
lglrandlitrav(LGL * lgl,int (* fun)(LGL *,int lit))10712 static int lglrandlitrav (LGL * lgl, int (*fun)(LGL*,int lit)) {
10713   int delta, mod, prev, first, ulit, count;
10714   if (lgl->nvars < 2) return 0;
10715   first = mod = 2*lgl->nvars;
10716   ulit = lglrand (lgl) % mod;
10717   delta = lglrand (lgl) % mod;
10718   if (!delta) delta++;
10719   while (lglgcd (delta, mod) > 1)
10720     if (++delta == mod) delta = 1;
10721   count = mod;
10722   LOG (2,
10723     "random literal traversal start %d delta %d mod %d",
10724      ulit, delta, mod);
10725   for (;;) {
10726     count--;
10727     assert (count >= 0);
10728     if (ulit >= 4 && !fun (lgl, lglilit (ulit))) return 0;
10729     prev = ulit;
10730     ulit += delta;
10731     if (ulit >= mod) ulit -= mod;
10732     if (ulit == first) { assert (!count); break; }
10733     if (first == mod) first = prev;
10734   }
10735   return 1;
10736 }
10737 
lglsimpleprobeinit(LGL * lgl)10738 static void lglsimpleprobeinit (LGL * lgl) {
10739   int idx, rem = 0, ret = 0;
10740   for (idx = 2; idx < lgl->nvars; idx++) lgl->avars[idx].equiv = 0;
10741   for (idx = 2; idx < lgl->nvars; idx++) {
10742     if (!lglisfree (lgl, idx)) continue;
10743     if (lglavar (lgl, idx)->donotsimpleprobe) ret++; else rem++;
10744   }
10745   if (!rem) {
10746     ret = 0;
10747     for (idx = 2; idx < lgl->nvars; idx++) {
10748       if (!lglisfree (lgl, idx)) continue;
10749       lglavar (lgl, idx)->donotsimpleprobe = 0;
10750       rem++;
10751     }
10752   }
10753   if (!ret)
10754     lglprt (lgl, 1,
10755       "[simpleprobe-%d] all %d free variables schedulable",
10756       lgl->stats->prb.simple.count, rem);
10757   else
10758     lglprt (lgl, 1,
10759       "[simpleprobe-%d] %d schedulable variables %.0f%%",
10760       lgl->stats->prb.simple.count, rem, lglpcnt (rem, lglrem (lgl)));
10761   lglwrkinit (lgl, 0, 1);
10762   assert (!lgl->donotsched), lgl->donotsched = 1;
10763   lglrandlitrav (lgl, lglwrktouch);
10764   assert (lgl->donotsched), lgl->donotsched = 0;
10765   assert (lgl->opts->prbsimple.val);
10766   lglchkirrstats (lgl);
10767 }
10768 
lglsimpleprobereset(LGL * lgl,int nvars)10769 static void lglsimpleprobereset (LGL * lgl, int nvars) {
10770   const int * p;
10771   int idx;
10772   lglrelstk (lgl, &lgl->sprb->units);
10773   lglrelstk (lgl, &lgl->sprb->impls);
10774   lglrelstk (lgl, &lgl->sprb->eqs);
10775   for (idx = 2; idx < lgl->nvars; idx++) lgl->avars[idx].donotsimpleprobe = 1;
10776   for (p = lgl->wrk->queue.start; p < lgl->wrk->queue.top; p++)
10777     lgl->avars[abs (*p)].donotsimpleprobe = 0;
10778   lglwrkreset (lgl);
10779   lglrelstk (lgl, &lgl->sprb->counted);
10780   lglrelstk (lgl, &lgl->sprb->marked);
10781   assert (nvars == lgl->nvars);
10782   lgl->sprb->spes -= nvars;
10783   DEL (lgl->sprb->spes, 2*nvars);
10784 }
10785 
10786 static int lglflush (LGL *);
10787 static void lgldense (LGL *, int rmredbintrn);
10788 static void lglsparse (LGL *);
10789 
lglsimpleprobeunits(LGL * lgl)10790 static int lglsimpleprobeunits (LGL * lgl) {
10791   const int * p;
10792   int lit, res;
10793   Val val;
10794   res = 0;
10795   lglchkirrstats (lgl);
10796   for (p = lgl->sprb->units.start; !lgl->mt && p < lgl->sprb->units.top; p++) {
10797     lit = *p;
10798     val = lglval (lgl, lit);
10799     if (val > 0) continue;
10800     lgl->stats->prb.simple.failed++;
10801     if (val < 0) {
10802       lgldrupligaddclsarg (lgl, REDCS, lit, 0);
10803       LOG (1, "inconsistent unit %d", lit);
10804       lglmt (lgl);
10805     } else {
10806       lglunit (lgl, lit);
10807       res++;
10808       if (!lglflush (lgl)) {
10809 	LOG (1, "propagating simple HBR unit %d results in conflict", lit);
10810 	lglmt (lgl);
10811       }
10812     }
10813   }
10814   return res;
10815 }
10816 
lglsimpleprobeimpls(LGL * lgl)10817 static int lglsimpleprobeimpls (LGL * lgl) {
10818   int a, b, res;
10819   res = 0;
10820   while (!lglmtstk (&lgl->sprb->impls)) {
10821     b = lglpopstk (&lgl->sprb->impls);
10822     a = lglpopstk (&lgl->sprb->impls);
10823     if (lglval (lgl, a) || lglval (lgl, b)) continue;
10824     if (lglhasbin (lgl, a, b)) continue;
10825     LOG (2, "adding previously detected hyper binary resolvent %d %d", a, b);
10826     lgldrupligaddclsarg (lgl, REDCS, a, b, 0);
10827     res++;
10828     lgl->stats->hbr.cnt++;
10829     lgl->stats->hbr.simple++;
10830     (void) lglwchbin (lgl, a, b, REDCS);
10831     (void) lglwchbin (lgl, b, a, REDCS);
10832     lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
10833     lglwrktouch (lgl, -a);
10834     lglwrktouch (lgl, -b);
10835     if (!lglhasbin (lgl, -a, -b)) continue;
10836     LOG (2, "found equivalent literals %d and %d", -a, b);
10837     lglpushstk (lgl, &lgl->sprb->eqs, -a);
10838     lglpushstk (lgl, &lgl->sprb->eqs, b);
10839   }
10840   return res;
10841 }
10842 
lglhasonlybin(LGL * lgl,int lit,int other)10843 static int lglhasonlybin (LGL * lgl, int lit, int other) {
10844   HTS * hts = lglhts (lgl, lit);
10845   const int * w;
10846   int blit;
10847   if (hts->count != 1) return 0;
10848   w = lglhts2wchs (lgl, hts);
10849   blit = *w;
10850   if ((blit & MASKCS) != BINCS) return 0;
10851   return (blit >> RMSHFT) == other;
10852 }
10853 
lglsimpleprobemerged(LGL * lgl,int a,int b)10854 static int lglsimpleprobemerged (LGL * lgl, int a, int b) {
10855   return lglhasonlybin (lgl, -a, b) && lglhasonlybin (lgl, -b, a);
10856 }
10857 
10858 static int lglflushclauses (LGL * lgl, int lit);
10859 
lglsimpleprobeclscp(LGL * lgl,int nonrepr,int repr,Stk * stk)10860 static void lglsimpleprobeclscp (LGL * lgl, int nonrepr, int repr, Stk * stk) {
10861   int blit, tag, red, other, other2, lidx, count, found, start, trivial;
10862   const int * p, * w, * eow, * c, * q;
10863   HTS * hts = lglhts (lgl, nonrepr);
10864   assert (abs (repr) < abs (nonrepr));
10865   w = lglhts2wchs (lgl, hts);
10866   eow = w + hts->count;
10867   count = 0;
10868   for (p = w; p < eow; p++) {
10869     INCSTEPS (prb.simple.steps);
10870     blit = *p;
10871     tag = blit & MASKCS;
10872     if (tag == TRNCS || tag == LRGCS) p++;
10873     if (tag == LRGCS) continue;
10874     start = lglcntstk (stk);
10875     trivial = 0;
10876     red = blit & REDCS;
10877     lglpushstk (lgl, stk, red);
10878     lglpushstk (lgl, stk, repr);
10879     if (tag == BINCS || tag == TRNCS) {
10880       other = blit >> RMSHFT;
10881       if (other == -repr) trivial = 1;
10882       else if (other != repr) lglpushstk (lgl, stk, other);
10883       if (tag == TRNCS) {
10884 	other2 = *p;
10885 	if (other2 == -repr) trivial = 1;
10886 	else if (other2 != repr) lglpushstk (lgl, stk, other2);
10887       }
10888     } else {
10889       assert (tag == OCCS);
10890       lidx = blit >> RMSHFT;
10891       c = lglidx2lits (lgl, red, lidx);
10892       found = 0;
10893       for (q = c; !trivial && (other = *q); q++) {
10894 	if (other >= NOTALIT) trivial = 1;
10895 	else if (other == nonrepr) found++;
10896 	else if (other == -repr) trivial = 1;
10897 	else if (other != repr) lglpushstk (lgl, stk, other);
10898       }
10899       assert (trivial || found);
10900     }
10901     if (trivial) lglrststk (stk, start);
10902     else lglpushstk (lgl, stk, 0), count++;
10903   }
10904   LOG (2, "copied %d clauses with %d replacing %d by %d",
10905        count, nonrepr, nonrepr, repr);
10906 }
10907 
lglsimpleprobebinexists(LGL * lgl,int a,int b)10908 static int lglsimpleprobebinexists (LGL * lgl, int a, int b) {
10909   const int * p, * w, * eow;
10910   int blit, tag, red, other;
10911   HTS * hts;
10912   hts = lglhts (lgl, a);
10913   w = lglhts2wchs (lgl, hts);
10914   eow = w + hts->count;
10915   for (p = w; p < eow; p++) {
10916     blit = *p;
10917     tag = blit & MASKCS;
10918     if (tag == TRNCS || tag == LRGCS) p++;
10919     if (tag != BINCS) continue;
10920     red = blit & REDCS;
10921     if (red) continue;
10922     other = blit >> RMSHFT;
10923     if (other == b) return 1;
10924   }
10925   return 0;
10926 }
10927 
lglsimpleprobetrnexists(LGL * lgl,int a,int b,int c)10928 static int lglsimpleprobetrnexists (LGL * lgl, int a, int b, int c) {
10929   int blit, tag, red, other, other2;
10930   const int * p, * w, * eow;
10931   HTS * hts;
10932   hts = lglhts (lgl, a);
10933   w = lglhts2wchs (lgl, hts);
10934   eow = w + hts->count;
10935   for (p = w; p < eow; p++) {
10936     blit = *p;
10937     tag = blit & MASKCS;
10938     if (tag == TRNCS || tag == LRGCS) p++;
10939     red = blit & REDCS;
10940     if (red) continue;
10941     other = blit >> RMSHFT;
10942     if (tag == BINCS) {
10943       if (other == b) return 1;
10944       if (other == c) return 1;
10945     } else if (tag == TRNCS) {
10946       other2 = *p;
10947       if (other == b && other2 == c) return 1;
10948       if (other == c && other2 == b) return 1;
10949     }
10950   }
10951   return 0;
10952 }
10953 
lglsimpleprobelrgexists(LGL * lgl,int a)10954 static int lglsimpleprobelrgexists (LGL * lgl, int a) {
10955   int blit, tag, red, other, other2, lidx, res;
10956   const int * p, * w, * eow, * c, * q;
10957   HTS * hts;
10958   for (p = lgl->clause.start; p + 1 < lgl->clause.top; p++) {
10959     other = *p;
10960     assert (!lglsignedmarked (lgl, other));
10961     lglsignedmark (lgl, other);
10962   }
10963   assert (lglsignedmarked (lgl, a));
10964   hts = lglhts (lgl, a);
10965   w = lglhts2wchs (lgl, hts);
10966   eow = w + hts->count;
10967   res = 0;
10968   for (p = w; !res && p < eow; p++) {
10969     blit = *p;
10970     tag = blit & MASKCS;
10971     if (tag == TRNCS || tag == LRGCS) p++;
10972     red = blit & REDCS;
10973     if (red || tag == LRGCS) continue;
10974     other = blit >> RMSHFT;
10975     if (tag == BINCS) {
10976       res = lglsignedmarked (lgl, other);
10977     } else if (tag == TRNCS) {
10978       other2 = *p;
10979       res = lglsignedmarked (lgl, other) && lglsignedmarked (lgl, other2);
10980     } else {
10981       assert (tag == OCCS);
10982       lidx = other;
10983       c = lglidx2lits (lgl, 0, lidx);
10984       for (q = c; (other = *q); q++)
10985 	if (!lglsignedmarked (lgl, other)) break;
10986       res = !other;
10987     }
10988   }
10989   for (p = lgl->clause.start; p + 1 < lgl->clause.top; p++)
10990     lglunmark (lgl, *p);
10991   return res;
10992 }
10993 
lglsimpleprobeclausexists(LGL * lgl)10994 static int lglsimpleprobeclausexists (LGL * lgl) {
10995   int len = lglcntstk (&lgl->clause) - 1, a, b, c, * p, * s, res;
10996   assert (len >= 0);
10997   assert (!lgl->clause.top[-1]);
10998   s = lgl->clause.start;
10999   for (p = s + 1; p + 1 < lgl->clause.top; p++)
11000     if (lglhts (lgl, *s)->count > lglhts (lgl, *p)->count)
11001       SWAP (int, *s, *p);
11002   a = lgl->clause.start[0];
11003   if (len == 2) {
11004     b = lgl->clause.start[1];
11005     res = lglsimpleprobebinexists (lgl, a, b);
11006   } else if (len == 3) {
11007     b = lgl->clause.start[1];
11008     c = lgl->clause.start[2];
11009     res = lglsimpleprobetrnexists (lgl, a, b, c);
11010   } else if (len > 3)
11011     res = lglsimpleprobelrgexists (lgl, a);
11012   else res = 0;
11013   if (res) LOG (2, "will not add already existing clause");
11014   return res;
11015 }
11016 
lglsimpleprobeaddclausesonstack(LGL * lgl,Stk * stk)11017 static void lglsimpleprobeaddclausesonstack (LGL * lgl, Stk * stk) {
11018   int count, red, lit, size;
11019   const int * c, * p, * q;
11020   count = 0;
11021   for (c = stk->start; c < stk->top; c = p + 1) {
11022     red = *(p = c);
11023     if (p[1] == REMOVED) {
11024       p++;
11025       while (p + 1 < stk->top && p[1] == REMOVED) p++;
11026       continue;
11027     }
11028     assert (!red || red == REDCS);
11029     assert (lglmtstk (&lgl->clause));
11030     do {
11031       lit = *++p;
11032       lglpushstk (lgl, &lgl->clause, lit);
11033     } while (lit);
11034     if (!lglisimpcls (lgl) && !lglsimpleprobeclausexists (lgl)) {
11035       lgldrupligaddcls (lgl, REDCS);
11036       q = lgl->clause.start;
11037       size = lglcntstk (&lgl->clause);
11038       assert (size > 0);
11039       assert (!q[size-1]);
11040       size--;
11041       if (size > 2 && lgl->opts->prbsimple.val >= 3)
11042 	while ((lit = *q++))
11043 	  lglwrktouch (lgl, lit);
11044       if (size == 2 && lgl->opts->prbsimple.val >= 2)
11045 	lglwrktouch (lgl, -q[0]),
11046 	lglwrktouch (lgl, -q[1]);
11047       lgladdcls (lgl, red, 0, 1);
11048       count++;
11049     }
11050     lglclnstk (&lgl->clause);
11051     if (!lglflush (lgl)) break;
11052   }
11053   LOG (2, "added %d non-trivial clauses", count);
11054 }
11055 
lglsimpleprobeaddprbincls(LGL * lgl,int a,int b)11056 static void lglsimpleprobeaddprbincls (LGL * lgl, int a, int b) {
11057   assert (lgl->probing);
11058   assert (lglmtstk (&lgl->clause));
11059   assert (abs (a) != abs (b));
11060   assert (!lglval (lgl, a));
11061   assert (!lglval (lgl, b));
11062   lglpushstk (lgl, &lgl->clause, a);
11063   lglpushstk (lgl, &lgl->clause, b);
11064   lglpushstk (lgl, &lgl->clause, 0);
11065   if (!lglsimpleprobeclausexists (lgl)) {
11066     LOG (2, "added simple probing connecting binary clause", a, b);
11067     lgldrupligaddcls (lgl, REDCS);
11068     lgladdcls (lgl, 0, 0, 1);
11069   }
11070   lglclnstk (&lgl->clause);
11071 }
11072 
lglcmpilit(int * a,int * b)11073 static int lglcmpilit (int * a, int * b) {
11074   int res, l = *a, k = *b;
11075   if ((res = abs (l) - abs (k))) return res;
11076   return l - k;
11077 }
11078 
lglcmpcls(LGL * lgl,const int * c,const int * d)11079 static int lglcmpcls (LGL * lgl, const int * c, const int * d) {
11080   const int * p, * q;
11081   if (*c >= REMOVED && *d >= REMOVED) return c - d;
11082   if (*c >= REMOVED) return 1;
11083   if (*d >= REMOVED) return -1;
11084   for (p = c, q = d; *p && *q == *p; p++, q++)
11085     ;
11086   return *p - *q;
11087 }
11088 
lglcmpsz(LGL * lgl,const int * start,PSz * p,PSz * q)11089 static int lglcmpsz (LGL * lgl, const int * start, PSz * p, PSz * q) {
11090   const int * c, * d;
11091   int res;
11092   if ((res = p->size - q->size)) return res;
11093   c = start + p->pos, d = start + q->pos;
11094   if ((res = lglcmpcls (lgl, c, d))) return res;
11095   if ((res = c[-1] - d[-1])) return res;
11096   return p->pos - q->pos;
11097 }
11098 
11099 #define LGLCMPSZ(A,B) (lglcmpsz(lgl, start, (A), (B)))
11100 
lglrmdupclsonstack(LGL * lgl,Stk * stk,Stk * sort)11101 static void lglrmdupclsonstack (LGL * lgl, Stk * stk, Stk * sort) {
11102   int * start, * c, * p, * d, pos, size, i;
11103   PSz * ps;
11104   lglclnstk (sort);
11105   start = stk->start;
11106   for (c = start; c < stk->top; c = p + 1) {
11107     c++;
11108     assert (c < stk->top);
11109     pos = c - start;
11110     size = 0;
11111     for (p = c; *p; p++) size++;
11112     SORT (int, c, size, lglcmpilit);
11113     lglpushstk (lgl, sort, pos);
11114     lglpushstk (lgl, sort, size);
11115   }
11116   size = lglcntstk (sort)/2;
11117   if (size <= 1) return;
11118   ps = (PSz *) sort->start;
11119   SORT (PSz, ps, size, LGLCMPSZ);
11120   for (i = 1; i < size; i++) {
11121     if (ps[i-1].size != ps[i].size) continue;
11122     c = stk->start + ps[i-1].pos;
11123     d = stk->start + ps[i].pos;
11124     if (lglcmpcls (lgl, c, d)) continue;
11125     LOGCLS (4, d, "not copying duplicate %s clause", lglred2str (d[-1]));
11126     while (*d) *d++ = REMOVED;
11127     *d = REMOVED;
11128   }
11129 }
11130 
lglsimpleprobemerge(LGL * lgl,int repr,int nonrepr)11131 static void lglsimpleprobemerge (LGL * lgl, int repr, int nonrepr) {
11132   const int druplig = lgl->opts->druplig.val;
11133   Val valrepr, valnonrepr;
11134   Stk stk, sort;
11135   int unit;
11136   lglchkirrstats (lgl);
11137   lgl->stats->prb.simple.eqs++;
11138   assert (abs (repr) < abs (nonrepr));
11139   lglavar (lgl, nonrepr)->equiv = 1;
11140   CLR (stk); CLR (sort);
11141   if (druplig) {
11142     lgldrupligaddclsarg (lgl, REDCS, repr, -nonrepr, 0),
11143     lgldrupligaddclsarg (lgl, REDCS, -repr, nonrepr, 0);
11144   }
11145   lglsimpleprobeclscp (lgl, nonrepr, repr, &stk);
11146   lglsimpleprobeclscp (lgl, -nonrepr, -repr, &stk);
11147   lglrmdupclsonstack (lgl, &stk, &sort);
11148   lglsimpleprobeaddclausesonstack (lgl, &stk);
11149   lglrelstk (lgl, &sort);
11150   lglrelstk (lgl, &stk);
11151   lglflushclauses (lgl, nonrepr);
11152   lglflushclauses (lgl, -nonrepr);
11153   if (lgl->mt) goto FIXDRUPLIG;
11154   valrepr = lglval (lgl, repr);
11155   valnonrepr = lglval (lgl, nonrepr);
11156   if (valrepr && valnonrepr == valrepr) goto FIXDRUPLIG;
11157   if (valrepr && valrepr == -valrepr) {
11158     LOG (1, "equality between %d and %d became inconsistent", repr, nonrepr);
11159     lglmt (lgl);
11160     goto FIXDRUPLIG;
11161   }
11162   if (valrepr && !valnonrepr) unit = valrepr < 0 ? -nonrepr : nonrepr;
11163   else if (!valrepr && valnonrepr) unit = valnonrepr < 0 ? -repr : repr;
11164   else unit = 0, assert (!valrepr), assert (!valnonrepr);
11165   if (unit) {
11166     LOG (1, "new unit %d from equality between %d and %d", unit, repr, nonrepr);
11167     lglunit (lgl, unit);
11168     (void) lglflush (lgl);
11169   } else lglsimpleprobeaddprbincls (lgl, repr, -nonrepr),
11170 	 lglsimpleprobeaddprbincls (lgl, -repr, nonrepr);
11171   lglchkirrstats (lgl);
11172 FIXDRUPLIG:
11173   if (druplig) {
11174     lgldrupligdelclsarg (lgl, repr, -nonrepr, 0),
11175     lgldrupligdelclsarg (lgl, -repr, nonrepr, 0);
11176   }
11177 }
11178 
lglsimpleprobeqs(LGL * lgl)11179 static int lglsimpleprobeqs (LGL * lgl) {
11180   int a, b, res;
11181   res = 0;
11182   while (!lgl->mt && !lglmtstk (&lgl->sprb->eqs)) {
11183     a = lglpopstk (&lgl->sprb->eqs);
11184     b = lglpopstk (&lgl->sprb->eqs);
11185     if (lglval (lgl, a)) continue;
11186     assert (!lglval (lgl, b));
11187     assert (abs (a) != abs (b));
11188     if (lglsimpleprobemerged (lgl, a, b)) continue;
11189     if (abs (b) < abs (a)) SWAP (int, a, b);
11190     lglsimpleprobemerge (lgl, a, b);
11191     res++;
11192   }
11193   return res;
11194 }
11195 
lglspe(LGL * lgl,int lit)11196 static SPE * lglspe (LGL * lgl, int lit) {
11197   assert (2 <= abs (lit) && abs (lit) < lgl->nvars);
11198   return lgl->sprb->spes + lit;
11199 }
11200 
lglsimpleprobehbr(LGL * lgl,int touched,const int * c)11201 static void lglsimpleprobehbr (LGL * lgl, int touched, const int * c) {
11202   int blit, tag, lit, other, count, val, maxcount, rem, first, second;
11203   const int * p, * q, * w, * eow;
11204   unsigned sum, tmp;
11205   SPE * spe;
11206   HTS * hts;
11207   first = second = count = sum = 0;
11208   for (p = c; (lit = *p); p++) {
11209     if (lglwrktouched (lgl, lit)) return;
11210     if ((val = lglval (lgl, lit)) > 0) return;
11211     if (val < 0) continue;
11212     if (!first) first = lit;
11213     else if (!second) second = lit;
11214     sum += (unsigned) lit;
11215     count++;
11216   }
11217   if (count == 2) {
11218     assert (first && second);
11219     if (lglhasbin (lgl, -first, -second)) {
11220       LOG (2, "found equivalent literals %d and %d", -first, second);
11221       lglpushstk (lgl, &lgl->sprb->eqs, -first);
11222       lglpushstk (lgl, &lgl->sprb->eqs, second);
11223       goto DONE;
11224     }
11225   }
11226   rem = count;
11227   maxcount = 0;
11228   assert (lglmtstk (&lgl->sprb->counted));
11229   for (p = c; (lit = *p); p++) {
11230     if (INCSTEPS (prb.simple.steps) >= lgl->limits->prb.steps) goto DONE;
11231     val = lglval (lgl, lit);
11232     assert (val <= 0);
11233     if (val) continue;
11234     hts = lglhts (lgl, -lit);
11235     w = lglhts2wchs (lgl, hts);
11236     eow = w + hts->count;
11237     assert (lglmtstk (&lgl->sprb->marked));
11238     for (q = w; q < eow; q++) {
11239       if (INCSTEPS (prb.simple.steps) >= lgl->limits->prb.steps) goto DONE;
11240       blit = *q;
11241       tag = blit & MASKCS;
11242       if (tag == TRNCS || tag == LRGCS) q++;
11243       if (tag != BINCS) continue;
11244       other = blit >> RMSHFT;
11245       val = lglval (lgl, other);
11246       assert (val >= 0);
11247       if (val) continue;
11248       if ((spe = lglspe (lgl, other))->mark) continue;
11249       if (lglspe (lgl, -other)->mark) {
11250 	LOG (2, "unit %d through very simple hyper binary resolution", -lit);
11251 	lglpushstk (lgl, &lgl->sprb->units, -lit);
11252 	goto DONE;
11253       }
11254       if (!spe->count) lglpushstk (lgl, &lgl->sprb->counted, other);
11255       spe->sum += (unsigned) lit;
11256       spe->count++;
11257       spe->mark = 1;
11258       lglpushstk (lgl, &lgl->sprb->marked, other);
11259       if (spe->count > maxcount) maxcount = spe->count;
11260     }
11261     while (!lglmtstk (&lgl->sprb->marked)) {
11262       other = lglpopstk (&lgl->sprb->marked);
11263       spe = lglspe (lgl, other);
11264       assert (spe->mark);
11265       spe->mark = 0;
11266     }
11267     rem--;
11268     assert (maxcount + rem <= count);
11269     if (maxcount + rem + 1 < count) goto DONE;
11270   }
11271   if (count <= 2) goto DONE;
11272   for (q = lgl->sprb->counted.start; q < lgl->sprb->counted.top; q++) {
11273     other = *q;
11274     assert (!lglval (lgl, other));
11275     spe = lglspe (lgl, other);
11276     assert (spe->count <= count);
11277     if (spe->count == count) {
11278       LOG (2, "unit %d through simple hyper binary resolution", other);
11279       lglpushstk (lgl, &lgl->sprb->units, other);
11280     } else if (spe->count + 1 == count) {
11281       tmp = sum - spe->sum;
11282       lit = (int) tmp;
11283       assert (2 <= abs (lit) && abs (lit) < lgl->nvars);
11284       if (abs (lit) != abs (other) && !lglhasbin (lgl, other, lit)) {
11285 	LOG (2, "simple hyper binary resolvent %d %d", other, lit);
11286 	lglpushstk (lgl, &lgl->sprb->impls, other);
11287 	lglpushstk (lgl, &lgl->sprb->impls, lit);
11288       }
11289     }
11290   }
11291   for (p = c; (lit = *p); p++) {
11292     if (lglval (lgl, lit)) continue;
11293     spe = lglspe (lgl, lit);
11294     if (spe->count + 2 != count) continue;
11295     tmp = sum - spe->sum;
11296     tmp -= (unsigned) lit;
11297     other = (int) tmp;
11298     assert (2 <= abs (other) && abs (other) < lgl->nvars);
11299     if (abs (lit) != abs (other) && !lglhasbin (lgl, other, lit)) {
11300       LOG (2, "self-subsuming hyper binary resolvent %d %d", other, lit);
11301       lglpushstk (lgl, &lgl->sprb->impls, other);
11302       lglpushstk (lgl, &lgl->sprb->impls, lit);
11303     }
11304   }
11305 DONE:
11306   while (!lglmtstk (&lgl->sprb->counted)) {
11307     lit = lglpopstk (&lgl->sprb->counted);
11308     spe = lglspe (lgl, lit);
11309     CLRPTR (spe);
11310   }
11311   lglclnstk (&lgl->sprb->marked);
11312 }
11313 
lglpushnmarkseen(LGL * lgl,int lit)11314 static void lglpushnmarkseen (LGL * lgl, int lit) {
11315   lglpushstk (lgl, &lgl->seen, lit);
11316   lglmarkunmarked (lgl, lit);
11317 }
11318 
lglsignedmarknpushseen(LGL * lgl,int lit)11319 static void lglsignedmarknpushseen (LGL * lgl, int lit) {
11320   lglsignedmark (lgl, lit);
11321   lglpushstk (lgl, &lgl->seen, lit);
11322 }
11323 
lglsimpleliftmark(LGL * lgl,int root,int level)11324 static void lglsimpleliftmark (LGL * lgl, int root, int level) {
11325   const int * p, * w, * eow;
11326   int blit, tag, other;
11327   HTS * hts;
11328   INCSTEPS (prb.simple.steps);
11329   assert (level > 0);
11330   assert (lglsignedmarked (lgl, -root));
11331   LOG (3, "next simple lifting marking from %d at level %d", root, level);
11332   hts = lglhts (lgl, root);
11333   w = lglhts2wchs (lgl, hts);
11334   eow = w + hts->count;
11335   for (p = w; p < eow; p++) {
11336     blit = *p;
11337     tag = blit & MASKCS;
11338     if (tag == TRNCS || tag == LRGCS) p++;
11339     if (tag != BINCS) continue;
11340     other = blit >> RMSHFT;
11341     if (lglsignedmarked (lgl, other)) continue;
11342     lglsignedmarknpushseen (lgl, other);
11343     LOG (4, "next simple lifting marking from %d at level %d marked %d",
11344          root, level, other);
11345     if (level > 1) lglsimpleliftmark (lgl, -other, level-1);
11346   }
11347 }
11348 
lglsimpleliftcollect(LGL * lgl,int root,int start,int level)11349 static void lglsimpleliftcollect (LGL * lgl, int root, int start, int level) {
11350   const int * p, * w, * eow;
11351   int blit, tag, other;
11352   HTS * hts;
11353   INCSTEPS (prb.simple.steps);
11354   assert (level > 0);
11355   LOG (3, "next simple lifting collecting from %d at level %d", start, level);
11356   hts = lglhts (lgl, start);
11357   w = lglhts2wchs (lgl, hts);
11358   eow = w + hts->count;
11359   for (p = w; p < eow; p++) {
11360     blit = *p;
11361     tag = blit & MASKCS;
11362     if (tag == TRNCS || tag == LRGCS) p++;
11363     if (tag != BINCS) continue;
11364     other = blit >> RMSHFT;
11365     if (other == -root) continue;
11366     if (lglsignedmarked (lgl, other)) {
11367       LOG (2, "simple lifted unit %d with root %d", other, root);
11368       lglpushstk (lgl, &lgl->sprb->units, other);
11369     } else if (other != root && lglsignedmarked (lgl, -other)) {
11370       LOG (2, "found equivalent literals %d and %d", root, other);
11371       lglpushstk (lgl, &lgl->sprb->eqs, root);
11372       lglpushstk (lgl, &lgl->sprb->eqs, other);
11373     }
11374     if (level > 1) lglsimpleliftcollect (lgl, root, -other, level-1);
11375   }
11376 }
11377 
lglsimplelift(LGL * lgl,int root)11378 static void lglsimplelift (LGL * lgl, int root) {
11379   int count, pos, neg;
11380   pos = lglhts (lgl, root)->count;
11381   neg = lglhts (lgl, -root)->count;
11382   if (neg < pos) root = -root;
11383   LOG (2, "next simple lifting %d", root);
11384   assert (lglmtstk (&lgl->seen));
11385   assert (!lglsignedmarked (lgl, -root));
11386   lglsignedmarknpushseen (lgl, -root);
11387   lglsimpleliftmark (lgl, root, lgl->opts->prbsimpleliftdepth.val);
11388   count = lglcntstk (&lgl->seen);
11389   LOG (3, "simple probing lifting marked %d literals for root %d",
11390        count, root);
11391   if (!count) return;
11392   lglsimpleliftcollect (lgl, root, -root, lgl->opts->prbsimpleliftdepth.val);
11393 #ifndef NLGLOG
11394   {
11395     int units = lglcntstk (&lgl->sprb->units);
11396     int eqs = lglcntstk (&lgl->sprb->eqs);
11397     assert (!(eqs & 1));
11398     eqs >>= 1;
11399     LOG (3, "found %d units through simple lifting for %d", units, root);
11400     LOG (3, "found %d equivalences through simple lifting for %d", eqs, root);
11401   }
11402 #endif
11403   lglpopnunmarkstk (lgl, &lgl->seen);
11404 }
11405 
lglsimpleprobelit(LGL * lgl,int lit)11406 static void lglsimpleprobelit (LGL * lgl, int lit) {
11407   int blit, tag, other, other2, red, lidx, cls[4];
11408   const int * p, * w, * eow, * c;
11409   HTS * hts;
11410   lgl->stats->prb.simple.probed++;
11411   assert (!lglval (lgl, lit));
11412   lglclnstk (&lgl->sprb->units);
11413   lglclnstk (&lgl->sprb->impls);
11414   if (!lglwrktouched (lgl, -lit)) lglsimplelift (lgl, lit);
11415   LOG (2, "next simple probing %d", lit);
11416   hts = lglhts (lgl, lit);
11417   if (!hts->count) return;
11418   w = lglhts2wchs (lgl, hts);
11419   eow = w + hts->count;
11420   for (p = w; p < eow; p++) {
11421     if (INCSTEPS (prb.simple.steps) >= lgl->limits->prb.steps) goto DONE;
11422     blit = *p;
11423     tag = blit & MASKCS;
11424     if (tag == TRNCS || tag == LRGCS) p++;
11425     if (tag == BINCS || tag == LRGCS) continue;
11426     if (tag == TRNCS) {
11427       other = blit >> RMSHFT;
11428       if (lglval (lgl, other)) continue;
11429       other2 = *p;
11430       if (lglval (lgl, other2)) continue;
11431       cls[0] = lit, cls[1] = other, cls[2] = other2, cls[3] = 0;
11432       lglsimpleprobehbr (lgl, lit, cls);
11433     } else {
11434       assert (tag == OCCS);
11435       red = (blit & REDCS);
11436       lidx = (blit >> RMSHFT);
11437       c = lglidx2lits (lgl, red, lidx);
11438       lglsimpleprobehbr (lgl, lit, c);
11439     }
11440   }
11441 DONE:
11442   assert (lglmtstk (&lgl->seen));
11443   lglpopnunmarkstk (lgl, &lgl->seen);
11444 }
11445 
lglprtsimpleproberem(LGL * lgl)11446 static void lglprtsimpleproberem (LGL * lgl) {
11447   int idx, ret = 0, rem = 0, sum;
11448   for (idx = 2; idx < lgl->nvars; idx++) {
11449     if (!lglisfree (lgl, idx)) continue;
11450     if (lglavar (lgl, idx)->donotsimpleprobe) ret++; else rem++;
11451   }
11452   if (rem) {
11453     sum = rem + ret;
11454     lglprt (lgl, 1,
11455       "[simpleprobe-%d] %d variables remain %.0f%% (%d retained %.0f%%)",
11456       lgl->stats->prb.simple.count,
11457       rem, lglpcnt (rem, sum),
11458       ret, lglpcnt (ret, sum));
11459   } else {
11460     lglprt (lgl, 1,
11461       "[simpleprobe-%d] fully completed simple probing",
11462       lgl->stats->prb.simple.count);
11463     for (idx = 2; idx < lgl->nvars; idx++)
11464       lglavar (lgl, idx)->donotsimpleprobe = 0;
11465   }
11466 }
11467 
lglirrlits(LGL * lgl)11468 static int64_t lglirrlits (LGL * lgl) { return lgl->stats->irr.lits.cur; }
11469 
lglredlits(LGL * lgl)11470 static int64_t lglredlits (LGL * lgl) {
11471   int64_t res = 2*lgl->stats->red.bin + 3*lgl->stats->red.trn;
11472   int glue;
11473   for (glue = 0; glue <= MAXGLUE; glue++) {
11474     res += lglcntstk (lgl->red + glue);
11475     res -= 2*lgl->stats->lir[glue].clauses;
11476   }
11477   return res;
11478 }
11479 
lglszpenaux(LGL * lgl,int litstoo,int redtoo)11480 static int lglszpenaux (LGL * lgl, int litstoo, int redtoo) {
11481   int64_t size64;
11482   int res;
11483   size64 = lgl->stats->irr.clauses.cur;
11484   if (litstoo) size64 += lglirrlits (lgl)/4;
11485   if (redtoo) {
11486     size64 += lgl->stats->irr.clauses.cur;
11487     if (litstoo) size64 += lglredlits (lgl)/4;
11488   }
11489   assert (size64 >= 0);
11490   size64 /= lgl->opts->sizepen.val;
11491   if (size64 >= INT_MAX) res = 32;
11492   else res = lglceild ((int) size64);
11493   if (res < 0) res = 0;
11494   if (res > lgl->opts->sizemaxpen.val) res = lgl->opts->sizemaxpen.val;
11495   return res;
11496 }
11497 
lglszpen(LGL * lgl)11498 static int lglszpen (LGL * lgl) { return lglszpenaux (lgl, 0, 0); }
11499 
11500 #ifndef NLGLYALSAT
11501 
lglitszpen(LGL * lgl)11502 static int lglitszpen (LGL * lgl) {
11503   int res = lglceild (lgl->stats->irr.lits.cur/lgl->opts->sizepen.val);
11504   if (res < 0) res = 0;
11505   if (res > lgl->opts->sizemaxpen.val + 2)
11506     res = lgl->opts->sizemaxpen.val + 2;
11507   return res;
11508 }
11509 
11510 #endif
11511 
lglvisearch(LGL * lgl)11512 static int64_t lglvisearch (LGL * lgl) {
11513   int64_t res = lgl->stats->visits.search;
11514   assert (res >= lgl->limits->inc.visits);
11515   res -= lgl->limits->inc.visits;
11516   return res;
11517 }
11518 
lglsetprbsimplelim(LGL * lgl)11519 static void lglsetprbsimplelim (LGL * lgl) {
11520   int64_t limit, irrlim;
11521   int pen, szpen;
11522   if (lgl->opts->prbsimplertc.val || lgl->opts->prbrtc.val) {
11523     lgl->limits->prb.steps = LLMAX;
11524     lglprt (lgl, 1,
11525       "[simpleprobe-%d] really no limit (run to completion)",
11526       lgl->stats->prb.simple.count);
11527   } else {
11528     limit = (lgl->opts->prbsimplereleff.val*lglvisearch (lgl))/1000;
11529     if (limit < lgl->opts->prbsimplemineff.val)
11530       limit = lgl->opts->prbsimplemineff.val;
11531     if (lgl->opts->prbsimplemaxeff.val >= 0 &&
11532         limit > lgl->opts->prbsimplemaxeff.val)
11533       limit = lgl->opts->prbsimplemaxeff.val;
11534     if (lgl->stats->prb.simple.count <= 1 &&
11535         lgl->opts->boost.val &&
11536         lgl->opts->prbsimpleboost.val > 1) {
11537       lglprt (lgl, 1,
11538 	"[simpleprobe-%d] boosting simple probing limit by %d",
11539 	lgl->stats->prb.simple.count, lgl->opts->prbsimpleboost.val);
11540       limit *= lgl->opts->prbsimpleboost.val;
11541     }
11542     limit >>= (pen = lgl->limits->prb.simple.pen + (szpen = lglszpen (lgl)));
11543     irrlim = (2*lgl->stats->irr.clauses.cur) >> szpen;
11544     if (lgl->opts->irrlim.val && limit < irrlim) {
11545       limit = irrlim;
11546       lglprt (lgl, 1,
11547   "[simpleprobe-%d] limit %lld based on %d irredundant clauses penalty %d",
11548 	lgl->stats->prb.simple.count,
11549 	(LGLL) limit, lgl->stats->irr.clauses.cur, szpen);
11550     } else
11551       lglprt (lgl, 1,
11552 	"[simpleprobe-%d] limit %lld penalty %d = %d + %d",
11553 	lgl->stats->prb.simple.count, (LGLL) limit,
11554 	pen, lgl->limits->prb.simple.pen, szpen);
11555     lgl->limits->prb.steps = lgl->stats->prb.simple.steps + limit;
11556   }
11557 }
11558 
lgldelaying(LGL * lgl,const char * name,int * delptr)11559 static int lgldelaying (LGL * lgl, const char * name, int * delptr) {
11560   if (!*delptr) return 0;
11561   *delptr -= 1;
11562   lglprt (lgl, 2,
11563     "[%s-delayed] skipping this scheduled invocation and %d more",
11564     name, *delptr);
11565   return 1;
11566 }
11567 
lglsimpleprobe(LGL * lgl)11568 static int lglsimpleprobe (LGL * lgl) {
11569   int deltarem, nunits, hbrs, neqs, oldrem = lglrem (lgl);
11570   int lit, success, nvars;
11571 
11572   if (lgldelaying (lgl, "simpleprobe",
11573         &lgl->limits->prb.simple.del.rem)) return 1;
11574 
11575   lglstart (lgl, &lgl->times->prb.simple);
11576   lgl->stats->prb.simple.count++;
11577 
11578   assert (!lgl->simp && !lgl->probing && !lgl->simpleprobing);
11579   lgl->simp = lgl->probing = lgl->simpleprobing = 1;
11580 
11581 
11582   NEW (lgl->sprb, 1);
11583 
11584   if (lgl->level > 0) lglbacktrack (lgl, 0);
11585   lglgc (lgl);
11586   assert (lgl->frozen);
11587   lgldense (lgl, 0);
11588   lglsimpleprobeinit (lgl);
11589   lglsetprbsimplelim (lgl);
11590   neqs = hbrs = nunits = 0;
11591 
11592   nvars = lgl->nvars;
11593   NEW (lgl->sprb->spes, 2*nvars);
11594   lgl->sprb->spes += nvars;
11595 
11596   while (!lgl->mt && (lit = lglwrknext (lgl))) {
11597     if (INCSTEPS (prb.simple.steps) >= lgl->limits->prb.steps) break;
11598     if (!lglisfree (lgl, lit)) continue;
11599     if (lglavar (lgl, lit)->equiv) continue;
11600     lglsimpleprobelit (lgl, lit);
11601     if (lgl->mt) break;
11602     lglchkirrstats (lgl);
11603     nunits += lglsimpleprobeunits (lgl);
11604     if (lgl->mt) break;
11605     hbrs += lglsimpleprobeimpls (lgl);
11606     if (lgl->mt) break;
11607     neqs += lglsimpleprobeqs (lgl);
11608     if (!lglflush (lgl)) break;
11609     if (lglterminate (lgl)) break;
11610     if (!lglsyncunits (lgl)) break;
11611   }
11612 
11613   lglsimpleprobereset (lgl, nvars);
11614   lglsparse (lgl);
11615   if (!lgl->mt) lgldecomp (lgl);
11616 
11617   DEL (lgl->sprb, 1);
11618 
11619   deltarem = oldrem - lglrem (lgl);
11620   success = deltarem || hbrs || nunits;
11621   LGLUPDPEN (prb.simple, deltarem);
11622   lglprtsimpleproberem (lgl);
11623 
11624   lglprt (lgl, 1 + !success,
11625     "[simpleprobe-%d] removed %d variables, found %d hbrs, %d units",
11626     lgl->stats->prb.simple.count, deltarem, hbrs, nunits);
11627 
11628   assert (lgl->simp && lgl->probing && lgl->simpleprobing);
11629   lgl->simp = lgl->probing = lgl->simpleprobing = 0;
11630   lglrep (lgl, 2, 'p');
11631   lglstop (lgl);
11632   return !lgl->mt;
11633 }
11634 
lglmvbcls(LGL * lgl,int a,int b)11635 static int lglmvbcls (LGL * lgl, int a, int b) {
11636   int res = 0;
11637   assert (abs (a) != abs (b));
11638   assert (!lglval (lgl, a));
11639   assert (!lglval (lgl, b));
11640   assert (lglmtstk (&lgl->clause));
11641   lglpushstk (lgl, &lgl->clause, a);
11642   lglpushstk (lgl, &lgl->clause, b);
11643   lglpushstk (lgl, &lgl->clause, 0);
11644   if (!lglsimpleprobeclausexists (lgl)) {
11645     LOG (2, "moving redundant binary clause %d %d", a, b);
11646     lgldrupligaddcls (lgl, REDCS);
11647     lgladdcls (lgl, REDCS, 0, 1);
11648     res = 1;
11649   }
11650   lglclnstk (&lgl->clause);
11651   lgl->stats->moved.bin++;
11652   return res;
11653 }
11654 
lglrmvbcls(LGL * lgl,int a,int b)11655 static int lglrmvbcls (LGL * lgl, int a, int b) {
11656   lglrmbcls (lgl, a, b, 0);
11657   if (lgl->opts->move.val) return lglmvbcls (lgl, a, b);
11658   return 0;
11659 }
11660 
lglmvtcls(LGL * lgl,int a,int b,int c)11661 static int lglmvtcls (LGL * lgl, int a, int b, int c) {
11662   int res = 0;
11663   assert (abs (a) != abs (b));
11664   assert (abs (a) != abs (c));
11665   assert (abs (b) != abs (c));
11666   assert (lglmtstk (&lgl->clause));
11667   lglpushstk (lgl, &lgl->clause, a);
11668   lglpushstk (lgl, &lgl->clause, b);
11669   lglpushstk (lgl, &lgl->clause, c);
11670   lglpushstk (lgl, &lgl->clause, 0);
11671   if (!lglsimpleprobeclausexists (lgl)) {
11672     LOG (2, "moving redundant ternary clause %d %d %d", a, b, c);
11673     lgldrupligaddcls (lgl, REDCS);
11674     lgladdcls (lgl, REDCS, 0, 1);
11675     res = 1;
11676   }
11677   lglclnstk (&lgl->clause);
11678   lgl->stats->moved.trn++;
11679   return res;
11680 }
11681 
lglrmvtcls(LGL * lgl,int a,int b,int c)11682 static int lglrmvtcls (LGL * lgl, int a, int b, int c) {
11683   assert (abs (a) != abs (b));
11684   assert (abs (a) != abs (c));
11685   assert (abs (b) != abs (c));
11686   lglrmtcls (lgl, a, b, c, 0);
11687   if (lgl->opts->move.val >= 2) return lglmvtcls (lgl, a, b, c);
11688   return 0;
11689 }
11690 
lglwaiting(LGL * lgl,const char * str,int wait)11691 static int lglwaiting (LGL * lgl, const char * str, int wait) {
11692   if (!wait) return 0;
11693   if (!lgl->wait) return 0;
11694   if (wait >= 2 && lgl->opts->elim.val && !lgl->elmrtc) {
11695     if (str)
11696       lglprt (lgl, 2,
11697 	"[%s-waiting] on variable elimination to be completed", str);
11698     return 1;
11699   }
11700   if (wait >= 1 && lgl->opts->block.val && !lgl->blkrtc) {
11701     if (str)
11702       lglprt (lgl, 2,
11703 	"[%s-waiting] on blocked clause elimination to be completed", str);
11704     return 1;
11705   }
11706   return 0;
11707 }
11708 
lglbasicate(LGL * lgl,int lit)11709 static void lglbasicate (LGL * lgl, int lit) {
11710   const int druplig = lgl->opts->druplig.val;
11711   int blit, tag, red, other, other2, lidx;
11712   const int * w, * eow, * p, * c, * l;
11713   int nonfalse, numtrue, val;
11714   HTS * hts;
11715   if (!lgl->opts->bate.val) return;
11716   if (lglwaiting (lgl, 0, lgl->opts->batewait.val)) return;
11717 RESTART:
11718   hts = lglhts (lgl, -lit);
11719   w = lglhts2wchs (lgl, hts);
11720   eow = w + hts->count;
11721   for (p = w; p < eow; p++) {
11722     blit = * p;
11723     tag = blit & MASKCS;
11724     if (tag == TRNCS || tag == LRGCS) p++;
11725     red = blit & REDCS;
11726     if (red) continue;
11727     if (tag == BINCS) continue;
11728     if (tag == TRNCS) {
11729       other = blit >> RMSHFT;
11730       numtrue = 0;
11731       if ((val = lglval (lgl, other)) < 0) continue;
11732       if (val > 0) {
11733 	if (!lglevel (lgl, other)) continue;
11734 	if (lgltd (lgl, other)->irr) numtrue++;
11735       }
11736       other2 = *p;
11737       if ((val = lglval (lgl, other2)) < 0) continue;
11738       if (val > 0) {
11739 	if (!lglevel (lgl, other2)) continue;
11740 	if (lgltd (lgl, other2)->irr) numtrue++;
11741       }
11742       if (!numtrue) continue;
11743       LOG (2, "basic ATE ternary clause %d %d %d", -lit, other, other2);
11744       lgl->stats->prb.basic.ate.trnr++;
11745       if (!lglrmvtcls (lgl, -lit, other, other2))
11746 	lgldrupligdelclsarg (lgl, -lit, other, other2, 0);
11747       goto RESTART;
11748     } else {
11749       assert (tag == OCCS || tag == LRGCS);
11750       if (tag == LRGCS && lgl->dense) continue;
11751       lidx = (tag == LRGCS) ? *p : (blit >> RMSHFT);
11752       assert (!red);
11753       c = lglidx2lits (lgl, 0, lidx);
11754       numtrue = nonfalse = 0;
11755       for (l = c; (nonfalse < 2 || !numtrue) && (other = *l); l++) {
11756 	if (other == -lit) continue;
11757 	assert (other != lit);
11758 	if ((val = lglval (lgl, other)) >= 0) nonfalse++;
11759 	if (val > 0) {
11760 	   if (!lglevel (lgl, other)) { numtrue = -1; break; }
11761 	   if (lgltd (lgl, other)->irr) numtrue++;
11762 	}
11763       }
11764       if (numtrue > 0 && nonfalse >= 2) {
11765 	LOGCLS (2, c, "basic ATE large clause");
11766 	lgl->stats->prb.basic.ate.lrg++;
11767 	if (druplig) lgldrupligdelclsaux (lgl, c);
11768 	lglrmlcls (lgl, lidx, 0);
11769 	goto RESTART;
11770       }
11771     }
11772   }
11773 }
11774 
lglbasicatestats(LGL * lgl)11775 static void lglbasicatestats (LGL * lgl) {
11776   int n = lgl->stats->prb.basic.ate.lrg + lgl->stats->prb.basic.ate.trnr;
11777   int d = n - lgl->stats->prb.basic.lastate;
11778   assert (d >= 0);
11779   if (d <= 0) return;
11780   lgl->stats->prb.basic.ate.count++;
11781   lglprt (lgl, 1,
11782     "[bate-%d] eliminated %d asymmetric tautologies during probing",
11783     lgl->stats->prb.basic.ate.count, d);
11784   lgl->stats->prb.basic.lastate = n;
11785 }
11786 
lglbasicprobelit(LGL * lgl,int root)11787 static void lglbasicprobelit (LGL * lgl, int root) {
11788   int old, ok, dom, lit, val;
11789   Stk lift, saved;
11790   const int * p;
11791   CLR (lift); CLR (saved);
11792   assert (lgl->simp);
11793   assert (lgl->probing || lgl->cceing);
11794   assert (!lgl->level);
11795   LOG (2, "next probe %d positive phase", root);
11796   assert (!lgl->level);
11797   if (lgl->treelooking) lgl->stats->prb.treelook.probed++;
11798   else if (lgl->cceing) lgl->stats->cce.probed++;
11799   else assert (lgl->basicprobing), lgl->stats->prb.basic.probed++;
11800   if (lglrand (lgl) & (1<<12)) root = -root;
11801   lgliassume (lgl, root);
11802   old = lgl->next;
11803   ok = lglbcp (lgl);
11804   dom = 0;
11805   if (ok) {
11806     lglclnstk (&saved);
11807     lglbasicate (lgl, root);
11808     for (p = lgl->trail.start + old; p < lgl->trail.top; p++) {
11809       lit = *p;
11810       if (lit == root) continue;
11811       lglpushstk (lgl, &saved, lit);
11812     }
11813   } else dom = lglprbana (lgl, root);
11814   lglbacktrack (lgl, 0);
11815   if (!ok) {
11816     LOG (1, "failed literal %d on probing", dom, root);
11817     lglpushstk (lgl, &lift, -dom);
11818     goto MERGE;
11819   }
11820   LOG (2, "next probe %d negative phase", -root);
11821   assert (!lgl->level);
11822   if (lgl->treelooking) lgl->stats->prb.treelook.probed++;
11823   else if (lgl->cceing) lgl->stats->cce.probed++;
11824   else assert (lgl->basicprobing), lgl->stats->prb.basic.probed++;
11825   lgliassume (lgl, -root);
11826   ok = lglbcp (lgl);
11827   if (ok) {
11828     lglbasicate (lgl, -root);
11829     for (p = saved.start; p < saved.top; p++) {
11830       lit = *p;
11831       val = lglval (lgl, lit);
11832       if (val <= 0) continue;
11833       if (lgl->treelooking) lgl->stats->prb.treelook.lifted++;
11834       else if (lgl->cceing) lgl->stats->cce.lifted++;
11835       else assert (lgl->basicprobing), lgl->stats->prb.basic.lifted++;
11836       lglpushstk (lgl, &lift, lit);
11837       LOG (2, "lifted %d", lit);
11838     }
11839   } else dom = lglprbana (lgl, -root);
11840   lglbacktrack (lgl, 0);
11841   if (!ok) {
11842     LOG (1, "failed literal %d on probing %d", dom, -root);
11843     lglpushstk (lgl, &lift, -dom);
11844   }
11845 MERGE:
11846   while (!lglmtstk (&lift)) {
11847     lit = lglpopstk (&lift);
11848     val = lglval (lgl, lit);
11849     if (val > 0) continue;
11850     if (val < 0) goto EMPTY;
11851     if (lgl->opts->druplig.val) {
11852       lgldrupligaddclsarg (lgl, REDCS, -root, lit, 0);
11853       lgldrupligaddclsarg (lgl, REDCS, root, lit, 0);
11854     }
11855     lglunit (lgl, lit);
11856     if (lgl->opts->druplig.val) {
11857       lgldrupligdelclsarg (lgl, -root, lit, 0);
11858       lgldrupligdelclsarg (lgl, root, lit, 0);
11859     }
11860     if (lgl->treelooking) lgl->stats->prb.treelook.failed++;
11861     else if (lgl->cceing) lgl->stats->cce.failed++;
11862     else assert (lgl->basicprobing), lgl->stats->prb.basic.failed++;
11863     if (lglbcp (lgl)) continue;
11864 EMPTY:
11865     LOG (1, "empty clause after propagating lifted and failed literals");
11866     lglmt (lgl);
11867   }
11868   lglrelstk (lgl, &lift);
11869   lglrelstk (lgl, &saved);
11870 }
11871 
lgltvar(LGL * lgl,int lit)11872 static TVar * lgltvar (LGL * lgl, int lit) {
11873   int idx = abs (lit);
11874   assert (2 <= idx && idx < lgl->nvars);
11875   assert (lgl->tlk);
11876   return lgl->tlk->tvars + idx;
11877 }
11878 
lglsignedtlmark(LGL * lgl,int lit)11879 static void lglsignedtlmark (LGL * lgl, int lit) {
11880   TVar * tv = lgltvar (lgl, lit);
11881   unsigned bit = 1u << (lit < 0);
11882   if (tv->mark & bit) return;
11883   tv->mark |= bit;
11884 }
11885 
lglsignedtlmarked(LGL * lgl,int lit)11886 static int lglsignedtlmarked (LGL * lgl, int lit) {
11887   TVar * tv = lgltvar (lgl, lit);
11888   unsigned bit = 1u << (lit < 0);
11889   return tv->mark & bit;
11890 }
11891 
lgltlenq(LGL * lgl,int start)11892 static void lgltlenq (LGL * lgl, int start) {
11893   int lit, blit, tag, other, oldcount, newcount, * stk;
11894   unsigned delta, i, j, mod;
11895   const int * p, * w, * eos;
11896   HTS * hts;
11897   assert (!lglsignedtlmarked (lgl, start));
11898   lglsignedtlmark (lgl, start);
11899   lglpushstk (lgl, &lgl->tlk->stk, start);
11900   while (!lglmtstk (&lgl->tlk->stk)) {
11901     lit = lglpopstk (&lgl->tlk->stk);
11902     LOG (2, "tree-look enqueue %d%s", lit, lit == start ? " start":"");
11903     if (lit) {
11904       assert (!lglval (lgl, lit));
11905       assert (lglsignedtlmarked (lgl, lit));
11906       lglpushstk (lgl, &lgl->tlk->seen, lit);
11907       lglpushstk (lgl, &lgl->tlk->stk, 0);
11908       hts = lglhts (lgl, lit);
11909       w = lglhts2wchs (lgl, hts);
11910       eos = w + hts->count;
11911       oldcount = lglcntstk (&lgl->tlk->stk);
11912       for (p = w; p < eos; p++) {
11913         INCSTEPS (prb.treelook.steps);
11914 	blit = *p;
11915 	tag = blit & MASKCS;
11916 	if (tag == OCCS) continue;
11917 	if (tag == TRNCS || tag == LRGCS) { p++; continue; }
11918 	assert (tag == BINCS);
11919 	other = -(blit >> RMSHFT);
11920 	if (lglval (lgl, other)) assert (lglval (lgl, other) < 0);
11921 	else if (!lglsignedtlmarked (lgl, other)) {
11922 	  lglsignedtlmark (lgl, other);
11923 	  lglpushstk (lgl, &lgl->tlk->stk, other);
11924 	}
11925       }
11926       newcount = lglcntstk (&lgl->tlk->stk);
11927       delta = newcount - oldcount;
11928       assert (delta >= 0);
11929       if ((mod = delta) <= 1) continue;
11930       stk = lgl->tlk->stk.start;
11931       for (i = 0; i < delta-1; i++, mod--) {
11932 	assert (mod > 0);
11933 	j = i + (lglrand (lgl) % mod);
11934 	assert (i <= j && j < delta);
11935 	if (i == j) continue;
11936 	SWAP (int, stk[i + oldcount], stk[j + oldcount]);
11937       }
11938     } else lglpushstk (lgl, &lgl->tlk->seen, 0);
11939   }
11940 }
11941 
lglisroot(LGL * lgl,int lit)11942 static int lglisroot (LGL * lgl, int lit) { return !lglhasbins (lgl, lit); }
11943 
lgltlunmarkall(LGL * lgl)11944 static void lgltlunmarkall (LGL * lgl) {
11945   int idx;
11946   for (idx = 2; idx < lgl->nvars; idx++)
11947     lgl->tlk->tvars[idx].mark = 0;
11948 }
11949 
lgltlschedlit(LGL * lgl,int lit)11950 static int lgltlschedlit (LGL * lgl, int lit) {
11951   if (INCSTEPS (prb.treelook.steps) > lgl->limits->prb.steps) return 0;
11952   if (!lglisfree (lgl, lit)) return 1;
11953   if (lglsignedtlmarked (lgl, lit)) return 1;
11954   if (!lglisroot (lgl, -lit)) return 1;
11955   if (!lgl->tlk->lkhd && lglavar (lgl, lit)->donotreelook) return 1;
11956   if (lgl->opts->treelook.val >= 2) {
11957     lglbasicprobelit (lgl, -lit);
11958     if (lgl->mt) return 0;
11959     if (lglterminate (lgl)) return 0;
11960     if (!lglisfree (lgl, lit)) return 1;
11961     if (!lglisroot (lgl, -lit)) return 1;
11962     if (!lglhasbins (lgl, lit)) return 1;
11963   }
11964   lgltlenq (lgl, lit);
11965   return 1;
11966 }
11967 
lgltlschedanylit(LGL * lgl,int lit)11968 static int lgltlschedanylit (LGL * lgl, int lit) {
11969   if (INCSTEPS (prb.treelook.steps) > lgl->limits->prb.steps) return 0;
11970   if (!lglisfree (lgl, lit)) return 1;
11971   if (lglsignedtlmarked (lgl, lit)) return 1;
11972   if (!lgl->tlk->lkhd && lglavar (lgl, lit)->donotreelook) return 1;
11973   if (lgl->opts->treelook.val >= 2) {
11974     lglbasicprobelit (lgl, -lit);
11975     if (lgl->mt) return 0;
11976     if (lglterminate (lgl)) return 0;
11977     if (!lglisfree (lgl, lit)) return 1;
11978   }
11979   lgltlenq (lgl, lit);
11980   return 1;
11981 }
11982 
lgltlsched(LGL * lgl)11983 static void lgltlsched (LGL * lgl) {
11984   int idx, round, count, * p;
11985   LOG (1, "scheduling tree-look literals");
11986   for (round = 0; !lgl->mt && round < 2; round++) {
11987     assert (lglmtstk (&lgl->tlk->seen));
11988     assert (lglmtstk (&lgl->tlk->stk));
11989     if (lglrandlitrav (lgl, lgltlschedlit))
11990       lglrandlitrav (lgl, lgltlschedanylit);
11991     lgltlunmarkall (lgl);
11992     lglrelstk (lgl, &lgl->tlk->stk);
11993     if (!lglmtstk (&lgl->tlk->seen)) break;
11994     for (idx = 2; idx < lgl->nvars; idx++)
11995       lglavar (lgl, idx)->donotreelook = 0;
11996   }
11997   lglfitstk (lgl, &lgl->tlk->seen);
11998   count = 0;
11999   for (p = lgl->tlk->seen.start; p < lgl->tlk->seen.top; p++)
12000     if (*p) count++;
12001   lglprt (lgl, 1,
12002     "[treelook-%d] scheduled %d literals %.0f%%",
12003     lgl->stats->prb.treelook.count, count, lglpcnt (count, 2*lglrem (lgl)));
12004   if (!count)
12005     for (idx = 2; idx < lgl->nvars; idx++)
12006       lglavar (lgl, idx)->donotreelook = 0;
12007 }
12008 
lgltlassign(LGL * lgl,Stk * assignment,int lit)12009 static void lgltlassign (LGL * lgl, Stk * assignment, int lit) {
12010   TVar * tv;
12011   LOG (2, "tree-look assign %d", lit);
12012   tv = lgltvar (lgl, lit);
12013   assert (!tv->val);
12014   tv->val = lglsgn (lit) * (1 + lglcntstk (assignment));
12015   lglpushstk (lgl, assignment, lit);
12016   assert (tv->val);
12017   assert (lglsgn (tv->val) == lglsgn (lit));
12018 }
12019 
lgltlunassign(LGL * lgl,int lit)12020 static void lgltlunassign (LGL * lgl, int lit) {
12021   TVar * tv;
12022   LOG (2, "tree-look unassign %d", lit);
12023   tv = lgltvar (lgl, lit);
12024   assert (tv->val);
12025   assert (lglsgn (tv->val) == lglsgn (lit));
12026   tv->val = 0;
12027 }
12028 
lgltlval(LGL * lgl,int lit)12029 static int lgltlval (LGL * lgl, int lit) {
12030   TVar * tv = lgltvar (lgl, lit);
12031   int res;
12032   if (!tv->val) return 0;
12033   res = lglsgn (tv->val);
12034   if (lit < 0) res = -res;
12035   return res;
12036 }
12037 
lglincreducedptr(LGL * lgl,Flt * reducedptr,int size)12038 static void lglincreducedptr (LGL * lgl, Flt * reducedptr, int size) {
12039   Flt reduced = *reducedptr, inc = lglflt (-size, 1);
12040   reduced = lgladdflt (reduced, inc);
12041   LOG (2, "reduced score incremented to %s from %s by %s (size %d)",
12042        lglflt2str (lgl, reduced),
12043        lglflt2str (lgl, *reducedptr),
12044        lglflt2str (lgl, inc),
12045        size);
12046   *reducedptr = reduced;
12047 }
12048 
lgltlbcp(LGL * lgl,Stk * assignment,Flt * reducedptr,int dom)12049 static int lgltlbcp (LGL * lgl,
12050                      Stk * assignment, Flt * reducedptr, int dom) {
12051   int next = lglcntstk (assignment), next2 = next, lit, size, implied;
12052   int blit, tag, other, other2, val, lidx, red, found, trivial;
12053   int numnonfalse, numfalse, firstfalse, litval, skip;
12054   const int * p, * w, * eos, * c, * q;
12055   HTS * hts;
12056   if (lglval (lgl, dom)) return 1;
12057   assert (!lgltlval (lgl, dom));
12058   lgltlassign (lgl, assignment, dom);
12059   lgl->stats->prb.treelook.probed++;
12060   LOG (2, "starting tree-look bcp on %d", dom);
12061   for (;;) {
12062     if (next2 < lglcntstk (assignment)) {
12063       assert (lgl->simp);
12064       INCSTEPS (props.simp);
12065       if (lgl->lkhd) INCSTEPS (props.lkhd);
12066       lit = lglpeek (assignment, next2++);
12067       assert (lgltlval (lgl, lit) > 0);
12068       LOG (2, "tree-look binary clause bcp on %d", lit);
12069       hts = lglhts (lgl, -lit);
12070       w = lglhts2wchs (lgl, hts);
12071       eos = w + hts->count;
12072       for (p = w; p < eos; p++) {
12073 	assert (lgl->simp);
12074 	lgl->stats->visits.simp++;
12075 	if (lgl->lkhd) lgl->stats->visits.lkhd++;
12076 	INCSTEPS (prb.treelook.steps);
12077 	blit = *p;
12078 	tag = blit & MASKCS;
12079 	if (tag == OCCS) continue;
12080 	if (tag == TRNCS || tag == LRGCS) { p++; continue; }
12081 	assert (tag == BINCS);
12082 	other = blit >> RMSHFT;
12083 	val = lglval (lgl, other);
12084 	if (val < 0) return 0;
12085 	if (val > 0) continue;
12086 	val = lgltlval (lgl, other);
12087 	if (val < 0) return 0;
12088 	if (reducedptr) lglincreducedptr (lgl, reducedptr, 2);
12089 	if (val > 0) continue;
12090 	lgltlassign (lgl, assignment, other);
12091       }
12092     } else if (next < lglcntstk (assignment)) {
12093       lit = lglpeek (assignment, next++);
12094       litval = lgltlval (lgl, lit);
12095       assert (litval > 0);
12096       LOG (2, "tree-look non-binary clause bcp on %d", lit);
12097       hts = lglhts (lgl, -lit);
12098       w = lglhts2wchs (lgl, hts);
12099       eos = w + hts->count;
12100       for (p = w; p < eos; p++) {
12101 	blit = *p;
12102 	tag = blit & MASKCS;
12103 	if (tag == LRGCS || tag == TRNCS) p++;
12104 	if (tag == BINCS || tag == LRGCS) continue;
12105 	INCSTEPS (prb.treelook.steps);
12106 	assert (lglmtstk (&lgl->clause));
12107 	skip = trivial = 0;
12108 	if (tag == TRNCS) {
12109 	  other = blit >> RMSHFT;
12110 	  other2 = *p;
12111 	  if (lglval (lgl, other) > 0 ||
12112 	      lglval (lgl, other2) > 0) skip = 1;
12113 	  else {
12114 	    if (lgltlval (lgl, other) > 0 ||
12115 	        lgltlval (lgl, other2) > 0) trivial = 1;
12116 	    lglpushstk (lgl, &lgl->clause, -lit),
12117 	    lglpushstk (lgl, &lgl->clause, other),
12118 	    lglpushstk (lgl, &lgl->clause, other2);
12119 	  }
12120 	} else {
12121 	  assert (tag == OCCS);
12122 	  red = blit & REDCS;
12123 	  lidx = blit >> RMSHFT;
12124 	  found = trivial = 0;
12125 	  c = lglidx2lits (lgl, red, lidx);
12126 	  INCSTEPS (prb.treelook.steps);
12127 	  for (q = c; !skip && (other = *q); q++) {
12128 	    if (other >= NOTALIT) skip = 1;
12129 	    else if (lglval (lgl, other) > 0) skip = 1;
12130 	    else {
12131 	      if (other == -lit) assert (!found), found++;
12132 	      if (lgltlval (lgl, other) > 0) trivial = 1;
12133 	      lglpushstk (lgl, &lgl->clause, other);
12134 	    }
12135 	  }
12136 	  assert (skip || found);
12137 	}
12138 	numnonfalse = numfalse = size = implied = 0;
12139 	firstfalse = 1;
12140 	if (!skip) {
12141 	  INCSTEPS (prb.treelook.steps);
12142 	  for (q = lgl->clause.start; q < lgl->clause.top; q++) {
12143 	    other = *q;
12144 	    if (lglval (lgl, other) < 0) continue;
12145 	    size++;
12146 	    if ((val = lgltlval (lgl, other)) < 0) {
12147 	      if (reducedptr && -val < litval) firstfalse = 0;
12148 	      numfalse++;
12149 	      continue;
12150 	    }
12151 	    numnonfalse++;
12152 	    if (implied == NOTALIT) continue;
12153 	    else if (implied) implied = NOTALIT;
12154 	    else implied = other;
12155 	  }
12156 	}
12157 	lglclnstk (&lgl->clause);
12158 	if (skip) continue;
12159 	if (reducedptr && firstfalse)
12160 	  lglincreducedptr (lgl, reducedptr, size);
12161 	if (trivial) continue;
12162 	if (!numnonfalse) { assert (!implied); return 0; }
12163 	assert (implied);
12164 	if (implied == NOTALIT) continue;
12165 	assert (numnonfalse == 1);
12166 	if (!numfalse) continue; // TODO remove?
12167 	INCSTEPS (prb.treelook.steps);
12168 	if (tag == TRNCS) lgl->stats->hbr.trn++; else lgl->stats->hbr.lrg++;
12169 	LOG (2, "tree-look hyper binary resolvent %d %d", -dom, implied);
12170         lgldrupligaddclsarg (lgl, REDCS, -dom, implied, 0);
12171 	(void) lglwchbin (lgl, -dom, implied, REDCS);
12172 	(void) lglwchbin (lgl, implied, -dom, REDCS);
12173 	lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
12174 	lgl->stats->hbr.cnt++;
12175 	lgl->stats->prgss++;
12176 	lgltlassign (lgl, assignment, implied);
12177 	assert (next > 0),  next--; // force to redo this trn/lrg literal
12178 	break;	// and continue outer 'next2' prop on 'implied'
12179       }
12180     } else break;
12181   }
12182   if (reducedptr) assert (lgl->tlk->lkhd), lgl->tlk->lkhd[dom] = *reducedptr;
12183   return 1;
12184 }
12185 
lgltreelooklit(LGL * lgl,Stk * a,Ftk * r,int lit)12186 static void lgltreelooklit (LGL * lgl, Stk * a, Ftk * r, int lit) {
12187   Flt reduced;
12188   LOG (2, "treelook dequeue %d", lit);
12189   if (lit) {
12190     if (lgl->opts->treelook.val >= 2 &&
12191 	lglmtstk (a) &&
12192 	lglisfree (lgl, lit)) lglbasicprobelit (lgl, -lit);
12193     if (r) {
12194       reduced = lglmtftk (r) ? FLTMIN : lgltopftk (r);
12195       lglpushftk (lgl, r, reduced);
12196     }
12197     lglpushstk (lgl, a, 0);
12198     if (lgl->mt || !lglisfree (lgl, lit)) return;
12199     if (lgltlval (lgl, -lit) > 0 ||
12200 	(!lgltlval (lgl, lit) &&
12201 	 !lgltlbcp (lgl, a, r ? &reduced : 0, lit))) {
12202       int tmp;
12203       LOG (1, "tree-look failed literal %d", lit);
12204       if (!(tmp = lglval (lgl, lit))) {
12205 	lgl->stats->prb.treelook.failed++;
12206 	lglunit (lgl, -lit);
12207 	if (!lglbcp (lgl)) {
12208 	  LOG (1, "inconsistent tree-look failed literal");
12209 	  if (!lgl->mt) lglmt (lgl);
12210 	}
12211       } else if (tmp > 0) {
12212 	lgl->stats->prb.treelook.failed++;
12213 	LOG (1, "tree-look failed literal literal %d inconsistent", lit);
12214 	if (!lgl->mt) lglmt (lgl);
12215       } else LOG (1, "tree-look failed literal %d already found", lit);
12216     }
12217     if (r) {
12218       assert (r->start < r->top);
12219       assert (r->top[-1] <= reduced);
12220       r->top[-1] = reduced;
12221     }
12222   } else {
12223     if (r) lglpopftk (r);
12224     while ((lit = lglpopstk (a)))
12225       lgltlunassign (lgl, lit);
12226   }
12227 }
12228 
lglsetprbtreelooklim(LGL * lgl,int * lkhdresptr)12229 static int64_t lglsetprbtreelooklim (LGL * lgl, int * lkhdresptr) {
12230   int szpen, lastpen, pen, boost;
12231   int64_t limit, irrlim;
12232   if (lgl->opts->treelookrtc.val || lgl->opts->prbrtc.val) {
12233     limit = lgl->limits->prb.steps = LLMAX;
12234     lglprt (lgl, 1,
12235       "[treelook-%d] really no limit (run to completion)",
12236       lgl->stats->prb.treelook.count);
12237   } else if (lkhdresptr && lgl->opts->treelookfull.val) {
12238     limit = lgl->limits->prb.steps = LLMAX;
12239     lglprt (lgl, 1,
12240       "[treelook-%d] unlimited look-ahead requested",
12241       lgl->stats->prb.treelook.count);
12242   } else {
12243     limit = (lgl->opts->treelookreleff.val*lglvisearch (lgl))/2000;
12244     if (limit < lgl->opts->treelookmineff.val)
12245       limit = lgl->opts->treelookmineff.val;
12246     if (lgl->opts->treelookmaxeff.val >= 0 &&
12247         limit > lgl->opts->treelookmaxeff.val)
12248       limit = lgl->opts->treelookmaxeff.val;
12249     assert (lgl->tlk);
12250     szpen = lglszpen (lgl);
12251     lastpen = lgl->tlk->lkhd ?
12252       lgl->limits->lkhdpen : lgl->limits->prb.treelook.pen;
12253     limit >>= (pen = szpen + lastpen);
12254     irrlim = (lgl->stats->irr.clauses.cur/4) >> szpen;
12255     if (lgl->opts->boost.val && lgl->tlk->lkhd)
12256       boost = lgl->opts->treelookboost.val;
12257     else boost = 1;
12258     limit *= boost;
12259     if (lgl->opts->irrlim.val && limit < irrlim) {
12260       limit = irrlim;
12261       lglprt (lgl, 1,
12262   "[treelook-%d] limit %lld based on %d irredundant clauses penalty %d",
12263 	lgl->stats->prb.treelook.count,
12264 	(LGLL) limit, lgl->stats->irr.clauses.cur, szpen);
12265     } else
12266       lglprt (lgl, 1,
12267 	"[treelook-%d] limit %lld penalty %d = %d + %d boost %d",
12268 	lgl->stats->prb.treelook.count, (LGLL) limit,
12269 	pen, lastpen, szpen, boost);
12270     if (lkhdresptr)
12271       lglprt (lgl, 1, "[treelook-%d] limited look-ahead requested",
12272 	      lgl->stats->prb.treelook.count);
12273     lgl->limits->prb.steps = lgl->stats->prb.treelook.steps + limit;
12274   }
12275 
12276   return limit;
12277 }
12278 
lglclntlvals(LGL * lgl)12279 static void lglclntlvals (LGL * lgl) {
12280   int idx;
12281   for (idx = 2; idx < lgl->nvars; idx++) lgl->tlk->tvars[idx].val = 0;
12282 }
12283 
12284 #ifndef NDEBUG
lglieliminated(LGL * lgl,int ilit)12285 static int lglieliminated (LGL * lgl, int ilit) {
12286   return lglelit2ext (lgl, lglexport (lgl, ilit))->eliminated;
12287 }
12288 #endif
12289 
lgliblocking(LGL * lgl,int ilit)12290 static int lgliblocking (LGL * lgl, int ilit) {
12291   return lglelit2ext (lgl, lglexport (lgl, ilit))->blocking;
12292 }
12293 
lgltlsetlkhd(LGL * lgl,int * lkhdresptr,int remlits)12294 static void lgltlsetlkhd (LGL * lgl, int * lkhdresptr, int remlits) {
12295   LKHD lkhdrescore, lkhdscore, lkhdpos, lkhdneg;
12296   Flt jwhrescore, jwhscore, jwhpos, jwhneg;
12297   int idx, lkhdres, phase, elit;
12298   Ext * ext;
12299   assert (lkhdresptr);
12300   lkhdres = 0; lkhdrescore = FLTMIN; jwhrescore = FLTMIN;
12301   assert (!lgl->nvars || lgl->tlk->lkhd);
12302   lgljwh (lgl);
12303   for (idx = 2; idx < lgl->nvars; idx++) {
12304     if (!lglisfree (lgl, idx)) continue;
12305     assert (!lglieliminated (lgl, idx));
12306     if (lkhdresptr && lgliblocking (lgl, idx)) continue;
12307     if (!remlits) {
12308       lkhdpos = lgl->tlk->lkhd[idx];
12309       lkhdneg = lgl->tlk->lkhd[-idx];
12310       lkhdscore = lglmulflt (lkhdneg, lkhdpos);
12311       if (lkhdscore > FLTMIN)
12312 	lkhdscore = lgladdflt (lkhdscore, lgladdflt (lkhdneg, lkhdpos));
12313     } else lkhdscore = lkhdpos = lkhdneg = FLTMIN;
12314     jwhpos = lgl->jwh[lglulit (idx)];
12315     jwhneg = lgl->jwh[lglulit (-idx)];
12316     jwhscore = lglmulflt (jwhpos, jwhneg);
12317     jwhscore = lgladdflt (jwhscore, lgladdflt (jwhpos, jwhneg));
12318     LOG (1,
12319       "final tree based look-ahead score [%s,%s] "
12320       "(pos [%s,%s], neg [%s,%s]) of %d",
12321        lglflt2str (lgl, lkhdscore), lglflt2str (lgl,jwhscore),
12322        lglflt2str (lgl, lkhdpos), lglflt2str (lgl,jwhpos),
12323        lglflt2str (lgl, lkhdneg), lglflt2str (lgl,jwhneg),
12324        idx);
12325 
12326     // phase with less weighted reductions
12327          if (lkhdpos > lkhdneg) phase = -1;
12328     else if (lkhdpos < lkhdneg) phase = 1;
12329     // then with more weighted occs
12330     else if (jwhpos > jwhneg) phase = 1;
12331     else if (jwhpos < jwhneg) phase = -1;
12332     // otherwise negative phase
12333     else phase = -1;
12334 
12335     if (lkhdres) {
12336       if (lkhdscore < lkhdrescore) continue;
12337       if (lkhdscore == lkhdrescore && jwhscore <= jwhrescore) continue;
12338     }
12339     lkhdrescore = lkhdscore;
12340     jwhrescore = jwhscore;
12341     lkhdres = phase * idx;
12342   }
12343   if (lkhdres) {
12344     elit = lglexport (lgl, lkhdres);
12345     ext = lglelit2ext (lgl, elit);
12346     assert (!ext->eliminated);
12347     assert (!ext->blocking);
12348     lglprt (lgl, 1, "[treelook-%d] best look-ahead %d score [%s,%s]",
12349       lgl->stats->prb.treelook.count, lkhdres,
12350       lglflt2str (lgl, lkhdrescore), lglflt2str (lgl, jwhrescore));
12351     if (ext->melted) {
12352       ext->melted = 0;
12353       LOG (2, "tree-look-ahead winner external %d not melted anymore", elit);
12354     } else
12355       LOG (2,
12356 	"tree-look-ahead winner external %d was not melted anyhow", elit);
12357   } else LOG (1, "no proper best tree-look-ahead literal found");
12358   if (lkhdresptr) *lkhdresptr = lkhdres;
12359 }
12360 
lglgenericreport(LGL * lgl,const char * name,int count,int probed,int nprobes,double start)12361 static void lglgenericreport (LGL * lgl, const char * name, int count,
12362                               int probed, int nprobes, double start) {
12363   int div, mod;
12364   assert (nprobes >= 0);
12365   if (!nprobes || lgl->opts->verbose.val < 2) return;
12366   if (lgl->opts->verbose.val == 2) div = 10;
12367   else if (lgl->opts->verbose.val == 3) div = 100;
12368   else div = 0;
12369   mod = div ? (nprobes + div - 1) / div : 1;
12370   assert (mod > 0);
12371   if (probed % mod) return;
12372   lglprt (lgl, 1,
12373     "[%s-%d] probed %d/%d (%.0f%%) %.1f sec %d vars %.0f MB",
12374     name, count, probed, nprobes, lglpcnt (probed, nprobes),
12375     lglgetime (lgl) - start, lglrem (lgl), lglmb (lgl));
12376 }
12377 
lgltreelookreport(LGL * lgl,int probed,int nprobes,double start)12378 static void lgltreelookreport (LGL * lgl,
12379                               int probed, int nprobes, double start) {
12380   lglgenericreport (lgl,
12381      "treelook", lgl->stats->prb.treelook.count, probed, nprobes, start);
12382 }
12383 
lgltreelookaux(LGL * lgl,int * lkhdresptr)12384 static int lgltreelookaux (LGL * lgl, int * lkhdresptr) {
12385   int oldhbrs, oldrem, remvarsall, remvarslkhd, remlits, notfullyscheduled;
12386   int deltavars, newhbrs, success, idx, next, lit, nseen;
12387   int64_t oldsteps, steps, limit;
12388   Stk assignment;
12389   double start;
12390   Ftk reduced;
12391   TVar * tv;
12392   AVar * av;
12393 
12394   if (lgl->mt) return 0;
12395   if (lkhdresptr) *lkhdresptr = 0;
12396   if (!lgl->nvars) return 1;
12397 
12398   lglstart (lgl, &lgl->times->prb.treelook);
12399   lgl->stats->prb.treelook.count++;
12400 
12401   NEW (lgl->tlk, 1);
12402   NEW (lgl->tlk->tvars, lgl->nvars);
12403 
12404   assert (!lgl->simp && !lgl->probing && !lgl->treelooking);
12405   lgl->simp = lgl->probing = lgl->treelooking = 1;
12406 
12407   if (lgl->level > 0) lglbacktrack (lgl, 0);
12408   oldhbrs = lgl->stats->hbr.cnt;
12409   oldrem = lglrem (lgl);
12410 
12411   assert (!lgl->tlk->lkhd);
12412   if (lkhdresptr) {
12413     NEW (lgl->tlk->lkhd, 2*lgl->nvars);
12414     lgl->tlk->lkhd += lgl->nvars;
12415     assert (lgl->tlk->lkhd);
12416   }
12417 
12418   limit = lglsetprbtreelooklim (lgl, lkhdresptr);
12419   oldsteps = lgl->stats->prb.treelook.steps;
12420 
12421   lgltlsched (lgl);
12422 
12423   steps = lgl->stats->prb.treelook.steps - oldsteps;
12424   lglprt (lgl, 1, "[treelook-%d] scheduling used %lld steps",
12425     lgl->stats->prb.treelook.count, (LGLL) steps);
12426 
12427   if (limit != LLMAX) {
12428     notfullyscheduled =
12429       (lgl->stats->prb.treelook.steps >= lgl->limits->prb.steps);
12430     lgl->limits->prb.steps = lgl->stats->prb.treelook.steps + limit;
12431     if (notfullyscheduled)
12432       lglprt (lgl, 1, "[treelook-%d] not fully scheduled",
12433  	lgl->stats->prb.treelook.count);
12434     else
12435       lglprt (lgl, 1, "[treelook-%d] scheduled completely",
12436  	lgl->stats->prb.treelook.count);
12437   } else notfullyscheduled = 0;
12438 
12439   CLR (assignment); CLR (reduced);
12440   remlits = remvarsall = remvarslkhd = 0;
12441 
12442   nseen = lglcntstk (&lgl->tlk->seen);
12443   if (!lgl->mt && nseen) {
12444 
12445     (void) lglsetprbtreelooklim (lgl, lkhdresptr);
12446     oldsteps = lgl->stats->prb.treelook.steps;
12447 
12448     lgldense (lgl, 0);
12449     next = 0;
12450     start = lglgetime (lgl);
12451     lgltreelookreport (lgl, next, nseen, start);
12452     while (!lgl->mt &&
12453 	   !lglterminate (lgl) &&
12454 	   lglsyncunits (lgl) &&
12455 	   next < nseen &&
12456 	   lgl->stats->prb.treelook.steps < lgl->limits->prb.steps) {
12457       lit = lglpeek (&lgl->tlk->seen, next++);
12458       lgltreelooklit (lgl, &assignment, lkhdresptr ? &reduced : 0, lit);
12459       lgltreelookreport (lgl, next, nseen, start);
12460     }
12461     lgltreelookreport (lgl, next, nseen, start);
12462     lglclntlvals (lgl);
12463     assert (lgl->stats->prb.treelook.steps >= oldsteps);
12464     steps = lgl->stats->prb.treelook.steps - oldsteps;
12465     lglprt (lgl, 1, "[treelook-%d] used %lld steps",
12466       lgl->stats->prb.treelook.count, (LGLL) steps);
12467     while (next < lglcntstk (&lgl->tlk->seen)) {
12468       lit = lglpeek (&lgl->tlk->seen, next++);
12469       if (!lit) continue;
12470       if (!lglisfree (lgl, lit)) continue;
12471       remlits++;
12472       tv = lgltvar (lgl, lit);
12473       tv->val = 1;
12474     }
12475     for (idx = 2; idx < lgl->nvars; idx++)
12476       if (lglisfree (lgl, idx)) {
12477 	tv = lgltvar (lgl, idx);
12478 	av = lglavar (lgl, idx);
12479 	if (tv->val) {
12480 	   tv->val = 0;
12481 	   if (!av->donotreelook) remvarsall++;
12482 	   remvarslkhd++;
12483 	} else if (!av->donotreelook) av->donotreelook = 1;
12484       }
12485     assert (remvarslkhd >= remvarsall);
12486 
12487     if (remvarsall || notfullyscheduled) {
12488       lglprt (lgl, 1, "[treelook-%d] %d literals remain %.0f%%%s",
12489 	lgl->stats->prb.treelook.count,
12490 	remlits, lglpcnt (remlits, 2*lglrem (lgl)),
12491         lkhdresptr ? " in look-ahead" : "");
12492       if (lkhdresptr)
12493 	lglprt (lgl, 1, "[treelook-%d] %d look-ahead variables remain %.0f%%",
12494 	  lgl->stats->prb.treelook.count,
12495 	  remvarslkhd, lglpcnt (remvarslkhd, lglrem (lgl)));
12496       lglprt (lgl, 1,
12497 	"[treelook-%d] %d variables remain to probed next time %.0f%%",
12498 	lgl->stats->prb.treelook.count,
12499 	remvarsall, lglpcnt (remvarsall, lglrem (lgl)));
12500     } else {
12501       lglprt (lgl, 1,
12502         "[treelook-%d] fully completed tree based probing%s",
12503 	lgl->stats->prb.treelook.count, lkhdresptr ? " in look-ahead" : "");
12504       for (idx = 2; idx < lgl->nvars; idx++)
12505 	lglavar (lgl, idx)->donotreelook = 0;
12506     }
12507     lglsparse (lgl);
12508   }
12509 
12510   DEL (lgl->tlk->tvars, lgl->nvars);
12511   lglgc (lgl);
12512   lglrelftk (lgl, &reduced);
12513   lglrelstk (lgl, &assignment);
12514   lglrelstk (lgl, &lgl->tlk->seen);
12515   if (!lgl->mt && lkhdresptr)
12516     lgltlsetlkhd (lgl, lkhdresptr, remlits || notfullyscheduled);
12517   if (lgl->tlk->lkhd) {
12518     lgl->tlk->lkhd -= lgl->nvars;
12519     DEL (lgl->tlk->lkhd, 2*lgl->nvars);
12520   }
12521   DEL (lgl->tlk, 1);
12522   newhbrs = lgl->stats->hbr.cnt - oldhbrs;
12523   if (newhbrs && !lgl->mt && !lkhdresptr) lgldecomp (lgl);
12524 
12525   assert (lgl->simp && lgl->probing && lgl->treelooking);
12526   lgl->simp = lgl->probing = lgl->treelooking = 0;
12527 
12528   deltavars = oldrem - lglrem (lgl);
12529   success = deltavars || newhbrs;
12530   if (!lkhdresptr) LGLUPDPEN (prb.treelook, deltavars);
12531   else if (remlits && lgl->limits->lkhdpen < lgl->opts->penmax.val)
12532     lgl->limits->lkhdpen++;
12533   else if (!remlits && lgl->limits->lkhdpen)
12534     lgl->limits->lkhdpen--;
12535   lglprt (lgl, 1 + !success,
12536 	  "[treelook-%d] removed %d variables, found %d hbrs",
12537 	  lgl->stats->prb.treelook.count, deltavars, newhbrs);
12538   lglrep (lgl, 2, 'p');
12539   lglstop (lgl);
12540   lglbasicatestats (lgl);
12541   return !lgl->mt;
12542 }
12543 
lgltreelook(LGL * lgl)12544 static int lgltreelook (LGL * lgl) {
12545   if (lgldelaying (lgl, "treelook",
12546         &lgl->limits->prb.treelook.del.rem)) return 1;
12547   return lgltreelookaux (lgl, 0);
12548 }
12549 
lgljwhlook(LGL * lgl)12550 static int lgljwhlook (LGL * lgl) {
12551   Flt best, pos, neg, score;
12552   int res, idx, elit;
12553   Ext * ext;
12554   lgljwh (lgl);
12555   best = FLTMIN;
12556   res = 0;
12557   for (idx = 2; idx < lgl->nvars; idx++) {
12558     if (!lglisfree (lgl, idx)) continue;
12559     assert (!lglieliminated (lgl, idx));
12560     if (lgliblocking (lgl, idx)) continue;
12561     pos = lgl->jwh[lglulit (idx)];
12562     neg = lgl->jwh[lglulit (-idx)];
12563     score = lglmulflt (pos, neg);
12564     score = lgladdflt (score, lgladdflt (pos, neg));
12565     if (res && score <= best) continue;
12566     LOG (1, "jwh look-ahead score %s (pos %s, neg %s) of %d",
12567       lglflt2str (lgl, score), lglflt2str (lgl, pos), lglflt2str (lgl, neg),
12568       idx);
12569     res = (pos > neg) ? idx : -idx;
12570     best = score;
12571   }
12572   if (res) {
12573     elit = lglexport (lgl, res);
12574     ext = lglelit2ext (lgl, elit);
12575     lglprt (lgl, 1, "[jwhlook] best look-ahead %d score %s",
12576             res, lglflt2str (lgl, best));
12577     if (ext->melted) {
12578       ext->melted = 0;
12579       LOG (2, "jwh-look-ahead winner external %d not melted anymore", elit);
12580     } else
12581       LOG (2, "jwh-look-ahead winner external %d was not melted anyhow", elit);
12582   } else LOG (1, "no proper best jwh-look-ahead literal found");
12583   return res;
12584 }
12585 
lglislook(LGL * lgl)12586 static int lglislook (LGL * lgl) {
12587   int64_t best, pos, neg, score;
12588   int res, idx, elit, * scores;
12589   Ext * ext;
12590   scores = lglis (lgl);
12591   best = res = 0;
12592   for (idx = 2; idx < lgl->nvars; idx++) {
12593     if (!lglisfree (lgl, idx)) continue;
12594     assert (!lglieliminated (lgl, idx));
12595     if (lgliblocking (lgl, idx)) continue;
12596     pos = scores[idx], neg = scores[-idx];
12597     score = pos * neg + pos + neg;
12598     assert (0 <= score && pos <= score && neg <= score);
12599     if (res && score <= best) continue;
12600     LOG (1,
12601       "LIS look-ahead score %lld (pos %lld, neg %lld) of %d",
12602       (LGLL) score, (LGLL) pos, (LGLL) neg, idx);
12603     res = (pos > neg) ? idx : -idx;
12604     best = score;
12605   }
12606   scores -= lgl->nvars;
12607   DEL (scores, 2*lgl->nvars);
12608   if (res) {
12609     elit = lglexport (lgl, res);
12610     ext = lglelit2ext (lgl, elit);
12611     assert (!ext->eliminated && !ext->blocking);
12612     lglprt (lgl, 1,
12613       "[lislook] best LIS look-ahead %d score %lld",
12614       res, (LGLL) best);
12615     if (ext->melted) {
12616       ext->melted = 0;
12617       LOG (2, "look-ahead winner external %d not melted anymore", elit);
12618     } else
12619       LOG (2, "look-ahead winner external %d was not melted anyhow", elit);
12620   } else LOG (1, "no proper best LIS look-ahead literal found");
12621   return res;
12622 }
12623 
lglsatmul64(int64_t a,int64_t b)12624 static int64_t lglsatmul64 (int64_t a, int64_t b) {
12625   assert (a >= 0), assert (b >= 0);
12626   return (b && (LLMAX / b < a)) ? LLMAX : a * b;
12627 }
12628 
lglsatadd64(int64_t a,int64_t b)12629 static int64_t lglsatadd64 (int64_t a, int64_t b) {
12630   assert (a >= 0), assert (b >= 0);
12631   return (LLMAX - b < a) ? LLMAX : a + b;
12632 }
12633 
lglsumlenscores(LGL * lgl)12634 static int64_t * lglsumlenscores (LGL * lgl) {
12635   int idx, sign, lit, tag, blit, other, other2, red;
12636   const int *p, * w, * eow, * c;
12637   int64_t * res, len;
12638   Val val, tmp, tmp2;
12639   HTS * hts;
12640   Stk * s;
12641   NEW (res, 2*lgl->nvars);
12642   res += lgl->nvars;
12643   for (idx = 2; idx < lgl->nvars; idx++)
12644     for (sign = -1; sign <= 1; sign += 2) {
12645       lit = sign * idx;
12646       val = lglval (lgl, lit);
12647       if (val > 0) continue;
12648       hts = lglhts (lgl, lit);
12649       if (!hts->offset) continue;
12650       w = lglhts2wchs (lgl, hts);
12651       eow = w + hts->count;
12652       for (p = w; p < eow; p++) {
12653 	blit = *p;
12654 	tag = blit & MASKCS;
12655 	if (tag == TRNCS || tag == LRGCS) p++;
12656 	if (tag == LRGCS) continue;
12657 	red = blit & REDCS;
12658 	if (red) continue;
12659 	other = blit >> RMSHFT;
12660 	if (abs (other) < abs (lit)) continue;
12661 	tmp = lglval (lgl, other);
12662 	if (tmp > 0) continue;
12663 	if (tag == BINCS) {
12664 	  assert (!tmp);
12665 	  res[lit] += 2;
12666 	  res[other] += 2;
12667 	} else {
12668 	  assert (tag == TRNCS);
12669 	  other2 = *p;
12670 	  if (abs (other2) < abs (lit)) continue;
12671 	  tmp2 = lglval (lgl, other2);
12672 	  if (tmp2 > 0) continue;
12673 	  assert ((val > 0) + (tmp > 0) + (tmp2 > 0) == 0);
12674 	  assert ((val < 0) + (tmp < 0) + (tmp2 < 0) <= 1);
12675 	  len = !val + !tmp + !tmp2;
12676 	  if (!val) res[lit] += len;
12677 	  if (!tmp) res[other] += len;
12678 	  if (!tmp2) res[other2] += len;
12679 	}
12680       }
12681     }
12682   s = &lgl->irr;
12683   for (c = s->start; c < s->top; c = p + 1) {
12684     p = c;
12685     if (*p >= NOTALIT) continue;
12686     val = -1;
12687     len = 0;
12688     while ((other = *p)) {
12689       tmp = lglval (lgl, other);
12690       if (tmp > val) val = tmp;
12691       if (!tmp) len++;
12692       p++;
12693     }
12694     if (val > 0) continue;
12695     for (p = c; (other = *p); p++)
12696       if (!lglval (lgl, other))
12697 	res[other] += len;
12698   }
12699   return res;
12700 }
12701 
lglsumlenlook(LGL * lgl)12702 static int lglsumlenlook (LGL * lgl) {
12703   int64_t best, pos, neg, score, * scores;
12704   int res, idx, elit;
12705   Ext * ext;
12706   scores = lglsumlenscores (lgl);
12707   best = res = 0;
12708   for (idx = 2; idx < lgl->nvars; idx++) {
12709     if (!lglisfree (lgl, idx)) continue;
12710     assert (!lglieliminated (lgl, idx));
12711     if (lgliblocking (lgl, idx)) continue;
12712     pos = scores[idx], neg = scores[-idx];
12713     score = lglsatadd64 (lglsatmul64 (pos, neg), lglsatadd64 (pos, neg));
12714     assert (0 <= score), assert (pos <= score), assert (neg <= score);
12715     if (res && score <= best) continue;
12716     LOG (1,
12717       "look-ahead score %lld (pos %lld, neg %lld) of %d",
12718       (LGLL) score, (LGLL) pos, (LGLL) neg, idx);
12719     res = (pos > neg) ? idx : -idx;
12720     best = score;
12721   }
12722   scores -= lgl->nvars;
12723   DEL (scores, 2*lgl->nvars);
12724   if (res) {
12725     elit = lglexport (lgl, res);
12726     ext = lglelit2ext (lgl, elit);
12727     assert (!ext->eliminated && !ext->blocking);
12728     lglprt (lgl, 1,
12729       "[sumlook] best look-ahead %d score %lld",
12730       res, (LGLL) best);
12731     if (ext->melted) {
12732       ext->melted = 0;
12733       LOG (2, "look-ahead winner external %d not melted anymore", elit);
12734     } else
12735       LOG (2, "look-ahead winner external %d was not melted anyhow", elit);
12736   } else LOG (1, "no proper best look-ahead literal found");
12737   return res;
12738 }
12739 
lglschedbasicprobe(LGL * lgl,Stk * probes,int round)12740 static int lglschedbasicprobe (LGL * lgl, Stk * probes, int round) {
12741   int idx, res, i, j, donotbasicprobes, keepscheduled;
12742   assert (lglmtstk (probes));
12743   for (idx = 2; idx < lgl->nvars; idx++) {
12744     if (!lglisfree (lgl, idx)) continue;
12745     if (lgl->opts->prbasic.val <= 1 &&
12746         (lglhasbins (lgl, idx) == lglhasbins (lgl, -idx))) continue;
12747     LOG (1, "new probe %d", idx);
12748     lglpushstk (lgl, probes, idx);
12749   }
12750   res = lglcntstk (probes);
12751   donotbasicprobes = keepscheduled = 0;
12752   for (i = 0; i < res; i++) {
12753     idx = lglpeek (probes, i);
12754     if (!idx) continue;
12755     assert (lglisfree (lgl, idx));
12756     if (lglavar (lgl, idx)->donotbasicprobe) donotbasicprobes++;
12757     else keepscheduled++;
12758   }
12759   if (!keepscheduled) {
12760     for (i = 0; i < res; i++) {
12761       idx = lglpeek (probes, i);
12762       if (!idx) continue;
12763       assert (lglisfree (lgl, idx));
12764       lglavar (lgl, idx)->donotbasicprobe = 0;
12765       keepscheduled++;
12766     }
12767     donotbasicprobes = 0;
12768   }
12769   for (i = 0; i < res; i++) {
12770     idx = lglpeek (probes, i);
12771     if (!idx) continue;
12772     assert (lglisfree (lgl, idx));
12773     if (lglavar (lgl, idx)->donotbasicprobe) donotbasicprobes++;
12774     else keepscheduled++;
12775   }
12776   j = 0;
12777   for (i = 0; i < res; i++) {
12778     idx = lglpeek (probes, i);
12779     if (!idx) continue;
12780     if (!lglavar (lgl, idx)->donotbasicprobe)
12781       lglpoke (probes, j++, idx);
12782   }
12783   lglrststk (probes, (res = j));
12784   if (!res)
12785     lglprt (lgl, 2, "[basicprobe-%d-%d] no potential probes found",
12786 	    lgl->stats->prb.basic.count, round);
12787   else if (!donotbasicprobes)
12788     lglprt (lgl, 2, "[basicprobe-%d-%d] scheduled all %d potential probes",
12789 	    lgl->stats->prb.basic.count, round, res);
12790   else
12791     lglprt (lgl, 2, "[basicprobe-%d-%d] scheduled %d probes %.0f%%",
12792 	    lgl->stats->prb.basic.count, round,
12793 	    res, lglpcnt (res, lglrem (lgl)));
12794   return res;
12795 }
12796 
lglsetprbasiclim(LGL * lgl)12797 static void lglsetprbasiclim (LGL * lgl) {
12798   int64_t limit, irrlim;
12799   int pen, szpen;
12800   if (lgl->opts->prbasicrtc.val || lgl->opts->prbrtc.val) {
12801     lgl->limits->prb.steps = LLMAX;
12802     lglprt (lgl, 1,
12803       "[basicprobe-%d] really no limit (run to completion)",
12804       lgl->stats->prb.basic.count);
12805   } else {
12806     limit = (lgl->opts->prbasicreleff.val*lglvisearch (lgl))/1000;
12807     if (limit < lgl->opts->prbasicmineff.val)
12808       limit = lgl->opts->prbasicmineff.val;
12809     if (lgl->opts->prbasicmaxeff.val >= 0 &&
12810 	limit > lgl->opts->prbasicmaxeff.val)
12811       limit = lgl->opts->prbasicmaxeff.val;
12812     limit >>= (pen = lgl->limits->prb.basic.pen + (szpen = lglszpen (lgl)));
12813     irrlim = (8*lgl->stats->irr.clauses.cur) >> szpen;
12814     if (lgl->opts->irrlim.val && limit < irrlim) {
12815       limit = irrlim;
12816       lglprt (lgl, 1,
12817     "[basicprobe-%d] limit %lld based on %d irredundant clauses penalty %d",
12818 	lgl->stats->prb.basic.count,
12819 	(LGLL) limit, lgl->stats->irr.clauses.cur, szpen);
12820     } else
12821       lglprt (lgl, 1, "[basicprobe-%d] limit %lld penalty %d = %d + %d",
12822 	lgl->stats->prb.basic.count, (LGLL) limit,
12823 	pen, lgl->limits->prb.basic.pen, szpen);
12824     lgl->limits->prb.steps = lgl->stats->prb.basic.steps + limit;
12825   }
12826 }
12827 
lglbasicprobereport(LGL * lgl,int probed,int nprobes,double start)12828 static void lglbasicprobereport (LGL * lgl,
12829                                  int probed, int nprobes, double start) {
12830   lglgenericreport (lgl,
12831     "basicprobe", lgl->stats->prb.basic.count, probed, nprobes, start);
12832 }
12833 
lglbasicprobe(LGL * lgl)12834 static int lglbasicprobe (LGL * lgl) {
12835 #ifndef NLGLOG
12836   int origprobed = lgl->stats->prb.basic.probed;
12837 #endif
12838   int origfailed = lgl->stats->prb.basic.failed;
12839   int origlifted = lgl->stats->prb.basic.lifted;
12840   int orighbr = lgl->stats->hbr.cnt;
12841   int root, failed, lifted, units, first, idx;
12842   int oldrem, deltarem, deltahbr, remprobes;
12843   int nprobes, success, round, probed;
12844   int oldhbr, oldfailed, oldlifted;
12845   Stk probes, lift, saved;
12846   unsigned pos, delta;
12847   double start;
12848   if (!lgl->nvars) return 1;
12849   if (!lgl->opts->probe.val) return 1;
12850   if (lgldelaying (lgl, "basicprobe",
12851         &lgl->limits->prb.basic.del.rem)) return 1;
12852   lglstart (lgl, &lgl->times->prb.basic);
12853   lgl->stats->prb.basic.count++;
12854   if (lgl->level > 0) lglbacktrack (lgl, 0);
12855   assert (!lgl->simp && !lgl->probing && !lgl->basicprobing);
12856   lgl->simp = lgl->probing = lgl->basicprobing = 1;
12857   CLR (lift); CLR (probes); CLR (saved);
12858   lglsetprbasiclim (lgl);
12859   oldfailed = origfailed;
12860   oldlifted = origlifted;
12861   oldhbr = lgl->stats->hbr.cnt;
12862   oldrem = lglrem (lgl);
12863   round = 0;
12864 RESTART:
12865   nprobes = lglschedbasicprobe (lgl, &probes, round);
12866   remprobes = 0;
12867   if (!nprobes) goto DONE;
12868   pos = lglrand (lgl) % nprobes;
12869   delta = lglrand (lgl) % nprobes;
12870   if (!delta) delta++;
12871   probed = 0;
12872   start = lglgetime (lgl);
12873   lglbasicprobereport (lgl, probed, nprobes, start);
12874   while (lglgcd (delta, nprobes) > 1)
12875     if (++delta == nprobes) delta = 1;
12876   LOG (1, "probing start %u delta %u mod %u", pos, delta, nprobes);
12877   first = 0;
12878   while (!lgl->mt) {
12879     if (lgl->stats->prb.basic.steps >= lgl->limits->prb.steps) break;
12880     if (lglterminate (lgl)) break;
12881     if (!lglsyncunits (lgl)) break;
12882     assert (pos < (unsigned) nprobes);
12883     root = probes.start[pos];
12884     probes.start[pos] = 0;
12885     if (!root || root == first) {
12886       lglprt (lgl, 1,
12887         "[basicprobe-%d-%d] %d sched %.0f%%, %d failed, %d lifted, %d hbrs",
12888 	lgl->stats->prb.basic.count, round,
12889 	nprobes, lglpcnt (nprobes, lglrem (lgl)),
12890         lgl->stats->prb.basic.failed - oldfailed,
12891         lgl->stats->prb.basic.lifted - oldlifted,
12892         lgl->stats->hbr.cnt - oldhbr);
12893       for (idx = 2; idx < lgl->nvars; idx++)
12894 	lglavar (lgl, idx)->donotbasicprobe = 0;
12895       break;
12896     }
12897     lglavar (lgl, root)->donotbasicprobe = 1;
12898     if (!first) first = root;
12899     pos += delta;
12900     if (pos >= nprobes) pos -= nprobes;
12901     if (!lglisfree (lgl, root)) continue;
12902     lglbasicprobereport (lgl, ++probed, nprobes, start);
12903     lglbasicprobelit (lgl, root);
12904   }
12905   lglbasicprobereport (lgl, probed, nprobes, start);
12906   if (!lgl->mt) {
12907     if (lgl->stats->prb.basic.steps >= lgl->limits->prb.steps) {
12908       while (!lglmtstk (&probes))
12909 	if((idx = lglpopstk (&probes)) && lglisfree (lgl, idx)) remprobes++;
12910       lglprt (lgl, 1,
12911         "[basicprobe-%d-%d] %d probes remain %.0f%% after last round",
12912 	lgl->stats->prb.basic.count, round,
12913 	remprobes, lglpcnt (remprobes, lglrem (lgl)));
12914     } else if (round >= lgl->opts->prbasicroundlim.val) {
12915       lglprt (lgl, 1,
12916 	      "[basicprobe-%d-%d] round limit %d hit",
12917 	      lgl->stats->prb.basic.count, round,
12918 	      lgl->opts->prbasicroundlim.val);
12919     } else if (lgl->stats->prb.basic.failed > oldfailed ||
12920                lgl->stats->prb.basic.lifted > oldlifted ||
12921 	       lgl->stats->hbr.cnt > oldhbr) {
12922       oldfailed = lgl->stats->prb.basic.failed;
12923       oldlifted = lgl->stats->prb.basic.lifted;
12924       lglclnstk (&probes);
12925       if (oldhbr < lgl->stats->hbr.cnt && lgl->opts->decompose.val)
12926 	if (!lgldecomp (lgl)) goto DONE;
12927       oldhbr = lgl->stats->hbr.cnt;
12928       round++;
12929       goto RESTART;
12930     } else {
12931       assert (!remprobes);
12932       lglprt (lgl, 1,
12933 	      "[basicprobe-%d-%d] fully completed probing",
12934 	      lgl->stats->prb.basic.count, round);
12935       for (idx = 2; idx < lgl->nvars; idx++)
12936 	lglavar (lgl, idx)->donotbasicprobe = 0;
12937     }
12938   }
12939 DONE:
12940   lglrelstk (lgl, &lift);
12941   lglrelstk (lgl, &probes);
12942   lglrelstk (lgl, &saved);
12943 
12944   assert (lgl->stats->hbr.cnt >= orighbr);
12945   assert (lglrem (lgl) <= oldrem);
12946   deltarem = oldrem - lglrem (lgl);
12947   deltahbr = lgl->stats->hbr.cnt - orighbr;
12948   success = deltarem || deltahbr;
12949   LGLUPDPEN (prb.basic, deltarem);
12950   assert (lgl->stats->prb.basic.failed >= origfailed);
12951   assert (lgl->stats->prb.basic.lifted >= origlifted);
12952   failed = lgl->stats->prb.basic.failed - origfailed;
12953   lifted = lgl->stats->prb.basic.lifted - origlifted;
12954 #ifndef NLGLOG
12955   assert (lgl->stats->prb.basic.probed >= origprobed);
12956   probed = lgl->stats->prb.basic.probed - origprobed;
12957   LOG (1, "%ssuccessfully probed %d out of %d probes %.1f%%",
12958        success ? "" : "un", probed, nprobes, lglpcnt (probed, nprobes));
12959   LOG (1, "found %d failed %.1f%% lifted %d through probing",
12960        failed, lglpcnt (failed, probed), lifted);
12961 #endif
12962   assert (lgl->probing && lgl->simp && lgl->basicprobing);
12963   lgl->simp = lgl->probing = lgl->basicprobing = 0;
12964   units = failed + lifted;
12965   lglprt (lgl, 1 + !units,
12966     "[basicprobe-%d-%d] %d units = %d failed (%.0f%%) + %d lifted (%.0f%%)",
12967     lgl->stats->prb.basic.count, round,
12968     units, failed, lglpcnt (failed, units), lifted, lglpcnt (lifted, units));
12969   lglprt (lgl, 1 + !success,
12970     "[basicprobe-%d-%d] removed %d variables, found %d hbrs",
12971     lgl->stats->prb.basic.count, round, deltarem, deltahbr);
12972   lglrep (lgl, 2, 'p');
12973   lglstop (lgl);
12974   lglbasicatestats (lgl);
12975   return !lgl->mt;
12976 }
12977 
lglsmallirr(LGL * lgl)12978 static int lglsmallirr (LGL * lgl) {
12979   int maxirrlidx = lglcntstk (&lgl->irr), limit;
12980   int64_t tmp = MAXREDLIDX;
12981   tmp *= lgl->opts->smallirr.val;
12982   tmp /= 100;
12983   limit = (tmp < INT_MAX) ? tmp : INT_MAX;
12984   if (maxirrlidx >= limit) return 0;
12985   return  1;
12986 }
12987 
lglprobe(LGL * lgl)12988 static int lglprobe (LGL * lgl) {
12989   int res = 1, mod = 0, all, small = lglsmallirr (lgl);
12990   int (*prb[3])(LGL *);
12991   lglstart (lgl, &lgl->times->probe);
12992   if (small && lgl->opts->prbsimple.val) prb[mod++] = lglsimpleprobe;
12993   if (small && lgl->opts->treelook.val) prb[mod++] = lgltreelook;
12994   if (lgl->opts->prbasic.val) prb[mod++] = lglbasicprobe;
12995   all = lgl->stats->prb.simple.count;
12996   all += lgl->stats->prb.basic.count;
12997   all += lgl->stats->prb.treelook.count;
12998   if (lgl->stats->simp.count == 2) {
12999     int i;
13000     res = 1;
13001     for (i = 0; res && i < mod; i++) res = prb[i] (lgl);
13002   } else res = mod ? prb[all % mod] (lgl) : 1;
13003   lglstop (lgl);
13004   return res;
13005 }
13006 
lglinitevars(LGL * lgl)13007 static void lglinitevars (LGL * lgl) {
13008   EVar * ev;
13009   int idx;
13010   assert (lgl->occs);
13011   NEW (lgl->evars, lgl->nvars);
13012   for (idx = 2; idx < lgl->nvars; idx++) {
13013     ev = lgl->evars + idx;
13014     ev->pos = -1;
13015   }
13016 }
13017 
lgldense(LGL * lgl,int rmredbintrn)13018 static void lgldense (LGL * lgl, int rmredbintrn) {
13019   int lit, lidx, count, idx, other, other2, blit, sign, tag, red;
13020   const int * start, * top, * c, * p, * eow;
13021   int * q, * w;
13022   EVar * ev;
13023   HTS * hts;
13024   LOG (1, "transition to dense mode");
13025   assert (!lgl->dense);
13026   assert (!lgl->rmredbintrn);
13027   assert (!lgl->evars);
13028   assert (lglsmallirr (lgl));
13029   assert (lglmtstk (&lgl->esched));
13030   assert (lglmtstk (&lgl->saved.bin));
13031   assert (lglmtstk (&lgl->saved.trn));
13032   assert (!lgl->eliminating || !lgl->elm->pivot);
13033   lgl->stats->dense++;
13034   if (rmredbintrn) {
13035     lgl->rmredbintrn = 1;
13036     LOG (1, "temporarily removing redundant binary and ternary clauses");
13037   }
13038   count = 0;
13039   if (lgl->occs) lglinitevars (lgl);
13040   for (idx = 2; idx < lgl->nvars; idx++)
13041     for (sign = -1; sign <= 1; sign += 2) {
13042       lit = sign * idx;
13043       hts = lglhts (lgl, lit);
13044       if (!hts->count) continue;
13045       q = w = lglhts2wchs (lgl, hts);
13046       eow = w + hts->count;
13047       for (p = w; p < eow; p++) {
13048 	blit = *p;
13049 	tag = blit & MASKCS;
13050 	if (tag == TRNCS || tag == LRGCS) p++;
13051 	red = blit & REDCS;
13052 	if (red) {
13053 	   if (tag == LRGCS) continue;
13054 	   if (rmredbintrn) {
13055 	     assert (tag == BINCS || tag == TRNCS);
13056 	     other = blit >> RMSHFT;
13057 	     if (abs (other) < idx) continue;
13058 	     if (tag == TRNCS) {
13059 	       other2 = *p;
13060 	       if (abs (other2) < idx) continue;
13061 	       lglpushstk (lgl, &lgl->saved.trn, lit);
13062 	       lglpushstk (lgl, &lgl->saved.trn, other);
13063 	       lglpushstk (lgl, &lgl->saved.trn, other2);
13064 	       assert (lgl->stats->red.trn);
13065 	       lgl->stats->red.trn--;
13066 	     } else {
13067 	       lglpushstk (lgl, &lgl->saved.bin, lit);
13068 	       lglpushstk (lgl, &lgl->saved.bin, other);
13069 	       assert (lgl->stats->red.bin);
13070 	       lgl->stats->red.bin--;
13071 	     }
13072 	   } else {
13073 	     *q++ = blit;
13074 	     if (tag == TRNCS) *q++ = *p;
13075 	   }
13076 	} else {
13077 	  *q++ = blit;
13078 	  if (tag == LRGCS || tag == TRNCS) *q++ = *p;
13079 	  if (tag == LRGCS) continue;
13080 	  assert (tag == BINCS || tag == TRNCS);
13081 	  other = blit >> RMSHFT;
13082 	  if (abs (other) < idx) continue;
13083 	  if (tag == TRNCS) {
13084 	    other2 = *p;
13085 	    if (abs (other2) < idx) continue;
13086 	    lglincocc (lgl, other2), count++;
13087 	  }
13088 	  lglincocc (lgl, lit), count++;
13089 	  lglincocc (lgl, other), count++;
13090 	}
13091       }
13092       lglshrinkhts (lgl, hts, q - w);
13093     }
13094   lglfitstk (lgl, &lgl->saved.bin);
13095   lglfitstk (lgl, &lgl->saved.trn);
13096   if (count)
13097     LOG (1, "counted %d occurrences in small irredundant clauses", count);
13098   {
13099     count = 0;
13100     start = lgl->irr.start;
13101     top = lgl->irr.top;
13102     for (c = start; c < top; c = p + 1) {
13103       p = c;
13104       if (*c >= NOTALIT) continue;
13105       lidx = c - start;
13106       assert (0 <= lidx), assert (lidx < MAXIRRLIDX);
13107       blit = (lidx << RMSHFT) | OCCS;
13108       for (; (lit = *p); p++) {
13109 	hts = lglhts (lgl, lit);
13110 	lglpushwch (lgl, hts, blit);
13111 	lglincocc (lgl, lit), count++;
13112       }
13113     }
13114   }
13115   if (count)
13116     LOG (1, "counted %d occurrences in large irredundant clauses", count);
13117   count = 0;
13118   if (lgl->occs) {
13119     for (idx = 2; idx < lgl->nvars; idx++) {
13120       ev = lglevar (lgl, idx);
13121       if (ev->pos >= 0) continue;
13122       if (lglifrozen (lgl, idx)) continue;
13123       if (lgl->donotsched) {
13124 	AVar * av = lglavar (lgl, idx);
13125 	if (lgl->eliminating && av->donotelm) continue;
13126 	if (lgl->blocking && av->donotblk) continue;
13127       }
13128       assert (!ev->occ[0] && !ev->occ[1]);
13129       lglesched (lgl, idx);
13130       count++;
13131     }
13132     if (count) LOG (1, "scheduled %d zombies", count);
13133   }
13134   LOG (1, "continuing in dense mode");
13135   lgl->dense = 1;
13136   lglfullyconnected (lgl);
13137   if (lgl->occs && lgl->opts->verbose.val >= 1) {
13138     const char * str;
13139     int inst, vl;
13140     count = 0;
13141     if (lgl->eliminating) str = "elim", inst = lgl->stats->elm.count, vl = 1;
13142     else if (lgl->blocking) str = "block", inst = lgl->stats->blk.count, vl=1;
13143     else str = "dense", inst = lgl->stats->dense, vl = 2;
13144     for (idx = 2; idx < lgl->nvars; idx++)
13145       if (lglevar (lgl, idx)->pos >= 0) count++;
13146     lglprt (lgl, vl,
13147       "[%s-%d] scheduled %d variables %.0f%%",
13148       str, inst, count, lglpcnt (count, lgl->nvars-2));
13149   }
13150 }
13151 
lglsparse(LGL * lgl)13152 static void lglsparse (LGL * lgl) {
13153   int idx, sign, lit, count, blit, tag;
13154   int * w, *p, * eow, * q;
13155   HTS * hts;
13156   assert (!lgl->notfullyconnected);
13157   assert (lgl->dense);
13158   lgl->stats->sparse++;
13159   count = 0;
13160   for (idx = 2; idx < lgl->nvars; idx++)
13161     for (sign = -1; sign <= 1; sign += 2) {
13162       lit = sign * idx;
13163       hts = lglhts (lgl, lit);
13164       if (!hts->count) continue;
13165       w = lglhts2wchs (lgl, hts);
13166       eow = w + hts->count;
13167       for (p = q = w; p < eow; p++) {
13168 	blit = *p;
13169 	tag = blit & MASKCS;
13170 	if (tag == OCCS) { count++; continue; }
13171 	*q++ = blit;
13172 	if (tag == BINCS) continue;
13173 	assert (tag == LRGCS || tag == TRNCS);
13174 	assert (p + 1 < eow);
13175 	*q++ = *++p;
13176       }
13177       assert (hts->count - (p - q) == q - w);
13178       lglshrinkhts (lgl, hts, q - w);
13179     }
13180   if (lgl->occs) {
13181     DEL (lgl->evars, lgl->nvars);
13182     lglrelstk (lgl, &lgl->esched);
13183   }
13184   LOG (1, "removed %d full irredundant occurrences", count);
13185   lgl->dense = 0;
13186   lgl->notfullyconnected = 1;
13187   LOG (1, "large clauses not fully connected yet");
13188 }
13189 
lglm2i(LGL * lgl,int mlit)13190 static int lglm2i (LGL * lgl, int mlit) {
13191   int res, midx = abs (mlit);
13192   assert (0 < midx);
13193   res = lglpeek (&lgl->elm->m2i, midx);
13194   if (mlit < 0) res = -res;
13195   return res;
13196 }
13197 
lgli2m(LGL * lgl,int ilit)13198 static int lgli2m (LGL * lgl, int ilit) {
13199   AVar * av = lglavar (lgl, ilit);
13200   int res = av->mark;
13201   if (!res) {
13202     res = lglcntstk (&lgl->seen) + 1;
13203     av->mark = res;
13204     assert (2*lglcntstk (&lgl->seen) == lglcntstk (&lgl->elm->noccs) - 2);
13205     assert (2*lglcntstk (&lgl->seen) == lglcntstk (&lgl->elm->mark) - 2);
13206     assert (2*lglcntstk (&lgl->seen) == lglcntstk (&lgl->elm->occs) - 2);
13207     assert (lglcntstk (&lgl->seen) == lglcntstk (&lgl->elm->m2i) - 1);
13208     lglpushstk (lgl, &lgl->seen, abs (ilit));
13209     lglpushstk (lgl, &lgl->elm->noccs, 0);
13210     lglpushstk (lgl, &lgl->elm->noccs, 0);
13211     lglpushstk (lgl, &lgl->elm->mark, 0);
13212     lglpushstk (lgl, &lgl->elm->mark, 0);
13213     lglpushstk (lgl, &lgl->elm->occs, 0);
13214     lglpushstk (lgl, &lgl->elm->occs, 0);
13215     lglpushstk (lgl, &lgl->elm->m2i, abs (ilit));
13216     LOG (4, "mapped internal variable %d to marked variable %d",
13217 	 abs (ilit), res);
13218   }
13219   if (ilit < 0) res = -res;
13220   return res;
13221 }
13222 
lglsig(int lit)13223 static unsigned lglsig (int lit) {
13224   unsigned ulit = lglulit (lit), res;
13225   assert (ulit >= 2);
13226   ulit -= 2;
13227   res = (1u << (ulit & 31));
13228   return res;
13229 }
13230 
lgladdecl(LGL * lgl,const int * c)13231 static void lgladdecl (LGL * lgl, const int * c) {
13232   int ilit, mlit, umlit, size = 0, next, prev;
13233   unsigned csig = 0;
13234   const int * p;
13235   Val val;
13236 #if !defined (NDEBUG) || !defined (NLGLOG)
13237   int lidx;
13238 #endif
13239   LOGCLS (3, c, "copying irredundant clause");
13240   INCSTEPS (elm.copies);
13241   size = 0;
13242   for (p = c; (ilit = *p); p++) {
13243     val = lglval (lgl, ilit);
13244     assert (val <= 0);
13245     if (val < 0) continue;
13246     size++;
13247     if (abs (ilit) == lgl->elm->pivot) continue;
13248     mlit = lgli2m (lgl, ilit);
13249     assert (abs (mlit) != 1);
13250     csig |= lglsig (mlit);
13251   }
13252   assert (size >= 1);
13253   next = lglcntstk (&lgl->elm->lits);
13254 #if !defined (NDEBUG) || !defined (NLGLOG)
13255   lidx = next;
13256 #endif
13257   assert (next > 0);
13258   for (p = c; (ilit = *p); p++) {
13259     val = lglval (lgl, ilit);
13260     if (val < 0) continue;
13261     mlit = lgli2m (lgl, ilit);
13262     lglpushstk (lgl, &lgl->elm->lits, mlit);
13263     umlit = lglulit (mlit);
13264     prev = lglpeek (&lgl->elm->occs, umlit);
13265     lglpushstk (lgl, &lgl->elm->next, prev);
13266     lglpoke (&lgl->elm->occs, umlit, next++);
13267     lglpushstk (lgl, &lgl->elm->csigs, csig);
13268     lglpushstk (lgl, &lgl->elm->sizes, size);
13269     lgl->elm->noccs.start[umlit]++;
13270   }
13271   lglpushstk (lgl, &lgl->elm->lits, 0);
13272   lglpushstk (lgl, &lgl->elm->next, 0);
13273   lglpushstk (lgl, &lgl->elm->csigs, 0);
13274   lglpushstk (lgl, &lgl->elm->sizes, 0);
13275   lgl->elm->necls++;
13276   LOGCLS (4, lgl->elm->lits.start + lidx, "copied and mapped clause");
13277 #ifndef NDEBUG
13278   LOGMCLS (4, lgl->elm->lits.start + lidx, "copied and remapped clause");
13279   {
13280     int i, j = 0;
13281     for (i = 0; c[i]; i++) {
13282       Val val = lglval (lgl, c[i]);
13283       assert (val <= 0);
13284       if (val < 0) continue;
13285       assert (c[i] == lglm2i (lgl, lglpeek (&lgl->elm->lits, lidx + j++)));
13286     }
13287   }
13288 #endif
13289 }
13290 
lglecls(LGL * lgl,int lit)13291 static int lglecls (LGL * lgl, int lit) {
13292   int blit, tag, red, other, lidx, count;
13293   const int * p, * w, * eow, * c;
13294   int d[4];
13295   HTS * hts;
13296   LOG (3, "copying irredundant clauses with %d", lit);
13297   count = 0;
13298   hts = lglhts (lgl, lit);
13299   if (!hts->count) return 0;
13300   w = lglhts2wchs (lgl, hts);
13301   eow = w + hts->count;
13302   for (p = w; p < eow; p++) {
13303     blit = *p;
13304     tag = blit & MASKCS;
13305     if (tag == TRNCS || tag == LRGCS) p++;
13306     if (tag == LRGCS) continue;
13307     red = blit & REDCS;
13308     if (red) continue;
13309     if (tag == BINCS || tag == TRNCS) {
13310       d[0] = lit;
13311       other = blit >> RMSHFT;
13312       d[1] = other;
13313       if (tag == TRNCS) d[2] = *p, d[3] = 0;
13314       else d[2] = 0;
13315       c = d;
13316     } else {
13317       assert (tag == OCCS);
13318       lidx = (tag == OCCS) ? (blit >> RMSHFT) : *p;
13319       c = lglidx2lits (lgl, 0, lidx);
13320     }
13321     lgladdecl (lgl, c);
13322     count++;
13323   }
13324   return count;
13325 }
13326 
lglrstecls(LGL * lgl)13327 static void lglrstecls (LGL * lgl)  {
13328   assert (lgl->elm->pivot);
13329   lglclnstk (&lgl->elm->lits);
13330   lglclnstk (&lgl->elm->next);
13331   lglclnstk (&lgl->elm->csigs);
13332   lglclnstk (&lgl->elm->sizes);
13333   lglclnstk (&lgl->elm->occs);
13334   lglclnstk (&lgl->elm->noccs);
13335   lglclnstk (&lgl->elm->mark);
13336   lglclnstk (&lgl->elm->m2i);
13337   lglpopnunmarkstk (lgl, &lgl->seen);
13338   lgl->elm->pivot = 0;
13339 }
13340 
lglrelecls(LGL * lgl)13341 static void lglrelecls (LGL * lgl)  {
13342   lglrelstk (lgl, &lgl->elm->lits);
13343   lglrelstk (lgl, &lgl->elm->next);
13344   lglrelstk (lgl, &lgl->elm->csigs);
13345   lglrelstk (lgl, &lgl->elm->sizes);
13346   lglrelstk (lgl, &lgl->elm->occs);
13347   lglrelstk (lgl, &lgl->elm->noccs);
13348   lglrelstk (lgl, &lgl->elm->mark);
13349   lglrelstk (lgl, &lgl->elm->m2i);
13350   lglrelstk (lgl, &lgl->elm->clv);
13351 }
13352 
lglinitecls(LGL * lgl,int idx)13353 static void lglinitecls (LGL * lgl, int idx) {
13354 #ifndef NLGLOG
13355   int clauses;
13356 #endif
13357   assert (!lgl->elm->pivot);
13358   assert (idx >= 2);
13359   assert (lglmtstk (&lgl->elm->lits));
13360   assert (lglmtstk (&lgl->elm->next));
13361   assert (lglmtstk (&lgl->elm->csigs));
13362   assert (lglmtstk (&lgl->elm->sizes));
13363   assert (lglmtstk (&lgl->elm->occs));
13364   assert (lglmtstk (&lgl->elm->noccs));
13365   assert (lglmtstk (&lgl->elm->m2i));
13366   assert (lglmtstk (&lgl->seen));
13367   lgl->elm->pivot = idx;
13368   lglpushstk (lgl, &lgl->elm->mark, 0);
13369   lglpushstk (lgl, &lgl->elm->mark, 0);
13370   lglpushstk (lgl, &lgl->elm->occs, 0);
13371   lglpushstk (lgl, &lgl->elm->occs, 0);
13372   lglpushstk (lgl, &lgl->elm->noccs, 0);
13373   lglpushstk (lgl, &lgl->elm->noccs, 0);
13374   lglpushstk (lgl, &lgl->elm->m2i, 0);
13375   (void) lgli2m (lgl, idx);
13376   lglpushstk (lgl, &lgl->elm->lits, 0);
13377   lglpushstk (lgl, &lgl->elm->next, 0);
13378   lglpushstk (lgl, &lgl->elm->csigs, 0);
13379   lglpushstk (lgl, &lgl->elm->sizes, 0);
13380   lgl->elm->necls = 0;
13381 #ifndef NLGLOG
13382   clauses =
13383 #endif
13384   lglecls (lgl, idx);
13385   lgl->elm->negcls = lgl->elm->necls;
13386   lgl->elm->neglidx = lglcntstk (&lgl->elm->lits);
13387 #ifndef NLGLOG
13388   clauses +=
13389 #endif
13390   lglecls (lgl, -idx);
13391   LOG (2, "found %d variables in %d clauses with %d or %d",
13392        lglcntstk (&lgl->seen), clauses, idx, -idx);
13393   assert (lgl->elm->pivot);
13394 }
13395 
lglelrmcls(LGL * lgl,int lit,int * c,int clidx)13396 static void lglelrmcls (LGL * lgl, int lit, int * c, int clidx) {
13397   int lidx, i, other, ulit, * lits, * csigs, blit, tag, red, other2;
13398   int * p, * eow, * w, count;
13399   HTS * hts;
13400 #ifndef NDEBUG
13401   int size;
13402 #endif
13403   lits = lgl->elm->lits.start;
13404   csigs = lgl->elm->csigs.start;
13405   assert (lits < c && c < lgl->elm->lits.top - 1);
13406   lidx = c - lits;
13407   LOGCLS (2, c, "removing clause");
13408   for (i = lidx; (other = lits[i]); i++) {
13409     assert (other < NOTALIT);
13410     lits[i] = REMOVED;
13411     csigs[i] = 0;
13412     ulit = lglulit (other);
13413     assert (ulit < lglcntstk (&lgl->elm->noccs));
13414     assert (lgl->elm->noccs.start[ulit] > 0);
13415     lgl->elm->noccs.start[ulit] -= 1;
13416   }
13417 #ifndef NDEBUG
13418   size = lglpeek (&lgl->elm->sizes, lidx);
13419 #endif
13420   hts = lglhts (lgl, lit);
13421   assert (hts->count > 0 && hts->count >= clidx);
13422   w = lglhts2wchs (lgl, hts);
13423   eow = w + hts->count;
13424   blit = tag = count = 0;
13425   for (p = w; p < eow; p++) {
13426     blit = *p;
13427     tag = blit & MASKCS;
13428     if (tag == TRNCS || tag == LRGCS) p++;
13429     if (tag == LRGCS) continue;
13430     red = blit & REDCS;
13431     if (red) continue;
13432     if (count == clidx) break;
13433     count++;
13434   }
13435   assert (count == clidx);
13436   assert (blit && tag);
13437   assert (p < eow);
13438   if (tag == BINCS) {
13439     assert (size >= 2);
13440     other = blit >> RMSHFT;
13441     lglrmbcls (lgl, lit, other, 0);
13442     lgldrupligdelclsarg (lgl, lit, other, 0);
13443   } else if (tag == TRNCS) {
13444     other = blit >> RMSHFT;
13445     other2 = *p;
13446     lgldrupligdelclsarg (lgl, lit, other, other2, 0);
13447     lglrmtcls (lgl, lit, other, other2, 0);
13448   } else {
13449     assert (tag == OCCS);
13450     lidx = (tag == OCCS) ? (blit >> RMSHFT) : *p;
13451 #ifndef NDEBUG
13452     {
13453       int * q, * d = lglidx2lits (lgl, 0, lidx);
13454       for (q = d; *q; q++)
13455 	;
13456       assert (q - d >= size);
13457     }
13458 #endif
13459     lgldrupligdelclsaux (lgl, lglidx2lits (lgl, 0, lidx));
13460     lglrmlcls (lgl, lidx, 0);
13461   }
13462 }
13463 
13464 #define BWL 2
13465 
lglbacksub(LGL * lgl,int * c,int str,int ** dptr,int * dlidxptr)13466 static int lglbacksub (LGL * lgl, int * c, int str,
13467                        int ** dptr, int * dlidxptr) {
13468   int * start = lgl->elm->lits.start, * p, * q, marked = 0, res, * d;
13469   int lit, ulit, occ, next, osize, other, uolit, size, plit, phase, clidx;
13470   unsigned ocsig, csig = 0, masksig;
13471 #ifndef NLGLOG
13472   const char * mode = str ? "strengthening" : "subsumption";
13473 #endif
13474   LOGMCLS (BWL + 1, c, "backward %s check for clause", mode);
13475   LOGCLS (BWL + 1, c, "backward %s check for mapped clause", mode);
13476   phase = (c - start) >= lgl->elm->neglidx;
13477   for (p = c; (lit = *p); p++)
13478     if (abs (lit) != 1)
13479       csig |= lglsig (lit);
13480   size = p - c;
13481   assert (csig == lglpeek (&lgl->elm->csigs, c - start));
13482   assert (size == lglpeek (&lgl->elm->sizes, c - start));
13483   res = 0;
13484   if (dptr) *dptr = 0;
13485   if (dlidxptr) *dlidxptr = 0;
13486 
13487   if (str) phase = !phase;
13488   lit = phase ? -1 : 1;
13489   masksig = ~(lglsig (-lit) | lglsig (lit));
13490 
13491   ulit = lglulit (lit);
13492   occ = lglpeek (&lgl->elm->noccs, ulit);
13493   if (!str && occ <= 1) return 0;
13494   if (str && !occ) return 0;
13495   if (occ > lgl->elm->bkwdocclim) return 0;
13496   for (next = lglpeek (&lgl->elm->occs, ulit);
13497        !res && next &&
13498 	 lgl->limits->elm.steps > lgl->stats->elm.steps;
13499        next = lglpeek (&lgl->elm->next, next)) {
13500       INCSTEPS (elm.steps);
13501       if (next == p - start) continue;
13502       if (phase != (next >= lgl->elm->neglidx)) continue;
13503       plit = lglpeek (&lgl->elm->lits, next);
13504       if (plit >= NOTALIT) continue;
13505       assert (plit == lit);
13506       osize = lglpeek (&lgl->elm->sizes, next);
13507       INCSTEPS (elm.steps);
13508       if (osize > size) continue;
13509       ocsig = lglpeek (&lgl->elm->csigs, next);
13510       INCSTEPS (elm.steps);
13511       assert (ocsig);
13512       ocsig &= masksig;
13513       if ((ocsig & ~csig)) continue;
13514       if (!marked) {
13515 	for (q = c; (other = *q); q++) {
13516 	  if (str && abs (other) == 1) other = -other;
13517 	  uolit = lglulit (other);
13518 	  assert (!lglpeek (&lgl->elm->mark, uolit));
13519 	  lglpoke (&lgl->elm->mark, uolit, 1);
13520 	}
13521 	marked = 1;
13522         ADDSTEPS (elm.steps, q-c);
13523       }
13524       d = lgl->elm->lits.start + next;
13525       if (c <= d && d < c + size) continue;
13526       if (str) lgl->stats->elm.strchks++; else lgl->stats->elm.subchks++;
13527       while (d[-1]) d--;
13528       assert (c != d);
13529       LOGMCLS (BWL + 1, d, "backward %s check with clause", mode);
13530       res = 1;
13531       for (q = d; res && (other = *q); q++) {
13532 	uolit = lglulit (other);
13533 	res = lglpeek (&lgl->elm->mark, uolit);
13534       }
13535       ADDSTEPS (elm.steps, q-d);
13536       if (!res || !str || osize < size) continue;
13537       ADDSTEPS (elm.steps, q-d);
13538       LOGMCLS (BWL, d,
13539         "static double strengthened by double self-subsuming resolution");
13540       q = lgl->elm->lits.start;
13541       if (phase) {
13542         assert ((c - start) < lgl->elm->neglidx);
13543         assert ((d - start) >= lgl->elm->neglidx);
13544 	q += lgl->elm->neglidx;
13545       } else {
13546         assert (!phase);
13547         assert ((d - start) < lgl->elm->neglidx);
13548         assert ((c - start) >= lgl->elm->neglidx);
13549 	assert (!lglpeek (&lgl->elm->lits, 0));
13550 	q++;
13551       }
13552       clidx = 0;
13553       while (q < d) {
13554 	other = *q++;
13555 	if (other >= NOTALIT) {
13556 	  while (*q++)
13557 	    ;
13558 	  continue;
13559 	}
13560 	if (!other) clidx++;
13561       }
13562       LOGMCLS (BWL, d,
13563 	"strengthened and subsumed original irredundant clause");
13564       LOGCLS (BWL, d,
13565         "strengthened and subsumed mapped irredundant clause");
13566       *dptr = d, *dlidxptr = clidx;
13567       assert (res);
13568   }
13569   if (marked) {
13570     for (p = c; (lit = *p); p++) {
13571       if (str && abs (lit) == 1) lit = -lit;
13572       ulit = lglulit (lit);
13573       assert (lglpeek (&lgl->elm->mark, ulit));
13574       lglpoke (&lgl->elm->mark, ulit, 0);
13575     }
13576     ADDSTEPS (elm.steps, q-c);
13577   }
13578   return res;
13579 }
13580 
lglelmsub(LGL * lgl)13581 static void lglelmsub (LGL * lgl) {
13582   int clidx, count, subsumed, pivot, * c;
13583   if (!lgl->opts->elmotfsub.val) return;
13584   count = clidx = subsumed = 0;
13585   pivot = lgl->elm->pivot;
13586   for (c = lgl->elm->lits.start + 1;
13587        c < lgl->elm->lits.top &&
13588 	 lgl->limits->elm.steps > lgl->stats->elm.steps;
13589        c++) {
13590     INCSTEPS (elm.steps);
13591     if (count++ == lgl->elm->negcls) clidx = 0, pivot = -pivot;
13592     if (lglbacksub (lgl, c, 0, 0, 0)) {
13593       subsumed++;
13594       lgl->stats->elm.sub++;
13595       LOGMCLS (BWL, c, "subsumed original irredundant clause");
13596       LOGCLS (3, c, "subsumed mapped irredundant clause");
13597       lglelrmcls (lgl, pivot, c, clidx);
13598     } else clidx++;
13599     while (*c) c++;
13600   }
13601   LOG (BWL + !subsumed,
13602     "subsumed %d clauses containing %d or %d",
13603     subsumed, lgl->elm->pivot, -lgl->elm->pivot);
13604 }
13605 
lglelmstr(LGL * lgl)13606 static int lglelmstr (LGL * lgl) {
13607   int clidx, count, strengthened, pivot, * c, * p, mlit, ilit, res, found;
13608   int * d, dlidx;
13609   int size;
13610   if (!lgl->opts->elmotfstr.val) return 0;
13611   count = clidx = strengthened = 0;
13612   pivot = lgl->elm->pivot;
13613   res = 0;
13614   LOG (3, "strengthening with pivot %d", pivot);
13615   for (c = lgl->elm->lits.start + 1;
13616        c < lgl->elm->lits.top &&
13617 	 lgl->limits->elm.steps > lgl->stats->elm.steps;
13618        c++) {
13619     INCSTEPS (elm.steps);
13620     if (count++ == lgl->elm->negcls) {
13621       clidx = 0, pivot = -pivot;
13622       LOG (3, "strengthening with pivot %d", pivot);
13623     }
13624     if (*c == REMOVED) {
13625       while (*c) { assert (*c == REMOVED); c++; }
13626       continue;
13627     }
13628     if (lglbacksub (lgl, c, 1, &d, &dlidx)) {
13629       strengthened++;
13630       lgl->stats->elm.str++;
13631       LOGMCLS (2, c, "strengthening original irredundant clause");
13632       LOGCLS (3, c, "strengthening mapped irredundant clause");
13633       assert (lglmtstk (&lgl->clause));
13634       found = 0;
13635       size = 0;
13636       for (p = c; (mlit = *p); p++) {
13637 	ilit = lglm2i (lgl, *p);
13638 	if (ilit == pivot) { found++; continue; }
13639 	assert (!lglval (lgl, ilit));
13640 	lglpushstk (lgl, &lgl->clause, ilit);
13641 	size++;
13642       }
13643       assert (found);
13644       lglpushstk (lgl, &lgl->clause, 0);
13645       LOGCLS (2, lgl->clause.start, "static strengthened irredundant clause");
13646       lgldrupligaddcls (lgl, REDCS);
13647       if (d) lglelrmcls (lgl, -pivot, d, dlidx);
13648       lglelrmcls (lgl, pivot, c, clidx);
13649       lgladdcls (lgl, 0, 0, 1);
13650       lglclnstk (&lgl->clause);
13651       if (size == 1) { res = 1; break; }
13652     } else clidx++;
13653     while (*c) c++;
13654   }
13655   LOG (2, "strengthened %d clauses containing %d or %d",
13656        strengthened, lgl->elm->pivot, -lgl->elm->pivot);
13657   return res;
13658 }
13659 
lglflushclauses(LGL * lgl,int lit)13660 static int lglflushclauses (LGL * lgl, int lit) {
13661   int blit, tag, red, other, other2, count, glue, res;
13662   const int druplig = lgl->opts->druplig.val;
13663   const int * p, * w, * eow;
13664   int lidx, glidx, slidx;
13665   int * c, * q;
13666   HTS * hts;
13667   Stk * s;
13668 #ifndef NDEBUG
13669   int occs;
13670 #endif
13671   lglchkirrstats (lgl);
13672   assert (lgl->probing || lgl->lkhd || lgl->dense);
13673   hts = lglhts (lgl, lit);
13674   if (!hts->count) return 0;
13675 #ifndef NDEBUG
13676   occs = lgl->occs ? lglocc (lgl, lit) : 0;
13677 #endif
13678   res = 0;
13679   LOG (2, "flushing clauses with literal %d", lit);
13680   w = lglhts2wchs (lgl, hts);
13681   eow = w + hts->count;
13682   count = 0;
13683   for (p = w; p < eow; p++) {
13684     if (lgl->blocking) INCSTEPS (blk.steps);
13685     if (lgl->eliminating) INCSTEPS (elm.steps);
13686     if (lgl->simpleprobing) INCSTEPS (prb.simple.steps);
13687     blit = *p;
13688     tag = blit & MASKCS;
13689     red = blit & REDCS;
13690     other = blit >> RMSHFT;
13691     if (tag == TRNCS || tag == LRGCS) p++;
13692     if (tag == BINCS) {
13693       lglrmbwch (lgl, other, lit, red);
13694       LOG (2, "flushed %s binary clause %d %d", lglred2str (red), lit, other);
13695       if (druplig) lgldrupligdelclsarg (lgl, lit, other, 0);
13696       lgldeclscnt (lgl, 2, red, 0);
13697       if (!red) lgldecocc (lgl, lit), lgldecocc (lgl, other), res++;
13698       count++;
13699     } else if (tag == TRNCS) {
13700       other2 = *p;
13701       lglrmtwch (lgl, other2, lit, other, red);
13702       lglrmtwch (lgl, other, lit, other2, red);
13703       LOG (2, "flushed %s ternary clause %d %d %d",
13704 	   lglred2str (red), lit, other, other2);
13705       if (druplig) lgldrupligdelclsarg (lgl, lit, other, other2, 0);
13706       lgldeclscnt (lgl, 3, red, 0);
13707       if (!red)  {
13708 	lgldecocc (lgl, lit);
13709 	lgldecocc (lgl, other);
13710 	lgldecocc (lgl, other2);
13711 	res++;
13712       }
13713       count++;
13714     } else {
13715       assert (tag == OCCS || tag == LRGCS);
13716       if (tag == LRGCS) {
13717 	lidx = *p;
13718 	s = lglidx2stk (lgl, red, lidx);
13719 	if (red) {
13720 	  glue = lidx & GLUEMASK;
13721 	  c = s->start + (lidx >> GLUESHFT);
13722 	} else {
13723 	  glue = 0;
13724 	  c = s->start + lidx;
13725 	}
13726       } else {
13727 	lidx = (blit >> RMSHFT);
13728 	s = &lgl->irr;
13729 	c = s->start + lidx;
13730 	glue = 0;
13731       }
13732       if (c >= s->top || (other = c[0]) >= NOTALIT) continue;
13733       LOGCLS (2, c, "flushed %s large clause", lglred2str (red));
13734       if (druplig) lgldrupligdelclsaux (lgl, c);
13735       if (tag == LRGCS) {
13736 	if (other == lit) other = c[1];
13737 	assert (abs (other) != abs (lit));
13738 	lglrmlwch (lgl, other, red, lidx);
13739       } else {
13740 	glidx = lidx;
13741 	if (red) glidx <<= GLUESHFT;
13742 	if (c[1] != lit) lglrmlwch (lgl, c[1], red, glidx);
13743 	if (other != lit) lglrmlwch (lgl, other, red, glidx);
13744       }
13745       if (red) {
13746 	assert (!glue);
13747 	LGLCHKACT (c[-1]);
13748 	c[-1] = REMOVED;
13749       } else lgldecocc (lgl, lit);
13750       for (q = c; (other = *q); q++) { assert (other < NOTALIT);
13751 	*q = REMOVED;
13752 	if (other == lit) continue;
13753 	if (red && glue) continue;
13754 	slidx = lidx;
13755 	if (red && tag == LRGCS) slidx >>= GLUESHFT;
13756 	lglrmlocc (lgl, other, red, slidx);
13757 	if (!red) lgldecocc (lgl, other);
13758       }
13759       *q = REMOVED;
13760       lgldeclscnt (lgl, q - c, red, glue);
13761       lgltrimlitstk (lgl, red, lidx);
13762       if (!red) res++;
13763       count++;
13764     }
13765   }
13766 #ifndef NDEBUG
13767   if (lgl->occs) assert (occs == res);
13768 #endif
13769   lglshrinkhts (lgl, hts, 0);
13770   LOG (2, "flushed %d clauses with %d including %d irredundant",
13771        count, lit, res);
13772   lglchkirrstats (lgl);
13773   return res;
13774 }
13775 
lglflushlits(LGL * lgl,int lit)13776 static int lglflushlits (LGL * lgl, int lit) {
13777   int blit, tag, red, other, other2, size, satisfied, d[3], glue;
13778   const int druplig = lgl->opts->druplig.val;
13779   int * p, * w, * eow, * c, * l, * k;
13780   int lidx, slidx, glidx;
13781   int count, res;
13782   Val val, val2;
13783   long delta;
13784   Stk saved;
13785   Stk * s;
13786 
13787 // Some compilers do not like local functions, thus we use macros instead.
13788 //
13789 #define FIXPTRS() do { p += delta, w += delta, eow += delta; } while (0)
13790 
13791   HTS * hts;
13792   LOG (2, "flushing literal %d from clauses", lit);
13793   assert (!lgl->level);
13794   assert (lglifixed (lgl, lit) < 0);
13795   assert (lgl->dense);
13796   lglchkirrstats (lgl);
13797   hts = lglhts (lgl, lit);
13798   w = lglhts2wchs (lgl, hts);
13799   eow = w + hts->count;
13800   res = count = 0;
13801   CLR (saved);
13802   for (p = w; p < eow; p++) {
13803     if (lgl->blocking) INCSTEPS (blk.steps);
13804     if (lgl->eliminating) INCSTEPS (elm.steps);
13805     if (lgl->simpleprobing) INCSTEPS (prb.simple.steps);
13806     count++;
13807     blit = *p;
13808     tag = blit & MASKCS;
13809     red = blit & REDCS;
13810     if (tag == BINCS) {
13811       other = blit >> RMSHFT;
13812       assert ((red && lgliselim (lgl, other)) || lglval (lgl, other) > 0);
13813       lglrmbwch (lgl, other, lit, red);
13814       LOG (2, "flushed %s binary clause %d %d", lglred2str (red), lit, other);
13815       if (druplig) lgldrupligdelclsarg (lgl, lit, other, 0);
13816       lgldeclscnt (lgl, 2, red, 0);
13817       if (!red) {
13818 	if (lgl->dense) lgldecocc (lgl, lit), lgldecocc (lgl, other);
13819 	res++;
13820       }
13821     } else if (tag == TRNCS) {
13822       other = blit >> RMSHFT;
13823       other2 = *++p;
13824       lglrmtwch (lgl, other2, lit, other, red);
13825       lglrmtwch (lgl, other, lit, other2, red);
13826       LOG (2, "flushed %s ternary clause %d %d %d",
13827 	   lglred2str (red), lit, other, other2);
13828       lgldeclscnt (lgl, 3, red, 0);
13829       if (!red)  {
13830 	if (lgl->dense) {
13831 	  lgldecocc (lgl, lit);
13832 	  lgldecocc (lgl, other);
13833 	  lgldecocc (lgl, other2);
13834 	}
13835 	res++;
13836       }
13837       val = lglval (lgl, other);
13838       val2 = lglval (lgl, other2);
13839       if (!val && !val2) {
13840 	LOG (2,
13841   "reducing flushed %s ternary clause %d %d %d to binary %s clause %d %d",
13842 	     lglred2str (red),
13843 	     lit, other, other2,
13844 	     lglred2str (red),
13845 	     other, other2);
13846 	delta = lglwchbin (lgl, other, other2, red);
13847 	delta += lglwchbin (lgl, other2, other, red);
13848 	if (lgl->simpleprobing && lgl->opts->prbsimple.val >= 2)
13849 	  lglwrktouch (lgl, -other), lglwrktouch (lgl, -other2);
13850 	if (delta) FIXPTRS ();
13851 	if (red) {
13852 	  lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
13853 	} else {
13854 	  lglincirr (lgl, 2);
13855 	  if (lgl->dense) lglincocc (lgl, other), lglincocc (lgl, other2);
13856 	}
13857 	if (druplig) lgldrupligaddclsarg (lgl, REDCS, other, other2, 0);
13858       } else {
13859 #ifndef NDEBUG
13860 	if (!red || (!lgliselim (lgl, other) && !lgliselim (lgl, other2)))
13861 	  assert (val > 0 || val2 > 0);
13862 #endif
13863       }
13864       if (druplig) lgldrupligdelclsarg (lgl, lit, other, other2, 0);
13865     } else {
13866       assert (tag == OCCS || tag == LRGCS);
13867       lidx = (tag == LRGCS) ? *++p : (blit >> RMSHFT);
13868       s = lglidx2stk (lgl, red, lidx);
13869       c = s->start + (red ? (lidx >> GLUESHFT) : lidx);
13870       if (c >= s->top || c[0] >= NOTALIT) continue;
13871       size = satisfied = 0;
13872       assert (lglmtstk (&saved));
13873       for (l = c; (other = *l); l++) {
13874 	if (druplig) lglpushstk (lgl, &saved, other);
13875 	if (satisfied) continue;
13876 	if (other == lit) continue;
13877 	if ((val = lglval (lgl, other)) < 0) continue;
13878 	if (val > 0) { satisfied = 1; continue; }
13879 	if (size < 3) d[size] = other;
13880 	size++;
13881       }
13882       if (!satisfied && size == 2) {
13883 	LOGCLS (2, c,
13884 	  "reducing to binary %s clause %d %d flushed large %s clause",
13885 	     lglred2str (red), d[0], d[1], lglred2str (red));
13886 	delta = lglwchbin (lgl, d[0], d[1], red);
13887 	delta += lglwchbin (lgl, d[1], d[0], red);
13888 	if (delta) FIXPTRS ();
13889 	if (red) {
13890 	  lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
13891 	} else {
13892 	  lglincirr (lgl, 2);
13893 	  if (lgl->dense) lglincocc (lgl, d[0]), lglincocc (lgl, d[1]);
13894 	}
13895 	if (lgl->simpleprobing && lgl->opts->prbsimple.val >= 2)
13896 	  lglwrktouch (lgl, -d[0]), lglwrktouch (lgl, -d[1]);
13897 	if (druplig) lgldrupligaddclsarg (lgl, REDCS, d[0], d[1], 0);
13898       }
13899       if (!satisfied && size == 3) {
13900 	LOGCLS (2, c,
13901 	  "reducing to ternary %s clause %d %d %d flushed large %s clause",
13902 	     lglred2str (red), d[0], d[1], d[2], lglred2str (red));
13903 	delta = lglwchtrn (lgl, d[0], d[1], d[2], red);
13904 	delta += lglwchtrn (lgl, d[1], d[0], d[2], red);
13905 	delta += lglwchtrn (lgl, d[2], d[0], d[1], red);
13906 	if (delta) FIXPTRS ();
13907 	if (red) {
13908 	  lgl->stats->red.trn++, assert (lgl->stats->red.trn > 0);
13909 	} else {
13910 	  lglincirr (lgl, 3);
13911 	  if (lgl->dense) {
13912 	    lglincocc (lgl, d[0]);
13913 	    lglincocc (lgl, d[1]);
13914 	    lglincocc (lgl, d[2]);
13915 	  }
13916 	}
13917 	if (lgl->simpleprobing && lgl->opts->prbsimple.val >= 3)
13918 	  lglwrktouch (lgl, d[0]),
13919 	  lglwrktouch (lgl, d[1]),
13920 	  lglwrktouch (lgl, d[2]);
13921 	if (druplig) lgldrupligaddclsarg (lgl, REDCS, d[0], d[1], d[2], 0);
13922       }
13923       if (lgl->dense && !red) {
13924 	for (l = c; (other = *l); l++) {
13925 	  if (satisfied || size <= 3 || lglval (lgl, other) < 0) {
13926 	    if (!red) lgldecocc (lgl, other);
13927 	    if (other != lit) {
13928 	      slidx = lidx;
13929 	      if (red && tag == LRGCS) slidx >>= GLUESHFT;
13930 	      lglrmlocc (lgl, other, red, slidx);
13931 	    }
13932 	  }
13933 	}
13934       }
13935       glidx = lidx;
13936       if (red && tag == OCCS) glidx <<= GLUESHFT;
13937       if (c[0] != lit) lglrmlwch (lgl, c[0], red, glidx);
13938       if (c[1] != lit) lglrmlwch (lgl, c[1], red, glidx);
13939       if (satisfied || size <= 3) {
13940 	if (red) { LGLCHKACT (c[-1]); c[-1] = REMOVED; }
13941 	for (k = c; (other = *k); k++) *k = REMOVED;
13942 	*k = REMOVED;
13943 	if (red) {
13944 	  glue = (tag == LRGCS) ? (lidx & GLUEMASK) : 0;
13945 	  assert (lgl->stats->lir[glue].clauses > 0);
13946 	  lgl->stats->lir[glue].clauses--;
13947 	  assert (lgl->stats->red.lrg > 0);
13948 	  lgl->stats->red.lrg--;
13949 	} else lgldecirr (lgl, k - c);
13950       } else {
13951 	for (l = k = c; (other = *l); l++) {
13952 	  if ((val = lglval (lgl, other)) < 0) continue;
13953 	  if (lgl->simpleprobing && lgl->opts->prbsimple.val >= 3)
13954 	    lglwrktouch (lgl, other);
13955 	  assert (abs (other) != abs (lit));
13956 	  assert (!val);
13957 	  *k++ = other;
13958 	}
13959 	assert (size == k - c);
13960 	if (!red && k < l) {
13961 	  assert (lgl->stats->irr.lits.cur >= l - k);
13962 	  lgl->stats->irr.lits.cur -= l - k;
13963 	}
13964 	*k++ = 0;
13965 	while (k <= l) *k++ = REMOVED;
13966 	delta = lglwchlrg (lgl, c[0], c[1], red, glidx);
13967 	delta += lglwchlrg (lgl, c[1], c[0], red, glidx);
13968 	if (delta) FIXPTRS ();
13969 	if (druplig) lgldrupligaddclsaux (lgl, REDCS, c);
13970       }
13971       lgltrimlitstk (lgl, red, lidx);
13972       if (druplig) {
13973 	assert (lglcntstk (&saved) >= 4);
13974 	lglpushstk (lgl, &saved, 0);
13975 	lgldrupligdelclsaux (lgl, saved.start);
13976 	lglclnstk (&saved);
13977       }
13978     }
13979   }
13980   lglrelstk (lgl, &saved);
13981   hts = lglhts (lgl, lit);
13982   lglshrinkhts (lgl, hts, 0);
13983   LOG (2, "flushed %d occurrences of literal %d including %d irredundant",
13984        count, lit, res);
13985   lglchkirrstats (lgl);
13986   return res;
13987 
13988 #undef FIXPTRS
13989 
13990 }
13991 
lglflush(LGL * lgl)13992 static int lglflush (LGL * lgl) {
13993   int lit, count;
13994   if (lgl->mt) return 0;
13995   lglchkirrstats (lgl);
13996   assert (!lgl->level);
13997   assert (lgl->probing || lgl->lkhd || lgl->dense);
13998   if (lgl->flushed == lglcntstk (&lgl->trail)) return 1;
13999   if (!lglbcp (lgl)) { lglmt (lgl); return 0; }
14000   if (!lglsyncunits (lgl)) { assert (lgl->mt); return 0; }
14001   count = 0;
14002   while  (lgl->flushed < lglcntstk (&lgl->trail)) {
14003     lit = lglpeek (&lgl->trail, lgl->flushed++);
14004     lglflushclauses (lgl, lit);
14005     lglflushlits (lgl, -lit);
14006     count++;
14007   }
14008   LOG (2, "flushed %d literals", count);
14009   assert (!lgl->mt);
14010   return 1;
14011 }
14012 
lglblockinglit(LGL * lgl,int ilit)14013 static void lglblockinglit (LGL * lgl, int ilit) {
14014   int elit = lglexport (lgl, ilit), sgnbit = (1 << (elit < 0));
14015   Ext * ext = lglelit2ext (lgl, elit);
14016   assert (!ext->equiv);
14017   assert (!ext->eliminated);
14018   assert (abs (ext->repr) == abs (ilit));
14019   if (ext->blocking & sgnbit) return;
14020   ext->blocking |= sgnbit;
14021   LOG (3, "marking external %d internal %d as blocking", elit, ilit);
14022   lgl->stats->blk.lits++;
14023 }
14024 
lglelmfrelit(LGL * lgl,int mpivot,int * sop,int * eop,int * son,int * eon)14025 static void lglelmfrelit (LGL * lgl, int mpivot,
14026 			  int * sop, int * eop, int * son, int * eon) {
14027   int ipivot = mpivot * lgl->elm->pivot, clidx, ilit, tmp, cover, maxcover;
14028   int * c, * d, * p, * q, lit, nontrivial, idx, sgn, clen, reslen;
14029   assert (mpivot == 1 || mpivot == -1);
14030   assert (ipivot);
14031   LOG (3,
14032        "blocked clause elimination and forced resolution of clauses with %d",
14033 	ipivot);
14034   clidx = 0;
14035   cover = lglpeek (&lgl->elm->noccs, lglulit (-mpivot));
14036   for (c = sop; c < eop; c = p + 1) {
14037     if (lgl->eliminating) INCSTEPS (elm.steps);
14038     if (*c == REMOVED) {
14039       for (p = c + 1; *p; p++)
14040 	;
14041       continue;
14042     }
14043     maxcover = 0;
14044     for (p = c; (lit = *p); p++) {
14045       if (lit == mpivot) continue;
14046       assert (lit != -mpivot);
14047       maxcover += lglpeek (&lgl->elm->noccs, lglulit (-lit));
14048     }
14049     if (maxcover < cover - 1) { clidx++; continue; }
14050     for (p = c; (lit = *p); p++) {
14051       if (lit == mpivot) continue;
14052       assert (lit != -mpivot);
14053       idx = abs (lit);
14054       assert (!lglpeek (&lgl->elm->mark, idx));
14055       sgn = lglsgn (lit);
14056       lglpoke (&lgl->elm->mark, idx, sgn);
14057     }
14058     nontrivial = 0;
14059     clen = p - c;
14060     for (d = son; !nontrivial && d < eon; d = q + 1) {
14061       INCSTEPS (elm.steps);
14062       if (*d == REMOVED) {
14063 	for (q = d + 1; *q; q++)
14064 	  ;
14065 	continue;
14066       }
14067       INCSTEPS (elm.resolutions);
14068       LOGMCLS (3, c, "trying forced resolution 1st antecedent");
14069       LOGMCLS (3, d, "trying forced resolution 2nd antecedent");
14070       assert (clen > 0);
14071       reslen = clen - 1;
14072       for (q = d; (lit = *q); q++) {
14073 	if (lit == -mpivot) continue;
14074 	assert (lit != mpivot);
14075 	idx = abs (lit), sgn = lglsgn (lit);
14076 	tmp = lglpeek (&lgl->elm->mark, idx);
14077 	if (tmp == -sgn) break;
14078 	if (tmp != sgn) reslen++;
14079       }
14080       if (lit) {
14081 	while (*++q) ;
14082 	LOG (3, "trying forced resolution ends with trivial resolvent");
14083       } else {
14084 	LOG (3, "non trivial resolvent in blocked clause elimination");
14085 	nontrivial = INT_MAX;
14086       }
14087     }
14088     for (p = c; (lit = *p); p++) {
14089       if (lit == mpivot) continue;
14090       assert (lit != -mpivot);
14091       idx = abs (lit);
14092       assert (lglpeek (&lgl->elm->mark, idx) == lglsgn (lit));
14093       lglpoke (&lgl->elm->mark, idx, 0);
14094     }
14095     assert (lgl->opts->elim.val);
14096     if (!nontrivial &&
14097         lgl->opts->block.val &&
14098 	lgl->opts->elmblk.val &&
14099 	(!lgl->opts->elmblkwait.val || !lgl->opts->elim.val || lgl->elmrtc)) {
14100       assert (maxcover >= cover);
14101       lgl->stats->elm.blkd++;
14102       LOGMCLS (2, c, "blocked on %d clause", ipivot);
14103       lglepush (lgl, ipivot);
14104       for (p = c; (lit = *p); p++) {
14105 	if (lit == mpivot) continue;
14106 	assert (lit != -mpivot);
14107 	ilit = lglm2i (lgl, lit);
14108 	lglepush (lgl, ilit);
14109       }
14110       lglepush (lgl, 0);
14111       lglelrmcls (lgl, ipivot, c, clidx);
14112       lglblockinglit (lgl, ipivot);
14113       continue;
14114     }
14115     clidx++;
14116     if (lgl->limits->elm.steps <= lgl->stats->elm.steps) {
14117       LOG (2, "maximum number of steps in elimination exhausted");
14118       return;
14119     }
14120   }
14121 }
14122 
lglelmfre(LGL * lgl)14123 static void lglelmfre (LGL * lgl) {
14124   int * sop, * eop, * son, * eon;
14125   assert (lgl->elm->pivot);
14126   sop = lgl->elm->lits.start + 1;
14127   eop = son = lgl->elm->lits.start + lgl->elm->neglidx;
14128   eon = lgl->elm->lits.top;
14129   lglelmfrelit (lgl, 1, sop, eop, son, eon);
14130   lglelmfrelit (lgl, -1, son, eon, sop, eop);
14131 }
14132 
lgleliminated(LGL * lgl,int pivot)14133 static void lgleliminated (LGL * lgl, int pivot) {
14134   AVar * av;
14135   int elit;
14136   Ext * e;
14137   assert (!lglifrozen (lgl, pivot));
14138   av = lglavar (lgl, pivot);
14139   assert (av->type == FREEVAR);
14140   av->type = ELIMVAR;
14141   lgl->stats->elm.elmd++;
14142   assert (lgl->stats->elm.elmd > 0);
14143   lglflushclauses (lgl, pivot);
14144   lglflushclauses (lgl, -pivot);
14145   LOG (2, "eliminated %d", pivot);
14146   elit = lglexport (lgl, pivot);
14147   e = lglelit2ext (lgl, elit);
14148   assert (!e->eliminated);
14149   assert (!e->equiv);
14150   e->eliminated = 1;
14151 }
14152 
lglepusheliminated(LGL * lgl,int idx)14153 static void lglepusheliminated (LGL * lgl, int idx) {
14154   const int * p, * w, * eow, * c, * l;
14155   int lit, blit, tag, red, other;
14156   HTS * hts;
14157   lit = (lglocc (lgl, idx) < lglocc (lgl, -idx)) ? idx : -idx;
14158   LOG (3, "keeping clauses with %d for extending assignment", lit);
14159   hts = lglhts (lgl, lit);
14160   w = lglhts2wchs (lgl, hts);
14161   eow = w + hts->count;
14162   for (p = w; p < eow; p++) {
14163     blit = *p;
14164     tag = blit & MASKCS;
14165     if (tag == TRNCS || tag == LRGCS) p++;
14166     if (tag == LRGCS) continue;
14167     red = blit & REDCS;
14168     if (red) continue;
14169     lglepush (lgl, lit);
14170     if (tag == BINCS || tag == TRNCS) {
14171       lglepush (lgl, blit >> RMSHFT);
14172       if (tag == TRNCS)
14173 	lglepush (lgl, *p);
14174     } else {
14175       assert (tag == OCCS);
14176       c = lglidx2lits (lgl, 0, blit >> RMSHFT);
14177       for (l = c; (other = *l); l++)
14178 	if (other != lit)
14179 	  lglepush (lgl, other);
14180     }
14181     lglepush (lgl, 0);
14182   }
14183   lglepush (lgl, -lit);
14184   lglepush (lgl, 0);
14185   lgleliminated (lgl, idx);
14186 }
14187 
lglunhimpl(const DFPR * dfpr,int a,int b)14188 static int lglunhimpl (const DFPR * dfpr, int a, int b) {
14189   int u = lglulit (a), v = lglulit (b), c, d, f, g;
14190   c = dfpr[u].discovered; if (!c) return 0;
14191   d = dfpr[v].discovered; if (!d) return 0;
14192   f = dfpr[u].finished, g = dfpr[v].finished;
14193   assert (0 < c && c < f);
14194   assert (0 < d && d < g);
14195   return c < d && g < f;
14196 }
14197 
lglunhimplies2(const DFPR * dfpr,int a,int b)14198 static int lglunhimplies2 (const DFPR * dfpr, int a, int b) {
14199   return lglunhimpl (dfpr, a, b) || lglunhimpl (dfpr, -b, -a);
14200 }
14201 
lglunhimplincl(const DFPR * dfpr,int a,int b)14202 static int lglunhimplincl (const DFPR * dfpr, int a, int b) {
14203   int u = lglulit (a), v = lglulit (b), c, d, f, g;
14204   c = dfpr[u].discovered; if (!c) return 0;
14205   d = dfpr[v].discovered; if (!d) return 0;
14206   f = dfpr[u].finished, g = dfpr[v].finished;
14207   assert (0 < c && c < f);
14208   assert (0 < d && d < g);
14209   return c <= d && g <= f;
14210 }
14211 
lglunhimplies2incl(const DFPR * dfpr,int a,int b)14212 static int lglunhimplies2incl (const DFPR * dfpr, int a, int b) {
14213   return lglunhimplincl (dfpr, a, b) || lglunhimplincl (dfpr, -b, -a);
14214 }
14215 
lglhastrn(LGL * lgl,int a,int b,int c)14216 static int lglhastrn (LGL * lgl, int a, int b, int c) {
14217   int blit, tag, other, other2;
14218   const int * w, * eow, * p;
14219   HTS * ha, * hb, * hc;
14220   ha = lglhts (lgl, a);
14221   hb = lglhts (lgl, b);
14222   if (hb->count < ha->count) { SWAP (int, a, b); SWAP (HTS *, ha, hb); }
14223   hc = lglhts (lgl, c);
14224   if (hc->count < ha->count) { SWAP (int, a, c); SWAP (HTS *, ha, hc); }
14225   w = lglhts2wchs (lgl, ha);
14226   eow = w + ha->count;
14227   for (p = w; p < eow; p++) {
14228     blit = *p;
14229     tag = blit & MASKCS;
14230     if (tag == OCCS) continue;
14231     if (tag == BINCS) {
14232       other = blit >> RMSHFT;
14233       if (other == b || other == c) return 1;
14234       continue;
14235     }
14236     if (tag == TRNCS || tag == LRGCS) p++;
14237     if (tag == LRGCS) continue;
14238     assert (tag == TRNCS);
14239     other = blit >> RMSHFT;
14240     if (other != b && other != c) continue;
14241     other2 = *p;
14242     if (other2 == b || other2 == c) return 1;
14243   }
14244   if (hc->count < hb->count) { SWAP (int, b, c); SWAP (HTS *, hb, hc); }
14245   w = lglhts2wchs (lgl, hb);
14246   eow = w + hb->count;
14247   for (p = w; p < eow; p++) {
14248     blit = *p;
14249     tag = blit & MASKCS;
14250     if (tag == OCCS) continue;
14251     if (tag == TRNCS || tag == LRGCS) { p++; continue; }
14252     assert (tag == BINCS);
14253     other = blit >> RMSHFT;
14254     if (other == c) return 1;
14255   }
14256   return 0;
14257 }
14258 
lglfactor(LGL * lgl,int lim,int count)14259 static int64_t lglfactor (LGL * lgl, int lim, int count) {
14260   int64_t factor, res;
14261   if (!count) return lim;
14262   switch (lgl->opts->factor.val) {
14263     default: factor = 1; break;
14264     case 1: factor = lglceild (count); break;
14265     case 2: factor = count; break;
14266     case 3: factor = count*(int64_t)count; break;
14267   }
14268   if (!factor) factor = 1;
14269   if (factor > lgl->opts->factmax.val) factor = lgl->opts->factmax.val;
14270   res = lim * factor;
14271   return res;
14272 }
14273 
lglforcedve(LGL * lgl,int idx)14274 static int lglforcedve (LGL * lgl, int idx) {
14275   int pocc = lglocc (lgl, idx);
14276   int nocc = lglocc (lgl, -idx);
14277   int count = lgl->stats->elm.count;
14278   if (!pocc) return 1;
14279   if (!nocc) return 1;
14280   if (pocc + nocc <= lgl->opts->elmoccsumforced.val) return 1;
14281   if (lgl->opts->elmfull.val) return 0;
14282   if (pocc >= lglfactor (lgl, lgl->opts->elmocclim1.val, count)) return -1;
14283   if (nocc >= lglfactor (lgl, lgl->opts->elmocclim1.val, count)) return -1;
14284   if (pocc < lglfactor (lgl, lgl->opts->elmocclim2.val, count)) return 0;
14285   if (nocc < lglfactor (lgl, lgl->opts->elmocclim2.val, count)) return 0;
14286   return -1;
14287 }
14288 
lgltrylargeve(LGL * lgl)14289 static int lgltrylargeve (LGL * lgl) {
14290   const int * c, * d, * sop, * eop, * son, * eon, * p, * q, * start, * end;
14291   int lit, idx, sgn, tmp, ip, ilit, npocc, nnocc, limit, count, i, res;
14292   int clen, dlen, reslen, maxreslen;
14293   ip = lgl->elm->pivot;
14294   assert (ip);
14295   if ((res = lglforcedve (lgl, ip))) return res > 0;
14296   sop = lgl->elm->lits.start + 1;
14297   eop = son = lgl->elm->lits.start + lgl->elm->neglidx;
14298   eon = lgl->elm->lits.top;
14299   npocc = lglpeek (&lgl->elm->noccs, lglulit (1));
14300   nnocc = lglpeek (&lgl->elm->noccs, lglulit (-1));
14301   limit = npocc + nnocc;
14302   count = 0;
14303   for (i = 0; i <= 1; i++) {
14304     start = i ? son : sop;
14305     end = i ? eon : eop;
14306     for (c = start; c < end; c++) {
14307       INCSTEPS (elm.steps);
14308       if (*c == REMOVED) { while (*c) c++; continue; }
14309       while ((lit = *c)) {
14310 	(void) lglm2i (lgl, lit);
14311 	c++;
14312       }
14313       count++;
14314     }
14315   }
14316   assert (count == limit);
14317   LOG (3, "trying clause distribution for %d with limit %d", ip, limit);
14318   maxreslen = 0;
14319   for (c = sop; c < eop && limit >= 0; c = p + 1) {
14320     INCSTEPS (elm.steps);
14321     if (*c == REMOVED) {
14322       for (p = c + 1; *p; p++)
14323         ;
14324       continue;
14325     }
14326     assert (lglmtstk (&lgl->resolvent));
14327     clen = 0;
14328     for (p = c; (lit = *p); p++) {
14329       if (lit == 1) continue;
14330       assert (lit != -1);
14331       idx = abs (lit);
14332       assert (!lglpeek (&lgl->elm->mark, idx));
14333       sgn = lglsgn (lit);
14334       lglpoke (&lgl->elm->mark, idx, sgn);
14335       ilit = lglm2i (lgl, lit);
14336       lglpushstk (lgl, &lgl->resolvent, ilit);
14337       clen++;
14338     }
14339     for (d = son; limit >= 0 && d < eon; d = q + 1) {
14340       INCSTEPS (elm.steps);
14341       if (*d == REMOVED) {
14342 	for (q = d + 1; *q; q++)
14343 	  ;
14344 	continue;
14345       }
14346       INCSTEPS (elm.resolutions);
14347       LOGMCLS (3, c, "trying resolution 1st antecedent");
14348       LOGMCLS (3, d, "trying resolution 2nd antecedent");
14349       dlen = 0;
14350       reslen = clen;
14351       for (q = d; (lit = *q); q++) {
14352 	if (lit == -1) continue;
14353 	dlen++;
14354 	assert (lit != 1);
14355 	idx = abs (lit), sgn = lglsgn (lit);
14356 	tmp = lglpeek (&lgl->elm->mark, idx);
14357 	if (tmp == -sgn) break;
14358 	if (tmp == sgn) continue;
14359 	ilit = lglm2i (lgl, lit);
14360 	lglpushstk (lgl, &lgl->resolvent, ilit);
14361 	reslen++;
14362       }
14363       assert (reslen == lglcntstk (&lgl->resolvent));
14364       if (!lit && reslen == 1) {
14365 	LOG (3, "trying resolution ends with unit clause");
14366 	lit = lglpeek (&lgl->resolvent, 0);
14367 	limit += lglevar (lgl, lit)->occ[lit < 0];
14368       } else if (lit) {
14369 	while (*++q) ;
14370 	LOG (3, "trying resolution ends with trivial resolvent");
14371       } else {
14372 	limit--;
14373 	LOG (3,
14374 	     "trying resolution with non trivial resolvent remaining %d",
14375 	     limit);
14376 	if (reslen > maxreslen) maxreslen = reslen;
14377       }
14378       assert (!*q);
14379       lglrststk (&lgl->resolvent, clen);
14380     }
14381     lglclnstk (&lgl->resolvent);
14382     for (p = c; (lit = *p); p++) {
14383       if (lit == 1) continue;
14384       assert (lit != -1);
14385       idx = abs (lit);
14386       assert (lglpeek (&lgl->elm->mark, idx) == lglsgn (lit));
14387       lglpoke (&lgl->elm->mark, idx, 0);
14388     }
14389     if (lgl->limits->elm.steps <= lgl->stats->elm.steps) {
14390       LOG (2, "maximum number of steps in elimination exhausted");
14391       return 0;
14392     }
14393   }
14394   assert (lglm2i (lgl, 1) == ip);
14395   if (limit < 0) {
14396     LOG (3, "resolving away %d would increase number of clauses", ip);
14397     return 0;
14398   }
14399   if (limit) LOG (2, "resolving away %d removes %d clauses", ip, limit);
14400   else LOG (2, "resolving away %d does not change number of clauses", ip);
14401   return 1;
14402 }
14403 
lgldolargeve(LGL * lgl)14404 static void lgldolargeve (LGL * lgl) {
14405   const int * c, * d, * sop, * eop, * son, * eon, * p, * q, * start, * end;
14406   int lit, idx, sgn, tmp, ip, ilit, mp, npocc, nnocc;
14407   int clen, dlen, reslen;
14408   Val val;
14409   ip = lgl->elm->pivot;
14410   assert (ip);
14411   sop = lgl->elm->lits.start + 1;
14412   eop = son = lgl->elm->lits.start + lgl->elm->neglidx;
14413   eon = lgl->elm->lits.top;
14414   npocc = lglpeek (&lgl->elm->noccs, lglulit (1));
14415   nnocc = lglpeek (&lgl->elm->noccs, lglulit (-1));
14416   LOG (2, "(large) variable elimination of %d", lgl->elm->pivot);
14417   if (npocc < nnocc) start = sop, end = eop, mp = 1;
14418   else start = son, end = eon, ip = -ip, mp = -1;
14419   LOG (3, "will save clauses with %d for extending assignment", ip);
14420   for (c = start; c < end; c = p + 1) {
14421     INCSTEPS (elm.steps);
14422     if (*c == REMOVED) {
14423       for (p = c + 1; *p; p++)
14424 	;
14425       continue;
14426     }
14427     lglepush (lgl, ip);
14428     for (p = c; (lit = *p); p++)  {
14429       if (lit == mp) continue;
14430       assert (lit != -mp);
14431       ilit = lglm2i (lgl, lit);
14432       lglepush (lgl, ilit);
14433     }
14434     lglepush (lgl, 0);
14435   }
14436   lglepush (lgl, -ip);
14437   lglepush (lgl, 0);
14438   for (c = sop; c < eop; c = p + 1) {
14439     INCSTEPS (elm.steps);
14440     if (*c == REMOVED) {
14441       for (p = c + 1; *p; p++)
14442 	;
14443       continue;
14444     }
14445     assert (lglmtstk (&lgl->resolvent));
14446     clen = 0;
14447     for (p = c; (lit = *p); p++) {
14448       if (lit == 1) continue;
14449       assert (lit != -1);
14450       idx = abs (lit);
14451       assert (!lglpeek (&lgl->elm->mark, idx));
14452       sgn = lglsgn (lit);
14453       lglpoke (&lgl->elm->mark, idx, sgn);
14454       ilit = lglm2i (lgl, lit);
14455       lglpushstk (lgl, &lgl->resolvent, ilit);
14456       clen++;
14457     }
14458     for (d = son; d < eon; d = q + 1) {
14459       INCSTEPS (elm.steps);
14460       if (*d == REMOVED) {
14461 	for (q = d + 1; *q; q++)
14462 	  ;
14463 	continue;
14464       }
14465       INCSTEPS (elm.resolutions);
14466       assert (lglmtstk (&lgl->clause));
14467       dlen = 0;
14468       reslen = clen;
14469       for (q = d; (lit = *q); q++) {
14470 	if (lit == -1) continue;
14471 	dlen++;
14472 	assert (lit != 1);
14473 	idx = abs (lit), sgn = lglsgn (lit);
14474 	tmp = lglpeek (&lgl->elm->mark, idx);
14475 	if (tmp == sgn) continue;
14476 	if (tmp == -sgn) break;
14477 	ilit = lglm2i (lgl, lit);
14478 	val = lglval (lgl, ilit);
14479 	if (val < 0) continue;
14480 	if (val > 0) break;
14481 	lglpushstk (lgl, &lgl->clause, ilit);
14482 	ilit = lglm2i (lgl, lit);
14483 	lglpushstk (lgl, &lgl->resolvent, ilit);
14484 	reslen++;
14485       }
14486       assert (reslen == lglcntstk (&lgl->resolvent));
14487       if (!lit && reslen == 1) {
14488 	goto RESOLVE;
14489       } if (lit) {
14490 	while (*++q) ;
14491       } else {
14492 RESOLVE:
14493 	LOGMCLS (3, c, "resolving variable elimination 1st antecedent");
14494 	LOGMCLS (3, d, "resolving variable elimination 2nd antecedent");
14495 	for (p = c; (lit = *p); p++) {
14496 	  if (lit == 1) continue;
14497 	  assert (lit != -1);
14498 	  ilit = lglm2i (lgl, lit);
14499 	  val = lglval (lgl, ilit);
14500 	  if (val < 0) continue;
14501 	  if (val > 0) break;
14502 	  lglpushstk (lgl, &lgl->clause, ilit);
14503 	}
14504 	if (!lit) {
14505 	  lglpushstk (lgl, &lgl->clause, 0);
14506 	  LOGCLS (3, lgl->clause.start, "variable elimination resolvent");
14507 	  lgldrupligaddcls (lgl, REDCS);
14508 	  lgladdcls (lgl, 0, 0, 1);
14509 	}
14510       }
14511       lglclnstk (&lgl->clause);
14512       assert (!*q);
14513       lglrststk (&lgl->resolvent, clen);
14514     }
14515     lglclnstk (&lgl->resolvent);
14516     for (p = c; (lit = *p); p++) {
14517       if (lit == 1) continue;
14518       assert (lit != -1);
14519       idx = abs (lit);
14520       assert (lglpeek (&lgl->elm->mark, idx) == lglsgn (lit));
14521       lglpoke (&lgl->elm->mark, idx, 0);
14522     }
14523   }
14524   lgleliminated (lgl, lgl->elm->pivot);
14525   lgl->stats->elm.large++;
14526 }
14527 
lglelimlitaux(LGL * lgl,int idx)14528 static void lglelimlitaux (LGL * lgl, int idx) {
14529   lglelmsub (lgl);
14530   if (lglelmstr (lgl)) return;
14531   lglelmfre (lgl);
14532   if (lgltrylargeve (lgl)) lgldolargeve (lgl);
14533 }
14534 
lgls2m(LGL * lgl,int ilit)14535 static int lgls2m (LGL * lgl, int ilit) {
14536   AVar * av = lglavar (lgl, ilit);
14537   int res = av->mark;
14538   if (!res) {
14539     res = lglcntstk (&lgl->seen) + 1;
14540     if (res > lgl->opts->smallvevars.val + 1) return 0;
14541     av->mark = res;
14542     assert (lglcntstk (&lgl->seen) == lglcntstk (&lgl->elm->m2i) - 1);
14543     lglpushstk (lgl, &lgl->seen, abs (ilit));
14544     lglpushstk (lgl, &lgl->elm->m2i, abs (ilit));
14545     LOG (4, "mapped internal variable %d to marked variable %d",
14546 	 abs (ilit), res);
14547   }
14548   if (ilit < 0) res = -res;
14549   return res;
14550 }
14551 
lglvar2funaux(int v,Fun res,int negate)14552 static void lglvar2funaux (int v, Fun res, int negate) {
14553   uint64_t tmp;
14554   int i, j, p;
14555   assert (0 <= v && v < FUNVAR);
14556   if (v < 6) {
14557     tmp = lglbasevar2funtab[v];
14558     if (negate) tmp = ~tmp;
14559     for (i = 0; i < FUNQUADS; i++)
14560       res[i] = tmp;
14561   } else {
14562     tmp = negate ? ~0ull : 0ull;
14563     p = 1 << (v - 6);
14564     j = 0;
14565     for (i = 0; i < FUNQUADS; i++) {
14566       res[i] = tmp;
14567       if (++j < p) continue;
14568       tmp = ~tmp;
14569       j = 0;
14570     }
14571   }
14572 }
14573 
lglvar2fun(int v,Fun res)14574 static void lglvar2fun (int v, Fun res) {
14575   lglvar2funaux (v, res, 0);
14576 }
14577 
lglnegvar2fun(int v,Fun res)14578 static void lglnegvar2fun (int v, Fun res) {
14579   lglvar2funaux (v, res, 1);
14580 }
14581 
lglfuncpy(Fun dst,const Fun src)14582 static void lglfuncpy (Fun dst, const Fun src) {
14583   int i;
14584   for (i = 0; i < FUNQUADS; i++)
14585     dst[i] = src[i];
14586 }
14587 
lglfalsefun(Fun res)14588 static void lglfalsefun (Fun res) {
14589   int i;
14590   for (i = 0; i < FUNQUADS; i++)
14591     res[i] = 0ll;
14592 }
14593 
lgltruefun(Fun res)14594 static void lgltruefun (Fun res) {
14595   int i;
14596   for (i = 0; i < FUNQUADS; i++)
14597     res[i] = ~0ll;
14598 }
14599 
lglisfalsefun(const Fun f)14600 static int lglisfalsefun (const Fun f) {
14601   int i;
14602   for (i = 0; i < FUNQUADS; i++)
14603     if (f[i] != 0ll) return 0;
14604   return 1;
14605 }
14606 
lglistruefun(const Fun f)14607 static int lglistruefun (const Fun f) {
14608   int i;
14609   for (i = 0; i < FUNQUADS; i++)
14610     if (f[i] != ~0ll) return 0;
14611   return 1;
14612 }
14613 
lglorfun(Fun a,const Fun b)14614 static void lglorfun (Fun a, const Fun b) {
14615   int i;
14616   for (i = 0; i < FUNQUADS; i++)
14617     a[i] |= b[i];
14618 }
14619 
lglornegfun(Fun a,const Fun b)14620 static void lglornegfun (Fun a, const Fun b) {
14621   int i;
14622   for (i = 0; i < FUNQUADS; i++)
14623     a[i] |= ~b[i];
14624 }
14625 
lglor3fun(Fun a,const Fun b,const Fun c)14626 static void lglor3fun (Fun a, const Fun b, const Fun c) {
14627   int i;
14628   for (i = 0; i < FUNQUADS; i++)
14629     a[i] = b[i] | c[i];
14630 }
14631 
lglor3negfun(Fun a,const Fun b,const Fun c)14632 static void lglor3negfun (Fun a, const Fun b, const Fun c) {
14633   int i;
14634   for (i = 0; i < FUNQUADS; i++)
14635     a[i] = b[i] | ~c[i];
14636 }
14637 
lglandornegfun(Fun a,const Fun b,const Fun c)14638 static void lglandornegfun (Fun a, const Fun b, const Fun c) {
14639   int i;
14640   for (i = 0; i < FUNQUADS; i++)
14641     a[i] &= b[i] | ~c[i];
14642 }
14643 
lglandfun(Fun a,const Fun b)14644 static void lglandfun (Fun a, const Fun b) {
14645   int i;
14646   for (i = 0; i < FUNQUADS; i++)
14647     a[i] &= b[i];
14648 }
14649 
lgland3fun(Fun a,const Fun b,const Fun c)14650 static void lgland3fun (Fun a, const Fun b, const Fun c) {
14651   int i;
14652   for (i = 0; i < FUNQUADS; i++)
14653     a[i] = b[i] & c[i];
14654 }
14655 
lgland3negfun(Fun a,const Fun b,const Fun c)14656 static void lgland3negfun (Fun a, const Fun b, const Fun c) {
14657   int i;
14658   for (i = 0; i < FUNQUADS; i++)
14659     a[i] = b[i] & ~c[i];
14660 }
14661 
lglsrfun(Fun a,int shift)14662 static void lglsrfun (Fun a, int shift) {
14663   uint64_t rest, tmp;
14664   int i, j, q, b, l;
14665   assert (0 <= shift);
14666   b = shift & 63;
14667   q = shift >> 6;
14668   j = 0;
14669   i = q;
14670   assert (i >= 0);
14671   l = 64 - b;
14672   while (j < FUNQUADS) {
14673     if (i < FUNQUADS) {
14674       tmp = a[i] >> b;
14675       rest = (b && i+1 < FUNQUADS) ? (a[i+1] << l) : 0ull;
14676       a[j] = rest | tmp;
14677     } else a[j] = 0ull;
14678     i++, j++;
14679   }
14680 }
14681 
lglslfun(Fun a,int shift)14682 static void lglslfun (Fun a, int shift) {
14683   uint64_t rest, tmp;
14684   int i, j, q, b, l;
14685   assert (0 <= shift);
14686   b = shift & 63;
14687   q = shift >> 6;
14688   j = FUNQUADS - 1;
14689   i = j - q;
14690   l = 64 - b;
14691   while (j >= 0) {
14692     if (i >= 0) {
14693       tmp = a[i] << b;
14694       rest = (b && i > 0) ? (a[i-1] >> l) : 0ll;
14695       a[j] = rest | tmp;
14696     } else a[j] = 0ll;
14697     i--, j--;
14698   }
14699 }
14700 
lgls2fun(int mlit,Fun res)14701 static void lgls2fun (int mlit, Fun res) {
14702   int midx = abs (mlit), sidx = midx - 2;
14703   assert (0 <= sidx && sidx < FUNVAR);
14704   if (mlit < 0) lglnegvar2fun (sidx, res);
14705   else lglvar2fun (sidx, res);
14706 }
14707 
lglinitsmallve(LGL * lgl,int lit,Fun res)14708 static int lglinitsmallve (LGL * lgl, int lit, Fun res) {
14709   int blit, tag, red, other, other2, lidx, mlit;
14710   const int * p, * w, * eow, * c, * q;
14711   Fun cls, tmp;
14712   HTS * hts;
14713   Val val;
14714   assert (!lglval (lgl, lit));
14715   LOG (3, "initializing small variable eliminiation for %d", lit);
14716 #ifndef NDEBUG
14717   mlit =
14718 #endif
14719   lgls2m (lgl, lit);
14720   assert (abs (mlit) == 1);
14721   hts = lglhts (lgl, lit);
14722   lgltruefun (res);
14723   if (!hts->count) goto DONE;
14724   w = lglhts2wchs (lgl, hts);
14725   eow = w + hts->count;
14726   for (p = w; p < eow; p++) {
14727     INCSTEPS (elm.steps);
14728     blit = *p;
14729     tag = blit & MASKCS;
14730     if (tag == TRNCS || tag == LRGCS) p++;
14731     if (tag == LRGCS) continue;
14732     red = blit & REDCS;
14733     if (red) continue;
14734     lglfalsefun (cls);
14735     if (tag == BINCS || tag == TRNCS) {
14736       other = blit >> RMSHFT;
14737       val = lglval (lgl, other);
14738       assert (val <= 0);
14739       if (!val) {
14740 	mlit = lgls2m (lgl, other);
14741 	if (!mlit) return 0;
14742 	lgls2fun (mlit, tmp);
14743 	lglorfun (cls, tmp);
14744       }
14745       if (tag == TRNCS) {
14746 	other2 = *p;
14747 	val = lglval (lgl, other2);
14748 	assert (val <= 0);
14749 	if (!val) {
14750 	  mlit = lgls2m (lgl, other2);
14751 	  if (!mlit) return 0;
14752 	  lgls2fun (mlit, tmp);
14753 	  lglorfun (cls, tmp);
14754 	}
14755       }
14756     } else {
14757       assert (tag == OCCS);
14758       lidx = blit >> RMSHFT;
14759       c = lglidx2lits (lgl, 0, lidx);
14760       for (q = c; (other = *q); q++) {
14761 	if (other == lit) continue;
14762 	assert (other != -lit);
14763 	val = lglval (lgl, other);
14764 	assert (val <= 0);
14765 	if (!val) {
14766 	  mlit = lgls2m (lgl, other);
14767 	  if (!mlit) return 0;
14768 	  lgls2fun (mlit, tmp);
14769 	  lglorfun (cls, tmp);
14770 	}
14771       }
14772     }
14773     assert (!lglisfalsefun (cls));
14774     assert (!lglistruefun (cls));
14775     lglandfun (res, cls);
14776     INCSTEPS (elm.copies);
14777   }
14778 DONE:
14779   return 1;
14780 }
14781 
lglresetsmallve(LGL * lgl)14782 static void lglresetsmallve (LGL * lgl) {
14783   lglclnstk (&lgl->elm->m2i);
14784   lglclnstk (&lgl->elm->clv);
14785   lglpopnunmarkstk (lgl, &lgl->seen);
14786 }
14787 
lglsmallevalcls(unsigned cls,Fun res)14788 static void lglsmallevalcls (unsigned cls, Fun res) {
14789   Fun tmp;
14790   int v;
14791   lglfalsefun (res);
14792   for (v = 0; v < FUNVAR; v++) {
14793     if (cls & (1 << (2*v + 1))) {
14794       lglvar2fun (v, tmp);
14795       lglornegfun (res, tmp);
14796     } else if (cls & (1 << (2*v))) {
14797       lglvar2fun (v, tmp);
14798       lglorfun (res, tmp);
14799     }
14800   }
14801 }
14802 
lglpos2cnf(int pos)14803 static Cnf lglpos2cnf (int pos) { assert (pos >=0 ); return pos; }
lglsize2cnf(int s)14804 static Cnf lglsize2cnf (int s) { assert (s >=0 ); return ((Cnf)s) << 32; }
lglcnf2pos(Cnf cnf)14805 static int lglcnf2pos (Cnf cnf) { return cnf & 0xfffffll; }
lglcnf2size(Cnf cnf)14806 static int lglcnf2size (Cnf cnf) { return cnf >> 32; }
14807 
lglcnf(int pos,int size)14808 static Cnf lglcnf (int pos, int size) {
14809   return lglpos2cnf (pos) | lglsize2cnf (size);
14810 }
14811 
lglsmallevalcnf(LGL * lgl,Cnf cnf,Fun res)14812 static void lglsmallevalcnf (LGL * lgl, Cnf cnf, Fun res) {
14813   Fun tmp;
14814   int i, n, p, cls;
14815   p = lglcnf2pos (cnf);
14816   n = lglcnf2size (cnf);
14817   lgltruefun (res);
14818   for (i = 0; i < n; i++) {
14819     cls = lglpeek (&lgl->elm->clv, p + i);
14820     lglsmallevalcls (cls, tmp);
14821     lglandfun (res, tmp);
14822   }
14823 }
14824 
lglnegcofactorfun(const Fun f,int v,Fun res)14825 static void lglnegcofactorfun (const Fun f, int v, Fun res) {
14826   Fun mask, masked;
14827   lglvar2fun (v, mask);
14828   lgland3negfun (masked, f, mask);
14829   lglfuncpy (res, masked);
14830   lglslfun (masked, (1 << v));
14831   lglorfun (res, masked);
14832 }
14833 
lglposcofactorfun(const Fun f,int v,Fun res)14834 static void lglposcofactorfun (const Fun f, int v, Fun res) {
14835   Fun mask, masked;
14836   lglvar2fun (v, mask);
14837   lgland3fun (masked, f, mask);
14838   lglfuncpy (res, masked);
14839   lglsrfun (masked, (1 << v));
14840   lglorfun (res, masked);
14841 }
14842 
lglsmallfundeps0(const Fun f)14843 static int lglsmallfundeps0 (const Fun f) {
14844   int i;
14845   for (i = 0; i < FUNQUADS; i++)
14846     if (((f[i] & 0xaaaaaaaaaaaaaaaaull)>>1) !=
14847          (f[i] & 0x5555555555555555ull)) return 1;
14848   return 0;
14849 }
14850 
lglsmallfundeps1(const Fun f)14851 static int lglsmallfundeps1 (const Fun f) {
14852   int i;
14853   for (i = 0; i < FUNQUADS; i++)
14854     if (((f[i] & 0xccccccccccccccccull)>>2) !=
14855          (f[i] & 0x3333333333333333ull)) return 1;
14856   return 0;
14857 }
14858 
lglsmallfundeps2(const Fun f)14859 static int lglsmallfundeps2 (const Fun f) {
14860   int i;
14861   for (i = 0; i < FUNQUADS; i++)
14862     if (((f[i] & 0xf0f0f0f0f0f0f0f0ull)>>4) !=
14863          (f[i] & 0x0f0f0f0f0f0f0f0full)) return 1;
14864   return 0;
14865 }
14866 
lglsmallfundeps3(const Fun f)14867 static int lglsmallfundeps3 (const Fun f) {
14868   int i;
14869   for (i = 0; i < FUNQUADS; i++)
14870     if (((f[i] & 0xff00ff00ff00ff00ull)>>8) !=
14871          (f[i] & 0x00ff00ff00ff00ffull)) return 1;
14872   return 0;
14873 }
14874 
lglsmallfundeps4(const Fun f)14875 static int lglsmallfundeps4 (const Fun f) {
14876   int i;
14877   for (i = 0; i < FUNQUADS; i++)
14878     if (((f[i] & 0xffff0000ffff0000ull)>>16) !=
14879          (f[i] & 0x0000ffff0000ffffull)) return 1;
14880   return 0;
14881 }
14882 
lglsmallfundeps5(const Fun f)14883 static int lglsmallfundeps5 (const Fun f) {
14884   int i;
14885   for (i = 0; i < FUNQUADS; i++)
14886     if (((f[i] & 0xffffffff00000000ull)>>32) !=
14887          (f[i] & 0x00000000ffffffffull)) return 1;
14888   return 0;
14889 }
14890 
lglsmallfundepsgen(const Fun f,int min)14891 static int lglsmallfundepsgen (const Fun f, int min) {
14892   const int c = (1 << (min - 6));
14893   int i, j;
14894   assert (min >= 6);
14895   for (i = 0; i < FUNQUADS; i += (1 << (min - 5)))
14896     for (j = 0; j < c; j++)
14897       if (f[i + j] != f[i + c + j]) return 1;
14898   return 0;
14899 }
14900 
lglsmalltopvar(const Fun f,int min)14901 static int lglsmalltopvar (const Fun f, int min) {
14902   int i;
14903   switch (min) {
14904     case 0: if (lglsmallfundeps0 (f)) return 0;
14905     case 1: if (lglsmallfundeps1 (f)) return 1;
14906     case 2: if (lglsmallfundeps2 (f)) return 2;
14907     case 3: if (lglsmallfundeps3 (f)) return 3;
14908     case 4: if (lglsmallfundeps4 (f)) return 4;
14909     case 5: if (lglsmallfundeps5 (f)) return 5;
14910   }
14911   for (i = lglmax (6, min); i <= FUNVAR - 2; i++)
14912     if (lglsmallfundepsgen (f, i)) return i;
14913   return i;
14914 }
14915 
lglsmalladdlit2cnf(LGL * lgl,Cnf cnf,int lit)14916 static Cnf lglsmalladdlit2cnf (LGL * lgl, Cnf cnf, int lit) {
14917   int p, m, q, n, i, cls;
14918   Cnf res;
14919   p = lglcnf2pos (cnf);
14920   m = lglcnf2size (cnf);
14921   q = lglcntstk (&lgl->elm->clv);
14922   for (i = 0; i < m; i++) {
14923     cls = lglpeek (&lgl->elm->clv, p + i);
14924     assert (!(cls & lit));
14925     cls |= lit;
14926     lglpushstk (lgl, &lgl->elm->clv, cls);
14927   }
14928   n = lglcntstk (&lgl->elm->clv) - q;
14929   res = lglcnf (q, n);
14930   return res;
14931 }
14932 
14933 #ifndef NDEBUG
lglefun(const Fun a,const Fun b)14934 static int lglefun (const Fun a, const Fun b) {
14935   int i;
14936   for (i = 0; i < FUNQUADS; i++)
14937     if (a[i] & ~b[i]) return 0;
14938   return 1;
14939 }
14940 #endif
14941 
14942 // The dual version of Minato's algorithm for computing an irredundant
14943 // product of sums.   The original algorithm computes an irredundant sum of
14944 // products. It uses BDDs for representing boolean functions and ZDDs for
14945 // manipulating sum of product.  We work with function tables stored as bit
14946 // maps and plain CNFs stored as lists of clauses instead.
14947 
lglsmallipos(LGL * lgl,const Fun U,const Fun L,int min)14948 static Cnf lglsmallipos (LGL * lgl, const Fun U, const Fun L, int min) {
14949   Fun U0, U1, L0, L1, Unew, ftmp;
14950   Cnf c0, c1, cstar, ctmp, res;
14951   int x, y, z;
14952   assert (lglefun (L, U));
14953   if (lglistruefun (U)) return TRUECNF;
14954   if (lglisfalsefun (L)) return FALSECNF;
14955   lgl->stats->elm.ipos++;
14956   assert (min < lglcntstk (&lgl->elm->m2i));
14957   y = lglsmalltopvar (U, min);
14958   z = lglsmalltopvar (L, min);
14959   INCSTEPS (elm.steps);
14960   x = (y < z) ? y : z;
14961   assert (x < FUNVAR);
14962   lglnegcofactorfun (U, x, U0); lglposcofactorfun (U, x, U1);
14963   lglnegcofactorfun (L, x, L0); lglposcofactorfun (L, x, L1);
14964   lglor3negfun (ftmp, U0, L1);
14965   c0 = lglsmallipos (lgl, ftmp, L0, min+1);
14966   lglor3negfun (ftmp, U1, L0);
14967   c1 = lglsmallipos (lgl, ftmp, L1, min+1);
14968   lglsmallevalcnf (lgl, c0, ftmp);
14969   lglor3negfun (Unew, U0, ftmp);
14970   lglsmallevalcnf (lgl, c1, ftmp);
14971   lglandornegfun (Unew, U1, ftmp);
14972   lglor3fun (ftmp, L0, L1);
14973   cstar = lglsmallipos (lgl, Unew, ftmp, min+1);
14974   assert (cstar != FALSECNF);
14975   ctmp = lglsmalladdlit2cnf (lgl, c1, (1 << (2*x + 1)));
14976   res = lglcnf2pos (ctmp);
14977   ctmp = lglsmalladdlit2cnf (lgl, c0, (1 << (2*x)));
14978   if (res == TRUECNF) res = lglcnf2pos (ctmp);
14979   ctmp = lglsmalladdlit2cnf (lgl, cstar, 0);
14980   if (res == TRUECNF) res = lglcnf2pos (ctmp);
14981   res |= lglsize2cnf (lglcntstk (&lgl->elm->clv) - res);
14982   return res;
14983 }
14984 
lglsmallve(LGL * lgl,Cnf cnf)14985 static void lglsmallve (LGL * lgl, Cnf cnf) {
14986   int * soc = lgl->elm->clv.start + lglcnf2pos (cnf);
14987   int * eoc = soc + lglcnf2size (cnf);
14988   int * p, cls, v, lit, trivial;
14989   Val val;
14990   for (p = soc; !lgl->mt && p < eoc; p++) {
14991     cls = *p;
14992     assert (lglmtstk (&lgl->clause));
14993     trivial = 0;
14994     for (v = 0; v < FUNVAR; v++) {
14995       if (cls & (1 << (2*v + 1))) lit = -lglm2i (lgl, v+2);
14996       else if (cls & (1 << (2*v))) lit = lglm2i (lgl, v+2);
14997       else continue;
14998       val = lglval (lgl, lit);
14999       if (val < 0) continue;
15000       if (val > 0) trivial = 1;
15001       lglpushstk (lgl, &lgl->clause, lit);
15002     }
15003     if (!trivial) {
15004       INCSTEPS (elm.resolutions);
15005       lglpushstk (lgl, &lgl->clause, 0);
15006       LOGCLS (3, lgl->clause.start, "small elimination resolvent");
15007       lgldrupligaddcls (lgl, REDCS);
15008       lgladdcls (lgl, 0, 0, 1);
15009     }
15010     lglclnstk (&lgl->clause);
15011   }
15012 }
15013 
lglsmallisunitcls(LGL * lgl,int cls)15014 static int lglsmallisunitcls (LGL * lgl, int cls) {
15015   int fidx, fsign, flit, mlit, ilit;
15016   ilit = 0;
15017   for (fidx = 0; fidx < FUNVAR; fidx++)
15018     for (fsign = 0; fsign <= 1; fsign++) {
15019       flit = 1<<(2*fidx + fsign);
15020       if (!(cls & flit)) continue;
15021       if (ilit) return 0;
15022       mlit = (fidx + 2) * (fsign ? -1 : 1);
15023       ilit = lglm2i (lgl, mlit);
15024     }
15025   return ilit;
15026 }
15027 
lglsmallcnfunits(LGL * lgl,Cnf cnf)15028 static int lglsmallcnfunits (LGL * lgl, Cnf cnf) {
15029   int p, m, i, res, cls, ilit;
15030   p = lglcnf2pos (cnf);
15031   m = lglcnf2size (cnf);
15032   res = 0;
15033   for (i = 0; i < m; i++) {
15034     cls = lglpeek (&lgl->elm->clv, p + i);
15035     ilit = lglsmallisunitcls (lgl, cls);
15036     if (!ilit) continue;
15037     assert (lglval (lgl, ilit) >= 0);
15038     lglunit (lgl, ilit);
15039     res++;
15040   }
15041   return res;
15042 }
15043 
lgltrysmallve(LGL * lgl,int idx)15044 static int lgltrysmallve (LGL * lgl, int idx) {
15045   int res, new, old, units;
15046   Fun pos, neg, fun;
15047   EVar * ev;
15048   Cnf cnf;
15049   assert (lglmtstk (&lgl->elm->m2i));
15050   assert (lglmtstk (&lgl->seen));
15051   assert (lglmtstk (&lgl->elm->clv));
15052   if (!lgl->opts->smallve.val) return 0;
15053   if (lgl->opts->smallvewait.val && !lgl->elmrtc) return 0;
15054   lglpushstk (lgl, &lgl->elm->m2i, 0);
15055   lglpushstk (lgl, &lgl->elm->clv, 0);
15056   res = 0;
15057   if (lglinitsmallve (lgl, idx, pos) && lglinitsmallve (lgl, -idx, neg)) {
15058     lglor3fun (fun, pos, neg);
15059     cnf = lglsmallipos (lgl, fun, fun, 0);
15060     new = lglcnf2size (cnf);
15061     units = lglsmallcnfunits (lgl, cnf);
15062     assert (units <= new);
15063     new -= units;
15064     ev = lglevar (lgl, idx);
15065     old = ev->occ[0] + ev->occ[1];
15066     LOG (2,
15067 "small elimination of %d replaces %d old with %d new clauses and %d units",
15068       idx, old, new, units);
15069     lgl->stats->elm.small.tried++;
15070     if (new > old) {
15071       if (units > 0) {
15072 	LOG (2,
15073 "unforced small elimination of %d would add %d clauses but produces %d units",
15074 	  idx, new - old, units);
15075         res = 1;
15076       } else {
15077 	LOG (2,
15078 "unforced small elimination of %d would add %d clauses considered failed",
15079 	  idx, new - old);
15080         lgl->stats->elm.small.failed++;
15081       }
15082     } else {
15083       LOG (2,
15084 "small elimination of %d removes %d clauses thus considered promising",
15085 	idx, old - new);
15086       lglepusheliminated (lgl, idx);
15087       lglflushclauses (lgl, idx);
15088       lglflushclauses (lgl, -idx);
15089       lglsmallve (lgl, cnf);
15090       lgl->stats->elm.small.elm++;
15091       res = 1;
15092     }
15093   } else LOG (2, "too many variables for small elimination");
15094   lglresetsmallve (lgl);
15095   return res;
15096 }
15097 
lgl2manyoccs4elm(LGL * lgl,int lit)15098 static int lgl2manyoccs4elm (LGL * lgl, int lit) {
15099   return lglocc (lgl, lit) >
15100            lglfactor (lgl, lgl->opts->elmocclim.val, lgl->stats->elm.count);
15101 }
15102 
lglchkoccs4elmlit(LGL * lgl,int lit)15103 static int lglchkoccs4elmlit (LGL * lgl, int lit) {
15104   int blit, tag, red, other, other2, lidx, size, lits, count;
15105   const int * p, * w, * eow, * c, * l;
15106   int64_t litslim;
15107   HTS * hts;
15108   if (lgl->opts->elmfull.val) return 1;
15109   count = lgl->stats->elm.count;
15110   litslim = lglfactor (lgl, lgl->opts->elmlitslim.val, count);
15111   hts = lglhts (lgl, lit);
15112   w = lglhts2wchs (lgl, hts);
15113   eow = w + hts->count;
15114   lits = 0;
15115   for (p = w; p < eow; p++) {
15116     blit = *p;
15117     tag = blit & MASKCS;
15118     red = blit & REDCS;
15119     if (tag == TRNCS || tag == LRGCS) p++;
15120     if (red || tag == LRGCS) continue;
15121     if (tag == BINCS) {
15122       other = blit >> RMSHFT;
15123       if (lgl2manyoccs4elm (lgl, other)) return 0;
15124       lits += 2;
15125     } else if (tag == TRNCS) {
15126       other = blit >> RMSHFT;
15127       if (lgl2manyoccs4elm (lgl, other)) return 0;
15128       other2 = *p;
15129       if (lgl2manyoccs4elm (lgl, other2)) return 0;
15130       lits += 3;
15131     } else {
15132       assert (tag == OCCS);
15133       lidx = blit >> RMSHFT;
15134       c = lglidx2lits (lgl, 0, lidx);
15135       size = 0;
15136       for (l = c; (other = *l); l++) {
15137         if (lgl2manyoccs4elm (lgl, other)) return 0;
15138         if (++size > lglfactor (lgl, lgl->opts->elmclslim.val, count))
15139 	  return 0;
15140       }
15141       lits += size;
15142     }
15143     if (lits > litslim) return 0;
15144   }
15145   return 1;
15146 }
15147 
lglchkoccs4elm(LGL * lgl,int idx)15148 static int lglchkoccs4elm (LGL * lgl, int idx) {
15149   int res;
15150   if ((res = lglforcedve (lgl, idx)) > 0) return 1;
15151   if (res < 0) return 0;
15152   if (lgl2manyoccs4elm (lgl, idx)) return 0;
15153   if (lgl2manyoccs4elm (lgl, -idx)) return 0;
15154   if (!lglchkoccs4elmlit (lgl, idx)) return 0;
15155   if (!lglchkoccs4elmlit (lgl, -idx)) return 0;
15156   return 1;
15157 }
15158 
lglispure(LGL * lgl,int lit)15159 static int lglispure (LGL * lgl, int lit) {
15160   if (!lgl->opts->pure.val) return 0;
15161   if (lglifrozen (lgl, lit)) return 0;
15162   return !lglocc (lgl, -lit);
15163 }
15164 
lglpurelit(LGL * lgl,int lit)15165 static int lglpurelit (LGL * lgl, int lit) {
15166   int res;
15167   LOG(1, "pure literal %d", lit);
15168   assert (!lglocc (lgl, -lit));
15169   res = lglflushclauses (lgl, lit);
15170   assert (lgl->blocking || lgl->eliminating);
15171   if (lgl->blocking) {
15172     lgl->stats->blk.pure++;
15173     lgl->stats->blk.clauses += res;
15174     ADDSTEPS (blk.steps, res);
15175   }
15176   if (lgl->eliminating) {
15177     lgl->stats->elm.pure++;
15178     ADDSTEPS (elm.steps, res);
15179   }
15180   lglepusheliminated (lgl, lit);
15181   return res;
15182 }
15183 
lglelimlit(LGL * lgl,int idx)15184 static void lglelimlit (LGL * lgl, int idx) {
15185   int forced;
15186   if (!lglisfree (lgl, idx)) return;
15187   if (lglispure (lgl, idx)) { (void) lglpurelit (lgl, idx); return; }
15188   if (lglispure (lgl, -idx)) { (void) lglpurelit (lgl, -idx); return; }
15189   if (!lglchkoccs4elm (lgl, idx)) return;
15190   LOG (2, "trying to eliminate %d", idx);
15191   if ((forced = lglforcedve (lgl, idx)) < 0) return;
15192   if (!forced && lgltrysmallve (lgl, idx)) return;
15193   lglinitecls (lgl, idx);
15194   lglelimlitaux (lgl, idx);
15195   if (lgl->elm->pivot) lglrstecls (lgl);
15196 }
15197 
lglblockcls(LGL * lgl,int lit)15198 static int lglblockcls (LGL * lgl, int lit) {
15199   int blit, tag, red, other, other2, lidx, val, count, size;
15200   const int * p, * w, * eow, * c, *l;
15201   int bc = lgl->stats->blk.count;
15202   HTS * hts;
15203   INCSTEPS (blk.steps);
15204   hts = lglhts (lgl, lit);
15205   if (!hts->count) return 1;
15206   w = lglhts2wchs (lgl, hts);
15207   eow = w + hts->count;
15208   count = 0;
15209   for (p = w; p < eow; p++) {
15210     blit = *p;
15211     tag = blit & MASKCS;
15212     if (tag == TRNCS || tag == LRGCS) p++;
15213     if (tag == LRGCS) continue;
15214     red = blit & REDCS;
15215     if (red) continue;
15216     count++;
15217     lgl->stats->blk.res++;
15218     INCSTEPS (blk.steps);
15219     if (tag == BINCS || tag == TRNCS) {
15220       other = blit >> RMSHFT;
15221       val = lglmarked (lgl, other);
15222       if (val < 0) continue;
15223       if (tag == TRNCS) {
15224 	other2 = *p;
15225 	val = lglmarked (lgl, other2);
15226 	if (val < 0) continue;
15227       }
15228     } else {
15229       assert (tag == OCCS);
15230       lidx = blit >> RMSHFT;
15231       c = lglidx2lits (lgl, 0, lidx);
15232       size = 0;
15233       for (l = c; (other = *l); l++) {
15234 	val = lglmarked (lgl, other);
15235 	if (++size > lglfactor (lgl, lgl->opts->blkclslim.val, bc)) return 0;
15236 	if (val < 0) break;
15237       }
15238       if (other) continue;
15239     }
15240     return 0;
15241   }
15242   LOG (3, "resolved %d trivial resolvents on %d", count, lit);
15243   return 1;
15244 }
15245 
lgl2manyoccs4blk(LGL * lgl,int lit)15246 static int lgl2manyoccs4blk (LGL * lgl, int lit) {
15247   return lglhts (lgl, lit)->count >
15248            lglfactor (lgl, lgl->opts->blkocclim.val, lgl->stats->blk.count);
15249 }
15250 
lgldonotblocklit(LGL * lgl,int lit)15251 static int lgldonotblocklit (LGL * lgl, int lit) {
15252   int pocc = lglocc (lgl, lit);
15253   int nocc = lglocc (lgl, -lit);
15254   int count = lgl->stats->blk.count;
15255   if (pocc >= lglfactor (lgl, lgl->opts->blkocclim1.val, count)) return 1;
15256   if (nocc >= lglfactor (lgl, lgl->opts->blkocclim1.val, count)) return 1;
15257   if (pocc < lglfactor (lgl, lgl->opts->blkocclim2.val, count)) return 0;
15258   if (nocc < lglfactor (lgl, lgl->opts->blkocclim2.val, count)) return 0;
15259   return 1;
15260 }
15261 
lglblocklit(LGL * lgl,int lit,Stk * stk)15262 static int lglblocklit (LGL * lgl, int lit, Stk * stk) {
15263   int blit, tag, red, blocked, other, other2, lidx, count, size;
15264   int bc = lgl->stats->blk.count;
15265   int * p, * w, * eow, * c, * l;
15266   HTS * hts;
15267   if (lglval (lgl, lit)) return 0;
15268   if (lgldonotblocklit (lgl, lit)) return 0;
15269   if (lgl2manyoccs4blk (lgl, lit)) return 0;
15270   hts = lglhts (lgl, lit);
15271   assert (!lgl->opts->pure.val || hts->count > 0);
15272   w = lglhts2wchs (lgl, hts);
15273   eow = w + hts->count;
15274   count = 0;
15275   assert (lglmtstk (stk+2) && lglmtstk (stk+3) && lglmtstk (stk+4));
15276   for (p = w; p < eow; p++) {
15277     if (INCSTEPS (blk.steps) >= lgl->limits->blk.steps) break;
15278     if (lglterminate (lgl)) break;
15279     blit = *p;
15280     tag = blit & MASKCS;
15281     if (tag == TRNCS || tag == LRGCS) p++;
15282     if (tag == LRGCS) continue;
15283     red = blit & REDCS;
15284     if (red) continue;
15285     assert (lglmtstk (&lgl->seen));
15286     blocked = 0;
15287     if (tag == BINCS || tag == TRNCS) {
15288       if (!lgl->opts->blksmall.val) continue;
15289       other = blit >> RMSHFT;
15290       if (lgl2manyoccs4blk (lgl, other)) continue;
15291       lglpushnmarkseen (lgl, other);
15292       if (tag == TRNCS) {
15293 	other2 = *p;
15294         if (lgl2manyoccs4blk (lgl, other2)) goto CONTINUE;
15295 	lglpushnmarkseen (lgl, other2);
15296       }
15297     } else {
15298       assert (tag == OCCS);
15299       if (!lgl->opts->blklarge.val) continue;
15300       lidx = blit >> RMSHFT;
15301       c = lglidx2lits (lgl, 0, lidx);
15302       size = 0;
15303       for (l = c; (other = *l); l++) {
15304 	if (other == lit) continue;
15305         if (lgl2manyoccs4blk (lgl, other)) goto CONTINUE;
15306 	if (++size > lglfactor (lgl, lgl->opts->blkclslim.val, bc))
15307 	  goto CONTINUE;
15308 	lglpushnmarkseen (lgl, other);
15309       }
15310     }
15311     blocked = lglblockcls (lgl, -lit);
15312 CONTINUE:
15313     lglpopnunmarkstk (lgl, &lgl->seen);
15314     if (!blocked) continue;
15315     if (tag == BINCS) {
15316       other = blit >> RMSHFT;
15317       lglpushstk (lgl, stk+2, other);
15318     } else if (tag == TRNCS) {
15319       other = blit >> RMSHFT;
15320       lglpushstk (lgl, stk+3, other);
15321       other2 = *p;
15322       lglpushstk (lgl, stk+3, other2);
15323     } else {
15324       assert (tag == OCCS);
15325       lidx = blit >> RMSHFT;
15326       lglpushstk (lgl, stk+4, lidx);
15327     }
15328   }
15329   while (!lglmtstk (stk+2)) {
15330     if (INCSTEPS (blk.steps) >= lgl->limits->blk.steps) break;
15331     count++;
15332     other = lglpopstk (stk+2);
15333     LOG (2, "blocked binary clause %d %d on %d", lit, other, lit);
15334     lglrmbcls (lgl, lit, other, 0);
15335     lglepush (lgl, lit);
15336     lglepush (lgl, other);
15337     lglepush (lgl, 0);
15338     if (!lglmvbcls (lgl, lit, other))
15339       lgldrupligdelclsarg (lgl, lit, other, 0);
15340   }
15341   while (!lglmtstk (stk+3)) {
15342     if (INCSTEPS (blk.steps) >= lgl->limits->blk.steps) break;
15343     count++;
15344     other2 = lglpopstk (stk+3);
15345     other = lglpopstk (stk+3);
15346     LOG (2, "blocked ternary clause %d %d %d on %d", lit, other, other2, lit);
15347     lglrmtcls (lgl, lit, other, other2, 0);
15348     lglepush (lgl, lit);
15349     lglepush (lgl, other);
15350     lglepush (lgl, other2);
15351     lglepush (lgl, 0);
15352     if (!lglmvtcls (lgl, lit, other, other2))
15353       lgldrupligdelclsarg (lgl, lit, other, other2, 0);
15354   }
15355   while (!lglmtstk (stk+4)) {
15356     if (INCSTEPS (blk.steps) >= lgl->limits->blk.steps) break;
15357     lidx = lglpopstk (stk+4);
15358     count++;
15359     c = lglidx2lits (lgl, 0, lidx);
15360     LOGCLS (2, c, "blocked on %d large clause", lit);
15361     lgldrupligdelclsaux (lgl, c);
15362     lglepush (lgl, lit);
15363     for (l = c; (other = *l); l++)
15364       if (other != lit) lglepush (lgl, other);
15365     lglepush (lgl, 0);
15366     lglrmlcls (lgl, lidx, 0);
15367   }
15368   LOG (2, "found %d blocked clauses with %d", count, lit);
15369   lgl->stats->blk.clauses += count;
15370   if (count > 0) lglblockinglit (lgl, lit);
15371   lglclnstk (stk+2), lglclnstk (stk+3), lglclnstk (stk+4);
15372   return count;
15373 }
15374 
lglsetblklim(LGL * lgl)15375 static void lglsetblklim (LGL * lgl) {
15376   int64_t limit, irrlim;
15377   int pen, szpen;
15378   if (lgl->opts->blkrtc.val) {
15379     lgl->limits->blk.steps = LLMAX;
15380     lglprt (lgl, 1,
15381       "[block-%d] really no limit (run to completion)",
15382       lgl->stats->blk.count);
15383   } else {
15384     limit = (lgl->opts->blkreleff.val*lglvisearch (lgl))/1000;
15385     if (limit < lgl->opts->blkmineff.val) limit = lgl->opts->blkmineff.val;
15386     if (lgl->opts->blkmaxeff.val >= 0 && limit > lgl->opts->blkmaxeff.val)
15387       limit = lgl->opts->blkmaxeff.val;
15388     if (lgl->stats->blk.count <= 1 &&
15389         lgl->opts->boost.val &&
15390 	lglrem (lgl) < lgl->opts->blkboostvlim.val) {
15391       lglprt (lgl, 1,
15392         "[block-%d] boosting limit by %d",
15393 	lgl->stats->blk.count, lgl->opts->blkboost.val);
15394       limit *= lgl->opts->blkboost.val;
15395     }
15396     limit >>= (pen = lgl->limits->blk.pen + (szpen = lglszpen (lgl)));
15397     irrlim = (lgl->stats->irr.clauses.cur/2) >> szpen;
15398     if (lgl->opts->irrlim.val && limit < irrlim) {
15399       limit = irrlim;
15400       lglprt (lgl, 1,
15401   "[block-%d] limit of %lld steps based on %d irredundant clauses penalty %d",
15402 	lgl->stats->blk.count,
15403 	(LGLL) limit, lgl->stats->irr.clauses.cur, szpen);
15404     } else
15405       lglprt (lgl, 1,
15406 	"[block-%d] limit of %lld steps penalty %d = %d + %d",
15407 	lgl->stats->blk.count, (LGLL) limit,
15408 	pen, lgl->limits->blk.pen, szpen);
15409     lgl->limits->blk.steps = lgl->stats->blk.steps + limit;
15410   }
15411 }
15412 
lgleschedrem(LGL * lgl,int this_time)15413 static int lgleschedrem (LGL * lgl, int this_time) {
15414   int idx, res = 0, count;
15415   const char * str;
15416   AVar * av;
15417   for (idx = 2; idx < lgl->nvars; idx++) {
15418     if (lglifrozen (lgl, idx)) continue;
15419     if (!lglisfree (lgl, idx)) continue;
15420     av = lglavar (lgl, idx);
15421     if (lgl->eliminating && av->donotelm) continue;
15422     if (lgl->blocking && av->donotblk) continue;
15423     res++;
15424   }
15425   assert (lgl->eliminating || lgl->blocking);
15426   if (lgl->eliminating) count = lgl->stats->elm.count, str = "elim";
15427   else assert (lgl->blocking), count = lgl->stats->blk.count, str = "block";
15428   if (res)
15429     lglprt (lgl, 1,
15430       "[%s-%d] %d variables %.0f%% %s time",
15431       str, count,
15432       res, lglpcnt (res, lglrem (lgl)),
15433       this_time ? "will be scheduled this" : "remain to be tried next");
15434   else {
15435     lglprt (lgl, 1,
15436       "[%s-%d] no untried remaining variables left",
15437       str, count);
15438     for (idx = 2; idx < lgl->nvars; idx++) {
15439       av = lglavar (lgl, idx);
15440       if (lgl->eliminating) av->donotelm = 0;
15441       if (lgl->blocking) av->donotblk = 0;
15442     }
15443   }
15444   return res;
15445 }
15446 
lglsetdonotesched(LGL * lgl,int completed)15447 static void lglsetdonotesched (LGL * lgl, int completed) {
15448   AVar * av;
15449   EVar * ev;
15450   int idx;
15451   assert (lgl->eliminating + lgl->blocking == 1);
15452   for (idx = 2; idx < lgl->nvars; idx++) {
15453     av = lglavar (lgl, idx);
15454     ev = lglevar (lgl, idx);
15455     if (lgl->eliminating) {
15456       if (completed) av->donotelm = 0;
15457       else if (ev->pos < 0) av->donotelm = 1;
15458     }
15459     if (lgl->blocking) {
15460       if (completed) av->donotblk = 0;
15461       else if (ev->pos < 0) av->donotblk = 1;
15462     }
15463   }
15464 }
15465 
lglblkdone(LGL * lgl)15466 static int lglblkdone (LGL * lgl) {
15467   if (!lglsmallirr (lgl)) return 1;
15468   if (lglterminate (lgl)) return 1;
15469   if (lglmtstk (&lgl->esched)) return 1;
15470   if (lgl->stats->blk.steps >= lgl->limits->blk.steps) return 1;
15471   return 0;
15472 }
15473 
lglblock(LGL * lgl)15474 static void lglblock (LGL * lgl) {
15475   int oldrem = lgl->blkrem, oldall = lgl->blkall;
15476   int oldirr = lgl->stats->irr.clauses.cur;
15477   int idx, count, all, rem, success;
15478   Stk blocked[5];
15479   assert (lglsmallirr (lgl));
15480   assert (!lgl->simp);
15481   assert (!lgl->dense);
15482   assert (!lgl->eliminating);
15483   assert (!lgl->blocking);
15484   assert (!lgl->occs);
15485   lglstart (lgl, &lgl->times->block);
15486   if (lgl->level) lglbacktrack (lgl, 0);
15487   lgl->simp = lgl->blocking = lgl->occs = 1;
15488   lgl->stats->blk.count++;
15489   lglgc (lgl);
15490   assert (lgl->frozen);
15491   assert (!(oldall && !oldrem));
15492   all = !oldrem || !oldall;
15493   if (all)
15494     lglprt (lgl, 1,
15495       "[block-%d] scheduling all variables this time",
15496       lgl->stats->blk.count);
15497   else if (!lgleschedrem (lgl, 1)) all = 1, oldrem = 0;
15498   if (!all) assert (!lgl->donotsched), lgl->donotsched = 1;
15499   lgldense (lgl, 1);
15500   if (!all) assert (lgl->donotsched), lgl->donotsched = 0;
15501   lglsetblklim (lgl);
15502   CLR (blocked);
15503   count = 0;
15504   if (!lgl->opts->blkresched.val)
15505     assert (!lgl->donotsched), lgl->donotsched = 1;
15506   while (!lglblkdone (lgl)) {
15507     idx = lglpopesched (lgl);
15508     lglavar (lgl, idx)->donotblk = 1;
15509     if (!lglisfree (lgl, idx)) continue;
15510     if (lglispure (lgl, -idx)) count += lglpurelit (lgl, -idx);
15511     else if (lglispure (lgl, idx)) count += lglpurelit (lgl, idx);
15512     else {
15513       if (lglocc (lgl, -idx) > lglocc (lgl, idx)) idx = -idx;
15514       count += lglblocklit (lgl, idx, blocked);
15515       count += lglblocklit (lgl, -idx, blocked);
15516     }
15517   }
15518   if (!lgl->opts->blkresched.val)
15519     assert (lgl->donotsched), lgl->donotsched = 0;
15520   rem = lglcntstk (&lgl->esched);
15521   if (!rem) {
15522     lglprt (lgl, 1,
15523       "[block-%d] fully completed",
15524       lgl->stats->blk.count);
15525     lgl->blkrtc = 1;
15526   } else {
15527     lglprt (lgl, 1,
15528       "[block-%d] incomplete %d not tried %.0f%%",
15529       lgl->stats->blk.count, rem, lglpcnt (rem, lgl->nvars - 2));
15530   }
15531   lglsetdonotesched (lgl, !rem);
15532   lglrelstk (lgl, &lgl->esched);
15533   lglsparse (lgl);
15534   lglgc (lgl);
15535   lglrelstk (lgl, blocked+2);
15536   lglrelstk (lgl, blocked+3);
15537   lglrelstk (lgl, blocked+4);
15538   lgl->blkrem = rem > 0;
15539   lgl->blkall = all && lgl->blkrem;
15540   lglprt (lgl, 1,
15541     "[block-%d] transition to [ all %d rem %d ] state",
15542     lgl->stats->blk.count, lgl->blkall, lgl->blkrem);
15543   assert (lgl->simp && lgl->blocking && lgl->occs);
15544   lgl->blocking = lgl->simp = lgl->occs = 0;
15545   lgl->stats->irrprgss += count;
15546   lglprt (lgl, 1,
15547     "[block-%d] eliminated %d blocked clauses",
15548     lgl->stats->blk.count, count);
15549   if (!lgl->blkrtc &&
15550       lgl->stats->blk.count <= lgl->opts->blksuccessmaxwortc.val) {
15551     success = 1;
15552     lglprt (lgl, 1,
15553       "[block-%d] considered successful since not run to completion yet",
15554       lgl->stats->blk.count);
15555   } else if (count) {
15556     success = (oldirr/lgl->opts->blksuccessrat.val <= count);
15557     if (!success)
15558       lglprt (lgl, 1,
15559 	"[block-%d] %d < 1/%d * %d = %d considered unsuccessful",
15560 	lgl->stats->blk.count, count, lgl->opts->blksuccessrat.val,
15561 	oldirr, oldirr/lgl->opts->blksuccessrat.val);
15562   } else success = 0;
15563   LGLUPDPEN (blk, success);
15564   lglrep (lgl, 2, 'k');
15565   lglstop (lgl);
15566   assert (!lgl->mt);
15567 }
15568 
lglsetccelim(LGL * lgl)15569 static void lglsetccelim (LGL * lgl) {
15570   int count = lgl->stats->cce.count - lgl->opts->cceboostdel.val;
15571   int64_t limit, irrlim;
15572   int pen, szpen;
15573   if (lgl->opts->ccertc.val > 1) {
15574     lgl->limits->cce.steps = LLMAX;
15575     lglprt (lgl, 1,
15576       "[cce-%d] really no limit (run to completion)",
15577       lgl->stats->cce.count);
15578   } else if (lgl->opts->ccertc.val ||
15579       (count > 0 &&
15580        lglrem (lgl) < lgl->opts->ccertcintvlim.val &&
15581        !(count % lgl->opts->ccertcint.val))) {
15582     limit = 4000000000ll;
15583     lgl->limits->cce.steps = lgl->stats->cce.steps + limit;
15584     lglprt (lgl, 1,
15585        "[cce-%d] almost no limit of %lld steps",
15586        lgl->stats->cce.count, (LGLL) limit);
15587   } else {
15588     limit = (lgl->opts->ccereleff.val*lglvisearch (lgl))/1000;
15589     if (limit < lgl->opts->ccemineff.val) limit = lgl->opts->ccemineff.val;
15590     if (lgl->opts->ccemaxeff.val >= 0 && limit > lgl->opts->ccemaxeff.val)
15591       limit = lgl->opts->ccemaxeff.val;
15592     if (count > 0 &&
15593         (count <= 1 || !(count % lgl->opts->cceboostint.val)) &&
15594         lgl->opts->boost.val &&
15595 	lgl->nvars < lgl->opts->cceboostvlim.val) {
15596       lglprt (lgl, 1,
15597         "[cce-%d] boosting limit by %d",
15598 	lgl->stats->cce.count, lgl->opts->cceboost.val);
15599       limit *= lgl->opts->cceboost.val;
15600     }
15601     limit >>= (pen = lgl->limits->cce.pen + (szpen = lglszpen (lgl)));
15602     irrlim = (lgl->stats->irr.clauses.cur) >> szpen;
15603     if (lgl->opts->irrlim.val && limit < irrlim) {
15604       limit = irrlim;
15605       lglprt (lgl, 1,
15606   "[cce-%d] limit of %lld steps based on %d irredundant clauses penalty %d",
15607 	lgl->stats->cce.count,
15608 	(LGLL) limit, lgl->stats->irr.clauses.cur, szpen );
15609     } else
15610       lglprt (lgl, 1,
15611 	"[cce-%d] limit of %lld steps penalty %d = %d + %d",
15612 	lgl->stats->cce.count, (LGLL) limit,
15613 	pen, lgl->limits->cce.pen, szpen);
15614     lgl->limits->cce.steps = lgl->stats->cce.steps + limit;
15615   }
15616 }
15617 
15618 #define CCELOGLEVEL 2
15619 
lglsignedmark2(LGL * lgl,int lit)15620 static void lglsignedmark2 (LGL * lgl, int lit) {
15621   AVar * av = lglavar (lgl, lit);
15622   int bit = 1 << (2 + (lit < 0));
15623   if (av->mark & bit) return;
15624   av->mark |= bit;
15625 }
15626 
lglsignedunmark2(LGL * lgl,int lit)15627 static void lglsignedunmark2 (LGL * lgl, int lit) {
15628   AVar * av = lglavar (lgl, lit);
15629   int bit = 1 << (2 + (lit < 0));
15630   if (!(av->mark & bit)) return;
15631   av->mark &= ~bit;
15632 }
15633 
lglsignedmarked2(LGL * lgl,int lit)15634 static int lglsignedmarked2 (LGL * lgl, int lit) {
15635   AVar * av = lglavar (lgl, lit);
15636   int bit = 1 << (2 + (lit < 0));
15637   return av->mark & bit;
15638 }
15639 
lglabcecls(LGL * lgl,int lit,const int * c)15640 static int lglabcecls (LGL * lgl, int lit, const int * c) {
15641   int other, found = 0;
15642   const int * p;
15643   for (p = c; (other = *p); p++)
15644     if (other == -lit) found++;
15645     else if (lglsignedmarked (lgl, -other)) return 1;
15646   assert (found == 1);
15647   return 0;
15648 }
15649 
lglabce(LGL * lgl,int lit)15650 static int lglabce (LGL * lgl, int lit) {
15651   const int * p, * w, * eow, * c;
15652   int blit, tag, other, cls[4];
15653   HTS * hts;
15654   assert (!lglifrozen (lgl, lit));
15655   hts = lglhts (lgl, -lit);
15656   w = lglhts2wchs (lgl, hts);
15657   eow = w + hts->count;
15658   cls[0] = -lit, cls[3] = 0;
15659   for (p = w; p < eow; p++) {
15660     if (lgl->limits->cce.steps <= INCSTEPS (cce.steps)) return 0;
15661     blit = *p;
15662     tag = blit & MASKCS;
15663     if (tag == TRNCS || tag == LRGCS) p++;
15664     if (blit & REDCS) continue;
15665     if (tag == LRGCS) continue;
15666     other = blit >> RMSHFT;
15667     cls[1] = other;
15668     if (tag == BINCS) cls[2] = 0, c = cls;
15669     else if (tag == TRNCS) cls[2] = *p, c = cls;
15670     else assert (tag == OCCS), c = lglidx2lits (lgl, 0, other);
15671     if (!lglabcecls (lgl, lit, c)) return 0;
15672   }
15673   return 1;
15674 }
15675 
lglcceclause(LGL * lgl,const int * c,int igntag,int cce)15676 static int lglcceclause (LGL * lgl,
15677                          const int * c,
15678 			 int igntag,
15679 			 int cce) {
15680   int other, res, nextala, nextcla, lit, blit, tag, other2, i, j, n;
15681   int ala, first, old, prev, steps, lidx;
15682   int * newtop, * d, * q, * r;
15683   const int * p, * eow, * w;
15684   long delta;
15685   HTS * hts;
15686   LOGCLS (CCELOGLEVEL, c, "trying CCE on clause");
15687   assert (lglmtstk (&lgl->cce->extend));
15688   assert (lglmtstk (&lgl->cce->cla));
15689   assert (lglmtstk (&lgl->seen));
15690   for (p = c; (other = *p); p++) {
15691     assert (!lglmarked (lgl, other));
15692     lglpushstk (lgl, &lgl->seen, other);
15693     lglpushstk (lgl, &lgl->cce->cla, other);
15694     lglsignedmark (lgl, other);
15695   }
15696   n = lglcntstk (&lgl->seen);
15697   for (i = n-1; i > 0; i--) {
15698     j = lglrand (lgl) % (i + 1);
15699     if (j == i) continue;
15700     SWAP (int, lgl->seen.start[i], lgl->seen.start[j]);
15701     SWAP (int, lgl->cce->cla.start[i], lgl->cce->cla.start[j]);
15702   }
15703   nextcla = nextala = res = 0;
15704 ALA:
15705   while (!res && nextala < lglcntstk (&lgl->seen)) {
15706     lit = lglpeek (&lgl->seen, nextala++);
15707     assert (lglsignedmarked (lgl, lit));
15708     assert (!lglsignedmarked (lgl, -lit));
15709     hts = lglhts (lgl, lit);
15710     w = newtop = lglhts2wchs (lgl, hts);
15711     eow = w + hts->count;
15712     steps = 0;
15713     for (p = w; !res && p < eow; p++) {
15714       steps++;
15715       blit = *p;
15716       *newtop++ = blit;
15717       tag = blit & MASKCS;
15718       if (tag == TRNCS || tag == LRGCS) *newtop++ = *++p;
15719       if (tag == OCCS) continue;
15720       if (blit & REDCS) continue;
15721       other = blit >> RMSHFT;
15722       if (lglsignedmarked (lgl, -other)) continue;
15723       if (tag == BINCS) {
15724 	if (lglsignedmarked (lgl, other)) {
15725 	  if (igntag == BINCS) {
15726 	    if (c[0] == lit && c[1] == other) continue;
15727 	    if (c[1] == lit && c[0] == other) continue;
15728 	  }
15729 	  LOG (CCELOGLEVEL,
15730 	       "ALA on binary clause %d %d results in ATE", lit, other);
15731 	  res = 1;
15732 	} else {
15733 	  assert (!lglmarked (lgl, other));
15734 	  LOG (CCELOGLEVEL, "ALA %d through binary clause %d %d",
15735 	       -other, lit, other);
15736 	  lglsignedmark (lgl, -other);
15737 	  lglpushstk (lgl, &lgl->seen, -other);
15738 	}
15739       } else if (tag == TRNCS) {
15740 	other2 = *p;
15741 	if (lglsignedmarked (lgl, -other2)) continue;
15742 	if (lglsignedmarked (lgl, other)) {
15743 	  if (lglsignedmarked (lgl, other2)) {
15744 	    if (igntag == TRNCS) {
15745 	      if (c[0] == lit && c[1] == other && c[2] == other2) continue;
15746 	      if (c[0] == lit && c[2] == other && c[1] == other2) continue;
15747 	      if (c[1] == lit && c[0] == other && c[2] == other2) continue;
15748 	      if (c[1] == lit && c[2] == other && c[0] == other2) continue;
15749 	      if (c[2] == lit && c[0] == other && c[1] == other2) continue;
15750 	      if (c[2] == lit && c[1] == other && c[0] == other2) continue;
15751 	    }
15752 	    LOG (CCELOGLEVEL,
15753 	      "ALA on ternary clause %d %d %d results in ATE",
15754 	      lit, other, other2);
15755 	    res = 1;
15756 	  } else {
15757 	    assert (!lglmarked (lgl, other2));
15758 	    LOG (CCELOGLEVEL,
15759 	         "ALA %d through ternary clause %d %d %d (1st case)",
15760 		 -other2, lit, other, other2);
15761 	    lglsignedmark (lgl, -other2);
15762 	    lglpushstk (lgl, &lgl->seen, -other2);
15763 	  }
15764 	} else if (lglsignedmarked (lgl, other2)) {
15765 	  assert (!lglmarked (lgl, other));
15766 	  LOG (CCELOGLEVEL,
15767 	      "ALA %d through ternary clause %d %d %d (2nd case)",
15768 	      -other, lit, other, other2);
15769 	  lglsignedmark (lgl, -other);
15770 	  lglpushstk (lgl, &lgl->seen, -other);
15771 	}
15772       } else {
15773 	assert (tag == LRGCS);
15774 	d = lglidx2lits (lgl, 0, (lidx = *p));
15775 	if (d == c) continue;
15776 	if (d[0] == lit) SWAP (int, d[0], d[1]);
15777 	assert (d[1] == lit);
15778 	if (lglsignedmarked (lgl, -d[0])) continue;
15779 	for (q = d + 2; (other = *q); q++) {
15780 	  if (lglsignedmarked (lgl, -other)) break;
15781 	  if (!lglsignedmarked (lgl, other)) break;
15782 	}
15783 	if (other) {
15784 	  newtop -= 2, assert (w <= newtop);
15785 	  SWAP (int, d[1], *q);
15786 	  assert (d[1] == other);
15787           delta = lglwchlrg (lgl, d[1], d[0], 0, lidx);
15788 	  if (delta) w += delta, p += delta, newtop += delta, eow += delta;
15789 	} else if (lglsignedmarked (lgl, d[0])) {
15790 	  LOGCLS (CCELOGLEVEL, d, "ATE after ALA on large clause");
15791 	  res = 1;
15792 	} else {
15793 	  ala = -d[0];
15794 	  assert (!lglmarked (lgl, ala));
15795 	  LOGCLS (CCELOGLEVEL, d, "ALA %d through large clause", ala);
15796 	  lglsignedmark (lgl, ala);
15797 	  lglpushstk (lgl, &lgl->seen, ala);
15798 	}
15799       }
15800     }
15801     assert (newtop <= eow);
15802     while (p < eow) *newtop++ = *p++;
15803     lglshrinkhts (lgl, hts, newtop - w);
15804     if (lgl->limits->cce.steps <= ADDSTEPS (cce.steps, steps)) goto DONE;
15805   }
15806   if (res || !lgl->opts->block.val || cce < 3) goto SKIPCLA;
15807   while (!res && nextcla < lglcntstk (&lgl->cce->cla)) {
15808     lit = lglpeek (&lgl->cce->cla, nextcla++);
15809     if (lglifrozen (lgl, lit)) continue;
15810     assert (lglsignedmarked (lgl, lit));
15811     assert (!lglsignedmarked (lgl, -lit));
15812     hts = lglhts (lgl, -lit);
15813     w = lglhts2wchs (lgl, hts);
15814     eow = w + hts->count;
15815     old = lglcntstk (&lgl->cce->cla);
15816     first = 1;
15817     for (p = w; p < eow; p++) {
15818       if (lgl->limits->cce.steps <= INCSTEPS (cce.steps)) goto DONE;
15819       blit = *p;
15820       tag = blit & MASKCS;
15821       if (tag == TRNCS || tag == LRGCS) p++;
15822       if (tag == LRGCS) continue;
15823       if (blit & REDCS) continue;
15824       other = blit >> RMSHFT;
15825       if (first) {
15826 	if (tag == BINCS) {
15827 	  if (lglsignedmarked (lgl, -other)) continue;
15828 	  if (!lglsignedmarked (lgl, other))
15829 	    lglpushstk (lgl, &lgl->cce->cla, other);
15830 	} else if (tag == TRNCS) {
15831 	  if (lglsignedmarked (lgl, -other)) continue;
15832 	  if (lglsignedmarked (lgl, -(other2 = *p))) continue;
15833 	  if (!lglsignedmarked (lgl, other))
15834 	    lglpushstk (lgl, &lgl->cce->cla, other);
15835 	  if (!lglsignedmarked (lgl, other2))
15836 	    lglpushstk (lgl, &lgl->cce->cla, other2);
15837 	} else {
15838 	  assert (tag == OCCS);
15839 	  d = lglidx2lits (lgl, 0, other);
15840 	  assert (d != c);
15841 	  for (q = d; (other = *q); q++) {
15842 	    if (other == -lit) continue;
15843 	    if (lglsignedmarked (lgl, -other)) break;
15844 	  }
15845 	  if (other) continue;
15846 	  for (q = d; (other = *q); q++)
15847 	    if (other != -lit && !lglsignedmarked (lgl, other))
15848 	      lglpushstk (lgl, &lgl->cce->cla, other);
15849 	}
15850 	first = 0;
15851       } else {
15852 	r = lgl->cce->cla.start + old;
15853 	if (tag == BINCS) {
15854 	  if (lglsignedmarked (lgl, -other)) continue;
15855 	  for (q = r; q < lgl->cce->cla.top; q++)
15856 	    if (*q == other) *r++ = *q;
15857 	} else if (tag == TRNCS) {
15858 	  if (lglsignedmarked (lgl, -other)) continue;
15859 	  if (lglsignedmarked (lgl, -(other2 = *p))) continue;
15860 	  for (q = r; q < lgl->cce->cla.top; q++)
15861 	    if (*q == other || *q == other2) *r++ = *q;
15862 	} else {
15863 	  assert (tag == OCCS);
15864 	  d = lglidx2lits (lgl, 0, other);
15865 	  assert (d != c);
15866 	  for (q = d; (other = *q); q++) {
15867 	    if (other == -lit) continue;
15868 	    if (lglsignedmarked (lgl, -other)) break;
15869 	  }
15870 	  if (other) continue;
15871 	  for (q = d; (other = *q); q++) {
15872 	    if (other == -lit) continue;
15873 	    assert (other != lit);
15874 	    assert (!lglsignedmarked2 (lgl, other));
15875 	    assert (!lglsignedmarked2 (lgl, -other));
15876 	    lglsignedmark2 (lgl, other);
15877 	  }
15878 	  for (q = r; q < lgl->cce->cla.top; q++)
15879 	    if (lglsignedmarked2 (lgl, (other = *q)))
15880 	      *r++ = other;
15881 	  for (q = d; (other = *q); q++) {
15882 	    if (other == -lit) continue;
15883 	    assert (other != lit);
15884 	    assert (lglsignedmarked2 (lgl, other));
15885 	    lglsignedunmark2 (lgl, other);
15886 	  }
15887 	}
15888 	if ((lgl->cce->cla.top = r) == lgl->cce->cla.start + old) break;
15889       }
15890     }
15891     if (lglcntstk (&lgl->cce->cla) > old) {
15892       nextcla = 0;
15893       lglpushstk (lgl, &lgl->cce->extend, lit);
15894       for (q = lgl->cce->cla.start; q < lgl->cce->cla.start + old; q++)
15895 	if (*q != lit) lglpushstk (lgl, &lgl->cce->extend, *q);
15896       lglpushstk (lgl, &lgl->cce->extend, 0);
15897     }
15898     for (q = lgl->cce->cla.start + old; !res && q < lgl->cce->cla.top; q++) {
15899       if (lglsignedmarked (lgl, -*q)) {
15900 	LOG (CCELOGLEVEL, "CLA on %d results in ATE", *q);
15901 	res = 1;
15902       } else {
15903 	LOG (CCELOGLEVEL, "CLA %d on %d", *q, lit);
15904 	lglpushstk (lgl, &lgl->seen, *q);
15905 	lglsignedmark (lgl, *q);
15906       }
15907     }
15908     if (!res && p == eow && nextala < lglcntstk (&lgl->seen)) goto ALA;
15909   }
15910 SKIPCLA:
15911   if (res) {
15912     LOGCLS (CCELOGLEVEL, c, "ATE clause");
15913     lgl->stats->cce.ate++;
15914   } else if (lgl->opts->block.val && cce >= 2) {
15915    for (p = lgl->cce->cla.start; p < lgl->cce->cla.top; p++)
15916      if (!lglifrozen (lgl, (other = *p)) && (res = lglabce (lgl, other)))
15917        break;
15918     if (res) {
15919       LOGCLS (CCELOGLEVEL, c, "ABCE on %d clause", other);
15920       lglpushstk (lgl, &lgl->cce->extend, other);
15921       for (p = lgl->cce->cla.start; p < lgl->cce->cla.top; p++)
15922         if (*p != other) lglpushstk (lgl, &lgl->cce->extend, *p);
15923       lglpushstk (lgl, &lgl->cce->extend, 0);
15924       lgl->stats->cce.abce++;
15925     }
15926   }
15927   if (res) lgl->stats->cce.eliminated++;
15928 DONE:
15929   lglpopnunmarkstk (lgl, &lgl->seen);
15930   lglclnstk (&lgl->cce->cla);
15931   if (res && !lglmtstk (&lgl->cce->extend)) {
15932     assert (cce >= 2);
15933     assert (lgl->opts->block.val);
15934     prev = 0;
15935     for (p = lgl->cce->extend.start; p < lgl->cce->extend.top; p++) {
15936       lit = *p;
15937       lglepush (lgl, lit);
15938       if (!prev) assert (!lglifrozen (lgl, lit)), lglblockinglit (lgl, lit);
15939       prev = lit;
15940     }
15941   }
15942   lglclnstk (&lgl->cce->extend);
15943   return res;
15944 }
15945 
lglcce2str(int cce)15946 static const char * lglcce2str (int cce) {
15947   assert (0 <= cce), assert (cce <= 3);
15948   if (cce == 3) return "ACCE";
15949   else if (cce == 2) return "ABCE";
15950   else if (cce == 1) return "ATE";
15951   else return "none";
15952 }
15953 
lglccesmallclauses(LGL * lgl,int lit)15954 static int lglccesmallclauses (LGL * lgl, int lit) {
15955   int idx = abs (lit), blit, tag, red, other, other2;
15956   HTS * hts = lglhts (lgl, lit);
15957   const int * p, * w, * eow;
15958   CCE * cce = lgl->cce;
15959   Stk * clauses;
15960   assert (cce);
15961   if (!lglisfree (lgl, lit)) return 1;
15962   clauses = &cce->clauses;
15963   w = lglhts2wchs (lgl, hts);
15964   eow = w + hts->count;
15965   INCSTEPS (cce.steps);
15966   for (p = w; p < eow; p++) {
15967     blit = *p;
15968     tag = blit & MASKCS;
15969     if (tag == OCCS) continue;
15970     if (tag == TRNCS || tag == LRGCS) p++;
15971     if (tag == LRGCS) continue;
15972     red = blit & REDCS;
15973     if (red) continue;
15974     other = blit >> RMSHFT;
15975     if (abs (other) < idx) continue;
15976     if (!lglisfree (lgl, other)) continue;
15977     if (tag == TRNCS) {
15978       other2 = *p;
15979       if (abs (other2) < idx) continue;
15980       if (abs (other2) < abs (other)) continue;
15981       if (!lglisfree (lgl, other2)) continue;
15982       lglpushstk (lgl, clauses, other2);
15983       cce->trn++;
15984     } else {
15985       assert (tag == BINCS);
15986       cce->bin++;
15987     }
15988     lglpushstk (lgl, clauses, other);
15989     lglpushstk (lgl, clauses, lit);
15990     lglpushstk (lgl, clauses, 0);
15991   }
15992   return 1;
15993 }
15994 
lglccesmall(LGL * lgl,int cce,int round)15995 static void lglccesmall (LGL * lgl, int cce, int round) {
15996   int count, valid, invalid, tried, eliminated, elim2, elim3;
15997   int size, lit, tag;
15998   const int * p, * c;
15999   Stk * clauses;
16000   assert (lgl->cce);
16001   clauses = &lgl->cce->clauses;
16002   assert (!lgl->cce->clauses.start);
16003   lglrandlitrav (lgl, lglccesmallclauses);
16004   lglfitstk (lgl, &lgl->cce->clauses);
16005   count = lgl->cce->bin + lgl->cce->trn;
16006   lglprt (lgl, 1,
16007     "[cce-%d-%d] scheduling %d clauses = %d binary + %d ternary",
16008     lgl->stats->cce.count, round, count, lgl->cce->bin, lgl->cce->trn);
16009   tried = eliminated = invalid = elim2 = elim3 = 0;
16010   for (c = clauses->start; c < clauses->top; c = p + 1) {
16011     if (lgl->mt) break;
16012     if (lglterminate (lgl)) break;
16013     if (lgl->limits->cce.steps <= lgl->stats->cce.steps) break;
16014     valid = 1;
16015     for (p = c; (lit = *p); p++)
16016       if (!lglisfree (lgl, lit))
16017 	valid = 0;
16018     if (valid) {
16019       tried++;
16020       size = p - c;
16021       assert (2 <= size), assert (size <= 3);
16022       tag = size == 2 ? BINCS : TRNCS;
16023       if (!lglcceclause (lgl, c, tag, cce)) continue;
16024       eliminated++;
16025       if (size == 2) {
16026         if (!lglrmvbcls (lgl, c[0], c[1]))
16027 	  lgldrupligdelclsarg (lgl, c[0], c[1], 0);
16028 	elim2++;
16029       } else {
16030 	assert (size == 3);
16031         if (!lglrmvtcls (lgl, c[0], c[1], c[2]))
16032 	  lgldrupligdelclsarg (lgl, c[0], c[1], c[2], 0);
16033 	elim3++;
16034       }
16035     } else invalid++;
16036   }
16037   assert (count >= tried + invalid);
16038   lglrelstk (lgl, &lgl->cce->clauses);
16039   if (tried)
16040     lglprt (lgl, 1,
16041       "[cce-%d-%d] tried to eliminate %d small clauses %.0f%%",
16042       lgl->stats->cce.count, round, tried, lglpcnt (tried, count));
16043   if (elim2)
16044     lglprt (lgl, 1,
16045       "[cce-%d-%d] eliminated %d binary clauses %.0f%%",
16046       lgl->stats->cce.count, round, elim2, lglpcnt (elim2, lgl->cce->bin));
16047   if (elim3)
16048     lglprt (lgl, 1,
16049       "[cce-%d-%d] eliminated %d ternary clauses %.0f%%",
16050       lgl->stats->cce.count, round, elim3, lglpcnt (elim3, lgl->cce->trn));
16051   if (eliminated)
16052     lglprt (lgl, 1,
16053       "[cce-%d-%d] eliminated %d small clauses %.0f%%",
16054       lgl->stats->cce.count, round, eliminated, lglpcnt (eliminated, count));
16055 }
16056 
lglcce(LGL * lgl)16057 static int lglcce (LGL * lgl) {
16058   int oldvars = lgl->nvars, cce, lenlim, startirr, success;
16059   int oldirr, eliminated, total, idx, round;
16060   int completedsmall, completedlarge;
16061   int64_t oldsteps, deltasteps;
16062   int elmlarge, elmsmall;
16063   lglstart (lgl, &lgl->times->cce);
16064   lgl->stats->cce.count++;
16065   lglsetccelim (lgl);
16066   round = total = 0;
16067   startirr = lgl->stats->irr.clauses.cur;
16068 RESTART:
16069   round++;
16070   lenlim = INT_MAX;
16071   cce = lgl->opts->cce.val;
16072   if (cce == 3 && lgl->ccertc < 2 &&
16073       lgl->opts->cce3wait.val >= lgl->stats->cce.count) {
16074     lglprt (lgl, 2,
16075       "[cce-%d-%d] restricted to ABCE since ccertc=%s",
16076       lgl->stats->cce.count, round, lglcce2str (lgl->ccertc));
16077     cce = 2;
16078   }
16079   if (cce == 2 && lgl->ccertc < 1 &&
16080       lgl->opts->cce2wait.val >= lgl->stats->cce.count) {
16081     lglprt (lgl, 2,
16082       "[cce-%d-%d] restricted to ATE since ccertc=%s",
16083       lgl->stats->cce.count, round, lglcce2str (lgl->ccertc));
16084    cce = 1;
16085   }
16086   if (cce > 1 && !(lgl->stats->cce.count % lgl->opts->cceateint.val)) {
16087     lglprt (lgl, 2,
16088       "[cce-%d-%d] restricted to ATE due to ATE interval %d",
16089       lgl->stats->cce.count, round, lgl->opts->cceateint.val);
16090     cce = 1;
16091   }
16092   oldirr = lgl->stats->irr.clauses.cur;
16093   lglprt (lgl, 2, "[cce-%d-%d] starting round %d (%s)",
16094           lgl->stats->cce.count, round, round, lglcce2str (cce));
16095   assert (!lgl->simp && !lgl->cceing && !lgl->occs);
16096   lgl->cceing = lgl->simp = 1;
16097   if (lgl->level > 0) lglbacktrack (lgl, 0);
16098   NEW (lgl->cce, 1);
16099   NEW (lgl->cce->rem, oldvars);
16100   for (idx = 2; idx < oldvars; idx++) lgl->cce->rem[idx] = INT_MAX;
16101   lglgc (lgl);
16102   assert (lgl->frozen);
16103   lgldense (lgl, 1);
16104   oldsteps = lgl->stats->cce.steps;
16105   elmlarge = 0;
16106   while (!lgl->mt &&
16107          lenlim > 4 &&
16108 	 !lglterminate (lgl) &&
16109 	 lgl->limits->cce.steps > lgl->stats->cce.steps) {
16110     int maxlen = 0, count;
16111     const int * p, * c;
16112     Stk lidcs;
16113     CLR (lidcs);
16114     for (c = lgl->irr.start; c < lgl->irr.top; c = p + 1) {
16115       int len, lidx;
16116       if (*(p = c) >= NOTALIT) continue;
16117       while (*p) p++;
16118       len = p - c;
16119       if (len >= lenlim) continue;
16120       if (len < maxlen) continue;
16121       if (len > maxlen) {
16122 	lglclnstk (&lidcs);
16123 	maxlen = len;
16124       }
16125       lidx = c - lgl->irr.start;
16126       lglpushstk (lgl, &lidcs, lidx);
16127     }
16128     ADDSTEPS (cce.steps, lglcntstk (&lgl->irr)/128);
16129     count = lglcntstk (&lidcs);
16130     lglprt (lgl, 2,
16131       "[cce-%d-%d] scheduling %d clauses of length %d",
16132       lgl->stats->cce.count, round, count, maxlen);
16133     eliminated = 0;
16134     for (p = lidcs.start;
16135          p < lidcs.top &&
16136 	 !lgl->mt &&
16137 	 !lglterminate (lgl) &&
16138 	 lgl->limits->cce.steps > lgl->stats->cce.steps;
16139 	 p++) {
16140       int lidx = *p;
16141       c = lgl->irr.start + lidx;
16142       if (*c >= NOTALIT) continue;
16143       if (!lglcceclause (lgl, c, OCCS, cce)) continue;
16144       lgldrupligdelclsaux (lgl, c);
16145       lglrmlcls (lgl, lidx, 0);
16146       eliminated++;
16147     }
16148     elmlarge += eliminated;
16149     lglrelstk (lgl, &lidcs);
16150     lenlim = maxlen;
16151     lglprt (lgl, 1 + !eliminated,
16152       "[cce-%d-%d] eliminated %d clauses out of %d (%.0f%%) of length %d",
16153       lgl->stats->cce.count, round,
16154       eliminated, count, lglpcnt (eliminated, count), maxlen);
16155   }
16156   completedlarge = (lgl->limits->cce.steps > lgl->stats->cce.steps);
16157   if (completedlarge)
16158     lglprt (lgl, 1,
16159       "[cce-%d-%d] completed large round (%s)",
16160       lgl->stats->cce.count, round, lglcce2str (cce));
16161   else
16162     lglprt (lgl, 1,
16163       "[cce-%d-%d] incomplete large round (%s)",
16164       lgl->stats->cce.count, round, lglcce2str (cce));
16165   deltasteps = lgl->stats->cce.steps - oldsteps;
16166   lglprt (lgl, 1 + !elmlarge,
16167     "[cce-%d-%d] eliminated %d large clauses in %lld steps",
16168     lgl->stats->cce.count, round, elmlarge, (LGLL) deltasteps);
16169   deltasteps /= 2;
16170   if (LLMAX - deltasteps > lgl->limits->cce.steps) {
16171     lgl->limits->cce.steps += deltasteps;
16172     lglprt (lgl, 1,
16173       "[cce-%d-%d] allowing another %lld steps for small clauses",
16174       lgl->stats->cce.count, round, deltasteps);
16175   } else {
16176     lgl->limits->cce.steps = LLMAX;
16177     lglprt (lgl, 1,
16178       "[cce-%d-%d] unlimited number of steps for small clauses",
16179       lgl->stats->cce.count, round);
16180   }
16181   lglccesmall (lgl, cce, round);
16182   elmsmall = oldirr - lgl->stats->irr.clauses.cur - elmlarge;
16183   lglprt (lgl, 1 + !elmsmall,
16184     "[cce-%d-%d] eliminated %d small clauses in %lld steps",
16185     lgl->stats->cce.count, round, elmsmall,
16186     (LGLL) lgl->stats->cce.steps - oldsteps - deltasteps);
16187   completedsmall = (lgl->limits->cce.steps > lgl->stats->cce.steps);
16188   COVER (!completedsmall && lgl->opts->ccertc.val > 1);
16189   if (completedsmall)
16190     lglprt (lgl, 1,
16191       "[cce-%d-%d] completed small round (%s)",
16192       lgl->stats->cce.count, round, lglcce2str (cce));
16193   else
16194     lglprt (lgl, 1,
16195       "[cce-%d-%d] incomplete small round (%s)",
16196       lgl->stats->cce.count, round, lglcce2str (cce));
16197   if (completedsmall && completedlarge) {
16198     if (lgl->ccertc < cce) {
16199       lgl->ccertc = cce;
16200       lglprt (lgl, 1,
16201 	"[cce-%d-%d] completed small and large (%s)",
16202 	lgl->stats->cce.count, round, lglcce2str (cce));
16203     }
16204   }
16205   lglsparse (lgl);
16206   lglgc (lgl);
16207   lglrelstk (lgl, &lgl->cce->extend);
16208   lglrelstk (lgl, &lgl->cce->cla);
16209   DEL (lgl->cce->rem, oldvars);
16210   DEL (lgl->cce, 1);
16211   assert (oldirr >= lgl->stats->irr.clauses.cur);
16212   eliminated = oldirr - lgl->stats->irr.clauses.cur;
16213   total += eliminated;
16214   lglprt (lgl, 1,
16215     "[cce-%d-%d] eliminated %d covered clauses in round %d",
16216     lgl->stats->cce.count, round, eliminated, round);
16217   assert (lgl->simp && lgl->cceing);
16218   lgl->cceing = lgl->simp = 0;
16219   if (!lgl->mt &&
16220       eliminated &&
16221       !lglterminate (lgl) &&
16222       round < lgl->opts->ccemaxround.val &&
16223       lgl->limits->cce.steps > lgl->stats->cce.steps) goto RESTART;
16224   lglprt (lgl, 1,
16225     "[cce-%d] eliminated %d covered clauses in TOTAL during %d rounds",
16226     lgl->stats->cce.count, total, round);
16227   if (total) {
16228     success = (startirr/lgl->opts->ccesuccessrat.val <= total);
16229     if (!success)
16230       lglprt (lgl, 1,
16231 	"[cce-%d] %d < 1/%d * %d = %d considered unsuccessful",
16232 	lgl->stats->cce.count, total, lgl->opts->ccesuccessrat.val,
16233 	startirr, startirr/lgl->opts->ccesuccessrat.val);
16234   } else success = 0;
16235   LGLUPDPEN (cce, success);
16236   lglrep (lgl, 2, 'E');
16237   lglstop (lgl);
16238   lglbasicatestats (lgl);
16239   return !lgl->mt;
16240 }
16241 
lglsetelmlim(LGL * lgl,int * reschedptr)16242 static void lglsetelmlim (LGL * lgl, int * reschedptr) {
16243   int count = lgl->stats->elm.count - lgl->opts->elmboostdel.val;
16244   int pen, szpen, resched = 0;
16245   int64_t limit, irrlim;
16246   if (lgl->opts->elmrtc.val > 1) {
16247     lgl->limits->elm.steps = LLMAX;
16248     lglprt (lgl, 1,
16249       "[elim-%d] really no limit (run to completion)",
16250       lgl->stats->elm.count);
16251     resched = (lgl->opts->elmresched.val & 4);
16252   } else if (lgl->opts->elmrtc.val ||
16253              (count > 0 &&
16254 	      lglrem (lgl) < lgl->opts->elmrtcintvlim.val &&
16255              !(count % lgl->opts->elmrtcint.val))) {
16256     limit = 100000000000ll;
16257     lgl->limits->elm.steps = lgl->stats->elm.steps + limit;
16258     lglprt (lgl, 1,
16259       "[elim-%d] almost no limit of %lld steps",
16260       lgl->stats->elm.count, (LGLL) limit);
16261     resched = (lgl->opts->elmresched.val & 4);
16262   } else {
16263     limit = (lgl->opts->elmreleff.val*lglvisearch (lgl))/1000;
16264     if (limit < lgl->opts->elmineff.val) limit = lgl->opts->elmineff.val;
16265     if (lgl->opts->elmaxeff.val >= 0 && limit > lgl->opts->elmaxeff.val)
16266       limit = lgl->opts->elmaxeff.val;
16267     if (count > 0 &&
16268         (count == 1 ||
16269         !(count % lgl->opts->elmboostint.val)) &&
16270 	lglrem (lgl) < lgl->opts->elmboostvlim.val &&
16271         lgl->opts->boost.val &&
16272         lgl->opts->elmboost.val > 1) {
16273       lglprt (lgl, 1,
16274         "[elim-%d] boosting limit by %d",
16275 	lgl->stats->elm.count, lgl->opts->elmboost.val);
16276       limit *= lgl->opts->elmboost.val;
16277       resched = (lgl->opts->elmresched.val & 2);
16278     } else resched = (lgl->opts->elmresched.val & 1);
16279     limit >>= (pen = lgl->limits->elm.pen + (szpen = lglszpen (lgl)));
16280     irrlim = (lgl->stats->irr.clauses.cur) >> szpen;
16281     if (lgl->opts->irrlim.val && limit < irrlim) {
16282       limit = irrlim;
16283       lglprt (lgl, 1,
16284   "[elim-%d] limit of %lld steps based on %d irredundant clauses penalty %d",
16285 	lgl->stats->elm.count,
16286 	(LGLL) limit, lgl->stats->irr.clauses.cur, szpen);
16287     } else
16288       lglprt (lgl, 1,
16289         "[elim-%d] limit of %lld steps penalty %d = %d + %d",
16290 	lgl->stats->elm.count, (LGLL) limit,
16291 	pen, lgl->limits->elm.pen, szpen);
16292     lgl->limits->elm.steps = lgl->stats->elm.steps + limit;
16293   }
16294   lglprt (lgl, 1,					// TODO 2?
16295     "[elim-%d] rescheduling of touched variables %s",
16296     lgl->stats->elm.count, resched ? "enabled" : "disabled");
16297   *reschedptr = resched;
16298 }
16299 
lglforceschedall(LGL * lgl)16300 static int lglforceschedall (LGL * lgl) {
16301   const int oldonotsched = lgl->donotsched;
16302   int idx, res = 0;
16303   AVar * av;
16304   assert (lgl->eliminating);
16305   assert (lglmtstk (&lgl->esched));
16306   assert (lgl->touching), lgl->touching = 0;
16307   lgl->donotsched = 0;
16308   for (idx = 2; idx < lgl->nvars; idx++) {
16309     if (lglifrozen (lgl, idx)) continue;
16310     if (!lglisfree (lgl, idx)) continue;
16311     av = lglavar (lgl, idx);
16312     av->donotelm = 0;
16313     lglesched (lgl, idx);
16314     res++;
16315   }
16316   assert (!lgl->touching), lgl->touching = 1;
16317   assert (!lgl->donotsched);
16318   if (oldonotsched) lgl->donotsched = 1;
16319   lglprt (lgl, 1,
16320     "[elim-%d-%d] fully rescheduled %d variables %.0f%%",
16321     lgl->stats->elm.count, lgl->elm->round,
16322     res, lglpcnt (res, lgl->nvars - 2));
16323   return res;
16324 }
16325 
lgladdstrbincls(LGL * lgl,int a,int b)16326 static void lgladdstrbincls (LGL * lgl, int a, int b) {
16327   assert (lglisfree (lgl, a));
16328   assert (lglisfree (lgl, b));
16329   assert (lglmtstk (&lgl->clause));
16330   lglpushstk (lgl, &lgl->clause, a);
16331   lglpushstk (lgl, &lgl->clause, b);
16332   lglpushstk (lgl, &lgl->clause, 0);
16333   LOG (BWL, "strengthened binary clause", a, b);
16334   lgldrupligaddcls (lgl, REDCS);
16335   lgladdcls (lgl, 0, 0, 1);
16336   lglclnstk (&lgl->clause);
16337 }
16338 
lglbackwardlit(LGL * lgl,const int * clause,const int * skip,int size,int minlit,int * subptr,int * strptr)16339 static int lglbackwardlit (LGL * lgl,
16340 			   const int * clause, const int * skip,
16341 			   int size, int minlit,
16342 			   int *subptr, int *strptr) {
16343   int res, blit, tag, red, other, other2, lidx, count, remove, hit;
16344   const int druplig = lgl->opts->druplig.val;
16345   const int * p, * w, * eow, * c, * l;
16346   int marked, marked2, val;
16347   Stk saved;
16348   HTS * hts;
16349   CLR (saved);
16350   assert (!lgl->level);
16351   lgl->stats->bkwd.tried.lits++;
16352   LOGCLS (BWL, clause,
16353     "backward subsume and strengthen clauses with %d by size %d clause",
16354     minlit, size);
16355   hit = res = 0;
16356   hts = lglhts (lgl, minlit);
16357   w = lglhts2wchs (lgl, hts);
16358   eow = w + hts->count;
16359   for (p = w; !res && p < eow; p++) {
16360     blit = *p;
16361     tag = blit & MASKCS;
16362     if (tag == TRNCS || tag == LRGCS) p++;
16363     if (tag == LRGCS) continue;
16364     if (p == skip) continue;
16365     red = blit & REDCS;
16366     if (red) continue;
16367     lgl->stats->bkwd.tried.occs++;
16368     INCSTEPS (elm.steps);
16369     if (tag == BINCS) {
16370       if (size > 2) continue;
16371       other = blit >> RMSHFT;
16372       if (!lglisfree (lgl, other)) continue;
16373       marked = lglmarked (lgl, other);
16374       if (marked > 0) {
16375 	if (size == 2 && !hit++) continue;
16376 	LOG (BWL, "subsumed binary clause %d %d", minlit, other);
16377 	assert (!(w <= skip && skip < eow) || skip < p);
16378 	ADDSTEPS (elm.steps, 2);
16379         if (druplig) lgldrupligdelclsarg (lgl, minlit, other, 0);
16380 	lglrmbcls (lgl, minlit, other, 0);
16381 	lgl->stats->bkwd.sub2++;
16382 	*subptr += 1;
16383 	res = 1;
16384       } else if (marked < 0) {
16385 	LOG (BWL,
16386 	  "removing %d and thus strengthening binary clause %d %d",
16387 	  other, minlit, other);
16388 	assert (p != skip);
16389 	ADDSTEPS (elm.steps, 2);
16390 	lglunit (lgl, minlit);
16391 	lgl->stats->bkwd.str2++;
16392 	*strptr += 1;
16393 	res = 1;
16394       }
16395     } else if (tag == TRNCS) {
16396       if (size > 3) continue;
16397       other = blit >> RMSHFT;
16398       other2 = *p;
16399       if (!lglisfree (lgl, other)) continue;
16400       if (!lglisfree (lgl, other2)) continue;
16401       marked = lglmarked (lgl, other);
16402       marked2 = lglmarked (lgl, other2);
16403       if ((size == 2 && (marked > 0 || marked2 > 0)) ||
16404           (size == 3 && marked > 0 && marked2 > 0)) {
16405 	if (size == 3 && !hit++) continue;
16406 	assert (!(w <= skip && skip < eow) || skip < p);
16407 	LOG (BWL,
16408 	  "subsumed ternary clause %d %d %d",
16409 	  minlit, other, other2);
16410 	ADDSTEPS (elm.steps, 3);
16411         if (druplig) lgldrupligdelclsarg (lgl, minlit, other, other2, 0);
16412 	lglrmtcls (lgl, minlit, other, other2, 0);
16413 	lgl->stats->bkwd.sub3++;
16414 	*subptr += 1;
16415 	res = 1;
16416       } else {
16417 	if (marked < 0 && marked2 > 0) {
16418 	  int tmp = other; other = other2; other2 = tmp;
16419 	} else if (marked <= 0 || marked2 >= 0) continue;
16420 	LOG (BWL,
16421 	  "removing %d and thus strengthening ternary clause %d %d %d",
16422 	  other2, minlit, other, other2);
16423 	assert (lglmarked (lgl, other) > 0);
16424 	assert (lglmarked (lgl, other2) < 0);
16425 	lgladdstrbincls (lgl, minlit, other);
16426         if (druplig) lgldrupligdelclsarg (lgl, minlit, other, other2, 0);
16427 	lglrmtcls (lgl, minlit, other, other2, 0);
16428 	if (size == 3) {
16429 	  LOG (BWL,
16430 	    "removing %d and thus strengthening ternary clause %d %d %d",
16431 	    other2, minlit, other, -other2);
16432           if (druplig) lgldrupligdelclsarg (lgl, minlit, other, -other2, 0);
16433 	  lglrmtcls (lgl, minlit, other, -other2, 0);
16434 	  lgl->stats->bkwd.str3self++;
16435 	}
16436 	ADDSTEPS (elm.steps, 3);
16437 	lgl->stats->bkwd.str3++;
16438 	*strptr += 1;
16439 	res = 1;
16440       }
16441     } else {
16442       assert (tag == OCCS);
16443       lidx = blit >> RMSHFT;
16444       c = lglidx2lits (lgl, 0, lidx);
16445       if (c == skip) continue;
16446       INCSTEPS (elm.steps);
16447       count = size;
16448       remove = 0;
16449       for (l = c; (other = *l); l++) {
16450 	val = lglval (lgl, other);
16451 	if (val > 0) { remove = INT_MAX; break; }
16452 	if (val < 0) continue;
16453 	assert (!val);
16454 	marked = lglmarked (lgl, other);
16455 	if (!marked) continue;
16456 	count--;
16457 	if (marked > 0) continue;
16458 	if (remove) { remove = INT_MAX; break; }
16459 	remove = other;
16460       }
16461       if (count > 0) continue;
16462       if (remove == INT_MAX) continue;
16463       if (!remove) {
16464 	assert (!(w <= skip && skip < eow) || skip < p);
16465 	LOGCLS (BWL, c, "subsumed large clause");
16466 	ADDSTEPS (elm.steps, (l - c));
16467 	if (druplig) lgldrupligdelclsaux (lgl, c);
16468 	lglrmlcls (lgl, lidx, 0);
16469 	lgl->stats->bkwd.subl++;
16470 	*subptr += 1;
16471 	res = 1;
16472       } else if (lglsmallirr (lgl)) {
16473 	LOGCLS (BWL, c, "removing %d and thus strengthening clause", remove);
16474 	assert (lglmtstk (&lgl->clause));
16475 	assert (lglmtstk (&saved));
16476 	for (l = c; (other = *l); l++) {
16477 	  if (druplig) lglpushstk (lgl, &saved, other);
16478 	  if (other == remove) continue;
16479 	  val = lglval (lgl, other);
16480 	  if (val < 0) continue;
16481 	  assert (!val);
16482 	  lglpushstk (lgl, &lgl->clause, other);
16483 	}
16484 	lglpushstk (lgl, &lgl->clause, 0);
16485 	LOGCLS (BWL, lgl->clause.start, "strengthened clause");
16486 
16487 	if (druplig) {
16488 	  lgldrupligaddcls (lgl, REDCS);
16489 	  assert (l - c == lglcntstk (&saved));
16490 	  lglpushstk (lgl, &saved, 0);
16491 	  lgldrupligdelclsaux (lgl, saved.start);
16492 	  lglclnstk (&saved);
16493 	}
16494 	ADDSTEPS (elm.steps, (l - c));
16495 	lglrmlcls (lgl, lidx, 0);
16496 	if (l - c == size) lgl->stats->bkwd.strlself++;
16497 
16498 	lgladdcls (lgl, 0, 0, 1);
16499 	lglclnstk (&lgl->clause);
16500 	lgl->stats->bkwd.strl++;
16501 	*strptr += 1;
16502 	res = 1;
16503       }
16504     }
16505   }
16506   lglrelstk (lgl, &saved);
16507   return res;
16508 }
16509 
lglbackwardclause(LGL * lgl,const int * clause,const int * skip,int * subsumedptr,int * strengthenedptr)16510 static int lglbackwardclause (LGL * lgl,
16511                               const int * clause, const int * skip,
16512 			      int * subsumedptr, int * strengthenedptr) {
16513   int lit, size, minlit, minlit2, minocc, minocc2, tmpocc, res, large;
16514   const int * p;
16515   long delta;
16516   lgl->stats->bkwd.tried.clauses++;
16517   INCSTEPS (elm.steps);
16518   minocc = minlit = minocc2 = minlit2 = 0;
16519   for (p = clause; (lit = *p); p++) {
16520     lglmarkunmarked (lgl, lit);
16521     tmpocc = lglocc (lgl, lit);
16522     if (!minlit || tmpocc < minocc) {
16523       minocc2 = minocc, minlit2 = minlit;
16524       minocc = tmpocc, minlit = lit;
16525     } else if (!minlit2 || tmpocc < minocc2) {
16526       minocc2 = tmpocc, minlit2 = lit;
16527     }
16528   }
16529   size = p - clause;
16530   assert (size >= 2);
16531   LOG (BWL, "minimum occurrence %d of literal %d", minocc, minlit);
16532   LOG (BWL, "next minimum occurrence %d of literal %d", minocc2, minlit2);
16533   large = (lgl->irr.start <= clause && clause < lgl->irr.top);
16534   delta = large ? clause - lgl->irr.start : 0;
16535   res = lglbackwardlit (lgl, clause, skip,
16536 		        size, minlit, subsumedptr, strengthenedptr);
16537   if (!res) {
16538     res = lglbackwardlit (lgl, clause, skip,
16539 			  size, minlit2, subsumedptr, strengthenedptr);
16540   }
16541   if (res && large) clause = lgl->irr.start + delta;
16542   for (p = clause; (lit = *p); p++)
16543     lglunmark (lgl, lit);
16544   return res;
16545 }
16546 
lglbackward(LGL * lgl,int * u,int * t,int64_t steps,int * completedptr)16547 static void lglbackward (LGL * lgl, int * u, int * t,
16548                          int64_t steps, int * completedptr) {
16549   int idx, sign, lit, blit, red, tag, other, other2, clause[4], * w;
16550   int oldtouched, newtouched, round, touched;
16551   int64_t limit, delta, scaled;
16552   const int * p, * eow, * c;
16553   HTS * hts;
16554   Stk stk;
16555   lglstart (lgl, &lgl->times->backward);
16556   lgl->elm->bkwdocclim =
16557     lglfactor (lgl, lgl->opts->bkwdocclim.val, lgl->stats->elm.count);
16558   CLR (stk);
16559   *u = *t = 0;
16560   if (LLMAX/lgl->opts->bkwdscale.val <= steps/100) scaled = LLMAX;
16561   else scaled = steps/100 * lgl->opts->bkwdscale.val;
16562   if (lgl->limits->elm.steps - scaled <= lgl->stats->elm.steps)
16563     limit = lgl->limits->elm.steps;
16564   else limit = lgl->stats->elm.steps + scaled;
16565   delta = limit - lgl->stats->elm.steps;
16566   lglprt (lgl, 1,
16567     "[elim-%d-%d] backward subsumption/strengthening limit %lld",
16568     lgl->stats->elm.count, lgl->elm->round, delta);
16569   round = 0;
16570 RESTARTOUCHED:
16571   round++;
16572   oldtouched = lglcntstk (&lgl->elm->touched.stk);
16573   assert (oldtouched >= lgl->elm->touched.mt);
16574   oldtouched -= lgl->elm->touched.mt;
16575   lglprt (lgl, 1,
16576     "[elim-%d-%d-%d] backward checking %d touched variables %.0f%%",
16577     lgl->stats->elm.count, lgl->elm->round, round,
16578     oldtouched, lglpcnt (oldtouched, lglrem (lgl)));
16579   *completedptr = 0;
16580   while ((idx = lglpoptouched (lgl))) {
16581     for (sign = -1; sign <= 1; sign += 2) {
16582 RESTARTLIT:
16583       if (lgl->mt) goto DONE;
16584       if (lglterminate (lgl)) goto DONE;
16585 
16586       // TODO DID NOT WORK?  REMOVE OR FIX?
16587       // if (!lglsyncunits (lgl)) goto DONE;
16588 
16589       if (!lglisfree (lgl, idx)) continue;
16590       if (INCSTEPS (elm.steps) >= limit) goto DONE;
16591       lit = sign * idx;
16592       hts = lglhts (lgl, lit);
16593       w = lglhts2wchs (lgl, hts);
16594       eow = w + hts->count;
16595       lglclnstk (&stk);
16596       for (p = w; p < eow; p++) {
16597 	blit = *p;
16598 	tag = blit & MASKCS;
16599 	if (tag == TRNCS || tag == LRGCS) p++;
16600 	if (tag != BINCS) continue;
16601 	red = blit & REDCS;
16602 	if (red) continue;
16603 	lglpushstk (lgl, &stk, blit);
16604       }
16605       for (p = w; p < eow; p++) {
16606 	blit = *p;
16607 	tag = blit & MASKCS;
16608 	if (tag == TRNCS || tag == LRGCS) p++;
16609 	if (tag != TRNCS) continue;
16610 	red = blit & REDCS;
16611 	if (red) continue;
16612 	lglpushstk (lgl, &stk, blit);
16613 	lglpushstk (lgl, &stk, *p);
16614       }
16615       for (p = w; p < eow; p++) {
16616 	blit = *p;
16617 	tag = blit & MASKCS;
16618 	if (tag == TRNCS || tag == LRGCS) p++;
16619 	red = blit & REDCS;
16620 	if (!red && (tag == BINCS || tag == TRNCS)) continue;
16621 	lglpushstk (lgl, &stk, blit);
16622 	if (tag == TRNCS || tag == LRGCS)
16623 	  lglpushstk (lgl, &stk, *p);
16624       }
16625       assert (lglcntstk (&stk) == hts->count);
16626       memcpy (w, stk.start, lglcntstk (&stk) * sizeof *w);
16627       clause[0] = lit;
16628       for (p = w; p < eow; p++) {
16629 	blit = *p;
16630 	tag = blit & MASKCS;
16631 	if (tag == TRNCS || tag == LRGCS) p++;
16632 	if (tag == LRGCS) continue;
16633 	red = blit & REDCS;
16634 	if (red) continue;
16635 	if (INCSTEPS (elm.steps) >= limit) goto DONE;
16636 	if (tag == BINCS) {
16637 	  other = blit >> RMSHFT;
16638 	  if (abs (other) < idx) continue;
16639 	  clause[1] = other, clause[2] = 0;
16640 	  if (!lglbackwardclause (lgl, clause, p, u, t)) continue;
16641 	} else if (tag == TRNCS) {
16642 	  other = blit >> RMSHFT;
16643 	  if (abs (other) < idx) continue;
16644 	  other2 = *p;
16645 	  if (abs (other2) < idx) continue;
16646 	  clause[1] = other, clause[2] = other2, clause[3] = 0;
16647 	  if (!lglbackwardclause (lgl, clause, p, u, t)) continue;
16648 	} else { assert (tag == OCCS); continue; }
16649 	if (lglflush (lgl)) goto RESTARTLIT;
16650 	else goto DONE;
16651       }
16652     }
16653   }
16654   for (c = lgl->irr.start; c < lgl->irr.top; c = p + 1) {
16655     if (!lglsmallirr (lgl)) goto DONE;
16656     if (INCSTEPS (elm.steps) >= limit) goto DONE;
16657     if (*(p = c) >= NOTALIT) continue;
16658     touched = 0;
16659     while ((lit = *p)) {
16660       if (!touched && lgltouched (lgl, lit)) touched = 1;
16661       p++;
16662     }
16663     if (touched) lglbackwardclause (lgl, c, c, u, t);
16664   }
16665   if (round < lgl->opts->bkwdroundlim.val &&
16666       !lglmtstk (&lgl->elm->touched.stk))
16667     goto RESTARTOUCHED;
16668   *completedptr = 1;
16669 DONE:
16670   newtouched = lglcntstk (&lgl->elm->touched.stk);
16671   assert (newtouched >= lgl->elm->touched.mt);
16672   newtouched -= lgl->elm->touched.mt;
16673   if (*completedptr)
16674     assert (!newtouched),
16675     lglprt (lgl, 1,
16676       "[elim-%d-%d-%d] fully completed backward checking in %d rounds",
16677       lgl->stats->elm.count, lgl->elm->round, round, round);
16678   else
16679     lglprt (lgl, 1,
16680       "[elim-%d-%d-%d] incomplete backward checking %d remain %.0f%%",
16681       lgl->stats->elm.count, lgl->elm->round, round,
16682       newtouched, lglpcnt (newtouched, oldtouched));
16683   lglrelstk (lgl, &stk);
16684   lglstop (lgl);
16685 }
16686 
lglelmdone(LGL * lgl,int * allptr)16687 static int lglelmdone (LGL * lgl, int * allptr) {
16688   int newelmd, eliminated, subsumed, strengthened, bkwdcompleted;
16689   const int oldonotsched = lgl->donotsched;
16690   const int newdonotsched = !lgl->opts->bkwdresched.val;
16691   int64_t steps, oldsteps;
16692   if (!lglsmallirr (lgl)) return 1;
16693   if (lglterminate (lgl)) return 1;
16694   if (lgl->limits->elm.steps <= lgl->stats->elm.steps) return 1;
16695   if (!lglmtstk (&lgl->esched)) return 0;
16696   steps = ((oldsteps = lgl->stats->elm.steps) - lgl->elm->oldsteps);
16697   eliminated = (newelmd = lgl->stats->elm.elmd) - lgl->elm->oldelmd;
16698   assert (eliminated >= 0);
16699   if (eliminated <= 0) {
16700     lglprt (lgl, 1,
16701       "[elim-%d-%d] no variable eliminated in round %d in %lld steps",
16702       lgl->stats->elm.count, lgl->elm->round,
16703       lgl->elm->round, (LGLL) steps);
16704     return 1;
16705   }
16706   lglprt (lgl, 1,
16707     "[elim-%d-%d] eliminated %d variables %.0f%% in round %d in %lld steps",
16708     lgl->stats->elm.count, lgl->elm->round, eliminated,
16709     lglpcnt (eliminated, lgl->nvars - 2), lgl->elm->round, (LGLL) steps);
16710   if (oldonotsched != newdonotsched) lgl->donotsched = newdonotsched;
16711   lglbackward (lgl, &subsumed, &strengthened, steps, &bkwdcompleted);
16712   if (oldonotsched != newdonotsched) lgl->donotsched = oldonotsched;
16713   steps = lgl->stats->elm.steps - oldsteps;
16714   lglprt (lgl, 1,
16715     "[elim-%d-%d] subsumed %d and strengthened %d clauses in %lld steps",
16716     lgl->stats->elm.count, lgl->elm->round, subsumed, strengthened,
16717     (LGLL) steps);
16718   lgl->stats->elm.rounds++;
16719   lgl->elm->oldelmd = newelmd;
16720   lgl->elm->oldsteps = lgl->stats->elm.steps;
16721   if (lgl->mt) return 1;
16722   if (lgl->limits->elm.steps <= lgl->stats->elm.steps) return 1;
16723   if (lgl->elm->round >= lgl->opts->elmroundlim.val) return 1;
16724   if (!lglmtstk (&lgl->esched)) {
16725     lglprt (lgl, 1,
16726       "[elim-%d-%d] rescheduled %d variables %.0f%% by backward subsumption",
16727       lgl->stats->elm.count, lgl->elm->round,
16728       lglcntstk (&lgl->esched),
16729       lglpcnt (lglcntstk (&lgl->esched), lglrem (lgl)));
16730     lgl->elm->round++;
16731     return 0;
16732   }
16733   if (bkwdcompleted && *allptr) return 1;
16734   *allptr = 1;
16735   if (!lglforceschedall (lgl)) return 1;
16736   lgl->elm->round++;
16737   return 0;
16738 }
16739 
lglinitouched(LGL * lgl)16740 static void lglinitouched (LGL * lgl) {
16741   int idx;
16742   assert (lgl->eliminating);
16743   lgl->elm->touched.nvars = lgl->nvars;
16744   NEW (lgl->elm->touched.pos, lgl->nvars);
16745   for (idx = 2; idx < lgl->nvars; idx++)
16746     lgl->elm->touched.pos[idx] = -1;
16747 }
16748 
lglreltouched(LGL * lgl)16749 static void lglreltouched (LGL * lgl) {
16750   lglrelstk (lgl, &lgl->elm->touched.stk);
16751   DEL (lgl->elm->touched.pos, lgl->elm->touched.nvars);
16752 }
16753 
lglelim(LGL * lgl)16754 static int lglelim (LGL * lgl) {
16755   int res = 1, idx, elmd, oldnvars, sched, success, all, rem;
16756   int oldrem = lgl->elmrem, oldall = lgl->elmall, resched;
16757   assert (lgl->opts->elim.val);
16758   assert (!lgl->mt);
16759   assert (lgl->nvars > 2);
16760   assert (!lgl->eliminating);
16761   assert (!lgl->simp);
16762   assert (!lgl->occs);
16763   lglstart (lgl, &lgl->times->elim);
16764   lgl->stats->elm.count++;
16765   lgl->eliminating = lgl->simp = lgl->occs = 1;
16766   NEW (lgl->elm, 1);
16767   lgl->elm->oldelmd = lgl->stats->elm.elmd;
16768   lgl->elm->round = 1;
16769   lgl->elm->oldsteps = lgl->stats->elm.steps;
16770   lgl->stats->elm.rounds++;
16771   if (lgl->level > 0) lglbacktrack (lgl, 0);
16772   oldnvars = lglrem (lgl);
16773   lglgc (lgl);
16774   assert (lgl->frozen);
16775   assert (!(oldall && !oldrem));
16776   all = !oldrem || !oldall;
16777   if (all)
16778     lglprt (lgl, 1,
16779       "[elim-%d] scheduling all variables this time",
16780        lgl->stats->elm.count);
16781   else if (!lgleschedrem (lgl, 1)) all = 1, oldrem = 0;
16782   if (!all) assert (!lgl->donotsched), lgl->donotsched = 1;
16783   assert (!lgl->touching);
16784   lgldense (lgl, 1);
16785   lglinitouched (lgl);
16786   if (!all) assert (lgl->donotsched), lgl->donotsched = 0;
16787   assert (!lgl->touching), lgl->touching = 1;
16788   lglsetelmlim (lgl, &resched);
16789   if (!resched) assert (!lgl->donotsched), lgl->donotsched = 1;
16790   sched = lglcntstk (&lgl->esched);
16791   while (res && !lglelmdone (lgl, &all)) {
16792     idx = lglpopesched (lgl);
16793     lglavar (lgl, idx)->donotelm = 1;
16794     lglelimlit (lgl, idx);
16795     res = lglflush (lgl);
16796     assert (res || lgl->mt);
16797   }
16798   assert (lgl->touching), lgl->touching = 0;
16799   if (!resched) assert (lgl->donotsched), lgl->donotsched = 0;
16800   rem = lglcntstk (&lgl->esched);
16801   if (!rem) {
16802     lglprt (lgl, 1,
16803       "[elim-%d] fully completed in %d rounds",
16804       lgl->stats->elm.count, lgl->elm->round);
16805     lgl->elmrtc = 1;
16806   } else {
16807     lglprt (lgl, 1,
16808       "[elim-%d] incomplete %d not tried %.0f%% in round %d",
16809       lgl->stats->elm.count,
16810       rem, lglpcnt (rem, lgl->nvars - 2),
16811       lgl->elm->round);
16812   }
16813   lglsetdonotesched (lgl, !rem);
16814   lglrelstk (lgl, &lgl->esched);
16815   lglreltouched (lgl);
16816   lglrelecls (lgl);
16817   lglsparse (lgl);
16818   lglgc (lgl);
16819   DEL (lgl->elm, 1);
16820   lgl->elmrem = rem > 0;
16821   lgl->elmall = all && lgl->elmrem;
16822   lglprt (lgl, 1,
16823     "[elim-%d] transition to [ all %d rem %d ] state",
16824     lgl->stats->elm.count, lgl->elmall, lgl->elmrem);
16825   elmd = oldnvars - lglrem (lgl);
16826   lgl->stats->irrprgss += elmd;
16827   lglprt (lgl, 1,
16828     "[elim-%d] eliminated %d = %.0f%% variables out of %d scheduled",
16829     lgl->stats->elm.count, elmd, lglpcnt (elmd, sched), sched);
16830   if (!lgl->elmrtc  &&
16831       lgl->stats->elm.count <= lgl->opts->elmsuccessmaxwortc.val) {
16832     success = 1;
16833     lglprt (lgl, 1,
16834       "[elim-%d] considered successful since not run to completion yet",
16835       lgl->stats->elm.count);
16836   } else if (elmd) {
16837     success = (oldnvars/lgl->opts->elmsuccessrat.val <= elmd);
16838     if (!success)
16839       lglprt (lgl, 1,
16840 	"[elim-%d] %d < 1/%d * %d = %d considered unsuccessful",
16841 	lgl->stats->elm.count, elmd, lgl->opts->elmsuccessrat.val,
16842 	sched, sched/lgl->opts->elmsuccessrat.val);
16843   } else success = 0;
16844   LGLUPDPEN (elm, success);
16845   lglrep (lgl, 2, 'e');
16846   assert (lgl->eliminating && lgl->simp && lgl->occs);
16847   lgl->eliminating = lgl->simp = lgl->occs = 0;
16848   lglstop (lgl);
16849   return !lgl->mt;
16850 }
16851 
lglsynceqs(LGL * lgl)16852 static int lglsynceqs (LGL * lgl) {
16853   int * ereprs, emax = lgl->maxext;
16854   int elit1, erepr1, elit2, erepr2;
16855   int ilit1, irepr1, ilit2, irepr2;
16856   int consumed = 0, produced = 0;
16857   assert (!lgl->mt);
16858   assert (!lgl->level);
16859   if (!lgl->nvars) return 1;
16860   if (!lgl->cbs) return 1;
16861   if (!lgl->cbs->eqs.lock.fun) return 1;
16862   assert (lgl->repr);
16863   ereprs = lgl->cbs->eqs.lock.fun (lgl->cbs->eqs.lock.state);
16864   produced = consumed = 0;
16865   for (elit1 = 1; elit1 <= emax; elit1++) {
16866     if (lglelitblockingoreliminated (lgl, elit1)) continue;
16867     elit2 = lglptrjmp (ereprs, emax, elit1);
16868     if (elit2 == elit1) continue;
16869     if (lglelitblockingoreliminated (lgl, elit2)) continue;
16870     assert (elit2 != -elit1);
16871     erepr1 = lglerepr (lgl, elit1);
16872     if (lglelitblockingoreliminated (lgl, erepr1)) continue;
16873     erepr2 = lglerepr (lgl, elit2);
16874     if (lglelitblockingoreliminated (lgl, erepr2)) continue;
16875     if (erepr1 == erepr2) continue;
16876     if (erepr1 == -erepr2) {
16877 INCONSISTENT:
16878       LOG (1, "inconsistent external equivalence %d %d", elit1, elit2);
16879       assert (!lgl->level);
16880       lglmt (lgl);
16881       goto DONE;
16882     }
16883     ilit1 = lglimport (lgl, elit1);
16884     ilit2 = lglimport (lgl, elit2);
16885     if (ilit1 == ilit2) continue;
16886     if (ilit1 == -ilit2) goto INCONSISTENT;
16887     if (abs (ilit1) <= 1) continue;
16888     if (abs (ilit2) <= 1) continue;
16889     irepr1 = lglirepr (lgl, ilit1);
16890     irepr2 = lglirepr (lgl, ilit2);
16891     if (irepr1 == irepr2) continue;
16892     if (irepr1 == -irepr2) goto INCONSISTENT;
16893     if (abs (irepr1) <= 1) continue;
16894     if (abs (irepr2) <= 1) continue;
16895     LOG (2, "importing external equivalence %d %d as internal %d %d",
16896 	 elit1, elit2, irepr1, irepr2);
16897     if (!lglisfree (lgl, irepr1)) continue;
16898     if (!lglisfree (lgl, irepr2)) continue;
16899     consumed++;
16900     lglimerge (lgl, irepr1, irepr2);
16901   }
16902   LOG (1, "consumed %d equivalences", consumed);
16903   for (elit1 = 1; elit1 <= emax; elit1++) {
16904     elit2 = lglerepr (lgl, elit1);
16905     if (elit1 == elit2) continue;
16906     assert (elit1 != -elit2);
16907     erepr1 = lglptrjmp (ereprs, emax, elit1);
16908     erepr2 = lglptrjmp (ereprs, emax, elit2);
16909     if (erepr1 == erepr2) continue;
16910     assert (erepr1 != -erepr2);
16911     LOG (2, "exporting external equivalence %d %d", erepr1, erepr2);
16912     produced++;
16913     ereprs[abs (erepr1)] = (erepr1 < 0) ? -erepr2 : erepr2;
16914   }
16915   LOG (1, "produced %d equivalences", produced);
16916 DONE:
16917   if (lgl->cbs->eqs.unlock.fun)
16918     lgl->cbs->eqs.unlock.fun (lgl->cbs->eqs.unlock.state, consumed, produced);
16919   return !lgl->mt;
16920 }
16921 
lgldecomp(LGL * lgl)16922 static int lgldecomp (LGL * lgl) {
16923   int res = 1, oldnvars = lgl->nvars, removed;
16924   assert (lgl->opts->decompose.val || lgl->probing || lgl->gaussing || lgl->sweeping);
16925   assert (!lgl->decomposing);
16926   lglstart (lgl, &lgl->times->decompose);
16927   lgl->stats->decomps++;
16928   lgl->decomposing = 1;
16929   lgl->simp++;
16930   assert (lgl->simp > 0);
16931   if (lgl->level > 0) lglbacktrack (lgl, 0);
16932   res = 0;
16933   lglgc (lgl);
16934   if (!lglsyncunits (lgl)) goto DONE;
16935   lglgc (lgl);
16936   if (lgl->mt) goto DONE;
16937   if (!lgltarjan (lgl)) goto DONE;
16938   if (!lglsynceqs (lgl)) goto DONE;
16939   lglchkred (lgl);
16940   lgldcpdis (lgl);
16941   lgldcpcln (lgl);
16942   lgldcpcon (lgl);
16943   lglcompact (lgl);
16944   lglmap (lgl);
16945   if (lgl->mt) goto DONE;
16946   if (!lglbcp (lgl)) { lglmt (lgl); goto DONE; }
16947   lglcount (lgl);
16948   lglgc (lgl);
16949   if (lgl->mt) goto DONE;
16950   res = 1;
16951 DONE:
16952   if (lgl->repr) DEL (lgl->repr, lgl->nvars);
16953   assert (lgl->decomposing);
16954   lgl->decomposing = 0;
16955   ASSERT (lgl->simp > 0);
16956   lgl->simp--;
16957   removed = oldnvars - lgl->nvars;
16958   if (removed)
16959     lglprt (lgl, 1,
16960       "[decomp-%d] removed %d variables",
16961       lgl->stats->decomps, removed);
16962   lglrep (lgl, 2, 'd');
16963   lglstop (lgl);
16964   return res;
16965 }
16966 
lglnvars(LGL * lgl)16967 int lglnvars (LGL * lgl) { return lglrem (lgl); }
16968 
lglnclauses(LGL * lgl)16969 int lglnclauses (LGL * lgl) { return lgl->stats->irr.clauses.cur; }
16970 
lgldstpull(LGL * lgl,int lit)16971 static int lgldstpull (LGL * lgl, int lit) {
16972   AVar * av;
16973   av = lglavar (lgl, lit);
16974   assert ((lit > 0) == av->wasfalse);
16975   if (av->mark) return 0;
16976   if (!lglevel (lgl, lit)) return 0;
16977   av->mark = 1;
16978   if (lgldecision (lgl, lit)) {
16979     lglpushstk (lgl, &lgl->clause, lit);
16980     LOG (3, "added %d to learned clause", lit);
16981   } else {
16982     lglpushstk (lgl, &lgl->seen, -lit);
16983     LOG (3, "pulled in distillation literal %d", -lit);
16984   }
16985   return 1;
16986 }
16987 
lglanalit(LGL * lgl,int lit)16988 static int lglanalit (LGL * lgl, int lit) {
16989   int r0, r1, antecedents, other, next, tag, * p, * rsn;
16990   AVar * av;
16991   assert (lglmtstk (&lgl->seen));
16992   assert (lglmtstk (&lgl->clause));
16993   antecedents = 1;
16994   av = lglavar (lgl, lit);
16995   rsn = lglrsn (lgl, lit);
16996   r0 = rsn[0], r1 = rsn[1];
16997   LOGREASON (2, lit, r0, r1, "starting literal analysis for %d with", lit);
16998   LOG (3, "added %d to learned clause", lit);
16999   lglpushstk (lgl, &lgl->clause, lit);
17000   assert ((lit < 0) == av->wasfalse);
17001   assert (!av->mark);
17002   av->mark = 1;
17003   next = 0;
17004   for (;;) {
17005     tag = r0 & MASKCS;
17006     if (tag == BINCS || tag == TRNCS) {
17007       other = r0 >> RMSHFT;
17008       lgldstpull (lgl, other);
17009       if (tag == TRNCS) lgldstpull (lgl, r1);
17010     } else if (tag == UNITCS) assert (!lglevel (lgl, lit));
17011     else if (tag == DECISION) assert (lglavar (lgl, lit)->assumed);
17012     else {
17013       assert (tag == LRGCS);
17014       for (p = lglidx2lits (lgl, (r0 & REDCS), r1); (other = *p); p++)
17015 	if (other != lit) lgldstpull (lgl, *p);
17016     }
17017     if (next == lglcntstk (&lgl->seen)) break;
17018     lit = lglpeek (&lgl->seen, next++);
17019     assert ((lit < 0) == lglavar (lgl, lit)->wasfalse);
17020     rsn = lglrsn (lgl, lit);
17021     r0 = rsn[0], r1 = rsn[1];
17022     LOGREASON (2, lit, r0, r1, "literal analysis of");
17023     antecedents++;
17024   }
17025   lglpopnunmarkstk (lgl, &lgl->seen);
17026   LOG (2, "literal analysis used %d antecedents", antecedents);
17027   assert (lglcntstk (&lgl->clause) >= 1);
17028   return antecedents;
17029 }
17030 
lglfailedass(LGL * lgl)17031 static int lglfailedass (LGL * lgl) {
17032   assert (lgl->level >= lgl->alevel);
17033   return lgl->level == lgl->alevel && lgl->failed;
17034 }
17035 
lglanafailed(LGL * lgl)17036 static void lglanafailed (LGL * lgl) {
17037   int ilit, elit, erepr, failed, size;
17038   unsigned bit, rbit, ibit, count;
17039   Ext * ext, * rext;
17040   const int * p;
17041   AVar * av;
17042   assert (lgl->mt || lglfailedass (lgl));
17043   if (lgl->mt) {
17044     LOG (1, "no failed assumptions since CNF unconditionally inconsistent");
17045   } else if ((failed = lgl->failed) == -1) {
17046     assert (!lgl->level);
17047     elit = 0;
17048     for (p = lgl->eassume.start; !elit && p < lgl->eassume.top; p++) {
17049       erepr = lglerepr (lgl, *p);
17050       if (lglederef (lgl, erepr) < 0) elit = *p;
17051     }
17052     assert (elit);
17053     LOG (1, "found single external failed assumption %d", elit);
17054     ext = lglelit2ext (lgl, elit);
17055     assert (!ext->failed);
17056     bit = 1u << (elit < 0);
17057     assert (ext->assumed & bit);
17058     ext->failed |= bit;
17059   } else {
17060     assert (abs (failed) > 1);
17061     if ((av = lglavar (lgl, failed))->assumed == 3) {
17062       LOG (1, "inconsistent internal assumptions %d and %d", failed, -failed);
17063       assert (!av->failed);
17064       av->failed = 3;
17065     } else {
17066       lglanalit (lgl, -failed);
17067       for (p = lgl->clause.start; p < lgl->clause.top; p++) {
17068 	ilit = *p;
17069 	av = lglavar (lgl, ilit);
17070 	bit = (1u << (ilit > 0));
17071 	assert (av->assumed & bit);
17072 	assert (!(av->failed & bit));
17073 	av->failed |= bit;
17074       }
17075       size = lglcntstk (&lgl->clause);
17076       assert (size > 0);
17077       lglpushstk (lgl, &lgl->clause, 0);
17078       lglprt (lgl, 2,
17079 	 "[analyze-final] learned clause with size %d out of %d",
17080 	 size, lglcntstk (&lgl->eassume));
17081       LOGCLS (2, lgl->clause.start, "failed assumption clause");
17082       lgldrupligaddcls (lgl, REDCS);
17083       lgladdcls (lgl, REDCS, size, 0);
17084       lglpopstk (&lgl->clause);
17085       lglpopnunmarkstk (lgl, &lgl->clause);
17086     }
17087     count = 0;
17088     for (p = lgl->eassume.start; p < lgl->eassume.top; p++) {
17089       elit =  *p;
17090       bit = 1u << (elit < 0);
17091       ext = lglelit2ext (lgl, elit);
17092       assert (!ext->eliminated && !ext->blocking);
17093       assert (ext->assumed & bit);
17094       if (ext->failed & bit) continue;
17095       if (ext->equiv) {
17096 	erepr = ext->repr;
17097 	rbit = bit;
17098 	if (erepr < 0) rbit ^= 3;
17099 	if (elit < 0) erepr = -erepr;
17100 	rext = lglelit2ext (lgl, erepr);
17101 	assert (!rext->equiv);
17102 	if (rext->failed & rbit) continue;
17103 	ilit = rext->repr;
17104 	ibit = rbit;
17105 	if (ilit < 0) ilit = -ilit, ibit ^= 3;
17106 	if (ilit == 1) continue;
17107 	assert (ilit && ilit != -1);
17108 	av = lglavar (lgl, ilit);
17109 	if (!(av->failed & ibit)) continue;
17110 	rext->failed |= rbit;
17111 	count++;
17112 	if (rext->assumed & rbit) {
17113 	  LOG (2,
17114 	       "found representative external failed assumption %d",
17115 	       erepr);
17116 	} else {
17117 	  LOG (2,
17118 	       "found non representative external failed assumption %d",
17119 	       elit);
17120 	  ext->failed |= bit;
17121 	}
17122       } else {
17123 	ilit = ext->repr;
17124 	ibit = bit;
17125 	if (ilit < 0) ilit = -ilit, ibit ^= 3;
17126 	if (ilit == 1) continue;
17127 	assert (ilit && ilit != -1);
17128 	av = lglavar (lgl, ilit);
17129 	if (!(av->failed & ibit)) continue;
17130 	LOG (2, "found external failed assumption %d", elit);
17131 	ext->failed |= bit;
17132 	count++;
17133       }
17134     }
17135     LOG (1, "found %u external failed assumptions", count);
17136   }
17137   TRANS (FAILED);
17138 }
17139 
lglternreslit(LGL * lgl,int lit)17140 static void lglternreslit (LGL * lgl, int lit) {
17141   int * pw, * peow, * nw, * neow, * p, * n;
17142   int pblit, ptag, pother, pother2, pdelta;
17143   int nblit, ntag, nother, nother2, ndelta;
17144   HTS * phts, * nhts;
17145   int a, b, c;
17146 
17147   phts = lglhts (lgl, lit);
17148   pw = lglhts2wchs (lgl, phts);
17149   peow = pw + phts->count;
17150   nhts = lglhts (lgl, -lit);
17151   nw = lglhts2wchs (lgl, nhts);
17152   neow = nw + nhts->count;
17153   for (n = nw; n < neow; n++) {
17154     if (INCSTEPS (ternres.steps) >= lgl->limits->ternres.steps) return;
17155     nblit = *n;
17156     ntag = nblit & MASKCS;
17157     if (ntag == BINCS || ntag == OCCS) continue;
17158     if (ntag == TRNCS) break;
17159     assert (ntag == LRGCS);
17160     n++;
17161   }
17162   if (n >= neow) return;
17163   for (p = pw;
17164        p < peow && lgl->stats->ternres.steps < lgl->limits->ternres.steps;
17165        p++) {
17166     INCSTEPS (ternres.steps);
17167     pblit = *p;
17168     ptag = pblit & MASKCS;
17169     if (ptag == BINCS || ptag == OCCS) continue;
17170     if (ptag == TRNCS || ptag == LRGCS) p++;
17171     if (ptag == LRGCS) continue;
17172     assert (ptag == TRNCS);
17173     pother = pblit >> RMSHFT;
17174     if (lglval (lgl, pother)) continue;
17175     pother2 = *p;
17176     if (lglval (lgl, pother2)) continue;
17177     for (n = nw;
17178 	 n < neow && lgl->stats->ternres.steps < lgl->limits->ternres.steps;
17179 	 n++) {
17180       INCSTEPS (ternres.steps);
17181       nblit = *n;
17182       ntag = nblit & MASKCS;
17183       if (ntag == BINCS || ntag == OCCS) continue;
17184       if (ntag == TRNCS || ntag == LRGCS) n++;
17185       if (ntag == LRGCS) continue;
17186       assert (ntag == TRNCS);
17187       nother = nblit >> RMSHFT;
17188       if (lglval (lgl, nother)) continue;
17189       nother2 = *n;
17190       if (lglval (lgl, nother2)) continue;
17191       if ((nother == pother && nother2 == pother2) ||
17192 	  (nother == pother2 && nother2 == pother)) {
17193 	a = nother, b = nother2;
17194 	if (lglhasbin (lgl, a, b)) continue;
17195 	lgl->stats->ternres.bin++;
17196 	LOG (2, "ternary resolvent %d %d", a, b);
17197 	lgldrupligaddclsarg (lgl, REDCS, a, b, 0);
17198 	lglwchbin (lgl, a, b, REDCS);
17199 	lglwchbin (lgl, b, a, REDCS);
17200 	lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
17201 	lglwrktouch (lgl, a);
17202 	lglwrktouch (lgl, b);
17203       } else {
17204 	a = nother, b = nother2;
17205 	if (nother == pother || nother2 == pother) c = pother2;
17206 	else if (nother == pother2 || nother2 == pother2) c = pother;
17207 	else continue;
17208 	assert (a != b && b != c && a != c);
17209 	assert (a != -b);
17210 	if (a == -c || b == -c) continue;
17211 	if (lglhastrn (lgl, a, b, c)) continue;
17212 	lgl->stats->ternres.trn++;
17213 	LOG (2, "ternary resolvent %d %d %d", a, b, c);
17214 	lgldrupligaddclsarg (lgl, REDCS, a, b, c, 0);
17215 	lglwchtrn (lgl, a, b, c, REDCS);
17216 	lglwchtrn (lgl, b, a, c, REDCS);
17217 	lglwchtrn (lgl, c, a, b, REDCS);
17218 	lgl->stats->red.trn++, assert (lgl->stats->red.trn > 0);
17219 	lglwrktouch (lgl, a);
17220 	lglwrktouch (lgl, b);
17221 	lglwrktouch (lgl, c);
17222       }
17223       pdelta = p - pw;
17224       phts = lglhts (lgl, lit);
17225       pw = lglhts2wchs (lgl, phts);
17226       peow = pw + phts->count;
17227       p = pw + pdelta;
17228       ndelta = n - nw;
17229       nhts = lglhts (lgl, -lit);
17230       nw = lglhts2wchs (lgl, nhts);
17231       neow = nw + nhts->count;
17232       n = nw + ndelta;
17233     }
17234   }
17235 }
17236 
lglternresidx(LGL * lgl,int idx)17237 static void lglternresidx (LGL * lgl, int idx) {
17238   lglternreslit (lgl, idx);
17239   lglternreslit (lgl, -idx);
17240 }
17241 
lglseternreslim(LGL * lgl)17242 static void lglseternreslim (LGL * lgl) {
17243   int64_t limit, irrlim;
17244   int pen, szpen;
17245   if (lgl->opts->ternresrtc.val) {
17246     lgl->limits->ternres.steps = LLMAX;
17247     lglprt (lgl, 1,
17248        "[ternres-%d] really no limit (run to completion)",
17249        lgl->stats->ternres.count);
17250   } else {
17251     limit = (lgl->opts->trnreleff.val*lglvisearch (lgl))/1000;
17252     if (limit < lgl->opts->trnrmineff.val) limit = lgl->opts->trnrmineff.val;
17253     if (lgl->opts->trnrmaxeff.val >= 0 && limit > lgl->opts->trnrmaxeff.val)
17254       limit = lgl->opts->trnrmaxeff.val;
17255     if (lgl->stats->ternres.count <= 1 &&
17256         lgl->opts->boost.val &&
17257         lgl->opts->ternresboost.val > 1) {
17258       lglprt (lgl, 1,
17259         "[ternres-%d] boosting ternary resolution limit by %d",
17260 	lgl->stats->ternres.count, lgl->opts->ternresboost.val);
17261       limit *= lgl->opts->ternresboost.val;
17262     }
17263     limit >>= (pen = lgl->limits->ternres.pen + (szpen = lglszpen (lgl)));
17264     irrlim = (4*lgl->stats->irr.clauses.cur) >> szpen;
17265     if (lgl->opts->irrlim.val && limit < irrlim) {
17266       limit = irrlim;
17267       lglprt (lgl, 1,
17268   "[ternres-%d] limit %lld based on %d irredundant clauses penalty %d",
17269 	lgl->stats->ternres.count,
17270 	(LGLL) limit, lgl->stats->irr.clauses.cur, szpen);
17271     } else
17272       lglprt (lgl, 1, "[ternres-%d] limit %lld with penalty %d = %d + %d",
17273 	lgl->stats->ternres.count, (LGLL) limit,
17274 	pen, lgl->limits->ternres.pen, szpen);
17275     lgl->limits->ternres.steps = lgl->stats->ternres.steps + limit;
17276   }
17277 }
17278 
lglprternresrem(LGL * lgl)17279 static void lglprternresrem (LGL * lgl) {
17280   int idx, ret = 0, rem = 0, sum;
17281   for (idx = 2; idx < lgl->nvars; idx++) {
17282     if (!lglisfree (lgl, idx)) continue;
17283     if (lglavar (lgl, idx)->donoternres) ret++; else rem++;
17284   }
17285   if (rem) {
17286     sum = ret + rem;
17287     lglprt (lgl, 1,
17288       "[ternres-%d] %d variables remain %.0f%% (%d retained %.0f%%)",
17289       lgl->stats->ternres.count,
17290       rem, lglpcnt (rem, sum),
17291       ret, lglpcnt (ret, sum));
17292   } else {
17293     lglprt (lgl, 1,
17294       "[ternres-%d] fully completed ternary resolution",
17295       lgl->stats->ternres.count);
17296     for (idx = 2; idx < lgl->nvars; idx++)
17297       lglavar (lgl, idx)->donoternres = 0;
17298   }
17299 }
17300 
lglternresinit(LGL * lgl)17301 static void lglternresinit (LGL * lgl) {
17302   int idx, schedulable = 0, donoternres = 0;
17303   lglwrkinit (lgl, 1, 1);
17304   for (idx = 2; idx < lgl->nvars; idx++) {
17305     if (!lglisfree (lgl, idx)) continue;
17306     if (lglavar (lgl, idx)->donoternres) donoternres++;
17307     else schedulable++;
17308   }
17309   if (!schedulable) {
17310     donoternres = 0;
17311     for (idx = 2; idx < lgl->nvars; idx++) {
17312       if (!lglisfree (lgl, idx)) continue;
17313       lglavar (lgl, idx)->donoternres = 0;
17314       schedulable++;
17315     }
17316   }
17317   if (!donoternres)
17318     lglprt (lgl, 1,
17319       "[ternres-%d] all %d free variables schedulable",
17320       lgl->stats->ternres.count, schedulable);
17321   else
17322     lglprt (lgl, 1,
17323       "[ternres-%d] %d schedulable variables %.0f%%",
17324       lgl->stats->ternres.count, schedulable, lglpcnt (schedulable, lgl->nvars-2));
17325   assert (!lgl->donotsched), lgl->donotsched = 1;
17326   lglrandidxtrav (lgl, lglwrktouch);
17327   assert (lgl->donotsched), lgl->donotsched = 0;
17328 }
17329 
lglternres(LGL * lgl)17330 static int lglternres (LGL * lgl) {
17331   int before, after, delta;
17332   int before2, after2, delta2;
17333   int before3, after3, delta3;
17334   int success, lit;
17335   if (lgl->nvars <= 2) return 1;
17336   lglstart (lgl, &lgl->times->ternres);
17337   ASSERT (!lgl->simp && !lgl->ternresing);
17338   lgl->simp = lgl->ternresing = 1;
17339   lgl->stats->ternres.count++;
17340   if (lgl->level > 0) lglbacktrack (lgl, 0);
17341   lglseternreslim (lgl);
17342 
17343   lglternresinit (lgl);
17344 
17345   before2 = lgl->stats->ternres.bin;
17346   before3 = lgl->stats->ternres.trn;
17347   while (lgl->stats->ternres.steps < lgl->limits->ternres.steps) {
17348     if (lglterminate (lgl)) break;
17349     if (!lglsyncunits (lgl)) break;
17350     if (!(lit = lglwrknext (lgl))) {
17351       lglprt (lgl, 2,  "[ternres-%d] saturated", lgl->stats->ternres.count);
17352       break;
17353     }
17354     INCSTEPS (ternres.steps);
17355     assert (lit > 0);
17356     if (!lglisfree (lgl, lit)) continue;
17357     lglavar (lgl, lit)->donoternres = 1;
17358     lglternresidx (lgl, lit);
17359   }
17360   after2 = lgl->stats->ternres.bin;
17361   after3 = lgl->stats->ternres.trn;
17362   after = after2 + after3;
17363   before = before2 + before3;
17364   delta2 = after2 - before2;
17365   delta3 = after3 - before3;
17366   delta = after - before;
17367   success = before < after;
17368   lglprt (lgl, 1,
17369     "[ternres-%d] %d ternary resolvents (%d bin, %d trn)",
17370     lgl->stats->ternres.count, delta, delta2, delta3);
17371   LGLUPDPEN (ternres, success);
17372   assert (lgl->simp && lgl->ternresing);
17373   lgl->simp = lgl->ternresing = 0;
17374   lglprternresrem (lgl);
17375   lglrep (lgl, 2, 'T');
17376   lglwrkreset (lgl);
17377   lglstop (lgl);
17378   return !lgl->mt;
17379 }
17380 
17381 typedef struct POSLIDX { int pos, lidx; } POSLIDX;
17382 
lglcmposlidx(LGL * lgl,int * lits,POSLIDX * a,POSLIDX * b)17383 int lglcmposlidx (LGL * lgl, int * lits, POSLIDX * a, POSLIDX * b) {
17384   const int * c = lits + a->pos, * d = lits + b->pos;
17385   int i, l, k, p, q;
17386   for (i = 0; i < 4; i++) {
17387     l = c[i], k = d[i];
17388     ASSERT (l != INT_MIN);
17389     ASSERT (k != INT_MIN);
17390     p = abs (l), q = abs (k);
17391     if (p < q) return -1;
17392     if (p > q) return 1;
17393     if (l < k) return -1;
17394     if (l > k) return 1;
17395   }
17396   return 0;
17397 }
17398 
17399 #define LGLCMPOSLIDX(A,B) lglcmposlidx (lgl, lits.start, (A), (B))
17400 
lglquatres1(LGL * lgl,int * trnptr)17401 static int lglquatres1 (LGL * lgl, int * trnptr) {
17402   int mask, size, lidx, count, lrg, total, tlrg, pos, m[4], i, j, k, l, n;
17403   int glue, maxglue = lglscaleglue (lgl, 4), pivot, a, b, redi, redj, red;
17404   int assigned, trn, sub;
17405   const int * p, * c, * d;
17406   POSLIDX * pls;
17407   Stk lits, clauses, *s;
17408   assert (!lgl->level);
17409   assert (lgl->notrim);
17410   lglstart (lgl, &lgl->times->quatres1);
17411   CLR (lits); CLR (clauses);
17412   total = trn = sub = tlrg = 0;
17413   for (glue = -1; glue <= maxglue; glue++) {
17414     count = lrg = 0;
17415     if (glue < 0) mask = MAXGLUE, s = &lgl->irr;
17416     else mask = glue, s = lgl->red + glue;
17417     for (c = s->start; c < s->top; c = p + 1) {
17418       if (*c >= REMOVED) { p = c; continue; }
17419       if (glue >= 0) assert (lglisact (*c)), c++;
17420       assigned = 0;
17421       for (p = c; *p; p++)
17422 	if (lglval (lgl, *p)) assigned++;
17423       if (assigned) continue;
17424       size = p - c;
17425       lrg++;
17426       if (size > 4) continue;
17427       assert (size == 4);
17428       lidx = c - s->start;
17429       assert (lidx >= 0);
17430       lidx <<= GLUESHFT;
17431       lidx |= mask;
17432       pos = lglcntstk (&lits);
17433       assert (!(pos & 3));
17434       lglpushstk (lgl, &clauses, pos);
17435       lglpushstk (lgl, &clauses, lidx);
17436       for (i = 0; i < 4; i++) m[i] = c[i];
17437       for (i = 0; i < 3; i++)
17438 	for (j = i+1; j < 4; j++)
17439 	  if (abs (m[i]) > abs (m[j]))
17440 	    SWAP (int, m[i], m[j]);
17441       for (i = 0; i < 4; i++) lglpushstk (lgl, &lits, m[i]);
17442       count++;
17443     }
17444     if (glue < 0)
17445       lglprt (lgl, 2,
17446 	"[quatres-%d] found %d irredundant quaternary clauses %.0f%%",
17447 	lgl->stats->quatres.count, count, lglpcnt (count, lrg));
17448     else
17449       lglprt (lgl, 2,
17450 	"[quatres-%d] found %d glue %d quaternary clauses %.0f%%",
17451 	lgl->stats->quatres.count, count, glue, lglpcnt (count, lrg));
17452     total += count;
17453     tlrg += lrg;
17454   }
17455   lglfitstk (lgl, &lits), lglfitstk (lgl, &clauses);
17456   lglprt (lgl, 1 + !tlrg,
17457     "[quatres-%d] found %d quaternary clauses %.0f%% in total",
17458     lgl->stats->quatres.count, total, lglpcnt (total, tlrg));
17459   pls = (POSLIDX*) clauses.start;
17460   assert (lglcntstk (&clauses) == 2*total);
17461   SORT (POSLIDX, pls, total, LGLCMPOSLIDX);
17462 #if 0
17463   for (i = 0; i < total; i++) {
17464     c = lits.start + pls[i].pos;
17465     lidx = pls[i].lidx;
17466     printf ("c pls[%d] %d %d %d %d (glue %d, pos %d)\n",
17467       i,
17468       c[0], c[1], c[2], c[3],
17469       (lidx & GLUEMASK), (lidx >> GLUESHFT));
17470   }
17471 #endif
17472   for (i = 0; i < total - 1; i++) {
17473     pos = pls[i].pos;
17474     if (pos < 0) continue;
17475     c = lits.start + pos;
17476     for (j = i + 1; j < total; j++) {
17477       if (pls[i].pos < 0) break;
17478       pos = pls[j].pos;
17479       if (pos < 0) break;
17480       d = lits.start + pos;
17481       pivot = 0;
17482       for (k = 0; k < 4; k++) {
17483 	a = c[k], b = d[k];
17484 	if (abs (a) != abs (b)) break;
17485 	if (a == b) continue;
17486 	if (pivot) break;
17487 	pivot = a;
17488       }
17489       if (k < 4) break;
17490       assert (i != j);
17491       assert (pls[i].lidx != pls[j].lidx);
17492       redi = ((pls[i].lidx & GLUEMASK) == MAXGLUE) ? 0 : REDCS;
17493       redj = ((pls[j].lidx & GLUEMASK) == MAXGLUE) ? 0 : REDCS;
17494       if (pivot) {
17495 	n = 0;
17496 	for (l = 0; l < 4; l++) if (c[l] != pivot) m[n++] = c[l];
17497 	assert (n == 3);
17498 	if (lglhastrn (lgl, m[0], m[1], m[2])) continue;
17499 	red = redi & redj;
17500 	LOG (2,
17501 	  "self-subsuming %s ternary resolvent %d %d %d",
17502 	  red ? "redundant" : "irredundant", m[0], m[1], m[2]);
17503 	lgldrupligaddclsarg (lgl, REDCS, m[0], m[1], m[2], 0);
17504 	lglwchtrn (lgl, m[0], m[1], m[2], red);
17505 	lglwchtrn (lgl, m[1], m[0], m[2], red);
17506 	lglwchtrn (lgl, m[2], m[0], m[1], red);
17507 	if (!red) lglincirr (lgl, 3);
17508 	else lgl->stats->red.trn++, assert (lgl->stats->red.trn > 0);
17509 	lgl->stats->quatres.self2++;
17510 	*trnptr += 1, trn++;
17511 	lgldrupligdelclsarg (lgl, c[0], c[1], c[2], c[3], 0);
17512 	if (redi) lglrmlcls (lgl, pls[i].lidx, REDCS);
17513 	else lglrmlcls (lgl, (pls[i].lidx >> GLUESHFT), 0);
17514 	lgldrupligdelclsarg (lgl, d[0], d[1], d[2], d[3], 0);
17515 	if (redj) lglrmlcls (lgl, pls[j].lidx, REDCS);
17516 	else lglrmlcls (lgl, (pls[j].lidx >> GLUESHFT), 0);
17517 	pls[i].pos = pls[j].pos = -1;
17518       } else if (redi) {
17519 	lgl->stats->quatres.dup++, sub++;
17520 	lgldrupligdelclsarg (lgl, c[0], c[1], c[2], c[3], 0);
17521         lglrmlcls (lgl, pls[i].lidx, REDCS);
17522 	pls[i].pos = -1;
17523       } else if (redj) {
17524 	lgl->stats->quatres.dup++;
17525 	lgldrupligdelclsarg (lgl, d[0], d[1], d[2], d[3], 0);
17526 	lglrmlcls (lgl, pls[j].lidx, REDCS);
17527 	pls[j].pos = -1;
17528       } else {
17529 	lgl->stats->quatres.dup++;
17530 	lgldrupligdelclsarg (lgl, d[0], d[1], d[2], d[3], 0);
17531 	lglrmlcls (lgl, (pls[j].lidx >> GLUESHFT), 0);
17532 	pls[j].pos = -1;
17533       }
17534     }
17535   }
17536   lglrelstk (lgl, &lits), lglrelstk (lgl, &clauses);
17537   lglprt (lgl, 1 + !sub,
17538     "[quatres-%d-1] removed %d duplicate quaternary clauses",
17539     lgl->stats->quatres.count, sub);
17540   lglprt (lgl, 1 + !trn,
17541     "[quatres-%d-1] added %d double-self-subsuming ternary resolvents",
17542     lgl->stats->quatres.count, trn);
17543   lglstop (lgl);
17544   return tlrg;
17545 }
17546 
lglhasquad(LGL * lgl)17547 static int lglhasquad (LGL * lgl) {
17548   int blit, tag, red, other, other2, lidx, glue, count, lit, other3, val;
17549   const int * p, * w, * eow, * q, * c, * d, * r, * l;
17550   int maxglue = lglscaleglue (lgl, 4);
17551   int maxcount, tmpcount, maxlit;
17552   HTS * hts;
17553   assert (lglcntstk (&lgl->clause) == 5);
17554   maxcount = -1, maxlit = 0;
17555   for (p = (c = lgl->clause.start); (lit = *p); p++) {
17556     assert (!lglval (lgl, lit));
17557     tmpcount = lglhts (lgl, lit)->count;
17558     if (tmpcount <= maxcount) continue;
17559     maxcount = tmpcount, maxlit = lit;
17560   }
17561   assert (maxlit), assert (maxcount >= 0);
17562   for (p = c; (lit = *p); p++) {
17563     if (lit == maxlit) continue;
17564     hts = lglhts (lgl, lit);
17565     w = lglhts2wchs (lgl, hts);
17566     eow = w + hts->count;
17567     for (q = w; q < eow; q++) {
17568       blit = *q;
17569       tag = blit & MASKCS;
17570       if (tag == BINCS) {
17571 	other = blit >> RMSHFT;
17572 	for (r = c; (other3 = *r); r++)
17573 	  if (other3 == other) return 1;
17574       } else if (tag == TRNCS) {
17575 	other = blit >> RMSHFT;
17576 	other2 = *++q;
17577 	count = 0;
17578 	for (r = c; (other3 = *r); r++) {
17579 	       if (other3 == other) { if (++count == 2) return 1; }
17580 	  else if (other3 == other2) { if (++count == 2) return 1; }
17581 	}
17582       } else {
17583 	assert (tag == LRGCS);
17584 	red = blit & REDCS;
17585 	lidx = *++q;
17586 	if (red) {
17587 	  glue = lidx & GLUEMASK;
17588 	  if (glue > maxglue) continue;
17589 	}
17590 	d = lglidx2lits (lgl, red, lidx);
17591 	count = 0;
17592 	for (l = d; (other = *l); l++) {
17593 	  val = lglval (lgl, other);
17594 	  if (val > 0) break;
17595 	  if (val < 0) continue;
17596 	  if (count >= 4) break;
17597 	  for (r = c; (other3 = *r); r++)
17598 	    if (other3 == other) break;
17599 	  if (!other3) break;
17600 	  count++;
17601 	}
17602 	if (!other) return 1;
17603       }
17604     }
17605   }
17606   return 0;
17607 }
17608 
lglquatres2(LGL * lgl,int * trnptr,int * quadptr)17609 static void lglquatres2 (LGL * lgl, int * trnptr, int * quadptr) {
17610   int lit, sign, other, blit, tag, red, lidx, trn, quat, glue, glue2;
17611   int count, pos, neg, extra, pivot, other2, other3, rednew;
17612   const int * start, * c, * p, * w, * eow, * q, * d, * l;
17613   int maxcheck = lgl->stats->quatres.count, check;
17614   int maxglue = lglscaleglue (lgl, 4), val;
17615   long delta;
17616   HTS * hts;
17617   Stk * s;
17618   lglstart (lgl, &lgl->times->quatres2);
17619   assert (!lgl->level);
17620   assert (lgl->notrim);
17621   trn = quat = 0;
17622   for (glue = -1; glue <= maxglue; glue++) {
17623     s = (glue < 0) ? &lgl->irr : lgl->red + glue;
17624     for (c = (start = s->start); c < s->top; c = p + 1) {
17625       if (*c >= REMOVED) { p = c; continue; }
17626       if (glue >= 0) assert (lglisact (*c)), c++;
17627       count = 0;
17628       for (p = c; (lit = *p); p++) {
17629 	val = lglval (lgl, lit);
17630 	if (val < 0) continue;
17631 	if (val > 0) break;
17632 	if (++count > 4) break;
17633       }
17634       if (lit) {
17635 	while (*++p)
17636 	  ;
17637 	continue;
17638       }
17639       assert (count <= 4);
17640       if (count < 4) continue;
17641       for (p = c; (lit = *p); p++)
17642 	if (!lglval (lgl, lit))
17643 	  lglmark (lgl, lit);
17644       for (p = c; (lit = *p); p++) {
17645 	if (lglval (lgl, lit)) continue;
17646 	for (sign = -1; sign <= 1; sign += 2) {
17647 	  hts = lglhts (lgl, sign*lit);
17648 	  w = lglhts2wchs (lgl, hts);
17649 	  eow = w + hts->count;
17650 	  check = 0;
17651 	  for (q = w; check < maxcheck && q < eow; q++) {
17652 	    blit = *q;
17653 	    tag = blit & MASKCS;
17654 	    red = blit & REDCS;
17655 	    if (tag == TRNCS || tag == LRGCS) q++;
17656 	    if (maxglue < MAXGLUE && tag == LRGCS) {
17657 	      lidx = *q;
17658 	      if (red) {
17659 		glue2 = lidx & GLUEMASK;
17660 		if (glue2 > maxglue) continue;
17661 	      } else glue2 = -1;
17662 	      if (glue2 < glue) continue;
17663 	      d = lglidx2lits (lgl, red, lidx);
17664 	      if (d == c) continue;
17665 	      if (glue2 == glue && d < c) continue;
17666 	      check++;
17667 	      count = pos = neg = extra = pivot = 0;
17668 	      for (l = d; (other = *l); l++) {
17669 		val = lglval (lgl, other);
17670 		if (val < 0) continue;
17671 		if (val > 0) break;
17672 		val = lglmarked (lgl, other);
17673 		if (val < 0) {
17674 		  if (neg++) break;
17675 		  pivot = other;
17676 		} else if (val > 0) {
17677 		   if (++pos > 2) break;
17678 		} else {
17679 		  assert (!val);
17680 		  if (count++) break;
17681 		  extra = other;
17682 		}
17683 	      }
17684 	      if (other) continue;
17685 	      if (neg != 1 || pos != 2 || count != 1) continue;
17686 	      assert (extra);
17687 	      assert (lglmtstk (&lgl->clause));
17688 	      for (l = c; (other = *l); l++) {
17689 		if (lglval (lgl, other)) continue;
17690 		if (other == pivot) continue;
17691 		if (other == -pivot) continue;
17692 		lglpushstk (lgl, &lgl->clause, other);
17693 	      }
17694 	      lglpushstk (lgl, &lgl->clause, extra);
17695 	      lglpushstk (lgl, &lgl->clause, 0);
17696 	      if (!lglhasquad (lgl)) {
17697 		LOGCLS (0, c,
17698 		  "1st pivot %d quaternary scaled glue %d antecedent",
17699 		  -pivot, glue);
17700 		LOGCLS (0, d,
17701 		  "2nd pivot %d quaternary scaled glue %d antecedent",
17702 		  pivot, glue2);
17703 		LOGCLS (0, lgl->clause.start, "found quaternary resolvent");
17704 		LOG (5, "before: w + %d = q = eow - %d", (int)(q - w), (int)(eow - w));
17705 		lgldrupligaddcls (lgl, REDCS);
17706 		lgladdcls (lgl, REDCS, 4, 0);
17707 		delta = s->start - start;
17708 		if (delta) {
17709 		  LOG (5, "fixing glue %d clauses start by %ld", glue, delta);
17710 		  c += delta, p += delta, start = s->start;
17711 		}
17712 		hts = lglhts (lgl, sign*lit);
17713 		delta = lglhts2wchs (lgl, hts) - w;
17714 		if (delta) {
17715 		  LOG (5, "fixing %d watches start by %ld", sign*lit, delta);
17716 		  w += delta, q += delta;
17717 		}
17718 		if (w + hts->count != eow) {
17719 		  LOG (5, "fixing %d watches end from %x to %x",
17720 		    sign*lit, eow, w + hts->count);
17721 		  eow = w + hts->count;
17722 		}
17723 		LOG (5, "after: w + %d = q = eow - %d", (int)(q - w), (int)(eow - w));
17724 		lgl->stats->quatres.quat++;
17725 		*quadptr += 1, quat++;
17726 	      }
17727 	      lglclnstk (&lgl->clause);
17728 	    } else if (tag == TRNCS) {
17729 	      if (sign > 0) continue;
17730 	      other = blit >> RMSHFT;
17731 	      if (lglval (lgl, other)) continue;
17732 	      if (lglmarked (lgl, other) <= 0) continue;
17733 	      other2 = *q;
17734 	      if (lglval (lgl, other2)) continue;
17735 	      if (lglmarked (lgl, other2) <= 0) continue;
17736 	      // This gives a usefull ternary self-subsuming resolvent:
17737 	      // (lit A B C) resolved with (-lit A B) gives (A B C)
17738 	      // Other cases produce too many quaternary resolvents (b7ztz6).
17739 	      LOGCLS (0, c,
17740 		"1st pivot %d quaternary scaled glue %d antecedent",
17741 		lit, glue);
17742 	      LOG (0,
17743 	        "2nd pivot %d ternary antecedent %d %d %d",
17744 		-lit, -lit, other, other2);
17745 	      extra = 0;
17746 	      for (l = c; !extra; l++) {
17747 		other3 = *l;
17748 		assert (other3);
17749 		if (other3 == lit) continue;
17750 		assert (other3 != -lit);
17751 		if (other3 == other) continue;
17752 		if (other3 == other2) continue;
17753 		val = lglval (lgl, other3);
17754 		assert (val <= 0);
17755 		if (val) continue;
17756 		extra = other3;
17757 	      }
17758 	      assert (extra != -other);
17759 	      assert (extra != -other2);
17760 	      rednew = (glue >= 0) ? REDCS : 0;
17761 	      LOG (0,
17762 		"self-subsuming %s ternary resolvent %d %d %d",
17763 		rednew ? "redundant" : "irredundant", other, other2, extra);
17764 	      lgldrupligaddclsarg (lgl, REDCS, other, other2, extra, 0);
17765 	      lglwchtrn (lgl, other, other2, extra, rednew);
17766 	      lglwchtrn (lgl, other2, other, extra, rednew);
17767 	      lglwchtrn (lgl, extra, other, other2, rednew);
17768 	      // NOTE: 'hts', 'q', 'w', 'eow' might be invalid now.
17769 	      // But 'c' has to remain valid:
17770 	      assert (s->start == start), assert (c + 4 < s->top);
17771 	      if (!rednew) lglincirr (lgl, 3);
17772 	      else lgl->stats->red.trn++, assert (lgl->stats->red.trn > 0);
17773 	      lgl->stats->quatres.self1++;
17774 	      *trnptr += 1, trn++;
17775 	      for (p = c; (other3 = *p); p++)	// set 'p' to point after 'c'
17776 		if (!lglval (lgl, other3))	// reset marks now because
17777 		  lglunmark (lgl, other3);	// 'lglrmlcls' invalidates 'c'
17778 	      lidx = c - start;
17779 	      if (rednew) {
17780 		assert (lidx >= 0);
17781 		lidx <<= GLUESHFT;
17782 		assert (lidx >= 0);
17783 		assert (0 <= glue), assert (glue <= MAXGLUE);
17784 		lidx |= glue;
17785 	      }
17786 	      lgldrupligdelclsaux (lgl, c);
17787 	      assert (!*p);
17788 	      lglrmlcls (lgl, lidx, rednew);	// rednew = redold (of 'c')
17789 	      assert (start <= c), assert (c + 3 < p), assert (p <= s->top);
17790 	      assert (p[-0] == REMOVED);
17791 	      assert (p[-1] == REMOVED);
17792 	      assert (p[-2] == REMOVED);
17793 	      assert (p[-3] == REMOVED);
17794 	      assert (p[-4] == REMOVED), assert (c[0] == REMOVED);
17795 	      goto NEXT_CLAUSE;
17796 	    }
17797 	  }
17798 	}
17799       }
17800       for (p = c; (lit = *p); p++)
17801 	if (!lglval (lgl, lit))
17802 	  lglunmark (lgl, lit);
17803 NEXT_CLAUSE:
17804       ;
17805     }
17806   }
17807   lglprt (lgl, 1 + !trn,
17808     "[quatres-%d-2] added %d single-self-subsuming ternary resolvents",
17809     lgl->stats->quatres.count, trn);
17810   lglprt (lgl, 1 + !quat,
17811     "[quatres-%d-2] added %d quaternary resolvents",
17812     lgl->stats->quatres.count, quat);
17813   lglstop (lgl);
17814 }
17815 
lglquatres(LGL * lgl)17816 static void lglquatres (LGL * lgl) {
17817   int trn, quad;
17818   lglstart (lgl, &lgl->times->quatres);
17819   if (lgl->level) lglbacktrack (lgl, 0);
17820   assert (!lgl->simp), assert (!lgl->quatres), assert (!lgl->notrim);
17821   lgl->simp = lgl->quatres = lgl->notrim = 1;
17822   lgl->stats->quatres.count++;
17823   trn = quad = 0;
17824   if (lglquatres1 (lgl, &trn)) lglquatres2 (lgl, &trn, &quad);
17825   LGLUPDPEN (quatres, trn + quad);
17826   assert (lgl->simp), assert (lgl->quatres), assert (lgl->notrim);
17827   lgl->simp = lgl->quatres = lgl->notrim = 0;
17828   lglrep (lgl, 2, 'q');
17829   lglstop (lgl);
17830 }
17831 
lgltrdbin(LGL * lgl,int start,int target,int irr)17832 static int lgltrdbin (LGL * lgl, int start, int target, int irr) {
17833   int lit, next, blit, tag, red, other, * p, * w, * eow, res, ign, val;
17834   HTS * hts;
17835   assert (lglmtstk (&lgl->seen));
17836   assert (abs (start) < abs (target));
17837   LOG (2, "trying transitive reduction of %s binary clause %d %d",
17838        lglred2str (irr^REDCS), start, target);
17839   lgl->stats->trd.bins++;
17840   lglpushnmarkseen (lgl, -start);
17841   next = 0;
17842   res = 0;
17843   ign = 1;
17844   while (next < lglcntstk (&lgl->seen)) {
17845     lit = lglpeek (&lgl->seen, next++);
17846     INCSTEPS (trd.steps);
17847     LOG (3, "transitive reduction search step %d", lit);
17848     val = lglval (lgl, lit);
17849     if (val) continue;
17850     hts = lglhts (lgl, -lit);
17851     if (!hts->count) continue;
17852     w = lglhts2wchs (lgl, hts);
17853     eow = w + hts->count;
17854     for (p = w; p < eow; p++) {
17855       blit = *p;
17856       tag = blit & MASKCS;
17857       if (tag == LRGCS || tag == TRNCS) p++;
17858       if (tag != BINCS) continue;
17859       red = blit & REDCS;
17860       if (irr && red) continue;
17861       other = blit >> RMSHFT;
17862       if (other == start) continue;
17863       if (other == target) {
17864 	if (lit == -start && ign) { ign = 0; continue; }
17865 	LOG (2, "transitive path closed with %s binary clause %d %d",
17866 	     lglred2str (red), -lit, other);
17867 	res = 1;
17868 	goto DONE;
17869       }
17870       val = lglmarked (lgl, other);
17871       if (val > 0) continue;
17872       if (val < 0) {
17873 	assert (lgl->level == 0);
17874 	lgl->stats->trd.failed++;
17875 	LOG (1, "failed literal %d in transitive reduction", -start);
17876 	lglunit (lgl, start);
17877 	val = lglbcp (lgl);
17878 	if (!val && !lgl->mt) lglmt (lgl);
17879 	assert (val || lgl->mt);
17880 	res = -1;
17881 	goto DONE;
17882       }
17883       lglpushnmarkseen (lgl, other);
17884       LOG (3, "transitive reduction follows %s binary clause %d %d",
17885 	   lglred2str (red), -lit, other);
17886     }
17887   }
17888 DONE:
17889   lglpopnunmarkstk (lgl, &lgl->seen);
17890   return res;
17891 }
17892 
lgltrdlit(LGL * lgl,int start)17893 static void lgltrdlit (LGL * lgl, int start) {
17894   int target, * w, * p, * eow, blit, tag, red, val;
17895 #ifndef NDEBUG
17896   int unassigned = lgl->unassigned;
17897 #endif
17898   HTS * hts;
17899   val = lglval (lgl, start);
17900   if (val) return;
17901   LOG (2, "transitive reduction of binary clauses with %d", start);
17902   assert (lglmtstk (&lgl->seen));
17903   hts = lglhts (lgl, start);
17904   if (!hts->count) return;
17905   lgl->stats->trd.lits++;
17906   w = lglhts2wchs (lgl, hts);
17907   eow = w + hts->count;
17908   for (p = w;
17909        p < eow && (lgl->stats->trd.steps < lgl->limits->trd.steps);
17910        p++) {
17911     blit = *p;
17912     tag = blit & MASKCS;
17913     if (tag == TRNCS || tag == LRGCS) p++;
17914     if (tag != BINCS) continue;
17915     target = blit >> RMSHFT;
17916     if (abs (start) > abs (target)) continue;
17917     red = blit & REDCS;
17918     val = lgltrdbin (lgl, start, target, red^REDCS);
17919     if (!val) continue;
17920     if (val < 0) { assert (lgl->mt || lgl->unassigned < unassigned); break; }
17921     LOG (2, "removing transitive redundant %s binary clause %d %d",
17922 	 lglred2str (red), start, target);
17923     lgl->stats->trd.red++;
17924     lgl->stats->prgss++;
17925     lgldrupligdelclsarg (lgl, start, target, 0);
17926     lglrmbwch (lgl, start, target, red);
17927     lglrmbwch (lgl, target, start, red);
17928     assert (!lgl->dense);
17929     if (red) assert (lgl->stats->red.bin > 0), lgl->stats->red.bin--;
17930     else lgldecirr (lgl, 2);
17931     break;
17932   }
17933 }
17934 
lglsetrdlim(LGL * lgl)17935 static void lglsetrdlim (LGL * lgl) {
17936   int64_t limit, irrlim;
17937   int pen, szpen;
17938   limit = (lgl->opts->trdreleff.val*lglvisearch (lgl))/1000;
17939   if (limit < lgl->opts->trdmineff.val) limit = lgl->opts->trdmineff.val;
17940   if (lgl->opts->trdmaxeff.val >= 0 && limit > lgl->opts->trdmaxeff.val)
17941     limit = lgl->opts->trdmaxeff.val;
17942   limit >>= (pen = lgl->limits->trd.pen + (szpen = lglszpen (lgl)));
17943   irrlim = (lgl->stats->irr.clauses.cur) >> szpen;
17944   if (lgl->opts->irrlim.val && limit < irrlim) {
17945     limit = irrlim;
17946     lglprt (lgl, 1,
17947   "[transred-%d] limit %lld based on %d irredundant clauses penalty %d",
17948       lgl->stats->trd.count,
17949       (LGLL) limit, lgl->stats->irr.clauses.cur, szpen);
17950   } else
17951     lglprt (lgl, 1, "[transred-%d] limit %lld with penalty %d = %d + %d",
17952       lgl->stats->trd.count, (LGLL) limit,
17953       pen, lgl->limits->trd.pen, szpen);
17954   lgl->limits->trd.steps = lgl->stats->trd.steps + limit;
17955 }
17956 
lgltrd(LGL * lgl)17957 static int lgltrd (LGL * lgl) {
17958   unsigned pos, delta, mod, ulit, first, last;
17959   int failed = lgl->stats->trd.failed;
17960   int red = lgl->stats->trd.red;
17961   int lit, count, success;
17962   if (lgl->nvars <= 2) return 1;
17963   lgl->stats->trd.count++;
17964   lglstart (lgl, &lgl->times->transred);
17965   assert (!lgl->simp);
17966   lgl->simp = 1;
17967   if (lgl->level > 0) lglbacktrack (lgl, 0);
17968   lglsetrdlim (lgl);
17969   mod = 2*(lgl->nvars - 2);
17970   assert (mod > 0);
17971   pos = lglrand (lgl) % mod;
17972   delta = lglrand (lgl) % mod;
17973   if (!delta) delta++;
17974   while (lglgcd (delta, mod) > 1)
17975     if (++delta == mod) delta = 1;
17976   LOG (1, "transitive reduction start %u delta %u mod %u", pos, delta, mod);
17977   first = mod;
17978   count = 0;
17979   while (lgl->stats->trd.steps < lgl->limits->trd.steps) {
17980     if (lglterminate (lgl)) break;
17981     if (!lglsyncunits (lgl)) break;
17982     ulit = pos + 4;
17983     lit = lglilit (ulit);
17984     lgltrdlit (lgl, lit);
17985     count++;
17986     assert (count <= mod);
17987     if (lgl->mt) break;
17988     last = pos;
17989     pos += delta;
17990     if (pos >= mod) pos -= mod;
17991     if (pos == first) { assert (count == mod); break; }
17992     if (mod == 1) break;
17993     if (first == mod) first = last;
17994   }
17995   failed = lgl->stats->trd.failed - failed;
17996   red = lgl->stats->trd.red - red;
17997   success = failed || red;
17998   LGLUPDPEN (trd, success);
17999   assert (lgl->simp);
18000   lglprt (lgl, 1,
18001     "[transred-%d] removed %d transitive binary clauses",
18002     lgl->stats->trd.count, red);
18003   lglprt (lgl, 1 + !failed,
18004     "[transred-%d] found %d units",
18005     lgl->stats->trd.count, failed);
18006   lgl->simp = 0;
18007   lglrep (lgl, 2, 'D');
18008   lglstop (lgl);
18009   return !lgl->mt;
18010 }
18011 
lglunhdhasbins(LGL * lgl,const DFPR * dfpr,int lit,int irronly)18012 static int lglunhdhasbins (LGL * lgl, const DFPR * dfpr,
18013 			   int lit, int irronly) {
18014   int blit, tag, other, val, red, ulit;
18015   const int * p, * w, * eos;
18016   HTS * hts;
18017   assert (!lglval (lgl, lit));
18018   hts = lglhts (lgl, lit);
18019   w = lglhts2wchs (lgl, hts);
18020   eos = w + hts->count;
18021   for (p = w; p < eos; p++) {
18022     blit = *p;
18023     tag = blit & MASKCS;
18024     if (tag == OCCS) continue;
18025     if (tag == TRNCS || tag == LRGCS) { p++; continue; }
18026     red = blit & REDCS;
18027     if (irronly && red) continue;
18028     other = blit >> RMSHFT;
18029     val = lglval (lgl, other);
18030     assert (val >= 0);
18031     if (val > 0) continue;
18032     ulit = lglulit (other);
18033     if (!dfpr[ulit].discovered) return 1;
18034   }
18035   return 0;
18036 }
18037 
lglunhdisroot(LGL * lgl,int lit,DFPR * dfpr,int irronly)18038 static int lglunhdisroot (LGL * lgl, int lit, DFPR * dfpr, int irronly) {
18039   int res = !lglunhdhasbins (lgl, dfpr, lit, irronly);
18040   assert (!res || !dfpr[lglulit (lit)].discovered);
18041   return res;
18042 }
18043 
lglmtwtk(Wtk * wtk)18044 static int lglmtwtk (Wtk * wtk) { return wtk->top == wtk->start; }
18045 
lglfullwtk(Wtk * wtk)18046 static int lglfullwtk (Wtk * wtk) { return wtk->top == wtk->end; }
18047 
lglsizewtk(Wtk * wtk)18048 static int lglsizewtk (Wtk * wtk) { return wtk->end - wtk->start; }
18049 
lglcntwtk(Wtk * wtk)18050 static int lglcntwtk (Wtk * wtk) { return wtk->top - wtk->start; }
18051 
lglrelwtk(LGL * lgl,Wtk * wtk)18052 static void lglrelwtk (LGL * lgl, Wtk * wtk) {
18053   DEL (wtk->start, lglsizewtk (wtk));
18054   memset (wtk, 0, sizeof *wtk);
18055 }
18056 
lglenlwtk(LGL * lgl,Wtk * wtk)18057 static void lglenlwtk (LGL * lgl, Wtk * wtk) {
18058   int oldsize = lglsizewtk (wtk);
18059   int newsize = oldsize ? 2*oldsize : 1;
18060   int count = lglcntwtk (wtk);
18061   RSZ (wtk->start, oldsize, newsize);
18062   wtk->top = wtk->start + count;
18063   wtk->end = wtk->start + newsize;
18064 }
18065 
lglpushwtk(LGL * lgl,Wtk * wtk,Wrag wrag,int lit,int other,int red)18066 static void lglpushwtk (LGL * lgl, Wtk * wtk,
18067 			Wrag wrag, int lit, int other, int red) {
18068   Work w;
18069   if (lglfullwtk (wtk)) lglenlwtk (lgl, wtk);
18070   w.wrag = wrag;
18071   w.other = other;
18072   w.red = red ? 1 : 0;
18073   w.removed = 0;
18074   w.lit = lit;
18075   *wtk->top++ = w;
18076 }
18077 
lglstamp(LGL * lgl,int root,DFPR * dfpr,DFOPF * dfopf,Wtk * work,Stk * units,Stk * sccs,Stk * trds,int * visitedptr,int stamp,int irronly)18078 static int lglstamp (LGL * lgl, int root,
18079 		     DFPR * dfpr, DFOPF * dfopf,
18080 		     Wtk * work, Stk * units, Stk * sccs, Stk * trds,
18081 		     int * visitedptr, int stamp, int irronly) {
18082   int uroot, lit, ulit, blit, tag, red, other, failed, uother, unotother;
18083   int observed, discovered, pos, undiscovered;
18084   unsigned start, end, mod, i, j, sccsize;
18085   const int * p, * w, * eos;
18086   int startstamp;
18087   const Work * r;
18088   int removed;
18089   HTS * hts;
18090   Wrag wrag;
18091   if (lglval (lgl, root)) return stamp;
18092   uroot =  lglulit (root);
18093   if (dfpr[uroot].discovered) return stamp;
18094   assert (!dfpr[uroot].finished);
18095   assert (lglmtwtk (work));
18096   assert (lglmtstk (units));
18097   assert (lglmtstk (sccs));
18098   assert (lglmtstk (trds));
18099   LOG (3, "stamping dfs %s %d %s",
18100        (lglunhdisroot (lgl, root, dfpr, irronly) ? "root" : "start"), root,
18101        irronly ? "only over irredundant clauses" :
18102 		 "also over redundant clauses");
18103   startstamp = 0;
18104   lglpushwtk (lgl, work, PREFIX, root, 0, 0);
18105   while (!lglmtwtk (work)) {
18106     INCSTEPS (unhd.steps);
18107     LGLPOPWTK (work, wrag, lit, other, red, removed);
18108     if (removed) continue;
18109     if (wrag == PREFIX) {
18110       ulit = lglulit (lit);
18111       if (dfpr[ulit].discovered) {
18112 	dfopf[ulit].observed = stamp;
18113 	LOG (3, "stamping %d observed %d", lit, stamp);
18114 	continue;
18115       }
18116       assert (!dfpr[ulit].finished);
18117       dfpr[ulit].discovered = ++stamp;
18118       dfopf[ulit].observed = stamp;
18119       LOG (3, "stamping %d observed %d", lit, stamp);
18120       *visitedptr += 1;
18121       if (!startstamp) {
18122 	startstamp = stamp;
18123 	LOG (3, "root %d with stamp %d", lit, startstamp);
18124 	dfpr[ulit].root = lit;
18125 	LOG (4, "stamping %d root %d", lit, lit);
18126 	assert (!dfpr[ulit].parent);
18127 	LOG (4, "stamping %d parent %d", lit, 0);
18128       }
18129       LOG (4, "stamping %d discovered %d", lit, stamp);
18130       lglpushwtk (lgl, work, POSTFIX, lit, 0, 0);
18131       assert (dfopf[ulit].pushed < 0);
18132       dfopf[ulit].pushed = lglcntwtk (work);
18133       assert (!dfopf[ulit].flag);
18134       dfopf[ulit].flag = 1;
18135       lglpushstk (lgl, sccs, lit);
18136       hts = lglhts (lgl, -lit);
18137       w = lglhts2wchs (lgl, hts);
18138       eos = w + hts->count;
18139       for (undiscovered = 0; undiscovered <= 1 ; undiscovered++) {
18140 	start = lglcntwtk (work);
18141 	for (p = w; p < eos; p++) {
18142 	  blit = *p;
18143 	  tag = blit & MASKCS;
18144 	  if (tag == OCCS) continue;
18145 	  if (tag == TRNCS || tag == LRGCS) { p++; continue; }
18146 	  assert (tag == BINCS);
18147 	  red = blit & REDCS;
18148 	  if (irronly && red) continue;
18149 	  other = blit >> RMSHFT;
18150 	  if (lglval (lgl, other)) continue;
18151 	  uother = lglulit (other);
18152 	  if (undiscovered != !dfpr[uother].discovered) continue;
18153 	  // Kind of defensive, since 'lglrmbindup' should avoid it
18154 	  // and this fix may not really work anyhow since it does
18155 	  // not distinguish between irredundant and redundant clauses.
18156 	  // Thus we put a hard COVER here.
18157 	  COVER (lglsignedmarked (lgl, other) > 0);
18158 	  if (lglsignedmarked (lgl, other) > 0) {
18159 	    LOG (2, "stamping skips duplicated edge %d %d", lit, other);
18160 	    continue;
18161 	  }
18162 	  lglsignedmark (lgl, other);
18163 	  lglpushwtk (lgl, work, BEFORE, lit, other, red);
18164 	}
18165 	end = lglcntwtk (work);
18166 	for (r = work->start + start; r < work->top; r++)
18167 	  lglunmark (lgl, r->other);
18168 	mod = (end - start);
18169 	if (mod <= 1) continue;
18170 	for (i = start; i < end - 1;  i++) {
18171 	  assert (1 < mod && mod == (end - i));
18172 	  j = lglrand (lgl) % mod--;
18173 	  if (!j) continue;
18174 	  j = i + j;
18175 	  SWAP (Work, work->start[i], work->start[j]);
18176 	}
18177       }
18178     } else if (wrag == BEFORE) {	// before recursive call
18179       LOG (2, "stamping edge %d %d before recursion", lit, other);
18180       lglpushwtk (lgl, work, AFTER, lit, other, red);
18181       ulit = lglulit (lit);
18182       uother = lglulit (other);
18183       unotother = lglulit (-other);
18184       if (lgl->opts->unhdextstamp.val && (irronly || red) &&
18185 	  dfopf[uother].observed > dfpr[ulit].discovered) {
18186 	LOG (2, "transitive edge %d %d during stamping", lit, other);
18187 	lgl->stats->unhd.stamp.trds++;
18188 	lgl->stats->prgss++;
18189 	if (red) lgl->stats->unhd.tauts.red++;
18190 	lglrmbcls (lgl, -lit, other, red);
18191 	if ((pos = dfopf[unotother].pushed) >= 0) {
18192 	  while (pos  < lglcntwtk (work)) {
18193 	    if (work->start[pos].lit != -other) break;
18194 	    if (work->start[pos].other == -lit) {
18195 	      LOG (3, "removing edge %d %d from DFS stack", -other, -lit);
18196 	      work->start[pos].removed = 1;
18197 	    }
18198 	    pos++;
18199 	  }
18200 	}
18201 	work->top--;
18202 	assert (dfpr[uother].discovered); // and thus 'parent' + 'root' set
18203 	continue;
18204       }
18205       observed = dfopf[unotother].observed;
18206       if (lgl->opts->unhdextstamp.val && startstamp <= observed) {
18207 	LOG (1, "stamping failing edge %d %d", lit, other);
18208 	for (failed = lit;
18209 	     dfpr[lglulit (failed)].discovered > observed;
18210 	     failed = dfpr[lglulit (failed)].parent)
18211 	  assert (failed);
18212 	LOG (1, "stamping failed literal %d", failed);
18213 	lglpushstk (lgl, units, -failed);
18214 	lgl->stats->unhd.stamp.failed++;
18215 	if (dfpr[unotother].discovered && !dfpr[unotother].finished) {
18216 	  LOG (2, "stamping skips edge %d %d after failed literal %d",
18217 	       lit, other, failed);
18218 	  work->top--;
18219 	  continue;
18220 	}
18221       }
18222       if (!dfpr[uother].discovered) {
18223 	dfpr[uother].parent = lit;
18224 	LOG (4, "stamping %d parent %d", other, lit);
18225 	dfpr[uother].root = root;
18226 	LOG (4, "stamping %d root %d", other, root);
18227 	lglpushwtk (lgl, work, PREFIX, other, 0, 0);
18228       }
18229     } else if (wrag == AFTER) {		// after recursive call
18230       LOG (2, "stamping edge %d %d after recursion", lit, other);
18231       uother = lglulit (other);
18232       ulit = lglulit (lit);
18233       if (lgl->opts->unhdextstamp.val && !dfpr[uother].finished &&
18234 	  dfpr[uother].discovered < dfpr[ulit].discovered) {
18235 	LOG (2, "stamping back edge %d %d", lit, other);
18236 	dfpr[ulit].discovered = dfpr[uother].discovered;
18237 	LOG (3, "stamping %d reduced discovered to %d",
18238 	     lit, dfpr[ulit].discovered);
18239 	if (dfopf[ulit].flag) {
18240 	  LOG (2, "stamping %d as being part of a non-trivial SCC", lit);
18241 	  dfopf[ulit].flag = 0;
18242 	}
18243       }
18244       dfopf[uother].observed = stamp;
18245       LOG (3, "stamping %d observed %d", other, stamp);
18246     } else {
18247       assert (wrag == POSTFIX);
18248       LOG (2, "stamping postfix %d", lit);
18249       ulit = lglulit (lit);
18250       if (dfopf[ulit].flag) {
18251 	stamp++;
18252 	sccsize = 0;
18253 	discovered = dfpr[ulit].discovered;
18254 	do {
18255 	  other = lglpopstk (sccs);
18256 	  uother = lglulit (other);
18257 	  dfopf[uother].pushed = -1;
18258 	  dfopf[uother].flag = 0;
18259 	  dfpr[uother].discovered = discovered;
18260 	  dfpr[uother].finished = stamp;
18261 	  LOG (3, "stamping %d interval %d %d parent %d root %d",
18262 	       other, dfpr[uother].discovered, dfpr[uother].finished,
18263 	       dfpr[uother].parent, dfpr[uother].root);
18264 	  sccsize++;
18265 	} while (other != lit);
18266 	assert (lgl->opts->unhdextstamp.val || sccsize == 1);
18267 	if (sccsize > 1) {
18268 	  LOG (2, "stamping non trivial SCC of size %d", sccsize);
18269 	  lgl->stats->unhd.stamp.sumsccsizes += sccsize;
18270 	  lgl->stats->unhd.stamp.sccs++;
18271 	}
18272       } else assert (lgl->opts->unhdextstamp.val);
18273     }
18274   }
18275   assert (lglmtwtk (work));
18276   assert (lglmtstk (sccs));
18277   return stamp;
18278 }
18279 
lglunhlca(LGL * lgl,const DFPR * dfpr,int a,int b)18280 static int lglunhlca (LGL * lgl, const DFPR * dfpr, int a, int b) {
18281   const DFPR * c, * d;
18282   int u, v, p;
18283   if (a == b) return a;
18284   u = lglulit (a), v = lglulit (b);
18285   c = dfpr + u, d = dfpr + v;
18286   if (c->discovered <= d->discovered) {
18287     p = a;
18288   } else {
18289     assert (c->discovered > d->discovered);
18290     p = b;
18291     SWAP (const DFPR *, c, d);
18292   }
18293   for (;;) {
18294     assert (c->discovered <= d->discovered);
18295     if (d->finished <= c->finished) break;
18296     p = c->parent;
18297     if (!p) break;
18298     u = lglulit (p);
18299     c = dfpr + u;
18300   }
18301   LOG (3, "unhiding least common ancestor of %d and %d is %d", a, b, p);
18302   return p;
18303 }
18304 
lglunhidefailed(LGL * lgl,const DFPR * dfpr)18305 static int lglunhidefailed (LGL * lgl, const DFPR * dfpr) {
18306   int idx, sign, lit, unit, nfailed = 0;
18307   for (idx = 2; idx < lgl->nvars; idx++) {
18308     for (sign = -1; sign <= 1; sign += 2) {
18309       if (lglterminate (lgl)) return 0;
18310       if (!lglsyncunits (lgl)) return 0;
18311       INCSTEPS (unhd.steps);
18312       lit = sign * idx;
18313       if (lglval (lgl, lit)) continue;
18314       if (!dfpr[lglulit (lit)].discovered) continue;
18315       if (lglunhimplincl (dfpr, lit, -lit)) {
18316 	unit = -lit;
18317 	LOG (2, "unhiding %d implies %d", lit, -lit);
18318       } else if (lglunhimplincl (dfpr, -lit, lit)) {
18319 	unit = lit;
18320 	LOG (2, "unhiding %d implies %d", -lit, lit);
18321       } else continue;
18322       LOG (1, "unhiding failed literal %d", -unit);
18323       lglunit (lgl, unit);
18324       lgl->stats->unhd.failed.lits++;
18325       nfailed++;
18326       if (lglbcp (lgl)) continue;
18327       LOG (1, "empty clause after propagating unhidden failed literal");
18328       assert (!lgl->mt);
18329       lglmt (lgl);
18330       return 0;
18331     }
18332   }
18333   LOG (1, "unhiding %d failed literals in this round", nfailed);
18334   return 1;
18335 }
18336 
lglunhroot(const DFPR * dfpr,int lit)18337 static int lglunhroot (const DFPR * dfpr, int lit) {
18338   return dfpr[lglulit (lit)].root;
18339 }
18340 
lglunhidebintrn(LGL * lgl,const DFPR * dfpr,int irronly)18341 static int lglunhidebintrn (LGL * lgl, const DFPR * dfpr, int irronly) {
18342   int idx, sign, lit, blit, tag, red, other, other2, unit, root, lca;
18343   int nbinred, ntrnred, nbinunits, ntrnunits, ntrnstr, ntrnhbrs;
18344   const int * p, * eow;
18345   int ulit, uother;
18346   int * w , * q;
18347   long delta;
18348   HTS * hts;
18349   nbinred = ntrnred = nbinunits = ntrnunits = ntrnstr = ntrnhbrs = 0;
18350   for (idx = 2; idx < lgl->nvars; idx++) {
18351     for (sign = -1; sign <= 1; sign += 2) {
18352       if (lglterminate (lgl)) return 0;
18353       if (!lglsyncunits (lgl)) return 0;
18354       INCSTEPS (unhd.steps);
18355       lit = sign * idx;
18356       if (lglval (lgl, lit)) continue;
18357       ulit = lglulit (lit);
18358       if (!dfpr[ulit].discovered) continue;
18359       hts = lglhts (lgl, lit);
18360       w = lglhts2wchs (lgl, hts);
18361       eow = w + hts->count;
18362       q = w;
18363       for (p = w; p < eow; p++) {
18364 	blit = *p;
18365 	*q++ = blit;
18366 	tag = blit & MASKCS;
18367 	if (tag == TRNCS || tag == LRGCS) *q++ = *++p;
18368 	if (tag == LRGCS) continue;
18369 	red = blit & REDCS;
18370 	other = blit >> RMSHFT;
18371 	if (lglval (lgl, other)) continue;
18372 	uother = lglulit (other);
18373 	if (tag == BINCS) {
18374 	  if (lglunhimplies2 (dfpr, other, lit)) {
18375 	    LOG (2, "unhiding removal of literal %d "
18376 		    "with implication %d %d from binary clause %d %d",
18377 		 other, other, lit, lit, other);
18378 	    lgl->stats->unhd.units.bin++;
18379 	    nbinunits++;
18380 	    unit = lit;
18381 UNIT:
18382 	    lglunit (lgl, unit);
18383 	    p++;
18384 	    while (p < eow) *q++ = *p++;
18385 	    lglshrinkhts (lgl, hts, hts->count - (p - q));
18386 	    if (lglbcp (lgl)) goto NEXTIDX;
18387 	    LOG (1, "empty clause after propagating unhidden lifted unit");
18388 	    assert (!lgl->mt);
18389 	    lglmt (lgl);
18390 	    return 0;
18391 	  } else if ((root = lglunhroot (dfpr, -lit)) &&
18392 		     !lglval (lgl, root) &&
18393 		     root == lglunhroot (dfpr, -other)) {
18394 	    LOG (2, "negated literals in binary clause %d %d implied by %d",
18395 		 lit, other, root);
18396 	    lgl->stats->unhd.failed.bin++;
18397 	    lca = lglunhlca (lgl, dfpr, -lit, -other);
18398 	    unit = -lca;
18399 	    assert (unit);
18400 	    goto UNIT;
18401 	  } else if (!irronly && !red) continue;
18402 	  else {
18403 	    if (dfpr[uother].parent == -lit) continue;
18404 	    if (dfpr[ulit].parent == -other) continue;
18405 	    if (!lglunhimplies2 (dfpr, -lit, other)) continue;
18406 	    LOG (2, "unhiding tautological binary clause %d %d", lit, other);
18407 	    lgl->stats->unhd.tauts.bin++;
18408 	    lgl->stats->prgss++;
18409 	    if (red) lgl->stats->unhd.tauts.red++;
18410 	    nbinred++;
18411 	    lglrmbwch (lgl, other, lit, red);
18412 	    LOG (2, "removed %s binary clause %d %d",
18413 		 lglred2str (red), lit, other);
18414 	    lgldeclscnt (lgl, 2, red, 0);
18415 	    assert (!lgl->dense);
18416 	    q--;
18417 	  }
18418 	} else {
18419 	  assert (tag == TRNCS);
18420 	  other2 = *p;
18421 	  if (lglval (lgl, other2)) continue;
18422 	  if (lglunhimplies2incl (dfpr, other, lit) &&
18423 	      lglunhimplies2incl (dfpr, other2, lit)) {
18424 	    LOG (2,
18425 		 "unhiding removal of literals %d and %d with implications "
18426 		 "%d %d and %d %d from ternary clause %d %d %d",
18427 		 other, other2,
18428 		 other, lit,
18429 		 other2, lit,
18430 		 lit, other, other2);
18431 	    lgl->stats->unhd.str.trn += 2;
18432 	    if (red) lgl->stats->unhd.str.red += 2;
18433 	    lgl->stats->unhd.units.trn++;
18434 	    ntrnunits++;
18435 	    unit = lit;
18436 	    goto UNIT;
18437 	  } else if ((root = lglunhroot (dfpr, -lit)) &&
18438 		     !lglval (lgl, root) &&
18439 		     root == lglunhroot (dfpr, -other) &&
18440 		     root == lglunhroot (dfpr, -other2)) {
18441 	    LOG (2,
18442 	      "negation of literals in ternary clauses %d %d %d "
18443 	      "implied by %d", lit, other, other2, root);
18444 	    lgl->stats->unhd.failed.trn++;
18445 	    lca = lglunhlca (lgl, dfpr, -lit, -other);
18446 	    assert (lca);
18447 	    lca = lglunhlca (lgl, dfpr, lca, -other2);
18448 	    assert (lca);
18449 	    unit = -lca;
18450 	    goto UNIT;
18451 	  } else if ((red || irronly) &&
18452 		     (lglunhimplies2incl (dfpr, -lit, other) ||
18453 		      lglunhimplies2incl (dfpr, -lit, other2))) {
18454 
18455 	    if (!lgl->opts->unhdatrn.val) continue;
18456 	    if (red && lgl->opts->unhdatrn.val == 1) continue;
18457 
18458 	    LOG (2, "unhiding %s tautological ternary clause %d %d %d",
18459 		 lglred2str (red), lit, other, other2);
18460 	    lgl->stats->unhd.tauts.trn++;
18461 	    lgl->stats->prgss++;
18462 	    if (red) lgl->stats->unhd.tauts.red++;
18463 	    ntrnred++;
18464 	    lglrmtwch (lgl, other, lit, other2, red);
18465 	    lglrmtwch (lgl, other2, lit, other, red);
18466 	    LOG (2, "removed %s ternary clause %d %d %d",
18467 		 lglred2str (red), lit, other, other2);
18468 	    lgldeclscnt (lgl, 3, red, 0);
18469 	    assert (!lgl->dense);
18470 	    if (!red && lgl->opts->move.val >= 2) {
18471 	      long delta;
18472 	      assert (q >= w);
18473 	      assert (q[-2] == blit);
18474 	      assert (q[-1] == other2);
18475 	      q[-2] |= REDCS;
18476 	      delta = lglwchtrn (lgl, other, lit, other2, REDCS);
18477 	      delta += lglwchtrn (lgl, other2, lit, other, REDCS);
18478 	      if (delta) w += delta, eow += delta, p += delta, q += delta;
18479 	      LOG (2, "moved ternary clause %d %d %d", lit, other, other2);
18480               lgl->stats->red.trn++, assert (lgl->stats->red.trn > 0);
18481 	      lgl->stats->moved.trn++;
18482 	    } else q -= 2;
18483 	  } else if (lglunhimplies2incl (dfpr, other2, lit)) {
18484 TRNSTR:
18485 	    LOG (2,
18486 		 "unhiding removal of literal %d with implication "
18487 		 "%d %d from ternary clause %d %d %d",
18488 		 other2, other2, lit, lit, other, other2);
18489 	    lgl->stats->unhd.str.trn++;
18490 	    lgl->stats->prgss++;
18491 	    if (red) lgl->stats->unhd.str.red++;
18492 	    ntrnstr++;
18493 	    lglrmtwch (lgl, other, lit, other2, red);
18494 	    lglrmtwch (lgl, other2, lit, other, red);
18495 	    LOG (2, "removed %s ternary clause %d %d %d",
18496 		 lglred2str (red), lit, other, other2);
18497 	    lgldeclscnt (lgl, 3, red, 0);
18498 	    if (!red) lglincirr (lgl, 2);
18499 	    else lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
18500 	    delta = lglwchbin (lgl, other, lit, red);
18501 	    if (delta) { p += delta, q += delta, eow += delta, w += delta; }
18502 	    (--q)[-1] = red | BINCS | RMSHFTLIT (other);
18503 	    lgldrupligaddclsarg (lgl, REDCS, lit, other, 0);
18504 	    continue;
18505 	  } else if (lglunhimplies2incl (dfpr, other, lit)) {
18506 	    SWAP (int, other, other2);
18507 	    goto TRNSTR;
18508 	  } else if (lgl->opts->unhdhbr.val &&
18509 		     (root = lglunhroot (dfpr, -lit)) &&
18510 		     !lglval (lgl, root)) {
18511 	    if (root == lglunhroot (dfpr, -other2)) {
18512 	      lca = lglunhlca (lgl, dfpr, -lit, -other2);
18513 	    } else if (root == lglunhroot (dfpr, -other)) {
18514 	      lca = lglunhlca (lgl, dfpr, -lit, -other);
18515 	      SWAP (int, other, other2);
18516 	    } else if (lglunhimplies2incl (dfpr, root, -other2)) lca = root;
18517 	    else if (lglunhimplies2incl (dfpr, root, -other)) {
18518 	      lca = root;
18519 	      SWAP (int, other, other2);
18520 	    } else continue;
18521 	    assert (lca);
18522 	    if (abs (lca) == abs (lit)) continue;
18523 	    if (abs (lca) == abs (other)) continue;
18524 	    if (abs (lca) == abs (other2)) continue;
18525 	    if (lglunhimplies2incl (dfpr, lca, other)) continue;
18526 	    LOG (2,
18527 	      "negations of literals %d %d in ternary clause %d %d %d "
18528 	      "implied by %d", lit, other2, lit, other, other2, lca);
18529 	    lgl->stats->unhd.hbrs.trn++;
18530 	    if (red) lgl->stats->unhd.hbrs.red++;
18531 	    lgl->stats->prgss++;
18532 	    ntrnhbrs++;
18533 	    LOG (2, "unhidden hyper binary resolved clause %d %d",-lca,other);
18534 	    lgldrupligaddclsarg (lgl, REDCS, -lca, other, 0);
18535 	    assert (lca != -lit);
18536 	    lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
18537 	    delta = lglwchbin (lgl, -lca, other, REDCS);
18538 	    if (delta) { p += delta, q += delta, eow += delta, w += delta; }
18539 	    delta = lglwchbin (lgl, other, -lca, REDCS);
18540 	    if (delta) { p += delta, q += delta, eow += delta, w += delta; }
18541 	  }
18542 	}
18543       }
18544       lglshrinkhts (lgl, hts, hts->count - (p - q));
18545     }
18546 NEXTIDX:
18547     ;
18548   }
18549   if (nbinred) LOG (2, "unhiding %d tautological binary clauses", nbinred);
18550   if (nbinunits) LOG (2, "unhiding %d units in binary clauses", nbinunits);
18551   if (ntrnred) LOG (2, "unhiding %d tautological ternary clauses", ntrnred);
18552   if (ntrnstr) LOG (2, "unhiding %d strengthened ternary clauses", ntrnstr);
18553   if (ntrnunits) LOG (2, "unhiding %d units in ternary clauses", ntrnunits);
18554   if (ntrnstr) LOG (2,
18555     "unhidden %d hyper binary resolution from ternary clauses", ntrnhbrs);
18556   return 1;
18557 }
18558 
lglcmpdfl(const DFL * a,const DFL * b)18559 static int lglcmpdfl (const DFL * a, const DFL * b) {
18560   return a->discovered - b->discovered;
18561 }
18562 
lglunhideglue(LGL * lgl,const DFPR * dfpr,int glue,int irronly)18563 static int lglunhideglue (LGL * lgl, const DFPR * dfpr, int glue, int irronly) {
18564   DFL * dfl, * eodfl, * d, * e; int szdfl, posdfl, negdfl, ndfl, res;
18565   int oldsize, newsize, hastobesatisfied, satisfied, tautological;
18566   int watched, lit, ulit, val, sign, nonfalse, root, lca, unit;
18567   int ntaut = 0, nstr = 0, nunits = 0, nhbrs = 0, lidx;
18568   int * p, * q, * c, * eoc, red;
18569   int lca1, lca2, root1, root2;
18570   Stk * lits;
18571 #ifndef NLGLOG
18572   char type[20];
18573   if (glue < 0) sprintf (type, "irredundant");
18574   else sprintf (type, "redundant glue %d", glue);
18575 #endif
18576   assert (!lgl->mt);
18577   assert (-1 <= glue && glue < MAXGLUE);
18578   if (glue < 0) {
18579     lits = &lgl->irr;
18580     red = 0;
18581   } else {
18582     lits = lgl->red + glue;
18583     red = REDCS;
18584   }
18585   res = 1;
18586   dfl = 0; szdfl = 0;
18587   // go through all clauses of this glue and for each do:
18588   //
18589   //   SHRINK  simplify clause according to current assignment
18590   //   FAILED  check if it is a hidden failed literal
18591   //   HTE     check if it is a hidden tautology
18592   //   STRNEG  remove hidden literals using complement literals
18593   //   STRPOS  remove hidden literals using positive literals
18594   //   HBR     perform unhiding hyper binary resolution
18595   //   NEXT    clean up, unwatch if necessary, reconnect bin/trn, bcp unit
18596   //
18597   for (c = lits->start; !lgl->mt && c < lits->top; c = eoc + 1) {
18598     if (lglterminate (lgl) || !lglsyncunits (lgl)) { res = 0; break; }
18599     if ((lit = *(eoc = c)) >= NOTALIT) continue;
18600     INCSTEPS (unhd.steps);
18601     lidx = c - lits->start;
18602     if (red) { lidx <<= GLUESHFT; lidx |= glue; }
18603     watched = 1;
18604     while (*eoc) eoc++;
18605     oldsize = eoc - c;
18606 
18607     unit = hastobesatisfied = satisfied = tautological = ndfl = 0;
18608 //SHRINK: check satisfied + remove false literals + count visited
18609     q = c;
18610     nonfalse = posdfl = negdfl = 0;
18611     for (p = c; p < eoc; p++) {
18612       lit = *p;
18613       val = lglval (lgl, lit);
18614       if (val > 0) {
18615 	satisfied = 1;
18616 	q = c + 2;
18617 	break;
18618       }
18619       if (val < 0) {
18620 	if (p < c + 2) {
18621 	  *q++ = lit;		// watched, so have to keep it
18622 	  hastobesatisfied = 1;	// for assertion checking only
18623 	}
18624 	continue;
18625       }
18626       *q++ = lit;
18627       nonfalse++;
18628       if (dfpr[lglulit (lit)].discovered) posdfl++;	// count pos in BIG
18629       if (dfpr[lglulit (-lit)].discovered) negdfl++;	// count neg in BIG
18630     }
18631     *(eoc = q) = 0;
18632     assert (eoc - c >= 2);	// we assume bcp done before
18633     ndfl = posdfl + negdfl;	// number of literals in BIG
18634     if (hastobesatisfied) assert (satisfied);
18635     if (satisfied || ndfl < 2) goto NEXT;
18636     assert (nonfalse = eoc - c);
18637     assert (nonfalse >= negdfl);
18638 //FAILED: find root implying all negated literals
18639     if (nonfalse != negdfl) goto HTE;	// not enough complement lits in BIG
18640     assert (c < eoc);
18641     root = lglunhroot (dfpr, -*c);
18642     if (lglval (lgl, root)) goto HTE;
18643     for (p = c + 1; p < eoc && lglunhroot (dfpr, -*p) == root; p++)
18644       ;
18645     if (p < eoc) goto HTE;		// at least two roots
18646     LOGCLS (2, c, "unhiding failed literal through large %s clause",type);
18647     LOG (2, "unhiding that all negations are implied by root %d", root);
18648     lca = -*c;
18649     for (p = c + 1; p < eoc; p++)
18650       lca = lglunhlca (lgl, dfpr, -*p, lca);
18651     assert (!lglval (lgl, lca));
18652     LOG (2, "unhiding failed large %s clause implied by LCA %d", type, lca);
18653     lgl->stats->unhd.failed.lrg++;
18654     unit = -lca;
18655     goto NEXT;  // otherwise need to properly unwatch and restart etc.
18656 		// which is too difficult to implement so leave further
18657 		// simplification of this clause to next unhiding round
18658 HTE:
18659     if (glue < 0 && !irronly) goto STRNEG; // skip tautology checking if
18660 					   // redundant clauses used and
18661 					   // we work on irredundant clauses
18662     if (posdfl < 2 || negdfl < 2) goto STRNEG;
18663     if (ndfl > szdfl) { RSZ (dfl, szdfl, ndfl); szdfl = ndfl; }
18664     ndfl = 0;
18665     // copy all literals and their complements to 'dfl'
18666     for (p = c; p < eoc; p++) {
18667       for (sign = -1; sign <= 1; sign += 2) {
18668 	lit = *p;
18669 	ulit = lglulit (sign * lit);
18670 	if (!dfpr[ulit].discovered) continue;	// not in BIG so skip
18671 	assert (ndfl < szdfl);
18672 	dfl[ndfl].discovered = dfpr[ulit].discovered;
18673 	dfl[ndfl].finished = dfpr[ulit].finished;
18674 	dfl[ndfl].sign = sign;
18675 #ifndef NLGLOG
18676 	dfl[ndfl].lit4logging = lit;
18677 #endif
18678 	ndfl++;
18679       }
18680     }
18681     ADDSTEPS (unhd.steps, 6);				// rough guess
18682     SORT (DFL, dfl, ndfl, lglcmpdfl);
18683     eodfl = dfl + ndfl;
18684     // Now check if there are two consecutive literals, the first
18685     // a complement of a literal in the clause, which implies another
18686     // literal actually occurring positive in the clause, where
18687     // 'd' ranges over complement literals
18688     // 'e' ranges over original literals
18689     for (d = dfl; d < eodfl - 1; d++)
18690       if (d->sign < 0) break;			// get first negative pos
18691     while (d < eodfl - 1) {
18692       assert (d->sign < 0);
18693       for (e = d + 1; e < eodfl && e->finished < d->finished; e++) {
18694 	if (e->sign < 0) continue;		// get next positive pos
18695 	assert (d->sign < 0 && e->sign > 0);
18696 	assert (d->discovered <= e->discovered);
18697 	assert (e ->finished <= d->finished);
18698 	LOGCLS (2, c,
18699 		"unhiding with implication %d %d tautological %s clause",
18700 		-d->lit4logging, e->lit4logging, type);
18701 	ntaut++;
18702 	lgl->stats->unhd.tauts.lrg++;
18703 	if (red) lgl->stats->unhd.tauts.red++;
18704 	lgl->stats->prgss++;
18705 	tautological = 1;
18706 	goto NEXT;
18707       }
18708       for (d = e; d < eodfl && d->sign > 0; d++)
18709 	;
18710     }
18711 STRNEG:
18712     if (negdfl < 2) goto STRPOS;
18713     if (negdfl > szdfl) { RSZ (dfl, szdfl, negdfl); szdfl = negdfl; }
18714     INCSTEPS (unhd.steps);
18715     ndfl = 0;
18716     // copy complement literals to 'dfl'
18717     for (p = c; p < eoc; p++) {
18718       lit = *p;
18719       ulit = lglulit (-lit);			// NOTE: '-lit' not 'lit'
18720       if (!dfpr[ulit].discovered) continue;
18721       assert (ndfl < szdfl);
18722       dfl[ndfl].discovered = dfpr[ulit].discovered;	// of '-lit'
18723       dfl[ndfl].finished = dfpr[ulit].finished;		// of '-lit'
18724       dfl[ndfl].lit = lit;			// NOTE: but 'lit' here
18725       ndfl++;
18726     }
18727     if (ndfl < 2) goto STRPOS;
18728     ADDSTEPS (unhd.steps, 3);			// rough guess
18729     SORT (DFL, dfl, ndfl, lglcmpdfl);
18730     eodfl = dfl + ndfl;
18731     for (d = dfl; d < eodfl - 1; d = e) {
18732       assert (d->discovered);
18733       for (e = d + 1; e < eodfl && d->finished >= e->finished; e++) {
18734 	assert (d->discovered <= e->discovered);
18735 	lit = e->lit;
18736 	LOGCLS (2, c,
18737 		"unhiding removal of literal %d "
18738 		"with implication %d %d from large %s clause",
18739 		lit, -d->lit, -e->lit, type);
18740 	e->lit = 0;
18741 	nstr++;
18742 	lgl->stats->unhd.str.lrg++;
18743 	if (red) lgl->stats->unhd.str.red++;
18744 	lgl->stats->prgss++;
18745 	if (!watched) continue;
18746 	if (lit != c[0] && lit != c[1]) continue;
18747 	lglrmlwch (lgl, c[0], red, lidx);
18748 	lglrmlwch (lgl, c[1], red, lidx);
18749 	watched = 0;
18750       }
18751     }
18752     assert (eoc - c >= 1 );
18753     q = c;
18754     if (watched) q += 2;			// keep watched literals
18755 						// if we still watch
18756     // move non BIG literals
18757     for (p = q; p < eoc; p++) {
18758       lit = *p;
18759       ulit = lglulit (-lit);			// NOTE: '-lit' not 'lit'
18760       if (dfpr[ulit].discovered) continue;
18761       *q++ = lit;
18762     }
18763     // copy from 'dfl' unremoved BIG literals back to clause
18764     for (d = dfl; d < eodfl; d++) {
18765       lit = d->lit;
18766       if (!lit) continue;
18767       if (watched && lit == c[0]) continue;
18768       if (watched && lit == c[1]) continue;
18769       *q++ = lit;
18770     }
18771     *(eoc = q) = 0;
18772 STRPOS:
18773     if (posdfl < 2) goto HBR;
18774     if (posdfl > szdfl) { RSZ (dfl, szdfl, posdfl); szdfl = posdfl; }
18775     ndfl = 0;
18776     // copy original literals to 'dfl' but sort reverse wrt 'discovered'
18777     for (p = c; p < eoc; p++) {
18778       lit = *p;
18779       ulit = lglulit (lit);			// NOTE: now 'lit'
18780       if (!dfpr[ulit].discovered) continue;
18781       assert (ndfl < szdfl);
18782       dfl[ndfl].discovered = -dfpr[ulit].discovered;	// of 'lit'
18783       dfl[ndfl].finished = -dfpr[ulit].finished;		// of 'lit'
18784       dfl[ndfl].lit = lit;
18785       ndfl++;
18786     }
18787     if (ndfl < 2) goto NEXT;
18788     ADDSTEPS (unhd.steps, 3);			// rough guess
18789     SORT (DFL, dfl, ndfl, lglcmpdfl);
18790     eodfl = dfl + ndfl;
18791     for (d = dfl; d < eodfl - 1; d = e) {
18792       assert (d->discovered);
18793       for (e = d + 1; e < eodfl && d->finished >= e->finished; e++) {
18794 	assert (d->discovered <= e->discovered);
18795 	lit = e->lit;
18796 	LOGCLS (2, c,
18797 		"unhiding removal of literal %d "
18798 		"with implication %d %d from large %s clause",
18799 		lit, e->lit, d->lit, type);
18800 	e->lit = 0;
18801 	nstr++;
18802 	lgl->stats->unhd.str.lrg++;
18803 	if (red) lgl->stats->unhd.str.red++;
18804 	lgl->stats->prgss++;
18805 	if (!watched) continue;
18806 	if (lit != c[0] && lit != c[1]) continue;
18807 	lglrmlwch (lgl, c[0], red, lidx);
18808 	lglrmlwch (lgl, c[1], red, lidx);
18809 	watched = 0;
18810       }
18811     }
18812     assert (eoc - c >= 1 );
18813     q = c;
18814     if (watched) q += 2;
18815     for (p = q; p < eoc; p++) {
18816       lit = *p;
18817       ulit = lglulit (lit);			// NOTE: now 'lit'
18818       if (dfpr[ulit].discovered) continue;
18819       *q++ = lit;
18820     }
18821     for (d = dfl; d < eodfl; d++) {
18822       lit = d->lit;
18823       if (!lit) continue;
18824       if (watched && lit == c[0]) continue;
18825       if (watched && lit == c[1]) continue;
18826       *q++ = lit;
18827     }
18828     *(eoc = q) = 0;
18829 HBR:
18830     if (!lgl->opts->unhdhbr.val) goto NEXT;
18831     if (eoc - c < 3) goto NEXT;
18832     root1 = root2 = lca1 = lca2 = 0;
18833     for (p = c; (lit = *p); p++) {
18834       root = lglunhroot (dfpr, -lit);
18835       if (!root) root = -lit;
18836       if (!root1) { root1 = root; continue; }
18837       if (root1 == root) continue;
18838       if (!root2) { root2 = root; continue; }
18839       if (root2 == root) continue;
18840       if (lglunhimplies2incl (dfpr, root1, -lit)) { lca1 = root1; continue; }
18841       if (lglunhimplies2incl (dfpr, root2, -lit)) { lca2 = root2; continue; }
18842       goto NEXT;			// else more than two roots ...
18843     }
18844     assert (root1);
18845     if (!root2) goto NEXT;
18846     if (root1 == -root2) goto NEXT;
18847     if (lglunhimplies2incl (dfpr, root1, -root2)) goto NEXT;
18848     LOGCLS (2, c, "root hyper binary resolution %d %d of %s clause",
18849 	    -root1, -root2, type);
18850     if (!lca1 && !lca2) {
18851       for (p = c; (lit = *p); p++) {
18852 	root = lglunhroot (dfpr, -lit);
18853 	if (root) {
18854 	  if (root == root1)
18855 	    lca1 = lca1 ? lglunhlca (lgl, dfpr, lca1, -lit) : -lit;
18856 	  if (root == root2)
18857 	    lca2 = lca2 ? lglunhlca (lgl, dfpr, lca2, -lit) : -lit;
18858 	} else {
18859 	  assert (!lca2);
18860 	  if (lca1) lca2 = -lit; else lca1 = -lit;
18861 	}
18862       }
18863     } else {
18864       if (!lca1) lca1 = root1;
18865       if (!lca2) lca2 = root2;
18866     }
18867     if (lca1 == -lca2) goto NEXT;
18868     if (lglunhimplies2incl (dfpr, lca1, -lca2)) goto NEXT;
18869     LOGCLS (2, c, "lca hyper binary resolution %d %d of %s clause",
18870 	    -lca1, -lca2, type);
18871     lgl->stats->unhd.hbrs.lrg++;
18872     if (red) lgl->stats->unhd.hbrs.red++;
18873     lgldrupligaddclsarg (lgl, REDCS, -lca1, -lca2, 0);
18874     lglwchbin (lgl, -lca1, -lca2, REDCS);
18875     lglwchbin (lgl, -lca2, -lca1, REDCS);
18876     lgl->stats->red.bin++;
18877     assert (lgl->stats->red.bin > 0);
18878 NEXT:
18879     newsize = eoc - c;
18880     assert (satisfied || tautological || newsize >= 1);
18881     if (newsize <= 3 || satisfied || tautological) {
18882       lgldeclscnt (lgl, oldsize, red, glue);
18883       if (watched) {
18884 	lglrmlwch (lgl, c[0], red, lidx);
18885 	lglrmlwch (lgl, c[1], red, lidx);
18886       }
18887     } else if (!red) {
18888       assert (lgl->stats->irr.lits.cur >= c + oldsize - eoc);
18889       lgl->stats->irr.lits.cur -= c + oldsize - eoc;
18890     }
18891     assert (!*eoc);
18892     for (p = c + oldsize; p > eoc; p--) *p = REMOVED;
18893     if (satisfied || tautological) {
18894       while (p >= c) *p-- = REMOVED;
18895       if (red) { LGLCHKACT (c[-1]); c[-1] = REMOVED; }
18896       eoc = c + oldsize;
18897       continue;
18898     }
18899     if (newsize < oldsize) lgldrupligaddclsaux (lgl, REDCS, c);
18900     if (red && newsize <= 3) { LGLCHKACT (c[-1]); c[-1] = REMOVED; }
18901     if (newsize > 3 && !watched) {
18902       (void) lglwchlrg (lgl, c[0], c[1], red, lidx);
18903       (void) lglwchlrg (lgl, c[1], c[0], red, lidx);
18904     } else if (newsize == 3) {
18905       LOGCLS (2, c, "large %s clause became ternary", type);
18906       lglwchtrn (lgl, c[0], c[1], c[2], red);
18907       lglwchtrn (lgl, c[1], c[0], c[2], red);
18908       lglwchtrn (lgl, c[2], c[0], c[1], red);
18909       if (!red) lglincirr (lgl, 3);
18910       else lgl->stats->red.trn++, assert (lgl->stats->red.trn > 0);
18911       c[0] = c[1] = c[2] = *eoc = REMOVED;
18912     } else if (newsize == 2) {
18913       LOGCLS (2, c, "large %s clause became binary", type);
18914       lglwchbin (lgl, c[0], c[1], red);
18915       lglwchbin (lgl, c[1], c[0], red);
18916       if (!red) lglincirr (lgl, 2);
18917       else lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
18918       c[0] = c[1] = *eoc = REMOVED;
18919     } else if (newsize == 1) {
18920       LOGCLS (2, c, "large %s clause became unit", type);
18921       unit = c[0];		// even works if unit already set
18922       c[0] = *eoc = REMOVED;
18923       lgl->stats->unhd.units.lrg++;
18924       nunits++;
18925     }
18926     if (!unit) continue;
18927     lglunit (lgl, unit);
18928     if (lglbcp (lgl)) continue;
18929     assert (!lgl->mt);
18930     lglmt (lgl);
18931     LOG (1, "unhiding large clause produces empty clause");
18932     res = 0;
18933   }
18934   if (nunits)
18935     LOG (1, "unhiding %d units from large %s clauses", nunits, type);
18936   if (ntaut)
18937     LOG (1, "unhiding %d large tautological %s clauses", ntaut, type);
18938   if (nstr)
18939     LOG (1, "unhiding removal of %d literals in %s clauses", nstr, type);
18940   if (nhbrs)
18941     LOG (1, "unhiding %d hyper binary resolutions in %s clauses", nhbrs, type);
18942   if (dfl) DEL (dfl, szdfl);
18943   return res;
18944 }
18945 
lglfixlrgwchs(LGL * lgl)18946 static void lglfixlrgwchs (LGL * lgl) {
18947   int idx, sign, lit, blit, tag, red, lidx, fixed;
18948   const int * p, * eow, * c;
18949   int * q, * w;
18950   HTS * hts;
18951   fixed = 0;
18952   for (idx = 2; idx < lgl->nvars; idx++) {
18953     for (sign = -1; sign <= 1; sign += 2) {
18954       lit = sign * idx;
18955       hts = lglhts (lgl, lit);
18956       w = lglhts2wchs (lgl, hts);
18957       eow = w + hts->count;
18958       q = w;
18959       for (p = w; p < eow; p++) {
18960 	blit = *p;
18961 	tag = blit & MASKCS;
18962 	if (tag == BINCS) { *q++ = blit; continue; }
18963 	lidx = *++p;
18964 	if (tag == TRNCS) { *q++ = blit; *q++ = lidx; continue; }
18965 	assert (tag == LRGCS);
18966 	red = blit & REDCS;
18967 	c = lglidx2lits (lgl, red, lidx);
18968 	if (*c >= NOTALIT) { fixed++; continue; }
18969 	*q++ = blit;
18970 	*q++ = lidx;
18971       }
18972       lglshrinkhts (lgl, hts, hts->count - (p - q));
18973     }
18974   }
18975   assert (!(fixed & 1));
18976   if (fixed) LOG (1, "fixed %d large watches", fixed);
18977 }
18978 
lglunhidelrg(LGL * lgl,const DFPR * dfpr,int irronly)18979 static int lglunhidelrg (LGL * lgl, const DFPR * dfpr, int irronly) {
18980   int glue, res = 1;
18981   for (glue = -1; res && glue < MAXGLUE; glue++)
18982     res = lglunhideglue (lgl, dfpr, glue, irronly);
18983   lglfixlrgwchs (lgl);
18984   return res;
18985 }
18986 
lglunhdunits(LGL * lgl)18987 static int lglunhdunits (LGL * lgl) {
18988   int res = lgl->stats->unhd.units.bin;
18989   res += lgl->stats->unhd.units.trn;
18990   res += lgl->stats->unhd.units.lrg;
18991   return res;
18992 }
18993 
lglunhdfailed(LGL * lgl)18994 static int lglunhdfailed (LGL * lgl) {
18995   int res = lgl->stats->unhd.stamp.failed;
18996   res += lgl->stats->unhd.failed.lits;
18997   res += lgl->stats->unhd.failed.bin;
18998   res += lgl->stats->unhd.failed.trn;
18999   res += lgl->stats->unhd.failed.lrg;
19000   return res;
19001 }
19002 
lglunhdhbrs(LGL * lgl)19003 static int lglunhdhbrs (LGL * lgl) {
19004   int res = lgl->stats->unhd.hbrs.trn;
19005   res += lgl->stats->unhd.hbrs.lrg;
19006   return res;
19007 }
19008 
lglunhdtauts(LGL * lgl)19009 static int lglunhdtauts (LGL * lgl) {
19010   int res = lgl->stats->unhd.stamp.trds;
19011   res += lgl->stats->unhd.tauts.bin;
19012   res += lgl->stats->unhd.tauts.trn;
19013   res += lgl->stats->unhd.tauts.lrg;
19014   return res;
19015 }
19016 
lglunhdstrd(LGL * lgl)19017 static int lglunhdstrd (LGL * lgl) {
19018   int res = lgl->stats->unhd.units.bin;	// shared!
19019   res += lgl->stats->unhd.str.trn;
19020   res += lgl->stats->unhd.str.lrg;
19021   return res;
19022 }
19023 
lglrmbindup(LGL * lgl)19024 static void lglrmbindup (LGL * lgl) {
19025   int idx, sign, lit, blit, tag, red, other, round, redrem, irrem;
19026   int * w, * eow, * p, * q;
19027   HTS * hts;
19028   redrem = irrem = 0;
19029   for (idx = 2; idx < lgl->nvars; idx++) {
19030     for (sign = -1; sign <= 1; sign += 2) {
19031       lit = sign * idx;
19032       assert (lglmtstk (&lgl->seen));
19033       for (round = 0; round < 2; round++) {
19034 	hts = lglhts (lgl, lit);
19035 	w = lglhts2wchs (lgl, hts);
19036 	eow = w + hts->count;
19037 	q = w;
19038 	for (p = w; p < eow; p++) {
19039 	  blit = *p;
19040 	  tag = blit & MASKCS;
19041 	  if (tag != BINCS) *q++ = blit;
19042 	  if (tag== LRGCS || tag == TRNCS) *q++ = *++p;
19043 	  if (tag != BINCS) continue;
19044 	  red = blit & REDCS;
19045 	  other = blit >> RMSHFT;
19046 	  if (lglsignedmarked (lgl, other)) {
19047 	    if (round && !red) goto ONLYCOPY;
19048 	    if (red) redrem++; else irrem++;
19049 	    if (abs (lit) > abs (other)) {
19050 	      LOG (2,
19051 		"removing duplicated %s binary clause %d %d and 2nd watch %d",
19052 		lglred2str (red), lit, other, other);
19053 	      lgldeclscnt (lgl, 2, red, 0);
19054 	      if (!red && lgl->dense)
19055 		lgldecocc (lgl, lit), lgldecocc (lgl, other);
19056 	      lgl->stats->bindup.removed++;
19057 	      if (red) lgl->stats->bindup.red++;
19058 	    } else
19059 	      LOG (2,
19060 		"removing 1st watch %d of duplicated %s binary clause %d %d",
19061 		other, lglred2str (red), other, lit);
19062 	  } else {
19063 	    if ((!round && !red) || (round && red))
19064 	      lglsignedmarknpushseen (lgl, other);
19065 ONLYCOPY:
19066 	    *q++ = blit;
19067 	  }
19068 	}
19069 	lglshrinkhts (lgl, hts, hts->count - (p - q));
19070       }
19071       lglpopnunmarkstk (lgl, &lgl->seen);
19072     }
19073   }
19074   assert (!(irrem & 1));
19075   assert (!(redrem & 1));
19076 }
19077 
lglstampall(LGL * lgl,int irronly)19078 static DFPR * lglstampall (LGL * lgl, int irronly) {
19079   int roots, searches, noimpls, unassigned, visited;
19080   unsigned pos, delta, mod, ulit, first, last, count;
19081   int root, stamp, rootsonly, lit;
19082   Stk units, sccs, trds;
19083   DFOPF * dfopf, * q;
19084   DFPR * dfpr;
19085   Wtk work;
19086   Val val;
19087   if (lgl->nvars <= 2) return 0;
19088   lglrmbindup (lgl);
19089   NEW (dfpr, 2*lgl->nvars);
19090   NEW (dfopf, 2*lgl->nvars);
19091   CLR (work); CLR (sccs); CLR (trds); CLR (units);
19092   for (q = dfopf; q < dfopf + 2*lgl->nvars; q++) q->pushed = -1;
19093   searches = roots = noimpls = unassigned = stamp = visited = 0;
19094   for (rootsonly = 1; rootsonly >= 0; rootsonly--) {
19095     count = 0;
19096     first = mod = 2*(lgl->nvars - 2);
19097     assert (mod > 0);
19098     pos = lglrand (lgl) % mod;
19099     delta = lglrand (lgl) % mod;
19100     if (!delta) delta++;
19101     while (lglgcd (delta, mod) > 1)
19102       if (++delta == mod) delta = 1;
19103     LOG (2, "unhiding %s round start %u delta %u mod %u",
19104 	 (rootsonly ? "roots-only": "non-root"), pos, delta, mod);
19105     for (;;) {
19106       if (lglterminate (lgl)) { searches = 0; goto DONE; }
19107       if (!lglsyncunits (lgl)) { assert (lgl->mt); goto DONE; }
19108       ulit = pos + 4;
19109       root = lglilit (ulit);
19110       INCSTEPS (unhd.steps);
19111       count++;
19112       if (lglval (lgl, root)) goto CONTINUE;
19113       if (rootsonly) unassigned++;
19114       if (dfpr[lglulit (root)].discovered) goto CONTINUE;
19115       if (rootsonly &&
19116 	  !lglunhdisroot (lgl, root, dfpr, irronly)) goto CONTINUE;
19117       if (!lglunhdhasbins (lgl, dfpr, -root, irronly)) {
19118 	if (rootsonly) noimpls++;
19119 	goto CONTINUE;
19120       }
19121       if (rootsonly) roots++;
19122       searches++;
19123       assert (lglmtstk (&units));
19124       stamp = lglstamp (lgl, root, dfpr, dfopf,
19125 			&work, &units, &sccs, &trds, &visited,
19126 			stamp, irronly);
19127       while (!lglmtstk (&units)) {
19128 	lit = lglpopstk (&units);
19129 	val = lglval (lgl, lit);
19130 	if (val > 0) continue;
19131 	if (val < 0) {
19132 	  assert (!lgl->mt);
19133 	  LOG (1, "unhidding stamp unit %d already false", lit);
19134 	  lglmt (lgl);
19135 	  goto DONE;
19136 	}
19137 	lglunit (lgl, lit);
19138 	if (!lglbcp (lgl)) {
19139 	  assert (!lgl->mt);
19140 	  LOG (1, "propagating unhidden stamp unit %d failed", lit);
19141 	  lglmt (lgl);
19142 	  goto DONE;
19143 	}
19144       }
19145 CONTINUE:
19146       last = pos;
19147       pos += delta;
19148       if (pos >= mod) pos -= mod;
19149       if (pos == first) { assert (count == mod); break; }
19150       if (mod == 1) break;
19151       if (first == mod) first = last;
19152     }
19153   }
19154   assert (searches >= roots);
19155   lglprt (lgl, 2,
19156 	  "[unhd-%d-%d] %d unassigned variables out of %d (%.0f%%)",
19157 	  lgl->stats->unhd.count, lgl->stats->unhd.rounds,
19158 	  lgl->unassigned, lgl->nvars - 2,
19159 	    lglpcnt (lgl->unassigned, lgl->nvars - 2));
19160   lglprt (lgl, 2,
19161 	  "[unhd-%d-%d] %d root literals out of %d (%.0f%%)",
19162 	  lgl->stats->unhd.count, lgl->stats->unhd.rounds,
19163 	  roots, unassigned, lglpcnt (roots, unassigned));
19164   lglprt (lgl, 2,
19165     "[unhd-%d-%d] %d additional non-root searches out of %d (%.0f%%)",
19166 	  lgl->stats->unhd.count, lgl->stats->unhd.rounds,
19167 	  searches - roots, unassigned,
19168 	    lglpcnt (searches - roots, unassigned));
19169   lglprt (lgl, 2,
19170 	  "[unhd-%d-%d] %d literals not in F2 out of %d (%.0f%%)",
19171 	  lgl->stats->unhd.count, lgl->stats->unhd.rounds,
19172 	  noimpls, unassigned, lglpcnt (noimpls, unassigned));
19173   lglprt (lgl, 2,
19174 	  "[unhd-%d-%d] %d visited literals out of %d (%.0f%%)",
19175 	  lgl->stats->unhd.count, lgl->stats->unhd.rounds,
19176 	  visited, unassigned, lglpcnt (visited, unassigned));
19177   lglprt (lgl, 2,
19178 	  "[unhd-%d-%d] %.2f average number visited literals per search",
19179 	  lgl->stats->unhd.count, lgl->stats->unhd.rounds,
19180 	  lglavg (visited, searches));
19181 DONE:
19182   if (!searches || lgl->mt) { DEL (dfpr, 2*lgl->nvars); dfpr = 0; }
19183   lglrelwtk (lgl, &work);
19184   lglrelstk (lgl, &units);
19185   lglrelstk (lgl, &sccs);
19186   lglrelstk (lgl, &trds);
19187   DEL (dfopf, 2*lgl->nvars);
19188   return dfpr;
19189 }
19190 
lglsetunhdlim(LGL * lgl)19191 static void lglsetunhdlim (LGL * lgl) {
19192   int64_t limit, irrlim;
19193   int pen, szpen;
19194   limit = (lgl->opts->unhdreleff.val*lglvisearch (lgl))/1000;
19195   if (limit < lgl->opts->unhdmineff.val) limit = lgl->opts->unhdmineff.val;
19196   if (lgl->opts->unhdmaxeff.val >= 0 && limit > lgl->opts->unhdmaxeff.val)
19197     limit = lgl->opts->unhdmaxeff.val;
19198   limit >>= (pen = lgl->limits->unhd.pen + (szpen = lglszpenaux (lgl, 1, 1)));
19199   irrlim = (lgl->stats->irr.clauses.cur/16) >> szpen;
19200   if (lgl->opts->irrlim.val && limit < irrlim) {
19201     limit = irrlim;
19202     lglprt (lgl, 1,
19203       "[unhide-%d] limit %lld based on %d irredundant clauses penalty %d",
19204       lgl->stats->unhd.count,
19205       (LGLL) limit, lgl->stats->irr.clauses.cur, szpen);
19206   } else
19207     lglprt (lgl, 1, "[unhide-%d] limit %lld with penalty %d = %d + %d",
19208       lgl->stats->unhd.count, (LGLL) limit,
19209       pen, lgl->limits->unhd.pen, szpen);
19210   lgl->limits->unhd.steps = lgl->stats->unhd.steps + limit;
19211 }
19212 
lglunhide(LGL * lgl)19213 static int lglunhide (LGL * lgl) {
19214   int irronly, round, maxrounds, noprgssrounds, success;
19215   int oldunits, oldfailed, oldtauts, oldhbrs, oldstrd;
19216   int deltaunits, deltafailed;
19217   int64_t roundprgss = 0;
19218   DFPR * dfpr = 0;
19219   assert (lgl->opts->unhide.val);
19220   if (lgl->nvars <= 2) return 1;
19221   lgl->stats->unhd.count++;
19222   assert (!lgl->unhiding);
19223   lgl->unhiding = 1;
19224   assert (!lgl->simp);
19225   lgl->simp = 1;
19226   lglstart (lgl, &lgl->times->unhide);
19227   irronly = !lgl->stats->red.bin || (lgl->stats->unhd.count & 1);
19228   if (lgl->level > 0) lglbacktrack (lgl, 0);
19229   maxrounds = lgl->opts->unhdroundlim.val;
19230   lglsetunhdlim (lgl);
19231   oldunits = lglunhdunits (lgl);
19232   oldfailed = lglunhdfailed (lgl);
19233   oldtauts = lglunhdtauts (lgl);
19234   oldhbrs = lglunhdhbrs (lgl);
19235   oldstrd = lglunhdstrd (lgl);
19236   noprgssrounds = round = 0;
19237   while (!lgl->mt) {
19238     if (round >= maxrounds) break;
19239     if (round > 0 &&
19240         roundprgss == lgl->stats->prgss &&
19241 	noprgssrounds++ == lgl->opts->unhdlnpr.val) {
19242       LOG (1, "too many non progress unhiding rounds");
19243       break;
19244     }
19245     round++;
19246     roundprgss = lgl->stats->prgss;
19247     lgl->stats->unhd.rounds++;
19248     lglgc (lgl);
19249     if (!lgl->nvars || lgl->mt) break;
19250     assert (!dfpr);
19251     dfpr = lglstampall (lgl, irronly);
19252     if (!dfpr) break;
19253     if (!lglunhidefailed (lgl, dfpr)) break;
19254     if (!lglunhidebintrn (lgl, dfpr, irronly)) break;
19255     if (!lglunhidelrg (lgl, dfpr, irronly)) break;
19256     if (lgl->stats->unhd.steps >= lgl->limits->unhd.steps) break;
19257     irronly = !lgl->stats->red.bin || !irronly;
19258     DEL (dfpr, 2*lgl->nvars);
19259     assert (!dfpr);
19260   }
19261   if (dfpr) DEL (dfpr, 2*lgl->nvars);
19262   lglprt (lgl, 1,
19263     "[unhide-%d-%d] %d units, %d failed, %d tauts, %d hbrs, %d literals",
19264     lgl->stats->unhd.count, lgl->stats->unhd.rounds,
19265     (deltaunits = lglunhdunits (lgl) - oldunits),
19266     (deltafailed = lglunhdfailed (lgl) - oldfailed),
19267     lglunhdtauts (lgl) - oldtauts,
19268     lglunhdhbrs (lgl) - oldhbrs,
19269     lglunhdstrd (lgl) - oldstrd);
19270   success = deltaunits + deltafailed;
19271   LGLUPDPEN (unhd, success);
19272   assert (lgl->simp);
19273   lgl->simp = 0;
19274   assert (lgl->unhiding);
19275   lgl->unhiding = 0;
19276   lglrep (lgl, 2, 'u');
19277   lglstop (lgl);
19278   return !lgl->mt;
19279 }
19280 
lglpar64(uint64_t i)19281 static int lglpar64 (uint64_t i) {
19282   unsigned x;
19283   int res = 0;
19284   for (x = i; x; x = x & (x - 1))
19285     res = !res;
19286   return res;
19287 }
19288 
lgldec64(uint64_t i)19289 static uint64_t lgldec64 (uint64_t i) {
19290   uint64_t res;
19291   for (res = i - 1; lglpar64 (res); res--)
19292     ;
19293   return res;
19294 }
19295 
lglgdump(LGL * lgl)19296 static void lglgdump (LGL * lgl) {
19297 #ifndef NLGLOG
19298   const int * p, * start, * top;
19299   start = lgl->gauss->xors.start;
19300   top = lgl->gauss->xors.top;
19301   for (p = start; p < top; p++) {
19302     if (*p >= NOTALIT) continue;
19303     fprintf (lgl->out, "c eqn[%lld]", (LGLL)(p - start));
19304     while (*p > 1) fprintf (lgl->out, " %d", *p++);
19305     fprintf (lgl->out, " = %d\n", *p);
19306   }
19307 #endif
19308 }
19309 
lglgaussubclsaux(LGL * lgl,uint64_t signs,const int * c)19310 static int lglgaussubclsaux (LGL * lgl, uint64_t signs,  const int * c) {
19311   int lit, i, min, minocc, tmpocc, blit, tag, other, other2, red, lidx;
19312   const int * p, * w, * eow, * d, * q;
19313   HTS * hts;
19314   assert (lgl->dense);
19315   minocc = INT_MAX;
19316   min = i = 0;
19317   INCSTEPS (gauss.steps.extr);
19318   for (p = c; (lit = *p); p++) {
19319     if (lglmarked (lgl, lit)) return 0;
19320     assert (i < 8 * sizeof signs);
19321     if (signs & (1ull << i++)) lit = -lit;
19322     lglsignedmark (lgl, lit);
19323     tmpocc = lglocc (lgl, lit) + lglhts (lgl, lit)->count;
19324     assert (tmpocc < INT_MAX);
19325     if (tmpocc >= minocc) continue;
19326     minocc = tmpocc;
19327     min = lit;
19328   }
19329   assert (min);
19330   hts = lglhts (lgl, min);
19331   w = lglhts2wchs (lgl, hts);
19332   eow = w + hts->count;
19333   for (p = w; p < eow; p++) {
19334     INCSTEPS (gauss.steps.extr);
19335     blit = *p;
19336     tag = blit & MASKCS;
19337     if (tag == TRNCS || tag == LRGCS) p++;
19338     if (tag == LRGCS) continue;
19339     if (tag == BINCS) {
19340       other = blit >> RMSHFT;
19341       if (lglsignedmarked (lgl, other)) return 1;
19342     } else if (tag == TRNCS) {
19343       other = blit >> RMSHFT;
19344       if (!lglsignedmarked (lgl, other)) continue;
19345       other2 = *p;
19346       if (lglsignedmarked (lgl, other2)) return 1;
19347     } else {
19348       assert (tag == OCCS);
19349       red = blit & REDCS;
19350       lidx = blit >> RMSHFT;
19351       d = lglidx2lits (lgl, red, lidx);
19352       for (q = d; (other = *q); q++)
19353 	if (!lglsignedmarked (lgl, other)) break;
19354       if (!other) return 1;
19355     }
19356   }
19357   return 0;
19358 }
19359 
lglgaussubcls(LGL * lgl,uint64_t signs,const int * c)19360 static int lglgaussubcls (LGL * lgl, uint64_t signs,  const int * c) {
19361   int res = lglgaussubclsaux (lgl, signs, c), lit;
19362   const int * p;
19363   for (p = c; (lit = *p); p++) lglunmark (lgl, lit);
19364   return res;
19365 }
19366 
19367 #define GL 2
19368 
lglgaussextractxoraux(LGL * lgl,const int * c)19369 static int lglgaussextractxoraux (LGL * lgl, const int * c) {
19370   int lit, val, size, maxsize, negs, start, max, *d, * q;
19371   int allxors = lgl->opts->gaussextrall.val;
19372   uint64_t signs;
19373   const int * p;
19374   assert (!lgl->level);
19375   maxsize = lgl->opts->gaussmaxor.val;
19376   max = negs = size = 0;
19377   start = lglcntstk (&lgl->gauss->xors);
19378   for (p = c; (lit = *p); p++) {
19379     if ((val = lglval (lgl, lit)) > 0) return 0;
19380     if (val < 0) continue;
19381     if (lit < 0) {
19382       if (!allxors && negs) return 0;
19383       negs = !negs;
19384     }
19385     if (!max || abs (max) < abs (lit)) max = lit;
19386     lglpushstk (lgl, &lgl->gauss->xors, lit);
19387     if (++size > maxsize) return 0;
19388   }
19389   assert (negs == 0 || negs == 1);
19390   if (size <= 1) return 0;
19391   if (!allxors && negs && max > 0) return 0;
19392   lglpushstk (lgl, &lgl->gauss->xors, 0);
19393   d = lgl->gauss->xors.start + start;
19394   assert (size <= 8 * sizeof signs);
19395   signs = lgldec64 (1ull << size);
19396   do {
19397     if (!lglgaussubcls (lgl, signs, d)) break;
19398     signs = lgldec64 (signs);
19399   } while (signs &&
19400            lgl->stats->gauss.steps.extr < lgl->limits->gauss.steps.extr);
19401   if (signs) return 0;
19402   for (q = d; (lit = *q); q++) *q = abs (lit);
19403   *q = !negs;
19404   LOGEQN (GL, start, "extracted %d-ary XOR constraint",  size);
19405   lgl->stats->gauss.arity.sum += size;
19406   if (lgl->stats->gauss.arity.max.total < size)
19407     lgl->stats->gauss.arity.max.total = size;
19408   if (lgl->stats->gauss.arity.max.last < size)
19409     lgl->stats->gauss.arity.max.last = size;
19410   lgl->stats->gauss.extracted.total++;
19411   lgl->stats->gauss.extracted.last++;
19412   return 1;
19413 }
19414 
lglgaussextractxor(LGL * lgl,const int * c)19415 static int lglgaussextractxor (LGL * lgl, const int * c) {
19416   int old = lglcntstk (&lgl->gauss->xors), res;
19417   if (!(res = lglgaussextractxoraux (lgl, c)))
19418     lglrststk (&lgl->gauss->xors, old);
19419   return res;
19420 }
19421 
lglgaussextractsmallit(LGL * lgl,int lit)19422 static int lglgaussextractsmallit (LGL * lgl, int lit) {
19423   int allxors = lgl->opts->gaussextrall.val;
19424   int cls[4], blit, tag, other, other2;
19425   const int * w, * eow, * p;
19426   HTS * hts;
19427   if (lgl->stats->gauss.steps.extr >= lgl->limits->gauss.steps.extr)
19428     return 0;
19429   if (lglval (lgl, lit) > 0) return 1;
19430   hts = lglhts (lgl, lit);
19431   w = lglhts2wchs (lgl, hts);
19432   eow = w + hts->count;
19433   for (p = w; p < eow; p++) {
19434     blit = *p;
19435     tag = blit & MASKCS;
19436     if (tag == TRNCS || tag == LRGCS) p++;
19437     if (tag == OCCS || tag == LRGCS) continue;
19438     other = blit >> RMSHFT;
19439     if (!allxors && abs (other) < lit) continue;
19440     cls[0] = lit;
19441     cls[1] = other;
19442     if (tag == TRNCS) {
19443       other2 = *p;
19444       if (!allxors && abs (other2) < lit) continue;
19445       cls[2] = other2;
19446       cls[3] = 0;
19447     } else {
19448       assert (tag == BINCS);
19449       cls[2] = 0;
19450     }
19451     lglgaussextractxor (lgl, cls);
19452   }
19453   return 1;
19454 }
19455 
lglgaussextractsmall(LGL * lgl)19456 static int lglgaussextractsmall (LGL * lgl) {
19457   int64_t before = lgl->stats->gauss.extracted.total, after, delta;
19458   int res;
19459   lglrandlitrav (lgl, lglgaussextractsmallit);
19460   after = lgl->stats->gauss.extracted.total;
19461   delta = after - before;
19462   res = (delta > INT_MAX) ? INT_MAX : delta;
19463   return res;
19464 }
19465 
lglgaussextractlarge(LGL * lgl)19466 static int lglgaussextractlarge (LGL * lgl) {
19467   const int * p, * c;
19468   int res = 0;
19469   for (c = lgl->irr.start; c < lgl->irr.top; c = p + 1) {
19470     if (lgl->stats->gauss.steps.extr >= lgl->limits->gauss.steps.extr) break;
19471     if (*(p = c) >= NOTALIT) continue;
19472     res += lglgaussextractxor (lgl, c);
19473     while (*p) p++;
19474   }
19475   return res;
19476 }
19477 
lglgaussconeqn(LGL * lgl,int eqn)19478 static void lglgaussconeqn (LGL * lgl, int eqn) {
19479   const int * xors = lgl->gauss->xors.start;
19480   int i, var;
19481   INCSTEPS (gauss.steps.elim);
19482   for (i = eqn; (var = xors[i]) > 1; i++)
19483     lglpushstk (lgl, lgl->gauss->occs + var, eqn);
19484 }
19485 
lglgaussdiseqn(LGL * lgl,int eqn)19486 static void lglgaussdiseqn (LGL * lgl, int eqn) {
19487   int * xors = lgl->gauss->xors.start, i, var;
19488   for (i = eqn; (var = xors[i]) > 1; i++) {
19489     xors[i] = NOTALIT;
19490     lgl->gauss->garbage++;
19491     INCSTEPS (gauss.steps.elim);
19492     lglrmstk (lgl->gauss->occs + var, eqn);
19493   }
19494   xors[i] = NOTALIT;
19495   lgl->gauss->garbage++;
19496 }
19497 
lglgaussconnect(LGL * lgl)19498 static void lglgaussconnect (LGL * lgl) {
19499   int c, i, eox = lglcntstk (&lgl->gauss->xors), connected, var, vars;
19500   const int * xors = lgl->gauss->xors.start;
19501   Stk * occs;
19502   LOG (2,  "connecting equations");
19503   assert (!lgl->gauss->occs);
19504   NEW (lgl->gauss->occs, lgl->nvars);
19505   vars = connected = 0;
19506   for (c = 0; c < eox; c = i + 1) {
19507     INCSTEPS (gauss.steps.elim);
19508     for (i = c; (var = xors[i]) > 1; i++) {
19509       occs = lgl->gauss->occs + var;
19510       if (lglmtstk (occs)) vars++;
19511       lglpushstk (lgl, lgl->gauss->occs + var, c);
19512       connected++;
19513     }
19514   }
19515   lglprt (lgl, 1,
19516      "[gauss-%d] connected %d occurrences of %d variables (average %.1f)",
19517       lgl->stats->gauss.count, connected, vars, lglavg (connected, vars));
19518 }
19519 
lglgaussorderidx(LGL * lgl,int var)19520 static int lglgaussorderidx (LGL * lgl,  int var) {
19521   assert (2 <= var && var < lgl->nvars);
19522   if (!lglmtstk (lgl->gauss->occs + var))
19523     lglpushstk (lgl, &lgl->gauss->order, var);
19524   return 1;
19525 }
19526 
lglgaussorder(LGL * lgl)19527 static void lglgaussorder (LGL * lgl) {
19528   lglrandidxtrav (lgl, lglgaussorderidx);
19529   NEW (lgl->gauss->eliminated, lgl->nvars);
19530 }
19531 
lglgaussdisconnect(LGL * lgl)19532 static void lglgaussdisconnect (LGL * lgl) {
19533   int idx;
19534   assert (lgl->gauss->occs);
19535   LOG (2, "disconnecting equations");
19536   for (idx = 2; idx < lgl->nvars; idx++)
19537     lglrelstk (lgl, lgl->gauss->occs + idx);
19538   DEL (lgl->gauss->occs, lgl->nvars);
19539   assert (!lgl->gauss->occs);
19540 }
19541 
lglgaussextract(LGL * lgl)19542 static void lglgaussextract (LGL * lgl) {
19543   int extracted, lits;
19544   assert (lglsmallirr (lgl));
19545   if (lgl->level) lglbacktrack (lgl, 0);
19546   lglgc (lgl);
19547   if (lgl->mt) return;
19548   lgldense (lgl, 0);
19549   extracted = lglgaussextractsmall (lgl);
19550   extracted += lglgaussextractlarge (lgl);
19551   lits = lglcntstk (&lgl->gauss->xors) - extracted;
19552   lglprt (lgl, 1,
19553     "[gauss-%d] extracted %d xors of average arity %.1f",
19554     lgl->stats->gauss.count, extracted, lglavg (lits, extracted));
19555   lglsparse (lgl);
19556   lglgc (lgl);
19557   if (lgl->mt) return;
19558   lglfitstk (lgl, &lgl->gauss->xors);
19559 }
19560 
lglgaussoccs(LGL * lgl,int a)19561 static int lglgaussoccs (LGL * lgl, int a) {
19562   return lglcntstk (lgl->gauss->occs + a);
19563 }
19564 
lglcmpgauss(LGL * lgl,int a,int b)19565 static int lglcmpgauss (LGL * lgl, int a, int b) {
19566   int res = lglgaussoccs (lgl, a) - lglgaussoccs (lgl, b);
19567   if (!res) res = a - b;
19568   return res;
19569 }
19570 
19571 #define LGLCMPGAUSS(A,B) lglcmpgauss (lgl, *(A), *(B))
19572 
lglgaussort(LGL * lgl)19573 static void lglgaussort (LGL * lgl) {
19574   int max = lglcntstk (&lgl->gauss->order), rest, * start;
19575   assert (lgl->gauss->next <= max);
19576   rest = max - lgl->gauss->next;
19577   start = lgl->gauss->order.start + lgl->gauss->next;
19578   ADDSTEPS (gauss.steps.elim, rest);
19579   SORT (int, start, rest, LGLCMPGAUSS);
19580   lglprt (lgl, 3,
19581      "[gauss-%d] sorted %d remaining variables",
19582       lgl->stats->gauss.count, rest);
19583 }
19584 
lglgausspickeqn(LGL * lgl,int pivot)19585 static int lglgausspickeqn (LGL * lgl, int pivot) {
19586   int res, cand, weight, size, tmp, other, found;
19587   const int * p, * e, * q;
19588   Stk * occs;
19589   assert (lglgaussoccs (lgl, pivot));
19590   res = -1;
19591   weight = INT_MAX; size = INT_MAX;
19592   occs = lgl->gauss->occs + pivot;
19593   for (p = occs->start; p < occs->top; p++) {
19594     e = lgl->gauss->xors.start + (cand = *p);
19595     found = tmp = 0;
19596     INCSTEPS (gauss.steps.elim);
19597     for (q = e; (other = *q) > 1; q++) {
19598       if (lgl->gauss->eliminated[other]) break;
19599       if (other == pivot) { assert (!found); found++; continue; }
19600       tmp += lglgaussoccs (lgl, other) - 1;
19601     }
19602     if (other > 1) continue;
19603     assert (found);
19604     if (res >= 0 && q - e >= size) continue;
19605     if (res >= 0 && q - e == size && tmp >= weight) continue;
19606     weight = tmp;
19607     size = q - e;
19608     res = cand;
19609   }
19610   if (res >= 0)
19611     LOGEQN (2, res, "picking size %d weight %d equation", size, weight);
19612   else
19613     LOG (2, "no uneliminated equation for pivot %d left", pivot);
19614   return res;
19615 }
19616 
lglcpystk(LGL * lgl,Stk * dst,Stk * src)19617 static void lglcpystk (LGL * lgl, Stk * dst, Stk * src) {
19618   const int * p;
19619   for (p = src->start; p < src->top; p++)
19620     lglpushstk (lgl, dst, *p);
19621 }
19622 
lglgaussaddeqn(LGL * lgl,int eqn)19623 static int lglgaussaddeqn (LGL * lgl, int eqn) {
19624   const int * p;
19625   AVar * av;
19626   int var;
19627   for (p = lgl->gauss->xors.start + eqn; (var = *p) > 1; p++) {
19628     av = lglavar (lgl, var);
19629     if (!av->mark) lglpushstk (lgl, &lgl->clause, var);
19630     av->mark = !av->mark;
19631   }
19632   return var;
19633 }
19634 
lglgaussubst(LGL * lgl,int pivot,int subst)19635 static void lglgaussubst (LGL * lgl, int pivot, int subst) {
19636   Stk * occs = lgl->gauss->occs + pivot;
19637   int eqn, rhs, res;
19638   const int * p;
19639   int * q;
19640   assert (lglcntstk (occs) > 1);
19641   while (lglcntstk (occs) > 1) {
19642     if (lglterminate (lgl)) return;
19643     eqn = occs->start[0];
19644     if (eqn == subst) eqn = occs->start[1];
19645     assert (lglmtstk (&lgl->clause));
19646     LOGEQN (2, subst, "  1st row (kept)     ");
19647     rhs = lglgaussaddeqn (lgl, eqn);
19648     LOGEQN (2, eqn, "  2nd row (replaced) ");
19649     if (lglgaussaddeqn (lgl, subst)) rhs = !rhs;
19650     lglgaussdiseqn (lgl, eqn);
19651     q = lgl->clause.start;
19652     for (p = q; p < lgl->clause.top; p++)
19653       if (lglmarked (lgl, *p)) *q++ = *p;
19654     lgl->clause.top = q;
19655     if (!lglmtstk (&lgl->clause)) {
19656       res = lglcntstk (&lgl->gauss->xors);
19657       lglcpystk (lgl, &lgl->gauss->xors, &lgl->clause);
19658       lglpushstk (lgl, &lgl->gauss->xors, rhs);
19659       LOGEQN (2, res, "  result row         ");
19660       lglgaussconeqn (lgl, res);
19661     } else if (rhs == 0) {
19662       LOG (2, "trivial result row 0 = 0");
19663     } else {
19664       assert (rhs == 1);
19665       LOG (1, "inconsistent result row 0 = 1 from gaussian elimination");
19666       lgl->mt= 1;
19667     }
19668     lglpopnunmarkstk (lgl, &lgl->clause);
19669   }
19670 }
19671 
lglgausschkeliminated(LGL * lgl)19672 static void lglgausschkeliminated (LGL * lgl) {
19673 #ifndef NDEBUG
19674   int idx, eliminated, occs;
19675   if (!lgl->opts->check.val) return;
19676   for (idx = 2; idx < lgl->nvars; idx++) {
19677     eliminated = lgl->gauss->eliminated[idx];
19678     occs = lglgaussoccs (lgl, idx);
19679     if (eliminated == 1) assert (occs == 1);
19680     if (eliminated == 2) assert (occs == 0);
19681   }
19682 #endif
19683 }
19684 
lglgaussgc(LGL * lgl)19685 static void lglgaussgc (LGL * lgl) {
19686   int count = lglcntstk (&lgl->gauss->xors), * q;
19687   const int * p;
19688   if (lgl->gauss->garbage < count/2 + 10000) return;
19689   lgl->stats->gauss.gcs++;
19690   lglprt (lgl, 2,
19691      "[gauss-%d] collecting %d garbage out of %d",
19692      lgl->stats->gauss.count, lgl->gauss->garbage, count);
19693   lglgaussdisconnect (lgl);
19694   q = lgl->gauss->xors.start;
19695   for (p = q; p < lgl->gauss->xors.top; p++)
19696     if (*p != NOTALIT) *q++ = *p;
19697   lgl->gauss->xors.top = q;
19698   lglfitstk (lgl, &lgl->gauss->xors);
19699   lglgaussconnect (lgl);
19700   lgl->gauss->garbage = 0;
19701 }
19702 
lglgausselimvar(LGL * lgl,int pivot)19703 static int lglgausselimvar (LGL * lgl, int pivot) {
19704   int subst, changed, occs, eliminated;
19705   LOG (2, "eliminating variable %d occurring %d times",
19706        pivot, lglgaussoccs (lgl, pivot));
19707   assert (!lgl->gauss->eliminated[pivot]);
19708   if (!(occs = lglgaussoccs (lgl, pivot))) {
19709     LOG (2, "variable %d disappeared ", pivot);
19710     eliminated = 2;
19711     changed = 0;
19712   } else if (occs == 1) {
19713     LOG (2, "eliminated variable %d occurrs exactly once", pivot);
19714     eliminated = 1;
19715     changed = 0;
19716   } else {
19717     lglgaussgc (lgl);
19718     subst = lglgausspickeqn (lgl, pivot);
19719     if (subst >= 0) {
19720       lglgaussubst (lgl, pivot, subst);
19721       eliminated = 1;
19722       changed = 1;
19723     } else {
19724       eliminated = 3;
19725       changed = 0;
19726     }
19727   }
19728   lgl->gauss->eliminated[pivot] = eliminated;
19729   lglgausschkeliminated (lgl);
19730   return changed;
19731 }
19732 
lglgausselim(LGL * lgl)19733 static void lglgausselim (LGL * lgl) {
19734   int pivot, changed = 1;
19735   while (!lgl->mt && lgl->gauss->next < lglcntstk (&lgl->gauss->order)) {
19736     if (lgl->stats->gauss.steps.elim >= lgl->limits->gauss.steps.elim) break;
19737     if (lglterminate (lgl)) break;
19738     if (changed) lglgaussort (lgl);
19739     pivot = lglpeek (&lgl->gauss->order, lgl->gauss->next++);
19740     changed = lglgausselimvar (lgl, pivot);
19741   }
19742 }
19743 
lglgaussinit(LGL * lgl)19744 static void lglgaussinit (LGL * lgl) {
19745   assert (!lgl->gauss);
19746   NEW (lgl->gauss, 1);
19747 }
19748 
lglgaussreset(LGL * lgl)19749 static void lglgaussreset (LGL * lgl) {
19750   assert (lgl->gauss);
19751   if (lgl->gauss->occs) lglgaussdisconnect (lgl);
19752   if (lgl->gauss->eliminated) DEL (lgl->gauss->eliminated, lgl->nvars);
19753   lglrelstk (lgl, &lgl->gauss->xors);
19754   lglrelstk (lgl, &lgl->gauss->order);
19755   DEL (lgl->gauss, 1);
19756 }
19757 
lglgaussexp2(LGL * lgl,int a,int b)19758 static int lglgaussexp2 (LGL * lgl, int a, int b) {
19759   assert (lgl->gaussing);
19760   assert (lglmtstk (&lgl->clause));
19761   if (lglhasbin (lgl, a, b)) return 0;
19762   lglpushstk (lgl, &lgl->clause, a);
19763   lglpushstk (lgl, &lgl->clause, b);
19764   lglpushstk (lgl, &lgl->clause, 0);
19765   LOGCLS (2, lgl->clause.start, "gauss exported binary clause");
19766   lgladdcls (lgl, REDCS, 0, 0);
19767   lglclnstk (&lgl->clause);
19768   return 1;
19769 }
19770 
lglgaussexp3(LGL * lgl,int a,int b,int c)19771 static int lglgaussexp3 (LGL * lgl, int a, int b, int c) {
19772   assert (lgl->gaussing);
19773   assert (lglmtstk (&lgl->clause));
19774   if (lglhastrn (lgl, a, b, c)) return 0;
19775   lglpushstk (lgl, &lgl->clause, a);
19776   lglpushstk (lgl, &lgl->clause, b);
19777   lglpushstk (lgl, &lgl->clause, c);
19778   lglpushstk (lgl, &lgl->clause, 0);
19779   LOGCLS (2, lgl->clause.start, "gauss exported ternary clause");
19780   lgladdcls (lgl, REDCS, 0, 0);
19781   lglclnstk (&lgl->clause);
19782   return 1;
19783 }
19784 
lglgaussexport(LGL * lgl)19785 static int lglgaussexport (LGL * lgl) {
19786   int var, size, val, rhs, unit, a, b, c, exported;
19787   const int * e, * p, * q;
19788   for (e = lgl->gauss->xors.start; e < lgl->gauss->xors.top; e = p + 1) {
19789     if (*(p = e) >= NOTALIT) continue;
19790     while ((var = *p) > 1) p++;
19791     rhs = *p;
19792     assert (lglmtstk (&lgl->clause));
19793     for (q = e; q < p; q++) {
19794       var = *q;
19795       val = lglval (lgl, var);
19796       if (val < 0) continue;
19797       if (val > 0) { rhs = !rhs; continue; }
19798       lglpushstk (lgl, &lgl->clause, var);
19799     }
19800     size = lglcntstk (&lgl->clause);
19801     if (!size && !rhs) continue;
19802     if (!size && rhs) {
19803       LOGEQN (1, e - lgl->gauss->xors.start,
19804               "gauss exporting inconsistent equation");
19805       return 0;
19806     }
19807     a = (size > 0) ? lgl->clause.start[0] : 0;
19808     b = (size > 1) ? lgl->clause.start[1] : 0;
19809     c = (size > 2) ? lgl->clause.start[2] : 0;
19810     lglclnstk (&lgl->clause);
19811     if (size == 1) {
19812       unit = a;
19813       if (!rhs) unit = -unit;
19814       LOG (1, "gauss exporting unit %d", unit);
19815       lgl->stats->gauss.units++;
19816       lglunit (lgl, unit);
19817     } else if (size == 2) {
19818       if (rhs) b = -b;
19819       exported = lglgaussexp2 (lgl, -a, b);
19820       exported |= lglgaussexp2 (lgl, a, -b);
19821       if (exported) {
19822 	LOG (1, "gauss exporting equivalence %d = %d", a, b);
19823 	lgl->stats->gauss.equivs++;
19824       }
19825     } else if (size == 3 && lgl->opts->gaussexptrn.val) {
19826       if (!rhs) c = -c;
19827       exported = lglgaussexp3 (lgl, a, b, c);
19828       exported |= lglgaussexp3 (lgl, a, -b, -c);
19829       exported |= lglgaussexp3 (lgl, -a, b, -c);
19830       exported |= lglgaussexp3 (lgl, -a, -b, c);
19831       if (exported) {
19832 	LOG (1, "gauss exporting ternary equation %d + %d + %d = 1",
19833 	     a, b, c);
19834 	lgl->stats->gauss.trneqs++;
19835       }
19836     }
19837   }
19838   return 1;
19839 }
19840 
lglsetgausslim(LGL * lgl)19841 static void lglsetgausslim (LGL * lgl) {
19842   int64_t limit, irrlim;
19843   int pen, szpen;
19844   limit = (lgl->opts->gaussreleff.val*lglvisearch (lgl))/1000;
19845   if (limit < lgl->opts->gaussmineff.val) limit = lgl->opts->gaussmineff.val;
19846   if (lgl->opts->gaussmaxeff.val >= 0 && limit > lgl->opts->gaussmaxeff.val)
19847     limit = lgl->opts->gaussmaxeff.val;
19848   limit >>= (pen = lgl->limits->gauss.pen + (szpen = lglszpen (lgl)));
19849   irrlim = (lgl->stats->irr.clauses.cur/2) >> szpen;
19850   if (lgl->opts->irrlim.val && limit < irrlim) {
19851     limit = irrlim;
19852     lglprt (lgl, 1,
19853       "[gauss-%d] limit %lld based on %d irredundant clauses penalty %d",
19854       lgl->stats->gauss.count,
19855       (LGLL) limit, lgl->stats->irr.clauses.cur, szpen);
19856   } else
19857     lglprt (lgl, 1, "[gauss-%d] limit %lld penalty %d = %d + %d",
19858       lgl->stats->gauss.count, (LGLL) limit,
19859       pen, lgl->limits->gauss.pen, szpen);
19860   lgl->limits->gauss.steps.extr = lgl->stats->gauss.steps.extr + limit;
19861   lgl->limits->gauss.steps.elim = lgl->stats->gauss.steps.elim + limit;
19862 }
19863 
lglgauss(LGL * lgl)19864 static int lglgauss (LGL * lgl) {
19865   int oldunits, oldequivs, oldtrneqs;
19866   int units, equivs, trneqs;
19867   int success;
19868   assert (lgl->opts->gauss.val);
19869   if (lgl->mt) return 0;
19870   if (lgl->nvars <= 2) return 1;
19871   lglstart (lgl, &lgl->times->gauss);
19872   assert (!lgl->simp && !lgl->gaussing);
19873   lgl->simp = lgl->gaussing = 1;
19874   lgl->stats->gauss.count++;
19875   lgl->stats->gauss.extracted.last = 0;
19876   lgl->stats->gauss.arity.max.last = 0;
19877   lglsetgausslim (lgl);
19878   lglgaussinit (lgl);
19879   lglgaussextract (lgl);
19880   oldunits = lgl->stats->gauss.units;
19881   oldequivs = lgl->stats->gauss.equivs;
19882   oldtrneqs = lgl->stats->gauss.trneqs;
19883   if (!lglmtstk (&lgl->gauss->xors)) {
19884     lglgaussconnect (lgl);
19885     lglgaussorder (lgl);
19886     lglsetgausslim (lgl);
19887     lglgausselim (lgl);
19888     if (!lgl->mt && !lglterminate (lgl)) {
19889       if (lgl->opts->verbose.val >= 3) lglgdump (lgl);
19890       lglgaussdisconnect (lgl);
19891       if (!lglgaussexport (lgl) || !lglbcp (lgl)) lglmt (lgl);
19892       else if (lgl->limits->gauss.steps.extr > lgl->stats->gauss.steps.extr &&
19893                lgl->limits->gauss.steps.elim > lgl->stats->gauss.steps.elim)
19894 	lglprt (lgl, 1, "[gauss-%d] fully completed", lgl->stats->gauss.count);
19895     }
19896   }
19897   lglgaussreset (lgl);
19898   units = lgl->stats->gauss.units - oldunits;
19899   equivs = lgl->stats->gauss.equivs - oldequivs;
19900   trneqs = lgl->stats->gauss.trneqs - oldtrneqs;
19901   success = units || equivs;
19902   if (!lgl->mt && success && !lglterminate (lgl) && lgl->opts->decompose.val)
19903     lgldecomp (lgl);
19904   if (trneqs) success = 1;
19905   if (lgl->mt)
19906     lglprt (lgl, 1, "[gauss-%d] proved unsatisfiability",
19907       lgl->stats->gauss.count);
19908   else {
19909     lglprt (lgl, 1,
19910       "[gauss-%d] exported %d unary, %d binary and %d ternary equations",
19911       lgl->stats->gauss.count, units, equivs, trneqs);
19912   }
19913   LGLUPDPEN (gauss, success);
19914   lglrep (lgl, 2, 'G');
19915   assert (lgl->simp && lgl->gaussing);
19916   lgl->simp = lgl->gaussing = 0;
19917   lglstop (lgl);
19918   return !lgl->mt;
19919 }
19920 
19921 /*------------------------------------------------------------------------*/
19922 
19923 #define CARDLOGLEVEL 2
19924 
lglcardsub(LGL * lgl,const int * lits,int bound)19925 static int lglcardsub (LGL * lgl, const int * lits, int bound) {
19926   int count, size, res, minlit, minocc, nocc, lit, pos, otherbound;
19927   Card * card = lgl->card;
19928   const int * p, * c, * q;
19929   Stk * s;
19930   minocc = INT_MAX;
19931   minlit = 0;
19932   for (p = lits; minocc && (lit = *p); p++) {
19933     lglmarkunmarked (lgl, lit);
19934     s = card->occs + lit;
19935     INCSTEPS (card.steps);
19936     nocc = lglcntstk (s);
19937     if (nocc > minocc) continue;
19938     minlit = lit;
19939     minocc = nocc;
19940   }
19941   res = 0;
19942   if (minocc && minlit) {
19943     size = p - lits;
19944     s = card->occs + minlit;
19945     for (p = s->start; p < s->top; p++) {
19946       pos = *p;
19947       c = card->cards.start + pos;
19948       INCSTEPS (card.steps);
19949       otherbound = *c;
19950       if (otherbound > bound) continue;
19951       count = 0;
19952       INCSTEPS (card.steps);
19953       for (q = c + 1; *q; q++) count++;
19954       if (count < size) continue;
19955       count = 0;
19956       INCSTEPS (card.steps);
19957       for (q = c + 1; (count < size) && (lit = *q); q++)
19958 	if (lglmarked (lgl, lit) > 0) count++;
19959       if (count >= size) {
19960 	LOGCLS (CARDLOGLEVEL, lits,
19961 	  "subsumed cardinality constraint %d >=", bound);
19962 	LOGCLS (CARDLOGLEVEL, c + 1,
19963 	  "subsuming cardinality constraint %d >=", otherbound);
19964 	res = 1;
19965       }
19966     }
19967   }
19968   for (p = lits; (lit = *p); p++) lglunmark (lgl, lit);
19969   return res;
19970 }
19971 
lglcard1sub(LGL * lgl,const int * lits)19972 static int lglcard1sub (LGL * lgl, const int * lits) {
19973   int res, minlit, minocc, nocc, lit, count, size;
19974   Card * card = lgl->card;
19975   const int * p, * c, * q;
19976   Stk * s;
19977   minocc = INT_MAX;
19978   minlit = 0;
19979   for (p = lits; minocc && (lit = *p); p++) {
19980     lglmarkunmarked (lgl, lit);
19981     s = card->occs + lit;
19982     INCSTEPS (card.steps);
19983     nocc = lglcntstk (s);
19984     if (nocc > minocc) continue;
19985     minlit = lit;
19986     minocc = nocc;
19987   }
19988   res = 0;
19989   if (!minocc || !minlit) goto DONE;
19990   size = p - lits;
19991   s = card->occs + minlit;
19992   count = 0;
19993   for (p = s->start; !res && p < s->top; p++) {
19994     c = card->atmost1.start + *p;
19995     for (q = c; (lit = *q); q++)
19996       if (lglmarked (lgl, lit) && ++count >= size)
19997 	break;
19998     if (!lit) continue;
19999     LOGCLS (CARDLOGLEVEL, lits,
20000       "subsumed at-most-one cardinality constraint 1 >=");
20001     LOGCLS (CARDLOGLEVEL, c,
20002       "subsuming at-most-one cardinality constraint 1 >=");
20003     res = 1;
20004   }
20005 DONE:
20006   for (p = lits; (lit = *p); p++) lglunmark (lgl, lit);
20007   return res;
20008 }
20009 
lglcard2sub(LGL * lgl,const int * lits,int * minlitptr)20010 static int lglcard2sub (LGL * lgl, const int * lits, int * minlitptr) {
20011   int res, minlit, minocc, nocc, lit, count, size;
20012   Card * card = lgl->card;
20013   const int * p, * c, * q;
20014   Stk * s;
20015   minocc = INT_MAX;
20016   minlit = 0;
20017   for (p = lits; minocc && (lit = *p); p++) {
20018     lglmarkunmarked (lgl, lit);
20019     s = card->occs + lit;
20020     INCSTEPS (card.steps);
20021     nocc = lglcntstk (s);
20022     if (nocc > minocc) continue;
20023     minlit = lit;
20024     minocc = nocc;
20025   }
20026   assert (!minocc || p + 1 == card->atmost2.top);
20027   res = 0;
20028   if (!minocc || !minlit || *minlitptr == minlit) goto DONE;
20029   *minlitptr = minlit;
20030   size = p - lits;
20031   s = card->occs + minlit;
20032   count = 0;
20033   for (p = s->start; !res && p < s->top; p++) {
20034     c = card->atmost2.start + *p;
20035     for (q = c; (lit = *q); q++)
20036       if (lglmarked (lgl, lit) && ++count >= size)
20037 	break;
20038     if (!lit) continue;
20039     LOGCLS (CARDLOGLEVEL, lits,
20040       "subsumed at-most-two cardinality constraint 2 >=");
20041     LOGCLS (CARDLOGLEVEL, c,
20042       "subsuming at-most-two cardinality constraint 2 >=");
20043     res = 1;
20044   }
20045 DONE:
20046   for (p = lits; (lit = *p); p++) lglunmark (lgl, lit);
20047   return res;
20048 }
20049 
lgladdcard(LGL * lgl,const int * lits,int bound)20050 static int lgladdcard (LGL * lgl, const int * lits, int bound) {
20051   Card * card = lgl->card;
20052   const int * p;
20053   int start, lit;
20054 #if !defined(NDEBUG) || !defined(NLGLOG)
20055   int size = 0;
20056   for (p = lits; *p; p++) size++;
20057 #endif
20058   if (lglcardsub (lgl, lits, bound)) {
20059     lgl->stats->card.subsumed++;
20060     return 0;
20061   }
20062   LOGCLS (CARDLOGLEVEL, lits,
20063     "new %s cardinality constraint %d >=",
20064     (bound + 1 < size ? "real" : "pseudo"), bound);
20065   assert (bound <= size);
20066   assert (size <=
20067     lglfactor (lgl, lgl->stats->card.count, lgl->opts->cardmaxlen.val));
20068 #ifndef NDEBUG
20069   for (p = lits; (lit = *p); p++) assert (!card->eliminated[abs (lit)]);
20070   for (p = lits; (lit = *p); p++) assert (!card->count[abs (lit)]);
20071 #endif
20072   assert (card);
20073   start = lglcntstk (&card->cards);
20074   lglpushstk (lgl, &card->cards, bound);
20075   for (p = lits; (lit = *p); p++) {
20076     lglpushstk (lgl, &card->cards, lit);
20077     lglpushstk (lgl, card->occs + lit, start);
20078   }
20079   lglpushstk (lgl, &card->cards, 0);
20080   return 1;
20081 }
20082 
lglcardfmstep(LGL * lgl,int pivot,int cardposidx,int cardnegidx)20083 static void lglcardfmstep (LGL * lgl, int pivot,
20084                            int cardposidx, int cardnegidx) {
20085   int bn, bp, ln, lp, b, c, s, lit, idx, addcard, len, unit[2], div, elim;
20086   const int cardcut = lgl->opts->cardcut.val;
20087   const int * p, * q, * cn, * cp;
20088   int * r, divsame, cardmaxlen;
20089   Card * card = lgl->card;
20090   INCSTEPS (card.steps);
20091   lgl->stats->card.resolved++;
20092   assert (0 <= cardposidx && cardposidx < lglcntstk (&card->cards));
20093   assert (0 <= cardnegidx && cardnegidx < lglcntstk (&card->cards));
20094   cp = card->cards.start + cardposidx;
20095   cn = card->cards.start + cardnegidx;
20096   bp = *cp++; assert (bp >= 0);
20097   bn = *cn++; assert (bp >= 0);
20098   LOGCLS (CARDLOGLEVEL, cp,
20099     "first antecedent fourier-motzkin on %d cardinality constraint %d >=",
20100     pivot, bp);
20101   LOGCLS (CARDLOGLEVEL, cn,
20102     "second antecedent fourier-motzkin on %d cardinality constraint %d >=",
20103     -pivot, bn);
20104   b = bp + bn;
20105   LOG (CARDLOGLEVEL, "starting with bound %d", b);
20106   assert (lglmtstk (&lgl->clause));
20107   for (p = cp; (lit = *p); p++) {
20108     idx = abs (lit);
20109     assert (!card->count[idx]);
20110     lglpushstk (lgl, &lgl->clause, idx);
20111     card->count[idx] += lglsgn (lit);
20112   }
20113   lp = p - cp;
20114   assert (bp < lp);
20115   elim = 0;
20116   div = 1;
20117   for (q = cn; (lit = *q); q++) {
20118     idx = abs (lit);
20119     c = card->count[idx];
20120     assert (!c || abs (c) == 1);
20121     s = lglsgn (lit);
20122     if (!c) lglpushstk (lgl, &lgl->clause, idx);
20123     card->count[idx] += s;
20124     if (c && c != s) elim++;
20125     if (c == s) div = 2;
20126   }
20127   ln = q - cn;
20128   assert (bn < ln);
20129   divsame = 1;
20130   for (p = lgl->clause.start; divsame && p < lgl->clause.top; p++) {
20131     idx = abs (*p);
20132     c = card->count[idx];
20133     if (!c) continue;
20134     if (c < 0) c = -c;
20135     divsame = (c == div);
20136   }
20137 #ifndef NLGLOG
20138   if (lgl->opts->log.val >= CARDLOGLEVEL) {
20139     int first = 1;
20140     lglogstart (lgl, CARDLOGLEVEL,
20141       "pseudo-boolean resolvent %d - %d >= ", b, elim);
20142     for (p = lgl->clause.start; p < lgl->clause.top; p++) {
20143       idx = *p;
20144       assert (1 < idx), assert (idx < lgl->nvars);
20145       c = card->count[idx];
20146       if (!c) continue;
20147       if (!first)
20148 	fprintf (lgl->out, " %c ", (c < 0) ? '-' : '+');
20149       else if (c < 0)
20150 	fputs ("-", lgl->out);
20151       first = 0;
20152       c = abs (c);
20153       assert (c > 0);
20154       if (c != 1) fprintf (lgl->out, "%d*", c);
20155       fprintf (lgl->out, "%d", idx);
20156     }
20157     if (first) fputs ("0", lgl->out);
20158     lglogend (lgl);
20159   }
20160 #endif
20161   LOG (CARDLOGLEVEL,
20162     "size %d cardinalty resolvent contains %d eliminated division %d %s",
20163     lglcntstk (&lgl->clause) - elim, elim, div, divsame ? "all" : "some");
20164   r = lgl->clause.start;
20165   for (p = r; p < lgl->clause.top; p++) {
20166     idx = *p;
20167     c = card->count[idx];
20168     if (divsame || cardcut == 1) c /= div;
20169     else if (abs (c) != 1 && cardcut == 2 && div == 2) c = 0;
20170     if (!c) continue;
20171     lit = (c < 0) ? -idx : idx;
20172     *r++ = lit;
20173   }
20174   lgl->clause.top = r;
20175   b -= elim;
20176   assert (div == 1 || div == 2);
20177   if ((divsame || cardcut == 1) && div == 2) b /= 2;
20178   len = lglcntstk (&lgl->clause);
20179   lglpushstk (lgl, &lgl->clause, 0);
20180   addcard = 0;
20181   cardmaxlen =
20182     lglfactor (lgl, lgl->stats->card.count, lgl->opts->cardmaxlen.val);
20183   if (!cardcut && div > 1) {
20184     LOG (CARDLOGLEVEL,
20185       "ignoring resolved cardinality constraint which requires cut");
20186     assert (!addcard);
20187   } else if (b < 0) {
20188     assert (!addcard);
20189     assert (!lgl->mt);
20190     LOGCLS (CARDLOGLEVEL, lgl->clause.start,
20191       "inconsistent cardinality constraint %d >=", b);
20192     lglmt (lgl);
20193   } else if (b == 0) {
20194     assert (!addcard);
20195     LOGCLS (CARDLOGLEVEL, lgl->clause.start,
20196       "forcing cardinality constraint %d >=", b);
20197     for (p = lgl->clause.start; p < lgl->clause.top - 1; p++) {
20198       lit = *p;
20199       assert (lit);
20200       lgl->stats->card.units++;
20201       lglpushstk (lgl, &lgl->card->units, -lit);
20202       card->count[abs (lit)] = 0;
20203       unit[0] = lit;
20204       unit[1] = 0;
20205       (void) lgladdcard (lgl, unit, 0);
20206     }
20207   } else if (b >= len) {
20208     LOGCLS (CARDLOGLEVEL, lgl->clause.start,
20209       "trivial resolved cardinality constraint %d >=", b);
20210     assert (!addcard);
20211   } else if (len > cardmaxlen) {
20212     LOGCLS (CARDLOGLEVEL, lgl->clause.start,
20213       "length %d exceeds limit %d of resolved cardinality constraint %d >=",
20214       len, cardmaxlen, b);
20215   } else {
20216     addcard = 1;
20217     assert (0 < b);
20218     LOGCLS (CARDLOGLEVEL, lgl->clause.start,
20219       "resolved cardinality constraint %d >=", b);
20220     if (b == 1 &&
20221         ((ln >= 3 && lp >= 3) ||
20222          lglcntstk (&lgl->clause) >
20223 	   lglfactor (lgl,
20224 	     lgl->stats->card.count, lgl->opts->cardexpam1.val))) {
20225       LOGCLS (CARDLOGLEVEL, lgl->clause.start,
20226         "saving to export at-most-one constraint 1 >=");
20227       for (p = lgl->clause.start; p < lgl->clause.top; p++)
20228 	lglpushstk (lgl, &lgl->card->expam1, *p);
20229     }
20230   }
20231   cp = card->cards.start + cardposidx + 1;
20232   cn = card->cards.start + cardnegidx + 1;
20233   for (p = cp; (lit = *p); p++) card->count[abs (lit)] = 0;
20234   for (q = cn; (lit = *q); q++) card->count[abs (lit)] = 0;
20235   if (addcard > 0) (void) lgladdcard (lgl, lgl->clause.start, b);
20236   lglclnstk (&lgl->clause);
20237   // COVER (cardcut == 2 && div == 2 && divsame);
20238 }
20239 
lglrmcardexcept(LGL * lgl,int cardidx,int except)20240 static void lglrmcardexcept (LGL * lgl, int cardidx, int except) {
20241   Card * card = lgl->card;
20242   int * c, * p, lit;
20243   assert (0 <= cardidx && cardidx < lglcntstk (&card->cards));
20244   c = card->cards.start + cardidx + 1;
20245   LOGCLS (CARDLOGLEVEL, c, "removing cardinality constraint %d >=", c[-1]);
20246   for (p = c; (lit = *p); p++)
20247     if (lit != except)
20248       lglrmstk (card->occs + lit, cardidx);
20249 }
20250 
lglcardocc(LGL * lgl,int a)20251 static int lglcardocc (LGL * lgl, int a) {
20252   return lglcntstk (lgl->card->occs + a);
20253 }
20254 
lglcmpcard(LGL * lgl,int a,int b)20255 static int lglcmpcard (LGL * lgl, int a, int b) {
20256   int64_t s = lglcardocc (lgl, a) * (int64_t) lglcardocc (lgl, -a);
20257   int64_t t = lglcardocc (lgl, b) * (int64_t) lglcardocc (lgl, -b);
20258   if (s > t) return -1;
20259   if (s < t) return 1;
20260   return b - a;
20261 }
20262 
20263 #define LGLCMPCARD(A,B) lglcmpcard (lgl, *(A), *(B))
20264 
lglcardresched(LGL * lgl)20265 static void lglcardresched (LGL * lgl) {
20266   Stk * elim = &lgl->card->elim;
20267   int count = lglcntstk (elim);
20268   ADDSTEPS (card.steps, 4*count);
20269   SORT (int, elim->start, lglcntstk (elim), LGLCMPCARD);
20270   lgl->stats->card.resched++;
20271 }
20272 
lglcardfmlit(LGL * lgl,int pivot)20273 static void lglcardfmlit (LGL * lgl, int pivot) {
20274   Stk * poccs = lgl->card->occs + pivot, * noccs = lgl->card->occs - pivot;
20275   int pcnt = lglcntstk (poccs), ncnt = lglcntstk (noccs);
20276   int count = lgl->stats->card.count;
20277   const int * p, * q;
20278   assert (pivot > 0);
20279   assert (!lgl->card->eliminated[pivot]);
20280   if (!pcnt || !ncnt) goto DONE;
20281   if (pcnt > lglfactor (lgl, lgl->opts->cardocclim1.val, count)) goto DONE;
20282   if (ncnt > lglfactor (lgl, lgl->opts->cardocclim1.val, count)) goto DONE;
20283   if (pcnt > lglfactor (lgl, lgl->opts->cardocclim2.val, count) &&
20284       ncnt > lglfactor (lgl, lgl->opts->cardocclim2.val, count)) goto DONE;
20285   lgl->stats->card.eliminated++;
20286   lgl->card->eliminated[pivot] = 1;
20287   LOG (CARDLOGLEVEL,
20288     "fourier-motzkin pivot %d with %d positive and %d negative occurrences",
20289     pivot, pcnt, ncnt);
20290   for (p = poccs->start; !lgl->mt && p < poccs->top; p++)
20291     for (q = noccs->start; !lgl->mt && q < noccs->top; q++)
20292       lglcardfmstep (lgl, pivot, *p, *q);
20293 DONE:
20294   for (p = poccs->start; !lgl->mt && p < poccs->top; p++) {
20295     lglrmcardexcept (lgl, *p, pivot);
20296     INCSTEPS (card.steps);
20297   }
20298   for (q = noccs->start; !lgl->mt && q < noccs->top; q++) {
20299     lglrmcardexcept (lgl, *q, -pivot);
20300     INCSTEPS (card.steps);
20301   }
20302   lglrelstk (lgl, poccs);
20303   lglrelstk (lgl, noccs);
20304   if (!(lgl->stats->card.eliminated % lgl->opts->cardreschedint.val))
20305     lglcardresched (lgl);
20306 }
20307 
lglcardfm(LGL * lgl)20308 static void lglcardfm (LGL * lgl) {
20309   Stk * elim;
20310   lglcardresched (lgl);
20311   elim = &lgl->card->elim;
20312   while (!lgl->mt &&
20313          !lglmtstk (elim) &&
20314          !lglterminate (lgl) &&
20315          lgl->limits->card.steps >= INCSTEPS (card.steps))
20316     lglcardfmlit (lgl, lglpopstk (elim));
20317 }
20318 
lglsetcardlim(LGL * lgl)20319 static int64_t lglsetcardlim (LGL * lgl) {
20320   int64_t limit, irrlim;
20321   int pen, szpen;
20322   limit = (lgl->opts->cardreleff.val*lglvisearch (lgl))/1000;
20323   if (limit < lgl->opts->cardmineff.val) limit = lgl->opts->cardmineff.val;
20324   if (lgl->opts->cardmaxeff.val >= 0 && limit > lgl->opts->cardmaxeff.val)
20325     limit = lgl->opts->cardmaxeff.val;
20326   limit >>= (pen = lgl->limits->card.pen + (szpen = lglszpen (lgl)));
20327   irrlim = (lgl->stats->irr.clauses.cur/4) >> szpen;
20328   if (lgl->opts->irrlim.val && limit < irrlim) {
20329     limit = irrlim;
20330     lglprt (lgl, 1,
20331       "[card-%d] limit %lld based on %d irredundant clauses penalty %d",
20332       lgl->stats->card.count,
20333       (LGLL) limit, lgl->stats->irr.clauses.cur, szpen);
20334   } else
20335     lglprt (lgl, 1, "[card-%d] limit %lld penalty %d = %d + %d",
20336       lgl->stats->card.count, (LGLL) limit,
20337       pen, lgl->limits->card.pen, szpen);
20338   lgl->limits->card.steps = lgl->stats->card.steps + limit;
20339   return limit;
20340 }
20341 
lglsetcardlimagain(LGL * lgl,int64_t limit)20342 static void lglsetcardlimagain (LGL * lgl, int64_t limit) {
20343   lglprt (lgl, 1,
20344     "[card-%d] using previous limit %lld for elimination",
20345     lgl->stats->card.count, (LGLL) limit, lgl->stats->irr.clauses.cur);
20346   lgl->limits->card.steps = lgl->stats->card.steps + limit;
20347 }
20348 
lglcard1extractlit(LGL * lgl,int lit)20349 static int lglcard1extractlit (LGL * lgl, int lit) {
20350   const int ignused = lgl->opts->cardignused.val;
20351   int blit, tag, other, other2, i, j, cntother;
20352   int start, size, trivial, subsumed;
20353   const int * p, * w, * eow;
20354   Card * card;
20355   HTS * hts;
20356   lgl->stats->card.found.am1.last.cnt = 0;
20357   lgl->stats->card.found.am1.last.max = 0;
20358   if (lglterminate (lgl)) return 0;
20359   if (lgl->limits->card.steps < INCSTEPS (card.steps)) return 0;
20360   card = lgl->card;
20361   if (ignused && card->lit2used[lit]) return 1;
20362   start = lglcntstk (&card->atmost1);
20363   LOG (CARDLOGLEVEL + 1,
20364     "starting at-most-one clique[%d] for %d",
20365     start, lit);
20366   lglpushstk (lgl, &card->atmost1, lit);
20367   card->marked[lit] = 1;
20368   hts = lglhts (lgl, -lit);
20369   w = lglhts2wchs (lgl, hts);
20370   eow = w + hts->count;
20371   INCSTEPS (card.steps);
20372   for (p = w; p < eow; p++) {
20373     blit = *p;
20374     tag = blit & MASKCS;
20375     if (tag == TRNCS || tag == LRGCS) p++;
20376     if (tag != BINCS) continue;
20377     other = -(blit >> RMSHFT);
20378     if (ignused && card->lit2used[other]) continue;
20379     for (i = start + 1; i < lglcntstk (&card->atmost1); i++) {
20380       other2 = lglpeek (&card->atmost1, i);
20381       if (!lglhasbin (lgl, -other, -other2)) break;
20382     }
20383     if (i < lglcntstk (&card->atmost1)) continue;
20384     card->marked[other] = 1;
20385     assert (i == lglcntstk (&card->atmost1));
20386     lglpushstk (lgl, &card->atmost1, other);
20387     LOG (CARDLOGLEVEL + 1,
20388        "adding %d to at-most-one clique[%d] for %d", other, start, lit);
20389     cntother = lglhts (lgl, -other)->count;
20390     for (j = start + 1; j < i; j++) {
20391       int tmp = lglpeek (&card->atmost1, j);
20392       int cntmp = lglhts (lgl, -tmp)->count;
20393       if (cntmp > cntother) break;
20394     }
20395     if (j < i) {
20396       int k;
20397       for (k = i; k > j; k--)
20398 	card->atmost1.start[k] = card->atmost1.start[k - 1];
20399       card->atmost1.start[j] = other;
20400     }
20401 #ifndef NDEBUG
20402     for (j = start + 1; j + 1 < i; j++)
20403       assert (lglhts (lgl, -lglpeek (&card->atmost1, j))->count <=
20404               lglhts (lgl, -lglpeek (&card->atmost1, j+1))->count);
20405 #endif
20406   }
20407   size = lglcntstk (&card->atmost1) - start;
20408   trivial = (size <= 2);
20409   if (!ignused) {
20410     lglpushstk (lgl, &card->atmost1, 0);
20411     subsumed = lglcard1sub (lgl, card->atmost1.start + start);
20412     lglpopstk (&card->atmost1);
20413   } else subsumed = 0;
20414   for (p = card->atmost1.start + start; p < card->atmost1.top; p++) {
20415     other = *p;
20416     assert (card->marked[other]);
20417     card->marked[other] = 0;
20418     if (!trivial && !subsumed) card->lit2used[other] = 1;
20419   }
20420   if (trivial || subsumed) {
20421     LOG (CARDLOGLEVEL + 1,
20422       "resetting at-most-one clique[%d] for %d of trivial size %d",
20423       start, lit, size);
20424     lglrststk (&card->atmost1, start);
20425   } else {
20426 #ifndef NLGLOG
20427     if (lgl->opts->log.val >= CARDLOGLEVEL) {
20428       lglogstart (lgl, CARDLOGLEVEL,
20429 	"non trivial size %d at-most-one constraint 1 >= ", size);
20430       for (i = start; i < start + size; i++) {
20431 	if (i > start) fputs (" + ", lgl->out);
20432 	fprintf (lgl->out, "%d", lglpeek (&card->atmost1, i));
20433       }
20434       lglogend (lgl);
20435     }
20436 #endif
20437     if (!ignused) {
20438       for (i = start; i < start + size; i++) {
20439 	other = lglpeek (&card->atmost1, i);
20440 	lglpushstk (lgl, &card->occs[other], start);
20441       }
20442     }
20443     lglpushstk (lgl, &card->atmost1, 0);
20444     lgl->stats->card.found.am1.total.sum += size;
20445     lgl->stats->card.found.am1.total.cnt++;
20446     lgl->stats->card.found.am1.last.cnt++;
20447     if (lgl->stats->card.found.am1.total.max < size)
20448       lgl->stats->card.found.am1.total.max = size;
20449     if (lgl->stats->card.found.am1.last.max < size)
20450       lgl->stats->card.found.am1.last.max = size;
20451   }
20452   return 1;
20453 }
20454 
lglcardreloccs(LGL * lgl)20455 static void lglcardreloccs (LGL * lgl) {
20456   Card * card = lgl->card;
20457   int sign, idx, lit;
20458   assert (card), assert (!lgl->nvars || card->occs);
20459   for (sign = -1; sign <= 1; sign += 2)
20460     for (idx = 2; idx < lgl->nvars; idx++) {
20461       lit = sign * idx;
20462       lglrelstk (lgl, &card->occs[lit]);
20463     }
20464   card->occs -= lgl->nvars;
20465   DEL (card->occs, 2*lgl->nvars);
20466 }
20467 
lglcard1extract(LGL * lgl)20468 static int lglcard1extract (LGL * lgl) {
20469   struct { int cnt; int64_t sum; } before, after, delta;
20470   const int ignused = lgl->opts->cardignused.val;
20471   Card * card = lgl->card;
20472 
20473   lglpushstk (lgl, &card->atmost1, 0);
20474 
20475   NEW (card->lit2used, 2*lgl->nvars);
20476   card->lit2used += lgl->nvars;
20477   NEW (card->marked, 2*lgl->nvars);
20478   card->marked += lgl->nvars;
20479   if (!ignused) {
20480     NEW (card->occs, 2*lgl->nvars);
20481     card->occs += lgl->nvars;
20482   }
20483 
20484   before.cnt = lgl->stats->card.found.am1.total.cnt;
20485   before.sum = lgl->stats->card.found.am1.total.sum;
20486 
20487   lglrandlitrav (lgl, lglcard1extractlit);
20488 
20489   after.cnt = lgl->stats->card.found.am1.total.cnt;
20490   after.sum = lgl->stats->card.found.am1.total.sum;
20491   assert (after.cnt >= before.cnt);
20492   assert (after.sum >= before.sum);
20493   delta.cnt = after.cnt - before.cnt;
20494   delta.sum = after.sum - before.sum;
20495 
20496   card->lit2used -= lgl->nvars;
20497   DEL (card->lit2used, 2*lgl->nvars);
20498   card->marked -= lgl->nvars;
20499   DEL (card->marked, 2*lgl->nvars);
20500   if (!ignused) lglcardreloccs (lgl);
20501 
20502   if (delta.cnt)
20503     lglprt (lgl, 1,
20504       "[card-%d] found %d at-most-one constraints of average size %.1f",
20505       lgl->stats->card.count, delta.cnt, lglavg (delta.sum, delta.cnt));
20506   else
20507     lglprt (lgl, 1,
20508       "[card-%d] no at-most-one constraint found",
20509       lgl->stats->card.count);
20510 
20511   return delta.cnt;
20512 }
20513 
lglcard2extractlit(LGL * lgl,int lit)20514 static int lglcard2extractlit (LGL * lgl, int lit) {
20515   int blit, tag, other, other2, other3, i, j, k, res = 1;
20516   const int ignused = lgl->opts->cardignused.val;
20517   int start, size, minlit;
20518   const int * p, * w, * eow;
20519   int * q;
20520   Card * card;
20521   HTS * hts;
20522   lgl->stats->card.found.am2.last.cnt = 0;
20523   lgl->stats->card.found.am2.last.max = 0;
20524   if (lglterminate (lgl)) return 0;
20525   if (lgl->limits->card.steps < INCSTEPS (card.steps)) return 0;
20526   card = lgl->card;
20527   if (ignused && card->lit2used[lit]) return 1;
20528 
20529   start = lglcntstk (&card->atmost2);
20530   LOG (CARDLOGLEVEL + 1, "starting at-most-two clique[%d] for %d", start, lit);
20531   assert (!card->lit2count[lit]);
20532   hts = lglhts (lgl, -lit);
20533   w = lglhts2wchs (lgl, hts);
20534   eow = w + hts->count;
20535   INCSTEPS (card.steps);
20536   for (p = w; p < eow; p++) {
20537     blit = *p;
20538     tag = blit & MASKCS;
20539     if (tag == TRNCS || tag == LRGCS) p++;
20540     if (tag != TRNCS) continue;
20541     other = -(blit >> RMSHFT);
20542     other2 = -*p;
20543     if (card->lit2count[-other] || card->lit2count[-other2]) continue;
20544     if (!card->lit2count[lit]++) lglpushstk (lgl, &card->atmost2, lit);
20545     if (!card->lit2count[other]++) lglpushstk (lgl, &card->atmost2, other);
20546     if (!card->lit2count[other2]++) lglpushstk (lgl, &card->atmost2, other2);
20547   }
20548   q = card->atmost2.start + start;
20549   for (p = q; p < card->atmost2.top; p++) {
20550     if (card->lit2count [other =*p] > 1) *q++ = other;
20551     else card->lit2count[other] = 0;
20552   }
20553   card->atmost2.top = q;
20554   size = lglcntstk (&card->atmost2) - start;
20555   if (size < 4) {
20556     LOG (CARDLOGLEVEL + 1,
20557       "less than 4 literals occuring 2 times in ternary clauses with %d",
20558        -lit);
20559 FAILED:
20560     while (lglcntstk (&card->atmost2) > start) {
20561       int lit = lglpopstk (&card->atmost2);
20562       assert (card->lit2count[lit] > 0);
20563       card->lit2count[lit] = 0;
20564     }
20565     return res;
20566   }
20567   minlit = 0;
20568 RESTART:
20569   if (!ignused) {
20570     int subsumed;
20571     lglpushstk (lgl, &card->atmost2, 0);
20572     subsumed = lglcard2sub (lgl, card->atmost2.start + start, &minlit);
20573     lglpopstk (&card->atmost2);
20574     if (subsumed) goto FAILED;
20575   }
20576   LOG (CARDLOGLEVEL + 1, "trying to connect %d literals", size-1);
20577   for (i = 0; i < size-2; i++) {
20578     other = -lglpeek (&card->atmost2, start + i);
20579     for (j = i+1; j < size-1; j++) {
20580       other2 = -lglpeek (&card->atmost2, start + j);
20581       for (k = j+1; k < size; k++) {
20582 	if (lgl->limits->card.steps < INCSTEPS (card.steps)) {
20583 	  LOG (CARDLOGLEVEL + 1, "cardinality extraction step limit hit");
20584 	  res = 0;
20585 	  goto FAILED;
20586 	}
20587 	other3 = -lglpeek (&card->atmost2, start + k);
20588 	if (!lglhastrn (lgl, other, other2, other3)) {
20589 	  LOG (CARDLOGLEVEL + 1,
20590 	    "ternary clause %d %d %d missing", other, other2, other3);
20591 	  assert (size >= 4);
20592 	  if (size == 4) goto FAILED;
20593 	  int l, tmp;
20594 	  if (k > j + 1) l = k;
20595 	  else {
20596 	    int occ2 = card->lit2count[-other2];
20597 	    int occ3 = card->lit2count[-other3];
20598 	    if (occ2 > occ3) l = k;
20599 	    else if (occ2 < occ3) l = j;
20600 	    else {
20601 	      occ2 = lglhts (lgl, other2)->count;
20602 	      occ3 = lglhts (lgl, other3)->count;
20603 	      if (occ2 > occ3) l = k;
20604 	      else if (occ2 < occ3) l = j;
20605 	      else l = (lglrand (lgl) & 1) ? j : k;
20606 	    }
20607 	  }
20608 	  tmp = lglpeek (&card->atmost2, start + l);
20609 	  assert (abs (tmp) != abs (lit));
20610 	  assert (card->lit2count[tmp] > 0);
20611 	  card->lit2count[tmp] = 0;
20612 	  while (l + 1 < size) {
20613 	    tmp = lglpeek (&card->atmost2, start + l + 1);
20614 	    assert (abs (tmp) != abs (lit));
20615 	    lglpoke (&card->atmost2, start + l++, tmp);
20616 	  }
20617 	  assert (l == size - 1);
20618 	  card->atmost2.top--;
20619 	  size--;
20620 	  assert (size >= 4);
20621 	  assert (card->atmost2.start + start + size == card->atmost2.top);
20622 	  goto RESTART;
20623 	}
20624       }
20625     }
20626   }
20627 #ifndef NLGLOG
20628   if (lgl->opts->log.val >= CARDLOGLEVEL) {
20629     lglogstart (lgl, CARDLOGLEVEL,
20630       "non trivial size %d at-most-two constraint 2 >= ", size);
20631     for (i = start; i < start + size; i++) {
20632       if (i > start) fputs (" + ", lgl->out);
20633       fprintf (lgl->out, "%d", lglpeek (&card->atmost2, i));
20634     }
20635     lglogend (lgl);
20636   }
20637 #endif
20638   for (i = start; i < start + size; i++) {
20639     other = lglpeek (&card->atmost2, i);
20640     card->lit2count[other] = 0;
20641     card->lit2used[other] = 1;
20642     if (!ignused) lglpushstk (lgl, &card->occs[other], start);
20643   }
20644   lglpushstk (lgl, &card->atmost2, 0);
20645   lgl->stats->card.found.am2.total.sum += size;
20646   lgl->stats->card.found.am2.total.cnt++;
20647   lgl->stats->card.found.am2.last.cnt++;
20648   if (lgl->stats->card.found.am2.total.max < size)
20649     lgl->stats->card.found.am2.total.max = size;
20650   if (lgl->stats->card.found.am2.last.max < size)
20651     lgl->stats->card.found.am2.last.max = size;
20652   return res;
20653 }
20654 
lglcard2extract(LGL * lgl)20655 static int lglcard2extract (LGL * lgl) {
20656   struct { int cnt; int64_t sum; } before, after, delta;
20657   const int ignused = lgl->opts->cardignused.val;
20658   Card * card = lgl->card;
20659 
20660   lglpushstk (lgl, &card->atmost2, 0);
20661   NEW (card->lit2used, 2*lgl->nvars);
20662   card->lit2used += lgl->nvars;
20663   NEW (card->lit2count, 2*lgl->nvars);
20664   card->lit2count += lgl->nvars;
20665   if (!ignused) {
20666     NEW (card->occs, 2*lgl->nvars);
20667     card->occs += lgl->nvars;
20668   }
20669 
20670   before.cnt = lgl->stats->card.found.am2.total.cnt;
20671   before.sum = lgl->stats->card.found.am2.total.sum;
20672 
20673   lglrandlitrav (lgl, lglcard2extractlit);
20674 
20675   after.cnt = lgl->stats->card.found.am2.total.cnt;
20676   after.sum = lgl->stats->card.found.am2.total.sum;
20677   assert (after.cnt >= before.cnt);
20678   assert (after.sum >= before.sum);
20679   delta.cnt = after.cnt - before.cnt;
20680   delta.sum = after.sum - before.sum;
20681 
20682   card->lit2used -= lgl->nvars;
20683   DEL (card->lit2used, 2*lgl->nvars);
20684   card->lit2count -= lgl->nvars;
20685   DEL (card->lit2count, 2*lgl->nvars);
20686   if (!ignused) lglcardreloccs (lgl);
20687 
20688   if (delta.cnt)
20689     lglprt (lgl, 1,
20690       "[card-%d] found %d at-most-two constraints of average size %.1f",
20691       lgl->stats->card.count, delta.cnt, lglavg (delta.sum, delta.cnt));
20692   else
20693     lglprt (lgl, 1,
20694       "[card-%d] no at-most-two constraint found",
20695       lgl->stats->card.count);
20696 
20697   return delta.cnt;
20698 }
20699 
lglcarduseclswithlit(LGL * lgl,int lit)20700 static int lglcarduseclswithlit (LGL * lgl, int lit) {
20701   int pos = !lglmtstk (lgl->card->occs + lit);
20702   int neg = !lglmtstk (lgl->card->occs - lit);
20703   int level = lgl->opts->carduse.val;
20704   switch (level) {
20705     case 0: return 0;
20706     case 1: return pos && !neg;
20707     case 2: return pos;
20708     default: assert (level == 3); return pos || neg;
20709   }
20710 }
20711 
lglcardelim(LGL * lgl,int count)20712 static int lglcardelim (LGL * lgl, int count) {
20713   int blit, tag, other, other2, bound, used;
20714   int idx, sign, lit, start, len, res, glue;
20715   const int * p, * w, * eow, * c, * q;
20716   Card * card = lgl->card;
20717   int cardmaxlen;
20718   int clause[4];
20719   HTS * hts;
20720   Stk * s;
20721 
20722   NEW (card->occs, 2*lgl->nvars);
20723   NEW (card->eliminated, lgl->nvars);
20724   NEW (card->count, lgl->nvars);
20725   card->occs += lgl->nvars;
20726   used = 0;
20727   cardmaxlen =
20728     lglfactor (lgl, lgl->stats->card.count, lgl->opts->cardmaxlen.val);
20729   for (start = 1; start < lglcntstk (&card->atmost1); start++) {
20730     for (len = 0; lglpeek (&card->atmost1, start + len); len++)
20731       ;
20732     if (len >= lgl->opts->cardminlen.val &&
20733 	len <= cardmaxlen &&
20734         lgladdcard (lgl, card->atmost1.start + start, 1)) {
20735       lgl->stats->card.used.am1.sum += len;
20736       lgl->stats->card.used.am1.cnt++;
20737       used++;
20738     }
20739     start += len;
20740   }
20741   for (start = 1; start < lglcntstk (&card->atmost2); start++) {
20742     for (len = 0; lglpeek (&card->atmost2, start + len); len++)
20743       ;
20744     if (len >= lgl->opts->cardminlen.val &&
20745 	len <= cardmaxlen &&
20746         lgladdcard (lgl, card->atmost2.start + start, 2)) {
20747       lgl->stats->card.used.am2.sum += len;
20748       lgl->stats->card.used.am2.cnt++;
20749       used++;
20750     }
20751     start += len;
20752   }
20753   if (used) {
20754     lglprt (lgl, 1,
20755       "[card-%d] %d out of %d constraints (%.0f%%) meet size limits",
20756       lgl->stats->card.count, used, count, lglpcnt (used, count));
20757   } else {
20758     lglprt (lgl, 1,
20759       "[card-%d] no constraint out of %d meets size limits",
20760       lgl->stats->card.count, count);
20761     goto SKIP;
20762   }
20763   for (idx = 2; idx < lgl->nvars; idx++) {
20764     if (lglmtstk (card->occs + idx) &&
20765 	lglmtstk (card->occs - idx)) continue;
20766     LOG (CARDLOGLEVEL, "variable %d scheduled for elimination", idx);
20767     lglpushstk (lgl, &card->elim, idx);
20768   }
20769   if (!lgl->opts->carduse.val) goto DO_NOT_USE_CLAUSES;
20770   for (idx = 2; idx < lgl->nvars; idx++) {
20771     if (lglterminate (lgl) ||
20772 	lgl->limits->card.steps < INCSTEPS (card.steps)) goto SKIP;
20773     for (sign = -1; sign <= 1; sign += 2) {
20774       lit = sign * idx;
20775       if (!lglcarduseclswithlit (lgl, lit)) continue;
20776       hts = lglhts (lgl, lit);
20777       w = lglhts2wchs (lgl, hts);
20778       eow = w + hts->count;
20779       for (p = w; p < eow; p++) {
20780 	blit = *p;
20781 	tag = blit & MASKCS;
20782 	if (tag == TRNCS || tag == LRGCS) p++;
20783 	if (tag == BINCS) {
20784 	  other = blit >> RMSHFT;
20785 	  if (abs (other) < idx) continue;
20786 	  clause[0] = -lit, clause[1] = -other, clause[2] = 0;
20787 	  (void) lgladdcard (lgl, clause, 1);
20788 	} else if (tag == TRNCS) {
20789 	  other = blit >> RMSHFT;
20790 	  if (abs (other) < idx) continue;
20791 	  other2 = *p;
20792 	  if (abs (other2) < idx) continue;
20793 	  clause[0] = -lit, clause[1] = -other,
20794 	  clause[2] = -other2, clause[3] = 0;
20795 	  (void) lgladdcard (lgl, clause, 2);
20796 	} else assert (tag == LRGCS);
20797       }
20798     }
20799   }
20800   for (glue = -1; glue <= lgl->opts->cardglue.val; glue++) {
20801     s = (glue < 0) ? &lgl->irr : lgl->red + glue;
20802     for (c = s->start; c < s->top; c = p + 1) {
20803       if (*(p = c) >= NOTALIT) continue;
20804       for (p = c; *p; p++)
20805 	;
20806       for (q = c; (lit = *q); q++)
20807 	if (lglcarduseclswithlit (lgl, lit)) break;
20808       if (!lit) continue;
20809       len = p - c;
20810       if (len > cardmaxlen) continue;
20811       assert (len >= 4);
20812       bound = len - 1;
20813       assert (lglmtstk (&lgl->clause));
20814       for (q = c; (lit = *q); q++)
20815 	lglpushstk (lgl, &lgl->clause, -lit);
20816       lglpushstk (lgl, &lgl->clause, 0);
20817       (void) lgladdcard (lgl, lgl->clause.start, bound);
20818       lglclnstk (&lgl->clause);
20819       if (lglterminate (lgl) ||
20820 	  lgl->limits->card.steps < INCSTEPS (card.steps)) goto SKIP;
20821     }
20822   }
20823 DO_NOT_USE_CLAUSES:
20824   lglcardfm (lgl);
20825 SKIP:
20826   lglcardreloccs (lgl);
20827   DEL (card->count, lgl->nvars);
20828   lglrelstk (lgl, &card->cards);
20829   lglrelstk (lgl, &card->elim);
20830   DEL (card->eliminated, lgl->nvars);
20831   if (lgl->mt)
20832     lglprt (lgl, 1,
20833       "[card-%d] produced empty clause",
20834       lgl->stats->card.count);
20835   else if (!lglmtstk (&card->units)) {
20836     lglprt (lgl, 1,
20837        "[card-%d] found %d units",
20838        lgl->stats->card.count, lglcntstk (&card->units));
20839     while (!lgl->mt && !lglmtstk (&card->units)) {
20840       lit = lglpopstk (&card->units);
20841       if (lglval (lgl, lit) > 0) continue;
20842       if (lglval (lgl, lit) < 0) {
20843 	lglprt (lgl, 1,
20844 	  "[card-%d] found inconsistent unit",
20845 	  lgl->stats->card.count);
20846 	lglmt (lgl);
20847       } else {
20848 	lglunit (lgl, lit);
20849 	if (!lglbcp (lgl)) {
20850 	  lglprt (lgl, 1,
20851 	    "[card-%d] inconsistent unit propagation",
20852 	    lgl->stats->card.count);
20853 	  assert (!lgl->mt);
20854 	  lglmt (lgl);
20855 	}
20856       }
20857     }
20858   }
20859   res = lglcntstk (&card->units);
20860   lglrelstk (lgl, &card->units);
20861   if (!lgl->mt) {
20862     if (res)
20863       lglprt (lgl, 1,
20864 	"[card-%d] found %d units", lgl->stats->card.count, res);
20865     else
20866       lglprt (lgl, 1, "[card-%d] no units found", lgl->stats->card.count);
20867 
20868     if (!lglmtstk (&card->expam1)) {
20869       int generated = 0, exported = 0, genused = 0;
20870       for (c = card->expam1.start; c < card->expam1.top; c = p + 1) {
20871 	int a, usefull = 0;
20872 	generated++;
20873 	for (p = c; (a = *p); p++) if (lglval (lgl, a)) break;
20874 	if (a) {
20875 	  while (*++p)
20876 	    ;
20877 	  continue;
20878 	}
20879 	for (p = c; (a = -*p); p++) {
20880 	  int b;
20881 	  for (q = p + 1; (b = -*q); q++)
20882 	    if (!lglhasbin (lgl, a, b)) {
20883 	      LOG (CARDLOGLEVEL,
20884 	        "exporting at-most-one constraint binary clause %d %d",
20885 		a, b);
20886 	      assert (lglmtstk (&lgl->clause));
20887 	      lglpushstk (lgl, &lgl->clause, a);
20888 	      lglpushstk (lgl, &lgl->clause, b);
20889 	      lglpushstk (lgl, &lgl->clause, 0);
20890 	      lgladdcls (lgl, REDCS, 0, 1);
20891 	      lglclnstk (&lgl->clause);
20892 	      lgl->stats->card.expam1++;
20893 	      exported++;
20894 	      usefull = 1;
20895 	    }
20896 	}
20897 	if (usefull) genused++;
20898       }
20899       lglprt (lgl, 1,
20900         "[card-%d] generated %d at-most-one constraints, %d used %.0f%%",
20901         lgl->stats->card.count,
20902 	generated, genused, lglpcnt (genused, generated));
20903       lglprt (lgl, 1,
20904 	"[card-%d] exported %d binary clauses, %.1f per/constraint",
20905         lgl->stats->card.count, exported, lglavg (exported, genused));
20906     } else
20907       lglprt (lgl, 1,
20908         "[card-%d] no at-most-one constraints generated",
20909         lgl->stats->card.count);
20910   }
20911   lglrelstk (lgl, &card->expam1);
20912   return res;
20913 }
20914 
lglcard(LGL * lgl)20915 static int lglcard (LGL * lgl) {
20916   int success, count;
20917   int64_t limit;
20918   assert (!lgl->mt);
20919   lglstart (lgl, &lgl->times->card);
20920   lgl->stats->card.count++;
20921   if (lgl->level) lglbacktrack (lgl, 0);
20922   limit = lglsetcardlim (lgl);
20923   assert (!lgl->card);
20924   NEW (lgl->card, 1);
20925   count = lglcard1extract (lgl) + lglcard2extract (lgl);
20926   if (!lglterminate (lgl) && count) {
20927     lglsetcardlimagain (lgl, limit);
20928     success = lglcardelim (lgl, count);
20929   } else success = 0;
20930   lglrelstk (lgl, &lgl->card->atmost1);
20931   lglrelstk (lgl, &lgl->card->atmost2);
20932   DEL (lgl->card, 1);
20933   LGLUPDPEN (card, success);
20934   lglstop (lgl);
20935   return !lgl->mt;
20936 }
20937 
20938 /*------------------------------------------------------------------------*/
20939 
lglbcaoccmin(LGL * lgl,int lit)20940 static int lglbcaoccmin (LGL * lgl, int lit) {
20941   int * p, * w, * eow;
20942   int res, blit, red, tag;
20943   HTS * hts;
20944   hts = lglhts (lgl, lit);
20945   w = lglhts2wchs (lgl, hts);
20946   eow = w + hts->count;
20947   res = 0;
20948   for (p = w; res <= 3 && p < eow; p++) {
20949     blit = *p;
20950     tag = blit & MASKCS;
20951     red = blit & REDCS;
20952     if (tag == TRNCS || tag == LRGCS) p++;
20953     if (tag == LRGCS) continue;
20954     if (!red) res++;
20955   }
20956   return res;
20957 }
20958 
lglbcaskiplit(LGL * lgl,int lit)20959 static int lglbcaskiplit (LGL * lgl, int lit) {
20960   int pocc, nocc;
20961   if (lgl->opts->bca.val >= 2) return 0;
20962   pocc = lglbcaoccmin (lgl, lit);
20963   if (pocc <= 1) return 1;
20964   nocc = lglbcaoccmin (lgl, -lit);
20965   if (nocc <= 1) return 1;
20966   return pocc == 2 && nocc == 2;
20967 }
20968 
lglbcalitaux(LGL * lgl,int lit)20969 static void lglbcalitaux (LGL * lgl, int lit) {
20970   int first, blit, tag, red, lidx, other, tmp, found, other2, found2, * r;
20971   const int * w, * p, * eow, * c, * q;
20972   Stk * covered = &lgl->bca->covered;
20973   int round;
20974   HTS * hts;
20975   assert (lglisfree (lgl, lit));
20976   assert (lgl->opts->bca.val);
20977   assert (!(lglavar (lgl, lit)->inred & (1 << (lit < 0))));
20978   hts = lglhts (lgl, lit);
20979   if (!hts->count) return;
20980   if (lglbcaskiplit (lgl, lit)) { lgl->stats->bca.skipped++; return; }
20981   assert (lglmtstk (covered));
20982   first = 1;
20983   w = lglhts2wchs (lgl, hts);
20984   eow = w + hts->count;
20985   for (round = 0; round < 2; round++) {
20986     for (p = w; (first || !lglmtstk (covered)) && p < eow; p++) {
20987       blit = *p;
20988       tag = blit & MASKCS;
20989       red = blit & REDCS;
20990       if (tag == TRNCS || tag == LRGCS) p++;
20991       assert (!red || tag != LRGCS);
20992       if (tag == LRGCS) continue;
20993       if (round != (tag == OCCS)) continue;
20994       INCSTEPS (bca.steps);
20995       if (tag == BINCS) {
20996 	assert (!round);
20997 	other = blit >> RMSHFT;
20998 	if (lglval (lgl, other) > 0) continue;
20999 	assert (!lglval (lgl, other));
21000 	found = first;
21001 	while (!lglmtstk (covered))
21002 	  if (other == lglpopstk (covered)) found = 1;
21003 	if (found) lglpushstk (lgl, covered, other);
21004       } else if (tag == TRNCS) {
21005 	assert (!round);
21006 	other = blit >> RMSHFT;
21007 	if (lglval (lgl, other) > 0) continue;
21008 	other2 = *p;
21009 	if (lglval (lgl, other2) > 0) continue;
21010 	found = found2 = first;
21011 	while (!lglmtstk (covered))
21012 	  if (other == (tmp = lglpopstk (covered))) found = 1;
21013 	  else if (tmp == other2) found2 = 1;
21014 	if (found && !lglval (lgl, other)) lglpushstk (lgl, covered, other);
21015 	if (found2 && !lglval (lgl, other2)) lglpushstk (lgl, covered, other2);
21016       } else {
21017 	assert (!red);
21018 	assert (round);
21019 	assert (tag == OCCS);
21020 	lidx = blit >> RMSHFT;
21021 	c = lglidx2lits (lgl, red, lidx);
21022 	INCSTEPS (bca.steps);
21023 	for (q = c; (other = *q); q++)
21024 	  if (other != lit && lglval (lgl, other) > 0) break;
21025 	if (other) continue;
21026 	if (first) {
21027 	  for (q = c; (other = *q); q++)
21028 	    if (other != lit && !lglval (lgl, other))
21029 	      lglpushstk (lgl, covered, other);
21030 	} else {
21031 	  for (q = covered->start; q < covered->top; q++)
21032 	    assert (!lglsignedmarked (lgl, *q)), lglsignedmark (lgl, *q);
21033 	  for (q = c; (other = *q); q++)
21034 	    if (other != lit && lglsignedmarked (lgl, other))
21035 	      assert (!lglval (lgl, other)), lglsignedunmark (lgl, other);
21036 	  r = covered->start;
21037 	  for (q = r; q < covered->top; q++)
21038 	    if (lglsignedmarked (lgl, (other = *q)))
21039 	      lglsignedunmark (lgl, other);
21040 	    else *r++ = other;
21041 	  covered->top = r;
21042 	}
21043       }
21044       first = 0;
21045     }
21046   }
21047 }
21048 
lglbcalit(LGL * lgl,int lit)21049 static int lglbcalit (LGL * lgl, int lit) {
21050   unsigned bit;
21051   AVar * av;
21052   int other;
21053   if (lgl->limits->bca.steps < lgl->stats->bca.steps) return 0;
21054   if (lgl->limits->bca.added < lgl->stats->bca.added) return 0;
21055   if (lglterminate (lgl)) return 0;
21056   if (lglifrozen (lgl, lit)) return 1;
21057   if (!lglisfree (lgl, lit)) return 1;
21058   av = lglavar (lgl, lit);
21059   bit = (1 << (lit < 0));
21060   if (av->inred & bit) return 1;
21061   lglbcalitaux (lgl, lit);
21062   while (!lglmtstk (&lgl->bca->covered)) {
21063     INCSTEPS (bca.steps);
21064     other = lglpopstk (&lgl->bca->covered);
21065     if (lglhasbin (lgl, -lit, -other)) continue;
21066     LOG (2, "adding binary blocked clause %d %d", -lit, -other);
21067     assert (lglmtstk (&lgl->clause));
21068     lglpushstk (lgl, &lgl->clause, -lit);
21069     lglpushstk (lgl, &lgl->clause, -other);
21070     lglpushstk (lgl, &lgl->clause, 0);
21071     lgladdcls (lgl, REDCS, 0, 1);
21072     lglclnstk (&lgl->clause);
21073     lgl->stats->bca.added++;
21074   }
21075   return 1;
21076 }
21077 
lglupdbcadel(LGL * lgl,int success)21078 static void lglupdbcadel (LGL * lgl, int success) {
21079   if (success && lgl->limits->bca.del.cur)
21080     lgl->limits->bca.del.cur /= 2;
21081   if (!success && lgl->limits->bca.del.cur < lgl->opts->delmax.val)
21082     lgl->limits->bca.del.cur++;
21083   lgl->limits->bca.del.rem = lgl->limits->bca.del.cur;
21084 }
21085 
lglbca(LGL * lgl)21086 static void lglbca (LGL * lgl) {
21087   int oldadded = lgl->stats->bca.added, added, limadded;
21088   int idx, glue, other, inred, usable, scale;
21089   const int * c, * p;
21090   int64_t oldsteps, lim64;
21091   unsigned bit;
21092   AVar * av;
21093 
21094   lglstart (lgl, &lgl->times->bca);
21095 
21096   NEW (lgl->bca, 1);
21097 
21098   lgl->stats->bca.count++;
21099   oldsteps = lgl->stats->bca.steps;
21100   lgl->limits->bca.steps = oldsteps + lgl->opts->bcamaxeff.val;
21101 
21102   limadded = lgl->stats->irr.clauses.cur;
21103   scale = lgl->opts->bcaddlimldscale.val;
21104   if (scale < 0) limadded >>= -scale;
21105   else if ((INT_MAX >> scale) < limadded) limadded = INT_MAX;
21106   else limadded <<=scale;
21107   lim64 = lgl->stats->bca.added/2;
21108   lim64 += limadded/2 + 500;
21109   if (lim64 > (int64_t) INT_MAX) lim64 = INT_MAX;
21110   lgl->limits->bca.added = lim64;
21111 
21112   lglprt (lgl, 1,
21113     "[bca-%d] limit of %d steps and %d added (scaled %d)",
21114     lgl->stats->bca.count, lgl->opts->bcamaxeff.val,
21115     lgl->limits->bca.added, scale);
21116 
21117   assert (!lgl->bcaing);
21118   lgl->bcaing = 1;
21119 
21120   if (lgl->level > 0) lglbacktrack (lgl, 0);
21121   lglgc (lgl);
21122   assert (lgl->frozen);
21123 
21124   for (idx = 2; idx < lgl->nvars; idx++) lglavar (lgl, idx)->inred = 0;
21125   inred = 0;
21126   for (glue = 0; glue <= MAXGLUE; glue++) {
21127     Stk * s = lgl->red + glue;
21128     for (c = s->start; c < s->top; c = p + 1) {
21129       p = c;
21130       if (*p >= NOTALIT) continue;
21131       INCSTEPS (bca.steps);
21132       while ((other = *p)) {
21133 	p++;
21134 	bit = (1 << (other < 0));
21135 	av = lglavar (lgl, other);
21136 	if (av->inred & bit) continue;
21137 	av->inred |= bit;
21138 	inred++;
21139       }
21140     }
21141   }
21142   lglprt (lgl, 2,
21143     "[bca-%d] %d out of %d literals in large redundant clauses %.0f%%",
21144     lgl->stats->bca.count,
21145     inred, 2*(lgl->nvars-1), lglpcnt (inred, 2*(lgl->nvars-1)));
21146 
21147   usable = 0;
21148   for (idx = 2; idx < lgl->nvars; idx++) {
21149     if (lglifrozen (lgl, idx)) continue;
21150     if (!lglisfree (lgl, idx)) continue;
21151     av = lglavar (lgl, idx);
21152     for (bit = 1; bit <= 2; bit++) if (!(av->inred & bit)) usable++;
21153   }
21154   lglprt (lgl, 1,
21155     "[bca-%d] %d out of %d literals actually usable %.0f%%",
21156     lgl->stats->bca.count,
21157     usable, 2*(lgl->nvars-1), lglpcnt (usable, 2*(lgl->nvars-1)));
21158 
21159   if (usable < lgl->opts->bcaminuse.val) {
21160     lglprt (lgl, 1, "[bca-%d] not enough literals usable",
21161             lgl->stats->bca.count);
21162     goto DONE;
21163   }
21164 
21165   lgldense (lgl, 0);
21166   lglrandlitrav (lgl, lglbcalit);
21167   lglsparse (lgl);
21168   lglgc (lgl);
21169 
21170 DONE:
21171   added = lgl->stats->bca.added - oldadded;
21172   lglprt (lgl, 1, "[bca-%d] added %d blocked clauses in %lld steps",
21173           lgl->stats->bca.count, added,
21174 	  (LGLL) lgl->stats->bca.steps - oldsteps);
21175   assert (lgl->bcaing);
21176   lgl->bcaing = 0;
21177   lglupdbcadel (lgl, added);
21178   lglrelstk (lgl, &lgl->bca->covered);
21179   DEL (lgl->bca, 1);
21180   lglstop (lgl);
21181 }
21182 
21183 /*------------------------------------------------------------------------*/
21184 
lgltreducing(LGL * lgl)21185 static int lgltreducing (LGL * lgl) {
21186   if (lgldelaying (lgl, "transred", &lgl->limits->trd.del.rem)) return 0;
21187   if (lglwaiting (lgl, "transred", lgl->opts->transredwait.val)) return 0;
21188   return lgl->opts->transred.val;
21189 }
21190 
lglunhiding(LGL * lgl)21191 static int lglunhiding (LGL * lgl) {
21192   if (lgldelaying (lgl, "unhide", &lgl->limits->unhd.del.rem)) return 0;
21193   if (lglwaiting (lgl, "unhide", lgl->opts->unhidewait.val)) return 0;
21194   return lgl->opts->unhide.val;
21195 }
21196 
lgldecomposing(LGL * lgl)21197 static int lgldecomposing (LGL * lgl) { return lgl->opts->decompose.val; }
21198 
lglblocking(LGL * lgl)21199 static int lglblocking (LGL * lgl) {
21200   if (!lgl->opts->block.val) return 0;
21201   if (lgl->allfrozen) return 0;
21202   if (lgldelaying (lgl, "block", &lgl->limits->blk.del.rem)) return 0;
21203   if (lgl->opts->blockwait.val && lgl->wait &&
21204       (!lgl->opts->elim.val || !lgl->elmrtc)) {
21205     lglprt (lgl, 2,
21206       "[block-waiting] for bounded variable elimination to be completed");
21207     return 0;
21208   }
21209   if (!lglsmallirr (lgl)) return 0;
21210   if (lgl->nvars <= 2) return 0;
21211   if (lgl->mt) return 0;
21212   if (lgl->blkrem) return 1;
21213   return lgl->stats->irrprgss > lgl->limits->blk.irrprgss;
21214 }
21215 
lgleliminating(LGL * lgl)21216 static int lgleliminating (LGL * lgl) {
21217   if (!lgl->opts->elim.val) return 0;
21218   if (lgl->allfrozen) return 0;
21219   if (lgldelaying (lgl, "elim", &lgl->limits->elm.del.rem)) return 0;
21220   if (!lglsmallirr (lgl)) return 0;
21221   if (lgl->nvars <= 2) return 0;
21222   if (lgl->mt) return 0;
21223   if (lgl->elmrem) return 1;
21224   return lgl->stats->irrprgss > lgl->limits->elm.irrprgss;
21225 }
21226 
lglbcaing(LGL * lgl)21227 static int lglbcaing (LGL * lgl) {
21228   if (!lgl->opts->bca.val) return 0;
21229   if (lgl->allfrozen) return 0;
21230   if (lgldelaying (lgl, "bca", &lgl->limits->bca.del.rem)) return 0;
21231   if (lglwaiting (lgl, "bca", lgl->opts->bcawait.val)) return 0;
21232   if (!lglsmallirr (lgl)) return 0;
21233   return 1;
21234 }
21235 
lglreducing(LGL * lgl)21236 static int lglreducing (LGL * lgl) {
21237   int reducable;
21238   if (!lgl->opts->reduce.val) return 0;
21239   reducable = lgl->stats->red.lrg;
21240   assert (reducable >= lgl->lrgluereasons);
21241   reducable -= lgl->lrgluereasons;
21242   assert (reducable >= lgl->stats->lir[0].clauses);
21243   reducable -= lgl->stats->lir[0].clauses;
21244   return reducable >= lgl->limits->reduce.redlarge;
21245 }
21246 
lgldefragmenting(LGL * lgl)21247 static int lgldefragmenting (LGL * lgl) {
21248   int relfree;
21249   if (lgl->stats->pshwchs < lgl->limits->dfg) return 0;
21250   if (!lgl->nvars) return 0;
21251   relfree = (100 * lgl->wchs->free + 99) / lgl->nvars;
21252   return relfree >= lgl->opts->defragfree.val;
21253 }
21254 
lglforcerestart(LGL * lgl)21255 static int lglforcerestart (LGL * lgl) {
21256   const int64_t  percent = lgl->opts->restartforcelim.val;
21257   int64_t actual, smoothed, limit;
21258   int forcing;
21259   assert (lgl->opts->restartcheckforced.val);
21260   assert (percent);
21261   switch (lgl->opts->restartforcemode.val) {
21262     default:
21263     case 0:
21264       actual = lgl->stats->glue.fast.val;
21265       smoothed = lgl->stats->avglue.val;
21266       break;
21267     case 1:
21268       actual = lgl->stats->glue.fast.val;
21269       smoothed = lgl->stats->glue.slow.val;
21270       break;
21271     case 2:
21272       actual = lgl->stats->glue.diff.actual;
21273       smoothed = lgl->stats->glue.diff.smoothed.val;
21274       break;
21275   }
21276   assert (lglvalidint64 (smoothed));
21277   limit = (smoothed < 0 ? -smoothed : smoothed);
21278   assert (limit >= 0);
21279   if (!lglvalidint64 (limit)) return 0;
21280   limit /= 100;
21281   if (INT64MAX/percent < limit) return 0;
21282   limit *= percent;
21283   forcing = (limit < actual);
21284   LOG (2,
21285     "%s glue MACD %g * %.2f = %g %s %g at %lld conflicts",
21286     (forcing ? "forcing" : "not forcing"),
21287     smoothed/(double)(1ll<<32),
21288     lgl->opts->restartforcelim.val/100.0,
21289     limit/(double)(1ll<<32),
21290     forcing ? "<" : ">=",
21291     actual/(double)(1ll<<32),
21292     (LGLL) lgl->stats->confs);
21293   return forcing;
21294 }
21295 
lgldelayrestart(LGL * lgl)21296 static int lgldelayrestart (LGL * lgl) {
21297   const int64_t   actual = ((int64_t)lgl->level) << 32;
21298   const int64_t smoothed = lgl->stats->jlevel.slow.val;
21299   const int64_t  percent = lgl->opts->restartdelaylim.val;
21300   int64_t limit;
21301   int delaying;
21302   assert (lgl->opts->restartdelay.val);
21303   assert (percent);
21304   assert (lglvalidint64 (smoothed));
21305   limit = (smoothed < 0 ? -smoothed : smoothed);
21306   assert (limit >= 0);
21307   if (!lglvalidint64 (limit)) return 0;
21308   limit /= 100;
21309   if (INT64MAX/percent < limit) return 0;
21310   limit *= percent;
21311   delaying = (limit > actual);
21312   LOG (2,
21313     "%s restart MACD %g * %.2f = %g %s %g at %lld conflicts",
21314     (delaying ? "delaying" : "not delaying"),
21315     smoothed/(double)(1ll<<32),
21316     lgl->opts->restartdelaylim.val/100.0,
21317     limit/(double)(1ll<<32),
21318     delaying ? ">" : "<=",
21319     actual/(double)(1ll<<32),
21320     (LGLL) lgl->stats->confs);
21321   return delaying;
21322 }
21323 
lglrestarting(LGL * lgl)21324 static int lglrestarting (LGL * lgl) {
21325   int assumptions;
21326   if (lgl->stats->confs < lgl->limits->restart.confs) return 0;
21327   if (!lgl->opts->restart.val) return 0;
21328   if (!lgl->level) return 0;
21329   if ((assumptions = lglcntstk (&lgl->assume))) {
21330     if (lgl->assumed < assumptions) return 0;
21331     assert (lgl->alevel <= lgl->level);
21332     if (lgl->alevel == lgl->level) return 0;
21333   }
21334   lgl->stats->restarts.checked++;
21335   lgl->limits->restart.confs = lgl->stats->confs + 1;
21336   if (lgl->opts->restartfixed.val) return 1;
21337   if (lgl->opts->agility.val &&
21338       ((100*lgl->stats->agility) >> 32) > lgl->opts->agilitylim.val) {
21339     lgl->stats->restarts.agile++;
21340 NORESTART:
21341     lgl->stats->restarts.skipped++;
21342     lglrep (lgl, 3, 'L');
21343     return 0;
21344   }
21345   if (lgl->opts->restartdelay.val && lgldelayrestart (lgl)) {
21346     lgl->stats->restarts.delayed++;
21347     goto NORESTART;
21348   }
21349   if (lgl->opts->restartblock.val == 2 && lglblockrestart (lgl)) {
21350     lgl->limits->restart.confs = lgl->stats->confs + lgl->opts->restartint.val;
21351     lgl->stats->restarts.blocked++;
21352     goto NORESTART;
21353   }
21354   if (lgl->opts->restartcheckforced.val && !lglforcerestart (lgl)) {
21355     lgl->stats->restarts.notforced++;
21356     goto NORESTART;
21357   }
21358   lgl->stats->restarts.forced++;
21359 #ifndef NLGLFILES
21360   {
21361     static FILE * restartfile = 0;
21362     if (!restartfile) restartfile = fopen ("/tmp/restarts", "w");
21363     fprintf (restartfile, "%lld\n", (LGLL) lgl->stats->confs);
21364     fflush (restartfile);
21365   }
21366 #endif
21367   return 1;
21368 }
21369 
lglquatresolving(LGL * lgl)21370 static int lglquatresolving (LGL * lgl) {
21371   if (lgldelaying (lgl, "quatres", &lgl->limits->quatres.del.rem)) return 0;
21372   if (lglwaiting (lgl, "quatres", lgl->opts->quatreswait.val)) return 0;
21373   return lgl->opts->quatres.val;
21374 }
21375 
lglternresolving(LGL * lgl)21376 static int lglternresolving (LGL * lgl) {
21377   if (lgldelaying (lgl, "ternres", &lgl->limits->ternres.del.rem)) return 0;
21378   if (lglwaiting (lgl, "ternres", lgl->opts->ternreswait.val)) return 0;
21379   return lgl->opts->ternres.val;
21380 }
21381 
lglgaussing(LGL * lgl)21382 static int lglgaussing (LGL * lgl) {
21383   if (lgldelaying (lgl, "gauss", &lgl->limits->gauss.del.rem)) return 0;
21384   if (lglwaiting (lgl, "gauss", lgl->opts->gausswait.val)) return 0;
21385   if (!lglsmallirr (lgl)) return 0;
21386   return lgl->opts->gauss.val;
21387 }
21388 
lglprobing(LGL * lgl)21389 static int lglprobing (LGL * lgl) {
21390   if (!lgl->opts->probe.val) return 0;
21391   if (lgl->opts->prbasic.val) return 1;
21392   if (!lglsmallirr (lgl)) return 0;
21393   if (lgl->opts->prbsimple.val) return 1;
21394   if (lgl->opts->treelook.val) return 1;
21395   return 0;
21396 }
21397 
lglcarding(LGL * lgl)21398 static int lglcarding (LGL * lgl) {
21399   if (!lgl->opts->card.val) return 0;
21400   if (lgldelaying (lgl, "card", &lgl->limits->card.del.rem)) return 0;
21401   if (lglwaiting (lgl, "card", lgl->opts->cardwait.val)) return 0;
21402   return 1;
21403 }
21404 
lglcceing(LGL * lgl)21405 static int lglcceing (LGL * lgl) {
21406   if (!lgl->opts->cce.val) return 0;
21407   if (lgl->allfrozen) return 0;
21408   if (lgldelaying (lgl, "cce", &lgl->limits->cce.del.rem)) return 0;
21409   if (lglwaiting (lgl, "cce", lgl->opts->ccewait.val)) return 0;
21410   if (!lglsmallirr (lgl)) return 0;
21411   return 1;
21412 }
21413 
21414 /*------------------------------------------------------------------------*/
21415 
lglupdlocslim(LGL * lgl,int updconflimtoo)21416 static void lglupdlocslim (LGL * lgl, int updconflimtoo) {
21417   int rem = lglrem (lgl), varslimit, vardelta;
21418   vardelta = (rem * lgl->opts->locsvared.val + 999)/1000;
21419   if (vardelta > rem) vardelta = rem;
21420   varslimit = rem - vardelta;
21421   lgl->limits->locs.vars = varslimit;
21422   lglprt (lgl, 1 + !lgl->opts->locs.val,
21423     "[locs-lim] next local search variable limit %d = %d - %d",
21424     varslimit, rem, vardelta);
21425   if (!updconflimtoo) return;
21426   lgl->limits->locs.inc += lgl->opts->locscint.val;
21427   assert (lgl->limits->locs.confs <= LLMAX - lgl->limits->locs.inc);
21428   lgl->limits->locs.confs = lgl->stats->confs + lgl->limits->locs.inc;
21429   lglprt (lgl, 1 + !lgl->opts->locs.val,
21430     "[locs-lim] next local search conflict limit increased by %d to %lld",
21431     lgl->limits->locs.inc, lgl->limits->locs.confs);
21432 }
21433 
lglocsing(LGL * lgl)21434 static int lglocsing (LGL * lgl) {
21435 #ifndef NLGLYALSAT
21436   int rem;
21437   if (!lgl->opts->locs.val) return 0;
21438   if (lgl->limits->locs.confs > lgl->stats->confs) return 0;
21439   if (lgl->stats->irr.clauses.cur > lgl->opts->locsclim.val) {
21440     lglprt (lgl, 2, "[locs] skipped due to too many clauses");
21441     return 0;
21442   }
21443   rem = lglrem (lgl);
21444   if (rem < lgl->limits->locs.vars) {
21445     lglprt (lgl, 2,
21446       "[locs-limit] local search skipped (remaining %d < limit %d)",
21447       rem, lgl->limits->locs.vars);
21448     lglupdlocslim (lgl, 1);
21449     return 0;
21450   }
21451   if (lglwaiting (lgl, "locs", lgl->opts->locswait.val)) return 0;
21452   if (lgl->opts->locs.val < 0) return 1;
21453   return (lgl->stats->locs.count < lgl->opts->locs.val);
21454 #else
21455   (void) lgl;
21456   return 0;
21457 #endif
21458 }
21459 
21460 #ifndef NLGLYALSAT
21461 
lglocscopy(LGL * lgl,Yals * yals)21462 static void lglocscopy (LGL * lgl, Yals * yals) {
21463   int idx, sign, lit, blit, tag, red, other, other2;
21464   int count, redcount, units, tmp;
21465   const int * p, * w, * eow, * c;
21466   HTS * hts;
21467   Stk * s;
21468   assert (!lgl->level);
21469   if (!lgl->mt && !lglbcp (lgl)) lglmt (lgl);
21470   if (!lgl->mt) lglgc (lgl);
21471   if (lgl->mt) return;
21472   count = redcount = units = 0;
21473   for (idx = 2; idx < lgl->nvars; idx++)
21474     for (sign = -1; sign <= 1; sign += 2) {
21475       lit = sign * idx;
21476       assert (!lglval (lgl, lit));
21477       hts = lglhts (lgl, lit);
21478       w = lglhts2wchs (lgl, hts);
21479       eow = w + hts->count;
21480       for (p = w; p < eow; p++) {
21481 	blit = *p;
21482 	tag = blit & MASKCS;
21483 	red = blit & REDCS;
21484 	if (tag == TRNCS || tag == LRGCS) p++;
21485 	if (red && tag == BINCS && lgl->opts->locsred.val < 2) continue;
21486 	if (red && tag == TRNCS && lgl->opts->locsred.val < 3) continue;
21487 	if (tag != BINCS && tag != TRNCS) continue;
21488 	other = blit >> RMSHFT;
21489 	if (abs (other) < idx) continue;
21490 	assert (!lglval (lgl, other));
21491 	if (tag == TRNCS) {
21492 	  other2 = *p;
21493 	  if (abs (other2) < idx) continue;
21494 	  assert (!lglval (lgl, other2));
21495 	} else other2 = 0;
21496 	yals_add (yals, lit);
21497 	yals_add (yals, other);
21498 	if (other2) yals_add (yals, other2);
21499 	yals_add (yals, 0);
21500 	if (red) redcount++;
21501 	count++;
21502       }
21503     }
21504   for (idx = 2; idx < lgl->nvars; idx++) {
21505     tmp = lglifixed (lgl, idx);
21506     if (!tmp) continue;
21507     lit = (tmp < 0) ? -idx : idx;
21508     yals_add (yals, lit);
21509     yals_add (yals, 0);
21510     units++;
21511   }
21512   for (red = -1; red < MAXGLUE; red++) {
21513     s = red < 0 ? &lgl->irr : lgl->red + red;
21514     if (red >= 0 && lgl->opts->locsred.val < 4) break;
21515     for (c = s->start; c < s->top; c = p + 1) {
21516       p = c;
21517       if (*p >= NOTALIT) continue;
21518       while ((other = *p)) {
21519 	assert (!lglval (lgl, other));
21520 	yals_add (yals, other);
21521 	p++;
21522       }
21523       yals_add (yals, 0);
21524       if (red >= 0) redcount++;
21525       count++;
21526     }
21527   }
21528 
21529   lglprt (lgl, 1,
21530     "[locs-%d] copied %d irredundant clauses",
21531     lgl->stats->locs.count, count - redcount);
21532   if (redcount)
21533     lglprt (lgl, 1,
21534       "[locs-%d] copied %d redundant clauses",
21535       lgl->stats->locs.count, redcount);
21536   if (units)
21537     lglprt (lgl, 1,
21538       "[locs-%d] copied %d units",
21539       lgl->stats->locs.count, units);
21540 
21541   for (count = 0; count < lglcntstk (&lgl->assume); count++) {
21542     lit = lglpeek (&lgl->assume, count);
21543     if (abs (lit) <= 0) continue;
21544     yals_add (yals, lit);
21545     yals_add (yals, 0);
21546   }
21547   if (count)
21548     lglprt (lgl, 1,
21549       "[locs-%d] copied %d assumptions as %d unit clauses",
21550       lgl->stats->locs.count, count, count);
21551   else
21552     lglprt (lgl, 2,
21553       "[locs-%d] no assumptions copied",
21554       lgl->stats->locs.count);
21555 }
21556 
lglsetlocslim(LGL * lgl)21557 static int64_t lglsetlocslim (LGL * lgl) {
21558   int pen, boost;
21559   int64_t limit;
21560   if (lgl->opts->locsrtc.val) {
21561     limit = LLMAX;
21562     lglprt (lgl, 1,
21563       "[locs-%d] really no limit (run to completion)",
21564       lgl->stats->locs.count);
21565   } else {
21566     limit = (lgl->opts->locsreleff.val*lglvisearch (lgl))/100;
21567     if (limit < lgl->opts->locsmineff.val)
21568       limit = lgl->opts->locsmineff.val;
21569     if (lgl->opts->locsmaxeff.val >= 0 &&
21570         limit > lgl->opts->locsmaxeff.val)
21571       limit = lgl->opts->locsmaxeff.val;
21572     if (lgl->stats->locs.count <= 1 &&
21573         lgl->opts->boost.val &&
21574         lgl->opts->locsboost.val > 1) {
21575       boost = lgl->opts->locsboost.val;
21576       lglprt (lgl, 1,
21577 	"[locs-%d] intially boosting limit by factor of %d",
21578 	lgl->stats->locs.count, boost);
21579     } else boost = 1;
21580     limit *= boost;
21581     pen = lglitszpen (lgl);
21582     limit >>= pen;
21583     lglprt (lgl, 1,
21584       "[locs-%d] limit %lld literal penalty %d",
21585       lgl->stats->locs.count, (LGLL) limit, pen);
21586   }
21587   return limit;
21588 }
21589 
21590 #endif
21591 
lglocsaux(LGL * lgl,int hitlim)21592 static int lglocsaux (LGL * lgl, int hitlim) {
21593   int lkhd = 0;
21594 #ifndef NLGLYALSAT
21595   int save = lgl->opts->locsexport.val && lgl->opts->phasesave.val;
21596   int res, min, pos, neg, idx, lit, old_val, len;
21597   const int set = lgl->opts->locset.val;
21598   unsigned long long seed;
21599   char * prefix;
21600   int64_t limit;
21601   AVar * av;
21602   Val val;
21603   Yals * yals;
21604   lglstart (lgl, &lgl->times->locs);
21605   if (lgl->level) lglbacktrack (lgl, 0);
21606   if (!lgl->stats->locs.count++) {
21607     const char * yals_version ();
21608     if (lgl->opts->verbose.val > 0)
21609       lglprt (lgl, 1,
21610 	"[locs-%d] %s",
21611 	lgl->stats->locs.count, yals_version ());
21612     else if (lgl->opts->locsbanner.val) {
21613       char * prefix = lgl->prefix;
21614       lgl->prefix = "c ";
21615       lglprt (lgl, 0, "%s", yals_version ());
21616       lgl->prefix = prefix;
21617     }
21618   }
21619   yals = yals_new_with_mem_mgr ( lgl,
21620 	   (YalsMalloc) lglnew, (YalsRealloc) lglrsz, (YalsFree) lgldel);
21621   yals_setout (yals, lgl->out);
21622   len = strlen (lgl->prefix) + 80;
21623   NEW (prefix, len);
21624   if (lgl->tid >= 0)
21625     sprintf (prefix, "%s%d [locs-%d] ",
21626       lgl->prefix, lgl->tid, lgl->stats->locs.count);
21627   else
21628     sprintf (prefix, "%s[locs-%d] ", lgl->prefix, lgl->stats->locs.count);
21629   yals_setprefix (yals, prefix);
21630   DEL (prefix, len);
21631   old_val = yals_getopt (yals, "verbose");
21632   if (old_val < lgl->opts->verbose.val)
21633     yals_setopt (yals, "verbose", lgl->opts->verbose.val);
21634   seed = lglrand (lgl);
21635   if (lgl->tid >= 0) seed *= lgl->tid + 1;
21636   seed += 1237 * (unsigned) lgl->stats->locs.count;
21637   yals_srand (yals, seed);
21638   if (hitlim > 0) yals_setopt (yals, "hitlim", hitlim);
21639   lglocscopy (lgl, yals);
21640   if (lgl->mt) goto DONE;
21641   limit = lglsetlocslim (lgl);
21642   pos = neg = 0;
21643   for (idx = 2; idx < lgl->nvars; idx++) {
21644     av = lglavar (lgl, idx);
21645          if (set == 2 && av->phase > 0) lit = idx;
21646     else if (set == 2 && av->phase < 0) lit = -idx;
21647     else if (set == 1 && av->locsval > 0) lit = idx;
21648     else if (set == 1 && av->locsval < 0) lit = -idx;
21649     else continue;
21650     assert (lit);
21651     if (lit < 0) neg++; else pos++;
21652     yals_setphase (yals, lit);
21653   }
21654   lglprt (lgl, 1,
21655     "[locs-%d] importing %d positive %.0f%% and %d negative %.0f%% phases",
21656     lgl->stats->locs.count,
21657     pos, lglpcnt (pos, pos + neg),
21658     neg, lglpcnt (neg, pos + neg));
21659   if (limit < LLMAX/1000) limit *= 1000; else limit = LLMAX;
21660   yals_setmemslimit (yals, limit);
21661   if (lgl->cbs && lgl->cbs->term.fun)
21662     yals_seterm (yals, lgl->cbs->term.fun, lgl->cbs->term.state);
21663   if (lgl->cbs && lgl->cbs->getime)
21664     yals_setime (yals, lgl->cbs->getime);
21665   if (lgl->cbs && lgl->cbs->msglock.lock)
21666     yals_setmsglock (yals,
21667       lgl->cbs->msglock.lock,
21668       lgl->cbs->msglock.unlock,
21669       lgl->cbs->msglock.state);
21670   res = yals_sat (yals);
21671   min = yals_minimum (yals);
21672   lglprt (lgl, 1,
21673     "[locs-%d] local search returns %d with minimum %d",
21674     lgl->stats->locs.count, res, min);
21675   if (min < lgl->stats->locs.min) lgl->stats->locs.min = min;
21676   lgl->stats->locs.flips += yals_flips (yals);
21677   lgl->stats->locs.mems += yals_mems (yals);
21678   if (res == 10) save = 1;
21679   pos = neg = 0;
21680   for (idx = 2; idx < lgl->nvars; idx++) {
21681     val = yals_deref (yals, idx);
21682     assert (abs (val) == 1);
21683     av = lglavar (lgl, idx);
21684     if (val < 0) neg++, av->locsval = -1;
21685     else if (val > 0) pos++, av->locsval = 1;
21686     if (save) av->phase = val;
21687   }
21688   lglprt (lgl, 1,
21689     "[locs-%d] %s %d positive %.0f%% and %d negative %.0f%% phases",
21690     lgl->stats->locs.count,
21691     save ? "exported" : "found",
21692     pos, lglpcnt (pos, pos + neg),
21693     neg, lglpcnt (neg, pos + neg));
21694 DONE:
21695   if (lgl->opts->verbose.val >= 1) yals_stats (yals);
21696   yals_del (yals);
21697   lglstop (lgl);
21698 #endif
21699   return lkhd;
21700 }
21701 
lglocs(LGL * lgl)21702 static void lglocs (LGL * lgl) {
21703   (void) lglocsaux (lgl, 0);
21704   lglupdlocslim (lgl, 1);
21705 }
21706 
lglocslook(LGL * lgl)21707 static int lglocslook (LGL * lgl) {
21708   int res = lglocsaux (lgl, 100000), elit;
21709   Ext * ext;
21710   if (res) {
21711     elit = lglexport (lgl, res);
21712     ext = lglelit2ext (lgl, elit);
21713     if (!ext->eliminated && !ext->blocking) {
21714       lglprt (lgl, 1, "[locslook] best local search look-ahead %d", res);
21715       if (ext->melted) {
21716 	ext->melted = 0;
21717 	LOG (2, "look-ahead winner external %d not melted anymore", elit);
21718       } else
21719 	LOG (2, "look-ahead winner external %d was not melted anyhow", elit);
21720     } else {
21721       lglprt (lgl, 1, "[locslook] no valid local search look-ahead");
21722       lglprt (lgl, 1, "[locslook] falling back to JWH");
21723       res = lgljwhlook (lgl);
21724     }
21725   } else LOG (1, "no proper local search look-ahead literal found");
21726 
21727   return res;
21728 }
21729 
21730 /*------------------------------------------------------------------------*/
21731 
lglforklit(int ilit)21732 static int lglforklit (int ilit) {
21733   int idx = abs (ilit), res;
21734   assert (idx > 1);
21735   res = idx - 1;
21736   if (ilit < 0) res = -res;
21737   return res;
21738 }
21739 
21740 /*------------------------------------------------------------------------*/
21741 
lglsweeping(LGL * lgl)21742 static int lglsweeping (LGL * lgl) {
21743   if (!lglsmallirr (lgl)) return 0;
21744   if (!lgl->opts->sweep.val) return 0;
21745   if (lgldelaying (lgl, "sweep", &lgl->limits->sweep.del.rem)) return 0;
21746   if (lglwaiting (lgl, "sweep", lgl->opts->sweepwait.val)) return 0;
21747   return 1;
21748 }
21749 
lglinitsweep(LGL * lgl)21750 static void lglinitsweep (LGL * lgl) {
21751   int idx, lit, pos, neg, rem = 0, ret = 0;
21752   AVar * av;
21753   for (idx = 2; idx < lgl->nvars; idx++) {
21754     if (!lglisfree (lgl, idx)) continue;
21755     if (lglavar (lgl, idx)->donotsweep) ret++; else rem++;
21756   }
21757   if (!rem) {
21758     ret = 0;
21759     for (idx = 2; idx < lgl->nvars; idx++) {
21760       if (!lglisfree (lgl, idx)) continue;
21761       lglavar (lgl, idx)->donotsweep = 0;
21762       rem++;
21763     }
21764   }
21765   pos = neg = 0;
21766   for (idx = 2; idx < lgl->nvars; idx++) {
21767     if (!lglisfree (lgl, idx)) continue;
21768     av = lglavar (lgl, idx);
21769     if (av->donotsweep) continue;
21770     if (av->phase <= 0) lit = -idx, neg++;
21771     else lit = idx, pos++;
21772     lglpushstk (lgl, &lgl->swp->partition, lit);
21773   }
21774   assert (pos + neg == rem);
21775   if (rem > 1) {
21776     lglpushstk (lgl, &lgl->swp->partition, 0);
21777     lgl->swp->partitions++;
21778   } else if (rem) {
21779     assert (rem == 1);
21780     lglclnstk (&lgl->swp->partition);
21781   } else assert (lglmtstk (&lgl->swp->partition));
21782   lglprt (lgl, 1,
21783     "[sweep-%d-%d] %d pos %.1f%% + %d neg %.1f%% = %d sched %.1f%% ret %d",
21784     lgl->stats->sweep.count, lgl->swp->round,
21785     pos, lglpcnt (pos, rem),
21786     neg, lglpcnt (neg, rem),
21787     rem, lglpcnt (rem, lgl->nvars - 2), ret);
21788 }
21789 
lglsweepavgpartitionsize(LGL * lgl)21790 static double lglsweepavgpartitionsize (LGL * lgl) {
21791   int count, n;
21792   double res;
21793   assert (lgl->swp);
21794   if (lglmtstk (&lgl->swp->partition)) return 0;
21795   count = lglcntstk (&lgl->swp->partition);
21796   n = lgl->swp->partitions;
21797   assert (0 < n), assert (n < count);
21798   res = count - n;
21799   res /= n;
21800   return res;
21801 }
21802 
lgladdsweepbincls(LGL * lgl,int a,int b)21803 static void lgladdsweepbincls (LGL * lgl, int a, int b) {
21804   assert (lgl->swp);
21805   assert (lglmtstk (&lgl->clause));
21806   lglpushstk (lgl, &lgl->clause, a);
21807   lglpushstk (lgl, &lgl->clause, b);
21808   lglpushstk (lgl, &lgl->clause, 0);
21809   LOG (2, "sweeping detected binary clause", a, b);
21810   lgldrupligaddcls (lgl, REDCS);
21811   lgladdcls (lgl, REDCS, 0, 1);
21812   lglclnstk (&lgl->clause);
21813 }
21814 
lglsweepsatinitlit(LGL * lgl,int lit,int a,int b)21815 static void lglsweepsatinitlit (LGL * lgl, int lit, int a, int b) {
21816   int idx = abs (lit), decision;
21817   AVar * av;
21818   assert (a > 0), assert (b > 0);
21819   if (a == idx) return;
21820   if (b == idx) return;
21821   av = lglavar (lgl, idx);
21822   if (av->mark) return;
21823   av->mark = 1;
21824   if (lgldefphase (lgl, idx) <= 0) decision = -idx;
21825   else decision = idx;
21826   LOG (2, "sweep SAT adding decision %d", decision);
21827   lglpushstk (lgl, &lgl->swp->decision.stk, decision);
21828 }
21829 
21830 #define LGLCMPSWPDEC(A,B) lgldcmp (lgl, *(B), *(A))
21831 
lglsweepsatinit(LGL * lgl,int a,int b)21832 static void lglsweepsatinit (LGL * lgl, int a, int b) {
21833   int i, idx, sign, lit, blit, tag, red, other, other2, lidx, old, count;
21834   const int sweepred = lgl->opts->sweepred.val;
21835   const int sweepirr = lgl->opts->sweepirr.val;
21836   const int * w, * eow, * p, * c, * l;
21837   HTS * hts;
21838   a = abs (a), b = abs (b);
21839   if (b > a) SWAP (int, a, b);
21840   if (a == lgl->swp->decision.cached.a &&
21841       b == lgl->swp->decision.cached.b) {
21842     LOG (2, "sweep SAT using cached environment of %d and %d", a, b);
21843     lgl->stats->sweep.cached++;
21844     count = lglcntstk (&lgl->swp->decision.stk);
21845     goto DONE;
21846   }
21847   lglclnstk (&lgl->swp->decision.stk);
21848   for (i = 0; i <= 1; i++) {
21849     idx = i ? b : a;
21850     old = lglcntstk (&lgl->swp->decision.stk);
21851     LOG (2, "sweep SAT initializing environment of %d", idx);
21852     for (sign = -1; sign <= 1; sign += 2) {
21853       lit = sign * idx;
21854       hts = lglhts (lgl, lit);
21855       w = lglhts2wchs (lgl, hts);
21856       eow = w + hts->count;
21857       for (p = w; p < eow; p++) {
21858 	blit = *p;
21859 	tag = blit & MASKCS;
21860 	if (tag == TRNCS || tag == LRGCS) p++;
21861 	red = blit & REDCS;
21862 	if (tag == BINCS) {
21863 	  if (!red && sweepirr < 1) continue;
21864 	  if (red && sweepred < 1) continue;
21865 	  other = blit >> RMSHFT;
21866 	  lglsweepsatinitlit (lgl, other, a, b);
21867 	} else if (tag == TRNCS) {
21868 	  if (!red && sweepirr < 2) continue;
21869 	  if (red && sweepred < 2) continue;
21870 	  other = blit >> RMSHFT;
21871 	  lglsweepsatinitlit (lgl, other, a, b);
21872 	  other2 = *p;
21873 	  lglsweepsatinitlit (lgl, other2, a, b);
21874 	} else {
21875 	  assert (tag == LRGCS);
21876 	  if (!red && sweepirr < 3) continue;
21877 	  if (red && sweepred < 3) continue;
21878 	  lidx = *p;
21879 	  c = lglidx2lits (lgl, red, lidx);
21880 	  for (l = c; (other = *l); l++)
21881 	    lglsweepsatinitlit (lgl, other, a, b);
21882 	}
21883       }
21884     }
21885     count = lglcntstk (&lgl->swp->decision.stk) - old;
21886     LOG (2, "sweep SAT environment of %d contains %d decisions", idx, count);
21887     (void) count;
21888   }
21889   for (p = lgl->swp->decision.stk.start; p < lgl->swp->decision.stk.top; p++)
21890     lglavar (lgl, *p)->mark = 0;
21891   lgl->swp->decision.cached.a = a;
21892   lgl->swp->decision.cached.b = b;
21893   count = lglcntstk (&lgl->swp->decision.stk);
21894   SORT (int, lgl->swp->decision.stk.start, count, LGLCMPSWPDEC);
21895 DONE:
21896   LOG (2,
21897     "sweep SAT environment of %d and %d, contains %d decisions",
21898     a, b, count);
21899   lgl->swp->sumsize.envs += count;
21900   lgl->stats->sweep.sumsize.envs += count;
21901 }
21902 
lglsweepdec(LGL * lgl)21903 static int lglsweepdec (LGL * lgl) {
21904   int i, lit = 0;
21905   for (i = 0; i < lglcntstk (&lgl->swp->decision.stk); i++) {
21906     lit = lglpeek (&lgl->swp->decision.stk, i);
21907     if (!lglval (lgl, lit)) break;
21908   }
21909   if (i == lglcntstk (&lgl->swp->decision.stk)) {
21910     LOG (2, "no sweep implication decision left");
21911     return 0;
21912   }
21913   LOG (2,
21914     "sweep typed %d implication check decision %d score %s",
21915     lgl->swp->type, lit, lglscr2str (lgl, lglqvar (lgl, lit)->score));
21916   lgliassume (lgl, lit);
21917   lgl->swp->decision.count++;
21918   lgl->stats->sweep.decs++;
21919   return 1;
21920 }
21921 
lglsweepsat(LGL * lgl,int lim,int a,int b)21922 static int lglsweepsat (LGL * lgl, int lim, int a, int b) {
21923   int n = 0, aval, bval;
21924   assert (lgl->level == 2);
21925   lgl->stats->sweep.sat++;
21926   lgl->swp->sat++;
21927   LOG (2,
21928     "deep sweep implication SAT check %d/%d decision limit %d",
21929     lgl->swp->sat, lgl->stats->sweep.sat, lim);
21930   for (;;) {
21931     if (lglbcp (lgl)) {
21932       if (lgl->mt) return 0;
21933       if ((aval = lglval (lgl, a)) < 0) return 0;
21934       if ((bval = lglval (lgl, b)) > 0) return 0;
21935       if (!aval) {
21936 	assert (!lgl->level);
21937 	lgliassume (lgl, a);
21938 	lgl->swp->decision.count++;
21939 	lgl->stats->sweep.decs++;
21940 	continue;
21941       }
21942       LOG (2,
21943 	"sweep typed %d assumption %d score %s",
21944 	lgl->swp->type, a, lglscr2str (lgl, lglqvar (lgl, a)->score));
21945       if (!bval) {
21946 	assert (lgl->level <= 1);
21947 	lgliassume (lgl, -b);
21948 	lgl->swp->decision.count++;
21949 	lgl->stats->sweep.decs++;
21950 	continue;
21951       }
21952       LOG (2,
21953 	"sweep typed %d assumption %d score %s",
21954 	lgl->swp->type, b, lglscr2str (lgl, lglqvar (lgl, b)->score));
21955       assert (lglval (lgl, a) > 0), assert (lglval (lgl, b) < 0);
21956       if (++n > lim) {
21957 	LOG (2, "deep sweep SAT checking decision limit %d reached", lim);
21958 	return 1;
21959       }
21960       if (!lglsweepdec (lgl)) return 1;
21961     } else if (!lglana (lgl)) return 0;
21962   }
21963 }
21964 
lglsweepliesaux(LGL * lgl,int a,int b)21965 static int lglsweepliesaux (LGL * lgl, int a, int b) {
21966   int ok, val, res, dec;
21967   assert (!lgl->level);
21968   if (lgl->mt) return 0;
21969   if (lglifixed (lgl, a)) return 0;
21970   if (lglifixed (lgl, b)) return 0;
21971   lgliassume (lgl, a);
21972   ok = lglbcp (lgl);
21973   if (ok) {
21974     assert (lgl->level == 1);
21975     val = lglval (lgl, b);
21976     if (val > 0) {
21977       lglbacktrack (lgl, 0);
21978       LOG (1, "sweep implication check %d -> %d subsumed by BCP", a, b);
21979       res = 1;
21980     } else if (val < 0) {
21981       LOG (1, "sweep implication check %d -> %d incompatible with BCP", a, b);
21982       res = 0;
21983     } else {
21984       lgliassume (lgl, -b);
21985       ok = lglbcp (lgl);
21986       if (ok) {
21987 	dec = lgl->stats->sweep.count - 1;
21988 	dec *= lgl->opts->sweepfacdec.val;
21989 	if (dec < lgl->opts->sweepmindec.val)
21990 	  dec = lgl->opts->sweepmindec.val;
21991 	if (dec > lgl->opts->sweepmaxdec.val)
21992 	  dec = lgl->opts->sweepmaxdec.val;
21993 	if (dec) {
21994 	  lglsweepsatinit (lgl, a, b);
21995 	  ok = lglsweepsat (lgl, dec, a, b);
21996 	  if (ok) {
21997 	    LOG (1, "deep sweep implication check %d -> %d failed", a, b);
21998 	    res = 0;
21999 	  } else {
22000 	    lgl->stats->sweep.unsat++;
22001 	    LOG (1, "deep sweep implication check %d -> %d succeeded", a, b);
22002 	    if (lgl->level) lglbacktrack (lgl, 0);
22003 	    res = 1;
22004 	  }
22005 	} else {
22006 	  LOG (2, "skipping sweep implication SAT check");
22007 	  res = 0;
22008 	}
22009       } else {
22010 	LOG (1, "shallow sweep implication check %d -> %d succeeded", a, b);
22011 	lglbacktrack (lgl, 0);
22012 	lgladdsweepbincls (lgl, -a, b);
22013 	lgl->stats->sweep.impls++;
22014 	res = 1;
22015       }
22016     }
22017   } else {
22018     lglbacktrack (lgl, 0);
22019     LOG (1, "failed literal %d during sweep implication check", a);
22020     lgl->stats->sweep.failed++;
22021     lglunit (lgl, -a);
22022     if (!lglbcp (lgl)) {
22023       LOG (1, "empty clause propagating unit in sweep implication check");
22024       lglmt (lgl);
22025     }
22026     res = 0;
22027   }
22028   return res;
22029 }
22030 
lglsweeplies(LGL * lgl,int a,int b)22031 static int lglsweeplies (LGL * lgl, int a, int b) {
22032   int res = lglsweepliesaux (lgl, a, b);
22033   if (!res) lgl->stats->sweep.queries.type[lgl->swp->type].sat++;
22034   else lgl->stats->sweep.queries.type[lgl->swp->type].unsat++;
22035   lglprt (lgl, 2,
22036     "[sweep-%d-%d-%d] implication check %s",
22037     lgl->stats->sweep.count, lgl->swp->round, lgl->swp->query,
22038     res ? "succeeded" : "failed");
22039   return res;
22040 }
22041 
lglsweepquery(LGL * lgl)22042 static void lglsweepquery (LGL * lgl) {
22043   int count = lglcntstk (&lgl->swp->partition), l, r, size;
22044   int p, q, a, b, i, c, newpartitions, newsize, newtotal;
22045   int total = count - lgl->swp->partitions, remove, val;
22046   int * partition = lgl->swp->partition.start;
22047   int minsize, best, start, bestscore;
22048   Stk newpartition;
22049   switch (lgl->swp->query % 5) {
22050     case 1: lgl->swp->type = 2; break;	// score
22051     case 2: lgl->swp->type = 1; break;	// size
22052     case 3: lgl->swp->type = 2; break;	// score
22053     case 4: lgl->swp->type = 1; break;	// size
22054     case 0: lgl->swp->type = 0; break;	// random
22055   }
22056   lgl->stats->sweep.queries.total++;
22057   lgl->stats->sweep.queries.type[lgl->swp->type].count++;
22058   assert (count > 0);
22059   lglprt (lgl, 2,
22060     "[sweep-%d-%d-%d] %d classes with %d vars of avg size %.1f",
22061     lgl->stats->sweep.count, lgl->swp->round, lgl->swp->query,
22062     lgl->swp->partitions, total, lglsweepavgpartitionsize (lgl));
22063 
22064   l = lglrand (lgl) % count;
22065   if (!partition[l]) { assert (l > 0); l--; }
22066   while (l > 0 && partition[l-1])
22067     l--;
22068   if (lgl->swp->type == 1) {		// min size partition
22069     INCSTEPS (sweep.steps);
22070     best = start = l;
22071     minsize = INT_MAX;
22072     do {
22073       assert (l < count);
22074       INCSTEPS (sweep.steps);
22075       size = 0;
22076       for (r = l; (a = partition[r]); r++) {
22077 	COVER (lglifixed (lgl, a));
22078 	if (lglifixed (lgl, a)) continue;
22079 	size++;
22080       }
22081       if (size < minsize) best = l, minsize = size;
22082       if ((l = r + 1) == count) l = 0;
22083     } while (l != start);
22084     l = best;
22085   } else if (lgl->swp->type == 2) {	// best score partition
22086     INCSTEPS (sweep.steps);
22087     best = start = l;
22088     bestscore = 0;
22089     do {
22090       assert (l < count);
22091       INCSTEPS (sweep.steps);
22092       for (r = l; (a = partition[r]); r++) {
22093 	if (lglifixed (lgl, a)) continue;
22094 	if (bestscore && lgldcmp (lgl, a, bestscore) < 0) continue;
22095 	best = l, bestscore = a;
22096       }
22097       if ((l = r + 1) == count) l = 0;
22098     } while (l != start);
22099     l = best;
22100   } else assert (lgl->swp->type == 0);	// random partition
22101   INCSTEPS (sweep.steps);
22102   for (r = l; partition[r]; r++)
22103     ;
22104   size = r - l;
22105   assert (1 < size), assert (size < count);
22106   lgl->swp->sumsize.classes += size;
22107   lgl->stats->sweep.sumsize.classes += size;
22108   lglprt (lgl, 2,
22109     "[sweep-%d-%d-%d] "
22110     "type %d picked size %d class [%d:%d] %.1f%%",
22111     lgl->stats->sweep.count, lgl->swp->round, lgl->swp->query,
22112     lgl->swp->type, size, l, r-1, lglpcnt (size, total));
22113   assert (size >= 2);
22114   p = lglrand (lgl) % size;
22115   q = lglrand (lgl) % size;
22116   if (p == q) q = !p;
22117   if (p + q >= size) q = p + q - size;
22118   p += l, assert (l <= p), assert (p < r);
22119   q += l, assert (l <= p), assert (q < r);
22120   assert (p != q);
22121   a = partition [p];
22122   b = partition [q];
22123   for (i = l; i < r; i++) {
22124     if (i == p) continue;
22125     if (i == q) continue;
22126     c = partition[i];
22127     if (lgldcmp (lgl, c, a) > 0) a = c, p = i;
22128   }
22129   for (i = l; i < r; i++) {
22130     if (i == p) continue;
22131     if (i == q) continue;
22132     c = partition[i];
22133     if (lgldcmp (lgl, c, b) > 0) b = c, q = i;
22134   }
22135   assert (a), assert (b);
22136   assert (abs (a) != abs (b));
22137   LOG (2,
22138     "picked literal pair %d and %d at position %d and %d",
22139     a, b, p, q);
22140   assert (!lgl->level);
22141   if (lglsweeplies (lgl, a, b) && lglsweeplies (lgl, b, a)) {
22142     assert (!lgl->level);
22143     lgl->stats->sweep.equivs++;
22144     remove = b;
22145     LOG (2,
22146       "found equivalence between %d and %d and will remove %d",
22147       a, b, b);
22148   } else remove = 0;
22149   CLR (newpartition);
22150   newsize = newpartitions = 0;
22151   if (!lgl->mt) {
22152     for (val = -1; val <= 1; val++) {
22153       for (i = 0; i < count; i++) {
22154 	if ((c = partition[i])) {
22155 	  if (c == remove) continue;
22156 	  if (lglifixed (lgl, c)) continue;
22157 	  if (lglval (lgl, c) != val) continue;
22158 	  lglpushstk (lgl, &newpartition, c);
22159 	  newsize++;
22160 	} else if (newsize > 1) {
22161 	  lglpushstk (lgl, &newpartition, 0);
22162 	  newpartitions++;
22163 	  newsize = 0;
22164 	} else if (newsize) {
22165 	  assert (newsize == 1);
22166 	  (void) lglpopstk (&newpartition);
22167 	  newsize = 0;
22168 	}
22169       }
22170     }
22171     ADDSTEPS (sweep.steps, (count >> 3));
22172   }
22173   assert (!newsize);
22174   assert (!newpartitions || !newpartition.top[-1]);
22175   newtotal = lglcntstk (&newpartition) - newpartitions;
22176   if (lgl->level > 0) lglbacktrack (lgl, 0);
22177   if (lgl->swp->partitions >= newpartitions)
22178     lglprt (lgl, 2,
22179       "[sweep-%d-%d-%d] removed %d literals and removed %d classes",
22180       lgl->stats->sweep.count, lgl->swp->round, lgl->swp->query,
22181       total - newtotal, lgl->swp->partitions - newpartitions);
22182   else
22183     lglprt (lgl, 2,
22184       "[sweep-%d-%d-%d] removed %d literals and added %d classes",
22185       lgl->stats->sweep.count, lgl->swp->round, lgl->swp->query,
22186       total - newtotal, newpartitions - lgl->swp->partitions);
22187   lgl->swp->partitions = newpartitions;
22188   lglfitstk (lgl, &newpartition);
22189   lglrelstk (lgl, &lgl->swp->partition);
22190   lgl->swp->partition = newpartition;
22191 }
22192 
lglsetsweeplim(LGL * lgl)22193 static void lglsetsweeplim (LGL * lgl) {
22194   int count = lgl->stats->sweep.count - lgl->opts->sweepboostdel.val;
22195   int64_t limit, irrlim;
22196   int pen, szpen;
22197   if (lgl->opts->sweeprtc.val > 1) {
22198     lgl->limits->sweep.steps = LLMAX;
22199     lglprt (lgl, 1,
22200       "[sweep-%d] really no limit (run to completion)",
22201       lgl->stats->sweep.count);
22202   } else if (lgl->opts->sweeprtc.val ||
22203 	     lgl->opts->prbrtc.val ||
22204 	     (count > 0 &&
22205 	      lglrem (lgl) < lgl->opts->sweeprtcintvlim.val &&
22206 	      !(count % lgl->opts->sweeprtcint.val))) {
22207     limit = 4000000000ll;
22208     lgl->limits->sweep.steps = lgl->stats->sweep.steps + limit;
22209     lglprt (lgl, 1,
22210       "[sweep-%d] almost no limit of %lld steps",
22211       lgl->stats->sweep.count, (LGLL) limit);
22212   } else {
22213     limit = (lgl->opts->sweepreleff.val*lglvisearch (lgl))/1000;
22214     if (limit < lgl->opts->sweepmineff.val)
22215       limit = lgl->opts->sweepmineff.val;
22216     if (lgl->opts->sweepmaxeff.val >= 0 &&
22217 	limit > lgl->opts->sweepmaxeff.val)
22218       limit = lgl->opts->sweepmaxeff.val;
22219     if (count > 0 &&
22220         (count <= 1 || !(count % lgl->opts->sweepboostint.val)) &&
22221 	lglrem (lgl) < lgl->opts->sweepboostvlim.val &&
22222         lgl->opts->boost.val &&
22223         lgl->opts->sweepboost.val > 1) {
22224       lglprt (lgl, 1,
22225 	"[sweep-%d] boosting sweeping limit by %d",
22226 	lgl->stats->sweep.count, lgl->opts->sweepboost.val);
22227       limit *= lgl->opts->sweepboost.val;
22228     }
22229     limit >>= (pen = lgl->limits->sweep.pen + (szpen = lglszpen (lgl)));
22230     irrlim = (2*lgl->stats->irr.clauses.cur) >> szpen;
22231     if (lgl->opts->irrlim.val && limit < irrlim) {
22232       limit = irrlim;
22233       lglprt (lgl, 1,
22234 	"[sweep-%d] limit %lld based on %d irredundant clauses penalty %d",
22235 	lgl->stats->sweep.count,
22236 	(LGLL) limit, lgl->stats->irr.clauses.cur, szpen);
22237     } else
22238       lglprt (lgl, 1,
22239         "[sweep-%d] limit %lld penalty %d = %d + %d",
22240 	lgl->stats->sweep.count, (LGLL) limit,
22241 	pen, lgl->limits->sweep.pen, szpen);
22242     lgl->limits->sweep.steps = lgl->stats->sweep.steps + limit;
22243   }
22244 }
22245 
lglsweepretain(LGL * lgl)22246 static void lglsweepretain (LGL * lgl) {
22247   int idx, ret = 0, rem = 0, sum;
22248   const int * p;
22249   for (idx = 2; idx < lgl->nvars; idx++)
22250     lglavar (lgl, idx)->donotsweep = 1;
22251   for (p = lgl->swp->partition.start;
22252        p < lgl->swp->partition.top;
22253        p++) {
22254     if(!(idx = *p)) continue;
22255     lglavar (lgl, idx)->donotsweep = 0;
22256   }
22257   for (idx = 2; idx < lgl->nvars; idx++) {
22258     if (!lglisfree (lgl, idx)) continue;
22259     if (lglavar (lgl, idx)->donotsweep) ret++; else rem++;
22260   }
22261   if (rem) {
22262     sum = rem + ret;
22263     lglprt (lgl, 1,
22264       "[sweep-%d-%d] %d variables remain %.0f%% (%d retained %.0f%%)",
22265       lgl->stats->sweep.count, lgl->swp->round,
22266       rem, lglpcnt (rem, sum),
22267       ret, lglpcnt (ret, sum));
22268   } else {
22269     lglprt (lgl, 1,
22270       "[sweep-%d-%d] fully completed sweeping round",
22271       lgl->stats->sweep.count, lgl->swp->round);
22272     for (idx = 2; idx < lgl->nvars; idx++)
22273       lglavar (lgl, idx)->donotsweep = 0;
22274     lgl->sweeprtc = 1;
22275   }
22276 }
22277 
lglsweep(LGL * lgl)22278 static int lglsweep (LGL * lgl) {
22279   int deltarem, deltafailed, deltaimpls, deltaequivs, deltaorigrem;
22280   int round, origrem, oldrem, oldfailed, oldimpls, oldequivs;
22281   int64_t oldsteps, deltasteps, origqueries, deltaqueries;
22282   int success, forgive;
22283   lglstart (lgl, &lgl->times->sweep);
22284   if (lgl->level > 0) lglbacktrack (lgl, 0);
22285   assert (!lgl->simp), assert (!lgl->sweeping);
22286   lgl->simp = lgl->sweeping = 1;
22287   if (!lglbcp (lgl)) goto DONE;
22288   lglgc (lgl);
22289   if (lgl->mt) goto DONE;
22290   lgl->stats->sweep.count++;
22291   lglsetsweeplim (lgl);
22292   origrem = lglrem (lgl);
22293   origqueries = lgl->stats->sweep.queries.total;
22294   round = 0;
22295   forgive = lgl->opts->sweepforgive.val;
22296 RESTART:
22297   round++;
22298   lgl->stats->sweep.rounds++;
22299   oldrem = lglrem (lgl);
22300   oldfailed = lgl->stats->sweep.failed;
22301   oldimpls = lgl->stats->sweep.impls;
22302   oldequivs = lgl->stats->sweep.equivs;
22303   oldsteps = lgl->stats->sweep.steps;
22304   assert (!lgl->swp);
22305   NEW (lgl->swp, 1);
22306   lgl->swp->round = round;
22307   lglinitsweep (lgl);
22308   for (lgl->swp->query = 1;
22309     !lgl->mt &&
22310       !lglmtstk (&lgl->swp->partition) &&
22311       lgl->stats->sweep.steps <= lgl->limits->sweep.steps;
22312     lgl->swp->query++)
22313     lglsweepquery (lgl);
22314   deltasteps = lgl->stats->sweep.steps - oldsteps;
22315   lglprt (lgl, 1,
22316     "[sweep-%d-%d] %lld steps %d queries %.2f avg class size",
22317     lgl->stats->sweep.count, round,
22318     (LGLL) deltasteps, lgl->swp->query,
22319       lglavg (lgl->swp->sumsize.classes, lgl->swp->query));
22320   lglprt (lgl, 1,
22321     "[sweep-%d-%d] %d decisions %d SAT calls %.2f avg env size",
22322     lgl->stats->sweep.count, round,
22323     lgl->swp->decision.count, lgl->swp->sat,
22324       lglavg (lgl->swp->sumsize.envs, lgl->swp->sat));
22325   lglrelstk (lgl, &lgl->swp->decision.stk);
22326   lglsweepretain (lgl);
22327   lglrelstk (lgl, &lgl->swp->partition);
22328   if (!lgl->mt) lgldecomp (lgl);
22329   assert (lgl->swp->round == round);
22330   DEL (lgl->swp, 1);
22331   lgl->swp = 0;
22332   deltarem = oldrem - lglrem (lgl);
22333   deltafailed = lgl->stats->sweep.failed - oldfailed;
22334   deltaimpls = lgl->stats->sweep.impls - oldimpls;
22335   deltaequivs = lgl->stats->sweep.equivs - oldequivs;
22336   lglprt (lgl, 1,
22337     "[sweep-%d-%d] removed %d vars (%d failed, %d eqs, %d impls)",
22338     lgl->stats->sweep.count, round,
22339     deltarem, deltafailed, deltaequivs, deltaimpls);
22340   if ((deltarem || forgive > 0) &&
22341       !lgl->mt &&
22342       (lgl->opts->sweepmaxround.val < 0 ||
22343        round < lgl->opts->sweepmaxround.val) &&
22344       lgl->stats->sweep.steps <= lgl->limits->sweep.steps) {
22345     if (deltarem) forgive = lgl->opts->sweepforgive.val; else forgive--;
22346     goto RESTART;
22347   }
22348   deltaorigrem = origrem - lglrem (lgl);
22349   if (!lgl->sweeprtc &&
22350       lgl->stats->sweep.count <= lgl->opts->sweepsuccessmaxwortc.val) {
22351     success = 1;
22352     lglprt (lgl, 1,
22353       "[sweep-%d] considered successful since not run to completion yet",
22354       lgl->stats->sweep.count);
22355   } else if (deltaorigrem) {
22356     success = (origrem/lgl->opts->sweepsuccessrat.val <= deltaorigrem);
22357     if (!success)
22358       lglprt (lgl, 1,
22359 	"[sweep-%d] %d < 1/%d * %d = %d considered unsuccessful",
22360 	lgl->stats->sweep.count, deltaorigrem, lgl->opts->sweepsuccessrat.val,
22361 	origrem, origrem/lgl->opts->sweepsuccessrat.val);
22362   } else success = 0;
22363   LGLUPDPEN (sweep, success);
22364   deltaqueries = lgl->stats->sweep.queries.total - origqueries;
22365   lglprt (lgl, 1,
22366     "[sweep-%d] removed %d vars in TOTAL (%d rounds, %lld queries)",
22367     lgl->stats->sweep.count, deltaorigrem, round, (LGLL) deltaqueries);
22368 DONE:
22369   assert (lgl->simp), assert (lgl->sweeping);
22370   lgl->simp = lgl->sweeping = 0;
22371   lglstop (lgl);
22372   return !lgl->mt;
22373 }
22374 
22375 /*------------------------------------------------------------------------*/
22376 
lglqcmp(LGL * lgl,int a,int b)22377 static int lglqcmp (LGL * lgl, int a, int b) {
22378   Flt ascore, bscore, pos, neg;
22379   pos = lgl->jwh[lglulit (a)];
22380   neg = lgl->jwh[lglulit (-a)];
22381   ascore = lglmulflt (pos, neg);
22382   pos = lgl->jwh[lglulit (b)];
22383   neg = lgl->jwh[lglulit (-b)];
22384   bscore = lglmulflt (pos, neg);
22385   if (ascore < bscore) return -1;
22386   if (ascore > bscore) return 1;
22387   return a - b;
22388 }
22389 
22390 #define LGLQCMP(A,B) lglqcmp (lgl, *(A), *(B))
22391 
lglqueuesort(LGL * lgl)22392 static void lglqueuesort (LGL * lgl) {
22393   int count, i, lit;
22394   QVar * qv;
22395   lglstart (lgl, &lgl->times->queuesort);
22396   if (lgl->queue.mt) lglqueueflush (lgl);
22397   lgl->stats->queue.sorted++;
22398   assert (!lgl->queue.mt);
22399   count = lglcntstk (&lgl->queue.stk);
22400   assert (count > 0);
22401   SORT (int, lgl->queue.stk.start, count, LGLQCMP);
22402   for (i = 0; i < count; i++) {
22403     lit = lglpeek (&lgl->queue.stk, i);
22404     qv = lglqvar (lgl, lit);
22405     assert (qv->enqueued);
22406     assert (qv->pos >= 0);
22407     qv->pos = i;
22408   }
22409   lglprt (lgl, 2,
22410     "[sort-queue-%d] sorted %d after %lld conflicts and %lld flushed queues",
22411     (LGLL) lgl->stats->queue.sorted, count,
22412     (LGLL) lgl->stats->confs, (LGLL) lgl->stats->queue.flushed);
22413   lgl->queue.next = count - 1;
22414   lglstop (lgl);
22415 }
22416 
lglqueuesorting(LGL * lgl)22417 static int lglqueuesorting (LGL * lgl) {
22418   int count = lglcntstk (&lgl->queue.stk);
22419   assert (lgl->queue.mt <= count);
22420   if (lgl->queue.mt >= count) return 0;
22421   return lgl->opts->queuesort.val;
22422 }
22423 
22424 /*------------------------------------------------------------------------*/
22425 
22426 #define LGLCMPSCR(A,B) lglscrcmp (lgl, *(A), *(B))
22427 
lglshowscoredist(LGL * lgl)22428 static void lglshowscoredist (LGL * lgl) {
22429   int idx, pos = 0, zero = 0, min = 0, sum = 0, diff;
22430   Flt * scores;
22431   QVar * q;
22432   lglstart (lgl, &lgl->times->showscoredist);
22433   NEW (scores, lgl->nvars);
22434   for (idx = 2; idx < lgl->nvars; idx++) {
22435     if (!lglisfree (lgl, idx)) continue;
22436     q = lglqvar (lgl, idx);
22437     if (q->score == FLTMIN) zero++;
22438     else if (q->score <= lgl->minscore) min++;
22439     else pos++;
22440     scores[sum++] = q->score;
22441   }
22442   lglprt (lgl, 1,
22443     "[score-distribution-%d] "
22444     "%d pos %.2f%%, %d min %.2f%%, %d zero %.2f%%",
22445     lgl->stats->simp.count,
22446     pos, lglpcnt (pos, sum),
22447     min, lglpcnt (min, sum),
22448     zero, lglpcnt (zero, sum));
22449   SORT (Flt, scores, sum, LGLCMPSCR);
22450   diff = 0;
22451   for (idx = 0; idx < sum; idx++)
22452     if (!idx || lglscrcmp (lgl, scores[idx-1], scores[idx])) diff++;
22453   DEL (scores, lgl->nvars);
22454   lglprt (lgl, 1,
22455     "[score-distribution-%d] "
22456     "%d different %.2f%% out of total %d variables",
22457     lgl->stats->simp.count,
22458     diff, lglpcnt (diff, sum),
22459     sum);
22460   lglstop (lgl);
22461 }
22462 
lglfeatures(LGL * lgl)22463 static Features lglfeatures (LGL * lgl) {
22464   int idx, sign, lit, blit, tag, red, other, other1, len, lrg;
22465   const int * p, * w, * eow, * c;
22466   HTS * hts;
22467   Features res;
22468   CLR (res);
22469   res.n = lgl->stats->features;
22470   res.s = lglsec (lgl);
22471   res.vo = lgl->limits->inc.vars.start;
22472   res.vc = lglrem (lgl);
22473   res.co = lgl->limits->inc.clauses.start;
22474   res.cc = lgl->stats->irr.clauses.cur;
22475   res.x = lgl->stats->gauss.extracted.last;
22476   res.a1 = lgl->stats->card.found.am1.last.cnt;
22477   res.a2 = lgl->stats->card.found.am2.last.cnt;
22478   res.c = lgl->stats->confs / 1000;
22479   res.o = lgl->stats->otfs.total / 1000;
22480   res.g = lgl->stats->glue.slow.val >> 32;
22481   res.j = lgl->stats->jlevel.slow.val >> 32;
22482   for (idx = 2; idx < lgl->nvars; idx++)
22483     for (sign = -1; sign <= 1; sign += 2) {
22484       lit = sign * idx;
22485       hts = lglhts (lgl, lit);
22486       w = lglhts2wchs (lgl, hts);
22487       eow = w + hts->count;
22488       for (p = w; p < eow; p++) {
22489 	blit = *p;
22490 	tag = blit & MASKCS;
22491 	red = blit & REDCS;
22492 	if (tag == TRNCS || tag == LRGCS) p++;
22493 	if (red || tag == LRGCS) continue;
22494 	other = blit >> RMSHFT;
22495 	if (abs (other) < idx) continue;
22496 	if (tag == BINCS) {
22497 	  res.b++;
22498 	} else {
22499 	  assert (tag == TRNCS);
22500 	  other1 = *p;
22501 	  if (abs (other1) < idx) continue;
22502 	  res.t++;
22503 	}
22504       }
22505     }
22506   lrg = 0;
22507   for (c = lgl->irr.start; c < lgl->irr.top; c = p + 1) {
22508     if (*(p = c) >= REMOVED) continue;
22509     while (*++p)
22510       ;
22511     len = p - c;
22512     if (len <= 4) res.q++;
22513     else if (len <= 10) res.c1++;
22514     else if (len <= 100) res.c2++;
22515     else if (len <= 1000) res.c3++;
22516     else if (len <= 10000) res.c4++;
22517     else lrg++;
22518   }
22519   assert (res.b + res.t + res.q +
22520           res.c1 + res.c2 + res.c3 + res.c4 + lrg == res.cc);
22521   return res;
22522 }
22523 
lglnormfeatures(Features f)22524 static Features lglnormfeatures (Features f) {
22525   Features res = f;
22526   int * p = (int*) &res, i;
22527   for (i = 2; i < NFEATURES; i++)
22528     p[i] = lglceild (p[i] + 1);
22529   return res;
22530 }
22531 
lglintstrlen(int i)22532 static int lglintstrlen (int i) {
22533   assert (i >= 0);
22534   if (i < 10) return 1;
22535   if (i < 100) return 2;
22536   if (i < 1000) return 3;
22537   if (i < 10000) return 4;
22538   if (i < 100000) return 5;
22539   if (i < 1000000) return 6;
22540   if (i < 10000000) return 7;
22541   if (i < 100000000) return 8;
22542   if (i < 1000000000) return 9;
22543   return 10;
22544 }
22545 
lglshowfeatures(LGL * lgl)22546 static void lglshowfeatures (LGL * lgl) {
22547   int size[NFEATURES], i;
22548   const int * p;
22549   char fmt[20];
22550   Features f, n;
22551   if (!lgl->opts->features.val) return;
22552   if (lgl->opts->verbose.val <= 0) return;
22553   if (lgl->stats->features >= lgl->opts->features.val) return;
22554   lglstart (lgl, &lgl->times->showfeatures);
22555   f = lglfeatures (lgl);
22556   p = (int*) &f;
22557   for (i = 0; i < NFEATURES; i++)
22558     size[i] = lglmax (strlen (featurenames[i]), lglintstrlen (p[i]));
22559 
22560   lglmsgstart (lgl, 0);
22561   fprintf (lgl->out, "[heatures-%d]", f.n);
22562   for (i = 0; i < NFEATURES; i++) {
22563     sprintf (fmt, " %%%ds",  size[i]);
22564     fprintf (lgl->out, fmt, featurenames[i]);
22565   }
22566   lglmsgend (lgl);
22567 
22568   lglmsgstart (lgl, 0);
22569   fprintf (lgl->out, "[features-%d]", f.n);
22570   for (i = 0; i < NFEATURES; i++) {
22571     sprintf (fmt, " %%%dd",  size[i]);
22572     fprintf (lgl->out, fmt, p[i]);
22573   }
22574   lglmsgend (lgl);
22575 
22576   n = lglnormfeatures (f);
22577   p = (int*) &n;
22578   lglmsgstart (lgl, 0);
22579   fprintf (lgl->out, "[neatures-%d]", n.n);
22580   for (i = 0; i < NFEATURES; i++) {
22581     sprintf (fmt, " %%%dd",  size[i]);
22582     fprintf (lgl->out, fmt, p[i]);
22583   }
22584   lglmsgend (lgl);
22585   lgl->stats->features++;
22586   lglstop (lgl);
22587 }
22588 
22589 /*------------------------------------------------------------------------*/
22590 
lglisimp(LGL * lgl)22591 static int lglisimp (LGL * lgl) {
22592   if (!lgl->opts->simplify.val) return 1;
22593 
22594   if (lglquatresolving (lgl)) lglquatres (lgl);
22595   if (lglterminate (lgl)) return 1;
22596   assert (!lgl->mt);
22597 
22598   if (lglternresolving (lgl) && !lglternres (lgl)) return 0;
22599   if (lglterminate (lgl)) return 1;
22600   assert (!lgl->mt);
22601 
22602   if (lglcarding (lgl) && !lglcard (lgl)) return 0;
22603   if (lglterminate (lgl)) return 1;
22604   assert (!lgl->mt);
22605 
22606   if (lglgaussing (lgl) && !lglgauss (lgl)) return 0;
22607   if (lglterminate (lgl)) return 1;
22608   assert (!lgl->mt);
22609 
22610   if (lgldecomposing (lgl) && !lgldecomp (lgl)) return 0;
22611   if (lglterminate (lgl)) return 1;
22612   assert (!lgl->mt);
22613 
22614   if (lglprobing (lgl) && !lglprobe (lgl)) return 0;
22615   if (lglterminate (lgl)) return 1;
22616   assert (!lgl->mt);
22617 
22618   if (lglunhiding (lgl) && !lglunhide (lgl)) return 0;
22619   if (lglterminate (lgl)) return 1;
22620   assert (!lgl->mt);
22621 
22622   if (lgltreducing (lgl) && !lgltrd (lgl)) return 0;
22623   if (lglterminate (lgl)) return 1;
22624   assert (!lgl->mt);
22625 
22626   if (lglblocking (lgl)) lglblock (lgl);
22627   if (lglterminate (lgl)) return 1;
22628   assert (!lgl->mt);
22629 
22630   if (lglcceing (lgl) && !lglcce (lgl)) return 0;
22631   if (lglterminate (lgl)) return 1;
22632   assert (!lgl->mt);
22633 
22634   if (lgleliminating (lgl) && !lglelim (lgl)) return 0;
22635   if (lglterminate (lgl)) return 1;
22636   assert (!lgl->mt);
22637 
22638   if (!lgltopgc (lgl)) return 0;
22639   if (lglterminate (lgl)) return 1;
22640   assert (!lgl->mt);
22641 
22642   if (lglbcaing (lgl)) lglbca (lgl);
22643   if (lglterminate (lgl)) return 1;
22644   assert (!lgl->mt);
22645 
22646   if (lglsweeping (lgl) && !lglsweep (lgl)) return 0;
22647   if (lglterminate (lgl)) return 1;
22648   assert (!lgl->mt);
22649 
22650   if (!lgl->allphaseset) lglphase (lgl);
22651   if (lglterminate (lgl)) return 1;
22652   assert (!lgl->mt);
22653 
22654   if (lglqueuesorting (lgl)) lglqueuesort (lgl);
22655   if (lglterminate (lgl)) return 1;
22656 
22657   lgldefrag (lgl);
22658   if (lglterminate (lgl)) return 1;
22659 
22660   lglshowscoredist (lgl);
22661   lglshowfeatures (lgl);
22662 
22663   return 1;
22664 }
22665 
lglupdsimpcinc(LGL * lgl,int red,int success)22666 static void lglupdsimpcinc (LGL * lgl, int red, int success) {
22667   const char * type = "no";
22668   int inc = 0, div = 1, res;
22669   assert (red >= 0);
22670   if (red <= 100) {
22671     if (red > 0) {
22672       switch (lgl->opts->simpcintincdiv.val) {
22673 	case 3:
22674 	  if (red >= 50) div = 4;
22675 	  else if (red >= 20) div = 3;
22676 	  else if (red >= 10) div = 2;
22677 	  break;
22678 	case 2: div = red/2 + 1; break;
22679 	case 1: div = red/1 + 1; break;
22680 	case 0:
22681 	default:
22682           assert (!lgl->opts->simpcintincdiv.val);
22683 	  break;
22684       }
22685     }
22686     inc = lgl->opts->simpcintinc.val;
22687     if (lgl->opts->simplify.val == 1) {
22688       type = "arithmetic";
22689     } else if (lgl->opts->simplify.val == 2) {
22690       if (inc < lgl->limits->simp.cinc) inc = lgl->limits->simp.cinc;
22691       type = "geometric";
22692     } else inc = 0;
22693   }
22694   res = inc / div;
22695   if (lgl->limits->simp.cinc - res <= INT_MAX)
22696     lgl->limits->simp.cinc += res;
22697   lglprt (lgl, 2,
22698     "[simplification-%d] new lgl->limits->simp.cinc %d",
22699     lgl->stats->simp.count, lgl->limits->simp.cinc);
22700   if (div > 1)
22701     lglprt (lgl, 1,
22702       "[simplification-%d] %s conflict interval increment %d = %d / %d",
22703       lgl->stats->simp.count, type, res, inc, div);
22704   else
22705     lglprt (lgl, 1,
22706       "[simplification-%d] full %s conflict interval increment %d",
22707       lgl->stats->simp.count, type, res);
22708 
22709   if (success &&
22710       lgl->opts->simpcintmaxsoft.val >= 0 &&
22711       lgl->limits->simp.cinc >= lgl->opts->simpcintmaxsoft.val) {
22712     lgl->limits->simp.cinc = lgl->opts->simpcintmaxsoft.val;
22713     lglprt (lgl, 1,
22714       "[simplification-%d] "
22715       "conflict interval soft limit %d reached",
22716       lgl->stats->simp.count, lgl->limits->simp.cinc);
22717   } else if (lgl->opts->simpcintmaxhard.val >= 0 &&
22718              lgl->limits->simp.cinc >= lgl->opts->simpcintmaxhard.val) {
22719     lgl->limits->simp.cinc = lgl->opts->simpcintmaxhard.val;
22720     lglprt (lgl, 1,
22721       "[simplification-%d] "
22722       "conflict interval hard limit %d reached",
22723       lgl->stats->simp.count, lgl->limits->simp.cinc);
22724   }
22725 }
22726 
lglsethardsimplim(LGL * lgl)22727 static void lglsethardsimplim (LGL * lgl) {
22728   int64_t hard, delta;
22729   delta = lgl->limits->simp.confs - lgl->stats->confs;
22730   if (delta < 0) delta = 0;
22731   delta *= lgl->opts->simpincdelmaxfact.val;
22732   delta /= 100;
22733   if (delta < lgl->opts->simpincdelmaxmin.val)
22734     delta = lgl->opts->simpincdelmaxmin.val;
22735   if (LLMAX - delta < lgl->limits->simp.confs) hard = LLMAX;
22736   else hard = lgl->limits->simp.confs + delta;
22737   lgl->limits->simp.hard = hard;
22738   lglprt (lgl, 1,	// TODO set this to 2
22739     "[simplification-%d] hard conflict limit %lld (soft %lld + delta %lld)",
22740     lgl->stats->simp.count,
22741     (LGLL) lgl->limits->simp.hard, (LGLL) lgl->limits->simp.confs, (LGLL) delta);
22742 }
22743 
lglupdsimpint(LGL * lgl,int oldrem,int oldirr,int forced)22744 static void lglupdsimpint (LGL * lgl, int oldrem, int oldirr, int forced) {
22745   int remvar, remirr, pcntred, simpcinc;
22746   int64_t pcntremvar64, pcntremirr64;
22747   int pcntremvar, pcntremirr;
22748 
22749   remvar = oldrem - lglrem (lgl);
22750   if (remvar < 0) remvar = 0;
22751   pcntremvar64 = (remvar > 0) ? ((1000ll*remvar)/oldrem + 5)/10 : 0ll;
22752   assert (pcntremvar64 <= 100);
22753   pcntremvar = pcntremvar64;
22754   lglprt (lgl, 1,
22755     "[simplification-%d] removed %d variables %.1f%% "
22756     "(%d remain %0.f%%)",
22757     lgl->stats->simp.count, remvar, lglpcnt (remvar, oldrem),
22758     lglrem (lgl), lglpcnt (lglrem (lgl), lgl->limits->inc.vars.start));
22759 
22760   remirr = oldirr - lgl->stats->irr.clauses.cur;
22761   if (remirr < 0) remirr = 0;
22762   pcntremirr64 = (remirr > 0) ? ((1000ll*remirr)/oldirr + 5)/10 : 0ll;
22763   assert (pcntremirr64 <= 100);
22764   pcntremirr = pcntremirr64;
22765   lglprt (lgl, 1,
22766     "[simplification-%d] removed %d irredundant clauses %.1f%% "
22767     "(%d remain %.0f%%)",
22768     lgl->stats->simp.count, remirr, lglpcnt (remirr, oldirr),
22769     lgl->stats->irr.clauses.cur,
22770       lglpcnt (lgl->stats->irr.clauses.cur, lgl->limits->inc.clauses.start));
22771 
22772   pcntred = lglmax (pcntremvar, pcntremirr);
22773   lglprt (lgl, 1,
22774     "[simplification-%d] maximum reduction of %d%% = max (%d%%, %d%%)",
22775     lgl->stats->simp.count, pcntred, pcntremvar, pcntremirr);
22776 
22777   if (forced) {
22778     simpcinc = 0;
22779     lglprt (lgl, 1,
22780       "[simplification-%d] forced so keeping old conflict interval %d",
22781       lgl->stats->simp.count, lgl->limits->simp.cinc);
22782   } else if (lgl->stats->confs < lgl->limits->simp.confs &&
22783              (simpcinc = lgl->limits->simp.cinc)) {
22784     lglprt (lgl, 1,
22785       "[simplification-%d] keeping old conflict interval %d "
22786       "(non-conflict triggered simplification)",
22787       lgl->stats->simp.count, lgl->limits->simp.cinc);
22788   } else if (remvar > 0 && pcntred >= lgl->opts->simprtc.val) {
22789     int64_t scaledcinc;
22790     int factor;
22791     lglprt (lgl, 1,
22792       "[simplification-%d] large reduction %d%% >= %d%% limit",
22793       lgl->stats->simp.count, pcntred, lgl->opts->simprtc.val);
22794     factor = lgl->opts->simpidiv.val - lgl->stats->simp.count;
22795     if (factor <= 0) factor = 1;
22796     simpcinc = lgl->opts->simpcintdelay.val / factor;
22797     scaledcinc = lgl->stats->confs/lgl->opts->simpiscale.val;
22798     if (scaledcinc > lgl->limits->simp.cinc)
22799       scaledcinc = lgl->limits->simp.cinc;
22800     if (scaledcinc < simpcinc) {
22801       lglprt (lgl, 1,
22802 	"[simplification-%d] next conflict interval %d = %d/%d",
22803 	lgl->stats->simp.count,
22804 	simpcinc, lgl->opts->simpcintdelay.val, factor);
22805     } else {
22806       assert (scaledcinc <= INT_MAX);
22807       simpcinc = (int) scaledcinc;
22808       lglprt (lgl, 1,
22809 	"[simplification-%d] next conflict interval %d = min (%lld/%d, %d)",
22810 	lgl->stats->simp.count,
22811 	simpcinc, (LGLL) lgl->stats->confs, lgl->opts->simpiscale.val,
22812 	lgl->limits->simp.cinc);
22813     }
22814   } else {
22815     lglupdsimpcinc (lgl, pcntred, remvar || remirr);
22816     simpcinc = lgl->limits->simp.cinc;
22817     lglprt (lgl, 1,
22818       "[simplification-%d] new conflict interval %d",
22819       lgl->stats->simp.count, simpcinc);
22820   }
22821 
22822   if (forced) {
22823     lglprt (lgl, 1,
22824       "[simplification-%d] conflict limit remains at %lld (hard %lld)",
22825       lgl->stats->simp.count,
22826       (LGLL) lgl->limits->simp.confs, (LGLL) lgl->limits->simp.hard);
22827   } else {
22828     int penalty, pensimpcinc;
22829          if (!lgl->opts->simpintsizepen.val ||
22830 	     lgl->stats->irr.clauses.cur <    1000000)    penalty = 1;
22831     else if (lgl->stats->irr.clauses.cur <   10000000)    penalty = 2;
22832     else /*  lgl->stats->irr.clauses.cur >=  10000000) */ penalty = 4;
22833     if (INT_MAX/penalty < simpcinc) pensimpcinc = INT_MAX;
22834     else pensimpcinc = penalty * simpcinc;
22835     lglprt (lgl, 1,
22836       "[simplification-%d] penalized conflict interval %d = %d * %d",
22837       lgl->stats->simp.count, pensimpcinc, penalty, simpcinc);
22838     assert (pensimpcinc >= 0);
22839     lgl->limits->simp.confs = lgl->stats->confs + pensimpcinc;
22840     assert (lgl->limits->simp.confs >= 0);
22841     lglsethardsimplim (lgl);
22842     lglprt (lgl, 1,
22843       "[simplification-%d] new conflict limit %lld (hard %lld)",
22844       lgl->stats->simp.count,
22845       (LGLL) lgl->limits->simp.confs, (LGLL) lgl->limits->simp.hard);
22846   }
22847 
22848   if (lgl->stats->confs >= lgl->limits->simp.confs) {
22849     lgl->limits->simp.confs = lgl->stats->confs + 1;
22850     if (lgl->limits->simp.hard < lgl->limits->simp.confs)
22851        lgl->limits->simp.hard = lgl->limits->simp.confs;
22852     lglprt (lgl, 1,
22853       "[simplification-%d] "
22854       "fixed conflict limit %d (wait at least for one conflict)",
22855       lgl->stats->simp.count, lgl->stats->confs);
22856   }
22857 
22858   if (forced == 1 &&
22859       lgl->limits->simp.itinc < lgl->opts->simpitintinclim.val) {
22860     if (lgl->limits->simp.itinc < INT_MAX/10) lgl->limits->simp.itinc *= 10;
22861     else lgl->limits->simp.itinc = INT_MAX;
22862     if (lgl->limits->simp.itinc > lgl->opts->simpitintinclim.val)
22863       lgl->limits->simp.itinc = lgl->opts->simpitintinclim.val;
22864     lglprt (lgl, 1,
22865       "[simplification-%d] new iteration interval %d",
22866       lgl->stats->simp.count, lgl->limits->simp.itinc);
22867   }
22868   lgl->limits->simp.its = lgl->stats->its.count + lgl->limits->simp.itinc;
22869 
22870   if (forced == 2 &&
22871       lgl->limits->simp.binc < lgl->opts->simpbintinclim.val) {
22872     if (lgl->limits->simp.binc < INT_MAX/10) lgl->limits->simp.binc *= 10;
22873     else lgl->limits->simp.binc = INT_MAX;
22874     if (lgl->limits->simp.binc > lgl->opts->simpbintinclim.val)
22875       lgl->limits->simp.binc = lgl->opts->simpbintinclim.val;
22876     lglprt (lgl, 1,
22877       "[simplification-%d] new binary interval %d",
22878       lgl->stats->simp.count, lgl->limits->simp.binc);
22879   }
22880   lgl->limits->simp.bin = lgl->stats->bins + lgl->limits->simp.binc;
22881 
22882   if (forced == 3 &&
22883       lgl->limits->simp.tinc < lgl->opts->simptintinclim.val) {
22884     if (lgl->limits->simp.tinc < INT_MAX/10) lgl->limits->simp.tinc *= 10;
22885     else lgl->limits->simp.tinc = INT_MAX;
22886     if (lgl->limits->simp.tinc > lgl->opts->simptintinclim.val)
22887       lgl->limits->simp.tinc = lgl->opts->simptintinclim.val;
22888     lglprt (lgl, 1,
22889       "[simplification-%d] new ternary interval %d",
22890       lgl->stats->simp.count, lgl->limits->simp.tinc);
22891   }
22892   lgl->limits->simp.trn = lgl->stats->trns + lgl->limits->simp.tinc;
22893 
22894   lgl->limits->simp.vars = lglrem (lgl);
22895   lgl->repforcehead = 1;
22896   if (lgl->wait > 0) lgl->wait--;
22897 
22898 #ifndef NLGLFILES
22899   {
22900     static FILE * simpsfile = 0;
22901     if (!simpsfile) simpsfile = fopen ("/tmp/simps", "w");
22902     fprintf (simpsfile, "%lld\n", (LGLL) lgl->stats->confs);
22903     fflush (simpsfile);
22904   }
22905 #endif
22906 }
22907 
lglpreprocessing(LGL * lgl,int forced)22908 static int lglpreprocessing (LGL * lgl, int forced) {
22909   int res, oldrem, oldirr;
22910   if (lgl->mt) return 0;
22911   assert (!lgl->searching);
22912   lgl->stats->simp.count++;
22913   oldrem = lglrem (lgl);
22914   oldirr = lgl->stats->irr.clauses.cur;
22915   res = lglisimp (lgl);
22916   lglupdsimpint (lgl, oldrem, oldirr, forced);
22917   assert (res == !lgl->mt);
22918   return res;
22919 }
22920 
lglsimplimhit(LGL * lgl,int * forcedptr)22921 static int lglsimplimhit (LGL * lgl, int * forcedptr) {
22922   int64_t n, o, d;
22923   int a, r, res = 0;;
22924   if (!lgl->opts->inprocessing.val && lgl->stats->simp.count) return 0;
22925   if (lgl->stats->confs < lgl->limits->simp.hard) {
22926     if (lgl->opts->simpitintdecdelay.val &&
22927         lgl->stats->its.avg.diff.smoothed.val < 0) return 0;
22928     if (lgl->opts->simpjleveldecdelay.val &&
22929         lgl->stats->jlevel.diff.smoothed.val < 0) return 0;
22930   }
22931   if (lgl->stats->confs >= lgl->limits->simp.confs) {
22932     lglprt (lgl, 1, "");
22933     lglprt (lgl, 1,
22934       "[simplification-%d] "
22935       "limit %lld conflicts (hard %lld) hit after %lld conflicts",
22936       lgl->stats->simp.count + 1,
22937       (LGLL) lgl->limits->simp.confs, (LGLL) lgl->limits->simp.hard,
22938       (LGLL) lgl->stats->confs);
22939     lgl->stats->simp.limhit.confs++;
22940     *forcedptr = 0;
22941     res = 1;
22942   }
22943   if (!res && lgl->stats->trns >= lgl->limits->simp.trn) {
22944     lglprt (lgl, 1, "");
22945     lglprt (lgl, 1,
22946       "[simplification-%d] limit of %lld ternary hit after %lld ternaries",
22947       lgl->stats->simp.count + 1,
22948       (LGLL) lgl->limits->simp.trn, (LGLL) lgl->stats->trns);
22949     lgl->stats->simp.limhit.trn++;
22950     *forcedptr = 3;
22951     res = 1;
22952   }
22953   if (!res && lgl->stats->bins >= lgl->limits->simp.bin) {
22954     lglprt (lgl, 1, "");
22955     lglprt (lgl, 1,
22956       "[simplification-%d] limit of %lld binary hit after %lld binaries",
22957       lgl->stats->simp.count + 1,
22958       (LGLL) lgl->limits->simp.bin, (LGLL) lgl->stats->bins);
22959     lgl->stats->simp.limhit.bin++;
22960     *forcedptr = 2;
22961     res = 1;
22962   }
22963   if (!res && lgl->stats->its.count >= lgl->limits->simp.its) {
22964     lglprt (lgl, 1, "");
22965     lglprt (lgl, 1,
22966       "[simplification-%d] limit of %lld iterations hit after %d iterations",
22967       lgl->stats->simp.count + 1,
22968       (LGLL) lgl->limits->simp.its, lgl->stats->its.count);
22969     lgl->stats->simp.limhit.its++;
22970     *forcedptr = 1;
22971     res = 1;
22972   }
22973   if (!res &&
22974       (o = lgl->limits->simp.vars) &&
22975       (n = lglrem (lgl)) >= lgl->opts->simpvarlim.val) {
22976     d = n - o;
22977     r = 100*d;
22978     r /= o;
22979     if (r <= INT_MIN || r > INT_MAX) a = INT_MAX;
22980     else if (r < 0) a = -r;
22981     else a = r;
22982     if (a >= lgl->opts->simpvarchg.val) {
22983       lglprt (lgl, 1, "");
22984       lglprt (lgl, 1,
22985 	"[simplification-%d] limit hit: "
22986 	"remaining variables changed from %lld to %lld by %d%%",
22987 	lgl->stats->simp.count + 1, (LGLL) o, (LGLL) n, r);
22988       lgl->stats->simp.limhit.vars++;
22989       *forcedptr = -1;
22990       res = 1;
22991     }
22992   }
22993   return res;
22994 }
22995 
lglinprocessing(LGL * lgl)22996 static int lglinprocessing (LGL * lgl) {
22997   int res, oldrem, oldirr, forced;
22998   assert (lgl->searching);
22999   if (!lglsimplimhit (lgl, &forced)) return !lgl->mt;
23000   lgl->stats->simp.count++;
23001   lglstart (lgl, &lgl->times->inprocessing);
23002   oldrem = lglrem (lgl);
23003   oldirr = lgl->stats->irr.clauses.cur;
23004   res = lglisimp (lgl);
23005   lglupdsimpint (lgl, oldrem, oldirr, forced);
23006   lglstop (lgl);
23007   assert (res == !lgl->mt);
23008   return res;
23009 }
23010 
lglbcptop(LGL * lgl)23011 static int lglbcptop (LGL * lgl) {
23012   int res;
23013   if (lglbcp (lgl)) res = 1;
23014   else {
23015 #ifndef NDEBUG
23016     int tmp =
23017 #endif
23018     lglana (lgl);
23019     assert (!tmp);
23020     if (lgl->conf.lit) {
23021       LOG (1, "top level propagation produces inconsistency");
23022       lglmt (lgl);
23023     } else assert (lgl->failed);
23024     res = 0;
23025   }
23026   return res;
23027 }
23028 
lglimhit(LGL * lgl,Lim * lim)23029 static int lglimhit (LGL * lgl, Lim * lim) {
23030   if (!lim) return 0;
23031   if (lim->decs >= 0 && lgl->stats->decisions >= lim->decs) {
23032     lglprt (lgl, 1, "[limits] decision limit %lld hit at %lld decisions",
23033       (LGLL) lim->decs, (LGLL) lgl->stats->decisions);
23034     return 1;
23035   }
23036   if (lim->confs >= 0 && lgl->stats->confs >= lim->confs) {
23037     lglprt (lgl, 1, "[limits] conflict limit %lld hit at %lld conflicts",
23038       (LGLL) lim->confs, (LGLL) lgl->stats->confs);
23039     return 1;
23040   }
23041   if (lim->props >= 0 && lgl->stats->props.search >= lim->props) {
23042     lglprt (lgl, 1,
23043       "[limits] propagation limit %lld hit at %lld propagations",
23044       (LGLL) lim->props, (LGLL) lgl->stats->props.search);
23045     return 1;
23046   }
23047   return 0;
23048 }
23049 
lgloop(LGL * lgl,Lim * lim)23050 static int lgloop (LGL * lgl, Lim * lim) {
23051   unsigned confs = 0;
23052   for (;;) {
23053     if (lglbcpsearch (lgl) && lglinprocessing (lgl)) {
23054       if (lglterminate (lgl)) return 0;
23055       if (!lglsyncunits (lgl)) return 20;
23056       if (!lglsyncls (lgl)) continue;
23057       if (lglfailedass (lgl)) return 20;
23058       if (lglreducing (lgl)) lglreduce (lgl, 0);
23059       if (lgldefragmenting (lgl)) lgldefrag (lgl);
23060       if (lglimhit (lgl, lim)) return 0;
23061       if (lglocsing (lgl)) lglocs (lgl);
23062       if (lglrestarting (lgl)) { lglrestart (lgl); continue; }
23063       if (!lgldecide (lgl)) return 10;
23064     } else if (!lglana (lgl)) return 20;
23065     else if (!(++confs & 15) && lglterminate (lgl)) return 0;
23066   }
23067 }
23068 
lglsearch(LGL * lgl,Lim * lim)23069 static int lglsearch (LGL * lgl, Lim * lim) {
23070   int res;
23071   assert (!lgl->searching);
23072   lgl->searching = 1;
23073   lglstart (lgl, &lgl->times->search);
23074   res = lgloop (lgl, lim);
23075   assert (lgl->searching);
23076   lgl->searching = 0;
23077   lglstop (lgl);
23078   return res;
23079 }
23080 
lgltopsimp(LGL * lgl,int forcesimp)23081 static int lgltopsimp (LGL * lgl, int forcesimp) {
23082   assert (lgl->state == READY);
23083   if (lgl->mt) return 20;
23084   if (lglfailedass (lgl)) return 20;
23085   if (!lglbcptop (lgl)) return 20;
23086   if (lgl->mt || lglfailedass (lgl)) return 20;
23087   if (lglterminate (lgl)) return 0;
23088   lglshowfeatures (lgl);
23089   if ((forcesimp || lglsimplimhit (lgl, &forcesimp)) &&
23090       !lglpreprocessing (lgl, forcesimp)) return 20;
23091   if (lglfailedass (lgl)) return 20;
23092   lglrep (lgl, 2, 's');
23093   return 0;
23094 }
23095 
lglsolve(LGL * lgl,Lim * lim,int forcesimp)23096 static int lglsolve (LGL * lgl, Lim * lim, int forcesimp) {
23097   int res;
23098   lglstart (lgl, &lgl->times->preprocessing);
23099   res = lgltopsimp (lgl, forcesimp);
23100   lglstop (lgl);
23101   if (res) { assert (res == 20); return res; }
23102   return lglsearch (lgl, lim);
23103 }
23104 
lglincsetup(LGL * lgl)23105 static void lglincsetup (LGL * lgl) {
23106 
23107   if (lgl->opts->incsavevisits.val)
23108     lgl->limits->inc.visits = lgl->stats->visits.search;
23109 
23110   assert (lgl->limits->inc.clauses.add <= lgl->stats->irr.clauses.add);
23111   if (lgl->limits->inc.clauses.add < lgl->stats->irr.clauses.add) {
23112     lgl->limits->inc.clauses.add = lgl->stats->irr.clauses.add;
23113     lgl->elmrtc = lgl->blkrtc = lgl->ccertc = 0;
23114     lgl->wait = lgl->opts->waitmax.val;
23115   }
23116 
23117   lgl->limits->inc.clauses.start = lgl->stats->irr.clauses.cur;
23118   lgl->limits->inc.vars.start = lglrem (lgl);
23119 
23120   lglinitredl (lgl);
23121 
23122   lgl->stats->locs.min = INT_MAX;
23123   lglupdlocslim (lgl, 0);
23124 
23125   CLR (lgl->limits->restart);
23126   lgl->limits->restart.confs = lgl->stats->confs;
23127 
23128   if (lgl->opts->incredcint.val > 1) {
23129     lgl->limits->simp.cinc /= lgl->opts->incredcint.val;
23130     lglprt (lgl, 1,
23131        "[incremental-setup] conflict interval increment reduced to %d",
23132        lgl->limits->simp.cinc);
23133   }
23134   if (lgl->opts->incredconfslim.val) {
23135     lgl->limits->simp.confs =
23136       ((100-lgl->opts->incredconfslim.val)*lgl->limits->simp.confs)/100;
23137     lglsethardsimplim (lgl);
23138     lglprt (lgl, 1,
23139        "[incremental-setup] conflict limit reduced to %lld (hard %lld)",
23140        (LGLL) lgl->limits->simp.confs, (LGLL) lgl->limits->simp.hard);
23141   }
23142 
23143   if (!lgl->limits->simp.itinc)
23144     lgl->limits->simp.itinc = lgl->opts->simpitintinc.val;
23145   lgl->limits->simp.its =
23146     lgl->stats->its.count + lgl->opts->simpitintinc.val;
23147 
23148   if (!lgl->limits->simp.binc)
23149     lgl->limits->simp.binc = lgl->opts->simpbintinc.val;
23150   lgl->limits->simp.bin = lgl->stats->bins + lgl->opts->simpbintinc.val;
23151 
23152   if (!lgl->limits->simp.tinc)
23153     lgl->limits->simp.tinc = lgl->opts->simptintinc.val;
23154   lgl->limits->simp.trn = lgl->stats->trns + lgl->opts->simptintinc.val;
23155 
23156   lglinitmacd (lgl, &lgl->stats->jlevel,
23157     lgl->opts->jlevelmacdfast.val,
23158     lgl->opts->jlevelmacdslow.val,
23159     lgl->opts->jlevelmacdsmooth.val);
23160 
23161   lglinitema (lgl, &lgl->stats->tlevel, lgl->opts->tlevelema.val);
23162 
23163   lglinitmacd (lgl, &lgl->stats->glue,
23164     lgl->opts->gluemacdfast.val,
23165     lgl->opts->gluemacdslow.val,
23166     lgl->opts->gluemacdsmooth.val);
23167 
23168   lglinitavg (&lgl->stats->avglue);
23169 
23170   lglinitmacd (lgl, &lgl->stats->its.avg,
23171     lgl->opts->itsmacdfast.val,
23172     lgl->opts->itsmacdslow.val,
23173     lgl->opts->itsmacdsmooth.val);
23174 
23175   lglinitema (lgl, &lgl->stats->stability.avg, lgl->opts->stabema.val);
23176 
23177   CLR (lgl->limits->elm.del);
23178   CLR (lgl->limits->blk.del);
23179 
23180   CLR (lgl->limits->trd.del);
23181   CLR (lgl->limits->unhd.del);
23182   CLR (lgl->limits->ternres.del);
23183   CLR (lgl->limits->cce.del);
23184   CLR (lgl->limits->card.del);
23185 
23186   CLR (lgl->limits->gauss.del);
23187 
23188   CLR (lgl->limits->prb.simple.del);
23189   CLR (lgl->limits->prb.basic.del);
23190   CLR (lgl->limits->prb.treelook.del);
23191 
23192   CLR (lgl->limits->bca.del);
23193 }
23194 
lglsetup(LGL * lgl)23195 static void lglsetup (LGL * lgl) {
23196   if (lgl->setuponce) goto DONE;
23197   lgl->limits->dfg = lgl->stats->pshwchs + lgl->opts->defragint.val;
23198 
23199   lgl->limits->blk.irrprgss = -1;
23200   lgl->limits->elm.irrprgss = -1;
23201   lgl->limits->term.steps = -1;
23202 
23203   lgl->rng.w = (unsigned) lgl->opts->seed.val;
23204   lgl->rng.z = ~lgl->rng.w;
23205   lgl->rng.w <<= 1;
23206   lgl->rng.z <<= 1;
23207   lgl->rng.w += 1;
23208   lgl->rng.z += 1;
23209   lgl->rng.w *= 2019164533u, lgl->rng.z *= 1000632769u;
23210 
23211   assert (!lgl->stats->decisions);
23212   lgl->limits->randec += lgl->opts->randecint.val/2;
23213   lgl->limits->randec += lglrand (lgl) % lgl->opts->randecint.val;
23214 
23215   lgl->limits->simp.vars = lglrem (lgl);
23216 
23217   lgl->setuponce = 1;
23218   lglchkenv (lgl);
23219 DONE:
23220   lglinitscores (lgl);
23221   lglincsetup (lgl);
23222   TRANS (READY);
23223 }
23224 
lglinitsolve(LGL * lgl)23225 static void lglinitsolve (LGL * lgl) {
23226   if (lgl->state != READY) lglsetup (lgl);
23227   lglredvars (lgl);
23228   lglfitstk (lgl, &lgl->irr);
23229 #ifndef NCHKSOL
23230   lglfitstk (lgl, &lgl->orig);
23231 #endif
23232   lglrep (lgl, 1, '*');
23233 }
23234 
lgleassign(LGL * lgl,int lit)23235 static void lgleassign (LGL * lgl, int lit) {
23236   Ext * ext;
23237   ext = lglelit2ext (lgl, lit);
23238   LOG (3, "external assign %d ", lit);
23239   ext->val = lglsgn (lit);
23240 }
23241 
lglcomputechanged(LGL * lgl)23242 static void lglcomputechanged (LGL * lgl) {
23243   Ext * ext;
23244   int eidx;
23245   lgl->changed = 0;
23246   for (eidx = 1; eidx <= lgl->maxext; eidx++) {
23247     ext = lglelit2ext (lgl, eidx);
23248     if (ext->oldval && ext->oldval != ext->val) lgl->changed++;
23249     ext->oldval = ext->val;
23250   }
23251   LOG (1, "changed %d assignments in extension", lgl->changed);
23252 }
23253 
lglextend(LGL * lgl)23254 static void lglextend (LGL * lgl) {
23255   int * p, lit, eidx, ilit, next, satisfied, val, * start, erepr, equiv;
23256   Ext * ext, * extrepr;
23257   assert (lgl->state & SATISFIED);
23258   assert (!(lgl->state & EXTENDED));
23259   lgleunassignall (lgl);
23260   for (equiv = 0; equiv <= 1; equiv++) {
23261     if (equiv)
23262       LOG (1, "initializing assignment of non-representative externals");
23263     else
23264       LOG (1, "initializing assignment of external representatives");
23265     for (eidx = 1; eidx <= lgl->maxext; eidx++) {
23266       ext = lglelit2ext (lgl, eidx);
23267       if (!ext->imported) continue;
23268       if (equiv != ext->equiv) continue;
23269       assert (!ext->val);
23270       if (ext->equiv) {
23271 	erepr = lglerepr (lgl, eidx);
23272 LOG (3, "initializing external %d assignment from external representative %d",
23273 	 eidx, erepr);
23274 	assert (erepr != eidx);
23275 	extrepr = lglelit2ext (lgl, erepr);
23276 	if (!(val = extrepr->val)) {
23277 	  ilit = extrepr->repr;
23278 	  if (ilit) {
23279 	    LOG (3, "using external %d to internal %d mapping",
23280 		 abs (erepr), ilit);
23281 	    val = lglcval (lgl, ilit);
23282 	  } else
23283 LOG (3, "external %d without internal representative", abs (erepr));
23284 	}
23285 	if (erepr < 0) val = -val;
23286       } else
23287       if ((ilit = ext->repr)) {
23288 	LOG (3, "using external %d to internal %d mapping", eidx, ilit);
23289 	val = lglcval (lgl, ilit);
23290       } else {
23291 	LOG (3, "external %d without internal representative", eidx);
23292 	val = 0;
23293       }
23294       lit = (val > 0) ? eidx : -eidx;
23295       lgleassign (lgl, lit);
23296     }
23297   }
23298   start = lgl->extend.start;
23299   p = lgl->extend.top;
23300   if (p == start) goto SKIP;
23301   assert (p > start);
23302   p--;
23303   assert (!*p);
23304   while (p > start) {
23305 #ifndef NLGLOG
23306     if (lgl->opts->log.val >= 4) {
23307       int * q;
23308       for (q = p; q > start && q[-1]; q--)
23309 	;
23310       LOGCLS (4, q, "next sigma clause to consider");
23311     }
23312 #endif
23313     satisfied = 0;
23314     next = 0;
23315     do {
23316       lit = next;
23317       if (p == start) next = 0; else next = *--p;
23318       if (!lit || satisfied) continue;
23319       val = lglederef (lgl, lit);
23320       assert (!next || val);
23321       if (val > 0) {
23322 	LOG (4, "sigma clause satisfied by %d", lit);
23323 	satisfied = 1;
23324       }
23325     } while (next);
23326     assert (lit);
23327     if (satisfied) continue;
23328     lgleassign (lgl, lit);
23329   }
23330 SKIP:
23331   lglcomputechanged (lgl);
23332   TRANS (EXTENDED);
23333 }
23334 
lglsetphases(LGL * lgl)23335 void lglsetphases (LGL * lgl) {
23336   int elit, phase;
23337   REQINITNOTFORKED ();
23338   TRAPI ("setphases");
23339   REQUIRE (SATISFIED | EXTENDED);
23340   if (!(lgl->state & EXTENDED)) lglextend (lgl);
23341   for (elit = 1; elit <= lgl->maxext; elit++) {
23342     phase = lglederef (lgl, elit);
23343     assert (abs (phase) <= 1);
23344     lglesetphase (lgl, elit, phase);
23345   }
23346   if (lgl->clone) lglsetphases (lgl->clone);
23347 }
23348 
23349 #ifndef NCHKSOL
23350 #include <signal.h>
23351 #include <unistd.h>
lglchksol(LGL * lgl)23352 static void lglchksol (LGL * lgl) {
23353   int * p, * c, * eoo = lgl->orig.top, lit, satisfied, sign, idx;
23354   unsigned bit;
23355   Ext * ext;
23356   assert (lglmtstk (&lgl->orig) || !eoo[-1]);
23357   assert (lgl->state == EXTENDED);
23358   for (c = lgl->orig.start; c < eoo; c = p + 1) {
23359     satisfied = 0;
23360     for (p = c; (lit = *p); p++)
23361       if (!satisfied && lglederef (lgl, lit) > 0)
23362 	satisfied = 1;
23363     if (satisfied) continue;
23364     fflush (stderr);
23365     lglmsgstart (lgl, 0);
23366     fprintf (lgl->out, "unsatisfied original external clause");
23367     for (p = c; (lit = *p); p++) fprintf (lgl->out, " %d", lit);
23368     lglmsgend (lgl);
23369     ASSERT (satisfied);
23370     usleep (1000);
23371     abort ();	// NOTE: not 'lglabort' on purpose !!
23372   }
23373   for (idx = 1; idx <= lgl->maxext; idx++) {
23374     ext = lglelit2ext (lgl, idx);
23375     if (!ext->assumed) continue;
23376     for (sign = -1; sign <= 1; sign += 2) {
23377       lit = sign * idx;
23378       bit = 1u << (lit < 0);
23379       if (!(ext->assumed & bit)) continue;
23380       if (lglederef (lgl, lit) > 0) continue;
23381       lglprt (lgl, 0, "unsatisfied assumption %d", lit);
23382       assert (lglederef (lgl, lit) > 0);
23383       usleep (1000);
23384       abort ();	// DITO: not 'lglabort' on purpose !!
23385     }
23386   }
23387 }
23388 #endif
23389 
lglclass(LGL * lgl,LGL * from)23390 static void lglclass (LGL * lgl, LGL * from) {
23391   Ext * extfrom, * extlgl;
23392   int eidx, cloned;
23393   REQINITNOTFORKED ();
23394   ABORTIF (lgl->mt, "can not clone assignment into inconsistent manager");
23395   ABORTIF (!from, "uninitialized 'from' solver");
23396   ABORTIF (!(from->state & (SATISFIED | EXTENDED)),
23397     "require 'from' state to be (SATISFIED | EXTENDED)");
23398   ABORTIF (from->maxext != lgl->maxext,
23399     "can not clone assignments for different sets of variables");
23400   if (!(from->state & EXTENDED)) lglextend (from);
23401   lglreset (lgl);
23402   lgleunassignall (lgl);
23403   cloned = lgl->changed = 0;
23404   for (eidx = 1; eidx <= lgl->maxext; eidx++) {
23405     extlgl = lglelit2ext (lgl, eidx);
23406     if (!extlgl->imported) continue;
23407     extfrom = lglelit2ext (from, eidx);
23408     ABORTIF (!extfrom->imported,
23409       "can not clone assignment of literal imported only by 'to'");
23410     assert (extfrom->val == 1 || extfrom->val == -1);
23411     lgleassign (lgl, extfrom->val*eidx);
23412     cloned++;
23413   }
23414   lglcomputechanged (lgl);
23415   lglprt (lgl, 1, "[class] cloned %d assignments (%d changed)",
23416           cloned, lgl->changed);
23417   TRANS (EXTENDED);
23418 #ifndef NCHKSOL
23419   lglchksol (lgl);
23420 #endif
23421 }
23422 
lglnegass(LGL * lgl)23423 static void lglnegass (LGL * lgl) {
23424   const int  * p;
23425   Stk eassume;
23426   REQINITNOTFORKED ();
23427   TRAPI ("negass");
23428   if (lgl->mt) return;
23429   CLR (eassume);
23430   for (p = lgl->eassume.start; p < lgl->eassume.top; p++)
23431     lglpushstk (lgl, &eassume, *p);
23432   for (p = eassume.start; p < eassume.top; p++)
23433     lgleadd (lgl, -*p);
23434   lgleadd (lgl, 0);
23435   assert (lglmtstk (&lgl->eassume));
23436   for (p = eassume.start; p < eassume.top; p++)
23437     lglassume (lgl, *p);
23438   lglrelstk (lgl, &eassume);
23439   lgluse (lgl);
23440   if (lgl->clone) lglnegass (lgl->clone);
23441 }
23442 
lglcompactify(LGL * lgl,int res)23443 static int lglcompactify (LGL * lgl, int res) {
23444   if (!lgl->opts->compact.val) return 0;
23445   if (!res) return 1;
23446   if (res == 20) return 1;
23447   assert (res == 10);
23448   return lgl->opts->compact.val >= 2;
23449 }
23450 
lglisat(LGL * lgl,Lim * lim,int simpits)23451 static int lglisat (LGL * lgl, Lim * lim, int simpits) {
23452   int res, count, reported = lgl->stats->reported;
23453   lglreset (lgl);
23454   lglinitsolve (lgl);
23455   res = lglsolve (lgl, lim, 0);
23456   for (count = 0; !res && count < simpits; count++) {
23457     lglprt (lgl, 1,
23458       "[simplification-%d] next forced simplification iteration %d",
23459       lgl->stats->simp.count + 1, count + 1);
23460     res = lglsolve (lgl, lim, 1);
23461   }
23462   if (lglcompactify (lgl, res)) lglcompact (lgl);
23463   if (!res) {
23464     TRANS (UNKNOWN);
23465     lglrep (lgl, 1, '?');
23466   }
23467   if (res == 10) {
23468     TRANS (SATISFIED);
23469     lglrep (lgl, 1, '1');
23470   }
23471   if (res == 20) {
23472     TRANS (UNSATISFIED);
23473     if (!lgl->level && !lgl->mt) assert (lgl->failed);
23474     lglrep (lgl, 1, '0');
23475   }
23476   if (reported != lgl->stats->reported) lglflshrep (lgl);
23477   if (res == 10) lglextend (lgl);
23478 #ifndef NCHKSOL
23479   if (res == 10) lglchksol (lgl);
23480 #endif
23481   return res;
23482 }
23483 
lglunclone(LGL * lgl,LGL * from)23484 int lglunclone (LGL * lgl, LGL * from) {
23485   int res;
23486   REQINITNOTFORKED ();
23487   if (lgl->mt) return 20;
23488   ABORTIF (!from, "uninitialized 'from' solver");
23489   if (from->mt || (from->state & UNSATISFIED)) {
23490     lglprt (lgl, 1, "[unclone] unsatisfied state");
23491     lglnegass (lgl);
23492     res = lglisat (lgl, 0, 0);
23493   } else if (from->state & (SATISFIED | EXTENDED)) {
23494     lglprt (lgl, 1, "[unclone] satisfied state");
23495     lglclass (lgl, from);
23496     res = 10;
23497   } else {
23498     lglprt (lgl, 1, "[unclone] unknown state");
23499     lglreset (lgl);
23500     TRANS (UNKNOWN);
23501     res = 0;
23502   }
23503   return res;
23504 }
23505 
23506 #define CHKCLONESTATS(STATS) \
23507 do { \
23508   assert (clone->stats->STATS == orig->stats->STATS); \
23509 } while (0)
23510 
lglchkclonesamestats(LGL * orig)23511 static void lglchkclonesamestats (LGL * orig) {
23512 #ifndef NDEBUG
23513   LGL * clone = orig->clone;
23514   assert (clone);
23515   assert (clone->state == orig->state);
23516   CHKCLONESTATS (confs);
23517   CHKCLONESTATS (decisions);
23518   CHKCLONESTATS (bytes.current);
23519   CHKCLONESTATS (bytes.max);
23520   CHKCLONESTATS (props.search);
23521   CHKCLONESTATS (props.simp);
23522   CHKCLONESTATS (props.lkhd);
23523   CHKCLONESTATS (visits.search);
23524   CHKCLONESTATS (visits.simp);
23525   CHKCLONESTATS (visits.lkhd);
23526 #endif
23527 }
23528 
23529 #define CHKCLONE() \
23530 do { \
23531   if (!lgl->clone) break; \
23532   lglchkclonesamestats (lgl); \
23533 } while (0)
23534 
23535 #define CHKCLONENORES(FUN) \
23536 do { \
23537   if (!lgl->clone) break; \
23538   FUN (lgl->clone); \
23539   CHKCLONE (); \
23540 } while (0)
23541 
23542 #define CHKCLONERES(FUN,RES) \
23543 do { \
23544   int CLONERES; \
23545   if (!lgl->clone) break; \
23546   CLONERES = FUN (lgl->clone); \
23547   ABORTIF (CLONERES != (RES), \
23548            "%s (lgl->clone) = %d differs from %s (lgl) = %d", \
23549 	   __FUNCTION__, CLONERES, __FUNCTION__, (RES)); \
23550   CHKCLONE (); \
23551 } while (0)
23552 
23553 #define RETURN(FUN,RES) \
23554 do { \
23555   TRAPI ("return %d", (RES)); \
23556   CHKCLONERES (FUN, (RES)); \
23557 } while (0)
23558 
23559 #define CHKCLONEARGRES(FUN,ARG,RES) \
23560 do { \
23561   int CLONERES; \
23562   if (!lgl->clone) break; \
23563   CLONERES = FUN (lgl->clone, (ARG)); \
23564   ABORTIF (CLONERES != (RES), \
23565            "%s (lgl->clone, %d) = %d differs from %s (lgl, %d) = %d", \
23566 	   __FUNCTION__, (ARG), CLONERES, __FUNCTION__, (ARG), (RES)); \
23567   CHKCLONE (); \
23568 } while (0)
23569 
23570 #define RETURNARG(FUN,ARG,RES) \
23571 do { \
23572   TRAPI ("return %d", (RES)); \
23573   CHKCLONEARGRES (FUN, (ARG), (RES)); \
23574 } while (0)
23575 
lglsetlim(LGL * lgl,Lim * lim)23576 static void lglsetlim (LGL * lgl, Lim * lim) {
23577   int64_t clim, dlim, plim, confs, decs, props, delay, delayed;
23578   if ((dlim = lgl->opts->dlim.val) < 0) {
23579     lim->decs = -1;
23580     lglprt (lgl, 1, "[limits] no decision limit");
23581   } else {
23582     decs = lgl->stats->decisions;
23583     lim->decs = (decs >= LLMAX - dlim) ? LLMAX : decs + dlim;
23584     lglprt (lgl, 1, "[limits] decision limit %lld after %lld decisions",
23585             (LGLL) lim->decs, (LGLL) decs);
23586   }
23587   if ((clim = lgl->opts->clim.val) < 0) {
23588     lim->confs = -1;
23589     lglprt (lgl, 1, "[limits] no conflict limit");
23590   } else {
23591     confs = lgl->stats->confs;
23592     lim->confs = (confs >= LLMAX - clim) ? LLMAX : confs + clim;
23593     lglprt (lgl, 1, "[limits] conflict limit %lld after %lld conflicts",
23594             (LGLL) lim->confs, (LGLL) confs);
23595   }
23596   if ((plim = lgl->opts->plim.val) < 0) {
23597     lim->props = -1;
23598     lglprt (lgl, 1, "[limits] no propagation limit");
23599   } else {
23600     plim *= 1000;
23601     props = lgl->stats->props.search;
23602     lim->props = (props >= LLMAX - plim) ? LLMAX : props + plim;
23603     lglprt (lgl, 1,
23604       "[limits] propagation limit %lld after %lld propagations",
23605       (LGLL) lim->props, (LGLL) props);
23606   }
23607   if ((delay = lgl->opts->simpinitdelay.val) > 0) {
23608     delayed = lgl->stats->confs + delay;
23609     if (delayed > lgl->limits->simp.confs) {
23610       lgl->limits->simp.confs = delayed;
23611       lglsethardsimplim (lgl);
23612       lglprt (lgl, 1,
23613 	"[limits] simplification delayed by %lld to %lld conflicts (hard %lld)",
23614 	(LGLL) delay, (LGLL) lgl->limits->simp.confs, (LGLL) lgl->limits->simp.hard);
23615     } else lglprt (lgl, 1,
23616              "[limits] simplification conflict limit already exceeds delay");
23617   } else lglprt (lgl, 1,
23618            "[limits] simplification not delayed since 'simpdelay' zero");
23619 }
23620 
lglsat(LGL * lgl)23621 int lglsat (LGL * lgl) {
23622   int res;
23623   Lim lim;
23624   REQINITNOTFORKED ();
23625   TRAPI ("sat");
23626   lglstart (lgl, &lgl->times->all);
23627   lgl->stats->calls.sat++;
23628   ABORTIF (!lglmtstk (&lgl->clause), "clause terminating zero missing");
23629   lglfreezer (lgl);
23630   lglsetlim (lgl, &lim);
23631   res = lglisat (lgl, &lim, 0);
23632   lglstop (lgl);
23633   RETURN (lglsat, res);
23634   return res;
23635 }
23636 
lglookahead(LGL * lgl)23637 int lglookahead (LGL * lgl) {
23638   int ilit, res;
23639   REQINITNOTFORKED ();
23640   TRAPI ("lkhd");
23641   ABORTIF (!lglmtstk (&lgl->eassume), "imcompatible with 'lglassume'");
23642   ABORTIF (!lglmtstk (&lgl->clause), "clause terminating zero missing");
23643   ABORTIF (lgl->opts->druplig.val && lgl->opts->lkhd.val == 2,
23644     "can not use tree based look ahead while Druplig is enabled");
23645   lglstart (lgl, &lgl->times->all);
23646   lglstart (lgl, &lgl->times->lookahead);
23647   lgl->stats->calls.lkhd++;
23648   lglreset (lgl);
23649   assert (!lgl->lkhd);
23650   lgl->lkhd = 1;
23651   lglfreezer (lgl);
23652   if (lgl->level) lglbacktrack (lgl, 0);
23653   if (!lgl->mt && lglbcp (lgl)) {
23654     ilit = 0;
23655     if (lgl->opts->lkhd.val == 2 && !lglsmallirr (lgl))
23656       ilit = lgljwhlook (lgl);
23657     else switch (lgl->opts->lkhd.val) {
23658       case -1: ilit = lglocslook (lgl); break;
23659       case 0: ilit = lglislook (lgl); break;
23660       case 1: ilit = lgljwhlook (lgl); break;
23661       case 2:
23662 	if (!lgltreelookaux (lgl, &ilit)) assert (lgl->mt);
23663 	break;
23664       case 3:
23665       default:
23666         assert (lgl->opts->lkhd.val == 3);
23667 	ilit = lglsumlenlook (lgl);
23668 	break;
23669     }
23670     res = (!lgl->mt && ilit) ? lglexport (lgl, ilit) : 0;
23671     assert (!res || !lglelit2ext (lgl, res)->melted);
23672   } else lglmt (lgl), res = 0;
23673   assert (lgl->lkhd);
23674   lgl->lkhd = 0;
23675   lglstop (lgl);
23676   lglstop (lgl);
23677   TRANS (LOOKED);
23678   RETURN (lglookahead, res);
23679   return res;
23680 }
23681 
lglchanged(LGL * lgl)23682 int lglchanged (LGL * lgl) {
23683   int res;
23684   REQINITNOTFORKED ();
23685   TRAPI ("changed");
23686   REQUIRE (EXTENDED);
23687   res = lgl->changed;
23688   RETURN (lglchanged, res);
23689   return res;
23690 }
23691 
lglsimp(LGL * lgl,int iterations)23692 int lglsimp (LGL * lgl, int iterations) {
23693   Lim lim;
23694   int res;
23695   REQINITNOTFORKED ();
23696   TRAPI ("simp %d", iterations);
23697   ABORTIF (iterations < 0, "negative number of simplification iterations");
23698   ABORTIF (!lglmtstk (&lgl->clause), "clause terminating zero missing");
23699   lglstart (lgl, &lgl->times->all);
23700   lgl->stats->calls.simp++;
23701   lglfreezer (lgl);
23702   CLR (lim);
23703   lim.decs = lgl->stats->decisions;
23704   res = lglisat (lgl, &lim, iterations);
23705   assert (!lgl->level);
23706   lglstop (lgl);
23707   RETURNARG (lglsimp, iterations, res);
23708   return res;
23709 }
23710 
lglmaxvar(LGL * lgl)23711 int lglmaxvar (LGL * lgl) {
23712   int res;
23713   REQINITNOTFORKED ();
23714   TRAPI ("maxvar");
23715   res = lgl->maxext;
23716   RETURN (lglmaxvar, res);
23717   return res;
23718 }
23719 
lglincvar(LGL * lgl)23720 int lglincvar (LGL  *lgl) {
23721   int res;
23722   REQINITNOTFORKED ();
23723   TRAPI ("incvar");
23724   res = lgl->maxext + 1;
23725   (void) lglimport (lgl, res);
23726   RETURN (lglincvar, res);
23727   return res;
23728 }
23729 
lglderef(LGL * lgl,int elit)23730 int lglderef (LGL * lgl, int elit) {
23731   int res;
23732   REQINIT ();
23733   TRAPI ("deref %d", elit);
23734   lgl->stats->calls.deref++;
23735   ABORTIF (!elit, "can not deref zero literal");
23736   REQUIRE (SATISFIED | EXTENDED);
23737   if (!(lgl->state & EXTENDED)) lglextend (lgl);
23738   res = lglederef (lgl, elit);
23739   RETURNARG (lglderef, elit, res);
23740   return res;
23741 }
23742 
lglfailed(LGL * lgl,int elit)23743 int lglfailed (LGL * lgl, int elit) {
23744   unsigned bit;
23745   Ext * ext;
23746   int res;
23747   REQINITNOTFORKED ();
23748   TRAPI ("failed %d", elit);
23749   lgl->stats->calls.failed++;
23750   ABORTIF (!elit, "can not check zero failed literal");
23751   REQUIRE (UNSATISFIED | FAILED);
23752   ABORTIF (abs (elit) > lgl->maxext,
23753 	   "can not check unimported failed literal");
23754   ext = lglelit2ext (lgl, elit);
23755   bit = 1u << (elit < 0);
23756   ABORTIF (!(ext->assumed & bit),
23757 	   "can not check unassumed failed literal");
23758   if (!(lgl->state & FAILED)) {
23759     lglstart (lgl, &lgl->times->all);
23760     lglanafailed (lgl);
23761     lglstop (lgl);
23762   }
23763   res = (ext->failed & bit) != 0;
23764   RETURNARG (lglfailed, elit, res);
23765   return res;
23766 }
23767 
lglinconsistent(LGL * lgl)23768 int lglinconsistent (LGL * lgl) {
23769   int res;
23770   TRAPI ("inconsistent");
23771   res = (lgl->mt != 0);
23772   RETURN (lglinconsistent, res);
23773   return res;
23774 }
23775 
lglefixed(LGL * lgl,int elit)23776 static int lglefixed (LGL * lgl, int elit) {
23777   int res, ilit;
23778   assert (elit);
23779   if (abs (elit) > lgl->maxext) return 0;
23780   ilit = lglimport (lgl, elit);
23781   if (!ilit) res = 0;
23782   else if (abs (ilit) == 1) res = ilit;
23783   else res = lglifixed (lgl , ilit);
23784   return res;
23785 }
23786 
lglfixed(LGL * lgl,int elit)23787 int lglfixed (LGL * lgl, int elit) {
23788   int res;
23789   REQINITNOTFORKED ();
23790   TRAPI ("fixed %d", elit);
23791   lgl->stats->calls.fixed++;
23792   ABORTIF (!elit, "can not deref zero literal");
23793   res = lglefixed (lgl, elit);
23794   RETURNARG (lglfixed, elit, res);
23795   return res;
23796 }
23797 
lglrepr(LGL * lgl,int elit)23798 int lglrepr (LGL * lgl, int elit) {
23799   int res, eidx = abs (elit);
23800   REQINITNOTFORKED ();
23801   TRAPI ("repr %d", elit);
23802   lgl->stats->calls.repr++;
23803   if (eidx > lgl->maxext) res = elit;
23804   else {
23805     res = lglerepr (lgl, elit);
23806     if (abs (res) <= 1) res = elit;
23807   }
23808   RETURNARG (lglrepr, elit, res);
23809   return res;
23810 }
23811 
lglfreeze(LGL * lgl,int elit)23812 void lglfreeze (LGL * lgl, int elit) {
23813   Ext * ext;
23814   REQINITNOTFORKED ();
23815   TRAPI ("freeze %d", elit);
23816   lgl->stats->calls.freeze++;
23817   ABORTIF (!elit, "can not freeze zero literal");
23818   REQUIRE (UNUSED|OPTSET|USED|RESET|SATISFIED|UNSATISFIED|FAILED|LOOKED|
23819 	   UNKNOWN|EXTENDED);
23820   LOG (2, "freezing external literal %d", elit);
23821   (void) lglimport (lgl, elit);
23822   ext = lglelit2ext (lgl, elit);
23823   ABORTIF (ext->melted, "freezing melted literal %d", elit);
23824   assert (!ext->blocking && !ext->eliminated);
23825   ABORTIF (ext->frozen == INT_MAX, "literal %d frozen too often", elit);
23826   ext->frozen++;
23827   if (!ext->frozen) {
23828     lgl->stats->irrprgss++;
23829     lglmelter (lgl);
23830   }
23831   if (lgl->clone) lglfreeze (lgl->clone, elit);
23832 }
23833 
lglfrozen(LGL * lgl,int elit)23834 int lglfrozen (LGL * lgl, int elit) {
23835   Ext * ext;
23836   int res;
23837   REQINITNOTFORKED ();
23838   TRAPI ("frozen %d", elit);
23839   ABORTIF (!elit, "can not check zero literal for being frozen");
23840   if (abs (elit) > lgl->maxext) res = INT_MAX;
23841   else if (!(ext = lglelit2ext (lgl, elit))->imported) res = INT_MAX;
23842   else res = ext->frozen;
23843   RETURNARG (lglfrozen, elit, res);
23844   return res;
23845 }
23846 
lglusable(LGL * lgl,int elit)23847 int lglusable (LGL * lgl, int elit) {
23848   Ext * ext;
23849   int res;
23850   REQINITNOTFORKED ();
23851   TRAPI ("usable %d", elit);
23852   ABORTIF (!elit, "can not check zero literal for being usable");
23853   if (abs (elit) > lgl->maxext) res = 1;
23854   else if (!(ext = lglelit2ext (lgl, elit))->imported) res = 1;
23855   else res = !ext->melted;
23856   RETURNARG (lglusable, elit, res);
23857   return res;
23858 }
23859 
lglereusable(LGL * lgl,int elit)23860 static int lglereusable (LGL * lgl, int elit) {
23861   Ext * ext;
23862   int res;
23863   if (abs (elit) > lgl->maxext) res = 1;
23864   else if (!(ext = lglelit2ext (lgl, elit))->imported) res = 1;
23865   else if (ext->blocking) res = 0;
23866   else if (ext->eliminated) res = 0;
23867   else if (ext->equiv) res = 0;
23868   else if (abs (ext->repr) == 1) res = 0;
23869   else res = 1;
23870   return res;
23871 }
23872 
lglreusable(LGL * lgl,int elit)23873 int lglreusable (LGL * lgl, int elit) {
23874   int res;
23875   REQINITNOTFORKED ();
23876   TRAPI ("reusable %d", elit);
23877   ABORTIF (!elit, "can not check zero literal for being reusable");
23878   res = lglereusable (lgl, elit);
23879   RETURNARG (lglreusable, elit, res);
23880   return res;
23881 }
23882 
lglreuse(LGL * lgl,int elit)23883 void lglreuse (LGL * lgl, int elit) {
23884   Ext * ext;
23885   REQINITNOTFORKED ();
23886   TRAPI ("reuse %d", elit);
23887   ABORTIF (!elit, "can not reuse zero literal");
23888   ABORTIF (!lglereusable (lgl, elit), "can not reuse non-reusable literal");
23889   if (abs (elit) <= lgl->maxext) {
23890     ext = lglelit2ext (lgl, elit);
23891     if (ext->imported) {
23892       assert (!ext->blocking);
23893       assert (!ext->eliminated);
23894       if (ext->melted) {
23895 	LOG (2,
23896 	  "forced permanently melted external %d to be reused",
23897 	  elit);
23898 	ext->melted = 0;
23899 	lglmelter (lgl);
23900       }
23901     }
23902   }
23903   if (lgl->clone) lglreuse (lgl->clone, elit);
23904 }
23905 
lglmeltall(LGL * lgl)23906 void lglmeltall (LGL * lgl) {
23907   int idx, melted;
23908   Ext * ext;
23909   REQINITNOTFORKED ();
23910   TRAPI ("meltall");
23911   melted = 0;
23912   for (idx = 1; idx <= lgl->maxext; idx++) {
23913     ext = lglelit2ext (lgl, idx);
23914     ext->melted = 0;
23915     if (!ext->frozen) continue;
23916     lgl->stats->irrprgss++;
23917     ext->frozen = 0;
23918     melted++;
23919   }
23920   lglprt (lgl, 1, "[meltall] melted %d frozen literals", melted);
23921   lglmelter (lgl);
23922   if (lgl->clone) lglmeltall (lgl->clone);
23923 }
23924 
lglmelt(LGL * lgl,int elit)23925 void lglmelt (LGL * lgl, int elit) {
23926   Ext * ext;
23927   REQINITNOTFORKED ();
23928   TRAPI ("melt %d", elit);
23929   lgl->stats->calls.melt++;
23930   ABORTIF (!elit, "can not melt zero literal");
23931   REQUIRE (UNUSED|OPTSET|USED|RESET|
23932 	   SATISFIED|UNSATISFIED|FAILED|UNKNOWN|LOOKED|
23933 	   EXTENDED);
23934   LOG (2, "melting external literal %d", elit);
23935   (void) lglimport (lgl, elit);
23936   ext = lglelit2ext (lgl, elit);
23937   ABORTIF (!ext->frozen, "can not melt fully unfrozen literal %d", elit);
23938   assert (!ext->blocking && !ext->eliminated);
23939   ext->frozen--;
23940   lglmelter (lgl);	// TODO guard  by !ext->frozen?
23941   if (lgl->clone) lglmelt (lgl->clone, elit);
23942 }
23943 
lglreconstk(LGL * lgl,int ** startptr,int ** toptr)23944 void lglreconstk (LGL * lgl, int ** startptr, int ** toptr) {
23945   REQINITNOTFORKED ();
23946   TRAPI ("reconstk");
23947   lglfitstk (lgl, &lgl->extend);	// 'lglcompact' -> 'lglclone'!!
23948   if (startptr) *startptr = lgl->extend.start;
23949   if (toptr) *toptr = lgl->extend.top;
23950   if (lgl->clone) lglreconstk (lgl->clone, 0, 0);
23951 }
23952 
lglprstart(LGL * lgl)23953 static void lglprstart (LGL * lgl) {
23954   assert (lgl->prefix);
23955   fputs (lgl->prefix, lgl->out);
23956   if (lgl->tid >= 0) fprintf (lgl->out, "%d ", lgl->tid);
23957 }
23958 
lglprs(LGL * lgl,const char * fmt,...)23959 static void lglprs (LGL * lgl, const char * fmt, ...) {
23960   va_list ap;
23961   lglprstart (lgl);
23962   va_start (ap, fmt);
23963   vfprintf (lgl->out, fmt, ap);
23964   va_end (ap);
23965   fputc ('\n', lgl->out);
23966 }
23967 
lglprsline(LGL * lgl)23968 static void lglprsline (LGL * lgl) {
23969   lglprstart (lgl);
23970   fputc ('\n', lgl->out);
23971 }
23972 
lglsqr(double a)23973 static double lglsqr (double a) { return a*a; }
23974 
lglgluestats(LGL * lgl)23975 static void lglgluestats (LGL * lgl) {
23976   int64_t added, reduced, retired, forcing, resolved, conflicts;
23977   int64_t wadded, wreduced, wretired, wforcing, wresolved, wconflicts;
23978   int64_t avgadded, avgreduced, avgretired, avgforcing, avgresolved, avgconflicts;
23979   double madded, mreduced, mretired, mforcing, mresolved, mconflicts;
23980   double vadded, vreduced, vretired, vforcing, vresolved, vconflicts;
23981   double sadded, sreduced, sretired, sforcing, sresolved, sconflicts;
23982   Stats * s = lgl->stats;
23983   int glue, maxglue;
23984   lglprs (lgl,
23985     "scaled glue%11s %3s %9s %3s %9s %3s %9s %3s %9s %3s %9s %7s",
23986     "added","", "reduced","", "retired","",
23987     "forcing","", "resolved","", "conflicts", "maxmb");
23988   added = reduced = retired = forcing = resolved = conflicts = 0;
23989   wadded = wreduced = wretired = wforcing = wresolved = wconflicts = 0;
23990   for (glue = 0; glue <= MAXGLUE; glue++) {
23991     added += s->lir[glue].added;
23992     reduced += s->lir[glue].reduced;
23993     retired += s->lir[glue].retired;
23994     forcing += s->lir[glue].forcing;
23995     resolved += s->lir[glue].resolved;
23996     conflicts += s->lir[glue].conflicts;
23997     wadded += glue*s->lir[glue].added;
23998     wreduced += glue*s->lir[glue].reduced;
23999     wretired += glue*s->lir[glue].retired;
24000     wforcing += glue*s->lir[glue].forcing;
24001     wresolved += glue*s->lir[glue].resolved;
24002     wconflicts += glue*s->lir[glue].conflicts;
24003   }
24004   avgadded = added ? (((10*wadded)/added+5)/10) : 0;
24005   avgreduced = reduced ? (((10*wreduced)/reduced+5)/10) : 0;
24006   avgretired = retired ? (((10*wretired)/retired+5)/10) : 0;
24007   avgforcing = forcing ? (((10*wforcing)/forcing+5)/10) : 0;
24008   avgresolved = resolved ? (((10*wresolved)/resolved+5)/10) : 0;
24009   avgconflicts = conflicts ? (((10*wconflicts)/conflicts+5)/10) : 0;
24010   lglprsline (lgl);
24011   lglprs (lgl,
24012     "all %14lld %13lld %13lld %13lld %13lld %13lld",
24013      (LGLL) added,
24014      (LGLL) reduced,
24015      (LGLL) retired,
24016      (LGLL) forcing,
24017      (LGLL) resolved,
24018      (LGLL) conflicts);
24019   lglprsline (lgl);
24020   if (lgl->opts->verbose.val < 2) {
24021     for (maxglue = MAXGLUE; maxglue >= 1; maxglue--)
24022       if (s->lir[maxglue].added) break;
24023     if (maxglue + 1 == MAXGLUE) maxglue = MAXGLUE;
24024   } else maxglue = MAXGLUE;
24025   for (glue = 0; glue <= maxglue; glue++) {
24026     lglprs (lgl,
24027       "%2d %-5d %9lld %3.0f%c%9lld %3.0f%c%9lld %3.0f%c%9lld %3.0f%c%9lld %3.0f%c%9lld %3.0f%c %6.1f",
24028       glue,
24029       lglunscaleglue (lgl, glue),
24030       (LGLL) s->lir[glue].added,
24031 	lglpcnt (s->lir[glue].added, added),
24032 	(glue == avgadded) ? '<' : ' ',
24033       (LGLL) s->lir[glue].reduced,
24034 	lglpcnt (s->lir[glue].reduced, reduced),
24035 	(glue == avgreduced) ? '<' : ' ',
24036       (LGLL) s->lir[glue].retired,
24037 	lglpcnt (s->lir[glue].retired, retired),
24038 	(glue == avgretired) ? '<' : ' ',
24039       (LGLL) s->lir[glue].forcing,
24040 	lglpcnt (s->lir[glue].forcing, forcing),
24041 	(glue == avgforcing) ? '<' : ' ',
24042       (LGLL) s->lir[glue].resolved,
24043 	lglpcnt (s->lir[glue].resolved, resolved),
24044 	(glue == avgresolved) ? '<' : ' ',
24045       (LGLL) s->lir[glue].conflicts,
24046 	lglpcnt (s->lir[glue].conflicts, conflicts),
24047 	(glue == avgconflicts) ? '<' : ' ',
24048 	s->lir[glue].maxbytes/(double)(1<<20));
24049   }
24050   lglprsline (lgl);
24051 
24052   madded = lglavg (wadded, added),
24053   mreduced = lglavg (wreduced, reduced),
24054   mretired = lglavg (wretired, retired),
24055   mforcing = lglavg (wforcing, forcing),
24056   mresolved = lglavg (wresolved, resolved),
24057   mconflicts = lglavg (wconflicts, conflicts);
24058 
24059   lglprs (lgl,
24060     "avg  %19.1f%14.1f%14.1f%14.1f%14.1f%14.1f",
24061      madded, mreduced, mretired, mforcing, mresolved, mconflicts);
24062 
24063   vadded = vreduced = vretired = vforcing = vresolved = vconflicts = 0;
24064   for (glue = 0; glue <= MAXGLUE; glue++) {
24065     vadded += s->lir[glue].added * lglsqr (glue - madded);
24066     vreduced += s->lir[glue].reduced * lglsqr (glue - mreduced);
24067     vretired += s->lir[glue].retired * lglsqr (glue - mretired);
24068     vforcing += s->lir[glue].forcing * lglsqr (glue - mforcing);
24069     vresolved += s->lir[glue].resolved * lglsqr (glue - mresolved);
24070     vconflicts += s->lir[glue].conflicts * lglsqr (glue - mconflicts);
24071   }
24072   sadded = sqrt (lglavg (vadded, added));
24073   sreduced = sqrt (lglavg (vreduced, reduced));
24074   sretired = sqrt (lglavg (vretired, retired));
24075   sforcing = sqrt (lglavg (vforcing, forcing));
24076   sresolved = sqrt (lglavg (vresolved, resolved));
24077   sconflicts = sqrt (lglavg (vconflicts, conflicts));
24078 
24079   lglprs (lgl,
24080     "std  %19.1f%14.1f%14.1f%14.1f%14.1f%14.1f",
24081      sadded, sreduced, sretired, sforcing, sresolved, sconflicts);
24082 }
24083 
24084 typedef struct TN { double t; const char * n; } TN;
24085 
lglcmptn(const TN * a,const TN * b)24086 static int lglcmptn (const TN * a, const TN * b) {
24087   if (a->t > b->t) return -1;
24088   if (a->t < b->t) return 1;
24089   return strcmp (a->n, b->n);
24090 }
24091 
24092 #define INSTN(NAME,FIELD) \
24093 do { \
24094   TN * tn; \
24095   if (lglignprofptr (lgl, &ts->FIELD)) break; \
24096   tn = tns + ntns++; \
24097   ASSERT (ntns <= sztns); \
24098   tn->t = ts->FIELD; \
24099   tn->n = #NAME; \
24100 } while (0)
24101 
lglprofsort(LGL * lgl)24102 static void lglprofsort (LGL * lgl) {
24103   int i, ntns, nimportant, nprint;
24104   Times * ts = lgl->times;
24105   const int sztns = 100;
24106   TN tns[sztns];
24107   double sum;
24108 
24109   ntns = 0;
24110 
24111   INSTN (analysis, analysis);
24112   INSTN (backward, backward);
24113   INSTN (bca, bca);
24114   INSTN (block, block);
24115   INSTN (bump, bump);
24116   INSTN (card, card);
24117   INSTN (cce, cce);
24118   INSTN (decide, decide);
24119   INSTN (decompose, decompose);
24120   INSTN (defrag, defrag);
24121   INSTN (druplig, druplig);
24122   INSTN (elim, elim);
24123   INSTN (gauss, gauss);
24124   INSTN (gc, gc);
24125   INSTN (heapdecision, heapdecision);
24126   INSTN (locs, locs);
24127   INSTN (mincls, mincls);
24128   INSTN (phase, phase);
24129   INSTN (probe, probe);
24130   INSTN (quatres1, quatres1);
24131   INSTN (quatres2, quatres2);
24132   INSTN (quatres, quatres);
24133   INSTN (queuedecision, queuedecision);
24134   INSTN (queuesort, queuesort);
24135   INSTN (redcls, redcls);
24136   INSTN (reduce, reduce);
24137   INSTN (restart, restart);
24138   INSTN (showfeatures, showfeatures);
24139   INSTN (showscoredist, showscoredist);
24140   INSTN (subl, subl);
24141   INSTN (sweep, sweep);
24142   INSTN (ternres, ternres);
24143   INSTN (transred, transred);
24144   INSTN (unhide, unhide);
24145 
24146   // Force insertion sort to avoid implicit memory allocation!
24147   // Otherwise an already existing memory corruption will trigger
24148   // another signal and thus might result in non-termination.
24149 
24150   ISORT (TN, lglcmptn, tns, ntns);
24151 
24152   sum = 0;
24153   assert (ntns > 3);
24154   for (nimportant = ntns-1; nimportant > 3; nimportant--) {
24155     sum += tns[nimportant].t;
24156     if (lglpcnt (sum, ts->all) >= 1.0) break;
24157   }
24158   if (nimportant == ntns - 1) nimportant++;
24159 
24160   if (!lgl->opts->profilelong.val && lgl->opts->verbose.val < 2)
24161     nprint = nimportant;
24162   else nprint = ntns;
24163 
24164   for (i = 0; i < nprint; i++) {
24165     if (i == nimportant) {
24166       if (i) lglprs (lgl, "");
24167       lglprs (lgl, "%8.3f < 1%% rest (below)", sum);
24168       if (i + 1 < nprint) lglprs (lgl, "");
24169     }
24170     lglprs (lgl, "%8.3f %3.0f%% %s",
24171       tns[i].t, lglpcnt (tns[i].t, ts->all), tns[i].n);
24172   }
24173 
24174   if (nimportant == nprint && nprint < ntns) {
24175     if (nprint) lglprs (lgl, "");
24176     lglprs (lgl, "%8.3f < 1%% rest (not shown)", sum);
24177   }
24178 }
24179 
lglprof(LGL * lgl)24180 static void lglprof (LGL * lgl) {
24181   Times * ts = lgl->times;
24182   double t = ts->all, simp, search;
24183 
24184   assert (lgl->opts->verbose.val >= 0);
24185   simp = ts->preprocessing + ts->inprocessing;
24186   if (!lgl->opts->verbose.val || !lgl->opts->profile.val) goto SHORT;
24187 
24188   lglprofsort (lgl);
24189 
24190   if (!lglignprofptr (lgl, &ts->prb.simple) &&
24191       (lgl->opts->profilelong.val ||
24192        lgl->opts->verbose.val >= 2 ||
24193        ts->prb.simple || ts->prb.basic || ts->prb.treelook)) {
24194     lglprs (lgl, "----------------------------------");
24195     lglprs (lgl, "%8.3f %3.0f%% probe simple    %3.0f%%",
24196       ts->prb.simple,
24197       lglpcnt (ts->prb.simple, t),
24198       lglpcnt (ts->prb.simple, ts->probe));
24199     lglprs (lgl, "%8.3f %3.0f%% probe basic     %3.0f%%",
24200       ts->prb.basic,
24201       lglpcnt (ts->prb.basic, t),
24202       lglpcnt (ts->prb.basic, ts->probe));
24203     lglprs (lgl, "%8.3f %3.0f%% probe tree-look %3.0f%%",
24204       ts->prb.treelook,
24205       lglpcnt (ts->prb.treelook, t),
24206       lglpcnt (ts->prb.treelook, ts->probe));
24207   }
24208   lglprs (lgl, "==================================");
24209   lglprs (lgl, "%8.3f %3.0f%% preprocessing   %3.0f%%",
24210     ts->preprocessing,
24211     lglpcnt (ts->preprocessing, t),
24212     lglpcnt (ts->preprocessing, simp));
24213   lglprs (lgl, "%8.3f %3.0f%% inprocessing    %3.0f%%",
24214     ts->inprocessing,
24215     lglpcnt (ts->inprocessing, t),
24216     lglpcnt (ts->inprocessing, simp));
24217   lglprs (lgl, "==================================");
24218 SHORT:
24219   lglprs (lgl, "%8.3f %3.0f%% simplifying", simp, lglpcnt (simp, t));
24220   if (lgl->stats->calls.lkhd)
24221     lglprs (lgl, "%8.3f %3.0f%% lookahead",
24222       ts->lookahead, lglpcnt (ts->lookahead, t));
24223   search = ts->search - ts->inprocessing;
24224   lglprs (lgl, "%8.3f %3.0f%% search", search, lglpcnt (search, t));
24225   lglprs (lgl, "==================================");
24226   lglprs (lgl, "%8.3f %3.0f%% all", t, 100.0);
24227 }
24228 
lglstats(LGL * lgl)24229 void lglstats (LGL * lgl) {
24230   long long visits, min, p, steps, sum;
24231   int remaining, removed;
24232   Stats * s;
24233   double t;
24234   REQINITNOTFORKED ();
24235   if (lgl->opts->verbose.val < 0) return;
24236   lglflushtimers (lgl);
24237   s = lgl->stats;
24238   t = lgl->times->all;
24239   p = s->props.search + s->props.simp + s->props.lkhd;
24240   if (!lgl->opts->verbose.val) goto SHORT;
24241 
24242   lglprs (lgl, "agil: %.2f%% agility",
24243     100.0 * (s->agility / (double) (1ll << 32)));
24244 
24245   sum = s->prb.basic.ate.trnr + s->prb.basic.ate.lrg;
24246   lglprs (lgl,
24247     "bate: %lld basic ate = %d trn %.0f%% + %d lrg %.0f%% in %d updates",
24248     sum, s->prb.basic.ate.trnr, lglpcnt (s->prb.basic.ate.trnr, sum),
24249     s->prb.basic.ate.lrg, lglpcnt (s->prb.basic.ate.lrg, sum),
24250     s->prb.basic.ate.count);
24251 
24252   lglprs (lgl,
24253     "bcas: %d count, %lld added (%lld skipped), %lld steps",
24254     s->bca.count, (LGLL) s->bca.added, s->bca.skipped, (LGLL) s->bca.steps);
24255 
24256   lglprs (lgl,
24257     "bkwd: tried %lld clauses, %lld lits, %.2f lits/clause",
24258     (LGLL) s->bkwd.tried.clauses, (LGLL) s->bkwd.tried.lits,
24259     lglavg (s->bkwd.tried.lits, s->bkwd.tried.clauses));
24260   lglprs (lgl,
24261     "bkwd: checked %lld occs, %.2f occs/clause, %.2f occs/lit",
24262     (LGLL) s->bkwd.tried.occs,
24263     lglavg (s->bkwd.tried.occs, s->bkwd.tried.clauses),
24264     lglavg (s->bkwd.tried.occs, s->bkwd.tried.lits));
24265   lglprs (lgl,
24266     "bkwd: subsumed %d binary, %d ternary, %d large",
24267     s->bkwd.sub2, s->bkwd.sub3, s->bkwd.subl);
24268   lglprs (lgl,
24269     "bkwd: strengthened %d binary, "
24270     "%d ternary (%.0f%% self), %d large (%.0f%% self)",
24271     s->bkwd.str2,
24272     s->bkwd.str3, lglpcnt (s->bkwd.str3self, s->bkwd.str3),
24273     s->bkwd.strl, lglpcnt (s->bkwd.strlself, s->bkwd.strl));
24274 
24275   lglprs (lgl,
24276     "blkd: %d bces, %d removed, %lld resolutions, %lld steps",
24277     s->blk.count, s->blk.clauses, (LGLL) s->blk.res, (LGLL) s->blk.steps);
24278   lglprs (lgl,
24279     "blkd: %d blocking literals %.0f%%, %d pure",
24280     s->blk.lits, lglpcnt (s->blk.lits, 2*lgl->maxext), s->blk.pure);
24281 
24282   lglprs (lgl,
24283     "bump: %lld bumped seen, %lld lits %.1f on average",
24284     s->bump.count,
24285     (LGLL) s->bump.lits,
24286     lglavg (s->bump.lits, s->bump.count));
24287 
24288   lglprs (lgl,
24289     "card: %d count, %d units, %d am1, %lld steps",
24290     s->card.count, s->card.units, s->card.expam1, (LGLL) s->card.steps);
24291   lglprs (lgl,
24292     "card: %d rescheduled, %lld eliminated, %lld resolved, %lld subsumed",
24293     s->card.resched, (LGLL) s->card.eliminated,
24294     (LGLL) s->card.resolved, (LGLL) s->card.subsumed);
24295   lglprs (lgl,
24296     "card: %d at-most-one constraints found, average size %.2f",
24297     s->card.found.am1.total.cnt,
24298     lglavg (s->card.found.am1.total.sum, s->card.found.am1.total.cnt));
24299   lglprs (lgl,
24300     "card: %d at-most-one constraints used %.0f%%, average size %.2f",
24301     s->card.used.am1.cnt,
24302     lglpcnt (s->card.used.am1.cnt, s->card.found.am1.total.cnt),
24303     lglavg (s->card.used.am1.sum, s->card.used.am1.cnt));
24304   lglprs (lgl,
24305     "card: %d at-most-two constraints found, average size %.2f",
24306     s->card.found.am2.total.cnt,
24307     lglavg (s->card.found.am2.total.sum, s->card.found.am2.total.cnt));
24308   lglprs (lgl,
24309     "card: %d at-most-two constraints used %.0f%%, average size %.2f",
24310     s->card.used.am2.cnt,
24311     lglpcnt (s->card.used.am2.cnt, s->card.found.am2.total.cnt),
24312     lglavg (s->card.used.am2.sum, s->card.used.am2.cnt));
24313 
24314   lglprs (lgl,
24315     "cces: %d cces, %d eliminated, %d ate %.0f%%, %d abce %.0f%%",
24316     s->cce.count, s->cce.eliminated,
24317     s->cce.ate, lglpcnt (s->cce.ate, s->cce.eliminated),
24318     s->cce.abce, lglpcnt (s->cce.abce, s->cce.eliminated));
24319   lglprs (lgl,
24320     "cces: %lld probed, %d lifted, %d failed",
24321     (LGLL) s->cce.probed, s->cce.lifted, s->cce.failed);
24322   lglprs (lgl,
24323     "cces: %lld cached, %lld rsz, %lld cols %.0f%%, "
24324     "%lld srch, %lld hits %.0f%%",
24325     (LGLL) s->cce.cache.ins,
24326     (LGLL) s->cce.cache.rsz,
24327     (LGLL) s->cce.cache.cols,
24328       lglpcnt (s->cce.cache.cols, s->cce.cache.ins),
24329     (LGLL) s->cce.cache.search,
24330     (LGLL) s->cce.cache.hits,
24331       lglpcnt (s->cce.cache.hits, s->cce.cache.search));
24332 
24333   lglprs (lgl,
24334     "clls: %lld sat, %lld simp, %lld freeze, %lld melt",
24335     (LGLL) s->calls.sat, (LGLL) s->calls.simp,
24336     (LGLL) s->calls.freeze, (LGLL) s->calls.melt);
24337   lglprs (lgl,
24338     "clls: %lld add, %lld assume, %lld deref, %lld failed",
24339     (LGLL) s->calls.add, (LGLL) s->calls.assume,
24340     (LGLL) s->calls.deref, (LGLL) s->calls.failed);
24341   lglprs (lgl,
24342     "clls: %lld lkhd, %lld cassume, %lld mosat",
24343     (LGLL) s->calls.lkhd, (LGLL) s->calls.cassume, (LGLL) s->calls.mosat);
24344 
24345   lglprs (lgl,
24346     "coll: %d gcs, %d rescored clauses, %d rescored vars",
24347     s->gcs, s->rescored.clauses, s->rescored.vars);
24348 
24349   lglprs (lgl,
24350     "dcps: %d decompositions, %d equivalent %.0f%%",
24351 	  s->decomps, s->equiv.sum, lglpcnt (s->equiv.sum, lgl->maxext));
24352 
24353   lglprs (lgl,
24354     "deco: %lld decision-only clauses %.0f%%, %.0f%% reduction",
24355     s->mincls.deco, lglpcnt (s->mincls.deco, s->clauses.learned),
24356     lglpcnt (s->deco.sum.orig - s->deco.sum.red, s->deco.sum.orig));
24357 
24358   lglprs (lgl,
24359     "decs: %lld total, %lld rnd %.3f%%, %lld heap %.3f%, %lld queue %.3f%%",
24360     (LGLL) s->decisions,
24361     (LGLL) s->randecs, lglpcnt (s->randecs, s->decisions),
24362     (LGLL) s->hdecs, lglpcnt (s->hdecs, s->decisions),
24363     (LGLL) s->qdecs, lglpcnt (s->qdecs, s->decisions));
24364 
24365   lglprs (lgl,
24366     "elms: %d elims, %d eliminated %.0f%%, %d pure %.0f%%",
24367      s->elm.count,
24368      s->elm.elmd, lglpcnt (s->elm.elmd, lgl->maxext),
24369      s->elm.pure, lglpcnt (s->elm.pure, s->elm.elmd));
24370   lglprs (lgl,
24371     "elms: %d rounds, %.1f rounds/bve",
24372     s->elm.rounds, lglavg (s->elm.rounds, s->elm.count));
24373   lglprs (lgl,
24374     "elms: %d small %.0f%%, %d large %.0f%%",
24375     s->elm.small.elm, lglpcnt (s->elm.small.elm, s->elm.elmd),
24376     s->elm.large, lglpcnt (s->elm.large, s->elm.elmd));
24377   lglprs (lgl,
24378     "elms: %d tried small, %d succeeded %.0f%%, %d failed %.0f%%",
24379     s->elm.small.tried, s->elm.small.tried - s->elm.small.failed,
24380       lglpcnt (s->elm.small.tried - s->elm.small.failed, s->elm.small.tried),
24381     s->elm.small.failed,
24382       lglpcnt (s->elm.small.failed, s->elm.small.tried));
24383   lglprs (lgl,
24384     "elms: %d subsumed, %d strengthened, %d blocked",
24385     s->elm.sub, s->elm.str, s->elm.blkd);
24386   lglprs (lgl,
24387     "elms: %lld copies, %lld resolutions, %lld ipos",
24388     (LGLL) s->elm.copies, (LGLL) s->elm.resolutions, (LGLL) s->elm.ipos);
24389   lglprs (lgl,
24390     "elms: %lld subchks, %lld strchks",
24391     (LGLL) s->elm.subchks, (LGLL) s->elm.strchks);
24392 
24393   lglprs (lgl,
24394     "gaus: %lld extractions, %lld extracted, %.1f size, %d max",
24395     s->gauss.count, s->gauss.extracted,
24396     lglavg (s->gauss.arity.sum, s->gauss.extracted.total),
24397     s->gauss.arity.max);
24398   lglprs (lgl,
24399     "gaus: exported %d units, %d binary and %d ternary equations",
24400     s->gauss.units, s->gauss.equivs, s->gauss.trneqs);
24401   steps = s->gauss.steps.extr + s->gauss.steps.extr;
24402   lglprs (lgl,
24403     "gaus: %d gc, %lld steps, %lld extr %.0f%%, %lld elim %.0f%%",
24404     s->gauss.gcs, (LGLL) steps,
24405     s->gauss.steps.extr, lglpcnt (s->gauss.steps.extr, steps),
24406     s->gauss.steps.elim, lglpcnt (s->gauss.steps.elim, steps));
24407 
24408   lglprs (lgl,
24409     "glue: %.1f orig avg, %.1f real avg, %.1f scaled avg",
24410     lglavg (s->clauses.glue, s->clauses.learned),
24411     lglavg (s->clauses.realglue, s->clauses.learned),
24412     lglavg (s->clauses.scglue, s->clauses.learned));
24413   lglprs (lgl,
24414     "glue: %lld maxscaledglue=%d (%.0f%%), %lld kept %.0f%%",
24415     (LGLL) s->clauses.maxglue.count, MAXGLUE,
24416     lglpcnt (s->clauses.maxglue.count, s->clauses.learned),
24417     (LGLL) s->clauses.maxglue.kept,
24418     lglpcnt (s->clauses.maxglue.kept, s->clauses.learned));
24419 
24420   lglprs (lgl,
24421     "hbrs: %d = %d simple %.0f%% + %d trn %.0f%% + %d lrg %.0f%%, %d sub %.0f%%",
24422     s->hbr.cnt,
24423     s->hbr.simple, lglpcnt (s->hbr.simple, s->hbr.cnt),
24424     s->hbr.trn, lglpcnt (s->hbr.trn, s->hbr.cnt),
24425     s->hbr.lrg, lglpcnt (s->hbr.lrg, s->hbr.cnt),
24426     s->hbr.sub, lglpcnt (s->hbr.sub, s->hbr.cnt));
24427 
24428   lglprs (lgl,
24429     "locs: %d count, %lld flips, %lld mems, %d minimun",
24430     s->locs.count, (LGLL) s->locs.flips, (LGLL) s->locs.mems, s->locs.min);
24431 
24432   assert (s->lits.nonmin >= s->lits.learned);
24433   min = s->lits.nonmin - s->lits.learned;
24434   lglprs (lgl,
24435     "lrnd: %lld clauses, %.1f length",
24436     (LGLL) s->clauses.learned,
24437     lglavg (s->lits.learned, s->clauses.learned));
24438   lglprs (lgl,
24439     "lrnd: %lld lits = %lld orig - %lld removed %.0f%%",
24440     (LGLL) s->lits.learned,
24441     (LGLL) s->lits.nonmin,
24442     (LGLL) min, lglpcnt (min, s->lits.nonmin));
24443   lglprs (lgl,
24444     "lrnd: %lld uips %.0f%%, %lld flips %.0f%%",
24445     (LGLL) s->uips, lglpcnt (s->uips, s->clauses.learned),
24446     (LGLL) s->decflipped, lglpcnt (s->decflipped, s->clauses.learned));
24447 
24448   sum = s->mincls.min + s->mincls.bin + s->mincls.size + s->mincls.deco;
24449   lglprs (lgl,
24450     "mins: %lld mins %.0f%%, %lld bin %.0f%%, %lld size %.0f%%",
24451     (LGLL) s->mincls.min, lglpcnt (s->mincls.min, sum),
24452     (LGLL) s->mincls.bin, lglpcnt (s->mincls.bin, sum),
24453     (LGLL) s->mincls.size, lglpcnt (s->mincls.size, sum),
24454     (LGLL) s->mincls.deco, lglpcnt (s->mincls.deco, sum));
24455   lglprs (lgl,
24456     "mins: %lld poisoned searches, %lld hits, %.0f%% hit rate",
24457     (LGLL) s->mincls.poison.search, (LGLL) s->mincls.poison.hits,
24458     lglpcnt (s->mincls.poison.hits, s->mincls.poison.search));
24459   lglprs (lgl,
24460     "mins: %lld used twice searches, %lld hits, %.0f%% hit rate",
24461     (LGLL) s->mincls.usedtwice.search, (LGLL) s->mincls.usedtwice.hits,
24462     lglpcnt (s->mincls.usedtwice.hits, s->mincls.usedtwice.search));
24463 
24464   sum = s->moved.bin + s->moved.trn;
24465   lglprs (lgl,
24466     "move: moved %lld, %lld bin %.0f%%, %lld trn %.0f%%",
24467     sum,
24468     (LGLL) s->moved.bin, lglpcnt (s->moved.bin, sum),
24469     (LGLL) s->moved.trn, lglpcnt (s->moved.trn, sum));
24470 
24471   sum = s->otfs.str.red + s->otfs.str.irr;
24472   assert (sum == s->otfs.str.bin + s->otfs.str.trn + s->otfs.str.lrg);
24473   lglprs (lgl,
24474     "otfs: %lld driving %.0f%%, %lld restarting %.0f%%",
24475     (LGLL) s->otfs.driving, lglpcnt (s->otfs.driving, sum),
24476     (LGLL) s->otfs.restarting, lglpcnt (s->otfs.restarting, sum));
24477   lglprs (lgl,
24478     "otfs: str %lld, %lld red %.0f%%, %lld irr %.0f%%",
24479     sum,
24480     (LGLL) s->otfs.str.red, lglpcnt (s->otfs.str.red, sum),
24481     (LGLL) s->otfs.str.irr, lglpcnt (s->otfs.str.irr, sum));
24482   lglprs (lgl,
24483     "otfs: str %lld, %lld bin %.0f%%, %lld trn %.0f%%, %lld lrg %.0f%%",
24484     sum,
24485     (LGLL) s->otfs.str.bin, lglpcnt (s->otfs.str.bin, sum),
24486     (LGLL) s->otfs.str.trn, lglpcnt (s->otfs.str.trn, sum),
24487     (LGLL) s->otfs.str.lrg, lglpcnt (s->otfs.str.lrg, sum));
24488 
24489   sum = s->otfs.sub.red + s->otfs.sub.irr;
24490   assert (sum == s->otfs.total);
24491   assert (sum == s->otfs.sub.bin + s->otfs.sub.trn + s->otfs.sub.lrg);
24492   lglprs (lgl,
24493     "otfs: sub %lld, %lld red %.0f%%, %lld irr %.0f%%",
24494     sum,
24495     (LGLL) s->otfs.sub.red, lglpcnt (s->otfs.sub.red, sum),
24496     (LGLL) s->otfs.sub.irr, lglpcnt (s->otfs.sub.irr, sum));
24497   lglprs (lgl,
24498     "otfs: sub %lld, %lld bin %.0f%%, %lld trn %.0f%%, %lld lrg %.0f%%",
24499     sum,
24500     (LGLL) s->otfs.sub.bin, lglpcnt (s->otfs.sub.bin, sum),
24501     (LGLL) s->otfs.sub.trn, lglpcnt (s->otfs.sub.trn, sum),
24502     (LGLL) s->otfs.sub.lrg, lglpcnt (s->otfs.sub.lrg, sum));
24503 
24504   lglprs (lgl,
24505     "phas: %lld computed, %lld set, %lld pos (%.0f%%), %lld neg (%.0f%%)",
24506     (LGLL) s->phase.count, (LGLL) s->phase.set,
24507     (LGLL) s->phase.pos, lglpcnt (s->phase.pos, s->phase.set),
24508     (LGLL) s->phase.neg, lglpcnt (s->phase.neg, s->phase.set));
24509 
24510   lglprs (lgl,
24511     "prbs: %d basic, %lld probed, %d failed, %d lifted",
24512     s->prb.basic.count, (LGLL) s->prb.basic.probed,
24513     s->prb.basic.failed, s->prb.basic.lifted);
24514   lglprs (lgl,
24515     "prbs: %d simple, %lld probed, %d failed, %d eqs",
24516     s->prb.simple.count, (LGLL) s->prb.simple.probed,
24517     s->prb.simple.failed, s->prb.simple.eqs);
24518   lglprs (lgl,
24519     "prbs: %d treelook, %lld probed, %d failed, %d lifted",
24520     s->prb.treelook.count, (LGLL) s->prb.treelook.probed,
24521     s->prb.treelook.failed, s->prb.treelook.lifted);
24522 
24523   lglprs (lgl,
24524     "prom: %lld locked %.0f%% out of %lld tried",
24525     (LGLL) s->promote.locked,
24526     lglpcnt (s->promote.locked, s->promote.tried),
24527     (LGLL) s->promote.tried);
24528 
24529   lglprs (lgl,
24530     "prps: %lld props, %.0f props/dec",
24531     (LGLL) p, lglavg (s->props.search, s->decisions));
24532   lglprs (lgl,
24533     "prps: %.0f%% srch, %.0f%% simp, %.0f%% lkhd",
24534     lglpcnt (s->props.search, p), lglpcnt (s->props.simp, p),
24535     lglpcnt (s->props.lkhd, p));
24536 
24537   lglprs (lgl,
24538     "quat: %d count, %lld quat, %lld self1, %lld self2, %lld dup",
24539     s->quatres.count,
24540     (LGLL) s->quatres.quat,
24541     (LGLL) s->quatres.self1,
24542     (LGLL) s->quatres.self2,
24543     (LGLL) s->quatres.dup);
24544 
24545   lglprs (lgl,
24546     "queu: %lld flushed, %lld sorted, %lld decisions %.3f%%",
24547     (LGLL) s->queue.flushed, (LGLL) s->queue.sorted,
24548     (LGLL) s->qdecs, lglpcnt (s->qdecs, s->decisions));
24549 
24550   lglprs (lgl,
24551     "redc: %lld clauses %.0f%%, %lld tried %.0f%%, %lld sat %.0f%%",
24552     (LGLL) s->redcls.cls.red,
24553       lglpcnt (s->redcls.cls.red, s->redcls.cls.tried),
24554     (LGLL) s->redcls.cls.tried,
24555       lglpcnt (s->redcls.cls.tried, s->confs),
24556     (LGLL) s->redcls.cls.sat,
24557       lglpcnt (s->redcls.cls.sat, s->redcls.cls.tried));
24558   lglprs (lgl,
24559     "redc: %lld lits %.0f%%, %lld tried %.0f%%, %lld sat %.0f%%",
24560     (LGLL) s->redcls.lits.red,
24561       lglpcnt (s->redcls.lits.red, s->redcls.lits.tried),
24562     (LGLL) s->redcls.lits.tried,
24563       lglpcnt (s->redcls.lits.tried, s->lits.nonmin),
24564     (LGLL) s->redcls.lits.sat,
24565       lglpcnt (s->redcls.lits.sat, s->redcls.lits.tried));
24566   lglprs (lgl,
24567     "redc: %lld times jump level reduced, %.1f levels on average",
24568     (LGLL) s->redcls.jlevel.red,
24569     lglavg (s->redcls.jlevel.sum, s->redcls.jlevel.red));
24570 
24571   lglprs (lgl,
24572     "reds: %d count, %.1f conflicts per reduce",
24573     s->reduced.count, lglavg (s->confs, s->reduced.count));
24574   lglprs (lgl,
24575     "reds: %d memlim %.0f%%, %d arith %.0f%%",
24576     s->reduced.memlim, lglpcnt (s->reduced.memlim, s->reduced.count),
24577     s->reduced.arith, lglpcnt (s->reduced.arith, s->reduced.count));
24578   sum = s->reduced.collected + s->reduced.retired;
24579   lglprs (lgl,
24580     "reds: %lld collected %.0f%%, %lld retired %.0f%%",
24581     s->reduced.collected, lglpcnt (s->reduced.collected, sum),
24582     s->reduced.retired, lglpcnt (s->reduced.retired, sum));
24583 
24584   lglprs (lgl,
24585     "rmbd: %d removed, %d red %.0f%%",
24586     s->bindup.removed, s->bindup.red,
24587     lglpcnt (s->bindup.red, s->bindup.removed));
24588 
24589   lglprs (lgl,
24590     "rsts: %lld restarts %.0f%% of checked, %lld skipped %.0f%%",
24591     (LGLL) s->restarts.count,
24592       lglpcnt (s->restarts.count, s->restarts.checked),
24593     (LGLL) s->restarts.skipped,
24594       lglpcnt (s->restarts.skipped, s->restarts.checked));
24595   lglprs (lgl,
24596     "rsts: %lld checks %.0f%%, %lld forced %.0f%%",
24597     (LGLL) s->restarts.checked,
24598       lglpcnt (s->restarts.checked, s->confs),
24599     (LGLL) s->restarts.forced,
24600       lglpcnt (s->restarts.forced, s->restarts.checked));
24601   lglprs (lgl,
24602     "rsts: %lld not forced (%.0f%% of checked, %.0f%% of skipped)",
24603     (LGLL) s->restarts.notforced,
24604       lglpcnt (s->restarts.notforced, s->restarts.checked),
24605       lglpcnt (s->restarts.notforced, s->restarts.skipped));
24606   lglprs (lgl,
24607     "rsts: %lld agile %.0f%% of skipped, %lld delayed %.0f%%",
24608     (LGLL) s->restarts.agile,
24609       lglpcnt (s->restarts.agile, s->restarts.skipped),
24610     (LGLL) s->restarts.delayed,
24611       lglpcnt (s->restarts.delayed, s->restarts.skipped));
24612   lglprs (lgl,
24613     "rsts: %lld blocked %.2f%% restart, %lld reused %.0f%%",
24614     (LGLL) s->restarts.blocked,
24615       lglpcnt (s->restarts.blocked, s->restarts.count),
24616     (LGLL) s->restarts.reused,
24617       lglpcnt (s->restarts.reused, s->restarts.skipped));
24618   lglprs (lgl,
24619     "rsts: %lld partial reuse %.1f%% of restarts, kept %.1f%%",
24620     (LGLL) s->restarts.kept.count,
24621     lglpcnt (s->restarts.kept.count, s->restarts.count),
24622     lglavg (s->restarts.kept.sum, s->restarts.kept.count));
24623   lglprs (lgl,
24624     "rsts: %lld delta %.1f avg, %lld penalty %.1f avg",
24625     (LGLL) s->restarts.delta.delta,
24626       lglavg (s->restarts.delta.delta, s->restarts.delta.count),
24627     (LGLL) s->restarts.delta.pen,
24628       lglavg (s->restarts.delta.pen, s->restarts.delta.count));
24629 
24630   lglprs (lgl,
24631     "scic: %lld set, %.1f%% min, %.1f%% max",
24632     (LGLL) s->setscincf.count,
24633     s->setscincf.min/10.0, s->setscincf.max/10.0);
24634 
24635   lglprs (lgl,
24636     "simp: %d count, %d confs %0.f%%, %d vars %.0f%%",
24637     s->simp.count,
24638     s->simp.limhit.confs, lglpcnt (s->simp.limhit.confs, s->simp.count),
24639     s->simp.limhit.vars, lglpcnt (s->simp.limhit.vars, s->simp.count));
24640   lglprs (lgl,
24641     "simp: %d its %0.f%%, %d bin %.0f%%, %d trns %.0f%%",
24642     s->simp.limhit.its, lglpcnt (s->simp.limhit.its, s->simp.count),
24643     s->simp.limhit.bin, lglpcnt (s->simp.limhit.bin, s->simp.count),
24644     s->simp.limhit.trn, lglpcnt (s->simp.limhit.trn, s->simp.count));
24645 
24646    lglprs (lgl,
24647     "subl: %lld count (%lld tried %.1f), %lld sub out of %lld (%.1f%%)",
24648     s->subl.count, s->subl.tried, lglavg (s->subl.tried, s->subl.count),
24649     s->subl.sub, s->subl.cands, lglpcnt (s->subl.sub, s->subl.cands));
24650 
24651   lglprs (lgl,
24652     "swps: %d count, %lld rounds, %lld queries (%.1f/round)",
24653     s->sweep.count, (LGLL) s->sweep.rounds, (LGLL) s->sweep.queries.total,
24654     lglavg (s->sweep.queries.total, s->sweep.rounds));
24655   lglprs (lgl,
24656     "swps: %lld sat calls, %lld unsat (%.1f%% success rate)",
24657     s->sweep.sat,
24658     s->sweep.unsat, lglavg (s->sweep.confs, s->sweep.sat));
24659   lglprs (lgl,
24660     "swps: %lld decisions %.1f, %lld conflicts %.1f",
24661     (LGLL) s->sweep.decs, lglavg (s->sweep.decs, s->sweep.sat),
24662     (LGLL) s->sweep.confs, lglavg (s->sweep.confs, s->sweep.sat));
24663   lglprs (lgl,
24664     "swps; %.1f avg class size, %.1f avg environment size",
24665     lglavg (s->sweep.sumsize.classes, s->sweep.queries.total),
24666     lglavg (s->sweep.sumsize.envs, s->sweep.sat));
24667   lglprs (lgl,
24668     "swps: %d failed, %d impls, %d equivs",
24669     s->sweep.failed, s->sweep.impls, s->sweep.equivs);
24670 
24671   lglprs (lgl,
24672     "swp0: %lld type 0 queries, %lld unsat (%.1f%%), %lld sat (%.1f%%)",
24673     (LGLL) s->sweep.queries.type[0].count,
24674     (LGLL) s->sweep.queries.type[0].unsat,
24675     lglpcnt (s->sweep.queries.type[0].unsat, s->sweep.queries.type[0].count),
24676     (LGLL) s->sweep.queries.type[0].sat,
24677     lglpcnt (s->sweep.queries.type[0].sat, s->sweep.queries.type[0].count));
24678   lglprs (lgl,
24679     "swp1: %lld type 1 queries, %lld unsat (%.1f%%), %lld sat (%.1f%%)",
24680     (LGLL) s->sweep.queries.type[1].count,
24681     (LGLL) s->sweep.queries.type[1].unsat,
24682     lglpcnt (s->sweep.queries.type[1].unsat, s->sweep.queries.type[1].count),
24683     (LGLL) s->sweep.queries.type[1].sat,
24684     lglpcnt (s->sweep.queries.type[1].sat, s->sweep.queries.type[1].count));
24685   lglprs (lgl,
24686     "swp2: %lld type 2 queries, %lld unsat (%.1f%%), %lld sat (%.1f%%)",
24687     (LGLL) s->sweep.queries.type[2].count,
24688     (LGLL) s->sweep.queries.type[2].unsat,
24689     lglpcnt (s->sweep.queries.type[2].unsat, s->sweep.queries.type[2].count),
24690     (LGLL) s->sweep.queries.type[2].sat,
24691     lglpcnt (s->sweep.queries.type[2].sat, s->sweep.queries.type[2].count));
24692 
24693   lglprs (lgl,
24694     "sync: %lld produced units, %lld successful consumptions %.0f%%",
24695     s->sync.units.produced, s->sync.units.consumed.actual,
24696     lglpcnt (s->sync.units.consumed.actual, s->sync.units.produced));
24697   lglprs (lgl,
24698     "sync: %lld consume units calls, %lld tried %.0f%%, %lld success %.0f%%",
24699     s->sync.units.consumed.calls,
24700     s->sync.units.consumed.tried,
24701     lglpcnt (s->sync.units.consumed.tried, s->sync.units.consumed.calls),
24702     s->sync.units.consumed.actual,
24703     lglpcnt (s->sync.units.consumed.actual, s->sync.units.consumed.calls));
24704   lglprs (lgl,
24705     "sync: %lld produced clauses, %lld successful consumptions %.0f%%",
24706     s->sync.cls.produced, s->sync.cls.consumed.actual,
24707     lglpcnt (s->sync.cls.consumed.actual, s->sync.cls.produced));
24708   lglprs (lgl,
24709     "sync: %lld consume clause calls, %lld tried %.0f%%, %lld success %.0f%%",
24710     s->sync.cls.consumed.calls,
24711     s->sync.cls.consumed.tried,
24712     lglpcnt (s->sync.cls.consumed.tried, s->sync.cls.consumed.calls),
24713     s->sync.cls.consumed.actual,
24714     lglpcnt (s->sync.cls.consumed.actual, s->sync.cls.consumed.calls));
24715 
24716   lglprs (lgl, "time: %lld calls to obtain time", (LGLL) s->times);
24717 
24718   lglprs (lgl,
24719     "tops: %d fixed %.0f%%, %d its, %.2f confs/it",
24720     s->fixed.sum, lglpcnt (s->fixed.sum, lgl->maxext),
24721     s->its.count, lglavg (s->confs, s->its.count));
24722 
24723   lglprs (lgl,
24724     "trds: %d transitive reductions, %d removed, %d failed",
24725     s->trd.count, s->trd.red, s->trd.failed);
24726   lglprs (lgl,
24727     "trds: %lld nodes, %lld edges, %lld steps",
24728     (LGLL) s->trd.lits, (LGLL) s->trd.bins, (LGLL) s->trd.steps);
24729 
24730   lglprs (lgl, "trim: %lld words, %.1f MB",
24731     (LGLL) s->trims, (s->trims * sizeof (int)) / (double)(1<<20));
24732 
24733   lglprs (lgl,
24734     "trnr: %d count, %d bin, %d trn, %lld steps",
24735     s->ternres.count, s->ternres.bin,
24736     s->ternres.trn, (LGLL) s->ternres.steps);
24737 
24738   lglprs (lgl,
24739     "unhd: %d count, %d rounds, %lld steps",
24740     s->unhd.count, s->unhd.rounds, (LGLL) s->unhd.steps);
24741   lglprs (lgl,
24742     "unhd: %d non-trivial sccs of average size %.1f",
24743     s->unhd.stamp.sccs,
24744     lglavg (s->unhd.stamp.sumsccsizes, s->unhd.stamp.sccs));
24745   sum = lglunhdunits (lgl);
24746   lglprs (lgl,
24747     "unhd: %lld units, %d bin, %d trn, %d lrg",
24748     sum, s->unhd.units.bin, s->unhd.units.trn, s->unhd.units.lrg);
24749   sum = lglunhdfailed (lgl);
24750   lglprs (lgl,
24751     "unhd: %lld failed, %d stamp, %d lits, %d bin, %d trn, %d lrg",
24752     sum, s->unhd.stamp.failed, s->unhd.failed.lits,
24753     s->unhd.failed.bin, s->unhd.failed.trn, s->unhd.units.lrg);
24754   sum = lglunhdtauts (lgl);
24755   lglprs (lgl,
24756     "unhd: %lld tauts, %d bin %.0f%%, %d trn %.0f%%, %d lrg %.0f%%",
24757     sum,
24758     s->unhd.tauts.bin, lglpcnt (s->unhd.tauts.bin, sum),
24759     s->unhd.tauts.trn, lglpcnt (s->unhd.tauts.trn, sum),
24760     s->unhd.tauts.lrg, lglpcnt (s->unhd.tauts.lrg, sum));
24761   lglprs (lgl,
24762     "unhd: %lld tauts, %d stamp %.0f%%, %d red %.0f%%",
24763     sum,
24764     s->unhd.stamp.trds, lglpcnt (s->unhd.stamp.trds, sum),
24765     s->unhd.tauts.red, lglpcnt (s->unhd.tauts.red, sum));
24766   sum = lglunhdhbrs (lgl);
24767   lglprs (lgl,
24768     "unhd: %lld hbrs, %d trn %.0f%%, %d lrg %.0f%%, %d red %.0f%%",
24769     sum,
24770     s->unhd.hbrs.trn, lglpcnt (s->unhd.hbrs.trn, sum),
24771     s->unhd.hbrs.lrg, lglpcnt (s->unhd.hbrs.lrg, sum),
24772     s->unhd.hbrs.red, lglpcnt (s->unhd.hbrs.red, sum));
24773   sum = lglunhdstrd (lgl);
24774   lglprs (lgl,
24775     "unhd: %lld str, %d bin %.0f%%, %d trn %.0f%%, %d lrg %.0f%%, %d red %.0f%%",
24776     sum,
24777     s->unhd.units.bin, lglpcnt (s->unhd.units.bin, sum),
24778     s->unhd.str.trn, lglpcnt (s->unhd.str.trn, sum),
24779     s->unhd.str.lrg, lglpcnt (s->unhd.str.lrg, sum),
24780     s->unhd.str.red, lglpcnt (s->unhd.str.red, sum));
24781 
24782   removed = s->fixed.sum + s->elm.elmd + s->equiv.sum;
24783   remaining = lgl->maxext - removed;
24784   assert (remaining >= 0);
24785   lglprs (lgl,
24786     "vars: %d remaining %.0f%% and %d removed %.0f%% out of %d",
24787     remaining, lglpcnt (remaining, lgl->maxext),
24788     removed, lglpcnt (removed, lgl->maxext), lgl->maxext);
24789   lglprs (lgl,
24790     "vars: %d fixed %.0f%%, %d eliminated %.0f%%, %d equivalent %.0f%%",
24791     s->fixed.sum, lglpcnt (s->fixed.sum, lgl->maxext),
24792     s->elm.elmd, lglpcnt (s->elm.elmd, lgl->maxext),
24793     s->equiv.sum, lglpcnt (s->equiv.sum, lgl->maxext));
24794 
24795   visits = s->visits.search + s->visits.simp + s->visits.lkhd;
24796   lglprs (lgl,
24797     "vsts: %lld visits, %.0f%% srch, %.0f%% simp, %.0f%% lkhd",
24798     (LGLL) visits, lglpcnt (s->visits.search, visits),
24799     lglpcnt (s->visits.simp, visits), lglpcnt (s->visits.lkhd, visits));
24800   lglprs (lgl,
24801     "vsts: %.1f search visits per propagation, %.1f per conflict",
24802     lglavg (s->visits.search, s->props.search),
24803     lglavg (s->visits.search, s->confs));
24804 
24805   lglprs (lgl,
24806     "wchs: %lld pushed, %lld enlarged, %d defrags",
24807     (LGLL) s->pshwchs, (LGLL) s->enlwchs, s->defrags);
24808 
24809   lglprsline (lgl);
24810   lglgluestats (lgl);
24811   lglprsline (lgl);
24812 
24813 #ifndef NLGLDRUPLIG
24814   if (lgl->druplig) {
24815     druplig_stats (lgl->druplig, lgl->out);
24816     lglprsline (lgl);
24817   }
24818 #endif
24819 
24820 SHORT:
24821   lglprof (lgl);
24822   lglprsline (lgl);
24823   lglprs (lgl,
24824     "%13lld conflicts,    %10.1f confs/sec",
24825     (LGLL) s->confs, lglavg (s->confs, t));
24826   lglprs (lgl,
24827     "%13lld ternaries,    %10.1f confs/ternary",
24828     (LGLL) s->trns, lglavg (s->confs, s->trns));
24829   lglprs (lgl,
24830     "%13lld binaries,     %10.1f confs/binary",
24831     (LGLL) s->bins, lglavg (s->confs, s->bins));
24832   lglprs (lgl,
24833     "%13lld iterations,   %10.1f confs/iteration",
24834     (LGLL) s->its.count, lglavg (s->confs, s->its.count));
24835   lglprsline (lgl);
24836   lglprs (lgl,
24837     "%13lld reductions,   %10.1f redus/sec, %8.1f confs/reduction",
24838     (LGLL) s->reduced.count,
24839     lglavg (s->reduced.count, t), lglavg (s->confs, s->reduced.count));
24840   lglprs (lgl,
24841     "%13lld restarts,     %10.1f rests/sec, %8.1f confs/restart",
24842     (LGLL) s->restarts.count,
24843     lglavg (s->restarts.count, t), lglavg (s->confs, s->restarts.count));
24844   lglprs (lgl,
24845     "%13lld decisions,    %10.1f decis/sec, %8.1f decis/conflict",
24846     (LGLL) s->decisions,
24847     lglavg (s->decisions, t), lglavg (s->decisions, s->confs));
24848   lglprs (lgl,
24849     "%13lld propagations, %10.1f props/sec, %8.1f props/decision",
24850     (LGLL) p, lglavg (p, t), lglavg (p, s->decisions));
24851   lglprsline (lgl);
24852   lglprs (lgl, "%.1f seconds, %.1f MB", t, lglmaxmb (lgl));
24853   fflush (lgl->out);
24854 }
24855 
lglgetprops(LGL * lgl)24856 int64_t lglgetprops (LGL * lgl) {
24857   REQINITNOTFORKED ();
24858   return lgl->stats->props.search + lgl->stats->props.simp;
24859 }
24860 
lglgetconfs(LGL * lgl)24861 int64_t lglgetconfs (LGL * lgl) {
24862   REQINITNOTFORKED ();
24863   return lgl->stats->confs;
24864 }
24865 
lglgetdecs(LGL * lgl)24866 int64_t lglgetdecs (LGL * lgl) {
24867   REQINITNOTFORKED ();
24868   return lgl->stats->decisions;
24869 }
24870 
lglsizes(LGL * lgl)24871 void lglsizes (LGL * lgl) {
24872   lglprt (lgl, 0, "sizeof (int) == %ld", (long) sizeof (int));
24873   lglprt (lgl, 0, "sizeof (unsigned) == %ld", (long) sizeof (unsigned));
24874   lglprt (lgl, 0, "sizeof (void*) == %ld", (long) sizeof (void*));
24875   lglprt (lgl, 0, "sizeof (Stk) == %ld", (long) sizeof (Stk));
24876   lglprt (lgl, 0, "sizeof (Fun) == %ld", (long) sizeof (Fun));
24877   lglprt (lgl, 0, "sizeof (AVar) == %ld", (long) sizeof (AVar));
24878   lglprt (lgl, 0, "sizeof (DVar) == %ld", (long) sizeof (DVar));
24879   lglprt (lgl, 0, "sizeof (QVar) == %ld", (long) sizeof (QVar));
24880   lglprt (lgl, 0, "sizeof (EVar) == %ld", (long) sizeof (EVar));
24881   lglprt (lgl, 0, "sizeof (Stats.lir) == %ld", (long) sizeof ((Stats*)0)->lir);
24882   lglprt (lgl, 0, "sizeof (Stats) == %ld", (long) sizeof (Stats));
24883   lglprt (lgl, 0, "sizeof (LGL) == %ld", (long) sizeof (LGL));
24884   lglprt (lgl, 0, "MAXVAR == %ld", (long) MAXVAR);
24885   lglprt (lgl, 0, "MAXREDLIDX == %ld", (long) MAXREDLIDX);
24886   lglprt (lgl, 0, "MAXIRRLIDX == %ld", (long) MAXIRRLIDX);
24887 }
24888 
24889 #define LGLRELSTK(MGR,STKPTR) \
24890 do { \
24891   assert (lglmtstk (STKPTR)); \
24892   lglrelstk ((MGR), (STKPTR)); \
24893 } while (0)
24894 
lglrelease(LGL * lgl)24895 void lglrelease (LGL * lgl) {
24896   lgldealloc dealloc;
24897   int i;
24898 
24899   REQINIT ();
24900   if (lgl->clone) lglrelease (lgl->clone), lgl->clone = 0;
24901   TRAPI ("release");
24902 
24903 #ifndef NLGLDRUPLIG
24904   if (lgl->druplig) druplig_reset (lgl->druplig), lgl->druplig = 0;
24905 #endif
24906 
24907   // Heap state starts here:
24908 
24909   DEL (lgl->avars, lgl->szvars);
24910   DEL (lgl->doms, 2*lgl->szvars);
24911   DEL (lgl->drail, lgl->szdrail);
24912   DEL (lgl->dvars, lgl->szvars);
24913   DEL (lgl->ext, lgl->szext);
24914   DEL (lgl->i2e, lgl->szvars);
24915   DEL (lgl->jwh, 2*lgl->szvars);
24916   DEL (lgl->qvars, lgl->szvars);
24917   DEL (lgl->vals, lgl->szvars);
24918 
24919   lglrelctk (lgl, &lgl->control);
24920 
24921   lglrelstk (lgl, &lgl->assume);
24922 #ifndef NDEBUG
24923   lglrelstk (lgl, &lgl->prevclause);
24924 #endif
24925   lglrelstk (lgl, &lgl->clause);
24926   lglrelstk (lgl, &lgl->dsched);
24927   lglrelstk (lgl, &lgl->queue.stk);
24928   lglrelstk (lgl, &lgl->eassume);
24929   lglrelstk (lgl, &lgl->eclause);
24930   lglrelstk (lgl, &lgl->extend);
24931   lglrelstk (lgl, &lgl->learned);
24932   lglrelstk (lgl, &lgl->frames);
24933   lglrelstk (lgl, &lgl->promote);
24934   lglrelstk (lgl, &lgl->trail);
24935   lglrelstk (lgl, &lgl->wchs->stk);
24936 
24937 #ifndef NCHKSOL
24938   lglrelstk (lgl, &lgl->orig);
24939 #endif
24940 
24941   lglrelstk (lgl, &lgl->irr);
24942   for (i = 0; i <= MAXGLUE; i++) lglrelstk (lgl, &lgl->red[i]);
24943 
24944   // The following heap allocated memory has no state:
24945 
24946   LGLRELSTK (lgl, &lgl->lcaseen);
24947   LGLRELSTK (lgl, &lgl->resolvent);
24948   LGLRELSTK (lgl, &lgl->minstk);
24949   LGLRELSTK (lgl, &lgl->poisoned);
24950   LGLRELSTK (lgl, &lgl->seen);
24951 
24952   lglrelstk (lgl, &lgl->saved.bin);
24953   lglrelstk (lgl, &lgl->saved.trn);
24954 
24955   DEL (lgl->limits, 1);
24956   DEL (lgl->times, 1);
24957   DEL (lgl->timers, 1);
24958   DEL (lgl->red, MAXGLUE+1);
24959   DEL (lgl->wchs, 1);
24960 
24961   if (lgl->fltstr) DEL (lgl->fltstr, 1);
24962   if (lgl->cbs) DEL (lgl->cbs, 1);		// next to last
24963   lgldelstr (lgl, lgl->prefix);			// last
24964 
24965   // adjust upfront the mem counters ...
24966 
24967   lgldec (lgl, sizeof *lgl->stats);
24968   lgldec (lgl, sizeof *lgl->opts);
24969   lgldec (lgl, sizeof *lgl->mem);
24970   lgldec (lgl, sizeof *lgl);
24971 
24972   assert (getenv ("LGLEAK") || !lgl->stats->bytes.current);
24973 
24974   if (lgl->closeapitrace == 1) fclose (lgl->apitrace);
24975   if (lgl->closeapitrace == 2) pclose (lgl->apitrace);
24976 
24977   if ((dealloc = lgl->mem->dealloc)) {
24978      void * memstate = lgl->mem->state;
24979      if (lgl->stats) dealloc (memstate, lgl->stats, sizeof *lgl->stats);
24980      if (lgl->times) dealloc (memstate, lgl->times, sizeof *lgl->times);
24981      if (lgl->opts) dealloc (memstate, lgl->opts, sizeof *lgl->opts);
24982      assert (lgl->mem);
24983      dealloc (memstate, lgl->mem, sizeof *lgl->mem);
24984      dealloc (memstate, lgl, sizeof *lgl);
24985   } else {
24986     free (lgl->stats);
24987     free (lgl->times);
24988     free (lgl->opts);
24989     free (lgl->mem);
24990     free (lgl);
24991   }
24992 }
24993 
lglutrav(LGL * lgl,void * state,void (* trav)(void *,int))24994 void lglutrav (LGL * lgl, void * state, void (*trav)(void *, int)) {
24995   int elit, val;
24996   REQINITNOTFORKED ();
24997   if (!lgl->mt && !lglbcp (lgl)) lglmt (lgl);
24998   if (!lgl->mt) lglgc (lgl);
24999   if (lgl->mt) return;
25000   if (lgl->level > 0) lglbacktrack (lgl, 0);
25001   for (elit = 1; elit <= lgl->maxext; elit++) {
25002     if (!(val = lglefixed (lgl, elit))) continue;
25003     trav (state, (val < 0) ? -elit : elit);
25004   }
25005 }
25006 
lgletrav(LGL * lgl,void * state,void (* trav)(void *,int,int))25007 void lgletrav (LGL * lgl, void * state, void (*trav)(void *, int, int)) {
25008   int elit, erepr;
25009   REQINITNOTFORKED ();
25010   if (!lgl->mt && !lglbcp (lgl)) lglmt (lgl);
25011   if (!lgl->mt) lglgc (lgl);
25012   if (lgl->mt) return;
25013   if (lgl->level > 0) lglbacktrack (lgl, 0);
25014   for (elit = 1; elit <= lgl->maxext; elit++) {
25015     if (lglefixed (lgl, elit)) continue;
25016     erepr = lglerepr (lgl, elit);
25017     if (erepr == elit) continue;
25018     trav (state, elit, erepr);
25019   }
25020 }
25021 
lglictrav(LGL * lgl,int internal,void * state,void (* trav)(void *,int))25022 static void lglictrav (LGL * lgl, int internal,
25023                        void * state, void (*trav)(void *, int)) {
25024   int idx, sign, lit, blit, tag, red, other, other2;
25025   const int * p, * w, * eow, * c;
25026   HTS * hts;
25027   REQINITNOTFORKED ();
25028   if (lgl->level > 0) lglbacktrack (lgl, 0);
25029   if (!lgl->mt && !lglbcp (lgl)) lglmt (lgl);
25030   if (!lgl->mt) lglgc (lgl);
25031   if (lgl->mt) { trav (state, 0); return; }
25032   for (idx = 2; idx < lgl->nvars; idx++)
25033     for (sign = -1; sign <= 1; sign += 2) {
25034       lit = sign * idx;
25035       assert (!lglval (lgl, lit));
25036       hts = lglhts (lgl, lit);
25037       w = lglhts2wchs (lgl, hts);
25038       eow = w + hts->count;
25039       for (p = w; p < eow; p++) {
25040 	blit = *p;
25041 	tag = blit & MASKCS;
25042 	red = blit & REDCS;
25043 	if (tag == TRNCS || tag == LRGCS) p++;
25044 	if (red) continue;
25045 	if (tag != BINCS && tag != TRNCS) continue;
25046 	other = blit >> RMSHFT;
25047 	if (abs (other) < idx) continue;
25048 	assert (!lglval (lgl, other));
25049 	if (tag == TRNCS) {
25050 	  other2 = *p;
25051 	  if (abs (other2) < idx) continue;
25052 	  assert (!lglval (lgl, other2));
25053 	} else other2 = 0;
25054 	trav (state, internal ? lit : lglexport (lgl, lit));
25055 	trav (state, internal ? other : lglexport (lgl, other));
25056 	if (other2) trav (state, internal ? other2 : lglexport (lgl, other2));
25057 	trav (state, 0);
25058       }
25059     }
25060   for (c = lgl->irr.start; c < lgl->irr.top; c = p + 1) {
25061     p = c;
25062     if (*p >= NOTALIT) continue;
25063     while ((other = *p)) {
25064       assert (!lglval (lgl, other));
25065       trav (state, internal ? other : lglexport (lgl, other));
25066       p++;
25067     }
25068     trav (state, 0);
25069   }
25070 }
25071 
lglctrav(LGL * lgl,void * state,void (* trav)(void *,int))25072 void lglctrav (LGL * lgl, void * state, void (*trav)(void *, int)) {
25073   lglictrav (lgl, 0, state, trav);
25074 }
25075 
lgltravcounter(void * voidptr,int lit)25076 static void lgltravcounter (void * voidptr, int lit) {
25077   int * cntptr = voidptr;
25078   if (!lit) *cntptr += 1;
25079 }
25080 
lgltravprinter(void * voidptr,int lit)25081 static void lgltravprinter (void * voidptr, int lit) {
25082   FILE * out = voidptr;
25083   if (lit) fprintf (out, "%d ", lit);
25084   else fprintf (out, "0\n");
25085 }
25086 
lglprint(LGL * lgl,FILE * file)25087 void lglprint (LGL * lgl, FILE * file) {
25088   int count = 0;
25089   lglctrav (lgl, &count, lgltravcounter);
25090   fprintf (file, "p cnf %d %d\n", lglmaxvar (lgl), count);
25091   lglctrav (lgl, file, lgltravprinter);
25092 }
25093 
lglprintall(LGL * lgl,FILE * file)25094 void lglprintall (LGL * lgl, FILE * file) {
25095   int count = 0;
25096   lgltravall (lgl, &count, lgltravcounter);
25097   fprintf (file, "p cnf %d %d\n", lglmaxvar (lgl), count);
25098   lgltravall (lgl, file, lgltravprinter);
25099 }
25100 
lglrtrav(LGL * lgl,void * state,void (* trav)(void *,int,int))25101 void lglrtrav (LGL * lgl, void * state, void (*trav)(void *, int, int)) {
25102   int idx, sign, lit, blit, tag, red, other, other2, glue;
25103   const int * p, * c, * w, * eow;
25104   Stk * lir;
25105   HTS * hts;
25106   REQINITNOTFORKED ();
25107   if (lgl->mt) return;
25108   lglgc (lgl);
25109   if (lgl->level > 0) lglbacktrack (lgl, 0);
25110   for (idx = 2; idx < lgl->nvars; idx++) {
25111     if (lglval (lgl, idx)) continue;
25112     for (sign = -1; sign <= 1; sign += 2) {
25113       lit = sign * idx;
25114       hts = lglhts (lgl, lit);
25115       w = lglhts2wchs (lgl, hts);
25116       eow = w + hts->count;
25117       for (p = w; p < eow; p++) {
25118 	blit = *p;
25119 	tag = blit & MASKCS;
25120 	red = blit & REDCS;
25121 	if (tag == TRNCS || tag == LRGCS) p++;
25122 	if (!red) continue;
25123 	if (tag != BINCS && tag != TRNCS) continue;
25124 	other = blit >> RMSHFT;
25125 	if (abs (other) < idx) continue;
25126 	assert (!lglval (lgl, other));
25127 	if (tag == TRNCS) {
25128 	  other2 = *p;
25129 	  if (abs (other2) < idx) continue;
25130 	  assert (!lglval (lgl, other2));
25131 	} else other2 = 0;
25132 	trav (state, lglexport (lgl, lit), 0);
25133 	trav (state, lglexport (lgl, other), 0);
25134 	if (other2) trav (state, lglexport (lgl, other2), 0);
25135 	trav (state, 0, 0);
25136       }
25137     }
25138   }
25139   for (glue = 0; glue < MAXGLUE; glue++) {
25140     lir = lgl->red + glue;
25141     for (c = lir->start; c < lir->top; c = p + 1) {
25142       p = c;
25143       if (*p >= NOTALIT) continue;
25144       while ((other = *p)) {
25145 	assert (!lglval (lgl, other));
25146 	trav (state, lglexport (lgl, other), 0);
25147 	p++;
25148       }
25149       trav (state, 0, 0);
25150     }
25151   }
25152 }
25153 
lgltravallu(void * voidptr,int unit)25154 static void lgltravallu (void * voidptr, int unit) {
25155   Trv * state = voidptr;
25156   state->trav (state->state, unit);
25157   state->trav (state->state, 0);
25158 }
25159 
lgltravalle(void * voidptr,int lit,int repr)25160 static void lgltravalle (void * voidptr, int lit, int repr) {
25161   Trv * state = voidptr;
25162   state->trav (state->state, -lit);
25163   state->trav (state->state, repr);
25164   state->trav (state->state, 0);
25165   state->trav (state->state, lit);
25166   state->trav (state->state, -repr);
25167   state->trav (state->state, 0);
25168 }
25169 
lgltravall(LGL * lgl,void * state,void (* trav)(void *,int))25170 void lgltravall (LGL * lgl, void * state, void (*trav)(void *, int)) {
25171   Trv travstate;
25172   travstate.state = state;
25173   travstate.trav = trav;
25174   lglutrav (lgl, &travstate, lgltravallu);
25175   lgletrav (lgl, &travstate, lgltravalle);
25176   lglctrav (lgl, state, trav);
25177 }
25178 
25179 #ifndef NDEBUG
25180 
lgldump(LGL * lgl)25181 void lgldump (LGL * lgl) {
25182   int idx, sign, lit, blit, tag, red, other, other2, glue;
25183   const int * p, * w, * eow, * c, * top;
25184   Stk * lir;
25185   HTS * hts;
25186   for (idx = 2; idx < lgl->nvars; idx++)
25187     for (sign = -1; sign <= 1; sign += 2) {
25188       lit = sign * idx;
25189       hts = lglhts (lgl, lit);
25190       w = lglhts2wchs (lgl, hts);
25191       eow = w + hts->count;
25192       for (p = w; p < eow; p++) {
25193 	blit = *p;
25194 	tag = blit & MASKCS;
25195 	red = blit & REDCS;
25196 	if (tag == TRNCS || tag == LRGCS) p++;
25197 	if (tag == BINCS) {
25198 	  other = blit >> RMSHFT;
25199 	  if (abs (other) < idx) continue;
25200 	  other2 = 0;
25201 	} else if (tag == TRNCS) {
25202 	  other = blit >> RMSHFT;
25203 	  if (abs (other) < idx) continue;
25204 	  other2 = *p;
25205 	  if (abs (other2) < idx) continue;
25206 	} else continue;
25207 	fprintf (lgl->out, "%s %d %d", red ? "red" : "irr", lit, other);
25208 	if (tag == TRNCS) fprintf (lgl->out, " %d", other2);
25209 	fprintf (lgl->out, "\n");
25210       }
25211     }
25212   top = lgl->irr.top;
25213   for (c = lgl->irr.start; c < top; c = p + 1) {
25214     p = c;
25215     if (*p >= NOTALIT) continue;
25216     fprintf (lgl->out, "irr");
25217     while (*p) fprintf (lgl->out, " %d", *p++);
25218     fprintf (lgl->out, "\n");
25219   }
25220   for (glue = 0; glue < MAXGLUE; glue++) {
25221     lir = lgl->red + glue;
25222     top = lir->top;
25223     for (c = lir->start; c < top; c = p + 1) {
25224       p = c;
25225       if (*p >= NOTALIT) continue;
25226       fprintf (lgl->out, "glue%d", glue);
25227       while (*p) fprintf (lgl->out, " %d", *p++);
25228       fprintf (lgl->out, "\n");
25229     }
25230   }
25231 }
25232 
25233 #endif
25234 
lglforkadd(void * ptr,int lit)25235 static void lglforkadd (void * ptr, int lit) {
25236   lgladd (ptr, lit ? lglforklit (lit) : 0);
25237 }
25238 
lglfork(LGL * parent)25239 LGL * lglfork (LGL * parent) {
25240   LGL * child;
25241   {
25242     LGL * lgl = parent;
25243     REQINIT ();
25244     ABORTIF (!lglmtstk (&parent->eassume), "can not fork under assumptions");
25245     ABORTIF (parent->forked == INT_MAX, "parent forked too often");
25246   }
25247   if (parent->level > 0) lglbacktrack (parent, 0);
25248   (void) lglbcp (parent);
25249   lglgc (parent);
25250   child = lglminit (parent->mem->state,
25251                     parent->mem->alloc,
25252                     parent->mem->realloc,
25253                     parent->mem->dealloc);
25254   child->parent = parent;
25255   memcpy (child->opts, parent->opts, sizeof *parent->opts);
25256   lglcopyclonenfork (child, parent);
25257   lglictrav (parent, 1, child, lglforkadd);
25258   assert (parent->stats->irr.clauses.cur == child->stats->irr.clauses.cur);
25259   parent->forked++;
25260   assert (parent->forked > 0);
25261   lglprt (parent, 1, "forked-%d", parent->forked);
25262   return child;
25263 }
25264 
lglflass(LGL * lgl,LGL * from)25265 static void lglflass (LGL * lgl, LGL * from) {
25266   int idx, copied = 0;
25267   assert (!lgl->level), assert (!lgl->mt);
25268   assert ((from->state & (SATISFIED | EXTENDED)));
25269   if (lgl->nvars) assert (lgl->nvars == from->maxext + 2);
25270   else assert (!from->maxext);
25271   lglreset (lgl);
25272   for (idx = 2; idx < lgl->nvars; idx++) {
25273     int val = lglderef (from, idx-1);
25274     int lit = val < 0 ? -idx : idx;
25275     lgldassume (lgl, lit);
25276     copied++;
25277   }
25278   lglprt (lgl, 1, "[flass] copied %d internal assignments", copied);
25279   TRANS (SATISFIED);
25280   lglextend (lgl);
25281 #ifndef NCHKSOL
25282   lglchksol (lgl);
25283 #endif
25284 }
25285 
lgljoin(LGL * parent,LGL * child)25286 int lgljoin (LGL * parent, LGL * child) {
25287   int res;
25288   {
25289     LGL * lgl = parent;
25290     ABORTIF (!parent, "uninitialized parent manager");
25291     ABORTIF (!child, "uninitialized child manager");
25292     ABORTIF (!parent->forked, "parent manager not forked");
25293     ABORTIF (!child->parent, "child manager has not parent");
25294     ABORTIF (child->parent != parent, "child manager has different parent");
25295     ABORTIF (!lglmtstk (&child->eassume),
25296       "child manager with assumptions not supported yet");
25297   }
25298   if (child->mt || (child->state & UNSATISFIED)) {
25299 #ifndef NLGLOG
25300     LGL * lgl = parent;
25301 #endif
25302     assert (child->mt);				  // no assumptions yet ...
25303     lglprt (parent, 1, "[join] unsatisfied state");
25304     if (!parent->mt) {
25305       LOG (1, "joining empty clause");
25306       parent->mt = 1;
25307     } else LOG (1, "no need to join empty clause since parent has one");
25308     res = 20;
25309   } else if (child->state & (SATISFIED | EXTENDED)) {
25310     lglprt (parent, 1, "[join] satisfied state");
25311     lglflass (parent, child);
25312     res = 10;
25313   } else {
25314     lglprt (parent, 1, "[join] unknown state");
25315     lglreset (parent);
25316     {
25317       LGL * lgl = parent;
25318       TRANS (UNKNOWN);
25319     }
25320     res = 0;
25321   }
25322   return res;
25323 }
25324