1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.sat4j.tools;
31
32 import java.io.PrintStream;
33 import java.io.PrintWriter;
34 import java.util.ArrayList;
35 import java.util.List;
36 import java.util.Map;
37
38 import org.sat4j.core.ASolverFactory;
39 import org.sat4j.core.ConstrGroup;
40 import org.sat4j.core.Vec;
41 import org.sat4j.core.VecInt;
42 import org.sat4j.minisat.core.Counter;
43 import org.sat4j.specs.ContradictionException;
44 import org.sat4j.specs.IConstr;
45 import org.sat4j.specs.ISolver;
46 import org.sat4j.specs.ISolverService;
47 import org.sat4j.specs.IVec;
48 import org.sat4j.specs.IVecInt;
49 import org.sat4j.specs.SearchListener;
50 import org.sat4j.specs.TimeoutException;
51
52
53
54
55
56
57
58
59
60
61
62
63
64 public class ManyCore<S extends ISolver> implements ISolver, OutcomeListener {
65
66 private static final int NORMAL_SLEEP = 500;
67
68 private static final int FAST_SLEEP = 50;
69
70
71
72
73 private static final long serialVersionUID = 1L;
74
75 private final String[] availableSolvers;
76
77 protected final List<S> solvers;
78 protected final int numberOfSolvers;
79 private int winnerId;
80 private boolean resultFound;
81 private volatile int remainingSolvers;
82 private volatile int sleepTime;
83 private volatile boolean solved;
84
85 private final IVec<Counter> solversStats = new Vec<Counter>();
86
87 public ManyCore(ASolverFactory<S> factory, String... solverNames) {
88 this.availableSolvers = solverNames;
89 this.numberOfSolvers = solverNames.length;
90 this.solvers = new ArrayList<S>(this.numberOfSolvers);
91 for (int i = 0; i < this.numberOfSolvers; i++) {
92 this.solvers.add(factory
93 .createSolverByName(this.availableSolvers[i]));
94 this.solversStats.push(new Counter(0));
95 }
96 }
97
98
99
100
101
102
103
104
105
106 public ManyCore(String[] names, S... solverObjects) {
107 this(solverObjects);
108 for (int i = 0; i < names.length; i++) {
109 this.availableSolvers[i] = names[i];
110 }
111 }
112
113 public ManyCore(S... solverObjects) {
114 this.availableSolvers = new String[solverObjects.length];
115 for (int i = 0; i < solverObjects.length; i++) {
116 this.availableSolvers[i] = "solver" + i;
117 }
118 this.numberOfSolvers = solverObjects.length;
119 this.solvers = new ArrayList<S>(this.numberOfSolvers);
120 for (int i = 0; i < this.numberOfSolvers; i++) {
121 this.solvers.add(solverObjects[i]);
122 this.solversStats.push(new Counter());
123 }
124 }
125
126 public void addAllClauses(IVec<IVecInt> clauses)
127 throws ContradictionException {
128 for (int i = 0; i < this.numberOfSolvers; i++) {
129 this.solvers.get(i).addAllClauses(clauses);
130 }
131 }
132
133 public IConstr addAtLeast(IVecInt literals, int degree)
134 throws ContradictionException {
135 ConstrGroup group = new ConstrGroup(false);
136 for (int i = 0; i < this.numberOfSolvers; i++) {
137 group.add(this.solvers.get(i).addAtLeast(literals, degree));
138 }
139 return group;
140 }
141
142 public IConstr addAtMost(IVecInt literals, int degree)
143 throws ContradictionException {
144 ConstrGroup group = new ConstrGroup(false);
145 for (int i = 0; i < this.numberOfSolvers; i++) {
146 group.add(this.solvers.get(i).addAtMost(literals, degree));
147 }
148 return group;
149 }
150
151 public IConstr addExactly(IVecInt literals, int n)
152 throws ContradictionException {
153 ConstrGroup group = new ConstrGroup(false);
154 for (int i = 0; i < this.numberOfSolvers; i++) {
155 group.add(this.solvers.get(i).addExactly(literals, n));
156 }
157 return group;
158 }
159
160 public IConstr addClause(IVecInt literals) throws ContradictionException {
161 ConstrGroup group = new ConstrGroup(false);
162 for (int i = 0; i < this.numberOfSolvers; i++) {
163 group.add(this.solvers.get(i).addClause(literals));
164 }
165 return group;
166 }
167
168 public void clearLearntClauses() {
169 for (int i = 0; i < this.numberOfSolvers; i++) {
170 this.solvers.get(i).clearLearntClauses();
171 }
172 }
173
174 public void expireTimeout() {
175 for (int i = 0; i < this.numberOfSolvers; i++) {
176 this.solvers.get(i).expireTimeout();
177 }
178 this.sleepTime = FAST_SLEEP;
179 }
180
181 public Map<String, Number> getStat() {
182 return this.solvers.get(this.winnerId).getStat();
183 }
184
185 public int getTimeout() {
186 return this.solvers.get(0).getTimeout();
187 }
188
189 public long getTimeoutMs() {
190 return this.solvers.get(0).getTimeoutMs();
191 }
192
193 public int newVar() {
194 throw new UnsupportedOperationException();
195 }
196
197 public int newVar(int howmany) {
198 int result = 0;
199 for (int i = 0; i < this.numberOfSolvers; i++) {
200 result = this.solvers.get(i).newVar(howmany);
201 }
202 return result;
203 }
204
205 @Deprecated
206 public void printStat(PrintStream out, String prefix) {
207 for (int i = 0; i < this.numberOfSolvers; i++) {
208 out.printf(
209 "%s>>>>>>>>>> Solver number %d (%d answers) <<<<<<<<<<<<<<<<<<\n",
210 prefix, i, this.solversStats.get(i).getValue());
211 this.solvers.get(i).printStat(out, prefix);
212 }
213 }
214
215 public void printStat(PrintWriter out, String prefix) {
216 for (int i = 0; i < this.numberOfSolvers; i++) {
217 out.printf(
218 "%s>>>>>>>>>> Solver number %d (%d answers) <<<<<<<<<<<<<<<<<<\n",
219 prefix, i, this.solversStats.get(i).getValue());
220 this.solvers.get(i).printStat(out, prefix);
221 }
222 }
223
224 public boolean removeConstr(IConstr c) {
225 if (c instanceof ConstrGroup) {
226 ConstrGroup group = (ConstrGroup) c;
227 boolean removed = true;
228 IConstr toRemove;
229 for (int i = 0; i < this.numberOfSolvers; i++) {
230 toRemove = group.getConstr(i);
231 if (toRemove != null) {
232 removed = removed
233 & this.solvers.get(i).removeConstr(toRemove);
234 }
235 }
236 return removed;
237 }
238 throw new IllegalArgumentException(
239 "Can only remove a group of constraints!");
240 }
241
242 public void reset() {
243 for (int i = 0; i < this.numberOfSolvers; i++) {
244 this.solvers.get(i).reset();
245 }
246 }
247
248 public void setExpectedNumberOfClauses(int nb) {
249 for (int i = 0; i < this.numberOfSolvers; i++) {
250 this.solvers.get(i).setExpectedNumberOfClauses(nb);
251 }
252 }
253
254 public void setTimeout(int t) {
255 for (int i = 0; i < this.numberOfSolvers; i++) {
256 this.solvers.get(i).setTimeout(t);
257 }
258 }
259
260 public void setTimeoutMs(long t) {
261 for (int i = 0; i < this.numberOfSolvers; i++) {
262 this.solvers.get(i).setTimeoutMs(t);
263 }
264 }
265
266 public void setTimeoutOnConflicts(int count) {
267 for (int i = 0; i < this.numberOfSolvers; i++) {
268 this.solvers.get(i).setTimeoutOnConflicts(count);
269 }
270 }
271
272 public String toString(String prefix) {
273 StringBuffer res = new StringBuffer();
274 res.append(prefix);
275 res.append("ManyCore solver with ");
276 res.append(this.numberOfSolvers);
277 res.append(" solvers running in parallel");
278 res.append("\n");
279 for (int i = 0; i < this.numberOfSolvers; i++) {
280 res.append(prefix);
281 res.append(">>>>>>>>>> Solver number ");
282 res.append(i);
283 res.append(" <<<<<<<<<<<<<<<<<<\n");
284 res.append(this.solvers.get(i).toString(prefix));
285 if (i < this.numberOfSolvers - 1) {
286 res.append("\n");
287 }
288 }
289 return res.toString();
290 }
291
292 public int[] findModel() throws TimeoutException {
293 if (isSatisfiable()) {
294 return model();
295 }
296
297 return null;
298 }
299
300 public int[] findModel(IVecInt assumps) throws TimeoutException {
301 if (isSatisfiable(assumps)) {
302 return model();
303 }
304
305 return null;
306 }
307
308 public boolean isSatisfiable() throws TimeoutException {
309 return isSatisfiable(VecInt.EMPTY, false);
310 }
311
312 public synchronized boolean isSatisfiable(IVecInt assumps,
313 boolean globalTimeout) throws TimeoutException {
314 this.remainingSolvers = this.numberOfSolvers;
315 this.solved = false;
316 for (int i = 0; i < this.numberOfSolvers; i++) {
317 new Thread(new RunnableSolver(i, this.solvers.get(i), assumps,
318 globalTimeout, this)).start();
319 }
320 try {
321 this.sleepTime = NORMAL_SLEEP;
322 do {
323 wait(this.sleepTime);
324 } while (this.remainingSolvers > 0);
325 } catch (InterruptedException e) {
326
327 }
328 if (!this.solved) {
329 assert this.remainingSolvers == 0;
330 throw new TimeoutException();
331 }
332 return this.resultFound;
333 }
334
335 public boolean isSatisfiable(boolean globalTimeout) throws TimeoutException {
336 throw new UnsupportedOperationException();
337 }
338
339 public boolean isSatisfiable(IVecInt assumps) throws TimeoutException {
340 throw new UnsupportedOperationException();
341 }
342
343 public int[] model() {
344 return this.solvers.get(this.winnerId).model();
345 }
346
347 public boolean model(int var) {
348 return this.solvers.get(this.winnerId).model(var);
349 }
350
351 public int nConstraints() {
352 return this.solvers.get(0).nConstraints();
353 }
354
355 public int nVars() {
356 return this.solvers.get(0).nVars();
357 }
358
359 public void printInfos(PrintWriter out, String prefix) {
360 for (int i = 0; i < this.numberOfSolvers; i++) {
361 out.printf("%s>>>>>>>>>> Solver number %d <<<<<<<<<<<<<<<<<<\n",
362 prefix, i);
363 this.solvers.get(i).printInfos(out, prefix);
364 }
365 }
366
367 public synchronized void onFinishWithAnswer(boolean finished,
368 boolean result, int index) {
369 if (finished && !this.solved) {
370 this.winnerId = index;
371 this.solversStats.get(index).inc();
372 this.solved = true;
373 this.resultFound = result;
374 for (int i = 0; i < this.numberOfSolvers; i++) {
375 if (i != this.winnerId) {
376 this.solvers.get(i).expireTimeout();
377 }
378 }
379 this.sleepTime = FAST_SLEEP;
380 System.out.println(getLogPrefix() + "And the winner is "
381 + this.availableSolvers[this.winnerId]);
382 }
383 this.remainingSolvers--;
384 }
385
386 public boolean isDBSimplificationAllowed() {
387 return this.solvers.get(0).isDBSimplificationAllowed();
388 }
389
390 public void setDBSimplificationAllowed(boolean status) {
391 for (int i = 0; i < this.numberOfSolvers; i++) {
392 this.solvers.get(0).setDBSimplificationAllowed(status);
393 }
394 }
395
396 public <I extends ISolverService> void setSearchListener(
397 SearchListener<I> sl) {
398 for (int i = 0; i < this.numberOfSolvers; i++) {
399 this.solvers.get(i).setSearchListener(sl);
400 }
401 }
402
403
404
405
406 public <I extends ISolverService> SearchListener<I> getSearchListener() {
407 return this.solvers.get(0).getSearchListener();
408 }
409
410 public int nextFreeVarId(boolean reserve) {
411 int res = -1;
412 for (int i = 0; i < this.numberOfSolvers; ++i) {
413 res = this.solvers.get(i).nextFreeVarId(reserve);
414 }
415 return res;
416 }
417
418 public IConstr addBlockingClause(IVecInt literals)
419 throws ContradictionException {
420 ConstrGroup group = new ConstrGroup(false);
421 for (int i = 0; i < this.numberOfSolvers; i++) {
422 group.add(this.solvers.get(i).addBlockingClause(literals));
423 }
424 return group;
425 }
426
427 public boolean removeSubsumedConstr(IConstr c) {
428 if (c instanceof ConstrGroup) {
429 ConstrGroup group = (ConstrGroup) c;
430 boolean removed = true;
431 IConstr toRemove;
432 for (int i = 0; i < this.numberOfSolvers; i++) {
433 toRemove = group.getConstr(i);
434 if (toRemove != null) {
435 removed = removed
436 & this.solvers.get(i)
437 .removeSubsumedConstr(toRemove);
438 }
439 }
440 return removed;
441 }
442 throw new IllegalArgumentException(
443 "Can only remove a group of constraints!");
444 }
445
446 public boolean isVerbose() {
447 return this.solvers.get(0).isVerbose();
448 }
449
450 public void setVerbose(boolean value) {
451 for (int i = 0; i < this.numberOfSolvers; i++) {
452 this.solvers.get(i).setVerbose(value);
453 }
454 }
455
456 public void setLogPrefix(String prefix) {
457 for (int i = 0; i < this.numberOfSolvers; i++) {
458 this.solvers.get(i).setLogPrefix(prefix);
459 }
460
461 }
462
463 public String getLogPrefix() {
464 return this.solvers.get(0).getLogPrefix();
465 }
466
467 public IVecInt unsatExplanation() {
468 return this.solvers.get(this.winnerId).unsatExplanation();
469 }
470
471 public int[] primeImplicant() {
472 return this.solvers.get(this.winnerId).primeImplicant();
473 }
474
475
476
477
478 public boolean primeImplicant(int p) {
479 return this.solvers.get(this.winnerId).primeImplicant(p);
480 }
481
482 public List<S> getSolvers() {
483 return new ArrayList<S>(this.solvers);
484 }
485
486 public int[] modelWithInternalVariables() {
487 return this.solvers.get(this.winnerId).modelWithInternalVariables();
488 }
489
490 public int realNumberOfVariables() {
491 return this.solvers.get(0).realNumberOfVariables();
492 }
493
494 public void registerLiteral(int p) {
495 for (int i = 0; i < this.numberOfSolvers; i++) {
496 this.solvers.get(i).registerLiteral(p);
497 }
498
499 }
500
501 public boolean isSolverKeptHot() {
502 return this.solvers.get(0).isSolverKeptHot();
503 }
504
505 public void setKeepSolverHot(boolean value) {
506 for (int i = 0; i < this.numberOfSolvers; i++) {
507 this.solvers.get(i).setKeepSolverHot(value);
508 }
509
510 }
511 }
512
513 class RunnableSolver implements Runnable {
514
515 private final int index;
516 private final ISolver solver;
517 private final OutcomeListener ol;
518 private final IVecInt assumps;
519 private final boolean globalTimeout;
520
521 public RunnableSolver(int i, ISolver solver, IVecInt assumps,
522 boolean globalTimeout, OutcomeListener ol) {
523 this.index = i;
524 this.solver = solver;
525 this.ol = ol;
526 this.assumps = assumps;
527 this.globalTimeout = globalTimeout;
528 }
529
530 public void run() {
531 try {
532 boolean result = this.solver.isSatisfiable(this.assumps,
533 this.globalTimeout);
534 this.ol.onFinishWithAnswer(true, result, this.index);
535 } catch (Exception e) {
536 this.ol.onFinishWithAnswer(false, false, this.index);
537 }
538 }
539
540 }