ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
cadical_deduplicate.cpp
Go to the documentation of this file.
1#include "global.h"
2
3#include "internal.hpp"
4
6
7namespace CaDiCaL {
8
9// Equivalent literal substitution in 'decompose' and shrinking in 'subsume'
10// or 'vivify' might produce duplicated binary clauses. They can not be
11// found in 'subsume' nor 'vivify' since we explicitly do not consider
12// binary clauses as candidates to be shrunken or subsumed. They are
13// detected here by a simple scan of watch lists and then marked as garbage.
14// This is actually also quite fast.
15
16// Further it might also be possible that two binary clauses can be resolved
17// to produce a unit (we call it 'hyper unary resolution'). For example
18// resolving the binary clauses '1 -2' and '1 2' produces the unit '1'.
19// This could be found by probing in 'probe' unless '-1' also occurs in a
20// binary clause (add the clause '-1 2' to those two clauses) in which case
21// '1' as well as '2' both occur positively as well as negatively and none
22// of them nor their negation is considered as probe
23
25
26 if (!opts.deduplicate)
27 return;
28 if (unsat)
29 return;
31 return;
32
33 START_SIMPLIFIER (deduplicate, DEDUP);
34 stats.deduplications++;
35
38
39 vector<int> stack; // To save marked literals and unmark them later.
40
41 int64_t subsumed = 0;
42 int64_t units = 0;
43
44 for (auto idx : vars) {
45
46 if (unsat)
47 break;
48 if (!active (idx))
49 continue;
50 int unit = 0;
51
52 for (int sign = -1; !unit && sign <= 1; sign += 2) {
53
54 const int lit = sign * idx; // Consider all literals.
55
56 CADICAL_assert (stack.empty ());
57 Watches &ws = watches (lit);
58
59 // We are removing references to garbage clause. Thus no 'auto'.
60
61 const const_watch_iterator end = ws.end ();
62 watch_iterator j = ws.begin ();
64
65 for (i = j; !unit && i != end; i++) {
66 Watch w = *j++ = *i;
67 if (!w.binary ())
68 continue;
69 int other = w.blit;
70 const int tmp = marked (other);
71 Clause *c = w.clause;
72
73 if (tmp > 0) { // Found duplicated binary clause.
74
75 if (c->garbage) {
76 j--;
77 continue;
78 }
79 LOG (c, "found duplicated");
80
81 // The previous identical clause 'd' might be redundant and if the
82 // second clause 'c' is not (so irredundant), then we have to keep
83 // 'c' instead of 'd', thus we search for it and replace it.
84
85 if (!c->redundant) {
87 for (k = ws.begin ();; k++) {
88 CADICAL_assert (k != i);
89 if (!k->binary ())
90 continue;
91 if (k->blit != other)
92 continue;
93 Clause *d = k->clause;
94 if (d->garbage)
95 continue;
96 c = d;
97 break;
98 }
99 *k = w;
100 }
101
102 LOG (c, "mark garbage duplicated");
103 stats.subsumed++;
104 stats.deduplicated++;
105 subsumed++;
106 mark_garbage (c);
107 j--;
108
109 } else if (tmp < 0) { // Hyper unary resolution.
110
111 LOG ("found %d %d and %d %d which produces unit %d", lit, -other,
112 lit, other, lit);
113 unit = lit;
114 if (lrat) {
115 // taken from fradical
116 CADICAL_assert (lrat_chain.empty ());
117 lrat_chain.push_back (c->id);
118 // We've forgotten where the other binary clause is, so go find
119 // it again
120 for (watch_iterator k = ws.begin ();; k++) {
121 CADICAL_assert (k != i);
122 if (!k->binary ())
123 continue;
124 if (k->blit != -other)
125 continue;
126 lrat_chain.push_back (k->clause->id);
127 break;
128 }
129 }
130 j = ws.begin (); // Flush 'ws'.
131 units++;
132
133 } else {
134 if (c->garbage)
135 continue;
136 mark (other);
137 stack.push_back (other);
138 }
139 }
140
141 if (j == ws.begin ())
142 erase_vector (ws);
143 else if (j != end)
144 ws.resize (j - ws.begin ()); // Shrink watchers.
145
146 for (const auto &other : stack)
147 unmark (other);
148
149 stack.clear ();
150 }
151
152 // Propagation potentially messes up the watches and thus we can not
153 // propagate the unit immediately after finding it. Instead we break
154 // out of both loops and assign and propagate the unit here.
155
156 if (unit) {
157
158 stats.failed++;
159 stats.hyperunary++;
160 assign_unit (unit);
161 // lrat_chain.clear (); done in search_assign
162
163 if (!propagate ()) {
164 LOG ("empty clause after propagating unit");
166 }
167 }
168 }
169 STOP_SIMPLIFIER (deduplicate, DEDUP);
170
171 report ('2', !opts.reportall && !(subsumed + units));
172}
173
174} // namespace CaDiCaL
175
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define CADICAL_assert(ignore)
Definition global.h:14
#define LOG(...)
int sign(int lit)
Definition util.hpp:22
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
Watches::iterator watch_iterator
Definition watch.hpp:47
#define START_SIMPLIFIER(S, M)
Definition profile.hpp:172
#define STOP_SIMPLIFIER(S, M)
Definition profile.hpp:197
int lit
Definition satVec.h:130
void mark_duplicated_binary_clauses_as_garbage()
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)
bool watching() const
Definition internal.hpp:462
signed char marked(int lit) const
Definition internal.hpp:478
bool active(int lit)
Definition internal.hpp:360
const Range vars
Definition internal.hpp:324
bool binary() const
Definition watch.hpp:42
Clause * clause
Definition watch.hpp:35
signed char mark
Definition value.h:8
vector watches
Definition watch.h:49