ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
shrink.c
Go to the documentation of this file.
1#include "shrink.h"
2#include "allocate.h"
3#include "inline.h"
4#include "minimize.h"
5
7
8static void reset_shrinkable (kissat *solver) {
9#ifdef LOGGING
10 size_t reset = 0;
11#endif
12 while (!EMPTY_STACK (solver->shrinkable)) {
13 const unsigned idx = POP_STACK (solver->shrinkable);
14 assigned *a = solver->assigned + idx;
16 a->shrinkable = false;
17#ifdef LOGGING
18 reset++;
19#endif
20 }
21 LOG ("resetting %zu shrinkable variables", reset);
22}
23
24static void mark_shrinkable_as_removable (kissat *solver) {
25#ifdef LOGGING
26 size_t marked = 0, reset = 0;
27#endif
28 struct assigned *assigned = solver->assigned;
29 while (!EMPTY_STACK (solver->shrinkable)) {
30 const unsigned idx = POP_STACK (solver->shrinkable);
31 struct assigned *a = assigned + idx;
33 a->shrinkable = false;
35#ifdef LOGGING
36 reset++;
37#endif
38 if (a->removable)
39 continue;
40 kissat_push_removable (solver, assigned, idx);
41#ifdef LOGGING
42 marked++;
43#endif
44 }
45 LOG ("resetting %zu shrinkable variables", reset);
46 LOG ("marked %zu removable variables", marked);
47}
48
49static inline int shrink_literal (kissat *solver, assigned *assigned,
50 unsigned level, unsigned lit) {
51 KISSAT_assert (solver->assigned == assigned);
52 KISSAT_assert (VALUE (lit) < 0);
53
54 const unsigned idx = IDX (lit);
55 struct assigned *a = assigned + idx;
57 if (!a->level) {
58 LOG2 ("skipping root level assigned %s", LOGLIT (lit));
59 return 0;
60 }
61 if (a->shrinkable) {
62 LOG2 ("skipping already shrinkable literal %s", LOGLIT (lit));
63 return 0;
64 }
65 if (a->level < level) {
66 if (a->removable) {
67 LOG2 ("skipping removable thus shrinkable %s", LOGLIT (lit));
68 return 0;
69 }
70 const bool always_minimize_on_lower_level = (GET_OPTION (shrink) > 2);
71 if (always_minimize_on_lower_level &&
73 LOG2 ("minimized thus shrinkable %s", LOGLIT (lit));
74 return 0;
75 }
76 LOG ("literal %s on lower level %u < %u not removable/shrinkable",
77 LOGLIT (lit), a->level, level);
78 return -1;
79 }
80 LOG2 ("marking %s as shrinkable", LOGLIT (lit));
81 a->shrinkable = true;
82 PUSH_STACK (solver->shrinkable, idx);
83 return 1;
84}
85
86static inline unsigned shrunken_block (kissat *solver, unsigned level,
87 unsigned *begin_block,
88 unsigned *end_block, unsigned uip) {
90 const unsigned not_uip = NOT (uip);
91 LOG ("found unique implication point %s on level %u", LOGLIT (uip),
92 level);
93
94 KISSAT_assert (begin_block < end_block);
95#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
96 const size_t tmp = end_block - begin_block;
97 LOG ("shrinking %zu literals on level %u to single literal %s", tmp,
98 level, LOGLIT (not_uip));
99 KISSAT_assert (tmp > 1);
100#endif
101
102#ifdef LOGGING
103 bool not_uip_was_in_clause = false;
104#endif
105 unsigned block_shrunken = 0;
106
107 for (unsigned *p = begin_block; p != end_block; p++) {
108 const unsigned lit = *p;
109 if (lit == INVALID_LIT)
110 continue;
111#ifdef LOGGING
112 if (lit == not_uip)
113 not_uip_was_in_clause = true;
114 else
115 LOG ("shrunken literal %s", LOGLIT (lit));
116#endif
117 *p = INVALID_LIT;
118 block_shrunken++;
119 }
120 *begin_block = not_uip;
121 KISSAT_assert (block_shrunken);
122 block_shrunken--;
123#ifdef LOGGING
124 if (not_uip_was_in_clause)
125 LOG ("keeping single literal %s on level %u", LOGLIT (not_uip), level);
126 else
127 LOG ("shrunken all literals on level %u and added %s instead", level,
128 LOGLIT (not_uip));
129#endif
130 const unsigned uip_idx = IDX (uip);
131 assigned *assigned = solver->assigned;
132 struct assigned *a = assigned + uip_idx;
133 if (!a->analyzed)
134 kissat_push_analyzed (solver, assigned, uip_idx);
135
136 mark_shrinkable_as_removable (solver);
137#ifndef LOGGING
138 (void) level;
139#endif
140 return block_shrunken;
141}
142
143static inline void push_literals_of_block (kissat *solver,
145 unsigned *begin_block,
146 unsigned *end_block,
147 unsigned level) {
148 KISSAT_assert (assigned == solver->assigned);
149
150 for (const unsigned *p = begin_block; p != end_block; p++) {
151 const unsigned lit = *p;
152 if (lit == INVALID_LIT)
153 continue;
154#ifndef KISSAT_NDEBUG
155 int tmp =
156#endif
157 shrink_literal (solver, assigned, level, lit);
158 KISSAT_assert (tmp > 0);
159 }
160}
161
162static inline unsigned shrink_along_binary (kissat *solver,
164 unsigned level, unsigned uip,
165 unsigned other) {
166 KISSAT_assert (VALUE (other) < 0);
167 LOGBINARY2 (uip, other, "shrinking along %s reason", LOGLIT (uip));
168 int tmp = shrink_literal (solver, assigned, level, other);
169#ifndef LOGGING
170 (void) uip;
171#endif
172 return tmp > 0;
173}
174
175static inline unsigned
176shrink_along_large (kissat *solver, assigned *assigned, unsigned level,
177 unsigned uip, reference ref, bool *failed_ptr) {
178 unsigned open = 0;
179 LOGREF2 (ref, "shrinking along %s reason", LOGLIT (uip));
180 clause *c = kissat_dereference_clause (solver, ref);
181 if (GET_OPTION (minimizeticks))
182 INC (search_ticks);
183 for (all_literals_in_clause (other, c)) {
184 if (other == uip)
185 continue;
186 KISSAT_assert (VALUE (other) < 0);
187 int tmp = shrink_literal (solver, assigned, level, other);
188 if (tmp < 0) {
189 *failed_ptr = true;
190 break;
191 }
192 if (tmp > 0)
193 open++;
194 }
195 return open;
196}
197
198static inline unsigned shrink_along_reason (kissat *solver,
200 unsigned level, unsigned uip,
201 bool resolve_large_clauses,
202 bool *failed_ptr) {
203 unsigned open = 0;
204 const unsigned uip_idx = IDX (uip);
205 struct assigned *a = assigned + uip_idx;
207 KISSAT_assert (a->level == level);
209 if (a->binary) {
210 const unsigned other = a->reason;
211 open = shrink_along_binary (solver, assigned, level, uip, other);
212 } else {
213 reference ref = a->reason;
214 if (resolve_large_clauses)
215 open = shrink_along_large (solver, assigned, level, uip, ref,
216 failed_ptr);
217 else {
218 LOGREF (ref, "not shrinking %s reason", LOGLIT (uip));
219 *failed_ptr = true;
220 }
221 }
222 return open;
223}
224
225static inline unsigned shrink_block (kissat *solver, unsigned *begin_block,
226 unsigned *end_block, unsigned level,
227 unsigned max_trail) {
229
230 unsigned open = end_block - begin_block;
231
232 LOG ("trying to shrink %u literals on level %u", open, level);
233 LOG ("maximum trail position %u on level %u", max_trail, level);
234
235 assigned *assigned = solver->assigned;
236
237 push_literals_of_block (solver, assigned, begin_block, end_block, level);
238
239 KISSAT_assert (SIZE_STACK (solver->shrinkable) == open);
240
241 const unsigned *const begin_trail = BEGIN_ARRAY (solver->trail);
242
243 const bool resolve_large_clauses = (GET_OPTION (shrink) > 1);
244 unsigned uip = INVALID_LIT;
245 bool failed = false;
246
247 const unsigned *t = begin_trail + max_trail;
248
249 while (!failed) {
250 {
251 do
252 KISSAT_assert (begin_trail <= t), uip = *t--;
253 while (!assigned[IDX (uip)].shrinkable);
254 }
255 if (open == 1)
256 break;
257 open += shrink_along_reason (solver, assigned, level, uip,
258 resolve_large_clauses, &failed);
259 KISSAT_assert (open > 1);
260 open--;
261 }
262
263 unsigned block_shrunken = 0;
264 if (failed)
265 reset_shrinkable (solver);
266 else
267 block_shrunken =
268 shrunken_block (solver, level, begin_block, end_block, uip);
269
270 return block_shrunken;
271}
272
273static unsigned *next_block (kissat *solver, unsigned *begin_lits,
274 unsigned *end_block, unsigned *level_ptr,
275 unsigned *max_trail_ptr) {
276 assigned *assigned = solver->assigned;
277
278 unsigned level = INVALID_LEVEL;
279 unsigned max_trail = 0;
280
281 unsigned *begin_block = end_block;
282
283 while (begin_lits < begin_block) {
284 const unsigned lit = begin_block[-1];
286 const unsigned idx = IDX (lit);
287 struct assigned *a = assigned + idx;
288 unsigned lit_level = a->level;
289 if (level == INVALID_LEVEL) {
290 level = lit_level;
291 LOG ("starting to shrink level %u", level);
292 } else {
293 KISSAT_assert (lit_level >= level);
294 if (lit_level > level)
295 break;
296 }
297 begin_block--;
298 const unsigned trail = a->trail;
299 if (trail > max_trail)
300 max_trail = trail;
301 }
302
303 *level_ptr = level;
304 *max_trail_ptr = max_trail;
305
306 return begin_block;
307}
308
309static unsigned minimize_block (kissat *solver, unsigned *begin_block,
310 unsigned *end_block) {
311 unsigned minimized = 0;
312
313 for (unsigned *p = begin_block; p != end_block; p++) {
314 const unsigned lit = *p;
316 if (!kissat_minimize_literal (solver, lit, true))
317 continue;
318 LOG ("minimize-shrunken literal %s", LOGLIT (lit));
319 *p = INVALID_LIT;
320 minimized++;
321 }
322
323 return minimized;
324}
325
326static inline unsigned *
327minimize_and_shrink_block (kissat *solver, unsigned *begin_lits,
328 unsigned *end_block, unsigned *total_shrunken,
329 unsigned *total_minimized) {
330 KISSAT_assert (EMPTY_STACK (solver->shrinkable));
331
332 unsigned level, max_trail;
333
334 unsigned *begin_block =
335 next_block (solver, begin_lits, end_block, &level, &max_trail);
336
337 unsigned open = end_block - begin_block;
338 KISSAT_assert (open > 0);
339
340 unsigned block_shrunken = 0;
341 unsigned block_minimized = 0;
342
343 if (open < 2)
344 LOG ("only one literal on level %u", level);
345 else {
346 block_shrunken =
347 shrink_block (solver, begin_block, end_block, level, max_trail);
348 if (!block_shrunken)
349 block_minimized = minimize_block (solver, begin_block, end_block);
350 }
351
352 block_shrunken += block_minimized;
353 LOG ("shrunken %u literals on level %u (including %u minimized)",
354 block_shrunken, level, block_minimized);
355
356 *total_minimized += block_minimized;
357 *total_shrunken += block_shrunken;
358
359 return begin_block;
360}
361
363 KISSAT_assert (GET_OPTION (minimize) > 0);
364 KISSAT_assert (GET_OPTION (shrink) > 0);
365 KISSAT_assert (!EMPTY_STACK (solver->clause));
366
367 START (shrink);
368
369 unsigned total_shrunken = 0;
370 unsigned total_minimized = 0;
371
372 unsigned *begin_lits = BEGIN_STACK (solver->clause);
373 unsigned *end_lits = END_STACK (solver->clause);
374
375 unsigned *end_block = END_STACK (solver->clause);
376
377 while (end_block != begin_lits)
378 end_block = minimize_and_shrink_block (
379 solver, begin_lits, end_block, &total_shrunken, &total_minimized);
380 unsigned *q = begin_lits;
381 for (const unsigned *p = q; p != end_lits; p++) {
382 const unsigned lit = *p;
383 if (lit != INVALID_LIT)
384 *q++ = lit;
385 }
386 LOG ("clause shrunken by %u literals (including %u minimized)",
387 total_shrunken, total_minimized);
388 KISSAT_assert (q + total_shrunken == end_lits);
389 SET_END_OF_STACK (solver->clause, q);
390 ADD (literals_shrunken, total_shrunken);
391 ADD (literals_minshrunken, total_minimized);
392
393 LOGTMP ("shrunken learned");
395
396 STOP (shrink);
397}
398
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define BEGIN_ARRAY
Definition array.h:50
#define DECISION_REASON
Definition assign.h:9
#define INVALID_LEVEL
Definition assign.h:12
#define BEGIN_STACK(S)
Definition stack.h:46
#define POP_STACK(S)
Definition stack.h:37
#define SIZE_STACK(S)
Definition stack.h:19
#define EMPTY_STACK(S)
Definition stack.h:18
#define SET_END_OF_STACK(S, P)
Definition stack.h:62
#define PUSH_STACK(S, E)
Definition stack.h:39
#define END_STACK(S)
Definition stack.h:48
#define INVALID_LIT
#define ADD(NAME, DELTA)
#define INC(NAME)
#define LOG(...)
Cube * p
Definition exorList.c:222
#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 LOGREF(...)
Definition logging.h:433
#define LOG2(...)
Definition logging.h:352
#define LOGTMP(...)
Definition logging.h:463
#define LOGBINARY2(...)
Definition logging.h:445
#define LOGREF2(...)
Definition logging.h:436
#define LOGLIT(...)
Definition logging.hpp:99
void kissat_reset_poisoned(kissat *solver)
Definition minimize.c:145
bool kissat_minimize_literal(kissat *solver, unsigned lit, bool lit_in_clause)
Definition minimize.c:138
unsigned short ref
Definition giaNewBdd.h:38
#define GET_OPTION(N)
Definition options.h:295
#define STOP(P)
Definition profile.hpp:158
#define START(P)
Definition profile.hpp:150
ABC_NAMESPACE_HEADER_START typedef unsigned reference
Definition reference.h:9
int lit
Definition satVec.h:130
#define IDX(LIT)
Definition literal.h:28
#define NOT(LIT)
Definition literal.h:33
void kissat_shrink_clause(kissat *solver)
Definition shrink.c:362
bool binary
Definition assign.h:23
bool analyzed
Definition assign.h:22
unsigned trail
Definition assign.h:20
bool removable
Definition assign.h:25
bool poisoned
Definition assign.h:24
unsigned reason
Definition assign.h:28
bool shrinkable
Definition assign.h:26
unsigned level
Definition assign.h:19
#define VALUE(LIT)
Definition value.h:10