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.math.BigInteger;
33
34 import org.sat4j.core.Vec;
35 import org.sat4j.core.VecInt;
36 import org.sat4j.specs.ContradictionException;
37 import org.sat4j.specs.IConstr;
38 import org.sat4j.specs.ISolver;
39 import org.sat4j.specs.IVec;
40 import org.sat4j.specs.IVecInt;
41
42
43
44
45
46
47
48 public class GateTranslator extends SolverDecorator<ISolver> {
49
50
51
52
53 private static final long serialVersionUID = 1L;
54
55 public GateTranslator(ISolver solver) {
56 super(solver);
57 }
58
59
60
61
62
63
64
65
66
67
68 public IConstr gateFalse(int y) throws ContradictionException {
69 IVecInt clause = new VecInt(2);
70 clause.push(-y);
71 return processClause(clause);
72 }
73
74
75
76
77
78
79
80
81
82 public IConstr gateTrue(int y) throws ContradictionException {
83 IVecInt clause = new VecInt(2);
84 clause.push(y);
85 return processClause(clause);
86 }
87
88
89
90
91
92
93
94
95
96
97
98
99 public IConstr[] ite(int y, int x1, int x2, int x3)
100 throws ContradictionException {
101 IConstr[] constrs = new IConstr[6];
102 IVecInt clause = new VecInt(5);
103
104
105 clause.push(-y).push(-x1).push(x2);
106 constrs[0] = processClause(clause);
107 clause.clear();
108 clause.push(-y).push(x1).push(x3);
109 constrs[1] = processClause(clause);
110
111
112
113
114
115
116
117 clause.clear();
118 clause.push(-x1).push(-x2).push(y);
119 constrs[2] = processClause(clause);
120 clause.clear();
121 clause.push(x1).push(-x3).push(y);
122 constrs[3] = processClause(clause);
123 clause.clear();
124 clause.push(-x2).push(-x3).push(y);
125 constrs[4] = processClause(clause);
126
127
128
129 clause.clear();
130 clause.push(-y).push(x2).push(x3);
131 constrs[5] = processClause(clause);
132 return constrs;
133 }
134
135
136
137
138
139
140
141
142
143
144 public IConstr[] and(int y, IVecInt literals) throws ContradictionException {
145
146 IConstr[] constrs = new IConstr[literals.size() + 1];
147
148 IVecInt clause = new VecInt(literals.size() + 2);
149 clause.push(y);
150 for (int i = 0; i < literals.size(); i++) {
151 clause.push(-literals.get(i));
152 }
153 constrs[0] = processClause(clause);
154 clause.clear();
155 for (int i = 0; i < literals.size(); i++) {
156
157 clause.clear();
158 clause.push(-y);
159 clause.push(literals.get(i));
160 constrs[i + 1] = processClause(clause);
161 }
162 return constrs;
163 }
164
165
166
167
168
169
170
171
172
173
174 public IConstr[] and(int y, int x1, int x2) throws ContradictionException {
175 IVecInt clause = new VecInt(4);
176 IConstr[] constrs = new IConstr[3];
177 clause.push(-y);
178 clause.push(x1);
179 constrs[0] = addClause(clause);
180 clause.clear();
181 clause.push(-y);
182 clause.push(x2);
183 constrs[1] = addClause(clause);
184 clause.clear();
185 clause.push(y);
186 clause.push(-x1);
187 clause.push(-x2);
188 constrs[2] = addClause(clause);
189 return constrs;
190 }
191
192
193
194
195
196
197
198
199
200 public IConstr[] or(int y, IVecInt literals) throws ContradictionException {
201
202
203 IConstr[] constrs = new IConstr[literals.size() + 1];
204 IVecInt clause = new VecInt(literals.size() + 2);
205 literals.copyTo(clause);
206 clause.push(-y);
207 constrs[0] = processClause(clause);
208 clause.clear();
209 for (int i = 0; i < literals.size(); i++) {
210
211 clause.clear();
212 clause.push(y);
213 clause.push(-literals.get(i));
214 constrs[i + 1] = processClause(clause);
215 }
216 return constrs;
217 }
218
219
220
221
222
223
224
225
226
227 public IConstr[] halfOr(int y, IVecInt literals)
228 throws ContradictionException {
229 IConstr[] constrs = new IConstr[literals.size()];
230 IVecInt clause = new VecInt(literals.size() + 2);
231 for (int i = 0; i < literals.size(); i++) {
232
233 clause.clear();
234 clause.push(y);
235 clause.push(-literals.get(i));
236 constrs[i] = processClause(clause);
237 }
238 return constrs;
239 }
240
241 private IConstr processClause(IVecInt clause) throws ContradictionException {
242 return addClause(clause);
243 }
244
245
246
247
248
249
250
251
252
253 public IConstr[] not(int y, int x) throws ContradictionException {
254 IConstr[] constrs = new IConstr[2];
255 IVecInt clause = new VecInt(3);
256
257
258 clause.push(-y).push(-x);
259 constrs[0] = processClause(clause);
260
261 clause.clear();
262 clause.push(y).push(x);
263 constrs[1] = processClause(clause);
264 return constrs;
265 }
266
267
268
269
270
271
272
273
274
275 public IConstr[] xor(int y, IVecInt literals) throws ContradictionException {
276 literals.push(-y);
277 int[] f = new int[literals.size()];
278 literals.copyTo(f);
279 IVec<IConstr> vconstrs = new Vec<IConstr>();
280 xor2Clause(f, 0, false, vconstrs);
281 IConstr[] constrs = new IConstr[vconstrs.size()];
282 vconstrs.copyTo(constrs);
283 return constrs;
284 }
285
286
287
288
289
290
291
292
293
294 public IConstr[] iff(int y, IVecInt literals) throws ContradictionException {
295 literals.push(y);
296 int[] f = new int[literals.size()];
297 literals.copyTo(f);
298 IVec<IConstr> vconstrs = new Vec<IConstr>();
299 iff2Clause(f, 0, false, vconstrs);
300 IConstr[] constrs = new IConstr[vconstrs.size()];
301 vconstrs.copyTo(constrs);
302 return constrs;
303 }
304
305
306
307
308 public void xor(int x, int a, int b) throws ContradictionException {
309 IVecInt clause = new VecInt(3);
310 clause.push(-a).push(b).push(x);
311 processClause(clause);
312 clause.clear();
313 clause.push(a).push(-b).push(x);
314 processClause(clause);
315 clause.clear();
316 clause.push(-a).push(-b).push(-x);
317 processClause(clause);
318 clause.clear();
319 clause.push(a).push(b).push(-x);
320 processClause(clause);
321 clause.clear();
322 }
323
324 private void xor2Clause(int[] f, int prefix, boolean negation,
325 IVec<IConstr> constrs) throws ContradictionException {
326 if (prefix == f.length - 1) {
327 IVecInt clause = new VecInt(f.length + 1);
328 for (int i = 0; i < f.length - 1; ++i) {
329 clause.push(f[i]);
330 }
331 clause.push(f[f.length - 1] * (negation ? -1 : 1));
332 constrs.push(processClause(clause));
333 return;
334 }
335
336 if (negation) {
337 f[prefix] = -f[prefix];
338 xor2Clause(f, prefix + 1, false, constrs);
339 f[prefix] = -f[prefix];
340
341 xor2Clause(f, prefix + 1, true, constrs);
342 } else {
343 xor2Clause(f, prefix + 1, false, constrs);
344
345 f[prefix] = -f[prefix];
346 xor2Clause(f, prefix + 1, true, constrs);
347 f[prefix] = -f[prefix];
348 }
349 }
350
351 private void iff2Clause(int[] f, int prefix, boolean negation,
352 IVec<IConstr> constrs) throws ContradictionException {
353 if (prefix == f.length - 1) {
354 IVecInt clause = new VecInt(f.length + 1);
355 for (int i = 0; i < f.length - 1; ++i) {
356 clause.push(f[i]);
357 }
358 clause.push(f[f.length - 1] * (negation ? -1 : 1));
359 processClause(clause);
360 return;
361 }
362
363 if (negation) {
364 iff2Clause(f, prefix + 1, false, constrs);
365 f[prefix] = -f[prefix];
366 iff2Clause(f, prefix + 1, true, constrs);
367 f[prefix] = -f[prefix];
368 } else {
369 f[prefix] = -f[prefix];
370 iff2Clause(f, prefix + 1, false, constrs);
371 f[prefix] = -f[prefix];
372 iff2Clause(f, prefix + 1, true, constrs);
373 }
374 }
375
376
377
378
379
380
381 public void fullAdderSum(int x, int a, int b, int c)
382 throws ContradictionException {
383 IVecInt clause = new VecInt(4);
384
385 clause.push(a).push(b).push(c).push(-x);
386 processClause(clause);
387 clause.clear();
388
389 clause.push(a).push(-b).push(-c).push(-x);
390 processClause(clause);
391 clause.clear();
392 clause.push(-a).push(b).push(-c).push(-x);
393 processClause(clause);
394 clause.clear();
395 clause.push(-a).push(-b).push(c).push(-x);
396 processClause(clause);
397 clause.clear();
398 clause.push(-a).push(-b).push(-c).push(x);
399 processClause(clause);
400 clause.clear();
401 clause.push(-a).push(b).push(c).push(x);
402 processClause(clause);
403 clause.clear();
404 clause.push(a).push(-b).push(c).push(x);
405 processClause(clause);
406 clause.clear();
407 clause.push(a).push(b).push(-c).push(x);
408 processClause(clause);
409 clause.clear();
410 }
411
412
413
414
415 public void fullAdderCarry(int x, int a, int b, int c)
416 throws ContradictionException {
417 IVecInt clause = new VecInt(3);
418 clause.push(-b).push(-c).push(x);
419 processClause(clause);
420 clause.clear();
421 clause.push(-a).push(-c).push(x);
422 processClause(clause);
423 clause.clear();
424 clause.push(-a).push(-b).push(x);
425 processClause(clause);
426 clause.clear();
427 clause.push(b).push(c).push(-x);
428 processClause(clause);
429 clause.clear();
430 clause.push(a).push(c).push(-x);
431 processClause(clause);
432 clause.clear();
433 clause.push(a).push(b).push(-x);
434 processClause(clause);
435 clause.clear();
436 }
437
438
439
440
441 public void additionalFullAdderConstraints(int xcarry, int xsum, int a,
442 int b, int c) throws ContradictionException {
443 IVecInt clause = new VecInt(3);
444 clause.push(-xcarry).push(-xsum).push(a);
445 processClause(clause);
446 clause.push(-xcarry).push(-xsum).push(b);
447 processClause(clause);
448 clause.push(-xcarry).push(-xsum).push(c);
449 processClause(clause);
450 clause.push(xcarry).push(xsum).push(-a);
451 processClause(clause);
452 clause.push(xcarry).push(xsum).push(-b);
453 processClause(clause);
454 clause.push(xcarry).push(xsum).push(-c);
455 processClause(clause);
456 }
457
458
459
460
461 public void halfAdderSum(int x, int a, int b) throws ContradictionException {
462 xor(x, a, b);
463 }
464
465
466
467
468 public void halfAdderCarry(int x, int a, int b)
469 throws ContradictionException {
470 and(x, a, b);
471 }
472
473
474
475
476
477
478
479
480 public void optimisationFunction(IVecInt literals, IVec<BigInteger> coefs,
481 IVecInt result) throws ContradictionException {
482 IVec<IVecInt> buckets = new Vec<IVecInt>();
483 IVecInt bucket;
484
485 for (int i = 0; i < literals.size(); i++) {
486 int p = literals.get(i);
487 BigInteger a = coefs.get(i);
488 for (int j = 0; j < a.bitLength(); j++) {
489 bucket = createIfNull(buckets, j);
490 if (a.testBit(j)) {
491 bucket.push(p);
492 }
493 }
494 }
495
496 int x, y, z;
497 int sum, carry;
498 for (int i = 0; i < buckets.size(); i++) {
499 bucket = buckets.get(i);
500 while (bucket.size() >= 3) {
501 x = bucket.get(0);
502 y = bucket.get(1);
503 z = bucket.get(2);
504 bucket.remove(x);
505 bucket.remove(y);
506 bucket.remove(z);
507 sum = nextFreeVarId(true);
508 carry = nextFreeVarId(true);
509 fullAdderSum(sum, x, y, z);
510 fullAdderCarry(carry, x, y, z);
511 additionalFullAdderConstraints(carry, sum, x, y, z);
512 bucket.push(sum);
513 createIfNull(buckets, i + 1).push(carry);
514 }
515 while (bucket.size() == 2) {
516 x = bucket.get(0);
517 y = bucket.get(1);
518 bucket.remove(x);
519 bucket.remove(y);
520 sum = nextFreeVarId(true);
521 carry = nextFreeVarId(true);
522 halfAdderSum(sum, x, y);
523 halfAdderCarry(carry, x, y);
524 bucket.push(sum);
525 createIfNull(buckets, i + 1).push(carry);
526 }
527 assert bucket.size() == 1;
528 result.push(bucket.last());
529 bucket.pop();
530 assert bucket.isEmpty();
531 }
532 }
533
534
535
536
537
538
539
540
541
542 private IVecInt createIfNull(IVec<IVecInt> buckets, int i) {
543 IVecInt bucket = buckets.get(i);
544 if (bucket == null) {
545 bucket = new VecInt();
546 buckets.push(bucket);
547 assert buckets.get(i) == bucket;
548 }
549 return bucket;
550
551 }
552 }