|
|
@ -126,3 +126,48 @@ fn test_is_clause_unit() {
|
|
126
|
126
|
assert!(!is_clause_unit(vars, vec!(1, 2, 3)));
|
|
127
|
127
|
assert!(!is_clause_unit(vars, vec!(1, 2)));
|
|
128
|
128
|
}
|
|
|
129
|
|
|
|
130
|
fn dpll(clauses: Vec<Clause>) -> Option<BoundVars> {
|
|
|
131
|
fn dpll_inner(stack: &mut Vec<(Var, BoundVars)>, vars: &mut BoundVars, clauses: Vec<Clause>) -> Option<BoundVars> {
|
|
|
132
|
if clauses.iter().all(|c| is_clause_satisfied(&vars, c.clone())) { // all clauses satisfied, success
|
|
|
133
|
Some(vars.clone())
|
|
|
134
|
} else if clauses.iter().any(|c| is_clause_conflict(&vars, c.clone())) { // a conflict exists, backtrack
|
|
|
135
|
match stack.pop() {
|
|
|
136
|
None => None, // nothing to backtrack, no solution found
|
|
|
137
|
Some((v, b)) => {
|
|
|
138
|
let bv = &mut b.clone();
|
|
|
139
|
bv.insert(v);
|
|
|
140
|
dpll_inner(stack, bv, clauses)
|
|
|
141
|
}
|
|
|
142
|
}
|
|
|
143
|
} else if clauses.iter().any(|c| is_clause_unit(&vars, c.clone())) { // a unit clause exists, propagate
|
|
|
144
|
let cs = clauses.clone();
|
|
|
145
|
let clause = cs.iter().find(|&c| is_clause_unit(&vars, c.clone())).unwrap();
|
|
|
146
|
let unknown = *clause.iter().find(|&v| is_unknown(&vars, *v)).unwrap();
|
|
|
147
|
vars.insert(unknown);
|
|
|
148
|
dpll_inner(stack, vars, clauses)
|
|
|
149
|
} else { // none of the above, decide (guess) an unknown variable
|
|
|
150
|
let mut unknown: Var = 0;
|
|
|
151
|
for c in clauses.clone() {
|
|
|
152
|
for v in c {
|
|
|
153
|
if is_unknown(vars, v) {
|
|
|
154
|
unknown = v;
|
|
|
155
|
break;
|
|
|
156
|
}
|
|
|
157
|
}
|
|
|
158
|
}
|
|
|
159
|
assert!(unknown != 0);
|
|
|
160
|
stack.push((unknown, vars.clone()));
|
|
|
161
|
vars.insert(-unknown);
|
|
|
162
|
dpll_inner(stack, vars, clauses)
|
|
|
163
|
}
|
|
|
164
|
}
|
|
|
165
|
|
|
|
166
|
dpll_inner(&mut Vec::new(), &mut empty_vars(), clauses)
|
|
|
167
|
}
|
|
|
168
|
|
|
|
169
|
#[test]
|
|
|
170
|
fn test_dpll_trivial() {
|
|
|
171
|
let clauses = vec!(vec!(1, 2), vec!(2));
|
|
|
172
|
assert!(dpll(clauses).is_some());
|
|
|
173
|
}
|