ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
cadical_compact.cpp
Go to the documentation of this file.
1#include "global.h"
2
3#include "internal.hpp"
4
6
7namespace CaDiCaL {
8
9/*------------------------------------------------------------------------*/
10
11// Compacting removes holes generated by inactive variables (fixed,
12// eliminated, substituted or pure) by mapping active variables indices down
13// to a contiguous interval of indices.
14
15/*------------------------------------------------------------------------*/
16
18 if (level)
19 return false;
20 if (!opts.compact)
21 return false;
22 if (stats.conflicts < lim.compact)
23 return false;
24 int inactive = max_var - active ();
25 CADICAL_assert (inactive >= 0);
26 if (!inactive)
27 return false;
28 if (inactive < opts.compactmin)
29 return false;
30 return inactive >= (1e-3 * opts.compactlim) * max_var;
31}
32
33/*------------------------------------------------------------------------*/
34
35struct Mapper {
36
38 int new_max_var; // New 'max_var' after compacting.
39 int *table; // Old variable index to new literal map.
40 int first_fixed; // First fixed variable index.
41 int map_first_fixed; // Mapped literal of first fixed variable.
42 signed char first_fixed_val; // Value of first fixed variable.
43 size_t new_vsize;
44
45 /*----------------------------------------------------------------------*/
46 // We produce a compacting garbage collector like map of old 'src' to
47 // new 'dst' variables. Inactive variables are just skipped except for
48 // fixed ones which will be mapped to the first fixed variable (in the
49 // appropriate phase). This avoids to handle the case 'fixed value'
50 // separately as it is done in Lingeling, where fixed variables are
51 // mapped to the internal variable '1'.
52 //
55 first_fixed_val (0) {
56 table = new int[internal->max_var + 1u];
57 clear_n (table, internal->max_var + 1u);
58
59 CADICAL_assert (!internal->level);
60
61 for (auto src : internal->vars) {
62 const Flags &f = internal->flags (src);
63 if (f.active ())
64 table[src] = ++new_max_var;
65 else if (f.fixed () && !first_fixed)
67 }
68
71 }
72
73 ~Mapper () { delete[] table; }
74
75 /*----------------------------------------------------------------------*/
76 // Map old variable indices. A result of zero means not mapped.
77 //
78 int map_idx (int src) {
79 CADICAL_assert (0 < src);
80 CADICAL_assert (src <= internal->max_var);
81 const int res = table[src];
83 return res;
84 }
85
86 /*----------------------------------------------------------------------*/
87 // The 'map_idx' above is just a look-up into the 'table'. Here we have
88 // to care about signedness of 'src', and in addition that fixed variables
89 // have all to be mapped to the first fixed variable 'first_fixed'.
90 //
91 int map_lit (int src) {
92 int res = map_idx (abs (src));
93 if (!res) {
94 const signed char tmp = internal->val (src);
95 if (tmp) {
97 res = map_first_fixed;
98 if (tmp != first_fixed_val)
99 res = -res;
100 }
101 } else if ((src) < 0)
102 res = -res;
103 CADICAL_assert (abs (res) <= new_max_var);
104 return res;
105 }
106
107 /*----------------------------------------------------------------------*/
108 // Map positive variable indices in vector.
109 //
110 template <class T> void map_vector (vector<T> &v) {
111 for (auto src : internal->vars) {
112 const int dst = map_idx (src);
113 if (!dst)
114 continue;
115 CADICAL_assert (0 < dst);
116 CADICAL_assert (dst <= src);
117 v[dst] = v[src];
118 }
119 v.resize (new_vsize);
120 shrink_vector (v);
121 }
122
123 /*----------------------------------------------------------------------*/
124 // Map positive and negative variable indices in two-sided vector.
125 //
126 template <class T> void map2_vector (vector<T> &v) {
127 for (auto src : internal->vars) {
128 const int dst = map_idx (src);
129 if (!dst)
130 continue;
131 CADICAL_assert (0 < dst);
132 CADICAL_assert (dst <= src);
133 v[2 * dst] = v[2 * src];
134 v[2 * dst + 1] = v[2 * src + 1];
135 }
136 v.resize (2 * new_vsize);
137 shrink_vector (v);
138 }
139
140 /*----------------------------------------------------------------------*/
141 // Map a vector of literals, flush inactive literals, then resize and
142 // shrink it to fit the new size after flushing.
143 //
145 const auto end = v.end ();
146 auto j = v.begin (), i = j;
147 for (; i != end; i++) {
148 const int src = *i;
149 int dst = map_idx (abs (src));
150 CADICAL_assert (abs (dst) <= abs (src));
151 if (!dst)
152 continue;
153 if (src < 0)
154 dst = -dst;
155 *j++ = dst;
156 }
157 v.resize (j - v.begin ());
158 shrink_vector (v);
159 }
160};
161
162/*------------------------------------------------------------------------*/
163
164static signed char *ignore_clang_analyze_memory_leak_warning;
165
167
168 START (compact);
169
171
172 stats.compacts++;
173
177 CADICAL_assert (clause.empty ());
178 CADICAL_assert (levels.empty ());
179 CADICAL_assert (analyzed.empty ());
180 CADICAL_assert (minimized.empty ());
181 CADICAL_assert (control.size () == 1);
182 CADICAL_assert (propagated == trail.size ());
183
185
186 Mapper mapper (this);
187
188 if (mapper.first_fixed)
189 LOG ("found first fixed %d",
190 sign (mapper.first_fixed_val) * mapper.first_fixed);
191 else
192 LOG ("no variable fixed");
193
194 if (!assumptions.empty ()) {
195 CADICAL_assert (!external->assumptions.empty ());
196 LOG ("temporarily reset internal assumptions");
198 }
199
200 const bool is_constraint = !constraint.empty ();
201 if (is_constraint) {
202 CADICAL_assert (!external->constraint.empty ());
203 LOG ("temporarily reset internal constraint");
205 }
206
207 /*======================================================================*/
208 // In this first part we only map stuff without reallocation / shrinking.
209 /*======================================================================*/
210
211 // Flush the external indices. This has to occur before we map 'vals'.
212 // Also fixes external units.
213 //
214 for (auto eidx : external->vars) {
215 int src = external->e2i[eidx];
216 if (!src) {
217 continue;
218 }
219 if (lrat || frat) {
220 CADICAL_assert (eidx > 0);
221 CADICAL_assert (external->ext_units.size () >= (size_t) 2 * eidx + 1);
222 int64_t id1 = external->ext_units[2 * eidx];
223 int64_t id2 = external->ext_units[2 * eidx + 1];
224 CADICAL_assert (!id1 || !id2);
225 if (!id1 && !id2) {
226 int64_t new_id1 = unit_clauses (2 * src);
227 int64_t new_id2 = unit_clauses (2 * src + 1);
228 external->ext_units[2 * eidx] = new_id1;
229 external->ext_units[2 * eidx + 1] = new_id2;
230 }
231 }
232 int dst = mapper.map_lit (src);
233 LOG ("compact %" PRId64
234 " maps external %d to internal %d from internal %d",
235 stats.compacts, eidx, dst, src);
236 external->e2i[eidx] = dst;
237 }
238
239 // Delete garbage units. Needs to occur before resizing unit_clauses
240 //
241 if (lrat || frat) {
242 for (auto src : internal->vars) {
243 const int dst = mapper.map_idx (src);
244 CADICAL_assert (dst <= src);
245 const signed char tmp = internal->val (src);
246 if (!dst && !tmp) {
247 unit_clauses (2 * src) = 0;
248 unit_clauses (2 * src + 1) = 0;
249 continue;
250 }
251 if (!tmp || src == mapper.first_fixed) {
252 CADICAL_assert (0 < dst);
253 if (dst == src)
254 continue;
255 CADICAL_assert (!unit_clauses (2 * dst) && !unit_clauses (2 * dst + 1));
256 unit_clauses (2 * dst) = unit_clauses (2 * src);
257 unit_clauses (2 * dst + 1) = unit_clauses (2 * src + 1);
258 unit_clauses (2 * src) = 0;
259 unit_clauses (2 * src + 1) = 0;
260 continue;
261 }
262 int64_t id = unit_clauses (2 * src);
263 int lit = src;
264 if (!id) {
265 id = unit_clauses (2 * src + 1);
266 lit = -lit;
267 }
268 unit_clauses (2 * src) = 0;
269 unit_clauses (2 * src + 1) = 0;
270 CADICAL_assert (id);
271 }
272 unit_clauses_idx.resize (2 * mapper.new_vsize);
274 }
275 // Map the literals in all clauses.
276 //
277 for (const auto &c : clauses) {
278 CADICAL_assert (!c->garbage);
279 for (auto &src : *c) {
280 CADICAL_assert (!val (src));
281 int dst;
282 dst = mapper.map_lit (src);
283 CADICAL_assert (dst || c->garbage);
284 src = dst;
285 }
286 }
287
288 // Map the blocking literals in all watches.
289 //
290 if (!wtab.empty ())
291 for (auto lit : lits)
292 for (auto &w : watches (lit))
293 w.blit = mapper.map_lit (w.blit);
294
295 // We first flush inactive variables and map the links in the queue. This
296 // has to be done before we map the actual links data structure 'links'.
297 {
298 int prev = 0, mapped_prev = 0, next;
299 for (int idx = queue.first; idx; idx = next) {
300 next = links[idx].next;
301 if (idx == mapper.first_fixed)
302 continue;
303 const int dst = mapper.map_idx (idx);
304 if (!dst)
305 continue;
306 CADICAL_assert (active (idx));
307 if (prev)
308 links[prev].next = dst;
309 else
310 queue.first = dst;
311 links[idx].prev = mapped_prev;
312 mapped_prev = dst;
313 prev = idx;
314 }
315 if (prev)
316 links[prev].next = 0;
317 else
318 queue.first = 0;
319 queue.unassigned = queue.last = mapped_prev;
320 }
321
322 /*======================================================================*/
323 // In the second part we map, flush and shrink arrays.
324 /*======================================================================*/
325
326 CADICAL_assert (trail.size () == num_assigned);
328 propagated = trail.size ();
329 num_assigned = trail.size ();
330 if (mapper.first_fixed) {
331 CADICAL_assert (trail.size () == 1);
332 var (mapper.first_fixed).trail = 0; // before mapping 'vtab'
333 } else
334 CADICAL_assert (trail.empty ());
335
336 if (!probes.empty ())
338
339 if (!sweep_schedule.empty ())
341
342 /*======================================================================*/
343 // In the third part we map stuff and also reallocate memory.
344 /*======================================================================*/
345
346 // Now we continue in reverse order of allocated bytes, e.g., see
347 // 'Internal::enlarge' which reallocates in order of allocated bytes.
348
349 mapper.map_vector (ftab);
350 mapper.map_vector (parents);
351 mapper.map_vector (marks);
352 mapper.map_vector (phases.saved);
353 mapper.map_vector (phases.forced);
354 mapper.map_vector (phases.target);
355 mapper.map_vector (phases.best);
356 mapper.map_vector (phases.prev);
357 mapper.map_vector (phases.min);
358
359 // Special code for 'frozentab'.
360 //
361 for (auto src : vars) {
362 const int dst = abs (mapper.map_lit (src));
363 if (!dst)
364 continue;
365 if (src == dst)
366 continue;
367 CADICAL_assert (dst < src);
368 if ((size_t) src >= frozentab.size ())
369 break;
370 if ((size_t) dst >= frozentab.size ())
371 break;
372 frozentab[dst] += frozentab[src];
373 frozentab[src] = 0;
374 }
375 frozentab.resize (min (frozentab.size (), mapper.new_vsize));
377
378 // Special code for 'relevanttab'.
379 //
380 if (external) {
381 for (auto src : vars) {
382 const int dst = abs (mapper.map_lit (src));
383 if (!dst)
384 continue;
385 if (src == dst)
386 continue;
387 CADICAL_assert (dst < src);
388
389 relevanttab[dst] += relevanttab[src];
390 relevanttab[src] = 0;
391 }
392 relevanttab.resize (mapper.new_vsize);
394 }
395
396 /*----------------------------------------------------------------------*/
397
398 if (!external->assumptions.empty ()) {
399
400 for (const auto &elit : external->assumptions) {
401 CADICAL_assert (elit);
402 CADICAL_assert (elit != INT_MIN);
403 int eidx = abs (elit);
404 CADICAL_assert (eidx <= external->max_var);
405 int ilit = external->e2i[eidx];
406 CADICAL_assert (ilit); // Because we froze all!!!
407 if (elit < 0)
408 ilit = -ilit;
409 assume (ilit);
410 }
411
412 PHASE ("compact", stats.compacts, "reassumed %zd external assumptions",
413 external->assumptions.size ());
414 }
415
416 // Special case for 'val' as for 'val' we trade branch less code for
417 // memory and always allocated an [-maxvar,...,maxvar] array.
418 {
419 signed char *new_vals = new signed char[2 * mapper.new_vsize];
420 ignore_clang_analyze_memory_leak_warning = new_vals;
421 new_vals += mapper.new_vsize;
422 for (auto src : vars)
423 new_vals[-mapper.map_idx (src)] = vals[-src];
424 for (auto src : vars)
425 new_vals[mapper.map_idx (src)] = vals[src];
426 new_vals[0] = 0;
427 vals -= vsize;
428 delete[] vals;
429 vals = new_vals;
430 vsize = mapper.new_vsize;
431 }
432
433 // 'constrain' uses 'val', so this code has to be after remapping that
434 if (is_constraint) {
436 CADICAL_assert (!external->constraint.back ());
437 for (auto elit : external->constraint) {
438 CADICAL_assert (elit != INT_MIN);
439 int eidx = abs (elit);
440 CADICAL_assert (eidx <= external->max_var);
441 int ilit = external->e2i[eidx];
442 CADICAL_assert (!ilit == !elit);
443 if (elit < 0)
444 ilit = -ilit;
445 LOG ("re adding lit external %d internal %d to constraint", elit,
446 ilit);
447 constrain (ilit);
448 }
449 PHASE ("compact", stats.compacts,
450 "added %zd external literals to constraint",
451 external->constraint.size () - 1);
452 }
453
454 mapper.map_vector (i2e);
455 mapper.map2_vector (ptab);
456 mapper.map_vector (btab);
457 mapper.map_vector (gtab);
458 mapper.map_vector (links);
459 mapper.map_vector (vtab);
460 if (!ntab.empty ())
461 mapper.map2_vector (ntab);
462 if (!wtab.empty ())
463 mapper.map2_vector (wtab);
464 if (!otab.empty ())
465 mapper.map2_vector (otab);
466 if (!rtab.empty ())
467 mapper.map2_vector (rtab);
468 if (!big.empty ())
469 mapper.map2_vector (big);
470
471 /*======================================================================*/
472 // In the fourth part we map the binary heap for scores.
473 /*======================================================================*/
474
475 // The simplest way to map a binary heap is to get all elements from the
476 // heap and reinsert them. This could be slightly improved in terms of
477 // speed if we add a 'flush (int * map)' function to 'Heap', but that is
478 // pretty complicated and would require that the 'Heap' knows that mapped
479 // elements with 'zero' destination should be flushed.
480
481 vector<int> saved;
482 CADICAL_assert (saved.empty ());
483 if (!scores.empty ()) {
484 while (!scores.empty ()) {
485 const int src = scores.front ();
486 scores.pop_front ();
487 const int dst = mapper.map_idx (src);
488 if (!dst)
489 continue;
490 if (src == mapper.first_fixed)
491 continue;
492 saved.push_back (dst);
493 }
494 scores.erase ();
495 }
496 mapper.map_vector (stab);
497 if (!saved.empty ()) {
498 for (const auto idx : saved)
499 scores.push_back (idx);
500 scores.shrink ();
501 }
502
503 /*----------------------------------------------------------------------*/
504
505 PHASE ("compact", stats.compacts,
506 "reducing internal variables from %d to %d", max_var,
507 mapper.new_max_var);
508
509 /*----------------------------------------------------------------------*/
510
511 // Need to adjust the target and best assigned counters too.
512
513 size_t new_target_assigned = 0, new_best_assigned = 0;
514
515 for (auto idx : Range (mapper.new_max_var)) {
516 if (phases.target[idx])
517 new_target_assigned++;
518 if (phases.best[idx])
519 new_best_assigned++;
520 }
521
522 LOG ("reset target assigned from %zd to %zd", target_assigned,
523 new_target_assigned);
524 LOG ("reset best assigned from %zd to %zd", best_assigned,
525 new_best_assigned);
526
527 target_assigned = new_target_assigned;
528 best_assigned = new_best_assigned;
530 notified = 0;
531
532 INIT_EMA (averages.current.trail.fast, opts.ematrailfast);
533 INIT_EMA (averages.current.trail.slow, opts.ematrailslow);
534
535 /*----------------------------------------------------------------------*/
536
537 max_var = mapper.new_max_var;
538
539 stats.unused = 0;
540 stats.inactive = stats.now.fixed = mapper.first_fixed ? 1 : 0;
541 stats.now.substituted = stats.now.eliminated = stats.now.pure = 0;
542
544
545 int64_t delta = opts.compactint * (stats.compacts + 1);
546 lim.compact = stats.conflicts + delta;
547
548 PHASE ("compact", stats.compacts,
549 "new compact limit %" PRId64 " after %" PRId64 " conflicts",
550 lim.compact, delta);
551
552 STOP (compact);
553}
554
555} // namespace CaDiCaL
556
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define CADICAL_assert(ignore)
Definition global.h:14
#define LOG(...)
#define INIT_EMA(E, WINDOW)
Definition ema.hpp:61
#define PHASE(...)
Definition message.hpp:52
int sign(int lit)
Definition util.hpp:22
void shrink_vector(std::vector< T > &v)
Definition util.hpp:101
void clear_n(T *base, size_t n)
Definition util.hpp:149
#define STOP(P)
Definition profile.hpp:158
#define START(P)
Definition profile.hpp:150
int lit
Definition satVec.h:130
bool fixed() const
Definition flags.hpp:70
bool active() const
Definition flags.hpp:69
External * external
Definition internal.hpp:312
vector< int > ptab
Definition internal.hpp:238
vector< unsigned > relevanttab
Definition internal.hpp:225
vector< int > analyzed
Definition internal.hpp:267
Var & var(int lit)
Definition internal.hpp:452
vector< unsigned > frozentab
Definition internal.hpp:223
vector< int64_t > gtab
Definition internal.hpp:235
vector< int64_t > unit_clauses_idx
Definition internal.hpp:209
vector< int > constraint
Definition internal.hpp:262
vector< Bins > big
Definition internal.hpp:240
vector< int > trail
Definition internal.hpp:259
const Sange lits
Definition internal.hpp:325
vector< Var > vtab
Definition internal.hpp:231
signed char val(int lit) const
vector< int > i2e
Definition internal.hpp:224
vector< int > sweep_schedule
Definition internal.hpp:274
size_t no_conflict_until
Definition internal.hpp:258
vector< int64_t > ntab
Definition internal.hpp:239
vector< int > assumptions
Definition internal.hpp:261
bool active(int lit)
Definition internal.hpp:360
vector< Occs > rtab
Definition internal.hpp:237
vector< Clause * > clauses
Definition internal.hpp:283
signed char * vals
Definition internal.hpp:221
vector< signed char > marks
Definition internal.hpp:222
vector< int64_t > btab
Definition internal.hpp:234
const Range vars
Definition internal.hpp:324
vector< int > minimized
Definition internal.hpp:270
vector< Level > control
Definition internal.hpp:282
int64_t & unit_clauses(int uidx)
Definition internal.hpp:443
vector< double > stab
Definition internal.hpp:230
vector< int > parents
Definition internal.hpp:232
Internal * internal
Definition internal.hpp:311
ScoreSchedule scores
Definition internal.hpp:229
int active() const
Definition internal.hpp:362
vector< int > probes
Definition internal.hpp:281
Watches & watches(int lit)
Definition internal.hpp:467
vector< Occs > otab
Definition internal.hpp:236
vector< Watches > wtab
Definition internal.hpp:241
vector< int > levels
Definition internal.hpp:266
vector< int > clause
Definition internal.hpp:260
vector< Flags > ftab
Definition internal.hpp:233
void map_flush_and_shrink_lits(vector< int > &v)
void map_vector(vector< T > &v)
int map_idx(int src)
Mapper(Internal *i)
signed char first_fixed_val
void map2_vector(vector< T > &v)
int map_lit(int src)
int trail
Definition var.hpp:20