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