ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
fastel.c
Go to the documentation of this file.
1#include "fastel.h"
2#include "dense.h"
3#include "eliminate.h"
4#include "inline.h"
5#include "internal.h"
6#include "print.h"
7#include "rank.h"
8#include "report.h"
9#include "terminate.h"
10#include "weaken.h"
11
13
14static bool fast_forward_subsumed (kissat *solver, clause *c) {
17 unsigned max_occurring = INVALID_LIT;
18 size_t max_occurrence = 0;
19 watches *all_watches = solver->watches;
20 mark *marks = solver->marks;
21 value *values = solver->values;
22 for (all_literals_in_clause (other, c)) {
23 const unsigned other_idx = IDX (other);
24 if (!ACTIVE (other_idx))
25 continue;
26 watches *other_watches = all_watches + other;
27 size_t other_occurrence = SIZE_WATCHES (*other_watches);
28 if (other_occurrence <= max_occurrence)
29 continue;
30 max_occurrence = other_occurrence;
31 max_occurring = other;
32 marks[other] = 1;
33 }
34 bool subsumed = false;
35 const size_t fasteloccs = GET_OPTION (fasteloccs);
36 for (all_literals_in_clause (other, c)) {
37 if (other == max_occurring)
38 continue;
39 const unsigned other_idx = IDX (other);
40 if (!ACTIVE (other_idx))
41 continue;
42 watches *other_watches = all_watches + other;
43 const size_t size_other_watches = SIZE_WATCHES (*other_watches);
44 if (size_other_watches > fasteloccs)
45 continue;
46 for (all_binary_large_watches (watch, *other_watches)) {
47 if (watch.type.binary) {
48 const unsigned other2 = watch.type.lit;
49 if (marks[other2]) {
50 LOGBINARY (other, other2, "subsuming");
51 subsumed = true;
52 break;
53 }
54 } else {
55 const reference d_ref = watch.large.ref;
56 clause *d = kissat_dereference_clause (solver, d_ref);
57 if (d == c)
58 continue;
59 if (d->garbage)
60 continue;
61 if (d->size > c->size)
62 continue;
64 subsumed = true;
65 for (all_literals_in_clause (other2, d)) {
66 if (values[other2] < 0)
67 continue;
68 if (!marks[other2]) {
69 subsumed = false;
70 break;
71 }
72 }
73 if (subsumed)
74 LOGCLS (d, "subsuming");
75 }
76 }
77 if (subsumed)
78 break;
79 }
80 for (all_literals_in_clause (other, c))
81 marks[other] = 0;
82 if (subsumed) {
83 LOGCLS (c, "subsumed");
85 INC (subsumed);
86 INC (fast_subsumed);
87 }
88 return subsumed;
89}
90
91static size_t flush_occurrences (kissat *solver, unsigned lit) {
92 const size_t fasteloccs = GET_OPTION (fasteloccs);
93 const size_t fastelclslim = GET_OPTION (fastelclslim);
94 const size_t fastelsub = GET_OPTION (fastelsub);
95 const value *const values = solver->values;
96 const flags *const all_flags = solver->flags;
98 watch *begin = BEGIN_WATCHES (*watches);
99 watch *end = END_WATCHES (*watches);
100 watch *q = begin, *p = q;
101 size_t res = 0;
102 while (p != end) {
103 const watch watch = *q++ = *p++;
104 if (watch.type.binary) {
105 const unsigned other = watch.binary.lit;
106 if (values[other] > 0)
107 continue;
108 const unsigned other_idx = IDX (other);
109 const flags *other_flags = all_flags + other_idx;
110 if (other_flags->eliminated) {
111 q--;
112 continue;
113 }
114 } else {
115 const reference ref = watch.large.ref;
116 clause *c = kissat_dereference_clause (solver, ref);
117 if (c->garbage) {
118 q--;
119 continue;
120 }
121 if (c->size > fastelclslim) {
122 res = fasteloccs + 1;
123 break;
124 }
125 for (all_literals_in_clause (other, c)) {
126 value other_value = values[other];
127 if (other_value > 0) {
128 LOGCLS (c, "%s satisfied", LOGLIT (other));
130 q--;
131 continue;
132 }
133 }
134 if (fastelsub && fast_forward_subsumed (solver, c)) {
135 q--;
136 continue;
137 }
138 }
139 if (++res > fasteloccs)
140 break;
141 }
142 if (q < p) {
143 while (p != end)
144 *q++ = *p++;
146 }
147 return res;
148}
149
150static void do_fast_resolve_binary_binary (kissat *solver, unsigned pivot,
151 unsigned clit, unsigned dlit) {
152 KISSAT_assert (!FLAGS (IDX (clit))->eliminated);
153 KISSAT_assert (!FLAGS (IDX (dlit))->eliminated);
154 if (clit == NOT (dlit)) {
155 LOG ("resolvent tautological");
156 return;
157 }
158 value *values = solver->values;
159 value cval = values[clit];
160 if (cval > 0) {
161 LOG ("1st antecedent satisfied");
162 return;
163 }
164 value dval = values[dlit];
165 if (dval > 0) {
166 LOG ("2nd antecedent satisfied");
167 return;
168 }
169 if (cval < 0 && dval < 0) {
170 KISSAT_assert (!solver->inconsistent);
171 solver->inconsistent = true;
172 LOG ("resolved empty clause");
175 return;
176 }
177 if (cval < 0) {
178 LOG ("resolved unit clause %s", LOGLIT (dlit));
179 INC (eliminate_units);
181 return;
182 }
183 if (dval < 0) {
184 LOG ("resolved unit clause %s", LOGLIT (clit));
185 INC (eliminate_units);
187 return;
188 }
189 if (clit == dlit) {
190 LOG ("resolved unit clause %s", LOGLIT (clit));
191 INC (eliminate_units);
193 return;
194 }
195 KISSAT_assert (!cval);
196 KISSAT_assert (!dval);
197 unsigneds *clause = &solver->clause;
199 PUSH_STACK (*clause, clit);
200 PUSH_STACK (*clause, dlit);
201 LOGTMP ("%s resolvent", LOGVAR (pivot));
202#ifndef LOGGING
203 (void) pivot;
204#endif
207}
208
209static void do_fast_resolve_binary_large (kissat *solver, unsigned pivot,
210 unsigned lit, clause *c) {
211 KISSAT_assert (!FLAGS (IDX (lit))->eliminated);
212 if (c->garbage)
213 return;
215 value *values = solver->values;
216 value lit_val = values[lit];
217 if (lit_val > 0) {
218 LOG ("binary clause antecedent satisfied");
219 return;
220 }
221 unsigneds *clause = &solver->clause;
223 if (!lit_val)
225 bool satisfied = false, tautological = false;
226 const unsigned not_lit = NOT (lit);
227 for (all_literals_in_clause (other, c)) {
228 const unsigned idx_other = IDX (other);
229 if (idx_other == pivot)
230 continue;
231 if (other == lit)
232 continue;
233 if (other == not_lit) {
234 LOG ("resolvent tautological");
235 tautological = true;
236 break;
237 }
238 value other_val = values[other];
239 if (other_val < 0)
240 continue;
241 if (other_val > 0) {
242 LOG ("large clause antecedent satisfied");
244 satisfied = true;
245 break;
246 }
247 PUSH_STACK (*clause, other);
248 }
249 if (satisfied || tautological) {
251 return;
252 }
253 size_t size = SIZE_STACK (*clause);
254 if (!size) {
255 KISSAT_assert (!solver->inconsistent);
256 solver->inconsistent = true;
257 LOG ("resolved empty clause");
260 return;
261 }
262 if (size == 1) {
263 const unsigned unit = PEEK_STACK (*clause, 0);
265 LOG ("resolved unit clause %s", LOGLIT (unit));
266 INC (eliminate_units);
268 return;
269 }
270 LOGTMP ("%s resolvent", LOGVAR (pivot));
273}
274
275static void do_fast_resolve_large_large (kissat *solver, unsigned pivot,
276 clause *c, clause *d) {
277 if (c->garbage)
278 return;
279 if (d->garbage)
280 return;
283 value *values = solver->values;
284 mark *marks = solver->marks;
285 unsigneds *clause = &solver->clause;
287 bool satisfied = false, tautological = false;
288 for (all_literals_in_clause (other, c)) {
289 const unsigned idx_other = IDX (other);
290 if (idx_other == pivot)
291 continue;
292 value other_val = values[other];
293 if (other_val < 0)
294 continue;
295 if (other_val > 0) {
296 LOG ("1st antecedent satisfied");
297 satisfied = true;
298 break;
299 }
300 PUSH_STACK (*clause, other);
301 marks[other] = 1;
302 }
303 if (satisfied || tautological) {
304 for (all_stack (unsigned, other, *clause))
305 marks[other] = 0;
307 return;
308 }
309 size_t marked = SIZE_STACK (*clause);
310 for (all_literals_in_clause (other, d)) {
311 const unsigned idx_other = IDX (other);
312 if (idx_other == pivot)
313 continue;
314 value other_val = values[other];
315 if (other_val < 0)
316 continue;
317 if (other_val > 0) {
318 LOG ("2nd antecedent satisfied");
319 satisfied = true;
320 break;
321 }
322 mark mark_other = marks[other];
323 if (mark_other)
324 continue;
325 const unsigned not_other = NOT (other);
326 mark mark_not_other = marks[not_other];
327 if (mark_not_other) {
328 LOG ("tautological resolvent");
329 tautological = true;
330 break;
331 }
332 PUSH_STACK (*clause, other);
333 }
334 if (satisfied || tautological) {
335 for (all_stack (unsigned, other, *clause))
336 marks[other] = 0;
338 return;
339 }
340 size_t size = SIZE_STACK (*clause);
341 if (!size) {
342 KISSAT_assert (!solver->inconsistent);
343 solver->inconsistent = true;
344 LOG ("resolved empty clause");
347 return;
348 }
349 if (size == 1) {
350 const unsigned unit = PEEK_STACK (*clause, 0);
352 marks[unit] = 0;
353 LOG ("resolved unit clause %s", LOGLIT (unit));
354 INC (eliminate_units);
356 return;
357 }
358 LOGTMP ("%s resolvent", LOGVAR (pivot));
360 RESIZE_STACK (*clause, marked);
361 for (all_stack (unsigned, other, *clause))
362 marks[other] = 0;
364}
365
366static void do_fast_resolve (kissat *solver, unsigned pivot, watch cwatch,
367 watch dwatch) {
368 KISSAT_assert (!solver->inconsistent);
369 LOGWATCH (LIT (pivot), cwatch, "1st fast %s elimination antecedent",
370 LOGVAR (pivot));
371 LOGWATCH (NOT (LIT (pivot)), dwatch, "1st fast %s elimination antecedent",
372 LOGVAR (pivot));
373 const unsigned clit = cwatch.binary.lit;
374 const unsigned dlit = dwatch.binary.lit;
375 const reference cref = cwatch.large.ref;
376 const reference dref = dwatch.large.ref;
377 const bool cbin = cwatch.type.binary;
378 const bool dbin = dwatch.type.binary;
379 clause *c = cbin ? 0 : kissat_dereference_clause (solver, cref);
380 clause *d = dbin ? 0 : kissat_dereference_clause (solver, dref);
381 if (cbin && dbin)
382 do_fast_resolve_binary_binary (solver, pivot, clit, dlit);
383 else if (cbin && !dbin)
384 do_fast_resolve_binary_large (solver, pivot, clit, d);
385 else if (!cbin && dbin)
386 do_fast_resolve_binary_large (solver, pivot, dlit, c);
387 else {
388 KISSAT_assert (!cbin), KISSAT_assert (!dbin);
389 do_fast_resolve_large_large (solver, pivot, c, d);
390 }
391}
392
393static void fast_delete_and_weaken_clauses (kissat *solver, unsigned lit) {
394 watches *all_watches = solver->watches;
395 watches *lit_watches = all_watches + lit;
396 value *values = solver->values;
397 for (all_binary_large_watches (watch, *lit_watches)) {
398 if (watch.type.binary) {
399 const unsigned other = watch.binary.lit;
400 const value value = values[other];
401 if (value <= 0)
404 } else {
405 const reference ref = watch.large.ref;
406 clause *c = kissat_dereference_clause (solver, ref);
407 if (!c->garbage) {
408 bool satisfied = false;
409 for (all_literals_in_clause (other, c))
410 if (values[other] > 0) {
411 satisfied = true;
412 break;
413 }
414 if (!satisfied)
417 }
418 }
419 }
420 RELEASE_WATCHES (*lit_watches);
421}
422
423static void do_fast_eliminate (kissat *solver, unsigned pivot) {
424 LOG ("fast variable elimination of %s", LOGVAR (pivot));
425 const unsigned lit = LIT (pivot);
426 const unsigned not_lit = NOT (lit);
427 watches *all_watches = solver->watches;
428 watches *lit_watches = all_watches + lit;
429 watches *not_lit_watches = all_watches + not_lit;
430 LOG ("occurs %zu positively", SIZE_WATCHES (*lit_watches));
431 LOG ("occurs %zu negatively", SIZE_WATCHES (*not_lit_watches));
432 watch *begin_lit_watches = BEGIN_WATCHES (*lit_watches);
433 watch *begin_not_lit_watches = BEGIN_WATCHES (*not_lit_watches);
434 watch *end_lit_watches = END_WATCHES (*lit_watches);
435 watch *end_not_lit_watches = END_WATCHES (*not_lit_watches);
436 for (watch *p = begin_lit_watches; p < end_lit_watches; p++)
437 for (watch *q = begin_not_lit_watches; q < end_not_lit_watches; q++) {
438 do_fast_resolve (solver, pivot, *p, *q);
439 if (solver->inconsistent)
440 return;
441 watches *new_all_watches = solver->watches;
442 const size_t i = p - begin_lit_watches;
443 const size_t j = q - begin_not_lit_watches;
444 all_watches = new_all_watches;
445 lit_watches = all_watches + lit;
446 not_lit_watches = all_watches + not_lit;
447 begin_lit_watches = BEGIN_WATCHES (*lit_watches);
448 begin_not_lit_watches = BEGIN_WATCHES (*not_lit_watches);
449 end_lit_watches = END_WATCHES (*lit_watches);
450 end_not_lit_watches = END_WATCHES (*not_lit_watches);
451 p = begin_lit_watches + i;
452 q = begin_not_lit_watches + j;
453 }
454 KISSAT_assert (!solver->inconsistent);
455 INC (eliminated);
456 INC (fast_eliminated);
458 fast_delete_and_weaken_clauses (solver, lit);
459 fast_delete_and_weaken_clauses (solver, not_lit);
460}
461
462static bool can_fast_resolve_binary_binary (kissat *solver, unsigned clit,
463 unsigned dlit) {
464 KISSAT_assert (!FLAGS (IDX (clit))->eliminated);
465 KISSAT_assert (!FLAGS (IDX (dlit))->eliminated);
466 if (clit == NOT (dlit))
467 return false;
468 value *values = solver->values;
469 value cval = values[clit];
470 if (cval > 0)
471 return false;
472 value dval = values[dlit];
473 if (dval > 0)
474 return false;
475 if (cval < 0 && dval < 0) {
476 KISSAT_assert (!solver->inconsistent);
477 solver->inconsistent = true;
478 LOG ("resolved empty clause");
481 return false;
482 }
483 if (cval < 0) {
484 LOG ("resolved unit clause %s", LOGLIT (dlit));
485 INC (eliminate_units);
487 return false;
488 }
489 if (dval < 0) {
490 LOG ("resolved unit clause %s", LOGLIT (clit));
491 INC (eliminate_units);
493 return false;
494 }
495 if (clit == dlit) {
496 LOG ("resolved unit clause %s", LOGLIT (clit));
497 INC (eliminate_units);
499 return false;
500 }
501 KISSAT_assert (!cval);
502 KISSAT_assert (!dval);
503 return true;
504}
505
506static bool can_fast_resolve_binary_large (kissat *solver, unsigned pivot,
507 unsigned lit, clause *c) {
508 KISSAT_assert (!FLAGS (IDX (lit))->eliminated);
509 if (c->garbage)
510 return false;
512 value *values = solver->values;
513 value lit_val = values[lit];
514 if (lit_val > 0)
515 return false;
516 const unsigned not_lit = NOT (lit);
517 bool found_lit = false;
518 for (all_literals_in_clause (other, c)) {
519 if (other == lit)
520 found_lit = true;
521 if (other == not_lit)
522 return false;
523 value other_val = values[other];
524 if (other_val > 0) {
525 LOG ("large clause antecedent satisfied");
527 return false;
528 }
529 }
530 if (found_lit) {
531 unsigneds *clause = &solver->clause;
533 for (all_literals_in_clause (other, c)) {
534 const unsigned idx = IDX (other);
535 if (idx == pivot)
536 continue;
537 value value = values[other];
538 if (value < 0)
539 continue;
541 PUSH_STACK (*clause, other);
542 }
543 LOGTMP ("self-subsuming resolvent");
544 INC (strengthened);
545 INC (fast_strengthened);
546 const size_t size = SIZE_STACK (*clause);
547 const reference ref = kissat_reference_clause (solver, c);
548 if (!size) {
549 KISSAT_assert (!solver->inconsistent);
550 solver->inconsistent = true;
551 LOG ("resolved empty clause");
554 } else if (size == 1) {
555 const unsigned unit = PEEK_STACK (*clause, 0);
556 LOG ("resolved %s unit clause", LOGLIT (unit));
557 INC (eliminate_units);
559 } else
562 c = kissat_dereference_clause (solver, ref);
563 LOGCLS (c, "self-subsuming antecedent");
565 return false;
566 }
567 return true;
568}
569
570static bool can_fast_resolve_large_large (kissat *solver, unsigned pivot,
571 clause *c, clause *d) {
572 if (c->garbage)
573 return false;
574 if (d->garbage)
575 return false;
578 value *values = solver->values;
579 mark *marks = solver->marks;
580 bool satisfied = false;
581 unsigneds *clause = &solver->clause;
583 for (all_literals_in_clause (other, c)) {
584 const unsigned idx_other = IDX (other);
585 if (idx_other == pivot)
586 continue;
587 value other_val = values[other];
588 if (other_val < 0)
589 continue;
590 if (other_val > 0) {
591 satisfied = true;
592 LOGCLS (c, "%s satisfied", LOGLIT (other));
594 break;
595 }
596 KISSAT_assert (!marks[other]);
597 marks[other] = 1;
598 PUSH_STACK (*clause, other);
599 }
600 bool tautological = false;
601 if (!satisfied) {
602 for (all_literals_in_clause (other, d)) {
603 const unsigned idx_other = IDX (other);
604 if (idx_other == pivot)
605 continue;
606 value other_val = values[other];
607 if (other_val < 0)
608 continue;
609 if (other_val > 0) {
610 satisfied = true;
611 LOGCLS (d, "%s satisfied", LOGLIT (other));
613 break;
614 }
615 const unsigned not_other = NOT (other);
616 const mark mark_not_other = marks[not_other];
617 if (mark_not_other) {
618 tautological = true;
619 break;
620 }
621 const mark other_mark = marks[other];
622 if (other_mark)
623 continue;
624 PUSH_STACK (*clause, other);
625 }
626 }
627 for (all_literals_in_clause (other, c))
628 marks[other] = 0;
629 bool strengthened = false;
630 if (!satisfied && !tautological) {
631 const size_t size = SIZE_STACK (*clause);
632 if (!size) {
633 KISSAT_assert (!solver->inconsistent);
634 solver->inconsistent = true;
635 LOG ("resolved empty clause");
638 strengthened = true;
639 } else if (size == 1) {
640 const unsigned unit = PEEK_STACK (*clause, 0);
641 LOG ("resolved %s unit clause", LOGLIT (unit));
642 INC (eliminate_units);
644 strengthened = true;
645 } else {
646 bool c_subsumed = false, d_subsumed = false;
647 bool marked = false;
648 if (size < c->size) {
649 marked = true;
650 for (all_stack (unsigned, other, *clause))
651 marks[other] = 1;
652 size_t count = 0;
653 for (all_literals_in_clause (other, c))
654 if (marks[other])
655 count++;
656 c_subsumed = (count >= size);
657 }
658 if (size < d->size) {
659 if (!marked) {
660 marked = true;
661 for (all_stack (unsigned, other, *clause))
662 marks[other] = 1;
663 }
664 size_t count = 0;
665 for (all_literals_in_clause (other, d))
666 if (marks[other])
667 count++;
668 d_subsumed = (count >= size);
669 }
670 if (marked) {
671 for (all_stack (unsigned, other, *clause))
672 marks[other] = 0;
673 }
674 if (c_subsumed || d_subsumed) {
675 LOGTMP ("self-subsuming resolvent");
676 INC (strengthened);
677 INC (fast_strengthened);
678 const reference c_ref = kissat_reference_clause (solver, c);
679 const reference d_ref = kissat_reference_clause (solver, d);
681 strengthened = true;
682 if (c_subsumed) {
683 c = kissat_dereference_clause (solver, c_ref);
684 LOGCLS (c, "self-subsuming antecedent");
686 }
687 if (d_subsumed) {
688 d = kissat_dereference_clause (solver, d_ref);
689 LOGCLS (d, "self-subsuming antecedent");
691 }
692 if (c_subsumed && d_subsumed)
693 INC (fast_subsumed);
694 }
695 }
696 }
698 return !satisfied && !tautological && !strengthened;
699}
700
701static bool can_fast_resolve (kissat *solver, unsigned pivot, watch cwatch,
702 watch dwatch) {
703 KISSAT_assert (!solver->inconsistent);
704 const unsigned clit = cwatch.binary.lit;
705 const unsigned dlit = dwatch.binary.lit;
706 const reference cref = cwatch.large.ref;
707 const reference dref = dwatch.large.ref;
708 const bool cbin = cwatch.type.binary;
709 const bool dbin = dwatch.type.binary;
710 clause *c = cbin ? 0 : kissat_dereference_clause (solver, cref);
711 clause *d = dbin ? 0 : kissat_dereference_clause (solver, dref);
712 if (cbin && dbin)
713 return can_fast_resolve_binary_binary (solver, clit, dlit);
714 if (cbin && !dbin)
715 return can_fast_resolve_binary_large (solver, pivot, clit, d);
716 if (!cbin && dbin)
717 return can_fast_resolve_binary_large (solver, pivot, dlit, c);
718 KISSAT_assert (!cbin), KISSAT_assert (!dbin);
719 return can_fast_resolve_large_large (solver, pivot, c, d);
720}
721
722static bool resolvents_limited (kissat *solver, unsigned pivot,
723 size_t limit) {
724 const unsigned lit = LIT (pivot);
725 const unsigned not_lit = NOT (lit);
726 watches *all_watches = solver->watches;
727 watches *lit_watches = all_watches + lit;
728 watches *not_lit_watches = all_watches + not_lit;
729 watch *begin_lit_watches = BEGIN_WATCHES (*lit_watches);
730 watch *begin_not_lit_watches = BEGIN_WATCHES (*not_lit_watches);
731 watch *end_lit_watches = END_WATCHES (*lit_watches);
732 watch *end_not_lit_watches = END_WATCHES (*not_lit_watches);
733 size_t resolved = 0;
734 for (watch *p = begin_lit_watches; p < end_lit_watches; p++)
735 for (watch *q = begin_not_lit_watches; q < end_not_lit_watches; q++) {
736 if (can_fast_resolve (solver, pivot, *p, *q) && ++resolved > limit)
737 return false;
738 if (solver->inconsistent)
739 return false;
740 watches *new_all_watches = solver->watches;
741 const size_t i = p - begin_lit_watches;
742 const size_t j = q - begin_not_lit_watches;
743 all_watches = new_all_watches;
744 lit_watches = all_watches + lit;
745 not_lit_watches = all_watches + not_lit;
746 begin_lit_watches = BEGIN_WATCHES (*lit_watches);
747 begin_not_lit_watches = BEGIN_WATCHES (*not_lit_watches);
748 end_lit_watches = END_WATCHES (*lit_watches);
749 end_not_lit_watches = END_WATCHES (*not_lit_watches);
750 p = begin_lit_watches + i;
751 q = begin_not_lit_watches + j;
752 }
753 return true;
754}
755
756static bool try_to_fast_eliminate (kissat *solver, unsigned pivot) {
757 KISSAT_assert (!solver->inconsistent);
758 if (!ACTIVE (pivot))
759 return false;
760 const unsigned lit = LIT (pivot);
761 const unsigned not_lit = NOT (lit);
762 const size_t fasteloccs = GET_OPTION (fasteloccs);
763 const size_t pos = flush_occurrences (solver, lit);
764 if (pos > fasteloccs)
765 return false;
766 const size_t neg = flush_occurrences (solver, not_lit);
767 if (neg > fasteloccs)
768 return false;
769 const size_t sum = pos + neg;
770 const size_t product = pos * neg;
771 if (sum > fasteloccs)
772 return false;
773 const size_t fastelim = GET_OPTION (fastelim);
774 if (product <= fastelim) {
775 do_fast_eliminate (solver, pivot);
776 return true;
777 }
778 if (resolvents_limited (solver, pivot, fastelim)) {
779 do_fast_eliminate (solver, pivot);
780 return true;
781 }
782 return false;
783}
784
785static void flush_eliminated_binary_clauses_of_literal (kissat *solver,
786 unsigned lit) {
787 flags *all_flags = solver->flags;
789 watch *begin = BEGIN_WATCHES (*watches);
790 watch *end = END_WATCHES (*watches);
791 watch *q = begin, *p = q;
792 while (p != end) {
793 watch watch = *q++ = *p++;
794 if (!watch.type.binary)
795 continue;
796 const unsigned other = watch.binary.lit;
797 const unsigned other_idx = IDX (other);
798 flags *other_flags = all_flags + other_idx;
799 if (other_flags->eliminated)
800 q--;
801 }
803}
804
805static void flush_eliminated_binary_clauses (kissat *solver) {
806 for (all_variables (idx)) {
807 const unsigned lit = LIT (idx);
808 const unsigned not_lit = NOT (lit);
809 flush_eliminated_binary_clauses_of_literal (solver, lit);
810 flush_eliminated_binary_clauses_of_literal (solver, not_lit);
811 }
812}
813
814struct candidate {
815 unsigned pivot;
816 unsigned score;
817};
818
819typedef struct candidate candidate;
820typedef STACK (candidate) candidates;
821
822#define RANK_CANDIDATE(CANDIDATE) ((CANDIDATE).score)
823
825 if (solver->inconsistent)
826 return;
827 if (!GET_OPTION (fastel))
828 return;
829#ifndef KISSAT_QUIET
830 const unsigned variables_before = solver->active;
831#endif
832 KISSAT_assert (!solver->level);
833 START (fastel);
836 const unsigned fastelrounds = GET_OPTION (fastelrounds);
837 const size_t fasteloccs = GET_OPTION (fasteloccs);
838#ifndef KISSAT_QUIET
839 unsigned eliminated = 0;
840#endif
841 unsigned round = 0;
842 candidates candidates;
843 INIT_STACK (candidates);
844 bool done = false;
845 do {
846 if (round++ >= fastelrounds)
847 break;
849 solver, "gathering candidates for fast elimination round %u",
850 round);
851 KISSAT_assert (EMPTY_STACK (candidates));
852 flags *all_flags = solver->flags;
853 for (all_variables (pivot)) {
854 flags *pivot_flags = all_flags + pivot;
855 if (!pivot_flags->active)
856 continue;
857 if (!pivot_flags->eliminate)
858 continue;
859 const unsigned lit = LIT (pivot);
860 const size_t pos = flush_occurrences (solver, lit);
861 if (pos > fasteloccs)
862 continue;
863 const unsigned not_lit = LIT (pivot);
864 const size_t neg = flush_occurrences (solver, not_lit);
865 if (neg > fasteloccs)
866 continue;
867 const unsigned score = pos + neg;
868 if (score > fasteloccs)
869 continue;
871 PUSH_STACK (candidates, candidate);
872 }
873#ifndef KISSAT_QUIET
874 const size_t size_candidates = SIZE_STACK (candidates);
875 const size_t active_variables = solver->active;
877 solver, "gathered %zu candidates %.0f%% in elimination round %u",
878 size_candidates, kissat_percent (size_candidates, active_variables),
879 round);
880#endif
881 RADIX_STACK (candidate, unsigned, candidates, RANK_CANDIDATE);
882 unsigned eliminated_this_round = 0;
883 for (all_stack (candidate, candidate, candidates)) {
884 const unsigned pivot = candidate.pivot;
885 flags *pivot_flags = all_flags + pivot;
886 if (!pivot_flags->active)
887 continue;
888 if (!pivot_flags->eliminate)
889 continue;
891 done = true;
892 break;
893 }
894 if (try_to_fast_eliminate (solver, pivot))
895 eliminated_this_round++;
896 if (solver->inconsistent) {
897 done = true;
898 break;
899 }
900 pivot_flags->eliminate = false;
902 if (solver->inconsistent) {
903 done = true;
904 break;
905 }
906 }
907 CLEAR_STACK (candidates);
908#ifndef KISSAT_QUIET
909 eliminated += eliminated_this_round;
911 solver, "fast eliminated %u of %zu candidates %.0f%% in round %u",
912 eliminated_this_round, size_candidates,
913 kissat_percent (eliminated_this_round, size_candidates), round);
914#endif
915 if (!eliminated_this_round)
916 done = true;
917 } while (!done);
918 RELEASE_STACK (candidates);
919 for (all_variables (idx))
920 FLAGS (idx)->eliminate = true;
921 flush_eliminated_binary_clauses (solver);
923#ifndef KISSAT_QUIET
924 const unsigned original_variables = solver->statistics.variables_original;
925 const unsigned variables_after = solver->active;
927 solver,
928 "[fastel] "
929 "fast elimination of %u variables %.0f%% (%u remain %.0f%%)",
930 eliminated, kissat_percent (eliminated, variables_before),
931 variables_after,
932 kissat_percent (variables_after, original_variables));
933#endif
934 STOP (fastel);
935 REPORT (!eliminated, 'e');
936}
937
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
void kissat_learned_unit(kissat *solver, unsigned lit)
Definition assign.c:18
#define RESIZE_STACK(S, NEW_SIZE)
Definition stack.h:55
#define all_stack(T, E, S)
Definition stack.h:94
#define SIZE_STACK(S)
Definition stack.h:19
#define EMPTY_STACK(S)
Definition stack.h:18
#define RELEASE_STACK(S)
Definition stack.h:71
#define CLEAR_STACK(S)
Definition stack.h:50
#define PUSH_STACK(S, E)
Definition stack.h:39
#define PEEK_STACK(S, N)
Definition stack.h:29
#define INIT_STACK(S)
Definition stack.h:22
#define STACK(TYPE)
Definition stack.h:10
#define INVALID_LIT
#define INC(NAME)
#define LOG(...)
ABC_NAMESPACE_IMPL_START typedef signed char value
#define FLAGS
#define CHECK_AND_ADD_EMPTY(...)
Definition check.h:146
reference kissat_new_irredundant_clause(kissat *solver)
Definition clause.c:140
void kissat_mark_clause_as_garbage(kissat *solver, clause *c)
Definition clause.c:164
void kissat_delete_binary(kissat *solver, unsigned a, unsigned b)
Definition clause.c:181
void kissat_enter_dense_mode(kissat *solver, litpairs *irredundant)
Definition dense.c:101
void kissat_resume_sparse_mode(kissat *solver, bool flush_eliminated, litpairs *irredundant)
Definition dense.c:201
void kissat_flush_units_while_connected(kissat *solver)
Definition eliminate.c:162
#define ACTIVE
Definition espresso.h:129
bool pos
Definition globals.c:30
Cube * p
Definition exorList.c:222
#define RANK_CANDIDATE(CANDIDATE)
void kissat_fast_variable_elimination(struct kissat *)
void kissat_mark_eliminated_variable(kissat *solver, unsigned idx)
Definition flags.c:79
#define all_variables(IDX)
Definition internal.h:269
#define all_literals_in_clause(LIT, C)
Definition clause.h:47
#define KISSAT_assert(ignore)
Definition global.h:13
#define solver
Definition kitten.c:211
#define LOGBINARY(...)
Definition logging.h:442
#define LOGWATCH(...)
Definition logging.h:454
#define LOGCLS(...)
Definition logging.h:415
#define LOGTMP(...)
Definition logging.h:463
#define LOGLIT(...)
Definition logging.hpp:99
unsigned long long size
Definition giaNewBdd.h:39
unsigned short ref
Definition giaNewBdd.h:38
#define GET_OPTION(N)
Definition options.h:295
#define kissat_verbose(...)
Definition print.h:51
#define kissat_extremely_verbose(...)
Definition print.h:53
#define kissat_very_verbose(...)
Definition print.h:52
#define STOP(P)
Definition profile.hpp:158
#define START(P)
Definition profile.hpp:150
#define ADD_EMPTY_TO_PROOF(...)
Definition proof.h:135
#define RADIX_STACK(VTYPE, RTYPE, S, RANK)
Definition rank.h:136
ABC_NAMESPACE_HEADER_START typedef unsigned reference
Definition reference.h:9
#define REPORT(...)
Definition report.h:10
int lit
Definition satVec.h:130
#define LIT(IDX)
Definition literal.h:31
#define IDX(LIT)
Definition literal.h:28
#define NOT(LIT)
Definition literal.h:33
unsigned pivot
Definition fastel.c:815
unsigned score
Definition fastel.c:816
bool redundant
Definition clause.h:28
unsigned size
Definition clause.h:37
bool garbage
Definition clause.h:25
Definition flags.h:11
bool eliminate
Definition flags.h:15
bool active
Definition flags.h:12
bool eliminated
Definition flags.h:16
#define TERMINATED(BIT)
Definition terminate.h:42
#define fastel_terminated_1
Definition terminate.h:63
Definition watch.h:41
large_watch large
Definition watch.h:45
watch_type type
Definition watch.h:42
binary_watch binary
Definition watch.h:43
signed char mark
Definition value.h:8
void kissat_connect_irredundant_large_clauses(kissat *solver)
Definition watch.c:171
#define SIZE_WATCHES(W)
Definition watch.h:104
#define BEGIN_WATCHES(WS)
Definition watch.h:115
#define END_WATCHES(WS)
Definition watch.h:118
#define RELEASE_WATCHES(WS)
Definition watch.h:126
#define SET_END_OF_WATCHES(WS, P)
Definition watch.h:128
vector watches
Definition watch.h:49
#define all_binary_large_watches(WATCH, WATCHES)
Definition watch.h:158
#define WATCHES(LIT)
Definition watch.h:137
void kissat_weaken_binary(kissat *solver, unsigned lit, unsigned other)
Definition weaken.c:48
void kissat_weaken_clause(kissat *solver, unsigned lit, clause *c)
Definition weaken.c:38