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.minisat.core.ILits;
33 import org.sat4j.minisat.core.UnitPropagationListener;
34 import org.sat4j.specs.ContradictionException;
35
36
37
38
39
40
41
42
43
44
45 public class MinWatchPbLongLimit extends WatchPbLong {
46 private static final long serialVersionUID = 1L;
47
48
49
50
51 protected long watchCumul = 0;
52
53
54
55
56
57 protected long compWatchCumul = 0;
58
59
60
61
62 protected boolean[] watched;
63
64
65
66
67 protected int[] watching;
68
69
70
71
72
73
74 protected int watchingCount = 0;
75
76
77
78
79
80
81
82
83
84
85
86 protected MinWatchPbLongLimit(ILits voc, IDataStructurePB mpb) {
87
88 super(mpb);
89 this.voc = voc;
90
91 watching = new int[this.coefs.length];
92 watched = new boolean[this.coefs.length];
93 activity = 0;
94 watchCumul = 0;
95 watchingCount = 0;
96
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 protected MinWatchPbLongLimit(ILits voc, int[] lits, BigInteger[] coefs,
113 BigInteger degree) {
114
115 super(lits, coefs, degree);
116 this.voc = voc;
117
118 watching = new int[this.coefs.length];
119 watched = new boolean[this.coefs.length];
120 activity = 0;
121 watchCumul = 0;
122 watchingCount = 0;
123
124 }
125
126
127
128
129
130
131
132
133 @Override
134 protected void computeWatches() throws ContradictionException {
135 assert watchCumul == 0;
136 assert watchingCount == 0;
137 for (int i = 0; i < lits.length
138 && watchCumulMinusValueIsLessThanDegree(coefs[0]); i++) {
139 if (!voc.isFalsified(lits[i])) {
140 voc.watch(lits[i] ^ 1, this);
141 watching[watchingCount++] = i;
142 watched[i] = true;
143
144 addToWC(coefs[i]);
145 }
146 }
147
148 if (learnt)
149 watchMoreForLearntConstraint();
150
151 if (watchCumul < degree) {
152 throw new ContradictionException("non satisfiable constraint");
153 }
154 assert nbOfWatched() == watchingCount;
155 }
156
157 private void watchMoreForLearntConstraint() {
158
159
160 int free = 1;
161 int maxlevel, maxi, level;
162
163 while (watchCumulMinusValueIsLessThanDegree(coefs[0]) && (free > 0)) {
164 free = 0;
165
166
167 maxlevel = -1;
168 maxi = -1;
169 for (int i = 0; i < lits.length; i++) {
170 if (voc.isFalsified(lits[i]) && !watched[i]) {
171 free++;
172 level = voc.getLevel(lits[i]);
173 if (level > maxlevel) {
174 maxi = i;
175 maxlevel = level;
176 }
177 }
178 }
179
180 if (free > 0) {
181 assert maxi >= 0;
182 voc.watch(lits[maxi] ^ 1, this);
183 watching[watchingCount++] = maxi;
184 watched[maxi] = true;
185
186 addToWC(coefs[maxi]);
187 free--;
188 assert free >= 0;
189 }
190 }
191 assert lits.length == 1 || watchingCount > 1;
192 }
193
194
195
196
197
198
199
200
201
202
203 @Override
204 protected void computePropagation(UnitPropagationListener s)
205 throws ContradictionException {
206
207 int ind = 0;
208 while (ind < lits.length
209 && watchCumulMinusValueIsLessThanDegree(coefs[watching[ind]])) {
210
211 if (voc.isUnassigned(lits[ind]) && !s.enqueue(lits[ind], this)) {
212 throw new ContradictionException("non satisfiable constraint");
213 }
214 ind++;
215 }
216 }
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236 public static MinWatchPbLongLimit normalizedMinWatchPbNew(
237 UnitPropagationListener s, ILits voc, int[] lits,
238 BigInteger[] coefs, BigInteger degree)
239 throws ContradictionException {
240
241 MinWatchPbLongLimit outclause = new MinWatchPbLongLimit(voc, lits,
242 coefs, degree);
243
244 if (outclause.degree <= 0) {
245 return null;
246 }
247
248 outclause.computeWatches();
249
250 outclause.computePropagation(s);
251
252 return outclause;
253
254 }
255
256
257
258
259
260
261
262
263
264 protected int nbOfWatched() {
265 int retour = 0;
266 for (int ind = 0; ind < this.watched.length; ind++) {
267 for (int i = 0; i < watchingCount; i++)
268 if (watching[i] == ind)
269 assert watched[ind];
270 retour += (this.watched[ind]) ? 1 : 0;
271 }
272 return retour;
273 }
274
275
276
277
278
279
280
281
282
283
284 public boolean propagate(UnitPropagationListener s, int p) {
285 assert nbOfWatched() == watchingCount;
286 assert watchingCount > 1;
287
288
289
290 int pIndiceWatching = 0;
291 while (pIndiceWatching < watchingCount
292 && (lits[watching[pIndiceWatching]] ^ 1) != p)
293 pIndiceWatching++;
294 int pIndice = watching[pIndiceWatching];
295
296 assert p == (lits[pIndice] ^ 1);
297 assert watched[pIndice];
298
299
300
301 long maxCoef = maximalCoefficient(pIndice);
302
303
304
305 maxCoef = updateWatched(maxCoef, pIndice);
306
307
308 assert nbOfWatched() == watchingCount;
309
310
311 if (watchCumulMinusValueIsLessThanDegree(coefs[pIndice])) {
312
313
314 voc.watch(p, this);
315 assert watched[pIndice];
316 assert !isSatisfiable();
317 return false;
318 } else {
319 assert Long.MAX_VALUE - coefs[pIndice] > maxCoef;
320 if (watchCumulMinusValueIsLessThanDegree(coefs[pIndice] + maxCoef)) {
321
322 assert watchingCount != 0;
323
324
325 for (int i = 0; i < watchingCount; i++) {
326 assert Long.MAX_VALUE - coefs[pIndice] > coefs[watching[i]];
327
328
329 if (watchCumulMinusValueIsLessThanDegree(coefs[pIndice]
330 + coefs[watching[i]])
331 && i != pIndiceWatching
332 && !voc.isSatisfied(lits[watching[i]])
333 && !s.enqueue(lits[watching[i]], this)) {
334 voc.watch(p, this);
335 assert !isSatisfiable();
336 return false;
337 }
338 }
339 }
340
341
342 voc.undos(p).push(this);
343 }
344
345
346 watched[pIndice] = false;
347 substractToWC(coefs[pIndice]);
348 watching[pIndiceWatching] = watching[--watchingCount];
349
350 assert watchingCount != 0;
351 assert nbOfWatched() == watchingCount;
352
353 return true;
354 }
355
356
357
358
359 public void remove(UnitPropagationListener upl) {
360 for (int i = 0; i < watchingCount; i++) {
361 voc.watches(lits[watching[i]] ^ 1).remove(this);
362 this.watched[this.watching[i]] = false;
363 }
364 watchingCount = 0;
365 assert nbOfWatched() == watchingCount;
366 int ind = 0;
367 while (ind < coefs.length
368 && watchCumulMinusValueIsLessThanDegree(coefs[ind])) {
369
370 upl.unset(lits[ind]);
371 ind++;
372 }
373 }
374
375
376
377
378
379
380
381 public void undo(int p) {
382 voc.watch(p, this);
383 int pIndice = 0;
384 while ((lits[pIndice] ^ 1) != p)
385 pIndice++;
386
387 assert pIndice < lits.length;
388
389
390 addToWC(coefs[pIndice]);
391
392 assert watchingCount == nbOfWatched();
393
394 watched[pIndice] = true;
395 watching[watchingCount++] = pIndice;
396
397 assert watchingCount == nbOfWatched();
398 }
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413 public static WatchPbLong normalizedWatchPbNew(ILits voc,
414 IDataStructurePB mpb) {
415 return new MinWatchPbLong(voc, mpb);
416 }
417
418
419
420
421
422
423
424
425
426 protected long maximalCoefficient(int pIndice) {
427 long maxCoef = 0;
428 for (int i = 0; i < watchingCount; i++)
429 if (coefs[watching[i]] > maxCoef && watching[i] != pIndice) {
430 maxCoef = coefs[watching[i]];
431 }
432
433 assert learnt || maxCoef != 0;
434
435 return maxCoef;
436 }
437
438
439
440
441
442
443
444
445
446
447
448
449
450 protected long updateWatched(long mc, int pIndice) {
451 long maxCoef = mc;
452
453 if (watchingCount < size()) {
454
455
456 long upWatchCumul = 0;
457 long compUpWatchCumul = 0;
458 if (compWatchCumul > 0) {
459 assert watchCumul == Long.MAX_VALUE;
460 compUpWatchCumul = compWatchCumul - coefs[pIndice];
461 if (compUpWatchCumul < 0) {
462 upWatchCumul = Long.MAX_VALUE - compUpWatchCumul;
463 compUpWatchCumul = 0;
464 }
465 } else {
466 upWatchCumul = watchCumul - coefs[pIndice];
467 }
468
469
470
471 long degreePlusMaxCoef = 0;
472 long compDegreePlusMaxCoef = 0;
473 if (Long.MAX_VALUE - degree < maxCoef) {
474 degreePlusMaxCoef = Long.MAX_VALUE;
475 compDegreePlusMaxCoef = maxCoef - (Long.MAX_VALUE - degree);
476 } else
477 degreePlusMaxCoef = degree + maxCoef;
478 for (int ind = 0; ind < lits.length; ind++) {
479
480 if ((compUpWatchCumul == 0 && compDegreePlusMaxCoef == 0 && upWatchCumul >= degreePlusMaxCoef)
481 || (compUpWatchCumul > compDegreePlusMaxCoef)
482 || (compUpWatchCumul == compDegreePlusMaxCoef && upWatchCumul == degreePlusMaxCoef)) {
483
484
485 break;
486 }
487
488 if (!voc.isFalsified(lits[ind]) && !watched[ind]) {
489
490
491 if (Long.MAX_VALUE - coefs[ind] >= upWatchCumul)
492 upWatchCumul = upWatchCumul + coefs[ind];
493 else {
494 compUpWatchCumul = coefs[ind]
495 - (Long.MAX_VALUE - upWatchCumul);
496 upWatchCumul = Long.MAX_VALUE;
497 }
498
499
500 watched[ind] = true;
501 assert watchingCount < size();
502 watching[watchingCount++] = ind;
503 voc.watch(lits[ind] ^ 1, this);
504
505
506 if (coefs[ind] > maxCoef) {
507 maxCoef = coefs[ind];
508
509 compDegreePlusMaxCoef = 0;
510 if (Long.MAX_VALUE - degree < maxCoef) {
511 degreePlusMaxCoef = Long.MAX_VALUE;
512 compDegreePlusMaxCoef = maxCoef
513 - (Long.MAX_VALUE - degree);
514 } else
515 degreePlusMaxCoef = degree + maxCoef;
516
517
518 }
519 }
520 }
521
522
523 watchCumul = upWatchCumul;
524 compWatchCumul = compUpWatchCumul;
525 addToWC(coefs[pIndice]);
526 }
527 return maxCoef;
528 }
529
530 private boolean watchCumulMinusValueIsLessThanDegree(long coef) {
531 return ((watchCumul - coef) < degree && watchCumul != Long.MAX_VALUE)
532 || (compWatchCumul - coef) > 0
533 || ((watchCumul - coef) + compWatchCumul) < degree;
534 }
535
536 private void addToWC(long coef) {
537 if (Long.MAX_VALUE - coef >= watchCumul)
538 watchCumul = watchCumul + coef;
539 else {
540 compWatchCumul = coef - (Long.MAX_VALUE - watchCumul);
541 watchCumul = Long.MAX_VALUE;
542 }
543 }
544
545 private void substractToWC(long coef) {
546 if (compWatchCumul == 0)
547 watchCumul = watchCumul - coef;
548 else {
549 compWatchCumul = compWatchCumul - coef;
550 if (compWatchCumul < 0) {
551 watchCumul = watchCumul - compWatchCumul;
552 compWatchCumul = 0;
553 }
554 }
555 }
556
557 }