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