Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

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#pragma once
22
23#include <assert.h>
24
30
31namespace Minisat {
32namespace Internal {
33
34//=================================================================================================
35// Variables, literals, lifted booleans, clauses:
36
37
38// NOTE! Variables are just integers. No abstraction here. They should be chosen from 0..N,
39// so that they can be used as array indices.
40
41using Var = int;
42#define var_Undef (-1)
43
44
45struct Lit {
46 int x;
47
48 // Use this as a constructor:
49 friend Lit mkLit(Var var, bool sign);
50
51 bool operator == (Lit p) const { return x == p.x; }
52 bool operator != (Lit p) const { return x != p.x; }
53 bool operator < (Lit p) const { return x < p.x; } // '<' makes p, ~p adjacent in the ordering.
54};
55
56
57inline Lit mkLit (Var var, bool sign = false) { Lit p; p.x = var + var + (int)sign; return p; }
58inline Lit operator ~(Lit p) { Lit q; q.x = p.x ^ 1; return q; }
59inline Lit operator ^(Lit p, bool b) { Lit q; q.x = p.x ^ (unsigned int)b; return q; }
60inline bool sign (Lit p) { return p.x & 1; }
61inline int var (Lit p) { return p.x >> 1; }
62
63// Mapping Literals to and from compact integers suitable for array indexing:
64inline int toInt (Var v) { return v; }
65inline int toInt (Lit p) { return p.x; }
66inline Lit toLit (int i) { Lit p; p.x = i; return p; }
67
68#if 0
69const Lit lit_Undef = mkLit(var_Undef, false); // }- Useful special constants.
70const Lit lit_Error = mkLit(var_Undef, true ); // }
71#endif
72
73const Lit lit_Undef = { -2 }; // }- Useful special constants.
74const Lit lit_Error = { -1 }; // }
75
76
77//=================================================================================================
78// Lifted booleans:
79//
80// NOTE: this implementation is optimized for the case when comparisons between values are mostly
81// between one variable and one constant. Some care had to be taken to make sure that gcc
82// does enough constant propagation to produce sensible code, and this appears to be somewhat
83// fragile unfortunately.
84
85#define l_True (lbool((uint8_t)0)) // gcc does not do constant propagation if these are real constants.
86#define l_False (lbool((uint8_t)1))
87#define l_Undef (lbool((uint8_t)2))
88#define l_Timeout (lbool((uint8_t)9)) // HEDTKE
89
90class lbool {
92
93public:
94 explicit lbool(uint8_t v) : value(v) { }
95
96 lbool() : value(0) { }
97 explicit lbool(bool x) : value(!x) { }
98
99#if 0
100 bool operator == (lbool b) const { return ( (b.value & 2) & (value & 2) ) | (!(b.value & 2) & (value == b.value)); }
101#endif
102 bool operator == (lbool b) const {
103 return (( (b.value & 2) & (value & 2) ) | (((b.value & 2) == 0) & (value == b.value))) != 0;
104 }
105
106 bool operator != (lbool b) const { return !(*this == b); }
107 lbool operator ^ (bool b) const { return lbool((uint8_t)(value^(uint8_t)b)); }
108
110 uint8_t sel = (this->value << 1) | (b.value << 3);
111 uint8_t v = (0xF7F755F4 >> sel) & 3;
112 return lbool(v); }
113
115 uint8_t sel = (this->value << 1) | (b.value << 3);
116 uint8_t v = (0xFCFCF400 >> sel) & 3;
117 return lbool(v); }
118
119 friend int toInt (lbool l);
120 friend lbool toLbool(int v);
121};
122inline int toInt (lbool l) { return l.value; }
123inline lbool toLbool(int v) { return lbool((uint8_t)v); }
124
125//=================================================================================================
126// Clause -- a simple class for representing a clause:
127
128class Clause;
130
131#ifdef _MSC_VER
132#pragma warning ( push )
133#pragma warning ( disable : 4200 )
134#endif
135
136class Clause {
137 struct {
138 unsigned mark : 2;
139 unsigned learnt : 1;
140 unsigned has_extra : 1;
141 unsigned reloced : 1;
142 unsigned size : 27; } header;
143 union { Lit lit; float act; uint32_t abs; CRef rel; } data[0];
144
145 friend class ClauseAllocator;
146
147 // NOTE: This constructor cannot be used directly (doesn't allocate enough memory).
148 template<class V>
149 Clause(const V& ps, bool use_extra, bool learnt) {
150 header.mark = 0;
151 header.learnt = learnt;
152 header.has_extra = use_extra;
153 header.reloced = 0;
154 header.size = ps.size();
155
156 for (int i = 0; i < ps.size(); i++)
157 data[i].lit = ps[i];
158
159 if (header.has_extra){
160 if (header.learnt)
161 data[header.size].act = 0;
162 else
163 calcAbstraction(); }
164 }
165
166public:
168 assert(header.has_extra);
170 for (int i = 0; i < size(); i++)
171 abstraction |= 1 << (var(data[i].lit) & 31);
172 data[header.size].abs = abstraction; }
173
174
175 int size () const { return header.size; }
176 void shrink (int i) { assert(i <= size()); if (header.has_extra) data[header.size-i] = data[header.size]; header.size -= i; }
177 void pop () { shrink(1); }
178 bool learnt () const { return header.learnt; }
179 bool has_extra () const { return header.has_extra; }
180 uint32_t mark () const { return header.mark; }
181 void mark (uint32_t m) { header.mark = m; }
182 const Lit& last () const { return data[header.size-1].lit; }
183
184 bool reloced () const { return header.reloced; }
185 CRef relocation () const { return data[0].rel; }
186 void relocate (CRef c) { header.reloced = 1; data[0].rel = c; }
187
188 // NOTE: somewhat unsafe to change the clause in-place! Must manually call 'calcAbstraction' afterwards for
189 // subsumption operations to behave correctly.
190 Lit& operator [] (int i) { return data[i].lit; }
191 Lit operator [] (int i) const { return data[i].lit; }
192 operator const Lit* (void) const { return reinterpret_cast<const Lit*>(data); }
193
194 float& activity () { assert(header.has_extra); return data[header.size].act; }
195 uint32_t abstraction () const { assert(header.has_extra); return data[header.size].abs; }
196
197 Lit subsumes (const Clause& other) const;
198 void strengthen (Lit p);
199};
200
201#ifdef _MSC_VER
202#pragma warning ( pop )
203#endif
204
205
206//=================================================================================================
207// ClauseAllocator -- a simple class for allocating memory for clauses:
208
209
211class ClauseAllocator : public RegionAllocator<uint32_t>
212{
213 static int clauseWord32Size(int size, bool has_extra){
214 return (sizeof(Clause) + (sizeof(Lit) * (size + (int)has_extra))) / sizeof(uint32_t); }
215 public:
217
220
224
225 template<class Lits>
226 CRef alloc(const Lits& ps, bool learnt = false)
227 {
228 assert(sizeof(Lit) == sizeof(uint32_t));
229 assert(sizeof(float) == sizeof(uint32_t));
230 bool use_extra = learnt | extra_clause_field;
231
233 new (lea(cid)) Clause(ps, use_extra, learnt);
234
235 return cid;
236 }
237
238 // Deref, Load Effective Address (LEA), Inverse of LEA (AEL):
241 Clause* lea (Ref r) { return reinterpret_cast<Clause*>(RegionAllocator<uint32_t>::lea(r)); }
242 const Clause* lea(Ref r) const { return reinterpret_cast<const Clause*>(RegionAllocator<uint32_t>::lea(r)); }
244
250
252 {
253 Clause& c = operator[](cr);
254
255 if (c.reloced()) { cr = c.relocation(); return; }
256
257 cr = to.alloc(c, c.learnt());
258 c.relocate(cr);
259
260 // Copy extra data-fields:
261 // (This could be cleaned-up. Generalize Clause-constructor to be applicable here instead?)
262 to[cr].mark(c.mark());
263 if (to[cr].learnt()) to[cr].activity() = c.activity();
264 else if (to[cr].has_extra()) to[cr].calcAbstraction();
265 }
266};
267
268
269//=================================================================================================
270// OccLists -- a class for maintaining occurence lists with lazy deletion:
271
272template<class Idx, class Vec, class Deleted>
274{
279
280 public:
281 OccLists(const Deleted& d) : deleted(d) {}
282
283 void init (const Idx& idx){ occs.growTo(toInt(idx)+1); dirty.growTo(toInt(idx)+1, 0); }
284#if 0
285 Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; }
286#endif
287 Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; }
288 Vec& lookup (const Idx& idx){ if (dirty[toInt(idx)]) clean(idx); return occs[toInt(idx)]; }
289
290 void cleanAll ();
291 void clean (const Idx& idx);
292 void smudge (const Idx& idx){
293 if (dirty[toInt(idx)] == 0){
294 dirty[toInt(idx)] = 1;
295 dirties.push(idx);
296 }
297 }
298
299 void clear(bool free = true){
300 occs .clear(free);
301 dirty .clear(free);
302 dirties.clear(free);
303 }
304};
305
306
307template<class Idx, class Vec, class Deleted>
309{
310 for (int i = 0; i < dirties.size(); i++)
311 // Dirties may contain duplicates so check here if a variable is already cleaned:
312 if (dirty[toInt(dirties[i])])
313 clean(dirties[i]);
314 dirties.clear();
315}
316
317
318template<class Idx, class Vec, class Deleted>
320{
321 Vec& vec = occs[toInt(idx)];
322 int i, j;
323 for (i = j = 0; i < vec.size(); i++)
324 if (!deleted(vec[i]))
325 vec[j++] = vec[i];
326 vec.shrink(i - j);
327 dirty[toInt(idx)] = 0;
328}
329
330
331//=================================================================================================
332// CMap -- a class for mapping clauses to values:
333
334
335template<class T>
336class CMap
337{
338 struct CRefHash {
339 uint32_t operator()(CRef cr) const { return (uint32_t)cr; } };
340
343
344 public:
345 // Size-operations:
346 void clear () { map.clear(); }
347 int size () const { return map.elems(); }
348
349
350 // Insert/Remove/Test mapping:
351 void insert (CRef cr, const T& t){ map.insert(cr, t); }
352 void growTo (CRef cr, const T& t){ map.insert(cr, t); } // NOTE: for compatibility
353 void remove (CRef cr) { map.remove(cr); }
354 bool has (CRef cr, T& t) { return map.peek(cr, t); }
355
356 // Vector interface (the clause 'c' must already exist):
357 const T& operator [] (CRef cr) const { return map[cr]; }
358 T& operator [] (CRef cr) { return map[cr]; }
359
360 // Iteration (not transparent at all at the moment):
361 int bucket_count() const { return map.bucket_count(); }
362 const vec<typename HashTable::Pair>& bucket(int i) const { return map.bucket(i); }
363
364 // Move contents to other map:
365 void moveTo(CMap& other){ map.moveTo(other.map); }
366
367 // TMP debug:
368 void debug(){
369 printf(" --- size = %d, bucket_count = %d\n", size(), map.bucket_count()); }
370};
371
372
373/*_________________________________________________________________________________________________
374|
375| subsumes : (other : const Clause&) -> Lit
376|
377| Description:
378| Checks if clause subsumes 'other', and at the same time, if it can be used to simplify 'other'
379| by subsumption resolution.
380|
381| Result:
382| lit_Error - No subsumption or simplification
383| lit_Undef - Clause subsumes 'other'
384| p - The literal p can be deleted from 'other'
385|________________________________________________________________________________________________@*/
386inline Lit Clause::subsumes(const Clause& other) const
387{
388#if 0
389 if (other.size() < size() || (extra.abst & ~other.extra.abst) != 0)
390 if (other.size() < size() || (!learnt() && !other.learnt() && (extra.abst & ~other.extra.abst) != 0))
391#endif
392 assert(!header.learnt); assert(!other.header.learnt);
393 assert(header.has_extra); assert(other.header.has_extra);
394 if (other.header.size < header.size || (data[header.size].abs & ~other.data[other.header.size].abs) != 0)
395 return lit_Error;
396
397 Lit ret = lit_Undef;
398 const Lit* c = static_cast<const Lit*>(*this);
399 const Lit* d = static_cast<const Lit*>(other);
400
401 for (unsigned i = 0; i < header.size; i++) {
402 // search for c[i] or ~c[i]
403 for (unsigned j = 0; j < other.header.size; j++)
404 if (c[i] == d[j])
405 goto ok;
406 else if (ret == lit_Undef && c[i] == ~d[j]){
407 ret = c[i];
408 goto ok;
409 }
410
411 // did not find it
412 return lit_Error;
413 ok:;
414 }
415
416 return ret;
417}
418
420{
421 remove(*this, p);
423}
424
425//=================================================================================================
426} // namespace Internal
427} // namespace Minisat
#define var_Undef
Definition SolverTypes.h:42
void moveTo(CMap &other)
bool has(CRef cr, T &t)
void insert(CRef cr, const T &t)
const vec< typename HashTable::Pair > & bucket(int i) const
void growTo(CRef cr, const T &t)
const T & operator[](CRef cr) const
void reloc(CRef &cr, ClauseAllocator &to)
const Clause * lea(Ref r) const
static int clauseWord32Size(int size, bool has_extra)
CRef alloc(const Lits &ps, bool learnt=false)
const Clause & operator[](Ref r) const
void moveTo(ClauseAllocator &to)
ClauseAllocator(uint32_t start_cap)
uint32_t abstraction() const
uint32_t mark() const
void mark(uint32_t m)
struct Minisat::Internal::Clause::@4 header
union Minisat::Internal::Clause::@5 data[0]
Clause(const V &ps, bool use_extra, bool learnt)
const Lit & last() const
Lit subsumes(const Clause &other) const
bool peek(const K &k, D &d) const
Definition Map.h:136
void insert(const K &k, const D &d)
Definition Map.h:135
int elems() const
Definition Map.h:173
int bucket_count() const
Definition Map.h:174
const vec< Pair > & bucket(int i) const
Definition Map.h:189
void moveTo(Map &other)
Definition Map.h:177
void remove(const K &k)
Definition Map.h:156
void clean(const Idx &idx)
Vec & lookup(const Idx &idx)
void init(const Idx &idx)
OccLists(const Deleted &d)
Vec & operator[](const Idx &idx)
void smudge(const Idx &idx)
void clear(bool free=true)
void moveTo(RegionAllocator &to)
Definition Alloc.h:76
lbool operator&&(lbool b) const
lbool operator||(lbool b) const
bool operator!=(lbool b) const
bool operator==(lbool b) const
friend int toInt(lbool l)
lbool operator^(bool b) const
friend lbool toLbool(int v)
int size(void) const
Definition Vec.h:63
void shrink(int nelems)
Definition Vec.h:64
void clear(bool dealloc=false)
Definition Vec.h:121
void push(void)
Definition Vec.h:73
void growTo(int size)
Definition Vec.h:113
int r[]
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
RegionAllocator< uint32_t >::Ref CRef
lbool toLbool(int v)
const Lit lit_Error
Definition SolverTypes.h:74
Lit mkLit(Var var, bool sign=false)
Definition SolverTypes.h:57
const Lit lit_Undef
Definition SolverTypes.h:73
bool sign(Lit p)
Definition SolverTypes.h:60
Lit operator~(Lit p)
Definition SolverTypes.h:58
Lit operator^(Lit p, bool b)
Definition SolverTypes.h:59
Lit toLit(int i)
Definition SolverTypes.h:66
const CRef CRef_Undef
int toInt(Var v)
Definition SolverTypes.h:64
static void remove(V &ts, const T &t)
Definition Alg.h:36
uint32_t operator()(CRef cr) const
bool operator==(Lit p) const
Definition SolverTypes.h:51
bool operator!=(Lit p) const
Definition SolverTypes.h:52
bool operator<(Lit p) const
Definition SolverTypes.h:53
friend Lit mkLit(Var var, bool sign)
Definition SolverTypes.h:57