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 protected IConstr prevConstr;
52
53 private Number currentValue = -1;
54
55 protected int[] prevfullmodel;
56 protected int[] prevmodelwithinternalvars;
57 protected boolean[] prevboolmodel;
58
59 protected boolean isSolutionOptimal;
60
61
62
63
64 private static final long serialVersionUID = 1L;
65
66 public LexicoDecorator(T solver) {
67 super(solver);
68 }
69
70 public void addCriterion(IVecInt literals) {
71 IVecInt copy = new VecInt(literals.size());
72 literals.copyTo(copy);
73 this.criteria.add(copy);
74 }
75
76 public boolean admitABetterSolution() throws TimeoutException {
77 return admitABetterSolution(VecInt.EMPTY);
78 }
79
80 public boolean admitABetterSolution(IVecInt assumps)
81 throws TimeoutException {
82 this.isSolutionOptimal = false;
83 if (decorated().isSatisfiable(assumps, true)) {
84 this.prevboolmodel = new boolean[nVars()];
85 for (int i = 0; i < nVars(); i++) {
86 this.prevboolmodel[i] = decorated().model(i + 1);
87 }
88 this.prevfullmodel = decorated().model();
89 this.prevmodelwithinternalvars = decorated()
90 .modelWithInternalVariables();
91 calculateObjective();
92 return true;
93 }
94 return manageUnsatCase();
95 }
96
97 protected boolean manageUnsatCase() {
98 if (this.prevfullmodel == null) {
99
100 return false;
101 }
102
103
104 if (this.currentCriterion < numberOfCriteria() - 1) {
105 if (this.prevConstr != null) {
106 super.removeConstr(this.prevConstr);
107 this.prevConstr = null;
108 }
109 try {
110 fixCriterionValue();
111 } catch (ContradictionException e) {
112 throw new IllegalStateException(e);
113 }
114 if (isVerbose()) {
115 System.out.println(getLogPrefix()
116 + "Found optimal criterion number "
117 + (this.currentCriterion + 1));
118 }
119 this.currentCriterion++;
120 calculateObjective();
121 return true;
122 }
123 if (isVerbose()) {
124 System.out.println(getLogPrefix()
125 + "Found optimal solution for the last criterion ");
126 }
127 this.isSolutionOptimal = true;
128 if (this.prevConstr != null) {
129 super.removeConstr(this.prevConstr);
130 this.prevConstr = null;
131 }
132 return false;
133 }
134
135 public int numberOfCriteria() {
136 return this.criteria.size();
137 }
138
139 protected void fixCriterionValue() throws ContradictionException {
140 super.addExactly(this.criteria.get(this.currentCriterion),
141 this.currentValue.intValue());
142 }
143
144 @Override
145 public int[] model() {
146 return this.prevfullmodel;
147 }
148
149 @Override
150 public boolean model(int var) {
151 return this.prevboolmodel[var - 1];
152 }
153
154 @Override
155 public int[] modelWithInternalVariables() {
156 return this.prevmodelwithinternalvars;
157 }
158
159 public boolean hasNoObjectiveFunction() {
160 return false;
161 }
162
163 public boolean nonOptimalMeansSatisfiable() {
164 return true;
165 }
166
167 public Number calculateObjective() {
168 this.currentValue = evaluate();
169 return this.currentValue;
170 }
171
172 public Number getObjectiveValue() {
173 return this.currentValue;
174 }
175
176 public Number getObjectiveValue(int criterion) {
177 return evaluate(criterion);
178 }
179
180 public void forceObjectiveValueTo(Number forcedValue)
181 throws ContradictionException {
182 throw new UnsupportedOperationException();
183 }
184
185 public void discard() throws ContradictionException {
186 discardCurrentSolution();
187
188 }
189
190 public void discardCurrentSolution() throws ContradictionException {
191 if (this.prevConstr != null) {
192 super.removeSubsumedConstr(this.prevConstr);
193 }
194 try {
195 this.prevConstr = discardSolutionsForOptimizing();
196 } catch (ContradictionException c) {
197 this.prevConstr = null;
198 if (!manageUnsatCase()) {
199 throw c;
200 }
201 }
202
203 }
204
205 protected IConstr discardSolutionsForOptimizing()
206 throws ContradictionException {
207 return super.addAtMost(this.criteria.get(this.currentCriterion),
208 this.currentValue.intValue() - 1);
209 }
210
211 protected Number evaluate() {
212 return evaluate(this.currentCriterion);
213 }
214
215 protected Number evaluate(int criterion) {
216 int value = 0;
217 int lit;
218 for (IteratorInt it = this.criteria.get(this.currentCriterion)
219 .iterator(); it.hasNext();) {
220 lit = it.next();
221 if (lit > 0 && this.prevboolmodel[lit - 1] || lit < 0
222 && !this.prevboolmodel[-lit - 1]) {
223 value++;
224 }
225 }
226 return value;
227 }
228
229 public boolean isOptimal() {
230 return this.isSolutionOptimal;
231 }
232
233 public void setTimeoutForFindingBetterSolution(int seconds) {
234
235 throw new UnsupportedOperationException("No implemented yet");
236 }
237
238 }