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
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
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
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 }