Painless
A framework to ease parallelization of sequential CDCL SAT solvers
Loading...
Searching...
No Matches
preprocess.hpp
1#pragma once
2
3#include "./utils-prs/bitset.hpp"
4#include "./utils-prs/hashmap.hpp"
5#include "preprocessors/PreprocessorInterface.hpp"
6#include "utils/ErrorCodes.hpp"
7#include "utils/Parameters.hpp"
8
9#include <atomic>
10#include <cassert>
11#include <chrono>
12#include <functional>
13#include <queue>
14#include <unordered_set>
15#include <vector>
16
17typedef long long ll;
18
19#define mapv(a, b) (1ll * (a) * nlit + (ll)(b))
20
21inline int
22pnsign(int x)
23{
24 return (x > 0 ? 1 : -1);
25}
26inline int
27sign(int x)
28{
29 return x & 1 ? -1 : 1;
30}
31inline int
32tolit(int x)
33{
34 return x > 0 ? ((x - 1) << 1) : ((-x - 1) << 1 | 1);
35}
36inline int
37negative(int x)
38{
39 return x ^ 1;
40}
41inline int
42toiidx(int x)
43{
44 return (x >> 1) + 1;
45}
46inline int
47toeidx(int x)
48{
49 return (x & 1 ? -toiidx(x) : toiidx(x));
50}
51
52struct xorgate
53{
54 xorgate(int _c, int _rhs, int _sz) { c = _c, rhs = _rhs, sz = _sz; }
55
56 public:
57 int c;
58 int rhs;
59 int sz;
60};
61
63{
64 std::vector<int> in;
65 int ins, out, type;
66 type_gate()
67 : ins(0)
68 , out(0)
69 , type(0)
70 {
71 }
72 void push_in(int x)
73 {
74 in.push_back(x);
75 ins++;
76 }
77 int& operator[](int index) { return in[index]; }
78 const int& operator[](int index) const { return in[index]; }
79 type_gate& operator=(const type_gate& other)
80 {
81 ins = other.ins;
82 out = other.out;
83 type = other.type;
84 in.resize(ins);
85 for (int i = 0; i < ins; i++)
86 in[i] = other.in[i];
87 return *this;
88 }
89};
90
96{
97 public:
98 preprocess(int id_);
99 int vars;
100 int clauses;
101 std::vector<std::vector<int>> clause, res_clause;
102
103 ~preprocess();
104
105 int flag, epcec_out, maxvar, nxors, rins;
106 int *psign, *psum, *fixed, *cell, *used, *model, *topo_counter;
107 std::vector<int> epcec_in, epcec_rin, *inv_C;
108 std::vector<type_gate> gate;
109
110 int maxlen, orivars, oriclauses, res_clauses, resolutions;
111 int *f, nlit, *a, *val, *color, *varval, *q, *seen, *resseen, *clean, *mapto, *mapfrom, *mapval;
112 // HashMap* C;
113 std::vector<int>*occurp, *occurn, clause_delete, nxtc, resolution;
114
115 int find(int x);
116 bool res_is_empty(int var);
117 void update_var_clause_label();
118 void preprocess_init();
119 bool preprocess_resolution();
120 bool preprocess_binary();
121 bool preprocess_up();
122 void get_complete_model();
123
124 std::vector<std::vector<int>> card_one;
125 std::vector<std::vector<double>> mat;
126 std::vector<int>* occur;
127 std::vector<int> cdel;
128 int check_card(int id);
129 int preprocess_card();
130 int search_almost_one();
131 int card_elimination();
132 int scc_almost_one();
133 void upd_occur(int v, int s);
134
135 int* abstract;
136 int gauss_eli_unit;
137 int gauss_eli_binary;
138 std::vector<xorgate> xors;
139 std::vector<int> scc_id;
140 std::vector<std::vector<int>> scc;
141 std::vector<std::vector<int>> xor_scc;
142 bool preprocess_gauss();
143 int search_xors();
144 int cal_dup_val(int i);
145 int ecc_var();
146 int ecc_xor();
147 int gauss_elimination();
148
149 int rematch_eql(int x);
150 int rematch_and(int x);
151 int rematch_xor(int x);
152 bool cnf2aig();
153 int find_fa(int x);
154 int preprocess_circuit();
155 void epcec_preprocess();
156 bool do_epcec();
157 bool _simulate(Bitset** result, int bit_size);
158
159 /* Painless */
160 unsigned int getVariablesCount() { return this->vars; }
161
162 void restoreModel(std::vector<int>& model)
163 {
164 for (int i = 1; i <= this->orivars; i++)
165 if (this->mapto[i])
166 this->mapval[i] = (model[abs(this->mapto[i]) - 1] > 0 ? 1 : -1) * (this->mapto[i] > 0 ? 1 : -1);
167 this->get_complete_model();
168 model.clear();
169 for (int i = 1; i <= this->orivars; i++) {
170 model.push_back(i * this->mapval[i]);
171 }
172
173 LOG1("[PRS %d] restored model of size %d, vars: %d, orivars: %d",
174 this->getSolverId(),
175 model.size(),
176 this->vars,
177 this->orivars);
178 }
179
180 int count = 0; /* Moved from preprocess.cpp */
181
182 /* Modifiable attribute */
183
184 int maxVarCircuit;
185 int maxVarGauss;
186 int maxVarCard;
187
188 int maxClauseSizeXor;
189 int maxClauseCircuit;
190 int maxClauseBinary;
191 int maxClauseGauss;
192 int maxClauseCard;
193
194 std::vector<std::function<int()>> preprocessors;
195
196 int preprocess_circuit_wrapper()
197 {
198 int res = 0;
199 auto init = std::chrono::high_resolution_clock::now();
200
201 if (vars <= this->maxVarCircuit && clauses <= this->maxClauseCircuit) {
202 res = preprocess_circuit();
203 if (res == 10) {
204 LOG0("[PRS %d] Solved by Circuit Check", this->getSolverId());
205 } else {
206 res = 0;
207 }
208 }
209 auto circuit = std::chrono::high_resolution_clock::now();
210 LOG1("[PRS %d] Circuit Check took %.3lfs",
211 this->getSolverId(),
212 std::chrono::duration_cast<std::chrono::milliseconds>(circuit - init).count() / 1000.0);
213 return res;
214 }
215
216 int preprocess_gauss_wrapper()
217 {
218 int res = 0;
219 auto init = std::chrono::high_resolution_clock::now();
220
221 if (vars <= this->maxVarGauss && clauses <= this->maxClauseGauss) {
222 res = preprocess_gauss();
223 if (!res) {
224 LOG0("[PRS %d] Solved by Gauss Elimination", this->getSolverId());
225 res = 20;
226 } else {
227 res = 0;
228 }
229 }
230 auto gauss = std::chrono::high_resolution_clock::now();
231 LOG1("[PRS %d] Gauss Elimination (xor-limit=%d) took %.3lfs",
232 this->getSolverId(),
233 this->maxClauseSizeXor,
234 std::chrono::duration_cast<std::chrono::milliseconds>(gauss - init).count() / 1000.0);
235 return res;
236 }
237
238 int preprocess_propagation_wrapper()
239 {
240 auto init = std::chrono::high_resolution_clock::now();
241 int res = preprocess_up();
242
243 if (!res) {
244 delete[] mapto;
245 delete[] mapval;
246 clause.clear();
247 res = 20;
248 } else {
249 res = 0;
250 }
251
252 auto up = std::chrono::high_resolution_clock::now();
253 LOG1("[PRS %d] Unit Propagation took %.3lfs",
254 this->getSolverId(),
255 std::chrono::duration_cast<std::chrono::milliseconds>(up - init).count() / 1000.0);
256 return res;
257 }
258
259 int preprocess_card_wrapper()
260 {
261 int res = 0;
262 auto init = std::chrono::high_resolution_clock::now();
263
264 if (vars <= this->maxVarCard && clauses <= this->maxClauseCard) {
265 res = preprocess_card();
266 if (!res) {
267 LOG0("[PRS %d] Solved by Card Elimination", this->getSolverId());
268 delete[] mapto;
269 delete[] mapval;
270 clause.clear();
271 res_clause.clear();
272 resolution.clear();
273 res = 20;
274 } else {
275 res = 0;
276 }
277 }
278 auto card = std::chrono::high_resolution_clock::now();
279 LOG1("[PRS %d] Card Elimination took %.3lfs",
280 this->getSolverId(),
281 std::chrono::duration_cast<std::chrono::milliseconds>(card - init).count() / 1000.0);
282 return res;
283 }
284
285 int preprocess_resolution_wrapper()
286 {
287 auto init = std::chrono::high_resolution_clock::now();
288 int res = preprocess_resolution();
289 if (!res) {
290 LOG0("[PRS %d] Solved by Resolution", this->getSolverId());
291 delete[] mapto;
292 delete[] mapval;
293 clause.clear();
294 res_clause.clear();
295 resolution.clear();
296 res = 20;
297 }
298 auto resol = std::chrono::high_resolution_clock::now();
299 LOG1("[PRS %d] Resolution took %.3lfs",
300 this->getSolverId(),
301 std::chrono::duration_cast<std::chrono::milliseconds>(resol - init).count() / 1000.0);
302 return res;
303 }
304
305 int preprocess_binary_wrapper()
306 {
307 auto init = std::chrono::high_resolution_clock::now();
308 int res = 0;
309 if (clauses <= this->maxClauseBinary) {
310 res = preprocess_binary();
311 if (!res) {
312 delete[] mapto;
313 delete[] mapval;
314 clause.clear();
315 res_clause.clear();
316 resolution.clear();
317 res = 20;
318 }
319 }
320 auto binary = std::chrono::high_resolution_clock::now();
321 LOG1("[PRS %d] Binary took %.3lfs",
322 this->getSolverId(),
323 std::chrono::duration_cast<std::chrono::milliseconds>(binary - init).count() / 1000.0);
324 return res;
325 }
326
327 public:
328 /* Preprocess Interface */
329
331 {
332 LOGERROR("NOT IMPLEMENTED, YET!");
333 exit(PERR_NOT_SUPPORTED);
334 }
335
337 {
338 LOGERROR("NOT IMPLEMENTED, YET!");
339 exit(PERR_NOT_SUPPORTED);
340 }
341
342 SatResult solve(const std::vector<int>& cube = {}) override;
343
344 void releaseMemory() override;
345
346 std::vector<int> getModel() override;
347
348 void loadFormula(const char* filename) override;
349
350 void addInitialClauses(const std::vector<simpleClause>& clauses, unsigned int nbVariables)
351 {
352 LOGERROR("NOT IMPLEMENTED, YET!");
353 exit(PERR_NOT_SUPPORTED);
354 }
355
357 {
358 LOGERROR("NOT IMPLEMENTED, YET!");
359 exit(PERR_NOT_SUPPORTED);
360 }
361
362 std::vector<simpleClause> getSimplifiedFormula()
363 {
364 // PRS uses indexes from 1 to prs.clauses
365 clause.erase(clause.begin());
366 return clause;
367 }
368
369 std::size_t getClausesCount() { return clauses; }
370
371 void diversify(const SeedGenerator& getSeed) { LOGWARN("preprocess has no diversification, yet"); }
372
374 {
375 if(this->clauses < 0 || this->vars < 0) std::abort();
376 return { (unsigned)this->clauses, (unsigned)(this->oriclauses - this->clauses), 0, 0, (unsigned)(this->orivars - this->vars) };
377 }
378
379 int getDivisionVariable() { return 0; }
380
381 void addClause(ClauseExchangePtr clause) { return; }
382 void addClauses(const std::vector<ClauseExchangePtr>& clauses) { return; }
383};
#define LOGERROR(...)
Log an error message.
Definition Logger.hpp:120
#define LOGWARN(...)
Log a warning message.
Definition Logger.hpp:137
#define LOG1(...)
Log a message with verbosity level 1.
Definition Logger.hpp:162
#define LOG0(...)
Log a message with verbosity level 0.
Definition Logger.hpp:154
A class representing a bitset with dynamic size.
Definition Bitset.hpp:14
Interface for preprocessor algorithms in SAT solving.
Definition PreprocessorInterface.hpp:40
unsigned int getSolverId()
Get the solver ID.
Definition SolverInterface.hpp:178
SatResult
Enumeration for SAT solver results.
Definition SolverInterface.hpp:39
Preperocessing technique statistics.
Definition PreprocessorInterface.hpp:14
The different simplification techniques implemented in PRS framework.
Definition preprocess.hpp:96
void releaseMemory() override
Release memory used by the preprocessor.
void setSolverInterrupt()
Interrupt resolution, solving cannot continue until interrupt is unset.
Definition preprocess.hpp:330
void addClause(ClauseExchangePtr clause)
Add a permanent clause to the formula.
Definition preprocess.hpp:381
SatResult solve(const std::vector< int > &cube={}) override
Solve the formula with a given cube.
void printStatistics()
Print solver statistics.
Definition preprocess.hpp:356
void unsetSolverInterrupt()
Remove the SAT solving interrupt request.
Definition preprocess.hpp:336
PreprocessorStats getPreprocessorStatistics()
Get statistics about the preprocessing.
Definition preprocess.hpp:373
unsigned int getVariablesCount()
Get the current number of variables.
Definition preprocess.hpp:160
void addInitialClauses(const std::vector< simpleClause > &clauses, unsigned int nbVariables)
Add a list of initial clauses to the formula.
Definition preprocess.hpp:350
std::vector< int > getModel() override
Return the model in case of SAT result.
int getDivisionVariable()
Get a variable suitable for search splitting.
Definition preprocess.hpp:379
void diversify(const SeedGenerator &getSeed)
Perform native diversification. The Default lambda returns the solver ID.
Definition preprocess.hpp:371
void addClauses(const std::vector< ClauseExchangePtr > &clauses)
Add a list of permanent clauses to the formula.
Definition preprocess.hpp:382
std::vector< simpleClause > getSimplifiedFormula()
Get the simplified formula after preprocessing.
Definition preprocess.hpp:362
void restoreModel(std::vector< int > &model)
Restore the original model from the preprocessed one.
Definition preprocess.hpp:162
void loadFormula(const char *filename) override
Load formula from a given dimacs file.
Definition preprocess.hpp:63
Definition preprocess.hpp:53