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