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.pb.constraints.pb;
29
30 import java.math.BigInteger;
31
32 import org.sat4j.minisat.core.ILits;
33 import org.sat4j.minisat.core.UnitPropagationListener;
34 import org.sat4j.specs.ContradictionException;
35
36 public class MinWatchPb extends WatchPb {
37
38 private static final long serialVersionUID = 1L;
39
40
41
42
43 protected boolean[] watched;
44
45
46
47
48 protected int[] watching;
49
50
51
52
53 protected int watchingCount = 0;
54
55
56
57
58
59
60
61
62
63 protected MinWatchPb(ILits voc, IDataStructurePB mpb) {
64
65 super(mpb);
66 this.voc = voc;
67
68 watching = new int[this.coefs.length];
69 watched = new boolean[this.coefs.length];
70 activity = 0;
71 watchCumul = BigInteger.ZERO;
72 watchingCount = 0;
73
74 }
75
76 protected MinWatchPb(ILits voc, int[] lits, BigInteger[] coefs,
77 BigInteger degree) {
78
79 super(lits, coefs, degree);
80 this.voc = voc;
81
82 watching = new int[this.coefs.length];
83 watched = new boolean[this.coefs.length];
84 activity = 0;
85 watchCumul = BigInteger.ZERO;
86 watchingCount = 0;
87
88 }
89
90
91
92
93
94
95 @Override
96 protected void computeWatches() throws ContradictionException {
97 assert watchCumul.signum() == 0;
98 assert watchingCount == 0;
99 for (int i = 0; i < lits.length
100 && watchCumul.subtract(coefs[0]).compareTo(degree) < 0; i++) {
101 if (!voc.isFalsified(lits[i])) {
102 voc.watch(lits[i] ^ 1, this);
103 watching[watchingCount++] = i;
104 watched[i] = true;
105
106 watchCumul = watchCumul.add(coefs[i]);
107 }
108 }
109
110 if (learnt)
111 watchMoreForLearntConstraint();
112
113 if (watchCumul.compareTo(degree) < 0) {
114 throw new ContradictionException("non satisfiable constraint");
115 }
116 assert nbOfWatched() == watchingCount;
117 }
118
119 private void watchMoreForLearntConstraint() {
120
121
122 int free = 1;
123 int maxlevel, maxi, level;
124
125 while ((watchCumul.subtract(coefs[0]).compareTo(degree) < 0)
126 && (free > 0)) {
127 free = 0;
128
129 maxlevel = -1;
130 maxi = -1;
131 for (int i = 0; i < lits.length; i++) {
132 if (voc.isFalsified(lits[i]) && !watched[i]) {
133 free++;
134 level = voc.getLevel(lits[i]);
135 if (level > maxlevel) {
136 maxi = i;
137 maxlevel = level;
138 }
139 }
140 }
141
142 if (free > 0) {
143 assert maxi >= 0;
144 voc.watch(lits[maxi] ^ 1, this);
145 watching[watchingCount++] = maxi;
146 watched[maxi] = true;
147
148 watchCumul = watchCumul.add(coefs[maxi]);
149 free--;
150 assert free >= 0;
151 }
152 }
153 assert lits.length == 1 || watchingCount > 1;
154 }
155
156
157
158
159
160
161
162
163 @Override
164 protected void computePropagation(UnitPropagationListener s)
165 throws ContradictionException {
166
167 int ind = 0;
168 while (ind < lits.length
169 && watchCumul.subtract(coefs[watching[ind]]).compareTo(degree) < 0) {
170 if (voc.isUnassigned(lits[ind]) && !s.enqueue(lits[ind], this)) {
171 throw new ContradictionException("non satisfiable constraint");
172 }
173 ind++;
174 }
175 }
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191 public static MinWatchPb normalizedMinWatchPbNew(UnitPropagationListener s,
192 ILits voc, int[] lits, BigInteger[] coefs, BigInteger degree)
193 throws ContradictionException {
194
195 MinWatchPb outclause = new MinWatchPb(voc, lits, coefs, degree);
196
197 if (outclause.degree.signum() <= 0) {
198 return null;
199 }
200
201 outclause.computeWatches();
202
203 outclause.computePropagation(s);
204
205 return outclause;
206
207 }
208
209
210
211
212
213
214 protected int nbOfWatched() {
215 int retour = 0;
216 for (int ind = 0; ind < this.watched.length; ind++) {
217 for (int i = 0; i < watchingCount; i++)
218 if (watching[i] == ind)
219 assert watched[ind];
220 retour += (this.watched[ind]) ? 1 : 0;
221 }
222 return retour;
223 }
224
225
226
227
228
229
230
231
232
233
234 public boolean propagate(UnitPropagationListener s, int p) {
235 assert nbOfWatched() == watchingCount;
236 assert watchingCount > 1;
237
238
239 int pIndiceWatching = 0;
240 while (pIndiceWatching < watchingCount
241 && (lits[watching[pIndiceWatching]] ^ 1) != p)
242 pIndiceWatching++;
243 int pIndice = watching[pIndiceWatching];
244
245 assert p == (lits[pIndice] ^ 1);
246 assert watched[pIndice];
247
248
249
250 BigInteger maxCoef = maximalCoefficient(pIndice);
251
252
253 maxCoef = updateWatched(maxCoef, pIndice);
254
255 BigInteger upWatchCumul = watchCumul.subtract(coefs[pIndice]);
256 assert nbOfWatched() == watchingCount;
257
258
259 if (upWatchCumul.compareTo(degree) < 0) {
260
261 voc.watch(p, this);
262 assert watched[pIndice];
263 assert !isSatisfiable();
264 return false;
265 } else if (upWatchCumul.compareTo(degree.add(maxCoef)) < 0) {
266
267 assert watchingCount != 0;
268 BigInteger limit = upWatchCumul.subtract(degree);
269 for (int i = 0; i < watchingCount; i++) {
270 if (limit.compareTo(coefs[watching[i]]) < 0
271 && i != pIndiceWatching
272 && !voc.isSatisfied(lits[watching[i]])
273 && !s.enqueue(lits[watching[i]], this)) {
274 voc.watch(p, this);
275 assert !isSatisfiable();
276 return false;
277 }
278 }
279
280 voc.undos(p).push(this);
281 }
282
283
284 watched[pIndice] = false;
285 watchCumul = upWatchCumul;
286 watching[pIndiceWatching] = watching[--watchingCount];
287
288 assert watchingCount != 0;
289 assert nbOfWatched() == watchingCount;
290
291 return true;
292 }
293
294
295
296
297 public void remove(UnitPropagationListener upl) {
298 for (int i = 0; i < watchingCount; i++) {
299 voc.watches(lits[watching[i]] ^ 1).remove(this);
300 this.watched[this.watching[i]] = false;
301 }
302 watchingCount = 0;
303 assert nbOfWatched() == watchingCount;
304 }
305
306
307
308
309
310
311
312 public void undo(int p) {
313 voc.watch(p, this);
314 int pIndice = 0;
315 while ((lits[pIndice] ^ 1) != p)
316 pIndice++;
317
318 assert pIndice < lits.length;
319
320 watchCumul = watchCumul.add(coefs[pIndice]);
321
322 assert watchingCount == nbOfWatched();
323
324 watched[pIndice] = true;
325 watching[watchingCount++] = pIndice;
326
327 assert watchingCount == nbOfWatched();
328 }
329
330
331
332
333 public static WatchPb normalizedWatchPbNew(ILits voc, IDataStructurePB mpb) {
334 return new MinWatchPb(voc, mpb);
335 }
336
337
338
339
340
341
342
343
344 protected BigInteger maximalCoefficient(int pIndice) {
345 BigInteger maxCoef = BigInteger.ZERO;
346 for (int i = 0; i < watchingCount; i++)
347 if (coefs[watching[i]].compareTo(maxCoef) > 0
348 && watching[i] != pIndice) {
349 maxCoef = coefs[watching[i]];
350 }
351
352 assert learnt || maxCoef.signum() != 0;
353
354 return maxCoef;
355 }
356
357 protected BigInteger updateWatched(BigInteger mc, int pIndice) {
358 BigInteger maxCoef = mc;
359 if (watchingCount < size()) {
360 BigInteger upWatchCumul = watchCumul.subtract(coefs[pIndice]);
361
362 BigInteger degreePlusMaxCoef = degree.add(maxCoef);
363 for (int ind = 0; ind < lits.length; ind++) {
364 if (upWatchCumul.compareTo(degreePlusMaxCoef) >= 0) {
365
366 break;
367 }
368
369 if (!voc.isFalsified(lits[ind]) && !watched[ind]) {
370 upWatchCumul = upWatchCumul.add(coefs[ind]);
371 watched[ind] = true;
372 assert watchingCount < size();
373 watching[watchingCount++] = ind;
374 voc.watch(lits[ind] ^ 1, this);
375
376 if (coefs[ind].compareTo(maxCoef) > 0) {
377 maxCoef = coefs[ind];
378 degreePlusMaxCoef = degree.add(maxCoef);
379
380
381 }
382 }
383 }
384 watchCumul = upWatchCumul.add(coefs[pIndice]);
385 }
386 return maxCoef;
387 }
388
389 }