2 * ezSAT -- A simple and easy to use CNF generator for SAT solvers
4 * Copyright (C) 2013 Claire Xenia Wolf <claire@yosyshq.com>
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.
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.
20 #include "ezminisat.h"
31 uint32_t operator()() {
32 uint32_t t
= x
^ (x
<< 11);
34 w
^= (w
>> 19) ^ t
^ (t
>> 8);
39 bool test(ezSAT
&sat
, int assumption
= 0)
41 std::vector
<int> modelExpressions
;
42 std::vector
<bool> modelValues
;
44 for (int id
= 1; id
<= sat
.numLiterals(); id
++)
46 modelExpressions
.push_back(id
);
48 if (sat
.solve(modelExpressions
, modelValues
, assumption
)) {
49 printf("satisfiable:");
50 for (int i
= 0; i
< int(modelExpressions
.size()); i
++)
51 printf(" %s=%d", sat
.to_string(modelExpressions
[i
]).c_str(), int(modelValues
[i
]));
55 printf("not satisfiable.\n\n");
60 // ------------------------------------------------------------------------------------------------------------
64 printf("==== %s ====\n\n", __PRETTY_FUNCTION__
);
67 sat
.non_incremental();
68 sat
.assume(sat
.OR("A", "B"));
69 sat
.assume(sat
.NOT(sat
.AND("A", "B")));
73 // ------------------------------------------------------------------------------------------------------------
75 void test_xorshift32_try(ezSAT
&sat
, uint32_t input_pattern
)
77 uint32_t output_pattern
= input_pattern
;
78 output_pattern
^= output_pattern
<< 13;
79 output_pattern
^= output_pattern
>> 17;
80 output_pattern
^= output_pattern
<< 5;
82 std::vector
<int> modelExpressions
;
83 std::vector
<int> forwardAssumptions
, backwardAssumptions
;
84 std::vector
<bool> forwardModel
, backwardModel
;
86 sat
.vec_append(modelExpressions
, sat
.vec_var("i", 32));
87 sat
.vec_append(modelExpressions
, sat
.vec_var("o", 32));
89 sat
.vec_append_unsigned(forwardAssumptions
, sat
.vec_var("i", 32), input_pattern
);
90 sat
.vec_append_unsigned(backwardAssumptions
, sat
.vec_var("o", 32), output_pattern
);
92 if (!sat
.solve(modelExpressions
, backwardModel
, backwardAssumptions
)) {
93 printf("backward solving failed!\n");
97 if (!sat
.solve(modelExpressions
, forwardModel
, forwardAssumptions
)) {
98 printf("forward solving failed!\n");
102 printf("xorshift32 test with input pattern 0x%08x:\n", input_pattern
);
104 printf("forward solution: input=0x%08x output=0x%08x\n",
105 (unsigned int)sat
.vec_model_get_unsigned(modelExpressions
, forwardModel
, sat
.vec_var("i", 32)),
106 (unsigned int)sat
.vec_model_get_unsigned(modelExpressions
, forwardModel
, sat
.vec_var("o", 32)));
108 printf("backward solution: input=0x%08x output=0x%08x\n",
109 (unsigned int)sat
.vec_model_get_unsigned(modelExpressions
, backwardModel
, sat
.vec_var("i", 32)),
110 (unsigned int)sat
.vec_model_get_unsigned(modelExpressions
, backwardModel
, sat
.vec_var("o", 32)));
112 if (forwardModel
!= backwardModel
) {
113 printf("forward and backward results are inconsistend!\n");
117 printf("passed.\n\n");
120 void test_xorshift32()
122 printf("==== %s ====\n\n", __PRETTY_FUNCTION__
);
129 std::vector
<int> bits
= sat
.vec_var("i", 32);
131 bits
= sat
.vec_xor(bits
, sat
.vec_shl(bits
, 13));
132 bits
= sat
.vec_xor(bits
, sat
.vec_shr(bits
, 17));
133 bits
= sat
.vec_xor(bits
, sat
.vec_shl(bits
, 5));
135 sat
.vec_set(bits
, sat
.vec_var("o", 32));
137 test_xorshift32_try(sat
, 0);
138 test_xorshift32_try(sat
, 314159265);
139 test_xorshift32_try(sat
, rng());
140 test_xorshift32_try(sat
, rng());
141 test_xorshift32_try(sat
, rng());
142 test_xorshift32_try(sat
, rng());
144 sat
.printDIMACS(stdout
, true);
148 // ------------------------------------------------------------------------------------------------------------
150 #define CHECK(_expr1, _expr2) check(#_expr1, _expr1, #_expr2, _expr2)
152 void check(const char *expr1_str
, bool expr1
, const char *expr2_str
, bool expr2
)
154 if (expr1
== expr2
) {
155 printf("[ %s ] == [ %s ] .. ok (%s == %s)\n", expr1_str
, expr2_str
, expr1
? "true" : "false", expr2
? "true" : "false");
157 printf("[ %s ] != [ %s ] .. ERROR (%s != %s)\n", expr1_str
, expr2_str
, expr1
? "true" : "false", expr2
? "true" : "false");
162 void test_signed(int8_t a
, int8_t b
, int8_t c
)
166 std::vector
<int> av
= sat
.vec_const_signed(a
, 8);
167 std::vector
<int> bv
= sat
.vec_const_signed(b
, 8);
168 std::vector
<int> cv
= sat
.vec_const_signed(c
, 8);
170 printf("Testing signed arithmetic using: a=%+d, b=%+d, c=%+d\n", int(a
), int(b
), int(c
));
172 CHECK(a
< b
+c
, sat
.solve(sat
.vec_lt_signed(av
, sat
.vec_add(bv
, cv
))));
173 CHECK(a
<= b
-c
, sat
.solve(sat
.vec_le_signed(av
, sat
.vec_sub(bv
, cv
))));
175 CHECK(a
> b
+c
, sat
.solve(sat
.vec_gt_signed(av
, sat
.vec_add(bv
, cv
))));
176 CHECK(a
>= b
-c
, sat
.solve(sat
.vec_ge_signed(av
, sat
.vec_sub(bv
, cv
))));
181 void test_unsigned(uint8_t a
, uint8_t b
, uint8_t c
)
186 b
^= c
, c
^= b
, b
^= c
;
188 std::vector
<int> av
= sat
.vec_const_unsigned(a
, 8);
189 std::vector
<int> bv
= sat
.vec_const_unsigned(b
, 8);
190 std::vector
<int> cv
= sat
.vec_const_unsigned(c
, 8);
192 printf("Testing unsigned arithmetic using: a=%d, b=%d, c=%d\n", int(a
), int(b
), int(c
));
194 CHECK(a
< b
+c
, sat
.solve(sat
.vec_lt_unsigned(av
, sat
.vec_add(bv
, cv
))));
195 CHECK(a
<= b
-c
, sat
.solve(sat
.vec_le_unsigned(av
, sat
.vec_sub(bv
, cv
))));
197 CHECK(a
> b
+c
, sat
.solve(sat
.vec_gt_unsigned(av
, sat
.vec_add(bv
, cv
))));
198 CHECK(a
>= b
-c
, sat
.solve(sat
.vec_ge_unsigned(av
, sat
.vec_sub(bv
, cv
))));
203 void test_count(uint32_t x
)
208 for (int i
= 0; i
< 32; i
++)
209 if (((x
>> i
) & 1) != 0)
212 printf("Testing bit counting using x=0x%08x (%d set bits) .. ", x
, count
);
214 std::vector
<int> v
= sat
.vec_const_unsigned(x
, 32);
216 std::vector
<int> cv6
= sat
.vec_const_unsigned(count
, 6);
217 std::vector
<int> cv4
= sat
.vec_const_unsigned(count
<= 15 ? count
: 15, 4);
219 if (cv6
!= sat
.vec_count(v
, 6, false)) {
220 fprintf(stderr
, "FAILED 6bit-no-clipping test!\n");
224 if (cv4
!= sat
.vec_count(v
, 4, true)) {
225 fprintf(stderr
, "FAILED 4bit-clipping test!\n");
234 printf("==== %s ====\n\n", __PRETTY_FUNCTION__
);
238 for (int i
= 0; i
< 100; i
++)
239 test_signed(rng() % 19 - 10, rng() % 19 - 10, rng() % 19 - 10);
241 for (int i
= 0; i
< 100; i
++)
242 test_unsigned(rng() % 10, rng() % 10, rng() % 10);
244 test_count(0x00000000);
245 test_count(0xffffffff);
246 for (int i
= 0; i
< 30; i
++)
252 // ------------------------------------------------------------------------------------------------------------
256 printf("==== %s ====\n\n", __PRETTY_FUNCTION__
);
259 int a
= ez
.frozen_literal("a");
260 int b
= ez
.frozen_literal("b");
261 int c
= ez
.frozen_literal("c");
262 int d
= ez
.frozen_literal("d");
264 std::vector
<int> abcd
;
270 ez
.assume(ez
.onehot(abcd
));
272 int solution_counter
= 0;
275 std::vector
<bool> modelValues
;
276 bool ok
= ez
.solve(abcd
, modelValues
);
281 printf("Solution: %d %d %d %d\n", int(modelValues
[0]), int(modelValues
[1]), int(modelValues
[2]), int(modelValues
[3]));
284 std::vector
<int> sol
;
285 for (int i
= 0; i
< 4; i
++) {
288 sol
.push_back(modelValues
[i
] ? abcd
[i
] : ez
.NOT(abcd
[i
]));
290 ez
.assume(ez
.NOT(ez
.expression(ezSAT::OpAnd
, sol
)));
292 if (count_hot
!= 1) {
293 fprintf(stderr
, "Wrong number of hot bits!\n");
300 if (solution_counter
!= 4) {
301 fprintf(stderr
, "Wrong number of one-hot solutions!\n");
310 printf("==== %s ====\n\n", __PRETTY_FUNCTION__
);
313 int a
= ez
.frozen_literal("a");
314 int b
= ez
.frozen_literal("b");
315 int c
= ez
.frozen_literal("c");
316 int d
= ez
.frozen_literal("d");
318 std::vector
<int> abcd
;
324 ez
.assume(ez
.manyhot(abcd
, 1, 2));
326 int solution_counter
= 0;
329 std::vector
<bool> modelValues
;
330 bool ok
= ez
.solve(abcd
, modelValues
);
335 printf("Solution: %d %d %d %d\n", int(modelValues
[0]), int(modelValues
[1]), int(modelValues
[2]), int(modelValues
[3]));
338 std::vector
<int> sol
;
339 for (int i
= 0; i
< 4; i
++) {
342 sol
.push_back(modelValues
[i
] ? abcd
[i
] : ez
.NOT(abcd
[i
]));
344 ez
.assume(ez
.NOT(ez
.expression(ezSAT::OpAnd
, sol
)));
346 if (count_hot
!= 1 && count_hot
!= 2) {
347 fprintf(stderr
, "Wrong number of hot bits!\n");
354 if (solution_counter
!= 4 + 4*3/2) {
355 fprintf(stderr
, "Wrong number of one-hot solutions!\n");
364 printf("==== %s ====\n\n", __PRETTY_FUNCTION__
);
367 int a
= ez
.frozen_literal("a");
368 int b
= ez
.frozen_literal("b");
369 int c
= ez
.frozen_literal("c");
371 int x
= ez
.frozen_literal("x");
372 int y
= ez
.frozen_literal("y");
373 int z
= ez
.frozen_literal("z");
375 std::vector
<int> abc
;
380 std::vector
<int> xyz
;
385 ez
.assume(ez
.ordered(abc
, xyz
));
387 int solution_counter
= 0;
391 std::vector
<int> modelVariables
;
392 std::vector
<bool> modelValues
;
394 modelVariables
.push_back(a
);
395 modelVariables
.push_back(b
);
396 modelVariables
.push_back(c
);
398 modelVariables
.push_back(x
);
399 modelVariables
.push_back(y
);
400 modelVariables
.push_back(z
);
402 bool ok
= ez
.solve(modelVariables
, modelValues
);
407 printf("Solution: %d %d %d | %d %d %d\n",
408 int(modelValues
[0]), int(modelValues
[1]), int(modelValues
[2]),
409 int(modelValues
[3]), int(modelValues
[4]), int(modelValues
[5]));
411 std::vector
<int> sol
;
412 for (size_t i
= 0; i
< modelVariables
.size(); i
++)
413 sol
.push_back(modelValues
[i
] ? modelVariables
[i
] : ez
.NOT(modelVariables
[i
]));
414 ez
.assume(ez
.NOT(ez
.expression(ezSAT::OpAnd
, sol
)));
419 if (solution_counter
!= 8+7+6+5+4+3+2+1) {
420 fprintf(stderr
, "Wrong number of solutions!\n");
427 // ------------------------------------------------------------------------------------------------------------
438 printf("Passed all tests.\n\n");