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
#![deny(missing_docs)]
use rsat::cdcl::{Solver, SolverOptions};
use solhop_types::dimacs::Dimacs;
use solhop_types::{Lit, Solution, Var};
pub fn solve(dimacs: Dimacs) -> (Solution, usize) {
match dimacs {
Dimacs::Cnf { n_vars, clauses } => {
let n_clauses = clauses.len();
let mut sat_solver = Solver::new(SolverOptions::default());
let _vars = (0..n_vars)
.map(|_| sat_solver.new_var())
.collect::<Vec<_>>();
let mut ref_vars = vec![];
let mut cost = clauses.len();
for clause in clauses {
let mut clause = clause;
let ref_var = sat_solver.new_var();
ref_vars.push(ref_var);
clause.push(ref_var.pos_lit());
sat_solver.add_clause(clause);
}
if n_clauses == 0 {
return (sat_solver.solve(vec![]), 0);
}
let totalizer_lits = gen_totalizer(&ref_vars, &mut sat_solver);
let mut last_best = None;
loop {
let sol = sat_solver.solve(vec![]);
match sol {
Solution::Unsat => break,
Solution::Best(_) => break,
Solution::Sat(model) => last_best = Some((model, cost)),
Solution::Unknown => break,
}
if cost == 0 {
break;
}
cost -= 1;
sat_solver.add_clause(vec![!totalizer_lits[cost]]);
}
match last_best {
Some((model, cost)) => (
Solution::Best(model[0..n_vars].iter().copied().collect()),
n_clauses - cost,
),
None => (Solution::Unknown, 0),
}
}
_ => panic!("not implemented for wcnf yet!"),
}
}
fn gen_totalizer(vars: &[Var], solver: &mut Solver) -> Vec<Lit> {
debug_assert!(vars.len() >= 1);
let mut output: Vec<Vec<Lit>> = vars.into_iter().map(|&v| vec![v.pos_lit()]).collect();
loop {
output = totalizer_single_level(output, solver);
if output.len() == 1 {
break output[0].clone();
}
}
}
fn totalizer_single_level(input: Vec<Vec<Lit>>, solver: &mut Solver) -> Vec<Vec<Lit>> {
let mut output = vec![];
let mut input_iter = input.into_iter();
loop {
if let Some(first) = input_iter.next() {
if let Some(second) = input_iter.next() {
let a = first.len();
let b = second.len();
let parent_lits: Vec<_> = (0..a + b).map(|_| solver.new_var().pos_lit()).collect();
for i in 0..a {
solver.add_clause(vec![!first[i], parent_lits[i]]);
}
for j in 0..b {
solver.add_clause(vec![!second[j], parent_lits[j]]);
}
for i in 0..a {
for j in 0..b {
solver.add_clause(vec![!first[i], !second[j], parent_lits[i + j + 1]]);
}
}
for i in 1..parent_lits.len() {
solver.add_clause(vec![!parent_lits[i], parent_lits[i - 1]]);
}
output.push(parent_lits);
} else {
output.push(first);
break;
}
} else {
break;
}
}
output
}