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 private IConstr processClause(IVecInt clause) throws ContradictionException {
218 return addClause(clause);
219 }
220
221
222
223
224
225
226
227
228
229 public IConstr[] not(int y, int x) throws ContradictionException {
230 IConstr[] constrs = new IConstr[2];
231 IVecInt clause = new VecInt(3);
232
233
234 clause.push(-y).push(-x);
235 constrs[0] = processClause(clause);
236
237 clause.clear();
238 clause.push(y).push(x);
239 constrs[1] = processClause(clause);
240 return constrs;
241 }
242
243
244
245
246
247
248
249
250
251 public IConstr[] xor(int y, IVecInt literals) throws ContradictionException {
252 literals.push(-y);
253 int[] f = new int[literals.size()];
254 literals.copyTo(f);
255 IVec<IConstr> vconstrs = new Vec<IConstr>();
256 xor2Clause(f, 0, false, vconstrs);
257 IConstr[] constrs = new IConstr[vconstrs.size()];
258 vconstrs.copyTo(constrs);
259 return constrs;
260 }
261
262
263
264
265
266
267
268
269
270 public IConstr[] iff(int y, IVecInt literals) throws ContradictionException {
271 literals.push(y);
272 int[] f = new int[literals.size()];
273 literals.copyTo(f);
274 IVec<IConstr> vconstrs = new Vec<IConstr>();
275 iff2Clause(f, 0, false, vconstrs);
276 IConstr[] constrs = new IConstr[vconstrs.size()];
277 vconstrs.copyTo(constrs);
278 return constrs;
279 }
280
281
282
283
284 public void xor(int x, int a, int b) throws ContradictionException {
285 IVecInt clause = new VecInt(3);
286 clause.push(-a).push(b).push(x);
287 processClause(clause);
288 clause.clear();
289 clause.push(a).push(-b).push(x);
290 processClause(clause);
291 clause.clear();
292 clause.push(-a).push(-b).push(-x);
293 processClause(clause);
294 clause.clear();
295 clause.push(a).push(b).push(-x);
296 processClause(clause);
297 clause.clear();
298 }
299
300 private void xor2Clause(int[] f, int prefix, boolean negation,
301 IVec<IConstr> constrs) throws ContradictionException {
302 if (prefix == f.length - 1) {
303 IVecInt clause = new VecInt(f.length + 1);
304 for (int i = 0; i < f.length - 1; ++i) {
305 clause.push(f[i]);
306 }
307 clause.push(f[f.length - 1] * (negation ? -1 : 1));
308 constrs.push(processClause(clause));
309 return;
310 }
311
312 if (negation) {
313 f[prefix] = -f[prefix];
314 xor2Clause(f, prefix + 1, false, constrs);
315 f[prefix] = -f[prefix];
316
317 xor2Clause(f, prefix + 1, true, constrs);
318 } else {
319 xor2Clause(f, prefix + 1, false, constrs);
320
321 f[prefix] = -f[prefix];
322 xor2Clause(f, prefix + 1, true, constrs);
323 f[prefix] = -f[prefix];
324 }
325 }
326
327 private void iff2Clause(int[] f, int prefix, boolean negation,
328 IVec<IConstr> constrs) throws ContradictionException {
329 if (prefix == f.length - 1) {
330 IVecInt clause = new VecInt(f.length + 1);
331 for (int i = 0; i < f.length - 1; ++i) {
332 clause.push(f[i]);
333 }
334 clause.push(f[f.length - 1] * (negation ? -1 : 1));
335 processClause(clause);
336 return;
337 }
338
339 if (negation) {
340 iff2Clause(f, prefix + 1, false, constrs);
341 f[prefix] = -f[prefix];
342 iff2Clause(f, prefix + 1, true, constrs);
343 f[prefix] = -f[prefix];
344 } else {
345 f[prefix] = -f[prefix];
346 iff2Clause(f, prefix + 1, false, constrs);
347 f[prefix] = -f[prefix];
348 iff2Clause(f, prefix + 1, true, constrs);
349 }
350 }
351
352
353
354
355
356
357 public void fullAdderSum(int x, int a, int b, int c)
358 throws ContradictionException {
359 IVecInt clause = new VecInt(4);
360
361 clause.push(a).push(b).push(c).push(-x);
362 processClause(clause);
363 clause.clear();
364
365 clause.push(a).push(-b).push(-c).push(-x);
366 processClause(clause);
367 clause.clear();
368 clause.push(-a).push(b).push(-c).push(-x);
369 processClause(clause);
370 clause.clear();
371 clause.push(-a).push(-b).push(c).push(-x);
372 processClause(clause);
373 clause.clear();
374 clause.push(-a).push(-b).push(-c).push(x);
375 processClause(clause);
376 clause.clear();
377 clause.push(-a).push(b).push(c).push(x);
378 processClause(clause);
379 clause.clear();
380 clause.push(a).push(-b).push(c).push(x);
381 processClause(clause);
382 clause.clear();
383 clause.push(a).push(b).push(-c).push(x);
384 processClause(clause);
385 clause.clear();
386 }
387
388
389
390
391 public void fullAdderCarry(int x, int a, int b, int c)
392 throws ContradictionException {
393 IVecInt clause = new VecInt(3);
394 clause.push(-b).push(-c).push(x);
395 processClause(clause);
396 clause.clear();
397 clause.push(-a).push(-c).push(x);
398 processClause(clause);
399 clause.clear();
400 clause.push(-a).push(-b).push(x);
401 processClause(clause);
402 clause.clear();
403 clause.push(b).push(c).push(-x);
404 processClause(clause);
405 clause.clear();
406 clause.push(a).push(c).push(-x);
407 processClause(clause);
408 clause.clear();
409 clause.push(a).push(b).push(-x);
410 processClause(clause);
411 clause.clear();
412 }
413
414
415
416
417 public void additionalFullAdderConstraints(int xcarry, int xsum, int a,
418 int b, int c) throws ContradictionException {
419 IVecInt clause = new VecInt(3);
420 clause.push(-xcarry).push(-xsum).push(a);
421 processClause(clause);
422 clause.push(-xcarry).push(-xsum).push(b);
423 processClause(clause);
424 clause.push(-xcarry).push(-xsum).push(c);
425 processClause(clause);
426 clause.push(xcarry).push(xsum).push(-a);
427 processClause(clause);
428 clause.push(xcarry).push(xsum).push(-b);
429 processClause(clause);
430 clause.push(xcarry).push(xsum).push(-c);
431 processClause(clause);
432 }
433
434
435
436
437 public void halfAdderSum(int x, int a, int b) throws ContradictionException {
438 xor(x, a, b);
439 }
440
441
442
443
444 public void halfAdderCarry(int x, int a, int b)
445 throws ContradictionException {
446 and(x, a, b);
447 }
448
449
450
451
452
453
454
455
456 public void optimisationFunction(IVecInt literals, IVec<BigInteger> coefs,
457 IVecInt result) throws ContradictionException {
458 IVec<IVecInt> buckets = new Vec<IVecInt>();
459 IVecInt bucket;
460
461 for (int i = 0; i < literals.size(); i++) {
462 int p = literals.get(i);
463 BigInteger a = coefs.get(i);
464 for (int j = 0; j < a.bitLength(); j++) {
465 bucket = createIfNull(buckets, j);
466 if (a.testBit(j)) {
467 bucket.push(p);
468 }
469 }
470 }
471
472 int x, y, z;
473 int sum, carry;
474 for (int i = 0; i < buckets.size(); i++) {
475 bucket = buckets.get(i);
476 while (bucket.size() >= 3) {
477 x = bucket.get(0);
478 y = bucket.get(1);
479 z = bucket.get(2);
480 bucket.remove(x);
481 bucket.remove(y);
482 bucket.remove(z);
483 sum = nextFreeVarId(true);
484 carry = nextFreeVarId(true);
485 fullAdderSum(sum, x, y, z);
486 fullAdderCarry(carry, x, y, z);
487 additionalFullAdderConstraints(carry, sum, x, y, z);
488 bucket.push(sum);
489 createIfNull(buckets, i + 1).push(carry);
490 }
491 while (bucket.size() == 2) {
492 x = bucket.get(0);
493 y = bucket.get(1);
494 bucket.remove(x);
495 bucket.remove(y);
496 sum = nextFreeVarId(true);
497 carry = nextFreeVarId(true);
498 halfAdderSum(sum, x, y);
499 halfAdderCarry(carry, x, y);
500 bucket.push(sum);
501 createIfNull(buckets, i + 1).push(carry);
502 }
503 assert bucket.size() == 1;
504 result.push(bucket.last());
505 bucket.pop();
506 assert bucket.isEmpty();
507 }
508 }
509
510
511
512
513
514
515
516
517
518 private IVecInt createIfNull(IVec<IVecInt> buckets, int i) {
519 IVecInt bucket = buckets.get(i);
520 if (bucket == null) {
521 bucket = new VecInt();
522 buckets.push(bucket);
523 assert buckets.get(i) == bucket;
524 }
525 return bucket;
526
527 }
528 }