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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 package org.sat4j.minisat.core;
51
52 import static org.sat4j.core.LiteralsUtils.toDimacs;
53 import static org.sat4j.core.LiteralsUtils.var;
54
55 import java.io.PrintStream;
56 import java.io.PrintWriter;
57 import java.io.Serializable;
58 import java.lang.reflect.Field;
59 import java.util.Comparator;
60 import java.util.HashMap;
61 import java.util.Iterator;
62 import java.util.Map;
63 import java.util.Timer;
64 import java.util.TimerTask;
65
66 import org.sat4j.core.ConstrGroup;
67 import org.sat4j.core.Vec;
68 import org.sat4j.core.VecInt;
69 import org.sat4j.specs.ContradictionException;
70 import org.sat4j.specs.IConstr;
71 import org.sat4j.specs.ISolver;
72 import org.sat4j.specs.IVec;
73 import org.sat4j.specs.IVecInt;
74 import org.sat4j.specs.IteratorInt;
75 import org.sat4j.specs.Lbool;
76 import org.sat4j.specs.SearchListener;
77 import org.sat4j.specs.TimeoutException;
78
79
80
81
82
83
84
85 public class Solver<D extends DataStructureFactory> implements ISolver,
86 UnitPropagationListener, ActivityListener, Learner {
87
88 private static final long serialVersionUID = 1L;
89
90 private static final double CLAUSE_RESCALE_FACTOR = 1e-20;
91
92 private static final double CLAUSE_RESCALE_BOUND = 1 / CLAUSE_RESCALE_FACTOR;
93
94
95
96
97 private final IVec<Constr> constrs = new Vec<Constr>();
98
99
100
101
102 private final IVec<Constr> learnts = new Vec<Constr>();
103
104
105
106
107 private double claInc = 1.0;
108
109
110
111
112 private double claDecay = 1.0;
113
114
115
116
117
118 private int qhead = 0;
119
120
121
122
123
124
125 protected final IVecInt trail = new VecInt();
126
127
128
129
130
131
132 protected final IVecInt trailLim = new VecInt();
133
134
135
136
137
138
139 protected int rootLevel;
140
141 private int[] model = null;
142
143 protected ILits voc;
144
145 private IOrder order;
146
147 private final ActivityComparator comparator = new ActivityComparator();
148
149 private SolverStats stats = new SolverStats();
150
151 private LearningStrategy<D> learner;
152
153 protected volatile boolean undertimeout;
154
155 private long timeout = Integer.MAX_VALUE;
156
157 private boolean timeBasedTimeout = true;
158
159 protected D dsfactory;
160
161 private SearchParams params;
162
163 private final IVecInt __dimacs_out = new VecInt();
164
165 private SearchListener slistener = new VoidTracing();
166
167 private RestartStrategy restarter;
168
169 private final Map<String, Counter> constrTypes = new HashMap<String, Counter>();
170
171 private boolean isDBSimplificationAllowed = false;
172
173 private final IVecInt learnedLiterals = new VecInt();
174
175 private boolean verbose = false;
176
177 private String prefix = "c ";
178 private int declaredMaxVarId = 0;
179
180 protected IVecInt dimacs2internal(IVecInt in) {
181 __dimacs_out.clear();
182 __dimacs_out.ensure(in.size());
183 int p;
184 for (int i = 0; i < in.size(); i++) {
185 p = in.get(i);
186 if (p == 0) {
187 throw new IllegalArgumentException(
188 "0 is not a valid variable identifier");
189 }
190 __dimacs_out.unsafePush(voc.getFromPool(p));
191 }
192 return __dimacs_out;
193 }
194
195
196
197
198 public void registerLiteral(int p) {
199 voc.getFromPool(p);
200 }
201
202
203
204
205
206
207
208 public Solver(LearningStrategy<D> learner, D dsf, IOrder order,
209 RestartStrategy restarter) {
210 this(learner, dsf, new SearchParams(), order, restarter);
211 }
212
213 public Solver(LearningStrategy<D> learner, D dsf, SearchParams params,
214 IOrder order, RestartStrategy restarter) {
215 this.learner = learner;
216 this.order = order;
217 this.params = params;
218 setDataStructureFactory(dsf);
219 this.restarter = restarter;
220 }
221
222
223
224
225
226
227
228
229 public final void setDataStructureFactory(D dsf) {
230 dsfactory = dsf;
231 dsfactory.setUnitPropagationListener(this);
232 dsfactory.setLearner(this);
233 voc = dsf.getVocabulary();
234 order.setLits(voc);
235 }
236
237
238
239
240 public boolean isVerbose() {
241 return verbose;
242 }
243
244
245
246
247
248 public void setVerbose(boolean value) {
249 verbose = value;
250 }
251
252
253
254
255 public void setSearchListener(SearchListener sl) {
256 slistener = sl;
257 }
258
259
260
261
262 public SearchListener getSearchListener() {
263 return slistener;
264 }
265
266
267
268
269 public void setLearner(LearningStrategy<D> learner) {
270 this.learner = learner;
271 }
272
273 public void setTimeout(int t) {
274 timeout = t * 1000L;
275 timeBasedTimeout = true;
276 }
277
278 public void setTimeoutMs(long t) {
279 timeout = t;
280 timeBasedTimeout = true;
281 }
282
283 public void setTimeoutOnConflicts(int count) {
284 timeout = count;
285 timeBasedTimeout = false;
286 }
287
288 public void setSearchParams(SearchParams sp) {
289 params = sp;
290 }
291
292 public void setRestartStrategy(RestartStrategy restarter) {
293 this.restarter = restarter;
294 }
295
296 public void expireTimeout() {
297 undertimeout = false;
298 if (timeBasedTimeout) {
299 if (timer != null) {
300 timer.cancel();
301 timer = null;
302 }
303 } else {
304 if (conflictCount != null) {
305 conflictCount = null;
306 }
307 }
308 }
309
310 protected int nAssigns() {
311 return trail.size();
312 }
313
314 public int nConstraints() {
315 return constrs.size();
316 }
317
318 public void learn(Constr c) {
319 learnts.push(c);
320 c.setLearnt();
321 c.register();
322 stats.learnedclauses++;
323 switch (c.size()) {
324 case 2:
325 stats.learnedbinaryclauses++;
326 break;
327 case 3:
328 stats.learnedternaryclauses++;
329 break;
330 default:
331
332 }
333 }
334
335 public final int decisionLevel() {
336 return trailLim.size();
337 }
338
339 @Deprecated
340 public int newVar() {
341 int index = voc.nVars() + 1;
342 voc.ensurePool(index);
343 return index;
344 }
345
346 public int newVar(int howmany) {
347 voc.ensurePool(howmany);
348 declaredMaxVarId = howmany;
349 return howmany;
350 }
351
352 public IConstr addClause(IVecInt literals) throws ContradictionException {
353 IVecInt vlits = dimacs2internal(literals);
354 return addConstr(dsfactory.createClause(vlits));
355 }
356
357 public boolean removeConstr(IConstr co) {
358 if (co == null) {
359 throw new IllegalArgumentException(
360 "Reference to the constraint to remove needed!");
361 }
362 Constr c = (Constr) co;
363 c.remove(this);
364 constrs.remove(c);
365 clearLearntClauses();
366 String type = c.getClass().getName();
367 constrTypes.get(type).dec();
368 return true;
369 }
370
371
372
373
374 public boolean removeSubsumedConstr(IConstr co) {
375 if (co == null) {
376 throw new IllegalArgumentException(
377 "Reference to the constraint to remove needed!");
378 }
379 if (constrs.last() != co) {
380 throw new IllegalArgumentException(
381 "Can only remove latest added constraint!!!");
382 }
383 Constr c = (Constr) co;
384 c.remove(this);
385 constrs.pop();
386 String type = c.getClass().getName();
387 constrTypes.get(type).dec();
388 return true;
389 }
390
391 public void addAllClauses(IVec<IVecInt> clauses)
392 throws ContradictionException {
393 for (Iterator<IVecInt> iterator = clauses.iterator(); iterator
394 .hasNext();) {
395 addClause(iterator.next());
396 }
397 }
398
399 public IConstr addAtMost(IVecInt literals, int degree)
400 throws ContradictionException {
401 int n = literals.size();
402 IVecInt opliterals = new VecInt(n);
403 for (IteratorInt iterator = literals.iterator(); iterator.hasNext();) {
404 opliterals.push(-iterator.next());
405 }
406 return addAtLeast(opliterals, n - degree);
407 }
408
409 public IConstr addAtLeast(IVecInt literals, int degree)
410 throws ContradictionException {
411 IVecInt vlits = dimacs2internal(literals);
412 return addConstr(dsfactory.createCardinalityConstraint(vlits, degree));
413 }
414
415 public IConstr addExactly(IVecInt literals, int n)
416 throws ContradictionException {
417 ConstrGroup group = new ConstrGroup(false);
418 group.add(addAtMost(literals, n));
419 group.add(addAtLeast(literals, n));
420 return group;
421 }
422
423 @SuppressWarnings("unchecked")
424 public boolean simplifyDB() {
425
426
427 IVec<Constr>[] cs = new IVec[] { constrs, learnts };
428 for (int type = 0; type < 2; type++) {
429 int j = 0;
430 for (int i = 0; i < cs[type].size(); i++) {
431 if (cs[type].get(i).simplify()) {
432
433 cs[type].get(i).remove(this);
434 } else {
435 cs[type].moveTo(j++, i);
436 }
437 }
438 cs[type].shrinkTo(j);
439 }
440 return true;
441 }
442
443
444
445
446
447
448 public int[] model() {
449 if (model == null) {
450 throw new UnsupportedOperationException(
451 "Call the solve method first!!!");
452 }
453 int[] nmodel = new int[model.length];
454 System.arraycopy(model, 0, nmodel, 0, model.length);
455 return nmodel;
456 }
457
458
459
460
461
462
463
464
465 public boolean enqueue(int p) {
466 return enqueue(p, null);
467 }
468
469
470
471
472
473
474
475
476
477
478
479 public boolean enqueue(int p, Constr from) {
480 assert p > 1;
481 if (voc.isSatisfied(p)) {
482
483 return true;
484 }
485 if (voc.isFalsified(p)) {
486
487 return false;
488 }
489
490 voc.satisfies(p);
491 voc.setLevel(p, decisionLevel());
492 voc.setReason(p, from);
493 trail.push(p);
494 return true;
495 }
496
497 private boolean[] mseen = new boolean[0];
498
499 private final IVecInt mpreason = new VecInt();
500
501 private final IVecInt moutLearnt = new VecInt();
502
503
504
505
506
507 public void analyze(Constr confl, Pair results) throws TimeoutException {
508 assert confl != null;
509
510 final boolean[] seen = mseen;
511 final IVecInt outLearnt = moutLearnt;
512 final IVecInt preason = mpreason;
513
514 outLearnt.clear();
515 assert outLearnt.size() == 0;
516 for (int i = 0; i < seen.length; i++) {
517 seen[i] = false;
518 }
519
520 int counter = 0;
521 int p = ILits.UNDEFINED;
522
523 outLearnt.push(ILits.UNDEFINED);
524
525 int outBtlevel = 0;
526 IConstr prevConfl = null;
527
528 do {
529 preason.clear();
530 assert confl != null;
531 if (prevConfl != confl) {
532 confl.calcReason(p, preason);
533 learnedConstraintsDeletionStrategy.onConflictAnalysis(confl);
534
535 for (int j = 0; j < preason.size(); j++) {
536 int q = preason.get(j);
537 order.updateVar(q);
538 if (!seen[q >> 1]) {
539 seen[q >> 1] = true;
540 if (voc.getLevel(q) == decisionLevel()) {
541 counter++;
542 order.updateVarAtDecisionLevel(q);
543 } else if (voc.getLevel(q) > 0) {
544
545
546
547 outLearnt.push(q ^ 1);
548 outBtlevel = Math.max(outBtlevel, voc.getLevel(q));
549 }
550 }
551 }
552 }
553 prevConfl = confl;
554
555 do {
556 p = trail.last();
557 confl = voc.getReason(p);
558 undoOne();
559 } while (!seen[p >> 1]);
560
561
562 } while (--counter > 0);
563
564 outLearnt.set(0, p ^ 1);
565 simplifier.simplify(outLearnt);
566
567 Constr c = dsfactory.createUnregisteredClause(outLearnt);
568 slistener.learn(c);
569 learnedConstraintsDeletionStrategy.onConflict(c);
570 results.reason = c;
571
572 assert outBtlevel > -1;
573 results.backtrackLevel = outBtlevel;
574 }
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589 public IVecInt analyzeFinalConflictInTermsOfAssumptions(Constr confl,
590 IVecInt assumps, int conflictingLiteral) {
591 if (assumps.size() == 0) {
592 return null;
593 }
594 while (!trailLim.isEmpty() && trailLim.last() == trail.size()) {
595
596 trailLim.pop();
597 }
598 final boolean[] seen = mseen;
599 final IVecInt outLearnt = moutLearnt;
600 final IVecInt preason = mpreason;
601
602 outLearnt.clear();
603 if (trailLim.size() == 0) {
604
605 return outLearnt;
606 }
607
608 assert outLearnt.size() == 0;
609 for (int i = 0; i < seen.length; i++) {
610 seen[i] = false;
611 }
612
613 if (confl == null) {
614 seen[conflictingLiteral >> 1] = true;
615 }
616
617 int p = ILits.UNDEFINED;
618 while (confl == null && trail.size() > 0 && trailLim.size() > 0) {
619 p = trail.last();
620 confl = voc.getReason(p);
621 undoOne();
622 if (confl == null && p == (conflictingLiteral ^ 1)) {
623 outLearnt.push(toDimacs(p));
624 }
625 if (trail.size() <= trailLim.last()) {
626 trailLim.pop();
627 }
628 }
629 if (confl == null) {
630 return outLearnt;
631 }
632 do {
633
634 preason.clear();
635 confl.calcReason(p, preason);
636
637 for (int j = 0; j < preason.size(); j++) {
638 int q = preason.get(j);
639 if (!seen[q >> 1]) {
640 seen[q >> 1] = true;
641 if (voc.getReason(q) == null && voc.getLevel(q) > 0) {
642 assert assumps.contains(toDimacs(q));
643 outLearnt.push(toDimacs(q));
644 }
645 }
646 }
647
648
649 do {
650 p = trail.last();
651 confl = voc.getReason(p);
652 undoOne();
653 if (decisionLevel() > 0 && trail.size() <= trailLim.last()) {
654 trailLim.pop();
655 }
656 } while (trail.size() > 0 && decisionLevel() > 0
657 && (!seen[p >> 1] || confl == null));
658 } while (decisionLevel() > 0);
659 return outLearnt;
660 }
661
662 interface ISimplifier extends Serializable {
663 void simplify(IVecInt outLearnt);
664 }
665
666 public static final ISimplifier NO_SIMPLIFICATION = new ISimplifier() {
667
668
669
670 private static final long serialVersionUID = 1L;
671
672 public void simplify(IVecInt outLearnt) {
673 }
674
675 @Override
676 public String toString() {
677 return "No reason simplification";
678 }
679 };
680
681 public final ISimplifier SIMPLE_SIMPLIFICATION = new ISimplifier() {
682
683
684
685 private static final long serialVersionUID = 1L;
686
687 public void simplify(IVecInt conflictToReduce) {
688 simpleSimplification(conflictToReduce);
689 }
690
691 @Override
692 public String toString() {
693 return "Simple reason simplification";
694 }
695 };
696
697 public final ISimplifier EXPENSIVE_SIMPLIFICATION = new ISimplifier() {
698
699
700
701
702 private static final long serialVersionUID = 1L;
703
704 public void simplify(IVecInt conflictToReduce) {
705 expensiveSimplification(conflictToReduce);
706 }
707
708 @Override
709 public String toString() {
710 return "Expensive reason simplification";
711 }
712 };
713
714 public final ISimplifier EXPENSIVE_SIMPLIFICATION_WLONLY = new ISimplifier() {
715
716
717
718
719 private static final long serialVersionUID = 1L;
720
721 public void simplify(IVecInt conflictToReduce) {
722 expensiveSimplificationWLOnly(conflictToReduce);
723 }
724
725 @Override
726 public String toString() {
727 return "Expensive reason simplification specific for WL data structure";
728 }
729 };
730
731 private ISimplifier simplifier = NO_SIMPLIFICATION;
732
733
734
735
736
737
738
739
740
741
742 public void setSimplifier(String simp) {
743 Field f;
744 try {
745 f = Solver.class.getDeclaredField(simp);
746 simplifier = (ISimplifier) f.get(this);
747 } catch (Exception e) {
748 e.printStackTrace();
749 simplifier = NO_SIMPLIFICATION;
750 }
751 }
752
753
754
755
756
757
758
759
760
761
762 public void setSimplifier(ISimplifier simp) {
763 simplifier = simp;
764 }
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788 private void simpleSimplification(IVecInt conflictToReduce) {
789 int i, j, p;
790 final boolean[] seen = mseen;
791 IConstr r;
792 for (i = j = 1; i < conflictToReduce.size(); i++) {
793 r = voc.getReason(conflictToReduce.get(i));
794 if (r == null || r.canBePropagatedMultipleTimes()) {
795 conflictToReduce.moveTo(j++, i);
796 } else {
797 for (int k = 0; k < r.size(); k++) {
798 p = r.get(k);
799 if (!seen[p >> 1] && voc.isFalsified(p)
800 && (voc.getLevel(p) != 0)) {
801 conflictToReduce.moveTo(j++, i);
802 break;
803 }
804 }
805 }
806 }
807 conflictToReduce.shrink(i - j);
808 stats.reducedliterals += (i - j);
809 }
810
811 private final IVecInt analyzetoclear = new VecInt();
812
813 private final IVecInt analyzestack = new VecInt();
814
815
816 private void expensiveSimplification(IVecInt conflictToReduce) {
817
818
819 int i, j;
820
821 analyzetoclear.clear();
822 conflictToReduce.copyTo(analyzetoclear);
823 for (i = 1, j = 1; i < conflictToReduce.size(); i++)
824 if (voc.getReason(conflictToReduce.get(i)) == null
825 || !analyzeRemovable(conflictToReduce.get(i)))
826 conflictToReduce.moveTo(j++, i);
827 conflictToReduce.shrink(i - j);
828 stats.reducedliterals += (i - j);
829 }
830
831
832
833
834 private boolean analyzeRemovable(int p) {
835 assert voc.getReason(p) != null;
836 ILits lvoc = voc;
837 IVecInt lanalyzestack = analyzestack;
838 IVecInt lanalyzetoclear = analyzetoclear;
839 lanalyzestack.clear();
840 lanalyzestack.push(p);
841 final boolean[] seen = mseen;
842 int top = lanalyzetoclear.size();
843 while (lanalyzestack.size() > 0) {
844 int q = lanalyzestack.last();
845 assert lvoc.getReason(q) != null;
846 Constr c = lvoc.getReason(q);
847 lanalyzestack.pop();
848 if (c.canBePropagatedMultipleTimes()) {
849 for (int j = top; j < lanalyzetoclear.size(); j++)
850 seen[lanalyzetoclear.get(j) >> 1] = false;
851 lanalyzetoclear.shrink(lanalyzetoclear.size() - top);
852 return false;
853 }
854 for (int i = 0; i < c.size(); i++) {
855 int l = c.get(i);
856 if (!seen[var(l)] && lvoc.isFalsified(l)
857 && lvoc.getLevel(l) != 0) {
858 if (lvoc.getReason(l) == null) {
859 for (int j = top; j < lanalyzetoclear.size(); j++)
860 seen[lanalyzetoclear.get(j) >> 1] = false;
861 lanalyzetoclear.shrink(lanalyzetoclear.size() - top);
862 return false;
863 }
864 seen[l >> 1] = true;
865 lanalyzestack.push(l);
866 lanalyzetoclear.push(l);
867 }
868 }
869
870 }
871
872 return true;
873 }
874
875
876 private void expensiveSimplificationWLOnly(IVecInt conflictToReduce) {
877
878
879 int i, j;
880
881 analyzetoclear.clear();
882 conflictToReduce.copyTo(analyzetoclear);
883 for (i = 1, j = 1; i < conflictToReduce.size(); i++)
884 if (voc.getReason(conflictToReduce.get(i)) == null
885 || !analyzeRemovableWLOnly(conflictToReduce.get(i)))
886 conflictToReduce.moveTo(j++, i);
887 conflictToReduce.shrink(i - j);
888 stats.reducedliterals += (i - j);
889 }
890
891
892
893
894 private boolean analyzeRemovableWLOnly(int p) {
895 assert voc.getReason(p) != null;
896 analyzestack.clear();
897 analyzestack.push(p);
898 final boolean[] seen = mseen;
899 int top = analyzetoclear.size();
900 while (analyzestack.size() > 0) {
901 int q = analyzestack.last();
902 assert voc.getReason(q) != null;
903 Constr c = voc.getReason(q);
904 analyzestack.pop();
905 for (int i = 1; i < c.size(); i++) {
906 int l = c.get(i);
907 if (!seen[var(l)] && voc.getLevel(l) != 0) {
908 if (voc.getReason(l) == null) {
909 for (int j = top; j < analyzetoclear.size(); j++)
910 seen[analyzetoclear.get(j) >> 1] = false;
911 analyzetoclear.shrink(analyzetoclear.size() - top);
912 return false;
913 }
914 seen[l >> 1] = true;
915 analyzestack.push(l);
916 analyzetoclear.push(l);
917 }
918 }
919 }
920
921 return true;
922 }
923
924
925
926
927
928
929 protected void undoOne() {
930
931 int p = trail.last();
932 assert p > 1;
933 assert voc.getLevel(p) >= 0;
934 int x = p >> 1;
935
936 voc.unassign(p);
937 voc.setReason(p, null);
938 voc.setLevel(p, -1);
939
940 order.undo(x);
941
942 trail.pop();
943
944
945 IVec<Undoable> undos = voc.undos(p);
946 assert undos != null;
947 for (int size = undos.size(); size > 0; size--) {
948 undos.last().undo(p);
949 undos.pop();
950 }
951 }
952
953
954
955
956
957
958
959 public void claBumpActivity(Constr confl) {
960 confl.incActivity(claInc);
961 if (confl.getActivity() > CLAUSE_RESCALE_BOUND)
962 claRescalActivity();
963
964
965
966 }
967
968 public void varBumpActivity(int p) {
969 order.updateVar(p);
970 }
971
972 private void claRescalActivity() {
973 for (int i = 0; i < learnts.size(); i++) {
974 learnts.get(i).rescaleBy(CLAUSE_RESCALE_FACTOR);
975 }
976 claInc *= CLAUSE_RESCALE_FACTOR;
977 }
978
979 private final IVec<Propagatable> watched = new Vec<Propagatable>();
980
981
982
983
984 public Constr propagate() {
985 IVec<Propagatable> lwatched = watched;
986 IVecInt ltrail = trail;
987 ILits lvoc = voc;
988 SolverStats lstats = stats;
989 IOrder lorder = order;
990 SearchListener lslistener = slistener;
991
992
993 while (qhead < ltrail.size()) {
994 lstats.propagations++;
995 int p = ltrail.get(qhead++);
996 lslistener.propagating(toDimacs(p), null);
997 lorder.assignLiteral(p);
998
999
1000
1001 assert p > 1;
1002 lwatched.clear();
1003 lvoc.watches(p).moveTo(lwatched);
1004 final int size = lwatched.size();
1005 for (int i = 0; i < size; i++) {
1006 lstats.inspects++;
1007
1008
1009
1010
1011
1012
1013
1014
1015 if (!lwatched.get(i).propagate(this, p)) {
1016
1017
1018
1019 final int sizew = lwatched.size();
1020 for (int j = i + 1; j < sizew; j++) {
1021 lvoc.watch(p, lwatched.get(j));
1022 }
1023 qhead = ltrail.size();
1024
1025 return (Constr) lwatched.get(i);
1026 }
1027 }
1028 }
1029 return null;
1030 }
1031
1032 void record(Constr constr) {
1033 constr.assertConstraint(this);
1034 slistener.adding(toDimacs(constr.get(0)));
1035 if (constr.size() == 1) {
1036 stats.learnedliterals++;
1037 } else {
1038 learner.learns(constr);
1039 }
1040 }
1041
1042
1043
1044
1045 public boolean assume(int p) {
1046
1047 assert trail.size() == qhead;
1048 assert !trailLim.contains(trail.size());
1049 trailLim.push(trail.size());
1050 return enqueue(p);
1051 }
1052
1053
1054
1055
1056 private void cancel() {
1057
1058 int decisionvar = trail.unsafeGet(trailLim.last());
1059 slistener.backtracking(toDimacs(decisionvar));
1060 for (int c = trail.size() - trailLim.last(); c > 0; c--) {
1061 undoOne();
1062 }
1063 trailLim.pop();
1064 }
1065
1066
1067
1068
1069 private void cancelLearntLiterals(int learnedLiteralsLimit) {
1070 learnedLiterals.clear();
1071
1072 while (trail.size() > learnedLiteralsLimit) {
1073 learnedLiterals.push(trail.last());
1074 undoOne();
1075 }
1076
1077
1078 }
1079
1080
1081
1082
1083
1084
1085 protected void cancelUntil(int level) {
1086 while (decisionLevel() > level) {
1087 cancel();
1088 }
1089 qhead = trail.size();
1090 }
1091
1092 private final Pair analysisResult = new Pair();
1093
1094 private boolean[] userbooleanmodel;
1095
1096 private IVecInt unsatExplanationInTermsOfAssumptions;
1097
1098 Lbool search(long nofConflicts, IVecInt assumps) {
1099 assert rootLevel == decisionLevel();
1100 stats.starts++;
1101 int conflictC = 0;
1102 int backjumpLevel;
1103
1104
1105 order.setVarDecay(1 / params.getVarDecay());
1106 claDecay = 1 / params.getClaDecay();
1107
1108 do {
1109 slistener.beginLoop();
1110
1111 Constr confl = propagate();
1112 assert trail.size() == qhead;
1113
1114 if (confl == null) {
1115
1116
1117
1118 if (decisionLevel() == 0 && isDBSimplificationAllowed) {
1119
1120
1121 stats.rootSimplifications++;
1122 boolean ret = simplifyDB();
1123 assert ret;
1124 }
1125
1126
1127 assert nAssigns() <= voc.realnVars();
1128 if (nAssigns() == voc.realnVars()) {
1129 slistener.solutionFound();
1130 modelFound();
1131 return Lbool.TRUE;
1132 }
1133 if (conflictC >= nofConflicts) {
1134
1135
1136 cancelUntil(rootLevel);
1137 return Lbool.UNDEFINED;
1138 }
1139 if (needToReduceDB) {
1140 reduceDB();
1141 needToReduceDB = false;
1142
1143 }
1144
1145 stats.decisions++;
1146 int p = order.select();
1147 assert p > 1;
1148 slistener.assuming(toDimacs(p));
1149 boolean ret = assume(p);
1150 assert ret;
1151 } else {
1152
1153 stats.conflicts++;
1154 conflictC++;
1155 slistener.conflictFound(confl, decisionLevel(), trail.size());
1156 conflictCount.newConflict();
1157
1158 if (decisionLevel() == rootLevel) {
1159
1160 unsatExplanationInTermsOfAssumptions = analyzeFinalConflictInTermsOfAssumptions(
1161 confl, assumps, ILits.UNDEFINED);
1162 return Lbool.FALSE;
1163 }
1164
1165 try {
1166 analyze(confl, analysisResult);
1167 } catch (TimeoutException e) {
1168 return Lbool.UNDEFINED;
1169 }
1170 assert analysisResult.backtrackLevel < decisionLevel();
1171 backjumpLevel = Math.max(analysisResult.backtrackLevel,
1172 rootLevel);
1173 slistener.backjump(backjumpLevel);
1174 cancelUntil(backjumpLevel);
1175 if (backjumpLevel == rootLevel) {
1176 conflictC = 0;
1177 }
1178 assert (decisionLevel() >= rootLevel)
1179 && (decisionLevel() >= analysisResult.backtrackLevel);
1180 if (analysisResult.reason == null) {
1181 return Lbool.FALSE;
1182 }
1183 record(analysisResult.reason);
1184 analysisResult.reason = null;
1185 decayActivities();
1186 }
1187 } while (undertimeout);
1188 return Lbool.UNDEFINED;
1189 }
1190
1191 protected void analyzeAtRootLevel(Constr conflict) {
1192 }
1193
1194 private final IVecInt implied = new VecInt();
1195 private final IVecInt decisions = new VecInt();
1196
1197 private int[] fullmodel;
1198
1199
1200
1201
1202 void modelFound() {
1203 IVecInt tempmodel = new VecInt(nVars());
1204 userbooleanmodel = new boolean[realNumberOfVariables()];
1205 fullmodel = null;
1206 for (int i = 1; i <= nVars(); i++) {
1207 if (voc.belongsToPool(i)) {
1208 int p = voc.getFromPool(i);
1209 if (!voc.isUnassigned(p)) {
1210 tempmodel.push(voc.isSatisfied(p) ? i : -i);
1211 userbooleanmodel[i - 1] = voc.isSatisfied(p);
1212 if (voc.getReason(p) == null) {
1213 decisions.push(tempmodel.last());
1214 } else {
1215 implied.push(tempmodel.last());
1216 }
1217 }
1218 }
1219 }
1220 model = new int[tempmodel.size()];
1221 tempmodel.copyTo(model);
1222 if (realNumberOfVariables() > nVars()) {
1223 for (int i = nVars() + 1; i <= realNumberOfVariables(); i++) {
1224 if (voc.belongsToPool(i)) {
1225 int p = voc.getFromPool(i);
1226 if (!voc.isUnassigned(p)) {
1227 tempmodel.push(voc.isSatisfied(p) ? i : -i);
1228 userbooleanmodel[i - 1] = voc.isSatisfied(p);
1229 }
1230 }
1231 }
1232 fullmodel = new int[tempmodel.size()];
1233 tempmodel.moveTo(fullmodel);
1234 }
1235 cancelUntil(rootLevel);
1236 }
1237
1238 public int[] primeImplicant() {
1239 IVecInt currentD = new VecInt(decisions.size());
1240 decisions.copyTo(currentD);
1241 IVecInt assumptions = new VecInt(implied.size() + decisions.size());
1242 implied.copyTo(assumptions);
1243 decisions.copyTo(assumptions);
1244 IVecInt prime = new VecInt(assumptions.size());
1245 implied.copyTo(prime);
1246 for (int i = 0; i < currentD.size(); i++) {
1247 int p = currentD.get(i);
1248 assumptions.remove(p);
1249 assumptions.push(-p);
1250 try {
1251 if (isSatisfiable(assumptions)) {
1252 assumptions.pop();
1253 assumptions.push(-p);
1254 } else {
1255 prime.push(p);
1256 assumptions.pop();
1257 assumptions.push(p);
1258 }
1259 } catch (TimeoutException e) {
1260 throw new IllegalStateException("Should not timeout here", e);
1261 }
1262 }
1263 int[] implicant = new int[prime.size()];
1264 prime.copyTo(implicant);
1265 return implicant;
1266 }
1267
1268 public boolean model(int var) {
1269 if (var <= 0 || var > realNumberOfVariables()) {
1270 throw new IllegalArgumentException(
1271 "Use a valid Dimacs var id as argument!");
1272 }
1273 if (userbooleanmodel == null) {
1274 throw new UnsupportedOperationException(
1275 "Call the solve method first!!!");
1276 }
1277 return userbooleanmodel[var - 1];
1278 }
1279
1280 public void clearLearntClauses() {
1281 for (Iterator<Constr> iterator = learnts.iterator(); iterator.hasNext();)
1282 iterator.next().remove(this);
1283 learnts.clear();
1284 learnedLiterals.clear();
1285 }
1286
1287 protected void reduceDB() {
1288 stats.reduceddb++;
1289 learnedConstraintsDeletionStrategy.reduce(learnts);
1290 System.gc();
1291 }
1292
1293
1294
1295
1296 private void sortOnActivity() {
1297 learnts.sort(comparator);
1298 }
1299
1300
1301
1302
1303 protected void decayActivities() {
1304 order.varDecayActivity();
1305 claDecayActivity();
1306 }
1307
1308
1309
1310
1311 private void claDecayActivity() {
1312 claInc *= claDecay;
1313 }
1314
1315
1316
1317
1318 public boolean isSatisfiable() throws TimeoutException {
1319 return isSatisfiable(VecInt.EMPTY);
1320 }
1321
1322
1323
1324
1325 public boolean isSatisfiable(boolean global) throws TimeoutException {
1326 return isSatisfiable(VecInt.EMPTY, global);
1327 }
1328
1329 private double timebegin = 0;
1330
1331 private boolean needToReduceDB;
1332
1333 private ConflictTimer conflictCount;
1334
1335 private transient Timer timer;
1336
1337 public boolean isSatisfiable(IVecInt assumps) throws TimeoutException {
1338 return isSatisfiable(assumps, false);
1339 }
1340
1341 interface LearnedConstraintsDeletionStrategy extends Serializable {
1342
1343 void init();
1344
1345 ConflictTimer getTimer();
1346
1347 void reduce(IVec<Constr> learnedConstrs);
1348
1349 void onConflict(Constr outLearnt);
1350
1351 void onConflictAnalysis(Constr reason);
1352 }
1353
1354 public final LearnedConstraintsDeletionStrategy fixedSize(final int maxsize) {
1355 return new LearnedConstraintsDeletionStrategy() {
1356
1357 private static final long serialVersionUID = 1L;
1358 private final ConflictTimer aTimer = new ConflictTimerAdapter(
1359 maxsize) {
1360
1361 private static final long serialVersionUID = 1L;
1362
1363 @Override
1364 void run() {
1365 needToReduceDB = true;
1366 }
1367 };
1368
1369 public void reduce(IVec<Constr> learnedConstrs) {
1370 int i, j, k;
1371 for (i = j = k = 0; i < learnts.size()
1372 && learnts.size() - k > maxsize; i++) {
1373 Constr c = learnts.get(i);
1374 if (c.locked() || c.size() == 2) {
1375 learnts.set(j++, learnts.get(i));
1376 } else {
1377 c.remove(Solver.this);
1378 k++;
1379 }
1380 }
1381 for (; i < learnts.size(); i++) {
1382 learnts.set(j++, learnts.get(i));
1383 }
1384 if (verbose) {
1385 System.out.println(getLogPrefix()
1386 + "cleaning " + (learnts.size() - j)
1387 + " clauses out of " + learnts.size());
1388 System.out.flush();
1389 }
1390 learnts.shrinkTo(j);
1391 }
1392
1393 public void onConflictAnalysis(Constr reason) {
1394
1395
1396 }
1397
1398 public void onConflict(Constr outLearnt) {
1399
1400
1401 }
1402
1403 @Override
1404 public String toString() {
1405 return "Fixed size (" + maxsize
1406 + ") learned constraints deletion strategy";
1407 }
1408
1409 public void init() {
1410 }
1411
1412 public ConflictTimer getTimer() {
1413 return aTimer;
1414 }
1415 };
1416 }
1417
1418
1419
1420
1421 public final LearnedConstraintsDeletionStrategy memory_based = new LearnedConstraintsDeletionStrategy() {
1422
1423 private static final long serialVersionUID = 1L;
1424
1425 final long memorybound = Runtime.getRuntime().freeMemory() / 10;
1426
1427 private final ConflictTimer freeMem = new ConflictTimerAdapter(500) {
1428 private static final long serialVersionUID = 1L;
1429
1430 @Override
1431 void run() {
1432 long freemem = Runtime.getRuntime().freeMemory();
1433
1434 if (freemem < memorybound) {
1435
1436 needToReduceDB = true;
1437 }
1438 }
1439 };
1440
1441 public void reduce(IVec<Constr> learnedConstrs) {
1442 sortOnActivity();
1443 int i, j;
1444 for (i = j = 0; i < learnts.size() / 2; i++) {
1445 Constr c = learnts.get(i);
1446 if (c.locked() || c.size() == 2) {
1447 learnts.set(j++, learnts.get(i));
1448 } else {
1449 c.remove(Solver.this);
1450 }
1451 }
1452 for (; i < learnts.size(); i++) {
1453 learnts.set(j++, learnts.get(i));
1454 }
1455 if (verbose) {
1456 System.out.println(getLogPrefix()
1457 + "cleaning " + (learnts.size() - j)
1458 + " clauses out of " + learnts.size());
1459 System.out.flush();
1460 }
1461 learnts.shrinkTo(j);
1462 }
1463
1464 public ConflictTimer getTimer() {
1465 return freeMem;
1466 }
1467
1468 @Override
1469 public String toString() {
1470 return "Memory based learned constraints deletion strategy";
1471 }
1472
1473 public void init() {
1474
1475 }
1476
1477 public void onConflict(Constr constr) {
1478
1479
1480 }
1481
1482 public void onConflictAnalysis(Constr reason) {
1483 if (reason.learnt())
1484 claBumpActivity(reason);
1485 }
1486 };
1487
1488
1489
1490
1491 public final LearnedConstraintsDeletionStrategy glucose = new LearnedConstraintsDeletionStrategy() {
1492
1493 private static final long serialVersionUID = 1L;
1494 private int[] flags = new int[0];
1495 private int flag = 0;
1496 private int wall = 0;
1497
1498 private final ConflictTimer clauseManagement = new ConflictTimerAdapter(
1499 1000) {
1500 private static final long serialVersionUID = 1L;
1501 private int nbconflict = 0;
1502 private static final int MAX_CLAUSE = 5000;
1503 private static final int INC_CLAUSE = 1000;
1504 private int nextbound = MAX_CLAUSE;
1505
1506 @Override
1507 void run() {
1508 nbconflict += bound();
1509 if (nbconflict >= nextbound) {
1510 nextbound += INC_CLAUSE;
1511 if (nextbound > wall) {
1512 nextbound = wall;
1513 }
1514 nbconflict = 0;
1515 needToReduceDB = true;
1516 }
1517 }
1518
1519 @Override
1520 public void reset() {
1521 super.reset();
1522 nextbound = MAX_CLAUSE;
1523 if (nbconflict >= nextbound) {
1524 nbconflict = 0;
1525 needToReduceDB = true;
1526 }
1527 }
1528 };
1529
1530 public void reduce(IVec<Constr> learnedConstrs) {
1531 sortOnActivity();
1532 int i, j;
1533 for (i = j = learnedConstrs.size() / 2; i < learnedConstrs.size(); i++) {
1534 Constr c = learnedConstrs.get(i);
1535 if (c.locked() || c.getActivity() <= 2.0) {
1536 learnedConstrs.set(j++, learnts.get(i));
1537 } else {
1538 c.remove(Solver.this);
1539 }
1540 }
1541 if (verbose) {
1542 System.out
1543 .println(getLogPrefix()
1544 + "cleaning " + (learnedConstrs.size() - j)
1545 + " clauses out of " + learnedConstrs.size() + " with flag " + flag + "/" + stats.conflicts);
1546 System.out.flush();
1547 }
1548 learnts.shrinkTo(j);
1549
1550 }
1551
1552 public ConflictTimer getTimer() {
1553 return clauseManagement;
1554 }
1555
1556 @Override
1557 public String toString() {
1558 return "Glucose learned constraints deletion strategy";
1559 }
1560
1561 public void init() {
1562 final int howmany = voc.nVars();
1563 wall = constrs.size() > 10000 ? constrs.size() : 10000;
1564 if (flags.length <= howmany) {
1565 flags = new int[howmany + 1];
1566 }
1567 flag = 0;
1568 clauseManagement.reset();
1569 }
1570
1571 public void onConflict(Constr constr) {
1572 int nblevel = 1;
1573 flag++;
1574 int currentLevel;
1575 for (int i = 1; i < constr.size(); i++) {
1576 currentLevel = voc.getLevel(constr.get(i));
1577 if (flags[currentLevel] != flag) {
1578 flags[currentLevel] = flag;
1579 nblevel++;
1580 }
1581 }
1582 constr.incActivity(nblevel);
1583 }
1584
1585 public void onConflictAnalysis(Constr reason) {
1586
1587 }
1588 };
1589
1590 private LearnedConstraintsDeletionStrategy learnedConstraintsDeletionStrategy = glucose;
1591
1592
1593
1594
1595
1596 public void setLearnedConstraintsDeletionStrategy(
1597 LearnedConstraintsDeletionStrategy lcds) {
1598 learnedConstraintsDeletionStrategy = lcds;
1599 }
1600
1601 public boolean isSatisfiable(IVecInt assumps, boolean global)
1602 throws TimeoutException {
1603 Lbool status = Lbool.UNDEFINED;
1604 final int howmany = voc.nVars();
1605 if (mseen.length <= howmany) {
1606 mseen = new boolean[howmany + 1];
1607 }
1608 trail.ensure(howmany);
1609 trailLim.ensure(howmany);
1610 learnedLiterals.ensure(howmany);
1611 decisions.clear();
1612 implied.clear();
1613 slistener.start();
1614 model = null;
1615 userbooleanmodel = null;
1616 unsatExplanationInTermsOfAssumptions = null;
1617 order.init();
1618 learnedConstraintsDeletionStrategy.init();
1619 int learnedLiteralsLimit = trail.size();
1620
1621
1622 qhead = 0;
1623
1624
1625 for (int i = learnedLiteralsLimit - 1; i >= 0; i--) {
1626 int p = trail.get(i);
1627 IVec<Undoable> undos = voc.undos(p);
1628 assert undos != null;
1629 for (int size = undos.size(); size > 0; size--) {
1630 undos.last().undo(p);
1631 undos.pop();
1632 }
1633 }
1634
1635
1636 for (IteratorInt iterator = learnedLiterals.iterator(); iterator
1637 .hasNext();) {
1638 enqueue(iterator.next());
1639 }
1640
1641
1642 Constr confl = propagate();
1643 if (confl != null) {
1644 analyzeAtRootLevel(confl);
1645 slistener.conflictFound(confl, 0, 0);
1646 slistener.end(Lbool.FALSE);
1647 cancelUntil(0);
1648 cancelLearntLiterals(learnedLiteralsLimit);
1649 return false;
1650 }
1651
1652
1653 for (IteratorInt iterator = assumps.iterator(); iterator.hasNext();) {
1654 int assump = iterator.next();
1655 int p = voc.getFromPool(assump);
1656 if ((!voc.isSatisfied(p) && !assume(p))
1657 || ((confl = propagate()) != null)) {
1658 if (confl == null) {
1659 slistener.conflictFound(p);
1660 unsatExplanationInTermsOfAssumptions = analyzeFinalConflictInTermsOfAssumptions(
1661 null, assumps, p);
1662 unsatExplanationInTermsOfAssumptions.push(assump);
1663 } else {
1664 slistener.conflictFound(confl, decisionLevel(),
1665 trail.size());
1666 unsatExplanationInTermsOfAssumptions = analyzeFinalConflictInTermsOfAssumptions(
1667 confl, assumps, ILits.UNDEFINED);
1668 }
1669
1670 slistener.end(Lbool.FALSE);
1671 cancelUntil(0);
1672 cancelLearntLiterals(learnedLiteralsLimit);
1673 return false;
1674 }
1675 }
1676 rootLevel = decisionLevel();
1677
1678
1679 order.init();
1680 learner.init();
1681
1682 boolean firstTimeGlobal = false;
1683 if (timeBasedTimeout) {
1684 if (!global || timer == null) {
1685 firstTimeGlobal = true;
1686 undertimeout = true;
1687 TimerTask stopMe = new TimerTask() {
1688 @Override
1689 public void run() {
1690 undertimeout = false;
1691 }
1692 };
1693 timer = new Timer(true);
1694 timer.schedule(stopMe, timeout);
1695 conflictCount = learnedConstraintsDeletionStrategy.getTimer();
1696 }
1697 } else {
1698 if (!global || conflictCount == null) {
1699 firstTimeGlobal = true;
1700 undertimeout = true;
1701 ConflictTimer conflictTimeout = new ConflictTimerAdapter(
1702 (int) timeout) {
1703 private static final long serialVersionUID = 1L;
1704
1705 @Override
1706 public void run() {
1707 undertimeout = false;
1708 }
1709 };
1710 conflictCount = new ConflictTimerContainer().add(
1711 conflictTimeout).add(
1712 learnedConstraintsDeletionStrategy.getTimer());
1713 }
1714 }
1715 if (!global || firstTimeGlobal) {
1716 restarter.init(params);
1717 timebegin = System.currentTimeMillis();
1718 }
1719 needToReduceDB = false;
1720
1721 while ((status == Lbool.UNDEFINED) && undertimeout) {
1722 status = search(restarter.nextRestartNumberOfConflict(), assumps);
1723 if (status == Lbool.UNDEFINED) {
1724 restarter.onRestart();
1725 slistener.restarting();
1726 }
1727 }
1728
1729 cancelUntil(0);
1730 cancelLearntLiterals(learnedLiteralsLimit);
1731 if (!global && timeBasedTimeout) {
1732 timer.cancel();
1733 timer = null;
1734 }
1735 slistener.end(status);
1736 if (!undertimeout) {
1737 String message = " Timeout (" + timeout
1738 + (timeBasedTimeout ? "s" : " conflicts") + ") exceeded";
1739 throw new TimeoutException(message);
1740 }
1741 return status == Lbool.TRUE;
1742 }
1743
1744 public void printInfos(PrintWriter out, String prefix) {
1745 out.print(prefix);
1746 out.println("constraints type ");
1747 long total = 0;
1748 for (Map.Entry<String, Counter> entry : constrTypes.entrySet()) {
1749 out.println(prefix + entry.getKey() + " => " + entry.getValue());
1750 total += entry.getValue().getValue();
1751 }
1752 out.print(prefix);
1753 out.print(total);
1754 out.println(" constraints processed.");
1755 }
1756
1757
1758
1759
1760 public void printLearntClausesInfos(PrintWriter out, String prefix) {
1761 Map<String, Counter> learntTypes = new HashMap<String, Counter>();
1762 for (Iterator<Constr> it = learnts.iterator(); it.hasNext();) {
1763 String type = it.next().getClass().getName();
1764 Counter count = learntTypes.get(type);
1765 if (count == null) {
1766 learntTypes.put(type, new Counter());
1767 } else {
1768 count.inc();
1769 }
1770 }
1771 out.print(prefix);
1772 out.println("learnt constraints type ");
1773 for (Map.Entry<String, Counter> entry : learntTypes.entrySet()) {
1774 out.println(prefix + entry.getKey() + " => " + entry.getValue());
1775 }
1776 }
1777
1778 public SolverStats getStats() {
1779 return stats;
1780 }
1781
1782
1783
1784
1785
1786
1787 protected void initStats(SolverStats myStats) {
1788 this.stats = myStats;
1789 }
1790
1791 public IOrder getOrder() {
1792 return order;
1793 }
1794
1795 public void setOrder(IOrder h) {
1796 order = h;
1797 order.setLits(voc);
1798 }
1799
1800 public ILits getVocabulary() {
1801 return voc;
1802 }
1803
1804 public void reset() {
1805 trail.clear();
1806 trailLim.clear();
1807 qhead = 0;
1808 for (Iterator<Constr> iterator = constrs.iterator(); iterator.hasNext();)
1809 iterator.next().remove(this);
1810 constrs.clear();
1811 clearLearntClauses();
1812 voc.resetPool();
1813 dsfactory.reset();
1814 stats.reset();
1815 constrTypes.clear();
1816 }
1817
1818 public int nVars() {
1819 if (declaredMaxVarId == 0) {
1820 return voc.nVars();
1821 }
1822 return declaredMaxVarId;
1823 }
1824
1825
1826
1827
1828
1829
1830 protected IConstr addConstr(Constr constr) {
1831 if (constr == null) {
1832 Counter count = constrTypes.get("ignored satisfied constraints");
1833 if (count == null) {
1834 constrTypes.put("ignored satisfied constraints", new Counter());
1835 } else {
1836 count.inc();
1837 }
1838 } else {
1839 constrs.push(constr);
1840 String type = constr.getClass().getName();
1841 Counter count = constrTypes.get(type);
1842 if (count == null) {
1843 constrTypes.put(type, new Counter());
1844 } else {
1845 count.inc();
1846 }
1847 }
1848 return constr;
1849 }
1850
1851 public DataStructureFactory getDSFactory() {
1852 return dsfactory;
1853 }
1854
1855 public IVecInt getOutLearnt() {
1856 return moutLearnt;
1857 }
1858
1859
1860
1861
1862
1863
1864
1865
1866 public IConstr getIthConstr(int i) {
1867 return constrs.get(i);
1868 }
1869
1870
1871
1872
1873
1874
1875
1876 public void printStat(PrintStream out, String prefix) {
1877 printStat(new PrintWriter(out, true), prefix);
1878 }
1879
1880 public void printStat(PrintWriter out, String prefix) {
1881 stats.printStat(out, prefix);
1882 double cputime = (System.currentTimeMillis() - timebegin) / 1000;
1883 out.println(prefix
1884 + "speed (assignments/second)\t: " + stats.propagations
1885 / cputime);
1886 order.printStat(out, prefix);
1887 printLearntClausesInfos(out, prefix);
1888 }
1889
1890
1891
1892
1893
1894
1895 public String toString(String prefix) {
1896 StringBuffer stb = new StringBuffer();
1897 Object[] objs = { dsfactory, learner, params, order, simplifier,
1898 restarter, learnedConstraintsDeletionStrategy };
1899 stb.append(prefix);
1900 stb.append("--- Begin Solver configuration ---");
1901 stb.append("\n");
1902 for (Object o : objs) {
1903 stb.append(prefix);
1904 stb.append(o.toString());
1905 stb.append("\n");
1906 }
1907 stb.append(prefix);
1908 stb.append("timeout=");
1909 if (timeBasedTimeout) {
1910 stb.append(timeout / 1000);
1911 stb.append("s\n");
1912 } else {
1913 stb.append(timeout);
1914 stb.append(" conflicts\n");
1915 }
1916 stb.append(prefix);
1917 stb.append("DB Simplification allowed=");
1918 stb.append(isDBSimplificationAllowed);
1919 stb.append("\n");
1920 stb.append(prefix);
1921 stb.append("--- End Solver configuration ---");
1922 return stb.toString();
1923 }
1924
1925
1926
1927
1928
1929
1930 @Override
1931 public String toString() {
1932 return toString("");
1933 }
1934
1935 public int getTimeout() {
1936 return (int) (timeBasedTimeout ? timeout / 1000 : timeout);
1937 }
1938
1939
1940
1941
1942 public long getTimeoutMs() {
1943 if (!timeBasedTimeout) {
1944 throw new UnsupportedOperationException(
1945 "The timeout is given in number of conflicts!");
1946 }
1947 return timeout;
1948 }
1949
1950 public void setExpectedNumberOfClauses(int nb) {
1951 constrs.ensure(nb);
1952 }
1953
1954 public Map<String, Number> getStat() {
1955 return stats.toMap();
1956 }
1957
1958 public int[] findModel() throws TimeoutException {
1959 if (isSatisfiable()) {
1960 return model();
1961 }
1962
1963
1964 return null;
1965 }
1966
1967 public int[] findModel(IVecInt assumps) throws TimeoutException {
1968 if (isSatisfiable(assumps)) {
1969 return model();
1970 }
1971
1972
1973 return null;
1974 }
1975
1976 public boolean isDBSimplificationAllowed() {
1977 return isDBSimplificationAllowed;
1978 }
1979
1980 public void setDBSimplificationAllowed(boolean status) {
1981 isDBSimplificationAllowed = status;
1982 }
1983
1984
1985
1986
1987 public int nextFreeVarId(boolean reserve) {
1988 return voc.nextFreeVarId(reserve);
1989 }
1990
1991
1992
1993
1994 public IConstr addBlockingClause(IVecInt literals)
1995 throws ContradictionException {
1996 return addClause(literals);
1997 }
1998
1999
2000
2001
2002 public void unset(int p) {
2003
2004
2005 if (voc.isUnassigned(p) || trail.isEmpty()) {
2006 return;
2007 }
2008 int current = trail.last();
2009 while (current != p) {
2010 undoOne();
2011 if (trail.isEmpty()) {
2012 return;
2013 }
2014 current = trail.last();
2015 }
2016 undoOne();
2017 qhead = trail.size();
2018 }
2019
2020
2021
2022
2023 public void setLogPrefix(String prefix) {
2024 this.prefix = prefix;
2025 }
2026
2027
2028
2029
2030 public String getLogPrefix() {
2031 return prefix;
2032 }
2033
2034
2035
2036
2037 public IVecInt unsatExplanation() {
2038 IVecInt copy = new VecInt(unsatExplanationInTermsOfAssumptions.size());
2039 unsatExplanationInTermsOfAssumptions.copyTo(copy);
2040 return copy;
2041 }
2042
2043
2044
2045
2046 public int[] modelWithInternalVariables() {
2047 if (model == null) {
2048 throw new UnsupportedOperationException(
2049 "Call the solve method first!!!");
2050 }
2051 int[] nmodel;
2052 if (nVars() == realNumberOfVariables()) {
2053 nmodel = new int[model.length];
2054 System.arraycopy(model, 0, nmodel, 0, nmodel.length);
2055 } else {
2056 nmodel = new int[fullmodel.length];
2057 System.arraycopy(fullmodel, 0, nmodel, 0, nmodel.length);
2058 }
2059
2060 return nmodel;
2061 }
2062
2063
2064
2065
2066 public int realNumberOfVariables() {
2067 return voc.nVars();
2068 }
2069
2070 }
2071
2072 class ActivityComparator implements Comparator<Constr>, Serializable {
2073
2074 private static final long serialVersionUID = 1L;
2075
2076
2077
2078
2079
2080
2081 public int compare(Constr c1, Constr c2) {
2082 long delta = Math.round(c1.getActivity() - c2.getActivity());
2083 if (delta == 0) {
2084 return c1.size() - c2.size();
2085 }
2086 return (int) delta;
2087 }
2088 }
2089
2090 interface ConflictTimer {
2091
2092 void reset();
2093
2094 void newConflict();
2095 }
2096
2097 abstract class ConflictTimerAdapter implements Serializable, ConflictTimer {
2098
2099
2100
2101
2102 private static final long serialVersionUID = 1L;
2103
2104 private int counter;
2105
2106 private final int bound;
2107
2108 ConflictTimerAdapter(final int bound) {
2109 this.bound = bound;
2110 counter = 0;
2111 }
2112
2113 public void reset() {
2114 counter = 0;
2115 }
2116
2117 public void newConflict() {
2118 counter++;
2119 if (counter == bound) {
2120 run();
2121 counter = 0;
2122 }
2123 }
2124
2125 abstract void run();
2126
2127 public int bound() {
2128 return bound;
2129 }
2130 }
2131
2132 class ConflictTimerContainer implements Serializable, ConflictTimer {
2133
2134
2135
2136
2137 private static final long serialVersionUID = 1L;
2138
2139 private final IVec<ConflictTimer> timers = new Vec<ConflictTimer>();
2140
2141 ConflictTimerContainer add(ConflictTimer timer) {
2142 timers.push(timer);
2143 return this;
2144 }
2145
2146 public void reset() {
2147 Iterator<ConflictTimer> it = timers.iterator();
2148 while (it.hasNext()) {
2149 it.next().reset();
2150 }
2151 }
2152
2153 public void newConflict() {
2154 Iterator<ConflictTimer> it = timers.iterator();
2155 while (it.hasNext()) {
2156 it.next().newConflict();
2157 }
2158 }
2159 }