16#ifdef STAND_ALONE_KITTEN
23static const char *
usage =
28" [-n] [-O[<n>]] [-p] [ <dimacs> [ <output> ] ]\n"
33" -l enable low-level logging\n"
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"
43" <dimacs> input in DIMACS format (default '<stdin>')\n"
44" <output> DRAT proof or clausal core file\n"
51typedef signed char value;
53static void die (
const char *fmt, ...) {
54 fputs (
"kitten: error: ", stderr);
57 vfprintf (stderr, fmt, ap);
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);
70#define CALLOC(T, P, N) \
72 (P) = (T*) kitten_calloc (N, sizeof *(P)); \
74#define DEALLOC(P, N) free (P)
78#define ENLARGE_STACK(S) \
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); \
87 die ("out of memory reallocating '%zu' bytes", BYTES); \
88 (S).allocated = (S).begin + NEW_CAPACITY; \
89 (S).end = (S).begin + SIZE; \
96 statistics *statistics = &kitten->statistics; \
97 KISSAT_assert (statistics->NAME < UINT64_MAX); \
101#define ADD(NAME, DELTA) \
103 statistics *statistics = &kitten->statistics; \
104 KISSAT_assert (statistics->NAME <= UINT64_MAX - (DELTA)); \
105 statistics->NAME += (DELTA); \
108#define KITTEN_TICKS (kitten->statistics.kitten_ticks)
119#define KITTEN_TICKS (solver->statistics_.kitten_ticks)
127#define INVALID UINT_MAX
128#define MAX_VARS ((1u << 31) - 1)
130#define CORE_FLAG (1u)
131#define LEARNED_FLAG (2u)
180#ifdef STAND_ALONE_KITTEN
187 uint64_t kitten_flip;
188 uint64_t kitten_flipped;
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;
209#ifndef STAND_ALONE_KITTEN
211#define solver (kitten->kissat)
218#if defined(STAND_ALONE_KITTEN) && defined(LOGGING)
272#ifdef STAND_ALONE_KITTEN
279static inline bool is_core_klause (
klause *c) {
283static inline bool is_learned_klause (
klause *c) {
301 const unsigned *
p = (
const unsigned *) c;
304 const unsigned res =
p - begin;
312#define KATCHES(KIT) (kitten->watches[KISSAT_assert ((KIT) < kitten->lits), (KIT)])
314#define all_klauses(C) \
315 klause *C = begin_klauses (kitten), *end_##C = end_klauses (kitten); \
317 (C) = next_klause (kitten, C)
319#define all_original_klauses(C) \
320 klause *C = begin_klauses (kitten), \
321 *end_##C = end_original_klauses (kitten); \
323 (C) = next_klause (kitten, C)
325#define all_learned_klauses(C) \
326 klause *C = begin_learned_klauses (kitten), \
327 *end_##C = end_klauses (kitten); \
329 (C) = next_klause (kitten, C)
331#define all_kits(KIT) \
332 size_t KIT = 0, KIT_##END = kitten->lits; \
336#define BEGIN_KLAUSE(C) (C)->lits
338#define END_KLAUSE(C) (BEGIN_KLAUSE (C) + (C)->size)
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); \
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); \
354#ifdef STAND_ALONE_KITTEN
355#define logging (kitten->logging)
357#define logging GET_OPTION (log)
360static void log_basic (
kitten *,
const char *, ...)
361 __attribute__ ((format (printf, 2, 3)));
370 fputc (
'\n', stdout);
374static void log_reference (
kitten *,
unsigned,
const char *, ...)
375 __attribute__ ((format (printf, 3, 4)));
386 if (is_learned_klause (c)) {
387 fputs (
" learned", stdout);
389 printf (
"[%u]", c->
aux);
391 fputs (
" original", stdout);
393 printf (
"[%u]", c->
aux);
395 printf (
" size %u clause[%u]", c->
size, ref);
402 printf (
"@%u=%d", vars[
lit / 2].level, (
int)
value);
404 fputc (
'\n', stdout);
411 log_basic (kitten, __VA_ARGS__); \
417 log_reference (kitten, __VA_ARGS__); \
434 unsigned found = 0, prev =
INVALID;
466 const unsigned lit = 2 * idx;
475static void update_search (
kitten *
kitten,
unsigned idx) {
479 LOG (
"search updated to %u stamped %" PRIu64, idx,
484 LOG (
"enqueue %u", idx);
500 LOG (
"dequeue %u", idx);
503 const unsigned prev = l->
prev;
504 const unsigned next = l->
next;
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++) {
522 LOG (
"initialized decision queue from %zu to %zu", old_vars, new_vars);
540#ifdef STAND_ALONE_KITTEN
543 initialize_kitten (
kitten);
546#define RESIZE1(T, P) \
548 void *OLD_PTR = (P); \
549 CALLOC (T, (P), new_size / 2); \
550 const size_t BYTES = old_vars * sizeof *(P); \
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; \
559#define RESIZE2(T, P) \
561 void *OLD_PTR = (P); \
562 CALLOC (T, (P), new_size); \
563 const size_t BYTES = old_lits * sizeof *(P); \
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; \
572static void enlarge_internal (
kitten *
kitten,
size_t new_lits) {
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)
582 LOG (
"internal literals resized to %zu from %zu (requested %zu)",
583 new_size, old_size, new_lits);
596 init_queue (
kitten, old_vars, new_vars);
597 LOG (
"internal literals activated until %zu literals", new_lits);
601static const char *status_to_string (
int status) {
604 return "formula satisfied";
606 return "formula inconsistent";
608 return "formula inconsistent and core computed";
611 return "formula unsolved";
615static void invalid_api_usage (
const char *fun,
const char *fmt, ...) {
616 fprintf (stderr,
"kitten: fatal error: invalid API usage in '%s': ", fun);
619 vfprintf (stderr, fmt, ap);
621 fputc (
'\n', stderr);
626#define INVALID_API_USAGE(...) invalid_api_usage (__func__, __VA_ARGS__)
628#define REQUIRE_INITIALIZED() \
631 INVALID_API_USAGE ("solver argument zero"); \
634#define REQUIRE_STATUS(EXPECTED) \
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)); \
643#define UPDATE_STATUS(STATUS) \
645 if (kitten->status != (STATUS)) \
646 LOG ("updating status from '%s' to '%s'", \
647 status_to_string (kitten->status), status_to_string (STATUS)); \
649 LOG ("keeping status at '%s'", status_to_string (STATUS)); \
650 kitten->status = (STATUS); \
653#ifdef STAND_ALONE_KITTEN
658 initialize_kitten (
kitten);
674 initialize_kitten (
kitten);
686 LOG (
"enabling antecedents tracking");
693 LOG (
"randomizing phases");
701 const unsigned rest =
vars & ~63u;
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;
725 LOG (
"flipping phases");
731 const unsigned rest =
vars & ~7u;
734 uint64_t *
p = (uint64_t *) (
phases + i);
735 *
p ^= 0x0101010101010101;
745 LOG (
"forcing no ticks limit");
753 if (UINT64_MAX - delta <= current) {
754 LOG (
"forcing unlimited ticks limit");
757 limit = current + delta;
758 LOG (
"new limit of %" PRIu64
" ticks after %" PRIu64, limit, delta);
766 for (
size_t i = 0; i !=
size; i++) {
770 const unsigned first = a[i];
771 const unsigned second = a[j];
777static void shuffle_unsigned_stack (
kitten *
kitten, unsigneds *stack) {
784 for (
size_t i = 0; i !=
size; i++) {
789 const katch second = a[j];
795static void shuffle_katches_stack (
kitten *
kitten, katches *stack) {
802 LOG (
"shuffling watch lists");
809 LOG (
"shuffling variable decision order");
812 for (
unsigned i = 0; i !=
vars; i++) {
821 LOG (
"shuffling units");
832static inline unsigned *antecedents_func (
klause *c) {
839 ROG (ref,
"watching %u in",
lit);
846 const unsigned blit = c->
lits[0] ^ c->
lits[1] ^
lit;
847 const bool binary =
size == 2;
858static inline void connect_new_klause (
kitten *
kitten,
unsigned ref) {
865 ROG (ref,
"registering inconsistent empty");
868 ROG (ref,
"ignoring inconsistent empty");
869 }
else if (c->
size == 1) {
870 ROG (ref,
"watching unit");
881#ifdef STAND_ALONE_KITTEN
882 die (
"maximum number of literals exhausted");
884 kissat_fatal (
"kitten: maximum number of literals exhausted");
887 const unsigned res = (unsigned) ref;
893static void new_original_klause (
kitten *
kitten,
unsigned id) {
894 unsigned res = new_reference (
kitten);
902 connect_new_klause (
kitten, res);
904#ifdef STAND_ALONE_KITTEN
905 kitten->statistics.original++;
909static void enlarge_external (
kitten *
kitten,
size_t 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)
918 LOG (
"external resizing to %zu variables from %zu (requested %u)",
919 new_size, old_size, new_evars);
922 const size_t bytes = old_evars *
sizeof *
kitten->
import;
925 DEALLOC (old_import, old_size);
929 LOG (
"external variables enlarged to %u", new_evars);
932static unsigned import_literal (
kitten *
kitten,
unsigned elit) {
933 const unsigned eidx = elit / 2;
935 enlarge_external (
kitten, eidx);
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;
950 enlarge_internal (
kitten, new_lits);
954static unsigned export_literal (
kitten *
kitten,
unsigned ilit) {
955 const unsigned iidx = ilit / 2;
958 const unsigned elit = 2 * eidx + (ilit & 1);
963 unsigned res = new_reference (
kitten);
978 connect_new_klause (
kitten, res);
980#ifdef STAND_ALONE_KITTEN
1010#ifndef KISSAT_NDEBUG
1011 for (
unsigned i = 0; i <
vars; i++)
1043#ifndef STAND_ALONE_KITTEN
1055#ifdef STAND_ALONE_KITTEN
1062static inline void move_to_front (
kitten *
kitten,
unsigned idx) {
1065 LOG (
"move to front variable %u", idx);
1071static inline void assign (
kitten *
kitten,
unsigned lit,
unsigned reason) {
1074 LOG (
"assign %u as decision",
lit);
1076 ROG (reason,
"assign %u reason",
lit);
1079 const unsigned not_lit =
lit ^ 1;
1084 const unsigned idx =
lit / 2;
1085 const unsigned sign =
lit & 1;
1098 const unsigned other_idx = other / 2;
1099 const unsigned other_ref =
kitten->
vars[other_idx].reason;
1115static inline unsigned propagate_literal (
kitten *
kitten,
unsigned lit) {
1116 LOG (
"propagating %u",
lit);
1119 const unsigned not_lit =
lit ^ 1;
1125 uint64_t ticks = (((
char *) end_watches - (
char *) q) >> 7) + 1;
1126 while (
p != end_watches) {
1136 if (blit_value < 0) {
1137 ROG (ref,
"conflict");
1138 INC (kitten_conflicts);
1143 assign (
kitten, blit, ref);
1151 const unsigned other =
lits[0] ^
lits[1] ^ not_lit;
1154 if (other_value > 0) {
1160 value replacement_value = -1;
1161 unsigned replacement =
INVALID;
1162 const unsigned *
const end_lits =
lits + c->
size;
1164 for (r =
lits + 2; r != end_lits; r++) {
1166 replacement_value =
values[replacement];
1167 if (replacement_value >= 0)
1170 if (replacement_value >= 0) {
1172 ROG (ref,
"unwatching %u in", not_lit);
1174 lits[1] = replacement;
1176 watch_klause (
kitten, replacement, c, ref);
1178 }
else if (other_value < 0) {
1179 ROG (ref,
"conflict");
1180 INC (kitten_conflicts);
1185 assign (
kitten, other, ref);
1188 while (
p != end_watches)
1191 ADD (kitten_ticks, ticks);
1202 conflict = propagate_literal (
kitten,
lit);
1214 move_to_front (
kitten, idx);
1220 const unsigned not_lit =
lit ^ 1;
1223 const unsigned idx =
lit / 2;
1227 LOG (
"unassign %u",
lit);
1235 update_search (
kitten, idx);
1241 LOG (
"back%s to level %u",
1242 (
kitten->
level == jump + 1 ?
"tracking" :
"jumping"), jump);
1248 const unsigned idx =
lit / 2;
1262 LOG (
"completely backtracking to level 0");
1265#ifndef KISSAT_NDEBUG
1278static void analyze (
kitten *
kitten,
unsigned conflict) {
1285 unsigned reason = conflict;
1290 unsigned open = 0, jump = 0,
size = 1, uip;
1295 ROG (reason,
"analyzing");
1298 const unsigned idx =
lit / 2;
1302 LOG (
"analyzed %u",
lit);
1305 const kar *
const v =
vars + idx;
1306 const unsigned tmp = v->level;
1325 }
while (!
marks[idx = uip / 2]);
1329 reason =
vars[idx].reason;
1331 const unsigned not_uip = uip ^ 1;
1332 LOG (
"first UIP %u jump level %u size %u", not_uip, jump,
size);
1339 backtrack (
kitten, jump);
1340 assign (
kitten, not_uip, learned_ref);
1349 LOG (
"analyzing failing assumptions");
1352 unsigned failed_clashing =
INVALID;
1353 unsigned first_failed =
INVALID;
1354 unsigned failed_unit =
INVALID;
1360 const unsigned failed_idx =
lit / 2;
1361 const kar *
const failed_var =
vars + failed_idx;
1362 if (!failed_var->level) {
1367 failed_clashing =
lit;
1372 else if (failed_clashing !=
INVALID)
1373 failed = failed_clashing;
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);
1385 LOG (
"root-level falsified assumption %u",
failed);
1391 const unsigned not_failed =
failed ^ 1;
1392 if (failed_clashing !=
INVALID) {
1393 LOG (
"clashing with negated assumption %u", not_failed);
1401 marks[failed_idx] =
true;
1409 const unsigned reason =
var->reason;
1411 unsigned lit = 2 * idx;
1414 LOG (
"failed assumption %u",
lit);
1417 const unsigned not_lit =
lit ^ 1;
1420 ROG (reason,
"analyzing");
1424 const unsigned other_idx = other / 2;
1425 if (other_idx == idx)
1427 if (
marks[other_idx])
1429 marks[other_idx] =
true;
1431 LOG (
"analyzing final literal %u", other ^ 1);
1474 LOG (
"found failing assumption %u", assumption);
1477 }
else if (
value > 0) {
1480 LOG (
"pseudo decision level %u for already satisfied assumption %u",
1483 decision = assumption;
1484 LOG (
"using assumption %u as decision", decision);
1493 LOG (
"ticks limit %" PRIu64
" hit after %" PRIu64
" ticks",
1498#ifndef STAND_ALONE_KITTEN
1512 update_search (
kitten, idx);
1514 decision = 2 * idx + phase;
1515 LOG (
"decision %u variable %u phase %u", decision, idx, phase);
1517 INC (kitten_decisions);
1529 ROG (ref,
"registering inconsistent virtually empty");
1547 ROG (ref,
"analyzing inconsistent");
1550 const unsigned idx =
lit / 2;
1555 LOG (
"analyzed %u",
lit);
1563 const kar *
const v =
vars + idx;
1569 ROG (ref,
"registering final inconsistent empty");
1584 LOG (
"no root level unit clauses");
1588 LOG (
"propagating %zu root level unit clauses",
1598 ROG (ref,
"propagating unit");
1599 const unsigned unit = c->
lits[0];
1607 assign (
kitten, unit, ref);
1608 const unsigned conflict = propagate (
kitten);
1644 LOG (
"resetting core clauses");
1647 if (is_core_klause (c))
1648 unset_core_klause (c), reset++;
1649 LOG (
"reset %zu core clauses", reset);
1659#ifndef KISSAT_NDEBUG
1674 reset_assumptions (
kitten);
1689 LOG (
"can not flip root-level assigned literal %u",
lit);
1694 LOG (
"trying to flip value of satisfied literal %u",
lit);
1700 uint64_t ticks = (((
char *) end_watches - (
char *) q) >> 7) + 1;
1702 while (
p != end_watches) {
1717 if (other_value > 0)
1719 value replacement_value = -1;
1720 unsigned replacement =
INVALID;
1721 const unsigned *
const end_lits =
lits + c->
size;
1723 for (r =
lits + 2; r != end_lits; r++) {
1726 replacement_value =
values[replacement];
1728 if (replacement_value > 0)
1731 if (replacement_value > 0) {
1733 ROG (ref,
"unwatching %u in",
lit);
1735 lits[1] = replacement;
1737 watch_klause (
kitten, replacement, c, ref);
1741 ROG (ref,
"single satisfied");
1746 while (
p != end_watches)
1749 ADD (kitten_ticks, ticks);
1751 LOG (
"flipping value of %u",
lit);
1753 const unsigned not_lit =
lit ^ 1;
1755 INC (kitten_flipped);
1757 LOG (
"failed to flip value of %u",
lit);
1766 reset_incremental (
kitten);
1767 const unsigned ilit = import_literal (
kitten, elit);
1768 LOG (
"registering assumption %u", ilit);
1774 const unsigned *elits,
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;
1785 const unsigned ilit = import_literal (
kitten, elit);
1787 const unsigned iidx = ilit / 2;
1796 new_original_klause (
kitten,
id);
1810 unsigned clause[2] = {a, b};
1814#ifdef STAND_ALONE_KITTEN
1815static volatile bool time_limit_hit;
1821 reset_incremental (
kitten);
1825 LOG (
"starting solving under %zu assumptions",
1828 INC (kitten_solved);
1830 int res = propagate_units (
kitten);
1832 const unsigned conflict = propagate (
kitten);
1835 analyze (
kitten, conflict);
1841#ifdef STAND_ALONE_KITTEN
1842 if (time_limit_hit) {
1843 time_limit_hit =
false;
1854 reset_assumptions (
kitten);
1863 INC (kitten_unknown);
1865 LOG (
"finished solving with result %d", res);
1873 uint64_t *learned_ptr) {
1879 LOG (
"computing clausal core");
1884 unsigned original = 0;
1893 LOG (
"assumptions mutually inconsistent");
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;
1926 set_core_klause (d);
1927 if (is_learned_klause (d))
1933 if (is_core_klause (c))
1937 ROG (c_ref,
"analyzing antecedent core");
1938 if (!is_learned_klause (c))
1942 if (!is_core_klause (d))
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;
1965 void (*traverse) (
void *,
unsigned)) {
1968 LOG (
"traversing core of original clauses");
1970 unsigned traversed = 0;
1974 if (is_learned_klause (c))
1976 if (!is_core_klause (c))
1978 ROG (reference_klause (
kitten, c),
"traversing");
1979 traverse (state, c->
aux);
1983 LOG (
"traversed %u original core clauses", traversed);
1990 void (*traverse) (
void *,
bool,
size_t,
1991 const unsigned *)) {
1994 LOG (
"traversing clausal core");
1996 unsigned traversed = 0;
2001 const bool learned = is_learned_klause (c);
2005 const unsigned elit = export_literal (
kitten, ilit);
2009 const unsigned *elits =
eclause->begin;
2010 ROG (reference_klause (
kitten, c),
"traversing");
2016 LOG (
"traversed %u core clauses", traversed);
2025 LOG (
"shrinking formula to core of original clauses");
2042 if (is_learned_klause (inconsistent) || inconsistent->size) {
2051 klause const *
const end = end_original_klauses (
kitten);
2053 unsigned original = 0;
2055 for (
klause *c = begin, *next; c != end; c = next) {
2056 next = next_klause (
kitten, c);
2058 if (is_learned_klause (c))
2060 if (!is_core_klause (c))
2062 unset_core_klause (c);
2063 const unsigned dst = (
unsigned *) q - (
unsigned *) begin;
2068 }
else if (
size == 1)
2077 const size_t bytes = (
char *) next - (
char *) c;
2079 q = (
klause *) ((
char *) q + bytes);
2088 LOG (
"%u original clauses left", original);
2097 const unsigned eidx = elit / 2;
2103 const unsigned ilit = 2 * (iidx - 1) + (elit & 1);
2108 const unsigned eidx = elit / 2;
2115 const unsigned ilit = 2 * iidx + (elit & 1);
2127 const unsigned eidx = elit / 2;
2133 const unsigned ilit = 2 * (iidx - 1) + (elit & 1);
2134 return flip_literal (
kitten, ilit);
2139 const unsigned eidx = elit / 2;
2145 const unsigned ilit = 2 * (iidx - 1) + (elit & 1);
2151#ifdef STAND_ALONE_KITTEN
2155#include <sys/resource.h>
2156#include <sys/time.h>
2158static double process_time (
void) {
2161 if (getrusage (RUSAGE_SELF, &u))
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;
2170 if (getrusage (RUSAGE_SELF, &u))
2172 const uint64_t bytes = ((uint64_t) u.ru_maxrss) << 10;
2173 return bytes / (double) (1 << 20);
2178static void msg (
const char *, ...) __attribute__ ((format (printf, 1, 2)));
2180static
void msg (
const char *fmt, ...) {
2181 fputs (
"c ", stdout);
2186 fputc (
'\n', stdout);
2192typedef struct parser parser;
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);
2209#define ERROR(...) parse_error (parser, __VA_ARGS__)
2211static inline int next_char (parser *parser) {
2212 int res = getc (parser->file);
2214 res = getc (parser->file);
2216 ERROR (
"expected new line after carriage return");
2223#define NEXT() next_char (parser)
2225#define FAILED INT_MIN
2227static int parse_number (parser *parser,
int *res_ptr) {
2232 while (isdigit (ch =
NEXT ())) {
2235 if (INT_MAX / 10 < res)
2238 const int digit = ch -
'0';
2239 if (INT_MAX - digit < res)
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;
2254 while ((ch =
NEXT ()) !=
'\n')
2256 ERROR (
"unexpected end-of-file in comment");
2257 }
else if (ch !=
' ' && ch !=
'\t' && ch !=
'\n')
2261 if (ch !=
'p' || last !=
'\n')
2262 ERROR (
"expected 'c' or 'p' at start of line");
2263 bool valid = (
NEXT () ==
' ' &&
NEXT () ==
'c' &&
NEXT () ==
'n' &&
2267 if (valid && (parse_number (parser, &vars) !=
' ' ||
2268 parse_number (parser, &clauses) !=
'\n'))
2271 ERROR (
"invalid header");
2272 msg (
"found header 'p cnf %d %d'", vars, clauses);
2276 kitten->logging = parser->logging;
2277#define logging (kitten->logging)
2283 bool tautological =
false;
2284 uint64_t offset = 0;
2288 if (parsed < clauses)
2289 ERROR (
"clause missing");
2291 ERROR (
"zero missing");
2294 if (ch ==
' ' || ch ==
'\t' || ch ==
'\n')
2297 while ((ch =
NEXT ()) !=
'\n')
2299 ERROR (
"unexpected end-of-file in comment");
2306 ungetc (ch, parser->file);
2307 ch = parse_number (parser, &iidx);
2309 ERROR (
"invalid literal");
2311 ERROR (
"unexpected end-of-file after literal");
2313 while ((ch =
NEXT ()) !=
'\n')
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");
2319 ERROR (
"maximum variable exceeded");
2320 if (parsed == clauses)
2321 ERROR (
"too many clauses");
2322 const int ilit =
sign * iidx;
2327 marks[ulit / 2] = 0;
2329 LOG (
"skipping tautological clause");
2330 tautological =
false;
2331 }
else if (offset > UINT_MAX)
2332 ERROR (
"too many original literals");
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);
2357 memcpy (new_marks, marks, size_marks);
2359 size_marks = new_size_marks;
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;
2371 LOG (
"adding parsed integer literal %d as external literal %u",
2383typedef struct line line;
2390static void flush_line (line *line) {
2393 for (
size_t i = 0; i < line->size; i++)
2394 fputc (line->buffer[i], stdout);
2395 fputc (
'\n', stdout);
2399static inline void print_lit (line *line,
int lit) {
2402 const size_t len =
strlen (tmp);
2403 if (line->size + len > 78)
2406 line->buffer[0] =
'v';
2409 strcpy (line->buffer + line->size, tmp);
2413static void print_witness (
kitten *
kitten,
int max_var) {
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) {
2419 const int iidx = ulit / 2 + 1;
2420 const int ilit = (
sign > 0 ? iidx : -iidx);
2421 print_lit (&line, ilit);
2423 print_lit (&line, 0);
2427static double percent (
double a,
double b) {
return b ? 100 * a / b : 0; }
2429typedef struct core_writer core_writer;
2434#ifndef KISSAT_NDEBUG
2439static void write_offset (
void *ptr,
unsigned offset) {
2440 core_writer *writer = ptr;
2441#ifndef KISSAT_NDEBUG
2444 int const *
p = &
PEEK_STACK (*writer->originals, offset);
2445 FILE *
file = writer->file;
2447 fprintf (
file,
"%d ", *
p++);
2448 fputs (
"0\n",
file);
2451static void write_core (
kitten *
kitten,
unsigned reduced, ints *originals,
2457 writer.originals = originals;
2458#ifndef KISSAT_NDEBUG
2465#ifndef KISSAT_NDEBUG
2467typedef struct lemma_writer lemma_writer;
2469struct lemma_writer {
2476static void write_lemma (
void *ptr,
bool learned,
size_t size,
2477 const unsigned *lits) {
2480 const unsigned *
const end = lits +
size;
2484 lemma_writer *writer = ptr;
2485 FILE *
file = writer->file;
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;
2496 fprintf (
file,
"%d ", ilit);
2498 fputs (
"0\n",
file);
2507 lemma_writer writer;
2517 msg (
"conflicts: %20" PRIu64,
2519 msg (
"decisions: %20" PRIu64,
2521 msg (
"propagations: %20" PRIu64,
2523 msg (
"maximum-resident-set-size: %23.2f MB",
2524 maximum_resident_set_size ());
2525 msg (
"process-time: %23.2f seconds", process_time ());
2528static volatile int time_limit;
2529static volatile kitten *static_kitten;
2540#define SIGNAL(SIG) \
2541static void (*SIG ## _handler)(int);
2545static void (*SIGALRM_handler)(int);
2549static void reset_alarm (
void) {
2550 if (time_limit > 0) {
2552 time_limit_hit =
false;
2556static void reset_signals (
void) {
2557#define SIGNAL(SIG) signal (SIG, SIG##_handler);
2563static const char *signal_name (
int sig) {
2564#define SIGNAL(SIG) \
2569 return "SIGUNKNOWN";
2572static void catch_signal (
int sig) {
2577 msg (
"caught signal %d (%s)", sig, signal_name (sig));
2582static void catch_alarm (
int sig) {
2585 time_limit_hit =
true;
2591#define SIGNAL(SIG) SIG##_handler = signal (SIG, catch_signal);
2594 if (time_limit > 0) {
2595 SIGALRM_handler = signal (SIGALRM, catch_alarm);
2600static bool parse_arg (
const char *arg,
unsigned *res_ptr) {
2603 while ((ch = *arg++)) {
2606 if (UINT_MAX / 10 < res)
2609 const unsigned digit = ch -
'0';
2610 if (UINT_MAX - digit < res)
2618static bool parse_lit (
const char *arg,
int *res_ptr) {
2619 int res = 0,
sign, ch;
2626 while ((ch = *arg++)) {
2629 if (INT_MAX / 10 < res)
2632 const int digit = ch -
'0';
2633 if (INT_MAX - digit < res)
2644int main (
int argc,
char **argv) {
2647 const char *dimacs_path = 0;
2648 const char *output_path = 0;
2649 unsigned shrink = 0;
2650 bool witness =
true;
2653 bool logging =
false;
2655 for (
int i = 1; i < argc; i++) {
2656 const char *arg = argv[i];
2660 else if (!
strcmp (arg,
"-l"))
2663 else if (!
strcmp (arg,
"-n"))
2665 else if (!
strcmp (arg,
"-p"))
2667 else if (!
strcmp (arg,
"-a")) {
2669 die (
"argument to '-a' missing");
2671 if (!parse_lit (argv[i], &
lit) || !
lit)
2672 die (
"invalid '-a %s'", argv[i]);
2674 }
else if (!
strcmp (arg,
"-t")) {
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])
2681 else if (arg[0] ==
'-' && arg[1] ==
'O' && parse_arg (arg + 2, &shrink))
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)
2692 if (proof && !output_path)
2693 die (
"option '-p' without output file");
2695 die (
"can not using shrinking with assumptions");
2697 bool close_dimacs_file =
true;
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 "
2706 msg (
"reading '%s'", dimacs_path);
2713 parser.path = dimacs_path;
2715 parser.file = dimacs_file;
2717 parser.logging = logging;
2719 kitten = parse (&parser, ((output_path && !proof) ? &originals : 0),
2722 if (close_dimacs_file)
2723 fclose (dimacs_file);
2724 msg (
"parsed DIMACS file in %.2f seconds", process_time ());
2727 msg (
"tracking antecedents");
2731 msg (
"assuming %zu assumptions",
SIZE_STACK (assumptions));
2732 for (
all_stack (
int, ilit, assumptions)) {
2733 unsigned ulit = 2u * (abs (ilit) - 1) + (ilit < 0);
2739 printf (
"s SATISFIABLE\n");
2742 print_witness (
kitten, max_var);
2743 }
else if (res == 20) {
2744 printf (
"s UNSATISFIABLE\n");
2747 const unsigned original =
kitten->statistics.original;
2749 unsigned reduced_original, round = 0;
2750 uint64_t reduced_learned;
2753 msg (
"computing clausal core of %" PRIu64
" clauses",
2759 msg (
"found %" PRIu64
" core lemmas %.0f%% "
2760 "out of %" PRIu64
" learned clauses",
2761 reduced_learned, percent (reduced_learned, learned), learned);
2766 msg (
"shrinking round %u", ++round);
2768 msg (
"reduced to %u core clauses %.0f%% "
2769 "out of %u original clauses",
2770 reduced_original, percent (reduced_original, original),
2780 FILE *output_file = fopen (output_path,
"w");
2782 die (
"can not open '%s' for writing", output_path);
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
2788 reduced_learned, percent (reduced_learned, learned), learned);
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),
2796 fclose (output_file);
2799 fputs (
"s UNKNOWN\n", stdout);
2808 msg (
"exit %d", res);
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
void kissat_free(kissat *solver, void *ptr, size_t bytes)
ABC_NAMESPACE_IMPL_END int main(int argc, char *argv[])
GLOBAL VARIABLES ///.
#define POKE_STACK(S, N, E)
#define all_stack(T, E, S)
#define SET_END_OF_STACK(S, P)
#define all_antecedents(REF, C)
ABC_NAMESPACE_IMPL_START typedef signed char value
#define all_literals_in_klause(KIT, C)
#define all_original_klauses(C)
void kissat_fatal(const char *fmt,...)
#define KISSAT_assert(ignore)
kitten * kitten_init(void)
int kitten_solve(kitten *kitten)
void kitten_shrink_to_clausal_core(kitten *kitten)
kitten * kitten_embedded(struct kissat *kissat)
unsigned new_learned_klause(kitten *kitten)
#define REQUIRE_INITIALIZED()
void kitten_traverse_core_clauses(kitten *kitten, void *state, void(*traverse)(void *, bool, size_t, const unsigned *))
void kitten_traverse_core_ids(kitten *kitten, void *state, void(*traverse)(void *, unsigned))
bool kitten_flip_literal(kitten *kitten, unsigned elit)
void kitten_unit(kitten *kitten, unsigned lit)
void kitten_release(kitten *kitten)
void kitten_binary(kitten *kitten, unsigned a, unsigned b)
void kitten_assume(kitten *kitten, unsigned elit)
bool kitten_failed(kitten *kitten, unsigned elit)
void kitten_no_ticks_limit(kitten *kitten)
void kitten_track_antecedents(kitten *kitten)
void kitten_clause(kitten *kitten, size_t size, unsigned *elits)
#define REQUIRE_STATUS(EXPECTED)
void kitten_clause_with_id_and_exception(kitten *kitten, unsigned id, size_t size, const unsigned *elits, unsigned except)
signed char kitten_fixed(kitten *kitten, unsigned elit)
#define INVALID_API_USAGE(...)
int kitten_status(kitten *kitten)
void kitten_set_ticks_limit(kitten *kitten, uint64_t delta)
unsigned kitten_compute_clausal_core(kitten *kitten, uint64_t *learned_ptr)
void kitten_shuffle_clauses(kitten *kitten)
void kitten_randomize_phases(kitten *kitten)
void kitten_clear(kitten *kitten)
void completely_backtrack_to_root_level(kitten *kitten)
void kitten_flip_phases(kitten *kitten)
signed char kitten_value(kitten *kitten, unsigned elit)
#define UPDATE_STATUS(STATUS)
uint64_t maximum_resident_set_size()
double percent(double a, double b)
struct kitten::@051124040274372165372010377332320121035140324322 queue
#define kitten_terminated_1