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.
32 // each token (terminal or non-terminal) is represented by an integer number
35 // the number zero is not used as valid token number and is used to encode
36 // unused parameters for the functions.
38 // positive numbers are literals, with 1 = CONST_TRUE and 2 = CONST_FALSE;
40 // negative numbers are non-literal expressions. each expression is represented
41 // by an operator id and a list of expressions (literals or non-literals).
45 OpNot
, OpAnd
, OpOr
, OpXor
, OpIFF
, OpITE
48 static const int CONST_TRUE
;
49 static const int CONST_FALSE
;
53 bool flag_non_incremental
;
55 bool non_incremental_solve_used_up
;
57 std::map
<std::string
, int> literalsCache
;
58 std::vector
<std::string
> literals
;
60 std::map
<std::pair
<OpId
, std::vector
<int>>, int> expressionsCache
;
61 std::vector
<std::pair
<OpId
, std::vector
<int>>> expressions
;
64 int cnfVariableCount
, cnfClausesCount
;
65 std::vector
<int> cnfLiteralVariables
, cnfExpressionVariables
;
66 std::vector
<std::vector
<int>> cnfClauses
, cnfClausesBackup
;
68 void add_clause(const std::vector
<int> &args
);
69 void add_clause(const std::vector
<int> &args
, bool argsPolarity
, int a
= 0, int b
= 0, int c
= 0);
70 void add_clause(int a
, int b
= 0, int c
= 0);
72 int bind_cnf_not(const std::vector
<int> &args
);
73 int bind_cnf_and(const std::vector
<int> &args
);
74 int bind_cnf_or(const std::vector
<int> &args
);
77 void preSolverCallback();
81 bool solverTimoutStatus
;
86 unsigned int statehash
;
87 void addhash(unsigned int);
89 void keep_cnf() { flag_keep_cnf
= true; }
90 void non_incremental() { flag_non_incremental
= true; }
92 bool mode_keep_cnf() const { return flag_keep_cnf
; }
93 bool mode_non_incremental() const { return flag_non_incremental
; }
99 int literal(const std::string
&name
);
100 int frozen_literal();
101 int frozen_literal(const std::string
&name
);
102 int expression(OpId op
, int a
= 0, int b
= 0, int c
= 0, int d
= 0, int e
= 0, int f
= 0);
103 int expression(OpId op
, const std::vector
<int> &args
);
105 void lookup_literal(int id
, std::string
&name
) const;
106 const std::string
&lookup_literal(int id
) const;
108 void lookup_expression(int id
, OpId
&op
, std::vector
<int> &args
) const;
109 const std::vector
<int> &lookup_expression(int id
, OpId
&op
) const;
111 int parse_string(const std::string
&text
);
112 std::string
to_string(int id
) const;
114 int numLiterals() const { return literals
.size(); }
115 int numExpressions() const { return expressions
.size(); }
117 int eval(int id
, const std::vector
<int> &values
) const;
119 // SAT solver interface
120 // If you are planning on using the solver API (and not simply create a CNF) you must use a child class
121 // of ezSAT that actually implements a solver backend, such as ezMiniSAT (see ezminisat.h).
123 virtual bool solver(const std::vector
<int> &modelExpressions
, std::vector
<bool> &modelValues
, const std::vector
<int> &assumptions
);
125 bool solve(const std::vector
<int> &modelExpressions
, std::vector
<bool> &modelValues
, const std::vector
<int> &assumptions
) {
126 return solver(modelExpressions
, modelValues
, assumptions
);
129 bool solve(const std::vector
<int> &modelExpressions
, std::vector
<bool> &modelValues
, int a
= 0, int b
= 0, int c
= 0, int d
= 0, int e
= 0, int f
= 0) {
130 std::vector
<int> assumptions
;
131 if (a
!= 0) assumptions
.push_back(a
);
132 if (b
!= 0) assumptions
.push_back(b
);
133 if (c
!= 0) assumptions
.push_back(c
);
134 if (d
!= 0) assumptions
.push_back(d
);
135 if (e
!= 0) assumptions
.push_back(e
);
136 if (f
!= 0) assumptions
.push_back(f
);
137 return solver(modelExpressions
, modelValues
, assumptions
);
140 bool solve(int a
= 0, int b
= 0, int c
= 0, int d
= 0, int e
= 0, int f
= 0) {
141 std::vector
<int> assumptions
, modelExpressions
;
142 std::vector
<bool> modelValues
;
143 if (a
!= 0) assumptions
.push_back(a
);
144 if (b
!= 0) assumptions
.push_back(b
);
145 if (c
!= 0) assumptions
.push_back(c
);
146 if (d
!= 0) assumptions
.push_back(d
);
147 if (e
!= 0) assumptions
.push_back(e
);
148 if (f
!= 0) assumptions
.push_back(f
);
149 return solver(modelExpressions
, modelValues
, assumptions
);
152 void setSolverTimeout(int newTimeoutSeconds
) {
153 solverTimeout
= newTimeoutSeconds
;
156 bool getSolverTimoutStatus() {
157 return solverTimoutStatus
;
160 // manage CNF (usually only accessed by SAT solvers)
162 virtual void clear();
163 virtual void freeze(int id
);
164 virtual bool eliminated(int idx
);
166 void assume(int id
, int context_id
) { assume(OR(id
, NOT(context_id
))); }
167 int bind(int id
, bool auto_freeze
= true);
168 int bound(int id
) const;
170 int numCnfVariables() const { return cnfVariableCount
; }
171 int numCnfClauses() const { return cnfClausesCount
; }
172 const std::vector
<std::vector
<int>> &cnf() const { return cnfClauses
; }
175 void consumeCnf(std::vector
<std::vector
<int>> &cnf
);
177 // use this function to get the full CNF in keep_cnf mode
178 void getFullCnf(std::vector
<std::vector
<int>> &full_cnf
) const;
180 std::string
cnfLiteralInfo(int idx
) const;
182 // simple helpers for build expressions easily
187 _V(int id
) : id(id
) { }
188 _V(const char *name
) : id(0), name(name
) { }
189 _V(const std::string
&name
) : id(0), name(name
) { }
190 int get(ezSAT
*that
) {
193 return that
->frozen_literal(name
);
202 return expression(OpNot
, a
.get(this));
205 int AND(_V a
= 0, _V b
= 0, _V c
= 0, _V d
= 0, _V e
= 0, _V f
= 0) {
206 return expression(OpAnd
, a
.get(this), b
.get(this), c
.get(this), d
.get(this), e
.get(this), f
.get(this));
209 int OR(_V a
= 0, _V b
= 0, _V c
= 0, _V d
= 0, _V e
= 0, _V f
= 0) {
210 return expression(OpOr
, a
.get(this), b
.get(this), c
.get(this), d
.get(this), e
.get(this), f
.get(this));
213 int XOR(_V a
= 0, _V b
= 0, _V c
= 0, _V d
= 0, _V e
= 0, _V f
= 0) {
214 return expression(OpXor
, a
.get(this), b
.get(this), c
.get(this), d
.get(this), e
.get(this), f
.get(this));
217 int IFF(_V a
, _V b
= 0, _V c
= 0, _V d
= 0, _V e
= 0, _V f
= 0) {
218 return expression(OpIFF
, a
.get(this), b
.get(this), c
.get(this), d
.get(this), e
.get(this), f
.get(this));
221 int ITE(_V a
, _V b
, _V c
) {
222 return expression(OpITE
, a
.get(this), b
.get(this), c
.get(this));
225 void SET(_V a
, _V b
) {
226 assume(IFF(a
.get(this), b
.get(this)));
229 // simple helpers for building expressions with bit vectors
231 std::vector
<int> vec_const(const std::vector
<bool> &bits
);
232 std::vector
<int> vec_const_signed(int64_t value
, int numBits
);
233 std::vector
<int> vec_const_unsigned(uint64_t value
, int numBits
);
234 std::vector
<int> vec_var(int numBits
);
235 std::vector
<int> vec_var(std::string name
, int numBits
);
236 std::vector
<int> vec_cast(const std::vector
<int> &vec1
, int toBits
, bool signExtend
= false);
238 std::vector
<int> vec_not(const std::vector
<int> &vec1
);
239 std::vector
<int> vec_and(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
240 std::vector
<int> vec_or(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
241 std::vector
<int> vec_xor(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
243 std::vector
<int> vec_iff(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
244 std::vector
<int> vec_ite(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
, const std::vector
<int> &vec3
);
245 std::vector
<int> vec_ite(int sel
, const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
247 std::vector
<int> vec_count(const std::vector
<int> &vec
, int numBits
, bool clip
= true);
248 std::vector
<int> vec_add(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
249 std::vector
<int> vec_sub(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
250 std::vector
<int> vec_neg(const std::vector
<int> &vec
);
252 void vec_cmp(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
, int &carry
, int &overflow
, int &sign
, int &zero
);
254 int vec_lt_signed(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
255 int vec_le_signed(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
256 int vec_ge_signed(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
257 int vec_gt_signed(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
259 int vec_lt_unsigned(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
260 int vec_le_unsigned(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
261 int vec_ge_unsigned(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
262 int vec_gt_unsigned(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
264 int vec_eq(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
265 int vec_ne(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
267 std::vector
<int> vec_shl(const std::vector
<int> &vec1
, int shift
, bool signExtend
= false);
268 std::vector
<int> vec_srl(const std::vector
<int> &vec1
, int shift
);
270 std::vector
<int> vec_shr(const std::vector
<int> &vec1
, int shift
, bool signExtend
= false) { return vec_shl(vec1
, -shift
, signExtend
); }
271 std::vector
<int> vec_srr(const std::vector
<int> &vec1
, int shift
) { return vec_srl(vec1
, -shift
); }
273 std::vector
<int> vec_shift(const std::vector
<int> &vec1
, int shift
, int extend_left
, int extend_right
);
274 std::vector
<int> vec_shift_right(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
, bool vec2_signed
, int extend_left
, int extend_right
);
275 std::vector
<int> vec_shift_left(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
, bool vec2_signed
, int extend_left
, int extend_right
);
277 void vec_append(std::vector
<int> &vec
, const std::vector
<int> &vec1
) const;
278 void vec_append_signed(std::vector
<int> &vec
, const std::vector
<int> &vec1
, int64_t value
);
279 void vec_append_unsigned(std::vector
<int> &vec
, const std::vector
<int> &vec1
, uint64_t value
);
281 int64_t vec_model_get_signed(const std::vector
<int> &modelExpressions
, const std::vector
<bool> &modelValues
, const std::vector
<int> &vec1
) const;
282 uint64_t vec_model_get_unsigned(const std::vector
<int> &modelExpressions
, const std::vector
<bool> &modelValues
, const std::vector
<int> &vec1
) const;
284 int vec_reduce_and(const std::vector
<int> &vec1
);
285 int vec_reduce_or(const std::vector
<int> &vec1
);
287 void vec_set(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
);
288 void vec_set_signed(const std::vector
<int> &vec1
, int64_t value
);
289 void vec_set_unsigned(const std::vector
<int> &vec1
, uint64_t value
);
291 // helpers for generating ezSATbit and ezSATvec objects
293 struct ezSATbit
bit(_V a
);
294 struct ezSATvec
vec(const std::vector
<int> &vec
);
296 // printing CNF and internal state
298 void printDIMACS(FILE *f
, bool verbose
= false) const;
299 void printInternalState(FILE *f
) const;
301 // more sophisticated constraints (designed to be used directly with assume(..))
303 int onehot(const std::vector
<int> &vec
, bool max_only
= false);
304 int manyhot(const std::vector
<int> &vec
, int min_hot
, int max_hot
= -1);
305 int ordered(const std::vector
<int> &vec1
, const std::vector
<int> &vec2
, bool allow_equal
= true);
308 // helper classes for using operator overloading when generating complex expressions
315 ezSATbit(ezSAT
&sat
, ezSAT::_V a
) : sat(sat
), id(sat
.VAR(a
)) { }
317 ezSATbit
operator ~() { return ezSATbit(sat
, sat
.NOT(id
)); }
318 ezSATbit
operator &(const ezSATbit
&other
) { return ezSATbit(sat
, sat
.AND(id
, other
.id
)); }
319 ezSATbit
operator |(const ezSATbit
&other
) { return ezSATbit(sat
, sat
.OR(id
, other
.id
)); }
320 ezSATbit
operator ^(const ezSATbit
&other
) { return ezSATbit(sat
, sat
.XOR(id
, other
.id
)); }
321 ezSATbit
operator ==(const ezSATbit
&other
) { return ezSATbit(sat
, sat
.IFF(id
, other
.id
)); }
322 ezSATbit
operator !=(const ezSATbit
&other
) { return ezSATbit(sat
, sat
.NOT(sat
.IFF(id
, other
.id
))); }
324 operator int() const { return id
; }
325 operator ezSAT::_V() const { return ezSAT::_V(id
); }
326 operator std::vector
<int>() const { return std::vector
<int>(1, id
); }
332 std::vector
<int> vec
;
334 ezSATvec(ezSAT
&sat
, const std::vector
<int> &vec
) : sat(sat
), vec(vec
) { }
336 ezSATvec
operator ~() { return ezSATvec(sat
, sat
.vec_not(vec
)); }
337 ezSATvec
operator -() { return ezSATvec(sat
, sat
.vec_neg(vec
)); }
339 ezSATvec
operator &(const ezSATvec
&other
) { return ezSATvec(sat
, sat
.vec_and(vec
, other
.vec
)); }
340 ezSATvec
operator |(const ezSATvec
&other
) { return ezSATvec(sat
, sat
.vec_or(vec
, other
.vec
)); }
341 ezSATvec
operator ^(const ezSATvec
&other
) { return ezSATvec(sat
, sat
.vec_xor(vec
, other
.vec
)); }
343 ezSATvec
operator +(const ezSATvec
&other
) { return ezSATvec(sat
, sat
.vec_add(vec
, other
.vec
)); }
344 ezSATvec
operator -(const ezSATvec
&other
) { return ezSATvec(sat
, sat
.vec_sub(vec
, other
.vec
)); }
346 ezSATbit
operator < (const ezSATvec
&other
) { return ezSATbit(sat
, sat
.vec_lt_unsigned(vec
, other
.vec
)); }
347 ezSATbit
operator <=(const ezSATvec
&other
) { return ezSATbit(sat
, sat
.vec_le_unsigned(vec
, other
.vec
)); }
348 ezSATbit
operator ==(const ezSATvec
&other
) { return ezSATbit(sat
, sat
.vec_eq(vec
, other
.vec
)); }
349 ezSATbit
operator !=(const ezSATvec
&other
) { return ezSATbit(sat
, sat
.vec_ne(vec
, other
.vec
)); }
350 ezSATbit
operator >=(const ezSATvec
&other
) { return ezSATbit(sat
, sat
.vec_ge_unsigned(vec
, other
.vec
)); }
351 ezSATbit
operator > (const ezSATvec
&other
) { return ezSATbit(sat
, sat
.vec_gt_unsigned(vec
, other
.vec
)); }
353 ezSATvec
operator <<(int shift
) { return ezSATvec(sat
, sat
.vec_shl(vec
, shift
)); }
354 ezSATvec
operator >>(int shift
) { return ezSATvec(sat
, sat
.vec_shr(vec
, shift
)); }
356 operator std::vector
<int>() const { return vec
; }