summaryrefslogtreecommitdiff
path: root/cryptominisat5/cryptominisat-5.6.3/src/xorfinder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cryptominisat5/cryptominisat-5.6.3/src/xorfinder.cpp')
-rw-r--r--cryptominisat5/cryptominisat-5.6.3/src/xorfinder.cpp873
1 files changed, 873 insertions, 0 deletions
diff --git a/cryptominisat5/cryptominisat-5.6.3/src/xorfinder.cpp b/cryptominisat5/cryptominisat-5.6.3/src/xorfinder.cpp
new file mode 100644
index 000000000..5f050d152
--- /dev/null
+++ b/cryptominisat5/cryptominisat-5.6.3/src/xorfinder.cpp
@@ -0,0 +1,873 @@
+/******************************************
+Copyright (c) 2016, Mate Soos
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+***********************************************/
+
+#include "xorfinder.h"
+#include "time_mem.h"
+#include "solver.h"
+#include "occsimplifier.h"
+#include "clauseallocator.h"
+#include "sqlstats.h"
+
+#include <limits>
+//#define XOR_DEBUG
+
+using namespace CMSat;
+using std::cout;
+using std::endl;
+
+XorFinder::XorFinder(OccSimplifier* _occsimplifier, Solver* _solver) :
+ occsimplifier(_occsimplifier)
+ , solver(_solver)
+ , toClear(_solver->toClear)
+{
+}
+
+void XorFinder::find_xors_based_on_long_clauses()
+{
+ #ifdef DEBUG_MARKED_CLAUSE
+ assert(solver->no_marked_clauses());
+ #endif
+
+ vector<Lit> lits;
+ for (vector<ClOffset>::iterator
+ it = occsimplifier->clauses.begin()
+ , end = occsimplifier->clauses.end()
+ ; it != end && xor_find_time_limit > 0
+ ; ++it
+ ) {
+ ClOffset offset = *it;
+ Clause* cl = solver->cl_alloc.ptr(offset);
+ xor_find_time_limit -= 1;
+
+ //Already freed
+ if (cl->freed() || cl->getRemoved()) {
+ continue;
+ }
+
+ //Too large -> too expensive
+ if (cl->size() > solver->conf.maxXorToFind) {
+ continue;
+ }
+
+ //If not tried already, find an XOR with it
+ if (!cl->stats.marked_clause ) {
+ cl->stats.marked_clause = true;
+ assert(!cl->getRemoved());
+
+ size_t needed_per_ws = 1ULL << (cl->size()-2);
+ //let's allow shortened clauses
+ needed_per_ws >>= 1;
+
+ for(const Lit lit: *cl) {
+ if (solver->watches[lit].size() < needed_per_ws) {
+ goto next;
+ }
+ if (solver->watches[~lit].size() < needed_per_ws) {
+ goto next;
+ }
+ }
+
+ lits.resize(cl->size());
+ std::copy(cl->begin(), cl->end(), lits.begin());
+ findXor(lits, offset, cl->abst);
+ next:;
+ }
+ }
+}
+
+void XorFinder::clean_equivalent_xors(vector<Xor>& txors)
+{
+ if (!txors.empty()) {
+ for(Xor& x: txors) {
+ std::sort(x.begin(), x.end());
+ }
+ std::sort(txors.begin(), txors.end());
+
+ vector<Xor>::iterator i = txors.begin();
+ vector<Xor>::iterator j = i;
+ i++;
+ uint64_t size = 1;
+ for(vector<Xor>::iterator end = txors.end(); i != end; i++) {
+ if (*j != *i) {
+ j++;
+ *j = *i;
+ size++;
+ }
+ }
+ txors.resize(size);
+ }
+}
+
+void XorFinder::find_xors()
+{
+ runStats.clear();
+ runStats.numCalls = 1;
+ grab_mem();
+ if ((solver->conf.xor_var_per_cut + 2) > solver->conf.maxXorToFind) {
+ if (solver->conf.verbosity) {
+ cout << "c WARNING updating max XOR to find to "
+ << (solver->conf.xor_var_per_cut + 2)
+ << " as the current number was lower than the cutting number" << endl;
+ }
+ solver->conf.maxXorToFind = solver->conf.xor_var_per_cut + 2;
+ }
+
+ xors.clear();
+ double myTime = cpuTime();
+ const int64_t orig_xor_find_time_limit =
+ 1000LL*1000LL*solver->conf.xor_finder_time_limitM
+ *solver->conf.global_timeout_multiplier;
+
+ xor_find_time_limit = orig_xor_find_time_limit;
+
+ occsimplifier->sort_occurs_and_set_abst();
+ if (solver->conf.verbosity) {
+ cout << "c [occ-xor] sort occur list T: " << (cpuTime()-myTime) << endl;
+ }
+
+ #ifdef DEBUG_MARKED_CLAUSE
+ assert(solver->no_marked_clauses());
+ #endif
+
+ find_xors_based_on_long_clauses();
+ assert(runStats.foundXors == xors.size());
+
+ //clean them of equivalent XORs
+ clean_equivalent_xors(xors);
+
+ //Cleanup
+ for(ClOffset offset: occsimplifier->clauses) {
+ Clause* cl = solver->cl_alloc.ptr(offset);
+ cl->stats.marked_clause = false;
+ }
+
+ //Print stats
+ const bool time_out = (xor_find_time_limit < 0);
+ const double time_remain = float_div(xor_find_time_limit, orig_xor_find_time_limit);
+ runStats.findTime = cpuTime() - myTime;
+ runStats.time_outs += time_out;
+ solver->sumSearchStats.num_xors_found_last = xors.size();
+ print_found_xors();
+
+ if (solver->conf.verbosity) {
+ runStats.print_short(solver, time_remain);
+ }
+ globalStats += runStats;
+
+ if (solver->sqlStats) {
+ solver->sqlStats->time_passed(
+ solver
+ , "xor-find"
+ , cpuTime() - myTime
+ , time_out
+ , time_remain
+ );
+ }
+}
+
+void XorFinder::print_found_xors()
+{
+ if (solver->conf.verbosity >= 5) {
+ cout << "c Found XORs: " << endl;
+ for(vector<Xor>::const_iterator
+ it = xors.begin(), end = xors.end()
+ ; it != end
+ ; ++it
+ ) {
+ cout << "c " << *it << endl;
+ }
+ }
+}
+
+void XorFinder::add_xors_to_solver()
+{
+ solver->xorclauses = xors;
+ #if defined(SLOW_DEBUG) || defined(XOR_DEBUG)
+ for(const Xor& x: xors) {
+ for(uint32_t v: x) {
+ assert(solver->varData[v].removed == Removed::none);
+ }
+ }
+ #endif
+}
+
+void XorFinder::findXor(vector<Lit>& lits, const ClOffset offset, cl_abst_type abst)
+{
+ //Set this clause as the base for the XOR, fill 'seen'
+ xor_find_time_limit -= lits.size()/4+1;
+ poss_xor.setup(lits, offset, abst, occcnt);
+
+ //Run findXorMatch for the 2 smallest watchlists
+ Lit slit = lit_Undef;
+ Lit slit2 = lit_Undef;
+ uint32_t smallest = std::numeric_limits<uint32_t>::max();
+ uint32_t smallest2 = std::numeric_limits<uint32_t>::max();
+ for (size_t i = 0, end = lits.size(); i < end; i++) {
+ const Lit lit = lits[i];
+ uint32_t num = solver->watches[lit].size();
+ num += solver->watches[~lit].size();
+ if (num < smallest) {
+ slit2 = slit;
+ smallest2 = smallest;
+
+ slit = lit;
+ smallest = num;
+ } else if (num < smallest2) {
+ slit2 = lit;
+ smallest2 = num;
+ }
+ }
+ findXorMatch(solver->watches[slit], slit);
+ findXorMatch(solver->watches[~slit], ~slit);
+ findXorMatch(solver->watches[slit2], slit2);
+ findXorMatch(solver->watches[~slit2], ~slit2);
+
+ if (poss_xor.foundAll()) {
+ std::sort(lits.begin(), lits.end());
+ Xor found_xor(lits, poss_xor.getRHS());
+ #if defined(SLOW_DEBUG) || defined(XOR_DEBUG)
+ for(Lit lit: lits) {
+ assert(solver->varData[lit.var()].removed == Removed::none);
+ }
+ #endif
+
+ add_found_xor(found_xor);
+ for(ClOffset offs: poss_xor.get_offsets()) {
+ Clause* cl = solver->cl_alloc.ptr(offs);
+ assert(!cl->getRemoved());
+ cl->set_used_in_xor(true);
+ }
+ }
+ poss_xor.clear_seen(occcnt);
+}
+
+void XorFinder::add_found_xor(const Xor& found_xor)
+{
+ xors.push_back(found_xor);
+ runStats.foundXors++;
+ runStats.sumSizeXors += found_xor.size();
+}
+
+void XorFinder::findXorMatch(watch_subarray_const occ, const Lit wlit)
+{
+ xor_find_time_limit -= (int64_t)occ.size()/8+1;
+ for (const Watched& w: occ) {
+ if (w.isIdx()) {
+ continue;
+ }
+ assert(poss_xor.getSize() > 2);
+
+ if (w.isBin()) {
+ #ifdef SLOW_DEBUG
+ assert(occcnt[wlit.var()]);
+ #endif
+ if (!occcnt[w.lit2().var()]) {
+ goto end;
+ }
+
+ binvec.clear();
+ binvec.resize(2);
+ binvec[0] = w.lit2();
+ binvec[1] = wlit;
+ if (binvec[0] > binvec[1]) {
+ std::swap(binvec[0], binvec[1]);
+ }
+
+ xor_find_time_limit -= 1;
+ poss_xor.add(binvec, std::numeric_limits<ClOffset>::max(), varsMissing);
+ if (poss_xor.foundAll())
+ break;
+ } else {
+ if (w.getBlockedLit().toInt() == lit_Undef.toInt())
+ //Clauses are ordered, lit_Undef means it's larger than maxXorToFind
+ break;
+
+ if (w.getBlockedLit().toInt() == lit_Error.toInt())
+ //lit_Error means it's freed or removed, and it's ordered so no more
+ break;
+
+ if ((w.getBlockedLit().toInt() | poss_xor.getAbst()) != poss_xor.getAbst())
+ continue;
+
+ xor_find_time_limit -= 3;
+ const ClOffset offset = w.get_offset();
+ Clause& cl = *solver->cl_alloc.ptr(offset);
+ if (cl.freed() || cl.getRemoved()) {
+ //Clauses are ordered!!
+ break;
+ }
+
+ //Allow the clause to be smaller or equal in size
+ if (cl.size() > poss_xor.getSize()) {
+ //clauses are ordered!!
+ break;
+ }
+
+ //Doesn't contain variables not in the original clause
+ #if defined(SLOW_DEBUG) || defined(XOR_DEBUG)
+ assert(cl.abst == calcAbstraction(cl));
+ #endif
+ if ((cl.abst | poss_xor.getAbst()) != poss_xor.getAbst())
+ continue;
+
+ //Check RHS, vars inside
+ bool rhs = true;
+ for (const Lit cl_lit :cl) {
+ //early-abort, contains literals not in original clause
+ if (!occcnt[cl_lit.var()])
+ goto end;
+
+ rhs ^= cl_lit.sign();
+ }
+ //either the invertedness has to match, or the size must be smaller
+ if (rhs != poss_xor.getRHS() && cl.size() == poss_xor.getSize())
+ continue;
+
+ //If the size of this clause is the same of the base clause, then
+ //there is no point in using this clause as a base for another XOR
+ //because exactly the same things will be found.
+ if (cl.size() == poss_xor.getSize()) {
+ cl.stats.marked_clause = true;;
+ }
+
+ xor_find_time_limit -= cl.size()/4+1;
+ poss_xor.add(cl, offset, varsMissing);
+ if (poss_xor.foundAll())
+ break;
+ }
+ end:;
+ }
+
+ if (solver->conf.doCache &&
+ solver->conf.useCacheWhenFindingXors &&
+ !poss_xor.foundAll()
+ ) {
+ const TransCache& cache1 = solver->implCache[wlit];
+ for (const LitExtra litExtra: cache1.lits) {
+ const Lit otherlit = litExtra.getLit();
+ if (!occcnt[otherlit.var()]) {
+ continue;
+ }
+
+ binvec.clear();
+ binvec.resize(2);
+ binvec[0] = otherlit;
+ binvec[1] = wlit;
+ if (binvec[0] > binvec[1]) {
+ std::swap(binvec[0], binvec[1]);
+ }
+
+ xor_find_time_limit -= 1;
+ poss_xor.add(binvec, std::numeric_limits<ClOffset>::max(), varsMissing);
+ if (poss_xor.foundAll())
+ break;
+ }
+ }
+}
+
+vector<Xor> XorFinder::remove_xors_without_connecting_vars(const vector<Xor>& this_xors)
+{
+ if (this_xors.empty())
+ return this_xors;
+
+ double myTime = cpuTime();
+ vector<Xor> ret;
+ assert(toClear.empty());
+
+ //Fill seen with vars used
+ uint32_t non_empty = 0;
+ for(const Xor& x: this_xors) {
+ if (x.size() != 0) {
+ non_empty++;
+ }
+
+ for(uint32_t v: x) {
+ if (solver->seen[v] == 0) {
+ toClear.push_back(Lit(v, false));
+ }
+
+ if (solver->seen[v] < 2) {
+ solver->seen[v]++;
+ }
+ }
+ }
+
+ vector<Xor>::const_iterator i = this_xors.begin();
+ for(vector<Xor>::const_iterator end = this_xors.end()
+ ; i != end
+ ; i++
+ ) {
+ if (xor_has_interesting_var(*i)) {
+ ret.push_back(*i);
+ }
+ }
+
+ for(Lit l: toClear) {
+ solver->seen[l.var()] = 0;
+ }
+ toClear.clear();
+
+ double time_used = cpuTime() - myTime;
+ if (solver->conf.verbosity) {
+ cout << "c [xor-rem-unconnected] left with " << ret.size()
+ << " xors from " << non_empty << " non-empty xors"
+ << solver->conf.print_times(time_used)
+ << endl;
+ }
+ if (solver->sqlStats) {
+ solver->sqlStats->time_passed_min(
+ solver
+ , "xor-rem-no-connecting-vars"
+ , time_used
+ );
+ }
+
+ return ret;
+}
+
+bool XorFinder::xor_together_xors(vector<Xor>& this_xors)
+{
+ if (occcnt.size() != solver->nVars())
+ grab_mem();
+
+ if (this_xors.empty())
+ return solver->okay();
+
+ #ifdef SLOW_DEBUG
+ for(auto x: occcnt) {
+ assert(x == 0);
+ }
+ #endif
+
+ assert(solver->okay());
+ assert(solver->decisionLevel() == 0);
+ assert(solver->watches.get_smudged_list().empty());
+ const size_t origsize = this_xors.size();
+
+ uint32_t xored = 0;
+ const double myTime = cpuTime();
+ assert(toClear.empty());
+
+ //Link in xors into watchlist
+ for(size_t i = 0; i < this_xors.size(); i++) {
+ const Xor& x = this_xors[i];
+ for(uint32_t v: x) {
+ if (occcnt[v] == 0) {
+ toClear.push_back(Lit(v, false));
+ }
+ occcnt[v]++;
+
+ Lit l(v, false);
+ assert(solver->watches.size() > l.toInt());
+ solver->watches[l].push(Watched(i)); //Idx watch
+ solver->watches.smudge(l);
+ }
+ }
+
+ //until fixedpoint
+ bool changed = true;
+ while(changed) {
+ changed = false;
+ interesting.clear();
+ for(const Lit l: toClear) {
+ if (occcnt[l.var()] == 2) {
+ interesting.push_back(l.var());
+ }
+ }
+
+ while(!interesting.empty()) {
+ #ifdef SLOW_DEBUG
+ {
+ vector<uint32_t> check;
+ check.resize(solver->nVars(), 0);
+ for(size_t i = 0; i < this_xors.size(); i++) {
+ const Xor& x = this_xors[i];
+ for(uint32_t v: x) {
+ check[v]++;
+ }
+ }
+ for(size_t i = 0; i < solver->nVars(); i++) {
+ assert(check[i] == occcnt[i]);
+ }
+ }
+ #endif
+
+ const uint32_t v = interesting.back();
+ interesting.resize(interesting.size()-1);
+ if (occcnt[v] != 2)
+ continue;
+
+ size_t idxes[2];
+ unsigned at = 0;
+ size_t i2 = 0;
+ assert(solver->watches.size() > Lit(v, false).toInt());
+ watch_subarray ws = solver->watches[Lit(v, false)];
+
+ for(size_t i = 0; i < ws.size(); i++) {
+ const Watched& w = ws[i];
+ if (!w.isIdx()) {
+ ws[i2++] = ws[i];
+ } else if (this_xors[w.get_idx()] != Xor()) {
+ assert(at < 2);
+ idxes[at] = w.get_idx();
+ at++;
+ }
+ }
+ assert(at == 2);
+ ws.resize(i2);
+
+ if (this_xors[idxes[0]] == this_xors[idxes[1]]) {
+ //Equivalent, so delete one
+ this_xors[idxes[0]] = Xor();
+
+ //Re-attach the other, remove the occur of the one we deleted
+ const Xor& x = this_xors[idxes[1]];
+ solver->watches[Lit(v, false)].push(Watched(idxes[1]));
+ for(uint32_t v2: x) {
+ Lit l(v2, false);
+ assert(occcnt[l.var()] >= 2);
+ occcnt[l.var()]--;
+ if (occcnt[l.var()] == 2) {
+ interesting.push_back(l.var());
+ }
+ }
+ } else {
+ uint32_t clash_num;
+ vector<uint32_t> vars = xor_two(this_xors[idxes[0]], this_xors[idxes[1]], clash_num);
+ if (clash_num > 1) {
+ //add back to ws
+ ws.push(Watched(idxes[0]));
+ ws.push(Watched(idxes[1]));
+ continue;
+ }
+ occcnt[v] -= 2;
+ assert(occcnt[v] == 0);
+
+ Xor x_new(vars, this_xors[idxes[0]].rhs ^ this_xors[idxes[1]].rhs);
+ changed = true;
+ this_xors.push_back(x_new);
+ for(uint32_t v2: x_new) {
+ Lit l(v2, false);
+ solver->watches[l].push(Watched(this_xors.size()-1));
+ assert(occcnt[l.var()] >= 1);
+ if (occcnt[l.var()] == 2) {
+ interesting.push_back(l.var());
+ }
+ }
+ this_xors[idxes[0]] = Xor();
+ this_xors[idxes[1]] = Xor();
+ xored++;
+ }
+ }
+ }
+
+ for(const Lit l: toClear) {
+ occcnt[l.var()] = 0;
+ }
+ toClear.clear();
+
+ solver->clean_occur_from_idx_types_only_smudged();
+ clean_xors_from_empty();
+ double recur_time = cpuTime() - myTime;
+ if (solver->conf.verbosity) {
+ cout
+ << "c [xor-together] xored together " << xored << " xors"
+ << " orig num xors: " << origsize
+ << solver->conf.print_times(recur_time)
+ << endl;
+ }
+
+
+ if (solver->sqlStats) {
+ solver->sqlStats->time_passed_min(
+ solver
+ , "xor-xor-together"
+ , recur_time
+ );
+ }
+
+ #if defined(SLOW_DEBUG) || defined(XOR_DEBUG)
+ //Make sure none is 2.
+ assert(toClear.empty());
+ for(const Xor& x: this_xors) {
+ for(uint32_t v: x) {
+ if (occcnt[v] == 0) {
+ toClear.push_back(Lit(v, false));
+ }
+
+ //Don't roll around
+ occcnt[v]++;
+ }
+ }
+
+ for(const Lit c: toClear) {
+ /*This is now possible because we don't XOR them together
+ in case they clash on more than 1 variable */
+ //assert(occcnt[c.var()] != 2);
+
+ occcnt[c.var()] = 0;
+ }
+ toClear.clear();
+ #endif
+
+ return solver->okay();
+}
+
+void XorFinder::clean_xors_from_empty()
+{
+ size_t i2 = 0;
+ for(size_t i = 0;i < xors.size(); i++) {
+ Xor& x = xors[i];
+ if (x.size() == 0
+ && x.rhs == false
+ ) {
+ //nothing, skip
+ } else {
+ xors[i2] = xors[i];
+ i2++;
+ }
+ }
+ xors.resize(i2);
+}
+
+bool XorFinder::add_new_truths_from_xors(vector<Xor>& this_xors, vector<Lit>* out_changed_occur)
+{
+ size_t origTrailSize = solver->trail_size();
+ size_t origBins = solver->binTri.redBins;
+ double myTime = cpuTime();
+
+ assert(solver->ok);
+ size_t i2 = 0;
+ for(size_t i = 0;i < this_xors.size(); i++) {
+ Xor& x = this_xors[i];
+ solver->clean_xor_vars_no_prop(x.get_vars(), x.rhs);
+ if (x.size() > 2) {
+ this_xors[i2] = this_xors[i];
+ i2++;
+ continue;
+ }
+
+ switch(x.size() ) {
+ case 0: {
+ if (x.rhs == true) {
+ solver->ok = false;
+ return false;
+ }
+ break;
+ }
+
+ case 1: {
+ Lit lit = Lit(x[0], !x.rhs);
+ if (solver->value(lit) == l_False) {
+ solver->ok = false;
+ } else if (solver->value(lit) == l_Undef) {
+ solver->enqueue(lit);
+ if (out_changed_occur)
+ solver->ok = solver->propagate_occur();
+ else
+ solver->ok = solver->propagate<true>().isNULL();
+ }
+ if (!solver->ok) {
+ goto end;
+ }
+ break;
+ }
+
+ case 2: {
+ //RHS == 1 means both same is not allowed
+ vector<Lit> lits{Lit(x[0], false), Lit(x[1], true^x.rhs)};
+ solver->add_clause_int(lits, true, ClauseStats(), out_changed_occur != NULL);
+ if (!solver->ok) {
+ goto end;
+ }
+ lits = {Lit(x[0], true), Lit(x[1], false^x.rhs)};
+ solver->add_clause_int(lits, true, ClauseStats(), out_changed_occur != NULL);
+ if (!solver->ok) {
+ goto end;
+ }
+ if (out_changed_occur) {
+ solver->ok = solver->propagate_occur();
+ } else {
+ solver->ok = solver->propagate<true>().isNULL();
+ }
+
+ if (out_changed_occur) {
+ out_changed_occur->push_back(Lit(x[0], false));
+ out_changed_occur->push_back(Lit(x[1], false));
+ }
+ break;
+ }
+
+ default: {
+ assert(false && "Not possible");
+ }
+ }
+ }
+ this_xors.resize(i2);
+ end:
+
+ double add_time = cpuTime() - myTime;
+ uint32_t num_bins_added = solver->binTri.redBins - origBins;
+ uint32_t num_units_added = solver->trail_size() - origTrailSize;
+
+ if (solver->conf.verbosity) {
+ cout
+ << "c [xor-add-lem] added unit " << num_units_added
+ << " bin " << num_bins_added
+ << solver->conf.print_times(add_time)
+ << endl;
+ }
+
+
+ if (solver->sqlStats) {
+ solver->sqlStats->time_passed_min(
+ solver
+ , "xor-add-new-bin-unit"
+ , add_time
+ );
+ }
+
+ return solver->okay();
+}
+
+vector<uint32_t> XorFinder::xor_two(Xor& x1, Xor& x2, uint32_t& clash_num)
+{
+ clash_num = 0;
+ x1.sort();
+ x2.sort();
+ vector<uint32_t> ret;
+ size_t x1_at = 0;
+ size_t x2_at = 0;
+ while(x1_at < x1.size() || x2_at < x2.size()) {
+ if (x1_at == x1.size()) {
+ ret.push_back(x2[x2_at]);
+ x2_at++;
+ continue;
+ }
+
+ if (x2_at == x2.size()) {
+ ret.push_back(x1[x1_at]);
+ x1_at++;
+ continue;
+ }
+
+ const uint32_t a = x1[x1_at];
+ const uint32_t b = x2[x2_at];
+ if (a == b) {
+ clash_num++;
+ x1_at++;
+ x2_at++;
+ continue;
+ }
+
+ if (a < b) {
+ ret.push_back(a);
+ x1_at++;
+ continue;
+ } else {
+ ret.push_back(b);
+ x2_at++;
+ continue;
+ }
+ }
+
+ return ret;
+}
+
+bool XorFinder::xor_has_interesting_var(const Xor& x)
+{
+ for(uint32_t v: x) {
+ if (solver->seen[v] > 1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+size_t XorFinder::mem_used() const
+{
+ size_t mem = 0;
+ mem += xors.capacity()*sizeof(Xor);
+
+ //Temporary
+ mem += tmpClause.capacity()*sizeof(Lit);
+ mem += varsMissing.capacity()*sizeof(uint32_t);
+
+ return mem;
+}
+
+void XorFinder::grab_mem()
+{
+ occcnt.clear();
+ occcnt.resize(solver->nVars(), 0);
+}
+
+void XorFinder::free_mem()
+{
+ occcnt.clear();
+ occcnt.shrink_to_fit();
+}
+
+void XorFinder::Stats::print_short(const Solver* solver, double time_remain) const
+{
+ cout
+ << "c [occ-xor] found " << std::setw(6) << foundXors
+ << " avg sz " << std::setw(4) << std::fixed << std::setprecision(1)
+ << float_div(sumSizeXors, foundXors)
+ << solver->conf.print_times(findTime, time_outs, time_remain)
+ << endl;
+}
+
+void XorFinder::Stats::print() const
+{
+ cout << "c --------- XOR STATS ----------" << endl;
+ print_stats_line("c num XOR found on avg"
+ , float_div(foundXors, numCalls)
+ , "avg size"
+ );
+
+ print_stats_line("c XOR avg size"
+ , float_div(sumSizeXors, foundXors)
+ );
+
+ print_stats_line("c XOR finding time"
+ , findTime
+ , float_div(time_outs, numCalls)*100.0
+ , "time-out"
+ );
+ cout << "c --------- XOR STATS END ----------" << endl;
+}
+
+XorFinder::Stats& XorFinder::Stats::operator+=(const XorFinder::Stats& other)
+{
+ //Time
+ findTime += other.findTime;
+
+ //XOR
+ foundXors += other.foundXors;
+ sumSizeXors += other.sumSizeXors;
+
+ //Usefulness
+ time_outs += other.time_outs;
+
+ return *this;
+}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback