1 /******************************************
2 Copyright (c) 2012 Cheng-Shen Han
3 Copyright (c) 2012 Jie-Hong Roland Jiang
4 Copyright (c) 2018 Mate Soos
5
6 For more information, see " When Boolean Satisfiability Meets Gaussian
7 Elimination in a Simplex Way." by Cheng-Shen Han and Jie-Hong Roland Jiang
8 in CAV (Computer Aided Verification), 2012: 410-426
9
10
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be included in
19 all copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 THE SOFTWARE.
28 ***********************************************/
29
30 #include <algorithm>
31 #include <iomanip>
32 #include <iostream>
33 #include <set>
34
35 #include "gaussian.h"
36 #include "clause.h"
37 #include "clausecleaner.h"
38 #include "datasync.h"
39 #include "propby.h"
40 #include "solver.h"
41 #include "time_mem.h"
42 #include "varreplacer.h"
43 #include "xorfinder.h"
44
45 using std::cout;
46 using std::endl;
47 using std::ostream;
48 using std::set;
49
50 //#define VERBOSE_DEBUG
51 //#define SLOW_DEBUG
52
53 //don't delete gauss watches, but check when propagating and
54 //lazily delete then
55 //#define LAZY_DELETE_HACK
56
57 #ifdef VERBOSE_DEBUG
58 #include <iterator>
59 #endif
60
61 using namespace CMSat;
62
63 // if variable is not in Gaussian matrix , assiag unknown column
64 static const uint32_t unassigned_col = std::numeric_limits<uint32_t>::max();
65
EGaussian(Solver * _solver,const uint32_t _matrix_no,const vector<Xor> & _xorclauses)66 EGaussian::EGaussian(
67 Solver* _solver,
68 const uint32_t _matrix_no,
69 const vector<Xor>& _xorclauses) :
70 xorclauses(_xorclauses),
71 solver(_solver),
72 matrix_no(_matrix_no)
73
74 {
75 }
76
~EGaussian()77 EGaussian::~EGaussian() {
78 delete_gauss_watch_this_matrix();
79 for(auto& x: tofree) {
80 delete[] x;
81 }
82 tofree.clear();
83
84 delete cols_unset;
85 delete cols_vals;
86 delete tmp_col;
87 delete tmp_col2;
88 }
89
90 struct ColSorter {
ColSorterColSorter91 explicit ColSorter(Solver* _solver) :
92 solver(_solver)
93 {
94 for(const auto& ass: solver->assumptions) {
95 Lit p = solver->map_outer_to_inter(ass.lit_outer);
96 if (p.var() < solver->nVars()) {
97 assert(solver->seen.size() > p.var());
98 solver->seen[p.var()] = 1;
99 }
100 }
101 }
102
finishupColSorter103 void finishup()
104 {
105 for(const auto& ass: solver->assumptions) {
106 Lit p = solver->map_outer_to_inter(ass.lit_outer);
107 if (p.var() < solver->nVars()) {
108 solver->seen[p.var()] = 0;
109 }
110 }
111 }
112
operator ()ColSorter113 bool operator()(const uint32_t a, const uint32_t b)
114 {
115 assert(solver->seen.size() > a);
116 assert(solver->seen.size() > b);
117 if (solver->seen[b] && !solver->seen[a]) {
118 return true;
119 }
120
121 if (!solver->seen[b] && solver->seen[a]) {
122 return false;
123 }
124
125 return false;
126 //return solver->varData[a].level < solver->varData[b].level;
127 //return solver->var_act_vsids[a] > solver->var_act_vsids[b];
128 }
129
130 Solver* solver;
131 };
132
select_columnorder()133 uint32_t EGaussian::select_columnorder() {
134 var_to_col.clear();
135 var_to_col.resize(solver->nVars(), unassigned_col);
136 vector<uint32_t> vars_needed;
137 uint32_t largest_used_var = 0;
138
139 for (const Xor& x : xorclauses) {
140 for (const uint32_t v : x) {
141 assert(solver->value(v) == l_Undef);
142 if (var_to_col[v] == unassigned_col) {
143 vars_needed.push_back(v);
144 var_to_col[v] = unassigned_col - 1;
145 largest_used_var = std::max(largest_used_var, v);
146 }
147 }
148 }
149
150 if (vars_needed.size() >= std::numeric_limits<uint32_t>::max() / 2 - 1) {
151 if (solver->conf.verbosity) {
152 cout << "c Matrix has too many columns, exiting select_columnorder" << endl;
153 }
154
155 return 0;
156 }
157 if (xorclauses.size() >= std::numeric_limits<uint32_t>::max() / 2 - 1) {
158 if (solver->conf.verbosity) {
159 cout << "c Matrix has too many rows, exiting select_columnorder" << endl;
160 }
161 return 0;
162 }
163 var_to_col.resize(largest_used_var + 1);
164
165
166 ColSorter c(solver);
167 std::sort(vars_needed.begin(), vars_needed.end(),c);
168 c.finishup();
169
170 #ifdef COL_ORDER_DEBUG_VERBOSE_DEBUG
171 cout << "col order: " << endl;
172 for(auto& x: vars_needed) {
173 bool assump = false;
174 for(const auto& ass: solver->assumptions) {
175 if (solver->map_outer_to_inter(ass.lit_outer).var() == x) {
176 assump = true;
177 }
178 }
179 cout << "assump:" << (int)assump
180 << " act: " << std::setprecision(2) << std::scientific
181 << solver->var_act_vsids[x] << std::fixed
182 << " level: " << solver->varData[x].level
183 << endl;
184 }
185 #endif
186
187
188 col_to_var.clear();
189 for (uint32_t v : vars_needed) {
190 assert(var_to_col[v] == unassigned_col - 1);
191 col_to_var.push_back(v);
192 var_to_col[v] = col_to_var.size() - 1;
193 }
194
195 // for the ones that were not in the order_heap, but are marked in var_to_col
196 for (uint32_t v = 0; v != var_to_col.size(); v++) {
197 if (var_to_col[v] == unassigned_col - 1) {
198 // assert(false && "order_heap MUST be complete!");
199 col_to_var.push_back(v);
200 var_to_col[v] = col_to_var.size() - 1;
201 }
202 }
203
204 #ifdef VERBOSE_DEBUG_MORE
205 cout << "(" << matrix_no << ") num_xorclauses: " << num_xorclauses << endl;
206 cout << "(" << matrix_no << ") col_to_var: ";
207 std::copy(col_to_var.begin(), col_to_var.end(),
208 std::ostream_iterator<uint32_t>(cout, ","));
209 cout << endl;
210 cout << "num_cols:" << num_cols << endl;
211 cout << "col is set:" << endl;
212 std::copy(col_is_set.begin(), col_is_set.end(),
213 std::ostream_iterator<char>(cout, ","));
214 #endif
215
216 return xorclauses.size();
217 }
218
fill_matrix()219 void EGaussian::fill_matrix() {
220 var_to_col.clear();
221
222 // decide which variable in matrix column and the number of rows
223 num_rows = select_columnorder();
224 num_cols = col_to_var.size();
225 if (num_rows == 0 || num_cols == 0) {
226 return;
227 }
228 mat.resize(num_rows, num_cols); // initial gaussian matrix
229
230 uint32_t matrix_row = 0;
231 for (uint32_t i = 0; i != xorclauses.size(); i++) {
232 const Xor& c = xorclauses[i];
233 mat[matrix_row].set(c, var_to_col, num_cols);
234 matrix_row++;
235 }
236 assert(num_rows == matrix_row);
237
238 // reset
239 var_has_resp_row.clear();
240 var_has_resp_row.resize(solver->nVars(), 0);
241 row_to_var_non_resp.clear();
242
243 delete_gauss_watch_this_matrix();
244
245 //reset satisfied_xor state
246 assert(solver->decisionLevel() == 0);
247 satisfied_xors.clear();
248 satisfied_xors.resize(num_rows, 0);
249 }
250
delete_gauss_watch_this_matrix()251 void EGaussian::delete_gauss_watch_this_matrix()
252 {
253 for (size_t ii = 0; ii < solver->gwatches.size(); ii++) {
254 clear_gwatches(ii);
255 }
256 }
257
clear_gwatches(const uint32_t var)258 void EGaussian::clear_gwatches(const uint32_t var)
259 {
260 //if there is only one matrix, don't check, just empty it
261 if (solver->gmatrices.size() == 0) {
262 solver->gwatches[var].clear();
263 return;
264 }
265
266 GaussWatched* i = solver->gwatches[var].begin();
267 GaussWatched* j = i;
268 for(GaussWatched* end = solver->gwatches[var].end(); i != end; i++) {
269 if (i->matrix_num != matrix_no) {
270 *j++ = *i;
271 }
272 }
273 solver->gwatches[var].shrink(i-j);
274 }
275
clean_xors()276 bool EGaussian::clean_xors()
277 {
278 for(Xor& x: xorclauses) {
279 solver->clean_xor_vars_no_prop(x.get_vars(), x.rhs);
280 }
281 XorFinder f(NULL, solver);
282 if (!f.add_new_truths_from_xors(xorclauses))
283 return false;
284
285 return true;
286 }
287
full_init(bool & created)288 bool EGaussian::full_init(bool& created) {
289 assert(solver->ok);
290 assert(solver->decisionLevel() == 0);
291 bool do_again_gauss = true;
292 created = true;
293 if (!clean_xors()) {
294 return false;
295 }
296
297 while (do_again_gauss) {
298 do_again_gauss = false;
299
300 if (!solver->clauseCleaner->clean_xor_clauses(xorclauses)) {
301 return false;
302 }
303
304 fill_matrix();
305 before_init_density = get_density();
306 if (num_rows == 0 || num_cols == 0) {
307 created = false;
308 return solver->okay();
309 }
310
311 eliminate();
312
313 // find some row already true false, and insert watch list
314 gret ret = adjust_matrix();
315
316 switch (ret) {
317 case gret::confl:
318 solver->ok = false;
319 return false;
320 break;
321 case gret::prop:
322 do_again_gauss = true;
323
324 assert(solver->decisionLevel() == 0);
325 solver->ok = (solver->propagate<false>().isNULL());
326 if (!solver->ok) {
327 return false;
328 }
329 break;
330 default:
331 break;
332 }
333 }
334
335 #ifdef SLOW_DEBUG
336 check_watchlist_sanity();
337 #endif
338
339 if (solver->conf.verbosity >= 2) {
340 cout << "c [gauss] initialised matrix " << matrix_no << endl;
341 }
342
343 xor_reasons.resize(num_rows);
344 uint32_t num_64b = num_cols/64+(bool)(num_cols%64);
345 for(auto& x: tofree) {
346 delete[] x;
347 }
348 tofree.clear();
349 delete cols_unset;
350 delete cols_vals;
351 delete tmp_col;
352 delete tmp_col2;
353
354 int64_t* x = new int64_t[num_64b+1];
355 tofree.push_back(x);
356 cols_unset = new PackedRow(num_64b, x);
357
358 x = new int64_t[num_64b+1];
359 tofree.push_back(x);
360 cols_vals = new PackedRow(num_64b, x);
361
362 x = new int64_t[num_64b+1];
363 tofree.push_back(x);
364 tmp_col = new PackedRow(num_64b, x);
365
366 x = new int64_t[num_64b+1];
367 tofree.push_back(x);
368 tmp_col2 = new PackedRow(num_64b, x);
369
370 cols_vals->rhs() = 0;
371 cols_unset->rhs() = 0;
372 tmp_col->rhs() = 0;
373 tmp_col2->rhs() = 0;
374 after_init_density = get_density();
375
376 update_cols_vals_set(true);
377 #ifdef SLOW_DEBUG
378 check_invariants();
379 #endif
380
381
382 return true;
383 }
384
eliminate()385 void EGaussian::eliminate() {
386 uint32_t row = 0;
387 uint32_t col = 0;
388 PackedMatrix::iterator end_row_it = mat.begin() + num_rows;
389 PackedMatrix::iterator row_i = mat.begin();
390
391 // Gauss-Jordan Elimination
392 while (row != num_rows && col != num_cols) {
393 PackedMatrix::iterator row_with_1_in_col = row_i;
394
395 //Find first "1" in column.
396 for (; row_with_1_in_col != end_row_it; ++row_with_1_in_col) {
397 if ((*row_with_1_in_col)[col]) {
398 break;
399 }
400 }
401
402 //We have found a "1" in this column
403 if (row_with_1_in_col != end_row_it) {
404 //cout << "col zeroed:" << col << " var is: " << col_to_var[col] + 1 << endl;
405 var_has_resp_row[col_to_var[col]] = 1;
406
407 // swap row row_with_1_in_col and rowIt
408 if (row_with_1_in_col != row_i) {
409 (*row_i).swapBoth(*row_with_1_in_col);
410 }
411
412 // XOR into *all* rows that have a "1" in column COL
413 // Since we XOR into *all*, this is Gauss-Jordan (and not just Gauss)
414 for (PackedMatrix::iterator k_row = mat.begin()
415 ; k_row != end_row_it
416 ; ++k_row
417 ) {
418 // xor rows K and I
419 if (k_row != row_i) {
420 if ((*k_row)[col]) {
421 (*k_row).xor_in(*row_i);
422 }
423 }
424 }
425 row++;
426 ++row_i;
427 }
428 col++;
429 }
430 //print_matrix();
431 }
432
adjust_matrix()433 gret EGaussian::adjust_matrix()
434 {
435 assert(solver->decisionLevel() == 0);
436 assert(row_to_var_non_resp.empty());
437 assert(satisfied_xors.size() >= num_rows);
438 #ifdef VERBOSE_DEBUG
439 cout << "mat[" << matrix_no << "] adjusting matrix" << endl;
440 #endif
441
442 PackedMatrix::iterator end = mat.begin() + num_rows;
443 PackedMatrix::iterator rowIt = mat.begin();
444 uint32_t row_n = 0; // row index
445 uint32_t adjust_zero = 0; // elimination row
446
447 while (rowIt != end) {
448 uint32_t non_resp_var;
449 const uint32_t popcnt = (*rowIt).find_watchVar(
450 tmp_clause, col_to_var, var_has_resp_row, non_resp_var);
451
452 switch (popcnt) {
453
454 //Conflict or satisfied
455 case 0:
456 // printf("%d:Warning: this row is all zero in adjust matrix n",row_id);
457 adjust_zero++;
458
459 // conflict
460 if ((*rowIt).rhs()) {
461 // printf("%d:Warring: this row is conflict in adjust matrix!!!",row_id);
462 #ifdef VERBOSE_DEBUG
463 cout << "-> conflict on row: " << row_n << endl;
464 #endif
465 return gret::confl;
466 }
467 #ifdef VERBOSE_DEBUG
468 cout << "-> empty on this row. " << endl;
469 cout << "-> Satisfied XORs set for row: " << row_n << endl;
470 #endif
471 satisfied_xors[row_n] = 1;
472 break;
473
474 //Normal propagation
475 case 1:
476 {
477 // printf("%d:This row only one variable, need to propogation!!!! in adjust matrix
478 // n",row_id);
479
480 bool xorEqualFalse = !mat[row_n].rhs();
481 tmp_clause[0] = Lit(tmp_clause[0].var(), xorEqualFalse);
482 assert(solver->value(tmp_clause[0].var()) == l_Undef);
483 solver->enqueue(tmp_clause[0]); // propagation
484
485 #ifdef VERBOSE_DEBUG
486 cout << "-> Propagation for " << tmp_clause[0] << endl;
487 cout << "-> Satisfied XORs set for row: " << row_n << endl;
488 #endif
489 satisfied_xors[row_n] = 1;
490 #ifdef SLOW_DEBUG
491 assert(check_row_satisfied(row_n));
492 #endif
493
494 //adjusting
495 (*rowIt).setZero(); // reset this row all zero
496 row_to_var_non_resp.push_back(std::numeric_limits<uint32_t>::max());
497 var_has_resp_row[tmp_clause[0].var()] = 0;
498 return gret::prop;
499 }
500
501 //Binary XOR
502 case 2: {
503 // printf("%d:This row have two variable!!!! in adjust matrix n",row_id);
504 bool xorEqualFalse = !mat[row_n].rhs();
505
506 tmp_clause[0] = tmp_clause[0].unsign();
507 tmp_clause[1] = tmp_clause[1].unsign();
508 solver->ok = solver->add_xor_clause_inter(tmp_clause, !xorEqualFalse, true);
509 release_assert(solver->ok);
510
511 #ifdef VERBOSE_DEBUG
512 cout << "-> bin-xor on row: " << row_n << endl;
513 #endif
514
515 // reset this row all zero, no need for this row
516 (*rowIt).rhs() = 0;
517 (*rowIt).setZero();
518
519 row_to_var_non_resp.push_back(std::numeric_limits<uint32_t>::max()); // delete non-basic value in this row
520 var_has_resp_row[tmp_clause[0].var()] = 0; // delete basic value in this row
521 break;
522 }
523
524 default: // need to update watch list
525 // printf("%d:need to update watch list n",row_id);
526 assert(non_resp_var != std::numeric_limits<uint32_t>::max());
527
528 // insert watch list
529 #ifdef VERBOSE_DEBUG
530 cout << "-> watch 1: resp var " << tmp_clause[0].var()+1 << "for row " << row_n << endl;
531 cout << "-> watch 2: non-resp var " << non_resp_var+1 << "for row " << row_n << endl;
532 #endif
533 solver->gwatches[tmp_clause[0].var()].push(
534 GaussWatched(row_n, matrix_no)); // insert basic variable
535
536 solver->gwatches[non_resp_var].push(
537 GaussWatched(row_n, matrix_no)); // insert non-basic variable
538 row_to_var_non_resp.push_back(non_resp_var); // record in this row non-basic variable
539 break;
540 }
541 ++rowIt;
542 row_n++;
543 }
544 // printf("DD:nb_rows:%d %d %d n",nb_rows.size() , row_n - adjust_zero , adjust_zero);
545 assert(row_to_var_non_resp.size() == row_n - adjust_zero);
546
547 mat.resizeNumRows(row_n - adjust_zero);
548 num_rows = row_n - adjust_zero;
549
550 return gret::nothing_satisfied;
551 }
552
553 // Delete this row because we have already add to xor clause, nothing to do anymore
delete_gausswatch(const uint32_t row_n)554 void EGaussian::delete_gausswatch(
555 const uint32_t row_n
556 ) {
557 // clear nonbasic value watch list
558 bool debug_find = false;
559 vec<GaussWatched>& ws_t = solver->gwatches[row_to_var_non_resp[row_n]];
560
561 for (int32_t tmpi = ws_t.size() - 1; tmpi >= 0; tmpi--) {
562 if (ws_t[tmpi].row_n == row_n
563 && ws_t[tmpi].matrix_num == matrix_no
564 ) {
565 ws_t[tmpi] = ws_t.last();
566 ws_t.shrink(1);
567 debug_find = true;
568 break;
569 }
570 }
571 #ifdef VERBOSE_DEBUG
572 cout
573 << "mat[" << matrix_no << "] "
574 << "Tried cleaning watch of var: "
575 << row_to_var_non_resp[row_n]+1 << endl;
576 #endif
577 assert(debug_find);
578 }
579
get_max_level(const GaussQData & gqd,const uint32_t row_n)580 uint32_t EGaussian::get_max_level(const GaussQData& gqd, const uint32_t row_n)
581 {
582 auto cl = get_reason(row_n);
583 uint32_t nMaxLevel = gqd.currLevel;
584 uint32_t nMaxInd = 1;
585
586 for (uint32_t i = 1; i < cl->size(); i++) {
587 Lit l = (*cl)[i];
588 uint32_t nLevel = solver->varData[l.var()].level;
589 if (nLevel > nMaxLevel) {
590 nMaxLevel = nLevel;
591 nMaxInd = i;
592 }
593 }
594
595 //should we??
596 if (nMaxInd != 1) {
597 std::swap((*cl)[1], (*cl)[nMaxInd]);
598 }
599 return nMaxLevel;
600 }
601
find_truths(GaussWatched * & i,GaussWatched * & j,const uint32_t var,const uint32_t row_n,GaussQData & gqd)602 bool EGaussian::find_truths(
603 GaussWatched*& i,
604 GaussWatched*& j,
605 const uint32_t var,
606 const uint32_t row_n,
607 GaussQData& gqd
608 ) {
609 assert(gqd.ret != gauss_res::confl);
610 #ifdef LAZY_DELETE_HACK
611 if (!mat[row_n][var_to_col[var]]) {
612 //lazy delete
613 return true;
614 }
615 #endif
616 // printf("dd Watch variable : %d , Wathch row num %d n", p , row_n);
617
618 #ifdef VERBOSE_DEBUG
619 cout << "mat[" << matrix_no << "] find_truths" << endl;
620 cout << "-> row: " << row_n << endl;
621 cout << "-> var: " << var+1 << endl;
622 cout << "-> dec lev:" << solver->decisionLevel() << endl;
623 #endif
624 #ifdef SLOW_DEBUG
625 assert(row_n < num_rows);
626 assert(satisfied_xors.size() > row_n);
627 #endif
628
629 // this XOR is already satisfied
630 if (satisfied_xors[row_n]) {
631 #ifdef VERBOSE_DEBUG
632 cout << "-> xor satisfied as per satisfied_xors[row_n]" << endl;
633 #endif
634 #ifdef SLOW_DEBUG
635 assert(check_row_satisfied(row_n));
636 #endif
637 *j++ = *i;
638 find_truth_ret_satisfied_precheck++;
639 return true;
640 }
641
642
643 // swap resp and non-resp variable
644 bool was_resp_var = false;
645 if (var_has_resp_row[var] == 1) {
646 //var has a responsible row, so THIS row must be it!
647 //since if a var has a responsible row, only ONE row can have a 1 there
648 was_resp_var = true;
649 var_has_resp_row[row_to_var_non_resp[row_n]] = 1;
650 var_has_resp_row[var] = 0;
651 }
652
653 uint32_t new_resp_var;
654 Lit ret_lit_prop;
655 #ifdef SLOW_DEBUG
656 check_cols_unset_vals();
657 #endif
658 const gret ret = mat[row_n].propGause(
659 solver->assigns,
660 col_to_var,
661 var_has_resp_row,
662 new_resp_var,
663 *tmp_col,
664 *tmp_col2,
665 *cols_vals,
666 *cols_unset,
667 ret_lit_prop);
668 find_truth_called_propgause++;
669
670 switch (ret) {
671 case gret::confl: {
672 find_truth_ret_confl++;
673 *j++ = *i;
674
675 xor_reasons[row_n].must_recalc = true;
676 xor_reasons[row_n].propagated = lit_Undef;
677 gqd.confl = PropBy(matrix_no, row_n);
678 gqd.ret = gauss_res::confl;
679 #ifdef VERBOSE_DEBUG
680 cout
681 << "--> conflict" << endl;
682 #endif
683
684 if (was_resp_var) { // recover
685 var_has_resp_row[row_to_var_non_resp[row_n]] = 0;
686 var_has_resp_row[var] = 1;
687 }
688
689 return false;
690 }
691
692 case gret::prop: {
693 find_truth_ret_prop++;
694 #ifdef VERBOSE_DEBUG
695 cout
696 << "--> propagation" << endl;
697 #endif
698 *j++ = *i;
699
700
701 xor_reasons[row_n].must_recalc = true;
702 xor_reasons[row_n].propagated = ret_lit_prop;
703 assert(solver->value(ret_lit_prop.var()) == l_Undef);
704 if (gqd.currLevel == solver->decisionLevel()) {
705 solver->enqueue(ret_lit_prop, gqd.currLevel, PropBy(matrix_no, row_n));
706 } else {
707 uint32_t nMaxLevel = get_max_level(gqd, row_n);
708 solver->enqueue(ret_lit_prop, nMaxLevel, PropBy(matrix_no, row_n));
709 }
710 update_cols_vals_set(ret_lit_prop);
711 gqd.ret = gauss_res::prop;
712
713 if (was_resp_var) { // recover
714 var_has_resp_row[row_to_var_non_resp[row_n]] = 0;
715 var_has_resp_row[var] = 1;
716 }
717
718 #ifdef VERBOSE_DEBUG
719 cout << "--> Satisfied XORs set for row: " << row_n << endl;
720 #endif
721 satisfied_xors[row_n] = 1;
722 #ifdef SLOW_DEBUG
723 assert(check_row_satisfied(row_n));
724 #endif
725 return true;
726 }
727
728 // find new watch list
729 case gret::nothing_fnewwatch:
730 #ifdef VERBOSE_DEBUG
731 cout
732 << "--> found new watch: " << new_resp_var+1 << endl;
733 #endif
734
735 find_truth_ret_fnewwatch++;
736 // printf("%d:This row is find new watch:%d => orig %d p:%d n",row_n ,
737 // new_resp_var,orig_basic , p);
738
739 if (was_resp_var) {
740 /// clear watchlist, because only one responsible value in watchlist
741 assert(new_resp_var != var);
742 clear_gwatches(new_resp_var);
743 #ifdef VERBOSE_DEBUG
744 cout << "Cleared watchlist for new resp var: " << new_resp_var+1 << endl;
745 cout << "After clear..."; print_gwatches(new_resp_var);
746 #endif
747 }
748 assert(new_resp_var != var);
749 #ifdef SLOW_DEBUG
750 #ifdef VERBOSE_DEBUG
751 print_gwatches(new_resp_var);
752 #endif
753 check_row_not_in_watch(new_resp_var, row_n);
754 #endif
755 solver->gwatches[new_resp_var].push(GaussWatched(row_n, matrix_no));
756
757 if (was_resp_var) {
758 //it was the responsible one, so the newly watched var
759 //is the new column it's responsible for
760 //so elimination will be needed
761
762 //clear old one, add new resp
763 var_has_resp_row[row_to_var_non_resp[row_n]] = 0;
764 var_has_resp_row[new_resp_var] = 1;
765
766 // store the eliminate variable & row
767 gqd.new_resp_var = new_resp_var;
768 gqd.new_resp_row = row_n;
769 if (solver->gmatrices.size() == 1) {
770 assert(solver->gwatches[gqd.new_resp_var].size() == 1);
771 }
772 gqd.do_eliminate = true;
773 return true;
774 } else {
775 row_to_var_non_resp[row_n] = new_resp_var;
776 return true;
777 }
778
779 // this row already true
780 case gret::nothing_satisfied:
781 #ifdef VERBOSE_DEBUG
782 cout
783 << "--> satisfied" << endl;
784 #endif
785
786 find_truth_ret_satisfied++;
787 // printf("%d:This row is nothing( maybe already true) n",row_n);
788 *j++ = *i;
789 if (was_resp_var) { // recover
790 var_has_resp_row[row_to_var_non_resp[row_n]] = 0;
791 var_has_resp_row[var] = 1;
792 }
793
794 #ifdef VERBOSE_DEBUG
795 cout << "--> Satisfied XORs set for row: " << row_n << endl;
796 #endif
797 satisfied_xors[row_n] = 1;
798 #ifdef SLOW_DEBUG
799 assert(check_row_satisfied(row_n));
800 #endif
801 return true;
802
803 //error here
804 default:
805 assert(false); // cannot be here
806 break;
807 }
808
809 assert(false);
810 return true;
811 }
812
update_cols_vals_set(const Lit lit1)813 inline void EGaussian::update_cols_vals_set(const Lit lit1)
814 {
815 cols_unset->clearBit(var_to_col[lit1.var()]);
816 if (!lit1.sign()) {
817 cols_vals->setBit(var_to_col[lit1.var()]);
818 }
819 }
820
update_cols_vals_set(bool force)821 void EGaussian::update_cols_vals_set(bool force)
822 {
823 //cancelled_since_val_update = true;
824 if (cancelled_since_val_update || force) {
825 cols_vals->setZero();
826 cols_unset->setOne();
827
828 for(uint32_t col = 0; col < col_to_var.size(); col++) {
829 uint32_t var = col_to_var[col];
830 if (solver->value(var) != l_Undef) {
831 cols_unset->clearBit(col);
832 if (solver->value(var) == l_True) {
833 cols_vals->setBit(col);
834 }
835 }
836 }
837 last_val_update = solver->trail.size();
838 cancelled_since_val_update = false;
839 return;
840 }
841
842 assert(solver->trail.size() >= last_val_update);
843 for(uint32_t i = last_val_update; i < solver->trail.size(); i++) {
844 uint32_t var = solver->trail[i].lit.var();
845 if (var_to_col.size() <= var) {
846 continue;
847 }
848 uint32_t col = var_to_col[var];
849 if (col != unassigned_col) {
850 assert (solver->value(var) != l_Undef);
851 cols_unset->clearBit(col);
852 if (solver->value(var) == l_True) {
853 cols_vals->setBit(col);
854 }
855 }
856 }
857 last_val_update = solver->trail.size();
858 }
859
eliminate_col(uint32_t p,GaussQData & gqd)860 void EGaussian::eliminate_col(uint32_t p, GaussQData& gqd) {
861 PackedMatrix::iterator new_resp_row = mat.begin() + gqd.new_resp_row;
862 PackedMatrix::iterator rowI = mat.begin();
863 PackedMatrix::iterator end = mat.end();
864 const uint32_t new_resp_col = var_to_col[gqd.new_resp_var];
865 uint32_t row_n = 0;
866
867 #ifdef VERBOSE_DEBUG
868 cout
869 << "mat[" << matrix_no << "] "
870 << "** eliminating this column: " << new_resp_col << endl
871 << "-> row that will be the SOLE one having a 1: " << gqd.new_resp_row << endl
872 << "-> var associated with col: " << gqd.new_resp_var+1
873 << endl;
874 #endif
875 elim_called++;
876
877 while (rowI != end) {
878 //Row has a '1' in eliminating column, and it's not the row responsible
879 if (new_resp_row != rowI && (*rowI)[new_resp_col]) {
880
881 // detect orignal non-basic watch list change or not
882 uint32_t orig_non_resp_var = row_to_var_non_resp[row_n];
883 uint32_t orig_non_resp_col = var_to_col[orig_non_resp_var];
884 assert((*rowI)[orig_non_resp_col]);
885 #ifdef VERBOSE_DEBUG
886 cout
887 << "--> This row " << row_n
888 << " is being watched on var: " << orig_non_resp_var + 1
889 << " i.e. it must contain '1' for this var's column"
890 << endl;
891 #endif
892
893 assert(satisfied_xors[row_n] == 0);
894 (*rowI).xor_in(*new_resp_row);
895 elim_xored_rows++;
896
897 //NOTE: responsible variable cannot be eliminated of course
898 // (it's the only '1' in that column).
899 // But non-responsible can be eliminated. So let's check that
900 // and then deal with it if we have to
901 if (!(*rowI)[orig_non_resp_col]) {
902
903 #ifdef VERBOSE_DEBUG
904 cout
905 << "--> This row " << row_n
906 << " can no longer be watched (non-responsible), it has no '1' at col " << orig_non_resp_col
907 << " (var " << col_to_var[orig_non_resp_col]+1 << ")"
908 << " fixing up..."<< endl;
909 #endif
910
911 // Delete orignal non-responsible var from watch list
912 if (orig_non_resp_var != gqd.new_resp_var) {
913 #ifndef LAZY_DELETE_HACK
914 delete_gausswatch(row_n);
915 #endif
916 } else {
917 //this does not need a delete, because during
918 //find_truths, we already did clear_gwatches of the
919 //orig_non_resp_var, so there is nothing to delete here
920 }
921
922 Lit ret_lit_prop;
923 uint32_t new_non_resp_var = 0;
924 #ifdef SLOW_DEBUG
925 check_cols_unset_vals();
926 #endif
927 const gret ret = (*rowI).propGause(
928 solver->assigns,
929 col_to_var,
930 var_has_resp_row,
931 new_non_resp_var,
932 *tmp_col,
933 *tmp_col2,
934 *cols_vals,
935 *cols_unset,
936 ret_lit_prop
937 );
938 elim_called_propgause++;
939
940 switch (ret) {
941 case gret::confl: {
942 elim_ret_confl++;
943 #ifdef VERBOSE_DEBUG
944 cout
945 << "---> conflict during fixup"<< endl;
946 #endif
947
948 solver->gwatches[p].push(
949 GaussWatched(row_n, matrix_no));
950
951 // update in this row non-basic variable
952 row_to_var_non_resp[row_n] = p;
953
954 xor_reasons[row_n].must_recalc = true;
955 xor_reasons[row_n].propagated = lit_Undef;
956 gqd.confl = PropBy(matrix_no, row_n);
957 gqd.ret = gauss_res::confl;
958 break;
959 }
960 case gret::prop: {
961 elim_ret_prop++;
962 #ifdef VERBOSE_DEBUG
963 cout
964 << "---> propagation during fixup" << endl;
965 #endif
966
967 // if conflicted already, just update non-basic variable
968 if (gqd.ret == gauss_res::confl) {
969 #ifdef SLOW_DEBUG
970 check_row_not_in_watch(p, row_n);
971 #endif
972 solver->gwatches[p].push(GaussWatched(row_n, matrix_no));
973 row_to_var_non_resp[row_n] = p;
974 break;
975 }
976
977 // update no_basic information
978 #ifdef SLOW_DEBUG
979 check_row_not_in_watch(p, row_n);
980 #endif
981 solver->gwatches[p].push(GaussWatched(row_n, matrix_no));
982 row_to_var_non_resp[row_n] = p;
983
984 xor_reasons[row_n].must_recalc = true;
985 xor_reasons[row_n].propagated = ret_lit_prop;
986 assert(solver->value(ret_lit_prop.var()) == l_Undef);
987 if (gqd.currLevel == solver->decisionLevel()) {
988 solver->enqueue(ret_lit_prop, gqd.currLevel, PropBy(matrix_no, row_n));
989 } else {
990 uint32_t nMaxLevel = get_max_level(gqd, row_n);
991 solver->enqueue(ret_lit_prop, nMaxLevel, PropBy(matrix_no, row_n));
992 }
993 update_cols_vals_set(ret_lit_prop);
994 gqd.ret = gauss_res::prop;
995
996 #ifdef VERBOSE_DEBUG
997 cout << "---> Satisfied XORs set for row: " << row_n << endl;
998 #endif
999 satisfied_xors[row_n] = 1;
1000 #ifdef SLOW_DEBUG
1001 assert(check_row_satisfied(row_n));
1002 #endif
1003 break;
1004 }
1005
1006 // find new watch list
1007 case gret::nothing_fnewwatch:
1008 elim_ret_fnewwatch++;
1009 #ifdef VERBOSE_DEBUG
1010 cout
1011 << "---> Nothing, clause NOT already satisfied, pushing in "
1012 << new_non_resp_var+1 << " as non-responsible var ( "
1013 << row_n << " row) "
1014 << endl;
1015 #endif
1016
1017 #ifdef SLOW_DEBUG
1018 check_row_not_in_watch(new_non_resp_var, row_n);
1019 #endif
1020 solver->gwatches[new_non_resp_var].push(GaussWatched(row_n, matrix_no));
1021 row_to_var_non_resp[row_n] = new_non_resp_var;
1022 break;
1023
1024 // this row already satisfied
1025 case gret::nothing_satisfied:
1026 elim_ret_satisfied++;
1027 #ifdef VERBOSE_DEBUG
1028 cout
1029 << "---> Nothing to do, already satisfied , pushing in "
1030 << p+1 << " as non-responsible var ( "
1031 << row_n << " row) "
1032 << endl;
1033 #endif
1034
1035 // printf("%d:This row is nothing( maybe already true) in eliminate col
1036 // n",num_row);
1037
1038 #ifdef SLOW_DEBUG
1039 check_row_not_in_watch(p, row_n);
1040 #endif
1041 solver->gwatches[p].push(GaussWatched(row_n, matrix_no));
1042 row_to_var_non_resp[row_n] = p;
1043
1044 #ifdef VERBOSE_DEBUG
1045 cout << "---> Satisfied XORs set for row: " << row_n << endl;
1046 #endif
1047 satisfied_xors[row_n] = 1;
1048 #ifdef SLOW_DEBUG
1049 assert(check_row_satisfied(row_n));
1050 #endif
1051 break;
1052 default:
1053 // can not here
1054 assert(false);
1055 break;
1056 }
1057 } else {
1058 #ifdef VERBOSE_DEBUG
1059 cout
1060 << "--> OK, this row " << row_n
1061 << " still contains '1', can still be responsible" << endl;
1062 #endif
1063 }
1064 }
1065 ++rowI;
1066 row_n++;
1067 }
1068
1069 // Debug_funtion();
1070 #ifdef VERBOSE_DEBUG
1071 cout
1072 << "mat[" << matrix_no << "] "
1073 << "eliminate_col - exiting. " << endl;
1074 #endif
1075 }
1076
print_matrix()1077 void EGaussian::print_matrix() {
1078 uint32_t row = 0;
1079 for (PackedMatrix::iterator it = mat.begin(); it != mat.end();
1080 ++it, row++) {
1081 cout << *it << " -- row:" << row;
1082 if (row >= num_rows) {
1083 cout << " (considered past the end)";
1084 }
1085 cout << endl;
1086 }
1087 }
1088
print_matrix_stats(uint32_t verbosity)1089 void EGaussian::print_matrix_stats(uint32_t verbosity)
1090 {
1091 std::stringstream ss;
1092 ss << "c [g " << matrix_no << "] ";
1093 const std::string pre = ss.str();
1094
1095 cout << std::left;
1096
1097 if (verbosity >= 2) {
1098 cout << pre << "truth-find satisfied : "
1099 << print_value_kilo_mega(find_truth_ret_satisfied_precheck, false) << endl;
1100 }
1101
1102 if (verbosity >= 1) {
1103 cout << pre << "truth-find prop checks : "
1104 << print_value_kilo_mega(find_truth_called_propgause, false) << endl;
1105 }
1106
1107
1108 if (verbosity >= 2) {
1109 cout << pre << "-> of which fnnewat : "
1110 << std::setw(5) << std::setprecision(2) << std::right
1111 << stats_line_percent(find_truth_ret_fnewwatch, find_truth_called_propgause)
1112 << " %"
1113 << endl;
1114 cout << pre << "-> of which sat : "
1115 << std::setw(5) << std::setprecision(2) << std::right
1116 << stats_line_percent(find_truth_ret_satisfied, find_truth_called_propgause)
1117 << " %"
1118 << endl;
1119 }
1120
1121 if (verbosity >= 1) {
1122 cout << pre << "-> of which prop : "
1123 << std::setw(5) << std::setprecision(2) << std::right
1124 << stats_line_percent(find_truth_ret_prop, find_truth_called_propgause)
1125 << " %"
1126 << endl;
1127 cout << pre << "-> of which confl : "
1128 << std::setw(5) << std::setprecision(2) << std::right
1129 << stats_line_percent(find_truth_ret_confl, find_truth_called_propgause)
1130 << " %"
1131 << endl;
1132 }
1133
1134 cout << std::left;
1135 cout << pre << "elim called : "
1136 << print_value_kilo_mega(elim_called, false) << endl;
1137
1138 if (verbosity >= 2) {
1139 cout << pre << "-> lead to xor rows : "
1140 << print_value_kilo_mega(elim_xored_rows, false) << endl;
1141
1142 cout << pre << "--> lead to prop checks : "
1143 << print_value_kilo_mega(elim_called_propgause, false) << endl;
1144
1145 cout << pre << "---> of which satsified : "
1146 << std::setw(5) << std::setprecision(2) << std::right
1147 << stats_line_percent(elim_ret_satisfied, elim_called_propgause)
1148 << " %"
1149 << endl;
1150
1151 cout << pre << "---> of which prop : "
1152 << std::setw(5) << std::setprecision(2) << std::right
1153 << stats_line_percent(elim_ret_prop, elim_called_propgause)
1154 << " %"
1155 << endl;
1156
1157 cout << pre << "---> of which fnnewat : "
1158 << std::setw(5) << std::setprecision(2) << std::right
1159 << stats_line_percent(elim_ret_fnewwatch, elim_called_propgause)
1160 << " %"
1161 << endl;
1162
1163 cout << pre << "---> of which confl : "
1164 << std::setw(5) << std::setprecision(2) << std::right
1165 << stats_line_percent(elim_ret_confl, elim_called_propgause)
1166 << " %"
1167 << endl;
1168 }
1169
1170 if (verbosity == 1) {
1171 cout << pre << "---> which lead to prop : "
1172 << std::setw(5) << std::setprecision(2) << std::right
1173 << stats_line_percent(elim_ret_prop, elim_called)
1174 << " %"
1175 << endl;
1176
1177 cout << pre << "---> which lead to confl: "
1178 << std::setw(5) << std::setprecision(2) << std::right
1179 << stats_line_percent(elim_ret_confl, elim_called)
1180 << " %"
1181 << endl;
1182 }
1183
1184 cout << std::left;
1185 cout << pre << "size: "
1186 << std::setw(5) << num_rows << " x "
1187 << std::setw(5) << num_cols << endl;
1188
1189 double density = get_density();
1190
1191 if (verbosity >= 2) {
1192 cout << pre << "density before init: "
1193 << std::setprecision(4) << std::left << before_init_density
1194 << endl;
1195 cout << pre << "density after init: "
1196 << std::setprecision(4) << std::left << after_init_density
1197 << endl;
1198 cout << pre << "density : "
1199 << std::setprecision(4) << std::left << density
1200 << endl;
1201 }
1202 cout << std::setprecision(2);
1203 }
1204
get_reason(uint32_t row)1205 vector<Lit>* EGaussian::get_reason(uint32_t row)
1206 {
1207 if (!xor_reasons[row].must_recalc) {
1208 return &(xor_reasons[row].reason);
1209 }
1210 vector<Lit>& tofill = xor_reasons[row].reason;
1211 tofill.clear();
1212
1213 mat[row].get_reason(
1214 tofill,
1215 solver->assigns,
1216 col_to_var,
1217 *cols_vals,
1218 *tmp_col2,
1219 xor_reasons[row].propagated);
1220
1221 xor_reasons[row].must_recalc = false;
1222 return &tofill;
1223 }
1224
1225 //////////////////
1226 // Checking functions below
1227 //////////////////
1228
check_row_not_in_watch(const uint32_t v,const uint32_t row_num) const1229 void EGaussian::check_row_not_in_watch(const uint32_t v, const uint32_t row_num) const
1230 {
1231 for(const auto& x: solver->gwatches[v]) {
1232 if (x.matrix_num == matrix_no && x.row_n == row_num) {
1233 cout << "OOOps, row ID " << row_num << " already in watch for var: " << v+1 << endl;
1234 assert(false);
1235 }
1236 }
1237 }
1238
print_gwatches(const uint32_t var) const1239 void EGaussian::print_gwatches(const uint32_t var) const
1240 {
1241 vec<GaussWatched> mycopy;
1242 for(const auto& x: solver->gwatches[var]) {
1243 mycopy.push(x);
1244 }
1245
1246 std::sort(mycopy.begin(), mycopy.end());
1247 cout << "Watch for var " << var+1 << ": ";
1248 for(const auto& x: mycopy) {
1249 cout
1250 << "(Mat num: " << x.matrix_num
1251 << " row_n: " << x.row_n << ") ";
1252 }
1253 cout << endl;
1254 }
1255
1256
check_no_prop_or_unsat_rows()1257 void EGaussian::check_no_prop_or_unsat_rows()
1258 {
1259 #ifdef VERBOSE_DEBUG
1260 cout << "mat[" << matrix_no << "] checking invariants..." << endl;
1261 #endif
1262
1263 for(uint32_t row = 0; row < num_rows; row++) {
1264 uint32_t bits_unset = 0;
1265 bool val = mat[row].rhs();
1266 for(uint32_t col = 0; col < num_cols; col++) {
1267 if (mat[row][col]) {
1268 uint32_t var = col_to_var[col];
1269 if (solver->value(var) == l_Undef) {
1270 bits_unset++;
1271 } else {
1272 val ^= (solver->value(var) == l_True);
1273 }
1274 }
1275 }
1276
1277 bool error = false;
1278 if (bits_unset == 1) {
1279 cout << "ERROR: row " << row << " is PROP but did not propagate!!!" << endl;
1280 error = true;
1281 }
1282 if (bits_unset == 0 && val != false) {
1283 cout << "ERROR: row " << row << " is UNSAT but did not conflict!" << endl;
1284 error = true;
1285 }
1286 if (error) {
1287 for(uint32_t var = 0; var < solver->nVars(); var++) {
1288 const auto& ws = solver->gwatches[var];
1289 for(const auto& w: ws) {
1290 if (w.matrix_num == matrix_no && w.row_n == row) {
1291 cout << " gauss watched at var: " << var+1
1292 << " val: " << solver->value(var) << endl;
1293 }
1294 }
1295 }
1296
1297 cout << " matrix no: " << matrix_no << endl;
1298 cout << " row: " << row << endl;
1299 uint32_t var = row_to_var_non_resp[row];
1300 cout << " non-resp var: " << var+1 << endl;
1301 cout << " dec level: " << solver->decisionLevel() << endl;
1302 }
1303 assert(bits_unset > 1 || (bits_unset == 0 && val == 0));
1304 }
1305 }
1306
check_watchlist_sanity()1307 void EGaussian::check_watchlist_sanity()
1308 {
1309 for(size_t i = 0; i < solver->nVars(); i++) {
1310 for(auto w: solver->gwatches[i]) {
1311 if (w.matrix_num == matrix_no) {
1312 assert(i < var_to_col.size());
1313 }
1314 }
1315 }
1316 }
1317
check_tracked_cols_only_one_set()1318 void EGaussian::check_tracked_cols_only_one_set()
1319 {
1320 vector<uint32_t> row_resp_for_var(num_rows, var_Undef);
1321 for(uint32_t col = 0; col < num_cols; col++) {
1322 uint32_t var = col_to_var[col];
1323 if (var_has_resp_row[var]) {
1324 uint32_t num_ones = 0;
1325 uint32_t found_row = var_Undef;
1326 for(uint32_t row = 0; row < num_rows; row++) {
1327 if (mat[row][col]) {
1328 num_ones++;
1329 found_row = row;
1330 }
1331 }
1332 if (num_ones == 0) {
1333 cout
1334 << "mat[" << matrix_no << "] "
1335 << "WARNING: Tracked col " << col
1336 << " var: " << var+1
1337 << " has 0 rows' bit set to 1..."
1338 << endl;
1339 }
1340 if (num_ones > 1) {
1341 cout
1342 << "mat[" << matrix_no << "] "
1343 << "ERROR: Tracked col " << col
1344 << " var: " << var+1
1345 << " has " << num_ones << " rows' bit set to 1!!"
1346 << endl;
1347 assert(num_ones <= 1);
1348 }
1349 if (num_ones == 1) {
1350 if (row_resp_for_var[found_row] != var_Undef) {
1351 cout << "ERROR One row can only be responsible for one col"
1352 << " but row " << found_row << " is responsible for"
1353 << " var: " << row_resp_for_var[found_row]+1
1354 << " and var: " << var+1
1355 << endl;
1356 assert(false);
1357 }
1358 row_resp_for_var[found_row] = var;
1359 }
1360 }
1361 }
1362 }
1363
check_invariants()1364 void CMSat::EGaussian::check_invariants()
1365 {
1366 check_tracked_cols_only_one_set();
1367 check_no_prop_or_unsat_rows();
1368 #ifdef VERBOSE_DEBUG
1369 cout
1370 << "mat[" << matrix_no << "] "
1371 << "Checked invariants. Dec level: " << solver->decisionLevel() << endl;
1372 #endif
1373 }
1374
check_row_satisfied(const uint32_t row)1375 bool EGaussian::check_row_satisfied(const uint32_t row)
1376 {
1377 bool ret = true;
1378 bool fin = mat[row].rhs();
1379 for(uint32_t i = 0; i < num_cols; i++) {
1380 if (mat[row][i]) {
1381 uint32_t var = col_to_var[i];
1382 auto val = solver->value(var);
1383 if (val == l_Undef) {
1384 cout << "Var " << var+1 << " col: " << i << " is undef!" << endl;
1385 ret = false;
1386 }
1387 fin ^= val == l_True;
1388 }
1389 }
1390 return ret && fin == false;
1391 }
1392
check_cols_unset_vals()1393 void EGaussian::check_cols_unset_vals()
1394 {
1395 for(uint32_t i = 0; i < num_cols; i ++) {
1396 uint32_t var = col_to_var[i];
1397 if (solver->value(var) == l_Undef) {
1398 assert((*cols_unset)[i] == 1);
1399 } else {
1400 assert((*cols_unset)[i] == 0);
1401 }
1402
1403 if (solver->value(var) == l_True) {
1404 assert((*cols_vals)[i] == 1);
1405 } else {
1406 assert((*cols_vals)[i] == 0);
1407 }
1408 }
1409 }
1410
must_disable(GaussQData & gqd)1411 bool EGaussian::must_disable(GaussQData& gqd)
1412 {
1413 gqd.engaus_disable_checks++;
1414 if ((gqd.engaus_disable_checks & 0x3ff) == 0x3ff //only check once in a while
1415 ) {
1416 uint64_t egcalled = elim_called + find_truth_ret_satisfied_precheck+find_truth_called_propgause;
1417 uint32_t limit = (double)egcalled*solver->conf.gaussconf.min_usefulness_cutoff;
1418 uint32_t useful = find_truth_ret_prop+find_truth_ret_confl+elim_ret_prop+elim_ret_confl;
1419 //cout << "CHECKING - limit: " << limit << " useful:" << useful << endl;
1420 if (egcalled > 200 && useful < limit) {
1421 if (solver->conf.verbosity) {
1422 const double perc =
1423 stats_line_percent(useful, egcalled);
1424 cout << "c [g <" << matrix_no << "] Disabling GJ-elim in this round. "
1425 " Usefulness was: "
1426 << std::setprecision(4) << std::fixed << perc
1427 << "%"
1428 << std::setprecision(2)
1429 << " over " << egcalled << " calls"
1430 << endl;
1431 }
1432 return true;
1433 }
1434 }
1435
1436 return false;
1437 }
1438