GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/prop/bvminisat/core/SolverTypes.h Lines: 124 131 94.7 %
Date: 2021-05-21 Branches: 62 170 36.5 %

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