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 import java.math.BigInteger;
30
31 import org.sat4j.minisat.constraints.cnf.Lits;
32 import org.sat4j.minisat.core.Constr;
33 import org.sat4j.minisat.core.ILits;
34 import org.sat4j.minisat.core.Undoable;
35 import org.sat4j.minisat.core.UnitPropagationListener;
36 import org.sat4j.specs.ContradictionException;
37 import org.sat4j.specs.IVecInt;
38
39 public class MaxWatchCard implements Constr, Undoable, Serializable {
40
41 private static final long serialVersionUID = 1L;
42
43
44
45
46 private int degree;
47
48
49
50
51 private int[] lits;
52
53
54
55
56 private boolean moreThan;
57
58
59
60
61 private int watchCumul;
62
63
64
65
66 private final ILits voc;
67
68
69
70
71
72
73
74
75
76 private MaxWatchCard(ILits voc, IVecInt ps, boolean moreThan, int degree) {
77
78
79 this.voc = voc;
80 this.degree = degree;
81 this.moreThan = moreThan;
82
83
84 int[] index = new int[voc.nVars() * 2 + 2];
85 for (int i = 0; i < index.length; i++)
86 index[i] = 0;
87
88 for (int i = 0; i < ps.size(); i++) {
89 if (index[ps.get(i) ^ 1] == 0) {
90 index[ps.get(i)]++;
91 } else {
92 index[ps.get(i) ^ 1]--;
93 }
94 }
95
96 int ind = 0;
97 while (ind < ps.size()) {
98 if (index[ps.get(ind)] > 0) {
99 index[ps.get(ind)]--;
100 ind++;
101 } else {
102 if ((ps.get(ind) & 1) != 0)
103 this.degree--;
104 ps.set(ind, ps.last());
105 ps.pop();
106 }
107 }
108
109
110 lits = new int[ps.size()];
111 ps.moveTo(lits);
112
113
114 normalize();
115
116
117 watchCumul = 0;
118
119
120 for (int i = 0; i < lits.length; i++) {
121
122 if (!voc.isFalsified(lits[i])) {
123 watchCumul++;
124 voc.watch(lits[i] ^ 1, this);
125 }
126 }
127 }
128
129
130
131
132
133
134
135
136
137
138 public void calcReason(int p, IVecInt outReason) {
139
140
141 for (int i = 0; i < lits.length; i++) {
142
143 if (voc.isFalsified(lits[i])) {
144
145 outReason.push(lits[i] ^ 1);
146 }
147 }
148 }
149
150
151
152
153
154
155
156 public double getActivity() {
157
158 return 0;
159 }
160
161
162
163
164
165
166
167
168 public void incActivity(double claInc) {
169
170 }
171
172
173
174
175
176
177
178 public boolean learnt() {
179
180 return false;
181 }
182
183
184
185
186
187
188
189 public boolean locked() {
190
191 return true;
192 }
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210 public static MaxWatchCard maxWatchCardNew(UnitPropagationListener s,
211 ILits voc, IVecInt ps, boolean moreThan, int degree)
212 throws ContradictionException {
213
214 MaxWatchCard outclause = null;
215
216
217 if (ps.size() == 0) {
218 throw new ContradictionException("Creating empty clause");
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 null;
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() {
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 }