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 		// if (voc.isSatisfied(lits[0])) {
118 		// // do not need to do anything if clause is satisfied
119 		// voc.watch(p, this);
120 		// return true;
121 		// }
122 
123 		// look for new literal to watch:
124 		for (int i = 2; i < mylits.length; i++) {
125 			if (!voc.isFalsified(mylits[i])) {
126 				mylits[1] = mylits[i];
127 				mylits[i] = p ^ 1;
128 				voc.watch(mylits[1] ^ 1, this);
129 				return true;
130 			}
131 		}
132 		// assert voc.isFalsified(mylits[1]);
133 		// the clause is now either unit or null
134 		voc.watch(p, this);
135 		// propagates first watched literal
136 		return s.enqueue(mylits[0], this);
137 	}
138 
139 	/*
140 	 * For learnt clauses only @author leberre
141 	 */
142 	public boolean locked() {
143 		return voc.getReason(lits[0]) == this;
144 	}
145 
146 	/**
147 	 * @return the activity of the clause
148 	 */
149 	public double getActivity() {
150 		return activity;
151 	}
152 
153 	@Override
154 	public String toString() {
155 		StringBuffer stb = new StringBuffer();
156 		for (int i = 0; i < lits.length; i++) {
157 			stb.append(Lits.toString(lits[i]));
158 			stb.append("["); //$NON-NLS-1$
159 			stb.append(voc.valueToString(lits[i]));
160 			stb.append("]"); //$NON-NLS-1$
161 			stb.append(" "); //$NON-NLS-1$
162 		}
163 		return stb.toString();
164 	}
165 
166 	/**
167 	 * Retourne le ieme literal de la clause. Attention, cet ordre change durant
168 	 * la recherche.
169 	 * 
170 	 * @param i
171 	 *            the index of the literal
172 	 * @return the literal
173 	 */
174 	public int get(int i) {
175 		return lits[i];
176 	}
177 
178 	/**
179 	 * @param d
180 	 */
181 	public void rescaleBy(double d) {
182 		activity *= d;
183 	}
184 
185 	public int size() {
186 		return lits.length;
187 	}
188 
189 	public void assertConstraint(UnitPropagationListener s) {
190 		boolean ret = s.enqueue(lits[0], this);
191 		assert ret;
192 	}
193 
194 	public ILits getVocabulary() {
195 		return voc;
196 	}
197 
198 	public int[] getLits() {
199 		int[] tmp = new int[size()];
200 		System.arraycopy(lits, 0, tmp, 0, size());
201 		return tmp;
202 	}
203 
204 	@Override
205 	public boolean equals(Object obj) {
206 		if (obj == null)
207 			return false;
208 		try {
209 			WLClause wcl = (WLClause) obj;
210 			if (lits.length != wcl.lits.length)
211 				return false;
212 			boolean ok;
213 			for (int lit : lits) {
214 				ok = false;
215 				for (int lit2 : wcl.lits)
216 					if (lit == lit2) {
217 						ok = true;
218 						break;
219 					}
220 				if (!ok)
221 					return false;
222 			}
223 			return true;
224 		} catch (ClassCastException e) {
225 			return false;
226 		}
227 	}
228 
229 	@Override
230 	public int hashCode() {
231 		long sum = 0;
232 		for (int p : lits) {
233 			sum += p;
234 		}
235 		return (int) sum / lits.length;
236 	}
237 
238 }