ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
kitten.c
Go to the documentation of this file.
1#include "kitten.h"
2#include "random.h"
3#include "stack.h"
4
5#include <assert.h>
6#include <inttypes.h>
7#include <limits.h>
8#include <stdarg.h>
9#include <stdbool.h>
10#include <stdint.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14
15/*------------------------------------------------------------------------*/
16#ifdef STAND_ALONE_KITTEN
17/*------------------------------------------------------------------------*/
18
19#include <unistd.h>
20
21// clang-format off
22
23static const char * usage =
24"usage: kitten [-h]"
25#ifdef LOGGING
26" [-l]"
27#endif
28" [-n] [-O[<n>]] [-p] [ <dimacs> [ <output> ] ]\n"
29"\n"
30"where\n"
31"\n"
32#ifdef LOGGING
33" -l enable low-level logging\n"
34#endif
35" -n do not print witness\n"
36" -O[<effort>] core shrinking effort\n"
37" -p produce DRAT proof\n"
38" -a <lit> assume a literal\n"
39" -t <sec> set time limit\n"
40"\n"
41"and\n"
42"\n"
43" <dimacs> input in DIMACS format (default '<stdin>')\n"
44" <output> DRAT proof or clausal core file\n"
45;
46
47// clang-format on
48
49// Replacement for 'kissat' allocators in the stand alone variant.
50
51typedef signed char value;
52
53static void die (const char *fmt, ...) {
54 fputs ("kitten: error: ", stderr);
55 va_list ap;
56 va_start (ap, fmt);
57 vfprintf (stderr, fmt, ap);
58 va_end (ap);
59 fputc ('\n', stderr);
60 exit (1);
61}
62
63static inline void *kitten_calloc (size_t n, size_t size) {
64 void *res = calloc (n, size);
65 if (n && size && !res)
66 die ("out of memory allocating '%zu * %zu' bytes", n, size);
67 return res;
68}
69
70#define CALLOC(T, P, N) \
71 do { \
72 (P) = (T*) kitten_calloc (N, sizeof *(P)); \
73 } while (0)
74#define DEALLOC(P, N) free (P)
75
76#undef ENLARGE_STACK
77
78#define ENLARGE_STACK(S) \
79 do { \
80 KISSAT_assert (FULL_STACK (S)); \
81 const size_t SIZE = SIZE_STACK (S); \
82 const size_t OLD_CAPACITY = CAPACITY_STACK (S); \
83 const size_t NEW_CAPACITY = OLD_CAPACITY ? 2 * OLD_CAPACITY : 1; \
84 const size_t BYTES = NEW_CAPACITY * sizeof *(S).begin; \
85 (S).begin = realloc ((S).begin, BYTES); \
86 if (!(S).begin) \
87 die ("out of memory reallocating '%zu' bytes", BYTES); \
88 (S).allocated = (S).begin + NEW_CAPACITY; \
89 (S).end = (S).begin + SIZE; \
90 } while (0)
91
92// Beside allocators above also use stand alone statistics counters.
93
94#define INC(NAME) \
95 do { \
96 statistics *statistics = &kitten->statistics; \
97 KISSAT_assert (statistics->NAME < UINT64_MAX); \
98 statistics->NAME++; \
99 } while (0)
100
101#define ADD(NAME, DELTA) \
102 do { \
103 statistics *statistics = &kitten->statistics; \
104 KISSAT_assert (statistics->NAME <= UINT64_MAX - (DELTA)); \
105 statistics->NAME += (DELTA); \
106 } while (0)
107
108#define KITTEN_TICKS (kitten->statistics.kitten_ticks)
109
110/*------------------------------------------------------------------------*/
111#else // '#ifdef STAND_ALONE_KITTEN'
112/*------------------------------------------------------------------------*/
113
114#include "allocate.h" // Use 'kissat' allocator if embedded.
115#include "error.h" // Use 'kissat_fatal' if embedded.
116#include "internal.h" // Also use 'kissat' statistics if embedded.
117#include "terminate.h" // For macros defining termination macro.
118
119#define KITTEN_TICKS (solver->statistics_.kitten_ticks)
120
121/*------------------------------------------------------------------------*/
122#endif // STAND_ALONE_KITTEN
123/*------------------------------------------------------------------------*/
124
126
127#define INVALID UINT_MAX
128#define MAX_VARS ((1u << 31) - 1)
129
130#define CORE_FLAG (1u)
131#define LEARNED_FLAG (2u)
132
133// clang-format off
134
135typedef struct kar kar;
136typedef struct kink kink;
137typedef struct klause klause;
138typedef struct katch katch;
139typedef STACK (unsigned) klauses;
140typedef STACK (katch) katches;
141
142// clang-format on
143
144struct kar {
145 unsigned level;
146 unsigned reason;
147};
148
149struct kink {
150 unsigned next;
151 unsigned prev;
152 uint64_t stamp;
153};
154
155#define KITTEN_BLIT
156
157#ifdef KITTEN_BLIT
158
159struct katch {
160 unsigned blit;
161 unsigned ref : 31;
162 bool binary : 1;
163};
164
165#else
166
167struct katch {
168 unsigned ref;
169};
170
171#endif
172
173struct klause {
174 unsigned aux;
175 unsigned size;
176 unsigned flags;
177 unsigned lits[1];
178};
179
180#ifdef STAND_ALONE_KITTEN
181
182typedef struct statistics statistics;
183
184struct statistics {
185 uint64_t learned;
186 uint64_t original;
187 uint64_t kitten_flip;
188 uint64_t kitten_flipped;
189 uint64_t kitten_sat;
190 uint64_t kitten_solve;
191 uint64_t kitten_solved;
192 uint64_t kitten_conflicts;
193 uint64_t kitten_decisions;
194 uint64_t kitten_propagations;
195 uint64_t kitten_ticks;
196 uint64_t kitten_unknown;
197 uint64_t kitten_unsat;
198};
199
200#endif
201
202typedef struct kimits kimits;
203
204struct kimits {
205 uint64_t ticks;
206};
207
208struct kitten {
209#ifndef STAND_ALONE_KITTEN
210 struct kissat *kissat;
211#define solver (kitten->kissat)
212#endif
213
214 // First zero initialized field in 'clear_kitten' is 'status'.
215 //
217
218#if defined(STAND_ALONE_KITTEN) && defined(LOGGING)
219 bool logging;
220#endif
223
224 unsigned level;
225 unsigned propagated;
226 unsigned unassigned;
227 unsigned inconsistent;
228 unsigned failing;
229
230 uint64_t generator;
231
232 size_t lits;
233 size_t evars;
234
236
237 struct {
238 unsigned first, last;
239 uint64_t stamp;
240 unsigned search;
242
243 // The 'size' field below is the first not zero reinitialized field
244 // by 'memset' in 'clear_kitten' (after 'kissat').
245
246 size_t size;
247 size_t esize;
248
253 bool *failed;
254 unsigned char *phases;
255 unsigned *import;
256 katches *watches;
257
258 unsigneds analyzed;
259 unsigneds assumptions;
260 unsigneds core;
261 unsigneds eclause;
262 unsigneds export_;
263 unsigneds klause;
264 unsigneds klauses;
265 unsigneds resolved;
266 unsigneds trail;
267 unsigneds units;
268
270 uint64_t initialized;
271
272#ifdef STAND_ALONE_KITTEN
274#endif
275};
276
277/*------------------------------------------------------------------------*/
278
279static inline bool is_core_klause (klause *c) {
280 return c->flags & CORE_FLAG;
281}
282
283static inline bool is_learned_klause (klause *c) {
284 return c->flags & LEARNED_FLAG;
285}
286
287static inline void set_core_klause (klause *c) { c->flags |= CORE_FLAG; }
288
289static inline void unset_core_klause (klause *c) { c->flags &= ~CORE_FLAG; }
290
291static inline klause *dereference_klause (kitten *kitten, unsigned ref) {
292 unsigned *res = BEGIN_STACK (kitten->klauses) + ref;
294 return (klause *) res;
295}
296
297#ifdef LOGGING
298
299static inline unsigned reference_klause (kitten *kitten, const klause *c) {
300 const unsigned *const begin = BEGIN_STACK (kitten->klauses);
301 const unsigned *p = (const unsigned *) c;
302 KISSAT_assert (begin <= p);
304 const unsigned res = p - begin;
305 return res;
306}
307
308#endif
309
310/*------------------------------------------------------------------------*/
311
312#define KATCHES(KIT) (kitten->watches[KISSAT_assert ((KIT) < kitten->lits), (KIT)])
313
314#define all_klauses(C) \
315 klause *C = begin_klauses (kitten), *end_##C = end_klauses (kitten); \
316 (C) != end_##C; \
317 (C) = next_klause (kitten, C)
318
319#define all_original_klauses(C) \
320 klause *C = begin_klauses (kitten), \
321 *end_##C = end_original_klauses (kitten); \
322 (C) != end_##C; \
323 (C) = next_klause (kitten, C)
324
325#define all_learned_klauses(C) \
326 klause *C = begin_learned_klauses (kitten), \
327 *end_##C = end_klauses (kitten); \
328 (C) != end_##C; \
329 (C) = next_klause (kitten, C)
330
331#define all_kits(KIT) \
332 size_t KIT = 0, KIT_##END = kitten->lits; \
333 KIT != KIT_##END; \
334 KIT++
335
336#define BEGIN_KLAUSE(C) (C)->lits
337
338#define END_KLAUSE(C) (BEGIN_KLAUSE (C) + (C)->size)
339
340#define all_literals_in_klause(KIT, C) \
341 unsigned KIT, *KIT##_PTR = BEGIN_KLAUSE (C), \
342 *KIT##_END = END_KLAUSE (C); \
343 KIT##_PTR != KIT##_END && ((KIT = *KIT##_PTR), true); \
344 ++KIT##_PTR
345
346#define all_antecedents(REF, C) \
347 unsigned REF, *REF##_PTR = antecedents_func (C), \
348 *REF##_END = REF##_PTR + (C)->aux; \
349 REF##_PTR != REF##_END && ((REF = *REF##_PTR), true); \
350 ++REF##_PTR
351
352#ifdef LOGGING
353
354#ifdef STAND_ALONE_KITTEN
355#define logging (kitten->logging)
356#else
357#define logging GET_OPTION (log)
358#endif
359
360static void log_basic (kitten *, const char *, ...)
361 __attribute__ ((format (printf, 2, 3)));
362
363static void log_basic (kitten *kitten, const char *fmt, ...) {
364 KISSAT_assert (logging);
365 printf ("c KITTEN %u ", kitten->level);
366 va_list ap;
367 va_start (ap, fmt);
368 vprintf (fmt, ap);
369 va_end (ap);
370 fputc ('\n', stdout);
371 fflush (stdout);
372}
373
374static void log_reference (kitten *, unsigned, const char *, ...)
375 __attribute__ ((format (printf, 3, 4)));
376
377static void log_reference (kitten *kitten, unsigned ref, const char *fmt,
378 ...) {
379 klause *c = dereference_klause (kitten, ref);
380 KISSAT_assert (logging);
381 printf ("c KITTEN %u ", kitten->level);
382 va_list ap;
383 va_start (ap, fmt);
384 vprintf (fmt, ap);
385 va_end (ap);
386 if (is_learned_klause (c)) {
387 fputs (" learned", stdout);
388 if (c->aux)
389 printf ("[%u]", c->aux);
390 } else {
391 fputs (" original", stdout);
392 if (c->aux != INVALID)
393 printf ("[%u]", c->aux);
394 }
395 printf (" size %u clause[%u]", c->size, ref);
396 value *values = kitten->values;
397 kar *vars = kitten->vars;
398 for (all_literals_in_klause (lit, c)) {
399 printf (" %u", lit);
400 const value value = values[lit];
401 if (value)
402 printf ("@%u=%d", vars[lit / 2].level, (int) value);
403 }
404 fputc ('\n', stdout);
405 fflush (stdout);
406}
407
408#define LOG(...) \
409 do { \
410 if (logging) \
411 log_basic (kitten, __VA_ARGS__); \
412 } while (0)
413
414#define ROG(...) \
415 do { \
416 if (logging) \
417 log_reference (kitten, __VA_ARGS__); \
418 } while (0)
419
420#else
421
422#define LOG(...) \
423 do { \
424 } while (0)
425#define ROG(...) \
426 do { \
427 } while (0)
428
429#endif
430
431static void check_queue (kitten *kitten) {
432#ifdef CHECK_KITTEN
433 const unsigned vars = kitten->lits / 2;
434 unsigned found = 0, prev = INVALID;
436 uint64_t stamp = 0;
437 for (unsigned idx = kitten->queue.first, next; idx != INVALID;
438 idx = next) {
439 kink *link = links + idx;
440 KISSAT_assert (link->prev == prev);
441 KISSAT_assert (!found || stamp < link->stamp);
443 stamp = link->stamp;
444 next = link->next;
445 prev = idx;
446 found++;
447 }
448 KISSAT_assert (found == vars);
449 unsigned next = INVALID;
450 found = 0;
451 for (unsigned idx = kitten->queue.last, prev; idx != INVALID;
452 idx = prev) {
453 kink *link = links + idx;
454 KISSAT_assert (link->next == next);
455 prev = link->prev;
456 next = idx;
457 found++;
458 }
459 KISSAT_assert (found == vars);
460 value *values = kitten->values;
461 bool first = true;
462 for (unsigned idx = kitten->queue.search, next; idx != INVALID;
463 idx = next) {
464 kink *link = links + idx;
465 next = link->next;
466 const unsigned lit = 2 * idx;
467 KISSAT_assert (first || values[lit]);
468 first = false;
469 }
470#else
471 (void) kitten;
472#endif
473}
474
475static void update_search (kitten *kitten, unsigned idx) {
476 if (kitten->queue.search == idx)
477 return;
478 kitten->queue.search = idx;
479 LOG ("search updated to %u stamped %" PRIu64, idx,
480 kitten->links[idx].stamp);
481}
482
483static void enqueue (kitten *kitten, unsigned idx) {
484 LOG ("enqueue %u", idx);
486 kink *l = links + idx;
487 const unsigned last = kitten->queue.last;
488 if (last == INVALID)
489 kitten->queue.first = idx;
490 else
491 links[last].next = idx;
492 l->prev = last;
493 l->next = INVALID;
494 kitten->queue.last = idx;
495 l->stamp = kitten->queue.stamp++;
496 LOG ("stamp %" PRIu64, l->stamp);
497}
498
499static void dequeue (kitten *kitten, unsigned idx) {
500 LOG ("dequeue %u", idx);
502 kink *l = links + idx;
503 const unsigned prev = l->prev;
504 const unsigned next = l->next;
505 if (prev == INVALID)
506 kitten->queue.first = next;
507 else
508 links[prev].next = next;
509 if (next == INVALID)
510 kitten->queue.last = prev;
511 else
512 links[next].prev = prev;
513}
514
515static void init_queue (kitten *kitten, size_t old_vars, size_t new_vars) {
516 for (size_t idx = old_vars; idx < new_vars; idx++) {
517 KISSAT_assert (!kitten->values[2 * idx]);
518 KISSAT_assert (kitten->unassigned < UINT_MAX);
520 enqueue (kitten, idx);
521 }
522 LOG ("initialized decision queue from %zu to %zu", old_vars, new_vars);
523 update_search (kitten, kitten->queue.last);
524 check_queue (kitten);
525}
526
527static void initialize_kitten (kitten *kitten) {
533 kitten->limits.ticks = UINT64_MAX;
535}
536
537static void clear_kitten (kitten *kitten) {
538 size_t bytes = (char *) &kitten->size - (char *) &kitten->status;
539 memset (&kitten->status, 0, bytes);
540#ifdef STAND_ALONE_KITTEN
541 memset (&kitten->statistics, 0, sizeof (statistics));
542#endif
543 initialize_kitten (kitten);
544}
545
546#define RESIZE1(T, P) \
547 do { \
548 void *OLD_PTR = (P); \
549 CALLOC (T, (P), new_size / 2); \
550 const size_t BYTES = old_vars * sizeof *(P); \
551 if (BYTES) \
552 memcpy ((P), OLD_PTR, BYTES); \
553 void *NEW_PTR = (P); \
554 (P) = (T*) OLD_PTR; \
555 DEALLOC ((P), old_size / 2); \
556 (P) = (T*) NEW_PTR; \
557 } while (0)
558
559#define RESIZE2(T, P) \
560 do { \
561 void *OLD_PTR = (P); \
562 CALLOC (T, (P), new_size); \
563 const size_t BYTES = old_lits * sizeof *(P); \
564 if (BYTES) \
565 memcpy ((P), OLD_PTR, BYTES); \
566 void *NEW_PTR = (P); \
567 (P) = (T*) OLD_PTR; \
568 DEALLOC ((P), old_size); \
569 (P) = (T*) NEW_PTR; \
570 } while (0)
571
572static void enlarge_internal (kitten *kitten, size_t new_lits) {
573 const size_t old_lits = kitten->lits;
574 KISSAT_assert (old_lits < new_lits);
575 const size_t old_size = kitten->size;
576 const unsigned new_vars = new_lits / 2;
577 const unsigned old_vars = old_lits / 2;
578 if (old_size < new_lits) {
579 size_t new_size = old_size ? 2 * old_size : 2;
580 while (new_size <= new_lits)
581 new_size *= 2;
582 LOG ("internal literals resized to %zu from %zu (requested %zu)",
583 new_size, old_size, new_lits);
584
586 RESIZE1 (unsigned char, kitten->phases);
588 RESIZE2 (bool, kitten->failed);
591 RESIZE2 (katches, kitten->watches);
592
593 kitten->size = new_size;
594 }
595 kitten->lits = new_lits;
596 init_queue (kitten, old_vars, new_vars);
597 LOG ("internal literals activated until %zu literals", new_lits);
598 return;
599}
600
601static const char *status_to_string (int status) {
602 switch (status) {
603 case 10:
604 return "formula satisfied";
605 case 20:
606 return "formula inconsistent";
607 case 21:
608 return "formula inconsistent and core computed";
609 default:
610 KISSAT_assert (!status);
611 return "formula unsolved";
612 }
613}
614
615static void invalid_api_usage (const char *fun, const char *fmt, ...) {
616 fprintf (stderr, "kitten: fatal error: invalid API usage in '%s': ", fun);
617 va_list ap;
618 va_start (ap, fmt);
619 vfprintf (stderr, fmt, ap);
620 va_end (ap);
621 fputc ('\n', stderr);
622 fflush (stderr);
623 abort ();
624}
625
626#define INVALID_API_USAGE(...) invalid_api_usage (__func__, __VA_ARGS__)
627
628#define REQUIRE_INITIALIZED() \
629 do { \
630 if (!kitten) \
631 INVALID_API_USAGE ("solver argument zero"); \
632 } while (0)
633
634#define REQUIRE_STATUS(EXPECTED) \
635 do { \
636 REQUIRE_INITIALIZED (); \
637 if (kitten->status != (EXPECTED)) \
638 INVALID_API_USAGE ("invalid status '%s' (expected '%s')", \
639 status_to_string (kitten->status), \
640 status_to_string (EXPECTED)); \
641 } while (0)
642
643#define UPDATE_STATUS(STATUS) \
644 do { \
645 if (kitten->status != (STATUS)) \
646 LOG ("updating status from '%s' to '%s'", \
647 status_to_string (kitten->status), status_to_string (STATUS)); \
648 else \
649 LOG ("keeping status at '%s'", status_to_string (STATUS)); \
650 kitten->status = (STATUS); \
651 } while (0)
652
653#ifdef STAND_ALONE_KITTEN
654
655kitten *kitten_init (void) {
656 kitten *kitten;
657 CALLOC (struct kitten, kitten, 1);
658 initialize_kitten (kitten);
659 return kitten;
660}
661
662#else
663
665 if (!kissat)
666 INVALID_API_USAGE ("'kissat' argument zero");
667
668 kitten *kitten;
669 struct kitten dummy;
670 dummy.kissat = kissat;
671 kitten = &dummy;
672 CALLOC (struct kitten, kitten, 1);
674 initialize_kitten (kitten);
675 return kitten;
676}
677
678#endif
679
681 REQUIRE_STATUS (0);
682
683 if (kitten->learned)
684 INVALID_API_USAGE ("can not start tracking antecedents after learning");
685
686 LOG ("enabling antecedents tracking");
687 kitten->antecedents = true;
688}
689
692
693 LOG ("randomizing phases");
694
695 unsigned char *phases = kitten->phases;
696 const unsigned vars = kitten->size / 2;
697
698 uint64_t random = kissat_next_random64 (&kitten->generator);
699
700 unsigned i = 0;
701 const unsigned rest = vars & ~63u;
702
703 while (i != rest) {
704 uint64_t *p = (uint64_t *) (phases + i);
705 p[0] = (random >> 0) & 0x0101010101010101;
706 p[1] = (random >> 1) & 0x0101010101010101;
707 p[2] = (random >> 2) & 0x0101010101010101;
708 p[3] = (random >> 3) & 0x0101010101010101;
709 p[4] = (random >> 4) & 0x0101010101010101;
710 p[5] = (random >> 5) & 0x0101010101010101;
711 p[6] = (random >> 6) & 0x0101010101010101;
712 p[7] = (random >> 7) & 0x0101010101010101;
713 random = kissat_next_random64 (&kitten->generator);
714 i += 64;
715 }
716
717 unsigned shift = 0;
718 while (i != vars)
719 phases[i++] = (random >> shift++) & 1;
720}
721
724
725 LOG ("flipping phases");
726
727 unsigned char *phases = kitten->phases;
728 const unsigned vars = kitten->size / 2;
729
730 unsigned i = 0;
731 const unsigned rest = vars & ~7u;
732
733 while (i != rest) {
734 uint64_t *p = (uint64_t *) (phases + i);
735 *p ^= 0x0101010101010101;
736 i += 8;
737 }
738
739 while (i != vars)
740 phases[i++] ^= 1;
741}
742
745 LOG ("forcing no ticks limit");
746 kitten->limits.ticks = UINT64_MAX;
747}
748
749void kitten_set_ticks_limit (kitten *kitten, uint64_t delta) {
751 const uint64_t current = KITTEN_TICKS;
752 uint64_t limit;
753 if (UINT64_MAX - delta <= current) {
754 LOG ("forcing unlimited ticks limit");
755 limit = UINT64_MAX;
756 } else {
757 limit = current + delta;
758 LOG ("new limit of %" PRIu64 " ticks after %" PRIu64, limit, delta);
759 }
760
761 kitten->limits.ticks = limit;
762}
763
764static void shuffle_unsigned_array (kitten *kitten, size_t size,
765 unsigned *a) {
766 for (size_t i = 0; i != size; i++) {
767 const size_t j = kissat_pick_random (&kitten->generator, 0, i);
768 if (j == i)
769 continue;
770 const unsigned first = a[i];
771 const unsigned second = a[j];
772 a[i] = second;
773 a[j] = first;
774 }
775}
776
777static void shuffle_unsigned_stack (kitten *kitten, unsigneds *stack) {
778 const size_t size = SIZE_STACK (*stack);
779 unsigned *a = BEGIN_STACK (*stack);
780 shuffle_unsigned_array (kitten, size, a);
781}
782
783static void shuffle_katches_array (kitten *kitten, size_t size, katch *a) {
784 for (size_t i = 0; i != size; i++) {
785 const size_t j = kissat_pick_random (&kitten->generator, 0, i);
786 if (j == i)
787 continue;
788 const katch first = a[i];
789 const katch second = a[j];
790 a[i] = second;
791 a[j] = first;
792 }
793}
794
795static void shuffle_katches_stack (kitten *kitten, katches *stack) {
796 const size_t size = SIZE_STACK (*stack);
797 katch *a = BEGIN_STACK (*stack);
798 shuffle_katches_array (kitten, size, a);
799}
800
801static void shuffle_katches (kitten *kitten) {
802 LOG ("shuffling watch lists");
803 const size_t lits = kitten->lits;
804 for (size_t lit = 0; lit != lits; lit++)
805 shuffle_katches_stack (kitten, &KATCHES (lit));
806}
807
808static void shuffle_queue (kitten *kitten) {
809 LOG ("shuffling variable decision order");
810
811 const unsigned vars = kitten->lits / 2;
812 for (unsigned i = 0; i != vars; i++) {
813 const unsigned idx = kissat_pick_random (&kitten->generator, 0, vars);
814 dequeue (kitten, idx);
815 enqueue (kitten, idx);
816 }
817 update_search (kitten, kitten->queue.last);
818}
819
820static void shuffle_units (kitten *kitten) {
821 LOG ("shuffling units");
822 shuffle_unsigned_stack (kitten, &kitten->units);
823}
824
826 REQUIRE_STATUS (0);
827 shuffle_queue (kitten);
828 shuffle_katches (kitten);
829 shuffle_units (kitten);
830}
831
832static inline unsigned *antecedents_func (klause *c) {
833 KISSAT_assert (is_learned_klause (c));
834 return c->lits + c->size;
835}
836
837static inline void watch_klause (kitten *kitten, unsigned lit, klause *c,
838 unsigned ref) {
839 ROG (ref, "watching %u in", lit);
840 katches *watches = &KATCHES (lit);
841 katch katch;
842 katch.ref = ref;
843#ifdef KITTEN_BLIT
844 const unsigned size = c->size;
845 KISSAT_assert (lit == c->lits[0] || lit == c->lits[1]);
846 const unsigned blit = c->lits[0] ^ c->lits[1] ^ lit;
847 const bool binary = size == 2;
848 KISSAT_assert (size > 1);
849 KISSAT_assert (ref < (1u << 31));
850 katch.blit = blit;
851 katch.binary = binary;
852#else
853 (void) c;
854#endif
856}
857
858static inline void connect_new_klause (kitten *kitten, unsigned ref) {
859 ROG (ref, "new");
860
861 klause *c = dereference_klause (kitten, ref);
862
863 if (!c->size) {
864 if (kitten->inconsistent == INVALID) {
865 ROG (ref, "registering inconsistent empty");
867 } else
868 ROG (ref, "ignoring inconsistent empty");
869 } else if (c->size == 1) {
870 ROG (ref, "watching unit");
871 PUSH_STACK (kitten->units, ref);
872 } else {
873 watch_klause (kitten, c->lits[0], c, ref);
874 watch_klause (kitten, c->lits[1], c, ref);
875 }
876}
877
878static unsigned new_reference (kitten *kitten) {
879 size_t ref = SIZE_STACK (kitten->klauses);
880 if (ref >= INVALID) {
881#ifdef STAND_ALONE_KITTEN
882 die ("maximum number of literals exhausted");
883#else
884 kissat_fatal ("kitten: maximum number of literals exhausted");
885#endif
886 }
887 const unsigned res = (unsigned) ref;
888 KISSAT_assert (res != INVALID);
889 INC (kitten_ticks);
890 return res;
891}
892
893static void new_original_klause (kitten *kitten, unsigned id) {
894 unsigned res = new_reference (kitten);
895 unsigned size = SIZE_STACK (kitten->klause);
896 unsigneds *klauses = &kitten->klauses;
897 PUSH_STACK (*klauses, id);
899 PUSH_STACK (*klauses, 0);
900 for (all_stack (unsigned, lit, kitten->klause))
902 connect_new_klause (kitten, res);
904#ifdef STAND_ALONE_KITTEN
905 kitten->statistics.original++;
906#endif
907}
908
909static void enlarge_external (kitten *kitten, size_t eidx) {
910 const size_t old_size = kitten->esize;
911 const unsigned old_evars = kitten->evars;
912 KISSAT_assert (old_evars <= eidx);
913 const unsigned new_evars = eidx + 1;
914 if (old_size <= eidx) {
915 size_t new_size = old_size ? 2 * old_size : 1;
916 while (new_size <= eidx)
917 new_size *= 2;
918 LOG ("external resizing to %zu variables from %zu (requested %u)",
919 new_size, old_size, new_evars);
920 unsigned *old_import = kitten->import;
921 CALLOC (unsigned, kitten->import, new_size);
922 const size_t bytes = old_evars * sizeof *kitten->import;
923 if (bytes)
924 memcpy (kitten->import, old_import, bytes);
925 DEALLOC (old_import, old_size);
926 kitten->esize = new_size;
927 }
928 kitten->evars = new_evars;
929 LOG ("external variables enlarged to %u", new_evars);
930}
931
932static unsigned import_literal (kitten *kitten, unsigned elit) {
933 const unsigned eidx = elit / 2;
934 if (eidx >= kitten->evars)
935 enlarge_external (kitten, eidx);
936
937 unsigned iidx = kitten->import[eidx];
938 if (!iidx) {
939 iidx = SIZE_STACK (kitten->export_);
940 PUSH_STACK (kitten->export_, eidx);
941 kitten->import[eidx] = iidx + 1;
942 } else
943 iidx--;
944 unsigned ilit = 2 * iidx + (elit & 1);
945 LOG ("imported external literal %u as internal literal %u", elit, ilit);
946 const size_t new_lits = (ilit | 1) + (size_t) 1;
947 KISSAT_assert (ilit < new_lits);
948 KISSAT_assert (ilit / 2 < new_lits / 2);
949 if (new_lits > kitten->lits)
950 enlarge_internal (kitten, new_lits);
951 return ilit;
952}
953
954static unsigned export_literal (kitten *kitten, unsigned ilit) {
955 const unsigned iidx = ilit / 2;
957 const unsigned eidx = PEEK_STACK (kitten->export_, iidx);
958 const unsigned elit = 2 * eidx + (ilit & 1);
959 return elit;
960}
961
963 unsigned res = new_reference (kitten);
964 unsigneds *klauses = &kitten->klauses;
965 const size_t size = SIZE_STACK (kitten->klause);
966 KISSAT_assert (size <= UINT_MAX);
967 const size_t aux =
969 KISSAT_assert (aux <= UINT_MAX);
970 PUSH_STACK (*klauses, (unsigned) aux);
971 PUSH_STACK (*klauses, (unsigned) size);
973 for (all_stack (unsigned, lit, kitten->klause))
975 if (aux)
976 for (all_stack (unsigned, ref, kitten->resolved))
977 PUSH_STACK (*klauses, ref);
978 connect_new_klause (kitten, res);
979 kitten->learned = true;
980#ifdef STAND_ALONE_KITTEN
981 kitten->statistics.learned++;
982#endif
983 return res;
984}
985
987 LOG ("clear kitten of size %zu", kitten->size);
988
993
1000
1001 for (all_kits (kit))
1002 CLEAR_STACK (KATCHES (kit));
1003
1004 while (!EMPTY_STACK (kitten->export_))
1006
1007 const size_t lits = kitten->size;
1008 const unsigned vars = lits / 2;
1009
1010#ifndef KISSAT_NDEBUG
1011 for (unsigned i = 0; i < vars; i++)
1012 KISSAT_assert (!kitten->marks[i]);
1013#endif
1014
1015 if (vars) {
1016 memset (kitten->phases, 0, vars);
1017 memset (kitten->vars, 0, vars);
1018 }
1019
1020 if (lits) {
1021 memset (kitten->values, 0, lits);
1022 memset (kitten->failed, 0, lits);
1023 }
1024
1025 clear_kitten (kitten);
1026}
1027
1039
1040 for (size_t lit = 0; lit < kitten->size; lit++)
1042
1043#ifndef STAND_ALONE_KITTEN
1044 const size_t lits = kitten->size;
1045 const unsigned vars = lits / 2;
1046#endif
1051 DEALLOC (kitten->vars, vars);
1055#ifdef STAND_ALONE_KITTEN
1056 free (kitten);
1057#else
1058 kissat_free (kitten->kissat, kitten, sizeof *kitten);
1059#endif
1060}
1061
1062static inline void move_to_front (kitten *kitten, unsigned idx) {
1063 if (idx == kitten->queue.last)
1064 return;
1065 LOG ("move to front variable %u", idx);
1066 dequeue (kitten, idx);
1067 enqueue (kitten, idx);
1068 KISSAT_assert (kitten->values[2 * idx]);
1069}
1070
1071static inline void assign (kitten *kitten, unsigned lit, unsigned reason) {
1072#ifdef LOGGING
1073 if (reason == INVALID)
1074 LOG ("assign %u as decision", lit);
1075 else
1076 ROG (reason, "assign %u reason", lit);
1077#endif
1079 const unsigned not_lit = lit ^ 1;
1081 KISSAT_assert (!values[not_lit]);
1082 values[lit] = 1;
1083 values[not_lit] = -1;
1084 const unsigned idx = lit / 2;
1085 const unsigned sign = lit & 1;
1086 kitten->phases[idx] = sign;
1088 kar *v = kitten->vars + idx;
1089 v->level = kitten->level;
1090 if (!v->level) {
1091 KISSAT_assert (reason != INVALID);
1092 klause *c = dereference_klause (kitten, reason);
1093 if (c->size > 1) {
1094 if (kitten->antecedents) {
1095 PUSH_STACK (kitten->resolved, reason);
1096 for (all_literals_in_klause (other, c))
1097 if (other != lit) {
1098 const unsigned other_idx = other / 2;
1099 const unsigned other_ref = kitten->vars[other_idx].reason;
1100 KISSAT_assert (other_ref != INVALID);
1101 PUSH_STACK (kitten->resolved, other_ref);
1102 }
1103 }
1105 reason = new_learned_klause (kitten);
1108 }
1109 }
1110 v->reason = reason;
1112 kitten->unassigned--;
1113}
1114
1115static inline unsigned propagate_literal (kitten *kitten, unsigned lit) {
1116 LOG ("propagating %u", lit);
1118 KISSAT_assert (values[lit] > 0);
1119 const unsigned not_lit = lit ^ 1;
1120 katches *watches = kitten->watches + not_lit;
1121 unsigned conflict = INVALID;
1122 katch *q = BEGIN_STACK (*watches);
1123 const katch *const end_watches = END_STACK (*watches);
1124 katch const *p = q;
1125 uint64_t ticks = (((char *) end_watches - (char *) q) >> 7) + 1;
1126 while (p != end_watches) {
1127 katch katch = *q++ = *p++;
1128 const unsigned ref = katch.ref;
1129#ifdef KITTEN_BLIT
1130 const unsigned blit = katch.blit;
1131 KISSAT_assert (blit != not_lit);
1132 const value blit_value = values[blit];
1133 if (blit_value > 0)
1134 continue;
1135 if (katch.binary) {
1136 if (blit_value < 0) {
1137 ROG (ref, "conflict");
1138 INC (kitten_conflicts);
1139 conflict = ref;
1140 break;
1141 } else {
1142 KISSAT_assert (!blit_value);
1143 assign (kitten, blit, ref);
1144 continue;
1145 }
1146 }
1147#endif
1148 klause *c = dereference_klause (kitten, ref);
1149 KISSAT_assert (c->size > 1);
1150 unsigned *lits = c->lits;
1151 const unsigned other = lits[0] ^ lits[1] ^ not_lit;
1152 const value other_value = values[other];
1153 ticks++;
1154 if (other_value > 0) {
1155#ifdef KITTEN_BLIT
1156 q[-1].blit = other;
1157#endif
1158 continue;
1159 }
1160 value replacement_value = -1;
1161 unsigned replacement = INVALID;
1162 const unsigned *const end_lits = lits + c->size;
1163 unsigned *r;
1164 for (r = lits + 2; r != end_lits; r++) {
1165 replacement = *r;
1166 replacement_value = values[replacement];
1167 if (replacement_value >= 0)
1168 break;
1169 }
1170 if (replacement_value >= 0) {
1171 KISSAT_assert (replacement != INVALID);
1172 ROG (ref, "unwatching %u in", not_lit);
1173 lits[0] = other;
1174 lits[1] = replacement;
1175 *r = not_lit;
1176 watch_klause (kitten, replacement, c, ref);
1177 q--;
1178 } else if (other_value < 0) {
1179 ROG (ref, "conflict");
1180 INC (kitten_conflicts);
1181 conflict = ref;
1182 break;
1183 } else {
1184 KISSAT_assert (!other_value);
1185 assign (kitten, other, ref);
1186 }
1187 }
1188 while (p != end_watches)
1189 *q++ = *p++;
1191 ADD (kitten_ticks, ticks);
1192 return conflict;
1193}
1194
1195static inline unsigned propagate (kitten *kitten) {
1197 unsigned propagated = 0;
1198 unsigned conflict = INVALID;
1199 while (conflict == INVALID &&
1201 const unsigned lit = PEEK_STACK (kitten->trail, kitten->propagated);
1202 conflict = propagate_literal (kitten, lit);
1203 kitten->propagated++;
1204 propagated++;
1205 }
1206 ADD (kitten_propagations, propagated);
1207 return conflict;
1208}
1209
1210static void bump (kitten *kitten) {
1211 value *marks = kitten->marks;
1212 for (all_stack (unsigned, idx, kitten->analyzed)) {
1213 marks[idx] = 0;
1214 move_to_front (kitten, idx);
1215 }
1216 check_queue (kitten);
1217}
1218
1219static inline void unassign (kitten *kitten, value *values, unsigned lit) {
1220 const unsigned not_lit = lit ^ 1;
1222 KISSAT_assert (values[not_lit]);
1223 const unsigned idx = lit / 2;
1224#ifdef LOGGING
1225 kar *var = kitten->vars + idx;
1226 kitten->level = var->level;
1227 LOG ("unassign %u", lit);
1228#endif
1229 values[lit] = values[not_lit] = 0;
1231 kitten->unassigned++;
1232 kink *links = kitten->links;
1233 kink *link = links + idx;
1234 if (link->stamp > links[kitten->queue.search].stamp)
1235 update_search (kitten, idx);
1236}
1237
1238static void backtrack (kitten *kitten, unsigned jump) {
1239 check_queue (kitten);
1240 KISSAT_assert (jump < kitten->level);
1241 LOG ("back%s to level %u",
1242 (kitten->level == jump + 1 ? "tracking" : "jumping"), jump);
1243 kar *vars = kitten->vars;
1245 unsigneds *trail = &kitten->trail;
1246 while (!EMPTY_STACK (*trail)) {
1247 const unsigned lit = TOP_STACK (*trail);
1248 const unsigned idx = lit / 2;
1249 const unsigned level = vars[idx].level;
1250 if (level == jump)
1251 break;
1252 (void) POP_STACK (*trail);
1253 unassign (kitten, values, lit);
1254 }
1256 kitten->level = jump;
1257 check_queue (kitten);
1258}
1259
1261 check_queue (kitten);
1262 LOG ("completely backtracking to level 0");
1264 unsigneds *trail = &kitten->trail;
1265#ifndef KISSAT_NDEBUG
1266 kar *vars = kitten->vars;
1267#endif
1268 for (all_stack (unsigned, lit, *trail)) {
1269 KISSAT_assert (vars[lit / 2].level);
1270 unassign (kitten, values, lit);
1271 }
1272 CLEAR_STACK (*trail);
1273 kitten->propagated = 0;
1274 kitten->level = 0;
1275 check_queue (kitten);
1276}
1277
1278static void analyze (kitten *kitten, unsigned conflict) {
1285 unsigned reason = conflict;
1286 value *marks = kitten->marks;
1287 const kar *const vars = kitten->vars;
1288 const unsigned level = kitten->level;
1289 unsigned const *p = END_STACK (kitten->trail);
1290 unsigned open = 0, jump = 0, size = 1, uip;
1291 for (;;) {
1292 KISSAT_assert (reason != INVALID);
1293 klause *c = dereference_klause (kitten, reason);
1294 KISSAT_assert (c);
1295 ROG (reason, "analyzing");
1296 PUSH_STACK (kitten->resolved, reason);
1297 for (all_literals_in_klause (lit, c)) {
1298 const unsigned idx = lit / 2;
1299 if (marks[idx])
1300 continue;
1302 LOG ("analyzed %u", lit);
1303 marks[idx] = true;
1304 PUSH_STACK (kitten->analyzed, idx);
1305 const kar *const v = vars + idx;
1306 const unsigned tmp = v->level;
1307 if (tmp < level) {
1308 if (tmp > jump) {
1309 jump = tmp;
1310 if (size > 1) {
1311 const unsigned other = PEEK_STACK (kitten->klause, 1);
1312 POKE_STACK (kitten->klause, 1, lit);
1313 lit = other;
1314 }
1315 }
1317 size++;
1318 } else
1319 open++;
1320 }
1321 unsigned idx;
1322 do {
1324 uip = *--p;
1325 } while (!marks[idx = uip / 2]);
1326 KISSAT_assert (open);
1327 if (!--open)
1328 break;
1329 reason = vars[idx].reason;
1330 }
1331 const unsigned not_uip = uip ^ 1;
1332 LOG ("first UIP %u jump level %u size %u", not_uip, jump, size);
1333 POKE_STACK (kitten->klause, 0, not_uip);
1334 bump (kitten);
1336 const unsigned learned_ref = new_learned_klause (kitten);
1339 backtrack (kitten, jump);
1340 assign (kitten, not_uip, learned_ref);
1341}
1342
1343static void failing (kitten *kitten) {
1349 LOG ("analyzing failing assumptions");
1350 const value *const values = kitten->values;
1351 const kar *const vars = kitten->vars;
1352 unsigned failed_clashing = INVALID;
1353 unsigned first_failed = INVALID;
1354 unsigned failed_unit = INVALID;
1355 for (all_stack (unsigned, lit, kitten->assumptions)) {
1356 if (values[lit] >= 0)
1357 continue;
1358 if (first_failed == INVALID)
1359 first_failed = lit;
1360 const unsigned failed_idx = lit / 2;
1361 const kar *const failed_var = vars + failed_idx;
1362 if (!failed_var->level) {
1363 failed_unit = lit;
1364 break;
1365 }
1366 if (failed_clashing == INVALID && failed_var->reason == INVALID)
1367 failed_clashing = lit;
1368 }
1369 unsigned failed;
1370 if (failed_unit != INVALID)
1371 failed = failed_unit;
1372 else if (failed_clashing != INVALID)
1373 failed = failed_clashing;
1374 else
1375 failed = first_failed;
1377 const unsigned failed_idx = failed / 2;
1378 const kar *const failed_var = vars + failed_idx;
1379 const unsigned failed_reason = failed_var->reason;
1380 LOG ("first failed assumption %u", failed);
1381 kitten->failed[failed] = true;
1382
1383 if (failed_unit != INVALID) {
1384 KISSAT_assert (dereference_klause (kitten, failed_reason)->size == 1);
1385 LOG ("root-level falsified assumption %u", failed);
1386 kitten->failing = failed_reason;
1387 ROG (kitten->failing, "failing reason");
1388 return;
1389 }
1390
1391 const unsigned not_failed = failed ^ 1;
1392 if (failed_clashing != INVALID) {
1393 LOG ("clashing with negated assumption %u", not_failed);
1394 kitten->failed[not_failed] = true;
1396 return;
1397 }
1398
1399 value *marks = kitten->marks;
1400 KISSAT_assert (!marks[failed_idx]);
1401 marks[failed_idx] = true;
1402 PUSH_STACK (kitten->analyzed, failed_idx);
1403 PUSH_STACK (kitten->klause, not_failed);
1404
1405 for (size_t next = 0; next < SIZE_STACK (kitten->analyzed); next++) {
1406 const unsigned idx = PEEK_STACK (kitten->analyzed, next);
1407 KISSAT_assert (marks[idx]);
1408 const kar *var = vars + idx;
1409 const unsigned reason = var->reason;
1410 if (reason == INVALID) {
1411 unsigned lit = 2 * idx;
1412 if (values[lit] < 0)
1413 lit ^= 1;
1414 LOG ("failed assumption %u", lit);
1416 kitten->failed[lit] = true;
1417 const unsigned not_lit = lit ^ 1;
1418 PUSH_STACK (kitten->klause, not_lit);
1419 } else {
1420 ROG (reason, "analyzing");
1421 PUSH_STACK (kitten->resolved, reason);
1422 klause *c = dereference_klause (kitten, reason);
1423 for (all_literals_in_klause (other, c)) {
1424 const unsigned other_idx = other / 2;
1425 if (other_idx == idx)
1426 continue;
1427 if (marks[other_idx])
1428 continue;
1429 marks[other_idx] = true;
1430 PUSH_STACK (kitten->analyzed, other_idx);
1431 LOG ("analyzing final literal %u", other ^ 1);
1432 }
1433 }
1434 }
1435
1436 for (all_stack (unsigned, idx, kitten->analyzed))
1437 KISSAT_assert (marks[idx]), marks[idx] = 0;
1439
1440 const size_t resolved = SIZE_STACK (kitten->resolved);
1442
1443 if (resolved == 1) {
1445 ROG (kitten->failing, "reusing as core");
1446 } else {
1448 ROG (kitten->failing, "new core");
1449 }
1450
1453}
1454
1455static void flush_trail (kitten *kitten) {
1456 unsigneds *trail = &kitten->trail;
1457 LOG ("flushing %zu root-level literals from trail", SIZE_STACK (*trail));
1459 kitten->propagated = 0;
1460 CLEAR_STACK (*trail);
1461}
1462
1463static int decide (kitten *kitten) {
1464 if (!kitten->level && !EMPTY_STACK (kitten->trail))
1465 flush_trail (kitten);
1466
1467 const value *const values = kitten->values;
1468 unsigned decision = INVALID;
1469 const size_t assumptions = SIZE_STACK (kitten->assumptions);
1470 while (kitten->level < assumptions) {
1471 unsigned assumption = PEEK_STACK (kitten->assumptions, kitten->level);
1472 value value = values[assumption];
1473 if (value < 0) {
1474 LOG ("found failing assumption %u", assumption);
1475 failing (kitten);
1476 return 20;
1477 } else if (value > 0) {
1478
1479 kitten->level++;
1480 LOG ("pseudo decision level %u for already satisfied assumption %u",
1481 kitten->level, assumption);
1482 } else {
1483 decision = assumption;
1484 LOG ("using assumption %u as decision", decision);
1485 break;
1486 }
1487 }
1488
1489 if (!kitten->unassigned)
1490 return 10;
1491
1492 if (KITTEN_TICKS >= kitten->limits.ticks) {
1493 LOG ("ticks limit %" PRIu64 " hit after %" PRIu64 " ticks",
1495 return -1;
1496 }
1497
1498#ifndef STAND_ALONE_KITTEN
1500 return -1;
1501#endif
1502
1503 if (decision == INVALID) {
1504 unsigned idx = kitten->queue.search;
1505 const kink *const links = kitten->links;
1506 for (;;) {
1507 KISSAT_assert (idx != INVALID);
1508 if (!values[2 * idx])
1509 break;
1510 idx = links[idx].prev;
1511 }
1512 update_search (kitten, idx);
1513 const unsigned phase = kitten->phases[idx];
1514 decision = 2 * idx + phase;
1515 LOG ("decision %u variable %u phase %u", decision, idx, phase);
1516 }
1517 INC (kitten_decisions);
1518 kitten->level++;
1519 assign (kitten, decision, INVALID);
1520 return 0;
1521}
1522
1523static void inconsistent (kitten *kitten, unsigned ref) {
1524 KISSAT_assert (ref != INVALID);
1526
1527 if (!kitten->antecedents) {
1529 ROG (ref, "registering inconsistent virtually empty");
1530 return;
1531 }
1532
1533 unsigneds *analyzed = &kitten->analyzed;
1534 unsigneds *resolved = &kitten->resolved;
1535
1538
1539 value *marks = kitten->marks;
1540 const kar *const vars = kitten->vars;
1541 unsigned next = 0;
1542
1543 for (;;) {
1544 KISSAT_assert (ref != INVALID);
1545 klause *c = dereference_klause (kitten, ref);
1546 KISSAT_assert (c);
1547 ROG (ref, "analyzing inconsistent");
1548 PUSH_STACK (*resolved, ref);
1549 for (all_literals_in_klause (lit, c)) {
1550 const unsigned idx = lit / 2;
1551 KISSAT_assert (!vars[idx].level);
1552 if (marks[idx])
1553 continue;
1555 LOG ("analyzed %u", lit);
1556 marks[idx] = true;
1557 PUSH_STACK (kitten->analyzed, idx);
1558 }
1559 if (next == SIZE_STACK (kitten->analyzed))
1560 break;
1561 const unsigned idx = PEEK_STACK (kitten->analyzed, next);
1562 next++;
1563 const kar *const v = vars + idx;
1564 KISSAT_assert (!v->level);
1565 ref = v->reason;
1566 }
1569 ROG (ref, "registering final inconsistent empty");
1571
1572 for (all_stack (unsigned, idx, *analyzed))
1573 marks[idx] = 0;
1574
1577}
1578
1579static int propagate_units (kitten *kitten) {
1580 if (kitten->inconsistent != INVALID)
1581 return 20;
1582
1583 if (EMPTY_STACK (kitten->units)) {
1584 LOG ("no root level unit clauses");
1585 return 0;
1586 }
1587
1588 LOG ("propagating %zu root level unit clauses",
1590
1591 const value *const values = kitten->values;
1592
1593 for (size_t next = 0; next < SIZE_STACK (kitten->units); next++) {
1594 const unsigned ref = PEEK_STACK (kitten->units, next);
1595 KISSAT_assert (ref != INVALID);
1596 klause *c = dereference_klause (kitten, ref);
1597 KISSAT_assert (c->size == 1);
1598 ROG (ref, "propagating unit");
1599 const unsigned unit = c->lits[0];
1600 const value value = values[unit];
1601 if (value > 0)
1602 continue;
1603 if (value < 0) {
1604 inconsistent (kitten, ref);
1605 return 20;
1606 }
1607 assign (kitten, unit, ref);
1608 const unsigned conflict = propagate (kitten);
1609 if (conflict == INVALID)
1610 continue;
1611 inconsistent (kitten, conflict);
1612 return 20;
1613 }
1614 return 0;
1615}
1616
1617/*------------------------------------------------------------------------*/
1618
1619static klause *begin_klauses (kitten *kitten) {
1620 return (klause *) BEGIN_STACK (kitten->klauses);
1621}
1622
1623static klause *end_original_klauses (kitten *kitten) {
1624 return (klause *) (BEGIN_STACK (kitten->klauses) +
1626}
1627
1628static klause *end_klauses (kitten *kitten) {
1629 return (klause *) END_STACK (kitten->klauses);
1630}
1631
1632static klause *next_klause (kitten *kitten, klause *c) {
1633 KISSAT_assert (begin_klauses (kitten) <= c);
1634 KISSAT_assert (c < end_klauses (kitten));
1635 unsigned *res = c->lits + c->size;
1636 if (kitten->antecedents && is_learned_klause (c))
1637 res += c->aux;
1638 return (klause *) res;
1639}
1640
1641/*------------------------------------------------------------------------*/
1642
1643static void reset_core (kitten *kitten) {
1644 LOG ("resetting core clauses");
1645 size_t reset = 0;
1646 for (all_klauses (c))
1647 if (is_core_klause (c))
1648 unset_core_klause (c), reset++;
1649 LOG ("reset %zu core clauses", reset);
1651}
1652
1653static void reset_assumptions (kitten *kitten) {
1654 LOG ("reset %zu assumptions", SIZE_STACK (kitten->assumptions));
1655 while (!EMPTY_STACK (kitten->assumptions)) {
1656 const unsigned assumption = POP_STACK (kitten->assumptions);
1657 kitten->failed[assumption] = false;
1658 }
1659#ifndef KISSAT_NDEBUG
1660 for (size_t i = 0; i < kitten->size; i++)
1662#endif
1664 if (kitten->failing != INVALID) {
1665 ROG (kitten->failing, "reset failed assumption reason");
1667 }
1668}
1669
1670static void reset_incremental (kitten *kitten) {
1671 if (kitten->level)
1674 reset_assumptions (kitten);
1675 else
1677 if (kitten->status == 21)
1678 reset_core (kitten);
1679 UPDATE_STATUS (0);
1680}
1681
1682/*------------------------------------------------------------------------*/
1683
1684static bool flip_literal (kitten *kitten, unsigned lit) {
1685 INC (kitten_flip);
1686 signed char *values = kitten->values;
1688 if (!kitten->vars[lit / 2].level) {
1689 LOG ("can not flip root-level assigned literal %u", lit);
1690 return false;
1691 }
1692 if (values[lit] < 0)
1693 lit ^= 1;
1694 LOG ("trying to flip value of satisfied literal %u", lit);
1695 KISSAT_assert (values[lit] > 0);
1696 katches *watches = kitten->watches + lit;
1697 katch *q = BEGIN_STACK (*watches);
1698 const katch *const end_watches = END_STACK (*watches);
1699 katch const *p = q;
1700 uint64_t ticks = (((char *) end_watches - (char *) q) >> 7) + 1;
1701 bool res = true;
1702 while (p != end_watches) {
1703 const katch katch = *q++ = *p++;
1704#ifdef KITTEN_BLIT
1705 const unsigned blit = katch.blit;
1706 KISSAT_assert (blit != lit);
1707 const value blit_value = values[blit];
1708 if (blit_value > 0)
1709 continue;
1710#endif
1711 const unsigned ref = katch.ref;
1712 klause *c = dereference_klause (kitten, ref);
1713 unsigned *lits = c->lits;
1714 const unsigned other = lits[0] ^ lits[1] ^ lit;
1715 const value other_value = values[other];
1716 ticks++;
1717 if (other_value > 0)
1718 continue;
1719 value replacement_value = -1;
1720 unsigned replacement = INVALID;
1721 const unsigned *const end_lits = lits + c->size;
1722 unsigned *r;
1723 for (r = lits + 2; r != end_lits; r++) {
1724 replacement = *r;
1725 KISSAT_assert (replacement != lit);
1726 replacement_value = values[replacement];
1727 KISSAT_assert (replacement_value);
1728 if (replacement_value > 0)
1729 break;
1730 }
1731 if (replacement_value > 0) {
1732 KISSAT_assert (replacement != INVALID);
1733 ROG (ref, "unwatching %u in", lit);
1734 lits[0] = other;
1735 lits[1] = replacement;
1736 *r = lit;
1737 watch_klause (kitten, replacement, c, ref);
1738 q--;
1739 } else {
1740 KISSAT_assert (replacement_value < 0);
1741 ROG (ref, "single satisfied");
1742 res = false;
1743 break;
1744 }
1745 }
1746 while (p != end_watches)
1747 *q++ = *p++;
1749 ADD (kitten_ticks, ticks);
1750 if (res) {
1751 LOG ("flipping value of %u", lit);
1752 values[lit] = -1;
1753 const unsigned not_lit = lit ^ 1;
1754 values[not_lit] = 1;
1755 INC (kitten_flipped);
1756 } else
1757 LOG ("failed to flip value of %u", lit);
1758 return res;
1759}
1760
1761/*------------------------------------------------------------------------*/
1762
1763void kitten_assume (kitten *kitten, unsigned elit) {
1765 if (kitten->status)
1766 reset_incremental (kitten);
1767 const unsigned ilit = import_literal (kitten, elit);
1768 LOG ("registering assumption %u", ilit);
1769 PUSH_STACK (kitten->assumptions, ilit);
1770}
1771
1773 size_t size,
1774 const unsigned *elits,
1775 unsigned except) {
1777 if (kitten->status)
1778 reset_incremental (kitten);
1780 const unsigned *const end = elits + size;
1781 for (const unsigned *p = elits; p != end; p++) {
1782 const unsigned elit = *p;
1783 if (elit == except)
1784 continue;
1785 const unsigned ilit = import_literal (kitten, elit);
1786 KISSAT_assert (ilit < kitten->lits);
1787 const unsigned iidx = ilit / 2;
1788 if (kitten->marks[iidx])
1789 INVALID_API_USAGE ("variable '%u' of literal '%u' occurs twice",
1790 elit / 2, elit);
1791 kitten->marks[iidx] = true;
1792 PUSH_STACK (kitten->klause, ilit);
1793 }
1794 for (unsigned *p = kitten->klause.begin; p != kitten->klause.end; p++)
1795 kitten->marks[*p / 2] = false;
1796 new_original_klause (kitten, id);
1798}
1799
1800void kitten_clause (kitten *kitten, size_t size, unsigned *elits) {
1802 INVALID);
1803}
1804
1805void kitten_unit (kitten *kitten, unsigned lit) {
1806 kitten_clause (kitten, 1, &lit);
1807}
1808
1809void kitten_binary (kitten *kitten, unsigned a, unsigned b) {
1810 unsigned clause[2] = {a, b};
1812}
1813
1814#ifdef STAND_ALONE_KITTEN
1815static volatile bool time_limit_hit;
1816#endif
1817
1820 if (kitten->status)
1821 reset_incremental (kitten);
1822 else if (kitten->level)
1824
1825 LOG ("starting solving under %zu assumptions",
1827
1828 INC (kitten_solved);
1829
1830 int res = propagate_units (kitten);
1831 while (!res) {
1832 const unsigned conflict = propagate (kitten);
1833 if (conflict != INVALID) {
1834 if (kitten->level)
1835 analyze (kitten, conflict);
1836 else {
1837 inconsistent (kitten, conflict);
1838 res = 20;
1839 }
1840 } else
1841#ifdef STAND_ALONE_KITTEN
1842 if (time_limit_hit) {
1843 time_limit_hit = false;
1844 break;
1845 } else
1846#endif
1847 res = decide (kitten);
1848 }
1849
1850 if (res < 0)
1851 res = 0;
1852
1853 if (!res && !EMPTY_STACK (kitten->assumptions))
1854 reset_assumptions (kitten);
1855
1856 UPDATE_STATUS (res);
1857
1858 if (res == 10)
1859 INC (kitten_sat);
1860 else if (res == 20)
1861 INC (kitten_unsat);
1862 else
1863 INC (kitten_unknown);
1864
1865 LOG ("finished solving with result %d", res);
1866
1867 return res;
1868}
1869
1871
1873 uint64_t *learned_ptr) {
1874 REQUIRE_STATUS (20);
1875
1876 if (!kitten->antecedents)
1877 INVALID_API_USAGE ("antecedents not tracked");
1878
1879 LOG ("computing clausal core");
1880
1881 unsigneds *resolved = &kitten->resolved;
1883
1884 unsigned original = 0;
1885 uint64_t learned = 0;
1886
1887 unsigned reason_ref = kitten->inconsistent;
1888
1889 if (reason_ref == INVALID) {
1891 reason_ref = kitten->failing;
1892 if (reason_ref == INVALID) {
1893 LOG ("assumptions mutually inconsistent");
1894
1895
1896 // goto DONE;
1897 if (learned_ptr)
1898 *learned_ptr = learned;
1899
1900 LOG ("clausal core of %u original clauses", original);
1901 LOG ("clausal core of %" PRIu64 " learned clauses", learned);
1902#ifdef STAND_ALONE_KITTEN
1903 kitten->statistics.original = original;
1904 kitten->statistics.learned = 0;
1905#endif
1906 UPDATE_STATUS (21);
1907
1908 return original;
1909
1910
1911 }
1912 }
1913
1914 PUSH_STACK (*resolved, reason_ref);
1915 unsigneds *core = &kitten->core;
1917
1918 while (!EMPTY_STACK (*resolved)) {
1919 const unsigned c_ref = POP_STACK (*resolved);
1920 if (c_ref == INVALID) {
1921 const unsigned d_ref = POP_STACK (*resolved);
1922 ROG (d_ref, "core[%zu]", SIZE_STACK (*core));
1923 PUSH_STACK (*core, d_ref);
1924 klause *d = dereference_klause (kitten, d_ref);
1925 KISSAT_assert (!is_core_klause (d));
1926 set_core_klause (d);
1927 if (is_learned_klause (d))
1928 learned++;
1929 else
1930 original++;
1931 } else {
1932 klause *c = dereference_klause (kitten, c_ref);
1933 if (is_core_klause (c))
1934 continue;
1935 PUSH_STACK (*resolved, c_ref);
1937 ROG (c_ref, "analyzing antecedent core");
1938 if (!is_learned_klause (c))
1939 continue;
1940 for (all_antecedents (d_ref, c)) {
1941 klause *d = dereference_klause (kitten, d_ref);
1942 if (!is_core_klause (d))
1943 PUSH_STACK (*resolved, d_ref);
1944 }
1945 }
1946 }
1947
1948 //DONE:
1949
1950 if (learned_ptr)
1951 *learned_ptr = learned;
1952
1953 LOG ("clausal core of %u original clauses", original);
1954 LOG ("clausal core of %" PRIu64 " learned clauses", learned);
1955#ifdef STAND_ALONE_KITTEN
1956 kitten->statistics.original = original;
1957 kitten->statistics.learned = 0;
1958#endif
1959 UPDATE_STATUS (21);
1960
1961 return original;
1962}
1963
1965 void (*traverse) (void *, unsigned)) {
1966 REQUIRE_STATUS (21);
1967
1968 LOG ("traversing core of original clauses");
1969
1970 unsigned traversed = 0;
1971
1972 for (all_original_klauses (c)) {
1973 KISSAT_assert (!is_learned_klause (c));
1974 if (is_learned_klause (c))
1975 continue;
1976 if (!is_core_klause (c))
1977 continue;
1978 ROG (reference_klause (kitten, c), "traversing");
1979 traverse (state, c->aux);
1980 traversed++;
1981 }
1982
1983 LOG ("traversed %u original core clauses", traversed);
1984 (void) traversed;
1985
1986 KISSAT_assert (kitten->status == 21);
1987}
1988
1990 void (*traverse) (void *, bool, size_t,
1991 const unsigned *)) {
1992 REQUIRE_STATUS (21);
1993
1994 LOG ("traversing clausal core");
1995
1996 unsigned traversed = 0;
1997
1998 for (all_stack (unsigned, c_ref, kitten->core)) {
1999 klause *c = dereference_klause (kitten, c_ref);
2000 KISSAT_assert (is_core_klause (c));
2001 const bool learned = is_learned_klause (c);
2002 unsigneds *eclause = &kitten->eclause;
2004 for (all_literals_in_klause (ilit, c)) {
2005 const unsigned elit = export_literal (kitten, ilit);
2006 PUSH_STACK (*eclause, elit);
2007 }
2008 const size_t size = SIZE_STACK (*eclause);
2009 const unsigned *elits = eclause->begin;
2010 ROG (reference_klause (kitten, c), "traversing");
2011 traverse (state, learned, size, elits);
2013 traversed++;
2014 }
2015
2016 LOG ("traversed %u core clauses", traversed);
2017 (void) traversed;
2018
2019 KISSAT_assert (kitten->status == 21);
2020}
2021
2023 REQUIRE_STATUS (21);
2024
2025 LOG ("shrinking formula to core of original clauses");
2026
2028
2029 kitten->unassigned = kitten->lits / 2;
2030 kitten->propagated = 0;
2031 kitten->level = 0;
2032
2033 update_search (kitten, kitten->queue.last);
2034
2035 memset (kitten->values, 0, kitten->lits);
2036
2037 for (all_kits (lit))
2039
2041 klause *inconsistent = dereference_klause (kitten, kitten->inconsistent);
2042 if (is_learned_klause (inconsistent) || inconsistent->size) {
2043 ROG (kitten->inconsistent, "resetting inconsistent");
2045 } else
2046 ROG (kitten->inconsistent, "keeping inconsistent");
2047
2049
2050 klause *begin = begin_klauses (kitten), *q = begin;
2051 klause const *const end = end_original_klauses (kitten);
2052#ifdef LOGGING
2053 unsigned original = 0;
2054#endif
2055 for (klause *c = begin, *next; c != end; c = next) {
2056 next = next_klause (kitten, c);
2057 KISSAT_assert (!is_learned_klause (c));
2058 if (is_learned_klause (c))
2059 continue;
2060 if (!is_core_klause (c))
2061 continue;
2062 unset_core_klause (c);
2063 const unsigned dst = (unsigned *) q - (unsigned *) begin;
2064 const unsigned size = c->size;
2065 if (!size) {
2066 if (!kitten->inconsistent)
2067 kitten->inconsistent = dst;
2068 } else if (size == 1)
2069 PUSH_STACK (kitten->units, dst);
2070 else {
2071 watch_klause (kitten, c->lits[0], c, dst);
2072 watch_klause (kitten, c->lits[1], c, dst);
2073 }
2074 if (c == q)
2075 q = next;
2076 else {
2077 const size_t bytes = (char *) next - (char *) c;
2078 memmove (q, c, bytes);
2079 q = (klause *) ((char *) q + bytes);
2080 }
2081#ifdef LOGGING
2082 original++;
2083#endif
2084 }
2085 SET_END_OF_STACK (kitten->klauses, (unsigned *) q);
2087 LOG ("end of original clauses at %zu", kitten->end_original_ref);
2088 LOG ("%u original clauses left", original);
2089
2091
2092 UPDATE_STATUS (0);
2093}
2094
2095signed char kitten_value (kitten *kitten, unsigned elit) {
2096 REQUIRE_STATUS (10);
2097 const unsigned eidx = elit / 2;
2098 if (eidx >= kitten->evars)
2099 return 0;
2100 unsigned iidx = kitten->import[eidx];
2101 if (!iidx)
2102 return 0;
2103 const unsigned ilit = 2 * (iidx - 1) + (elit & 1);
2104 return kitten->values[ilit];
2105}
2106
2107signed char kitten_fixed (kitten *kitten, unsigned elit) {
2108 const unsigned eidx = elit / 2;
2109 if (eidx >= kitten->evars)
2110 return 0;
2111 unsigned iidx = kitten->import[eidx];
2112 if (!iidx)
2113 return 0;
2114 iidx--;
2115 const unsigned ilit = 2 * iidx + (elit & 1);
2116 signed char res = kitten->values[ilit];
2117 if (!res)
2118 return 0;
2119 kar *v = kitten->vars + iidx;
2120 if (v->level)
2121 return 0;
2122 return res;
2123}
2124
2125bool kitten_flip_literal (kitten *kitten, unsigned elit) {
2126 REQUIRE_STATUS (10);
2127 const unsigned eidx = elit / 2;
2128 if (eidx >= kitten->evars)
2129 return false;
2130 unsigned iidx = kitten->import[eidx];
2131 if (!iidx)
2132 return false;
2133 const unsigned ilit = 2 * (iidx - 1) + (elit & 1);
2134 return flip_literal (kitten, ilit);
2135}
2136
2137bool kitten_failed (kitten *kitten, unsigned elit) {
2138 REQUIRE_STATUS (20);
2139 const unsigned eidx = elit / 2;
2140 if (eidx >= kitten->evars)
2141 return false;
2142 unsigned iidx = kitten->import[eidx];
2143 if (!iidx)
2144 return false;
2145 const unsigned ilit = 2 * (iidx - 1) + (elit & 1);
2146 return kitten->failed[ilit];
2147}
2148
2149/*------------------------------------------------------------------------*/
2150
2151#ifdef STAND_ALONE_KITTEN
2152
2153#include <ctype.h>
2154#include <signal.h>
2155#include <sys/resource.h>
2156#include <sys/time.h>
2157
2158static double process_time (void) {
2159 struct rusage u;
2160 double res;
2161 if (getrusage (RUSAGE_SELF, &u))
2162 return 0;
2163 res = u.ru_utime.tv_sec + 1e-6 * u.ru_utime.tv_usec;
2164 res += u.ru_stime.tv_sec + 1e-6 * u.ru_stime.tv_usec;
2165 return res;
2166}
2167
2168static double maximum_resident_set_size (void) {
2169 struct rusage u;
2170 if (getrusage (RUSAGE_SELF, &u))
2171 return 0;
2172 const uint64_t bytes = ((uint64_t) u.ru_maxrss) << 10;
2173 return bytes / (double) (1 << 20);
2174}
2175
2176#include "attribute.h"
2177
2178static void msg (const char *, ...) __attribute__ ((format (printf, 1, 2)));
2179
2180static void msg (const char *fmt, ...) {
2181 fputs ("c ", stdout);
2182 va_list ap;
2183 va_start (ap, fmt);
2184 vprintf (fmt, ap);
2185 va_end (ap);
2186 fputc ('\n', stdout);
2187 fflush (stdout);
2188}
2189
2190#undef logging
2191
2192typedef struct parser parser;
2193
2194struct parser {
2195 const char *path;
2196 uint64_t lineno;
2197 FILE *file;
2198#ifdef LOGGING
2199 bool logging;
2200#endif
2201};
2202
2203static void parse_error (parser *parser, const char *msg) {
2204 fprintf (stderr, "kitten: error: %s:%" PRIu64 ": parse error: %s\n",
2205 parser->path, parser->lineno, msg);
2206 exit (1);
2207}
2208
2209#define ERROR(...) parse_error (parser, __VA_ARGS__)
2210
2211static inline int next_char (parser *parser) {
2212 int res = getc (parser->file);
2213 if (res == '\r') {
2214 res = getc (parser->file);
2215 if (res != '\n')
2216 ERROR ("expected new line after carriage return");
2217 }
2218 if (res == '\n')
2219 parser->lineno++;
2220 return res;
2221}
2222
2223#define NEXT() next_char (parser)
2224
2225#define FAILED INT_MIN
2226
2227static int parse_number (parser *parser, int *res_ptr) {
2228 int ch = NEXT ();
2229 if (!isdigit (ch))
2230 return FAILED;
2231 int res = ch - '0';
2232 while (isdigit (ch = NEXT ())) {
2233 if (!res)
2234 return FAILED;
2235 if (INT_MAX / 10 < res)
2236 return FAILED;
2237 res *= 10;
2238 const int digit = ch - '0';
2239 if (INT_MAX - digit < res)
2240 return FAILED;
2241 res += digit;
2242 }
2243 *res_ptr = res;
2244 return ch;
2245}
2246
2247static kitten *parse (parser *parser, ints *originals, int *max_var) {
2248 signed char *marks = 0;
2249 size_t size_marks = 0;
2250 int last = '\n', ch;
2251 for (;;) {
2252 ch = NEXT ();
2253 if (ch == 'c') {
2254 while ((ch = NEXT ()) != '\n')
2255 if (ch == EOF)
2256 ERROR ("unexpected end-of-file in comment");
2257 } else if (ch != ' ' && ch != '\t' && ch != '\n')
2258 break;
2259 last = ch;
2260 }
2261 if (ch != 'p' || last != '\n')
2262 ERROR ("expected 'c' or 'p' at start of line");
2263 bool valid = (NEXT () == ' ' && NEXT () == 'c' && NEXT () == 'n' &&
2264 NEXT () == 'f' && NEXT () == ' ');
2265 int vars = 0;
2266 int clauses = 0;
2267 if (valid && (parse_number (parser, &vars) != ' ' ||
2268 parse_number (parser, &clauses) != '\n'))
2269 valid = false;
2270 if (!valid)
2271 ERROR ("invalid header");
2272 msg ("found header 'p cnf %d %d'", vars, clauses);
2273 *max_var = vars;
2275#ifdef LOGGING
2276 kitten->logging = parser->logging;
2277#define logging (kitten->logging)
2278#endif
2279 unsigneds clause;
2281 int iidx = 0;
2282 int parsed = 0;
2283 bool tautological = false;
2284 uint64_t offset = 0;
2285 for (;;) {
2286 ch = NEXT ();
2287 if (ch == EOF) {
2288 if (parsed < clauses)
2289 ERROR ("clause missing");
2290 if (iidx)
2291 ERROR ("zero missing");
2292 break;
2293 }
2294 if (ch == ' ' || ch == '\t' || ch == '\n')
2295 continue;
2296 if (ch == 'c') {
2297 while ((ch = NEXT ()) != '\n')
2298 if (ch == EOF)
2299 ERROR ("unexpected end-of-file in comment");
2300 continue;
2301 }
2302 int sign = 1;
2303 if (ch == '-')
2304 sign = -1;
2305 else
2306 ungetc (ch, parser->file);
2307 ch = parse_number (parser, &iidx);
2308 if (ch == FAILED)
2309 ERROR ("invalid literal");
2310 if (ch == EOF)
2311 ERROR ("unexpected end-of-file after literal");
2312 if (ch == 'c') {
2313 while ((ch = NEXT ()) != '\n')
2314 if (ch == EOF)
2315 ERROR ("unexpected end-of-file in comment");
2316 } else if (ch != ' ' && ch != '\t' && ch != '\n')
2317 ERROR ("expected comment or white space after literal");
2318 if (iidx > vars)
2319 ERROR ("maximum variable exceeded");
2320 if (parsed == clauses)
2321 ERROR ("too many clauses");
2322 const int ilit = sign * iidx;
2323 if (originals)
2324 PUSH_STACK (*originals, ilit);
2325 if (!iidx) {
2326 for (all_stack (unsigned, ulit, clause))
2327 marks[ulit / 2] = 0;
2328 if (tautological) {
2329 LOG ("skipping tautological clause");
2330 tautological = false;
2331 } else if (offset > UINT_MAX)
2332 ERROR ("too many original literals");
2333 else {
2334 KISSAT_assert (SIZE_STACK (clause) <= UINT_MAX);
2335 const unsigned size = SIZE_STACK (clause);
2336 const unsigned *const lits = BEGIN_STACK (clause);
2337 kitten_clause_with_id_and_exception (kitten, offset, size, lits,
2338 INVALID);
2339 }
2341 parsed++;
2342
2343 if (originals)
2344 offset = SIZE_STACK (*originals);
2345 else
2346 offset = parsed;
2347 } else if (!tautological) {
2348 const unsigned uidx = iidx - 1;
2349 const unsigned ulit = 2 * uidx + (sign < 0);
2350 if (uidx >= size_marks) {
2351 size_t new_size_marks = size_marks ? 2 * size_marks : 1;
2352 while (uidx >= new_size_marks)
2353 new_size_marks *= 2;
2354 signed char *new_marks;
2355 CALLOC (signed char, new_marks, new_size_marks);
2356 if (size_marks)
2357 memcpy (new_marks, marks, size_marks);
2358 DEALLOC (marks, size_marks);
2359 size_marks = new_size_marks;
2360 marks = new_marks;
2361 }
2362 value mark = marks[uidx];
2363 if (sign < 0)
2364 mark = -mark;
2365 if (mark > 0)
2366 LOG ("dropping repeated %d in parsed clause", ilit);
2367 else if (mark < 0) {
2368 LOG ("parsed clause contains both %d and %d", -ilit, ilit);
2369 tautological = true;
2370 } else {
2371 LOG ("adding parsed integer literal %d as external literal %u",
2372 ilit, ulit);
2373 marks[uidx] = sign;
2374 PUSH_STACK (clause, ulit);
2375 }
2376 }
2377 }
2379 free (marks);
2380 return kitten;
2381}
2382
2383typedef struct line line;
2384
2385struct line {
2386 char buffer[80];
2387 size_t size;
2388};
2389
2390static void flush_line (line *line) {
2391 if (!line->size)
2392 return;
2393 for (size_t i = 0; i < line->size; i++)
2394 fputc (line->buffer[i], stdout);
2395 fputc ('\n', stdout);
2396 line->size = 0;
2397}
2398
2399static inline void print_lit (line *line, int lit) {
2400 char tmp[16];
2401 sprintf (tmp, " %d", lit);
2402 const size_t len = strlen (tmp);
2403 if (line->size + len > 78)
2404 flush_line (line);
2405 if (!line->size) {
2406 line->buffer[0] = 'v';
2407 line->size = 1;
2408 }
2409 strcpy (line->buffer + line->size, tmp);
2410 line->size += len;
2411}
2412
2413static void print_witness (kitten *kitten, int max_var) {
2414 KISSAT_assert (max_var >= 0);
2415 line line = {.size = 0};
2416 const size_t parsed_lits = 2 * (size_t) max_var;
2417 for (size_t ulit = 0; ulit < parsed_lits; ulit += 2) {
2418 const value sign = kitten_value (kitten, ulit);
2419 const int iidx = ulit / 2 + 1;
2420 const int ilit = (sign > 0 ? iidx : -iidx);
2421 print_lit (&line, ilit);
2422 }
2423 print_lit (&line, 0);
2424 flush_line (&line);
2425}
2426
2427static double percent (double a, double b) { return b ? 100 * a / b : 0; }
2428
2429typedef struct core_writer core_writer;
2430
2431struct core_writer {
2432 FILE *file;
2433 ints *originals;
2434#ifndef KISSAT_NDEBUG
2435 unsigned written;
2436#endif
2437};
2438
2439static void write_offset (void *ptr, unsigned offset) {
2440 core_writer *writer = ptr;
2441#ifndef KISSAT_NDEBUG
2442 writer->written++;
2443#endif
2444 int const *p = &PEEK_STACK (*writer->originals, offset);
2445 FILE *file = writer->file;
2446 while (*p)
2447 fprintf (file, "%d ", *p++);
2448 fputs ("0\n", file);
2449}
2450
2451static void write_core (kitten *kitten, unsigned reduced, ints *originals,
2452 FILE *file) {
2453 KISSAT_assert (originals);
2454 fprintf (file, "p cnf %zu %u\n", kitten->evars, reduced);
2455 core_writer writer;
2456 writer.file = file;
2457 writer.originals = originals;
2458#ifndef KISSAT_NDEBUG
2459 writer.written = 0;
2460#endif
2461 kitten_traverse_core_ids (kitten, &writer, write_offset);
2462 KISSAT_assert (writer.written == reduced);
2463}
2464
2465#ifndef KISSAT_NDEBUG
2466
2467typedef struct lemma_writer lemma_writer;
2468
2469struct lemma_writer {
2470 FILE *file;
2471 uint64_t written;
2472};
2473
2474#endif
2475
2476static void write_lemma (void *ptr, bool learned, size_t size,
2477 const unsigned *lits) {
2478 if (!learned)
2479 return;
2480 const unsigned *const end = lits + size;
2481#ifdef KISSAT_NDEBUG
2482 FILE *file = ptr;
2483#else
2484 lemma_writer *writer = ptr;
2485 FILE *file = writer->file;
2486 writer->written++;
2487#endif
2488 for (const unsigned *p = lits; p != end; p++) {
2489 const unsigned ulit = *p;
2490 const unsigned idx = ulit / 2;
2491 const unsigned sign = ulit & 1;
2492 KISSAT_assert (idx + 1 <= (unsigned) INT_MAX);
2493 int ilit = idx + 1;
2494 if (sign)
2495 ilit = -ilit;
2496 fprintf (file, "%d ", ilit);
2497 }
2498 fputs ("0\n", file);
2499}
2500
2501static void write_lemmas (kitten *kitten, uint64_t reduced, FILE *file) {
2502 void *state;
2503#ifdef KISSAT_NDEBUG
2504 state = file;
2505 (void) reduced;
2506#else
2507 lemma_writer writer;
2508 writer.file = file;
2509 writer.written = 0;
2510 state = &writer;
2511#endif
2512 kitten_traverse_core_clauses (kitten, state, write_lemma);
2513 KISSAT_assert (writer.written == reduced);
2514}
2515
2516static void print_statistics (statistics statistics) {
2517 msg ("conflicts: %20" PRIu64,
2518 statistics.kitten_conflicts);
2519 msg ("decisions: %20" PRIu64,
2520 statistics.kitten_decisions);
2521 msg ("propagations: %20" PRIu64,
2522 statistics.kitten_propagations);
2523 msg ("maximum-resident-set-size: %23.2f MB",
2524 maximum_resident_set_size ());
2525 msg ("process-time: %23.2f seconds", process_time ());
2526}
2527
2528static volatile int time_limit;
2529static volatile kitten *static_kitten;
2530
2531#define SIGNALS \
2532 SIGNAL (SIGABRT) \
2533 SIGNAL (SIGBUS) \
2534 SIGNAL (SIGINT) \
2535 SIGNAL (SIGSEGV) \
2536 SIGNAL (SIGTERM)
2537
2538// clang-format off
2539
2540#define SIGNAL(SIG) \
2541static void (*SIG ## _handler)(int);
2542SIGNALS
2543#undef SIGNAL
2544
2545static void (*SIGALRM_handler)(int);
2546
2547// clang-format on
2548
2549static void reset_alarm (void) {
2550 if (time_limit > 0) {
2551 time_limit = 0;
2552 time_limit_hit = false;
2553 }
2554}
2555
2556static void reset_signals (void) {
2557#define SIGNAL(SIG) signal (SIG, SIG##_handler);
2558 SIGNALS
2559#undef SIGNAL
2560 static_kitten = 0;
2561}
2562
2563static const char *signal_name (int sig) {
2564#define SIGNAL(SIG) \
2565 if (sig == SIG) \
2566 return #SIG;
2567 SIGNALS
2568#undef SIGNAL
2569 return "SIGUNKNOWN";
2570}
2571
2572static void catch_signal (int sig) {
2573 if (!static_kitten)
2574 return;
2575 statistics statistics = static_kitten->statistics;
2576 reset_signals ();
2577 msg ("caught signal %d (%s)", sig, signal_name (sig));
2578 print_statistics (statistics);
2579 raise (sig);
2580}
2581
2582static void catch_alarm (int sig) {
2583 KISSAT_assert (sig == SIGALRM);
2584 if (time_limit > 0)
2585 time_limit_hit = true;
2586 (void) sig;
2587}
2588
2589static void init_signals (kitten *kitten) {
2590 static_kitten = kitten;
2591#define SIGNAL(SIG) SIG##_handler = signal (SIG, catch_signal);
2592 SIGNALS
2593#undef SIGNAL
2594 if (time_limit > 0) {
2595 SIGALRM_handler = signal (SIGALRM, catch_alarm);
2596 alarm (time_limit);
2597 }
2598}
2599
2600static bool parse_arg (const char *arg, unsigned *res_ptr) {
2601 unsigned res = 0;
2602 int ch;
2603 while ((ch = *arg++)) {
2604 if (!isdigit (ch))
2605 return false;
2606 if (UINT_MAX / 10 < res)
2607 return false;
2608 res *= 10;
2609 const unsigned digit = ch - '0';
2610 if (UINT_MAX - digit < res)
2611 return false;
2612 res += digit;
2613 }
2614 *res_ptr = res;
2615 return true;
2616}
2617
2618static bool parse_lit (const char *arg, int *res_ptr) {
2619 int res = 0, sign, ch;
2620 if (*arg == '-') {
2621 sign = -1;
2622 if (*++arg == '0')
2623 return false;
2624 } else
2625 sign = 1;
2626 while ((ch = *arg++)) {
2627 if (!isdigit (ch))
2628 return false;
2629 if (INT_MAX / 10 < res)
2630 return false;
2631 res *= 10;
2632 const int digit = ch - '0';
2633 if (INT_MAX - digit < res)
2634 return false;
2635 res += digit;
2636 }
2637 res *= sign;
2638 *res_ptr = res;
2639 return true;
2640}
2641
2642#undef logging
2643
2644int main (int argc, char **argv) {
2645 ints assumptions;
2646 INIT_STACK (assumptions);
2647 const char *dimacs_path = 0;
2648 const char *output_path = 0;
2649 unsigned shrink = 0;
2650 bool witness = true;
2651 bool proof = false;
2652#ifdef LOGGING
2653 bool logging = false;
2654#endif
2655 for (int i = 1; i < argc; i++) {
2656 const char *arg = argv[i];
2657 if (!strcmp (arg, "-h"))
2658 fputs (usage, stdout), exit (0);
2659#ifdef LOGGING
2660 else if (!strcmp (arg, "-l"))
2661 logging = true;
2662#endif
2663 else if (!strcmp (arg, "-n"))
2664 witness = false;
2665 else if (!strcmp (arg, "-p"))
2666 proof = true;
2667 else if (!strcmp (arg, "-a")) {
2668 if (++i == argc)
2669 die ("argument to '-a' missing");
2670 int lit;
2671 if (!parse_lit (argv[i], &lit) || !lit)
2672 die ("invalid '-a %s'", argv[i]);
2673 PUSH_STACK (assumptions, lit);
2674 } else if (!strcmp (arg, "-t")) {
2675 if (++i == argc)
2676 die ("argument to '-t' missing");
2677 if ((time_limit = atoi (argv[i])) <= 0)
2678 die ("invalid argument in '-t %s'", argv[i]);
2679 } else if (arg[0] == '-' && arg[1] == 'O' && !arg[2])
2680 shrink = 1;
2681 else if (arg[0] == '-' && arg[1] == 'O' && parse_arg (arg + 2, &shrink))
2682 ;
2683 else if (*arg == '-')
2684 die ("invalid option '%s' (try '-h')", arg);
2685 else if (output_path)
2686 die ("too many arguments (try '-h')");
2687 else if (dimacs_path)
2688 output_path = arg;
2689 else
2690 dimacs_path = arg;
2691 }
2692 if (proof && !output_path)
2693 die ("option '-p' without output file");
2694 if (shrink && !EMPTY_STACK (assumptions))
2695 die ("can not using shrinking with assumptions");
2696 FILE *dimacs_file;
2697 bool close_dimacs_file = true;
2698 if (!dimacs_path)
2699 close_dimacs_file = false, dimacs_file = stdin, dimacs_path = "<stdin>";
2700 else if (!(dimacs_file = fopen (dimacs_path, "r")))
2701 die ("can not open '%s' for reading", dimacs_path);
2702 msg ("Kitten SAT Solver");
2703 msg ("Copyright (c) 2021-2024 Armin Biere University of Freiburg");
2704 msg ("Copyright (c) 2020-2021 Armin Biere Johannes Kepler University "
2705 "Linz");
2706 msg ("reading '%s'", dimacs_path);
2707 ints originals;
2708 INIT_STACK (originals);
2709 kitten *kitten;
2710 int max_var;
2711 {
2712 parser parser;
2713 parser.path = dimacs_path;
2714 parser.lineno = 1;
2715 parser.file = dimacs_file;
2716#ifdef LOGGING
2717 parser.logging = logging;
2718#endif
2719 kitten = parse (&parser, ((output_path && !proof) ? &originals : 0),
2720 &max_var);
2721 }
2722 if (close_dimacs_file)
2723 fclose (dimacs_file);
2724 msg ("parsed DIMACS file in %.2f seconds", process_time ());
2725 init_signals (kitten);
2726 if (output_path) {
2727 msg ("tracking antecedents");
2729 }
2730 if (!EMPTY_STACK (assumptions)) {
2731 msg ("assuming %zu assumptions", SIZE_STACK (assumptions));
2732 for (all_stack (int, ilit, assumptions)) {
2733 unsigned ulit = 2u * (abs (ilit) - 1) + (ilit < 0);
2734 kitten_assume (kitten, ulit);
2735 }
2736 }
2737 int res = kitten_solve (kitten);
2738 if (res == 10) {
2739 printf ("s SATISFIABLE\n");
2740 fflush (stdout);
2741 if (witness)
2742 print_witness (kitten, max_var);
2743 } else if (res == 20) {
2744 printf ("s UNSATISFIABLE\n");
2745 fflush (stdout);
2746 if (output_path) {
2747 const unsigned original = kitten->statistics.original;
2748 const uint64_t learned = kitten->statistics.learned;
2749 unsigned reduced_original, round = 0;
2750 uint64_t reduced_learned;
2751
2752 for (;;) {
2753 msg ("computing clausal core of %" PRIu64 " clauses",
2754 kitten->statistics.original + kitten->statistics.learned);
2755
2756 reduced_original =
2757 kitten_compute_clausal_core (kitten, &reduced_learned);
2758
2759 msg ("found %" PRIu64 " core lemmas %.0f%% "
2760 "out of %" PRIu64 " learned clauses",
2761 reduced_learned, percent (reduced_learned, learned), learned);
2762
2763 if (!shrink--)
2764 break;
2765
2766 msg ("shrinking round %u", ++round);
2767
2768 msg ("reduced to %u core clauses %.0f%% "
2769 "out of %u original clauses",
2770 reduced_original, percent (reduced_original, original),
2771 original);
2772
2775
2776 reset_alarm ();
2777 res = kitten_solve (kitten);
2778 KISSAT_assert (res == 20);
2779 }
2780 FILE *output_file = fopen (output_path, "w");
2781 if (!output_file)
2782 die ("can not open '%s' for writing", output_path);
2783 if (proof) {
2784 msg ("writing proof to '%s'", output_path);
2785 write_lemmas (kitten, reduced_learned, output_file);
2786 msg ("written %" PRIu64 " core lemmas %.0f%% of %" PRIu64
2787 " learned clauses",
2788 reduced_learned, percent (reduced_learned, learned), learned);
2789 } else {
2790 msg ("writing original clausal core to '%s'", output_path);
2791 write_core (kitten, reduced_original, &originals, output_file);
2792 msg ("written %u core clauses %.0f%% of %u original clauses",
2793 reduced_original, percent (reduced_original, original),
2794 original);
2795 }
2796 fclose (output_file);
2797 }
2798 } else {
2799 fputs ("s UNKNOWN\n", stdout);
2800 fflush (stdout);
2801 }
2802 RELEASE_STACK (originals);
2803 RELEASE_STACK (assumptions);
2804 statistics statistics = kitten->statistics;
2805 reset_signals ();
2807 print_statistics (statistics);
2808 msg ("exit %d", res);
2809 return res;
2810}
2811
2812#endif
2813
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
void kissat_free(kissat *solver, void *ptr, size_t bytes)
Definition allocate.c:61
ABC_NAMESPACE_IMPL_END int main(int argc, char *argv[])
GLOBAL VARIABLES ///.
Definition main.c:9
#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
#define ADD(NAME, DELTA)
#define all_klauses(C)
#define INC(NAME)
#define CALLOC(T, P, N)
#define all_antecedents(REF, C)
ABC_NAMESPACE_IMPL_START typedef signed char value
#define all_literals_in_klause(KIT, C)
#define CORE_FLAG
#define KATCHES(KIT)
#define LEARNED_FLAG
#define all_original_klauses(C)
#define KITTEN_TICKS
#define DEALLOC(P, N)
#define INVALID
#define all_kits(KIT)
struct kar kar
#define SIGNALS
void kissat_fatal(const char *fmt,...)
Definition error.c:58
Cube * p
Definition exorList.c:222
struct file file
Definition file.h:21
#define vprintf
Definition fretime.h:138
#define NEXT()
Definition gzread.c:69
#define KISSAT_assert(ignore)
Definition global.h:13
kitten * kitten_init(void)
int kitten_solve(kitten *kitten)
Definition kitten.c:1818
void kitten_shrink_to_clausal_core(kitten *kitten)
Definition kitten.c:2022
kitten * kitten_embedded(struct kissat *kissat)
Definition kitten.c:664
#define RESIZE2(T, P)
Definition kitten.c:559
unsigned new_learned_klause(kitten *kitten)
Definition kitten.c:962
#define REQUIRE_INITIALIZED()
Definition kitten.c:628
void kitten_traverse_core_clauses(kitten *kitten, void *state, void(*traverse)(void *, bool, size_t, const unsigned *))
Definition kitten.c:1989
void kitten_traverse_core_ids(kitten *kitten, void *state, void(*traverse)(void *, unsigned))
Definition kitten.c:1964
bool kitten_flip_literal(kitten *kitten, unsigned elit)
Definition kitten.c:2125
#define LOG(...)
Definition kitten.c:422
void kitten_unit(kitten *kitten, unsigned lit)
Definition kitten.c:1805
void kitten_release(kitten *kitten)
Definition kitten.c:1028
void kitten_binary(kitten *kitten, unsigned a, unsigned b)
Definition kitten.c:1809
void kitten_assume(kitten *kitten, unsigned elit)
Definition kitten.c:1763
bool kitten_failed(kitten *kitten, unsigned elit)
Definition kitten.c:2137
void kitten_no_ticks_limit(kitten *kitten)
Definition kitten.c:743
void kitten_track_antecedents(kitten *kitten)
Definition kitten.c:680
#define ROG(...)
Definition kitten.c:425
void kitten_clause(kitten *kitten, size_t size, unsigned *elits)
Definition kitten.c:1800
#define REQUIRE_STATUS(EXPECTED)
Definition kitten.c:634
void kitten_clause_with_id_and_exception(kitten *kitten, unsigned id, size_t size, const unsigned *elits, unsigned except)
Definition kitten.c:1772
signed char kitten_fixed(kitten *kitten, unsigned elit)
Definition kitten.c:2107
#define INVALID_API_USAGE(...)
Definition kitten.c:626
#define KATCHES(KIT)
Definition kitten.c:312
int kitten_status(kitten *kitten)
Definition kitten.c:1870
void kitten_set_ticks_limit(kitten *kitten, uint64_t delta)
Definition kitten.c:749
#define RESIZE1(T, P)
Definition kitten.c:546
unsigned kitten_compute_clausal_core(kitten *kitten, uint64_t *learned_ptr)
Definition kitten.c:1872
void kitten_shuffle_clauses(kitten *kitten)
Definition kitten.c:825
void kitten_randomize_phases(kitten *kitten)
Definition kitten.c:690
void kitten_clear(kitten *kitten)
Definition kitten.c:986
void completely_backtrack_to_root_level(kitten *kitten)
Definition kitten.c:1260
void kitten_flip_phases(kitten *kitten)
Definition kitten.c:722
signed char kitten_value(kitten *kitten, unsigned elit)
Definition kitten.c:2095
#define UPDATE_STATUS(STATUS)
Definition kitten.c:643
usage()
Definition main.c:626
uint64_t maximum_resident_set_size()
double percent(double a, double b)
Definition util.hpp:21
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
Definition file.h:23
unsigned ref
Definition kitten.c:161
unsigned blit
Definition kitten.c:160
bool binary
Definition kitten.c:162
uint64_t ticks
uint64_t stamp
unsigned next
unsigned prev
kar * vars
Definition kitten.c:249
size_t lits
Definition kitten.c:232
uint64_t initialized
Definition kitten.c:270
unsigned propagated
Definition kitten.c:225
unsigneds klause
Definition kitten.c:263
katches * watches
Definition kitten.c:256
unsigned first
Definition kitten.c:238
unsigned * import
Definition kitten.c:255
value * values
Definition kitten.c:252
unsigneds core
Definition kitten.c:260
unsigneds analyzed
Definition kitten.c:258
size_t evars
Definition kitten.c:233
unsigned level
Definition kitten.c:224
kimits limits
Definition kitten.c:269
struct kissat * kissat
Definition kitten.c:210
unsigneds units
Definition kitten.c:267
unsigned search
Definition kitten.c:240
unsigneds assumptions
Definition kitten.c:259
unsigneds export_
Definition kitten.c:262
int status
Definition kitten.c:216
unsigneds eclause
Definition kitten.c:261
unsigned inconsistent
Definition kitten.c:227
bool * failed
Definition kitten.c:253
unsigneds trail
Definition kitten.c:266
uint64_t stamp
Definition kitten.c:239
struct kitten::@051124040274372165372010377332320121035140324322 queue
unsigneds resolved
Definition kitten.c:265
kink * links
Definition kitten.c:250
size_t size
Definition kitten.c:246
unsigned last
Definition kitten.c:238
unsigned failing
Definition kitten.c:228
bool learned
Definition kitten.c:222
value * marks
Definition kitten.c:251
uint64_t generator
Definition kitten.c:230
unsigned char * phases
Definition kitten.c:254
bool antecedents
Definition kitten.c:221
unsigned unassigned
Definition kitten.c:226
unsigneds klauses
Definition kitten.c:264
size_t esize
Definition kitten.c:247
size_t end_original_ref
Definition kitten.c:235
unsigned size
unsigned aux
unsigned lits[1]
unsigned flags
Definition queue.h:20
uint64_t original
uint64_t learned
#define TERMINATED(BIT)
Definition terminate.h:42
#define kitten_terminated_1
Definition terminate.h:65
char * memcpy()
char * calloc()
VOID_HACK abort()
char * memset()
int strlen()
int strcmp()
char * sprintf()
char * memmove()
char * strcpy()
VOID_HACK free()
VOID_HACK exit()
long random()
signed char mark
Definition value.h:8
vector watches
Definition watch.h:49
#define const
Definition zconf.h:196