ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
clause.hpp
Go to the documentation of this file.
1#ifndef _clause_hpp_INCLUDED
2#define _clause_hpp_INCLUDED
3
4#include "global.h"
5
6#include "util.hpp"
7#include <climits>
8#include <cstdint>
9#include <cstdlib>
10
12
13namespace CaDiCaL {
14
15/*------------------------------------------------------------------------*/
16
17typedef int *literal_iterator;
18typedef const int *const_literal_iterator;
19
20/*------------------------------------------------------------------------*/
21
22// The 'Clause' data structure is very important. There are usually many
23// clauses and accessing them is a hot-spot. Thus we use common
24// optimizations to reduce memory and improve cache usage, even though this
25// induces some complexity in understanding the code.
26//
27// The most important optimization is to 'embed' the actual literals in the
28// clause. This requires a variadic size structure and thus strictly is not
29// 'C' conform, but supported by all compilers we used. The alternative is
30// to store the actual literals somewhere else, which not only needs more
31// memory but more importantly also requires another memory access and thus
32// is very costly.
33
34struct Clause {
35 union {
36 int64_t id; // Used to create LRAT-style proofs
37 Clause *copy; // Only valid if 'moved', then that's where to.
38 //
39 // The 'copy' field is only valid for 'moved' clauses in the moving
40 // garbage collector 'copy_non_garbage_clauses' for keeping clauses
41 // compactly in a contiguous memory arena. Otherwise, so almost all of
42 // the time, 'id' is valid. See 'collect.cpp' for details.
43 };
44 bool conditioned : 1; // Tried for globally blocked clause elimination.
45 bool covered : 1; // Already considered for covered clause elimination.
46 bool enqueued : 1; // Enqueued on backward queue.
47 bool frozen : 1; // Temporarily frozen (in covered clause elimination).
48 bool garbage : 1; // can be garbage collected unless it is a 'reason'
49 bool gate : 1; // Clause part of a gate (function definition).
50 bool hyper : 1; // redundant hyper binary or ternary resolved
51 bool instantiated : 1; // tried to instantiate
52 bool moved : 1; // moved during garbage collector ('copy' valid)
53 bool reason : 1; // reason / antecedent clause can not be collected
54 bool redundant : 1; // aka 'learned' so not 'irredundant' (original)
55 bool transred : 1; // already checked for transitive reduction
56 bool subsume : 1; // not checked in last subsumption round
57 bool swept : 1; // clause used to sweep equivalences
58 bool flushed : 1; // garbage in proof deleted binaries
59 unsigned used : 8; // resolved in conflict analysis since last 'reduce'
60 bool vivified : 1; // clause already vivified
61 bool vivify : 1; // clause scheduled to be vivified
62
63 // The glucose level ('LBD' or short 'glue') is a heuristic value for the
64 // expected usefulness of a learned clause, where smaller glue is consider
65 // more useful. During learning the 'glue' is determined as the number of
66 // decisions in the learned clause. Thus the glue of a clause is a strict
67 // upper limit on the smallest number of decisions needed to make it
68 // propagate. For instance a binary clause will propagate if one of its
69 // literals is set to false. Similarly a learned clause with glue 1 can
70 // propagate after one decision, one with glue 2 after 2 decisions etc.
71 // In some sense the glue is an abstraction of the size of the clause.
72 //
73 // See the IJCAI'09 paper by Audemard & Simon for more details. We
74 // switched back and forth between keeping the glue stored in a clause and
75 // using it only initially to determine whether it is kept, that is
76 // survives clause reduction. The latter strategy is not bad but also
77 // does not allow to use glue values for instance in 'reduce'.
78 //
79 // More recently we also update the glue and promote clauses to lower
80 // level tiers during conflict analysis. The idea of using three tiers is
81 // also due to Chanseok Oh and thus used in all recent 'Maple...' solvers.
82 // Tier one are the always kept clauses with low glue at most
83 // 'opts.reducetier1glue' (default '2'). The second tier contains all
84 // clauses with glue larger than 'opts.reducetier1glue' but smaller or
85 // equal than 'opts.reducetier2glue' (default '6'). The third tier
86 // consists of clauses with glue larger than 'opts.reducetier2glue'.
87 //
88 // Clauses in tier one are not deleted in 'reduce'. Clauses in tier
89 // two require to be unused in two consecutive 'reduce' intervals before
90 // being collected while for clauses in tier three not being used since
91 // the last 'reduce' call makes them deletion candidates. Clauses derived
92 // by hyper binary or ternary resolution (even though small and thus with
93 // low glue) are always removed if they remain unused during one interval.
94 // See 'mark_useless_redundant_clauses_as_garbage' in 'reduce.cpp' and
95 // 'bump_clause' in 'analyze.cpp'.
96 //
97 int glue;
98
99 int size; // Actual size of 'literals' (at least 2).
100 int pos; // Position of last watch replacement [Gent'13].
101
102 // This 'flexible array member' is of variadic 'size' (and actually
103 // shrunken if strengthened) and keeps the literals close to the header of
104 // the clause to avoid another pointer dereference, which would be costly.
105
106 // In earlier versions we used 'literals[2]' to fake it (in order to
107 // support older Microsoft compilers even though this feature is in C99)
108 // and at the same time being able to overlay the first two literals with
109 // the 'copy' field above, as having a flexible array member inside a
110 // union is not allowed. Now compilers start to figure out that those
111 // literals can be accessed with indices larger than 1 and produce
112 // warnings. After having the 'id' field mandatory we now overlay that
113 // one with the copy field.
114
115 // However, it turns out that even though flexible array members are in
116 // C99 they are not in C11++, and therefore pedantic compilation with
117 // '--pedantic' fails completely. Therefore we still support as
118 // alternative faked flexible array members, which unfortunately need
119 // then again more care when accessing the literals outside the faked
120 // virtual sizes and the compiler can somehow figure that out, because
121 // that would in turn produce a warning.
122
123#ifndef NFLEXIBLE
124 int literals[];
125#else
126 int literals[2];
127#endif
128
129 // Supports simple range based for loops over clauses.
130
133
136
137 static size_t bytes (int size) {
138
139 // Memory sanitizer insists that clauses put into consecutive memory in
140 // the arena are still 8 byte aligned. We could also allocate 8 byte
141 // aligned memory there. However, assuming the real memory foot print
142 // of a clause is 8 bytes anyhow, we just allocate 8 byte aligned memory
143 // all the time (even if allocated outside of the arena).
144 //
145 CADICAL_assert (size > 1);
146 const size_t header_bytes = sizeof (Clause);
147 const size_t actual_literal_bytes = size * sizeof (int);
148 size_t combined_bytes = header_bytes + actual_literal_bytes;
149#ifdef NFLEXIBLE
150 const size_t faked_literals_bytes = sizeof ((Clause *) 0)->literals;
151 combined_bytes -= faked_literals_bytes;
152#endif
153 size_t aligned_bytes = align (combined_bytes, 8);
154 return aligned_bytes;
155 }
156
157 size_t bytes () const { return bytes (size); }
158
159 // Check whether this clause is ready to be collected and deleted. The
160 // 'reason' flag is only there to protect reason clauses in 'reduce',
161 // which does not backtrack to the root level. If garbage collection is
162 // triggered from a preprocessor, which backtracks to the root level, then
163 // 'reason' is false for sure. We want to use the same garbage collection
164 // code though for both situations and thus hide here this variance.
165 //
166 bool collect () const { return !reason && garbage; }
167};
168
170 bool operator() (const Clause *a, const Clause *b) {
171 return a->size < b->size;
172 }
173};
174
175/*------------------------------------------------------------------------*/
176
177// Place literals over the same variable close to each other. This would
178// allow eager removal of identical literals and detection of tautological
179// clauses but is only currently used for better logging (see also
180// 'opts.logsort' in 'logging.cpp').
181
183 bool operator() (int a, int b) const {
184 using namespace std;
185 int s = abs (a), t = abs (b);
186 return s < t || (s == t && a < b);
187 }
188};
189
190} // namespace CaDiCaL
191
193
194#endif
#define ABC_NAMESPACE_CXX_HEADER_START
#define ABC_NAMESPACE_CXX_HEADER_END
#define CADICAL_assert(ignore)
Definition global.h:14
int * literal_iterator
Definition clause.hpp:17
size_t align(size_t n, size_t alignment)
Definition util.hpp:59
const int * const_literal_iterator
Definition clause.hpp:18
size_t bytes() const
Definition clause.hpp:157
literal_iterator begin()
Definition clause.hpp:131
static size_t bytes(int size)
Definition clause.hpp:137
unsigned used
Definition clause.hpp:59
bool instantiated
Definition clause.hpp:51
const_literal_iterator end() const
Definition clause.hpp:135
literal_iterator end()
Definition clause.hpp:132
Clause * copy
Definition clause.hpp:37
const_literal_iterator begin() const
Definition clause.hpp:134
bool collect() const
Definition clause.hpp:166
bool operator()(int a, int b) const
Definition clause.hpp:183
bool operator()(const Clause *a, const Clause *b)
Definition clause.hpp:170