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.minisat.constraints.card;
29
30 import java.io.Serializable;
31
32 import org.sat4j.minisat.constraints.cnf.Lits;
33 import org.sat4j.minisat.constraints.cnf.UnitClauses;
34 import org.sat4j.minisat.core.Constr;
35 import org.sat4j.minisat.core.ILits;
36 import org.sat4j.minisat.core.Undoable;
37 import org.sat4j.minisat.core.UnitPropagationListener;
38 import org.sat4j.specs.ContradictionException;
39 import org.sat4j.specs.IVecInt;
40
41 public class MinWatchCard implements Constr, Undoable, Serializable {
42
43 private static final long serialVersionUID = 1L;
44
45 public static final boolean ATLEAST = true;
46
47 public static final boolean ATMOST = false;
48
49
50
51
52 protected int degree;
53
54
55
56
57 private final int[] lits;
58
59
60
61
62 private boolean moreThan;
63
64
65
66
67 protected int watchCumul;
68
69
70
71
72 private final ILits voc;
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 public MinWatchCard(ILits voc, IVecInt ps, boolean moreThan, int degree) {
88
89 this.voc = voc;
90 this.degree = degree;
91 this.moreThan = moreThan;
92
93
94 int[] index = new int[voc.nVars() * 2 + 2];
95
96
97
98 for (int i = 0; i < ps.size(); i++) {
99 int p = ps.get(i);
100 if (index[p ^ 1] == 0) {
101 index[p]++;
102 } else {
103 index[p ^ 1]--;
104 }
105 }
106
107 int ind = 0;
108 while (ind < ps.size()) {
109 if (index[ps.get(ind)] > 0) {
110 index[ps.get(ind)]--;
111 ind++;
112 } else {
113
114 if ((ps.get(ind) & 1) != 0)
115 this.degree--;
116 ps.delete(ind);
117 }
118 }
119
120
121 lits = new int[ps.size()];
122 ps.moveTo(lits);
123
124
125 normalize();
126
127 }
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 protected MinWatchCard(ILits voc, IVecInt ps, int degree) {
144
145 this.voc = voc;
146 this.degree = degree;
147 this.moreThan = ATLEAST;
148
149
150 lits = new int[ps.size()];
151 ps.moveTo(lits);
152
153 }
154
155
156
157
158
159
160
161
162
163
164 public void calcReason(int p, IVecInt outReason) {
165 for (int i = 0; i < lits.length; i++) {
166 if (voc.isFalsified(lits[i])) {
167 outReason.push(lits[i] ^ 1);
168 }
169 }
170 }
171
172
173
174
175
176
177
178 public double getActivity() {
179
180 return 0;
181 }
182
183
184
185
186
187
188
189
190 public void incActivity(double claInc) {
191
192 }
193
194
195
196
197
198
199
200 public boolean learnt() {
201 return false;
202 }
203
204
205
206
207
208
209
210
211
212
213
214 protected static int linearisation(ILits voc, IVecInt ps) {
215
216 int modif = 0;
217
218 for (int i = 0; i < ps.size();) {
219
220 if (voc.isUnassigned(ps.get(i))) {
221 i++;
222 } else {
223
224
225 if (voc.isSatisfied(ps.get(i))) {
226 modif--;
227 }
228
229
230 ps.set(i, ps.last());
231 ps.pop();
232 }
233 }
234
235
236
237 assert modif <= 0;
238
239 return modif;
240 }
241
242
243
244
245
246
247
248 public boolean locked() {
249
250 return true;
251 }
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271 public static Constr minWatchCardNew(UnitPropagationListener s, ILits voc,
272 IVecInt ps, boolean moreThan, int degree)
273 throws ContradictionException {
274
275 int mydegree = degree + linearisation(voc, ps);
276
277 if (ps.size() < mydegree) {
278 throw new ContradictionException();
279 } else if (ps.size() == mydegree) {
280 for (int i = 0; i < ps.size(); i++)
281 if (!s.enqueue(ps.get(i))) {
282 throw new ContradictionException();
283 }
284 return new UnitClauses(ps);
285 }
286
287
288 MinWatchCard retour = new MinWatchCard(voc, ps, moreThan, mydegree);
289
290 if (retour.degree <= 0)
291 return null;
292
293 retour.computeWatches();
294
295 retour.computePropagation(s);
296
297 return retour;
298 }
299
300
301
302
303 public final void normalize() {
304
305 if (!moreThan) {
306
307 this.degree = 0 - this.degree;
308
309 for (int indLit = 0; indLit < lits.length; indLit++) {
310 lits[indLit] = lits[indLit] ^ 1;
311 this.degree++;
312 }
313 this.moreThan = true;
314 }
315 }
316
317
318
319
320
321
322
323
324
325
326 public boolean propagate(UnitPropagationListener s, int p) {
327
328
329 if (watchCumul == degree) {
330 voc.watch(p, this);
331 return false;
332 }
333
334
335 int indFalsified = 0;
336 while ((lits[indFalsified] ^ 1) != p)
337 indFalsified++;
338 assert watchCumul > degree;
339
340
341 int indSwap = degree + 1;
342 while (indSwap < lits.length && voc.isFalsified(lits[indSwap]))
343 indSwap++;
344
345
346 if (indSwap == lits.length) {
347
348 voc.watch(p, this);
349
350 watchCumul--;
351 assert watchCumul == degree;
352 voc.undos(p).push(this);
353
354
355 for (int i = 0; i <= degree; i++)
356 if ((p != (lits[i] ^ 1)) && !s.enqueue(lits[i], this))
357 return false;
358
359 return true;
360 }
361
362 int tmpInt = lits[indSwap];
363 lits[indSwap] = lits[indFalsified];
364 lits[indFalsified] = tmpInt;
365
366
367 voc.watch(tmpInt ^ 1, this);
368
369 return true;
370 }
371
372
373
374
375
376
377 public void remove(UnitPropagationListener upl) {
378 for (int i = 0; i < Math.min(degree + 1, lits.length); i++) {
379 voc.watches(lits[i] ^ 1).remove(this);
380 }
381 }
382
383
384
385
386
387
388
389 public void rescaleBy(double d) {
390
391 }
392
393
394
395
396
397
398 public boolean simplify() {
399
400 for (int i = 0, count = 0; i < lits.length; i++)
401 if (voc.isSatisfied(lits[i]) && (++count == degree))
402 return true;
403
404 return false;
405 }
406
407
408
409
410
411
412 @Override
413 public String toString() {
414 StringBuffer stb = new StringBuffer();
415 stb.append("Card (" + lits.length + ") : ");
416 if (lits.length > 0) {
417
418 stb.append(Lits.toString(this.lits[0]));
419 stb.append("[");
420 stb.append(voc.valueToString(lits[0]));
421 stb.append("@");
422 stb.append(voc.getLevel(lits[0]));
423 stb.append("]");
424 stb.append(" ");
425
426 for (int i = 1; i < lits.length; i++) {
427
428 stb.append(" + ");
429 stb.append(Lits.toString(this.lits[i]));
430 stb.append("[");
431 stb.append(voc.valueToString(lits[i]));
432 stb.append("@");
433 stb.append(voc.getLevel(lits[i]));
434 stb.append("]");
435 stb.append(" ");
436
437 }
438 stb.append(">= ");
439 stb.append(this.degree);
440 }
441 return stb.toString();
442 }
443
444
445
446
447
448
449
450 public void undo(int p) {
451
452 watchCumul++;
453 }
454
455 public void setLearnt() {
456 throw new UnsupportedOperationException();
457 }
458
459 public void register() {
460 throw new UnsupportedOperationException();
461 }
462
463 public int size() {
464 return lits.length;
465 }
466
467 public int get(int i) {
468 return lits[i];
469 }
470
471 public void assertConstraint(UnitPropagationListener s) {
472 throw new UnsupportedOperationException();
473 }
474
475 protected void computeWatches() {
476 int indSwap = lits.length;
477 int tmpInt;
478 for (int i = 0; i <= degree && i < indSwap; i++) {
479 while (voc.isFalsified(lits[i]) && --indSwap > i) {
480 tmpInt = lits[i];
481 lits[i] = lits[indSwap];
482 lits[indSwap] = tmpInt;
483 }
484
485
486 if (!voc.isFalsified(lits[i])) {
487 watchCumul++;
488 voc.watch(lits[i] ^ 1, this);
489 }
490 }
491 if (learnt()) {
492
493
494 int free = 1;
495 while ((watchCumul <= degree) && (free > 0)) {
496 free = 0;
497
498 int maxlevel = -1, maxi = -1;
499 for (int i = watchCumul; i < lits.length; i++) {
500 if (voc.isFalsified(lits[i])) {
501 free++;
502 int level = voc.getLevel(lits[i]);
503 if (level > maxlevel) {
504 maxi = i;
505 maxlevel = level;
506 }
507 }
508 }
509 if (free > 0) {
510 assert maxi >= 0;
511 voc.watch(lits[maxi] ^ 1, this);
512 tmpInt = lits[maxi];
513 lits[maxi] = lits[watchCumul];
514 lits[watchCumul] = tmpInt;
515 watchCumul++;
516 free--;
517 assert free >= 0;
518 }
519 }
520 assert lits.length == 1 || watchCumul > 1;
521 }
522
523 }
524
525 protected MinWatchCard computePropagation(UnitPropagationListener s)
526 throws ContradictionException {
527
528
529 if (watchCumul == degree) {
530 for (int i = 0; i < lits.length; i++)
531 if (!s.enqueue(lits[i])) {
532 throw new ContradictionException();
533 }
534 return null;
535 }
536
537
538 if (watchCumul < degree) {
539 throw new ContradictionException();
540 }
541 return this;
542 }
543
544 public int[] getLits() {
545 int[] tmp = new int[size()];
546 System.arraycopy(lits, 0, tmp, 0, size());
547 return tmp;
548 }
549
550 public ILits getVocabulary() {
551 return voc;
552 }
553
554 @Override
555 public boolean equals(Object card) {
556 if (card == null) {
557 return false;
558 }
559 try {
560 MinWatchCard mcard = (MinWatchCard) card;
561 if (mcard.degree != degree)
562 return false;
563 if (lits.length != mcard.lits.length)
564 return false;
565 boolean ok;
566 for (int lit : lits) {
567 ok = false;
568 for (int lit2 : mcard.lits)
569 if (lit == lit2) {
570 ok = true;
571 break;
572 }
573 if (!ok)
574 return false;
575 }
576 return true;
577 } catch (ClassCastException e) {
578 return false;
579 }
580 }
581
582 @Override
583 public int hashCode() {
584 long sum = 0;
585 for (int p : lits) {
586 sum += p;
587 }
588 sum += degree;
589 return (int) sum / (lits.length + 1);
590 }
591
592
593
594
595 public void forwardActivity(double claInc) {
596
597 }
598
599 public boolean canBePropagatedMultipleTimes() {
600 return true;
601 }
602 }