ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
cadical_transred.cpp
Go to the documentation of this file.
1#include "global.h"
2
3#include "internal.hpp"
4
6
7namespace CaDiCaL {
8
9// Implement transitive reduction in the binary implication graph. This is
10// important for hyper binary resolution, which has the risk to produce too
11// many hyper binary resolvents otherwise. This algorithm only works on
12// binary clauses and is usually pretty fast. It will also find some failed
13// literals (in the binary implication graph).
14
16 if (!opts.transred)
17 return;
18 if (unsat)
19 return;
21 return;
22 if (!stats.current.redundant && !stats.current.irredundant)
23 return;
24
25 CADICAL_assert (opts.transred);
27
29 stats.transreds++;
30
31 // Transitive reduction can not be run to completion for larger formulas
32 // with many binary clauses. We bound it in the same way as 'probe_core'.
33 //
34 int64_t limit = stats.propagations.search;
35 limit -= last.transred.propagations;
36 limit *= 1e-3 * opts.transredeffort;
37 if (limit < opts.transredmineff)
38 limit = opts.transredmineff;
39 if (limit > opts.transredmaxeff)
40 limit = opts.transredmaxeff;
41
42 PHASE ("transred", stats.transreds,
43 "transitive reduction limit of %" PRId64 " propagations", limit);
44
45 const auto end = clauses.end ();
46 auto i = clauses.begin ();
47
48 // Find first clause not checked for being transitive yet.
49 //
50 for (; i != end; i++) {
51 Clause *c = *i;
52 if (c->garbage)
53 continue;
54 if (c->size != 2)
55 continue;
56 if (c->redundant && c->hyper)
57 continue;
58 if (!c->transred)
59 break;
60 }
61
62 // If all candidate clauses have been checked reschedule all.
63 //
64 if (i == end) {
65
66 PHASE ("transred", stats.transreds,
67 "rescheduling all clauses since no clauses to check left");
68 for (i = clauses.begin (); i != end; i++) {
69 Clause *c = *i;
70 if (c->transred)
71 c->transred = false;
72 }
73 i = clauses.begin ();
74 }
75
76 // Move watches of binary clauses to the front. Thus we can stop iterating
77 // watches as soon a long clause is found during watch traversal.
78 //
79 sort_watches ();
80
81 // This working stack plays the same role as the 'trail' during standard
82 // propagation.
83 //
84 vector<int> work;
85
86 int64_t propagations = 0, units = 0, removed = 0;
87
88 while (!unsat && i != end && !terminated_asynchronously () &&
89 propagations < limit) {
90 Clause *c = *i++;
91
92 // A clause is a candidate for being transitive if it is binary, and not
93 // the result of hyper binary resolution. The reason for excluding
94 // those, is that they come in large numbers, most of them are reduced
95 // away anyhow and further are non-transitive at the point they are
96 // added (see the code in 'hyper_binary_resolve' in 'prope.cpp' and
97 // also check out our CPAIOR paper on tree-based look ahead).
98 //
99 if (c->garbage)
100 continue;
101 if (c->size != 2)
102 continue;
103 if (c->redundant && c->hyper)
104 continue;
105 if (c->transred)
106 continue; // checked before?
107 c->transred = true; // marked as checked
108
109 LOG (c, "checking transitive reduction of");
110
111 // Find a different path from 'src' to 'dst' in the binary implication
112 // graph, not using 'c'. Since this is the same as checking whether
113 // there is a path from '-dst' to '-src', we can do the reverse search
114 // if the number of watches of '-dst' is larger than those of 'src'.
115 //
116 int src = -c->literals[0];
117 int dst = c->literals[1];
118 if (val (src) || val (dst))
119 continue;
120 if (watches (-src).size () < watches (dst).size ()) {
121 int tmp = dst;
122 dst = -src;
123 src = -tmp;
124 }
125
126 LOG ("searching path from %d to %d", src, dst);
127
128 // If the candidate clause is irredundant then we can not use redundant
129 // binary clauses in the implication graph. See our inprocessing rules
130 // paper, why this restriction is required.
131 //
132 const bool irredundant = !c->redundant;
133
134 CADICAL_assert (work.empty ());
135 mark (src);
136 work.push_back (src);
137 LOG ("transred assign %d", src);
138
139 bool transitive = false; // found path from 'src' to 'dst'?
140 bool failed = false; // 'src' failed literal?
141
142 size_t j = 0; // 'propagated' in BFS
143
144 CADICAL_assert (lrat_chain.empty ());
145 CADICAL_assert (mini_chain.empty ());
147
148 while (!transitive && !failed && j < work.size ()) {
149 const int lit = work[j++];
150 CADICAL_assert (marked (lit) > 0);
151 LOG ("transred propagating %d", lit);
152 propagations++;
153 const Watches &ws = watches (-lit);
154 const const_watch_iterator eow = ws.end ();
156 for (k = ws.begin (); !transitive && !failed && k != eow; k++) {
157 const Watch &w = *k;
158 if (!w.binary ())
159 break; // since we sorted watches above
160 Clause *d = w.clause;
161 if (d == c)
162 continue;
163 if (irredundant && d->redundant)
164 continue;
165 if (d->garbage)
166 continue;
167 const int other = w.blit;
168 if (other == dst)
169 transitive = true; // 'dst' reached
170 else {
171 const int tmp = marked (other);
172 if (tmp > 0)
173 continue;
174 else if (tmp < 0) {
175 if (lrat) {
176 parents.push_back (lit);
177 mini_chain.push_back (d->id);
178 work.push_back (other);
179 }
180 LOG ("found both %d and %d reachable", -other, other);
181 failed = true;
182 } else {
183 if (lrat) {
184 parents.push_back (lit);
185 mini_chain.push_back (d->id);
186 }
187 mark (other);
188 work.push_back (other);
189 LOG ("transred assign %d", other);
190 }
191 }
192 }
193 }
194
195 int failed_lit = work.back ();
196 int next_pos = 0;
197 int next_neg = 0;
198
199 // Unassign all assigned literals (same as '[bp]acktrack').
200 //
201 while (!work.empty ()) {
202 const int lit = work.back ();
203 work.pop_back ();
204 if (lrat && failed && !work.empty ()) {
205 CADICAL_assert (!parents.empty () && !mini_chain.empty ());
206 LOG ("transred LRAT current lit %d next pos %d next neg %d", lit,
207 next_pos, next_neg);
208 if (lit == failed_lit || lit == next_pos) {
209 lrat_chain.push_back (mini_chain.back ());
210 next_pos = parents.back ();
211 } else if (lit == -failed_lit || lit == next_neg) {
212 lrat_chain.push_back (mini_chain.back ());
213 next_neg = parents.back ();
214 }
215 parents.pop_back ();
216 mini_chain.pop_back ();
217 }
218 unmark (lit);
219 }
220 mini_chain.clear ();
221 CADICAL_assert (mini_chain.empty ());
222 if (lrat && failed) {
223 reverse (lrat_chain.begin (), lrat_chain.end ());
224 }
225
226 if (transitive) {
227 removed++;
228 stats.transitive++;
229 LOG (c, "transitive redundant");
230 mark_garbage (c);
231 } else if (failed) {
232 units++;
233 LOG ("found failed literal %d during transitive reduction", src);
234 stats.failed++;
235 stats.transredunits++;
236 assign_unit (-src);
237 if (!propagate ()) {
238 VERBOSE (1, "propagating new unit results in conflict");
240 }
241 }
242 lrat_chain.clear ();
243 }
244
245 last.transred.propagations = stats.propagations.search;
246 stats.propagations.transred += propagations;
247 erase_vector (work);
248
249 PHASE ("transred", stats.transreds,
250 "removed %" PRId64 " transitive clauses, found %" PRId64 " units",
251 removed, units);
252
254 report ('t', !opts.reportall && !(removed + units));
255}
256
257} // namespace CaDiCaL
258
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define CADICAL_assert(ignore)
Definition global.h:14
#define LOG(...)
#define PHASE(...)
Definition message.hpp:52
#define VERBOSE(...)
Definition message.hpp:58
Watches::const_iterator const_watch_iterator
Definition watch.hpp:48
vector< Watch > Watches
Definition watch.hpp:45
void erase_vector(std::vector< T > &v)
Definition util.hpp:90
#define START_SIMPLIFIER(S, M)
Definition profile.hpp:172
#define STOP_SIMPLIFIER(S, M)
Definition profile.hpp:197
int lit
Definition satVec.h:130
int64_t irredundant() const
Definition internal.hpp:383
void mark_garbage(Clause *)
vector< int64_t > lrat_chain
Definition internal.hpp:210
void report(char type, int verbose_level=0)
void unmark(int lit)
Definition internal.hpp:490
bool terminated_asynchronously(int factor=1)
signed char val(int lit) const
bool limit(const char *name, int)
signed char marked(int lit) const
Definition internal.hpp:478
vector< Clause * > clauses
Definition internal.hpp:283
vector< int > parents
Definition internal.hpp:232
vector< int64_t > mini_chain
Definition internal.hpp:211
Watches & watches(int lit)
Definition internal.hpp:467
bool binary() const
Definition watch.hpp:42
Clause * clause
Definition watch.hpp:35
unsigned size
Definition vector.h:35
signed char mark
Definition value.h:8
vector watches
Definition watch.h:49