View Javadoc

1   package org.sat4j.multicore;
2   
3   import java.io.PrintStream;
4   import java.io.PrintWriter;
5   import java.util.ArrayList;
6   import java.util.List;
7   import java.util.Map;
8   
9   import org.sat4j.core.ASolverFactory;
10  import org.sat4j.core.VecInt;
11  import org.sat4j.specs.ContradictionException;
12  import org.sat4j.specs.IConstr;
13  import org.sat4j.specs.ISolver;
14  import org.sat4j.specs.IVec;
15  import org.sat4j.specs.IVecInt;
16  import org.sat4j.specs.SearchListener;
17  import org.sat4j.specs.TimeoutException;
18  import org.sat4j.tools.ConstrGroup;
19  
20  public class ManyCore<S extends ISolver> implements ISolver, OutcomeListener {
21  
22  	/**
23  	 * 
24  	 */
25  	private static final long serialVersionUID = 1L;
26  
27  	private final String[] availableSolvers; // = { };
28  
29  	protected final List<S> solvers;
30  	protected final int numberOfSolvers;
31  	private int winnerId;
32  	private boolean resultFound;
33  	private volatile int remainingSolvers;
34  
35  	private volatile boolean solved;
36  
37  	public ManyCore(ASolverFactory<S> factory, String... solverNames) {
38  		availableSolvers = solverNames;
39  		Runtime runtime = Runtime.getRuntime();
40  		long memory = runtime.maxMemory();
41  		int numberOfCores = runtime.availableProcessors();
42  		if (memory > 500000000L) {
43  			numberOfSolvers = solverNames.length < numberOfCores ? solverNames.length
44  					: numberOfCores;
45  		} else {
46  			numberOfSolvers = 1;
47  		}
48  		solvers = new ArrayList<S>(numberOfSolvers);
49  		for (int i = 0; i < numberOfSolvers; i++) {
50  			solvers.add(factory.createSolverByName(availableSolvers[i]));
51  		}
52  	}
53  
54  	public void addAllClauses(IVec<IVecInt> clauses)
55  			throws ContradictionException {
56  		for (int i = 0; i < numberOfSolvers; i++) {
57  			solvers.get(i).addAllClauses(clauses);
58  		}
59  	}
60  
61  	public IConstr addAtLeast(IVecInt literals, int degree)
62  			throws ContradictionException {
63  		ConstrGroup group = new ConstrGroup();
64  		for (int i = 0; i < numberOfSolvers; i++) {
65  			group.add(solvers.get(i).addAtLeast(literals, degree));
66  		}
67  		return group;
68  	}
69  
70  	public IConstr addAtMost(IVecInt literals, int degree)
71  			throws ContradictionException {
72  		ConstrGroup group = new ConstrGroup();
73  		for (int i = 0; i < numberOfSolvers; i++) {
74  			group.add(solvers.get(i).addAtMost(literals, degree));
75  		}
76  		return group;
77  	}
78  
79  	public IConstr addClause(IVecInt literals) throws ContradictionException {
80  		ConstrGroup group = new ConstrGroup();
81  		for (int i = 0; i < numberOfSolvers; i++) {
82  			group.add(solvers.get(i).addClause(literals));
83  		}
84  		return group;
85  	}
86  
87  	public void clearLearntClauses() {
88  		for (int i = 0; i < numberOfSolvers; i++) {
89  			solvers.get(i).clearLearntClauses();
90  		}
91  	}
92  
93  	public void expireTimeout() {
94  		for (int i = 0; i < numberOfSolvers; i++) {
95  			solvers.get(i).expireTimeout();
96  		}
97  	}
98  
99  	public Map<String, Number> getStat() {
100 		return solvers.get(winnerId).getStat();
101 	}
102 
103 	public int getTimeout() {
104 		return solvers.get(0).getTimeout();
105 	}
106 
107 	public long getTimeoutMs() {
108 		return solvers.get(0).getTimeoutMs();
109 	}
110 
111 	public int newVar() {
112 		throw new UnsupportedOperationException();
113 	}
114 
115 	public int newVar(int howmany) {
116 		int result = 0;
117 		for (int i = 0; i < numberOfSolvers; i++) {
118 			result = solvers.get(i).newVar(howmany);
119 		}
120 		return result;
121 	}
122 
123 	@Deprecated
124 	public void printStat(PrintStream out, String prefix) {
125 		solvers.get(winnerId).printStat(out, prefix);
126 	}
127 
128 	public void printStat(PrintWriter out, String prefix) {
129 		solvers.get(winnerId).printStat(out, prefix);
130 	}
131 
132 	public boolean removeConstr(IConstr c) {
133 		ConstrGroup group = (ConstrGroup) c;
134 		boolean removed = true;
135 		for (int i = 0; i < numberOfSolvers; i++) {
136 			removed = removed & solvers.get(i).removeConstr(group.getConstr(i));
137 		}
138 		return removed;
139 	}
140 
141 	public void reset() {
142 		for (int i = 0; i < numberOfSolvers; i++) {
143 			solvers.get(i).reset();
144 		}
145 	}
146 
147 	public void setExpectedNumberOfClauses(int nb) {
148 		for (int i = 0; i < numberOfSolvers; i++) {
149 			solvers.get(i).setExpectedNumberOfClauses(nb);
150 		}
151 	}
152 
153 	public void setTimeout(int t) {
154 		for (int i = 0; i < numberOfSolvers; i++) {
155 			solvers.get(i).setTimeout(t);
156 		}
157 	}
158 
159 	public void setTimeoutMs(long t) {
160 		for (int i = 0; i < numberOfSolvers; i++) {
161 			solvers.get(i).setTimeoutMs(t);
162 		}
163 	}
164 
165 	public void setTimeoutOnConflicts(int count) {
166 		for (int i = 0; i < numberOfSolvers; i++) {
167 			solvers.get(i).setTimeoutOnConflicts(count);
168 		}
169 	}
170 
171 	public String toString(String prefix) {
172 		StringBuffer res = new StringBuffer();
173 		res.append(prefix);
174 		res.append("ManyCore solver with ");
175 		res.append(numberOfSolvers);
176 		res.append(" solvers running in parallel");
177 		res.append("\n");
178 		for (int i = 0; i < numberOfSolvers; i++) {
179 			res.append(solvers.get(i).toString(prefix));
180 			res.append("\n");
181 		}
182 		return res.toString();
183 	}
184 
185 	public int[] findModel() throws TimeoutException {
186 		throw new UnsupportedOperationException();
187 	}
188 
189 	public int[] findModel(IVecInt assumps) throws TimeoutException {
190 		throw new UnsupportedOperationException();
191 	}
192 
193 	public boolean isSatisfiable() throws TimeoutException {
194 		return isSatisfiable(VecInt.EMPTY, false);
195 	}
196 
197 	public boolean isSatisfiable(IVecInt assumps, boolean globalTimeout)
198 			throws TimeoutException {
199 		remainingSolvers = numberOfSolvers;
200 		solved = false;
201 		for (int i = 0; i < numberOfSolvers; i++) {
202 			new Thread(new RunnableSolver(i, solvers.get(i), assumps,
203 					globalTimeout, this)).start();
204 		}
205 		try {
206 			do {
207 				Thread.sleep(500);
208 			} while (remainingSolvers > 0);
209 		} catch (InterruptedException e) {
210 			// TODO: handle exception
211 		}
212 		if (!solved) {
213 			assert remainingSolvers == 0;
214 			throw new TimeoutException();
215 		}
216 		return resultFound;
217 	}
218 
219 	public boolean isSatisfiable(boolean globalTimeout) throws TimeoutException {
220 		throw new UnsupportedOperationException();
221 	}
222 
223 	public boolean isSatisfiable(IVecInt assumps) throws TimeoutException {
224 		throw new UnsupportedOperationException();
225 	}
226 
227 	public int[] model() {
228 		return solvers.get(winnerId).model();
229 	}
230 
231 	public boolean model(int var) {
232 		return solvers.get(winnerId).model(var);
233 	}
234 
235 	public int nConstraints() {
236 		return solvers.get(0).nConstraints();
237 	}
238 
239 	public int nVars() {
240 		return solvers.get(0).nVars();
241 	}
242 
243 	public void printInfos(PrintWriter out, String prefix) {
244 		for (int i = 0; i < numberOfSolvers; i++) {
245 			solvers.get(i).printInfos(out, prefix);
246 		}
247 	}
248 
249 	public synchronized void onFinishWithAnswer(boolean finished,
250 			boolean result, int index) {
251 		if (finished && !solved) {
252 			winnerId = index;
253 			solved = true;
254 			resultFound = result;
255 			for (int i = 0; i < numberOfSolvers; i++) {
256 				if (i != winnerId)
257 					solvers.get(i).expireTimeout();
258 			}
259 			System.out.println("c And the winner is "
260 					+ availableSolvers[winnerId]);
261 		}
262 		remainingSolvers--;
263 	}
264 
265 	public boolean isDBSimplificationAllowed() {
266 		return solvers.get(0).isDBSimplificationAllowed();
267 	}
268 
269 	public void setDBSimplificationAllowed(boolean status) {
270 		for (int i = 0; i < numberOfSolvers; i++) {
271 			solvers.get(0).setDBSimplificationAllowed(status);
272 		}
273 	}
274 
275 	public void setSearchListener(SearchListener sl) {
276 		for (int i = 0; i < numberOfSolvers; i++) {
277 			solvers.get(i).setSearchListener(sl);
278 		}
279 	}
280 
281 	/**
282 	 * @since 2.2
283 	 */
284 	public SearchListener getSearchListener() {
285 		return solvers.get(0).getSearchListener();
286 	}
287 
288 	public int nextFreeVarId(boolean reserve) {
289 		return solvers.get(0).nextFreeVarId(reserve);
290 	}
291 
292 	public IConstr addBlockingClause(IVecInt literals)
293 			throws ContradictionException {
294 		ConstrGroup group = new ConstrGroup(false);
295 		for (int i = 0; i < numberOfSolvers; i++) {
296 			group.add(solvers.get(i).addBlockingClause(literals));
297 		}
298 		return group;
299 	}
300 
301 	public boolean removeSubsumedConstr(IConstr c) {
302 		ConstrGroup group = (ConstrGroup) c;
303 		boolean removed = true;
304 		for (int i = 0; i < numberOfSolvers; i++) {
305 			removed = removed
306 					& solvers.get(i).removeSubsumedConstr(group.getConstr(i));
307 		}
308 		return removed;
309 	}
310 
311 	public boolean isVerbose() {
312 		return false;
313 	}
314 
315 	public void setVerbose(boolean value) {
316 		// do nothing
317 	}
318 
319 	public void setLogPrefix(String prefix) {
320 		for (int i = 0; i < numberOfSolvers; i++) {
321 			solvers.get(i).setLogPrefix(prefix);
322 		}
323 
324 	}
325 
326 	public String getLogPrefix() {
327 		return solvers.get(0).getLogPrefix();
328 	}
329 
330 	public IVecInt unsatExplanation() {
331 		return solvers.get(0).unsatExplanation();
332 	}
333 }
334 
335 interface OutcomeListener {
336 	void onFinishWithAnswer(boolean finished, boolean result, int index);
337 }
338 
339 class RunnableSolver implements Runnable {
340 
341 	private final int index;
342 	private final ISolver solver;
343 	private final OutcomeListener ol;
344 	private final IVecInt assumps;
345 	private final boolean globalTimeout;
346 
347 	public RunnableSolver(int i, ISolver solver, IVecInt assumps,
348 			boolean globalTimeout, OutcomeListener ol) {
349 		index = i;
350 		this.solver = solver;
351 		this.ol = ol;
352 		this.assumps = assumps;
353 		this.globalTimeout = globalTimeout;
354 	}
355 
356 	public void run() {
357 		try {
358 			boolean result = solver.isSatisfiable(assumps, globalTimeout);
359 			ol.onFinishWithAnswer(true, result, index);
360 		} catch (Exception e) {
361 			ol.onFinishWithAnswer(false, false, index);
362 		}
363 	}
364 
365 }