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 package org.sat4j.maxsat;
31
32 import java.math.BigInteger;
33
34 import org.sat4j.core.ConstrGroup;
35 import org.sat4j.core.Vec;
36 import org.sat4j.core.VecInt;
37 import org.sat4j.pb.IPBSolver;
38 import org.sat4j.pb.ObjectiveFunction;
39 import org.sat4j.pb.PBSolverDecorator;
40 import org.sat4j.specs.ContradictionException;
41 import org.sat4j.specs.IConstr;
42 import org.sat4j.specs.IVec;
43 import org.sat4j.specs.IVecInt;
44 import org.sat4j.specs.IteratorInt;
45
46
47
48
49
50
51
52
53
54
55 public class WeightedMaxSatDecorator extends PBSolverDecorator {
56
57 public static final BigInteger SAT4J_MAX_BIG_INTEGER = new BigInteger(
58 "100000000000000000000000000000000000000000");
59
60 protected int nbnewvar;
61
62 private static final long serialVersionUID = 1L;
63
64 private BigInteger falsifiedWeight = BigInteger.ZERO;
65
66 private boolean maxVarIdFixed = false;
67 private final boolean equivalence;
68
69 private final IVecInt lits = new VecInt();
70
71 private final IVec<BigInteger> coefs = new Vec<BigInteger>();
72
73 private final ObjectiveFunction obj = new ObjectiveFunction(this.lits,
74 this.coefs);
75
76
77 public WeightedMaxSatDecorator(IPBSolver solver) {
78 this(solver, false);
79 }
80
81 public WeightedMaxSatDecorator(IPBSolver solver, boolean equivalence) {
82 super(solver);
83 solver.setObjectiveFunction(this.obj);
84 this.equivalence = equivalence;
85 }
86
87 @Override
88 public int newVar(int howmany) {
89 int res = super.newVar(howmany);
90 this.maxVarIdFixed = true;
91 return res;
92 }
93
94 @Override
95 public void setExpectedNumberOfClauses(int nb) {
96 this.lits.ensure(nb);
97 this.falsifiedWeight = BigInteger.ZERO;
98 super.setExpectedNumberOfClauses(nb);
99 }
100
101 protected BigInteger top = SAT4J_MAX_BIG_INTEGER;
102
103 public void setTopWeight(BigInteger top) {
104 this.top = top;
105 }
106
107 protected void checkMaxVarId() {
108 if (!this.maxVarIdFixed) {
109 throw new IllegalStateException(
110 "Please call newVar(int) before adding constraints!!!");
111 }
112 }
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129 @Override
130 public IConstr addClause(IVecInt literals) throws ContradictionException {
131 return addSoftClause(1, literals);
132 }
133
134
135
136
137
138
139
140
141
142 public IConstr addHardClause(IVecInt literals)
143 throws ContradictionException {
144 return super.addClause(literals);
145 }
146
147
148
149
150
151
152
153
154
155 public IConstr addSoftClause(IVecInt literals)
156 throws ContradictionException {
157 return addSoftClause(1, literals);
158 }
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173 public IConstr addSoftClause(int weight, IVecInt literals)
174 throws ContradictionException {
175 return addSoftClause(BigInteger.valueOf(weight), literals);
176 }
177
178 public IConstr addSoftClause(BigInteger weight, IVecInt literals)
179 throws ContradictionException {
180 checkMaxVarId();
181 if (weight.compareTo(this.top) < 0) {
182
183 if (literals.size() == 1) {
184
185
186
187
188 int lit = -literals.get(0);
189 int index = this.lits.containsAt(lit);
190 if (index == -1) {
191
192 index = this.lits.containsAt(-lit);
193 if (index != -1) {
194 this.falsifiedWeight = this.falsifiedWeight.add(weight);
195 BigInteger oldw = this.coefs.get(index);
196 BigInteger diff = oldw.subtract(weight);
197 if (diff.signum() > 0) {
198 this.coefs.set(index, diff);
199 } else if (diff.signum() < 0) {
200 this.lits.set(index, lit);
201 this.coefs.set(index, diff.abs());
202
203
204
205 this.falsifiedWeight = this.falsifiedWeight
206 .add(diff);
207 } else {
208 assert diff.signum() == 0;
209 this.lits.delete(index);
210 this.coefs.delete(index);
211 }
212 this.obj.setCorrection(this.falsifiedWeight);
213 } else {
214 registerLiteral(lit);
215 this.lits.push(lit);
216 this.coefs.push(weight);
217 }
218 } else {
219 this.coefs.set(index, this.coefs.get(index).add(weight));
220 }
221 return UnitWeightedClause.instance();
222 }
223 this.coefs.push(weight);
224 int newvar = nextFreeVarId(true);
225 literals.push(newvar);
226 this.lits.push(newvar);
227 if (this.equivalence) {
228 ConstrGroup constrs = new ConstrGroup();
229 constrs.add(super.addClause(literals));
230 IVecInt clause = new VecInt(2);
231 clause.push(-newvar);
232 for (int i = 0; i < literals.size() - 1; i++) {
233 clause.push(-literals.get(i));
234 constrs.add(super.addClause(clause));
235 clause.pop();
236 }
237 return constrs;
238 }
239 }
240 return super.addClause(literals);
241 }
242
243
244
245
246
247
248
249
250
251
252
253
254
255 public IConstr addSoftAtLeast(IVecInt literals, int degree)
256 throws ContradictionException {
257 return addSoftAtLeast(BigInteger.ONE, literals, degree);
258 }
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274 public IConstr addSoftAtLeast(int weight, IVecInt literals, int degree)
275 throws ContradictionException {
276 return addSoftAtLeast(BigInteger.valueOf(weight), literals, degree);
277 }
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293 public IConstr addSoftAtLeast(BigInteger weight, IVecInt literals,
294 int degree) throws ContradictionException {
295 checkMaxVarId();
296 if (weight.compareTo(this.top) < 0) {
297 this.coefs.push(weight);
298 int newvar = nextFreeVarId(true);
299 this.lits.push(newvar);
300 IVec<BigInteger> cardcoeffs = new Vec<BigInteger>(
301 literals.size() + 1);
302 cardcoeffs.growTo(literals.size(), BigInteger.ONE);
303 literals.push(newvar);
304 BigInteger bigDegree = BigInteger.valueOf(degree);
305 cardcoeffs.push(bigDegree);
306 return addPseudoBoolean(literals, cardcoeffs, true, bigDegree);
307 } else {
308 return addAtLeast(literals, degree);
309 }
310 }
311
312
313
314
315
316
317
318
319
320
321
322
323
324 public IConstr addSoftAtMost(IVecInt literals, int degree)
325 throws ContradictionException {
326 return addSoftAtMost(BigInteger.ONE, literals, degree);
327 }
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343 public IConstr addSoftAtMost(int weight, IVecInt literals, int degree)
344 throws ContradictionException {
345 return addSoftAtMost(BigInteger.valueOf(weight), literals, degree);
346 }
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362 public IConstr addSoftAtMost(BigInteger weight, IVecInt literals, int degree)
363 throws ContradictionException {
364 checkMaxVarId();
365 if (weight.compareTo(this.top) < 0) {
366 this.coefs.push(weight);
367 int newvar = nextFreeVarId(true);
368 this.lits.push(newvar);
369 IVec<BigInteger> cardcoeffs = new Vec<BigInteger>(
370 literals.size() + 1);
371 cardcoeffs.growTo(literals.size(), BigInteger.ONE);
372 literals.push(newvar);
373 BigInteger bigDegree = BigInteger.valueOf(degree);
374 cardcoeffs.push(bigDegree.negate());
375 return addPseudoBoolean(literals, cardcoeffs, true, bigDegree);
376 } else {
377 return addAtMost(literals, degree);
378 }
379 }
380
381
382
383
384
385
386
387 public void addLiteralsToMinimize(IVecInt literals) {
388 for (IteratorInt it = literals.iterator(); it.hasNext();) {
389 this.lits.push(it.next());
390 this.coefs.push(BigInteger.ONE);
391 }
392 }
393
394
395
396
397
398
399
400
401
402 public void addWeightedLiteralsToMinimize(IVecInt literals,
403 IVec<BigInteger> coefficients) {
404 if (literals.size() != this.coefs.size()) {
405 throw new IllegalArgumentException();
406 }
407 for (int i = 0; i < literals.size(); i++) {
408 this.lits.push(literals.get(i));
409 this.coefs.push(coefficients.get(i));
410 }
411 }
412
413
414
415
416
417
418
419
420
421 public void addWeightedLiteralsToMinimize(IVecInt literals,
422 IVecInt coefficients) {
423 if (literals.size() != coefficients.size()) {
424 throw new IllegalArgumentException();
425 }
426 for (int i = 0; i < literals.size(); i++) {
427 this.lits.push(literals.get(i));
428 this.coefs.push(BigInteger.valueOf(coefficients.get(i)));
429 }
430 }
431
432 @Override
433 public void reset() {
434 this.coefs.clear();
435 this.lits.clear();
436 this.nbnewvar = 0;
437 super.reset();
438 }
439
440
441
442
443
444
445
446
447 public void forceObjectiveValueTo(Number forcedValue)
448 throws ContradictionException {
449 if (this.lits.size() > 0) {
450
451 super.addPseudoBoolean(this.lits, this.coefs, false,
452 (BigInteger) forcedValue);
453 }
454 }
455 }