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.opt;
31
32 import org.sat4j.core.VecInt;
33 import org.sat4j.specs.ContradictionException;
34 import org.sat4j.specs.IConstr;
35 import org.sat4j.specs.IOptimizationProblem;
36 import org.sat4j.specs.ISolver;
37 import org.sat4j.specs.IVecInt;
38 import org.sat4j.specs.TimeoutException;
39 import org.sat4j.tools.SolverDecorator;
40
41
42
43
44
45
46
47
48 public final class MinOneDecorator extends SolverDecorator<ISolver> implements
49 IOptimizationProblem {
50
51
52
53
54 private static final long serialVersionUID = 1L;
55
56 private int[] prevmodel;
57
58 private boolean isSolutionOptimal;
59
60 public MinOneDecorator(ISolver solver) {
61 super(solver);
62 }
63
64 public boolean admitABetterSolution() throws TimeoutException {
65 return admitABetterSolution(VecInt.EMPTY);
66 }
67
68
69
70
71 public boolean admitABetterSolution(IVecInt assumps)
72 throws TimeoutException {
73 this.isSolutionOptimal = false;
74 boolean result = isSatisfiable(assumps, true);
75 if (result) {
76 this.prevmodel = super.model();
77 calculateObjectiveValue();
78 } else {
79 this.isSolutionOptimal = true;
80 }
81 return result;
82 }
83
84 public boolean hasNoObjectiveFunction() {
85 return false;
86 }
87
88 public boolean nonOptimalMeansSatisfiable() {
89 return true;
90 }
91
92 private int counter;
93
94 public Number calculateObjective() {
95 calculateObjectiveValue();
96 return this.counter;
97 }
98
99 private void calculateObjectiveValue() {
100 this.counter = 0;
101 for (int p : this.prevmodel) {
102 if (p > 0) {
103 this.counter++;
104 }
105 }
106 }
107
108 private final IVecInt literals = new VecInt();
109
110 private IConstr previousConstr;
111
112
113
114
115 public void discardCurrentSolution() throws ContradictionException {
116 if (this.literals.isEmpty()) {
117 for (int i = 1; i <= nVars(); i++) {
118 this.literals.push(i);
119 }
120 }
121 if (this.previousConstr != null) {
122 super.removeConstr(this.previousConstr);
123 }
124 this.previousConstr = addAtMost(this.literals, this.counter - 1);
125 }
126
127 @Override
128 public int[] model() {
129
130 return this.prevmodel;
131 }
132
133 @Override
134 public void reset() {
135 this.literals.clear();
136 this.previousConstr = null;
137 super.reset();
138 }
139
140
141
142
143 public Number getObjectiveValue() {
144 return this.counter;
145 }
146
147 public void discard() throws ContradictionException {
148 discardCurrentSolution();
149 }
150
151
152
153
154 public void forceObjectiveValueTo(Number forcedValue)
155 throws ContradictionException {
156 try {
157 addAtMost(this.literals, forcedValue.intValue());
158 } catch (ContradictionException ce) {
159 this.isSolutionOptimal = true;
160 throw ce;
161 }
162
163 }
164
165 public boolean isOptimal() {
166 return this.isSolutionOptimal;
167 }
168 }