ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
resolve.c
Go to the documentation of this file.
1#include "resolve.h"
2#include "eliminate.h"
3#include "gates.h"
4#include "inline.h"
5#include "print.h"
6
7#include <inttypes.h>
8#include <string.h>
9
11
12static inline unsigned occurrences_literal (kissat *solver, unsigned lit,
13 bool *update) {
14 KISSAT_assert (!solver->watching);
15
17#ifdef LOGGING
18 const size_t size_watches = SIZE_WATCHES (*watches);
19 LOG ("literal %s has %zu watches", LOGLIT (lit), size_watches);
20#endif
21 const unsigned clslim = GET_OPTION (eliminateclslim);
22
23 watch *const begin = BEGIN_WATCHES (*watches), *q = begin;
24 const watch *const end = END_WATCHES (*watches), *p = q;
25
26 const value *const values = solver->values;
27 ward *const arena = BEGIN_STACK (solver->arena);
28
29 bool failed = false;
30 unsigned res = 0;
31
32 while (p != end) {
33 const watch head = *q++ = *p++;
34 if (head.type.binary) {
35 const unsigned other = head.binary.lit;
36 const value value = values[other];
37 KISSAT_assert (value >= 0);
38 if (value > 0) {
40 q--;
41 } else
42 res++;
43 } else {
44 const reference ref = head.large.ref;
45 KISSAT_assert (ref < SIZE_STACK (solver->arena));
46 clause *const c = (struct clause *) (arena + ref);
47 if (c->garbage)
48 q--;
49 else if (c->size > clslim) {
50 LOG ("literal %s watches too long clause of size %u", LOGLIT (lit),
51 c->size);
52 failed = true;
53 break;
54 } else
55 res++;
56 }
57 }
58 while (p != end)
59 *q++ = *p++;
61 if (failed)
62 return UINT_MAX;
63 if (q != end) {
64 *update = true;
65 LOG ("literal %s actually occurs only %u times", LOGLIT (lit), res);
66 }
67 return res;
68}
69
70static inline clause *watch_to_clause (kissat *solver, ward *const arena,
71 clause *const tmp, unsigned lit,
72 watch watch) {
73 clause *res;
74 if (watch.type.binary) {
75 const unsigned other = watch.binary.lit;
76 tmp->lits[0] = lit;
77 tmp->lits[1] = other;
78 res = tmp;
79 } else {
80 const reference ref = watch.large.ref;
81 KISSAT_assert (ref < SIZE_STACK (solver->arena));
82 res = (struct clause *) (arena + ref);
83 }
84#ifdef KISSAT_NDEBUG
85 (void) solver;
86#endif
87 return res;
88}
89
90static bool generate_resolvents (kissat *solver, unsigned lit,
91 statches *const watches0,
92 statches *const watches1,
93 uint64_t *const resolved_ptr,
94 uint64_t limit) {
95 const unsigned not_lit = NOT (lit);
96 unsigned resolved = *resolved_ptr;
97 bool failed = false;
98
99 clause tmp0, tmp1;
100 memset (&tmp0, 0, sizeof tmp0);
101 memset (&tmp1, 0, sizeof tmp1);
102 tmp0.size = tmp1.size = 2;
103
104 ward *const arena = BEGIN_STACK (solver->arena);
105 const value *const values = solver->values;
106 value *const marks = solver->marks;
107
108 const unsigned clslim = GET_OPTION (eliminateclslim);
109
110 for (all_stack (watch, watch0, *watches0)) {
111 clause *const c = watch_to_clause (solver, arena, &tmp0, lit, watch0);
112
113 if (c->garbage) {
114 KISSAT_assert (c != &tmp0);
115 continue;
116 }
117
118 bool first_antecedent_satisfied = false;
119
120 for (all_literals_in_clause (other, c)) {
121 if (other == lit)
122 continue;
123 const value value = values[other];
124 if (value < 0)
125 continue;
126 if (value > 0) {
127 first_antecedent_satisfied = true;
128 if (c != &tmp0)
130 break;
131 }
132 }
133
134 if (first_antecedent_satisfied)
135 continue;
136
137 for (all_literals_in_clause (other, c)) {
138 if (other == lit)
139 continue;
140 KISSAT_assert (!marks[other]);
141 marks[other] = 1;
142 }
143
144 for (all_stack (watch, watch1, *watches1)) {
145 clause *const d =
146 watch_to_clause (solver, arena, &tmp1, not_lit, watch1);
147
148 if (d->garbage) {
149 KISSAT_assert (d != &tmp1);
150 continue;
151 }
152
153 LOGCLS (c, "first %s antecedent", LOGLIT (lit));
154 LOGCLS (d, "second %s antecedent", LOGLIT (not_lit));
155
156 bool resolvent_satisfied_or_tautological = false;
157 const size_t saved = SIZE_STACK (solver->resolvents);
158
159 INC (eliminate_resolutions);
160
161 for (all_literals_in_clause (other, d)) {
162 if (other == not_lit)
163 continue;
164 const value value = values[other];
165 if (value < 0) {
166 LOG2 ("dropping falsified literal %s", LOGLIT (other));
167 continue;
168 }
169 if (value > 0) {
170 if (d != &tmp1)
172 resolvent_satisfied_or_tautological = true;
173 break;
174 }
175 if (marks[other]) {
176 LOG2 ("dropping repeated %s literal", LOGLIT (other));
177 continue;
178 }
179 const unsigned not_other = NOT (other);
180 if (marks[not_other]) {
181 LOG ("resolvent tautological on %s and %s "
182 "with second %s antecedent",
183 LOGLIT (NOT (other)), LOGLIT (other), LOGLIT (not_lit));
184 resolvent_satisfied_or_tautological = true;
185 break;
186 }
187 LOG2 ("including unassigned literal %s", LOGLIT (other));
188 PUSH_STACK (solver->resolvents, other);
189 }
190
191 if (resolvent_satisfied_or_tautological) {
192 RESIZE_STACK (solver->resolvents, saved);
193 continue;
194 }
195
196 if (++resolved > limit) {
197 LOG ("limit of %" PRIu64 " resolvent exceeded", limit);
198 failed = true;
199 break;
200 }
201
202 for (all_literals_in_clause (other, c)) {
203 if (other == lit)
204 continue;
205 const value value = values[other];
206 KISSAT_assert (value <= 0);
207 if (value < 0) {
208 LOG2 ("dropping falsified literal %s", LOGLIT (other));
209 continue;
210 }
211 PUSH_STACK (solver->resolvents, other);
212 }
213
214 size_t size_resolvent = SIZE_STACK (solver->resolvents) - saved;
215 LOGLITS (size_resolvent, BEGIN_STACK (solver->resolvents) + saved,
216 "resolvent");
217
218 if (!size_resolvent) {
219 KISSAT_assert (!solver->inconsistent);
220 solver->inconsistent = true;
221 LOG ("resolved empty clause");
224 failed = true;
225 break;
226 }
227
228 if (size_resolvent == 1) {
229 const unsigned unit = PEEK_STACK (solver->resolvents, saved);
230 INC (eliminate_units);
232 RESIZE_STACK (solver->resolvents, saved);
233 if (marks[unit] <= 0)
234 continue;
235 LOGCLS (c, "first antecedent becomes satisfied");
236 first_antecedent_satisfied = true;
237 (void) first_antecedent_satisfied;
238 break;
239 }
240
241 if (size_resolvent > clslim) {
242 LOG ("resolvent size limit exceeded");
243 failed = true;
244 break;
245 }
246
247 PUSH_STACK (solver->resolvents, INVALID_LIT);
248 }
249
250 for (all_literals_in_clause (other, c)) {
251 if (other == lit)
252 continue;
253 KISSAT_assert (marks[other] == 1);
254 marks[other] = 0;
255 }
256
257 if (failed)
258 break;
259 }
260
261 *resolved_ptr = resolved;
262
263 return !failed;
264}
265
267 unsigned *lit_ptr) {
268 unsigned lit = LIT (idx);
269 unsigned not_lit = NOT (lit);
270
271 bool update = false;
272 bool pure = false;
273 uint64_t limit;
274
275 {
276 unsigned pos_count = occurrences_literal (solver, lit, &update);
277 unsigned neg_count = occurrences_literal (solver, not_lit, &update);
278
279 if (pos_count > neg_count) {
280 SWAP (unsigned, lit, not_lit);
281 SWAP (size_t, pos_count, neg_count);
282 }
283
284 const unsigned occlim = GET_OPTION (eliminateocclim);
285 limit = pos_count + (uint64_t) neg_count;
286
287 if (pos_count && limit > occlim) {
288 LOG ("no elimination of variable %u "
289 "since it has %" PRIu64 " > %u occurrences",
290 idx, limit, occlim);
291 return false;
292 }
293
294 if (pos_count) {
295 const uint64_t bound = solver->bounds.eliminate.additional_clauses;
296 limit += bound;
297 LOG ("trying to eliminate %s "
298 "limit %" PRIu64 " bound %" PRIu64,
299 LOGVAR (idx), limit, bound);
300 } else {
301 LOG ("eliminating pure literal %s thus its variable %u", LOGLIT (lit),
302 idx);
303 pure = true;
304 }
305 }
306
307 *lit_ptr = lit;
308
309 INC (eliminate_attempted);
310 if (pure)
311 return true;
312
313 const bool gates = !pure && kissat_find_gates (solver, lit);
314
315 statches *const gates0 = &solver->gates[0];
316 statches *const gates1 = &solver->gates[1];
317
318 if (solver->values[lit]) {
319 kissat_extremely_verbose (solver, "definition produced unit");
320 CLEAR_STACK (*gates0);
321 CLEAR_STACK (*gates1);
322 return false;
323 }
324
325 bool failed = false;
326 uint64_t resolved = 0;
327
329 statches *const antecedents0 = &solver->antecedents[0];
330 statches *const antecedents1 = &solver->antecedents[1];
331
332 if (gates) {
333 LOG ("resolving gates[0] against antecedents[1] clauses");
334 if (!generate_resolvents (solver, lit, gates0, antecedents1, &resolved,
335 limit))
336 failed = true;
337 else {
338 LOG ("resolving gates[1] against antecedents[0] clauses");
339 if (!generate_resolvents (solver, not_lit, gates1, antecedents0,
340 &resolved, limit)) {
341 failed = true;
342 } else if (solver->resolve_gate) {
343 LOG ("need to resolved gates[0] against gates[1] too");
344 if (!generate_resolvents (solver, lit, gates0, gates1, &resolved,
345 limit))
346 failed = true;
347 }
348 }
349 } else {
350 LOG ("no gate extracted thus resolving all clauses");
351 if (!generate_resolvents (solver, lit, antecedents0, antecedents1,
352 &resolved, limit))
353 failed = true;
354 }
355
356 CLEAR_STACK (*antecedents0);
357 CLEAR_STACK (*antecedents1);
358
359 if (failed) {
360 LOG ("elimination of %s failed", LOGVAR (IDX (lit)));
361 CLEAR_STACK (solver->resolvents);
362 if (update)
364 }
365
366 LOG ("resolved %" PRIu64 " resolvents", resolved);
367
368 CLEAR_STACK (*gates0);
369 CLEAR_STACK (*gates1);
370
371 return !failed;
372}
373
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
ABC_NAMESPACE_HEADER_START typedef word ward
Definition arena.h:12
void kissat_learned_unit(kissat *solver, unsigned lit)
Definition assign.c:18
#define BEGIN_STACK(S)
Definition stack.h:46
#define RESIZE_STACK(S, NEW_SIZE)
Definition stack.h:55
#define all_stack(T, E, S)
Definition stack.h:94
#define SIZE_STACK(S)
Definition stack.h:19
#define CLEAR_STACK(S)
Definition stack.h:50
#define PUSH_STACK(S, E)
Definition stack.h:39
#define PEEK_STACK(S, N)
Definition stack.h:29
#define INVALID_LIT
#define INC(NAME)
#define LOG(...)
ABC_NAMESPACE_IMPL_START typedef signed char value
#define LOGLITS(...)
#define CHECK_AND_ADD_EMPTY(...)
Definition check.h:146
void kissat_eliminate_clause(kissat *solver, clause *c, unsigned lit)
Definition eliminate.c:128
void kissat_update_variable_score(kissat *solver, unsigned idx)
Definition eliminate.c:82
void kissat_eliminate_binary(kissat *solver, unsigned lit, unsigned other)
Definition eliminate.c:121
Cube * p
Definition exorList.c:222
bool kissat_find_gates(kissat *solver, unsigned lit)
Definition gates.c:36
void kissat_get_antecedents(kissat *solver, unsigned lit)
Definition gates.c:103
#define all_literals_in_clause(LIT, C)
Definition clause.h:47
#define KISSAT_assert(ignore)
Definition global.h:13
#define solver
Definition kitten.c:211
#define LOGCLS(...)
Definition logging.h:415
#define LOG2(...)
Definition logging.h:352
#define LOGLIT(...)
Definition logging.hpp:99
unsigned short ref
Definition giaNewBdd.h:38
#define GET_OPTION(N)
Definition options.h:295
#define kissat_extremely_verbose(...)
Definition print.h:53
#define ADD_EMPTY_TO_PROOF(...)
Definition proof.h:135
ABC_NAMESPACE_HEADER_START typedef unsigned reference
Definition reference.h:9
bool kissat_generate_resolvents(kissat *solver, unsigned idx, unsigned *lit_ptr)
Definition resolve.c:266
int lit
Definition satVec.h:130
#define LIT(IDX)
Definition literal.h:31
#define IDX(LIT)
Definition literal.h:28
#define NOT(LIT)
Definition literal.h:33
unsigned lits[3]
Definition clause.h:39
unsigned size
Definition clause.h:37
bool garbage
Definition clause.h:25
Definition watch.h:41
large_watch large
Definition watch.h:45
watch_type type
Definition watch.h:42
binary_watch binary
Definition watch.h:43
char * memset()
#define SWAP(TYPE, A, B)
Definition utilities.h:151
#define SIZE_WATCHES(W)
Definition watch.h:104
#define BEGIN_WATCHES(WS)
Definition watch.h:115
#define END_WATCHES(WS)
Definition watch.h:118
#define SET_END_OF_WATCHES(WS, P)
Definition watch.h:128
vector watches
Definition watch.h:49
#define WATCHES(LIT)
Definition watch.h:137