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