ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
cadical_lucky.cpp
Go to the documentation of this file.
1#include "global.h"
2
3#include "internal.hpp"
4
6
7namespace CaDiCaL {
8
9// It turns out that even in the competition there are formulas which are
10// easy to satisfy by either setting all variables to the same truth value
11// or by assigning variables to the same value and propagating it. In the
12// latter situation this can be done either in the order of all variables
13// (forward or backward) or in the order of all clauses. These lucky
14// assignments can be tested initially in a kind of pre-solving step.
15
16// This function factors out clean up code common among the 'lucky'
17// functions for backtracking and resetting a potential conflict. One could
18// also use exceptions here, but there are two different reasons for
19// aborting early. The first kind of aborting is due to asynchronous
20// termination and the second kind due to a situation in which it is clear
21// that a particular function will not be successful (for instance a
22// completely negative clause is found). The latter situation returns zero
23// and will just abort the particular lucky function, while the former will
24// abort all (by returning '-1').
25
26int Internal::unlucky (int res) {
27 if (level > 0)
28 backtrack ();
29 if (conflict)
30 conflict = 0;
31 return res;
32}
33
35 LOG ("checking that all clauses contain a negative literal");
37 CADICAL_assert (assumptions.empty ());
38 for (const auto &c : clauses) {
40 return unlucky (-1);
41 if (c->garbage)
42 continue;
43 if (c->redundant)
44 continue;
45 bool satisfied = false, found_negative_literal = false;
46 for (const auto &lit : *c) {
47 const signed char tmp = val (lit);
48 if (tmp > 0) {
49 satisfied = true;
50 break;
51 }
52 if (tmp < 0)
53 continue;
54 if (lit > 0)
55 continue;
56 found_negative_literal = true;
57 break;
58 }
59 if (satisfied || found_negative_literal)
60 continue;
61 LOG (c, "found purely positively");
62 return unlucky (0);
63 }
64 VERBOSE (1, "all clauses contain a negative literal");
65 for (auto idx : vars) {
67 return unlucky (-1);
68 if (val (idx))
69 continue;
71 if (propagate ())
72 continue;
74 LOG ("propagation failed including redundant clauses");
75 return unlucky (0);
76 }
77 stats.lucky.constant.zero++;
78 return 10;
79}
80
82 LOG ("checking that all clauses contain a positive literal");
84 CADICAL_assert (assumptions.empty ());
85 for (const auto &c : clauses) {
87 return unlucky (-1);
88 if (c->garbage)
89 continue;
90 if (c->redundant)
91 continue;
92 bool satisfied = false, found_positive_literal = false;
93 for (const auto &lit : *c) {
94 const signed char tmp = val (lit);
95 if (tmp > 0) {
96 satisfied = true;
97 break;
98 }
99 if (tmp < 0)
100 continue;
101 if (lit < 0)
102 continue;
103 found_positive_literal = true;
104 break;
105 }
106 if (satisfied || found_positive_literal)
107 continue;
108 LOG (c, "found purely negatively");
109 return unlucky (0);
110 }
111 VERBOSE (1, "all clauses contain a positive literal");
112 for (auto idx : vars) {
114 return unlucky (-1);
115 if (val (idx))
116 continue;
118 if (propagate ())
119 continue;
120 CADICAL_assert (level > 0);
121 LOG ("propagation failed including redundant clauses");
122 return unlucky (0);
123 }
124 stats.lucky.constant.one++;
125 return 10;
126}
127
128/*------------------------------------------------------------------------*/
131 bool no_conflict = propagate ();
132 if (no_conflict)
133 return false;
134 if (level > 1) {
135 backtrack (level - 1);
137 no_conflict = propagate ();
138 if (no_conflict)
139 return false;
140 return true;
141 } else {
142 analyze ();
144 no_conflict = propagate ();
145 if (!no_conflict) {
146 analyze ();
147 LOG ("lucky inconsistency backward assigning to true");
148 return true;
149 }
150 }
151 return false;
152}
153
155 LOG ("checking increasing variable index false assignment");
158 CADICAL_assert (assumptions.empty ());
159 for (auto idx : vars) {
160 START:
162 return unlucky (-1);
163 if (val (idx))
164 continue;
165 if (lucky_propagate_discrepency (-idx)) {
166 if (unsat)
167 return 20;
168 else
169 return unlucky (0);
170 } else
171 goto START;
172 }
173 VERBOSE (1, "forward assuming variables false satisfies formula");
175 stats.lucky.forward.zero++;
176 return 10;
177}
178
180 LOG ("checking increasing variable index true assignment");
183 CADICAL_assert (assumptions.empty ());
184 for (auto idx : vars) {
185 START:
187 return unlucky (-1);
188 if (val (idx))
189 continue;
190 if (lucky_propagate_discrepency (idx)) {
191 if (unsat)
192 return 20;
193 else
194 return unlucky (0);
195 } else
196 goto START;
197 }
198 VERBOSE (1, "forward assuming variables true satisfies formula");
200 stats.lucky.forward.one++;
201 return 10;
202}
203
204/*------------------------------------------------------------------------*/
205
207 LOG ("checking decreasing variable index false assignment");
210 CADICAL_assert (assumptions.empty ());
211 for (int idx = max_var; idx > 0; idx--) {
212 START:
214 return unlucky (-1);
215 if (val (idx))
216 continue;
217 if (lucky_propagate_discrepency (-idx)) {
218 if (unsat)
219 return 20;
220 else
221 return unlucky (0);
222 } else
223 goto START;
224 }
225 VERBOSE (1, "backward assuming variables false satisfies formula");
227 stats.lucky.backward.zero++;
228 return 10;
229}
230
232 LOG ("checking decreasing variable index true assignment");
235 CADICAL_assert (assumptions.empty ());
236 for (int idx = max_var; idx > 0; idx--) {
237 START:
239 return unlucky (-1);
240 if (val (idx))
241 continue;
242 if (lucky_propagate_discrepency (idx)) {
243 if (unsat)
244 return 20;
245 else
246 return unlucky (0);
247 } else
248 goto START;
249 }
250 VERBOSE (1, "backward assuming variables true satisfies formula");
252 stats.lucky.backward.one++;
253 return 10;
254}
255
256/*------------------------------------------------------------------------*/
257
258// The following two functions test if the formula is a satisfiable horn
259// formula. Actually the test is slightly more general. It goes over all
260// clauses and assigns the first positive literal to true and propagates.
261// Already satisfied clauses are of course skipped. A reverse function
262// is not implemented yet.
263
265 LOG ("checking that all clauses are positive horn satisfiable");
267 CADICAL_assert (assumptions.empty ());
268 for (const auto &c : clauses) {
270 return unlucky (-1);
271 if (c->garbage)
272 continue;
273 if (c->redundant)
274 continue;
275 int positive_literal = 0;
276 bool satisfied = false;
277 for (const auto &lit : *c) {
278 const signed char tmp = val (lit);
279 if (tmp > 0) {
280 satisfied = true;
281 break;
282 }
283 if (tmp < 0)
284 continue;
285 if (lit < 0)
286 continue;
287 positive_literal = lit;
288 break;
289 }
290 if (satisfied)
291 continue;
292 if (!positive_literal) {
293 LOG (c, "no positive unassigned literal in");
294 return unlucky (0);
295 }
296 CADICAL_assert (positive_literal > 0);
297 LOG (c, "found positive literal %d in", positive_literal);
298 search_assume_decision (positive_literal);
299 if (propagate ())
300 continue;
301 LOG ("propagation of positive literal %d leads to conflict",
302 positive_literal);
303 return unlucky (0);
304 }
305 for (auto idx : vars) {
307 return unlucky (-1);
308 if (val (idx))
309 continue;
311 if (propagate ())
312 continue;
313 LOG ("propagation of remaining literal %d leads to conflict", -idx);
314 return unlucky (0);
315 }
316 VERBOSE (1, "clauses are positive horn satisfied");
319 stats.lucky.horn.positive++;
320 return 10;
321}
322
324 LOG ("checking that all clauses are negative horn satisfiable");
326 CADICAL_assert (assumptions.empty ());
327 for (const auto &c : clauses) {
329 return unlucky (-1);
330 if (c->garbage)
331 continue;
332 if (c->redundant)
333 continue;
334 int negative_literal = 0;
335 bool satisfied = false;
336 for (const auto &lit : *c) {
337 const signed char tmp = val (lit);
338 if (tmp > 0) {
339 satisfied = true;
340 break;
341 }
342 if (tmp < 0)
343 continue;
344 if (lit > 0)
345 continue;
346 negative_literal = lit;
347 break;
348 }
349 if (satisfied)
350 continue;
351 if (!negative_literal) {
352 if (level > 0)
353 backtrack ();
354 LOG (c, "no negative unassigned literal in");
355 return unlucky (0);
356 }
357 CADICAL_assert (negative_literal < 0);
358 LOG (c, "found negative literal %d in", negative_literal);
359 search_assume_decision (negative_literal);
360 if (propagate ())
361 continue;
362 LOG ("propagation of negative literal %d leads to conflict",
363 negative_literal);
364 return unlucky (0);
365 }
366 for (auto idx : vars) {
368 return unlucky (-1);
369 if (val (idx))
370 continue;
372 if (propagate ())
373 continue;
374 LOG ("propagation of remaining literal %d leads to conflict", idx);
375 return unlucky (0);
376 }
377 VERBOSE (1, "clauses are negative horn satisfied");
380 stats.lucky.horn.negative++;
381 return 10;
382}
383
384/*------------------------------------------------------------------------*/
385
389 if (!opts.lucky)
390 return 0;
391
392 // TODO: Some of the lucky assignments can also be found if there are
393 // assumptions, but this is not completely implemented nor tested yet.
394 // Nothing done for constraint either.
395 // External propagator assumes a CDCL loop, so lucky is not tried here.
396 if (!assumptions.empty () || !constraint.empty () || external_prop)
397 return 0;
398
399 START (search);
400 START (lucky);
403 stats.lucky.tried++;
404 const int64_t active_before = stats.active;
405 int res = trivially_false_satisfiable ();
406 if (!res)
408 if (!res)
410 if (!res)
412 if (!res)
414 if (!res)
416 if (!res)
418 if (!res)
420 if (res < 0)
422 if (res == 10)
423 stats.lucky.succeeded++;
424 report ('l', !res);
426
427 const int64_t units = active_before - stats.active;
428
429 if (!res && units)
430 LOG ("lucky %zd units", units);
432 STOP (lucky);
433 STOP (search);
434
435 return res;
436}
437
438} // namespace CaDiCaL
439
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define CADICAL_assert(ignore)
Definition global.h:14
#define LOG(...)
#define VERBOSE(...)
Definition message.hpp:58
#define STOP(P)
Definition profile.hpp:158
#define START(P)
Definition profile.hpp:150
int lit
Definition satVec.h:130
bool searching_lucky_phases
Definition internal.hpp:189
vector< int > constraint
Definition internal.hpp:262
void report(char type, int verbose_level=0)
bool terminated_asynchronously(int factor=1)
void search_assume_decision(int decision)
signed char val(int lit) const
bool lucky_propagate_discrepency(int)
vector< int > assumptions
Definition internal.hpp:261
void backtrack(int target_level=0)
int unlucky(int res)
vector< Clause * > clauses
Definition internal.hpp:283
const Range vars
Definition internal.hpp:324
void require_mode(Mode m) const
Definition internal.hpp:173
int trivially_false_satisfiable()
volatile bool termination_forced
Definition internal.hpp:320