Added support for Minisat::SimpSolver + ezSAT frezze() API

This commit is contained in:
Clifford Wolf 2014-02-23 01:35:59 +01:00
parent b76528d8a5
commit dab1612f81
5 changed files with 79 additions and 11 deletions

View File

@ -72,6 +72,7 @@ struct SatGen
} else { } else {
std::string name = pf + stringf(c.wire->width == 1 ? "%s" : "%s [%d]", RTLIL::id2cstr(c.wire->name), c.offset); std::string name = pf + stringf(c.wire->width == 1 ? "%s" : "%s [%d]", RTLIL::id2cstr(c.wire->name), c.offset);
vec.push_back(ez->literal(name)); vec.push_back(ez->literal(name));
ez->freeze(vec.back());
} }
return vec; return vec;
} }

View File

@ -51,9 +51,19 @@ void ezMiniSAT::clear()
} }
foundContradiction = false; foundContradiction = false;
minisatVars.clear(); minisatVars.clear();
#if EZMINISAT_SIMPSOLVER && EZMINISAT_INCREMENTAL
cnfFrozenVars.clear();
#endif
ezSAT::clear(); ezSAT::clear();
} }
#if EZMINISAT_SIMPSOLVER && EZMINISAT_INCREMENTAL
void ezMiniSAT::freeze(int id)
{
cnfFrozenVars.insert(bind(id));
}
#endif
ezMiniSAT *ezMiniSAT::alarmHandlerThis = NULL; ezMiniSAT *ezMiniSAT::alarmHandlerThis = NULL;
clock_t ezMiniSAT::alarmHandlerTimeout = 0; clock_t ezMiniSAT::alarmHandlerTimeout = 0;
@ -92,7 +102,7 @@ contradiction:
modelIdx.push_back(bind(id)); modelIdx.push_back(bind(id));
if (minisatSolver == NULL) { if (minisatSolver == NULL) {
minisatSolver = new EZMINISAT_SOLVER; minisatSolver = new Solver;
minisatSolver->verbosity = EZMINISAT_VERBOSITY; minisatSolver->verbosity = EZMINISAT_VERBOSITY;
} }
@ -106,13 +116,27 @@ contradiction:
while (int(minisatVars.size()) < numCnfVariables()) while (int(minisatVars.size()) < numCnfVariables())
minisatVars.push_back(minisatSolver->newVar()); minisatVars.push_back(minisatSolver->newVar());
#if EZMINISAT_SIMPSOLVER && EZMINISAT_INCREMENTAL
for (auto idx : cnfFrozenVars)
minisatSolver->setFrozen(minisatVars.at(idx > 0 ? idx-1 : -idx-1), true);
cnfFrozenVars.clear();
#endif
for (auto &clause : cnf) { for (auto &clause : cnf) {
Minisat::vec<Minisat::Lit> ps; Minisat::vec<Minisat::Lit> ps;
for (auto idx : clause) for (auto idx : clause) {
if (idx > 0) if (idx > 0)
ps.push(Minisat::mkLit(minisatVars.at(idx-1))); ps.push(Minisat::mkLit(minisatVars.at(idx-1)));
else else
ps.push(Minisat::mkLit(minisatVars.at(-idx-1), true)); ps.push(Minisat::mkLit(minisatVars.at(-idx-1), true));
#if EZMINISAT_SIMPSOLVER
if (minisatSolver->isEliminated(minisatVars.at(idx > 0 ? idx-1 : -idx-1))) {
fprintf(stderr, "Assert in %s:%d failed! Missing call to ezsat->freeze(): %s (lit=%d)\n",
__FILE__, __LINE__, cnfLiteralInfo(idx).c_str(), idx);
abort();
}
#endif
}
if (!minisatSolver->addClause(ps)) if (!minisatSolver->addClause(ps))
goto contradiction; goto contradiction;
} }
@ -122,11 +146,18 @@ contradiction:
Minisat::vec<Minisat::Lit> assumps; Minisat::vec<Minisat::Lit> assumps;
for (auto idx : extraClauses) for (auto idx : extraClauses) {
if (idx > 0) if (idx > 0)
assumps.push(Minisat::mkLit(minisatVars.at(idx-1))); assumps.push(Minisat::mkLit(minisatVars.at(idx-1)));
else else
assumps.push(Minisat::mkLit(minisatVars.at(-idx-1), true)); assumps.push(Minisat::mkLit(minisatVars.at(-idx-1), true));
#if EZMINISAT_SIMPSOLVER
if (minisatSolver->isEliminated(minisatVars.at(idx > 0 ? idx-1 : -idx-1))) {
fprintf(stderr, "Assert in %s:%d failed! Missing call to ezsat->freeze(): %s\n", __FILE__, __LINE__, cnfLiteralInfo(idx).c_str());
abort();
}
#endif
}
sighandler_t old_alarm_sighandler = NULL; sighandler_t old_alarm_sighandler = NULL;
int old_alarm_timeout = 0; int old_alarm_timeout = 0;

