Add option to choose solver

This commit is contained in:
Leo Alt
2021-07-27 17:14:21 +02:00
parent e3184c737a
commit 6c8ecfa82c
53 changed files with 650 additions and 92 deletions
+7 -5
View File
@@ -40,7 +40,8 @@ SMTPortfolio::SMTPortfolio(
):
SolverInterface(_queryTimeout)
{
m_solvers.emplace_back(make_unique<SMTLib2Interface>(move(_smtlib2Responses), move(_smtCallback), m_queryTimeout));
if (_enabledSolvers.smtlib2)
m_solvers.emplace_back(make_unique<SMTLib2Interface>(move(_smtlib2Responses), move(_smtCallback), m_queryTimeout));
#ifdef HAVE_Z3
if (_enabledSolvers.z3 && Z3Interface::available())
m_solvers.emplace_back(make_unique<Z3Interface>(m_queryTimeout));
@@ -143,10 +144,11 @@ pair<CheckResult, vector<string>> SMTPortfolio::check(vector<Expression> const&
vector<string> SMTPortfolio::unhandledQueries()
{
// This code assumes that the constructor guarantees that
// SmtLib2Interface is in position 0.
smtAssert(!m_solvers.empty(), "");
smtAssert(dynamic_cast<SMTLib2Interface*>(m_solvers.front().get()), "");
return m_solvers.front()->unhandledQueries();
// SmtLib2Interface is in position 0, if enabled.
if (!m_solvers.empty())
if (auto smtlib2 = dynamic_cast<SMTLib2Interface*>(m_solvers.front().get()))
return smtlib2->unhandledQueries();
return {};
}
bool SMTPortfolio::solverAnswered(CheckResult result)
+64 -6
View File
@@ -23,10 +23,13 @@
#include <libsolutil/Common.h>
#include <range/v3/view.hpp>
#include <cstdio>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
@@ -36,16 +39,71 @@ namespace solidity::smtutil
struct SMTSolverChoice
{
bool cvc4 = false;
bool smtlib2 = false;
bool z3 = false;
static constexpr SMTSolverChoice All() { return {true, true}; }
static constexpr SMTSolverChoice CVC4() { return {true, false}; }
static constexpr SMTSolverChoice Z3() { return {false, true}; }
static constexpr SMTSolverChoice None() { return {false, false}; }
static constexpr SMTSolverChoice All() { return {true, true, true}; }
static constexpr SMTSolverChoice CVC4() { return {true, false, false}; }
static constexpr SMTSolverChoice SMTLIB2() { return {false, true, false}; }
static constexpr SMTSolverChoice Z3() { return {false, false, true}; }
static constexpr SMTSolverChoice None() { return {false, false, false}; }
static std::optional<SMTSolverChoice> fromString(std::string const& _solvers)
{
SMTSolverChoice solvers;
if (_solvers == "all")
{
smtAssert(solvers.setSolver("cvc4"), "");
smtAssert(solvers.setSolver("smtlib2"), "");
smtAssert(solvers.setSolver("z3"), "");
}
else
for (auto&& s: _solvers | ranges::views::split(',') | ranges::to<std::vector<std::string>>())
if (!solvers.setSolver(s))
return {};
return solvers;
}
SMTSolverChoice& operator&(SMTSolverChoice const& _other)
{
cvc4 &= _other.cvc4;
smtlib2 &= _other.smtlib2;
z3 &= _other.z3;
return *this;
}
SMTSolverChoice& operator&=(SMTSolverChoice const& _other)
{
return *this & _other;
}
bool operator!=(SMTSolverChoice const& _other) const noexcept { return !(*this == _other); }
bool operator==(SMTSolverChoice const& _other) const noexcept
{
return cvc4 == _other.cvc4 &&
smtlib2 == _other.smtlib2 &&
z3 == _other.z3;
}
bool setSolver(std::string const& _solver)
{
static std::set<std::string> const solvers{"cvc4", "smtlib2", "z3"};
if (!solvers.count(_solver))
return false;
if (_solver == "cvc4")
cvc4 = true;
else if (_solver == "smtlib2")
smtlib2 = true;
else if (_solver == "z3")
z3 = true;
return true;
}
bool none() { return !some(); }
bool some() { return cvc4 || z3; }
bool all() { return cvc4 && z3; }
bool some() { return cvc4 || smtlib2 || z3; }
bool all() { return cvc4 && smtlib2 && z3; }
};
enum class CheckResult