ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
cadical_instantiate.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// This provides an implementation of variable instantiation, a technique
12// for removing literals with few occurrence (see also 'instantiate.hpp').
13
14/*------------------------------------------------------------------------*/
15
16// Triggered at the end of a variable elimination round ('elim_round').
17
19 Instantiator &instantiator) {
21 for (auto idx : vars) {
22 if (frozen (idx))
23 continue;
24 if (!active (idx))
25 continue;
26 if (flags (idx).elim)
27 continue; // BVE attempt pending
28 for (int sign = -1; sign <= 1; sign += 2) {
29 const int lit = sign * idx;
30 if (noccs (lit) > opts.instantiateocclim)
31 continue;
32 Occs &os = occs (lit);
33 for (const auto &c : os) {
34 if (c->garbage)
35 continue;
36 if (opts.instantiateonce && c->instantiated)
37 continue;
38 if (c->size < opts.instantiateclslim)
39 continue;
40 bool satisfied = false;
41 int unassigned = 0;
42 for (const auto &other : *c) {
43 const signed char tmp = val (other);
44 if (tmp > 0)
45 satisfied = true;
46 if (!tmp)
47 unassigned++;
48 }
49 if (satisfied)
50 continue;
51 if (unassigned < 3)
52 continue; // avoid learning units
53 size_t negoccs = occs (-lit).size ();
54 LOG (c,
55 "instantiation candidate literal %d "
56 "with %zu negative occurrences in",
57 lit, negoccs);
58 instantiator.candidate (lit, c, c->size, negoccs);
59 }
60 }
61 }
62}
63
64/*------------------------------------------------------------------------*/
65
66// Specialized propagation and assignment routines for instantiation.
67
68inline void Internal::inst_assign (int lit) {
69 LOG ("instantiate assign %d", lit);
73 set_val (lit, 1);
74 trail.push_back (lit);
75}
76
77// Conflict analysis is only needed to do valid resolution proofs.
78// We remember propagated clauses in order of assignment (in inst_chain)
79// which allows us to do a variant of conflict analysis if the instantiation
80// attempt succeeds.
81//
82bool Internal::inst_propagate () { // Adapted from 'propagate'.
84 int64_t before = propagated;
85 bool ok = true;
86 while (ok && propagated != trail.size ()) {
87 const int lit = -trail[propagated++];
88 LOG ("instantiate propagating %d", -lit);
89 Watches &ws = watches (lit);
90 const const_watch_iterator eow = ws.end ();
91 const_watch_iterator i = ws.begin ();
92 watch_iterator j = ws.begin ();
93 while (i != eow) {
94 const Watch w = *j++ = *i++;
95 const signed char b = val (w.blit);
96 if (b > 0)
97 continue;
98 if (w.binary ()) {
99 if (b < 0) {
100 ok = false;
101 LOG (w.clause, "conflict");
102 if (lrat) {
103 inst_chain.push_back (w.clause);
104 }
105 break;
106 } else {
107 if (lrat) {
108 inst_chain.push_back (w.clause);
109 }
110 inst_assign (w.blit);
111 }
112 } else {
114 const int other = lits[0] ^ lits[1] ^ lit;
115 lits[0] = other, lits[1] = lit;
116 const signed char u = val (other);
117 if (u > 0)
118 j[-1].blit = other;
119 else {
120 const int size = w.clause->size;
121 const const_literal_iterator end = lits + size;
122 const literal_iterator middle = lits + w.clause->pos;
123 literal_iterator k = middle;
124 signed char v = -1;
125 int r = 0;
126 while (k != end && (v = val (r = *k)) < 0)
127 k++;
128 if (v < 0) {
129 k = lits + 2;
130 CADICAL_assert (w.clause->pos <= size);
131 while (k != middle && (v = val (r = *k)) < 0)
132 k++;
133 }
134 w.clause->pos = k - lits;
135 CADICAL_assert (lits + 2 <= k), CADICAL_assert (k <= w.clause->end ());
136 if (v > 0) {
137 j[-1].blit = r;
138 } else if (!v) {
139 LOG (w.clause, "unwatch %d in", r);
140 lits[1] = r;
141 *k = lit;
142 watch_literal (r, lit, w.clause);
143 j--;
144 } else if (!u) {
145 CADICAL_assert (v < 0);
146 if (lrat) {
147 inst_chain.push_back (w.clause);
148 }
149 inst_assign (other);
150 } else {
151 CADICAL_assert (u < 0);
152 CADICAL_assert (v < 0);
153 if (lrat) {
154 inst_chain.push_back (w.clause);
155 }
156 LOG (w.clause, "conflict");
157 ok = false;
158 break;
159 }
160 }
161 }
162 }
163 if (j != i) {
164 while (i != eow)
165 *j++ = *i++;
166 ws.resize (j - ws.begin ());
167 }
168 }
169 int64_t delta = propagated - before;
170 stats.propagations.instantiate += delta;
171 STOP (propagate);
172 return ok;
173}
174
175/*------------------------------------------------------------------------*/
176
177// This is the instantiation attempt.
178
180 stats.instried++;
181 if (c->garbage)
182 return false;
184 bool found = false, satisfied = false, inactive = false;
185 int unassigned = 0;
186 for (const auto &other : *c) {
187 if (other == lit)
188 found = true;
189 const signed char tmp = val (other);
190 if (tmp > 0) {
191 satisfied = true;
192 break;
193 }
194 if (!tmp && !active (other)) {
195 inactive = true;
196 break;
197 }
198 if (!tmp)
199 unassigned++;
200 }
201 if (!found)
202 return false;
203 if (inactive)
204 return false;
205 if (satisfied)
206 return false;
207 if (unassigned < 3)
208 return false;
209 size_t before = trail.size ();
210 CADICAL_assert (propagated == before);
212 CADICAL_assert (inst_chain.empty ());
213 LOG (c, "trying to instantiate %d in", lit);
215 c->instantiated = true;
216 CADICAL_assert (lrat_chain.empty ());
217 level++;
218 inst_assign (lit); // Assume 'lit' to true.
219 for (const auto &other : *c) {
220 if (other == lit)
221 continue;
222 const signed char tmp = val (other);
223 if (tmp) {
224 CADICAL_assert (tmp < 0);
225 continue;
226 }
227 inst_assign (-other); // Assume other to false.
228 }
229 bool ok = inst_propagate (); // Propagate.
230 CADICAL_assert (lrat_chain.empty ()); // chain will be built here
231 if (ok) {
232 inst_chain.clear ();
233 } else if (lrat) { // analyze conflict for lrat
234 CADICAL_assert (inst_chain.size ());
235 Clause *reason = inst_chain.back ();
236 inst_chain.pop_back ();
237 lrat_chain.push_back (reason->id);
238 for (const auto &other : *reason) {
239 Flags &f = flags (other);
240 CADICAL_assert (!f.seen);
241 f.seen = true;
242 analyzed.push_back (other);
243 }
244 }
245 while (trail.size () > before) { // Backtrack.
246 const int other = trail.back ();
247 LOG ("instantiate unassign %d", other);
248 trail.pop_back ();
249 CADICAL_assert (val (other) > 0);
250 num_assigned--;
251 set_val (other, 0);
252 // this is a variant of conflict analysis which is only needed for lrat
253 if (!ok && inst_chain.size () && lrat) {
254 Flags &f = flags (other);
255 if (f.seen) {
256 Clause *reason = inst_chain.back ();
257 lrat_chain.push_back (reason->id);
258 for (const auto &other : *reason) {
259 Flags &f = flags (other);
260 if (f.seen)
261 continue;
262 f.seen = true;
263 analyzed.push_back (other);
264 }
265 f.seen = false;
266 }
267 inst_chain.pop_back ();
268 }
269 }
270 CADICAL_assert (inst_chain.empty ());
271 // post processing step for lrat
272 if (!ok && lrat) {
273 if (flags (lit).seen)
274 lrat_chain.push_back (c->id);
275 for (const auto &other : *c) {
276 Flags &f = flags (other);
277 f.seen = false;
278 }
279 for (int other : analyzed) {
280 Flags &f = flags (other);
281 if (!f.seen) {
282 f.seen = true;
283 continue;
284 }
285 int64_t id = unit_id (-other);
286 lrat_chain.push_back (id);
287 }
289 reverse (lrat_chain.begin (), lrat_chain.end ());
290 }
291 CADICAL_assert (analyzed.empty ());
292 propagated = before;
293 CADICAL_assert (level == 1);
294 level = 0;
295 if (ok) {
296 CADICAL_assert (lrat_chain.empty ());
297 LOG ("instantiation failed");
298 return false;
299 }
300 unwatch_clause (c);
301 LOG (lrat_chain, "instantiate proof chain");
303 watch_clause (c);
304 lrat_chain.clear ();
305 CADICAL_assert (c->size > 1);
306 LOG ("instantiation succeeded");
307 stats.instantiated++;
308 return true;
309}
310
311/*------------------------------------------------------------------------*/
312
313// Try to instantiate all candidates collected before through the
314// 'collect_instantiation_candidates' routine.
315
317 CADICAL_assert (opts.instantiate);
319 stats.instrounds++;
320#ifndef CADICAL_QUIET
321 const int64_t candidates = instantiator.candidates.size ();
322 int64_t tried = 0;
323#endif
324 int64_t instantiated = 0;
325 init_watches ();
327 if (propagated < trail.size ()) {
328 if (!propagate ()) {
329 LOG ("propagation after connecting watches failed");
332 }
333 }
334 PHASE ("instantiate", stats.instrounds,
335 "attempting to instantiate %" PRId64
336 " candidate literal clause pairs",
337 candidates);
338 while (!unsat && !terminated_asynchronously () &&
339 !instantiator.candidates.empty ()) {
340 Instantiator::Candidate cand = instantiator.candidates.back ();
341 instantiator.candidates.pop_back ();
342#ifndef CADICAL_QUIET
343 tried++;
344#endif
345 if (!active (cand.lit))
346 continue;
347 LOG (cand.clause,
348 "trying to instantiate %d with "
349 "%zd negative occurrences in",
350 cand.lit, cand.negoccs);
351 if (!instantiate_candidate (cand.lit, cand.clause))
352 continue;
353 instantiated++;
354 VERBOSE (2,
355 "instantiation %" PRId64 " (%.1f%%) succeeded "
356 "(%.1f%%) with %zd negative occurrences in size %d clause",
357 tried, percent (tried, candidates),
358 percent (instantiated, tried), cand.negoccs, cand.size);
359 }
360 PHASE ("instantiate", stats.instrounds,
361 "instantiated %" PRId64 " candidate successfully "
362 "out of %" PRId64 " tried %.1f%%",
363 instantiated, tried, percent (instantiated, tried));
364 report ('I', !instantiated);
365 reset_watches ();
367}
368
369} // namespace CaDiCaL
370
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define CADICAL_assert(ignore)
Definition global.h:14
#define LOG(...)
void candidate(int l, Clause *c, int s, size_t n)
#define PHASE(...)
Definition message.hpp:52
#define VERBOSE(...)
Definition message.hpp:58
int sign(int lit)
Definition util.hpp:22
Watches::const_iterator const_watch_iterator
Definition watch.hpp:48
vector< Clause * > Occs
Definition occs.hpp:18
int * literal_iterator
Definition clause.hpp:17
const char * flags()
const int * const_literal_iterator
Definition clause.hpp:18
vector< Watch > Watches
Definition watch.hpp:45
double percent(double a, double b)
Definition util.hpp:21
Watches::iterator watch_iterator
Definition watch.hpp:47
#define STOP(P)
Definition profile.hpp:158
#define START(P)
Definition profile.hpp:150
int lit
Definition satVec.h:130
literal_iterator begin()
Definition clause.hpp:131
bool instantiated
Definition clause.hpp:51
void watch_literal(int lit, int blit, Clause *c)
Definition internal.hpp:623
vector< int > analyzed
Definition internal.hpp:267
void unwatch_clause(Clause *c)
Definition internal.hpp:640
vector< int64_t > lrat_chain
Definition internal.hpp:210
void report(char type, int verbose_level=0)
Flags & flags(int lit)
Definition internal.hpp:454
vector< int > trail
Definition internal.hpp:259
bool terminated_asynchronously(int factor=1)
const Sange lits
Definition internal.hpp:325
void watch_clause(Clause *c)
Definition internal.hpp:633
bool frozen(int lit)
void elim(bool update_limits=true)
signed char val(int lit) const
vector< Clause * > inst_chain
Definition internal.hpp:214
int64_t unit_id(int lit) const
Definition internal.hpp:434
void collect_instantiation_candidates(Instantiator &)
void set_val(int lit, signed char val)
bool active(int lit)
Definition internal.hpp:360
int64_t & noccs(int lit)
Definition internal.hpp:466
void strengthen_clause(Clause *, int)
const Range vars
Definition internal.hpp:324
bool instantiate_candidate(int lit, Clause *)
Occs & occs(int lit)
Definition internal.hpp:465
bool occurring() const
Definition internal.hpp:461
void instantiate(Instantiator &)
void connect_watches(bool irredundant_only=false)
bool binary() const
Definition watch.hpp:42
Clause * clause
Definition watch.hpp:35
unsigned size
Definition vector.h:35
vector watches
Definition watch.h:49