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