View Javadoc

1   /*******************************************************************************
2    * SAT4J: a SATisfiability library for Java Copyright (C) 2004, 2012 Artois University and CNRS
3    *
4    * All rights reserved. This program and the accompanying materials
5    * are made available under the terms of the Eclipse Public License v1.0
6    * which accompanies this distribution, and is available at
7    *  http://www.eclipse.org/legal/epl-v10.html
8    *
9    * Alternatively, the contents of this file may be used under the terms of
10   * either the GNU Lesser General Public License Version 2.1 or later (the
11   * "LGPL"), in which case the provisions of the LGPL are applicable instead
12   * of those above. If you wish to allow use of your version of this file only
13   * under the terms of the LGPL, and not to allow others to use your version of
14   * this file under the terms of the EPL, indicate your decision by deleting
15   * the provisions above and replace them with the notice and other provisions
16   * required by the LGPL. If you do not delete the provisions above, a recipient
17   * may use your version of this file under the terms of the EPL or the LGPL.
18   *
19   * Based on the original MiniSat specification from:
20   *
21   * An extensible SAT solver. Niklas Een and Niklas Sorensson. Proceedings of the
22   * Sixth International Conference on Theory and Applications of Satisfiability
23   * Testing, LNCS 2919, pp 502-518, 2003.
24   *
25   * See www.minisat.se for the original solver in C++.
26   *
27   * Contributors:
28   *   CRIL - initial API and implementation
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   * @author leberre Contrainte de cardinalit?
48   */
49  public class AtLeast implements Propagatable, Constr, Undoable, Serializable {
50  
51      private static final long serialVersionUID = 1L;
52  
53      /** number of allowed falsified literal */
54      protected int maxUnsatisfied;
55  
56      /** current number of falsified literals */
57      private int counter;
58  
59      /**
60       * constraint literals
61       */
62      protected final int[] lits;
63  
64      protected final ILits voc;
65  
66      /**
67       * @param ps
68       *            a vector of literals
69       * @param degree
70       *            the minimal number of satisfied literals
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              // on verifie si le litteral est affecte
89              if (voc.isUnassigned(ps.get(i))) {
90                  // go to next literal
91                  i++;
92              } else {
93                  // Si le litteral est satisfait,
94                  // ?a revient ? baisser le degr?
95                  if (voc.isSatisfied(ps.get(i))) {
96                      degree--;
97                  }
98                  // dans tous les cas, s'il est assign?,
99                  // on enleve le ieme litteral
100                 ps.delete(i);
101             }
102         }
103 
104         // on trie le vecteur ps
105         ps.sortUnique();
106         // ?limine les clauses tautologiques
107         // deux litt?raux de signe oppos?s apparaissent dans la m?me
108         // clause
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      * @since 2.1
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      * @since 2.1
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      * (non-Javadoc)
151      * 
152      * @see Constr#propagate(Solver, Lit)
153      */
154     public boolean propagate(UnitPropagationListener s, int p) {
155         // remet la clause dans la liste des clauses regardees
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         // If no more can be false, enqueue the rest:
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      * (non-Javadoc)
178      * 
179      * @see Constr#simplify(Solver)
180      */
181     public boolean simplify() {
182         return false;
183     }
184 
185     /*
186      * (non-Javadoc)
187      * 
188      * @see Constr#undo(Solver, Lit)
189      */
190     public void undo(int p) {
191         this.counter--;
192     }
193 
194     /*
195      * (non-Javadoc)
196      * 
197      * @see Constr#calcReason(Solver, Lit, Vec)
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      * (non-Javadoc)
213      * 
214      * @see org.sat4j.minisat.datatype.Constr#learnt()
215      */
216     public boolean learnt() {
217         // Ces contraintes ne sont pas apprises pour le moment.
218         return false;
219     }
220 
221     /*
222      * (non-Javadoc)
223      * 
224      * @see org.sat4j.minisat.datatype.Constr#getActivity()
225      */
226     public double getActivity() {
227         return 0;
228     }
229 
230     public void setActivity(double d) {
231     }
232 
233     /*
234      * (non-Javadoc)
235      * 
236      * @see org.sat4j.minisat.datatype.Constr#incActivity(double)
237      */
238     public void incActivity(double claInc) {
239     }
240 
241     /*
242      * For learnt clauses only @author leberre
243      */
244     public boolean locked() {
245         // FIXME need to be adapted to AtLeast
246         // return lits[0].getReason() == this;
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      * Textual representation of the constraint
287      * 
288      * @return a string representing the constraint.
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             // if (voc.isUnassigned(lits[i])) {
296             stb.append(" + "); //$NON-NLS-1$
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(">= "); //$NON-NLS-1$
305         stb.append(size() - this.maxUnsatisfied);
306 
307         return stb.toString();
308     }
309 
310     /**
311      * @since 2.1
312      */
313     public void forwardActivity(double claInc) {
314         // TODO Auto-generated method stub
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 }