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 package org.sat4j.minisat.constraints.card;
27
28 import java.io.Serializable;
29
30 import org.sat4j.minisat.constraints.cnf.Lits;
31 import org.sat4j.minisat.core.Constr;
32 import org.sat4j.minisat.core.ILits;
33 import org.sat4j.minisat.core.Undoable;
34 import org.sat4j.minisat.core.UnitPropagationListener;
35 import org.sat4j.specs.ContradictionException;
36 import org.sat4j.specs.IVecInt;
37
38 public class MinWatchCard implements Constr, Undoable, Serializable {
39
40 private static final long serialVersionUID = 1L;
41
42 public static final boolean ATLEAST = true;
43
44 public static final boolean ATMOST = false;
45
46
47
48
49 protected int degree;
50
51
52
53
54 private int[] lits;
55
56
57
58
59 private boolean moreThan;
60
61
62
63
64 protected int watchCumul;
65
66
67
68
69 private final ILits voc;
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 public MinWatchCard(ILits voc, IVecInt ps, boolean moreThan, int degree) {
85
86 this.voc = voc;
87 this.degree = degree;
88 this.moreThan = moreThan;
89
90
91 int[] index = new int[voc.nVars() * 2 + 2];
92 for (int i = 0; i < index.length; i++)
93 index[i] = 0;
94
95 for (int i = 0; i < ps.size(); i++) {
96 if (index[ps.get(i) ^ 1] == 0) {
97 index[ps.get(i)]++;
98 } else {
99 index[ps.get(i) ^ 1]--;
100 }
101 }
102
103 int ind = 0;
104 while (ind < ps.size()) {
105 if (index[ps.get(ind)] > 0) {
106 index[ps.get(ind)]--;
107 ind++;
108 } else {
109
110 if ((ps.get(ind) & 1) != 0)
111 this.degree--;
112 ps.set(ind, ps.last());
113 ps.pop();
114 }
115 }
116
117
118 lits = new int[ps.size()];
119 ps.moveTo(lits);
120
121
122 normalize();
123
124 }
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 protected MinWatchCard(ILits voc, IVecInt ps, int degree) {
140
141 this.voc = voc;
142 this.degree = degree;
143 this.moreThan = ATLEAST;
144
145
146 lits = new int[ps.size()];
147 ps.moveTo(lits);
148
149 }
150
151
152
153
154
155
156
157
158
159
160 public void calcReason(int p, IVecInt outReason) {
161
162
163 for (int i = 0; i < lits.length; i++) {
164
165 if (voc.isFalsified(lits[i])) {
166
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 MinWatchCard minWatchCardNew(UnitPropagationListener s,
272 ILits voc, IVecInt ps, boolean moreThan, int degree)
273 throws ContradictionException {
274
275 int mydegree = degree + linearisation(voc, ps);
276
277 if (ps.size() == 0 && mydegree > 0) {
278 throw new ContradictionException();
279 } else if (ps.size() == mydegree || ps.size() <= 0) {
280 for (int i = 0; i < ps.size(); i++)
281 if (!s.enqueue(ps.get(i))) {
282 throw new ContradictionException();
283 }
284 return null;
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 public void remove() {
376 for (int i = 0; i <= degree; i++) {
377 voc.watches(lits[i] ^ 1).remove(this);
378 }
379 }
380
381
382
383
384
385
386
387 public void rescaleBy(double d) {
388
389 }
390
391
392
393
394
395
396 public boolean simplify() {
397
398 for (int i = 0, count = 0; i < lits.length; i++)
399 if (voc.isSatisfied(lits[i]) && (++count == degree))
400 return true;
401
402 return false;
403 }
404
405
406
407
408
409
410 @Override
411 public String toString() {
412 StringBuffer stb = new StringBuffer();
413 stb.append("Card (" + lits.length + ") : ");
414 if (lits.length > 0) {
415
416 stb.append(Lits.toString(this.lits[0]));
417 stb.append("[");
418 stb.append(voc.valueToString(lits[0]));
419 stb.append("@");
420 stb.append(voc.getLevel(lits[0]));
421 stb.append("]");
422 stb.append(" ");
423
424 for (int i = 1; i < lits.length; i++) {
425
426 stb.append(" + ");
427 stb.append(Lits.toString(this.lits[i]));
428 stb.append("[");
429 stb.append(voc.valueToString(lits[i]));
430 stb.append("@");
431 stb.append(voc.getLevel(lits[i]));
432 stb.append("]");
433 stb.append(" ");
434
435 }
436 stb.append(">= ");
437 stb.append(this.degree);
438 }
439 return stb.toString();
440 }
441
442
443
444
445
446
447
448 public void undo(int p) {
449
450 watchCumul++;
451 }
452
453 public void setLearnt() {
454 throw new UnsupportedOperationException();
455 }
456
457 public void register() {
458 throw new UnsupportedOperationException();
459 }
460
461 public int size() {
462 return lits.length;
463 }
464
465 public int get(int i) {
466 return lits[i];
467 }
468
469 public void assertConstraint(UnitPropagationListener s) {
470 throw new UnsupportedOperationException();
471 }
472
473 protected void computeWatches() {
474 int indSwap = lits.length;
475 int tmpInt;
476 for (int i = 0; i <= degree && i < indSwap; i++) {
477 while (voc.isFalsified(lits[i]) && --indSwap > i) {
478 tmpInt = lits[i];
479 lits[i] = lits[indSwap];
480 lits[indSwap] = tmpInt;
481 }
482
483
484 if (!voc.isFalsified(lits[i])) {
485 watchCumul++;
486 voc.watch(lits[i] ^ 1, this);
487 }
488 }
489 if (learnt()) {
490
491
492 int free = 1;
493 while ((watchCumul <= degree) && (free > 0)) {
494 free = 0;
495
496 int maxlevel = -1, maxi = -1;
497 for (int i = watchCumul; i < lits.length; i++) {
498 if (voc.isFalsified(lits[i])) {
499 free++;
500 int level = voc.getLevel(lits[i]);
501 if (level > maxlevel) {
502 maxi = i;
503 maxlevel = level;
504 }
505 }
506 }
507 if (free > 0) {
508 assert maxi >= 0;
509 voc.watch(lits[maxi] ^ 1, this);
510 tmpInt = lits[maxi];
511 lits[maxi] = lits[watchCumul];
512 lits[watchCumul] = tmpInt;
513 watchCumul++;
514 free--;
515 assert free >= 0;
516 }
517 }
518 assert lits.length == 1 || watchCumul > 1;
519 }
520
521 }
522
523 protected MinWatchCard computePropagation(UnitPropagationListener s)
524 throws ContradictionException {
525
526
527 if (watchCumul == degree) {
528 for (int i = 0; i < lits.length; i++)
529 if (!s.enqueue(lits[i])) {
530 throw new ContradictionException();
531 }
532 return null;
533 }
534
535
536 if (watchCumul < degree) {
537 throw new ContradictionException();
538 }
539 return this;
540 }
541
542 public int[] getLits() {
543 int[] tmp = new int[size()];
544 System.arraycopy(lits, 0, tmp, 0, size());
545 return tmp;
546 }
547
548 public ILits getVocabulary() {
549 return voc;
550 }
551 }