1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.sat4j.maxsat;
20
21 import java.math.BigInteger;
22
23 import org.sat4j.core.Vec;
24 import org.sat4j.core.VecInt;
25 import org.sat4j.minisat.core.DataStructureFactory;
26 import org.sat4j.minisat.core.IOrder;
27 import org.sat4j.minisat.core.Solver;
28 import org.sat4j.pb.IPBSolver;
29 import org.sat4j.pb.ObjectiveFunction;
30 import org.sat4j.pb.PBSolverDecorator;
31 import org.sat4j.pb.orders.VarOrderHeapObjective;
32 import org.sat4j.specs.ContradictionException;
33 import org.sat4j.specs.IConstr;
34 import org.sat4j.specs.IOptimizationProblem;
35 import org.sat4j.specs.IVec;
36 import org.sat4j.specs.IVecInt;
37 import org.sat4j.specs.IteratorInt;
38 import org.sat4j.specs.TimeoutException;
39
40
41
42
43
44
45
46
47
48
49 public class WeightedMaxSatDecorator extends PBSolverDecorator implements
50 IOptimizationProblem {
51
52
53
54
55 private static final long serialVersionUID = 1L;
56
57 protected int nborigvars;
58
59 private int nbexpectedclauses;
60
61 private long falsifiedWeight;
62
63 protected int nbnewvar;
64
65 protected int[] prevmodel;
66 protected boolean[] prevboolmodel;
67
68 protected int[] prevfullmodel;
69
70 public WeightedMaxSatDecorator(IPBSolver solver) {
71 super(solver);
72 IOrder<?> order = ((Solver<?, ? extends DataStructureFactory<?>>) solver)
73 .getOrder();
74 if (order instanceof VarOrderHeapObjective) {
75 ((VarOrderHeapObjective) order).setObjectiveFunction(obj);
76 }
77 }
78
79 @Override
80 public int newVar(int howmany) {
81 nborigvars = super.newVar(howmany);
82 return nborigvars;
83 }
84
85 @Override
86 public void setExpectedNumberOfClauses(int nb) {
87 nbexpectedclauses = nb;
88 lits.ensure(nb);
89 falsifiedWeight = 0;
90 super.setExpectedNumberOfClauses(nb);
91 super.newVar(nborigvars + nbexpectedclauses);
92 }
93
94 @Override
95 public int[] model() {
96 return prevmodel;
97 }
98
99 @Override
100 public boolean model(int var) {
101 return prevboolmodel[var - 1];
102 }
103
104 protected int top = Integer.MAX_VALUE;
105
106 public void setTopWeight(int top) {
107 this.top = top;
108 }
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 @Override
124 public IConstr addClause(IVecInt literals) throws ContradictionException {
125 int weight = literals.get(0);
126 literals.delete(0);
127 return addSoftClause(weight, literals);
128 }
129
130
131
132
133
134
135
136
137
138 public IConstr addHardClause(IVecInt literals)
139 throws ContradictionException {
140 return super.addClause(literals);
141 }
142
143
144
145
146
147
148
149
150
151 public IConstr addSoftClause(IVecInt literals)
152 throws ContradictionException {
153 return addSoftClause(1, literals);
154 }
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169 public IConstr addSoftClause(int weight, IVecInt literals)
170 throws ContradictionException {
171 if (weight < top) {
172 BigInteger bigweight = BigInteger.valueOf(weight);
173 if (literals.size() == 2) {
174
175
176
177
178 int lit = -literals.get(1);
179 int index = lits.containsAt(lit);
180 if (index != -1) {
181 coefs.set(index, coefs.get(index).add(bigweight));
182 } else {
183
184 index = lits.containsAt(-lit);
185 if (index != -1) {
186 falsifiedWeight += weight;
187 BigInteger oldw = coefs.get(index);
188 BigInteger diff = oldw.subtract(bigweight);
189 if (diff.signum() > 0) {
190 coefs.set(index, diff);
191 } else if (diff.signum() < 0) {
192 lits.set(index, lit);
193 coefs.set(index, diff.abs());
194
195
196
197 falsifiedWeight += diff.intValue();
198 } else {
199 assert diff.signum() == 0;
200 lits.delete(index);
201 coefs.delete(index);
202 }
203 } else {
204 lits.push(lit);
205 coefs.push(bigweight);
206 }
207 }
208 return null;
209 }
210 coefs.push(bigweight);
211 int newvar = nborigvars + ++nbnewvar;
212 literals.push(newvar);
213 lits.push(newvar);
214 }
215 return super.addClause(literals);
216 }
217
218
219
220
221
222
223
224 public void addLiteralsToMinimize(IVecInt literals) {
225 for (IteratorInt it = literals.iterator(); it.hasNext();) {
226 lits.push(it.next());
227 coefs.push(BigInteger.ONE);
228 }
229 }
230
231
232
233
234
235
236
237
238
239 public void addWeightedLiteralsToMinimize(IVecInt literals,
240 IVec<BigInteger> coefficients) {
241 if (literals.size() != coefs.size())
242 throw new IllegalArgumentException();
243 for (int i = 0; i < literals.size(); i++) {
244 lits.push(literals.get(i));
245 coefs.push(coefficients.get(i));
246 }
247 }
248
249
250
251
252
253
254
255
256
257 public void addWeightedLiteralsToMinimize(IVecInt literals,
258 IVecInt coefficients) {
259 if (literals.size() != coefficients.size())
260 throw new IllegalArgumentException();
261 for (int i = 0; i < literals.size(); i++) {
262 lits.push(literals.get(i));
263 coefs.push(BigInteger.valueOf(coefficients.get(i)));
264 }
265 }
266
267 public boolean admitABetterSolution() throws TimeoutException {
268 boolean result = super.isSatisfiable(true);
269 if (result) {
270 prevboolmodel = new boolean[nVars()];
271 for (int i = 0; i < nVars(); i++) {
272 prevboolmodel[i] = decorated().model(i + 1);
273 }
274 int nbtotalvars = nborigvars + nbnewvar;
275 if (prevfullmodel == null)
276 prevfullmodel = new int[nbtotalvars];
277 for (int i = 1; i <= nbtotalvars; i++) {
278 prevfullmodel[i - 1] = super.model(i) ? i : -i;
279 }
280 prevmodel = new int[nborigvars];
281 for (int i = 0; i < nborigvars; i++) {
282 prevmodel[i] = prevfullmodel[i];
283 }
284 }
285 return result;
286 }
287
288 @Override
289 public void reset() {
290 coefs.clear();
291 lits.clear();
292 nbnewvar = 0;
293 super.reset();
294 }
295
296 public boolean hasNoObjectiveFunction() {
297 return false;
298 }
299
300 public boolean nonOptimalMeansSatisfiable() {
301 return false;
302 }
303
304 private int counter;
305
306 public Number calculateObjective() {
307 counter = 0;
308 for (int q : prevfullmodel) {
309 int index = lits.containsAt(q);
310 if (index != -1) {
311 counter += coefs.get(index).intValue();
312 }
313 }
314 return falsifiedWeight + counter;
315 }
316
317 private final IVecInt lits = new VecInt();
318
319 private final IVec<BigInteger> coefs = new Vec<BigInteger>();
320
321 private final ObjectiveFunction obj = new ObjectiveFunction(lits, coefs);
322
323 public void discard() throws ContradictionException {
324 assert lits.size() == coefs.size();
325 super.addPseudoBoolean(lits, coefs, false, BigInteger
326 .valueOf(counter - 1));
327 }
328
329 }