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 package org.sat4j.tools.encoding;
32
33 import org.sat4j.core.ConstrGroup;
34 import org.sat4j.core.VecInt;
35 import org.sat4j.specs.ContradictionException;
36 import org.sat4j.specs.IConstr;
37 import org.sat4j.specs.ISolver;
38 import org.sat4j.specs.IVecInt;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class Commander extends EncodingStrategyAdapter {
56
57
58
59
60
61
62 @Override
63 public IConstr addAtMostOne(ISolver solver, IVecInt literals)
64 throws ContradictionException {
65
66 return addAtMostOne(solver, literals, 3);
67 }
68
69 private IConstr addAtMostOne(ISolver solver, IVecInt literals, int groupSize)
70 throws ContradictionException {
71
72 ConstrGroup constrGroup = new ConstrGroup(false);
73
74 IVecInt clause = new VecInt();
75 IVecInt clause1 = new VecInt();
76
77 final int n = literals.size();
78
79 int nbGroup = (int) Math.ceil((double) literals.size()
80 / (double) groupSize);
81
82 if (nbGroup == 1) {
83 for (int i = 0; i < literals.size() - 1; i++) {
84 for (int j = i + 1; j < literals.size(); j++) {
85 clause.push(-literals.get(i));
86 clause.push(-literals.get(j));
87 constrGroup.add(solver.addClause(clause));
88 clause.clear();
89 }
90 }
91 return constrGroup;
92 }
93
94 int[] c = new int[nbGroup];
95
96 for (int i = 0; i < nbGroup; i++) {
97 c[i] = solver.nextFreeVarId(true);
98 }
99
100 int nbVarLastGroup = n - (nbGroup - 1) * groupSize;
101
102
103 for (int i = 0; i < nbGroup; i++) {
104 int size = 0;
105 if (i == nbGroup - 1) {
106 size = nbVarLastGroup;
107 } else {
108 size = groupSize;
109 }
110
111 for (int j = 0; j < size - 1; j++) {
112 for (int k = j + 1; k < size; k++) {
113 clause.push(-literals.get(i * groupSize + j));
114 clause.push(-literals.get(i * groupSize + k));
115 constrGroup.add(solver.addClause(clause));
116 clause.clear();
117 }
118 }
119
120
121
122
123
124 clause1.push(-c[i]);
125 for (int j = 0; j < size; j++) {
126 clause1.push(literals.get(i * groupSize + j));
127 clause.push(c[i]);
128 clause.push(-literals.get(i * groupSize + j));
129 constrGroup.add(solver.addClause(clause));
130 clause.clear();
131 }
132 constrGroup.add(solver.addClause(clause1));
133 clause1.clear();
134 }
135
136
137
138 constrGroup.add(addAtMostOne(solver, new VecInt(c), groupSize));
139 return constrGroup;
140 }
141
142 @Override
143 public IConstr addAtMost(ISolver solver, IVecInt literals, int degree)
144 throws ContradictionException {
145 return super.addAtMost(solver, literals, degree);
146
147 }
148
149 private IConstr addAtMost(ISolver solver, IVecInt literals, int k,
150 int groupSize) throws ContradictionException {
151 ConstrGroup constrGroup = new ConstrGroup(false);
152
153 IVecInt clause = new VecInt();
154
155 final int n = literals.size();
156
157 int nbGroup = (int) Math.ceil((double) n / (double) groupSize);
158
159 if (nbGroup == 1) {
160 for (IVecInt vec : literals.subset(k + 1)) {
161 for (int i = 0; i < vec.size(); i++) {
162 clause.push(-vec.get(i));
163 }
164 constrGroup.add(solver.addClause(clause));
165 clause.clear();
166 }
167 return constrGroup;
168 }
169
170 int[][] c = new int[nbGroup][k];
171 VecInt vecC = new VecInt();
172
173 for (int i = 0; i < nbGroup - 1; i++) {
174 for (int j = 0; j < k; j++) {
175 c[i][j] = solver.nextFreeVarId(true);
176 vecC.push(c[i][j]);
177 }
178 }
179
180 int nbVarLastGroup = n - (nbGroup - 1) * groupSize;
181 int nbCForLastGroup;
182
183 nbCForLastGroup = k;
184
185 for (int j = 0; j < nbCForLastGroup; j++) {
186 c[nbGroup - 1][j] = solver.nextFreeVarId(true);
187 vecC.push(c[nbGroup - 1][j]);
188 }
189
190 VecInt[] groupTab = new VecInt[nbGroup];
191
192
193
194
195 for (int i = 0; i < nbGroup - 1; i++) {
196 groupTab[i] = new VecInt();
197
198 int size = 0;
199 if (i == nbGroup - 1) {
200 size = nbVarLastGroup;
201 } else {
202 size = groupSize;
203 }
204
205 for (int j = 0; j < size; j++) {
206 groupTab[i].push(literals.get(i * groupSize + j));
207 }
208 for (int j = 0; j < k; j++) {
209 groupTab[i].push(-c[i][j]);
210 }
211 }
212
213 int size = nbVarLastGroup;
214 groupTab[nbGroup - 1] = new VecInt();
215 for (int j = 0; j < size; j++) {
216 groupTab[nbGroup - 1].push(literals.get((nbGroup - 1) * groupSize
217 + j));
218 }
219 for (int j = 0; j < nbCForLastGroup; j++) {
220 groupTab[nbGroup - 1].push(-c[nbGroup - 1][j]);
221 }
222
223 Binomial bin = new Binomial();
224
225
226
227 for (int i = 0; i < nbGroup; i++) {
228 constrGroup.add(bin.addAtMost(solver, groupTab[i], k));
229 System.out.println(constrGroup.getConstr(i).size());
230 }
231
232
233
234 for (int i = 0; i < nbGroup; i++) {
235 constrGroup.add(bin.addAtLeast(solver, groupTab[i], k));
236 System.out.println(constrGroup.getConstr(i + nbGroup).size());
237 }
238
239 for (int i = 0; i < nbGroup; i++) {
240 for (int j = 0; j < k - 1; j++) {
241 clause.push(-c[i][j]);
242 clause.push(c[i][j + 1]);
243 constrGroup.add(solver.addClause(clause));
244 clause.clear();
245 }
246 }
247
248 constrGroup.add(addAtMost(solver, vecC, k));
249
250 return constrGroup;
251 }
252
253 @Override
254 public IConstr addAtLeast(ISolver solver, IVecInt literals, int k)
255 throws ContradictionException {
256
257 IVecInt newLits = new VecInt();
258 for (int i = 0; i < literals.size(); i++) {
259 newLits.push(-literals.get(i));
260 }
261
262 return addAtMost(solver, newLits, literals.size() - k);
263 }
264
265 @Override
266 public IConstr addExactlyOne(ISolver solver, IVecInt literals)
267 throws ContradictionException {
268 ConstrGroup group = new ConstrGroup();
269
270 group.add(addAtLeastOne(solver, literals));
271 group.add(addAtMostOne(solver, literals));
272
273 return group;
274 }
275
276 @Override
277 public IConstr addExactly(ISolver solver, IVecInt literals, int degree)
278 throws ContradictionException {
279 ConstrGroup group = new ConstrGroup();
280
281 group.add(addAtLeast(solver, literals, degree));
282 group.add(addAtMost(solver, literals, degree));
283
284 return group;
285 }
286 }