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