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 import java.math.BigInteger;
32
33 import org.sat4j.minisat.constraints.cnf.Lits;
34 import org.sat4j.minisat.constraints.cnf.UnitClauses;
35 import org.sat4j.minisat.core.Constr;
36 import org.sat4j.minisat.core.ILits;
37 import org.sat4j.minisat.core.Undoable;
38 import org.sat4j.minisat.core.UnitPropagationListener;
39 import org.sat4j.specs.ContradictionException;
40 import org.sat4j.specs.IVecInt;
41
42 public final class MaxWatchCard implements Constr, Undoable, Serializable {
43
44 private static final long serialVersionUID = 1L;
45
46
47
48
49 private int degree;
50
51
52
53
54 private final int[] lits;
55
56
57
58
59 private boolean moreThan;
60
61
62
63
64 private int watchCumul;
65
66
67
68
69 private final ILits voc;
70
71
72
73
74
75
76
77
78
79 private MaxWatchCard(ILits voc, IVecInt ps, boolean moreThan, int degree) {
80
81
82 this.voc = voc;
83 this.degree = degree;
84 this.moreThan = moreThan;
85
86
87 int[] index = new int[voc.nVars() * 2 + 2];
88 for (int i = 0; i < index.length; i++)
89 index[i] = 0;
90
91 for (int i = 0; i < ps.size(); i++) {
92 if (index[ps.get(i) ^ 1] == 0) {
93 index[ps.get(i)]++;
94 } else {
95 index[ps.get(i) ^ 1]--;
96 }
97 }
98
99 int ind = 0;
100 while (ind < ps.size()) {
101 if (index[ps.get(ind)] > 0) {
102 index[ps.get(ind)]--;
103 ind++;
104 } else {
105 if ((ps.get(ind) & 1) != 0)
106 this.degree--;
107 ps.set(ind, ps.last());
108 ps.pop();
109 }
110 }
111
112
113 lits = new int[ps.size()];
114 ps.moveTo(lits);
115
116
117 normalize();
118
119
120 watchCumul = 0;
121
122
123 for (int i = 0; i < lits.length; i++) {
124
125 if (!voc.isFalsified(lits[i])) {
126 watchCumul++;
127 voc.watch(lits[i] ^ 1, this);
128 }
129 }
130 }
131
132
133
134
135
136
137
138
139
140
141 public void calcReason(int p, IVecInt outReason) {
142 for (int i = 0; i < lits.length; i++) {
143 if (voc.isFalsified(lits[i])) {
144 outReason.push(lits[i] ^ 1);
145 }
146 }
147 }
148
149
150
151
152
153
154
155 public double getActivity() {
156
157 return 0;
158 }
159
160
161
162
163
164
165
166
167 public void incActivity(double claInc) {
168
169 }
170
171
172
173
174
175
176
177 public boolean learnt() {
178
179 return false;
180 }
181
182
183
184
185
186
187
188 public boolean locked() {
189
190 return true;
191 }
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209 public static Constr maxWatchCardNew(UnitPropagationListener s, ILits voc,
210 IVecInt ps, boolean moreThan, int degree)
211 throws ContradictionException {
212
213 MaxWatchCard outclause = null;
214
215
216 if (ps.size() < degree) {
217 throw new ContradictionException(
218 "Creating trivially inconsistent constraint");
219 } else if (ps.size() == degree) {
220 for (int i = 0; i < ps.size(); i++)
221 if (!s.enqueue(ps.get(i))) {
222 throw new ContradictionException(
223 "Contradiction with implied literal");
224 }
225 return new UnitClauses(ps);
226 }
227
228
229 outclause = new MaxWatchCard(voc, ps, moreThan, degree);
230
231
232 if (outclause.degree <= 0)
233 return null;
234
235
236 if (outclause.watchCumul < outclause.degree)
237 throw new ContradictionException();
238
239
240 if (outclause.watchCumul == outclause.degree) {
241 for (int i = 0; i < outclause.lits.length; i++) {
242 if (!s.enqueue(outclause.lits[i])) {
243 throw new ContradictionException(
244 "Contradiction with implied literal");
245 }
246 }
247 return null;
248 }
249
250 return outclause;
251 }
252
253
254
255
256 public final void normalize() {
257
258 if (!moreThan) {
259
260 this.degree = 0 - this.degree;
261
262 for (int indLit = 0; indLit < lits.length; indLit++) {
263 lits[indLit] = lits[indLit] ^ 1;
264 this.degree++;
265 }
266 this.moreThan = true;
267 }
268 }
269
270
271
272
273
274
275
276
277
278
279 public boolean propagate(UnitPropagationListener s, int p) {
280
281
282 voc.watch(p, this);
283 assert !voc.isFalsified(p);
284
285
286 if (this.watchCumul == this.degree)
287 return false;
288
289
290 voc.undos(p).push(this);
291 watchCumul--;
292
293
294 if (watchCumul == degree) {
295 for (int q : lits) {
296 if (voc.isUnassigned(q) && !s.enqueue(q, this)) {
297 return false;
298 }
299 }
300 }
301 return true;
302 }
303
304
305
306
307 public void remove(UnitPropagationListener upl) {
308 for (int q : lits) {
309 voc.watches(q ^ 1).remove(this);
310 }
311 }
312
313
314
315
316
317
318
319 public void rescaleBy(double d) {
320 }
321
322
323
324
325
326
327 public boolean simplify() {
328
329 int i = 0;
330
331
332 int curr = watchCumul;
333
334
335 while (i < this.lits.length) {
336
337 if (voc.isUnassigned(lits[i++])) {
338 curr--;
339 if (curr < this.degree)
340 return false;
341 }
342 }
343
344 return false;
345 }
346
347
348
349
350
351
352 @Override
353 public String toString() {
354 StringBuffer stb = new StringBuffer();
355
356 if (lits.length > 0) {
357 if (voc.isUnassigned(lits[0])) {
358 stb.append(Lits.toString(this.lits[0]));
359 stb.append(" ");
360 }
361 for (int i = 1; i < lits.length; i++) {
362 if (voc.isUnassigned(lits[i])) {
363 stb.append(" + ");
364 stb.append(Lits.toString(this.lits[i]));
365 stb.append(" ");
366 }
367 }
368 stb.append(">= ");
369 stb.append(this.degree);
370 }
371 return stb.toString();
372 }
373
374
375
376
377
378
379
380 public void undo(int p) {
381 watchCumul++;
382 }
383
384 public void setLearnt() {
385 throw new UnsupportedOperationException();
386 }
387
388 public void register() {
389 throw new UnsupportedOperationException();
390 }
391
392 public int size() {
393 return lits.length;
394 }
395
396 public int get(int i) {
397 return lits[i];
398 }
399
400 public void assertConstraint(UnitPropagationListener s) {
401 throw new UnsupportedOperationException();
402 }
403
404
405
406
407
408
409 public BigInteger getCoef(int literal) {
410 return BigInteger.ONE;
411 }
412
413
414
415
416
417
418 public BigInteger getDegree() {
419 return BigInteger.valueOf(degree);
420 }
421
422 public ILits getVocabulary() {
423 return voc;
424 }
425
426
427
428
429 public void forwardActivity(double claInc) {
430
431
432 }
433
434 public boolean canBePropagatedMultipleTimes() {
435 return true;
436 }
437 }