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.cnf;
29  
30  import java.io.Serializable;
31  
32  import org.sat4j.minisat.core.Constr;
33  import org.sat4j.minisat.core.ILits;
34  import org.sat4j.minisat.core.UnitPropagationListener;
35  import org.sat4j.specs.IVecInt;
36  
37  /**
38   * Lazy data structure for clause using Watched Literals.
39   * 
40   * @author leberre
41   */
42  public abstract class WLClause implements Constr, Serializable {
43  
44  	private static final long serialVersionUID = 1L;
45  
46  	/**
47  	 * @since 2.1
48  	 */
49  	protected double activity;
50  
51  	protected final int[] lits;
52  
53  	protected final ILits voc;
54  
55  	/**
56  	 * Creates a new basic clause
57  	 * 
58  	 * @param voc
59  	 *            the vocabulary of the formula
60  	 * @param ps
61  	 *            A VecInt that WILL BE EMPTY after calling that method.
62  	 */
63  	public WLClause(IVecInt ps, ILits voc) {
64  		lits = new int[ps.size()];
65  		ps.moveTo(lits);
66  		assert ps.size() == 0;
67  		this.voc = voc;
68  		activity = 0;
69  	}
70  
71  	/*
72  	 * (non-Javadoc)
73  	 * 
74  	 * @see Constr#calcReason(Solver, Lit, Vec)
75  	 */
76  	public void calcReason(int p, IVecInt outReason) {
77  		// assert outReason.size() == 0
78  		// && ((p == ILits.UNDEFINED) || (p == lits[0]));
79  		final int[] mylits = lits;
80  		for (int i = (p == ILits.UNDEFINED) ? 0 : 1; i < mylits.length; i++) {
81  			assert voc.isFalsified(mylits[i]);
82  			outReason.push(mylits[i] ^ 1);
83  		}
84  	}
85  
86  	/**
87  	 * @since 2.1
88  	 */
89  	public void remove(UnitPropagationListener upl) {
90  		voc.watches(lits[0] ^ 1).remove(this);
91  		voc.watches(lits[1] ^ 1).remove(this);
92  		// la clause peut etre effacee
93  	}
94  
95  	/*
96  	 * (non-Javadoc)
97  	 * 
98  	 * @see Constr#simplify(Solver)
99  	 */
100 	public boolean simplify() {
101 		for (int i = 0; i < lits.length; i++) {
102 			if (voc.isSatisfied(lits[i])) {
103 				return true;
104 			}
105 		}
106 		return false;
107 	}
108 
109 	public boolean propagate(UnitPropagationListener s, int p) {
110 		final int[] mylits = lits;
111 		// Lits[1] must contain a falsified literal
112 		if (mylits[0] == (p ^ 1)) {
113 			mylits[0] = mylits[1];
114 			mylits[1] = p ^ 1;
115 		}
116 		// assert mylits[1] == (p ^ 1);
117 		int previous = p ^ 1, tmp;
118 		// look for new literal to watch: applying move to front strategy
119 		for (int i = 2; i < mylits.length; i++) {
120 			if (!voc.isFalsified(mylits[i])) {
121 				mylits[1] = mylits[i];
122 				mylits[i] = previous;
123 				voc.watch(mylits[1] ^ 1, this);
124 				return true;
125 			} else {
126 				tmp = previous;
127 				previous = mylits[i];
128 				mylits[i] = tmp;
129 			}
130 		}
131 		// assert voc.isFalsified(mylits[1]);
132 		// the clause is now either unit or null
133 		// move back the literals to their initial position
134 		for (int i = 2; i < mylits.length; i++) {
135 			mylits[i - 1] = mylits[i];
136 		}
137 		mylits[mylits.length - 1] = previous;
138 		voc.watch(p, this);
139 		// propagates first watched literal
140 		return s.enqueue(mylits[0], this);
141 	}
142 
143 	/*
144 	 * For learnt clauses only @author leberre
145 	 */
146 	public boolean locked() {
147 		return voc.getReason(lits[0]) == this;
148 	}
149 
150 	/**
151 	 * @return the activity of the clause
152 	 */
153 	public double getActivity() {
154 		return activity;
155 	}
156 
157 	@Override
158 	public String toString() {
159 		StringBuffer stb = new StringBuffer();
160 		for (int i = 0; i < lits.length; i++) {
161 			stb.append(Lits.toString(lits[i]));
162 			stb.append("["); //$NON-NLS-1$
163 			stb.append(voc.valueToString(lits[i]));
164 			stb.append("]"); //$NON-NLS-1$
165 			stb.append(" "); //$NON-NLS-1$
166 		}
167 		return stb.toString();
168 	}
169 
170 	/**
171 	 * Retourne le ieme literal de la clause. Attention, cet ordre change durant
172 	 * la recherche.
173 	 * 
174 	 * @param i
175 	 *            the index of the literal
176 	 * @return the literal
177 	 */
178 	public int get(int i) {
179 		return lits[i];
180 	}
181 
182 	/**
183 	 * @param d
184 	 */
185 	public void rescaleBy(double d) {
186 		activity *= d;
187 	}
188 
189 	public int size() {
190 		return lits.length;
191 	}
192 
193 	public void assertConstraint(UnitPropagationListener s) {
194 		boolean ret = s.enqueue(lits[0], this);
195 		assert ret;
196 	}
197 
198 	public ILits getVocabulary() {
199 		return voc;
200 	}
201 
202 	public int[] getLits() {
203 		int[] tmp = new int[size()];
204 		System.arraycopy(lits, 0, tmp, 0, size());
205 		return tmp;
206 	}
207 
208 	@Override
209 	public boolean equals(Object obj) {
210 		if (obj == null)
211 			return false;
212 		try {
213 			WLClause wcl = (WLClause) obj;
214 			if (lits.length != wcl.lits.length)
215 				return false;
216 			boolean ok;
217 			for (int lit : lits) {
218 				ok = false;
219 				for (int lit2 : wcl.lits)
220 					if (lit == lit2) {
221 						ok = true;
222 						break;
223 					}
224 				if (!ok)
225 					return false;
226 			}
227 			return true;
228 		} catch (ClassCastException e) {
229 			return false;
230 		}
231 	}
232 
233 	@Override
234 	public int hashCode() {
235 		long sum = 0;
236 		for (int p : lits) {
237 			sum += p;
238 		}
239 		return (int) sum / lits.length;
240 	}
241 
242 	public boolean canBePropagatedMultipleTimes() {
243 		return false;
244 	}
245 }