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