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.minisat.core.UnitPropagationListener;
42  import org.sat4j.specs.ContradictionException;
43  import org.sat4j.specs.IVecInt;
44  import org.sat4j.specs.IteratorInt;
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     
282 
283 
284 
285 
286     @Override
287     public String toString() {
288         StringBuffer stb = new StringBuffer();
289         stb.append("Card (" + this.lits.length + ") : ");
290         for (int lit : this.lits) {
291             
292             stb.append(" + "); 
293             stb.append(Lits.toString(lit));
294             stb.append("[");
295             stb.append(this.voc.valueToString(lit));
296             stb.append("@");
297             stb.append(this.voc.getLevel(lit));
298             stb.append("]  ");
299         }
300         stb.append(">= "); 
301         stb.append(size() - this.maxUnsatisfied);
302 
303         return stb.toString();
304     }
305 
306     
307 
308 
309     public void forwardActivity(double claInc) {
310         
311 
312     }
313 
314     public boolean canBePropagatedMultipleTimes() {
315         return true;
316     }
317 
318     public Constr toConstraint() {
319         return this;
320     }
321 
322     public void calcReasonOnTheFly(int p, IVecInt trail, IVecInt outReason) {
323         int c = p == ILits.UNDEFINED ? -1 : 0;
324         IVecInt vlits = new VecInt(this.lits);
325         for (IteratorInt it = trail.iterator(); it.hasNext();) {
326             int q = it.next();
327             if (vlits.contains(q ^ 1)) {
328                 outReason.push(q);
329                 if (++c > this.maxUnsatisfied) {
330                     return;
331                 }
332             }
333         }
334     }
335 }