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