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.prevfullmodel == null) {
96
97 return false;
98 }
99
100
101 if (this.currentCriterion < numberOfCriteria() - 1) {
102 if (this.prevConstr != null) {
103 super.removeConstr(this.prevConstr);
104 this.prevConstr = null;
105 }
106 try {
107 fixCriterionValue();
108 } catch (ContradictionException e) {
109 throw new IllegalStateException(e);
110 }
111 if (isVerbose()) {
112 System.out.println(getLogPrefix()
113 + "Found optimal criterion number "
114 + (this.currentCriterion + 1));
115 }
116 this.currentCriterion++;
117 calculateObjective();
118 return true;
119 }
120 if (isVerbose()) {
121 System.out.println(getLogPrefix()
122 + "Found optimal solution for the last criterion ");
123 }
124 this.isSolutionOptimal = true;
125 if (this.prevConstr != null) {
126 super.removeConstr(this.prevConstr);
127 this.prevConstr = null;
128 }
129 return false;
130 }
131
132 public int numberOfCriteria() {
133 return this.criteria.size();
134 }
135
136 protected void fixCriterionValue() throws ContradictionException {
137 super.addExactly(this.criteria.get(this.currentCriterion),
138 this.currentValue.intValue());
139 }
140
141 @Override
142 public int[] model() {
143 return this.prevfullmodel;
144 }
145
146 @Override
147 public boolean model(int var) {
148 return this.prevboolmodel[var - 1];
149 }
150
151 public boolean hasNoObjectiveFunction() {
152 return false;
153 }
154
155 public boolean nonOptimalMeansSatisfiable() {
156 return true;
157 }
158
159 public Number calculateObjective() {
160 this.currentValue = evaluate();
161 return this.currentValue;
162 }
163
164 public Number getObjectiveValue() {
165 return this.currentValue;
166 }
167
168 public Number getObjectiveValue(int criterion) {
169 return evaluate(criterion);
170 }
171
172 public void forceObjectiveValueTo(Number forcedValue)
173 throws ContradictionException {
174 throw new UnsupportedOperationException();
175 }
176
177 public void discard() throws ContradictionException {
178 discardCurrentSolution();
179
180 }
181
182 public void discardCurrentSolution() throws ContradictionException {
183 if (this.prevConstr != null) {
184 super.removeSubsumedConstr(this.prevConstr);
185 }
186 try {
187 this.prevConstr = discardSolutionsForOptimizing();
188 } catch (ContradictionException c) {
189 this.prevConstr = null;
190 if (!manageUnsatCase()) {
191 throw c;
192 }
193 }
194
195 }
196
197 protected IConstr discardSolutionsForOptimizing()
198 throws ContradictionException {
199 return super.addAtMost(this.criteria.get(this.currentCriterion),
200 this.currentValue.intValue() - 1);
201 }
202
203 protected Number evaluate() {
204 return evaluate(this.currentCriterion);
205 }
206
207 protected Number evaluate(int criterion) {
208 int value = 0;
209 int lit;
210 for (IteratorInt it = this.criteria.get(this.currentCriterion)
211 .iterator(); it.hasNext();) {
212 lit = it.next();
213 if (lit > 0 && this.prevboolmodel[lit - 1] || lit < 0
214 && !this.prevboolmodel[-lit - 1]) {
215 value++;
216 }
217 }
218 return value;
219 }
220
221 public boolean isOptimal() {
222 return this.isSolutionOptimal;
223 }
224
225 public void setTimeoutForFindingBetterSolution(int seconds) {
226
227 throw new UnsupportedOperationException("No implemented yet");
228 }
229
230 }