-
Notifications
You must be signed in to change notification settings - Fork 0
/
dpll.h
140 lines (122 loc) · 3.36 KB
/
dpll.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#ifndef PAR_DPLL_DPLL_H
#define PAR_DPLL_DPLL_H
#include <unordered_set>
#include <iostream>
#if USE_CILK
#include <cilk/cilk.h>
#endif
#include "utils.h"
#include "formula.h"
#include "system.h"
using namespace std;
#if USE_CILK
bool exit_all;
#endif
enum StepResult {
Sat, Unsat, Continue
};
bool branch_out(Formula& formula, int someLiteral, bool copy);
StepResult dpll_step(Formula& formula) {
if (formula.is_consistent()) {
#if DEBUG_MODE
cout << "sat by all pure literals!" << endl;
#endif
return Sat;
}
if (!formula.emptyClauses.empty()) {
#if DEBUG_MODE
cout << "unsat by empty clause(s)!" << endl;
#endif
return Unsat;
}
formula.unitClauses.iterate([&formula](int unitClause) {
auto& clauseLiterals = formula.literalsIn[unitClause];
if (clauseLiterals.empty()) { // possibly empty due to unit propagation
return;
}
auto literal = clauseLiterals.first();
#if DEBUG_MODE
cout << "unit propagate " << formula.cnf_literal(literal) << endl;
#endif
formula.unit_propagation(literal);
});
formula.pureLiterals.iterate([&formula](int pureLiteral) {
#if DEBUG_MODE
cout << "assign pure literal " << formula.cnf_literal(pureLiteral) << endl;
#endif
formula.pure_literal_assign(pureLiteral);
});
return Continue;
}
bool dpll(Formula& formula) {
#if USE_CILK
if (exit_all) { // global parallel control
return false;
}
#endif
#if DEBUG_MODE
cout << "start of dpll" << endl;
print_cnf(*formula.produce());
#endif
auto stepResult = dpll_step(formula);
#if DEBUG_MODE
cout << "after dpll step. result: " << stepResult << endl;
print_cnf(*formula.produce());
#endif
if (stepResult != Continue) {
auto sat = stepResult == Sat;
#if USE_CILK
if (sat) { // global parallel control
exit_all = true;
}
#endif
return sat;
}
auto& activeLiterals = formula.activeLiterals;
if (activeLiterals.empty()) {
#if DEBUG_MODE
cout << "no more active literals. quit!" << endl;
#endif
auto sat = formula.emptyClauses.empty();
#if USE_CILK
if (sat) { // global parallel control
exit_all = true;
}
#endif
return sat;
}
auto someLiteral = activeLiterals.first();
#if DEBUG_MODE
cout << "adding " << someLiteral << " (and negation) as unit clause" << endl;
#endif
#if USE_CILK
#if USE_CUTOFF
if (formula.activeLiterals.size() <= CUTOFF) {
return branch_out(formula, someLiteral, true) || branch_out(formula, formula.neg_literal(someLiteral), false);
} else {
#endif
auto formula2 = formula;
auto left = cilk_spawn
branch_out(formula2, someLiteral, false);
auto right = branch_out(formula, formula.neg_literal(someLiteral), false);
cilk_sync;
return left || right;
#if USE_CUTOFF
}
#endif
#else
// first branch copies formula
return branch_out(formula, someLiteral, true) || branch_out(formula, formula.neg_literal(someLiteral), false);
#endif
}
bool branch_out(Formula& formula, int someLiteral, bool copy) {
if (copy) {
auto formula2 = formula;
formula2.add_unit_clause(someLiteral);
return dpll(formula2);
} else {
formula.add_unit_clause(someLiteral);
return dpll(formula);
}
}
#endif //PAR_DPLL_DPLL_H