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