z3-z3-4.13.0.src.shell.dimacs_frontend.cpp Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
dimacs_frontend.cpp
Abstract:
Frontend for reading dimacs input files
Author:
Leonardo de Moura (leonardo) 2011-07-26.
Revision History:
--*/
#include
#include
#include
#include "util/timeout.h"
#include "util/rlimit.h"
#include "util/gparams.h"
#include "sat/dimacs.h"
#include "sat/sat_params.hpp"
#include "sat/sat_solver.h"
#include "sat/tactic/goal2sat.h"
#include "sat/tactic/sat2goal.h"
#include "ast/reg_decl_plugins.h"
#include "tactic/tactic.h"
#include "tactic/fd_solver/fd_solver.h"
extern bool g_display_statistics;
static sat::solver * g_solver = nullptr;
static clock_t g_start_time;
static tactic_ref g_tac;
static statistics g_st;
static void display_statistics() {
clock_t end_time = clock();
if (g_tac && g_display_statistics) {
g_tac->collect_statistics(g_st);
}
if (g_solver && g_display_statistics) {
std::cout.flush();
std::cerr.flush();
g_solver->collect_statistics(g_st);
g_st.update("total time", ((static_cast(end_time) - static_cast(g_start_time)) / CLOCKS_PER_SEC));
g_st.display_smt2(std::cout);
}
g_display_statistics = false;
}
static void on_timeout() {
display_statistics();
_Exit(0);
}
static void STD_CALL on_ctrl_c(int) {
signal (SIGINT, SIG_DFL);
display_statistics();
raise(SIGINT);
}
static void display_model(sat::solver const & s) {
sat::model const & m = s.get_model();
std::cout << "v ";
for (unsigned i = 1; i < m.size(); i++) {
switch (m[i]) {
case l_false: std::cout << "-" << i << " "; break;
case l_undef: break;
case l_true: std::cout << i << " "; break;
}
}
std::cout << "0\n";
}
static void display_core(sat::solver const& s, vector const& tracking_clauses) {
std::cout << "v core\n";
sat::literal_vector const& c = s.get_core();
for (unsigned i = 0; i < c.size(); ++i) {
sat::literal_vector const& cls = tracking_clauses[c[i].var()];
for (unsigned j = 0; j < cls.size(); ++j) {
std::cout << cls[j] << " ";
}
std::cout << "\n";
}
}
static void track_clause(sat::solver& dst,
sat::literal_vector& lits,
sat::literal_vector& assumptions,
vector& tracking_clauses) {
sat::literal lit = sat::literal(dst.mk_var(true, false), false);
tracking_clauses.set(lit.var(), lits);
lits.push_back(~lit);
dst.mk_clause(lits.size(), lits.data());
assumptions.push_back(lit);
}
static void track_clauses(sat::solver const& src,
sat::solver& dst,
sat::literal_vector& assumptions,
vector& tracking_clauses) {
for (sat::bool_var v = 0; v < src.num_vars(); ++v) {
dst.mk_var(false, true);
}
sat::literal_vector lits;
sat::literal lit;
sat::clause * const * it = src.begin_clauses();
sat::clause * const * end = src.end_clauses();
svector bin_clauses;
src.collect_bin_clauses(bin_clauses, false, false);
tracking_clauses.reserve(2*src.num_vars() + static_cast(end - it) + bin_clauses.size());
for (sat::bool_var v = 1; v < src.num_vars(); ++v) {
if (src.value(v) != l_undef) {
bool sign = src.value(v) == l_false;
lits.reset();
lits.push_back(sat::literal(v, sign));
track_clause(dst, lits, assumptions, tracking_clauses);
}
}
for (; it != end; ++it) {
lits.reset();
sat::clause& cls = *(*it);
lits.append(static_cast(cls.end()-cls.begin()), cls.begin());
track_clause(dst, lits, assumptions, tracking_clauses);
}
for (unsigned i = 0; i < bin_clauses.size(); ++i) {
lits.reset();
lits.push_back(bin_clauses[i].first);
lits.push_back(bin_clauses[i].second);
track_clause(dst, lits, assumptions, tracking_clauses);
}
}
void verify_solution(char const * file_name) {
params_ref p = gparams::get_module("sat");
p.set_bool("produce_models", true);
reslimit limit;
sat::solver solver(p, limit);
std::ifstream in(file_name);
if (in.bad() || in.fail()) {
std::cerr << "(error \"failed to open file '" << file_name << "'\")" << std::endl;
exit(ERR_OPEN_FILE);
}
parse_dimacs(in, std::cerr, solver);
sat::model const & m = g_solver->get_model();
for (unsigned i = 1; i < m.size(); i++) {
sat::literal lit(i, false);
switch (m[i]) {
case l_false: lit.neg(); break;
case l_undef: break;
case l_true: break;
}
solver.mk_clause(1, &lit);
}
lbool r = solver.check();
switch (r) {
case l_false:
std::cout << "model checking failed\n";
break;
case l_true:
std::cout << "model validated\n";
break;
default:
std::cout << "inconclusive model\n";
break;
}
}
lbool solve_parallel(sat::solver& s) {
params_ref p = gparams::get_module("sat");
ast_manager m;
reg_decl_plugins(m);
sat2goal s2g;
ref mc;
atom2bool_var a2b(m);
for (unsigned v = 0; v < s.num_vars(); ++v) {
a2b.insert(m.mk_const(symbol(v), m.mk_bool_sort()), v);
}
goal_ref g = alloc(goal, m);
s2g(s, a2b, p, *g, mc);
g_tac = mk_parallel_qffd_tactic(m, p);
std::string reason_unknown;
model_ref md;
labels_vec labels;
proof_ref pr(m);
expr_dependency_ref core(m);
lbool r = check_sat(*g_tac, g, md, labels, pr, core, reason_unknown);
switch (r) {
case l_true:
if (gparams::get_ref().get_bool("model_validate", false)) {
// populate the SAT solver with the model obtained from parallel execution.
for (auto const& kv : a2b) {
sat::literal lit;
bool is_true = m.is_true((*md)(kv.m_key));
lit = sat::literal(kv.m_value, !is_true);
s.mk_clause(1, &lit);
}
// VERIFY(l_true == s.check());
}
break;
case l_false:
break;
default:
break;
}
display_statistics();
g_display_statistics = false;
g_tac = nullptr;
return r;
}
unsigned read_dimacs(char const * file_name) {
g_start_time = clock();
register_on_timeout_proc(on_timeout);
signal(SIGINT, on_ctrl_c);
params_ref p = gparams::get_module("sat");
params_ref par = gparams::get_module("parallel");
p.set_bool("produce_models", true);
p.set_bool("cardinality.solver", false);
sat_params sp(p);
reslimit limit;
sat::solver solver(p, limit);
g_solver = &solver;
if (file_name) {
std::ifstream in(file_name);
if (in.bad() || in.fail()) {
std::cerr << "(error \"failed to open file '" << file_name << "'\")" << std::endl;
exit(ERR_OPEN_FILE);
}
parse_dimacs(in, std::cerr, solver);
}
else {
parse_dimacs(std::cin, std::cerr, solver);
}
IF_VERBOSE(20, solver.display_status(verbose_stream()););
lbool r;
vector tracking_clauses;
params_ref p2;
p2.copy(p);
p2.set_sym("drat.file", symbol::null);
sat::solver solver2(p2, limit);
if (p.get_bool("dimacs.core", false)) {
g_solver = &solver2;
sat::literal_vector assumptions;
track_clauses(solver, solver2, assumptions, tracking_clauses);
r = g_solver->check(assumptions.size(), assumptions.data());
}
else if (par.get_bool("enable", false)) {
r = solve_parallel(solver);
}
else {
r = g_solver->check();
}
switch (r) {
case l_true:
std::cout << "s SATISFIABLE\n";
if (file_name && gparams::get_ref().get_bool("model_validate", false)) verify_solution(file_name);
display_model(*g_solver);
break;
case l_undef:
std::cout << "s UNKNOWN\n";
break;
case l_false:
std::cout << "s UNSATISFIABLE\n";
if (p.get_bool("dimacs.core", false)) {
display_core(*g_solver, tracking_clauses);
}
break;
}
display_statistics();
return 0;
}