ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
factor.c
Go to the documentation of this file.
1#include "factor.h"
2#include "bump.h"
3#include "clause.h"
4#include "dense.h"
5#include "heap.h"
6#include "import.h"
7#include "inline.h"
8#include "inlineheap.h"
9#include "inlinequeue.h"
10#include "inlinevector.h"
11#include "internal.h"
12#include "logging.h"
13#include "print.h"
14#include "report.h"
15#include "sort.h"
16#include "terminate.h"
17#include "vector.h"
18#include "watch.h"
19
20#include <string.h>
21
23
24#define FACTOR 1
25#define QUOTIENT 2
26#define NOUNTED 4
27
28struct quotient {
29 size_t id;
30 struct quotient *prev, *next;
31 unsigned factor;
32 statches clauses;
33 sizes matches;
34 size_t matched;
35};
36
37typedef struct quotient quotient;
38
39struct scores {
40 double *score;
41 unsigneds scored;
42};
43
44typedef struct scores scores;
45
46struct factoring {
48 size_t size, allocated;
49 unsigned initial;
50 unsigned *count;
52 unsigned hops;
53 unsigned bound;
54 unsigneds fresh;
55 unsigneds counted;
56 unsigneds nounted;
57 references qlauses;
58 uint64_t limit;
59 struct {
63};
64
65typedef struct factoring factoring;
66
67static void init_factoring (kissat *solver, factoring *factoring,
68 uint64_t limit) {
69 memset (factoring, 0, sizeof *factoring);
73 factoring->bound = solver->bounds.eliminate.additional_clauses;
74 if (GET_OPTION (factorstructural))
75 factoring->hops = GET_OPTION (factorhops);
76 const unsigned hops = factoring->hops;
77 if (hops) {
79 for (unsigned i = 0; i != hops; i++) {
81 NALLOC (double, scores->score, VARS);
82 double *score = scores->score;
83 for (all_variables (idx))
84 score[idx] = -1;
85 }
86 }
88#ifndef KISSAT_NDEBUG
89 for (all_literals (lit))
90 KISSAT_assert (!solver->marks[lit]);
91#endif
92}
93
94static void release_quotients (factoring *factoring) {
95 kissat *const solver = factoring->solver;
96 mark *marks = solver->marks;
97 for (quotient *q = factoring->quotients.first, *next; q; q = next) {
98 next = q->next;
99 unsigned factor = q->factor;
100 KISSAT_assert (marks[factor] == FACTOR);
101 marks[factor] = 0;
102 RELEASE_STACK (q->clauses);
103 RELEASE_STACK (q->matches);
104 kissat_free (solver, q, sizeof *q);
105 }
106 const unsigned hops = factoring->hops;
107 if (hops) {
108 for (unsigned i = 0; i != hops; i++) {
110 unsigneds *scored = &scores->scored;
111 double *score = scores->score;
112 while (!EMPTY_STACK (*scored)) {
113 unsigned idx = POP_STACK (*scored);
114 score[idx] = -1;
115 }
116 }
117 }
119}
120
121static void release_factoring (factoring *factoring) {
122 kissat *const solver = factoring->solver;
123 KISSAT_assert (EMPTY_STACK (solver->analyzed));
132 release_quotients (factoring);
135 const size_t allocated_score = factoring->allocated / 2;
136 const unsigned hops = factoring->hops;
137 if (hops) {
138 for (unsigned i = 0; i != hops; i++) {
140 double *score = scores->score;
141 DEALLOC (score, allocated_score);
143 }
145 }
146#ifndef KISSAT_NDEBUG
147 for (all_literals (lit))
148 KISSAT_assert (!solver->marks[lit]);
149#endif
150}
151
152static void update_candidate (factoring *factoring, unsigned lit) {
153 heap *cands = &factoring->schedule;
154 kissat *const solver = factoring->solver;
155 const size_t size = SIZE_WATCHES (solver->watches[lit]);
156 if (size > 1) {
157 kissat_adjust_heap (solver, cands, lit);
158 kissat_update_heap (solver, cands, lit, size);
159 if (!kissat_heap_contains (cands, lit))
160 kissat_push_heap (solver, cands, lit);
161 } else if (kissat_heap_contains (cands, lit))
162 kissat_pop_heap (solver, cands, lit);
163}
164
165static void schedule_factorization (factoring *factoring) {
166 kissat *const solver = factoring->solver;
167 flags *flags = solver->flags;
168 for (all_variables (idx)) {
169 if (ACTIVE (idx)) {
170 struct flags *f = flags + idx;
171 const unsigned lit = LIT (idx);
172 const unsigned not_lit = NOT (lit);
173 if (f->factor & 1)
174 update_candidate (factoring, lit);
175 if (f->factor & 2)
176 update_candidate (factoring, not_lit);
177 }
178 }
179#ifndef KISSAT_QUIET
180 heap *cands = &factoring->schedule;
181 size_t size_cands = kissat_size_heap (cands);
183 solver, "scheduled %zu factorization candidate literals %.0f %%",
184 size_cands, kissat_percent (size_cands, LITS));
185#endif
186}
187
188static quotient *new_quotient (factoring *factoring, unsigned factor) {
189 kissat *const solver = factoring->solver;
190 mark *marks = solver->marks;
191 KISSAT_assert (!marks[factor]);
192 marks[factor] = FACTOR;
193 quotient *res = (quotient*)kissat_malloc (solver, sizeof *res);
194 memset (res, 0, sizeof *res);
195 res->factor = factor;
197 if (last) {
199 KISSAT_assert (!last->next);
200 last->next = res;
201 res->id = last->id + 1;
202 } else {
205 }
206 factoring->quotients.last = res;
207 res->prev = last;
208 LOG ("new quotient[%zu] with factor %s", res->id, LOGLIT (factor));
209 return res;
210}
211
212static size_t first_factor (factoring *factoring, unsigned factor) {
213 kissat *const solver = factoring->solver;
214 watches *all_watches = solver->watches;
215 watches *factor_watches = all_watches + factor;
217 quotient *quotient = new_quotient (factoring, factor);
218 statches *clauses = &quotient->clauses;
219 uint64_t ticks = 0;
220 for (all_binary_large_watches (watch, *factor_watches)) {
221 PUSH_STACK (*clauses, watch);
222#ifndef KISSAT_NDEBUG
223 if (watch.type.binary)
224 continue;
225 const reference ref = watch.large.ref;
226 clause *const c = kissat_dereference_clause (solver, ref);
228#endif
229 ticks++;
230 }
231 size_t res = SIZE_STACK (*clauses);
232 LOG ("quotient[0] factor %s size %zu", LOGLIT (factor), res);
233 KISSAT_assert (res > 1);
234 ADD (factor_ticks, ticks);
235 return res;
236}
237
238static void clear_nounted (kissat *solver, unsigneds *nounted) {
239 mark *marks = solver->marks;
240 for (all_stack (unsigned, lit, *nounted)) {
241 KISSAT_assert (marks[lit] & NOUNTED);
242 marks[lit] &= ~NOUNTED;
243 }
244 CLEAR_STACK (*nounted);
245}
246
247static void clear_qlauses (kissat *solver, references *qlauses) {
248 ward *const arena = BEGIN_STACK (solver->arena);
249 for (all_stack (reference, ref, *qlauses)) {
250 clause *const c = (clause *) (arena + ref);
252 c->quotient = false;
253 }
254 CLEAR_STACK (*qlauses);
255}
256
257static double distinct_paths (factoring *factoring, unsigned src_lit,
258 unsigned dst_idx, unsigned hops) {
259 kissat *const solver = factoring->solver;
260 const unsigned src_idx = IDX (src_lit);
261 bool matched = (src_idx == dst_idx);
262 if (!hops)
263 return matched;
264 const unsigned next_hops = hops - 1;
265 scores *scores = &factoring->scores[next_hops];
266 double *score = scores->score;
267 double res = score[src_idx];
268 if (res >= 0)
269 return res;
270 res = matched;
271 for (unsigned sign = 0; sign != 2; sign++) {
272 const unsigned signed_src_lit = src_lit ^ sign;
273 watches *const watches = &WATCHES (signed_src_lit);
274 uint64_t ticks =
275 1 + kissat_cache_lines (SIZE_WATCHES (*watches), sizeof (watch));
277 if (watch.type.binary) {
278 const unsigned other = watch.binary.lit;
279 res += distinct_paths (factoring, other, dst_idx, next_hops);
280 } else {
281 const reference ref = watch.large.ref;
282 clause *c = kissat_dereference_clause (solver, ref);
283 ticks++;
284 for (all_literals_in_clause (other, c))
285 if (other != signed_src_lit)
286 res += distinct_paths (factoring, other, dst_idx, next_hops);
287 }
288 }
289 ADD (factor_ticks, ticks);
290 }
291 KISSAT_assert (res >= 0);
292 score[src_idx] = res;
293 unsigneds *scored = &scores->scored;
294 PUSH_STACK (*scored, src_idx);
295 LOG ("caching %g distinct paths from %s to %s in %u hops", res,
296 LOGVAR (src_idx), LOGVAR (dst_idx), hops);
297 return res;
298}
299
300static double structural_score (factoring *factoring, unsigned lit) {
301 const quotient *first_quotient = factoring->quotients.first;
302 KISSAT_assert (first_quotient);
303 const unsigned first_factor = first_quotient->factor;
304#ifndef KISSAT_NDEBUG
305 kissat *const solver = factoring->solver;
306#endif
307 const unsigned first_factor_idx = IDX (first_factor);
308 return distinct_paths (factoring, lit, first_factor_idx, factoring->hops);
309}
310
311static double watches_score (factoring *factoring, unsigned lit) {
312 kissat *const solver = factoring->solver;
313 watches *watches = solver->watches + lit;
314 double res = SIZE_WATCHES (*watches);
315 LOG ("watches score %g of %s", res, LOGLIT (lit));
316 return res;
317}
318
319static double tied_next_factor_score (factoring *factoring, unsigned lit) {
320 if (factoring->hops)
321 return structural_score (factoring, lit);
322 else
323 return watches_score (factoring, lit);
324}
325
326static unsigned next_factor (factoring *factoring,
327 unsigned *next_count_ptr) {
328 quotient *last_quotient = factoring->quotients.last;
329 KISSAT_assert (last_quotient);
330 statches *last_clauses = &last_quotient->clauses;
331 kissat *const solver = factoring->solver;
332 watches *all_watches = solver->watches;
333 unsigned *count = factoring->count;
334 unsigneds *counted = &factoring->counted;
335 references *qlauses = &factoring->qlauses;
336 KISSAT_assert (EMPTY_STACK (*counted));
337 KISSAT_assert (EMPTY_STACK (*qlauses));
338 ward *const arena = BEGIN_STACK (solver->arena);
339 mark *marks = solver->marks;
340 const unsigned initial = factoring->initial;
341 uint64_t ticks =
342 1 + kissat_cache_lines (SIZE_STACK (*last_clauses), sizeof (watch));
343 for (all_stack (watch, quotient_watch, *last_clauses)) {
344 if (quotient_watch.type.binary) {
345 const unsigned q = quotient_watch.binary.lit;
346 watches *q_watches = all_watches + q;
347 ticks += 1 + kissat_cache_lines (SIZE_WATCHES (*q_watches),
348 sizeof (watch));
349 for (all_binary_large_watches (next_watch, *q_watches)) {
350 if (!next_watch.type.binary)
351 continue;
352 const unsigned next = next_watch.binary.lit;
353 if (next > initial)
354 continue;
355 if (marks[next] & FACTOR)
356 continue;
357 const unsigned next_idx = IDX (next);
358 if (!ACTIVE (next_idx))
359 continue;
360 if (!count[next])
361 PUSH_STACK (*counted, next);
362 count[next]++;
363 }
364 } else {
365 const reference c_ref = quotient_watch.large.ref;
366 clause *const c = (clause *) (arena + c_ref);
368 unsigned min_lit = INVALID_LIT, factors = 0;
369 size_t min_size = 0;
370 ticks++;
371 for (all_literals_in_clause (other, c)) {
372 if (marks[other] & FACTOR) {
373 if (factors++)
374 break;
375 } else {
376 KISSAT_assert (!(marks[other] & QUOTIENT));
377 marks[other] |= QUOTIENT;
378 watches *other_watches = all_watches + other;
379 const size_t other_size = SIZE_WATCHES (*other_watches);
380 if (min_lit != INVALID_LIT && min_size <= other_size)
381 continue;
382 min_lit = other;
383 min_size = other_size;
384 }
385 }
386 KISSAT_assert (factors);
387 if (factors == 1) {
388 KISSAT_assert (min_lit != INVALID_LIT);
389 watches *min_watches = all_watches + min_lit;
390 unsigned c_size = c->size;
391 unsigneds *nounted = &factoring->nounted;
392 KISSAT_assert (EMPTY_STACK (*nounted));
393 ticks += 1 + kissat_cache_lines (SIZE_WATCHES (*min_watches),
394 sizeof (watch));
395 for (all_binary_large_watches (min_watch, *min_watches)) {
396 if (min_watch.type.binary)
397 continue;
398 const reference d_ref = min_watch.large.ref;
399 if (c_ref == d_ref)
400 continue;
401 clause *const d = (clause *) (arena + d_ref);
402 ticks++;
403 if (d->quotient)
404 continue;
405 if (d->size != c_size)
406 continue;
407 unsigned next = INVALID_LIT;
408 int continue_with_next_min_watch = 0;
409 for (all_literals_in_clause (other, d)) {
410 const mark mark = marks[other];
411 if (mark & QUOTIENT)
412 continue;
413 if (mark & FACTOR) {
414 continue_with_next_min_watch = 1;
415 break;
416 }
417 if (mark & NOUNTED) {
418 continue_with_next_min_watch = 1;
419 break;
420 }
421 if (next != INVALID_LIT) {
422 continue_with_next_min_watch = 1;
423 break;
424 }
425 next = other;
426 }
427 if(continue_with_next_min_watch) {
428 continue;
429 }
430 KISSAT_assert (next != INVALID_LIT);
431 if (next > initial)
432 continue;
433 const unsigned next_idx = IDX (next);
434 if (!ACTIVE (next_idx))
435 continue;
436 KISSAT_assert (!(marks[next] & (FACTOR | NOUNTED)));
437 marks[next] |= NOUNTED;
438 PUSH_STACK (*nounted, next);
439 d->quotient = true;
440 PUSH_STACK (*qlauses, d_ref);
441 if (!count[next])
442 PUSH_STACK (*counted, next);
443 count[next]++;
444 }
445 clear_nounted (solver, nounted);
446 }
447 for (all_literals_in_clause (other, c))
448 marks[other] &= ~QUOTIENT;
449 }
450 ADD (factor_ticks, ticks);
451 ticks = 0;
452 if (solver->statistics_.factor_ticks > factoring->limit)
453 break;
454 }
455 clear_qlauses (solver, qlauses);
456 unsigned next_count = 0, next = INVALID_LIT;
457 if (solver->statistics_.factor_ticks <= factoring->limit) {
458 unsigned ties = 0;
459 for (all_stack (unsigned, lit, *counted)) {
460 const unsigned lit_count = count[lit];
461 if (lit_count < next_count)
462 continue;
463 if (lit_count == next_count) {
464 KISSAT_assert (lit_count);
465 ties++;
466 } else {
467 KISSAT_assert (lit_count > next_count);
468 next_count = lit_count;
469 next = lit;
470 ties = 1;
471 }
472 }
473 if (next_count < 2) {
474 LOG ("next factor count %u smaller than 2", next_count);
475 next = INVALID_LIT;
476 } else if (ties > 1) {
477 LOG ("found %u tied next factor candidate literals with count %u",
478 ties, next_count);
479 double next_score = -1;
480 for (all_stack (unsigned, lit, *counted)) {
481 const unsigned lit_count = count[lit];
482 if (lit_count != next_count)
483 continue;
484 double lit_score = tied_next_factor_score (factoring, lit);
485 KISSAT_assert (lit_score >= 0);
486 LOG ("score %g of next factor candidate %s", lit_score,
487 LOGLIT (lit));
488 if (lit_score <= next_score)
489 continue;
490 next_score = lit_score;
491 next = lit;
492 }
493 KISSAT_assert (next_score >= 0);
494 KISSAT_assert (next != INVALID_LIT);
495 LOG ("best score %g of next factor %s", next_score, LOGLIT (next));
496 } else {
497 KISSAT_assert (ties == 1);
498 LOG ("single next factor %s with count %u", LOGLIT (next),
499 next_count);
500 }
501 }
502 for (all_stack (unsigned, lit, *counted))
503 count[lit] = 0;
504 CLEAR_STACK (*counted);
505 KISSAT_assert (next == INVALID_LIT || next_count > 1);
506 *next_count_ptr = next_count;
507 return next;
508}
509
510static void factorize_next (factoring *factoring, unsigned next,
511 unsigned expected_next_count) {
512 quotient *last_quotient = factoring->quotients.last;
513 quotient *next_quotient = new_quotient (factoring, next);
514
515 kissat *const solver = factoring->solver;
516 watches *all_watches = solver->watches;
517 ward *const arena = BEGIN_STACK (solver->arena);
518 mark *marks = solver->marks;
519
520 KISSAT_assert (last_quotient);
521 statches *last_clauses = &last_quotient->clauses;
522 statches *next_clauses = &next_quotient->clauses;
523 sizes *matches = &next_quotient->matches;
524 references *qlauses = &factoring->qlauses;
525 KISSAT_assert (EMPTY_STACK (*qlauses));
526
527 uint64_t ticks =
528 1 + kissat_cache_lines (SIZE_STACK (*last_clauses), sizeof (watch));
529
530 size_t i = 0;
531
532 for (all_stack (watch, last_watch, *last_clauses)) {
533 if (last_watch.type.binary) {
534 const unsigned q = last_watch.binary.lit;
535 watches *q_watches = all_watches + q;
536 ticks += 1 + kissat_cache_lines (SIZE_WATCHES (*q_watches),
537 sizeof (watch));
538 for (all_binary_large_watches (q_watch, *q_watches))
539 if (q_watch.type.binary && q_watch.binary.lit == next) {
540 LOGBINARY (last_quotient->factor, q, "matched");
541 LOGBINARY (next, q, "keeping");
542 PUSH_STACK (*next_clauses, last_watch);
543 PUSH_STACK (*matches, i);
544 break;
545 }
546 } else {
547 const reference c_ref = last_watch.large.ref;
548 clause *const c = (clause *) (arena + c_ref);
550 unsigned min_lit = INVALID_LIT, factors = 0;
551 size_t min_size = 0;
552 ticks++;
553 for (all_literals_in_clause (other, c)) {
554 if (marks[other] & FACTOR) {
555 if (factors++)
556 break;
557 } else {
558 KISSAT_assert (!(marks[other] & QUOTIENT));
559 marks[other] |= QUOTIENT;
560 watches *other_watches = all_watches + other;
561 const size_t other_size = SIZE_WATCHES (*other_watches);
562 if (min_lit != INVALID_LIT && min_size <= other_size)
563 continue;
564 min_lit = other;
565 min_size = other_size;
566 }
567 }
568 KISSAT_assert (factors);
569 if (factors == 1) {
570 KISSAT_assert (min_lit != INVALID_LIT);
571 watches *min_watches = all_watches + min_lit;
572 unsigned c_size = c->size;
573 ticks += 1 + kissat_cache_lines (SIZE_WATCHES (*min_watches),
574 sizeof (watch));
575 for (all_binary_large_watches (min_watch, *min_watches)) {
576 if (min_watch.type.binary)
577 continue;
578 const reference d_ref = min_watch.large.ref;
579 if (c_ref == d_ref)
580 continue;
581 clause *const d = (clause *) (arena + d_ref);
582 ticks++;
583 if (d->quotient)
584 continue;
585 if (d->size != c_size)
586 continue;
587 for (all_literals_in_clause (other, d)) {
588 const mark mark = marks[other];
589 if (mark & QUOTIENT)
590 continue;
591 if (other != next)
592 goto CONTINUE_WITH_NEXT_MIN_WATCH;
593 }
594 LOGCLS (c, "matched");
595 LOGCLS (d, "keeping");
596 PUSH_STACK (*next_clauses, min_watch);
597 PUSH_STACK (*matches, i);
598 PUSH_STACK (*qlauses, d_ref);
599 d->quotient = true;
600 break;
601 CONTINUE_WITH_NEXT_MIN_WATCH:;
602 }
603 }
604 for (all_literals_in_clause (other, c))
605 marks[other] &= ~QUOTIENT;
606 }
607 i++;
608 }
609
610 clear_qlauses (solver, qlauses);
611 ADD (factor_ticks, ticks);
612
613 KISSAT_assert (expected_next_count <= SIZE_STACK (*next_clauses));
614 (void) expected_next_count;
615}
616
617static quotient *best_quotient (factoring *factoring,
618 size_t *best_reduction_ptr) {
619 size_t factors = 1, best_reduction = 0;
620 quotient *best = 0;
621 kissat *const solver = factoring->solver;
622 for (quotient *q = factoring->quotients.first; q; q = q->next) {
623 size_t quotients = SIZE_STACK (q->clauses);
624 size_t before_factorization = quotients * factors;
625 size_t after_factorization = quotients + factors;
626 if (before_factorization == after_factorization)
627 LOG ("quotient[%zu] factors %zu clauses into %zu thus no change",
628 factors - 1, before_factorization, after_factorization);
629 else if (before_factorization < after_factorization)
630 LOG ("quotient[%zu] factors %zu clauses into %zu thus %zu more",
631 factors - 1, before_factorization, after_factorization,
632 after_factorization - before_factorization);
633 else {
634 size_t delta = before_factorization - after_factorization;
635 LOG ("quotient[%zu] factors %zu clauses into %zu thus %zu less",
636 factors - 1, before_factorization, after_factorization, delta);
637 if (!best || best_reduction < delta) {
638 best_reduction = delta;
639 best = q;
640 }
641 }
642 factors++;
643 }
644 if (!best) {
645 LOG ("no decreasing quotient found");
646 return 0;
647 }
648 LOG ("best decreasing quotient[%zu] with reduction %zu", best->id,
649 best_reduction);
650 *best_reduction_ptr = best_reduction;
651 (void) solver;
652 return best;
653}
654
655static void resize_factoring (factoring *factoring, unsigned lit) {
656 kissat *const solver = factoring->solver;
657 KISSAT_assert (lit > NOT (lit));
658 const size_t old_size = factoring->size;
659 KISSAT_assert (lit > old_size);
660 const size_t old_allocated = factoring->allocated;
661 size_t new_size = lit + 1;
662 if (new_size > old_allocated) {
663 size_t new_allocated = 2 * old_allocated;
664 while (new_size > new_allocated)
665 new_allocated *= 2;
666 unsigned *count = factoring->count;
667 count = (unsigned*)kissat_nrealloc (solver, count, old_allocated, new_allocated,
668 sizeof *count);
669 const size_t delta_allocated = new_allocated - old_allocated;
670 const size_t delta_bytes = delta_allocated * sizeof *count;
671 memset (count + old_size, 0, delta_bytes);
672 factoring->count = count;
673 KISSAT_assert (!(old_allocated & 1));
674 KISSAT_assert (!(new_allocated & 1));
675 const size_t old_allocated_score = old_allocated / 2;
676 const size_t new_allocated_score = new_allocated / 2;
677 for (unsigned i = 0; i != factoring->hops; i++) {
679 double *score = scores->score;
680 score = (double*)kissat_nrealloc (solver, score, old_allocated_score,
681 new_allocated_score, sizeof *score);
682 for (size_t i = old_allocated_score; i != new_allocated_score; i++)
683 score[i] = -1;
684 scores->score = score;
685 }
686 factoring->allocated = new_allocated;
687 }
688 factoring->size = new_size;
689}
690
691static void flush_unmatched_clauses (kissat *solver, quotient *q) {
692 quotient *prev = q->prev;
693 sizes *q_matches = &q->matches, *prev_matches = &prev->matches;
694 statches *q_clauses = &q->clauses, *prev_clauses = &prev->clauses;
695 const size_t n = SIZE_STACK (*q_clauses);
696 KISSAT_assert (n == SIZE_STACK (*q_matches));
697 bool prev_is_first = !prev->id;
698 size_t i = 0;
699 while (i != n) {
700 size_t j = PEEK_STACK (*q_matches, i);
701 KISSAT_assert (i <= j);
702 if (!prev_is_first) {
703 size_t matches = PEEK_STACK (*prev_matches, j);
704 POKE_STACK (*prev_matches, i, matches);
705 }
706 watch watch = PEEK_STACK (*prev_clauses, j);
707 POKE_STACK (*prev_clauses, i, watch);
708 i++;
709 }
710 LOG ("flushing %zu clauses of quotient[%zu]",
711 SIZE_STACK (*prev_clauses) - n, prev->id);
712 if (!prev_is_first)
713 RESIZE_STACK (*prev_matches, n);
714 RESIZE_STACK (*prev_clauses, n);
715 (void) solver;
716}
717
718static void add_factored_divider (factoring *factoring, quotient *q,
719 unsigned fresh) {
720 const unsigned factor = q->factor;
721 kissat *const solver = factoring->solver;
722 LOGBINARY (fresh, factor, "factored %s divider", LOGLIT (factor));
724 INC (clauses_factored);
725 ADD (literals_factored, 2);
726}
727
728static void add_factored_quotient (factoring *factoring, quotient *q,
729 unsigned not_fresh) {
730 kissat *const solver = factoring->solver;
731 LOG ("adding factored quotient[%zu] clauses", q->id);
732 for (all_stack (watch, watch, q->clauses)) {
733 if (watch.type.binary) {
734 const unsigned other = watch.binary.lit;
735 LOGBINARY (not_fresh, other, "factored quotient");
736 kissat_new_binary_clause (solver, not_fresh, other);
737 ADD (literals_factored, 2);
738 } else {
739 const reference c_ref = watch.large.ref;
740 clause *const c = kissat_dereference_clause (solver, c_ref);
741 unsigneds *clause = &solver->clause;
743 const unsigned factor = q->factor;
744#ifndef KISSAT_NDEBUG
745 bool found = false;
746#endif
747 PUSH_STACK (*clause, not_fresh);
748 for (all_literals_in_clause (other, c)) {
749 if (other == factor) {
750#ifndef KISSAT_NDEBUG
751 found = true;
752#endif
753 continue;
754 }
755 PUSH_STACK (*clause, other);
756 }
757 KISSAT_assert (found);
758 ADD (literals_factored, c->size);
761 }
762 INC (clauses_factored);
763 }
764}
765
766static void eagerly_remove_watch (kissat *solver, watches *watches,
767 watch needle) {
769 watch *end = END_WATCHES (*watches);
770 KISSAT_assert (p != end);
771 watch *last = end - 1;
772 while (p->raw != needle.raw)
773 p++, KISSAT_assert (p != end);
774 if (p != last)
775 memmove (p, p + 1, (last - p) * sizeof *p);
777}
778
779static void eagerly_remove_binary (kissat *solver, watches *watches,
780 unsigned lit) {
781 const watch needle = kissat_binary_watch (lit);
782 eagerly_remove_watch (solver, watches, needle);
783}
784
785static void delete_unfactored (factoring *factoring, quotient *q) {
786 kissat *const solver = factoring->solver;
787 LOG ("deleting unfactored quotient[%zu] clauses", q->id);
788 const unsigned factor = q->factor;
789 for (all_stack (watch, watch, q->clauses)) {
790 if (watch.type.binary) {
791 const unsigned other = watch.binary.lit;
792 LOGBINARY (factor, other, "deleting unfactored");
793 eagerly_remove_binary (solver, &WATCHES (other), factor);
794 eagerly_remove_binary (solver, &WATCHES (factor), other);
796 ADD (literals_unfactored, 2);
797 } else {
798 const reference ref = watch.large.ref;
799 clause *c = kissat_dereference_clause (solver, ref);
800 LOGCLS (c, "deleting unfactored");
801 for (all_literals_in_clause (lit, c))
802 eagerly_remove_watch (solver, &WATCHES (lit), watch);
804 ADD (literals_unfactored, c->size);
805 }
806 INC (clauses_unfactored);
807 }
808}
809
810static void update_factored (factoring *factoring, quotient *q) {
811 kissat *const solver = factoring->solver;
812 const unsigned factor = q->factor;
813 update_candidate (factoring, factor);
814 update_candidate (factoring, NOT (factor));
815 for (all_stack (watch, watch, q->clauses)) {
816 if (watch.type.binary) {
817 const unsigned other = watch.binary.lit;
818 update_candidate (factoring, other);
819 } else {
820 const reference ref = watch.large.ref;
821 clause *c = kissat_dereference_clause (solver, ref);
822 LOGCLS (c, "deleting unfactored");
823 for (all_literals_in_clause (lit, c))
824 if (lit != factor)
825 update_candidate (factoring, lit);
826 }
827 }
828}
829
830static bool apply_factoring (factoring *factoring, quotient *q) {
831 kissat *const solver = factoring->solver;
832 const unsigned fresh = kissat_fresh_literal (solver);
833 if (fresh == INVALID_LIT)
834 return false;
835 INC (factored);
836 PUSH_STACK (factoring->fresh, fresh);
837 for (quotient *p = q; p->prev; p = p->prev)
838 flush_unmatched_clauses (solver, p);
839 for (quotient *p = q; p; p = p->prev)
840 add_factored_divider (factoring, p, fresh);
841 const unsigned not_fresh = NOT (fresh);
842 add_factored_quotient (factoring, q, not_fresh);
843 for (quotient *p = q; p; p = p->prev)
844 delete_unfactored (factoring, p);
845 for (quotient *p = q; p; p = p->prev)
846 update_factored (factoring, p);
847 KISSAT_assert (fresh < not_fresh);
848 resize_factoring (factoring, not_fresh);
849 return true;
850}
851
852static void
853adjust_scores_and_phases_of_fresh_varaibles (factoring *factoring) {
854 const unsigned *begin = BEGIN_STACK (factoring->fresh);
855 const unsigned *end = END_STACK (factoring->fresh);
856 kissat *const solver = factoring->solver;
857 {
858 const unsigned *p = begin;
859 while (p != end) {
860 const unsigned lit = *p++;
861 const unsigned idx = IDX (lit);
862 LOG ("unbumping fresh[%zu] %s", (size_t) (p - begin - 1),
863 LOGVAR (idx));
864 const double score = 0;
865 kissat_update_heap (solver, &solver->scores, idx, score);
866 }
867 }
868 {
869 const unsigned *p = end;
870 links *links = solver->links;
871 queue *queue = &solver->queue;
872 while (p != begin) {
873 const unsigned lit = *--p;
874 const unsigned idx = IDX (lit);
875 kissat_dequeue_links (idx, links, queue);
876 }
877 queue->stamp = 0;
878 unsigned rest = queue->first;
879 p = end;
880 while (p != begin) {
881 const unsigned lit = *--p;
882 const unsigned idx = IDX (lit);
883 struct links *l = links + idx;
884 if (DISCONNECTED (queue->first)) {
886 queue->last = idx;
887 } else {
888 struct links *first = links + queue->first;
890 first->prev = idx;
891 }
892 l->next = queue->first;
893 queue->first = idx;
895 l->stamp = ++queue->stamp;
896 }
897 while (!DISCONNECTED (rest)) {
898 struct links *l = links + rest;
899 l->stamp = ++queue->stamp;
900 rest = l->next;
901 }
902 solver->queue.search.idx = queue->last;
903 solver->queue.search.stamp = queue->stamp;
904 }
905}
906
907static bool run_factorization (kissat *solver, uint64_t limit) {
909 init_factoring (solver, &factoring, limit);
910 schedule_factorization (&factoring);
911 bool done = false;
912#ifndef KISSAT_QUIET
913 unsigned factored = 0;
914#endif
915 uint64_t *ticks = &solver->statistics_.factor_ticks;
917 solver, "factorization limit of %" PRIu64 " ticks", limit - *ticks);
918 while (!done && !kissat_empty_heap (&factoring.schedule)) {
919 const unsigned first =
920 kissat_pop_max_heap (solver, &factoring.schedule);
921 const unsigned first_idx = IDX (first);
922 if (!ACTIVE (first_idx))
923 continue;
924 if (*ticks > limit) {
925 kissat_very_verbose (solver, "factorization ticks limit hit");
926 break;
927 }
929 break;
930 struct flags *f = solver->flags + first_idx;
931 const unsigned bit = 1u << NEGATED (first);
932 if (!(f->factor & bit))
933 continue;
934 f->factor &= ~bit;
935 const size_t first_count = first_factor (&factoring, first);
936 if (first_count > 1) {
937 for (;;) {
938 unsigned next_count;
939 const unsigned next = next_factor (&factoring, &next_count);
940 if (next == INVALID_LIT)
941 break;
942 KISSAT_assert (next_count > 1);
943 if (next_count < 2)
944 break;
945 factorize_next (&factoring, next, next_count);
946 }
947 size_t reduction;
948 quotient *q = best_quotient (&factoring, &reduction);
949 if (q && reduction > factoring.bound) {
950 if (apply_factoring (&factoring, q)) {
951#ifndef KISSAT_QUIET
952 factored++;
953#endif
954 } else
955 done = true;
956 }
957 }
958 release_quotients (&factoring);
959 }
960 bool completed = kissat_empty_heap (&factoring.schedule);
961 adjust_scores_and_phases_of_fresh_varaibles (&factoring);
962 release_factoring (&factoring);
963 REPORT (!factored, 'f');
964 return completed;
965}
966
967static void connect_clauses_to_factor (kissat *solver) {
968 const unsigned size_limit = GET_OPTION (factorsize);
969 if (size_limit < 3) {
970 kissat_extremely_verbose (solver, "only factorizing binary clauses");
971 return;
972 }
973 kissat_very_verbose (solver, "factorizing clauses of maximum size %u",
974 size_limit);
975 clause *last_irredundant = kissat_last_irredundant_clause (solver);
976 ward *const arena = BEGIN_STACK (solver->arena);
977 watches *all_watches = solver->watches;
978 unsigned *bincount, *largecount;
979 CALLOC (unsigned, bincount, LITS);
980 for (all_literals (lit)) {
981 if (!ACTIVE (IDX (lit)))
982 continue;
985 const unsigned other = watch.type.lit;
986 if (lit > other)
987 continue;
988 bincount[lit]++;
989 bincount[other]++;
990 }
991 }
992 CALLOC (unsigned, largecount, LITS);
993 size_t initial_candidates = 0;
994 for (all_clauses (c)) {
995 if (c->garbage)
996 continue;
997 if (last_irredundant && last_irredundant < c)
998 break;
999 if (c->redundant)
1000 continue;
1001 if (c->size > size_limit)
1002 continue;
1003 for (all_literals_in_clause (lit, c))
1004 largecount[lit]++;
1005 initial_candidates++;
1006 }
1008 "initially found %zu large clause candidates",
1009 initial_candidates);
1010 size_t candidates = initial_candidates;
1011 const unsigned rounds = GET_OPTION (factorcandrounds);
1012 for (unsigned round = 1; round <= rounds; round++) {
1013 size_t new_candidates = 0;
1014 unsigned *newlargecount;
1015 CALLOC (unsigned, newlargecount, LITS);
1016 for (all_clauses (c)) {
1017 if (c->garbage)
1018 continue;
1019 if (last_irredundant && last_irredundant < c)
1020 break;
1021 if (c->redundant)
1022 continue;
1023 if (c->size > size_limit)
1024 continue;
1025 for (all_literals_in_clause (lit, c))
1026 if (bincount[lit] + largecount[lit] < 2)
1027 goto CONTINUE_WITH_NEXT_CLAUSE1;
1028 for (all_literals_in_clause (lit, c))
1029 newlargecount[lit]++;
1030 new_candidates++;
1031 CONTINUE_WITH_NEXT_CLAUSE1:;
1032 }
1033 DEALLOC (largecount, LITS);
1034 largecount = newlargecount;
1035 if (candidates == new_candidates) {
1037 "no large factorization candidate clauses "
1038 "reduction in round %u",
1039 round);
1040 break;
1041 }
1042 candidates = new_candidates;
1044 solver,
1045 "reduced to %zu large factorization candidate clauses %.0f%% in "
1046 "round %u",
1047 candidates, kissat_percent (candidates, initial_candidates), round);
1048 }
1049#ifndef KISSAT_QUIET
1050 size_t connected = 0;
1051#endif
1052 for (all_clauses (c)) {
1053 if (c->garbage)
1054 continue;
1055 if (last_irredundant && last_irredundant < c)
1056 break;
1057 if (c->redundant)
1058 continue;
1059 if (c->size > size_limit)
1060 continue;
1061 int continue_with_next_clause2 = 0;
1062 for (all_literals_in_clause (lit, c))
1063 if (bincount[lit] + largecount[lit] < 2) {
1064 continue_with_next_clause2 = 1;
1065 break;
1066 }
1067 if(continue_with_next_clause2) {
1068 continue;
1069 }
1070 const reference ref = (ward *) c - arena;
1071 kissat_inlined_connect_clause (solver, all_watches, c, ref);
1072#ifndef KISSAT_QUIET
1073 connected++;
1074#endif
1075 }
1076 DEALLOC (largecount, LITS);
1077 DEALLOC (bincount, LITS);
1079 solver, "connected %zu large factorization candidate clauses %.0f%%",
1080 connected, kissat_percent (candidates, initial_candidates));
1081}
1082
1084 KISSAT_assert (!solver->level);
1085 if (solver->inconsistent)
1086 return;
1087 if (!GET_OPTION (factor))
1088 return;
1089 statistics *s = &solver->statistics_;
1090 if (solver->limits.factor.marked >= s->literals_factor) {
1092 solver,
1093 "factorization skipped as no literals have been marked to be added "
1094 "(%" PRIu64 " < %" PRIu64,
1095 solver->limits.factor.marked, s->literals_factor);
1096 return;
1097 }
1098 START (factor);
1099 INC (factorizations);
1100 kissat_phase (solver, "factorization", GET (factorizations),
1101 "binary clause bounded variable addition");
1102 uint64_t limit = GET_OPTION (factoriniticks);
1103 if (s->factorizations > 1) {
1104 SET_EFFORT_LIMIT (tmp, factor, factor_ticks);
1105 limit = tmp;
1106 } else {
1108 "initially limiting to %" PRIu64
1109 " million factorization ticks",
1110 limit);
1111 limit *= 1e6;
1112 limit += s->factor_ticks;
1113 }
1114#ifndef KISSAT_QUIET
1115 struct {
1116 int64_t variables, binary, clauses, ticks;
1117 } before, after, delta;
1118 before.variables = s->variables_extension + s->variables_original;
1119 before.binary = BINARY_CLAUSES;
1120 before.clauses = IRREDUNDANT_CLAUSES;
1121 before.ticks = s->factor_ticks;
1122#endif
1124 connect_clauses_to_factor (solver);
1125 bool completed = run_factorization (solver, limit);
1127#ifndef KISSAT_QUIET
1128 after.variables = s->variables_extension + s->variables_original;
1129 after.binary = BINARY_CLAUSES;
1130 after.clauses = IRREDUNDANT_CLAUSES;
1131 after.ticks = s->factor_ticks;
1132 delta.variables = after.variables - before.variables;
1133 delta.binary = before.binary - after.binary;
1134 delta.clauses = before.clauses - after.clauses;
1135 delta.ticks = after.ticks - before.ticks;
1136 kissat_very_verbose (solver, "used %f million factorization ticks",
1137 delta.ticks * 1e-6);
1138 kissat_phase (solver, "factorization", GET (factorizations),
1139 "introduced %" PRId64 " extension variables %.0f%%",
1140 delta.variables,
1141 kissat_percent (delta.variables, before.variables));
1142 kissat_phase (solver, "factorization", GET (factorizations),
1143 "removed %" PRId64 " binary clauses %.0f%%", delta.binary,
1144 kissat_percent (delta.binary, before.binary));
1145 kissat_phase (solver, "factorization", GET (factorizations),
1146 "removed %" PRId64 " large clauses %.0f%%", delta.clauses,
1147 kissat_percent (delta.clauses, before.clauses));
1148#endif
1149 if (completed)
1150 solver->limits.factor.marked = s->literals_factor;
1151 STOP (factor);
1152}
1153
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
void * kissat_malloc(kissat *solver, size_t bytes)
Definition allocate.c:49
void kissat_free(kissat *solver, void *ptr, size_t bytes)
Definition allocate.c:61
void * kissat_nrealloc(kissat *solver, void *p, size_t o, size_t n, size_t size)
Definition allocate.c:151
#define NALLOC(T, P, N)
Definition allocate.h:24
ABC_NAMESPACE_HEADER_START typedef word ward
Definition arena.h:12
#define BEGIN_STACK(S)
Definition stack.h:46
#define RESIZE_STACK(S, NEW_SIZE)
Definition stack.h:55
#define POP_STACK(S)
Definition stack.h:37
#define POKE_STACK(S, N, E)
Definition stack.h:32
#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 END_STACK(S)
Definition stack.h:48
#define INVALID_LIT
#define QUOTIENT
#define NOUNTED
#define ADD(NAME, DELTA)
#define INC(NAME)
#define CALLOC(T, P, N)
#define LOG(...)
#define DEALLOC(P, N)
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_new_binary_clause(kissat *solver, unsigned first, unsigned second)
Definition clause.c:122
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
#define ACTIVE
Definition espresso.h:129
Cube * p
Definition exorList.c:222
#define FACTOR
Definition factor.c:24
void kissat_factor(kissat *solver)
Definition factor.c:1083
ABC_NAMESPACE_IMPL_START void kissat_release_heap(kissat *solver, heap *heap)
Definition heap.c:10
unsigned kissat_fresh_literal(kissat *solver)
Definition import.c:84
#define VARS
Definition internal.h:250
#define all_variables(IDX)
Definition internal.h:269
#define all_literals(LIT)
Definition internal.h:274
#define all_clauses(C)
Definition internal.h:279
#define LITS
Definition internal.h:251
#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 SET_EFFORT_LIMIT(LIMIT, NAME, THRESHHOLD)
Definition limit.hpp:131
#define LOGBINARY(...)
Definition logging.h:442
#define LOGCLS(...)
Definition logging.h:415
#define LOGLIT(...)
Definition logging.hpp:99
bool sign(Lit p)
Definition SolverTypes.h:63
unsigned short ref
Definition giaNewBdd.h:38
#define GET_OPTION(N)
Definition options.h:295
#define kissat_extremely_verbose(...)
Definition print.h:53
#define kissat_very_verbose(...)
Definition print.h:52
#define kissat_phase(...)
Definition print.h:48
#define STOP(P)
Definition profile.hpp:158
#define START(P)
Definition profile.hpp:150
#define DISCONNECTED(IDX)
Definition queue.h:8
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 NEGATED(LIT)
Definition literal.h:35
#define IDX(LIT)
Definition literal.h:28
#define NOT(LIT)
Definition literal.h:33
#define IRREDUNDANT_CLAUSES
Definition statistics.h:337
#define BINARY_CLAUSES
Definition statistics.h:340
#define GET(NAME)
Definition statistics.h:416
bool quotient
Definition clause.h:26
bool redundant
Definition clause.h:28
unsigned size
Definition clause.h:37
bool garbage
Definition clause.h:25
uint64_t limit
Definition factor.c:58
unsigned hops
Definition factor.c:52
scores * scores
Definition factor.c:51
struct factoring::@160277325255143145147274163211332332056211107037 quotients
unsigned initial
Definition factor.c:49
size_t size
Definition factor.c:48
references qlauses
Definition factor.c:57
quotient * first
Definition factor.c:60
unsigned bound
Definition factor.c:53
unsigneds nounted
Definition factor.c:56
unsigned * count
Definition factor.c:50
size_t allocated
Definition factor.c:48
kissat * solver
Definition factor.c:47
heap schedule
Definition factor.c:62
unsigneds counted
Definition factor.c:55
quotient * last
Definition factor.c:60
unsigneds fresh
Definition factor.c:54
Definition flags.h:11
unsigned factor
Definition flags.h:17
Definition heap.h:19
Definition queue.h:20
unsigned last
Definition queue.h:21
unsigned first
Definition queue.h:21
unsigned stamp
Definition queue.h:21
sizes matches
Definition factor.c:33
statches clauses
Definition factor.c:32
unsigned factor
Definition factor.c:31
struct quotient * prev
Definition factor.c:30
size_t id
Definition factor.c:29
struct quotient * next
Definition factor.c:30
size_t matched
Definition factor.c:34
unsigneds scored
Definition factor.c:41
double * score
Definition factor.c:40
#define TERMINATED(BIT)
Definition terminate.h:42
#define factor_terminated_1
Definition terminate.h:62
Definition watch.h:41
unsigned raw
Definition watch.h:46
large_watch large
Definition watch.h:45
watch_type type
Definition watch.h:42
binary_watch binary
Definition watch.h:43
char * memset()
char * memmove()
signed char mark
Definition value.h:8
#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 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