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