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