1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.sat4j.tools;
31
32 import java.util.ArrayList;
33 import java.util.List;
34
35 import org.sat4j.core.VecInt;
36 import org.sat4j.specs.ContradictionException;
37 import org.sat4j.specs.IConstr;
38 import org.sat4j.specs.IOptimizationProblem;
39 import org.sat4j.specs.ISolver;
40 import org.sat4j.specs.IVecInt;
41 import org.sat4j.specs.IteratorInt;
42 import org.sat4j.specs.TimeoutException;
43
44 public class LexicoDecorator<T extends ISolver> extends SolverDecorator<T>
45 implements IOptimizationProblem {
46
47 protected final List<IVecInt> criteria = new ArrayList<IVecInt>();
48
49 protected int currentCriterion = 0;
50
51 private IConstr prevConstr;
52
53 private Number currentValue = -1;
54
55 protected int[] prevfullmodel;
56 protected boolean[] prevboolmodel;
57
58 private boolean isSolutionOptimal;
59
60
61
62
63 private static final long serialVersionUID = 1L;
64
65 public LexicoDecorator(T solver) {
66 super(solver);
67 }
68
69 public void addCriterion(IVecInt literals) {
70 IVecInt copy = new VecInt(literals.size());
71 literals.copyTo(copy);
72 this.criteria.add(copy);
73 }
74
75 public boolean admitABetterSolution() throws TimeoutException {
76 return admitABetterSolution(VecInt.EMPTY);
77 }
78
79 public boolean admitABetterSolution(IVecInt assumps)
80 throws TimeoutException {
81 this.isSolutionOptimal = false;
82 if (decorated().isSatisfiable(assumps, true)) {
83 this.prevboolmodel = new boolean[nVars()];
84 for (int i = 0; i < nVars(); i++) {
85 this.prevboolmodel[i] = decorated().model(i + 1);
86 }
87 this.prevfullmodel = decorated().model();
88 calculateObjective();
89 return true;
90 }
91 return manageUnsatCase();
92 }
93
94 private boolean manageUnsatCase() {
95 if (this.currentCriterion < numberOfCriteria() - 1) {
96 if (this.prevConstr != null) {
97 super.removeConstr(this.prevConstr);
98 this.prevConstr = null;
99 }
100 try {
101 fixCriterionValue();
102 } catch (ContradictionException e) {
103 throw new IllegalStateException(e);
104 }
105 if (isVerbose()) {
106 System.out.println(getLogPrefix()
107 + "Found optimal criterion number "
108 + (this.currentCriterion + 1));
109 }
110 this.currentCriterion++;
111 calculateObjective();
112 return true;
113 }
114 if (isVerbose()) {
115 System.out.println(getLogPrefix()
116 + "Found optimal solution for the last criterion ");
117 }
118 this.isSolutionOptimal = true;
119 if (this.prevConstr != null) {
120 super.removeConstr(this.prevConstr);
121 this.prevConstr = null;
122 }
123 return false;
124 }
125
126 protected int numberOfCriteria() {
127 return this.criteria.size();
128 }
129
130 protected void fixCriterionValue() throws ContradictionException {
131 super.addAtMost(this.criteria.get(this.currentCriterion),
132 this.currentValue.intValue());
133 super.addAtLeast(this.criteria.get(this.currentCriterion),
134 this.currentValue.intValue());
135 }
136
137 @Override
138 public int[] model() {
139 return this.prevfullmodel;
140 }
141
142 @Override
143 public boolean model(int var) {
144 return this.prevboolmodel[var - 1];
145 }
146
147 public boolean hasNoObjectiveFunction() {
148 return false;
149 }
150
151 public boolean nonOptimalMeansSatisfiable() {
152 return true;
153 }
154
155 public Number calculateObjective() {
156 this.currentValue = evaluate();
157 return this.currentValue;
158 }
159
160 public Number getObjectiveValue() {
161 return this.currentValue;
162 }
163
164 public void forceObjectiveValueTo(Number forcedValue)
165 throws ContradictionException {
166 throw new UnsupportedOperationException();
167 }
168
169 public void discard() throws ContradictionException {
170 discardCurrentSolution();
171
172 }
173
174 public void discardCurrentSolution() throws ContradictionException {
175 if (this.prevConstr != null) {
176 super.removeSubsumedConstr(this.prevConstr);
177 }
178 try {
179 this.prevConstr = discardSolutionsForOptimizing();
180 } catch (ContradictionException c) {
181 this.prevConstr = null;
182 if (!manageUnsatCase()) {
183 throw c;
184 }
185 }
186
187 }
188
189 protected IConstr discardSolutionsForOptimizing()
190 throws ContradictionException {
191 return super.addAtMost(this.criteria.get(this.currentCriterion),
192 this.currentValue.intValue() - 1);
193 }
194
195 protected Number evaluate() {
196 int value = 0;
197 int lit;
198 for (IteratorInt it = this.criteria.get(this.currentCriterion)
199 .iterator(); it.hasNext();) {
200 lit = it.next();
201 if (lit > 0 && this.prevboolmodel[lit - 1] || lit < 0
202 && !this.prevboolmodel[-lit - 1]) {
203 value++;
204 }
205 }
206 return value;
207 }
208
209 public boolean isOptimal() {
210 return this.isSolutionOptimal;
211 }
212
213 }