1 /******************************************
2 Copyright (c) 2016, Mate Soos
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 ***********************************************/
22
23 #include "cnf.h"
24
25 #include <stdexcept>
26
27 #include "vardata.h"
28 #include "solvertypes.h"
29 #include "clauseallocator.h"
30 #include "watchalgos.h"
31 #include "varupdatehelper.h"
32 #include "time_mem.h"
33
34 using namespace CMSat;
35
new_var(const bool bva,const uint32_t orig_outer)36 void CNF::new_var(const bool bva, const uint32_t orig_outer)
37 {
38 if (nVars() >= 1ULL<<28) {
39 cout << "ERROR! Variable requested is far too large" << endl;
40 throw std::runtime_error("ERROR! Variable requested is far too large");
41 }
42
43 minNumVars++;
44 enlarge_minimal_datastructs();
45 if (orig_outer == std::numeric_limits<uint32_t>::max()) {
46 //completely new var
47 enlarge_nonminimial_datastructs();
48
49 uint32_t minVar = nVars()-1;
50 uint32_t maxVar = nVarsOuter()-1;
51 interToOuterMain.push_back(maxVar);
52 const uint32_t x = interToOuterMain[minVar];
53 interToOuterMain[minVar] = maxVar;
54 interToOuterMain[maxVar] = x;
55
56 outerToInterMain.push_back(maxVar);
57 outerToInterMain[maxVar] = minVar;
58 outerToInterMain[x] = maxVar;
59
60 swapVars(nVarsOuter()-1);
61 varData[nVars()-1].is_bva = bva;
62 if (bva) {
63 num_bva_vars ++;
64 } else {
65 outer_to_with_bva_map.push_back(nVarsOuter() - 1);
66 }
67 } else {
68 //Old var, re-inserted
69 assert(orig_outer < nVarsOuter());
70
71 const uint32_t minVar = nVars()-1;
72 uint32_t k = interToOuterMain[minVar];
73 uint32_t z = outerToInterMain[orig_outer];
74 interToOuterMain[minVar] = orig_outer;
75 interToOuterMain[z] = k;
76
77 outerToInterMain[k] = z;
78 outerToInterMain[orig_outer] = minVar;
79
80 swapVars(z);
81 }
82
83 #ifdef SLOW_DEBUG
84 test_reflectivity_of_renumbering();
85 #endif
86 }
87
new_vars(const size_t n)88 void CNF::new_vars(const size_t n)
89 {
90 if (nVars() + n >= 1ULL<<28) {
91 cout << "ERROR! Variable requested is far too large" << endl;
92 std::exit(-1);
93 }
94
95 minNumVars += n;
96 enlarge_minimal_datastructs(n);
97 enlarge_nonminimial_datastructs(n);
98
99 size_t inter_at = interToOuterMain.size();
100 interToOuterMain.insert(interToOuterMain.end(), n, 0);
101
102 size_t outer_at = outerToInterMain.size();
103 outerToInterMain.insert(outerToInterMain.end(), n, 0);
104
105 size_t outer_to_with_bva_at = outer_to_with_bva_map.size();
106 outer_to_with_bva_map.insert(outer_to_with_bva_map.end(), n, 0);
107
108 for(int i = n-1; i >= 0; i--) {
109 const uint32_t minVar = nVars()-i-1;
110 const uint32_t maxVar = nVarsOuter()-i-1;
111
112 interToOuterMain[inter_at++] = maxVar;
113 const uint32_t x = interToOuterMain[minVar];
114 interToOuterMain[minVar] = maxVar;
115 interToOuterMain[maxVar] = x;
116
117 outerToInterMain[outer_at++] = maxVar;
118 outerToInterMain[maxVar] = minVar;
119 outerToInterMain[x] = maxVar;
120
121 swapVars(nVarsOuter()-i-1, i);
122 varData[nVars()-i-1].is_bva = false;
123 outer_to_with_bva_map[outer_to_with_bva_at++] = nVarsOuter()-i-1;
124 }
125
126 #ifdef SLOW_DEBUG
127 test_reflectivity_of_renumbering();
128 #endif
129 }
130
swapVars(const uint32_t which,const int off_by)131 void CNF::swapVars(const uint32_t which, const int off_by)
132 {
133 std::swap(assigns[nVars()-off_by-1], assigns[which]);
134 std::swap(varData[nVars()-off_by-1], varData[which]);
135 }
136
enlarge_nonminimial_datastructs(size_t n)137 void CNF::enlarge_nonminimial_datastructs(size_t n)
138 {
139 assigns.insert(assigns.end(), n, l_Undef);
140 varData.insert(varData.end(), n, VarData());
141 depth.insert(depth.end(), n, 0);
142 }
143
enlarge_minimal_datastructs(size_t n)144 void CNF::enlarge_minimal_datastructs(size_t n)
145 {
146 watches.insert(2*n);
147 #ifdef USE_GAUSS
148 gwatches.insert(2*n);
149 #endif
150 seen.insert(seen.end(), 2*n, 0);
151 seen2.insert(seen2.end(), 2*n, 0);
152 permDiff.insert(permDiff.end(), 2*n, 0);
153 }
154
save_on_var_memory()155 void CNF::save_on_var_memory()
156 {
157 //never resize varData --> contains info about what is replaced/etc.
158 //never resize assigns --> contains 0-level assigns
159 //never resize interToOuterMain, outerToInterMain
160
161 watches.resize(nVars()*2);
162 watches.consolidate();
163
164 #ifdef USE_GAUSS
165 gwatches.resize(nVars()*2);
166 //TODO
167 //gwatches.consolidate();
168 #endif
169
170 for(auto& l: longRedCls) {
171 l.shrink_to_fit();
172 }
173 longIrredCls.shrink_to_fit();
174
175 seen.resize(nVars()*2);
176 seen.shrink_to_fit();
177 seen2.resize(nVars()*2);
178 seen2.shrink_to_fit();
179 permDiff.resize(nVars()*2);
180 permDiff.shrink_to_fit();
181 }
182
183 //Test for reflectivity of interToOuterMain & outerToInterMain
test_reflectivity_of_renumbering() const184 void CNF::test_reflectivity_of_renumbering() const
185 {
186 vector<uint32_t> test(nVarsOuter());
187 for(size_t i = 0; i < nVarsOuter(); i++) {
188 test[i] = i;
189 }
190 updateArrayRev(test, interToOuterMain);
191 #ifdef DEBUG_RENUMBER
192 for(size_t i = 0; i < nVarsOuter(); i++) {
193 cout << i << ": "
194 << std::setw(2) << test[i] << ", "
195 << std::setw(2) << outerToInterMain[i]
196 << endl;
197 }
198 #endif
199
200 for(size_t i = 0; i < nVarsOuter(); i++) {
201 assert(test[i] == outerToInterMain[i]);
202 }
203 #ifdef DEBUG_RENUMBR
204 cout << "Passed test" << endl;
205 #endif
206 }
207
updateWatch(watch_subarray ws,const vector<uint32_t> & outerToInter)208 inline void CNF::updateWatch(
209 watch_subarray ws
210 , const vector<uint32_t>& outerToInter
211 ) {
212 for(Watched *it = ws.begin(), *end = ws.end()
213 ; it != end
214 ; ++it
215 ) {
216 if (it->isBin()) {
217 it->setLit2(
218 getUpdatedLit(it->lit2(), outerToInter)
219 );
220 continue;
221 }
222
223 assert(it->isClause());
224 const Clause &cl = *cl_alloc.ptr(it->get_offset());
225 Lit blocked_lit = it->getBlockedLit();
226 blocked_lit = getUpdatedLit(it->getBlockedLit(), outerToInter);
227 bool found = false;
228 for(Lit lit: cl) {
229 if (lit == blocked_lit) {
230 found = true;
231 break;
232 }
233 }
234 if (!found) {
235 it->setBlockedLit(cl[2]);
236 } else {
237 it->setBlockedLit(blocked_lit);
238 }
239 }
240 }
241
updateVars(const vector<uint32_t> & outerToInter,const vector<uint32_t> & interToOuter,const vector<uint32_t> & interToOuter2)242 void CNF::updateVars(
243 const vector<uint32_t>& outerToInter
244 , const vector<uint32_t>& interToOuter
245 , const vector<uint32_t>& interToOuter2
246 ) {
247 updateArray(varData, interToOuter);
248 updateArray(assigns, interToOuter);
249 updateBySwap(watches, seen, interToOuter2);
250
251 for(watch_subarray w: watches) {
252 if (!w.empty())
253 updateWatch(w, outerToInter);
254 }
255
256 updateArray(interToOuterMain, interToOuter);
257 updateArrayMapCopy(outerToInterMain, outerToInter);
258 }
259
mem_used_longclauses() const260 uint64_t CNF::mem_used_longclauses() const
261 {
262 uint64_t mem = 0;
263 mem += cl_alloc.mem_used();
264 mem += longIrredCls.capacity()*sizeof(ClOffset);
265 for(auto& l: longRedCls) {
266 mem += l.capacity()*sizeof(ClOffset);
267 }
268 return mem;
269 }
270
print_mem_used_longclauses(const size_t totalMem) const271 uint64_t CNF::print_mem_used_longclauses(const size_t totalMem) const
272 {
273 uint64_t mem = mem_used_longclauses();
274 print_stats_line("c Mem for longclauses"
275 , mem/(1024UL*1024UL)
276 , "MB"
277 , stats_line_percent(mem, totalMem)
278 , "%"
279 );
280
281 return mem;
282 }
283
cl_size(const Watched & ws) const284 size_t CNF::cl_size(const Watched& ws) const
285 {
286 switch(ws.getType()) {
287 case watch_binary_t:
288 return 2;
289
290 case watch_clause_t: {
291 const Clause* cl = cl_alloc.ptr(ws.get_offset());
292 return cl->size();
293 }
294
295 default:
296 assert(false);
297 return 0;
298 }
299 }
300
watches_to_string(const Lit lit,watch_subarray_const ws) const301 string CNF::watches_to_string(const Lit lit, watch_subarray_const ws) const
302 {
303 std::stringstream ss;
304 for(Watched w: ws) {
305 ss << watched_to_string(lit, w) << " -- ";
306 }
307 return ss.str();
308 }
309
watched_to_string(Lit otherLit,const Watched & ws) const310 string CNF::watched_to_string(Lit otherLit, const Watched& ws) const
311 {
312 std::stringstream ss;
313 switch(ws.getType()) {
314 case watch_binary_t:
315 ss << otherLit << ", " << ws.lit2();
316 if (ws.red()) {
317 ss << "(red)";
318 }
319 break;
320
321 case watch_clause_t: {
322 const Clause* cl = cl_alloc.ptr(ws.get_offset());
323 for(size_t i = 0; i < cl->size(); i++) {
324 ss << (*cl)[i];
325 if (i + 1 < cl->size())
326 ss << ", ";
327 }
328 if (cl->red()) {
329 ss << "(red)";
330 }
331 break;
332 }
333
334 default:
335 assert(false);
336 break;
337 }
338
339 return ss.str();
340 }
341
operator ()(const ClOffset x,const ClOffset y)342 bool ClauseSizeSorter::operator () (const ClOffset x, const ClOffset y)
343 {
344 Clause* cl1 = cl_alloc.ptr(x);
345 Clause* cl2 = cl_alloc.ptr(y);
346 return (cl1->size() < cl2->size());
347 }
348
mem_used_renumberer() const349 size_t CNF::mem_used_renumberer() const
350 {
351 size_t mem = 0;
352 mem += interToOuterMain.capacity()*sizeof(uint32_t);
353 mem += outerToInterMain.capacity()*sizeof(uint32_t);
354 mem += outer_to_with_bva_map.capacity()*sizeof(uint32_t);
355 return mem;
356 }
357
build_outer_to_without_bva_map() const358 vector<uint32_t> CNF::build_outer_to_without_bva_map() const
359 {
360 vector<uint32_t> ret;
361 size_t at = 0;
362 for(size_t i = 0; i < nVarsOuter(); i++) {
363 if (!varData[map_outer_to_inter(i)].is_bva) {
364 ret.push_back(at);
365 at++;
366 } else {
367 ret.push_back(var_Undef);
368 }
369 }
370
371 return ret;
372 }
373
mem_used() const374 size_t CNF::mem_used() const
375 {
376 size_t mem = 0;
377 mem += sizeof(conf);
378 mem += sizeof(binTri);
379 mem += seen.capacity()*sizeof(uint16_t);
380 mem += seen2.capacity()*sizeof(uint8_t);
381 mem += toClear.capacity()*sizeof(Lit);
382
383 return mem;
384 }
385
save_state(SimpleOutFile & f) const386 void CNF::save_state(SimpleOutFile& f) const
387 {
388 /*assert(!seen.empty());
389 assert(!varData.empty());
390 assert(watches.size() != 0);*/
391
392 f.put_vector(interToOuterMain);
393 f.put_vector(outerToInterMain);
394
395 f.put_vector(assigns);
396 f.put_vector(varData);
397 f.put_uint32_t(minNumVars);
398 f.put_uint32_t(num_bva_vars);
399 f.put_uint32_t(ok);
400 }
401
load_state(SimpleInFile & f)402 void CNF::load_state(SimpleInFile& f)
403 {
404 assert(seen.empty());
405 assert(varData.empty());
406 assert(watches.size() == 0);
407
408 f.get_vector(interToOuterMain);
409 f.get_vector(outerToInterMain);
410 build_outer_to_without_bva_map();
411
412 f.get_vector(assigns);
413 f.get_vector(varData);
414 minNumVars = f.get_uint32_t();
415 num_bva_vars = f.get_uint32_t();
416 ok = f.get_uint32_t();
417
418 watches.resize(nVars()*2);
419 }
420
421
test_all_clause_attached() const422 void CNF::test_all_clause_attached() const
423 {
424 test_all_clause_attached(longIrredCls);
425 for(const vector<ClOffset>& l: longRedCls) {
426 test_all_clause_attached(l);
427 }
428 }
429
test_all_clause_attached(const vector<ClOffset> & offsets) const430 void CNF::test_all_clause_attached(const vector<ClOffset>& offsets) const
431 {
432 for (vector<ClOffset>::const_iterator
433 it = offsets.begin(), end = offsets.end()
434 ; it != end
435 ; ++it
436 ) {
437 assert(normClauseIsAttached(*it));
438 }
439 }
440
normClauseIsAttached(const ClOffset offset) const441 bool CNF::normClauseIsAttached(const ClOffset offset) const
442 {
443 bool attached = true;
444 const Clause& cl = *cl_alloc.ptr(offset);
445 assert(cl.size() > 2);
446
447 attached &= findWCl(watches[cl[0]], offset);
448 attached &= findWCl(watches[cl[1]], offset);
449
450 if (detached_xor_clauses && cl._xor_is_detached) {
451 //We expect this NOT to be attached, actually.
452 if (attached) {
453 cout
454 << "Failed. XOR-representing clause is NOT supposed to be attached"
455 << " clause: " << cl
456 << " _xor_is_detached: " << cl._xor_is_detached
457 << " detached_xor_clauses: " << detached_xor_clauses
458 << endl;
459 }
460 return !attached;
461 }
462
463 bool satisfied = satisfied_cl(cl);
464 uint32_t num_false2 = 0;
465 num_false2 += value(cl[0]) == l_False;
466 num_false2 += value(cl[1]) == l_False;
467 if (!satisfied) {
468 if (num_false2 != 0) {
469 cout << "Clause failed: " << cl << endl;
470 for(Lit l: cl) {
471 cout << "val " << l << " : " << value(l) << endl;
472 }
473 for(const Watched& w: watches[cl[0]]) {
474 cout << "watch " << cl[0] << endl;
475 if (w.isClause() && w.get_offset() == offset) {
476 cout << "Block lit: " << w.getBlockedLit()
477 << " val: " << value(w.getBlockedLit()) << endl;
478 }
479 }
480 for(const Watched& w: watches[cl[1]]) {
481 cout << "watch " << cl[1] << endl;
482 if (w.isClause() && w.get_offset() == offset) {
483 cout << "Block lit: " << w.getBlockedLit()
484 << " val: " << value(w.getBlockedLit()) << endl;
485 }
486 }
487 }
488 assert(num_false2 == 0 && "propagation was not full??");
489 }
490
491 return attached;
492 }
493
find_all_attach() const494 void CNF::find_all_attach() const
495 {
496 for (size_t i = 0; i < watches.size(); i++) {
497 const Lit lit = Lit::toLit(i);
498 for (uint32_t i2 = 0; i2 < watches[lit].size(); i2++) {
499 const Watched& w = watches[lit][i2];
500 if (!w.isClause())
501 continue;
502
503 //Get clause
504 Clause* cl = cl_alloc.ptr(w.get_offset());
505 assert(!cl->freed());
506
507 bool satisfied = satisfied_cl(*cl);
508 if (!satisfied) {
509 if (value(w.getBlockedLit()) == l_True) {
510 cout << "ERROR: Clause " << *cl << " not satisfied, but its blocked lit, "
511 << w.getBlockedLit() << " is." << endl;
512 }
513 assert(value(w.getBlockedLit()) != l_True && "Blocked lit is satisfied but clause is NOT!!");
514 }
515
516 //Assert watch correctness
517 if ((*cl)[0] != lit
518 && (*cl)[1] != lit
519 ) {
520 std::cerr
521 << "ERROR! Clause " << (*cl)
522 << " not attached?"
523 << endl;
524
525 assert(false);
526 std::exit(-1);
527 }
528
529 //Clause in one of the lists
530 if (!find_clause(w.get_offset())) {
531 std::cerr
532 << "ERROR! did not find clause " << *cl
533 << endl;
534
535 assert(false);
536 std::exit(1);
537 }
538 }
539 }
540
541 find_all_attach(longIrredCls);
542 for(auto& lredcls: longRedCls) {
543 find_all_attach(lredcls);
544 }
545 }
546
find_all_attach(const vector<ClOffset> & cs) const547 void CNF::find_all_attach(const vector<ClOffset>& cs) const
548 {
549 for(vector<ClOffset>::const_iterator
550 it = cs.begin(), end = cs.end()
551 ; it != end
552 ; ++it
553 ) {
554 Clause& cl = *cl_alloc.ptr(*it);
555 bool should_be_attached = true;
556 if (detached_xor_clauses && cl._xor_is_detached) {
557 should_be_attached = false;
558 }
559 bool ret = findWCl(watches[cl[0]], *it);
560 if (ret != should_be_attached) {
561 cout
562 << "Clause " << cl
563 << " (red: " << cl.red()
564 << " used in xor: " << cl.used_in_xor()
565 << " detached xor: " << cl._xor_is_detached
566 << " should be attached: " << should_be_attached
567 << " )";
568 if (ret) {
569 cout << " doesn't have its 1st watch attached!";
570 } else {
571 cout << " HAS its 1st watch attached (but it should NOT)!";
572 }
573 cout << endl;
574
575 assert(false);
576 std::exit(-1);
577 }
578
579 ret = findWCl(watches[cl[1]], *it);
580 if (ret != should_be_attached) {
581 cout
582 << "Clause " << cl
583 << " (red: " << cl.red()
584 << " used in xor: " << cl.used_in_xor()
585 << " detached xor: " << cl._xor_is_detached
586 << " should be attached: " << should_be_attached
587 << " )";
588 if (ret) {
589 cout << " doesn't have its 2nd watch attached!";
590 } else {
591 cout << " HAS its 2nd watch attached (but it should NOT)!";
592 }
593 cout << endl;
594
595 assert(false);
596 std::exit(-1);
597 }
598 }
599 }
600
601
find_clause(const ClOffset offset) const602 bool CNF::find_clause(const ClOffset offset) const
603 {
604 for (uint32_t i = 0; i < longIrredCls.size(); i++) {
605 if (longIrredCls[i] == offset)
606 return true;
607 }
608
609 for(auto& lredcls: longRedCls) {
610 for (ClOffset off: lredcls) {
611 if (off == offset)
612 return true;
613 }
614 }
615
616 return false;
617 }
618
check_wrong_attach() const619 void CNF::check_wrong_attach() const
620 {
621 #ifdef SLOW_DEBUG
622 for(auto& lredcls: longRedCls) {
623 for (ClOffset offs: lredcls) {
624 const Clause& cl = *cl_alloc.ptr(offs);
625 for (uint32_t i = 0; i < cl.size(); i++) {
626 if (i > 0)
627 assert(cl[i-1].var() != cl[i].var());
628 }
629 }
630 }
631 for(watch_subarray_const ws: watches) {
632 check_watchlist(ws);
633 }
634 #endif
635 }
636
check_watchlist(watch_subarray_const ws) const637 void CNF::check_watchlist(watch_subarray_const ws) const
638 {
639 for(const Watched& w: ws) {
640 if (!w.isClause()) {
641 continue;
642 }
643
644 const ClOffset offs = w.get_offset();
645 const Clause& c = *cl_alloc.ptr(offs);
646 Lit blockedLit = w.getBlockedLit();
647 /*cout << "Clause " << c << " blocked lit: "<< blockedLit << " val: " << value(blockedLit)
648 << " blocked removed:" << !(varData[blockedLit.var()].removed == Removed::none)
649 << " cl satisfied: " << satisfied_cl(&c)
650 << endl;*/
651 assert(blockedLit.var() < nVars());
652
653 if (varData[blockedLit.var()].removed == Removed::none
654 //0-level FALSE --> clause cleaner removed it from clause, that's OK
655 && value(blockedLit) != l_False
656 && !satisfied_cl(c)
657 ) {
658 bool found = false;
659 for(Lit l: c) {
660 if (l == blockedLit) {
661 found = true;
662 break;
663 }
664 }
665 if (!found) {
666 cout << "Did not find non-removed blocked lit " << blockedLit
667 << " val: " << value(blockedLit) << endl
668 << "In clause " << c << endl;
669 }
670 assert(found);
671 }
672
673 }
674 }
675
676
count_lits(const vector<ClOffset> & clause_array,const bool red,const bool allowFreed) const677 uint64_t CNF::count_lits(
678 const vector<ClOffset>& clause_array
679 , const bool red
680 , const bool allowFreed
681 ) const {
682 uint64_t lits = 0;
683 for(vector<ClOffset>::const_iterator
684 it = clause_array.begin(), end = clause_array.end()
685 ; it != end
686 ; ++it
687 ) {
688 const Clause& cl = *cl_alloc.ptr(*it);
689 if (cl.freed()) {
690 assert(allowFreed);
691 } else {
692 if ((cl.red() ^ red) == false) {
693 lits += cl.size();
694 }
695 }
696 }
697
698 return lits;
699 }
700
print_all_clauses() const701 void CNF::print_all_clauses() const
702 {
703 for(vector<ClOffset>::const_iterator
704 it = longIrredCls.begin(), end = longIrredCls.end()
705 ; it != end
706 ; ++it
707 ) {
708 Clause* cl = cl_alloc.ptr(*it);
709 cout
710 << "Normal clause offs " << *it
711 << " cl: " << *cl
712 << endl;
713 }
714
715
716 uint32_t wsLit = 0;
717 for (watch_array::const_iterator
718 it = watches.begin(), end = watches.end()
719 ; it != end
720 ; ++it, wsLit++
721 ) {
722 Lit lit = Lit::toLit(wsLit);
723 watch_subarray_const ws = *it;
724 cout << "watches[" << lit << "]" << endl;
725 for (const Watched *it2 = ws.begin(), *end2 = ws.end()
726 ; it2 != end2
727 ; it2++
728 ) {
729 if (it2->isBin()) {
730 cout << "Binary clause part: " << lit << " , " << it2->lit2() << endl;
731 } else if (it2->isClause()) {
732 cout << "Normal clause offs " << it2->get_offset() << endl;
733 }
734 }
735 }
736 }
737
no_marked_clauses() const738 bool CNF::no_marked_clauses() const
739 {
740 for(ClOffset offset: longIrredCls) {
741 Clause* cl = cl_alloc.ptr(offset);
742 assert(!cl->stats.marked_clause);
743 }
744
745 for(auto& lredcls: longRedCls) {
746 for(ClOffset offset: lredcls) {
747 Clause* cl = cl_alloc.ptr(offset);
748 assert(!cl->stats.marked_clause);
749 }
750 }
751
752 return true;
753 }
754
add_drat(std::ostream * os,bool add_ID)755 void CNF::add_drat(std::ostream* os, bool add_ID) {
756 if (drat)
757 delete drat;
758
759 if (add_ID) {
760 drat = new DratFile<true>(interToOuterMain);
761 } else {
762 drat = new DratFile<false>(interToOuterMain);
763 }
764 drat->setFile(os);
765 }
766
get_outside_var_incidence()767 vector<uint32_t> CNF::get_outside_var_incidence()
768 {
769 vector<uint32_t> inc;
770 inc.resize(nVars(), 0);
771 for(uint32_t i = 0; i < nVars()*2; i++) {
772 const Lit l = Lit::toLit(i);
773 for(const auto& x: watches[l]) {
774 if (x.isBin() && !x.red()) {
775 inc[x.lit2().var()]++;
776 inc[l.var()]++;
777 }
778 }
779 }
780
781 for(const auto& offs: longIrredCls) {
782 Clause* cl = cl_alloc.ptr(offs);
783 for(const auto& l: *cl) {
784 inc[l.var()]++;
785 }
786 }
787
788 //Map to outer
789 vector<uint32_t> inc_outer(nVarsOuter(), 0);
790 for(uint32_t i = 0; i < inc.size(); i ++) {
791 uint32_t outer = map_inter_to_outer(i);
792 inc_outer[outer] = inc[i];
793 }
794
795 //Map to outside
796 if (get_num_bva_vars() != 0) {
797 inc_outer = map_back_vars_to_without_bva(inc_outer);
798 }
799 return inc_outer;
800 }
801
get_outside_var_incidence_also_red()802 vector<uint32_t> CNF::get_outside_var_incidence_also_red()
803 {
804 vector<uint32_t> inc;
805 inc.resize(nVars(), 0);
806 for(uint32_t i = 0; i < nVars()*2; i++) {
807 const Lit l = Lit::toLit(i);
808 for(const auto& x: watches[l]) {
809 if (x.isBin()) {
810 inc[x.lit2().var()]++;
811 inc[l.var()]++;
812 }
813 }
814 }
815
816 for(const auto& offs: longIrredCls) {
817 Clause* cl = cl_alloc.ptr(offs);
818 for(const auto& l: *cl) {
819 inc[l.var()]++;
820 }
821 }
822
823 for(const auto& reds: longRedCls) {
824 for(const auto& offs: reds) {
825 Clause* cl = cl_alloc.ptr(offs);
826 for(const auto& l: *cl) {
827 inc[l.var()]++;
828 }
829 }
830 }
831
832 //Map to outer
833 vector<uint32_t> inc_outer(nVarsOuter(), 0);
834 for(uint32_t i = 0; i < inc.size(); i ++) {
835 uint32_t outer = map_inter_to_outer(i);
836 inc_outer[outer] = inc[i];
837 }
838
839 //Map to outside
840 if (get_num_bva_vars() != 0) {
841 inc_outer = map_back_vars_to_without_bva(inc_outer);
842 }
843 return inc_outer;
844 }
845