1224fd3a9a9a31f8c1007a12e78b461dbf5ee609
[yosys.git] / libs / ezsat / ezsat.cc
1 /*
2 * ezSAT -- A simple and easy to use CNF generator for SAT solvers
3 *
4 * Copyright (C) 2013 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20 #include "ezsat.h"
21
22 #include <cmath>
23 #include <algorithm>
24 #include <cassert>
25 #include <string>
26
27 #include <stdlib.h>
28
29 const int ezSAT::CONST_TRUE = 1;
30 const int ezSAT::CONST_FALSE = 2;
31
32 static std::string my_int_to_string(int i)
33 {
34 #ifdef __MINGW32__
35 char buffer[64];
36 snprintf(buffer, 64, "%d", i);
37 return buffer;
38 #else
39 return std::to_string(i);
40 #endif
41 }
42
43 ezSAT::ezSAT()
44 {
45 statehash = 5381;
46
47 flag_keep_cnf = false;
48 flag_non_incremental = false;
49
50 non_incremental_solve_used_up = false;
51
52 cnfConsumed = false;
53 cnfVariableCount = 0;
54 cnfClausesCount = 0;
55
56 solverTimeout = 0;
57 solverTimoutStatus = false;
58
59 literal("CONST_TRUE");
60 literal("CONST_FALSE");
61
62 assert(literal("CONST_TRUE") == CONST_TRUE);
63 assert(literal("CONST_FALSE") == CONST_FALSE);
64 }
65
66 ezSAT::~ezSAT()
67 {
68 }
69
70 void ezSAT::addhash(unsigned int h)
71 {
72 statehash = ((statehash << 5) + statehash) ^ h;
73 }
74
75 int ezSAT::value(bool val)
76 {
77 return val ? CONST_TRUE : CONST_FALSE;
78 }
79
80 int ezSAT::literal()
81 {
82 literals.push_back(std::string());
83 return literals.size();
84 }
85
86 int ezSAT::literal(const std::string &name)
87 {
88 if (literalsCache.count(name) == 0) {
89 literals.push_back(name);
90 literalsCache[name] = literals.size();
91 }
92 return literalsCache.at(name);
93 }
94
95 int ezSAT::frozen_literal()
96 {
97 int id = literal();
98 freeze(id);
99 return id;
100 }
101
102 int ezSAT::frozen_literal(const std::string &name)
103 {
104 int id = literal(name);
105 freeze(id);
106 return id;
107 }
108
109 int ezSAT::expression(OpId op, int a, int b, int c, int d, int e, int f)
110 {
111 std::vector<int> args(6);
112 args[0] = a, args[1] = b, args[2] = c;
113 args[3] = d, args[4] = e, args[5] = f;
114 return expression(op, args);
115 }
116
117 int ezSAT::expression(OpId op, const std::vector<int> &args)
118 {
119 std::vector<int> myArgs;
120 myArgs.reserve(args.size());
121 bool xorRemovedOddTrues = false;
122
123 addhash(__LINE__);
124 addhash(op);
125
126 for (auto arg : args)
127 {
128 addhash(__LINE__);
129 addhash(arg);
130
131 if (arg == 0)
132 continue;
133 if (op == OpAnd && arg == CONST_TRUE)
134 continue;
135 if ((op == OpOr || op == OpXor) && arg == CONST_FALSE)
136 continue;
137 if (op == OpXor && arg == CONST_TRUE) {
138 xorRemovedOddTrues = !xorRemovedOddTrues;
139 continue;
140 }
141 myArgs.push_back(arg);
142 }
143
144 if (myArgs.size() > 0 && (op == OpAnd || op == OpOr || op == OpXor || op == OpIFF)) {
145 std::sort(myArgs.begin(), myArgs.end());
146 int j = 0;
147 for (int i = 1; i < int(myArgs.size()); i++)
148 if (j < 0 || myArgs[j] != myArgs[i])
149 myArgs[++j] = myArgs[i];
150 else if (op == OpXor)
151 j--;
152 myArgs.resize(j+1);
153 }
154
155 switch (op)
156 {
157 case OpNot:
158 assert(myArgs.size() == 1);
159 if (myArgs[0] == CONST_TRUE)
160 return CONST_FALSE;
161 if (myArgs[0] == CONST_FALSE)
162 return CONST_TRUE;
163 break;
164
165 case OpAnd:
166 if (myArgs.size() == 0)
167 return CONST_TRUE;
168 if (myArgs.size() == 1)
169 return myArgs[0];
170 break;
171
172 case OpOr:
173 if (myArgs.size() == 0)
174 return CONST_FALSE;
175 if (myArgs.size() == 1)
176 return myArgs[0];
177 break;
178
179 case OpXor:
180 if (myArgs.size() == 0)
181 return xorRemovedOddTrues ? CONST_TRUE : CONST_FALSE;
182 if (myArgs.size() == 1)
183 return xorRemovedOddTrues ? NOT(myArgs[0]) : myArgs[0];
184 break;
185
186 case OpIFF:
187 assert(myArgs.size() >= 1);
188 if (myArgs.size() == 1)
189 return CONST_TRUE;
190 // FIXME: Add proper const folding
191 break;
192
193 case OpITE:
194 assert(myArgs.size() == 3);
195 if (myArgs[0] == CONST_TRUE)
196 return myArgs[1];
197 if (myArgs[0] == CONST_FALSE)
198 return myArgs[2];
199 break;
200
201 default:
202 abort();
203 }
204
205 std::pair<OpId, std::vector<int>> myExpr(op, myArgs);
206 int id = 0;
207
208 if (expressionsCache.count(myExpr) > 0) {
209 id = expressionsCache.at(myExpr);
210 } else {
211 id = -(int(expressions.size()) + 1);
212 expressionsCache[myExpr] = id;
213 expressions.push_back(myExpr);
214 }
215
216 if (xorRemovedOddTrues)
217 id = NOT(id);
218
219 addhash(__LINE__);
220 addhash(id);
221
222 return id;
223 }
224
225 void ezSAT::lookup_literal(int id, std::string &name) const
226 {
227 assert(0 < id && id <= int(literals.size()));
228 name = literals[id - 1];
229 }
230
231 const std::string &ezSAT::lookup_literal(int id) const
232 {
233 assert(0 < id && id <= int(literals.size()));
234 return literals[id - 1];
235 }
236
237 void ezSAT::lookup_expression(int id, OpId &op, std::vector<int> &args) const
238 {
239 assert(0 < -id && -id <= int(expressions.size()));
240 op = expressions[-id - 1].first;
241 args = expressions[-id - 1].second;
242 }
243
244 const std::vector<int> &ezSAT::lookup_expression(int id, OpId &op) const
245 {
246 assert(0 < -id && -id <= int(expressions.size()));
247 op = expressions[-id - 1].first;
248 return expressions[-id - 1].second;
249 }
250
251 int ezSAT::parse_string(const std::string &)
252 {
253 abort();
254 }
255
256 std::string ezSAT::to_string(int id) const
257 {
258 std::string text;
259
260 if (id > 0)
261 {
262 lookup_literal(id, text);
263 }
264 else
265 {
266 OpId op;
267 std::vector<int> args;
268 lookup_expression(id, op, args);
269
270 switch (op)
271 {
272 case OpNot:
273 text = "not(";
274 break;
275
276 case OpAnd:
277 text = "and(";
278 break;
279
280 case OpOr:
281 text = "or(";
282 break;
283
284 case OpXor:
285 text = "xor(";
286 break;
287
288 case OpIFF:
289 text = "iff(";
290 break;
291
292 case OpITE:
293 text = "ite(";
294 break;
295
296 default:
297 abort();
298 }
299
300 for (int i = 0; i < int(args.size()); i++) {
301 if (i > 0)
302 text += ", ";
303 text += to_string(args[i]);
304 }
305
306 text += ")";
307 }
308
309 return text;
310 }
311
312 int ezSAT::eval(int id, const std::vector<int> &values) const
313 {
314 if (id > 0) {
315 if (id <= int(values.size()) && (values[id-1] == CONST_TRUE || values[id-1] == CONST_FALSE || values[id-1] == 0))
316 return values[id-1];
317 return 0;
318 }
319
320 OpId op;
321 const std::vector<int> &args = lookup_expression(id, op);
322 int a, b;
323
324 switch (op)
325 {
326 case OpNot:
327 assert(args.size() == 1);
328 a = eval(args[0], values);
329 if (a == CONST_TRUE)
330 return CONST_FALSE;
331 if (a == CONST_FALSE)
332 return CONST_TRUE;
333 return 0;
334 case OpAnd:
335 a = CONST_TRUE;
336 for (auto arg : args) {
337 b = eval(arg, values);
338 if (b != CONST_TRUE && b != CONST_FALSE)
339 a = 0;
340 if (b == CONST_FALSE)
341 return CONST_FALSE;
342 }
343 return a;
344 case OpOr:
345 a = CONST_FALSE;
346 for (auto arg : args) {
347 b = eval(arg, values);
348 if (b != CONST_TRUE && b != CONST_FALSE)
349 a = 0;
350 if (b == CONST_TRUE)
351 return CONST_TRUE;
352 }
353 return a;
354 case OpXor:
355 a = CONST_FALSE;
356 for (auto arg : args) {
357 b = eval(arg, values);
358 if (b != CONST_TRUE && b != CONST_FALSE)
359 return 0;
360 if (b == CONST_TRUE)
361 a = a == CONST_TRUE ? CONST_FALSE : CONST_TRUE;
362 }
363 return a;
364 case OpIFF:
365 assert(args.size() > 0);
366 a = eval(args[0], values);
367 for (auto arg : args) {
368 b = eval(arg, values);
369 if (b != CONST_TRUE && b != CONST_FALSE)
370 return 0;
371 if (b != a)
372 return CONST_FALSE;
373 }
374 return CONST_TRUE;
375 case OpITE:
376 assert(args.size() == 3);
377 a = eval(args[0], values);
378 if (a == CONST_TRUE)
379 return eval(args[1], values);
380 if (a == CONST_FALSE)
381 return eval(args[2], values);
382 return 0;
383 default:
384 abort();
385 }
386 }
387
388 void ezSAT::clear()
389 {
390 cnfConsumed = false;
391 cnfVariableCount = 0;
392 cnfClausesCount = 0;
393 cnfLiteralVariables.clear();
394 cnfExpressionVariables.clear();
395 cnfClauses.clear();
396 }
397
398 void ezSAT::freeze(int)
399 {
400 }
401
402 bool ezSAT::eliminated(int)
403 {
404 return false;
405 }
406
407 void ezSAT::assume(int id)
408 {
409 addhash(__LINE__);
410 addhash(id);
411
412 if (id < 0)
413 {
414 assert(0 < -id && -id <= int(expressions.size()));
415 cnfExpressionVariables.resize(expressions.size());
416
417 if (cnfExpressionVariables[-id-1] == 0)
418 {
419 OpId op;
420 std::vector<int> args;
421 lookup_expression(id, op, args);
422
423 if (op == OpNot) {
424 int idx = bind(args[0]);
425 cnfClauses.push_back(std::vector<int>(1, -idx));
426 cnfClausesCount++;
427 return;
428 }
429 if (op == OpOr) {
430 std::vector<int> clause;
431 for (int arg : args)
432 clause.push_back(bind(arg));
433 cnfClauses.push_back(clause);
434 cnfClausesCount++;
435 return;
436 }
437 if (op == OpAnd) {
438 for (int arg : args) {
439 cnfClauses.push_back(std::vector<int>(1, bind(arg)));
440 cnfClausesCount++;
441 }
442 return;
443 }
444 }
445 }
446
447 int idx = bind(id);
448 cnfClauses.push_back(std::vector<int>(1, idx));
449 cnfClausesCount++;
450 }
451
452 void ezSAT::add_clause(const std::vector<int> &args)
453 {
454 addhash(__LINE__);
455 for (auto arg : args)
456 addhash(arg);
457
458 cnfClauses.push_back(args);
459 cnfClausesCount++;
460 }
461
462 void ezSAT::add_clause(const std::vector<int> &args, bool argsPolarity, int a, int b, int c)
463 {
464 std::vector<int> clause;
465 for (auto arg : args)
466 clause.push_back(argsPolarity ? +arg : -arg);
467 if (a != 0)
468 clause.push_back(a);
469 if (b != 0)
470 clause.push_back(b);
471 if (c != 0)
472 clause.push_back(c);
473 add_clause(clause);
474 }
475
476 void ezSAT::add_clause(int a, int b, int c)
477 {
478 std::vector<int> clause;
479 if (a != 0)
480 clause.push_back(a);
481 if (b != 0)
482 clause.push_back(b);
483 if (c != 0)
484 clause.push_back(c);
485 add_clause(clause);
486 }
487
488 int ezSAT::bind_cnf_not(const std::vector<int> &args)
489 {
490 assert(args.size() == 1);
491 return -args[0];
492 }
493
494 int ezSAT::bind_cnf_and(const std::vector<int> &args)
495 {
496 assert(args.size() >= 2);
497
498 int idx = ++cnfVariableCount;
499 add_clause(args, false, idx);
500
501 for (auto arg : args)
502 add_clause(-idx, arg);
503
504 return idx;
505 }
506
507 int ezSAT::bind_cnf_or(const std::vector<int> &args)
508 {
509 assert(args.size() >= 2);
510
511 int idx = ++cnfVariableCount;
512 add_clause(args, true, -idx);
513
514 for (auto arg : args)
515 add_clause(idx, -arg);
516
517 return idx;
518 }
519
520 int ezSAT::bound(int id) const
521 {
522 if (id > 0 && id <= int(cnfLiteralVariables.size()))
523 return cnfLiteralVariables[id-1];
524 if (-id > 0 && -id <= int(cnfExpressionVariables.size()))
525 return cnfExpressionVariables[-id-1];
526 return 0;
527 }
528
529 std::string ezSAT::cnfLiteralInfo(int idx) const
530 {
531 for (int i = 0; i < int(cnfLiteralVariables.size()); i++) {
532 if (cnfLiteralVariables[i] == idx)
533 return to_string(i+1);
534 if (cnfLiteralVariables[i] == -idx)
535 return "NOT " + to_string(i+1);
536 }
537 for (int i = 0; i < int(cnfExpressionVariables.size()); i++) {
538 if (cnfExpressionVariables[i] == idx)
539 return to_string(-i-1);
540 if (cnfExpressionVariables[i] == -idx)
541 return "NOT " + to_string(-i-1);
542 }
543 return "<unnamed>";
544 }
545
546 int ezSAT::bind(int id, bool auto_freeze)
547 {
548 addhash(__LINE__);
549 addhash(id);
550 addhash(auto_freeze);
551
552 if (id >= 0) {
553 assert(0 < id && id <= int(literals.size()));
554 cnfLiteralVariables.resize(literals.size());
555 if (eliminated(cnfLiteralVariables[id-1])) {
556 fprintf(stderr, "ezSAT: Missing freeze on literal `%s'.\n", to_string(id).c_str());
557 abort();
558 }
559 if (cnfLiteralVariables[id-1] == 0) {
560 cnfLiteralVariables[id-1] = ++cnfVariableCount;
561 if (id == CONST_TRUE)
562 add_clause(+cnfLiteralVariables[id-1]);
563 if (id == CONST_FALSE)
564 add_clause(-cnfLiteralVariables[id-1]);
565 }
566 return cnfLiteralVariables[id-1];
567 }
568
569 assert(0 < -id && -id <= int(expressions.size()));
570 cnfExpressionVariables.resize(expressions.size());
571
572 if (eliminated(cnfExpressionVariables[-id-1]))
573 {
574 cnfExpressionVariables[-id-1] = 0;
575
576 // this will recursively call bind(id). within the recursion
577 // the cnf is pre-set to 0. an idx is allocated there, then it
578 // is frozen, then it returns here with the new idx already set.
579 if (auto_freeze)
580 freeze(id);
581 }
582
583 if (cnfExpressionVariables[-id-1] == 0)
584 {
585 OpId op;
586 std::vector<int> args;
587 lookup_expression(id, op, args);
588 int idx = 0;
589
590 if (op == OpXor) {
591 while (args.size() > 1) {
592 std::vector<int> newArgs;
593 for (int i = 0; i < int(args.size()); i += 2)
594 if (i+1 == int(args.size())) {
595 newArgs.push_back(args[i]);
596 } else {
597 int sub1 = AND(args[i], NOT(args[i+1]));
598 int sub2 = AND(NOT(args[i]), args[i+1]);
599 newArgs.push_back(OR(sub1, sub2));
600 }
601 args.swap(newArgs);
602 }
603 idx = bind(args.at(0), false);
604 goto assign_idx;
605 }
606
607 if (op == OpIFF) {
608 std::vector<int> invArgs;
609 for (auto arg : args)
610 invArgs.push_back(NOT(arg));
611 int sub1 = expression(OpAnd, args);
612 int sub2 = expression(OpAnd, invArgs);
613 idx = bind(OR(sub1, sub2), false);
614 goto assign_idx;
615 }
616
617 if (op == OpITE) {
618 int sub1 = AND(args[0], args[1]);
619 int sub2 = AND(NOT(args[0]), args[2]);
620 idx = bind(OR(sub1, sub2), false);
621 goto assign_idx;
622 }
623
624 for (int i = 0; i < int(args.size()); i++)
625 args[i] = bind(args[i], false);
626
627 switch (op)
628 {
629 case OpNot: idx = bind_cnf_not(args); break;
630 case OpAnd: idx = bind_cnf_and(args); break;
631 case OpOr: idx = bind_cnf_or(args); break;
632 default: abort();
633 }
634
635 assign_idx:
636 assert(idx != 0);
637 cnfExpressionVariables[-id-1] = idx;
638 }
639
640 return cnfExpressionVariables[-id-1];
641 }
642
643 void ezSAT::consumeCnf()
644 {
645 if (mode_keep_cnf())
646 cnfClausesBackup.insert(cnfClausesBackup.end(), cnfClauses.begin(), cnfClauses.end());
647 else
648 cnfConsumed = true;
649 cnfClauses.clear();
650 }
651
652 void ezSAT::consumeCnf(std::vector<std::vector<int>> &cnf)
653 {
654 if (mode_keep_cnf())
655 cnfClausesBackup.insert(cnfClausesBackup.end(), cnfClauses.begin(), cnfClauses.end());
656 else
657 cnfConsumed = true;
658 cnf.swap(cnfClauses);
659 cnfClauses.clear();
660 }
661
662 void ezSAT::getFullCnf(std::vector<std::vector<int>> &full_cnf) const
663 {
664 assert(full_cnf.empty());
665 full_cnf.insert(full_cnf.end(), cnfClausesBackup.begin(), cnfClausesBackup.end());
666 full_cnf.insert(full_cnf.end(), cnfClauses.begin(), cnfClauses.end());
667 }
668
669 void ezSAT::preSolverCallback()
670 {
671 assert(!non_incremental_solve_used_up);
672 if (mode_non_incremental())
673 non_incremental_solve_used_up = true;
674 }
675
676 bool ezSAT::solver(const std::vector<int>&, std::vector<bool>&, const std::vector<int>&)
677 {
678 preSolverCallback();
679 fprintf(stderr, "************************************************************************\n");
680 fprintf(stderr, "ERROR: You are trying to use the solve() method of the ezSAT base class!\n");
681 fprintf(stderr, "Use a dervied class like ezMiniSAT instead.\n");
682 fprintf(stderr, "************************************************************************\n");
683 abort();
684 }
685
686 std::vector<int> ezSAT::vec_const(const std::vector<bool> &bits)
687 {
688 std::vector<int> vec;
689 for (auto bit : bits)
690 vec.push_back(bit ? CONST_TRUE : CONST_FALSE);
691 return vec;
692 }
693
694 std::vector<int> ezSAT::vec_const_signed(int64_t value, int numBits)
695 {
696 std::vector<int> vec;
697 for (int i = 0; i < numBits; i++)
698 vec.push_back(((value >> i) & 1) != 0 ? CONST_TRUE : CONST_FALSE);
699 return vec;
700 }
701
702 std::vector<int> ezSAT::vec_const_unsigned(uint64_t value, int numBits)
703 {
704 std::vector<int> vec;
705 for (int i = 0; i < numBits; i++)
706 vec.push_back(((value >> i) & 1) != 0 ? CONST_TRUE : CONST_FALSE);
707 return vec;
708 }
709
710 std::vector<int> ezSAT::vec_var(int numBits)
711 {
712 std::vector<int> vec;
713 for (int i = 0; i < numBits; i++)
714 vec.push_back(literal());
715 return vec;
716 }
717
718 std::vector<int> ezSAT::vec_var(std::string name, int numBits)
719 {
720 std::vector<int> vec;
721 for (int i = 0; i < numBits; i++) {
722 vec.push_back(VAR(name + my_int_to_string(i)));
723 }
724 return vec;
725 }
726
727 std::vector<int> ezSAT::vec_cast(const std::vector<int> &vec1, int toBits, bool signExtend)
728 {
729 std::vector<int> vec;
730 for (int i = 0; i < toBits; i++)
731 if (i >= int(vec1.size()))
732 vec.push_back(signExtend ? vec1.back() : CONST_FALSE);
733 else
734 vec.push_back(vec1[i]);
735 return vec;
736 }
737
738 std::vector<int> ezSAT::vec_not(const std::vector<int> &vec1)
739 {
740 std::vector<int> vec;
741 for (auto bit : vec1)
742 vec.push_back(NOT(bit));
743 return vec;
744 }
745
746 std::vector<int> ezSAT::vec_and(const std::vector<int> &vec1, const std::vector<int> &vec2)
747 {
748 assert(vec1.size() == vec2.size());
749 std::vector<int> vec(vec1.size());
750 for (int i = 0; i < int(vec1.size()); i++)
751 vec[i] = AND(vec1[i], vec2[i]);
752 return vec;
753 }
754
755 std::vector<int> ezSAT::vec_or(const std::vector<int> &vec1, const std::vector<int> &vec2)
756 {
757 assert(vec1.size() == vec2.size());
758 std::vector<int> vec(vec1.size());
759 for (int i = 0; i < int(vec1.size()); i++)
760 vec[i] = OR(vec1[i], vec2[i]);
761 return vec;
762 }
763
764 std::vector<int> ezSAT::vec_xor(const std::vector<int> &vec1, const std::vector<int> &vec2)
765 {
766 assert(vec1.size() == vec2.size());
767 std::vector<int> vec(vec1.size());
768 for (int i = 0; i < int(vec1.size()); i++)
769 vec[i] = XOR(vec1[i], vec2[i]);
770 return vec;
771 }
772
773 std::vector<int> ezSAT::vec_iff(const std::vector<int> &vec1, const std::vector<int> &vec2)
774 {
775 assert(vec1.size() == vec2.size());
776 std::vector<int> vec(vec1.size());
777 for (int i = 0; i < int(vec1.size()); i++)
778 vec[i] = IFF(vec1[i], vec2[i]);
779 return vec;
780 }
781
782 std::vector<int> ezSAT::vec_ite(const std::vector<int> &vec1, const std::vector<int> &vec2, const std::vector<int> &vec3)
783 {
784 assert(vec1.size() == vec2.size() && vec2.size() == vec3.size());
785 std::vector<int> vec(vec1.size());
786 for (int i = 0; i < int(vec1.size()); i++)
787 vec[i] = ITE(vec1[i], vec2[i], vec3[i]);
788 return vec;
789 }
790
791
792 std::vector<int> ezSAT::vec_ite(int sel, const std::vector<int> &vec1, const std::vector<int> &vec2)
793 {
794 assert(vec1.size() == vec2.size());
795 std::vector<int> vec(vec1.size());
796 for (int i = 0; i < int(vec1.size()); i++)
797 vec[i] = ITE(sel, vec1[i], vec2[i]);
798 return vec;
799 }
800
801 // 'y' is the MSB (carry) and x the LSB (sum) output
802 static void fulladder(ezSAT *that, int a, int b, int c, int &y, int &x)
803 {
804 int tmp = that->XOR(a, b);
805 int new_x = that->XOR(tmp, c);
806 int new_y = that->OR(that->AND(a, b), that->AND(c, tmp));
807 #if 0
808 printf("FULLADD> a=%s, b=%s, c=%s, carry=%s, sum=%s\n", that->to_string(a).c_str(), that->to_string(b).c_str(),
809 that->to_string(c).c_str(), that->to_string(new_y).c_str(), that->to_string(new_x).c_str());
810 #endif
811 x = new_x, y = new_y;
812 }
813
814 // 'y' is the MSB (carry) and x the LSB (sum) output
815 static void halfadder(ezSAT *that, int a, int b, int &y, int &x)
816 {
817 int new_x = that->XOR(a, b);
818 int new_y = that->AND(a, b);
819 #if 0
820 printf("HALFADD> a=%s, b=%s, carry=%s, sum=%s\n", that->to_string(a).c_str(), that->to_string(b).c_str(),
821 that->to_string(new_y).c_str(), that->to_string(new_x).c_str());
822 #endif
823 x = new_x, y = new_y;
824 }
825
826 std::vector<int> ezSAT::vec_count(const std::vector<int> &vec, int numBits, bool clip)
827 {
828 std::vector<int> sum = vec_const_unsigned(0, numBits);
829 std::vector<int> carry_vector;
830
831 for (auto bit : vec) {
832 int carry = bit;
833 for (int i = 0; i < numBits; i++)
834 halfadder(this, carry, sum[i], carry, sum[i]);
835 carry_vector.push_back(carry);
836 }
837
838 if (clip) {
839 int overflow = vec_reduce_or(carry_vector);
840 sum = vec_ite(overflow, vec_const_unsigned(~0, numBits), sum);
841 }
842
843 #if 0
844 printf("COUNT> vec=[");
845 for (int i = int(vec.size())-1; i >= 0; i--)
846 printf("%s%s", to_string(vec[i]).c_str(), i ? ", " : "");
847 printf("], result=[");
848 for (int i = int(sum.size())-1; i >= 0; i--)
849 printf("%s%s", to_string(sum[i]).c_str(), i ? ", " : "");
850 printf("]\n");
851 #endif
852
853 return sum;
854 }
855
856 std::vector<int> ezSAT::vec_add(const std::vector<int> &vec1, const std::vector<int> &vec2)
857 {
858 assert(vec1.size() == vec2.size());
859 std::vector<int> vec(vec1.size());
860 int carry = CONST_FALSE;
861 for (int i = 0; i < int(vec1.size()); i++)
862 fulladder(this, vec1[i], vec2[i], carry, carry, vec[i]);
863
864 #if 0
865 printf("ADD> vec1=[");
866 for (int i = int(vec1.size())-1; i >= 0; i--)
867 printf("%s%s", to_string(vec1[i]).c_str(), i ? ", " : "");
868 printf("], vec2=[");
869 for (int i = int(vec2.size())-1; i >= 0; i--)
870 printf("%s%s", to_string(vec2[i]).c_str(), i ? ", " : "");
871 printf("], result=[");
872 for (int i = int(vec.size())-1; i >= 0; i--)
873 printf("%s%s", to_string(vec[i]).c_str(), i ? ", " : "");
874 printf("]\n");
875 #endif
876
877 return vec;
878 }
879
880 std::vector<int> ezSAT::vec_sub(const std::vector<int> &vec1, const std::vector<int> &vec2)
881 {
882 assert(vec1.size() == vec2.size());
883 std::vector<int> vec(vec1.size());
884 int carry = CONST_TRUE;
885 for (int i = 0; i < int(vec1.size()); i++)
886 fulladder(this, vec1[i], NOT(vec2[i]), carry, carry, vec[i]);
887
888 #if 0
889 printf("SUB> vec1=[");
890 for (int i = int(vec1.size())-1; i >= 0; i--)
891 printf("%s%s", to_string(vec1[i]).c_str(), i ? ", " : "");
892 printf("], vec2=[");
893 for (int i = int(vec2.size())-1; i >= 0; i--)
894 printf("%s%s", to_string(vec2[i]).c_str(), i ? ", " : "");
895 printf("], result=[");
896 for (int i = int(vec.size())-1; i >= 0; i--)
897 printf("%s%s", to_string(vec[i]).c_str(), i ? ", " : "");
898 printf("]\n");
899 #endif
900
901 return vec;
902 }
903
904 std::vector<int> ezSAT::vec_neg(const std::vector<int> &vec)
905 {
906 std::vector<int> zero(vec.size(), CONST_FALSE);
907 return vec_sub(zero, vec);
908 }
909
910 void ezSAT::vec_cmp(const std::vector<int> &vec1, const std::vector<int> &vec2, int &carry, int &overflow, int &sign, int &zero)
911 {
912 assert(vec1.size() == vec2.size());
913 carry = CONST_TRUE;
914 zero = CONST_FALSE;
915 for (int i = 0; i < int(vec1.size()); i++) {
916 overflow = carry;
917 fulladder(this, vec1[i], NOT(vec2[i]), carry, carry, sign);
918 zero = OR(zero, sign);
919 }
920 overflow = XOR(overflow, carry);
921 carry = NOT(carry);
922 zero = NOT(zero);
923
924 #if 0
925 printf("CMP> vec1=[");
926 for (int i = int(vec1.size())-1; i >= 0; i--)
927 printf("%s%s", to_string(vec1[i]).c_str(), i ? ", " : "");
928 printf("], vec2=[");
929 for (int i = int(vec2.size())-1; i >= 0; i--)
930 printf("%s%s", to_string(vec2[i]).c_str(), i ? ", " : "");
931 printf("], carry=%s, overflow=%s, sign=%s, zero=%s\n", to_string(carry).c_str(), to_string(overflow).c_str(), to_string(sign).c_str(), to_string(zero).c_str());
932 #endif
933 }
934
935 int ezSAT::vec_lt_signed(const std::vector<int> &vec1, const std::vector<int> &vec2)
936 {
937 int carry, overflow, sign, zero;
938 vec_cmp(vec1, vec2, carry, overflow, sign, zero);
939 return OR(AND(NOT(overflow), sign), AND(overflow, NOT(sign)));
940 }
941
942 int ezSAT::vec_le_signed(const std::vector<int> &vec1, const std::vector<int> &vec2)
943 {
944 int carry, overflow, sign, zero;
945 vec_cmp(vec1, vec2, carry, overflow, sign, zero);
946 return OR(AND(NOT(overflow), sign), AND(overflow, NOT(sign)), zero);
947 }
948
949 int ezSAT::vec_ge_signed(const std::vector<int> &vec1, const std::vector<int> &vec2)
950 {
951 int carry, overflow, sign, zero;
952 vec_cmp(vec1, vec2, carry, overflow, sign, zero);
953 return OR(AND(NOT(overflow), NOT(sign)), AND(overflow, sign));
954 }
955
956 int ezSAT::vec_gt_signed(const std::vector<int> &vec1, const std::vector<int> &vec2)
957 {
958 int carry, overflow, sign, zero;
959 vec_cmp(vec1, vec2, carry, overflow, sign, zero);
960 return AND(OR(AND(NOT(overflow), NOT(sign)), AND(overflow, sign)), NOT(zero));
961 }
962
963 int ezSAT::vec_lt_unsigned(const std::vector<int> &vec1, const std::vector<int> &vec2)
964 {
965 int carry, overflow, sign, zero;
966 vec_cmp(vec1, vec2, carry, overflow, sign, zero);
967 return carry;
968 }
969
970 int ezSAT::vec_le_unsigned(const std::vector<int> &vec1, const std::vector<int> &vec2)
971 {
972 int carry, overflow, sign, zero;
973 vec_cmp(vec1, vec2, carry, overflow, sign, zero);
974 return OR(carry, zero);
975 }
976
977 int ezSAT::vec_ge_unsigned(const std::vector<int> &vec1, const std::vector<int> &vec2)
978 {
979 int carry, overflow, sign, zero;
980 vec_cmp(vec1, vec2, carry, overflow, sign, zero);
981 return NOT(carry);
982 }
983
984 int ezSAT::vec_gt_unsigned(const std::vector<int> &vec1, const std::vector<int> &vec2)
985 {
986 int carry, overflow, sign, zero;
987 vec_cmp(vec1, vec2, carry, overflow, sign, zero);
988 return AND(NOT(carry), NOT(zero));
989 }
990
991 int ezSAT::vec_eq(const std::vector<int> &vec1, const std::vector<int> &vec2)
992 {
993 return vec_reduce_and(vec_iff(vec1, vec2));
994 }
995
996 int ezSAT::vec_ne(const std::vector<int> &vec1, const std::vector<int> &vec2)
997 {
998 return NOT(vec_reduce_and(vec_iff(vec1, vec2)));
999 }
1000
1001 std::vector<int> ezSAT::vec_shl(const std::vector<int> &vec1, int shift, bool signExtend)
1002 {
1003 std::vector<int> vec;
1004 for (int i = 0; i < int(vec1.size()); i++) {
1005 int j = i-shift;
1006 if (int(vec1.size()) <= j)
1007 vec.push_back(signExtend ? vec1.back() : CONST_FALSE);
1008 else if (0 <= j)
1009 vec.push_back(vec1[j]);
1010 else
1011 vec.push_back(CONST_FALSE);
1012 }
1013 return vec;
1014 }
1015
1016 std::vector<int> ezSAT::vec_srl(const std::vector<int> &vec1, int shift)
1017 {
1018 std::vector<int> vec;
1019 for (int i = 0; i < int(vec1.size()); i++) {
1020 int j = i-shift;
1021 while (j < 0)
1022 j += vec1.size();
1023 while (j >= int(vec1.size()))
1024 j -= vec1.size();
1025 vec.push_back(vec1[j]);
1026 }
1027 return vec;
1028 }
1029
1030 std::vector<int> ezSAT::vec_shift(const std::vector<int> &vec1, int shift, int extend_left, int extend_right)
1031 {
1032 std::vector<int> vec;
1033 for (int i = 0; i < int(vec1.size()); i++) {
1034 int j = i+shift;
1035 if (j < 0)
1036 vec.push_back(extend_right);
1037 else if (j >= int(vec1.size()))
1038 vec.push_back(extend_left);
1039 else
1040 vec.push_back(vec1[j]);
1041 }
1042 return vec;
1043 }
1044
1045 static int my_clog2(int x)
1046 {
1047 int result = 0;
1048 for (x--; x > 0; result++)
1049 x >>= 1;
1050 return result;
1051 }
1052
1053 std::vector<int> ezSAT::vec_shift_right(const std::vector<int> &vec1, const std::vector<int> &vec2, bool vec2_signed, int extend_left, int extend_right)
1054 {
1055 int vec2_bits = std::min(my_clog2(vec1.size()) + (vec2_signed ? 1 : 0), int(vec2.size()));
1056
1057 std::vector<int> overflow_bits(vec2.begin() + vec2_bits, vec2.end());
1058 int overflow_left = CONST_FALSE, overflow_right = CONST_FALSE;
1059
1060 if (vec2_signed) {
1061 int overflow = CONST_FALSE;
1062 for (auto bit : overflow_bits)
1063 overflow = OR(overflow, XOR(bit, vec2[vec2_bits-1]));
1064 overflow_left = AND(overflow, NOT(vec2.back()));
1065 overflow_right = AND(overflow, vec2.back());
1066 } else
1067 overflow_left = vec_reduce_or(overflow_bits);
1068
1069 std::vector<int> buffer = vec1;
1070
1071 if (vec2_signed)
1072 while (buffer.size() < vec1.size() + (1 << vec2_bits))
1073 buffer.push_back(extend_left);
1074
1075 std::vector<int> overflow_pattern_left(buffer.size(), extend_left);
1076 std::vector<int> overflow_pattern_right(buffer.size(), extend_right);
1077
1078 buffer = vec_ite(overflow_left, overflow_pattern_left, buffer);
1079
1080 if (vec2_signed)
1081 buffer = vec_ite(overflow_right, overflow_pattern_left, buffer);
1082
1083 for (int i = vec2_bits-1; i >= 0; i--) {
1084 std::vector<int> shifted_buffer;
1085 if (vec2_signed && i == vec2_bits-1)
1086 shifted_buffer = vec_shift(buffer, -(1 << i), extend_left, extend_right);
1087 else
1088 shifted_buffer = vec_shift(buffer, 1 << i, extend_left, extend_right);
1089 buffer = vec_ite(vec2[i], shifted_buffer, buffer);
1090 }
1091
1092 buffer.resize(vec1.size());
1093 return buffer;
1094 }
1095
1096 std::vector<int> ezSAT::vec_shift_left(const std::vector<int> &vec1, const std::vector<int> &vec2, bool vec2_signed, int extend_left, int extend_right)
1097 {
1098 // vec2_signed is not implemented in vec_shift_left() yet
1099 assert(vec2_signed == false);
1100
1101 int vec2_bits = std::min(my_clog2(vec1.size()), int(vec2.size()));
1102
1103 std::vector<int> overflow_bits(vec2.begin() + vec2_bits, vec2.end());
1104 int overflow = vec_reduce_or(overflow_bits);
1105
1106 std::vector<int> buffer = vec1;
1107 std::vector<int> overflow_pattern_right(buffer.size(), extend_right);
1108 buffer = vec_ite(overflow, overflow_pattern_right, buffer);
1109
1110 for (int i = 0; i < vec2_bits; i++) {
1111 std::vector<int> shifted_buffer;
1112 shifted_buffer = vec_shift(buffer, -(1 << i), extend_left, extend_right);
1113 buffer = vec_ite(vec2[i], shifted_buffer, buffer);
1114 }
1115
1116 buffer.resize(vec1.size());
1117 return buffer;
1118 }
1119
1120 void ezSAT::vec_append(std::vector<int> &vec, const std::vector<int> &vec1) const
1121 {
1122 for (auto bit : vec1)
1123 vec.push_back(bit);
1124 }
1125
1126 void ezSAT::vec_append_signed(std::vector<int> &vec, const std::vector<int> &vec1, int64_t value)
1127 {
1128 assert(int(vec1.size()) <= 64);
1129 for (int i = 0; i < int(vec1.size()); i++) {
1130 if (((value >> i) & 1) != 0)
1131 vec.push_back(vec1[i]);
1132 else
1133 vec.push_back(NOT(vec1[i]));
1134 }
1135 }
1136
1137 void ezSAT::vec_append_unsigned(std::vector<int> &vec, const std::vector<int> &vec1, uint64_t value)
1138 {
1139 assert(int(vec1.size()) <= 64);
1140 for (int i = 0; i < int(vec1.size()); i++) {
1141 if (((value >> i) & 1) != 0)
1142 vec.push_back(vec1[i]);
1143 else
1144 vec.push_back(NOT(vec1[i]));
1145 }
1146 }
1147
1148 int64_t ezSAT::vec_model_get_signed(const std::vector<int> &modelExpressions, const std::vector<bool> &modelValues, const std::vector<int> &vec1) const
1149 {
1150 int64_t value = 0;
1151 std::map<int, bool> modelMap;
1152 assert(modelExpressions.size() == modelValues.size());
1153 for (int i = 0; i < int(modelExpressions.size()); i++)
1154 modelMap[modelExpressions[i]] = modelValues[i];
1155 for (int i = 0; i < 64; i++) {
1156 int j = i < int(vec1.size()) ? i : vec1.size()-1;
1157 if (modelMap.at(vec1[j]))
1158 value |= int64_t(1) << i;
1159 }
1160 return value;
1161 }
1162
1163 uint64_t ezSAT::vec_model_get_unsigned(const std::vector<int> &modelExpressions, const std::vector<bool> &modelValues, const std::vector<int> &vec1) const
1164 {
1165 uint64_t value = 0;
1166 std::map<int, bool> modelMap;
1167 assert(modelExpressions.size() == modelValues.size());
1168 for (int i = 0; i < int(modelExpressions.size()); i++)
1169 modelMap[modelExpressions[i]] = modelValues[i];
1170 for (int i = 0; i < int(vec1.size()); i++)
1171 if (modelMap.at(vec1[i]))
1172 value |= uint64_t(1) << i;
1173 return value;
1174 }
1175
1176 int ezSAT::vec_reduce_and(const std::vector<int> &vec1)
1177 {
1178 return expression(OpAnd, vec1);
1179 }
1180
1181 int ezSAT::vec_reduce_or(const std::vector<int> &vec1)
1182 {
1183 return expression(OpOr, vec1);
1184 }
1185
1186 void ezSAT::vec_set(const std::vector<int> &vec1, const std::vector<int> &vec2)
1187 {
1188 assert(vec1.size() == vec2.size());
1189 for (int i = 0; i < int(vec1.size()); i++)
1190 SET(vec1[i], vec2[i]);
1191 }
1192
1193 void ezSAT::vec_set_signed(const std::vector<int> &vec1, int64_t value)
1194 {
1195 assert(int(vec1.size()) <= 64);
1196 for (int i = 0; i < int(vec1.size()); i++) {
1197 if (((value >> i) & 1) != 0)
1198 assume(vec1[i]);
1199 else
1200 assume(NOT(vec1[i]));
1201 }
1202 }
1203
1204 void ezSAT::vec_set_unsigned(const std::vector<int> &vec1, uint64_t value)
1205 {
1206 assert(int(vec1.size()) <= 64);
1207 for (int i = 0; i < int(vec1.size()); i++) {
1208 if (((value >> i) & 1) != 0)
1209 assume(vec1[i]);
1210 else
1211 assume(NOT(vec1[i]));
1212 }
1213 }
1214
1215 ezSATbit ezSAT::bit(_V a)
1216 {
1217 return ezSATbit(*this, a);
1218 }
1219
1220 ezSATvec ezSAT::vec(const std::vector<int> &vec)
1221 {
1222 return ezSATvec(*this, vec);
1223 }
1224
1225 void ezSAT::printDIMACS(FILE *f, bool verbose) const
1226 {
1227 if (cnfConsumed) {
1228 fprintf(stderr, "Usage error: printDIMACS() must not be called after cnfConsumed()!");
1229 abort();
1230 }
1231
1232 int digits = ceil(log10f(cnfVariableCount)) + 2;
1233
1234 fprintf(f, "c generated by ezSAT\n");
1235
1236 if (verbose)
1237 {
1238 fprintf(f, "c\n");
1239 fprintf(f, "c mapping of variables to literals:\n");
1240 for (int i = 0; i < int(cnfLiteralVariables.size()); i++)
1241 if (cnfLiteralVariables[i] != 0)
1242 fprintf(f, "c %*d: %s\n", digits, cnfLiteralVariables[i], literals[i].c_str());
1243
1244 fprintf(f, "c\n");
1245 fprintf(f, "c mapping of variables to expressions:\n");
1246 for (int i = 0; i < int(cnfExpressionVariables.size()); i++)
1247 if (cnfExpressionVariables[i] != 0)
1248 fprintf(f, "c %*d: %d\n", digits, cnfExpressionVariables[i], -i-1);
1249
1250 if (mode_keep_cnf()) {
1251 fprintf(f, "c\n");
1252 fprintf(f, "c %d clauses from backup, %d from current buffer\n",
1253 int(cnfClausesBackup.size()), int(cnfClauses.size()));
1254 }
1255
1256 fprintf(f, "c\n");
1257 }
1258
1259 std::vector<std::vector<int>> all_clauses;
1260 getFullCnf(all_clauses);
1261 assert(cnfClausesCount == int(all_clauses.size()));
1262
1263 fprintf(f, "p cnf %d %d\n", cnfVariableCount, cnfClausesCount);
1264 int maxClauseLen = 0;
1265 for (auto &clause : all_clauses)
1266 maxClauseLen = std::max(int(clause.size()), maxClauseLen);
1267 if (!verbose)
1268 maxClauseLen = std::min(maxClauseLen, 3);
1269 for (auto &clause : all_clauses) {
1270 for (auto idx : clause)
1271 fprintf(f, " %*d", digits, idx);
1272 if (maxClauseLen >= int(clause.size()))
1273 fprintf(f, " %*d\n", (digits + 1)*int(maxClauseLen - clause.size()) + digits, 0);
1274 else
1275 fprintf(f, " %*d\n", digits, 0);
1276 }
1277 }
1278
1279 static std::string expression2str(const std::pair<ezSAT::OpId, std::vector<int>> &data)
1280 {
1281 std::string text;
1282 switch (data.first) {
1283 #define X(op) case ezSAT::op: text += #op; break;
1284 X(OpNot)
1285 X(OpAnd)
1286 X(OpOr)
1287 X(OpXor)
1288 X(OpIFF)
1289 X(OpITE)
1290 default:
1291 abort();
1292 #undef X
1293 }
1294 text += ":";
1295 for (auto it : data.second)
1296 text += " " + my_int_to_string(it);
1297 return text;
1298 }
1299
1300 void ezSAT::printInternalState(FILE *f) const
1301 {
1302 fprintf(f, "--8<-- snip --8<--\n");
1303
1304 fprintf(f, "literalsCache:\n");
1305 for (auto &it : literalsCache)
1306 fprintf(f, " `%s' -> %d\n", it.first.c_str(), it.second);
1307
1308 fprintf(f, "literals:\n");
1309 for (int i = 0; i < int(literals.size()); i++)
1310 fprintf(f, " %d: `%s'\n", i+1, literals[i].c_str());
1311
1312 fprintf(f, "expressionsCache:\n");
1313 for (auto &it : expressionsCache)
1314 fprintf(f, " `%s' -> %d\n", expression2str(it.first).c_str(), it.second);
1315
1316 fprintf(f, "expressions:\n");
1317 for (int i = 0; i < int(expressions.size()); i++)
1318 fprintf(f, " %d: `%s'\n", -i-1, expression2str(expressions[i]).c_str());
1319
1320 fprintf(f, "cnfVariables (count=%d):\n", cnfVariableCount);
1321 for (int i = 0; i < int(cnfLiteralVariables.size()); i++)
1322 if (cnfLiteralVariables[i] != 0)
1323 fprintf(f, " literal %d -> %d (%s)\n", i+1, cnfLiteralVariables[i], to_string(i+1).c_str());
1324 for (int i = 0; i < int(cnfExpressionVariables.size()); i++)
1325 if (cnfExpressionVariables[i] != 0)
1326 fprintf(f, " expression %d -> %d (%s)\n", -i-1, cnfExpressionVariables[i], to_string(-i-1).c_str());
1327
1328 fprintf(f, "cnfClauses:\n");
1329 for (auto &i1 : cnfClauses) {
1330 for (auto &i2 : i1)
1331 fprintf(f, " %4d", i2);
1332 fprintf(f, "\n");
1333 }
1334 if (cnfConsumed)
1335 fprintf(f, " *** more clauses consumed via cnfConsume() ***\n");
1336
1337 fprintf(f, "--8<-- snap --8<--\n");
1338 }
1339
1340 int ezSAT::onehot(const std::vector<int> &vec, bool max_only)
1341 {
1342 // Mixed one-hot/binary encoding as described by Claessen in Sec. 4.2 of
1343 // "Successful SAT Encoding Techniques. Magnus Bjiirk. 25th July 2009".
1344 // http://jsat.ewi.tudelft.nl/addendum/Bjork_encoding.pdf
1345
1346 std::vector<int> formula;
1347
1348 // add at-leat-one constraint
1349 if (max_only == false)
1350 formula.push_back(expression(OpOr, vec));
1351
1352 // create binary vector
1353 int num_bits = ceil(log2(vec.size()));
1354 std::vector<int> bits;
1355 for (int k = 0; k < num_bits; k++)
1356 bits.push_back(literal());
1357
1358 // add at-most-one clauses using binary encoding
1359 for (size_t i = 0; i < vec.size(); i++)
1360 for (int k = 0; k < num_bits; k++) {
1361 std::vector<int> clause;
1362 clause.push_back(NOT(vec[i]));
1363 clause.push_back((i & (1 << k)) != 0 ? bits[k] : NOT(bits[k]));
1364 formula.push_back(expression(OpOr, clause));
1365 }
1366
1367 return expression(OpAnd, formula);
1368 }
1369
1370 int ezSAT::manyhot(const std::vector<int> &vec, int min_hot, int max_hot)
1371 {
1372 // many-hot encoding using a simple sorting network
1373
1374 if (max_hot < 0)
1375 max_hot = min_hot;
1376
1377 std::vector<int> formula;
1378 int M = max_hot+1, N = vec.size();
1379 std::map<std::pair<int,int>, int> x;
1380
1381 for (int i = -1; i < N; i++)
1382 for (int j = -1; j < M; j++)
1383 x[std::pair<int,int>(i,j)] = j < 0 ? CONST_TRUE : i < 0 ? CONST_FALSE : literal();
1384
1385 for (int i = 0; i < N; i++)
1386 for (int j = 0; j < M; j++) {
1387 formula.push_back(OR(NOT(vec[i]), x[std::pair<int,int>(i-1,j-1)], NOT(x[std::pair<int,int>(i,j)])));
1388 formula.push_back(OR(NOT(vec[i]), NOT(x[std::pair<int,int>(i-1,j-1)]), x[std::pair<int,int>(i,j)]));
1389 formula.push_back(OR(vec[i], x[std::pair<int,int>(i-1,j)], NOT(x[std::pair<int,int>(i,j)])));
1390 formula.push_back(OR(vec[i], NOT(x[std::pair<int,int>(i-1,j)]), x[std::pair<int,int>(i,j)]));
1391 #if 0
1392 // explicit resolution clauses -- in tests it was better to let the sat solver figure those out
1393 formula.push_back(OR(NOT(x[std::pair<int,int>(i-1,j-1)]), NOT(x[std::pair<int,int>(i-1,j)]), x[std::pair<int,int>(i,j)]));
1394 formula.push_back(OR(x[std::pair<int,int>(i-1,j-1)], x[std::pair<int,int>(i-1,j)], NOT(x[std::pair<int,int>(i,j)])));
1395 #endif
1396 }
1397
1398 for (int j = 0; j < M; j++) {
1399 if (j+1 <= min_hot)
1400 formula.push_back(x[std::pair<int,int>(N-1,j)]);
1401 else if (j+1 > max_hot)
1402 formula.push_back(NOT(x[std::pair<int,int>(N-1,j)]));
1403 }
1404
1405 return expression(OpAnd, formula);
1406 }
1407
1408 int ezSAT::ordered(const std::vector<int> &vec1, const std::vector<int> &vec2, bool allow_equal)
1409 {
1410 std::vector<int> formula;
1411 int last_x = CONST_FALSE;
1412
1413 assert(vec1.size() == vec2.size());
1414 for (size_t i = 0; i < vec1.size(); i++)
1415 {
1416 int a = vec1[i], b = vec2[i];
1417 formula.push_back(OR(NOT(a), b, last_x));
1418
1419 int next_x = i+1 < vec1.size() ? literal() : allow_equal ? CONST_FALSE : CONST_TRUE;
1420 formula.push_back(OR(a, b, last_x, NOT(next_x)));
1421 formula.push_back(OR(NOT(a), NOT(b), last_x, NOT(next_x)));
1422 last_x = next_x;
1423 }
1424
1425 return expression(OpAnd, formula);
1426 }
1427