ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
walk.c
Go to the documentation of this file.
1#include "walk.h"
2#include "allocate.h"
3#include "decide.h"
4#include "dense.h"
5#include "inline.h"
6#include "phases.h"
7#include "print.h"
8#include "rephase.h"
9#include "report.h"
10#include "terminate.h"
11#include "warmup.h"
12
13#include <string.h>
14
16
17typedef struct tagged tagged;
18typedef struct counter counter;
19typedef struct walker walker;
20
21#define LD_MAX_WALK_REF 31
22#define MAX_WALK_REF ((1u << LD_MAX_WALK_REF) - 1)
23
24struct tagged {
25 unsigned ref : LD_MAX_WALK_REF;
26 bool binary : 1;
27};
28
29static inline tagged make_tagged (bool binary, unsigned ref) {
31 tagged res = {.ref = ref, .binary = binary};
32 return res;
33}
34
35struct counter {
36 unsigned count;
37 unsigned pos;
38};
39
40// clang-format off
41typedef STACK (double) doubles;
42// clang-format on
43
44#define INVALID_BEST_TRAIL_POS UINT_MAX
45
46struct walker {
48
49 unsigned best_trail_pos;
50 unsigned clauses;
51 unsigned current;
52 unsigned exponents;
53 unsigned initial;
54 unsigned minimum;
55 unsigned offset;
56
58
59 counter *counters;
60 litpairs *binaries;
61 tagged *refs;
62 double *table;
63
64 value *original_values;
65 value *best_values;
66
67 doubles scores;
68 unsigneds unsat;
69 unsigneds trail;
70
71 double size;
72 double epsilon;
73
74 uint64_t limit;
75 uint64_t flipped;
76#ifndef KISSAT_QUIET
77 uint64_t start;
78 struct {
79 uint64_t flipped;
80 unsigned minimum;
81 } report;
82#endif
83};
84
85static const unsigned *dereference_literals (kissat *solver, walker *walker,
86 unsigned counter_ref,
87 unsigned *size_ptr) {
88 KISSAT_assert (counter_ref < walker->clauses);
89 tagged tagged = walker->refs[counter_ref];
90 unsigned const *lits;
91 if (tagged.binary) {
92 const unsigned binary_ref = tagged.ref;
93 lits = PEEK_STACK (*walker->binaries, binary_ref).lits;
94 *size_ptr = 2;
95 } else {
96 const reference clause_ref = tagged.ref;
97 clause *c = kissat_dereference_clause (solver, clause_ref);
98 *size_ptr = c->size;
99 lits = c->lits;
100 }
101 return lits;
102}
103
104static void push_unsat (kissat *solver, walker *walker, counter *counters,
105 unsigned counter_ref) {
106 KISSAT_assert (counter_ref < walker->clauses);
107 counter *counter = counters + counter_ref;
108 KISSAT_assert (SIZE_STACK (walker->unsat) <= UINT_MAX);
109 counter->pos = SIZE_STACK (walker->unsat);
110 PUSH_STACK (walker->unsat, counter_ref);
111#ifdef LOGGING
112 unsigned size;
113 const unsigned *const lits =
114 dereference_literals (solver, walker, counter_ref, &size);
115 LOGLITS (size, lits, "pushed unsatisfied[%u]", counter->pos);
116#endif
117}
118
119static bool pop_unsat (kissat *solver, walker *walker, counter *counters,
120 unsigned counter_ref, unsigned pos) {
121 KISSAT_assert (walker->current);
122 KISSAT_assert (counter_ref < walker->clauses);
123 KISSAT_assert (counters[counter_ref].pos == pos);
124 KISSAT_assert (walker->current == SIZE_STACK (walker->unsat));
125 const unsigned other_counter_ref = POP_STACK (walker->unsat);
126 walker->current--;
127 bool res = false;
128 if (counter_ref != other_counter_ref) {
129 KISSAT_assert (other_counter_ref < walker->clauses);
130 counter *other_counter = counters + other_counter_ref;
131 KISSAT_assert (other_counter->pos == walker->current);
133 other_counter->pos = pos;
134 POKE_STACK (walker->unsat, pos, other_counter_ref);
135 res = true;
136 }
137#ifdef LOGGING
138 unsigned size;
139 const unsigned *const lits =
140 dereference_literals (solver, walker, counter_ref, &size);
141 LOGLITS (size, lits, "popped unsatisfied[%u]", pos);
142#else
143 (void) solver;
144#endif
145 return res;
146}
147
148static double cbvals[][2] = {{0.0, 2.00}, {3.0, 2.50}, {4.0, 2.85},
149 {5.0, 3.70}, {6.0, 5.10}, {7.0, 7.40}};
150
151static double fit_cbval (double size) {
152 const size_t num_cbvals = sizeof cbvals / sizeof *cbvals;
153 size_t i = 0;
154 while (i + 2 < num_cbvals &&
155 (cbvals[i][0] > size || cbvals[i + 1][0] < size))
156 i++;
157 const double x2 = cbvals[i + 1][0], x1 = cbvals[i][0];
158 const double y2 = cbvals[i + 1][1], y1 = cbvals[i][1];
159 const double dx = x2 - x1, dy = y2 - y1;
160 KISSAT_assert (dx);
161 const double res = dy * (size - x1) / dx + y1;
162 KISSAT_assert (res > 0);
163 return res;
164}
165
166static void init_score_table (walker *walker) {
167 kissat *solver = walker->solver;
168
169 const double cb = (GET (walks) & 1) ? fit_cbval (walker->size) : 2.0;
170 const double base = 1 / cb;
171
172 double next;
173 unsigned exponents = 0;
174 for (next = 1; next; next *= base)
175 exponents++;
176
177 walker->table = (double*)kissat_malloc (solver, exponents * sizeof (double));
178
179 unsigned i = 0;
180 double epsilon;
181 for (epsilon = next = 1; next; next = epsilon * base)
182 walker->table[i++] = epsilon = next;
183
184 KISSAT_assert (i == exponents);
185 walker->exponents = exponents;
186 walker->epsilon = epsilon;
187
188 kissat_phase (solver, "walk", GET (walks),
189 "CB %.2f with inverse %.2f as base", cb, base);
190 kissat_phase (solver, "walk", GET (walks), "table size %u and epsilon %g",
191 exponents, epsilon);
192}
193
194static unsigned currently_unsatified (walker *walker) {
195 return SIZE_STACK (walker->unsat);
196}
197
198static void import_decision_phases (walker *walker) {
199 kissat *solver = walker->solver;
200 INC (walk_decisions);
201 const flags *const flags = solver->flags;
202 value *values = solver->values;
203 walker->best_values = (value*)kissat_calloc (solver, VARS, 1);
204 value *best_values = walker->best_values;
205#ifndef KISSAT_QUIET
206 unsigned imported = 0;
207#endif
208 for (all_variables (idx)) {
209 if (!flags[idx].active)
210 continue;
213 best_values[idx] = value;
214 const unsigned lit = LIT (idx);
215 const unsigned not_lit = NOT (lit);
216 values[lit] = value;
217 values[not_lit] = -value;
218#ifndef KISSAT_QUIET
219 imported++;
220#endif
221 LOG ("copied %s decision phase %d", LOGVAR (idx), (int) value);
222 }
223 kissat_phase (solver, "walk", GET (walks),
224 "imported %u decision phases %.0f%%", imported,
225 kissat_percent (imported, solver->active));
226}
227
228static unsigned connect_binary_counters (walker *walker) {
229 kissat *solver = walker->solver;
230 value *values = solver->values;
231 tagged *refs = walker->refs;
232 watches *all_watches = solver->watches;
233 counter *counters = walker->counters;
234
235 KISSAT_assert (SIZE_STACK (*walker->binaries) <= UINT_MAX);
236 const unsigned size = SIZE_STACK (*walker->binaries);
237 litpair *binaries = BEGIN_STACK (*walker->binaries);
238 unsigned unsat = 0, counter_ref = 0;
239
240 for (unsigned binary_ref = 0; binary_ref < size; binary_ref++) {
241 const litpair *const litpair = binaries + binary_ref;
242 const unsigned first = litpair->lits[0];
243 const unsigned second = litpair->lits[1];
244 KISSAT_assert (first < LITS), KISSAT_assert (second < LITS);
245 const value first_value = values[first];
246 const value second_value = values[second];
247 if (!first_value || !second_value)
248 continue;
249 KISSAT_assert (counter_ref < walker->clauses);
250 refs[counter_ref] = make_tagged (true, binary_ref);
251 watches *first_watches = all_watches + first;
252 watches *second_watches = all_watches + second;
253 kissat_push_large_watch (solver, first_watches, counter_ref);
254 kissat_push_large_watch (solver, second_watches, counter_ref);
255 const unsigned count = (first_value > 0) + (second_value > 0);
256 counter *counter = counters + counter_ref;
257 counter->count = count;
258 if (!count) {
259 push_unsat (solver, walker, counters, counter_ref);
260 unsat++;
261 }
262 counter_ref++;
263 }
264 kissat_phase (solver, "walk", GET (walks),
265 "initially %u unsatisfied binary clauses %.0f%% out of %u",
266 unsat, kissat_percent (unsat, counter_ref), counter_ref);
267#ifdef KISSAT_QUIET
268 (void) unsat;
269#endif
270 walker->size += 2.0 * counter_ref;
271 return counter_ref;
272}
273
274static void connect_large_counters (walker *walker, unsigned counter_ref) {
275 kissat *solver = walker->solver;
276 KISSAT_assert (!solver->level);
277 const value *const original_values = walker->original_values;
278 const value *const local_search_values = solver->values;
279 ward *const arena = BEGIN_STACK (solver->arena);
280 counter *counters = walker->counters;
281 tagged *refs = walker->refs;
282
283 unsigned unsat = 0;
284 unsigned large = 0;
285
286 clause *last_irredundant = kissat_last_irredundant_clause (solver);
287
288 for (all_clauses (c)) {
289 if (last_irredundant && c > last_irredundant)
290 break;
291 if (c->garbage)
292 continue;
293 if (c->redundant)
294 continue;
295 bool continue_with_next_clause = false;
296 for (all_literals_in_clause (lit, c)) {
297 const value value = original_values[lit];
298 if (value <= 0)
299 continue;
300 LOGCLS (c, "%s satisfied", LOGLIT (lit));
302 KISSAT_assert (c->garbage);
303 continue_with_next_clause = true;
304 break;
305 }
306 if (continue_with_next_clause)
307 continue;
308 large++;
309 KISSAT_assert (kissat_clause_in_arena (solver, c));
310 reference clause_ref = (ward *) c - arena;
311 KISSAT_assert (clause_ref <= MAX_WALK_REF);
312 KISSAT_assert (counter_ref < walker->clauses);
313 refs[counter_ref] = make_tagged (false, clause_ref);
314 unsigned count = 0, size = 0;
315 for (all_literals_in_clause (lit, c)) {
316 const value value = local_search_values[lit];
317 if (!value) {
318 KISSAT_assert (original_values[lit] < 0);
319 continue;
320 }
322 kissat_push_large_watch (solver, watches, counter_ref);
323 size++;
324 if (value > 0)
325 count++;
326 }
327 counter *counter = walker->counters + counter_ref;
328 counter->count = count;
329
330 if (!count) {
331 push_unsat (solver, walker, counters, counter_ref);
332 unsat++;
333 }
334 counter_ref++;
335 walker->size += size;
336 }
337 kissat_phase (solver, "walk", GET (walks),
338 "initially %u unsatisfied large clauses %.0f%% out of %u",
339 unsat, kissat_percent (unsat, large), large);
340#ifdef KISSAT_QUIET
341 (void) large;
342 (void) unsat;
343#endif
344}
345
346#ifndef KISSAT_QUIET
347
349 walker->report.minimum = walker->minimum;
350 kissat_very_verbose (solver, "initial minimum of %u unsatisfied clauses",
351 walker->minimum);
352}
353
354static void report_minimum (const char *type, kissat *solver,
355 walker *walker) {
356 KISSAT_assert (walker->minimum <= walker->report.minimum);
358 "%s minimum of %u unsatisfied clauses after %" PRIu64
359 " flipped literals",
360 type, walker->minimum, walker->flipped);
361 walker->report.minimum = walker->minimum;
362}
363#else
364#define report_initial_minimum(...) \
365 do { \
366 } while (0)
367#define report_minimum(...) \
368 do { \
369 } while (0)
370#endif
371
372static void init_walker (kissat *solver, walker *walker,
373 litpairs *binaries) {
374 uint64_t clauses = BINIRR_CLAUSES;
375 KISSAT_assert (clauses <= MAX_WALK_REF);
376
377 memset (walker, 0, sizeof *walker);
378
379 walker->solver = solver;
380 walker->clauses = clauses;
381 walker->binaries = binaries;
382 walker->random = solver->random ^ solver->statistics_.walks;
383
384 walker->original_values = solver->values;
385 solver->values = (value*)kissat_calloc (solver, LITS, 1);
386
387 import_decision_phases (walker);
388
389 walker->counters = (counter*)kissat_malloc (solver, clauses * sizeof (counter));
390 walker->refs = (tagged*)kissat_malloc (solver, clauses * sizeof (tagged));
391
392 KISSAT_assert (!walker->size);
393 const unsigned counter_ref = connect_binary_counters (walker);
394 connect_large_counters (walker, counter_ref);
395
396 walker->current = walker->initial = currently_unsatified (walker);
397
398 kissat_phase (solver, "walk", GET (walks),
399 "initially %u unsatisfied irredundant clauses %.0f%% "
400 "out of %" PRIu64,
401 walker->initial, kissat_percent (walker->initial, clauses),
402 clauses);
403
404 walker->size = kissat_average (walker->size, clauses);
405 kissat_phase (solver, "walk", GET (walks), "average clause size %.2f",
406 walker->size);
407
408 walker->minimum = walker->current;
409 init_score_table (walker);
410
412}
413
414static void init_walker_limit (kissat *solver, walker *walker) {
415 SET_EFFORT_LIMIT (limit, walk, walk_steps);
416 walker->limit = limit;
417 walker->flipped = 0;
418#ifndef KISSAT_QUIET
419 walker->start = solver->statistics_.walk_steps;
420 walker->report.minimum = UINT_MAX;
421 walker->report.flipped = 0;
422#endif
423}
424
425static void release_walker (walker *walker) {
426 kissat *solver = walker->solver;
427 kissat_dealloc (solver, walker->table, walker->exponents,
428 sizeof (double));
429 unsigned clauses = walker->clauses;
430 kissat_dealloc (solver, walker->refs, clauses, sizeof (tagged));
431 kissat_dealloc (solver, walker->counters, clauses, sizeof (counter));
432 RELEASE_STACK (walker->unsat);
433 RELEASE_STACK (walker->scores);
434 RELEASE_STACK (walker->trail);
435 kissat_free (solver, solver->values, LITS);
436 kissat_free (solver, walker->best_values, VARS);
437 RELEASE_STACK (walker->unsat);
438 solver->values = walker->original_values;
439}
440
441static unsigned break_value (kissat *solver, walker *walker, value *values,
442 unsigned lit) {
443 KISSAT_assert (values[lit] < 0);
444 const unsigned not_lit = NOT (lit);
445 watches *watches = &WATCHES (not_lit);
446 unsigned steps = 1;
447 unsigned res = 0;
449 steps++;
451 reference counter_ref = watch.large.ref;
452 KISSAT_assert (counter_ref < walker->clauses);
453 counter *counter = walker->counters + counter_ref;
454 res += (counter->count == 1);
455 }
456 ADD (walk_steps, steps);
457#ifdef KISSAT_NDEBUG
458 (void) values;
459#endif
460 return res;
461}
462
463static double scale_score (walker *walker, unsigned breaks) {
464 if (breaks < walker->exponents)
465 return walker->table[breaks];
466 else
467 return walker->epsilon;
468}
469
470static unsigned pick_literal (kissat *solver, walker *walker) {
471 KISSAT_assert (walker->current == SIZE_STACK (walker->unsat));
472 const unsigned pos = walker->flipped++ % walker->current;
473 const unsigned counter_ref = PEEK_STACK (walker->unsat, pos);
474 unsigned size;
475 const unsigned *const lits =
476 dereference_literals (solver, walker, counter_ref, &size);
477
478 LOGLITS (size, lits, "picked unsatisfied[%u]", pos);
479 KISSAT_assert (EMPTY_STACK (walker->scores));
480
481 value *values = solver->values;
482
483 double sum = 0;
484 unsigned picked_lit = INVALID_LIT;
485
486 const unsigned *const end_of_lits = lits + size;
487 for (const unsigned *p = lits; p != end_of_lits; p++) {
488 const unsigned lit = *p;
489 if (!values[lit])
490 continue;
491 picked_lit = lit;
492 const unsigned breaks = break_value (solver, walker, values, lit);
493 const double score = scale_score (walker, breaks);
494 KISSAT_assert (score > 0);
495 LOG ("literal %s breaks %u score %g", LOGLIT (lit), breaks, score);
496 PUSH_STACK (walker->scores, score);
497 sum += score;
498 }
499 KISSAT_assert (picked_lit != INVALID_LIT);
500 KISSAT_assert (0 < sum);
501
502 const double random = kissat_pick_double (&walker->random);
504
505 const double threshold = sum * random;
506 LOG ("score sum %g and random threshold %g", sum, threshold);
507
508 // KISSAT_assert (threshold < sum); // NOT TRUE!!!!
509
510 double *scores = BEGIN_STACK (walker->scores);
511#ifdef LOGGING
512 double picked_score = 0;
513#endif
514
515 sum = 0;
516
517 for (const unsigned *p = lits; p != end_of_lits; p++) {
518 const unsigned lit = *p;
519 if (!values[lit])
520 continue;
521 const double score = *scores++;
522 sum += score;
523 if (threshold < sum) {
524 picked_lit = lit;
525#ifdef LOGGING
526 picked_score = score;
527#endif
528 break;
529 }
530 }
531 KISSAT_assert (picked_lit != INVALID_LIT);
532 LOG ("picked literal %s with score %g", LOGLIT (picked_lit),
533 picked_score);
534
535 CLEAR_STACK (walker->scores);
536
537 return picked_lit;
538}
539
540static void break_clauses (kissat *solver, walker *walker,
541 const value *const values, unsigned flipped) {
542#ifdef LOGGING
543 unsigned broken = 0;
544#endif
545 const unsigned not_flipped = NOT (flipped);
546 KISSAT_assert (values[not_flipped] < 0);
547 LOG ("breaking one-satisfied clauses containing negated flipped literal "
548 "%s",
549 LOGLIT (not_flipped));
550 watches *watches = &WATCHES (not_flipped);
551 counter *counters = walker->counters;
552 unsigned steps = 1;
554 steps++;
556 const unsigned counter_ref = watch.large.ref;
557 KISSAT_assert (counter_ref < walker->clauses);
558 counter *counter = counters + counter_ref;
560 if (--counter->count)
561 continue;
562 push_unsat (solver, walker, counters, counter_ref);
563#ifdef LOGGING
564 broken++;
565#endif
566 }
567 LOG ("broken %u one-satisfied clauses containing "
568 "negated flipped literal %s",
569 broken, LOGLIT (not_flipped));
570 ADD (walk_steps, steps);
571#ifdef KISSAT_NDEBUG
572 (void) values;
573#endif
574}
575
576static void make_clauses (kissat *solver, walker *walker,
577 const value *const values, unsigned flipped) {
578 KISSAT_assert (values[flipped] > 0);
579 LOG ("making unsatisfied clauses containing flipped literal %s",
580 LOGLIT (flipped));
581 watches *watches = &WATCHES (flipped);
582 counter *counters = walker->counters;
583 unsigned steps = 1;
584#ifdef LOGGING
585 unsigned made = 0;
586#endif
588 steps++;
590 const unsigned counter_ref = watch.large.ref;
591 KISSAT_assert (counter_ref < walker->clauses);
592 counter *counter = counters + counter_ref;
593 KISSAT_assert (counter->count < UINT_MAX);
594 if (counter->count++)
595 continue;
596 if (pop_unsat (solver, walker, counters, counter_ref, counter->pos))
597 steps++;
598#ifdef LOGGING
599 made++;
600#endif
601 }
602 LOG ("made %u unsatisfied clauses containing flipped literal %s", made,
603 LOGLIT (flipped));
604 ADD (walk_steps, steps);
605#ifdef KISSAT_NDEBUG
606 (void) values;
607#endif
608}
609
610static void save_all_values (kissat *solver, walker *walker) {
612 KISSAT_assert (walker->best_trail_pos == INVALID_BEST_TRAIL_POS);
613 LOG ("copying all values as best phases since trail is invalid");
614 const value *const current_values = solver->values;
615 value *best_values = walker->best_values;
616 for (all_variables (idx)) {
617 const unsigned lit = LIT (idx);
618 const value value = current_values[lit];
619 if (value)
620 best_values[idx] = value;
621 }
622 LOG ("reset best trail position to 0");
623 walker->best_trail_pos = 0;
624}
625
626static void save_walker_trail (kissat *solver, walker *walker, bool keep) {
627#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
628 KISSAT_assert (walker->best_trail_pos != INVALID_BEST_TRAIL_POS);
629 KISSAT_assert (SIZE_STACK (walker->trail) <= UINT_MAX);
630 const unsigned size_trail = SIZE_STACK (walker->trail);
631 KISSAT_assert (walker->best_trail_pos <= size_trail);
632 const unsigned kept = size_trail - walker->best_trail_pos;
633 LOG ("saving %u values of flipped literals on trail of size %u",
634 walker->best_trail_pos, size_trail);
635#else
636 (void) solver;
637#endif
638 value *best_values = walker->best_values;
639 unsigned *begin = BEGIN_STACK (walker->trail);
640 const unsigned *const best = begin + walker->best_trail_pos;
641 for (const unsigned *p = begin; p != best; p++) {
642 const unsigned lit = *p;
643 const value value = NEGATED (lit) ? -1 : 1;
644 const unsigned idx = IDX (lit);
645 best_values[idx] = value;
646 }
647 if (!keep) {
648 LOG ("no need to shift and keep remaining %u literals", kept);
649 return;
650 }
651 LOG ("flushed %u literals %.0f%% from trail", walker->best_trail_pos,
652 kissat_percent (walker->best_trail_pos, size_trail));
653 const unsigned *const end = END_STACK (walker->trail);
654 unsigned *q = begin;
655 for (const unsigned *p = best; p != end; p++)
656 *q++ = *p;
657 KISSAT_assert ((size_t) (end - q) == walker->best_trail_pos);
658 KISSAT_assert ((size_t) (q - begin) == kept);
659 SET_END_OF_STACK (walker->trail, q);
660 LOG ("keeping %u literals %.0f%% on trail", kept,
661 kissat_percent (kept, size_trail));
662 LOG ("reset best trail position to 0");
663 walker->best_trail_pos = 0;
664}
665
666static void push_flipped (kissat *solver, walker *walker,
667 unsigned flipped) {
668 if (walker->best_trail_pos == INVALID_BEST_TRAIL_POS) {
669 LOG ("not pushing flipped %s to already invalid trail",
670 LOGLIT (flipped));
672 } else {
673 KISSAT_assert (SIZE_STACK (walker->trail) <= UINT_MAX);
674 const unsigned size_trail = SIZE_STACK (walker->trail);
675 KISSAT_assert (walker->best_trail_pos <= size_trail);
676 const unsigned limit = VARS / 4 + 1;
678 if (size_trail < limit) {
679 PUSH_STACK (walker->trail, flipped);
680 LOG ("pushed flipped %s to trail which now has size %u",
681 LOGLIT (flipped), size_trail + 1);
682 } else if (walker->best_trail_pos) {
683 LOG ("trail reached limit %u but has best position %u", limit,
684 walker->best_trail_pos);
685 save_walker_trail (solver, walker, true);
686 PUSH_STACK (walker->trail, flipped);
687 KISSAT_assert (SIZE_STACK (walker->trail) <= UINT_MAX);
688 LOG ("pushed flipped %s to trail which now has size %zu",
689 LOGLIT (flipped), SIZE_STACK (walker->trail));
690 } else {
691 LOG ("trail reached limit %u without best position", limit);
692 CLEAR_STACK (walker->trail);
693 LOG ("not pushing %s to invalidated trail", LOGLIT (flipped));
694 walker->best_trail_pos = INVALID_BEST_TRAIL_POS;
695 LOG ("best trail position becomes invalid");
696 }
697 }
698}
699
700static void flip_literal (kissat *solver, walker *walker, unsigned flip) {
701 LOG ("flipping literal %s", LOGLIT (flip));
702 value *values = solver->values;
703 const value value = values[flip];
704 KISSAT_assert (value < 0);
705 values[flip] = -value;
706 values[NOT (flip)] = value;
707 make_clauses (solver, walker, values, flip);
708 break_clauses (solver, walker, values, flip);
709 walker->current = currently_unsatified (walker);
710}
711
712static void update_best (kissat *solver, walker *walker) {
713 KISSAT_assert (walker->current < walker->minimum);
714 walker->minimum = walker->current;
715#ifndef KISSAT_QUIET
716 int verbosity = kissat_verbosity (solver);
717 bool report = (verbosity > 2);
718 if (verbosity == 2) {
719 if (walker->flipped / 2 >= walker->report.flipped)
720 report = true;
721 else if (walker->minimum < 5 || walker->report.minimum == UINT_MAX ||
722 walker->minimum <= walker->report.minimum / 2)
723 report = true;
724 if (report) {
725 walker->report.minimum = walker->minimum;
726 walker->report.flipped = walker->flipped;
727 }
728 }
729 if (report)
730 report_minimum ("new", solver, walker);
731#endif
732 if (walker->best_trail_pos == INVALID_BEST_TRAIL_POS)
733 save_all_values (solver, walker);
734 else {
736 walker->best_trail_pos = SIZE_STACK (walker->trail);
737 LOG ("new best trail position %u", walker->best_trail_pos);
738 }
739}
740
741static void local_search_step (kissat *solver, walker *walker) {
742 KISSAT_assert (walker->current);
743 INC (flipped);
744 KISSAT_assert (walker->flipped < UINT64_MAX);
745 walker->flipped++;
746 LOG ("starting local search flip %" PRIu64 " with %u unsatisfied clauses",
747 GET (flipped), walker->current);
748 unsigned lit = pick_literal (solver, walker);
749 flip_literal (solver, walker, lit);
750 push_flipped (solver, walker, lit);
751 if (walker->current < walker->minimum)
752 update_best (solver, walker);
753 LOG ("ending local search step %" PRIu64 " with %u unsatisfied clauses",
754 GET (flipped), walker->current);
755}
756
757static void local_search_round (walker *walker) {
758 kissat *solver = walker->solver;
759#ifndef KISSAT_QUIET
760 const unsigned before = walker->minimum;
761#endif
762 statistics *statistics = &solver->statistics_;
763 while (walker->minimum && walker->limit > statistics->walk_steps) {
765 break;
766 local_search_step (solver, walker);
767 }
768#ifndef KISSAT_QUIET
769 report_minimum ("last", solver, walker);
770 KISSAT_assert (statistics->walk_steps >= walker->start);
771 const uint64_t steps = statistics->walk_steps - walker->start;
772 // clang-format off
774 "walking ends with %u unsatisfied clauses", walker->current);
776 "flipping %" PRIu64 " literals took %" PRIu64 " steps (%.2f per flipped)",
777 walker->flipped, steps, kissat_average (steps, walker->flipped));
778 // clang-format on
779 const unsigned after = walker->minimum;
781 solver, "walk", GET (walks), "%s minimum %u after %" PRIu64 " flips",
782 after < before ? "new" : "unchanged", after, walker->flipped);
783#endif
784}
785
786static void export_best_values (walker *walker) {
787 kissat *const solver = walker->solver;
788 const value *const best = walker->best_values;
789 value *const saved = solver->phases.saved;
790 KISSAT_assert (sizeof *saved == 1);
791 KISSAT_assert (sizeof *best == 1);
792 memcpy (saved, best, VARS);
793}
794
795static bool save_final_minimum (walker *walker) {
796 kissat *solver = walker->solver;
797
798 KISSAT_assert (walker->minimum <= walker->initial);
799 if (walker->minimum == walker->initial) {
800 kissat_phase (solver, "walk", GET (walks),
801 "no improvement thus keeping saved phases");
802 return false;
803 }
804
805 kissat_phase (solver, "walk", GET (walks),
806 "saving improved assignment of %u unsatisfied clauses",
807 walker->minimum);
808
809 if (!walker->best_trail_pos ||
810 walker->best_trail_pos == INVALID_BEST_TRAIL_POS)
811 LOG ("minimum already saved");
812 else
813 save_walker_trail (solver, walker, false);
814
815 export_best_values (walker);
816 INC (walk_improved);
817
818 return true;
819}
820
821#ifdef CHECK_WALK
822
823static void check_walk (kissat *solver, unsigned expected) {
824 unsigned unsatisfied = 0;
825 watches *all_watches = solver->watches;
826 const value *const saved = solver->phases.saved;
827 for (all_literals (lit)) {
829 watches *watches = all_watches + lit;
830 if (kissat_empty_vector (watches))
831 continue;
832 value value = solver->values[lit];
833 if (!value) {
834 value = saved[IDX (lit)];
836 if (NEGATED (lit))
837 value = -value;
838 }
839 if (value > 0)
840 continue;
842 if (watch.type.binary) {
843 const unsigned other = watch.binary.lit;
844 if (other < lit)
845 continue;
846 value = solver->values[other];
847 if (!value) {
848 value = saved[IDX (other)];
850 if (NEGATED (other))
851 value = -value;
852 }
853 if (value > 0)
854 continue;
855 unsatisfied++;
856 LOGBINARY (lit, other, "unsat");
857 }
858 }
859 for (all_clauses (c)) {
860 if (c->redundant)
861 continue;
862 if (c->garbage)
863 continue;
864 bool satisfied = false;
865 for (all_literals_in_clause (lit, c)) {
866 value value = solver->values[lit];
867 if (!value) {
868 value = saved[IDX (lit)];
870 if (NEGATED (lit))
871 value = -value;
872 }
873 if (value > 0)
874 satisfied = true;
875 }
876 if (satisfied)
877 continue;
878 LOGCLS (c, "unsatisfied");
879 unsatisfied++;
880 }
881 LOG ("expected %u unsatisfied", expected);
882 LOG ("actually %u unsatisfied", unsatisfied);
883 KISSAT_assert (expected == unsatisfied);
884}
885
886#endif
887
888static void walking_phase (kissat *solver) {
889 INC (walks);
890 litpairs irredundant;
894 init_walker (solver, &walker, &irredundant);
895 init_walker_limit (solver, &walker);
896 local_search_round (&walker);
897#ifdef CHECK_WALK
898 bool improved =
899#endif
900 save_final_minimum (&walker);
901#ifdef CHECK_WALK
902 unsigned expected = walker.minimum;
903#endif
904 release_walker (&walker);
907#if CHECK_WALK
908 if (improved)
909 check_walk (solver, expected);
910#endif
911}
912
914 reference last_irredundant = solver->last_irredundant;
915 if (last_irredundant == INVALID_REF)
916 last_irredundant = SIZE_STACK (solver->arena);
917
918 if (last_irredundant > MAX_WALK_REF) {
920 "can not walk since last "
921 "irredundant clause reference %u too large",
922 last_irredundant);
923 return false;
924 }
925
926 uint64_t clauses = BINIRR_CLAUSES;
927 if (clauses > MAX_WALK_REF) {
929 "can not walk due to "
930 "way too many irredundant clauses %" PRIu64,
931 clauses);
932 return false;
933 }
934
935 return true;
936}
937
939 KISSAT_assert (!solver->level);
940 KISSAT_assert (!solver->inconsistent);
941 KISSAT_assert (kissat_propagated (solver));
943
944 reference last_irredundant = solver->last_irredundant;
945 if (last_irredundant == INVALID_REF)
946 last_irredundant = SIZE_STACK (solver->arena);
947
948 if (last_irredundant > MAX_WALK_REF) {
949 kissat_phase (solver, "walk", GET (walks),
950 "last irredundant clause reference %u too large",
951 last_irredundant);
952 return;
953 }
954
955 uint64_t clauses = BINIRR_CLAUSES;
956 if (clauses > MAX_WALK_REF) {
957 kissat_phase (solver, "walk", GET (walks),
958 "way too many irredundant clauses %" PRIu64, clauses);
959 return;
960 }
961
962 if (GET_OPTION (warmup))
964
966 walking_phase (solver);
968}
969
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
void * kissat_malloc(kissat *solver, size_t bytes)
Definition allocate.c:49
void * kissat_calloc(kissat *solver, size_t n, size_t size)
Definition allocate.c:97
void kissat_free(kissat *solver, void *ptr, size_t bytes)
Definition allocate.c:61
void kissat_dealloc(kissat *solver, void *ptr, size_t n, size_t size)
Definition allocate.c:114
ABC_NAMESPACE_HEADER_START typedef word ward
Definition arena.h:12
ABC_NAMESPACE_HEADER_START typedef uint64_t generator
Definition random.h:12
#define BEGIN_STACK(S)
Definition stack.h:46
#define POP_STACK(S)
Definition stack.h:37
#define POKE_STACK(S, N, E)
Definition stack.h:32
#define SIZE_STACK(S)
Definition stack.h:19
#define EMPTY_STACK(S)
Definition stack.h:18
#define SET_END_OF_STACK(S, P)
Definition stack.h:62
#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 END_STACK(S)
Definition stack.h:48
#define INVALID_LIT
#define ADD(NAME, DELTA)
#define INC(NAME)
#define LOG(...)
ABC_NAMESPACE_IMPL_START typedef signed char value
#define LOGLITS(...)
void kissat_mark_clause_as_garbage(kissat *solver, clause *c)
Definition clause.c:164
int kissat_decide_phase(kissat *solver, unsigned idx)
Definition decide.c:157
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
pcover irredundant()
bool pos
Definition globals.c:30
Cube * p
Definition exorList.c:222
type
CUBE COVER and CUBE typedefs ///.
Definition exor.h:90
#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
unsigned long long size
Definition giaNewBdd.h:39
#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_SEARCH_AND_START_SIMPLIFIER(...)
Definition profile.h:133
#define STOP_SIMPLIFIER_AND_RESUME_SEARCH(...)
Definition profile.h:136
#define INVALID_REF
Definition reference.h:16
ABC_NAMESPACE_HEADER_START typedef unsigned reference
Definition reference.h:9
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 GET(NAME)
Definition statistics.h:416
#define BINIRR_CLAUSES
Definition statistics.h:341
unsigned lits[3]
Definition clause.h:39
unsigned size
Definition clause.h:37
Definition walk.c:35
unsigned count
Definition walk.c:36
unsigned pos
Definition walk.c:37
Definition flags.h:11
unsigned lits[2]
Definition watch.h:65
Definition walk.c:24
unsigned ref
Definition walk.c:25
bool binary
Definition walk.c:26
#define walk_terminated_1
Definition terminate.h:86
#define TERMINATED(BIT)
Definition terminate.h:42
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
char * memcpy()
char * memset()
long random()
struct walker walker
Definition walk.c:19
#define LD_MAX_WALK_REF
Definition walk.c:21
#define report_minimum(...)
Definition walk.c:367
void kissat_walk(kissat *solver)
Definition walk.c:938
#define INVALID_BEST_TRAIL_POS
#define MAX_WALK_REF
Definition walk.c:22
#define report_initial_minimum(...)
Definition walk.c:364
bool kissat_walking(kissat *solver)
Definition walk.c:913
ABC_NAMESPACE_IMPL_START void kissat_warmup(kissat *solver)
Definition warmup.c:11
#define all_binary_blocking_watches(WATCH, WATCHES)
Definition watch.h:151
vector watches
Definition watch.h:49
#define all_binary_large_watches(WATCH, WATCHES)
Definition watch.h:158
#define WATCHES(LIT)
Definition watch.h:137