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