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.Vec;
67 import org.sat4j.core.VecInt;
68 import org.sat4j.specs.ContradictionException;
69 import org.sat4j.specs.IConstr;
70 import org.sat4j.specs.ISolver;
71 import org.sat4j.specs.IVec;
72 import org.sat4j.specs.IVecInt;
73 import org.sat4j.specs.IteratorInt;
74 import org.sat4j.specs.Lbool;
75 import org.sat4j.specs.SearchListener;
76 import org.sat4j.specs.TimeoutException;
77
78
79
80
81
82
83
84 public class Solver<D extends DataStructureFactory> implements ISolver,
85 UnitPropagationListener, ActivityListener, Learner {
86
87 private static final long serialVersionUID = 1L;
88
89 private static final double CLAUSE_RESCALE_FACTOR = 1e-20;
90
91 private static final double CLAUSE_RESCALE_BOUND = 1 / CLAUSE_RESCALE_FACTOR;
92
93
94
95
96 private final IVec<Constr> constrs = new Vec<Constr>();
97
98
99
100
101 private final IVec<Constr> learnts = new Vec<Constr>();
102
103
104
105
106 private double claInc = 1.0;
107
108
109
110
111 private double claDecay = 1.0;
112
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 final SolverStats stats = new SolverStats();
150
151 private final LearningStrategy<D> learner;
152
153 protected final AssertingClauseGenerator analyzer;
154
155 private volatile boolean undertimeout;
156
157 private long timeout = Integer.MAX_VALUE;
158
159 private boolean timeBasedTimeout = true;
160
161 protected D dsfactory;
162
163 private SearchParams params;
164
165 private final IVecInt __dimacs_out = new VecInt();
166
167 private SearchListener slistener = new NullSearchListener();
168
169 private RestartStrategy restarter;
170
171 private final Map<String, Counter> constrTypes = new HashMap<String, Counter>();
172
173 private boolean isDBSimplificationAllowed = false;
174
175 private final IVecInt learnedLiterals = new VecInt();
176
177 protected IVecInt dimacs2internal(IVecInt in) {
178
179
180
181
182
183 __dimacs_out.clear();
184 __dimacs_out.ensure(in.size());
185 for (int i = 0; i < in.size(); i++) {
186 assert (in.get(i) != 0);
187 __dimacs_out.unsafePush(voc.getFromPool(in.get(i)));
188 }
189 return __dimacs_out;
190 }
191
192
193
194
195
196
197
198
199
200
201 public Solver(AssertingClauseGenerator acg, LearningStrategy<D> learner,
202 D dsf, IOrder order, RestartStrategy restarter) {
203 this(acg, learner, dsf, new SearchParams(), order, restarter);
204 }
205
206 public Solver(AssertingClauseGenerator acg, LearningStrategy<D> learner,
207 D dsf, SearchParams params, IOrder order, RestartStrategy restarter) {
208 analyzer = acg;
209 this.learner = learner;
210 this.order = order;
211 this.params = params;
212 setDataStructureFactory(dsf);
213 this.restarter = restarter;
214 }
215
216
217
218
219
220
221
222
223 public final void setDataStructureFactory(D dsf) {
224 dsfactory = dsf;
225 dsfactory.setUnitPropagationListener(this);
226 dsfactory.setLearner(this);
227 voc = dsf.getVocabulary();
228 order.setLits(voc);
229 }
230
231
232
233
234 public void setSearchListener(SearchListener sl) {
235 slistener = sl;
236 }
237
238 public void setTimeout(int t) {
239 timeout = t * 1000L;
240 timeBasedTimeout = true;
241 }
242
243 public void setTimeoutMs(long t) {
244 timeout = t;
245 timeBasedTimeout = true;
246 }
247
248 public void setTimeoutOnConflicts(int count) {
249 timeout = count;
250 timeBasedTimeout = false;
251 }
252
253 public void setSearchParams(SearchParams sp) {
254 params = sp;
255 }
256
257 public void setRestartStrategy(RestartStrategy restarter) {
258 this.restarter = restarter;
259 }
260
261 public void expireTimeout() {
262 undertimeout = false;
263 }
264
265 protected int nAssigns() {
266 return trail.size();
267 }
268
269 public int nConstraints() {
270 return constrs.size() + trail.size();
271 }
272
273 public void learn(Constr c) {
274 learnts.push(c);
275 c.setLearnt();
276 c.register();
277 stats.learnedclauses++;
278 switch (c.size()) {
279 case 2:
280 stats.learnedbinaryclauses++;
281 break;
282 case 3:
283 stats.learnedternaryclauses++;
284 break;
285 default:
286
287 }
288 }
289
290 public int decisionLevel() {
291 return trailLim.size();
292 }
293
294 @Deprecated
295 public int newVar() {
296 int index = voc.nVars() + 1;
297 voc.ensurePool(index);
298 return index;
299 }
300
301 public int newVar(int howmany) {
302 voc.ensurePool(howmany);
303 return voc.nVars();
304 }
305
306 public IConstr addClause(IVecInt literals) throws ContradictionException {
307 IVecInt vlits = dimacs2internal(literals);
308 return addConstr(dsfactory.createClause(vlits));
309 }
310
311 public boolean removeConstr(IConstr co) {
312 if (co == null) {
313 throw new IllegalArgumentException(
314 "Reference to the constraint to remove needed!");
315 }
316 Constr c = (Constr) co;
317 c.remove(this);
318 constrs.remove(c);
319 clearLearntClauses();
320 String type = c.getClass().getName();
321 constrTypes.get(type).dec();
322 return true;
323 }
324
325
326
327
328 public boolean removeSubsumedConstr(IConstr co) {
329 if (co == null) {
330 throw new IllegalArgumentException(
331 "Reference to the constraint to remove needed!");
332 }
333 if (constrs.last() != co) {
334 throw new IllegalArgumentException(
335 "Can only remove latest added constraint!!!");
336 }
337 Constr c = (Constr) co;
338 c.remove(this);
339 constrs.pop();
340 String type = c.getClass().getName();
341 constrTypes.get(type).dec();
342 return true;
343 }
344
345 public void addAllClauses(IVec<IVecInt> clauses)
346 throws ContradictionException {
347 for (Iterator<IVecInt> iterator = clauses.iterator(); iterator
348 .hasNext();) {
349 addClause(iterator.next());
350 }
351 }
352
353 public IConstr addAtMost(IVecInt literals, int degree)
354 throws ContradictionException {
355 int n = literals.size();
356 IVecInt opliterals = new VecInt(n);
357 for (IteratorInt iterator = literals.iterator(); iterator.hasNext();) {
358 opliterals.push(-iterator.next());
359 }
360 return addAtLeast(opliterals, n - degree);
361 }
362
363 public IConstr addAtLeast(IVecInt literals, int degree)
364 throws ContradictionException {
365 IVecInt vlits = dimacs2internal(literals);
366 return addConstr(dsfactory.createCardinalityConstraint(vlits, degree));
367 }
368
369 @SuppressWarnings("unchecked")
370 public boolean simplifyDB() {
371
372
373
374
375
376
377
378
379 IVec<Constr>[] cs = new IVec[] { constrs, learnts };
380 for (int type = 0; type < 2; type++) {
381 int j = 0;
382 for (int i = 0; i < cs[type].size(); i++) {
383 if (cs[type].get(i).simplify()) {
384
385 cs[type].get(i).remove(this);
386 } else {
387 cs[type].moveTo(j++, i);
388 }
389 }
390 cs[type].shrinkTo(j);
391 }
392 return true;
393 }
394
395
396
397
398
399
400 public int[] model() {
401 if (model == null) {
402 throw new UnsupportedOperationException(
403 "Call the solve method first!!!");
404 }
405 int[] nmodel = new int[model.length];
406 System.arraycopy(model, 0, nmodel, 0, model.length);
407 return nmodel;
408 }
409
410
411
412
413
414
415
416
417 public boolean enqueue(int p) {
418 return enqueue(p, null);
419 }
420
421
422
423
424
425
426
427
428
429
430
431 public boolean enqueue(int p, Constr from) {
432 assert p > 1;
433 if (voc.isSatisfied(p)) {
434
435 return true;
436 }
437 if (voc.isFalsified(p)) {
438
439 return false;
440 }
441
442 voc.satisfies(p);
443 voc.setLevel(p, decisionLevel());
444 voc.setReason(p, from);
445 trail.push(p);
446 if (from != null) {
447 from.forwardActivity(claInc);
448 }
449 return true;
450 }
451
452 private boolean[] mseen = new boolean[0];
453
454 private final IVecInt preason = new VecInt();
455
456 private final IVecInt outLearnt = new VecInt();
457
458 public void analyze(Constr confl, Pair results) {
459 assert confl != null;
460 outLearnt.clear();
461
462 final boolean[] seen = mseen;
463
464 assert outLearnt.size() == 0;
465 for (int i = 0; i < seen.length; i++) {
466 seen[i] = false;
467 }
468
469 analyzer.initAnalyze();
470 int p = ILits.UNDEFINED;
471
472 outLearnt.push(ILits.UNDEFINED);
473
474 int outBtlevel = 0;
475
476 do {
477 preason.clear();
478 assert confl != null;
479 confl.calcReason(p, preason);
480 learnedConstraintsDeletionStrategy.onConflictAnalysis(confl);
481
482 for (int j = 0; j < preason.size(); j++) {
483 int q = preason.get(j);
484 order.updateVar(q);
485 if (!seen[q >> 1]) {
486
487 seen[q >> 1] = true;
488 if (voc.getLevel(q) == decisionLevel()) {
489 analyzer.onCurrentDecisionLevelLiteral(q);
490 } else if (voc.getLevel(q) > 0) {
491
492 outLearnt.push(q ^ 1);
493 outBtlevel = Math.max(outBtlevel, voc.getLevel(q));
494 }
495 }
496 }
497
498
499 do {
500 p = trail.last();
501 confl = voc.getReason(p);
502 undoOne();
503 } while (!seen[p >> 1]);
504
505
506 } while (analyzer.clauseNonAssertive(confl));
507
508 outLearnt.set(0, p ^ 1);
509 simplifier.simplify(outLearnt);
510
511 Constr c = dsfactory.createUnregisteredClause(outLearnt);
512 slistener.learn(c);
513 learnedConstraintsDeletionStrategy.onConflict(c);
514 results.reason = c;
515
516 assert outBtlevel > -1;
517 results.backtrackLevel = outBtlevel;
518 }
519
520 interface ISimplifier extends Serializable {
521 void simplify(IVecInt outLearnt);
522 }
523
524 public static final ISimplifier NO_SIMPLIFICATION = new ISimplifier() {
525
526
527
528 private static final long serialVersionUID = 1L;
529
530 public void simplify(IVecInt outLearnt) {
531 }
532
533 @Override
534 public String toString() {
535 return "No reason simplification";
536 }
537 };
538
539 public final ISimplifier SIMPLE_SIMPLIFICATION = new ISimplifier() {
540
541
542
543 private static final long serialVersionUID = 1L;
544
545 public void simplify(IVecInt conflictToReduce) {
546 simpleSimplification(conflictToReduce);
547 }
548
549 @Override
550 public String toString() {
551 return "Simple reason simplification";
552 }
553 };
554
555 public final ISimplifier EXPENSIVE_SIMPLIFICATION = new ISimplifier() {
556
557
558
559
560 private static final long serialVersionUID = 1L;
561
562 public void simplify(IVecInt conflictToReduce) {
563 expensiveSimplification(conflictToReduce);
564 }
565
566 @Override
567 public String toString() {
568 return "Expensive reason simplification";
569 }
570 };
571
572 private ISimplifier simplifier = NO_SIMPLIFICATION;
573
574
575
576
577
578
579
580
581
582
583 public void setSimplifier(String simp) {
584 Field f;
585 try {
586 f = Solver.class.getDeclaredField(simp);
587 simplifier = (ISimplifier) f.get(this);
588 } catch (Exception e) {
589 e.printStackTrace();
590 simplifier = NO_SIMPLIFICATION;
591 }
592 }
593
594
595
596
597
598
599
600
601
602
603 public void setSimplifier(ISimplifier simp) {
604 simplifier = simp;
605 }
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629 private void simpleSimplification(IVecInt conflictToReduce) {
630 int i, j;
631 final boolean[] seen = mseen;
632 for (i = j = 1; i < conflictToReduce.size(); i++) {
633 IConstr r = voc.getReason(conflictToReduce.get(i));
634 if (r == null) {
635 conflictToReduce.moveTo(j++, i);
636 } else {
637 for (int k = 0; k < r.size(); k++)
638 if (voc.isFalsified(r.get(k)) && !seen[r.get(k) >> 1]
639 && (voc.getLevel(r.get(k)) != 0)) {
640 conflictToReduce.moveTo(j++, i);
641 break;
642 }
643 }
644 }
645 conflictToReduce.shrink(i - j);
646 stats.reducedliterals += (i - j);
647 }
648
649 private final IVecInt analyzetoclear = new VecInt();
650
651 private final IVecInt analyzestack = new VecInt();
652
653
654 private void expensiveSimplification(IVecInt conflictToReduce) {
655
656
657 int i, j;
658
659 analyzetoclear.clear();
660 conflictToReduce.copyTo(analyzetoclear);
661 for (i = 1, j = 1; i < conflictToReduce.size(); i++)
662 if (voc.getReason(conflictToReduce.get(i)) == null
663 || !analyzeRemovable(conflictToReduce.get(i)))
664 conflictToReduce.moveTo(j++, i);
665 conflictToReduce.shrink(i - j);
666 stats.reducedliterals += (i - j);
667 }
668
669
670
671
672 private boolean analyzeRemovable(int p) {
673 assert voc.getReason(p) != null;
674 analyzestack.clear();
675 analyzestack.push(p);
676 final boolean[] seen = mseen;
677 int top = analyzetoclear.size();
678 while (analyzestack.size() > 0) {
679 int q = analyzestack.last();
680 assert voc.getReason(q) != null;
681 Constr c = voc.getReason(q);
682 analyzestack.pop();
683 for (int i = 0; i < c.size(); i++) {
684 int l = c.get(i);
685 if (voc.isFalsified(l) && !seen[var(l)] && voc.getLevel(l) != 0) {
686 if (voc.getReason(l) == null) {
687 for (int j = top; j < analyzetoclear.size(); j++)
688 seen[analyzetoclear.get(j) >> 1] = false;
689 analyzetoclear.shrink(analyzetoclear.size() - top);
690 return false;
691 }
692 seen[l >> 1] = true;
693 analyzestack.push(l);
694 analyzetoclear.push(l);
695 }
696 }
697 }
698
699 return true;
700 }
701
702
703
704
705
706
707 protected void undoOne() {
708
709 int p = trail.last();
710 assert p > 1;
711 assert voc.getLevel(p) >= 0;
712 int x = p >> 1;
713
714 voc.unassign(p);
715 voc.setReason(p, null);
716 voc.setLevel(p, -1);
717
718 order.undo(x);
719
720 trail.pop();
721
722
723
724 IVec<Undoable> undos = voc.undos(p);
725 assert undos != null;
726 while (undos.size() > 0) {
727 undos.last().undo(p);
728 undos.pop();
729 }
730 }
731
732
733
734
735
736
737
738 public void claBumpActivity(Constr confl) {
739 confl.incActivity(claInc);
740 if (confl.getActivity() > CLAUSE_RESCALE_BOUND)
741 claRescalActivity();
742
743
744
745 }
746
747 public void varBumpActivity(int p) {
748 order.updateVar(p);
749 }
750
751 private void claRescalActivity() {
752 for (int i = 0; i < learnts.size(); i++) {
753 learnts.get(i).rescaleBy(CLAUSE_RESCALE_FACTOR);
754 }
755 claInc *= CLAUSE_RESCALE_FACTOR;
756 }
757
758
759
760
761 public Constr propagate() {
762 while (qhead < trail.size()) {
763 stats.propagations++;
764 int p = trail.get(qhead++);
765 slistener.propagating(toDimacs(p), null);
766 order.assignLiteral(p);
767
768
769
770 assert p > 1;
771 IVec<Propagatable> watched = dsfactory.getWatchesFor(p);
772
773 final int size = watched.size();
774 for (int i = 0; i < size; i++) {
775 stats.inspects++;
776 if (!watched.get(i).propagate(this, p)) {
777
778
779
780 dsfactory.conflictDetectedInWatchesFor(p, i);
781 qhead = trail.size();
782
783 return (Constr) watched.get(i);
784 }
785 }
786 }
787 return null;
788 }
789
790 void record(Constr constr) {
791 constr.assertConstraint(this);
792 slistener.adding(toDimacs(constr.get(0)));
793 if (constr.size() == 1) {
794 stats.learnedliterals++;
795 } else {
796 learner.learns(constr);
797 }
798 }
799
800
801
802
803 public boolean assume(int p) {
804
805 assert trail.size() == qhead;
806 trailLim.push(trail.size());
807 return enqueue(p);
808 }
809
810
811
812
813 private void cancel() {
814
815 int decisionvar = trail.unsafeGet(trailLim.last());
816 slistener.backtracking(toDimacs(decisionvar));
817 for (int c = trail.size() - trailLim.last(); c > 0; c--) {
818 undoOne();
819 }
820 trailLim.pop();
821 }
822
823
824
825
826 private void cancelLearntLiterals(int learnedLiteralsLimit) {
827 learnedLiterals.clear();
828
829 while (trail.size() > learnedLiteralsLimit) {
830 learnedLiterals.push(trail.last());
831 undoOne();
832 }
833 qhead = trail.size();
834
835 }
836
837
838
839
840
841
842 protected void cancelUntil(int level) {
843 while (decisionLevel() > level) {
844 cancel();
845 }
846 qhead = trail.size();
847 }
848
849 private final Pair analysisResult = new Pair();
850
851 private boolean[] fullmodel;
852
853 Lbool search(long nofConflicts) {
854 assert rootLevel == decisionLevel();
855 stats.starts++;
856 int conflictC = 0;
857
858
859 order.setVarDecay(1 / params.getVarDecay());
860 claDecay = 1 / params.getClaDecay();
861
862 do {
863 slistener.beginLoop();
864
865 Constr confl = propagate();
866 assert trail.size() == qhead;
867
868 if (confl == null) {
869
870
871
872 if (decisionLevel() == 0 && isDBSimplificationAllowed) {
873
874
875 stats.rootSimplifications++;
876 boolean ret = simplifyDB();
877 assert ret;
878 }
879
880
881 assert nAssigns() <= voc.realnVars();
882 if (nAssigns() == voc.realnVars()) {
883 slistener.solutionFound();
884 modelFound();
885 return Lbool.TRUE;
886 }
887 if (conflictC >= nofConflicts) {
888
889
890 cancelUntil(rootLevel);
891 return Lbool.UNDEFINED;
892 }
893 if (needToReduceDB) {
894 reduceDB();
895 needToReduceDB = false;
896
897 }
898
899 stats.decisions++;
900 int p = order.select();
901 assert p > 1;
902 slistener.assuming(toDimacs(p));
903 boolean ret = assume(p);
904 assert ret;
905 } else {
906
907 stats.conflicts++;
908 conflictC++;
909 slistener.conflictFound(confl);
910 conflictCount.newConflict();
911 if (decisionLevel() == rootLevel) {
912
913 return Lbool.FALSE;
914 }
915
916 analyze(confl, analysisResult);
917 assert analysisResult.backtrackLevel < decisionLevel();
918 cancelUntil(Math.max(analysisResult.backtrackLevel, rootLevel));
919 assert (decisionLevel() >= rootLevel)
920 && (decisionLevel() >= analysisResult.backtrackLevel);
921 if (analysisResult.reason == null) {
922 return Lbool.FALSE;
923 }
924 record(analysisResult.reason);
925 analysisResult.reason = null;
926 decayActivities();
927 }
928 } while (undertimeout);
929 return Lbool.UNDEFINED;
930 }
931
932 protected void analyzeAtRootLevel(Constr conflict) {
933 }
934
935
936
937
938 void modelFound() {
939 model = new int[trail.size()];
940 fullmodel = new boolean[nVars()];
941 int index = 0;
942 for (int i = 1; i <= voc.nVars(); i++) {
943 if (voc.belongsToPool(i)) {
944 int p = voc.getFromPool(i);
945 if (!voc.isUnassigned(p)) {
946 model[index++] = voc.isSatisfied(p) ? i : -i;
947 fullmodel[i - 1] = voc.isSatisfied(p);
948 }
949 }
950 }
951 assert index == model.length;
952 cancelUntil(rootLevel);
953 }
954
955 public boolean model(int var) {
956 if (var <= 0 || var > nVars()) {
957 throw new IllegalArgumentException(
958 "Use a valid Dimacs var id as argument!");
959 }
960 if (fullmodel == null) {
961 throw new UnsupportedOperationException(
962 "Call the solve method first!!!");
963 }
964 return fullmodel[var - 1];
965 }
966
967 public void clearLearntClauses() {
968 for (Iterator<Constr> iterator = learnts.iterator(); iterator.hasNext();)
969 iterator.next().remove(this);
970 learnts.clear();
971 learnedLiterals.clear();
972 }
973
974 protected void reduceDB() {
975 sortOnActivity();
976 stats.reduceddb++;
977 learnedConstraintsDeletionStrategy.reduce(learnts);
978 System.gc();
979 }
980
981
982
983
984 private void sortOnActivity() {
985 learnts.sort(comparator);
986 }
987
988
989
990
991 protected void decayActivities() {
992 order.varDecayActivity();
993 claDecayActivity();
994 }
995
996
997
998
999 private void claDecayActivity() {
1000 claInc *= claDecay;
1001 }
1002
1003
1004
1005
1006 public boolean isSatisfiable() throws TimeoutException {
1007 return isSatisfiable(VecInt.EMPTY);
1008 }
1009
1010
1011
1012
1013 public boolean isSatisfiable(boolean global) throws TimeoutException {
1014 return isSatisfiable(VecInt.EMPTY, global);
1015 }
1016
1017 private double timebegin = 0;
1018
1019 private boolean needToReduceDB;
1020
1021 private ConflictTimer conflictCount;
1022
1023 private transient Timer timer;
1024
1025 public boolean isSatisfiable(IVecInt assumps) throws TimeoutException {
1026 return isSatisfiable(assumps, false);
1027 }
1028
1029 interface LearnedConstraintsDeletionStrategy extends Serializable {
1030
1031 void init();
1032
1033 ConflictTimer getTimer();
1034
1035 void reduce(IVec<Constr> learnedConstrs);
1036
1037 void onConflict(Constr outLearnt);
1038
1039 void onConflictAnalysis(Constr reason);
1040 }
1041
1042
1043
1044
1045 public LearnedConstraintsDeletionStrategy MEMORY_BASED = new LearnedConstraintsDeletionStrategy() {
1046
1047
1048
1049
1050 private static final long serialVersionUID = 1L;
1051
1052 final long memorybound = Runtime.getRuntime().freeMemory() / 10;
1053
1054 private final ConflictTimer freeMem = new ConflictTimerAdapter(500) {
1055 private static final long serialVersionUID = 1L;
1056
1057 @Override
1058 void run() {
1059 long freemem = Runtime.getRuntime().freeMemory();
1060
1061 if (freemem < memorybound) {
1062
1063 needToReduceDB = true;
1064 }
1065 }
1066 };
1067
1068 public void reduce(IVec<Constr> learnedConstrs) {
1069 int i, j;
1070 for (i = j = 0; i < learnts.size() / 2; i++) {
1071 Constr c = learnts.get(i);
1072 if (c.locked() || c.size() == 2) {
1073 learnts.set(j++, learnts.get(i));
1074 } else {
1075 c.remove(Solver.this);
1076 }
1077 }
1078 for (; i < learnts.size(); i++) {
1079 learnts.set(j++, learnts.get(i));
1080 }
1081 System.out.println("c cleaning " + (learnts.size() - j)
1082 + " clauses out of " + learnts.size());
1083 learnts.shrinkTo(j);
1084 }
1085
1086 public ConflictTimer getTimer() {
1087 return freeMem;
1088 }
1089
1090 @Override
1091 public String toString() {
1092 return "Memory based learned constraints deletion strategy";
1093 }
1094
1095 public void init() {
1096
1097 }
1098
1099 public void onConflict(Constr outLearnt) {
1100
1101
1102 }
1103
1104 public void onConflictAnalysis(Constr reason) {
1105 if (reason.learnt())
1106 claBumpActivity(reason);
1107 }
1108 };
1109
1110
1111
1112
1113 public LearnedConstraintsDeletionStrategy GLUCOSE = new LearnedConstraintsDeletionStrategy() {
1114
1115
1116
1117
1118 private static final long serialVersionUID = 1L;
1119 private int[] flags = new int[0];
1120 private int flag = 0;
1121
1122 private final ConflictTimer clauseManagement = new ConflictTimerAdapter(
1123 500) {
1124 private static final long serialVersionUID = 1L;
1125 private int nbconflict = 0;
1126 private static final int MAX_CLAUSE = 20000;
1127 private static final int INC_CLAUSE = 500;
1128 private int nextbound = MAX_CLAUSE;
1129
1130 @Override
1131 void run() {
1132 nbconflict += INC_CLAUSE;
1133
1134 if (nbconflict >= nextbound) {
1135 nextbound += INC_CLAUSE;
1136 nbconflict = 0;
1137 needToReduceDB = true;
1138 }
1139 }
1140 };
1141
1142 public void reduce(IVec<Constr> learnedConstrs) {
1143 int i, j;
1144 for (i = j = learnedConstrs.size() / 2; i < learnedConstrs.size(); i++) {
1145 Constr c = learnedConstrs.get(i);
1146 if (c.locked() || c.getActivity() <= 2.0) {
1147 learnedConstrs.set(j++, learnts.get(i));
1148 } else {
1149 c.remove(Solver.this);
1150 }
1151 }
1152 System.out
1153 .println("c cleaning " + (learnedConstrs.size() - j)
1154 + " clauses out of " + learnedConstrs.size() + " with flag " + flag);
1155 learnts.shrinkTo(j);
1156
1157 }
1158
1159 public ConflictTimer getTimer() {
1160 return clauseManagement;
1161 }
1162
1163 @Override
1164 public String toString() {
1165 return "Glucose learned constraints deletion strategy";
1166 }
1167
1168 public void init() {
1169 final int howmany = voc.nVars();
1170 if (flags.length <= howmany) {
1171 flags = new int[howmany + 1];
1172 }
1173
1174 }
1175
1176 public void onConflict(Constr outLearnt) {
1177
1178 int nblevel = 1;
1179 flag++;
1180 int currentLevel;
1181 for (int i = 1; i < outLearnt.size(); i++) {
1182 currentLevel = voc.getLevel(outLearnt.get(i));
1183 if (flags[currentLevel] != flag) {
1184 flags[currentLevel] = flag;
1185 nblevel++;
1186 }
1187 }
1188 outLearnt.incActivity(nblevel);
1189 }
1190
1191 public void onConflictAnalysis(Constr reason) {
1192
1193 }
1194 };
1195
1196 private LearnedConstraintsDeletionStrategy learnedConstraintsDeletionStrategy = MEMORY_BASED;
1197
1198
1199
1200
1201
1202 public void setLearnedConstraintsDeletionStrategy(
1203 LearnedConstraintsDeletionStrategy lcds) {
1204 learnedConstraintsDeletionStrategy = lcds;
1205 }
1206
1207 public boolean isSatisfiable(IVecInt assumps, boolean global)
1208 throws TimeoutException {
1209 Lbool status = Lbool.UNDEFINED;
1210
1211 final int howmany = voc.nVars();
1212 if (mseen.length <= howmany) {
1213 mseen = new boolean[howmany + 1];
1214 }
1215 trail.ensure(howmany);
1216 trailLim.ensure(howmany);
1217 learnedLiterals.ensure(howmany);
1218 timebegin = System.currentTimeMillis();
1219 slistener.start();
1220 model = null;
1221 fullmodel = null;
1222 order.init();
1223 learnedConstraintsDeletionStrategy.init();
1224
1225 int learnedLiteralsLimit = trail.size();
1226
1227
1228 for (IteratorInt iterator = learnedLiterals.iterator(); iterator
1229 .hasNext();) {
1230 enqueue(iterator.next());
1231 }
1232
1233
1234 Constr confl = propagate();
1235 if (confl != null) {
1236 analyzeAtRootLevel(confl);
1237 slistener.conflictFound(confl);
1238 slistener.end(Lbool.FALSE);
1239 cancelUntil(0);
1240 cancelLearntLiterals(learnedLiteralsLimit);
1241 return false;
1242 }
1243
1244
1245 for (IteratorInt iterator = assumps.iterator(); iterator.hasNext();) {
1246 int p = voc.getFromPool(iterator.next());
1247 if (!assume(p) || ((confl = propagate()) != null)) {
1248 if (confl == null) {
1249 slistener.conflictFound(p);
1250 } else {
1251 slistener.conflictFound(confl);
1252 }
1253 slistener.end(Lbool.FALSE);
1254 cancelUntil(0);
1255 cancelLearntLiterals(learnedLiteralsLimit);
1256 return false;
1257 }
1258 }
1259 rootLevel = decisionLevel();
1260
1261
1262 order.init();
1263 learner.init();
1264 restarter.init(params);
1265
1266 if (timeBasedTimeout) {
1267 if (!global || timer == null) {
1268 TimerTask stopMe = new TimerTask() {
1269 @Override
1270 public void run() {
1271 undertimeout = false;
1272 }
1273 };
1274 timer = new Timer(true);
1275 timer.schedule(stopMe, timeout);
1276 conflictCount = learnedConstraintsDeletionStrategy.getTimer();
1277 undertimeout = true;
1278 }
1279 } else {
1280 if (!global || conflictCount == null) {
1281 ConflictTimer conflictTimeout = new ConflictTimerAdapter(
1282 (int) timeout) {
1283 private static final long serialVersionUID = 1L;
1284
1285 @Override
1286 public void run() {
1287 undertimeout = false;
1288 }
1289 };
1290 undertimeout = true;
1291 conflictCount = new ConflictTimerContainer().add(
1292 conflictTimeout).add(
1293 learnedConstraintsDeletionStrategy.getTimer());
1294 }
1295 }
1296 needToReduceDB = false;
1297
1298 while ((status == Lbool.UNDEFINED) && undertimeout) {
1299 status = search(restarter.nextRestartNumberOfConflict());
1300
1301
1302
1303 restarter.onRestart();
1304 }
1305
1306 cancelUntil(0);
1307 cancelLearntLiterals(learnedLiteralsLimit);
1308 if (!global && timeBasedTimeout) {
1309 timer.cancel();
1310 timer = null;
1311 }
1312 slistener.end(status);
1313 if (!undertimeout) {
1314 String message = " Timeout (" + timeout
1315 + (timeBasedTimeout ? "s" : " conflicts") + ") exceeded";
1316 throw new TimeoutException(message);
1317 }
1318 return status == Lbool.TRUE;
1319 }
1320
1321 public void printInfos(PrintWriter out, String prefix) {
1322 out.print(prefix);
1323 out.println("constraints type ");
1324 for (Map.Entry<String, Counter> entry : constrTypes.entrySet()) {
1325 out.println(prefix + entry.getKey() + " => " + entry.getValue());
1326 }
1327 }
1328
1329
1330
1331
1332 public void printLearntClausesInfos(PrintWriter out, String prefix) {
1333 Map<String, Counter> learntTypes = new HashMap<String, Counter>();
1334 for (Iterator<Constr> it = learnts.iterator(); it.hasNext();) {
1335 String type = it.next().getClass().getName();
1336 Counter count = learntTypes.get(type);
1337 if (count == null) {
1338 learntTypes.put(type, new Counter());
1339 } else {
1340 count.inc();
1341 }
1342 }
1343 out.print(prefix);
1344 out.println("learnt constraints type ");
1345 for (Map.Entry<String, Counter> entry : learntTypes.entrySet()) {
1346 out.println(prefix + entry.getKey() + " => " + entry.getValue());
1347 }
1348 }
1349
1350 public SolverStats getStats() {
1351 return stats;
1352 }
1353
1354 public IOrder getOrder() {
1355 return order;
1356 }
1357
1358 public void setOrder(IOrder h) {
1359 order = h;
1360 order.setLits(voc);
1361 }
1362
1363 public ILits getVocabulary() {
1364 return voc;
1365 }
1366
1367 public void reset() {
1368
1369 voc.resetPool();
1370 dsfactory.reset();
1371 constrs.clear();
1372 learnts.clear();
1373 stats.reset();
1374 constrTypes.clear();
1375 }
1376
1377 public int nVars() {
1378 return voc.nVars();
1379 }
1380
1381
1382
1383
1384
1385
1386 protected IConstr addConstr(Constr constr) {
1387 if (constr != null) {
1388 constrs.push(constr);
1389 String type = constr.getClass().getName();
1390 Counter count = constrTypes.get(type);
1391 if (count == null) {
1392 constrTypes.put(type, new Counter());
1393 } else {
1394 count.inc();
1395 }
1396 }
1397 return constr;
1398 }
1399
1400 public DataStructureFactory getDSFactory() {
1401 return dsfactory;
1402 }
1403
1404 public IVecInt getOutLearnt() {
1405 return outLearnt;
1406 }
1407
1408
1409
1410
1411
1412
1413
1414
1415 public IConstr getIthConstr(int i) {
1416 return constrs.get(i);
1417 }
1418
1419
1420
1421
1422
1423
1424
1425 public void printStat(PrintStream out, String prefix) {
1426 printStat(new PrintWriter(out), prefix);
1427 }
1428
1429 public void printStat(PrintWriter out, String prefix) {
1430 stats.printStat(out, prefix);
1431 double cputime = (System.currentTimeMillis() - timebegin) / 1000;
1432 out.println(prefix
1433 + "speed (assignments/second)\t: " + stats.propagations
1434 / cputime);
1435 order.printStat(out, prefix);
1436 printLearntClausesInfos(out, prefix);
1437 }
1438
1439
1440
1441
1442
1443
1444 public String toString(String prefix) {
1445 StringBuffer stb = new StringBuffer();
1446 Object[] objs = { analyzer, dsfactory, learner, params, order,
1447 simplifier, restarter, learnedConstraintsDeletionStrategy };
1448 stb.append(prefix);
1449 stb.append("--- Begin Solver configuration ---");
1450 stb.append("\n");
1451 for (Object o : objs) {
1452 stb.append(prefix);
1453 stb.append(o.toString());
1454 stb.append("\n");
1455 }
1456 stb.append(prefix);
1457 stb.append("timeout=");
1458 if (timeBasedTimeout) {
1459 stb.append(timeout / 1000);
1460 stb.append("s\n");
1461 } else {
1462 stb.append(timeout);
1463 stb.append(" conflicts\n");
1464 }
1465 stb.append(prefix);
1466 stb.append("DB Simplification allowed=");
1467 stb.append(isDBSimplificationAllowed);
1468 stb.append("\n");
1469 stb.append(prefix);
1470 stb.append("--- End Solver configuration ---");
1471 return stb.toString();
1472 }
1473
1474
1475
1476
1477
1478
1479 @Override
1480 public String toString() {
1481 return toString("");
1482 }
1483
1484 public int getTimeout() {
1485 return (int) (timeBasedTimeout ? timeout / 1000 : timeout);
1486 }
1487
1488
1489
1490
1491 public long getTimeoutMs() {
1492 if (!timeBasedTimeout) {
1493 throw new UnsupportedOperationException(
1494 "The timeout is given in number of conflicts!");
1495 }
1496 return timeout;
1497 }
1498
1499 public void setExpectedNumberOfClauses(int nb) {
1500 constrs.ensure(nb);
1501 }
1502
1503 public Map<String, Number> getStat() {
1504 return stats.toMap();
1505 }
1506
1507 public int[] findModel() throws TimeoutException {
1508 if (isSatisfiable()) {
1509 return model();
1510 }
1511
1512
1513 return null;
1514 }
1515
1516 public int[] findModel(IVecInt assumps) throws TimeoutException {
1517 if (isSatisfiable(assumps)) {
1518 return model();
1519 }
1520
1521
1522 return null;
1523 }
1524
1525 public boolean isDBSimplificationAllowed() {
1526 return isDBSimplificationAllowed;
1527 }
1528
1529 public void setDBSimplificationAllowed(boolean status) {
1530 isDBSimplificationAllowed = status;
1531 }
1532
1533
1534
1535
1536 public int nextFreeVarId(boolean reserve) {
1537 return voc.nextFreeVarId(reserve);
1538 }
1539
1540
1541
1542
1543 public IConstr addBlockingClause(IVecInt literals)
1544 throws ContradictionException {
1545 return addClause(literals);
1546 }
1547
1548
1549
1550
1551 public void unset(int p) {
1552 int current = trail.last();
1553 while (current != p) {
1554 undoOne();
1555 current = trail.last();
1556 }
1557 undoOne();
1558 }
1559
1560 }
1561
1562 class ActivityComparator implements Comparator<Constr>, Serializable {
1563
1564 private static final long serialVersionUID = 1L;
1565
1566
1567
1568
1569
1570
1571 public int compare(Constr c1, Constr c2) {
1572 long delta = Math.round(c1.getActivity() - c2.getActivity());
1573 if (delta == 0) {
1574 return c1.size() - c2.size();
1575 }
1576 return (int) delta;
1577 }
1578 }
1579
1580 interface ConflictTimer {
1581
1582 void reset();
1583
1584 void newConflict();
1585 }
1586
1587 abstract class ConflictTimerAdapter implements Serializable, ConflictTimer {
1588
1589
1590
1591
1592 private static final long serialVersionUID = 1L;
1593
1594 private int counter;
1595
1596 private final int bound;
1597
1598 ConflictTimerAdapter(final int bound) {
1599 this.bound = bound;
1600 counter = 0;
1601 }
1602
1603 public void reset() {
1604 counter = 0;
1605 }
1606
1607 public void newConflict() {
1608 counter++;
1609 if (counter == bound) {
1610 run();
1611 counter = 0;
1612 }
1613 }
1614
1615 abstract void run();
1616 }
1617
1618 class ConflictTimerContainer implements Serializable, ConflictTimer {
1619
1620
1621
1622
1623 private static final long serialVersionUID = 1L;
1624
1625 private final IVec<ConflictTimer> timers = new Vec<ConflictTimer>();
1626
1627 ConflictTimerContainer add(ConflictTimer timer) {
1628 timers.push(timer);
1629 return this;
1630 }
1631
1632 public void reset() {
1633 Iterator<ConflictTimer> it = timers.iterator();
1634 while (it.hasNext()) {
1635 it.next().reset();
1636 }
1637 }
1638
1639 public void newConflict() {
1640 Iterator<ConflictTimer> it = timers.iterator();
1641 while (it.hasNext()) {
1642 it.next().newConflict();
1643 }
1644 }
1645 }