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.minisat.constraints.card;
31
32 import java.io.Serializable;
33
34 import org.sat4j.core.VecInt;
35 import org.sat4j.minisat.constraints.cnf.Lits;
36 import org.sat4j.minisat.constraints.cnf.UnitClauses;
37 import org.sat4j.minisat.core.Constr;
38 import org.sat4j.minisat.core.ILits;
39 import org.sat4j.minisat.core.Propagatable;
40 import org.sat4j.minisat.core.Undoable;
41 import org.sat4j.specs.ContradictionException;
42 import org.sat4j.specs.IVecInt;
43 import org.sat4j.specs.IteratorInt;
44 import org.sat4j.specs.UnitPropagationListener;
45
46
47
48
49 public class AtLeast implements Propagatable, Constr, Undoable, Serializable {
50
51 private static final long serialVersionUID = 1L;
52
53
54 protected int maxUnsatisfied;
55
56
57 private int counter;
58
59
60
61
62 protected final int[] lits;
63
64 protected final ILits voc;
65
66
67
68
69
70
71
72 public AtLeast(ILits voc, IVecInt ps, int degree) {
73 this.maxUnsatisfied = ps.size() - degree;
74 this.voc = voc;
75 this.counter = 0;
76 this.lits = new int[ps.size()];
77 ps.moveTo(this.lits);
78 }
79
80 protected static int niceParameters(UnitPropagationListener s, ILits voc,
81 IVecInt ps, int deg) throws ContradictionException {
82
83 if (ps.size() < deg) {
84 throw new ContradictionException();
85 }
86 int degree = deg;
87 for (int i = 0; i < ps.size();) {
88
89 if (voc.isUnassigned(ps.get(i))) {
90
91 i++;
92 } else {
93
94
95 if (voc.isSatisfied(ps.get(i))) {
96 degree--;
97 }
98
99
100 ps.delete(i);
101 }
102 }
103
104
105 ps.sortUnique();
106
107
108
109
110 if (ps.size() == degree) {
111 for (int i = 0; i < ps.size(); i++) {
112 if (!s.enqueue(ps.get(i))) {
113 throw new ContradictionException();
114 }
115 }
116 return 0;
117 }
118
119 if (ps.size() < degree) {
120 throw new ContradictionException();
121 }
122 return degree;
123
124 }
125
126
127
128
129 public static Constr atLeastNew(UnitPropagationListener s, ILits voc,
130 IVecInt ps, int n) throws ContradictionException {
131 int degree = niceParameters(s, voc, ps, n);
132 if (degree == 0) {
133 return new UnitClauses(ps);
134 }
135 Constr constr = new AtLeast(voc, ps, degree);
136 constr.register();
137 return constr;
138 }
139
140
141
142
143 public void remove(UnitPropagationListener upl) {
144 for (int q : this.lits) {
145 this.voc.watches(q ^ 1).remove(this);
146 }
147 }
148
149
150
151
152
153
154 public boolean propagate(UnitPropagationListener s, int p) {
155
156 this.voc.watch(p, this);
157
158 if (this.counter == this.maxUnsatisfied) {
159 return false;
160 }
161
162 this.counter++;
163 this.voc.undos(p).push(this);
164
165
166 if (this.counter == this.maxUnsatisfied) {
167 for (int q : this.lits) {
168 if (this.voc.isUnassigned(q) && !s.enqueue(q, this)) {
169 return false;
170 }
171 }
172 }
173 return true;
174 }
175
176
177
178
179
180
181 public boolean simplify() {
182 return false;
183 }
184
185
186
187
188
189
190 public void undo(int p) {
191 this.counter--;
192 }
193
194
195
196
197
198
199 public void calcReason(int p, IVecInt outReason) {
200 int c = p == ILits.UNDEFINED ? -1 : 0;
201 for (int q : this.lits) {
202 if (this.voc.isFalsified(q)) {
203 outReason.push(q ^ 1);
204 if (++c > this.maxUnsatisfied) {
205 return;
206 }
207 }
208 }
209 }
210
211
212
213
214
215
216 public boolean learnt() {
217
218 return false;
219 }
220
221
222
223
224
225
226 public double getActivity() {
227 return 0;
228 }
229
230 public void setActivity(double d) {
231 }
232
233
234
235
236
237
238 public void incActivity(double claInc) {
239 }
240
241
242
243
244 public boolean locked() {
245
246
247 return true;
248 }
249
250 public void setLearnt() {
251 throw new UnsupportedOperationException();
252 }
253
254 public void register() {
255 this.counter = 0;
256 for (int q : this.lits) {
257 voc.watch(q ^ 1, this);
258 if (voc.isFalsified(q)) {
259 this.counter++;
260 this.voc.undos(q ^ 1).push(this);
261 }
262 }
263 }
264
265 public int size() {
266 return this.lits.length;
267 }
268
269 public int get(int i) {
270 return this.lits[i];
271 }
272
273 public void rescaleBy(double d) {
274 throw new UnsupportedOperationException();
275 }
276
277 public void assertConstraint(UnitPropagationListener s) {
278 throw new UnsupportedOperationException();
279 }
280
281 public void assertConstraintIfNeeded(UnitPropagationListener s) {
282 throw new UnsupportedOperationException();
283 }
284
285
286
287
288
289
290 @Override
291 public String toString() {
292 StringBuffer stb = new StringBuffer();
293 stb.append("Card (" + this.lits.length + ") : ");
294 for (int lit : this.lits) {
295
296 stb.append(" + ");
297 stb.append(Lits.toString(lit));
298 stb.append("[");
299 stb.append(this.voc.valueToString(lit));
300 stb.append("@");
301 stb.append(this.voc.getLevel(lit));
302 stb.append("] ");
303 }
304 stb.append(">= ");
305 stb.append(size() - this.maxUnsatisfied);
306
307 return stb.toString();
308 }
309
310
311
312
313 public void forwardActivity(double claInc) {
314
315
316 }
317
318 public boolean canBePropagatedMultipleTimes() {
319 return true;
320 }
321
322 public Constr toConstraint() {
323 return this;
324 }
325
326 public void calcReasonOnTheFly(int p, IVecInt trail, IVecInt outReason) {
327 int c = p == ILits.UNDEFINED ? -1 : 0;
328 IVecInt vlits = new VecInt(this.lits);
329 for (IteratorInt it = trail.iterator(); it.hasNext();) {
330 int q = it.next();
331 if (vlits.contains(q ^ 1)) {
332 outReason.push(q);
333 if (++c > this.maxUnsatisfied) {
334 return;
335 }
336 }
337 }
338 }
339 }