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