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