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 package org.sat4j.minisat.constraints.pb;
27
28 import java.io.Serializable;
29 import java.math.BigInteger;
30 import java.util.Random;
31
32 import org.sat4j.core.Vec;
33 import org.sat4j.core.VecInt;
34 import org.sat4j.minisat.constraints.cnf.Lits;
35 import org.sat4j.minisat.core.ILits;
36 import org.sat4j.minisat.core.Undoable;
37 import org.sat4j.minisat.core.UnitPropagationListener;
38 import org.sat4j.specs.ContradictionException;
39 import org.sat4j.specs.IVec;
40 import org.sat4j.specs.IVecInt;
41
42 public abstract class WatchPb implements PBConstr, Undoable, Serializable {
43
44
45
46
47 public static final boolean ATMOST = false;
48
49
50
51
52 public static final boolean ATLEAST = true;
53
54
55
56
57 private static final Random rand = new Random(91648253);
58
59
60
61
62 protected double activity;
63
64
65
66
67 protected BigInteger[] coefs;
68
69
70
71
72 protected BigInteger degree;
73
74
75
76
77 protected int[] lits;
78
79
80
81
82 protected boolean learnt = false;
83
84
85
86
87 protected boolean locked;
88
89
90
91
92 protected BigInteger watchCumul = BigInteger.ZERO;
93
94
95
96
97 protected ILits voc;
98
99
100
101
102 WatchPb() {
103 }
104
105 WatchPb(IDataStructurePB mpb) {
106 int size = mpb.size();
107 lits = new int[size];
108 this.coefs = new BigInteger[size];
109 mpb.buildConstraintFromMapPb(lits, coefs);
110
111 this.degree = mpb.getDegree();
112
113
114 sort();
115 }
116
117 WatchPb(int[] lits, BigInteger[] coefs, BigInteger degree) {
118 this.lits = lits;
119 this.coefs = coefs;
120 this.degree = degree;
121
122 sort();
123 }
124
125
126
127
128
129
130
131 public boolean isAssertive(int dl) {
132 BigInteger slack = BigInteger.ZERO;
133 for (int i = 0; i < lits.length; i++) {
134 if ((coefs[i].signum() > 0)
135 && ((!voc.isFalsified(lits[i]) || voc.getLevel(lits[i]) >= dl)))
136 slack = slack.add(coefs[i]);
137 }
138 slack = slack.subtract(degree);
139 if (slack.signum() < 0)
140 return false;
141 for (int i = 0; i < lits.length; i++) {
142 if ((coefs[i].signum() > 0)
143 && (voc.isUnassigned(lits[i]) || voc.getLevel(lits[i]) >= dl)
144 && (slack.compareTo(coefs[i]) < 0)) {
145 return true;
146 }
147 }
148 return false;
149 }
150
151
152
153
154
155
156
157
158
159
160 public void calcReason(int p, IVecInt outReason) {
161 for (int q : lits) {
162 if (voc.isFalsified(q)) {
163 outReason.push(q ^ 1);
164 }
165 }
166 }
167
168 abstract protected void computeWatches() throws ContradictionException;
169
170 abstract protected void computePropagation(UnitPropagationListener s)
171 throws ContradictionException;
172
173
174
175
176
177
178
179
180 public int get(int i) {
181 return lits[i];
182 }
183
184
185
186
187
188
189
190
191 public BigInteger getCoef(int i) {
192 return coefs[i];
193 }
194
195
196
197
198
199
200
201 public double getActivity() {
202 return activity;
203 }
204
205 public static IDataStructurePB niceParameters(IVecInt ps,
206 IVec<BigInteger> bigCoefs, boolean moreThan, BigInteger bigDeg,
207 ILits voc) throws ContradictionException {
208
209 if (ps.size() == 0) {
210 throw new ContradictionException("Creating Empty clause ?");
211 } else if (ps.size() != bigCoefs.size()) {
212 throw new IllegalArgumentException(
213 "Contradiction dans la taille des tableaux ps=" + ps.size()
214 + " coefs=" + bigCoefs.size() + ".");
215 }
216 return niceCheckedParameters(ps, bigCoefs, moreThan, bigDeg, voc);
217 }
218
219 public static IDataStructurePB niceCheckedParameters(IVecInt ps,
220 IVec<BigInteger> bigCoefs, boolean moreThan, BigInteger bigDeg,
221 ILits voc) {
222 assert ps.size() != 0 && ps.size() == bigCoefs.size();
223 int[] lits = new int[ps.size()];
224 ps.copyTo(lits);
225 BigInteger[] bc = new BigInteger[bigCoefs.size()];
226 bigCoefs.copyTo(bc);
227 BigInteger bigDegree = bigDeg;
228 if (!moreThan) {
229 for (int i = 0; i < lits.length; i++) {
230 bc[i] = bc[i].negate();
231 }
232 bigDegree = bigDegree.negate();
233 }
234
235 for (int i = 0; i < bc.length; i++)
236 if (bc[i].signum() < 0) {
237 lits[i] = lits[i] ^ 1;
238 bc[i] = bc[i].negate();
239 bigDegree = bigDegree.add(bc[i]);
240 }
241
242 IDataStructurePB mpb = new MapPb();
243 if (bigDegree.signum() > 0)
244 bigDegree = mpb.cuttingPlane(lits, bc, bigDegree);
245 if (bigDegree.signum() > 0)
246 bigDegree = mpb.saturation();
247 if (bigDegree.signum() <= 0)
248 return null;
249 return mpb;
250 }
251
252
253
254
255
256
257 public void incActivity(double claInc) {
258 activity += claInc;
259 }
260
261
262
263
264
265
266
267 public BigInteger slackConstraint() {
268 return recalcLeftSide().subtract(this.degree);
269 }
270
271
272
273
274
275
276
277
278
279
280
281 public BigInteger slackConstraint(BigInteger[] coefs, BigInteger degree) {
282 return recalcLeftSide(coefs).subtract(degree);
283 }
284
285
286
287
288
289
290
291
292
293 public BigInteger recalcLeftSide(BigInteger[] coefs) {
294 BigInteger poss = BigInteger.ZERO;
295
296 for (int i = 0; i < lits.length; i++)
297 if (!voc.isFalsified(lits[i])) {
298 assert coefs[i].signum() >= 0;
299 poss = poss.add(coefs[i]);
300 }
301 return poss;
302 }
303
304
305
306
307
308
309
310 public BigInteger recalcLeftSide() {
311 return recalcLeftSide(this.coefs);
312 }
313
314
315
316
317
318
319 protected boolean isSatisfiable() {
320 return recalcLeftSide().compareTo(degree) >= 0;
321 }
322
323
324
325
326
327
328
329 public boolean learnt() {
330 return learnt;
331 }
332
333
334
335
336
337
338 public boolean locked() {
339 return true;
340 }
341
342
343
344
345
346
347
348
349
350
351 protected static BigInteger ppcm(BigInteger a, BigInteger b) {
352 return a.divide(a.gcd(b)).multiply(b);
353 }
354
355
356
357
358
359
360
361 public void rescaleBy(double d) {
362 activity *= d;
363 }
364
365 void selectionSort(int from, int to) {
366 int i, j, best_i;
367 BigInteger tmp;
368 int tmp2;
369
370 for (i = from; i < to - 1; i++) {
371 best_i = i;
372 for (j = i + 1; j < to; j++) {
373 if (coefs[j].compareTo(coefs[best_i]) > 0)
374 best_i = j;
375 }
376 tmp = coefs[i];
377 coefs[i] = coefs[best_i];
378 coefs[best_i] = tmp;
379 tmp2 = lits[i];
380 lits[i] = lits[best_i];
381 lits[best_i] = tmp2;
382 }
383 }
384
385
386
387
388 public void setLearnt() {
389 learnt = true;
390 }
391
392
393
394
395
396
397 public boolean simplify() {
398 BigInteger cumul = BigInteger.ZERO;
399
400 int i = 0;
401 while (i < lits.length && cumul.compareTo(degree) < 0) {
402 if (voc.isSatisfied(lits[i])) {
403
404 cumul = cumul.add(coefs[i]);
405 }
406 i++;
407 }
408
409 return (cumul.compareTo(degree) >= 0);
410 }
411
412 public int size() {
413 return lits.length;
414 }
415
416
417
418
419 final protected void sort() {
420 assert this.lits != null;
421 if (coefs.length > 0) {
422 this.sort(0, size());
423 BigInteger buffInt = coefs[0];
424 for (int i = 1; i < coefs.length; i++) {
425 assert buffInt.compareTo(coefs[i]) >= 0;
426 buffInt = coefs[i];
427 }
428
429 }
430 }
431
432
433
434
435
436
437
438
439
440 final protected void sort(int from, int to) {
441 int width = to - from;
442 if (to - from <= 15)
443 selectionSort(from, to);
444
445 else {
446 BigInteger pivot = coefs[rand.nextInt(width) + from];
447 BigInteger tmp;
448 int i = from - 1;
449 int j = to;
450 int tmp2;
451
452 for (;;) {
453 do
454 i++;
455 while (coefs[i].compareTo(pivot) > 0);
456 do
457 j--;
458 while (pivot.compareTo(coefs[j]) > 0);
459
460 if (i >= j)
461 break;
462
463 tmp = coefs[i];
464 coefs[i] = coefs[j];
465 coefs[j] = tmp;
466 tmp2 = lits[i];
467 lits[i] = lits[j];
468 lits[j] = tmp2;
469 }
470
471 sort(from, i);
472 sort(i, to);
473 }
474
475 }
476
477 @Override
478 public String toString() {
479 StringBuffer stb = new StringBuffer();
480
481 if (lits.length > 0) {
482 for (int i = 0; i < lits.length; i++) {
483
484 stb.append(" + ");
485 stb.append(this.coefs[i]);
486 stb.append(".");
487 stb.append(Lits.toString(this.lits[i]));
488 stb.append("[");
489 stb.append(voc.valueToString(lits[i]));
490 stb.append("@");
491 stb.append(voc.getLevel(lits[i]));
492 stb.append("]");
493 stb.append(" ");
494
495 }
496 stb.append(">= ");
497 stb.append(this.degree);
498 }
499 return stb.toString();
500 }
501
502 public void assertConstraint(UnitPropagationListener s) {
503 BigInteger tmp = slackConstraint();
504 for (int i = 0; i < lits.length; i++) {
505 if (voc.isUnassigned(lits[i]) && tmp.compareTo(coefs[i]) < 0) {
506 boolean ret = s.enqueue(lits[i], this);
507 assert ret;
508 }
509 }
510 }
511
512
513
514
515
516
517 public BigInteger getDegree() {
518 return degree;
519 }
520
521 public void register() {
522 assert learnt;
523 try {
524 computeWatches();
525 } catch (ContradictionException e) {
526 System.out.println(this);
527 assert false;
528 }
529 }
530
531 public static IVec<BigInteger> toVecBigInt(IVecInt vec) {
532 IVec<BigInteger> bigVec = new Vec<BigInteger>(vec.size());
533 for (int i = 0; i < vec.size(); ++i)
534 bigVec.push(BigInteger.valueOf(vec.get(i)));
535 return bigVec;
536 }
537
538 public static BigInteger toBigInt(int i) {
539 return BigInteger.valueOf(i);
540 }
541
542 public BigInteger[] getCoefs() {
543 BigInteger[] coefsBis = new BigInteger[coefs.length];
544 System.arraycopy(coefs, 0, coefsBis, 0, coefs.length);
545 return coefsBis;
546 }
547
548 public int[] getLits() {
549 int[] litsBis = new int[lits.length];
550 System.arraycopy(lits, 0, litsBis, 0, lits.length);
551 return litsBis;
552 }
553
554 public ILits getVocabulary() {
555 return voc;
556 }
557
558
559
560
561 public IVecInt computeAnImpliedClause() {
562 BigInteger cptCoefs = BigInteger.ZERO;
563 int index = coefs.length;
564 while ((cptCoefs.compareTo(degree) > 0) && (index > 0)) {
565 cptCoefs = cptCoefs.add(coefs[--index]);
566 }
567 if (index > 0 && index < size() / 2) {
568
569
570 IVecInt literals = new VecInt(index);
571 for (int j = 0; j <= index; j++)
572 literals.push(lits[j]);
573 return literals;
574 }
575 return null;
576 }
577
578 public boolean coefficientsEqualToOne() {
579 return false;
580 }
581
582 }