ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
backbone.c
Go to the documentation of this file.
1#include "backbone.h"
2#include "allocate.h"
3#include "analyze.h"
4#include "backtrack.h"
5#include "decide.h"
6#include "inline.h"
7#include "internal.h"
8#include "logging.h"
9#include "print.h"
10#include "proprobe.h"
11#include "report.h"
12#include "terminate.h"
13#include "trail.h"
14#include "utilities.h"
15
17
18static void schedule_backbone_candidates (kissat *solver,
19 unsigneds *candidates) {
20 flags *flags = solver->flags;
21 unsigned not_rescheduled = 0;
22 for (all_variables (idx)) {
23 const struct flags *f = flags + idx;
24 if (!f->active)
25 continue;
26 const unsigned lit = LIT (idx);
27 if (f->backbone0) {
28 PUSH_STACK (*candidates, lit);
29 LOG ("rescheduling backbone literal candidate %s", LOGLIT (lit));
30 } else
31 not_rescheduled++;
32 if (f->backbone1) {
33 const unsigned not_lit = NOT (lit);
34 PUSH_STACK (*candidates, not_lit);
35 LOG ("rescheduling backbone literal candidate %s", LOGLIT (not_lit));
36 } else
37 not_rescheduled++;
38 }
39#ifndef KISSAT_QUIET
40 const size_t rescheduled = SIZE_STACK (*candidates);
41 const unsigned active_literals = 2u * solver->active;
43 solver, "rescheduled %zu backbone candidate literals %.0f%%",
44 rescheduled, kissat_percent (rescheduled, active_literals));
45#endif
46 if (not_rescheduled) {
47 for (all_variables (idx)) {
48 struct flags *f = flags + idx;
49 if (!f->active)
50 continue;
51 const unsigned lit = LIT (idx);
52 if (!f->backbone0) {
53 LOG ("scheduling backbone literal candidate %s", LOGLIT (lit));
54 PUSH_STACK (*candidates, lit);
55 }
56 if (!f->backbone1) {
57 const unsigned not_lit = NOT (lit);
58 LOG ("scheduling backbone literal candidate %s", LOGLIT (not_lit));
59 PUSH_STACK (*candidates, not_lit);
60 }
61 }
62 }
63#ifndef KISSAT_QUIET
64 const size_t total = SIZE_STACK (*candidates);
66 "scheduled %zu backbone candidate literals %.0f%%"
67 " in total",
68 total, kissat_percent (total, active_literals));
69#endif
70}
71
72static void keep_backbone_candidates (kissat *solver,
73 unsigneds *candidates) {
74 flags *flags = solver->flags;
75 size_t prioritized = 0;
76 size_t remain = 0;
77 for (all_stack (unsigned, lit, *candidates)) {
78 const unsigned idx = IDX (lit);
79 const struct flags *f = flags + idx;
80 if (!f->active)
81 continue;
82 remain++;
83 if (NEGATED (lit))
84 prioritized += f->backbone1;
85 else
86 prioritized += f->backbone0;
87 }
88 KISSAT_assert (prioritized <= remain);
89 if (!remain) {
90 kissat_very_verbose (solver, "no backbone candidates remain");
91#ifndef KISSAT_NDEBUG
92 for (all_variables (idx)) {
93 const struct flags *f = flags + idx;
94 if (!f->active)
95 continue;
98 }
99#endif
100 return;
101 }
102#ifndef KISSAT_QUIET
103 const size_t active_literals = 2u * solver->active;
104#endif
105 if (prioritized == remain)
107 "keeping all remaining %zu backbone "
108 "candidates %.0f%% prioritized (all were)",
109 remain, kissat_percent (remain, active_literals));
110 else if (!prioritized) {
111 for (all_stack (unsigned, lit, *candidates)) {
112 const unsigned idx = IDX (lit);
113 struct flags *f = flags + idx;
114 if (!f->active)
115 continue;
116 if (NEGATED (lit)) {
118 f->backbone1 = true;
119 } else {
121 f->backbone0 = true;
122 }
123 }
125 "keeping all remaining %zu backbone "
126 "candidates %.0f%% prioritized (none was)",
127 remain, kissat_percent (remain, active_literals));
128 } else {
130 "keeping %zu backbone candidates %.0f%% "
131 "prioritized (%.0f%% of remaining %zu)",
132 prioritized,
133 kissat_percent (prioritized, active_literals),
134 kissat_percent (prioritized, remain), remain);
135 }
136}
137
138static inline void backbone_assign (kissat *solver, unsigned_array *trail,
139 value *values, assigned *assigned,
140 unsigned lit, unsigned reason) {
141 const unsigned not_lit = NOT (lit);
142 KISSAT_assert (!values[lit]);
143 KISSAT_assert (!values[not_lit]);
144 values[lit] = 1;
145 values[not_lit] = -1;
146 PUSH_ARRAY (*trail, lit);
147 const unsigned idx = IDX (lit);
148 struct assigned *a = assigned + idx;
149 a->reason = reason;
150 a->level = solver->level;
151}
152
153static inline clause *
154backbone_propagate_literal (kissat *solver, const bool stop_early,
155 const watches *const all_watches,
156 unsigned_array *trail, value *values,
157 assigned *assigned, unsigned lit) {
158 LOG ("backbone propagating %s", LOGLIT (lit));
160 KISSAT_assert (values[lit] > 0);
161
162 const unsigned not_lit = NOT (lit);
163 KISSAT_assert (values[not_lit] < 0);
164
165 KISSAT_assert (not_lit < LITS);
166 const watches *const watches = all_watches + not_lit;
167
168 const watch *const begin_watches = BEGIN_CONST_WATCHES (*watches);
169 const watch *const end_watches = END_CONST_WATCHES (*watches);
170 const watch *p = begin_watches;
171
172 while (p != end_watches) {
173 const watch watch = *p++;
174 if (watch.type.binary) {
175 const unsigned other = watch.binary.lit;
177 const value value = values[other];
178 if (value > 0)
179 continue;
180 if (value < 0)
181 return kissat_binary_conflict (solver, not_lit, other);
183 backbone_assign (solver, trail, values, assigned, other, lit);
184 LOG ("backbone assign %s reason binary clause %s %s", LOGLIT (other),
185 LOGLIT (other), LOGLIT (not_lit));
186 } else {
187 if (stop_early) {
188#ifndef KISSAT_NDEBUG
189 for (const union watch *q = p + 1; q != end_watches; q++) {
190 const union watch watch = *q++;
192 }
193#endif
194 break;
195 }
196
197 p++;
198 }
199 }
200
201 const size_t touched = p - begin_watches;
202 solver->ticks += 1 + kissat_cache_lines (touched, sizeof (watch));
203
204 return 0;
205}
206
207static inline clause *backbone_propagate (kissat *solver,
208 unsigned_array *trail,
209 value *values,
211 const bool stop_early =
212 solver->large_clauses_watched_after_binary_clauses;
213
214 clause *conflict = 0;
215 solver->ticks = 0;
216
217 const watches *const watches = solver->watches;
218 unsigned *propagate = solver->propagate;
219
220 while (!conflict && propagate != END_ARRAY (*trail))
221 conflict = backbone_propagate_literal (
222 solver, stop_early, watches, trail, values, assigned, *propagate++);
223
224 KISSAT_assert (solver->propagate <= propagate);
225 const unsigned propagated = propagate - solver->propagate;
226 solver->propagate = propagate;
227
228 ADD (backbone_propagations, propagated);
229 ADD (probing_propagations, propagated);
230 ADD (propagations, propagated);
231
232 const uint64_t ticks = solver->ticks;
233
234 ADD (backbone_ticks, ticks);
235 ADD (probing_ticks, ticks);
236 ADD (ticks, ticks);
237
238 return conflict;
239}
240
241static inline void backbone_backtrack (kissat *solver,
242 unsigned_array *trail, value *values,
243 unsigned *saved,
244 unsigned decision_level) {
245 KISSAT_assert (decision_level <= solver->level);
246 unsigned *end_trail = END_ARRAY (*trail);
247 KISSAT_assert (saved != end_trail);
248 LOG ("backbone backtracking to trail level %zu and decision level %u",
249 (size_t) (saved - BEGIN_ARRAY (*trail)), decision_level);
250 while (saved != end_trail) {
251 const unsigned lit = *--end_trail;
252 const unsigned not_lit = NOT (lit);
253 LOG ("backbone unassign %s", LOGLIT (lit));
254 KISSAT_assert (values[lit] > 0);
255 KISSAT_assert (values[not_lit] < 0);
256 values[lit] = values[not_lit] = 0;
257 }
258 SET_END_OF_ARRAY (solver->trail, saved);
259 solver->level = decision_level;
260 solver->propagate = saved;
261}
262
263static unsigned backbone_analyze (kissat *solver, clause *conflict) {
264 KISSAT_assert (conflict);
265 LOGCLS (conflict, "backbone analyzing");
266 KISSAT_assert (conflict->size == 2);
267
268 assigned *const assigned = solver->assigned;
269
270 kissat_push_analyzed (solver, assigned, IDX (conflict->lits[0]));
271 kissat_push_analyzed (solver, assigned, IDX (conflict->lits[1]));
272
273 const unsigned *t = END_ARRAY (solver->trail);
274
275 for (;;) {
276 KISSAT_assert (t > BEGIN_ARRAY (solver->trail));
277
278 unsigned lit = *--t;
279
280 const unsigned lit_idx = IDX (lit);
281 const struct assigned *a = assigned + lit_idx;
282 if (!a->analyzed)
283 continue;
284
285 LOG ("backbone analyzing %s", LOGLIT (lit));
286 const unsigned reason = a->reason;
289 const unsigned reason_idx = IDX (reason);
290 const struct assigned *b = assigned + reason_idx;
291 if (!b->analyzed) {
292 LOG ("reason %s of %s not yet analyzed", LOGLIT (reason),
293 LOGLIT (lit));
294 kissat_push_analyzed (solver, assigned, reason_idx);
295 } else {
296 LOG ("backbone UIP %s", LOGLIT (reason));
298 return reason;
299 }
300 }
301}
302
303#ifndef KISSAT_NDEBUG
304
305static void
306check_large_clauses_watched_after_binary_clauses (kissat *solver) {
307 for (all_literals (lit)) {
308 bool large = false;
310 if (watch.type.binary)
311 KISSAT_assert (!large);
312 else
313 large = true;
314 }
315}
316
317#endif
318
319static unsigned compute_backbone (kissat *solver) {
320#ifndef KISSAT_NDEBUG
321 if (solver->large_clauses_watched_after_binary_clauses)
322 check_large_clauses_watched_after_binary_clauses (solver);
323#endif
324 size_t failed = 0;
325 unsigneds units;
326 unsigneds candidates;
327 INIT_STACK (candidates);
328 INIT_STACK (units);
329 schedule_backbone_candidates (solver, &candidates);
330#ifndef KISSAT_QUIET
331 const size_t scheduled = SIZE_STACK (candidates);
332#endif
333#if defined(METRICS) && (!defined(KISSAT_QUIET) || !defined(KISSAT_NDEBUG))
334 const uint64_t implied_before = solver->statistics_.backbone_implied;
335#endif
336 unsigned_array *trail = &solver->trail;
337 value *values = solver->values;
338 flags *flags = solver->flags;
339 assigned *assigned = solver->assigned;
340
341 KISSAT_assert (kissat_propagated (solver));
342 KISSAT_assert (kissat_trail_flushed (solver));
343
344 unsigned inconsistent = INVALID_LIT;
345
346 SET_EFFORT_LIMIT (ticks_limit, backbone, backbone_ticks);
347 size_t round_limit = GET_OPTION (backbonerounds);
348 KISSAT_assert (solver->statistics_.backbone_computations);
349 round_limit *= solver->statistics_.backbone_computations;
350 const size_t max_rounds = GET_OPTION (backbonemaxrounds);
351 if (round_limit > max_rounds)
352 round_limit = max_rounds;
353
354 size_t round = 0;
355
356 for (;;) {
357 if (round >= round_limit) {
358 kissat_very_verbose (solver, "backbone round limit %zu hit", round);
359 break;
360 }
361 const uint64_t ticks = solver->statistics_.backbone_ticks;
362 if (ticks > ticks_limit) {
364 "backbone ticks limit %" PRIu64 " hit "
365 "after %" PRIu64 " ticks",
366 ticks_limit, ticks);
367 break;
368 }
369 size_t previous = failed;
370 KISSAT_assert (!solver->inconsistent);
372 break;
373 round++;
374 INC (backbone_rounds);
375 LOG ("starting backbone round %zu", round);
376 unsigned *const begin_candidates = BEGIN_STACK (candidates);
377 KISSAT_assert (!solver->level);
378#if !defined(KISSAT_QUIET) && defined(METRICS)
379 size_t decisions = 0;
380 uint64_t propagated = solver->statistics_.backbone_propagations;
381#endif
382 unsigned active_before = solver->active;
383 {
384 unsigned *q = begin_candidates;
385 const unsigned *p = begin_candidates;
386 const unsigned *const end_candidates = END_STACK (candidates);
387 while (p != end_candidates) {
388 KISSAT_assert (!solver->inconsistent);
389 const unsigned probe = *q++ = *p++;
390 const value value = values[probe];
391 if (value > 0) {
392 q--;
393 LOG ("removing satisfied backbone probe %s", LOGLIT (probe));
394 const unsigned idx = IDX (probe);
395 struct flags *f = flags + idx;
396 if (NEGATED (probe))
397 f->backbone1 = false;
398 else
399 f->backbone0 = false;
400 continue;
401 }
402 if (value < 0) {
403 const unsigned idx = IDX (probe);
404 struct assigned *a = assigned + idx;
405 if (a->level)
406 LOG ("skipping falsified backbone probe %s", LOGLIT (probe));
407 else {
408 LOG ("removing root-level falsified backbone probe %s",
409 LOGLIT (probe));
410 q--;
411 }
412 continue;
413 }
414 if (solver->statistics_.backbone_ticks > ticks_limit)
415 break;
417 break;
418 const unsigned level = solver->level;
419 unsigned *const saved = END_ARRAY (*trail);
420 KISSAT_assert (level != UINT_MAX);
421#if !defined(KISSAT_QUIET) && defined(METRICS)
422 decisions++;
423#endif
424 solver->level = level + 1;
425 INC (backbone_probes);
426 backbone_assign (solver, trail, values, assigned, probe,
428 LOG ("backbone assume %s", LOGLIT (probe));
429 clause *conflict =
430 backbone_propagate (solver, trail, values, assigned);
431 if (!conflict) {
432 LOG ("propagating backbone probe %s successful", LOGLIT (probe));
433 continue;
434 }
435
436 failed++;
437 INC (backbone_units);
438 q--;
439
440 LOG ("propagating backbone probe %s failed", LOGLIT (probe));
441 unsigned uip = backbone_analyze (solver, conflict);
442 unsigned not_uip = NOT (uip);
443 backbone_backtrack (solver, trail, values, saved, level);
444
445 PUSH_STACK (units, not_uip);
446 backbone_assign (solver, trail, values, assigned, not_uip,
448 LOG ("backbone forced assign %s", LOGLIT (not_uip));
449 KISSAT_assert (failed == SIZE_STACK (units));
450
451 conflict = backbone_propagate (solver, trail, values, assigned);
452 if (conflict) {
453 LOG ("propagating backbone forced %s failed", LOGLIT (not_uip));
454 inconsistent = not_uip;
455 break;
456 }
457
458 LOG ("propagating backbone forced %s successful", LOGLIT (not_uip));
459 }
460#ifndef KISSAT_QUIET
461 size_t remain = end_candidates - p;
462 if (remain)
464 "backbone round %zu aborted with "
465 "%zu candidates %.0f%% remaining",
466 round, remain,
467 kissat_percent (remain, scheduled));
468 else
470 "backbone round %zu completed with "
471 "all %zu scheduled candidates tried",
472 round, scheduled);
473#endif
474 while (p != end_candidates)
475 *q++ = *p++;
476
477 SET_END_OF_STACK (candidates, q);
478 }
479 if (inconsistent == INVALID_LIT) {
480 LOG ("flushing satisfied probe candidates");
481 unsigned *q = begin_candidates;
482 const unsigned *p = begin_candidates;
483 const unsigned *const end_candidates = END_STACK (candidates);
484 while (p != end_candidates) {
485 const unsigned probe = *q++ = *p++;
486 const value value = values[probe];
487 if (value > 0) {
488 q--;
489 LOG ("removing satisfied backbone probe %s", LOGLIT (probe));
490 const unsigned idx = IDX (probe);
491 struct flags *f = flags + idx;
492 if (NEGATED (probe))
493 f->backbone1 = false;
494 else
495 f->backbone0 = false;
496 continue;
497 }
498 if (value < 0) {
499 LOG ("keeping falsified probe %s", LOGLIT (probe));
500 continue;
501 }
503 LOG ("keeping unassigned probe %s", LOGLIT (probe));
504 }
505 LOG ("flushed %zu probe candidates",
506 (size_t) (q - BEGIN_STACK (candidates)));
507 SET_END_OF_STACK (candidates, q);
508 }
509 if (!EMPTY_ARRAY (*trail))
510 backbone_backtrack (solver, trail, values, BEGIN_ARRAY (*trail), 0);
511 if (inconsistent == INVALID_LIT && previous < failed) {
512 for (size_t i = previous; i < failed; i++) {
513 const unsigned unit = PEEK_STACK (units, i);
514 LOG ("assigning backbone unit %s", LOGLIT (unit));
516 }
517 if (kissat_probing_propagate (solver, 0, true))
518 break;
519 }
520 KISSAT_assert (solver->active <= active_before);
521 unsigned implied = active_before - solver->active;
522 KISSAT_assert (failed <= failed);
523 ADD (backbone_implied, implied);
524#ifndef KISSAT_QUIET
525#ifdef METRICS
526 propagated = solver->statistics_.backbone_propagations - propagated;
528 "backbone round %zu with %zu decisions "
529 "(%.2f propagations per decision)",
530 round, decisions,
531 kissat_average (propagated, decisions));
532#endif
533 size_t left = SIZE_STACK (candidates);
535 "backbone round %zu produced %zu failed literals"
536 " %u implied (%zu candidates left %.0f%%)",
537 round, failed - previous, implied, left,
538 kissat_percent (left, scheduled));
539#endif
540 if (inconsistent != INVALID_LIT)
541 break;
542 if (EMPTY_STACK (candidates))
543 break;
544 }
545
546 if (inconsistent != INVALID_LIT && !solver->inconsistent) {
547 LOG ("assuming forced unit %s", LOGLIT (inconsistent));
548 kissat_learned_unit (solver, inconsistent);
549 (void) kissat_probing_propagate (solver, 0, true);
550 KISSAT_assert (solver->inconsistent);
551 }
552 RELEASE_STACK (units);
553 if (solver->inconsistent)
554 kissat_phase (solver, "backbone", GET (backbone_computations),
555 "inconsistent binary clauses");
556 else {
557 keep_backbone_candidates (solver, &candidates);
558#if defined(METRICS) && (!defined(KISSAT_QUIET) || !defined(KISSAT_NDEBUG))
559 KISSAT_assert (implied_before <= solver->statistics_.backbone_implied);
560#endif
561#if defined(METRICS) && !defined(KISSAT_QUIET)
562 const uint64_t total_implied =
563 solver->statistics_.backbone_implied - implied_before;
564 kissat_phase (solver, "backbone", GET (backbone_computations),
565 "found %zu backbone literals %" PRIu64
566 " implied in %zu rounds",
567 failed, total_implied, round);
568#endif
569 }
570 RELEASE_STACK (candidates);
571 return failed;
572}
573
575 if (solver->inconsistent)
576 return;
577 if (!GET_OPTION (backbone))
578 return;
580 return;
581 KISSAT_assert (solver->watching);
582 KISSAT_assert (solver->probing);
583 KISSAT_assert (!solver->level);
584 START (backbone);
585 INC (backbone_computations);
586#if !defined(KISSAT_NDEBUG) || defined(METRICS)
587 KISSAT_assert (!solver->backbone_computing);
588 solver->backbone_computing = true;
589#endif
590#ifndef KISSAT_QUIET
591 const unsigned failed =
592#endif
593 compute_backbone (solver);
594 REPORT (!failed, 'b');
595#if !defined(KISSAT_NDEBUG) || defined(METRICS)
596 KISSAT_assert (solver->backbone_computing);
597 solver->backbone_computing = false;
598#endif
599 STOP (backbone);
600}
601
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
void kissat_reset_only_analyzed_literals(kissat *solver)
Definition analyze.c:328
#define PUSH_ARRAY(A, E)
Definition array.h:26
#define SET_END_OF_ARRAY
Definition array.h:53
#define EMPTY_ARRAY
Definition array.h:23
#define BEGIN_ARRAY
Definition array.h:50
#define END_ARRAY
Definition array.h:51
void kissat_learned_unit(kissat *solver, unsigned lit)
Definition assign.c:18
#define DECISION_REASON
Definition assign.h:9
#define UNIT_REASON
Definition assign.h:10
void kissat_binary_clauses_backbone(kissat *solver)
Definition backbone.c:574
#define BEGIN_STACK(S)
Definition stack.h:46
#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 SET_END_OF_STACK(S, P)
Definition stack.h:62
#define RELEASE_STACK(S)
Definition stack.h:71
#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 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
Cube * p
Definition exorList.c:222
#define all_variables(IDX)
Definition internal.h:269
#define all_literals(LIT)
Definition internal.h:274
#define LITS
Definition internal.h:251
#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 LOGCLS(...)
Definition logging.h:415
#define LOGLIT(...)
Definition logging.hpp:99
#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
clause * kissat_probing_propagate(kissat *solver, clause *ignore, bool flush)
Definition proprobe.c:37
#define REPORT(...)
Definition report.h:10
int lit
Definition satVec.h:130
#define LIT(IDX)
Definition literal.h:31
#define VALID_INTERNAL_LITERAL(LIT)
Definition literal.h:23
#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
bool analyzed
Definition assign.h:22
unsigned trail
Definition assign.h:20
unsigned reason
Definition assign.h:28
unsigned level
Definition assign.h:19
unsigned lits[3]
Definition clause.h:39
unsigned size
Definition clause.h:37
Definition flags.h:11
bool active
Definition flags.h:12
bool backbone0
Definition flags.h:13
bool backbone1
Definition flags.h:14
#define backbone_terminated_2
Definition terminate.h:46
#define backbone_terminated_1
Definition terminate.h:45
#define TERMINATED(BIT)
Definition terminate.h:42
#define backbone_terminated_3
Definition terminate.h:47
Definition watch.h:41
watch_type type
Definition watch.h:42
binary_watch binary
Definition watch.h:43
#define all_binary_blocking_watches(WATCH, WATCHES)
Definition watch.h:151
#define END_CONST_WATCHES(WS)
Definition watch.h:123
vector watches
Definition watch.h:49
#define BEGIN_CONST_WATCHES(WS)
Definition watch.h:120
#define WATCHES(LIT)
Definition watch.h:137