Adding support for reading wrong assumptions
[satlib.git] / lingeling / code / lglib.c
1 /*-------------------------------------------------------------------------*/
2 /* Copyright 2010-2014 Armin Biere Johannes Kepler University Linz Austria */
3 /*-------------------------------------------------------------------------*/
4
5 #include "lglib.h"
6
7 /*-------------------------------------------------------------------------*/
8
9 #include <assert.h>
10 #include <ctype.h>
11 #include <limits.h>
12 #include <math.h>
13 #include <stdarg.h>
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <sys/resource.h>
19 #include <sys/time.h>
20 #include <unistd.h>
21
22 /*-------------------------------------------------------------------------*/
23
24 #ifndef NLGLPICOSAT
25 #include "picosat.h"
26 #endif
27
28 #ifndef NLGLYALSAT
29 #include "yals.h"
30 #endif
31
32 #ifndef NLGLDRUPLIG
33 #include "druplig.h"
34 #endif
35
36 /*-------------------------------------------------------------------------*/
37
38 #define REMOVED         INT_MAX
39 #define NOTALIT         ((INT_MAX >> RMSHFT))
40 #define MAXVAR          ((INT_MAX >> RMSHFT) - 2)
41
42 #define GLUESHFT        4
43 #define POW2GLUE        (1 << GLUESHFT)
44 #define MAXGLUE         (POW2GLUE - 1)
45 #define GLUEMASK        (POW2GLUE - 1)
46 #define MAXREDLIDX      ((1 << (31 - GLUESHFT)) - 2)
47 #define MAXIRRLIDX      ((1 << (31 - RMSHFT)) - 2)
48
49 #define MAXLDFW         31      
50 #define REPMOD          22
51
52 #define FUNVAR          10
53 #define FUNQUADS        (1<<(FUNVAR - 6))
54 #define FALSECNF        (1ll<<32)
55 #define TRUECNF         0ll
56
57 #define FLTPRC          32
58 #define EXPMIN          (0x0000 ## 0000)
59 #define EXPZRO          (0x1000 ## 0000)
60 #define EXPMAX          (0x7fff ## ffff)
61 #define MNTBIT          (0x0000 ## 0001 ## 0000 ## 0000 ## ull)
62 #define MNTMAX          (0x0000 ## 0001 ## ffff ## ffff ## ull)
63 #define FLTMIN          (0x0000 ## 0000 ## 0000 ## 0000 ## ll)
64 #define FLTMAX          (0x7fff ## ffff ## ffff ## ffff ## ll)
65
66 #define LGL_SCORE_AVG           4
67 #define LGL_SCORE_EVSIDS        5
68 #define LGL_SCORE_VSIDS256      6
69 #define LGL_SCORE_FAVG          7
70
71 #ifdef NDBLSCR
72 #define MAXSCOREXP      (1<<30)
73 #else
74 #define MAXSCOREXP      (1<<9)
75 #endif
76
77 #define DEFSCOREXP      500
78
79 #define LLMAX           FLTMAX
80
81 #define MAXFLTSTR       6
82 #define MAXPHN          10
83
84 /*------------------------------------------------------------------------*/
85 #ifndef NLGLOG
86 /*------------------------------------------------------------------------*/
87
88 #define MAPLOGLEVEL(LEVEL) (LEVEL)
89
90 #define LOG(LEVEL,FMT,ARGS...) \
91 do { \
92   if (MAPLOGLEVEL(LEVEL) > lgl->opts->log.val) break; \
93   lglogstart (lgl, MAPLOGLEVEL(LEVEL), FMT, ##ARGS); \
94   lglogend (lgl); \
95 } while (0)
96
97 #define LOGCLS(LEVEL,CLS,FMT,ARGS...) \
98 do { \
99   const int * P; \
100   if (MAPLOGLEVEL(LEVEL) > lgl->opts->log.val) break; \
101   lglogstart (lgl, MAPLOGLEVEL(LEVEL), FMT, ##ARGS); \
102   for (P = (CLS); *P; P++) fprintf (lgl->out, " %d", *P); \
103   lglogend (lgl); \
104 } while (0)
105
106 #define LOGMCLS(LEVEL,CLS,FMT,ARGS...) \
107 do { \
108   const int * P; \
109   if (MAPLOGLEVEL(LEVEL) > lgl->opts->log.val) break; \
110   lglogstart (lgl, MAPLOGLEVEL(LEVEL), FMT, ##ARGS); \
111   for (P = (CLS); *P; P++) fprintf (lgl->out, " %d", lglm2i (lgl, *P)); \
112   lglogend (lgl); \
113 } while (0)
114
115 #define LOGRESOLVENT(LEVEL,FMT,ARGS...) \
116 do { \
117   const int * P; \
118   if (MAPLOGLEVEL(LEVEL) > lgl->opts->log.val) break; \
119   lglogstart (lgl, MAPLOGLEVEL(LEVEL), FMT, ##ARGS); \
120   for (P = lgl->resolvent.start; P < lgl->resolvent.top; P++) \
121     fprintf (lgl->out, " %d", *P); \
122   lglogend (lgl); \
123 } while (0)
124
125 #define LOGREASON(LEVEL,LIT,REASON0,REASON1,FMT,ARGS...) \
126 do { \
127   int TAG, TMP, RED, G; \
128   const int * C, * P; \
129   if (MAPLOGLEVEL(LEVEL) > lgl->opts->log.val) break; \
130   lglogstart (lgl, MAPLOGLEVEL(LEVEL), FMT, ##ARGS); \
131   TMP = (REASON0 >> RMSHFT); \
132   RED = (REASON0 & REDCS); \
133   TAG = (REASON0 & MASKCS); \
134   if (TAG == DECISION) fputs (" decision", lgl->out); \
135   else if (TAG == UNITCS) fprintf (lgl->out, " unit %d", LIT); \
136   else if (TAG == BINCS) { \
137     fprintf (lgl->out, \
138        " %s binary clause %d %d", lglred2str (RED), LIT, TMP); \
139   } else if (TAG == TRNCS) { \
140     fprintf (lgl->out, " %s ternary clause %d %d %d", \
141             lglred2str (RED), LIT, TMP, REASON1); \
142   } else { \
143     assert (TAG == LRGCS); \
144     C = lglidx2lits (lgl, RED, REASON1); \
145     for (P = C; *P; P++) \
146       ; \
147     fprintf (lgl->out, " size %ld", (long)(P - C)); \
148     if (RED) { \
149       G = (REASON1 & GLUEMASK); \
150       fprintf (lgl->out, " glue %d redundant", G); \
151     } else fputs (" irredundant", lgl->out); \
152     fputs (" clause", lgl->out); \
153     for (P = C; *P; P++) { \
154       fprintf (lgl->out, " %d", *P); \
155     } \
156   } \
157   lglogend (lgl); \
158 } while (0)
159
160 #define LOGDSCHED(LEVEL,LIT,FMT,ARGS...) \
161   do { \
162     int POS; \
163     if (MAPLOGLEVEL(LEVEL) > lgl->opts->log.val) break; \
164     POS = *lgldpos (lgl, LIT); \
165     lglogstart (lgl, MAPLOGLEVEL(LEVEL), "dsched[%d] = %d ", POS, LIT); \
166     printf (FMT, ##ARGS); \
167     printf (" score %s", lglscr2str (lgl, lglqvar (lgl, LIT)->score)); \
168     lglogend (lgl); \
169   } while (0)
170
171 #define LOGESCHED(LEVEL,LIT,FMT,ARGS...) \
172 do { \
173   int POS; \
174   EVar * EV; \
175   if (MAPLOGLEVEL(LEVEL) > lgl->opts->log.val) break; \
176   POS = *lglepos (lgl, LIT); \
177   EV = lglevar (lgl, LIT); \
178   lglogstart (lgl, MAPLOGLEVEL(LEVEL), "esched[%d] = %d ", POS, LIT); \
179   fprintf (lgl->out, FMT, ##ARGS); \
180   fprintf (lgl->out, " score"); \
181   fprintf (lgl->out, " occ %d %d", EV->occ[0], EV->occ[1]); \
182   lglogend (lgl); \
183 } while (0)
184
185 #define LOGEQN(LEVEL,EQN,FMT,ARGS...) \
186 do { \
187   const int * P, * START; \
188   if (MAPLOGLEVEL(LEVEL) > lgl->opts->log.val) break; \
189   lglogstart (lgl, MAPLOGLEVEL(LEVEL), FMT, ##ARGS); \
190   START = lgl->gauss->xors.start + (EQN); \
191   assert (START < lgl->gauss->xors.top); \
192   for (P = START; *P > 1; P++) fprintf (lgl->out, " %d", *P); \
193   fprintf (lgl->out, " = %d", *P); \
194   lglogend (lgl); \
195 } while (0)
196
197 /*------------------------------------------------------------------------*/
198 #else /* end of then start of else part of 'ifndef NLGLOG' */
199 /*------------------------------------------------------------------------*/
200
201 #define LOG(ARGS...) do { } while (0)
202 #define LOGCLS(ARGS...) do { } while (0)
203 #define LOGMCLS(ARGS...) do { } while (0)
204 #define LOGRESOLVENT(ARGS...) do { } while (0)
205 #define LOGREASON(ARGS...) do { } while (0)
206 #define LOGDSCHED(ARGS...) do { } while (0)
207 #define LOGESCHED(ARGS...) do { } while (0)
208 #define LOGEQN(ARGS...) do { } while (0)
209
210 /*------------------------------------------------------------------------*/
211 #endif /* end of else part of 'ifndef NLGLOG' */
212 /*------------------------------------------------------------------------*/
213
214 #define ABORTIF(COND,FMT,ARGS...) \
215 do { \
216   if (!(COND)) break; \
217   fprintf (stderr, "*** API usage error of '%s' in '%s'", \
218            __FILE__, __FUNCTION__); \
219   if (lgl && lgl->tid >= 0) fprintf (stderr, " (tid %d)", lgl->tid); \
220   fputs (": ", stderr); \
221   fprintf (stderr, FMT, ##ARGS); \
222   fputc ('\n', stderr); \
223   fflush (stderr); \
224   lglabort (lgl); \
225   exit (1); \
226 } while (0)
227
228 // Useful for using our 'sleeponabort' and other hooks 'on abort' ...
229
230 #ifndef NDEBUG
231 #define ASSERT(COND) \
232 do { \
233   if ((COND)) break; \
234   fprintf (stderr, \
235     "liblgl.a: %s:%d: %s: Lingeling Assertion `%s' failed.", \
236     __FUNCTION__, __LINE__, __FILE__, # COND); \
237   if (lgl && lgl->tid >= 0) fprintf (stderr, " (tid %d)", lgl->tid); \
238   fputc ('\n', stderr); \
239   fflush (stderr); \
240   lglabort (lgl); \
241   exit (1); \
242 } while (0)
243 #else
244 #define ASSERT(COND) do { } while (0)
245 #endif
246
247 #define COVER(COND) \
248 do { \
249   if (!(COND)) break; \
250   fprintf (stderr, \
251     "liblgl.a: %s:%d: %s: Coverage target `%s' reached.", \
252     __FUNCTION__, __LINE__, __FILE__, # COND); \
253   if (lgl && lgl->tid >= 0) fprintf (stderr, " (tid %d)", lgl->tid); \
254   fputc ('\n', stderr); \
255   fflush (stderr); \
256   abort (); /* TODO: why not 'lglabort' */ \
257 } while (0)
258
259 #define REQINIT() \
260 do { \
261   ABORTIF (!lgl, "uninitialized manager"); \
262 } while (0)
263
264 #define REQINITNOTFORKED() \
265 do { \
266   REQINIT (); \
267   ABORTIF (lgl->forked, "forked manager"); \
268 } while (0)
269
270 #define REQUIRE(STATE) \
271 do { \
272   REQINIT (); \
273   ABORTIF(!(lgl->state & (STATE)), "!(%s)", #STATE); \
274 } while (0)
275
276 #define TRANS(STATE) \
277 do { \
278   assert (lgl->state != STATE); \
279   LOG (1, "transition to state " #STATE); \
280   lgl->state = STATE; \
281 } while (0)
282
283 /*------------------------------------------------------------------------*/
284
285 #if !defined(NDEBUG) || !defined(NLGLOG)
286 #define RESOLVENT
287 #endif
288
289 /*------------------------------------------------------------------------*/
290
291 #define TRAPI(MSG,ARGS...) \
292 do { \
293   if (!lgl->apitrace) break; \
294   lgltrapi (lgl, MSG, ##ARGS); \
295 } while (0)
296
297 #define LGLCHKACT(ACT) \
298 do { assert (NOTALIT <= (ACT) && (ACT) < REMOVED - 1); } while (0)
299
300 /*------------------------------------------------------------------------*/
301
302 #define OPT(SHRT,LNG,VAL,MIN,MAX,DESCRP) \
303 do { \
304   Opt * opt = &lgl->opts->LNG; \
305   opt->shrt = SHRT; \
306   opt->lng = #LNG; \
307   opt->dflt = opt->val = VAL; \
308   assert (MIN <= VAL); \
309   opt->min = MIN; \
310   assert (VAL <= MAX); \
311   opt->max = MAX; \
312   opt->descrp = DESCRP; \
313   lglgetenv (lgl, opt, #LNG); \
314 } while (0)
315
316 /*------------------------------------------------------------------------*/
317
318 #define NEW(P,N) \
319 do { (P) = lglnew (lgl, (N) * sizeof *(P)); } while (0)
320
321 #define DEL(P,N) \
322 do { lgldel (lgl, (P), (N) * sizeof *(P)); (P) = 0; } while (0)
323
324 #define RSZ(P,O,N) \
325 do { (P) = lglrsz (lgl, (P), (O)*sizeof*(P), (N)*sizeof*(P)); } while (0)
326
327 #define CLN(P,N) \
328 do { memset ((P), 0, (N) * sizeof *(P)); } while (0)
329
330 #define CLRPTR(P) \
331 do { memset ((P), 0, sizeof *(P)); } while (0)
332
333 #define CLR(P) \
334 do { memset (&(P), 0, sizeof (P)); } while (0)
335
336 /*------------------------------------------------------------------------*/
337
338 #define SWAP(TYPE,A,B) \
339 do { TYPE TMP = (A); (A) = (B); (B) = TMP; } while (0)
340
341 #define ISORTLIM 10
342
343 #define CMPSWAP(TYPE,CMP,P,Q) \
344 do { if (CMP (&(P), &(Q)) > 0) SWAP (TYPE, P, Q); } while(0)
345
346 #define QPART(TYPE,CMP,A,L,R) \
347 do { \
348   TYPE PIVOT; \
349   int J = (R); \
350   I = (L) - 1; \
351   PIVOT = (A)[J]; \
352   for (;;) { \
353     while (CMP (&(A)[++I], &PIVOT) < 0) \
354       ; \
355     while (CMP (&PIVOT, &(A)[--J]) < 0) \
356       if (J == (L)) break; \
357     if (I >= J) break; \
358     SWAP (TYPE, (A)[I], (A)[J]); \
359   } \
360   SWAP (TYPE, (A)[I], (A)[R]); \
361 } while(0)
362
363 #define QSORT(TYPE,CMP,A,N) \
364 do { \
365   int L = 0, R = (N) - 1, M, LL, RR, I; \
366   assert (lglmtstk (&lgl->sortstk)); \
367   if (R - L <= ISORTLIM) break; \
368   for (;;) { \
369     M = (L + R) / 2; \
370     SWAP (TYPE, (A)[M], (A)[R - 1]); \
371     CMPSWAP (TYPE, CMP, (A)[L], (A)[R - 1]); \
372     CMPSWAP (TYPE, CMP, (A)[L], (A)[R]); \
373     CMPSWAP (TYPE, CMP, (A)[R - 1], (A)[R]); \
374     QPART (TYPE, CMP, (A), L + 1, R - 1); \
375     if (I - L < R - I) { LL = I + 1; RR = R; R = I - 1; } \
376     else { LL = L; RR = I - 1; L = I + 1; } \
377     if (R - L > ISORTLIM) { \
378       assert (RR - LL > ISORTLIM); \
379       lglpushstk (lgl, &lgl->sortstk, LL); \
380       lglpushstk (lgl, &lgl->sortstk, RR); \
381     } else if (RR - LL > ISORTLIM) L = LL, R = RR; \
382     else if (!lglmtstk (&lgl->sortstk)) { \
383       R = lglpopstk (&lgl->sortstk); \
384       L = lglpopstk (&lgl->sortstk); \
385     } else break; \
386   } \
387 } while (0)
388
389 #define ISORT(TYPE,CMP,A,N) \
390 do { \
391   TYPE PIVOT; \
392   int L = 0, R = (N) - 1, I, J; \
393   for (I = R; I > L; I--) \
394     CMPSWAP (TYPE, CMP, (A)[I - 1], (A)[I]); \
395   for (I = L + 2; I <= R; I++) { \
396     J = I; \
397     PIVOT = (A)[I]; \
398     while (CMP (&PIVOT, &(A)[J - 1]) < 0) { \
399       (A)[J] = (A)[J - 1]; \
400       J--; \
401     } \
402     (A)[J] = PIVOT; \
403   } \
404 } while (0)
405
406 #ifdef NDEBUG
407 #define CHKSORT(CMP,A,N) do { } while(0)
408 #else
409 #define CHKSORT(CMP,A,N) \
410 do { \
411   int I; \
412   for (I = 0; I < (N) - 1; I++) \
413     assert (CMP (&(A)[I], &(A)[I + 1]) <= 0); \
414 } while(0)
415 #endif
416
417 #define SORT(TYPE,A,N,CMP) \
418 do { \
419   TYPE * AA = (A); \
420   int NN = (N); \
421   QSORT (TYPE, CMP, AA, NN); \
422   ISORT (TYPE, CMP, AA, NN); \
423   CHKSORT (CMP, AA, NN); \
424 } while (0)
425
426 /*------------------------------------------------------------------------*/
427
428 #define LGLPOPWTK(WTK,WRAG,LIT,OTHER,RED,REMOVED) \
429 do { \
430   assert (!lglmtwtk (WTK)); \
431   (WTK)->top--; \
432   (WRAG) = (WTK)->top->wrag; \
433   (LIT) = (WTK)->top->lit; \
434   (OTHER) = (WTK)->top->other; \
435   (RED) = (WTK)->top->red ? REDCS : 0; \
436   (REMOVED) = (WTK)->top->removed; \
437 } while (0)
438
439 /*------------------------------------------------------------------------*/
440
441 #define CLONE(FIELD,SIZE) \
442 do { \
443   NEW (lgl->FIELD, (SIZE)); \
444   memcpy (lgl->FIELD, orig->FIELD, (SIZE) * sizeof *(lgl->FIELD)); \
445 } while (0)
446
447 #define CLONESTK(NAME) \
448 do { \
449   size_t COUNT = orig->NAME.top - orig->NAME.start; \
450   size_t SIZE = orig->NAME.end - orig->NAME.start; \
451   size_t BYTES = SIZE * sizeof *lgl->NAME.start; \
452   NEW (lgl->NAME.start, SIZE); \
453   memcpy (lgl->NAME.start, orig->NAME.start, BYTES); \
454   lgl->NAME.top = lgl->NAME.start + COUNT; \
455   lgl->NAME.end = lgl->NAME.start + SIZE; \
456 } while (0)
457
458 /*------------------------------------------------------------------------*/
459
460 #define INCSTEPS(NAME) \
461  ((lgl->stats->steps++), (lgl->stats->NAME++))
462
463 #define ADDSTEPS(NAME,INC) \
464  ((lgl->stats->steps += INC), (lgl->stats->NAME += INC))
465
466 /*------------------------------------------------------------------------*/
467
468 #define LGLUPDPEN(NAME,SUCCESS) \
469 do { \
470   assert (!lgl->limits->NAME.del.rem); \
471   if ((SUCCESS) && lgl->limits->NAME.pen) \
472     lgl->limits->NAME.pen--; \
473   if (!(SUCCESS) && lgl->limits->NAME.pen < lgl->opts->penmax.val) \
474     lgl->limits->NAME.pen++; \
475   if ((SUCCESS) && lgl->limits->NAME.del.cur) \
476     lgl->limits->NAME.del.cur /= 2; \
477   if (!(SUCCESS) && lgl->limits->NAME.del.cur < lgl->opts->delmax.val) \
478     lgl->limits->NAME.del.cur++; \
479   lgl->limits->NAME.del.rem = lgl->limits->NAME.del.cur; \
480 } while (0)
481
482 /*-------------------------------------------------------------------------*/
483
484 #define LGLL long long
485
486 /*-------------------------------------------------------------------------*/
487
488 typedef enum Tag {
489   FREEVAR = 0,
490   FIXEDVAR = 1,
491   EQUIVAR = 2,
492   ELIMVAR = 3,
493
494   DECISION = 0,
495   UNITCS = 1,
496   OCCS = 1,
497   BINCS = 2,
498   TRNCS = 3,
499   LRGCS = 4,
500   MASKCS = 7,
501
502   REDCS = 8,
503   RMSHFT = 4,
504 } Tag;
505
506 typedef enum State {
507   UNUSED        = (1<<0),
508   OPTSET        = (1<<1),
509   USED          = (1<<2),
510   READY         = (1<<3),
511   UNKNOWN       = (1<<4),
512   SATISFIED     = (1<<5),
513   EXTENDED      = (1<<6),
514   UNSATISFIED   = (1<<7),
515   FAILED        = (1<<8),
516   LOOKED        = (1<<9),
517   RESET         = (1<<10),
518 } State;
519
520 typedef enum Wrag {
521   PREFIX = 0,
522   BEFORE = 1,
523   AFTER = 2,
524   POSTFIX = 3,
525 } Wrag;
526
527 typedef enum GTag { ANDTAG, ITETAG, XORTAG } GTag;
528
529 /*------------------------------------------------------------------------*/
530
531 typedef struct Opt {
532   char shrt;
533   const char * lng, * descrp;
534   int val, min, max, dflt;
535 } Opt;
536
537 typedef struct Opts {
538
539   Opt beforefirst;
540
541   Opt abstime;
542   Opt actavgmax;
543   Opt actdblarithlim;
544   Opt actgeomlim;
545   Opt actgsdul;
546   Opt acts;
547   Opt actstdmax;
548   Opt actstdmin;
549   Opt actvlim;
550   Opt agile;
551   Opt agilelim;
552   Opt agilesinint;
553   Opt bate;
554   Opt batewait;
555   Opt bca;
556   Opt bcamaxeff;
557   Opt bcaminuse;
558   Opt bcawait;
559   Opt bva;
560   Opt bias;
561   Opt binlocsdel;
562   Opt binsimpdel;
563   Opt bkwdscale;
564   Opt blkboost;
565   Opt blkboostvlim;
566   Opt blkclslim;
567   Opt blklarge;
568   Opt blkmaxeff;
569   Opt blkmineff;
570   Opt blkocclim;
571   Opt blkocclim1;
572   Opt blkocclim2;
573   Opt blkreleff;
574   Opt blkrtc;
575   Opt blksched2b2;
576   Opt blkschedmin;
577   Opt blkschedprod;
578   Opt blkschedpure;
579   Opt blkschedsum;
580   Opt blksmall;
581   Opt blksuccesslim;
582   Opt blksuccessrat;
583   Opt block;
584   Opt blockwait;
585   Opt boost;
586   Opt bumpbcplits;
587   Opt bumpclslits;
588   Opt bumpseenaftermin;
589   Opt bumpseenbeforemin;
590   Opt bumpseenlits;
591   Opt bumpseenminsize;
592   Opt card;
593   Opt cardcut;
594   Opt cardexpam1;
595   Opt cardglue;
596   Opt cardignused;
597   Opt cardmaxeff;
598   Opt cardmaxlen;
599   Opt cardmineff;
600   Opt cardminlen;
601   Opt cardocclim1;
602   Opt cardocclim2;
603   Opt cardreleff;
604   Opt cardreschedint;
605   Opt carduse;
606   Opt cardwait;
607   Opt cce;
608   Opt cceboost;
609   Opt cceboostvlim;
610   Opt cce2wait;
611   Opt cce3wait;
612   Opt ccemaxeff;
613   Opt ccemineff;
614   Opt cceonlyifstuck;
615   Opt ccereleff;
616   Opt ccertc;
617   Opt ccesuccesslim;
618   Opt ccesuccessrat;
619   Opt ccewait;
620   Opt cgrclsr;
621   Opt cgrclsrwait;
622   Opt cgreleff;
623   Opt cgrextand;
624   Opt cgrexteq;
625   Opt cgrextite;
626   Opt cgrextunits;
627   Opt cgrextxor;
628   Opt cgrmaxeff;
629   Opt cgrmaxority;
630   Opt cgrmineff;
631   Opt cintinc;
632   Opt cintincdiv;
633   Opt cintmaxhard;
634   Opt cintmaxsoft;
635   Opt cliff;
636   Opt cliffmaxeff;
637   Opt cliffmineff;
638   Opt cliffreleff;
639   Opt cliffwait;
640   Opt clim;
641   Opt compact;
642   Opt deco;
643   Opt decolim;
644   Opt decompose;
645   Opt defragfree;
646   Opt defragint;
647   Opt delmax;
648   Opt dlim;
649   Opt drup;
650   Opt druplig;
651   Opt elim;
652   Opt elmaxeff;
653   Opt elmblk;
654   Opt elmblkwait;
655   Opt elmboost;
656   Opt elmclslim;
657   Opt elmfull;
658   Opt elmineff;
659   Opt elmlitslim;
660   Opt elmocclim;
661   Opt elmocclim1;
662   Opt elmocclim2;
663   Opt elmreleff;
664   Opt elmroundlim;
665   Opt elmrtc;
666   Opt elmsched2b2;
667   Opt elmschediff;
668   Opt elmschedmin;
669   Opt elmschedprod;
670   Opt elmschedpure;
671   Opt elmschedsum;
672   Opt elmsuccesslim;
673   Opt elmsuccessrat;
674   Opt exitonabort;
675   Opt factmax;
676   Opt factor;
677   Opt flipdur;
678   Opt flipint;
679   Opt flipldmod;
680   Opt fliplevels;
681   Opt flipping;
682   Opt fliptop;
683   Opt flipvlim;
684   Opt force;
685   Opt gauss;
686   Opt gaussexptrn;
687   Opt gaussextrall;
688   Opt gaussmaxeff;
689   Opt gaussmaxor;
690   Opt gaussmineff;
691   Opt gaussreleff;
692   Opt gausswait;
693   Opt gluekeep;
694   Opt gluescale;
695   Opt import;
696   Opt incredcint;
697   Opt incredconfslim;
698   Opt incsavevisits;
699   Opt inprocessing;
700   Opt irrlim;
701   Opt itlocsdel;
702   Opt itsimpdel;
703   Opt jwhred;
704   Opt keepmaxglue;
705   Opt lftmaxeff;
706   Opt lftmineff;
707   Opt lftreleff;
708   Opt lftroundlim;
709   Opt lhbr;
710   Opt lift;
711   Opt liftlrg;
712   Opt liftwait;
713   Opt lkhd;
714   Opt lkhdmisifelmrtc;
715   Opt locs;
716   Opt locsboost;
717   Opt locscint;
718   Opt locsdec;
719   Opt locset;
720   Opt locsexport;
721   Opt locsmaxeff;
722   Opt locsmineff;
723   Opt locsclim;
724   Opt locsred;
725   Opt locsreleff;
726   Opt locsrtc;
727   Opt locsvared;
728   Opt locswait;
729   Opt maxglue;
730   Opt maxscorexp;
731   Opt mega;
732   Opt megaint;
733   Opt megawait;
734   Opt memlim;
735   Opt minimize;
736   Opt minlocalgluelim;
737   Opt minrecgluelim;
738   Opt mocint;
739   Opt move;
740   Opt otfs;
741   Opt otfsbump;
742   Opt otfsconf;
743   Opt penmax;
744   Opt phase;
745   Opt phaseflip;
746   Opt phasegluebit;
747   Opt phaseneginit;
748   Opt plain;
749   Opt plim;
750   Opt prbasic;
751   Opt prbasicmaxeff;
752   Opt prbasicmineff;
753   Opt prbasicreleff;
754   Opt prbasicroundlim;
755   Opt prbasicrtc;
756   Opt prbrtc;
757   Opt prbsimple;
758   Opt prbsimpleboost;
759   Opt prbsimpleliftdepth;
760   Opt prbsimplemaxeff;
761   Opt prbsimplemineff;
762   Opt prbsimplereleff;
763   Opt prbsimplertc;
764   Opt probe;
765   Opt psm;
766   Opt pure;
767   Opt randec;
768   Opt randecflipint;
769   Opt randecint;
770   Opt rdp;
771   Opt rdpclslim;
772   Opt rdplim;
773   Opt rdpmaxeff;
774   Opt rdpmineff;
775   Opt rdpmodelm;
776   Opt rdpreleff;
777   Opt rdpwait;
778   Opt redfixed;
779   Opt redinoutinc;
780   Opt redlbound;
781   Opt redlexpfac;
782   Opt redlinc;
783   Opt redlinit;
784   Opt redlmaxabs;
785   Opt redlmaxinc;
786   Opt redlmaxrel;
787   Opt redlminabs;
788   Opt redlmininc;
789   Opt redlminrel;
790   Opt redloutinc;
791   Opt redoutclim;
792   Opt redoutvlim;
793   Opt reduce;
794   Opt rephase;
795   Opt rephaseinc;
796   Opt restart;
797   Opt restartinit;
798   Opt restartint;
799   Opt restartintscale;
800   Opt reusetrail;
801   Opt rmincpen;
802   Opt rstinoutinc;
803   Opt saturating;
804   Opt scincinc;
805   Opt score;
806   Opt seed;
807   Opt simpdelay;
808   Opt simpen;
809   Opt simpidiv;
810   Opt simpinterdelay;
811   Opt simpiscale;
812   Opt simplify;
813   Opt simprtc;
814   Opt simpvarchg;
815   Opt simpvarlim;
816   Opt sizemaxpen;
817   Opt sizepen;
818   Opt sleeponabort;
819   Opt smallirr;
820   Opt smallve;
821   Opt smallvevars;
822   Opt smallvewait;
823   Opt sortlits;
824   Opt subl;
825   Opt synclsall;
826   Opt synclsglue;
827   Opt synclsint;
828   Opt synclslen;
829   Opt syncunint;
830   Opt tabr;
831   Opt tabrcfactor;
832   Opt tabrkeep;
833   Opt tabrvfactor;
834   Opt termint;
835   Opt ternres;
836   Opt ternresboost;
837   Opt ternresrtc;
838   Opt ternreswait;
839   Opt transred;
840   Opt transredwait;
841   Opt trdmaxeff;
842   Opt trdmineff;
843   Opt trdreleff;
844   Opt treelook;
845   Opt treelookboost;
846   Opt treelookfull;
847   Opt treelooklrg;
848   Opt treelookmaxeff;
849   Opt treelookmineff;
850   Opt treelookreleff;
851   Opt treelookrtc;
852   Opt trep;
853   Opt trepint;
854   Opt trnreleff;
855   Opt trnrmaxeff;
856   Opt trnrmineff;
857   Opt unhdatrn;
858   Opt unhdextstamp;
859   Opt unhdhbr;
860   Opt unhdlnpr;
861   Opt unhdmaxeff;
862   Opt unhdmineff;
863   Opt unhdreleff;
864   Opt unhdroundlim;
865   Opt unhide;
866   Opt unhidewait;
867   Opt wait;
868   Opt waitmax;
869   Opt witness;
870
871   Opt check;
872   Opt log;
873   Opt verbose;
874
875   Opt afterlast;
876
877 } Opts;
878
879 #define FIRSTOPT(lgl) (&(lgl)->opts->beforefirst + 1)
880 #define LASTOPT(lgl) (&(lgl)->opts->afterlast - 1)
881
882 /*------------------------------------------------------------------------*/
883
884 typedef int Exp;
885 typedef uint64_t Mnt;
886 typedef int64_t Flt;
887 typedef int64_t Cnf;
888 typedef uint64_t Fun[FUNQUADS];
889 typedef signed char Val;
890 typedef Flt LKHD;
891
892 /*------------------------------------------------------------------------*/
893 #ifdef NDBLSCR
894 typedef Flt Scr;
895 #else
896 typedef double Scr;
897 #endif
898 /*------------------------------------------------------------------------*/
899
900 typedef struct Conf { int lit, rsn[2]; } Conf;
901 typedef struct Ctk { struct Ctr * start, * top, * end; } Ctk;
902 typedef struct DFOPF { int observed, pushed, flag; } DFOPF;
903 typedef struct DFPR { int discovered, finished, parent, root; } DFPR;
904 typedef struct EVar { int occ[2], pos, score; } EVar;
905 typedef struct Ftk { Flt * start, * top, * end; } Ftk;
906 typedef struct HTS { int offset, count; }  HTS;
907 typedef struct ITEC { int other, other2; } ITEC;
908 typedef struct Lim { int64_t confs, decs, props; } Lim;
909 typedef struct PASL { int psm, act, size, lidx; } PASL;
910 typedef struct PSz { int pos, size; } PSz;
911 typedef struct Qnd { int prev, next; struct Qln * line; } Qnd;
912 typedef struct RNG { unsigned z, w; } RNG;
913 typedef struct Stk { int * start, * top, * end; } Stk;
914 typedef struct Tmrs { double phase[MAXPHN]; int idx[MAXPHN], nest; } Tmrs;
915 typedef struct Trv { void * state; void (*trav)(void *, int); } Trv;
916 typedef struct TVar { signed int val : 30; unsigned mark : 2; } TVar;
917 typedef struct Wtk { struct Work * start, * top, * end; } Wtk;
918
919 /*------------------------------------------------------------------------*/
920
921 typedef struct Ctr { 
922   signed int decision : 31; 
923   unsigned used : 1;
924 } Ctr;
925
926 typedef struct DVar { HTS hts[2]; } DVar;
927
928 typedef struct QVar { Scr score; int pos; } QVar;
929
930 typedef struct TD {
931   signed int level:30;
932   unsigned lrglue:1, irr:1; 
933   int rsn[2];
934 } TD;
935
936 typedef struct ID { int level, lit, rsn[2]; } ID;
937
938 typedef struct Impls { ID * start, * top, * end; } Impls;
939
940 typedef struct AVar {
941   unsigned type : 4;
942 #ifndef NDEBUG
943   unsigned simp:1, wasfalse:1;
944 #endif
945   unsigned equiv:1, lcamark:4;
946   signed int phase:2, bias:2, fase:2;
947   unsigned inred:2, poisoned:1, assumed:2, failed:2, gate:1;
948   unsigned donotelm:1, donotblk:1, donotcgrcls:1, donotlft:1, donoternres:1;
949   unsigned donotbasicprobe:1, donotsimpleprobe:1, donotreelook:1, mega:2;
950 #ifndef NLGLYALSAT
951   signed int locsval:2;
952 #endif
953   int mark, trail;
954 } AVar;
955
956 typedef struct Ext {
957   unsigned equiv:1,melted:1,blocking:2,eliminated:1,tmpfrozen:1,imported:1;
958   unsigned assumed:2,failed:2,internal:1,defined:1;
959   signed int val:2, oldval:2;
960   int repr, frozen;
961 } Ext;
962
963 typedef struct Work {
964   unsigned wrag : 2;
965   signed int lit : 30, other : 30;
966   unsigned red : 1, removed : 1;
967 } Work;
968
969 typedef struct DFL {
970   int discovered, finished;
971   union { int lit, sign; };
972 #ifndef NLGLOG
973   int lit4logging;
974 #endif
975 } DFL;
976
977 typedef struct Gat {
978   int lhs, minrhs;
979   unsigned tag : 2;
980   unsigned mark : 1;
981   signed int size : 29;
982   union {
983     int lits[2];
984     struct { int * cls, origlhs; };
985     struct { int cond, pos, neg; };
986   };
987 } Gat;
988
989 /*------------------------------------------------------------------------*/
990
991 typedef struct Stats {
992   int64_t steps, trims;
993   int defrags, iterations, acts, reported, repcntdown, gcs, decomps;
994   int cutwidths;
995   struct { int64_t count, steps; struct { int max, min; } mincut; } force;
996   struct { int clauses, vars; } rescored;
997   struct { int count;
998            struct {int64_t scaled, orig; } intsum;
999            struct { int count, saturating, agile, reuse; } skipped;
1000            struct { int count; int64_t sum; } kept; } restarts;
1001   struct { int count, reset, geom, gul, arith, arith2, memlim; } reduced;
1002   int64_t prgss, irrprgss, enlwchs, pshwchs, height, dense, sparse;
1003   int64_t confs, decisions, randecs, randecsflipped, flipped, fliphases;
1004   int64_t uips, decflipped;
1005   struct { struct { int cur, max; int64_t add; } clauses, lits; } irr;
1006   struct { int64_t sat, mosat, simp, deref, fixed, freeze, lkhd;
1007            int64_t melt, add, assume, cassume, failed, repr; } calls;
1008   struct { int64_t search, hits; } poison;
1009   struct { int64_t search, simp, lkhd; } props, visits, travs;
1010   struct { size_t current, max; } bytes;
1011   struct { int bin, trn, lrg; } red;
1012   struct { int cnt, simple, trn, lrg, sub; } hbr;
1013   struct { int current, sum; } fixed, equiv;
1014   struct { int count, bin, trn; int64_t steps; } trnr;
1015   struct { int count, clauses, lits, pure; int64_t res, steps; } blk;
1016   struct { int count, eq, units; int64_t esteps, csteps;
1017            struct { int all, and, xor, ite; } matched;
1018            struct { int all, and, xor, ite; } simplified;
1019            struct { int64_t all, and, xor, ite; } extracted; } cgr;
1020   struct {
1021     struct { int count, failed, eqs; int64_t probed, steps; } simple;
1022     struct { int count, failed, lifted; 
1023              int64_t probed, steps, lastate;
1024              struct { int trnr, lrg, count; } ate; } basic;
1025     struct { int count, failed, lifted; int64_t probed, steps; } treelook;
1026   } prb;
1027   struct { int count, eqs, units, impls; int64_t probed0, probed1; } lift;
1028   struct { int count, red, failed; int64_t lits, bins, steps; } trd;
1029   struct { int removed, red; } bindup;
1030   struct { int count, rounds;
1031            struct { int trds, failed, sccs; int64_t sumsccsizes; } stamp;
1032            struct { int lits, bin, trn, lrg; } failed;
1033            struct { int bin, trn, lrg, red; } tauts;
1034            struct { int bin, trn, lrg; } units;
1035            struct { int trn, lrg, red; } hbrs;
1036            struct { int trn, lrg, red; } str;
1037            int64_t steps; } unhd;
1038   struct {
1039     int count, elmd, large, sub, str, blkd, rounds;
1040     struct { int elm, tried, failed; } small;
1041     int64_t resolutions, copies, subchks, strchks, ipos, steps; } elm;
1042   struct {
1043     int sub2, sub3, subl, str2, str3, str3self, strl, strlself;
1044     struct { int64_t lits, clauses, occs; } tried;
1045     int64_t steps;
1046   } bkwd;
1047   struct {
1048     struct { struct { int irr, red; } dyn; } sub, str;
1049     int64_t driving, restarting; } otfs;
1050   struct { int64_t nonmin, learned; } lits;
1051   struct { 
1052     int64_t learned, glue, realglue, nonmaxglue, maxglue, scglue; }
1053   clauses;
1054   struct {
1055     int clauses;
1056     int64_t added, reduced, resolved, forcing, conflicts, saved;
1057   } lir[POW2GLUE];
1058   struct { int64_t sum; int count; } glues;
1059   struct { int count; int64_t set, pos, neg; } phase;
1060   struct { int count; struct { int confs, irr, vars; } limhit; } simp;
1061   struct { int count; int64_t steps; } luby, inout;
1062   struct { int count, gcs, units, equivs, trneqs; 
1063            struct { int max; int64_t sum; } arity; 
1064            struct { int64_t extr, elim; } steps;
1065            int64_t extracted; } gauss;
1066   struct { int count, eliminated, ate, abce, failed, lifted;
1067            int64_t steps, probed;
1068            struct { int64_t search, hits, cols, ins, rsz; } cache; } cce;
1069   struct { int count, failed, lifted; int64_t decisions, steps; } cliff;
1070   struct { 
1071     int count, units, expam1, resched;
1072     int64_t steps, eliminated, resolved, subsumed;
1073     struct { struct { int64_t sum, cnt; } found, used; } am1, am2; } card;
1074   struct { int64_t bin, trn, lrg; } moved;
1075   struct { int count, inc; } rephase;
1076   struct { int count; int64_t added, skipped, steps; } bca;
1077   struct { int count; int64_t added, removed; } bva;
1078   struct { 
1079     struct {
1080       int64_t produced; 
1081       struct { int64_t actual, tried, calls; } consumed;
1082     } cls, units;
1083   } sync;
1084   struct { struct { int64_t orig, red; } sum; } deco;
1085   struct { int64_t min, bin, size, deco; } mincls;
1086   int64_t drupped, druplig;
1087   struct {
1088     int64_t count, units, bin, trn, steps, elim, res;
1089     struct { int64_t bound, len, model; } limhit; } rdp;
1090   struct { int64_t count, tried, cands, sub; } subl;
1091   struct { int count; int64_t flips, mems; int min; } locs;
1092   struct { int count; } tabr;
1093   struct { int count, failed, lifted, eqs, rounds; } mega;
1094 } Stats;
1095
1096 /*------------------------------------------------------------------------*/
1097
1098 typedef struct Times {
1099   double all, dcp, elm, trd, gc, dfg, red, blk, ana, unhd, dec, lkhd;
1100   double rsts, lft, trn, cgr, phs, srch, prep, inpr, bump, mcls, gauss;
1101   double card, cce, cliff, ctw, force, bca, rdp, locs, bkwd, bva, tabr;
1102   double mega;
1103   struct { double all, simple, basic, treelook; } prb;
1104 } Times;
1105
1106 /*------------------------------------------------------------------------*/
1107
1108 typedef struct Del { int cur, rem; } Del;
1109
1110 typedef struct Limits {
1111   int flipint, lkhdpen;
1112   int64_t randec, dfg;
1113   struct {
1114     int64_t visits;
1115     struct { int64_t add; int start; } clauses;
1116     struct { int start; } vars;
1117   } inc;
1118   struct { int clauses, vars; } tabr;
1119   struct { int inner, outer, extra; } reduce;
1120   struct { struct { int64_t otfs, confs; } vars; } rescore;
1121   struct { int pen; Del del; int64_t esteps, csteps; } cgr;
1122   struct { int pen; Del del; int64_t steps, irrprgss; } elm, blk, cliff;
1123   struct { int pen; Del del; int64_t steps; }
1124     rdp, trd, unhd, trnr, lft, cce, card;
1125   struct { int pen; Del del; struct { int64_t extr, elim; } steps; } gauss;
1126   struct { int64_t confs; } rephase;
1127   struct { int64_t confs; int wasmaxdelta, maxdelta, luby, inout; } restart;
1128   struct { int64_t steps; 
1129            struct { int pen; Del del; } simple, basic, treelook; } prb;
1130   struct { int64_t vars, confs; int pen, cinc; } simp;
1131   struct { int64_t steps, confs; } sync;
1132   struct { int64_t steps; } term;
1133   struct { int64_t fixed; } gc;
1134   struct { Del del; int64_t steps; } bca;
1135   struct { int64_t steps, time; } trep;
1136   struct { int64_t confs, inc; int vars; } locs;
1137 } Limits;
1138
1139 /*------------------------------------------------------------------------*/
1140
1141 typedef struct Cbs {
1142   struct { int (*fun)(void*); void * state; int done; } term;
1143   struct {
1144     struct { void (*fun)(void*,int); void * state; } produce, consumed;
1145     struct { void(*fun)(void*,int**,int**); void*state; } consume;
1146   } units;
1147   struct {
1148     struct { void (*fun)(void*,int*,int); void * state; } produce;
1149     struct { void(*fun)(void*,int**,int*); void*state; } consume;
1150     struct { void (*fun)(void*,int); void * state; } consumed;
1151   } cls;
1152   struct {
1153     struct { int * (*fun)(void*); void * state; } lock;
1154     struct { void (*fun)(void*,int,int); void * state; } unlock;
1155   } eqs;
1156   struct { void(*lock)(void*); void (*unlock)(void*); void*state; } msglock;
1157   double (*getime)(void);
1158   void (*onabort)(void *); void * abortstate;
1159 } Cbs;
1160
1161 typedef struct Cgr {
1162   struct { int units, eq, all, and, xor, ite, org; } extracted;
1163   struct { int all, and, xor, ite, org; } simplified;
1164   struct { int all, and, xor, ite, org; } matched;
1165   Stk * goccs, units; Gat * gates; int szgates;
1166 } Cgr;
1167
1168 typedef struct Cliff { Stk lift, lits; } Cliff;
1169
1170 typedef struct BCA { Stk covered; } BCA;
1171
1172 typedef struct Dis { struct { Stk bin, trn; } red, irr; } Dis;
1173
1174 typedef struct Elm {
1175   int64_t oldsteps;
1176   int pivot, negcls, necls, neglidx, round, oldelmd;
1177   Stk lits, next, clv, csigs, sizes, occs, noccs, mark, m2i;
1178 } Elm;
1179
1180 typedef struct RDP {
1181   int * count, eliminated;
1182   Stk lits, * occs;
1183   double start;
1184 } RDP;
1185
1186 typedef struct Card {
1187   Stk atmost1, atmost2, cards, elim, * occs, units, expam1;
1188   char * eliminated, * lit2used, * marked;
1189   signed char * count;
1190   int * lit2count;
1191 } Card;
1192
1193 typedef struct FltStr { int current; char str[MAXFLTSTR][100]; } FltStr;
1194
1195 typedef struct SPE { signed int count : 31; unsigned mark : 1, sum; } SPE;
1196
1197 typedef struct SPrb { 
1198   Stk units, impls, eqs, counted, marked;
1199   SPE * spes;
1200 } SPrb;
1201
1202 typedef struct Gauss { 
1203   Stk xors, order, * occs; 
1204   signed char * eliminated;
1205   int garbage, next; 
1206 } Gauss;
1207
1208 typedef struct CCE {
1209   Stk cla, extend, clauses;
1210   int * rem, bin, trn;
1211 } CCE;
1212
1213 typedef struct Tlk { Stk stk, seen; TVar * tvars; LKHD * lkhd; } Tlk;
1214
1215 typedef struct Mem {
1216   void * state;
1217   lglalloc alloc; lglrealloc realloc; lgldealloc dealloc;
1218 } Mem;
1219
1220 typedef struct Wchs { Stk stk; int start[MAXLDFW], free; } Wchs;
1221
1222 typedef struct Wrk {
1223   Stk queue;
1224   int count, head, size, posonly, fifo, * pos;
1225 } Wrk;
1226
1227 /*------------------------------------------------------------------------*/
1228
1229 struct LGL {
1230   State state;
1231
1232   int probing, flipping, notflipped, tid, tids, bias, phaseneg;
1233   int nvars, szvars, maxext, szext, maxdef, szdef, changed, mt, repcntdown;
1234   int szdrail, bnext, next, next2, flushed, level, alevel, wait;
1235   int unassigned, lrgluereasons, failed, assumed, cassumed, ncassumed;
1236
1237   Scr scinc, scincf, maxscore;
1238
1239   char lifting, cceing, gaussing, cliffing, bcaing, forcerephead;
1240   char cgrclosing, searching, simp, allphaseset, flushphases, occs;
1241   char unhiding, basicprobing, simpleprobing, treelooking, setuponce;
1242   char eliminating, donotsched, blocking, ternresing, lkhd, allfrozen;
1243   char blkall, blkrem, blkrtc, elmall, elmrem, elmrtc, decomposing;
1244   char frozen, dense, notfullyconnected, forcegc, allowforce;
1245   char ccertc, elmstuck, blkstuck;
1246
1247   LGL * parent;
1248   int forked;
1249
1250   unsigned long long flips;
1251
1252   Conf conf;
1253   RNG rng;
1254
1255   // the state above this line is copied during 'clone' with 'memcpy'
1256
1257   Mem * mem;
1258   Opts * opts;
1259   Stats * stats;
1260   Times * times;
1261   Tmrs * timers;
1262   Limits * limits;
1263   Ext * ext, * def;
1264   int * i2e;
1265   int * doms;
1266   DVar * dvars;
1267   QVar * qvars;
1268   AVar * avars;
1269   Val * vals;
1270   Flt * jwh;
1271   TD * drail;
1272   Stk * red;
1273   Wchs * wchs;
1274
1275   Ctk control;
1276   Stk clause, eclause, extend, irr, trail, frames;
1277   Stk dsched, eassume, assume, cassume, fassume, learned;
1278 #ifndef NCHKSOL
1279   Stk orig;
1280 #endif
1281
1282   union {
1283     Elm * elm; Cgr * cgr; SPrb * sprb; Tlk * tlk; Gauss * gauss;
1284     CCE * cce; Cliff * cliff; BCA * bca; Card * card; RDP * rdp;
1285   };
1286   union { Stk lcaseen, sortstk, resolvent; };
1287   Stk poisoned, seen, esched, minstk;
1288   EVar * evars;
1289   Dis * dis;
1290   Wrk * wrk;
1291   int * repr;
1292
1293   char closeapitrace;
1294   FILE * out, * apitrace;
1295   char * prefix;
1296   Cbs * cbs;
1297
1298   LGL * clone;
1299
1300   FltStr * fltstr;
1301 #if !defined(NLGLPICOSAT)
1302   struct { PicoSAT * solver; int res; char chk; } picosat;
1303 #endif
1304 #if !defined(NLGLDRUPLIG)
1305   Druplig * druplig;
1306 #endif
1307 };
1308
1309 /*-------------------------------------------------------------------------*/
1310
1311 #define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
1312
1313 static const char lglfloorldtab[256] =
1314 {
1315 // 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
1316   -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
1317   LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
1318   LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
1319 };
1320
1321 static const uint64_t lglbasevar2funtab[6] = {
1322   0xaaaaaaaaaaaaaaaaull, 0xccccccccccccccccull, 0xf0f0f0f0f0f0f0f0ull,
1323   0xff00ff00ff00ff00ull, 0xffff0000ffff0000ull, 0xffffffff00000000ull,
1324 };
1325
1326 /*-------------------------------------------------------------------------*/
1327
1328 static int lglfloorld (int n) {
1329   assert (n >= 0);
1330   if (n < (1<<8)) return lglfloorldtab[n];
1331   if (n < (1<<16)) return 8 + lglfloorldtab[n>>8];
1332   if (n < (1<<24)) return 16 + lglfloorldtab[n>>16];
1333   return 24 + lglfloorldtab[n>>24];
1334 }
1335
1336 static int lglispow2 (int n) {
1337   assert (0 <= n && n <= INT_MAX);
1338   return !(n & (n - 1));
1339 }
1340
1341 static int lglceilld (int n) {
1342   int res = lglfloorld (n);
1343   if (!lglispow2 (n)) res++;
1344   return res;
1345 }
1346
1347 static int lglceilsqrt32 (int x) {
1348   int l = 0, m, r, mm, rr;
1349 #ifndef NDEBUG
1350   int ll = 0;
1351 #endif
1352   if (x <= 0) return 0;
1353   r = 46340; rr = r*r;
1354   if (x >= rr) return r;
1355   for (;;) {
1356     assert (l < r);
1357     assert (ll < x && x < rr);
1358     if (r - l == 1) return r;
1359     m = (l + r)/2;
1360     mm = m*m;
1361     if (mm == x) return m;
1362     if (mm < x) {
1363       l = m;
1364 #ifndef NDEBUG
1365       ll = mm;
1366 #endif
1367     } else r = m, rr = mm;
1368   }
1369 }
1370
1371 static int lglceilsqrt64 (int x) {
1372   int64_t l = 0, m, r, mm, rr;
1373 #ifndef NDEBUG
1374   int64_t ll = 0;
1375 #endif
1376   if (x <= 0) return 0;
1377   r = 3037000499ll; rr = r*r;
1378   if (x >= rr) return r;
1379   for (;;) {
1380     assert (l < r);
1381     assert (ll < x && x < rr);
1382     if (r - l == 1) return r;
1383     m = (l + r)/2;
1384     mm = m*m;
1385     if (mm == x) return m;
1386     if (mm < x) {
1387       l = m;
1388 #ifndef NDEBUG
1389       ll = mm;
1390 #endif
1391     } else r = m, rr = mm;
1392   }
1393 }
1394
1395 static void lglchkflt (Flt a) {
1396 #ifndef NDEBUG
1397   assert (a >= 0);
1398   assert (FLTMAX >= (uint64_t) a);
1399 #else
1400   (void) a;
1401 #endif
1402 }
1403
1404 static Exp lglexp (Flt a) {
1405   Exp res = a >> FLTPRC;
1406   assert (0 <= res && res <= EXPMAX);
1407   res -= EXPZRO;
1408   return res;
1409 }
1410
1411 static Mnt lglmnt (Flt a) {
1412   Mnt res = a & MNTMAX;
1413   res |= MNTBIT;
1414   assert (res <= MNTMAX);
1415   return res;
1416 }
1417
1418 static Flt lglflt (Exp e, Mnt m) {
1419   Flt res;
1420   if (!m) return FLTMIN;
1421   if (m < MNTBIT) {
1422     while (!(m & MNTBIT)) {
1423       m <<= 1;
1424       if (e > INT_MIN) e--;
1425       else break;
1426     }
1427   } else {
1428     while (m > MNTMAX) {
1429        m >>= 1;
1430        if (e > INT_MIN) e++;
1431        else break;
1432     }
1433   }
1434   if (e < -EXPZRO) return FLTMIN;
1435   if (e > EXPMAX - EXPZRO) return FLTMAX;
1436   e += EXPZRO;
1437   assert (0 <= e && e <= EXPMAX);
1438   assert (m <= MNTMAX);
1439   assert (m & MNTBIT);
1440   res = m & ~MNTBIT;
1441   res |= ((Flt)e) << FLTPRC;
1442   return res;
1443 }
1444
1445 #ifdef NDBLSCR
1446 static Flt lglrat (unsigned n, unsigned d) {
1447   Mnt m;
1448   Exp e;
1449   if (!n) return FLTMIN;
1450   if (!d) return FLTMAX;
1451   m = n;
1452   e = 0;
1453   while (!(m & (1ull << 63))) m <<= 1, e--;
1454   m /= d;
1455   return lglflt (e, m);
1456 }
1457 #endif
1458
1459 #ifndef NDEBUG
1460 double lglflt2dbl (Flt a) {
1461   return lglmnt (a) * pow (2.0, lglexp (a));
1462 }
1463 #endif
1464
1465 #ifdef NDBLSCR
1466 static const char * lgll2str (LGL * lgl, Flt a) {
1467   assert (lgl->fltstr);
1468   lgl->fltstr->current++;
1469   if (lgl->fltstr->current == MAXFLTSTR) lgl->fltstr->current = 0;
1470   sprintf (lgl->fltstr->str[lgl->fltstr->current], "%lld", (LGLL) a);
1471   return lgl->fltstr->str[lgl->fltstr->current];
1472 }
1473 #endif
1474
1475 static const char * lglflt2str (LGL * lgl, Flt a) {
1476   double d, e;
1477   assert (lgl->fltstr);
1478   if (a == FLTMIN) return "0";
1479   if (a == FLTMAX) return "inf";
1480   d = lglmnt (a);
1481   d /= 4294967296ll;
1482   e = lglexp (a);
1483   e += 32;
1484   lgl->fltstr->current++;
1485   if (lgl->fltstr->current == MAXFLTSTR) lgl->fltstr->current = 0;
1486   sprintf (lgl->fltstr->str[lgl->fltstr->current], "%.6fd%+03.0f", d, e);
1487   return lgl->fltstr->str[lgl->fltstr->current];
1488 }
1489
1490 static Flt lgladdflt (Flt a, Flt b) {
1491   Exp e, f, g;
1492   Mnt m, n, o;
1493   lglchkflt (a);
1494   lglchkflt (b);
1495   if (a == FLTMAX) return FLTMAX;
1496   if (b == FLTMAX) return FLTMAX;
1497   if (a == FLTMIN) return b;
1498   if (b == FLTMIN) return a;
1499   e = lglexp (a);
1500   f = lglexp (b);
1501   if (e < f) g = e, e = f, f = g, o = a, a = b, b = o;
1502   m = lglmnt (a);
1503   n = lglmnt (b);
1504   m += n >> (e - f);
1505   return lglflt (e, m);
1506 }
1507
1508 static Flt lglmulflt (Flt a, Flt b) {
1509   Exp e, ea, eb;
1510   Mnt m, ma, mb;
1511   lglchkflt (a);
1512   lglchkflt (b);
1513   if (a == FLTMAX) return FLTMAX;
1514   if (b == FLTMAX) return FLTMAX;
1515   if (a == FLTMIN) return FLTMIN;
1516   if (b == FLTMIN) return FLTMIN;
1517   ea = lglexp (a); eb = lglexp (b);
1518   if (ea > 0 && eb > 0 && (INT_MAX - ea < eb)) return FLTMAX;
1519   e = ea + eb;
1520   if (e > EXPMAX - EXPZRO - 32) return FLTMAX;
1521   e += 32;
1522   ma = lglmnt (a); mb = lglmnt (b);
1523   ma >>= 1; mb >>= 1;
1524   m = ma * mb;
1525   assert (3ull << 62);
1526   m >>= 30;
1527   return lglflt (e, m);
1528 }
1529
1530 #ifdef NDBLSCR
1531 static Flt lglshflt (Flt a, int s) {
1532   Exp e;
1533   Mnt m;
1534   if (a == FLTMAX) return FLTMAX;
1535   if (a == FLTMIN) return FLTMIN;
1536   assert (0 <= s);
1537   e = lglexp (a);
1538   if (e < INT_MIN + s) return FLTMIN;
1539   e -= s;
1540   m = lglmnt (a);
1541   return lglflt (e, m);
1542 }
1543 #endif
1544
1545 /*------------------------------------------------------------------------*/
1546 #ifdef NDBLSCR
1547
1548 static const char * lglscr2str (LGL * lgl, Scr scr) {
1549   if (lgl->opts->score.val == LGL_SCORE_EVSIDS ||
1550       lgl->opts->score.val == LGL_SCORE_AVG) return lglflt2str (lgl, scr);
1551   else return lgll2str (lgl, scr);
1552 }
1553
1554 static Scr lgladdscr (Scr a, Scr b) { return lgladdflt (a, b); }
1555 static Scr lglmulscr (Scr a, Scr b) { return lglmulflt (a, b); }
1556
1557 #else /* !NDBLSCR */
1558
1559 static const char * lgldbl2str (LGL * lgl, double d) {
1560   assert (lgl->fltstr);
1561   lgl->fltstr->current++;
1562   if (lgl->fltstr->current == MAXFLTSTR) lgl->fltstr->current = 0;
1563   sprintf (lgl->fltstr->str[lgl->fltstr->current], "%g", d);
1564   return lgl->fltstr->str[lgl->fltstr->current];
1565 }
1566
1567 static const char * lglscr2str (LGL * lgl, Scr scr) {
1568   return lgldbl2str (lgl, scr);
1569 }
1570
1571 static Scr lgladdscr (Scr a, Scr b) { return a + b; }
1572 static Scr lglmulscr (Scr a, Scr b) { return a * b; }
1573
1574 #endif
1575 /*------------------------------------------------------------------------*/
1576
1577 static void lglwrn (LGL * lgl, const char * msg, ...) {
1578   va_list ap;
1579   fprintf (lgl->out, "*** warning in '%s': ", __FILE__);
1580   va_start (ap, msg);
1581   vfprintf (lgl->out, msg, ap);
1582   va_end (ap);
1583   fputc ('\n', lgl->out);
1584   fflush (lgl->out);
1585 }
1586
1587 static void lgldie (LGL * lgl, const char * msg, ...) {
1588   va_list ap;
1589   fprintf (lgl->out, "*** internal error in '%s': ", __FILE__);
1590   va_start (ap, msg);
1591   vfprintf (lgl->out, msg, ap);
1592   va_end (ap);
1593   fputc ('\n', lgl->out);
1594   fflush (lgl->out);
1595   exit (0);
1596 }
1597
1598 static void lglabort (LGL * lgl) {
1599   if (!lgl) exit (1);
1600   if (lgl->opts && lgl->opts->sleeponabort.val) {
1601     fprintf (stderr,
1602 "liblgl.a: Process %d will sleep for %d seconds "
1603 " before continuing with 'lglabort' procedure.\n",
1604       getpid (), lgl->opts->sleeponabort.val);
1605     sleep (lgl->opts->sleeponabort.val);
1606   }
1607   if (lgl->cbs && lgl->cbs->onabort)
1608     lgl->cbs->onabort (lgl->cbs->abortstate);
1609   if (lgl->opts && lgl->opts->exitonabort.val) exit (1);
1610   abort ();
1611 }
1612
1613 static const char * lglprefix (LGL * lgl) {
1614   return lgl && lgl->prefix ? lgl->prefix : "c (LGL HAS NO PREFIX YET) ";
1615 }
1616
1617 static int lglmsgstart (LGL * lgl, int level) {
1618 #ifndef NLGLOG
1619   if (lgl->opts->log.val <= 0)
1620 #endif
1621   if (lgl->opts->verbose.val < level) return 0;
1622   if (lgl->cbs && lgl->cbs->msglock.lock)
1623     lgl->cbs->msglock.lock (lgl->cbs->msglock.state);
1624   fputs (lglprefix (lgl), lgl->out);
1625   if (lgl->tid >= 0) fprintf (lgl->out, "%d ", lgl->tid);
1626   return 1;
1627 }
1628
1629 static void lglmsgend (LGL * lgl) {
1630   fputc ('\n', lgl->out);
1631   fflush (lgl->out);
1632   if (lgl->cbs && lgl->cbs->msglock.unlock)
1633     lgl->cbs->msglock.unlock (lgl->cbs->msglock.state);
1634 }
1635
1636 static void lglprt (LGL * lgl, int level, const char * msg, ...) {
1637   va_list ap;
1638 #ifndef NLGLOG
1639   if (lgl->opts->log.val <= 0)
1640 #endif
1641   if (lgl->opts->verbose.val < level) return;
1642   lglmsgstart (lgl, level);
1643   va_start (ap, msg);
1644   vfprintf (lgl->out, msg, ap);
1645   va_end (ap);
1646   lglmsgend (lgl);
1647 }
1648
1649 #ifndef NLGLOG
1650 static void lglogstart (LGL * lgl, int level, const char * msg, ...) {
1651   va_list ap;
1652   assert (lgl->opts->log.val >= level);
1653   if (lgl->cbs && lgl->cbs->msglock.lock)
1654     lgl->cbs->msglock.lock (lgl->cbs->msglock.state);
1655   fputs (lglprefix (lgl), lgl->out);
1656   if (lgl->tid >= 0) fprintf (lgl->out, "%d ", lgl->tid);
1657   fprintf (lgl->out, "LOG%d %d ", level, lgl->level);
1658   va_start (ap, msg);
1659   vfprintf (lgl->out, msg, ap);
1660   va_end (ap);
1661 }
1662
1663 #define lglogend lglmsgend
1664 #endif
1665
1666 /*------------------------------------------------------------------------*/
1667
1668 void lglsetid (LGL * lgl, int tid, int tids) {
1669   REQINITNOTFORKED ();
1670   ABORTIF (tid < 0, "negative id");
1671   ABORTIF (tid >= tids, "id exceed number of ids");
1672   lgl->tid = tid;
1673   lgl->tids = tids;
1674 }
1675
1676 /*------------------------------------------------------------------------*/
1677
1678 static void lglinc (LGL * lgl, size_t bytes) {
1679   lgl->stats->bytes.current += bytes;
1680   if (lgl->stats->bytes.max < lgl->stats->bytes.current) {
1681     lgl->stats->bytes.max = lgl->stats->bytes.current;
1682     LOG (5, "maximum allocated %ld bytes", lgl->stats->bytes.max);
1683   }
1684 }
1685
1686 static void lgldec (LGL * lgl, size_t bytes) {
1687   assert (lgl->stats->bytes.current >= bytes);
1688   lgl->stats->bytes.current -= bytes;
1689 }
1690
1691 static void * lglnew (LGL * lgl, size_t bytes) {
1692   void * res;
1693   if (!bytes) return 0;
1694   if (lgl->mem->alloc) res = lgl->mem->alloc (lgl->mem->state, bytes);
1695   else res = malloc (bytes);
1696   if (!res) lgldie (lgl, "out of memory allocating %ld bytes", bytes);
1697   assert (res);
1698   LOG (5, "allocating %p with %ld bytes", res, bytes);
1699   lglinc (lgl, bytes);
1700   if (res) memset (res, 0, bytes);
1701   return res;
1702 }
1703
1704 static void lgldel (LGL * lgl, void * ptr, size_t bytes) {
1705   if (!ptr) { assert (!bytes); return; }
1706   lgldec (lgl, bytes);
1707   LOG (5, "freeing %p with %ld bytes", ptr, bytes);
1708   if (lgl->mem->dealloc) lgl->mem->dealloc (lgl->mem->state, ptr, bytes);
1709   else free (ptr);
1710 }
1711
1712 static void * lglrsz (LGL * lgl, void * ptr, size_t old, size_t new) {
1713   void * res;
1714   assert (!ptr == !old);
1715   if (!ptr) return lglnew (lgl, new);
1716   if (!new) { lgldel (lgl, ptr, old); return 0; }
1717   if (old == new) return ptr;
1718   lgldec (lgl, old);
1719   if (lgl->mem->realloc)
1720     res = lgl->mem->realloc (lgl->mem->state, ptr, old, new);
1721   else res = realloc (ptr, new);
1722   if (!res)
1723     lgldie (lgl, "out of memory reallocating %ld to %ld bytes", old, new);
1724   assert (res);
1725   LOG (5, "reallocating %p to %p from %ld to %ld bytes", ptr, res, old, new);
1726   lglinc (lgl, new);
1727   if (new > old) memset (res + old, 0, new - old);
1728   return res;
1729 }
1730
1731 /*------------------------------------------------------------------------*/
1732
1733 static char * lglstrdup (LGL * lgl, const char * str) {
1734   char * res;
1735   NEW (res, strlen (str) + 1);
1736   return strcpy (res, str);
1737 }
1738
1739 static void lgldelstr (LGL * lgl, char * str) {
1740   DEL (str, strlen (str) + 1);
1741 }
1742
1743 /*------------------------------------------------------------------------*/
1744
1745 static void lglinitcbs (LGL * lgl) {
1746   if (!lgl->cbs) NEW (lgl->cbs, 1);
1747 }
1748
1749 void lglonabort (LGL * lgl, void * abortstate, void (*onabort)(void*)) {
1750   REQINITNOTFORKED ();
1751   lglinitcbs (lgl);
1752   lgl->cbs->abortstate = abortstate;
1753   lgl->cbs->onabort = onabort;
1754 }
1755
1756 void lglseterm (LGL * lgl, int (*fun)(void*), void * state) {
1757   REQINITNOTFORKED ();
1758   lglinitcbs (lgl);
1759   lgl->cbs->term.fun = fun;
1760   lgl->cbs->term.state = state;
1761 }
1762
1763 void lglsetproduceunit (LGL * lgl, void (*fun) (void*, int), void * state) {
1764   REQINITNOTFORKED ();
1765   lglinitcbs (lgl);
1766   lgl->cbs->units.produce.fun = fun;
1767   lgl->cbs->units.produce.state = state;
1768 }
1769
1770 void lglsetconsumeunits (LGL * lgl,
1771                          void (*fun) (void*, int **, int **),
1772                          void * state) {
1773   REQINITNOTFORKED ();
1774   lglinitcbs (lgl);
1775   lgl->cbs->units.consume.fun =  fun;
1776   lgl->cbs->units.consume.state = state;
1777 }
1778
1779 void lglsetconsumedunits (LGL * lgl,
1780                           void (*fun) (void*, int), void * state) {
1781   REQINITNOTFORKED ();
1782   lglinitcbs (lgl);
1783   lgl->cbs->units.consumed.fun = fun;
1784   lgl->cbs->units.consumed.state = state;
1785 }
1786
1787 void lglsetproducecls (LGL * lgl, 
1788                        void (*fun) (void*, int *, int), void * state) {
1789   REQINITNOTFORKED ();
1790   lglinitcbs (lgl);
1791   lgl->cbs->cls.produce.fun = fun;
1792   lgl->cbs->cls.produce.state = state;
1793 }
1794
1795 void lglsetconsumecls (LGL * lgl,
1796                        void (*fun) (void*, int **, int *),
1797                        void * state) {
1798   REQINITNOTFORKED ();
1799   lglinitcbs (lgl);
1800   lgl->cbs->cls.consume.fun =  fun;
1801   lgl->cbs->cls.consume.state = state;
1802 }
1803
1804 void lglsetconsumedcls (LGL * lgl,
1805                         void (*fun) (void*, int), void * state) {
1806   REQINITNOTFORKED ();
1807   lglinitcbs (lgl);
1808   lgl->cbs->cls.consumed.fun = fun;
1809   lgl->cbs->cls.consumed.state = state;
1810 }
1811
1812 void lglsetlockeq (LGL * lgl, int * (*fun)(void*), void * state) {
1813   REQINITNOTFORKED ();
1814   lglinitcbs (lgl);
1815   lgl->cbs->eqs.lock.fun = fun;
1816   lgl->cbs->eqs.lock.state = state;
1817 }
1818
1819 void lglsetunlockeq (LGL * lgl, void (*fun)(void*,int,int), void * state) {
1820   REQINITNOTFORKED ();
1821   lglinitcbs (lgl);
1822   lgl->cbs->eqs.unlock.fun = fun;
1823   lgl->cbs->eqs.unlock.state = state;
1824 }
1825
1826 void lglsetmsglock (LGL * lgl,
1827                     void (*lock)(void*), void (*unlock)(void*),
1828                     void * state) {
1829   REQINITNOTFORKED ();
1830   lglinitcbs (lgl);
1831   lgl->cbs->msglock.lock = lock;
1832   lgl->cbs->msglock.unlock = unlock;
1833   lgl->cbs->msglock.state = state;
1834 }
1835
1836 void lglsetime (LGL * lgl, double (*time)(void)) {
1837   REQINITNOTFORKED ();
1838   lglinitcbs (lgl);
1839   lgl->cbs->getime = time;
1840 }
1841
1842 /*------------------------------------------------------------------------*/
1843
1844 static int lglfullstk (Stk * s) { return s->top == s->end; }
1845 static int lglmtstk (Stk * s) { return s->top == s->start; }
1846 static size_t lglcntstk (Stk * s) { return s->top - s->start; }
1847 static size_t lglszstk (Stk * s) { return s->end - s->start; }
1848
1849 static int lglpeek (Stk * s, int pos) {
1850   assert (0 <= pos && pos < lglszstk (s));
1851   return s->start[pos];
1852 }
1853
1854 static void lglpoke (Stk * s, int pos, int val) {
1855   assert (0 <= pos && pos <= lglszstk (s));
1856   s->start[pos] = val;
1857 }
1858
1859 static void lglenlstk (LGL * lgl, Stk * s) {
1860   size_t old_size = lglszstk (s);
1861   size_t new_size = old_size ? 2 * old_size : 1;
1862   size_t count = lglcntstk (s);
1863   RSZ (s->start, old_size, new_size);
1864   s->top = s->start + count;
1865   s->end = s->start + new_size;
1866 }
1867
1868 static void lglrelstk (LGL * lgl, Stk * s) {
1869   DEL (s->start, lglszstk (s));
1870   CLRPTR (s);
1871 }
1872
1873 static void lglshrstk (LGL * lgl, Stk * s, int new_size) {
1874   size_t old_size, count = lglcntstk (s);
1875   assert (new_size >= 0);
1876   assert (count <= new_size);
1877   if (new_size > 0) {
1878     old_size = lglszstk (s);
1879     RSZ (s->start, old_size, new_size);
1880     s->top = s->start + count;
1881     s->end = s->start + new_size;
1882   } else lglrelstk (lgl, s);
1883 }
1884
1885 static void lglfitstk (LGL * lgl, Stk * s) {
1886   lglshrstk (lgl, s, lglcntstk (s));
1887 }
1888
1889 static void lglpushstk (LGL * lgl, Stk * s, int elem) {
1890   if (lglfullstk (s)) lglenlstk (lgl, s);
1891   *s->top++ = elem;
1892 }
1893
1894 static void lglrmstk (Stk * s, int elem) {
1895   int * p, * q;
1896   for (p = s->start; p < s->top; p++)
1897     if (*p == elem) break;
1898   assert (p < s->top);
1899   q = p++;
1900   while (p < s->top)
1901     *q++ = *p++;
1902   s->top = q;
1903 }
1904
1905 static int lglpopstk (Stk * s) { assert (!lglmtstk (s)); return *--s->top; }
1906
1907 static int lgltopstk (Stk * s) { assert (!lglmtstk (s)); return s->top[-1]; }
1908
1909 static void lglrststk (Stk * s, int newsz) {
1910   assert (0 <= newsz && newsz <= lglcntstk (s));
1911   s->top = s->start + newsz;
1912 }
1913
1914 static void lglclnstk (Stk * s) { lglrststk (s, 0); }
1915
1916 /*------------------------------------------------------------------------*/
1917
1918 static void lgltrapi (LGL * lgl, const char * msg, ...) {
1919   va_list ap;
1920   assert (lgl->apitrace);
1921   va_start (ap, msg);
1922   vfprintf (lgl->apitrace, msg, ap);
1923   va_end (ap);
1924   fputc ('\n', lgl->apitrace);
1925 }
1926
1927 static void lglopenapitrace (LGL * lgl, const char * name) {
1928   FILE * file;
1929   char * cmd;
1930   int len;
1931   len = strlen (name);
1932   if (len >= 3 && !strcmp (name + len - 3, ".gz")) {
1933     len += 20;
1934     NEW (cmd, len);
1935     sprintf (cmd, "gzip -c > %s", name);
1936     file = popen (cmd, "w");
1937     DEL (cmd, len);
1938     if (file) lgl->closeapitrace = 2;
1939   } else {
1940     file = fopen (name, "w");
1941     if (file) lgl->closeapitrace = 1;
1942   }
1943   if (file) lgl->apitrace = file;
1944   else lglwrn (lgl, "can not write API trace to '%s'", name);
1945   TRAPI ("init");
1946 }
1947
1948 void lglwtrapi (LGL * lgl, FILE * apitrace) {
1949   REQUIRE (UNUSED);
1950   ABORTIF (lgl->apitrace, "can only write one API trace");
1951   lgl->apitrace = apitrace;
1952   TRAPI ("init");
1953 }
1954
1955 /*------------------------------------------------------------------------*/
1956 #if !defined(NLGLPICOSAT) && !defined(NDEBUG)
1957
1958 static void lglpicosatinit (LGL * lgl) {
1959   if (lgl->picosat.solver) return;
1960   lgl->picosat.solver = picosat_init ();
1961   picosat_set_prefix (lgl->picosat.solver, "c PST ");
1962   lgl->picosat.chk = 1;
1963   picosat_add (lgl->picosat.solver, 1);
1964   picosat_add (lgl->picosat.solver, 0);
1965   LOG (1, "PicoSAT initialized");
1966 }
1967
1968 #endif
1969 /*------------------------------------------------------------------------*/
1970
1971 static unsigned lglrand (LGL * lgl) {
1972   unsigned res;
1973   lgl->rng.z = 36969 * (lgl->rng.z & 65535) + (lgl->rng.z >> 16);
1974   lgl->rng.w = 18000 * (lgl->rng.w & 65535) + (lgl->rng.w >> 16);
1975   res = (lgl->rng.z << 16) + lgl->rng.w;
1976   LOG (5, "rng %u", res);
1977   return res;
1978 }
1979
1980 /*------------------------------------------------------------------------*/
1981
1982 static int lglmtftk (Ftk * ftk) { return ftk->top == ftk->start; }
1983
1984 static int lglfullftk (Ftk * ftk) { return ftk->top == ftk->end; }
1985
1986 static int lglsizeftk (Ftk * ftk) { return ftk->end - ftk->start; }
1987
1988 static int lglcntftk (Ftk * ftk) { return ftk->top - ftk->start; }
1989
1990 static void lglrelftk (LGL * lgl, Ftk * ftk) {
1991   DEL (ftk->start, lglsizeftk (ftk));
1992   memset (ftk, 0, sizeof *ftk);
1993 }
1994
1995 static void lglenlftk (LGL * lgl, Ftk * ftk) {
1996   int oldsize = lglsizeftk (ftk);
1997   int newsize = oldsize ? 2*oldsize : 1;
1998   int count = lglcntftk (ftk);
1999   RSZ (ftk->start, oldsize, newsize);
2000   ftk->top = ftk->start + count;
2001   ftk->end = ftk->start + newsize;
2002 }
2003
2004 static void lglpushftk (LGL * lgl, Ftk * ftk, Flt f) {
2005   if (lglfullftk (ftk)) lglenlftk (lgl, ftk);
2006   *ftk->top++ = f;
2007 }
2008
2009 static Flt lgltopftk (Ftk * ftk) {
2010   assert (!lglmtftk (ftk));
2011   return ftk->top[-1];
2012 }
2013
2014 static Flt lglpopftk (Ftk * ftk) {
2015   assert (!lglmtftk (ftk));
2016   return *--ftk->top;
2017 }
2018
2019 /*------------------------------------------------------------------------*/
2020
2021 static int lglfullctk (Ctk * ctk) { return ctk->top == ctk->end; }
2022
2023 static int lglsizectk (Ctk * ctk) { return ctk->end - ctk->start; }
2024
2025 static int lglcntctk (Ctk * ctk) { return ctk->top - ctk->start; }
2026
2027 static void lglrelctk (LGL * lgl, Ctk * ctk) {
2028   DEL (ctk->start, lglsizectk (ctk));
2029   memset (ctk, 0, sizeof *ctk);
2030 }
2031
2032 static void lglenlctk (LGL * lgl, Ctk * ctk) {
2033   int oldsize = lglsizectk (ctk);
2034   int newsize = oldsize ? 2*oldsize : 1;
2035   int count = lglcntctk (ctk);
2036   RSZ (ctk->start, oldsize, newsize);
2037   ctk->top = ctk->start + count;
2038   ctk->end = ctk->start + newsize;
2039 }
2040
2041 static void lglpushcontrol (LGL * lgl, int decision) {
2042   Ctk * ctk = &lgl->control;
2043   Ctr * ctr;
2044   if (lglfullctk (ctk)) lglenlctk (lgl, ctk);
2045   ctr = ctk->top++;
2046   ctr->decision = decision;
2047   ctr->used = 0;
2048 }
2049
2050 static void lglpopcontrol (LGL * lgl) {
2051   assert (lgl->control.top > lgl->control.start);
2052   --lgl->control.top;
2053 }
2054
2055 static void lglrstcontrol (LGL * lgl, int count) {
2056   while (lglcntctk (&lgl->control) > count)
2057     lglpopcontrol (lgl);
2058 }
2059
2060 static int lglevelused (LGL * lgl, int level) {
2061   Ctk * ctk = &lgl->control;
2062   Ctr * ctr;
2063   assert (0 < level && level < lglsizectk (ctk));
2064   ctr = ctk->start + level;
2065   return ctr->used;
2066 }
2067
2068 static void lgluselevel (LGL * lgl, int level) {
2069   Ctk * ctk = &lgl->control;
2070   Ctr * ctr;
2071   assert (0 < level && level < lglsizectk (ctk));
2072   ctr = ctk->start + level;
2073   ctr->used = 1;
2074 }
2075
2076 static void lglunuselevel (LGL * lgl, int level) {
2077   Ctk * ctk = &lgl->control;
2078   Ctr * ctr;
2079   assert (0 < level);
2080   assert (level < lglcntctk (ctk));  
2081   assert (0 < level);
2082   ctr = ctk->start + level;
2083   assert (ctr->used);
2084   ctr->used = 0;
2085 }
2086
2087 /*------------------------------------------------------------------------*/
2088
2089 static void lglgetenv (LGL * lgl, Opt * opt, const char * lname) {
2090   const char * q, * valstr;
2091   char uname[40], * p;
2092   int newval, oldval;
2093   assert (strlen (lname) + 3 + 1 < sizeof (uname));
2094   uname[0] = 'L'; uname[1] = 'G'; uname[2] = 'L';
2095   p = uname + 3;
2096   for (q = lname; *q; q++) {
2097     assert (p < uname + sizeof uname);
2098     *p++ = toupper (*q);
2099   }
2100   assert (p < uname + sizeof uname);
2101   *p = 0;
2102   valstr = getenv (uname);
2103   if (!valstr) return;
2104   oldval = opt->val;
2105   newval = atoi (valstr);
2106   if (newval < opt->min) newval = opt->min;
2107   if (newval > opt->max) newval = opt->max;
2108   if (newval == oldval) return;
2109   opt->val = newval;
2110   TRAPI ("option %s %d", lname, newval);
2111   COVER (lgl->clone);
2112   if (lgl->clone) lglsetopt (lgl->clone, lname, newval);
2113 }
2114
2115 static void lglchkenv (LGL * lgl) {
2116   extern char ** environ;
2117   char * src, *eos, * dst;
2118   char ** p, * s, * d;
2119   int len;
2120   for (p = environ; (src = *p); p++) {
2121     if (src[0] != 'L' || src[1] != 'G' || src[2] != 'L') continue;
2122     for (eos = src; *eos && *eos != '='; eos++)
2123       ;
2124     len = eos - (src + 3);
2125     NEW (dst, len + 1);
2126     d = dst;
2127     for (s = src + 3; s < eos; s++) *d++ = tolower (*s);
2128     *d = 0;
2129     if (!lglhasopt (lgl, dst) && strcmp (dst, "apitrace"))
2130       lglwrn (lgl, "invalid 'LGL...' environment '%s'", src);
2131     DEL (dst, len + 1);
2132   }
2133 }
2134
2135 #define SETPLAIN(NAME) \
2136 do { \
2137   if (val) lgl->opts->NAME.val = 0; \
2138   else lgl->opts->NAME.val = lgl->opts->NAME.dflt; \
2139 } while (0)
2140
2141 #define SETDRUP SETPLAIN
2142
2143 static void lglsetdrup (LGL * lgl, int val) {
2144   SETDRUP (bca);
2145   SETDRUP (card);
2146   SETDRUP (decompose);
2147   SETDRUP (probe);
2148   SETDRUP (lift);
2149   SETDRUP (cgrclsr);
2150   SETDRUP (gauss);
2151   SETDRUP (mega);
2152   SETDRUP (rdp);
2153   SETDRUP (smallve);
2154   lglprt (lgl, 1, "[drup] drup solving switched %s", val ? "on" : "off");
2155 }
2156
2157 #define SETDRUPLIG SETPLAIN
2158
2159 static void lglsetdruplig (LGL * lgl, int val) {
2160   SETDRUPLIG (bca);
2161   SETDRUPLIG (card);
2162   SETDRUPLIG (decompose);
2163   SETDRUPLIG (probe);
2164   SETDRUPLIG (lift);
2165   SETDRUPLIG (cgrclsr);
2166   SETDRUPLIG (gauss);
2167   SETDRUPLIG (mega);
2168   SETDRUPLIG (rdp);
2169   SETDRUPLIG (smallve);
2170   lglprt (lgl, 1,
2171     "[druplig] druplig checking switched %s",
2172     val ? "on" : "off");
2173 }
2174
2175 static void lglsetplain (LGL * lgl, int val) {
2176   SETPLAIN (bca);
2177   SETPLAIN (bva);
2178   SETPLAIN (block);
2179   SETPLAIN (card);
2180   SETPLAIN (cce);
2181   SETPLAIN (cgrclsr);
2182   SETPLAIN (cliff);
2183   SETPLAIN (decompose);
2184   SETPLAIN (elim);
2185   SETPLAIN (gauss);
2186   SETPLAIN (lift);
2187   SETPLAIN (locs);
2188   SETPLAIN (mega);
2189   SETPLAIN (probe);
2190   SETPLAIN (rdp);
2191   SETPLAIN (ternres);
2192   SETPLAIN (transred);
2193   SETPLAIN (unhide);
2194   lglprt (lgl, 1, "[plain] plain solving switched %s", val ? "on" : "off");
2195 }
2196
2197 #define SETWAIT(NAME) \
2198 do { \
2199   if (val) lgl->opts->NAME.val = lgl->opts->NAME.dflt; \
2200   else lgl->opts->NAME.val = 0; \
2201 } while (0)
2202
2203 static void lglsetwait (LGL * lgl, int val) {
2204   SETWAIT (batewait);
2205   SETWAIT (bcawait);
2206   SETWAIT (blockwait);
2207   SETWAIT (ccewait);
2208   SETWAIT (cgrclsrwait);
2209   SETWAIT (cliffwait);
2210   SETWAIT (elmblkwait);
2211   SETWAIT (gausswait);
2212   SETWAIT (liftwait);
2213   SETWAIT (smallvewait);
2214   SETWAIT (ternreswait);
2215   SETWAIT (transredwait);
2216   SETWAIT (unhidewait);
2217   lglprt (lgl, 1, "[wait] waiting %s", val ? "enabled" : "disabled");
2218 }
2219
2220 static LGL * lglnewlgl (void * mem,
2221                         lglalloc alloc,
2222                         lglrealloc realloc,
2223                         lgldealloc dealloc) {
2224   LGL * lgl = alloc ? alloc (mem, sizeof *lgl) : malloc (sizeof *lgl);
2225   ABORTIF (!lgl, "out of memory allocating main solver object");
2226   CLRPTR (lgl);
2227
2228   lgl->mem = alloc ? alloc (mem, sizeof *lgl->mem) : malloc (sizeof *lgl->mem);
2229   ABORTIF (!lgl->mem, "out of memory allocating memory manager object");
2230
2231   lgl->mem->state = mem;
2232   lgl->mem->alloc = alloc;
2233   lgl->mem->realloc = realloc;
2234   lgl->mem->dealloc = dealloc;
2235
2236   lgl->opts = alloc ? alloc (mem, sizeof (Opts)) : malloc (sizeof (Opts));
2237   ABORTIF (!lgl->opts, "out of memory allocating option manager object");
2238   CLRPTR (lgl->opts);
2239
2240   lgl->stats = alloc ? alloc (mem, sizeof (Stats)) : malloc (sizeof (Stats));
2241   ABORTIF (!lgl->stats, "out of memory allocating statistic counters");
2242   CLRPTR (lgl->stats);
2243
2244   lglinc (lgl, sizeof *lgl);
2245   lglinc (lgl, sizeof *lgl->mem);
2246   lglinc (lgl, sizeof *lgl->opts);
2247   lglinc (lgl, sizeof *lgl->stats);
2248
2249   return lgl;
2250 }
2251
2252 static void lglinitscores (LGL * lgl) {
2253   Scr oldscincf, oldmaxscore = lgl->maxscore;
2254   if (lgl->opts->score.val != LGL_SCORE_EVSIDS) {
2255     lgl->maxscore = (1ll << 60);
2256     if (oldmaxscore != lgl->maxscore)
2257       lglprt (lgl, 1,
2258         "[init-scores] fixed maxium score %s",
2259         lglscr2str (lgl, lgl->maxscore));
2260   } else {
2261     oldscincf = lgl->scincf;
2262 #ifdef NDBLSCR
2263     lgl->scincf = lglrat (1000 + lgl->opts->scincinc.val, 1000);
2264     lgl->maxscore = lglflt (lgl->opts->maxscorexp.val, 1);
2265 #else
2266     lgl->scincf = (1000.0 + lgl->opts->scincinc.val) / 1000.0;
2267     lgl->maxscore = scalbln (1.0, lgl->opts->maxscorexp.val);
2268 #endif
2269     if (oldscincf != lgl->scincf)
2270       lglprt (lgl, 1,
2271         "[init-scores] score increment factor %s (--scincinc=%d)",
2272         lglscr2str (lgl, lgl->scincf), lgl->opts->scincinc.val);
2273
2274     if (oldmaxscore != lgl->maxscore)
2275       lglprt (lgl, 1,
2276         "[init-scores] maxium score limit %s (--maxscorexp=%d)",
2277         lglscr2str (lgl, lgl->maxscore), lgl->opts->maxscorexp.val);
2278   }
2279 }
2280
2281 LGL * lglminit (void * mem,
2282                 lglalloc alloc,
2283                 lglrealloc realloc,
2284                 lgldealloc dealloc) {
2285   const int K = 1000, M = K*K, I = INT_MAX;
2286   const int MG = MAXGLUE, MG0 = MG*10;
2287   const char * apitracename;
2288   LGL * lgl;
2289   int i;
2290
2291   lgl = 0;
2292   ABORTIF (!alloc+!realloc+!dealloc != 0 && !alloc+!realloc+!dealloc != 3,
2293            "inconsistent set of external memory handlers");
2294
2295   assert (sizeof (long) == sizeof (void*));
2296
2297   assert (REMOVED > ((MAXVAR << RMSHFT) | MASKCS | REDCS));
2298   assert (REMOVED > MAXREDLIDX);
2299   assert (REMOVED > MAXIRRLIDX);
2300
2301   assert (MAXREDLIDX == MAXIRRLIDX);
2302   assert (GLUESHFT == RMSHFT);
2303
2304   assert (INT_MAX > ((MAXREDLIDX << GLUESHFT) | GLUEMASK));
2305   assert (INT_MAX > ((MAXIRRLIDX << RMSHFT) | MASKCS | REDCS));
2306
2307   assert (MAXGLUE < POW2GLUE);
2308
2309   lgl = lglnewlgl (mem, alloc, realloc, dealloc);
2310   lgl->tid = -1;
2311
2312   lglpushcontrol (lgl, 0);
2313   assert (lglcntctk (&lgl->control) == lgl->level + 1);
2314
2315   lgl->out = stdout;
2316   lgl->prefix = lglstrdup (lgl, "c ");
2317
2318   apitracename = getenv ("LGLAPITRACE");
2319   if (apitracename) lglopenapitrace (lgl, apitracename);
2320
2321   OPT(0,abstime,0,0,1,"print absolute time when reporting");
2322   OPT(0,actavgmax,3*MG0/4,0,MG0,"glue average max limit for dyn acts");
2323   OPT(0,actdblarithlim,3,0,MG,"glue lim for dbl arith increase");
2324   OPT(0,actgeomlim,2,0,MG,"glue limit for geometric increase");
2325   OPT(0,actgsdul,7,0,MG0,"glue useless standard deviation limit");
2326   OPT(0,acts,2,0,2,"activity based reduction: 0=no,1=enable,2=dyn");
2327   OPT(0,actstdmax,3*MG0/4,0,MG0,"glue std dev max limit for dyn acts");
2328   OPT(0,actstdmin,10,0,MG0,"glue std dev min limit for dyn acts");
2329   OPT(0,actvlim,200*K,0,I,"activity based reduction variable limit");
2330   OPT(0,agile,1,0,2,"agility based restart skipping, 1=std, 2=sinus");
2331   OPT(0,agilelim,30,0,100,"agility limit for restarts");
2332   OPT(0,agilesinint,100*K,1,I,"agility limit sinus interval");
2333   OPT(0,bate,1,0,1,"basic ATE removal during probing");
2334   OPT(0,batewait,2,0,2,"wait for BCE (1) and/or BVE (2)");
2335   OPT(0,bca,1,0,2,"enable blocked clause addition (1=week,2=strong)");
2336   OPT(0,bcamaxeff,10*M,0,I,"BCA maximum number of steps");
2337   OPT(0,bcaminuse,100,0,I,"min number of literals required to be usable");
2338   OPT(0,bcawait,2,0,2,"wait for BCE (1) and/or BVE (2)");
2339   OPT(0,bva,0,0,1,"enable bounded variable addition (BVA)");
2340   OPT(0,bias,2,-1,2,"decision order initial bias (0=no,2=cw)");
2341   OPT(0,binlocsdel,10,0,1000,"delay local seach after learning binary clause");
2342   OPT(0,binsimpdel,2,0,1000,"delay simp after learning binary clause");
2343   OPT(0,bkwdscale,2,1,1000,"backward steps scaled vs elimination steps");
2344   OPT(0,blkboost,10,1,10000,"initial BCE boost");
2345   OPT(0,blkboostvlim,1000000,0,I,"init BCE boost variable limit");
2346   OPT(0,blkclslim,1*M,3,I,"max blocked clause size");
2347   OPT(0,blklarge,1,0,1,"BCE of large clauses");
2348   OPT(0,blkmaxeff,800*M,-1,I,"max effort in BCE (-1=unlimited)");
2349   OPT(0,blkmineff,50*M,0,I,"min effort in BCE");
2350   OPT(0,blkocclim1,100*K,1,I,"one-sided max occ of BCE");
2351   OPT(0,blkocclim,1*M,3,I,"max occ in BCE");
2352   OPT(0,blkocclim2,10*K,2,I,"two-sided max occ of BCE");
2353   OPT(0,blkreleff,100,0,K,"rel effort in BCE");
2354   OPT(0,blkrtc,0,0,1,"run BCE until completion");
2355   OPT(0,blksched2b2,0,0,1,"BCE schedule 2x2 first");
2356   OPT(0,blkschedmin,0,0,1,"BCE schedule based on minimum of occurrences");
2357   OPT(0,blkschedprod,0,0,1,"BCE schedule based on product too");
2358   OPT(0,blkschedpure,1,0,1,"BCE schedule pure literals first");
2359   OPT(0,blkschedsum,1,0,1,"BCE schedule based on sum of occurrences too");
2360   OPT(0,blksmall,1,0,1,"BCE of small clauses");
2361   OPT(0,blksuccesslim,10*K,0,I,"BCE success limit");
2362   OPT(0,blksuccessrat,1000,1,I,"BCE success ratio");
2363   OPT(0,block,1,0,1,"blocked clause elimination (BCE)");
2364   OPT(0,blockwait,1,0,1,"wait for BVE");
2365   OPT(0,boost,1,0,1,"enable boosting of preprocessors");
2366   OPT(0,bumpbcplits,0,0,1,"bump unseen but propagated literals");
2367   OPT(0,bumpclslits,0,0,1,"bump literals in minimized clause");
2368   OPT(0,bumpseenaftermin,0,0,1,"bump seen after minimization");
2369   OPT(0,bumpseenbeforemin,1,0,1,"bump seen before minimization");
2370   OPT(0,bumpseenlits,1,0,1,"bump seen literals");
2371   OPT(0,bumpseenminsize,3,0,I,"minimum 1st UIP clause for bumping seen");
2372   OPT(0,card,1,0,1,"cardinality constraint reasoning");
2373   OPT(0,cardcut,2,0,2,"1=gomoroy-cuts,2=strengthen");
2374   OPT(0,cardexpam1,3,2,I,"min length of exported at-most-one constraint");
2375   OPT(0,cardglue,0,-1,MAXGLUE,"use lrg red cls too (-1=irr,0=moved,...)");
2376   OPT(0,cardignused,0,0,1,"ignored already used literals in extraction");
2377   OPT(0,cardmaxeff,300*M,-1,I,"max effort for cardmineff reasoning");
2378   OPT(0,cardmaxlen,1000,0,I,"maximal length of cardinality constraints");
2379   OPT(0,cardmineff,2*M,0,I,"min effort for cardmineff reasoning");
2380   OPT(0,cardminlen,3,0,I,"minimal length of (initial) card constraints");
2381   OPT(0,cardocclim1,300,0,I,"one-sided cardinality constraints occ limit");
2382   OPT(0,cardocclim2,15,0,I,"two-sided cardinality constraints occ limit");
2383   OPT(0,cardreleff,5,0,10*K,"rel effort for cardinality reasoning");
2384   OPT(0,cardreschedint,10,1,I,"reschedule variable for card reasoning");
2385   OPT(0,carduse,2,0,3,"use clauses (1=oneside,2=bothsidetoo,3=anyside)");
2386   OPT(0,cardwait,0,0,2,"wait for BCE (1) and/or BVE (2)");
2387   OPT(0,cce2wait,1,0,I,"wait for ATE to finish before doing ABCE");
2388   OPT(0,cce,3,0,3,"covered clause elimination (1=ate,2=abce,3=acce)");
2389   OPT(0,cceboost,10,1,1000,"initial CCE boost");
2390   OPT(0,cceboostvlim,1000000,0,I,"initial CCE boost variable limit");
2391   OPT(0,cce3wait,2,0,I,"wait for ABCE to finish before doing ACCE");
2392   OPT(0,ccemaxeff,I,-1,I,"max effort in covered clause elimination");
2393   OPT(0,ccemineff,30*M,0,I,"min effort in covered clause elimination");
2394   OPT(0,cceonlyifstuck,0,0,1,"ABCE+ACCE only if elm+blk stuck");
2395   OPT(0,ccereleff,20,0,K,"rel effort in covered clause elimination");
2396   OPT(0,ccertc,0,0,1,"run CCE until completition");
2397   OPT(0,ccesuccesslim,10*K,0,I,"CCE success limit");
2398   OPT(0,ccesuccessrat,1000,1,I,"CCE success ratio");
2399   OPT(0,ccewait,2,0,2,"wait for BCE (1) and/or BVE (2)");
2400   OPT(0,cgrclsr,1,0,1,"gate extraction and congruence closure");
2401   OPT(0,cgrclsrwait,2,0,2,"wait for BCE (1) and/or BVE (2)");
2402   OPT(0,cgreleff,1,0,10*K,"rel effort in congruence closure");
2403   OPT(0,cgrextand,1,0,1,"extract and gates");
2404   OPT(0,cgrexteq,1,0,1,"extract equivalences");
2405   OPT(0,cgrextite,1,0,1,"extract ite gates");
2406   OPT(0,cgrextunits,1,0,1,"extract units");
2407   OPT(0,cgrextxor,1,0,1,"extract xor gates");
2408   OPT(0,cgrmaxeff,8*M,-1,I,"max effort in congruence closure");
2409   OPT(0,cgrmaxority,20,2,30,"maximum xor arity to be extracted");
2410   OPT(0,cgrmineff,200*K,0,I,"min effort in congruence closure");
2411   OPT(0,cintinc,20*K,10,M,"inprocessing conflict interval increment");
2412   OPT(0,cintincdiv,1,0,3,"cintinc reduce policy: 0=no,1=div1,2=div2,3=heur");
2413   OPT(0,cintmaxhard,10*M,-1,I,"hard max conflict interval limit");
2414   OPT(0,cintmaxsoft,1*M,-1,I,"soft max conflict interval limit");
2415   OPT(0,cliff,1,0,1,"cliffing");
2416   OPT(0,cliffmaxeff,100*M,-1,I,"max effort in cliffing");
2417   OPT(0,cliffmineff,10*M,0,I,"min effort in cliffing");
2418   OPT(0,cliffreleff,8,0,10*K,"rel effort in cliffing");
2419   OPT(0,cliffwait,2,0,2,"wait for BCE (1) and/or BVE (2)");
2420   OPT(0,clim,-1,-1,I,"conflict limit");
2421   OPT(0,compact,0,0,2,"compactify after 'lglsat/lglsimp' (1=UNS,2=SAT)");
2422   OPT(0,deco,1,0,2,"learn decision-only clauses too (2=all-decisions)");
2423   OPT(0,decolim,30,0,I,"decision-only clauses glue limit");
2424   OPT(0,decompose,1,0,1,"enable decompose");
2425   OPT(0,defragfree,50,10,K,"defragmentation free watches limit");
2426   OPT(0,defragint,10*M,100,I,"defragmentation pushed watches interval");
2427   OPT(0,delmax,10,0,10,"maximum delay");
2428   OPT(0,dlim,-1,-1,I,"decision limit");
2429   OPT(0,drup,0,0,1,"print DRUP proof");
2430 #if 1
2431   OPT(0,druplig,0,0,1,"check proof through Druplig internally");
2432 #else
2433   OPT(0,druplig,1,1,1,"check proof through Druplig internally");
2434 #endif
2435   OPT(0,elim,1,0,1,"bounded variable eliminiation (BVE)");
2436   OPT(0,elmaxeff,800*M,-1,I,"max effort in BVE (-1=unlimited)");
2437   OPT(0,elmblk,1,0,1,"enable BCE during BVE");
2438   OPT(0,elmblkwait,1,0,1,"wait for BVE to be completed once");
2439   OPT(0,elmboost,40,1,1000,"initial elimination boost");
2440   OPT(0,elmclslim,1*M,3,I,"max antecendent size in elimination");
2441   OPT(0,elmfull,0,0,1,"no elimination limits");
2442   OPT(0,elmineff,20*M,0,I,"min effort in BVE");
2443   OPT(0,elmlitslim,200,0,I,"one side literals limit for elimination");
2444   OPT(0,elmocclim1,1000,1,I,"one-sided max occ of BVE");
2445   OPT(0,elmocclim,1*M,3,I,"max occurrences in BVE");
2446   OPT(0,elmocclim2,100,2,I,"two-sided max occ of BVE");
2447   OPT(0,elmreleff,200,0,10*K,"rel effort in BVE");
2448   OPT(0,elmroundlim,3,1,I,"variable elimination rounds limit");
2449   OPT(0,elmrtc,0,0,1,"run BVE until completion");
2450   OPT(0,elmsched2b2,0,0,1,"BVE schedule 2x2 first");
2451   OPT(0,elmschediff,0,0,1,"BVE schedule based on diff of occurrences too");
2452   OPT(0,elmschedmin,0,0,1,"BVE schedule based on minimum of occurrences");
2453   OPT(0,elmschedprod,0,0,1,"BVE schedule based on product too");
2454   OPT(0,elmschedpure,1,0,1,"BVE schedule pure literals first");
2455   OPT(0,elmschedsum,1,0,1,"BVE schedule based on sum of occurrences too");
2456   OPT(0,elmsuccesslim,1000,0,I,"BVE success limit");
2457   OPT(0,elmsuccessrat,1000,1,I,"BVE success ratio");
2458   OPT(0,exitonabort,0,0,1,"exit instead abort after internal error");
2459   OPT(0,factmax,100000,1,I,"maximum factor");
2460   OPT(0,factor,3,0,3,"{cls,occ}lim factors (0=const1,1=ld,2=lin,3=sqr)");
2461   OPT(0,flipdur,10,1,I,"flipping duration in number of conflicts");
2462   OPT(0,flipint,10,0,I,"flipping interval in number top level decision");
2463   OPT(0,flipldmod,4,0,30,"flipping phase log2 of mod"); 
2464   OPT(0,fliplevels,6,0,30,"flipping decision levels");
2465   OPT(0,flipping,1,0,1,"enable point flipping");
2466   OPT(0,fliptop,1,0,1,"flipping only at the top level");
2467   OPT(0,flipvlim,100*K,0,I,"no flipping beyond this number vars");
2468   OPT(0,force,0,0,I,"reorder variables with force algorithm");
2469   OPT(0,gauss,1,0,1,"enable gaussian elimination");
2470   OPT(0,gaussexptrn,1,0,1,"export trn cls from gaussian elimination");
2471   OPT(0,gaussextrall,1,0,1,"extract all xors (with duplicates)");
2472   OPT(0,gaussmaxeff,50*M,-1,I,"max effort in gaussian elimination");
2473   OPT(0,gaussmaxor,20,2,64,"maximum xor size in gaussian elimination");
2474   OPT(0,gaussmineff,2*M,0,I,"min effort in gaussian elimination");
2475   OPT(0,gaussreleff,2,0,10*K,"rel effort in gaussian elimination");
2476   OPT(0,gausswait,2,0,2,"wait for BCE (1) and/or BVE (2)");
2477   OPT(0,gluekeep,3,0,I,"keep clauses with this original glue");
2478   OPT(0,gluescale,4,1,4,"glue scaling: 1=linear,2=sqrt,3=ld,4=hybrid");
2479   OPT(0,import,1,0,1,"import external indices and map them");
2480   OPT(0,incredcint,1,1,I,"incremental reduce conflict interval");
2481   OPT(0,incredconfslim,0,0,100,"incremental reduce conflict limit");
2482   OPT(0,incsavevisits,0,0,1,"incremental start new visits counter");
2483   OPT(0,inprocessing,1,0,1,"enable inprocessing");
2484   OPT(0,irrlim,1,0,1,"use irredundant clauses as limit for simps");
2485   OPT(0,itlocsdel,100,0,100*K,"local search delay after iteration");
2486   OPT(0,itsimpdel,20,0,100*K,"simplification delay after iteration");
2487   OPT(0,jwhred,1,0,1,"compute JWH score based on redundant clauses too");
2488   OPT(0,keepmaxglue,1,0,1,"keep maximum glue clauses");
2489   OPT(0,lftmaxeff,20*M,-1,I,"max effort in lifting");
2490   OPT(0,lftmineff,500*K,0,I,"min effort in lifting");
2491   OPT(0,lftreleff,6,0,10*K,"rel effort in lifting");
2492   OPT(0,lftroundlim,5,0,I,"lifting round limit");
2493   OPT(0,lhbr,1,0,1, "enable lazy hyber binary reasoning");
2494   OPT(0,lift,1,0,1,"enable double lookahead lifting");
2495   OPT(0,liftlrg,3,0,I,"consider large clauses with this many unassigned");
2496   OPT(0,liftwait,2,0,2,"wait for BCE (1) and/or BVE (2)");
2497   OPT(0,lkhd,2,-1,3, "-1=LOCS,0=LIS,1=JWH,2=TREELOOK,3=LENSUM");
2498   OPT(0,lkhdmisifelmrtc,0,0,1,"MIS if elimination ran to completion");
2499   OPT(0,locs,0,-1,I,"use local search (-1=always otherwise how often)");
2500   OPT(0,locsclim,1*M,0,(I>>8),"clause limit for local search");
2501   OPT(0,locsboost,2,0,100,"initial local search boost");
2502   OPT(0,locscint,10*K,1,I,"conflict interval for LOCS");
2503   OPT(0,locsdec,2,0,2,"bump 1=mostflipped 2=minlits");
2504   OPT(0,locset,2,0,2,"initialize local search phases (1=prev,2=cur)");
2505   OPT(0,locsexport,1,0,1,"export phases from local search");
2506   OPT(0,locsmaxeff,100000,0,I,"max effort in local search");
2507   OPT(0,locsmineff,1000,0,I,"min effort in local search");
2508   OPT(0,locsred,0,0,4,"apply local search on redundant clauses too");
2509   OPT(0,locsreleff,5,0,100,"rel effort in local search");
2510   OPT(0,locsrtc,0,0,1,"run local search until completion");
2511   OPT(0,locsvared,100,0,1000,"max variable reduction for LOCS");
2512   OPT(0,locswait,2,0,2,"wait for BCE(1) and/or BVE(2)");
2513   OPT(0,maxglue,I,0,I,"min glue which is considered as MAXGLUE");
2514   OPT(0,maxscorexp,DEFSCOREXP,7,MAXSCOREXP,"maximum score exponent");
2515   OPT(0,mega,0,0,1,"mega probing through preprocessor look-ahead");
2516   OPT(0,megaint,4,1,I,"mega probing interval");
2517   OPT(0,megawait,2,0,2,"mega probing waiting for BCE / BVE");
2518   OPT(0,memlim,-1,-1,I,"memory limit in MB (-1=no limit)");
2519   OPT(0,minimize,2,0,2,"minimize learned clauses (1=local,2=recursive)");
2520   OPT(0,minlocalgluelim,30,0,I,"glue limit for using local minimization");
2521   OPT(0,minrecgluelim,20,0,I,"glue limit for using recursive minimization");
2522   OPT(0,mocint,1000,1,I,"multiple objectives conflict limit interval");
2523   OPT(0,move,2,0,3,"move redundant cls (1=only-binary,2=ternary,3=all)");
2524   OPT(0,otfs,1,0,1,"enable on-the-fly subsumption");
2525   OPT(0,otfsbump,0,0,2,"bump literals during OTFS (1=conflict,2=drive)");
2526   OPT(0,otfsconf,0,0,1,"count on-the-fly restart as conflict");
2527   OPT(0,penmax,4,0,16,"maximum penalty");
2528   OPT(0,phase,0,-1,1,"default phase (-1=neg,0=JeroslowWang,1=pos)");
2529   OPT(0,phaseflip,0,0,1,"flip Jeroslow Wang phase");
2530   OPT(0,phasegluebit,0,0,I,"Glue-Bit phase selection on these levels");
2531   OPT(0,phaseneginit,0,0,I,"initial zero phase conflict interval");
2532   OPT(0,plain,0,0,1,"plain mode disables all preprocessing");
2533   OPT(0,plim,-1,-1,I,"propagation limit (thousands)");
2534   OPT(0,prbasic,1,0,2,"enable basic probing procedure (1=roots-only)");
2535   OPT(0,prbasicmaxeff,100*M,-1,I,"max effort in basic probing");
2536   OPT(0,prbasicmineff,M,0,I,"min effort in basic probing");
2537   OPT(0,prbasicreleff,10,0,10*K,"rel effort in basic probing");
2538   OPT(0,prbasicroundlim,9,1,I,"basic probing round limit");
2539   OPT(0,prbasicrtc,0,0,1,"run basic probing until completion");
2540   OPT(0,prbrtc,0,0,1,"run all probing until completion");
2541   OPT(0,prbsimple,2,0,3,"simple probing (1=shallow,2=deep,3=touchall)");
2542   OPT(0,prbsimpleboost,10,1,1000,"initial simple probing boost");
2543   OPT(0,prbsimpleliftdepth,2,1,4,"simple probing lifting depth");
2544   OPT(0,prbsimplemaxeff,200*M,-1,I,"max effort in simple probing");
2545   OPT(0,prbsimplemineff,2*M,0,I,"min effort in simple probing");
2546   OPT(0,prbsimplereleff,40,0,10*K,"rel effort in simple probing");
2547   OPT(0,prbsimplertc,0,0,1,"run simple probing until completion");
2548   OPT(0,probe,1,0,1,"enable probing");
2549   OPT(0,psm,3,0,3,"use PSM metric (1=afteract,2=afterglue,3=first");
2550   OPT(0,pure,1,0,1,"enable pure literal elimination during BCE");
2551   OPT(0,randec,0,0,1,"enable random decisions");
2552   OPT(0,randecflipint,0,0,I,"random decision flip phase interval");
2553   OPT(0,randecint,1000,2,I/2,"random decision interval");
2554   OPT(0,rdp,0,0,3,"random DP (2=redbin,3=redtrn");
2555   OPT(0,rdpclslim,3,0,I,"random DP resolvent size limit");
2556   OPT(0,rdplim,100,0,200,"limit #resolvents in percent original clauses");
2557   OPT(0,rdpmaxeff,10*M,-1,I,"max effort in RDP");
2558   OPT(0,rdpmineff,10*K,0,I,"min effort in RDP");
2559   OPT(0,rdpmodelm,0,0,1,"use model elimination in RDP");
2560   OPT(0,rdpreleff,2,0,10*K,"rel effort in RDP");
2561   OPT(0,rdpwait,2,0,2,"wait for BCE (1) and/or BVE (2)");
2562   OPT(0,redfixed,0,0,1,"keep a fixed size of learned clauses");
2563   OPT(0,redinoutinc,100,1,1000,"reduce inner/outer relative increment");
2564   OPT(0,redlbound,0,0,1,"relative and absolute bounds on learned clauses");
2565   OPT(0,redlexpfac,10,0,1000,"exponential reduce limit increment factor");
2566   OPT(0,redlinc,1000,1,10*M,"reduce limit increment");
2567   OPT(0,redlinit,4*K,1,100*M,"initial reduce limit");
2568   OPT(0,redlmaxabs,1000000,10,I/2,"maximum absolute reduce limit");
2569   OPT(0,redlmaxinc,200,1,100*K,"rel max reduce limit increment");
2570   OPT(0,redlmaxrel,300,10,10000,"maximum relative reduce limit");
2571   OPT(0,redlminabs,500,10,1000000,"minimum absolute reduce limit");
2572   OPT(0,redlmininc,10,1,100*K,"rel min reduce limit increment");
2573   OPT(0,redlminrel,10,10,1000,"minimum relative reduce limit");
2574   OPT(0,redloutinc,10000,0,1000000,"outer arithmetic reduce increment");
2575   OPT(0,redoutclim,5000,0,I,"clause limit for outer reduce schedule");
2576   OPT(0,redoutvlim,1000,0,I,"variable limit for outer reduce schedule");
2577   OPT(0,reduce,2,0,4,"clause reduction (1=noouter,2=luby,3=inout,4=arith)");
2578   OPT(0,rephase,1,0,2,"enable flushing and recomputation of phases (2=full)");
2579   OPT(0,rephaseinc,10000,1,I,"rephasing increment");
2580   OPT(0,restart,2,0,3,"enable restarting (0=no,1=fixed,2=luby,3=inout)");
2581   OPT(0,restartinit,0,0,I,"initial restart interval");
2582   OPT(0,restartint,5,1,I,"restart interval");
2583   OPT(0,restartintscale,0,-1,1,"scale restart interval");
2584   OPT(0,reusetrail,1,0,1,"reuse trail");
2585   OPT(0,rmincpen,4,0,32,"logarithm of watcher removal penalty");
2586   OPT(0,rstinoutinc,110,1,1000,"restart inner/outer relative increment");
2587   OPT(0,saturating,70,0,1000,"saturating level (no restart)");
2588   OPT(0,scincinc,200,0,10*K,"score increment increment in per mille");
2589   OPT(0,score,5,0,6,"0=static,1=inc,2=vmtf,3=sum,4=avg,5=evsids,6=vsids256");
2590   OPT(0,seed,0,0,I,"random number generator seed");
2591   OPT(0,simpdelay,0,0,I,"initial simplification delay");
2592   OPT(0,simpen,0,0,24,"logarithmic initial simplification penalty");
2593   OPT(0,simpidiv,3,1,100,"simplification inter delay divisor");
2594   OPT(0,simpinterdelay,2000,0,I,"inprocessing simplification delay");
2595   OPT(0,simpiscale,100,1,10000,"relative simplification inter delay scale");
2596   OPT(0,simplify,2,0,2,"enable simplification");
2597   OPT(0,simprtc,5,1,100,"min var reduction for simplification RTC");
2598   OPT(0,simpvarchg,100,1,1000, "simp remaining vars percentage change lim");
2599   OPT(0,simpvarlim,100,0,I, "simp remaining vars min limit");
2600   OPT(0,sizemaxpen,5,0,20,"maximum logarithmic size penalty");
2601   OPT(0,sizepen,1*M,1,I,"number of clauses size penalty starting point");
2602   OPT(0,sleeponabort,0,0,I,"sleep this seconds before abort/exit");
2603   OPT(0,smallirr,90,0,100,"max percentage irr lits for BCE and VE");
2604   OPT(0,smallve,1,0,1,"enable small number variables elimination");
2605   OPT(0,smallvevars,FUNVAR,4,FUNVAR, "variables small variable elimination");
2606   OPT(0,smallvewait,0,0,1,"wait with small variable elimination");
2607   OPT(0,sortlits,0,0,1,"sort lits of cls during garbage collection");
2608   OPT(0,subl,9,0,10*K,"try to subsume this many recent learned clauses");
2609   OPT(0,synclsall,1,0,1,"always synchronize all unconsumed clauses");
2610   OPT(0,synclsglue,8,0,I,"clause synchronization glue limit");
2611   OPT(0,synclsint,100,0,1000,"clause synchronization confs interval");
2612   OPT(0,synclslen,40,0,I,"clause synchronization length limit");
2613   OPT(0,syncunint,111111,0,M,"unit synchronization steps interval");
2614   OPT(0,tabr,3,0,4,"tabula rasa (1=red,2=phases,3=cinc,4=scores");
2615   OPT(0,tabrcfactor,2,1,I,"tabula rasa clause factor");
2616   OPT(0,tabrkeep,3,1,4,"1=none,2=bin,3=bin+trn,4=bin+trn+glue0");
2617   OPT(0,tabrvfactor,4,1,I,"tabula rasa variable factor");
2618   OPT(0,termint,122222,0,M,"termination check interval");
2619   OPT(0,ternres,1,0,1,"generate ternary resolvents");
2620   OPT(0,ternresboost,5,1,100,"initial ternary reslution boost");
2621   OPT(0,ternresrtc,0,0,1,"run ternary resolvents until completion");
2622   OPT(0,ternreswait,2,0,2,"wait for BCE (1) and/or BVE (2)");
2623   OPT(0,transred,1,0,1,"enable transitive reduction");
2624   OPT(0,transredwait,2,0,2,"wait for BCE (1) and/or BVE (2)");
2625   OPT(0,trdmaxeff,2*M,-1,I,"max effort in transitive reduction");
2626   OPT(0,trdmineff,100*K,0,I,"min effort in transitive reduction");
2627   OPT(0,trdreleff,10,0,10*K,"rel effort in transitive reduction");
2628   OPT(0,treelook,1,0,2,"enable tree-based look-ahead (2=scheduleprobing)");
2629   OPT(0,treelookboost,20,1,100000,"tree-based look-head boost factor");
2630   OPT(0,treelookfull,0,0,1,"do not limit tree-based look-head");
2631   OPT(0,treelooklrg,1,0,1,"use large clauses during tree-look");
2632   OPT(0,treelookmaxeff,50*M,-1,I,"max effort in tree-look based probing");
2633   OPT(0,treelookmineff,300*K,0,I,"min effort in tree-look based probing");
2634   OPT(0,treelookreleff,1,0,10*K,"rel effort in tree-look based probing");
2635   OPT(0,treelookrtc,0,0,1,"run tree-based look-ahead until completion");
2636   OPT(0,trep,0,0,1,"enable time based interval reporting");
2637   OPT(0,trepint,55555,1,I,"interval for time based reporting");
2638   OPT(0,trnreleff,10,0,K,"rel effort in ternary resolutions");
2639   OPT(0,trnrmaxeff,200*M,-1,I,"max effort in ternary resolutions");
2640   OPT(0,trnrmineff,4*M,0,I,"min effort in ternary resolutions");
2641   OPT(0,unhdatrn,2,0,2,"unhide redundant ternary clauses (1=move,2=force)");
2642   OPT(0,unhdextstamp,1,0,1,"used extended stamping features");
2643   OPT(0,unhdhbr,0,0,1,"enable unhiding hyper binary resolution");
2644   OPT(0,unhdlnpr,3,0,I,"unhide no progress round limit");
2645   OPT(0,unhdmaxeff,20*M,-1,I,"max effort in unhiding");
2646   OPT(0,unhdmineff,100*K,0,I,"min effort in unhiding");
2647   OPT(0,unhdreleff,2,0,10*K,"rel effort in unhiding");
2648   OPT(0,unhdroundlim,20,0,100,"unhide round limit");
2649   OPT(0,unhide,1,0,1,"enable unhiding");
2650   OPT(0,unhidewait,0,0,2,"wait for BCE (1) and/or BVE (2)");
2651   OPT(0,wait,1,0,1,"enable or disable all waiting");
2652   OPT(0,waitmax,4,-1,I,"max simps to wait (-1=nomax)");
2653   OPT(0,witness,1,0,1,"print witness");
2654
2655   OPT('c',check,0,0,3,"check level");
2656   OPT('l',log,-1,-1,5,"log level");
2657   OPT('v',verbose,0,-1,4,"verbosity level");
2658
2659   if (lgl->opts->plain.val) lglsetplain (lgl, 1);
2660   if (lgl->opts->drup.val) lglsetdrup (lgl, 1);
2661   if (lgl->opts->druplig.val) lglsetdruplig (lgl, 1);
2662   if (!lgl->opts->wait.val) lglsetwait (lgl, 0);
2663
2664   if (abs (lgl->opts->bias.val) <= 1) lgl->bias = lgl->opts->bias.val;
2665   else lgl->bias = 1;
2666
2667   NEW (lgl->times, 1);
2668   NEW (lgl->timers, 1);
2669   NEW (lgl->limits, 1);
2670   NEW (lgl->fltstr, 1);
2671   NEW (lgl->red, MAXGLUE+1);
2672   NEW (lgl->wchs, 1);
2673   for (i = 0; i < MAXLDFW; i++) lgl->wchs->start[i] = INT_MAX;
2674   lglpushstk (lgl, &lgl->wchs->stk, INT_MAX);
2675   lglpushstk (lgl, &lgl->wchs->stk, INT_MAX);
2676
2677 #ifdef NDBLSCR
2678   lgl->scinc = lglflt (0, 1);
2679 #else
2680   lgl->scinc = 1;
2681 #endif
2682
2683   TRANS (UNUSED);
2684
2685   return lgl;
2686 }
2687
2688 static void lglcopyclonenfork (LGL * dst, LGL * src) {
2689   memcpy (dst->opts, src->opts, sizeof *src->opts);
2690   dst->out = src->out;
2691   if (dst->prefix) lgldelstr (dst, dst->prefix);
2692   dst->prefix = lglstrdup (dst, src->prefix);
2693   if (src->cbs) {
2694     lglinitcbs (dst);
2695     if (src->cbs->onabort) {
2696       dst->cbs->abortstate = src->cbs->abortstate;
2697       dst->cbs->onabort = src->cbs->onabort;
2698     }
2699     if (src->cbs->getime) dst->cbs->getime = src->cbs->getime;
2700   }
2701 }
2702
2703 static void lglcompact (LGL *);
2704
2705 LGL * lglmclone (LGL * orig,
2706                  void * mem,
2707                  lglalloc alloc,
2708                  lglrealloc realloc,
2709                  lgldealloc dealloc) {
2710   size_t max_bytes, current_bytes;
2711   LGL * lgl = orig;
2712   int glue;
2713
2714   if (!orig) return 0;
2715   lglcompact (orig);
2716   LOG (1, "cloning");
2717   lgl = lglnewlgl (mem, alloc, realloc, dealloc);
2718   memcpy (lgl, orig, ((char*)&orig->mem) - (char*) orig);
2719   max_bytes = lgl->stats->bytes.max;
2720   current_bytes = lgl->stats->bytes.current;
2721   memcpy (lgl->stats, orig->stats, sizeof *orig->stats);
2722   lgl->stats->bytes.current = current_bytes;
2723   lgl->stats->bytes.max = max_bytes;
2724
2725   lglcopyclonenfork (lgl, orig);
2726
2727   CLONE (limits, 1);
2728   CLONE (times, 1);
2729   CLONE (timers, 1);            assert (!lgl->timers->nest);
2730   CLONE (fltstr, 1);
2731   CLONE (ext, orig->szext);
2732   CLONE (i2e, orig->szvars);
2733   CLONE (doms, 2*orig->szvars);
2734   CLONE (dvars, orig->szvars);
2735   CLONE (qvars, orig->szvars);
2736   CLONE (avars, orig->szvars);
2737   CLONE (vals, orig->szvars);
2738   CLONE (jwh, 2*orig->szvars);
2739   CLONE (drail, orig->szdrail);
2740
2741   NEW (lgl->red, MAXGLUE+1);
2742   for (glue = 0; glue <= MAXGLUE; glue++) CLONESTK (red[glue]);
2743
2744   NEW (lgl->wchs, 1);
2745   memcpy (lgl->wchs, orig->wchs, sizeof *orig->wchs);
2746   CLONESTK (wchs->stk);
2747
2748   CLONESTK (control);
2749   CLONESTK (clause);
2750   CLONESTK (eclause);
2751   CLONESTK (extend);
2752   CLONESTK (irr);
2753   CLONESTK (trail);
2754   CLONESTK (frames);
2755   CLONESTK (eassume);
2756   CLONESTK (assume);
2757   CLONESTK (fassume);
2758   CLONESTK (learned);
2759   CLONESTK (cassume);
2760   CLONESTK (dsched);
2761 #ifndef NCHKSOL
2762   CLONESTK (orig);
2763 #endif
2764 #ifndef NDEBUG
2765   {
2766     const char * p;
2767     for (p = (char*)&orig->elm; p < (char*)(&orig->repr+1); p++) assert (!*p);
2768   }
2769 #endif
2770   assert (lgl->stats->bytes.current == orig->stats->bytes.current);
2771   assert (lgl->stats->bytes.max <= orig->stats->bytes.max);
2772   lgl->stats->bytes.max = orig->stats->bytes.max;
2773   return lgl;
2774 }
2775
2776 LGL * lglclone (LGL * lgl) {
2777   REQINIT ();
2778   return lglmclone (lgl,
2779                     lgl->mem->state,
2780                     lgl->mem->alloc,
2781                     lgl->mem->realloc,
2782                     lgl->mem->dealloc);
2783 }
2784
2785 void lglchkclone (LGL * lgl) {
2786   REQINITNOTFORKED ();
2787   TRAPI ("chkclone");
2788 #ifdef NLGLPICOSAT
2789   if (!lgl->opts->druplig.val) {
2790     if (lgl->clone) lglrelease (lgl->clone);
2791     lgl->clone = lglclone (lgl);
2792   }
2793 #endif
2794 }
2795
2796 LGL * lglinit (void) { return lglminit (0, 0, 0, 0); }
2797
2798 static int lglmaxoptnamelen (LGL * lgl) {
2799   int res = 0, len;
2800   Opt * o;
2801   for (o = FIRSTOPT (lgl); o <= LASTOPT (lgl); o++)
2802     if ((len = strlen (o->lng)) > res)
2803       res = len;
2804   return res;
2805 }
2806
2807 void lglusage (LGL * lgl) {
2808   char fmt[20];
2809   int len;
2810   Opt * o;
2811   REQINITNOTFORKED ();
2812   len = lglmaxoptnamelen (lgl);
2813   sprintf (fmt, "--%%-%ds", len);
2814   for (o = FIRSTOPT (lgl); o <= LASTOPT (lgl); o++) {
2815     if (o->shrt) fprintf (lgl->out, "-%c|", o->shrt);
2816     else fprintf (lgl->out, "   ");
2817     fprintf (lgl->out, fmt, o->lng);
2818     fprintf (lgl->out, " %s [%d]\n", o->descrp, o->val);
2819   }
2820 }
2821
2822 static int lglignopt (const char * name) {
2823   if (!strcmp (name, "abstime")) return 1;
2824   if (!strcmp (name, "check")) return 1;
2825   if (!strcmp (name, "drup")) return 1;
2826   if (!strcmp (name, "exitonabort")) return 1;
2827   if (!strcmp (name, "log")) return 1;
2828   if (!strcmp (name, "sleeponabort")) return 1;
2829   if (!strcmp (name, "verbose")) return 1;
2830   if (!strcmp (name, "witness")) return 1;
2831   return 0;
2832 }
2833
2834 void lglopts (LGL * lgl, const char * prefix, int ignsome) {
2835   Opt * o;
2836   REQINITNOTFORKED ();
2837   for (o = FIRSTOPT (lgl); o <= LASTOPT (lgl); o++) {
2838     if (ignsome && lglignopt (o->lng)) continue;
2839     fprintf (lgl->out, "%s--%s=%d\n", prefix, o->lng, o->val);
2840   }
2841 }
2842
2843 void lglrgopts (LGL * lgl) {
2844   Opt * o;
2845   REQINITNOTFORKED ();
2846   for (o = FIRSTOPT (lgl); o <= LASTOPT (lgl); o++)
2847     fprintf (lgl->out, "%s %d %d %d\n", o->lng, o->val, o->min, o->max);
2848 }
2849
2850 void lglpcs (LGL * lgl, int mixed) {
2851   int i, printi, printl;
2852   int64_t range;
2853   Opt * o;
2854   REQINITNOTFORKED ();
2855   for (o = FIRSTOPT (lgl); o <= LASTOPT (lgl); o++) {
2856     if (lglignopt (o->lng)) continue;
2857     range = o->max; range -= o->min;
2858     if (range >= 7 && mixed < 0) continue;
2859     printi = printl = 0;
2860     printf ("%s ", o->lng);
2861     if (range < 7) {
2862       printf ("{%d", o->min);
2863       for (i = o->min + 1; i <= o->max; i++) printf (",%d", i);
2864       printf ("}");
2865     } else if (!mixed) {
2866       printf ("[%d,%d]", o->min, o->max);
2867       printi = 1;
2868       printl = (o->min > 0 && range >= 100);
2869     } else if (o->dflt == o->min || o->dflt == o->max) {
2870       printf ("{%d,%d,%d,%d,%d}",
2871         o->min,
2872         (int)(o->min + (1*range + 3)/4),
2873         (int)(o->min + (2*range + 3)/4),
2874         (int)(o->min + (3*range + 3)/4),
2875         o->max);
2876     } else if (o->dflt == o->min + 1) {
2877       printf ("{%d,%d,%d,%d}",
2878         o->min,
2879         o->dflt,
2880         (int)(o->dflt + (o->max - (int64_t) o->dflt)/2),
2881         o->max);
2882     } else if (o->dflt + 1 == o->max) {
2883       printf ("{%d,%d,%d,%d}",
2884         o->min,
2885         (int)(o->min + (o->dflt - (int64_t) o->min)/2),
2886         o->dflt,
2887         o->max);
2888     } else {
2889       assert (o->dflt - o->min >= 2);
2890       assert (o->max - o->dflt >= 2);
2891       printf ("{%d,%d,%d,%d,%d}",
2892         o->min,
2893         (int)(o->min + (o->dflt - (int64_t) o->min)/2),
2894         o->dflt,
2895         (int)(o->dflt + (o->max - (int64_t) o->min)/2),
2896         o->max);
2897     }
2898     printf ("[%d]", o->dflt);
2899     if (printi) printf ("i"); 
2900     if (printl) printf ("l"); 
2901     printf (" # %s\n",o->descrp);
2902   }
2903 }
2904
2905 int lglhasopt (LGL * lgl, const char * opt) {
2906   Opt * o;
2907   REQINITNOTFORKED ();
2908   for (o = FIRSTOPT (lgl); o <= LASTOPT (lgl); o++) {
2909     if (!opt[1] && o->shrt == opt[0]) return 1;
2910     if (!strcmp (o->lng, opt)) return 1;
2911   }
2912   return 0;
2913 }
2914
2915 void * lglfirstopt (LGL * lgl) { return FIRSTOPT (lgl); }
2916
2917 void * lglnextopt (LGL * lgl,
2918                    void * current,
2919                    const char **nameptr,
2920                    int *valptr, int *minptr, int *maxptr) {
2921   Opt * opt = current, * res = opt + 1;
2922   if (res > LASTOPT (lgl)) return 0;
2923   if (nameptr) *nameptr = opt->lng;
2924   if (valptr) *valptr = opt->val;
2925   if (minptr) *minptr = opt->min;
2926   if (maxptr) *maxptr = opt->max;
2927   return res;
2928 }
2929
2930 void lglsetopt (LGL * lgl, const char * opt, int val) {
2931   int oldval;
2932   Opt * o;
2933   REQINITNOTFORKED ();
2934   for (o = FIRSTOPT (lgl); o <= LASTOPT (lgl); o++) {
2935     if (!opt[1] && o->shrt == opt[0]) break;
2936     if (!strcmp (o->lng, opt)) break;
2937   }
2938   if (o > LASTOPT (lgl)) return;
2939   if (val < o->min) val = o->min;
2940   if (o->max < val) val = o->max;
2941   oldval = o->val;
2942   o->val = val;
2943   if (o == &lgl->opts->flipping && !oldval)
2944     lgl->flipping = lgl->notflipped = 0;
2945   if (o == &lgl->opts->plain) {
2946     if (val > 0 && !oldval) lglsetplain (lgl, 1);
2947     if (!val && oldval) lglsetplain (lgl, 0);
2948   }
2949   if (o == &lgl->opts->drup) {
2950     if (val > 0 && !oldval) lglsetdrup (lgl, 1);
2951     if (!val && oldval) lglsetdrup (lgl, 0);
2952   }
2953   if (o == &lgl->opts->druplig) {
2954     if (val > 0 && !oldval) lglsetdruplig (lgl, 1);
2955     if (!val && oldval) lglsetdruplig (lgl, 0);
2956   }
2957   if (o == &lgl->opts->wait) {
2958     if (val > 0 && !oldval) lglsetwait (lgl, 1);
2959     if (!val && oldval) lglsetwait (lgl, 0);
2960   }
2961   if (o == &lgl->opts->phase && val != oldval) lgl->flushphases = 1;
2962   if (lgl->state == UNUSED) TRANS (OPTSET);
2963   TRAPI ("option %s %d", opt, val);
2964 }
2965
2966 static int lglws (int ch) {
2967   return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
2968 }
2969
2970 int lglreadopts (LGL * lgl, FILE * file) {
2971   int res, ch, val, nvalbuf, noptbuf;
2972   char optbuf[40], valbuf[40];
2973   const char * opt;
2974   res = 0;
2975   for (;;) {
2976     while (lglws (ch = getc (file)))
2977       ;
2978     if (ch == EOF) break;
2979     noptbuf = 0;
2980     optbuf[noptbuf++] = ch;
2981     while ((ch = getc (file)) != EOF && !lglws (ch)) {
2982       if (noptbuf + 1 >= sizeof optbuf) { ch = EOF; break; }
2983       optbuf[noptbuf++] = ch;
2984     }
2985     if (ch == EOF) break;
2986     assert (noptbuf < sizeof optbuf);
2987     optbuf[noptbuf++] = 0;
2988     assert (lglws (ch));
2989     while (lglws (ch = getc (file)))
2990       ;
2991     if (ch == EOF) break;
2992     nvalbuf = 0;
2993     valbuf[nvalbuf++] = ch;
2994     while ((ch = getc (file)) != EOF && !lglws (ch)) {
2995       if (nvalbuf + 1 >= sizeof valbuf) break;
2996       valbuf[nvalbuf++] = ch;
2997     }
2998     assert (nvalbuf < sizeof valbuf);
2999     valbuf[nvalbuf++] = 0;
3000     opt = optbuf;
3001     val = atoi (valbuf);
3002     lglprt (lgl, 1, "read option --%s=%d", opt, val);
3003     lglsetopt (lgl, opt, val);
3004     res++;
3005   }
3006   return res;
3007 }
3008
3009 void lglsetout (LGL * lgl, FILE * out) { lgl->out = out; }
3010
3011 FILE * lglgetout (LGL * lgl) { return lgl->out; }
3012
3013 void lglsetprefix (LGL * lgl, const char * prefix) {
3014   lgldelstr (lgl, lgl->prefix);
3015   lgl->prefix = lglstrdup (lgl, prefix);
3016 }
3017
3018 const char * lglgetprefix (LGL * lgl) { return lgl->prefix; }
3019
3020 static Opt * lgligetopt (LGL * lgl, const char * opt) {
3021   Opt * o;
3022   REQINITNOTFORKED ();
3023   for (o = FIRSTOPT (lgl); o <= LASTOPT (lgl); o++) {
3024     if (!opt[1] && o->shrt == opt[0]) return o;
3025     if (!strcmp (o->lng, opt)) return o;
3026   }
3027   return 0;
3028 }
3029
3030 int lglgetopt (LGL * lgl, const char * opt) {
3031   Opt * o = lgligetopt (lgl, opt);
3032   return o ? o->val : 0;
3033 }
3034
3035 int lglgetoptminmax (LGL * lgl, const char * opt,
3036                      int * min_ptr, int * max_ptr) {
3037   Opt * o = lgligetopt (lgl, opt);
3038   if (!o) return 0;
3039   if (min_ptr) *min_ptr = o->min;
3040   if (max_ptr) *max_ptr = o->max;
3041   return o->val;
3042 }
3043
3044 /*------------------------------------------------------------------------*/
3045
3046 static void lglrszvars (LGL * lgl, int new_size) {
3047   int old_size = lgl->szvars;
3048   assert (lgl->nvars <= new_size);
3049   RSZ (lgl->vals, old_size, new_size);
3050   RSZ (lgl->i2e, old_size, new_size);
3051   RSZ (lgl->doms, 2*old_size, 2*new_size);
3052   RSZ (lgl->dvars, old_size, new_size);
3053   RSZ (lgl->avars, old_size, new_size);
3054   RSZ (lgl->qvars, old_size, new_size);
3055   RSZ (lgl->jwh, 2*old_size, 2*new_size);
3056   lgl->szvars = new_size;
3057 }
3058
3059 static void lglenlvars (LGL * lgl) {
3060   size_t old_size, new_size;
3061   old_size = lgl->szvars;
3062   new_size = old_size ? 2 * old_size : 4;
3063   LOG (3, "enlarging internal variables from %ld to %ld", old_size, new_size);
3064   lglrszvars (lgl, new_size);
3065 }
3066
3067 static void lglredvars (LGL * lgl) {
3068   size_t old_size, new_size;
3069   old_size = lgl->szvars;
3070   new_size = lgl->nvars;
3071   if (new_size == old_size) return;
3072   LOG (3, "reducing variables from %ld to %ld", old_size, new_size);
3073   lglrszvars (lgl, new_size);
3074 }
3075
3076 static int lglmax (int a, int b) { return a > b ? a : b; }
3077
3078 static int lglmin (int a, int b) { return a < b ? a : b; }
3079
3080 /*------------------------------------------------------------------------*/
3081
3082 static DVar * lgldvar (LGL * lgl, int lit) {
3083   assert (2 <= abs (lit) && abs (lit) < lgl->nvars);
3084   return lgl->dvars + abs (lit);
3085 }
3086
3087 /*------------------------------------------------------------------------*/
3088
3089 static AVar * lglavar (LGL * lgl, int lit) {
3090   assert (2 <= abs (lit) && abs (lit) < lgl->nvars);
3091   return lgl->avars + abs (lit);
3092 }
3093
3094 static Val lglval (LGL * lgl, int lit) {
3095   int idx = abs (lit);
3096   Val res;
3097   ASSERT (2 <= idx && idx < lgl->nvars);
3098   res = lgl->vals[idx];
3099   if (lit < 0) res = -res;
3100   return res;
3101 }
3102
3103 static int lgltrail (LGL * lgl, int lit) { return lglavar (lgl, lit)->trail; }
3104
3105 static TD * lgltd (LGL * lgl, int lit) {
3106   int pos = lgltrail (lgl, lit);
3107   assert (0 <= pos && pos < lgl->szdrail);
3108   return lgl->drail + pos;
3109 }
3110
3111 static int lglevel (LGL * lgl, int lit) { return lgltd (lgl, lit)->level; }
3112
3113 static int lglisfree (LGL * lgl, int lit) {
3114   return lglavar (lgl, lit)->type == FREEVAR;
3115 }
3116
3117 /*------------------------------------------------------------------------*/
3118
3119 static QVar * lglqvar (LGL * lgl, int lit) {
3120   assert (2 <= abs (lit) && abs (lit) < lgl->nvars);
3121   return lgl->qvars + abs (lit);
3122 }
3123
3124 static int * lgldpos (LGL * lgl, int lit) {
3125   QVar * qv;
3126   int * res;
3127   qv = lglqvar (lgl, lit);
3128   res = &qv->pos;
3129   return res;
3130 }
3131
3132 static int lglscrcmp (Scr a, Scr b) {
3133   if (a < b) return -1;
3134   if (a > b) return 1;
3135   return 0;
3136 }
3137
3138 static int lgldcmp (LGL * lgl, int l, int k) {
3139   QVar * pv = lglqvar (lgl, l);
3140   QVar * qv = lglqvar (lgl, k);
3141   int res;
3142   if ((res = lglscrcmp (pv->score, qv->score))) return res;
3143   res = lgl->bias * (l - k);
3144   return res;
3145 }
3146
3147 #ifndef NDEBUG
3148 static void lglchkdsched (LGL * lgl) {
3149   int * p, parent, child, ppos, cpos, size, i, tmp;
3150   Stk * s = &lgl->dsched;
3151   size = lglcntstk (s);
3152   p = s->start;
3153   for (ppos = 0; ppos < size; ppos++) {
3154     parent = p[ppos];
3155     tmp = *lgldpos (lgl, parent);
3156     assert (ppos == tmp);
3157     for (i = 0; i <= 1; i++) {
3158       cpos = 2*ppos + 1 + i;
3159       if (cpos >= size) continue;
3160       child = p[cpos];
3161       tmp = *lgldpos (lgl, child);
3162       assert (cpos == tmp);
3163       assert (lgldcmp (lgl, parent, child) >= 0);
3164     }
3165   }
3166 }
3167 #endif
3168
3169 static void lgldup (LGL * lgl, int lit) {
3170   int child = lit, parent, cpos, ppos, * p, * cposptr, * pposptr;
3171   Stk * s = &lgl->dsched;
3172   p = s->start;
3173   cposptr = lgldpos (lgl, child);
3174   cpos = *cposptr;
3175   assert (cpos >= 0);
3176   while (cpos > 0) {
3177     ppos = (cpos - 1)/2;
3178     parent = p[ppos];
3179     if (lgldcmp (lgl, parent, lit) >= 0) break;
3180     pposptr = lgldpos (lgl, parent);
3181     assert (*pposptr == ppos);
3182     p[cpos] = parent;
3183     *pposptr = cpos;
3184     LOGDSCHED (5, parent, "down from %d", ppos);
3185     cpos = ppos;
3186   }
3187   if (*cposptr == cpos) return;
3188 #ifndef NLGLOG
3189   ppos = *cposptr;
3190 #endif
3191   *cposptr = cpos;
3192   p[cpos] = lit;
3193   LOGDSCHED (5, lit, "up from %d", ppos);
3194 #ifndef NDEBUG
3195   if (lgl->opts->check.val >= 2) lglchkdsched (lgl);
3196 #endif
3197 }
3198
3199 static void lglddown (LGL * lgl, int lit) {
3200   int parent = lit, child, right, ppos, cpos;
3201   int * p, * pposptr, * cposptr, size;
3202   Stk * s = &lgl->dsched;
3203   size = lglcntstk (s);
3204   p = s->start;
3205   pposptr = lgldpos (lgl, parent);
3206   ppos = *pposptr;
3207   assert (0 <= ppos);
3208   for (;;) {
3209     cpos = 2*ppos + 1;
3210     if (cpos >= size) break;
3211     child = p[cpos];
3212     if (cpos + 1 < size) {
3213       right = p[cpos + 1];
3214       if (lgldcmp (lgl, child, right) < 0) cpos++, child = right;
3215     }
3216     if (lgldcmp (lgl, child, lit) <= 0) break;
3217     cposptr = lgldpos (lgl, child);
3218     assert (*cposptr = cpos);
3219     p[ppos] = child;
3220     *cposptr = ppos;
3221     LOGDSCHED (5, child, "up from %d", cpos);
3222     ppos = cpos;
3223   }
3224   if (*pposptr == ppos) return;
3225 #ifndef NLGLOG
3226   cpos = *pposptr;
3227 #endif
3228   *pposptr = ppos;
3229   p[ppos] = lit;
3230   LOGDSCHED (5, lit, "down from %d", cpos);
3231 #ifndef NDEBUG
3232   if (lgl->opts->check.val >= 2) lglchkdsched (lgl);
3233 #endif
3234 }
3235
3236 static void lgldsched (LGL * lgl, int lit) {
3237   int * p = lgldpos (lgl, lit);
3238   Stk * s = &lgl->dsched;
3239   assert (*p < 0);
3240   *p = lglcntstk (s);
3241   lglpushstk (lgl, s, lit);
3242   lgldup (lgl, lit);
3243   lglddown (lgl, lit);
3244   LOGDSCHED (4, lit, "pushed");
3245 }
3246
3247 static int lgltopdsched (LGL * lgl) {
3248   assert (!lglmtstk (&lgl->dsched));
3249   return lgl->dsched.start[0];
3250 }
3251
3252 static int lglpopdsched (LGL * lgl) {
3253   Stk * s = &lgl->dsched;
3254   int res, last, cnt, * p;
3255   QVar * qv;
3256   assert (!lglmtstk (s));
3257   res = *s->start;
3258   LOGDSCHED (4, res, "popped");
3259   qv = lglqvar (lgl, res);
3260   assert (!qv->pos);
3261   qv->pos = -1;
3262   last = lglpopstk (s);
3263   cnt = lglcntstk (s);
3264   if (!cnt) { assert (last == res); return res; }
3265   p = lgldpos (lgl, last);
3266   assert (*p == cnt);
3267   *p = 0;
3268   *s->start = last;
3269   lglddown (lgl, last);
3270   return res;
3271 }
3272
3273 static void lgldreschedule (LGL * lgl) {
3274   Stk * s = &lgl->dsched;
3275   int idx, i, pos, cnt = lglcntstk (s);
3276   QVar * qv;
3277   LOG (1, "rescheduling %d variables", cnt);
3278   for (idx = 2; idx < lgl->nvars; idx++) lglqvar (lgl, idx)->pos = -1;
3279   pos = 0;
3280   s->top = s->start;
3281   for (i = 0; i < cnt; i++) {
3282     assert (pos <= i);
3283     assert (s->start + pos == s->top);
3284     idx = s->start[i];
3285     if (abs (idx) <= 1) continue;
3286     qv = lglqvar (lgl, idx);
3287     if (!lglisfree (lgl, idx)) { qv->pos = -1; continue; }
3288     assert (qv->pos == -1);
3289     s->start[pos] = idx;
3290     qv->pos = pos++;
3291     s->top++;
3292     lgldup (lgl, idx);
3293     lglddown (lgl, idx);
3294   }
3295   LOG (1, "new schedule with %d variables", lglcntstk (s));
3296   lglfitstk (lgl, s);
3297 #ifndef NDEBUG
3298   if (lgl->opts->check.val >= 1) lglchkdsched (lgl);
3299 #endif
3300 }
3301
3302 #define RVL 2
3303
3304 static void lglrescorevars (LGL * lgl) {
3305   Scr oldscinc, oldscore, newscore, oldmaxscore = 0, newmaxscore = 0;
3306   int64_t newotfs;
3307   QVar * qv;
3308   int idx;
3309   lgl->stats->rescored.vars++;
3310   for (idx = 2; idx < lgl->nvars; idx++) {
3311     qv = lglqvar (lgl, idx);
3312     oldscore = qv->score;
3313     if (oldscore > oldmaxscore) oldmaxscore = oldscore;
3314 #ifdef NDBLSCR
3315     if (lgl->opts->score.val == LGL_SCORE_EVSIDS ||
3316         lgl->opts->score.val == LGL_SCORE_AVG)
3317       newscore = lglshflt (oldscore, lgl->opts->maxscorexp.val);
3318     else newscore = (oldscore >> 32);
3319 #else
3320     newscore = oldscore / lgl->maxscore;
3321 #endif
3322     qv->score = newscore;
3323     if (qv->score > newmaxscore) newmaxscore = qv->score;
3324     LOG (3, "rescored variable %d from %s to %s",
3325          idx, lglscr2str (lgl, oldscore), lglscr2str (lgl, qv->score));
3326   }
3327   lgldreschedule (lgl);
3328   newotfs = lgl->stats->otfs.driving + lgl->stats->otfs.restarting;
3329   assert (newotfs >= lgl->limits->rescore.vars.otfs);
3330   assert (lgl->stats->confs >= lgl->limits->rescore.vars.confs);
3331   lglprt (lgl, RVL,
3332     "[rescored-vars-%d] after %lld conflicts and %lld OTFS",
3333     lgl->stats->rescored.vars,
3334     lgl->stats->confs - lgl->limits->rescore.vars.confs,
3335     newotfs - lgl->limits->rescore.vars.otfs);
3336   lgl->limits->rescore.vars.confs = lgl->stats->confs;
3337   lgl->limits->rescore.vars.otfs = newotfs;
3338   lglprt (lgl, RVL,
3339     "[rescored-vars-%d] old maximum score %s",
3340     lgl->stats->rescored.vars, lglscr2str (lgl, oldmaxscore));
3341   lglprt (lgl, RVL,
3342     "[rescored-vars-%d] new maximum score %s",
3343     lgl->stats->rescored.vars, lglscr2str (lgl, newmaxscore));
3344   if (lgl->opts->score.val == LGL_SCORE_EVSIDS) {
3345     oldscinc = lgl->scinc;
3346 #ifdef NDBLSCR
3347     lgl->scinc = lglshflt (oldscinc, lgl->opts->maxscorexp.val);
3348 #else
3349     lgl->scinc = oldscinc / lgl->maxscore;
3350 #endif
3351     assert (lgl->scinc > 0);
3352     lglprt (lgl, RVL,
3353       "[rescored-vars-%d] old score increment %s",
3354       lgl->stats->rescored.vars, lglscr2str (lgl, oldscinc));
3355     lglprt (lgl, RVL,
3356       "[rescored-vars-%d] new score increment %s",
3357       lgl->stats->rescored.vars, lglscr2str (lgl, lgl->scinc));
3358   }
3359 }
3360
3361 static void lglbumpscinc (LGL * lgl) {
3362   Scr oldscinc;
3363   if (lgl->opts->score.val == LGL_SCORE_VSIDS256) {
3364     if (!(lgl->stats->confs & 255)) {
3365       int idx;
3366       for (idx = 2; idx < lgl->nvars; idx++) {
3367         QVar * qv = lglqvar (lgl, idx);
3368         qv->score /= 2;
3369         if (qv->pos < 0) continue;
3370         lglddown (lgl, idx);
3371       }
3372     }
3373   } else if (lgl->opts->score.val == LGL_SCORE_EVSIDS) {
3374     oldscinc = lgl->scinc;
3375     lgl->scinc = lglmulscr (oldscinc, lgl->scincf);
3376     LOG (3, "bumped variable score increment from %s to %s",
3377          lglscr2str (lgl, oldscinc), lglscr2str (lgl, lgl->scinc));
3378     if (lgl->scinc < lgl->maxscore) return;
3379     LOG (2, "variable max score %s hit", lglscr2str (lgl, lgl->maxscore));
3380     lglrescorevars (lgl);
3381   }
3382 }
3383
3384 /*------------------------------------------------------------------------*/
3385
3386 static int lglnewvar (LGL * lgl) {
3387   AVar * av;
3388   DVar * dv;
3389   QVar * qv;
3390   int res;
3391   assert (!lgl->dense);
3392   if (lgl->nvars == lgl->szvars) lglenlvars (lgl);
3393   if (lgl->nvars) res = lgl->nvars++;
3394   else res = 2, lgl->nvars = 3;
3395   assert (res < lgl->szvars);
3396   if (res > MAXVAR) lgldie (lgl, "more than %d variables", MAXVAR - 1);
3397   assert (res <= MAXVAR);
3398   assert (((res << RMSHFT) >> RMSHFT) == res);
3399   assert (((-res << RMSHFT) >> RMSHFT) == -res);
3400   LOG (3, "new internal variable %d", res);
3401   dv = lgl->dvars + res;
3402   CLRPTR (dv);
3403   av = lgl->avars + res;
3404   CLRPTR (av);
3405   qv = lgl->qvars + res;
3406   CLRPTR (qv);
3407   qv->pos = -1;
3408   lgldsched (lgl, res);
3409   lgl->unassigned++;
3410   lgl->allphaseset = 0;
3411   return res;
3412 }
3413
3414 static int lglsgn (int lit) { return (lit < 0) ? -1 : 1; }
3415
3416 static Ext * lglelit2ext (LGL * lgl, int elit) {
3417   int idx = abs (elit);
3418   assert (0 < idx), assert (idx <= lgl->maxext);
3419   return lgl->ext + idx;
3420 }
3421
3422 #if 0
3423 static Ext * lgldlit2ext (LGL * lgl, int dlit) {
3424   int idx = abs (dlit);
3425   assert (0 < idx), assert (idx <= lgl->maxdef);
3426   return lgl->def + idx;
3427 }
3428 #endif
3429
3430 static int lglerepr (LGL * lgl, int elit) {
3431   int res, next, tmp;
3432   Ext * ext;
3433   assert (0 < abs (elit)), assert (abs (elit) <= lgl->maxext);
3434   res = elit;
3435   for (;;) {
3436     ext = lglelit2ext (lgl, res);
3437     if (!ext->equiv) break;
3438     next = ext->repr;
3439     if (res < 0) next = -next;
3440     res = next;
3441   }
3442   tmp = elit;
3443   for (;;) {
3444     ext = lglelit2ext (lgl, tmp);
3445     if (!ext->equiv) { assert (tmp == res); break; }
3446     next = ext->repr;
3447     ext->repr = (tmp < 0) ? -res : res;
3448     if (tmp < 0) next = -next;
3449     tmp = next;
3450   }
3451   return res;
3452 }
3453
3454 static void lgladjext (LGL * lgl, int eidx) {
3455   size_t old, new;
3456   assert (eidx >= lgl->szext);
3457   assert (eidx > lgl->maxext);
3458   assert (lgl->szext >= lgl->maxext);
3459   old = lgl->szext;
3460   new = old ? 2*old : 2;
3461   while (eidx >= new) new *= 2;
3462   assert (eidx < new), assert (new >= lgl->szext);
3463   LOG (3, "enlarging external variables from %ld to %ld", old, new);
3464   RSZ (lgl->ext, old, new);
3465   lgl->szext = new;
3466 }
3467
3468 #if 0
3469 static void lgladjdef (LGL * lgl, int didx) {
3470   size_t old, new;
3471   assert (didx);
3472   assert (didx >= lgl->szdef);
3473   assert (didx > lgl->maxdef);
3474   assert (lgl->szdef > lgl->maxdef);
3475   old = lgl->szdef;
3476   new = old ? 2*old : 2;
3477   while (didx >= new) new *= 2;
3478   assert (didx < new), assert (new >= lgl->szdef);
3479   LOG (3, "enlarging defined variables from %ld to %ld", old, new);
3480   RSZ (lgl->def, old, new);
3481   lgl->szdef = new;
3482 }
3483 #endif
3484
3485 static void lglmelter (LGL * lgl) {
3486   if (lgl->allfrozen) {
3487     lglprt (lgl, 1,
3488       "[melter] not all literals assumed to be frozen anymore");
3489     lgl->allfrozen = 0;
3490   }
3491   if (lgl->limits->elm.pen || lgl->limits->blk.pen || lgl->limits->cce.pen) {
3492     lglprt (lgl, 1,
3493       "[melter] reset penalties: %d elm, %d blk, %d cce",
3494       lgl->limits->elm.pen, lgl->limits->blk.pen, lgl->limits->cce.pen);
3495     lgl->limits->elm.pen = lgl->limits->blk.pen = lgl->limits->cce.pen = 0;
3496   }
3497   lgl->frozen = lgl->allfrozen = 0;
3498   LOG (2, "melted solver");
3499 }
3500
3501 static int lglimportaux (LGL * lgl, int elit) {
3502   int res, repr, eidx = abs (elit);
3503   Ext * ext;
3504   assert (elit);
3505   if (eidx >= lgl->szext) lgladjext (lgl, eidx);
3506   if (eidx > lgl->maxext) {
3507     lgl->maxext = eidx;
3508     lglmelter (lgl);
3509   }
3510   repr = lglerepr (lgl, elit);
3511   ext = lglelit2ext (lgl, repr);
3512   assert (!ext->equiv);
3513   res = ext->repr;
3514   if (!ext->imported) {
3515     res = lglnewvar (lgl);
3516     assert (!ext->equiv);
3517     ext->repr = res;
3518     ext->imported = 1;
3519     assert (eidx <= INT_MAX/2);
3520     lgl->i2e[res] = 2*eidx;
3521     LOG (3, "mapping external variable %d to %d", eidx, res);
3522     lglmelter (lgl);
3523   }
3524   if (repr < 0) res = -res;
3525   LOG (2, "importing %d as %d", elit, res);
3526   return res;
3527 }
3528
3529 static int lglimport (LGL * lgl, int elit) {
3530   assert (elit);
3531   if (!lgl->opts->import.val) {
3532     if (!lgl->maxext) (void) lglimportaux (lgl, 1);
3533     while (lgl->maxext < abs (elit))
3534       (void) lglimportaux (lgl, lgl->maxext + 1);
3535   }
3536   return lglimportaux (lgl, elit);
3537 }
3538
3539 static Stk * lglidx2stk (LGL * lgl, int red, int lidx) {
3540   int glue = 0;
3541   Stk * s;
3542   assert (red == 0 || red == REDCS);
3543   assert (0 <= lidx);
3544   if (!red) s = &lgl->irr;
3545   else {
3546     glue = lidx & GLUEMASK;
3547     lidx >>= GLUESHFT;
3548     assert (lidx <= MAXREDLIDX);
3549     s = &lgl->red[glue];
3550   }
3551   return s;
3552 }
3553
3554 static int * lglidx2lits (LGL * lgl, int red, int lidx) {
3555   Stk * s = lglidx2stk (lgl, red, lidx);
3556   int * res;
3557   assert (red == 0 || red == REDCS);
3558   assert (0 <= lidx);
3559   res = s->start + (red ? (lidx >> GLUESHFT) : lidx);
3560 #ifndef NDEBUG
3561   if (red && (lidx & GLUEMASK) == MAXGLUE) assert (res < s->end);
3562   else assert (res < s->top);
3563 #endif
3564   return res;
3565 }
3566
3567 #ifndef NLGLOG
3568 static const char * lglred2str (int red) {
3569   assert (!red || red == REDCS);
3570   return red ? "redundant" : "irredundant";
3571 }
3572 #endif
3573
3574 static int lgliselim (LGL * lgl, int lit) {
3575   Tag tag = lglavar (lgl, lit)->type;
3576   return tag == ELIMVAR;
3577 }
3578
3579 #if 0
3580 static int lglisdef (LGL * lgl, int ilit) {
3581   int iidx = abs (ilit), tidx, res;
3582   assert (2 <= iidx), assert (iidx < lgl->nvars);
3583   tidx = lgl->i2e[iidx];
3584   res = tidx & 1;
3585   return res;
3586 }
3587 #endif
3588
3589 static int lglexport (LGL * lgl, int ilit) {
3590   int iidx, tidx, eidx, def, res;
3591   iidx = abs (ilit);
3592   assert (2 <= iidx), assert (iidx < lgl->nvars);
3593   tidx = lgl->i2e[iidx];
3594   def = tidx & 1;
3595   tidx >>= 1;
3596   assert (tidx);
3597   eidx = tidx;
3598   if (def) eidx += lgl->maxext;
3599   res = eidx;
3600   if (ilit < 0) res = -res;
3601   return res;
3602 }
3603
3604 static int * lglrsn (LGL * lgl, int lit) { return lgltd (lgl, lit)->rsn; }
3605
3606 static int lglulit (int lit) { return 2*abs (lit) + (lit < 0); }
3607
3608 static void lglsetdom (LGL * lgl, int lit, int dom) {
3609   assert (2 <= abs (lit)  && abs (lit) < lgl->nvars);
3610   assert (2 <= abs (dom)  && abs (dom) < lgl->nvars);
3611   ASSERT (lglval (lgl, lit) >= 0);
3612   ASSERT (lglval (lgl, dom) >= 0);
3613   lgl->doms[lglulit (lit)] = dom;
3614   LOG (3, "literal %d dominated by %d", lit, dom);
3615 }
3616
3617 static int lglgetdom (LGL * lgl, int lit) {
3618   int res;
3619   assert (2 <= abs (lit)  && abs (lit) < lgl->nvars);
3620   assert (lglval (lgl, lit) >= 0);
3621   res = lgl->doms[lglulit (lit)];
3622   return res;
3623 }
3624
3625 static HTS * lglhts (LGL * lgl, int lit) {
3626   return lgldvar (lgl, lit)->hts + (lit < 0);
3627 }
3628
3629 static int * lglhts2wchs (LGL * lgl, HTS * hts) {
3630   int * res = lgl->wchs->stk.start + hts->offset;
3631   assert (res < lgl->wchs->stk.top);
3632   assert (res + hts->count < lgl->wchs->stk.top);
3633   assert (res + hts->count < lgl->wchs->stk.top);
3634   return res;
3635 }
3636
3637 static void lglassign (LGL * lgl, int lit, int r0, int r1) {
3638   int * p, other, other2, * c, lidx, found;
3639   int idx, phase, glue, tag, dom, red, irr;
3640   AVar * av = lglavar (lgl, lit);
3641   TD * td;
3642   LOGREASON (2, lit, r0, r1, "assign %d through", lit);
3643   av->trail = lglcntstk (&lgl->trail);
3644   if (av->trail >= lgl->szdrail) {
3645     int newszdrail = lgl->szdrail ? 2*lgl->szdrail : 1;
3646     RSZ (lgl->drail, lgl->szdrail, newszdrail);
3647     lgl->szdrail = newszdrail;
3648   }
3649   td = lgltd (lgl, lit);
3650   tag = r0 & MASKCS;
3651   dom = (tag == BINCS) ? lglgetdom (lgl, -(r0 >> RMSHFT)) : lit;
3652   lglsetdom (lgl, lit, dom);
3653 #ifndef NDEBUG
3654   {
3655     if (tag == BINCS || tag == TRNCS) {
3656       other = r0 >> RMSHFT;
3657       assert (lglval (lgl, other) < 0);
3658       if (tag == TRNCS) {
3659         other2 = r1;
3660         assert (lglval (lgl, other2) < 0);
3661       }
3662     } else if (tag == LRGCS) {
3663       red = r0 & REDCS;
3664       lidx = r1;
3665       c = lglidx2lits (lgl, red, lidx);
3666       found = 0;
3667       for (p = c; (other = *p); p++)
3668         if (other == lit) found++;
3669         else assert (lglval (lgl, other) < 0);
3670       assert (found == 1);
3671     } else assert (tag == DECISION || tag == UNITCS);
3672   }
3673   assert (!lglval (lgl, lit));
3674   assert (lgl->unassigned > 0);
3675   assert (!lgliselim (lgl, lit));
3676 #endif
3677   idx = abs (lit);
3678   phase = lglsgn (lit);
3679   lgl->vals[idx] = phase;
3680   if (!lgl->simp && !lgl->flipping && !lgl->phaseneg) {
3681     lgl->flips -= lgl->flips/100000ull;
3682     if (av->phase != phase) lgl->flips += 10000ull;
3683     av->phase = phase;
3684   }
3685 #ifndef NDEBUG
3686   if (phase < 0) av->wasfalse = 1; else av->wasfalse = 0;
3687 #endif
3688   td->level = lgl->level;
3689   if (!lgl->level) {
3690     td->irr = 1;
3691     if (av->type == EQUIVAR) {
3692       assert (lgl->stats->equiv.current > 0);
3693       lgl->stats->equiv.current--;
3694       assert (lgl->stats->equiv.sum > 0);
3695       lgl->stats->equiv.sum--;
3696     } else {
3697       assert (av->type == FREEVAR);
3698       av->type = FIXEDVAR;
3699     }
3700     lgl->stats->fixed.sum++;
3701     lgl->stats->fixed.current++;
3702     lgl->stats->prgss++;
3703     lgl->stats->irrprgss++;
3704     td->rsn[0] = UNITCS | (lit << RMSHFT);
3705     td->rsn[1] = 0;
3706     if (lgl->cbs && lgl->cbs->units.produce.fun) {
3707       LOG (2, "trying to export internal unit %d external %d\n",
3708            lgl->tid, lit, lglexport (lgl, lit));
3709       lgl->stats->sync.units.produced++;
3710       lgl->cbs->units.produce.fun (lgl->cbs->units.produce.state,
3711                                   lglexport (lgl, lit));
3712       LOG (2, "exporting internal unit %d external %d\n",
3713               lgl->tid, lit, lglexport (lgl, lit));
3714     }
3715   } else {
3716     td->rsn[0] = r0;
3717     td->rsn[1] = r1;
3718     if (lgl->level == 1) {
3719       assert (tag != UNITCS);
3720       if (tag == DECISION) irr = 1;
3721       else if ((irr = !(red = (r0 & REDCS)))) {
3722         if (tag == BINCS) {
3723           other = r0 >> RMSHFT;
3724           irr = lgltd (lgl, other)->irr;
3725         } else if (tag == TRNCS) {
3726           other = r0 >> RMSHFT;
3727           if ((irr = lgltd (lgl, other)->irr)) {
3728             other2 = r1;
3729             irr = lgltd (lgl, other2)->irr;
3730           }
3731         } else {
3732           assert (tag == LRGCS);
3733           lidx = r1;
3734           c = lglidx2lits (lgl, red, lidx);
3735           found = 0;
3736           for (p = c; irr && (other = *p); p++)
3737             if (other == lit) found++;
3738             else irr = lgltd (lgl, other)->irr;
3739           assert (!irr || found == 1);
3740         }
3741       }
3742     } else irr = 0;
3743     td->irr = irr;
3744   }
3745
3746   lglpushstk (lgl, &lgl->trail, lit);
3747   if (!lgl->failed && (av->assumed & (1u << (lit > 0)))) {
3748     LOG (2, "failed assumption %d", -lit);
3749     lgl->failed = -lit;
3750   }
3751   lgl->unassigned--;
3752   td->lrglue = 0;
3753   if ((r0 & REDCS) && (r0 & MASKCS) == LRGCS) {
3754     glue = r1 & GLUEMASK;
3755     lgl->stats->lir[glue].forcing++;
3756     assert (lgl->stats->lir[glue].forcing > 0);
3757     if (lgl->level && 0 < glue && glue < MAXGLUE) {
3758       lgl->lrgluereasons++;
3759       assert (lgl->lrgluereasons > 0);
3760       td->lrglue = 1;
3761     }
3762 #ifndef NDEBUG
3763     if (glue == MAXGLUE)
3764       assert ((r1 >> GLUESHFT) + 4 < lglcntstk (&lgl->red[MAXGLUE]));
3765 #endif
3766   }
3767 }
3768
3769 static void lglf2rce (LGL * lgl, int lit, int other, int red) {
3770   assert (lglval (lgl, other) < 0);
3771   assert (!red || red == REDCS);
3772   assert (!lgliselim (lgl, other));
3773   lglassign (lgl, lit, ((other << RMSHFT) | BINCS | red), 0);
3774 }
3775
3776 static void lglf3rce (LGL * lgl, int lit, int other, int other2, int red) {
3777   assert (lglval (lgl, other) < 0);
3778   assert (lglval (lgl, other2) < 0);
3779   assert (!lgliselim (lgl, other));
3780   assert (!lgliselim (lgl, other2));
3781   assert (!red || red == REDCS);
3782   lglassign (lgl, lit, ((other << RMSHFT) | TRNCS | red), other2);
3783 }
3784
3785 static void lglflrce (LGL * lgl, int lit, int red, int lidx) {
3786 #ifndef NDEBUG
3787   int * p = lglidx2lits (lgl, red, lidx), other;
3788   while ((other = *p++)) {
3789     assert (!lgliselim (lgl, other));
3790     if (other != lit) assert (lglval (lgl, other) < 0);
3791   }
3792   assert (red == 0 || red == REDCS);
3793 #endif
3794   lglassign (lgl, lit, red | LRGCS, lidx);
3795 }
3796
3797 static int lgldscheduled (LGL * lgl, int lit) {
3798   return lglqvar (lgl, lit)->pos >= 0;
3799 }
3800
3801 static void lglunassign (LGL * lgl, int lit) {
3802   int idx = abs (lit), r0, r1, tag, lidx, glue;
3803   TD *  td;
3804   LOG (2, "unassign %d", lit);
3805   assert (lglval (lgl, lit) > 0);
3806   assert (lgl->vals[idx] == lglsgn (lit));
3807   lgl->vals[idx] = 0;
3808   lgl->unassigned++;
3809   assert (lgl->unassigned > 0);
3810   if (!lgldscheduled (lgl, lit)) lgldsched (lgl, idx);
3811   td = lgltd (lgl, idx);
3812   r0 = td->rsn[0];
3813   if (!(r0 & REDCS)) return;
3814   tag = r0 & MASKCS;
3815   if (tag != LRGCS) return;
3816   r1 = td->rsn[1];
3817   glue = r1 & GLUEMASK;
3818   if (td->lrglue) {
3819     assert (lgl->lrgluereasons > 0);
3820     lgl->lrgluereasons--;
3821   }
3822   if (glue < MAXGLUE) return;
3823   lidx = r1 >> GLUESHFT;
3824   LOG (2, "eagerly deleting maximum glue clause at %d", lidx);
3825   lglrststk (&lgl->red[glue], lidx);
3826 }
3827
3828 static Val lglifixed (LGL * lgl, int lit) {
3829   int res;
3830   if (!(res = lglval (lgl, lit))) return 0;
3831   if (lglevel (lgl, lit) > 0) return 0;
3832   return res;
3833 }
3834
3835 static void lglbacktrack (LGL * lgl, int level) {
3836   int lit;
3837   assert (level >= 0);
3838   assert (lgl->level > level);
3839   LOG (2, "backtracking to level %d", level);
3840   assert (level <= lgl->level);
3841   assert (abs (lgl->failed) != 1 || lgl->failed == -1);
3842   if (lgl->failed &&
3843       lgl->failed != -1 &&
3844       lglevel (lgl, lgl->failed) > level) {
3845     LOG (2, "resetting failed assumption %d", lgl->failed);
3846     lgl->failed = 0;
3847   }
3848   while (!lglmtstk (&lgl->trail)) {
3849     lit = lgltopstk (&lgl->trail);
3850     assert (abs (lit) > 1);
3851     if (lglevel (lgl, lit) <= level) break;
3852     lglunassign (lgl, lit);
3853     lgl->trail.top--;
3854   }
3855   if (!level) {
3856     assert (!lgl->lrgluereasons);
3857     while (!lglmtstk (&lgl->red[MAXGLUE])) {
3858       int tmp = lglpopstk (&lgl->red[MAXGLUE]);
3859       assert (tmp >= NOTALIT);
3860       (void) tmp;
3861     }
3862   }
3863   if (lgl->alevel > level) {
3864     LOG (2,
3865          "resetting assumption decision level to %d from %d",
3866          level, lgl->alevel);
3867     lgl->alevel = level;
3868     if (lgl->assumed) {
3869       LOG (2,
3870            "resetting assumption queue level to 0 from %d",
3871            lgl->assumed);
3872       lgl->assumed = 0;
3873     }
3874   }
3875   lgl->level = level;
3876   lglrstcontrol (lgl, level + 1);
3877   assert (lglcntctk (&lgl->control) == lgl->level + 1);
3878   lgl->conf.lit = 0;
3879   lgl->conf.rsn[0] = lgl->conf.rsn[1] = 0;
3880   lgl->next2 = lgl->next = lglcntstk (&lgl->trail);
3881   LOG (2, "backtracked ");
3882 }
3883
3884 static int lglmarked (LGL * lgl, int lit) {
3885   int res = lglavar (lgl, lit)->mark;
3886   if (lit < 0) res = -res;
3887   return res;
3888 }
3889
3890 static void lgldrupinc (LGL * lgl) {
3891   assert (lgl->opts->drup.val);
3892   if (lgl->stats->drupped++) return;
3893   printf ("o proof DRUP\n");
3894 }
3895
3896 static void lgldrupclsaux (LGL * lgl, const int * cls) {
3897   const int * p;
3898   lgldrupinc (lgl);
3899   for (p = cls; *p;  p++) printf ("%d ", lglexport (lgl, *p));
3900   printf ("0\n");
3901   fflush (stdout);
3902 }
3903
3904 static void lgldrupcls (LGL * lgl) {
3905   lgldrupclsaux (lgl, lgl->clause.start);
3906 }
3907
3908 static void lgldrupclsarg (LGL * lgl, int first, ...) {
3909   va_list ap;
3910   int lit;
3911   assert (lgl->opts->drup.val);
3912   lgldrupinc (lgl);
3913   printf ("%d", first ? lglexport (lgl, first) : 0);
3914   if (first) {
3915     va_start (ap, first);
3916     do { 
3917       lit = va_arg (ap, int);
3918       printf (" %d", lit ? lglexport (lgl, lit) : 0);
3919     } while (lit);
3920   }
3921   printf ("\n");
3922   fflush (stdout);
3923 }
3924
3925 #ifndef NLGLPICOSAT
3926
3927 #define PICOSAT (assert (lgl && lgl->picosat.solver), lgl->picosat.solver)
3928
3929 #ifndef NDEBUG
3930 static void lglpicosataddcls (LGL* lgl, const int * c){
3931   const int * p;
3932   lglpicosatinit (lgl);
3933   for (p = c; *p; p++) picosat_add (PICOSAT, *p);
3934   picosat_add (PICOSAT, 0);
3935 }
3936 #endif
3937
3938 static void lglpicosatchkclsaux (LGL * lgl, int * c) {
3939 #ifndef NDEBUG
3940   int * p;
3941   lglpicosatinit (lgl);
3942   if (picosat_inconsistent (PICOSAT)) {
3943     LOG (3, "no need to check since PicoSAT is already inconsistent");
3944     return;
3945   }
3946   LOGCLS (3, c, "checking consistency with PicoSAT of clause");
3947   for (p = c; *p; p++) picosat_assume (PICOSAT, -*p);
3948   (void) picosat_sat (PICOSAT, -1);
3949   assert (picosat_res (PICOSAT) == 20);
3950 #endif
3951 }
3952
3953 static void lglpicosatchkcls (LGL * lgl) {
3954   lglpicosatchkclsaux (lgl, lgl->clause.start);
3955 }
3956
3957 static void lglpicosatchkclsarg (LGL * lgl, int first, ...) {
3958 #ifndef NDEBUG
3959   va_list ap;
3960   Stk stk;
3961   int lit;
3962   if (!lgl->opts->check.val) return;
3963   lglpicosatinit (lgl);
3964   CLR (stk);
3965   if (first) {
3966     va_start (ap, first);
3967     lglpushstk (lgl, &stk, first);
3968     for (;;) {
3969       lit = va_arg (ap, int);
3970       if (!lit) break;
3971       lglpushstk (lgl, &stk, lit);
3972     }
3973     va_end (ap);
3974   }
3975   lglpushstk (lgl, &stk, 0);
3976   lglpicosatchkclsaux (lgl, stk.start);
3977   lglrelstk (lgl, &stk);
3978 #endif
3979 }
3980
3981 static void lglpicosatchkunsat (LGL * lgl) {
3982 #ifndef NDEBUG
3983   int res, * p;
3984   lglpicosatinit (lgl);
3985   if (lgl->picosat.res) {
3986     LOG (1, "determined earlier that PicoSAT proved unsatisfiability");
3987     assert (lgl->picosat.res == 20);
3988   }
3989   if (picosat_inconsistent (PICOSAT)) {
3990     LOG (1, "PicoSAT is already in inconsistent state");
3991     return;
3992   }
3993   for (p = lgl->eassume.start; p < lgl->eassume.top; p++)
3994     picosat_assume (PICOSAT, lglimport (lgl, *p));
3995   res = picosat_sat (PICOSAT, -1);
3996   assert (res == 20);
3997   LOG (1, "PicoSAT proved unsatisfiability");
3998 #endif
3999 }
4000 #endif
4001
4002 static void lglunitnocheck (LGL * lgl, int lit) {
4003   ASSERT (!lgl->level);
4004   LOG (1, "unit %d", lit);
4005   lglassign (lgl, lit, (lit << RMSHFT) | UNITCS, 0);
4006 }
4007
4008 #ifndef NLGLDRUPLIG
4009 static int lgldruplig (LGL * lgl) {
4010   if (!lgl->opts->druplig.val) return 0;
4011   if (!lgl->druplig) lgl->druplig = druplig_init ();
4012   return 1;
4013 }
4014 #endif
4015
4016 static void lgldrupligaddclsarg (LGL * lgl, int red, ...) {
4017 #ifndef NLGLDRUPLIG
4018   if (lgldruplig (lgl)) {
4019     va_list ap;
4020     va_start (ap, red);
4021     for (;;) {
4022       int lit = va_arg (ap, int);
4023       if (!lit) break;
4024       druplig_add_literal (lgl->druplig, lglexport (lgl, lit));
4025     }
4026     if (red) druplig_check_and_add_redundant_clause (lgl->druplig);
4027     else druplig_add_original_clause (lgl->druplig);
4028   }
4029 #else
4030   (void) lgl, (void) red;
4031 #endif
4032 }
4033
4034 static void lglunit (LGL * lgl, int lit) {
4035   if (lgl->opts->drup.val) lgldrupclsarg (lgl, lit, 0);
4036 #ifndef NLGLPICOSAT
4037   lglpicosatchkclsarg (lgl, lit, 0);
4038 #endif
4039   lgldrupligaddclsarg (lgl, REDCS, lglexport (lgl, lit), 0);
4040   lglunitnocheck (lgl, lit);
4041 }
4042
4043 static void lglmark (LGL * lgl, int lit) {
4044   lglavar (lgl, lit)->mark = lglsgn (lit);
4045 }
4046
4047 static void lglmarkunmarked (LGL * lgl, int lit) {
4048   AVar * av = lglavar (lgl, lit);
4049   assert (!av->mark);
4050   av->mark = lglsgn (lit);
4051 }
4052
4053 static void lglunmark (LGL * lgl, int lit) { lglavar (lgl, lit)->mark = 0; }
4054
4055 static void lglchksimpcls (LGL * lgl) {
4056 #ifndef NDEBUG
4057   int *p, tmp, lit;
4058   AVar * av;
4059   for (p = lgl->clause.start; (lit = *p); p++) {
4060     tmp = lglifixed (lgl, lit);
4061     assert (!tmp);
4062     av = lglavar (lgl, lit);
4063     assert (!av->simp);
4064     av->simp = 1;
4065   }
4066   while (p > lgl->clause.start)
4067     lglavar (lgl,  *--p)->simp = 0;
4068 #endif
4069 }
4070
4071 static int lglcval (LGL * lgl, int litorval) {
4072   assert (litorval);
4073   if (litorval == 1 || litorval == -1) return litorval;
4074   return lglval (lgl, litorval);
4075 }
4076
4077 /*------------------------------------------------------------------------*/
4078
4079 static int lglsimpcls (LGL * lgl) {
4080   int * p, * q = lgl->clause.start, lit, tmp, mark;
4081   for (p = lgl->clause.start; (lit = *p); p++) {
4082     tmp = lglcval (lgl, lit);
4083     if (tmp == 1) { LOG (4, "literal %d satisfies clauses", lit); break; }
4084     if (tmp == -1) { LOG (4, "removing false literal %d", lit); continue; }
4085     mark = lglmarked (lgl, lit);
4086     if (mark > 0)
4087       { LOG (4, "removing duplicated literal %d", lit); continue; }
4088     if (mark < 0)
4089       { LOG (4, "literals %d and %d occur both", -lit, lit); break; }
4090     *q++ = lit;
4091     lglmark (lgl, lit);
4092   }
4093
4094   *q = 0;
4095   lgl->clause.top = q + 1;
4096
4097   while (q > lgl->clause.start) lglunmark (lgl, *--q);
4098
4099   if (lit) LOG (2, "simplified clause is trivial");
4100   else LOGCLS (2, lgl->clause.start, "simplified clause");
4101
4102   return lit;
4103 }
4104
4105 static void lglorderclsaux (LGL * lgl, int * start) {
4106   int * p, max = 0, level, lit;
4107   for (p = start; (lit = *p); p++) {
4108     if (!lglval (lgl, lit)) continue;
4109     level = lglevel (lgl, lit);
4110     if (level <= max) continue;
4111     max = level;
4112     *p = start[0];
4113     start[0] = lit;
4114   }
4115 }
4116
4117 static void lglordercls (LGL * lgl) {
4118   assert (lglcntstk (&lgl->clause) > 2);
4119   lglorderclsaux (lgl, lgl->clause.start);
4120   LOG (3, "head literal %d", lgl->clause.start[0]);
4121   lglorderclsaux (lgl, lgl->clause.start  + 1);
4122   LOG (3, "tail literal %d", lgl->clause.start[1]);
4123   LOGCLS (3, lgl->clause.start, "ordered clause");
4124 }
4125 /*------------------------------------------------------------------------*/
4126
4127
4128 static void lglfreewch (LGL * lgl, int oldoffset, int oldhcount) {
4129   int ldoldhcount = lglceilld (oldhcount);
4130   lgl->wchs->stk.start[oldoffset] = lgl->wchs->start[ldoldhcount];
4131   assert (oldoffset);
4132   lgl->wchs->start[ldoldhcount] = oldoffset;
4133   lgl->wchs->free++;
4134   assert (lgl->wchs->free > 0);
4135   LOG (5, "saving watch stack at %d of size %d on free list %d",
4136        oldoffset, oldhcount, ldoldhcount);
4137 }
4138
4139 static void lglshrinkhts (LGL * lgl, HTS * hts, int newcount) {
4140   int * p, i, oldcount = hts->count;
4141   assert (newcount <= oldcount);
4142   if (newcount == oldcount) return;
4143   p = lglhts2wchs (lgl, hts);
4144   for (i = newcount; i < oldcount; i++) p[i] = 0;
4145   hts->count = newcount;
4146   if (newcount) return;
4147   lglfreewch (lgl, hts->offset, oldcount);
4148   hts->offset = 0;
4149 }
4150
4151 static long lglenlwchs (LGL * lgl, HTS * hts) {
4152   int oldhcount = hts->count, oldoffset = hts->offset, newoffset;
4153   int oldwcount, newwcount, oldwsize, newwsize, i, j;
4154   int newhcount = oldhcount ? 2*oldhcount : 1;
4155   int * oldwstart, * newwstart, * start;
4156   int ldnewhcount = lglfloorld (newhcount);
4157   long res = 0;
4158
4159   newhcount = (1<<ldnewhcount);
4160   assert (newhcount > oldhcount);
4161
4162   LOG (5, "increasing watch stack at %d from %d to %d",
4163        oldoffset, oldhcount, newhcount);
4164
4165   assert (!oldoffset == !oldhcount);
4166
4167   lgl->stats->enlwchs++;
4168
4169   newoffset = lgl->wchs->start[ldnewhcount];
4170   start = lgl->wchs->stk.start;
4171   if (newoffset != INT_MAX) {
4172     lgl->wchs->start[ldnewhcount] = start[newoffset];
4173     start[newoffset] = 0;
4174     assert (lgl->wchs->free > 0);
4175     lgl->wchs->free--;
4176     LOG (5, "reusing free watch stack at %d of size %d",
4177          newoffset, (1 << ldnewhcount));
4178   } else {
4179     assert (lgl->wchs->stk.start[hts->offset]);
4180     assert (lgl->wchs->stk.top[-1] == INT_MAX);
4181
4182     oldwcount = lglcntstk (&lgl->wchs->stk);
4183     newwcount = oldwcount + newhcount;
4184     oldwsize = lglszstk (&lgl->wchs->stk);
4185     newwsize = oldwsize;
4186
4187     assert (lgl->wchs->stk.top == lgl->wchs->stk.start + oldwcount);
4188     assert (oldwcount > 0);
4189
4190     while (newwsize < newwcount) newwsize *= 2;
4191     if (newwsize > oldwsize) {
4192       newwstart = oldwstart = lgl->wchs->stk.start;
4193       RSZ (newwstart, oldwsize, newwsize);
4194       LOG (3, "resized global watcher stack from %d to %d",
4195            oldwsize, newwsize);
4196       res = newwstart - oldwstart;
4197       if (res) {
4198         LOG (3, "moved global watcher stack by %ld", res);
4199         start = lgl->wchs->stk.start = newwstart;
4200       }
4201       lgl->wchs->stk.end = start + newwsize;
4202     }
4203     lgl->wchs->stk.top = start + newwcount;
4204     lgl->wchs->stk.top[-1] = INT_MAX;
4205     newoffset = oldwcount - 1;
4206     LOG (5,
4207          "new watch stack of size %d at end of global watcher stack at %d",
4208          newhcount, newoffset);
4209   }
4210   assert (start == lgl->wchs->stk.start);
4211   assert (start[0]);
4212   j = newoffset;
4213   for (i = oldoffset; i < oldoffset + oldhcount; i++) {
4214     start[j++] = start[i];
4215     start[i] = 0;
4216   }
4217   while (j < newoffset + newhcount)
4218     start[j++] = 0;
4219   assert (start + j <= lgl->wchs->stk.top);
4220   hts->offset = newoffset;
4221   if (oldhcount > 0) lglfreewch (lgl, oldoffset, oldhcount);
4222   return res;
4223 }
4224
4225 static long lglpushwch (LGL * lgl, HTS * hts, int wch) {
4226   long res = 0;
4227   int * wchs = lglhts2wchs (lgl, hts);
4228   assert (sizeof (res) == sizeof (void*));
4229   assert (hts->count >= 0);
4230   if (wchs[hts->count]) {
4231     res = lglenlwchs (lgl, hts);
4232     wchs = lglhts2wchs (lgl, hts);
4233   }
4234   assert (!wchs[hts->count]);
4235   assert (wch != INT_MAX);
4236   wchs[hts->count++] = wch;
4237   lgl->stats->pshwchs++;
4238   assert (lgl->stats->pshwchs > 0);
4239   return res;
4240 }
4241
4242 static long lglwchbin (LGL * lgl, int lit, int other, int red) {
4243   HTS * hts = lglhts (lgl, lit);
4244   int cs = ((other << RMSHFT) | BINCS | red);
4245   long res;
4246   assert (red == 0 || red == REDCS);
4247   res = lglpushwch (lgl, hts, cs);
4248   LOG (3, "new %s binary watch %d blit %d", lglred2str (red), lit, other);
4249   return res;
4250 }
4251
4252 static long lglwchtrn (LGL * lgl, int a, int b, int c, int red) {
4253   HTS * hts = lglhts (lgl, a);
4254   int cs = ((b << RMSHFT) | TRNCS | red);
4255   long res;
4256   assert (red == 0 || red == REDCS);
4257   res = lglpushwch (lgl, hts, cs);
4258   res += lglpushwch (lgl, hts, c);
4259   LOG (3, "new %s ternary watch %d blits %d %d", lglred2str (red), a, b, c);
4260   return res;
4261 }
4262
4263 static long lglwchlrg (LGL * lgl, int lit, int other, int red, int lidx) {
4264   HTS * hts = lglhts (lgl, lit);
4265   int blit = ((other << RMSHFT) | LRGCS | red);
4266   long res = 0;
4267   assert (red == 0 || red == REDCS);
4268   res += lglpushwch (lgl, hts, blit);
4269   res += lglpushwch (lgl, hts, lidx);
4270 #ifndef NLGLOG
4271   {
4272     int * p = lglidx2lits (lgl, red, lidx);
4273     if (red)
4274       LOG (3,
4275            "watching %d with blit %d in red[%d][%d] %d %d %d %d%s",
4276            lit, other, (lidx & GLUEMASK), (lidx >> GLUESHFT),
4277            p[0], p[1], p[2], p[3], (p[4] ? " ..." : ""));
4278     else
4279       LOG (3,
4280        "watching %d with blit %d in irr[%d] %d %d %d %d%s",
4281        lit, other, lidx, p[0], p[1], p[2], p[3], (p[4] ? " ..." : ""));
4282   }
4283 #endif
4284   assert (sizeof (res) == sizeof (void*));
4285   return res;
4286 }
4287
4288 /*------------------------------------------------------------------------*/
4289
4290 static EVar * lglevar (LGL * lgl, int lit) {
4291   int idx = abs (lit);
4292   assert (1 <= idx && idx < lgl->nvars);
4293   return lgl->evars + idx;
4294 }
4295
4296 static int * lglepos (LGL * lgl, int lit) {
4297   EVar * ev;
4298   int * res;
4299   ev = lglevar (lgl, lit);
4300   res = &ev->pos;
4301   return res;
4302 }
4303
4304 static int lglecmp (LGL * lgl, int l, int k) {
4305   return lglevar (lgl,k)->score - lglevar (lgl,l)->score;
4306 }
4307
4308 #ifndef NDEBUG
4309 static void lglchkesched (LGL * lgl) {
4310   int * p, parent, child, ppos, cpos, size, i, tmp;
4311   Stk * s = &lgl->esched;
4312   size = lglcntstk (s);
4313   p = s->start;
4314   for (ppos = 0; ppos < size; ppos++) {
4315     parent = p[ppos];
4316     tmp = *lglepos (lgl, parent);
4317     assert (ppos == tmp);
4318     for (i = 0; i <= 1; i++) {
4319       cpos = 2*ppos + 1 + i;
4320       if (cpos >= size) continue;
4321       child = p[cpos];
4322       tmp = *lglepos (lgl, child);
4323       assert (cpos == tmp);
4324       assert (lglecmp (lgl, parent, child) >= 0);
4325     }
4326   }
4327 }
4328 #endif
4329
4330 static void lgleup (LGL * lgl, int lit) {
4331   int child = lit, parent, cpos, ppos, * p, * cposptr, * pposptr;
4332   Stk * s = &lgl->esched;
4333   p = s->start;
4334   cposptr = lglepos (lgl, child);
4335   cpos = *cposptr;
4336   assert (cpos >= 0);
4337   while (cpos > 0) {
4338     ppos = (cpos - 1)/2;
4339     parent = p[ppos];
4340     if (lglecmp (lgl, parent, lit) >= 0) break;
4341     pposptr = lglepos (lgl, parent);
4342     assert (*pposptr == ppos);
4343     p[cpos] = parent;
4344     *pposptr = cpos;
4345     LOGESCHED (5, parent, "down from %d", ppos);
4346     cpos = ppos;
4347   }
4348   if (*cposptr == cpos) return;
4349 #ifndef NLGLOG
4350   ppos = *cposptr;
4351 #endif
4352   *cposptr = cpos;
4353   p[cpos] = lit;
4354   LOGESCHED (5, lit, "up from %d", ppos);
4355 #ifndef NDEBUG
4356   if (lgl->opts->check.val >= 2) lglchkesched (lgl);
4357 #endif
4358 }
4359
4360 static void lgledown (LGL * lgl, int lit) {
4361   int parent = lit, child, right, ppos, cpos;
4362   int * p, * pposptr, * cposptr, size;
4363   Stk * s = &lgl->esched;
4364   size = lglcntstk (s);
4365   p = s->start;
4366   pposptr = lglepos (lgl, parent);
4367   ppos = *pposptr;
4368   assert (0 <= ppos);
4369   for (;;) {
4370     cpos = 2*ppos + 1;
4371     if (cpos >= size) break;
4372     child = p[cpos];
4373     if (cpos + 1 < size) {
4374       right = p[cpos + 1];
4375       if (lglecmp (lgl, child, right) < 0)
4376         cpos++, child = right;
4377     }
4378     if (lglecmp (lgl, child, lit) <= 0) break;
4379     cposptr = lglepos (lgl, child);
4380     assert (*cposptr = cpos);
4381     p[ppos] = child;
4382     *cposptr = ppos;
4383     LOGESCHED (5, child, "up from %d", cpos);
4384     ppos = cpos;
4385   }
4386   if (*pposptr == ppos) return;
4387 #ifndef NLGLOG
4388   cpos = *pposptr;
4389 #endif
4390   *pposptr = ppos;
4391   p[ppos] = lit;
4392   LOGESCHED (5, lit, "down from %d", cpos);
4393 #ifndef NDEBUG
4394   if (lgl->opts->check.val >= 2) lglchkesched (lgl);
4395 #endif
4396 }
4397
4398 static int lglifrozen (LGL * lgl, int ilit) {
4399   int elit = lglexport (lgl, ilit);
4400   Ext * ext = lglelit2ext (lgl, elit);
4401   return ext->frozen || ext->tmpfrozen;
4402 }
4403
4404 static void lglesched (LGL * lgl, int lit) {
4405   AVar * av;
4406   int * p;
4407   Stk * s;
4408   if (lgl->cceing) return;
4409   if (lgl->cgrclosing) return;
4410   if (lglifrozen (lgl, lit)) return;
4411   if (!lglisfree (lgl, lit)) return;
4412   if (lgl->donotsched) {
4413     av = lglavar (lgl, lit);
4414     if (lgl->eliminating && av->donotelm) return;
4415     if (lgl->blocking && av->donotblk) return;
4416   }
4417   p = lglepos (lgl, lit);
4418   s = &lgl->esched;
4419   if (*p >= 0) return;
4420   *p = lglcntstk (s);
4421   lglpushstk (lgl, s, lit);
4422   lgleup (lgl, lit);
4423   lgledown (lgl, lit);
4424   LOGESCHED (4, lit, "pushed");
4425 }
4426
4427 /*------------------------------------------------------------------------*/
4428
4429 static unsigned lglgcd (unsigned a, unsigned b) {
4430   unsigned tmp;
4431   assert (a), assert (b);
4432   if (a < b) SWAP (unsigned, a, b);
4433   while (b) tmp = b, b = a % b, a = tmp;
4434   return a;
4435 }
4436
4437 static uint64_t lglgcd64 (uint64_t a, uint64_t b) {
4438   uint64_t tmp;
4439   assert (a), assert (b);
4440   if (a < b) SWAP (uint64_t, a, b);
4441   while (b) tmp = b, b = a % b, a = tmp;
4442   return a;
4443 }
4444
4445 static int lglrandidxtrav (LGL * lgl, int (*fun)(LGL*,int idx)) {
4446   int idx, delta, mod, prev, first, res;
4447   first = mod = lglmax (lgl->nvars, 2);
4448   idx = lglrand (lgl) % mod;
4449   delta = lglrand (lgl) % mod;
4450   if (!delta) delta++;
4451   while (lglgcd (delta, mod) > 1)
4452     if (++delta == mod) delta = 1;
4453   res = 1;
4454   LOG (2,
4455     "random index traversal start %d delta %d mod %d",
4456      idx, delta, mod);
4457   while (res) {
4458     if (idx >= 2 && !fun (lgl, idx)) res = 0;
4459     else {
4460       prev = idx;
4461       idx += delta;
4462       if (idx >= mod) idx -= mod;
4463       if (idx == first) break;
4464       if (first == mod) first = prev;
4465     }
4466   }
4467   return res;
4468 }
4469
4470 static int lglrem (LGL * lgl) {
4471   int res = lgl->nvars;
4472   if (!res) return 0;
4473   assert (res >= 2);
4474   res -= lgl->stats->fixed.current + 2;
4475   assert (res >= 0);
4476   return res;
4477 }
4478
4479 static double lglpcnt (double n, double d) {
4480   if (d <= 0 || !n) return 0.0;
4481   return 100.0 * n / d;
4482 }
4483
4484 static int lglecalc (LGL * lgl, EVar * ev) {
4485   int oldscore = ev->score, o0 = ev->occ[0], o1 = ev->occ[1], newscore;
4486   if (lgl->eliminating) {
4487     if (lgl->opts->elmschedpure.val && (!o0 || !o1)) newscore = 0;
4488     else if (lgl->opts->elmsched2b2.val && o0 <= 2 && o1 <= 2) newscore = 1;
4489     else {
4490       newscore = 0;
4491       if (lgl->opts->elmschedsum.val) newscore += o0 + o1;
4492       if (lgl->opts->elmschedmin.val) newscore += lglmin (o0, o1);
4493       if (lgl->opts->elmschediff.val) newscore -= o0 < o1 ? o1-o0 : o0-o1;
4494       if (lgl->opts->elmschedprod.val) {
4495         int64_t tmp = newscore, prod = o0 * (int64_t) o1;
4496         tmp += prod;
4497         newscore = tmp <= INT_MAX ? tmp : INT_MAX;
4498       }
4499     }
4500   } else {
4501     assert (lgl->blocking);
4502     if (lgl->opts->blkschedpure.val && (!o0 || !o1)) newscore = 0;
4503     else if (lgl->opts->blksched2b2.val && o0 <= 2 && o1 <= 2) newscore = 1;
4504     else {
4505       newscore = 0;
4506       if (lgl->opts->blkschedsum.val) newscore += o0 + o1;
4507       if (lgl->opts->blkschedmin.val) newscore += lglmin (o0, o1);
4508       if (lgl->opts->blkschedprod.val) {
4509         int64_t tmp = newscore, prod = o0 * (int64_t) o1;
4510         tmp += prod;
4511         newscore = tmp <= INT_MAX ? tmp : INT_MAX;
4512       }
4513     }
4514   }
4515   ev->score = newscore;
4516   return newscore - oldscore;
4517 }
4518
4519 static int lglocc (LGL * lgl, int lit) {
4520   if (!lgl->occs) return lglhts (lgl, lit)->count;
4521   return lglevar (lgl, lit)->occ[lit < 0];
4522 }
4523
4524 static void lglincocc (LGL * lgl, int lit) {
4525   int idx, sign, change;
4526   EVar * ev;
4527   if (!lgl->occs) return;
4528   idx = abs (lit), sign = (lit < 0);
4529   ev = lglevar (lgl, lit);
4530   assert (lglisfree (lgl, lit));
4531   ev->occ[sign] += 1;
4532   assert (ev->occ[sign] > 0);
4533   change = lglecalc (lgl, ev);
4534   LOG (3, "inc occ of %d now occs[%d] = %d %d",
4535        lit, idx, ev->occ[0], ev->occ[1]);
4536   if (ev->pos < 0) lglesched (lgl, idx);
4537   else if (change > 0) lgledown (lgl, idx);
4538   else if (change < 0) lgleup (lgl, idx);
4539 }
4540
4541 static int lglisact (int act) { return NOTALIT <= act && act < REMOVED-1; }
4542
4543 static int lglrescoreglue (LGL * lgl, int glue) {
4544   int * c, * p, oldact, newact, count = 0;;
4545   Stk * lir = lgl->red + glue;
4546   for (c = lir->start; c < lir->top; c = p + 1) {
4547     oldact = *c;
4548     if (oldact == REMOVED) {
4549       for (p = c + 1; p < lir->top && *p == REMOVED; p++)
4550         ;
4551       assert (p >= lir->top || *p < NOTALIT || lglisact (*p));
4552       p--;
4553     } else {
4554       assert (NOTALIT <= oldact && oldact <= REMOVED - 1);
4555       newact = NOTALIT + ((oldact - NOTALIT) + 1) / 2;
4556       *c++ = newact;
4557       LOGCLS (5, c, "rescoring activity from %d to %d of clause",
4558               oldact - NOTALIT, newact - NOTALIT);
4559       for (p = c; *p; p++)
4560         ;
4561       count++;
4562     }
4563   }
4564   return count;
4565 }
4566
4567 static void lglrescoreclauses (LGL * lgl) {
4568   int glue, count = 0;;
4569   lgl->stats->rescored.clauses++;
4570   for (glue = 0; glue < MAXGLUE; glue++)
4571     count += lglrescoreglue (lgl, glue);
4572   lglprt (lgl, RVL, "[rescored-clauses-%d] rescored activity of %d clauses",
4573     lgl->stats->rescored.clauses, count);
4574 }
4575
4576 static void lglchkirrstats (LGL * lgl) {
4577 #if  0
4578   int idx, sign, lit, blit, tag, red, other, other2, clauses, lits;
4579   const int * p, * w, * eow, * c, * top;
4580   HTS * hts;
4581   clauses = lits = 0;
4582   for (idx = 2; idx < lgl->nvars; idx++)
4583     for (sign = -1; sign <= 1; sign += 2) {
4584       lit = sign * idx;
4585       hts = lglhts (lgl, lit);
4586       w = lglhts2wchs (lgl, hts);
4587       eow = w + hts->count;
4588       for (p = w; p < eow; p++) {
4589         blit = *p;
4590         tag = blit & MASKCS;
4591         if (tag == TRNCS || tag == LRGCS) p++;
4592         red = blit & REDCS;
4593         if (red) continue;
4594         if (tag == BINCS) {
4595           other = blit >> RMSHFT;
4596           if (abs (other) < idx) continue;
4597           lits += 2;
4598         } else if (tag == TRNCS) {
4599           other = blit >> RMSHFT;
4600           if (abs (other) < idx) continue;
4601           other2 = *p;
4602           if (abs (other2) < idx) continue;
4603           lits += 3;
4604         } else continue;
4605         clauses++;
4606       }
4607     }
4608   top = lgl->irr.top;
4609   for (c = lgl->irr.start; c < top; c = p + 1) {
4610     if (*(p = c) >= NOTALIT) continue;
4611     while (*++p)
4612       ;
4613     lits += p - c;
4614     clauses++;
4615   }
4616   assert (clauses == lgl->stats->irr.clauses.cur);
4617   assert (lits == lgl->stats->irr.lits.cur);
4618 #else
4619   (void) lgl;
4620 #endif
4621 }
4622
4623 static void lglincirr (LGL * lgl, int size) {
4624   if (size < 2) return;
4625   lgl->stats->irr.clauses.cur++;
4626   assert (lgl->stats->irr.clauses.cur > 0);
4627   if (lgl->stats->irr.clauses.cur > lgl->stats->irr.clauses.max)
4628     lgl->stats->irr.clauses.max = lgl->stats->irr.clauses.cur;
4629   lgl->stats->irr.lits.cur += size;
4630   assert (lgl->stats->irr.lits.cur >= size);
4631   if (lgl->stats->irr.lits.cur > lgl->stats->irr.lits.max)
4632     lgl->stats->irr.lits.max = lgl->stats->irr.lits.cur;
4633   lgl->stats->irrprgss++;
4634 }
4635
4636 static void lgldecirr (LGL * lgl, int size) {
4637   assert (size >= 2);
4638   assert (lgl->stats->irr.clauses.cur > 0);
4639   lgl->stats->irr.clauses.cur--;
4640   assert (lgl->stats->irr.lits.cur >= size);
4641   lgl->stats->irr.lits.cur -= size;
4642   assert (!lgl->stats->irr.clauses.cur == !lgl->stats->irr.lits.cur);
4643   lgl->stats->irrprgss++;
4644 }
4645
4646 static void lglbumplidx (LGL * lgl, int lidx) {
4647   int glue = (lidx & GLUEMASK), * c, *ap, act;
4648   Stk * lir = lgl->red + glue;
4649   if (glue >= MAXGLUE) return;
4650   lidx >>= GLUESHFT;
4651   c = lir->start + lidx;
4652   assert (lir->start < c && c < lir->end);
4653   ap = c - 1;
4654   act = *ap;
4655   if (act < REMOVED - 1) {
4656     LGLCHKACT (act);
4657     act += 1;
4658     LGLCHKACT (act);
4659     *ap = act;
4660   }
4661   LOGCLS (4, c, "bumped activity to %d of glue %d clause", act-NOTALIT, glue);
4662   lgl->stats->lir[glue].resolved++;
4663   assert (lgl->stats->lir[glue].resolved > 0);
4664   if (act >= REMOVED - 1) lglrescoreclauses (lgl);
4665 }
4666
4667 static void lglincjwh (LGL * lgl, int lit, Flt inc) {
4668   int ulit = lglulit (lit);
4669   Flt old = lgl->jwh[ulit];
4670   Flt new = lgladdflt (old, inc);
4671   lgl->jwh[ulit] = new;
4672 }
4673
4674 static int lglscaleglue (LGL * lgl, int origlue) {
4675   int scaledglue, redglue;
4676   assert (0 <= origlue);
4677   if (origlue <= lgl->opts->gluekeep.val) scaledglue = 0;
4678   else if (origlue >= lgl->opts->maxglue.val) scaledglue = MAXGLUE;
4679   else {
4680     redglue = origlue - lgl->opts->gluekeep.val;
4681     assert (redglue >= 1);
4682     switch (lgl->opts->gluescale.val) {
4683       case 4:
4684        scaledglue = lglceilsqrt32 (redglue);
4685        if (scaledglue > MAXGLUE/2)
4686          scaledglue = MAXGLUE/2 + 1 + lglceilld (scaledglue - MAXGLUE/2);
4687        break;
4688       case 3: scaledglue = 1 + lglceilld (redglue); break;
4689       case 2: scaledglue = lglceilsqrt32 (redglue); break;
4690       default: scaledglue = redglue; break;
4691     }
4692     assert (scaledglue > 0);
4693     if (scaledglue > MAXGLUE) scaledglue = MAXGLUE;
4694   }
4695   if (lgl->opts->keepmaxglue.val && scaledglue == MAXGLUE)
4696     scaledglue = MAXGLUE-1;
4697   assert (0 <= scaledglue && scaledglue <= MAXGLUE);
4698   return scaledglue;
4699 }
4700
4701 static void lgldrupligaddcls (LGL * lgl, int red) {
4702 #ifndef NLGLDRUPLIG
4703   if (lgldruplig (lgl)) {
4704     const int * p;
4705     int lit;
4706     for (p = lgl->clause.start; p < lgl->clause.top; p++)
4707       if ((lit = *p))
4708         druplig_add_literal (lgl->druplig, lglexport (lgl, lit));
4709     if (red) druplig_check_and_add_redundant_clause (lgl->druplig);
4710     else druplig_add_original_clause (lgl->druplig);
4711   }
4712 #else
4713   (void) lgl, (void) red;
4714 #endif
4715 }
4716
4717 static int lgladdcls (LGL * lgl, int red, int origlue, int force) {
4718   int size, lit, other, other2, * p, lidx, unit, blit;
4719   int scaledglue, prevglue;
4720   Flt inc;
4721   Val val;
4722   Stk * w;
4723   lgl->stats->prgss++;
4724   if (lgl->eliminating) {
4725     size = lglcntstk (&lgl->clause);
4726     ADDSTEPS (elm.steps, size);
4727   }
4728   if (!red) lgl->stats->irrprgss++;
4729   assert (!lglmtstk (&lgl->clause));
4730   assert (!lgl->clause.top[-1]);
4731   if (force) lglchksimpcls (lgl);
4732 #if !defined(NLGLPICOSAT) && !defined(NDEBUG)
4733   lglpicosataddcls (lgl, lgl->clause.start);
4734 #endif
4735   size = lglcntstk (&lgl->clause) - 1;
4736   if (!red) lglincirr (lgl, size);
4737   else if (size == 2) lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
4738   else if (size == 3) lgl->stats->red.trn++, assert (lgl->stats->red.trn > 0);
4739   assert (size >= 0);
4740   if (!size) {
4741     LOG (1, "found empty clause");
4742     lgl->mt = 1;
4743     return 0;
4744   }
4745   lit = lgl->clause.start[0];
4746   if (size == 1) {
4747     assert (lglval (lgl, lit) >= 0);
4748     if (!lglval (lgl, lit)) {
4749       if (red) lglunit (lgl, lit);
4750       else lglunitnocheck (lgl, lit);
4751     }
4752     return 0;
4753   }
4754   inc = lglflt (-size, 1);
4755   other = lgl->clause.start[1];
4756   if (size == 2) {
4757     lglwchbin (lgl, lit, other, red);
4758     lglwchbin (lgl, other, lit, red);
4759     if (red) {
4760       if (force && lglval (lgl, lit) < 0) lglf2rce (lgl, other, lit, REDCS);
4761       if (force && lglval (lgl, other) < 0) lglf2rce (lgl, lit, other, REDCS);
4762     } else if (lgl->dense) {
4763       assert (!red);
4764       lglincocc (lgl, lit);
4765       lglincocc (lgl, other);
4766     }
4767     if (!red) lglincjwh (lgl, lit, inc), lglincjwh (lgl, other, inc);
4768     return 0;
4769   }
4770   lglordercls (lgl);
4771   lit = lgl->clause.start[0];
4772   other = lgl->clause.start[1];
4773   if (size == 3) {
4774     other2 = lgl->clause.start[2];
4775     lglwchtrn (lgl, lit, other, other2, red);
4776     lglwchtrn (lgl, other, lit, other2, red);
4777     lglwchtrn (lgl, other2, lit, other, red);
4778     if (red) {
4779       if (force && lglval (lgl, lit) < 0 && lglval (lgl, other) < 0)
4780         lglf3rce (lgl, other2, lit, other, REDCS);
4781       if (force && lglval (lgl, lit) < 0 && lglval (lgl, other2) < 0)
4782         lglf3rce (lgl, other, lit, other2, REDCS);
4783       if (force && lglval (lgl, other) < 0 && lglval (lgl, other2) < 0)
4784         lglf3rce (lgl, lit, other, other2, REDCS);
4785     } else if (lgl->dense) {
4786       assert (!red);
4787       lglincocc (lgl, lit);
4788       lglincocc (lgl, other);
4789       lglincocc (lgl, other2);
4790     }
4791     if (!red) lglincjwh (lgl, lit, inc),
4792               lglincjwh (lgl, other, inc),
4793               lglincjwh (lgl, other2, inc);
4794     return 0;
4795   }
4796   assert (size > 3);
4797   if (red) {
4798     scaledglue = lglscaleglue (lgl, origlue);
4799     lgl->stats->clauses.scglue += scaledglue;
4800     if (scaledglue == MAXGLUE) lgl->stats->clauses.maxglue++;
4801     else lgl->stats->clauses.nonmaxglue++;
4802     w = lgl->red + scaledglue;
4803     lidx = lglcntstk (w) + 1;
4804     if (lidx > MAXREDLIDX) {
4805       prevglue = scaledglue;
4806       if (lidx > MAXREDLIDX) {
4807         scaledglue = prevglue;
4808         while (scaledglue + 1 < MAXGLUE && lidx > MAXREDLIDX) {
4809           w = lgl->red + ++scaledglue;
4810           lidx = lglcntstk (w) + 1;
4811         }
4812       }
4813       if (lidx > MAXREDLIDX) {
4814         scaledglue = prevglue;
4815         while (scaledglue > 0 && lidx > MAXREDLIDX) {
4816           w = lgl->red + --scaledglue;
4817           lidx = lglcntstk (w) + 1;
4818         }
4819       }
4820       if (lidx > MAXREDLIDX && scaledglue < MAXGLUE) {
4821         w = lgl->red + (scaledglue = MAXGLUE);
4822         lidx = lglcntstk (w) + 1;
4823       }
4824       if (lidx > MAXREDLIDX && scaledglue == MAXGLUE) {
4825         lglbacktrack (lgl, 0);
4826         lidx = lglcntstk (w);
4827         assert (!lidx);
4828       }
4829       if (lidx > MAXREDLIDX)
4830         lgldie (lgl, "number of redundant large clause literals exhausted");
4831     }
4832     lglpushstk (lgl, w, NOTALIT);
4833     assert (lidx == lglcntstk (w));
4834     lidx <<= GLUESHFT;
4835     assert (0 <= lidx);
4836     lidx |= scaledglue;
4837     lgl->stats->lir[scaledglue].clauses++;
4838     assert (lgl->stats->lir[scaledglue].clauses > 0);
4839     lgl->stats->lir[scaledglue].added++;
4840     assert (lgl->stats->lir[scaledglue].added > 0);
4841   } else {
4842     w = &lgl->irr;
4843     lidx = lglcntstk (w);
4844     scaledglue = 0;
4845     if (lidx <= 0 && !lglmtstk (w))
4846       lgldie (lgl, "number of irredundant large clause literals exhausted");
4847   }
4848   for (p = lgl->clause.start; (other2 = *p); p++)
4849     lglpushstk (lgl, w, other2), lglincjwh (lgl, other2, inc);
4850   lglpushstk (lgl, w, 0);
4851   if (red) {
4852     unit = 0;
4853     for (p = lgl->clause.start; (other2 = *p); p++) {
4854       val = lglval (lgl, other2);
4855       assert (!force || val <= 0);
4856       if (val < 0) continue;
4857       if (unit) unit = INT_MAX;
4858       else unit = other2;
4859     }
4860     if (force && unit && unit != INT_MAX) lglflrce (lgl, unit, red, lidx);
4861   }
4862   assert (red == 0 || red == REDCS);
4863   if (!red || (red && scaledglue < MAXGLUE)) {
4864     (void) lglwchlrg (lgl, lit, other, red, lidx);
4865     (void) lglwchlrg (lgl, other, lit, red, lidx);
4866   }
4867   if (red && scaledglue != MAXGLUE) {
4868     lglbumplidx (lgl, lidx);
4869     lgl->stats->red.lrg++;
4870   }
4871   if (!red && lgl->dense >= 2) {
4872     if (lidx > MAXIRRLIDX)
4873       lgldie (lgl, "number of irredundant large clause literals exhausted");
4874     blit = (lidx << RMSHFT) | OCCS;
4875     for (p = lgl->clause.start; (other2 = *p); p++) {
4876       lglincocc (lgl, other2);
4877       lglpushwch (lgl, lglhts (lgl, other2), blit);
4878     }
4879   }
4880   lglchkirrstats (lgl);
4881   return lidx;
4882 }
4883
4884 static void lgliadd (LGL * lgl, int ilit) {
4885   int size;
4886 #ifndef NLGLOG
4887   if (lglmtstk (&lgl->clause)) LOG (4, "opening irredundant clause");
4888 #endif
4889   assert (abs (ilit) < 2 || abs (ilit) < lgl->nvars);
4890   lglpushstk (lgl, &lgl->clause, ilit);
4891   if (ilit) {
4892     LOG (4, "added literal %d", ilit);
4893   } else {
4894     LOG (4, "closing irredundant clause");
4895     LOGCLS (3, lgl->clause.start, "unsimplified irredundant clause");
4896     if (!lglsimpcls (lgl)) {
4897       lgldrupligaddcls (lgl, 0);
4898       lgladdcls (lgl, 0, 0, 1);
4899       lgl->stats->irr.clauses.add++;
4900       size = lglcntstk (&lgl->clause) - 1;
4901       assert (size >= 0);
4902       lgl->stats->irr.lits.add += size;
4903     }
4904     lglclnstk (&lgl->clause);
4905   }
4906 }
4907
4908 static void lgleunassignall (LGL * lgl) {
4909   int eidx;
4910   for (eidx = 1; eidx <= lgl->maxext; eidx++)
4911     lglelit2ext (lgl, eidx)->val = 0;
4912 }
4913
4914 static void lglchkeassumeclean (LGL * lgl) {
4915   assert (lglmtstk (&lgl->eassume));
4916 #ifndef NDEBUG
4917   int eidx;
4918   for (eidx = 1; eidx <= lgl->maxext; eidx++) {
4919     Ext * ext = lglelit2ext (lgl, eidx);
4920     assert (!ext->assumed);
4921     assert (!ext->failed);
4922   }
4923 #endif
4924 }
4925
4926 static void lglchkassumeclean (LGL * lgl) {
4927   assert (!lgl->failed);
4928   assert (!lgl->assumed);
4929   assert (!lgl->cassumed);
4930   assert (!lgl->ncassumed);
4931   assert (lglmtstk (&lgl->assume));
4932 #ifndef NDEBUG
4933   if (lgl->opts->check.val >= 1) {
4934     int idx;
4935     for (idx = 2; idx < lgl->nvars; idx++) {
4936       AVar * av = lglavar (lgl, idx);
4937       assert (!av->assumed);
4938       assert (!av->failed);
4939     }
4940   }
4941 #endif
4942 }
4943
4944 static void lglreset (LGL * lgl) {
4945   int elit, ilit, erepr;
4946   Ext * ext, * rext;
4947   unsigned bit;
4948   AVar * av;
4949   if (lgl->state == RESET) return;
4950   if (lgl->state <= USED) return;
4951   assert (lgl->state & (UNKNOWN|SATISFIED|EXTENDED|UNSATISFIED|FAILED|LOOKED));
4952   if (lgl->level > 0) lglbacktrack (lgl, 0);
4953   if (!lglmtstk (&lgl->eassume)) {
4954     LOG (2, "resetting %d external assumptions", lglcntstk (&lgl->eassume));
4955     while (!lglmtstk (&lgl->eassume)) {
4956       elit = lglpopstk (&lgl->eassume);
4957       ext = lglelit2ext (lgl, elit);
4958       ext->assumed = 0;
4959       if (ext->failed) {
4960         ext->failed = 0;
4961         erepr = lglerepr (lgl, elit);
4962         if (erepr != elit) {
4963           rext = lglelit2ext (lgl, erepr);
4964           rext->failed = 0;
4965         }
4966       }
4967     }
4968   }
4969   lglchkeassumeclean (lgl);
4970   if (!lglmtstk (&lgl->assume)) {
4971     LOG (2, "resetting %d internal assumptions", lglcntstk (&lgl->assume));
4972     while (!lglmtstk (&lgl->assume)) {
4973       ilit = lglpopstk (&lgl->assume);
4974       av = lglavar (lgl, ilit);
4975       bit = (1u << (ilit < 0));
4976       assert (av->assumed & bit);
4977       av->assumed &= ~bit;
4978       av->failed &= ~bit;
4979     }
4980   }
4981   if (!lglmtstk (&lgl->cassume)) {
4982     assert (lgl->ncassumed);
4983     LOG (2, "resetting assumed clause of size %d", lglcntstk (&lgl->cassume));
4984     lglclnstk (&lgl->cassume);
4985     lgl->cassumed = lgl->ncassumed = 0;
4986   } else assert (!lgl->ncassumed), assert (!lgl->cassumed);
4987   if (lgl->failed) {
4988     LOG (2, "resetting internal failed assumption %d", lgl->failed);
4989     lgl->failed = 0;
4990   }
4991   if (lgl->assumed) {
4992     LOG (2, "resetting assumption queue level to 0 from %d", lgl->assumed);
4993     lgl->assumed = 0;
4994   }
4995   lglchkassumeclean (lgl);
4996 #if !defined(NDEBUG) && !defined (NLGLPICOSAT)
4997   if (lgl->picosat.res) {
4998     LOG (2, "resetting earlier PicoSAT result %d", lgl->picosat.res);
4999     lgl->picosat.res = 0;
5000   }
5001 #endif
5002   lgleunassignall (lgl);
5003   if (lgl->cbs && lgl->cbs->term.done) {
5004     LOG (2, "resetting forced termination done flag");
5005     lgl->cbs->term.done = 0;
5006   }
5007   TRANS (RESET);
5008 }
5009
5010 static void lgluse (LGL * lgl) {
5011   if (lgl->state >= USED) return;
5012   assert (lgl->state == UNUSED || lgl->state == OPTSET);
5013   TRANS (USED);
5014 }
5015
5016 static void lgleadd (LGL * lgl, int elit) {
5017   int ilit;
5018   lglreset (lgl);
5019   if (elit) {
5020     ilit = lglimport (lgl, elit);
5021     LOG (4, "adding external literal %d as %d", elit, ilit);
5022   } else {
5023     ilit = 0;
5024     LOG (4, "closing external clause");
5025   }
5026   lgliadd (lgl, ilit);
5027 #ifndef NCHKSOL
5028   lglpushstk (lgl, &lgl->orig, elit);
5029 #endif
5030 }
5031
5032 void lgladd (LGL * lgl, int elit) {
5033   int eidx = abs (elit);
5034   Ext * ext;
5035   REQINITNOTFORKED ();
5036   TRAPI ("add %d", elit);
5037   if (0 < eidx && eidx <= lgl->maxext) {
5038     ext = lglelit2ext (lgl, elit);
5039     ABORTIF (ext->melted, "adding melted literal %d", elit);
5040   }
5041   lgl->stats->calls.add++;
5042   lgleadd (lgl, elit);
5043   lgluse (lgl);
5044   if (lgl->clone) lgladd (lgl->clone, elit);
5045 }
5046
5047 static void lglisetphase (LGL * lgl, int lit, int phase) {
5048   AVar * av;
5049   if (lit < 0) lit = -lit, phase = -phase;
5050   av = lglavar (lgl, lit);
5051   av->fase = phase;
5052   LOG (2, "setting phase of internal literal %d to %d", lit, phase);
5053 }
5054
5055 static void lglesetphase (LGL * lgl, int elit, int phase) {
5056   int ilit = lglimport (lgl, elit);
5057   if (abs (ilit) >= 2) {
5058     LOG (2, "setting phase of external literal %d to %d", elit, phase);
5059     lglisetphase (lgl, ilit, phase);
5060   } else LOG (2, "setting phase of external literal %d skipped", elit);
5061 }
5062
5063 void lglsetphase (LGL * lgl, int elit) {
5064   REQINITNOTFORKED ();
5065   TRAPI ("setphase %d", elit);
5066   ABORTIF (!elit, "invalid literal argument");
5067   if (elit < 0) lglesetphase (lgl, -elit, -1);
5068   else lglesetphase (lgl, elit, 1);
5069   if (lgl->clone) lglsetphase (lgl->clone, elit);
5070 }
5071
5072 void lglresetphase (LGL * lgl, int elit) {
5073   REQINITNOTFORKED ();
5074   TRAPI ("resetphase %d", elit);
5075   ABORTIF (!elit, "invalid literal argument");
5076   lglesetphase (lgl, elit, 0);
5077   if (lgl->clone) lglresetphase (lgl->clone, elit);
5078 }
5079
5080 static void lgleassume (LGL * lgl, int elit) {
5081   int ilit, val;
5082   unsigned bit;
5083   AVar * av;
5084   Ext * ext;
5085   lglreset (lgl);
5086   ilit = lglimport (lgl, elit);
5087   LOG (2, "assuming external literal %d", elit);
5088   bit = 1u << (elit < 0);
5089   ext = lglelit2ext (lgl, elit);
5090   if (!(ext->assumed & bit)) {
5091     ext->assumed |= bit;
5092     lglpushstk (lgl, &lgl->eassume, elit);
5093   }
5094   assert (!lgl->level);
5095   if (!(val = lglcval (lgl, ilit))) {
5096     av = lglavar (lgl, ilit);
5097     bit = (1u << (ilit < 0));
5098     if (av->assumed & bit) {
5099       LOG (2, "internal literal %d already assumed", ilit);
5100     } else {
5101       av->assumed |= bit;
5102       if (av->assumed & (bit^3))
5103         LOG (2, "negation %d was also already assumed", -ilit);
5104       lglpushstk (lgl, &lgl->assume, ilit);
5105     }
5106   } else if (val > 0) {
5107     LOG (2, "externally assumed literal %d already fixed to true", elit);
5108   } else {
5109     assert (val < 0);
5110     LOG (2, "externally assumed literal %d already fixed to false", elit);
5111     if (ilit != -1) {
5112       av = lglavar (lgl, ilit);
5113       bit = (1u << (ilit < 0));
5114       if (!(av->assumed & bit)) {
5115         av->assumed |= bit;
5116         lglpushstk (lgl, &lgl->assume, ilit);
5117       }
5118     }
5119     if (!lgl->failed) lgl->failed = ilit;
5120   }
5121 }
5122
5123 static void lglecassume (LGL * lgl, int elit) {
5124   LOG (2, "adding external literal %d to assumed clause", elit);
5125 }
5126
5127 void lglassume (LGL * lgl, int elit) {
5128   int eidx = abs (elit);
5129   Ext * ext;
5130   REQINITNOTFORKED ();
5131   TRAPI ("assume %d", elit);
5132   lgl->stats->calls.assume++;
5133   ABORTIF (!elit, "can not assume invalid literal 0");
5134   if (0 < eidx && eidx <= lgl->maxext) {
5135     ext = lglelit2ext (lgl, elit);
5136     ABORTIF (ext->melted, "assuming melted literal %d", elit);
5137   }
5138   lgleassume (lgl, elit);
5139   lgluse (lgl);
5140   lglmelter (lgl);
5141   if (lgl->clone) lglassume (lgl->clone, elit);
5142 }
5143
5144 void lglcassume (LGL * lgl, int elit) {
5145   int eidx = abs (elit);
5146   Ext * ext;
5147   REQINITNOTFORKED ();
5148   TRAPI ("cassume %d", elit);
5149   lgl->stats->calls.cassume++;
5150   if (0 < eidx && eidx <= lgl->maxext) {
5151     ext = lglelit2ext (lgl, elit);
5152     ABORTIF (ext->melted, "assuming melted literal %d", elit);
5153   }
5154   lglecassume (lgl, elit);
5155   lgluse (lgl);
5156   if (lgl->clone) lglcassume (lgl->clone, elit);
5157 }
5158
5159 void lglfixate (LGL * lgl) {
5160   const int  * p;
5161   Stk eassume;
5162   REQINITNOTFORKED ();
5163   TRAPI ("fixate");
5164   if (lgl->mt) return;
5165   CLR (eassume);
5166   for (p = lgl->eassume.start; p < lgl->eassume.top; p++)
5167     lglpushstk (lgl, &eassume, *p);
5168   for (p = eassume.start; p < eassume.top; p++)
5169     lgleadd (lgl, *p), lgleadd (lgl, 0);
5170   lglrelstk (lgl, &eassume);
5171   lgluse (lgl);
5172   if (lgl->clone) lglfixate (lgl->clone);
5173 }
5174
5175 static void lglbonflict (LGL * lgl, int lit, int blit) {
5176   assert (lglevel (lgl, lit) >= lglevel (lgl, blit >> RMSHFT));
5177   assert (!lgliselim (lgl, blit >> RMSHFT));
5178   assert (!lgliselim (lgl, lit));
5179   lgl->conf.lit = lit;
5180   lgl->conf.rsn[0] = blit;
5181   LOG (2, "inconsistent %s binary clause %d %d",
5182        lglred2str (blit & REDCS), lit, (blit >> RMSHFT));
5183 }
5184
5185 static void lgltonflict (LGL * lgl, int lit, int blit, int other2) {
5186   assert ((blit & MASKCS) == TRNCS);
5187   assert (lglevel (lgl, lit) >= lglevel (lgl, blit >> RMSHFT));
5188   assert (lglevel (lgl, lit) >= lglevel (lgl, other2));
5189   assert (!lgliselim (lgl, blit >> RMSHFT));
5190   assert (!lgliselim (lgl, other2));
5191   assert (!lgliselim (lgl, lit));
5192   lgl->conf.lit = lit;
5193   lgl->conf.rsn[0] = blit;
5194   lgl->conf.rsn[1] = other2;
5195   LOG (2, "inconsistent %s ternary clause %d %d %d",
5196        lglred2str (blit & REDCS), lit, (blit>>RMSHFT), other2);
5197 }
5198
5199 static void lglonflict (LGL * lgl, int check, int lit, int red, int lidx) {
5200   int glue;
5201 #if !defined (NLGLOG) || !defined (NDEBUG)
5202   int * p, * c = lglidx2lits (lgl, red, lidx);
5203 #endif
5204   assert (red == REDCS || !red);
5205 #ifndef NDEBUG
5206   {
5207     int found = 0;
5208     for (p = c; *p; p++) {
5209       if(*p == lit) found++;
5210       assert (lglval (lgl, *p) <= -check);
5211       assert (lglevel (lgl, lit) >= lglevel (lgl, *p));
5212       assert (!lgliselim (lgl, lit));
5213     }
5214     assert (found == 1);
5215   }
5216 #endif
5217   lgl->conf.lit = lit;
5218   lgl->conf.rsn[0] = red | LRGCS;
5219   lgl->conf.rsn[1] = lidx;
5220 #ifndef NLGLOG
5221   if (lgl->opts->log.val >= 2) {
5222     lglogstart (lgl, 2, "inconsistent %s large clause", lglred2str (red));
5223     for (p = c ; *p; p++)
5224       fprintf (lgl->out, " %d", *p);
5225     lglogend (lgl);
5226   }
5227 #endif
5228   if (red) {
5229     glue = lidx & GLUEMASK;
5230     lgl->stats->lir[glue].conflicts++;
5231     assert (lgl->stats->lir[glue].conflicts > 0);
5232   }
5233 }
5234
5235 static void lgldeclscnt (LGL * lgl, int size, int red, int glue) {
5236   assert (!red || red == REDCS);
5237   if (!red) lgldecirr (lgl, size);
5238   else if (size == 2) assert (lgl->stats->red.bin), lgl->stats->red.bin--;
5239   else if (size == 3) assert (lgl->stats->red.trn), lgl->stats->red.trn--;
5240   else {
5241     assert (lgl->stats->red.lrg > 0);
5242     lgl->stats->red.lrg--;
5243     assert (lgl->stats->lir[glue].clauses > 0);
5244     lgl->stats->lir[glue].clauses--;
5245   }
5246 }
5247
5248 static void lglrminc (LGL * lgl, const int * w, const int * eow) {
5249   int inc;
5250   assert (w <= eow);
5251   assert (sizeof w < 8 || eow <= w + INT_MAX);
5252   inc = eow - w;
5253   assert (inc >= 0);
5254   inc >>= lgl->opts->rmincpen.val;
5255   inc++;
5256   assert (lgl->blocking + lgl->eliminating + lgl->simpleprobing <= 1);
5257   if (lgl->blocking) ADDSTEPS (blk.steps, inc);
5258   else if (lgl->eliminating) ADDSTEPS (elm.steps, inc);
5259   else if (lgl->simpleprobing) ADDSTEPS (prb.simple.steps, inc);
5260 }
5261
5262 static void lglrmtwch (LGL * lgl, int lit, int other1, int other2, int red) {
5263   int * p, blit, other, blit1, blit2, * w, * eow, tag;
5264   HTS * hts;
5265   assert (!red || red == REDCS);
5266   LOG (3, "removing %s ternary watch %d blits %d %d",
5267        lglred2str (red), lit, other1, other2);
5268   hts = lglhts (lgl, lit);
5269   assert (hts->count >= 2);
5270   p = w = lglhts2wchs (lgl, hts);
5271   eow = w + hts->count;
5272   lglrminc (lgl, w, eow);
5273   blit1 = (other1 << RMSHFT) | red | TRNCS;
5274   blit2 = (other2 << RMSHFT) | red | TRNCS;
5275   for (;;) {
5276     assert (p < eow);
5277     blit = *p++;
5278     tag = blit & MASKCS;
5279     if (tag == BINCS || tag == OCCS) continue;
5280     other = *p++;
5281     if (tag == LRGCS) continue;
5282     assert (tag == TRNCS);
5283     if (blit == blit1 && other == other2) break;
5284     if (blit == blit2 && other == other1) break;
5285   }
5286   while (p < eow) p[-2] = p[0], p++;
5287   lglshrinkhts (lgl, hts, p - w - 2);
5288 }
5289
5290 static void lglpopnunmarkstk (LGL * lgl, Stk * stk) {
5291   while (!lglmtstk (stk))
5292     lglavar (lgl, lglpopstk (stk))->mark = 0;
5293 }
5294
5295 static void lglpopnunlcamarkstk (LGL * lgl, Stk * stk) {
5296   while (!lglmtstk (stk))
5297     lglavar (lgl, lglpopstk (stk))->lcamark = 0;
5298 }
5299
5300 static int lglcamarked (LGL * lgl, int lit) {
5301   switch (lglavar (lgl, lit)->lcamark) {
5302     case 1: return (lit < 0) ? -1 : 1;
5303     case 2: return (lit < 0) ? -2 : 2;
5304     case 4: return (lit < 0) ? 1 : -1;
5305     case 8: return (lit < 0) ? 2 : -2;
5306     default: assert (!lglavar (lgl, lit)->lcamark); return 0;
5307   }
5308 }
5309
5310 static void lglcamark (LGL * lgl, int lit, int mark) {
5311   int newmark;
5312   AVar * av;
5313   assert (mark == 1 || mark == 2);
5314   av = lglavar (lgl, lit);
5315   assert (!av->lcamark);
5316   newmark = mark;
5317   if (lit < 0) newmark <<= 2;
5318   av->lcamark = newmark;
5319   lglpushstk (lgl, &lgl->lcaseen, lit);
5320   assert (lglcamarked (lgl, lit) == mark);
5321   assert (lglcamarked (lgl, -lit) == -mark);
5322 }
5323
5324 static int lglca (LGL * lgl, int a, int b) {
5325   int blit, tag, mark, negmark, prevmark, c, res, prev, next, al, bl;
5326   const int * p, * w, * eow;
5327   HTS * hts;
5328   if (!a) return b;
5329   if (!b) return a;
5330   if (a == b) return a;
5331   if (a == -b) return 0;
5332   al = lglevel (lgl, a);
5333   bl = lglevel (lgl, b);
5334   if (!al) return b;
5335   if (!bl) return a;
5336   assert (lglval (lgl, a) > 0);
5337   assert (lglval (lgl, b) > 0);
5338   assert (lglmtstk (&lgl->lcaseen));
5339   lglcamark (lgl, a, 1);
5340   lglcamark (lgl, b, 2);
5341   res = next = 0;
5342   while (next < lglcntstk (&lgl->lcaseen)) {
5343     c = lglpeek (&lgl->lcaseen, next++);
5344     assert (lglval (lgl, c) > 0);
5345     assert (lglevel (lgl, c) > 0);
5346     mark = lglcamarked (lgl, c);
5347     assert (mark == 1 || mark == 2);
5348     negmark = mark ^ 3;
5349     hts = lglhts (lgl, c);
5350     if (!hts->count) continue;
5351     w = lglhts2wchs (lgl, hts);
5352     eow = w + hts->count;
5353     for (p = w; p < eow; p++) {
5354       blit = *p;
5355       tag = blit & MASKCS;
5356       if (tag == TRNCS || tag == LRGCS) p++;
5357       if (tag != BINCS) continue;
5358       prev = -(blit >> RMSHFT);
5359       if (!lglevel (lgl, prev)) continue;
5360       if (lglval (lgl, prev) <= 0) continue;
5361       if ((prevmark = lglcamarked (lgl, prev)) < 0) continue;
5362       if (mark == prevmark) continue;
5363       if (prevmark == negmark) { res = prev; goto DONE; }
5364       lglcamark (lgl, prev, mark);
5365     }
5366   }
5367 DONE:
5368   lglpopnunlcamarkstk (lgl, &lgl->lcaseen);
5369   LOG (3, "least common ancestor of %d and %d is %d", a, b, res);
5370   return res;
5371 }
5372
5373 static void lglrmlwch (LGL * lgl, int lit, int red, int lidx) {
5374   int blit, tag, * p, * q, * w, * eow, ored, olidx;
5375   HTS * hts;
5376 #ifndef NLGLOG
5377   p = lglidx2lits (lgl, red, lidx);
5378   if (red)
5379     LOG (3, "removing watch %d in red[%d][%d] %d %d %d %d%s",
5380          lit, (lidx & GLUEMASK), (lidx >> GLUESHFT), p[0], p[1], p[2], p[3],
5381          (p[4] ? " ..." : ""));
5382   else
5383     LOG (3, "removing watch %d in irr[%d] %d %d %d %d%s",
5384          lit, lidx, p[0], p[1], p[2], p[3], (p[4] ? " ..." : ""));
5385 #endif
5386   hts = lglhts (lgl, lit);
5387   assert (hts->count >= 2);
5388   p = w = lglhts2wchs (lgl, hts);
5389   eow = w + hts->count;
5390   lglrminc (lgl, w, eow);
5391   for (;;) {
5392     assert (p < eow);
5393     blit = *p++;
5394     tag = blit & MASKCS;
5395     if (tag == BINCS) continue;
5396     if (tag == OCCS) { assert (lgl->dense); continue; }
5397     olidx = *p++;
5398     if (tag == TRNCS) continue;
5399     assert (tag == LRGCS);
5400     ored = blit & REDCS;
5401     if (ored != red) continue;
5402     if (olidx == lidx) break;
5403   }
5404   assert ((p[-2] & REDCS) == red);
5405   assert (p[-1] == lidx);
5406   for (q = p; q < eow; q++)
5407     q[-2] = q[0];
5408   lglshrinkhts (lgl, hts, q - w - 2);
5409 }
5410
5411 static void lglpropsearch (LGL * lgl, int lit) {
5412   int * q, * eos, blit, other, other2, other3, red, prev;
5413   int tag, val, val2, lidx, * c, * l;
5414   int64_t travs;
5415   const int * p;
5416   int visits;
5417   long delta;
5418   HTS * hts;
5419
5420   LOG (3, "propagating %d in search", lit);
5421
5422   assert (!lgl->simp);
5423   assert (!lgl->lkhd);
5424   assert (!lgl->probing);
5425   assert (!lgl->lifting);
5426   assert (!lgl->cliffing);
5427   assert (!lgl->dense);
5428   assert (!lgliselim (lgl, lit));
5429   assert (lglval (lgl, lit) == 1);
5430
5431   hts = lglhts (lgl, -lit);
5432   if (!hts->offset) return;
5433   q = lglhts2wchs (lgl, hts);
5434   assert (hts->count >= 0);
5435   eos = q + hts->count;
5436   visits = 0;
5437   travs = 0;
5438   for (p = q; p < eos; p++) {
5439     visits++;
5440     *q++ = blit = *p;
5441     tag = blit & MASKCS;
5442     if (tag != BINCS) {
5443       assert (tag == TRNCS || tag == LRGCS);
5444       *q++ = *++p;
5445     }
5446     other = (blit >> RMSHFT);
5447     travs++;
5448     val = lglval (lgl, other);
5449     if (val > 0) continue;
5450     red = blit & REDCS;
5451     if (tag == BINCS) {
5452       if (val < 0) { lglbonflict (lgl, -lit, blit); p++; break; }
5453       lglf2rce (lgl, other, -lit, red);
5454     } else if (tag == TRNCS) {
5455       other2 = *p;
5456       travs++;
5457       val2 = lglval (lgl, other2);
5458       if (val2 > 0) continue;
5459       if (!val && !val2) continue;
5460       if (val < 0 && val2 < 0) {
5461         lgltonflict (lgl, -lit, blit, other2);
5462         p++;
5463         break;
5464       }
5465       if (!val) SWAP (int, other, other2);
5466       else assert (val < 0);
5467       lglf3rce (lgl, other2, -lit, other, red);
5468     } else {
5469       assert (tag == LRGCS);
5470       assert (val <= 0);
5471       lidx = *p;
5472       travs++;
5473       c = lglidx2lits (lgl, red, lidx);
5474       other2 = c[0];
5475       if (other2 == -lit) other2 = c[0] = c[1], c[1] = -lit;
5476       else assert (c[1] == -lit);
5477       if (other2 != other) {
5478         other = other2;
5479         travs++;
5480         val = lglval (lgl, other);
5481         if (val > 0) {
5482           q[-2] = LRGCS | (other2 << RMSHFT) | red;
5483           continue;
5484         }
5485       }
5486       assert (!red || !lgliselim (lgl, other));
5487       val2 = INT_MAX;
5488       prev = -lit;
5489       for (l = c + 2; (other2 = *l); l++) {
5490         *l = prev;
5491         travs++;
5492         val2 = lglval (lgl, other2);
5493         if (val2 >= 0) break;
5494         assert (!red || !lgliselim (lgl, other));
5495         prev = other2;
5496       }
5497       assert (val2 != INT_MAX);
5498       if (other2 && val2 >= 0) {
5499         c[1] = other2;
5500         assert (other == c[0]);
5501         delta = lglwchlrg (lgl, other2, other, red, lidx);
5502         if (delta) p += delta, q += delta, eos += delta;
5503         q -= 2;
5504         continue;
5505       }
5506       while (l > c + 2) {
5507         other3 = *--l;
5508         *l = prev;
5509         prev = other3;
5510       }
5511       assert (!other2 || val2 >= 0);
5512       if (val < 0) {
5513         lglonflict (lgl, 1, -lit, red, lidx);
5514         p++;
5515         break;
5516       }
5517       assert (!val);
5518       lglflrce (lgl, other, red, lidx);
5519     }
5520   }
5521   while (p < eos) *q++ = *p++;
5522   lglshrinkhts (lgl, hts, hts->count - (p - q));
5523   assert (!lgl->simp);
5524
5525   lgl->stats->visits.search += visits;
5526   lgl->stats->travs.search += travs;
5527 }
5528
5529 static int lglhbred (LGL * lgl, int subsumed, int red) {
5530   int res = subsumed ? red : REDCS;
5531   LOG (3, "hyber binary learned clause becomes %s", lglred2str (res));
5532   return res;
5533 }
5534
5535 static void lgldecocc (LGL *, int);     //TODO move scheduling ...
5536
5537 static void lglrmlocc (LGL * lgl, int lit, int red, int lidx) {
5538   int search, blit, tag, * p, * q, * w, * eow;
5539   HTS * hts;
5540   if (lgl->dense < 2) return;
5541 #ifndef NLGLOG
5542   if (red) LOG (3, "removing occurrence %d in red[0][%d]", lit, lidx);
5543   else LOG (3, "removing occurrence %d in irr[%d]", lit, lidx);
5544 #endif
5545   assert (!red || red == REDCS);
5546   hts = lglhts (lgl, lit);
5547   assert (hts->count >= 1);
5548   assert (lidx <= MAXIRRLIDX);
5549   search = (lidx << RMSHFT) | OCCS | red;
5550   assert (search >= 0);
5551   p = w = lglhts2wchs (lgl, hts);
5552   eow = w + hts->count;
5553   lglrminc (lgl, w, eow);
5554   do {
5555     assert (p < eow);
5556     blit = *p++;
5557     tag = blit & MASKCS;
5558     if (tag == TRNCS || tag == LRGCS) p++;
5559   } while (blit != search);
5560   assert (p[-1] == search);
5561   for (q = p ; q < eow; q++)
5562     q[-1] = q[0];
5563   lglshrinkhts (lgl, hts, q - w - 1);
5564 }
5565
5566 static void lglflushremovedoccs (LGL * lgl, int lit) {
5567   HTS * hts = lglhts (lgl, lit);
5568   int * w = lglhts2wchs (lgl, hts);
5569   int * eow = w + hts->count;
5570   int blit, tag, red, lidx;
5571   int * p, * q, * c;
5572   lglrminc (lgl, w, eow);
5573   for (p = q = w; p < eow; p++) {
5574     blit = *p;
5575     tag = blit & MASKCS;
5576     red = blit & REDCS;
5577     if (tag == TRNCS || tag == LRGCS) p++;
5578     if (tag == BINCS) *q++ = blit;
5579     else if (tag == TRNCS) *q++ = blit, *q++ = *p;
5580     else {
5581       assert (tag == LRGCS || tag == OCCS);
5582       if (!red) {
5583         lidx = (tag == LRGCS) ? *p : (blit >> RMSHFT);
5584         c = lglidx2lits (lgl, red, lidx);
5585         if (c[0] == REMOVED) continue;
5586       }
5587       *q++ = blit;
5588       if (tag == LRGCS) *q++ = *p;
5589     }
5590   }
5591   lglshrinkhts (lgl, hts, q - w);
5592 }
5593
5594 static void lglpropupdvisits (LGL * lgl, int visits, int64_t travs) {
5595   if (lgl->lkhd) lgl->stats->visits.lkhd += visits;
5596   else if (lgl->simp) lgl->stats->visits.simp += visits;
5597   else lgl->stats->visits.search += visits;
5598
5599   if (lgl->lkhd) lgl->stats->travs.lkhd += travs;
5600   else if (lgl->simp) lgl->stats->travs.simp += travs;
5601   else lgl->stats->travs.search += travs;
5602
5603   if (lgl->basicprobing) ADDSTEPS (prb.basic.steps, visits);
5604   if (lgl->simpleprobing) ADDSTEPS (prb.simple.steps, visits);
5605   if (lgl->treelooking) ADDSTEPS (prb.treelook.steps, visits);
5606   if (lgl->cceing) ADDSTEPS (cce.steps, visits);
5607   if (lgl->cliffing) ADDSTEPS (cliff.steps, visits);
5608 }
5609
5610 static void lglprop (LGL * lgl, int lit) {
5611   int * p, * q, * eos, blit, other, other2, other3, red, prev;
5612   int tag, val, val2, lidx, * c, * l, dom, hbred, subsumed;
5613   int glue, flushoccs, visits;
5614   int64_t travs;
5615   long delta;
5616   HTS * hts;
5617   LOG (3, "propagating %d over ternary and large clauses", lit);
5618   assert (!lgliselim (lgl, lit));
5619   assert (lglval (lgl, lit) == 1);
5620   hts = lglhts (lgl, -lit);
5621   if (!hts->offset) return;
5622   flushoccs = 0;
5623   q = lglhts2wchs (lgl, hts);
5624   assert (hts->count >= 0);
5625   eos = q + hts->count;
5626   visits = 0;
5627   travs = 0;
5628   for (p = q; p < eos; p++) {
5629     blit = *p;
5630     tag = blit & MASKCS;
5631     red = blit & REDCS;
5632     if (tag == OCCS) {
5633       assert (lgl->dense);
5634       assert (!red);
5635       *q++ = blit;
5636       continue;
5637     }
5638     visits++;
5639     other = (blit >> RMSHFT);
5640     travs++;
5641     val = lglval (lgl, other);
5642     if (tag == BINCS) {
5643       *q++ = blit;
5644       if (val > 0) continue;
5645       if (red && lgliselim (lgl, other)) continue;
5646       if (val < 0) {
5647         lglbonflict (lgl, -lit, blit);
5648         p++;
5649         break;
5650       }
5651       assert (!val);
5652       lglf2rce (lgl, other, -lit, red);
5653     } else if (tag == TRNCS) {
5654       *q++ = blit;
5655       other2 = *++p;
5656       *q++ = other2;
5657       if (val > 0) continue;
5658       travs++;
5659       if (red && lgliselim (lgl, other)) continue;
5660       val2 = lglval (lgl, other2);
5661       if (val2 > 0) continue;
5662       if (!val && !val2) continue;
5663       if (red && lgliselim (lgl, other2)) continue;
5664       if (val < 0 && val2 < 0) {
5665         lgltonflict (lgl, -lit, blit, other2);
5666         p++;
5667         break;
5668       }
5669       if (!val) SWAP (int, other, other2); else assert (val < 0);
5670       if (lgl->level &&
5671           lgl->simp &&
5672           lgl->opts->lhbr.val &&
5673           !lgl->cgrclosing) {
5674         assert (lgl->simp);
5675         dom = lglgetdom (lgl, lit);
5676         if (lglgetdom (lgl, -other) != dom) goto NO_HBR_JUST_F3RCE;
5677         dom = lglca (lgl, lit, -other);
5678         if (!dom) goto NO_HBR_JUST_F3RCE;
5679         subsumed = (dom == lit || dom == -other);
5680         hbred = lglhbred (lgl, subsumed, red);
5681         LOG (2, "hyper binary resolved %s clause %d %d",
5682              lglred2str (hbred), -dom, other2);
5683         if (lgl->opts->drup.val) lgldrupclsarg (lgl, -dom, other2, 0);
5684 #ifndef NLGLPICOSAT
5685         lglpicosatchkclsarg (lgl, -dom, other2, 0);
5686 #endif
5687         if (subsumed) {
5688           LOG (2, "subsumes %s ternary clause %d %d %d",
5689                lglred2str (red), -lit, other, other2);
5690           lglrmtwch (lgl, other2, other, -lit, red);
5691           lglrmtwch (lgl, other, other2, -lit, red);
5692           lgl->stats->hbr.sub++;
5693           if (red) assert (lgl->stats->red.trn), lgl->stats->red.trn--;
5694           else {
5695             lgldecirr (lgl, 3);
5696             if (lgl->dense) {
5697               if (-dom == -lit) lgldecocc (lgl, other);
5698               else { assert (-dom == other); lgldecocc (lgl, -lit); }
5699             }
5700           }
5701         }
5702         delta = 0;
5703         if (dom == lit) {
5704           LOG (3,
5705     "replacing %s ternary watch %d blits %d %d with binary %d blit %d",
5706           lglred2str (red), -lit, other, other2, -dom, other2);
5707           assert (subsumed);
5708           blit = (other2 << RMSHFT) | BINCS | hbred;
5709           q[-2] = blit;
5710           q--;
5711         } else {
5712           if (dom == -other) {
5713             LOG (3, "removing %s ternary watch %d blits %d %d",
5714                  lglred2str (red), -lit, other, other2);
5715             assert (subsumed);
5716             q -= 2;
5717           } else {
5718             LOG (2, "replaces %s ternary clause %d %d %d as reason for %d",
5719                  lglred2str (red), -lit, other, other2, other2);
5720             assert (!subsumed);
5721             assert (abs (dom) != abs (lit));
5722             assert (abs (other2) != abs (lit));
5723           }
5724           delta += lglwchbin (lgl, -dom, other2, hbred);
5725         }
5726         delta += lglwchbin (lgl, other2, -dom, hbred);
5727         if (delta) p += delta, q += delta, eos += delta;
5728         if (hbred) lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
5729         else lglincirr (lgl, 2);
5730         lglf2rce (lgl, other2, -dom, hbred);
5731         lgl->stats->hbr.trn++;
5732         lgl->stats->hbr.cnt++;
5733         lgl->stats->prgss++;
5734       } else {
5735 NO_HBR_JUST_F3RCE:
5736        lglf3rce (lgl, other2, -lit, other, red);
5737       }
5738     } else {
5739       assert (tag == LRGCS);
5740       if (val > 0) goto COPYL;
5741       lidx = p[1];
5742       c = lglidx2lits (lgl, red, lidx);
5743       other2 = c[0];
5744       if (other2 >= NOTALIT) {
5745         p++;
5746         continue;
5747       }
5748       if (other2 == -lit) other2 = c[0] = c[1], c[1] = -lit;
5749       if (other2 != other) {
5750         other = other2;
5751         travs++;
5752         val = lglval (lgl, other);
5753         blit = red;
5754         blit |= LRGCS;
5755         blit |= other2 << RMSHFT;
5756         if (val > 0) goto COPYL;
5757       }
5758       if (red && lgliselim (lgl, other)) goto COPYL;
5759       val2 = INT_MAX;
5760       prev = -lit;
5761       for (l = c + 2; (other2 = *l); l++) {
5762         *l = prev;
5763         travs++;
5764         val2 = lglval (lgl, other2);
5765         if (val2 >= 0) break;
5766         if (red && lgliselim (lgl, other2)) break;
5767         prev = other2;
5768       }
5769       assert (val2 != INT_MAX);
5770       if (other2 && val2 >= 0) {
5771         c[1] = other2;
5772         assert (other == c[0]);
5773         delta = lglwchlrg (lgl, other2, other, red, lidx);
5774         if (delta) p += delta, q += delta, eos += delta;
5775         p++;
5776         continue;
5777       }
5778
5779       while (l > c + 2) {
5780         other3 = *--l;
5781         *l = prev;
5782         prev = other3;
5783       }
5784
5785       if (other2 && val2 < 0) goto COPYL;
5786
5787       if (val < 0) {
5788         lglonflict (lgl, 1, -lit, red, lidx);
5789         break;
5790       }
5791
5792       assert (!val);
5793       if (lgl->level &&
5794           lgl->simp &&
5795           lgl->opts->lhbr.val &&
5796           !lgl->cgrclosing) {
5797         assert (lgl->simp);
5798         dom = 0;
5799         for (l = c; (other2 = *l); l++) {
5800           if (other2 == other) continue;
5801           travs++;
5802           if (!lglevel (lgl, other2)) continue;
5803           assert (lglval (lgl, other2) < 0);
5804           if (!dom) dom = lglgetdom (lgl, -other);
5805           if (dom != lglgetdom (lgl, -other2)) goto NO_HBR_JUST_FLRCE;
5806         }
5807         LOGCLS (2, c, "dominator %d for %s clause", dom, lglred2str (red));
5808         dom = 0;
5809         for (l = c; (other2 = *l); l++) {
5810           if (other2 == other) continue;
5811           if (!lglevel (lgl, other2)) continue;
5812           dom = lglca (lgl, dom, -other2);
5813         }
5814         if (!dom) goto NO_HBR_JUST_FLRCE;
5815         LOGCLS (2, c, "closest dominator %d", dom);
5816         subsumed = 0;
5817         for (l = c; !subsumed && (other2 = *l); l++)
5818           subsumed = (dom == -other2);
5819         assert (lit != dom || subsumed);
5820         hbred = lglhbred (lgl, subsumed, red);
5821         LOG (2, "hyper binary resolved %s clause %d %d",
5822              lglred2str (hbred), -dom, other);
5823         if (lgl->opts->drup.val) lgldrupclsarg (lgl, -dom, other, 0);
5824 #ifndef NLGLPICOSAT
5825         lglpicosatchkclsarg (lgl, -dom, other, 0);
5826 #endif
5827         if (subsumed) {
5828           LOGCLS (2, c, "subsumes %s large clause", lglred2str (red));
5829           lglrmlwch (lgl, other, red, lidx);
5830           lgl->stats->hbr.sub++;
5831           if (red) {
5832             glue = lidx & GLUEMASK;
5833             if (glue != MAXGLUE) {
5834               assert (lgl->stats->red.lrg);
5835               lgl->stats->red.lrg--;
5836               assert (lgl->stats->lir[glue].clauses > 0);
5837               lgl->stats->lir[glue].clauses--;
5838             }
5839           }
5840           if (!red && lgl->dense) {
5841             for (l = c; (other2 = *l); l++) {
5842               if (other2 != -lit) lglrmlocc (lgl, other2, 0, lidx);
5843               if (other2 == -dom) continue;
5844               if (other2 == other) continue;
5845               lgldecocc (lgl, other2);
5846             }
5847             flushoccs++;
5848           }
5849           if (red && glue < MAXGLUE) { LGLCHKACT (c[-1]); c[-1] = REMOVED; }
5850           for (l = c; *l; l++) *l = REMOVED;
5851           if (!red) lgldecirr (lgl, l - c);
5852           *l = REMOVED;
5853         }
5854         delta = 0;
5855         if (dom == lit) {
5856           assert (subsumed);
5857           LOG (3,
5858                "replacing %s large watch %d with binary watch %d blit %d",
5859                lglred2str (red), -lit, -lit, -dom);
5860           blit = (other << RMSHFT) | BINCS | hbred;
5861           *q++ = blit, p++;
5862         } else {
5863           if (subsumed) {
5864             LOG (3, "removing %s large watch %d", lglred2str (red), -lit);
5865             p++;
5866           } else {
5867             LOGCLS (2, c,
5868                     "%s binary clause %d %d becomes reasons "
5869                     "for %d instead of %s large clause",
5870                     lglred2str (hbred), -dom, other, other, lglred2str (red));
5871             assert (hbred == REDCS);
5872           }
5873           delta += lglwchbin (lgl, -dom, other, hbred);
5874         }
5875         delta += lglwchbin (lgl, other, -dom, hbred);
5876         if (delta) p += delta, q += delta, eos += delta;
5877         if (hbred) lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
5878         else lglincirr (lgl, 2);
5879         lglf2rce (lgl, other, -dom, hbred);
5880         lgl->stats->hbr.lrg++;
5881         lgl->stats->hbr.cnt++;
5882         lgl->stats->prgss++;
5883         if (subsumed) continue;
5884       } else {
5885 NO_HBR_JUST_FLRCE:
5886         lglflrce (lgl, other, red, lidx);
5887       }
5888 COPYL:
5889       *q++ = blit;
5890       *q++ = *++p;
5891     }
5892   }
5893   while (p < eos) *q++ = *p++;
5894   lglshrinkhts (lgl, hts, hts->count - (p - q));
5895   if (flushoccs) lglflushremovedoccs (lgl, -lit);
5896   lglpropupdvisits (lgl, visits, travs);
5897 }
5898
5899 static void lglprop2 (LGL * lgl, int lit) {
5900   int other, blit, tag, val, red, visits;
5901   const int * p, * w, * eow;
5902   int64_t travs;
5903   HTS * hts;
5904   LOG (3, "propagating %d over binary clauses", lit);
5905   assert (!lgliselim (lgl, lit));
5906   assert (lglval (lgl, lit) == 1);
5907   visits = 0;
5908   travs = 0;
5909   hts = lglhts (lgl, -lit);
5910   w = lglhts2wchs (lgl, hts);
5911   eow = w + hts->count;
5912   for (p = w; p < eow; p++) {
5913     blit = *p;
5914     tag = blit & MASKCS;
5915     if (tag == TRNCS || tag == LRGCS) p++;
5916     if (tag != BINCS) continue;
5917     visits++;
5918     red = blit & REDCS;
5919     other = blit >> RMSHFT;
5920     travs++;
5921     if (lgliselim (lgl, other)) { assert (red); continue; }
5922     val = lglval (lgl, other);
5923     if (val > 0) continue;
5924     if (val < 0) { lglbonflict (lgl, -lit, blit); break; }
5925     lglf2rce (lgl, other, -lit, red);
5926   }
5927
5928   lglpropupdvisits (lgl, visits, travs);
5929 }
5930
5931 static int lglbcp (LGL * lgl) {
5932   int lit, trail, count;
5933   assert (!lgl->mt);
5934   assert (!lgl->conf.lit);
5935   assert (!lgl->notfullyconnected);
5936   count = 0;
5937   while (!lgl->conf.lit) {
5938     trail = lglcntstk (&lgl->trail);
5939     if (lgl->next2 < trail) {
5940       lit = lglpeek (&lgl->trail, lgl->next2++);
5941       lglprop2 (lgl, lit);
5942       continue;
5943     }
5944     if (lgl->next >= trail) break;
5945     count++;
5946     lit = lglpeek (&lgl->trail, lgl->next++);
5947     lglprop (lgl, lit);
5948   }
5949   if (lgl->lkhd) ADDSTEPS (props.lkhd, count);
5950   else if (lgl->simp) ADDSTEPS (props.simp, count);
5951   else ADDSTEPS (props.search, count);
5952   return !lgl->conf.lit;
5953 }
5954
5955 static int lglbcpsearch (LGL * lgl) {
5956   int lit, count = 0;
5957   assert (!lgl->simp);
5958   assert (!lgl->notfullyconnected);
5959   while ((!lgl->failed || !lgl->level) &&
5960          !lgl->conf.lit &&
5961          lgl->next < lglcntstk (&lgl->trail)) {
5962     lit = lglpeek (&lgl->trail, lgl->next++);
5963     lglpropsearch (lgl, lit);
5964     count++;
5965   }
5966   ADDSTEPS (props.search, count);
5967   lgl->next2 = lgl->next;
5968   if (lgl->conf.lit && lgl->failed) {
5969     LOG (2, "inconsistency overwrites failed assumption %d", lgl->failed);
5970     lgl->failed = 0;
5971   }
5972   return !lgl->conf.lit && !lgl->failed;
5973 }
5974
5975 #ifndef NDEBUG
5976 static void lglchkclnvar (LGL * lgl) {
5977   AVar * av;
5978   int i;
5979   for (i = 2; i < lgl->nvars; i++) {
5980     av = lglavar (lgl, i);
5981     assert (!av->mark);
5982   }
5983 }
5984 #endif
5985
5986 #ifdef RESOLVENT
5987 static int lglmaintainresolvent (LGL * lgl) {
5988 #ifndef NDEBUG
5989   if (lgl->opts->check.val >= 1) return 1;
5990 #endif
5991 #ifndef NLGLOG
5992   if (lgl->opts->log.val >= 2) return 1;
5993 #endif
5994   return 0;
5995 }
5996 #endif
5997
5998 static int lgldecision (LGL * lgl, int lit) {
5999   int * rsn = lglrsn (lgl, lit);
6000   int tag = rsn[0] & MASKCS;
6001   return tag == DECISION;
6002 }
6003
6004 static int lglassumption (LGL * lgl, int lit) {
6005   return lglavar (lgl, lit)->assumed;
6006 }
6007
6008 static int lglpull (LGL * lgl, int lit) {
6009   AVar * av = lglavar (lgl, lit);
6010   int level, res;
6011   level = lglevel (lgl, lit);
6012   if (!level) return 0;
6013   if (av->mark) return 0;
6014   av->mark = 1;
6015   lglpushstk (lgl, &lgl->seen, lit);
6016 #ifdef RESOLVENT
6017   if (lglmaintainresolvent (lgl)) {
6018     lglpushstk (lgl, &lgl->resolvent, lit);
6019     LOG (2, "adding %d to resolvent", lit);
6020     LOGRESOLVENT (3, "resolvent after adding %d is", lit);
6021   }
6022 #endif
6023   if (level == lgl->level) {
6024     LOG (2, "reason literal %d at same level %d", lit, lgl->level);
6025     res = 1;
6026   } else {
6027     lglpushstk (lgl, &lgl->clause, lit);
6028     LOG (2, "adding literal %d at upper level %d to 1st UIP clause",
6029          lit, lglevel (lgl, lit));
6030     if (!lglevelused (lgl, level)) {
6031       lgluselevel (lgl, level);
6032       lglpushstk (lgl, &lgl->frames, level);
6033       LOG (2, "pulled in decision level %d", level);
6034     }
6035     res = 0;
6036   }
6037   return res;
6038 }
6039
6040 static int lglpoison (LGL * lgl, int lit, Stk * stk, int local) {
6041   AVar * av = lglavar (lgl, lit);
6042   int level, res;
6043   if (av->mark) res = 0;
6044   else {
6045     level = lglevel (lgl, lit);
6046     if (!level) res = 0;
6047     else {
6048       assert (level < lgl->level);
6049       if (lgldecision (lgl, lit)) res = 1;
6050       else if (!lglevelused (lgl, level)) res = 1;
6051       else {
6052         lgl->stats->poison.search++;
6053         if (av->poisoned) {
6054           lgl->stats->poison.hits++;
6055           res = 1;
6056         } else if (local) res = 1;
6057         else {
6058           av->mark = 1;
6059           lglpushstk (lgl, &lgl->seen, lit);
6060           lglpushstk (lgl, stk, lit);
6061           res = 0;
6062         }
6063       }
6064     }
6065   }
6066   if (res && !av->poisoned) {
6067     av->poisoned = 1;
6068     lglpushstk (lgl, &lgl->poisoned, lit);
6069   }
6070   return res;
6071 }
6072
6073 static int lglminclslit (LGL * lgl, int start, int local) {
6074   int lit, tag, r0, r1, other, * p, * q, *top, old;
6075   int poisoned, * rsn, found;
6076   AVar * av, * bv;
6077   assert (lglmarked (lgl, start));
6078   lit = start;
6079   rsn = lglrsn (lgl, lit);
6080   r0 = rsn[0];
6081   tag = (r0 & MASKCS);
6082   if (tag == DECISION) return 0;
6083   old = lglcntstk (&lgl->seen);
6084   assert (lglmtstk (&lgl->minstk));
6085   for (;;) {
6086     r1 = rsn[1];
6087     if (tag == BINCS || tag == TRNCS) {
6088       other = r0 >> RMSHFT;
6089       if (lglpoison (lgl, other, &lgl->minstk, local)) goto FAILED;
6090       if (tag == TRNCS &&
6091           lglpoison (lgl, r1, &lgl->minstk, local)) goto FAILED;
6092     } else {
6093       assert (tag == LRGCS);
6094       p = lglidx2lits (lgl, (r0 & REDCS), r1);
6095       found = 0;
6096       while ((other = *p++)) {
6097         if (other == -lit) found++;
6098         else if (lglpoison (lgl, other, &lgl->minstk, local)) goto FAILED;
6099       }
6100       assert (found == 1);
6101     }
6102     if (lglmtstk (&lgl->minstk)) { lglrelstk (lgl, &lgl->minstk); return 1; }
6103     lit = lglpopstk (&lgl->minstk);
6104     assert (lglavar (lgl, lit)->mark);
6105     rsn = lglrsn (lgl, lit);
6106     r0 = rsn[0];
6107     tag = (r0 & MASKCS);
6108   }
6109 FAILED:
6110   lglclnstk (&lgl->minstk);
6111   p = lgl->seen.top;
6112   top = lgl->seen.top = lgl->seen.start + old;
6113   while (p > top) {
6114     lit = *--p;
6115     av = lglavar (lgl, lit);
6116     assert (av->mark);
6117     av->mark = 0;
6118     poisoned = av->poisoned;
6119     if (poisoned) continue;
6120     rsn = lglrsn (lgl, lit);
6121     r0 = rsn[0];
6122     tag = (r0 & MASKCS);
6123     assert (tag != DECISION);
6124     r1 = rsn[1];
6125     if (tag == BINCS || tag == TRNCS) {
6126       other = r0 >> RMSHFT;
6127       bv = lglavar (lgl, other);
6128       if (bv->poisoned) poisoned = 1;
6129       else if (tag == TRNCS) {
6130         bv = lglavar (lgl, r1);
6131         if (bv->poisoned) poisoned = 1;
6132       }
6133     } else {
6134       assert (tag == LRGCS);
6135       q = lglidx2lits (lgl, (r0 & REDCS), r1);
6136       while (!poisoned && (other = *q++))
6137         poisoned = lglavar (lgl, other)->poisoned;
6138     }
6139     if (!poisoned) continue;
6140     assert (!av->poisoned);
6141     av->poisoned = 1;
6142     lglpushstk (lgl, &lgl->poisoned, lit);
6143   }
6144   return 0;
6145 }
6146
6147 double lglprocesstime (void) {
6148   struct rusage u;
6149   double res;
6150   if (getrusage (RUSAGE_SELF, &u)) return 0;
6151   res = u.ru_utime.tv_sec + 1e-6 * u.ru_utime.tv_usec;
6152   res += u.ru_stime.tv_sec + 1e-6 * u.ru_stime.tv_usec;
6153   return res;
6154 }
6155
6156 static double lglgetime (LGL * lgl) {
6157   if (lgl->cbs && lgl->cbs->getime) return lgl->cbs->getime ();
6158   else return lglprocesstime ();
6159 }
6160
6161 static void lglstart (LGL * lgl, double * timestatsptr) {
6162   int nest = lgl->timers->nest;
6163   assert (timestatsptr);
6164   assert (nest < MAXPHN);
6165   assert ((double*) lgl->times <= timestatsptr);
6166   assert (timestatsptr < (double*)(sizeof *lgl->times + (char*) lgl->times));
6167   lgl->timers->idx[nest] = timestatsptr - (double*)lgl->times;
6168   lgl->timers->phase[nest] = lglgetime (lgl);
6169   lgl->timers->nest++;
6170 }
6171
6172 void lglflushtimers (LGL * lgl) {
6173   double time = lglgetime (lgl), delta, entered, * ptr;
6174   int nest;
6175   for (nest = 0; nest < lgl->timers->nest; nest++) {
6176     entered = lgl->timers->phase[nest];
6177     lgl->timers->phase[nest] = time;
6178     delta = time - entered;
6179     if (delta < 0) delta = 0;
6180     ptr = lgl->timers->idx[nest] + (double*)lgl->times;
6181     *ptr += delta;
6182   }
6183 }
6184
6185 double lglsec (LGL * lgl) {
6186   REQINIT ();
6187   lglflushtimers (lgl);
6188   return lgl->times->all;
6189 }
6190
6191 static void lglstop (LGL * lgl) {
6192   lglflushtimers (lgl);
6193   lgl->timers->nest--;
6194   assert (lgl->timers->nest >= 0);
6195 }
6196
6197 double lglmaxmb (LGL * lgl) {
6198   REQINIT ();
6199   return (lgl->stats->bytes.max + sizeof *lgl) / (double)(1<<20);
6200 }
6201
6202 size_t lglbytes (LGL * lgl) {
6203   REQINIT ();
6204   return lgl->stats->bytes.current;
6205 }
6206
6207 double lglmb (LGL * lgl) {
6208   REQINIT ();
6209   return (lgl->stats->bytes.current + sizeof *lgl) / (double)(1<<20);
6210 }
6211
6212 static double lglagility (LGL * lgl) { return lgl->flips/1e7; }
6213
6214 static double lglavg (double n, double d) {
6215   return d != 0 ? n / d : 0.0;
6216 }
6217
6218 static double lglheight (LGL * lgl) {
6219   return lglavg (lgl->stats->height, lgl->stats->decisions);
6220 }
6221
6222 static double lglglue (LGL * lgl) {
6223   return lglavg (lgl->stats->glues.sum, lgl->stats->glues.count);
6224 }
6225
6226 static void lglrephead (LGL * lgl) {
6227   if (lgl->tid > 0) return;
6228   lgl->forcerephead = 0;
6229   lgl->repcntdown = REPMOD;
6230   if (lgl->tid > 0) return;
6231   if (lgl->cbs && lgl->cbs->msglock.lock)
6232     lgl->cbs->msglock.lock (lgl->cbs->msglock.state);
6233   assert (lgl->prefix);
6234   fprintf (lgl->out, "%s\n", lgl->prefix);
6235   fprintf (lgl->out, "%s%s"
6236 " seconds         irredundant          redundant clauses agility  "
6237 " height\n", lgl->prefix, !lgl->tid ? "  " : "");
6238   fprintf (lgl->out, "%s%s"
6239 "         variables clauses conflicts large ternary binary    "
6240 "glue         MB\n", lgl->prefix, !lgl->tid ? "  " : "");
6241   fprintf (lgl->out, "%s\n", lgl->prefix);
6242   fflush (lgl->out);
6243   if (lgl->cbs && lgl->cbs->msglock.unlock)
6244     lgl->cbs->msglock.unlock (lgl->cbs->msglock.state);
6245 }
6246
6247 static void lglrep (LGL * lgl, int level, char type) {
6248   if (lgl->opts->verbose.val < level) return;
6249   if ((level > 0 && lgl->forcerephead) || !lgl->repcntdown--)
6250     lglrephead (lgl);
6251   lglprt (lgl, level,
6252           "%c %6.1f %7d %8d %9lld %7d %6d %5d %3.0f %4.1f %5.1f %4.0f",
6253           type,
6254           lgl->opts->abstime.val ? lglgetime (lgl) : lglsec (lgl),
6255           lglrem (lgl),
6256           lgl->stats->irr.clauses.cur,
6257           (LGLL) lgl->stats->confs,
6258           lgl->stats->red.lrg,
6259           lgl->stats->red.trn,
6260           lgl->stats->red.bin,
6261           lglagility (lgl),
6262           lglglue (lgl),
6263           lglheight (lgl),
6264           lglmb (lgl));
6265   lgl->stats->reported++;
6266 }
6267
6268 static void lglflshrep (LGL * lgl) {
6269   if (!lgl->stats->reported) return;
6270   if (lgl->stats->reported % REPMOD) lglrephead (lgl);
6271   else lglprt (lgl, 1, "");
6272 }
6273
6274 static void lglfitlir (LGL * lgl, Stk * lir) {
6275   lglfitstk (lgl, lir);
6276 }
6277
6278 static void lglchkred (LGL * lgl) {
6279 #ifndef NDEBUG
6280   int glue, idx, sign, lit, thisum, sum, sum2, sum3;
6281   int blit, tag, red, other, other2;
6282   int * p, * c, * w, * eow;
6283   HTS * hts;
6284   Stk * lir;
6285   if (lgl->mt) return;
6286   sum = 0;
6287   for (glue = 0; glue < MAXGLUE; glue++) {
6288     lir = lgl->red + glue;
6289     thisum = 0;
6290     for (c = lir->start; c < lir->top; c = p + 1) {
6291       p = c;
6292       if (*p >= NOTALIT) continue;
6293       while (*p) p++;
6294       assert (p - c >= 4);
6295       thisum++;
6296     }
6297     assert (thisum == lgl->stats->lir[glue].clauses);
6298     sum += thisum;
6299   }
6300   assert (sum == lgl->stats->red.lrg);
6301   sum2 = sum3 = 0;
6302   for (idx = 2; idx < lgl->nvars; idx++)
6303     for (sign = -1; sign <= 1; sign += 2) {
6304       lit = sign * idx;
6305       hts = lglhts (lgl, lit);
6306       w = lglhts2wchs (lgl, hts);
6307       eow = w + hts->count;
6308       for (p = w; p < eow; p++) {
6309         blit = *p;
6310         tag = blit & MASKCS;
6311         red = blit & REDCS;
6312         if (tag == TRNCS || tag == LRGCS) p++;
6313         if (!red || tag == LRGCS || tag == OCCS) continue;
6314         other = blit >> RMSHFT;
6315         if (abs (other) < idx) continue;
6316         if (tag == BINCS) sum2++;
6317         else {
6318           assert (tag == TRNCS);
6319           other2 = *p;
6320           if (abs (other2) < idx) continue;
6321           sum3++;
6322         }
6323       }
6324     }
6325   assert (sum2 == lgl->stats->red.bin);
6326   assert (sum3 == lgl->stats->red.trn);
6327 #endif
6328 }
6329
6330 static int lglcmppasl (LGL * lgl, PASL * a, PASL * b, int glueuseless) {
6331   int res, psmval, psmdiff, aglue, bglue, gluediff;
6332   psmdiff = a->psm - b->psm;
6333   psmval = lgl->opts->psm.val;
6334   if (psmval == 3 && psmdiff) return psmdiff;
6335   aglue = (a->lidx & GLUEMASK);
6336   bglue = (b->lidx & GLUEMASK);
6337   gluediff = aglue - bglue;
6338   if (!glueuseless && gluediff) return gluediff;
6339   if (psmval == 2 && psmdiff) return psmdiff;
6340   if ((res = (a->act - b->act))) return res;
6341   if (psmval == 1 && psmdiff) return psmdiff;
6342   if ((res = (b->size - a->size))) return res;
6343   if (glueuseless && gluediff) return gluediff;
6344   return a->lidx - b->lidx;
6345 }
6346
6347 #define LGLCMPPASL(A,B) lglcmppasl (lgl, (A), (B), glueuseless)
6348
6349 static int lglneedacts (LGL * lgl,
6350                         int * glueuselessptr,
6351                         int * needmoreclausesptr) {
6352   int64_t clauses = 0, weighted = 0, tmp, avg, var = 0, std, delta;
6353   int glue, maxglue = 0;
6354
6355   for (glue = 0; glue <= MAXGLUE; glue++) {
6356     tmp = lgl->stats->lir[glue].clauses;
6357     if (tmp) maxglue = glue;
6358     clauses += tmp;
6359     weighted += glue * tmp;
6360   }
6361   avg = clauses ? (10*weighted)/clauses : 0;
6362   lglprt (lgl, 2,
6363     "[needacts-%d] existing clauses glue average %.1f",
6364     lgl->stats->reduced.count, avg/10.0);
6365   for (glue = 1; glue <= MAXGLUE; glue++) {
6366     delta = (10*glue - avg);
6367     var += delta*delta * lgl->stats->lir[glue].clauses;
6368   }
6369   var = clauses ? var / clauses : 0;
6370   std = lglceilsqrt64 (var);
6371   lglprt (lgl, 2,
6372     "[needacts-%d] existing clauses glue standard deviation %.1f",
6373     lgl->stats->reduced.count, std/10.0);
6374
6375   if (std < lgl->opts->actgsdul.val) {
6376     lglprt (lgl, 2,
6377       "[needacts-%d] glue useless since standard deviation %.1f < %.1f",
6378       lgl->stats->reduced.count, std/10.0, lgl->opts->actgsdul.val/10.0);
6379     *glueuselessptr = 1;
6380   } else {
6381     lglprt (lgl, 2,
6382       "[needacts-%d] glue useful since standard deviation %.1f >= %.1f",
6383       lgl->stats->reduced.count, std/10.0, lgl->opts->actgsdul.val/10.0);
6384     *glueuselessptr = 0;
6385   }
6386
6387   if (maxglue <= lgl->opts->actgeomlim.val) {
6388     lglprt (lgl, 2,
6389       "[needacts-%d] really need more clauses since maxglue %d <= %d",
6390       lgl->stats->reduced.count, maxglue, lgl->opts->actgeomlim.val);
6391     *needmoreclausesptr = 2;
6392   } else if (maxglue <= lgl->opts->actdblarithlim.val) {
6393     lglprt (lgl, 2,
6394       "[needacts-%d] could use more clauses since maxglue %d <= %d",
6395       lgl->stats->reduced.count, maxglue, lgl->opts->actdblarithlim.val);
6396     *needmoreclausesptr = 1;
6397   } else {
6398     lglprt (lgl, 2,
6399       "[needacts-%d] no need for more clauses since maxglue %d > %d",
6400       lgl->stats->reduced.count, maxglue, lgl->opts->actdblarithlim.val);
6401     *needmoreclausesptr = 0;
6402   }
6403
6404   if (lglrem (lgl) > lgl->opts->actvlim.val) {
6405     lglprt (lgl, 2,
6406       "[needacts-%d] too many variables %d > %d",
6407       lgl->stats->reduced.count, lglrem (lgl), lgl->opts->actvlim.val);
6408     return 0;
6409   }
6410   if (avg > lgl->opts->actavgmax.val) {
6411     lglprt (lgl, 2,
6412       "[needacts-%d] very large average glue %.1f > %.1f",
6413       lgl->stats->reduced.count, avg/10.0, lgl->opts->actavgmax.val/10.0);
6414     return 1;
6415   }
6416   if (std <= lgl->opts->actstdmin.val) {
6417     lglprt (lgl, 2,
6418       "[needacts-%d] very small standard deviation glue %.1f <= %.1f",
6419       lgl->stats->reduced.count, std/10.0, lgl->opts->actstdmin.val/10.0);
6420     return 1;
6421   }
6422   if (std > lgl->opts->actstdmax.val) {
6423     lglprt (lgl, 2,
6424       "[needacts-%d] very large standard deviation glue %.1f > %.1f",
6425       lgl->stats->reduced.count, std/10.0, lgl->opts->actstdmax.val/10.0);
6426     return 1;
6427   }
6428
6429   lglprt (lgl, 2,
6430     "[needacts-%d] regular glue average and standard deviation",
6431     lgl->stats->reduced.count);
6432
6433   return 0;
6434 }
6435
6436 static int lglagile (LGL * lgl) {
6437   switch (lgl->opts->agile.val) {
6438     case 1:
6439       return lgl->flips >= lgl->opts->agilelim.val * 10000000ull;
6440     case 2:
6441       return lgl->flips >=
6442         (50*(sin(lgl->stats->confs*M_PI/2.0/lgl->opts->agilesinint.val) + 1))
6443         * 10000000ull;
6444   }
6445  return 0;
6446 }
6447
6448 static int lglsaturating (LGL * lgl) {
6449   int64_t avglue, avgheight;
6450   if (!lgl->opts->saturating.val) return 0;
6451   if (!lgl->stats->glues.count) return 0;
6452   if (!lgl->stats->decisions) return 0;
6453   avglue = lgl->stats->glues.sum;
6454   avglue *= 100 + lgl->opts->saturating.val;
6455   avglue /= lgl->stats->glues.count;
6456   avgheight = lgl->stats->height;
6457   avgheight *= 100;
6458   avgheight /= lgl->stats->decisions;
6459   return avglue >= avgheight;
6460 }
6461
6462 static void lglboundredl (LGL * lgl) {
6463   int64_t minabs, minrel, maxabs, maxrel, oldlim, newlim;
6464
6465   newlim = oldlim = lgl->limits->reduce.inner;
6466   if (!lgl->opts->redlbound.val) goto SKIP;
6467
6468   lglprt (lgl, 2, 
6469     "[bound-reduce-limit] preliminary reduce limit %d before bounding",
6470     oldlim);
6471
6472   minrel = lgl->opts->redlminrel.val;
6473   minrel *= (lgl->stats->irr.clauses.cur + 99ll)/100ll;
6474   minabs = lgl->opts->redlminabs.val;
6475
6476   lglprt (lgl, 2, "[bound-reduce-limit] minrel = %d, minabs = %d",
6477     minrel, minabs);
6478
6479   if (minrel < minabs) {
6480     if (minrel > lgl->limits->reduce.inner) {
6481       lglprt (lgl, 2, 
6482         "[bound-reduce-limit] relative minimum reduce limit %d hit", minrel);
6483       newlim = minrel;
6484     }
6485   } else {
6486     if (minabs > lgl->limits->reduce.inner) {
6487       lglprt (lgl, 2, 
6488         "[bound-reduce-limit] absolute minimum reduce limit of %d hit",
6489         minabs);
6490       newlim = minabs;
6491     }
6492   }
6493
6494   maxrel = lgl->opts->redlmaxrel.val;
6495   maxrel *= (lgl->stats->irr.clauses.cur + 99ll)/100ll;
6496   maxrel += lgl->opts->redlmininc.val * (int64_t) lgl->limits->reduce.extra;
6497   maxabs = lgl->opts->redlmaxabs.val;
6498
6499   lglprt (lgl, 2,
6500     "[bound-reduce-limit] maxrel = %d, maxabs = %d", maxrel, maxabs);
6501
6502   if (maxrel < maxabs) {
6503     lgl->limits->reduce.extra++;
6504     if (maxrel < lgl->limits->reduce.inner) {
6505       lglprt (lgl, 2, 
6506         "[bound-reduce-limit] relative maximum reduce limit %d hit", maxrel);
6507       newlim = maxrel;
6508     }
6509   } else {
6510     if (maxabs < lgl->limits->reduce.inner) {
6511       lglprt (lgl, 2,
6512         "[bound-reduce-limit] absolute maximum reduce limit of %d hit",
6513         maxabs);
6514       newlim = maxabs;
6515     }
6516   }
6517
6518 SKIP:
6519
6520   lgl->limits->reduce.inner = newlim;
6521   lglprt (lgl, 2,
6522     "[bound-reduce-limit] new reduce limit of %d after %lld conflicts",
6523     lgl->limits->reduce.inner, (LGLL) lgl->stats->confs);
6524 }
6525
6526 static int64_t lglubyrec (LGL * lgl, int i) {
6527   int64_t res = 0, s = 0;
6528   int k;
6529
6530   for (k = 1; !res && k < 32; s++, k++) {
6531     if (i == (1 << k) - 1)
6532       res = 1 << (k - 1);
6533   }
6534
6535   for (k = 1; !res; k++, s++)
6536     if ((1 << (k - 1)) <= i && i < (1 << k) - 1)
6537       res = lglubyrec (lgl, i - (1 << (k-1)) + 1);
6538
6539   lgl->stats->luby.steps += s;
6540
6541   assert (res > 0);
6542   return res;
6543 }
6544
6545 static int64_t lgluby (LGL * lgl, int i) {
6546   assert (i > 0);
6547   lgl->stats->luby.count++;
6548   return lglubyrec (lgl, i);
6549 }
6550
6551 static int64_t lglinout (LGL * lgl, int c, int relincpcnt) {
6552   int64_t i = 1, o = 1;
6553
6554   assert (c > 0);
6555
6556   lgl->stats->inout.count++;
6557   lgl->stats->inout.steps += c;
6558
6559   while (c-- > 0) {
6560     i = ((100 + relincpcnt)*i + 99)/100;
6561     if (i < o) continue;
6562     i = 1;
6563     o = ((100 + relincpcnt)*o + 99)/100;
6564   }
6565
6566   assert (i > 0);
6567   return i;
6568 }
6569
6570 static int lglmemout (LGL * lgl) {
6571   size_t cur;
6572   int res;
6573   if (lgl->opts->memlim.val < 0) return 0;
6574   cur = lgl->stats->bytes.current;
6575   cur >>= 20;
6576   res = (cur >= lgl->opts->memlim.val);
6577   if (res)
6578     lglprt (lgl, 2, "memory limit of %d MB hit after allocating %lld MB",
6579       lgl->opts->memlim.val, (LGLL) cur);
6580   return res;
6581 }
6582
6583 static Val lgliphase (LGL * lgl, int lit) {
6584   Val res = lglavar (lgl, lit)->phase;
6585   if (lit < 0) res = -res;
6586   return res;
6587 }
6588
6589 static void lglreduce (LGL * lgl, int forced) {
6590   int * p, * q, * start, * c, ** maps, * sizes, * map, * eow, * rsn;
6591   int nlocked, collected, sumcollected, nunlocked, moved, act, psm;
6592   int glue, minredglue, maxredglue, target, rem, nkeep;
6593   int inc, acts, glueuseless, needmoreclauses, delta;
6594   PASL * pasls, * pasl; int npasls, szpasls;
6595   int size, idx, tag, red, i, blit;
6596   int r0, lidx, src, dst, lit;
6597   char type = '-';
6598   int64_t outer;
6599   HTS * hts;
6600   DVar * dv;
6601   Stk * lir;
6602   lglchkred (lgl);
6603   lglstart (lgl, &lgl->times->red);
6604   lgl->stats->reduced.count++;
6605   LOG (1, "starting reduction %d", lgl->stats->reduced.count);
6606   acts = lglneedacts (lgl, &glueuseless, &needmoreclauses);
6607   delta = lgl->stats->red.lrg;
6608   delta -= lgl->lrgluereasons;
6609   delta -= lgl->stats->lir[0].clauses;
6610   assert (delta >= 0);
6611   if (delta > 3*lgl->limits->reduce.inner/2)
6612     target = delta - lgl->limits->reduce.inner/2;
6613   else target = delta/2;
6614   rem = target;
6615   LOG (2, "target is to collect %d clauses out of %d", target, delta);
6616   for (maxredglue = MAXGLUE-1; maxredglue >= 0; maxredglue--)
6617     if (lgl->stats->lir[maxredglue].clauses > 0) break;
6618   LOG (2, "maximum reduction glue %d", maxredglue);
6619   if (lgl->opts->acts.val < 2) acts = lgl->opts->acts.val;
6620   if (acts) {
6621     lgl->stats->acts++;
6622     lglprt (lgl, 2,
6623       "[needacts-%d] using primarily activities for reduction",
6624       lgl->stats->reduced.count);
6625     szpasls = lgl->stats->red.lrg;
6626     minredglue = 1;
6627   } else {
6628     lglprt (lgl, 2,
6629       "[needacts-%d] using primarily glues for reduction",
6630       lgl->stats->reduced.count);
6631     pasls = 0;
6632     if (maxredglue > 0) {
6633       for (minredglue = maxredglue;  minredglue > 1;  minredglue--) {
6634         LOG (2, "%d candidate clauses with glue %d",
6635              lgl->stats->lir[minredglue].clauses, minredglue);
6636         if (lgl->stats->lir[minredglue].clauses >= rem) break;
6637         rem -= lgl->stats->lir[minredglue].clauses;
6638       }
6639     } else minredglue = 1;
6640     szpasls = lgl->stats->lir[minredglue].clauses;
6641   }
6642   LOG (2, "minum reduction glue %d with %d remaining target clauses %.0f%%",
6643        minredglue, rem, lglpcnt (rem, target));
6644   NEW (maps, maxredglue + 1);
6645   NEW (sizes, maxredglue + 1);
6646   for (glue = minredglue; glue <= maxredglue; glue++) {
6647     lir = lgl->red + glue;
6648     size = lglcntstk (lir);
6649     assert (!size || size >= 6);
6650     size = (size + 5)/6;
6651     sizes[glue] = size;
6652     lglfitstk (lgl, lir);
6653     NEW (maps[glue], size);
6654     map = maps[glue];
6655     for (i = 0; i < size; i++) map[i] = -2;
6656   }
6657   nlocked = 0;
6658   for (i = 0; i < lglcntstk (&lgl->trail); i++) {
6659     lit = lglpeek (&lgl->trail, i);
6660     idx = abs (lit);
6661     rsn = lglrsn (lgl, idx);
6662     r0 = rsn[0];
6663     red = r0 & REDCS;
6664     if (!red) continue;
6665     tag = r0 & MASKCS;
6666     if (tag != LRGCS) continue;
6667     lidx = rsn[1];
6668     glue = lidx & GLUEMASK;
6669     if (glue == MAXGLUE) continue;
6670     if (glue < minredglue) continue;
6671     if (glue > maxredglue) continue;
6672     lidx >>= GLUESHFT;
6673 #ifndef NLGLOG
6674     lir = lgl->red + glue;
6675     LOGCLS (5, lir->start + lidx,
6676             "locking reason of literal %d glue %d clause",
6677             lit, glue);
6678 #endif
6679     lidx /= 6;
6680     assert (lidx < sizes[glue]);
6681     assert (maps[glue][lidx] == -2);
6682     maps[glue][lidx] = -1;
6683     nlocked++;
6684   }
6685   LOG (2, "locked %d learned clauses %.0f%%",
6686        nlocked, lglpcnt (nlocked, lgl->stats->red.lrg));
6687   NEW (pasls, szpasls);
6688   npasls = 0;
6689   for (glue = minredglue; glue <= maxredglue; glue++) {
6690     lir = lgl->red + glue;
6691     start = lir->start;
6692     for (c = start; c < lir->top; c = p + 1) {
6693       psm = 0;
6694       act = *c;
6695       if (act == REMOVED) {
6696         for (p = c + 1; p < lir->top && *p == REMOVED; p++)
6697           ;
6698         p--;
6699         continue;
6700       }
6701       for (p = ++c; (lit = *p); p++)
6702         if (lgliphase (lgl, lit) >= 0) psm++;
6703       assert (npasls < szpasls);
6704       pasl = pasls + npasls++;
6705       pasl->psm = psm;
6706       pasl->act = act;
6707       pasl->size = p - c;
6708       pasl->lidx = ((c - start) << GLUESHFT) | glue;
6709     }
6710     if (!acts) { assert (glue == minredglue); break; }
6711   }
6712   assert (npasls <= szpasls);
6713
6714   if (glueuseless) {
6715     lglprt (lgl, 2,
6716       "[reduce-%d] ignoring useless glue",
6717       lgl->stats->reduced.count);
6718     lgl->stats->reduced.gul++;
6719   }
6720   SORT (PASL, pasls, npasls, LGLCMPPASL);
6721   LOG (1, "copied and sorted %d activities", npasls);
6722
6723   nkeep = 0;
6724   for (idx = rem; idx < npasls; idx++) {
6725     pasl = pasls + idx;
6726     lidx = pasl->lidx;
6727     glue = lidx & GLUEMASK;
6728     lidx >>= GLUESHFT;
6729     lidx /= 6;
6730     assert (lidx < sizes[glue]);
6731     maps[glue][lidx] = -1;
6732     nkeep++;
6733   }
6734   DEL (pasls, szpasls);
6735   LOG (1, "explicity marked %d additional clauses to keep", nkeep);
6736   sumcollected = 0;
6737   for (glue = minredglue; glue <= maxredglue; glue++) {
6738     lir = lgl->red + glue;
6739     map = maps[glue];
6740 #ifndef NDEBUG
6741     size = sizes[glue];
6742 #endif
6743     q = start = lir->start;
6744     collected = 0;
6745     for (c = start; c < lir->top; c = p + 1) {
6746       act = *c++;
6747       if (act == REMOVED) {
6748         for (p = c; p < lir->top && *p == REMOVED; p++)
6749           ;
6750         assert (p >= lir->top || *p < NOTALIT || lglisact (*p));
6751         p--;
6752         continue;
6753       }
6754       p = c;
6755       LGLCHKACT (act);
6756       src = (c - start)/6;
6757       assert (src < size);
6758       if (map[src] == -2) {
6759         assert (collected < lgl->stats->lir[glue].clauses);
6760         collected++;
6761         LOGCLS (5, c, "collecting glue %d clause", glue);
6762         while (*p) p++;
6763       } else {
6764         dst = q - start + 1;
6765         map[src] = dst;
6766         if (p == q) {
6767           while (*p) p++;
6768           q = p + 1;
6769         } else {
6770           *q++ = act;
6771           LOGCLS (5, c, "moving from %d to %d glue %d clause",
6772                   (c - start), dst, glue);
6773           while (*p) *q++ = *p++;
6774           *q++ = 0;
6775         }
6776       }
6777     }
6778     LOG (2, "collected %d glue %d clauses", collected, glue);
6779     sumcollected += collected;
6780     assert (sumcollected <= lgl->stats->red.lrg);
6781     assert (lgl->stats->lir[glue].clauses >= collected);
6782     lgl->stats->lir[glue].clauses -= collected;
6783     lgl->stats->lir[glue].reduced += collected;
6784     lir->top = q;
6785     lglfitlir  (lgl, lir);
6786   }
6787   LOG (2, "collected altogether %d clauses", sumcollected);
6788   assert (sumcollected <= lgl->stats->red.lrg);
6789   lgl->stats->red.lrg -= sumcollected;
6790   nunlocked = 0;
6791   for (idx = 2; idx < lgl->nvars; idx++) {
6792     if (!lglval (lgl, idx)) continue;
6793     rsn = lglrsn (lgl, idx);
6794     r0 = rsn[0];
6795     red = r0 & REDCS;
6796     if (!red) continue;
6797     tag = r0 & MASKCS;
6798     if (tag != LRGCS) continue;
6799     lidx = rsn[1];
6800     glue = lidx & GLUEMASK;
6801     if (glue < minredglue) continue;
6802     if (glue > maxredglue) continue;
6803     src = (lidx >> GLUESHFT);
6804     assert (src/6 < sizes[glue]);
6805     dst = maps[glue][src/6];
6806     assert (dst >= 0);
6807     dst <<= GLUESHFT;
6808     dst |= lidx & GLUEMASK;
6809     rsn[1] = dst;
6810     nunlocked++;
6811   }
6812   LOG (2, "unlocked %d reasons", nunlocked);
6813   assert (nlocked == nunlocked);
6814   collected = moved = 0;
6815   for (idx = 2; idx < lgl->nvars; idx++) {
6816     dv = lgldvar (lgl, idx);
6817     for (i = 0; i <= 1; i++) {
6818       hts = dv->hts + i;
6819       if (!hts->offset) continue;
6820       q = lglhts2wchs (lgl, hts);
6821       assert (hts->count >= 0);
6822       eow = q + hts->count;
6823       for (p = q; p < eow; p++) {
6824         blit = *p;
6825         red = blit & REDCS;
6826         tag = blit & MASKCS;
6827         if (red && tag == LRGCS) {
6828           lidx = *++p;
6829           glue = lidx & GLUEMASK;
6830           if (glue < minredglue || glue > maxredglue) {
6831             dst = lidx >> GLUESHFT;
6832           } else {
6833             src = lidx >> GLUESHFT;
6834             assert (src/6 < sizes[glue]);
6835             dst = maps[glue][src/6];
6836           }
6837           if (dst >= 0) {
6838             moved++;
6839             *q++ = blit;
6840             *q++ = (dst << GLUESHFT) | (lidx & GLUEMASK);
6841           } else collected++;
6842         } else {
6843           *q++ = blit;
6844           if (tag != BINCS) {
6845             assert (tag == TRNCS || tag == LRGCS);
6846             *q++ = *++p;
6847           }
6848         }
6849       }
6850       lglshrinkhts (lgl, hts, hts->count - (p - q));
6851     }
6852   }
6853   LOG (1, "moved %d and collected %d occurrences", moved, collected);
6854   for (glue = minredglue; glue <= maxredglue; glue++)
6855     DEL (maps[glue], sizes[glue]);
6856   DEL (sizes, maxredglue+1);
6857   DEL (maps, maxredglue+1);
6858   if (lgl->opts->redfixed.val) goto NOINC;
6859   if (lglmemout (lgl)) {
6860     inc = 0;
6861     lglprt (lgl, 2,
6862       "[reduce-%d] no increase of reduce limit since memory limit was hit",
6863       lgl->stats->reduced.count);
6864     lgl->stats->reduced.memlim++;
6865   } else if (!needmoreclauses) {
6866     inc = lgl->opts->redlinc.val;
6867     lglprt (lgl, 2,
6868       "[reduce-%d] arithmetic increase of reduce limit",
6869       lgl->stats->reduced.count);
6870     lgl->stats->reduced.arith++;
6871   } else if (needmoreclauses == 1) {
6872     inc = 2*lgl->opts->redlinc.val;
6873     lglprt (lgl, 2,
6874        "[reduce-%d] double-arithmetic increase of reduce limit",
6875        lgl->stats->reduced.count);
6876     lgl->stats->reduced.arith2++;
6877     lgl->stats->reduced.arith++;
6878   } else {
6879     inc = (lgl->opts->redlexpfac.val * lgl->limits->reduce.inner + 99)/100;
6880     if (!inc) inc++;
6881     lglprt (lgl, 2,
6882       "[reduce-%d] geometric increase of reduce limit",
6883       lgl->stats->reduced.count);
6884     lgl->stats->reduced.geom++;
6885   }
6886   LOG (1, "reduce increment %d", inc);
6887   lgl->limits->reduce.inner += inc;
6888   assert (forced || lgl->opts->reduce.val);
6889   if  (lgl->opts->reduce.val > 1 &&
6890        (lglrem (lgl) < lgl->opts->redoutvlim.val ||
6891         lgl->stats->irr.clauses.cur < lgl->opts->redoutclim.val) &&
6892        lgl->limits->reduce.inner >= lgl->limits->reduce.outer) {
6893     type = '/';
6894     lgl->stats->reduced.reset++;
6895     lgl->limits->reduce.inner = lgl->opts->redlinit.val;
6896     lglboundredl (lgl);
6897     if (lgl->opts->reduce.val == 2) {
6898       outer = lgl->limits->reduce.inner;
6899       outer *= lgluby (lgl, lgl->stats->reduced.reset);
6900     } else if (lgl->opts->reduce.val == 3) {
6901       outer = lgl->limits->reduce.inner;
6902       outer *= lglinout (lgl, lgl->stats->reduced.reset,
6903                          lgl->opts->redinoutinc.val);
6904     } else {
6905       assert (lgl->opts->reduce.val == 4);
6906       outer = lgl->limits->reduce.outer + lgl->opts->redloutinc.val;
6907       if (outer < lgl->limits->reduce.inner)
6908         outer = lgl->limits->reduce.inner;
6909     }
6910     if (outer > (int64_t) INT_MAX) outer = INT_MAX;
6911     lgl->limits->reduce.outer = outer;
6912   } else lglboundredl (lgl);
6913 NOINC:
6914   lglrelstk (lgl, &lgl->learned);
6915   lglrep (lgl, 1, type);
6916   lglchkred (lgl);
6917   lglstop (lgl);
6918 }
6919
6920 void lglreducecache (LGL * lgl) {
6921   REQINITNOTFORKED ();
6922   TRAPI ("reduce");
6923   if (lgl->mt) return;
6924   lgl->limits->reduce.inner = lgl->opts->redlinit.val;
6925   lglboundredl (lgl);
6926   lglreduce (lgl, 1);
6927   lgl->limits->reduce.inner = lgl->opts->redlinit.val;
6928   lglboundredl (lgl);
6929   lgl->limits->reduce.outer = 2*lgl->limits->reduce.inner;
6930   lglprt (lgl, 1, "[reduce-cache] new limit %d", lgl->limits->reduce.inner);
6931   if (lgl->clone) lglreducecache (lgl->clone);
6932 }
6933
6934 #ifndef NLGLPICOSA
6935 static void lglpicosatrestart (LGL *);
6936 #endif
6937
6938 static void lgliflushcache (LGL * lgl, int keep) {
6939   int idx, sign, lit, blit, tag, red, * w, * q, lidx, glue;
6940   int bin, trn, lrg, start;
6941   const int * p, * eow;
6942   HTS * hts;
6943   assert (1 <= keep), assert (keep <= 4);
6944   if (lgl->level) lglbacktrack (lgl, 0);
6945   bin = trn = lrg = 0;
6946   for (idx = 2; idx < lgl->nvars; idx++) {
6947     for (sign = -1; sign <= 1; sign += 2) {
6948       lit = sign * idx;
6949       hts = lglhts (lgl, lit);
6950       w = lglhts2wchs (lgl, hts);
6951       eow = w + hts->count;
6952       q = w;
6953       for (p = q; p < eow; p++) {
6954         blit = *p;
6955         tag = blit & MASKCS;
6956         if (tag == TRNCS || tag == LRGCS) p++;
6957         red = blit & REDCS;
6958         if (red) {
6959           if (tag == BINCS) {
6960             if (keep < 2) continue;
6961           } else if (tag == TRNCS) {
6962             if (keep < 3) continue;
6963           } else {
6964             assert (tag == LRGCS);
6965             if (keep < 4) continue;
6966             lidx = *p;
6967             glue = lidx & GLUEMASK;
6968             if (glue > 0) continue;
6969           }
6970         }
6971         *q++ = blit;
6972         if (tag == TRNCS || tag == LRGCS) *q++ = *p;
6973       }
6974       lglshrinkhts (lgl, hts, q - w);
6975     }
6976   }
6977   if (keep < 2) bin = lgl->stats->red.bin, lgl->stats->red.bin = 0;
6978   if (keep < 3) trn = lgl->stats->red.trn, lgl->stats->red.trn = 0;
6979   start = (keep >= 4);
6980   for (glue = start; glue < MAXGLUE; glue++) {
6981     lrg += lgl->stats->lir[glue].clauses;
6982     lgl->stats->lir[glue].clauses = 0;
6983   }
6984   assert (lrg <= lgl->stats->red.lrg), lgl->stats->red.lrg -= lrg;
6985   lglrelstk (lgl, &lgl->learned);
6986   for (glue = start; glue < MAXGLUE; glue++)
6987     lglrelstk (lgl, lgl->red + glue);
6988   lglprt (lgl, 1,
6989     "[flush-cache] %d binary, %d ternary, %d large",
6990     bin, trn, lrg);
6991 #ifndef NLGLPICOSA
6992   lglpicosatrestart (lgl);
6993 #endif
6994 }
6995
6996 void lglflushcache (LGL * lgl) {
6997   REQINITNOTFORKED ();
6998   TRAPI ("flush");
6999   if (lgl->mt) return;
7000   lgl->limits->reduce.inner = lgl->opts->redlinit.val;
7001   lglboundredl (lgl);
7002   lgliflushcache (lgl, 1);
7003   lgl->limits->reduce.inner = lgl->opts->redlinit.val;
7004   lglboundredl (lgl);
7005   lgl->limits->reduce.outer = 2*lgl->limits->reduce.inner;
7006   lglprt (lgl, 1, "[flush-cache] new limit %d", lgl->limits->reduce.inner);
7007   if (lgl->clone) lglflushcache (lgl->clone);
7008 }
7009
7010
7011 static void lglrmbwch (LGL * lgl, int lit, int other, int red) {
7012   int * p, blit, blit1, * w, * eow, tag;
7013   HTS * hts;
7014   assert (!red || red == REDCS);
7015   LOG (3, "removing %s binary watch %d blit %d",
7016        lglred2str (red), lit, other);
7017   hts = lglhts (lgl, lit);
7018   assert (hts->count >= 1);
7019   p = w = lglhts2wchs (lgl, hts);
7020   eow = w + hts->count;
7021   lglrminc (lgl, w, eow);
7022   blit1 = (other << RMSHFT) | red | BINCS;
7023   for (;;) {
7024     assert (p < eow);
7025     blit = *p++;
7026     tag = blit & MASKCS;
7027     if (tag == TRNCS || tag == LRGCS) { p++; continue; }
7028     if (tag == OCCS) { assert (lgl->dense); continue; }
7029     assert (tag == BINCS);
7030     if (blit == blit1) break;
7031   }
7032   while (p < eow) p[-1] = p[0], p++;
7033   lglshrinkhts (lgl, hts, p - w - 1);
7034 }
7035
7036 static int lglpopesched (LGL * lgl) {
7037   Stk * s = &lgl->esched;
7038   int res, last, cnt, * p;
7039   EVar * ev;
7040   assert (!lglmtstk (s));
7041   res = *s->start;
7042   assert (!lglifrozen (lgl, res));
7043   LOGESCHED (4, res, "popped");
7044   ev = lglevar (lgl, res);
7045   assert (!ev->pos);
7046   ev->pos = -1;
7047   last = lglpopstk (s);
7048   cnt = lglcntstk (s);
7049   if (!cnt) { assert (last == res); return res; }
7050   p = lglepos (lgl, last);
7051   assert (*p == cnt);
7052   *p = 0;
7053   *s->start = last;
7054   lgledown (lgl, last);
7055   return res;
7056 }
7057
7058 static void lgldecocc (LGL * lgl, int lit) {
7059   int idx, sign, change;
7060   EVar * ev;
7061   if (!lgl->occs) return;
7062   idx = abs (lit), sign = (lit < 0);
7063   ev = lglevar (lgl, lit);
7064   assert (ev->occ[sign] > 0);
7065   ev->occ[sign] -= 1;
7066   if (!lglisfree (lgl, lit)) return;
7067   change = lglecalc (lgl, ev);
7068   LOG (3, "dec occ of %d now occs[%d] = %d %d",
7069        lit, idx,  ev->occ[0], ev->occ[1]);
7070   if (ev->pos < 0) lglesched (lgl, idx);
7071   else if (change < 0) lgleup (lgl, idx);
7072   else if (change > 0) lgledown (lgl, idx);
7073 }
7074
7075 static void lglrmbcls (LGL * lgl, int a, int b, int red) {
7076   lglrmbwch (lgl, a, b, red);
7077   lglrmbwch (lgl, b, a, red);
7078   LOG (2, "removed %s binary clause %d %d", lglred2str (red), a, b);
7079   lgldeclscnt (lgl, 2, red, 0);
7080   if (!red && lgl->dense) lgldecocc (lgl, a), lgldecocc (lgl, b);
7081 }
7082
7083 static void lglrmtcls (LGL * lgl, int a, int b, int c, int red) {
7084   lglrmtwch (lgl, a, b, c, red);
7085   lglrmtwch (lgl, b, a, c, red);
7086   lglrmtwch (lgl, c, a, b, red);
7087   LOG (2, "removed %s ternary clause %d %d %d", lglred2str (red), a, b, c);
7088   lgldeclscnt (lgl, 3, red, 0);
7089   if (!red && lgl->dense)
7090     lgldecocc (lgl, a), lgldecocc (lgl, b), lgldecocc (lgl, c);
7091 }
7092
7093 static void lgltrimlitstk (LGL * lgl, int red, int lidx) {
7094   Stk * s = lglidx2stk (lgl, red, lidx);
7095   int * p = s->top;
7096   while (p > s->start && p[-1] == REMOVED)
7097     p--;
7098   if (p < s->top) {
7099     int64_t trimmed = s->top - p;
7100 #ifndef NLGLOG
7101     if (red) LOG (4, "trimmed 'red[%d]' by %lld", (LGLL) trimmed);
7102     else LOG (4, "trimmed 'irr' by %lld", (LGLL) trimmed);
7103 #endif
7104     lgl->stats->trims += trimmed;
7105     s->top = p;
7106     if (red) {
7107       int glue = (lidx & GLUEMASK), maxlidx;
7108       assert (s == &lgl->red[glue]);
7109       maxlidx = (lglcntstk (s) << GLUESHFT) | glue;
7110       for (p = lgl->learned.start; p < lgl->learned.top; p += 3) {
7111         int olidx = *p, oglue = (olidx & GLUEMASK);
7112         if (oglue == glue && olidx >= maxlidx) *p = INT_MIN;
7113       }
7114     }
7115   }
7116 }
7117
7118 static void lglrmlcls (LGL * lgl, int lidx, int red) {
7119   int * c, * p, glue, lit;
7120   assert (!red || red == REDCS);
7121   glue = red ? (lidx & GLUEMASK) : 0;
7122   c = lglidx2lits (lgl, red, lidx);
7123   if (!red || glue < MAXGLUE) {
7124     lglrmlwch (lgl, c[0], red, lidx);
7125     lglrmlwch (lgl, c[1], red, lidx);
7126   }
7127   if (!red && lgl->dense) {
7128     for (p = c; (lit = *p); p++) {
7129       lglrmlocc (lgl, lit, red, lidx);
7130       lgldecocc (lgl, lit);
7131     }
7132   }
7133   if (red && glue < MAXGLUE) { LGLCHKACT (c[-1]); c[-1] = REMOVED; }
7134   for (p = c; *p; p++) *p = REMOVED;
7135   *p = REMOVED;
7136   if (glue != MAXGLUE) lgldeclscnt (lgl, p - c, red, glue);
7137   lgltrimlitstk (lgl, red, lidx);
7138 }
7139
7140 static void lgldynsub (LGL * lgl, int lit, int r0, int r1) {
7141   int red, tag;
7142   tag = r0 & MASKCS;
7143   LOGREASON (2, lit, r0, r1, "removing on-the-fly subsumed");
7144   red = r0 & REDCS;
7145   if (red) lgl->stats->otfs.sub.dyn.red++;
7146   else lgl->stats->otfs.sub.dyn.irr++;
7147   if (tag == BINCS) lglrmbcls (lgl, lit, (r0>>RMSHFT), red);
7148   else if (tag == TRNCS) lglrmtcls (lgl, lit, (r0>>RMSHFT), r1, red);
7149   else { assert (tag == LRGCS); lglrmlcls (lgl, r1, red); }
7150 }
7151
7152 static void lglunflict (LGL * lgl, int lit) {
7153   lgl->conf.lit = lit;
7154   lgl->conf.rsn[0] = (lit << RMSHFT) | UNITCS;
7155   LOG (1, "inconsistent unary clause %d", lit);
7156 }
7157
7158 static void lgldynstr (LGL * lgl, int del, int lit, int r0, int r1) {
7159   int * p, * c, lidx, other, red, tag, glue, other2, other3, blit;
7160   tag = r0 & MASKCS;
7161   LOGREASON (2, lit, r0, r1,
7162     "on-the-fly strengthening by removing %d from", del);
7163   red = r0 & REDCS;
7164   if (red) lgl->stats->otfs.str.dyn.red++;
7165   else lgl->stats->otfs.str.dyn.irr++;
7166   lgl->stats->prgss++;
7167   if (!red) lgl->stats->irrprgss++;
7168   if (tag == BINCS) {
7169     other = (del == lit) ? (r0 >> RMSHFT) : lit;
7170     assert (other != del);
7171     lglrmbcls (lgl, del, other, red);
7172     if (lgl->opts->drup.val) lgldrupclsarg (lgl, other, 0);
7173 #ifndef NLGLPICOSAT
7174     lglpicosatchkclsarg (lgl, other, 0);
7175 #endif
7176     lglunflict (lgl, other);
7177     return;
7178   }
7179   if (tag == TRNCS) {
7180     if (lit == del) other = (r0 >> RMSHFT), other2 = r1;
7181     else if (del == r1) other = lit, other2 = (r0 >> RMSHFT);
7182     else other = lit, other2 = r1;
7183     assert (del != other && del != other2);
7184     lglrmtcls (lgl, del, other, other2, red);
7185     if (lgl->opts->drup.val) lgldrupclsarg (lgl, other, other2, 0);
7186 #ifndef NLGLPICOSAT
7187     lglpicosatchkclsarg (lgl, other, other2, 0);
7188 #endif
7189     if (!red) lglincirr (lgl, 2);
7190     else lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
7191     lglwchbin (lgl, other, other2, red);
7192     lglwchbin (lgl, other2, other, red);
7193     if (lglevel (lgl, other) < lglevel (lgl, other2)) SWAP (int, other, other2);
7194     blit = (other2 << RMSHFT) | BINCS | red;
7195     lglbonflict (lgl, other, blit);
7196     return;
7197   }
7198   assert (tag == LRGCS);
7199   lidx = r1;
7200   glue = red ? (lidx & GLUEMASK) : 0;
7201   c = lglidx2lits (lgl, red, lidx);
7202   for (p = c; *p != del; p++)
7203     assert (*p);
7204   if (glue < MAXGLUE) {
7205     lglrmlwch (lgl, c[0], red, lidx);
7206     lglrmlwch (lgl, c[1], red, lidx);
7207   }
7208   while ((other = *++p)) p[-1] = other;
7209   p[-1] = 0, *p = REMOVED;
7210   lgltrimlitstk (lgl, red, lidx);
7211   if (!red) assert (lgl->stats->irr.lits.cur), lgl->stats->irr.lits.cur--;
7212   lglorderclsaux (lgl, c + 0);
7213   lglorderclsaux (lgl, c + 1);
7214   if (lgl->opts->drup.val) lgldrupclsaux (lgl, c);
7215 #ifndef NLGLPICOSAT
7216   lglpicosatchkclsaux (lgl, c);
7217 #endif
7218   assert (p - c > 3);
7219   if (p - c == 4) {
7220     assert (!c[3] && c[4] >= NOTALIT);
7221     other = c[0], other2 = c[1], other3 = c[2];
7222     if (red && glue < MAXGLUE) { LGLCHKACT (c[-1]); c[-1] = REMOVED; }
7223     c[0] = c[1] = c[2] = c[3] = REMOVED;
7224     lgltrimlitstk (lgl, red, lidx);
7225     if (lglevel (lgl, other2) < lglevel (lgl, other3))
7226       SWAP (int, other2, other3);
7227     if (lglevel (lgl, other) < lglevel (lgl, other2))
7228       SWAP (int, other, other2);
7229     lglwchtrn (lgl, other, other2, other3, red);
7230     lglwchtrn (lgl, other2, other, other3, red);
7231     lglwchtrn (lgl, other3, other, other2, red);
7232     if (red) {
7233       if (glue < MAXGLUE) {
7234         assert (lgl->stats->red.lrg > 0);
7235         lgl->stats->red.lrg--;
7236         assert (lgl->stats->lir[glue].clauses > 0);
7237         lgl->stats->lir[glue].clauses--;
7238       }
7239       lgl->stats->red.trn++;
7240       assert (lgl->stats->red.trn > 0);
7241     }
7242     lgltonflict (lgl, other, (other2 << RMSHFT) | red | TRNCS, other3);
7243   } else {
7244     if (glue < MAXGLUE) {
7245       LOG (3, "new head literal %d", c[0]);
7246       (void) lglwchlrg (lgl, c[0], c[1], red, lidx);
7247       LOG (3, "new tail literal %d", c[1]);
7248       (void) lglwchlrg (lgl, c[1], c[0], red, lidx);
7249     }
7250     lglonflict (lgl, 0, c[0], red, lidx);
7251   }
7252 }
7253
7254 static void lglclnframes (LGL * lgl) {
7255   while (!lglmtstk (&lgl->frames))
7256     lglunuselevel (lgl, lglpopstk (&lgl->frames));
7257 }
7258
7259 static void lglclnpoisoned (LGL * lgl) {
7260   while (!lglmtstk (&lgl->poisoned)) {
7261     int lit = lglpopstk (&lgl->poisoned);
7262     AVar * av = lglavar (lgl, lit);
7263     assert (!av->mark);
7264     assert (av->poisoned);
7265     av->poisoned = 0;
7266   }
7267 }
7268
7269 static void lglclnana (LGL * lgl) {
7270 #ifdef RESOLVENT
7271   if (lglmaintainresolvent  (lgl)) lglclnstk (&lgl->resolvent);
7272 #endif
7273   lglclnstk (&lgl->clause);
7274   lglpopnunmarkstk (lgl, &lgl->seen);
7275   lglclnframes (lgl);
7276 }
7277
7278 static void lglbumplit (LGL * lgl, int lit) {
7279   int idx = abs (lit), mightneedtorescore = 0;
7280   QVar * qv = lglqvar (lgl, idx);
7281   Scr oldscore, newscore;
7282   oldscore = qv->score;
7283   switch (lgl->opts->score.val) {
7284     default:
7285     case 0:
7286       newscore = 0;
7287       break;
7288     case 6:
7289       assert (lgl->opts->score.val == LGL_SCORE_VSIDS256);
7290     case 1:
7291       newscore = oldscore + 1;
7292       LOG (0,
7293         "incrementing score of variable %d from %lld to %lld",
7294         idx, (LGLL) oldscore, (LGLL) newscore);
7295       break;
7296     case 2:
7297       newscore = lgl->stats->confs;
7298       LOG (0,
7299         "setting last conflict of variable %d from %lld to %lld",
7300         idx, (LGLL) oldscore, (LGLL) newscore);
7301       break;
7302     case 3:
7303       newscore = oldscore + lgl->stats->confs;
7304       LOG (0,
7305         "changing sum of conflict counts of variable %d from %lld to %lld",
7306         idx, (LGLL) oldscore, (LGLL) newscore);
7307       mightneedtorescore = 1;
7308       break;
7309     case 4:
7310       assert (lgl->opts->score.val == LGL_SCORE_AVG);
7311 #ifdef NDBLSCR
7312       newscore = lglflt (0, (uint64_t) (lgl->stats->confs + 1));
7313       newscore = lgladdflt (oldscore, newscore);
7314       newscore = lglshflt (newscore, 1);
7315 #else
7316       newscore = (oldscore + lgl->stats->confs)/2.0;
7317 #endif
7318       assert (newscore > oldscore);
7319       LOG (3,
7320         "averaging of %d from %s to %s after %lld conflicts",
7321         idx, lglscr2str (lgl, oldscore), lglscr2str (lgl, newscore),
7322         (LGLL) lgl->stats->confs);
7323       break;
7324     case 5:
7325       assert (lgl->opts->score.val == LGL_SCORE_EVSIDS);
7326       newscore = lgladdscr (oldscore, lgl->scinc);
7327       LOG (3,
7328         "bumping EVSIDS score of variable %d from %s to %s",
7329         idx, lglscr2str (lgl, oldscore), lglscr2str (lgl, newscore));
7330       assert (newscore > oldscore);
7331       mightneedtorescore = 1;
7332       break;
7333   }
7334   qv->score = newscore;
7335   if (lgldscheduled (lgl, idx)) lgldup (lgl, idx);
7336   if (mightneedtorescore && newscore >= lgl->maxscore) lglrescorevars (lgl);
7337 }
7338
7339 static void lglbumpseenlits (LGL * lgl) {
7340   const int * p;
7341   if (!lgl->opts->bumpseenlits.val) return;
7342   lglstart (lgl, &lgl->times->bump);
7343   for (p = lgl->seen.start; p < lgl->seen.top; p++) lglbumplit (lgl, *p);
7344   lglstop (lgl);
7345 }
7346
7347 static void lglbumpclslits (LGL * lgl) {
7348   const int * p;
7349   int lit;
7350   lglstart (lgl, &lgl->times->bump);
7351   p = lgl->clause.start;
7352   while ((lit = *p++)) lglbumplit (lgl, lit);
7353   lglstop (lgl);
7354 }
7355
7356 static void lglmincls (LGL * lgl, int uip, int glue) {
7357   int origsize = lglcntstk (&lgl->clause) - 1;
7358   int * p, * q, other, minimized, local;
7359   if (!lgl->opts->minimize.val) return;
7360   if (glue > lgl->opts->minlocalgluelim.val) return;
7361   lglstart (lgl, &lgl->times->mcls);
7362   q = lgl->clause.start;
7363   minimized = 0;
7364   local = lgl->opts->minimize.val <= 1 || glue > lgl->opts->minrecgluelim.val;
7365   assert (lglmtstk (&lgl->poisoned));
7366   for (p = q; (other = *p); p++)
7367     if (other != uip && lglminclslit (lgl, other, local)) {
7368       LOG (2, "removed %d", other);
7369       minimized++;
7370     } else *q++ = other;
7371   *q++ = 0;
7372   lglclnpoisoned (lgl);
7373   assert (lgl->clause.top - q == minimized);
7374   COVER (glue + 1 >= origsize && minimized > 0);        // unreachable ...
7375   LOG (2, "clause minimized by %d literals", minimized);
7376   LOGCLS (2, lgl->clause.start, "minimized clause");
7377   lgl->clause.top = q;
7378   lglstop (lgl);
7379 }
7380
7381 static void lgliassume (LGL * lgl, int lit) {
7382   lgl->level++;
7383   lglpushcontrol (lgl, lit);
7384   assert (lglcntctk (&lgl->control) == lgl->level + 1);
7385   LOG (2, "internally assuming %d", lit);
7386   lglassign (lgl, lit, DECISION, 0);
7387 }
7388
7389 static void lgldassume (LGL * lgl, int lit) {
7390   LOG (1, "next assumed decision %d external %d", lit, lglexport (lgl, lit));
7391   lgl->stats->decisions++;
7392   lgl->stats->height += lgl->level;
7393   lgliassume (lgl, lit);
7394   assert (lgldecision (lgl, lit));
7395 }
7396
7397 void lgldeco2 (LGL * lgl) {
7398   int next, level, lit, tag, r0, r1, other, count;
7399   const int * p, * rsn;
7400   AVar * av;
7401   assert (lgl->opts->deco.val == 2);
7402   assert (lglmtstk (&lgl->clause));
7403   for (p = lgl->seen.start; p < lgl->seen.top; p++)
7404     lglavar (lgl, *p)->mark = 0;
7405   next = 0;
7406   count = lglcntstk (&lgl->seen);
7407   LOG (2, "starting only-decision clause analysis after seeing %d", count);
7408   while (next < lglcntstk (&lgl->seen)) {
7409     lit = lglpeek (&lgl->seen, next++);
7410     level = lglevel (lgl, lit);
7411     if (!level || level == lgl->level) continue;
7412     av = lglavar (lgl, lit);
7413     if (av->mark) continue;
7414     av->mark = 1;
7415     if (lgldecision (lgl, lit)) lglpushstk (lgl, &lgl->clause, lit);
7416     else {
7417       rsn = lglrsn (lgl, lit);
7418       r0 = rsn[0], r1 = rsn[1];
7419       tag = r0 & MASKCS;
7420       if (tag == BINCS || tag == TRNCS) {
7421         other = r0 >> RMSHFT;
7422         lglpushstk (lgl, &lgl->seen, other);
7423         if (tag == TRNCS) lglpushstk (lgl, &lgl->seen, r1);
7424       } else {
7425         assert (tag == LRGCS);
7426         p = lglidx2lits (lgl, (r0 & REDCS), r1);
7427         while ((other = *p++))
7428           if (other != -lit)
7429             lglpushstk (lgl, &lgl->seen, other);
7430       }
7431     }
7432   }
7433   assert (next >= count);
7434   LOG (2, "saw %d more in only-decision clause analysis", next - count);
7435   while (lglcntstk (&lgl->seen) > count)
7436     lglavar (lgl, lglpopstk (&lgl->seen))->mark = 0;
7437 }
7438
7439 void lgldeco1 (LGL * lgl, int jlevel) {
7440   Ctr * p;
7441   int lit;
7442   assert (lgl->opts->deco.val == 1);
7443   assert (lglmtstk (&lgl->clause));
7444   for (p = lgl->control.start + 1; p <= lgl->control.start + jlevel; p++) {
7445     assert (p < lgl->control.top);
7446     lit = -p->decision;
7447     assert (lgldecision (lgl, lit));
7448     assert (lglevel (lgl, lit));
7449     assert (lglevel (lgl, lit) <= jlevel);
7450     lglpushstk (lgl, &lgl->clause, lit);
7451   }
7452 }
7453
7454 void lgldeco (LGL * lgl, int jlevel) {
7455   assert (lgl->opts->deco.val);
7456   if (lgl->opts->deco.val == 1) lgldeco1 (lgl, jlevel);
7457   else lgldeco2 (lgl);
7458 }
7459
7460 #define SCL 2
7461
7462 static int lglsubl (LGL * lgl, int lidx, int size, int glue) {
7463   const int * c, * p;
7464   int count, lit;
7465   assert (lidx);
7466   assert ((lidx & GLUEMASK) < MAXGLUE);
7467   c = lglidx2lits (lgl, REDCS, lidx);
7468   count = 0;
7469   for (p = c; count < size && (lit = *p); p++) {
7470     if (lit == REMOVED) return 1;
7471     if (lglmarked (lgl, lit) > 0) count++;
7472   }
7473   lgl->stats->subl.tried++;
7474   if (count < size) {
7475     LOGCLS (4, c, "only %d literals shared in clause", count);
7476     return 0;
7477   }
7478   LOGCLS (2, c,
7479     "subsuming learned scaled glue %d clause",
7480     (int)(lidx & GLUEMASK));
7481   LOGCLS (2, lgl->clause.start,
7482     "subsumed by new size %d scaled glue %d clause",
7483     size, lglscaleglue (lgl, glue));
7484   lgl->stats->subl.sub++;
7485   lglrmlcls (lgl, lidx, REDCS);
7486   return 1;
7487 }
7488
7489 static int lglana (LGL * lgl) {
7490   int open, resolved, tag, lit, uip, r0, r1, other, other2, * p, * q, lidx;
7491   int size, savedsize, resolventsize, level, red, glue, realglue;
7492   int jlevel, mlevel, nmlevel, origsize, redsize;
7493   int del, cl, c0, c1, sl, s0, s1;
7494   int len, * rsn;
7495   int64_t cpi;
7496   int delay;
7497 #ifdef RESOLVENT
7498   AVar * av;
7499 #endif
7500   if (lgl->mt) return 0;
7501   if (lgl->failed) return 0;
7502   if (!lgl->conf.lit) return 1;
7503   if (!lgl->level) {
7504     if (lgl->opts->drup.val) lgldrupclsarg (lgl, 0);
7505 #ifndef NLGLPICOSAT
7506     lglpicosatchkclsarg (lgl, 0);
7507 #endif
7508     lgl->mt = 1;
7509     return 0;
7510   }
7511   if (lgl->flipping) {
7512     assert (lgl->flipping > 0);
7513     if (lgl->flipping == 1) LOG (1, "switching off phase flipping");
7514     lgl->flipping--;
7515   }
7516   if (lgl->phaseneg) {
7517     assert (lgl->phaseneg > 0);
7518     if (lgl->phaseneg == 1) LOG (1, "switching off initial negative phase");
7519     lgl->phaseneg--;
7520   }
7521   lglstart (lgl, &lgl->times->ana);
7522   lgl->stats->confs++;
7523 RESTART:
7524   assert (lgl->conf.lit);
7525   assert (lglmtstk (&lgl->seen));
7526   assert (lglmtstk (&lgl->clause));
7527   assert (lglmtstk (&lgl->resolvent));
7528 #ifndef NDEBUG
7529   if (lgl->opts->check.val > 0) lglchkclnvar (lgl);
7530 #endif
7531   open = 0;
7532   lit = lgl->conf.lit, r0 = lgl->conf.rsn[0], r1 = lgl->conf.rsn[1];
7533   savedsize = resolved = 0;
7534   open += lglpull (lgl, lit);
7535   LOG (2, "starting analysis with reason of literal %d", lit);
7536   for (;;) {
7537     LOGREASON (2, lit, r0, r1, "analyzing");
7538     if (resolved++) {
7539 #ifdef RESOLVENT
7540       if (lglmaintainresolvent (lgl)) {
7541         LOG (2, "removing %d from resolvent", -lit);
7542         lglrmstk (&lgl->resolvent, -lit);
7543         LOGRESOLVENT (3, "resolvent after removing %d is", -lit);
7544       }
7545 #endif
7546     }
7547     assert (lglevel (lgl, lit) == lgl->level);
7548     tag = r0 & MASKCS;
7549     if (tag == BINCS || tag == TRNCS) {
7550       other = r0 >> RMSHFT;
7551       size = lglevel (lgl, other) ? 2 : 1;
7552       if (lglpull (lgl, other)) open++;
7553       if (tag == TRNCS) {
7554         if (lglevel (lgl, r1)) size++;
7555         if (lglpull (lgl, r1)) open++;
7556       }
7557     } else {
7558       assert (tag == LRGCS);
7559       red = r0 & REDCS;
7560       p = lglidx2lits (lgl, red, r1);
7561       size = 0;
7562       while ((other = *p++)) {
7563         if (lglevel (lgl, other)) size++;
7564         if (lglpull (lgl, other)) open++;
7565       }
7566       if (red) lglbumplidx (lgl, r1);
7567     }
7568     LOG (3, "open %d antecendents %d learned %d resolved %d",
7569          open-1, size, lglcntstk (&lgl->clause), lglcntstk (&lgl->resolvent));
7570     assert (open > 0);
7571     resolventsize = open + lglcntstk (&lgl->clause);
7572 #ifdef RESOLVENT
7573     LOGRESOLVENT (2, "resolvent");
7574     if (lglmaintainresolvent (lgl))
7575       assert (lglcntstk (&lgl->resolvent) == resolventsize);
7576 #endif
7577     if (lgl->opts->otfs.val &&
7578         (resolved >= 2) &&
7579         resolventsize > 1 &&
7580         (resolventsize < size || (resolved==2 && resolventsize<savedsize))) {
7581       cl = lgl->conf.lit;
7582       c0 = lgl->conf.rsn[0];
7583       c1 = lgl->conf.rsn[1];
7584       assert (resolved >= 2);
7585       del = lit;
7586       if (resolved > 2) ;
7587       else if (resolventsize >= size) del = -lit, lit = cl, r0 = c0, r1 = c1;
7588       else if (resolventsize >= savedsize) ;
7589       else {
7590         if (r0 & REDCS) {
7591           sl = lit, s0 = r0, s1 = r1;
7592           del = -lit, lit = cl, r0 = c0, r1 = c1;
7593         } else sl = cl, s0 = c0, s1 = c1;
7594         lgldynsub (lgl, sl, s0, s1);
7595       }
7596       lgldynstr (lgl, del, lit, r0, r1);
7597       lit = lgl->conf.lit;
7598       r0 = lgl->conf.rsn[0];
7599       r1 = lgl->conf.rsn[1];
7600       assert (lglevel (lgl, lit) == lgl->level);
7601       tag = r0 & MASKCS;
7602       if (tag == UNITCS) {
7603         mlevel = lglevel (lgl, lit);
7604         nmlevel = 1;
7605         jlevel = 0;
7606       } else if (tag == BINCS) {
7607         jlevel = lglevel (lgl, lit);
7608         other = r0 >> RMSHFT;
7609         mlevel = lglevel (lgl, other);
7610         if (jlevel > mlevel) { nmlevel = 1; SWAP (int, mlevel, jlevel); }
7611         else if (jlevel == mlevel) nmlevel = 2;
7612         else assert (jlevel < mlevel), nmlevel = 1;
7613       } else if (tag== TRNCS) {
7614         jlevel = lglevel (lgl, lit);
7615         other = r0 >> RMSHFT;
7616         level = lglevel (lgl, other);
7617         other2 = r1;
7618         mlevel = lglevel (lgl, other2);
7619         if (jlevel > mlevel) SWAP (int, jlevel, mlevel);
7620         if (level > mlevel) SWAP (int, level, mlevel);
7621         if (level > jlevel) SWAP (int, level, jlevel);
7622         assert (mlevel >= jlevel);
7623         assert (jlevel >= level);
7624         if (mlevel == jlevel) nmlevel = 2 + (jlevel == level);
7625         else assert (mlevel > jlevel), nmlevel = 1;
7626         assert (nmlevel == 1 + (mlevel == jlevel) + (mlevel == level));
7627       } else {
7628         mlevel = lglevel (lgl, lit), nmlevel = 1, jlevel = 0;
7629         assert (tag == LRGCS);
7630         red = r0 & REDCS;
7631         p = lglidx2lits (lgl, red, r1);
7632         while (jlevel < lgl->level && (other = *p++)) {
7633           if (other == lit) continue;
7634           assert (other != -lit);
7635           level = lglevel (lgl, other);
7636           if (level < mlevel) {
7637             if (level > jlevel) jlevel = level;
7638             continue;
7639           }
7640           if (level == mlevel) nmlevel++;
7641           else {
7642             assert (level > mlevel);
7643             jlevel = mlevel;
7644             mlevel = level;
7645             nmlevel = 1;
7646           }
7647         }
7648         if (red) lglbumplidx (lgl, r1);
7649       }
7650       if (nmlevel >= 2) {
7651         LOG (2, "restarting analysis after on-the-fly strengthening");
7652         lgl->stats->otfs.restarting++;
7653         if (lgl->opts->otfsbump.val >= 1)
7654           lglbumpseenlits (lgl), lglbumpscinc (lgl);
7655         lglclnana (lgl);
7656         if (lgl->level > mlevel) lglbacktrack (lgl, mlevel);
7657         if (lgl->opts->otfsconf.val) lgl->stats->confs++;
7658         goto RESTART;
7659       }
7660       assert (nmlevel == 1);
7661       assert (mlevel > jlevel);
7662       assert (lglevel (lgl, lit) == mlevel);
7663       LOGREASON (2, lit, r0, r1,
7664         "driving %d at level %d through strengthened", lit, jlevel);
7665       lgl->stats->otfs.driving++;
7666       lglbacktrack (lgl, jlevel);
7667       if (tag == LRGCS && (r0 & REDCS) && (r1 & GLUEMASK) == MAXGLUE) {
7668         // Note, that 'lit' is unassigned by 'backtrack' above and thus if
7669         // it's reason is at the end of the MAXGLUE stack, then the reason
7670         // becomes invalid.  See the corresponding 'assert' in 'lglassign'.
7671         // Our original incorrect fix to this problem was to simply increase
7672         // the size of the stack to point after the zero sentinel, which
7673         // however produces garbage on the MAXGLUE stack and thus we only
7674         // follow this idea if the reason of 'lit' is exactly after the
7675         // current end of the MAXGLUE stack. If it starts before the end
7676         // nothing has to be done.  Otherwise we have to move the reason
7677         // literals and update the reason.
7678         p = lglidx2lits (lgl, REDCS, r1);
7679         if (p > lgl->red[MAXGLUE].top) {
7680           int * q;
7681           rsn = lglrsn (lgl, lit);
7682           r1 = lglcntstk (&lgl->red[MAXGLUE]);
7683           r1 <<= GLUESHFT;
7684           r1 |= MAXGLUE;
7685           rsn[1] = r1;
7686           for (q = lgl->red[MAXGLUE].top; *p; p++) {
7687             assert (q < p);
7688             *q++ = *p;
7689           }
7690           *q++ = 0;
7691           lgl->red[MAXGLUE].top = q;
7692         } else if (p == lgl->red[MAXGLUE].top) {
7693           while (*p) { assert (*p < NOTALIT); p++; }
7694           if (++p > lgl->red[MAXGLUE].top) lgl->red[MAXGLUE].top = p;
7695         }
7696       }
7697       lglassign (lgl, lit, r0, r1);
7698       if (lgl->opts->otfsbump.val >= 2) 
7699         lglbumpseenlits (lgl), lglbumpscinc (lgl);
7700       len = INT_MAX;
7701       goto DONE;
7702     }
7703     savedsize = size;
7704     while (!lglmarked (lgl, lit = lglpopstk (&lgl->trail))) {
7705       if (lgl->opts->bumpbcplits.val) lglbumplit (lgl, lit);
7706       lglunassign (lgl, lit);
7707     }
7708     lglunassign (lgl, lit);
7709     if (!--open) { uip = -lit; break; }
7710     LOG (2, "analyzing reason of literal %d next", lit);
7711     rsn = lglrsn (lgl, lit);
7712     r0 = rsn[0], r1 = rsn[1];
7713   }
7714   assert (uip);
7715   LOG (2, "adding UIP %d at same level %d to 1st UIP clause",
7716        uip, lgl->level);
7717   lglpushstk (lgl, &lgl->clause, uip);
7718   assert (lglmarked (lgl, uip));
7719 #ifdef RESOLVENT
7720   LOGRESOLVENT (3, "final resolvent before flushing fixed literals");
7721   if (lglmaintainresolvent  (lgl)) {
7722     int * q = lgl->resolvent.start;
7723     for (p = q; p < lgl->resolvent.top; p++)
7724       if (lglevel (lgl, (other = *p)))
7725         *q++ = other;
7726     lgl->resolvent.top = q;
7727     LOGRESOLVENT (2, "final resolvent after flushing fixed literals");
7728     assert (lglcntstk (&lgl->resolvent) == lglcntstk (&lgl->clause));
7729     for (p = lgl->clause.start; p < lgl->clause.top; p++)
7730       assert (lglavar (lgl, *p)->mark > 0);
7731     for (p = lgl->resolvent.start; p < lgl->resolvent.top; p++) {
7732       av = lglavar (lgl, *p); assert (av->mark > 0); av->mark = -av->mark;
7733     }
7734     for (p = lgl->clause.start; p < lgl->clause.top; p++)
7735       assert (lglavar (lgl, *p)->mark < 0);
7736     for (p = lgl->resolvent.start; p < lgl->resolvent.top; p++) {
7737       av = lglavar (lgl, *p); assert (av->mark < 0); av->mark = -av->mark;
7738     }
7739     lglclnstk (&lgl->resolvent);
7740   }
7741 #endif
7742   lglpushstk (lgl, &lgl->clause, 0);
7743   LOGCLS (2, lgl->clause.start, "1st UIP clause");
7744   if (lgl->opts->drup.val) lgldrupcls (lgl);
7745 #ifndef NLGLPICOSAT
7746   lglpicosatchkcls (lgl);
7747 #endif
7748
7749   mlevel = lgl->level;
7750   jlevel = glue = realglue = 0;
7751   for (p = lgl->frames.start; p < lgl->frames.top; p++) {
7752     level = *p;
7753     assert (0 < level && level < lgl->level);
7754     if (level < mlevel) mlevel = level;
7755     if (level > jlevel) jlevel = level;
7756     if (level >= lgl->alevel) realglue++;
7757     glue++;
7758   }
7759   assert (realglue <= glue);
7760   assert (glue == lglcntstk (&lgl->frames));
7761   LOG (2, "jump level %d", jlevel);
7762   LOG (2, "minimum level %d", mlevel);
7763   LOG (2, "glue %d covers %.0f%%", glue,
7764        (float)(jlevel ? lglpcnt (glue, (jlevel - mlevel) + 1) : 100.0));
7765
7766   if (lglrsn (lgl, uip)[0]) lgl->stats->uips++;
7767   else if (jlevel + 1 == lgl->level) lgl->stats->decflipped++;
7768
7769   origsize = lglcntstk (&lgl->clause) - 1;
7770   assert (glue + 1 <= origsize);
7771   if (origsize >= lgl->opts->bumpseenminsize.val &&
7772       lgl->opts->bumpseenbeforemin.val) lglbumpseenlits (lgl);
7773   lgl->stats->lits.nonmin += origsize;
7774   redsize = jlevel + 1;
7775   if (origsize == 2) {
7776     lgl->stats->mincls.bin++;
7777     LOGCLS (2, lgl->clause.start, "binary 1st UIP clause not minimized");
7778   } else if (glue + 1 == origsize) {
7779     lgl->stats->mincls.size++;
7780     LOGCLS (2, lgl->clause.start,
7781       "size %d 1st UIP clause with glue %d can not minimized",
7782       origsize, glue);
7783   } else if (jlevel > 1 &&
7784       lgl->opts->deco.val &&
7785       redsize < 2*origsize/3 &&
7786       glue > lgl->opts->decolim.val) {
7787     assert (origsize > 2);
7788     lgl->stats->mincls.deco++;
7789     lgl->stats->deco.sum.orig += origsize;
7790     lglclnstk (&lgl->clause);
7791     lgldeco (lgl, jlevel);
7792     glue = lglcntstk (&lgl->clause);
7793     lglpushstk (lgl, &lgl->clause, uip);
7794     lgl->stats->deco.sum.red += lglcntstk (&lgl->clause);
7795     lglpushstk (lgl, &lgl->clause, 0);
7796     LOGCLS (2, lgl->clause.start,
7797       "size %d 1st UIP clause discarded for size %d decision-only clause",
7798       origsize, redsize);
7799   } else {
7800     lgl->stats->mincls.min++;
7801     lglmincls (lgl, uip, glue);
7802   }
7803
7804   if (origsize >= lgl->opts->bumpseenminsize.val &&
7805       lgl->opts->bumpseenaftermin.val) lglbumpseenlits (lgl);
7806   if (origsize < lgl->opts->bumpseenminsize.val ||
7807       lgl->opts->bumpclslits.val) lglbumpclslits (lgl);
7808
7809   lglbumpscinc (lgl);
7810   lglbacktrack (lgl, jlevel);
7811
7812   len = lglcntstk (&lgl->clause) - 1;
7813   lgl->stats->clauses.glue += glue;
7814   lgl->stats->clauses.realglue += realglue;
7815   lgl->stats->lits.learned += len;
7816   lgl->stats->clauses.learned++;
7817   lgl->stats->glues.count++;
7818   lgl->stats->glues.sum += glue;
7819   if (lgl->opts->drup.val) lgldrupcls (lgl);
7820 #ifndef NLGLPICOSAT
7821   lglpicosatchkcls (lgl);
7822 #endif
7823   lgldrupligaddcls (lgl, REDCS);
7824   lidx = lgladdcls (lgl, REDCS, realglue, 1);
7825
7826   if (lgl->opts->subl.val) {
7827     lgl->stats->subl.count++;
7828     lglpopnunmarkstk (lgl, &lgl->seen);
7829     size = lglcntstk (&lgl->clause) - 1;
7830     if (size > 1) {
7831       unsigned sig = 0;
7832       p = lgl->clause.start;
7833       while ((lit = *p++)) {
7834         sig |= (1u << (lglulit (lit) & 31));
7835         lglmark (lgl, lit);
7836       }
7837       q = lgl->learned.start;
7838       for (p = q; p < lgl->learned.top; p += 3) {
7839         int olidx = p[0], osize = p[1];
7840         unsigned osig = (unsigned) p[2];
7841         if (olidx < 0) continue;
7842         if (osize <= size ||
7843             (sig & ~osig) ||
7844             !lglsubl (lgl, olidx, size, glue))
7845           *q++ = olidx, *q++ = osize, *q++ = (int) osig;
7846       }
7847       lgl->learned.top = q;
7848       if (lidx && (lidx & GLUEMASK) < MAXGLUE) {
7849         lgl->stats->subl.cands++;
7850         lglpushstk (lgl, &lgl->learned, lidx);
7851         lglpushstk (lgl, &lgl->learned, size);
7852         lglpushstk (lgl, &lgl->learned, (int) sig);
7853         if (lglcntstk (&lgl->learned) / 3 > lgl->opts->subl.val) {
7854           q = lgl->learned.start;
7855           for (p = q + 3; p < lgl->learned.top; p++) *q++ = *p;
7856           lgl->learned.top = q;
7857         }
7858       } 
7859       p = lgl->clause.start;
7860       while ((lit = *p++)) lglunmark (lgl, lit);
7861     }
7862   }
7863
7864   if (lgl->cbs &&
7865       lgl->cbs->cls.produce.fun &&
7866       glue <= lgl->opts->synclsglue.val &&
7867       lglcntstk (&lgl->clause) - 1 <= lgl->opts->synclslen.val) {
7868     assert (lglmtstk (&lgl->eclause));
7869     for (p = lgl->clause.start; *p; p++)
7870       lglpushstk (lgl, &lgl->eclause, lglexport (lgl, *p));
7871     lglpushstk (lgl, &lgl->eclause, 0);
7872     LOGCLS (SCL, lgl->eclause.start,
7873       "exporting external redundant glue %d length %d clause", 
7874       glue, lglcntstk (&lgl->clause) -1);
7875     lgl->stats->sync.cls.produced++;
7876     lgl->cbs->cls.produce.fun (lgl->cbs->cls.produce.state,
7877                                lgl->eclause.start, glue);
7878     lglclnstk (&lgl->eclause);
7879   }
7880
7881 DONE:
7882
7883   if (!lgl->simp)  {
7884
7885     cpi = lgl->stats->confs / (1 + lgl->stats->iterations);
7886
7887     if (len == 2) {
7888       if ((delay = lgl->opts->binsimpdel.val)) {
7889         if (cpi/2 < (int64_t) delay) delay = (int) cpi/2;
7890         lgl->limits->simp.confs += delay;
7891       }
7892       if ((delay = lgl->opts->binlocsdel.val)) {
7893         if (cpi/2 < (int64_t) delay) delay = (int) cpi/2;
7894         lgl->limits->locs.confs += delay;
7895       }
7896       lglrep (lgl, 2, 'b');
7897     }
7898
7899     if (!lgl->level) {
7900       if ((delay = lgl->opts->itsimpdel.val)) {
7901         if (cpi/2 < (int64_t) delay) delay = (int) cpi/2;
7902         lgl->limits->simp.confs += delay;
7903       }
7904       if ((delay = lgl->opts->itlocsdel.val)) {
7905         if (cpi/2 < (int64_t) delay) delay = (int) cpi/2;
7906         lgl->limits->locs.confs += delay;
7907       }
7908       lgl->stats->iterations++;
7909       lglrep (lgl, 1, 'i');
7910     }
7911   }
7912
7913   lglclnana (lgl);
7914   lglstop (lgl);
7915
7916   return 1;
7917 }
7918
7919 static int lglscalerestartint (LGL * lgl, int delta) {
7920   int64_t res = delta;
7921   if (lgl->opts->restartintscale.val > 0) {
7922     res *= lgl->stats->decisions + 1;
7923     res /= lgl->stats->confs + 1;
7924   } else if (lgl->opts->restartintscale.val < 0) {
7925     res *= lgl->stats->confs + 1;
7926     res /= lgl->stats->decisions + 1;
7927   }
7928   if (res <= 1) res = 1;
7929   lgl->stats->restarts.intsum.orig += delta;
7930   lgl->stats->restarts.intsum.scaled += res;
7931   return res;
7932 }
7933
7934 static void lglincrestartlfixed (LGL * lgl) {
7935   int delta = lgl->opts->restartint.val;
7936   delta = lglscalerestartint (lgl, delta);
7937   lgl->limits->restart.confs = lgl->stats->confs + delta;
7938   lglrep (lgl, 1, 'R');
7939 }
7940
7941 static void lglincrestartaux (LGL * lgl, int skip) {
7942   int delta = lgl->opts->restartint.val, count;
7943   if (lgl->opts->restart.val == 2) {
7944     count = ++lgl->limits->restart.luby;
7945     delta *= lgluby (lgl, count);
7946   } else {
7947     assert (lgl->opts->restart.val == 3);
7948     count = ++lgl->limits->restart.inout;
7949     delta *= lglinout (lgl, count, lgl->opts->rstinoutinc.val);
7950   }
7951   delta = lglscalerestartint (lgl, delta);
7952   lgl->limits->restart.confs = lgl->stats->confs + delta;
7953   if (lgl->limits->restart.wasmaxdelta)
7954     lglrep (lgl, 1 + skip, skip ? 'N' : 'R');
7955   else lglrep (lgl, 2, skip ? 'n' : 'r');
7956   if (delta > lgl->limits->restart.maxdelta) {
7957     lgl->limits->restart.wasmaxdelta = 1;
7958     lgl->limits->restart.maxdelta = delta;
7959   } else lgl->limits->restart.wasmaxdelta = 0;
7960 }
7961
7962 static void lglincrestartl (LGL * lgl, int skip) {
7963   switch (lgl->opts->restart.val) {
7964     case 1: lglincrestartlfixed (lgl); break;
7965     case 2: case 3: lglincrestartaux (lgl, skip); break;
7966     default: break;
7967   }
7968 }
7969
7970 static int lglnextdecision (LGL * lgl) {
7971   int res = 0;
7972   if (!lgl->unassigned) return 0;
7973   lglstart (lgl, &lgl->times->dec);
7974   while (!res && !lglmtstk (&lgl->dsched)) {
7975     int next = lgltopdsched (lgl);
7976     if (!lglval (lgl, next) && lglisfree (lgl, next)) res = next;
7977     else lglpopdsched (lgl);
7978   }
7979   LOG (2, "next decision would be %d", res);
7980   lglstop (lgl);
7981   return res;
7982 }
7983
7984 static int lglreusetrail (LGL * lgl) {
7985   int next = 0, res = 0, prev, level;
7986   const Ctr * p;
7987   assert (lgl->opts->reusetrail.val);
7988   if (lgl->flipping) {
7989     lgl->flipping = 0;
7990     lglprt (lgl, 2, 
7991       "[reuse-trail] no reuse after forced termination of flipping");
7992     return lgl->alevel;
7993   }
7994   if (!(next = lglnextdecision (lgl))) return 0;
7995   for (p = lgl->control.start + 1; p < lgl->control.top; p++) {
7996     prev = p->decision;
7997     assert (lgldecision (lgl, prev));
7998     if (!lglassumption (lgl, prev) && lgldcmp (lgl, prev, next) < 0) break;
7999     level = lglevel (lgl, prev);
8000     assert (level == p - lgl->control.start);
8001     assert (res + 1 == level);
8002     res = level;
8003   }
8004   if (res)
8005     lglprt (lgl, 2,
8006     "[reuse-trail] reusing level %d from current level %d", res, lgl->level);
8007   else
8008     lglprt (lgl, 2, "[reuse-trail] can not reuse any level");
8009   return res;
8010 }
8011
8012 static void lglrestart (LGL * lgl) {
8013   int skip, level;
8014   int64_t kept;
8015   assert (lgl->opts->restart.val);
8016   lglstart (lgl, &lgl->times->rsts);
8017   if (lglagile (lgl))
8018     lgl->stats->restarts.skipped.agile++, skip = 1;
8019   else if (lglsaturating (lgl))
8020     lgl->stats->restarts.skipped.saturating++, skip = 1;
8021   else skip = 0;
8022   if (skip) {
8023     lgl->stats->restarts.skipped.count++;
8024     LOG (1, "skipping restart with agility %.0f%%", lglagility (lgl));
8025   } else {
8026     LOG (1, "restarting with agility %.0f%% not saturating",
8027       lglagility (lgl));
8028     if (!lgl->opts->reusetrail.val ||
8029         lgl->opts->restart.val <= 1 ||
8030         lgl->opts->phasegluebit.val) level = 0;
8031     else level = lglreusetrail (lgl);
8032     if (level < lgl->alevel) level = lgl->alevel;
8033     else if (level > lgl->alevel) {
8034       kept = (100*level) / lgl->level;
8035       lgl->stats->restarts.kept.sum += kept;
8036       lgl->stats->restarts.kept.count++;
8037     }
8038     if (level < lgl->level) {
8039       lglbacktrack (lgl, level);
8040       lgl->stats->restarts.count++;
8041     } else {
8042       lgl->stats->restarts.skipped.count++;
8043       lgl->stats->restarts.skipped.reuse++;
8044     }
8045   }
8046   lglincrestartl (lgl, skip);
8047   lglstop (lgl);
8048 }
8049
8050 static void lgldefrag (LGL * lgl) {
8051   int * wchs, nwchs, i, idx, bit, ldsize, size, offset, * start, * q, * end;
8052   const int * p, * eow, * w;
8053   HTS * hts;
8054   lglstart (lgl, &lgl->times->dfg);
8055   lgl->stats->defrags++;
8056   nwchs = lglcntstk (&lgl->wchs->stk);
8057   NEW (wchs, nwchs);
8058   memcpy (wchs, lgl->wchs->stk.start, nwchs * sizeof *wchs);
8059   for (i = 0; i < MAXLDFW; i++) lgl->wchs->start[i] = INT_MAX;
8060   lgl->wchs->free = 0;
8061   start = lgl->wchs->stk.start;
8062   assert (nwchs >= 1);
8063   assert (start[0] == INT_MAX);
8064   offset = 1;
8065   for (idx = 2; idx < lgl->nvars; idx++)
8066   for (bit = 0; bit <= 1; bit++) {
8067     hts = lgl->dvars[idx].hts + bit;
8068     if (!hts->offset) { assert (!hts->count); continue; }
8069     ldsize = lglceilld (hts->count);
8070     size = (1 << ldsize);
8071     assert (size >= hts->count);
8072     w = wchs + hts->offset;
8073     hts->offset = offset;
8074     eow = w + hts->count;
8075     q = start + offset;
8076     for (p = w; p < eow; p++) *q++ = *p;
8077     offset += size;
8078     end = start + offset;
8079     while (q < end) *q++ = 0;
8080   }
8081   DEL (wchs, nwchs);
8082   q = start + offset;
8083   *q++ = INT_MAX;
8084   assert (q <= lgl->wchs->stk.top);
8085   lgl->wchs->stk.top = q;
8086   lglfitstk (lgl, &lgl->wchs->stk);
8087   lgl->limits->dfg = lgl->stats->pshwchs + lgl->opts->defragint.val;
8088   lglrep (lgl, 2, 'F');
8089   lglstop (lgl);
8090 }
8091
8092 static void lgldis (LGL * lgl) {
8093   int blit, nblit, tag, red, * p, * q, * eow, * w;
8094   int idx, sign, lit, other, other2;
8095   Stk bins, trns;
8096   Val val, val2;
8097   HTS * hts;
8098   assert (!lgl->level);
8099   CLR (bins); CLR (trns);
8100   for (idx = 2; idx < lgl->nvars; idx++)
8101     for (sign = -1; sign <= 1; sign += 2) {
8102       lit = idx * sign;
8103       hts = lglhts (lgl, lit);
8104       if (!hts->offset) continue;
8105       val = lglval (lgl, lit);
8106       assert (hts->count > 0);
8107       if (val || lgliselim (lgl, lit))
8108         { lglshrinkhts (lgl, hts, 0); continue; }
8109       assert (lglisfree (lgl, lit));
8110       assert (lglmtstk (&bins));
8111       assert (lglmtstk (&trns));
8112       w = lglhts2wchs (lgl, hts);
8113       eow = w + hts->count;
8114       for (p = w; p < eow; p++) {
8115         blit = *p;
8116         tag = blit & MASKCS;
8117         red = blit & REDCS;
8118         if (tag == OCCS) continue;
8119         if (tag == TRNCS || tag == LRGCS) p++;
8120         if (tag == LRGCS) continue;
8121         other = blit >> RMSHFT;
8122         val = lglval (lgl, other);
8123         if (val > 0) continue;
8124         if (lgliselim (lgl, other)) continue;
8125         if (tag == BINCS) {
8126           assert (!val);
8127           lglpushstk (lgl, &bins, blit);
8128           continue;
8129         }
8130         assert (tag == TRNCS);
8131         other2 = *p;
8132         val2 = lglval (lgl, other2);
8133         if (val2 > 0) continue;
8134         if (lgliselim (lgl, other2)) continue;
8135         if (val < 0) {
8136           assert (val < 0 && !val2);
8137           nblit = red | (other2<<RMSHFT) | BINCS;
8138           lglpushstk (lgl, &bins, nblit);
8139           continue;
8140         }
8141         if (val2 < 0) {
8142           assert (!val && val2 < 0);
8143           nblit = red | (other<<RMSHFT) | BINCS;
8144           lglpushstk (lgl, &bins, nblit);
8145           continue;
8146         }
8147         assert (!val && !val2);
8148         lglpushstk (lgl, &trns, blit);
8149         lglpushstk (lgl, &trns, other2);
8150       }
8151       q = w;
8152       for (p = bins.start; p != bins.top; p++) *q++ = *p;
8153       for (p = trns.start; p != trns.top; p++) *q++ = *p;
8154       lglshrinkhts (lgl, hts, q - w);
8155       lglclnstk (&bins);
8156       lglclnstk (&trns);
8157     }
8158   lglrelstk (lgl, &bins);
8159   lglrelstk (lgl, &trns);
8160   lglrelstk (lgl, &lgl->learned);
8161 }
8162
8163 static int lglcmphase (LGL * lgl, int a, int b) {
8164   return lgliphase (lgl, b) - lgliphase (lgl, a);
8165 }
8166
8167 #define LGLCMPHASE(A,B) lglcmphase (lgl, *(A), *(B))
8168
8169 static void lglconnaux (LGL * lgl, int glue) {
8170   int lit, satisfied, lidx, size, red, act;
8171   const int * p, * c, * start, * top;
8172   int * q, * d;
8173   Stk * stk;
8174   Val val;
8175   if (glue >= 0) {
8176     assert (glue < MAXGLUE);
8177     red = REDCS;
8178     stk = lgl->red + glue;
8179   } else red = 0, stk = &lgl->irr;
8180   c = start = q = stk->start;
8181   top = stk->top;
8182   while (c < top) {
8183     act = *c;
8184     if (act == REMOVED) {
8185       for (p = c + 1; p < top && *p == REMOVED; p++)
8186         ;
8187       assert (p >= top || *p < NOTALIT || lglisact (*p));
8188       c = p;
8189       continue;
8190     }
8191     if (lglisact (act)) *q++ = *c++; else act = -1;
8192     p = c;
8193     d = q;
8194     satisfied = 0;
8195     while (assert (p < top), (lit = *p++)) {
8196       assert (lit < NOTALIT);
8197       if (satisfied) continue;
8198       val = lglval (lgl, lit);
8199       if (lgliselim (lgl, lit))  {
8200         assert (lgl->eliminating || lgl->blocking);
8201         satisfied = 1;
8202       } else if (val > 0) satisfied = 1;
8203       else if (!val) *q++ = lit;
8204     }
8205     if (satisfied || p == c + 1) {
8206       q = d - (act >= 0);
8207     } else if (!(size = q - d)) {
8208       q = d - (act >= 0);
8209       if (!lgl->mt) {
8210         LOG (1, "empty clause during connection garbage collection phase");
8211         lgl->mt = 1;
8212       }
8213     } else if (size == 1) {
8214       q = d - (act >= 0);
8215       LOG (1, "unit during garbage collection");
8216       lglunit (lgl, d[0]);
8217     } else if (size == 2) {
8218       q = d - (act >= 0);
8219       lglwchbin (lgl, d[0], d[1], red);
8220       lglwchbin (lgl, d[1], d[0], red);
8221     } else if (size == 3) {
8222       q = d - (act >= 0);
8223       lglwchtrn (lgl, d[0], d[1], d[2], red);
8224       lglwchtrn (lgl, d[1], d[0], d[2], red);
8225       lglwchtrn (lgl, d[2], d[0], d[1], red);
8226     } else {
8227       assert (size > 3);
8228       if (lgl->opts->sortlits.val) SORT (int, d, size, LGLCMPHASE);
8229       *q++ = 0;
8230       lidx = d - start;
8231       if (red) {
8232         assert (lidx <= MAXREDLIDX);
8233         lidx <<= GLUESHFT;
8234         assert (0 <= lidx);
8235         lidx |= glue;
8236       }
8237       (void) lglwchlrg (lgl, d[0], d[1], red, lidx);
8238       (void) lglwchlrg (lgl, d[1], d[0], red, lidx);
8239     }
8240     c = p;
8241   }
8242   stk->top = q;
8243 }
8244
8245 static void lglfullyconnected (LGL * lgl) {
8246   if (!lgl->notfullyconnected) return;
8247   LOG (1, "switching to fully connected mode");
8248   lgl->notfullyconnected  = 0;
8249 }
8250
8251 static void lglcon (LGL * lgl) {
8252   int glue;
8253   for (glue = -1; glue < MAXGLUE; glue++) lglconnaux (lgl, glue);
8254   lglfullyconnected (lgl);
8255 }
8256
8257 static void lglcount (LGL * lgl) {
8258   int idx, sign, lit, tag, blit, red, other, other2, glue, count;
8259   const int * p, * w, * c, * eow;
8260   HTS * hts;
8261   Stk * lir;
8262   lgl->stats->irr.clauses.cur = 0;
8263   lgl->stats->irr.lits.cur = 0;
8264   lgl->stats->red.bin = 0;
8265   lgl->stats->red.trn = 0;
8266   lgl->stats->red.lrg = 0;
8267   for (idx = 2; idx < lgl->nvars; idx++)
8268     for (sign = -1; sign <= 1; sign += 2) {
8269       lit = sign * idx;
8270       hts = lglhts (lgl, lit);
8271       if (!hts->offset) continue;
8272       w = lglhts2wchs (lgl, hts);
8273       eow = w + hts->count;
8274       for (p = w; p < eow; p++) {
8275         blit = *p;
8276         red = blit & REDCS;
8277         tag = blit & MASKCS;
8278         if (tag == LRGCS || tag == TRNCS) p++;
8279         if (tag == LRGCS) continue;
8280         assert (tag == BINCS || tag == TRNCS);
8281         other = blit >> RMSHFT;
8282         assert (abs (other) != abs (lit));
8283         if (abs (lit) >= abs (other)) continue;
8284         assert (2 == BINCS && 3 == TRNCS);
8285         if (tag == TRNCS) {
8286           other2 = *p;
8287           assert (abs (other2) != abs (lit));
8288           assert (abs (other2) != abs (other));
8289           if (abs (lit) >= abs (other2)) continue;
8290         }
8291         if (!red) {
8292           lgl->stats->irr.clauses.cur++;
8293           if (tag == BINCS) lgl->stats->irr.lits.cur += 2;
8294           else assert (tag == TRNCS), lgl->stats->irr.lits.cur += 3;
8295         } else if (tag == BINCS) lgl->stats->red.bin++;
8296         else assert (tag == TRNCS), lgl->stats->red.trn++;
8297       }
8298     }
8299   assert (lgl->stats->red.bin >= 0 && lgl->stats->red.trn >= 0);
8300   for (c = lgl->irr.start; c < lgl->irr.top; c = p + 1) {
8301     if (*(p = c) >= REMOVED) continue;
8302     while (*p) p++;
8303     lgl->stats->irr.lits.cur += p - c;
8304     lgl->stats->irr.clauses.cur++;
8305   }
8306   LOG (1, "counted %d irredundant clauses with %d literals",
8307        lgl->stats->irr.clauses.cur, lgl->stats->irr.lits.cur);
8308   for (glue = 0; glue < MAXGLUE; glue++) {
8309     lir = lgl->red + glue;
8310     count = 0;
8311     for (c = lir->start; c < lir->top; c++)
8312       if (!*c) count++;
8313     if (count)
8314       LOG (1, "counted %d redundant clauses with glue %d", count, glue);
8315     lgl->stats->red.lrg += count;
8316     lgl->stats->lir[glue].clauses = count;
8317   }
8318   assert (lgl->stats->red.lrg >= 0);
8319   if (lgl->stats->red.bin)
8320     LOG (1, "counted %d binary redundant clauses altogether",
8321          lgl->stats->red.bin);
8322   if (lgl->stats->red.trn)
8323     LOG (1, "counted %d ternary redundant clauses altogether",
8324          lgl->stats->red.trn);
8325   if (lgl->stats->red.lrg)
8326     LOG (1, "counted %d large redundant clauses altogether",
8327          lgl->stats->red.lrg);
8328 }
8329
8330 static int lglilit (int ulit) {
8331   int res = ulit/2;
8332   assert (res >= 1);
8333   if (ulit & 1) res = -res;
8334   return res;
8335 }
8336
8337 static void lgljwh (LGL * lgl) {
8338   int idx, sign, lit, tag, blit, other, other2, red, size, glue;
8339   const int *p, * w, * eow, * c;
8340   Val val, tmp, tmp2;
8341   HTS * hts;
8342   Stk * s;
8343   Flt inc;
8344   CLN (lgl->jwh, 2*lgl->nvars);
8345   for (idx = 2; idx < lgl->nvars; idx++)
8346     for (sign = -1; sign <= 1; sign += 2) {
8347       lit = sign * idx;
8348       val = lglval (lgl, lit);
8349       if (val > 0) continue;
8350       hts = lglhts (lgl, lit);
8351       if (!hts->offset) continue;
8352       w = lglhts2wchs (lgl, hts);
8353       eow = w + hts->count;
8354       for (p = w; p < eow; p++) {
8355         blit = *p;
8356         tag = blit & MASKCS;
8357         if (tag == TRNCS || tag == LRGCS) p++;
8358         if (tag == LRGCS) continue;
8359         red = blit & REDCS;
8360         if (!lgl->opts->jwhred.val && red) continue;
8361         other = blit >> RMSHFT;
8362         if (abs (other) < abs (lit)) continue;
8363         tmp = lglval (lgl, other);
8364         if (tmp > 0) continue;
8365         if (tag == BINCS) {
8366           assert (!tmp);
8367           inc = lglflt (-2, 1);
8368           lglincjwh (lgl, lit, inc);
8369           lglincjwh (lgl, other, inc);
8370         } else {
8371           assert (tag == TRNCS);
8372           other2 = *p;
8373           if (abs (other2) < abs (lit)) continue;
8374           tmp2 = lglval (lgl, other2);
8375           if (tmp2 > 0) continue;
8376           assert ((val > 0) + (tmp > 0) + (tmp2 > 0) == 0);
8377           assert ((val < 0) + (tmp < 0) + (tmp2 < 0) <= 1);
8378           size = 3 + val + tmp + tmp2;
8379           assert (2 <= size && size <= 3);
8380           inc = lglflt (-size, 1);
8381           if (!val) lglincjwh (lgl, lit, inc);
8382           if (!tmp) lglincjwh (lgl, other, inc);
8383           if (!tmp2) lglincjwh (lgl, other2, inc);
8384         }
8385       }
8386     }
8387   for (glue = -1; glue < MAXGLUE; glue++) {
8388     if (glue < 0) s = &lgl->irr;
8389     else if (!lgl->opts->jwhred.val) continue;
8390     else s = &lgl->red[glue];
8391     for (c = s->start; c < s->top; c = p + 1) {
8392       p = c;
8393       if (*p >= NOTALIT) continue;
8394       val = -1;
8395       size = 0;
8396       while ((other = *p)) {
8397         tmp = lglval (lgl, other);
8398         if (tmp > val) val = tmp;
8399         if (!tmp) size++;
8400         p++;
8401       }
8402       if (val > 0) continue;
8403       inc = lglflt (-size, 1);
8404       for (p = c; (other = *p); p++)
8405         if (!lglval (lgl, other))
8406           lglincjwh (lgl, other, inc);
8407     }
8408   }
8409 }
8410
8411 static int * lglis (LGL * lgl) {
8412   int idx, sign, lit, tag, blit, other, other2, red, * res;
8413   const int *p, * w, * eow, * c;
8414   Val val, tmp, tmp2;
8415   HTS * hts;
8416   Stk * s;
8417   NEW (res, 2*lgl->nvars);
8418   res += lgl->nvars;
8419   for (idx = 2; idx < lgl->nvars; idx++)
8420     for (sign = -1; sign <= 1; sign += 2) {
8421       lit = sign * idx;
8422       val = lglval (lgl, lit);
8423       if (val > 0) continue;
8424       hts = lglhts (lgl, lit);
8425       if (!hts->offset) continue;
8426       w = lglhts2wchs (lgl, hts);
8427       eow = w + hts->count;
8428       for (p = w; p < eow; p++) {
8429         blit = *p;
8430         tag = blit & MASKCS;
8431         if (tag == TRNCS || tag == LRGCS) p++;
8432         if (tag == LRGCS) continue;
8433         red = blit & REDCS;
8434         if (red) continue;
8435         other = blit >> RMSHFT;
8436         if (abs (other) < abs (lit)) continue;
8437         tmp = lglval (lgl, other);
8438         if (tmp > 0) continue;
8439         if (tag == BINCS) {
8440           assert (!tmp);
8441           res[lit]++,
8442           res[other]++;
8443         } else {
8444           assert (tag == TRNCS);
8445           other2 = *p;
8446           if (abs (other2) < abs (lit)) continue;
8447           tmp2 = lglval (lgl, other2);
8448           if (tmp2 > 0) continue;
8449           assert ((val > 0) + (tmp > 0) + (tmp2 > 0) == 0);
8450           assert ((val < 0) + (tmp < 0) + (tmp2 < 0) <= 1);
8451           if (!val) res[lit]++;
8452           if (!tmp) res[other]++;
8453           if (!tmp2) res[other2]++;
8454         }
8455       }
8456     }
8457   s = &lgl->irr;
8458   for (c = s->start; c < s->top; c = p + 1) {
8459     p = c;
8460     if (*p >= NOTALIT) continue;
8461     val = -1;
8462     while ((other = *p)) {
8463       tmp = lglval (lgl, other);
8464       if (tmp > val) val = tmp;
8465       p++;
8466     }
8467     if (val > 0) continue;
8468     for (p = c; (other = *p); p++)
8469       if (!lglval (lgl, other))
8470         res[other]++;
8471   }
8472   return res;
8473 }
8474
8475 static int lglsetjwhbias (LGL * lgl, int idx) {
8476   AVar * av = lglavar (lgl, idx);
8477   Flt pos, neg;
8478   int bias;
8479   idx = abs (idx);
8480   pos = lgl->jwh[lglulit (idx)];
8481   neg = lgl->jwh[lglulit (-idx)];
8482   if (av->phase) return av->phase;
8483   if (lgl->opts->phaseflip.val) SWAP (int, pos, neg);
8484   bias = (pos > neg) ? 1 : -1;
8485   if (av->bias == bias) return bias;
8486   av->bias = bias;
8487   lgl->stats->phase.set++;
8488   if (bias > 0) lgl->stats->phase.pos++; else lgl->stats->phase.neg++;
8489   LOG (1, "JW bias %d (pos %s, neg %s)", 
8490        bias * idx, lglflt2str (lgl, pos), lglflt2str (lgl, neg));
8491   return bias;
8492 }
8493
8494 static void lglsetallphases (LGL * lgl) {
8495   int res = 1, idx;
8496   for (idx = 2; res && idx < lgl->nvars; idx++)
8497     res = (!lglisfree (lgl, idx) || lglavar (lgl, idx)->phase);
8498   lgl->allphaseset = res;
8499 }
8500
8501 static void lglflushphasesaux (LGL * lgl, int full) {
8502   int idx, flushed = 0;
8503   AVar * av;
8504   for (idx = 2; idx < lgl->nvars; idx++) {
8505     if (!lglisfree (lgl, idx)) continue;
8506     av = lglavar (lgl, idx);
8507     if (!full && av->phase) continue;
8508     av->phase = 0;
8509     flushed++;
8510   }
8511   lglprt (lgl, 1,
8512     "[flushphases] %d phases reset%s", 
8513     flushed, (full ? " fully" : ""));
8514   lgl->allphaseset = !flushed;
8515   lgl->flushphases = 0;
8516 }
8517
8518 static void lglflushphases (LGL * lgl) {
8519   int full = (lgl->opts->rephase.val >= 2);
8520   lglflushphasesaux (lgl, full);
8521 }
8522
8523 static void lglphase (LGL * lgl) {
8524   int64_t set = lgl->stats->phase.set;
8525   int64_t pos = lgl->stats->phase.pos;
8526   int64_t neg = lgl->stats->phase.neg;
8527   int idx;
8528   lglstart (lgl, &lgl->times->phs);
8529   if (lgl->flushphases) lglflushphases (lgl);
8530   if (lgl->opts->phase.val) goto DONE;
8531   lglsetallphases (lgl);
8532   if (lgl->allphaseset) goto DONE;
8533   lgl->stats->phase.count++;
8534   lgljwh (lgl);
8535   for (idx = 2; idx < lgl->nvars; idx++) lglsetjwhbias (lgl, idx);
8536   set = lgl->stats->phase.set - set;
8537   pos = lgl->stats->phase.pos - pos;
8538   neg = lgl->stats->phase.neg - neg;
8539   lglprt (lgl, 1,
8540      "[phase-%d] phase bias: %lld positive %.0f%%, %lld negative %.0f%%",
8541      lgl->stats->phase.count,
8542      (LGLL) pos, lglpcnt (pos, set),
8543      (LGLL) neg, lglpcnt (neg, set));
8544 DONE:
8545   lglstop (lgl);
8546 }
8547
8548 static int lglrephasing (LGL * lgl) {
8549   if (!lgl->opts->rephase.val) return 0;
8550   if (lgl->stats->confs < lgl->limits->rephase.confs) return 0;
8551   return 1;
8552 }
8553
8554 static void lglrephase (LGL * lgl) {
8555   lgl->stats->rephase.count++;
8556   lgl->stats->rephase.inc *= 2;
8557   lgl->limits->rephase.confs = lgl->stats->confs + lgl->stats->rephase.inc;
8558   lglprt (lgl, 1,
8559      "[rephase-%d] after %lld conflicts (new increment %d, next %lld)",
8560      lgl->stats->rephase.count, (LGLL) lgl->stats->confs,
8561      lgl->stats->rephase.inc, (LGLL) lgl->limits->rephase.confs);
8562   lglflushphases (lgl);
8563 }
8564
8565 static void lglchkbcpclean (LGL * lgl, const char * where) {
8566   ASSERT (lgl->next2 == lgl->next && lgl->next == lglcntstk (&lgl->trail));
8567   ASSERT (!lgl->conf.lit);
8568   ASSERT (!lgl->mt);
8569 }
8570
8571 static void lglcutwidth (LGL * lgl) {
8572   int lidx, res, l4, r4, b4, l10, r10, b10, m, oldbias;
8573   int idx, sign, lit, blit, tag, red, other, other2;
8574   const int * p, * w, * eow, * c, * q;
8575   int * widths, max, cut, min4, min10;
8576   int64_t sum, avg;
8577   HTS * hts;
8578   if (lgl->nvars <= 2) return;
8579   lgl->stats->cutwidths++;
8580   lglstart (lgl, &lgl->times->ctw);
8581   oldbias = lgl->bias;
8582   assert (abs (oldbias) <= 1);
8583   if (abs (lgl->opts->bias.val) <= 1) {
8584     lgl->bias = lgl->opts->bias.val;
8585     goto DONE;
8586   }
8587   min4 = min10 = INT_MAX;
8588   sum = max = cut = 0;
8589   NEW (widths, lgl->nvars);
8590   l4 = 2 + (lgl->nvars - 2 + 3)/4;
8591   r4 = 2 + (3*(lgl->nvars - 2)+3)/4;
8592   assert (2 <= l4 && l4 <= r4 && r4 <= lgl->nvars);
8593   l10 = 2 + (lgl->nvars - 2 + 9)/10;
8594   r10 = 2 + (9*(lgl->nvars - 2)+9)/10;
8595   assert (2 <= l10 && l10 <= r10 && r10 <= lgl->nvars);
8596   b4 = b10 = 0;
8597   for (idx = 2; idx < lgl->nvars; idx++) {
8598     for (sign = -1; sign <= 1; sign += 2) {
8599       lit = idx * sign;
8600       hts = lglhts (lgl, lit);
8601       w = lglhts2wchs (lgl, hts);
8602       eow = w + hts->count;
8603       for (p = w; p < eow; p++) {
8604         blit = *p;
8605         red = blit & REDCS;
8606         tag = blit & MASKCS;
8607         other = abs (blit >> RMSHFT);
8608         if (tag == BINCS) {
8609           if (red) continue;
8610           if (other > idx) widths[other]++, cut++;
8611         } else if (tag == TRNCS) {
8612           other2 = abs (*++p);
8613           if (red) continue;
8614           if (other > idx) widths[other]++, cut++;
8615           if (other2 > idx) widths[other2]++, cut++;
8616         } else {
8617           assert (tag == LRGCS);
8618           lidx = *++p;
8619           if (red) continue;
8620           c = lglidx2lits (lgl, 0, lidx);
8621           for (q = c; (other = abs (*q)); q++) {
8622             if (other == idx) continue;
8623             if (other > idx) widths[other]++, cut++;
8624           }
8625         }
8626       }
8627     }
8628     assert (0 <= cut && 0 <= widths[idx]);
8629     cut -= widths[idx];
8630     assert (cut >= 0);
8631     if (cut > max) max = cut;
8632     if (l4 <= idx && idx <= r4 && cut < min4) b4 = idx, min4 = cut;
8633     if (l10 <= idx && idx <= r10 && cut < min10) b10 = idx, min10 = cut;
8634     sum += cut;
8635     assert (sum >= 0);
8636   }
8637   DEL (widths, lgl->nvars);
8638   assert (lgl->nvars > 0);
8639   avg = sum / (LGLL) lgl->nvars;
8640   assert (avg <= INT_MAX);
8641   res = (int) avg;
8642   lglprt (lgl, 1,
8643     "[cut-width] %d, max %d, min4 %d at %.0f%%, min10 %d at %.0f%%",
8644     res, max,
8645     min4, lglpcnt ((b4 - 2), lgl->nvars - 2),
8646     min10, lglpcnt ((b10 - 2), lgl->nvars - 2));
8647   m = (lgl->nvars + 2)/2;
8648   if (b4 < m && b10 < m) lgl->bias = -1;
8649   if (b4 > m && b10 > m) lgl->bias = 1;
8650   lglprt (lgl, 1, "[cut-width] cut-width based bias %d", lgl->bias);
8651 DONE:
8652   lgldreschedule (lgl);
8653   assert (abs (lgl->bias <= 1));
8654   lglprt (lgl, 1, "[decision-order] bias %d, old %d", lgl->bias, oldbias);
8655   lglstop (lgl);
8656 }
8657
8658 static int lglmaplit (int * map, int lit) {
8659   return map [ abs (lit) ] * lglsgn (lit);
8660 }
8661
8662 static void lglmapstk (LGL * lgl, int * map, Stk * lits) {
8663   int * p, * eol;
8664   eol = lits->top;
8665   for (p = lits->start; p < eol; p++)
8666     *p = lglmaplit (map, *p);
8667 }
8668
8669 static void lglmapglue (LGL * lgl, int * map, Stk * lits) {
8670   int * p, * eol;
8671   eol = lits->top;
8672   for (p = lits->start; p < eol; p++)
8673     if (!lglisact (*p)) *p = lglmaplit (map, *p);
8674 }
8675
8676 static void lglmaplits (LGL * lgl, int * map) {
8677   int glue;
8678   lglmapstk (lgl, map, &lgl->irr);
8679   for (glue = 0; glue < MAXGLUE; glue++)
8680     lglmapglue (lgl, map, &lgl->red[glue]);
8681 }
8682
8683 static void lglmapvars (LGL * lgl, int * map, int nvars) {
8684   int i, oldnvars = lgl->nvars, sign, udst, idst, usrc, isrc;
8685   DVar * dvars;
8686   QVar * qvars;
8687   AVar * avars;
8688   Val * vals;
8689   int * i2e;
8690   Flt * jwh;
8691
8692   if (nvars > 2) assert (nvars <= oldnvars);
8693   else nvars = 0;
8694
8695   DEL (lgl->doms, 2*lgl->szvars);
8696   NEW (lgl->doms, 2*nvars);
8697
8698   NEW (vals, nvars);
8699   for (i = 2; i < oldnvars; i++)
8700     if (lglisfree (lgl, i))
8701       vals[map[i]] = lgl->vals[i];
8702   DEL (lgl->vals, lgl->szvars);
8703   lgl->vals = vals;
8704
8705   NEW (i2e, nvars);
8706   for (i = 2; i < oldnvars; i++)
8707     if (lglisfree (lgl, i))
8708       i2e[map[i]] = lgl->i2e[i];
8709   DEL (lgl->i2e, lgl->szvars);
8710   lgl->i2e = i2e;
8711
8712   NEW (dvars, nvars);
8713   for (i = 2; i < oldnvars; i++)
8714     if (lglisfree (lgl, i))
8715       dvars[map[i]] = lgl->dvars[i];
8716   DEL (lgl->dvars, lgl->szvars);
8717   lgl->dvars = dvars;
8718
8719   NEW (qvars, nvars);
8720   for (i = 2; i < oldnvars; i++)
8721     if (lglisfree (lgl, i))
8722       qvars[map[i]] = lgl->qvars[i];
8723   DEL (lgl->qvars, lgl->szvars);
8724   lgl->qvars = qvars;
8725
8726   NEW (jwh, 2*nvars);
8727   for (i = 2; i < oldnvars; i++)
8728     if (lglisfree (lgl, i))
8729       for (sign = -1; sign <= 1; sign += 2) {
8730           isrc = sign * i;
8731           idst = sign * map[i];
8732           usrc = lglulit (isrc);
8733           udst = lglulit (idst);
8734           jwh[udst] = lgladdflt (jwh[udst], lgl->jwh[usrc]);
8735         }
8736   DEL (lgl->jwh, 2*lgl->szvars);
8737   lgl->jwh = jwh;
8738
8739   NEW (avars, nvars);           
8740   for (i = 2; i < oldnvars; i++)
8741     if (lglisfree (lgl, i))
8742       avars[map[i]] = lgl->avars[i];
8743   DEL (lgl->avars, lgl->szvars);
8744   lgl->avars = avars;              // Last since 'lglisfree' depends on it !!!
8745
8746   lgl->nvars = lgl->szvars = nvars;
8747   lgl->stats->fixed.current = 0;
8748 }
8749
8750 static void lglmaphts (LGL * lgl, int * map) {
8751   int idx, sign, lit, * w, *eow, * p, other, other2, blit, tag, red;
8752   int newblit, newother, newother2;
8753   HTS * hts;
8754   for (idx = 2; idx < lgl->nvars; idx++)
8755     for (sign = -1; sign <= 1; sign += 2) {
8756       lit = sign * idx;
8757       hts = lglhts (lgl, lit);
8758       if (!hts->count) continue;
8759       w = lglhts2wchs (lgl, hts);
8760       eow = w + hts->count;
8761       for (p = w; p < eow; p++) {
8762         blit = *p;
8763         tag = blit & MASKCS;
8764         assert (tag == BINCS || tag == TRNCS || tag == LRGCS);
8765         red = blit & REDCS;
8766         other = blit >> RMSHFT;
8767         newother = lglmaplit (map, other);
8768         newblit = (newother << RMSHFT) | tag | red;
8769         *p = newblit;
8770         if (tag == BINCS) continue;
8771         other2 = *++p;
8772         if (tag == LRGCS) continue;
8773         assert (tag == TRNCS);
8774         newother2 = lglmaplit (map, other2);
8775         *p = newother2;
8776       }
8777     }
8778 }
8779
8780 static void lglmaptrail (LGL * lgl, int * map) {
8781   int * p, * q, src, dst;
8782   for (p = lgl->trail.start; p < lgl->trail.top; p++)
8783     if (lglevel (lgl, *p) > 0) break;
8784   for (q = lgl->trail.start; p < lgl->trail.top; p++) {
8785     src = *p;
8786     assert (lglevel (lgl, src) > 0);
8787     dst = lglmaplit (map, src);
8788     *q++ = dst;
8789   }
8790   lgl->trail.top = q;
8791   lgl->flushed = lgl->next2 = lgl->next = lglcntstk (&lgl->trail);
8792 }
8793
8794 static int lglptrjmp (int * repr, int max, int start) {
8795 #ifndef NDEBUG
8796   int prev = 0, count = 0;
8797 #endif
8798   int next, idx, res, sgn, tmp;
8799   assert (repr);
8800   next = start;
8801   do {
8802     res = next;
8803     idx = abs (res);
8804     assert (idx <= max);
8805     sgn = lglsgn (res);
8806     next = repr[idx];
8807     next *= sgn;
8808 #ifndef NDEBUG
8809     if (prev || next) assert (prev != next);
8810     prev = res;
8811     assert (count <= max);
8812 #endif
8813   } while (next);
8814   tmp = start;
8815   while (tmp != res) {
8816     idx = abs (tmp), sgn = lglsgn (tmp);
8817     next = repr[idx] * sgn;
8818     repr[idx] = sgn * res;
8819     tmp = next;
8820   }
8821   return res;
8822 }
8823
8824 static int lglirepr (LGL * lgl, int lit) {
8825   assert (lgl->repr);
8826   return lglptrjmp (lgl->repr, lgl->nvars - 1, lit);
8827 }
8828
8829 static void lglmapext (LGL * lgl, int * map) {
8830   int eidx, ilit, mlit;
8831   Ext * ext;
8832   for (eidx = 1; eidx <= lgl->maxext; eidx++) (void) lglerepr (lgl, eidx);
8833   for (eidx = 1; eidx <= lgl->maxext; eidx++) {
8834     ext = lgl->ext + eidx;
8835     if (!ext->imported) continue;
8836     if (ext->equiv) {
8837       LOG (3, "mapping external %d to equivalent external %d",
8838            eidx, ext->repr);
8839       continue;
8840     }
8841     ilit = ext->repr;
8842     mlit = lglmaplit (map, ilit);
8843     LOG (3, "mapping external %d to internal %d", eidx, mlit);
8844     ext->repr = mlit;
8845   }
8846 }
8847
8848 static void lglmapdef (LGL * lgl, int * map) {
8849   int didx, mlit, recycle, recycled;
8850   Ext * ext;
8851   if (!lgl->maxdef) return;
8852   recycled = 0;
8853   for (didx = 1; didx <= lgl->maxdef; didx++) {
8854     ext = lgl->def + didx;
8855     assert (!ext->imported);
8856     assert (ext->defined);
8857     mlit = lglmaplit (map, ext->repr);
8858     if (ext->blocking) {
8859       LOG (3, "keeping definition %d since it was blocked", didx);
8860       recycle = 0;
8861     } else if (ext->eliminated) {
8862       LOG (3, "keeping definition %d since it was eliminated", didx);
8863       recycle = 0;
8864     } else if (ext->equiv) {
8865       LOG (3, "keeping definition %d since it was equivalent", didx);
8866       recycle = 1;
8867     } else {
8868       assert (ext->repr);
8869       if (abs (mlit) == 1) {
8870         LOG (3,
8871           "recycling definition %d since it is mapped to constant %d",
8872           didx, mlit);
8873         recycle = 1;
8874       } else recycle = 0;
8875     }
8876     if (recycle) recycled++;
8877     LOG (3, "definition %d mapped to internal %d", didx, mlit);
8878     ext->repr = mlit;
8879   }
8880   LOG (2, "could have recycled %d definitions", recycled);
8881 }
8882
8883 static void lglsignedmark (LGL * lgl, int lit) {
8884   AVar * av = lglavar (lgl, lit);
8885   int bit = 1 << (lit < 0);
8886   if (av->mark & bit) return;
8887   av->mark |= bit;
8888 }
8889
8890 static void lglsignedunmark (LGL * lgl, int lit) {
8891   AVar * av = lglavar (lgl, lit);
8892   int bit = 1 << (lit < 0);
8893   if (!(av->mark & bit)) return;
8894   av->mark &= ~bit;
8895 }
8896
8897 static int lglsignedmarked (LGL * lgl, int lit) {
8898   AVar * av = lglavar (lgl, lit);
8899   int bit = 1 << (lit < 0);
8900   return av->mark & bit;
8901 }
8902
8903 static void lglmapass (LGL * lgl, int * map) {
8904   int * p, * q, iass, mass, flushed;
8905   unsigned bit;
8906   AVar * av;
8907   if (abs (lgl->failed) != 1) lgl->failed = lglmaplit (map, lgl->failed);
8908   for (p = q = lgl->assume.start; p < lgl->assume.top; p++) {
8909     iass = *p;
8910     mass = lglmaplit (map, iass);
8911     if (mass == 1) continue;
8912     if (mass == -1) {
8913       if (lgl->failed != -1) {
8914 #ifndef NDEBUG
8915         int * r;
8916         for (r = lgl->eassume.start; r < lgl->eassume.top; r++)
8917           if (lglimport (lgl, *r) == -1) break;
8918         assert (r < lgl->eassume.top);
8919 #endif
8920         LOG (2, "enforcing a failed assumption");
8921         lgl->failed = -1;
8922       }
8923       continue;
8924     }
8925     LOG (2, "mapping previous internal assumption %d to %d", iass, mass);
8926     av = lglavar (lgl, mass);
8927     bit = 1u << (mass < 0);
8928     if (!(av->assumed & bit)) {
8929       LOG (2, "assuming new representative %d instead of %d", mass, iass);
8930       av->assumed |= bit;
8931     }
8932     *q++ = mass;
8933   }
8934   lgl->assume.top = q;
8935   flushed = 0;
8936   for (p = q = lgl->assume.start; p < lgl->assume.top; p++) {
8937     iass = *p;
8938     if (lglsignedmarked (lgl, iass)) { flushed++; continue; }
8939     lglsignedmark (lgl, iass);
8940     *q++ = iass;
8941   }
8942   lgl->assume.top = q;
8943   for (p = lgl->assume.start; p < lgl->assume.top; p++) {
8944     iass = *p;
8945     assert (lglsignedmarked (lgl, iass));
8946     lglsignedunmark (lgl, iass);
8947   }
8948   if (flushed)
8949     LOG (2, "flushed %d duplicated internal assumptions", flushed);
8950 }
8951
8952 #if !defined(NDEBUG) && !defined(NLGLPICOSAT)
8953 static void lglpicosataddstk (LGL * lgl, const Stk * stk) {
8954   const int * p;
8955   int lit;
8956   for (p = stk->start; p < stk->top; p++) {
8957     lit = *p;
8958     if (lit >= NOTALIT) continue;
8959     picosat_add (PICOSAT, lit);
8960   }
8961 }
8962
8963 static void lglpicosataddunits (LGL * lgl) {
8964   int idx, val;
8965   assert (!lgl->level);
8966   assert (lgl->picosat.solver);
8967   for (idx = 2; idx < lgl->nvars; idx++) {
8968     val = lglval (lgl, idx);
8969     if (!val) continue;
8970     picosat_add (PICOSAT, (val < 0) ? -idx : idx);
8971     picosat_add (PICOSAT, 0);
8972   }
8973 }
8974
8975 static void lglpicosataddhts (LGL * lgl) {
8976   int idx, sign, lit, tag, blit, other, other2;
8977   const int * w, * p, * eow;
8978   HTS * hts;
8979   assert (lgl->picosat.solver);
8980   for (idx = 2; idx < lgl->nvars; idx++)
8981     for (sign = -1; sign <= 1; sign += 2) {
8982       lit = sign * idx;
8983       hts = lglhts (lgl, lit);
8984       if (!hts->count) continue;
8985       w = lglhts2wchs (lgl, hts);
8986       eow = w + hts->count;
8987       for (p = w; p < eow; p++) {
8988         blit = *p;
8989         tag = blit & MASKCS;
8990         if (tag == BINCS) {
8991           other = blit >> RMSHFT;
8992           if (abs (other) < idx) continue;
8993           picosat_add (PICOSAT, lit);
8994           picosat_add (PICOSAT, other);
8995           picosat_add (PICOSAT, 0);
8996         } else if (tag == TRNCS) {
8997           other = blit >> RMSHFT;
8998           other2 = *++p;
8999           if (abs (other) < idx) continue;
9000           if (abs (other2) < idx) continue;
9001           picosat_add (PICOSAT, lit);
9002           picosat_add (PICOSAT, other);
9003           picosat_add (PICOSAT, other2);
9004           picosat_add (PICOSAT, 0);
9005         } else if (tag == LRGCS) p++;
9006         else assert (lgl->dense && tag == OCCS);
9007       }
9008     }
9009 }
9010 #endif
9011
9012 static void lglpicosatchkall (LGL * lgl) {
9013 #if !defined(NDEBUG) && !defined(NLGLPICOSAT)
9014   int res, * p;
9015   lglpicosatinit (lgl);
9016   if (lgl->opts->check.val >= 2) {
9017     for (p = lgl->eassume.start; p < lgl->eassume.top; p++)
9018       picosat_assume (PICOSAT, lglimport (lgl, *p));
9019     res = picosat_sat (PICOSAT, -1);
9020     LOG (1, "PicoSAT returns %d", res);
9021     if (lgl->picosat.res) assert (res == lgl->picosat.res);
9022     lgl->picosat.res = res;
9023   }
9024   if (picosat_inconsistent (PICOSAT)) {
9025     assert (!lgl->picosat.res || lgl->picosat.res == 20);
9026     lgl->picosat.res = 20;
9027   }
9028 #endif
9029 }
9030
9031 static void lglpicosatrestart (LGL * lgl) {
9032 #if !defined(NDEBUG) && !defined(NLGLPICOSAT)
9033   int glue;
9034   if (lgl->picosat.solver) {
9035     picosat_reset (lgl->picosat.solver);
9036     LOG (1, "PicoSAT reset");
9037     lgl->picosat.solver = 0;
9038   }
9039   lglpicosatinit (lgl);
9040   lglpicosataddunits (lgl);
9041   if (lgl->mt) picosat_add (PICOSAT, 0);
9042   lglpicosataddhts (lgl);
9043   lglpicosataddstk (lgl, &lgl->irr);
9044   for (glue = 0; glue < MAXGLUE; glue++)
9045     lglpicosataddstk (lgl, &lgl->red[glue]);
9046 #endif
9047 }
9048
9049 static void lglmaplkhdscore (LGL * lgl, int * map, int oldnvars) {
9050   LKHD * oldlkhdscore = lgl->tlk->lkhd, score;
9051   int idx, src, sign, dst;
9052   NEW (lgl->tlk->lkhd, 2*lgl->nvars);
9053   lgl->tlk->lkhd += lgl->nvars;
9054   for (idx = oldnvars-1; idx >= 2; idx--) {
9055     for (sign = -1; sign <= 1; sign += 2) {
9056       src = sign * idx;
9057       dst = lglmaplit (map, src);
9058       if (abs (dst) <= 1) continue;
9059       score = oldlkhdscore[src];
9060       LOG (2, "mapping look-ahead score %s of %d as score of %d",
9061            lglflt2str (lgl, score), src, dst);
9062       lgl->tlk->lkhd[dst] = score;
9063     }
9064   }
9065   oldlkhdscore -= oldnvars;
9066   DEL (oldlkhdscore, 2*oldnvars);
9067 }
9068
9069 static int lglmapsize (LGL * lgl) {
9070   int size = 0, idx;
9071   for (idx = 2; idx < lgl->nvars; idx++) 
9072     if (lglisfree (lgl, idx)) size++;
9073   LOG (1, "mapping %d remaining variables", size);
9074   return size;
9075 }
9076
9077 static void lglmapnonequiv (LGL * lgl, int * map, int size) {
9078   int count = 0, idx;
9079   AVar * av;
9080   Val val;
9081   map[0] = 0, map[1] = 1;
9082   for (idx = 2; idx < lgl->nvars; idx++) {
9083     if (map[idx]) continue;
9084     av = lglavar (lgl, idx);
9085     if (av->type == FREEVAR) {
9086       assert (idx > 0);
9087       if (map[idx]) { assert (map[idx] < idx); continue; }
9088       LOG (3, "mapping free %d to %d", idx, count + 2);
9089       map[idx] = count + 2;
9090       count++;
9091     } else if (av->type == EQUIVAR) {
9092       assert (lgl->repr);
9093       assert (!map[idx]);
9094     } else if (av->type == FIXEDVAR) {
9095       val = lgl->vals[idx];
9096       assert (val);
9097       LOG (3, "mapping assigned %d to %d", idx, (int) val);
9098       map[idx] = val;
9099     } else {
9100       assert (av->type == ELIMVAR);
9101       assert (!lglifrozen (lgl, idx));
9102       map[idx] = 0;
9103     }
9104   }
9105   assert (count == size);
9106 }
9107
9108 static void lglmapequiv (LGL * lgl, int * map) {
9109   int idx, repr, dst;
9110   AVar * av;
9111   for (idx = 2; idx < lgl->nvars; idx++) {
9112     if (map[idx]) continue;
9113     av = lglavar (lgl, idx);
9114     if (av->type == ELIMVAR) continue;
9115     assert (av->type == EQUIVAR);
9116     assert (lgl->repr);
9117     assert (!map[idx]);
9118     repr = lglirepr (lgl, idx);
9119     assert (repr != idx);
9120     assert (map[abs (repr)]);
9121     dst = lglmaplit (map, repr);
9122     LOG (3, "mapping equivalent %d to %d", idx, dst);
9123     map[idx] = dst;
9124   }
9125 }
9126
9127 typedef struct ForceData { int pos, count; double sum; } ForceData;
9128
9129 static void lglincfdat (ForceData * fdat, int lit, double cog) {
9130   int idx = abs (lit);
9131   fdat[idx].count++;
9132   fdat[idx].sum += cog;
9133 }
9134
9135 static int lglcmpfdat (ForceData * fdat, int l, int k) {
9136   ForceData * d, * e;
9137   l = abs (l);
9138   k = abs (k);
9139   d = fdat + l;
9140   e = fdat + k;
9141   if (d->sum < e->sum) return -1;
9142   if (d->sum > e->sum) return 1;
9143   if (d->pos < e->pos) return -1;
9144   if (d->pos > e->pos) return 1;
9145   return l - k;
9146 }
9147
9148 static int64_t lglsteps (LGL * lgl) {
9149   int64_t res = lgl->stats->steps;
9150 #ifndef NDEBUG
9151   // Note, this would be bulky and slow ...
9152   int64_t steps = 0;
9153   steps += lgl->stats->bca.steps;
9154   steps += lgl->stats->blk.steps;
9155   steps += lgl->stats->card.steps;
9156   steps += lgl->stats->cce.steps;
9157   steps += lgl->stats->cgr.csteps;
9158   steps += lgl->stats->cgr.esteps;
9159   steps += lgl->stats->cliff.steps;
9160   steps += lgl->stats->elm.copies;
9161   steps += lgl->stats->elm.resolutions;
9162   steps += lgl->stats->elm.steps;
9163   steps += lgl->stats->force.steps;
9164   steps += lgl->stats->gauss.steps.elim;
9165   steps += lgl->stats->gauss.steps.extr;
9166   steps += lgl->stats->prb.basic.steps;
9167   steps += lgl->stats->prb.simple.steps;
9168   steps += lgl->stats->prb.treelook.steps;
9169   steps += lgl->stats->props.lkhd;
9170   steps += lgl->stats->props.search;
9171   steps += lgl->stats->props.simp;
9172   steps += lgl->stats->rdp.steps;
9173   steps += lgl->stats->trd.steps;
9174   steps += lgl->stats->trnr.steps;
9175   steps += lgl->stats->unhd.steps;
9176   assert (steps == res);
9177 #endif
9178   return res;
9179 }
9180
9181 static void lgltrep (LGL * lgl) {
9182   int64_t steps, i;
9183   double t;
9184   if (!lgl->opts->trep.val) return;
9185   if (lgl->opts->verbose.val) return;
9186   steps = lglsteps (lgl);
9187   if (steps < lgl->limits->trep.steps) return;
9188   lgl->limits->trep.steps += lgl->opts->trepint.val;
9189   t = lgl->opts->abstime.val ? lglgetime (lgl) : lglsec (lgl);
9190   if (t < lgl->limits->trep.time) return;
9191   lglrep (lgl, 0, (lgl->simp ? 'P' : 'S'));
9192   i = lgl->limits->trep.time;
9193   do {
9194          if (!i)         i = 1;
9195     else if (i == 1)     i = 2;
9196     else if (i == 2)     i = 5;
9197     else if (i < 10)     i = 10;
9198     else if (i < 60)     i += 10;
9199     else if (i < 300)    i += 60;
9200     else if (i < 900)    i += 300;
9201     else if (i < 7200)   i += 900;
9202     else                 i += 3600;
9203   } while (i < t);
9204   lgl->limits->trep.time = i;
9205 }
9206
9207 static int lglterminate (LGL * lgl) {
9208   int64_t steps;
9209   int res;
9210   lgltrep (lgl);
9211   if (!lgl->cbs) return 0;
9212   if (!lgl->cbs->term.fun) return 0;
9213   if (lgl->cbs->term.done) return 1;
9214   steps = lglsteps (lgl);
9215   if (steps < lgl->limits->term.steps) return 0;
9216   res = lgl->cbs->term.fun (lgl->cbs->term.state);
9217   if (res) lgl->cbs->term.done = res;
9218   else lgl->limits->term.steps = steps + lgl->opts->termint.val;
9219   return  res;
9220 }
9221
9222 #define LGLCMPFDAT(A,B) (lglcmpfdat(fdat, *(A), *(B)))
9223
9224 static void lglforce (LGL * lgl, int * map) {
9225   int idx, lit, sign, blit, tag, red, other, other2, size, C, V, o, min, max;
9226   int round = 1, first = !lgl->stats->force.count;
9227   double cog, span, oldspan, mincut;
9228   const int * p, * w, * eow, * c;
9229   ForceData * fdat;
9230   HTS * hts;
9231   Stk order;
9232   if (!lgl->allowforce) return;
9233   if (!lgl->opts->force.val) return;
9234   lglstart (lgl, &lgl->times->force);
9235   span = INT_MAX;
9236 RESTART:
9237   oldspan = span;
9238   lgl->stats->force.count++;
9239   NEW (fdat, lgl->nvars);
9240   CLR (order);
9241   V = 0;
9242   for (idx = 2; idx < lgl->nvars; idx++) {
9243     if (!lglisfree (lgl, idx)) continue;
9244     fdat[idx].pos = map[idx];
9245     lglpushstk (lgl, &order, idx);
9246     V++;
9247   }
9248   if (V <= 1) goto DONE;
9249   C = 0;
9250   span = 0;
9251   for (idx = 2; idx < lgl->nvars; idx++)
9252     for (sign = -1; sign <= 1; sign += 2) {
9253       INCSTEPS (force.steps);
9254       lit = sign * idx;
9255       hts = lglhts (lgl, lit);
9256       w = lglhts2wchs (lgl, hts);
9257       eow = w + hts->count;
9258       for (p = w; p < eow; p++) {
9259         blit = *p;
9260         tag = blit & MASKCS;
9261         if (tag == TRNCS || tag == LRGCS) p++;
9262         if (tag == LRGCS) continue;
9263         red = blit & REDCS;
9264         if (red) continue;
9265         other = abs (blit >> RMSHFT);
9266         if (other < idx) continue;
9267         if (tag == BINCS) {
9268           cog = fdat[idx].pos + fdat[other].pos;
9269           cog /= 2;
9270           lglincfdat (fdat, idx, cog);
9271           lglincfdat (fdat, other, cog);
9272           o = fdat[idx].pos, min = o, max = o;
9273           o = fdat[other].pos, min = lglmin (min, o), max = lglmax (max, o);
9274           span += max - min;
9275           C++;
9276         } else if (tag == TRNCS) {
9277           other2 = abs (*p);
9278           if (other2 < idx) continue;
9279           cog = fdat[idx].pos + fdat[other].pos + fdat[other2].pos;
9280           cog /= 3;
9281           lglincfdat (fdat, idx, cog);
9282           lglincfdat (fdat, other, cog);
9283           lglincfdat (fdat, other2, cog);
9284           o = fdat[idx].pos, min = o, max = o;
9285           o = fdat[other].pos, min = lglmin (min, o), max = lglmax (max, o);
9286           o = fdat[other2].pos, min = lglmin (min, o), max = lglmax (max, o);
9287           span += max - min;
9288           C++;
9289         }
9290       }
9291     }
9292   for (c = lgl->irr.start; c < lgl->irr.top; c = p + 1) {
9293     if (*(p = c) >= NOTALIT) continue;
9294     INCSTEPS (force.steps);
9295     cog = 0;
9296     while ((idx = abs (*p))) cog += fdat[idx].pos, p++;
9297     size = p - c;
9298     assert (size >= 4);
9299     assert (p >= c + 4);
9300     cog /= size;
9301     min = INT_MAX, max = INT_MIN;
9302     for (p = c; (idx = abs (*p)); p++) {
9303       o = fdat[idx].pos, min = lglmin (min, o), max = lglmax (max, o);
9304       lglincfdat (fdat, idx, cog);
9305     }
9306     span += max - min;
9307     C++;
9308   }
9309   for (idx = 2; idx < lgl->nvars; idx++) {
9310     if (!lglisfree (lgl, idx)) continue;
9311     if (!(size = fdat[idx].count)) continue;
9312     fdat[idx].sum /= size;
9313   }
9314   assert (V > 1);
9315   mincut = span / (V - 1);
9316   if (C > 0) span /= C; else span = 0;
9317   if (lgl->stats->force.count > 1) {
9318     if (lgl->stats->force.mincut.min > mincut)
9319       lgl->stats->force.mincut.min = mincut;
9320     if (lgl->stats->force.mincut.max < mincut)
9321       lgl->stats->force.mincut.max = mincut;
9322   } else lgl->stats->force.mincut.min = lgl->stats->force.mincut.max = mincut;
9323   lglprt (lgl, 1, 
9324     "[force-%lld] mincut %.1f, span %.1f, %d variables, %d clauses",
9325     (LGLL) lgl->stats->force.count, mincut, span, V, C);
9326   SORT (int, order.start, lglcntstk (&order), LGLCMPFDAT);
9327   o = 2;
9328   for (p = order.start; p < order.top; p++) {
9329     idx = *p;
9330     assert (lglisfree (lgl, idx));
9331     LOG (3, "forced mapping free %d to %d", idx, o);
9332     map[idx] = o++;
9333   }
9334 DONE:
9335   DEL (fdat, lgl->nvars);
9336   lglrelstk (lgl, &order);
9337   if (first && !lglterminate (lgl)) {
9338     if (round++ < lgl->opts->force.val) goto RESTART;
9339     if (round < lglceilld (lglrem (lgl))) goto RESTART;
9340     if (oldspan > span && (oldspan - span) > oldspan/100.0) goto RESTART;
9341   }
9342   lglstop (lgl);
9343 }
9344
9345 static void lglmap (LGL * lgl) {
9346   int size, * map, oldnvars, mapsize;
9347 #ifndef NLGLPICOSAT
9348   lglpicosatchkall (lgl);
9349 #endif
9350   assert (!lgl->level);
9351   lgldreschedule (lgl);
9352   size = lglmapsize (lgl);
9353   oldnvars = lgl->nvars;
9354   mapsize = lglmax (oldnvars, 2);
9355   NEW (map, mapsize);
9356   lglmapnonequiv (lgl, map, size);
9357   lglmapequiv (lgl, map);
9358   lglforce (lgl, map);
9359   lglmaptrail (lgl, map);
9360   lglmapvars (lgl, map, size + 2);
9361   lglmaplits (lgl, map);
9362   lglmapstk (lgl, map, &lgl->dsched);
9363   if (lgl->cgrclosing) lglmapstk (lgl, map, &lgl->cgr->units);
9364   lglmapext (lgl, map);
9365   lglmapdef (lgl, map);
9366   lglmapass (lgl, map);
9367   if (lgl->treelooking && lgl->tlk && lgl->tlk->lkhd)
9368     lglmaplkhdscore (lgl, map, oldnvars);
9369   assert (lglmtstk (&lgl->clause));
9370   lglmaphts (lgl, map);
9371   DEL (map, mapsize);
9372   if (lgl->repr) DEL (lgl->repr, oldnvars);
9373   lglpicosatrestart (lgl);
9374   lgl->unassigned = size;
9375   lgldreschedule (lgl);
9376 }
9377
9378 static int lglgcnotnecessary (LGL * lgl) {
9379   if (lgl->forcegc) return 0;
9380   if (lgl->notfullyconnected) return 0;
9381   return lgl->stats->fixed.sum <= lgl->limits->gc.fixed;
9382 }
9383
9384 static void lglcompact (LGL * lgl) {
9385   int glue;
9386   lglfitstk (lgl, &lgl->assume);
9387   lglfitstk (lgl, &lgl->clause);
9388   lglfitstk (lgl, &lgl->eclause);
9389   lglfitstk (lgl, &lgl->dsched);
9390   lglfitstk (lgl, &lgl->eassume);
9391   lglfitstk (lgl, &lgl->extend);
9392   lglfitstk (lgl, &lgl->fassume);
9393   lglfitstk (lgl, &lgl->learned);
9394   lglfitstk (lgl, &lgl->cassume);
9395   lglfitstk (lgl, &lgl->frames);
9396 #ifndef NCHKSOL
9397   lglfitstk (lgl, &lgl->orig);
9398 #endif
9399   lglfitstk (lgl, &lgl->trail);
9400   lgldefrag (lgl);
9401   lglfitstk (lgl, &lgl->wchs->stk);
9402
9403   lglfitstk (lgl, &lgl->irr);
9404   for (glue = 0; glue <= MAXGLUE; glue++)
9405     lglfitlir (lgl, lgl->red + glue);
9406   lglrelstk (lgl, &lgl->lcaseen);
9407   lglrelstk (lgl, &lgl->minstk);
9408   lglrelstk (lgl, &lgl->poisoned);
9409   lglrelstk (lgl, &lgl->seen);
9410   lglrelstk (lgl, &lgl->esched);
9411 }
9412
9413 static void lglgc (LGL * lgl) {
9414   if (lgl->mt) return;
9415   lglchkred (lgl);
9416   if (lglgcnotnecessary (lgl)) return;
9417   lglstart (lgl, &lgl->times->gc);
9418   lglchkbcpclean (lgl, "gc");
9419   lglrep (lgl, 2, 'g');
9420   lgl->stats->gcs++;
9421   if (lgl->level > 0) lglbacktrack (lgl, 0);
9422   for (;;) {
9423     lgldis (lgl);
9424     lglcon (lgl);
9425     if (lgl->mt) break;
9426     if (lgl->next2 == lgl->next &&
9427         lgl->next == lglcntstk (&lgl->trail)) break;
9428     if (!lglbcp (lgl)) {
9429       assert (!lgl->mt);
9430       LOG (1, "empty clause after propagating garbage collection unit");
9431       lgl->mt = 1;
9432       break;
9433     }
9434   }
9435   lglcount (lgl);
9436   lglmap (lgl);
9437
9438   lglcompact (lgl);
9439
9440   lgl->limits->gc.fixed = lgl->stats->fixed.sum;
9441
9442   lglchkred (lgl);
9443   lglrep (lgl, 2, 'c');
9444   lglstop (lgl);
9445 }
9446
9447 static int lgltopgc (LGL * lgl) {
9448   if (lgl->mt) return 0;
9449   assert (!lgl->forcegc && !lgl->allowforce);
9450   lgl->forcegc = lgl->allowforce = 1;
9451   lglgc (lgl);
9452   assert (lgl->forcegc && lgl->allowforce);
9453   lgl->forcegc = lgl->allowforce = 0;
9454   return !lgl->mt;
9455 }
9456
9457 static int lglrandec (LGL * lgl) {
9458   unsigned size, pos, start, delta;
9459   int lit;
9460   lgl->limits->randec = lgl->stats->decisions;
9461   lgl->limits->randec += lgl->opts->randecint.val/2;
9462   lgl->limits->randec += lglrand (lgl) % lgl->opts->randecint.val;
9463   assert (lgl->nvars > 2);
9464   size = lgl->nvars - 2;
9465   if (!size) return 0;
9466   pos = start = lglrand (lgl) % size;
9467   lit = 2 + pos;
9468   assert (2 <= lit && lit < lgl->nvars);
9469   if (lglval (lgl, lit)) {
9470     delta = lglrand (lgl) % size;
9471     if (size == 1) return 0;
9472     if (!delta) delta++;
9473     while (lglgcd (delta, size) != 1)
9474       if (++delta == size) delta = 1;
9475     do {
9476       pos += delta;
9477       if (pos >= size) pos -= size;
9478       if (pos == start) return 0;
9479       lit = pos + 2;
9480       assert (2 <= lit && lit < lgl->nvars);
9481     } while (lglval (lgl, lit));
9482   }
9483   lgl->stats->randecs++;
9484   return lit;
9485 }
9486
9487 static int lgladecide (LGL * lgl) {
9488   int res, val;
9489   while (lgl->assumed < lglcntstk (&lgl->assume)) {
9490     res = lglpeek (&lgl->assume, lgl->assumed);
9491     val = lglcval (lgl, res);
9492     if (val > 0) LOG (3, "assumption %d already satisfied", res);
9493     lgl->assumed++;
9494     LOG (3, "new assumption queue level %d", lgl->assumed);
9495     assert (val >= 0);
9496     if (!val) return res;
9497   }
9498   return 0;
9499 }
9500
9501 static int lgldefphase (LGL * lgl, int idx) {
9502   AVar * av;
9503   int bias;
9504   assert (idx > 0);
9505   av = lglavar (lgl, idx);
9506   if (!av->phase) {
9507     bias = lgl->opts->phase.val;
9508     if (!bias) bias = av->bias;
9509     if (!bias) bias = lglsetjwhbias (lgl, idx);
9510     av->phase = bias;
9511   }
9512   return av->phase;
9513 }
9514
9515 static int lgldecidephase (LGL * lgl, int lit) {
9516   int res = abs (lit), flipped, diff;
9517   AVar * av = lglavar (lgl, lit);
9518   if (av->fase) return av->fase * res;
9519   if ((diff = lgl->level - lgl->alevel) < lgl->opts->phasegluebit.val) {
9520     LOG (1, "Glue-Bit initial level counting");
9521     if (!((lgl->stats->restarts.count >> (diff & 3)) & 1)) res = -res;
9522     return res;
9523   }
9524   if (lgl->phaseneg || lgldefphase (lgl, res) <= 0) res = -res;
9525   if (!lgl->flipping &&
9526       !lgl->phaseneg &&
9527       lgl->opts->flipping.val &&
9528       lglrem (lgl) <= lgl->opts->flipvlim.val &&
9529       lgl->level >= lgl->alevel &&
9530       lgl->assumed == lglcntstk (&lgl->assume) &&
9531       (!lgl->opts->fliptop.val || lgl->level == lgl->alevel)) {
9532     if (lgl->notflipped >= lgl->limits->flipint) {
9533       LOG (1, "switching on phase flipping");
9534       lgl->stats->fliphases++;
9535       lgl->limits->flipint = lgl->opts->flipint.val;
9536       lgl->flipping = lgl->opts->flipdur.val;
9537       lgl->notflipped = 0;
9538     } else lgl->notflipped++;
9539   }
9540   if (lgl->flipping) {
9541     const int fliplevels = lgl->opts->fliplevels.val;
9542     const int ldmod = lgl->opts->flipldmod.val;
9543     const int level = lgl->level - lgl->alevel;
9544     int shift = fliplevels - lglmin (level, fliplevels);
9545     int flip = !((lgl->stats->fliphases >> ldmod) & (1 << shift));
9546     if (level > fliplevels) flip = 0;
9547     assert (!lgl->phaseneg);
9548     flipped = flip ? -res : res;
9549     LOG (2, "flipping phase of %d to %d", res, flipped);
9550     lgl->stats->flipped++;
9551     res = flipped;
9552   }
9553   return res;
9554 }
9555
9556 static int lglhasbins (LGL * lgl, int lit) {
9557   int blit, tag, other, other2, val, val2, implied;
9558   const int * p, * w, * eos, * q;
9559   HTS * hts;
9560   assert (!lgl->level);
9561   assert (lglisfree (lgl, lit));
9562   hts = lglhts (lgl, lit);
9563   w = lglhts2wchs (lgl, hts);
9564   eos = w + hts->count;
9565   for (p = w; p < eos; p++) {
9566     if (lgl->treelooking) INCSTEPS (prb.treelook.steps);
9567     blit = *p;
9568     tag = blit & MASKCS;
9569     if (tag == BINCS) {
9570       other = blit >> RMSHFT;
9571       val = lglval (lgl, other);
9572       assert (val >= 0);
9573       if (!val) return 1;
9574     } else if (tag == TRNCS) {
9575       other = blit >> RMSHFT;
9576       other2= *++p;
9577       val = lglval (lgl, other);
9578       val2 = lglval (lgl, other2);
9579       assert (val >= 0 || val2 >= 0);
9580       if (val > 0 || val2 > 0) continue;
9581       if (!val && val2 < 0) return 1;
9582       if (val < 0 && !val2) return 1;
9583     } else {
9584       assert (tag == LRGCS);
9585       q = lglidx2lits (lgl, (blit & REDCS), *++p);
9586       implied = 0;
9587       while ((other = *q++)) {
9588         if (other == lit) continue;
9589         val = lglval (lgl, other);
9590         if (val > 0) break;
9591         if (val < 0) continue;
9592         if (implied) break;
9593         implied = other;
9594       }
9595       if (other) continue;
9596       if (implied) return 1;
9597     }
9598   }
9599   return 0;
9600 }
9601
9602 static int lglhasbinortrn (LGL * lgl, int lit) {
9603   int blit, tag, other, other2, val, val2, implied;
9604   const int * p, * w, * eos, * q;
9605   HTS * hts;
9606   assert (!lgl->level);
9607   assert (lglisfree (lgl, lit));
9608   hts = lglhts (lgl, lit);
9609   w = lglhts2wchs (lgl, hts);
9610   eos = w + hts->count;
9611   for (p = w; p < eos; p++) {
9612     if (lgl->treelooking) INCSTEPS (prb.treelook.steps);
9613     blit = *p;
9614     tag = blit & MASKCS;
9615     if (tag == BINCS) {
9616       other = blit >> RMSHFT;
9617       val = lglval (lgl, other);
9618       assert (val >= 0);
9619       if (!val) return 1;
9620     } else if (tag == TRNCS) {
9621       other = blit >> RMSHFT;
9622       other2= *++p;
9623       val = lglval (lgl, other);
9624       val2 = lglval (lgl, other2);
9625       assert (val >= 0 || val2 >= 0);
9626       if (val <= 0 && val2 <= 0) return 1;
9627     } else {
9628       assert (tag == LRGCS);
9629       q = lglidx2lits (lgl, (blit & REDCS), *++p);
9630       implied = 0;
9631       while (implied <= 2 && (other = *q++)) {
9632         if (other == lit) continue;
9633         val = lglval (lgl, other);
9634         if (val > 0) break;
9635         if (!val) implied++;
9636       }
9637       if (other) continue;
9638       if (implied <= 2) return 1;
9639     }
9640   }
9641   return 0;
9642 }
9643
9644 static int lgldecide (LGL * lgl) {
9645   int lit;
9646   lglchkbcpclean (lgl, "decide");
9647   if (!lgl->unassigned) return 0;
9648   if ((lit = lgladecide (lgl))) {
9649     LOG (2, "using assumption %d as decision", lit);
9650     lgl->alevel = lgl->level + 1;
9651     LOG (2, "new assumption decision level %d", lgl->alevel);
9652   } else {
9653     if (lgl->opts->randec.val &&
9654         lgl->limits->randec <= lgl->stats->decisions) {
9655       lit = lglrandec (lgl);
9656       lit = lgldecidephase (lgl, lit);
9657       LOG (2, "random decision %d", lit);
9658       if (lgl->opts->randecflipint.val &&
9659           !(lgl->stats->randecs % lgl->opts->randecflipint.val)) {
9660         lit = -lit;
9661         LOG (2, "flipped random decision %d", lit);
9662         lgl->stats->randecsflipped++;
9663       }
9664     } else {
9665       lit = lglnextdecision (lgl);
9666       lit = lgldecidephase (lgl, lit);
9667     }
9668   }
9669   if (lit) lgldassume (lgl, lit);
9670   return 1;
9671 }
9672
9673 static void lgldcpdis (LGL * lgl) {
9674   int idx, sign, lit, tag, blit, red, other, other2, i;
9675   const int * w, * p, * eow;
9676   Val val;
9677   HTS * hts;
9678   Stk * s;
9679   NEW (lgl->dis, 1);
9680   for (idx = 2; idx < lgl->nvars; idx++)
9681     for (sign = -1; sign <= 1; sign += 2) {
9682       lit = sign * idx;
9683       hts = lglhts (lgl, lit);
9684       if (!hts->offset) continue;
9685       assert (hts->count > 0);
9686       w = lglhts2wchs (lgl, hts);
9687       eow = w + hts->count;
9688       hts->count = hts->offset = 0;
9689       val = lglval (lgl, lit);
9690       if (val > 0) continue;
9691       for (p = w; p < eow; p++) {
9692         blit = *p;
9693         tag = blit & MASKCS;
9694         if (tag == TRNCS || tag == LRGCS) p++;
9695         if (tag == LRGCS) continue;
9696         other = blit >> RMSHFT;
9697         if (abs (other) < idx) continue;
9698         val = lglval (lgl, other);
9699         if (val > 0) continue;
9700         red = blit & REDCS;
9701         if (red && !lglisfree (lgl, other)) continue;
9702         if (tag == BINCS) {
9703           s = red ? &lgl->dis->red.bin : &lgl->dis->irr.bin;
9704         } else {
9705           assert (tag == TRNCS);
9706           other2 = *p;
9707           if (abs (other2) < idx) continue;
9708           val = lglval (lgl, other2);
9709           if (val > 0) continue;
9710           if (red && !lglisfree (lgl, other2)) continue;
9711           s = red ? &lgl->dis->red.trn : &lgl->dis->irr.trn;
9712           lglpushstk (lgl, s, other2);
9713         }
9714         lglpushstk (lgl, s, other);
9715         lglpushstk (lgl, s, lit);
9716         lglpushstk (lgl, s, 0);
9717       }
9718     }
9719   lglrststk (&lgl->wchs->stk, 2);
9720   lgl->wchs->stk.top[-1] = INT_MAX;
9721   for (i = 0; i < MAXLDFW; i++) lgl->wchs->start[i] = INT_MAX;
9722   lgl->wchs->free = 0;
9723   lglrelstk (lgl, &lgl->learned);
9724 }
9725
9726 static void lgldcpclnstk (LGL * lgl, int red, Stk * s) {
9727   int oldsz, newsz, lit, mark, satisfied, repr, act;
9728   const int * p, * c, * eos = s->top;
9729   int * start, * q, * r, * d;
9730   Stk * t;
9731   Val val;
9732   q = start = s->start;
9733   for (c = q; c < eos; c = p + 1) {
9734     act = *c;
9735     if (act == REMOVED) {
9736       for (p = c + 1; p < eos && *p == REMOVED; p++)
9737         ;
9738       assert (p >= eos || *p < NOTALIT || lglisact (*p));
9739       p--;
9740       continue;
9741     }
9742     if (lglisact (act)) *q++ = *c++; else act = -1;
9743     d = q;
9744     satisfied = 0;
9745 #ifndef NDEBUG
9746     for (p = c; assert (p < eos), (lit = *p); p++) {
9747       assert (!lglavar (lgl, lit)->mark);
9748       repr = lglirepr (lgl, lit);
9749       assert (abs (repr) == 1 || !lglavar (lgl, lit)->mark);
9750     }
9751 #endif
9752     for (p = c; assert (p < eos), (lit = *p); p++) {
9753       assert (lit < NOTALIT);
9754       if (satisfied) continue;
9755       repr = lglirepr (lgl, lit);
9756       val = lglcval (lgl, repr);
9757       if (val > 0) { satisfied = 1; continue; }
9758       if (val < 0) continue;
9759       mark = lglmarked (lgl, repr);
9760       if (mark < 0) { satisfied = 1; continue; }
9761       if (mark > 0) continue;
9762       lglmark (lgl, repr);
9763       *q++ = repr;
9764     }
9765     oldsz = p - c;
9766     for (r = d; r < q; r++) lglunmark (lgl, *r);
9767     if (satisfied || !oldsz) { q = d - (act >= 0); continue; }
9768     newsz = q - d;
9769     if (newsz >= 4) {
9770       assert (act < 0 || d[-1] == act);
9771       *q++ = 0;
9772       assert (d <= c);
9773     } else if (!newsz) {
9774       LOG (1, "found empty clause while cleaning decomposition");
9775       lgl->mt = 1;
9776       q = d - (act >= 0);
9777     } else if (newsz == 1) {
9778       LOG (1, "new unit %d while cleaning decomposition", d[0]);
9779       lglunit (lgl, d[0]);
9780       q = d - (act >= 0);
9781     } else if (newsz == 2) {
9782       t = red ? &lgl->dis->red.bin : &lgl->dis->irr.bin;
9783       if (s != t) {
9784         lglpushstk (lgl, t, d[0]);
9785         lglpushstk (lgl, t, d[1]);
9786         lglpushstk (lgl, t, 0);
9787         q = d - (act >= 0);
9788       } else *q++ = 0;
9789     } else {
9790       assert (newsz == 3);
9791       t = red ? &lgl->dis->red.trn : &lgl->dis->irr.trn;
9792       if (s != t) {
9793         lglpushstk (lgl, t, d[0]);
9794         lglpushstk (lgl, t, d[1]);
9795         lglpushstk (lgl, t, d[2]);
9796         lglpushstk (lgl, t, 0);
9797         q = d - (act >= 0);
9798       } else *q++ = 0;
9799     }
9800   }
9801   s->top = q;
9802 }
9803
9804 static void lgldcpconnaux (LGL * lgl, int red, int glue, Stk * s) {
9805   int * start = s->start, * q, * d, lit, size, lidx, act;
9806   const int * p, * c, * eos = s->top;
9807   assert (red == 0 || red == REDCS);
9808   assert (!glue || red);
9809   q = start;
9810   for (c = q; c < eos; c = p + 1) {
9811     if (lglisact (act = *c)) *q++ = *c++; else act = -1;
9812     d = q;
9813     for (p = c; (lit = *p); p++) {
9814       assert (!lgl->repr[abs (lit)]);
9815       assert (!lgl->vals[abs (lit)]);
9816       *q++ = lit;
9817     }
9818     size = q - d;
9819     if (size == 2) {
9820       q = d - (act >= 0);
9821       lglwchbin (lgl, d[0], d[1], red);
9822       lglwchbin (lgl, d[1], d[0], red);
9823     } else if (size == 3) {
9824       q = d - (act >= 0);
9825       lglwchtrn (lgl, d[0], d[1], d[2], red);
9826       lglwchtrn (lgl, d[1], d[0], d[2], red);
9827       lglwchtrn (lgl, d[2], d[0], d[1], red);
9828     } else {
9829       assert (size > 3);
9830       *q++ = 0;
9831       lidx = d - start;
9832       if (red) {
9833         assert (lidx <= MAXREDLIDX);
9834         lidx <<= GLUESHFT;
9835         assert (0 <= lidx);
9836         lidx |= glue;
9837       }
9838       (void) lglwchlrg (lgl, d[0], d[1], red, lidx);
9839       (void) lglwchlrg (lgl, d[1], d[0], red, lidx);
9840     }
9841   }
9842   s->top = q;
9843 }
9844
9845 static void lgldcpcon (LGL * lgl) {
9846   Stk * lir;
9847   int glue;
9848   lgldcpconnaux (lgl, 0, 0, &lgl->dis->irr.bin);
9849   lgldcpconnaux (lgl, REDCS, 0, &lgl->dis->red.bin);
9850   lgldcpconnaux (lgl, 0, 0, &lgl->dis->irr.trn);
9851   lgldcpconnaux (lgl, REDCS, 0, &lgl->dis->red.trn);
9852   lglrelstk (lgl, &lgl->dis->irr.bin);
9853   lglrelstk (lgl, &lgl->dis->irr.trn);
9854   lglrelstk (lgl, &lgl->dis->red.bin);
9855   lglrelstk (lgl, &lgl->dis->red.trn);
9856   DEL (lgl->dis, 1);
9857   lgldcpconnaux (lgl, 0, 0, &lgl->irr);
9858   for (glue = 0; glue < MAXGLUE; glue++) {
9859     lir = lgl->red + glue;
9860     lgldcpconnaux (lgl, REDCS, glue, lir);
9861   }
9862   lglfullyconnected (lgl);
9863 }
9864
9865 static void lgldcpcln (LGL * lgl) {
9866   int glue, old, rounds = 0;
9867   Stk * lir;
9868   do {
9869     rounds++;
9870     old = lgl->stats->fixed.current;
9871     lgldcpclnstk (lgl, 0, &lgl->irr);
9872     lgldcpclnstk (lgl, 0, &lgl->dis->irr.bin);
9873     lgldcpclnstk (lgl, 0, &lgl->dis->irr.trn);
9874     lgldcpclnstk (lgl, REDCS, &lgl->dis->red.bin);
9875     lgldcpclnstk (lgl, REDCS, &lgl->dis->red.trn);
9876     for (glue = 0; glue < MAXGLUE; glue++) {
9877       lir = lgl->red + glue;
9878       lgldcpclnstk (lgl, REDCS, lir);
9879     }
9880   } while (old < lgl->stats->fixed.current);
9881   LOG (1, "iterated %d decomposition cleaning rounds", rounds);
9882 }
9883
9884 static void lglepush (LGL * lgl, int ilit) {
9885   int elit = ilit ? lglexport (lgl, ilit) : 0;
9886   lglpushstk (lgl, &lgl->extend, elit);
9887   LOG (4, "pushing external %d internal %d", elit, ilit);
9888 }
9889
9890 static void lglemerge (LGL * lgl, int ilit0, int ilit1) {
9891   int elit0 = lglexport (lgl, ilit0), elit1 = lglexport (lgl, ilit1);
9892   int repr0 = lglerepr (lgl, elit0), repr1 = lglerepr (lgl, elit1);
9893   Ext * ext0 = lglelit2ext (lgl, repr0);
9894 #ifndef NDEBUG
9895   Ext * ext1 = lglelit2ext (lgl, repr1);
9896   int repr = repr1;
9897 #endif
9898   assert (abs (repr0) != abs (repr1));
9899   if (repr0 < 0) {
9900 #ifndef NLGLOG
9901     repr0 *= -1;
9902 #endif
9903     repr1 *= -1;
9904   }
9905   ext0->equiv = 1;
9906   ext0->repr = repr1;
9907   LOG (2, "merging external literals %d and %d", repr0, repr1);
9908   assert (lglerepr (lgl, elit0) == repr);
9909   assert (lglerepr (lgl, elit1) == repr);
9910   assert (!(ext0->frozen || ext0->tmpfrozen) ||
9911             ext1->frozen || ext1->tmpfrozen);
9912   lglepush (lgl, -ilit0); lglepush (lgl, ilit1); lglepush (lgl, 0);
9913   lglepush (lgl, ilit0); lglepush (lgl, -ilit1); lglepush (lgl, 0);
9914   if (lgl->opts->drup.val) {
9915     lgldrupclsarg (lgl, -ilit0, ilit1, 0);
9916     lgldrupclsarg (lgl, ilit0, -ilit1, 0);
9917   }
9918 }
9919
9920 static void lglimerge (LGL * lgl, int lit, int repr) {
9921   int idx = abs (lit);
9922   AVar * av = lglavar (lgl, idx);
9923   assert (!lglifrozen (lgl, lit) || lglifrozen (lgl, repr));
9924   if (lit < 0) repr = -repr;
9925   assert (av->type == FREEVAR);
9926   assert (lgl->repr);
9927   av->type = EQUIVAR;
9928   lgl->repr[idx] = repr;
9929   lgl->stats->prgss++;
9930   lgl->stats->irrprgss++;
9931   lgl->stats->equiv.sum++;
9932   lgl->stats->equiv.current++;
9933   assert (lgl->stats->equiv.sum > 0);
9934   assert (lgl->stats->equiv.current > 0);
9935 #if 0
9936   if (lgl->opts->drup.val) lgldrupclsarg (lgl, idx, -repr, 0);
9937   if (lgl->opts->drup.val) lgldrupclsarg (lgl, -idx, repr, 0);
9938 #endif
9939 #ifndef NLGLPICOSAT
9940   lglpicosatchkclsarg (lgl, idx, -repr, 0);
9941   lglpicosatchkclsarg (lgl, -idx, repr, 0);
9942 #endif
9943   lglemerge (lgl, idx, repr);
9944 }
9945
9946 static void lglfreezer (LGL * lgl) {
9947   int frozen, melted, tmpfrozen, elit, erepr, ilit;
9948   Ext * ext, * rext;
9949   int * p, eass;
9950   if (lgl->frozen) return;
9951   for (elit = 1; elit <= lgl->maxext; elit++)
9952     lgl->ext[elit].tmpfrozen = 0;
9953   tmpfrozen = frozen = 0;
9954   if (!lglmtstk (&lgl->eassume)) {
9955     for (p = lgl->eassume.start; p < lgl->eassume.top; p++) {
9956       eass = *p;
9957       ext = lglelit2ext (lgl, eass);
9958       assert (!ext->melted);
9959       assert (!ext->eliminated);
9960       assert (!ext->blocking);
9961       if (!ext->frozen && !ext->tmpfrozen) {
9962         ext->tmpfrozen = 1;
9963         tmpfrozen++;
9964         LOG (2, "temporarily freezing external assumption %d", eass);
9965         erepr = lglerepr (lgl, eass);
9966         rext = lglelit2ext (lgl, erepr);
9967         if (ext != rext && !rext->frozen && !rext->tmpfrozen) {
9968           assert (!rext->equiv);
9969           assert (!rext->eliminated);
9970           // assert (!rext->blocking);
9971           LOG (2,
9972             "temporarily freezing external assumption literal %d", erepr);
9973           rext->tmpfrozen = 1;
9974           tmpfrozen++;
9975         }
9976       }
9977     }
9978   }
9979   for (elit = 1; elit <= lgl->maxext; elit++) {
9980     ext = lglelit2ext (lgl, elit);
9981     if (!ext->frozen) continue;
9982     frozen++;
9983     assert (!ext->melted);
9984     assert (!ext->eliminated);
9985     assert (!ext->blocking);
9986     erepr = lglerepr (lgl, elit);
9987     rext = lglelit2ext (lgl, erepr);
9988     if (ext == rext) continue;
9989     if (rext->frozen) continue;
9990     if (rext->tmpfrozen) continue;
9991     // assert (!rext->melted);
9992     assert (!rext->equiv);
9993     assert (!rext->eliminated);
9994     // assert (!rext->blocking);
9995     LOG (2, "temporarily freezing external literal %d", erepr);
9996     rext->tmpfrozen = 1;
9997     tmpfrozen++;
9998   }
9999   melted = 0;
10000   for (elit = 1; elit <= lgl->maxext; elit++) {
10001     ext = lglelit2ext (lgl, elit);
10002     if (ext->frozen) continue;
10003     if (ext->melted) continue;
10004     if (ext->tmpfrozen) continue;
10005     if (!ext->imported) continue;
10006     LOG (2, "permanently melted external %d", elit);
10007     ext->melted = 1;
10008     melted++;
10009   }
10010   LOG (2, "found %d frozen external variables", frozen);
10011   LOG (2, "temporarily frozen %d external variables", tmpfrozen);
10012   LOG (2, "permanently melted %d external variables", melted);
10013   lgl->frozen = 1;
10014   LOG (2, "frozen solver");
10015   melted = frozen = 0;
10016   for (ilit = 2; ilit < lgl->nvars; ilit++) {
10017     if (!lglisfree (lgl, ilit)) continue;
10018     if (lglifrozen (lgl, ilit)) frozen++; else melted++;
10019   }
10020   lgl->allfrozen = !melted;
10021   if (lgl->allfrozen) 
10022     lglprt (lgl, 1, "[freezer] all %d free variables frozen", frozen);
10023   else
10024     lglprt (lgl, 1,
10025       "[freezer] frozen %d variables out of %d free variables %.0f%%",
10026       frozen, frozen + melted, lglpcnt (frozen, frozen + melted));
10027 }
10028
10029 static int lglcmprepr (LGL * lgl, int a, int b) {
10030   int f = lglifrozen (lgl, a), g = lglifrozen (lgl, b), res;
10031   if ((res = g - f)) return res;
10032   if ((res = (abs (a) - abs (b)))) return res;
10033   return a - b;
10034 }
10035
10036 static int lgltarjan (LGL * lgl) {
10037   int * dfsimap, * mindfsimap, idx, oidx, sign, lit, blit, tag, other;
10038   int dfsi, mindfsi, ulit, uother, tmp, repr, res, sgn, frozen;
10039   const int * p, * w, * eow;
10040   Stk stk, component;
10041   AVar * av;
10042   HTS * hts;
10043   if (!lgl->nvars) return 1;
10044   assert (lgl->frozen);
10045   dfsi = 0;
10046   NEW (dfsimap, 2*lgl->nvars);
10047   NEW (mindfsimap, 2*lgl->nvars);
10048   NEW (lgl->repr, lgl->nvars);
10049   CLR (stk); CLR (component);
10050   res = 1;
10051   for (idx = 2; idx < lgl->nvars; idx++) {
10052     for (sign = -1; sign <= 1; sign += 2) {
10053       lit = sign * idx;
10054       ulit = lglulit (lit);
10055       tmp = dfsimap[ulit];
10056       if (tmp) continue;
10057       lglpushstk (lgl, &stk, lit);
10058       while (!lglmtstk (&stk)) {
10059         lit = lglpopstk (&stk);
10060         if (lit) {
10061           ulit = lglulit (lit);
10062           if (dfsimap[ulit]) continue;
10063           dfsimap[ulit] = mindfsimap[ulit] = ++dfsi;
10064           lglpushstk (lgl, &component, lit);
10065           assert (dfsi > 0);
10066           lglpushstk (lgl, &stk, lit);
10067           lglpushstk (lgl, &stk, 0);
10068           hts = lglhts (lgl, -lit);
10069           if (!hts->offset) continue;
10070           assert (hts->count > 0);
10071           w = lglhts2wchs (lgl, hts);
10072           eow = w + hts->count;
10073           for (p = w; p < eow; p++) {
10074             blit = *p;
10075             tag = blit & MASKCS;
10076             if (tag != BINCS) { p++; continue; }
10077             other = blit >> RMSHFT;
10078             uother = lglulit (other);
10079             tmp = dfsimap[uother];
10080             if (tmp) continue;
10081             lglpushstk (lgl, &stk, other);
10082           }
10083         } else {
10084           assert (!lglmtstk (&stk));
10085           lit = lglpopstk (&stk);
10086           ulit = lglulit (lit);
10087           mindfsi = dfsimap[ulit];
10088           assert (mindfsi);
10089           hts = lglhts (lgl, -lit);
10090           w = lglhts2wchs (lgl, hts);
10091           eow = w + hts->count;
10092           for (p = w; p < eow; p++) {
10093             blit = *p;
10094             tag = blit & MASKCS;
10095             if (tag != BINCS) { p++; continue; }
10096             other = blit >> RMSHFT;
10097             uother = lglulit (other);
10098             tmp = mindfsimap[uother];
10099             if (tmp >= mindfsi) continue;
10100             mindfsi = tmp;
10101           }
10102           if (mindfsi == dfsimap[ulit]) {
10103             repr = lit;
10104             frozen = lglifrozen (lgl, repr);
10105             for (p = component.top - 1; (other = *p) != lit; p--) {
10106               if (lglcmprepr (lgl, other, repr) < 0) repr = other;
10107               if (!frozen && lglifrozen (lgl, other)) frozen = 1;
10108             }
10109             while ((other = lglpopstk (&component)) != lit) {
10110               mindfsimap[lglulit (other)] = INT_MAX;
10111               if (other == repr) continue;
10112               if (other == -repr) {
10113                 if (lgl->opts->drup.val) lgldrupclsarg (lgl, repr, 0);
10114                 LOG (1, "empty clause since repr[%d] = %d", repr, other);
10115                 lgl->mt = 1; res = 0; goto DONE;
10116               }
10117               sgn = lglsgn (other);
10118               oidx = abs (other);
10119               tmp = lgl->repr[oidx];
10120               if (tmp == sgn * repr) continue;
10121               LOG (2, "repr[%d] = %d", oidx, sgn * repr);
10122               if (tmp) {
10123                 if (lgl->opts->drup.val) lgldrupclsarg (lgl, repr, 0);
10124                 LOG (1, "empty clause since repr[%d] = %d and repr[%d] = %d",
10125                      oidx, tmp, oidx, sgn * repr);
10126                 lgl->mt = 1; res = 0; goto DONE;
10127               } else {
10128                 av = lglavar (lgl, oidx);
10129                 assert (sgn*oidx == other);
10130                 if (av->type == FREEVAR) lglimerge (lgl, other, repr);
10131                 else assert (av->type == FIXEDVAR);
10132               }
10133             }
10134             mindfsimap[lglulit (lit)] = INT_MAX;
10135             if (frozen) {
10136               LOG (2, "equivalence class of %d is frozen", repr);
10137               assert (lglifrozen (lgl, repr));
10138             }
10139           } else mindfsimap[ulit] = mindfsi;
10140         }
10141       }
10142     }
10143   }
10144 DONE:
10145   lglrelstk (lgl, &stk);
10146   lglrelstk (lgl, &component);
10147   DEL (mindfsimap, 2*lgl->nvars);
10148   DEL (dfsimap, 2*lgl->nvars);
10149   if (!res) DEL (lgl->repr, lgl->nvars);
10150   return res;
10151 }
10152
10153 static int lglsyncunits (LGL * lgl) {
10154   int * units, * eou, * p, elit, erepr, ilit, res, count = 0;
10155   void (*produce)(void*, int);
10156   int64_t steps;
10157   Ext * ext;
10158   Val val;
10159   if (lgl->mt) return 0;
10160   if (!lgl->cbs) return 1;
10161   if (!lgl->cbs->units.consume.fun) return 1;
10162   assert (!lgl->simp || !lgl->level);
10163   steps = lglsteps (lgl);
10164   if (steps < lgl->limits->sync.steps) return 1;
10165   lgl->limits->sync.steps = steps + lgl->opts->syncunint.val;
10166   lgl->stats->sync.units.consumed.calls++;
10167   lgl->cbs->units.consume.fun (lgl->cbs->units.consume.state, &units, &eou);
10168   if (units == eou) return 1;
10169   lgl->stats->sync.units.consumed.tried++;
10170   produce = lgl->cbs->units.produce.fun;
10171   lgl->cbs->units.produce.fun = 0;
10172   for (p = units; !lgl->mt && p < eou; p++) {
10173     elit = *p;
10174     erepr = lglerepr (lgl, elit);
10175     ext = lglelit2ext (lgl, erepr);
10176     assert (!ext->equiv);
10177     ilit = ext->repr;
10178     if (!ilit) continue;
10179     if (erepr < 0) ilit = -ilit;
10180     if (ilit == 1) continue;
10181     if (ilit == -1) val = -1;
10182     else {
10183       assert (abs (ilit) > 1);
10184       val = lglval (lgl, ilit);
10185       if (val && lglevel (lgl, ilit)) val = 0;
10186     }
10187     if (val == 1) continue;
10188     if (val == -1) {
10189       LOG (1, "mismatching synchronized external unit %d", elit);
10190       if (lgl->level > 0) lglbacktrack (lgl, 0);
10191       lgl->mt = 1;
10192     } else if (!lglisfree (lgl, ilit)) continue;
10193     else {
10194       assert (!val);
10195       if (lgl->level > 0) lglbacktrack (lgl, 0);
10196       lglunit (lgl, ilit);
10197       LOG (2, "importing internal unit %d external %d",
10198            lgl->tid, ilit, elit);
10199       count++;
10200     }
10201   }
10202   lgl->cbs->units.produce.fun = produce;
10203   if (lgl->cbs->units.consumed.fun)
10204     lgl->cbs->units.consumed.fun (lgl->cbs->units.consumed.state, count);
10205   if (count) lgl->stats->sync.units.consumed.actual++;
10206   if (lgl->mt) return 0;
10207   if (count) LOG (1, "imported %d units", count);
10208   if (!count) return 1;
10209   assert (!lgl->level);
10210   res = lglbcp (lgl);
10211   if(!res && !lgl->mt) lgl->mt = 1;
10212   return res;
10213 }
10214
10215 static int lglelitblockingoreliminated (LGL * lgl, int elit) {
10216   Ext * ext = lglelit2ext (lgl, elit);
10217   return ext->blocking || ext->eliminated;
10218 }
10219
10220 static int lglsynclsexist (LGL * lgl) {
10221   int len, lit, blit, tag, other, other2;
10222   int * s, * p, * w, * eow;
10223   HTS * hts;
10224   len = lglcntstk (&lgl->clause);
10225   assert (!len || lgl->clause.top[-1]);
10226   if (len <= 1) return 0;
10227   s = lgl->clause.start;
10228   for (p = s + 1; p + 1 < lgl->clause.top; p++) {
10229     assert (lglmarked (lgl, *p) > 0);
10230     if (lglhts (lgl, *s)->count > lglhts (lgl, *p)->count)
10231       SWAP (int, *s, *p);
10232   }
10233   hts = lglhts (lgl, (lit = *s));
10234   assert (lglmarked (lgl, lit) > 0);
10235   w = lglhts2wchs (lgl, hts);
10236   eow = w + hts->count;
10237   for (p = w; p < eow; p++) {
10238     blit = *p;
10239     tag = blit & MASKCS;
10240     if (tag == TRNCS || tag == LRGCS) p++;
10241     if (tag == LRGCS) continue;
10242     if (tag == BINCS) {
10243       other = blit >> RMSHFT;
10244       if (lglmarked (lgl, other) > 0) return 1;
10245     } else {
10246       assert (tag == TRNCS);
10247       if (len <= 2) continue;
10248       other = blit >> RMSHFT;
10249       if (lglmarked (lgl, other) > 0) return 1;
10250       other2 = *p;
10251       if (lglmarked (lgl, other2) > 0) return 1;
10252     }
10253   }
10254   return 0;
10255 }
10256
10257 static int lglsyncls (LGL * lgl) {
10258   int maxlevel, level, nonfalse, numtrue, res, delta, glue, consumed;
10259   int * cls, elit, erepr, tmp, ilit, len, newglue;
10260   const int * p;
10261   int64_t rate;
10262   if (lgl->mt) return 0;
10263   if (!lgl->cbs) return 1;
10264   if (!lgl->cbs->cls.consume.fun) return 1;
10265   assert (!lgl->simp);
10266   if (lgl->stats->confs < lgl->limits->sync.confs) return 1;
10267   delta = lgl->opts->synclsint.val;
10268   if (lgl->stats->sync.cls.consumed.calls) {
10269     rate = 100*lgl->stats->sync.cls.consumed.tried;
10270     rate /= lgl->stats->sync.cls.consumed.calls;
10271     LOG (SCL, "syncls tried/calls = %lld/%lld = %d%%",
10272       (LGLL) lgl->stats->sync.cls.consumed.tried,
10273       (LGLL) lgl->stats->sync.cls.consumed.calls,
10274       rate);
10275     if (rate) delta /= rate;
10276   }
10277   lgl->limits->sync.confs = lgl->stats->confs + delta;
10278   lgl->stats->sync.cls.consumed.calls++;
10279   consumed = 0;
10280 RESTART:
10281   lgl->cbs->cls.consume.fun (lgl->cbs->cls.consume.state, &cls, &glue);
10282   if (!cls) return 1;
10283   lgl->stats->sync.cls.consumed.tried++;
10284   LOGCLS (SCL, cls, "trying to import external clause");
10285   assert (lglmtstk (&lgl->clause));
10286   maxlevel = nonfalse = numtrue = 0;
10287 #ifndef NDEBUG
10288   for (p = cls; (elit = *p); p++) {
10289     ilit = lglimport (lgl, elit);
10290     if (abs (ilit) <= 1) continue;
10291     assert (!lglmarked (lgl, ilit));
10292   }
10293 #endif
10294   for (p = cls; (elit = *p); p++) {
10295     erepr = lglerepr (lgl, elit);
10296     if (lglelitblockingoreliminated (lgl, erepr)) break;
10297     ilit = lglimport (lgl, erepr);
10298     if (!ilit) break;
10299     if (ilit == 1) break;
10300     if (ilit == -1) continue;
10301     tmp = lglifixed (lgl, ilit);
10302     if (tmp > 0) break;
10303     if (tmp < 0) continue;
10304     tmp = lglmarked (lgl, ilit);
10305     if (tmp > 0) continue;
10306     if (tmp < 0) break;
10307     lglpushstk (lgl, &lgl->clause, ilit);
10308     lglmark (lgl, ilit);
10309     tmp = lglval (lgl, ilit);
10310     if (tmp > 0) numtrue++;
10311     else if (!tmp) nonfalse++;
10312     else if ((level = lglevel (lgl, ilit)) > maxlevel) maxlevel = level;
10313   }
10314   res = 1;
10315   if (!elit && lglsynclsexist (lgl)) elit = INT_MAX;
10316   for (p = lgl->clause.start; p < lgl->clause.top; p++)
10317     lglunmark (lgl, *p);
10318   if (elit) goto DONE;
10319   len = lglcntstk (&lgl->clause);
10320   if (!numtrue && nonfalse <= 1) {
10321     if (len <= 1 || maxlevel <= 1) level = 0;
10322     else {
10323       level = 0;
10324       for (p = lgl->clause.start; p < lgl->clause.top; p++) {
10325         ilit = *p;
10326         tmp = lglval (lgl, ilit);
10327         assert (tmp <= 0);
10328         if (!tmp) continue;
10329         tmp = lglevel (lgl, ilit);
10330         if (tmp < maxlevel && tmp > level) level = tmp;
10331       }
10332     }
10333     if (level < lgl->level) {
10334       LOG (SCL, "importing clause requires to backtrack to level %d", level);
10335       lglbacktrack (lgl, level);
10336     }
10337   }
10338   lglpushstk (lgl, &lgl->clause, 0);
10339   newglue = glue;
10340 #if 0
10341   if (len > 3 && glue <= lgl->opts->gluekeep.val)
10342     newglue = lgl->opts->gluekeep.val + 1;
10343 #endif
10344   LOGCLS (SCL, lgl->clause.start,
10345     "successfully imported as glue %d redundant glue %d length %d clause",
10346     newglue, glue, len);
10347   lgl->stats->sync.cls.consumed.actual++;
10348   lgldrupligaddcls (lgl, REDCS);
10349   lgladdcls (lgl, REDCS, newglue, !numtrue);
10350   consumed++;
10351   if (lgl->mt) res = 0;
10352   else res = lglbcpsearch (lgl);
10353 DONE:
10354   lglclnstk (&lgl->clause);
10355   if (res && lgl->opts->synclsall.val) goto RESTART;
10356   if (lgl->cbs->cls.consumed.fun)
10357     lgl->cbs->cls.consumed.fun (lgl->cbs->cls.consumed.state, consumed);
10358   return res;
10359 }
10360
10361 static int lglprbpull (LGL * lgl, int lit, int probe) {
10362   AVar * av;
10363   assert (lgl->level == 1);
10364   av = lglavar (lgl, lit);
10365   if (av->mark) return 0;
10366   if (!lglevel (lgl, lit)) return 0;
10367   assert (lglevel (lgl, lit) == 1);
10368   av->mark = 1;
10369   lglpushstk (lgl, &lgl->seen, -lit);
10370   LOG (3, "pulled in literal %d during probing analysis", -lit);
10371   return 1;
10372 }
10373
10374 static int lglprbana (LGL * lgl, int probe) {
10375   int open, lit, r0, r1, tag, red, other, res, * p, * rsn;
10376   assert (lgl->level == 1);
10377   assert (lgl->conf.lit);
10378   assert (lglmtstk (&lgl->seen));
10379   lit = lgl->conf.lit;
10380   r0 = lgl->conf.rsn[0], r1 = lgl->conf.rsn[1];
10381   open = lglprbpull (lgl, lit, probe);
10382   LOG (2, "starting probing analysis with reason of literal %d", lit);
10383   for (;;) {
10384     assert (lglevel (lgl, lit) == 1);
10385     tag = r0 & MASKCS;
10386     if (tag == BINCS || tag == TRNCS) {
10387       other = r0 >> RMSHFT;
10388       if (lglprbpull (lgl, other, probe)) open++;
10389       if (tag == TRNCS && lglprbpull (lgl, r1, probe)) open++;
10390     } else {
10391       assert (tag == LRGCS);
10392       red = r0 & REDCS;
10393       p = lglidx2lits (lgl, red, r1);
10394       while ((other = *p++)) open += lglprbpull (lgl, other, probe);
10395     }
10396     LOG (3, "open %d antecedents in probing analysis", open-1);
10397     assert (open > 0);
10398     while (!lglmarked (lgl, lit = lglpopstk (&lgl->trail)))
10399       lglunassign (lgl, lit);
10400     lglunassign (lgl, lit);
10401     if (!--open) { res = lit; break; }
10402     LOG (2, "analyzing reason of literal %d in probing analysis next", lit);
10403     rsn = lglrsn (lgl, lit);
10404     r0 = rsn[0], r1 = rsn[1];
10405   }
10406   assert (res);
10407   if (res == probe)
10408     LOG (2, "probing analysis returns the probe %d as 1st UIP", probe);
10409   else
10410     LOG (2, "probing analysis returns different 1st UIP %d and not probe %d",
10411          res, probe);
10412   lglpopnunmarkstk (lgl, &lgl->seen);
10413   return res;
10414 }
10415
10416 static int lglederef (LGL * lgl, int elit) {
10417   int ilit, res;
10418   Ext * ext;
10419   assert (elit);
10420   if (abs (elit) > lgl->maxext) return -1;
10421   ext = lglelit2ext (lgl, elit);
10422   if (!(res = ext->val)) {
10423     assert (!ext->equiv);
10424     ilit = ext->repr;
10425     res = ilit ? lglcval (lgl, ilit) : -1;
10426   }
10427   if (elit < 0) res = -res;
10428   return res;
10429 }
10430
10431 static int lgldecomp (LGL *); // TODO move
10432
10433 static int lglhasbin (LGL * lgl, int a, int b) {
10434   const int * w, * eow, * p;
10435   int blit, tag, other;
10436   HTS * ha, * hb;
10437   ha = lglhts (lgl, a);
10438   hb = lglhts (lgl, b);
10439   if (hb->count < ha->count) {
10440     SWAP (int, a, b); SWAP (HTS *, ha, hb);
10441   }
10442   w = lglhts2wchs (lgl, ha);
10443   eow = w + ha->count;
10444   for (p = w; p < eow; p++) {
10445     blit = *p;
10446     tag = blit & MASKCS;
10447     if (tag == OCCS) continue;
10448     if (tag == TRNCS || tag == LRGCS) { p++; continue; }
10449     assert (tag == BINCS);
10450     other = blit >> RMSHFT;
10451     if (other == b) return 1;
10452   }
10453   return 0;
10454 }
10455
10456 static void lglwrkinit (LGL * lgl, int posonly, int fifo) {
10457   int size, lit;
10458   NEW (lgl->wrk, 1);
10459   lgl->wrk->fifo = fifo;
10460   size = lgl->wrk->size = lgl->nvars;
10461   if (posonly) {
10462     NEW (lgl->wrk->pos, size);
10463     lgl->wrk->posonly = 1;
10464   } else {
10465     NEW (lgl->wrk->pos, 2*size);
10466     lgl->wrk->pos += size;
10467     for (lit = -size + 1; lit < -1; lit++) lgl->wrk->pos[lit] = -1;
10468   }
10469   for (lit = 2; lit < size; lit++) lgl->wrk->pos[lit] = -1;
10470 }
10471
10472 static void lglwrkreset (LGL * lgl) {
10473   lglrelstk (lgl, &lgl->wrk->queue);
10474   if (lgl->wrk->posonly) DEL (lgl->wrk->pos, lgl->wrk->size);
10475   else {
10476     lgl->wrk->pos -= lgl->wrk->size;
10477     DEL (lgl->wrk->pos, 2*lgl->wrk->size);
10478   }
10479   DEL (lgl->wrk, 1);
10480 }
10481
10482 static void lglwrkcompact (LGL * lgl) {
10483   int i, j = 0, lit, tail = lglcntstk (&lgl->wrk->queue);
10484   for (i = lgl->wrk->head; i < tail; i++) {
10485     lit = lgl->wrk->queue.start[i];
10486     if (!lit) continue;
10487     assert (!lgl->wrk->posonly || 1 < lit);
10488     assert (1 < abs (lit) && abs (lit) < lgl->wrk->size);
10489     assert (lgl->wrk->pos[lit] == i);
10490     if (!lglisfree (lgl, lit)) {
10491       lgl->wrk->pos[lit] = -1;
10492       assert (lgl->wrk->count > 0);
10493       lgl->wrk->count--;
10494     } else {
10495       lgl->wrk->queue.start[j] = lit;
10496       lgl->wrk->pos[lit] = j++;
10497     }
10498   }
10499   lglrststk (&lgl->wrk->queue, j);
10500   lgl->wrk->head = 0;
10501 }
10502
10503 static int lglwrktouched (LGL * lgl, int lit) {
10504   if (lgl->wrk->posonly) lit = abs (lit);
10505   return lgl->wrk->pos[lit] >= 0;
10506 }
10507
10508 static int lglwrktouch (LGL * lgl, int lit) {
10509   int tail, pos;
10510   if (!lglisfree (lgl, lit)) return 1;
10511   if (lgl->donotsched) {
10512     if (lgl->cgrclosing && lglavar (lgl, lit)->donotcgrcls) return 1;
10513     if (lgl->ternresing && lglavar (lgl, lit)->donoternres) return 1;
10514     if (lgl->simpleprobing && lglavar (lgl, lit)->donotsimpleprobe) return 1;
10515   }
10516   if (lgl->wrk->posonly) lit = abs (lit);
10517   tail = lglcntstk (&lgl->wrk->queue);
10518   LOG (4, "work touch %d", lit);
10519   if ((pos = lgl->wrk->pos[lit]) >= 0) {
10520     assert (lgl->wrk->queue.start[pos] == lit);
10521     lgl->wrk->queue.start[pos] = 0;
10522   }
10523   lgl->wrk->count++;
10524   assert (lgl->wrk->count > 0);
10525   lgl->wrk->pos[lit] = tail;
10526   lglpushstk (lgl, &lgl->wrk->queue, lit);
10527   if (tail/2 > lgl->wrk->count) lglwrkcompact (lgl);
10528   return 1;
10529 }
10530
10531 static int lglwrkdeq (LGL * lgl) {
10532   int res, pos;
10533   while ((pos = lgl->wrk->head) < lglcntstk (&lgl->wrk->queue)) {
10534     lgl->wrk->head++;
10535     res = lgl->wrk->queue.start[pos];
10536     if (!res) continue;
10537     lgl->wrk->queue.start[pos] = 0;
10538     assert (lgl->wrk->count > 0);
10539     lgl->wrk->count--;
10540     assert (lgl->wrk->pos[res] == pos);
10541     lgl->wrk->pos[res] = -1;
10542     if (lglisfree (lgl, res)) return res;
10543   }
10544   return 0;
10545 }
10546
10547 static int lglwrkpop (LGL * lgl) {
10548   int res;
10549   while (lglcntstk (&lgl->wrk->queue) > lgl->wrk->head) {
10550     res = lglpopstk (&lgl->wrk->queue);
10551     if (!res) continue;
10552 #ifndef NDEBUG
10553     {
10554       int pos = lglcntstk (&lgl->wrk->queue);
10555       assert (lgl->wrk->pos[res] == pos);
10556     }
10557 #endif
10558     lgl->wrk->pos[res] = -1;
10559     if (lglisfree (lgl, res)) return res;
10560   }
10561   return 0;
10562 }
10563
10564 static int lglwrknext (LGL * lgl) {
10565   return lgl->wrk->fifo ? lglwrkdeq (lgl) : lglwrkpop (lgl);
10566 }
10567
10568 static int lglrandlitrav (LGL * lgl, int (*fun)(LGL*,int lit)) {
10569   int delta, mod, prev, first, ulit, count;
10570   if (lgl->nvars < 2) return 0;
10571   first = mod = 2*lgl->nvars;
10572   ulit = lglrand (lgl) % mod;
10573   delta = lglrand (lgl) % mod;
10574   if (!delta) delta++;
10575   while (lglgcd (delta, mod) > 1)
10576     if (++delta == mod) delta = 1;
10577   count = mod;
10578   LOG (2,
10579     "random literal traversal start %d delta %d mod %d",
10580      ulit, delta, mod);
10581   for (;;) {
10582     count--;
10583     assert (count >= 0);
10584     if (ulit >= 4 && !fun (lgl, lglilit (ulit))) return 0;
10585     prev = ulit;
10586     ulit += delta;
10587     if (ulit >= mod) ulit -= mod;
10588     if (ulit == first) { assert (!count); break; }
10589     if (first == mod) first = prev;
10590   }
10591   return 1;
10592 }
10593
10594 static void lglsimpleprobeinit (LGL * lgl) {
10595   int idx, rem = 0, ret = 0;
10596   for (idx = 2; idx < lgl->nvars; idx++) lgl->avars[idx].equiv = 0;
10597   for (idx = 2; idx < lgl->nvars; idx++) {
10598     if (!lglisfree (lgl, idx)) continue;
10599     if (lglavar (lgl, idx)->donotsimpleprobe) ret++; else rem++;
10600   }
10601   if (!rem) {
10602     ret = 0;
10603     for (idx = 2; idx < lgl->nvars; idx++) {
10604       if (!lglisfree (lgl, idx)) continue;
10605       lglavar (lgl, idx)->donotsimpleprobe = 0;
10606       rem++;
10607     }
10608   }
10609   if (!ret)
10610     lglprt (lgl, 1, "[simpleprobe-%d] all %d free variables schedulable",
10611             lgl->stats->prb.simple.count, rem);
10612   else
10613     lglprt (lgl, 1,
10614       "[simpleprobe-%d] %d schedulable variables %.0f%%",
10615       lgl->stats->prb.simple.count, rem, lglpcnt (rem, lglrem (lgl)));
10616   lglwrkinit (lgl, 0, 1);
10617   assert (!lgl->donotsched), lgl->donotsched = 1;
10618   lglrandlitrav (lgl, lglwrktouch);
10619   assert (lgl->donotsched), lgl->donotsched = 0;
10620   assert (lgl->opts->prbsimple.val);
10621   lglchkirrstats (lgl);
10622 }
10623
10624 static void lglsimpleprobereset (LGL * lgl, int nvars) {
10625   const int * p;
10626   int idx;
10627   lglrelstk (lgl, &lgl->sprb->units);
10628   lglrelstk (lgl, &lgl->sprb->impls);
10629   lglrelstk (lgl, &lgl->sprb->eqs);
10630   for (idx = 2; idx < lgl->nvars; idx++) lgl->avars[idx].donotsimpleprobe = 1;
10631   for (p = lgl->wrk->queue.start; p < lgl->wrk->queue.top; p++)
10632     lgl->avars[abs (*p)].donotsimpleprobe = 0;
10633   lglwrkreset (lgl);
10634   lglrelstk (lgl, &lgl->sprb->counted);
10635   lglrelstk (lgl, &lgl->sprb->marked);
10636   assert (nvars == lgl->nvars);
10637   lgl->sprb->spes -= nvars;
10638   DEL (lgl->sprb->spes, 2*nvars);
10639 }
10640
10641 static int lglflush (LGL *);
10642 static void lgldense (LGL *, int);
10643 static void lglsparse (LGL *);
10644
10645 static int lglsimpleprobeunits (LGL * lgl) {
10646   const int * p;
10647   int lit, res;
10648   Val val;
10649   res = 0;
10650   lglchkirrstats (lgl);
10651   for (p = lgl->sprb->units.start; !lgl->mt && p < lgl->sprb->units.top; p++) {
10652     lit = *p;
10653     val = lglval (lgl, lit);
10654     if (val > 0) continue;
10655     lgl->stats->prb.simple.failed++;
10656     if (val < 0) {
10657       if (lgl->opts->drup.val) lgldrupclsarg (lgl, lit, 0);
10658       LOG (1, "inconsistent unit %d", lit);
10659       lgl->mt = 1;
10660     } else {
10661       lglunit (lgl, lit);
10662       res++;
10663       if (!lglflush (lgl)) {
10664         LOG (1, "propagating simple HBR unit %d results in conflict", lit);
10665         lgl->mt = 1;
10666       }
10667     }
10668   }
10669   return res;
10670 }
10671
10672 static int lglsimpleprobeimpls (LGL * lgl) {
10673   int a, b, res;
10674   res = 0;
10675   while (!lglmtstk (&lgl->sprb->impls)) {
10676     b = lglpopstk (&lgl->sprb->impls);
10677     a = lglpopstk (&lgl->sprb->impls);
10678     if (lglval (lgl, a) || lglval (lgl, b)) continue;
10679     if (lglhasbin (lgl, a, b)) continue;
10680     LOG (2, "adding previously detected hyper binary resolvent %d %d", a, b);
10681     if (lgl->opts->drup.val) lgldrupclsarg (lgl, a, b, 0);
10682 #ifndef NLGLPICOSAT
10683     lglpicosatchkclsarg (lgl, a, b, 0);
10684 #endif
10685     res++;
10686     lgl->stats->hbr.cnt++;
10687     lgl->stats->hbr.simple++;
10688     (void) lglwchbin (lgl, a, b, REDCS);
10689     (void) lglwchbin (lgl, b, a, REDCS);
10690     lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
10691     lglwrktouch (lgl, -a);
10692     lglwrktouch (lgl, -b);
10693     if (!lglhasbin (lgl, -a, -b)) continue;
10694     LOG (2, "found equivalent literals %d and %d", -a, b);
10695     lglpushstk (lgl, &lgl->sprb->eqs, -a);
10696     lglpushstk (lgl, &lgl->sprb->eqs, b);
10697   }
10698   return res;
10699 }
10700
10701 static int lglhasonlybin (LGL * lgl, int lit, int other) {
10702   HTS * hts = lglhts (lgl, lit);
10703   const int * w;
10704   int blit;
10705   if (hts->count != 1) return 0;
10706   w = lglhts2wchs (lgl, hts);
10707   blit = *w;
10708   if ((blit & MASKCS) != BINCS) return 0;
10709   return (blit >> RMSHFT) == other;
10710 }
10711
10712 static int lglsimpleprobemerged (LGL * lgl, int a, int b) {
10713   return lglhasonlybin (lgl, -a, b) && lglhasonlybin (lgl, -b, a);
10714 }
10715
10716 static int lglflushclauses (LGL * lgl, int lit);
10717
10718 static void lglsimpleprobeclscp (LGL * lgl, int nonrepr, int repr, Stk * stk) {
10719   int blit, tag, red, other, other2, lidx, count, found, start, trivial;
10720   const int * p, * w, * eow, * c, * q;
10721   HTS * hts = lglhts (lgl, nonrepr);
10722   assert (abs (repr) < abs (nonrepr));
10723   w = lglhts2wchs (lgl, hts);
10724   eow = w + hts->count;
10725   count = 0;
10726   for (p = w; p < eow; p++) {
10727     INCSTEPS (prb.simple.steps);
10728     blit = *p;
10729     tag = blit & MASKCS;
10730     if (tag == TRNCS || tag == LRGCS) p++;
10731     if (tag == LRGCS) continue;
10732     start = lglcntstk (stk);
10733     trivial = 0;
10734     red = blit & REDCS;
10735     lglpushstk (lgl, stk, red);
10736     lglpushstk (lgl, stk, repr);
10737     if (tag == BINCS || tag == TRNCS) {
10738       other = blit >> RMSHFT;
10739       if (other == -repr) trivial = 1;
10740       else if (other != repr) lglpushstk (lgl, stk, other);
10741       if (tag == TRNCS) {
10742         other2 = *p;
10743         if (other2 == -repr) trivial = 1;
10744         else if (other2 != repr) lglpushstk (lgl, stk, other2);
10745       }
10746     } else {
10747       assert (tag == OCCS);
10748       lidx = blit >> RMSHFT;
10749       c = lglidx2lits (lgl, red, lidx);
10750       found = 0;
10751       for (q = c; !trivial && (other = *q); q++) {
10752         if (other >= NOTALIT) trivial = 1;
10753         else if (other == nonrepr) found++;
10754         else if (other == -repr) trivial = 1;
10755         else if (other != repr) lglpushstk (lgl, stk, other);
10756       }
10757       assert (trivial || found);
10758     }
10759     if (trivial) lglrststk (stk, start);
10760     else lglpushstk (lgl, stk, 0), count++;
10761   }
10762   LOG (2, "copied %d clauses with %d replacing %d by %d",
10763        count, nonrepr, nonrepr, repr);
10764 }
10765
10766 static int lglsimpleprobebinexists (LGL * lgl, int a, int b) {
10767   const int * p, * w, * eow;
10768   int blit, tag, red, other;
10769   HTS * hts;
10770   hts = lglhts (lgl, a);
10771   w = lglhts2wchs (lgl, hts);
10772   eow = w + hts->count;
10773   for (p = w; p < eow; p++) {
10774     blit = *p;
10775     tag = blit & MASKCS;
10776     if (tag == TRNCS || tag == LRGCS) p++;
10777     if (tag != BINCS) continue;
10778     red = blit & REDCS;
10779     if (red) continue;
10780     other = blit >> RMSHFT;
10781     if (other == b) return 1;
10782   }
10783   return 0;
10784 }
10785
10786 static int lglsimpleprobetrnexists (LGL * lgl, int a, int b, int c) {
10787   int blit, tag, red, other, other2;
10788   const int * p, * w, * eow;
10789   HTS * hts;
10790   hts = lglhts (lgl, a);
10791   w = lglhts2wchs (lgl, hts);
10792   eow = w + hts->count;
10793   for (p = w; p < eow; p++) {
10794     blit = *p;
10795     tag = blit & MASKCS;
10796     if (tag == TRNCS || tag == LRGCS) p++;
10797     red = blit & REDCS;
10798     if (red) continue;
10799     other = blit >> RMSHFT;
10800     if (tag == BINCS) {
10801       if (other == b) return 1;
10802       if (other == c) return 1;
10803     } else if (tag == TRNCS) {
10804       other2 = *p;
10805       if (other == b && other2 == c) return 1;
10806       if (other == c && other2 == b) return 1;
10807     }
10808   }
10809   return 0;
10810 }
10811
10812 static int lglsimpleprobelrgexists (LGL * lgl, int a) {
10813   int blit, tag, red, other, other2, lidx, res;
10814   const int * p, * w, * eow, * c, * q;
10815   HTS * hts;
10816   for (p = lgl->clause.start; p + 1 < lgl->clause.top; p++) {
10817     other = *p;
10818     assert (!lglsignedmarked (lgl, other));
10819     lglsignedmark (lgl, other);
10820   }
10821   assert (lglsignedmarked (lgl, a));
10822   hts = lglhts (lgl, a);
10823   w = lglhts2wchs (lgl, hts);
10824   eow = w + hts->count;
10825   res = 0;
10826   for (p = w; !res && p < eow; p++) {
10827     blit = *p;
10828     tag = blit & MASKCS;
10829     if (tag == TRNCS || tag == LRGCS) p++;
10830     red = blit & REDCS;
10831     if (red || tag == LRGCS) continue;
10832     other = blit >> RMSHFT;
10833     if (tag == BINCS) {
10834       res = lglsignedmarked (lgl, other);
10835     } else if (tag == TRNCS) {
10836       other2 = *p;
10837       res = lglsignedmarked (lgl, other) && lglsignedmarked (lgl, other2);
10838     } else {
10839       assert (tag == OCCS);
10840       lidx = other;
10841       c = lglidx2lits (lgl, 0, lidx);
10842       for (q = c; (other = *q); q++)
10843         if (!lglsignedmarked (lgl, other)) break;
10844       res = !other;
10845     }
10846   }
10847   for (p = lgl->clause.start; p + 1 < lgl->clause.top; p++) 
10848     lglunmark (lgl, *p);
10849   return res;
10850 }
10851
10852 static int lglsimpleprobeclausexists (LGL * lgl) {
10853   int len = lglcntstk (&lgl->clause) - 1, a, b, c, * p, * s, res;
10854   assert (len >= 0);
10855   assert (!lgl->clause.top[-1]);
10856   s = lgl->clause.start;
10857   for (p = s + 1; p + 1 < lgl->clause.top; p++)
10858     if (lglhts (lgl, *s)->count > lglhts (lgl, *p)->count)
10859       SWAP (int, *s, *p);
10860   a = lgl->clause.start[0];
10861   if (len == 2) {
10862     b = lgl->clause.start[1];
10863     res = lglsimpleprobebinexists (lgl, a, b);
10864   } else if (len == 3) {
10865     b = lgl->clause.start[1];
10866     c = lgl->clause.start[2];
10867     res = lglsimpleprobetrnexists (lgl, a, b, c);
10868   } else if (len > 3)
10869     res = lglsimpleprobelrgexists (lgl, a);
10870   else res = 0;
10871   if (res) LOG (2, "will not add already existing clause");
10872   return res;
10873 }
10874
10875 static void lglsimpleprobeaddclausesonstack (LGL * lgl, Stk * stk) {
10876   int count, red, lit, size;
10877   const int * c, * p, * q;
10878   count = 0;
10879   for (c = stk->start; c < stk->top; c = p + 1) {
10880     red = *(p = c);
10881     if (p[1] == REMOVED) {
10882       p++;
10883       while (p + 1 < stk->top && p[1] == REMOVED) p++;
10884       continue;
10885     }
10886     assert (!red || red == REDCS);
10887     assert (lglmtstk (&lgl->clause));
10888     do {
10889       lit = *++p;
10890       lglpushstk (lgl, &lgl->clause, lit);
10891     } while (lit);
10892     if (!lglsimpcls (lgl) && !lglsimpleprobeclausexists (lgl)) {
10893       if (lgl->opts->drup.val) lgldrupcls (lgl);
10894 #ifndef NLGLPICOSAT
10895       lglpicosatchkcls (lgl);
10896 #endif
10897       q = lgl->clause.start;
10898       size = lglcntstk (&lgl->clause);
10899       assert (size > 0);
10900       assert (!q[size-1]);
10901       size--;
10902       if (size > 2 && lgl->opts->prbsimple.val >= 3)
10903         while ((lit = *q++))
10904           lglwrktouch (lgl, lit);
10905       if (size == 2 && lgl->opts->prbsimple.val >= 2)
10906         lglwrktouch (lgl, -q[0]),
10907         lglwrktouch (lgl, -q[1]);
10908       lgldrupligaddcls (lgl, REDCS);
10909       lgladdcls (lgl, red, 0, 1);
10910       count++;
10911     }
10912     lglclnstk (&lgl->clause);
10913     if (!lglflush (lgl)) break;
10914   }
10915   LOG (2, "added %d non-trivial clauses", count);
10916 }
10917
10918 static void lglsimpleprobeaddprbincls (LGL * lgl, int a, int b) {
10919   assert (lgl->probing);
10920   assert (lglmtstk (&lgl->clause));
10921   assert (abs (a) != abs (b));
10922   assert (!lglval (lgl, a));
10923   assert (!lglval (lgl, b));
10924   lglpushstk (lgl, &lgl->clause, a);
10925   lglpushstk (lgl, &lgl->clause, b);
10926   lglpushstk (lgl, &lgl->clause, 0);
10927   if (!lglsimpleprobeclausexists (lgl)) {
10928     LOG (2, "added simple probing connecting binary clause", a, b);
10929     if (lgl->opts->drup.val) lgldrupcls (lgl);
10930 #ifndef NLGLPICOSAT
10931     lglpicosatchkcls (lgl);
10932 #endif
10933     lgldrupligaddcls (lgl, REDCS);
10934     lgladdcls (lgl, 0, 0, 1);
10935   }
10936   lglclnstk (&lgl->clause);
10937 }
10938
10939 static int lglcmpilit (int * a, int * b) {
10940   int res, l = *a, k = *b;
10941   if ((res = abs (l) - abs (k))) return res;
10942   return l - k;
10943 }
10944
10945 static int lglcmpcls (LGL * lgl, const int * c, const int * d) {
10946   const int * p, * q;
10947   for (p = c, q = d; *p && *q == *p; p++, q++)
10948     ;
10949   return *p - *q;
10950 }
10951
10952 static int lglcmpsz (LGL * lgl, const int * start, PSz * p, PSz * q) {
10953   const int * c, * d;
10954   int res;
10955   if ((res = p->size - q->size)) return res;
10956   c = start + p->pos, d = start + q->pos;
10957   if ((res = lglcmpcls (lgl, c, d))) return res;
10958   if ((res = c[-1] - d[-1])) return res;
10959   return p->pos - q->pos;
10960 }
10961
10962 #define LGLCMPSZ(A,B) (lglcmpsz(lgl, start, (A), (B)))
10963
10964 static void lglrmdupclsonstack (LGL * lgl, Stk * stk, Stk * sort) {
10965   int * start, * c, * p, * d, pos, size, i;
10966   PSz * ps;
10967   lglclnstk (sort);
10968   start = stk->start;
10969   for (c = start; c < stk->top; c = p + 1) {
10970     c++;
10971     assert (c < stk->top);
10972     pos = c - start;
10973     size = 0;
10974     for (p = c; *p; p++) size++;
10975     SORT (int, c, size, lglcmpilit);
10976     lglpushstk (lgl, sort, pos);
10977     lglpushstk (lgl, sort, size);
10978   }
10979   size = lglcntstk (sort)/2;
10980   if (size <= 1) return;
10981   ps = (PSz *) sort->start;
10982   SORT (PSz, ps, size, LGLCMPSZ);
10983   for (i = 1; i < size; i++) {
10984     if (ps[i-1].size != ps[i].size) continue;
10985     c = stk->start + ps[i-1].pos;
10986     d = stk->start + ps[i].pos;
10987     if (lglcmpcls (lgl, c, d)) continue;
10988     LOGCLS (4, d, "not copying duplicate %s clause", lglred2str (d[-1]));
10989     while (*d) *d++ = REMOVED;
10990     *d = REMOVED;
10991   }
10992 }
10993
10994 static void lglsimpleprobemerge (LGL * lgl, int repr, int nonrepr) {
10995   Val valrepr, valnonrepr;
10996   Stk stk, sort;
10997   int unit;
10998   lglchkirrstats (lgl);
10999   lgl->stats->prb.simple.eqs++;
11000   assert (abs (repr) < abs (nonrepr));
11001   lglavar (lgl, nonrepr)->equiv = 1;
11002   CLR (stk); CLR (sort);
11003   lglsimpleprobeclscp (lgl, nonrepr, repr, &stk);
11004   lglsimpleprobeclscp (lgl, -nonrepr, -repr, &stk);
11005   lglflushclauses (lgl, nonrepr);
11006   lglflushclauses (lgl, -nonrepr);
11007   lglrmdupclsonstack (lgl, &stk, &sort);
11008   lglsimpleprobeaddclausesonstack (lgl, &stk);
11009   lglrelstk (lgl, &sort);
11010   lglrelstk (lgl, &stk);
11011   if (lgl->mt) return;
11012   valrepr = lglval (lgl, repr);
11013   valnonrepr = lglval (lgl, nonrepr);
11014   if (valrepr && valnonrepr == valrepr) return;
11015   if (valrepr && valrepr == -valrepr) {
11016     LOG (1, "equality between %d and %d became inconsistent", repr, nonrepr);
11017     lgl->mt = 1;
11018     return;
11019   }
11020   if (valrepr && !valnonrepr) unit = valrepr < 0 ? -nonrepr : nonrepr;
11021   else if (!valrepr && valnonrepr) unit = valnonrepr < 0 ? -repr : repr;
11022   else unit = 0, assert (!valrepr), assert (!valnonrepr);
11023   if (unit) {
11024     LOG (1, "new unit %d from equality between %d and %d", unit, repr, nonrepr);
11025     lglunit (lgl, unit);
11026     (void) lglflush (lgl);
11027   } else lglsimpleprobeaddprbincls (lgl, repr, -nonrepr),
11028          lglsimpleprobeaddprbincls (lgl, -repr, nonrepr);
11029   lglchkirrstats (lgl);
11030 }
11031
11032 static int lglsimpleprobeqs (LGL * lgl) {
11033   int a, b, res;
11034   res = 0;
11035   while (!lgl->mt && !lglmtstk (&lgl->sprb->eqs)) {
11036     a = lglpopstk (&lgl->sprb->eqs);
11037     b = lglpopstk (&lgl->sprb->eqs);
11038     if (lglval (lgl, a)) continue;
11039     assert (!lglval (lgl, b));
11040     assert (abs (a) != abs (b));
11041     if (lglsimpleprobemerged (lgl, a, b)) continue;
11042     if (abs (b) < abs (a)) SWAP (int, a, b);
11043     lglsimpleprobemerge (lgl, a, b);
11044     res++;
11045   }
11046   return res;
11047 }
11048
11049 static SPE * lglspe (LGL * lgl, int lit) {
11050   assert (2 <= abs (lit) && abs (lit) < lgl->nvars);
11051   return lgl->sprb->spes + lit;
11052 }
11053
11054 static void lglsimpleprobehbr (LGL * lgl, int touched, const int * c) {
11055   int blit, tag, lit, other, count, val, maxcount, rem, first, second;
11056   const int * p, * q, * w, * eow;
11057   unsigned sum, tmp;
11058   SPE * spe;
11059   HTS * hts;
11060   first = second = count = sum = 0;
11061   for (p = c; (lit = *p); p++) {
11062     if (lglwrktouched (lgl, lit)) return;
11063     if ((val = lglval (lgl, lit)) > 0) return;
11064     if (val < 0) continue;
11065     if (!first) first = lit;
11066     else if (!second) second = lit;
11067     sum += (unsigned) lit;
11068     count++;
11069   }
11070   if (count == 2) {
11071     assert (first && second);
11072     if (lglhasbin (lgl, -first, -second)) {
11073       LOG (2, "found equivalent literals %d and %d", -first, second);
11074       lglpushstk (lgl, &lgl->sprb->eqs, -first);
11075       lglpushstk (lgl, &lgl->sprb->eqs, second);
11076       goto DONE;
11077     }
11078   }
11079   rem = count;
11080   maxcount = 0;
11081   assert (lglmtstk (&lgl->sprb->counted));
11082   for (p = c; (lit = *p); p++) {
11083     if (INCSTEPS (prb.simple.steps) >= lgl->limits->prb.steps) goto DONE;
11084     val = lglval (lgl, lit);
11085     assert (val <= 0);
11086     if (val) continue;
11087     hts = lglhts (lgl, -lit);
11088     w = lglhts2wchs (lgl, hts);
11089     eow = w + hts->count;
11090     assert (lglmtstk (&lgl->sprb->marked));
11091     for (q = w; q < eow; q++) {
11092       if (INCSTEPS (prb.simple.steps) >= lgl->limits->prb.steps) goto DONE;
11093       blit = *q;
11094       tag = blit & MASKCS;
11095       if (tag == TRNCS || tag == LRGCS) q++;
11096       if (tag != BINCS) continue;
11097       other = blit >> RMSHFT;
11098       val = lglval (lgl, other);
11099       assert (val >= 0);
11100       if (val) continue;
11101       if ((spe = lglspe (lgl, other))->mark) continue;
11102       if (lglspe (lgl, -other)->mark) {
11103         LOG (2, "unit %d through very simple hyper binary resolution", -lit);
11104         lglpushstk (lgl, &lgl->sprb->units, -lit);
11105         goto DONE;
11106       }
11107       if (!spe->count) lglpushstk (lgl, &lgl->sprb->counted, other);
11108       spe->sum += (unsigned) lit;
11109       spe->count++;
11110       spe->mark = 1;
11111       lglpushstk (lgl, &lgl->sprb->marked, other);
11112       if (spe->count > maxcount) maxcount = spe->count;
11113     }
11114     while (!lglmtstk (&lgl->sprb->marked)) {
11115       other = lglpopstk (&lgl->sprb->marked);
11116       spe = lglspe (lgl, other);
11117       assert (spe->mark);
11118       spe->mark = 0;
11119     }
11120     rem--;
11121     assert (maxcount + rem <= count);
11122     if (maxcount + rem + 1 < count) goto DONE;
11123   }
11124   if (count <= 2) goto DONE;
11125   for (q = lgl->sprb->counted.start; q < lgl->sprb->counted.top; q++) {
11126     other = *q;
11127     assert (!lglval (lgl, other));
11128     spe = lglspe (lgl, other);
11129     assert (spe->count <= count);
11130     if (spe->count == count) {
11131       LOG (2, "unit %d through simple hyper binary resolution", other);
11132       lglpushstk (lgl, &lgl->sprb->units, other);
11133     } else if (spe->count + 1 == count) {
11134       tmp = sum - spe->sum;
11135       lit = (int) tmp;
11136       assert (2 <= abs (lit) && abs (lit) < lgl->nvars);
11137       if (abs (lit) != abs (other) && !lglhasbin (lgl, other, lit)) {
11138         LOG (2, "simple hyper binary resolvent %d %d", other, lit);
11139         lglpushstk (lgl, &lgl->sprb->impls, other);
11140         lglpushstk (lgl, &lgl->sprb->impls, lit);
11141       }
11142     }
11143   }
11144   for (p = c; (lit = *p); p++) {
11145     if (lglval (lgl, lit)) continue;
11146     spe = lglspe (lgl, lit);
11147     if (spe->count + 2 != count) continue;
11148     tmp = sum - spe->sum;
11149     tmp -= (unsigned) lit;
11150     other = (int) tmp;
11151     assert (2 <= abs (other) && abs (other) < lgl->nvars);
11152     if (abs (lit) != abs (other) && !lglhasbin (lgl, other, lit)) {
11153       LOG (2, "self-subsuming hyper binary resolvent %d %d", other, lit);
11154       lglpushstk (lgl, &lgl->sprb->impls, other);
11155       lglpushstk (lgl, &lgl->sprb->impls, lit);
11156     }
11157   }
11158 DONE:
11159   while (!lglmtstk (&lgl->sprb->counted)) {
11160     lit = lglpopstk (&lgl->sprb->counted);
11161     spe = lglspe (lgl, lit);
11162     CLRPTR (spe);
11163   }
11164   lglclnstk (&lgl->sprb->marked);
11165 }
11166
11167 static void lglpushnmarkseen (LGL * lgl, int lit) {
11168   lglpushstk (lgl, &lgl->seen, lit);
11169   lglmarkunmarked (lgl, lit);
11170 }
11171
11172 static void lglsignedmarknpushseen (LGL * lgl, int lit) {
11173   lglsignedmark (lgl, lit);
11174   lglpushstk (lgl, &lgl->seen, lit);
11175 }
11176
11177 static void lglsimpleliftmark (LGL * lgl, int root, int level) {
11178   const int * p, * w, * eow;
11179   int blit, tag, other;
11180   HTS * hts;
11181   INCSTEPS (prb.simple.steps);
11182   assert (level > 0);
11183   assert (lglsignedmarked (lgl, -root));
11184   LOG (3, "next simple lifting marking from %d at level %d", root, level);
11185   hts = lglhts (lgl, root);
11186   w = lglhts2wchs (lgl, hts);
11187   eow = w + hts->count;
11188   for (p = w; p < eow; p++) {
11189     blit = *p;
11190     tag = blit & MASKCS;
11191     if (tag == TRNCS || tag == LRGCS) p++;
11192     if (tag != BINCS) continue;
11193     other = blit >> RMSHFT;
11194     if (lglsignedmarked (lgl, other)) continue;
11195     lglsignedmarknpushseen (lgl, other);
11196     LOG (4, "next simple lifting marking from %d at level %d marked %d", 
11197          root, level, other);
11198     if (level > 1) lglsimpleliftmark (lgl, -other, level-1);
11199   }
11200 }
11201
11202 static void lglsimpleliftcollect (LGL * lgl, int root, int start, int level) {
11203   const int * p, * w, * eow;
11204   int blit, tag, other;
11205   HTS * hts;
11206   INCSTEPS (prb.simple.steps);
11207   assert (level > 0);
11208   LOG (3, "next simple lifting collecting from %d at level %d", start, level);
11209   hts = lglhts (lgl, start);
11210   w = lglhts2wchs (lgl, hts);
11211   eow = w + hts->count;
11212   for (p = w; p < eow; p++) {
11213     blit = *p;
11214     tag = blit & MASKCS;
11215     if (tag == TRNCS || tag == LRGCS) p++;
11216     if (tag != BINCS) continue;
11217     other = blit >> RMSHFT;
11218     if (other == -root) continue;
11219     if (lglsignedmarked (lgl, other)) {
11220       LOG (2, "simple lifted unit %d with root %d", other, root);
11221       lglpushstk (lgl, &lgl->sprb->units, other);
11222     } else if (other != root && lglsignedmarked (lgl, -other)) {
11223       LOG (2, "found equivalent literals %d and %d", root, other);
11224       lglpushstk (lgl, &lgl->sprb->eqs, root);
11225       lglpushstk (lgl, &lgl->sprb->eqs, other);
11226     } 
11227     if (level > 1) lglsimpleliftcollect (lgl, root, -other, level-1);
11228   }
11229 }
11230
11231 static void lglsimplelift (LGL * lgl, int root) {
11232   int count, pos, neg;
11233   pos = lglhts (lgl, root)->count;
11234   neg = lglhts (lgl, -root)->count;
11235   if (neg < pos) root = -root;
11236   LOG (2, "next simple lifting %d", root);
11237   assert (lglmtstk (&lgl->seen));
11238   assert (!lglsignedmarked (lgl, -root));
11239   lglsignedmarknpushseen (lgl, -root);
11240   lglsimpleliftmark (lgl, root, lgl->opts->prbsimpleliftdepth.val);
11241   count = lglcntstk (&lgl->seen);
11242   LOG (3, "simple probing lifting marked %d literals for root %d", 
11243        count, root);
11244   if (!count) return;
11245   lglsimpleliftcollect (lgl, root, -root, lgl->opts->prbsimpleliftdepth.val);
11246 #ifndef NLGLOG
11247   {
11248     int units = lglcntstk (&lgl->sprb->units);
11249     int eqs = lglcntstk (&lgl->sprb->eqs);
11250     assert (!(eqs & 1));
11251     eqs >>= 1;
11252     LOG (3, "found %d units through simple lifting for %d", units, root);
11253     LOG (3, "found %d equivalences through simple lifting for %d", eqs, root);
11254   }
11255 #endif
11256   lglpopnunmarkstk (lgl, &lgl->seen);
11257 }
11258
11259 static void lglsimpleprobelit (LGL * lgl, int lit) {
11260   int blit, tag, other, other2, red, lidx, cls[4];
11261   const int * p, * w, * eow, * c;
11262   HTS * hts;
11263   lgl->stats->prb.simple.probed++;
11264   assert (!lglval (lgl, lit));
11265   lglclnstk (&lgl->sprb->units);
11266   lglclnstk (&lgl->sprb->impls);
11267   if (!lglwrktouched (lgl, -lit)) lglsimplelift (lgl, lit);
11268   LOG (2, "next simple probing %d", lit);
11269   hts = lglhts (lgl, lit);
11270   if (!hts->count) return;
11271   w = lglhts2wchs (lgl, hts);
11272   eow = w + hts->count;
11273   for (p = w; p < eow; p++) {
11274     if (INCSTEPS (prb.simple.steps) >= lgl->limits->prb.steps) goto DONE;
11275     blit = *p;
11276     tag = blit & MASKCS;
11277     if (tag == TRNCS || tag == LRGCS) p++;
11278     if (tag == BINCS || tag == LRGCS) continue;
11279     if (tag == TRNCS) {
11280       other = blit >> RMSHFT;
11281       if (lglval (lgl, other)) continue;
11282       other2 = *p;
11283       if (lglval (lgl, other2)) continue;
11284       cls[0] = lit, cls[1] = other, cls[2] = other2, cls[3] = 0;
11285       lglsimpleprobehbr (lgl, lit, cls);
11286     } else {
11287       assert (tag == OCCS);
11288       red = (blit & REDCS);
11289       lidx = (blit >> RMSHFT);
11290       c = lglidx2lits (lgl, red, lidx);
11291       lglsimpleprobehbr (lgl, lit, c);
11292     }
11293   }
11294 DONE:
11295   assert (lglmtstk (&lgl->seen));
11296   lglpopnunmarkstk (lgl, &lgl->seen);
11297 }
11298
11299 static void lglprtsimpleproberem (LGL * lgl) {
11300   int idx, ret = 0, rem = 0;
11301   for (idx = 2; idx < lgl->nvars; idx++) {
11302     if (!lglisfree (lgl, idx)) continue;
11303     if (lglavar (lgl, idx)->donotsimpleprobe) ret++; else rem++;
11304   }
11305   if (rem)
11306     lglprt (lgl, 1,
11307       "[simpleprobe-%d] %d variables remain %.0f%% (%d retained)",
11308       lgl->stats->prb.simple.count, rem, lglpcnt (rem, lglrem (lgl)), ret);
11309   else {
11310     lglprt (lgl, 1, "[simpleprobe-%d] fully completed simple probing",
11311            lgl->stats->prb.simple.count);
11312     for (idx = 2; idx < lgl->nvars; idx++)
11313       lglavar (lgl, idx)->donotsimpleprobe = 0;
11314   }
11315 }
11316
11317 static int lglszpen (LGL * lgl) {
11318   int res = lglceilld (lgl->stats->irr.clauses.cur/lgl->opts->sizepen.val);
11319   if (res < 0) res = 0;
11320   if (res > lgl->opts->sizemaxpen.val) res = lgl->opts->sizemaxpen.val;
11321   return res;
11322 }
11323
11324 #ifndef NLGLYALSAT
11325
11326 static int lglitszpen (LGL * lgl) {
11327   int res = lglceilld (lgl->stats->irr.lits.cur/lgl->opts->sizepen.val);
11328   if (res < 0) res = 0;
11329   if (res > lgl->opts->sizemaxpen.val + 2)
11330     res = lgl->opts->sizemaxpen.val + 2;
11331   return res;
11332 }
11333
11334 #endif
11335
11336 static int64_t lglvisearch (LGL * lgl) {
11337   int64_t res = lgl->stats->visits.search;
11338   assert (res >= lgl->limits->inc.visits);
11339   res -= lgl->limits->inc.visits;
11340   return res;
11341 }
11342
11343 static void lglsetprbsimplelim (LGL * lgl) {
11344   int64_t limit, irrlim;
11345   int pen;
11346   if (lgl->opts->prbsimplertc.val || lgl->opts->prbrtc.val) {
11347     lgl->limits->prb.steps = LLMAX;
11348     lglprt (lgl, 1,
11349       "[simpleprobe-%d] no limit (run to completion)", 
11350       lgl->stats->prb.simple.count);
11351   } else {
11352     limit = (lgl->opts->prbsimplereleff.val*lglvisearch (lgl))/1000;
11353     if (limit < lgl->opts->prbsimplemineff.val) 
11354       limit = lgl->opts->prbsimplemineff.val;
11355     if (lgl->opts->prbsimplemaxeff.val >= 0 &&
11356         limit > lgl->opts->prbsimplemaxeff.val)
11357       limit = lgl->opts->prbsimplemaxeff.val;
11358     if (lgl->stats->prb.simple.count <= 1 &&
11359         lgl->opts->boost.val &&
11360         lgl->opts->prbsimpleboost.val > 1) {
11361       lglprt (lgl, 1,
11362         "[simpleprobe-%d] boosting simple probing limit by %d",
11363         lgl->stats->prb.simple.count, lgl->opts->prbsimpleboost.val);
11364       limit *= lgl->opts->prbsimpleboost.val;
11365     }
11366     limit >>= (pen = lgl->limits->prb.simple.pen + lglszpen (lgl));
11367     irrlim = lgl->stats->irr.clauses.cur/4;
11368     irrlim >>= lgl->limits->simp.pen;
11369     if (lgl->opts->irrlim.val && limit < irrlim) {
11370       limit = irrlim;
11371       lglprt (lgl, 1,
11372         "[simpleprobe-%d] limit %lld based on %d irredundant clauses",
11373         lgl->stats->prb.simple.count,
11374         (LGLL) limit, lgl->stats->irr.clauses.cur);
11375     } else
11376       lglprt (lgl, 1,
11377         "[simpleprobe-%d] limit %lld penalty %d = %d + %d",
11378         lgl->stats->prb.simple.count, (LGLL) limit,
11379         pen, lgl->limits->prb.simple.pen, lglszpen (lgl));
11380     lgl->limits->prb.steps = lgl->stats->prb.simple.steps + limit;
11381   }
11382 }
11383
11384 static int lgldelaying (LGL * lgl, const char * name, int * delptr) {
11385   if (!*delptr) return 0;
11386   *delptr -= 1;
11387   lglprt (lgl, 2,
11388     "[%s-delayed] skipping this scheduled invocation and %d more",
11389     name, *delptr);
11390   return 1;
11391 }
11392
11393 static int lglsimpleprobe (LGL * lgl) {
11394   int deltarem, nunits, hbrs, neqs, oldrem = lglrem (lgl);
11395   int lit, success, nvars;
11396
11397   if (lgldelaying (lgl, "simpleprobe",
11398         &lgl->limits->prb.simple.del.rem)) return 1;
11399
11400   lglstart (lgl, &lgl->times->prb.simple);
11401   lgl->stats->prb.simple.count++;
11402
11403   assert (!lgl->simp && !lgl->probing && !lgl->simpleprobing);
11404   lgl->simp = lgl->probing = lgl->simpleprobing = 1;
11405
11406
11407   NEW (lgl->sprb, 1);
11408
11409   if (lgl->level > 0) lglbacktrack (lgl, 0);
11410   lglgc (lgl);
11411   assert (lgl->frozen);
11412   lgldense (lgl, 1);
11413   lglsimpleprobeinit (lgl);
11414   lglsetprbsimplelim (lgl);
11415   neqs = hbrs = nunits = 0;
11416
11417   nvars = lgl->nvars;
11418   NEW (lgl->sprb->spes, 2*nvars);
11419   lgl->sprb->spes += nvars;
11420
11421   while (!lgl->mt && (lit = lglwrknext (lgl))) {
11422     if (INCSTEPS (prb.simple.steps) >= lgl->limits->prb.steps) break;
11423     if (!lglisfree (lgl, lit)) continue;
11424     if (lglavar (lgl, lit)->equiv) continue;
11425     lglsimpleprobelit (lgl, lit);
11426     if (lgl->mt) break;
11427     lglchkirrstats (lgl);
11428     nunits += lglsimpleprobeunits (lgl);
11429     if (lgl->mt) break;
11430     hbrs += lglsimpleprobeimpls (lgl);
11431     if (lgl->mt) break;
11432     neqs += lglsimpleprobeqs (lgl);
11433     if (!lglflush (lgl)) break;
11434     if (lglterminate (lgl)) break;
11435     if (!lglsyncunits (lgl)) break;
11436   }
11437
11438   lglsimpleprobereset (lgl, nvars);
11439   lglsparse (lgl);
11440   if (!lgl->mt) lgldecomp (lgl);
11441
11442   DEL (lgl->sprb, 1);
11443
11444   deltarem = oldrem - lglrem (lgl);
11445   success = deltarem || hbrs || nunits;
11446   LGLUPDPEN (prb.simple, deltarem);
11447   lglprtsimpleproberem (lgl);
11448
11449   lglprt (lgl, 1 + !success,
11450     "[simpleprobe-%d] removed %d variables, found %d hbrs, %d units",
11451     lgl->stats->prb.simple.count, deltarem, hbrs, nunits);
11452
11453   assert (lgl->simp && lgl->probing && lgl->simpleprobing);
11454   lgl->simp = lgl->probing = lgl->simpleprobing = 0;
11455   lglrep (lgl, 2, 'p');
11456   lglstop (lgl);
11457   return !lgl->mt;
11458 }
11459
11460 static void lglmvbcls (LGL * lgl, int a, int b) {
11461   assert (abs (a) != abs (b));
11462   assert (!lglval (lgl, a));
11463   assert (!lglval (lgl, b));
11464   assert (lglmtstk (&lgl->clause)); 
11465   lglpushstk (lgl, &lgl->clause, a);
11466   lglpushstk (lgl, &lgl->clause, b);
11467   lglpushstk (lgl, &lgl->clause, 0);
11468   if (!lglsimpleprobeclausexists (lgl)) {
11469     LOG (2, "moving redundant binary clause %d %d", a, b);
11470 #ifndef NLGLPICOSAT
11471     lglpicosatchkcls (lgl);
11472 #endif
11473     lgldrupligaddcls (lgl, REDCS);
11474     lgladdcls (lgl, REDCS, 0, 1);
11475   }
11476   lglclnstk (&lgl->clause);
11477   lgl->stats->moved.bin++;
11478 }
11479
11480 static void lglrmvbcls (LGL * lgl, int a, int b) {
11481   lglrmbcls (lgl, a, b, 0);
11482   if (lgl->opts->move.val) lglmvbcls (lgl, a, b);
11483 }
11484
11485 static void lglmvtcls (LGL * lgl, int a, int b, int c) {
11486   assert (abs (a) != abs (b));
11487   assert (abs (a) != abs (c));
11488   assert (abs (b) != abs (c));
11489   assert (lglmtstk (&lgl->clause)); 
11490   lglpushstk (lgl, &lgl->clause, a);
11491   lglpushstk (lgl, &lgl->clause, b);
11492   lglpushstk (lgl, &lgl->clause, c);
11493   lglpushstk (lgl, &lgl->clause, 0);
11494   if (!lglsimpleprobeclausexists (lgl)) {
11495     LOG (2, "moving redundant ternary clause %d %d %d", a, b, c);
11496 #ifndef NLGLPICOSAT
11497     lglpicosatchkcls (lgl);
11498 #endif
11499     lgldrupligaddcls (lgl, REDCS);
11500     lgladdcls (lgl, REDCS, 0, 1);
11501   }
11502   lglclnstk (&lgl->clause);
11503   lgl->stats->moved.trn++;
11504 }
11505
11506 static void lglrmvtcls (LGL * lgl, int a, int b, int c) {
11507   assert (abs (a) != abs (b));
11508   assert (abs (a) != abs (c));
11509   assert (abs (b) != abs (c));
11510   lglrmtcls (lgl, a, b, c, 0);
11511   if (lgl->opts->move.val >= 2) lglmvtcls (lgl, a, b, c);
11512 }
11513
11514 static void lglmvlcls (LGL * lgl, int lidx) {
11515   const int * p, * c;
11516   int other;
11517   assert (lglmtstk (&lgl->clause)); 
11518   c = lglidx2lits (lgl, 0, lidx);
11519   for (p = c; (other = *p); p++)
11520     lglpushstk (lgl, &lgl->clause, other);
11521   lglpushstk (lgl, &lgl->clause, 0);
11522   if (!lglsimpleprobeclausexists (lgl)) {
11523     LOGCLS (2, c, "moving redundant large clause");
11524 #ifndef NLGLPICOSAT
11525     lglpicosatchkcls (lgl);
11526 #endif
11527     lgldrupligaddcls (lgl, REDCS);
11528     lgladdcls (lgl, REDCS, 0, 0);
11529   }
11530   lglclnstk (&lgl->clause);
11531   lgl->stats->moved.lrg++;
11532 }
11533
11534 static void lglrmvlcls (LGL * lgl, int lidx) {
11535   if (lgl->opts->move.val >= 3) lglmvlcls (lgl, lidx);
11536   lglrmlcls (lgl, lidx, 0);
11537 }
11538
11539 static int lglwaiting (LGL * lgl, const char * str, int wait) {
11540   if (!wait) return 0;
11541   if (!lgl->wait) return 0;
11542   if (wait >= 2 && lgl->opts->elim.val && !lgl->elmrtc) {
11543     if (str)
11544       lglprt (lgl, 2,
11545         "[%s-waiting] on variable elimination to be completed", str);
11546     return 1;
11547   }
11548   if (wait >= 1 && lgl->opts->block.val && !lgl->blkrtc) {
11549     if (str)
11550       lglprt (lgl, 2, 
11551         "[%s-waiting] on blocked clause elimination to be completed", str);
11552     return 1;
11553   }
11554   return 0;
11555 }
11556
11557 static void lglbasicate (LGL * lgl, int lit) {
11558   int blit, tag, red, other, other2, lidx;
11559   const int * w, * eow, * p, * c, * l;
11560   int nonfalse, numtrue, val;
11561   HTS * hts;
11562   if (!lgl->opts->bate.val) return;
11563   if (lglwaiting (lgl, 0, lgl->opts->batewait.val)) return;
11564 RESTART:
11565   hts = lglhts (lgl, -lit);
11566   w = lglhts2wchs (lgl, hts);
11567   eow = w + hts->count;
11568   for (p = w; p < eow; p++) {
11569     blit = * p;
11570     tag = blit & MASKCS;
11571     if (tag == TRNCS || tag == LRGCS) p++;
11572     red = blit & REDCS;
11573     if (red) continue;
11574     if (tag == BINCS) continue;
11575     if (tag == TRNCS) {
11576       other = blit >> RMSHFT;
11577       numtrue = 0;
11578       if ((val = lglval (lgl, other)) < 0) continue;
11579       if (val > 0) {
11580         if (!lglevel (lgl, other)) continue;
11581         if (lgltd (lgl, other)->irr) numtrue++;
11582       }
11583       other2 = *p;
11584       if ((val = lglval (lgl, other2)) < 0) continue;
11585       if (val > 0) {
11586         if (!lglevel (lgl, other2)) continue;
11587         if (lgltd (lgl, other2)->irr) numtrue++;
11588       }
11589       if (!numtrue) continue;
11590       LOG (2, "basic ATE ternary clause %d %d %d", -lit, other, other2);
11591       lgl->stats->prb.basic.ate.trnr++;
11592       lglrmvtcls (lgl, -lit, other, other2);
11593       goto RESTART;
11594     } else {
11595       assert (tag == OCCS || tag == LRGCS);
11596       if (tag == LRGCS && lgl->dense) continue;
11597       lidx = (tag == LRGCS) ? *p : (blit >> RMSHFT);
11598       assert (!red);
11599       c = lglidx2lits (lgl, 0, lidx);
11600       numtrue = nonfalse = 0;
11601       for (l = c; (nonfalse < 2 || !numtrue) && (other = *l); l++) {
11602         if (other == -lit) continue;
11603         assert (other != lit);
11604         if ((val = lglval (lgl, other)) >= 0) nonfalse++;
11605         if (val > 0) {
11606            if (!lglevel (lgl, other)) { numtrue = -1; break; }
11607            if (lgltd (lgl, other)->irr) numtrue++;
11608         }
11609       }
11610       if (numtrue > 0 && nonfalse >= 2) {
11611         LOGCLS (2, c, "basic ATE large clause");
11612         lgl->stats->prb.basic.ate.lrg++;
11613         lglrmvlcls (lgl, lidx);
11614         goto RESTART;
11615       }
11616     }
11617   }
11618 }
11619
11620 static void lglbasicatestats (LGL * lgl) {
11621   int n = lgl->stats->prb.basic.ate.lrg + lgl->stats->prb.basic.ate.trnr;
11622   int d = n - lgl->stats->prb.basic.lastate;
11623   assert (d >= 0);
11624   if (d <= 0) return;
11625   lgl->stats->prb.basic.ate.count++;
11626   lglprt (lgl, 1,
11627     "[bate-%d] eliminated %d asymmetric tautologies during probing",
11628     lgl->stats->prb.basic.ate.count, d);
11629   lgl->stats->prb.basic.lastate = n;
11630 }
11631
11632 static void lglbasicprobelit (LGL * lgl, int root) {
11633   int old, ok, dom, lit, val;
11634   Stk lift, saved;
11635   const int * p;
11636   CLR (lift); CLR (saved);
11637   assert (lgl->simp);
11638   assert (lgl->probing || lgl->cceing);
11639   assert (!lgl->level);
11640   LOG (2, "next probe %d positive phase", root);
11641   assert (!lgl->level);
11642   if (lgl->treelooking) lgl->stats->prb.treelook.probed++;
11643   else if (lgl->cceing) lgl->stats->cce.probed++;
11644   else assert (lgl->basicprobing), lgl->stats->prb.basic.probed++;
11645   if (lglrand (lgl) & (1<<12)) root = -root;
11646   lgliassume (lgl, root);
11647   old = lgl->next;
11648   ok = lglbcp (lgl);
11649   dom = 0;
11650   if (ok) {
11651     lglclnstk (&saved);
11652     lglbasicate (lgl, root);
11653     for (p = lgl->trail.start + old; p < lgl->trail.top; p++) {
11654       lit = *p;
11655       if (lit == root) continue;
11656       lglpushstk (lgl, &saved, lit);
11657     }
11658   } else dom = lglprbana (lgl, root);
11659   lglbacktrack (lgl, 0);
11660   if (!ok) {
11661     LOG (1, "failed literal %d on probing", dom, root);
11662     lglpushstk (lgl, &lift, -dom);
11663     goto MERGE;
11664   }
11665   LOG (2, "next probe %d negative phase", -root);
11666   assert (!lgl->level);
11667   if (lgl->treelooking) lgl->stats->prb.treelook.probed++;
11668   else if (lgl->cceing) lgl->stats->cce.probed++;
11669   else assert (lgl->basicprobing), lgl->stats->prb.basic.probed++;
11670   lgliassume (lgl, -root);
11671   ok = lglbcp (lgl);
11672   if (ok) {
11673     lglbasicate (lgl, -root);
11674     for (p = saved.start; p < saved.top; p++) {
11675       lit = *p;
11676       val = lglval (lgl, lit);
11677       if (val <= 0) continue;
11678       if (lgl->treelooking) lgl->stats->prb.treelook.lifted++;
11679       else if (lgl->cceing) lgl->stats->cce.lifted++;
11680       else assert (lgl->basicprobing), lgl->stats->prb.basic.lifted++;
11681       lglpushstk (lgl, &lift, lit);
11682       LOG (2, "lifted %d", lit);
11683     }
11684   } else dom = lglprbana (lgl, -root);
11685   lglbacktrack (lgl, 0);
11686   if (!ok) {
11687     LOG (1, "failed literal %d on probing %d", dom, -root);
11688     lglpushstk (lgl, &lift, -dom);
11689   }
11690 MERGE:
11691   while (!lglmtstk (&lift)) {
11692     lit = lglpopstk (&lift);
11693     val = lglval (lgl, lit);
11694     if (val > 0) continue;
11695     if (val < 0) goto EMPTY;
11696     lglunit (lgl, lit);
11697     if (lgl->treelooking) lgl->stats->prb.treelook.failed++;
11698     else if (lgl->cceing) lgl->stats->cce.failed++;
11699     else assert (lgl->basicprobing), lgl->stats->prb.basic.failed++;
11700     if (lglbcp (lgl)) continue;
11701 EMPTY:
11702     LOG (1, "empty clause after propagating lifted and failed literals");
11703     lgl->mt = 1;
11704   }
11705   lglrelstk (lgl, &lift);
11706   lglrelstk (lgl, &saved);
11707 }
11708
11709 static TVar * lgltvar (LGL * lgl, int lit) {
11710   int idx = abs (lit);
11711   assert (2 <= idx && idx < lgl->nvars);
11712   assert (lgl->tlk);
11713   return lgl->tlk->tvars + idx;
11714 }
11715
11716 static void lglsignedtlmark (LGL * lgl, int lit) {
11717   TVar * tv = lgltvar (lgl, lit);
11718   unsigned bit = 1u << (lit < 0);
11719   if (tv->mark & bit) return;
11720   tv->mark |= bit;
11721 }
11722
11723 static int lglsignedtlmarked (LGL * lgl, int lit) {
11724   TVar * tv = lgltvar (lgl, lit);
11725   unsigned bit = 1u << (lit < 0);
11726   return tv->mark & bit;
11727 }
11728
11729 static void lgltlenq (LGL * lgl, int start) {
11730   int lit, blit, tag, other, oldcount, newcount, * stk;
11731   unsigned delta, i, j, mod;
11732   const int * p, * w, * eos;
11733   HTS * hts;
11734   assert (!lglsignedtlmarked (lgl, start));
11735   lglsignedtlmark (lgl, start);
11736   lglpushstk (lgl, &lgl->tlk->stk, start);
11737   while (!lglmtstk (&lgl->tlk->stk)) {
11738     lit = lglpopstk (&lgl->tlk->stk);
11739     LOG (2, "tree-look enqueue %d%s", lit, lit == start ? " start":"");
11740     if (lit) {
11741       assert (!lglval (lgl, lit));
11742       assert (lglsignedtlmarked (lgl, lit));
11743       lglpushstk (lgl, &lgl->tlk->seen, lit);
11744       lglpushstk (lgl, &lgl->tlk->stk, 0);
11745       hts = lglhts (lgl, lit);
11746       w = lglhts2wchs (lgl, hts);
11747       eos = w + hts->count;
11748       oldcount = lglcntstk (&lgl->tlk->stk);
11749       for (p = w; p < eos; p++) {
11750         INCSTEPS (prb.treelook.steps);
11751         blit = *p;
11752         tag = blit & MASKCS;
11753         if (tag == OCCS) continue;
11754         if (tag == TRNCS || tag == LRGCS) { p++; continue; }
11755         assert (tag == BINCS);
11756         other = -(blit >> RMSHFT);
11757         if (lglval (lgl, other)) assert (lglval (lgl, other) < 0);
11758         else if (!lglsignedtlmarked (lgl, other)) {
11759           lglsignedtlmark (lgl, other);
11760           lglpushstk (lgl, &lgl->tlk->stk, other);
11761         }
11762       }
11763       newcount = lglcntstk (&lgl->tlk->stk);
11764       delta = newcount - oldcount;
11765       assert (delta >= 0);
11766       if ((mod = delta) <= 1) continue;
11767       stk = lgl->tlk->stk.start;
11768       for (i = 0; i < delta-1; i++, mod--) {
11769         assert (mod > 0);
11770         j = i + (lglrand (lgl) % mod);
11771         assert (i <= j && j < delta);
11772         if (i == j) continue;
11773         SWAP (int, stk[i + oldcount], stk[j + oldcount]);
11774       }
11775     } else lglpushstk (lgl, &lgl->tlk->seen, 0);
11776   }
11777 }
11778
11779 static int lglisroot (LGL * lgl, int lit) { return !lglhasbins (lgl, lit); }
11780
11781 static void lgltlunmarkall (LGL * lgl) {
11782   int idx;
11783   for (idx = 2; idx < lgl->nvars; idx++)
11784     lgl->tlk->tvars[idx].mark = 0;
11785 }
11786
11787 static int lgltlschedlit (LGL * lgl, int lit) {
11788   if (INCSTEPS (prb.treelook.steps) > lgl->limits->prb.steps) return 0;
11789   if (!lglisfree (lgl, lit)) return 1;
11790   if (lglsignedtlmarked (lgl, lit)) return 1;
11791   if (!lglisroot (lgl, -lit)) return 1;
11792   if (!lgl->tlk->lkhd && lglavar (lgl, lit)->donotreelook) return 1;
11793   if (lgl->opts->treelook.val >= 2) {
11794     lglbasicprobelit (lgl, -lit);
11795     if (lgl->mt) return 0;
11796     if (lglterminate (lgl)) return 0;
11797     if (!lglisfree (lgl, lit)) return 1;
11798     if (!lglisroot (lgl, -lit)) return 1;
11799     if (!lglhasbins (lgl, lit)) return 1;
11800   }
11801   lgltlenq (lgl, lit);
11802   return 1;
11803 }
11804
11805 static int lgltlschedanylit (LGL * lgl, int lit) {
11806   if (INCSTEPS (prb.treelook.steps) > lgl->limits->prb.steps) return 0;
11807   if (!lglisfree (lgl, lit)) return 1;
11808   if (lglsignedtlmarked (lgl, lit)) return 1;
11809   if (!lgl->tlk->lkhd && lglavar (lgl, lit)->donotreelook) return 1;
11810   if (lgl->opts->treelook.val >= 2) {
11811     lglbasicprobelit (lgl, -lit);
11812     if (lgl->mt) return 0;
11813     if (lglterminate (lgl)) return 0;
11814     if (!lglisfree (lgl, lit)) return 1;
11815   }
11816   lgltlenq (lgl, lit);
11817   return 1;
11818 }
11819
11820 static void lgltlsched (LGL * lgl) {
11821   int idx, round, count, * p;
11822   LOG (1, "scheduling tree-look literals");
11823   for (round = 0; !lgl->mt && round < 2; round++) {
11824     assert (lglmtstk (&lgl->tlk->seen));
11825     assert (lglmtstk (&lgl->tlk->stk));
11826     if (lglrandlitrav (lgl, lgltlschedlit))
11827       lglrandlitrav (lgl, lgltlschedanylit);
11828     lgltlunmarkall (lgl);
11829     lglrelstk (lgl, &lgl->tlk->stk);
11830     if (!lglmtstk (&lgl->tlk->seen)) break;
11831     for (idx = 2; idx < lgl->nvars; idx++)
11832       lglavar (lgl, idx)->donotreelook = 0;
11833   }
11834   lglfitstk (lgl, &lgl->tlk->seen);
11835   count = 0;
11836   for (p = lgl->tlk->seen.start; p < lgl->tlk->seen.top; p++)
11837     if (*p) count++;
11838   lglprt (lgl, 1,
11839     "[treelook-%d] scheduled %d literals %.0f%%",
11840     lgl->stats->prb.treelook.count, count, lglpcnt (count, 2*lglrem (lgl)));
11841   if (!count)
11842     for (idx = 2; idx < lgl->nvars; idx++)
11843       lglavar (lgl, idx)->donotreelook = 0;
11844 }
11845
11846 static void lgltlassign (LGL * lgl, Stk * assignment, int lit) {
11847   TVar * tv;
11848   LOG (2, "tree-look assign %d", lit);
11849   tv = lgltvar (lgl, lit);
11850   assert (!tv->val);
11851   tv->val = lglsgn (lit) * (1 + lglcntstk (assignment));
11852   lglpushstk (lgl, assignment, lit);
11853   assert (tv->val);
11854   assert (lglsgn (tv->val) == lglsgn (lit));
11855 }
11856
11857 static void lgltlunassign (LGL * lgl, int lit) {
11858   TVar * tv;
11859   LOG (2, "tree-look unassign %d", lit);
11860   tv = lgltvar (lgl, lit);
11861   assert (tv->val);
11862   assert (lglsgn (tv->val) == lglsgn (lit));
11863   tv->val = 0;
11864 }
11865
11866 static int lgltlval (LGL * lgl, int lit) {
11867   TVar * tv = lgltvar (lgl, lit);
11868   int res;
11869   if (!tv->val) return 0;
11870   res = lglsgn (tv->val);
11871   if (lit < 0) res = -res;
11872   return res;
11873 }
11874
11875 static void lglincreducedptr (LGL * lgl, Flt * reducedptr, int size) {
11876   Flt reduced = *reducedptr, inc = lglflt (-size, 1);
11877   reduced = lgladdflt (reduced, inc);
11878   LOG (2, "reduced score incremented to %s from %s by %s (size %d)",
11879        lglflt2str (lgl, reduced), 
11880        lglflt2str (lgl, *reducedptr), 
11881        lglflt2str (lgl, inc),
11882        size);
11883   *reducedptr = reduced;
11884 }
11885
11886 static int lgltlbcp (LGL * lgl,
11887                      Stk * assignment, Flt * reducedptr, int dom) {
11888   int next = lglcntstk (assignment), next2 = next, lit, size, implied;
11889   int blit, tag, other, other2, val, lidx, red, found, trivial;
11890   int numnonfalse, numfalse, firstfalse, litval, skip;
11891   const int * p, * w, * eos, * c, * q;
11892   HTS * hts;
11893   if (lglval (lgl, dom)) return 1;
11894   assert (!lgltlval (lgl, dom));
11895   lgltlassign (lgl, assignment, dom);
11896   lgl->stats->prb.treelook.probed++;
11897   LOG (2, "starting tree-look bcp on %d", dom);
11898   for (;;) {
11899     if (next2 < lglcntstk (assignment)) {
11900       assert (lgl->simp);
11901       INCSTEPS (props.simp);
11902       if (lgl->lkhd) INCSTEPS (props.lkhd);
11903       lit = lglpeek (assignment, next2++);
11904       assert (lgltlval (lgl, lit) > 0);
11905       LOG (2, "tree-look binary clause bcp on %d", lit);
11906       hts = lglhts (lgl, -lit);
11907       w = lglhts2wchs (lgl, hts);
11908       eos = w + hts->count;
11909       for (p = w; p < eos; p++) {
11910         assert (lgl->simp);
11911         lgl->stats->visits.simp++;
11912         if (lgl->lkhd) lgl->stats->visits.lkhd++;
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         val = lglval (lgl, other);
11921         if (val < 0) return 0;
11922         if (val > 0) continue;
11923         val = lgltlval (lgl, other);
11924         if (val < 0) return 0;
11925         if (reducedptr) lglincreducedptr (lgl, reducedptr, 2);
11926         if (val > 0) continue;
11927         lgltlassign (lgl, assignment, other);
11928       }
11929     } else if (next < lglcntstk (assignment)) {
11930       lit = lglpeek (assignment, next++);
11931       litval = lgltlval (lgl, lit);
11932       assert (litval > 0);
11933       LOG (2, "tree-look non-binary clause bcp on %d", lit);
11934       hts = lglhts (lgl, -lit);
11935       w = lglhts2wchs (lgl, hts);
11936       eos = w + hts->count;
11937       for (p = w; p < eos; p++) {
11938         blit = *p;
11939         tag = blit & MASKCS;
11940         if (tag == LRGCS || tag == TRNCS) p++;
11941         if (tag == BINCS || tag == LRGCS) continue;
11942         INCSTEPS (prb.treelook.steps);
11943         assert (lglmtstk (&lgl->clause));
11944         skip = trivial = 0;
11945         if (tag == TRNCS) {
11946           other = blit >> RMSHFT;
11947           other2 = *p;
11948           if (lglval (lgl, other) > 0 || 
11949               lglval (lgl, other2) > 0) skip = 1;
11950           else {
11951             if (lgltlval (lgl, other) > 0 ||
11952                 lgltlval (lgl, other2) > 0) trivial = 1;
11953             lglpushstk (lgl, &lgl->clause, -lit),
11954             lglpushstk (lgl, &lgl->clause, other),
11955             lglpushstk (lgl, &lgl->clause, other2);
11956           }
11957         } else {
11958           assert (tag == OCCS);
11959           red = blit & REDCS;
11960           lidx = blit >> RMSHFT;
11961           found = trivial = 0;
11962           c = lglidx2lits (lgl, red, lidx);
11963           INCSTEPS (prb.treelook.steps);
11964           for (q = c; !skip && (other = *q); q++) {
11965             if (other >= NOTALIT) skip = 1;
11966             else if (lglval (lgl, other) > 0) skip = 1;
11967             else {
11968               if (other == -lit) assert (!found), found++;
11969               if (lgltlval (lgl, other) > 0) trivial = 1;
11970               lglpushstk (lgl, &lgl->clause, other);
11971             }
11972           }
11973           assert (skip || found);
11974         }
11975         numnonfalse = numfalse = size = implied = 0;
11976         firstfalse = 1;
11977         if (!skip) {
11978           INCSTEPS (prb.treelook.steps);
11979           for (q = lgl->clause.start; q < lgl->clause.top; q++) {
11980             other = *q;
11981             if (lglval (lgl, other) < 0) continue;
11982             size++;
11983             if ((val = lgltlval (lgl, other)) < 0) {
11984               if (reducedptr && -val < litval) firstfalse = 0;
11985               numfalse++; 
11986               continue; 
11987             }
11988             numnonfalse++;
11989             if (implied == NOTALIT) continue;
11990             else if (implied) implied = NOTALIT;
11991             else implied = other;
11992           }
11993         }
11994         lglclnstk (&lgl->clause);
11995         if (skip) continue;
11996         if (reducedptr && firstfalse) 
11997           lglincreducedptr (lgl, reducedptr, size);
11998         if (trivial) continue;
11999         if (!numnonfalse) { assert (!implied); return 0; }
12000         assert (implied);
12001         if (implied == NOTALIT) continue;
12002         assert (numnonfalse == 1);
12003         if (!numfalse) continue; // TODO remove?
12004         INCSTEPS (prb.treelook.steps);
12005         if (tag == TRNCS) lgl->stats->hbr.trn++; else lgl->stats->hbr.lrg++;
12006         LOG (2, "tree-look hyper binary resolvent %d %d", -dom, implied);
12007         if (lgl->opts->drup.val) lgldrupclsarg (lgl, -dom, implied, 0);
12008 #ifndef NLGLPICOSAT
12009         lglpicosatchkclsarg (lgl, -dom, implied, 0);
12010 #endif
12011         (void) lglwchbin (lgl, -dom, implied, REDCS);
12012         (void) lglwchbin (lgl, implied, -dom, REDCS);
12013         lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
12014         lgl->stats->hbr.cnt++;
12015         lgl->stats->prgss++;
12016         lgltlassign (lgl, assignment, implied);
12017         assert (next > 0),  next--; // force to redo this trn/lrg literal
12018         break;  // and continue outer 'next2' prop on 'implied'
12019       }
12020     } else break;
12021   }
12022   if (reducedptr) assert (lgl->tlk->lkhd), lgl->tlk->lkhd[dom] = *reducedptr;
12023   return 1;
12024 }
12025
12026 static void lgltreelooklit (LGL * lgl, Stk * a, Ftk * r, int lit) {
12027   Flt reduced;
12028   LOG (2, "treelook dequeue %d", lit);
12029   if (lit) {
12030     if (lgl->opts->treelook.val >= 2 &&
12031         lglmtstk (a) &&
12032         lglisfree (lgl, lit)) lglbasicprobelit (lgl, -lit);
12033     if (r) {
12034       reduced = lglmtftk (r) ? FLTMIN : lgltopftk (r);
12035       lglpushftk (lgl, r, reduced);
12036     }
12037     lglpushstk (lgl, a, 0);
12038     if (lgl->mt || !lglisfree (lgl, lit)) return;
12039     if (lgltlval (lgl, -lit) > 0 ||
12040         (!lgltlval (lgl, lit) && 
12041          !lgltlbcp (lgl, a, r ? &reduced : 0, lit))) {
12042       int tmp;
12043       LOG (1, "tree-look failed literal %d", lit);
12044       if (!(tmp = lglval (lgl, lit))) {
12045         lgl->stats->prb.treelook.failed++;
12046         lglunit (lgl, -lit);
12047         if (!lglbcp (lgl)) {
12048           if (!lgl->mt) lgl->mt = 1;
12049           LOG (1, "inconsistent tree-look failed literal");
12050         }
12051       } else if (tmp > 0) {
12052         lgl->stats->prb.treelook.failed++;
12053         LOG (1, "tree-look failed literal literal %d inconsistent", lit);
12054         if (!lgl->mt) lgl->mt = 1;
12055       } else LOG (1, "tree-look failed literal %d already found", lit);
12056     }
12057     if (r) {
12058       assert (r->start < r->top);
12059       assert (r->top[-1] <= reduced);
12060       r->top[-1] = reduced;
12061     }
12062   } else {
12063     if (r) lglpopftk (r);
12064     while ((lit = lglpopstk (a)))
12065       lgltlunassign (lgl, lit);
12066   }
12067 }
12068
12069 static int64_t lglsetprbtreelooklim (LGL * lgl, int * lkhdresptr) {
12070   int sizepen, lastpen, pen, boost;
12071   int64_t limit, irrlim;
12072   if (lgl->opts->treelookrtc.val || lgl->opts->prbrtc.val) {
12073     limit = lgl->limits->prb.steps = LLMAX;
12074     lglprt (lgl, 1, "[treelook-%d] no limit (run to completion)",
12075             lgl->stats->prb.treelook.count);
12076   } else if (lkhdresptr && lgl->opts->treelookfull.val) {
12077     limit = lgl->limits->prb.steps = LLMAX;
12078     lglprt (lgl, 1, "[treelook-%d] unlimited look-ahead requested",
12079             lgl->stats->prb.treelook.count);
12080   } else {
12081     limit = (lgl->opts->treelookreleff.val*lglvisearch (lgl))/2000;
12082     if (limit < lgl->opts->treelookmineff.val)
12083       limit = lgl->opts->treelookmineff.val;
12084     if (lgl->opts->treelookmaxeff.val >= 0 &&
12085         limit > lgl->opts->treelookmaxeff.val)
12086       limit = lgl->opts->treelookmaxeff.val;
12087     assert (lgl->tlk);
12088     sizepen = lglszpen (lgl);
12089     lastpen = lgl->tlk->lkhd ? 
12090       lgl->limits->lkhdpen : lgl->limits->prb.treelook.pen;
12091     pen = sizepen + lastpen;
12092     limit >>= pen;
12093     irrlim = lgl->stats->irr.clauses.cur/4;
12094     irrlim >>= lgl->limits->simp.pen;
12095     if (lgl->opts->boost.val && lgl->tlk->lkhd)
12096       boost = lgl->opts->treelookboost.val;
12097     else boost = 1;
12098     limit *= boost;
12099     if (lgl->opts->irrlim.val && limit < irrlim) {
12100       limit = irrlim;
12101       lglprt (lgl, 1, 
12102         "[treelook-%d] limit %lld based on %d irredundant clauses",
12103         lgl->stats->prb.treelook.count, 
12104         (LGLL) limit, lgl->stats->irr.clauses.cur);
12105     } else
12106       lglprt (lgl, 1, 
12107         "[treelook-%d] limit %lld penalty %d = %d + %d boost %d",
12108         lgl->stats->prb.treelook.count, (LGLL) limit,
12109         pen, lastpen, sizepen, boost);
12110     if (lkhdresptr)
12111       lglprt (lgl, 1, "[treelook-%d] limited look-ahead requested",
12112               lgl->stats->prb.treelook.count);
12113     lgl->limits->prb.steps = lgl->stats->prb.treelook.steps + limit;
12114   }
12115
12116   return limit;
12117 }
12118
12119 static void lglclntlvals (LGL * lgl) {
12120   int idx;
12121   for (idx = 2; idx < lgl->nvars; idx++) lgl->tlk->tvars[idx].val = 0;
12122 }
12123
12124 #ifndef NDEBUG
12125 static int lglieliminated (LGL * lgl, int ilit) {
12126   return lglelit2ext (lgl, lglexport (lgl, ilit))->eliminated;
12127 }
12128 #endif
12129
12130 static int lgliblocking (LGL * lgl, int ilit) {
12131   return lglelit2ext (lgl, lglexport (lgl, ilit))->blocking;
12132 }
12133
12134 static void lgltlsetlkhd (LGL * lgl, int * lkhdresptr, int remlits) {
12135   LKHD lkhdrescore, lkhdscore, lkhdpos, lkhdneg;
12136   Flt jwhrescore, jwhscore, jwhpos, jwhneg;
12137   int idx, lkhdres, phase, elit;
12138   Ext * ext;
12139   assert (lkhdresptr);
12140   lkhdres = 0; lkhdrescore = FLTMIN; jwhrescore = FLTMIN;
12141   assert (!lgl->nvars || lgl->tlk->lkhd);
12142   lgljwh (lgl);
12143   for (idx = 2; idx < lgl->nvars; idx++) {
12144     if (!lglisfree (lgl, idx)) continue;
12145     assert (!lglieliminated (lgl, idx));
12146     if (lkhdresptr && lgliblocking (lgl, idx)) continue;
12147     if (!remlits) {
12148       lkhdpos = lgl->tlk->lkhd[idx];
12149       lkhdneg = lgl->tlk->lkhd[-idx];
12150       lkhdscore = lglmulflt (lkhdneg, lkhdpos);
12151       if (lkhdscore > FLTMIN)
12152         lkhdscore = lgladdflt (lkhdscore, lgladdflt (lkhdneg, lkhdpos));
12153     } else lkhdscore = lkhdpos = lkhdneg = FLTMIN;
12154     jwhpos = lgl->jwh[lglulit (idx)];
12155     jwhneg = lgl->jwh[lglulit (-idx)];
12156     jwhscore = lglmulflt (jwhpos, jwhneg);
12157     jwhscore = lgladdflt (jwhscore, lgladdflt (jwhpos, jwhneg));
12158     LOG (1,
12159       "final tree based look-ahead score [%s,%s] "
12160       "(pos [%s,%s], neg [%s,%s]) of %d",
12161        lglflt2str (lgl, lkhdscore), lglflt2str (lgl,jwhscore),
12162        lglflt2str (lgl, lkhdpos), lglflt2str (lgl,jwhpos),
12163        lglflt2str (lgl, lkhdneg), lglflt2str (lgl,jwhneg),
12164        idx);
12165
12166     // phase with less weighted reductions
12167          if (lkhdpos > lkhdneg) phase = -1;
12168     else if (lkhdpos < lkhdneg) phase = 1;
12169     // then with more weighted occs
12170     else if (jwhpos > jwhneg) phase = 1;
12171     else if (jwhpos < jwhneg) phase = -1;
12172     // otherwise negative phase
12173     else phase = -1;
12174
12175     if (lkhdres) {
12176       if (lkhdscore < lkhdrescore) continue;
12177       if (lkhdscore == lkhdrescore && jwhscore <= jwhrescore) continue;
12178     }
12179     lkhdrescore = lkhdscore;
12180     jwhrescore = jwhscore;
12181     lkhdres = phase * idx;
12182   }
12183   if (lkhdres) {
12184     elit = lglexport (lgl, lkhdres);
12185     ext = lglelit2ext (lgl, elit);
12186     assert (!ext->eliminated);
12187     assert (!ext->blocking);
12188     lglprt (lgl, 1, "[treelook-%d] best look-ahead %d score [%s,%s]",
12189       lgl->stats->prb.treelook.count, lkhdres,
12190       lglflt2str (lgl, lkhdrescore), lglflt2str (lgl, jwhrescore));
12191     if (ext->melted) {
12192       ext->melted = 0;
12193       LOG (2, "tree-look-ahead winner external %d not melted anymore", elit);
12194     } else
12195       LOG (2,
12196         "tree-look-ahead winner external %d was not melted anyhow", elit);
12197   } else LOG (1, "no proper best tree-look-ahead literal found");
12198   if (lkhdresptr) *lkhdresptr = lkhdres;
12199 }
12200
12201 static void lglgenericreport (LGL * lgl, const char * name, int count,
12202                               int probed, int nprobes, double start) {
12203   int div, mod;
12204   assert (nprobes >= 0);
12205   if (!nprobes || lgl->opts->verbose.val < 2) return;
12206   if (lgl->opts->verbose.val == 2) div = 10;
12207   else if (lgl->opts->verbose.val == 3) div = 100;
12208   else div = 0;
12209   mod = div ? (nprobes + div - 1) / div : 1;
12210   assert (mod > 0);
12211   if (probed % mod) return;
12212   lglprt (lgl, 1,
12213     "[%s-%d] probed %d/%d (%.0f%%) %.1f sec %d vars %.0f MB",
12214     name, count, probed, nprobes, lglpcnt (probed, nprobes),
12215     lglgetime (lgl) - start, lglrem (lgl), lglmb (lgl));
12216 }
12217
12218 static void lgltreelookreport (LGL * lgl,
12219                               int probed, int nprobes, double start) {
12220   lglgenericreport (lgl,
12221      "treelook", lgl->stats->prb.treelook.count, probed, nprobes, start);
12222 }
12223
12224 static int lgltreelookaux (LGL * lgl, int * lkhdresptr) {
12225   int oldhbrs, oldrem, remvarsall, remvarslkhd, remlits, notfullyscheduled;
12226   int deltavars, newhbrs, success, idx, next, lit, nseen;
12227   int64_t oldsteps, steps, limit;
12228   Stk assignment;
12229   double start;
12230   Ftk reduced;
12231   TVar * tv;
12232   AVar * av;
12233
12234   if (lgl->mt) return 0;
12235   if (lkhdresptr) *lkhdresptr = 0;
12236   if (!lgl->nvars) return 1;
12237
12238   lglstart (lgl, &lgl->times->prb.treelook);
12239   lgl->stats->prb.treelook.count++;
12240
12241   NEW (lgl->tlk, 1);
12242   NEW (lgl->tlk->tvars, lgl->nvars);
12243
12244   assert (!lgl->simp && !lgl->probing && !lgl->treelooking);
12245   lgl->simp = lgl->probing = lgl->treelooking = 1;
12246
12247   if (lgl->level > 0) lglbacktrack (lgl, 0);
12248   oldhbrs = lgl->stats->hbr.cnt;
12249   oldrem = lglrem (lgl);
12250
12251   assert (!lgl->tlk->lkhd);
12252   if (lkhdresptr) {
12253     NEW (lgl->tlk->lkhd, 2*lgl->nvars);
12254     lgl->tlk->lkhd += lgl->nvars;
12255     assert (lgl->tlk->lkhd);
12256   }
12257
12258   limit = lglsetprbtreelooklim (lgl, lkhdresptr);
12259   oldsteps = lgl->stats->prb.treelook.steps;
12260
12261   lgltlsched (lgl);
12262
12263   steps = lgl->stats->prb.treelook.steps - oldsteps;
12264   lglprt (lgl, 1, "[treelook-%d] scheduling used %lld steps",
12265     lgl->stats->prb.treelook.count, (LGLL) steps);
12266
12267   if (limit != LLMAX) {
12268     notfullyscheduled =
12269       (lgl->stats->prb.treelook.steps >= lgl->limits->prb.steps);
12270     lgl->limits->prb.steps = lgl->stats->prb.treelook.steps + limit;
12271     if (notfullyscheduled)
12272       lglprt (lgl, 1, "[treelook-%d] not fully scheduled",
12273         lgl->stats->prb.treelook.count);
12274     else
12275       lglprt (lgl, 1, "[treelook-%d] scheduled completely",
12276         lgl->stats->prb.treelook.count);
12277   } else notfullyscheduled = 0;
12278
12279   CLR (assignment); CLR (reduced);
12280   remlits = remvarsall = remvarslkhd = 0;
12281
12282   nseen = lglcntstk (&lgl->tlk->seen);
12283   if (!lgl->mt && nseen) {
12284
12285     (void) lglsetprbtreelooklim (lgl, lkhdresptr);
12286     oldsteps = lgl->stats->prb.treelook.steps;
12287
12288     lgldense (lgl, lgl->opts->treelooklrg.val);
12289     next = 0;
12290     start = lglgetime (lgl);
12291     lgltreelookreport (lgl, next, nseen, start);
12292     while (!lgl->mt &&
12293            !lglterminate (lgl) &&
12294            lglsyncunits (lgl) &&
12295            next < nseen &&
12296            lgl->stats->prb.treelook.steps < lgl->limits->prb.steps) {
12297       lit = lglpeek (&lgl->tlk->seen, next++);
12298       lgltreelooklit (lgl, &assignment, lkhdresptr ? &reduced : 0, lit);
12299       lgltreelookreport (lgl, next, nseen, start);
12300     }
12301     lgltreelookreport (lgl, next, nseen, start);
12302     lglclntlvals (lgl);
12303     assert (lgl->stats->prb.treelook.steps >= oldsteps);
12304     steps = lgl->stats->prb.treelook.steps - oldsteps;
12305     lglprt (lgl, 1, "[treelook-%d] used %lld steps",
12306       lgl->stats->prb.treelook.count, (LGLL) steps);
12307     while (next < lglcntstk (&lgl->tlk->seen)) {
12308       lit = lglpeek (&lgl->tlk->seen, next++);
12309       if (!lit) continue;
12310       if (!lglisfree (lgl, lit)) continue;
12311       remlits++;
12312       tv = lgltvar (lgl, lit);
12313       tv->val = 1;
12314     }
12315     for (idx = 2; idx < lgl->nvars; idx++)
12316       if (lglisfree (lgl, idx)) {
12317         tv = lgltvar (lgl, idx);
12318         av = lglavar (lgl, idx);
12319         if (tv->val) {
12320            tv->val = 0;
12321            if (!av->donotreelook) remvarsall++;
12322            remvarslkhd++;
12323         } else if (!av->donotreelook) av->donotreelook = 1;
12324       }
12325     assert (remvarslkhd >= remvarsall);
12326
12327     if (remvarsall || notfullyscheduled) {
12328       lglprt (lgl, 1, "[treelook-%d] %d literals remain %.0f%%%s",
12329         lgl->stats->prb.treelook.count,
12330         remlits, lglpcnt (remlits, 2*lglrem (lgl)),
12331         lkhdresptr ? " in look-ahead" : "");
12332       if (lkhdresptr)
12333         lglprt (lgl, 1, "[treelook-%d] %d look-ahead variables remain %.0f%%",
12334           lgl->stats->prb.treelook.count,
12335           remvarslkhd, lglpcnt (remvarslkhd, lglrem (lgl)));
12336       lglprt (lgl, 1,
12337         "[treelook-%d] %d variables remain to probed next time %.0f%%",
12338         lgl->stats->prb.treelook.count,
12339         remvarsall, lglpcnt (remvarsall, lglrem (lgl)));
12340     } else {
12341       lglprt (lgl, 1, 
12342         "[treelook-%d] fully completed tree based probing%s",
12343         lgl->stats->prb.treelook.count, lkhdresptr ? " in look-ahead" : "");
12344       for (idx = 2; idx < lgl->nvars; idx++)
12345         lglavar (lgl, idx)->donotreelook = 0;
12346     }
12347     lglsparse (lgl);
12348   }
12349
12350   DEL (lgl->tlk->tvars, lgl->nvars);
12351   lglgc (lgl);
12352   lglrelftk (lgl, &reduced);
12353   lglrelstk (lgl, &assignment);
12354   lglrelstk (lgl, &lgl->tlk->seen);
12355   if (!lgl->mt && lkhdresptr) 
12356     lgltlsetlkhd (lgl, lkhdresptr, remlits || notfullyscheduled);
12357   if (lgl->tlk->lkhd) {
12358     lgl->tlk->lkhd -= lgl->nvars;
12359     DEL (lgl->tlk->lkhd, 2*lgl->nvars);
12360   }
12361   DEL (lgl->tlk, 1);
12362   newhbrs = lgl->stats->hbr.cnt - oldhbrs;
12363   if (newhbrs && !lgl->mt && !lkhdresptr) lgldecomp (lgl);
12364
12365   assert (lgl->simp && lgl->probing && lgl->treelooking);
12366   lgl->simp = lgl->probing = lgl->treelooking = 0;
12367
12368   deltavars = oldrem - lglrem (lgl);
12369   success = deltavars || newhbrs;
12370   if (!lkhdresptr) LGLUPDPEN (prb.treelook, deltavars);
12371   else if (remlits && lgl->limits->lkhdpen < lgl->opts->penmax.val)
12372     lgl->limits->lkhdpen++;
12373   else if (!remlits && lgl->limits->lkhdpen)
12374     lgl->limits->lkhdpen--;
12375   lglprt (lgl, 1 + !success,
12376           "[treelook-%d] removed %d variables, found %d hbrs",
12377           lgl->stats->prb.treelook.count, deltavars, newhbrs);
12378   lglrep (lgl, 2, 'p');
12379   lglstop (lgl);
12380   lglbasicatestats (lgl);
12381   return !lgl->mt;
12382 }
12383
12384 static int lgltreelook (LGL * lgl) {
12385   if (lgldelaying (lgl, "treelook",
12386         &lgl->limits->prb.treelook.del.rem)) return 1;
12387   return lgltreelookaux (lgl, 0);
12388 }
12389
12390 static int lgljwhlook (LGL * lgl) {
12391   Flt best, pos, neg, score;
12392   int res, idx, elit;
12393   Ext * ext;
12394   lgljwh (lgl);
12395   best = FLTMIN;
12396   res = 0;
12397   for (idx = 2; idx < lgl->nvars; idx++) {
12398     if (!lglisfree (lgl, idx)) continue;
12399     assert (!lglieliminated (lgl, idx));
12400     if (lgliblocking (lgl, idx)) continue;
12401     pos = lgl->jwh[lglulit (idx)];
12402     neg = lgl->jwh[lglulit (-idx)];
12403     score = lglmulflt (pos, neg);
12404     score = lgladdflt (score, lgladdflt (pos, neg));
12405     if (res && score <= best) continue;
12406     LOG (1, "jwh look-ahead score %s (pos %s, neg %s) of %d",
12407       lglflt2str (lgl, score), lglflt2str (lgl, pos), lglflt2str (lgl, neg),
12408       idx);
12409     res = (pos > neg) ? idx : -idx;
12410     best = score;
12411   }
12412   if (res) {
12413     elit = lglexport (lgl, res);
12414     ext = lglelit2ext (lgl, elit);
12415     lglprt (lgl, 1, "[jwhlook] best look-ahead %d score %s",
12416             res, lglflt2str (lgl, best));
12417     if (ext->melted) {
12418       ext->melted = 0;
12419       LOG (2, "jwh-look-ahead winner external %d not melted anymore", elit);
12420     } else
12421       LOG (2, "jwh-look-ahead winner external %d was not melted anyhow", elit);
12422   } else LOG (1, "no proper best jwh-look-ahead literal found");
12423   return res;
12424 }
12425
12426 static int lglismislook (LGL * lgl, int max) {
12427   int64_t best, pos, neg, score;
12428   int res, idx, elit, * scores;
12429   Ext * ext;
12430   scores = lglis (lgl);
12431   best = res = 0;
12432   for (idx = 2; idx < lgl->nvars; idx++) {
12433     if (!lglisfree (lgl, idx)) continue;
12434     assert (!lglieliminated (lgl, idx));
12435     if (lgliblocking (lgl, idx)) continue;
12436     pos = scores[idx], neg = scores[-idx];
12437     score = pos * neg + pos + neg;
12438     assert (0 <= score && pos <= score && neg <= score);
12439     if (res) {
12440       if (max && score <= best) continue;
12441       if (!max && score >= best) continue;
12442     }
12443     LOG (1, "%s look-ahead score %lld (pos %lld, neg %lld) of %d",
12444       (max ? "LIS" : "MIS"), (LGLL) score, (LGLL) pos, (LGLL) neg, idx);
12445     res = (pos > neg) ? idx : -idx;
12446     best = score;
12447   }
12448   scores -= lgl->nvars;
12449   DEL (scores, 2*lgl->nvars);
12450   if (res) {
12451     elit = lglexport (lgl, res);
12452     ext = lglelit2ext (lgl, elit);
12453     assert (!ext->eliminated && !ext->blocking);
12454     lglprt (lgl, 1, "[lislook] best %s look-ahead %d score %lld", 
12455       (max ? "LIS" : "MIS"), res, (LGLL) best);
12456     if (ext->melted) {
12457       ext->melted = 0;
12458       LOG (2, "look-ahead winner external %d not melted anymore", elit);
12459     } else
12460       LOG (2, "look-ahead winner external %d was not melted anyhow", elit);
12461   } else LOG (1, "no proper best %s-look-ahead literal found",
12462            (max ? "LIS" : "MIS"));
12463   return res;
12464 }
12465
12466 static int lglislook (LGL * lgl) { return lglismislook (lgl, 1); }
12467 static int lglmislook (LGL * lgl) { return lglismislook (lgl, 0); }
12468
12469 static int64_t lglsatmul64 (int64_t a, int64_t b) {
12470   assert (a >= 0), assert (b >= 0);
12471   return (b && (LLMAX / b < a)) ? LLMAX : a * b;
12472 }
12473
12474 static int64_t lglsatadd64 (int64_t a, int64_t b) {
12475   assert (a >= 0), assert (b >= 0);
12476   return (LLMAX - b < a) ? LLMAX : a + b;
12477 }
12478
12479 static int64_t * lglsumlenscores (LGL * lgl) {
12480   int idx, sign, lit, tag, blit, other, other2, red;
12481   const int *p, * w, * eow, * c;
12482   int64_t * res, len;
12483   Val val, tmp, tmp2;
12484   HTS * hts;
12485   Stk * s;
12486   NEW (res, 2*lgl->nvars);
12487   res += lgl->nvars;
12488   for (idx = 2; idx < lgl->nvars; idx++)
12489     for (sign = -1; sign <= 1; sign += 2) {
12490       lit = sign * idx;
12491       val = lglval (lgl, lit);
12492       if (val > 0) continue;
12493       hts = lglhts (lgl, lit);
12494       if (!hts->offset) continue;
12495       w = lglhts2wchs (lgl, hts);
12496       eow = w + hts->count;
12497       for (p = w; p < eow; p++) {
12498         blit = *p;
12499         tag = blit & MASKCS;
12500         if (tag == TRNCS || tag == LRGCS) p++;
12501         if (tag == LRGCS) continue;
12502         red = blit & REDCS;
12503         if (red) continue;
12504         other = blit >> RMSHFT;
12505         if (abs (other) < abs (lit)) continue;
12506         tmp = lglval (lgl, other);
12507         if (tmp > 0) continue;
12508         if (tag == BINCS) {
12509           assert (!tmp);
12510           res[lit] += 2;
12511           res[other] += 2;
12512         } else {
12513           assert (tag == TRNCS);
12514           other2 = *p;
12515           if (abs (other2) < abs (lit)) continue;
12516           tmp2 = lglval (lgl, other2);
12517           if (tmp2 > 0) continue;
12518           assert ((val > 0) + (tmp > 0) + (tmp2 > 0) == 0);
12519           assert ((val < 0) + (tmp < 0) + (tmp2 < 0) <= 1);
12520           len = !val + !tmp + !tmp2;
12521           if (!val) res[lit] += len;
12522           if (!tmp) res[other] += len;
12523           if (!tmp2) res[other2] += len;
12524         }
12525       }
12526     }
12527   s = &lgl->irr;
12528   for (c = s->start; c < s->top; c = p + 1) {
12529     p = c;
12530     if (*p >= NOTALIT) continue;
12531     val = -1;
12532     len = 0;
12533     while ((other = *p)) {
12534       tmp = lglval (lgl, other);
12535       if (tmp > val) val = tmp;
12536       if (!tmp) len++;
12537       p++;
12538     }
12539     if (val > 0) continue;
12540     for (p = c; (other = *p); p++)
12541       if (!lglval (lgl, other))
12542         res[other] += len;
12543   }
12544   return res;
12545 }
12546
12547 static int lglsumlenlook (LGL * lgl) {
12548   int64_t best, pos, neg, score, * scores;
12549   int res, idx, elit;
12550   Ext * ext;
12551   scores = lglsumlenscores (lgl);
12552   best = res = 0;
12553   for (idx = 2; idx < lgl->nvars; idx++) {
12554     if (!lglisfree (lgl, idx)) continue;
12555     assert (!lglieliminated (lgl, idx));
12556     if (lgliblocking (lgl, idx)) continue;
12557     pos = scores[idx], neg = scores[-idx];
12558     score = lglsatadd64 (lglsatmul64 (pos, neg), lglsatadd64 (pos, neg));
12559     assert (0 <= score), assert (pos <= score), assert (neg <= score);
12560     if (res && score <= best) continue;
12561     LOG (1,
12562       "look-ahead score %lld (pos %lld, neg %lld) of %d",
12563       (LGLL) score, (LGLL) pos, (LGLL) neg, idx);
12564     res = (pos > neg) ? idx : -idx;
12565     best = score;
12566   }
12567   scores -= lgl->nvars;
12568   DEL (scores, 2*lgl->nvars);
12569   if (res) {
12570     elit = lglexport (lgl, res);
12571     ext = lglelit2ext (lgl, elit);
12572     assert (!ext->eliminated && !ext->blocking);
12573     lglprt (lgl, 1,
12574       "[sumlook] best look-ahead %d score %lld", 
12575       res, (LGLL) best);
12576     if (ext->melted) {
12577       ext->melted = 0;
12578       LOG (2, "look-ahead winner external %d not melted anymore", elit);
12579     } else
12580       LOG (2, "look-ahead winner external %d was not melted anyhow", elit);
12581   } else LOG (1, "no proper best look-ahead literal found");
12582   return res;
12583 }
12584
12585 static int lglschedbasicprobe (LGL * lgl, Stk * probes, int round) {
12586   int idx, res, i, j, donotbasicprobes, keepscheduled;
12587   assert (lglmtstk (probes));
12588   for (idx = 2; idx < lgl->nvars; idx++) {
12589     if (!lglisfree (lgl, idx)) continue;
12590     if (lgl->opts->prbasic.val <= 1 &&
12591         (lglhasbins (lgl, idx) == lglhasbins (lgl, -idx))) continue;
12592     LOG (1, "new probe %d", idx);
12593     lglpushstk (lgl, probes, idx);
12594   }
12595   res = lglcntstk (probes);
12596   donotbasicprobes = keepscheduled = 0;
12597   for (i = 0; i < res; i++) {
12598     idx = lglpeek (probes, i);
12599     if (!idx) continue;
12600     assert (lglisfree (lgl, idx));
12601     if (lglavar (lgl, idx)->donotbasicprobe) donotbasicprobes++;
12602     else keepscheduled++;
12603   }
12604   if (!keepscheduled) {
12605     for (i = 0; i < res; i++) {
12606       idx = lglpeek (probes, i);
12607       if (!idx) continue;
12608       assert (lglisfree (lgl, idx));
12609       lglavar (lgl, idx)->donotbasicprobe = 0;
12610       keepscheduled++;
12611     }
12612     donotbasicprobes = 0;
12613   }
12614   for (i = 0; i < res; i++) {
12615     idx = lglpeek (probes, i);
12616     if (!idx) continue;
12617     assert (lglisfree (lgl, idx));
12618     if (lglavar (lgl, idx)->donotbasicprobe) donotbasicprobes++;
12619     else keepscheduled++;
12620   }
12621   j = 0;
12622   for (i = 0; i < res; i++) {
12623     idx = lglpeek (probes, i);
12624     if (!idx) continue;
12625     if (!lglavar (lgl, idx)->donotbasicprobe)
12626       lglpoke (probes, j++, idx);
12627   }
12628   lglrststk (probes, (res = j));
12629   if (!res)
12630     lglprt (lgl, 2, "[basicprobe-%d-%d] no potential probes found",
12631             lgl->stats->prb.basic.count, round);
12632   else if (!donotbasicprobes)
12633     lglprt (lgl, 2, "[basicprobe-%d-%d] scheduled all %d potential probes",
12634             lgl->stats->prb.basic.count, round, res);
12635   else
12636     lglprt (lgl, 2, "[basicprobe-%d-%d] scheduled %d probes %.0f%%",
12637             lgl->stats->prb.basic.count, round,
12638             res, lglpcnt (res, lglrem (lgl)));
12639   return res;
12640 }
12641
12642 static void lglsetprbasiclim (LGL * lgl) {
12643   int64_t limit, irrlim;
12644   int pen;
12645   if (lgl->opts->prbasicrtc.val || lgl->opts->prbrtc.val) {
12646     lgl->limits->prb.steps = LLMAX;
12647     lglprt (lgl, 1, "[basicprobe-%d] no limit (run to completion)", 
12648             lgl->stats->prb.basic.count);
12649   } else {
12650     limit = (lgl->opts->prbasicreleff.val*lglvisearch (lgl))/1000;
12651     if (limit < lgl->opts->prbasicmineff.val)
12652       limit = lgl->opts->prbasicmineff.val;
12653     if (lgl->opts->prbasicmaxeff.val >= 0 &&
12654         limit > lgl->opts->prbasicmaxeff.val)
12655       limit = lgl->opts->prbasicmaxeff.val;
12656     limit >>= (pen = lgl->limits->prb.basic.pen + lglszpen (lgl));
12657     irrlim = 2*lgl->stats->irr.clauses.cur;
12658     irrlim >>= lgl->limits->simp.pen;
12659     if (lgl->opts->irrlim.val && limit < irrlim) {
12660       limit = irrlim;
12661       lglprt (lgl, 1,
12662         "[basicprobe-%d] limit %lld based on %d irredundant clauses",
12663         lgl->stats->prb.basic.count,
12664         (LGLL) limit, lgl->stats->irr.clauses.cur);
12665     } else
12666       lglprt (lgl, 1, "[basicprobe-%d] limit %lld penalty %d = %d + %d",
12667         lgl->stats->prb.basic.count, (LGLL) limit,
12668         pen, lgl->limits->prb.basic.pen, lglszpen (lgl));
12669     lgl->limits->prb.steps = lgl->stats->prb.basic.steps + limit;
12670   }
12671 }
12672
12673 static void lglbasicprobereport (LGL * lgl,
12674                                  int probed, int nprobes, double start) {
12675   lglgenericreport (lgl,
12676     "basicprobe", lgl->stats->prb.basic.count, probed, nprobes, start);
12677 }
12678
12679 static int lglbasicprobe (LGL * lgl) {
12680 #ifndef NLGLOG
12681   int origprobed = lgl->stats->prb.basic.probed;
12682 #endif
12683   int origfailed = lgl->stats->prb.basic.failed;
12684   int origlifted = lgl->stats->prb.basic.lifted;
12685   int orighbr = lgl->stats->hbr.cnt;
12686   int root, failed, lifted, units, first, idx;
12687   int oldrem, deltarem, deltahbr, remprobes;
12688   int nprobes, success, round, probed;
12689   int oldhbr, oldfailed, oldlifted;
12690   Stk probes, lift, saved;
12691   unsigned pos, delta;
12692   double start;
12693   if (!lgl->nvars) return 1;
12694   if (!lgl->opts->probe.val) return 1;
12695   if (lgldelaying (lgl, "basicprobe",
12696         &lgl->limits->prb.basic.del.rem)) return 1;
12697   lglstart (lgl, &lgl->times->prb.basic);
12698   lgl->stats->prb.basic.count++;
12699   if (lgl->level > 0) lglbacktrack (lgl, 0);
12700   assert (!lgl->simp && !lgl->probing && !lgl->basicprobing);
12701   lgl->simp = lgl->probing = lgl->basicprobing = 1;
12702   CLR (lift); CLR (probes); CLR (saved);
12703   lglsetprbasiclim (lgl);
12704   oldfailed = origfailed;
12705   oldlifted = origlifted;
12706   oldhbr = lgl->stats->hbr.cnt;
12707   oldrem = lglrem (lgl);
12708   round = 0;
12709 RESTART:
12710   nprobes = lglschedbasicprobe (lgl, &probes, round);
12711   remprobes = 0;
12712   if (!nprobes) goto DONE;
12713   pos = lglrand (lgl) % nprobes;
12714   delta = lglrand (lgl) % nprobes;
12715   if (!delta) delta++;
12716   probed = 0;
12717   start = lglgetime (lgl);
12718   lglbasicprobereport (lgl, probed, nprobes, start);
12719   while (lglgcd (delta, nprobes) > 1)
12720     if (++delta == nprobes) delta = 1;
12721   LOG (1, "probing start %u delta %u mod %u", pos, delta, nprobes);
12722   first = 0;
12723   while (!lgl->mt) {
12724     if (lgl->stats->prb.basic.steps >= lgl->limits->prb.steps) break;
12725     if (lglterminate (lgl)) break;
12726     if (!lglsyncunits (lgl)) break;
12727     assert (pos < (unsigned) nprobes);
12728     root = probes.start[pos];
12729     probes.start[pos] = 0;
12730     if (!root || root == first) {
12731       lglprt (lgl, 1,
12732         "[basicprobe-%d-%d] %d sched %.0f%%, %d failed, %d lifted, %d hbrs",
12733         lgl->stats->prb.basic.count, round,
12734         nprobes, lglpcnt (nprobes, lglrem (lgl)),
12735         lgl->stats->prb.basic.failed - oldfailed,
12736         lgl->stats->prb.basic.lifted - oldlifted,
12737         lgl->stats->hbr.cnt - oldhbr);
12738       for (idx = 2; idx < lgl->nvars; idx++)
12739         lglavar (lgl, idx)->donotbasicprobe = 0;
12740       break;
12741     }
12742     lglavar (lgl, root)->donotbasicprobe = 1;
12743     if (!first) first = root;
12744     pos += delta;
12745     if (pos >= nprobes) pos -= nprobes;
12746     if (!lglisfree (lgl, root)) continue;
12747     lglbasicprobereport (lgl, ++probed, nprobes, start);
12748     lglbasicprobelit (lgl, root);
12749   }
12750   lglbasicprobereport (lgl, probed, nprobes, start);
12751   if (!lgl->mt) {
12752     if (lgl->stats->prb.basic.steps >= lgl->limits->prb.steps) {
12753       while (!lglmtstk (&probes))
12754         if((idx = lglpopstk (&probes)) && lglisfree (lgl, idx)) remprobes++;
12755       lglprt (lgl, 1, 
12756         "[basicprobe-%d-%d] %d probes remain %.0f%% after last round",
12757         lgl->stats->prb.basic.count, round,
12758         remprobes, lglpcnt (remprobes, lglrem (lgl)));
12759     } else if (round >= lgl->opts->prbasicroundlim.val) {
12760       lglprt (lgl, 1,
12761               "[basicprobe-%d-%d] round limit %d hit",
12762               lgl->stats->prb.basic.count, round, 
12763               lgl->opts->prbasicroundlim.val);
12764     } else if (lgl->stats->prb.basic.failed > oldfailed ||
12765                lgl->stats->prb.basic.lifted > oldlifted ||
12766                lgl->stats->hbr.cnt > oldhbr) {
12767       oldfailed = lgl->stats->prb.basic.failed;
12768       oldlifted = lgl->stats->prb.basic.lifted;
12769       lglclnstk (&probes);
12770       if (oldhbr < lgl->stats->hbr.cnt && lgl->opts->decompose.val)
12771         if (!lgldecomp (lgl)) goto DONE;
12772       oldhbr = lgl->stats->hbr.cnt;
12773       round++;
12774       goto RESTART;
12775     } else {
12776       assert (!remprobes);
12777       lglprt (lgl, 1,
12778               "[basicprobe-%d-%d] fully completed probing",
12779               lgl->stats->prb.basic.count, round);
12780       for (idx = 2; idx < lgl->nvars; idx++)
12781         lglavar (lgl, idx)->donotbasicprobe = 0;
12782     }
12783   }
12784 DONE:
12785   lglrelstk (lgl, &lift);
12786   lglrelstk (lgl, &probes);
12787   lglrelstk (lgl, &saved);
12788
12789   assert (lgl->stats->hbr.cnt >= orighbr);
12790   assert (lglrem (lgl) <= oldrem);
12791   deltarem = oldrem - lglrem (lgl);
12792   deltahbr = lgl->stats->hbr.cnt - orighbr;
12793   success = deltarem || deltahbr;
12794   LGLUPDPEN (prb.basic, deltarem);
12795   assert (lgl->stats->prb.basic.failed >= origfailed);
12796   assert (lgl->stats->prb.basic.lifted >= origlifted);
12797   failed = lgl->stats->prb.basic.failed - origfailed;
12798   lifted = lgl->stats->prb.basic.lifted - origlifted;
12799 #ifndef NLGLOG
12800   assert (lgl->stats->prb.basic.probed >= origprobed);
12801   probed = lgl->stats->prb.basic.probed - origprobed;
12802   LOG (1, "%ssuccessfully probed %d out of %d probes %.1f%%",
12803        success ? "" : "un", probed, nprobes, lglpcnt (probed, nprobes));
12804   LOG (1, "found %d failed %.1f%% lifted %d through probing",
12805        failed, lglpcnt (failed, probed), lifted);
12806 #endif
12807   assert (lgl->probing && lgl->simp && lgl->basicprobing);
12808   lgl->simp = lgl->probing = lgl->basicprobing = 0;
12809   units = failed + lifted;
12810   lglprt (lgl, 1 + !units,
12811     "[basicprobe-%d-%d] %d units = %d failed (%.0f%%) + %d lifted (%.0f%%)",
12812     lgl->stats->prb.basic.count, round,
12813     units, failed, lglpcnt (failed, units), lifted, lglpcnt (lifted, units));
12814   lglprt (lgl, 1 + !success,
12815     "[basicprobe-%d-%d] removed %d variables, found %d hbrs",
12816     lgl->stats->prb.basic.count, round, deltarem, deltahbr);
12817   lglrep (lgl, 2, 'p');
12818   lglstop (lgl);
12819   lglbasicatestats (lgl);
12820   return !lgl->mt;
12821 }
12822
12823 static int lglsmallirr (LGL * lgl) {
12824   int maxirrlidx = lglcntstk (&lgl->irr), limit;
12825   int64_t tmp = MAXREDLIDX;
12826   tmp *= lgl->opts->smallirr.val;
12827   tmp /= 100;
12828   limit = (tmp < INT_MAX) ? tmp : INT_MAX;
12829   if (maxirrlidx >= limit) return 0;
12830   return  1;
12831 }
12832
12833 static int lglprobe (LGL * lgl) {
12834   int res = 1, mod = 0, all, small = lglsmallirr (lgl);
12835   int (*prb[3])(LGL *);
12836   lglstart (lgl, &lgl->times->prb.all);
12837   if (small && lgl->opts->prbsimple.val) prb[mod++] = lglsimpleprobe;
12838   if (small && lgl->opts->treelook.val) prb[mod++] = lgltreelook;
12839   if (lgl->opts->prbasic.val) prb[mod++] = lglbasicprobe;
12840   all = lgl->stats->prb.simple.count;
12841   all += lgl->stats->prb.basic.count;
12842   all += lgl->stats->prb.treelook.count;
12843   if (lgl->stats->simp.count == 2) {
12844     int i;
12845     res = 1;
12846     for (i = 0; res && i < mod; i++) res = prb[i] (lgl);
12847   } else res = mod ? prb[all % mod] (lgl) : 1;
12848   lglstop (lgl);
12849   return res;
12850 }
12851
12852 static void lglinitevars (LGL * lgl) {
12853   EVar * ev;
12854   int idx;
12855   assert (lgl->occs);
12856   NEW (lgl->evars, lgl->nvars);
12857   for (idx = 2; idx < lgl->nvars; idx++) {
12858     ev = lgl->evars + idx;
12859     ev->pos = -1;
12860   }
12861 }
12862
12863 static void lgldense (LGL * lgl, int occstoo) {
12864   int lit, lidx, count, idx, other, other2, blit, sign, tag, red;
12865   const int * start, * top, * c, * p, * eow;
12866   int * q, * w;
12867   EVar * ev;
12868   HTS * hts;
12869   LOG (1, "transition to dense mode");
12870   assert (!lgl->dense);
12871   assert (!lgl->evars);
12872   assert (lglsmallirr (lgl));
12873   assert (lglmtstk (&lgl->esched));
12874   assert (!lgl->eliminating || !lgl->elm->pivot);
12875   lgl->stats->dense++;
12876   count = 0;
12877   if (lgl->occs) lglinitevars (lgl);
12878   for (idx = 2; idx < lgl->nvars; idx++)
12879     for (sign = -1; sign <= 1; sign += 2) {
12880       lit = sign * idx;
12881       hts = lglhts (lgl, lit);
12882       if (!hts->count) continue;
12883       q = w = lglhts2wchs (lgl, hts);
12884       eow = w + hts->count;
12885       for (p = w; p < eow; p++) {
12886         blit = *p;
12887         tag = blit & MASKCS;
12888         if (tag == TRNCS || tag == LRGCS) p++;
12889         red = blit & REDCS;
12890         if (red && tag == LRGCS) continue;
12891         *q++ = blit;
12892         if (tag == LRGCS || tag == TRNCS) *q++ = *p;
12893         if (red) continue;
12894         if (tag == BINCS || tag == TRNCS) {
12895           other = blit >> RMSHFT;
12896           if (abs (other) < idx) continue;
12897           if (tag == TRNCS) {
12898             other2 = *p;
12899             if (abs (other2) < idx) continue;
12900             lglincocc (lgl, other2), count++;
12901           }
12902           lglincocc (lgl, lit), count++;
12903           lglincocc (lgl, other), count++;
12904         } else {
12905           assert (tag == LRGCS);
12906         }
12907       }
12908       lglshrinkhts (lgl, hts, q - w);
12909     }
12910   if (count)
12911     LOG (1, "counted %d occurrences in small irredundant clauses", count);
12912   if (occstoo) {
12913     count = 0;
12914     start = lgl->irr.start;
12915     top = lgl->irr.top;
12916     for (c = start; c < top; c = p + 1) {
12917       p = c;
12918       if (*c >= NOTALIT) continue;
12919       lidx = c - start;
12920       assert (lidx < MAXIRRLIDX);
12921       blit = (lidx << RMSHFT) | OCCS;
12922       for (; (lit = *p); p++) {
12923         hts = lglhts (lgl, lit);
12924         lglpushwch (lgl, hts, blit);
12925         lglincocc (lgl, lit), count++;
12926       }
12927     }
12928   }
12929   if (count)
12930     LOG (1, "counted %d occurrences in large irredundant clauses", count);
12931   count = 0;
12932   if (lgl->occs) {
12933     for (idx = 2; idx < lgl->nvars; idx++) {
12934       ev = lglevar (lgl, idx);
12935       if (ev->pos >= 0) continue;
12936       if (lglifrozen (lgl, idx)) continue;
12937       if (lgl->donotsched) {
12938         AVar * av = lglavar (lgl, idx);
12939         if (lgl->eliminating && av->donotelm) continue;
12940         if (lgl->blocking && av->donotblk) continue;
12941       }
12942       assert (!ev->occ[0] && !ev->occ[1]);
12943       lglesched (lgl, idx);
12944       count++;
12945     }
12946     if (count) LOG (1, "scheduled %d zombies", count);
12947   }
12948   LOG (1, "continuing in dense mode");
12949   lgl->dense = 1 + occstoo;
12950   lglfullyconnected (lgl);
12951   if (lgl->occs && lgl->opts->verbose.val >= 1) {
12952     const char * str;
12953     int inst, vl;
12954     count = 0;
12955     if (lgl->eliminating) str = "elim", inst = lgl->stats->elm.count, vl = 1;
12956     else if (lgl->blocking) str = "block", inst = lgl->stats->blk.count, vl=1;
12957     else str = "dense", inst = lgl->stats->dense, vl = 2;
12958     for (idx = 2; idx < lgl->nvars; idx++)
12959       if (lglevar (lgl, idx)->pos >= 0) count++;
12960     lglprt (lgl, vl,
12961       "[%s-%d] scheduled %d variables %.0f%%",
12962       str, inst, count, lglpcnt (count, lgl->nvars-2));
12963   }
12964 }
12965
12966 static void lglsparse (LGL * lgl) {
12967   int idx, sign, lit, count, blit, tag;
12968   int * w, *p, * eow, * q;
12969   HTS * hts;
12970   assert (!lgl->notfullyconnected);
12971   assert (lgl->dense);
12972   lgl->stats->sparse++;
12973   count = 0;
12974   for (idx = 2; idx < lgl->nvars; idx++)
12975     for (sign = -1; sign <= 1; sign += 2) {
12976       lit = sign * idx;
12977       hts = lglhts (lgl, lit);
12978       if (!hts->count) continue;
12979       w = lglhts2wchs (lgl, hts);
12980       eow = w + hts->count;
12981       for (p = q = w; p < eow; p++) {
12982         blit = *p;
12983         tag = blit & MASKCS;
12984         if (tag == OCCS) { count++; continue; }
12985         *q++ = blit;
12986         if (tag == BINCS) continue;
12987         assert (tag == LRGCS || tag == TRNCS);
12988         assert (p + 1 < eow);
12989         *q++ = *++p;
12990       }
12991       assert (hts->count - (p - q) == q - w);
12992       lglshrinkhts (lgl, hts, q - w);
12993     }
12994   if (lgl->occs) {
12995     DEL (lgl->evars, lgl->nvars);
12996     lglrelstk (lgl, &lgl->esched);
12997   }
12998   LOG (1, "removed %d full irredundant occurrences", count);
12999   lgl->dense = 0;
13000   lgl->notfullyconnected = 1;
13001   LOG (1, "large clauses not fully connected yet");
13002 }
13003
13004 static int lglm2i (LGL * lgl, int mlit) {
13005   int res, midx = abs (mlit);
13006   assert (0 < midx);
13007   res = lglpeek (&lgl->elm->m2i, midx);
13008   if (mlit < 0) res = -res;
13009   return res;
13010 }
13011
13012 static int lgli2m (LGL * lgl, int ilit) {
13013   AVar * av = lglavar (lgl, ilit);
13014   int res = av->mark;
13015   if (!res) {
13016     res = lglcntstk (&lgl->seen) + 1;
13017     av->mark = res;
13018     assert (2*lglcntstk (&lgl->seen) == lglcntstk (&lgl->elm->noccs) - 2);
13019     assert (2*lglcntstk (&lgl->seen) == lglcntstk (&lgl->elm->mark) - 2);
13020     assert (2*lglcntstk (&lgl->seen) == lglcntstk (&lgl->elm->occs) - 2);
13021     assert (lglcntstk (&lgl->seen) == lglcntstk (&lgl->elm->m2i) - 1);
13022     lglpushstk (lgl, &lgl->seen, abs (ilit));
13023     lglpushstk (lgl, &lgl->elm->noccs, 0);
13024     lglpushstk (lgl, &lgl->elm->noccs, 0);
13025     lglpushstk (lgl, &lgl->elm->mark, 0);
13026     lglpushstk (lgl, &lgl->elm->mark, 0);
13027     lglpushstk (lgl, &lgl->elm->occs, 0);
13028     lglpushstk (lgl, &lgl->elm->occs, 0);
13029     lglpushstk (lgl, &lgl->elm->m2i, abs (ilit));
13030     LOG (4, "mapped internal variable %d to marked variable %d",
13031          abs (ilit), res);
13032   }
13033   if (ilit < 0) res = -res;
13034   return res;
13035 }
13036
13037 static unsigned lglsig (int lit) {
13038   unsigned ulit = lglulit (lit), res;
13039   assert (ulit >= 2);
13040   ulit -= 2;
13041   res = (1u << (ulit & 31));
13042   return res;
13043 }
13044
13045 static void lgladdecl (LGL * lgl, const int * c) {
13046   int ilit, mlit, umlit, size = 0, next, prev;
13047   unsigned csig = 0;
13048   const int * p;
13049   Val val;
13050 #if !defined (NDEBUG) || !defined (NLGLOG)
13051   int lidx;
13052 #endif
13053   LOGCLS (3, c, "copying irredundant clause");
13054   INCSTEPS (elm.copies);
13055   size = 0;
13056   for (p = c; (ilit = *p); p++) {
13057     val = lglval (lgl, ilit);
13058     assert (val <= 0);
13059     if (val < 0) continue;
13060     size++;
13061     if (abs (ilit) == lgl->elm->pivot) continue;
13062     mlit = lgli2m (lgl, ilit);
13063     assert (abs (mlit) != 1);
13064     csig |= lglsig (mlit);
13065   }
13066   assert (size >= 1);
13067   next = lglcntstk (&lgl->elm->lits);
13068 #if !defined (NDEBUG) || !defined (NLGLOG)
13069   lidx = next;
13070 #endif
13071   assert (next > 0);
13072   for (p = c; (ilit = *p); p++) {
13073     val = lglval (lgl, ilit);
13074     if (val < 0) continue;
13075     mlit = lgli2m (lgl, ilit);
13076     lglpushstk (lgl, &lgl->elm->lits, mlit);
13077     umlit = lglulit (mlit);
13078     prev = lglpeek (&lgl->elm->occs, umlit);
13079     lglpushstk (lgl, &lgl->elm->next, prev);
13080     lglpoke (&lgl->elm->occs, umlit, next++);
13081     lglpushstk (lgl, &lgl->elm->csigs, csig);
13082     lglpushstk (lgl, &lgl->elm->sizes, size);
13083     lgl->elm->noccs.start[umlit]++;
13084   }
13085   lglpushstk (lgl, &lgl->elm->lits, 0);
13086   lglpushstk (lgl, &lgl->elm->next, 0);
13087   lglpushstk (lgl, &lgl->elm->csigs, 0);
13088   lglpushstk (lgl, &lgl->elm->sizes, 0);
13089   lgl->elm->necls++;
13090   LOGCLS (4, lgl->elm->lits.start + lidx, "copied and mapped clause");
13091 #ifndef NDEBUG
13092   LOGMCLS (4, lgl->elm->lits.start + lidx, "copied and remapped clause");
13093   {
13094     int i, j = 0;
13095     for (i = 0; c[i]; i++) {
13096       Val val = lglval (lgl, c[i]);
13097       assert (val <= 0);
13098       if (val < 0) continue;
13099       assert (c[i] == lglm2i (lgl, lglpeek (&lgl->elm->lits, lidx + j++)));
13100     }
13101   }
13102 #endif
13103 }
13104
13105 static int lglecls (LGL * lgl, int lit) {
13106   int blit, tag, red, other, lidx, count;
13107   const int * p, * w, * eow, * c;
13108   int d[4];
13109   HTS * hts;
13110   LOG (3, "copying irredundant clauses with %d", lit);
13111   count = 0;
13112   hts = lglhts (lgl, lit);
13113   if (!hts->count) return 0;
13114   w = lglhts2wchs (lgl, hts);
13115   eow = w + hts->count;
13116   for (p = w; p < eow; p++) {
13117     blit = *p;
13118     tag = blit & MASKCS;
13119     if (tag == TRNCS || tag == LRGCS) p++;
13120     if (tag == LRGCS) continue;
13121     red = blit & REDCS;
13122     if (red) continue;
13123     if (tag == BINCS || tag == TRNCS) {
13124       d[0] = lit;
13125       other = blit >> RMSHFT;
13126       d[1] = other;
13127       if (tag == TRNCS) d[2] = *p, d[3] = 0;
13128       else d[2] = 0;
13129       c = d;
13130     } else {
13131       assert (tag == OCCS);
13132       lidx = (tag == OCCS) ? (blit >> RMSHFT) : *p;
13133       c = lglidx2lits (lgl, 0, lidx);
13134     }
13135     lgladdecl (lgl, c);
13136     count++;
13137   }
13138   return count;
13139 }
13140
13141 static void lglrstecls (LGL * lgl)  {
13142   assert (lgl->elm->pivot);
13143   lglclnstk (&lgl->elm->lits);
13144   lglclnstk (&lgl->elm->next);
13145   lglclnstk (&lgl->elm->csigs);
13146   lglclnstk (&lgl->elm->sizes);
13147   lglclnstk (&lgl->elm->occs);
13148   lglclnstk (&lgl->elm->noccs);
13149   lglclnstk (&lgl->elm->mark);
13150   lglclnstk (&lgl->elm->m2i);
13151   lglpopnunmarkstk (lgl, &lgl->seen);
13152   lgl->elm->pivot = 0;
13153 }
13154
13155 static void lglrelecls (LGL * lgl)  {
13156   lglrelstk (lgl, &lgl->elm->lits);
13157   lglrelstk (lgl, &lgl->elm->next);
13158   lglrelstk (lgl, &lgl->elm->csigs);
13159   lglrelstk (lgl, &lgl->elm->sizes);
13160   lglrelstk (lgl, &lgl->elm->occs);
13161   lglrelstk (lgl, &lgl->elm->noccs);
13162   lglrelstk (lgl, &lgl->elm->mark);
13163   lglrelstk (lgl, &lgl->elm->m2i);
13164   lglrelstk (lgl, &lgl->elm->clv);
13165 }
13166
13167 static void lglinitecls (LGL * lgl, int idx) {
13168 #ifndef NLGLOG
13169   int clauses;
13170 #endif
13171   assert (!lgl->elm->pivot);
13172   assert (idx >= 2);
13173   assert (lglmtstk (&lgl->elm->lits));
13174   assert (lglmtstk (&lgl->elm->next));
13175   assert (lglmtstk (&lgl->elm->csigs));
13176   assert (lglmtstk (&lgl->elm->sizes));
13177   assert (lglmtstk (&lgl->elm->occs));
13178   assert (lglmtstk (&lgl->elm->noccs));
13179   assert (lglmtstk (&lgl->elm->m2i));
13180   assert (lglmtstk (&lgl->seen));
13181   lgl->elm->pivot = idx;
13182   lglpushstk (lgl, &lgl->elm->mark, 0);
13183   lglpushstk (lgl, &lgl->elm->mark, 0);
13184   lglpushstk (lgl, &lgl->elm->occs, 0);
13185   lglpushstk (lgl, &lgl->elm->occs, 0);
13186   lglpushstk (lgl, &lgl->elm->noccs, 0);
13187   lglpushstk (lgl, &lgl->elm->noccs, 0);
13188   lglpushstk (lgl, &lgl->elm->m2i, 0);
13189   (void) lgli2m (lgl, idx);
13190   lglpushstk (lgl, &lgl->elm->lits, 0);
13191   lglpushstk (lgl, &lgl->elm->next, 0);
13192   lglpushstk (lgl, &lgl->elm->csigs, 0);
13193   lglpushstk (lgl, &lgl->elm->sizes, 0);
13194   lgl->elm->necls = 0;
13195 #ifndef NLGLOG
13196   clauses =
13197 #endif
13198   lglecls (lgl, idx);
13199   lgl->elm->negcls = lgl->elm->necls;
13200   lgl->elm->neglidx = lglcntstk (&lgl->elm->lits);
13201 #ifndef NLGLOG
13202   clauses +=
13203 #endif
13204   lglecls (lgl, -idx);
13205   LOG (2, "found %d variables in %d clauses with %d or %d",
13206        lglcntstk (&lgl->seen), clauses, idx, -idx);
13207   assert (lgl->elm->pivot);
13208 }
13209
13210 static void lglelrmcls (LGL * lgl, int lit, int * c, int clidx) {
13211   int lidx, i, other, ulit, * lits, * csigs, blit, tag, red, other2;
13212   int * p, * eow, * w, count;
13213   HTS * hts;
13214 #ifndef NDEBUG
13215   int size;
13216 #endif
13217   lits = lgl->elm->lits.start;
13218   csigs = lgl->elm->csigs.start;
13219   assert (lits < c && c < lgl->elm->lits.top - 1);
13220   lidx = c - lits;
13221   LOGCLS (2, c, "removing clause");
13222   for (i = lidx; (other = lits[i]); i++) {
13223     assert (other < NOTALIT);
13224     lits[i] = REMOVED;
13225     csigs[i] = 0;
13226     ulit = lglulit (other);
13227     assert (ulit < lglcntstk (&lgl->elm->noccs));
13228     assert (lgl->elm->noccs.start[ulit] > 0);
13229     lgl->elm->noccs.start[ulit] -= 1;
13230   }
13231 #ifndef NDEBUG
13232   size = lglpeek (&lgl->elm->sizes, lidx);
13233 #endif
13234   hts = lglhts (lgl, lit);
13235   assert (hts->count > 0 && hts->count >= clidx);
13236   w = lglhts2wchs (lgl, hts);
13237   eow = w + hts->count;
13238   blit = tag = count = 0;
13239   for (p = w; p < eow; p++) {
13240     blit = *p;
13241     tag = blit & MASKCS;
13242     if (tag == TRNCS || tag == LRGCS) p++;
13243     if (tag == LRGCS) continue;
13244     red = blit & REDCS;
13245     if (red) continue;
13246     if (count == clidx) break;
13247     count++;
13248   }
13249   assert (count == clidx);
13250   assert (blit && tag);
13251   assert (p < eow);
13252   if (tag == BINCS) {
13253     assert (size >= 2);
13254     other = blit >> RMSHFT;
13255     lglrmbcls (lgl, lit, other, 0);
13256   } else if (tag == TRNCS) {
13257     other = blit >> RMSHFT;
13258     other2 = *p;
13259     lglrmtcls (lgl, lit, other, other2, 0);
13260   } else {
13261     assert (tag == OCCS);
13262     lidx = (tag == OCCS) ? (blit >> RMSHFT) : *p;
13263 #ifndef NDEBUG
13264     {
13265       int * q, * d = lglidx2lits (lgl, 0, lidx);
13266       for (q = d; *q; q++)
13267         ;
13268       assert (q - d >= size);
13269     }
13270 #endif
13271     lglrmlcls (lgl, lidx, 0);
13272   }
13273 }
13274
13275 #define BWL 2
13276
13277 static int lglbacksub (LGL * lgl, int * c, int str) {
13278   int * start = lgl->elm->lits.start, * p, * q, marked = 0, res, * d;
13279   int lit, ulit, occ, next, osize, other, uolit, size, plit, phase, clidx;
13280   unsigned ocsig, csig = 0, masksig;
13281 #ifndef NLGLOG
13282   const char * mode = str ? "strengthening" : "subsumption";
13283 #endif
13284   LOGMCLS (BWL + 1, c, "backward %s check for clause", mode);
13285   LOGCLS (BWL + 1, c, "backward %s check for mapped clause", mode);
13286   phase = (c - start) >= lgl->elm->neglidx;
13287   for (p = c; (lit = *p); p++)
13288     if (abs (lit) != 1)
13289       csig |= lglsig (lit);
13290   size = p - c;
13291   assert (csig == lglpeek (&lgl->elm->csigs, c - start));
13292   assert (size == lglpeek (&lgl->elm->sizes, c - start));
13293   res = 0;
13294
13295   if (str) phase = !phase;
13296   lit = phase ? -1 : 1;
13297   masksig = ~(lglsig (-lit) | lglsig (lit));
13298
13299   ulit = lglulit (lit);
13300   occ = lglpeek (&lgl->elm->noccs, ulit);
13301   if (!str && occ <= 1) return 0;
13302   if (str && !occ) return 0;
13303   for (next = lglpeek (&lgl->elm->occs, ulit);
13304        !res && next;
13305        next = lglpeek (&lgl->elm->next, next)) {
13306       INCSTEPS (elm.steps);
13307       if (next == p - start) continue;
13308       if (phase != (next >= lgl->elm->neglidx)) continue;
13309       plit = lglpeek (&lgl->elm->lits, next);
13310       if (plit >= NOTALIT) continue;
13311       assert (plit == lit);
13312       osize = lglpeek (&lgl->elm->sizes, next);
13313       if (osize > size) continue;
13314       ocsig = lglpeek (&lgl->elm->csigs, next);
13315       assert (ocsig);
13316       ocsig &= masksig;
13317       if ((ocsig & ~csig)) continue;
13318       if (!marked) {
13319         for (q = c; (other = *q); q++) {
13320           if (str && abs (other) == 1) other = -other;
13321           uolit = lglulit (other);
13322           assert (!lglpeek (&lgl->elm->mark, uolit));
13323           lglpoke (&lgl->elm->mark, uolit, 1);
13324         }
13325         marked = 1;
13326       }
13327       d = lgl->elm->lits.start + next;
13328       if (c <= d && d < c + size) continue;
13329       if (str) lgl->stats->elm.strchks++; else lgl->stats->elm.subchks++;
13330       while (d[-1]) d--;
13331       assert (c != d);
13332       LOGMCLS (BWL + 1, d, "backward %s check with clause", mode);
13333       res = 1;
13334       for (q = d; res && (other = *q); q++) {
13335         uolit = lglulit (other);
13336         res = lglpeek (&lgl->elm->mark, uolit);
13337       }
13338       if (!res || !str || osize < size) continue;
13339       LOGMCLS (BWL, d,
13340         "static double strengthened by double self-subsuming resolution");
13341       assert ((c - start) < lgl->elm->neglidx);
13342       assert ((d - start) >= lgl->elm->neglidx);
13343       assert (phase);
13344       clidx = 0;
13345       q = lgl->elm->lits.start + lgl->elm->neglidx;
13346       while (q < d) {
13347         other = *q++;
13348         if (other >= NOTALIT) { while (*q++) ; continue; }
13349         if (!other) clidx++;
13350       }
13351       LOGMCLS (BWL, d,
13352         "strengthened and subsumed original irredundant clause");
13353       LOGCLS (BWL, d,
13354         "strengthened and subsumed mapped irredundant clause");
13355       lglelrmcls (lgl, -lgl->elm->pivot, d, clidx);
13356   }
13357   if (marked) {
13358     for (p = c; (lit = *p); p++) {
13359       if (str && abs (lit) == 1) lit = -lit;
13360       ulit = lglulit (lit);
13361       assert (lglpeek (&lgl->elm->mark, ulit));
13362       lglpoke (&lgl->elm->mark, ulit, 0);
13363     }
13364   }
13365   return res;
13366 }
13367
13368 static void lglelmsub (LGL * lgl) {
13369   int clidx, count, subsumed, pivot, * c;
13370   count = clidx = subsumed = 0;
13371   pivot = lgl->elm->pivot;
13372   for (c = lgl->elm->lits.start + 1;
13373        c < lgl->elm->lits.top &&
13374          lgl->limits->elm.steps > lgl->stats->elm.steps;
13375        c++) {
13376     INCSTEPS (elm.steps);
13377     if (count++ == lgl->elm->negcls) clidx = 0, pivot = -pivot;
13378     if (lglbacksub (lgl, c, 0)) {
13379       subsumed++;
13380       lgl->stats->elm.sub++;
13381       LOGMCLS (BWL, c, "subsumed original irredundant clause");
13382       LOGCLS (3, c, "subsumed mapped irredundant clause");
13383       lglelrmcls (lgl, pivot, c, clidx);
13384     } else clidx++;
13385     while (*c) c++;
13386   }
13387   LOG (BWL + !subsumed,
13388     "subsumed %d clauses containing %d or %d",
13389     subsumed, lgl->elm->pivot, -lgl->elm->pivot);
13390 }
13391
13392 static int lglelmstr (LGL * lgl) {
13393   int clidx, count, strengthened, pivot, * c, * p, mlit, ilit, res, found;
13394   int size;
13395   count = clidx = strengthened = 0;
13396   pivot = lgl->elm->pivot;
13397   res = 0;
13398   LOG (3, "strengthening with pivot %d", pivot);
13399   for (c = lgl->elm->lits.start + 1;
13400        c < lgl->elm->lits.top &&
13401          lgl->limits->elm.steps > lgl->stats->elm.steps;
13402        c++) {
13403     INCSTEPS (elm.steps);
13404     if (count++ == lgl->elm->negcls) {
13405       clidx = 0, pivot = -pivot;
13406       LOG (3, "strengthening with pivot %d", pivot);
13407     }
13408     if (*c == REMOVED) {
13409       while (*c) { assert (*c == REMOVED); c++; }
13410       continue;
13411     }
13412     if (lglbacksub (lgl, c, 1)) {
13413       strengthened++;
13414       lgl->stats->elm.str++;
13415       LOGMCLS (2, c, "strengthening original irredundant clause");
13416       LOGCLS (3, c, "strengthening mapped irredundant clause");
13417       assert (lglmtstk (&lgl->clause));
13418       found = 0;
13419       size = 0;
13420       for (p = c; (mlit = *p); p++) {
13421         ilit = lglm2i (lgl, *p);
13422         if (ilit == pivot) { found++; continue; }
13423         assert (!lglval (lgl, ilit));
13424         lglpushstk (lgl, &lgl->clause, ilit);
13425         size++;
13426       }
13427       assert (found);
13428       lglpushstk (lgl, &lgl->clause, 0);
13429       LOGCLS (2, lgl->clause.start, "static strengthened irredundant clause");
13430       if (lgl->opts->drup.val) lgldrupcls (lgl);
13431 #ifndef NLGLPICOSAT
13432       lglpicosatchkcls (lgl);
13433 #endif
13434       lglelrmcls (lgl, pivot, c, clidx);
13435       lgldrupligaddcls (lgl, REDCS);
13436       lgladdcls (lgl, 0, 0, 1);
13437       lglclnstk (&lgl->clause);
13438       if (size == 1) { res = 1; break; }
13439     } else clidx++;
13440     while (*c) c++;
13441   }
13442   LOG (2, "strengthened %d clauses containing %d or %d",
13443        strengthened, lgl->elm->pivot, -lgl->elm->pivot);
13444   return res;
13445 }
13446
13447 static int lglflushclauses (LGL * lgl, int lit) {
13448   int blit, tag, red, other, other2, count, glue, res;
13449   const int * p, * w, * eow;
13450   int lidx, glidx, slidx;
13451   int * c, * q;
13452   HTS * hts;
13453   Stk * s;
13454 #ifndef NDEBUG
13455   int occs;
13456 #endif
13457   lglchkirrstats (lgl);
13458   assert (lgl->probing || lgl->lkhd || lgl->dense);
13459   hts = lglhts (lgl, lit);
13460   if (!hts->count) return 0;
13461 #ifndef NDEBUG
13462   occs = lgl->occs ? lglocc (lgl, lit) : 0;
13463 #endif
13464   res = 0;
13465   LOG (2, "flushing clauses with literal %d", lit);
13466   w = lglhts2wchs (lgl, hts);
13467   eow = w + hts->count;
13468   count = 0;
13469   for (p = w; p < eow; p++) {
13470     if (lgl->blocking) INCSTEPS (blk.steps);
13471     if (lgl->eliminating) INCSTEPS (elm.steps);
13472     if (lgl->simpleprobing) INCSTEPS (prb.simple.steps);
13473     blit = *p;
13474     tag = blit & MASKCS;
13475     red = blit & REDCS;
13476     other = blit >> RMSHFT;
13477     if (tag == TRNCS || tag == LRGCS) p++;
13478     if (tag == BINCS) {
13479       lglrmbwch (lgl, other, lit, red);
13480       LOG (2, "flushed %s binary clause %d %d", lglred2str (red), lit, other);
13481       lgldeclscnt (lgl, 2, red, 0);
13482       if (!red) lgldecocc (lgl, lit), lgldecocc (lgl, other), res++;
13483       count++;
13484     } else if (tag == TRNCS) {
13485       other2 = *p;
13486       lglrmtwch (lgl, other2, lit, other, red);
13487       lglrmtwch (lgl, other, lit, other2, red);
13488       LOG (2, "flushed %s ternary clause %d %d %d",
13489            lglred2str (red), lit, other, other2);
13490       lgldeclscnt (lgl, 3, red, 0);
13491       if (!red)  {
13492         lgldecocc (lgl, lit);
13493         lgldecocc (lgl, other);
13494         lgldecocc (lgl, other2);
13495         res++;
13496       }
13497       count++;
13498     } else {
13499       assert (tag == OCCS || tag == LRGCS);
13500       if (tag == LRGCS) {
13501         lidx = *p;
13502         s = lglidx2stk (lgl, red, lidx);
13503         if (red) {
13504           glue = lidx & GLUEMASK;
13505           c = s->start + (lidx >> GLUESHFT);
13506         } else {
13507           glue = 0;
13508           c = s->start + lidx;
13509         }
13510       } else {
13511         lidx = (blit >> RMSHFT);
13512         s = &lgl->irr;
13513         c = s->start + lidx;
13514         glue = 0;
13515       }
13516       if (c >= s->top || (other = c[0]) >= NOTALIT) continue;
13517       LOGCLS (2, c, "flushed %s large clause", lglred2str (red));
13518       if (tag == LRGCS) {
13519         if (other == lit) other = c[1];
13520         assert (abs (other) != abs (lit));
13521         lglrmlwch (lgl, other, red, lidx);
13522       } else {
13523         glidx = lidx;
13524         if (red) glidx <<= GLUESHFT;
13525         if (c[1] != lit) lglrmlwch (lgl, c[1], red, glidx);
13526         if (other != lit) lglrmlwch (lgl, other, red, glidx);
13527       }
13528       if (red) {
13529         assert (!glue);
13530         LGLCHKACT (c[-1]);
13531         c[-1] = REMOVED;
13532       } else lgldecocc (lgl, lit);
13533       for (q = c; (other = *q); q++) { assert (other < NOTALIT);
13534         *q = REMOVED;
13535         if (other == lit) continue;
13536         if (red && glue) continue;
13537         slidx = lidx;
13538         if (red && tag == LRGCS) slidx >>= GLUESHFT;
13539         lglrmlocc (lgl, other, red, slidx);
13540         if (!red) lgldecocc (lgl, other);
13541       }
13542       *q = REMOVED;
13543       lgldeclscnt (lgl, q - c, red, glue);
13544       lgltrimlitstk (lgl, red, lidx);
13545       if (!red) res++;
13546       count++;
13547     }
13548   }
13549 #ifndef NDEBUG
13550   if (lgl->occs) assert (occs == res);
13551 #endif
13552   lglshrinkhts (lgl, hts, 0);
13553   LOG (2, "flushed %d clauses with %d including %d irredundant",
13554        count, lit, res);
13555   lglchkirrstats (lgl);
13556   return res;
13557 }
13558
13559 static int lglflushlits (LGL * lgl, int lit) {
13560   int blit, tag, red, other, other2, size, satisfied, d[3], glue;
13561   int * p, * w, * eow, * c, * l, * k;
13562   int lidx, slidx, glidx;
13563   int count, res;
13564   Val val, val2;
13565   long delta;
13566   Stk * s;
13567
13568 // Some compilers do not like local functions, thus we use macros instead.
13569 //
13570 #define FIXPTRS() do { p += delta, w += delta, eow += delta; } while (0)
13571
13572   HTS * hts;
13573   LOG (2, "flushing literal %d from clauses", lit);
13574   assert (!lgl->level);
13575   assert (lglifixed (lgl, lit) < 0);
13576   assert (lgl->dense);
13577   lglchkirrstats (lgl);
13578   hts = lglhts (lgl, lit);
13579   w = lglhts2wchs (lgl, hts);
13580   eow = w + hts->count;
13581   res = count = 0;
13582   for (p = w; p < eow; p++) {
13583     if (lgl->blocking) INCSTEPS (blk.steps);
13584     if (lgl->eliminating) INCSTEPS (elm.steps);
13585     if (lgl->simpleprobing) INCSTEPS (prb.simple.steps);
13586     count++;
13587     blit = *p;
13588     tag = blit & MASKCS;
13589     red = blit & REDCS;
13590     if (tag == BINCS) {
13591       other = blit >> RMSHFT;
13592       assert ((red && lgliselim (lgl, other)) || lglval (lgl, other) > 0);
13593       lglrmbwch (lgl, other, lit, red);
13594       LOG (2, "flushed %s binary clause %d %d", lglred2str (red), lit, other);
13595       lgldeclscnt (lgl, 2, red, 0);
13596       if (!red) {
13597         if (lgl->dense) lgldecocc (lgl, lit), lgldecocc (lgl, other);
13598         res++;
13599       }
13600     } else if (tag == TRNCS) {
13601       other = blit >> RMSHFT;
13602       other2 = *++p;
13603       lglrmtwch (lgl, other2, lit, other, red);
13604       lglrmtwch (lgl, other, lit, other2, red);
13605       LOG (2, "flushed %s ternary clause %d %d %d",
13606            lglred2str (red), lit, other, other2);
13607       lgldeclscnt (lgl, 3, red, 0);
13608       if (!red)  {
13609         if (lgl->dense) {
13610           lgldecocc (lgl, lit);
13611           lgldecocc (lgl, other);
13612           lgldecocc (lgl, other2);
13613         }
13614         res++;
13615       }
13616       val = lglval (lgl, other);
13617       val2 = lglval (lgl, other2);
13618       if (!val && !val2) {
13619         LOG (2,
13620   "reducing flushed %s ternary clause %d %d %d to binary %s clause %d %d",
13621              lglred2str (red),
13622              lit, other, other2,
13623              lglred2str (red),
13624              other, other2);
13625         delta = lglwchbin (lgl, other, other2, red);
13626         delta += lglwchbin (lgl, other2, other, red);
13627         if (lgl->simpleprobing && lgl->opts->prbsimple.val >= 2)
13628           lglwrktouch (lgl, -other), lglwrktouch (lgl, -other2);
13629         if (delta) FIXPTRS ();
13630         if (red) {
13631           lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
13632         } else {
13633           lglincirr (lgl, 2);
13634           if (lgl->dense) lglincocc (lgl, other), lglincocc (lgl, other2);
13635         }
13636       } else {
13637 #ifndef NDEBUG
13638         if (!red || (!lgliselim (lgl, other) && !lgliselim (lgl, other2)))
13639           assert (val > 0 || val2 > 0);
13640 #endif
13641       }
13642     } else {
13643       assert (tag == OCCS || tag == LRGCS);
13644       lidx = (tag == LRGCS) ? *++p : (blit >> RMSHFT);
13645       s = lglidx2stk (lgl, red, lidx);
13646       c = s->start + (red ? (lidx >> GLUESHFT) : lidx);
13647       if (c >= s->top || c[0] >= NOTALIT) continue;
13648       size = satisfied = 0;
13649       for (l = c; (other = *l); l++) {
13650         if (other == lit) continue;
13651         if ((val = lglval (lgl, other)) < 0) continue;
13652         if (val > 0) { satisfied = 1; break; }
13653         if (size < 3) d[size] = other;
13654         size++;
13655       }
13656       if (!satisfied && size == 2) {
13657         LOGCLS (2, c,
13658           "reducing to binary %s clause %d %d flushed large %s clause",
13659              lglred2str (red), d[0], d[1], lglred2str (red));
13660         delta = lglwchbin (lgl, d[0], d[1], red);
13661         delta += lglwchbin (lgl, d[1], d[0], red);
13662         if (delta) FIXPTRS ();
13663         if (red) {
13664           lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
13665         } else {
13666           lglincirr (lgl, 2);
13667           if (lgl->dense) lglincocc (lgl, d[0]), lglincocc (lgl, d[1]);
13668         }
13669         if (lgl->simpleprobing && lgl->opts->prbsimple.val >= 2)
13670           lglwrktouch (lgl, -d[0]), lglwrktouch (lgl, -d[1]);
13671       }
13672       if (!satisfied && size == 3) {
13673         LOGCLS (2, c,
13674           "reducing to ternary %s clause %d %d %d flushed large %s clause",
13675              lglred2str (red), d[0], d[1], d[2], lglred2str (red));
13676         delta = lglwchtrn (lgl, d[0], d[1], d[2], red);
13677         delta += lglwchtrn (lgl, d[1], d[0], d[2], red);
13678         delta += lglwchtrn (lgl, d[2], d[0], d[1], red);
13679         if (delta) FIXPTRS ();
13680         if (red) {
13681           lgl->stats->red.trn++, assert (lgl->stats->red.trn > 0);
13682         } else {
13683           lglincirr (lgl, 3);
13684           if (lgl->dense) {
13685             lglincocc (lgl, d[0]);
13686             lglincocc (lgl, d[1]);
13687             lglincocc (lgl, d[2]);
13688           }
13689         }
13690         if (lgl->simpleprobing && lgl->opts->prbsimple.val >= 3)
13691           lglwrktouch (lgl, d[0]),
13692           lglwrktouch (lgl, d[1]),
13693           lglwrktouch (lgl, d[2]); 
13694       }
13695       if (lgl->dense && !red) {
13696         for (l = c; (other = *l); l++) {
13697           if (satisfied || size <= 3 || lglval (lgl, other) < 0) {
13698             if (!red) lgldecocc (lgl, other);
13699             if (other != lit) {
13700               slidx = lidx;
13701               if (red && tag == LRGCS) slidx >>= GLUESHFT;
13702               lglrmlocc (lgl, other, red, slidx);
13703             }
13704           }
13705         }
13706       }
13707       glidx = lidx;
13708       if (red && tag == OCCS) glidx <<= GLUESHFT;
13709       if (c[0] != lit) lglrmlwch (lgl, c[0], red, glidx);
13710       if (c[1] != lit) lglrmlwch (lgl, c[1], red, glidx);
13711       if (satisfied || size <= 3) {
13712         if (red) { LGLCHKACT (c[-1]); c[-1] = REMOVED; }
13713         for (k = c; (other = *k); k++) *k = REMOVED;
13714         *k = REMOVED;
13715         if (red) {
13716           glue = (tag == LRGCS) ? (lidx & GLUEMASK) : 0;
13717           assert (lgl->stats->lir[glue].clauses > 0);
13718           lgl->stats->lir[glue].clauses--;
13719           assert (lgl->stats->red.lrg > 0);
13720           lgl->stats->red.lrg--;
13721         } else lgldecirr (lgl, k - c);
13722       } else {
13723         for (l = k = c; (other = *l); l++) {
13724           if ((val = lglval (lgl, other)) < 0) continue;
13725           if (lgl->simpleprobing && lgl->opts->prbsimple.val >= 3)
13726             lglwrktouch (lgl, other);
13727           assert (abs (other) != abs (lit));
13728           assert (!val);
13729           *k++ = other;
13730         }
13731         assert (size == k - c);
13732         if (!red && k < l) {
13733           assert (lgl->stats->irr.lits.cur >= l - k);
13734           lgl->stats->irr.lits.cur -= l - k;
13735         }
13736         *k++ = 0;
13737         while (k <= l) *k++ = REMOVED;
13738         delta = lglwchlrg (lgl, c[0], c[1], red, glidx);
13739         delta += lglwchlrg (lgl, c[1], c[0], red, glidx);
13740         if (delta) FIXPTRS ();
13741       }
13742       lgltrimlitstk (lgl, red, lidx);
13743     }
13744   }
13745   hts = lglhts (lgl, lit);
13746   lglshrinkhts (lgl, hts, 0);
13747   LOG (2, "flushed %d occurrences of literal %d including %d irredundant",
13748        count, lit, res);
13749   lglchkirrstats (lgl);
13750   return res;
13751
13752 #undef FIXPTRS
13753
13754 }
13755
13756 static int lglflush (LGL * lgl) {
13757   int lit, count;
13758   if (lgl->mt) return 0;
13759   lglchkirrstats (lgl);
13760   assert (!lgl->level);
13761   assert (lgl->probing || lgl->lkhd || lgl->dense);
13762   if (lgl->flushed == lglcntstk (&lgl->trail)) return 1;
13763   if (!lglbcp (lgl)) { lgl->mt = 1; return 0; }
13764   if (!lglsyncunits (lgl)) { assert (lgl->mt); return 0; }
13765   count = 0;
13766   while  (lgl->flushed < lglcntstk (&lgl->trail)) {
13767     lit = lglpeek (&lgl->trail, lgl->flushed++);
13768     lglflushclauses (lgl, lit);
13769     lglflushlits (lgl, -lit);
13770     count++;
13771   }
13772   LOG (2, "flushed %d literals", count);
13773   assert (!lgl->mt);
13774   return 1;
13775 }
13776
13777 static void lglblockinglit (LGL * lgl, int ilit) {
13778   int elit = lglexport (lgl, ilit), sgnbit = (1 << (elit < 0));
13779   Ext * ext = lglelit2ext (lgl, elit);
13780   assert (!ext->equiv);
13781   assert (!ext->eliminated);
13782   assert (abs (ext->repr) == abs (ilit));
13783   if (ext->blocking & sgnbit) return;
13784   ext->blocking |= sgnbit;
13785   LOG (3, "marking external %d internal %d as blocking", elit, ilit);
13786   lgl->stats->blk.lits++;
13787 }
13788
13789 static void lglelmfrelit (LGL * lgl, int mpivot,
13790                           int * sop, int * eop, int * son, int * eon) {
13791   int ipivot = mpivot * lgl->elm->pivot, clidx, ilit, tmp, cover, maxcover;
13792   int * c, * d, * p, * q, lit, nontrivial, idx, sgn, clen, reslen;
13793   assert (mpivot == 1 || mpivot == -1);
13794   assert (ipivot);
13795   LOG (3,
13796        "blocked clause elimination and forced resolution of clauses with %d",
13797         ipivot);
13798   clidx = 0;
13799   cover = lglpeek (&lgl->elm->noccs, lglulit (-mpivot));
13800   for (c = sop; c < eop; c = p + 1) {
13801     if (lgl->eliminating) INCSTEPS (elm.steps);
13802     if (*c == REMOVED) { for (p = c + 1; *p; p++) ; continue; }
13803     maxcover = 0;
13804     for (p = c; (lit = *p); p++) {
13805       if (lit == mpivot) continue;
13806       assert (lit != -mpivot);
13807       maxcover += lglpeek (&lgl->elm->noccs, lglulit (-lit));
13808     }
13809     if (maxcover < cover - 1) { clidx++; continue; }
13810     for (p = c; (lit = *p); p++) {
13811       if (lit == mpivot) continue;
13812       assert (lit != -mpivot);
13813       idx = abs (lit);
13814       assert (!lglpeek (&lgl->elm->mark, idx));
13815       sgn = lglsgn (lit);
13816       lglpoke (&lgl->elm->mark, idx, sgn);
13817     }
13818     nontrivial = 0;
13819     clen = p - c;
13820     for (d = son; !nontrivial && d < eon; d = q + 1) {
13821       INCSTEPS (elm.steps);
13822       if (*d == REMOVED) { for (q = d + 1; *q; q++) ; continue; }
13823       INCSTEPS (elm.resolutions);
13824       LOGMCLS (3, c, "trying forced resolution 1st antecedent");
13825       LOGMCLS (3, d, "trying forced resolution 2nd antecedent");
13826       assert (clen > 0);
13827       reslen = clen - 1;
13828       for (q = d; (lit = *q); q++) {
13829         if (lit == -mpivot) continue;
13830         assert (lit != mpivot);
13831         idx = abs (lit), sgn = lglsgn (lit);
13832         tmp = lglpeek (&lgl->elm->mark, idx);
13833         if (tmp == -sgn) break;
13834         if (tmp != sgn) reslen++;
13835       }
13836       if (lit) {
13837         while (*++q) ;
13838         LOG (3, "trying forced resolution ends with trivial resolvent");
13839       } else {
13840         LOG (3, "non trivial resolvent in blocked clause elimination");
13841         nontrivial = INT_MAX;
13842       }
13843     }
13844     for (p = c; (lit = *p); p++) {
13845       if (lit == mpivot) continue;
13846       assert (lit != -mpivot);
13847       idx = abs (lit);
13848       assert (lglpeek (&lgl->elm->mark, idx) == lglsgn (lit));
13849       lglpoke (&lgl->elm->mark, idx, 0);
13850     }
13851     assert (lgl->opts->elim.val);
13852     if (!nontrivial &&
13853         lgl->opts->block.val &&
13854         lgl->opts->elmblk.val &&
13855         (!lgl->opts->elmblkwait.val || !lgl->opts->elim.val || lgl->elmrtc)) {
13856       assert (maxcover >= cover);
13857       lgl->stats->elm.blkd++;
13858       LOGMCLS (2, c, "blocked on %d clause", ipivot);
13859       lglepush (lgl, ipivot);
13860       for (p = c; (lit = *p); p++) {
13861         if (lit == mpivot) continue;
13862         assert (lit != -mpivot);
13863         ilit = lglm2i (lgl, lit);
13864         lglepush (lgl, ilit);
13865       }
13866       lglepush (lgl, 0);
13867       lglelrmcls (lgl, ipivot, c, clidx);
13868       lglblockinglit (lgl, ipivot);
13869       continue;
13870     }
13871     clidx++;
13872     if (lgl->limits->elm.steps <= lgl->stats->elm.steps) {
13873       LOG (2, "maximum number of steps in elimination exhausted");
13874       return;
13875     }
13876   }
13877 }
13878
13879 static void lglelmfre (LGL * lgl) {
13880   int * sop, * eop, * son, * eon;
13881   assert (lgl->elm->pivot);
13882   sop = lgl->elm->lits.start + 1;
13883   eop = son = lgl->elm->lits.start + lgl->elm->neglidx;
13884   eon = lgl->elm->lits.top;
13885   lglelmfrelit (lgl, 1, sop, eop, son, eon);
13886   lglelmfrelit (lgl, -1, son, eon, sop, eop);
13887 }
13888
13889 static void lgleliminated (LGL * lgl, int pivot) {
13890   AVar * av;
13891   int elit;
13892   Ext * e;
13893   assert (!lglifrozen (lgl, pivot));
13894   av = lglavar (lgl, pivot);
13895   assert (av->type == FREEVAR);
13896   av->type = ELIMVAR;
13897   lgl->stats->elm.elmd++;
13898   assert (lgl->stats->elm.elmd > 0);
13899   lglflushclauses (lgl, pivot);
13900   lglflushclauses (lgl, -pivot);
13901   LOG (2, "eliminated %d", pivot);
13902   elit = lglexport (lgl, pivot);
13903   e = lglelit2ext (lgl, elit);
13904   assert (!e->eliminated);
13905   assert (!e->equiv);
13906   e->eliminated = 1;
13907 }
13908
13909 static void lglepusheliminated (LGL * lgl, int idx) {
13910   const int * p, * w, * eow, * c, * l;
13911   int lit, blit, tag, red, other;
13912   HTS * hts;
13913   lit = (lglocc (lgl, idx) < lglocc (lgl, -idx)) ? idx : -idx;
13914   LOG (3, "keeping clauses with %d for extending assignment", lit);
13915   hts = lglhts (lgl, lit);
13916   w = lglhts2wchs (lgl, hts);
13917   eow = w + hts->count;
13918   for (p = w; p < eow; p++) {
13919     blit = *p;
13920     tag = blit & MASKCS;
13921     if (tag == TRNCS || tag == LRGCS) p++;
13922     if (tag == LRGCS) continue;
13923     red = blit & REDCS;
13924     if (red) continue;
13925     lglepush (lgl, lit);
13926     if (tag == BINCS || tag == TRNCS) {
13927       lglepush (lgl, blit >> RMSHFT);
13928       if (tag == TRNCS)
13929         lglepush (lgl, *p);
13930     } else {
13931       assert (tag == OCCS);
13932       c = lglidx2lits (lgl, 0, blit >> RMSHFT);
13933       for (l = c; (other = *l); l++)
13934         if (other != lit)
13935           lglepush (lgl, other);
13936     }
13937     lglepush (lgl, 0);
13938   }
13939   lglepush (lgl, -lit);
13940   lglepush (lgl, 0);
13941   lgleliminated (lgl, idx);
13942 }
13943
13944 static int lglunhimpl (const DFPR * dfpr, int a, int b) {
13945   int u = lglulit (a), v = lglulit (b), c, d, f, g;
13946   c = dfpr[u].discovered; if (!c) return 0;
13947   d = dfpr[v].discovered; if (!d) return 0;
13948   f = dfpr[u].finished, g = dfpr[v].finished;
13949   assert (0 < c && c < f);
13950   assert (0 < d && d < g);
13951   return c < d && g < f;
13952 }
13953
13954 static int lglunhimplies2 (const DFPR * dfpr, int a, int b) {
13955   return lglunhimpl (dfpr, a, b) || lglunhimpl (dfpr, -b, -a);
13956 }
13957
13958 static int lglunhimplincl (const DFPR * dfpr, int a, int b) {
13959   int u = lglulit (a), v = lglulit (b), c, d, f, g;
13960   c = dfpr[u].discovered; if (!c) return 0;
13961   d = dfpr[v].discovered; if (!d) return 0;
13962   f = dfpr[u].finished, g = dfpr[v].finished;
13963   assert (0 < c && c < f);
13964   assert (0 < d && d < g);
13965   return c <= d && g <= f;
13966 }
13967
13968 static int lglunhimplies2incl (const DFPR * dfpr, int a, int b) {
13969   return lglunhimplincl (dfpr, a, b) || lglunhimplincl (dfpr, -b, -a);
13970 }
13971
13972 static int lglhastrn (LGL * lgl, int a, int b, int c) {
13973   int blit, tag, other, other2;
13974   const int * w, * eow, * p;
13975   HTS * ha, * hb, * hc;
13976   ha = lglhts (lgl, a);
13977   hb = lglhts (lgl, b);
13978   if (hb->count < ha->count) { SWAP (int, a, b); SWAP (HTS *, ha, hb); }
13979   hc = lglhts (lgl, c);
13980   if (hc->count < ha->count) { SWAP (int, a, c); SWAP (HTS *, ha, hc); }
13981   w = lglhts2wchs (lgl, ha);
13982   eow = w + ha->count;
13983   for (p = w; p < eow; p++) {
13984     blit = *p;
13985     tag = blit & MASKCS;
13986     if (tag == OCCS) continue;
13987     if (tag == BINCS) {
13988       other = blit >> RMSHFT;
13989       if (other == b || other == c) return 1;
13990       continue;
13991     }
13992     if (tag == TRNCS || tag == LRGCS) p++;
13993     if (tag == LRGCS) continue;
13994     assert (tag == TRNCS);
13995     other = blit >> RMSHFT;
13996     if (other != b && other != c) continue;
13997     other2 = *p;
13998     if (other2 == b || other2 == c) return 1;
13999   }
14000   if (hc->count < hb->count) { SWAP (int, b, c); SWAP (HTS *, hb, hc); }
14001   w = lglhts2wchs (lgl, hb);
14002   eow = w + hb->count;
14003   for (p = w; p < eow; p++) {
14004     blit = *p;
14005     tag = blit & MASKCS;
14006     if (tag == OCCS) continue;
14007     if (tag == TRNCS || tag == LRGCS) { p++; continue; }
14008     assert (tag == BINCS);
14009     other = blit >> RMSHFT;
14010     if (other == c) return 1;
14011   }
14012   return 0;
14013 }
14014
14015 static int64_t lglfactor (LGL * lgl, int lim, int count) {
14016   int64_t factor, res;
14017   if (!count) return lim;
14018   switch (lgl->opts->factor.val) {
14019     default: factor = 1; break;
14020     case 1: factor = lglceilld (count); break;
14021     case 2: factor = count; break;
14022     case 3: factor = count*(int64_t)count; break;
14023   }
14024   if (!factor) factor = 1;
14025   if (factor > lgl->opts->factmax.val) factor = lgl->opts->factmax.val;
14026   res = lim * factor;
14027   return res;
14028 }
14029
14030 static int lglforcedve (LGL * lgl, int idx) {
14031   int pocc = lglocc (lgl, idx);
14032   int nocc = lglocc (lgl, -idx);
14033   int count = lgl->stats->elm.count;
14034   if (!pocc) return 1;
14035   if (!nocc) return 1;
14036   if (lgl->opts->elmfull.val) return 0;
14037   if (pocc >= lglfactor (lgl, lgl->opts->elmocclim1.val, count)) return -1;
14038   if (nocc >= lglfactor (lgl, lgl->opts->elmocclim1.val, count)) return -1;
14039   if (pocc < lglfactor (lgl, lgl->opts->elmocclim2.val, count)) return 0;
14040   if (nocc < lglfactor (lgl, lgl->opts->elmocclim2.val, count)) return 0;
14041   return -1;
14042 }
14043
14044 static int lgltrylargeve (LGL * lgl) {
14045   const int * c, * d, * sop, * eop, * son, * eon, * p, * q, * start, * end;
14046   int lit, idx, sgn, tmp, ip, ilit, npocc, nnocc, limit, count, i, res;
14047   int clen, dlen, reslen, maxreslen;
14048   ip = lgl->elm->pivot;
14049   assert (ip);
14050   if ((res = lglforcedve (lgl, ip))) return res > 0;
14051   sop = lgl->elm->lits.start + 1;
14052   eop = son = lgl->elm->lits.start + lgl->elm->neglidx;
14053   eon = lgl->elm->lits.top;
14054   npocc = lglpeek (&lgl->elm->noccs, lglulit (1));
14055   nnocc = lglpeek (&lgl->elm->noccs, lglulit (-1));
14056   limit = npocc + nnocc;
14057   count = 0;
14058   for (i = 0; i <= 1; i++) {
14059     start = i ? son : sop;
14060     end = i ? eon : eop;
14061     for (c = start; c < end; c++) {
14062       INCSTEPS (elm.steps);
14063       if (*c == REMOVED) { while (*c) c++; continue; }
14064       while ((lit = *c)) {
14065         (void) lglm2i (lgl, lit);
14066         c++;
14067       }
14068       count++;
14069     }
14070   }
14071   assert (count == limit);
14072   LOG (3, "trying clause distribution for %d with limit %d", ip, limit);
14073   maxreslen = 0;
14074   for (c = sop; c < eop && limit >= 0; c = p + 1) {
14075     INCSTEPS (elm.steps);
14076     if (*c == REMOVED) { for (p = c + 1; *p; p++) ; continue; }
14077     assert (lglmtstk (&lgl->resolvent));
14078     clen = 0;
14079     for (p = c; (lit = *p); p++) {
14080       if (lit == 1) continue;
14081       assert (lit != -1);
14082       idx = abs (lit);
14083       assert (!lglpeek (&lgl->elm->mark, idx));
14084       sgn = lglsgn (lit);
14085       lglpoke (&lgl->elm->mark, idx, sgn);
14086       ilit = lglm2i (lgl, lit);
14087       lglpushstk (lgl, &lgl->resolvent, ilit);
14088       clen++;
14089     }
14090     for (d = son; limit >= 0 && d < eon; d = q + 1) {
14091       INCSTEPS (elm.steps);
14092       if (*d == REMOVED) { for (q = d + 1; *q; q++) ; continue; }
14093       INCSTEPS (elm.resolutions);
14094       LOGMCLS (3, c, "trying resolution 1st antecedent");
14095       LOGMCLS (3, d, "trying resolution 2nd antecedent");
14096       dlen = 0;
14097       reslen = clen;
14098       for (q = d; (lit = *q); q++) {
14099         if (lit == -1) continue;
14100         dlen++;
14101         assert (lit != 1);
14102         idx = abs (lit), sgn = lglsgn (lit);
14103         tmp = lglpeek (&lgl->elm->mark, idx);
14104         if (tmp == -sgn) break;
14105         if (tmp == sgn) continue;
14106         ilit = lglm2i (lgl, lit);
14107         lglpushstk (lgl, &lgl->resolvent, ilit);
14108         reslen++;
14109       }
14110       assert (reslen == lglcntstk (&lgl->resolvent));
14111       if (!lit && reslen == 1) {
14112         LOG (3, "trying resolution ends with unit clause");
14113         lit = lglpeek (&lgl->resolvent, 0);
14114         limit += lglevar (lgl, lit)->occ[lit < 0];
14115       } else if (lit) {
14116         while (*++q) ;
14117         LOG (3, "trying resolution ends with trivial resolvent");
14118       } else {
14119         limit--;
14120         LOG (3,
14121              "trying resolution with non trivial resolvent remaining %d",
14122              limit);
14123         if (reslen > maxreslen) maxreslen = reslen;
14124       }
14125       assert (!*q);
14126       lglrststk (&lgl->resolvent, clen);
14127     }
14128     lglclnstk (&lgl->resolvent);
14129     for (p = c; (lit = *p); p++) {
14130       if (lit == 1) continue;
14131       assert (lit != -1);
14132       idx = abs (lit);
14133       assert (lglpeek (&lgl->elm->mark, idx) == lglsgn (lit));
14134       lglpoke (&lgl->elm->mark, idx, 0);
14135     }
14136     if (lgl->limits->elm.steps <= lgl->stats->elm.steps) {
14137       LOG (2, "maximum number of steps in elimination exhausted");
14138       return 0;
14139     }
14140   }
14141   assert (lglm2i (lgl, 1) == ip);
14142   if (limit < 0) {
14143     LOG (3, "resolving away %d would increase number of clauses", ip);
14144     return 0;
14145   }
14146   if (limit) LOG (2, "resolving away %d removes %d clauses", ip, limit);
14147   else LOG (2, "resolving away %d does not change number of clauses", ip);
14148   return 1;
14149 }
14150
14151 static void lgldolargeve (LGL * lgl) {
14152   const int * c, * d, * sop, * eop, * son, * eon, * p, * q, * start, * end;
14153   int lit, idx, sgn, tmp, ip, ilit, mp, npocc, nnocc;
14154   int clen, dlen, reslen;
14155   Val val;
14156   ip = lgl->elm->pivot;
14157   assert (ip);
14158   sop = lgl->elm->lits.start + 1;
14159   eop = son = lgl->elm->lits.start + lgl->elm->neglidx;
14160   eon = lgl->elm->lits.top;
14161   npocc = lglpeek (&lgl->elm->noccs, lglulit (1));
14162   nnocc = lglpeek (&lgl->elm->noccs, lglulit (-1));
14163   LOG (2, "(large) variable elimination of %d", lgl->elm->pivot);
14164   lglflushclauses (lgl, ip);
14165   lglflushclauses (lgl, -ip);
14166   if (npocc < nnocc) start = sop, end = eop, mp = 1;
14167   else start = son, end = eon, ip = -ip, mp = -1;
14168   LOG (3, "will save clauses with %d for extending assignment", ip);
14169   for (c = start; c < end; c = p + 1) {
14170     INCSTEPS (elm.steps);
14171     if (*c == REMOVED) { for (p = c + 1; *p; p++) ; continue; }
14172     lglepush (lgl, ip);
14173     for (p = c; (lit = *p); p++)  {
14174       if (lit == mp) continue;
14175       assert (lit != -mp);
14176       ilit = lglm2i (lgl, lit);
14177       lglepush (lgl, ilit);
14178     }
14179     lglepush (lgl, 0);
14180   }
14181   lglepush (lgl, -ip);
14182   lglepush (lgl, 0);
14183   for (c = sop; c < eop; c = p + 1) {
14184     INCSTEPS (elm.steps);
14185     if (*c == REMOVED) { for (p = c + 1; *p; p++) ; continue; }
14186     assert (lglmtstk (&lgl->resolvent));
14187     clen = 0;
14188     for (p = c; (lit = *p); p++) {
14189       if (lit == 1) continue;
14190       assert (lit != -1);
14191       idx = abs (lit);
14192       assert (!lglpeek (&lgl->elm->mark, idx));
14193       sgn = lglsgn (lit);
14194       lglpoke (&lgl->elm->mark, idx, sgn);
14195       ilit = lglm2i (lgl, lit);
14196       lglpushstk (lgl, &lgl->resolvent, ilit);
14197       clen++;
14198     }
14199     for (d = son; d < eon; d = q + 1) {
14200       INCSTEPS (elm.steps);
14201       if (*d == REMOVED) { for (q = d + 1; *q; q++) ; continue; }
14202       INCSTEPS (elm.resolutions);
14203       assert (lglmtstk (&lgl->clause));
14204       dlen = 0;
14205       reslen = clen;
14206       for (q = d; (lit = *q); q++) {
14207         if (lit == -1) continue;
14208         dlen++;
14209         assert (lit != 1);
14210         idx = abs (lit), sgn = lglsgn (lit);
14211         tmp = lglpeek (&lgl->elm->mark, idx);
14212         if (tmp == sgn) continue;
14213         if (tmp == -sgn) break;
14214         ilit = lglm2i (lgl, lit);
14215         val = lglval (lgl, ilit);
14216         if (val < 0) continue;
14217         if (val > 0) break;
14218         lglpushstk (lgl, &lgl->clause, ilit);
14219         ilit = lglm2i (lgl, lit);
14220         lglpushstk (lgl, &lgl->resolvent, ilit);
14221         reslen++;
14222       }
14223       assert (reslen == lglcntstk (&lgl->resolvent));
14224       if (!lit && reslen == 1) {
14225         goto RESOLVE;
14226       } if (lit) {
14227         while (*++q) ;
14228       } else {
14229 RESOLVE:
14230         LOGMCLS (3, c, "resolving variable elimination 1st antecedent");
14231         LOGMCLS (3, d, "resolving variable elimination 2nd antecedent");
14232         for (p = c; (lit = *p); p++) {
14233           if (lit == 1) continue;
14234           assert (lit != -1);
14235           ilit = lglm2i (lgl, lit);
14236           val = lglval (lgl, ilit);
14237           if (val < 0) continue;
14238           if (val > 0) break;
14239           lglpushstk (lgl, &lgl->clause, ilit);
14240         }
14241         if (!lit) {
14242           lglpushstk (lgl, &lgl->clause, 0);
14243           LOGCLS (3, lgl->clause.start, "variable elimination resolvent");
14244           lgldrupligaddcls (lgl, REDCS);
14245           lgladdcls (lgl, 0, 0, 1);
14246           if (lgl->opts->drup.val) lgldrupcls (lgl);
14247         }
14248       }
14249       lglclnstk (&lgl->clause);
14250       assert (!*q);
14251       lglrststk (&lgl->resolvent, clen);
14252     }
14253     lglclnstk (&lgl->resolvent);
14254     for (p = c; (lit = *p); p++) {
14255       if (lit == 1) continue;
14256       assert (lit != -1);
14257       idx = abs (lit);
14258       assert (lglpeek (&lgl->elm->mark, idx) == lglsgn (lit));
14259       lglpoke (&lgl->elm->mark, idx, 0);
14260     }
14261   }
14262   lgleliminated (lgl, lgl->elm->pivot);
14263   lgl->stats->elm.large++;
14264 }
14265
14266 static void lglelimlitaux (LGL * lgl, int idx) {
14267   lglelmsub (lgl);
14268   if (lglelmstr (lgl)) return;
14269   lglelmfre (lgl);
14270   if (lgltrylargeve (lgl)) lgldolargeve (lgl);
14271 }
14272
14273 static int lgls2m (LGL * lgl, int ilit) {
14274   AVar * av = lglavar (lgl, ilit);
14275   int res = av->mark;
14276   if (!res) {
14277     res = lglcntstk (&lgl->seen) + 1;
14278     if (res > lgl->opts->smallvevars.val + 1) return 0;
14279     av->mark = res;
14280     assert (lglcntstk (&lgl->seen) == lglcntstk (&lgl->elm->m2i) - 1);
14281     lglpushstk (lgl, &lgl->seen, abs (ilit));
14282     lglpushstk (lgl, &lgl->elm->m2i, abs (ilit));
14283     LOG (4, "mapped internal variable %d to marked variable %d",
14284          abs (ilit), res);
14285   }
14286   if (ilit < 0) res = -res;
14287   return res;
14288 }
14289
14290 static void lglvar2funaux (int v, Fun res, int negate) {
14291   uint64_t tmp;
14292   int i, j, p;
14293   assert (0 <= v && v < FUNVAR);
14294   if (v < 6) {
14295     tmp = lglbasevar2funtab[v];
14296     if (negate) tmp = ~tmp;
14297     for (i = 0; i < FUNQUADS; i++)
14298       res[i] = tmp;
14299   } else {
14300     tmp = negate ? ~0ull : 0ull;
14301     p = 1 << (v - 6);
14302     j = 0;
14303     for (i = 0; i < FUNQUADS; i++) {
14304       res[i] = tmp;
14305       if (++j < p) continue;
14306       tmp = ~tmp;
14307       j = 0;
14308     }
14309   }
14310 }
14311
14312 static void lglvar2fun (int v, Fun res) {
14313   lglvar2funaux (v, res, 0);
14314 }
14315
14316 static void lglnegvar2fun (int v, Fun res) {
14317   lglvar2funaux (v, res, 1);
14318 }
14319
14320 static void lglfuncpy (Fun dst, const Fun src) {
14321   int i;
14322   for (i = 0; i < FUNQUADS; i++)
14323     dst[i] = src[i];
14324 }
14325
14326 static void lglfalsefun (Fun res) {
14327   int i;
14328   for (i = 0; i < FUNQUADS; i++)
14329     res[i] = 0ll;
14330 }
14331
14332 static void lgltruefun (Fun res) {
14333   int i;
14334   for (i = 0; i < FUNQUADS; i++)
14335     res[i] = ~0ll;
14336 }
14337
14338 static int lglisfalsefun (const Fun f) {
14339   int i;
14340   for (i = 0; i < FUNQUADS; i++)
14341     if (f[i] != 0ll) return 0;
14342   return 1;
14343 }
14344
14345 static int lglistruefun (const Fun f) {
14346   int i;
14347   for (i = 0; i < FUNQUADS; i++)
14348     if (f[i] != ~0ll) return 0;
14349   return 1;
14350 }
14351
14352 static void lglorfun (Fun a, const Fun b) {
14353   int i;
14354   for (i = 0; i < FUNQUADS; i++)
14355     a[i] |= b[i];
14356 }
14357
14358 static void lglornegfun (Fun a, const Fun b) {
14359   int i;
14360   for (i = 0; i < FUNQUADS; i++)
14361     a[i] |= ~b[i];
14362 }
14363
14364 static void lglor3fun (Fun a, const Fun b, const Fun c) {
14365   int i;
14366   for (i = 0; i < FUNQUADS; i++)
14367     a[i] = b[i] | c[i];
14368 }
14369
14370 static void lglor3negfun (Fun a, const Fun b, const Fun c) {
14371   int i;
14372   for (i = 0; i < FUNQUADS; i++)
14373     a[i] = b[i] | ~c[i];
14374 }
14375
14376 static void lglandornegfun (Fun a, const Fun b, const Fun c) {
14377   int i;
14378   for (i = 0; i < FUNQUADS; i++)
14379     a[i] &= b[i] | ~c[i];
14380 }
14381
14382 static void lglandfun (Fun a, const Fun b) {
14383   int i;
14384   for (i = 0; i < FUNQUADS; i++)
14385     a[i] &= b[i];
14386 }
14387
14388 static void lgland3fun (Fun a, const Fun b, const Fun c) {
14389   int i;
14390   for (i = 0; i < FUNQUADS; i++)
14391     a[i] = b[i] & c[i];
14392 }
14393
14394 static void lgland3negfun (Fun a, const Fun b, const Fun c) {
14395   int i;
14396   for (i = 0; i < FUNQUADS; i++)
14397     a[i] = b[i] & ~c[i];
14398 }
14399
14400 static void lglsrfun (Fun a, int shift) {
14401   uint64_t rest, tmp;
14402   int i, j, q, b, l;
14403   assert (0 <= shift);
14404   b = shift & 63;
14405   q = shift >> 6;
14406   j = 0;
14407   i = q;
14408   assert (i >= 0);
14409   l = 64 - b;
14410   while (j < FUNQUADS) {
14411     if (i < FUNQUADS) {
14412       tmp = a[i] >> b;
14413       rest = (b && i+1 < FUNQUADS) ? (a[i+1] << l) : 0ull;
14414       a[j] = rest | tmp;
14415     } else a[j] = 0ull;
14416     i++, j++;
14417   }
14418 }
14419
14420 static void lglslfun (Fun a, int shift) {
14421   uint64_t rest, tmp;
14422   int i, j, q, b, l;
14423   assert (0 <= shift);
14424   b = shift & 63;
14425   q = shift >> 6;
14426   j = FUNQUADS - 1;
14427   i = j - q;
14428   l = 64 - b;
14429   while (j >= 0) {
14430     if (i >= 0) {
14431       tmp = a[i] << b;
14432       rest = (b && i > 0) ? (a[i-1] >> l) : 0ll;
14433       a[j] = rest | tmp;
14434     } else a[j] = 0ll;
14435     i--, j--;
14436   }
14437 }
14438
14439 static void lgls2fun (int mlit, Fun res) {
14440   int midx = abs (mlit), sidx = midx - 2;
14441   assert (0 <= sidx && sidx < FUNVAR);
14442   if (mlit < 0) lglnegvar2fun (sidx, res);
14443   else lglvar2fun (sidx, res);
14444 }
14445
14446 static int lglinitsmallve (LGL * lgl, int lit, Fun res) {
14447   int blit, tag, red, other, other2, lidx, mlit;
14448   const int * p, * w, * eow, * c, * q;
14449   Fun cls, tmp;
14450   HTS * hts;
14451   Val val;
14452   assert (!lglval (lgl, lit));
14453   LOG (3, "initializing small variable eliminiation for %d", lit);
14454 #ifndef NDEBUG
14455   mlit =
14456 #endif
14457   lgls2m (lgl, lit);
14458   assert (abs (mlit) == 1);
14459   hts = lglhts (lgl, lit);
14460   lgltruefun (res);
14461   if (!hts->count) goto DONE;
14462   w = lglhts2wchs (lgl, hts);
14463   eow = w + hts->count;
14464   for (p = w; p < eow; p++) {
14465     INCSTEPS (elm.steps);
14466     blit = *p;
14467     tag = blit & MASKCS;
14468     if (tag == TRNCS || tag == LRGCS) p++;
14469     if (tag == LRGCS) continue;
14470     red = blit & REDCS;
14471     if (red) continue;
14472     lglfalsefun (cls);
14473     if (tag == BINCS || tag == TRNCS) {
14474       other = blit >> RMSHFT;
14475       val = lglval (lgl, other);
14476       assert (val <= 0);
14477       if (!val) {
14478         mlit = lgls2m (lgl, other);
14479         if (!mlit) return 0;
14480         lgls2fun (mlit, tmp);
14481         lglorfun (cls, tmp);
14482       }
14483       if (tag == TRNCS) {
14484         other2 = *p;
14485         val = lglval (lgl, other2);
14486         assert (val <= 0);
14487         if (!val) {
14488           mlit = lgls2m (lgl, other2);
14489           if (!mlit) return 0;
14490           lgls2fun (mlit, tmp);
14491           lglorfun (cls, tmp);
14492         }
14493       }
14494     } else {
14495       assert (tag == OCCS);
14496       lidx = blit >> RMSHFT;
14497       c = lglidx2lits (lgl, 0, lidx);
14498       for (q = c; (other = *q); q++) {
14499         if (other == lit) continue;
14500         assert (other != -lit);
14501         val = lglval (lgl, other);
14502         assert (val <= 0);
14503         if (!val) {
14504           mlit = lgls2m (lgl, other);
14505           if (!mlit) return 0;
14506           lgls2fun (mlit, tmp);
14507           lglorfun (cls, tmp);
14508         }
14509       }
14510     }
14511     assert (!lglisfalsefun (cls));
14512     assert (!lglistruefun (cls));
14513     lglandfun (res, cls);
14514     INCSTEPS (elm.copies);
14515   }
14516 DONE:
14517   return 1;
14518 }
14519
14520 static void lglresetsmallve (LGL * lgl) {
14521   lglclnstk (&lgl->elm->m2i);
14522   lglclnstk (&lgl->elm->clv);
14523   lglpopnunmarkstk (lgl, &lgl->seen);
14524 }
14525
14526 static void lglsmallevalcls (unsigned cls, Fun res) {
14527   Fun tmp;
14528   int v;
14529   lglfalsefun (res);
14530   for (v = 0; v < FUNVAR; v++) {
14531     if (cls & (1 << (2*v + 1))) {
14532       lglvar2fun (v, tmp);
14533       lglornegfun (res, tmp);
14534     } else if (cls & (1 << (2*v))) {
14535       lglvar2fun (v, tmp);
14536       lglorfun (res, tmp);
14537     }
14538   }
14539 }
14540
14541 static Cnf lglpos2cnf (int pos) { assert (pos >=0 ); return pos; }
14542 static Cnf lglsize2cnf (int s) { assert (s >=0 ); return ((Cnf)s) << 32; }
14543 static int lglcnf2pos (Cnf cnf) { return cnf & 0xfffffll; }
14544 static int lglcnf2size (Cnf cnf) { return cnf >> 32; }
14545
14546 static Cnf lglcnf (int pos, int size) {
14547   return lglpos2cnf (pos) | lglsize2cnf (size);
14548 }
14549
14550 static void lglsmallevalcnf (LGL * lgl, Cnf cnf, Fun res) {
14551   Fun tmp;
14552   int i, n, p, cls;
14553   p = lglcnf2pos (cnf);
14554   n = lglcnf2size (cnf);
14555   lgltruefun (res);
14556   for (i = 0; i < n; i++) {
14557     cls = lglpeek (&lgl->elm->clv, p + i);
14558     lglsmallevalcls (cls, tmp);
14559     lglandfun (res, tmp);
14560   }
14561 }
14562
14563 static void lglnegcofactorfun (const Fun f, int v, Fun res) {
14564   Fun mask, masked;
14565   lglvar2fun (v, mask);
14566   lgland3negfun (masked, f, mask);
14567   lglfuncpy (res, masked);
14568   lglslfun (masked, (1 << v));
14569   lglorfun (res, masked);
14570 }
14571
14572 static void lglposcofactorfun (const Fun f, int v, Fun res) {
14573   Fun mask, masked;
14574   lglvar2fun (v, mask);
14575   lgland3fun (masked, f, mask);
14576   lglfuncpy (res, masked);
14577   lglsrfun (masked, (1 << v));
14578   lglorfun (res, masked);
14579 }
14580
14581 static int lglsmallfundeps0 (const Fun f) {
14582   int i;
14583   for (i = 0; i < FUNQUADS; i++)
14584     if (((f[i] & 0xaaaaaaaaaaaaaaaaull)>>1) !=
14585          (f[i] & 0x5555555555555555ull)) return 1;
14586   return 0;
14587 }
14588
14589 static int lglsmallfundeps1 (const Fun f) {
14590   int i;
14591   for (i = 0; i < FUNQUADS; i++)
14592     if (((f[i] & 0xccccccccccccccccull)>>2) !=
14593          (f[i] & 0x3333333333333333ull)) return 1;
14594   return 0;
14595 }
14596
14597 static int lglsmallfundeps2 (const Fun f) {
14598   int i;
14599   for (i = 0; i < FUNQUADS; i++)
14600     if (((f[i] & 0xf0f0f0f0f0f0f0f0ull)>>4) !=
14601          (f[i] & 0x0f0f0f0f0f0f0f0full)) return 1;
14602   return 0;
14603 }
14604
14605 static int lglsmallfundeps3 (const Fun f) {
14606   int i;
14607   for (i = 0; i < FUNQUADS; i++)
14608     if (((f[i] & 0xff00ff00ff00ff00ull)>>8) !=
14609          (f[i] & 0x00ff00ff00ff00ffull)) return 1;
14610   return 0;
14611 }
14612
14613 static int lglsmallfundeps4 (const Fun f) {
14614   int i;
14615   for (i = 0; i < FUNQUADS; i++)
14616     if (((f[i] & 0xffff0000ffff0000ull)>>16) !=
14617          (f[i] & 0x0000ffff0000ffffull)) return 1;
14618   return 0;
14619 }
14620
14621 static int lglsmallfundeps5 (const Fun f) {
14622   int i;
14623   for (i = 0; i < FUNQUADS; i++)
14624     if (((f[i] & 0xffffffff00000000ull)>>32) !=
14625          (f[i] & 0x00000000ffffffffull)) return 1;
14626   return 0;
14627 }
14628
14629 static int lglsmallfundepsgen (const Fun f, int min) {
14630   const int c = (1 << (min - 6));
14631   int i, j;
14632   assert (min >= 6);
14633   for (i = 0; i < FUNQUADS; i += (1 << (min - 5)))
14634     for (j = 0; j < c; j++)
14635       if (f[i + j] != f[i + c + j]) return 1;
14636   return 0;
14637 }
14638
14639 static int lglsmalltopvar (const Fun f, int min) {
14640   int i;
14641   switch (min) {
14642     case 0: if (lglsmallfundeps0 (f)) return 0;
14643     case 1: if (lglsmallfundeps1 (f)) return 1;
14644     case 2: if (lglsmallfundeps2 (f)) return 2;
14645     case 3: if (lglsmallfundeps3 (f)) return 3;
14646     case 4: if (lglsmallfundeps4 (f)) return 4;
14647     case 5: if (lglsmallfundeps5 (f)) return 5;
14648   }
14649   for (i = lglmax (6, min); i <= FUNVAR - 2; i++)
14650     if (lglsmallfundepsgen (f, i)) return i;
14651   return i;
14652 }
14653
14654 static Cnf lglsmalladdlit2cnf (LGL * lgl, Cnf cnf, int lit) {
14655   int p, m, q, n, i, cls;
14656   Cnf res;
14657   p = lglcnf2pos (cnf);
14658   m = lglcnf2size (cnf);
14659   q = lglcntstk (&lgl->elm->clv);
14660   for (i = 0; i < m; i++) {
14661     cls = lglpeek (&lgl->elm->clv, p + i);
14662     assert (!(cls & lit));
14663     cls |= lit;
14664     lglpushstk (lgl, &lgl->elm->clv, cls);
14665   }
14666   n = lglcntstk (&lgl->elm->clv) - q;
14667   res = lglcnf (q, n);
14668   return res;
14669 }
14670
14671 #ifndef NDEBUG
14672 static int lglefun (const Fun a, const Fun b) {
14673   int i;
14674   for (i = 0; i < FUNQUADS; i++)
14675     if (a[i] & ~b[i]) return 0;
14676   return 1;
14677 }
14678 #endif
14679
14680 // The dual version of Minato's algorithm for computing an irredundant
14681 // product of sums.   The original algorithm computes an irredundant sum of
14682 // products. It uses BDDs for representing boolean functions and ZDDs for
14683 // manipulating sum of product.  We work with function tables stored as bit
14684 // maps and plain CNFs stored as lists of clauses instead.
14685
14686 static Cnf lglsmallipos (LGL * lgl, const Fun U, const Fun L, int min) {
14687   Fun U0, U1, L0, L1, Unew, ftmp;
14688   Cnf c0, c1, cstar, ctmp, res;
14689   int x, y, z;
14690   assert (lglefun (L, U));
14691   if (lglistruefun (U)) return TRUECNF;
14692   if (lglisfalsefun (L)) return FALSECNF;
14693   lgl->stats->elm.ipos++;
14694   assert (min < lglcntstk (&lgl->elm->m2i));
14695   y = lglsmalltopvar (U, min);
14696   z = lglsmalltopvar (L, min);
14697   INCSTEPS (elm.steps);
14698   x = (y < z) ? y : z;
14699   assert (x < FUNVAR);
14700   lglnegcofactorfun (U, x, U0); lglposcofactorfun (U, x, U1);
14701   lglnegcofactorfun (L, x, L0); lglposcofactorfun (L, x, L1);
14702   lglor3negfun (ftmp, U0, L1);
14703   c0 = lglsmallipos (lgl, ftmp, L0, min+1);
14704   lglor3negfun (ftmp, U1, L0);
14705   c1 = lglsmallipos (lgl, ftmp, L1, min+1);
14706   lglsmallevalcnf (lgl, c0, ftmp);
14707   lglor3negfun (Unew, U0, ftmp);
14708   lglsmallevalcnf (lgl, c1, ftmp);
14709   lglandornegfun (Unew, U1, ftmp);
14710   lglor3fun (ftmp, L0, L1);
14711   cstar = lglsmallipos (lgl, Unew, ftmp, min+1);
14712   assert (cstar != FALSECNF);
14713   ctmp = lglsmalladdlit2cnf (lgl, c1, (1 << (2*x + 1)));
14714   res = lglcnf2pos (ctmp);
14715   ctmp = lglsmalladdlit2cnf (lgl, c0, (1 << (2*x)));
14716   if (res == TRUECNF) res = lglcnf2pos (ctmp);
14717   ctmp = lglsmalladdlit2cnf (lgl, cstar, 0);
14718   if (res == TRUECNF) res = lglcnf2pos (ctmp);
14719   res |= lglsize2cnf (lglcntstk (&lgl->elm->clv) - res);
14720   return res;
14721 }
14722
14723 static void lglsmallve (LGL * lgl, Cnf cnf) {
14724   int * soc = lgl->elm->clv.start + lglcnf2pos (cnf);
14725   int * eoc = soc + lglcnf2size (cnf);
14726   int * p, cls, v, lit, trivial;
14727   Val val;
14728   for (p = soc; !lgl->mt && p < eoc; p++) {
14729     cls = *p;
14730     assert (lglmtstk (&lgl->clause));
14731     trivial = 0;
14732     for (v = 0; v < FUNVAR; v++) {
14733       if (cls & (1 << (2*v + 1))) lit = -lglm2i (lgl, v+2);
14734       else if (cls & (1 << (2*v))) lit = lglm2i (lgl, v+2);
14735       else continue;
14736       val = lglval (lgl, lit);
14737       if (val < 0) continue;
14738       if (val > 0) trivial = 1;
14739       lglpushstk (lgl, &lgl->clause, lit);
14740     }
14741     if (!trivial) {
14742       INCSTEPS (elm.resolutions);
14743       lglpushstk (lgl, &lgl->clause, 0);
14744       LOGCLS (3, lgl->clause.start, "small elimination resolvent");
14745       if (lgl->opts->drup.val) lgldrupcls (lgl);
14746 #ifndef NLGLPICOSAT
14747       lglpicosatchkcls (lgl);
14748 #endif
14749       lgladdcls (lgl, 0, 0, 1);
14750     }
14751     lglclnstk (&lgl->clause);
14752   }
14753 }
14754
14755 static int lglsmallisunitcls (LGL * lgl, int cls) {
14756   int fidx, fsign, flit, mlit, ilit;
14757   ilit = 0;
14758   for (fidx = 0; fidx < FUNVAR; fidx++)
14759     for (fsign = 0; fsign <= 1; fsign++) {
14760       flit = 1<<(2*fidx + fsign);
14761       if (!(cls & flit)) continue;
14762       if (ilit) return 0;
14763       mlit = (fidx + 2) * (fsign ? -1 : 1);
14764       ilit = lglm2i (lgl, mlit);
14765     }
14766   return ilit;
14767 }
14768
14769 static int lglsmallcnfunits (LGL * lgl, Cnf cnf) {
14770   int p, m, i, res, cls, ilit;
14771   p = lglcnf2pos (cnf);
14772   m = lglcnf2size (cnf);
14773   res = 0;
14774   for (i = 0; i < m; i++) {
14775     cls = lglpeek (&lgl->elm->clv, p + i);
14776     ilit = lglsmallisunitcls (lgl, cls);
14777     if (!ilit) continue;
14778     assert (lglval (lgl, ilit) >= 0);
14779     lglunit (lgl, ilit);
14780     res++;
14781   }
14782   return res;
14783 }
14784
14785 static int lgltrysmallve (LGL * lgl, int idx) {
14786   int res, new, old, units;
14787   Fun pos, neg, fun;
14788   EVar * ev;
14789   Cnf cnf;
14790   assert (lglmtstk (&lgl->elm->m2i));
14791   assert (lglmtstk (&lgl->seen));
14792   assert (lglmtstk (&lgl->elm->clv));
14793   if (!lgl->opts->smallve.val) return 0;
14794   if (lgl->opts->smallvewait.val && !lgl->elmrtc) return 0;
14795   lglpushstk (lgl, &lgl->elm->m2i, 0);
14796   lglpushstk (lgl, &lgl->elm->clv, 0);
14797   res = 0;
14798   if (lglinitsmallve (lgl, idx, pos) && lglinitsmallve (lgl, -idx, neg)) {
14799     lglor3fun (fun, pos, neg);
14800     cnf = lglsmallipos (lgl, fun, fun, 0);
14801     new = lglcnf2size (cnf);
14802     units = lglsmallcnfunits (lgl, cnf);
14803     assert (units <= new);
14804     new -= units;
14805     ev = lglevar (lgl, idx);
14806     old = ev->occ[0] + ev->occ[1];
14807     LOG (2, "small elimination of %d replaces "
14808             "%d old with %d new clauses and %d units",
14809          idx, old, new, units);
14810     lgl->stats->elm.small.tried++;
14811     if (new <= old) {
14812       LOG (2, "small elimination of %d removes %d clauses", idx, old - new);
14813       lglepusheliminated (lgl, idx);
14814       lglflushclauses (lgl, idx);
14815       lglflushclauses (lgl, -idx);
14816       lglsmallve (lgl, cnf);
14817       lgl->stats->elm.small.elm++;
14818       res = 1;
14819     } else {
14820       LOG (2, "small elimination of %d would add %d clauses", idx, new - old);
14821       if (units > 0) res = 1;
14822       else lgl->stats->elm.small.failed++;
14823     }
14824   } else LOG (2, "too many variables for small elimination");
14825   lglresetsmallve (lgl);
14826   return res;
14827 }
14828
14829 static int lgl2manyoccs4elm (LGL * lgl, int lit) {
14830   return lglocc (lgl, lit) > 
14831            lglfactor (lgl, lgl->opts->elmocclim.val, lgl->stats->elm.count);
14832 }
14833
14834 static int lglchkoccs4elmlit (LGL * lgl, int lit) {
14835   int blit, tag, red, other, other2, lidx, size, lits, count;
14836   const int * p, * w, * eow, * c, * l;
14837   int64_t litslim;
14838   HTS * hts;
14839   if (lgl->opts->elmfull.val) return 1;
14840   count = lgl->stats->elm.count;
14841   litslim = lglfactor (lgl, lgl->opts->elmlitslim.val, count);
14842   hts = lglhts (lgl, lit);
14843   w = lglhts2wchs (lgl, hts);
14844   eow = w + hts->count;
14845   lits = 0;
14846   for (p = w; p < eow; p++) {
14847     blit = *p;
14848     tag = blit & MASKCS;
14849     red = blit & REDCS;
14850     if (tag == TRNCS || tag == LRGCS) p++;
14851     if (red || tag == LRGCS) continue;
14852     if (tag == BINCS) {
14853       other = blit >> RMSHFT;
14854       if (lgl2manyoccs4elm (lgl, other)) return 0;
14855       lits += 2;
14856     } else if (tag == TRNCS) {
14857       other = blit >> RMSHFT;
14858       if (lgl2manyoccs4elm (lgl, other)) return 0;
14859       other2 = *p;
14860       if (lgl2manyoccs4elm (lgl, other2)) return 0;
14861       lits += 3;
14862     } else {
14863       assert (tag == OCCS);
14864       lidx = blit >> RMSHFT;
14865       c = lglidx2lits (lgl, 0, lidx);
14866       size = 0;
14867       for (l = c; (other = *l); l++) {
14868         if (lgl2manyoccs4elm (lgl, other)) return 0;
14869         if (++size > lglfactor (lgl, lgl->opts->elmclslim.val, count))
14870           return 0;
14871       }
14872       lits += size;
14873     }
14874     if (lits > litslim) return 0;
14875   }
14876   return 1;
14877 }
14878
14879 static int lglchkoccs4elm (LGL * lgl, int idx) {
14880   int res;
14881   if ((res = lglforcedve (lgl, idx)) > 0) return 1;
14882   if (res < 0) return 0;
14883   if (lgl2manyoccs4elm (lgl, idx)) return 0;
14884   if (lgl2manyoccs4elm (lgl, -idx)) return 0;
14885   if (!lglchkoccs4elmlit (lgl, idx)) return 0;
14886   if (!lglchkoccs4elmlit (lgl, -idx)) return 0;
14887   return 1;
14888 }
14889
14890 static void lglelimlit (LGL * lgl, int idx) {
14891   int forced;
14892   if (!lglisfree (lgl, idx)) return;
14893   if (!lglchkoccs4elm (lgl, idx)) return;
14894   LOG (2, "trying to eliminate %d", idx);
14895   if ((forced = lglforcedve (lgl, idx)) < 0) return;
14896   if (!forced && lgltrysmallve (lgl, idx)) return;
14897   lglinitecls (lgl, idx);
14898   lglelimlitaux (lgl, idx);
14899   if (lgl->elm->pivot) lglrstecls (lgl);
14900 }
14901
14902 static int lglblockcls (LGL * lgl, int lit) {
14903   int blit, tag, red, other, other2, lidx, val, count, size;
14904   const int * p, * w, * eow, * c, *l;
14905   int bc = lgl->stats->blk.count;
14906   HTS * hts;
14907   INCSTEPS (blk.steps);
14908   hts = lglhts (lgl, lit);
14909   if (!hts->count) return 1;
14910   w = lglhts2wchs (lgl, hts);
14911   eow = w + hts->count;
14912   count = 0;
14913   for (p = w; p < eow; p++) {
14914     blit = *p;
14915     tag = blit & MASKCS;
14916     if (tag == TRNCS || tag == LRGCS) p++;
14917     if (tag == LRGCS) continue;
14918     red = blit & REDCS;
14919     if (red) continue;
14920     count++;
14921     lgl->stats->blk.res++;
14922     INCSTEPS (blk.steps);
14923     if (tag == BINCS || tag == TRNCS) {
14924       other = blit >> RMSHFT;
14925       val = lglmarked (lgl, other);
14926       if (val < 0) continue;
14927       if (tag == TRNCS) {
14928         other2 = *p;
14929         val = lglmarked (lgl, other2);
14930         if (val < 0) continue;
14931       }
14932     } else {
14933       assert (tag == OCCS);
14934       lidx = blit >> RMSHFT;
14935       c = lglidx2lits (lgl, 0, lidx);
14936       size = 0;
14937       for (l = c; (other = *l); l++) {
14938         val = lglmarked (lgl, other);
14939         if (++size > lglfactor (lgl, lgl->opts->blkclslim.val, bc)) return 0;
14940         if (val < 0) break;
14941       }
14942       if (other) continue;
14943     }
14944     return 0;
14945   }
14946   LOG (3, "resolved %d trivial resolvents on %d", count, lit);
14947   return 1;
14948 }
14949
14950 static int lglpurelit (LGL * lgl, int lit) {
14951   int res;
14952   LOG(1, "pure literal %d", lit);
14953   lgl->stats->blk.pure++;
14954   assert (!lglocc (lgl, -lit));
14955   res = lglflushclauses (lgl, lit);
14956   lgl->stats->blk.clauses += res;
14957   if (lgl->blocking) ADDSTEPS (blk.steps, res);
14958   lglepusheliminated (lgl, lit);
14959   return res;
14960 }
14961
14962 static int lgl2manyoccs4blk (LGL * lgl, int lit) {
14963   return lglhts (lgl, lit)->count >
14964            lglfactor (lgl, lgl->opts->blkocclim.val, lgl->stats->blk.count);
14965 }
14966
14967 static int lgldonotblocklit (LGL * lgl, int lit) {
14968   int pocc = lglocc (lgl, lit);
14969   int nocc = lglocc (lgl, -lit);
14970   int count = lgl->stats->blk.count;
14971   if (pocc >= lglfactor (lgl, lgl->opts->blkocclim1.val, count)) return 1;
14972   if (nocc >= lglfactor (lgl, lgl->opts->blkocclim1.val, count)) return 1;
14973   if (pocc < lglfactor (lgl, lgl->opts->blkocclim2.val, count)) return 0;
14974   if (nocc < lglfactor (lgl, lgl->opts->blkocclim2.val, count)) return 0;
14975   return 1;
14976 }
14977
14978 static int lglblocklit (LGL * lgl, int lit, Stk * stk) {
14979   int blit, tag, red, blocked, other, other2, lidx, count, size;
14980   int bc = lgl->stats->blk.count;
14981   int * p, * w, * eow, * c, * l;
14982   HTS * hts;
14983   if (lglval (lgl, lit)) return 0;
14984   if (lgldonotblocklit (lgl, lit)) return 0;
14985   if (lgl2manyoccs4blk (lgl, lit)) return 0;
14986   hts = lglhts (lgl, lit);
14987   assert (!lgl->opts->pure.val || hts->count > 0);
14988   w = lglhts2wchs (lgl, hts);
14989   eow = w + hts->count;
14990   count = 0;
14991   assert (lglmtstk (stk+2) && lglmtstk (stk+3) && lglmtstk (stk+4));
14992   for (p = w; p < eow; p++) {
14993     if (INCSTEPS (blk.steps) >= lgl->limits->blk.steps) break;
14994     if (lglterminate (lgl)) break;
14995     blit = *p;
14996     tag = blit & MASKCS;
14997     if (tag == TRNCS || tag == LRGCS) p++;
14998     if (tag == LRGCS) continue;
14999     red = blit & REDCS;
15000     if (red) continue;
15001     assert (lglmtstk (&lgl->seen));
15002     blocked = 0;
15003     if (tag == BINCS || tag == TRNCS) {
15004       if (!lgl->opts->blksmall.val) continue;
15005       other = blit >> RMSHFT;
15006       if (lgl2manyoccs4blk (lgl, other)) continue;
15007       lglpushnmarkseen (lgl, other);
15008       if (tag == TRNCS) {
15009         other2 = *p;
15010         if (lgl2manyoccs4blk (lgl, other2)) goto CONTINUE;
15011         lglpushnmarkseen (lgl, other2);
15012       }
15013     } else {
15014       assert (tag == OCCS);
15015       if (!lgl->opts->blklarge.val) continue;
15016       lidx = blit >> RMSHFT;
15017       c = lglidx2lits (lgl, 0, lidx);
15018       size = 0;
15019       for (l = c; (other = *l); l++) {
15020         if (other == lit) continue;
15021         if (lgl2manyoccs4blk (lgl, other)) goto CONTINUE;
15022         if (++size > lglfactor (lgl, lgl->opts->blkclslim.val, bc))
15023           goto CONTINUE;
15024         lglpushnmarkseen (lgl, other);
15025       }
15026     }
15027     blocked = lglblockcls (lgl, -lit);
15028 CONTINUE:
15029     lglpopnunmarkstk (lgl, &lgl->seen);
15030     if (!blocked) continue;
15031     if (tag == BINCS) {
15032       other = blit >> RMSHFT;
15033       lglpushstk (lgl, stk+2, other);
15034     } else if (tag == TRNCS) {
15035       other = blit >> RMSHFT;
15036       lglpushstk (lgl, stk+3, other);
15037       other2 = *p;
15038       lglpushstk (lgl, stk+3, other2);
15039     } else {
15040       assert (tag == OCCS);
15041       lidx = blit >> RMSHFT;
15042       lglpushstk (lgl, stk+4, lidx);
15043     }
15044   }
15045   while (!lglmtstk (stk+2)) {
15046     if (INCSTEPS (blk.steps) >= lgl->limits->blk.steps) break;
15047     count++;
15048     other = lglpopstk (stk+2);
15049     LOG (2, "blocked binary clause %d %d on %d", lit, other, lit);
15050     lglrmbcls (lgl, lit, other, 0);
15051     lglepush (lgl, lit);
15052     lglepush (lgl, other);
15053     lglepush (lgl, 0);
15054     if (lgl->opts->move.val) lglmvbcls (lgl, lit, other);
15055   }
15056   while (!lglmtstk (stk+3)) {
15057     if (INCSTEPS (blk.steps) >= lgl->limits->blk.steps) break;
15058     count++;
15059     other2 = lglpopstk (stk+3);
15060     other = lglpopstk (stk+3);
15061     LOG (2, "blocked ternary clause %d %d %d on %d", lit, other, other2, lit);
15062     lglrmtcls (lgl, lit, other, other2, 0);
15063     lglepush (lgl, lit);
15064     lglepush (lgl, other);
15065     lglepush (lgl, other2);
15066     lglepush (lgl, 0);
15067     if (lgl->opts->move.val >= 2) lglmvtcls (lgl, lit, other, other2);
15068   }
15069   while (!lglmtstk (stk+4)) {
15070     if (INCSTEPS (blk.steps) >= lgl->limits->blk.steps) break;
15071     lidx = lglpopstk (stk+4);
15072     count++;
15073     c = lglidx2lits (lgl, 0, lidx);
15074     LOGCLS (2, c, "blocked on %d large clause", lit);
15075     lglepush (lgl, lit);
15076     for (l = c; (other = *l); l++)
15077       if (other != lit) lglepush (lgl, other);
15078     lglepush (lgl, 0);
15079     lglrmvlcls (lgl, lidx);
15080   }
15081   LOG (2, "found %d blocked clauses with %d", count, lit);
15082   lgl->stats->blk.clauses += count;
15083   if (count > 0) lglblockinglit (lgl, lit);
15084   lglclnstk (stk+2), lglclnstk (stk+3), lglclnstk (stk+4);
15085   return count;
15086 }
15087
15088 static void lglsetblklim (LGL * lgl) {
15089   int64_t limit, irrlim;
15090   int pen;
15091   if (lgl->opts->blkrtc.val) {
15092     lgl->limits->blk.steps = LLMAX;
15093     lglprt (lgl, 1, "[block-%d] no limit", lgl->stats->blk.count);
15094   } else {
15095     limit = (lgl->opts->blkreleff.val*lglvisearch (lgl))/1000;
15096     if (limit < lgl->opts->blkmineff.val) limit = lgl->opts->blkmineff.val;
15097     if (lgl->opts->blkmaxeff.val >= 0 && limit > lgl->opts->blkmaxeff.val)
15098       limit = lgl->opts->blkmaxeff.val;
15099     if (lgl->stats->blk.count <= 1 &&
15100         lgl->opts->boost.val &&
15101         lgl->nvars < lgl->opts->blkboostvlim.val) {
15102       lglprt (lgl, 1,
15103         "[block-%d] boosting limit by %d",
15104         lgl->stats->blk.count, lgl->opts->blkboost.val);
15105       limit *= lgl->opts->blkboost.val;
15106     }
15107     limit >>= (pen = lgl->limits->blk.pen + lglszpen (lgl));
15108     irrlim = lgl->stats->irr.clauses.cur/2;
15109     irrlim >>= lgl->limits->simp.pen;
15110     if (lgl->opts->irrlim.val && limit < irrlim) {
15111       limit = irrlim;
15112       lglprt (lgl, 1, 
15113         "[block-%d] limit of %lld steps based on %d irredundant clauses",
15114         lgl->stats->blk.count, (LGLL) limit, lgl->stats->irr.clauses.cur);
15115     } else
15116       lglprt (lgl, 1, 
15117         "[block-%d] limit of %lld steps penalty %d = %d + %d",
15118         lgl->stats->blk.count, (LGLL) limit,
15119         pen, lgl->limits->blk.pen, lglszpen (lgl));
15120     lgl->limits->blk.steps = lgl->stats->blk.steps + limit;
15121   }
15122 }
15123
15124 static int lgleschedrem (LGL * lgl, int this_time) {
15125   int idx, res = 0, count;
15126   const char * str;
15127   AVar * av;
15128   for (idx = 2; idx < lgl->nvars; idx++) {
15129     if (lglifrozen (lgl, idx)) continue;
15130     if (!lglisfree (lgl, idx)) continue;
15131     av = lglavar (lgl, idx);
15132     if (lgl->eliminating && av->donotelm) continue;
15133     if (lgl->blocking && av->donotblk) continue;
15134     res++;
15135   }
15136   assert (lgl->eliminating || lgl->blocking);
15137   if (lgl->eliminating) count = lgl->stats->elm.count, str = "elim";
15138   else assert (lgl->blocking), count = lgl->stats->blk.count, str = "block";
15139   if (res)
15140     lglprt (lgl, 1,
15141       "[%s-%d] %d variables %.0f%% %s time",
15142       str, count,
15143       res, lglpcnt (res, lglrem (lgl)),
15144       this_time ? "will be scheduled this" : "remain to be tried next");
15145   else {
15146     lglprt (lgl, 1,
15147       "[%s-%d] no untried remaining variables left",
15148       str, count);
15149     for (idx = 2; idx < lgl->nvars; idx++) {
15150       av = lglavar (lgl, idx);
15151       if (lgl->eliminating) av->donotelm = 0;
15152       if (lgl->blocking) av->donotblk = 0;
15153     }
15154   }
15155   return res;
15156 }
15157
15158 static void lglsetdonotesched (LGL * lgl, int completed) {
15159   AVar * av;
15160   EVar * ev;
15161   int idx;
15162   assert (lgl->eliminating + lgl->blocking == 1);
15163   for (idx = 2; idx < lgl->nvars; idx++) {
15164     av = lglavar (lgl, idx);
15165     ev = lglevar (lgl, idx);
15166     if (lgl->eliminating) {
15167       if (completed) av->donotelm = 0;
15168       else if (ev->pos < 0) av->donotelm = 1;
15169     }
15170     if (lgl->blocking) {
15171       if (completed) av->donotblk = 0;
15172       else if (ev->pos < 0) av->donotblk = 1;
15173     }
15174   }
15175 }
15176
15177 static int lglblkdone (LGL * lgl) {
15178   if (!lglsmallirr (lgl)) return 1;
15179   if (lglterminate (lgl)) return 1;
15180   if (lglmtstk (&lgl->esched)) return 1;
15181   if (lgl->stats->blk.steps >= lgl->limits->blk.steps) return 1;
15182   return 0;
15183 }
15184
15185 static int lglispure (LGL * lgl, int lit) {
15186   if (!lgl->opts->pure.val) return 0;
15187   if (lglifrozen (lgl, lit)) return 0;
15188   return !lglocc (lgl, -lit);
15189 }
15190
15191 static void lglblock (LGL * lgl) {
15192   int oldrem = lgl->blkrem, oldall = lgl->blkall;
15193   int oldirr = lgl->stats->irr.clauses.cur;
15194   int idx, count, all, rem, success;
15195   Stk blocked[5];
15196   assert (lglsmallirr (lgl));
15197   assert (!lgl->simp);
15198   assert (!lgl->dense);
15199   assert (!lgl->eliminating);
15200   assert (!lgl->blocking);
15201   assert (!lgl->occs);
15202   lglstart (lgl, &lgl->times->blk);
15203   if (lgl->level) lglbacktrack (lgl, 0);
15204   lgl->simp = lgl->blocking = lgl->occs = 1;
15205   lgl->stats->blk.count++;
15206   lglgc (lgl);
15207   assert (lgl->frozen);
15208   assert (!(oldall && !oldrem));
15209   all = !oldrem || !oldall;
15210   if (all)
15211     lglprt (lgl, 1,
15212       "[block-%d] scheduling all variables this time",
15213       lgl->stats->blk.count);
15214   else if (!lgleschedrem (lgl, 1)) all = 1, oldrem = 0;
15215   if (!all) assert (!lgl->donotsched), lgl->donotsched = 1;
15216   lgldense (lgl, 1);
15217   if (!all) assert (lgl->donotsched), lgl->donotsched = 0;
15218   lglsetblklim (lgl);
15219   CLR (blocked);
15220   count = 0;
15221   while (!lglblkdone (lgl)) {
15222     idx = lglpopesched (lgl);
15223     lglavar (lgl, idx)->donotblk = 1;
15224     if (!lglisfree (lgl, idx)) continue;
15225     if (lglispure (lgl, -idx)) count += lglpurelit (lgl, -idx);
15226     else if (lglispure (lgl, idx)) count += lglpurelit (lgl, idx);
15227     else {
15228       if (lglocc (lgl, -idx) > lglocc (lgl, idx)) idx = -idx;
15229       count += lglblocklit (lgl, idx, blocked);
15230       count += lglblocklit (lgl, -idx, blocked);
15231     }
15232   }
15233   rem = lglcntstk (&lgl->esched);
15234   if (!rem) {
15235     lglprt (lgl, 1,
15236       "[block-%d] fully completed",
15237       lgl->stats->blk.count);
15238     lgl->blkrtc = 1;
15239   } else {
15240     lglprt (lgl, 1,
15241       "[block-%d] incomplete %d not tried %.0f%%",
15242       lgl->stats->blk.count, rem, lglpcnt (rem, lgl->nvars - 2));
15243   }
15244   lglsetdonotesched (lgl, !rem);
15245   lglrelstk (lgl, &lgl->esched);
15246   lglsparse (lgl);
15247   lglgc (lgl);
15248   lglrelstk (lgl, blocked+2);
15249   lglrelstk (lgl, blocked+3);
15250   lglrelstk (lgl, blocked+4);
15251   lgl->blkrem = rem > 0;
15252   lgl->blkall = all && lgl->blkrem;
15253   lglprt (lgl, 1,
15254     "[block-%d] transition to [ all %d rem %d ] state",
15255     lgl->stats->blk.count, lgl->blkall, lgl->blkrem);
15256   assert (lgl->simp && lgl->blocking && lgl->occs);
15257   lgl->blocking = lgl->simp = lgl->occs = 0;
15258   lgl->stats->irrprgss += count;
15259   lglprt (lgl, 1,
15260     "[block-%d] eliminated %d blocked clauses",
15261     lgl->stats->blk.count, count);
15262   if (oldirr < lgl->opts->blksuccesslim.val) success = count;
15263   else if (count) {
15264     success = (oldirr/lgl->opts->blksuccessrat.val <= count);
15265     if (!success)
15266       lglprt (lgl, 1,
15267         "[block-%d] %d < 1/%d * %d = %d considered unsuccessful",
15268         lgl->stats->blk.count, count, lgl->opts->blksuccessrat.val,
15269         oldirr, oldirr/lgl->opts->blksuccessrat.val);
15270   } else success = 0;
15271   LGLUPDPEN (blk, success);
15272   lgl->blkstuck = !rem && !count;
15273   if (lgl->blkstuck)
15274     lglprt (lgl, 2,
15275       "[block-%d] completed but nothing eliminated thus stuck",
15276       lgl->stats->blk.count);
15277   lglrep (lgl, 2, 'k');
15278   lglstop (lgl);
15279   assert (!lgl->mt);
15280 }
15281
15282 static void lglsetccelim (LGL * lgl) {
15283   int64_t limit, irrlim;
15284   int pen;
15285   if (lgl->opts->ccertc.val) {
15286     lgl->limits->cce.steps = LLMAX;
15287     lglprt (lgl, 1, "[cce-%d] no limit", lgl->stats->cce.count);
15288   } else {
15289     limit = (lgl->opts->ccereleff.val*lglvisearch (lgl))/1000;
15290     if (limit < lgl->opts->ccemineff.val) limit = lgl->opts->ccemineff.val;
15291     if (lgl->opts->ccemaxeff.val >= 0 && limit > lgl->opts->ccemaxeff.val)
15292       limit = lgl->opts->ccemaxeff.val;
15293     if (lgl->stats->cce.count <= 1 &&
15294         lgl->opts->boost.val &&
15295         lgl->nvars < lgl->opts->cceboostvlim.val) {
15296       lglprt (lgl, 1,
15297         "[cce-%d] boosting limit by %d",
15298         lgl->stats->cce.count, lgl->opts->cceboost.val);
15299       limit *= lgl->opts->cceboost.val;
15300     }
15301     limit >>= (pen = lgl->limits->cce.pen + lglszpen (lgl));
15302     irrlim = lgl->stats->irr.clauses.cur/2;
15303     irrlim >>= lgl->limits->simp.pen;
15304     if (lgl->opts->irrlim.val && limit < irrlim) {
15305       limit = irrlim;
15306       lglprt (lgl, 1,
15307         "[cce-%d] limit of %lld steps based on %d irredundant clauses",
15308         lgl->stats->cce.count, (LGLL) limit, lgl->stats->irr.clauses.cur);
15309     } else
15310       lglprt (lgl, 1,
15311         "[cce-%d] limit of %lld steps penalty %d = %d + %d",
15312         lgl->stats->cce.count, (LGLL) limit,
15313         pen, lgl->limits->cce.pen, lglszpen (lgl));
15314     lgl->limits->cce.steps = lgl->stats->cce.steps + limit;
15315   }
15316 }
15317
15318 #define CCELOGLEVEL 2
15319
15320 static void lglsignedmark2 (LGL * lgl, int lit) {
15321   AVar * av = lglavar (lgl, lit);
15322   int bit = 1 << (2 + (lit < 0));
15323   if (av->mark & bit) return;
15324   av->mark |= bit;
15325 }
15326
15327 static void lglsignedunmark2 (LGL * lgl, int lit) {
15328   AVar * av = lglavar (lgl, lit);
15329   int bit = 1 << (2 + (lit < 0));
15330   if (!(av->mark & bit)) return;
15331   av->mark &= ~bit;
15332 }
15333
15334 static int lglsignedmarked2 (LGL * lgl, int lit) {
15335   AVar * av = lglavar (lgl, lit);
15336   int bit = 1 << (2 + (lit < 0));
15337   return av->mark & bit;
15338 }
15339
15340 static int lglabcecls (LGL * lgl, int lit, const int * c) {
15341   int other, found = 0;
15342   const int * p;
15343   for (p = c; (other = *p); p++)
15344     if (other == -lit) found++;
15345     else if (lglsignedmarked (lgl, -other)) return 1;
15346   assert (found == 1);
15347   return 0;
15348 }
15349
15350 static int lglabce (LGL * lgl, int lit) {
15351   const int * p, * w, * eow, * c;
15352   int blit, tag, other, cls[4];
15353   HTS * hts;
15354   assert (!lglifrozen (lgl, lit));
15355   hts = lglhts (lgl, -lit);
15356   w = lglhts2wchs (lgl, hts);
15357   eow = w + hts->count;
15358   cls[0] = -lit, cls[3] = 0;
15359   for (p = w; p < eow; p++) {
15360     if (lgl->limits->cce.steps <= INCSTEPS (cce.steps)) return 0;
15361     blit = *p;
15362     tag = blit & MASKCS;
15363     if (tag == TRNCS || tag == LRGCS) p++;
15364     if (blit & REDCS) continue;
15365     if (tag == LRGCS) continue;
15366     other = blit >> RMSHFT;
15367     cls[1] = other;
15368     if (tag == BINCS) cls[2] = 0, c = cls;
15369     else if (tag == TRNCS) cls[2] = *p, c = cls;
15370     else assert (tag == OCCS), c = lglidx2lits (lgl, 0, other);
15371     if (!lglabcecls (lgl, lit, c)) return 0;
15372   }
15373   return 1;
15374 }
15375
15376 static int lglcceclause (LGL * lgl,
15377                          const int * c, 
15378                          int igntag,
15379                          int cce) {
15380   int other, res, nextala, nextcla, lit, blit, tag, other2, i, j, n;
15381   const int * p, * eow, * w, * d, * q;
15382   int unit, first, old, prev;
15383   HTS * hts;
15384   int * r;
15385   LOGCLS (CCELOGLEVEL, c, "trying CCE on clause");
15386   assert (lglmtstk (&lgl->cce->extend));
15387   assert (lglmtstk (&lgl->cce->cla));
15388   assert (lglmtstk (&lgl->seen));
15389   for (p = c; (other = *p); p++) {
15390     assert (!lglmarked (lgl, other));
15391     lglpushstk (lgl, &lgl->seen, other);
15392     lglpushstk (lgl, &lgl->cce->cla, other);
15393     lglsignedmark (lgl, other);
15394   }
15395   n = lglcntstk (&lgl->seen);
15396   for (i = n-1; i > 0; i--) {
15397     j = lglrand (lgl) % (i + 1);
15398     if (j == i) continue;
15399     SWAP (int, lgl->seen.start[i], lgl->seen.start[j]);
15400     SWAP (int, lgl->cce->cla.start[i], lgl->cce->cla.start[j]);
15401   }
15402   nextcla = nextala = res = 0;
15403 ALA:
15404   while (!res && nextala < lglcntstk (&lgl->seen)) {
15405     lit = lglpeek (&lgl->seen, nextala++);
15406     assert (lglsignedmarked (lgl, lit));
15407     assert (!lglsignedmarked (lgl, -lit));
15408     hts = lglhts (lgl, lit);
15409     w = lglhts2wchs (lgl, hts);
15410     eow = w + hts->count;
15411     for (p = w; !res && p < eow; p++) {
15412       if (lgl->limits->cce.steps <= INCSTEPS (cce.steps)) goto DONE;
15413       blit = *p;
15414       tag = blit & MASKCS;
15415       if (tag == TRNCS || tag == LRGCS) p++;
15416       if (tag == LRGCS) continue;
15417       if (blit & REDCS) continue;
15418       other = blit >> RMSHFT;
15419       if (tag == BINCS) {
15420         if (lglsignedmarked (lgl, -other)) continue;
15421         else if (lglsignedmarked (lgl, other)) {
15422           if (igntag == BINCS) {
15423             if (c[0] == lit && c[1] == other) continue;
15424             if (c[1] == lit && c[0] == other) continue;
15425           }
15426           LOG (CCELOGLEVEL, 
15427                "ALA on binary clause %d %d results in ATE", lit, other);
15428           res = 1;
15429         } else {
15430           assert (!lglmarked (lgl, other));
15431           LOG (CCELOGLEVEL, "ALA %d through binary clause %d %d", 
15432                -other, lit, other);
15433           lglsignedmark (lgl, -other);
15434           lglpushstk (lgl, &lgl->seen, -other);
15435         }
15436       } else if (tag == TRNCS) {
15437         if (lglsignedmarked (lgl, -other)) continue;
15438         other2 = *p;
15439         if (lglsignedmarked (lgl, -other2)) continue;
15440         if (lglsignedmarked (lgl, other)) {
15441           if (lglsignedmarked (lgl, other2)) {
15442             if (igntag == TRNCS) {
15443               if (c[0] == lit && c[1] == other && c[2] == other2) continue;
15444               if (c[0] == lit && c[2] == other && c[1] == other2) continue;
15445               if (c[1] == lit && c[0] == other && c[2] == other2) continue;
15446               if (c[1] == lit && c[2] == other && c[0] == other2) continue;
15447               if (c[2] == lit && c[0] == other && c[1] == other2) continue;
15448               if (c[2] == lit && c[1] == other && c[0] == other2) continue;
15449             }
15450             LOG (CCELOGLEVEL,
15451               "ALA on ternary clause %d %d %d results in ATE",
15452               lit, other, other2);
15453             res = 1;
15454           } else {
15455             assert (!lglmarked (lgl, other2));
15456             LOG (CCELOGLEVEL, 
15457                  "ALA %d through ternary clause %d %d %d (1st case)",
15458                  -other2, lit, other, other2);
15459             lglsignedmark (lgl, -other2);
15460             lglpushstk (lgl, &lgl->seen, -other2);
15461           }
15462         } else if (lglsignedmarked (lgl, other2)) {
15463           assert (!lglmarked (lgl, other));
15464           LOG (CCELOGLEVEL, 
15465               "ALA %d through ternary clause %d %d %d (2nd case)",
15466               -other, lit, other, other2);
15467           lglsignedmark (lgl, -other);
15468           lglpushstk (lgl, &lgl->seen, -other);
15469         }
15470       } else {
15471         assert (tag == OCCS);
15472         d = lglidx2lits (lgl, 0, other);
15473         if (d == c) { assert (igntag == OCCS); continue; }
15474         unit = 0;
15475         for (q = d; (other = *q); q++) {
15476           if (other == lit) continue;
15477           if (lglsignedmarked (lgl, -other)) break;
15478           if (lglsignedmarked (lgl, other)) continue;
15479           if (unit) break;
15480           unit = -other;
15481         }
15482         if (other) continue;
15483         if (!unit) {
15484           LOGCLS (CCELOGLEVEL, d, "ATE after ALA on large clause");
15485           res = 1;
15486         } else {
15487           assert (!lglmarked (lgl, unit));
15488           LOGCLS (CCELOGLEVEL, d, "ALA %d through large clause", unit);
15489           lglsignedmark (lgl, unit);
15490           lglpushstk (lgl, &lgl->seen, unit);
15491         }
15492       }
15493     }
15494   }
15495   if (res || !lgl->opts->block.val || cce < 3) goto SKIPCLA;
15496   while (!res && nextcla < lglcntstk (&lgl->cce->cla)) {
15497     lit = lglpeek (&lgl->cce->cla, nextcla++);
15498     if (lglifrozen (lgl, lit)) continue;
15499     assert (lglsignedmarked (lgl, lit));
15500     assert (!lglsignedmarked (lgl, -lit));
15501     hts = lglhts (lgl, -lit);
15502     w = lglhts2wchs (lgl, hts);
15503     eow = w + hts->count;
15504     old = lglcntstk (&lgl->cce->cla);
15505     first = 1;
15506     for (p = w; p < eow; p++) {
15507       if (lgl->limits->cce.steps <= INCSTEPS (cce.steps)) goto DONE;
15508       blit = *p;
15509       tag = blit & MASKCS;
15510       if (tag == TRNCS || tag == LRGCS) p++;
15511       if (tag == LRGCS) continue;
15512       if (blit & REDCS) continue;
15513       other = blit >> RMSHFT;
15514       if (first) {
15515         if (tag == BINCS) {
15516           if (lglsignedmarked (lgl, -other)) continue;
15517           if (!lglsignedmarked (lgl, other))
15518             lglpushstk (lgl, &lgl->cce->cla, other);
15519         } else if (tag == TRNCS) {
15520           if (lglsignedmarked (lgl, -other)) continue;
15521           if (lglsignedmarked (lgl, -*p)) continue;
15522           if (!lglsignedmarked (lgl, other))
15523             lglpushstk (lgl, &lgl->cce->cla, other);
15524           if (!lglsignedmarked (lgl, *p))
15525             lglpushstk (lgl, &lgl->cce->cla, *p);
15526         } else { 
15527           assert (tag == OCCS);
15528           d = lglidx2lits (lgl, 0, other);
15529           assert (d != c);
15530           for (q = d; (other = *q); q++)
15531             if (other != -lit && lglsignedmarked (lgl, -other)) break;
15532           if (other) continue;
15533           for (q = d; (other = *q); q++)
15534             if (other != -lit && !lglsignedmarked (lgl, other))
15535               lglpushstk (lgl, &lgl->cce->cla, other);
15536         }
15537         first = 0;
15538       } else {
15539         r = lgl->cce->cla.start + old;
15540         if (tag == BINCS) {
15541           if (lglsignedmarked (lgl, -other)) continue;
15542           for (q = r; q < lgl->cce->cla.top; q++)
15543             if (*q == other) *r++ = *q;
15544         } else if (tag == TRNCS) {
15545           if (lglsignedmarked (lgl, -other)) continue;
15546           if (lglsignedmarked (lgl, -(other2 = *p))) continue;
15547           for (q = r; q < lgl->cce->cla.top; q++)
15548             if (*q == other || *q == other2) *r++ = *q;
15549         } else {
15550           assert (tag == OCCS);
15551           d = lglidx2lits (lgl, 0, other);
15552           assert (d != c);
15553           for (q = d; (other = *q); q++)
15554             if (other != -lit && lglsignedmarked (lgl, -other)) break;
15555           if (other) continue;
15556           for (q = d; (other = *q); q++) {
15557             if (other == -lit) continue;
15558             assert (other != lit);
15559             assert (!lglsignedmarked2 (lgl, other));
15560             assert (!lglsignedmarked2 (lgl, -other));
15561             lglsignedmark2 (lgl, other);
15562           }
15563           for (q = r; q < lgl->cce->cla.top; q++)
15564             if (lglsignedmarked2 (lgl, (other = *q)))
15565               *r++ = other;
15566           for (q = d; (other = *q); q++) {
15567             if (other == -lit) continue;
15568             assert (other != lit);
15569             assert (lglsignedmarked2 (lgl, other));
15570             lglsignedunmark2 (lgl, other);
15571           }
15572         }
15573         if ((lgl->cce->cla.top = r) == lgl->cce->cla.start + old) break;
15574       }
15575     } 
15576     if (lglcntstk (&lgl->cce->cla) > old) {
15577       nextcla = 0;
15578       lglpushstk (lgl, &lgl->cce->extend, lit);
15579       for (q = lgl->cce->cla.start; q < lgl->cce->cla.start + old; q++)
15580         if (*q != lit) lglpushstk (lgl, &lgl->cce->extend, *q);
15581       lglpushstk (lgl, &lgl->cce->extend, 0);
15582     }
15583     for (q = lgl->cce->cla.start + old; !res && q < lgl->cce->cla.top; q++) {
15584       if (lglsignedmarked (lgl, -*q)) {
15585         LOG (CCELOGLEVEL, "CLA on %d results in ATE", *q);
15586         res = 1;
15587       } else {
15588         LOG (CCELOGLEVEL, "CLA %d on %d", *q, lit);
15589         lglpushstk (lgl, &lgl->seen, *q);
15590         lglsignedmark (lgl, *q);
15591       }
15592     }
15593     if (!res && p == eow && nextala < lglcntstk (&lgl->seen)) goto ALA;
15594   }
15595 SKIPCLA:
15596   if (res) {
15597     LOGCLS (CCELOGLEVEL, c, "ATE clause");
15598     lgl->stats->cce.ate++;
15599   } else if (lgl->opts->block.val && cce >= 2) {
15600    for (p = lgl->cce->cla.start; p < lgl->cce->cla.top; p++)
15601      if (!lglifrozen (lgl, (other = *p)) && (res = lglabce (lgl, other))) 
15602        break;
15603     if (res) {
15604       LOGCLS (CCELOGLEVEL, c, "ABCE on %d clause", other);
15605       lglpushstk (lgl, &lgl->cce->extend, other);
15606       for (p = lgl->cce->cla.start; p < lgl->cce->cla.top; p++)
15607         if (*p != other) lglpushstk (lgl, &lgl->cce->extend, *p);
15608       lglpushstk (lgl, &lgl->cce->extend, 0);
15609       lgl->stats->cce.abce++;
15610     }
15611   }
15612   if (res) lgl->stats->cce.eliminated++;
15613 DONE:
15614   lglpopnunmarkstk (lgl, &lgl->seen);
15615   lglclnstk (&lgl->cce->cla);
15616   if (res && !lglmtstk (&lgl->cce->extend)) {
15617     assert (cce >= 2);
15618     assert (lgl->opts->block.val);
15619     prev = 0;
15620     for (p = lgl->cce->extend.start; p < lgl->cce->extend.top; p++) {
15621       lit = *p;
15622       lglepush (lgl, lit);
15623       if (!prev) assert (!lglifrozen (lgl, lit)), lglblockinglit (lgl, lit);
15624       prev = lit;
15625     }
15626   }
15627   lglclnstk (&lgl->cce->extend);
15628   return res;
15629 }
15630
15631 static const char * lglcce2str (int cce) {
15632   assert (0 <= cce), assert (cce <= 3);
15633   if (cce == 3) return "ACCE";
15634   else if (cce == 2) return "ABCE";
15635   else if (cce == 1) return "ATE";
15636   else return "none";
15637 }
15638
15639 static int lglccesmallclauses (LGL * lgl, int lit) {
15640   int idx = abs (lit), blit, tag, red, other, other2;
15641   HTS * hts = lglhts (lgl, lit);
15642   const int * p, * w, * eow;
15643   CCE * cce = lgl->cce;
15644   Stk * clauses;
15645   assert (cce);
15646   if (!lglisfree (lgl, lit)) return 1;
15647   clauses = &cce->clauses;
15648   w = lglhts2wchs (lgl, hts);
15649   eow = w + hts->count;
15650   INCSTEPS (cce.steps);
15651   for (p = w; p < eow; p++) {
15652     blit = *p;
15653     tag = blit & MASKCS;
15654     if (tag == OCCS) continue;
15655     if (tag == TRNCS || tag == LRGCS) p++;
15656     if (tag == LRGCS) continue;
15657     red = blit & REDCS;
15658     if (red) continue;
15659     other = blit >> RMSHFT;
15660     if (abs (other) < idx) continue;
15661     if (!lglisfree (lgl, other)) continue;
15662     if (tag == TRNCS) {
15663       other2 = *p;
15664       if (abs (other2) < idx) continue;
15665       if (abs (other2) < abs (other)) continue;
15666       if (!lglisfree (lgl, other2)) continue;
15667       lglpushstk (lgl, clauses, other2);
15668       cce->trn++;
15669     } else {
15670       assert (tag == BINCS);
15671       cce->bin++;
15672     }
15673     lglpushstk (lgl, clauses, other);
15674     lglpushstk (lgl, clauses, lit);
15675     lglpushstk (lgl, clauses, 0);
15676   }
15677   return 1;
15678 }
15679
15680 static void lglccesmall (LGL * lgl, int cce) {
15681   int count, valid, invalid, tried, eliminated, elim2, elim3;
15682   int size, lit, tag;
15683   const int * p, * c;
15684   Stk * clauses;
15685   assert (lgl->cce);
15686   clauses = &lgl->cce->clauses;
15687   assert (!lgl->cce->clauses.start);
15688   lglrandlitrav (lgl, lglccesmallclauses);
15689   lglfitstk (lgl, &lgl->cce->clauses);
15690   count = lgl->cce->bin + lgl->cce->trn;
15691   lglprt (lgl, 1,
15692     "[cce-%d] scheduling %d clauses = %d binary + %d ternary",
15693     lgl->stats->cce.count, count, lgl->cce->bin, lgl->cce->trn);
15694   tried = eliminated = invalid = elim2 = elim3 = 0;
15695   for (c = clauses->start; c < clauses->top; c = p + 1) {
15696     if (lgl->mt) break;
15697     if (lglterminate (lgl)) break;
15698     if (lgl->limits->cce.steps <= lgl->stats->cce.steps) break;
15699     valid = 1;
15700     for (p = c; (lit = *p); p++)
15701       if (!lglisfree (lgl, lit))
15702         valid = 0;
15703     if (valid) {
15704       tried++;
15705       size = p - c;
15706       assert (2 <= size), assert (size <= 3);
15707       tag = size == 2 ? BINCS : TRNCS;
15708       if (!lglcceclause (lgl, c, tag, cce)) continue;
15709       eliminated++;
15710       if (size == 2) {
15711         lglrmvbcls (lgl, c[0], c[1]);
15712         elim2++;
15713       } else {
15714         assert (size == 3);
15715         lglrmvtcls (lgl, c[0], c[1], c[2]);
15716         elim3++;
15717       }
15718     } else invalid++;
15719   }
15720   assert (count >= tried + invalid);
15721   lglrelstk (lgl, &lgl->cce->clauses);
15722   if (tried)
15723     lglprt (lgl, 1,
15724       "[cce-%d] tried to eliminate %d small clauses %.0f%%",
15725       lgl->stats->cce.count, tried, lglpcnt (tried, count));
15726   if (eliminated)
15727     lglprt (lgl, 1,
15728       "[cce-%d] eliminated %d small clauses %.0f%%",
15729       lgl->stats->cce.count, eliminated, lglpcnt (eliminated, count));
15730   if (elim2)
15731     lglprt (lgl, 1,
15732       "[cce-%d] eliminated %d binary clauses %.0f%%",
15733       lgl->stats->cce.count, elim2, lglpcnt (elim2, lgl->cce->bin));
15734   if (elim3)
15735     lglprt (lgl, 1,
15736       "[cce-%d] eliminated %d ternary clauses %.0f%%",
15737       lgl->stats->cce.count, elim3, lglpcnt (elim3, lgl->cce->trn));
15738 }
15739
15740 static int lglcce (LGL * lgl) {
15741   int oldvars = lgl->nvars, cce, lenlim, startirr, success;
15742   int oldirr, eliminated, total, idx, round;
15743   int completedsmall, completedlarge;
15744   int64_t oldsteps, deltasteps;
15745   int elmlarge, elmsmall;
15746   lglstart (lgl, &lgl->times->cce);
15747   lgl->stats->cce.count++;
15748   lglsetccelim (lgl);
15749 #if 0
15750   if (lglprogressincelastcce (lgl)) {
15751     lglprt (lgl, 2,
15752       "[cce-%d] there was progress since last CCE so focusing on ATE first",
15753       lgl->stats->cce.count);
15754     lgl->ccertc = 0;            // TODO keep this?
15755   } else {
15756     lglprt (lgl, 2,
15757       "[cce-%d] no progress since last CCE so keeping ccertc=%s",
15758       lgl->stats->cce.count, lglcce2str (lgl->ccertc));
15759   }
15760 #endif
15761   round = total = 0;
15762   lenlim = INT_MAX;
15763   startirr = lgl->stats->irr.clauses.cur;
15764 RESTART:
15765   round++;
15766   cce = lgl->opts->cce.val;
15767   if (cce == 3 && lgl->ccertc < 2 &&
15768       lgl->opts->cce3wait.val >= lgl->stats->cce.count) {
15769     lglprt (lgl, 2,
15770       "[cce-%d-%d] restricted to ABCE since ccertc=%s",
15771       lgl->stats->cce.count, round, lglcce2str (lgl->ccertc));
15772     cce = 2;
15773   }
15774   if (cce == 2 && lgl->ccertc < 1 &&
15775       lgl->opts->cce2wait.val >= lgl->stats->cce.count) {
15776     lglprt (lgl, 2,
15777       "[cce-%d-%d] restricted to ATE since ccertc=%s",
15778       lgl->stats->cce.count, round, lglcce2str (lgl->ccertc));
15779    cce = 1;
15780   }
15781   oldirr = lgl->stats->irr.clauses.cur;
15782   lglprt (lgl, 2, "[cce-%d-%d] starting round %d (%s)",
15783           lgl->stats->cce.count, round, round, lglcce2str (cce));
15784   assert (!lgl->simp && !lgl->cceing && !lgl->occs);
15785   lgl->cceing = lgl->simp = 1;
15786   if (lgl->level > 0) lglbacktrack (lgl, 0);
15787   NEW (lgl->cce, 1);
15788   NEW (lgl->cce->rem, oldvars);
15789   for (idx = 2; idx < oldvars; idx++) lgl->cce->rem[idx] = INT_MAX;
15790   lglgc (lgl);
15791   assert (lgl->frozen);
15792   lgldense (lgl, 1);
15793   oldsteps = lgl->stats->cce.steps;
15794   elmlarge = 0;
15795   while (!lgl->mt && 
15796          lenlim > 4 &&
15797          !lglterminate (lgl) &&
15798          lgl->limits->cce.steps > lgl->stats->cce.steps) {
15799     int maxlen = 0, count;
15800     const int * p, * c;
15801     Stk lidcs;
15802     CLR (lidcs);
15803     for (c = lgl->irr.start; c < lgl->irr.top; c = p + 1) {
15804       int len, lidx;
15805       if (*(p = c) >= NOTALIT) continue;
15806       while (*p) p++;
15807       len = p - c;
15808       if (len >= lenlim) continue;
15809       if (len < maxlen) continue;
15810       if (len > maxlen) {
15811         lglclnstk (&lidcs);
15812         maxlen = len;
15813       }
15814       lidx = c - lgl->irr.start;
15815       lglpushstk (lgl, &lidcs, lidx);
15816     }
15817     ADDSTEPS (cce.steps, lglcntstk (&lgl->irr)/128);
15818     count = lglcntstk (&lidcs);
15819     lglprt (lgl, 2,
15820       "[cce-%d-%d] scheduling %d clauses of length %d",
15821       lgl->stats->cce.count, round, count, maxlen);
15822     eliminated = 0;
15823     for (p = lidcs.start;
15824          p < lidcs.top &&
15825          !lgl->mt &&
15826          !lglterminate (lgl) &&
15827          lgl->limits->cce.steps > lgl->stats->cce.steps; 
15828          p++) {
15829       int lidx = *p;
15830       c = lgl->irr.start + lidx;
15831       if (*c >= NOTALIT) continue;
15832       if (!lglcceclause (lgl, c, OCCS, cce)) continue;
15833       lglrmvlcls (lgl, lidx);
15834       eliminated++;
15835     }
15836     elmlarge += eliminated;
15837     lglrelstk (lgl, &lidcs);
15838     lenlim = maxlen;
15839     lglprt (lgl, 1 + !eliminated,
15840       "[cce-%d-%d] eliminated %d clauses out of %d (%.0f%%) of length %d",
15841       lgl->stats->cce.count, round,
15842       eliminated, count, lglpcnt (eliminated, count), maxlen);
15843   }
15844   completedlarge = (lgl->limits->cce.steps > lgl->stats->cce.steps);
15845   if (completedlarge)
15846     lglprt (lgl, 1,
15847       "[cce-%d-%d] completed large round (%s)",
15848       lgl->stats->cce.count, round, lglcce2str (cce));
15849   else
15850     lglprt (lgl, 1, 
15851       "[cce-%d-%d] incomplete large round (%s)",
15852       lgl->stats->cce.count, round, lglcce2str (cce));
15853   deltasteps = lgl->stats->cce.steps - oldsteps;
15854   lglprt (lgl, 1 + !elmlarge,
15855     "[cce-%d-%d] eliminated %d large clauses in %lld steps",
15856     lgl->stats->cce.count, round, elmlarge, (LGLL) deltasteps);
15857   deltasteps /= 2;
15858   if (LLMAX - deltasteps > lgl->limits->cce.steps) {
15859     lgl->limits->cce.steps += deltasteps;
15860     lglprt (lgl, 1,
15861       "[cce-%d-%d] allowing another %lld steps for small clauses",
15862       lgl->stats->cce.count, round, deltasteps);
15863   } else {
15864     lgl->limits->cce.steps = LLMAX;
15865     lglprt (lgl, 1,
15866       "[cce-%d-%d] unlimited number of steps for small clauses",
15867       lgl->stats->cce.count, round);
15868   }
15869   lglccesmall (lgl, cce);
15870   elmsmall = oldirr - lgl->stats->irr.clauses.cur - elmlarge;
15871   lglprt (lgl, 1 + !elmsmall,
15872     "[cce-%d-%d] eliminated %d small clauses in %lld steps",
15873     lgl->stats->cce.count, round, elmsmall,
15874     (LGLL) lgl->stats->cce.steps - oldsteps - deltasteps);
15875   completedsmall = (lgl->limits->cce.steps > lgl->stats->cce.steps);
15876   COVER (!completedsmall && lgl->opts->ccertc.val);
15877   if (completedsmall)
15878     lglprt (lgl, 1,
15879       "[cce-%d-%d] completed small round (%s)",
15880       lgl->stats->cce.count, round, lglcce2str (cce));
15881   else
15882     lglprt (lgl, 1, 
15883       "[cce-%d-%d] incomplete small round (%s)",
15884       lgl->stats->cce.count, round, lglcce2str (cce));
15885   if (completedsmall && completedlarge) {
15886     if (lgl->ccertc < cce) {
15887       lgl->ccertc = cce;
15888       lglprt (lgl, 1, 
15889         "[cce-%d-%d] completed small and large (%s)",
15890         lgl->stats->cce.count, round, lglcce2str (cce));
15891     }
15892   }
15893   lglsparse (lgl);
15894   lglgc (lgl);
15895   lglrelstk (lgl, &lgl->cce->extend);
15896   lglrelstk (lgl, &lgl->cce->cla);
15897   DEL (lgl->cce->rem, oldvars);
15898   DEL (lgl->cce, 1);
15899   assert (oldirr >= lgl->stats->irr.clauses.cur);
15900   eliminated = oldirr - lgl->stats->irr.clauses.cur;
15901   total += eliminated;
15902   lglprt (lgl, 1,
15903     "[cce-%d-%d] eliminated %d covered clauses in round %d",
15904     lgl->stats->cce.count, round, eliminated, round);
15905   assert (lgl->simp && lgl->cceing);
15906   lgl->cceing = lgl->simp = 0;
15907   if (!lgl->mt &&
15908       eliminated &&
15909       !lglterminate (lgl) &&
15910       lgl->limits->cce.steps > lgl->stats->cce.steps) goto RESTART;
15911   lglprt (lgl, 1,
15912     "[cce-%d] eliminated %d covered clauses in TOTAL during %d rounds",
15913     lgl->stats->cce.count, total, round);
15914   if (startirr < lgl->opts->ccesuccesslim.val) success = total;
15915   else if (total) {
15916     success = (startirr/lgl->opts->ccesuccessrat.val <= total);
15917     if (!success)
15918       lglprt (lgl, 1,
15919         "[cce-%d] %d < 1/%d * %d = %d considered unsuccessful",
15920         lgl->stats->cce.count, total, lgl->opts->ccesuccessrat.val,
15921         startirr, startirr/lgl->opts->ccesuccessrat.val);
15922   } else success = 0;
15923   LGLUPDPEN (cce, success);
15924   lglrep (lgl, 2, 'E');
15925   lglstop (lgl);
15926   lglbasicatestats (lgl);
15927   return !lgl->mt;
15928 }
15929
15930 static void lglcliffclause (LGL * lgl, const int * c) {
15931   int lit, start, i, first, dom, other, * r;
15932   const int * p, * q;
15933   for (p = c; (lit = *p);  p++) if (lglval (lgl, lit) > 0) return;
15934   LOGCLS (2, c, "cliffing clause");
15935   assert (lgl->cliff);
15936   assert (lglmtstk (&lgl->cliff->lift));
15937   assert (!lgl->level);
15938   assert (!lgl->mt);
15939   start = lglcntstk (&lgl->trail);
15940   first = 1;
15941   for (p = c; (lit = *p); p++) {
15942     if (lglval (lgl, lit) < 0) continue;
15943     lgl->stats->cliff.decisions++;
15944     lgliassume (lgl, lit);
15945     if (!lglbcp (lgl)) {
15946       LOG (1, "cliffing failed literal %d", lit);
15947       dom = lglprbana (lgl, lit);
15948       lglbacktrack (lgl, 0);
15949       lgl->stats->cliff.failed++;
15950       lglunit (lgl, -dom);
15951       if (!lglbcp (lgl)) {
15952         LOG (1, "empty clause after propagating %d", -dom);
15953         lgl->mt = 1;
15954       }
15955       goto DONE;
15956     } 
15957     if (first) {
15958       for (i = start; i < lglcntstk (&lgl->trail); i++) {
15959         other = lglpeek (&lgl->trail, i);
15960         lglpushstk (lgl, &lgl->cliff->lift, other);
15961       }
15962       first = 0;
15963     } else {
15964       r = lgl->cliff->lift.start;
15965       for (q = r; q < lgl->cliff->lift.top; q++)
15966         if (lglval (lgl, (other = *q)) > 0)
15967           *r++ = other;
15968       lgl->cliff->lift.top = r;
15969     }
15970     lglbacktrack (lgl, 0);
15971     if (lglmtstk (&lgl->cliff->lift)) return;
15972   }
15973   while (!lglmtstk (&lgl->cliff->lift)) {
15974     lit = lglpopstk (&lgl->cliff->lift);
15975     LOG (1, "cliffing lifted unit %d", lit);
15976     lgl->stats->cliff.lifted++;
15977     if (lglval (lgl, lit) > 0) continue;
15978     if (lglval (lgl, lit) < 0) {
15979       LOG (1, "inconsistent lifted unit %d", lit);
15980       lgl->mt = 1;
15981       goto DONE;
15982     }
15983     lglunit (lgl, lit);
15984     if (!lglbcp (lgl)) {
15985       LOG (1, "empty clause after propagating lifted unit %d", lit);
15986       lgl->mt = 1;
15987       goto DONE;
15988     }
15989   }
15990 DONE:
15991   lglclnstk (&lgl->cliff->lift);
15992 }
15993
15994 static int lglcliffclauses (LGL * lgl, Stk * stk) {
15995   const int * c, * p;
15996   for (c = stk->start; c < stk->top; c = p + 1) {
15997     if (*(p = c) >= NOTALIT) continue;
15998     if (INCSTEPS (cliff.steps) >= lgl->limits->cliff.steps) return 0;
15999     if (lglterminate (lgl)) return 0;
16000     lglcliffclause (lgl, c);
16001     if (lgl->mt) return 0;
16002     for (p = c; *p; p++)
16003       ;
16004   }
16005   return 1;
16006 }
16007
16008 static int lglclifflitrn (LGL * lgl, int lit) {
16009   const int * w, * eow, * p;
16010   int res, blit, tag, other, other2;
16011   HTS * hts;
16012   assert (lglmtstk (&lgl->cliff->lits));
16013   if (!lglisfree (lgl, lit)) return 1;
16014   if (INCSTEPS (cliff.steps) >= lgl->limits->cliff.steps) return 0;
16015   hts = lglhts (lgl, lit);
16016   w = lglhts2wchs (lgl, hts);
16017   eow = w + hts->count;
16018   for (p = w; p < eow; p++) {
16019     blit = *p;
16020     tag = blit & MASKCS;
16021     if (tag == TRNCS || tag == LRGCS) p++;
16022     if (tag == BINCS) continue;
16023     if (tag == LRGCS) continue;
16024     assert (tag == TRNCS);
16025     other = blit >> RMSHFT;
16026     if (abs (other) < abs (lit)) continue;
16027     other2 = *p;
16028     if (abs (other2) < abs (lit)) continue;
16029     lglpushstk (lgl, &lgl->cliff->lits, lit);
16030     lglpushstk (lgl, &lgl->cliff->lits, other);
16031     lglpushstk (lgl, &lgl->cliff->lits, other2);
16032     lglpushstk (lgl, &lgl->cliff->lits, 0);
16033   }
16034   res = lglcliffclauses (lgl, &lgl->cliff->lits);
16035   lglclnstk (&lgl->cliff->lits);
16036   return res && !lgl->mt;
16037 }
16038
16039 static int lglcliffred (LGL * lgl) {
16040   int glue;
16041   for (glue = 0; glue < MAXGLUE; glue++)
16042     if (!lglcliffclauses (lgl, &lgl->red[glue]))
16043       return 0;
16044   return 1;
16045 }
16046
16047 static void lglsetclifflim (LGL * lgl) {
16048   int64_t limit, irrlim;
16049   int pen;
16050   limit = (lgl->opts->cliffreleff.val*lglvisearch (lgl))/1000;
16051   if (limit < lgl->opts->cliffmineff.val) limit = lgl->opts->cliffmineff.val;
16052   if (lgl->opts->cliffmaxeff.val >= 0 && limit > lgl->opts->cliffmaxeff.val)
16053     limit = lgl->opts->cliffmaxeff.val;
16054   limit >>= (pen = lgl->limits->cliff.pen + lglszpen (lgl));
16055   irrlim = 2*lgl->stats->irr.clauses.cur;
16056   irrlim >>= lgl->limits->simp.pen;
16057   if (lgl->opts->irrlim.val && limit < irrlim) {
16058     limit = irrlim;
16059     lglprt (lgl, 1,
16060       "[cliff-%d] limit of %lld steps based on %d irredundant clauses",
16061       lgl->stats->cliff.count, (LGLL) limit, lgl->stats->irr.clauses.cur);
16062   } else
16063     lglprt (lgl, 1, "[cliff-%d] limit of %lld steps penalty %d = %d + %d",
16064             lgl->stats->cliff.count, (LGLL) limit,
16065             pen, lgl->limits->cliff.pen, lglszpen (lgl));
16066   lgl->limits->cliff.steps = lgl->stats->cliff.steps + limit;
16067 }
16068
16069 static int lglcliff (LGL * lgl) {
16070   int lifted, failed, oldlifted, oldfailed, success;
16071   lglstart (lgl, &lgl->times->cliff);
16072   lgl->stats->cliff.count++;
16073   assert (!lgl->simp && !lgl->cliffing);
16074   lgl->simp = lgl->cliffing = 1;
16075   assert (!lgl->cliff);
16076   NEW (lgl->cliff, 1);
16077   if (lgl->level > 0) lglbacktrack (lgl, 0);
16078   oldlifted = lgl->stats->cliff.lifted;
16079   oldfailed = lgl->stats->cliff.failed;
16080   lglsetclifflim (lgl);
16081   if (lglcliffclauses (lgl, &lgl->irr))
16082     if (lglrandlitrav (lgl, lglclifflitrn))
16083       (void) lglcliffred (lgl);
16084   lifted = lgl->stats->cliff.lifted - oldlifted;
16085   failed = lgl->stats->cliff.failed - oldfailed;
16086   lglprt (lgl, 1, "[cliff-%d] failed %d, lifted %d",
16087           lgl->stats->cliff.count, failed, lifted);
16088   assert (lgl->simp && lgl->cliffing);
16089   lgl->simp = lgl->cliffing = 0;
16090   lglrelstk (lgl, &lgl->cliff->lift);
16091   lglrelstk (lgl, &lgl->cliff->lits);
16092   DEL (lgl->cliff, 1);
16093   success = failed || lifted;
16094   LGLUPDPEN (cliff, success);
16095   lglrep (lgl, 2, 'K');
16096   lglstop (lgl);
16097   return !lgl->mt;
16098 }
16099
16100 static void lglsetelmlim (LGL * lgl) {
16101   int64_t limit, irrlim;
16102   int pen;
16103   if (lgl->opts->elmrtc.val) {
16104     lgl->limits->elm.steps = LLMAX;
16105     lglprt (lgl, 1, "[elim-%d] no limit", lgl->stats->elm.count);
16106   } else {
16107     limit = (lgl->opts->elmreleff.val*lglvisearch (lgl))/1000;
16108     if (limit < lgl->opts->elmineff.val) limit = lgl->opts->elmineff.val;
16109     if (lgl->opts->elmaxeff.val >= 0 && limit > lgl->opts->elmaxeff.val)
16110       limit = lgl->opts->elmaxeff.val;
16111     if (lgl->stats->elm.count <= 1 &&
16112         lgl->opts->boost.val &&
16113         lgl->opts->elmboost.val > 1) {
16114       lglprt (lgl, 1,
16115         "[elim-%d] boosting limit by %d",
16116         lgl->stats->elm.count, lgl->opts->elmboost.val);
16117       limit *= lgl->opts->elmboost.val;
16118     }
16119     limit >>= (pen = lgl->limits->elm.pen + lglszpen (lgl));
16120     irrlim = lgl->stats->irr.clauses.cur;
16121     irrlim >>= lgl->limits->simp.pen;
16122     if (lgl->opts->irrlim.val && limit < irrlim) {
16123       limit = irrlim;
16124       lglprt (lgl, 1,
16125         "[elim-%d] limit of %lld steps based on %d irredundant clauses",
16126         lgl->stats->elm.count, (LGLL) limit, lgl->stats->irr.clauses.cur);
16127     } else
16128       lglprt (lgl, 1,
16129         "[elim-%d] limit of %lld steps penalty %d = %d + %d",
16130         lgl->stats->elm.count, (LGLL) limit,
16131         pen, lgl->limits->elm.pen, lglszpen (lgl));
16132     lgl->limits->elm.steps = lgl->stats->elm.steps + limit;
16133   }
16134 }
16135
16136 static int lglforceschedall (LGL * lgl) {
16137   int idx, res = 0;
16138   AVar * av;
16139   assert (lgl->eliminating);
16140   assert (lglmtstk (&lgl->esched));
16141   lgl->donotsched = 0;
16142   for (idx = 2; idx < lgl->nvars; idx++) {
16143     if (lglifrozen (lgl, idx)) continue;
16144     if (!lglisfree (lgl, idx)) continue;
16145     av = lglavar (lgl, idx);
16146     av->donotelm = 0;
16147     lglesched (lgl, idx);
16148     res++;
16149   }
16150   lglprt (lgl, 1,
16151     "[elim-%d-%d] fully rescheduled %d variables %.0f%%",
16152     lgl->stats->elm.count, lgl->elm->round,
16153     res, lglpcnt (res, lgl->nvars - 2));
16154   return res;
16155 }
16156
16157 static void lgladdstrbincls (LGL * lgl, int a, int b) {
16158   assert (lglisfree (lgl, a));
16159   assert (lglisfree (lgl, b));
16160   assert (lglmtstk (&lgl->clause));
16161   lglpushstk (lgl, &lgl->clause, a);
16162   lglpushstk (lgl, &lgl->clause, b);
16163   lglpushstk (lgl, &lgl->clause, 0);
16164   LOG (BWL, "strengthened binary clause", a, b);
16165   if (lgl->opts->drup.val) lgldrupcls (lgl);
16166 #ifndef NLGLPICOSAT
16167   lglpicosatchkcls (lgl);
16168 #endif
16169   lgldrupligaddcls (lgl, REDCS);
16170   lgladdcls (lgl, 0, 0, 1);
16171   lglclnstk (&lgl->clause);
16172 }
16173
16174 static int lglbackwardlit (LGL * lgl,
16175                            const int * clause, const int * skip,
16176                            int size, int minlit,
16177                            int *subptr, int *strptr) {
16178   int res, blit, tag, red, other, other2, lidx, count, remove, hit;
16179   const int * p, * w, * eow, * c, * l;
16180   int marked, marked2, val;
16181   HTS * hts;
16182   assert (!lgl->level);
16183   lgl->stats->bkwd.tried.lits++;
16184   LOGCLS (BWL, clause,
16185     "backward subsume and strengthen clauses with %d by size %d clause",
16186     minlit, size);
16187   hit = res = 0;
16188   hts = lglhts (lgl, minlit);
16189   w = lglhts2wchs (lgl, hts);
16190   eow = w + hts->count;
16191   for (p = w; !res && p < eow; p++) {
16192     blit = *p;
16193     tag = blit & MASKCS;
16194     if (tag == TRNCS || tag == LRGCS) p++;
16195     if (tag == LRGCS) continue;
16196     if (p == skip) continue;
16197     red = blit & REDCS;
16198     if (red) continue;
16199     lgl->stats->bkwd.tried.occs++;
16200     INCSTEPS (elm.steps);
16201     if (tag == BINCS) {
16202       if (size > 2) continue;
16203       other = blit >> RMSHFT;
16204       if (!lglisfree (lgl, other)) continue;
16205       marked = lglmarked (lgl, other);
16206       if (marked > 0) {
16207         if (size == 2 && !hit++) continue;
16208         LOG (BWL, "subsumed binary clause %d %d", minlit, other);
16209         assert (!(w <= skip && skip < eow) || skip < p);
16210         ADDSTEPS (elm.steps, 2);
16211         lglrmbcls (lgl, minlit, other, 0);
16212         lgl->stats->bkwd.sub2++;
16213         *subptr += 1;
16214         res = 1;
16215       } else if (marked < 0) {
16216         LOG (BWL,
16217           "removing %d and thus strengthening binary clause %d %d",
16218           other, minlit, other);
16219         assert (p != skip);
16220         ADDSTEPS (elm.steps, 2);
16221         lglunit (lgl, minlit);
16222         lgl->stats->bkwd.str2++;
16223         *strptr += 1;
16224         res = 1;
16225       }
16226     } else if (tag == TRNCS) {
16227       if (size > 3) continue;
16228       other = blit >> RMSHFT;
16229       other2 = *p;
16230       if (!lglisfree (lgl, other)) continue;
16231       if (!lglisfree (lgl, other2)) continue;
16232       marked = lglmarked (lgl, other);
16233       marked2 = lglmarked (lgl, other2);
16234       if ((size == 2 && (marked > 0 || marked2 > 0)) ||
16235           (size == 3 && marked > 0 && marked2 > 0)) {
16236         if (size == 3 && !hit++) continue;
16237         assert (!(w <= skip && skip < eow) || skip < p);
16238         LOG (BWL,
16239           "subsumed ternary clause %d %d %d",
16240           minlit, other, other2);
16241         ADDSTEPS (elm.steps, 3);
16242         lglrmtcls (lgl, minlit, other, other2, 0);
16243         lgl->stats->bkwd.sub3++;
16244         *subptr += 1;
16245         res = 1;
16246       } else {
16247         if (marked < 0 && marked2 > 0) {
16248           int tmp = other; other = other2; other2 = tmp;
16249         } else if (marked <= 0 || marked2 >= 0) continue;
16250         LOG (BWL,
16251           "removing %d and thus strengthening ternary clause %d %d %d",
16252           other2, minlit, other, other2);
16253         assert (lglmarked (lgl, other) > 0);
16254         assert (lglmarked (lgl, other2) < 0);
16255         lgladdstrbincls (lgl, minlit, other);
16256         lglrmtcls (lgl, minlit, other, other2, 0);
16257         if (size == 3) {
16258           LOG (BWL,
16259             "removing %d and thus strengthening ternary clause %d %d %d",
16260             other2, minlit, other, -other2);
16261           lglrmtcls (lgl, minlit, other, -other2, 0);
16262           lgl->stats->bkwd.str3self++;
16263         }
16264         ADDSTEPS (elm.steps, 3);
16265         lgl->stats->bkwd.str3++;
16266         *strptr += 1;
16267         res = 1;
16268       }
16269     } else {
16270       assert (tag == OCCS);
16271       lidx = blit >> RMSHFT;
16272       c = lglidx2lits (lgl, 0, lidx);
16273       if (c == skip) continue;
16274       INCSTEPS (elm.steps);
16275       count = size;
16276       remove = 0;
16277       for (l = c; (other = *l); l++) {
16278         val = lglval (lgl, other);
16279         if (val > 0) { remove = INT_MAX; break; }
16280         if (val < 0) continue;
16281         assert (!val);
16282         marked = lglmarked (lgl, other);
16283         if (!marked) continue;
16284         count--;
16285         if (marked > 0) continue;
16286         if (remove) { remove = INT_MAX; break; }
16287         remove = other;
16288       }
16289       if (count > 0) continue;
16290       if (remove == INT_MAX) continue;
16291       if (!remove) {
16292         assert (!(w <= skip && skip < eow) || skip < p);
16293         LOGCLS (BWL, c, "subsumed large clause");
16294         ADDSTEPS (elm.steps, (l - c));
16295         lglrmlcls (lgl, lidx, 0);
16296         lgl->stats->bkwd.subl++;
16297         *subptr += 1;
16298         res = 1;
16299       } else if (lglsmallirr (lgl)) {
16300         LOGCLS (BWL, c, "removing %d and thus strengthening clause", remove);
16301         assert (lglmtstk (&lgl->clause));
16302         for (l = c; (other = *l); l++) {
16303           if (other == remove) continue;
16304           val = lglval (lgl, other);
16305           if (val < 0) continue;
16306           assert (!val);
16307           lglpushstk (lgl, &lgl->clause, other);
16308         }
16309         lglpushstk (lgl, &lgl->clause, 0);
16310         LOGCLS (BWL, lgl->clause.start, "strengthened clause");
16311         if (lgl->opts->drup.val) lgldrupcls (lgl);
16312 #ifndef NLGLPICOSAT
16313         lglpicosatchkcls (lgl);
16314 #endif
16315         ADDSTEPS (elm.steps, (l - c));
16316         lglrmlcls (lgl, lidx, 0);
16317         if (l - c == size) lgl->stats->bkwd.strlself++;
16318         lgldrupligaddcls (lgl, REDCS);
16319         lgladdcls (lgl, 0, 0, 1);
16320         lglclnstk (&lgl->clause);
16321         lgl->stats->bkwd.strl++;
16322         *strptr += 1;
16323         res = 1;
16324       }
16325     }
16326   }
16327   return res;
16328 }
16329
16330 static int lglbackwardclause (LGL * lgl,
16331                               const int * clause, const int * skip,
16332                               int * subsumedptr, int * strengthenedptr) {
16333   int lit, size, minlit, minlit2, minocc, minocc2, tmpocc, res, large;
16334   const int * p;
16335   long delta;
16336   lgl->stats->bkwd.tried.clauses++;
16337   INCSTEPS (elm.steps);
16338   minocc = minlit = minocc2 = minlit2 = 0;
16339   for (p = clause; (lit = *p); p++) {
16340     lglmarkunmarked (lgl, lit);
16341     tmpocc = lglocc (lgl, lit);
16342     if (!minlit || tmpocc < minocc) {
16343       minocc2 = minocc, minlit2 = minlit;
16344       minocc = tmpocc, minlit = lit;
16345     } else if (!minlit2 || tmpocc < minocc2) {
16346       minocc2 = tmpocc, minlit2 = lit;
16347     }
16348   }
16349   size = p - clause;
16350   assert (size >= 2);
16351   LOG (BWL, "minimum occurrence %d of literal %d", minocc, minlit);
16352   LOG (BWL, "next minimum occurrence %d of literal %d", minocc2, minlit2);
16353   large = (lgl->irr.start <= clause && clause < lgl->irr.top);
16354   delta = large ? clause - lgl->irr.start : 0;
16355   res = lglbackwardlit (lgl, clause, skip,
16356                         size, minlit, subsumedptr, strengthenedptr);
16357   if (!res) {
16358     res = lglbackwardlit (lgl, clause, skip,
16359                           size, minlit2, subsumedptr, strengthenedptr);
16360   }
16361   if (res && large) clause = lgl->irr.start + delta;
16362   for (p = clause; (lit = *p); p++)
16363     lglunmark (lgl, lit);
16364   return res;
16365 }
16366
16367 static void lglbackward (LGL * lgl, int * u, int * t, int64_t steps) {
16368   int idx, sign, lit, blit, red, tag, other, other2, clause[4], * w;
16369   int64_t limit, delta, scaled;
16370   const int * p, * eow, * c;
16371   HTS * hts;
16372   Stk stk;
16373   long i;
16374   lglstart (lgl, &lgl->times->bkwd);
16375   CLR (stk);
16376   *u = *t = 0;
16377   if (LLMAX/lgl->opts->bkwdscale.val <= steps) scaled = LLMAX;
16378   else scaled = steps * lgl->opts->bkwdscale.val;
16379   if (lgl->limits->elm.steps - scaled <= lgl->stats->elm.steps)
16380     limit = lgl->limits->elm.steps;
16381   else limit = lgl->stats->elm.steps + scaled;
16382   delta = limit - lgl->stats->elm.steps;
16383   lglprt (lgl, 1,
16384     "[elim-%d-%d] backward subsumption/strengthening limit %lld",
16385     lgl->stats->elm.count, lgl->elm->round, delta);
16386   for (idx = 2; idx < lgl->nvars; idx++) {
16387     for (sign = -1; sign <= 1; sign += 2) {
16388 RESTART:
16389       if (lgl->mt) goto DONE;
16390       if (lglterminate (lgl)) goto DONE;
16391
16392       // TODO DID NOT WORK?  REMOVE OR FIX?
16393       // if (!lglsyncunits (lgl)) goto DONE;
16394
16395       if (!lglisfree (lgl, idx)) continue;
16396       if (INCSTEPS (elm.steps) >= limit) goto DONE;
16397       lit = sign * idx;
16398       hts = lglhts (lgl, lit);
16399       w = lglhts2wchs (lgl, hts);
16400       eow = w + hts->count;
16401       lglclnstk (&stk);
16402       for (p = w; p < eow; p++) {
16403         blit = *p;
16404         tag = blit & MASKCS;
16405         if (tag == TRNCS || tag == LRGCS) p++;
16406         if (tag != BINCS) continue;
16407         red = blit & REDCS;
16408         if (red) continue;
16409         lglpushstk (lgl, &stk, blit);
16410       }
16411       for (p = w; p < eow; p++) {
16412         blit = *p;
16413         tag = blit & MASKCS;
16414         if (tag == TRNCS || tag == LRGCS) p++;
16415         if (tag != TRNCS) continue;
16416         red = blit & REDCS;
16417         if (red) continue;
16418         lglpushstk (lgl, &stk, blit);
16419         lglpushstk (lgl, &stk, *p);
16420       }
16421       for (p = w; p < eow; p++) {
16422         blit = *p;
16423         tag = blit & MASKCS;
16424         if (tag == TRNCS || tag == LRGCS) p++;
16425         red = blit & REDCS;
16426         if (!red && (tag == BINCS || tag == TRNCS)) continue;
16427         lglpushstk (lgl, &stk, blit);
16428         if (tag == TRNCS || tag == LRGCS)
16429           lglpushstk (lgl, &stk, *p);
16430       }
16431       assert (lglcntstk (&stk) == hts->count);
16432       memcpy (w, stk.start, lglcntstk (&stk) * sizeof *w);
16433       clause[0] = lit;
16434       for (p = w; p < eow; p++) {
16435         blit = *p;
16436         tag = blit & MASKCS;
16437         if (tag == TRNCS || tag == LRGCS) p++;
16438         if (tag == LRGCS) continue;
16439         red = blit & REDCS;
16440         if (red) continue;
16441         if (INCSTEPS (elm.steps) >= limit) goto DONE;
16442         if (tag == BINCS) {
16443           other = blit >> RMSHFT;
16444           if (abs (other) < idx) continue;
16445           clause[1] = other, clause[2] = 0;
16446           if (!lglbackwardclause (lgl, clause, p, u, t)) continue;
16447         } else if (tag == TRNCS) {
16448           other = blit >> RMSHFT;
16449           if (abs (other) < idx) continue;
16450           other2 = *p;
16451           if (abs (other2) < idx) continue;
16452           clause[1] = other, clause[2] = other2, clause[3] = 0;
16453           if (!lglbackwardclause (lgl, clause, p, u, t)) continue;
16454         } else { assert (tag == OCCS); continue; }
16455         if (lglflush (lgl)) goto RESTART;
16456         else goto DONE;
16457       }
16458     }
16459   }
16460   for (c = lgl->irr.start; c < lgl->irr.top; c = p + 1) {
16461     if (!lglsmallirr (lgl)) goto DONE;
16462     if (INCSTEPS (elm.steps) >= limit) goto DONE;
16463     if (*(p = c) >= NOTALIT) continue;
16464     while (*p) p++;
16465     i = p - lgl->irr.start;
16466     if (lglbackwardclause (lgl, c, c, u, t)) p = lgl->irr.start + i;
16467   }
16468 DONE:
16469   lglrelstk (lgl, &stk);
16470   lglstop (lgl);
16471 }
16472
16473 static int lglelmdone (LGL * lgl, int * allptr) {
16474   int newelmd, eliminated, subsumed, strengthened;
16475   int64_t steps, oldsteps;
16476   if (!lglsmallirr (lgl)) return 1;
16477   if (lglterminate (lgl)) return 1;
16478   if (lgl->limits->elm.steps <= lgl->stats->elm.steps) return 1;
16479   if (!lglmtstk (&lgl->esched)) return 0;
16480   steps = ((oldsteps = lgl->stats->elm.steps) - lgl->elm->oldsteps);
16481   eliminated = (newelmd = lgl->stats->elm.elmd) - lgl->elm->oldelmd;
16482   assert (eliminated >= 0);
16483   if (eliminated <= 0) {
16484     lglprt (lgl, 1,
16485       "[elim-%d-%d] no variable eliminated in round %d in %lld steps",
16486       lgl->stats->elm.count, lgl->elm->round,
16487       lgl->elm->round, (LGLL) steps);
16488     return 1;
16489   }
16490   lglprt (lgl, 1,
16491     "[elim-%d-%d] eliminated %d variables %.0f%% in round %d in %lld steps",
16492     lgl->stats->elm.count, lgl->elm->round, eliminated, 
16493     lglpcnt (eliminated, lgl->nvars - 2), lgl->elm->round, (LGLL) steps);
16494   lglbackward (lgl, &subsumed, &strengthened, steps);
16495   steps = lgl->stats->elm.steps - oldsteps;
16496   lglprt (lgl, 1,
16497     "[elim-%d-%d] subsumed %d and strengthened %d clauses in %lld steps",
16498     lgl->stats->elm.count, lgl->elm->round, subsumed, strengthened,
16499     (LGLL) steps);
16500   lgl->stats->elm.rounds++;
16501   lgl->elm->oldelmd = newelmd;
16502   lgl->elm->oldsteps = lgl->stats->elm.steps;
16503   if (lgl->mt) return 1;
16504   if (lgl->limits->elm.steps <= lgl->stats->elm.steps) return 1;
16505   if (lgl->elm->round >= lgl->opts->elmroundlim.val) return 1;
16506   if (!lglmtstk (&lgl->esched)) {
16507     lglprt (lgl, 1,
16508       "[elim-%d-%d] rescheduled %d variables %.0f%% by backward subsumption",
16509       lgl->stats->elm.count, lgl->elm->round,
16510       lglcntstk (&lgl->esched),
16511       lglpcnt (lglcntstk (&lgl->esched), lglrem (lgl)));
16512     lgl->elm->round++;
16513     return 0;
16514   }
16515   if (*allptr) return 1;
16516   *allptr = 1;
16517   if (!lglforceschedall (lgl)) return 1;
16518   lgl->elm->round++;
16519   return 0;
16520 }
16521
16522 static int lglelim (LGL * lgl) {
16523   int res = 1, idx, elmd, oldnvars, success, all, rem;
16524   int oldrem = lgl->elmrem, oldall = lgl->elmall;
16525   assert (lgl->opts->elim.val);
16526   assert (!lgl->mt);
16527   assert (lgl->nvars > 2);
16528   assert (!lgl->eliminating);
16529   assert (!lgl->simp);
16530   assert (!lgl->occs);
16531   lglstart (lgl, &lgl->times->elm);
16532   lgl->stats->elm.count++;
16533   lgl->eliminating = lgl->simp = lgl->occs = 1;
16534   NEW (lgl->elm, 1);
16535   lgl->elm->oldelmd = lgl->stats->elm.elmd;
16536   lgl->elm->round = 1;
16537   lgl->elm->oldsteps = lgl->stats->elm.steps;
16538   lgl->stats->elm.rounds++;
16539   if (lgl->level > 0) lglbacktrack (lgl, 0);
16540   oldnvars = lglrem (lgl);
16541   lglgc (lgl);
16542   assert (lgl->frozen);
16543   assert (!(oldall && !oldrem));
16544   all = !oldrem || !oldall;
16545   if (all)
16546     lglprt (lgl, 1,
16547       "[elim-%d] scheduling all variables this time",
16548        lgl->stats->elm.count);
16549   else if (!lgleschedrem (lgl, 1)) all = 1, oldrem = 0;
16550   if (!all) assert (!lgl->donotsched), lgl->donotsched = 1;
16551   lgldense (lgl, 1);
16552   if (!all) assert (lgl->donotsched), lgl->donotsched = 0;
16553   lglsetelmlim (lgl);
16554   while (res && !lglelmdone (lgl, &all)) {
16555     idx = lglpopesched (lgl);
16556     lglavar (lgl, idx)->donotelm = 1;
16557     lglelimlit (lgl, idx);
16558     res = lglflush (lgl);
16559     assert (res || lgl->mt);
16560   }
16561   rem = lglcntstk (&lgl->esched);
16562   if (!rem) {
16563     lglprt (lgl, 1,
16564       "[elim-%d] fully completed in %d rounds",
16565       lgl->stats->elm.count, lgl->elm->round);
16566     lgl->elmrtc = 1;
16567   } else {
16568     lglprt (lgl, 1,
16569       "[elim-%d] incomplete %d not tried %.0f%% in round %d",
16570       lgl->stats->elm.count,
16571       rem, lglpcnt (rem, lgl->nvars - 2),
16572       lgl->elm->round);
16573   }
16574   lglsetdonotesched (lgl, !rem);
16575   lglrelstk (lgl, &lgl->esched);
16576   lglrelecls (lgl);
16577   lglsparse (lgl);
16578   lglgc (lgl);
16579   DEL (lgl->elm, 1);
16580   lgl->elmrem = rem > 0;
16581   lgl->elmall = all && lgl->elmrem;
16582   lglprt (lgl, 1,
16583     "[elim-%d] transition to [ all %d rem %d ] state",
16584     lgl->stats->elm.count, lgl->elmall, lgl->elmrem);
16585   elmd = oldnvars - lglrem (lgl);
16586   lgl->stats->irrprgss += elmd;
16587   lglprt (lgl, 1,
16588     "[elim-%d] eliminated %d = %.0f%% variables out of %d",
16589     lgl->stats->elm.count, elmd, lglpcnt (elmd, oldnvars), oldnvars);
16590   if (oldnvars < lgl->opts->elmsuccesslim.val) success = elmd;
16591   else if (elmd) {
16592     success = (oldnvars/lgl->opts->elmsuccessrat.val <= elmd);
16593     if (!success)
16594       lglprt (lgl, 1,
16595         "[elim-%d] %d < 1/%d * %d = %d considered unsuccessful",
16596         lgl->stats->elm.count, elmd, lgl->opts->elmsuccessrat.val,
16597         oldnvars, oldnvars/lgl->opts->elmsuccessrat.val);
16598   } else success = 0;
16599   LGLUPDPEN (elm, success);
16600   lgl->elmstuck = !rem && !success;
16601   if (lgl->elmstuck)
16602     lglprt (lgl, 2,
16603       "[elim-%d] completed but nothing eliminated thus stuck",
16604       lgl->stats->elm.count);
16605   lglrep (lgl, 2, 'e');
16606   assert (lgl->eliminating && lgl->simp && lgl->occs);
16607   lgl->eliminating = lgl->simp = lgl->occs = 0;
16608   lglstop (lgl);
16609   return !lgl->mt;
16610 }
16611
16612 static int lglsynceqs (LGL * lgl) {
16613   int * ereprs, emax = lgl->maxext;
16614   int elit1, erepr1, elit2, erepr2;
16615   int ilit1, irepr1, ilit2, irepr2;
16616   int consumed = 0, produced = 0;
16617   assert (!lgl->mt);
16618   assert (!lgl->level);
16619   if (!lgl->nvars) return 1;
16620   if (!lgl->cbs) return 1;
16621   if (!lgl->cbs->eqs.lock.fun) return 1;
16622   assert (lgl->repr);
16623   ereprs = lgl->cbs->eqs.lock.fun (lgl->cbs->eqs.lock.state);
16624   produced = consumed = 0;
16625   for (elit1 = 1; elit1 <= emax; elit1++) {
16626     if (lglelitblockingoreliminated (lgl, elit1)) continue;
16627     elit2 = lglptrjmp (ereprs, emax, elit1);
16628     if (elit2 == elit1) continue;
16629     if (lglelitblockingoreliminated (lgl, elit2)) continue;
16630     assert (elit2 != -elit1);
16631     erepr1 = lglerepr (lgl, elit1);
16632     if (lglelitblockingoreliminated (lgl, erepr1)) continue;
16633     erepr2 = lglerepr (lgl, elit2);
16634     if (lglelitblockingoreliminated (lgl, erepr2)) continue;
16635     if (erepr1 == erepr2) continue;
16636     if (erepr1 == -erepr2) {
16637 INCONSISTENT:
16638       LOG (1, "inconsistent external equivalence %d %d", elit1, elit2);
16639       assert (!lgl->level);
16640       lgl->mt = 1;
16641       goto DONE;
16642     }
16643     ilit1 = lglimport (lgl, elit1);
16644     ilit2 = lglimport (lgl, elit2);
16645     if (ilit1 == ilit2) continue;
16646     if (ilit1 == -ilit2) goto INCONSISTENT;
16647     if (abs (ilit1) <= 1) continue;
16648     if (abs (ilit2) <= 1) continue;
16649     irepr1 = lglirepr (lgl, ilit1);
16650     irepr2 = lglirepr (lgl, ilit2);
16651     if (irepr1 == irepr2) continue;
16652     if (irepr1 == -irepr2) goto INCONSISTENT;
16653     if (abs (irepr1) <= 1) continue;
16654     if (abs (irepr2) <= 1) continue;
16655     LOG (2, "importing external equivalence %d %d as internal %d %d",
16656          elit1, elit2, irepr1, irepr2);
16657     if (!lglisfree (lgl, irepr1)) continue;
16658     if (!lglisfree (lgl, irepr2)) continue;
16659     consumed++;
16660     lglimerge (lgl, irepr1, irepr2);
16661   }
16662   LOG (1, "consumed %d equivalences", consumed);
16663   for (elit1 = 1; elit1 <= emax; elit1++) {
16664     elit2 = lglerepr (lgl, elit1);
16665     if (elit1 == elit2) continue;
16666     assert (elit1 != -elit2);
16667     erepr1 = lglptrjmp (ereprs, emax, elit1);
16668     erepr2 = lglptrjmp (ereprs, emax, elit2);
16669     if (erepr1 == erepr2) continue;
16670     assert (erepr1 != -erepr2);
16671     LOG (2, "exporting external equivalence %d %d", erepr1, erepr2);
16672     produced++;
16673     ereprs[abs (erepr1)] = (erepr1 < 0) ? -erepr2 : erepr2;
16674   }
16675   LOG (1, "produced %d equivalences", produced);
16676 DONE:
16677   if (lgl->cbs->eqs.unlock.fun)
16678     lgl->cbs->eqs.unlock.fun (lgl->cbs->eqs.unlock.state, consumed, produced);
16679   return !lgl->mt;
16680 }
16681
16682 static int lgldecomp (LGL * lgl) {
16683   int res = 1, oldnvars = lgl->nvars, removed;
16684   assert (lgl->opts->decompose.val || lgl->probing || lgl->gaussing);
16685   assert (!lgl->decomposing);
16686   lglstart (lgl, &lgl->times->dcp);
16687   lgl->stats->decomps++;
16688   lgl->decomposing = 1;
16689   lgl->simp++;
16690   assert (lgl->simp > 0);
16691   if (lgl->level > 0) lglbacktrack (lgl, 0);
16692   res = 0;
16693   lglgc (lgl);
16694   if (!lglsyncunits (lgl)) goto DONE;
16695   lglgc (lgl);
16696   if (lgl->mt) goto DONE;
16697   if (!lgltarjan (lgl)) goto DONE;
16698   if (!lglsynceqs (lgl)) goto DONE;
16699   lglchkred (lgl);
16700   lgldcpdis (lgl);
16701   lgldcpcln (lgl);
16702   lgldcpcon (lgl);
16703   lglcompact (lgl);
16704   lglmap (lgl);
16705   if (lgl->mt) goto DONE;
16706   if (!lglbcp (lgl)) { if (!lgl->mt) lgl->mt = 1; goto DONE; }
16707   lglcount (lgl);
16708   lglgc (lgl);
16709   if (lgl->mt) goto DONE;
16710   if (!lgl->mt) { lglpicosatchkall (lgl); lglpicosatrestart (lgl); }
16711   res = 1;
16712 DONE:
16713   if (lgl->repr) DEL (lgl->repr, lgl->nvars);
16714   assert (lgl->decomposing);
16715   lgl->decomposing = 0;
16716   ASSERT (lgl->simp > 0);
16717   lgl->simp--;
16718   removed = oldnvars - lgl->nvars;
16719   if (removed) lglprt (lgl, 1, "[decomp-%d] removed %d variables",
16720                        lgl->stats->decomps, removed);
16721   lglrep (lgl, 2, 'd');
16722   lglstop (lgl);
16723   return res;
16724 }
16725
16726 int lglnvars (LGL * lgl) { return lglrem (lgl); }
16727
16728 int lglnclauses (LGL * lgl) { return lgl->stats->irr.clauses.cur; }
16729
16730 static int lglcgrepr (LGL * lgl, int lit) {
16731   return lglptrjmp (lgl->repr, lgl->nvars - 1, lit);
16732 }
16733
16734 static void lglpushgocc (LGL * lgl, int lit, int gidx) {
16735   int idx, repr;
16736   Stk * goccs;
16737   repr = lglcgrepr (lgl, lit);
16738   if (abs (repr) == 1) repr = lit;
16739   idx = abs (repr);
16740   assert (2 <= idx && idx < lgl->nvars);
16741   goccs = lgl->cgr->goccs + idx;
16742   lglpushstk (lgl, goccs, gidx);
16743 }
16744
16745 static void lglenlargegates (LGL * lgl) {
16746   int oldsize = lgl->cgr->szgates;
16747   int newsize = oldsize ? 2*oldsize : 1;
16748   RSZ (lgl->cgr->gates, oldsize, newsize);
16749   lgl->cgr->szgates = newsize;
16750 }
16751
16752 static int lglcgreprnotconst (LGL * lgl, int lit) {
16753   int res;
16754   assert (abs (lit) != 1);
16755   res = lglcgrepr (lgl, lit);
16756   if (abs (res) == 1) res = lit;
16757   return res;
16758 }
16759
16760 static Gat * lglnewgate (LGL * lgl, GTag tag, int lhs, int size) {
16761   Gat * res;
16762   int gidx;
16763   assert (size >= 2);
16764   if (lgl->cgr->extracted.all >= lgl->cgr->szgates) lglenlargegates (lgl);
16765   assert (lgl->cgr->extracted.all < lgl->cgr->szgates);
16766   lgl->stats->cgr.extracted.all++;
16767   gidx = lgl->cgr->extracted.all++;
16768   res = lgl->cgr->gates + gidx;
16769   CLR (*res);
16770   lhs = lglcgreprnotconst (lgl, lhs);
16771   res->lhs = lhs;
16772   lglpushgocc (lgl, lhs, gidx);
16773   lglavar (lgl, lhs)->gate = 1;
16774   res->tag = tag;
16775   res->size = size;
16776   return res;
16777 }
16778
16779 static Gat * lglgidx2gat (LGL * lgl, int gidx) {
16780   assert (0 <= gidx && gidx < lgl->cgr->extracted.all);
16781   return lgl->cgr->gates + gidx;
16782 }
16783
16784 static int lglgat2idx (LGL * lgl, Gat * g) {
16785   assert (lgl->cgr->gates <= g && 
16786           g < lgl->cgr->gates + lgl->cgr->extracted.all);
16787   return g - lgl->cgr->gates;
16788 }
16789
16790 static int lglcgeq (LGL * lgl, int a, int b) {
16791   return lglcgrepr (lgl, a) == lglcgrepr (lgl, b);
16792 }
16793
16794 static int lglhasitegate (LGL * lgl, int lhs, int cond, int pos, int neg) {
16795   const int * p;
16796   int repr;
16797   Stk * s;
16798   repr = lglcgrepr (lgl, lhs);
16799   if (abs (repr) == 1) repr = lhs;
16800   s = lgl->cgr->goccs + abs (repr);
16801   Gat * g;
16802   for (p = s->start; p < s->top; p++) {
16803     g = lglgidx2gat (lgl, *p);
16804     if (g->tag != ITETAG) continue;
16805     assert (g->size == 2);
16806     if (g->lhs != lhs) continue;
16807     if (!lglcgeq (lgl, g->cond, cond)) continue;
16808     if (!lglcgeq (lgl, g->pos, pos)) continue;
16809     if (!lglcgeq (lgl, g->neg, neg)) continue;
16810     return 1;
16811   }
16812   return 0;
16813 }
16814
16815 #define EL 1
16816
16817 static void lglnewitegate (LGL * lgl, int lhs, int cond, int pos, int neg) {
16818   int gidx;
16819   Gat * g;
16820   lhs = lglcgreprnotconst (lgl, lhs);
16821   if (lhs < 0) lhs = -lhs, pos = -pos, neg = -neg;
16822   if ((pos < 0 && neg > 0) || (cond < 0 && lglsgn (pos) == lglsgn (neg))) {
16823     SWAP (int, pos, neg);
16824     cond = -cond;
16825   }
16826   cond = lglcgreprnotconst (lgl, cond);
16827   pos = lglcgreprnotconst (lgl, pos);
16828   neg = lglcgreprnotconst (lgl, neg);
16829   assert (abs (pos) != -abs (neg));
16830   if (lglhasitegate (lgl, lhs, cond, pos, neg)) return;
16831   g = lglnewgate (lgl, ITETAG, lhs, 2);
16832   gidx = lglgat2idx (lgl, g);
16833   g->cond = cond, g->pos = pos, g->neg = neg;
16834   lglpushgocc (lgl, cond, gidx);
16835   lglpushgocc (lgl, pos, gidx);
16836   lglpushgocc (lgl, neg, gidx);
16837   LOG (EL, "extracted ite gate %d = %d ? %d : %d", lhs, cond, pos, neg);
16838   lgl->stats->cgr.extracted.ite++;
16839   lgl->cgr->extracted.ite++;
16840 }
16841
16842 static int lglhasbingate (LGL * lgl, GTag tag, int lhs, int rhs0, int rhs1) {
16843   const int * p;
16844   Stk * s;
16845   Gat * g;
16846   lhs = lglcgreprnotconst (lgl, lhs);
16847   rhs0 = lglcgreprnotconst (lgl, rhs0);
16848   rhs1 = lglcgreprnotconst (lgl, rhs1);
16849   s = lgl->cgr->goccs + abs (lhs);
16850   for (p = s->start; p < s->top; p++) {
16851     g = lglgidx2gat (lgl, *p);
16852     if (g->tag != tag) continue;
16853     if (g->size != 2) continue;
16854     if (g->lhs != lhs) continue;
16855     if (!lglcgeq (lgl, g->lits[0], rhs0)) continue;
16856     if (!lglcgeq (lgl, g->lits[1], rhs1)) continue;
16857     return 1;
16858   }
16859   return 0;
16860 }
16861
16862 static int lglnewbingate (LGL * lgl, GTag tag, int lhs, int rhs0, int rhs1) {
16863   int gidx;
16864   Gat * g;
16865   lhs = lglcgreprnotconst (lgl, lhs);
16866   rhs0 = lglcgreprnotconst (lgl, rhs0);
16867   rhs1 = lglcgreprnotconst (lgl, rhs1);
16868   if (abs (rhs0) > abs (rhs1)) SWAP (int, rhs0, rhs1);
16869   if (tag == XORTAG && lhs < 0) lhs = -lhs, rhs0 = -rhs0;
16870   if (tag == XORTAG && rhs0 < 0) rhs0 = -rhs0, rhs1 = -rhs1;
16871   if (lglhasbingate (lgl, tag, lhs, rhs0, rhs1)) return 0;
16872   g = lglnewgate (lgl, tag, lhs, 2);
16873   gidx = lglgat2idx (lgl, g);
16874   g->lits[0] = rhs0, g->lits[1] = rhs1;
16875   lglpushgocc (lgl, rhs0, gidx);
16876   lglpushgocc (lgl, rhs1, gidx);
16877   if (tag == ANDTAG) {
16878     lgl->cgr->extracted.and++;
16879     lgl->stats->cgr.extracted.and++;
16880     LOG (EL, "extracted binary and gate %d = %d & %d", lhs, -rhs0, -rhs1);
16881   } else if (tag == XORTAG) {
16882     lgl->cgr->extracted.xor++;
16883     lgl->stats->cgr.extracted.xor++;
16884     LOG (EL, "extracted binary xor gate %d = %d ^ %d", -lhs, rhs0, rhs1);
16885   }
16886   return 1;
16887 }
16888
16889 static void lglnewlrgate (LGL * lgl, GTag tag, int lhs, int * cls, int size) {
16890   int gidx, other, lhsrepr;
16891   const int * p;
16892   Gat * g;
16893   assert (size >= 3);
16894   lhsrepr = lglcgreprnotconst (lgl, lhs);
16895   g = lglnewgate (lgl, tag, lhsrepr, size);
16896   g->origlhs = lhs;
16897   gidx = lglgat2idx (lgl, g);
16898   g->cls = cls;
16899   for (p = cls; (other = *p); p++) {
16900     if (abs (other) == lhs) continue;
16901     other = lglcgreprnotconst (lgl, other);
16902     lglpushgocc (lgl, other, gidx);
16903   }
16904   if (tag == ANDTAG) lgl->cgr->extracted.and++, lgl->stats->cgr.extracted.and++;
16905   if (tag == XORTAG) lgl->cgr->extracted.xor++, lgl->stats->cgr.extracted.xor++;
16906 #ifndef NLGLOG
16907   if (lgl->opts->log.val >= EL) {
16908     if (tag == ANDTAG) {
16909       int count = 0;
16910       lglogstart (lgl, EL, "extracted %d-ary and gate %d = ", size, lhsrepr);
16911       for (p = cls; (other = *p); p++) {
16912         if (abs (other) == abs (lhs)) continue;
16913         if (count++) fputs (" & ",  lgl->out);
16914         fprintf (lgl->out, "%d", -lglcgrepr (lgl, other));
16915       }
16916       lglogend (lgl);
16917     } else if (tag == XORTAG) {
16918       int count = 0;
16919       lglogstart (lgl, EL, "extracted %d-ary xor gate %d = ", size, -lhs);
16920       for (p = cls; (other = *p); p++) {
16921         if (abs (other) == abs (lhs)) continue;
16922         if (count++) fputs (" ^ ",  lgl->out);
16923         fprintf (lgl->out, "%d", lglcgrepr (lgl, other));
16924       }
16925       lglogend (lgl);
16926     } else COVER (1);
16927   }
16928 #endif
16929 }
16930
16931 static void lglcgmerge (LGL * lgl, int other, int repr) {
16932   int * p, * q, gidx;
16933   Stk * from, * to;
16934   Gat * g;
16935   assert (lgl->cgrclosing);
16936   if (abs (other) == 1) SWAP (int, other, repr);
16937   if (repr == -1) other = -other, repr = 1;
16938   assert (lglcgrepr (lgl, other) == other);
16939   assert (abs (repr) != abs (other));
16940   if (repr == 1) {
16941     assert (abs (other) >= 2);
16942     if (lgl->opts->drup.val) lgldrupclsarg (lgl, other, 0);
16943 #ifndef NLGLPICOSAT
16944     if (lgl->picosat.chk) lglpicosatchkclsarg (lgl, other, 0);
16945 #endif
16946     if (other < 0) other = -other, repr = -repr;
16947     lgl->repr[other] = repr;
16948     lglwrktouch (lgl, other);
16949   } else {
16950     assert (abs (repr) >= 2);
16951     assert (lglcgrepr (lgl, repr) == repr);
16952     if (lglcmprepr (lgl, other, repr) < 0) SWAP (int, repr, other);
16953     if (other < 0) other = -other, repr = -repr;
16954     lglimerge (lgl, other, repr);
16955     assert (0 < other);
16956     from = lgl->cgr->goccs + abs (other);
16957     to = lgl->cgr->goccs + abs (repr);
16958     q = to->start;
16959     for (p = q; p < to->top; p++) {
16960       g = lglgidx2gat (lgl, (gidx = *p));
16961       if (g->mark) continue;
16962       *q++ = gidx;
16963       g->mark = 1;
16964     }
16965     to->top = q;
16966     LOG (2, "merging %d gate occurrences of %d with %d occurrences of %d",
16967          lglcntstk (from), other, lglcntstk (to), repr);
16968     for (p = from->start; p < from->top; p++) {
16969       g = lglgidx2gat (lgl, (gidx = *p));
16970       if (g->mark) continue;
16971       g->mark = 1;
16972       lglpushstk (lgl, to, gidx);
16973     }
16974     lglrelstk (lgl, from);
16975     for (p = to->start; p < to->top; p++) {
16976       g = lglgidx2gat (lgl, *p); assert (g->mark); g->mark = 0;
16977     }
16978     lglwrktouch (lgl, repr);
16979   }
16980 }
16981
16982 static int lglcmpocc (LGL * lgl, int a, int b) {
16983   return lglocc (lgl, a) - lglocc (lgl, b);
16984 }
16985
16986 #define LGLCMPOCC(A,B) lglcmpocc (lgl, *(A), *(B))
16987
16988 static int lglcgextractlimhit (LGL * lgl) {
16989   return lgl->stats->cgr.esteps >= lgl->limits->cgr.esteps;
16990 }
16991
16992 static int lglincextractlimhit (LGL * lgl) {
16993   INCSTEPS (cgr.esteps);
16994   return lglcgextractlimhit (lgl);
16995 }
16996
16997 static int lglcgunit (LGL * lgl, int lit) {
16998   int next, repr, other, ok;
16999   Val val = lglval (lgl, lit);
17000   if (val > 0) return 1;
17001   if (val < 0) {
17002     LOG (1, "extracted unit already %d falsified", lit);
17003     lgl->mt = 1;
17004     return 0;
17005   }
17006   next = lgl->next;
17007   lglunit (lgl, lit);
17008   if ((ok = lglbcp (lgl))) {
17009     while (next < lgl->next) {
17010       other = lglpeek (&lgl->trail, next++);
17011       repr = lglcgrepr (lgl, other);
17012       if (repr == 1) continue;
17013       if (repr == -1) { ok = 0; break; }
17014       assert (repr != -1);
17015       lglcgmerge (lgl, repr, 1);
17016     }
17017   }
17018   if (!ok) {
17019     LOG (1, "propagation of congruence closure unit %d failed", lit);
17020     lgl->mt = 1;
17021   }
17022   return ok;
17023 }
17024
17025 static int lglcgextractands (LGL * lgl, int lit) {
17026   int blit, tag, other, other2, lidx, size, tmp, repr;
17027   const int * p, * w, * eow, * l;
17028   HTS * hts;
17029   Val val;
17030   int * c;
17031   if (!lgl->opts->cgrextand.val) return 1;
17032   repr = lglcgrepr (lgl, lit);
17033   if (lglval (lgl, lit)) { assert (abs (repr) == 1); return 1; }
17034   if (abs (repr) == 1) return 1;
17035   hts = lglhts (lgl, lit);
17036   w = lglhts2wchs (lgl, hts);
17037   eow = w + hts->count;
17038   for (p = w; p < eow; p++) {
17039     if (lglincextractlimhit (lgl)) return 0;
17040     blit = *p;
17041     tag = blit & MASKCS;
17042     if (tag == BINCS) {
17043       if (!lgl->opts->cgrexteq.val && !lgl->opts->cgrextunits.val) continue;
17044       tmp = blit >> RMSHFT;
17045       if ((val = lglval (lgl, tmp))) { assert (val > 0); continue; }
17046       repr = lglcgrepr (lgl, lit);
17047       other = lglcgrepr (lgl, -tmp);
17048       if (repr == other) continue;
17049       if (lglincextractlimhit (lgl)) return 0;
17050       if (lgl->opts->cgrextunits.val &&
17051           repr != 1 &&
17052           lglhasbin (lgl, lit, -tmp)) {
17053         LOG (EL, "extracted unit %d with %d %d and %d %d",
17054              lit, lit, tmp, lit, -tmp);
17055         lgl->cgr->extracted.units++;
17056         lgl->stats->cgr.units++;
17057         if (repr == -1) {
17058           LOG (1, "extracted unit %d in conflict with previous unit %d",
17059                lit, -lit);
17060           lgl->mt = 1;
17061           return 0;
17062         }
17063         if (!lglcgunit (lgl, repr)) return 0;
17064         if (lglval (lgl, lit)) return 1;
17065       } else if (lgl->opts->cgrexteq.val && lglhasbin (lgl, -lit, -tmp)) {
17066         lgl->cgr->extracted.eq++;
17067         lgl->stats->cgr.eq++;
17068         LOG (EL, "extracted equivalence %d = %d with representatives %d = %d",
17069              lit, -tmp, repr, other);
17070         if (repr == -other) {
17071           assert (!lgl->mt);
17072           LOG (1, "merging equivalence classes of opposite literals");
17073           lgl->mt = 1;
17074           return 0;
17075         }
17076         lglcgmerge (lgl, other, repr);
17077       }
17078       continue;
17079     }
17080     if (tag == TRNCS || tag == LRGCS) p++;
17081     if (tag == LRGCS) continue;
17082     if (tag == TRNCS) {
17083       other = blit >> RMSHFT;
17084       other2 = *p;
17085       if (lglocc (lgl, other) > lglocc (lgl, other2)) SWAP (int, other, other2);
17086       if (lglincextractlimhit (lgl)) return 0;
17087       if (!lglhasbin (lgl, -lit, -other)) continue;
17088       if (lglincextractlimhit (lgl)) return 0;
17089       if (!lglhasbin (lgl, -lit, -other2)) continue;
17090       lglnewbingate (lgl, ANDTAG, lit, other, other2);
17091     } else  {
17092       assert (tag == OCCS);
17093       if (lglincextractlimhit (lgl)) return 0;
17094       assert (lglmtstk (&lgl->clause));
17095       lidx = blit >> RMSHFT;
17096       c = lglidx2lits (lgl, (blit & REDCS), lidx);
17097       for (l = c; (other = *l); l++)
17098         if (other != lit) lglpushstk (lgl, &lgl->clause, other);
17099       size = l - c - 1;
17100       assert (size >= 3);
17101       SORT (int, lgl->clause.start, size, LGLCMPOCC);
17102       for (l = lgl->clause.start; l < lgl->clause.top; l++) {
17103         if (lglincextractlimhit (lgl)) { lglclnstk (&lgl->clause); return 0; }
17104         if (!lglhasbin (lgl, -lit, -*l)) break;
17105       }
17106       if (l == lgl->clause.top) lglnewlrgate (lgl, ANDTAG, lit, c, size);
17107       lglclnstk (&lgl->clause);
17108     }
17109   }
17110   return 1;
17111 }
17112
17113 static int lglparity (LGL * lgl) {
17114   const int * p;
17115   int res = 0;
17116   for (p = lgl->clause.start; p < lgl->clause.top; p++)
17117     if (*p < 0) res = !res;
17118   return res;
17119 }
17120
17121 static void lglinclause (LGL * lgl, int parity) {
17122   int * p;
17123   assert (lglparity (lgl) == parity);
17124   do {
17125     for (p = lgl->clause.start; p < lgl->clause.top; p++)
17126       if ((*p = -*p) < 0) break;
17127   } while (lglparity (lgl) != parity);
17128 }
17129
17130 static int lglxorhascls (LGL * lgl) {
17131   int lit, res, minlit = 0, minoccs = INT_MAX, litoccs, blit, tag, lidx;
17132   const int * p, * w, * eow, * l, * c;
17133   HTS * hts;
17134   for (p = lgl->clause.start; p < lgl->clause.top; p++) {
17135     lit = *p;
17136     litoccs = lglocc (lgl, lit);
17137     if (litoccs < minoccs) minlit = lit, minoccs = litoccs;
17138     lglsignedmark (lgl, lit);
17139   }
17140   res = 0;
17141   hts = lglhts (lgl, minlit);
17142   w = lglhts2wchs (lgl, hts);
17143   eow = w + hts->count;
17144   for (p = w; !res && p < eow; p++) {
17145     blit = *p;
17146     if (lglincextractlimhit (lgl)) { assert (!res); break; }
17147     tag = blit & MASKCS;
17148     if (tag == TRNCS || tag == LRGCS) p++;
17149     if (tag != OCCS) continue;
17150     lidx = blit >> RMSHFT;
17151     if (lglincextractlimhit (lgl)) { assert (!res); break; }
17152     c = lglidx2lits (lgl, (blit & REDCS), lidx);
17153     for (l = c; (lit = *l); l++) if (!lglsignedmarked (lgl, lit)) break;
17154     if (!lit) res = 1;
17155   }
17156   for (p = lgl->clause.start; p < lgl->clause.top; p++) lglunmark (lgl, *p);
17157   return res;
17158 }
17159
17160 static int lglcgextractxors (LGL * lgl, int lit) {
17161   int blit, tag, other, other2, lidx, size, count, parity, * c;
17162   const int * p, * w, * eow, * l;
17163   HTS * hts;
17164   if (!lgl->opts->cgrextxor.val) return 1;
17165   hts = lglhts (lgl, lit);
17166   w = lglhts2wchs (lgl, hts);
17167   eow = w + hts->count;
17168   for (p = w; p < eow; p++) {
17169     if (lglincextractlimhit (lgl)) return 0;
17170     blit = *p;
17171     tag = blit & MASKCS;
17172     if (tag == BINCS) continue;
17173     if (tag == TRNCS || tag == LRGCS) p++;
17174     if (tag == LRGCS) continue;
17175     if (tag == TRNCS) {
17176       if ((other = blit >> RMSHFT) < 0) continue;
17177       if ((other2 = *p) < 0) continue;
17178       INCSTEPS (cgr.esteps);
17179       if (!lglhastrn (lgl, lit, -other, -other2)) continue;
17180       INCSTEPS (cgr.esteps);
17181       if (!lglhastrn (lgl, -lit, other, -other2)) continue;
17182       INCSTEPS (cgr.esteps);
17183       if (!lglhastrn (lgl, -lit, -other, other2)) continue;
17184       lglnewbingate (lgl, XORTAG, lit, other, other2);
17185     } else {
17186       assert (tag == OCCS);
17187       if (lglincextractlimhit (lgl)) return 0;
17188       assert (lglmtstk (&lgl->clause));
17189       lidx = blit >> RMSHFT;
17190       c = lglidx2lits (lgl, (blit & REDCS), lidx);
17191       for (l = c; (other = *l); l++) {
17192         if (other != lit && other < 0) break;
17193         lglpushstk (lgl, &lgl->clause, other);
17194       }
17195       if (!other && (size = l - c - 1) <= lgl->opts->cgrmaxority.val) {
17196         assert (3 <= size && size <= 30);
17197         count = (1 << size);
17198         assert (count > 0);
17199         parity = (lit < 0);
17200         while (--count) {
17201           lglinclause (lgl, parity);
17202           INCSTEPS (cgr.esteps);
17203           if (!lglxorhascls (lgl)) break;
17204         }
17205         if (!count) {
17206 #ifndef NDEBUG
17207           int i;
17208           lglinclause (lgl, parity);
17209           for (i = 0; i <= size; i++) assert (lgl->clause.start[i] == c[i]);
17210 #endif
17211           lglnewlrgate (lgl, XORTAG, lit, c, size);
17212         }
17213       }
17214       lglclnstk (&lgl->clause);
17215     }
17216   }
17217   return !lglcgextractlimhit (lgl);
17218 }
17219
17220 static int lglcmpitecands (const ITEC * c, const ITEC * d) {
17221   int a = c->other, b = d->other;
17222   int res = abs (a) - abs (b);
17223   if (res) return res;
17224   if ((res = a - b)) return res;
17225   return c->other2 - d->other2;
17226 }
17227
17228 static int lglcgmergelhsrhs (LGL * lgl, int lhs, int rhs) {
17229   int conflict = 0;
17230   lhs = lglcgrepr (lgl, lhs);
17231   rhs = lglcgrepr (lgl, rhs);
17232   if (lhs == rhs) return 0;
17233   if (lhs == -rhs) conflict = 1;
17234   else if (lhs == 1) {
17235     if (rhs == -1) conflict = 1;
17236     else assert (rhs != 1), conflict = !lglcgunit (lgl, rhs);
17237   } else if (lhs == -1) {
17238     if (rhs == 1) conflict = 1;
17239     else assert (rhs != -1), conflict = !lglcgunit (lgl, -rhs);
17240   } else if (rhs == 1) conflict = !lglcgunit (lgl, lhs);
17241   else if (rhs == -1) conflict = !lglcgunit (lgl, -lhs);
17242   else lglcgmerge (lgl, lhs, rhs);
17243   return conflict;
17244 }
17245
17246 static void lglcgextractitecands (LGL * lgl, int lhs, ITEC * cands, int ncands) {
17247   int cond, pos, neg;
17248   int l, m, r, i, j;
17249   for (l = 0; l < ncands; l = r) {
17250     for (r = l + 1; r < ncands; r++)
17251       if (abs (cands[l].other) != abs (cands[r].other)) break;
17252     if (cands[l].other == cands[r-1].other) continue;
17253     assert (cands[l].other < 0);
17254     assert (cands[r-1].other > 0);
17255     assert (cands[l].other == -cands[r-1].other);
17256     for (m = l + 1; cands[m].other < 0; m++) assert (m + 1 < r);
17257     for (i = l; i + 1 < m; i++) assert (cands[i].other == cands[i+1].other);
17258     for (i = m; i + 1 < r; i++) assert (cands[i].other == cands[i+1].other);
17259     for (i = l; i < m; i++) {
17260       for (j = m; j < r; j++) {
17261         lhs = lglcgreprnotconst (lgl, lhs);
17262         INCSTEPS (cgr.esteps);
17263         cond = -cands[l].other;
17264         pos = -cands[l].other2;
17265         neg = -cands[m].other2;
17266         pos = lglcgreprnotconst (lgl, pos);
17267         neg = lglcgreprnotconst (lgl, neg);
17268         if (pos == -neg) continue;              // skip XORTAGs
17269         if (pos == neg) {
17270           if (lhs != pos && lglcgmergelhsrhs (lgl, lhs, pos)) return;
17271         } else lglnewitegate (lgl, lhs, cond, pos, neg);
17272       }
17273     }
17274   }
17275 }
17276
17277 static int lglcgextractites (LGL * lgl, int lit) {
17278   int blit, tag, other, other2;
17279   ITEC * cands; int ncands;
17280   const int * p, * w, * eow;
17281   HTS * hts;
17282   if (!lgl->opts->cgrextite.val) return 1;
17283   hts = lglhts (lgl, lit);
17284   w = lglhts2wchs (lgl, hts);
17285   eow = w + hts->count;
17286   for (p = w; p < eow; p++) {
17287     INCSTEPS (cgr.esteps);
17288     blit = *p;
17289     tag = blit & MASKCS;
17290     if (tag == BINCS || tag == OCCS) continue;
17291     p++;
17292     if (tag == LRGCS) continue;
17293     assert (tag == TRNCS);
17294     other = blit >> RMSHFT;
17295     other2 = *p;
17296     lglsignedmark (lgl, other);
17297     lglsignedmark (lgl, other2);
17298   }
17299   assert (lglmtstk (&lgl->seen));
17300   for (p = w; p < eow; p++) {
17301     blit = *p;
17302     tag = blit & MASKCS;
17303     if (tag == BINCS || tag == OCCS) continue;
17304     p++;
17305     if (tag == LRGCS) continue;
17306     INCSTEPS (cgr.esteps);
17307     assert (tag == TRNCS);
17308     other = blit >> RMSHFT;
17309     other2 = *p;
17310     if (lglsignedmarked (lgl, -other)) {
17311       INCSTEPS (cgr.esteps);
17312       if (lglhastrn (lgl, -lit, other, -other2)) {
17313         lglpushstk (lgl, &lgl->seen, other);
17314         lglpushstk (lgl, &lgl->seen, other2);
17315       }
17316     }
17317     if (lglsignedmarked (lgl, -other2)) {
17318       INCSTEPS (cgr.esteps);
17319       if (lglhastrn (lgl, -lit, -other, other2)) {
17320         lglpushstk (lgl, &lgl->seen, other2);
17321         lglpushstk (lgl, &lgl->seen, other);
17322       }
17323     }
17324   }
17325   for (p = w; p < eow; p++) {
17326     INCSTEPS (cgr.esteps);
17327     blit = *p;
17328     tag = blit & MASKCS;
17329     if (tag == BINCS || tag == OCCS) continue;
17330     p++;
17331     if (tag == LRGCS) continue;
17332     assert (tag == TRNCS);
17333     other = blit >> RMSHFT;
17334     other2 = *p;
17335     lglunmark (lgl, other);
17336     lglunmark (lgl, other2);
17337   }
17338   if ((ncands = lglcntstk (&lgl->seen))) {
17339     cands = (ITEC *) lgl->seen.start;
17340     assert (!(ncands & 1));
17341     ncands /= 2;
17342     SORT (ITEC, cands, ncands, lglcmpitecands);
17343     lglcgextractitecands (lgl, lit, cands, ncands);
17344   }
17345   lglclnstk (&lgl->seen);
17346   return !lglcgextractlimhit (lgl);
17347 }
17348
17349 static int lglcgextractidx (LGL * lgl, int idx) {
17350   if (!lglisfree (lgl, idx)) return 1;
17351   if (lglavar (lgl, idx)->donotcgrcls) return 1;
17352   if (lglcgextractlimhit (lgl)) return 0;
17353   if (lglterminate (lgl)) return 0;
17354   if (!lgl->mt && !lglcgextractands (lgl, idx)) return 0;
17355   if (!lgl->mt && !lglcgextractands (lgl, -idx)) return 0;
17356   if (!lgl->mt && !lglcgextractxors (lgl, idx)) return 0;
17357   if (!lgl->mt && !lglcgextractxors (lgl, -idx)) return 0;
17358   if (!lgl->mt && !lglcgextractites (lgl, idx)) return 0;
17359   if (!lgl->mt && !lglcgextractites (lgl, -idx)) return 0;
17360   return 1;
17361 }
17362
17363 static void lglgateextract (LGL * lgl) {
17364   int idx, count;
17365   LOG (EL, "starting new extraction %d", lgl->stats->cgr.count);
17366   lglrandidxtrav (lgl, lglcgextractidx);
17367   count = 0;
17368   for (idx = 2; idx < lgl->nvars; idx++) count += lgl->avars[idx].gate;
17369   if (lgl->cgr->extracted.units)
17370     lglprt (lgl, 2, "[extract-%d] extracted %d units",
17371       lgl->stats->cgr.count, lgl->cgr->extracted.units);
17372   if (lgl->cgr->extracted.eq)
17373     lglprt (lgl, 2, "[extract-%d] extracted %d equivalences",
17374       lgl->stats->cgr.count, lgl->cgr->extracted.eq);
17375   if (lgl->cgr->extracted.all)
17376     lglprt (lgl, 2,
17377       "[extract-%d] extracted %d gates for %d variables %.0f%%",
17378       lgl->stats->cgr.count, lgl->cgr->extracted.all,
17379       count, lglpcnt (count, lgl->nvars));
17380   if (lgl->cgr->extracted.and)
17381     lglprt (lgl, 2,
17382       "[extract-%d] %d and gates %.0f%% of all extracted gates",
17383       lgl->stats->cgr.count,
17384       lgl->cgr->extracted.and, lglpcnt (lgl->cgr->extracted.and, lgl->cgr->extracted.all));
17385   if (lgl->cgr->extracted.xor)
17386     lglprt (lgl, 2,
17387       "[extract-%d] %d xor gates %.0f%% of all extracted gates",
17388       lgl->stats->cgr.count,
17389       lgl->cgr->extracted.xor, lglpcnt (lgl->cgr->extracted.xor, lgl->cgr->extracted.all));
17390   if (lgl->cgr->extracted.ite)
17391     lglprt (lgl, 2,
17392       "[extract-%d] %d ite gates %.0f%% of all extracted gates",
17393       lgl->stats->cgr.count,
17394       lgl->cgr->extracted.ite, lglpcnt (lgl->cgr->extracted.ite, lgl->cgr->extracted.all));
17395 }
17396
17397 static void lglprtcgrem (LGL * lgl) {
17398   int idx, ret = 0, rem = 0;
17399   for (idx = 2; idx < lgl->nvars; idx++) {
17400     if (!lglisfree (lgl, idx)) continue;
17401     if (lglavar (lgl, idx)->donotcgrcls) ret++; else rem++;
17402   }
17403   if (rem)
17404     lglprt (lgl, 1, "[cgrclsr-%d] %d variables remain %.0f%% (%d retained)",
17405             lgl->stats->cgr.count, rem, lglpcnt (rem, lglrem (lgl)), ret);
17406   else {
17407     lglprt (lgl, 1, "[cgrclsr-%d] fully completed congruence closure",
17408            lgl->stats->cgr.count);
17409     for (idx = 2; idx < lgl->nvars; idx++)
17410       lglavar (lgl, idx)->donotcgrcls = 0;
17411   }
17412 }
17413
17414 static void lglcginit (LGL * lgl) {
17415   int idx, schedulable = 0, donotcgrcls = 0;
17416   for (idx = 2; idx < lgl->nvars; idx++) {
17417     if (!lglisfree (lgl, idx)) continue;
17418     if (lglavar (lgl, idx)->donotcgrcls) donotcgrcls++;
17419     else schedulable++;
17420   }
17421   if (!schedulable) {
17422     donotcgrcls = 0;
17423     for (idx = 2; idx < lgl->nvars; idx++) {
17424       if (!lglisfree (lgl, idx)) continue;
17425       lglavar (lgl, idx)->donotcgrcls = 0;
17426       schedulable++;
17427     }
17428   }
17429   if (!donotcgrcls)
17430     lglprt (lgl, 1, "[cgrclsr-%d] all %d free variables schedulable",
17431             lgl->stats->cgr.count, schedulable);
17432   else
17433     lglprt (lgl, 1,
17434       "[cgrclsr-%d] %d schedulable variables %.0f%%",
17435       lgl->stats->cgr.count, schedulable, lglpcnt (schedulable, lglrem (lgl)));
17436   lglwrkinit (lgl, 1, 1);
17437   assert (!lgl->donotsched), lgl->donotsched = 1;
17438   lglrandidxtrav (lgl, lglwrktouch);
17439   assert (lgl->donotsched), lgl->donotsched = 0;
17440   NEW (lgl->cgr->goccs, lgl->nvars);
17441 }
17442
17443 static void lglcgreset (LGL * lgl) {
17444   const int * p;
17445   int idx;
17446   for (idx = 2; idx < lgl->nvars; idx++) lgl->avars[idx].donotcgrcls = 1;
17447   for (p = lgl->wrk->queue.start; p < lgl->wrk->queue.top; p++)
17448     lgl->avars[abs (*p)].donotcgrcls = 0;
17449   lglwrkreset (lgl);
17450   for (idx = 2; idx < lgl->nvars; idx++) lgl->avars[idx].gate = 0;
17451   for (idx = 2; idx < lgl->nvars; idx++) lglrelstk (lgl, lgl->cgr->goccs + idx);
17452   DEL (lgl->cgr->goccs, lgl->nvars);
17453   DEL (lgl->cgr->gates, lgl->cgr->szgates);
17454   lgl->cgr->szgates = 0;
17455 }
17456
17457 static void lglsetbinminrhs (LGL * lgl, Gat * g) {
17458   int a = lglcgrepr (lgl, g->lits[0]);
17459   int b = lglcgrepr (lgl, g->lits[1]);
17460   assert (g->size == 2);
17461   assert (g->tag != ITETAG);
17462   if (abs (a) == 1 && abs (b) == 1) g->minrhs = INT_MAX;
17463   else if (abs (a) == 1) g->minrhs = b;
17464   else if (abs (b) == 1) g->minrhs = a;
17465   else g->minrhs = (abs (a) < abs (b)) ? a : b;
17466 }
17467
17468 static void lglsetlrgminrhs (LGL * lgl, Gat * g) {
17469   int * p, other;
17470   assert (g->size >= 3);
17471   g->minrhs = INT_MAX;
17472   for (p = g->cls; (other = *p); p++) {
17473     if (abs (other) == abs (g->lhs)) continue;
17474     other = lglcgrepr (lgl, other);
17475     if (abs (other) == 1) continue;
17476     if (abs (g->minrhs) > abs (other)) g->minrhs = other;
17477   }
17478   assert (g->minrhs);
17479 }
17480
17481 static void lglsetiteminrhs (LGL * lgl, Gat * g) {
17482   assert (g->tag == ITETAG);
17483   g->minrhs = lglcgrepr (lgl, g->cond);
17484 }
17485
17486 static void lglsetminrhs (LGL * lgl, Gat * g) {
17487   if (g->tag == ITETAG) lglsetiteminrhs (lgl, g);
17488   else if (g->size == 2) lglsetbinminrhs (lgl, g);
17489   else lglsetlrgminrhs (lgl, g);
17490   if (g->tag != ANDTAG && g->minrhs < 0) g->minrhs = -g->minrhs;
17491 }
17492
17493 static int lglcmpgoccs (LGL * lgl, int a, int b) {
17494   Gat * g = lglgidx2gat (lgl, a);
17495   Gat * h = lglgidx2gat (lgl, b);
17496   int res = (g->tag - h->tag); if (res) return res;
17497   if ((res = (g->size - h->size))) return res;
17498   if ((res = g->minrhs - h->minrhs)) return res;
17499   return a - b;
17500 }
17501
17502 #define LGLCMPGOCCS(A,B) lglcmpgoccs (lgl, *(A), *(B))
17503
17504 static int lglgoccsmatchcand (LGL * lgl, int a, int b) {
17505   Gat * g = lglgidx2gat (lgl, a);
17506   Gat * h = lglgidx2gat (lgl, b);
17507   return g->tag == h->tag && g->size == h->size && g->minrhs == h->minrhs;
17508 }
17509
17510 static int lglmatchitegate (LGL * lgl, Gat * g, Gat * h) {
17511   int gc = lglcgrepr (lgl, g->cond);
17512   int gp = lglcgrepr (lgl, g->pos);
17513   int gn = lglcgrepr (lgl, g->neg);
17514   int hc = lglcgrepr (lgl, h->cond);
17515   int hp = lglcgrepr (lgl, h->pos);
17516   int hn = lglcgrepr (lgl, h->neg);
17517   assert (g->tag == ITETAG);
17518   assert (g->size == 2);
17519   INCSTEPS (cgr.csteps);
17520   if (gc == 1) {
17521     if (hc == 1 && gp == hp) return 1;
17522     if (hc == -1 && gp == hn) return 1;
17523   } else if (gc == -1) {
17524     if (hc == 1 && gn == hp) return 1;
17525     if (hc == -1 && gn == hn) return 1;
17526   } else if (gc == hc) {
17527     if (gp == hp && gn == hn) return 1;
17528     if (gp == -hp && gn == -hn) return -1;
17529   } else if (gc == -hc) {
17530     if (gp == hn && gn == hp) return 1;
17531     if (gp == -hn && gn == -hp) return -1;
17532   }
17533   return 0;
17534 }
17535
17536 static int lglmatchbingate (LGL * lgl, Gat * g, Gat * h) {
17537   int g0 = lglcgrepr (lgl, g->lits[0]);
17538   int g1 = lglcgrepr (lgl, g->lits[1]);
17539   int h0 = lglcgrepr (lgl, h->lits[0]);
17540   int h1 = lglcgrepr (lgl, h->lits[1]);
17541   int sign;
17542   INCSTEPS (cgr.csteps);
17543   assert (g->size == 2);
17544   if (g->tag == XORTAG) {
17545     sign = 1;
17546     if (g0 < 0) sign = -sign, g0 = -g0;
17547     if (g1 < 0) sign = -sign, g1 = -g1;
17548     if (h0 < 0) sign = -sign, h0 = -h0;
17549     if (h1 < 0) sign = -sign, h1 = -h1;
17550   } else sign = 1;
17551   if (g0 == h0 && g1 == h1) return sign;
17552   if (g0 == h1 && g1 == h0) return sign;
17553   return 0;
17554 }
17555
17556 static int lglmatchlrgandaux (LGL * lgl, Gat * g, Gat * h) {
17557   int * p, other, repr, bit, res, jumped, gfalse, gtrue, htrue, hfalse;
17558   int found;
17559   AVar * u;
17560   assert (g->tag == ANDTAG);
17561   jumped = 1;
17562   gtrue = 1, gfalse = 0;
17563   found = 0;
17564   for (p = g->cls; (other = *p); p++) {
17565     INCSTEPS (cgr.csteps);
17566     if (abs (other) == abs (g->origlhs)) {
17567       assert (other == g->origlhs);
17568       found++;
17569       continue;
17570     }
17571     repr = lglcgrepr (lgl, -other);
17572     if (repr == -1) { gfalse = 1; break; }
17573     if (repr == 1) continue;
17574     gtrue = 0;
17575     if (repr != other) jumped = -1;
17576     u = lglavar (lgl, repr);
17577     bit = 1 << (repr < 0);
17578     if (u->mark & (bit^3)) gfalse = 1;
17579     if (u->mark & bit) continue;
17580     u->mark |= bit;
17581   }
17582   assert (other || found);
17583   res = 1;
17584   htrue  = 1, hfalse = 0;
17585   found = 0;
17586   for (p = h->cls; res && (other = *p); p++) {
17587     if (abs (other) == abs (h->origlhs)) {
17588       found++;
17589       assert (other == h->origlhs);
17590       continue;
17591     }
17592     repr = lglcgrepr (lgl, -other);
17593     if (repr == -1) { hfalse = 1; break; }
17594     if (repr == 1) continue;
17595     htrue = 0;
17596     if (repr != other) jumped = -1;
17597     u = lglavar (lgl, repr);
17598     bit = 1 << (repr < 0);
17599     if (!(u->mark & bit)) res = 0;
17600   }
17601   assert (!res || other || found);
17602   found = 0;
17603   for (p = g->cls; (other = *p); p++) {
17604     if (abs (other) == abs (g->origlhs)) { found++; continue; }
17605     repr = lglcgrepr (lgl, other);
17606     if (abs (repr) == 1) continue;
17607     u = lglavar (lgl, repr);
17608     u->mark = 0;
17609   }
17610   assert (found);
17611   if (gfalse) {
17612     lglcgmergelhsrhs (lgl, g->lhs, -1);
17613     res = 0;
17614   } else if (res && gtrue) {
17615     lglcgmergelhsrhs (lgl, g->lhs, 1);
17616     res = 0;
17617   }
17618   if (hfalse) {
17619     lglcgmergelhsrhs (lgl, h->lhs, -1);
17620     res = 0;
17621   } else if (htrue) {
17622     lglcgmergelhsrhs (lgl, h->lhs, 1);
17623     res = 0;
17624   }
17625   return jumped * res;
17626 }
17627
17628 static int lglmatchlrgand (LGL * lgl, Gat * g, Gat * h) {
17629   int res = lglmatchlrgandaux (lgl, g, h);
17630   if (res >= 0) return res;
17631   res = lglmatchlrgandaux (lgl, h, g);
17632   return abs (res);
17633 }
17634
17635 static int lglmatchlrgxor (LGL * lgl, Gat * g, Gat * h) {
17636   int * p, other, repr, res, gconst, hconst, hpar, gpar, sign, found;
17637   AVar * u;
17638   gconst = 1, gpar = -1;
17639   sign = 1;
17640   found = 0;
17641   for (p = g->cls; (other = *p); p++) {
17642     INCSTEPS (cgr.csteps);
17643     if (abs (other) == abs (g->origlhs)) {
17644       assert (other == g->origlhs);
17645       found++;
17646       continue;
17647     }
17648     repr = lglcgrepr (lgl, other);
17649     if (repr < 0) sign = -sign, gpar = -gpar;
17650     if (abs (repr) == 1) continue;
17651     else gconst = 0;
17652     u = lglavar (lgl, repr);
17653     u->mark = !u->mark;
17654   }
17655   assert (found);
17656   hconst = 1, hpar = -1;
17657   found = 0;
17658   for (p = h->cls; (other = *p); p++) {
17659     if (abs (other) == abs (h->origlhs)) {
17660       assert (other == h->origlhs);
17661       found++;
17662       continue;
17663     }
17664     repr = lglcgrepr (lgl, other);
17665     if (abs (repr) != 1) hconst = 0;
17666     if (repr < 0) sign = -sign, hpar = -hpar;
17667     if (abs (repr) == 1) continue;
17668     else gconst = 0;
17669     u = lglavar (lgl, repr);
17670     u->mark = !u->mark;
17671   }
17672   assert (found);
17673   res = 1;
17674   found = 0;
17675   for (p = g->cls; (other = *p); p++) {
17676     if (abs (other) == abs (g->origlhs)) { found++; continue; }
17677     repr = lglcgrepr (lgl, other);
17678     if (abs (repr) == 1) continue;
17679     u = lglavar (lgl, repr);
17680     if (!u->mark) continue;
17681     u->mark = 0;
17682     res = 0;
17683   }
17684   assert (found);
17685   found = 0;
17686   for (p = h->cls; (other = *p); p++) {
17687     if (abs (other) == abs (h->origlhs)) { found++; continue; }
17688     repr = lglcgrepr (lgl, other);
17689     if (abs (repr) == 1) continue;
17690     u = lglavar (lgl, repr);
17691     if (!u->mark) continue;
17692     u->mark = 0;
17693     res = 0;
17694   }
17695   assert (found);
17696   if (gconst) {
17697     lglcgmergelhsrhs (lgl, g->lhs, gpar);
17698     res = 0;
17699   }
17700   if (hconst) {
17701     lglcgmergelhsrhs (lgl, h->lhs, hpar);
17702     res = 0;
17703   }
17704   return sign*res;
17705 }
17706
17707 static int lglmatchgate (LGL * lgl, int fixed, Gat * g, Gat * h) {
17708   int l = lglcgrepr (lgl, g->lhs);
17709   int k = lglcgrepr (lgl, h->lhs);
17710   int repr, other, s;
17711   assert (g != h);
17712   INCSTEPS (cgr.csteps);
17713   assert (g->tag == h->tag);
17714   assert (g->size == h->size);
17715   assert (g->minrhs == h->minrhs);
17716   assert (g->size >= 2);
17717   if (g->tag == ITETAG) { if (!(s = lglmatchitegate (lgl, g, h))) return 0; }
17718   else if (g->size == 2) { if (!(s = lglmatchbingate (lgl, g, h))) return 0; }
17719   else if (g->tag == ANDTAG) { if (!(s = lglmatchlrgand (lgl, g, h))) return 0; }
17720   else if (g->tag == XORTAG) { if (!(s = lglmatchlrgxor (lgl, g, h))) return 0; }
17721   else return 0;
17722   repr = s*l, other = k;
17723   if (repr == other) return 0;
17724   lgl->stats->cgr.matched.all++;
17725   lgl->cgr->matched.all++;
17726   if (g->tag == ANDTAG) lgl->cgr->matched.and++, lgl->stats->cgr.matched.and++;
17727   if (g->tag == XORTAG) lgl->cgr->matched.xor++, lgl->stats->cgr.matched.xor++;
17728   if (g->tag == ITETAG) lgl->cgr->matched.ite++, lgl->stats->cgr.matched.ite++;
17729   if (repr == -other) {
17730     assert (!lgl->mt);
17731     LOG (1, "gate match to same literal only differing in sign");
17732     lgl->mt = 1;
17733     return 0;
17734   }
17735   LOG (1, "gates with lhs %d and %d match", g->lhs, h->lhs);
17736   lglcgmerge (lgl, other, repr);
17737   if (abs (fixed) == abs (other)) return 1;
17738   if (abs (fixed) == abs (repr)) return 1;
17739   return 0;
17740 }
17741
17742 static int lglcgrlimhit (LGL * lgl) {
17743   return lgl->stats->cgr.csteps >= lgl->limits->cgr.csteps;
17744 }
17745
17746 static int lglsimpbinand (LGL * lgl, Gat * g) {
17747   int lhs, a, b, res, conflict;
17748   assert (g->tag == ANDTAG && g->size == 2);
17749   lhs = lglcgrepr (lgl, g->lhs);
17750   a = lglcgrepr (lgl, -g->lits[0]);
17751   b = lglcgrepr (lgl, -g->lits[1]);
17752   conflict = res = 0;
17753   if (a == 1 && b == 1) {
17754     if (lhs == 1) return 0;
17755     res = 1;
17756     LOG (2, "binary and gate with lhs %d simplified to true", g->lhs);
17757     if (lhs == -1) conflict = 1; else conflict = !lglcgunit (lgl, lhs);
17758   } else if (a == -1 || b == -1 || a == -b) {
17759     if (lhs == -1) return 0;
17760     res = 1;
17761     LOG (2, "binary and gate with lhs %d simplified to false", g->lhs);
17762     if (lhs == 1) conflict = 1; else conflict = !lglcgunit (lgl, -lhs);
17763   } else {
17764     if (b == 1) SWAP (int, a, b);
17765     if (a == 1) {
17766       if (lhs == b) return 0;
17767       res = 1;
17768       LOG (2, "binary and gate with lhs %d simplifies to %d", g->lhs, b);
17769       if (lhs == -b) conflict = 1; else lglcgmerge (lgl, lhs, b);
17770     }
17771   }
17772   if (res) {
17773     lgl->cgr->simplified.all++;
17774     lgl->stats->cgr.simplified.all++;
17775     lgl->cgr->simplified.and++;
17776     lgl->stats->cgr.simplified.and++;
17777   }
17778   if (conflict) {
17779     LOG (1,
17780       "simplifying binary and gate with lhs %d leads to conflict", g->lhs);
17781     lgl->mt = 1;
17782     assert (res);
17783   }
17784   return res;
17785 }
17786
17787 static int lglsimplrgand (LGL * lgl, Gat * g) {
17788   int * p, lhs, other, repr, conflict, res, foundfalse, rhs, bit, found;
17789   AVar * u;
17790   assert (g->tag == ANDTAG && g->size > 2);
17791   lhs = lglcgrepr (lgl, g->lhs);
17792   rhs = foundfalse = 0;
17793   found = 0;
17794   for (p = g->cls; !foundfalse && (other = *p); p++) {
17795     if (other == g->origlhs) { found++; continue; }
17796     INCSTEPS (cgr.csteps);
17797     repr = lglcgrepr (lgl, -other);
17798     if (repr == 1) continue;
17799     if (repr == -1) { foundfalse = 1; break; }
17800     if (rhs) rhs = INT_MAX; else { assert (repr); rhs = repr; }
17801     u = lglavar (lgl, repr);
17802     bit = (1 << (repr < 0));
17803     if (u->mark & bit) continue;
17804     if (u->mark & (bit^3)) { foundfalse = 1; break; }
17805     u->mark |= bit;
17806   }
17807   assert (foundfalse || found);
17808   for (p = g->cls; (other = *p); p++) {
17809     if (other == g->origlhs) continue;
17810     repr = lglcgrepr (lgl, other);
17811     if (abs (repr) == 1) continue;
17812     lglavar (lgl, repr)->mark = 0;
17813   }
17814   conflict = res = 0;
17815   if (foundfalse) {
17816     if (lhs != -1) {
17817       res = 1;
17818       LOG (2, "gate with lhs %d simplifies to false", g->lhs);
17819       if (lhs == 1) conflict = 1; else conflict = !lglcgunit (lgl, -lhs);
17820     }
17821   } else if (!rhs) {
17822     if (lhs != 1) {
17823       res = 1;
17824       LOG (2, "large and gate with lhs %d simplifies to true", g->lhs);
17825       if (lhs == -1) conflict = 1; else conflict = !lglcgunit (lgl, lhs);
17826     }
17827   } else if (rhs != INT_MAX) {
17828     if (lhs != rhs) {
17829       res = 1;
17830       LOG (2, "large and gate with lhs %d simplifies to %d", g->lhs, rhs);
17831       if (lhs == -rhs) conflict = 1; else lglcgmerge (lgl, lhs, rhs);
17832     }
17833   }
17834   if (res) {
17835     lgl->cgr->simplified.all++;
17836     lgl->stats->cgr.simplified.all++;
17837     lgl->cgr->simplified.and++;
17838     lgl->stats->cgr.simplified.and++;
17839   }
17840   if (conflict) {
17841     LOG (1,
17842       "simplifying large and gate with lhs %d leads to conflict", g->lhs);
17843     lgl->mt = 1;
17844     assert (res);
17845   }
17846   return res;
17847 }
17848
17849 static int lglsimpand (LGL * lgl, Gat * g) {
17850   assert (g->tag == ANDTAG);
17851   if (g->size == 2) return lglsimpbinand (lgl, g);
17852   else return lglsimplrgand (lgl, g);
17853 }
17854
17855 static int lglsimpbinxor (LGL * lgl, Gat * g) {
17856   int res, conflict, lhs, rhs, a, b;
17857   assert (g->size == 2);
17858   assert (g->tag == XORTAG);
17859   lhs = -lglcgrepr (lgl, g->lhs);
17860   a = lglcgrepr (lgl, g->lits[0]);
17861   b = lglcgrepr (lgl, g->lits[1]);
17862   rhs = conflict = res = 0;
17863   if (a == b) rhs = -1;
17864   else if (a == -b) rhs = 1;
17865   else if (a == 1) rhs = -b;
17866   else if (a == -1) rhs = b;
17867   else if (b == 1) rhs = -a;
17868   else if (b == -1) rhs = a;
17869   else if (lhs == 1) lhs = a, rhs = -b;
17870   else if (lhs == -1) lhs = a, rhs = b;
17871   if (rhs && rhs != lhs) res = 1;
17872   if (res) {
17873     LOG (2, "simplified binary xor gate with lhs %d", g->lhs);
17874     assert (rhs);
17875     assert (lhs != rhs);
17876     lgl->cgr->simplified.all++;
17877     lgl->stats->cgr.simplified.all++;
17878     lgl->cgr->simplified.xor++;
17879     lgl->stats->cgr.simplified.xor++;
17880     conflict = lglcgmergelhsrhs (lgl, lhs, rhs);
17881   }
17882   if (conflict) {
17883     LOG (1,
17884       "simplifying binary xor gate with lhs %d leads to conflict", g->lhs);
17885     lgl->mt = 1;
17886     assert (res);
17887   }
17888   return res;
17889 }
17890
17891 static int lglsimplrgxor (LGL * lgl, Gat * g) {
17892   int conflict, lhs, rhs, other, repr, * p, found;
17893   assert (g->size > 2);
17894   assert (g->tag == XORTAG);
17895   lhs = -lglcgrepr (lgl, g->lhs);
17896   rhs = -1;
17897   found = 0;
17898   for (p = g->cls; (other = *p); p++) {
17899     if (other == g->origlhs) { found++; continue; }
17900     repr = lglcgrepr (lgl, other);
17901     if (repr == -1) continue;
17902     else if (repr == 1) rhs = -rhs;
17903     else if (repr == rhs) rhs = -1;
17904     else if (repr == lhs) lhs = -1;
17905     else if (repr == -lhs) lhs = 1;
17906     else if (lhs == -1) lhs = repr;
17907     else if (lhs == 1) lhs = -repr;
17908     else if (abs (rhs) != 1) return 0;
17909     else if (rhs == -1) rhs = repr;
17910     else { assert (rhs == 1); rhs = -repr; }
17911   }
17912   assert (found);
17913   if (lhs == rhs) return 0;
17914   LOG (2, "simplified large xor gate with lhs %d", g->lhs);
17915   assert (lhs != rhs);
17916   lgl->cgr->simplified.all++;
17917   lgl->stats->cgr.simplified.all++;
17918   lgl->cgr->simplified.xor++;
17919   lgl->stats->cgr.simplified.xor++;
17920   conflict = lglcgmergelhsrhs (lgl, lhs, rhs);
17921   if (conflict) {
17922     LOG (1,
17923       "simplifying large xor gate with lhs %d leads to conflict", g->lhs);
17924     lgl->mt = 1;
17925   }
17926   return 1;
17927 }
17928
17929 static int lglsimpxor (LGL * lgl, Gat * g) {
17930   assert (g->tag == XORTAG);
17931   if (g->size == 2) return lglsimpbinxor (lgl, g);
17932   else return lglsimplrgxor (lgl, g);
17933 }
17934
17935 static int lglsimpite (LGL * lgl, Gat * g) {
17936   int glhs = g->lhs;
17937   int lhs = lglcgrepr (lgl, glhs);
17938   int gc = lglcgrepr (lgl, g->cond);
17939   int gp = lglcgrepr (lgl, g->pos);
17940   int gn = lglcgrepr (lgl, g->neg);
17941   int res, conflict, rhs, gate;
17942   assert (g->tag == ITETAG);
17943   assert (g->size == 2);
17944   gate = rhs = conflict = res = 0;
17945   if (gc == 1 || gp == gn) res = 1, rhs = gp;
17946   else if (gc == -1) res = 1, rhs = gn;
17947   else if (gp == 1 && gn == -1) res = 1, rhs = gc;
17948   else if (gp == -1 && gn == 1) res = 1, rhs = -gc;
17949   else if (gn == -1 || gc == gn) {
17950     // (lhs = gc ? gp : -1) => lhs = gc & gp
17951     // (lhs = gc ? gp : gc) => lhs = gc & gp
17952     // COVER ("simplified ite to 'gc & gp'");
17953     if (gp == 1) res = 1, rhs = gc;
17954     else if (gp == -1) {
17955       assert (gn != -1 && gc == gn);
17956       res = 1, rhs = -1;
17957     } else {
17958       res = lglnewbingate (lgl, ANDTAG, glhs, -gc, -gp);
17959       gate = 1;
17960     }
17961   } else if (gp == -1 || gc == -gp) {
17962     // (lhs = gc ? -1 : gn) => lhs = -gc & gn
17963     // (lhs = gc ? -gc : gn) => lhs = -gc & gn
17964     // COVER ("simplified ite to '-gc & gn'");
17965     assert (gn != -1);
17966     if (gn == 1) res = 1, rhs = -gc;
17967     else {
17968       assert (gn != -1);
17969       res = lglnewbingate (lgl, ANDTAG, glhs, gc, -gn);
17970       gate = 1;
17971     }
17972   } else if (gp == 1 || gc == gp) {
17973     // (lhs = gc ? 1 : gn) => lhs = gc | gn
17974     // (lhs = gc ? gp : gn) => lhs = gc | gn
17975     // COVER ("simplified ite to 'gc | gn'");
17976     if (gn == 1) res = 1, rhs = 1;
17977     else {
17978       assert (gn != -1);
17979       res = lglnewbingate (lgl, ANDTAG, -glhs, gc, gn);
17980       gate = 1;
17981     }
17982   } else if (gn == 1 || gc == -gn) {
17983     // (lhs = gc ? gp : 1) => lhs = gc gp | -gc = gp | -gc
17984     // (lhs = gc ? gp : -gc) => lhs = gc gp | -gc = gp | -gc
17985     // COVER ("simplified ite to 'gp | -gc'");
17986     if (gp == 1) res = 1, rhs = 1;
17987     else {
17988       assert (gp != -1);
17989       res = lglnewbingate (lgl, ANDTAG, -glhs, gp, -gc);
17990       gate = 1;
17991     }
17992   } else if (gp == -gn) {
17993     // (lhs = gc ? -gn : gn) => lhs = gc&-gn | -gc&gn = gc ^ gn
17994     // COVER ("simplified ite to 'gc ^ gn'");
17995     res = lglnewbingate (lgl, XORTAG, -glhs, gc, gn);
17996     gate = 1;
17997   }
17998   if (res && !gate && lhs == rhs) res = 0;
17999   if (res && (gate || lhs != rhs)) {
18000     LOG (2, "simplified ite gate with lhs %d", glhs);
18001     lgl->cgr->simplified.all++;
18002     lgl->stats->cgr.simplified.all++;
18003     lgl->cgr->simplified.ite++;
18004     lgl->stats->cgr.simplified.ite++;
18005     if (!gate) {
18006       assert (rhs);
18007       assert (lhs != rhs);
18008       if (lhs != rhs) conflict = lglcgmergelhsrhs (lgl, lhs, rhs);
18009       else res = 0;
18010     }
18011   }
18012   if (conflict) {
18013     LOG (1, "simplifying ite gate with lhs %d leads to conflict", glhs);
18014     lgl->mt = 1;
18015     assert (res);
18016   }
18017   return res;
18018 }
18019
18020 static int lglsimpgate (LGL * lgl,  Gat * g) {
18021   if (g->tag == ANDTAG) return lglsimpand (lgl, g);
18022   else if (g->tag == ITETAG) return lglsimpite (lgl, g);
18023   else { assert (g->tag == XORTAG); return lglsimpxor (lgl, g); }
18024 }
18025
18026 static void lglcgrlit (LGL * lgl, int lit) {
18027   int * p, * q, * l, * r, round;
18028   Gat * g, * h;
18029   Stk * goccs;
18030   round = 0;
18031 RESTART:
18032   if (lgl->mt) return;
18033   goccs = lgl->cgr->goccs + abs (lit);
18034   if (lglmtstk (goccs)) return;
18035   round++;
18036   LOG (2, "simplifying gates with lhs %d", lit);
18037   for (l = goccs->start; !lgl->mt && l < goccs->top; l++) {
18038     INCSTEPS (cgr.csteps);
18039     if (lglcgrlimhit (lgl)) return;
18040     g = lglgidx2gat (lgl, *l);
18041     if (lglsimpgate (lgl, g)) goto RESTART;// goccs->start moves
18042   }
18043   LOG (2,
18044        "checking congruences of %d gates with rhs %d round %d",
18045        lglcntstk (goccs), lit, round);
18046   for (p = goccs->start; p < goccs->top; p++) {
18047     INCSTEPS (cgr.csteps);
18048     if (lglcgrlimhit (lgl)) return;
18049     g = lglgidx2gat (lgl, *p);
18050     lglsetminrhs (lgl, g);
18051   }
18052   SORT (int, goccs->start, lglcntstk (goccs), LGLCMPGOCCS);
18053   q = goccs->start + 1;
18054   for (p = q; p < goccs->top; p++) if (*p != q[-1]) *q++ = *p;
18055   goccs->top = q;
18056   for (l = goccs->start; !lgl->mt && l < goccs->top; l = r) {
18057     INCSTEPS (cgr.csteps);
18058     if (lglcgrlimhit (lgl)) return;
18059     for (r = l + 1; r < goccs->top && lglgoccsmatchcand (lgl, *l, *r); r++)
18060       ;
18061     for (p = l; !lgl->mt && p + 1 < r; p++) {
18062       g = lglgidx2gat (lgl, *p);
18063       if (abs (lglcgrepr (lgl, g->lhs)) == 1) continue;
18064       for (q = p + 1; !lgl->mt && q < r; q++) {
18065         // if (lglsimpgate (lgl, g)) goto RESTART;// goccs->start moves
18066         h = lglgidx2gat (lgl, *q);
18067         if (abs (lglcgrepr (lgl, h->lhs)) == 1) continue;
18068         if (lglsimpgate (lgl, h)) goto RESTART;// goccs->start moves
18069         if (lglmatchgate (lgl, lit, g, h)) goto RESTART;// goccs->start moves
18070       }
18071     }
18072   }
18073 }
18074
18075 static void lglclsr (LGL * lgl) {
18076   int lit;
18077   while (!lgl->mt &&
18078          !lglterminate (lgl) &&
18079          (lit = lglwrknext (lgl)) &&
18080          !lglcgrlimhit (lgl)) {
18081     lglcgrlit (lgl, lit);
18082     if (!lgl->mt && !lglcgrlimhit (lgl)) lglcgrlit (lgl, -lit);
18083   }
18084
18085   if (lgl->cgr->simplified.all)
18086     lglprt (lgl, 2, "[closure-%d] simplified %d gates",
18087            lgl->stats->cgr.count, lgl->cgr->simplified.all);
18088   if (lgl->cgr->simplified.and)
18089     lglprt (lgl, 2, "[closure-%d] simplified %d and gates",
18090             lgl->stats->cgr.count, lgl->cgr->simplified.and);
18091   if (lgl->cgr->simplified.xor)
18092     lglprt (lgl, 2, "[closure-%d] simplified %d xor gates",
18093             lgl->stats->cgr.count, lgl->cgr->simplified.xor);
18094   if (lgl->cgr->simplified.ite)
18095     lglprt (lgl, 2, "[closure-%d] simplified %d ite gates",
18096             lgl->stats->cgr.count, lgl->cgr->simplified.ite);
18097
18098   if (lgl->cgr->matched.all)
18099     lglprt (lgl, 2, "[closure-%d] matched %d gates",
18100             lgl->stats->cgr.count, lgl->cgr->matched.all);
18101   if (lgl->cgr->matched.and)
18102     lglprt (lgl, 2, "[closure-%d] matched %d and gates %.0f%%",
18103             lgl->stats->cgr.count, lgl->cgr->matched.and,
18104             lglpcnt (lgl->cgr->matched.and, lgl->cgr->matched.all));
18105   if (lgl->cgr->matched.xor)
18106     lglprt (lgl, 2, "[closure-%d] matched %d xor gates %.0f%%",
18107             lgl->stats->cgr.count, lgl->cgr->matched.xor,
18108             lglpcnt (lgl->cgr->matched.xor, lgl->cgr->matched.all));
18109   if (lgl->cgr->matched.ite)
18110     lglprt (lgl, 2, "[closure-%d] matched %d ite gates %.0f%%",
18111             lgl->stats->cgr.count, lgl->cgr->matched.ite,
18112             lglpcnt (lgl->cgr->matched.ite, lgl->cgr->matched.all));
18113 }
18114
18115 static int lgladdunits (LGL * lgl) {
18116   int idx, lit, repr;
18117   Val val;
18118   assert (!lgl->mt);
18119   assert (lglmtstk (&lgl->cgr->units));
18120   for (idx = 2; idx < lgl->nvars; idx++) {
18121     repr = lglcgrepr (lgl, idx);
18122     if (abs (repr) >= 2) continue;
18123     lit = (repr > 0) ? idx : -idx;
18124     val = lglval (lgl, lit);
18125     if (val > 0) continue;
18126     if (val < 0) {
18127       LOG (1, "inconsistent congruence closure unit %d", lit);
18128       lgl->mt = 1;
18129       return 0;
18130     }
18131     LOG (1, "adding congruence closure unit %d", lit);
18132     lglpushstk (lgl, &lgl->cgr->units, lit);
18133   }
18134   return 1;
18135 }
18136
18137 static int lglpropunits (LGL * lgl) {
18138   int lit;
18139   Val val;
18140   assert (!lgl->mt);
18141   assert (!lgl->level);
18142   while (!lglmtstk (&lgl->cgr->units)) {
18143     lit = lglpopstk (&lgl->cgr->units);
18144     val = lglcval (lgl, lit);
18145     if (val > 0) continue;
18146     if (val < 0) {
18147       LOG (1, "inconsistent congruence closure unit %d", lit);
18148       lgl->mt = 1;
18149     } else {
18150       LOG (1, "assigning congruence closure unit %d", lit);
18151       lglunitnocheck (lgl, lit);
18152 #if !defined(NLGLPICOSAT) && !defined(NDEBUG)
18153       {
18154         int cls[2]; cls[0] = lit; cls[1] = 0;
18155         lglpicosataddcls (lgl, cls);
18156       }
18157 #endif
18158       if (lglbcp (lgl)) continue;
18159       LOG (1, "conflict after assigning congruence closure unit %d", lit);
18160       lgl->mt = 1;
18161     }
18162   }
18163   return !lgl->mt;
18164 }
18165
18166 static void lglsetcgrclsrlim (LGL * lgl) {
18167   int64_t limit, irrlim;
18168   int pen;
18169   limit = (lgl->opts->cgreleff.val*lglvisearch (lgl))/1000;
18170   if (limit < lgl->opts->cgrmineff.val) limit = lgl->opts->cgrmineff.val;
18171   if (lgl->opts->cgrmaxeff.val >= 0 && limit > lgl->opts->cgrmaxeff.val)
18172     limit = lgl->opts->cgrmaxeff.val;
18173   limit >>= (pen = lgl->limits->cgr.pen + lglszpen (lgl));
18174   irrlim = lgl->stats->irr.clauses.cur/2;
18175   irrlim >>= lgl->limits->simp.pen;
18176   if (lgl->opts->irrlim.val && limit < irrlim) {
18177     limit = irrlim;
18178     lglprt (lgl, 1,
18179       "[cgrclsr-%d] limit %lld based on %d irredundant clauses",
18180       lgl->stats->cgr.count, (LGLL) limit, lgl->stats->irr.clauses.cur);
18181   } else
18182     lglprt (lgl, 1, "[cgrclsr-%d] limit %lld penalty %d = %d + %d",
18183       lgl->stats->cgr.count, (LGLL) limit,
18184       pen, lgl->limits->cgr.pen, lglszpen (lgl));
18185   lgl->limits->cgr.esteps = lgl->stats->cgr.esteps + limit;
18186   lgl->limits->cgr.csteps = lgl->stats->cgr.csteps + 2*limit;
18187 }
18188
18189 static int lglcgrclsr (LGL * lgl) {
18190   int nvars, oldrem, removed;
18191
18192   assert (lgl->opts->cgrclsr.val);
18193   assert (lglsmallirr (lgl));
18194   assert (!lgl->cgrclosing && !lgl->simp);
18195
18196   lglstart (lgl, &lgl->times->cgr);
18197
18198   oldrem = lglrem (lgl);
18199
18200   lgl->stats->cgr.count++;
18201   lgl->cgrclosing = lgl->simp = 1;
18202
18203   NEW (lgl->cgr, 1);
18204
18205   if (lgl->level > 0) lglbacktrack (lgl, 0);
18206   lglgc (lgl);
18207
18208   assert (lgl->frozen);
18209   lgldense (lgl, 1);
18210
18211   nvars = lgl->nvars;
18212   NEW (lgl->repr, nvars);
18213
18214   lglsetcgrclsrlim (lgl);
18215
18216   lglcginit (lgl);
18217   lglgateextract (lgl);
18218   if (!lgl->mt) lglclsr (lgl);
18219   lglcgreset (lgl);
18220
18221   lglsparse (lgl);
18222   if (lgl->mt) goto DONE;
18223   if (!lgladdunits (lgl)) { assert (lgl->mt); goto DONE; }
18224   lglchkred (lgl);
18225   lgldcpdis (lgl);
18226   lgldcpcln (lgl);
18227   lgldcpcon (lgl);
18228   lglcompact (lgl);
18229   lglmap (lgl);
18230   if (lgl->mt) goto DONE;
18231   if (!lglbcp (lgl)) goto DONE;
18232   if (!lglpropunits (lgl)) { assert (lgl->mt); goto DONE; }
18233   lglcount (lgl);
18234   lglgc (lgl);
18235   if (lgl->mt) goto DONE;
18236   if (!lgl->mt) { lglpicosatchkall (lgl); lglpicosatrestart (lgl); }
18237
18238 DONE:
18239
18240   lglrelstk (lgl, &lgl->cgr->units);
18241   if (lgl->repr) { assert (lgl->mt); DEL (lgl->repr, nvars); }
18242   removed = oldrem - lglrem (lgl);
18243   LGLUPDPEN (cgr, removed);
18244   DEL (lgl->cgr, 1);
18245   assert (lgl->simp && lgl->cgrclosing);
18246   lgl->cgrclosing = lgl->simp = 0;
18247   lglprtcgrem (lgl);
18248   lglprt (lgl, 1 + !removed,
18249     "[cgrclsr-%d] removed %d variables", lgl->stats->cgr.count, removed);
18250   lglrep (lgl, 2, 'C');
18251   lglstop (lgl);
18252   return !lgl->mt;
18253 }
18254
18255 static int lglrandomprobe (LGL * lgl, Stk * outer) {
18256   unsigned pos, delta, mod, first;
18257   int res;
18258   mod = lglcntstk (outer);
18259   if (!mod) return 0;
18260   first = pos = lglrand (lgl) % mod;
18261   res = lglpeek (outer, pos);
18262   if (!lglval (lgl, res)) return res;
18263   if (mod == 1) return 0;
18264   delta = lglrand (lgl) % mod;
18265   if (!delta) delta++;
18266   while (lglgcd (delta, mod) != 1)
18267     if (++delta == mod) { delta = 1; break; }
18268   assert (1 <= delta && delta < mod);
18269   for (;;) {
18270     pos += delta;
18271     if (pos >= mod) pos -= mod;
18272     assert (0 <= pos && pos < mod);
18273     if (pos == first) break;
18274     res = lglpeek (outer, pos);
18275     if (!lglval (lgl, res)) return res;
18276   }
18277   return 0;
18278 }
18279
18280 static int lglinnerprobe (LGL * lgl, int old,  Stk * outer,
18281                           Stk * tmp1, Stk * tmp2) {
18282   int i, lit, blit, tag, other, other2, red, lidx, res, val, count;
18283   const int * w, * eow, * p, * c, * q;
18284   HTS * hts;
18285   assert (old < lglcntstk (&lgl->trail));
18286   assert (!tmp2 || lglmtstk (tmp2));
18287   for (p = tmp1->start; p < tmp1->top; p++) {
18288     assert (!lglmarked (lgl, *p));
18289     lglmark (lgl, *p);
18290   }
18291   for (i = old; i < lglcntstk (&lgl->trail); i++) {
18292     lit = lglpeek (&lgl->trail, i);
18293     hts = lglhts (lgl, -lit);
18294     w = lglhts2wchs (lgl, hts);
18295     eow = w + hts->count;
18296     for (p = w; p < eow; p++) {
18297       blit = *p;
18298       tag = blit & MASKCS;
18299       if (tag == TRNCS || tag == LRGCS) p++;
18300       if (tag == BINCS) continue;
18301       if (tag == TRNCS) {
18302         other = blit >> RMSHFT;
18303         if (lglval (lgl, other) > 0) continue;
18304         other2 = *p;
18305         if (lglval (lgl, other2) > 0) continue;
18306         assert (!lglval (lgl, other));
18307         assert (!lglval (lgl, other2));
18308         other = abs (other);
18309         if (!lglmarked (lgl, other)) {
18310           lglmark (lgl, other);
18311           lglpushstk (lgl, tmp1, other);
18312           LOG (4, "potential inner probe %d for %d", other, lit);
18313         }
18314         other2 = abs (other2);
18315         if (!lglmarked (lgl, other2)) {
18316           lglmark (lgl, other2);
18317           lglpushstk (lgl, tmp1, other2);
18318           LOG (3, "potential inner probe %d for %d", other2, lit);
18319         }
18320       } else if (tmp2 && lgl->opts->liftlrg.val) {
18321         assert (tag == LRGCS);
18322         lidx = *p;
18323         red = blit & REDCS;
18324         c = lglidx2lits (lgl, red, lidx);
18325         count = lgl->opts->liftlrg.val;
18326         for (q = c; (other = *q) && count > 0; q++) {
18327           if (other == -lit) continue;
18328           assert (other != lit);
18329           val = lglval (lgl, other);
18330           if (val > 0) break;
18331           if (!val) count--;
18332         }
18333         if (other) continue;
18334         for (q = c; (other = *q); q++) {
18335           if (other == -lit) continue;
18336           assert (other != lit);
18337           val = lglval (lgl, other);
18338           COVER (!val);
18339           if (val < 0) continue;
18340           assert (!val);
18341           if (lglmarked (lgl, other)) continue;
18342           lglmark (lgl, other);
18343           lglpushstk (lgl, tmp2, other);
18344           LOG (3, "potential inner probe %d for %d", other, lit);
18345         }
18346       }
18347     }
18348   }
18349   LOG (2, "found %d inner probes", lglcntstk (tmp1));
18350   res = lglrandomprobe (lgl, tmp1);
18351   lglpopnunmarkstk (lgl, tmp1);
18352   if (!res) res = lglrandomprobe (lgl, outer);
18353   if (tmp2)
18354     for (p = tmp2->start; p < tmp2->top; p++) lglunmark (lgl, *p);
18355   return res;
18356 }
18357
18358 static void lglcleanrepr (LGL * lgl, Stk * represented, int * repr) {
18359   int idx;
18360   while (!lglmtstk (represented)) {
18361     idx = lglpopstk (represented);
18362     assert (2 <= idx && idx < lgl->nvars);
18363     assert (repr[idx]);
18364     repr[idx] = 0;
18365   }
18366 }
18367
18368 static void lgladdliftbincls (LGL * lgl, int a, int b) {
18369   assert (lgl->lifting);
18370   assert (lglmtstk (&lgl->clause));
18371   lglpushstk (lgl, &lgl->clause, a);
18372   lglpushstk (lgl, &lgl->clause, b);
18373   lglpushstk (lgl, &lgl->clause, 0);
18374   LOG (2, "lifted binary clause", a, b);
18375   if (lgl->opts->drup.val) lgldrupcls (lgl);
18376 #ifndef NLGLPICOSAT
18377   lglpicosatchkcls (lgl);
18378 #endif
18379   lgldrupligaddcls (lgl, REDCS);
18380   lgladdcls (lgl, REDCS, 0, 1);
18381   lglclnstk (&lgl->clause);
18382   lgl->stats->lift.impls++;
18383 }
18384
18385 static int64_t lglobalftlim (LGL * lgl) {
18386   int64_t limit, irrlim;
18387   int pen;
18388   limit = (lgl->opts->lftreleff.val*lglvisearch (lgl))/1000;
18389   if (limit < lgl->opts->lftmineff.val) limit = lgl->opts->lftmineff.val;
18390   if (lgl->opts->lftmaxeff.val >= 0 && limit > lgl->opts->lftmaxeff.val)
18391     limit = lgl->opts->lftmaxeff.val;
18392   limit >>= (pen = lgl->limits->lft.pen + lglszpen (lgl));
18393   irrlim = lgl->stats->irr.clauses.cur/4;
18394   irrlim >>= lgl->limits->simp.pen;
18395   if (lgl->opts->irrlim.val && limit < irrlim) {
18396     limit = irrlim;
18397     lglprt (lgl, 1,
18398       "[lift-%d] limit %lld based on %d irredundant clauses",
18399       lgl->stats->lift.count, (LGLL) limit, lgl->stats->irr.clauses.cur);
18400   } else
18401     lglprt (lgl, 1, "[lift-%d] limit %lld with penalty %d = %d + %d",
18402       lgl->stats->lift.count, (LGLL) limit,
18403       pen, lgl->limits->lft.pen, lglszpen (lgl));
18404   return limit;
18405 }
18406
18407 static void lglprtlftrem (LGL * lgl) {
18408   int idx, ret = 0, rem = 0;
18409   for (idx = 2; idx < lgl->nvars; idx++) {
18410     if (!lglisfree (lgl, idx)) continue;
18411     if (lglavar (lgl, idx)->donotlft) ret++; else rem++;
18412   }
18413   if (rem)
18414     lglprt (lgl, 1, "[lift-%d] %d variables remain %.0f%% (%d retained)",
18415             lgl->stats->lift.count, rem, lglpcnt (rem, lglrem (lgl)), ret);
18416   else {
18417     lglprt (lgl, 1, "[lift-%d] fully completed lifting",
18418             lgl->stats->lift.count);
18419     for (idx = 2; idx < lgl->nvars; idx++)
18420       lglavar (lgl, idx)->donotlft = 0;
18421   }
18422 }
18423
18424 static int lgliftaux (LGL * lgl) {
18425   int deltaunits, deltaimpls, origeqs, origunits, origimpls, units, impls, eqs;
18426   int lit1, lit2, repr1, repr2, orepr1, orepr2, tobeprobed, notobeprobed;
18427   int i, idx, lit, * reprs[3], first, outer, inner, round, branch;
18428   Stk probes, represented[2], saved, tmp1, tmp2;
18429   int ok, oldouter, dom, repr, other;
18430   unsigned pos, delta, mod;
18431   Val val, val1, val2;
18432   int64_t global;
18433 #ifndef NDEBUG
18434   int oldinner;
18435 #endif
18436   assert (lgl->simp && lgl->lifting && !lgl->level);
18437   NEW (lgl->repr, lgl->nvars);
18438   CLR (probes); CLR (saved); CLR (tmp1); CLR (tmp2);
18439   CLR (represented[0]); CLR (represented[1]);
18440   NEW (reprs[0], lgl->nvars);
18441   NEW (reprs[1], lgl->nvars);
18442   NEW (reprs[2], lgl->nvars);
18443   global = lgl->stats->visits.simp + lglobalftlim (lgl);
18444   tobeprobed = notobeprobed = 0;
18445   for (idx = 2; idx < lgl->nvars; idx++) {
18446     if (!lglisfree (lgl, idx)) continue;
18447     if (lglavar (lgl, idx)->donotlft) notobeprobed++;
18448     else if (lglhasbinortrn (lgl, idx) && lglhasbinortrn (lgl, -idx))
18449       tobeprobed++;
18450   }
18451   if (!tobeprobed) {
18452     for (idx = 2; idx < lgl->nvars; idx++) {
18453       if (!lglisfree (lgl, idx)) continue;
18454       lglavar (lgl, idx)->donotlft = 0;
18455       tobeprobed++;
18456     }
18457   }
18458   for (idx = 2; idx < lgl->nvars; idx++) {
18459     if (!lglisfree (lgl, idx)) continue;
18460     if (lglavar (lgl, idx)->donotlft) continue;
18461     if (!lglhasbinortrn (lgl, idx)) continue;
18462     if (!lglhasbinortrn (lgl, -idx)) continue;
18463     LOG (1, "new outer probe %d", idx);
18464     lit = (lglrand (lgl) & 1) ? idx : -idx;
18465     lglpushstk (lgl, &probes, lit);
18466   }
18467   mod = lglcntstk (&probes);
18468   lglprt (lgl, 1, "[lift-%d] using %d probes %.0f%%",
18469     lgl->stats->lift.count, mod, lglpcnt (mod, (lgl->nvars - 2)));
18470   round = 1;
18471   origimpls = impls = lgl->stats->lift.impls;
18472   origunits = units = lgl->stats->lift.units;
18473   origeqs = lgl->stats->lift.eqs;
18474   if (!(mod)) goto DONE;
18475   LOG (1, "found %u active outer probes out of %d variables %.1f%%",
18476        mod, lgl->nvars - 1, lglpcnt (mod, lgl->nvars-1));
18477   pos = lglrand (lgl)  % mod;
18478   delta = lglrand (lgl) % mod;
18479   if (!delta) delta++;
18480   while (lglgcd (delta, mod) > 1)
18481     if (++delta == mod) delta = 1;
18482   LOG (1, "lifting start %u delta %u mod %u", pos, delta, mod);
18483   first = 0;
18484   assert (lgl->simp);
18485   while (!lgl->mt) {
18486     if (lgl->stats->visits.simp >= global) break;
18487     if (lglterminate (lgl)) break;
18488     if (!lglsyncunits (lgl)) break;
18489     assert (pos < (unsigned) mod);
18490     outer = probes.start[pos];
18491     lglavar (lgl, outer)->donotlft = 1;
18492     if (outer == first) {
18493       assert (impls <= lgl->stats->lift.impls);
18494       assert (units <= lgl->stats->lift.units);
18495       deltaimpls = lgl->stats->lift.impls - impls;
18496       deltaunits = lgl->stats->lift.units - units;
18497       lglprt (lgl, 1, "[lift-%d-%d] found %d units %d impls in round %d",
18498          lgl->stats->lift.count, round, deltaunits, deltaimpls, round);
18499       impls = lgl->stats->lift.impls;
18500       units = lgl->stats->lift.units;
18501       if (round++ >= lgl->opts->lftroundlim.val) break;
18502     }
18503     if (!first) first = outer;
18504     pos += delta;
18505     if (pos >= mod) pos -= mod;
18506     if (lglval (lgl, outer)) continue;
18507     lgl->stats->lift.probed0++;
18508     LOG (2, "1st outer branch %d during lifting", outer);
18509     oldouter = lglcntstk (&lgl->trail);
18510     lgliassume (lgl, outer);
18511     ok = lglbcp (lgl);
18512     if (!ok) {
18513 FIRST_OUTER_BRANCH_FAILED:
18514       dom = lglprbana (lgl, outer);
18515       LOG (1, "1st outer branch failed literal %d during lifting", outer);
18516       lgl->stats->lift.units++;
18517       lglbacktrack (lgl, 0);
18518       lglunit (lgl, -dom);
18519       if (lglbcp (lgl)) continue;
18520       LOG (1, "empty clause after propagating outer probe during lifting");
18521       assert (!lgl->mt);
18522       lgl->mt = 1;
18523       break;
18524     }
18525     lglclnstk (&tmp2);
18526     inner = lglinnerprobe (lgl, oldouter, &probes, &tmp1, &tmp2);
18527     assert (lglmtstk (&represented[0]));
18528     if (!inner) {
18529 FIRST_OUTER_BRANCH_WIHOUT_INNER_PROBE:
18530       LOG (2, "no inner probe for 1st outer probe %d", outer);
18531       for (i = oldouter; i < lglcntstk (&lgl->trail); i++) {
18532         lit = lglpeek (&lgl->trail, i);
18533         idx = abs (lit);
18534         assert (!reprs[0][idx]);
18535         reprs[0][idx] = lglsgn (lit);
18536         lglpushstk (lgl, &represented[0], idx);
18537       }
18538       assert (lgl->level == 1);
18539       goto END_OF_FIRST_OUTER_BRANCH;
18540     }
18541 #ifndef NDEBUG
18542     oldinner = lglcntstk (&lgl->trail);
18543 #endif
18544     LOG (2, "1st inner branch %d in outer 1st branch %d", inner, outer);
18545     lgl->stats->lift.probed1++;
18546     lgliassume (lgl, inner);
18547     ok = lglbcp (lgl);
18548     if (!ok) {
18549       LOG (1, "1st inner branch failed literal %d on 1st outer branch %d",
18550           inner, outer);
18551       lglbacktrack (lgl, 1);
18552       assert (lglcntstk (&lgl->trail) == oldinner);
18553       lgladdliftbincls (lgl, -inner, -outer);
18554       assert (lglcntstk (&lgl->trail) == oldinner + 1);
18555       ok = lglbcp (lgl);
18556       if (ok) goto FIRST_OUTER_BRANCH_WIHOUT_INNER_PROBE;
18557       LOG (1, "conflict after propagating negation of 1st inner branch");
18558       goto FIRST_OUTER_BRANCH_FAILED;
18559     }
18560     lglclnstk (&saved);
18561     for (i = oldouter; i < lglcntstk (&lgl->trail); i++)
18562       lglpushstk (lgl, &saved, lglpeek (&lgl->trail, i));
18563     LOG (3, "saved %d assignments of 1st inner branch %d in 1st outer branch",
18564          lglcntstk (&saved), inner, outer);
18565     lglbacktrack (lgl, 1);
18566     assert (lglcntstk (&lgl->trail) == oldinner);
18567     LOG (2, "2nd inner branch %d in 1st outer branch %d", -inner, outer);
18568     lgl->stats->lift.probed1++;
18569     lgliassume (lgl, -inner);
18570     ok = lglbcp (lgl);
18571     if (!ok) {
18572       LOG (2, "2nd inner branch failed literal %d on 1st outer branch %d",
18573            -inner, outer);
18574       lglbacktrack (lgl, 1);
18575       assert (lglcntstk (&lgl->trail) == oldinner);
18576       lgladdliftbincls (lgl, inner, -outer);
18577       assert (lglcntstk (&lgl->trail) == oldinner + 1);
18578       ok = lglbcp (lgl);
18579       if (ok) goto FIRST_OUTER_BRANCH_WIHOUT_INNER_PROBE;
18580       LOG (1, "conflict after propagating negation of 2nd inner branch");
18581       goto FIRST_OUTER_BRANCH_FAILED;
18582     }
18583     while (!lglmtstk (&saved)) {
18584       lit = lglpopstk (&saved);
18585       idx = abs (lit);
18586       val1 = lglsgn (lit);
18587       val2 = lglval (lgl, idx);
18588       if (val1 == val2) {
18589         assert (!reprs[0][idx]);
18590         reprs[0][idx] = val1;
18591         lglpushstk (lgl, &represented[0], idx);
18592       } else if (lit != inner && val1 == -val2) {
18593         assert (lit != -inner);
18594         repr = lglptrjmp (reprs[0], lgl->nvars-1, inner);
18595         other = lglptrjmp (reprs[0], lgl->nvars-1, lit);
18596         if (lglcmprepr (lgl, other, repr) < 0) SWAP (int, repr, other);
18597         if (other < 0) other = -other, repr = -repr;
18598         assert (!reprs[0][other]);
18599         reprs[0][other] = repr;
18600         lglpushstk (lgl, &represented[0], other);
18601       } else assert (lit == inner || !val2);
18602     }
18603     lglbacktrack (lgl, 1);
18604 END_OF_FIRST_OUTER_BRANCH:
18605     assert (lgl->level == 1);
18606 #ifndef NLGLOG
18607     {
18608       LOG (1, "start of 1st outer branch %d equivalences:", outer);
18609       for (i = 0; i < lglcntstk (&represented[0]); i++) {
18610         other = lglpeek (&represented[0], i);
18611         repr = reprs[0][other];
18612         LOG (1, "  1st branch equivalence %d : %d = %d", i + 1, other, repr);
18613       }
18614       LOG (1, "end of 1st outer branch %d equivalences.", outer);
18615     }
18616 #endif
18617     lglbacktrack (lgl, 0);
18618     assert (lglcntstk (&lgl->trail) == oldouter);
18619     lgl->stats->lift.probed0++;
18620     LOG (2, "2nd outer branch %d during lifting", -outer);
18621     lgliassume (lgl, -outer);
18622     ok = lglbcp (lgl);
18623     if (!ok) {
18624 SECOND_OUTER_BRANCH_FAILED:
18625       dom = lglprbana (lgl, -outer);
18626       LOG (1, "2nd branch outer failed literal %d during lifting", -outer);
18627       lgl->stats->lift.units++;
18628       lglbacktrack (lgl, 0);
18629       lglunit (lgl, -dom);
18630       if (lglbcp (lgl)) goto CONTINUE;
18631       assert (!lgl->mt);
18632       lgl->mt = 1;
18633       goto CONTINUE;
18634     }
18635     assert (lglmtstk (&represented[1]));
18636 #ifndef NDEBUG
18637     oldinner = lglcntstk (&lgl->trail);
18638 #endif
18639     if (!inner || lglval (lgl, inner))
18640       inner = lglinnerprobe (lgl, oldouter, &probes, &tmp2, 0);
18641     if (!inner) {
18642 SECOND_OUTER_BRANCH_WIHOUT_INNER_PROBE:
18643       LOG (2, "no inner probe for 2nd outer branch %d", -outer);
18644       for (i = oldouter; i < lglcntstk (&lgl->trail); i++) {
18645         lit = lglpeek (&lgl->trail, i);
18646         idx = abs (lit);
18647         assert (!reprs[1][idx]);
18648         reprs[1][idx] = lglsgn (lit);
18649         lglpushstk (lgl, &represented[1], idx);
18650       }
18651       assert (lgl->level == 1);
18652       goto END_OF_SECOND_BRANCH;
18653     }
18654     LOG (2, "1st inner branch %d in outer 2nd branch %d", inner, -outer);
18655     lgl->stats->lift.probed1++;
18656     lgliassume (lgl, inner);
18657     ok = lglbcp (lgl);
18658     if (!ok) {
18659       LOG (1, "1st inner branch failed literal %d on 2nd outer branch %d",
18660            inner, -outer);
18661       lglbacktrack (lgl, 1);
18662       assert (lglcntstk (&lgl->trail) == oldinner);
18663       lgladdliftbincls (lgl, -inner, outer);
18664       assert (lglcntstk (&lgl->trail) == oldinner + 1);
18665       ok = lglbcp (lgl);
18666       if (ok) goto SECOND_OUTER_BRANCH_WIHOUT_INNER_PROBE;
18667       LOG (1, "conflict after propagating negation of 1st inner branch");
18668       goto SECOND_OUTER_BRANCH_FAILED;
18669     }
18670     lglclnstk (&saved);
18671     for (i = oldouter; i < lglcntstk (&lgl->trail); i++)
18672       lglpushstk (lgl, &saved, lglpeek (&lgl->trail, i));
18673     LOG (3,
18674          "saved %d assignments of 1st inner branch %d in 2nd outer branch %d",
18675          lglcntstk (&saved), inner, -outer);
18676     lglbacktrack (lgl, 1);
18677     assert (lglcntstk (&lgl->trail) == oldinner);
18678     LOG (2, "2nd inner branch %d in 2nd outer branch %d", -inner, -outer);
18679     lgl->stats->lift.probed1++;
18680     lgliassume (lgl, -inner);
18681     ok = lglbcp (lgl);
18682     if (!ok) {
18683       LOG (1, "2nd inner branch failed literal %d on 2nd outer branch %d",
18684            -inner, -outer);
18685       lglbacktrack (lgl, 1);
18686       assert (lglcntstk (&lgl->trail) == oldinner);
18687       lgladdliftbincls (lgl, inner, outer);
18688       assert (lglcntstk (&lgl->trail) == oldinner + 1);
18689       ok = lglbcp (lgl);
18690       if (ok) goto SECOND_OUTER_BRANCH_WIHOUT_INNER_PROBE;
18691       LOG (1, "conflict after propagating negation of 2nd inner branch");
18692       goto SECOND_OUTER_BRANCH_FAILED;
18693     }
18694     while (!lglmtstk (&saved)) {
18695       lit = lglpopstk (&saved);
18696       idx = abs (lit);
18697       val1 = lglsgn (lit);
18698       val2 = lglval (lgl, idx);
18699       if (val1 == val2) {
18700         assert (!reprs[1][idx]);
18701         reprs[1][idx] = val1;
18702         lglpushstk (lgl, &represented[1], idx);
18703       } else if (lit != inner && val1 == -val2) {
18704         assert (lit != -inner);
18705         repr = lglptrjmp (reprs[1], lgl->nvars-1, inner);
18706         other = lglptrjmp (reprs[1], lgl->nvars-1, lit);
18707         if (lglcmprepr (lgl, other, repr) < 0) SWAP (int, repr, other);
18708         if (other < 0) other = -other, repr = -repr;
18709         assert (!reprs[1][other]);
18710         reprs[1][other] = repr;
18711         lglpushstk (lgl, &represented[1], other);
18712       } else assert (lit == inner || !val2);
18713     }
18714     lglbacktrack (lgl, 1);
18715 END_OF_SECOND_BRANCH:
18716     assert (lgl->level == 1);
18717 #ifndef NLGLOG
18718     {
18719       LOG (1, "start of 2nd outer branch %d equivalences:", -outer);
18720       for (i = 0; i < lglcntstk (&represented[1]); i++) {
18721         other = lglpeek (&represented[1], i);
18722         repr = reprs[1][other];
18723         LOG (1, "  2nd branch equivalence %d : %d = %d", i + 1, other, repr);
18724       }
18725       LOG (1, "end of 2nd outer branch %d equivalences.", outer);
18726     }
18727 #endif
18728     lglbacktrack (lgl, 0);
18729     for (branch = 0; branch <= 1; branch++) {
18730       assert (lglptrjmp (reprs[!branch], lgl->nvars-1, 1) == 1);
18731       assert (lglptrjmp (reprs[!branch], lgl->nvars-1, -1) == -1);
18732       for (i = 0; i < lglcntstk (&represented[branch]); i++) {
18733         lit1 = lglpeek (&represented[branch], i);
18734         assert (2 <= lit1 && lit1 < lgl->nvars);
18735         lit2 = reprs[branch][lit1];
18736         assert (lit2);
18737         if (abs (lit2) == 1) {
18738           val = lglval (lgl, lit1);
18739           assert (!val || val == lit2);
18740           if (val) continue;
18741           repr1 = lglptrjmp (reprs[!branch], lgl->nvars-1, lit1);
18742           if (repr1 != lit2) continue;
18743           LOG (1, "  common constant equivalence : %d = %d  (branch %d)",
18744                lit1, lit2, branch);
18745           lglunit (lgl, lit2*lit1);
18746           lgl->stats->lift.units++;
18747         } else {
18748           repr1 = lglptrjmp (reprs[2], lgl->nvars-1, lit1);
18749           repr2 = lglptrjmp (reprs[2], lgl->nvars-1, lit2);
18750           if (repr1 == repr2) continue;
18751           orepr1 = lglptrjmp (reprs[!branch], lgl->nvars-1, lit1);
18752           orepr2 = lglptrjmp (reprs[!branch], lgl->nvars-1, lit2);
18753           if (orepr1 != orepr2) continue;
18754           assert (abs (repr1) > 1 && abs (repr2) > 1);
18755           if (lglcmprepr (lgl, repr2, repr1) < 0) SWAP (int, repr1, repr2);
18756           if (repr2 < 0) repr2 = -repr2, repr1 = -repr1;
18757           LOG (2, "  common equivalence candidate : %d = %d   (branch %d)",
18758                repr2, repr1, branch);
18759           reprs[2][repr2] = repr1;
18760         }
18761       }
18762     }
18763     if (!lglbcp (lgl)) lgl->mt = 1;
18764 CONTINUE:
18765     assert (!lgl->level);
18766     lglcleanrepr (lgl, &represented[0], reprs[0]);
18767     lglcleanrepr (lgl, &represented[1], reprs[1]);
18768   }
18769   if (lgl->mt) goto DONE;
18770   for (idx = 2; idx < lgl->nvars; idx++)
18771     (void) lglptrjmp (reprs[2], lgl->nvars-1, idx);
18772   for (idx = 2; idx < lgl->nvars; idx++) {
18773     repr = lglptrjmp (reprs[2], lgl->nvars-1, idx);
18774     val = lglval (lgl, idx);
18775     if (!val) continue;
18776     if (repr == -val) {
18777       LOG (1, "inconsistent assigned members of equivalence classe");
18778       lgl->mt = 1;
18779       goto DONE;
18780     }
18781     if (repr < 0) repr = -repr, val = -val;
18782     if (repr == 1) { assert (val == 1); continue; }
18783     reprs[2][repr] = val;
18784   }
18785   for (idx = 2; idx < lgl->nvars; idx++) {
18786     repr = lglptrjmp (reprs[2], lgl->nvars-1, idx);
18787     assert (repr);
18788     assert (repr != -idx);
18789     if (repr == idx) continue;
18790     if (abs (repr) == 1) continue;
18791     lgl->stats->lift.eqs++;
18792     LOG (1, "  real common equivalence : %d = %d", idx, repr);
18793     lglimerge (lgl, idx, repr);
18794   }
18795 DONE:
18796   assert (origimpls <= lgl->stats->lift.impls);
18797   assert (origunits <= lgl->stats->lift.units);
18798   assert (origeqs <= lgl->stats->lift.eqs);
18799   impls = lgl->stats->lift.impls - origimpls;
18800   units = lgl->stats->lift.units - origunits;
18801   eqs = lgl->stats->lift.eqs - origeqs;
18802   lglprt (lgl, 1, "[lift-%d] %d units, %d impls, %d eqs in %d rounds",
18803      lgl->stats->lift.count, units, impls, eqs, round);
18804   assert (!lgl->level);
18805   DEL (reprs[0], lgl->nvars);
18806   DEL (reprs[1], lgl->nvars);
18807   DEL (reprs[2], lgl->nvars);
18808   lglrelstk (lgl, &probes);
18809   lglrelstk (lgl, &represented[0]);
18810   lglrelstk (lgl, &represented[1]);
18811   lglrelstk (lgl, &saved);
18812   lglrelstk (lgl, &tmp1);
18813   lglrelstk (lgl, &tmp2);
18814   if (lgl->mt) DEL (lgl->repr, lgl->nvars);
18815   return !lgl->mt;
18816 }
18817
18818 static int lglift (LGL * lgl) {
18819   int oldrem = lglrem (lgl), removed;
18820   assert (lgl->opts->lift.val);
18821   lglstart (lgl, &lgl->times->lft);
18822   assert (!lgl->lifting);
18823   lgl->lifting = 1;
18824   lgl->stats->lift.count++;
18825   assert (!lgl->simp);
18826   lgl->simp = 1;
18827   if (lgl->level > 0) lglbacktrack (lgl, 0);
18828   if (!lglbcp (lgl)) goto DONE;
18829   lglgc (lgl);
18830   if (lgl->mt) goto DONE;
18831   if (!lgliftaux (lgl)) { assert (lgl->mt); goto DONE; }
18832   if (!lglsynceqs (lgl)) { assert (lgl->mt); goto DONE; }
18833   lglchkred (lgl);
18834   lgldcpdis (lgl);
18835   lgldcpcln (lgl);
18836   lgldcpcon (lgl);
18837   lglcompact (lgl);
18838   lglmap (lgl);
18839   if (lgl->mt) goto DONE;
18840   if (!lglbcp (lgl)) goto DONE;
18841   lglcount (lgl);
18842   lglgc (lgl);
18843   if (lgl->mt) goto DONE;
18844   if (!lgl->mt) { lglpicosatchkall (lgl); lglpicosatrestart (lgl); }
18845 DONE:
18846   removed = oldrem - lglrem (lgl);
18847   LGLUPDPEN (lft, removed);
18848   assert (lgl->lifting && lgl->simp);
18849   lgl->lifting = lgl->simp = 0;
18850   lglprtlftrem (lgl);
18851   lglprt (lgl, 1 + !removed,
18852     "[lift-%d] removed %d variables", lgl->stats->lift.count, removed);
18853   lglrep (lgl, 2, '^');
18854   lglstop (lgl);
18855   return !lgl->mt;
18856 }
18857
18858 static int lgldstpull (LGL * lgl, int lit) {
18859   AVar * av;
18860   av = lglavar (lgl, lit);
18861   assert ((lit > 0) == av->wasfalse);
18862   if (av->mark) return 0;
18863   if (!lglevel (lgl, lit)) return 0;
18864   av->mark = 1;
18865   if (lgldecision (lgl, lit)) {
18866     lglpushstk (lgl, &lgl->clause, lit);
18867     LOG (3, "added %d to learned clause", lit);
18868   } else {
18869     lglpushstk (lgl, &lgl->seen, -lit);
18870     LOG (3, "pulled in distillation literal %d", -lit);
18871   }
18872   return 1;
18873 }
18874
18875 static int lglanalit (LGL * lgl, int lit) {
18876   int r0, r1, antecedents, other, next, tag, * p, * rsn;
18877   AVar * av;
18878   assert (lglmtstk (&lgl->seen));
18879   assert (lglmtstk (&lgl->clause));
18880   antecedents = 1;
18881   av = lglavar (lgl, lit);
18882   rsn = lglrsn (lgl, lit);
18883   r0 = rsn[0], r1 = rsn[1];
18884   LOGREASON (2, lit, r0, r1, "starting literal analysis for %d with", lit);
18885   LOG (3, "added %d to learned clause", lit);
18886   lglpushstk (lgl, &lgl->clause, lit);
18887   assert ((lit < 0) == av->wasfalse);
18888   assert (!av->mark);
18889   av->mark = 1;
18890   next = 0;
18891   for (;;) {
18892     tag = r0 & MASKCS;
18893     if (tag == BINCS || tag == TRNCS) {
18894       other = r0 >> RMSHFT;
18895       lgldstpull (lgl, other);
18896       if (tag == TRNCS) lgldstpull (lgl, r1);
18897     } else if (tag == UNITCS) assert (!lglevel (lgl, lit));
18898     else if (tag == DECISION) assert (lglavar (lgl, lit)->assumed);
18899     else {
18900       assert (tag == LRGCS);
18901       for (p = lglidx2lits (lgl, (r0 & REDCS), r1); (other = *p); p++)
18902         if (other != lit) lgldstpull (lgl, *p);
18903     }
18904     if (next == lglcntstk (&lgl->seen)) break;
18905     lit = lglpeek (&lgl->seen, next++);
18906     assert ((lit < 0) == lglavar (lgl, lit)->wasfalse);
18907     rsn = lglrsn (lgl, lit);
18908     r0 = rsn[0], r1 = rsn[1];
18909     LOGREASON (2, lit, r0, r1, "literal analysis of");
18910     antecedents++;
18911   }
18912   lglpopnunmarkstk (lgl, &lgl->seen);
18913   LOG (2, "literal analysis used %d antecedents", antecedents);
18914   assert (lglcntstk (&lgl->clause) >= 1);
18915   return antecedents;
18916 }
18917
18918 static int lglfailedass (LGL * lgl) {
18919   assert (lgl->level >= lgl->alevel);
18920   return lgl->level == lgl->alevel && lgl->failed;
18921 }
18922
18923 static void lglanafailed (LGL * lgl) {
18924   int ilit, elit, erepr, failed, size;
18925   unsigned bit, rbit, ibit, count;
18926   Ext * ext, * rext;
18927   const int * p;
18928   AVar * av;
18929   assert (lgl->mt || lglfailedass (lgl));
18930   if (lgl->mt) {
18931     LOG (1, "no failed assumptions since CNF unconditionally inconsistent");
18932   } else if ((failed = lgl->failed) == -1) {
18933     assert (!lgl->level);
18934     elit = 0;
18935     for (p = lgl->eassume.start; !elit && p < lgl->eassume.top; p++) {
18936       erepr = lglerepr (lgl, *p);
18937       if (lglederef (lgl, erepr) < 0) elit = *p;
18938     }
18939     assert (elit);
18940     LOG (1, "found single external failed assumption %d", elit);
18941     ext = lglelit2ext (lgl, elit);
18942     assert (!ext->failed);
18943     bit = 1u << (elit < 0);
18944     assert (ext->assumed & bit);
18945     ext->failed |= bit;
18946   } else {
18947     assert (abs (failed) > 1);
18948     if ((av = lglavar (lgl, failed))->assumed == 3) {
18949       LOG (1, "inconsistent internal assumptions %d and %d", failed, -failed);
18950       assert (!av->failed);
18951       av->failed = 3;
18952     } else {
18953       lglanalit (lgl, -failed);
18954       for (p = lgl->clause.start; p < lgl->clause.top; p++) {
18955         ilit = *p;
18956         av = lglavar (lgl, ilit);
18957         bit = (1u << (ilit > 0));
18958         assert (av->assumed & bit);
18959         assert (!(av->failed & bit));
18960         av->failed |= bit;
18961       }
18962       size = lglcntstk (&lgl->clause);
18963       assert (size > 0);
18964       lglpushstk (lgl, &lgl->clause, 0);
18965       lglprt (lgl, 2,
18966          "[analyze-final] learned clause with size %d out of %d",
18967          size, lglcntstk (&lgl->eassume));
18968       LOGCLS (2, lgl->clause.start, "failed assumption clause");
18969       lgldrupligaddcls (lgl, REDCS);
18970       lgladdcls (lgl, REDCS, size, 0);
18971       lglpopstk (&lgl->clause);
18972       lglpopnunmarkstk (lgl, &lgl->clause);
18973     }
18974     count = 0;
18975     for (p = lgl->eassume.start; p < lgl->eassume.top; p++) {
18976       elit =  *p;
18977       bit = 1u << (elit < 0);
18978       ext = lglelit2ext (lgl, elit);
18979       assert (!ext->eliminated && !ext->blocking);
18980       assert (ext->assumed & bit);
18981       if (ext->failed & bit) continue;
18982       if (ext->equiv) {
18983         erepr = ext->repr;
18984         rbit = bit;
18985         if (erepr < 0) rbit ^= 3;
18986         if (elit < 0) erepr = -erepr;
18987         rext = lglelit2ext (lgl, erepr);
18988         assert (!rext->equiv);
18989         if (rext->failed & rbit) continue;
18990         ilit = rext->repr;
18991         ibit = rbit;
18992         if (ilit < 0) ilit = -ilit, ibit ^= 3;
18993         if (ilit == 1) continue;
18994         assert (ilit && ilit != -1);
18995         av = lglavar (lgl, ilit);
18996         if (!(av->failed & ibit)) continue;
18997         rext->failed |= rbit;
18998         count++;
18999         if (rext->assumed & rbit) {
19000           LOG (2,
19001                "found representative external failed assumption %d",
19002                erepr);
19003         } else {
19004           LOG (2,
19005                "found non representative external failed assumption %d",
19006                elit);
19007           ext->failed |= bit;
19008         }
19009       } else {
19010         ilit = ext->repr;
19011         ibit = bit;
19012         if (ilit < 0) ilit = -ilit, ibit ^= 3;
19013         if (ilit == 1) continue;
19014         assert (ilit && ilit != -1);
19015         av = lglavar (lgl, ilit);
19016         if (!(av->failed & ibit)) continue;
19017         LOG (2, "found external failed assumption %d", elit);
19018         ext->failed |= bit;
19019         count++;
19020       }
19021     }
19022     LOG (1, "found %u external failed assumptions", count);
19023   }
19024   TRANS (FAILED);
19025 }
19026
19027 static void lglternreslit (LGL * lgl, int lit) {
19028   int * pw, * peow, * nw, * neow, * p, * n;
19029   int pblit, ptag, pother, pother2, pdelta;
19030   int nblit, ntag, nother, nother2, ndelta;
19031   HTS * phts, * nhts;
19032   int a, b, c;
19033
19034   phts = lglhts (lgl, lit);
19035   pw = lglhts2wchs (lgl, phts);
19036   peow = pw + phts->count;
19037   nhts = lglhts (lgl, -lit);
19038   nw = lglhts2wchs (lgl, nhts);
19039   neow = nw + nhts->count;
19040   for (n = nw; n < neow; n++) {
19041     if (INCSTEPS (trnr.steps) >= lgl->limits->trnr.steps) return;
19042     nblit = *n;
19043     ntag = nblit & MASKCS;
19044     if (ntag == BINCS || ntag == OCCS) continue;
19045     if (ntag == TRNCS) break;
19046     assert (ntag == LRGCS);
19047     n++;
19048   }
19049   if (n >= neow) return;
19050   for (p = pw;
19051        p < peow && lgl->stats->trnr.steps < lgl->limits->trnr.steps;
19052        p++) {
19053     INCSTEPS (trnr.steps);
19054     pblit = *p;
19055     ptag = pblit & MASKCS;
19056     if (ptag == BINCS || ptag == OCCS) continue;
19057     if (ptag == TRNCS || ptag == LRGCS) p++;
19058     if (ptag == LRGCS) continue;
19059     assert (ptag == TRNCS);
19060     pother = pblit >> RMSHFT;
19061     if (lglval (lgl, pother)) continue;
19062     pother2 = *p;
19063     if (lglval (lgl, pother2)) continue;
19064     for (n = nw;
19065          n < neow && lgl->stats->trnr.steps < lgl->limits->trnr.steps;
19066          n++) {
19067       INCSTEPS (trnr.steps);
19068       nblit = *n;
19069       ntag = nblit & MASKCS;
19070       if (ntag == BINCS || ntag == OCCS) continue;
19071       if (ntag == TRNCS || ntag == LRGCS) n++;
19072       if (ntag == LRGCS) continue;
19073       assert (ntag == TRNCS);
19074       nother = nblit >> RMSHFT;
19075       if (lglval (lgl, nother)) continue;
19076       nother2 = *n;
19077       if (lglval (lgl, nother2)) continue;
19078       if ((nother == pother && nother2 == pother2) ||
19079           (nother == pother2 && nother2 == pother)) {
19080         a = nother, b = nother2;
19081         if (lglhasbin (lgl, a, b)) continue;
19082         lgl->stats->trnr.bin++;
19083         LOG (2, "ternary resolvent %d %d", a, b);
19084         if (lgl->opts->drup.val) lgldrupclsarg (lgl, a, b, 0);
19085 #ifndef NLGLPICOSAT
19086         lglpicosatchkclsarg (lgl, a, b, 0);
19087 #endif
19088         lglwchbin (lgl, a, b, REDCS);
19089         lglwchbin (lgl, b, a, REDCS);
19090         lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
19091         lglwrktouch (lgl, a);
19092         lglwrktouch (lgl, b);
19093       } else {
19094         a = nother, b = nother2;
19095         if (nother == pother || nother2 == pother) c = pother2;
19096         else if (nother == pother2 || nother2 == pother2) c = pother;
19097         else continue;
19098         assert (a != b && b != c && a != c);
19099         assert (a != -b);
19100         if (a == -c || b == -c) continue;
19101         if (lglhastrn (lgl, a, b, c)) continue;
19102         lgl->stats->trnr.trn++;
19103         LOG (2, "ternary resolvent %d %d %d", a, b, c);
19104         if (lgl->opts->drup.val) lgldrupclsarg (lgl, a, b, c, 0);
19105 #ifndef NLGLPICOSAT
19106         lglpicosatchkclsarg (lgl, a, b, c, 0);
19107 #endif
19108         lglwchtrn (lgl, a, b, c, REDCS);
19109         lglwchtrn (lgl, b, a, c, REDCS);
19110         lglwchtrn (lgl, c, a, b, REDCS);
19111         lgl->stats->red.trn++, assert (lgl->stats->red.trn > 0);
19112         lglwrktouch (lgl, a);
19113         lglwrktouch (lgl, b);
19114         lglwrktouch (lgl, c);
19115       }
19116       pdelta = p - pw;
19117       phts = lglhts (lgl, lit);
19118       pw = lglhts2wchs (lgl, phts);
19119       peow = pw + phts->count;
19120       p = pw + pdelta;
19121       ndelta = n - nw;
19122       nhts = lglhts (lgl, -lit);
19123       nw = lglhts2wchs (lgl, nhts);
19124       neow = nw + nhts->count;
19125       n = nw + ndelta;
19126     }
19127   }
19128 }
19129
19130 static void lglternresidx (LGL * lgl, int idx) {
19131   lglternreslit (lgl, idx);
19132   lglternreslit (lgl, -idx);
19133 }
19134
19135 static void lglseternreslim (LGL * lgl) {
19136   int64_t limit, irrlim;
19137   int pen;
19138   if (lgl->opts->ternresrtc.val) {
19139     lgl->limits->trnr.steps = LLMAX;
19140     lglprt (lgl, 1, "[ternres-%d] no limit (run to completion)",
19141             lgl->stats->trnr.count);
19142   } else {
19143     limit = (lgl->opts->trnreleff.val*lglvisearch (lgl))/1000;
19144     if (limit < lgl->opts->trnrmineff.val) limit = lgl->opts->trnrmineff.val;
19145     if (lgl->opts->trnrmaxeff.val >= 0 && limit > lgl->opts->trnrmaxeff.val)
19146       limit = lgl->opts->trnrmaxeff.val;
19147     if (lgl->stats->trnr.count <= 1 &&
19148         lgl->opts->boost.val &&
19149         lgl->opts->ternresboost.val > 1) {
19150       lglprt (lgl, 1,
19151         "[ternres-%d] boosting ternary resolution limit by %d",
19152         lgl->stats->trnr.count, lgl->opts->ternresboost.val);
19153       limit *= lgl->opts->ternresboost.val;
19154     }
19155     limit >>= (pen = lgl->limits->trnr.pen + lglszpen (lgl));
19156     irrlim = 4*lgl->stats->irr.clauses.cur;
19157     irrlim >>= lgl->limits->simp.pen;
19158     if (lgl->opts->irrlim.val && limit < irrlim) {
19159       limit = irrlim;
19160       lglprt (lgl, 1,
19161         "[ternres-%d] limit %lld based on %d irredundant clauses",
19162         lgl->stats->trnr.count, (LGLL) limit, lgl->stats->irr.clauses.cur);
19163     } else
19164       lglprt (lgl, 1, "[ternres-%d] limit %lld with penalty %d = %d + %d",
19165         lgl->stats->trnr.count, (LGLL) limit,
19166         pen, lgl->limits->trnr.pen, lglszpen (lgl));
19167     lgl->limits->trnr.steps = lgl->stats->trnr.steps + limit;
19168   }
19169 }
19170
19171 static void lglprternresrem (LGL * lgl) {
19172   int idx, ret = 0, rem = 0;
19173   for (idx = 2; idx < lgl->nvars; idx++) {
19174     if (!lglisfree (lgl, idx)) continue;
19175     if (lglavar (lgl, idx)->donoternres) ret++; else rem++;
19176   }
19177   if (rem)
19178     lglprt (lgl, 1, "[ternres-%d] %d variables remain %.0f%% (%d retained)",
19179             lgl->stats->trnr.count, rem, lglpcnt (rem, lglrem (lgl)), ret);
19180   else {
19181     lglprt (lgl, 1, "[ternres-%d] fully completed ternary resolution",
19182             lgl->stats->trnr.count);
19183     for (idx = 2; idx < lgl->nvars; idx++)
19184       lglavar (lgl, idx)->donoternres = 0;
19185   }
19186 }
19187
19188 static void lglternresinit (LGL * lgl) {
19189   int idx, schedulable = 0, donoternres = 0;
19190   lglwrkinit (lgl, 1, 1);
19191   for (idx = 2; idx < lgl->nvars; idx++) {
19192     if (!lglisfree (lgl, idx)) continue;
19193     if (lglavar (lgl, idx)->donoternres) donoternres++;
19194     else schedulable++;
19195   }
19196   if (!schedulable) {
19197     donoternres = 0;
19198     for (idx = 2; idx < lgl->nvars; idx++) {
19199       if (!lglisfree (lgl, idx)) continue;
19200       lglavar (lgl, idx)->donoternres = 0;
19201       schedulable++;
19202     }
19203   }
19204   if (!donoternres)
19205     lglprt (lgl, 1, "[ternres-%d] all %d free variables schedulable",
19206             lgl->stats->trnr.count, schedulable);
19207   else
19208     lglprt (lgl, 1,
19209       "[ternres-%d] %d schedulable variables %.0f%%",
19210       lgl->stats->trnr.count, schedulable, lglpcnt (schedulable, lgl->nvars-2));
19211   assert (!lgl->donotsched), lgl->donotsched = 1;
19212   lglrandidxtrav (lgl, lglwrktouch);
19213   assert (lgl->donotsched), lgl->donotsched = 0;
19214 }
19215
19216 static int lglternres (LGL * lgl) {
19217   int before, after, delta;
19218   int before2, after2, delta2;
19219   int before3, after3, delta3;
19220   int success, lit;
19221   if (lgl->nvars <= 2) return 1;
19222   lglstart (lgl, &lgl->times->trn);
19223   ASSERT (!lgl->simp && !lgl->ternresing);
19224   lgl->simp = lgl->ternresing = 1;
19225   lgl->stats->trnr.count++;
19226   if (lgl->level > 0) lglbacktrack (lgl, 0);
19227   lglseternreslim (lgl);
19228
19229   lglternresinit (lgl);
19230
19231   before2 = lgl->stats->trnr.bin;
19232   before3 = lgl->stats->trnr.trn;
19233   while (lgl->stats->trnr.steps < lgl->limits->trnr.steps) {
19234     if (lglterminate (lgl)) break;
19235     if (!lglsyncunits (lgl)) break;
19236     if (!(lit = lglwrknext (lgl))) {
19237       lglprt (lgl, 2,  "[ternres-%d] saturated", lgl->stats->trnr.count);
19238       break;
19239     }
19240     INCSTEPS (trnr.steps);
19241     assert (lit > 0);
19242     if (!lglisfree (lgl, lit)) continue;
19243     lglavar (lgl, lit)->donoternres = 1;
19244     lglternresidx (lgl, lit);
19245   }
19246   after2 = lgl->stats->trnr.bin;
19247   after3 = lgl->stats->trnr.trn;
19248   after = after2 + after3;
19249   before = before2 + before3;
19250   delta2 = after2 - before2;
19251   delta3 = after3 - before3;
19252   delta = after - before;
19253   success = before < after;
19254   lglprt (lgl, 1, "[ternres-%d] %d ternary resolvents (%d bin, %d trn)",
19255           lgl->stats->trnr.count, delta, delta2, delta3);
19256   LGLUPDPEN (trnr, success);
19257   assert (lgl->simp && lgl->ternresing);
19258   lgl->simp = lgl->ternresing = 0;
19259   lglprternresrem (lgl);
19260   lglrep (lgl, 2, 'T');
19261   lglwrkreset (lgl);
19262   lglstop (lgl);
19263   return !lgl->mt;
19264 }
19265
19266 static int lgltrdbin (LGL * lgl, int start, int target, int irr) {
19267   int lit, next, blit, tag, red, other, * p, * w, * eow, res, ign, val;
19268   HTS * hts;
19269   assert (lglmtstk (&lgl->seen));
19270   assert (abs (start) < abs (target));
19271   LOG (2, "trying transitive reduction of %s binary clause %d %d",
19272        lglred2str (irr^REDCS), start, target);
19273   lgl->stats->trd.bins++;
19274   lglpushnmarkseen (lgl, -start);
19275   next = 0;
19276   res = 0;
19277   ign = 1;
19278   while (next < lglcntstk (&lgl->seen)) {
19279     lit = lglpeek (&lgl->seen, next++);
19280     INCSTEPS (trd.steps);
19281     LOG (3, "transitive reduction search step %d", lit);
19282     val = lglval (lgl, lit);
19283     if (val) continue;
19284     hts = lglhts (lgl, -lit);
19285     if (!hts->count) continue;
19286     w = lglhts2wchs (lgl, hts);
19287     eow = w + hts->count;
19288     for (p = w; p < eow; p++) {
19289       blit = *p;
19290       tag = blit & MASKCS;
19291       if (tag == LRGCS || tag == TRNCS) p++;
19292       if (tag != BINCS) continue;
19293       red = blit & REDCS;
19294       if (irr && red) continue;
19295       other = blit >> RMSHFT;
19296       if (other == start) continue;
19297       if (other == target) {
19298         if (lit == -start && ign) { ign = 0; continue; }
19299         LOG (2, "transitive path closed with %s binary clause %d %d",
19300              lglred2str (red), -lit, other);
19301         res = 1;
19302         goto DONE;
19303       }
19304       val = lglmarked (lgl, other);
19305       if (val > 0) continue;
19306       if (val < 0) {
19307         assert (lgl->level == 0);
19308         lgl->stats->trd.failed++;
19309         LOG (1, "failed literal %d in transitive reduction", -start);
19310         lglunit (lgl, start);
19311         val = lglbcp (lgl);
19312         if (!val && !lgl->mt) lgl->mt = 1;
19313         assert (val || lgl->mt);
19314         res = -1;
19315         goto DONE;
19316       }
19317       lglpushnmarkseen (lgl, other);
19318       LOG (3, "transitive reduction follows %s binary clause %d %d",
19319            lglred2str (red), -lit, other);
19320     }
19321   }
19322 DONE:
19323   lglpopnunmarkstk (lgl, &lgl->seen);
19324   return res;
19325 }
19326
19327 static void lgltrdlit (LGL * lgl, int start) {
19328   int target, * w, * p, * eow, blit, tag, red, val;
19329 #ifndef NDEBUG
19330   int unassigned = lgl->unassigned;
19331 #endif
19332   HTS * hts;
19333   val = lglval (lgl, start);
19334   if (val) return;
19335   LOG (2, "transitive reduction of binary clauses with %d", start);
19336   assert (lglmtstk (&lgl->seen));
19337   hts = lglhts (lgl, start);
19338   if (!hts->count) return;
19339   lgl->stats->trd.lits++;
19340   w = lglhts2wchs (lgl, hts);
19341   eow = w + hts->count;
19342   for (p = w;
19343        p < eow && (lgl->stats->trd.steps < lgl->limits->trd.steps);
19344        p++) {
19345     blit = *p;
19346     tag = blit & MASKCS;
19347     if (tag == TRNCS || tag == LRGCS) p++;
19348     if (tag != BINCS) continue;
19349     target = blit >> RMSHFT;
19350     if (abs (start) > abs (target)) continue;
19351     red = blit & REDCS;
19352     val = lgltrdbin (lgl, start, target, red^REDCS);
19353     if (!val) continue;
19354     if (val < 0) { assert (lgl->mt || lgl->unassigned < unassigned); break; }
19355     LOG (2, "removing transitive redundant %s binary clause %d %d",
19356          lglred2str (red), start, target);
19357     lgl->stats->trd.red++;
19358     lgl->stats->prgss++;
19359     lglrmbwch (lgl, start, target, red);
19360     lglrmbwch (lgl, target, start, red);
19361     assert (!lgl->dense);
19362     if (red) assert (lgl->stats->red.bin > 0), lgl->stats->red.bin--;
19363     else lgldecirr (lgl, 2);
19364     break;
19365   }
19366 }
19367
19368 static void lglsetrdlim (LGL * lgl) {
19369   int64_t limit, irrlim;
19370   int pen;
19371   limit = (lgl->opts->trdreleff.val*lglvisearch (lgl))/1000;
19372   if (limit < lgl->opts->trdmineff.val) limit = lgl->opts->trdmineff.val;
19373   if (lgl->opts->trdmaxeff.val >= 0 && limit > lgl->opts->trdmaxeff.val)
19374     limit = lgl->opts->trdmaxeff.val;
19375   limit >>= (pen = lgl->limits->trd.pen + lglszpen (lgl));
19376   irrlim = lgl->stats->irr.clauses.cur;
19377   irrlim >>= lgl->limits->simp.pen;
19378   if (lgl->opts->irrlim.val && limit < irrlim) {
19379     limit = irrlim;
19380     lglprt (lgl, 1,
19381       "[transred-%d] limit %lld based on %d irredundant clauses",
19382       lgl->stats->trd.count, (LGLL) limit, lgl->stats->irr.clauses.cur);
19383   } else
19384     lglprt (lgl, 1, "[transred-%d] limit %lld with penalty %d = %d + %d",
19385       lgl->stats->trd.count, (LGLL) limit,
19386       pen, lgl->limits->trd.pen, lglszpen (lgl));
19387   lgl->limits->trd.steps = lgl->stats->trd.steps + limit;
19388 }
19389
19390 static int lgltrd (LGL * lgl) {
19391   unsigned pos, delta, mod, ulit, first, last;
19392   int failed = lgl->stats->trd.failed;
19393   int red = lgl->stats->trd.red;
19394   int lit, count, success;
19395   if (lgl->nvars <= 2) return 1;
19396   lgl->stats->trd.count++;
19397   lglstart (lgl, &lgl->times->trd);
19398   assert (!lgl->simp);
19399   lgl->simp = 1;
19400   if (lgl->level > 0) lglbacktrack (lgl, 0);
19401   lglsetrdlim (lgl);
19402   mod = 2*(lgl->nvars - 2);
19403   assert (mod > 0);
19404   pos = lglrand (lgl) % mod;
19405   delta = lglrand (lgl) % mod;
19406   if (!delta) delta++;
19407   while (lglgcd (delta, mod) > 1)
19408     if (++delta == mod) delta = 1;
19409   LOG (1, "transitive reduction start %u delta %u mod %u", pos, delta, mod);
19410   first = mod;
19411   count = 0;
19412   while (lgl->stats->trd.steps < lgl->limits->trd.steps) {
19413     if (lglterminate (lgl)) break;
19414     if (!lglsyncunits (lgl)) break;
19415     ulit = pos + 4;
19416     lit = lglilit (ulit);
19417     lgltrdlit (lgl, lit);
19418     count++;
19419     assert (count <= mod);
19420     if (lgl->mt) break;
19421     last = pos;
19422     pos += delta;
19423     if (pos >= mod) pos -= mod;
19424     if (pos == first) { assert (count == mod); break; }
19425     if (mod == 1) break;
19426     if (first == mod) first = last;
19427   }
19428   failed = lgl->stats->trd.failed - failed;
19429   red = lgl->stats->trd.red - red;
19430   success = failed || red;
19431   LGLUPDPEN (trd, success);
19432   assert (lgl->simp);
19433   lglprt (lgl, 1,
19434     "[transred-%d] removed %d transitive binary clauses",
19435     lgl->stats->trd.count, red);
19436   lglprt (lgl, 1 + !failed,
19437     "[transred-%d] found %d units",
19438     lgl->stats->trd.count, failed);
19439   lgl->simp = 0;
19440   lglrep (lgl, 2, 't');
19441   lglstop (lgl);
19442   return !lgl->mt;
19443 }
19444
19445 static int lglunhdhasbins (LGL * lgl, const DFPR * dfpr,
19446                            int lit, int irronly) {
19447   int blit, tag, other, val, red, ulit;
19448   const int * p, * w, * eos;
19449   HTS * hts;
19450   assert (!lglval (lgl, lit));
19451   hts = lglhts (lgl, lit);
19452   w = lglhts2wchs (lgl, hts);
19453   eos = w + hts->count;
19454   for (p = w; p < eos; p++) {
19455     blit = *p;
19456     tag = blit & MASKCS;
19457     if (tag == OCCS) continue;
19458     if (tag == TRNCS || tag == LRGCS) { p++; continue; }
19459     red = blit & REDCS;
19460     if (irronly && red) continue;
19461     other = blit >> RMSHFT;
19462     val = lglval (lgl, other);
19463     assert (val >= 0);
19464     if (val > 0) continue;
19465     ulit = lglulit (other);
19466     if (!dfpr[ulit].discovered) return 1;
19467   }
19468   return 0;
19469 }
19470
19471 static int lglunhdisroot (LGL * lgl, int lit, DFPR * dfpr, int irronly) {
19472   int res = !lglunhdhasbins (lgl, dfpr, lit, irronly);
19473   assert (!res || !dfpr[lglulit (lit)].discovered);
19474   return res;
19475 }
19476
19477 static int lglmtwtk (Wtk * wtk) { return wtk->top == wtk->start; }
19478
19479 static int lglfullwtk (Wtk * wtk) { return wtk->top == wtk->end; }
19480
19481 static int lglsizewtk (Wtk * wtk) { return wtk->end - wtk->start; }
19482
19483 static int lglcntwtk (Wtk * wtk) { return wtk->top - wtk->start; }
19484
19485 static void lglrelwtk (LGL * lgl, Wtk * wtk) {
19486   DEL (wtk->start, lglsizewtk (wtk));
19487   memset (wtk, 0, sizeof *wtk);
19488 }
19489
19490 static void lglenlwtk (LGL * lgl, Wtk * wtk) {
19491   int oldsize = lglsizewtk (wtk);
19492   int newsize = oldsize ? 2*oldsize : 1;
19493   int count = lglcntwtk (wtk);
19494   RSZ (wtk->start, oldsize, newsize);
19495   wtk->top = wtk->start + count;
19496   wtk->end = wtk->start + newsize;
19497 }
19498
19499 static void lglpushwtk (LGL * lgl, Wtk * wtk,
19500                         Wrag wrag, int lit, int other, int red) {
19501   Work w;
19502   if (lglfullwtk (wtk)) lglenlwtk (lgl, wtk);
19503   w.wrag = wrag;
19504   w.other = other;
19505   w.red = red ? 1 : 0;
19506   w.removed = 0;
19507   w.lit = lit;
19508   *wtk->top++ = w;
19509 }
19510
19511 static int lglstamp (LGL * lgl, int root,
19512                      DFPR * dfpr, DFOPF * dfopf,
19513                      Wtk * work, Stk * units, Stk * sccs, Stk * trds,
19514                      int * visitedptr, int stamp, int irronly) {
19515   int uroot, lit, ulit, blit, tag, red, other, failed, uother, unotother;
19516   int observed, discovered, pos, undiscovered;
19517   unsigned start, end, mod, i, j, sccsize;
19518   const int * p, * w, * eos;
19519   int startstamp;
19520   const Work * r;
19521   int removed;
19522   HTS * hts;
19523   Wrag wrag;
19524   if (lglval (lgl, root)) return stamp;
19525   uroot =  lglulit (root);
19526   if (dfpr[uroot].discovered) return stamp;
19527   assert (!dfpr[uroot].finished);
19528   assert (lglmtwtk (work));
19529   assert (lglmtstk (units));
19530   assert (lglmtstk (sccs));
19531   assert (lglmtstk (trds));
19532   LOG (3, "stamping dfs %s %d %s",
19533        (lglunhdisroot (lgl, root, dfpr, irronly) ? "root" : "start"), root,
19534        irronly ? "only over irredundant clauses" :
19535                  "also over redundant clauses");
19536   startstamp = 0;
19537   lglpushwtk (lgl, work, PREFIX, root, 0, 0);
19538   while (!lglmtwtk (work)) {
19539     INCSTEPS (unhd.steps);
19540     LGLPOPWTK (work, wrag, lit, other, red, removed);
19541     if (removed) continue;
19542     if (wrag == PREFIX) {
19543       ulit = lglulit (lit);
19544       if (dfpr[ulit].discovered) {
19545         dfopf[ulit].observed = stamp;
19546         LOG (3, "stamping %d observed %d", lit, stamp);
19547         continue;
19548       }
19549       assert (!dfpr[ulit].finished);
19550       dfpr[ulit].discovered = ++stamp;
19551       dfopf[ulit].observed = stamp;
19552       LOG (3, "stamping %d observed %d", lit, stamp);
19553       *visitedptr += 1;
19554       if (!startstamp) {
19555         startstamp = stamp;
19556         LOG (3, "root %d with stamp %d", lit, startstamp);
19557         dfpr[ulit].root = lit;
19558         LOG (4, "stamping %d root %d", lit, lit);
19559         assert (!dfpr[ulit].parent);
19560         LOG (4, "stamping %d parent %d", lit, 0);
19561       }
19562       LOG (4, "stamping %d discovered %d", lit, stamp);
19563       lglpushwtk (lgl, work, POSTFIX, lit, 0, 0);
19564       assert (dfopf[ulit].pushed < 0);
19565       dfopf[ulit].pushed = lglcntwtk (work);
19566       assert (!dfopf[ulit].flag);
19567       dfopf[ulit].flag = 1;
19568       lglpushstk (lgl, sccs, lit);
19569       hts = lglhts (lgl, -lit);
19570       w = lglhts2wchs (lgl, hts);
19571       eos = w + hts->count;
19572       for (undiscovered = 0; undiscovered <= 1 ; undiscovered++) {
19573         start = lglcntwtk (work);
19574         for (p = w; p < eos; p++) {
19575           blit = *p;
19576           tag = blit & MASKCS;
19577           if (tag == OCCS) continue;
19578           if (tag == TRNCS || tag == LRGCS) { p++; continue; }
19579           assert (tag == BINCS);
19580           red = blit & REDCS;
19581           if (irronly && red) continue;
19582           other = blit >> RMSHFT;
19583           if (lglval (lgl, other)) continue;
19584           uother = lglulit (other);
19585           if (undiscovered != !dfpr[uother].discovered) continue;
19586           // Kind of defensive, since 'lglrmbindup' should avoid it
19587           // and this fix may not really work anyhow since it does
19588           // not distinguish between irredundant and redundant clauses.
19589           // Thus we put a hard COVER here.
19590           COVER (lglsignedmarked (lgl, other) > 0);
19591           if (lglsignedmarked (lgl, other) > 0) {
19592             LOG (2, "stamping skips duplicated edge %d %d", lit, other);
19593             continue;
19594           }
19595           lglsignedmark (lgl, other);
19596           lglpushwtk (lgl, work, BEFORE, lit, other, red);
19597         }
19598         end = lglcntwtk (work);
19599         for (r = work->start + start; r < work->top; r++)
19600           lglunmark (lgl, r->other);
19601         mod = (end - start);
19602         if (mod <= 1) continue;
19603         for (i = start; i < end - 1;  i++) {
19604           assert (1 < mod && mod == (end - i));
19605           j = lglrand (lgl) % mod--;
19606           if (!j) continue;
19607           j = i + j;
19608           SWAP (Work, work->start[i], work->start[j]);
19609         }
19610       }
19611     } else if (wrag == BEFORE) {        // before recursive call
19612       LOG (2, "stamping edge %d %d before recursion", lit, other);
19613       lglpushwtk (lgl, work, AFTER, lit, other, red);
19614       ulit = lglulit (lit);
19615       uother = lglulit (other);
19616       unotother = lglulit (-other);
19617       if (lgl->opts->unhdextstamp.val && (irronly || red) &&
19618           dfopf[uother].observed > dfpr[ulit].discovered) {
19619         LOG (2, "transitive edge %d %d during stamping", lit, other);
19620         lgl->stats->unhd.stamp.trds++;
19621         lgl->stats->prgss++;
19622         if (red) lgl->stats->unhd.tauts.red++;
19623         lglrmbcls (lgl, -lit, other, red);
19624         if ((pos = dfopf[unotother].pushed) >= 0) {
19625           while (pos  < lglcntwtk (work)) {
19626             if (work->start[pos].lit != -other) break;
19627             if (work->start[pos].other == -lit) {
19628               LOG (3, "removing edge %d %d from DFS stack", -other, -lit);
19629               work->start[pos].removed = 1;
19630             }
19631             pos++;
19632           }
19633         }
19634         work->top--;
19635         assert (dfpr[uother].discovered); // and thus 'parent' + 'root' set
19636         continue;
19637       }
19638       observed = dfopf[unotother].observed;
19639       if (lgl->opts->unhdextstamp.val && startstamp <= observed) {
19640         LOG (1, "stamping failing edge %d %d", lit, other);
19641         for (failed = lit;
19642              dfpr[lglulit (failed)].discovered > observed;
19643              failed = dfpr[lglulit (failed)].parent)
19644           assert (failed);
19645         LOG (1, "stamping failed literal %d", failed);
19646         lglpushstk (lgl, units, -failed);
19647         lgl->stats->unhd.stamp.failed++;
19648         if (dfpr[unotother].discovered && !dfpr[unotother].finished) {
19649           LOG (2, "stamping skips edge %d %d after failed literal %d",
19650                lit, other, failed);
19651           work->top--;
19652           continue;
19653         }
19654       }
19655       if (!dfpr[uother].discovered) {
19656         dfpr[uother].parent = lit;
19657         LOG (4, "stamping %d parent %d", other, lit);
19658         dfpr[uother].root = root;
19659         LOG (4, "stamping %d root %d", other, root);
19660         lglpushwtk (lgl, work, PREFIX, other, 0, 0);
19661       }
19662     } else if (wrag == AFTER) {         // after recursive call
19663       LOG (2, "stamping edge %d %d after recursion", lit, other);
19664       uother = lglulit (other);
19665       ulit = lglulit (lit);
19666       if (lgl->opts->unhdextstamp.val && !dfpr[uother].finished &&
19667           dfpr[uother].discovered < dfpr[ulit].discovered) {
19668         LOG (2, "stamping back edge %d %d", lit, other);
19669         dfpr[ulit].discovered = dfpr[uother].discovered;
19670         LOG (3, "stamping %d reduced discovered to %d",
19671              lit, dfpr[ulit].discovered);
19672         if (dfopf[ulit].flag) {
19673           LOG (2, "stamping %d as being part of a non-trivial SCC", lit);
19674           dfopf[ulit].flag = 0;
19675         }
19676       }
19677       dfopf[uother].observed = stamp;
19678       LOG (3, "stamping %d observed %d", other, stamp);
19679     } else {
19680       assert (wrag == POSTFIX);
19681       LOG (2, "stamping postfix %d", lit);
19682       ulit = lglulit (lit);
19683       if (dfopf[ulit].flag) {
19684         stamp++;
19685         sccsize = 0;
19686         discovered = dfpr[ulit].discovered;
19687         do {
19688           other = lglpopstk (sccs);
19689           uother = lglulit (other);
19690           dfopf[uother].pushed = -1;
19691           dfopf[uother].flag = 0;
19692           dfpr[uother].discovered = discovered;
19693           dfpr[uother].finished = stamp;
19694           LOG (3, "stamping %d interval %d %d parent %d root %d",
19695                other, dfpr[uother].discovered, dfpr[uother].finished,
19696                dfpr[uother].parent, dfpr[uother].root);
19697           sccsize++;
19698         } while (other != lit);
19699         assert (lgl->opts->unhdextstamp.val || sccsize == 1);
19700         if (sccsize > 1) {
19701           LOG (2, "stamping non trivial SCC of size %d", sccsize);
19702           lgl->stats->unhd.stamp.sumsccsizes += sccsize;
19703           lgl->stats->unhd.stamp.sccs++;
19704         }
19705       } else assert (lgl->opts->unhdextstamp.val);
19706     }
19707   }
19708   assert (lglmtwtk (work));
19709   assert (lglmtstk (sccs));
19710   return stamp;
19711 }
19712
19713 static int lglunhlca (LGL * lgl, const DFPR * dfpr, int a, int b) {
19714   const DFPR * c, * d;
19715   int u, v, p;
19716   if (a == b) return a;
19717   u = lglulit (a), v = lglulit (b);
19718   c = dfpr + u, d = dfpr + v;
19719   if (c->discovered <= d->discovered) {
19720     p = a;
19721   } else {
19722     assert (c->discovered > d->discovered);
19723     p = b;
19724     SWAP (const DFPR *, c, d);
19725   }
19726   for (;;) {
19727     assert (c->discovered <= d->discovered);
19728     if (d->finished <= c->finished) break;
19729     p = c->parent;
19730     if (!p) break;
19731     u = lglulit (p);
19732     c = dfpr + u;
19733   }
19734   LOG (3, "unhiding least common ancestor of %d and %d is %d", a, b, p);
19735   return p;
19736 }
19737
19738 static int lglunhidefailed (LGL * lgl, const DFPR * dfpr) {
19739   int idx, sign, lit, unit, nfailed = 0;
19740   for (idx = 2; idx < lgl->nvars; idx++) {
19741     for (sign = -1; sign <= 1; sign += 2) {
19742       if (lglterminate (lgl)) return 0;
19743       if (!lglsyncunits (lgl)) return 0;
19744       INCSTEPS (unhd.steps);
19745       lit = sign * idx;
19746       if (lglval (lgl, lit)) continue;
19747       if (!dfpr[lglulit (lit)].discovered) continue;
19748       if (lglunhimplincl (dfpr, lit, -lit)) {
19749         unit = -lit;
19750         LOG (2, "unhiding %d implies %d", lit, -lit);
19751       } else if (lglunhimplincl (dfpr, -lit, lit)) {
19752         unit = lit;
19753         LOG (2, "unhiding %d implies %d", -lit, lit);
19754       } else continue;
19755       LOG (1, "unhiding failed literal %d", -unit);
19756       lglunit (lgl, unit);
19757       lgl->stats->unhd.failed.lits++;
19758       nfailed++;
19759       if (lglbcp (lgl)) continue;
19760       LOG (1, "empty clause after propagating unhidden failed literal");
19761       assert (!lgl->mt);
19762       lgl->mt = 1;
19763       return 0;
19764     }
19765   }
19766   LOG (1, "unhiding %d failed literals in this round", nfailed);
19767   return 1;
19768 }
19769
19770 static int lglunhroot (const DFPR * dfpr, int lit) {
19771   return dfpr[lglulit (lit)].root;
19772 }
19773
19774 static int lglunhidebintrn (LGL * lgl, const DFPR * dfpr, int irronly) {
19775   int idx, sign, lit, blit, tag, red, other, other2, unit, root, lca;
19776   int nbinred, ntrnred, nbinunits, ntrnunits, ntrnstr, ntrnhbrs;
19777   const int * p, * eow;
19778   int ulit, uother;
19779   int * w , * q;
19780   long delta;
19781   HTS * hts;
19782   nbinred = ntrnred = nbinunits = ntrnunits = ntrnstr = ntrnhbrs = 0;
19783   for (idx = 2; idx < lgl->nvars; idx++) {
19784     for (sign = -1; sign <= 1; sign += 2) {
19785       if (lglterminate (lgl)) return 0;
19786       if (!lglsyncunits (lgl)) return 0;
19787       INCSTEPS (unhd.steps);
19788       lit = sign * idx;
19789       if (lglval (lgl, lit)) continue;
19790       ulit = lglulit (lit);
19791       if (!dfpr[ulit].discovered) continue;
19792       hts = lglhts (lgl, lit);
19793       w = lglhts2wchs (lgl, hts);
19794       eow = w + hts->count;
19795       q = w;
19796       for (p = w; p < eow; p++) {
19797         blit = *p;
19798         *q++ = blit;
19799         tag = blit & MASKCS;
19800         if (tag == TRNCS || tag == LRGCS) *q++ = *++p;
19801         if (tag == LRGCS) continue;
19802         red = blit & REDCS;
19803         other = blit >> RMSHFT;
19804         if (lglval (lgl, other)) continue;
19805         uother = lglulit (other);
19806         if (tag == BINCS) {
19807           if (lglunhimplies2 (dfpr, other, lit)) {
19808             LOG (2, "unhiding removal of literal %d "
19809                     "with implication %d %d from binary clause %d %d",
19810                  other, other, lit, lit, other);
19811             lgl->stats->unhd.units.bin++;
19812             nbinunits++;
19813             unit = lit;
19814 UNIT:
19815             lglunit (lgl, unit);
19816             p++;
19817             while (p < eow) *q++ = *p++;
19818             lglshrinkhts (lgl, hts, hts->count - (p - q));
19819             if (lglbcp (lgl)) goto NEXTIDX;
19820             LOG (1, "empty clause after propagating unhidden lifted unit");
19821             assert (!lgl->mt);
19822             lgl->mt = 1;
19823             return 0;
19824           } else if ((root = lglunhroot (dfpr, -lit)) &&
19825                      !lglval (lgl, root) &&
19826                      root == lglunhroot (dfpr, -other)) {
19827             LOG (2, "negated literals in binary clause %d %d implied by %d",
19828                  lit, other, root);
19829             lgl->stats->unhd.failed.bin++;
19830             lca = lglunhlca (lgl, dfpr, -lit, -other);
19831             unit = -lca;
19832             assert (unit);
19833             goto UNIT;
19834           } else if (!irronly && !red) continue;
19835           else {
19836             if (dfpr[uother].parent == -lit) continue;
19837             if (dfpr[ulit].parent == -other) continue;
19838             if (!lglunhimplies2 (dfpr, -lit, other)) continue;
19839             LOG (2, "unhiding tautological binary clause %d %d", lit, other);
19840             lgl->stats->unhd.tauts.bin++;
19841             lgl->stats->prgss++;
19842             if (red) lgl->stats->unhd.tauts.red++;
19843             nbinred++;
19844             lglrmbwch (lgl, other, lit, red);
19845             LOG (2, "removed %s binary clause %d %d",
19846                  lglred2str (red), lit, other);
19847             lgldeclscnt (lgl, 2, red, 0);
19848             assert (!lgl->dense);
19849             q--;
19850           }
19851         } else {
19852           assert (tag == TRNCS);
19853           other2 = *p;
19854           if (lglval (lgl, other2)) continue;
19855           if (lglunhimplies2incl (dfpr, other, lit) &&
19856               lglunhimplies2incl (dfpr, other2, lit)) {
19857             LOG (2,
19858                  "unhiding removal of literals %d and %d with implications "
19859                  "%d %d and %d %d from ternary clause %d %d %d",
19860                  other, other2,
19861                  other, lit,
19862                  other2, lit,
19863                  lit, other, other2);
19864             lgl->stats->unhd.str.trn += 2;
19865             if (red) lgl->stats->unhd.str.red += 2;
19866             lgl->stats->unhd.units.trn++;
19867             ntrnunits++;
19868             unit = lit;
19869             goto UNIT;
19870           } else if ((root = lglunhroot (dfpr, -lit)) &&
19871                      !lglval (lgl, root) &&
19872                      root == lglunhroot (dfpr, -other) &&
19873                      root == lglunhroot (dfpr, -other2)) {
19874             LOG (2,
19875               "negation of literals in ternary clauses %d %d %d "
19876               "implied by %d", lit, other, other2, root);
19877             lgl->stats->unhd.failed.trn++;
19878             lca = lglunhlca (lgl, dfpr, -lit, -other);
19879             assert (lca);
19880             lca = lglunhlca (lgl, dfpr, lca, -other2);
19881             assert (lca);
19882             unit = -lca;
19883             goto UNIT;
19884           } else if ((red || irronly) &&
19885                      (lglunhimplies2incl (dfpr, -lit, other) ||
19886                       lglunhimplies2incl (dfpr, -lit, other2))) {
19887
19888             if (!lgl->opts->unhdatrn.val) continue;
19889             if (red && lgl->opts->unhdatrn.val == 1) continue;
19890
19891             LOG (2, "unhiding %s tautological ternary clause %d %d %d",
19892                  lglred2str (red), lit, other, other2);
19893             lgl->stats->unhd.tauts.trn++;
19894             lgl->stats->prgss++;
19895             if (red) lgl->stats->unhd.tauts.red++;
19896             ntrnred++;
19897             lglrmtwch (lgl, other, lit, other2, red);
19898             lglrmtwch (lgl, other2, lit, other, red);
19899             LOG (2, "removed %s ternary clause %d %d %d",
19900                  lglred2str (red), lit, other, other2);
19901             lgldeclscnt (lgl, 3, red, 0);
19902             assert (!lgl->dense);
19903             if (!red && lgl->opts->move.val >= 2) {
19904               long delta;
19905               assert (q >= w);
19906               assert (q[-2] == blit);
19907               assert (q[-1] == other2);
19908               q[-2] |= REDCS;
19909               delta = lglwchtrn (lgl, other, lit, other2, REDCS);
19910               delta += lglwchtrn (lgl, other2, lit, other, REDCS);
19911               if (delta) w += delta, eow += delta, p += delta, q += delta;
19912               LOG (2, "moved ternary clause %d %d %d", lit, other, other2);
19913               lgl->stats->red.trn++, assert (lgl->stats->red.trn > 0);
19914               lgl->stats->moved.trn++;
19915             } else q -= 2;
19916           } else if (lglunhimplies2incl (dfpr, other2, lit)) {
19917 TRNSTR:
19918             LOG (2,
19919                  "unhiding removal of literal %d with implication "
19920                  "%d %d from ternary clause %d %d %d",
19921                  other2, other2, lit, lit, other, other2);
19922             lgl->stats->unhd.str.trn++;
19923             lgl->stats->prgss++;
19924             if (red) lgl->stats->unhd.str.red++;
19925             ntrnstr++;
19926             lglrmtwch (lgl, other, lit, other2, red);
19927             lglrmtwch (lgl, other2, lit, other, red);
19928             LOG (2, "removed %s ternary clause %d %d %d",
19929                  lglred2str (red), lit, other, other2);
19930             lgldeclscnt (lgl, 3, red, 0);
19931             if (!red) lglincirr (lgl, 2);
19932             else lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
19933             delta = lglwchbin (lgl, other, lit, red);
19934             if (delta) { p += delta, q += delta, eow += delta, w += delta; }
19935             (--q)[-1] = red | BINCS | (other << RMSHFT);
19936             if (lgl->opts->drup.val) lgldrupclsarg (lgl, lit, other, 0);
19937 #ifndef NLGLPICOSAT
19938             lglpicosatchkclsarg (lgl, lit, other, 0);
19939 #endif
19940             continue;
19941           } else if (lglunhimplies2incl (dfpr, other, lit)) {
19942             SWAP (int, other, other2);
19943             goto TRNSTR;
19944           } else if (lgl->opts->unhdhbr.val &&
19945                      (root = lglunhroot (dfpr, -lit)) &&
19946                      !lglval (lgl, root)) {
19947             if (root == lglunhroot (dfpr, -other2)) {
19948               lca = lglunhlca (lgl, dfpr, -lit, -other2);
19949             } else if (root == lglunhroot (dfpr, -other)) {
19950               lca = lglunhlca (lgl, dfpr, -lit, -other);
19951               SWAP (int, other, other2);
19952             } else if (lglunhimplies2incl (dfpr, root, -other2)) lca = root;
19953             else if (lglunhimplies2incl (dfpr, root, -other)) {
19954               lca = root;
19955               SWAP (int, other, other2);
19956             } else continue;
19957             assert (lca);
19958             if (abs (lca) == abs (lit)) continue;
19959             if (abs (lca) == abs (other)) continue;
19960             if (abs (lca) == abs (other2)) continue;
19961             if (lglunhimplies2incl (dfpr, lca, other)) continue;
19962             LOG (2,
19963               "negations of literals %d %d in ternary clause %d %d %d "
19964               "implied by %d", lit, other2, lit, other, other2, lca);
19965             lgl->stats->unhd.hbrs.trn++;
19966             if (red) lgl->stats->unhd.hbrs.red++;
19967             lgl->stats->prgss++;
19968             ntrnhbrs++;
19969             LOG (2, "unhidden hyper binary resolved clause %d %d",-lca,other);
19970             if (lgl->opts->drup.val) lgldrupclsarg (lgl, -lca, other, 0);
19971 #ifndef NLGLPICOSAT
19972             lglpicosatchkclsarg (lgl, -lca, other, 0);
19973 #endif
19974             assert (lca != -lit);
19975             lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
19976             delta = lglwchbin (lgl, -lca, other, REDCS);
19977             if (delta) { p += delta, q += delta, eow += delta, w += delta; }
19978             delta = lglwchbin (lgl, other, -lca, REDCS);
19979             if (delta) { p += delta, q += delta, eow += delta, w += delta; }
19980           }
19981         }
19982       }
19983       lglshrinkhts (lgl, hts, hts->count - (p - q));
19984     }
19985 NEXTIDX:
19986     ;
19987   }
19988   if (nbinred) LOG (2, "unhiding %d tautological binary clauses", nbinred);
19989   if (nbinunits) LOG (2, "unhiding %d units in binary clauses", nbinunits);
19990   if (ntrnred) LOG (2, "unhiding %d tautological ternary clauses", ntrnred);
19991   if (ntrnstr) LOG (2, "unhiding %d strengthened ternary clauses", ntrnstr);
19992   if (ntrnunits) LOG (2, "unhiding %d units in ternary clauses", ntrnunits);
19993   if (ntrnstr) LOG (2, 
19994     "unhidden %d hyper binary resolution from ternary clauses", ntrnhbrs);
19995   return 1;
19996 }
19997
19998 static int lglcmpdfl (const DFL * a, const DFL * b) {
19999   return a->discovered - b->discovered;
20000 }
20001
20002 static int lglunhideglue (LGL * lgl, const DFPR * dfpr, int glue, int irronly) {
20003   DFL * dfl, * eodfl, * d, * e; int szdfl, posdfl, negdfl, ndfl, res;
20004   int oldsize, newsize, hastobesatisfied, satisfied, tautological;
20005   int watched, lit, ulit, val, sign, nonfalse, root, lca, unit;
20006   int ntaut = 0, nstr = 0, nunits = 0, nhbrs = 0, lidx;
20007   int * p, * q, * c, * eoc, red;
20008   int lca1, lca2, root1, root2;
20009   Stk * lits;
20010 #ifndef NLGLOG
20011   char type[20];
20012   if (glue < 0) sprintf (type, "irredundant");
20013   else sprintf (type, "redundant glue %d", glue);
20014 #endif
20015   assert (!lgl->mt);
20016   assert (-1 <= glue && glue < MAXGLUE);
20017   if (glue < 0) {
20018     lits = &lgl->irr;
20019     red = 0;
20020   } else {
20021     lits = lgl->red + glue;
20022     red = REDCS;
20023   }
20024   res = 1;
20025   dfl = 0; szdfl = 0;
20026   // go through all clauses of this glue and for each do:
20027   //
20028   //   SHRINK  simplify clause according to current assignment
20029   //   FAILED  check if it is a hidden failed literal
20030   //   HTE     check if it is a hidden tautology
20031   //   STRNEG  remove hidden literals using complement literals
20032   //   STRPOS  remove hidden literals using positive literals
20033   //   HBR     perform unhiding hyper binary resolution
20034   //   NEXT    clean up, unwatch if necessary, reconnect bin/trn, bcp unit
20035   //
20036   for (c = lits->start; !lgl->mt && c < lits->top; c = eoc + 1) {
20037     if (lglterminate (lgl) || !lglsyncunits (lgl)) { res = 0; break; }
20038     if ((lit = *(eoc = c)) >= NOTALIT) continue;
20039     INCSTEPS (unhd.steps);
20040     lidx = c - lits->start;
20041     if (red) { lidx <<= GLUESHFT; lidx |= glue; }
20042     watched = 1;
20043     while (*eoc) eoc++;
20044     oldsize = eoc - c;
20045
20046     unit = hastobesatisfied = satisfied = tautological = ndfl = 0;
20047 //SHRINK: check satisfied + remove false literals + count visited
20048     q = c;
20049     nonfalse = posdfl = negdfl = 0;
20050     for (p = c; p < eoc; p++) {
20051       lit = *p;
20052       val = lglval (lgl, lit);
20053       if (val > 0) {
20054         satisfied = 1;
20055         q = c + 2;
20056         break;
20057       }
20058       if (val < 0) {
20059         if (p < c + 2) {
20060           *q++ = lit;           // watched, so have to keep it
20061           hastobesatisfied = 1; // for assertion checking only
20062         }
20063         continue;
20064       }
20065       *q++ = lit;
20066       nonfalse++;
20067       if (dfpr[lglulit (lit)].discovered) posdfl++;     // count pos in BIG
20068       if (dfpr[lglulit (-lit)].discovered) negdfl++;    // count neg in BIG
20069     }
20070     *(eoc = q) = 0;
20071     assert (eoc - c >= 2);      // we assume bcp done before
20072     ndfl = posdfl + negdfl;     // number of literals in BIG
20073     if (hastobesatisfied) assert (satisfied);
20074     if (satisfied || ndfl < 2) goto NEXT;
20075     assert (nonfalse = eoc - c);
20076     assert (nonfalse >= negdfl);
20077 //FAILED: find root implying all negated literals
20078     if (nonfalse != negdfl) goto HTE;   // not enough complement lits in BIG
20079     assert (c < eoc);
20080     root = lglunhroot (dfpr, -*c);
20081     if (lglval (lgl, root)) goto HTE;
20082     for (p = c + 1; p < eoc && lglunhroot (dfpr, -*p) == root; p++)
20083       ;
20084     if (p < eoc) goto HTE;              // at least two roots
20085     LOGCLS (2, c, "unhiding failed literal through large %s clause",type);
20086     LOG (2, "unhiding that all negations are implied by root %d", root);
20087     lca = -*c;
20088     for (p = c + 1; p < eoc; p++)
20089       lca = lglunhlca (lgl, dfpr, -*p, lca);
20090     assert (!lglval (lgl, lca));
20091     LOG (2, "unhiding failed large %s clause implied by LCA %d", type, lca);
20092     lgl->stats->unhd.failed.lrg++;
20093     unit = -lca;
20094     goto NEXT;  // otherwise need to properly unwatch and restart etc.
20095                 // which is too difficult to implement so leave further
20096                 // simplification of this clause to next unhiding round
20097 HTE:
20098     if (glue < 0 && !irronly) goto STRNEG; // skip tautology checking if
20099                                            // redundant clauses used and
20100                                            // we work on irredundant clauses
20101     if (posdfl < 2 || negdfl < 2) goto STRNEG;
20102     if (ndfl > szdfl) { RSZ (dfl, szdfl, ndfl); szdfl = ndfl; }
20103     ndfl = 0;
20104     // copy all literals and their complements to 'dfl'
20105     for (p = c; p < eoc; p++) {
20106       for (sign = -1; sign <= 1; sign += 2) {
20107         lit = *p;
20108         ulit = lglulit (sign * lit);
20109         if (!dfpr[ulit].discovered) continue;   // not in BIG so skip
20110         assert (ndfl < szdfl);
20111         dfl[ndfl].discovered = dfpr[ulit].discovered;
20112         dfl[ndfl].finished = dfpr[ulit].finished;
20113         dfl[ndfl].sign = sign;
20114 #ifndef NLGLOG
20115         dfl[ndfl].lit4logging = lit;
20116 #endif
20117         ndfl++;
20118       }
20119     }
20120     ADDSTEPS (unhd.steps, 6);                           // rough guess
20121     SORT (DFL, dfl, ndfl, lglcmpdfl);
20122     eodfl = dfl + ndfl;
20123     // Now check if there are two consecutive literals, the first
20124     // a complement of a literal in the clause, which implies another
20125     // literal actually occurring positive in the clause, where
20126     // 'd' ranges over complement literals
20127     // 'e' ranges over original literals
20128     for (d = dfl; d < eodfl - 1; d++)
20129       if (d->sign < 0) break;                   // get first negative pos
20130     while (d < eodfl - 1) {
20131       assert (d->sign < 0);
20132       for (e = d + 1; e < eodfl && e->finished < d->finished; e++) {
20133         if (e->sign < 0) continue;              // get next positive pos
20134         assert (d->sign < 0 && e->sign > 0);
20135         assert (d->discovered <= e->discovered);
20136         assert (e ->finished <= d->finished);
20137         LOGCLS (2, c,
20138                 "unhiding with implication %d %d tautological %s clause",
20139                 -d->lit4logging, e->lit4logging, type);
20140         ntaut++;
20141         lgl->stats->unhd.tauts.lrg++;
20142         if (red) lgl->stats->unhd.tauts.red++;
20143         lgl->stats->prgss++;
20144         tautological = 1;
20145         goto NEXT;
20146       }
20147       for (d = e; d < eodfl && d->sign > 0; d++)
20148         ;
20149     }
20150 STRNEG:
20151     if (negdfl < 2) goto STRPOS;
20152     if (negdfl > szdfl) { RSZ (dfl, szdfl, negdfl); szdfl = negdfl; }
20153     INCSTEPS (unhd.steps);
20154     ndfl = 0;
20155     // copy complement literals to 'dfl'
20156     for (p = c; p < eoc; p++) {
20157       lit = *p;
20158       ulit = lglulit (-lit);                    // NOTE: '-lit' not 'lit'
20159       if (!dfpr[ulit].discovered) continue;
20160       assert (ndfl < szdfl);
20161       dfl[ndfl].discovered = dfpr[ulit].discovered;     // of '-lit'
20162       dfl[ndfl].finished = dfpr[ulit].finished;         // of '-lit'
20163       dfl[ndfl].lit = lit;                      // NOTE: but 'lit' here
20164       ndfl++;
20165     }
20166     if (ndfl < 2) goto STRPOS;
20167     ADDSTEPS (unhd.steps, 3);                   // rough guess
20168     SORT (DFL, dfl, ndfl, lglcmpdfl);
20169     eodfl = dfl + ndfl;
20170     for (d = dfl; d < eodfl - 1; d = e) {
20171       assert (d->discovered);
20172       for (e = d + 1; e < eodfl && d->finished >= e->finished; e++) {
20173         assert (d->discovered <= e->discovered);
20174         lit = e->lit;
20175         LOGCLS (2, c,
20176                 "unhiding removal of literal %d "
20177                 "with implication %d %d from large %s clause",
20178                 lit, -d->lit, -e->lit, type);
20179         e->lit = 0;
20180         nstr++;
20181         lgl->stats->unhd.str.lrg++;
20182         if (red) lgl->stats->unhd.str.red++;
20183         lgl->stats->prgss++;
20184         if (!watched) continue;
20185         if (lit != c[0] && lit != c[1]) continue;
20186         lglrmlwch (lgl, c[0], red, lidx);
20187         lglrmlwch (lgl, c[1], red, lidx);
20188         watched = 0;
20189       }
20190     }
20191     assert (eoc - c >= 1 );
20192     q = c;
20193     if (watched) q += 2;                        // keep watched literals
20194                                                 // if we still watch
20195     // move non BIG literals
20196     for (p = q; p < eoc; p++) {
20197       lit = *p;
20198       ulit = lglulit (-lit);                    // NOTE: '-lit' not 'lit'
20199       if (dfpr[ulit].discovered) continue;
20200       *q++ = lit;
20201     }
20202     // copy from 'dfl' unremoved BIG literals back to clause
20203     for (d = dfl; d < eodfl; d++) {
20204       lit = d->lit;
20205       if (!lit) continue;
20206       if (watched && lit == c[0]) continue;
20207       if (watched && lit == c[1]) continue;
20208       *q++ = lit;
20209     }
20210     *(eoc = q) = 0;
20211 STRPOS:
20212     if (posdfl < 2) goto HBR;
20213     if (posdfl > szdfl) { RSZ (dfl, szdfl, posdfl); szdfl = posdfl; }
20214     ndfl = 0;
20215     // copy original literals to 'dfl' but sort reverse wrt 'discovered'
20216     for (p = c; p < eoc; p++) {
20217       lit = *p;
20218       ulit = lglulit (lit);                     // NOTE: now 'lit'
20219       if (!dfpr[ulit].discovered) continue;
20220       assert (ndfl < szdfl);
20221       dfl[ndfl].discovered = -dfpr[ulit].discovered;    // of 'lit'
20222       dfl[ndfl].finished = -dfpr[ulit].finished;                // of 'lit'
20223       dfl[ndfl].lit = lit;
20224       ndfl++;
20225     }
20226     if (ndfl < 2) goto NEXT;
20227     ADDSTEPS (unhd.steps, 3);                   // rough guess
20228     SORT (DFL, dfl, ndfl, lglcmpdfl);
20229     eodfl = dfl + ndfl;
20230     for (d = dfl; d < eodfl - 1; d = e) {
20231       assert (d->discovered);
20232       for (e = d + 1; e < eodfl && d->finished >= e->finished; e++) {
20233         assert (d->discovered <= e->discovered);
20234         lit = e->lit;
20235         LOGCLS (2, c,
20236                 "unhiding removal of literal %d "
20237                 "with implication %d %d from large %s clause",
20238                 lit, e->lit, d->lit, type);
20239         e->lit = 0;
20240         nstr++;
20241         lgl->stats->unhd.str.lrg++;
20242         if (red) lgl->stats->unhd.str.red++;
20243         lgl->stats->prgss++;
20244         if (!watched) continue;
20245         if (lit != c[0] && lit != c[1]) continue;
20246         lglrmlwch (lgl, c[0], red, lidx);
20247         lglrmlwch (lgl, c[1], red, lidx);
20248         watched = 0;
20249       }
20250     }
20251     assert (eoc - c >= 1 );
20252     q = c;
20253     if (watched) q += 2;
20254     for (p = q; p < eoc; p++) {
20255       lit = *p;
20256       ulit = lglulit (lit);                     // NOTE: now 'lit'
20257       if (dfpr[ulit].discovered) continue;
20258       *q++ = lit;
20259     }
20260     for (d = dfl; d < eodfl; d++) {
20261       lit = d->lit;
20262       if (!lit) continue;
20263       if (watched && lit == c[0]) continue;
20264       if (watched && lit == c[1]) continue;
20265       *q++ = lit;
20266     }
20267     *(eoc = q) = 0;
20268 HBR:
20269     if (!lgl->opts->unhdhbr.val) goto NEXT;
20270     if (eoc - c < 3) goto NEXT;
20271     root1 = root2 = lca1 = lca2 = 0;
20272     for (p = c; (lit = *p); p++) {
20273       root = lglunhroot (dfpr, -lit);
20274       if (!root) root = -lit;
20275       if (!root1) { root1 = root; continue; }
20276       if (root1 == root) continue;
20277       if (!root2) { root2 = root; continue; }
20278       if (root2 == root) continue;
20279       if (lglunhimplies2incl (dfpr, root1, -lit)) { lca1 = root1; continue; }
20280       if (lglunhimplies2incl (dfpr, root2, -lit)) { lca2 = root2; continue; }
20281       goto NEXT;                        // else more than two roots ...
20282     }
20283     assert (root1);
20284     if (!root2) goto NEXT;
20285     if (root1 == -root2) goto NEXT;
20286     if (lglunhimplies2incl (dfpr, root1, -root2)) goto NEXT;
20287     LOGCLS (2, c, "root hyper binary resolution %d %d of %s clause",
20288             -root1, -root2, type);
20289     if (!lca1 && !lca2) {
20290       for (p = c; (lit = *p); p++) {
20291         root = lglunhroot (dfpr, -lit);
20292         if (root) {
20293           if (root == root1)
20294             lca1 = lca1 ? lglunhlca (lgl, dfpr, lca1, -lit) : -lit;
20295           if (root == root2)
20296             lca2 = lca2 ? lglunhlca (lgl, dfpr, lca2, -lit) : -lit;
20297         } else {
20298           assert (!lca2);
20299           if (lca1) lca2 = -lit; else lca1 = -lit;
20300         }
20301       }
20302     } else {
20303       if (!lca1) lca1 = root1;
20304       if (!lca2) lca2 = root2;
20305     }
20306     if (lca1 == -lca2) goto NEXT;
20307     if (lglunhimplies2incl (dfpr, lca1, -lca2)) goto NEXT;
20308     LOGCLS (2, c, "lca hyper binary resolution %d %d of %s clause",
20309             -lca1, -lca2, type);
20310     lgl->stats->unhd.hbrs.lrg++;
20311     if (red) lgl->stats->unhd.hbrs.red++;
20312     if (lgl->opts->drup.val) lgldrupclsarg (lgl, -lca1, -lca2, 0);
20313 #ifndef NLGLPICOSAT
20314     lglpicosatchkclsarg (lgl, -lca1, -lca2, 0);
20315 #endif
20316     lglwchbin (lgl, -lca1, -lca2, REDCS);
20317     lglwchbin (lgl, -lca2, -lca1, REDCS);
20318     lgl->stats->red.bin++;
20319     assert (lgl->stats->red.bin > 0);
20320 NEXT:
20321     newsize = eoc - c;
20322     assert (satisfied || tautological || newsize >= 1);
20323     if (newsize <= 3 || satisfied || tautological) {
20324       lgldeclscnt (lgl, oldsize, red, glue);
20325       if (watched) {
20326         lglrmlwch (lgl, c[0], red, lidx);
20327         lglrmlwch (lgl, c[1], red, lidx);
20328       }
20329     } else if (!red) {
20330       assert (lgl->stats->irr.lits.cur >= c + oldsize - eoc);
20331       lgl->stats->irr.lits.cur -= c + oldsize - eoc;
20332     }
20333     assert (!*eoc);
20334     for (p = c + oldsize; p > eoc; p--) *p = REMOVED;
20335     if (satisfied || tautological) {
20336       while (p >= c) *p-- = REMOVED;
20337       if (red) { LGLCHKACT (c[-1]); c[-1] = REMOVED; }
20338       eoc = c + oldsize;
20339       continue;
20340     }
20341     if (newsize < oldsize) {
20342       if (lgl->opts->drup.val) lgldrupclsaux (lgl, c);
20343 #ifndef NLGLPICOSAT
20344       lglpicosatchkclsaux (lgl, c);
20345 #endif
20346     }
20347     if (red && newsize <= 3) { LGLCHKACT (c[-1]); c[-1] = REMOVED; }
20348     if (newsize > 3 && !watched) {
20349       (void) lglwchlrg (lgl, c[0], c[1], red, lidx);
20350       (void) lglwchlrg (lgl, c[1], c[0], red, lidx);
20351     } else if (newsize == 3) {
20352       LOGCLS (2, c, "large %s clause became ternary", type);
20353       lglwchtrn (lgl, c[0], c[1], c[2], red);
20354       lglwchtrn (lgl, c[1], c[0], c[2], red);
20355       lglwchtrn (lgl, c[2], c[0], c[1], red);
20356       if (!red) lglincirr (lgl, 3);
20357       else lgl->stats->red.trn++, assert (lgl->stats->red.trn > 0);
20358       c[0] = c[1] = c[2] = *eoc = REMOVED;
20359     } else if (newsize == 2) {
20360       LOGCLS (2, c, "large %s clause became binary", type);
20361       lglwchbin (lgl, c[0], c[1], red);
20362       lglwchbin (lgl, c[1], c[0], red);
20363       if (!red) lglincirr (lgl, 2);
20364       else lgl->stats->red.bin++, assert (lgl->stats->red.bin > 0);
20365       c[0] = c[1] = *eoc = REMOVED;
20366     } else if (newsize == 1) {
20367       LOGCLS (2, c, "large %s clause became unit", type);
20368       unit = c[0];              // even works if unit already set
20369       c[0] = *eoc = REMOVED;
20370       lgl->stats->unhd.units.lrg++;
20371       nunits++;
20372     }
20373     if (!unit) continue;
20374     lglunit (lgl, unit);
20375     if (lglbcp (lgl)) continue;
20376     assert (!lgl->mt);
20377     lgl->mt = 1;
20378     LOG (1, "unhiding large clause produces empty clause");
20379     res = 0;
20380   }
20381   if (nunits)
20382     LOG (1, "unhiding %d units from large %s clauses", nunits, type);
20383   if (ntaut)
20384     LOG (1, "unhiding %d large tautological %s clauses", ntaut, type);
20385   if (nstr)
20386     LOG (1, "unhiding removal of %d literals in %s clauses", nstr, type);
20387   if (nhbrs)
20388     LOG (1, "unhiding %d hyper binary resolutions in %s clauses", nhbrs, type);
20389   if (dfl) DEL (dfl, szdfl);
20390   return res;
20391 }
20392
20393 static void lglfixlrgwchs (LGL * lgl) {
20394   int idx, sign, lit, blit, tag, red, lidx, fixed;
20395   const int * p, * eow, * c;
20396   int * q, * w;
20397   HTS * hts;
20398   fixed = 0;
20399   for (idx = 2; idx < lgl->nvars; idx++) {
20400     for (sign = -1; sign <= 1; sign += 2) {
20401       lit = sign * idx;
20402       hts = lglhts (lgl, lit);
20403       w = lglhts2wchs (lgl, hts);
20404       eow = w + hts->count;
20405       q = w;
20406       for (p = w; p < eow; p++) {
20407         blit = *p;
20408         tag = blit & MASKCS;
20409         if (tag == BINCS) { *q++ = blit; continue; }
20410         lidx = *++p;
20411         if (tag == TRNCS) { *q++ = blit; *q++ = lidx; continue; }
20412         assert (tag == LRGCS);
20413         red = blit & REDCS;
20414         c = lglidx2lits (lgl, red, lidx);
20415         if (*c >= NOTALIT) { fixed++; continue; }
20416         *q++ = blit;
20417         *q++ = lidx;
20418       }
20419       lglshrinkhts (lgl, hts, hts->count - (p - q));
20420     }
20421   }
20422   assert (!(fixed & 1));
20423   if (fixed) LOG (1, "fixed %d large watches", fixed);
20424 }
20425
20426 static int lglunhidelrg (LGL * lgl, const DFPR * dfpr, int irronly) {
20427   int glue, res = 1;
20428   for (glue = -1; res && glue < MAXGLUE; glue++)
20429     res = lglunhideglue (lgl, dfpr, glue, irronly);
20430   lglfixlrgwchs (lgl);
20431   return res;
20432 }
20433
20434 static int lglunhdunits (LGL * lgl) {
20435   int res = lgl->stats->unhd.units.bin;
20436   res += lgl->stats->unhd.units.trn;
20437   res += lgl->stats->unhd.units.lrg;
20438   return res;
20439 }
20440
20441 static int lglunhdfailed (LGL * lgl) {
20442   int res = lgl->stats->unhd.stamp.failed;
20443   res += lgl->stats->unhd.failed.lits;
20444   res += lgl->stats->unhd.failed.bin;
20445   res += lgl->stats->unhd.failed.trn;
20446   res += lgl->stats->unhd.failed.lrg;
20447   return res;
20448 }
20449
20450 static int lglunhdhbrs (LGL * lgl) {
20451   int res = lgl->stats->unhd.hbrs.trn;
20452   res += lgl->stats->unhd.hbrs.lrg;
20453   return res;
20454 }
20455
20456 static int lglunhdtauts (LGL * lgl) {
20457   int res = lgl->stats->unhd.stamp.trds;
20458   res += lgl->stats->unhd.tauts.bin;
20459   res += lgl->stats->unhd.tauts.trn;
20460   res += lgl->stats->unhd.tauts.lrg;
20461   return res;
20462 }
20463
20464 static int lglunhdstrd (LGL * lgl) {
20465   int res = lgl->stats->unhd.units.bin; // shared!
20466   res += lgl->stats->unhd.str.trn;
20467   res += lgl->stats->unhd.str.lrg;
20468   return res;
20469 }
20470
20471 static void lglrmbindup (LGL * lgl) {
20472   int idx, sign, lit, blit, tag, red, other, round, redrem, irrem;
20473   int * w, * eow, * p, * q;
20474   HTS * hts;
20475   redrem = irrem = 0;
20476   for (idx = 2; idx < lgl->nvars; idx++) {
20477     for (sign = -1; sign <= 1; sign += 2) {
20478       lit = sign * idx;
20479       assert (lglmtstk (&lgl->seen));
20480       for (round = 0; round < 2; round++) {
20481         hts = lglhts (lgl, lit);
20482         w = lglhts2wchs (lgl, hts);
20483         eow = w + hts->count;
20484         q = w;
20485         for (p = w; p < eow; p++) {
20486           blit = *p;
20487           tag = blit & MASKCS;
20488           if (tag != BINCS) *q++ = blit;
20489           if (tag== LRGCS || tag == TRNCS) *q++ = *++p;
20490           if (tag != BINCS) continue;
20491           red = blit & REDCS;
20492           other = blit >> RMSHFT;
20493           if (lglsignedmarked (lgl, other)) {
20494             if (round && !red) goto ONLYCOPY;
20495             if (red) redrem++; else irrem++;
20496             if (abs (lit) > abs (other)) {
20497               LOG (2,
20498                 "removing duplicated %s binary clause %d %d and 2nd watch %d",
20499                 lglred2str (red), lit, other, other);
20500               lgldeclscnt (lgl, 2, red, 0);
20501               if (!red && lgl->dense)
20502                 lgldecocc (lgl, lit), lgldecocc (lgl, other);
20503               lgl->stats->bindup.removed++;
20504               if (red) lgl->stats->bindup.red++;
20505             } else
20506               LOG (2,
20507                 "removing 1st watch %d of duplicated %s binary clause %d %d",
20508                 other, lglred2str (red), other, lit);
20509           } else {
20510             if ((!round && !red) || (round && red))
20511               lglsignedmarknpushseen (lgl, other);
20512 ONLYCOPY:
20513             *q++ = blit;
20514           }
20515         }
20516         lglshrinkhts (lgl, hts, hts->count - (p - q));
20517       }
20518       lglpopnunmarkstk (lgl, &lgl->seen);
20519     }
20520   }
20521   assert (!(irrem & 1));
20522   assert (!(redrem & 1));
20523 }
20524
20525 static DFPR * lglstampall (LGL * lgl, int irronly) {
20526   int roots, searches, noimpls, unassigned, visited;
20527   unsigned pos, delta, mod, ulit, first, last, count;
20528   int root, stamp, rootsonly, lit;
20529   Stk units, sccs, trds;
20530   DFOPF * dfopf, * q;
20531   DFPR * dfpr;
20532   Wtk work;
20533   Val val;
20534   if (lgl->nvars <= 2) return 0;
20535   lglrmbindup (lgl);
20536   NEW (dfpr, 2*lgl->nvars);
20537   NEW (dfopf, 2*lgl->nvars);
20538   CLR (work); CLR (sccs); CLR (trds); CLR (units);
20539   for (q = dfopf; q < dfopf + 2*lgl->nvars; q++) q->pushed = -1;
20540   searches = roots = noimpls = unassigned = stamp = visited = 0;
20541   for (rootsonly = 1; rootsonly >= 0; rootsonly--) {
20542     count = 0;
20543     first = mod = 2*(lgl->nvars - 2);
20544     assert (mod > 0);
20545     pos = lglrand (lgl) % mod;
20546     delta = lglrand (lgl) % mod;
20547     if (!delta) delta++;
20548     while (lglgcd (delta, mod) > 1)
20549       if (++delta == mod) delta = 1;
20550     LOG (2, "unhiding %s round start %u delta %u mod %u",
20551          (rootsonly ? "roots-only": "non-root"), pos, delta, mod);
20552     for (;;) {
20553       if (lglterminate (lgl)) { searches = 0; goto DONE; }
20554       if (!lglsyncunits (lgl)) { assert (lgl->mt); goto DONE; }
20555       ulit = pos + 4;
20556       root = lglilit (ulit);
20557       INCSTEPS (unhd.steps);
20558       count++;
20559       if (lglval (lgl, root)) goto CONTINUE;
20560       if (rootsonly) unassigned++;
20561       if (dfpr[lglulit (root)].discovered) goto CONTINUE;
20562       if (rootsonly &&
20563           !lglunhdisroot (lgl, root, dfpr, irronly)) goto CONTINUE;
20564       if (!lglunhdhasbins (lgl, dfpr, -root, irronly)) {
20565         if (rootsonly) noimpls++; goto CONTINUE;
20566       }
20567       if (rootsonly) roots++;
20568       searches++;
20569       assert (lglmtstk (&units));
20570       stamp = lglstamp (lgl, root, dfpr, dfopf,
20571                         &work, &units, &sccs, &trds, &visited,
20572                         stamp, irronly);
20573       while (!lglmtstk (&units)) {
20574         lit = lglpopstk (&units);
20575         val = lglval (lgl, lit);
20576         if (val > 0) continue;
20577         if (val < 0) {
20578           assert (!lgl->mt);
20579           LOG (1, "unhidding stamp unit %d already false", lit);
20580           lgl->mt = 1;
20581           goto DONE;
20582         }
20583         lglunit (lgl, lit);
20584         if (!lglbcp (lgl)) {
20585           assert (!lgl->mt);
20586           LOG (1, "propagating unhidden stamp unit %d failed", lit);
20587           lgl->mt = 1;
20588           goto DONE;
20589         }
20590       }
20591 CONTINUE:
20592       last = pos;
20593       pos += delta;
20594       if (pos >= mod) pos -= mod;
20595       if (pos == first) { assert (count == mod); break; }
20596       if (mod == 1) break;
20597       if (first == mod) first = last;
20598     }
20599   }
20600   assert (searches >= roots);
20601   lglprt (lgl, 2,
20602           "[unhd-%d-%d] %d unassigned variables out of %d (%.0f%%)",
20603           lgl->stats->unhd.count, lgl->stats->unhd.rounds,
20604           lgl->unassigned, lgl->nvars - 2,
20605             lglpcnt (lgl->unassigned, lgl->nvars - 2));
20606   lglprt (lgl, 2,
20607           "[unhd-%d-%d] %d root literals out of %d (%.0f%%)",
20608           lgl->stats->unhd.count, lgl->stats->unhd.rounds,
20609           roots, unassigned, lglpcnt (roots, unassigned));
20610   lglprt (lgl, 2,
20611     "[unhd-%d-%d] %d additional non-root searches out of %d (%.0f%%)",
20612           lgl->stats->unhd.count, lgl->stats->unhd.rounds,
20613           searches - roots, unassigned,
20614             lglpcnt (searches - roots, unassigned));
20615   lglprt (lgl, 2,
20616           "[unhd-%d-%d] %d literals not in F2 out of %d (%.0f%%)",
20617           lgl->stats->unhd.count, lgl->stats->unhd.rounds,
20618           noimpls, unassigned, lglpcnt (noimpls, unassigned));
20619   lglprt (lgl, 2,
20620           "[unhd-%d-%d] %d visited literals out of %d (%.0f%%)",
20621           lgl->stats->unhd.count, lgl->stats->unhd.rounds,
20622           visited, unassigned, lglpcnt (visited, unassigned));
20623   lglprt (lgl, 2,
20624           "[unhd-%d-%d] %.2f average number visited literals per search",
20625           lgl->stats->unhd.count, lgl->stats->unhd.rounds,
20626           lglavg (visited, searches));
20627 DONE:
20628   if (!searches || lgl->mt) { DEL (dfpr, 2*lgl->nvars); dfpr = 0; }
20629   lglrelwtk (lgl, &work);
20630   lglrelstk (lgl, &units);
20631   lglrelstk (lgl, &sccs);
20632   lglrelstk (lgl, &trds);
20633   DEL (dfopf, 2*lgl->nvars);
20634   return dfpr;
20635 }
20636
20637 static void lglsetunhdlim (LGL * lgl) {
20638   int64_t limit, irrlim;
20639   int pen;
20640   limit = (lgl->opts->unhdreleff.val*lglvisearch (lgl))/1000;
20641   if (limit < lgl->opts->unhdmineff.val) limit = lgl->opts->unhdmineff.val;
20642   if (lgl->opts->unhdmaxeff.val >= 0 && limit > lgl->opts->unhdmaxeff.val)
20643     limit = lgl->opts->unhdmaxeff.val;
20644   limit >>= (pen = lgl->limits->unhd.pen + lglszpen (lgl));
20645   irrlim = lgl->stats->irr.clauses.cur/2;
20646   irrlim >>= lgl->limits->simp.pen;
20647   if (lgl->opts->irrlim.val && limit < irrlim) {
20648     limit = irrlim;
20649     lglprt (lgl, 1,
20650       "[unhide-%d] limit %lld based on %d irredundant clauses",
20651       lgl->stats->unhd.count, (LGLL) limit, lgl->stats->irr.clauses.cur);
20652   } else
20653     lglprt (lgl, 1, "[unhide-%d] limit %lld with penalty %d = %d + %d",
20654       lgl->stats->unhd.count, (LGLL) limit,
20655       pen, lgl->limits->unhd.pen, lglszpen (lgl));
20656   lgl->limits->unhd.steps = lgl->stats->unhd.steps + limit;
20657 }
20658
20659 static int lglunhide (LGL * lgl) {
20660   int irronly, round, maxrounds, noprgssrounds, success;
20661   int oldunits, oldfailed, oldtauts, oldhbrs, oldstrd;
20662   int deltaunits, deltafailed;
20663   int64_t roundprgss = 0;
20664   DFPR * dfpr = 0;
20665   assert (lgl->opts->unhide.val);
20666   if (lgl->nvars <= 2) return 1;
20667   lgl->stats->unhd.count++;
20668   assert (!lgl->unhiding);
20669   lgl->unhiding = 1;
20670   assert (!lgl->simp);
20671   lgl->simp = 1;
20672   lglstart (lgl, &lgl->times->unhd);
20673   irronly = !lgl->stats->red.bin || (lgl->stats->unhd.count & 1);
20674   if (lgl->level > 0) lglbacktrack (lgl, 0);
20675   maxrounds = lgl->opts->unhdroundlim.val;
20676   lglsetunhdlim (lgl);
20677   oldunits = lglunhdunits (lgl);
20678   oldfailed = lglunhdfailed (lgl);
20679   oldtauts = lglunhdtauts (lgl);
20680   oldhbrs = lglunhdhbrs (lgl);
20681   oldstrd = lglunhdstrd (lgl);
20682   noprgssrounds = round = 0;
20683   while (!lgl->mt) {
20684     if (round >= maxrounds) break;
20685     if (round > 0 &&
20686         roundprgss == lgl->stats->prgss &&
20687         noprgssrounds++ == lgl->opts->unhdlnpr.val) {
20688       LOG (1, "too many non progress unhiding rounds");
20689       break;
20690     }
20691     round++;
20692     roundprgss = lgl->stats->prgss;
20693     lgl->stats->unhd.rounds++;
20694     lglgc (lgl);
20695     if (!lgl->nvars || lgl->mt) break;
20696     assert (!dfpr);
20697     dfpr = lglstampall (lgl, irronly);
20698     if (!dfpr) break;
20699     if (!lglunhidefailed (lgl, dfpr)) break;
20700     if (!lglunhidebintrn (lgl, dfpr, irronly)) break;
20701     if (!lglunhidelrg (lgl, dfpr, irronly)) break;
20702     if (lgl->stats->unhd.steps >= lgl->limits->unhd.steps) break;
20703     irronly = !lgl->stats->red.bin || !irronly;
20704     DEL (dfpr, 2*lgl->nvars);
20705     assert (!dfpr);
20706   }
20707   if (dfpr) DEL (dfpr, 2*lgl->nvars);
20708   lglprt (lgl, 1,
20709     "[unhide-%d-%d] %d units, %d failed, %d tauts, %d hbrs, %d literals",
20710     lgl->stats->unhd.count, lgl->stats->unhd.rounds,
20711     (deltaunits = lglunhdunits (lgl) - oldunits),
20712     (deltafailed = lglunhdfailed (lgl) - oldfailed),
20713     lglunhdtauts (lgl) - oldtauts,
20714     lglunhdhbrs (lgl) - oldhbrs,
20715     lglunhdstrd (lgl) - oldstrd);
20716   success = deltaunits + deltafailed;
20717   LGLUPDPEN (unhd, success);
20718   assert (lgl->simp);
20719   lgl->simp = 0;
20720   assert (lgl->unhiding);
20721   lgl->unhiding = 0;
20722   lglrep (lgl, 2, 'u');
20723   lglstop (lgl);
20724   return !lgl->mt;
20725 }
20726
20727 static int lglpar64 (uint64_t i) {
20728   unsigned x;
20729   int res = 0;
20730   for (x = i; x; x = x & (x - 1))
20731     res = !res;
20732   return res;
20733 }
20734
20735 static uint64_t lgldec64 (uint64_t i) {
20736   uint64_t res;
20737   for (res = i - 1; lglpar64 (res); res--)
20738     ;
20739   return res;
20740 }
20741
20742 static void lglgdump (LGL * lgl) {
20743 #ifndef NLGLOG
20744   const int * p, * start, * top;
20745   start = lgl->gauss->xors.start;
20746   top = lgl->gauss->xors.top;
20747   for (p = start; p < top; p++) {
20748     if (*p >= NOTALIT) continue;
20749     fprintf (lgl->out, "c eqn[%lld]", (LGLL)(p - start));
20750     while (*p > 1) fprintf (lgl->out, " %d", *p++);
20751     fprintf (lgl->out, " = %d\n", *p);
20752   }
20753 #endif
20754 }
20755
20756 static int lglgaussubclsaux (LGL * lgl, uint64_t signs,  const int * c) {
20757   int lit, i, min, minocc, tmpocc, blit, tag, other, other2, red, lidx;
20758   const int * p, * w, * eow, * d, * q;
20759   HTS * hts;
20760   assert (lgl->dense);
20761   minocc = INT_MAX;
20762   min = i = 0;
20763   INCSTEPS (gauss.steps.extr);
20764   for (p = c; (lit = *p); p++) {
20765     if (lglmarked (lgl, lit)) return 0;
20766     assert (i < 8 * sizeof signs);
20767     if (signs & (1ull << i++)) lit = -lit;
20768     lglsignedmark (lgl, lit);
20769     tmpocc = lglocc (lgl, lit) + lglhts (lgl, lit)->count;
20770     assert (tmpocc < INT_MAX);
20771     if (tmpocc >= minocc) continue;
20772     minocc = tmpocc;
20773     min = lit;
20774   }
20775   assert (min);
20776   hts = lglhts (lgl, min);
20777   w = lglhts2wchs (lgl, hts);
20778   eow = w + hts->count;
20779   for (p = w; p < eow; p++) {
20780     INCSTEPS (gauss.steps.extr);
20781     blit = *p;
20782     tag = blit & MASKCS;
20783     if (tag == TRNCS || tag == LRGCS) p++;
20784     if (tag == LRGCS) continue;
20785     if (tag == BINCS) {
20786       other = blit >> RMSHFT;
20787       if (lglsignedmarked (lgl, other)) return 1;
20788     } else if (tag == TRNCS) {
20789       other = blit >> RMSHFT;
20790       if (!lglsignedmarked (lgl, other)) continue;
20791       other2 = *p;
20792       if (lglsignedmarked (lgl, other2)) return 1;
20793     } else {
20794       assert (tag == OCCS);
20795       red = blit & REDCS;
20796       lidx = blit >> RMSHFT;
20797       d = lglidx2lits (lgl, red, lidx);
20798       for (q = d; (other = *q); q++)
20799         if (!lglsignedmarked (lgl, other)) break;
20800       if (!other) return 1;
20801     }
20802   }
20803   return 0;
20804 }
20805
20806 static int lglgaussubcls (LGL * lgl, uint64_t signs,  const int * c) {
20807   int res = lglgaussubclsaux (lgl, signs, c), lit;
20808   const int * p;
20809   for (p = c; (lit = *p); p++) lglunmark (lgl, lit);
20810   return res;
20811 }
20812
20813 #define GL 2
20814
20815 static int lglgaussextractxoraux (LGL * lgl, const int * c) {
20816   int lit, val, size, maxsize, negs, start, max, *d, * q;
20817   int allxors = lgl->opts->gaussextrall.val;
20818   uint64_t signs;
20819   const int * p;
20820   assert (!lgl->level);
20821   maxsize = lgl->opts->gaussmaxor.val;
20822   max = negs = size = 0;
20823   start = lglcntstk (&lgl->gauss->xors);
20824   for (p = c; (lit = *p); p++) {
20825     if ((val = lglval (lgl, lit)) > 0) return 0;
20826     if (val < 0) continue;
20827     if (lit < 0) { 
20828       if (!allxors && negs) return 0;
20829       negs = !negs; 
20830     }
20831     if (!max || abs (max) < abs (lit)) max = lit;
20832     lglpushstk (lgl, &lgl->gauss->xors, lit);
20833     if (++size > maxsize) return 0;
20834   }
20835   assert (negs == 0 || negs == 1);
20836   if (size <= 1) return 0;
20837   if (!allxors && negs && max > 0) return 0;
20838   lglpushstk (lgl, &lgl->gauss->xors, 0);
20839   d = lgl->gauss->xors.start + start;
20840   assert (size <= 8 * sizeof signs);
20841   signs = lgldec64 (1ull << size);
20842   do {
20843     if (!lglgaussubcls (lgl, signs, d)) break;
20844     signs = lgldec64 (signs);
20845   } while (signs &&
20846            lgl->stats->gauss.steps.extr < lgl->limits->gauss.steps.extr);
20847   if (signs) return 0;
20848   for (q = d; (lit = *q); q++) *q = abs (lit);
20849   *q = !negs;
20850   LOGEQN (GL, start, "extracted %d-ary XOR constraint",  size);
20851   lgl->stats->gauss.arity.sum += size;
20852   if (lgl->stats->gauss.arity.max < size) lgl->stats->gauss.arity.max = size;
20853   lgl->stats->gauss.extracted++;
20854   return 1;
20855 }
20856
20857 static int lglgaussextractxor (LGL * lgl, const int * c) {
20858   int old = lglcntstk (&lgl->gauss->xors), res;
20859   if (!(res = lglgaussextractxoraux (lgl, c)))
20860     lglrststk (&lgl->gauss->xors, old);
20861   return res;
20862 }
20863
20864 static int lglgaussextractsmallit (LGL * lgl, int lit) {
20865   int allxors = lgl->opts->gaussextrall.val;
20866   int cls[4], blit, tag, other, other2;
20867   const int * w, * eow, * p;
20868   HTS * hts;
20869   if (lgl->stats->gauss.steps.extr >= lgl->limits->gauss.steps.extr) 
20870     return 0;
20871   if (lglval (lgl, lit) > 0) return 1;
20872   hts = lglhts (lgl, lit);
20873   w = lglhts2wchs (lgl, hts);
20874   eow = w + hts->count;
20875   for (p = w; p < eow; p++) {
20876     blit = *p;
20877     tag = blit & MASKCS;
20878     if (tag == TRNCS || tag == LRGCS) p++;
20879     if (tag == OCCS || tag == LRGCS) continue;
20880     other = blit >> RMSHFT;
20881     if (!allxors && abs (other) < lit) continue;
20882     cls[0] = lit;
20883     cls[1] = other;
20884     if (tag == TRNCS) {
20885       other2 = *p;
20886       if (!allxors && abs (other2) < lit) continue;
20887       cls[2] = other2;
20888       cls[3] = 0;
20889     } else {
20890       assert (tag == BINCS);
20891       cls[2] = 0;
20892     }
20893     lglgaussextractxor (lgl, cls);
20894   }
20895   return 1;
20896 }
20897
20898 static int lglgaussextractsmall (LGL * lgl) {
20899   int64_t before = lgl->stats->gauss.extracted, after, delta;
20900   int res;
20901   lglrandlitrav (lgl, lglgaussextractsmallit);
20902   after = lgl->stats->gauss.extracted;
20903   delta = after - before;
20904   res = (delta > INT_MAX) ? INT_MAX : delta;
20905   return res;
20906 }
20907
20908 static int lglgaussextractlarge (LGL * lgl) {
20909   const int * p, * c;
20910   int res = 0;
20911   for (c = lgl->irr.start; c < lgl->irr.top; c = p + 1) {
20912     if (lgl->stats->gauss.steps.extr >= lgl->limits->gauss.steps.extr) break;
20913     if (*(p = c) >= NOTALIT) continue;
20914     res += lglgaussextractxor (lgl, c);
20915     while (*p) p++;
20916   }
20917   return res;
20918 }
20919
20920 static void lglgaussconeqn (LGL * lgl, int eqn) {
20921   const int * xors = lgl->gauss->xors.start;
20922   int i, var;
20923   INCSTEPS (gauss.steps.elim);
20924   for (i = eqn; (var = xors[i]) > 1; i++)
20925     lglpushstk (lgl, lgl->gauss->occs + var, eqn);
20926 }
20927
20928 static void lglgaussdiseqn (LGL * lgl, int eqn) {
20929   int * xors = lgl->gauss->xors.start, i, var;
20930   for (i = eqn; (var = xors[i]) > 1; i++) {
20931     xors[i] = NOTALIT;
20932     lgl->gauss->garbage++;
20933     INCSTEPS (gauss.steps.elim);
20934     lglrmstk (lgl->gauss->occs + var, eqn);
20935   }
20936   xors[i] = NOTALIT;
20937   lgl->gauss->garbage++;
20938 }
20939
20940 static void lglgaussconnect (LGL * lgl) {
20941   int c, i, eox = lglcntstk (&lgl->gauss->xors), connected, var, vars;
20942   const int * xors = lgl->gauss->xors.start;
20943   Stk * occs;
20944   LOG (2,  "connecting equations");
20945   assert (!lgl->gauss->occs);
20946   NEW (lgl->gauss->occs, lgl->nvars);
20947   vars = connected = 0;
20948   for (c = 0; c < eox; c = i + 1) {
20949     INCSTEPS (gauss.steps.elim);
20950     for (i = c; (var = xors[i]) > 1; i++) {
20951       occs = lgl->gauss->occs + var;
20952       if (lglmtstk (occs)) vars++;
20953       lglpushstk (lgl, lgl->gauss->occs + var, c);
20954       connected++;
20955     }
20956   }
20957   lglprt (lgl, 1, 
20958      "[gauss-%d] connected %d occurrences of %d variables (average %.1f)",
20959       lgl->stats->gauss.count, connected, vars, lglavg (connected, vars));
20960 }
20961
20962 static int lglgaussorderidx (LGL * lgl,  int var) {
20963   assert (2 <= var && var < lgl->nvars);
20964   if (!lglmtstk (lgl->gauss->occs + var))
20965     lglpushstk (lgl, &lgl->gauss->order, var);
20966   return 1;
20967 }
20968
20969 static void lglgaussorder (LGL * lgl) {
20970   lglrandidxtrav (lgl, lglgaussorderidx);
20971   NEW (lgl->gauss->eliminated, lgl->nvars);
20972 }
20973
20974 static void lglgaussdisconnect (LGL * lgl) {
20975   int idx;
20976   assert (lgl->gauss->occs);
20977   LOG (2, "disconnecting equations");
20978   for (idx = 2; idx < lgl->nvars; idx++)
20979     lglrelstk (lgl, lgl->gauss->occs + idx);
20980   DEL (lgl->gauss->occs, lgl->nvars);
20981   assert (!lgl->gauss->occs);
20982 }
20983
20984 static void lglgaussextract (LGL * lgl) {
20985   int extracted, lits;
20986   assert (lglsmallirr (lgl));
20987   if (lgl->level) lglbacktrack (lgl, 0);
20988   lglgc (lgl);
20989   if (lgl->mt) return;
20990   lgldense (lgl, 1);
20991   extracted = lglgaussextractsmall (lgl);
20992   extracted += lglgaussextractlarge (lgl);
20993   lits = lglcntstk (&lgl->gauss->xors) - extracted;
20994   lglprt (lgl, 1,
20995     "[gauss-%d] extracted %d xors of average arity %.1f",
20996     lgl->stats->gauss.count, extracted, lglavg (lits, extracted));
20997   lglsparse (lgl);
20998   lglgc (lgl);
20999   if (lgl->mt) return;
21000   lglfitstk (lgl, &lgl->gauss->xors);
21001 }
21002
21003 static int lglgaussoccs (LGL * lgl, int a) {
21004   return lglcntstk (lgl->gauss->occs + a);
21005 }
21006
21007 static int lglcmpgauss (LGL * lgl, int a, int b) {
21008   int res = lglgaussoccs (lgl, a) - lglgaussoccs (lgl, b);
21009   if (!res) res = a - b;
21010   return res;
21011 }
21012
21013 #define LGLCMPGAUSS(A,B) lglcmpgauss (lgl, *(A), *(B))
21014
21015 static void lglgaussort (LGL * lgl) {
21016   int max = lglcntstk (&lgl->gauss->order), rest, * start;
21017   assert (lgl->gauss->next <= max);
21018   rest = max - lgl->gauss->next;
21019   start = lgl->gauss->order.start + lgl->gauss->next;
21020   ADDSTEPS (gauss.steps.elim, rest);
21021   SORT (int, start, rest, LGLCMPGAUSS);
21022   lglprt (lgl, 3, 
21023      "[gauss-%d] sorted %d remaining variables",
21024       lgl->stats->gauss.count, rest);
21025 }
21026
21027 static int lglgausspickeqn (LGL * lgl, int pivot) {
21028   int res, cand, weight, size, tmp, other, found;
21029   const int * p, * e, * q;
21030   Stk * occs;
21031   assert (lglgaussoccs (lgl, pivot));
21032   res = -1;
21033   weight = INT_MAX; size = INT_MAX;
21034   occs = lgl->gauss->occs + pivot;
21035   for (p = occs->start; p < occs->top; p++) {
21036     e = lgl->gauss->xors.start + (cand = *p);
21037     found = tmp = 0;
21038     INCSTEPS (gauss.steps.elim);
21039     for (q = e; (other = *q) > 1; q++) {
21040       if (lgl->gauss->eliminated[other]) break;
21041       if (other == pivot) { assert (!found); found++; continue; }
21042       tmp += lglgaussoccs (lgl, other) - 1;
21043     }
21044     if (other > 1) continue;
21045     assert (found);
21046     if (res >= 0 && q - e >= size) continue;
21047     if (res >= 0 && q - e == size && tmp >= weight) continue;
21048     weight = tmp;
21049     size = q - e;
21050     res = cand;
21051   }
21052   if (res >= 0)
21053     LOGEQN (2, res, "picking size %d weight %d equation", size, weight);
21054   else
21055     LOG (2, "no uneliminated equation for pivot %d left", pivot);
21056   return res;
21057 }
21058
21059 static void lglcpystk (LGL * lgl, Stk * dst, Stk * src) {
21060   const int * p;
21061   for (p = src->start; p < src->top; p++)
21062     lglpushstk (lgl, dst, *p);
21063 }
21064
21065 static int lglgaussaddeqn (LGL * lgl, int eqn) {
21066   const int * p;
21067   AVar * av;
21068   int var;
21069   for (p = lgl->gauss->xors.start + eqn; (var = *p) > 1; p++) {
21070     av = lglavar (lgl, var);
21071     if (!av->mark) lglpushstk (lgl, &lgl->clause, var);
21072     av->mark = !av->mark;
21073   }
21074   return var;
21075 }
21076
21077 static void lglgaussubst (LGL * lgl, int pivot, int subst) {
21078   Stk * occs = lgl->gauss->occs + pivot;
21079   int eqn, rhs, res;
21080   const int * p;
21081   int * q;
21082   assert (lglcntstk (occs) > 1);
21083   while (lglcntstk (occs) > 1) {
21084     if (lglterminate (lgl)) return;
21085     eqn = occs->start[0];
21086     if (eqn == subst) eqn = occs->start[1];
21087     assert (lglmtstk (&lgl->clause));
21088     LOGEQN (2, subst, "  1st row (kept)     ");
21089     rhs = lglgaussaddeqn (lgl, eqn);
21090     LOGEQN (2, eqn, "  2nd row (replaced) ");
21091     if (lglgaussaddeqn (lgl, subst)) rhs = !rhs;
21092     lglgaussdiseqn (lgl, eqn);
21093     q = lgl->clause.start;
21094     for (p = q; p < lgl->clause.top; p++)
21095       if (lglmarked (lgl, *p)) *q++ = *p;
21096     lgl->clause.top = q;
21097     if (!lglmtstk (&lgl->clause)) {
21098       res = lglcntstk (&lgl->gauss->xors);
21099       lglcpystk (lgl, &lgl->gauss->xors, &lgl->clause);
21100       lglpushstk (lgl, &lgl->gauss->xors, rhs);
21101       LOGEQN (2, res, "  result row         ");
21102       lglgaussconeqn (lgl, res);
21103     } else if (rhs == 0) {
21104       LOG (2, "trivial result row 0 = 0");
21105     } else {
21106       assert (rhs == 1);
21107       LOG (1, "inconsistent result row 0 = 1 from gaussian elimination");
21108       lgl->mt= 1;
21109     }
21110     lglpopnunmarkstk (lgl, &lgl->clause);
21111   }
21112 }
21113
21114 static void lglgausschkeliminated (LGL * lgl) {
21115 #ifndef NDEBUG
21116   int idx, eliminated, occs;
21117   if (!lgl->opts->check.val) return;
21118   for (idx = 2; idx < lgl->nvars; idx++) {
21119     eliminated = lgl->gauss->eliminated[idx];
21120     occs = lglgaussoccs (lgl, idx);
21121     if (eliminated == 1) assert (occs == 1);
21122     if (eliminated == 2) assert (occs == 0);
21123   }
21124 #endif
21125 }
21126
21127 static void lglgaussgc (LGL * lgl) {
21128   int count = lglcntstk (&lgl->gauss->xors), * q;
21129   const int * p;
21130   if (lgl->gauss->garbage < count/2 + 10000) return;
21131   lgl->stats->gauss.gcs++;
21132   lglprt (lgl, 2, 
21133      "[gauss-%d] collecting %d garbage out of %d",
21134      lgl->stats->gauss.count, lgl->gauss->garbage, count);
21135   lglgaussdisconnect (lgl);
21136   q = lgl->gauss->xors.start;
21137   for (p = q; p < lgl->gauss->xors.top; p++)
21138     if (*p != NOTALIT) *q++ = *p;
21139   lgl->gauss->xors.top = q;
21140   lglfitstk (lgl, &lgl->gauss->xors);
21141   lglgaussconnect (lgl);
21142   lgl->gauss->garbage = 0;
21143 }
21144
21145 static int lglgausselimvar (LGL * lgl, int pivot) {
21146   int subst, changed, occs, eliminated;
21147   LOG (2, "eliminating variable %d occurring %d times",
21148        pivot, lglgaussoccs (lgl, pivot));
21149   assert (!lgl->gauss->eliminated[pivot]);
21150   if (!(occs = lglgaussoccs (lgl, pivot))) {
21151     LOG (2, "variable %d disappeared ", pivot);
21152     eliminated = 2;
21153     changed = 0;
21154   } else if (occs == 1) {
21155     LOG (2, "eliminated variable %d occurrs exactly once", pivot);
21156     eliminated = 1;
21157     changed = 0;
21158   } else {
21159     lglgaussgc (lgl);
21160     subst = lglgausspickeqn (lgl, pivot);
21161     if (subst >= 0) {
21162       lglgaussubst (lgl, pivot, subst);
21163       eliminated = 1;
21164       changed = 1;
21165     } else {
21166       eliminated = 3;
21167       changed = 0;
21168     }
21169   }
21170   lgl->gauss->eliminated[pivot] = eliminated;
21171   lglgausschkeliminated (lgl);
21172   return changed;
21173 }
21174
21175 static void lglgausselim (LGL * lgl) {
21176   int pivot, changed = 1;
21177   while (!lgl->mt && lgl->gauss->next < lglcntstk (&lgl->gauss->order)) {
21178     if (lgl->stats->gauss.steps.elim >= lgl->limits->gauss.steps.elim) break;
21179     if (lglterminate (lgl)) break;
21180     if (changed) lglgaussort (lgl);
21181     pivot = lglpeek (&lgl->gauss->order, lgl->gauss->next++);
21182     changed = lglgausselimvar (lgl, pivot);
21183   }
21184 }
21185
21186 static void lglgaussinit (LGL * lgl) {
21187   assert (!lgl->gauss);
21188   NEW (lgl->gauss, 1);
21189 }
21190
21191 static void lglgaussreset (LGL * lgl) {
21192   assert (lgl->gauss);
21193   if (lgl->gauss->occs) lglgaussdisconnect (lgl);
21194   if (lgl->gauss->eliminated) DEL (lgl->gauss->eliminated, lgl->nvars);
21195   lglrelstk (lgl, &lgl->gauss->xors);
21196   lglrelstk (lgl, &lgl->gauss->order);
21197   DEL (lgl->gauss, 1);
21198 }
21199
21200 static int lglgaussexp2 (LGL * lgl, int a, int b) {
21201   assert (lgl->gaussing);
21202   assert (lglmtstk (&lgl->clause));
21203   if (lglhasbin (lgl, a, b)) return 0;
21204   lglpushstk (lgl, &lgl->clause, a);
21205   lglpushstk (lgl, &lgl->clause, b);
21206   lglpushstk (lgl, &lgl->clause, 0);
21207   LOGCLS (2, lgl->clause.start, "gauss exported binary clause");
21208   assert (!lgl->opts->drup.val);
21209 #ifndef NLGLPICOSAT
21210   lglpicosatchkcls (lgl);
21211 #endif
21212   lgladdcls (lgl, REDCS, 0, 0);
21213   lglclnstk (&lgl->clause);
21214   return 1;
21215 }
21216
21217 static int lglgaussexp3 (LGL * lgl, int a, int b, int c) {
21218   assert (lgl->gaussing);
21219   assert (lglmtstk (&lgl->clause));
21220   if (lglhastrn (lgl, a, b, c)) return 0;
21221   lglpushstk (lgl, &lgl->clause, a);
21222   lglpushstk (lgl, &lgl->clause, b);
21223   lglpushstk (lgl, &lgl->clause, c);
21224   lglpushstk (lgl, &lgl->clause, 0);
21225   LOGCLS (2, lgl->clause.start, "gauss exported ternary clause");
21226   assert (!lgl->opts->drup.val);
21227 #ifndef NLGLPICOSAT
21228   lglpicosatchkcls (lgl);
21229 #endif
21230   lgladdcls (lgl, REDCS, 0, 0);
21231   lglclnstk (&lgl->clause);
21232   return 1;
21233 }
21234
21235 static int lglgaussexport (LGL * lgl) {
21236   int var, size, val, rhs, unit, a, b, c, exported;
21237   const int * e, * p, * q;
21238   for (e = lgl->gauss->xors.start; e < lgl->gauss->xors.top; e = p + 1) {
21239     if (*(p = e) >= NOTALIT) continue;
21240     while ((var = *p) > 1) p++;
21241     rhs = *p;
21242     assert (lglmtstk (&lgl->clause));
21243     for (q = e; q < p; q++) {
21244       var = *q;
21245       val = lglval (lgl, var);
21246       if (val < 0) continue;
21247       if (val > 0) { rhs = !rhs; continue; }
21248       lglpushstk (lgl, &lgl->clause, var);
21249     }
21250     size = lglcntstk (&lgl->clause);
21251     if (!size && !rhs) continue;
21252     if (!size && rhs) {
21253       LOGEQN (1, e - lgl->gauss->xors.start, 
21254               "gauss exporting inconsistent equation");
21255       return 0;
21256     }
21257     a = (size > 0) ? lgl->clause.start[0] : 0;
21258     b = (size > 1) ? lgl->clause.start[1] : 0;
21259     c = (size > 2) ? lgl->clause.start[2] : 0;
21260     lglclnstk (&lgl->clause);
21261     if (size == 1) {
21262       unit = a;
21263       if (!rhs) unit = -unit;
21264       LOG (1, "gauss exporting unit %d", unit);
21265       lgl->stats->gauss.units++;
21266       lglunit (lgl, unit);
21267     } else if (size == 2) {
21268       if (rhs) b = -b;
21269       exported = lglgaussexp2 (lgl, -a, b);
21270       exported |= lglgaussexp2 (lgl, a, -b);
21271       if (exported) {
21272         LOG (1, "gauss exporting equivalence %d = %d", a, b);
21273         lgl->stats->gauss.equivs++;
21274       }
21275     } else if (size == 3 && lgl->opts->gaussexptrn.val) {
21276       if (!rhs) c = -c;
21277       exported = lglgaussexp3 (lgl, a, b, c);
21278       exported |= lglgaussexp3 (lgl, a, -b, -c);
21279       exported |= lglgaussexp3 (lgl, -a, b, -c);
21280       exported |= lglgaussexp3 (lgl, -a, -b, c);
21281       if (exported) {
21282         LOG (1, "gauss exporting ternary equation %d + %d + %d = 1", 
21283              a, b, c);
21284         lgl->stats->gauss.trneqs++;
21285       }
21286     }
21287   }
21288   return 1;
21289 }
21290
21291 static void lglsetgausslim (LGL * lgl) {
21292   int64_t limit, irrlim;
21293   int pen;
21294   limit = (lgl->opts->gaussreleff.val*lglvisearch (lgl))/1000;
21295   if (limit < lgl->opts->gaussmineff.val) limit = lgl->opts->gaussmineff.val;
21296   if (lgl->opts->gaussmaxeff.val >= 0 && limit > lgl->opts->gaussmaxeff.val)
21297     limit = lgl->opts->gaussmaxeff.val;
21298   limit >>= (pen = lgl->limits->gauss.pen + lglszpen (lgl));
21299   irrlim = lgl->stats->irr.clauses.cur/2;
21300   irrlim >>= lgl->limits->simp.pen;
21301   if (lgl->opts->irrlim.val && limit < irrlim) {
21302     limit = irrlim;
21303     lglprt (lgl, 1, "[gauss-%d] limit %lld based on %d irredundant clauses",
21304       lgl->stats->gauss.count, (LGLL) limit, lgl->stats->irr.clauses.cur);
21305   } else
21306     lglprt (lgl, 1, "[gauss-%d] limit %lld penalty %d = %d + %d",
21307       lgl->stats->gauss.count, (LGLL) limit,
21308       pen, lgl->limits->gauss.pen, lglszpen (lgl));
21309   lgl->limits->gauss.steps.extr = lgl->stats->gauss.steps.extr + limit;
21310   lgl->limits->gauss.steps.elim = lgl->stats->gauss.steps.elim + limit;
21311 }
21312
21313 static int lglgauss (LGL * lgl) {
21314   int oldunits, oldequivs, oldtrneqs;
21315   int units, equivs, trneqs;
21316   int success;
21317   assert (lgl->opts->gauss.val);
21318   if (lgl->mt) return 0;
21319   if (lgl->nvars <= 2) return 1;
21320   lglstart (lgl, &lgl->times->gauss);
21321   assert (!lgl->simp && !lgl->gaussing);
21322   lgl->simp = lgl->gaussing = 1;
21323   lgl->stats->gauss.count++;
21324   lglsetgausslim (lgl);
21325   lglgaussinit (lgl);
21326   lglgaussextract (lgl);
21327   oldunits = lgl->stats->gauss.units;
21328   oldequivs = lgl->stats->gauss.equivs;
21329   oldtrneqs = lgl->stats->gauss.trneqs;
21330   if (!lglmtstk (&lgl->gauss->xors)) {
21331     lglgaussconnect (lgl);
21332     lglgaussorder (lgl);
21333     lglsetgausslim (lgl);
21334     lglgausselim (lgl);
21335     if (!lgl->mt && !lglterminate (lgl)) {
21336       if (lgl->opts->verbose.val >= 3) lglgdump (lgl);
21337       lglgaussdisconnect (lgl);
21338       if (!lglgaussexport (lgl) || !lglbcp (lgl)) lgl->mt = 1;
21339       else if (lgl->limits->gauss.steps.extr > lgl->stats->gauss.steps.extr &&
21340                lgl->limits->gauss.steps.elim > lgl->stats->gauss.steps.elim)
21341         lglprt (lgl, 1, "[gauss-%d] fully completed", lgl->stats->gauss.count);
21342     }
21343   }
21344   lglgaussreset (lgl);
21345   units = lgl->stats->gauss.units - oldunits;
21346   equivs = lgl->stats->gauss.equivs - oldequivs;
21347   trneqs = lgl->stats->gauss.trneqs - oldtrneqs;
21348   success = units || equivs;
21349   if (!lgl->mt && success && !lglterminate (lgl) && lgl->opts->decompose.val)
21350     lgldecomp (lgl);
21351   if (trneqs) success = 1;
21352   if (lgl->mt)
21353     lglprt (lgl, 1, "[gauss-%d] proved unsatisfiability",
21354       lgl->stats->gauss.count);
21355   else {
21356     lglprt (lgl, 1, 
21357       "[gauss-%d] exported %d unary, %d binary and %d ternary equations",
21358       lgl->stats->gauss.count, units, equivs, trneqs);
21359   }
21360   LGLUPDPEN (gauss, success);
21361   lglrep (lgl, 2, 'G');
21362   assert (lgl->simp && lgl->gaussing);
21363   lgl->simp = lgl->gaussing = 0;
21364   lglstop (lgl);
21365   return !lgl->mt;
21366 }
21367
21368 /*------------------------------------------------------------------------*/
21369
21370 #define CARDLOGLEVEL 2
21371
21372 static int lglcardsub (LGL * lgl, const int * lits, int bound) {
21373   int count, size, res, minlit, minocc, nocc, lit, pos, otherbound;
21374   Card * card = lgl->card;
21375   const int * p, * c, * q;
21376   Stk * s;
21377   minocc = INT_MAX;
21378   minlit = 0;
21379   for (p = lits; minocc && (lit = *p); p++) {
21380     lglmarkunmarked (lgl, lit);
21381     s = card->occs + lit;
21382     INCSTEPS (card.steps);
21383     nocc = lglcntstk (s);
21384     if (nocc > minocc) continue;
21385     minlit = lit;
21386     minocc = nocc;
21387   }
21388   res = 0;
21389   if (minocc && minlit) {
21390     size = p - lits;
21391     s = card->occs + minlit;
21392     for (p = s->start; p < s->top; p++) {
21393       pos = *p;
21394       c = card->cards.start + pos;
21395       INCSTEPS (card.steps);
21396       otherbound = *c;
21397       if (otherbound > bound) continue;
21398       count = 0;
21399       INCSTEPS (card.steps);
21400       for (q = c + 1; *q; q++) count++;
21401       if (count < size) continue;
21402       count = 0;
21403       INCSTEPS (card.steps);
21404       for (q = c + 1; (count < size) && (lit = *q); q++)
21405         if (lglmarked (lgl, lit) > 0) count++;
21406       if (count >= size) {
21407         LOGCLS (CARDLOGLEVEL, lits,
21408           "subsumed cardinality constraint %d >=", bound);
21409         LOGCLS (CARDLOGLEVEL, c + 1,
21410           "subsuming cardinality constraint %d >=", otherbound);
21411         res = 1;
21412       }
21413     }
21414   }
21415   for (p = lits; (lit = *p); p++) lglunmark (lgl, lit);
21416   return res;
21417 }
21418
21419 static int lglcard1sub (LGL * lgl, const int * lits) {
21420   int res, minlit, minocc, nocc, lit, count, size;
21421   Card * card = lgl->card;
21422   const int * p, * c, * q;
21423   Stk * s;
21424   minocc = INT_MAX;
21425   minlit = 0;
21426   for (p = lits; minocc && (lit = *p); p++) {
21427     lglmarkunmarked (lgl, lit);
21428     s = card->occs + lit;
21429     INCSTEPS (card.steps);
21430     nocc = lglcntstk (s);
21431     if (nocc > minocc) continue;
21432     minlit = lit;
21433     minocc = nocc;
21434   }
21435   res = 0;
21436   if (!minocc || !minlit) goto DONE;
21437   size = p - lits;
21438   s = card->occs + minlit;
21439   count = 0;
21440   for (p = s->start; !res && p < s->top; p++) {
21441     c = card->atmost1.start + *p;
21442     for (q = c; (lit = *q); q++)
21443       if (lglmarked (lgl, lit) && ++count >= size)
21444         break;
21445     if (!lit) continue;
21446     LOGCLS (CARDLOGLEVEL, lits,
21447       "subsumed at-most-one cardinality constraint 1 >=");
21448     LOGCLS (CARDLOGLEVEL, c,
21449       "subsuming at-most-one cardinality constraint 1 >=");
21450     res = 1;
21451   }
21452 DONE:
21453   for (p = lits; (lit = *p); p++) lglunmark (lgl, lit);
21454   return res;
21455 }
21456
21457 static int lglcard2sub (LGL * lgl, const int * lits, int * minlitptr) {
21458   int res, minlit, minocc, nocc, lit, count, size;
21459   Card * card = lgl->card;
21460   const int * p, * c, * q;
21461   Stk * s;
21462   minocc = INT_MAX;
21463   minlit = 0;
21464   for (p = lits; minocc && (lit = *p); p++) {
21465     lglmarkunmarked (lgl, lit);
21466     s = card->occs + lit;
21467     INCSTEPS (card.steps);
21468     nocc = lglcntstk (s);
21469     if (nocc > minocc) continue;
21470     minlit = lit;
21471     minocc = nocc;
21472   }
21473   assert (!minocc || p + 1 == card->atmost2.top);
21474   res = 0;
21475   if (!minocc || !minlit || *minlitptr == minlit) goto DONE;
21476   *minlitptr = minlit;
21477   size = p - lits;
21478   s = card->occs + minlit;
21479   count = 0;
21480   for (p = s->start; !res && p < s->top; p++) {
21481     c = card->atmost2.start + *p;
21482     for (q = c; (lit = *q); q++)
21483       if (lglmarked (lgl, lit) && ++count >= size)
21484         break;
21485     if (!lit) continue;
21486     LOGCLS (CARDLOGLEVEL, lits,
21487       "subsumed at-most-two cardinality constraint 2 >=");
21488     LOGCLS (CARDLOGLEVEL, c,
21489       "subsuming at-most-two cardinality constraint 2 >=");
21490     res = 1;
21491   }
21492 DONE:
21493   for (p = lits; (lit = *p); p++) lglunmark (lgl, lit);
21494   return res;
21495 }
21496
21497 static int lgladdcard (LGL * lgl, const int * lits, int bound) {
21498   Card * card = lgl->card;
21499   const int * p;
21500   int start, lit;
21501 #if !defined(NDEBUG) || !defined(NLGLOG)
21502   int size = 0;
21503   for (p = lits; *p; p++) size++;
21504 #endif
21505   if (lglcardsub (lgl, lits, bound)) {
21506     lgl->stats->card.subsumed++;
21507     return 0;
21508   }
21509   LOGCLS (CARDLOGLEVEL, lits,
21510     "new %s cardinality constraint %d >=",
21511     (bound + 1 < size ? "real" : "pseudo"), bound);
21512   assert (bound <= size);
21513   assert (size <=
21514     lglfactor (lgl, lgl->stats->card.count, lgl->opts->cardmaxlen.val));
21515 #ifndef NDEBUG
21516   for (p = lits; (lit = *p); p++) assert (!card->eliminated[abs (lit)]);
21517   for (p = lits; (lit = *p); p++) assert (!card->count[abs (lit)]);
21518 #endif
21519   assert (card);
21520   start = lglcntstk (&card->cards);
21521   lglpushstk (lgl, &card->cards, bound);
21522   for (p = lits; (lit = *p); p++) {
21523     lglpushstk (lgl, &card->cards, lit);
21524     lglpushstk (lgl, card->occs + lit, start);
21525   }
21526   lglpushstk (lgl, &card->cards, 0);
21527   return 1;
21528 }
21529
21530 static void lglcardfmstep (LGL * lgl, int pivot,
21531                            int cardposidx, int cardnegidx) {
21532   int bn, bp, ln, lp, b, c, s, lit, idx, addcard, len, unit[2], div, elim;
21533   const int cardcut = lgl->opts->cardcut.val;
21534   const int * p, * q, * cn, * cp;
21535   int * r, divsame, cardmaxlen;
21536   Card * card = lgl->card;
21537   INCSTEPS (card.steps);
21538   lgl->stats->card.resolved++;
21539   assert (0 <= cardposidx && cardposidx < lglcntstk (&card->cards));
21540   assert (0 <= cardnegidx && cardnegidx < lglcntstk (&card->cards));
21541   cp = card->cards.start + cardposidx;
21542   cn = card->cards.start + cardnegidx;
21543   bp = *cp++; assert (bp >= 0);
21544   bn = *cn++; assert (bp >= 0);
21545   LOGCLS (CARDLOGLEVEL, cp,
21546     "first antecedent fourier-motzkin on %d cardinality constraint %d >=",
21547     pivot, bp);
21548   LOGCLS (CARDLOGLEVEL, cn,
21549     "second antecedent fourier-motzkin on %d cardinality constraint %d >=",
21550     -pivot, bn);
21551   b = bp + bn;
21552   LOG (CARDLOGLEVEL, "starting with bound %d", b);
21553   assert (lglmtstk (&lgl->clause));
21554   for (p = cp; (lit = *p); p++) {
21555     idx = abs (lit);
21556     assert (!card->count[idx]);
21557     lglpushstk (lgl, &lgl->clause, idx);
21558     card->count[idx] += lglsgn (lit);
21559   }
21560   lp = p - cp;
21561   assert (bp < lp);
21562   elim = 0;
21563   div = 1;
21564   for (q = cn; (lit = *q); q++) {
21565     idx = abs (lit);
21566     c = card->count[idx];
21567     assert (!c || abs (c) == 1);
21568     s = lglsgn (lit);
21569     if (!c) lglpushstk (lgl, &lgl->clause, idx);
21570     card->count[idx] += s;
21571     if (c && c != s) elim++;
21572     if (c == s) div = 2;
21573   }
21574   ln = q - cn;
21575   assert (bn < ln);
21576   divsame = 1;
21577   for (p = lgl->clause.start; divsame && p < lgl->clause.top; p++) {
21578     idx = abs (*p);
21579     c = card->count[idx];
21580     if (!c) continue;
21581     if (c < 0) c = -c;
21582     divsame = (c == div);
21583   }
21584 #ifndef NLGLOG
21585   if (lgl->opts->log.val >= CARDLOGLEVEL) {
21586     int first = 1;
21587     lglogstart (lgl, CARDLOGLEVEL,
21588       "pseudo-boolean resolvent %d - %d >= ", b, elim);
21589     for (p = lgl->clause.start; p < lgl->clause.top; p++) {
21590       idx = *p;
21591       assert (1 < idx), assert (idx < lgl->nvars);
21592       c = card->count[idx];
21593       if (!c) continue;
21594       if (!first)
21595         fprintf (lgl->out, " %c ", (c < 0) ? '-' : '+');
21596       else if (c < 0)
21597         fputs ("-", lgl->out);
21598       first = 0;
21599       c = abs (c);
21600       assert (c > 0);
21601       if (c != 1) fprintf (lgl->out, "%d*", c);
21602       fprintf (lgl->out, "%d", idx);
21603     }
21604     if (first) fputs ("0", lgl->out);
21605     lglogend (lgl);
21606   }
21607 #endif
21608   LOG (CARDLOGLEVEL,
21609     "size %d cardinalty resolvent contains %d eliminated division %d %s", 
21610     lglcntstk (&lgl->clause) - elim, elim, div, divsame ? "all" : "some");
21611   r = lgl->clause.start;
21612   for (p = r; p < lgl->clause.top; p++) {
21613     idx = *p;
21614     c = card->count[idx];
21615     if (divsame || cardcut == 1) c /= div;
21616     else if (abs (c) != 1 && cardcut == 2 && div == 2) c = 0;
21617     if (!c) continue;
21618     lit = (c < 0) ? -idx : idx;
21619     *r++ = lit;
21620   }
21621   lgl->clause.top = r;
21622   b -= elim;
21623   assert (div == 1 || div == 2);
21624   if ((divsame || cardcut == 1) && div == 2) b /= 2;
21625   len = lglcntstk (&lgl->clause);
21626   lglpushstk (lgl, &lgl->clause, 0);
21627   addcard = 0;
21628   cardmaxlen =
21629     lglfactor (lgl, lgl->stats->card.count, lgl->opts->cardmaxlen.val);
21630   if (!cardcut && div > 1) {
21631     LOG (CARDLOGLEVEL,
21632       "ignoring resolved cardinality constraint which requires cut");
21633     assert (!addcard);
21634   } else if (b < 0) {
21635     assert (!addcard);
21636     assert (!lgl->mt);
21637     LOGCLS (CARDLOGLEVEL, lgl->clause.start,
21638       "inconsistent cardinality constraint %d >=", b);
21639     lgl->mt = 1;
21640   } else if (b == 0) {
21641     assert (!addcard);
21642     LOGCLS (CARDLOGLEVEL, lgl->clause.start,
21643       "forcing cardinality constraint %d >=", b);
21644     for (p = lgl->clause.start; p < lgl->clause.top - 1; p++) {
21645       lit = *p;
21646       assert (lit);
21647       lgl->stats->card.units++;
21648       lglpushstk (lgl, &lgl->card->units, -lit);
21649       card->count[abs (lit)] = 0;
21650       unit[0] = lit;
21651       unit[1] = 0;
21652       (void) lgladdcard (lgl, unit, 0);
21653     }
21654   } else if (b >= len) {
21655     LOGCLS (CARDLOGLEVEL, lgl->clause.start,
21656       "trivial resolved cardinality constraint %d >=", b);
21657     assert (!addcard);
21658   } else if (len > cardmaxlen) {
21659     LOGCLS (CARDLOGLEVEL, lgl->clause.start, 
21660       "length %d exceeds limit %d of resolved cardinality constraint %d >=",
21661       len, cardmaxlen, b);
21662   } else {
21663     addcard = 1;
21664     assert (0 < b);
21665     LOGCLS (CARDLOGLEVEL, lgl->clause.start,
21666       "resolved cardinality constraint %d >=", b);
21667     if (b == 1 && 
21668         ((ln >= 3 && lp >= 3) ||
21669          lglcntstk (&lgl->clause) > 
21670            lglfactor (lgl,
21671              lgl->stats->card.count, lgl->opts->cardexpam1.val))) {
21672       LOGCLS (CARDLOGLEVEL, lgl->clause.start,
21673         "saving to export at-most-one constraint 1 >=");
21674       for (p = lgl->clause.start; p < lgl->clause.top; p++)
21675         lglpushstk (lgl, &lgl->card->expam1, *p);
21676     }
21677   }
21678   cp = card->cards.start + cardposidx + 1;
21679   cn = card->cards.start + cardnegidx + 1;
21680   for (p = cp; (lit = *p); p++) card->count[abs (lit)] = 0;
21681   for (q = cn; (lit = *q); q++) card->count[abs (lit)] = 0;
21682   if (addcard > 0) (void) lgladdcard (lgl, lgl->clause.start, b);
21683   lglclnstk (&lgl->clause);
21684   // COVER (cardcut == 2 && div == 2 && divsame);
21685 }
21686
21687 static void lglrmcardexcept (LGL * lgl, int cardidx, int except) {
21688   Card * card = lgl->card;
21689   int * c, * p, lit;
21690   assert (0 <= cardidx && cardidx < lglcntstk (&card->cards));
21691   c = card->cards.start + cardidx + 1;
21692   LOGCLS (CARDLOGLEVEL, c, "removing cardinality constraint %d >=", c[-1]);
21693   for (p = c; (lit = *p); p++)
21694     if (lit != except)
21695       lglrmstk (card->occs + lit, cardidx);
21696 }
21697
21698 static int lglcardocc (LGL * lgl, int a) {
21699   return lglcntstk (lgl->card->occs + a);
21700 }
21701
21702 static int lglcmpcard (LGL * lgl, int a, int b) {
21703   int64_t s = lglcardocc (lgl, a) * (int64_t) lglcardocc (lgl, -a);
21704   int64_t t = lglcardocc (lgl, b) * (int64_t) lglcardocc (lgl, -b);
21705   if (s > t) return -1;
21706   if (s < t) return 1;
21707   return b - a;
21708 }
21709
21710 #define LGLCMPCARD(A,B) lglcmpcard (lgl, *(A), *(B))
21711
21712 static void lglcardresched (LGL * lgl) {
21713   Stk * elim = &lgl->card->elim;
21714   int count = lglcntstk (elim);
21715   ADDSTEPS (card.steps, 4*count);
21716   SORT (int, elim->start, lglcntstk (elim), LGLCMPCARD);
21717   lgl->stats->card.resched++;
21718 }
21719
21720 static void lglcardfmlit (LGL * lgl, int pivot) {
21721   Stk * poccs = lgl->card->occs + pivot, * noccs = lgl->card->occs - pivot;
21722   int pcnt = lglcntstk (poccs), ncnt = lglcntstk (noccs);
21723   int count = lgl->stats->card.count;
21724   const int * p, * q;
21725   assert (pivot > 0);
21726   assert (!lgl->card->eliminated[pivot]);
21727   if (!pcnt || !ncnt) goto DONE;
21728   if (pcnt > lglfactor (lgl, lgl->opts->cardocclim1.val, count)) goto DONE;
21729   if (ncnt > lglfactor (lgl, lgl->opts->cardocclim1.val, count)) goto DONE;
21730   if (pcnt > lglfactor (lgl, lgl->opts->cardocclim2.val, count) &&
21731       ncnt > lglfactor (lgl, lgl->opts->cardocclim2.val, count)) goto DONE;
21732   lgl->stats->card.eliminated++;
21733   lgl->card->eliminated[pivot] = 1;
21734   LOG (CARDLOGLEVEL,
21735     "fourier-motzkin pivot %d with %d positive and %d negative occurrences",
21736     pivot, pcnt, ncnt);
21737   for (p = poccs->start; !lgl->mt && p < poccs->top; p++)
21738     for (q = noccs->start; !lgl->mt && q < noccs->top; q++)
21739       lglcardfmstep (lgl, pivot, *p, *q);
21740 DONE:
21741   for (p = poccs->start; !lgl->mt && p < poccs->top; p++) {
21742     lglrmcardexcept (lgl, *p, pivot);
21743     INCSTEPS (card.steps);
21744   }
21745   for (q = noccs->start; !lgl->mt && q < noccs->top; q++) {
21746     lglrmcardexcept (lgl, *q, -pivot);
21747     INCSTEPS (card.steps);
21748   }
21749   lglrelstk (lgl, poccs);
21750   lglrelstk (lgl, noccs);
21751   if (!(lgl->stats->card.eliminated % lgl->opts->cardreschedint.val))
21752     lglcardresched (lgl);
21753 }
21754
21755 static void lglcardfm (LGL * lgl) {
21756   Stk * elim;
21757   lglcardresched (lgl);
21758   elim = &lgl->card->elim;
21759   while (!lgl->mt && 
21760          !lglmtstk (elim) &&
21761          !lglterminate (lgl) &&
21762          lgl->limits->card.steps >= INCSTEPS (card.steps))
21763     lglcardfmlit (lgl, lglpopstk (elim));
21764 }
21765
21766 static int64_t lglsetcardlim (LGL * lgl) {
21767   int64_t limit, irrlim;
21768   int pen;
21769   limit = (lgl->opts->cardreleff.val*lglvisearch (lgl))/1000;
21770   if (limit < lgl->opts->cardmineff.val) limit = lgl->opts->cardmineff.val;
21771   if (lgl->opts->cardmaxeff.val >= 0 && limit > lgl->opts->cardmaxeff.val)
21772     limit = lgl->opts->cardmaxeff.val;
21773   limit >>= (pen = lgl->limits->card.pen + lglszpen (lgl));
21774   irrlim = lgl->stats->irr.clauses.cur/4;
21775   irrlim >>= lgl->limits->simp.pen;
21776   if (lgl->opts->irrlim.val && limit < irrlim) {
21777     limit = irrlim;
21778     lglprt (lgl, 1,
21779       "[card-%d] limit %lld based on %d irredundant clauses",
21780       lgl->stats->card.count, (LGLL) limit, lgl->stats->irr.clauses.cur);
21781   } else
21782     lglprt (lgl, 1, "[card-%d] limit %lld penalty %d = %d + %d",
21783       lgl->stats->card.count, (LGLL) limit,
21784       pen, lgl->limits->card.pen, lglszpen (lgl));
21785   lgl->limits->card.steps = lgl->stats->card.steps + limit;
21786   return limit;
21787 }
21788
21789 static void lglsetcardlimagain (LGL * lgl, int64_t limit) {
21790   lglprt (lgl, 1,
21791     "[card-%d] using previous limit %lld for elimination",
21792     lgl->stats->card.count, (LGLL) limit, lgl->stats->irr.clauses.cur);
21793   lgl->limits->card.steps = lgl->stats->card.steps + limit;
21794 }
21795
21796 static int lglcard1extractlit (LGL * lgl, int lit) {
21797   const int ignused = lgl->opts->cardignused.val;
21798   int start, size, trivial, subsumed;
21799   int blit, tag, other, other2, i;
21800   const int * p, * w, * eow;
21801   Card * card;
21802   HTS * hts;
21803   if (lglterminate (lgl)) return 0;
21804   if (lgl->limits->card.steps < INCSTEPS (card.steps)) return 0;
21805   card = lgl->card;
21806   if (ignused && card->lit2used[lit]) return 1;
21807   start = lglcntstk (&card->atmost1);
21808   LOG (CARDLOGLEVEL + 1,
21809     "starting at-most-one clique[%d] for %d",
21810     start, lit);
21811   lglpushstk (lgl, &card->atmost1, lit);
21812   card->marked[lit] = 1;
21813   hts = lglhts (lgl, -lit);
21814   w = lglhts2wchs (lgl, hts);
21815   eow = w + hts->count;
21816   INCSTEPS (card.steps);
21817   for (p = w; p < eow; p++) {
21818     blit = *p;
21819     tag = blit & MASKCS;
21820     if (tag == TRNCS || tag == LRGCS) p++;
21821     if (tag != BINCS) continue;
21822     other = -(blit >> RMSHFT);
21823     if (ignused && card->lit2used[other]) continue;
21824     for (i = start + 1; i < lglcntstk (&card->atmost1); i++) {
21825       other2 = lglpeek (&card->atmost1, i);
21826       INCSTEPS (card.steps);
21827       if (!lglhasbin (lgl, -other, -other2)) break;
21828     }
21829     if (i < lglcntstk (&card->atmost1)) continue;
21830     card->marked[other] = 1;
21831     lglpushstk (lgl, &card->atmost1, other);
21832     LOG (CARDLOGLEVEL + 1,
21833        "adding %d to at-most-one clique[%d] for %d", other, start, lit);
21834   }
21835   size = lglcntstk (&card->atmost1) - start;
21836   trivial = (size <= 2);
21837   if (!ignused) {
21838     lglpushstk (lgl, &card->atmost1, 0);
21839     subsumed = lglcard1sub (lgl, card->atmost1.start + start);
21840     lglpopstk (&card->atmost1);
21841   } else subsumed = 0;
21842   for (p = card->atmost1.start + start; p < card->atmost1.top; p++) {
21843     other = *p;
21844     assert (card->marked[other]);
21845     card->marked[other] = 0;
21846     if (!trivial && !subsumed) card->lit2used[other] = 1;
21847   }
21848   if (trivial || subsumed) {
21849     LOG (CARDLOGLEVEL + 1,
21850       "resetting at-most-one clique[%d] for %d of trivial size %d",
21851       start, lit, size);
21852     lglrststk (&card->atmost1, start);
21853   } else {
21854 #ifndef NLGLOG
21855     if (lgl->opts->log.val >= CARDLOGLEVEL) {
21856       lglogstart (lgl, CARDLOGLEVEL,
21857         "non trivial size %d at-most-one constraint 1 >= ", size);
21858       for (i = start; i < start + size; i++) {
21859         if (i > start) fputs (" + ", lgl->out);
21860         fprintf (lgl->out, "%d", lglpeek (&card->atmost1, i));
21861       }
21862       lglogend (lgl);
21863     }
21864 #endif
21865     if (!ignused) {
21866       for (i = start; i < start + size; i++) {
21867         other = lglpeek (&card->atmost1, i);
21868         lglpushstk (lgl, &card->occs[other], start);
21869       }
21870     }
21871     lglpushstk (lgl, &card->atmost1, 0);
21872     lgl->stats->card.am1.found.sum += size;
21873     lgl->stats->card.am1.found.cnt++;
21874   }
21875   return 1;
21876 }
21877
21878 static void lglcardreloccs (LGL * lgl) {
21879   Card * card = lgl->card;
21880   int sign, idx, lit;
21881   assert (card), assert (!lgl->nvars || card->occs);
21882   for (sign = -1; sign <= 1; sign += 2)
21883     for (idx = 2; idx < lgl->nvars; idx++) {
21884       lit = sign * idx;
21885       lglrelstk (lgl, &card->occs[lit]);
21886     }
21887   card->occs -= lgl->nvars;
21888   DEL (card->occs, 2*lgl->nvars);
21889 }
21890
21891 static int lglcard1extract (LGL * lgl) {
21892   struct { int cnt; int64_t sum; } before, after, delta;
21893   const int ignused = lgl->opts->cardignused.val;
21894   Card * card = lgl->card;
21895
21896   lglpushstk (lgl, &card->atmost1, 0);
21897
21898   NEW (card->lit2used, 2*lgl->nvars);
21899   card->lit2used += lgl->nvars;
21900   NEW (card->marked, 2*lgl->nvars);
21901   card->marked += lgl->nvars;
21902   if (!ignused) {
21903     NEW (card->occs, 2*lgl->nvars);
21904     card->occs += lgl->nvars;
21905   }
21906
21907   before.cnt = lgl->stats->card.am1.found.cnt;
21908   before.sum = lgl->stats->card.am1.found.sum;
21909
21910   lglrandlitrav (lgl, lglcard1extractlit);
21911
21912   after.cnt = lgl->stats->card.am1.found.cnt;
21913   after.sum = lgl->stats->card.am1.found.sum;
21914   assert (after.cnt >= before.cnt);
21915   assert (after.sum >= before.sum);
21916   delta.cnt = after.cnt - before.cnt;
21917   delta.sum = after.sum - before.sum;
21918
21919   card->lit2used -= lgl->nvars;
21920   DEL (card->lit2used, 2*lgl->nvars);
21921   card->marked -= lgl->nvars;
21922   DEL (card->marked, 2*lgl->nvars);
21923   if (!ignused) lglcardreloccs (lgl);
21924
21925   if (delta.cnt)
21926     lglprt (lgl, 1, 
21927       "[card-%d] found %d at-most-one constraints of average size %.1f",
21928       lgl->stats->card.count, delta.cnt, lglavg (delta.sum, delta.cnt));
21929   else
21930     lglprt (lgl, 1,
21931       "[card-%d] no at-most-one constraint found",
21932       lgl->stats->card.count);
21933
21934   return delta.cnt;
21935 }
21936
21937 static int lglcard2extractlit (LGL * lgl, int lit) {
21938   int blit, tag, other, other2, other3, i, j, k, res = 1;
21939   const int ignused = lgl->opts->cardignused.val;
21940   int start, size, minlit;
21941   const int * p, * w, * eow;
21942   int * q;
21943   Card * card;
21944   HTS * hts;
21945   if (lglterminate (lgl)) return 0;
21946   if (lgl->limits->card.steps < INCSTEPS (card.steps)) return 0;
21947   card = lgl->card;
21948   if (ignused && card->lit2used[lit]) return 1;
21949
21950   start = lglcntstk (&card->atmost2);
21951   LOG (CARDLOGLEVEL + 1, "starting at-most-two clique[%d] for %d", start, lit);
21952   assert (!card->lit2count[lit]);
21953   hts = lglhts (lgl, -lit);
21954   w = lglhts2wchs (lgl, hts);
21955   eow = w + hts->count;
21956   INCSTEPS (card.steps);
21957   for (p = w; p < eow; p++) {
21958     blit = *p;
21959     tag = blit & MASKCS;
21960     if (tag == TRNCS || tag == LRGCS) p++;
21961     if (tag != TRNCS) continue;
21962     other = -(blit >> RMSHFT);
21963     other2 = -*p;
21964     if (card->lit2count[-other] || card->lit2count[-other2]) continue;
21965     if (!card->lit2count[lit]++) lglpushstk (lgl, &card->atmost2, lit);
21966     if (!card->lit2count[other]++) lglpushstk (lgl, &card->atmost2, other);
21967     if (!card->lit2count[other2]++) lglpushstk (lgl, &card->atmost2, other2);
21968   }
21969   q = card->atmost2.start + start;
21970   for (p = q; p < card->atmost2.top; p++) {
21971     if (card->lit2count [other =*p] > 1) *q++ = other;
21972     else card->lit2count[other] = 0;
21973   }
21974   card->atmost2.top = q;
21975   size = lglcntstk (&card->atmost2) - start;
21976   if (size < 4) {
21977     LOG (CARDLOGLEVEL + 1,
21978       "less than 4 literals occuring 2 times in ternary clauses with %d",
21979        -lit);
21980 FAILED:
21981     while (lglcntstk (&card->atmost2) > start) {
21982       int lit = lglpopstk (&card->atmost2);
21983       assert (card->lit2count[lit] > 0);
21984       card->lit2count[lit] = 0;
21985     }
21986     return res;
21987   }
21988   minlit = 0;
21989 RESTART:
21990   if (!ignused) {
21991     int subsumed;
21992     lglpushstk (lgl, &card->atmost2, 0);
21993     subsumed = lglcard2sub (lgl, card->atmost2.start + start, &minlit);
21994     lglpopstk (&card->atmost2);
21995     if (subsumed) goto FAILED;
21996   }
21997   LOG (CARDLOGLEVEL + 1, "trying to connect %d literals", size-1);
21998   for (i = 0; i < size-2; i++) {
21999     other = -lglpeek (&card->atmost2, start + i);
22000     for (j = i+1; j < size-1; j++) {
22001       other2 = -lglpeek (&card->atmost2, start + j);
22002       for (k = j+1; k < size; k++) {
22003         if (lgl->limits->card.steps < INCSTEPS (card.steps)) {
22004           LOG (CARDLOGLEVEL + 1, "cardinality extraction step limit hit");
22005           res = 0;
22006           goto FAILED;
22007         }
22008         other3 = -lglpeek (&card->atmost2, start + k);
22009         if (!lglhastrn (lgl, other, other2, other3)) {
22010           LOG (CARDLOGLEVEL + 1,
22011             "ternary clause %d %d %d missing", other, other2, other3);
22012           assert (size >= 4);
22013           if (size == 4) goto FAILED;
22014           int l, tmp;
22015           if (k > j + 1) l = k;
22016           else {
22017             int occ2 = card->lit2count[-other2];
22018             int occ3 = card->lit2count[-other3];
22019             if (occ2 > occ3) l = k;
22020             else if (occ2 < occ3) l = j;
22021             else {
22022               occ2 = lglhts (lgl, other2)->count;
22023               occ3 = lglhts (lgl, other3)->count;
22024               if (occ2 > occ3) l = k;
22025               else if (occ2 < occ3) l = j;
22026               else l = (lglrand (lgl) & 1) ? j : k;
22027             }
22028           }
22029           tmp = lglpeek (&card->atmost2, start + l);
22030           assert (abs (tmp) != abs (lit));
22031           assert (card->lit2count[tmp] > 0);
22032           card->lit2count[tmp] = 0;
22033           while (l + 1 < size) {
22034             tmp = lglpeek (&card->atmost2, start + l + 1);
22035             assert (abs (tmp) != abs (lit));
22036             lglpoke (&card->atmost2, start + l++, tmp);
22037           }
22038           assert (l == size - 1);
22039           card->atmost2.top--;
22040           size--;
22041           assert (size >= 4);
22042           assert (card->atmost2.start + start + size == card->atmost2.top);
22043           goto RESTART;
22044         }
22045       }
22046     }
22047   }
22048 #ifndef NLGLOG
22049   if (lgl->opts->log.val >= CARDLOGLEVEL) {
22050     lglogstart (lgl, CARDLOGLEVEL,
22051       "non trivial size %d at-most-two constraint 2 >= ", size);
22052     for (i = start; i < start + size; i++) {
22053       if (i > start) fputs (" + ", lgl->out);
22054       fprintf (lgl->out, "%d", lglpeek (&card->atmost2, i));
22055     }
22056     lglogend (lgl);
22057   }
22058 #endif
22059   for (i = start; i < start + size; i++) {
22060     other = lglpeek (&card->atmost2, i);
22061     card->lit2count[other] = 0;
22062     card->lit2used[other] = 1;
22063     if (!ignused) lglpushstk (lgl, &card->occs[other], start);
22064   }
22065   lglpushstk (lgl, &card->atmost2, 0);
22066   lgl->stats->card.am2.found.sum += size;
22067   lgl->stats->card.am2.found.cnt++;
22068   return res;
22069 }
22070
22071 static int lglcard2extract (LGL * lgl) {
22072   struct { int cnt; int64_t sum; } before, after, delta;
22073   const int ignused = lgl->opts->cardignused.val;
22074   Card * card = lgl->card;
22075
22076   lglpushstk (lgl, &card->atmost2, 0);
22077   NEW (card->lit2used, 2*lgl->nvars);
22078   card->lit2used += lgl->nvars;
22079   NEW (card->lit2count, 2*lgl->nvars);
22080   card->lit2count += lgl->nvars;
22081   if (!ignused) {
22082     NEW (card->occs, 2*lgl->nvars);
22083     card->occs += lgl->nvars;
22084   }
22085
22086   before.cnt = lgl->stats->card.am2.found.cnt;
22087   before.sum = lgl->stats->card.am2.found.sum;
22088
22089   lglrandlitrav (lgl, lglcard2extractlit);
22090
22091   after.cnt = lgl->stats->card.am2.found.cnt;
22092   after.sum = lgl->stats->card.am2.found.sum;
22093   assert (after.cnt >= before.cnt);
22094   assert (after.sum >= before.sum);
22095   delta.cnt = after.cnt - before.cnt;
22096   delta.sum = after.sum - before.sum;
22097
22098   card->lit2used -= lgl->nvars;
22099   DEL (card->lit2used, 2*lgl->nvars);
22100   card->lit2count -= lgl->nvars;
22101   DEL (card->lit2count, 2*lgl->nvars);
22102   if (!ignused) lglcardreloccs (lgl);
22103
22104   if (delta.cnt)
22105     lglprt (lgl, 1, 
22106       "[card-%d] found %d at-most-two constraints of average size %.1f",
22107       lgl->stats->card.count, delta.cnt, lglavg (delta.sum, delta.cnt));
22108   else
22109     lglprt (lgl, 1,
22110       "[card-%d] no at-most-two constraint found",
22111       lgl->stats->card.count);
22112
22113   return delta.cnt;
22114 }
22115
22116 static int lglcarduseclswithlit (LGL * lgl, int lit) {
22117   int pos = !lglmtstk (lgl->card->occs + lit);
22118   int neg = !lglmtstk (lgl->card->occs - lit);
22119   int level = lgl->opts->carduse.val;
22120   switch (level) {
22121     case 0: return 0;
22122     case 1: return pos && !neg;
22123     case 2: return pos;
22124     default: assert (level == 3); return pos || neg;
22125   }
22126 }
22127
22128 static int lglcardelim (LGL * lgl, int count) {
22129   int blit, tag, other, other2, bound, used;
22130   int idx, sign, lit, start, len, res, glue;
22131   const int * p, * w, * eow, * c, * q;
22132   Card * card = lgl->card;
22133   int cardmaxlen;
22134   int clause[4];
22135   HTS * hts;
22136   Stk * s;
22137
22138   NEW (card->occs, 2*lgl->nvars);
22139   NEW (card->eliminated, lgl->nvars);
22140   NEW (card->count, lgl->nvars);
22141   card->occs += lgl->nvars;
22142   used = 0;
22143   cardmaxlen =
22144     lglfactor (lgl, lgl->stats->card.count, lgl->opts->cardmaxlen.val);
22145   for (start = 1; start < lglcntstk (&card->atmost1); start++) {
22146     for (len = 0; lglpeek (&card->atmost1, start + len); len++)
22147       ;
22148     if (len >= lgl->opts->cardminlen.val &&
22149         len <= cardmaxlen &&
22150         lgladdcard (lgl, card->atmost1.start + start, 1)) {
22151       lgl->stats->card.am1.used.sum += len;
22152       lgl->stats->card.am1.used.cnt++;
22153       used++;
22154     }
22155     start += len;
22156   }
22157   for (start = 1; start < lglcntstk (&card->atmost2); start++) {
22158     for (len = 0; lglpeek (&card->atmost2, start + len); len++)
22159       ;
22160     if (len >= lgl->opts->cardminlen.val &&
22161         len <= cardmaxlen &&
22162         lgladdcard (lgl, card->atmost2.start + start, 2)) {
22163       lgl->stats->card.am2.used.sum += len;
22164       lgl->stats->card.am2.used.cnt++;
22165       used++;
22166     }
22167     start += len;
22168   }
22169   if (used) {
22170     lglprt (lgl, 1,
22171       "[card-%d] %d out of %d constraints (%.0f%%) meet size limits",
22172       lgl->stats->card.count, used, count, lglpcnt (used, count));
22173   } else {
22174     lglprt (lgl, 1,
22175       "[card-%d] no constraint out of %d meets size limits",
22176       lgl->stats->card.count, count);
22177     goto SKIP;
22178   }
22179   for (idx = 2; idx < lgl->nvars; idx++) {
22180     if (lglmtstk (card->occs + idx) &&
22181         lglmtstk (card->occs - idx)) continue;
22182     LOG (CARDLOGLEVEL, "variable %d scheduled for elimination", idx);
22183     lglpushstk (lgl, &card->elim, idx);
22184   }
22185   if (!lgl->opts->carduse.val) goto DO_NOT_USE_CLAUSES;
22186   for (idx = 2; idx < lgl->nvars; idx++) {
22187     if (lglterminate (lgl) ||
22188         lgl->limits->card.steps < INCSTEPS (card.steps)) goto SKIP;
22189     for (sign = -1; sign <= 1; sign += 2) {
22190       lit = sign * idx;
22191       if (!lglcarduseclswithlit (lgl, lit)) continue;
22192       hts = lglhts (lgl, lit);
22193       w = lglhts2wchs (lgl, hts);
22194       eow = w + hts->count;
22195       for (p = w; p < eow; p++) {
22196         blit = *p;
22197         tag = blit & MASKCS;
22198         if (tag == TRNCS || tag == LRGCS) p++;
22199         if (tag == BINCS) {
22200           other = blit >> RMSHFT;
22201           if (abs (other) < idx) continue;
22202           clause[0] = -lit, clause[1] = -other, clause[2] = 0;
22203           (void) lgladdcard (lgl, clause, 1);
22204         } else if (tag == TRNCS) {
22205           other = blit >> RMSHFT;
22206           if (abs (other) < idx) continue;
22207           other2 = *p;
22208           if (abs (other2) < idx) continue;
22209           clause[0] = -lit, clause[1] = -other,
22210           clause[2] = -other2, clause[3] = 0;
22211           (void) lgladdcard (lgl, clause, 2);
22212         } else assert (tag == LRGCS);
22213       }
22214     }
22215   }
22216   for (glue = -1; glue <= lgl->opts->cardglue.val; glue++) {
22217     s = (glue < 0) ? &lgl->irr : lgl->red + glue;
22218     for (c = s->start; c < s->top; c = p + 1) {
22219       if (*(p = c) >= NOTALIT) continue;
22220       for (p = c; *p; p++)
22221         ;
22222       for (q = c; (lit = *q); q++)
22223         if (lglcarduseclswithlit (lgl, lit)) break;
22224       if (!lit) continue;
22225       len = p - c;
22226       if (len > cardmaxlen) continue;
22227       assert (len >= 4);
22228       bound = len - 1;
22229       assert (lglmtstk (&lgl->clause));
22230       for (q = c; (lit = *q); q++)
22231         lglpushstk (lgl, &lgl->clause, -lit);
22232       lglpushstk (lgl, &lgl->clause, 0);
22233       (void) lgladdcard (lgl, lgl->clause.start, bound);
22234       lglclnstk (&lgl->clause);
22235       if (lglterminate (lgl) ||
22236           lgl->limits->card.steps < INCSTEPS (card.steps)) goto SKIP;
22237     }
22238   }
22239 DO_NOT_USE_CLAUSES:
22240   lglcardfm (lgl);
22241 SKIP:
22242   lglcardreloccs (lgl);
22243   DEL (card->count, lgl->nvars);
22244   lglrelstk (lgl, &card->cards);
22245   lglrelstk (lgl, &card->elim);
22246   DEL (card->eliminated, lgl->nvars);
22247   if (lgl->mt)
22248     lglprt (lgl, 1,
22249       "[card-%d] produced empty clause",
22250       lgl->stats->card.count);
22251   else if (!lglmtstk (&card->units)) {
22252     lglprt (lgl, 1,
22253        "[card-%d] found %d units",
22254        lgl->stats->card.count, lglcntstk (&card->units));
22255     while (!lgl->mt && !lglmtstk (&card->units)) {
22256       lit = lglpopstk (&card->units);
22257       if (lglval (lgl, lit) > 0) continue;
22258       if (lglval (lgl, lit) < 0) {
22259         lglprt (lgl, 1,
22260           "[card-%d] found inconsistent unit",
22261           lgl->stats->card.count);
22262         lgl->mt = 1;
22263       } else {
22264         lglunit (lgl, lit);
22265         if (!lglbcp (lgl)) {
22266           lglprt (lgl, 1,
22267             "[card-%d] inconsistent unit propagation",
22268             lgl->stats->card.count);
22269           assert (!lgl->mt);
22270           lgl->mt = 1;
22271         }
22272       }
22273     }
22274   }
22275   res = lglcntstk (&card->units);
22276   lglrelstk (lgl, &card->units);
22277   if (!lgl->mt) {
22278     if (res)
22279       lglprt (lgl, 1, 
22280         "[card-%d] found %d units", lgl->stats->card.count, res);
22281     else
22282       lglprt (lgl, 1, "[card-%d] no units found", lgl->stats->card.count);
22283
22284     if (!lglmtstk (&card->expam1)) {
22285       int generated = 0, exported = 0, genused = 0;
22286       for (c = card->expam1.start; c < card->expam1.top; c = p + 1) {
22287         int a, usefull = 0;
22288         generated++;
22289         for (p = c; (a = *p); p++) if (lglval (lgl, a)) break;
22290         if (a) { while (*++p) ; continue; }
22291         for (p = c; (a = -*p); p++) {
22292           int b;
22293           for (q = p + 1; (b = -*q); q++)
22294             if (!lglhasbin (lgl, a, b)) {
22295               LOG (CARDLOGLEVEL,
22296                 "exporting at-most-one constraint binary clause %d %d",
22297                 a, b);
22298               assert (lglmtstk (&lgl->clause));
22299               lglpushstk (lgl, &lgl->clause, a);
22300               lglpushstk (lgl, &lgl->clause, b);
22301               lglpushstk (lgl, &lgl->clause, 0);
22302               lgladdcls (lgl, REDCS, 0, 1);
22303               lglclnstk (&lgl->clause);
22304               lgl->stats->card.expam1++;
22305               exported++;
22306               usefull = 1;
22307               assert (!lgl->opts->drup.val);
22308 #ifndef NLGLPICOSAT
22309               lglpicosatchkclsarg (lgl, a, b, 0);
22310 #endif
22311             }
22312         }
22313         if (usefull) genused++;
22314       }
22315       lglprt (lgl, 1,
22316         "[card-%d] generated %d at-most-one constraints, %d used %.0f%%",
22317         lgl->stats->card.count,
22318         generated, genused, lglpcnt (genused, generated));
22319       lglprt (lgl, 1,
22320         "[card-%d] exported %d binary clauses, %.1f per/constraint",
22321         lgl->stats->card.count, exported, lglavg (exported, genused));
22322     } else
22323       lglprt (lgl, 1, 
22324         "[card-%d] no at-most-one constraints generated",
22325         lgl->stats->card.count);
22326   }
22327   lglrelstk (lgl, &card->expam1);
22328   return res;
22329 }
22330
22331 static int lglcard (LGL * lgl) {
22332   int success, count;
22333   int64_t limit;
22334   assert (!lgl->mt);
22335   lglstart (lgl, &lgl->times->card);
22336   lgl->stats->card.count++;
22337   if (lgl->level) lglbacktrack (lgl, 0);
22338   limit = lglsetcardlim (lgl);
22339   assert (!lgl->card);
22340   NEW (lgl->card, 1);
22341   count = lglcard1extract (lgl) + lglcard2extract (lgl);
22342   if (!lglterminate (lgl) && count) {
22343     lglsetcardlimagain (lgl, limit);
22344     success = lglcardelim (lgl, count);
22345   } else success = 0;
22346   lglrelstk (lgl, &lgl->card->atmost1);
22347   lglrelstk (lgl, &lgl->card->atmost2);
22348   DEL (lgl->card, 1);
22349   LGLUPDPEN (card, success);
22350   lglstop (lgl);
22351   return !lgl->mt;
22352 }
22353
22354 /*------------------------------------------------------------------------*/
22355
22356 static int lglrdpclslim (LGL * lgl) {
22357   int64_t res64;
22358   int res;
22359   res64 = lgl->opts->rdpclslim.val + (int64_t) lgl->stats->rdp.count;
22360   res = res64 > INT_MAX ? INT_MAX : res64;
22361   return res;
22362 }
22363
22364 static void lglrdpaddcls (LGL * lgl, const int * c) {
22365   int cidx = lglcntstk (&lgl->rdp->lits), lit;
22366   const int * p;
22367   for (p = c; (lit = *p); p++)
22368     ;
22369   if (p - c > lglrdpclslim (lgl) + 1) return;
22370   for (p = c; (lit = *p); p++) {
22371     lgl->rdp->count[lit]++;
22372     lglpushstk (lgl, &lgl->rdp->occs[lit], cidx);
22373     lglpushstk (lgl, &lgl->rdp->lits, lit);
22374   }
22375   lglpushstk (lgl, &lgl->rdp->lits, 0);
22376 }
22377
22378 static void lglrdpconbintrn (LGL *  lgl) {
22379   int idx, sign, lit, blit, tag, red, other, other2, cls[4];
22380   const int * p, * w, * eow;
22381   HTS * hts;
22382   for (sign = -1; sign <= 1; sign += 2)
22383     for (idx = 2; idx < lgl->nvars; idx++) {
22384       lit = sign * idx;
22385       hts = lglhts (lgl, lit);
22386       w = lglhts2wchs (lgl, hts);
22387       eow = w + hts->count;
22388       for (p = w; p < eow; p++) {
22389         blit = *p;
22390         tag = blit & MASKCS;
22391         red = blit & REDCS;
22392         if (tag == TRNCS || tag == LRGCS) p++;
22393         if (tag == LRGCS) continue;
22394         if (tag == BINCS) {
22395           if (red && lgl->opts->rdp.val < 2) continue;
22396           other = blit >> RMSHFT;
22397           if (abs (other) < idx) continue;
22398           cls[0] = lit, cls[1] = other, cls[2] = 0;
22399         } else if (tag == TRNCS) {
22400           if (red && lgl->opts->rdp.val < 3) continue;
22401           other = blit >> RMSHFT;
22402           if (abs (other) < idx) continue;
22403           other2 = *p;
22404           if (abs (other2) < idx) continue;
22405           cls[0] = lit, cls[1] = other, cls[2] = other2, cls[3] = 0;
22406         }
22407         lglrdpaddcls (lgl, cls);
22408       }
22409     }
22410 }
22411
22412 static void lglrdpconlrg (LGL * lgl) {
22413   const int * c, * p;
22414   for (c = lgl->irr.start; c < lgl->irr.top; c = p + 1) {
22415     if (*(p = c) >= NOTALIT) continue;
22416     assert (*p);
22417     while (*++p)
22418       ;
22419     lglrdpaddcls (lgl, c);
22420   }
22421 }
22422
22423 static void lglrdpreport (LGL * lgl) {
22424   lglgenericreport (lgl,
22425     "rdp", lgl->stats->rdp.count,
22426     lgl->rdp->eliminated, lgl->nvars, lgl->rdp->start);
22427 }
22428
22429 static void lglrdpinit (LGL * lgl) {
22430   NEW (lgl->rdp, 1);
22431   lgl->rdp->start = lglgetime (lgl);
22432   lglrdpreport (lgl);
22433   NEW (lgl->rdp->count, 2*lgl->nvars);
22434   lgl->rdp->count += lgl->nvars;
22435   NEW (lgl->rdp->occs, 2*lgl->nvars);
22436   lgl->rdp->occs += lgl->nvars;
22437   lglrdpconbintrn (lgl);
22438   lglrdpconlrg (lgl);
22439   lglfitstk (lgl, &lgl->rdp->lits);
22440 }
22441
22442 static void lglrdpreset (LGL * lgl) {
22443   int nvars = lgl->nvars;
22444   Stk * p;
22445   for (p = lgl->rdp->occs - nvars; p < lgl->rdp->occs + nvars; p++)
22446     lglrelstk (lgl, p);
22447   lgl->rdp->occs -= nvars;
22448   DEL (lgl->rdp->occs, 2*nvars);
22449   lgl->rdp->count -= nvars;
22450   DEL (lgl->rdp->count, 2*nvars);
22451   lglrelstk (lgl, &lgl->rdp->lits);
22452   DEL (lgl->rdp, 1);
22453 }
22454
22455 #define RDPL 2
22456
22457 static void lglrdpcollect (LGL * lgl, Stk * s) {
22458   int * q = s->start;
22459   const int * p;
22460   for (p = q; p < s->top; p++) {
22461     int cidx = *p;
22462     const int * c = lgl->rdp->lits.start + cidx;
22463     assert (c < lgl->rdp->lits.top);
22464     if (*c != REMOVED) *q++ = cidx;
22465   }
22466   LOG (RDPL, "collected %ld references", (long)(s->top - q));
22467   s->top = q;
22468 }
22469
22470 static void lglrdpflush (LGL * lgl, Stk * s) {
22471   const int * p, * q;
22472   for (p = s->start; p < s->top; p++) {
22473     int cidx = *p, * c = lgl->rdp->lits.start + cidx, lit;
22474     assert (c < lgl->rdp->lits.top);
22475     INCSTEPS (rdp.steps);
22476     for (q = c; (lit = *q); q++) {
22477       assert (lgl->rdp->count[lit] > 0);
22478       lgl->rdp->count[lit]--;
22479     }
22480     *c = REMOVED;
22481   }
22482   LOG (RDPL, "flushed %d references", lglcntstk (s));
22483 }
22484
22485 static int lglrdpresolve (LGL * lgl, int pivot, int cidx, int didx) {
22486   int res, lit, val, csize, dsize, rsize, resolventsize, conlypos, donlypos;
22487   const int * c = lgl->rdp->lits.start + cidx, * p;
22488   const int * d = lgl->rdp->lits.start + didx;
22489   const int64_t lim = lglrdpclslim (lgl);
22490   res = resolventsize = 0;
22491   assert (pivot > 0);
22492   assert (c < lgl->rdp->lits.top);
22493   assert (d < lgl->rdp->lits.top);
22494   assert (lglmtstk (&lgl->clause));
22495   INCSTEPS (rdp.steps);
22496   lgl->stats->rdp.res++;
22497   LOGCLS (RDPL+1, c, "RDP resolution 1st antecedent");
22498   conlypos = 1;
22499   for (p = c; resolventsize <= lim && (lit = *p); p++) {
22500     if (lit == pivot) continue;
22501     if (lit < 0) conlypos = 0;
22502     assert (lit != -pivot);
22503     val = lglval (lgl, lit);
22504     if (val < 0) continue;
22505     if (val > 0) {
22506       assert (!res);
22507       LOG (RDPL + 1, "1st antecedent statisfied");
22508       goto DONE;
22509     }
22510     lglpushstk (lgl, &lgl->clause, lit);
22511     lglmark (lgl, lit);
22512     resolventsize++;
22513   }
22514   csize = p - c;
22515   LOGCLS (RDPL+1, d, "RDP resolution 2nd antecedent");
22516   donlypos = 1;
22517   for (p = d; resolventsize <= lim && (lit = *p); p++) {
22518     if (-lit == pivot) continue;
22519     if (lit < 0) donlypos = 0;
22520     assert (lit != -pivot);
22521     val = lglval (lgl, lit);
22522     if (val < 0) continue;
22523     if (val > 0) {
22524       assert (!res);
22525       LOG (RDPL + 1, "2nd antecedent statisfied");
22526       goto DONE;
22527     }
22528     val = lglmarked (lgl, lit);
22529     if (val > 0) continue;
22530     if (val < 0) {
22531       assert (!res);
22532       LOG (RDPL + 1, "skipping trivial RDP resolvent");
22533       goto DONE;
22534     } 
22535     lglpushstk (lgl, &lgl->clause, lit);
22536     resolventsize++;
22537   }
22538   if (resolventsize > lim) {
22539     LOG (RDPL+1, "RDP larger than %d literals", lim);
22540     lgl->stats->rdp.limhit.len++;
22541     assert (!res);
22542     goto DONE;
22543   }
22544   if (resolventsize > 1 &&
22545       lgl->opts->rdpmodelm.val && !conlypos && !donlypos) {
22546     LOG (RDPL+1, "RDP model elimination prohibits resolution");
22547     lgl->stats->rdp.limhit.model++;
22548     assert (!res);
22549     goto DONE;
22550   }
22551   dsize = p - d;
22552   rsize = lglcntstk (&lgl->clause);
22553   assert (rsize == resolventsize);
22554   lglpushstk (lgl, &lgl->clause, 0);
22555   LOGCLS (RDPL+1, lgl->clause.start, "add non-trivial RDP resolvent");
22556   lglrdpaddcls (lgl, lgl->clause.start);
22557   if (!rsize) {
22558     LOG (1, "RDP produced empty clause");
22559     lgl->mt = 1;
22560   } else if (rsize == 1) {
22561     lit = lglpeek (&lgl->clause, 0);
22562     val = lglval (lgl, lit);
22563     if (val < 0) {
22564       LOG (1, "RDP produced inconsistent unit %d", lit);
22565       lgl->mt = 1;
22566     } else if (!val) {
22567       LOG (1, "RDP produced unit %d", lit);
22568       lgl->stats->rdp.units++;
22569       lglunit (lgl, lit);
22570       if (!lglbcp (lgl)) {
22571         LOG (1, "propagating RDP units produces empty clause");
22572         lgl->mt = 1;
22573       }
22574     }
22575   } else if (rsize == 2 && (csize > 2 || dsize > 2)) {
22576     int a = lglpeek (&lgl->clause, 0);
22577     int b = lglpeek (&lgl->clause, 1);
22578     INCSTEPS (rdp.steps);
22579     if (!lglhasbin (lgl, a, b)) {
22580       LOGCLS (RDPL+1, lgl->clause.start, "exporting binary RDP resolvent");
22581       lgladdcls (lgl, REDCS, 0, 1);
22582       lgl->stats->rdp.bin++;
22583 #ifndef NLGLPICOSAT
22584       lglpicosatchkcls (lgl);
22585 #endif
22586     }
22587   } else if (rsize == 3 && (csize > 3 || dsize > 3)) {
22588     int a = lglpeek (&lgl->clause, 0);
22589     int b = lglpeek (&lgl->clause, 1);
22590     int c = lglpeek (&lgl->clause, 2);
22591     INCSTEPS (rdp.steps);
22592     if (!lglhastrn (lgl, a, b, c)) {
22593       LOGCLS (RDPL+1, lgl->clause.start, "exporting ternary RDP resolvent");
22594       lgladdcls (lgl, REDCS, 0, 1);
22595       lgl->stats->rdp.trn++;
22596 #ifndef NLGLPICOSAT
22597       lglpicosatchkcls (lgl);
22598 #endif
22599     }
22600   }
22601   res = 1;
22602 DONE:
22603   while (!lglmtstk (&lgl->clause)) {
22604     lit = lglpopstk (&lgl->clause);
22605     if (lit) lglunmark (lgl, lit);
22606   }
22607   return res;
22608 }
22609
22610 static int lglrdplit (LGL * lgl, int idx) {
22611   int64_t npos, nneg, k, i, j, r, p, s, l;
22612   Stk * pos = &lgl->rdp->occs[idx];
22613   Stk * neg = &lgl->rdp->occs[-idx];
22614   lgl->stats->rdp.elim += 1;
22615   LOG (RDPL,
22616     "RDP pivot %d: pos %d/%d + neg %d/%d",
22617     idx,
22618     lgl->rdp->count[idx], lglcntstk (pos),
22619     lgl->rdp->count[-idx], lglcntstk (neg));
22620   lglrdpcollect (lgl, pos), lglrdpcollect (lgl, neg);
22621   assert (lgl->rdp->count[idx] >= lglcntstk (pos));
22622   assert (lgl->rdp->count[-idx] >= lglcntstk (neg));
22623   npos = lglcntstk (pos), nneg = lglcntstk (neg);
22624   if (!npos || !nneg) goto DONE;
22625   l = ((npos + nneg) * lgl->opts->rdplim.val + 50)/100;
22626   r = npos * nneg;
22627   p = lglrand (lgl);
22628   while (!p || lglgcd64 (p, r) != 1) p++;
22629   p = p % r;
22630   s = k = lglrand (lgl) % r;
22631   LOG (RDPL,
22632     "RDP traversal range %lld = %lld * %lld start %lld period %lld limit %lld",
22633     (LGLL) r, (LGLL) npos, (LGLL) nneg, (LGLL) s, (LGLL) p, (LGLL) l);
22634   do {
22635     i = k / nneg, j = k % nneg;
22636     LOG (RDPL + 1, "trying index %lld RDP pair %d %d", (LGLL) k, i, j);
22637     if (lglrdpresolve (lgl, idx, lglpeek (pos, i), lglpeek (neg, j))) l--;
22638     k += p; if (k >= r) k -= r;
22639     assert (0 <= k && k < r);
22640     if (l < 0) lgl->stats->rdp.limhit.bound++;
22641   } while (!lgl->mt && l >= 0 && s != k);
22642 DONE:
22643   lglrdpflush (lgl, pos), lglrdpflush (lgl, neg);
22644   lglrelstk (lgl, pos), lglrelstk (lgl, neg);
22645   lgl->rdp->eliminated++;
22646   lglrdpreport (lgl);
22647   return !lgl->mt && lgl->stats->rdp.steps < lgl->limits->rdp.steps;
22648 }
22649
22650 static void lglsetrdplim (LGL * lgl) {
22651   int64_t limit, irrlim;
22652   int pen;
22653   limit = (lgl->opts->rdpreleff.val*lglvisearch (lgl))/1000;
22654   if (limit < lgl->opts->rdpmineff.val) limit = lgl->opts->rdpmineff.val;
22655   if (lgl->opts->rdpmaxeff.val >= 0 && limit > lgl->opts->rdpmaxeff.val)
22656     limit = lgl->opts->rdpmaxeff.val;
22657   limit >>= (pen = lgl->limits->rdp.pen + lglszpen (lgl));
22658   irrlim = 3*lgl->stats->irr.clauses.cur;
22659   irrlim >>= lgl->limits->simp.pen;
22660   if (lgl->opts->irrlim.val && limit < irrlim) {
22661     limit = irrlim;
22662     lglprt (lgl, 1,
22663       "[rdp-%d] limit %lld based on %d irredundant clauses",
22664       lgl->stats->rdp.count, (LGLL) limit, lgl->stats->irr.clauses.cur);
22665   } else
22666     lglprt (lgl, 1, "[rdp-%d] limit %lld with penalty %d = %d + %d",
22667       lgl->stats->rdp.count, (LGLL) limit,
22668       pen, lgl->limits->rdp.pen, lglszpen (lgl));
22669   lgl->limits->rdp.steps = lgl->stats->rdp.steps + limit;
22670 }
22671
22672 static int lglrdp (LGL * lgl) {
22673   int oldunits, newunits, deltaunits, success;
22674   int oldtrn, newtrn, deltatrn;
22675   int oldbin, newbin, deltabin;
22676   if (lgl->nvars <= 2) return 1;
22677   if (lgl->mt) return 0;
22678   lglstart (lgl, &lgl->times->rdp);
22679   lgl->stats->rdp.count++;
22680   if (lgl->level) lglbacktrack (lgl, 0);
22681   assert (!lgl->simp);
22682   lgl->simp = 1;
22683   lglsetrdplim (lgl);
22684   oldunits = lgl->stats->rdp.units;
22685   oldbin = lgl->stats->rdp.bin;
22686   oldtrn = lgl->stats->rdp.trn;
22687   lglrdpinit (lgl);
22688   lglrandidxtrav (lgl, lglrdplit);
22689   lglrdpreport (lgl);
22690   lglrdpreset (lgl);
22691   newunits = lgl->stats->rdp.units; deltaunits = (newunits - oldunits);
22692   newbin = lgl->stats->rdp.bin; deltabin = (newbin - oldbin);
22693   newtrn = lgl->stats->rdp.trn; deltatrn = (newtrn - oldtrn);
22694   lglprt (lgl, 1,
22695     "[rdp-%d] found %d units, %d binary and %d ternary clauses",
22696     lgl->stats->rdp.count, deltaunits, deltabin, deltatrn);
22697   success = deltaunits + deltabin + deltatrn;
22698   LGLUPDPEN (rdp, success);
22699   assert (lgl->simp);
22700   lgl->simp = 0;
22701   lglstop (lgl);
22702   return !lgl->mt;
22703 }
22704
22705 /*------------------------------------------------------------------------*/
22706
22707 static int lglbcaoccmin (LGL * lgl, int lit) {
22708   int * p, * w, * eow;
22709   int res, blit, red, tag;
22710   HTS * hts;
22711   hts = lglhts (lgl, lit);
22712   w = lglhts2wchs (lgl, hts);
22713   eow = w + hts->count;
22714   res = 0;
22715   for (p = w; res <= 3 && p < eow; p++) {
22716     blit = *p;
22717     tag = blit & MASKCS;
22718     red = blit & REDCS;
22719     if (tag == TRNCS || tag == LRGCS) p++;
22720     if (tag == LRGCS) continue;
22721     if (!red) res++;
22722   }
22723   return res;
22724 }
22725
22726 static int lglbcaskiplit (LGL * lgl, int lit) {
22727   int pocc, nocc;
22728   if (lgl->opts->bca.val >= 2) return 0;
22729   pocc = lglbcaoccmin (lgl, lit);
22730   if (pocc <= 1) return 1;
22731   nocc = lglbcaoccmin (lgl, -lit);
22732   if (nocc <= 1) return 1;
22733   return pocc == 2 && nocc == 2;
22734 }
22735
22736 static void lglbcalitaux (LGL * lgl, int lit) {
22737   int first, blit, tag, red, lidx, other, tmp, found, other2, found2, * r;
22738   const int * w, * p, * eow, * c, * q;
22739   Stk * covered = &lgl->bca->covered;
22740   int round;
22741   HTS * hts;
22742   assert (lglisfree (lgl, lit));
22743   assert (lgl->opts->bca.val);
22744   assert (!(lglavar (lgl, lit)->inred & (1 << (lit < 0))));
22745   hts = lglhts (lgl, lit);
22746   if (!hts->count) return;
22747   if (lglbcaskiplit (lgl, lit)) { lgl->stats->bca.skipped++; return; }
22748   assert (lglmtstk (covered));
22749   first = 1;
22750   w = lglhts2wchs (lgl, hts);
22751   eow = w + hts->count;
22752   for (round = 0; round < 2; round++) {
22753     for (p = w; (first || !lglmtstk (covered)) && p < eow; p++) {
22754       blit = *p;
22755       tag = blit & MASKCS;
22756       red = blit & REDCS;
22757       if (tag == TRNCS || tag == LRGCS) p++;
22758       assert (!red || tag != LRGCS);
22759       if (tag == LRGCS) continue;
22760       if (round != (tag == OCCS)) continue;
22761       INCSTEPS (bca.steps);
22762       if (tag == BINCS) {
22763         assert (!round);
22764         other = blit >> RMSHFT;
22765         if (lglval (lgl, other) > 0) continue;
22766         assert (!lglval (lgl, other));
22767         found = first;
22768         while (!lglmtstk (covered))
22769           if (other == lglpopstk (covered)) found = 1;
22770         if (found) lglpushstk (lgl, covered, other);
22771       } else if (tag == TRNCS) {
22772         assert (!round);
22773         other = blit >> RMSHFT;
22774         if (lglval (lgl, other) > 0) continue;
22775         other2 = *p;
22776         if (lglval (lgl, other2) > 0) continue;
22777         found = found2 = first;
22778         while (!lglmtstk (covered))
22779           if (other == (tmp = lglpopstk (covered))) found = 1;
22780           else if (tmp == other2) found2 = 1;
22781         if (found && !lglval (lgl, other)) lglpushstk (lgl, covered, other);
22782         if (found2 && !lglval (lgl, other2)) lglpushstk (lgl, covered, other2);
22783       } else {
22784         assert (!red);
22785         assert (round);
22786         assert (tag == OCCS);
22787         lidx = blit >> RMSHFT;
22788         c = lglidx2lits (lgl, red, lidx);
22789         INCSTEPS (bca.steps);
22790         for (q = c; (other = *q); q++)
22791           if (other != lit && lglval (lgl, other) > 0) break;
22792         if (other) continue;
22793         if (first) {
22794           for (q = c; (other = *q); q++)
22795             if (other != lit && !lglval (lgl, other))
22796               lglpushstk (lgl, covered, other);
22797         } else {
22798           for (q = covered->start; q < covered->top; q++)
22799             assert (!lglsignedmarked (lgl, *q)), lglsignedmark (lgl, *q);
22800           for (q = c; (other = *q); q++)
22801             if (other != lit && lglsignedmarked (lgl, other))
22802               assert (!lglval (lgl, other)), lglsignedunmark (lgl, other);
22803           r = covered->start;
22804           for (q = r; q < covered->top; q++)
22805             if (lglsignedmarked (lgl, (other = *q)))
22806               lglsignedunmark (lgl, other);
22807             else *r++ = other;
22808           covered->top = r;
22809         }
22810       }
22811       first = 0;
22812     }
22813   }
22814 }
22815
22816 static int lglbcalit (LGL * lgl, int lit) {
22817   unsigned bit;
22818   AVar * av;
22819   int other;
22820   if (lgl->limits->bca.steps < lgl->stats->bca.steps) return 0;
22821   if (lglterminate (lgl)) return 0;
22822   if (lglifrozen (lgl, lit)) return 1;
22823   if (!lglisfree (lgl, lit)) return 1;
22824   av = lglavar (lgl, lit);
22825   bit = (1 << (lit < 0));
22826   if (av->inred & bit) return 1;
22827   lglbcalitaux (lgl, lit);
22828   while (!lglmtstk (&lgl->bca->covered)) {
22829     INCSTEPS (bca.steps);
22830     other = lglpopstk (&lgl->bca->covered);
22831     if (lglhasbin (lgl, -lit, -other)) continue;
22832     LOG (2, "adding binary blocked clause %d %d", -lit, -other);
22833     assert (lglmtstk (&lgl->clause));
22834     lglpushstk (lgl, &lgl->clause, -lit);
22835     lglpushstk (lgl, &lgl->clause, -other);
22836     lglpushstk (lgl, &lgl->clause, 0);
22837     lgladdcls (lgl, REDCS, 0, 1);
22838     lglclnstk (&lgl->clause);
22839     lgl->stats->bca.added++;
22840   }
22841   return 1;
22842 }
22843
22844 static void lglupdbcadel (LGL * lgl, int success) {
22845   if (success && lgl->limits->bca.del.cur)
22846     lgl->limits->bca.del.cur /= 2;
22847   if (!success && lgl->limits->bca.del.cur < lgl->opts->delmax.val)
22848     lgl->limits->bca.del.cur++;
22849   lgl->limits->bca.del.rem = lgl->limits->bca.del.cur;
22850 }
22851
22852 static void lglbca (LGL * lgl) {
22853   int oldadded = lgl->stats->bca.added, added;
22854   int idx, glue, other, inred, usable;
22855   const int * c, * p;
22856   int64_t oldsteps;
22857   unsigned bit;
22858   AVar * av;
22859
22860   lglstart (lgl, &lgl->times->bca);
22861
22862   NEW (lgl->bca, 1);
22863
22864   lgl->stats->bca.count++;
22865   oldsteps = lgl->stats->bca.steps;
22866   lgl->limits->bca.steps = oldsteps + lgl->opts->bcamaxeff.val;
22867   lglprt (lgl, 1, "[bca-%d] limit of %d steps", 
22868           lgl->stats->bca.count, lgl->opts->bcamaxeff.val);
22869
22870   assert (!lgl->bcaing);
22871   lgl->bcaing = 1;
22872
22873   if (lgl->level > 0) lglbacktrack (lgl, 0);
22874   lglgc (lgl);
22875   assert (lgl->frozen);
22876
22877   for (idx = 2; idx < lgl->nvars; idx++) lglavar (lgl, idx)->inred = 0;
22878   inred = 0;
22879   for (glue = 0; glue <= MAXGLUE; glue++) {
22880     Stk * s = lgl->red + glue;
22881     for (c = s->start; c < s->top; c = p + 1) {
22882       p = c;
22883       if (*p >= NOTALIT) continue;
22884       INCSTEPS (bca.steps);
22885       while ((other = *p)) {
22886         p++;
22887         bit = (1 << (other < 0));
22888         av = lglavar (lgl, other);
22889         if (av->inred & bit) continue;
22890         av->inred |= bit;
22891         inred++;
22892       }
22893     }
22894   }
22895   lglprt (lgl, 2, 
22896     "[bca-%d] %d out of %d literals in large redundant clauses %.0f%%",
22897     lgl->stats->bca.count,
22898     inred, 2*(lgl->nvars-1), lglpcnt (inred, 2*(lgl->nvars-1)));
22899
22900   usable = 0;
22901   for (idx = 2; idx < lgl->nvars; idx++) {
22902     if (lglifrozen (lgl, idx)) continue;
22903     if (!lglisfree (lgl, idx)) continue;
22904     av = lglavar (lgl, idx);
22905     for (bit = 1; bit <= 2; bit++) if (!(av->inred & bit)) usable++;
22906   }
22907   lglprt (lgl, 1, 
22908     "[bca-%d] %d out of %d literals actually usable %.0f%%",
22909     lgl->stats->bca.count,
22910     usable, 2*(lgl->nvars-1), lglpcnt (usable, 2*(lgl->nvars-1)));
22911
22912   if (usable < lgl->opts->bcaminuse.val) {
22913     lglprt (lgl, 1, "[bca-%d] not enough literals usable",
22914             lgl->stats->bca.count);
22915     goto DONE;
22916   }
22917
22918   lgldense (lgl, 1);
22919   lglrandlitrav (lgl, lglbcalit);
22920   lglsparse (lgl);
22921   lglgc (lgl);
22922
22923 DONE:
22924   added = lgl->stats->bca.added - oldadded;
22925   lglprt (lgl, 1, "[bca-%d] added %d blocked clauses in %lld steps",
22926           lgl->stats->bca.count, added, 
22927           (LGLL) lgl->stats->bca.steps - oldsteps);
22928   assert (lgl->bcaing);
22929   lgl->bcaing = 0;
22930   lglupdbcadel (lgl, added);
22931   lglrelstk (lgl, &lgl->bca->covered);
22932   DEL (lgl->bca, 1);
22933   lglstop (lgl);
22934 }
22935
22936 /*------------------------------------------------------------------------*/
22937
22938 #define BVAL 0
22939
22940 static int lglbvamult (LGL * lgl, int mult) {
22941   int other, blit, tag, red, res = 0;
22942   const int * p, * w, * eow;
22943   HTS * hts;
22944   hts = lglhts (lgl, mult);
22945   w = lglhts2wchs (lgl, hts);
22946   eow = w + hts->count;
22947   for (p = w; p < eow; p++) {
22948     blit = *p;
22949     tag = blit & MASKCS;
22950     if (tag == TRNCS || tag == LRGCS) p++;
22951     if (tag != BINCS) continue;
22952     red = blit & REDCS;
22953     if (red) continue;
22954     other = blit >> RMSHFT;
22955     if (lglsignedmarked (lgl, other)) res++;
22956   }
22957   return res;
22958 }
22959
22960 static void lglbvadef (LGL * lgl, int lit, int mult, Stk * factors) {
22961   // TODO what here?
22962 }
22963
22964 static void lglbvalit (LGL * lgl, int lit, Stk * factors) {
22965   int other, blit, tag, red, count, mult, factor;
22966   const int * p, * w, * eow;
22967   HTS * hts;
22968   if (!lglisfree (lgl, lit)) return;
22969   hts = lglhts (lgl, lit);
22970   if (hts->count < 3) return;
22971   LOG (BVAL, "trying to do BVA for literal %d", lit);
22972   lglclnstk (factors);
22973   w = lglhts2wchs (lgl, hts);
22974   eow = w + hts->count;
22975   for (p = w; p < eow; p++) {
22976     blit = *p;
22977     tag = blit & MASKCS;
22978     if (tag == TRNCS || tag == LRGCS) p++;
22979     if (tag != BINCS) continue;
22980     red = blit & REDCS;
22981     if (red) continue;
22982     other = blit >> RMSHFT;
22983     if (!lglisfree (lgl, other)) continue;
22984     if (lglsignedmarked (lgl, other)) continue;
22985     lglsignedmark (lgl, other);
22986     lglpushstk (lgl, factors, other);
22987   }
22988   count = lglcntstk (factors);
22989   LOG (BVAL, "found %d candidates to do BVA for literal %d", count, lit);
22990   while (lglcntstk (factors) >= 3) {
22991     factor = lgltopstk (factors);
22992     LOG (BVAL, "trying factor %d for candidate BVA literal %d", factor, lit);
22993     hts = lglhts (lgl, factor);
22994     w = lglhts2wchs (lgl, hts);
22995     eow = w + hts->count;
22996     for (p = w; p < eow; p++) {
22997       blit = *p;
22998       tag = blit & MASKCS;
22999       if (tag == TRNCS || tag == LRGCS) p++;
23000       if (tag != BINCS) continue;
23001       red = blit & REDCS;
23002       if (red) continue;
23003       mult = blit >> RMSHFT;
23004       if (mult == lit) continue;
23005       if (!lglisfree (lgl, mult)) continue;
23006       if ((count = lglbvamult (lgl, mult)) < 3) continue;
23007       count = lglbvamult (lgl, mult);
23008       LOG (BVAL,
23009         "multiplier %d with %d common factors for BVA literal %d",
23010         mult, count, lit);
23011       if (count < 3) continue;
23012       lglbvadef (lgl, lit, mult, factors);
23013       goto DONE;
23014     }
23015     (void) lglpopstk (factors);
23016     lglsignedunmark (lgl, factor);
23017   }
23018 DONE:
23019   while (!lglmtstk (factors)) {
23020     other = lglpopstk (factors); 
23021     assert (lglsignedmarked (lgl, other));
23022     lglsignedunmark (lgl, other);
23023   }
23024 }
23025
23026 static int lglcmpbvacands (int * binoccs, int a, int b) {
23027   return binoccs[a] - binoccs[b];
23028 }
23029
23030 #define LGLCMPBVACANDS(A,B) lglcmpbvacands (binoccs, *(A), *(B))
23031
23032 static void lglbva (LGL * lgl) {
23033   int * binoccs, nvars, idx, sgn, lit, blit, red, tag, other, count;
23034   int oldirr, removed, added;
23035   const int * p, * w, * eow;
23036   Stk cands, factors;
23037   HTS * hts;
23038   nvars = lgl->nvars;
23039   if (nvars <= 2) return;
23040   lglstart (lgl, &lgl->times->bva);
23041   lgl->stats->bva.count++;
23042   oldirr = lgl->stats->irr.clauses.cur;
23043   lglprt (lgl, 1,
23044     "[bva-%d] starting with %d variables and %d clauses",
23045     lgl->stats->bva.count, nvars - 2, oldirr);
23046   if (lgl->level > 0) lglbacktrack (lgl, 0);
23047   NEW (binoccs, 2*nvars);
23048   binoccs += nvars;
23049   CLR (cands);
23050   for (idx = 2; idx < nvars; idx++) {
23051     if (!lglisfree (lgl, idx)) continue;
23052     for (sgn = -1; sgn <= 1; sgn += 2) {
23053       lit = sgn * idx;
23054       hts = lglhts (lgl, lit);
23055       if (hts->count < 3) continue;
23056       count = 0;
23057       w = lglhts2wchs (lgl, hts);
23058       eow = w + hts->count;
23059       for (p = w; p < eow; p++) {
23060         blit = *p;
23061         tag = blit & MASKCS;
23062         if (tag == TRNCS || tag == LRGCS) p++;
23063         if (tag != BINCS) continue;
23064         red = blit & REDCS;
23065         if (red) continue;
23066         other = blit >> RMSHFT;
23067         if (!lglisfree (lgl, other)) continue;
23068         count++;
23069       }
23070       if (count < 3) continue;
23071       binoccs[lit] = count;
23072       lglpushstk (lgl, &cands, lit);
23073     }
23074   }
23075   if (lglmtstk (&cands)) {
23076     lglprt (lgl, 1,
23077       "[bva-%d] no candidates with at least three binary occurrences",
23078       lgl->stats->bva.count);
23079     goto DONE;
23080   }
23081   lglprt (lgl, 1,
23082     "[bva-%d] %d candidates with at least three binary occurrences",
23083     lgl->stats->bva.count, lglcntstk (&cands));
23084   SORT (int, cands.start, lglcntstk (&cands), LGLCMPBVACANDS);
23085   CLR (factors);
23086   while (!lglmtstk (&cands)) {
23087     lit = lglpopstk (&cands);
23088     lglbvalit (lgl, lit, &factors);
23089   }
23090   lglrelstk (lgl, &factors);
23091 DONE:
23092   binoccs -= nvars;
23093   DEL (binoccs, 2*nvars);
23094   lglrelstk (lgl, &cands);
23095   added = lgl->nvars - nvars;
23096   assert (added >= 0);
23097   removed = oldirr - lgl->stats->irr.clauses.cur;
23098   assert (removed >= 0);
23099   lgl->stats->bva.added += added;
23100   lgl->stats->bva.removed += removed;
23101   lglprt (lgl, 1,
23102     "[bva-%d] removed %d clauses and added %d variables",
23103     lgl->stats->bva.count, removed, added);
23104   lglstop (lgl);
23105 }
23106
23107 /*------------------------------------------------------------------------*/
23108
23109 static int lgltreducing (LGL * lgl) {
23110   if (lgldelaying (lgl, "transred", &lgl->limits->trd.del.rem)) return 0;
23111   if (lglwaiting (lgl, "transred", lgl->opts->transredwait.val)) return 0;
23112   return lgl->opts->transred.val;
23113 }
23114
23115 static int lglunhiding (LGL * lgl) { 
23116   if (lgldelaying (lgl, "unhide", &lgl->limits->unhd.del.rem)) return 0;
23117   if (lglwaiting (lgl, "unhide", lgl->opts->unhidewait.val)) return 0;
23118   return lgl->opts->unhide.val;
23119 }
23120
23121 static int lgldecomposing (LGL * lgl) { return lgl->opts->decompose.val; }
23122
23123 static int lglcgrclosing (LGL * lgl) {
23124   if (lgldelaying (lgl, "cgrclsr", &lgl->limits->cgr.del.rem)) return 0;
23125   if (lglwaiting (lgl, "cgrclsr", lgl->opts->cgrclsrwait.val)) return 0;
23126   return lgl->opts->cgrclsr.val && lglsmallirr (lgl);
23127 }
23128
23129 static int lglifting (LGL * lgl) {
23130   if (lgldelaying (lgl, "lift", &lgl->limits->lft.del.rem)) return 0;
23131   if (lglwaiting (lgl, "lift", lgl->opts->liftwait.val)) return 0;
23132   return lgl->opts->lift.val;
23133 }
23134
23135 static int lglblocking (LGL * lgl) {
23136   if (!lgl->opts->block.val) return 0;
23137   if (lgl->allfrozen) return 0;
23138   if (lgldelaying (lgl, "block", &lgl->limits->blk.del.rem)) return 0;
23139   if (lgl->opts->blockwait.val && lgl->wait &&
23140       (!lgl->opts->elim.val || !lgl->elmrtc)) {
23141     lglprt (lgl, 2, 
23142       "[block-waiting] for bounded variable elimination to be completed");
23143     return 0;
23144   }
23145   if (!lglsmallirr (lgl)) return 0;
23146   if (lgl->nvars <= 2) return 0;
23147   if (lgl->mt) return 0;
23148   if (lgl->blkrem) return 1;
23149   return lgl->stats->irrprgss > lgl->limits->blk.irrprgss;
23150 }
23151
23152 static int lgleliminating (LGL * lgl) {
23153   if (!lgl->opts->elim.val) return 0;
23154   if (lgl->allfrozen) return 0;
23155   if (lgldelaying (lgl, "elim", &lgl->limits->elm.del.rem)) return 0;
23156   if (!lglsmallirr (lgl)) return 0;
23157   if (lgl->nvars <= 2) return 0;
23158   if (lgl->mt) return 0;
23159   if (lgl->elmrem) return 1;
23160   return lgl->stats->irrprgss > lgl->limits->elm.irrprgss;
23161 }
23162
23163 static int lglrdping (LGL * lgl) {
23164   if (lgldelaying (lgl, "rdp", &lgl->limits->rdp.del.rem)) return 0;
23165   if (lglwaiting (lgl, "rdp", lgl->opts->rdpwait.val)) return 0;
23166   return lgl->opts->rdp.val;
23167 }
23168
23169 static int lglbcaing (LGL * lgl) {
23170   if (!lgl->opts->bca.val) return 0;
23171   if (lgl->allfrozen) return 0;
23172   if (lgldelaying (lgl, "bca", &lgl->limits->bca.del.rem)) return 0;
23173   if (lglwaiting (lgl, "bca", lgl->opts->bcawait.val)) return 0;
23174   if (!lglsmallirr (lgl)) return 0;
23175   return 1;
23176 }
23177
23178 static int lglbvaing (LGL * lgl) {
23179   if (!lgl->opts->bva.val) return 0;
23180   return 1;
23181 }
23182
23183 static int lglreducing (LGL * lgl) {
23184   int reducable;
23185   if (!lgl->opts->reduce.val) return 0;
23186   reducable = lgl->stats->red.lrg;
23187   assert (reducable >= lgl->lrgluereasons);
23188   reducable -= lgl->lrgluereasons;
23189   assert (reducable >= lgl->stats->lir[0].clauses);
23190   reducable -= lgl->stats->lir[0].clauses;
23191   return reducable >= lgl->limits->reduce.inner;
23192 }
23193
23194 static int lgldefragmenting (LGL * lgl) {
23195   int relfree;
23196   if (lgl->stats->pshwchs < lgl->limits->dfg) return 0;
23197   if (!lgl->nvars) return 0;
23198   relfree = (100 * lgl->wchs->free + 99) / lgl->nvars;
23199   return relfree >= lgl->opts->defragfree.val;
23200 }
23201
23202 static int lglrestarting (LGL * lgl) {
23203   int assumptions;
23204   if (!lgl->opts->restart.val) return 0;
23205   if (!lgl->level) return 0;
23206   if ((assumptions = lglcntstk (&lgl->assume))) {
23207     if (lgl->assumed < assumptions) return 0;
23208     assert (lgl->alevel <= lgl->level);
23209     if (lgl->alevel == lgl->level) return 0;
23210   }
23211   return lgl->stats->confs >= lgl->limits->restart.confs;
23212 }
23213
23214 static int lglternresolving (LGL * lgl) { 
23215   if (lgldelaying (lgl, "ternres", &lgl->limits->trnr.del.rem)) return 0;
23216   if (lglwaiting (lgl, "ternres", lgl->opts->ternreswait.val)) return 0;
23217   return lgl->opts->ternres.val;
23218 }
23219
23220 static int lglgaussing (LGL * lgl) { 
23221   if (lgldelaying (lgl, "gauss", &lgl->limits->gauss.del.rem)) return 0;
23222   if (lglwaiting (lgl, "gauss", lgl->opts->gausswait.val)) return 0;
23223   if (!lglsmallirr (lgl)) return 0;
23224   return lgl->opts->gauss.val;
23225 }
23226
23227 static int lglcliffing (LGL * lgl) {
23228   if (lgldelaying (lgl, "cliff", &lgl->limits->cliff.del.rem)) return 0;
23229   if (lglwaiting (lgl, "cliff", lgl->opts->cliffwait.val)) return 0;
23230   return lgl->opts->cliff.val;
23231 }
23232
23233 static int lglprobing (LGL * lgl) {
23234   if (!lgl->opts->probe.val) return 0;
23235   if (lgl->opts->prbasic.val) return 1;
23236   if (!lglsmallirr (lgl)) return 0;
23237   if (lgl->opts->prbsimple.val) return 1;
23238   if (lgl->opts->treelook.val) return 1;
23239   return 0;
23240 }
23241
23242 static int lglcarding (LGL * lgl) {
23243   if (!lgl->opts->card.val) return 0;
23244   if (lgldelaying (lgl, "card", &lgl->limits->card.del.rem)) return 0;
23245   if (lglwaiting (lgl, "card", lgl->opts->cardwait.val)) return 0;
23246   return 1;
23247 }
23248
23249 static int lglcceing (LGL * lgl) {
23250   if (!lgl->opts->cce.val) return 0;
23251   if (lgl->allfrozen) return 0;
23252   if (lgldelaying (lgl, "cce", &lgl->limits->cce.del.rem)) return 0;
23253   if (lglwaiting (lgl, "cce", lgl->opts->ccewait.val)) return 0;
23254   if (!lglsmallirr (lgl)) return 0;
23255   if (lgl->opts->cceonlyifstuck.val &&
23256       ((lgl->opts->elim.val && !lgl->elmstuck) || 
23257         (lgl->opts->block.val && !lgl->blkstuck))) {
23258     lglprt (lgl, 2,
23259       "[cce-%d] skipping since elmstuck=%d blkstuck=%d",
23260       lgl->stats->cce.count, lgl->elmstuck, lgl->blkstuck);
23261     return 0;
23262   }
23263   return 1;
23264 }
23265
23266 /*------------------------------------------------------------------------*/
23267
23268 static void lglupdlocslim (LGL * lgl, int updconflimtoo) {
23269   int rem = lglrem (lgl), varslimit, vardelta;
23270   vardelta = (rem * lgl->opts->locsvared.val + 999)/1000;
23271   if (vardelta > rem) vardelta = rem;
23272   varslimit = rem - vardelta;
23273   lgl->limits->locs.vars = varslimit;
23274   lglprt (lgl, 1 + !lgl->opts->locs.val,
23275     "[locs-lim] next local search variable limit %d = %d - %d",
23276     varslimit, rem, vardelta);
23277   if (!updconflimtoo) return;
23278   lgl->limits->locs.inc += lgl->opts->locscint.val;
23279   assert (lgl->limits->locs.confs <= LLMAX - lgl->limits->locs.inc);
23280   lgl->limits->locs.confs = lgl->stats->confs + lgl->limits->locs.inc;
23281   lglprt (lgl, 1 + !lgl->opts->locs.val,
23282     "[locs-lim] next local search conflict limit increased by %d to %lld",
23283     lgl->limits->locs.inc, lgl->limits->locs.confs);
23284 }
23285
23286 static int lglocsing (LGL * lgl) {
23287 #ifndef NLGLYALSAT
23288   int rem;
23289   if (!lgl->opts->locs.val) return 0;
23290   if (lgl->limits->locs.confs > lgl->stats->confs) return 0;
23291   if (lgl->stats->irr.clauses.cur > lgl->opts->locsclim.val) {
23292     lglprt (lgl, 2, "[locs] skipped due to too many clauses");
23293     return 0;
23294   }
23295   rem = lglrem (lgl);
23296   if (rem < lgl->limits->locs.vars) {
23297     lglprt (lgl, 2,
23298       "[locs-limit] local search skipped (remaining %d < limit %d)",
23299       rem, lgl->limits->locs.vars);
23300     lglupdlocslim (lgl, 1);
23301     return 0;
23302   }
23303   if (lglwaiting (lgl, "locs", lgl->opts->locswait.val)) return 0;
23304   if (lgl->opts->locs.val < 0) return 1;
23305   return (lgl->stats->locs.count < lgl->opts->locs.val);
23306 #else
23307   (void) lgl;
23308   return 0;
23309 #endif
23310 }
23311
23312 #ifndef NLGLYALSAT
23313
23314 static void lglocscopy (LGL * lgl, Yals * yals) {
23315   int idx, sign, lit, blit, tag, red, other, other2;
23316   int count, redcount, units, tmp;
23317   const int * p, * w, * eow, * c;
23318   HTS * hts;
23319   Stk * s;
23320   assert (!lgl->level);
23321   if (!lgl->mt && !lglbcp (lgl)) lgl->mt = 1;
23322   if (!lgl->mt) lglgc (lgl);
23323   if (lgl->mt) return;
23324   count = redcount = units = 0;
23325   for (idx = 2; idx < lgl->nvars; idx++)
23326     for (sign = -1; sign <= 1; sign += 2) {
23327       lit = sign * idx;
23328       assert (!lglval (lgl, lit));
23329       hts = lglhts (lgl, lit);
23330       w = lglhts2wchs (lgl, hts);
23331       eow = w + hts->count;
23332       for (p = w; p < eow; p++) {
23333         blit = *p;
23334         tag = blit & MASKCS;
23335         red = blit & REDCS;
23336         if (tag == TRNCS || tag == LRGCS) p++;
23337         if (red && tag == BINCS && lgl->opts->locsred.val < 2) continue;
23338         if (red && tag == TRNCS && lgl->opts->locsred.val < 3) continue;
23339         if (tag != BINCS && tag != TRNCS) continue;
23340         other = blit >> RMSHFT;
23341         if (abs (other) < idx) continue;
23342         assert (!lglval (lgl, other));
23343         if (tag == TRNCS) {
23344           other2 = *p;
23345           if (abs (other2) < idx) continue;
23346           assert (!lglval (lgl, other2));
23347         } else other2 = 0;
23348         yals_add (yals, lit);
23349         yals_add (yals, other);
23350         if (other2) yals_add (yals, other2);
23351         yals_add (yals, 0);
23352         if (red) redcount++;
23353         count++;
23354       }
23355     }
23356   for (idx = 2; idx < lgl->nvars; idx++) {
23357     tmp = lglifixed (lgl, idx);
23358     if (!tmp) continue;
23359     lit = (tmp < 0) ? -idx : idx;
23360     yals_add (yals, lit);
23361     yals_add (yals, 0);
23362     units++;
23363   }
23364   for (red = -1; red < MAXGLUE; red++) {
23365     s = red < 0 ? &lgl->irr : lgl->red + red;
23366     if (red >= 0 && lgl->opts->locsred.val < 4) break;
23367     for (c = s->start; c < s->top; c = p + 1) {
23368       p = c;
23369       if (*p >= NOTALIT) continue;
23370       while ((other = *p)) {
23371         assert (!lglval (lgl, other));
23372         yals_add (yals, other);
23373         p++;
23374       }
23375       yals_add (yals, 0);
23376       if (red >= 0) redcount++;
23377       count++;
23378     }
23379   }
23380
23381   lglprt (lgl, 1,
23382     "[locs-%d] copied %d irredundant clauses",
23383     lgl->stats->locs.count, count - redcount);
23384   if (redcount)
23385     lglprt (lgl, 1,
23386       "[locs-%d] copied %d redundant clauses",
23387       lgl->stats->locs.count, redcount);
23388   if (units)
23389     lglprt (lgl, 1,
23390       "[locs-%d] copied %d units",
23391       lgl->stats->locs.count, units);
23392
23393   for (count = 0; count < lglcntstk (&lgl->assume); count++) {
23394     lit = lglpeek (&lgl->assume, count);
23395     if (abs (lit) <= 0) continue;
23396     yals_add (yals, lit);
23397     yals_add (yals, 0);
23398   }
23399   if (count)
23400     lglprt (lgl, 1,
23401       "[locs-%d] copied %d assumptions as %d unit clauses",
23402       lgl->stats->locs.count, count, count);
23403   else
23404     lglprt (lgl, 2,
23405       "[locs-%d] no assumptions copied",
23406       lgl->stats->locs.count);
23407 }
23408
23409 static int64_t lglsetlocslim (LGL * lgl) {
23410   int pen, boost;
23411   int64_t limit;
23412   if (lgl->opts->locsrtc.val) {
23413     limit = LLMAX;
23414     lglprt (lgl, 1,
23415       "[locs-%d] no limit (run to completion)",
23416       lgl->stats->locs.count);
23417   } else {
23418     limit = (lgl->opts->locsreleff.val*lglvisearch (lgl))/100;
23419     if (limit < lgl->opts->locsmineff.val) 
23420       limit = lgl->opts->locsmineff.val;
23421     if (lgl->opts->locsmaxeff.val >= 0 &&
23422         limit > lgl->opts->locsmaxeff.val)
23423       limit = lgl->opts->locsmaxeff.val;
23424     if (lgl->stats->locs.count <= 1 &&
23425         lgl->opts->boost.val &&
23426         lgl->opts->locsboost.val > 1) {
23427       boost = lgl->opts->locsboost.val;
23428       lglprt (lgl, 1,
23429         "[locs-%d] intially boosting limit by factor of %d",
23430         lgl->stats->locs.count, boost);
23431     } else boost = 1;
23432     limit *= boost;
23433     pen = lglitszpen (lgl);
23434     limit >>= pen;
23435     lglprt (lgl, 1,
23436       "[locs-%d] limit %lld literal penalty %d",
23437       lgl->stats->locs.count, (LGLL) limit, pen);
23438   }
23439   return limit;
23440 }
23441
23442 #endif
23443
23444 static int lglocsaux (LGL * lgl, int hitlim) {
23445   int lkhd = 0;
23446 #ifndef NLGLYALSAT
23447   int res, min, pos, neg, idx, lit, old_val, len;
23448   const int set = lgl->opts->locset.val;
23449   int save = lgl->opts->locsexport.val;
23450   unsigned long long seed;
23451   char * prefix;
23452   int64_t limit;
23453   AVar * av;
23454   Val val;
23455   Yals * yals;
23456   lglstart (lgl, &lgl->times->locs);
23457   if (lgl->level) lglbacktrack (lgl, 0);
23458   if (!lgl->stats->locs.count++) {
23459     const char * yals_version ();
23460     lglprt (lgl, 1,
23461       "[locs-%d] %s",
23462       lgl->stats->locs.count, yals_version ());
23463   }
23464   yals = yals_new_with_mem_mgr ( lgl,
23465            (YalsMalloc) lglnew, (YalsRealloc) lglrsz, (YalsFree) lgldel);
23466   yals_setout (yals, lgl->out);
23467   len = strlen (lgl->prefix) + 80;
23468   NEW (prefix, len);
23469   if (lgl->tid >= 0)
23470     sprintf (prefix, "%s%d [locs-%d] ",
23471       lgl->prefix, lgl->tid, lgl->stats->locs.count);
23472   else
23473     sprintf (prefix, "%s[locs-%d] ", lgl->prefix, lgl->stats->locs.count);
23474   yals_setprefix (yals, prefix);
23475   DEL (prefix, len);
23476   old_val = yals_getopt (yals, "verbose");
23477   if (old_val < lgl->opts->verbose.val)
23478     yals_setopt (yals, "verbose", lgl->opts->verbose.val);
23479   seed = lglrand (lgl);
23480   if (lgl->tid >= 0) seed *= lgl->tid + 1;
23481   seed += 1237 * (unsigned) lgl->stats->locs.count;
23482   yals_srand (yals, seed);
23483   if (hitlim > 0) yals_setopt (yals, "hitlim", hitlim);
23484   lglocscopy (lgl, yals);
23485   if (lgl->mt) { res = 20; goto DONE; }
23486   limit = lglsetlocslim (lgl);
23487   pos = neg = 0;
23488   for (idx = 2; idx < lgl->nvars; idx++) {
23489     av = lglavar (lgl, idx);
23490          if (set == 2 && av->phase > 0) lit = idx;
23491     else if (set == 2 && av->phase < 0) lit = -idx;
23492     else if (set == 1 && av->locsval > 0) lit = idx;
23493     else if (set == 1 && av->locsval < 0) lit = -idx;
23494     else continue;
23495     assert (lit);
23496     if (lit < 0) neg++; else pos++;
23497     yals_setphase (yals, lit);
23498   }
23499   lglprt (lgl, 1,
23500     "[locs-%d] importing %d positive %.0f%% and %d negative %.0f%% phases",
23501     lgl->stats->locs.count,
23502     pos, lglpcnt (pos, pos + neg),
23503     neg, lglpcnt (neg, pos + neg));
23504   if (limit < LLMAX/1000) limit *= 1000; else limit = LLMAX;
23505   yals_setmemslimit (yals, limit);
23506   if (lgl->cbs && lgl->cbs->term.fun)
23507     yals_seterm (yals, lgl->cbs->term.fun, lgl->cbs->term.state);
23508   if (lgl->cbs && lgl->cbs->getime)
23509     yals_setime (yals, lgl->cbs->getime);
23510   if (lgl->cbs && lgl->cbs->msglock.lock)
23511     yals_setmsglock (yals,
23512       lgl->cbs->msglock.lock,
23513       lgl->cbs->msglock.unlock,
23514       lgl->cbs->msglock.state);
23515   res = yals_sat (yals);
23516   min = yals_minimum (yals);
23517   lglprt (lgl, 1,
23518     "[locs-%d] local search returns %d with minimum %d",
23519     lgl->stats->locs.count, res, min);
23520   if (min < lgl->stats->locs.min) lgl->stats->locs.min = min;
23521   lgl->stats->locs.flips += yals_flips (yals);
23522   lgl->stats->locs.mems += yals_mems (yals);
23523   if (res == 10) save = 1;
23524   pos = neg = 0;
23525   for (idx = 2; idx < lgl->nvars; idx++) {
23526     val = yals_deref (yals, idx);
23527     assert (abs (val) == 1);
23528     av = lglavar (lgl, idx);
23529     if (val < 0) neg++, av->locsval = -1;
23530     else if (val > 0) pos++, av->locsval = 1;
23531     if (save) av->phase = val;
23532   }
23533   lglprt (lgl, 1,
23534     "[locs-%d] %s %d positive %.0f%% and %d negative %.0f%% phases",
23535     lgl->stats->locs.count,
23536     save ? "exported" : "found",
23537     pos, lglpcnt (pos, pos + neg),
23538     neg, lglpcnt (neg, pos + neg));
23539   if (lgl->opts->locsdec.val == 1) {
23540     lkhd = yals_lkhd (yals);
23541     if (abs (lkhd) == 1) lkhd = 0;
23542     if (lkhd && lglisfree (lgl, lkhd)) {
23543       lglprt (lgl, 1,
23544         "[locs-%d] using local search look ahead %d",
23545         lgl->stats->locs.count, lkhd);
23546       lglbumplit (lgl, lkhd);
23547     }
23548   } else if (lgl->opts->locsdec.val == 2) {
23549     const int * p = yals_minlits (yals);
23550     int count = 0;
23551     while ((lit = *p++))
23552       if (abs (lit) > 1 && lglisfree (lgl, lit))
23553         lglbumplit (lgl, lit), count++;
23554     lglprt (lgl, 1,
23555       "[locs-%d] bumped all %d variables in unsatisfied clauses",
23556       lgl->stats->locs.count, count);
23557   }
23558 DONE:
23559   if (lgl->opts->verbose.val >= 1) yals_stats (yals);
23560   yals_del (yals);
23561   lglstop (lgl);
23562 #endif
23563   return lkhd;
23564 }
23565
23566 static void lglocs (LGL * lgl) {
23567   (void) lglocsaux (lgl, 0);
23568   lglupdlocslim (lgl, 1);
23569 }
23570
23571 static int lglocslook (LGL * lgl) {
23572   int res = lglocsaux (lgl, 100000), elit;
23573   Ext * ext;
23574   if (res) {
23575     elit = lglexport (lgl, res);
23576     ext = lglelit2ext (lgl, elit);
23577     if (!ext->eliminated && !ext->blocking) {
23578       lglprt (lgl, 1, "[locslook] best local search look-ahead %d", res);
23579       if (ext->melted) {
23580         ext->melted = 0;
23581         LOG (2, "look-ahead winner external %d not melted anymore", elit);
23582       } else
23583         LOG (2, "look-ahead winner external %d was not melted anyhow", elit);
23584     } else {
23585       lglprt (lgl, 1, "[locslook] no valid local search look-ahead");
23586       lglprt (lgl, 1, "[locslook] falling back to JWH");
23587       res = lgljwhlook (lgl);
23588     }
23589   } else LOG (1, "no proper local search look-ahead literal found");
23590
23591   return res;
23592 }
23593
23594 /*------------------------------------------------------------------------*/
23595 #if 0
23596
23597 static void lglanaconnected (LGL * lgl) {
23598   if (!lglsmallirr (lgl)) return;
23599   if (lgl->level) lglbacktrack (lgl, 0);
23600   lgldense (lgl, 1);
23601   lglsparse (lgl);
23602   lglgc (lgl);
23603 }
23604
23605 static void lglanabiconnected (LGL * lgl) {
23606   if (!lglsmallirr (lgl)) return;
23607   if (lgl->level) lglbacktrack (lgl, 0);
23608   lgldense (lgl, 1);
23609   lglsparse (lgl);
23610   lglgc (lgl);
23611 }
23612
23613 #endif
23614 /*------------------------------------------------------------------------*/
23615
23616 static int lglforklit (int ilit) {
23617   int idx = abs (ilit), res;
23618   assert (idx > 1);
23619   res = idx - 1;
23620   if (ilit < 0) res = -res;
23621   return res;
23622 }
23623
23624 static int lglmegaing (LGL * lgl) {
23625   if (!lgl->opts->mega.val) return 0;
23626   if (lgl->nvars <= 2) return 0;
23627   if (!lglmtstk (&lgl->eassume)) return 0;
23628   if (lglwaiting (lgl, "mega", lgl->opts->megawait.val)) return 0;
23629   if (lgl->stats->simp.count % lgl->opts->megaint.val) return 0;
23630   return 1;
23631 }
23632
23633 static int lglmega (LGL * lgl) {
23634   int remain, idx, start, lit, len, res, nlits, * vals, lifted, eqs;
23635   char * prefix;
23636   unsigned mod;
23637   LGL * forked;
23638   AVar * av;
23639   assert (lgl->opts->mega.val);
23640   assert (lgl->nvars > 2);
23641   assert (lglmtstk (&lgl->eassume));
23642   lglstart (lgl, &lgl->times->mega);
23643   lgl->stats->mega.count++;
23644   assert (!lgl->simp), assert (!lgl->probing);
23645   lgl->simp = lgl->probing = 1;
23646   if (lgl->level > 0) lglbacktrack (lgl, 0);
23647   remain = 0;
23648   nlits = 2*(lgl->nvars - 2);
23649   for (idx = 2; idx < lgl->nvars; idx++) {
23650     if (!lglisfree (lgl, idx)) continue;
23651     av = lglavar (lgl, idx);
23652     if (!(av->mega & 1)) remain++;
23653     if (!(av->mega & 2)) remain++;
23654   }
23655   if (remain)
23656     lglprt (lgl, 1,
23657        "[mega-%d] found %d remaining literals %.0f%% to try in round %d",
23658        lgl->stats->mega.count,
23659        remain, lglpcnt (remain, nlits), lgl->stats->mega.rounds);
23660   else {
23661     lgl->stats->mega.rounds++;
23662     remain = 0;
23663     for (idx = 2; idx < lgl->nvars; idx++) {
23664       if (!lglisfree (lgl, idx)) continue;
23665       av = lglavar (lgl, idx);
23666       av->mega = 0;
23667       remain += 2;
23668     }
23669     lglprt (lgl, 1,
23670       "[mega-%d] scheduled %d literals %.0f%% to try in new round %d",
23671       lgl->stats->mega.count,
23672       remain, lglpcnt (remain, nlits), lgl->stats->mega.rounds);
23673   }
23674   if (!remain) goto DONE;
23675   mod = lgl->nvars - 2;
23676   idx = lglrand (lgl) % mod;
23677   idx += 2;
23678   start = idx;
23679   assert (2 <= idx), assert (idx < lgl->nvars);
23680   lit = 0;
23681   for (;;) {
23682     int posbins, negbins;
23683     av = lglavar (lgl, idx);
23684     if (av->mega == 3) goto CONTINUE;
23685     posbins = lglhasbins (lgl, idx);
23686     negbins = lglhasbins (lgl, -idx);
23687     if (posbins && negbins) goto CONTINUE;
23688     if (av->mega == 1) {
23689        if (negbins) goto CONTINUE;
23690        lit = -idx; break;
23691     }
23692     if (av->mega == 2) {
23693       if (posbins) goto CONTINUE;
23694       lit = idx; break;
23695     }
23696     assert (!av->mega);
23697     if (posbins) { lit = -idx; break; }
23698     if (negbins) { lit = idx; break; }
23699     lit = (lglrand (lgl) & 1) ? -idx : idx;
23700     break;
23701 CONTINUE:
23702     if (++idx == lgl->nvars) idx = 2;
23703     if (idx == start) {
23704       lglprt (lgl, 1,
23705         "[mega-%d] no roots in binary implication graph found",
23706         lgl->stats->mega.count);
23707       goto DONE;
23708     }
23709   }
23710   assert (lit);
23711   forked = lglfork (lgl);
23712   lglsetopt (forked, "verbose",
23713     lglmax (lgl->opts->verbose.val - 1, 0));
23714   lglsetopt (forked, "bca", 0);
23715   lglsetopt (forked, "boost", 0);
23716   lglsetopt (forked, "mega", 0);
23717   lglsetopt (forked, "trep", 0);
23718   lglsetopt (forked, "wait", 0);
23719   len = strlen (lgl->prefix) + 40;
23720   NEW (prefix, len);
23721   sprintf (prefix, "%s:mega_%d_0: ", lgl->prefix, lgl->stats->mega.count);
23722   lglsetprefix (forked, prefix);
23723   DEL (prefix, len);
23724   lgladd (forked, lglforklit (lit)); lgladd (forked, 0);
23725   res = lglsimp (forked, 1);
23726   if (res == 20) {
23727     lgl->stats->mega.failed++;
23728     lglprt (lgl, 1,
23729       "[mega-%d] found failed literal in first branch",
23730       lgl->stats->mega.count);
23731     lglunit (lgl, -lit);
23732     if (!lglbcp (lgl)) { lgl->mt = 1; }
23733   } else {
23734     lglprt (lgl, 1,
23735       "[mega-%d] first branch not failing",
23736       lgl->stats->mega.count);
23737
23738     NEW (vals, lgl->nvars);
23739     for (idx = 2; idx < lgl->nvars; idx++) {
23740       int val = lglfixed (forked, lglforklit (idx));
23741       if (!val) continue;
23742       vals[idx] = val;
23743       av = lglavar (lgl, idx);
23744       if (val > 0) av->mega |= 1;
23745       if (val < 0) av->mega |= 2;
23746     }
23747     lglrelease (forked);
23748     lgl->forked--;
23749     forked = lglfork (lgl);
23750     lglsetopt (forked, "verbose",
23751       lglmax (lgl->opts->verbose.val - 1, 0));
23752     lglsetopt (forked, "bca", 0);
23753     lglsetopt (forked, "boost", 0);
23754     lglsetopt (forked, "mega", 0);
23755     lglsetopt (forked, "trep", 0);
23756     lglsetopt (forked, "wait", 0);
23757     len = strlen (lgl->prefix) + 40;
23758     NEW (prefix, len);
23759     sprintf (prefix, "%s:mega-%d-1: ", lgl->prefix, lgl->stats->mega.count);
23760     lglsetprefix (forked, prefix);
23761     DEL (prefix, len);
23762     lgladd (forked, lglforklit (-lit)); lgladd (forked, 0);
23763     res = lglsimp (forked, 1);
23764     if (res == 20) {
23765       lgl->stats->mega.failed++;
23766       lglprt (lgl, 1,
23767         "[mega-%d] found failed literal in second branch",
23768         lgl->stats->mega.count);
23769       lglunit (lgl, lit);
23770       if (!lglbcp (lgl)) { lgl->mt = 1; }
23771     } else {
23772       eqs = lifted = 0;
23773       for (idx = 2; idx < lgl->nvars; idx++) {
23774         int val = lglfixed (forked, lglforklit (idx));
23775         if (!val) continue;
23776         if (abs (idx) == abs (lit)) continue;
23777         if (vals[idx] == val) {
23778           lglunit (lgl, (val < 0) ? -idx : idx);
23779           lgl->stats->mega.lifted++;
23780           lifted++;
23781         } else if (vals[idx] == -val) {
23782           eqs++;
23783 #if 0
23784           lgl->stats->mega.eqs++;
23785           if (val > 0) {
23786             lgladd (lgl, lit), lgladd (lgl, idx); lgladd (lgl, 0);
23787             lgladd (lgl, -lit), lgladd (lgl, -idx); lgladd (lgl, 0);
23788           } else {
23789             lgladd (lgl, -lit), lgladd (lgl, idx); lgladd (lgl, 0);
23790             lgladd (lgl, -lit), lgladd (lgl, -idx); lgladd (lgl, 0);
23791           }
23792 #endif
23793         }
23794       }
23795       if (lifted || eqs) {
23796         lglprt (lgl, 1,
23797           "[mega-%d] lifted %d literals and found %d equivalences",
23798           lgl->stats->mega.count, lifted, eqs);
23799         if (!lglbcp (lgl)) { lgl->mt = 1; }
23800       } else
23801         lglprt (lgl, 1,
23802           "[mega-%d] unsuccesfull",
23803           lgl->stats->mega.count);
23804     }
23805     DEL (vals, lgl->nvars);
23806   }
23807   lglrelease (forked);
23808   lgl->forked--;
23809 DONE:
23810   assert (lgl->simp), assert (lgl->probing);
23811   lgl->simp = lgl->probing = 0;
23812   lglstop (lgl);
23813   return !lgl->mt;
23814 }
23815
23816 /*------------------------------------------------------------------------*/
23817
23818 static int lglisimp (LGL * lgl) {
23819   if (!lgl->opts->simplify.val) return 1;
23820
23821   if (lglternresolving (lgl) && !lglternres (lgl)) return 0;
23822   if (lglterminate (lgl)) return 1;
23823   assert (!lgl->mt);
23824
23825   if (lglcarding (lgl) && !lglcard (lgl)) return 0;
23826   if (lglterminate (lgl)) return 1;
23827   assert (!lgl->mt);
23828
23829   if (lglgaussing (lgl) && !lglgauss (lgl)) return 0;
23830   if (lglterminate (lgl)) return 1;
23831   assert (!lgl->mt);
23832
23833   if (lgldecomposing (lgl) && !lgldecomp (lgl)) return 0;
23834   if (lglterminate (lgl)) return 1;
23835   assert (!lgl->mt);
23836
23837   if (lglprobing (lgl) && !lglprobe (lgl)) return 0;
23838   if (lglterminate (lgl)) return 1;
23839   assert (!lgl->mt);
23840
23841   if (lglcgrclosing (lgl) && !lglcgrclsr (lgl)) return 0;
23842   if (lglterminate (lgl)) return 1;
23843   assert (!lgl->mt);
23844
23845   if (lglifting (lgl) && !lglift (lgl)) return 0;
23846   if (lglterminate (lgl)) return 1;
23847   assert (!lgl->mt);
23848
23849   if (lglcliffing (lgl) && !lglcliff (lgl)) return 0;
23850   if (lglterminate (lgl)) return 1;
23851   assert (!lgl->mt);
23852
23853   if (lglunhiding (lgl) && !lglunhide (lgl)) return 0;
23854   if (lglterminate (lgl)) return 1;
23855   assert (!lgl->mt);
23856
23857   if (lgltreducing (lgl) && !lgltrd (lgl)) return 0;
23858   if (lglterminate (lgl)) return 1;
23859   assert (!lgl->mt);
23860
23861   if (lglblocking (lgl)) lglblock (lgl);
23862   if (lglterminate (lgl)) return 1;
23863   assert (!lgl->mt);
23864
23865   if (lglcceing (lgl) && !lglcce (lgl)) return 0;
23866   if (lglterminate (lgl)) return 1;
23867   assert (!lgl->mt);
23868
23869   if (lgleliminating (lgl) && !lglelim (lgl)) return 0;
23870   if (lglterminate (lgl)) return 1;
23871   assert (!lgl->mt);
23872
23873   if (lglrdping (lgl) && !lglrdp (lgl)) return 0;
23874   if (lglterminate (lgl)) return 1;
23875   assert (!lgl->mt);
23876
23877   if (!lgltopgc (lgl)) return 0;
23878   if (lglterminate (lgl)) return 1;
23879   assert (!lgl->mt);
23880
23881   if (lglmegaing (lgl) && !lglmega (lgl)) return 0;
23882   if (lglterminate (lgl)) return 1;
23883   assert (!lgl->mt);
23884
23885   if (lglbcaing (lgl)) lglbca (lgl);
23886   if (lglterminate (lgl)) return 1;
23887   assert (!lgl->mt);
23888
23889   if (lglbvaing (lgl)) lglbva (lgl);
23890   if (lglterminate (lgl)) return 1;
23891   assert (!lgl->mt);
23892
23893   if (lglrephasing (lgl)) lglrephase (lgl);
23894   if (!lgl->allphaseset) lglphase (lgl);
23895   if (lglterminate (lgl)) return 1;
23896   assert (!lgl->mt);
23897
23898   lgldefrag (lgl);
23899
23900 #if 0
23901   lglanaconnected (lgl);
23902   lglanabiconnected (lgl);
23903 #endif
23904
23905   return 1;
23906 }
23907
23908 static int lgltabring (LGL * lgl) {
23909   int res, rem, irr;
23910   if (!lgl->opts->tabr.val) return 0;
23911   res = 0;
23912   rem = lglrem (lgl);
23913   if (rem < lgl->limits->tabr.vars) {
23914     lgl->stats->tabr.count++, res = 1;
23915     lglprt (lgl, 1,
23916       "[tabula-rasa-%d] number variables %d drops below limit %d",
23917         lgl->stats->tabr.count, rem, lgl->limits->tabr.vars);
23918   }
23919   irr = lgl->stats->irr.clauses.cur;
23920   if (irr < lgl->limits->tabr.clauses) {
23921     if (!res) lgl->stats->tabr.count++, res = 1;
23922     lglprt (lgl, 1,
23923       "[tabula-rasa-%d] number clauses %d drops below limit %d",
23924         lgl->stats->tabr.count, irr, lgl->limits->tabr.clauses);
23925   }
23926   return res;
23927 }
23928
23929 static void lglupdtabr (LGL * lgl) {
23930   lgl->limits->tabr.vars =
23931     lglrem (lgl) / lgl->opts->tabrvfactor.val;
23932   lgl->limits->tabr.clauses =
23933     lgl->stats->irr.clauses.cur / lgl->opts->tabrcfactor.val;
23934   lglprt (lgl, 1,
23935     "[tabula-rasa-%d] new variable limit %d and clause limit %d",
23936       lgl->stats->tabr.count,
23937       lgl->limits->tabr.vars, lgl->limits->tabr.clauses);
23938 }
23939
23940 static void lglincsetupreduce (LGL * lgl) {
23941   lgl->limits->reduce.inner = lgl->opts->redlinit.val;
23942   lglboundredl (lgl);
23943   lgl->limits->reduce.outer = 2*lgl->limits->reduce.inner;
23944 }
23945
23946 static void lgltabrflushred (LGL * lgl) {
23947   assert (lgl->opts->tabr.val >= 1);
23948   lgliflushcache (lgl, lgl->opts->tabrkeep.val);
23949   lglincsetupreduce (lgl);
23950 }
23951
23952 static void lgltabrflushphases (LGL * lgl) {
23953   if (lgl->opts->tabr.val < 2) return;
23954   lglflushphasesaux (lgl, 1);
23955   lglphase (lgl);
23956   lgl->limits->rephase.confs = lgl->stats->rephase.inc = 10000;
23957 }
23958
23959 static void lgltabrflushscores (LGL * lgl) {
23960   QVar * qv;
23961   int idx;
23962   if (lgl->opts->tabr.val < 4) return;
23963   lglrelstk (lgl, &lgl->dsched);
23964   lglcutwidth (lgl);
23965   for (idx = 2; idx < lgl->nvars; idx++) {
23966     qv = lgl->qvars + idx;
23967     qv->pos = -1;
23968     qv->score = 0;
23969     lgldsched (lgl, idx);
23970   }
23971 }
23972
23973 static void lgltabrsetup (LGL * lgl) {
23974   int64_t newlimit;
23975   if (lgl->opts->tabr.val < 3) return;
23976   if (lgl->limits->simp.cinc != lgl->opts->cintinc.val) {
23977     lgl->limits->simp.cinc = lgl->opts->cintinc.val;
23978     lglprt (lgl, 1,
23979       "[tabula-rasa-%d] new conflict interval %d",
23980       lgl->stats->tabr.count, lgl->limits->simp.cinc);
23981   } else 
23982     lglprt (lgl, 1,
23983       "[tabula-rasa-%d] conflict interval %d does not change",
23984       lgl->stats->tabr.count, lgl->limits->simp.cinc);
23985   newlimit = lgl->stats->confs + lgl->limits->simp.cinc;
23986   if (newlimit < lgl->limits->simp.confs) {
23987     lgl->limits->simp.confs = newlimit;
23988     lglprt (lgl, 1,
23989       "[tabula-rasa-%d] new conflict limit %d",
23990       lgl->stats->tabr.count, newlimit);
23991   } else
23992     lglprt (lgl, 1,
23993       "[tabula-rasa-%d] conflict limit %d does not change",
23994       lgl->stats->tabr.count, lgl->limits->simp.cinc);
23995 }
23996
23997 static void lgltabularasa (LGL * lgl) {
23998   lglstart (lgl, &lgl->times->tabr);
23999   if (lgl->level > 0) lglbacktrack (lgl, 0);
24000   lgltabrflushred (lgl);
24001   lgltabrflushphases (lgl);
24002   lgltabrflushscores (lgl);
24003   lgltabrsetup (lgl);
24004   lglupdtabr (lgl);
24005   lglstop (lgl);
24006 }
24007
24008 static void lglregularly (LGL * lgl) {
24009   if (lglreducing (lgl)) lglreduce (lgl, 0);
24010   if (lgltabring (lgl)) lgltabularasa (lgl);
24011   if (lgldefragmenting (lgl)) lgldefrag (lgl);
24012 }
24013
24014 static void lglupdsimpcinc (LGL * lgl, int red, int success) {
24015   const char * type = "no";
24016   int inc = 0, div = 1, res;
24017   assert (red >= 0);
24018   if (red <= 100) {
24019     if (red > 0) {
24020       switch (lgl->opts->cintincdiv.val) {
24021         case 3: 
24022           if (red >= 50) div = 4;
24023           else if (red >= 20) div = 3;
24024           else if (red >= 10) div = 2;
24025           break;
24026         case 2: div = red/2 + 1; break;
24027         case 1: div = red/1 + 1; break;
24028         case 0:
24029         default: 
24030           assert (!lgl->opts->cintincdiv.val);
24031           break;
24032       }
24033     }
24034     inc = lgl->opts->cintinc.val;
24035     if (lgl->opts->simplify.val == 1) {
24036       type = "arithmetic";
24037     } else if (lgl->opts->simplify.val == 2) {
24038       if (inc < lgl->limits->simp.cinc) inc = lgl->limits->simp.cinc;
24039       type = "geometric";
24040     } else inc = 0;
24041   }
24042   res = inc / div;
24043   if (lgl->limits->simp.cinc - res <= INT_MAX)
24044     lgl->limits->simp.cinc += res;
24045   lglprt (lgl, 2,
24046     "[simplification-%d] new lgl->limits->simp.cinc %d",
24047     lgl->stats->simp.count, lgl->limits->simp.cinc);
24048   if (div > 1)
24049     lglprt (lgl, 1,
24050       "[simplification-%d] %s conflict interval increment %d = %d / %d",
24051       lgl->stats->simp.count, type, res, inc, div);
24052   else
24053     lglprt (lgl, 1,
24054       "[simplification-%d] full %s conflict interval increment %d",
24055       lgl->stats->simp.count, type, res);
24056
24057   if (success &&
24058       lgl->opts->cintmaxsoft.val >= 0 &&
24059       lgl->limits->simp.cinc >= lgl->opts->cintmaxsoft.val) {
24060     lgl->limits->simp.cinc = lgl->opts->cintmaxsoft.val;
24061     lglprt (lgl, 1,
24062       "[simplification-%d] "
24063       "conflict interval soft limit %d reached",
24064       lgl->stats->simp.count, lgl->limits->simp.cinc);
24065   } else if (lgl->opts->cintmaxhard.val >= 0 &&
24066              lgl->limits->simp.cinc >= lgl->opts->cintmaxhard.val) {
24067     lgl->limits->simp.cinc = lgl->opts->cintmaxhard.val;
24068     lglprt (lgl, 1,
24069       "[simplification-%d] "
24070       "conflict interval hard limit %d reached",
24071       lgl->stats->simp.count, lgl->limits->simp.cinc);
24072   }
24073 }
24074
24075 static void lglupdsimpint (LGL * lgl, int oldrem, int oldirr, int forced) {
24076   int remvar, remirr, pcntred, simpcinc;
24077   int64_t pcntremvar64, pcntremirr64;
24078   int pcntremvar, pcntremirr;
24079
24080   remvar = oldrem - lglrem (lgl);
24081   if (remvar < 0) remvar = 0;
24082   pcntremvar64 = (remvar > 0) ? ((1000ll*remvar)/oldrem + 5)/10 : 0ll;
24083   assert (pcntremvar64 <= 100);
24084   pcntremvar = pcntremvar64;
24085   lglprt (lgl, 1,
24086     "[simplification-%d] removed %d variables %.1f%% "
24087     "(%d remain %0.f%%)",
24088     lgl->stats->simp.count, remvar, lglpcnt (remvar, oldrem),
24089     lglrem (lgl), lglpcnt (lglrem (lgl), lgl->limits->inc.vars.start));
24090
24091   remirr = oldirr - lgl->stats->irr.clauses.cur;
24092   if (remirr < 0) remirr = 0;
24093   pcntremirr64 = (remirr > 0) ? ((1000ll*remirr)/oldirr + 5)/10 : 0ll;
24094   assert (pcntremirr64 <= 100);
24095   pcntremirr = pcntremirr64;
24096   lglprt (lgl, 1,
24097     "[simplification-%d] removed %d irredundant clauses %.1f%% "
24098     "(%d remain %.0f%%)",
24099     lgl->stats->simp.count, remirr, lglpcnt (remirr, oldirr),
24100     lgl->stats->irr.clauses.cur,
24101       lglpcnt (lgl->stats->irr.clauses.cur, lgl->limits->inc.clauses.start));
24102
24103   pcntred = lglmax (pcntremvar, pcntremirr);
24104   lglprt (lgl, 1,
24105     "[simplification-%d] maximum reduction of %d%% = max (%d%%, %d%%)",
24106     lgl->stats->simp.count, pcntred, pcntremvar, pcntremirr);
24107
24108   if (forced) {
24109     simpcinc = 0;
24110     lglprt (lgl, 1,
24111       "[simplification-%d] forced so keeping old conflict interval %d",
24112       lgl->stats->simp.count, lgl->limits->simp.cinc);
24113   } else if (lgl->stats->confs < lgl->limits->simp.confs &&
24114              (simpcinc = lgl->limits->simp.cinc)) {
24115     lglprt (lgl, 1,
24116       "[simplification-%d] keeping old conflict interval %d "
24117       "(non-conflict triggered simplification)",
24118       lgl->stats->simp.count, lgl->limits->simp.cinc);
24119   } else if (remvar > 0 && pcntred >= lgl->opts->simprtc.val) {
24120     int64_t scaledcinc;
24121     int factor;
24122     lglprt (lgl, 1,
24123       "[simplification-%d] large reduction %d%% >= %d%% limit",
24124       lgl->stats->simp.count, pcntred, lgl->opts->simprtc.val);
24125     factor = lgl->opts->simpidiv.val - lgl->stats->simp.count;
24126     if (factor <= 0) factor = 1;
24127     simpcinc = lgl->opts->simpinterdelay.val / factor;
24128     scaledcinc = lgl->stats->confs/lgl->opts->simpiscale.val;
24129     if (scaledcinc > lgl->limits->simp.cinc)
24130       scaledcinc = lgl->limits->simp.cinc;
24131     if (scaledcinc < simpcinc) {
24132       lglprt (lgl, 1,
24133         "[simplification-%d] new conflict interval %d = %d/%d",
24134         lgl->stats->simp.count,
24135         simpcinc, lgl->opts->simpinterdelay.val, factor);
24136     } else {
24137       assert (scaledcinc <= INT_MAX);
24138       simpcinc = (int) scaledcinc;
24139       lglprt (lgl, 1,
24140         "[simplification-%d] new conflict interval %d = min (%lld/%d, %d)",
24141         lgl->stats->simp.count,
24142         simpcinc, (LGLL) lgl->stats->confs, lgl->opts->simpiscale.val,
24143         lgl->limits->simp.cinc);
24144     }
24145   } else {
24146     lglupdsimpcinc (lgl, pcntred, remvar || remirr);
24147     simpcinc = lgl->limits->simp.cinc;
24148     lglprt (lgl, 1, "[simplification-%d] new conflict interval %d",
24149             lgl->stats->simp.count, simpcinc);
24150   }
24151
24152   if (forced) {
24153     lglprt (lgl, 1,
24154       "[simplification-%d] conflict limit remains at %lld",
24155       lgl->stats->simp.count, (LGLL) lgl->limits->simp.confs);
24156   } else {
24157     int penalty, pensimpcinc;
24158          if (lgl->stats->irr.clauses.cur <    1000000) penalty = 1;
24159     else if (lgl->stats->irr.clauses.cur <   10000000) penalty = 2;
24160     else                                               penalty = 4;
24161     if (INT_MAX/penalty < simpcinc) pensimpcinc = INT_MAX;
24162     else pensimpcinc = penalty * simpcinc;
24163     lglprt (lgl, 1,
24164       "[simplification-%d] penalized conflict interval %d = %d * %d",
24165       lgl->stats->simp.count, pensimpcinc, penalty, simpcinc);
24166     assert (pensimpcinc >= 0);
24167     lgl->limits->simp.confs = lgl->stats->confs + pensimpcinc;
24168     assert (lgl->limits->simp.confs >= 0);
24169     lglprt (lgl, 1,
24170       "[simplification-%d] new conflict limit %lld",
24171       lgl->stats->simp.count, (LGLL) lgl->limits->simp.confs);
24172   }
24173
24174   if (lgl->limits->simp.pen > 0) {
24175     lgl->limits->simp.pen--;
24176     lglprt (lgl, 1,
24177       "[simplification-%d] simplification penalty reduced to %d",
24178       lgl->stats->simp.count, lgl->limits->simp.pen);
24179   }
24180
24181   lgl->limits->simp.vars = lglrem (lgl);
24182   lgl->forcerephead = 1;
24183   if (lgl->wait > 0) lgl->wait--;
24184 }
24185
24186 static int lglpreprocessing (LGL * lgl, int forced) {
24187   int res, oldrem, oldirr;
24188   if (lgl->mt) return 0;
24189   assert (!lgl->searching);
24190   lgl->stats->simp.count++;
24191   oldrem = lglrem (lgl);
24192   oldirr = lgl->stats->irr.clauses.cur;
24193   res = lglisimp (lgl);
24194   lglupdsimpint (lgl, oldrem, oldirr, forced);
24195   assert (res == !lgl->mt);
24196   return res;
24197 }
24198
24199 static int lglsimplimhit (LGL * lgl) {
24200   int64_t n, o, d;
24201   int a, r, res = 0;;
24202   if (!lgl->opts->inprocessing.val && lgl->stats->simp.count) return 0;
24203   if (lgl->stats->confs >= lgl->limits->simp.confs) {
24204     lglprt (lgl, 1, "");
24205     lglprt (lgl, 1,
24206       "[simplification-%d] limit of %lld conflicts hit after %lld conflicts",
24207       lgl->stats->simp.count + 1,
24208       (LGLL) lgl->limits->simp.confs, (LGLL) lgl->stats->confs);
24209     lgl->stats->simp.limhit.confs++;
24210     res = 1;
24211   }
24212   if (!res &&
24213       (o = lgl->limits->simp.vars) &&
24214       (n = lglrem (lgl)) >= lgl->opts->simpvarlim.val) {
24215     d = n - o;
24216     r = 100*d;
24217     r /= o;
24218     if (r <= INT_MIN || r > INT_MAX) a = INT_MAX;
24219     else if (r < 0) a = -r;
24220     else a = r;
24221     if (a >= lgl->opts->simpvarchg.val) {
24222       lglprt (lgl, 1, "");
24223       lglprt (lgl, 1,
24224         "[simplification-%d] limit hit: "
24225         "remaining variables changed from %lld to %lld by %d%%",
24226         lgl->stats->simp.count + 1, (LGLL) o, (LGLL) n, r);
24227       lgl->stats->simp.limhit.vars++;
24228       res = 1;
24229     }
24230   }
24231   if (res) {
24232     if (lgl->limits->simp.pen)
24233       lglprt (lgl, 1,
24234         "[simplification-%d] with simplification penalty of %d",
24235         lgl->stats->simp.count + 1, lgl->limits->simp.pen);
24236     else
24237       lglprt (lgl, 2,
24238         "[simplification-%d] no simplification penalty",
24239         lgl->stats->simp.count + 1);
24240   }
24241   return res;
24242 }
24243
24244 static int lglinprocessing (LGL * lgl) {
24245   int res, oldrem, oldirr;
24246   assert (lgl->searching);
24247   if (!lglsimplimhit (lgl)) return !lgl->mt;
24248   lgl->stats->simp.count++;
24249   lglstart (lgl, &lgl->times->inpr);
24250   oldrem = lglrem (lgl);
24251   oldirr = lgl->stats->irr.clauses.cur;
24252   res = lglisimp (lgl);
24253   lglupdsimpint (lgl, oldrem, oldirr, 0);
24254   lglstop (lgl);
24255   assert (res == !lgl->mt);
24256   return res;
24257 }
24258
24259 static int lglbcptop (LGL * lgl) {
24260   int res;
24261   if (lglbcp (lgl)) res = 1;
24262   else {
24263 #ifndef NDEBUG
24264     int tmp =
24265 #endif
24266     lglana (lgl);
24267     assert (!tmp);
24268     if (lgl->conf.lit) {
24269       LOG (1, "top level propagation produces inconsistency");
24270       if (!lgl->mt) lgl->mt = 1;
24271     } else assert (lgl->failed);
24272     res = 0;
24273   }
24274   return res;
24275 }
24276
24277 static int lglimhit (LGL * lgl, Lim * lim) {
24278   if (!lim) return 0;
24279   if (lim->decs >= 0 && lgl->stats->decisions >= lim->decs) {
24280     lglprt (lgl, 1, "[limits] decision limit %lld hit at %lld decisions",
24281       (LGLL) lim->decs, (LGLL) lgl->stats->decisions);
24282     return 1;
24283   }
24284   if (lim->confs >= 0 && lgl->stats->confs >= lim->confs) {
24285     lglprt (lgl, 1, "[limits] conflict limit %lld hit at %lld conflicts",
24286       (LGLL) lim->confs, (LGLL) lgl->stats->confs);
24287     return 1;
24288   }
24289   if (lim->props >= 0 && lgl->stats->props.search >= lim->props) {
24290     lglprt (lgl, 1,
24291       "[limits] propagation limit %lld hit at %lld propagations",
24292       (LGLL) lim->props, (LGLL) lgl->stats->props.search);
24293     return 1;
24294   }
24295   return 0;
24296 }
24297
24298 static int lgloop (LGL * lgl, Lim * lim) {
24299   unsigned confs = 0;
24300   for (;;) {
24301     if (lglbcpsearch (lgl) && lglinprocessing (lgl)) {
24302       if (lglterminate (lgl)) return 0;
24303       if (!lglsyncunits (lgl)) return 20;
24304       if (!lglsyncls (lgl)) continue;
24305       if (lglfailedass (lgl)) return 20;
24306       lglregularly (lgl);
24307       if (lglimhit (lgl, lim)) return 0;
24308       if (lglocsing (lgl)) lglocs (lgl);
24309       if (lglrestarting (lgl)) { lglrestart (lgl); continue; }
24310       if (!lgldecide (lgl)) return 10;
24311     } else if (!lglana (lgl)) return 20;
24312     else if (!(++confs & 15) && lglterminate (lgl)) return 0;
24313   }
24314 }
24315
24316 static int lglsearch (LGL * lgl, Lim * lim) {
24317   int res;
24318   assert (!lgl->searching);
24319   lgl->searching = 1;
24320   lglstart (lgl, &lgl->times->srch);
24321   res = lgloop (lgl, lim);
24322   assert (lgl->searching);
24323   lgl->searching = 0;
24324   lglstop (lgl);
24325   return res;
24326 }
24327
24328 static int lgltopsimp (LGL * lgl, int forcesimp) {
24329   assert (lgl->state == READY);
24330   if (lgl->mt) return 20;
24331   if (lglfailedass (lgl)) return 20;
24332   if (!lglbcptop (lgl)) return 20;
24333   if (lgl->mt || lglfailedass (lgl)) return 20;
24334   if (lglterminate (lgl)) return 0;
24335   if ((forcesimp || lglsimplimhit (lgl)) &&
24336       !lglpreprocessing (lgl, forcesimp)) return 20;
24337   if (lglfailedass (lgl)) return 20;
24338   if (!lgl->stats->cutwidths) lglcutwidth (lgl);
24339   lglrep (lgl, 2, 's');
24340   return 0;
24341 }
24342
24343 static int lglsolve (LGL * lgl, Lim * lim, int forcesimp) {
24344   int res;
24345   lgl->limits->simp.pen = lgl->opts->simpen.val;
24346   lglstart (lgl, &lgl->times->prep);
24347   res = lgltopsimp (lgl, forcesimp);
24348   lglstop (lgl);
24349   if (res) { assert (res == 20); return res; }
24350   return lglsearch (lgl, lim);
24351 }
24352
24353 static void lglincsetup (LGL * lgl) {
24354
24355   if (lgl->opts->incsavevisits.val)
24356     lgl->limits->inc.visits = lgl->stats->visits.search;
24357
24358   assert (lgl->limits->inc.clauses.add <= lgl->stats->irr.clauses.add);
24359   if (lgl->limits->inc.clauses.add < lgl->stats->irr.clauses.add) {
24360     lgl->limits->inc.clauses.add = lgl->stats->irr.clauses.add;
24361     lgl->elmrtc = lgl->blkrtc = lgl->ccertc = 0;
24362     lgl->elmstuck = lgl->blkstuck = 0;
24363     lgl->wait = lgl->opts->waitmax.val;
24364   }
24365
24366   lgl->limits->inc.clauses.start = lgl->stats->irr.clauses.cur;
24367   lgl->limits->inc.vars.start = lglrem (lgl);
24368
24369   lgl->limits->tabr.clauses = lgl->limits->inc.clauses.start;
24370   lgl->limits->tabr.vars = lgl->limits->inc.vars.start;
24371   lgl->limits->tabr.vars /= lgl->opts->tabrvfactor.val;
24372   lgl->limits->tabr.clauses /= lgl->opts->tabrcfactor.val;
24373
24374   lglincsetupreduce (lgl);
24375
24376   lgl->limits->flipint = lgl->opts->flipint.val;
24377
24378   lgl->stats->locs.min = INT_MAX;
24379   lglupdlocslim (lgl, 0);
24380
24381   lgl->limits->rephase.confs = lgl->stats->rephase.inc = 10000;
24382
24383   CLR (lgl->limits->restart);
24384   lgl->limits->restart.confs =
24385     lgl->stats->confs + lgl->opts->restartinit.val;
24386
24387   lgl->limits->simp.pen = 0;
24388   if (lgl->opts->incredcint.val > 1) {
24389     lgl->limits->simp.cinc /= lgl->opts->incredcint.val;
24390     lglprt (lgl, 1,
24391        "[incremental-setup] conflict interval increment reduced to %d",
24392        lgl->limits->simp.cinc);
24393   }
24394   if (lgl->opts->incredconfslim.val) {
24395     lgl->limits->simp.confs =
24396       ((100-lgl->opts->incredconfslim.val)*lgl->limits->simp.confs)/100;
24397     lglprt (lgl, 1,
24398        "[incremental-setup] conflict limit reduced to %lld",
24399        (LGLL) lgl->limits->simp.confs);
24400   }
24401
24402   CLR (lgl->limits->cgr.del);
24403
24404   CLR (lgl->limits->elm.del);
24405   CLR (lgl->limits->blk.del);
24406   CLR (lgl->limits->cliff.del);
24407
24408   CLR (lgl->limits->rdp.del);
24409   CLR (lgl->limits->trd.del);
24410   CLR (lgl->limits->unhd.del);
24411   CLR (lgl->limits->trnr.del);
24412   CLR (lgl->limits->lft.del);
24413   CLR (lgl->limits->cce.del);
24414   CLR (lgl->limits->card.del);
24415
24416   CLR (lgl->limits->gauss.del);
24417
24418   CLR (lgl->limits->prb.simple.del);
24419   CLR (lgl->limits->prb.basic.del);
24420   CLR (lgl->limits->prb.treelook.del);
24421
24422   CLR (lgl->limits->bca.del);
24423 }
24424
24425 static void lglsetup (LGL * lgl) {
24426   if (lgl->setuponce) goto DONE;
24427   lgl->limits->dfg = lgl->stats->pshwchs + lgl->opts->defragint.val;
24428
24429   lgl->limits->blk.irrprgss = -1;
24430   lgl->limits->elm.irrprgss = -1;
24431   lgl->limits->term.steps = -1;
24432
24433   lgl->phaseneg = lgl->opts->phaseneginit.val;
24434
24435   lgl->rng.w = (unsigned) lgl->opts->seed.val;
24436   lgl->rng.z = ~lgl->rng.w;
24437   lgl->rng.w <<= 1;
24438   lgl->rng.z <<= 1;
24439   lgl->rng.w += 1;
24440   lgl->rng.z += 1;
24441   lgl->rng.w *= 2019164533u, lgl->rng.z *= 1000632769u;
24442
24443   assert (!lgl->stats->decisions);
24444   lgl->limits->randec += lgl->opts->randecint.val/2;
24445   lgl->limits->randec += lglrand (lgl) % lgl->opts->randecint.val;
24446
24447   lgl->limits->simp.vars = lglrem (lgl);
24448
24449   lgl->setuponce = 1;
24450   lglchkenv (lgl);
24451 DONE:
24452   lglinitscores (lgl);
24453   lglincsetup (lgl);
24454   TRANS (READY);
24455 }
24456
24457 static void lglinitsolve (LGL * lgl) {
24458   if (lgl->state != READY) lglsetup (lgl);
24459   lglredvars (lgl);
24460   lglfitstk (lgl, &lgl->irr);
24461 #ifndef NCHKSOL
24462   lglfitstk (lgl, &lgl->orig);
24463 #endif
24464   lglrep (lgl, 1, '*');
24465 }
24466
24467 #ifndef NLGLPICOSAT
24468 static void lglpicosatchksol (LGL * lgl) {
24469 #ifndef NDEBUG
24470   int idx, lit, res, * p;
24471   Val val;
24472   if (lgl->picosat.res) assert (lgl->picosat.res == 10);
24473   lglpicosatinit (lgl);
24474   assert (!picosat_inconsistent (PICOSAT));
24475   for (idx = 2; idx < lgl->nvars; idx++) {
24476     val = lglval (lgl, idx);
24477     assert (val);
24478     lit = lglsgn (val) * idx;
24479     picosat_assume (PICOSAT, lit);
24480   }
24481   for (p = lgl->eassume.start; p < lgl->eassume.top; p++)
24482     picosat_assume (PICOSAT, lglimport (lgl, *p));
24483   res = picosat_sat (PICOSAT, -1);
24484   assert (res == 10);
24485   LOG (1, "PicoSAT checked solution");
24486 #endif
24487 }
24488 #endif
24489
24490 static void lgleassign (LGL * lgl, int lit) {
24491   Ext * ext;
24492   ext = lglelit2ext (lgl, lit);
24493   LOG (3, "external assign %d ", lit);
24494   ext->val = lglsgn (lit);
24495 }
24496
24497 static void lglcomputechanged (LGL * lgl) {
24498   Ext * ext;
24499   int eidx;
24500   lgl->changed = 0;
24501   for (eidx = 1; eidx <= lgl->maxext; eidx++) {
24502     ext = lglelit2ext (lgl, eidx);
24503     if (ext->oldval && ext->oldval != ext->val) lgl->changed++;
24504     ext->oldval = ext->val;
24505   }
24506   LOG (1, "changed %d assignments in extension", lgl->changed);
24507 }
24508
24509 static void lglextend (LGL * lgl) {
24510   int * p, lit, eidx, ilit, next, satisfied, val, * start, erepr, equiv;
24511   Ext * ext, * extrepr;
24512   assert (lgl->state & SATISFIED);
24513   assert (!(lgl->state & EXTENDED));
24514   lgleunassignall (lgl);
24515   for (equiv = 0; equiv <= 1; equiv++) {
24516     if (equiv)
24517       LOG (1, "initializing assignment of non-representative externals");
24518     else
24519       LOG (1, "initializing assignment of external representatives");
24520     for (eidx = 1; eidx <= lgl->maxext; eidx++) {
24521       ext = lglelit2ext (lgl, eidx);
24522       if (!ext->imported) continue;
24523       if (equiv != ext->equiv) continue;
24524       assert (!ext->val);
24525       if (ext->equiv) {
24526         erepr = lglerepr (lgl, eidx);
24527 LOG (3, "initializing external %d assignment from external representative %d",
24528          eidx, erepr);
24529         assert (erepr != eidx);
24530         extrepr = lglelit2ext (lgl, erepr);
24531         if (!(val = extrepr->val)) {
24532           ilit = extrepr->repr;
24533           if (ilit) {
24534             LOG (3, "using external %d to internal %d mapping",
24535                  abs (erepr), ilit);
24536             val = lglcval (lgl, ilit);
24537           } else
24538 LOG (3, "external %d without internal representative", abs (erepr));
24539         }
24540         if (erepr < 0) val = -val;
24541       } else
24542       if ((ilit = ext->repr)) {
24543         LOG (3, "using external %d to internal %d mapping", eidx, ilit);
24544         val = lglcval (lgl, ilit);
24545       } else {
24546         LOG (3, "external %d without internal representative", eidx);
24547         val = 0;
24548       }
24549       lit = (val > 0) ? eidx : -eidx;
24550       lgleassign (lgl, lit);
24551     }
24552   }
24553   start = lgl->extend.start;
24554   p = lgl->extend.top;
24555   if (p == start) goto SKIP;
24556   assert (p > start);
24557   p--;
24558   assert (!*p);
24559   while (p > start) {
24560 #ifndef NLGLOG
24561     if (lgl->opts->log.val >= 4) {
24562       int * q;
24563       for (q = p; q[-1]; q--)
24564         ;
24565       LOGCLS (4, q, "next sigma clause to consider");
24566     }
24567 #endif
24568     satisfied = 0;
24569     next = 0;
24570     do {
24571       lit = next;
24572       if (p == start) next = 0; else next = *--p;
24573       if (!lit || satisfied) continue;
24574       val = lglederef (lgl, lit);
24575       assert (!next || val);
24576       if (val > 0) {
24577         LOG (4, "sigma clause satisfied by %d", lit);
24578         satisfied = 1;
24579       }
24580     } while (next);
24581     assert (lit);
24582     if (satisfied) continue;
24583     lgleassign (lgl, lit);
24584   }
24585 SKIP:
24586   lglcomputechanged (lgl);
24587   TRANS (EXTENDED);
24588 }
24589
24590 void lglsetphases (LGL * lgl) {
24591   int elit, phase;
24592   REQINITNOTFORKED ();
24593   TRAPI ("setphases");
24594   REQUIRE (SATISFIED | EXTENDED);
24595   if (!(lgl->state & EXTENDED)) lglextend (lgl);
24596   for (elit = 1; elit <= lgl->maxext; elit++) {
24597     phase = lglederef (lgl, elit);
24598     assert (abs (phase) <= 1);
24599     lglesetphase (lgl, elit, phase);
24600   }
24601   if (lgl->clone) lglsetphases (lgl->clone);
24602 }
24603
24604 #ifndef NCHKSOL
24605 #include <signal.h>
24606 #include <unistd.h>
24607 static void lglchksol (LGL * lgl) {
24608   int * p, * c, * eoo = lgl->orig.top, lit, satisfied, sign, idx;
24609   unsigned bit;
24610   Ext * ext;
24611   assert (lglmtstk (&lgl->orig) || !eoo[-1]);
24612   assert (lgl->state == EXTENDED);
24613   for (c = lgl->orig.start; c < eoo; c = p + 1) {
24614     satisfied = 0;
24615     for (p = c; (lit = *p); p++)
24616       if (!satisfied && lglederef (lgl, lit) > 0)
24617         satisfied = 1;
24618     if (satisfied) continue;
24619     fflush (stderr);
24620     lglmsgstart (lgl, 0);
24621     fprintf (lgl->out, "unsatisfied original external clause");
24622     for (p = c; (lit = *p); p++) fprintf (lgl->out, " %d", lit);
24623     lglmsgend (lgl);
24624     assert (satisfied);
24625     usleep (1000);
24626     abort ();   // NOTE: not 'lglabort' on purpose !!
24627   }
24628   for (idx = 1; idx <= lgl->maxext; idx++) {
24629     ext = lglelit2ext (lgl, idx);
24630     if (!ext->assumed) continue;
24631     for (sign = -1; sign <= 1; sign += 2) {
24632       lit = sign * idx;
24633       bit = 1u << (lit < 0);
24634       if (!(ext->assumed & bit)) continue;
24635       if (lglederef (lgl, lit) > 0) continue;
24636       lglprt (lgl, 0, "unsatisfied assumption %d", lit);
24637       assert (lglederef (lgl, lit) > 0);
24638       usleep (1000);
24639       abort (); // DITO: not 'lglabort' on purpose !!
24640     }
24641   }
24642 }
24643 #endif
24644
24645 static void lglclass (LGL * lgl, LGL * from) {
24646   Ext * extfrom, * extlgl;
24647   int eidx, cloned;
24648   REQINITNOTFORKED ();
24649   ABORTIF (lgl->mt, "can not clone assignment into inconsistent manager");
24650   ABORTIF (!from, "uninitialized 'from' solver");
24651   ABORTIF (!(from->state & (SATISFIED | EXTENDED)),
24652     "require 'from' state to be (SATISFIED | EXTENDED)"); 
24653   ABORTIF (from->maxext != lgl->maxext,
24654     "can not clone assignments for different sets of variables");
24655   if (!(from->state & EXTENDED)) lglextend (from);
24656   lglreset (lgl);
24657   lgleunassignall (lgl);
24658   cloned = lgl->changed = 0;
24659   for (eidx = 1; eidx <= lgl->maxext; eidx++) {
24660     extlgl = lglelit2ext (lgl, eidx);
24661     if (!extlgl->imported) continue;
24662     extfrom = lglelit2ext (from, eidx);
24663     ABORTIF (!extfrom->imported, 
24664       "can not clone assignment of literal imported only by 'to'");
24665     assert (extfrom->val == 1 || extfrom->val == -1);
24666     lgleassign (lgl, extfrom->val*eidx);
24667     cloned++;
24668   }
24669   lglcomputechanged (lgl);
24670   lglprt (lgl, 1, "[class] cloned %d assignments (%d changed)",
24671           cloned, lgl->changed);
24672   TRANS (EXTENDED);
24673 #ifndef NCHKSOL
24674   lglchksol (lgl);
24675 #endif
24676 #ifndef NLGLPICOSAT
24677   lglpicosatchksol (lgl);
24678 #endif
24679 }
24680
24681 static void lglnegass (LGL * lgl) {
24682   const int  * p;
24683   Stk eassume;
24684   REQINITNOTFORKED ();
24685   TRAPI ("negass");
24686   if (lgl->mt) return;
24687   CLR (eassume);
24688   for (p = lgl->eassume.start; p < lgl->eassume.top; p++)
24689     lglpushstk (lgl, &eassume, *p);
24690   for (p = eassume.start; p < eassume.top; p++)
24691     lgleadd (lgl, -*p);
24692   lgleadd (lgl, 0);
24693   assert (lglmtstk (&lgl->eassume));
24694   for (p = eassume.start; p < eassume.top; p++)
24695     lglassume (lgl, *p);
24696   lglrelstk (lgl, &eassume);
24697   lgluse (lgl);
24698   if (lgl->clone) lglnegass (lgl->clone);
24699 }
24700
24701 static int lglcompactify (LGL * lgl, int res) {
24702   if (!lgl->opts->compact.val) return 0;
24703   if (!res) return 1;
24704   if (res == 20) return 1;
24705   assert (res == 10);
24706   return lgl->opts->compact.val >= 2;
24707 }
24708
24709 static int lglisat (LGL * lgl, Lim * lim, int simpits) {
24710   int res, count, reported = lgl->stats->reported;
24711   lglreset (lgl);
24712   lglinitsolve (lgl);
24713   res = lglsolve (lgl, lim, 0);
24714   for (count = 0; !res && count < simpits; count++) {
24715     lglprt (lgl, 1,
24716       "[simplification-%d] next forced simplification iteration %d",
24717       lgl->stats->simp.count + 1, count + 1);
24718     res = lglsolve (lgl, lim, 1);
24719   }
24720   if (lglcompactify (lgl, res)) lglcompact (lgl);
24721   if (!res) {
24722     TRANS (UNKNOWN);
24723     lglrep (lgl, 1, '?');
24724   }
24725   if (res == 10) {
24726     TRANS (SATISFIED);
24727     lglrep (lgl, 1, '1');
24728   }
24729   if (res == 20) {
24730     TRANS (UNSATISFIED);
24731     if (!lgl->level && !lgl->mt) assert (lgl->failed);
24732     lglrep (lgl, 1, '0');
24733   }
24734   if (reported != lgl->stats->reported) lglflshrep (lgl);
24735   if (res == 10) lglextend (lgl);
24736 #ifndef NCHKSOL
24737   if (res == 10) lglchksol (lgl);
24738 #endif
24739 #ifndef NLGLPICOSAT
24740   if (res == 10) lglpicosatchksol (lgl);
24741   if (res == 20) lglpicosatchkunsat (lgl);
24742 #endif
24743   return res;
24744 }
24745
24746 int lglunclone (LGL * lgl, LGL * from) {
24747   int res;
24748   REQINITNOTFORKED ();
24749   if (lgl->mt) return 20;
24750   ABORTIF (!from, "uninitialized 'from' solver");
24751   if (from->mt || (from->state & UNSATISFIED)) {
24752     lglprt (lgl, 1, "[unclone] unsatisfied state");
24753     lglnegass (lgl);
24754     res = lglisat (lgl, 0, 0);
24755   } else if (from->state & (SATISFIED | EXTENDED)) {
24756     lglprt (lgl, 1, "[unclone] satisfied state");
24757     lglclass (lgl, from);
24758     res = 10;
24759   } else {
24760     lglprt (lgl, 1, "[unclone] unknown state");
24761     lglreset (lgl);
24762     TRANS (UNKNOWN);
24763     res = 0;
24764   }
24765   return res;
24766 }
24767
24768 #define CHKCLONESTATS(STATS) \
24769 do { \
24770   assert (clone->stats->STATS == orig->stats->STATS); \
24771 } while (0)
24772
24773 static void lglchkclonesamestats (LGL * orig) {
24774 #ifndef NDEBUG
24775   LGL * clone = orig->clone;
24776   assert (clone);
24777   assert (clone->state == orig->state);
24778   CHKCLONESTATS (confs);
24779   CHKCLONESTATS (decisions);
24780   CHKCLONESTATS (bytes.current);
24781   CHKCLONESTATS (bytes.max);
24782   CHKCLONESTATS (props.search);
24783   CHKCLONESTATS (props.simp);
24784   CHKCLONESTATS (props.lkhd);
24785   CHKCLONESTATS (visits.search);
24786   CHKCLONESTATS (visits.simp);
24787   CHKCLONESTATS (visits.lkhd);
24788 #endif
24789 }
24790
24791 #define CHKCLONE() \
24792 do { \
24793   if (!lgl->clone) break; \
24794   lglchkclonesamestats (lgl); \
24795 } while (0)
24796
24797 #define CHKCLONENORES(FUN) \
24798 do { \
24799   if (!lgl->clone) break; \
24800   FUN (lgl->clone); \
24801   CHKCLONE (); \
24802 } while (0)
24803
24804 #define CHKCLONERES(FUN,RES) \
24805 do { \
24806   int CLONERES; \
24807   if (!lgl->clone) break; \
24808   CLONERES = FUN (lgl->clone); \
24809   ABORTIF (CLONERES != (RES), \
24810            "%s (lgl->clone) = %d differs from %s (lgl) = %d", \
24811            __FUNCTION__, CLONERES, __FUNCTION__, (RES)); \
24812   CHKCLONE (); \
24813 } while (0)
24814
24815 #define RETURN(FUN,RES) \
24816 do { \
24817   TRAPI ("return %d", (RES)); \
24818   CHKCLONERES (FUN, (RES)); \
24819 } while (0)
24820
24821 #define CHKCLONEARGRES(FUN,ARG,RES) \
24822 do { \
24823   int CLONERES; \
24824   if (!lgl->clone) break; \
24825   CLONERES = FUN (lgl->clone, (ARG)); \
24826   ABORTIF (CLONERES != (RES), \
24827            "%s (lgl->clone, %d) = %d differs from %s (lgl, %d) = %d", \
24828            __FUNCTION__, (ARG), CLONERES, __FUNCTION__, (ARG), (RES)); \
24829   CHKCLONE (); \
24830 } while (0)
24831
24832 #define RETURNARG(FUN,ARG,RES) \
24833 do { \
24834   TRAPI ("return %d", (RES)); \
24835   CHKCLONEARGRES (FUN, (ARG), (RES)); \
24836 } while (0)
24837
24838 static void lglsetlim (LGL * lgl, Lim * lim) {
24839   int64_t clim, dlim, plim, confs, decs, props, delay, delayed;
24840   if ((dlim = lgl->opts->dlim.val) < 0) {
24841     lim->decs = -1;
24842     lglprt (lgl, 1, "[limits] no decision limit");
24843   } else {
24844     decs = lgl->stats->decisions;
24845     lim->decs = (decs >= LLMAX - dlim) ? LLMAX : decs + dlim;
24846     lglprt (lgl, 1, "[limits] decision limit %lld after %lld decisions", 
24847             (LGLL) lim->decs, (LGLL) decs);
24848   }
24849   if ((clim = lgl->opts->clim.val) < 0) {
24850     lim->confs = -1;
24851     lglprt (lgl, 1, "[limits] no conflict limit");
24852   } else {
24853     confs = lgl->stats->confs;
24854     lim->confs = (confs >= LLMAX - clim) ? LLMAX : confs + clim;
24855     lglprt (lgl, 1, "[limits] conflict limit %lld after %lld conflicts", 
24856             (LGLL) lim->confs, (LGLL) confs);
24857   }
24858   if ((plim = lgl->opts->plim.val) < 0) {
24859     lim->props = -1;
24860     lglprt (lgl, 1, "[limits] no propagation limit");
24861   } else {
24862     plim *= 1000;
24863     props = lgl->stats->props.search;
24864     lim->props = (props >= LLMAX - plim) ? LLMAX : props + plim;
24865     lglprt (lgl, 1,
24866       "[limits] propagation limit %lld after %lld propagations", 
24867       (LGLL) lim->props, (LGLL) props);
24868   }
24869   if ((delay = lgl->opts->simpdelay.val) > 0) {
24870     delayed = lgl->stats->confs + delay;
24871     if (delayed > lgl->limits->simp.confs) {
24872       lgl->limits->simp.confs = delayed;
24873       lglprt (lgl, 1,
24874         "[limits] simplification delayed by %lld to %lld conflicts",
24875         (LGLL) delay, (LGLL) lgl->limits->simp.confs);
24876     } else lglprt (lgl, 1, 
24877              "[limits] simplification conflict limit already exceeds delay");
24878   } else lglprt (lgl, 1, 
24879            "[limits] simplification not delayed since 'simpdelay' zero");
24880 }
24881
24882 int lglsat (LGL * lgl) {
24883   int res;
24884   Lim lim;
24885   REQINITNOTFORKED ();
24886   TRAPI ("sat");
24887   lglstart (lgl, &lgl->times->all);
24888   lgl->stats->calls.sat++;
24889   ABORTIF (!lglmtstk (&lgl->clause), "clause terminating zero missing");
24890   lglfreezer (lgl);
24891   lglsetlim (lgl, &lim);
24892   res = lglisat (lgl, &lim, 0);
24893   lglstop (lgl);
24894   RETURN (lglsat, res);
24895   return res;
24896 }
24897
24898 int lglmosat (LGL * lgl, void * state, lglnotify f, int * targets) {
24899   int cint, clim, target, ntargets, rtargets, next, round, done;
24900   signed char * reported, * r;
24901   int64_t confs, totalclim;
24902   const int * p;
24903   Val val;
24904   Lim lim;
24905
24906   REQINITNOTFORKED ();
24907   ABORTIF (!lglmtstk (&lgl->clause), "clause terminating zero missing");
24908
24909   TRAPI ("mosat");
24910   lglstart (lgl, &lgl->times->all);
24911   lgl->stats->calls.mosat++;
24912
24913   ntargets = 0;
24914   for (p = targets; *p; p++) ntargets++;
24915   NEW (reported, ntargets);
24916   rtargets = ntargets;
24917
24918   cint = lgl->opts->mocint.val;
24919   totalclim = (lgl->opts->clim.val < 0) ? 
24920                 LLMAX : lgl->stats->confs + lgl->opts->clim.val;
24921   round = 1;
24922   done = next = 0;
24923
24924   lglprt (lgl, 1,
24925     "[mosat-%lld] given %d targets",
24926     (LGLL) lgl->stats->calls.mosat, ntargets);
24927
24928   while (!lgl->mt) {
24929
24930     for (p = targets, r = reported; !done && (target = *p); p++, r++) {
24931       if (*r) continue;
24932       val = lglfixed (lgl, target);
24933       if (val >= 0) {
24934          if (lgl->state == SATISFIED && lglval (lgl, target) > 0) val = 1;
24935          else val = 0;
24936       }
24937       if (!val) continue;
24938       LOG (1, "notify %d %d", target, val);
24939       done = !f (state, target, val);
24940       assert (rtargets > 0), rtargets--;
24941       *r = val;
24942     }
24943
24944     round++;
24945     lglprt (lgl, 1,
24946       "[mosat-%lld-%d] %d targets remain out of %d (%.0f%%)",
24947       (LGLL) lgl->stats->calls.mosat, round, rtargets, ntargets,
24948       lglpcnt (rtargets, ntargets));
24949
24950     if (!rtargets) break;
24951     if (lgl->stats->confs > totalclim) break;
24952
24953     for (;;) {
24954       assert (next < ntargets);
24955       if (!lglfixed (lgl, (target = targets[next]))) break;
24956       if (++next == ntargets) next = 0;
24957     }
24958
24959     LOG (1, "focusing on target %d", target);
24960     lglassume (lgl, target);
24961
24962     confs = lgl->stats->confs;
24963     clim = lglmin (cint, lgl->opts->clim.val);
24964     lim.confs = (confs >= LLMAX - clim) ? LLMAX : confs + clim;
24965     lim.decs = -1;
24966     lglprt (lgl, 1, "[limits] conflict limit %lld after %lld conflicts", 
24967             (LGLL) lim.confs, (LGLL) confs);
24968
24969     (void) lglisat (lgl, &lim, 0);
24970     cint += lgl->opts->mocint.val;
24971   }
24972
24973   DEL (reported, ntargets);
24974
24975   lglprt (lgl, 1,
24976     "[mosat-%lld] solved %d targets out of %d, %d remain",
24977     (LGLL) lgl->stats->calls.mosat,
24978     ntargets - rtargets, ntargets, rtargets);
24979
24980   lglstop (lgl);
24981
24982   return !rtargets;
24983 }
24984
24985 int lglookahead (LGL * lgl) {
24986   int ilit, res;
24987   REQINITNOTFORKED ();
24988   TRAPI ("lkhd");
24989   ABORTIF (!lglmtstk (&lgl->eassume), "imcompatible with 'lglassume'");
24990   ABORTIF (!lglmtstk (&lgl->clause), "clause terminating zero missing");
24991   lglstart (lgl, &lgl->times->all);
24992   lglstart (lgl, &lgl->times->lkhd);
24993   lgl->stats->calls.lkhd++;
24994   lglreset (lgl);
24995   assert (!lgl->lkhd);
24996   lgl->lkhd = 1;
24997   lglfreezer (lgl);
24998   if (lgl->level) lglbacktrack (lgl, 0);
24999   if (!lgl->mt && lglbcp (lgl)) {
25000     ilit = 0;
25001     if (lgl->opts->lkhdmisifelmrtc.val &&
25002         lgl->opts->elim.val && lgl->elmrtc)
25003       ilit = lglmislook (lgl);
25004     else if (lgl->opts->lkhd.val == 2 && !lglsmallirr (lgl))
25005       ilit = lgljwhlook (lgl);
25006     else switch (lgl->opts->lkhd.val) {
25007       case -1: ilit = lglocslook (lgl); break;
25008       case 0: ilit = lglislook (lgl); break;
25009       case 1: ilit = lgljwhlook (lgl); break;
25010       case 2:
25011         if (!lgltreelookaux (lgl, &ilit)) assert (lgl->mt);
25012         break;
25013       case 3:
25014       default:
25015         assert (lgl->opts->lkhd.val == 3);
25016         ilit = lglsumlenlook (lgl);
25017         break;
25018     }
25019     res = (!lgl->mt && ilit) ? lglexport (lgl, ilit) : 0;
25020     assert (!res || !lglelit2ext (lgl, res)->melted);
25021   } else lgl->mt = 1, res = 0;
25022   assert (lgl->lkhd);
25023   lgl->lkhd = 0;
25024   lglstop (lgl);
25025   lglstop (lgl);
25026   TRANS (LOOKED);
25027   RETURN (lglookahead, res);
25028   return res;
25029 }
25030
25031 int lglchanged (LGL * lgl) {
25032   int res;
25033   REQINITNOTFORKED ();
25034   TRAPI ("changed");
25035   REQUIRE (EXTENDED);
25036   res = lgl->changed;
25037   RETURN (lglchanged, res);
25038   return res;
25039 }
25040
25041 int lglsimp (LGL * lgl, int iterations) {
25042   Lim lim;
25043   int res;
25044   REQINITNOTFORKED ();
25045   TRAPI ("simp %d", iterations);
25046   ABORTIF (iterations < 0, "negative number of simplification iterations");
25047   ABORTIF (!lglmtstk (&lgl->clause), "clause terminating zero missing");
25048   lglstart (lgl, &lgl->times->all);
25049   lgl->stats->calls.simp++;
25050   lglfreezer (lgl);
25051   CLR (lim);
25052   lim.decs = lgl->stats->decisions;
25053   res = lglisat (lgl, &lim, iterations);
25054   assert (!lgl->level);
25055   lglstop (lgl);
25056   RETURNARG (lglsimp, iterations, res);
25057   return res;
25058 }
25059
25060 int lglmaxvar (LGL * lgl) {
25061   int res;
25062   REQINITNOTFORKED ();
25063   TRAPI ("maxvar");
25064   res = lgl->maxext;
25065   RETURN (lglmaxvar, res);
25066   return res;
25067 }
25068
25069 int lglincvar (LGL  *lgl) {
25070   int res;
25071   REQINITNOTFORKED ();
25072   TRAPI ("incvar");
25073   res = lgl->maxext + 1;
25074   (void) lglimport (lgl, res);
25075   RETURN (lglincvar, res);
25076   return res;
25077 }
25078
25079 int lglderef (LGL * lgl, int elit) {
25080   int res;
25081   REQINIT ();
25082   TRAPI ("deref %d", elit);
25083   lgl->stats->calls.deref++;
25084   ABORTIF (!elit, "can not deref zero literal");
25085   REQUIRE (SATISFIED | EXTENDED);
25086   if (!(lgl->state & EXTENDED)) lglextend (lgl);
25087   res = lglederef (lgl, elit);
25088   RETURNARG (lglderef, elit, res);
25089   return res;
25090 }
25091
25092 int lglfailed (LGL * lgl, int elit) {
25093   unsigned bit;
25094   Ext * ext;
25095   int res;
25096   REQINITNOTFORKED ();
25097   TRAPI ("failed %d", elit);
25098   lgl->stats->calls.failed++;
25099   ABORTIF (!elit, "can not check zero failed literal");
25100   REQUIRE (UNSATISFIED | FAILED);
25101   ABORTIF (abs (elit) > lgl->maxext,
25102            "can not check unimported failed literal");
25103   ext = lglelit2ext (lgl, elit);
25104   bit = 1u << (elit < 0);
25105   ABORTIF (!(ext->assumed & bit),
25106            "can not check unassumed failed literal");
25107   if (!(lgl->state & FAILED)) {
25108     lglstart (lgl, &lgl->times->all);
25109     lglanafailed (lgl);
25110     lglstop (lgl);
25111   }
25112   res = (ext->failed & bit) != 0;
25113   RETURNARG (lglfailed, elit, res);
25114   return res;
25115 }
25116
25117 int lglinconsistent (LGL * lgl) {
25118   int res;
25119   TRAPI ("inconsistent");
25120   res = (lgl->mt != 0);
25121   RETURN (lglinconsistent, res);
25122   return res;
25123 }
25124
25125 static int lglefixed (LGL * lgl, int elit) {
25126   int res, ilit;
25127   assert (elit);
25128   if (abs (elit) > lgl->maxext) return 0;
25129   ilit = lglimport (lgl, elit);
25130   if (!ilit) res = 0;
25131   else if (abs (ilit) == 1) res = ilit;
25132   else res = lglifixed (lgl , ilit);
25133   return res;
25134 }
25135
25136 int lglfixed (LGL * lgl, int elit) {
25137   int res;
25138   REQINITNOTFORKED ();
25139   TRAPI ("fixed %d", elit);
25140   lgl->stats->calls.fixed++;
25141   ABORTIF (!elit, "can not deref zero literal");
25142   res = lglefixed (lgl, elit);
25143   RETURNARG (lglfixed, elit, res);
25144   return res;
25145 }
25146
25147 int lglrepr (LGL * lgl, int elit) {
25148   int res, eidx = abs (elit);
25149   REQINITNOTFORKED ();
25150   TRAPI ("repr %d", elit);
25151   lgl->stats->calls.repr++;
25152   if (eidx > lgl->maxext) res = elit;
25153   else {
25154     res = lglerepr (lgl, elit);
25155     if (abs (res) <= 1) res = elit;
25156   }
25157   RETURNARG (lglrepr, elit, res);
25158   return res;
25159 }
25160
25161 void lglfreeze (LGL * lgl, int elit) {
25162   Ext * ext;
25163   REQINITNOTFORKED ();
25164   TRAPI ("freeze %d", elit);
25165   lgl->stats->calls.freeze++;
25166   ABORTIF (!elit, "can not freeze zero literal");
25167   REQUIRE (UNUSED|OPTSET|USED|RESET|SATISFIED|UNSATISFIED|FAILED|LOOKED|
25168            UNKNOWN|EXTENDED);
25169   LOG (2, "freezing external literal %d", elit);
25170   (void) lglimport (lgl, elit);
25171   ext = lglelit2ext (lgl, elit);
25172   ABORTIF (ext->melted, "freezing melted literal %d", elit);
25173   assert (!ext->blocking && !ext->eliminated);
25174   ABORTIF (ext->frozen == INT_MAX, "literal %d frozen too often", elit);
25175   ext->frozen++;
25176   if (!ext->frozen) {
25177     lgl->stats->irrprgss++;
25178     lglmelter (lgl);
25179   }
25180   if (lgl->clone) lglfreeze (lgl->clone, elit);
25181 }
25182
25183 int lglfrozen (LGL * lgl, int elit) {
25184   Ext * ext;
25185   int res;
25186   REQINITNOTFORKED ();
25187   TRAPI ("frozen %d", elit);
25188   ABORTIF (!elit, "can not check zero literal for being frozen");
25189   if (abs (elit) > lgl->maxext) res = INT_MAX;
25190   else if (!(ext = lglelit2ext (lgl, elit))->imported) res = INT_MAX;
25191   else res = ext->frozen;
25192   RETURNARG (lglfrozen, elit, res);
25193   return res;
25194 }
25195
25196 int lglusable (LGL * lgl, int elit) {
25197   Ext * ext;
25198   int res;
25199   REQINITNOTFORKED ();
25200   TRAPI ("usable %d", elit);
25201   ABORTIF (!elit, "can not check zero literal for being usable");
25202   if (abs (elit) > lgl->maxext) res = 1;
25203   else if (!(ext = lglelit2ext (lgl, elit))->imported) res = 1;
25204   else res = !ext->melted;
25205   RETURNARG (lglusable, elit, res);
25206   return res;
25207 }
25208
25209 static int lglereusable (LGL * lgl, int elit) {
25210   Ext * ext;
25211   int res;
25212   if (abs (elit) > lgl->maxext) res = 1;
25213   else if (!(ext = lglelit2ext (lgl, elit))->imported) res = 1;
25214   else if (ext->blocking) res = 0;
25215   else if (ext->eliminated) res = 0;
25216   else if (ext->equiv) res = 0;
25217   else if (abs (ext->repr) == 1) res = 0;
25218   else res = 1;
25219   return res;
25220 }
25221
25222 int lglreusable (LGL * lgl, int elit) {
25223   int res;
25224   REQINITNOTFORKED ();
25225   TRAPI ("reusable %d", elit);
25226   ABORTIF (!elit, "can not check zero literal for being reusable");
25227   res = lglereusable (lgl, elit);
25228   RETURNARG (lglreusable, elit, res);
25229   return res;
25230 }
25231
25232 void lglreuse (LGL * lgl, int elit) {
25233   Ext * ext;
25234   REQINITNOTFORKED ();
25235   TRAPI ("reuse %d", elit);
25236   ABORTIF (!elit, "can not reuse zero literal");
25237   ABORTIF (!lglereusable (lgl, elit), "can not reuse non-reusable literal");
25238   if (abs (elit) <= lgl->maxext) {
25239     ext = lglelit2ext (lgl, elit);
25240     if (ext->imported) {
25241       assert (!ext->blocking);
25242       assert (!ext->eliminated);
25243       if (ext->melted) {
25244         LOG (2,
25245           "forced permanently melted external %d to be reused",
25246           elit);
25247         ext->melted = 0;
25248         lglmelter (lgl);
25249       }
25250     }
25251   }
25252   if (lgl->clone) lglreuse (lgl->clone, elit);
25253 }
25254
25255 void lglmeltall (LGL * lgl) {
25256   int idx, melted;
25257   Ext * ext;
25258   REQINITNOTFORKED ();
25259   TRAPI ("meltall");
25260   melted = 0;
25261   for (idx = 1; idx <= lgl->maxext; idx++) {
25262     ext = lglelit2ext (lgl, idx);
25263     ext->melted = 0;
25264     if (!ext->frozen) continue;
25265     lgl->stats->irrprgss++;
25266     ext->frozen = 0;
25267     melted++;
25268   }
25269   lglprt (lgl, 1, "[meltall] melted %d frozen literals", melted);
25270   lglmelter (lgl);
25271   if (lgl->clone) lglmeltall (lgl->clone);
25272 }
25273
25274 void lglmelt (LGL * lgl, int elit) {
25275   Ext * ext;
25276   REQINITNOTFORKED ();
25277   TRAPI ("melt %d", elit);
25278   lgl->stats->calls.melt++;
25279   ABORTIF (!elit, "can not melt zero literal");
25280   REQUIRE (UNUSED|OPTSET|USED|RESET|
25281            SATISFIED|UNSATISFIED|FAILED|UNKNOWN|LOOKED|
25282            EXTENDED);
25283   LOG (2, "melting external literal %d", elit);
25284   (void) lglimport (lgl, elit);
25285   ext = lglelit2ext (lgl, elit);
25286   ABORTIF (!ext->frozen, "can not melt fully unfrozen literal %d", elit);
25287   assert (!ext->blocking && !ext->eliminated);
25288   ext->frozen--;
25289   lglmelter (lgl);      // TODO guard  by !ext->frozen?
25290   if (lgl->clone) lglmelt (lgl->clone, elit);
25291 }
25292
25293 void lglreconstk (LGL * lgl, int ** startptr, int ** toptr) {
25294   REQINITNOTFORKED ();
25295   TRAPI ("reconstk");
25296   lglfitstk (lgl, &lgl->extend);        // 'lglcompact' -> 'lglclone'!!
25297   if (startptr) *startptr = lgl->extend.start;
25298   if (toptr) *toptr = lgl->extend.top;
25299   if (lgl->clone) lglreconstk (lgl->clone, 0, 0);
25300 }
25301
25302 static void lglprstart (LGL * lgl) {
25303   assert (lgl->prefix);
25304   fputs (lgl->prefix, lgl->out);
25305   if (lgl->tid >= 0) fprintf (lgl->out, "%d ", lgl->tid);
25306 }
25307
25308 static void lglprs (LGL * lgl, const char * fmt, ...) {
25309   va_list ap;
25310   lglprstart (lgl);
25311   va_start (ap, fmt);
25312   vfprintf (lgl->out, fmt, ap);
25313   va_end (ap);
25314   fputc ('\n', lgl->out);
25315 }
25316
25317 static void lglprsline (LGL * lgl) {
25318   lglprstart (lgl);
25319   fputc ('\n', lgl->out);
25320 }
25321
25322 static double lglsqr (double a) { return a*a; }
25323
25324 static void lglgluestats (LGL * lgl) {
25325   int64_t added, reduced, forcing, resolved, conflicts;
25326   int64_t wadded, wreduced, wforcing, wresolved, wconflicts;
25327   int64_t avgadded, avgreduced, avgforcing, avgresolved, avgconflicts;
25328   double madded, mreduced, mforcing, mresolved, mconflicts;
25329   double vadded, vreduced, vforcing, vresolved, vconflicts;
25330   double sadded, sreduced, sforcing, sresolved, sconflicts;
25331   Stats * s = lgl->stats;
25332   int glue;
25333   lglprs (lgl,
25334     "scaledglue%7s %3s %9s %3s %9s %3s %9s %3s %9s",
25335     "added","", "reduced","", "forcing","", "resolved","", "conflicts");
25336   added = reduced = forcing = resolved = conflicts = 0;
25337   wadded = wreduced = wforcing = wresolved = wconflicts = 0;
25338   for (glue = 0; glue <= MAXGLUE; glue++) {
25339     added += s->lir[glue].added;
25340     reduced += s->lir[glue].reduced;
25341     forcing += s->lir[glue].forcing;
25342     resolved += s->lir[glue].resolved;
25343     conflicts += s->lir[glue].conflicts;
25344     wadded += glue*s->lir[glue].added;
25345     wreduced += glue*s->lir[glue].reduced;
25346     wforcing += glue*s->lir[glue].forcing;
25347     wresolved += glue*s->lir[glue].resolved;
25348     wconflicts += glue*s->lir[glue].conflicts;
25349   }
25350   avgadded = added ? (((10*wadded)/added+5)/10) : 0;
25351   avgreduced = reduced ? (((10*wreduced)/reduced+5)/10) : 0;
25352   avgforcing = forcing ? (((10*wforcing)/forcing+5)/10) : 0;
25353   avgresolved = resolved ? (((10*wresolved)/resolved+5)/10) : 0;
25354   avgconflicts = conflicts ? (((10*wconflicts)/conflicts+5)/10) : 0;
25355   lglprsline (lgl);
25356   lglprs (lgl,
25357     "all %9lld %3.0f %9lld %3.0f %9lld %3.0f %9lld %3.0f %9lld %3.0f",
25358      (LGLL) added, 100.0,
25359      (LGLL) reduced, 100.0,
25360      (LGLL) forcing, 100.0,
25361      (LGLL) resolved, 100.0,
25362      (LGLL) conflicts, 100.0);
25363   lglprsline (lgl);
25364   for (glue = 0; glue <= MAXGLUE; glue++) {
25365     lglprs (lgl,
25366       "%2d  %9lld %3.0f%c%9lld %3.0f%c%9lld %3.0f%c%9lld %3.0f%c%9lld %3.0f%c",
25367       glue,
25368       (LGLL) s->lir[glue].added,
25369         lglpcnt (s->lir[glue].added, added),
25370         (glue == avgadded) ? '<' : ' ',
25371       (LGLL) s->lir[glue].reduced,
25372         lglpcnt (s->lir[glue].reduced, reduced),
25373         (glue == avgreduced) ? '<' : ' ',
25374       (LGLL) s->lir[glue].forcing,
25375         lglpcnt (s->lir[glue].forcing, forcing),
25376         (glue == avgforcing) ? '<' : ' ',
25377       (LGLL) s->lir[glue].resolved,
25378         lglpcnt (s->lir[glue].resolved, resolved),
25379         (glue == avgresolved) ? '<' : ' ',
25380       (LGLL) s->lir[glue].conflicts,
25381         lglpcnt (s->lir[glue].conflicts, conflicts),
25382         (glue == avgconflicts) ? '<' : ' ');
25383   }
25384   lglprsline (lgl);
25385
25386   madded = lglavg (wadded, added),
25387   mreduced = lglavg (wreduced, reduced),
25388   mforcing = lglavg (wforcing, forcing),
25389   mresolved = lglavg (wresolved, resolved),
25390   mconflicts = lglavg (wconflicts, conflicts);
25391
25392   lglprs (lgl,
25393     "avg  %14.1f%14.1f%14.1f%14.1f%14.1f",
25394      madded, mreduced, mforcing, mresolved, mconflicts);
25395
25396   vadded = vreduced = vforcing = vresolved = vconflicts = 0;
25397   for (glue = 0; glue <= MAXGLUE; glue++) {
25398     vadded += s->lir[glue].added * lglsqr (glue - madded);
25399     vreduced += s->lir[glue].reduced * lglsqr (glue - mreduced);
25400     vforcing += s->lir[glue].forcing * lglsqr (glue - mforcing);
25401     vresolved += s->lir[glue].resolved * lglsqr (glue - mresolved);
25402     vconflicts += s->lir[glue].conflicts * lglsqr (glue - mconflicts);
25403   }
25404   sadded = sqrt (lglavg (vadded, added));
25405   sreduced = sqrt (lglavg (vreduced, reduced));
25406   sforcing = sqrt (lglavg (vforcing, forcing));
25407   sresolved = sqrt (lglavg (vresolved, resolved));
25408   sconflicts = sqrt (lglavg (vconflicts, conflicts));
25409
25410   lglprs (lgl,
25411     "std  %14.1f%14.1f%14.1f%14.1f%14.1f",
25412      sadded, sreduced, sforcing, sresolved, sconflicts);
25413 }
25414
25415 typedef struct TN { double t; const char * n; } TN;
25416
25417 static int lglcmptn (const TN * a, const TN * b) {
25418   if (a->t > b->t) return -1;
25419   if (a->t < b->t) return 1;
25420   return strcmp (a->n, b->n);
25421 }
25422
25423 #define INSTN(NAME,FIELD) \
25424 do { \
25425   TN * tn = tns + ntns++; \
25426   assert (ntns <= sztns); \
25427   tn->t = ts->FIELD; \
25428   tn->n = #NAME; \
25429 } while (0)
25430
25431 static void lglprofsort (LGL * lgl) {
25432   Times * ts = lgl->times;
25433   const int sztns = 31;
25434   int i, ntns = 0;
25435   TN tns[sztns];
25436
25437   INSTN (analysis, ana);
25438   INSTN (backward, bkwd);
25439   INSTN (bca, bca);
25440   INSTN (block, blk);
25441   INSTN (bump, bump);
25442   INSTN (bva, bva);
25443   INSTN (card, card);
25444   INSTN (cce, cce);
25445   INSTN (cgrclsr, cgr);
25446   INSTN (cliff, cliff);
25447   INSTN (cutwidth, ctw);
25448   INSTN (decide, dec);
25449   INSTN (decomp, dcp);
25450   INSTN (defrag, dfg );
25451   INSTN (elim, elm);
25452   INSTN (force, force);
25453   INSTN (gauss, gauss);
25454   INSTN (gc, gc);
25455   INSTN (lift, lft);
25456   INSTN (locs, locs);
25457   INSTN (mega, mega);
25458   INSTN (mincls, mcls);
25459   INSTN (phase, phs);
25460   INSTN (probe, prb.all);
25461   INSTN (rdp, rdp);
25462   INSTN (reduce, red );
25463   INSTN (restart, rsts);
25464   INSTN (tabularasa, tabr);
25465   INSTN (ternres, trn);
25466   INSTN (transred, trd);
25467   INSTN (unhide, unhd);
25468
25469   assert (ntns == sztns);
25470
25471   // Force insertion sort to avoid implicit memory allocation!
25472   // Otherwise an already existing memory corruption will trigger
25473   // another signal and thus might result in non-termination.
25474
25475   ISORT (TN, lglcmptn, tns, ntns);
25476
25477   for (i = 0; i < ntns; i++)
25478     lglprs (lgl, "%8.3f %3.0f%% %s",
25479       tns[i].t, lglpcnt (tns[i].t, ts->all), tns[i].n);
25480 }
25481
25482 static void lglprof (LGL * lgl) {
25483   Times * ts = lgl->times;
25484   double t = ts->all, simp, search;
25485
25486   assert (lgl->opts->verbose.val >= 0);
25487   simp = ts->prep + ts->inpr;
25488   if (!lgl->opts->verbose.val) goto SHORT;
25489
25490   lglprofsort (lgl);
25491
25492   lglprs (lgl, "----------------------------------");
25493   lglprs (lgl, "%8.3f %3.0f%% probe simple    %3.0f%%",
25494     ts->prb.simple,
25495     lglpcnt (ts->prb.simple, t),
25496     lglpcnt (ts->prb.simple, ts->prb.all));
25497   lglprs (lgl, "%8.3f %3.0f%% probe basic     %3.0f%%",
25498     ts->prb.basic,
25499     lglpcnt (ts->prb.basic, t),
25500     lglpcnt (ts->prb.basic, ts->prb.all));
25501   lglprs (lgl, "%8.3f %3.0f%% probe tree-look %3.0f%%",
25502     ts->prb.treelook,
25503     lglpcnt (ts->prb.treelook, t),
25504     lglpcnt (ts->prb.treelook, ts->prb.all));
25505   lglprs (lgl, "==================================");
25506   lglprs (lgl, "%8.3f %3.0f%% preprocessing   %3.0f%%",
25507     ts->prep,
25508     lglpcnt (ts->prep, t),
25509     lglpcnt (ts->prep, simp));
25510   lglprs (lgl, "%8.3f %3.0f%% inprocessing    %3.0f%%",
25511     ts->inpr,
25512     lglpcnt (ts->inpr, t),
25513     lglpcnt (ts->inpr, simp));
25514   lglprs (lgl, "==================================");
25515 SHORT:
25516   lglprs (lgl, "%8.3f %3.0f%% simplifying", simp, lglpcnt (simp, t));
25517   if (lgl->stats->calls.lkhd)
25518     lglprs (lgl, "%8.3f %3.0f%% lookahead", ts->lkhd, lglpcnt (ts->lkhd, t));
25519   search = ts->srch - ts->inpr;
25520   lglprs (lgl, "%8.3f %3.0f%% search", search, lglpcnt (search, t));
25521   lglprs (lgl, "==================================");
25522   lglprs (lgl, "%8.3f %3.0f%% all", t, 100.0);
25523 }
25524
25525 void lglstats (LGL * lgl) {
25526   long long visits, travs, min, p, steps;
25527   int remaining, removed, sum;
25528   Stats * s;
25529   double t;
25530   REQINITNOTFORKED ();
25531   if (lgl->opts->verbose.val < 0) return;
25532   s = lgl->stats;
25533   t = lgl->times->all;
25534   p = s->props.search + s->props.simp + s->props.lkhd;
25535   if (!lgl->opts->verbose.val) goto SHORT;
25536   sum = s->prb.basic.ate.trnr + s->prb.basic.ate.lrg;
25537   lglprs (lgl, 
25538     "bate: %d basic ate = %d trn %.0f%% + %d lrg %.0f%% in %d updates",
25539     sum, s->prb.basic.ate.trnr, lglpcnt (s->prb.basic.ate.trnr, sum),
25540     s->prb.basic.ate.lrg, lglpcnt (s->prb.basic.ate.lrg, sum),
25541     s->prb.basic.ate.count);
25542
25543   lglprs (lgl,
25544     "bcas: %d count, %lld added (%lld skipped), %lld steps",
25545     s->bca.count, (LGLL) s->bca.added, s->bca.skipped, (LGLL) s->bca.steps);
25546
25547   lglprs (lgl,
25548     "bkwd: tried %lld clauses, %lld lits, %.2f lits/clause",
25549     (LGLL) s->bkwd.tried.clauses, (LGLL) s->bkwd.tried.lits,
25550     lglavg (s->bkwd.tried.lits, s->bkwd.tried.clauses));
25551   lglprs (lgl,
25552     "bkwd: checked %lld occs, %.2f occs/clause, %.2f occs/lit",
25553     (LGLL) s->bkwd.tried.occs,
25554     lglavg (s->bkwd.tried.occs, s->bkwd.tried.clauses),
25555     lglavg (s->bkwd.tried.occs, s->bkwd.tried.lits));
25556   lglprs (lgl,
25557     "bkwd: subsumed %d binary, %d ternary, %d large",
25558     s->bkwd.sub2, s->bkwd.sub3, s->bkwd.subl);
25559   lglprs (lgl,
25560     "bkwd: strengthened %d binary, "
25561     "%d ternary (%.0f%% self), %d large (%.0f%% self)",
25562     s->bkwd.str2,
25563     s->bkwd.str3, lglpcnt (s->bkwd.str3self, s->bkwd.str3),
25564     s->bkwd.strl, lglpcnt (s->bkwd.strlself, s->bkwd.strl));
25565
25566   lglprs (lgl,
25567     "blkd: %d bces, %d removed, %lld resolutions, %lld steps",
25568     s->blk.count, s->blk.clauses, (LGLL) s->blk.res, (LGLL) s->blk.steps);
25569   lglprs (lgl,
25570     "blkd: %d blocking literals %.0f%%, %d pure",
25571     s->blk.lits, lglpcnt (s->blk.lits, 2*lgl->maxext), s->blk.pure);
25572
25573   lglprs (lgl,
25574     "bvas: %d bvas, %d added, %d removed",
25575     s->bva.count, s->bva.added, s->bva.removed);
25576
25577   lglprs (lgl,
25578     "card: %d count, %d units, %d am1, %lld steps",
25579     s->card.count, s->card.units, s->card.expam1, (LGLL) s->card.steps);
25580   lglprs (lgl,
25581     "card: %d rescheduled, %lld eliminated, %lld resolved, %lld subsumed",
25582     s->card.resched, (LGLL) s->card.eliminated,
25583     (LGLL) s->card.resolved, (LGLL) s->card.subsumed);
25584   lglprs (lgl,
25585     "card: %d at-most-one constraints found, average size %.2f",
25586     s->card.am1.found.cnt,
25587     lglavg (s->card.am1.found.sum, s->card.am1.found.cnt));
25588   lglprs (lgl,
25589     "card: %d at-most-one constraints used %.0f%%, average size %.2f",
25590     s->card.am1.used.cnt,
25591     lglpcnt (s->card.am1.used.cnt, s->card.am1.found.cnt),
25592     lglavg (s->card.am1.used.sum, s->card.am1.used.cnt));
25593   lglprs (lgl,
25594     "card: %d at-most-two constraints found, average size %.2f",
25595     s->card.am2.found.cnt,
25596     lglavg (s->card.am2.found.sum, s->card.am2.found.cnt));
25597   lglprs (lgl,
25598     "card: %d at-most-two constraints used %.0f%%, average size %.2f",
25599     s->card.am2.used.cnt,
25600     lglpcnt (s->card.am2.used.cnt, s->card.am2.found.cnt),
25601     lglavg (s->card.am2.used.sum, s->card.am2.used.cnt));
25602
25603   lglprs (lgl,
25604     "cces: %d cces, %d eliminated, %d ate %.0f%%, %d abce %.0f%%",
25605     s->cce.count, s->cce.eliminated,
25606     s->cce.ate, lglpcnt (s->cce.ate, s->cce.eliminated),
25607     s->cce.abce, lglpcnt (s->cce.abce, s->cce.eliminated));
25608   lglprs (lgl,
25609     "cces: %lld probed, %d lifted, %d failed",
25610     (LGLL) s->cce.probed, s->cce.lifted, s->cce.failed);
25611   lglprs (lgl,
25612     "cces: %lld cached, %lld rsz, %lld cols %.0f%%, "
25613     "%lld srch, %lld hits %.0f%%",
25614     (LGLL) s->cce.cache.ins,
25615     (LGLL) s->cce.cache.rsz,
25616     (LGLL) s->cce.cache.cols,
25617       lglpcnt (s->cce.cache.cols, s->cce.cache.ins),
25618     (LGLL) s->cce.cache.search,
25619     (LGLL) s->cce.cache.hits,
25620       lglpcnt (s->cce.cache.hits, s->cce.cache.search));
25621
25622   lglprs (lgl,
25623     "cgrs: %d count, %lld esteps, %lld csteps",
25624     s->cgr.count, (LGLL) s->cgr.esteps, (LGLL) s->cgr.csteps);
25625   lglprs (lgl,
25626     "cgrs: %d eqs, %d units", s->cgr.eq, s->cgr.units);
25627   lglprs (lgl,
25628     "cgrs: %d matched (%d ands %.0f%%, %d xors %.0f%%, %d ites %.0f%%)",
25629     s->cgr.matched.all,
25630     s->cgr.matched.and, lglpcnt (s->cgr.matched.and, s->cgr.matched.all),
25631     s->cgr.matched.xor, lglpcnt (s->cgr.matched.xor, s->cgr.matched.all),
25632     s->cgr.matched.ite, lglpcnt (s->cgr.matched.ite, s->cgr.matched.all));
25633   lglprs (lgl,
25634     "cgrs: %d simplified (%d ands %.0f%%, %d xors %.0f%%, %d ites %.0f%%)",
25635     s->cgr.simplified.all,
25636     s->cgr.simplified.and,
25637       lglpcnt (s->cgr.simplified.and, s->cgr.simplified.all),
25638     s->cgr.simplified.xor,
25639      lglpcnt (s->cgr.simplified.xor, s->cgr.simplified.all),
25640     s->cgr.simplified.ite,
25641      lglpcnt (s->cgr.simplified.ite, s->cgr.simplified.all));
25642   lglprs (lgl,
25643     "cgrs: %lld extracted "
25644     "(%lld ands %.0f%%, %lld xors %.0f%%, %lld ites %.0f%%)",
25645     (LGLL)s->cgr.extracted.all,
25646     (LGLL)s->cgr.extracted.and,
25647       lglpcnt (s->cgr.extracted.and, s->cgr.extracted.all),
25648     (LGLL)s->cgr.extracted.xor,
25649       lglpcnt (s->cgr.extracted.xor, s->cgr.extracted.all),
25650     (LGLL)s->cgr.extracted.ite,
25651        lglpcnt (s->cgr.extracted.ite, s->cgr.extracted.all));
25652
25653   lglprs (lgl,
25654     "clff: %d cliffs, %d lifted, %d failed",
25655     s->cliff.count, s->cliff.lifted, s->cliff.failed);
25656   lglprs (lgl,
25657     "clff: %lld decisions, %lld steps",
25658     (LGLL) s->cliff.decisions, (LGLL) s->cliff.steps);
25659
25660   lglprs (lgl,
25661     "clls: %lld sat, %lld simp, %lld freeze, %lld melt",
25662     (LGLL) s->calls.sat, (LGLL) s->calls.simp,
25663     (LGLL) s->calls.freeze, (LGLL) s->calls.melt);
25664   lglprs (lgl,
25665     "clls: %lld add, %lld assume, %lld deref, %lld failed",
25666     (LGLL) s->calls.add, (LGLL) s->calls.assume,
25667     (LGLL) s->calls.deref, (LGLL) s->calls.failed);
25668   lglprs (lgl,
25669     "clls: %lld lkhd, %lld cassume, %lld mosat",
25670     (LGLL) s->calls.lkhd, (LGLL) s->calls.cassume, (LGLL) s->calls.mosat);
25671
25672   lglprs (lgl,
25673     "coll: %d gcs, %d rescored clauses, %d rescored vars",
25674     s->gcs, s->rescored.clauses, s->rescored.vars);
25675
25676   lglprs (lgl,
25677     "dcps: %d decompositions, %d equivalent %.0f%%",
25678           s->decomps, s->equiv.sum, lglpcnt (s->equiv.sum, lgl->maxext));
25679
25680   lglprs (lgl,
25681     "deco: %lld decision-only clauses %.0f%%, %.0f%% reduction",
25682     s->mincls.deco, lglpcnt (s->mincls.deco, s->clauses.learned),
25683     lglpcnt (s->deco.sum.orig - s->deco.sum.red, s->deco.sum.orig)); 
25684
25685   lglprs (lgl,
25686     "decs: %lld decision, %lld random %.3f%%, %lld flipped %.3f%%",
25687     (LGLL) s->decisions,
25688     (LGLL) s->randecs, lglpcnt (s->randecs, s->decisions),
25689     (LGLL) s->randecsflipped, lglpcnt (s->randecsflipped, s->randecs));
25690   lglprs (lgl,
25691     "decs: %lld flipped %.3f%% (in %lld phases)",
25692     (LGLL) s->flipped, lglpcnt (s->flipped, s->decisions),
25693     (LGLL) s->fliphases);
25694
25695   lglprs (lgl,
25696     "elms: %d elims, %d eliminated %.0f%%",
25697      s->elm.count, s->elm.elmd, lglpcnt (s->elm.elmd, lgl->maxext));
25698   lglprs (lgl,
25699     "elms: %d rounds, %.1f rounds/bve",
25700     s->elm.rounds, lglavg (s->elm.rounds, s->elm.count));
25701   lglprs (lgl,
25702     "elms: %d small %.0f%%, %d large %.0f%%",
25703     s->elm.small.elm, lglpcnt (s->elm.small.elm, s->elm.elmd),
25704     s->elm.large, lglpcnt (s->elm.large, s->elm.elmd));
25705   lglprs (lgl,
25706     "elms: %d tried small, %d succeeded %.0f%%, %d failed %.0f%%",
25707     s->elm.small.tried, s->elm.small.tried - s->elm.small.failed,
25708       lglpcnt (s->elm.small.tried - s->elm.small.failed, s->elm.small.tried),
25709     s->elm.small.failed,
25710       lglpcnt (s->elm.small.failed, s->elm.small.tried));
25711   lglprs (lgl,
25712     "elms: %d subsumed, %d strengthened, %d blocked",
25713     s->elm.sub, s->elm.str, s->elm.blkd);
25714   lglprs (lgl,
25715     "elms: %lld copies, %lld resolutions, %lld ipos",
25716     (LGLL) s->elm.copies, (LGLL) s->elm.resolutions, (LGLL) s->elm.ipos);
25717   lglprs (lgl,
25718     "elms: %lld subchks, %lld strchks",
25719     (LGLL) s->elm.subchks, (LGLL) s->elm.strchks);
25720
25721   lglprs (lgl,
25722     "frcs: %lld computed, %d - %d average min-cut range",
25723     (LGLL) s->force.count, s->force.mincut.min, s->force.mincut.max);
25724
25725   lglprs (lgl,
25726     "gaus: %lld extractions, %lld extracted, %.1f size, %d max",
25727     s->gauss.count, s->gauss.extracted,
25728     lglavg (s->gauss.arity.sum, s->gauss.extracted), s->gauss.arity.max);
25729   lglprs (lgl,
25730     "gaus: exported %d units, %d binary and %d ternary equations",
25731     s->gauss.units, s->gauss.equivs, s->gauss.trneqs);
25732   steps = s->gauss.steps.extr + s->gauss.steps.extr;
25733   lglprs (lgl,
25734     "gaus: %d gc, %lld steps, %lld extr %.0f%%, %lld elim %.0f%%",
25735     s->gauss.gcs, (LGLL) steps,
25736     s->gauss.steps.extr, lglpcnt (s->gauss.steps.extr, steps),
25737     s->gauss.steps.elim, lglpcnt (s->gauss.steps.elim, steps));
25738
25739   lglprs (lgl,
25740     "glue: %.1f orig avg, %.1f real avg, %.1f scaled avg",
25741     lglavg (s->clauses.glue, s->clauses.learned),
25742     lglavg (s->clauses.realglue, s->clauses.learned),
25743     lglavg (s->clauses.scglue, s->clauses.learned));
25744   lglprs (lgl,
25745     "glue: %lld maxscaledglue=%d (%.0f%%)",
25746     (LGLL) s->clauses.maxglue, MAXGLUE,
25747     lglpcnt (s->clauses.maxglue, s->clauses.learned));
25748
25749   lglprs (lgl,
25750     "hbrs: %d = %d simple + %d trn %.0f%% + %d lrg %.0f%%, %d sub %.0f%%",
25751     s->hbr.cnt,
25752     s->hbr.simple, lglpcnt (s->hbr.simple, s->hbr.cnt),
25753     s->hbr.trn, lglpcnt (s->hbr.trn, s->hbr.cnt),
25754     s->hbr.lrg, lglpcnt (s->hbr.lrg, s->hbr.cnt),
25755     s->hbr.sub, lglpcnt (s->hbr.sub, s->hbr.cnt));
25756
25757   lglprs (lgl,
25758     "hght: %.0f average, %.2f height/glue",
25759     lglheight (lgl), lglavg (lglheight (lgl), lglglue (lgl)));
25760
25761   lglprs (lgl,
25762     "ints: %lld luby (%lld steps), %lld inout (%lld steps)",
25763     (LGLL) s->luby.count, (LGLL) s->luby.steps,
25764     (LGLL) s->inout.count, (LGLL) s->inout.steps);
25765
25766   sum = s->lift.probed0 + s->lift.probed1;
25767   lglprs (lgl,
25768     "lift: %d phases, %d probed (%lld level1 %.0f%%, %lld level2 %.0f%%)",
25769     s->lift.count, sum,
25770     (LGLL) s->lift.probed0, lglpcnt (s->lift.probed0, sum),
25771     (LGLL) s->lift.probed1, lglpcnt (s->lift.probed1, sum));
25772   lglprs (lgl,
25773     "lift: %d units, %d equivalences, %d implications",
25774     s->lift.units, s->lift.eqs, s->lift.impls);
25775
25776   lglprs (lgl,
25777     "locs: %d count, %lld flips, %lld mems, %d minimun",
25778     s->locs.count, (LGLL) s->locs.flips, (LGLL) s->locs.mems, s->locs.min);
25779
25780   lglprs (lgl,
25781     "lrnd: %lld clauses, %.1f length",
25782     (LGLL) s->clauses.learned,
25783     lglavg (s->lits.learned, s->clauses.learned));
25784   lglprs (lgl,
25785     "lrnd: %lld uips %.0f%%, %lld flips %.0f%%",
25786     (LGLL) s->uips, lglpcnt (s->uips, s->clauses.learned),
25787     (LGLL) s->decflipped, lglpcnt (s->decflipped, s->clauses.learned));
25788
25789   lglprs (lgl,
25790     "mega: %d count, %d failed, %d rounds",
25791     s->mega.count, s->mega.failed, s->mega.rounds);
25792
25793   assert (s->lits.nonmin >= s->lits.learned);
25794   min = s->lits.nonmin - s->lits.learned;
25795   sum = s->moved.bin + s->moved.trn + s->moved.lrg;
25796   lglprs (lgl,
25797     "mins: %lld learned lits, %.0f%% minimized",
25798     (LGLL) s->lits.learned, lglpcnt (min, s->lits.nonmin));
25799
25800   sum = s->mincls.min + s->mincls.bin + s->mincls.size + s->mincls.deco;
25801   lglprs (lgl,
25802     "mins: %lld mins %.0f%%, %lld bin %.0f%%, "
25803     "%lld size %.0f%%, %lld deco %.0f%%",
25804     (LGLL) s->mincls.min, lglpcnt (s->mincls.min, sum),
25805     (LGLL) s->mincls.bin, lglpcnt (s->mincls.bin, sum),
25806     (LGLL) s->mincls.size, lglpcnt (s->mincls.size, sum),
25807     (LGLL) s->mincls.deco, lglpcnt (s->mincls.deco, sum));
25808
25809   lglprs (lgl,
25810     "move: moved %lld, %lld bin %.0f%%, %lld trn %.0f%%, %lld lrg %.0f%%",
25811     sum,
25812     (LGLL) s->moved.bin, lglpcnt (s->moved.bin, sum),
25813     (LGLL) s->moved.trn, lglpcnt (s->moved.trn, sum),
25814     (LGLL) s->moved.lrg, lglpcnt (s->moved.lrg, sum));
25815
25816   sum = s->otfs.str.dyn.red + s->otfs.str.dyn.irr;
25817   lglprs (lgl,
25818     "otfs: str %d dyn (%d red, %d irr) %lld drv %.0f%%, %lld rst %.0f%%",
25819     sum,
25820     s->otfs.str.dyn.red, s->otfs.str.dyn.irr,
25821     (LGLL) s->otfs.driving, lglpcnt (s->otfs.driving, sum),
25822     (LGLL) s->otfs.restarting, lglpcnt (s->otfs.restarting, sum));
25823   lglprs (lgl,
25824     "otfs: sub %d dyn (%d red, %d irr)",
25825     s->otfs.sub.dyn.red + s->otfs.sub.dyn.irr,
25826     s->otfs.sub.dyn.red, s->otfs.sub.dyn.irr);
25827
25828   lglprs (lgl,
25829     "phas: %lld computed, %lld set, %lld pos (%.0f%%), %lld neg (%.0f%%)",
25830     (LGLL) s->phase.count, (LGLL) s->phase.set,
25831     (LGLL) s->phase.pos, lglpcnt (s->phase.pos, s->phase.set),
25832     (LGLL) s->phase.neg, lglpcnt (s->phase.neg, s->phase.set));
25833
25834   lglprs (lgl,
25835     "prbs: %d basic, %lld probed, %d failed, %d lifted",
25836     s->prb.basic.count, (LGLL) s->prb.basic.probed,
25837     s->prb.basic.failed, s->prb.basic.lifted);
25838   lglprs (lgl,
25839     "prbs: %d simple, %lld probed, %d failed, %d eqs",
25840     s->prb.simple.count, (LGLL) s->prb.simple.probed,
25841     s->prb.simple.failed, s->prb.simple.eqs);
25842   lglprs (lgl,
25843     "prbs: %d treelook, %lld probed, %d failed, %d lifted",
25844     s->prb.treelook.count, (LGLL) s->prb.treelook.probed,
25845     s->prb.treelook.failed, s->prb.treelook.lifted);
25846
25847   lglprs (lgl,
25848     "prps: %lld props, %.0f props/dec",
25849     (LGLL) p, lglavg (s->props.search, s->decisions));
25850   lglprs (lgl,
25851     "prps: %.0f%% srch, %.0f%% simp, %.0f%% lkhd",
25852     lglpcnt (s->props.search, p), lglpcnt (s->props.simp, p),
25853     lglpcnt (s->props.lkhd, p));
25854
25855   lglprs (lgl,
25856     "psns: %lld searches, %lld hits, %.0f%% hit rate",
25857     (LGLL) s->poison.search, (LGLL) s->poison.hits,
25858     lglpcnt (s->poison.hits, s->poison.search));
25859
25860   lglprs (lgl,
25861     "rdps: %d count, %d units, %d bin, %d trn, %lld steps",
25862     s->rdp.count, s->rdp.units, s->rdp.bin, s->rdp.trn, (LGLL) s->rdp.steps);
25863   lglprs (lgl,
25864     "rdps: %lld partial eliminations, %lld bounded %.0f%%",
25865     (LGLL) s->rdp.elim, (LGLL) s->rdp.limhit.bound, 
25866     lglpcnt (s->rdp.limhit.bound, s->rdp.elim));
25867   lglprs (lgl,
25868     "rdps: %lld resolutions, %lld size %.0f%%, %lld model %.0f%%",
25869     (LGLL) s->rdp.res,
25870     (LGLL) s->rdp.limhit.len, lglpcnt (s->rdp.limhit.len, s->rdp.res),
25871     (LGLL) s->rdp.limhit.model, lglpcnt (s->rdp.limhit.model, s->rdp.res));
25872
25873   lglprs (lgl,
25874     "reds: %d count, %d reset, %d acts %.0f%%",
25875     s->reduced.count, s->reduced.reset,
25876     s->acts, lglpcnt (s->acts, s->reduced.count));
25877   lglprs (lgl,
25878     "reds: %d geom %.0f%%, %d glue useless %.0f%%",
25879     s->reduced.geom, lglpcnt (s->reduced.geom, s->reduced.count),
25880     s->reduced.gul, lglpcnt (s->reduced.gul, s->reduced.count));
25881   lglprs (lgl,
25882     "reds: %d memlim %.0f%%, %d arith %.0f%%, %d double %.0f%%",
25883     s->reduced.memlim, lglpcnt (s->reduced.memlim, s->reduced.count),
25884     s->reduced.arith, lglpcnt (s->reduced.arith, s->reduced.count),
25885     s->reduced.arith2, lglpcnt (s->reduced.arith2, s->reduced.arith));
25886
25887   lglprs (lgl,
25888     "rmbd: %d removed, %d red %.0f%%",
25889     s->bindup.removed, s->bindup.red,
25890     lglpcnt (s->bindup.red, s->bindup.removed));
25891
25892   lglprs (lgl,
25893     "rphs: %d recomputed phases",
25894     s->rephase.count);
25895
25896   sum = s->restarts.count + s->restarts.skipped.count;
25897   lglprs (lgl,
25898     "rsts: %d restarts %.0f%%, %d skipped %.0f%%",
25899     s->restarts.count, lglpcnt (s->restarts.count, sum),
25900     s->restarts.skipped.count, lglpcnt (s->restarts.skipped.count, sum));
25901   lglprs (lgl,
25902     "rsts: %d saturating %.0f%%, %d agile %.0f%%, %d reuse %.0f%%",
25903     s->restarts.skipped.saturating,
25904       lglpcnt (s->restarts.skipped.saturating, s->restarts.skipped.count),
25905     s->restarts.skipped.agile,
25906       lglpcnt (s->restarts.skipped.agile, s->restarts.skipped.count),
25907     s->restarts.skipped.reuse,
25908       lglpcnt (s->restarts.skipped.reuse, s->restarts.skipped.count));
25909   lglprs (lgl,
25910     "rsts: %.1f avg interval, %.1f scaled, %.1f factor",
25911     lglavg (s->restarts.intsum.orig, s->restarts.count),
25912     lglavg (s->restarts.intsum.scaled, s->restarts.count),
25913     lglavg (s->restarts.intsum.orig, s->restarts.intsum.scaled));
25914   lglprs (lgl,
25915     "rsts: %d kept %.1f%% average %.1f%%",
25916     s->restarts.kept.count,
25917     lglpcnt (s->restarts.kept.count, s->restarts.count),
25918     lglavg (s->restarts.kept.sum, s->restarts.kept.count));
25919
25920   lglprs (lgl,
25921     "simp: %d count (%d confs %0.f%%, %d irr %.0f%%, %d vars %.0f%%)",
25922     s->simp.count,
25923     s->simp.limhit.confs, lglpcnt (s->simp.limhit.confs, s->simp.count),
25924     s->simp.limhit.irr, lglpcnt (s->simp.limhit.irr, s->simp.count),
25925     s->simp.limhit.vars, lglpcnt (s->simp.limhit.vars, s->simp.count));
25926
25927   lglprs (lgl,
25928     "subl: %lld count (%lld tried %.1f), %lld sub out of %lld (%.1f%%)",
25929     s->subl.count, s->subl.tried, lglavg (s->subl.tried, s->subl.count),
25930     s->subl.sub, s->subl.cands, lglpcnt (s->subl.sub, s->subl.cands));
25931
25932   lglprs (lgl,
25933     "sync: %lld produced units, %lld successful consumptions %.0f%%",
25934     s->sync.units.produced, s->sync.units.consumed.actual,
25935     lglpcnt (s->sync.units.consumed.actual, s->sync.units.produced));
25936   lglprs (lgl,
25937     "sync: %lld consume units calls, %lld tried %.0f%%, %lld success %.0f%%",
25938     s->sync.units.consumed.calls,
25939     s->sync.units.consumed.tried,
25940     lglpcnt (s->sync.units.consumed.tried, s->sync.units.consumed.calls),
25941     s->sync.units.consumed.actual,
25942     lglpcnt (s->sync.units.consumed.actual, s->sync.units.consumed.calls));
25943   lglprs (lgl,
25944     "sync: %lld produced clauses, %lld successful consumptions %.0f%%",
25945     s->sync.cls.produced, s->sync.cls.consumed.actual,
25946     lglpcnt (s->sync.cls.consumed.actual, s->sync.cls.produced));
25947   lglprs (lgl,
25948     "sync: %lld consume clause calls, %lld tried %.0f%%, %lld success %.0f%%",
25949     s->sync.cls.consumed.calls,
25950     s->sync.cls.consumed.tried,
25951     lglpcnt (s->sync.cls.consumed.tried, s->sync.cls.consumed.calls),
25952     s->sync.cls.consumed.actual,
25953     lglpcnt (s->sync.cls.consumed.actual, s->sync.cls.consumed.calls));
25954
25955   lglprs (lgl, "tabr: %d count", s->tabr.count);
25956
25957   lglprs (lgl,
25958     "tops: %d fixed %.0f%%, %d its, %.2f confs/it",
25959     s->fixed.sum, lglpcnt (s->fixed.sum, lgl->maxext), 
25960     s->iterations, lglavg (s->confs, s->iterations));
25961
25962   travs = s->travs.search + s->visits.simp + s->visits.lkhd;
25963   lglprs (lgl,
25964     "trvs: %lld traversals, %.0f%% srch, %.0f%% simp, %.0f%% lkhd",
25965     (LGLL) travs, lglpcnt (s->travs.search, travs),
25966     lglpcnt (s->travs.simp, travs), lglpcnt (s->travs.lkhd, travs));
25967   lglprs (lgl,
25968     "trvs: %.1f search traversals per propagation, %.1f per conflict",
25969     lglavg (s->travs.search, s->props.search),
25970     lglavg (s->travs.search, s->confs));
25971   lglprs (lgl,
25972     "trvs: %.1f search traversals per search visit",
25973     lglavg (s->travs.search, s->visits.search));
25974
25975   lglprs (lgl,
25976     "trds: %d transitive reductions, %d removed, %d failed",
25977     s->trd.count, s->trd.red, s->trd.failed);
25978   lglprs (lgl,
25979     "trds: %lld nodes, %lld edges, %lld steps",
25980     (LGLL) s->trd.lits, (LGLL) s->trd.bins, (LGLL) s->trd.steps);
25981
25982   lglprs (lgl, "trim: %lld words, %.1f MB",
25983     (LGLL) s->trims, (s->trims * sizeof (int)) / (double)(1<<20));
25984
25985   lglprs (lgl,
25986     "trnr: %d count, %d bin, %d trn, %lld steps",
25987     s->trnr.count, s->trnr.bin, s->trnr.trn, (LGLL) s->trnr.steps);
25988
25989   lglprs (lgl,
25990     "unhd: %d count, %d rounds, %lld steps",
25991     s->unhd.count, s->unhd.rounds, (LGLL) s->unhd.steps);
25992   lglprs (lgl,
25993     "unhd: %d non-trivial sccs of average size %.1f",
25994     s->unhd.stamp.sccs,
25995     lglavg (s->unhd.stamp.sumsccsizes, s->unhd.stamp.sccs));
25996   sum = lglunhdunits (lgl);
25997   lglprs (lgl,
25998     "unhd: %d units, %d bin, %d trn, %d lrg",
25999     sum, s->unhd.units.bin, s->unhd.units.trn, s->unhd.units.lrg);
26000   sum = lglunhdfailed (lgl);
26001   lglprs (lgl,
26002     "unhd: %d failed, %d stamp, %d lits, %d bin, %d trn, %d lrg",
26003     sum, s->unhd.stamp.failed, s->unhd.failed.lits,
26004     s->unhd.failed.bin, s->unhd.failed.trn, s->unhd.units.lrg);
26005   sum = lglunhdtauts (lgl);
26006   lglprs (lgl,
26007     "unhd: %d tauts, %d bin %.0f%%, %d trn %.0f%%, %d lrg %.0f%%",
26008     sum,
26009     s->unhd.tauts.bin, lglpcnt (s->unhd.tauts.bin, sum),
26010     s->unhd.tauts.trn, lglpcnt (s->unhd.tauts.trn, sum),
26011     s->unhd.tauts.lrg, lglpcnt (s->unhd.tauts.lrg, sum));
26012   lglprs (lgl,
26013     "unhd: %d tauts, %d stamp %.0f%%, %d red %.0f%%",
26014     sum,
26015     s->unhd.stamp.trds, lglpcnt (s->unhd.stamp.trds, sum),
26016     s->unhd.tauts.red, lglpcnt (s->unhd.tauts.red, sum));
26017   sum = lglunhdhbrs (lgl);
26018   lglprs (lgl,
26019     "unhd: %d hbrs, %d trn %.0f%%, %d lrg %.0f%%, %d red %.0f%%",
26020     sum,
26021     s->unhd.hbrs.trn, lglpcnt (s->unhd.hbrs.trn, sum),
26022     s->unhd.hbrs.lrg, lglpcnt (s->unhd.hbrs.lrg, sum),
26023     s->unhd.hbrs.red, lglpcnt (s->unhd.hbrs.red, sum));
26024   sum = lglunhdstrd (lgl);
26025   lglprs (lgl,
26026     "unhd: %d str, %d bin %.0f%%, %d trn %.0f%%, %d lrg %.0f%%, %d red %.0f%%",
26027     sum,
26028     s->unhd.units.bin, lglpcnt (s->unhd.units.bin, sum),
26029     s->unhd.str.trn, lglpcnt (s->unhd.str.trn, sum),
26030     s->unhd.str.lrg, lglpcnt (s->unhd.str.lrg, sum),
26031     s->unhd.str.red, lglpcnt (s->unhd.str.red, sum));
26032
26033   removed = s->fixed.sum + s->elm.elmd + s->equiv.sum;
26034   remaining = lgl->maxext - removed;
26035   assert (remaining >= 0);
26036   lglprs (lgl,
26037     "vars: %d remaining %.0f%% and %d removed %.0f%% out of %d",
26038     remaining, lglpcnt (remaining, lgl->maxext),
26039     removed, lglpcnt (removed, lgl->maxext), lgl->maxext);
26040   lglprs (lgl,
26041     "vars: %d fixed %.0f%%, %d eliminated %.0f%%, %d equivalent %.0f%%",
26042     s->fixed.sum, lglpcnt (s->fixed.sum, lgl->maxext),
26043     s->elm.elmd, lglpcnt (s->elm.elmd, lgl->maxext),
26044     s->equiv.sum, lglpcnt (s->equiv.sum, lgl->maxext));
26045
26046   visits = s->visits.search + s->visits.simp + s->visits.lkhd;
26047   lglprs (lgl,
26048     "vsts: %lld visits, %.0f%% srch, %.0f%% simp, %.0f%% lkhd",
26049     (LGLL) visits, lglpcnt (s->visits.search, visits),
26050     lglpcnt (s->visits.simp, visits), lglpcnt (s->visits.lkhd, visits));
26051   lglprs (lgl,
26052     "vsts: %.1f search visits per propagation, %.1f per conflict",
26053     lglavg (s->visits.search, s->props.search),
26054     lglavg (s->visits.search, s->confs));
26055
26056   lglprs (lgl,
26057     "wchs: %lld pushed, %lld enlarged, %d defrags",
26058     (LGLL) s->pshwchs, (LGLL) s->enlwchs, s->defrags);
26059
26060   lglprsline (lgl);
26061   lglgluestats (lgl);
26062   lglprsline (lgl);
26063 SHORT:
26064   lglprof (lgl);
26065   lglprsline (lgl);
26066   lglprs (lgl,
26067     "%lld decisions, %.1f decisions/sec",
26068     (LGLL) s->decisions, lglavg (s->decisions, t));
26069   lglprs (lgl,
26070     "%lld conflicts, %.1f conflicts/sec",
26071     (LGLL) s->confs, lglavg (s->confs, t));
26072   lglprs (lgl,
26073     "%lld propagations, %.1f megaprops/sec",
26074     (LGLL) p, lglavg (p/1e6, t));
26075   lglprs (lgl, "%.1f seconds, %.1f MB", t, lglmaxmb (lgl));
26076   fflush (lgl->out);
26077 }
26078
26079 int64_t lglgetprops (LGL * lgl) {
26080   REQINITNOTFORKED ();
26081   return lgl->stats->props.search + lgl->stats->props.simp;
26082 }
26083
26084 int64_t lglgetconfs (LGL * lgl) {
26085   REQINITNOTFORKED ();
26086   return lgl->stats->confs;
26087 }
26088
26089 int64_t lglgetdecs (LGL * lgl) {
26090   REQINITNOTFORKED ();
26091   return lgl->stats->decisions;
26092 }
26093
26094 void lglsizes (LGL * lgl) {
26095   lglprt (lgl, 0, "sizeof (int) == %ld", (long) sizeof (int));
26096   lglprt (lgl, 0, "sizeof (unsigned) == %ld", (long) sizeof (unsigned));
26097   lglprt (lgl, 0, "sizeof (void*) == %ld", (long) sizeof (void*));
26098   lglprt (lgl, 0, "sizeof (Stk) == %ld", (long) sizeof (Stk));
26099   lglprt (lgl, 0, "sizeof (Fun) == %ld", (long) sizeof (Fun));
26100   lglprt (lgl, 0, "sizeof (AVar) == %ld", (long) sizeof (AVar));
26101   lglprt (lgl, 0, "sizeof (DVar) == %ld", (long) sizeof (DVar));
26102   lglprt (lgl, 0, "sizeof (EVar) == %ld", (long) sizeof (EVar));
26103   lglprt (lgl, 0, "sizeof (Gat) == %ld", (long) sizeof (Gat));
26104   lglprt (lgl, 0, "sizeof (Stats.lir) == %ld", (long) sizeof ((Stats*)0)->lir);
26105   lglprt (lgl, 0, "sizeof (Stats) == %ld", (long) sizeof (Stats));
26106   lglprt (lgl, 0, "sizeof (LGL) == %ld", (long) sizeof (LGL));
26107   lglprt (lgl, 0, "MAXVAR == %ld", (long) MAXVAR);
26108   lglprt (lgl, 0, "MAXREDLIDX == %ld", (long) MAXREDLIDX);
26109   lglprt (lgl, 0, "MAXIRRLIDX == %ld", (long) MAXIRRLIDX);
26110 }
26111
26112 #define LGLRELSTK(MGR,STKPTR) \
26113 do { \
26114   assert (lglmtstk (STKPTR)); \
26115   lglrelstk ((MGR), (STKPTR)); \
26116 } while (0)
26117
26118 void lglrelease (LGL * lgl) {
26119   lgldealloc dealloc;
26120   int i;
26121
26122   REQINIT ();
26123   if (lgl->clone) lglrelease (lgl->clone), lgl->clone = 0;
26124   TRAPI ("release");
26125
26126 #ifndef NLGLDRUPLIG
26127   if (lgl->druplig) druplig_reset (lgl->druplig), lgl->druplig = 0;
26128 #endif
26129
26130   // Heap state starts here:
26131
26132   DEL (lgl->avars, lgl->szvars);
26133   DEL (lgl->doms, 2*lgl->szvars);
26134   DEL (lgl->drail, lgl->szdrail);
26135   DEL (lgl->dvars, lgl->szvars);
26136   DEL (lgl->ext, lgl->szext);
26137   DEL (lgl->i2e, lgl->szvars);
26138   DEL (lgl->jwh, 2*lgl->szvars);
26139   DEL (lgl->qvars, lgl->szvars);
26140   DEL (lgl->vals, lgl->szvars);
26141
26142   lglrelctk (lgl, &lgl->control);
26143
26144   lglrelstk (lgl, &lgl->assume);
26145   lglrelstk (lgl, &lgl->cassume);
26146   lglrelstk (lgl, &lgl->clause);
26147   lglrelstk (lgl, &lgl->dsched);
26148   lglrelstk (lgl, &lgl->eassume);
26149   lglrelstk (lgl, &lgl->eclause);
26150   lglrelstk (lgl, &lgl->extend);
26151   lglrelstk (lgl, &lgl->fassume);
26152   lglrelstk (lgl, &lgl->learned);
26153   lglrelstk (lgl, &lgl->frames);
26154   lglrelstk (lgl, &lgl->trail);
26155   lglrelstk (lgl, &lgl->wchs->stk);
26156
26157 #ifndef NCHKSOL
26158   lglrelstk (lgl, &lgl->orig);
26159 #endif
26160
26161   lglrelstk (lgl, &lgl->irr);
26162   for (i = 0; i <= MAXGLUE; i++) lglrelstk (lgl, &lgl->red[i]);
26163
26164   // The following heap allocated memory has no state:
26165
26166   LGLRELSTK (lgl, &lgl->lcaseen);
26167   LGLRELSTK (lgl, &lgl->minstk);
26168   LGLRELSTK (lgl, &lgl->poisoned);
26169   LGLRELSTK (lgl, &lgl->seen);
26170
26171   DEL (lgl->limits, 1);
26172   DEL (lgl->times, 1);
26173   DEL (lgl->timers, 1);
26174   DEL (lgl->red, MAXGLUE+1);
26175   DEL (lgl->wchs, 1);
26176
26177   if (lgl->fltstr) DEL (lgl->fltstr, 1);
26178   if (lgl->cbs) DEL (lgl->cbs, 1);              // next to last
26179   lgldelstr (lgl, lgl->prefix);                 // last
26180
26181   // adjust upfront the mem counters ...
26182
26183   lgldec (lgl, sizeof *lgl->stats);
26184   lgldec (lgl, sizeof *lgl->opts);
26185   lgldec (lgl, sizeof *lgl->mem);
26186   lgldec (lgl, sizeof *lgl);
26187
26188   assert (getenv ("LGLEAK") || !lgl->stats->bytes.current);
26189
26190   if (lgl->closeapitrace == 1) fclose (lgl->apitrace);
26191   if (lgl->closeapitrace == 2) pclose (lgl->apitrace);
26192
26193 #ifndef NDEBUG
26194 #ifndef NLGLPICOSAT
26195   if (lgl->picosat.solver) {
26196     if (lgl->opts->verbose.val > 0 && lgl->opts->check.val > 0)
26197       picosat_stats (PICOSAT);
26198     picosat_reset (PICOSAT);
26199     lgl->picosat.solver = 0;
26200   }
26201 #endif
26202 #endif
26203
26204   if ((dealloc = lgl->mem->dealloc)) {
26205      void * memstate = lgl->mem->state;
26206      if (lgl->stats) dealloc (memstate, lgl->stats, sizeof *lgl->stats);
26207      if (lgl->times) dealloc (memstate, lgl->times, sizeof *lgl->times);
26208      if (lgl->opts) dealloc (memstate, lgl->opts, sizeof *lgl->opts);
26209      assert (lgl->mem);
26210      dealloc (memstate, lgl->mem, sizeof *lgl->mem);
26211      dealloc (memstate, lgl, sizeof *lgl);
26212   } else {
26213     free (lgl->stats);
26214     free (lgl->times);
26215     free (lgl->opts);
26216     free (lgl->mem);
26217     free (lgl);
26218   }
26219 }
26220
26221 void lglutrav (LGL * lgl, void * state, void (*trav)(void *, int)) {
26222   int elit, val;
26223   REQINITNOTFORKED ();
26224   if (!lgl->mt && !lglbcp (lgl)) lgl->mt = 1;
26225   if (!lgl->mt) lglgc (lgl);
26226   if (lgl->mt) return;
26227   if (lgl->level > 0) lglbacktrack (lgl, 0);
26228   for (elit = 1; elit <= lgl->maxext; elit++) {
26229     if (!(val = lglefixed (lgl, elit))) continue;
26230     trav (state, (val < 0) ? -elit : elit);
26231   }
26232 }
26233
26234 void lgletrav (LGL * lgl, void * state, void (*trav)(void *, int, int)) {
26235   int elit, erepr;
26236   REQINITNOTFORKED ();
26237   if (!lgl->mt && !lglbcp (lgl)) lgl->mt = 1;
26238   if (!lgl->mt) lglgc (lgl);
26239   if (lgl->mt) return;
26240   if (lgl->level > 0) lglbacktrack (lgl, 0);
26241   for (elit = 1; elit <= lgl->maxext; elit++) {
26242     if (lglefixed (lgl, elit)) continue;
26243     erepr = lglerepr (lgl, elit);
26244     if (erepr == elit) continue;
26245     trav (state, elit, erepr);
26246   }
26247 }
26248
26249 static void lglictrav (LGL * lgl, int internal,
26250                        void * state, void (*trav)(void *, int)) {
26251   int idx, sign, lit, blit, tag, red, other, other2;
26252   const int * p, * w, * eow, * c;
26253   HTS * hts;
26254   REQINITNOTFORKED ();
26255   if (lgl->level > 0) lglbacktrack (lgl, 0);
26256   if (!lgl->mt && !lglbcp (lgl)) lgl->mt = 1;
26257   if (!lgl->mt) lglgc (lgl);
26258   if (lgl->mt) { trav (state, 0); return; }
26259   for (idx = 2; idx < lgl->nvars; idx++)
26260     for (sign = -1; sign <= 1; sign += 2) {
26261       lit = sign * idx;
26262       assert (!lglval (lgl, lit));
26263       hts = lglhts (lgl, lit);
26264       w = lglhts2wchs (lgl, hts);
26265       eow = w + hts->count;
26266       for (p = w; p < eow; p++) {
26267         blit = *p;
26268         tag = blit & MASKCS;
26269         red = blit & REDCS;
26270         if (tag == TRNCS || tag == LRGCS) p++;
26271         if (red) continue;
26272         if (tag != BINCS && tag != TRNCS) continue;
26273         other = blit >> RMSHFT;
26274         if (abs (other) < idx) continue;
26275         assert (!lglval (lgl, other));
26276         if (tag == TRNCS) {
26277           other2 = *p;
26278           if (abs (other2) < idx) continue;
26279           assert (!lglval (lgl, other2));
26280         } else other2 = 0;
26281         trav (state, internal ? lit : lglexport (lgl, lit));
26282         trav (state, internal ? other : lglexport (lgl, other));
26283         if (other2) trav (state, internal ? other2 : lglexport (lgl, other2));
26284         trav (state, 0);
26285       }
26286     }
26287   for (c = lgl->irr.start; c < lgl->irr.top; c = p + 1) {
26288     p = c;
26289     if (*p >= NOTALIT) continue;
26290     while ((other = *p)) {
26291       assert (!lglval (lgl, other));
26292       trav (state, internal ? other : lglexport (lgl, other));
26293       p++;
26294     }
26295     trav (state, 0);
26296   }
26297 }
26298
26299 void lglctrav (LGL * lgl, void * state, void (*trav)(void *, int)) {
26300   lglictrav (lgl, 0, state, trav);
26301 }
26302
26303 static void lgltravcounter (void * voidptr, int lit) {
26304   int * cntptr = voidptr;
26305   if (!lit) *cntptr += 1;
26306 }
26307
26308 static void lgltravprinter (void * voidptr, int lit) {
26309   FILE * out = voidptr;
26310   if (lit) fprintf (out, "%d ", lit);
26311   else fprintf (out, "0\n");
26312 }
26313
26314 void lglprint (LGL * lgl, FILE * file) {
26315   int count = 0;
26316   lglctrav (lgl, &count, lgltravcounter);
26317   fprintf (file, "p cnf %d %d\n", lglmaxvar (lgl), count);
26318   lglctrav (lgl, file, lgltravprinter);
26319 }
26320
26321 void lglprintall (LGL * lgl, FILE * file) {
26322   int count = 0;
26323   lgltravall (lgl, &count, lgltravcounter);
26324   fprintf (file, "p cnf %d %d\n", lglmaxvar (lgl), count);
26325   lgltravall (lgl, file, lgltravprinter);
26326 }
26327
26328 void lglrtrav (LGL * lgl, void * state, void (*trav)(void *, int, int)) {
26329   int idx, sign, lit, blit, tag, red, other, other2, glue;
26330   const int * p, * c, * w, * eow;
26331   Stk * lir;
26332   HTS * hts;
26333   REQINITNOTFORKED ();
26334   if (lgl->mt) return;
26335   lglgc (lgl);
26336   if (lgl->level > 0) lglbacktrack (lgl, 0);
26337   for (idx = 2; idx < lgl->nvars; idx++) {
26338     if (lglval (lgl, idx)) continue;
26339     for (sign = -1; sign <= 1; sign += 2) {
26340       lit = sign * idx;
26341       hts = lglhts (lgl, lit);
26342       w = lglhts2wchs (lgl, hts);
26343       eow = w + hts->count;
26344       for (p = w; p < eow; p++) {
26345         blit = *p;
26346         tag = blit & MASKCS;
26347         red = blit & REDCS;
26348         if (tag == TRNCS || tag == LRGCS) p++;
26349         if (!red) continue;
26350         if (tag != BINCS && tag != TRNCS) continue;
26351         other = blit >> RMSHFT;
26352         if (abs (other) < idx) continue;
26353         assert (!lglval (lgl, other));
26354         if (tag == TRNCS) {
26355           other2 = *p;
26356           if (abs (other2) < idx) continue;
26357           assert (!lglval (lgl, other2));
26358         } else other2 = 0;
26359         trav (state, lglexport (lgl, lit), 0);
26360         trav (state, lglexport (lgl, other), 0);
26361         if (other2) trav (state, lglexport (lgl, other2), 0);
26362         trav (state, 0, 0);
26363       }
26364     }
26365   }
26366   for (glue = 0; glue < MAXGLUE; glue++) {
26367     lir = lgl->red + glue;
26368     for (c = lir->start; c < lir->top; c = p + 1) {
26369       p = c;
26370       if (*p >= NOTALIT) continue;
26371       while ((other = *p)) {
26372         assert (!lglval (lgl, other));
26373         trav (state, lglexport (lgl, other), 0);
26374         p++;
26375       }
26376       trav (state, 0, 0);
26377     }
26378   }
26379 }
26380
26381 static void lgltravallu (void * voidptr, int unit) {
26382   Trv * state = voidptr;
26383   state->trav (state->state, unit);
26384   state->trav (state->state, 0);
26385 }
26386
26387 static void lgltravalle (void * voidptr, int lit, int repr) {
26388   Trv * state = voidptr;
26389   state->trav (state->state, -lit);
26390   state->trav (state->state, repr);
26391   state->trav (state->state, 0);
26392   state->trav (state->state, lit);
26393   state->trav (state->state, -repr);
26394   state->trav (state->state, 0);
26395 }
26396
26397 void lgltravall (LGL * lgl, void * state, void (*trav)(void *, int)) {
26398   Trv travstate;
26399   travstate.state = state;
26400   travstate.trav = trav;
26401   lglutrav (lgl, &travstate, lgltravallu);
26402   lgletrav (lgl, &travstate, lgltravalle);
26403   lglctrav (lgl, state, trav);
26404 }
26405
26406 #ifndef NDEBUG
26407
26408 void lgldump (LGL * lgl) {
26409   int idx, sign, lit, blit, tag, red, other, other2, glue;
26410   const int * p, * w, * eow, * c, * top;
26411   Stk * lir;
26412   HTS * hts;
26413   for (idx = 2; idx < lgl->nvars; idx++)
26414     for (sign = -1; sign <= 1; sign += 2) {
26415       lit = sign * idx;
26416       hts = lglhts (lgl, lit);
26417       w = lglhts2wchs (lgl, hts);
26418       eow = w + hts->count;
26419       for (p = w; p < eow; p++) {
26420         blit = *p;
26421         tag = blit & MASKCS;
26422         red = blit & REDCS;
26423         if (tag == TRNCS || tag == LRGCS) p++;
26424         if (tag == BINCS) {
26425           other = blit >> RMSHFT;
26426           if (abs (other) < idx) continue;
26427           other2 = 0;
26428         } else if (tag == TRNCS) {
26429           other = blit >> RMSHFT;
26430           if (abs (other) < idx) continue;
26431           other2 = *p;
26432           if (abs (other2) < idx) continue;
26433         } else continue;
26434         fprintf (lgl->out, "%s %d %d", red ? "red" : "irr", lit, other);
26435         if (tag == TRNCS) fprintf (lgl->out, " %d", other2);
26436         fprintf (lgl->out, "\n");
26437       }
26438     }
26439   top = lgl->irr.top;
26440   for (c = lgl->irr.start; c < top; c = p + 1) {
26441     p = c;
26442     if (*p >= NOTALIT) continue;
26443     fprintf (lgl->out, "irr");
26444     while (*p) fprintf (lgl->out, " %d", *p++);
26445     fprintf (lgl->out, "\n");
26446   }
26447   for (glue = 0; glue < MAXGLUE; glue++) {
26448     lir = lgl->red + glue;
26449     top = lir->top;
26450     for (c = lir->start; c < top; c = p + 1) {
26451       p = c;
26452       if (*p >= NOTALIT) continue;
26453       fprintf (lgl->out, "glue%d", glue);
26454       while (*p) fprintf (lgl->out, " %d", *p++);
26455       fprintf (lgl->out, "\n");
26456     }
26457   }
26458 }
26459
26460 #endif
26461
26462 static void lglforkadd (void * ptr, int lit) {
26463   lgladd (ptr, lit ? lglforklit (lit) : 0);
26464 }
26465
26466 LGL * lglfork (LGL * parent) {
26467   LGL * child;
26468   {
26469     LGL * lgl = parent;
26470     REQINIT ();
26471     ABORTIF (!lglmtstk (&parent->eassume), "can not fork under assumptions");
26472     ABORTIF (parent->forked == INT_MAX, "parent forked too often");
26473   }
26474   if (parent->level > 0) lglbacktrack (parent, 0);
26475   (void) lglbcp (parent);
26476   lglgc (parent);
26477   child = lglminit (parent->mem->state,
26478                     parent->mem->alloc,
26479                     parent->mem->realloc,
26480                     parent->mem->dealloc);
26481   child->parent = parent;
26482   memcpy (child->opts, parent->opts, sizeof *parent->opts);
26483   lglcopyclonenfork (child, parent);
26484   lglictrav (parent, 1, child, lglforkadd);
26485   assert (parent->stats->irr.clauses.cur == child->stats->irr.clauses.cur);
26486   parent->forked++;
26487   assert (parent->forked > 0);
26488   lglprt (parent, 1, "forked-%d", parent->forked);
26489   return child;
26490 }
26491
26492 static void lglflass (LGL * lgl, LGL * from) {
26493   int idx, copied = 0;
26494   assert (!lgl->level), assert (!lgl->mt);
26495   assert ((from->state & (SATISFIED | EXTENDED)));
26496   if (lgl->nvars) assert (lgl->nvars == from->maxext + 2);
26497   else assert (!from->maxext);
26498   lglreset (lgl);
26499   for (idx = 2; idx < lgl->nvars; idx++) {
26500     int val = lglderef (from, idx-1);
26501     int lit = val < 0 ? -idx : idx;
26502     lgldassume (lgl, lit);
26503     copied++;
26504   }
26505   lglprt (lgl, 1, "[flass] copied %d internal assignments", copied);
26506   TRANS (SATISFIED);
26507   lglextend (lgl);
26508 #ifndef NCHKSOL
26509   lglchksol (lgl);
26510 #endif
26511 #ifndef NLGLPICOSAT
26512   lglpicosatchksol (lgl);
26513 #endif
26514 }
26515
26516 int lgljoin (LGL * parent, LGL * child) {
26517   int res;
26518   {
26519     LGL * lgl = parent;
26520     ABORTIF (!parent, "uninitialized parent manager");
26521     ABORTIF (!child, "uninitialized child manager");
26522     ABORTIF (!parent->forked, "parent manager not forked");
26523     ABORTIF (!child->parent, "child manager has not parent");
26524     ABORTIF (child->parent != parent, "child manager has different parent");
26525     ABORTIF (!lglmtstk (&child->eassume),
26526       "child manager with assumptions not supported yet");
26527   }
26528   if (child->mt || (child->state & UNSATISFIED)) {
26529 #ifndef NLGLOG
26530     LGL * lgl = parent;
26531 #endif
26532     assert (child->mt);                           // no assumptions yet ...
26533     lglprt (parent, 1, "[join] unsatisfied state");
26534     if (!parent->mt) {
26535       LOG (1, "joining empty clause");
26536       parent->mt = 1;
26537     } else LOG (1, "no need to join empty clause since parent has one");
26538     res = 20;
26539   } else if (child->state & (SATISFIED | EXTENDED)) {
26540     lglprt (parent, 1, "[join] satisfied state");
26541     lglflass (parent, child);
26542     res = 10;
26543   } else {
26544     lglprt (parent, 1, "[join] unknown state");
26545     lglreset (parent);
26546     {
26547       LGL * lgl = parent;
26548       TRANS (UNKNOWN);
26549     }
26550     res = 0;
26551   }
26552   return res;
26553 }