View Javadoc

1   /*******************************************************************************
2    * SAT4J: a SATisfiability library for Java Copyright (C) 2004-2008 Daniel Le Berre
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   *******************************************************************************/
28  package org.sat4j.minisat.constraints.card;
29  
30  import java.io.Serializable;
31  import java.math.BigInteger;
32  
33  import org.sat4j.minisat.constraints.cnf.Lits;
34  import org.sat4j.minisat.constraints.cnf.UnitClauses;
35  import org.sat4j.minisat.core.Constr;
36  import org.sat4j.minisat.core.ILits;
37  import org.sat4j.minisat.core.Undoable;
38  import org.sat4j.minisat.core.UnitPropagationListener;
39  import org.sat4j.specs.ContradictionException;
40  import org.sat4j.specs.IVecInt;
41  
42  public final class MaxWatchCard implements Constr, Undoable, Serializable {
43  
44  	private static final long serialVersionUID = 1L;
45  
46  	/**
47  	 * Degr? de la contrainte de cardinalit?
48  	 */
49  	private int degree;
50  
51  	/**
52  	 * Liste des litt?raux de la contrainte
53  	 */
54  	private final int[] lits;
55  
56  	/**
57  	 * D?termine si c'est une in?galit? sup?rieure ou ?gale
58  	 */
59  	private boolean moreThan;
60  
61  	/**
62  	 * Somme des coefficients des litt?raux observ?s
63  	 */
64  	private int watchCumul;
65  
66  	/**
67  	 * Vocabulaire de la contrainte
68  	 */
69  	private final ILits voc;
70  
71  	/**
72  	 * Constructeur de base cr?ant des contraintes vides
73  	 * 
74  	 * @param size
75  	 *            nombre de litt?raux de la contrainte
76  	 * @param learnt
77  	 *            indique si la contrainte est apprise
78  	 */
79  	private MaxWatchCard(ILits voc, IVecInt ps, boolean moreThan, int degree) {
80  
81  		// On met en place les valeurs
82  		this.voc = voc;
83  		this.degree = degree;
84  		this.moreThan = moreThan;
85  
86  		// On simplifie ps
87  		int[] index = new int[voc.nVars() * 2 + 2];
88  		for (int i = 0; i < index.length; i++)
89  			index[i] = 0;
90  		// On repertorie les litt?raux utiles
91  		for (int i = 0; i < ps.size(); i++) {
92  			if (index[ps.get(i) ^ 1] == 0) {
93  				index[ps.get(i)]++;
94  			} else {
95  				index[ps.get(i) ^ 1]--;
96  			}
97  		}
98  		// On supprime les litt?raux inutiles
99  		int ind = 0;
100 		while (ind < ps.size()) {
101 			if (index[ps.get(ind)] > 0) {
102 				index[ps.get(ind)]--;
103 				ind++;
104 			} else {
105 				if ((ps.get(ind) & 1) != 0)
106 					this.degree--;
107 				ps.set(ind, ps.last());
108 				ps.pop();
109 			}
110 		}
111 
112 		// On copie les litt?raux de la contrainte
113 		lits = new int[ps.size()];
114 		ps.moveTo(lits);
115 
116 		// On normalise la contrainte au sens de Barth
117 		normalize();
118 
119 		// Mise en place de l'observation maximale
120 		watchCumul = 0;
121 
122 		// On observe les litt?raux non falsifi?
123 		for (int i = 0; i < lits.length; i++) {
124 			// Rappel: les ?l?ments falsifi?s ne seront jamais d?pil?s
125 			if (!voc.isFalsified(lits[i])) {
126 				watchCumul++;
127 				voc.watch(lits[i] ^ 1, this);
128 			}
129 		}
130 	}
131 
132 	/**
133 	 * Calcule la cause de l'affection d'un litt?ral
134 	 * 
135 	 * @param p
136 	 *            un litt?ral falsifi? (ou Lit.UNDEFINED)
137 	 * @param outReason
138 	 *            vecteur de litt?raux ? remplir
139 	 * @see Constr#calcReason(int p, IVecInt outReason)
140 	 */
141 	public void calcReason(int p, IVecInt outReason) {
142 		for (int i = 0; i < lits.length; i++) {
143 			if (voc.isFalsified(lits[i])) {
144 				outReason.push(lits[i] ^ 1);
145 			}
146 		}
147 	}
148 
149 	/**
150 	 * Obtenir la valeur de l'activit? de la contrainte
151 	 * 
152 	 * @return la valeur de l'activit? de la contrainte
153 	 * @see Constr#getActivity()
154 	 */
155 	public double getActivity() {
156 		// TODO getActivity
157 		return 0;
158 	}
159 
160 	/**
161 	 * Incr?mente la valeur de l'activit? de la contrainte
162 	 * 
163 	 * @param claInc
164 	 *            incr?ment de l'activit? de la contrainte
165 	 * @see Constr#incActivity(double claInc)
166 	 */
167 	public void incActivity(double claInc) {
168 		// TODO incActivity
169 	}
170 
171 	/**
172 	 * D?termine si la contrainte est apprise
173 	 * 
174 	 * @return true si la contrainte est apprise, false sinon
175 	 * @see Constr#learnt()
176 	 */
177 	public boolean learnt() {
178 		// TODO learnt
179 		return false;
180 	}
181 
182 	/**
183 	 * La contrainte est la cause d'une propagation unitaire
184 	 * 
185 	 * @return true si c'est le cas, false sinon
186 	 * @see Constr#locked()
187 	 */
188 	public boolean locked() {
189 		// TODO locked
190 		return true;
191 	}
192 
193 	/**
194 	 * Permet la cr?ation de contrainte de cardinalit? ? observation minimale
195 	 * 
196 	 * @param s
197 	 *            outil pour la propagation des litt?raux
198 	 * @param voc
199 	 *            vocabulaire utilis? par la contrainte
200 	 * @param ps
201 	 *            liste des litt?raux de la nouvelle contrainte
202 	 * @param moreThan
203 	 *            d?termine si c'est une sup?rieure ou ?gal ? l'origine
204 	 * @param degree
205 	 *            fournit le degr? de la contrainte
206 	 * @return une nouvelle clause si tout va bien, null sinon
207 	 * @throws ContradictionException
208 	 */
209 	public static Constr maxWatchCardNew(UnitPropagationListener s, ILits voc,
210 			IVecInt ps, boolean moreThan, int degree)
211 			throws ContradictionException {
212 
213 		MaxWatchCard outclause = null;
214 
215 		// La contrainte ne doit pas ?tre vide
216 		if (ps.size() < degree) {
217 			throw new ContradictionException(
218 					"Creating trivially inconsistent constraint"); //$NON-NLS-1$
219 		} else if (ps.size() == degree) {
220 			for (int i = 0; i < ps.size(); i++)
221 				if (!s.enqueue(ps.get(i))) {
222 					throw new ContradictionException(
223 							"Contradiction with implied literal"); //$NON-NLS-1$
224 				}
225 			return new UnitClauses(ps);
226 		}
227 
228 		// On cree la contrainte
229 		outclause = new MaxWatchCard(voc, ps, moreThan, degree);
230 
231 		// Si le degr? est insufisant
232 		if (outclause.degree <= 0)
233 			return null;
234 
235 		// Si il n'y a aucune chance de satisfaire la contrainte
236 		if (outclause.watchCumul < outclause.degree)
237 			throw new ContradictionException();
238 
239 		// Si les litt?raux observ?s sont impliqu?s
240 		if (outclause.watchCumul == outclause.degree) {
241 			for (int i = 0; i < outclause.lits.length; i++) {
242 				if (!s.enqueue(outclause.lits[i])) {
243 					throw new ContradictionException(
244 							"Contradiction with implied literal"); //$NON-NLS-1$
245 				}
246 			}
247 			return null;
248 		}
249 
250 		return outclause;
251 	}
252 
253 	/**
254 	 * On normalise la contrainte au sens de Barth
255 	 */
256 	public final void normalize() {
257 		// Gestion du signe
258 		if (!moreThan) {
259 			// On multiplie le degr? par -1
260 			this.degree = 0 - this.degree;
261 			// On r?vise chaque litt?ral
262 			for (int indLit = 0; indLit < lits.length; indLit++) {
263 				lits[indLit] = lits[indLit] ^ 1;
264 				this.degree++;
265 			}
266 			this.moreThan = true;
267 		}
268 	}
269 
270 	/**
271 	 * Propagation de la valeur de v?rit? d'un litt?ral falsifi?
272 	 * 
273 	 * @param s
274 	 *            objet utilis? pour la propagation
275 	 * @param p
276 	 *            le litt?ral propag? (il doit etre falsifie)
277 	 * @return false ssi une inconsistance est d?t?ct?e
278 	 */
279 	public boolean propagate(UnitPropagationListener s, int p) {
280 
281 		// On observe toujours tous les litt?raux
282 		voc.watch(p, this);
283 		assert !voc.isFalsified(p);
284 
285 		// Si le litt?ral p est impliqu?
286 		if (this.watchCumul == this.degree)
287 			return false;
288 
289 		// On met en place la mise ? jour du compteur
290 		voc.undos(p).push(this);
291 		watchCumul--;
292 
293 		// Si les litt?raux restant sont impliqu?s
294 		if (watchCumul == degree) {
295 			for (int q : lits) {
296 				if (voc.isUnassigned(q) && !s.enqueue(q, this)) {
297 					return false;
298 				}
299 			}
300 		}
301 		return true;
302 	}
303 
304 	/**
305 	 * @since 2.1
306 	 */
307 	public void remove(UnitPropagationListener upl) {
308 		for (int q : lits) {
309 			voc.watches(q ^ 1).remove(this);
310 		}
311 	}
312 
313 	/**
314 	 * Permet le r??chantillonage de l'activit? de la contrainte
315 	 * 
316 	 * @param d
317 	 *            facteur d'ajustement
318 	 */
319 	public void rescaleBy(double d) {
320 	}
321 
322 	/**
323 	 * Simplifie la contrainte(l'all?ge)
324 	 * 
325 	 * @return true si la contrainte est satisfaite, false sinon
326 	 */
327 	public boolean simplify() {
328 
329 		int i = 0;
330 
331 		// On esp?re le maximum de la somme
332 		int curr = watchCumul;
333 
334 		// Pour chaque litt?ral
335 		while (i < this.lits.length) {
336 			// On d?cr?mente si l'espoir n'est pas fond?
337 			if (voc.isUnassigned(lits[i++])) {
338 				curr--;
339 				if (curr < this.degree)
340 					return false;
341 			}
342 		}
343 
344 		return false;
345 	}
346 
347 	/**
348 	 * Cha?ne repr?sentant la contrainte
349 	 * 
350 	 * @return Cha?ne repr?sentant la contrainte
351 	 */
352 	@Override
353 	public String toString() {
354 		StringBuffer stb = new StringBuffer();
355 
356 		if (lits.length > 0) {
357 			if (voc.isUnassigned(lits[0])) {
358 				stb.append(Lits.toString(this.lits[0]));
359 				stb.append(" "); //$NON-NLS-1$
360 			}
361 			for (int i = 1; i < lits.length; i++) {
362 				if (voc.isUnassigned(lits[i])) {
363 					stb.append(" + "); //$NON-NLS-1$
364 					stb.append(Lits.toString(this.lits[i]));
365 					stb.append(" "); //$NON-NLS-1$
366 				}
367 			}
368 			stb.append(">= "); //$NON-NLS-1$
369 			stb.append(this.degree);
370 		}
371 		return stb.toString();
372 	}
373 
374 	/**
375 	 * M?thode appel?e lors du backtrack
376 	 * 
377 	 * @param p
378 	 *            le litt?ral d?saffect?
379 	 */
380 	public void undo(int p) {
381 		watchCumul++;
382 	}
383 
384 	public void setLearnt() {
385 		throw new UnsupportedOperationException();
386 	}
387 
388 	public void register() {
389 		throw new UnsupportedOperationException();
390 	}
391 
392 	public int size() {
393 		return lits.length;
394 	}
395 
396 	public int get(int i) {
397 		return lits[i];
398 	}
399 
400 	public void assertConstraint(UnitPropagationListener s) {
401 		throw new UnsupportedOperationException();
402 	}
403 
404 	/*
405 	 * (non-Javadoc)
406 	 * 
407 	 * @see org.sat4j.minisat.constraints.pb.PBConstr#getCoefficient(int)
408 	 */
409 	public BigInteger getCoef(int literal) {
410 		return BigInteger.ONE;
411 	}
412 
413 	/*
414 	 * (non-Javadoc)
415 	 * 
416 	 * @see org.sat4j.minisat.constraints.pb.PBConstr#getDegree()
417 	 */
418 	public BigInteger getDegree() {
419 		return BigInteger.valueOf(degree);
420 	}
421 
422 	public ILits getVocabulary() {
423 		return voc;
424 	}
425 
426 	/**
427 	 * @since 2.1
428 	 */
429 	public void forwardActivity(double claInc) {
430 		// TODO Auto-generated method stub
431 
432 	}
433 
434 	public boolean canBePropagatedMultipleTimes() {
435 		return true;
436 	}
437 }