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 MinWatchPbLong extends WatchPbLong {
45
46 private static final long serialVersionUID = 1L;
47
48
49
50
51 protected long watchCumul = 0;
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 MinWatchPbLong(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 = 0;
89 watchingCount = 0;
90
91 }
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 protected MinWatchPbLong(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 = 0;
116 watchingCount = 0;
117
118 }
119
120
121
122
123
124
125
126
127 @Override
128 protected void computeWatches() throws ContradictionException {
129 assert watchCumul == 0;
130 assert watchingCount == 0;
131 for (int i = 0; i < lits.length && (watchCumul - coefs[0]) < degree; i++) {
132 if (!voc.isFalsified(lits[i])) {
133 voc.watch(lits[i] ^ 1, this);
134 watching[watchingCount++] = i;
135 watched[i] = true;
136
137 watchCumul = watchCumul + coefs[i];
138 }
139 }
140
141 if (learnt)
142 watchMoreForLearntConstraint();
143
144 if (watchCumul < degree) {
145 throw new ContradictionException("non satisfiable constraint");
146 }
147 assert nbOfWatched() == watchingCount;
148 }
149
150 private void watchMoreForLearntConstraint() {
151
152
153 int free = 1;
154 int maxlevel, maxi, level;
155
156 while ((watchCumul - coefs[0]) < degree && (free > 0)) {
157 free = 0;
158
159
160 maxlevel = -1;
161 maxi = -1;
162 for (int i = 0; i < lits.length; i++) {
163 if (voc.isFalsified(lits[i]) && !watched[i]) {
164 free++;
165 level = voc.getLevel(lits[i]);
166 if (level > maxlevel) {
167 maxi = i;
168 maxlevel = level;
169 }
170 }
171 }
172
173 if (free > 0) {
174 assert maxi >= 0;
175 voc.watch(lits[maxi] ^ 1, this);
176 watching[watchingCount++] = maxi;
177 watched[maxi] = true;
178
179 watchCumul = watchCumul + coefs[maxi];
180 free--;
181 assert free >= 0;
182 }
183 }
184 assert lits.length == 1 || watchingCount > 1;
185 }
186
187
188
189
190
191
192
193
194
195
196 @Override
197 protected void computePropagation(UnitPropagationListener s)
198 throws ContradictionException {
199
200 int ind = 0;
201 while (ind < lits.length
202 && (watchCumul - coefs[watching[ind]]) < degree) {
203 if (voc.isUnassigned(lits[ind]) && !s.enqueue(lits[ind], this)) {
204 throw new ContradictionException("non satisfiable constraint");
205 }
206 ind++;
207 }
208 }
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228 public static MinWatchPbLong normalizedMinWatchPbNew(
229 UnitPropagationListener s, ILits voc, int[] lits,
230 BigInteger[] coefs, BigInteger degree)
231 throws ContradictionException {
232
233 MinWatchPbLong outclause = new MinWatchPbLong(voc, lits, coefs, degree);
234
235 if (outclause.degree <= 0) {
236 return null;
237 }
238
239 outclause.computeWatches();
240
241 outclause.computePropagation(s);
242
243 return outclause;
244
245 }
246
247
248
249
250
251
252
253
254
255 protected int nbOfWatched() {
256 int retour = 0;
257 for (int ind = 0; ind < this.watched.length; ind++) {
258 for (int i = 0; i < watchingCount; i++)
259 if (watching[i] == ind)
260 assert watched[ind];
261 retour += (this.watched[ind]) ? 1 : 0;
262 }
263 return retour;
264 }
265
266
267
268
269
270
271
272
273
274
275 @Override
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 long maxCoef = maximalCoefficient(pIndice);
294
295
296
297 maxCoef = updateWatched(maxCoef, pIndice);
298
299 long upWatchCumul = watchCumul - coefs[pIndice];
300 assert nbOfWatched() == watchingCount;
301
302
303 if (upWatchCumul < degree) {
304
305 voc.watch(p, this);
306 assert watched[pIndice];
307 assert !isSatisfiable();
308 return false;
309 } else if (upWatchCumul < (degree + maxCoef)) {
310
311 assert watchingCount != 0;
312 long limit = upWatchCumul - degree;
313 for (int i = 0; i < watchingCount; i++) {
314 if (limit < coefs[watching[i]] && i != pIndiceWatching
315 && !voc.isSatisfied(lits[watching[i]])
316 && !s.enqueue(lits[watching[i]], this)) {
317 voc.watch(p, this);
318 assert !isSatisfiable();
319 return false;
320 }
321 }
322
323
324 voc.undos(p).push(this);
325 }
326
327
328 watched[pIndice] = false;
329 watchCumul = upWatchCumul;
330 watching[pIndiceWatching] = watching[--watchingCount];
331
332 assert watchingCount != 0;
333 assert nbOfWatched() == watchingCount;
334
335 return true;
336 }
337
338
339
340
341 @Override
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 @Override
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 + 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 WatchPbLong normalizedWatchPbNew(ILits voc,
390 IDataStructurePB mpb) {
391 return new MinWatchPbLong(voc, mpb);
392 }
393
394
395
396
397
398
399
400
401
402 protected long maximalCoefficient(int pIndice) {
403 long maxCoef = 0;
404 for (int i = 0; i < watchingCount; i++)
405 if (coefs[watching[i]] > maxCoef && watching[i] != pIndice) {
406 maxCoef = coefs[watching[i]];
407 }
408
409 assert learnt || maxCoef != 0;
410
411 return maxCoef;
412 }
413
414
415
416
417
418
419
420
421
422
423
424
425
426 protected long updateWatched(long mc, int pIndice) {
427 long maxCoef = mc;
428
429 if (watchingCount < size()) {
430
431 long upWatchCumul = watchCumul - coefs[pIndice];
432
433
434
435 long degreePlusMaxCoef = degree + maxCoef;
436 for (int ind = 0; ind < lits.length; ind++) {
437 if (upWatchCumul >= degreePlusMaxCoef) {
438
439
440 break;
441 }
442
443 if (!voc.isFalsified(lits[ind]) && !watched[ind]) {
444
445 upWatchCumul = upWatchCumul + 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] > maxCoef) {
454 maxCoef = coefs[ind];
455 degreePlusMaxCoef = degree + maxCoef;
456
457
458 }
459 }
460 }
461
462 watchCumul = upWatchCumul + coefs[pIndice];
463 }
464 return maxCoef;
465 }
466
467 }