ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
cadical_kitten.c
Go to the documentation of this file.
1#include "global.h"
2
3#include "kitten.h"
4#include "random.h"
5#include "stack.h"
6
7#include <assert.h>
8#include <inttypes.h>
9#include <limits.h>
10#include <stdarg.h>
11#include <stdbool.h>
12#include <stdint.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16
18
19typedef signed char value;
20
21static void die (const char *fmt, ...) {
22 fputs ("cadical_kitten: error: ", stderr);
23 va_list ap;
24 va_start (ap, fmt);
25 vfprintf (stderr, fmt, ap);
26 va_end (ap);
27 fputc ('\n', stderr);
28 exit (1);
29}
30
31static inline void *cadical_kitten_calloc (size_t n, size_t size) {
32 void *res = calloc (n, size);
33 if (n && size && !res)
34 die ("out of memory allocating '%zu * %zu' bytes", n, size);
35 return res;
36}
37
38#define CALLOC(T, P, N) \
39 do { \
40 (P) = (T*)cadical_kitten_calloc (N, sizeof *(P)); \
41 } while (0)
42#define DEALLOC(P, N) free (P)
43
44#undef ENLARGE_STACK
45
46#define ENLARGE_STACK(S) \
47 do { \
48 CADICAL_assert (FULL_STACK (S)); \
49 const size_t SIZE = SIZE_STACK (S); \
50 const size_t OLD_CAPACITY = CAPACITY_STACK (S); \
51 const size_t NEW_CAPACITY = OLD_CAPACITY ? 2 * OLD_CAPACITY : 1; \
52 const size_t BYTES = NEW_CAPACITY * sizeof *(S).begin; \
53 (S).begin = (unsigned*)realloc ((S).begin, BYTES); \
54 if (!(S).begin) \
55 die ("out of memory reallocating '%zu' bytes", BYTES); \
56 (S).allocated = (S).begin + NEW_CAPACITY; \
57 (S).end = (S).begin + SIZE; \
58 } while (0)
59
60// Beside allocators above also use stand alone statistics counters.
61
62#define INC(NAME) \
63 do { \
64 statistics *statistics = &cadical_kitten->statistics; \
65 CADICAL_assert (statistics->NAME < UINT64_MAX); \
66 statistics->NAME++; \
67 } while (0)
68
69#define ADD(NAME, DELTA) \
70 do { \
71 statistics *statistics = &cadical_kitten->statistics; \
72 CADICAL_assert (statistics->NAME <= UINT64_MAX - (DELTA)); \
73 statistics->NAME += (DELTA); \
74 } while (0)
75
76#define KITTEN_TICKS (cadical_kitten->statistics.cadical_kitten_ticks)
77
78#define INVALID UINT_MAX
79#define MAX_VARS ((1u << 31) - 1)
80
81#define CORE_FLAG (1u)
82#define LEARNED_FLAG (2u)
83
84// clang-format off
85
86typedef struct kar kar;
87typedef struct kink kink;
88typedef struct klause klause;
89typedef STACK (unsigned) klauses;
90typedef unsigneds katches;
91
92// clang-format on
93
94struct kar {
95 unsigned level;
96 unsigned reason;
97};
98
99struct kink {
100 unsigned next;
101 unsigned prev;
102 uint64_t stamp;
103};
104
105struct klause {
106 unsigned aux;
107 unsigned size;
108 unsigned flags;
109 unsigned lits[1];
110};
111
112typedef struct statistics statistics;
113
128
129typedef struct kimits kimits;
130
131struct kimits {
132 uint64_t ticks;
133};
134
136 // First zero initialized field in 'clear_cadical_kitten' is 'status'.
137 //
139
140#if defined(LOGGING)
141 bool logging;
142#endif
145
146 unsigned level;
147 unsigned propagated;
148 unsigned unassigned;
149 unsigned inconsistent;
150 unsigned failing;
151
152 uint64_t generator;
153
154 size_t lits;
155 size_t evars;
156
158
159 struct {
160 unsigned first, last;
161 uint64_t stamp;
162 unsigned search;
164
165 // The 'size' field below is the first not zero reinitialized field
166 // by 'memset' in 'clear_cadical_kitten' (after 'kissat').
167
168 size_t size;
169 size_t esize;
170
175 bool *failed;
176 unsigned char *phases;
177 unsigned *import;
178 katches *watches;
179
180 unsigneds analyzed;
181 unsigneds assumptions;
182 unsigneds core;
183 unsigneds rcore;
184 unsigneds eclause;
185 unsigneds export_;
186 unsigneds klause;
187 unsigneds klauses;
188 unsigneds resolved;
189 unsigneds trail;
190 unsigneds units;
191 unsigneds prime[2];
192
194 int (*terminator) (void *);
196 unsigneds clause;
197 uint64_t initialized;
199};
200
201/*------------------------------------------------------------------------*/
202
203static inline bool is_core_klause (klause *c) {
204 return c->flags & CORE_FLAG;
205}
206
207static inline bool is_learned_klause (klause *c) {
208 return c->flags & LEARNED_FLAG;
209}
210
211static inline void set_core_klause (klause *c) { c->flags |= CORE_FLAG; }
212
213static inline void unset_core_klause (klause *c) { c->flags &= ~CORE_FLAG; }
214
215static inline klause *dereference_klause (cadical_kitten *cadical_kitten, unsigned ref) {
216 unsigned *res = BEGIN_STACK (cadical_kitten->klauses) + ref;
218 return (klause *) res;
219}
220
221static inline unsigned reference_klause (cadical_kitten *cadical_kitten, const klause *c) {
222 const unsigned *const begin = BEGIN_STACK (cadical_kitten->klauses);
223 const unsigned *p = (const unsigned *) c;
224 CADICAL_assert (begin <= p);
226 const unsigned res = p - begin;
227 return res;
228}
229
230/*------------------------------------------------------------------------*/
231
232#define KATCHES(KIT) (cadical_kitten->watches[CADICAL_assert ((KIT) < cadical_kitten->lits), (KIT)])
233
234#define all_klauses(C) \
235 klause *C = begin_klauses (cadical_kitten), *end_##C = end_klauses (cadical_kitten); \
236 (C) != end_##C; \
237 (C) = next_klause (cadical_kitten, C)
238
239#define all_original_klauses(C) \
240 klause *C = begin_klauses (cadical_kitten), \
241 *end_##C = end_original_klauses (cadical_kitten); \
242 (C) != end_##C; \
243 (C) = next_klause (cadical_kitten, C)
244
245#define all_learned_klauses(C) \
246 klause *C = begin_learned_klauses (cadical_kitten), \
247 *end_##C = end_klauses (cadical_kitten); \
248 (C) != end_##C; \
249 (C) = next_klause (cadical_kitten, C)
250
251#define all_kits(KIT) \
252 size_t KIT = 0, KIT_##END = cadical_kitten->lits; \
253 KIT != KIT_##END; \
254 KIT++
255
256#define BEGIN_KLAUSE(C) (C)->lits
257
258#define END_KLAUSE(C) (BEGIN_KLAUSE (C) + (C)->size)
259
260#define all_literals_in_klause(KIT, C) \
261 unsigned KIT, *KIT##_PTR = BEGIN_KLAUSE (C), \
262 *KIT##_END = END_KLAUSE (C); \
263 KIT##_PTR != KIT##_END && ((KIT = *KIT##_PTR), true); \
264 ++KIT##_PTR
265
266#define all_antecedents(REF, C) \
267 unsigned REF, *REF##_PTR = antecedents (C), \
268 *REF##_END = REF##_PTR + (C)->aux; \
269 REF##_PTR != REF##_END && ((REF = *REF##_PTR), true); \
270 ++REF##_PTR
271
272#ifdef LOGGING
273
274#define logging (cadical_kitten->logging)
275
276static void log_basic (cadical_kitten *, const char *, ...)
277 __attribute__ ((format (printf, 2, 3)));
278
279static void log_basic (cadical_kitten *cadical_kitten, const char *fmt, ...) {
280 CADICAL_assert (logging);
281 printf ("c KITTEN %u ", cadical_kitten->level);
282 va_list ap;
283 va_start (ap, fmt);
284 vprintf (fmt, ap);
285 va_end (ap);
286 fputc ('\n', stdout);
287 fflush (stdout);
288}
289
290static void log_reference (cadical_kitten *, unsigned, const char *, ...)
291 __attribute__ ((format (printf, 3, 4)));
292
293static void log_reference (cadical_kitten *cadical_kitten, unsigned ref, const char *fmt,
294 ...) {
295 klause *c = dereference_klause (cadical_kitten, ref);
296 CADICAL_assert (logging);
297 printf ("c KITTEN %u ", cadical_kitten->level);
298 va_list ap;
299 va_start (ap, fmt);
300 vprintf (fmt, ap);
301 va_end (ap);
302 if (is_learned_klause (c)) {
303 fputs (" learned", stdout);
304 if (c->aux)
305 printf ("[%u]", c->aux);
306 } else {
307 fputs (" original", stdout);
308 if (c->aux != INVALID)
309 printf ("[%u]", c->aux);
310 }
311 printf (" size %u clause[%u]", c->size, ref);
312 value *values = cadical_kitten->values;
313 kar *vars = cadical_kitten->vars;
314 for (all_literals_in_klause (lit, c)) {
315 printf (" %u", lit);
316 const value value = values[lit];
317 if (value)
318 printf ("@%u=%d", vars[lit / 2].level, (int) value);
319 }
320 fputc ('\n', stdout);
321 fflush (stdout);
322}
323
324static void log_literals (cadical_kitten *, unsigned *, unsigned, const char *, ...)
325 __attribute__ ((format (printf, 4, 5)));
326
327static void log_literals (cadical_kitten *cadical_kitten, unsigned *lits, unsigned size,
328 const char *fmt, ...) {
329 CADICAL_assert (logging);
330 printf ("c KITTEN %u ", cadical_kitten->level);
331 va_list ap;
332 va_start (ap, fmt);
333 vprintf (fmt, ap);
334 va_end (ap);
335 value *values = cadical_kitten->values;
336 kar *vars = cadical_kitten->vars;
337 for (unsigned i = 0; i < size; i++) {
338 const unsigned lit = lits[i];
339 printf (" %u", lit);
340 const value value = values[lit];
341 if (value)
342 printf ("@%u=%d", vars[lit / 2].level, (int) value);
343 }
344 fputc ('\n', stdout);
345 fflush (stdout);
346}
347
348#define LOG(...) \
349 do { \
350 if (logging) \
351 log_basic (cadical_kitten, __VA_ARGS__); \
352 } while (0)
353
354#define ROG(...) \
355 do { \
356 if (logging) \
357 log_reference (cadical_kitten, __VA_ARGS__); \
358 } while (0)
359
360#define LOGLITS(...) \
361 do { \
362 if (logging) \
363 log_literals (cadical_kitten, __VA_ARGS__); \
364 } while (0)
365
366#else
367
368#define LOG(...) \
369 do { \
370 } while (0)
371#define ROG(...) \
372 do { \
373 } while (0)
374#define LOGLITS(...) \
375 do { \
376 } while (0)
377
378#endif
379
380static void check_queue (cadical_kitten *cadical_kitten) {
381#ifdef CHECK_KITTEN
382 const unsigned vars = cadical_kitten->lits / 2;
383 unsigned found = 0, prev = INVALID;
385 uint64_t stamp = 0;
386 for (unsigned idx = cadical_kitten->queue.first, next; idx != INVALID;
387 idx = next) {
388 kink *link = links + idx;
389 CADICAL_assert (link->prev == prev);
390 CADICAL_assert (!found || stamp < link->stamp);
392 stamp = link->stamp;
393 next = link->next;
394 prev = idx;
395 found++;
396 }
397 CADICAL_assert (found == vars);
398 unsigned next = INVALID;
399 found = 0;
400 for (unsigned idx = cadical_kitten->queue.last, prev; idx != INVALID;
401 idx = prev) {
402 kink *link = links + idx;
403 CADICAL_assert (link->next == next);
404 prev = link->prev;
405 next = idx;
406 found++;
407 }
408 CADICAL_assert (found == vars);
409 value *values = cadical_kitten->values;
410 bool first = true;
411 for (unsigned idx = cadical_kitten->queue.search, next; idx != INVALID;
412 idx = next) {
413 kink *link = links + idx;
414 next = link->next;
415 const unsigned lit = 2 * idx;
416 CADICAL_assert (first || values[lit]);
417 first = false;
418 }
419#else
420 (void) cadical_kitten;
421#endif
422}
423
424static void update_search (cadical_kitten *cadical_kitten, unsigned idx) {
425 if (cadical_kitten->queue.search == idx)
426 return;
428 LOG ("search updated to %u stamped %" PRIu64, idx,
430}
431
432static void enqueue (cadical_kitten *cadical_kitten, unsigned idx) {
433 LOG ("enqueue %u", idx);
435 kink *l = links + idx;
436 const unsigned last = cadical_kitten->queue.last;
437 if (last == INVALID)
439 else
440 links[last].next = idx;
441 l->prev = last;
442 l->next = INVALID;
445 LOG ("stamp %" PRIu64, l->stamp);
446}
447
448static void dequeue (cadical_kitten *cadical_kitten, unsigned idx) {
449 LOG ("dequeue %u", idx);
451 kink *l = links + idx;
452 const unsigned prev = l->prev;
453 const unsigned next = l->next;
454 if (prev == INVALID)
455 cadical_kitten->queue.first = next;
456 else
457 links[prev].next = next;
458 if (next == INVALID)
459 cadical_kitten->queue.last = prev;
460 else
461 links[next].prev = prev;
462}
463
464static void init_queue (cadical_kitten *cadical_kitten, size_t old_vars, size_t new_vars) {
465 for (size_t idx = old_vars; idx < new_vars; idx++) {
469 enqueue (cadical_kitten, idx);
470 }
471 LOG ("initialized decision queue from %zu to %zu", old_vars, new_vars);
472 update_search (cadical_kitten, cadical_kitten->queue.last);
473 check_queue (cadical_kitten);
474}
475
476static void initialize_cadical_kitten (cadical_kitten *cadical_kitten) {
484 cadical_kitten->limits.ticks = UINT64_MAX;
486}
487
488static void clear_cadical_kitten (cadical_kitten *cadical_kitten) {
489 size_t bytes = (char *) &cadical_kitten->size - (char *) &cadical_kitten->status;
490 memset (&cadical_kitten->status, 0, bytes);
492 initialize_cadical_kitten (cadical_kitten);
493}
494
495#define RESIZE1(T, P) \
496 do { \
497 void *OLD_PTR = (P); \
498 CALLOC (T, (P), new_size / 2); \
499 const size_t BYTES = old_vars * sizeof *(P); \
500 memcpy ((P), OLD_PTR, BYTES); \
501 void *NEW_PTR = (P); \
502 (P) = (T*)OLD_PTR; \
503 DEALLOC ((P), old_size / 2); \
504 (P) = (T*)NEW_PTR; \
505 } while (0)
506
507#define RESIZE2(T, P) \
508 do { \
509 void *OLD_PTR = (P); \
510 CALLOC (T, (P), new_size); \
511 const size_t BYTES = old_lits * sizeof *(P); \
512 memcpy ((P), OLD_PTR, BYTES); \
513 void *NEW_PTR = (P); \
514 (P) = (T*)OLD_PTR; \
515 DEALLOC ((P), old_size); \
516 (P) = (T*)NEW_PTR; \
517 } while (0)
518
519static void enlarge_internal (cadical_kitten *cadical_kitten, size_t lit) {
520 const size_t new_lits = (lit | 1) + 1;
521 const size_t old_lits = cadical_kitten->lits;
522 CADICAL_assert (old_lits <= lit);
523 CADICAL_assert (old_lits < new_lits);
524 CADICAL_assert ((lit ^ 1) < new_lits);
525 CADICAL_assert (lit < new_lits);
526 const size_t old_size = cadical_kitten->size;
527 const unsigned new_vars = new_lits / 2;
528 const unsigned old_vars = old_lits / 2;
529 if (old_size < new_lits) {
530 size_t new_size = old_size ? 2 * old_size : 2;
531 while (new_size <= lit)
532 new_size *= 2;
533 LOG ("internal literals resized to %zu from %zu (requested %zu)",
534 new_size, old_size, new_lits);
535
537 RESIZE1 (unsigned char, cadical_kitten->phases);
542 RESIZE2 (katches, cadical_kitten->watches);
543
544 cadical_kitten->size = new_size;
545 }
546 cadical_kitten->lits = new_lits;
547 init_queue (cadical_kitten, old_vars, new_vars);
548 LOG ("internal literals activated until %zu literals", new_lits);
549 return;
550}
551
552static const char *status_to_string (int status) {
553 switch (status) {
554 case 10:
555 return "formula satisfied";
556 case 11:
557 return "formula satisfied and prime implicant computed";
558 case 20:
559 return "formula inconsistent";
560 case 21:
561 return "formula inconsistent and core computed";
562 default:
563 CADICAL_assert (!status);
564 return "formula unsolved";
565 }
566}
567
568static void invalid_api_usage (const char *fun, const char *fmt, ...) {
569 fprintf (stderr, "cadical_kitten: fatal error: invalid API usage in '%s': ", fun);
570 va_list ap;
571 va_start (ap, fmt);
572 vfprintf (stderr, fmt, ap);
573 va_end (ap);
574 fputc ('\n', stderr);
575 fflush (stderr);
576 abort ();
577}
578
579#define INVALID_API_USAGE(...) invalid_api_usage (__func__, __VA_ARGS__)
580
581#define REQUIRE_INITIALIZED() \
582 do { \
583 if (!cadical_kitten) \
584 INVALID_API_USAGE ("solver argument zero"); \
585 } while (0)
586
587#define REQUIRE_STATUS(EXPECTED) \
588 do { \
589 REQUIRE_INITIALIZED (); \
590 if (cadical_kitten->status != (EXPECTED)) \
591 INVALID_API_USAGE ("invalid status '%s' (expected '%s')", \
592 status_to_string (cadical_kitten->status), \
593 status_to_string (EXPECTED)); \
594 } while (0)
595
596#define UPDATE_STATUS(STATUS) \
597 do { \
598 if (cadical_kitten->status != (STATUS)) \
599 LOG ("updating status from '%s' to '%s'", \
600 status_to_string (cadical_kitten->status), status_to_string (STATUS)); \
601 else \
602 LOG ("keeping status at '%s'", status_to_string (STATUS)); \
603 cadical_kitten->status = (STATUS); \
604 } while (0)
605
609 initialize_cadical_kitten (cadical_kitten);
610 return cadical_kitten;
611}
612
613#ifdef LOGGING
614void cadical_kitten_set_logging (cadical_kitten *cadical_kitten) { logging = true; }
615#endif
616
618 REQUIRE_STATUS (0);
619
621 INVALID_API_USAGE ("can not start tracking antecedents after learning");
622
623 LOG ("enabling antecedents tracking");
625}
626
629
630 LOG ("randomizing phases");
631
632 unsigned char *phases = cadical_kitten->phases;
633 const unsigned vars = cadical_kitten->size / 2;
634
635 uint64_t random = kissat_next_random64 (&cadical_kitten->generator);
636
637 unsigned i = 0;
638 const unsigned rest = vars & ~63u;
639
640 while (i != rest) {
641 uint64_t *p = (uint64_t *) (phases + i);
642 p[0] = (random >> 0) & 0x0101010101010101;
643 p[1] = (random >> 1) & 0x0101010101010101;
644 p[2] = (random >> 2) & 0x0101010101010101;
645 p[3] = (random >> 3) & 0x0101010101010101;
646 p[4] = (random >> 4) & 0x0101010101010101;
647 p[5] = (random >> 5) & 0x0101010101010101;
648 p[6] = (random >> 6) & 0x0101010101010101;
649 p[7] = (random >> 7) & 0x0101010101010101;
650 random = kissat_next_random64 (&cadical_kitten->generator);
651 i += 64;
652 }
653
654 unsigned shift = 0;
655 while (i != vars)
656 phases[i++] = (random >> shift++) & 1;
657}
658
661
662 LOG ("flipping phases");
663
664 unsigned char *phases = cadical_kitten->phases;
665 const unsigned vars = cadical_kitten->size / 2;
666
667 unsigned i = 0;
668 const unsigned rest = vars & ~7u;
669
670 while (i != rest) {
671 uint64_t *p = (uint64_t *) (phases + i);
672 *p ^= 0x0101010101010101;
673 i += 8;
674 }
675
676 while (i != vars)
677 phases[i++] ^= 1;
678}
679
682 LOG ("forcing no ticks limit");
683 cadical_kitten->limits.ticks = UINT64_MAX;
684}
685
688 const uint64_t current = KITTEN_TICKS;
689 return current;
690}
691
694 const uint64_t current = KITTEN_TICKS;
695 uint64_t limit;
696 if (UINT64_MAX - delta <= current) {
697 LOG ("forcing unlimited ticks limit");
698 limit = UINT64_MAX;
699 } else {
700 limit = current + delta;
701 LOG ("new limit of %" PRIu64 " ticks after %" PRIu64, limit, delta);
702 }
703
704 cadical_kitten->limits.ticks = limit;
705}
706
713
715 int (*terminator) (void *)) {
717 LOG ("setting terminator");
718 cadical_kitten->terminator = terminator;
720}
721
722static void shuffle_unsigned_array (cadical_kitten *cadical_kitten, size_t size,
723 unsigned *a) {
724 for (size_t i = 0; i < size; i++) {
725 const size_t j = kissat_pick_random (&cadical_kitten->generator, 0, i);
726 if (j == i)
727 continue;
728 const unsigned first = a[i];
729 const unsigned second = a[j];
730 a[i] = second;
731 a[j] = first;
732 }
733}
734
735static void shuffle_unsigned_stack (cadical_kitten *cadical_kitten, unsigneds *stack) {
736 const size_t size = SIZE_STACK (*stack);
737 unsigned *a = BEGIN_STACK (*stack);
738 shuffle_unsigned_array (cadical_kitten, size, a);
739}
740
741static void shuffle_katches (cadical_kitten *cadical_kitten) {
742 LOG ("shuffling watch lists");
743 for (size_t lit = 0; lit < cadical_kitten->lits; lit++)
744 shuffle_unsigned_stack (cadical_kitten, &KATCHES (lit));
745}
746
747static void shuffle_queue (cadical_kitten *cadical_kitten) {
748 LOG ("shuffling variable decision order");
749
750 const unsigned vars = cadical_kitten->lits / 2;
751 for (unsigned i = 0; i < vars; i++) {
752 const unsigned idx = kissat_pick_random (&cadical_kitten->generator, 0, vars);
753 dequeue (cadical_kitten, idx);
754 enqueue (cadical_kitten, idx);
755 }
756 update_search (cadical_kitten, cadical_kitten->queue.last);
757}
758
759static void shuffle_units (cadical_kitten *cadical_kitten) {
760 LOG ("shuffling units");
761 shuffle_unsigned_stack (cadical_kitten, &cadical_kitten->units);
762}
763
765 REQUIRE_STATUS (0);
766 shuffle_queue (cadical_kitten);
767 shuffle_katches (cadical_kitten);
768 shuffle_units (cadical_kitten);
769}
770
771static inline unsigned *antecedents (klause *c) {
772 CADICAL_assert (is_learned_klause (c));
773 return c->lits + c->size;
774}
775
776static inline void watch_klause (cadical_kitten *cadical_kitten, unsigned lit,
777 unsigned ref) {
778 ROG (ref, "watching %u in", lit);
779 katches *watches = &KATCHES (lit);
780 PUSH_STACK (*watches, ref);
781}
782
783static inline void connect_new_klause (cadical_kitten *cadical_kitten, unsigned ref) {
784 ROG (ref, "new");
785
786 klause *c = dereference_klause (cadical_kitten, ref);
787
788 if (!c->size) {
790 ROG (ref, "registering inconsistent empty");
792 } else
793 ROG (ref, "ignoring inconsistent empty");
794 } else if (c->size == 1) {
795 ROG (ref, "watching unit");
797 } else {
798 watch_klause (cadical_kitten, c->lits[0], ref);
799 watch_klause (cadical_kitten, c->lits[1], ref);
800 }
801}
802
803static unsigned new_reference (cadical_kitten *cadical_kitten) {
805 if (ref >= INVALID) {
806 die ("maximum number of literals exhausted");
807 }
808 const unsigned res = (unsigned) ref;
809 CADICAL_assert (res != INVALID);
810 INC (cadical_kitten_ticks);
811 return res;
812}
813
814static void new_original_klause (cadical_kitten *cadical_kitten, unsigned id) {
815 unsigned res = new_reference (cadical_kitten);
816 unsigned size = SIZE_STACK (cadical_kitten->klause);
817 unsigneds *klauses = &cadical_kitten->klauses;
818 PUSH_STACK (*klauses, id);
819 PUSH_STACK (*klauses, size);
820 PUSH_STACK (*klauses, 0);
821 for (all_stack (unsigned, lit, cadical_kitten->klause))
822 PUSH_STACK (*klauses, lit);
823 connect_new_klause (cadical_kitten, res);
826}
827
828static void enlarge_external (cadical_kitten *cadical_kitten, size_t eidx) {
829 const size_t old_size = cadical_kitten->esize;
830 const unsigned old_evars = cadical_kitten->evars;
831 CADICAL_assert (old_evars <= eidx);
832 const unsigned new_evars = eidx + 1;
833 if (old_size <= eidx) {
834 size_t new_size = old_size ? 2 * old_size : 1;
835 while (new_size <= eidx)
836 new_size *= 2;
837 LOG ("external resizing to %zu variables from %zu (requested %u)",
838 new_size, old_size, new_evars);
839 unsigned *old_import = cadical_kitten->import;
840 CALLOC (unsigned, cadical_kitten->import, new_size);
841 const size_t bytes = old_evars * sizeof *cadical_kitten->import;
842 memcpy (cadical_kitten->import, old_import, bytes);
843 DEALLOC (old_import, old_size);
844 cadical_kitten->esize = new_size;
845 }
846 cadical_kitten->evars = new_evars;
847 LOG ("external variables enlarged to %u", new_evars);
848}
849
850static unsigned import_literal (cadical_kitten *cadical_kitten, unsigned elit) {
851 const unsigned eidx = elit / 2;
852 if (eidx >= cadical_kitten->evars)
853 enlarge_external (cadical_kitten, eidx);
854
855 unsigned iidx = cadical_kitten->import[eidx];
856 if (!iidx) {
859 cadical_kitten->import[eidx] = iidx + 1;
860 } else
861 iidx--;
862 unsigned ilit = 2 * iidx + (elit & 1);
863 LOG ("imported external literal %u as internal literal %u", elit, ilit);
864 if (ilit >= cadical_kitten->lits)
865 enlarge_internal (cadical_kitten, ilit);
866 return ilit;
867}
868
869static unsigned export_literal (cadical_kitten *cadical_kitten, unsigned ilit) {
870 const unsigned iidx = ilit / 2;
872 const unsigned eidx = PEEK_STACK (cadical_kitten->export_, iidx);
873 const unsigned elit = 2 * eidx + (ilit & 1);
874 return elit;
875}
876
878 unsigned res = new_reference (cadical_kitten);
879 unsigneds *klauses = &cadical_kitten->klauses;
880 const size_t size = SIZE_STACK (cadical_kitten->klause);
881 CADICAL_assert (size <= UINT_MAX);
882 const size_t aux =
884 CADICAL_assert (aux <= UINT_MAX);
885 PUSH_STACK (*klauses, (unsigned) aux);
886 PUSH_STACK (*klauses, (unsigned) size);
887 PUSH_STACK (*klauses, LEARNED_FLAG);
888 for (all_stack (unsigned, lit, cadical_kitten->klause))
889 PUSH_STACK (*klauses, lit);
890 if (aux)
891 for (all_stack (unsigned, ref, cadical_kitten->resolved))
892 PUSH_STACK (*klauses, ref);
893 connect_new_klause (cadical_kitten, res);
894 cadical_kitten->learned = true;
896 return res;
897}
898
900 LOG ("clear cadical_kitten of size %zu", cadical_kitten->size);
901
905
915
916 for (all_kits (kit))
917 CLEAR_STACK (KATCHES (kit));
918
921
922 const size_t lits = cadical_kitten->size;
923 const unsigned vars = lits / 2;
924
925#ifndef CADICAL_NDEBUG
926 for (unsigned i = 0; i < vars; i++)
928#endif
929
930 memset (cadical_kitten->phases, 0, vars);
931 memset (cadical_kitten->values, 0, lits);
932 memset (cadical_kitten->failed, 0, lits);
933 memset (cadical_kitten->vars, 0, vars);
934
935 clear_cadical_kitten (cadical_kitten);
936}
937
970
971static inline void move_to_front (cadical_kitten *cadical_kitten, unsigned idx) {
972 if (idx == cadical_kitten->queue.last)
973 return;
974 LOG ("move to front variable %u", idx);
975 dequeue (cadical_kitten, idx);
976 enqueue (cadical_kitten, idx);
978}
979
980static inline void assign (cadical_kitten *cadical_kitten, unsigned lit, unsigned reason) {
981#ifdef LOGGING
982 if (reason == INVALID)
983 LOG ("assign %u as decision", lit);
984 else
985 ROG (reason, "assign %u reason", lit);
986#endif
987 value *values = cadical_kitten->values;
988 const unsigned not_lit = lit ^ 1;
989 CADICAL_assert (!values[lit]);
990 CADICAL_assert (!values[not_lit]);
991 values[lit] = 1;
992 values[not_lit] = -1;
993 const unsigned idx = lit / 2;
994 const unsigned sign = lit & 1;
995 cadical_kitten->phases[idx] = sign;
997 kar *v = cadical_kitten->vars + idx;
998 v->level = cadical_kitten->level;
999 if (!v->level) {
1000 CADICAL_assert (reason != INVALID);
1001 klause *c = dereference_klause (cadical_kitten, reason);
1002 if (c->size > 1) {
1005 for (all_literals_in_klause (other, c))
1006 if (other != lit) {
1007 const unsigned other_idx = other / 2;
1008 const unsigned other_ref = cadical_kitten->vars[other_idx].reason;
1009 CADICAL_assert (other_ref != INVALID);
1010 PUSH_STACK (cadical_kitten->resolved, other_ref);
1011 }
1012 }
1017 }
1018 }
1019 v->reason = reason;
1022}
1023
1024static inline unsigned propagate_literal (cadical_kitten *cadical_kitten, unsigned lit) {
1025 LOG ("propagating %u", lit);
1026 value *values = cadical_kitten->values;
1027 CADICAL_assert (values[lit] > 0);
1028 const unsigned not_lit = lit ^ 1;
1029 katches *watches = cadical_kitten->watches + not_lit;
1030 unsigned conflict = INVALID;
1031 unsigned *q = BEGIN_STACK (*watches);
1032 const unsigned *const end_watches = END_STACK (*watches);
1033 unsigned const *p = q;
1034 uint64_t ticks = (((char *) end_watches - (char *) q) >> 7) + 1;
1035 while (p != end_watches) {
1036 const unsigned ref = *q++ = *p++;
1037 klause *c = dereference_klause (cadical_kitten, ref);
1038 CADICAL_assert (c->size > 1);
1039 unsigned *lits = c->lits;
1040 const unsigned other = lits[0] ^ lits[1] ^ not_lit;
1041 const value other_value = values[other];
1042 ticks++;
1043 if (other_value > 0)
1044 continue;
1045 value replacement_value = -1;
1046 unsigned replacement = INVALID;
1047 const unsigned *const end_lits = lits + c->size;
1048 unsigned *r;
1049 for (r = lits + 2; r != end_lits; r++) {
1050 replacement = *r;
1051 replacement_value = values[replacement];
1052 if (replacement_value >= 0)
1053 break;
1054 }
1055 if (replacement_value >= 0) {
1056 CADICAL_assert (replacement != INVALID);
1057 ROG (ref, "unwatching %u in", not_lit);
1058 lits[0] = other;
1059 lits[1] = replacement;
1060 *r = not_lit;
1061 watch_klause (cadical_kitten, replacement, ref);
1062 q--;
1063 } else if (other_value < 0) {
1064 ROG (ref, "conflict");
1065 INC (cadical_kitten_conflicts);
1066 conflict = ref;
1067 break;
1068 } else {
1069 CADICAL_assert (!other_value);
1070 assign (cadical_kitten, other, ref);
1071 }
1072 }
1073 while (p != end_watches)
1074 *q++ = *p++;
1076 ADD (cadical_kitten_ticks, ticks);
1077 return conflict;
1078}
1079
1080static inline unsigned propagate (cadical_kitten *cadical_kitten) {
1082 unsigned propagated = 0;
1083 unsigned conflict = INVALID;
1084 while (conflict == INVALID &&
1088 break;
1089 }
1091 conflict = propagate_literal (cadical_kitten, lit);
1093 propagated++;
1094 }
1095 ADD (cadical_kitten_propagations, propagated);
1096 return conflict;
1097}
1098
1099static void bump (cadical_kitten *cadical_kitten) {
1100 value *marks = cadical_kitten->marks;
1101 for (all_stack (unsigned, idx, cadical_kitten->analyzed)) {
1102 marks[idx] = 0;
1103 move_to_front (cadical_kitten, idx);
1104 }
1105 check_queue (cadical_kitten);
1106}
1107
1108static inline void unassign (cadical_kitten *cadical_kitten, value *values, unsigned lit) {
1109 const unsigned not_lit = lit ^ 1;
1110 CADICAL_assert (values[lit]);
1111 CADICAL_assert (values[not_lit]);
1112 const unsigned idx = lit / 2;
1113#ifdef LOGGING
1114 kar *var = cadical_kitten->vars + idx;
1115 cadical_kitten->level = var->level;
1116 LOG ("unassign %u", lit);
1117#endif
1118 values[lit] = values[not_lit] = 0;
1122 kink *link = links + idx;
1124 update_search (cadical_kitten, idx);
1125}
1126
1127static void backtrack (cadical_kitten *cadical_kitten, unsigned jump) {
1128 check_queue (cadical_kitten);
1129 CADICAL_assert (jump < cadical_kitten->level);
1130 LOG ("back%s to level %u",
1131 (cadical_kitten->level == jump + 1 ? "tracking" : "jumping"), jump);
1132 kar *vars = cadical_kitten->vars;
1133 value *values = cadical_kitten->values;
1134 unsigneds *trail = &cadical_kitten->trail;
1135 while (!EMPTY_STACK (*trail)) {
1136 const unsigned lit = TOP_STACK (*trail);
1137 const unsigned idx = lit / 2;
1138 const unsigned level = vars[idx].level;
1139 if (level == jump)
1140 break;
1141 (void) POP_STACK (*trail);
1142 unassign (cadical_kitten, values, lit);
1143 }
1145 cadical_kitten->level = jump;
1146 check_queue (cadical_kitten);
1147}
1148
1150 check_queue (cadical_kitten);
1151 LOG ("completely backtracking to level 0");
1152 value *values = cadical_kitten->values;
1153 unsigneds *trail = &cadical_kitten->trail;
1154 unsigneds *units = &cadical_kitten->units;
1155#ifndef CADICAL_NDEBUG
1156 kar *vars = cadical_kitten->vars;
1157#endif
1158 for (all_stack (unsigned, lit, *trail)) {
1159 CADICAL_assert (vars[lit / 2].level);
1160 unassign (cadical_kitten, values, lit);
1161 }
1162 CLEAR_STACK (*trail);
1163 for (all_stack (unsigned, ref, *units)) {
1164 klause *c = dereference_klause (cadical_kitten, ref);
1165 CADICAL_assert (c->size == 1);
1166 const unsigned unit = c->lits[0];
1167 const value value = values[unit];
1168 if (value <= 0)
1169 continue;
1170 unassign (cadical_kitten, values, unit);
1171 }
1173 cadical_kitten->level = 0;
1174 check_queue (cadical_kitten);
1175}
1176
1177static void analyze (cadical_kitten *cadical_kitten, unsigned conflict) {
1184 unsigned reason = conflict;
1185 value *marks = cadical_kitten->marks;
1186 const kar *const vars = cadical_kitten->vars;
1187 const unsigned level = cadical_kitten->level;
1188 unsigned const *p = END_STACK (cadical_kitten->trail);
1189 unsigned open = 0, jump = 0, size = 1, uip;
1190 for (;;) {
1191 CADICAL_assert (reason != INVALID);
1192 klause *c = dereference_klause (cadical_kitten, reason);
1193 CADICAL_assert (c);
1194 ROG (reason, "analyzing");
1196 for (all_literals_in_klause (lit, c)) {
1197 const unsigned idx = lit / 2;
1198 if (marks[idx])
1199 continue;
1201 LOG ("analyzed %u", lit);
1202 marks[idx] = true;
1204 const kar *const v = vars + idx;
1205 const unsigned tmp = v->level;
1206 if (tmp < level) {
1207 if (tmp > jump) {
1208 jump = tmp;
1209 if (size > 1) {
1210 const unsigned other = PEEK_STACK (cadical_kitten->klause, 1);
1212 lit = other;
1213 }
1214 }
1216 size++;
1217 } else
1218 open++;
1219 }
1220 unsigned idx;
1221 do {
1223 uip = *--p;
1224 } while (!marks[idx = uip / 2]);
1225 CADICAL_assert (open);
1226 if (!--open)
1227 break;
1228 reason = vars[idx].reason;
1229 }
1230 const unsigned not_uip = uip ^ 1;
1231 LOG ("first UIP %u jump level %u size %u", not_uip, jump, size);
1232 POKE_STACK (cadical_kitten->klause, 0, not_uip);
1233 bump (cadical_kitten);
1235 const unsigned learned_ref = cadical_new_learned_klause (cadical_kitten);
1238 backtrack (cadical_kitten, jump);
1239 assign (cadical_kitten, not_uip, learned_ref);
1240}
1241
1242static void failing (cadical_kitten *cadical_kitten) {
1248 LOG ("analyzing failing assumptions");
1249 const value *const values = cadical_kitten->values;
1250 const kar *const vars = cadical_kitten->vars;
1251 unsigned failed_clashing = INVALID;
1252 unsigned first_failed = INVALID;
1253 unsigned failed_unit = INVALID;
1254 for (all_stack (unsigned, lit, cadical_kitten->assumptions)) {
1255 if (values[lit] >= 0)
1256 continue;
1257 if (first_failed == INVALID)
1258 first_failed = lit;
1259 const unsigned failed_idx = lit / 2;
1260 const kar *const failed_var = vars + failed_idx;
1261 if (!failed_var->level) {
1262 failed_unit = lit;
1263 break;
1264 }
1265 if (failed_clashing == INVALID && failed_var->reason == INVALID)
1266 failed_clashing = lit;
1267 }
1268 unsigned failed;
1269 if (failed_unit != INVALID)
1270 failed = failed_unit;
1271 else if (failed_clashing != INVALID)
1272 failed = failed_clashing;
1273 else
1274 failed = first_failed;
1275 CADICAL_assert (failed != INVALID);
1276 const unsigned failed_idx = failed / 2;
1277 const kar *const failed_var = vars + failed_idx;
1278 const unsigned failed_reason = failed_var->reason;
1279 LOG ("first failed assumption %u", failed);
1280 cadical_kitten->failed[failed] = true;
1281
1282 if (failed_unit != INVALID) {
1283 CADICAL_assert (dereference_klause (cadical_kitten, failed_reason)->size == 1);
1284 LOG ("root-level falsified assumption %u", failed);
1285 cadical_kitten->failing = failed_reason;
1286 ROG (cadical_kitten->failing, "failing reason");
1287 return;
1288 }
1289
1290 const unsigned not_failed = failed ^ 1;
1291 if (failed_clashing != INVALID) {
1292 LOG ("clashing with negated assumption %u", not_failed);
1293 cadical_kitten->failed[not_failed] = true;
1295 return;
1296 }
1297
1298 value *marks = cadical_kitten->marks;
1299 CADICAL_assert (!marks[failed_idx]);
1300 marks[failed_idx] = true;
1301 PUSH_STACK (cadical_kitten->analyzed, failed_idx);
1302 PUSH_STACK (cadical_kitten->klause, not_failed);
1303
1304 unsigneds work;
1305 INIT_STACK (work);
1306
1308 "trail");
1309
1311 unsigned const *p = END_STACK (cadical_kitten->trail);
1312 unsigned open = 1;
1313 for (;;) {
1314 if (!open)
1315 break;
1316 open--;
1317 unsigned idx, uip;
1318 do {
1320 uip = *--p;
1321 } while (!marks[idx = uip / 2]);
1322
1323 const kar *var = vars + idx;
1324 const unsigned reason = var->reason;
1325 if (reason == INVALID) {
1326 unsigned lit = 2 * idx;
1327 if (values[lit] < 0)
1328 lit ^= 1;
1329 LOG ("failed assumption %u", lit);
1331 cadical_kitten->failed[lit] = true;
1332 const unsigned not_lit = lit ^ 1;
1333 PUSH_STACK (cadical_kitten->klause, not_lit);
1334 } else {
1335 ROG (reason, "analyzing");
1337 klause *c = dereference_klause (cadical_kitten, reason);
1338 for (all_literals_in_klause (other, c)) {
1339 const unsigned other_idx = other / 2;
1340 if (marks[other_idx])
1341 continue;
1342 CADICAL_assert (other_idx != idx);
1343 marks[other_idx] = true;
1344 CADICAL_assert (values[other]);
1345 if (vars[other_idx].level)
1346 open++;
1347 else
1348 PUSH_STACK (work, other_idx);
1349 PUSH_STACK (cadical_kitten->analyzed, other_idx);
1350
1351 LOG ("analyzing final literal %u", other ^ 1);
1352 }
1353 }
1354 }
1355 for (size_t next = 0; next < SIZE_STACK (work); next++) {
1356 const unsigned idx = PEEK_STACK (work, next);
1357 const kar *var = vars + idx;
1358 const unsigned reason = var->reason;
1359 if (reason == INVALID) {
1360 unsigned lit = 2 * idx;
1361 if (values[lit] < 0)
1362 lit ^= 1;
1363 LOG ("failed assumption %u", lit);
1365 cadical_kitten->failed[lit] = true;
1366 const unsigned not_lit = lit ^ 1;
1367 PUSH_STACK (cadical_kitten->klause, not_lit);
1368 } else {
1369 ROG (reason, "analyzing unit");
1371 }
1372 }
1373
1374 // this is bfs not dfs so it does not work for lrat :/
1375 /*
1376 for (size_t next = 0; next < SIZE_STACK (cadical_kitten->analyzed); next++) {
1377 const unsigned idx = PEEK_STACK (cadical_kitten->analyzed, next);
1378 CADICAL_assert (marks[idx]);
1379 const kar *var = vars + idx;
1380 const unsigned reason = var->reason;
1381 if (reason == INVALID) {
1382 unsigned lit = 2 * idx;
1383 if (values[lit] < 0)
1384 lit ^= 1;
1385 LOG ("failed assumption %u", lit);
1386 CADICAL_assert (!cadical_kitten->failed[lit]);
1387 cadical_kitten->failed[lit] = true;
1388 const unsigned not_lit = lit ^ 1;
1389 PUSH_STACK (cadical_kitten->klause, not_lit);
1390 } else {
1391 ROG (reason, "analyzing");
1392 PUSH_STACK (cadical_kitten->resolved, reason);
1393 klause *c = dereference_klause (cadical_kitten, reason);
1394 for (all_literals_in_klause (other, c)) {
1395 const unsigned other_idx = other / 2;
1396 if (other_idx == idx)
1397 continue;
1398 if (marks[other_idx])
1399 continue;
1400 marks[other_idx] = true;
1401 PUSH_STACK (cadical_kitten->analyzed, other_idx);
1402 LOG ("analyzing final literal %u", other ^ 1);
1403 }
1404 }
1405 }
1406 */
1407
1408 for (all_stack (unsigned, idx, cadical_kitten->analyzed))
1409 CADICAL_assert (marks[idx]), marks[idx] = 0;
1411
1412 RELEASE_STACK (work);
1413
1414 const size_t resolved = SIZE_STACK (cadical_kitten->resolved);
1415 CADICAL_assert (resolved);
1416
1417 if (resolved == 1) {
1419 ROG (cadical_kitten->failing, "reusing as core");
1420 } else {
1422 ROG (cadical_kitten->failing, "new core");
1423 }
1424
1427}
1428
1429static void flush_trail (cadical_kitten *cadical_kitten) {
1430 unsigneds *trail = &cadical_kitten->trail;
1431 LOG ("flushing %zu root-level literals from trail", SIZE_STACK (*trail));
1434 CLEAR_STACK (*trail);
1435}
1436
1437static int decide (cadical_kitten *cadical_kitten) {
1439 flush_trail (cadical_kitten);
1440
1441 const value *const values = cadical_kitten->values;
1442 unsigned decision = INVALID;
1443 const size_t assumptions = SIZE_STACK (cadical_kitten->assumptions);
1444 while (cadical_kitten->level < assumptions) {
1445 unsigned assumption = PEEK_STACK (cadical_kitten->assumptions, cadical_kitten->level);
1446 value value = values[assumption];
1447 if (value < 0) {
1448 LOG ("found failing assumption %u", assumption);
1449 failing (cadical_kitten);
1450 return 20;
1451 } else if (value > 0) {
1452
1454 LOG ("pseudo decision level %u for already satisfied assumption %u",
1455 cadical_kitten->level, assumption);
1456 } else {
1457 decision = assumption;
1458 LOG ("using assumption %u as decision", decision);
1459 break;
1460 }
1461 }
1462
1464 return 10;
1465
1467 LOG ("ticks limit %" PRIu64 " hit after %" PRIu64 " ticks",
1469 return -1;
1470 }
1471
1473 LOG ("terminator requested termination");
1474 return -1;
1475 }
1476
1477 if (decision == INVALID) {
1478 unsigned idx = cadical_kitten->queue.search;
1479 const kink *const links = cadical_kitten->links;
1480 for (;;) {
1481 CADICAL_assert (idx != INVALID);
1482 if (!values[2 * idx])
1483 break;
1484 idx = links[idx].prev;
1485 }
1486 update_search (cadical_kitten, idx);
1487 const unsigned phase = cadical_kitten->phases[idx];
1488 decision = 2 * idx + phase;
1489 LOG ("decision %u variable %u phase %u", decision, idx, phase);
1490 }
1491 INC (cadical_kitten_decisions);
1493 assign (cadical_kitten, decision, INVALID);
1494 return 0;
1495}
1496
1497static void inconsistent (cadical_kitten *cadical_kitten, unsigned ref) {
1498 CADICAL_assert (ref != INVALID);
1500
1503 ROG (ref, "registering inconsistent virtually empty");
1504 return;
1505 }
1506
1507 unsigneds *analyzed = &cadical_kitten->analyzed;
1508 unsigneds *resolved = &cadical_kitten->resolved;
1509
1510 CADICAL_assert (EMPTY_STACK (*analyzed));
1511 CADICAL_assert (EMPTY_STACK (*resolved));
1512
1513 value *marks = cadical_kitten->marks;
1514 const kar *const vars = cadical_kitten->vars;
1515 unsigned next = 0;
1516
1517 for (;;) {
1518 CADICAL_assert (ref != INVALID);
1519 klause *c = dereference_klause (cadical_kitten, ref);
1520 CADICAL_assert (c);
1521 ROG (ref, "analyzing inconsistent");
1522 PUSH_STACK (*resolved, ref);
1523 for (all_literals_in_klause (lit, c)) {
1524 const unsigned idx = lit / 2;
1525 CADICAL_assert (!vars[idx].level);
1526 if (marks[idx])
1527 continue;
1529 LOG ("analyzed %u", lit);
1530 marks[idx] = true;
1532 }
1533 if (next == SIZE_STACK (cadical_kitten->analyzed))
1534 break;
1535 const unsigned idx = PEEK_STACK (cadical_kitten->analyzed, next);
1536 next++;
1537 const kar *const v = vars + idx;
1538 CADICAL_assert (!v->level);
1539 ref = v->reason;
1540 }
1543 ROG (ref, "registering final inconsistent empty");
1545
1546 for (all_stack (unsigned, idx, *analyzed))
1547 marks[idx] = 0;
1548
1549 CLEAR_STACK (*analyzed);
1550 CLEAR_STACK (*resolved);
1551}
1552
1553static int propagate_units (cadical_kitten *cadical_kitten) {
1555 return 20;
1556
1558 LOG ("no root level unit clauses");
1559 return 0;
1560 }
1561
1562 LOG ("propagating %zu root level unit clauses",
1564
1565 const value *const values = cadical_kitten->values;
1566
1567 for (size_t next = 0; next < SIZE_STACK (cadical_kitten->units); next++) {
1568 const unsigned ref = PEEK_STACK (cadical_kitten->units, next);
1569 CADICAL_assert (ref != INVALID);
1570 klause *c = dereference_klause (cadical_kitten, ref);
1571 CADICAL_assert (c->size == 1);
1572 ROG (ref, "propagating unit");
1573 const unsigned unit = c->lits[0];
1574 const value value = values[unit];
1575 if (value > 0)
1576 continue;
1577 if (value < 0) {
1578 inconsistent (cadical_kitten, ref);
1579 return 20;
1580 }
1581 assign (cadical_kitten, unit, ref);
1582 }
1583 const unsigned conflict = propagate (cadical_kitten);
1584 if (conflict == INVALID)
1585 return 0;
1586 inconsistent (cadical_kitten, conflict);
1587 return 20;
1588}
1589
1590/*------------------------------------------------------------------------*/
1591
1592static klause *begin_klauses (cadical_kitten *cadical_kitten) {
1594}
1595
1596static klause *end_original_klauses (cadical_kitten *cadical_kitten) {
1597 return (klause *) (BEGIN_STACK (cadical_kitten->klauses) +
1599}
1600
1601static klause *end_klauses (cadical_kitten *cadical_kitten) {
1602 return (klause *) END_STACK (cadical_kitten->klauses);
1603}
1604
1605static klause *next_klause (cadical_kitten *cadical_kitten, klause *c) {
1606 CADICAL_assert (begin_klauses (cadical_kitten) <= c);
1607 CADICAL_assert (c < end_klauses (cadical_kitten));
1608 unsigned *res = c->lits + c->size;
1609 if (cadical_kitten->antecedents && is_learned_klause (c))
1610 res += c->aux;
1611 return (klause *) res;
1612}
1613
1614/*------------------------------------------------------------------------*/
1615
1616static void reset_core (cadical_kitten *cadical_kitten) {
1617 LOG ("resetting core clauses");
1618 size_t reset = 0;
1619 for (all_klauses (c))
1620 if (is_core_klause (c))
1621 unset_core_klause (c), reset++;
1622 LOG ("reset %zu core clauses", reset);
1624}
1625
1626static void reset_assumptions (cadical_kitten *cadical_kitten) {
1627 LOG ("reset %zu assumptions", SIZE_STACK (cadical_kitten->assumptions));
1629 const unsigned assumption = POP_STACK (cadical_kitten->assumptions);
1630 cadical_kitten->failed[assumption] = false;
1631 }
1632#ifndef CADICAL_NDEBUG
1633 for (size_t i = 0; i < cadical_kitten->size; i++)
1635#endif
1637 if (cadical_kitten->failing != INVALID) {
1638 ROG (cadical_kitten->failing, "reset failed assumption reason");
1640 }
1641}
1642
1643static void reset_incremental (cadical_kitten *cadical_kitten) {
1644 // if (cadical_kitten->level)
1647 reset_assumptions (cadical_kitten);
1648 else
1650 if (cadical_kitten->status == 21)
1651 reset_core (cadical_kitten);
1652 UPDATE_STATUS (0);
1653}
1654
1655/*------------------------------------------------------------------------*/
1656
1657static bool flip_literal (cadical_kitten *cadical_kitten, unsigned lit) {
1658 INC (cadical_kitten_flip);
1659 signed char *values = cadical_kitten->values;
1660 if (values[lit] < 0)
1661 lit ^= 1;
1662 LOG ("trying to flip value of satisfied literal %u", lit);
1663 CADICAL_assert (values[lit] > 0);
1664 katches *watches = cadical_kitten->watches + lit;
1665 unsigned *q = BEGIN_STACK (*watches);
1666 const unsigned *const end_watches = END_STACK (*watches);
1667 unsigned const *p = q;
1668 uint64_t ticks = (((char *) end_watches - (char *) q) >> 7) + 1;
1669 bool res = true;
1670 while (p != end_watches) {
1671 const unsigned ref = *q++ = *p++;
1672 klause *c = dereference_klause (cadical_kitten, ref);
1673 unsigned *lits = c->lits;
1674 const unsigned other = lits[0] ^ lits[1] ^ lit;
1675 const value other_value = values[other];
1676 ticks++;
1677 if (other_value > 0)
1678 continue;
1679 value replacement_value = -1;
1680 unsigned replacement = INVALID;
1681 const unsigned *const end_lits = lits + c->size;
1682 unsigned *r;
1683 for (r = lits + 2; r != end_lits; r++) {
1684 replacement = *r;
1685 CADICAL_assert (replacement != lit);
1686 replacement_value = values[replacement];
1687 CADICAL_assert (replacement_value);
1688 if (replacement_value > 0)
1689 break;
1690 }
1691 if (replacement_value > 0) {
1692 CADICAL_assert (replacement != INVALID);
1693 ROG (ref, "unwatching %u in", lit);
1694 lits[0] = other;
1695 lits[1] = replacement;
1696 *r = lit;
1697 watch_klause (cadical_kitten, replacement, ref);
1698 q--;
1699 } else {
1700 CADICAL_assert (replacement_value < 0);
1701 ROG (ref, "single satisfied");
1702 res = false;
1703 break;
1704 }
1705 }
1706 while (p != end_watches)
1707 *q++ = *p++;
1709 ADD (cadical_kitten_ticks, ticks);
1710 if (res) {
1711 LOG ("flipping value of %u", lit);
1712 values[lit] = -1;
1713 const unsigned not_lit = lit ^ 1;
1714 values[not_lit] = 1;
1715 INC (cadical_kitten_flipped);
1716 } else
1717 LOG ("failed to flip value of %u", lit);
1718 return res;
1719}
1720
1721/*------------------------------------------------------------------------*/
1722
1723// this cadical specific clause addition avoids copying clauses multiple
1724// times just to convert literals to unsigned representation.
1725//
1726static unsigned int2u (int lit) {
1727 CADICAL_assert (lit != 0);
1728 int idx = abs (lit) - 1;
1729 return (lit < 0) + 2u * (unsigned) idx;
1730}
1731
1735 reset_incremental (cadical_kitten);
1736 const unsigned ilit = import_literal (cadical_kitten, elit);
1737 LOG ("registering assumption %u", ilit);
1739}
1740
1742 unsigned kelit = int2u (elit);
1744}
1745
1747 size_t size,
1748 const unsigned *elits,
1749 unsigned except) {
1752 reset_incremental (cadical_kitten);
1754 const unsigned *const end = elits + size;
1755 for (const unsigned *p = elits; p != end; p++) {
1756 const unsigned elit = *p;
1757 if (elit == except)
1758 continue;
1759 const unsigned ilit = import_literal (cadical_kitten, elit);
1760 CADICAL_assert (ilit < cadical_kitten->lits);
1761 const unsigned iidx = ilit / 2;
1762 if (cadical_kitten->marks[iidx])
1763 INVALID_API_USAGE ("variable '%u' of literal '%u' occurs twice",
1764 elit / 2, elit);
1765 cadical_kitten->marks[iidx] = true;
1767 }
1768 for (unsigned *p = cadical_kitten->klause.begin; p != cadical_kitten->klause.end; p++)
1769 cadical_kitten->marks[*p / 2] = false;
1770 new_original_klause (cadical_kitten, id);
1772}
1773
1775 size_t size, const int *elits,
1776 unsigned except) {
1779 reset_incremental (cadical_kitten);
1781 const int *const end = elits + size;
1782 for (const int *p = elits; p != end; p++) {
1783 const unsigned elit = int2u (*p); // this is the conversion
1784 if (elit == except)
1785 continue;
1786 const unsigned ilit = import_literal (cadical_kitten, elit);
1787 CADICAL_assert (ilit < cadical_kitten->lits);
1788 const unsigned iidx = ilit / 2;
1789 if (cadical_kitten->marks[iidx])
1790 INVALID_API_USAGE ("variable '%u' of literal '%u' occurs twice",
1791 elit / 2, elit);
1792 cadical_kitten->marks[iidx] = true;
1794 }
1795 for (unsigned *p = cadical_kitten->klause.begin; p != cadical_kitten->klause.end; p++)
1796 cadical_kitten->marks[*p / 2] = false;
1797 new_original_klause (cadical_kitten, id);
1799}
1800
1802 size_t size, const int *elits,
1803 unsigned lit, unsigned other) {
1806 reset_incremental (cadical_kitten);
1808 bool sat = false;
1809 const int *const end = elits + size;
1810 for (const int *p = elits; p != end; p++) {
1811 const unsigned elit = int2u (*p); // this is the conversion
1812 if (elit == (lit ^ 1u) || elit == (other ^ 1u))
1813 continue;
1814 if (elit == lit || elit == other) {
1815 sat = true;
1816 break;
1817 }
1818 const unsigned ilit = import_literal (cadical_kitten, elit);
1819 CADICAL_assert (ilit < cadical_kitten->lits);
1820 const unsigned iidx = ilit / 2;
1821 if (cadical_kitten->marks[iidx])
1822 INVALID_API_USAGE ("variable '%u' of literal '%u' occurs twice",
1823 elit / 2, elit);
1824 cadical_kitten->marks[iidx] = true;
1826 }
1827 for (unsigned *p = cadical_kitten->klause.begin; p != cadical_kitten->klause.end; p++)
1828 cadical_kitten->marks[*p / 2] = false;
1829 if (!sat)
1830 new_original_klause (cadical_kitten, id);
1832}
1833
1838
1839void citten_clause_with_id (cadical_kitten *cadical_kitten, unsigned id, size_t size,
1840 int *elits) {
1842}
1843
1847
1848void cadical_kitten_binary (cadical_kitten *cadical_kitten, unsigned a, unsigned b) {
1849 unsigned clause[2] = {a, b};
1851}
1852
1856 reset_incremental (cadical_kitten);
1857 else // if (cadical_kitten->level)
1859
1860 LOG ("starting solving under %zu assumptions",
1862
1863 INC (cadical_kitten_solved);
1864
1865 int res = propagate_units (cadical_kitten);
1866 while (!res) {
1867 const unsigned conflict = propagate (cadical_kitten);
1870 LOG ("terminator requested termination");
1871 res = -1;
1872 break;
1873 }
1874 if (conflict != INVALID) {
1875 if (cadical_kitten->level)
1876 analyze (cadical_kitten, conflict);
1877 else {
1878 inconsistent (cadical_kitten, conflict);
1879 res = 20;
1880 }
1881 } else
1882 res = decide (cadical_kitten);
1883 }
1884
1885 if (res < 0)
1886 res = 0;
1887
1888 if (!res && !EMPTY_STACK (cadical_kitten->assumptions))
1889 reset_assumptions (cadical_kitten);
1890
1891 UPDATE_STATUS (res);
1892
1893 if (res == 10)
1894 INC (cadical_kitten_sat);
1895 else if (res == 20)
1896 INC (cadical_kitten_unsat);
1897 else
1898 INC (cadical_kitten_unknown);
1899
1900 LOG ("finished solving with result %d", res);
1901
1902 return res;
1903}
1904
1906
1908 uint64_t *learned_ptr) {
1909 REQUIRE_STATUS (20);
1910
1912 INVALID_API_USAGE ("antecedents not tracked");
1913
1914 LOG ("computing clausal core");
1915
1916 unsigneds *resolved = &cadical_kitten->resolved;
1917 CADICAL_assert (EMPTY_STACK (*resolved));
1918
1919 unsigned original = 0;
1920 uint64_t learned = 0;
1921
1922 unsigned reason_ref = cadical_kitten->inconsistent;
1923
1924 if (reason_ref == INVALID) {
1926 reason_ref = cadical_kitten->failing;
1927 if (reason_ref == INVALID) {
1928 LOG ("assumptions mutually inconsistent");
1929 //goto DONE;
1930 if (learned_ptr)
1931 *learned_ptr = learned;
1932
1933 LOG ("clausal core of %u original clauses", original);
1934 LOG ("clausal core of %" PRIu64 " learned clauses", learned);
1937 UPDATE_STATUS (21);
1938
1939 return original;
1940 }
1941 }
1942
1943 PUSH_STACK (*resolved, reason_ref);
1944 unsigneds *core = &cadical_kitten->core;
1945 CADICAL_assert (EMPTY_STACK (*core));
1946
1947 while (!EMPTY_STACK (*resolved)) {
1948 const unsigned c_ref = POP_STACK (*resolved);
1949 if (c_ref == INVALID) {
1950 const unsigned d_ref = POP_STACK (*resolved);
1951 ROG (d_ref, "core[%zu]", SIZE_STACK (*core));
1952 PUSH_STACK (*core, d_ref);
1953 klause *d = dereference_klause (cadical_kitten, d_ref);
1954 CADICAL_assert (!is_core_klause (d));
1955 set_core_klause (d);
1956 if (is_learned_klause (d))
1957 learned++;
1958 else
1959 original++;
1960 } else {
1961 klause *c = dereference_klause (cadical_kitten, c_ref);
1962 if (is_core_klause (c))
1963 continue;
1964 PUSH_STACK (*resolved, c_ref);
1965 PUSH_STACK (*resolved, INVALID);
1966 ROG (c_ref, "analyzing antecedent core");
1967 if (!is_learned_klause (c))
1968 continue;
1969 for (all_antecedents (d_ref, c)) {
1970 klause *d = dereference_klause (cadical_kitten, d_ref);
1971 if (!is_core_klause (d))
1972 PUSH_STACK (*resolved, d_ref);
1973 }
1974 }
1975 }
1976
1977 //DONE:
1978
1979 if (learned_ptr)
1980 *learned_ptr = learned;
1981
1982 LOG ("clausal core of %u original clauses", original);
1983 LOG ("clausal core of %" PRIu64 " learned clauses", learned);
1986 UPDATE_STATUS (21);
1987
1988 return original;
1989}
1990
1992 void (*traverse) (void *, unsigned)) {
1993 REQUIRE_STATUS (21);
1994
1995 LOG ("traversing core of original clauses");
1996
1997 unsigned traversed = 0;
1998
1999 for (all_original_klauses (c)) {
2000 // only happens for 'true' incremental calls, i.e. if add happens after
2001 // solve
2002 if (is_learned_klause (c))
2003 continue;
2004 if (!is_core_klause (c))
2005 continue;
2006 ROG (reference_klause (cadical_kitten, c), "traversing");
2007 traverse (state, c->aux);
2008 traversed++;
2009 }
2010
2011 LOG ("traversed %u original core clauses", traversed);
2012 (void) traversed;
2013
2015}
2016
2018 void (*traverse) (void *, bool, size_t,
2019 const unsigned *)) {
2020 REQUIRE_STATUS (21);
2021
2022 LOG ("traversing clausal core");
2023
2024 unsigned traversed = 0;
2025
2026 for (all_stack (unsigned, c_ref, cadical_kitten->core)) {
2027 klause *c = dereference_klause (cadical_kitten, c_ref);
2028 CADICAL_assert (is_core_klause (c));
2029 const bool learned = is_learned_klause (c);
2030 unsigneds *eclause = &cadical_kitten->eclause;
2031 CADICAL_assert (EMPTY_STACK (*eclause));
2032 for (all_literals_in_klause (ilit, c)) {
2033 const unsigned elit = export_literal (cadical_kitten, ilit);
2034 PUSH_STACK (*eclause, elit);
2035 }
2036 const size_t size = SIZE_STACK (*eclause);
2037 const unsigned *elits = eclause->begin;
2038 ROG (reference_klause (cadical_kitten, c), "traversing");
2039 traverse (state, learned, size, elits);
2040 CLEAR_STACK (*eclause);
2041 traversed++;
2042 }
2043
2044 LOG ("traversed %u core clauses", traversed);
2045 (void) traversed;
2046
2048}
2049
2051 cadical_kitten *cadical_kitten, void *state,
2052 void (*traverse) (void *state, unsigned, bool learned, size_t,
2053 const unsigned *)) {
2054 REQUIRE_STATUS (21);
2055
2056 LOG ("traversing clausal core");
2057
2058 unsigned traversed = 0;
2059
2060 for (all_stack (unsigned, c_ref, cadical_kitten->core)) {
2061 klause *c = dereference_klause (cadical_kitten, c_ref);
2062 CADICAL_assert (is_core_klause (c));
2063 const bool learned = is_learned_klause (c);
2064 unsigneds *eclause = &cadical_kitten->eclause;
2065 CADICAL_assert (EMPTY_STACK (*eclause));
2066 for (all_literals_in_klause (ilit, c)) {
2067 const unsigned elit = export_literal (cadical_kitten, ilit);
2068 PUSH_STACK (*eclause, elit);
2069 }
2070 const size_t size = SIZE_STACK (*eclause);
2071 const unsigned *elits = eclause->begin;
2072 ROG (reference_klause (cadical_kitten, c), "traversing");
2073 unsigned ctag = learned ? 0 : c->aux;
2074 traverse (state, ctag, learned, size, elits);
2075 CLEAR_STACK (*eclause);
2076 traversed++;
2077 }
2078
2079 LOG ("traversed %u core clauses", traversed);
2080 (void) traversed;
2081
2083}
2084
2086 void (*trace) (void *, unsigned, unsigned, bool,
2087 size_t, const unsigned *, size_t,
2088 const unsigned *)) {
2089 REQUIRE_STATUS (21);
2090
2091 LOG ("tracing clausal core");
2092
2093 unsigned traced = 0;
2094
2095 for (all_stack (unsigned, c_ref, cadical_kitten->core)) {
2096 klause *c = dereference_klause (cadical_kitten, c_ref);
2097 CADICAL_assert (is_core_klause (c));
2098 const bool learned = is_learned_klause (c);
2099 unsigneds *eclause = &cadical_kitten->eclause;
2100 CADICAL_assert (EMPTY_STACK (*eclause));
2101 for (all_literals_in_klause (ilit, c)) {
2102 const unsigned elit = export_literal (cadical_kitten, ilit);
2103 PUSH_STACK (*eclause, elit);
2104 }
2105 const size_t size = SIZE_STACK (*eclause);
2106 const unsigned *elits = eclause->begin;
2107
2108 unsigneds *resolved = &cadical_kitten->resolved;
2109 CADICAL_assert (EMPTY_STACK (*resolved));
2110 if (learned) {
2111 for (all_antecedents (ref, c)) {
2112 PUSH_STACK (*resolved, ref);
2113 }
2114 }
2115 const size_t rsize = SIZE_STACK (*resolved);
2116 const unsigned *rids = resolved->begin;
2117
2118 unsigned cid = reference_klause (cadical_kitten, c);
2119 unsigned ctag = learned ? 0 : c->aux;
2120 ROG (cid, "tracing");
2121 trace (state, cid, ctag, learned, size, elits, rsize, rids);
2122 CLEAR_STACK (*eclause);
2123 CLEAR_STACK (*resolved);
2124 traced++;
2125 }
2126
2127 LOG ("traced %u core clauses", traced);
2128 (void) traced;
2129
2131}
2132
2134 REQUIRE_STATUS (21);
2135
2136 LOG ("shrinking formula to core of original clauses");
2137
2139
2142 cadical_kitten->level = 0;
2143
2144 update_search (cadical_kitten, cadical_kitten->queue.last);
2145
2147
2148 for (all_kits (lit))
2150
2152 klause *inconsistent = dereference_klause (cadical_kitten, cadical_kitten->inconsistent);
2153 if (is_learned_klause (inconsistent) || inconsistent->size) {
2154 ROG (cadical_kitten->inconsistent, "resetting inconsistent");
2156 } else
2157 ROG (cadical_kitten->inconsistent, "keeping inconsistent");
2158
2160
2161 klause *begin = begin_klauses (cadical_kitten), *q = begin;
2162 klause const *const end = end_original_klauses (cadical_kitten);
2163#ifdef LOGGING
2164 unsigned original = 0;
2165#endif
2166 for (klause *c = begin, *next; c != end; c = next) {
2167 next = next_klause (cadical_kitten, c);
2168 // CADICAL_assert (!is_learned_klause (c)); not necessarily true
2169 if (is_learned_klause (c))
2170 continue;
2171 if (!is_core_klause (c))
2172 continue;
2173 unset_core_klause (c);
2174 const unsigned dst = (unsigned *) q - (unsigned *) begin;
2175 const unsigned size = c->size;
2176 if (!size) {
2179 } else if (size == 1) {
2181 ROG (dst, "keeping");
2182 } else {
2183 watch_klause (cadical_kitten, c->lits[0], dst);
2184 watch_klause (cadical_kitten, c->lits[1], dst);
2185 }
2186 if (c == q)
2187 q = next;
2188 else {
2189 const size_t bytes = (char *) next - (char *) c;
2190 memmove (q, c, bytes);
2191 q = (klause *) ((char *) q + bytes);
2192 }
2193#ifdef LOGGING
2194 original++;
2195#endif
2196 }
2197 SET_END_OF_STACK (cadical_kitten->klauses, (unsigned *) q);
2199 LOG ("end of original clauses at %zu", cadical_kitten->end_original_ref);
2200 LOG ("%u original clauses left", original);
2201
2203
2204 UPDATE_STATUS (0);
2205}
2206
2208 REQUIRE_STATUS (10);
2209 const unsigned elit = int2u (selit);
2210 const unsigned eidx = elit / 2;
2211 if (eidx >= cadical_kitten->evars)
2212 return 0;
2213 unsigned iidx = cadical_kitten->import[eidx];
2214 if (!iidx)
2215 return 0;
2216 const unsigned ilit = 2 * (iidx - 1) + (elit & 1);
2217 return cadical_kitten->values[ilit];
2218}
2219
2221 REQUIRE_STATUS (10);
2222 const unsigned eidx = elit / 2;
2223 if (eidx >= cadical_kitten->evars)
2224 return 0;
2225 unsigned iidx = cadical_kitten->import[eidx];
2226 if (!iidx)
2227 return 0;
2228 const unsigned ilit = 2 * (iidx - 1) + (elit & 1);
2229 return cadical_kitten->values[ilit];
2230}
2231
2233 const unsigned eidx = elit / 2;
2234 if (eidx >= cadical_kitten->evars)
2235 return 0;
2236 unsigned iidx = cadical_kitten->import[eidx];
2237 if (!iidx)
2238 return 0;
2239 iidx--;
2240 const unsigned ilit = 2 * iidx + (elit & 1);
2241 signed char res = cadical_kitten->values[ilit];
2242 if (!res)
2243 return 0;
2244 kar *v = cadical_kitten->vars + iidx;
2245 if (v->level)
2246 return 0;
2247 return res;
2248}
2249
2251 unsigned kelit = int2u (elit);
2252 return cadical_kitten_fixed (cadical_kitten, kelit);
2253}
2254
2256 REQUIRE_STATUS (10);
2257 const unsigned eidx = elit / 2;
2258 if (eidx >= cadical_kitten->evars)
2259 return false;
2260 unsigned iidx = cadical_kitten->import[eidx];
2261 if (!iidx)
2262 return false;
2263 const unsigned ilit = 2 * (iidx - 1) + (elit & 1);
2265 return false;
2266 return flip_literal (cadical_kitten, ilit);
2267}
2268
2270 REQUIRE_STATUS (10);
2271 unsigned kelit = int2u (elit);
2273}
2274
2276 REQUIRE_STATUS (20);
2277 const unsigned eidx = elit / 2;
2278 if (eidx >= cadical_kitten->evars)
2279 return false;
2280 unsigned iidx = cadical_kitten->import[eidx];
2281 if (!iidx)
2282 return false;
2283 const unsigned ilit = 2 * (iidx - 1) + (elit & 1);
2284 return cadical_kitten->failed[ilit];
2285}
2286
2287// checks both watches for clauses with only one literal positively
2288// assigned. if such a clause is found, return false. Otherwise fix watch
2289// invariant and return true
2290static bool prime_propagate (cadical_kitten *cadical_kitten, const unsigned idx,
2291 void *state, const bool ignoring,
2292 bool (*ignore) (void *, unsigned)) {
2293 unsigned lit = 2 * idx;
2294 unsigned conflict = INVALID;
2295 value *values = cadical_kitten->values;
2296 for (int i = 0; i < 2; i++) {
2297 if (conflict != INVALID)
2298 break;
2299 lit = lit ^ i;
2300 const unsigned not_lit = lit ^ 1;
2301 katches *watches = cadical_kitten->watches + not_lit;
2302 unsigned *q = BEGIN_STACK (*watches);
2303 const unsigned *const end_watches = END_STACK (*watches);
2304 unsigned const *p = q;
2305 uint64_t ticks = (((char *) end_watches - (char *) q) >> 7) + 1;
2306 while (p != end_watches) {
2307 const unsigned ref = *q++ = *p++;
2308 klause *c = dereference_klause (cadical_kitten, ref);
2309 if (is_learned_klause (c) || ignore (state, c->aux) == ignoring)
2310 continue;
2311 CADICAL_assert (c->size > 1);
2312 unsigned *lits = c->lits;
2313 const unsigned other = lits[0] ^ lits[1] ^ not_lit;
2314 const value other_value = values[other];
2315 ticks++;
2316 if (other_value > 0)
2317 continue;
2318 value replacement_value = -1;
2319 unsigned replacement = INVALID;
2320 const unsigned *const end_lits = lits + c->size;
2321 unsigned *r;
2322 for (r = lits + 2; r != end_lits; r++) {
2323 replacement = *r;
2324 replacement_value = values[replacement];
2325 if (replacement_value > 0)
2326 break;
2327 }
2328 if (replacement_value > 0) {
2329 CADICAL_assert (replacement != INVALID);
2330 ROG (ref, "unwatching %u in", not_lit);
2331 lits[0] = other;
2332 lits[1] = replacement;
2333 *r = not_lit;
2334 watch_klause (cadical_kitten, replacement, ref);
2335 q--;
2336 } else {
2337 ROG (ref, "idx %u forced prime by", idx);
2338 conflict = ref;
2339 break;
2340 }
2341 }
2342 while (p != end_watches)
2343 *q++ = *p++;
2345 ADD (cadical_kitten_ticks, ticks);
2346 }
2347 return conflict == INVALID;
2348}
2349
2351 void (*add_implicant) (void *, int, size_t,
2352 const unsigned *)) {
2353 REQUIRE_STATUS (11);
2354 // might be possible in some edge cases
2355 unsigneds *prime = &cadical_kitten->prime[side];
2356 unsigneds *prime2 = &cadical_kitten->prime[!side];
2357 CADICAL_assert (!EMPTY_STACK (*prime) || !EMPTY_STACK (*prime2));
2358 CLEAR_STACK (*prime2);
2359
2360 for (all_stack (unsigned, lit, *prime)) {
2361 const unsigned not_lit = lit ^ 1;
2362 const unsigned elit = export_literal (cadical_kitten, not_lit);
2363 PUSH_STACK (*prime2, elit);
2364 }
2365
2366 // adds a clause which will reset cadical_kitten status and backtrack
2367 add_implicant (state, side, SIZE_STACK (*prime2), BEGIN_STACK (*prime2));
2368 CLEAR_STACK (*prime);
2369 CLEAR_STACK (*prime2);
2370}
2371
2372// computes two prime implicants, only considering clauses based on ignore
2373// return -1 if no prime implicant has been computed, otherwise returns
2374// index of shorter implicant.
2375// TODO does not work if flip has been called beforehand
2377 bool (*ignore) (void *, unsigned)) {
2378 REQUIRE_STATUS (10);
2379
2380 value *values = cadical_kitten->values;
2381 kar *vars = cadical_kitten->vars;
2382 unsigneds unassigned;
2383 INIT_STACK (unassigned);
2384 bool limit_hit = 0;
2386 for (int i = 0; i < 2; i++) {
2387 const bool ignoring = i;
2388 for (all_stack (unsigned, lit, cadical_kitten->trail)) {
2390 LOG ("ticks limit %" PRIu64 " hit after %" PRIu64 " ticks",
2392 limit_hit = 1;
2393 break;
2394 }
2395 CADICAL_assert (values[lit] > 0);
2396 const unsigned idx = lit / 2;
2397 const unsigned ref = vars[idx].reason;
2398 CADICAL_assert (vars[idx].level);
2399 klause *c = 0;
2400 if (ref != INVALID)
2401 c = dereference_klause (cadical_kitten, ref);
2402 if (ref == INVALID || is_learned_klause (c) ||
2403 ignore (state, c->aux) == ignoring) {
2404 LOG ("non-prime candidate var %d", idx);
2405 if (prime_propagate (cadical_kitten, idx, state, ignoring, ignore)) {
2406 values[lit] = 0;
2407 values[lit ^ 1] = 0;
2408 PUSH_STACK (unassigned, lit);
2409 } else
2410 CADICAL_assert (values[lit] > 0);
2411 }
2412 }
2413 unsigneds *prime = &cadical_kitten->prime[i];
2414 // push on prime implicant stack.
2415 for (all_kits (lit)) {
2416 if (values[lit] > 0)
2417 PUSH_STACK (*prime, lit);
2418 }
2419 // reassign all literals on
2420 for (all_stack (unsigned, lit, unassigned)) {
2421 CADICAL_assert (!values[lit]);
2422 values[lit] = 1;
2423 values[lit ^ 1] = -1;
2424 }
2425 CLEAR_STACK (unassigned);
2426 }
2427 RELEASE_STACK (unassigned);
2428
2429 if (limit_hit) {
2432 return -1;
2433 }
2434 // the only case when one of the prime implicants is allowed to be empty
2435 // is if ignore returns always true or always false.
2438 UPDATE_STATUS (11);
2439
2441 return res;
2442}
2443
2444static bool contains_blit (cadical_kitten *cadical_kitten, klause *c, const unsigned blit) {
2445 for (all_literals_in_klause (lit, c)) {
2446 if (lit == blit)
2447 return true;
2448 }
2449 return false;
2450}
2451
2452static bool prime_propagate_blit (cadical_kitten *cadical_kitten, const unsigned idx,
2453 const unsigned blit) {
2454 unsigned lit = 2 * idx;
2455 unsigned conflict = INVALID;
2456 value *values = cadical_kitten->values;
2457 LOG ("prime propagating idx %u for blit %u", idx, blit);
2458 for (int i = 0; i < 2; i++) {
2459 if (conflict != INVALID)
2460 break;
2461 lit = lit ^ i;
2462 if (lit == blit)
2463 continue;
2464 const unsigned not_lit = lit ^ 1;
2465 katches *watches = cadical_kitten->watches + not_lit;
2466 unsigned *q = BEGIN_STACK (*watches);
2467 const unsigned *const end_watches = END_STACK (*watches);
2468 unsigned const *p = q;
2469 uint64_t ticks = (((char *) end_watches - (char *) q) >> 7) + 1;
2470 while (p != end_watches) {
2471 const unsigned ref = *q++ = *p++;
2472 klause *c = dereference_klause (cadical_kitten, ref);
2473 if (is_learned_klause (c))
2474 continue;
2475 ROG (ref, "checking with blit %u", blit);
2476 CADICAL_assert (c->size > 1);
2477 unsigned *lits = c->lits;
2478 const unsigned other = lits[0] ^ lits[1] ^ not_lit;
2479 const value other_value = values[other];
2480 ticks++;
2481 bool use = other == blit || not_lit == blit;
2482 if (other_value > 0)
2483 continue;
2484 value replacement_value = -1;
2485 unsigned replacement = INVALID;
2486 const unsigned *const end_lits = lits + c->size;
2487 unsigned *r;
2488 for (r = lits + 2; r != end_lits; r++) {
2489 replacement = *r;
2490 replacement_value = values[replacement];
2491 use = use || replacement == blit;
2492 if (replacement_value > 0)
2493 break;
2494 }
2495 if (replacement_value > 0) {
2496 CADICAL_assert (replacement != INVALID);
2497 ROG (ref, "unwatching %u in", not_lit);
2498 lits[0] = other;
2499 lits[1] = replacement;
2500 *r = not_lit;
2501 watch_klause (cadical_kitten, replacement, ref);
2502 q--;
2503 } else if (!use) {
2504 continue;
2505 } else {
2506 ROG (ref, "idx %u forced prime by", idx);
2507 conflict = ref;
2508 break;
2509 }
2510 }
2511 while (p != end_watches)
2512 *q++ = *p++;
2514 ADD (cadical_kitten_ticks, ticks);
2515 }
2516 return conflict == INVALID;
2517}
2518
2519static int compute_prime_implicant_for (cadical_kitten *cadical_kitten, unsigned blit) {
2520 value *values = cadical_kitten->values;
2521 kar *vars = cadical_kitten->vars;
2522 unsigneds unassigned;
2523 INIT_STACK (unassigned);
2524 bool limit_hit = false;
2526 for (int i = 0; i < 2; i++) {
2527 const unsigned block = blit ^ i;
2528 const bool ignoring = i;
2529 if (prime_propagate_blit (cadical_kitten, block / 2, block)) {
2530 value tmp = values[blit];
2531 CADICAL_assert (tmp);
2532 values[blit] = 0;
2533 values[blit ^ 1] = 0;
2534 PUSH_STACK (unassigned, tmp > 0 ? blit : blit ^ 1);
2535 PUSH_STACK (cadical_kitten->prime[i], block); // will be negated!
2536 } else
2537 CADICAL_assert (false);
2538 for (all_stack (unsigned, lit, cadical_kitten->trail)) {
2540 LOG ("ticks limit %" PRIu64 " hit after %" PRIu64 " ticks",
2542 limit_hit = true;
2543 break;
2544 }
2545 if (!values[lit])
2546 continue;
2547 CADICAL_assert (values[lit]); // not true when flipping is involved
2548 const unsigned idx = lit / 2;
2549 const unsigned ref = vars[idx].reason;
2550 CADICAL_assert (vars[idx].level);
2551 LOG ("non-prime candidate var %d", idx);
2552 if (prime_propagate_blit (cadical_kitten, idx, block)) {
2553 value tmp = values[lit];
2554 CADICAL_assert (tmp);
2555 values[lit] = 0;
2556 values[lit ^ 1] = 0;
2557 PUSH_STACK (unassigned, tmp > 0 ? lit : lit ^ 1);
2558 }
2559 }
2560 unsigneds *prime = &cadical_kitten->prime[i];
2561 // push on prime implicant stack.
2562 for (all_kits (lit)) {
2563 if (values[lit] > 0)
2564 PUSH_STACK (*prime, lit);
2565 }
2566 // reassign all literals on
2567 for (all_stack (unsigned, lit, unassigned)) {
2568 CADICAL_assert (!values[lit]);
2569 values[lit] = 1;
2570 values[lit ^ 1] = -1;
2571 }
2572 CLEAR_STACK (unassigned);
2573 }
2574 RELEASE_STACK (unassigned);
2575
2576 if (limit_hit) {
2579 return -1;
2580 }
2581 // the only case when one of the prime implicants is allowed to be empty
2582 // is if ignore returns always true or always false.
2586 "first implicant %u", blit);
2588 "second implicant %u", blit ^ 1);
2589 UPDATE_STATUS (11);
2590
2592 return res;
2593}
2594
2596 int elit) {
2597 REQUIRE_STATUS (10);
2598 unsigned kelit = int2u (elit);
2600 return -2;
2601 }
2602 const unsigned eidx = kelit / 2;
2603 unsigned iidx = cadical_kitten->import[eidx];
2604 CADICAL_assert (iidx);
2605 const unsigned ilit = 2 * (iidx - 1) + (kelit & 1);
2606 return compute_prime_implicant_for (cadical_kitten, ilit);
2607}
2608
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define CADICAL_assert(ignore)
Definition global.h:14
#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 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 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 TOP_STACK(S)
Definition stack.h:27
#define INIT_STACK(S)
Definition stack.h:22
#define STACK(TYPE)
Definition stack.h:10
#define END_STACK(S)
Definition stack.h:48
void cadical_kitten_assume_signed(cadical_kitten *cadical_kitten, int elit)
struct kink kink
void cadical_kitten_traverse_core_clauses_with_id(cadical_kitten *cadical_kitten, void *state, void(*traverse)(void *state, unsigned, bool learned, size_t, const unsigned *))
#define ADD(NAME, DELTA)
void citten_clause_with_id_and_equivalence(cadical_kitten *cadical_kitten, unsigned id, size_t size, const int *elits, unsigned lit, unsigned other)
#define RESIZE2(T, P)
#define all_klauses(C)
void cadical_kitten_clause(cadical_kitten *cadical_kitten, size_t size, unsigned *elits)
#define INC(NAME)
void cadical_kitten_shuffle_clauses(cadical_kitten *cadical_kitten)
void cadical_kitten_no_terminator(cadical_kitten *cadical_kitten)
struct kimits kimits
void cadical_completely_backtrack_to_root_level(cadical_kitten *cadical_kitten)
void cadical_kitten_no_ticks_limit(cadical_kitten *cadical_kitten)
#define CALLOC(T, P, N)
#define REQUIRE_INITIALIZED()
unsigned cadical_kitten_compute_clausal_core(cadical_kitten *cadical_kitten, uint64_t *learned_ptr)
cadical_kitten * cadical_kitten_init(void)
#define LOG(...)
int cadical_kitten_flip_and_implicant_for_signed_literal(cadical_kitten *cadical_kitten, int elit)
bool cadical_kitten_flip_literal(cadical_kitten *cadical_kitten, unsigned elit)
uint64_t cadical_kitten_current_ticks(cadical_kitten *cadical_kitten)
signed char cadical_kitten_fixed(cadical_kitten *cadical_kitten, unsigned elit)
void cadical_kitten_set_ticks_limit(cadical_kitten *cadical_kitten, uint64_t delta)
void cadical_kitten_traverse_core_clauses(cadical_kitten *cadical_kitten, void *state, void(*traverse)(void *, bool, size_t, const unsigned *))
void cadical_kitten_flip_phases(cadical_kitten *cadical_kitten)
void cadical_kitten_unit(cadical_kitten *cadical_kitten, unsigned lit)
#define all_antecedents(REF, C)
ABC_NAMESPACE_IMPL_START typedef signed char value
signed char cadical_kitten_signed_value(cadical_kitten *cadical_kitten, int selit)
#define all_literals_in_klause(KIT, C)
#define ROG(...)
void cadical_kitten_binary(cadical_kitten *cadical_kitten, unsigned a, unsigned b)
#define LOGLITS(...)
#define REQUIRE_STATUS(EXPECTED)
int cadical_kitten_solve(cadical_kitten *cadical_kitten)
#define CORE_FLAG
void cadical_kitten_trace_core(cadical_kitten *cadical_kitten, void *state, void(*trace)(void *, unsigned, unsigned, bool, size_t, const unsigned *, size_t, const unsigned *))
void cadical_kitten_set_terminator(cadical_kitten *cadical_kitten, void *data, int(*terminator)(void *))
#define INVALID_API_USAGE(...)
void cadical_kitten_add_prime_implicant(cadical_kitten *cadical_kitten, void *state, int side, void(*add_implicant)(void *, int, size_t, const unsigned *))
#define KATCHES(KIT)
void cadical_kitten_clear(cadical_kitten *cadical_kitten)
#define LEARNED_FLAG
void citten_clause_with_id(cadical_kitten *cadical_kitten, unsigned id, size_t size, int *elits)
#define RESIZE1(T, P)
#define all_original_klauses(C)
void cadical_kitten_randomize_phases(cadical_kitten *cadical_kitten)
void cadical_kitten_assume(cadical_kitten *cadical_kitten, unsigned elit)
int cadical_kitten_status(cadical_kitten *cadical_kitten)
#define KITTEN_TICKS
void citten_clause_with_id_and_exception(cadical_kitten *cadical_kitten, unsigned id, size_t size, const int *elits, unsigned except)
int cadical_kitten_compute_prime_implicant(cadical_kitten *cadical_kitten, void *state, bool(*ignore)(void *, unsigned))
bool cadical_kitten_flip_signed_literal(cadical_kitten *cadical_kitten, int elit)
signed char cadical_kitten_value(cadical_kitten *cadical_kitten, unsigned elit)
void cadical_kitten_release(cadical_kitten *cadical_kitten)
void cadical_kitten_shrink_to_clausal_core(cadical_kitten *cadical_kitten)
void cadical_kitten_clause_with_id_and_exception(cadical_kitten *cadical_kitten, unsigned id, size_t size, const unsigned *elits, unsigned except)
#define DEALLOC(P, N)
signed char cadical_kitten_fixed_signed(cadical_kitten *cadical_kitten, int elit)
unsigned cadical_new_learned_klause(cadical_kitten *cadical_kitten)
#define INVALID
void cadical_kitten_traverse_core_ids(cadical_kitten *cadical_kitten, void *state, void(*traverse)(void *, unsigned))
#define all_kits(KIT)
#define UPDATE_STATUS(STATUS)
void cadical_kitten_track_antecedents(cadical_kitten *cadical_kitten)
struct kar kar
bool cadical_kitten_failed(cadical_kitten *cadical_kitten, unsigned elit)
bool trace
Definition globals.c:36
Cube * p
Definition exorList.c:222
#define vprintf
Definition fretime.h:138
bool sign(Lit p)
Definition SolverTypes.h:63
unsigned long long size
Definition giaNewBdd.h:39
unsigned short ref
Definition giaNewBdd.h:38
unsigned short var
Definition giaNewBdd.h:35
int lit
Definition satVec.h:130
unsigneds prime[2]
statistics statistics
unsigned char * phases
unsigneds assumptions
unsigned * import
int(* terminator)(void *)
struct cadical_kitten::@204357353010102162247340364316301064170137016325 queue
unsigned inconsistent
uint64_t ticks
uint64_t stamp
unsigned next
unsigned prev
unsigned size
unsigned aux
unsigned lits[1]
unsigned flags
Definition queue.h:20
uint64_t cadical_kitten_unsat
uint64_t cadical_kitten_conflicts
uint64_t cadical_kitten_ticks
uint64_t cadical_kitten_flipped
uint64_t cadical_kitten_propagations
uint64_t cadical_kitten_sat
uint64_t cadical_kitten_flip
uint64_t original
uint64_t cadical_kitten_solved
uint64_t learned
uint64_t cadical_kitten_unknown
uint64_t cadical_kitten_decisions
char * memcpy()
char * calloc()
VOID_HACK abort()
char * memset()
char * memmove()
VOID_HACK free()
VOID_HACK exit()
long random()
vector watches
Definition watch.h:49
#define const
Definition zconf.h:196