ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
reduce.c
Go to the documentation of this file.
1#include "reduce.h"
2#include "allocate.h"
3#include "collect.h"
4#include "inline.h"
5#include "print.h"
6#include "rank.h"
7#include "report.h"
8#include "tiers.h"
9#include "trail.h"
10
11#include <inttypes.h>
12#include <math.h>
13
15
17 if (!GET_OPTION (reduce))
18 return false;
19 if (!solver->statistics_.clauses_redundant)
20 return false;
22 return false;
23 return true;
24}
25
26typedef struct reducible reducible;
27
28struct reducible {
29 uint64_t rank;
30 unsigned ref;
31};
32
33#define RANK_REDUCIBLE(RED) (RED).rank
34
35// clang-format off
36typedef STACK (reducible) reducibles;
37// clang-format on
38
39static bool collect_reducibles (kissat *solver, reducibles *reds,
40 reference start_ref) {
41 KISSAT_assert (start_ref != INVALID_REF);
42 KISSAT_assert (start_ref <= SIZE_STACK (solver->arena));
43 ward *const arena = BEGIN_STACK (solver->arena);
44 clause *start = (clause *) (arena + start_ref);
45 const clause *const end = (clause *) END_STACK (solver->arena);
46 KISSAT_assert (start < end);
47 while (start != end && !start->redundant)
48 start = kissat_next_clause (start);
49 if (start == end) {
50 solver->first_reducible = INVALID_REF;
51 LOG ("no reducible clause candidate left");
52 return false;
53 }
54 const reference redundant = (ward *) start - arena;
55#ifdef LOGGING
56 if (redundant < solver->first_reducible)
57 LOG ("updating start of redundant clauses from %zu to %zu",
58 (size_t) solver->first_reducible, (size_t) redundant);
59 else
60 LOG ("no update to start of redundant clauses %zu",
61 (size_t) solver->first_reducible);
62#endif
63 solver->first_reducible = redundant;
64 const unsigned tier1 = TIER1;
65 const unsigned tier2 = MAX (tier1, TIER2);
66 KISSAT_assert (tier1 <= tier2);
67 for (clause *c = start; c != end; c = kissat_next_clause (c)) {
68 if (!c->redundant)
69 continue;
70 if (c->garbage)
71 continue;
72 const unsigned used = c->used;
73 if (used)
74 c->used = used - 1;
75 if (c->reason)
76 continue;
77 const unsigned glue = c->glue;
78 if (glue <= tier1 && used)
79 continue;
80 if (glue <= tier2 && used >= MAX_USED - 1)
81 continue;
82 KISSAT_assert (kissat_clause_in_arena (solver, c));
83 reducible red;
84 const uint64_t negative_size = ~c->size;
85 const uint64_t negative_glue = ~c->glue;
86 red.rank = negative_size | (negative_glue << 32);
87 red.ref = (ward *) c - arena;
88 PUSH_STACK (*reds, red);
89 }
90 if (EMPTY_STACK (*reds)) {
91 kissat_phase (solver, "reduce", GET (reductions),
92 "did not find any reducible redundant clause");
93 return false;
94 }
95 return true;
96}
97
98#define USEFULNESS RANK_REDUCIBLE
99
100static void sort_reducibles (kissat *solver, reducibles *reds) {
101 RADIX_STACK (reducible, uint64_t, *reds, USEFULNESS);
102}
103
104static void mark_less_useful_clauses_as_garbage (kissat *solver,
105 reducibles *reds) {
106 statistics *statistics = &solver->statistics_;
107 const double high = GET_OPTION (reducehigh) * 0.1;
108 const double low = GET_OPTION (reducelow) * 0.1;
109 double percent;
110 if (low < high) {
111 const double delta = high - low;
112 percent = high - delta / log10 (statistics->reductions + 9);
113 } else
114 percent = low;
115 const double fraction = percent / 100.0;
116 const size_t size = SIZE_STACK (*reds);
117 size_t target = size * fraction;
118#ifndef KISSAT_QUIET
119 const size_t clauses =
120 statistics->clauses_irredundant + statistics->clauses_redundant;
121 kissat_phase (solver, "reduce", GET (reductions),
122 "reducing %zu (%.0f%%) out of %zu (%.0f%%) "
123 "reducible clauses",
124 target, kissat_percent (target, size), size,
125 kissat_percent (size, clauses));
126#endif
127 unsigned reduced = 0, reduced1 = 0, reduced2 = 0, reduced3 = 0;
128 ward *arena = BEGIN_STACK (solver->arena);
129 const reducible *const begin = BEGIN_STACK (*reds);
130 const reducible *const end = END_STACK (*reds);
131 const unsigned tier1 = TIER1;
132 const unsigned tier2 = TIER2;
133 for (const reducible *p = begin; p != end && target--; p++) {
134 clause *c = (clause *) (arena + p->ref);
135 KISSAT_assert (kissat_clause_in_arena (solver, c));
137 KISSAT_assert (!c->reason);
139 LOGCLS (c, "reducing");
141 reduced++;
142 if (c->glue <= tier1)
143 reduced1++;
144 else if (c->glue <= tier2)
145 reduced2++;
146 else
147 reduced3++;
148 }
149 ADD (clauses_reduced_tier1, reduced1);
150 ADD (clauses_reduced_tier2, reduced2);
151 ADD (clauses_reduced_tier3, reduced3);
152 ADD (clauses_reduced, reduced);
153}
154
156 START (reduce);
157 INC (reductions);
158 kissat_phase (solver, "reduce", GET (reductions),
159 "reduce limit %" PRIu64 " hit after %" PRIu64 " conflicts",
160 solver->limits.reduce.conflicts, CONFLICTS);
162 bool compact = kissat_compacting (solver);
163 reference start = compact ? 0 : solver->first_reducible;
164 if (start != INVALID_REF) {
165#ifndef KISSAT_QUIET
166 size_t arena_size = SIZE_STACK (solver->arena);
167 size_t words_to_sweep = arena_size - start;
168 size_t bytes_to_sweep = sizeof (word) * words_to_sweep;
169 kissat_phase (solver, "reduce", GET (reductions),
170 "reducing clauses after offset %" REFERENCE_FORMAT
171 " in arena",
172 start);
173 kissat_phase (solver, "reduce", GET (reductions),
174 "reducing %zu words %s %.0f%%", words_to_sweep,
175 FORMAT_BYTES (bytes_to_sweep),
176 kissat_percent (words_to_sweep, arena_size));
177#endif
179 reducibles reds;
180 INIT_STACK (reds);
181 if (collect_reducibles (solver, &reds, start)) {
182 sort_reducibles (solver, &reds);
183 mark_less_useful_clauses_as_garbage (solver, &reds);
184 RELEASE_STACK (reds);
185 kissat_sparse_collect (solver, compact, start);
186 } else if (compact)
187 kissat_sparse_collect (solver, compact, start);
188 else
190 } else
191 KISSAT_assert (solver->inconsistent);
192 } else
193 kissat_phase (solver, "reduce", GET (reductions), "nothing to reduce");
195 UPDATE_CONFLICT_LIMIT (reduce, reductions, SQRT, false);
196 solver->last.conflicts.reduce = CONFLICTS;
197 REPORT (0, '-');
198 STOP (reduce);
199 return solver->inconsistent ? 20 : 0;
200}
201
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
ABC_NAMESPACE_HEADER_START typedef word ward
Definition arena.h:12
#define MAX(a, b)
Definition avl.h:23
#define BEGIN_STACK(S)
Definition stack.h:46
#define SIZE_STACK(S)
Definition stack.h:19
#define EMPTY_STACK(S)
Definition stack.h:18
#define RELEASE_STACK(S)
Definition stack.h:71
#define PUSH_STACK(S, E)
Definition stack.h:39
#define INIT_STACK(S)
Definition stack.h:22
#define STACK(TYPE)
Definition stack.h:10
#define END_STACK(S)
Definition stack.h:48
#define ADD(NAME, DELTA)
#define INC(NAME)
#define LOG(...)
ABC_NAMESPACE_IMPL_START void kissat_classify(struct kissat *solver)
Definition classify.c:7
void kissat_mark_clause_as_garbage(kissat *solver, clause *c)
Definition clause.c:164
bool kissat_compacting(kissat *solver)
Definition collect.c:635
void kissat_sparse_collect(kissat *solver, bool compact, reference start)
Definition collect.c:610
pcover reduce()
Cube * p
Definition exorList.c:222
#define FORMAT_BYTES(BYTES)
Definition format.h:31
#define TIER1
Definition internal.h:258
#define TIER2
Definition internal.h:259
#define SQRT(COUNT)
Definition kimits.h:113
#define UPDATE_CONFLICT_LIMIT(NAME, COUNT, SCALE_COUNT_FUNCTION, SCALE_DELTA)
Definition kimits.h:115
#define MAX_USED
Definition clause.h:20
#define KISSAT_assert(ignore)
Definition global.h:13
unsigned __int64 word
DECLARATIONS ///.
Definition kitPerm.c:36
#define solver
Definition kitten.c:211
#define LOGCLS(...)
Definition logging.h:415
double percent(double a, double b)
Definition util.hpp:21
unsigned long long size
Definition giaNewBdd.h:39
#define GET_OPTION(N)
Definition options.h:295
#define kissat_phase(...)
Definition print.h:48
#define STOP(P)
Definition profile.hpp:158
#define START(P)
Definition profile.hpp:150
#define RADIX_STACK(VTYPE, RTYPE, S, RANK)
Definition rank.h:136
#define INVALID_REF
Definition reference.h:16
ABC_NAMESPACE_HEADER_START typedef unsigned reference
Definition reference.h:9
#define REFERENCE_FORMAT
Definition reference.h:11
#define REPORT(...)
Definition report.h:10
int kissat_reduce(kissat *solver)
Definition reduce.c:155
#define USEFULNESS
Definition reduce.c:98
ABC_NAMESPACE_IMPL_START bool kissat_reducing(kissat *solver)
Definition reduce.c:16
#define CONFLICTS
Definition statistics.h:335
#define GET(NAME)
Definition statistics.h:416
bool reason
Definition clause.h:27
unsigned glue
Definition clause.h:23
bool redundant
Definition clause.h:28
bool garbage
Definition clause.h:25
struct limits::@317277023072347355124305102271146250361353123031 reduce
uint64_t conflicts
Definition kimits.h:27
unsigned ref
Definition reduce.c:30
uint64_t rank
Definition reduce.c:29
void kissat_compute_and_set_tier_limits(struct kissat *solver)
Definition tiers.c:53
void kissat_unmark_reason_clauses(kissat *solver, reference start)
Definition trail.c:66
bool kissat_flush_and_mark_reason_clauses(kissat *solver, reference start)
Definition trail.c:49