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
165
166 for (int i = 0; i < lits.length; i++) {
167
168 if (voc.isFalsified(lits[i])) {
169
170 outReason.push(lits[i] ^ 1);
171 }
172 }
173 }
174
175
176
177
178
179
180
181 public double getActivity() {
182
183 return 0;
184 }
185
186
187
188
189
190
191
192
193 public void incActivity(double claInc) {
194
195 }
196
197
198
199
200
201
202
203 public boolean learnt() {
204 return false;
205 }
206
207
208
209
210
211
212
213
214
215
216
217 protected static int linearisation(ILits voc, IVecInt ps) {
218
219 int modif = 0;
220
221 for (int i = 0; i < ps.size();) {
222
223 if (voc.isUnassigned(ps.get(i))) {
224 i++;
225 } else {
226
227
228 if (voc.isSatisfied(ps.get(i))) {
229 modif--;
230 }
231
232
233 ps.set(i, ps.last());
234 ps.pop();
235 }
236 }
237
238
239
240 assert modif <= 0;
241
242 return modif;
243 }
244
245
246
247
248
249
250
251 public boolean locked() {
252
253 return true;
254 }
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274 public static MinWatchCard minWatchCardNew(UnitPropagationListener s,
275 ILits voc, IVecInt ps, boolean moreThan, int degree)
276 throws ContradictionException {
277
278 int mydegree = degree + linearisation(voc, ps);
279
280 if (ps.size() == 0 && mydegree > 0) {
281 throw new ContradictionException();
282 } else if (ps.size() == mydegree || ps.size() <= 0) {
283 for (int i = 0; i < ps.size(); i++)
284 if (!s.enqueue(ps.get(i))) {
285 throw new ContradictionException();
286 }
287 return null;
288 }
289
290
291 MinWatchCard retour = new MinWatchCard(voc, ps, moreThan, mydegree);
292
293 if (retour.degree <= 0)
294 return null;
295
296 retour.computeWatches();
297
298 retour.computePropagation(s);
299
300 return retour;
301 }
302
303
304
305
306 public final void normalize() {
307
308 if (!moreThan) {
309
310 this.degree = 0 - this.degree;
311
312 for (int indLit = 0; indLit < lits.length; indLit++) {
313 lits[indLit] = lits[indLit] ^ 1;
314 this.degree++;
315 }
316 this.moreThan = true;
317 }
318 }
319
320
321
322
323
324
325
326
327
328
329 public boolean propagate(UnitPropagationListener s, int p) {
330
331
332 if (watchCumul == degree) {
333 voc.watch(p, this);
334 return false;
335 }
336
337
338 int indFalsified = 0;
339 while ((lits[indFalsified] ^ 1) != p)
340 indFalsified++;
341 assert watchCumul > degree;
342
343
344 int indSwap = degree + 1;
345 while (indSwap < lits.length && voc.isFalsified(lits[indSwap]))
346 indSwap++;
347
348
349 if (indSwap == lits.length) {
350
351 voc.watch(p, this);
352
353 watchCumul--;
354 assert watchCumul == degree;
355 voc.undos(p).push(this);
356
357
358 for (int i = 0; i <= degree; i++)
359 if ((p != (lits[i] ^ 1)) && !s.enqueue(lits[i], this))
360 return false;
361
362 return true;
363 }
364
365 int tmpInt = lits[indSwap];
366 lits[indSwap] = lits[indFalsified];
367 lits[indFalsified] = tmpInt;
368
369
370 voc.watch(tmpInt ^ 1, this);
371
372 return true;
373 }
374
375
376
377
378
379
380 public void remove(UnitPropagationListener upl) {
381 for (int i = 0; i <= degree; i++) {
382 voc.watches(lits[i] ^ 1).remove(this);
383 }
384 }
385
386
387
388
389
390
391
392 public void rescaleBy(double d) {
393
394 }
395
396
397
398
399
400
401 public boolean simplify() {
402
403 for (int i = 0, count = 0; i < lits.length; i++)
404 if (voc.isSatisfied(lits[i]) && (++count == degree))
405 return true;
406
407 return false;
408 }
409
410
411
412
413
414
415 @Override
416 public String toString() {
417 StringBuffer stb = new StringBuffer();
418 stb.append("Card (" + lits.length + ") : ");
419 if (lits.length > 0) {
420
421 stb.append(Lits.toString(this.lits[0]));
422 stb.append("[");
423 stb.append(voc.valueToString(lits[0]));
424 stb.append("@");
425 stb.append(voc.getLevel(lits[0]));
426 stb.append("]");
427 stb.append(" ");
428
429 for (int i = 1; i < lits.length; i++) {
430
431 stb.append(" + ");
432 stb.append(Lits.toString(this.lits[i]));
433 stb.append("[");
434 stb.append(voc.valueToString(lits[i]));
435 stb.append("@");
436 stb.append(voc.getLevel(lits[i]));
437 stb.append("]");
438 stb.append(" ");
439
440 }
441 stb.append(">= ");
442 stb.append(this.degree);
443 }
444 return stb.toString();
445 }
446
447
448
449
450
451
452
453 public void undo(int p) {
454
455 watchCumul++;
456 }
457
458 public void setLearnt() {
459 throw new UnsupportedOperationException();
460 }
461
462 public void register() {
463 throw new UnsupportedOperationException();
464 }
465
466 public int size() {
467 return lits.length;
468 }
469
470 public int get(int i) {
471 return lits[i];
472 }
473
474 public void assertConstraint(UnitPropagationListener s) {
475 throw new UnsupportedOperationException();
476 }
477
478 protected void computeWatches() {
479 int indSwap = lits.length;
480 int tmpInt;
481 for (int i = 0; i <= degree && i < indSwap; i++) {
482 while (voc.isFalsified(lits[i]) && --indSwap > i) {
483 tmpInt = lits[i];
484 lits[i] = lits[indSwap];
485 lits[indSwap] = tmpInt;
486 }
487
488
489 if (!voc.isFalsified(lits[i])) {
490 watchCumul++;
491 voc.watch(lits[i] ^ 1, this);
492 }
493 }
494 if (learnt()) {
495
496
497 int free = 1;
498 while ((watchCumul <= degree) && (free > 0)) {
499 free = 0;
500
501 int maxlevel = -1, maxi = -1;
502 for (int i = watchCumul; i < lits.length; i++) {
503 if (voc.isFalsified(lits[i])) {
504 free++;
505 int level = voc.getLevel(lits[i]);
506 if (level > maxlevel) {
507 maxi = i;
508 maxlevel = level;
509 }
510 }
511 }
512 if (free > 0) {
513 assert maxi >= 0;
514 voc.watch(lits[maxi] ^ 1, this);
515 tmpInt = lits[maxi];
516 lits[maxi] = lits[watchCumul];
517 lits[watchCumul] = tmpInt;
518 watchCumul++;
519 free--;
520 assert free >= 0;
521 }
522 }
523 assert lits.length == 1 || watchCumul > 1;
524 }
525
526 }
527
528 protected MinWatchCard computePropagation(UnitPropagationListener s)
529 throws ContradictionException {
530
531
532 if (watchCumul == degree) {
533 for (int i = 0; i < lits.length; i++)
534 if (!s.enqueue(lits[i])) {
535 throw new ContradictionException();
536 }
537 return null;
538 }
539
540
541 if (watchCumul < degree) {
542 throw new ContradictionException();
543 }
544 return this;
545 }
546
547 public int[] getLits() {
548 int[] tmp = new int[size()];
549 System.arraycopy(lits, 0, tmp, 0, size());
550 return tmp;
551 }
552
553 public ILits getVocabulary() {
554 return voc;
555 }
556
557 @Override
558 public boolean equals(Object card) {
559 if (card == null) {
560 return false;
561 }
562 try {
563 MinWatchCard mcard = (MinWatchCard) card;
564 if (mcard.degree != degree)
565 return false;
566 if (lits.length != mcard.lits.length)
567 return false;
568 boolean ok;
569 for (int lit : lits) {
570 ok = false;
571 for (int lit2 : mcard.lits)
572 if (lit == lit2) {
573 ok = true;
574 break;
575 }
576 if (!ok)
577 return false;
578 }
579 return true;
580 } catch (ClassCastException e) {
581 return false;
582 }
583 }
584
585 @Override
586 public int hashCode() {
587 long sum = 0;
588 for (int p : lits) {
589 sum += p;
590 }
591 sum += degree;
592 return (int) sum / (lits.length + 1);
593 }
594
595
596
597
598 public void forwardActivity(double claInc) {
599
600 }
601 }