View File

@ -20,7 +20,7 @@
#ifndef EZMINISAT_H #ifndef EZMINISAT_H
#define EZMINISAT_H #define EZMINISAT_H
#define EZMINISAT_SOLVER Minisat::Solver #define EZMINISAT_SIMPSOLVER 0
#define EZMINISAT_VERBOSITY 0 #define EZMINISAT_VERBOSITY 0
#define EZMINISAT_INCREMENTAL 1 #define EZMINISAT_INCREMENTAL 1
@ -38,10 +38,19 @@ namespace Minisat {
class ezMiniSAT : public ezSAT class ezMiniSAT : public ezSAT
{ {
private: private:
EZMINISAT_SOLVER *minisatSolver; #if EZMINISAT_SIMPSOLVER
typedef Minisat::SimpSolver Solver;
#else
typedef Minisat::Solver Solver;
#endif
Solver *minisatSolver;
std::vector<int> minisatVars; std::vector<int> minisatVars;
bool foundContradiction; bool foundContradiction;
#if EZMINISAT_SIMPSOLVER && EZMINISAT_INCREMENTAL
std::set<int> cnfFrozenVars;
#endif
static ezMiniSAT *alarmHandlerThis; static ezMiniSAT *alarmHandlerThis;
static clock_t alarmHandlerTimeout; static clock_t alarmHandlerTimeout;
static void alarmHandler(int); static void alarmHandler(int);
@ -50,6 +59,9 @@ public:
ezMiniSAT(); ezMiniSAT();
virtual ~ezMiniSAT(); virtual ~ezMiniSAT();
virtual void clear(); virtual void clear();
#if EZMINISAT_SIMPSOLVER && EZMINISAT_INCREMENTAL
virtual void freeze(int id);
#endif
virtual bool solver(const std::vector<int> &modelExpressions, std::vector<bool> &modelValues, const std::vector<int> &assumptions); virtual bool solver(const std::vector<int> &modelExpressions, std::vector<bool> &modelValues, const std::vector<int> &assumptions);
}; };

View File

@ -29,18 +29,18 @@ const int ezSAT::FALSE = 2;
ezSAT::ezSAT() ezSAT::ezSAT()
{ {
literal("TRUE");
literal("FALSE");
assert(literal("TRUE") == TRUE);
assert(literal("FALSE") == FALSE);
cnfConsumed = false; cnfConsumed = false;
cnfVariableCount = 0; cnfVariableCount = 0;
cnfClausesCount = 0; cnfClausesCount = 0;
solverTimeout = 0; solverTimeout = 0;
solverTimoutStatus = false; solverTimoutStatus = false;
freeze(literal("TRUE"));
freeze(literal("FALSE"));
assert(literal("TRUE") == TRUE);
assert(literal("FALSE") == FALSE);
} }
ezSAT::~ezSAT() ezSAT::~ezSAT()
@ -345,6 +345,10 @@ void ezSAT::clear()
cnfAssumptions.clear(); cnfAssumptions.clear();
} }
void ezSAT::freeze(int)
{
}
void ezSAT::assume(int id) void ezSAT::assume(int id)
{ {
cnfAssumptions.insert(id); cnfAssumptions.insert(id);
@ -462,6 +466,23 @@ int ezSAT::bound(int id) const
return 0; return 0;
} }
std::string ezSAT::cnfLiteralInfo(int idx) const
{
for (size_t i = 0; i < cnfLiteralVariables.size(); i++) {
if (cnfLiteralVariables[i] == idx)
return to_string(i+1);
if (cnfLiteralVariables[i] == -idx)
return "NOT " + to_string(i+1);
}
for (size_t i = 0; i < cnfExpressionVariables.size(); i++) {
if (cnfExpressionVariables[i] == idx)
return to_string(-i-1);
if (cnfExpressionVariables[i] == -idx)
return "NOT " + to_string(-i-1);
}
return "<unnamed>";
}
int ezSAT::bind(int id) int ezSAT::bind(int id)
{ {
if (id >= 0) { if (id >= 0) {

View File

@ -141,6 +141,7 @@ public:
// manage CNF (usually only accessed by SAT solvers) // manage CNF (usually only accessed by SAT solvers)
virtual void clear(); virtual void clear();
virtual void freeze(int id);
void assume(int id); void assume(int id);
int bind(int id); int bind(int id);
@ -154,6 +155,8 @@ public:
void consumeCnf(); void consumeCnf();
void consumeCnf(std::vector<std::vector<int>> &cnf); void consumeCnf(std::vector<std::vector<int>> &cnf);
std::string cnfLiteralInfo(int idx) const;
// simple helpers for build expressions easily // simple helpers for build expressions easily
struct _V { struct _V {