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 }