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.math.BigInteger;
31
32 import org.sat4j.core.VecInt;
33 import org.sat4j.minisat.constraints.cnf.Lits;
34 import org.sat4j.minisat.core.ILits;
35 import org.sat4j.minisat.core.VarActivityListener;
36 import org.sat4j.specs.IteratorInt;
37
38
39
40
41
42 public class ConflictMap extends MapPb implements IConflict {
43
44 private final ILits voc;
45
46
47
48
49 protected BigInteger currentSlack;
50
51 protected int currentLevel;
52
53
54
55
56
57
58 protected VecInt[] byLevel;
59
60
61
62
63
64
65
66
67
68
69 public static IConflict createConflict(PBConstr cpb, int level) {
70 return new ConflictMap(cpb, level);
71 }
72
73 ConflictMap(PBConstr cpb, int level) {
74 super(cpb);
75 this.voc = cpb.getVocabulary();
76 this.currentLevel = level;
77 initStructures();
78 }
79
80 private void initStructures() {
81 currentSlack = BigInteger.ZERO;
82 byLevel = new VecInt[levelToIndex(currentLevel) + 1];
83 int ilit, litLevel, index;
84 BigInteger tmp;
85 for (int i = 0; i < size(); i++) {
86 ilit = weightedLits.getLit(i);
87 litLevel = voc.getLevel(ilit);
88
89 tmp = weightedLits.getCoef(i);
90 if ((tmp.signum() > 0)
91 && (((!voc.isFalsified(ilit)) || litLevel == currentLevel)))
92 currentSlack = currentSlack.add(tmp);
93
94 index = levelToIndex(litLevel);
95 if (byLevel[index] == null) {
96 byLevel[index] = new VecInt();
97 }
98 byLevel[index].push(ilit);
99 }
100 }
101
102
103
104
105
106
107
108 private static final int levelToIndex(int level) {
109 return level + 1;
110 }
111
112
113
114
115
116
117
118 private static final int indexToLevel(int indLevel) {
119 return indLevel - 1;
120 }
121
122
123
124
125
126 protected BigInteger coefMult = BigInteger.ZERO;
127
128 protected BigInteger coefMultCons = BigInteger.ZERO;
129
130
131
132
133
134
135
136
137
138
139
140 public BigInteger resolve(PBConstr cpb, int litImplied,
141 VarActivityListener val) {
142 assert litImplied > 1;
143 int nLitImplied = litImplied ^ 1;
144 if (cpb == null || !weightedLits.containsKey(nLitImplied)) {
145
146
147 int litLevel = levelToIndex(voc.getLevel(litImplied));
148 int lit = 0;
149 if (byLevel[litLevel] != null) {
150 if (byLevel[litLevel].contains(litImplied)) {
151 lit = litImplied;
152 assert weightedLits.containsKey(litImplied);
153 } else if (byLevel[litLevel].contains(nLitImplied)) {
154 lit = nLitImplied;
155 assert weightedLits.containsKey(nLitImplied);
156 }
157 }
158
159 if (lit > 0) {
160 byLevel[litLevel].remove(lit);
161 if (byLevel[0] == null)
162 byLevel[0] = new VecInt();
163 byLevel[0].push(lit);
164 }
165 return degree;
166 }
167
168 assert slackConflict().signum() <= 0;
169 assert degree.signum() >= 0;
170
171
172
173 BigInteger[] coefsCons = null;
174 BigInteger degreeCons = cpb.getDegree();
175
176
177 int ind = 0;
178 while (cpb.get(ind) != litImplied)
179 ind++;
180
181 assert cpb.get(ind) == litImplied;
182 assert cpb.getCoef(ind) != BigInteger.ZERO;
183
184 if (cpb.getCoef(ind).equals(BigInteger.ONE)) {
185
186
187 coefMultCons = weightedLits.get(nLitImplied);
188 coefMult = BigInteger.ONE;
189
190 degreeCons = degreeCons.multiply(coefMultCons);
191 } else {
192 if (weightedLits.get(nLitImplied).equals(BigInteger.ONE)) {
193
194
195 coefMult = cpb.getCoef(ind);
196 coefMultCons = BigInteger.ONE;
197
198 degree = degree.multiply(coefMult);
199 } else {
200
201
202 WatchPb wpb = (WatchPb) cpb;
203 coefsCons = wpb.getCoefs();
204 assert positiveCoefs(coefsCons);
205 degreeCons = reduceUntilConflict(litImplied, ind, coefsCons,
206 wpb);
207
208 degreeCons = degreeCons.multiply(coefMultCons);
209 degree = degree.multiply(coefMult);
210 }
211
212
213 if (!coefMult.equals(BigInteger.ONE))
214 for (int i = 0; i < size(); i++) {
215 changeCoef(i, weightedLits.getCoef(i).multiply(coefMult));
216 }
217 }
218
219 assert slackConflict().signum() <= 0;
220
221
222 degree = cuttingPlane(cpb, degreeCons, coefsCons, coefMultCons, val);
223
224
225 assert !weightedLits.containsKey(litImplied);
226 assert !weightedLits.containsKey(nLitImplied);
227
228 assert getLevelByLevel(litImplied) == -1;
229 assert getLevelByLevel(nLitImplied) == -1;
230 assert degree.signum() > 0;
231 assert slackConflict().signum() <= 0;
232
233
234 degree = saturation();
235 assert slackConflict().signum() <= 0;
236
237 return degree;
238 }
239
240 protected BigInteger reduceUntilConflict(int litImplied, int ind,
241 BigInteger[] reducedCoefs, WatchPb wpb) {
242 BigInteger slackResolve = BigInteger.ONE.negate();
243 BigInteger slackThis = BigInteger.ZERO;
244 BigInteger slackIndex;
245 BigInteger slackConflict = slackConflict();
246 BigInteger ppcm;
247 BigInteger reducedDegree = wpb.getDegree();
248 BigInteger previousCoefLitImplied = BigInteger.ZERO;
249 BigInteger tmp;
250 BigInteger coefLitImplied = weightedLits.get(litImplied ^ 1);
251
252 do {
253 if (slackResolve.signum() >= 0) {
254 assert slackThis.signum() > 0;
255 tmp = reduceInConstraint(wpb, reducedCoefs, ind, reducedDegree);
256 assert ((tmp.compareTo(reducedDegree) < 0) && (tmp
257 .compareTo(BigInteger.ONE) >= 0));
258 reducedDegree = tmp;
259 }
260
261 assert weightedLits.get(litImplied ^ 1).signum() > 0;
262 assert reducedCoefs[ind].signum() > 0;
263
264 if (!reducedCoefs[ind].equals(previousCoefLitImplied)) {
265 assert coefLitImplied.equals(weightedLits.get(litImplied ^ 1));
266 ppcm = ppcm(reducedCoefs[ind], coefLitImplied);
267 assert ppcm.signum() > 0;
268 coefMult = ppcm.divide(coefLitImplied);
269 coefMultCons = ppcm.divide(reducedCoefs[ind]);
270
271 assert coefMultCons.signum() > 0;
272 assert coefMult.signum() > 0;
273 assert coefMult.multiply(coefLitImplied).equals(
274 coefMultCons.multiply(reducedCoefs[ind]));
275 previousCoefLitImplied = reducedCoefs[ind];
276 }
277
278
279 slackThis = wpb.slackConstraint(reducedCoefs, reducedDegree)
280 .multiply(coefMultCons);
281 assert slackConflict.equals(slackConflict());
282 slackIndex = slackConflict.multiply(coefMult);
283 assert slackIndex.signum() <= 0;
284
285 slackResolve = slackThis.add(slackIndex);
286 } while (slackResolve.signum() >= 0);
287 assert coefMult.multiply(weightedLits.get(litImplied ^ 1)).equals(
288 coefMultCons.multiply(reducedCoefs[ind]));
289 return reducedDegree;
290
291 }
292
293
294
295
296 public BigInteger slackConflict() {
297 BigInteger poss = BigInteger.ZERO;
298 BigInteger tmp;
299
300 for (int i = 0; i < size(); i++) {
301 tmp = weightedLits.getCoef(i);
302 if (tmp.signum() != 0 && !voc.isFalsified(weightedLits.getLit(i)))
303 poss = poss.add(tmp);
304 }
305 return poss.subtract(degree);
306 }
307
308 public boolean oldIsAssertive(int dl) {
309 BigInteger tmp;
310 int lit;
311 BigInteger slack = computeSlack(dl).subtract(degree);
312 if (slack.signum() < 0)
313 return false;
314 for (int i = 0; i < size(); i++) {
315 tmp = weightedLits.getCoef(i);
316 lit = weightedLits.getLit(i);
317 if ((tmp.signum() > 0)
318 && (voc.isUnassigned(lit) || voc.getLevel(lit) >= dl)
319 && (slack.compareTo(tmp) < 0))
320 return true;
321 }
322 return false;
323 }
324
325
326 private BigInteger computeSlack(int dl) {
327 BigInteger slack = BigInteger.ZERO;
328 int lit;
329 BigInteger tmp;
330 for (int i = 0; i < size(); i++) {
331 tmp = weightedLits.getCoef(i);
332 lit = weightedLits.getLit(i);
333 if ((tmp.signum() > 0)
334 && (((!voc.isFalsified(lit)) || voc.getLevel(lit) >= dl)))
335 slack = slack.add(tmp);
336 }
337 return slack;
338 }
339
340
341
342
343
344
345
346
347
348 public boolean isAssertive(int dl) {
349 assert dl <= currentLevel;
350 assert dl <= currentLevel;
351
352 currentLevel = dl;
353
354 BigInteger slack = currentSlack.subtract(degree);
355 if (slack.signum() < 0)
356 return false;
357 return isImplyingLiteral(slack);
358 }
359
360
361
362
363 private boolean isImplyingLiteral(BigInteger slack) {
364
365 int unassigned = levelToIndex(-1);
366 if (byLevel[unassigned] != null) {
367 for (IteratorInt iterator = byLevel[unassigned].iterator(); iterator
368 .hasNext();) {
369 if (slack.compareTo(weightedLits.get(iterator.next())) < 0)
370 return true;
371 }
372 }
373
374 BigInteger tmp;
375 int level = levelToIndex(currentLevel);
376 if (byLevel[level] != null)
377 for (IteratorInt iterator = byLevel[level].iterator(); iterator
378 .hasNext();) {
379 tmp = weightedLits.get(iterator.next());
380 if (tmp != null && slack.compareTo(tmp) < 0)
381 return true;
382 }
383 return false;
384 }
385
386
387
388
389
390 private boolean isImplyingLiteralOrdered(int dl, BigInteger slack) {
391 int ilit, litLevel;
392 for (int i = 0; i < size(); i++) {
393 ilit = weightedLits.getLit(i);
394 litLevel = voc.getLevel(ilit);
395 if ((litLevel >= dl || voc.isUnassigned(ilit))
396 && (slack.compareTo(weightedLits.getCoef(i)) < 0))
397 return true;
398 }
399 return false;
400 }
401
402
403
404
405
406
407
408
409
410
411
412 protected static BigInteger ppcm(BigInteger a, BigInteger b) {
413 return a.divide(a.gcd(b)).multiply(b);
414 }
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433 public BigInteger reduceInConstraint(WatchPb wpb,
434 final BigInteger[] coefsBis, final int indLitImplied,
435 final BigInteger degreeBis) {
436
437 assert degreeBis.compareTo(BigInteger.ONE) > 0;
438
439 int lit = -1;
440 for (int ind = 0; (ind < wpb.lits.length) && (lit == -1); ind++)
441 if (coefsBis[ind].signum() != 0 && voc.isUnassigned(wpb.lits[ind])) {
442 assert coefsBis[ind].compareTo(degreeBis) < 0;
443 lit = ind;
444 }
445
446
447 if (lit == -1)
448 for (int ind = 0; (ind < wpb.lits.length) && (lit == -1); ind++)
449 if ((coefsBis[ind].signum() != 0)
450 && (voc.isSatisfied(wpb.lits[ind]))
451 && (ind != indLitImplied))
452 lit = ind;
453
454
455 assert lit != -1;
456
457 assert lit != indLitImplied;
458
459
460 BigInteger degUpdate = degreeBis.subtract(coefsBis[lit]);
461 coefsBis[lit] = BigInteger.ZERO;
462
463
464 degUpdate = saturation(coefsBis, degUpdate);
465
466 assert coefsBis[indLitImplied].signum() > 0;
467 assert degreeBis.compareTo(degUpdate) > 0;
468 return degUpdate;
469 }
470
471 static BigInteger saturation(BigInteger[] coefs, BigInteger degree) {
472 assert degree.signum() > 0;
473 BigInteger minimum = degree;
474 for (int i = 0; i < coefs.length; i++) {
475 if (coefs[i].signum() > 0)
476 minimum = minimum.min(coefs[i]);
477 coefs[i] = degree.min(coefs[i]);
478 }
479 if (minimum.equals(degree) && !degree.equals(BigInteger.ONE)) {
480
481
482 degree = BigInteger.ONE;
483 for (int i = 0; i < coefs.length; i++)
484 if (coefs[i].signum() > 0)
485 coefs[i] = degree;
486 }
487 return degree;
488 }
489
490 private static boolean positiveCoefs(final BigInteger[] coefsCons) {
491 for (int i = 0; i < coefsCons.length; i++) {
492 if (coefsCons[i].signum() <= 0)
493 return false;
494 }
495 return true;
496 }
497
498
499
500
501
502
503
504
505
506
507 public int getBacktrackLevel(int maxLevel) {
508
509
510 VecInt lits;
511 int level;
512 int indStop = levelToIndex(maxLevel) - 1;
513 int indStart = levelToIndex(0);
514 BigInteger slack = computeSlack(0).subtract(degree);
515 int previous = 0;
516 for (int indLevel = indStart; indLevel <= indStop; indLevel++) {
517 if (byLevel[indLevel] != null) {
518 level = indexToLevel(indLevel);
519 assert computeSlack(level).subtract(degree).equals(slack);
520 if (isImplyingLiteralOrdered(level, slack)) {
521 break;
522 }
523
524 lits = byLevel[indLevel];
525 int lit;
526 for (IteratorInt iterator = lits.iterator(); iterator.hasNext();) {
527 lit = iterator.next();
528 if (voc.isFalsified(lit)
529 && voc.getLevel(lit) == indexToLevel(indLevel))
530 slack = slack.subtract(weightedLits.get(lit));
531 }
532 if (!lits.isEmpty())
533 previous = level;
534 }
535 }
536 assert previous == oldGetBacktrackLevel(maxLevel);
537 return previous;
538 }
539
540 public int oldGetBacktrackLevel(int maxLevel) {
541 int litLevel;
542 int borneMax = maxLevel;
543 assert oldIsAssertive(borneMax);
544 int borneMin = -1;
545
546 for (int i = 0; i < size() ; i++) {
547 litLevel = voc.getLevel(weightedLits.getLit(i));
548 if (litLevel < borneMax && litLevel > borneMin
549 && oldIsAssertive(litLevel))
550 borneMax = litLevel;
551 }
552
553
554 int retour = 0;
555 for (int i = 0; i < size(); i++) {
556 litLevel = voc.getLevel(weightedLits.getLit(i));
557 if (litLevel > retour && litLevel < borneMax) {
558 retour = litLevel;
559 }
560 }
561 return retour;
562 }
563
564 public void updateSlack(int level) {
565 int dl = levelToIndex(level);
566 if (byLevel[dl] != null) {
567 int lit;
568 for (IteratorInt iterator = byLevel[dl].iterator(); iterator
569 .hasNext();) {
570 lit = iterator.next();
571 if (voc.isFalsified(lit))
572 currentSlack = currentSlack.add(weightedLits.get(lit));
573 }
574 }
575 }
576
577 @Override
578 void increaseCoef(int lit, BigInteger incCoef) {
579 if ((!voc.isFalsified(lit)) || voc.getLevel(lit) == currentLevel) {
580 currentSlack = currentSlack.add(incCoef);
581 }
582 assert byLevel[levelToIndex(voc.getLevel(lit))].contains(lit);
583 super.increaseCoef(lit, incCoef);
584 }
585
586 @Override
587 void decreaseCoef(int lit, BigInteger decCoef) {
588 if ((!voc.isFalsified(lit)) || voc.getLevel(lit) == currentLevel) {
589 currentSlack = currentSlack.subtract(decCoef);
590 }
591 assert byLevel[levelToIndex(voc.getLevel(lit))].contains(lit);
592 super.decreaseCoef(lit, decCoef);
593 }
594
595 @Override
596 void setCoef(int lit, BigInteger newValue) {
597 int litLevel = voc.getLevel(lit);
598 if ((!voc.isFalsified(lit)) || litLevel == currentLevel) {
599 if (weightedLits.containsKey(lit))
600 currentSlack = currentSlack.subtract(weightedLits.get(lit));
601 currentSlack = currentSlack.add(newValue);
602 }
603 int indLitLevel = levelToIndex(litLevel);
604 if (!weightedLits.containsKey(lit)) {
605 if (byLevel[indLitLevel] == null) {
606 byLevel[indLitLevel] = new VecInt();
607 }
608 byLevel[indLitLevel].push(lit);
609
610 }
611 assert byLevel[indLitLevel] != null;
612 assert byLevel[indLitLevel].contains(lit);
613 super.setCoef(lit, newValue);
614 }
615
616 @Override
617 void changeCoef(int indLit, BigInteger newValue) {
618 int lit = weightedLits.getLit(indLit);
619 int litLevel = voc.getLevel(lit);
620 if ((!voc.isFalsified(lit)) || litLevel == currentLevel) {
621 if (weightedLits.containsKey(lit))
622 currentSlack = currentSlack.subtract(weightedLits.get(lit));
623 currentSlack = currentSlack.add(newValue);
624 }
625 int indLitLevel = levelToIndex(litLevel);
626 assert weightedLits.containsKey(lit);
627 assert byLevel[indLitLevel] != null;
628 assert byLevel[indLitLevel].contains(lit);
629 super.changeCoef(indLit, newValue);
630 }
631
632
633 @Override
634 void removeCoef(int lit) {
635 int litLevel = voc.getLevel(lit);
636 if ((!voc.isFalsified(lit)) || litLevel == currentLevel) {
637 currentSlack = currentSlack.subtract(weightedLits.get(lit));
638 }
639 int indLitLevel = levelToIndex(litLevel);
640 assert indLitLevel < byLevel.length;
641 assert byLevel[indLitLevel] != null;
642 assert byLevel[indLitLevel].contains(lit);
643 byLevel[indLitLevel].remove(lit);
644 super.removeCoef(lit);
645 }
646
647
648 private int getLevelByLevel(int lit) {
649 for (int i = 0; i < byLevel.length; i++)
650 if (byLevel[i] != null && byLevel[i].contains(lit))
651 return i;
652 return -1;
653 }
654
655 public boolean slackIsCorrect(int dl) {
656 return currentSlack.equals(computeSlack(dl));
657 }
658
659 @Override
660 public String toString() {
661 int lit;
662 StringBuffer stb = new StringBuffer();
663 for (int i = 0; i < size(); i++) {
664 lit = weightedLits.getLit(i);
665 stb.append(weightedLits.getCoef(i));
666 stb.append(".");
667 stb.append(Lits.toString(lit));
668 stb.append(" ");
669 stb.append("[");
670 stb.append(voc.valueToString(lit));
671 stb.append("@");
672 stb.append(voc.getLevel(lit));
673 stb.append("]");
674 }
675 return stb.toString() + " >= " + degree;
676 }
677
678 }