ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
SolverTypes.h
Go to the documentation of this file.
1/***********************************************************************************[SolverTypes.h]
2Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
3Copyright (c) 2007-2010, Niklas Sorensson
4
5Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6associated documentation files (the "Software"), to deal in the Software without restriction,
7including without limitation the rights to use, copy, modify, merge, publish, distribute,
8sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
9furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in all copies or
12substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
15NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
17DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
18OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19**************************************************************************************************/
20
21
22#ifndef Minisat_SolverTypes_h
23#define Minisat_SolverTypes_h
24
25#include <assert.h>
26
27#include "sat/bsat2/IntTypes.h"
28#include "sat/bsat2/Alg.h"
29#include "sat/bsat2/Vec.h"
30#include "sat/bsat2/Map.h"
31#include "sat/bsat2/Alloc.h"
32
34
35namespace Minisat {
36
37//=================================================================================================
38// Variables, literals, lifted booleans, clauses:
39
40
41// NOTE! Variables are just integers. No abstraction here. They should be chosen from 0..N,
42// so that they can be used as array indices.
43
44typedef int Var;
45#define var_Undef (-1)
46
47
48struct Lit {
49 int x;
50
51 // Use this as a constructor:
52 friend Lit mkLit(Var var, bool sign);
53
54 bool operator == (Lit p) const { return x == p.x; }
55 bool operator != (Lit p) const { return x != p.x; }
56 bool operator < (Lit p) const { return x < p.x; } // '<' makes p, ~p adjacent in the ordering.
57};
58
59
60inline Lit mkLit (Var var, bool sign = false) { Lit p; p.x = var + var + (int)sign; return p; }
61inline Lit operator ~(Lit p) { Lit q; q.x = p.x ^ 1; return q; }
62inline Lit operator ^(Lit p, bool b) { Lit q; q.x = p.x ^ (unsigned int)b; return q; }
63inline bool sign (Lit p) { return p.x & 1; }
64inline int var (Lit p) { return p.x >> 1; }
65
66// Mapping Literals to and from compact integers suitable for array indexing:
67inline int toInt (Var v) { return v; }
68inline int toInt (Lit p) { return p.x; }
69inline Lit toLit (int i) { Lit p; p.x = i; return p; }
70
71//const Lit lit_Undef = mkLit(var_Undef, false); // }- Useful special constants.
72//const Lit lit_Error = mkLit(var_Undef, true ); // }
73
74const Lit lit_Undef = { -2 }; // }- Useful special constants.
75const Lit lit_Error = { -1 }; // }
76
77
78//=================================================================================================
79// Lifted booleans:
80//
81// NOTE: this implementation is optimized for the case when comparisons between values are mostly
82// between one variable and one constant. Some care had to be taken to make sure that gcc
83// does enough constant propagation to produce sensible code, and this appears to be somewhat
84// fragile unfortunately.
85
86#define l_True (lbool((uint8_t)0)) // gcc does not do constant propagation if these are real constants.
87#define l_False (lbool((uint8_t)1))
88#define l_Undef (lbool((uint8_t)2))
89
90class lbool {
91 uint8_t value;
92
93public:
94 explicit lbool(uint8_t v) : value(v) { }
95
96 lbool() : value(0) { }
97 explicit lbool(bool x) : value(!x) { }
98
99 bool operator == (lbool b) const { return ((b.value&2) & (value&2)) | (!(b.value&2)&(value == b.value)); }
100 bool operator != (lbool b) const { return !(*this == b); }
101 lbool operator ^ (bool b) const { return lbool((uint8_t)(value^(uint8_t)b)); }
102
104 uint8_t sel = (this->value << 1) | (b.value << 3);
105 uint8_t v = (0xF7F755F4 >> sel) & 3;
106 return lbool(v); }
107
109 uint8_t sel = (this->value << 1) | (b.value << 3);
110 uint8_t v = (0xFCFCF400 >> sel) & 3;
111 return lbool(v); }
112
113 friend int toInt (lbool l);
114 friend lbool toLbool(int v);
115};
116inline int toInt (lbool l) { return l.value; }
117inline lbool toLbool(int v) { return lbool((uint8_t)v); }
118
119//=================================================================================================
120// Clause -- a simple class for representing a clause:
121
122class Clause;
124
125class Clause {
126 struct {
127 unsigned mark : 2;
128 unsigned learnt : 1;
129 unsigned has_extra : 1;
130 unsigned reloced : 1;
131 unsigned size : 27; } header;
132 union { Lit lit; float act; uint32_t abs; CRef rel; } data[0];
133
134 friend class ClauseAllocator;
135
136 // NOTE: This constructor cannot be used directly (doesn't allocate enough memory).
137 template<class V>
138 Clause(const V& ps, bool use_extra, bool learnt) {
139 header.mark = 0;
140 header.learnt = learnt;
141 header.has_extra = use_extra;
142 header.reloced = 0;
143 header.size = ps.size();
144
145 for (int i = 0; i < ps.size(); i++)
146 data[i].lit = ps[i];
147
148 if (header.has_extra){
149 if (header.learnt)
150 data[header.size].act = 0;
151 else
152 calcAbstraction(); }
153 }
154
155public:
157 assert(header.has_extra);
159 for (int i = 0; i < size(); i++)
160 abstraction |= 1 << (var(data[i].lit) & 31);
161 data[header.size].abs = abstraction; }
162
163
164 int size () const { return header.size; }
165 void shrink (int i) { assert(i <= size()); if (header.has_extra) data[header.size-i] = data[header.size]; header.size -= i; }
166 void pop () { shrink(1); }
167 bool learnt () const { return header.learnt; }
168 bool has_extra () const { return header.has_extra; }
169 uint32_t mark () const { return header.mark; }
170 void mark (uint32_t m) { header.mark = m; }
171 const Lit& last () const { return data[header.size-1].lit; }
172
173 bool reloced () const { return header.reloced; }
174 CRef relocation () const { return data[0].rel; }
175 void relocate (CRef c) { header.reloced = 1; data[0].rel = c; }
176
177 // NOTE: somewhat unsafe to change the clause in-place! Must manually call 'calcAbstraction' afterwards for
178 // subsumption operations to behave correctly.
179 Lit& operator [] (int i) { return data[i].lit; }
180 Lit operator [] (int i) const { return data[i].lit; }
181 operator const Lit* (void) const { return (Lit*)data; }
182
183 float& activity () { assert(header.has_extra); return data[header.size].act; }
184 uint32_t abstraction () const { assert(header.has_extra); return data[header.size].abs; }
185
186 Lit subsumes (const Clause& other) const;
187 void strengthen (Lit p);
188};
189
190
191//=================================================================================================
192// ClauseAllocator -- a simple class for allocating memory for clauses:
193
194
196class ClauseAllocator : public RegionAllocator<uint32_t>
197{
198 static int clauseWord32Size(int size, bool has_extra){
199 return (sizeof(Clause) + (sizeof(Lit) * (size + (int)has_extra))) / sizeof(uint32_t); }
200 public:
202
205
209
210 template<class Lits>
211 CRef alloc(const Lits& ps, bool learnt = false)
212 {
213 assert(sizeof(Lit) == sizeof(uint32_t));
214 assert(sizeof(float) == sizeof(uint32_t));
215 bool use_extra = learnt | extra_clause_field;
216
217 CRef cid = RegionAllocator<uint32_t>::alloc(clauseWord32Size(ps.size(), use_extra));
218 new (lea(cid)) Clause(ps, use_extra, learnt);
219
220 return cid;
221 }
222
223 // Deref, Load Effective Address (LEA), Inverse of LEA (AEL):
227 const Clause* lea (Ref r) const { return (Clause*)RegionAllocator<uint32_t>::lea(r); }
229
230 void _free(CRef cid)
231 {
232 Clause& c = operator[](cid);
233 RegionAllocator<uint32_t>::_free(clauseWord32Size(c.size(), c.has_extra()));
234 }
235
237 {
238 Clause& c = operator[](cr);
239
240 if (c.reloced()) { cr = c.relocation(); return; }
241
242 cr = to.alloc(c, c.learnt());
243 c.relocate(cr);
244
245 // Copy extra data-fields:
246 // (This could be cleaned-up. Generalize Clause-constructor to be applicable here instead?)
247 to[cr].mark(c.mark());
248 if (to[cr].learnt()) to[cr].activity() = c.activity();
249 else if (to[cr].has_extra()) to[cr].calcAbstraction();
250 }
251};
252
253
254//=================================================================================================
255// OccLists -- a class for maintaining occurence lists with lazy deletion:
256
257template<class Idx, class Vec, class Deleted>
259{
260 vec<Vec> occs;
261 vec<char> dirty;
262 vec<Idx> dirties;
263 Deleted deleted;
264
265 public:
266 OccLists(const Deleted& d) : deleted(d) {}
267
268 void init (const Idx& idx){ occs.growTo(toInt(idx)+1); dirty.growTo(toInt(idx)+1, 0); }
269 // Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; }
270 Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; }
271 Vec& lookup (const Idx& idx){ if (dirty[toInt(idx)]) clean(idx); return occs[toInt(idx)]; }
272
273 void cleanAll ();
274 void clean (const Idx& idx);
275 void smudge (const Idx& idx){
276 if (dirty[toInt(idx)] == 0){
277 dirty[toInt(idx)] = 1;
278 dirties.push(idx);
279 }
280 }
281
282 void clear(bool free = true){
283 occs .clear(free);
284 dirty .clear(free);
285 dirties.clear(free);
286 }
287};
288
289
290template<class Idx, class Vec, class Deleted>
292{
293 for (int i = 0; i < dirties.size(); i++)
294 // Dirties may contain duplicates so check here if a variable is already cleaned:
295 if (dirty[toInt(dirties[i])])
296 clean(dirties[i]);
297 dirties.clear();
298}
299
300
301template<class Idx, class Vec, class Deleted>
303{
304 Vec& vec = occs[toInt(idx)];
305 int i, j;
306 for (i = j = 0; i < vec.size(); i++)
307 if (!deleted(vec[i]))
308 vec[j++] = vec[i];
309 vec.shrink(i - j);
310 dirty[toInt(idx)] = 0;
311}
312
313
314//=================================================================================================
315// CMap -- a class for mapping clauses to values:
316
317
318template<class T>
319class CMap
320{
321 struct CRefHash {
322 uint32_t operator()(CRef cr) const { return (uint32_t)cr; } };
323
324 typedef Map<CRef, T, CRefHash> HashTable;
325 HashTable map;
326
327 public:
328 // Size-operations:
329 void clear () { map.clear(); }
330 int size () const { return map.elems(); }
331
332
333 // Insert/Remove/Test mapping:
334 void insert (CRef cr, const T& t){ map.insert(cr, t); }
335 void growTo (CRef cr, const T& t){ map.insert(cr, t); } // NOTE: for compatibility
336 void remove (CRef cr) { map.remove(cr); }
337 bool has (CRef cr, T& t) { return map.peek(cr, t); }
338
339 // Vector interface (the clause 'c' must already exist):
340 const T& operator [] (CRef cr) const { return map[cr]; }
341 T& operator [] (CRef cr) { return map[cr]; }
342
343 // Iteration (not transparent at all at the moment):
344 int bucket_count() const { return map.bucket_count(); }
345 const vec<typename HashTable::Pair>& bucket(int i) const { return map.bucket(i); }
346
347 // Move contents to other map:
348 void moveTo(CMap& other){ map.moveTo(other.map); }
349
350 // TMP debug:
351 void debug(){
352 printf(" --- size = %d, bucket_count = %d\n", size(), map.bucket_count()); }
353};
354
355
356/*_________________________________________________________________________________________________
357|
358| subsumes : (other : const Clause&) -> Lit
359|
360| Description:
361| Checks if clause subsumes 'other', and at the same time, if it can be used to simplify 'other'
362| by subsumption resolution.
363|
364| Result:
365| lit_Error - No subsumption or simplification
366| lit_Undef - Clause subsumes 'other'
367| p - The literal p can be deleted from 'other'
368|________________________________________________________________________________________________@*/
369inline Lit Clause::subsumes(const Clause& other) const
370{
371 //if (other.size() < size() || (extra.abst & ~other.extra.abst) != 0)
372 //if (other.size() < size() || (!learnt() && !other.learnt() && (extra.abst & ~other.extra.abst) != 0))
373 assert(!header.learnt); assert(!other.header.learnt);
374 assert(header.has_extra); assert(other.header.has_extra);
375 if (other.header.size < header.size || (data[header.size].abs & ~other.data[other.header.size].abs) != 0)
376 return lit_Error;
377
378 Lit ret = lit_Undef;
379 const Lit* c = (const Lit*)(*this);
380 const Lit* d = (const Lit*)other;
381
382 for (unsigned i = 0; i < header.size; i++) {
383 // search for c[i] or ~c[i]
384 for (unsigned j = 0; j < other.header.size; j++)
385 if (c[i] == d[j])
386 goto ok;
387 else if (ret == lit_Undef && c[i] == ~d[j]){
388 ret = c[i];
389 goto ok;
390 }
391
392 // did not find it
393 return lit_Error;
394 ok:;
395 }
396
397 return ret;
398}
399
401{
402 remove(*this, p);
404}
405
406//=================================================================================================
407}
408
410
411#endif
unsigned int uint32_t
Definition Fxch.h:32
ABC_NAMESPACE_HEADER_START typedef unsigned char uint8_t
Definition Fxch.h:31
#define ABC_NAMESPACE_CXX_HEADER_START
#define ABC_NAMESPACE_CXX_HEADER_END
int size() const
int bucket_count() const
void growTo(CRef cr, const T &t)
void insert(CRef cr, const T &t)
const vec< typename HashTable::Pair > & bucket(int i) const
void moveTo(CMap &other)
const T & operator[](CRef cr) const
void remove(CRef cr)
bool has(CRef cr, T &t)
Ref ael(const Clause *t)
Clause & operator[](Ref r)
const Clause * lea(Ref r) const
void moveTo(ClauseAllocator &to)
void reloc(CRef &cr, ClauseAllocator &to)
CRef alloc(const Lits &ps, bool learnt=false)
ClauseAllocator(uint32_t start_cap)
const Clause & operator[](Ref r) const
bool reloced() const
bool learnt() const
void strengthen(Lit p)
void mark(uint32_t m)
void relocate(CRef c)
int size() const
float & activity()
void shrink(int i)
friend class ClauseAllocator
unsigned has_extra
Lit & operator[](int i)
uint32_t abstraction() const
const Lit & last() const
uint32_t mark() const
void calcAbstraction()
Lit subsumes(const Clause &other) const
CRef relocation() const
bool has_extra() const
void init(const Idx &idx)
void clean(const Idx &idx)
OccLists(const Deleted &d)
void clear(bool free=true)
Vec & operator[](const Idx &idx)
Vec & lookup(const Idx &idx)
void smudge(const Idx &idx)
void _free(int size)
Definition Alloc.h:62
void moveTo(RegionAllocator &to)
Definition Alloc.h:73
Ref ael(const T *t)
Definition Alloc.h:70
RegionAllocator(uint32_t start_cap=1024 *1024)
Definition Alloc.h:50
Ref alloc(int size)
Definition Alloc.h:117
T & operator[](Ref r)
Definition Alloc.h:65
bool operator!=(lbool b) const
lbool(uint8_t v)
Definition SolverTypes.h:94
friend int toInt(lbool l)
lbool operator||(lbool b) const
lbool operator&&(lbool b) const
bool operator==(lbool b) const
Definition SolverTypes.h:99
lbool operator^(bool b) const
friend lbool toLbool(int v)
void shrink(int nelems)
Definition Vec.h:66
int size(void) const
Definition Vec.h:65
Cube * p
Definition exorList.c:222
Definition Alg.h:28
const CRef CRef_Undef
Lit operator~(Lit p)
Definition SolverTypes.h:61
int toInt(Var v)
Definition SolverTypes.h:67
Lit toLit(int i)
Definition SolverTypes.h:69
lbool toLbool(int v)
int var(Lit p)
Definition SolverTypes.h:64
RegionAllocator< uint32_t >::Ref CRef
Lit operator^(Lit p, bool b)
Definition SolverTypes.h:62
const Lit lit_Error
Definition SolverTypes.h:75
Lit mkLit(Var var, bool sign=false)
Definition SolverTypes.h:60
bool sign(Lit p)
Definition SolverTypes.h:63
const Lit lit_Undef
Definition SolverTypes.h:74
#define false
Definition place_base.h:29
signed char lbool
Definition satVec.h:135
bool operator<(Lit p) const
Definition SolverTypes.h:56
bool operator==(Lit p) const
Definition SolverTypes.h:54
friend Lit mkLit(Var var, bool sign)
Definition SolverTypes.h:60
bool operator!=(Lit p) const
Definition SolverTypes.h:55
#define assert(ex)
Definition util_old.h:213
VOID_HACK free()