This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/packages/bee/cryptominisat-2.5.1/Solver/VarReplacer.cpp
Vitor Santos Costa 16015bd8e6 bee
2019-04-22 12:15:21 +01:00

522 lines
16 KiB
C++
Executable File

/***********************************************************************************
CryptoMiniSat -- Copyright (c) 2009 Mate Soos
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************************************/
#include "VarReplacer.h"
#include <iostream>
#include <iomanip>
#include "ClauseCleaner.h"
#include "PartHandler.h"
#include "time_mem.h"
//#define VERBOSE_DEBUG
//#define DEBUG_REPLACER
//#define REPLACE_STATISTICS
#ifdef VERBOSE_DEBUG
#include <iostream>
using std::cout;
using std::endl;
#endif
VarReplacer::VarReplacer(Solver& _solver) :
replacedLits(0)
, replacedVars(0)
, lastReplacedVars(0)
, solver(_solver)
{
}
VarReplacer::~VarReplacer()
{
for (uint i = 0; i != clauses.size(); i++)
clauseFree(clauses[i]);
}
const bool VarReplacer::performReplaceInternal()
{
#ifdef VERBOSE_DEBUG
cout << "Replacer started." << endl;
#endif
double time = cpuTime();
#ifdef REPLACE_STATISTICS
uint numRedir = 0;
for (uint i = 0; i < table.size(); i++) {
if (table[i].var() != i)
numRedir++;
}
std::cout << "Number of trees:" << reverseTable.size() << std::endl;
std::cout << "Number of redirected nodes:" << numRedir << std::endl;
/*map<Var, vector<Var> >::iterator it = reverseTable.begin();
map<Var, vector<Var> >::iterator end = reverseTable.end();
for (;it != end; it++) {
std::cout << "Tree size: " << it->second.size() << std::endl;
}*/
#endif //REPLACE_STATISTICS
solver.clauseCleaner->removeAndCleanAll(true);
if (!solver.ok) return false;
solver.testAllClauseAttach();
#ifdef VERBOSE_DEBUG
{
uint i = 0;
for (vector<Lit>::const_iterator it = table.begin(); it != table.end(); it++, i++) {
if (it->var() == i) continue;
cout << "Replacing var " << i+1 << " with Lit " << (it->sign() ? "-" : "") << it->var()+1 << endl;
}
}
#endif
Var var = 0;
const vec<char>& removedVars = solver.xorSubsumer->getVarElimed();
const vec<lbool>& removedVars2 = solver.partHandler->getSavedState();
const vec<char>& removedVars3 = solver.subsumer->getVarElimed();
for (vector<Lit>::const_iterator it = table.begin(); it != table.end(); it++, var++) {
if (it->var() == var || removedVars[it->var()] || removedVars2[it->var()] != l_Undef || removedVars3[it->var()]) continue;
#ifdef VERBOSE_DEBUG
cout << "Setting var " << var+1 << " to a non-decision var" << endl;
#endif
bool wasDecisionVar = solver.decision_var[var];
solver.setDecisionVar(var, false);
solver.setDecisionVar(it->var(), true);
uint32_t& activity1 = solver.activity[var];
uint32_t& activity2 = solver.activity[it->var()];
if (wasDecisionVar && activity1 > activity2) {
activity2 = activity1;
solver.order_heap.update(it->var());
solver.polarity[it->var()] = solver.polarity[var]^it->sign();
}
activity1 = 0;
solver.order_heap.update(var);
}
assert(solver.order_heap.heapProperty());
if (solver.verbosity >= 2)
std::cout << "c | Replacing " << std::setw(8) << replacedVars-lastReplacedVars << " vars" << std::flush;
lastReplacedVars = replacedVars;
solver.testAllClauseAttach();
if (!replace_set(solver.binaryClauses, true)) goto end;
if (!replace_set(solver.clauses, false)) goto end;
if (!replace_set(solver.learnts, false)) goto end;
if (!replace_set(solver.xorclauses)) goto end;
solver.testAllClauseAttach();
end:
for (uint i = 0; i != clauses.size(); i++)
solver.removeClause(*clauses[i]);
clauses.clear();
if (solver.verbosity >= 2) {
std::cout << " Replaced " << std::setw(8) << replacedLits<< " lits"
<< " Time: " << std::setw(8) << std::fixed << std::setprecision(2) << cpuTime()-time << " s "
<< std::setw(10) << " |" << std::endl;
}
replacedLits = 0;
solver.order_heap.filter(Solver::VarFilter(solver));
return solver.ok;
}
const bool VarReplacer::replace_set(vec<XorClause*>& cs)
{
XorClause **a = cs.getData();
XorClause **r = a;
for (XorClause **end = a + cs.size(); r != end; r++) {
XorClause& c = **r;
bool changed = false;
Var origVar1 = c[0].var();
Var origVar2 = c[1].var();
for (Lit *l = &c[0], *end2 = l + c.size(); l != end2; l++) {
Lit newlit = table[l->var()];
if (newlit.var() != l->var()) {
changed = true;
*l = Lit(newlit.var(), false);
c.invert(newlit.sign());
c.setVarChanged();
replacedLits++;
}
}
if (changed && handleUpdatedClause(c, origVar1, origVar2)) {
if (!solver.ok) {
for(;r != end; r++) clauseFree(*r);
cs.shrink(r-a);
return false;
}
c.setRemoved();
solver.freeLater.push(&c);
} else {
*a++ = *r;
}
}
cs.shrink(r-a);
return solver.ok;
}
const bool VarReplacer::handleUpdatedClause(XorClause& c, const Var origVar1, const Var origVar2)
{
uint origSize = c.size();
std::sort(c.getData(), c.getDataEnd());
Lit p;
uint32_t i, j;
for (i = j = 0, p = lit_Undef; i != c.size(); i++) {
if (c[i].var() == p.var()) {
//added, but easily removed
j--;
p = lit_Undef;
if (!solver.assigns[c[i].var()].isUndef())
c.invert(solver.assigns[c[i].var()].getBool());
} else if (solver.assigns[c[i].var()].isUndef()) //just add
c[j++] = p = c[i];
else c.invert(solver.assigns[c[i].var()].getBool()); //modify xor_clause_inverted instead of adding
}
c.shrink(i - j);
#ifdef VERBOSE_DEBUG
cout << "xor-clause after replacing: ";
c.plainPrint();
#endif
switch (c.size()) {
case 0:
solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
if (!c.xor_clause_inverted())
solver.ok = false;
return true;
case 1:
solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
solver.uncheckedEnqueue(Lit(c[0].var(), c.xor_clause_inverted()));
solver.ok = (solver.propagate() == NULL);
return true;
case 2: {
solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
c[0] = c[0].unsign();
c[1] = c[1].unsign();
addBinaryXorClause(c, c.xor_clause_inverted(), c.getGroup(), true);
return true;
}
default:
solver.detachModifiedClause(origVar1, origVar2, origSize, &c);
solver.attachClause(c);
return false;
}
assert(false);
return false;
}
const bool VarReplacer::replace_set(vec<Clause*>& cs, const bool binClauses)
{
Clause **a = cs.getData();
Clause **r = a;
for (Clause **end = a + cs.size(); r != end; r++) {
Clause& c = **r;
bool changed = false;
Lit origLit1 = c[0];
Lit origLit2 = c[1];
for (Lit *l = c.getData(), *end2 = l + c.size(); l != end2; l++) {
if (table[l->var()].var() != l->var()) {
changed = true;
*l = table[l->var()] ^ l->sign();
c.setVarChanged();
replacedLits++;
}
}
if (changed && handleUpdatedClause(c, origLit1, origLit2)) {
if (!solver.ok) {
for(;r != end; r++) clauseFree(*r);
cs.shrink(r-a);
return false;
}
} else {
if (!binClauses && c.size() == 2) {
solver.becameBinary++;
solver.binaryClauses.push(&c);
} else
*a++ = *r;
}
}
cs.shrink(r-a);
return solver.ok;
}
const bool VarReplacer::handleUpdatedClause(Clause& c, const Lit origLit1, const Lit origLit2)
{
bool satisfied = false;
std::sort(c.getData(), c.getData() + c.size());
Lit p;
uint32_t i, j;
const uint origSize = c.size();
for (i = j = 0, p = lit_Undef; i != origSize; i++) {
if (solver.value(c[i]) == l_True || c[i] == ~p) {
satisfied = true;
break;
}
else if (solver.value(c[i]) != l_False && c[i] != p)
c[j++] = p = c[i];
}
c.shrink(i - j);
if (satisfied) {
solver.detachModifiedClause(origLit1, origLit2, origSize, &c);
return true;
}
switch(c.size()) {
case 0:
solver.detachModifiedClause(origLit1, origLit2, origSize, &c);
solver.ok = false;
return true;
case 1 :
solver.detachModifiedClause(origLit1, origLit2, origSize, &c);
solver.uncheckedEnqueue(c[0]);
solver.ok = (solver.propagate() == NULL);
return true;
default:
solver.detachModifiedClause(origLit1, origLit2, origSize, &c);
solver.attachClause(c);
return false;
}
assert(false);
return false;
}
const vector<Var> VarReplacer::getReplacingVars() const
{
vector<Var> replacingVars;
for(map<Var, vector<Var> >::const_iterator it = reverseTable.begin(), end = reverseTable.end(); it != end; it++) {
replacingVars.push_back(it->first);
}
return replacingVars;
}
void VarReplacer::extendModelPossible() const
{
#ifdef VERBOSE_DEBUG
std::cout << "extendModelPossible() called" << std::endl;
#endif //VERBOSE_DEBUG
uint i = 0;
for (vector<Lit>::const_iterator it = table.begin(); it != table.end(); it++, i++) {
if (it->var() == i) continue;
#ifdef VERBOSE_DEBUG
cout << "Extending model: var "; solver.printLit(Lit(i, false));
cout << " to "; solver.printLit(*it);
cout << endl;
#endif
if (solver.assigns[it->var()] != l_Undef) {
if (solver.assigns[i] == l_Undef) {
bool val = (solver.assigns[it->var()] == l_False);
solver.uncheckedEnqueue(Lit(i, val ^ it->sign()));
} else {
assert(solver.assigns[i].getBool() == (solver.assigns[it->var()].getBool() ^ it->sign()));
}
}
solver.ok = (solver.propagate() == NULL);
assert(solver.ok);
}
}
void VarReplacer::extendModelImpossible(Solver& solver2) const
{
#ifdef VERBOSE_DEBUG
std::cout << "extendModelImpossible() called" << std::endl;
#endif //VERBOSE_DEBUG
vec<Lit> tmpClause;
uint i = 0;
for (vector<Lit>::const_iterator it = table.begin(); it != table.end(); it++, i++) {
if (it->var() == i) continue;
if (solver.assigns[it->var()] == l_Undef) {
assert(solver.assigns[it->var()] == l_Undef);
assert(solver.assigns[i] == l_Undef);
tmpClause.clear();
tmpClause.push(Lit(it->var(), true));
tmpClause.push(Lit(i, it->sign()));
solver2.addClause(tmpClause);
assert(solver2.ok);
tmpClause.clear();
tmpClause.push(Lit(it->var(), false));
tmpClause.push(Lit(i, it->sign()^true));
solver2.addClause(tmpClause);
assert(solver2.ok);
}
}
}
template<class T>
const bool VarReplacer::replace(T& ps, const bool xor_clause_inverted, const uint group)
{
// replace ps[0] with ps[1] (or -ps[1]) when xor_clause_inverted==true (or false)
#ifdef VERBOSE_DEBUG
std::cout << "replace() called with var " << ps[0].var()+1 << " and var " << ps[1].var()+1 << " with xor_clause_inverted " << xor_clause_inverted << std::endl;
#endif
assert(ps.size() == 2);
assert(!ps[0].sign());
assert(!ps[1].sign());
#ifdef DEBUG_REPLACER
assert(solver.assigns[ps[0].var()].isUndef());
assert(solver.assigns[ps[1].var()].isUndef());
#endif
Lit lit1 = table[ps[0].var()]; // lit1=ps[0] or to a' where already know that ps[0] == a'
Lit lit2 = table[ps[1].var()];
if(lit1.var() == lit2.var()) { // cycle
if(lit1.sign() ^ lit2.sign() == xor_clause_inverted) {
#ifdef VERBOSE_DEBUG
cout << "Inverted cycle in var-replacement -> UNSAT" << endl;
#endif
return (solver.ok = false);
}
return solver.ok;
}
if(lit1.sign() ^ !xor_clause_inverted) {
lit2 = ~lit2;
}
setAllThatPointsHereTo(lit1.var(), lit2);
replacedVars++;
addBinaryXorClause(ps, xor_clause_inverted, group);
return true;
}
template const bool VarReplacer::replace(vec<Lit>& ps, const bool xor_clause_inverted, const uint group);
template const bool VarReplacer::replace(XorClause& ps, const bool xor_clause_inverted, const uint group);
template<class T>
void VarReplacer::addBinaryXorClause(T& ps, const bool xor_clause_inverted, const uint group, const bool internal)
{
assert(internal || (replacedVars > lastReplacedVars));
#ifdef DEBUG_REPLACER
assert(!ps[0].sign());
assert(!ps[1].sign());
#endif
Clause* c;
ps[0] ^= xor_clause_inverted;
c = Clause_new(ps, group, false);
if (internal) {
solver.binaryClauses.push(c);
solver.becameBinary++;
} else
clauses.push(c);
solver.attachClause(*c);
ps[0] ^= true;
ps[1] ^= true;
c = Clause_new(ps, group, false);
if (internal) {
solver.binaryClauses.push(c);
solver.becameBinary++;
} else
clauses.push(c);
solver.attachClause(*c);
}
template void VarReplacer::addBinaryXorClause(vec<Lit>& ps, const bool xor_clause_inverted, const uint group, const bool internal);
template void VarReplacer::addBinaryXorClause(XorClause& ps, const bool xor_clause_inverted, const uint group, const bool internal);
/*
bool VarReplacer::alreadyIn(const Var var, const Lit lit)
{
Lit lit2 = table[var];
if (lit2.var() == lit.var()) {
if (lit2.sign() != lit.sign()) {
#ifdef VERBOSE_DEBUG
cout << "Inverted cycle in var-replacement -> UNSAT" << endl;
#endif
solver.ok = false;
}
return true;
}
lit2 = table[lit.var()];
if (lit2.var() == var) {
if (lit2.sign() != lit.sign()) {
#ifdef VERBOSE_DEBUG
cout << "Inverted cycle in var-replacement -> UNSAT" << endl;
#endif
solver.ok = false;
}
return true;
}
return false;
}
*/
void VarReplacer::setAllThatPointsHereTo(const Var var, const Lit lit)
{
map<Var, vector<Var> >::iterator it = reverseTable.find(var);
if (it != reverseTable.end()) {
for(vector<Var>::const_iterator it2 = it->second.begin(), end = it->second.end(); it2 != end; it2++) {
assert(table[*it2].var() == var);
if (lit.var() != *it2) {
table[*it2] = lit ^ table[*it2].sign();
reverseTable[lit.var()].push_back(*it2);
}
}
reverseTable.erase(it);
}
table[var] = lit;
reverseTable[lit.var()].push_back(var);
}
void VarReplacer::newVar()
{
table.push_back(Lit(table.size(), false));
}
void VarReplacer::reattachInternalClauses()
{
Clause **i = clauses.getData();
Clause **j = i;
for (Clause **end = clauses.getDataEnd(); i != end; i++) {
if (solver.value((**i)[0]) == l_Undef &&
solver.value((**i)[1]) == l_Undef) {
solver.attachClause(**i);
*j++ = *i;
}
}
clauses.shrink(i-j);
}