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