mirror of
https://github.com/Z3Prover/z3
synced 2025-04-22 16:45:31 +00:00
merge
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
e9d615e309
204 changed files with 4620 additions and 2435 deletions
|
@ -166,6 +166,8 @@ foreach (header ${libz3_public_headers})
|
|||
set_property(TARGET libz3 APPEND PROPERTY
|
||||
PUBLIC_HEADER "${CMAKE_SOURCE_DIR}/src/api/${header}")
|
||||
endforeach()
|
||||
set_property(TARGET libz3 APPEND PROPERTY
|
||||
PUBLIC_HEADER "${CMAKE_CURRENT_BINARY_DIR}/util/z3_version.h")
|
||||
|
||||
install(TARGETS libz3
|
||||
EXPORT Z3_EXPORTED_TARGETS
|
||||
|
|
|
@ -468,7 +468,7 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_get_decl_symbol_parameter(c, d, idx);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(d, 0);
|
||||
CHECK_VALID_AST(d, nullptr);
|
||||
if (idx >= to_func_decl(d)->get_num_parameters()) {
|
||||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||
return nullptr;
|
||||
|
@ -486,7 +486,7 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_get_decl_sort_parameter(c, d, idx);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(d, 0);
|
||||
CHECK_VALID_AST(d, nullptr);
|
||||
if (idx >= to_func_decl(d)->get_num_parameters()) {
|
||||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||
RETURN_Z3(nullptr);
|
||||
|
@ -504,7 +504,7 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_get_decl_ast_parameter(c, d, idx);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(d, 0);
|
||||
CHECK_VALID_AST(d, nullptr);
|
||||
if (idx >= to_func_decl(d)->get_num_parameters()) {
|
||||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||
RETURN_Z3(nullptr);
|
||||
|
@ -522,7 +522,7 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_get_decl_func_decl_parameter(c, d, idx);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(d, 0);
|
||||
CHECK_VALID_AST(d, nullptr);
|
||||
if (idx >= to_func_decl(d)->get_num_parameters()) {
|
||||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||
RETURN_Z3(nullptr);
|
||||
|
@ -596,7 +596,7 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_get_domain(c, d, i);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(d, 0);
|
||||
CHECK_VALID_AST(d, nullptr);
|
||||
if (i >= to_func_decl(d)->get_arity()) {
|
||||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||
RETURN_Z3(nullptr);
|
||||
|
|
|
@ -19,7 +19,7 @@ Revision History:
|
|||
--*/
|
||||
#include<typeinfo>
|
||||
#include "api/api_context.h"
|
||||
#include "util/version.h"
|
||||
#include "util/z3_version.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "api/api_log_macros.h"
|
||||
|
|
|
@ -379,10 +379,8 @@ extern "C" {
|
|||
for (unsigned i = 0; i < coll.m_rules.size(); ++i) {
|
||||
to_fixedpoint_ref(d)->add_rule(coll.m_rules[i].get(), coll.m_names[i]);
|
||||
}
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
to_fixedpoint_ref(d)->ctx().assert_expr(*it);
|
||||
for (expr * e : ctx.assertions()) {
|
||||
to_fixedpoint_ref(d)->ctx().assert_expr(e);
|
||||
}
|
||||
|
||||
return of_ast_vector(v);
|
||||
|
@ -717,5 +715,4 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
|
|
@ -1,113 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Arie Gurfinkel
|
||||
|
||||
Module Name:
|
||||
|
||||
api_datalog_spacer.inc
|
||||
|
||||
Abstract:
|
||||
|
||||
Spacer-specific datalog API
|
||||
|
||||
Author:
|
||||
|
||||
Arie Gurfinkel (arie)
|
||||
|
||||
Notes:
|
||||
this file is included at the bottom of api_datalog.cpp
|
||||
|
||||
--*/
|
||||
Z3_lbool Z3_API Z3_fixedpoint_query_from_lvl (Z3_context c, Z3_fixedpoint d, Z3_ast q, unsigned lvl) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_query_from_lvl (c, d, q, lvl);
|
||||
RESET_ERROR_CODE();
|
||||
lbool r = l_undef;
|
||||
unsigned timeout = to_fixedpoint(d)->m_params.get_uint("timeout", mk_c(c)->get_timeout());
|
||||
unsigned rlimit = to_fixedpoint(d)->m_params.get_uint("rlimit", mk_c(c)->get_rlimit());
|
||||
{
|
||||
scoped_rlimit _rlimit(mk_c(c)->m().limit(), rlimit);
|
||||
cancel_eh<reslimit> eh(mk_c(c)->m().limit());
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
scoped_timer timer(timeout, &eh);
|
||||
try {
|
||||
r = to_fixedpoint_ref(d)->ctx().query_from_lvl (to_expr(q), lvl);
|
||||
}
|
||||
catch (z3_exception& ex) {
|
||||
mk_c(c)->handle_exception(ex);
|
||||
r = l_undef;
|
||||
}
|
||||
to_fixedpoint_ref(d)->ctx().cleanup();
|
||||
}
|
||||
return of_lbool(r);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_fixedpoint_get_ground_sat_answer(Z3_context c, Z3_fixedpoint d) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_ground_sat_answer(c, d);
|
||||
RESET_ERROR_CODE();
|
||||
expr* e = to_fixedpoint_ref(d)->ctx().get_ground_sat_answer();
|
||||
mk_c(c)->save_ast_trail(e);
|
||||
RETURN_Z3(of_expr(e));
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
Z3_ast_vector Z3_API Z3_fixedpoint_get_rules_along_trace(
|
||||
Z3_context c,
|
||||
Z3_fixedpoint d)
|
||||
{
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_rules_along_trace(c, d);
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
Z3_ast_vector_ref* v = alloc(Z3_ast_vector_ref, *mk_c(c), m);
|
||||
mk_c(c)->save_object(v);
|
||||
expr_ref_vector rules(m);
|
||||
svector<symbol> names;
|
||||
|
||||
to_fixedpoint_ref(d)->ctx().get_rules_along_trace_as_formulas(rules, names);
|
||||
for (unsigned i = 0; i < rules.size(); ++i) {
|
||||
v->m_ast_vector.push_back(rules[i].get());
|
||||
}
|
||||
RETURN_Z3(of_ast_vector(v));
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
Z3_symbol Z3_API Z3_fixedpoint_get_rule_names_along_trace(
|
||||
Z3_context c,
|
||||
Z3_fixedpoint d)
|
||||
{
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_rule_names_along_trace(c, d);
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
Z3_ast_vector_ref* v = alloc(Z3_ast_vector_ref, *mk_c(c), m);
|
||||
mk_c(c)->save_object(v);
|
||||
expr_ref_vector rules(m);
|
||||
svector<symbol> names;
|
||||
std::stringstream ss;
|
||||
|
||||
to_fixedpoint_ref(d)->ctx().get_rules_along_trace_as_formulas(rules, names);
|
||||
for (unsigned i = 0; i < names.size(); ++i) {
|
||||
ss << ";" << names[i].str();
|
||||
}
|
||||
RETURN_Z3(of_symbol(symbol(ss.str().substr(1).c_str())));
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_add_invariant(Z3_context c, Z3_fixedpoint d, Z3_func_decl pred, Z3_ast property) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_add_invariant(c, d, pred, property);
|
||||
RESET_ERROR_CODE();
|
||||
to_fixedpoint_ref(d)->ctx ().add_invariant(to_func_decl(pred), to_expr(property));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_fixedpoint_get_reachable(Z3_context c, Z3_fixedpoint d, Z3_func_decl pred) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_reachable(c, d, pred);
|
||||
RESET_ERROR_CODE();
|
||||
expr_ref r = to_fixedpoint_ref(d)->ctx().get_reachable(to_func_decl(pred));
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
RETURN_Z3(of_expr(r.get()));
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
|
@ -163,7 +163,7 @@ extern "C" {
|
|||
if (to_goal_ref(g)->mc())
|
||||
(*to_goal_ref(g)->mc())(m_ref->m_model);
|
||||
RETURN_Z3(of_model(m_ref));
|
||||
Z3_CATCH_RETURN(0);
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
Z3_goal Z3_API Z3_goal_translate(Z3_context c, Z3_goal g, Z3_context target) {
|
||||
|
|
|
@ -19,7 +19,7 @@ Revision History:
|
|||
#include "api/z3.h"
|
||||
#include "api/api_log_macros.h"
|
||||
#include "util/util.h"
|
||||
#include "util/version.h"
|
||||
#include "util/z3_version.h"
|
||||
|
||||
std::ostream * g_z3_log = nullptr;
|
||||
bool g_z3_log_enabled = false;
|
||||
|
|
|
@ -124,10 +124,16 @@ extern "C" {
|
|||
}
|
||||
|
||||
|
||||
Z3_lbool Z3_API Z3_optimize_check(Z3_context c, Z3_optimize o) {
|
||||
Z3_lbool Z3_API Z3_optimize_check(Z3_context c, Z3_optimize o, unsigned num_assumptions, Z3_ast const assumptions[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_optimize_check(c, o);
|
||||
LOG_Z3_optimize_check(c, o, num_assumptions, assumptions);
|
||||
RESET_ERROR_CODE();
|
||||
for (unsigned i = 0; i < num_assumptions; i++) {
|
||||
if (!is_expr(to_ast(assumptions[i]))) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG, "assumption is not an expression");
|
||||
return Z3_L_UNDEF;
|
||||
}
|
||||
}
|
||||
lbool r = l_undef;
|
||||
cancel_eh<reslimit> eh(mk_c(c)->m().limit());
|
||||
unsigned timeout = to_optimize_ptr(o)->get_params().get_uint("timeout", mk_c(c)->get_timeout());
|
||||
|
@ -137,7 +143,9 @@ extern "C" {
|
|||
scoped_timer timer(timeout, &eh);
|
||||
scoped_rlimit _rlimit(mk_c(c)->m().limit(), rlimit);
|
||||
try {
|
||||
r = to_optimize_ptr(o)->optimize();
|
||||
expr_ref_vector asms(mk_c(c)->m());
|
||||
asms.append(num_assumptions, to_exprs(assumptions));
|
||||
r = to_optimize_ptr(o)->optimize(asms);
|
||||
}
|
||||
catch (z3_exception& ex) {
|
||||
if (!mk_c(c)->m().canceled()) {
|
||||
|
@ -157,6 +165,22 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
Z3_ast_vector Z3_API Z3_optimize_get_unsat_core(Z3_context c, Z3_optimize o) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_optimize_get_unsat_core(c, o);
|
||||
RESET_ERROR_CODE();
|
||||
expr_ref_vector core(mk_c(c)->m());
|
||||
to_optimize_ptr(o)->get_unsat_core(core);
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
|
||||
mk_c(c)->save_object(v);
|
||||
for (expr* e : core) {
|
||||
v->m_ast_vector.push_back(e);
|
||||
}
|
||||
RETURN_Z3(of_ast_vector(v));
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
||||
Z3_string Z3_API Z3_optimize_get_reason_unknown(Z3_context c, Z3_optimize o) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_optimize_to_string(c, o);
|
||||
|
@ -330,10 +354,8 @@ extern "C" {
|
|||
return;
|
||||
}
|
||||
|
||||
ptr_vector<expr>::const_iterator it = ctx->begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx->end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
to_optimize_ptr(opt)->add_hard_constraint(*it);
|
||||
for (expr * e : ctx->assertions()) {
|
||||
to_optimize_ptr(opt)->add_hard_constraint(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,10 +71,8 @@ extern "C" {
|
|||
SET_ERROR_CODE(Z3_PARSER_ERROR, errstrm.str().c_str());
|
||||
return of_ast_vector(v);
|
||||
}
|
||||
ptr_vector<expr>::const_iterator it = ctx->begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx->end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
v->m_ast_vector.push_back(*it);
|
||||
for (expr * e : ctx->assertions()) {
|
||||
v->m_ast_vector.push_back(e);
|
||||
}
|
||||
return of_ast_vector(v);
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*++
|
||||
Copyright (c) 2018 Microsoft Corporation
|
||||
Copyright (c) Microsoft Corporation, Arie Gurfinkel 2017
|
||||
|
||||
Module Name:
|
||||
|
||||
|
@ -70,39 +70,39 @@ extern "C"
|
|||
}
|
||||
|
||||
Z3_ast Z3_API Z3_qe_model_project_skolem (Z3_context c,
|
||||
Z3_model m,
|
||||
Z3_model mdl,
|
||||
unsigned num_bounds,
|
||||
Z3_app const bound[],
|
||||
Z3_ast body,
|
||||
Z3_ast_map map)
|
||||
{
|
||||
Z3_TRY;
|
||||
LOG_Z3_qe_model_project_skolem (c, m, num_bounds, bound, body, map);
|
||||
LOG_Z3_qe_model_project_skolem (c, mdl, num_bounds, bound, body, map);
|
||||
RESET_ERROR_CODE();
|
||||
|
||||
ast_manager& man = mk_c(c)->m ();
|
||||
app_ref_vector vars(man);
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
app_ref_vector vars(m);
|
||||
if (!to_apps(num_bounds, bound, vars)) {
|
||||
RETURN_Z3(nullptr);
|
||||
}
|
||||
|
||||
expr_ref result (mk_c(c)->m ());
|
||||
expr_ref result (m);
|
||||
result = to_expr (body);
|
||||
model_ref model (to_model_ref (m));
|
||||
expr_map emap (man);
|
||||
model_ref model (to_model_ref (mdl));
|
||||
expr_map emap (m);
|
||||
|
||||
spacer::qe_project (mk_c(c)->m (), vars, result, model, emap);
|
||||
mk_c(c)->save_ast_trail (result.get ());
|
||||
spacer::qe_project(m, vars, result, model, emap);
|
||||
mk_c(c)->save_ast_trail(result);
|
||||
|
||||
obj_map<ast, ast*> &map_z3 = to_ast_map_ref(map);
|
||||
|
||||
for (expr_map::iterator it = emap.begin(), end = emap.end(); it != end; ++it){
|
||||
man.inc_ref(&(it->get_key()));
|
||||
man.inc_ref(it->get_value());
|
||||
map_z3.insert(&(it->get_key()), it->get_value());
|
||||
for (auto& kv : emap) {
|
||||
m.inc_ref(kv.m_key);
|
||||
m.inc_ref(kv.m_value);
|
||||
map_z3.insert(kv.m_key, kv.m_value);
|
||||
}
|
||||
|
||||
return of_expr (result.get ());
|
||||
return of_expr (result);
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
@ -124,9 +124,9 @@ extern "C"
|
|||
|
||||
expr_ref result (mk_c(c)->m ());
|
||||
result = mk_and (lits);
|
||||
mk_c(c)->save_ast_trail (result.get ());
|
||||
mk_c(c)->save_ast_trail (result);
|
||||
|
||||
return of_expr (result.get ());
|
||||
return of_expr (result);
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
@ -138,8 +138,8 @@ extern "C"
|
|||
ast_ref_vector &vVars = to_ast_vector_ref (vars);
|
||||
|
||||
app_ref_vector vApps (mk_c(c)->m());
|
||||
for (unsigned i = 0; i < vVars.size (); ++i) {
|
||||
app *a = to_app (vVars.get (i));
|
||||
for (ast* v : vVars) {
|
||||
app * a = to_app(v);
|
||||
if (a->get_kind () != AST_APP) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG, nullptr);
|
||||
RETURN_Z3(nullptr);
|
||||
|
@ -162,7 +162,7 @@ extern "C"
|
|||
}
|
||||
}
|
||||
|
||||
mk_c(c)->save_ast_trail (result.get ());
|
||||
mk_c(c)->save_ast_trail (result);
|
||||
return of_expr (result);
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ extern "C" {
|
|||
expr_ref result(mk_c(c)->m());
|
||||
if (num_decls == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE, nullptr);
|
||||
RETURN_Z3(0);
|
||||
RETURN_Z3(nullptr);
|
||||
}
|
||||
|
||||
sort* const* ts = reinterpret_cast<sort * const*>(types);
|
||||
|
@ -166,7 +166,7 @@ extern "C" {
|
|||
result = mk_c(c)->m().mk_lambda(names.size(), ts, names.c_ptr(), to_expr(body));
|
||||
mk_c(c)->save_ast_trail(result.get());
|
||||
return of_ast(result.get());
|
||||
Z3_CATCH_RETURN(0);
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_lambda_const(Z3_context c,
|
||||
|
@ -178,7 +178,7 @@ extern "C" {
|
|||
RESET_ERROR_CODE();
|
||||
if (num_decls == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE, nullptr);
|
||||
RETURN_Z3(0);
|
||||
RETURN_Z3(nullptr);
|
||||
}
|
||||
|
||||
svector<symbol> _names;
|
||||
|
@ -196,7 +196,7 @@ extern "C" {
|
|||
result = mk_c(c)->m().mk_lambda(_vars.size(), _vars.c_ptr(), _names.c_ptr(), result);
|
||||
mk_c(c)->save_ast_trail(result.get());
|
||||
return of_ast(result.get());
|
||||
Z3_CATCH_RETURN(0);
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -157,10 +157,8 @@ extern "C" {
|
|||
bool initialized = to_solver(s)->m_solver.get() != nullptr;
|
||||
if (!initialized)
|
||||
init_solver(c, s);
|
||||
ptr_vector<expr>::const_iterator it = ctx->begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx->end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
to_solver_ref(s)->assert_expr(*it);
|
||||
for (expr * e : ctx->assertions()) {
|
||||
to_solver_ref(s)->assert_expr(e);
|
||||
}
|
||||
to_solver_ref(s)->set_model_converter(ctx->get_model_converter());
|
||||
}
|
||||
|
@ -179,6 +177,7 @@ extern "C" {
|
|||
LOG_Z3_solver_from_file(c, s, file_name);
|
||||
char const* ext = get_extension(file_name);
|
||||
std::ifstream is(file_name);
|
||||
init_solver(c, s);
|
||||
if (!is) {
|
||||
SET_ERROR_CODE(Z3_FILE_ACCESS_ERROR, nullptr);
|
||||
}
|
||||
|
@ -368,7 +367,22 @@ extern "C" {
|
|||
v->m_ast_vector.push_back(f);
|
||||
}
|
||||
RETURN_Z3(of_ast_vector(v));
|
||||
Z3_CATCH_RETURN(0);
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
Z3_ast_vector Z3_API Z3_solver_get_non_units(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_non_units(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
init_solver(c, s);
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
|
||||
mk_c(c)->save_object(v);
|
||||
expr_ref_vector fmls = to_solver_ref(s)->get_non_units(mk_c(c)->m());
|
||||
for (expr* f : fmls) {
|
||||
v->m_ast_vector.push_back(f);
|
||||
}
|
||||
RETURN_Z3(of_ast_vector(v));
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
static Z3_lbool _solver_check(Z3_context c, Z3_solver s, unsigned num_assumptions, Z3_ast const assumptions[]) {
|
||||
|
@ -615,7 +629,7 @@ extern "C" {
|
|||
}
|
||||
catch (z3_exception & ex) {
|
||||
mk_c(c)->handle_exception(ex);
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
|
||||
|
@ -628,7 +642,7 @@ extern "C" {
|
|||
to_ast_vector_ref(vs).push_back(a);
|
||||
}
|
||||
RETURN_Z3(of_ast_vector(v));
|
||||
Z3_CATCH_RETURN(0);
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -127,6 +127,14 @@ namespace z3 {
|
|||
unsat, sat, unknown
|
||||
};
|
||||
|
||||
enum rounding_mode {
|
||||
RNA,
|
||||
RNE,
|
||||
RTP,
|
||||
RTN,
|
||||
RTZ
|
||||
};
|
||||
|
||||
inline check_result to_check_result(Z3_lbool l) {
|
||||
if (l == Z3_L_TRUE) return sat;
|
||||
else if (l == Z3_L_FALSE) return unsat;
|
||||
|
@ -137,12 +145,17 @@ namespace z3 {
|
|||
/**
|
||||
\brief A Context manages all other Z3 objects, global configuration options, etc.
|
||||
*/
|
||||
|
||||
|
||||
class context {
|
||||
private:
|
||||
bool m_enable_exceptions;
|
||||
rounding_mode m_rounding_mode;
|
||||
Z3_context m_ctx;
|
||||
void init(config & c) {
|
||||
m_ctx = Z3_mk_context_rc(c);
|
||||
m_enable_exceptions = true;
|
||||
m_rounding_mode = RNA;
|
||||
Z3_set_error_handler(m_ctx, 0);
|
||||
Z3_set_ast_print_mode(m_ctx, Z3_PRINT_SMTLIB2_COMPLIANT);
|
||||
}
|
||||
|
@ -171,7 +184,7 @@ namespace z3 {
|
|||
}
|
||||
|
||||
/**
|
||||
\brief The C++ API uses by defaults exceptions on errors.
|
||||
\brief The C++ API uses by defaults exceptions on errors.
|
||||
For applications that don't work well with exceptions (there should be only few)
|
||||
you have the ability to turn off exceptions. The tradeoffs are that applications
|
||||
have to be very careful about using check_error() after calls that may result in an
|
||||
|
@ -247,6 +260,26 @@ namespace z3 {
|
|||
*/
|
||||
sort array_sort(sort d, sort r);
|
||||
sort array_sort(sort_vector const& d, sort r);
|
||||
/**
|
||||
\brief Return a floating point sort.
|
||||
\c ebits is a number of exponent bits,
|
||||
\c sbits is a number of significand bits,
|
||||
\pre where ebits must be larger than 1 and sbits must be larger than 2.
|
||||
*/
|
||||
sort fpa_sort(unsigned ebits, unsigned sbits);
|
||||
/**
|
||||
\brief Return a FloatingPoint sort with given precision bitwidth (16, 32, 64 or 128).
|
||||
*/
|
||||
template<size_t precision>
|
||||
sort fpa_sort();
|
||||
/**
|
||||
\brief Return a RoundingMode sort.
|
||||
*/
|
||||
sort fpa_rounding_mode();
|
||||
/**
|
||||
\breif Sets RoundingMode of FloatingPoints.
|
||||
*/
|
||||
void set_rounding_mode(rounding_mode rm);
|
||||
/**
|
||||
\brief Return an enumeration sort: enum_names[0], ..., enum_names[n-1].
|
||||
\c cs and \c ts are output parameters. The method stores in \c cs the constants corresponding to the enumerated elements,
|
||||
|
@ -284,6 +317,10 @@ namespace z3 {
|
|||
expr int_const(char const * name);
|
||||
expr real_const(char const * name);
|
||||
expr bv_const(char const * name, unsigned sz);
|
||||
expr fpa_const(char const * name, unsigned ebits, unsigned sbits);
|
||||
|
||||
template<size_t precision>
|
||||
expr fpa_const(char const * name);
|
||||
|
||||
expr bool_val(bool b);
|
||||
|
||||
|
@ -307,6 +344,9 @@ namespace z3 {
|
|||
expr bv_val(char const * n, unsigned sz);
|
||||
expr bv_val(unsigned n, bool const* bits);
|
||||
|
||||
expr fpa_val(double n);
|
||||
expr fpa_val(float n);
|
||||
|
||||
expr string_val(char const* s);
|
||||
expr string_val(std::string const& s);
|
||||
|
||||
|
@ -465,6 +505,7 @@ namespace z3 {
|
|||
public:
|
||||
sort(context & c):ast(c) {}
|
||||
sort(context & c, Z3_sort s):ast(c, reinterpret_cast<Z3_ast>(s)) {}
|
||||
sort(context & c, Z3_ast a):ast(c, a) {}
|
||||
sort(sort const & s):ast(s) {}
|
||||
operator Z3_sort() const { return reinterpret_cast<Z3_sort>(m_ast); }
|
||||
/**
|
||||
|
@ -523,6 +564,10 @@ namespace z3 {
|
|||
\brief Return true if this sort is a Finite domain sort.
|
||||
*/
|
||||
bool is_finite_domain() const { return sort_kind() == Z3_FINITE_DOMAIN_SORT; }
|
||||
/**
|
||||
\brief Return true if this sort is a Floating point sort.
|
||||
*/
|
||||
bool is_fpa() const { return sort_kind() == Z3_FLOATING_POINT_SORT; }
|
||||
|
||||
/**
|
||||
\brief Return the size of this Bit-vector sort.
|
||||
|
@ -531,6 +576,9 @@ namespace z3 {
|
|||
*/
|
||||
unsigned bv_size() const { assert(is_bv()); unsigned r = Z3_get_bv_sort_size(ctx(), *this); check_error(); return r; }
|
||||
|
||||
unsigned fpa_ebits() const { assert(is_fpa()); unsigned r = Z3_fpa_get_ebits(ctx(), *this); check_error(); return r; }
|
||||
|
||||
unsigned fpa_sbits() const { assert(is_fpa()); unsigned r = Z3_fpa_get_sbits(ctx(), *this); check_error(); return r; }
|
||||
/**
|
||||
\brief Return the domain of this Array sort.
|
||||
|
||||
|
@ -634,7 +682,7 @@ namespace z3 {
|
|||
\brief Return true if this is a regular expression.
|
||||
*/
|
||||
bool is_re() const { return get_sort().is_re(); }
|
||||
|
||||
|
||||
/**
|
||||
\brief Return true if this is a Finite-domain expression.
|
||||
|
||||
|
@ -644,6 +692,10 @@ namespace z3 {
|
|||
|
||||
*/
|
||||
bool is_finite_domain() const { return get_sort().is_finite_domain(); }
|
||||
/**
|
||||
\brief Return true if this is a FloatingPoint expression. .
|
||||
*/
|
||||
bool is_fpa() const { return get_sort().is_fpa(); }
|
||||
|
||||
/**
|
||||
\brief Return true if this expression is a numeral.
|
||||
|
@ -696,29 +748,29 @@ namespace z3 {
|
|||
\brief Return true if this expression is well sorted (aka type correct).
|
||||
*/
|
||||
bool is_well_sorted() const { bool r = Z3_is_well_sorted(ctx(), m_ast) != 0; check_error(); return r; }
|
||||
|
||||
|
||||
/**
|
||||
\brief Return string representation of numeral or algebraic number
|
||||
This method assumes the expression is numeral or algebraic
|
||||
|
||||
|
||||
\pre is_numeral() || is_algebraic()
|
||||
*/
|
||||
std::string get_decimal_string(int precision) const {
|
||||
assert(is_numeral() || is_algebraic());
|
||||
return std::string(Z3_get_numeral_decimal_string(ctx(), m_ast, precision));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Return int value of numeral, throw if result cannot fit in
|
||||
machine int
|
||||
|
||||
It only makes sense to use this function if the caller can ensure that
|
||||
the result is an integer or if exceptions are enabled.
|
||||
the result is an integer or if exceptions are enabled.
|
||||
If exceptions are disabled, then use the is_numeral_i function.
|
||||
|
||||
|
||||
\pre is_numeral()
|
||||
*/
|
||||
int get_numeral_int() const {
|
||||
int get_numeral_int() const {
|
||||
int result = 0;
|
||||
if (!is_numeral_i(result)) {
|
||||
assert(ctx().enable_exceptions());
|
||||
|
@ -727,13 +779,13 @@ namespace z3 {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Return uint value of numeral, throw if result cannot fit in
|
||||
machine uint
|
||||
|
||||
It only makes sense to use this function if the caller can ensure that
|
||||
the result is an integer or if exceptions are enabled.
|
||||
the result is an integer or if exceptions are enabled.
|
||||
If exceptions are disabled, then use the is_numeral_u function.
|
||||
\pre is_numeral()
|
||||
*/
|
||||
|
@ -747,11 +799,11 @@ namespace z3 {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Return \c int64_t value of numeral, throw if result cannot fit in
|
||||
\c int64_t.
|
||||
|
||||
|
||||
\pre is_numeral()
|
||||
*/
|
||||
int64_t get_numeral_int64() const {
|
||||
|
@ -764,11 +816,11 @@ namespace z3 {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Return \c uint64_t value of numeral, throw if result cannot fit in
|
||||
\c uint64_t.
|
||||
|
||||
|
||||
\pre is_numeral()
|
||||
*/
|
||||
uint64_t get_numeral_uint64() const {
|
||||
|
@ -786,7 +838,7 @@ namespace z3 {
|
|||
return Z3_get_bool_value(ctx(), m_ast);
|
||||
}
|
||||
|
||||
expr numerator() const {
|
||||
expr numerator() const {
|
||||
assert(is_numeral());
|
||||
Z3_ast r = Z3_get_numerator(ctx(), m_ast);
|
||||
check_error();
|
||||
|
@ -794,7 +846,7 @@ namespace z3 {
|
|||
}
|
||||
|
||||
|
||||
expr denominator() const {
|
||||
expr denominator() const {
|
||||
assert(is_numeral());
|
||||
Z3_ast r = Z3_get_denominator(ctx(), m_ast);
|
||||
check_error();
|
||||
|
@ -803,6 +855,17 @@ namespace z3 {
|
|||
|
||||
operator Z3_app() const { assert(is_app()); return reinterpret_cast<Z3_app>(m_ast); }
|
||||
|
||||
/**
|
||||
\brief Return a RoundingMode sort.
|
||||
*/
|
||||
sort fpa_rounding_mode() {
|
||||
assert(is_fpa());
|
||||
Z3_sort s = ctx().fpa_rounding_mode();
|
||||
check_error();
|
||||
return sort(ctx(), s);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Return the declaration associated with this application.
|
||||
This method assumes the expression is an application.
|
||||
|
@ -905,7 +968,7 @@ namespace z3 {
|
|||
bool is_implies() const { return is_app() && Z3_OP_IMPLIES == decl().decl_kind(); }
|
||||
bool is_eq() const { return is_app() && Z3_OP_EQ == decl().decl_kind(); }
|
||||
bool is_ite() const { return is_app() && Z3_OP_ITE == decl().decl_kind(); }
|
||||
|
||||
|
||||
friend expr distinct(expr_vector const& args);
|
||||
friend expr concat(expr const& a, expr const& b);
|
||||
friend expr concat(expr_vector const& args);
|
||||
|
@ -992,23 +1055,34 @@ namespace z3 {
|
|||
friend expr nor(expr const& a, expr const& b);
|
||||
friend expr xnor(expr const& a, expr const& b);
|
||||
|
||||
friend expr min(expr const& a, expr const& b);
|
||||
friend expr max(expr const& a, expr const& b);
|
||||
|
||||
expr rotate_left(unsigned i) { Z3_ast r = Z3_mk_rotate_left(ctx(), i, *this); ctx().check_error(); return expr(ctx(), r); }
|
||||
expr rotate_right(unsigned i) { Z3_ast r = Z3_mk_rotate_right(ctx(), i, *this); ctx().check_error(); return expr(ctx(), r); }
|
||||
expr repeat(unsigned i) { Z3_ast r = Z3_mk_repeat(ctx(), i, *this); ctx().check_error(); return expr(ctx(), r); }
|
||||
|
||||
friend expr abs(expr const & a);
|
||||
friend expr sqrt(expr const & a, expr const & rm);
|
||||
|
||||
friend expr operator~(expr const & a);
|
||||
expr extract(unsigned hi, unsigned lo) const { Z3_ast r = Z3_mk_extract(ctx(), hi, lo, *this); ctx().check_error(); return expr(ctx(), r); }
|
||||
expr extract(unsigned hi, unsigned lo) const { Z3_ast r = Z3_mk_extract(ctx(), hi, lo, *this); ctx().check_error(); return expr(ctx(), r); }
|
||||
unsigned lo() const { assert (is_app() && Z3_get_decl_num_parameters(ctx(), decl()) == 2); return static_cast<unsigned>(Z3_get_decl_int_parameter(ctx(), decl(), 1)); }
|
||||
unsigned hi() const { assert (is_app() && Z3_get_decl_num_parameters(ctx(), decl()) == 2); return static_cast<unsigned>(Z3_get_decl_int_parameter(ctx(), decl(), 0)); }
|
||||
|
||||
/**
|
||||
\brief FloatingPoint fused multiply-add.
|
||||
*/
|
||||
friend expr fma(expr const& a, expr const& b, expr const& c);
|
||||
|
||||
/**
|
||||
\brief sequence and regular expression operations.
|
||||
+ is overloaded as sequence concatenation and regular expression union.
|
||||
concat is overloaded to handle sequences and regular expressions
|
||||
*/
|
||||
expr extract(expr const& offset, expr const& length) const {
|
||||
expr extract(expr const& offset, expr const& length) const {
|
||||
check_context(*this, offset); check_context(offset, length);
|
||||
Z3_ast r = Z3_mk_seq_extract(ctx(), *this, offset, length); check_error(); return expr(ctx(), r);
|
||||
Z3_ast r = Z3_mk_seq_extract(ctx(), *this, offset, length); check_error(); return expr(ctx(), r);
|
||||
}
|
||||
expr replace(expr const& src, expr const& dst) const {
|
||||
check_context(*this, src); check_context(src, dst);
|
||||
|
@ -1049,19 +1123,19 @@ namespace z3 {
|
|||
return expr(ctx(), r);
|
||||
}
|
||||
|
||||
friend expr range(expr const& lo, expr const& hi);
|
||||
friend expr range(expr const& lo, expr const& hi);
|
||||
/**
|
||||
\brief create a looping regular expression.
|
||||
*/
|
||||
expr loop(unsigned lo) {
|
||||
Z3_ast r = Z3_mk_re_loop(ctx(), m_ast, lo, 0);
|
||||
check_error();
|
||||
return expr(ctx(), r);
|
||||
Z3_ast r = Z3_mk_re_loop(ctx(), m_ast, lo, 0);
|
||||
check_error();
|
||||
return expr(ctx(), r);
|
||||
}
|
||||
expr loop(unsigned lo, unsigned hi) {
|
||||
Z3_ast r = Z3_mk_re_loop(ctx(), m_ast, lo, hi);
|
||||
check_error();
|
||||
return expr(ctx(), r);
|
||||
Z3_ast r = Z3_mk_re_loop(ctx(), m_ast, lo, hi);
|
||||
check_error();
|
||||
return expr(ctx(), r);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1094,7 +1168,7 @@ namespace z3 {
|
|||
|
||||
|
||||
inline expr implies(expr const & a, expr const & b) {
|
||||
assert(a.is_bool() && b.is_bool());
|
||||
assert(a.is_bool() && b.is_bool());
|
||||
_Z3_MK_BIN_(a, b, Z3_mk_implies);
|
||||
}
|
||||
inline expr implies(expr const & a, bool b) { return implies(a, a.ctx().bool_val(b)); }
|
||||
|
@ -1109,7 +1183,13 @@ namespace z3 {
|
|||
inline expr mod(expr const & a, int b) { return mod(a, a.ctx().num_val(b, a.get_sort())); }
|
||||
inline expr mod(int a, expr const & b) { return mod(b.ctx().num_val(a, b.get_sort()), b); }
|
||||
|
||||
inline expr rem(expr const& a, expr const& b) { _Z3_MK_BIN_(a, b, Z3_mk_rem); }
|
||||
inline expr rem(expr const& a, expr const& b) {
|
||||
if (a.is_fpa() && b.is_fpa()) {
|
||||
_Z3_MK_BIN_(a, b, Z3_mk_fpa_rem);
|
||||
} else {
|
||||
_Z3_MK_BIN_(a, b, Z3_mk_rem);
|
||||
}
|
||||
}
|
||||
inline expr rem(expr const & a, int b) { return rem(a, a.ctx().num_val(b, a.get_sort())); }
|
||||
inline expr rem(int a, expr const & b) { return rem(b.ctx().num_val(a, b.get_sort()), b); }
|
||||
|
||||
|
@ -1158,8 +1238,8 @@ namespace z3 {
|
|||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
inline expr operator==(expr const & a, int b) { assert(a.is_arith() || a.is_bv()); return a == a.ctx().num_val(b, a.get_sort()); }
|
||||
inline expr operator==(int a, expr const & b) { assert(b.is_arith() || b.is_bv()); return b.ctx().num_val(a, b.get_sort()) == b; }
|
||||
inline expr operator==(expr const & a, int b) { assert(a.is_arith() || a.is_bv() || a.is_fpa()); return a == a.ctx().num_val(b, a.get_sort()); }
|
||||
inline expr operator==(int a, expr const & b) { assert(b.is_arith() || b.is_bv() || b.is_fpa()); return b.ctx().num_val(a, b.get_sort()) == b; }
|
||||
|
||||
inline expr operator!=(expr const & a, expr const & b) {
|
||||
check_context(a, b);
|
||||
|
@ -1168,8 +1248,8 @@ namespace z3 {
|
|||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
inline expr operator!=(expr const & a, int b) { assert(a.is_arith() || a.is_bv()); return a != a.ctx().num_val(b, a.get_sort()); }
|
||||
inline expr operator!=(int a, expr const & b) { assert(b.is_arith() || b.is_bv()); return b.ctx().num_val(a, b.get_sort()) != b; }
|
||||
inline expr operator!=(expr const & a, int b) { assert(a.is_arith() || a.is_bv() || a.is_fpa()); return a != a.ctx().num_val(b, a.get_sort()); }
|
||||
inline expr operator!=(int a, expr const & b) { assert(b.is_arith() || b.is_bv() || b.is_fpa()); return b.ctx().num_val(a, b.get_sort()) != b; }
|
||||
|
||||
inline expr operator+(expr const & a, expr const & b) {
|
||||
check_context(a, b);
|
||||
|
@ -1188,6 +1268,9 @@ namespace z3 {
|
|||
Z3_ast _args[2] = { a, b };
|
||||
r = Z3_mk_re_union(a.ctx(), 2, _args);
|
||||
}
|
||||
else if (a.is_fpa() && b.is_fpa()) {
|
||||
r = Z3_mk_fpa_add(a.ctx(), a.ctx().fpa_rounding_mode(), a, b);
|
||||
}
|
||||
else {
|
||||
// operator is not supported by given arguments.
|
||||
assert(false);
|
||||
|
@ -1208,6 +1291,9 @@ namespace z3 {
|
|||
else if (a.is_bv() && b.is_bv()) {
|
||||
r = Z3_mk_bvmul(a.ctx(), a, b);
|
||||
}
|
||||
else if (a.is_fpa() && b.is_fpa()) {
|
||||
r = Z3_mk_fpa_mul(a.ctx(), a.ctx().fpa_rounding_mode(), a, b);
|
||||
}
|
||||
else {
|
||||
// operator is not supported by given arguments.
|
||||
assert(false);
|
||||
|
@ -1245,6 +1331,9 @@ namespace z3 {
|
|||
else if (a.is_bv() && b.is_bv()) {
|
||||
r = Z3_mk_bvsdiv(a.ctx(), a, b);
|
||||
}
|
||||
else if (a.is_fpa() && b.is_fpa()) {
|
||||
r = Z3_mk_fpa_div(a.ctx(), a.ctx().fpa_rounding_mode(), a, b);
|
||||
}
|
||||
else {
|
||||
// operator is not supported by given arguments.
|
||||
assert(false);
|
||||
|
@ -1263,6 +1352,9 @@ namespace z3 {
|
|||
else if (a.is_bv()) {
|
||||
r = Z3_mk_bvneg(a.ctx(), a);
|
||||
}
|
||||
else if (a.is_fpa()) {
|
||||
r = Z3_mk_fpa_neg(a.ctx(), a);
|
||||
}
|
||||
else {
|
||||
// operator is not supported by given arguments.
|
||||
assert(false);
|
||||
|
@ -1281,6 +1373,9 @@ namespace z3 {
|
|||
else if (a.is_bv() && b.is_bv()) {
|
||||
r = Z3_mk_bvsub(a.ctx(), a, b);
|
||||
}
|
||||
else if (a.is_fpa() && b.is_fpa()) {
|
||||
r = Z3_mk_fpa_sub(a.ctx(), a.ctx().fpa_rounding_mode(), a, b);
|
||||
}
|
||||
else {
|
||||
// operator is not supported by given arguments.
|
||||
assert(false);
|
||||
|
@ -1300,6 +1395,9 @@ namespace z3 {
|
|||
else if (a.is_bv() && b.is_bv()) {
|
||||
r = Z3_mk_bvsle(a.ctx(), a, b);
|
||||
}
|
||||
else if (a.is_fpa() && b.is_fpa()) {
|
||||
r = Z3_mk_fpa_leq(a.ctx(), a, b);
|
||||
}
|
||||
else {
|
||||
// operator is not supported by given arguments.
|
||||
assert(false);
|
||||
|
@ -1322,6 +1420,9 @@ namespace z3 {
|
|||
else if (a.is_bv() && b.is_bv()) {
|
||||
r = Z3_mk_bvslt(a.ctx(), a, b);
|
||||
}
|
||||
else if (a.is_fpa() && b.is_fpa()) {
|
||||
r = Z3_mk_fpa_lt(a.ctx(), a, b);
|
||||
}
|
||||
else {
|
||||
// operator is not supported by given arguments.
|
||||
assert(false);
|
||||
|
@ -1341,6 +1442,9 @@ namespace z3 {
|
|||
else if (a.is_bv() && b.is_bv()) {
|
||||
r = Z3_mk_bvsgt(a.ctx(), a, b);
|
||||
}
|
||||
else if (a.is_fpa() && b.is_fpa()) {
|
||||
r = Z3_mk_fpa_gt(a.ctx(), a, b);
|
||||
}
|
||||
else {
|
||||
// operator is not supported by given arguments.
|
||||
assert(false);
|
||||
|
@ -1366,17 +1470,30 @@ namespace z3 {
|
|||
inline expr nand(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_bvnand(a.ctx(), a, b); return expr(a.ctx(), r); }
|
||||
inline expr nor(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_bvnor(a.ctx(), a, b); return expr(a.ctx(), r); }
|
||||
inline expr xnor(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_bvxnor(a.ctx(), a, b); return expr(a.ctx(), r); }
|
||||
|
||||
inline expr min(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_fpa_min(a.ctx(), a, b); return expr(a.ctx(), r); }
|
||||
inline expr max(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_fpa_max(a.ctx(), a, b); return expr(a.ctx(), r); }
|
||||
inline expr abs(expr const & a) { Z3_ast r = Z3_mk_fpa_abs(a.ctx(), a); return expr(a.ctx(), r); }
|
||||
inline expr sqrt(expr const & a, expr const& rm) {
|
||||
check_context(a, rm);
|
||||
assert(a.is_fpa());
|
||||
Z3_ast r = Z3_mk_fpa_sqrt(a.ctx(), rm, a);
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
inline expr operator~(expr const & a) { Z3_ast r = Z3_mk_bvnot(a.ctx(), a); return expr(a.ctx(), r); }
|
||||
|
||||
|
||||
inline expr fma(expr const& a, expr const& b, expr const& c, expr const& rm) {
|
||||
check_context(a, b); check_context(a, c); check_context(a, rm);
|
||||
assert(a.is_fpa() && b.is_fpa() && c.is_fpa());
|
||||
Z3_ast r = Z3_mk_fpa_fma(a.ctx(), rm, a, b, c);
|
||||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Create the if-then-else expression <tt>ite(c, t, e)</tt>
|
||||
|
||||
\pre c.is_bool()
|
||||
*/
|
||||
|
||||
inline expr ite(expr const & c, expr const & t, expr const & e) {
|
||||
check_context(c, t); check_context(c, e);
|
||||
assert(c.is_bool());
|
||||
|
@ -1453,45 +1570,45 @@ namespace z3 {
|
|||
inline expr smod(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvsmod(a.ctx(), a, b)); }
|
||||
inline expr smod(expr const & a, int b) { return smod(a, a.ctx().num_val(b, a.get_sort())); }
|
||||
inline expr smod(int a, expr const & b) { return smod(b.ctx().num_val(a, b.get_sort()), b); }
|
||||
|
||||
|
||||
/**
|
||||
\brief unsigned reminder operator for bitvectors
|
||||
*/
|
||||
inline expr urem(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvurem(a.ctx(), a, b)); }
|
||||
inline expr urem(expr const & a, int b) { return urem(a, a.ctx().num_val(b, a.get_sort())); }
|
||||
inline expr urem(int a, expr const & b) { return urem(b.ctx().num_val(a, b.get_sort()), b); }
|
||||
|
||||
|
||||
/**
|
||||
\brief shift left operator for bitvectors
|
||||
*/
|
||||
inline expr shl(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvshl(a.ctx(), a, b)); }
|
||||
inline expr shl(expr const & a, int b) { return shl(a, a.ctx().num_val(b, a.get_sort())); }
|
||||
inline expr shl(int a, expr const & b) { return shl(b.ctx().num_val(a, b.get_sort()), b); }
|
||||
|
||||
|
||||
/**
|
||||
\brief logic shift right operator for bitvectors
|
||||
*/
|
||||
inline expr lshr(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvlshr(a.ctx(), a, b)); }
|
||||
inline expr lshr(expr const & a, int b) { return lshr(a, a.ctx().num_val(b, a.get_sort())); }
|
||||
inline expr lshr(int a, expr const & b) { return lshr(b.ctx().num_val(a, b.get_sort()), b); }
|
||||
|
||||
|
||||
/**
|
||||
\brief arithmetic shift right operator for bitvectors
|
||||
*/
|
||||
inline expr ashr(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvashr(a.ctx(), a, b)); }
|
||||
inline expr ashr(expr const & a, int b) { return ashr(a, a.ctx().num_val(b, a.get_sort())); }
|
||||
inline expr ashr(int a, expr const & b) { return ashr(b.ctx().num_val(a, b.get_sort()), b); }
|
||||
|
||||
|
||||
/**
|
||||
\brief Extend the given bit-vector with zeros to the (unsigned) equivalent bitvector of size m+i, where m is the size of the given bit-vector.
|
||||
*/
|
||||
inline expr zext(expr const & a, unsigned i) { return to_expr(a.ctx(), Z3_mk_zero_ext(a.ctx(), i, a)); }
|
||||
|
||||
|
||||
/**
|
||||
\brief Sign-extend of the given bit-vector to the (signed) equivalent bitvector of size m+i, where m is the size of the given bit-vector.
|
||||
*/
|
||||
inline expr sext(expr const & a, unsigned i) { return to_expr(a.ctx(), Z3_mk_sign_ext(a.ctx(), i, a)); }
|
||||
|
||||
|
||||
template<typename T> class cast_ast;
|
||||
|
||||
template<> class cast_ast<ast> {
|
||||
|
@ -1563,7 +1680,7 @@ namespace z3 {
|
|||
unsigned m_index;
|
||||
public:
|
||||
iterator(ast_vector_tpl const* v, unsigned i): m_vector(v), m_index(i) {}
|
||||
iterator(iterator& other): m_vector(other.m_vector), m_index(other.m_index) {}
|
||||
iterator(iterator& other): m_vector(other.m_vector), m_index(other.m_index) {}
|
||||
iterator operator=(iterator const& other) { m_vector = other.m_vector; m_index = other.m_index; return *this; }
|
||||
|
||||
bool operator==(iterator const& other) {
|
||||
|
@ -1773,7 +1890,7 @@ namespace z3 {
|
|||
return expr(ctx, r);
|
||||
}
|
||||
|
||||
inline expr mk_or(expr_vector const& args) {
|
||||
inline expr mk_or(expr_vector const& args) {
|
||||
array<Z3_ast> _args(args);
|
||||
Z3_ast r = Z3_mk_or(args.ctx(), _args.size(), _args.ptr());
|
||||
args.check_error();
|
||||
|
@ -1852,7 +1969,7 @@ namespace z3 {
|
|||
model(context & c):object(c) { init(Z3_mk_model(c)); }
|
||||
model(context & c, Z3_model m):object(c) { init(m); }
|
||||
model(model const & s):object(s) { init(s.m_model); }
|
||||
model(model& src, context& dst, translate) : object(dst) { init(Z3_model_translate(src.ctx(), src, dst)); }
|
||||
model(model& src, context& dst, translate) : object(dst) { init(Z3_model_translate(src.ctx(), src, dst)); }
|
||||
~model() { Z3_model_dec_ref(ctx(), m_model); }
|
||||
operator Z3_model() const { return m_model; }
|
||||
model & operator=(model const & s) {
|
||||
|
@ -1884,7 +2001,7 @@ namespace z3 {
|
|||
}
|
||||
|
||||
// returns interpretation of constant declaration c.
|
||||
// If c is not assigned any value in the model it returns
|
||||
// If c is not assigned any value in the model it returns
|
||||
// an expression with a null ast reference.
|
||||
expr get_const_interp(func_decl c) const {
|
||||
check_context(*this, c);
|
||||
|
@ -1898,7 +2015,7 @@ namespace z3 {
|
|||
check_error();
|
||||
return func_interp(ctx(), r);
|
||||
}
|
||||
|
||||
|
||||
// returns true iff the model contains an interpretation
|
||||
// for function f.
|
||||
bool has_interp(func_decl f) const {
|
||||
|
@ -1945,7 +2062,7 @@ namespace z3 {
|
|||
bool is_uint(unsigned i) const { Z3_bool r = Z3_stats_is_uint(ctx(), m_stats, i); check_error(); return r != 0; }
|
||||
bool is_double(unsigned i) const { Z3_bool r = Z3_stats_is_double(ctx(), m_stats, i); check_error(); return r != 0; }
|
||||
unsigned uint_value(unsigned i) const { unsigned r = Z3_stats_get_uint_value(ctx(), m_stats, i); check_error(); return r; }
|
||||
double double_value(unsigned i) const { double r = Z3_stats_get_double_value(ctx(), m_stats, i); check_error(); return r; }
|
||||
double double_value(unsigned i) const { double r = Z3_stats_get_double_value(ctx(), m_stats, i); check_error(); return r; }
|
||||
friend std::ostream & operator<<(std::ostream & out, stats const & s);
|
||||
};
|
||||
inline std::ostream & operator<<(std::ostream & out, stats const & s) { out << Z3_stats_to_string(s.ctx(), s); return out; }
|
||||
|
@ -2001,7 +2118,7 @@ namespace z3 {
|
|||
void add(expr const & e, char const * p) {
|
||||
add(e, ctx().bool_const(p));
|
||||
}
|
||||
// fails for some compilers:
|
||||
// fails for some compilers:
|
||||
// void add(expr_vector const& v) { check_context(*this, v); for (expr e : v) add(e); }
|
||||
void from_file(char const* file) { Z3_solver_from_file(ctx(), m_solver, file); ctx().check_parser_error(); }
|
||||
void from_string(char const* s) { Z3_solver_from_string(ctx(), m_solver, s); ctx().check_parser_error(); }
|
||||
|
@ -2038,6 +2155,8 @@ namespace z3 {
|
|||
stats statistics() const { Z3_stats r = Z3_solver_get_statistics(ctx(), m_solver); check_error(); return stats(ctx(), r); }
|
||||
expr_vector unsat_core() const { Z3_ast_vector r = Z3_solver_get_unsat_core(ctx(), m_solver); check_error(); return expr_vector(ctx(), r); }
|
||||
expr_vector assertions() const { Z3_ast_vector r = Z3_solver_get_assertions(ctx(), m_solver); check_error(); return expr_vector(ctx(), r); }
|
||||
expr_vector non_units() const { Z3_ast_vector r = Z3_solver_get_non_units(ctx(), m_solver); check_error(); return expr_vector(ctx(), r); }
|
||||
expr_vector units() const { Z3_ast_vector r = Z3_solver_get_units(ctx(), m_solver); check_error(); return expr_vector(ctx(), r); }
|
||||
expr proof() const { Z3_ast r = Z3_solver_get_proof(ctx(), m_solver); check_error(); return expr(ctx(), r); }
|
||||
friend std::ostream & operator<<(std::ostream & out, solver const & s);
|
||||
|
||||
|
@ -2064,11 +2183,11 @@ namespace z3 {
|
|||
param_descrs get_param_descrs() { return param_descrs(ctx(), Z3_solver_get_param_descrs(ctx(), m_solver)); }
|
||||
|
||||
|
||||
expr_vector cube(expr_vector& vars, unsigned cutoff) {
|
||||
Z3_ast_vector r = Z3_solver_cube(ctx(), m_solver, vars, cutoff);
|
||||
check_error();
|
||||
return expr_vector(ctx(), r);
|
||||
}
|
||||
expr_vector cube(expr_vector& vars, unsigned cutoff) {
|
||||
Z3_ast_vector r = Z3_solver_cube(ctx(), m_solver, vars, cutoff);
|
||||
check_error();
|
||||
return expr_vector(ctx(), r);
|
||||
}
|
||||
|
||||
class cube_iterator {
|
||||
solver& m_solver;
|
||||
|
@ -2116,7 +2235,7 @@ namespace z3 {
|
|||
cube_iterator operator++(int) { assert(false); return *this; }
|
||||
expr_vector const * operator->() const { return &(operator*()); }
|
||||
expr_vector const& operator*() const { return m_cube; }
|
||||
|
||||
|
||||
bool operator==(cube_iterator const& other) {
|
||||
return other.m_end == m_end;
|
||||
};
|
||||
|
@ -2405,7 +2524,7 @@ namespace z3 {
|
|||
|
||||
class optimize : public object {
|
||||
Z3_optimize m_opt;
|
||||
|
||||
|
||||
public:
|
||||
class handle {
|
||||
unsigned m_h;
|
||||
|
@ -2453,8 +2572,20 @@ namespace z3 {
|
|||
void pop() {
|
||||
Z3_optimize_pop(ctx(), m_opt);
|
||||
}
|
||||
check_result check() { Z3_lbool r = Z3_optimize_check(ctx(), m_opt); check_error(); return to_check_result(r); }
|
||||
check_result check() { Z3_lbool r = Z3_optimize_check(ctx(), m_opt, 0, 0); check_error(); return to_check_result(r); }
|
||||
check_result check(expr_vector const& asms) {
|
||||
unsigned n = asms.size();
|
||||
array<Z3_ast> _asms(n);
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
check_context(*this, asms[i]);
|
||||
_asms[i] = asms[i];
|
||||
}
|
||||
Z3_lbool r = Z3_optimize_check(ctx(), m_opt, n, _asms.ptr());
|
||||
check_error();
|
||||
return to_check_result(r);
|
||||
}
|
||||
model get_model() const { Z3_model m = Z3_optimize_get_model(ctx(), m_opt); check_error(); return model(ctx(), m); }
|
||||
expr_vector unsat_core() const { Z3_ast_vector r = Z3_optimize_get_unsat_core(ctx(), m_opt); check_error(); return expr_vector(ctx(), r); }
|
||||
void set(params const & p) { Z3_optimize_set_params(ctx(), m_opt, p); check_error(); }
|
||||
expr lower(handle const& h) {
|
||||
Z3_ast r = Z3_optimize_get_lower(ctx(), m_opt, h.h());
|
||||
|
@ -2481,25 +2612,25 @@ namespace z3 {
|
|||
public:
|
||||
fixedpoint(context& c):object(c) { m_fp = Z3_mk_fixedpoint(c); Z3_fixedpoint_inc_ref(c, m_fp); }
|
||||
~fixedpoint() { Z3_fixedpoint_dec_ref(ctx(), m_fp); }
|
||||
operator Z3_fixedpoint() const { return m_fp; }
|
||||
operator Z3_fixedpoint() const { return m_fp; }
|
||||
void from_string(char const* s) { Z3_fixedpoint_from_string(ctx(), m_fp, s); check_error(); }
|
||||
void from_file(char const* s) { Z3_fixedpoint_from_file(ctx(), m_fp, s); check_error(); }
|
||||
void add_rule(expr& rule, symbol const& name) { Z3_fixedpoint_add_rule(ctx(), m_fp, rule, name); check_error(); }
|
||||
void add_fact(func_decl& f, unsigned * args) { Z3_fixedpoint_add_fact(ctx(), m_fp, f, f.arity(), args); check_error(); }
|
||||
check_result query(expr& q) { Z3_lbool r = Z3_fixedpoint_query(ctx(), m_fp, q); check_error(); return to_check_result(r); }
|
||||
check_result query(func_decl_vector& relations) {
|
||||
check_result query(func_decl_vector& relations) {
|
||||
array<Z3_func_decl> rs(relations);
|
||||
Z3_lbool r = Z3_fixedpoint_query_relations(ctx(), m_fp, rs.size(), rs.ptr());
|
||||
check_error();
|
||||
return to_check_result(r);
|
||||
Z3_lbool r = Z3_fixedpoint_query_relations(ctx(), m_fp, rs.size(), rs.ptr());
|
||||
check_error();
|
||||
return to_check_result(r);
|
||||
}
|
||||
expr get_answer() { Z3_ast r = Z3_fixedpoint_get_answer(ctx(), m_fp); check_error(); return expr(ctx(), r); }
|
||||
std::string reason_unknown() { return Z3_fixedpoint_get_reason_unknown(ctx(), m_fp); }
|
||||
void update_rule(expr& rule, symbol const& name) { Z3_fixedpoint_update_rule(ctx(), m_fp, rule, name); check_error(); }
|
||||
unsigned get_num_levels(func_decl& p) { unsigned r = Z3_fixedpoint_get_num_levels(ctx(), m_fp, p); check_error(); return r; }
|
||||
expr get_cover_delta(int level, func_decl& p) {
|
||||
Z3_ast r = Z3_fixedpoint_get_cover_delta(ctx(), m_fp, level, p);
|
||||
check_error();
|
||||
expr get_cover_delta(int level, func_decl& p) {
|
||||
Z3_ast r = Z3_fixedpoint_get_cover_delta(ctx(), m_fp, level, p);
|
||||
check_error();
|
||||
return expr(ctx(), r);
|
||||
}
|
||||
void add_cover(int level, func_decl& p, expr& property) { Z3_fixedpoint_add_cover(ctx(), m_fp, level, p, property); check_error(); }
|
||||
|
@ -2513,7 +2644,7 @@ namespace z3 {
|
|||
std::string to_string() { return Z3_fixedpoint_to_string(ctx(), m_fp, 0, 0); }
|
||||
std::string to_string(expr_vector const& queries) {
|
||||
array<Z3_ast> qs(queries);
|
||||
return Z3_fixedpoint_to_string(ctx(), m_fp, qs.size(), qs.ptr());
|
||||
return Z3_fixedpoint_to_string(ctx(), m_fp, qs.size(), qs.ptr());
|
||||
}
|
||||
void push() { Z3_fixedpoint_push(ctx(), m_fp); check_error(); }
|
||||
void pop() { Z3_fixedpoint_pop(ctx(), m_fp); check_error(); }
|
||||
|
@ -2548,11 +2679,37 @@ namespace z3 {
|
|||
inline sort context::string_sort() { Z3_sort s = Z3_mk_string_sort(m_ctx); check_error(); return sort(*this, s); }
|
||||
inline sort context::seq_sort(sort& s) { Z3_sort r = Z3_mk_seq_sort(m_ctx, s); check_error(); return sort(*this, r); }
|
||||
inline sort context::re_sort(sort& s) { Z3_sort r = Z3_mk_re_sort(m_ctx, s); check_error(); return sort(*this, r); }
|
||||
inline sort context::fpa_sort(unsigned ebits, unsigned sbits) { Z3_sort s = Z3_mk_fpa_sort(m_ctx, ebits, sbits); check_error(); return sort(*this, s); }
|
||||
|
||||
template<>
|
||||
inline sort context::fpa_sort<16>() { return fpa_sort(5, 11); }
|
||||
|
||||
template<>
|
||||
inline sort context::fpa_sort<32>() { return fpa_sort(8, 24); }
|
||||
|
||||
template<>
|
||||
inline sort context::fpa_sort<64>() { return fpa_sort(11, 53); }
|
||||
|
||||
template<>
|
||||
inline sort context::fpa_sort<128>() { return fpa_sort(15, 113); }
|
||||
|
||||
inline sort context::fpa_rounding_mode() {
|
||||
switch (m_rounding_mode) {
|
||||
case RNA: return sort(*this, Z3_mk_fpa_rna(m_ctx));
|
||||
case RNE: return sort(*this, Z3_mk_fpa_rne(m_ctx));
|
||||
case RTP: return sort(*this, Z3_mk_fpa_rtp(m_ctx));
|
||||
case RTN: return sort(*this, Z3_mk_fpa_rtn(m_ctx));
|
||||
case RTZ: return sort(*this, Z3_mk_fpa_rtz(m_ctx));
|
||||
default: return sort(*this);
|
||||
}
|
||||
}
|
||||
|
||||
inline void context::set_rounding_mode(rounding_mode rm) { m_rounding_mode = rm; }
|
||||
|
||||
inline sort context::array_sort(sort d, sort r) { Z3_sort s = Z3_mk_array_sort(m_ctx, d, r); check_error(); return sort(*this, s); }
|
||||
inline sort context::array_sort(sort_vector const& d, sort r) {
|
||||
array<Z3_sort> dom(d);
|
||||
Z3_sort s = Z3_mk_array_sort_n(m_ctx, dom.size(), dom.ptr(), r); check_error(); return sort(*this, s);
|
||||
Z3_sort s = Z3_mk_array_sort_n(m_ctx, dom.size(), dom.ptr(), r); check_error(); return sort(*this, s);
|
||||
}
|
||||
inline sort context::enumeration_sort(char const * name, unsigned n, char const * const * enum_names, func_decl_vector & cs, func_decl_vector & ts) {
|
||||
array<Z3_symbol> _enum_names(n);
|
||||
|
@ -2667,6 +2824,10 @@ namespace z3 {
|
|||
inline expr context::int_const(char const * name) { return constant(name, int_sort()); }
|
||||
inline expr context::real_const(char const * name) { return constant(name, real_sort()); }
|
||||
inline expr context::bv_const(char const * name, unsigned sz) { return constant(name, bv_sort(sz)); }
|
||||
inline expr context::fpa_const(char const * name, unsigned ebits, unsigned sbits) { return constant(name, fpa_sort(ebits, sbits)); }
|
||||
|
||||
template<size_t precision>
|
||||
inline expr context::fpa_const(char const * name) { return constant(name, fpa_sort<precision>()); }
|
||||
|
||||
inline expr context::bool_val(bool b) { return b ? expr(*this, Z3_mk_true(m_ctx)) : expr(*this, Z3_mk_false(m_ctx)); }
|
||||
|
||||
|
@ -2688,12 +2849,15 @@ namespace z3 {
|
|||
inline expr context::bv_val(int64_t n, unsigned sz) { sort s = bv_sort(sz); Z3_ast r = Z3_mk_int64(m_ctx, n, s); check_error(); return expr(*this, r); }
|
||||
inline expr context::bv_val(uint64_t n, unsigned sz) { sort s = bv_sort(sz); Z3_ast r = Z3_mk_unsigned_int64(m_ctx, n, s); check_error(); return expr(*this, r); }
|
||||
inline expr context::bv_val(char const * n, unsigned sz) { sort s = bv_sort(sz); Z3_ast r = Z3_mk_numeral(m_ctx, n, s); check_error(); return expr(*this, r); }
|
||||
inline expr context::bv_val(unsigned n, bool const* bits) {
|
||||
inline expr context::bv_val(unsigned n, bool const* bits) {
|
||||
array<Z3_bool> _bits(n);
|
||||
for (unsigned i = 0; i < n; ++i) _bits[i] = bits[i] ? 1 : 0;
|
||||
Z3_ast r = Z3_mk_bv_numeral(m_ctx, n, _bits.ptr()); check_error(); return expr(*this, r);
|
||||
Z3_ast r = Z3_mk_bv_numeral(m_ctx, n, _bits.ptr()); check_error(); return expr(*this, r);
|
||||
}
|
||||
|
||||
inline expr context::fpa_val(double n) { sort s = fpa_sort<64>(); Z3_ast r = Z3_mk_fpa_numeral_double(m_ctx, n, s); check_error(); return expr(*this, r); }
|
||||
inline expr context::fpa_val(float n) { sort s = fpa_sort<32>(); Z3_ast r = Z3_mk_fpa_numeral_float(m_ctx, n, s); check_error(); return expr(*this, r); }
|
||||
|
||||
inline expr context::string_val(char const* s) { Z3_ast r = Z3_mk_string(m_ctx, s); check_error(); return expr(*this, r); }
|
||||
inline expr context::string_val(std::string const& s) { Z3_ast r = Z3_mk_string(m_ctx, s.c_str()); check_error(); return expr(*this, r); }
|
||||
|
||||
|
@ -2817,8 +2981,8 @@ namespace z3 {
|
|||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
inline expr select(expr const & a, int i) {
|
||||
return select(a, a.ctx().num_val(i, a.get_sort().array_domain()));
|
||||
inline expr select(expr const & a, int i) {
|
||||
return select(a, a.ctx().num_val(i, a.get_sort().array_domain()));
|
||||
}
|
||||
inline expr select(expr const & a, expr_vector const & i) {
|
||||
check_context(a, i);
|
||||
|
@ -2848,10 +3012,10 @@ namespace z3 {
|
|||
return expr(a.ctx(), r);
|
||||
}
|
||||
|
||||
inline expr as_array(func_decl & f) {
|
||||
Z3_ast r = Z3_mk_as_array(f.ctx(), f);
|
||||
f.check_error();
|
||||
return expr(f.ctx(), r);
|
||||
inline expr as_array(func_decl & f) {
|
||||
Z3_ast r = Z3_mk_as_array(f.ctx(), f);
|
||||
f.check_error();
|
||||
return expr(f.ctx(), r);
|
||||
}
|
||||
|
||||
#define MK_EXPR1(_fn, _arg) \
|
||||
|
@ -2883,21 +3047,21 @@ namespace z3 {
|
|||
|
||||
inline expr set_del(expr const& s, expr const& e) {
|
||||
MK_EXPR2(Z3_mk_set_del, s, e);
|
||||
}
|
||||
}
|
||||
|
||||
inline expr set_union(expr const& a, expr const& b) {
|
||||
check_context(a, b);
|
||||
check_context(a, b);
|
||||
Z3_ast es[2] = { a, b };
|
||||
Z3_ast r = Z3_mk_set_union(a.ctx(), 2, es);
|
||||
a.check_error();
|
||||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
|
||||
inline expr set_intersect(expr const& a, expr const& b) {
|
||||
check_context(a, b);
|
||||
check_context(a, b);
|
||||
Z3_ast es[2] = { a, b };
|
||||
Z3_ast r = Z3_mk_set_intersect(a.ctx(), 2, es);
|
||||
a.check_error();
|
||||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
|
||||
|
@ -2981,10 +3145,10 @@ namespace z3 {
|
|||
MK_EXPR1(Z3_mk_re_complement, a);
|
||||
}
|
||||
inline expr range(expr const& lo, expr const& hi) {
|
||||
check_context(lo, hi);
|
||||
Z3_ast r = Z3_mk_re_range(lo.ctx(), lo, hi);
|
||||
lo.check_error();
|
||||
return expr(lo.ctx(), r);
|
||||
check_context(lo, hi);
|
||||
Z3_ast r = Z3_mk_re_range(lo.ctx(), lo, hi);
|
||||
lo.check_error();
|
||||
return expr(lo.ctx(), r);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2995,7 +3159,7 @@ namespace z3 {
|
|||
Z3_ast_vector r = Z3_parse_smtlib2_string(*this, s, 0, 0, 0, 0, 0, 0);
|
||||
check_error();
|
||||
return expr_vector(*this, r);
|
||||
|
||||
|
||||
}
|
||||
inline expr_vector context::parse_file(char const* s) {
|
||||
Z3_ast_vector r = Z3_parse_smtlib2_file(*this, s, 0, 0, 0, 0, 0, 0);
|
||||
|
|
|
@ -147,11 +147,6 @@ if (DOTNET_TOOLCHAIN_IS_WINDOWS)
|
|||
"/nostdlib+"
|
||||
"/reference:mscorlib.dll"
|
||||
)
|
||||
# FIXME: This flag only works when the working directory of csc.exe is
|
||||
# the directory containing the ``libz3`` target. I can't get this to work
|
||||
# correctly with multi-configuration generators (i.e. Visual Studio) so
|
||||
# just don't set the flag for now.
|
||||
#list(APPEND CSC_FLAGS "/linkresource:$<TARGET_FILE_NAME:libz3>")
|
||||
elseif (DOTNET_TOOLCHAIN_IS_MONO)
|
||||
# We need to give the assembly a strong name so that it can be installed
|
||||
# into the GAC.
|
||||
|
|
|
@ -183,9 +183,9 @@ namespace Microsoft.Z3
|
|||
/// don't use strict inequalities) meets the objectives.
|
||||
/// </summary>
|
||||
///
|
||||
public Status Check()
|
||||
public Status Check(params Expr[] assumptions)
|
||||
{
|
||||
Z3_lbool r = (Z3_lbool)Native.Z3_optimize_check(Context.nCtx, NativeObject);
|
||||
Z3_lbool r = (Z3_lbool)Native.Z3_optimize_check(Context.nCtx, NativeObject, (uint)assumptions.Length, AST.ArrayToNative(assumptions));
|
||||
switch (r)
|
||||
{
|
||||
case Z3_lbool.Z3_L_TRUE:
|
||||
|
@ -236,6 +236,25 @@ namespace Microsoft.Z3
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The unsat core of the last <c>Check</c>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The unsat core is a subset of <c>assumptions</c>
|
||||
/// The result is empty if <c>Check</c> was not invoked before,
|
||||
/// if its results was not <c>UNSATISFIABLE</c>, or if core production is disabled.
|
||||
/// </remarks>
|
||||
public BoolExpr[] UnsatCore
|
||||
{
|
||||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<Expr[]>() != null);
|
||||
|
||||
ASTVector core = new ASTVector(Context, Native.Z3_optimize_get_unsat_core(Context.nCtx, NativeObject));
|
||||
return core.ToBoolExprArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Declare an arithmetical maximization objective.
|
||||
/// Return a handle to the objective. The handle is used as
|
||||
|
|
|
@ -1976,6 +1976,22 @@ public class Context implements AutoCloseable {
|
|||
{
|
||||
return (SeqExpr) Expr.create(this, Native.mkString(nCtx(), s));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an integer expression to a string.
|
||||
*/
|
||||
public SeqExpr intToString(Expr e)
|
||||
{
|
||||
return (SeqExpr) Expr.create(this, Native.mkIntToStr(nCtx(), e.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an integer expression to a string.
|
||||
*/
|
||||
public IntExpr stringToInt(Expr e)
|
||||
{
|
||||
return (IntExpr) Expr.create(this, Native.mkStrToInt(nCtx(), e.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate sequences.
|
||||
|
|
|
@ -161,9 +161,23 @@ public class Optimize extends Z3Object {
|
|||
* Produce a model that (when the objectives are bounded and
|
||||
* don't use strict inequalities) meets the objectives.
|
||||
**/
|
||||
public Status Check()
|
||||
public Status Check(Expr... assumptions)
|
||||
{
|
||||
Z3_lbool r = Z3_lbool.fromInt(Native.optimizeCheck(getContext().nCtx(), getNativeObject()));
|
||||
Z3_lbool r;
|
||||
if (assumptions == null) {
|
||||
r = Z3_lbool.fromInt(
|
||||
Native.optimizeCheck(
|
||||
getContext().nCtx(),
|
||||
getNativeObject(), 0, null));
|
||||
}
|
||||
else {
|
||||
r = Z3_lbool.fromInt(
|
||||
Native.optimizeCheck(
|
||||
getContext().nCtx(),
|
||||
getNativeObject(),
|
||||
assumptions.length,
|
||||
AST.arrayToNative(assumptions)));
|
||||
}
|
||||
switch (r) {
|
||||
case Z3_L_TRUE:
|
||||
return Status.SATISFIABLE;
|
||||
|
@ -209,6 +223,21 @@ public class Optimize extends Z3Object {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The unsat core of the last {@code Check}.
|
||||
* Remarks: The unsat core
|
||||
* is a subset of {@code Assumptions} The result is empty if
|
||||
* {@code Check} was not invoked before, if its results was not
|
||||
* {@code UNSATISFIABLE}, or if core production is disabled.
|
||||
*
|
||||
* @throws Z3Exception
|
||||
**/
|
||||
public BoolExpr[] getUnsatCore()
|
||||
{
|
||||
ASTVector core = new ASTVector(getContext(), Native.optimizeGetUnsatCore(getContext().nCtx(), getNativeObject()));
|
||||
return core.ToBoolExprArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Declare an arithmetical maximization objective.
|
||||
* Return a handle to the objective. The handle is used as
|
||||
|
|
|
@ -43,6 +43,14 @@ let mk_list f n =
|
|||
in
|
||||
mk_list' 0 []
|
||||
|
||||
let check_int32 v = v = Int32.to_int (Int32.of_int v)
|
||||
|
||||
let mk_int_expr ctx v ty =
|
||||
if not (check_int32 v) then
|
||||
Z3native.mk_numeral ctx (string_of_int v) ty
|
||||
else
|
||||
Z3native.mk_int ctx v ty
|
||||
|
||||
let mk_context (settings:(string * string) list) =
|
||||
let cfg = Z3native.mk_config () in
|
||||
let f e = Z3native.set_param_value cfg (fst e) (snd e) in
|
||||
|
@ -531,7 +539,7 @@ end = struct
|
|||
let mk_fresh_const (ctx:context) (prefix:string) (range:Sort.sort) = Z3native.mk_fresh_const ctx prefix range
|
||||
let mk_app (ctx:context) (f:FuncDecl.func_decl) (args:expr list) = expr_of_func_app ctx f args
|
||||
let mk_numeral_string (ctx:context) (v:string) (ty:Sort.sort) = Z3native.mk_numeral ctx v ty
|
||||
let mk_numeral_int (ctx:context) (v:int) (ty:Sort.sort) = Z3native.mk_int ctx v ty
|
||||
let mk_numeral_int (ctx:context) (v:int) (ty:Sort.sort) = mk_int_expr ctx v ty
|
||||
let equal (a:expr) (b:expr) = AST.equal a b
|
||||
let compare (a:expr) (b:expr) = AST.compare a b
|
||||
end
|
||||
|
@ -1036,7 +1044,7 @@ struct
|
|||
let mk_mod = Z3native.mk_mod
|
||||
let mk_rem = Z3native.mk_rem
|
||||
let mk_numeral_s (ctx:context) (v:string) = Z3native.mk_numeral ctx v (mk_sort ctx)
|
||||
let mk_numeral_i (ctx:context) (v:int) = Z3native.mk_int ctx v (mk_sort ctx)
|
||||
let mk_numeral_i (ctx:context) (v:int) = mk_int_expr ctx v (mk_sort ctx)
|
||||
let mk_int2real = Z3native.mk_int2real
|
||||
let mk_int2bv = Z3native.mk_int2bv
|
||||
end
|
||||
|
@ -1061,11 +1069,13 @@ struct
|
|||
let mk_numeral_nd (ctx:context) (num:int) (den:int) =
|
||||
if den = 0 then
|
||||
raise (Error "Denominator is zero")
|
||||
else if not (check_int32 num) || not (check_int32 den) then
|
||||
raise (Error "numerals don't fit in 32 bits")
|
||||
else
|
||||
Z3native.mk_real ctx num den
|
||||
|
||||
let mk_numeral_s (ctx:context) (v:string) = Z3native.mk_numeral ctx v (mk_sort ctx)
|
||||
let mk_numeral_i (ctx:context) (v:int) = Z3native.mk_int ctx v (mk_sort ctx)
|
||||
let mk_numeral_i (ctx:context) (v:int) = mk_int_expr ctx v (mk_sort ctx)
|
||||
let mk_is_integer = Z3native.mk_is_int
|
||||
let mk_real2int = Z3native.mk_real2int
|
||||
|
||||
|
@ -1155,11 +1165,6 @@ struct
|
|||
let is_bv_xor3 (x:expr) = (AST.is_app x) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) = OP_XOR3)
|
||||
let get_size (x:Sort.sort) = Z3native.get_bv_sort_size (Sort.gc x) x
|
||||
|
||||
let get_int (x:expr) =
|
||||
match Z3native.get_numeral_int (Expr.gc x) x with
|
||||
| true, v -> v
|
||||
| false, _ -> raise (Error "Conversion failed.")
|
||||
|
||||
let numeral_to_string (x:expr) = Z3native.get_numeral_string (Expr.gc x) x
|
||||
let mk_const (ctx:context) (name:Symbol.symbol) (size:int) =
|
||||
Expr.mk_const ctx name (mk_sort ctx size)
|
||||
|
@ -1810,8 +1815,10 @@ struct
|
|||
| _ -> UNKNOWN
|
||||
|
||||
let get_model x =
|
||||
let q = Z3native.solver_get_model (gc x) x in
|
||||
if Z3native.is_null_model q then None else Some q
|
||||
try
|
||||
let q = Z3native.solver_get_model (gc x) x in
|
||||
if Z3native.is_null_model q then None else Some q
|
||||
with | _ -> None
|
||||
|
||||
let get_proof x =
|
||||
let q = Z3native.solver_get_proof (gc x) x in
|
||||
|
@ -1940,15 +1947,17 @@ struct
|
|||
let minimize (x:optimize) (e:Expr.expr) = mk_handle x (Z3native.optimize_minimize (gc x) x e)
|
||||
|
||||
let check (x:optimize) =
|
||||
let r = lbool_of_int (Z3native.optimize_check (gc x) x) in
|
||||
let r = lbool_of_int (Z3native.optimize_check (gc x) x) 0 [] in
|
||||
match r with
|
||||
| L_TRUE -> Solver.SATISFIABLE
|
||||
| L_FALSE -> Solver.UNSATISFIABLE
|
||||
| _ -> Solver.UNKNOWN
|
||||
|
||||
let get_model (x:optimize) =
|
||||
let q = Z3native.optimize_get_model (gc x) x in
|
||||
if Z3native.is_null_model q then None else Some q
|
||||
try
|
||||
let q = Z3native.optimize_get_model (gc x) x in
|
||||
if Z3native.is_null_model q then None else Some q
|
||||
with | _ -> None
|
||||
|
||||
let get_lower (x:handle) = Z3native.optimize_get_lower (gc x.opt) x.opt x.h
|
||||
let get_upper (x:handle) = Z3native.optimize_get_upper (gc x.opt) x.opt x.h
|
||||
|
|
|
@ -1152,9 +1152,6 @@ sig
|
|||
(** Create a new integer sort. *)
|
||||
val mk_sort : context -> Sort.sort
|
||||
|
||||
(** Retrieve the int value. *)
|
||||
val get_int : Expr.expr -> int
|
||||
|
||||
(** Get a big_int from an integer numeral *)
|
||||
val get_big_int : Expr.expr -> Big_int.big_int
|
||||
|
||||
|
@ -1543,9 +1540,6 @@ sig
|
|||
(** The size of a bit-vector sort. *)
|
||||
val get_size : Sort.sort -> int
|
||||
|
||||
(** Retrieve the int value. *)
|
||||
val get_int : Expr.expr -> int
|
||||
|
||||
(** Returns a string representation of a numeral. *)
|
||||
val numeral_to_string : Expr.expr -> string
|
||||
|
||||
|
@ -3413,10 +3407,10 @@ sig
|
|||
(** Parse the given string using the SMT-LIB2 parser.
|
||||
|
||||
@return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *)
|
||||
val parse_smtlib2_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Expr.expr
|
||||
val parse_smtlib2_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> AST.ASTVector.ast_vector
|
||||
|
||||
(** Parse the given file using the SMT-LIB2 parser. *)
|
||||
val parse_smtlib2_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Expr.expr
|
||||
val parse_smtlib2_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> AST.ASTVector.ast_vector
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ If you are using a 64-bit Python interpreter, you should use
|
|||
msbuild /p:configuration=external /p:platform=x64
|
||||
|
||||
|
||||
On Linux and OSX, you must install Z3Py, before trying example.py.
|
||||
To install Z3Py on Linux and OSX, you should execute the following
|
||||
On Linux and macOS, you must install Z3Py, before trying example.py.
|
||||
To install Z3Py on Linux and macOS, you should execute the following
|
||||
command in the Z3 root directory
|
||||
|
||||
sudo make install-z3py
|
||||
|
|
|
@ -73,7 +73,7 @@ def _build_z3():
|
|||
if subprocess.call(['nmake'], env=build_env,
|
||||
cwd=BUILD_DIR) != 0:
|
||||
raise LibError("Unable to build Z3.")
|
||||
else: # linux and osx
|
||||
else: # linux and macOS
|
||||
if subprocess.call(['make', '-j', str(multiprocessing.cpu_count())],
|
||||
env=build_env, cwd=BUILD_DIR) != 0:
|
||||
raise LibError("Unable to build Z3.")
|
||||
|
|
|
@ -1258,6 +1258,11 @@ def Consts(names, sort):
|
|||
names = names.split(" ")
|
||||
return [Const(name, sort) for name in names]
|
||||
|
||||
def FreshConst(sort, prefix='c'):
|
||||
"""Create a fresh constant of a specified sort"""
|
||||
ctx = _get_ctx(sort.ctx)
|
||||
return _to_expr_ref(Z3_mk_fresh_const(ctx.ref(), prefix, sort.ast), ctx)
|
||||
|
||||
def Var(idx, s):
|
||||
"""Create a Z3 free variable. Free variables are used to create quantified formulas.
|
||||
|
||||
|
@ -1744,7 +1749,9 @@ class QuantifierRef(BoolRef):
|
|||
return Z3_get_ast_id(self.ctx_ref(), self.as_ast())
|
||||
|
||||
def sort(self):
|
||||
"""Return the Boolean sort."""
|
||||
"""Return the Boolean sort or sort of Lambda."""
|
||||
if self.is_lambda():
|
||||
return _sort(self.ctx, self.as_ast())
|
||||
return BoolSort(self.ctx)
|
||||
|
||||
def is_forall(self):
|
||||
|
@ -2176,6 +2183,8 @@ class ArithRef(ExprRef):
|
|||
>>> (x * y).sort()
|
||||
Real
|
||||
"""
|
||||
if isinstance(other, BoolRef):
|
||||
return If(other, self, 0)
|
||||
a, b = _coerce_exprs(self, other)
|
||||
return ArithRef(_mk_bin(Z3_mk_mul, a, b), self.ctx)
|
||||
|
||||
|
@ -4278,7 +4287,7 @@ def get_map_func(a):
|
|||
_z3_assert(is_map(a), "Z3 array map expression expected.")
|
||||
return FuncDeclRef(Z3_to_func_decl(a.ctx_ref(), Z3_get_decl_ast_parameter(a.ctx_ref(), a.decl().ast, 0)), a.ctx)
|
||||
|
||||
def ArraySort(d, r):
|
||||
def ArraySort(*sig):
|
||||
"""Return the Z3 array sort with the given domain and range sorts.
|
||||
|
||||
>>> A = ArraySort(IntSort(), BoolSort())
|
||||
|
@ -4292,12 +4301,23 @@ def ArraySort(d, r):
|
|||
>>> AA
|
||||
Array(Int, Array(Int, Bool))
|
||||
"""
|
||||
sig = _get_args(sig)
|
||||
if __debug__:
|
||||
_z3_assert(is_sort(d), "Z3 sort expected")
|
||||
_z3_assert(is_sort(r), "Z3 sort expected")
|
||||
_z3_assert(d.ctx == r.ctx, "Context mismatch")
|
||||
_z3_assert(len(sig) > 1, "At least two arguments expected")
|
||||
arity = len(sig) - 1
|
||||
r = sig[arity]
|
||||
d = sig[0]
|
||||
if __debug__:
|
||||
for s in sig:
|
||||
_z3_assert(is_sort(s), "Z3 sort expected")
|
||||
_z3_assert(s.ctx == r.ctx, "Context mismatch")
|
||||
ctx = d.ctx
|
||||
return ArraySortRef(Z3_mk_array_sort(ctx.ref(), d.ast, r.ast), ctx)
|
||||
if len(sig) == 2:
|
||||
return ArraySortRef(Z3_mk_array_sort(ctx.ref(), d.ast, r.ast), ctx)
|
||||
dom = (Sort * arity)()
|
||||
for i in range(arity):
|
||||
dom[i] = sig[i].ast
|
||||
return ArraySortRef(Z3_mk_array_sort_n(ctx.ref(), arity, dom, r.ast), ctx)
|
||||
|
||||
def Array(name, dom, rng):
|
||||
"""Return an array constant named `name` with the given domain and range sorts.
|
||||
|
@ -6603,7 +6623,12 @@ class Solver(Z3PPObject):
|
|||
_handle_parse_error(e, self.ctx)
|
||||
|
||||
def cube(self, vars = None):
|
||||
"""Get set of cubes"""
|
||||
"""Get set of cubes
|
||||
The method takes an optional set of variables that restrict which
|
||||
variables may be used as a starting point for cubing.
|
||||
If vars is not None, then the first case split is based on a variable in
|
||||
this set.
|
||||
"""
|
||||
self.cube_vs = AstVector(None, self.ctx)
|
||||
if vars is not None:
|
||||
for v in vars:
|
||||
|
@ -6619,19 +6644,15 @@ class Solver(Z3PPObject):
|
|||
return
|
||||
|
||||
def cube_vars(self):
|
||||
"""Access the set of variables that were touched by the most recently generated cube.
|
||||
This set of variables can be used as a starting point for additional cubes.
|
||||
The idea is that variables that appear in clauses that are reduced by the most recent
|
||||
cube are likely more useful to cube on."""
|
||||
return self.cube_vs
|
||||
|
||||
def proof(self):
|
||||
"""Return a proof for the last `check()`. Proof construction must be enabled."""
|
||||
return _to_expr_ref(Z3_solver_get_proof(self.ctx.ref(), self.solver), self.ctx)
|
||||
|
||||
def from_file(self, filename):
|
||||
"""Parse assertions from a file"""
|
||||
Z3_solver_from_file(self.ctx.ref(), self.solver, filename)
|
||||
|
||||
def from_string(self, s):
|
||||
"""Parse assertions from a string"""
|
||||
Z3_solver_from_string(self.ctx.ref(), self.solver, s)
|
||||
|
||||
def assertions(self):
|
||||
"""Return an AST vector containing all added constraints.
|
||||
|
@ -6652,6 +6673,11 @@ class Solver(Z3PPObject):
|
|||
"""
|
||||
return AstVector(Z3_solver_get_units(self.ctx.ref(), self.solver), self.ctx)
|
||||
|
||||
def non_units(self):
|
||||
"""Return an AST vector containing all atomic formulas in solver state that are not units.
|
||||
"""
|
||||
return AstVector(Z3_solver_get_non_units(self.ctx.ref(), self.solver), self.ctx)
|
||||
|
||||
def statistics(self):
|
||||
"""Return statistics for the last `check()`.
|
||||
|
||||
|
@ -7285,10 +7311,15 @@ class Optimize(Z3PPObject):
|
|||
"""restore to previously created backtracking point"""
|
||||
Z3_optimize_pop(self.ctx.ref(), self.optimize)
|
||||
|
||||
def check(self):
|
||||
def check(self, *assumptions):
|
||||
"""Check satisfiability while optimizing objective functions."""
|
||||
return CheckSatResult(Z3_optimize_check(self.ctx.ref(), self.optimize))
|
||||
|
||||
assumptions = _get_args(assumptions)
|
||||
num = len(assumptions)
|
||||
_assumptions = (Ast * num)()
|
||||
for i in range(num):
|
||||
_assumptions[i] = assumptions[i].as_ast()
|
||||
return CheckSatResult(Z3_optimize_check(self.ctx.ref(), self.optimize, num, _assumptions))
|
||||
|
||||
def reason_unknown(self):
|
||||
"""Return a string that describes why the last `check()` returned `unknown`."""
|
||||
return Z3_optimize_get_reason_unknown(self.ctx.ref(), self.optimize)
|
||||
|
@ -7300,6 +7331,9 @@ class Optimize(Z3PPObject):
|
|||
except Z3Exception:
|
||||
raise Z3Exception("model is not available")
|
||||
|
||||
def unsat_core(self):
|
||||
return AstVector(Z3_optimize_get_unsat_core(self.ctx.ref(), self.optimize), self.ctx)
|
||||
|
||||
def lower(self, obj):
|
||||
if not isinstance(obj, OptimizeObjective):
|
||||
raise Z3Exception("Expecting objective handle returned by maximize/minimize")
|
||||
|
@ -8040,7 +8074,7 @@ def substitute(t, *m):
|
|||
"""
|
||||
if isinstance(m, tuple):
|
||||
m1 = _get_args(m)
|
||||
if isinstance(m1, list):
|
||||
if isinstance(m1, list) and all(isinstance(p, tuple) for p in m1):
|
||||
m = m1
|
||||
if __debug__:
|
||||
_z3_assert(is_expr(t), "Z3 expression expected")
|
||||
|
|
|
@ -6121,6 +6121,14 @@ extern "C" {
|
|||
*/
|
||||
Z3_ast_vector Z3_API Z3_solver_get_units(Z3_context c, Z3_solver s);
|
||||
|
||||
|
||||
/**
|
||||
\brief Return the set of non units in the solver state.
|
||||
|
||||
def_API('Z3_solver_get_non_units', AST_VECTOR, (_in(CONTEXT), _in(SOLVER)))
|
||||
*/
|
||||
Z3_ast_vector Z3_API Z3_solver_get_non_units(Z3_context c, Z3_solver s);
|
||||
|
||||
/**
|
||||
\brief Check whether the assertions in a given solver are consistent or not.
|
||||
|
||||
|
|
|
@ -117,10 +117,12 @@ extern "C" {
|
|||
\brief Check consistency and produce optimal values.
|
||||
\param c - context
|
||||
\param o - optimization context
|
||||
\param num_assumptions - number of additional assumptions
|
||||
\param assumptions - the additional assumptions
|
||||
|
||||
def_API('Z3_optimize_check', INT, (_in(CONTEXT), _in(OPTIMIZE)))
|
||||
def_API('Z3_optimize_check', INT, (_in(CONTEXT), _in(OPTIMIZE), _in(UINT), _in_array(2, AST)))
|
||||
*/
|
||||
Z3_lbool Z3_API Z3_optimize_check(Z3_context c, Z3_optimize o);
|
||||
Z3_lbool Z3_API Z3_optimize_check(Z3_context c, Z3_optimize o, unsigned num_assumptions, Z3_ast const assumptions[]);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -143,6 +145,14 @@ extern "C" {
|
|||
*/
|
||||
Z3_model Z3_API Z3_optimize_get_model(Z3_context c, Z3_optimize o);
|
||||
|
||||
/**
|
||||
\brief Retrieve the unsat core for the last #Z3_optimize_chec
|
||||
The unsat core is a subset of the assumptions \c a.
|
||||
|
||||
def_API('Z3_optimize_get_unsat_core', AST_VECTOR, (_in(CONTEXT), _in(OPTIMIZE)))
|
||||
*/
|
||||
Z3_ast_vector Z3_API Z3_optimize_get_unsat_core(Z3_context c, Z3_optimize o);
|
||||
|
||||
/**
|
||||
\brief Set parameters on optimization context.
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ Revision History:
|
|||
#include "math/polynomial/algebraic_numbers.h"
|
||||
#include "util/id_gen.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "util/gparams.h"
|
||||
|
||||
struct arith_decl_plugin::algebraic_numbers_wrapper {
|
||||
unsynch_mpq_manager m_qmanager;
|
||||
|
@ -487,7 +488,7 @@ func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
if (arity != 1 || domain[0] != m_int_decl || num_parameters != 1 || !parameters[0].is_int()) {
|
||||
m_manager->raise_exception("invalid divides application. Expects integer parameter and one argument of sort integer");
|
||||
}
|
||||
return m_manager->mk_func_decl(symbol("divides"), 1, &m_int_decl, m_manager->mk_bool_sort(),
|
||||
return m_manager->mk_func_decl(symbol("divisible"), 1, &m_int_decl, m_manager->mk_bool_sort(),
|
||||
func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
|
||||
|
@ -512,7 +513,7 @@ func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
if (num_args != 1 || m_manager->get_sort(args[0]) != m_int_decl || num_parameters != 1 || !parameters[0].is_int()) {
|
||||
m_manager->raise_exception("invalid divides application. Expects integer parameter and one argument of sort integer");
|
||||
}
|
||||
return m_manager->mk_func_decl(symbol("divides"), 1, &m_int_decl, m_manager->mk_bool_sort(),
|
||||
return m_manager->mk_func_decl(symbol("divisible"), 1, &m_int_decl, m_manager->mk_bool_sort(),
|
||||
func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
if (m_manager->int_real_coercions() && use_coercion(k)) {
|
||||
|
@ -549,8 +550,9 @@ void arith_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol con
|
|||
op_names.push_back(builtin_name("*",OP_MUL));
|
||||
op_names.push_back(builtin_name("/",OP_DIV));
|
||||
op_names.push_back(builtin_name("div",OP_IDIV));
|
||||
// clashes with user-defined functions
|
||||
// op_names.push_back(builtin_name("divides",OP_IDIVIDES));
|
||||
if (gparams::get_value("smtlib2_compliant") == "true") {
|
||||
op_names.push_back(builtin_name("divisible",OP_IDIVIDES));
|
||||
}
|
||||
op_names.push_back(builtin_name("rem",OP_REM));
|
||||
op_names.push_back(builtin_name("mod",OP_MOD));
|
||||
op_names.push_back(builtin_name("to_real",OP_TO_REAL));
|
||||
|
|
|
@ -424,7 +424,7 @@ sort * get_sort(expr const * n) {
|
|||
return to_quantifier(n)->get_sort();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1656,6 +1656,12 @@ bool ast_manager::are_distinct(expr* a, expr* b) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
func_decl* ast_manager::get_rec_fun_decl(quantifier* q) const {
|
||||
SASSERT(is_rec_fun_def(q));
|
||||
return to_app(to_app(q->get_pattern(0))->get_arg(0))->get_decl();
|
||||
}
|
||||
|
||||
|
||||
void ast_manager::register_plugin(family_id id, decl_plugin * plugin) {
|
||||
SASSERT(m_plugins.get(id, 0) == 0);
|
||||
m_plugins.setx(id, plugin, 0);
|
||||
|
|
|
@ -1632,6 +1632,7 @@ public:
|
|||
|
||||
bool is_rec_fun_def(quantifier* q) const { return q->get_qid() == m_rec_fun; }
|
||||
bool is_lambda_def(quantifier* q) const { return q->get_qid() == m_lambda_def; }
|
||||
func_decl* get_rec_fun_decl(quantifier* q) const;
|
||||
|
||||
symbol const& rec_fun_qid() const { return m_rec_fun; }
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ bool smt_renaming::all_is_legal(char const* s) {
|
|||
}
|
||||
|
||||
smt_renaming::smt_renaming() {
|
||||
for (unsigned i = 0; i < ARRAYSIZE(m_predef_names); ++i) {
|
||||
for (unsigned i = 0; i < Z3_ARRAYSIZE(m_predef_names); ++i) {
|
||||
symbol s(m_predef_names[i]);
|
||||
m_translate.insert(s, sym_b(s, false));
|
||||
m_rev_translate.insert(s, s);
|
||||
|
|
|
@ -152,21 +152,13 @@ namespace format_ns {
|
|||
|
||||
format * mk_int(ast_manager & m, int i) {
|
||||
char buffer[128];
|
||||
#ifdef _WINDOWS
|
||||
sprintf_s(buffer, ARRAYSIZE(buffer), "%d", i);
|
||||
#else
|
||||
sprintf(buffer, "%d", i);
|
||||
#endif
|
||||
SPRINTF_D(buffer, i);
|
||||
return mk_string(m, buffer);
|
||||
}
|
||||
|
||||
format * mk_unsigned(ast_manager & m, unsigned u) {
|
||||
char buffer[128];
|
||||
#ifdef _WINDOWS
|
||||
sprintf_s(buffer, ARRAYSIZE(buffer), "%u", u);
|
||||
#else
|
||||
sprintf(buffer, "%u", u);
|
||||
#endif
|
||||
SPRINTF_U(buffer, u);
|
||||
return mk_string(m, buffer);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ Notes:
|
|||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/well_sorted.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
#include "ast/used_vars.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
|
||||
#include "ast/fpa/fpa2bv_converter.h"
|
||||
#include "ast/rewriter/fpa_rewriter.h"
|
||||
|
@ -230,6 +232,42 @@ void fpa2bv_converter::mk_var(unsigned base_inx, sort * srt, expr_ref & result)
|
|||
result = m_util.mk_fp(sgn, e, s);
|
||||
}
|
||||
|
||||
expr_ref fpa2bv_converter::extra_quantify(expr * e)
|
||||
{
|
||||
used_vars uv;
|
||||
unsigned nv;
|
||||
|
||||
ptr_buffer<sort> new_decl_sorts;
|
||||
sbuffer<symbol> new_decl_names;
|
||||
expr_ref_buffer subst_map(m);
|
||||
|
||||
uv(e);
|
||||
nv = uv.get_num_vars();
|
||||
subst_map.resize(uv.get_max_found_var_idx_plus_1());
|
||||
|
||||
if (nv == 0)
|
||||
return expr_ref(e, m);
|
||||
|
||||
for (unsigned i = 0; i < nv; i++)
|
||||
{
|
||||
if (uv.contains(i)) {
|
||||
TRACE("fpa2bv", tout << "uv[" << i << "] = " << mk_ismt2_pp(uv.get(i), m) << std::endl; );
|
||||
sort * s = uv.get(i);
|
||||
var * v = m.mk_var(i, s);
|
||||
new_decl_sorts.push_back(s);
|
||||
new_decl_names.push_back(symbol(i));
|
||||
subst_map.set(i, v);
|
||||
}
|
||||
}
|
||||
|
||||
expr_ref res(m);
|
||||
var_subst vsubst(m);
|
||||
res = vsubst.operator()(e, nv, subst_map.c_ptr());
|
||||
TRACE("fpa2bv", tout << "subst'd = " << mk_ismt2_pp(res, m) << std::endl; );
|
||||
res = m.mk_forall(nv, new_decl_sorts.c_ptr(), new_decl_names.c_ptr(), res);
|
||||
return res;
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_uf(func_decl * f, unsigned num, expr * const * args, expr_ref & result)
|
||||
{
|
||||
TRACE("fpa2bv", tout << "UF: " << mk_ismt2_pp(f, m) << std::endl; );
|
||||
|
@ -252,7 +290,7 @@ void fpa2bv_converter::mk_uf(func_decl * f, unsigned num, expr * const * args, e
|
|||
m_bv_util.mk_extract(sbits+ebits-2, sbits-1, bv_app),
|
||||
m_bv_util.mk_extract(sbits-2, 0, bv_app));
|
||||
new_eq = m.mk_eq(fapp, flt_app);
|
||||
m_extra_assertions.push_back(new_eq);
|
||||
m_extra_assertions.push_back(extra_quantify(new_eq));
|
||||
result = flt_app;
|
||||
}
|
||||
else if (m_util.is_rm(rng)) {
|
||||
|
@ -263,7 +301,7 @@ void fpa2bv_converter::mk_uf(func_decl * f, unsigned num, expr * const * args, e
|
|||
bv_app = m.mk_app(bv_f, num, args);
|
||||
flt_app = m_util.mk_bv2rm(bv_app);
|
||||
new_eq = m.mk_eq(fapp, flt_app);
|
||||
m_extra_assertions.push_back(new_eq);
|
||||
m_extra_assertions.push_back(extra_quantify(new_eq));
|
||||
result = flt_app;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -220,6 +220,8 @@ private:
|
|||
|
||||
func_decl * mk_bv_uf(func_decl * f, sort * const * domain, sort * range);
|
||||
expr_ref nan_wrap(expr * n);
|
||||
|
||||
expr_ref extra_quantify(expr * e);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -215,6 +215,12 @@ bool fpa2bv_rewriter_cfg::reduce_quantifier(quantifier * old_q,
|
|||
new_decl_names.push_back(symbol(name_buffer.c_str()));
|
||||
new_decl_sorts.push_back(m_conv.bu().mk_sort(sbits+ebits));
|
||||
}
|
||||
else if (m_conv.is_rm(s)) {
|
||||
name_buffer.reset();
|
||||
name_buffer << n << ".bv";
|
||||
new_decl_names.push_back(symbol(name_buffer.c_str()));
|
||||
new_decl_sorts.push_back(m_conv.bu().mk_sort(3));
|
||||
}
|
||||
else {
|
||||
new_decl_sorts.push_back(s);
|
||||
new_decl_names.push_back(n);
|
||||
|
@ -248,6 +254,11 @@ bool fpa2bv_rewriter_cfg::reduce_var(var * t, expr_ref & result, proof_ref & res
|
|||
m_conv.bu().mk_extract(ebits - 1, 0, new_var),
|
||||
m_conv.bu().mk_extract(sbits+ebits-2, ebits, new_var));
|
||||
}
|
||||
else if (m_conv.is_rm(s)) {
|
||||
expr_ref new_var(m());
|
||||
new_var = m().mk_var(t->get_idx(), m_conv.bu().mk_sort(3));
|
||||
new_exp = m_conv.fu().mk_bv2rm(new_var);
|
||||
}
|
||||
else
|
||||
new_exp = m().mk_var(t->get_idx(), s);
|
||||
|
||||
|
|
|
@ -221,7 +221,7 @@ void defined_names::impl::mk_definition(expr * e, app * n, sort_ref_buffer & var
|
|||
args.push_back(m.mk_var(q->get_num_decls() - i - 1, q->get_decl_sort(i)));
|
||||
}
|
||||
array_util autil(m);
|
||||
func_decl * f = 0;
|
||||
func_decl * f = nullptr;
|
||||
if (autil.is_as_array(n2, f)) {
|
||||
n3 = m.mk_app(f, args.size()-1, args.c_ptr() + 1);
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ class name_nested_formulas : public name_exprs_core {
|
|||
ast_manager & m;
|
||||
expr * m_root;
|
||||
|
||||
pred(ast_manager & m):m(m), m_root(0) {}
|
||||
pred(ast_manager & m):m(m), m_root(nullptr) {}
|
||||
|
||||
bool operator()(expr * t) override {
|
||||
TRACE("name_exprs", tout << "name_nested_formulas::pred:\n" << mk_ismt2_pp(t, m) << "\n";);
|
||||
|
|
|
@ -393,10 +393,8 @@ expr_pattern_match::initialize(char const * spec_string) {
|
|||
VERIFY(parse_smt2_commands(ctx, is));
|
||||
ctx.set_print_success(ps);
|
||||
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
compile(*it);
|
||||
for (expr * e : ctx.assertions()) {
|
||||
compile(e);
|
||||
}
|
||||
TRACE("expr_pattern_match", display(tout); );
|
||||
}
|
||||
|
|
|
@ -1248,7 +1248,7 @@ void proof_checker::dump_proof(proof const* pr) {
|
|||
void proof_checker::dump_proof(unsigned num_antecedents, expr * const * antecedents, expr * consequent) {
|
||||
char buffer[128];
|
||||
#ifdef _WINDOWS
|
||||
sprintf_s(buffer, ARRAYSIZE(buffer), "proof_lemma_%d.smt2", m_proof_lemma_id);
|
||||
sprintf_s(buffer, Z3_ARRAYSIZE(buffer), "proof_lemma_%d.smt2", m_proof_lemma_id);
|
||||
#else
|
||||
sprintf(buffer, "proof_lemma_%d.smt2", m_proof_lemma_id);
|
||||
#endif
|
||||
|
|
|
@ -458,7 +458,7 @@ struct pb2bv_rewriter::imp {
|
|||
result = m.mk_true();
|
||||
expr_ref_vector carry(m), new_carry(m);
|
||||
m_base.push_back(bound + rational::one());
|
||||
for (rational b_i : m_base) {
|
||||
for (const rational& b_i : m_base) {
|
||||
unsigned B = b_i.get_unsigned();
|
||||
unsigned d_i = (bound % b_i).get_unsigned();
|
||||
bound = div(bound, b_i);
|
||||
|
|
|
@ -842,7 +842,9 @@ void seq_decl_plugin::get_sort_names(svector<builtin_name> & sort_names, symbol
|
|||
}
|
||||
|
||||
app* seq_decl_plugin::mk_string(symbol const& s) {
|
||||
parameter param(s);
|
||||
zstring canonStr(s.bare_str());
|
||||
symbol canonSym(canonStr.encode().c_str());
|
||||
parameter param(canonSym);
|
||||
func_decl* f = m_manager->mk_const_decl(m_stringc_sym, m_string,
|
||||
func_decl_info(m_family_id, OP_STRING_CONST, 1, ¶m));
|
||||
return m_manager->mk_const(f);
|
||||
|
|
|
@ -17,7 +17,7 @@ Notes:
|
|||
--*/
|
||||
#include "util/gparams.h"
|
||||
#include "util/env_params.h"
|
||||
#include "util/version.h"
|
||||
#include "util/z3_version.h"
|
||||
#include "ast/ast_smt_pp.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/ast_pp_dot.h"
|
||||
|
|
|
@ -1315,7 +1315,7 @@ void cmd_context::assert_expr(expr * t) {
|
|||
m().inc_ref(t);
|
||||
m_assertions.push_back(t);
|
||||
if (produce_unsat_cores())
|
||||
m_assertion_names.push_back(0);
|
||||
m_assertion_names.push_back(nullptr);
|
||||
if (m_solver)
|
||||
m_solver->assert_expr(t);
|
||||
}
|
||||
|
@ -1491,13 +1491,24 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions
|
|||
scoped_ctrl_c ctrlc(eh);
|
||||
scoped_timer timer(timeout, &eh);
|
||||
scoped_rlimit _rlimit(m().limit(), rlimit);
|
||||
expr_ref_vector asms(m());
|
||||
asms.append(num_assumptions, assumptions);
|
||||
if (!m_processing_pareto) {
|
||||
ptr_vector<expr> cnstr(m_assertions);
|
||||
cnstr.append(num_assumptions, assumptions);
|
||||
get_opt()->set_hard_constraints(cnstr);
|
||||
expr_ref_vector assertions(m());
|
||||
unsigned sz = m_assertions.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
if (m_assertion_names.size() > i && m_assertion_names[i]) {
|
||||
asms.push_back(m_assertion_names[i]);
|
||||
assertions.push_back(m().mk_implies(m_assertion_names[i], m_assertions[i]));
|
||||
}
|
||||
else {
|
||||
assertions.push_back(m_assertions[i]);
|
||||
}
|
||||
}
|
||||
get_opt()->set_hard_constraints(assertions);
|
||||
}
|
||||
try {
|
||||
r = get_opt()->optimize();
|
||||
r = get_opt()->optimize(asms);
|
||||
if (r == l_true && get_opt()->is_pareto()) {
|
||||
m_processing_pareto = true;
|
||||
}
|
||||
|
@ -1805,11 +1816,8 @@ void cmd_context::validate_model() {
|
|||
cancel_eh<reslimit> eh(m().limit());
|
||||
expr_ref r(m());
|
||||
scoped_ctrl_c ctrlc(eh);
|
||||
ptr_vector<expr>::const_iterator it = begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = end_assertions();
|
||||
bool invalid_model = false;
|
||||
for (; it != end; ++it) {
|
||||
expr * a = *it;
|
||||
for (expr * a : assertions()) {
|
||||
if (is_ground(a)) {
|
||||
r = nullptr;
|
||||
evaluator(a, r);
|
||||
|
|
|
@ -148,8 +148,8 @@ public:
|
|||
virtual bool empty() = 0;
|
||||
virtual void push() = 0;
|
||||
virtual void pop(unsigned n) = 0;
|
||||
virtual lbool optimize() = 0;
|
||||
virtual void set_hard_constraints(ptr_vector<expr> & hard) = 0;
|
||||
virtual lbool optimize(expr_ref_vector const& asms) = 0;
|
||||
virtual void set_hard_constraints(expr_ref_vector const & hard) = 0;
|
||||
virtual void display_assignment(std::ostream& out) = 0;
|
||||
virtual bool is_pareto() = 0;
|
||||
virtual void set_logic(symbol const& s) = 0;
|
||||
|
@ -452,11 +452,8 @@ public:
|
|||
|
||||
double get_seconds() const { return m_watch.get_seconds(); }
|
||||
|
||||
ptr_vector<expr>::const_iterator begin_assertions() const { return m_assertions.begin(); }
|
||||
ptr_vector<expr>::const_iterator end_assertions() const { return m_assertions.end(); }
|
||||
|
||||
ptr_vector<expr>::const_iterator begin_assertion_names() const { return m_assertion_names.begin(); }
|
||||
ptr_vector<expr>::const_iterator end_assertion_names() const { return m_assertion_names.end(); }
|
||||
ptr_vector<expr> const& assertions() const { return m_assertions; }
|
||||
ptr_vector<expr> const& assertion_names() const { return m_assertion_names; }
|
||||
|
||||
/**
|
||||
\brief Hack: consume assertions if there are no scopes.
|
||||
|
|
|
@ -28,20 +28,18 @@ void assert_exprs_from(cmd_context const & ctx, goal & t) {
|
|||
ast_manager & m = t.m();
|
||||
bool proofs_enabled = t.proofs_enabled();
|
||||
if (ctx.produce_unsat_cores()) {
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
ptr_vector<expr>::const_iterator it2 = ctx.begin_assertion_names();
|
||||
SASSERT(end - it == ctx.end_assertion_names() - it2);
|
||||
ptr_vector<expr>::const_iterator it = ctx.assertions().begin();
|
||||
ptr_vector<expr>::const_iterator end = ctx.assertions().end();
|
||||
ptr_vector<expr>::const_iterator it2 = ctx.assertion_names().begin();
|
||||
SASSERT(ctx.assertions().size() == ctx.assertion_names().size());
|
||||
for (; it != end; ++it, ++it2) {
|
||||
t.assert_expr(*it, proofs_enabled ? m.mk_asserted(*it) : nullptr, m.mk_leaf(*it2));
|
||||
}
|
||||
}
|
||||
else {
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
t.assert_expr(*it, proofs_enabled ? m.mk_asserted(*it) : nullptr, nullptr);
|
||||
for (expr * e : ctx.assertions()) {
|
||||
t.assert_expr(e, proofs_enabled ? m.mk_asserted(e) : nullptr, nullptr);
|
||||
}
|
||||
SASSERT(ctx.begin_assertion_names() == ctx.end_assertion_names());
|
||||
SASSERT(ctx.assertion_names().empty());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
class psort_inst_cache;
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
// CMW: for some unknown reason, llvm on OSX does not like the name `psort'
|
||||
// CMW: for some unknown reason, llvm on macOS does not like the name `psort'
|
||||
#define psort Z3_psort
|
||||
#endif
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace polynomial {
|
|||
|
||||
struct lt_var {
|
||||
bool operator()(power const & p1, power const & p2) {
|
||||
// CMW: The assertion below does not hold on OSX, because
|
||||
// CMW: The assertion below does not hold on macOS, because
|
||||
// their implementation of std::sort will try to compare
|
||||
// two items at the same index instead of comparing
|
||||
// the indices directly. I suspect that the purpose of
|
||||
|
|
|
@ -351,7 +351,7 @@ bool model::can_inline_def(top_sort& ts, func_decl* f) {
|
|||
|
||||
|
||||
expr_ref model::cleanup_expr(top_sort& ts, expr* e, unsigned current_partition) {
|
||||
if (!e) return expr_ref(0, m);
|
||||
if (!e) return expr_ref(nullptr, m);
|
||||
|
||||
TRACE("model", tout << "cleaning up:\n" << mk_pp(e, m) << "\n";);
|
||||
|
||||
|
@ -453,7 +453,7 @@ void model::remove_decls(ptr_vector<func_decl> & decls, func_decl_set const & s)
|
|||
|
||||
expr_ref model::get_inlined_const_interp(func_decl* f) {
|
||||
expr* v = get_const_interp(f);
|
||||
if (!v) return expr_ref(0, m);
|
||||
if (!v) return expr_ref(nullptr, m);
|
||||
top_sort st(m);
|
||||
expr_ref result1(v, m);
|
||||
expr_ref result2 = cleanup_expr(st, v, UINT_MAX);
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace datalog {
|
|||
rule_dependencies::rule_dependencies(const rule_dependencies & o, bool reversed):
|
||||
m_context(o.m_context) {
|
||||
if (reversed) {
|
||||
for (auto & kv : o) {
|
||||
for (auto & kv : o) {
|
||||
func_decl * pred = kv.m_key;
|
||||
item_set & orig_items = *kv.get_value();
|
||||
|
||||
|
@ -114,8 +114,8 @@ namespace datalog {
|
|||
app* a = to_app(e);
|
||||
d = a->get_decl();
|
||||
if (m_context.is_predicate(d)) {
|
||||
// insert d and ensure the invariant
|
||||
// that every predicate is present as
|
||||
// insert d and ensure the invariant
|
||||
// that every predicate is present as
|
||||
// a key in m_data
|
||||
s.insert(d);
|
||||
ensure_key(d);
|
||||
|
@ -148,7 +148,7 @@ namespace datalog {
|
|||
item_set& itms = *kv.get_value();
|
||||
set_intersection(itms, allowed);
|
||||
}
|
||||
for (func_decl* f : to_remove)
|
||||
for (func_decl* f : to_remove)
|
||||
remove_m_data_entry(f);
|
||||
}
|
||||
|
||||
|
@ -253,18 +253,18 @@ namespace datalog {
|
|||
//
|
||||
// -----------------------------------
|
||||
|
||||
rule_set::rule_set(context & ctx)
|
||||
: m_context(ctx),
|
||||
m_rule_manager(ctx.get_rule_manager()),
|
||||
m_rules(m_rule_manager),
|
||||
rule_set::rule_set(context & ctx)
|
||||
: m_context(ctx),
|
||||
m_rule_manager(ctx.get_rule_manager()),
|
||||
m_rules(m_rule_manager),
|
||||
m_deps(ctx),
|
||||
m_stratifier(nullptr),
|
||||
m_refs(ctx.get_manager()) {
|
||||
}
|
||||
|
||||
rule_set::rule_set(const rule_set & other)
|
||||
: m_context(other.m_context),
|
||||
m_rule_manager(other.m_rule_manager),
|
||||
rule_set::rule_set(const rule_set & other)
|
||||
: m_context(other.m_context),
|
||||
m_rule_manager(other.m_rule_manager),
|
||||
m_rules(m_rule_manager),
|
||||
m_deps(other.m_context),
|
||||
m_stratifier(nullptr),
|
||||
|
@ -353,10 +353,27 @@ namespace datalog {
|
|||
break; \
|
||||
} \
|
||||
} \
|
||||
|
||||
|
||||
DEL_VECTOR(*rules);
|
||||
DEL_VECTOR(m_rules);
|
||||
}
|
||||
}
|
||||
|
||||
void rule_set::replace_rule(rule * r, rule * other) {
|
||||
TRACE("dl", r->display(m_context, tout << "replace:"););
|
||||
func_decl* d = r->get_decl();
|
||||
rule_vector* rules = m_head2rules.find(d);
|
||||
#define REPLACE_VECTOR(_v) \
|
||||
for (unsigned i = (_v).size(); i > 0; ) { \
|
||||
--i; \
|
||||
if ((_v)[i] == r) { \
|
||||
(_v)[i] = other; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
|
||||
REPLACE_VECTOR(*rules);
|
||||
REPLACE_VECTOR(m_rules);
|
||||
}
|
||||
|
||||
void rule_set::ensure_closed() {
|
||||
if (!is_closed()) {
|
||||
|
@ -365,7 +382,7 @@ namespace datalog {
|
|||
}
|
||||
|
||||
bool rule_set::close() {
|
||||
SASSERT(!is_closed()); //the rule_set is not already closed
|
||||
SASSERT(!is_closed()); //the rule_set is not already closed
|
||||
m_deps.populate(*this);
|
||||
m_stratifier = alloc(rule_stratifier, m_deps);
|
||||
if (!stratified_negation()) {
|
||||
|
@ -426,7 +443,7 @@ namespace datalog {
|
|||
inherit_predicates(src);
|
||||
}
|
||||
|
||||
const rule_vector & rule_set::get_predicate_rules(func_decl * pred) const {
|
||||
const rule_vector & rule_set::get_predicate_rules(func_decl * pred) const {
|
||||
decl2rules::obj_map_entry * e = m_head2rules.find_core(pred);
|
||||
if (!e) {
|
||||
return m_empty_rule_vector;
|
||||
|
@ -519,7 +536,7 @@ namespace datalog {
|
|||
out << "\n";
|
||||
non_empty = false;
|
||||
}
|
||||
|
||||
|
||||
for (func_decl * first : *strat) {
|
||||
const func_decl_set & deps = m_deps.get_deps(first);
|
||||
for (func_decl * dep : deps) {
|
||||
|
@ -545,8 +562,8 @@ namespace datalog {
|
|||
unsigned rule_stratifier::get_predicate_strat(func_decl * pred) const {
|
||||
unsigned num;
|
||||
if (!m_pred_strat_nums.find(pred, num)) {
|
||||
//the number of the predicate is not stored, therefore it did not appear
|
||||
//in the algorithm and therefore it does not depend on anything and nothing
|
||||
//the number of the predicate is not stored, therefore it did not appear
|
||||
//in the algorithm and therefore it does not depend on anything and nothing
|
||||
//depends on it. So it is safe to assign zero strate to it, although it is
|
||||
//not strictly true.
|
||||
num = 0;
|
||||
|
@ -641,7 +658,7 @@ namespace datalog {
|
|||
}
|
||||
|
||||
|
||||
// We put components whose indegree is zero to m_strats and assign its
|
||||
// We put components whose indegree is zero to m_strats and assign its
|
||||
// m_components entry to zero.
|
||||
unsigned comp_cnt = m_components.size();
|
||||
for (unsigned i = 0; i < comp_cnt; i++) {
|
||||
|
@ -680,7 +697,7 @@ namespace datalog {
|
|||
strats_index++;
|
||||
}
|
||||
//we have managed to topologicaly order all the components
|
||||
SASSERT(std::find_if(m_components.begin(), m_components.end(),
|
||||
SASSERT(std::find_if(m_components.begin(), m_components.end(),
|
||||
std::bind1st(std::not_equal_to<item_set*>(), (item_set*)0)) == m_components.end());
|
||||
|
||||
//reverse the strats array, so that the only the later components would depend on earlier ones
|
||||
|
@ -713,7 +730,7 @@ namespace datalog {
|
|||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -77,7 +77,7 @@ namespace datalog {
|
|||
\brief Number of predicates that depend on \c f.
|
||||
*/
|
||||
unsigned out_degree(func_decl * f) const;
|
||||
|
||||
|
||||
/**
|
||||
\brief If the rependency graph is acyclic, put all elements into \c res
|
||||
ordered so that elements can depend only on elements that are before them.
|
||||
|
@ -131,7 +131,7 @@ namespace datalog {
|
|||
it must exist for the whole lifetime of the \c stratifier object.
|
||||
*/
|
||||
rule_stratifier(const rule_dependencies & deps)
|
||||
: m_deps(deps), m_next_preorder(0)
|
||||
: m_deps(deps), m_next_preorder(0)
|
||||
{
|
||||
process();
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ namespace datalog {
|
|||
const comp_vector & get_strats() const { return m_strats; }
|
||||
|
||||
unsigned get_predicate_strat(func_decl * pred) const;
|
||||
|
||||
|
||||
void display( std::ostream & out ) const;
|
||||
};
|
||||
|
||||
|
@ -203,6 +203,10 @@ namespace datalog {
|
|||
\brief Remove rule \c r from the rule set.
|
||||
*/
|
||||
void del_rule(rule * r);
|
||||
/**
|
||||
\brief Replace a rule \c r with the rule \c other
|
||||
*/
|
||||
void replace_rule(rule * r, rule * other);
|
||||
|
||||
/**
|
||||
\brief Add all rules from a different rule_set.
|
||||
|
@ -276,8 +280,7 @@ namespace datalog {
|
|||
inline std::ostream& operator<<(std::ostream& out, rule_set const& r) { r.display(out); return out; }
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif /* DL_RULE_SET_H_ */
|
||||
|
||||
|
|
|
@ -276,7 +276,7 @@ namespace datalog {
|
|||
}
|
||||
unsigned n = container.size();
|
||||
unsigned ofs = 1;
|
||||
int r_i = 1;
|
||||
unsigned r_i = 1;
|
||||
for(unsigned i=removed_cols[0]+1; i<n; i++) {
|
||||
if(r_i!=removed_col_cnt && removed_cols[r_i]==i) {
|
||||
r_i++;
|
||||
|
|
|
@ -177,5 +177,6 @@ def_module_params('fp',
|
|||
('spacer.dump_threshold', DOUBLE, 5.0, 'Threshold in seconds on dumping benchmarks'),
|
||||
('spacer.gpdr', BOOL, False, 'Use GPDR solving strategy for non-linear CHC'),
|
||||
('spacer.gpdr.bfs', BOOL, True, 'Use BFS exploration strategy for expanding model search'),
|
||||
('spacer.use_bg_invs', BOOL, False, 'Enable external background invariants'),
|
||||
|
||||
))
|
||||
|
|
|
@ -332,10 +332,8 @@ public:
|
|||
private:
|
||||
void set_background(cmd_context& ctx) {
|
||||
datalog::context& dlctx = m_dl_ctx->dlctx();
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
dlctx.assert_expr(*it);
|
||||
for (expr * e : ctx.assertions()) {
|
||||
dlctx.assert_expr(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -493,7 +493,8 @@ lemma::lemma (ast_manager &manager, expr * body, unsigned lvl) :
|
|||
m_pob(nullptr), m_ctp(nullptr),
|
||||
m_lvl(lvl), m_init_lvl(m_lvl),
|
||||
m_bumped(0), m_weakness(WEAKNESS_MAX),
|
||||
m_external(false), m_blocked(false) {
|
||||
m_external(false), m_blocked(false),
|
||||
m_background(false) {
|
||||
SASSERT(m_body);
|
||||
normalize(m_body, m_body);
|
||||
}
|
||||
|
@ -505,7 +506,8 @@ lemma::lemma(pob_ref const &p) :
|
|||
m_pob(p), m_ctp(nullptr),
|
||||
m_lvl(p->level()), m_init_lvl(m_lvl),
|
||||
m_bumped(0), m_weakness(p->weakness()),
|
||||
m_external(false), m_blocked(false) {
|
||||
m_external(false), m_blocked(false),
|
||||
m_background(false) {
|
||||
SASSERT(m_pob);
|
||||
m_pob->get_skolems(m_zks);
|
||||
add_binding(m_pob->get_binding());
|
||||
|
@ -519,8 +521,8 @@ lemma::lemma(pob_ref const &p, expr_ref_vector &cube, unsigned lvl) :
|
|||
m_pob(p), m_ctp(nullptr),
|
||||
m_lvl(p->level()), m_init_lvl(m_lvl),
|
||||
m_bumped(0), m_weakness(p->weakness()),
|
||||
m_external(false), m_blocked(false)
|
||||
{
|
||||
m_external(false), m_blocked(false),
|
||||
m_background(false) {
|
||||
if (m_pob) {
|
||||
m_pob->get_skolems(m_zks);
|
||||
add_binding(m_pob->get_binding());
|
||||
|
@ -921,10 +923,10 @@ void pred_transformer::simplify_formulas()
|
|||
{m_frames.simplify_formulas ();}
|
||||
|
||||
|
||||
expr_ref pred_transformer::get_formulas(unsigned level) const
|
||||
expr_ref pred_transformer::get_formulas(unsigned level, bool bg) const
|
||||
{
|
||||
expr_ref_vector res(m);
|
||||
m_frames.get_frame_geq_lemmas (level, res);
|
||||
m_frames.get_frame_geq_lemmas (level, res, bg);
|
||||
return mk_and(res);
|
||||
}
|
||||
|
||||
|
@ -935,6 +937,7 @@ bool pred_transformer::propagate_to_next_level (unsigned src_level)
|
|||
/// \brief adds a lemma to the solver and to child solvers
|
||||
void pred_transformer::add_lemma_core(lemma* lemma, bool ground_only)
|
||||
{
|
||||
SASSERT(!lemma->is_background());
|
||||
unsigned lvl = lemma->level();
|
||||
expr* l = lemma->get_expr();
|
||||
SASSERT(!lemma->is_ground() || is_clause(m, l));
|
||||
|
@ -975,8 +978,9 @@ void pred_transformer::add_lemma_core(lemma* lemma, bool ground_only)
|
|||
next_level(lvl), ground_only); }
|
||||
}
|
||||
|
||||
bool pred_transformer::add_lemma (expr *e, unsigned lvl) {
|
||||
bool pred_transformer::add_lemma (expr *e, unsigned lvl, bool bg) {
|
||||
lemma_ref lem = alloc(lemma, m, e, lvl);
|
||||
lem->set_background(bg);
|
||||
return m_frames.add_lemma(lem.get());
|
||||
}
|
||||
|
||||
|
@ -1217,15 +1221,18 @@ expr_ref pred_transformer::get_origin_summary (model &mdl,
|
|||
}
|
||||
|
||||
|
||||
void pred_transformer::add_cover(unsigned level, expr* property)
|
||||
void pred_transformer::add_cover(unsigned level, expr* property, bool bg)
|
||||
{
|
||||
SASSERT(!bg || is_infty_level(level));
|
||||
// replace bound variables by local constants.
|
||||
expr_ref result(property, m), v(m), c(m);
|
||||
expr_substitution sub(m);
|
||||
proof_ref pr(m);
|
||||
pr = m.mk_asserted(m.mk_true());
|
||||
for (unsigned i = 0; i < sig_size(); ++i) {
|
||||
c = m.mk_const(pm.o2n(sig(i), 0));
|
||||
v = m.mk_var(i, sig(i)->get_range());
|
||||
sub.insert(v, c);
|
||||
sub.insert(v, c, pr);
|
||||
}
|
||||
scoped_ptr<expr_replacer> rep = mk_default_expr_replacer(m);
|
||||
rep->set_substitution(&sub);
|
||||
|
@ -1236,13 +1243,38 @@ void pred_transformer::add_cover(unsigned level, expr* property)
|
|||
expr_ref_vector lemmas(m);
|
||||
flatten_and(result, lemmas);
|
||||
for (unsigned i = 0, sz = lemmas.size(); i < sz; ++i) {
|
||||
add_lemma(lemmas.get(i), level);
|
||||
add_lemma(lemmas.get(i), level, bg);
|
||||
}
|
||||
}
|
||||
|
||||
void pred_transformer::propagate_to_infinity (unsigned level)
|
||||
{m_frames.propagate_to_infinity (level);}
|
||||
|
||||
// compute a conjunction of all background facts
|
||||
void pred_transformer::get_pred_bg_invs(expr_ref_vector& out) {
|
||||
expr_ref inv(m), tmp1(m), tmp2(m);
|
||||
ptr_vector<func_decl> preds;
|
||||
for (auto kv : m_pt_rules) {
|
||||
expr* tag = kv.m_value->tag();
|
||||
datalog::rule const &r = kv.m_value->rule();
|
||||
find_predecessors (r, preds);
|
||||
|
||||
for (unsigned i = 0, preds_sz = preds.size(); i < preds_sz; i++) {
|
||||
func_decl* pre = preds[i];
|
||||
pred_transformer &pt = ctx.get_pred_transformer(pre);
|
||||
const lemma_ref_vector &invs = pt.get_bg_invs();
|
||||
CTRACE("spacer", !invs.empty(),
|
||||
tout << "add-bg-invariant: " << mk_pp (pre, m) << "\n";);
|
||||
for (auto inv : invs) {
|
||||
// tag -> inv1 ... tag -> invn
|
||||
tmp1 = m.mk_implies(tag, inv->get_expr());
|
||||
pm.formula_n2o(tmp1, tmp2, i);
|
||||
out.push_back(tmp2);
|
||||
TRACE("spacer", tout << tmp2 << "\n";);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// \brief Returns true if the obligation is already blocked by current lemmas
|
||||
|
@ -1293,7 +1325,7 @@ bool pred_transformer::is_qblocked (pob &n) {
|
|||
|
||||
// assert cti
|
||||
s->assert_expr(n.post());
|
||||
lbool res = s->check_sat(0, 0);
|
||||
lbool res = s->check_sat(0, nullptr);
|
||||
|
||||
// if (res == l_false) {
|
||||
// expr_ref_vector core(m);
|
||||
|
@ -1344,6 +1376,14 @@ lbool pred_transformer::is_reachable(pob& n, expr_ref_vector* core,
|
|||
|
||||
expr_ref_vector post (m), reach_assumps (m);
|
||||
post.push_back (n.post ());
|
||||
flatten_and(post);
|
||||
|
||||
// if equality propagation is disabled in arithmetic, expand
|
||||
// equality literals into two inequalities to increase the space
|
||||
// for interpolation
|
||||
if (!ctx.use_eq_prop()) {
|
||||
expand_literals(m, post);
|
||||
}
|
||||
|
||||
// populate reach_assumps
|
||||
if (n.level () > 0 && !m_all_init) {
|
||||
|
@ -1472,7 +1512,7 @@ bool pred_transformer::is_invariant(unsigned level, lemma* lem,
|
|||
expr_ref lemma_expr(m);
|
||||
lemma_expr = lem->get_expr();
|
||||
|
||||
expr_ref_vector conj(m), aux(m);
|
||||
expr_ref_vector cand(m), aux(m), conj(m);
|
||||
expr_ref gnd_lemma(m);
|
||||
|
||||
|
||||
|
@ -1482,8 +1522,8 @@ bool pred_transformer::is_invariant(unsigned level, lemma* lem,
|
|||
lemma_expr = gnd_lemma.get();
|
||||
}
|
||||
|
||||
conj.push_back(mk_not(m, lemma_expr));
|
||||
flatten_and (conj);
|
||||
cand.push_back(mk_not(m, lemma_expr));
|
||||
flatten_and (cand);
|
||||
|
||||
prop_solver::scoped_level _sl(*m_solver, level);
|
||||
prop_solver::scoped_subset_core _sc (*m_solver, true);
|
||||
|
@ -1494,9 +1534,12 @@ bool pred_transformer::is_invariant(unsigned level, lemma* lem,
|
|||
if (ctx.use_ctp()) {mdl_ref_ptr = &mdl;}
|
||||
m_solver->set_core(core);
|
||||
m_solver->set_model(mdl_ref_ptr);
|
||||
expr * bg = m_extend_lit.get ();
|
||||
lbool r = m_solver->check_assumptions (conj, aux, m_transition_clause,
|
||||
1, &bg, 1);
|
||||
|
||||
conj.push_back(m_extend_lit);
|
||||
if (ctx.use_bg_invs()) get_pred_bg_invs(conj);
|
||||
|
||||
lbool r = m_solver->check_assumptions (cand, aux, m_transition_clause,
|
||||
conj.size(), conj.c_ptr(), 1);
|
||||
if (r == l_false) {
|
||||
solver_level = m_solver->uses_level ();
|
||||
lem->reset_ctp();
|
||||
|
@ -1527,6 +1570,7 @@ bool pred_transformer::check_inductive(unsigned level, expr_ref_vector& state,
|
|||
m_solver->set_core(&core);
|
||||
m_solver->set_model (nullptr);
|
||||
expr_ref_vector aux (m);
|
||||
if (ctx.use_bg_invs()) get_pred_bg_invs(conj);
|
||||
conj.push_back (m_extend_lit);
|
||||
lbool res = m_solver->check_assumptions (state, aux,
|
||||
m_transition_clause,
|
||||
|
@ -1941,14 +1985,27 @@ void pred_transformer::update_solver_with_rfs(prop_solver *solver,
|
|||
}
|
||||
|
||||
/// pred_transformer::frames
|
||||
|
||||
|
||||
bool pred_transformer::frames::add_lemma(lemma *new_lemma)
|
||||
{
|
||||
TRACE("spacer", tout << "add-lemma: " << pp_level(new_lemma->level()) << " "
|
||||
<< m_pt.head()->get_name() << " "
|
||||
<< mk_pp(new_lemma->get_expr(), m_pt.get_ast_manager()) << "\n";);
|
||||
|
||||
if (new_lemma->is_background()) {
|
||||
SASSERT (is_infty_level(new_lemma->level()));
|
||||
|
||||
for (auto &l : m_bg_invs) {
|
||||
if (l->get_expr() == new_lemma->get_expr()) return false;
|
||||
}
|
||||
TRACE("spacer", tout << "add-external-lemma: "
|
||||
<< pp_level(new_lemma->level()) << " "
|
||||
<< m_pt.head()->get_name() << " "
|
||||
<< mk_pp(new_lemma->get_expr(), m_pt.get_ast_manager()) << "\n";);
|
||||
|
||||
m_bg_invs.push_back(new_lemma);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned i = 0;
|
||||
for (auto *old_lemma : m_lemmas) {
|
||||
if (old_lemma->get_expr() == new_lemma->get_expr()) {
|
||||
|
@ -2295,6 +2352,7 @@ void context::updt_params() {
|
|||
m_use_restarts = m_params.spacer_restarts();
|
||||
m_restart_initial_threshold = m_params.spacer_restart_initial_threshold();
|
||||
m_pdr_bfs = m_params.spacer_gpdr_bfs();
|
||||
m_use_bg_invs = m_params.spacer_use_bg_invs();
|
||||
|
||||
if (m_use_gpdr) {
|
||||
// set options to be compatible with GPDR
|
||||
|
@ -2423,36 +2481,38 @@ expr_ref context::get_cover_delta(int level, func_decl* p_orig, func_decl* p)
|
|||
if (m_rels.find(p, pt)) {
|
||||
return pt->get_cover_delta(p_orig, level);
|
||||
} else {
|
||||
IF_VERBOSE(10, verbose_stream() << "did not find predicate " << p->get_name() << "\n";);
|
||||
IF_VERBOSE(10, verbose_stream() << "did not find predicate "
|
||||
<< p->get_name() << "\n";);
|
||||
return expr_ref(m.mk_true(), m);
|
||||
}
|
||||
}
|
||||
|
||||
void context::add_cover(int level, func_decl* p, expr* property)
|
||||
void context::add_cover(int level, func_decl* p, expr* property, bool bg)
|
||||
{
|
||||
scoped_proof _pf_(m);
|
||||
|
||||
pred_transformer* pt = nullptr;
|
||||
if (!m_rels.find(p, pt)) {
|
||||
pt = alloc(pred_transformer, *this, get_manager(), p);
|
||||
m_rels.insert(p, pt);
|
||||
IF_VERBOSE(10, verbose_stream() << "did not find predicate " << p->get_name() << "\n";);
|
||||
IF_VERBOSE(10, verbose_stream() << "did not find predicate "
|
||||
<< p->get_name() << "\n";);
|
||||
}
|
||||
unsigned lvl = (level == -1)?infty_level():((unsigned)level);
|
||||
pt->add_cover(lvl, property);
|
||||
pt->add_cover(lvl, property, bg);
|
||||
}
|
||||
|
||||
void context::add_invariant (func_decl *p, expr *property)
|
||||
{add_cover (infty_level(), p, property);}
|
||||
{add_cover (infty_level(), p, property, true);}
|
||||
|
||||
expr_ref context::get_reachable(func_decl *p)
|
||||
{
|
||||
expr_ref context::get_reachable(func_decl *p) {
|
||||
pred_transformer* pt = nullptr;
|
||||
if (!m_rels.find(p, pt))
|
||||
{ return expr_ref(m.mk_false(), m); }
|
||||
return pt->get_reachable();
|
||||
}
|
||||
|
||||
bool context::validate()
|
||||
{
|
||||
bool context::validate() {
|
||||
if (!m_validate_result) { return true; }
|
||||
|
||||
std::stringstream msg;
|
||||
|
@ -2483,7 +2543,7 @@ bool context::validate()
|
|||
model_ref model;
|
||||
vector<relation_info> rs;
|
||||
model_converter_ref mc;
|
||||
get_level_property(m_inductive_lvl, refs, rs);
|
||||
get_level_property(m_inductive_lvl, refs, rs, use_bg_invs());
|
||||
inductive_property ex(m, mc, rs);
|
||||
ex.to_model(model);
|
||||
var_subst vs(m, false);
|
||||
|
@ -2624,13 +2684,13 @@ void context::init_lemma_generalizers()
|
|||
}
|
||||
|
||||
void context::get_level_property(unsigned lvl, expr_ref_vector& res,
|
||||
vector<relation_info>& rs) const {
|
||||
vector<relation_info>& rs, bool with_bg) const {
|
||||
for (auto const& kv : m_rels) {
|
||||
pred_transformer* r = kv.m_value;
|
||||
if (r->head() == m_query_pred) {
|
||||
continue;
|
||||
}
|
||||
expr_ref conj = r->get_formulas(lvl);
|
||||
expr_ref conj = r->get_formulas(lvl, with_bg);
|
||||
m_pm.formula_n2o(0, false, conj);
|
||||
res.push_back(conj);
|
||||
ptr_vector<func_decl> sig(r->head()->get_arity(), r->sig());
|
||||
|
@ -2662,7 +2722,7 @@ lbool context::solve(unsigned from_lvl)
|
|||
IF_VERBOSE(1, {
|
||||
expr_ref_vector refs(m);
|
||||
vector<relation_info> rs;
|
||||
get_level_property(m_inductive_lvl, refs, rs);
|
||||
get_level_property(m_inductive_lvl, refs, rs, use_bg_invs());
|
||||
model_converter_ref mc;
|
||||
inductive_property ex(m, mc, rs);
|
||||
verbose_stream() << ex.to_string();
|
||||
|
@ -2844,7 +2904,7 @@ model_ref context::get_model()
|
|||
model_ref model;
|
||||
expr_ref_vector refs(m);
|
||||
vector<relation_info> rs;
|
||||
get_level_property(m_inductive_lvl, refs, rs);
|
||||
get_level_property(m_inductive_lvl, refs, rs, use_bg_invs());
|
||||
inductive_property ex(m, const_cast<model_converter_ref&>(m_mc), rs);
|
||||
ex.to_model (model);
|
||||
return model;
|
||||
|
@ -2877,7 +2937,7 @@ expr_ref context::mk_unsat_answer() const
|
|||
{
|
||||
expr_ref_vector refs(m);
|
||||
vector<relation_info> rs;
|
||||
get_level_property(m_inductive_lvl, refs, rs);
|
||||
get_level_property(m_inductive_lvl, refs, rs, use_bg_invs());
|
||||
inductive_property ex(m, const_cast<model_converter_ref&>(m_mc), rs);
|
||||
return ex.to_expr();
|
||||
}
|
||||
|
|
|
@ -128,8 +128,9 @@ class lemma {
|
|||
unsigned m_init_lvl; // level at which lemma was created
|
||||
unsigned m_bumped:16;
|
||||
unsigned m_weakness:16;
|
||||
unsigned m_external:1;
|
||||
unsigned m_blocked:1;
|
||||
unsigned m_external:1; // external lemma from another solver
|
||||
unsigned m_blocked:1; // blocked by CTP
|
||||
unsigned m_background:1; // background assumed fact
|
||||
|
||||
void mk_expr_core();
|
||||
void mk_cube_core();
|
||||
|
@ -163,6 +164,9 @@ public:
|
|||
void set_external(bool ext){m_external = ext;}
|
||||
bool external() { return m_external;}
|
||||
|
||||
void set_background(bool v) {m_background = v;}
|
||||
bool is_background() {return m_background;}
|
||||
|
||||
bool is_blocked() {return m_blocked;}
|
||||
void set_blocked(bool v) {m_blocked=v;}
|
||||
|
||||
|
@ -222,6 +226,7 @@ class pred_transformer {
|
|||
pred_transformer &m_pt; // parent pred_transformer
|
||||
lemma_ref_vector m_pinned_lemmas; // all created lemmas
|
||||
lemma_ref_vector m_lemmas; // active lemmas
|
||||
lemma_ref_vector m_bg_invs; // background (assumed) invariants
|
||||
unsigned m_size; // num of frames
|
||||
|
||||
bool m_sorted; // true if m_lemmas is sorted by m_lt
|
||||
|
@ -230,7 +235,8 @@ class pred_transformer {
|
|||
void sort ();
|
||||
|
||||
public:
|
||||
frames (pred_transformer &pt) : m_pt (pt), m_size(0), m_sorted (true) {}
|
||||
frames (pred_transformer &pt) : m_pt (pt),
|
||||
m_size(0), m_sorted (true) {}
|
||||
~frames() {}
|
||||
void simplify_formulas ();
|
||||
|
||||
|
@ -245,17 +251,25 @@ class pred_transformer {
|
|||
}
|
||||
}
|
||||
}
|
||||
void get_frame_geq_lemmas (unsigned level, expr_ref_vector &out) const {
|
||||
void get_frame_geq_lemmas (unsigned level, expr_ref_vector &out,
|
||||
bool with_bg = false) const {
|
||||
for (auto &lemma : m_lemmas) {
|
||||
if (lemma->level() >= level) {
|
||||
out.push_back(lemma->get_expr());
|
||||
}
|
||||
}
|
||||
if (with_bg) {
|
||||
for (auto &lemma : m_bg_invs)
|
||||
out.push_back(lemma->get_expr());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned size () const {return m_size;}
|
||||
unsigned lemma_size () const {return m_lemmas.size ();}
|
||||
void add_frame () {m_size++;}
|
||||
const lemma_ref_vector& get_bg_invs() const {return m_bg_invs;}
|
||||
unsigned size() const {return m_size;}
|
||||
unsigned lemma_size() const {return m_lemmas.size ();}
|
||||
unsigned bg_invs_size() const {return m_bg_invs.size();}
|
||||
|
||||
void add_frame() {m_size++;}
|
||||
void inherit_frames (frames &other) {
|
||||
for (auto &other_lemma : other.m_lemmas) {
|
||||
lemma_ref new_lemma = alloc(lemma, m_pt.get_ast_manager(),
|
||||
|
@ -265,6 +279,7 @@ class pred_transformer {
|
|||
add_lemma(new_lemma.get());
|
||||
}
|
||||
m_sorted = false;
|
||||
m_bg_invs.append(other.m_bg_invs);
|
||||
}
|
||||
|
||||
bool add_lemma (lemma *new_lemma);
|
||||
|
@ -418,6 +433,11 @@ class pred_transformer {
|
|||
|
||||
app_ref mk_fresh_rf_tag ();
|
||||
|
||||
// get tagged formulae of all of the background invariants for all of the
|
||||
// predecessors of the current transformer
|
||||
void get_pred_bg_invs(expr_ref_vector &out);
|
||||
const lemma_ref_vector &get_bg_invs() const {return m_frames.get_bg_invs();}
|
||||
|
||||
public:
|
||||
pred_transformer(context& ctx, manager& pm, func_decl* head);
|
||||
~pred_transformer() {}
|
||||
|
@ -448,7 +468,7 @@ public:
|
|||
}
|
||||
unsigned get_num_levels() const {return m_frames.size ();}
|
||||
expr_ref get_cover_delta(func_decl* p_orig, int level);
|
||||
void add_cover(unsigned level, expr* property);
|
||||
void add_cover(unsigned level, expr* property, bool bg = false);
|
||||
expr_ref get_reachable();
|
||||
|
||||
std::ostream& display(std::ostream& strm) const;
|
||||
|
@ -484,7 +504,7 @@ public:
|
|||
bool propagate_to_next_level(unsigned level);
|
||||
void propagate_to_infinity(unsigned level);
|
||||
/// \brief Add a lemma to the current context and all users
|
||||
bool add_lemma(expr * lemma, unsigned lvl);
|
||||
bool add_lemma(expr * e, unsigned lvl, bool bg);
|
||||
bool add_lemma(lemma* lem) {return m_frames.add_lemma(lem);}
|
||||
expr* get_reach_case_var (unsigned idx) const;
|
||||
bool has_rfs () const { return !m_reach_facts.empty () ;}
|
||||
|
@ -527,7 +547,7 @@ public:
|
|||
bool check_inductive(unsigned level, expr_ref_vector& state,
|
||||
unsigned& assumes_level, unsigned weakness = UINT_MAX);
|
||||
|
||||
expr_ref get_formulas(unsigned level) const;
|
||||
expr_ref get_formulas(unsigned level, bool bg = false) const;
|
||||
|
||||
void simplify_formulas();
|
||||
|
||||
|
@ -958,6 +978,7 @@ class context {
|
|||
bool m_simplify_formulas_pre;
|
||||
bool m_simplify_formulas_post;
|
||||
bool m_pdr_bfs;
|
||||
bool m_use_bg_invs;
|
||||
unsigned m_push_pob_max_depth;
|
||||
unsigned m_max_level;
|
||||
unsigned m_restart_initial_threshold;
|
||||
|
@ -992,7 +1013,8 @@ class context {
|
|||
|
||||
// Generate inductive property
|
||||
void get_level_property(unsigned lvl, expr_ref_vector& res,
|
||||
vector<relation_info> & rs) const;
|
||||
vector<relation_info> & rs,
|
||||
bool with_bg = false) const;
|
||||
|
||||
|
||||
// Initialization
|
||||
|
@ -1027,18 +1049,20 @@ public:
|
|||
|
||||
|
||||
const fp_params &get_params() const { return m_params; }
|
||||
bool use_native_mbp () {return m_use_native_mbp;}
|
||||
bool use_ground_pob () {return m_ground_pob;}
|
||||
bool use_instantiate () {return m_instantiate;}
|
||||
bool weak_abs() {return m_weak_abs;}
|
||||
bool use_qlemmas () {return m_use_qlemmas;}
|
||||
bool use_euf_gen() {return m_use_euf_gen;}
|
||||
bool simplify_pob() {return m_simplify_pob;}
|
||||
bool use_ctp() {return m_use_ctp;}
|
||||
bool use_inc_clause() {return m_use_inc_clause;}
|
||||
unsigned blast_term_ite_inflation() {return m_blast_term_ite_inflation;}
|
||||
bool elim_aux() {return m_elim_aux;}
|
||||
bool reach_dnf() {return m_reach_dnf;}
|
||||
bool use_eq_prop() const {return m_use_eq_prop;}
|
||||
bool use_native_mbp() const {return m_use_native_mbp;}
|
||||
bool use_ground_pob() const {return m_ground_pob;}
|
||||
bool use_instantiate() const {return m_instantiate;}
|
||||
bool weak_abs() const {return m_weak_abs;}
|
||||
bool use_qlemmas() const {return m_use_qlemmas;}
|
||||
bool use_euf_gen() const {return m_use_euf_gen;}
|
||||
bool simplify_pob() const {return m_simplify_pob;}
|
||||
bool use_ctp() const {return m_use_ctp;}
|
||||
bool use_inc_clause() const {return m_use_inc_clause;}
|
||||
unsigned blast_term_ite_inflation() const {return m_blast_term_ite_inflation;}
|
||||
bool elim_aux() const {return m_elim_aux;}
|
||||
bool reach_dnf() const {return m_reach_dnf;}
|
||||
bool use_bg_invs() const {return m_use_bg_invs;}
|
||||
|
||||
ast_manager& get_ast_manager() const {return m;}
|
||||
manager& get_manager() {return m_pm;}
|
||||
|
@ -1081,7 +1105,7 @@ public:
|
|||
unsigned get_num_levels(func_decl* p);
|
||||
|
||||
expr_ref get_cover_delta(int level, func_decl* p_orig, func_decl* p);
|
||||
void add_cover(int level, func_decl* pred, expr* property);
|
||||
void add_cover(int level, func_decl* pred, expr* property, bool bg = false);
|
||||
expr_ref get_reachable (func_decl* p);
|
||||
void add_invariant (func_decl *pred, expr* property);
|
||||
model_ref get_model();
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace{
|
|||
contains_array_op_proc(ast_manager &manager) :
|
||||
m(manager), m_array_fid(m.mk_family_id("array"))
|
||||
{}
|
||||
virtual bool operator()(expr *e) {
|
||||
bool operator()(expr *e) override {
|
||||
return is_app(e) && to_app(e)->get_family_id() == m_array_fid;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -117,11 +117,11 @@ class lemma_quantifier_generalizer : public lemma_generalizer {
|
|||
int m_offset;
|
||||
public:
|
||||
lemma_quantifier_generalizer(context &ctx, bool normalize_cube = true);
|
||||
virtual ~lemma_quantifier_generalizer() {}
|
||||
virtual void operator()(lemma_ref &lemma);
|
||||
~lemma_quantifier_generalizer() override {}
|
||||
void operator()(lemma_ref &lemma) override;
|
||||
|
||||
virtual void collect_statistics(statistics& st) const;
|
||||
virtual void reset_statistics() {m_st.reset();}
|
||||
void collect_statistics(statistics& st) const override;
|
||||
void reset_statistics() override {m_st.reset();}
|
||||
private:
|
||||
bool generalize(lemma_ref &lemma, app *term);
|
||||
|
||||
|
|
|
@ -600,7 +600,7 @@ namespace spacer {
|
|||
proof* hypothesis_reducer::reduce_core(proof* pf) {
|
||||
SASSERT(m.is_false(m.get_fact(pf)));
|
||||
|
||||
proof *res = NULL;
|
||||
proof *res = nullptr;
|
||||
|
||||
ptr_vector<proof> todo;
|
||||
todo.push_back(pf);
|
||||
|
|
|
@ -94,6 +94,7 @@ void prop_solver::add_level()
|
|||
|
||||
void prop_solver::ensure_level(unsigned lvl)
|
||||
{
|
||||
if (is_infty_level(lvl)) return;
|
||||
while (lvl >= level_cnt()) {
|
||||
add_level();
|
||||
}
|
||||
|
|
|
@ -48,7 +48,8 @@ namespace spacer {
|
|||
}
|
||||
|
||||
inline bool is_infty_level(unsigned lvl) {
|
||||
return lvl == infty_level ();
|
||||
// XXX: level is 16 bits in class pob
|
||||
return lvl >= 65535;
|
||||
}
|
||||
|
||||
inline unsigned next_level(unsigned lvl) {
|
||||
|
|
|
@ -25,6 +25,7 @@ z3_add_component(transforms
|
|||
dl_mk_array_eq_rewrite.cpp
|
||||
dl_mk_array_instantiation.cpp
|
||||
dl_mk_elim_term_ite.cpp
|
||||
dl_mk_synchronize.cpp
|
||||
COMPONENT_DEPENDENCIES
|
||||
dataflow
|
||||
hilbert
|
||||
|
|
376
src/muz/transforms/dl_mk_synchronize.cpp
Normal file
376
src/muz/transforms/dl_mk_synchronize.cpp
Normal file
|
@ -0,0 +1,376 @@
|
|||
/*++
|
||||
Copyright (c) 2017-2018 Saint-Petersburg State University
|
||||
|
||||
Module Name:
|
||||
|
||||
dl_mk_synchronize.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Rule transformer that attempts to merge recursive iterations
|
||||
relaxing the shape of the inductive invariant.
|
||||
|
||||
Author:
|
||||
|
||||
Dmitry Mordvinov (dvvrd) 2017-05-24
|
||||
Lidiia Chernigovskaia (LChernigovskaya) 2017-10-20
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include "muz/transforms/dl_mk_synchronize.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace datalog {
|
||||
|
||||
typedef mk_synchronize::item_set_vector item_set_vector;
|
||||
|
||||
mk_synchronize::mk_synchronize(context& ctx, unsigned priority):
|
||||
rule_transformer::plugin(priority, false),
|
||||
m_ctx(ctx),
|
||||
m(ctx.get_manager()),
|
||||
rm(ctx.get_rule_manager())
|
||||
{}
|
||||
|
||||
bool mk_synchronize::is_recursive(rule &r, func_decl &decl) const {
|
||||
func_decl *hdecl = r.get_head()->get_decl();
|
||||
// AG: shouldn't decl appear in the body?
|
||||
if (hdecl == &decl) return true;
|
||||
auto & strata = m_stratifier->get_strats();
|
||||
unsigned num_of_stratum = m_stratifier->get_predicate_strat(hdecl);
|
||||
return strata[num_of_stratum]->contains(&decl);
|
||||
}
|
||||
|
||||
bool mk_synchronize::has_recursive_premise(app * app) const {
|
||||
func_decl* app_decl = app->get_decl();
|
||||
if (m_deps->get_deps(app_decl).contains(app_decl)) {
|
||||
return true;
|
||||
}
|
||||
rule_stratifier::comp_vector const & strata = m_stratifier->get_strats();
|
||||
unsigned num_of_stratum = m_stratifier->get_predicate_strat(app_decl);
|
||||
return strata[num_of_stratum]->size() > 1;
|
||||
}
|
||||
|
||||
item_set_vector mk_synchronize::add_merged_decls(ptr_vector<app> & apps) {
|
||||
unsigned sz = apps.size();
|
||||
item_set_vector merged_decls;
|
||||
merged_decls.resize(sz);
|
||||
auto & strata = m_stratifier->get_strats();
|
||||
for (unsigned j = 0; j < sz; ++j) {
|
||||
unsigned nos;
|
||||
nos = m_stratifier->get_predicate_strat(apps[j]->get_decl());
|
||||
merged_decls[j] = strata[nos];
|
||||
}
|
||||
return merged_decls;
|
||||
}
|
||||
|
||||
void mk_synchronize::add_new_rel_symbols(unsigned idx,
|
||||
item_set_vector const & decls,
|
||||
ptr_vector<func_decl> & decls_buf,
|
||||
bool & was_added) {
|
||||
if (idx >= decls.size()) {
|
||||
string_buffer<> buffer;
|
||||
ptr_vector<sort> domain;
|
||||
for (auto &d : decls_buf) {
|
||||
buffer << d->get_name() << "!!";
|
||||
domain.append(d->get_arity(), d->get_domain());
|
||||
}
|
||||
|
||||
symbol new_name = symbol(buffer.c_str());
|
||||
|
||||
if (!m_cache.contains(new_name)) {
|
||||
was_added = true;
|
||||
func_decl* orig = decls_buf[0];
|
||||
func_decl* product_pred = m_ctx.mk_fresh_head_predicate(new_name,
|
||||
symbol::null, domain.size(), domain.c_ptr(), orig);
|
||||
m_cache.insert(new_name, product_pred);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// -- compute Cartesian product of decls, and create a new
|
||||
// -- predicate for each element of the product
|
||||
for (auto &p : *decls[idx]) {
|
||||
decls_buf[idx] = p;
|
||||
add_new_rel_symbols(idx + 1, decls, decls_buf, was_added);
|
||||
}
|
||||
}
|
||||
|
||||
void mk_synchronize::replace_applications(rule & r, rule_set & rules,
|
||||
ptr_vector<app> & apps) {
|
||||
app_ref replacing = product_application(apps);
|
||||
|
||||
ptr_vector<app> new_tail;
|
||||
svector<bool> new_tail_neg;
|
||||
unsigned n = r.get_tail_size() - apps.size() + 1;
|
||||
unsigned tail_idx = 0;
|
||||
new_tail.resize(n);
|
||||
new_tail_neg.resize(n);
|
||||
new_tail[0] = replacing;
|
||||
new_tail_neg[0] = false;
|
||||
|
||||
for (unsigned i = 0; i < r.get_positive_tail_size(); ++i) {
|
||||
app* tail = r.get_tail(i);
|
||||
if (!apps.contains(tail)) {
|
||||
++tail_idx;
|
||||
new_tail[tail_idx] = tail;
|
||||
new_tail_neg[tail_idx] = false;
|
||||
}
|
||||
}
|
||||
for (unsigned i = r.get_positive_tail_size(); i < r.get_uninterpreted_tail_size(); ++i) {
|
||||
++tail_idx;
|
||||
new_tail[tail_idx] = r.get_tail(i);
|
||||
new_tail_neg[tail_idx] = true;
|
||||
}
|
||||
for (unsigned i = r.get_uninterpreted_tail_size(); i < r.get_tail_size(); ++i) {
|
||||
++tail_idx;
|
||||
new_tail[tail_idx] = r.get_tail(i);
|
||||
new_tail_neg[tail_idx] = false;
|
||||
}
|
||||
|
||||
rule_ref new_rule(rm);
|
||||
new_rule = rm.mk(r.get_head(), tail_idx + 1,
|
||||
new_tail.c_ptr(), new_tail_neg.c_ptr(), symbol::null, false);
|
||||
rules.replace_rule(&r, new_rule.get());
|
||||
}
|
||||
|
||||
rule_ref mk_synchronize::rename_bound_vars_in_rule(rule * r,
|
||||
unsigned & var_idx) {
|
||||
// AG: shift all variables in a rule so that lowest var index is var_idx?
|
||||
// AG: update var_idx in the process?
|
||||
ptr_vector<sort> sorts;
|
||||
r->get_vars(m, sorts);
|
||||
expr_ref_vector revsub(m);
|
||||
revsub.resize(sorts.size());
|
||||
for (unsigned i = 0; i < sorts.size(); ++i) {
|
||||
if (sorts[i]) {
|
||||
revsub[i] = m.mk_var(var_idx++, sorts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
rule_ref new_rule(rm);
|
||||
new_rule = rm.mk(r);
|
||||
rm.substitute(new_rule, revsub.size(), revsub.c_ptr());
|
||||
return new_rule;
|
||||
}
|
||||
|
||||
vector<rule_ref_vector> mk_synchronize::rename_bound_vars(item_set_vector const & heads,
|
||||
rule_set & rules) {
|
||||
// AG: is every item_set in heads corresponds to rules that are merged?
|
||||
// AG: why are bound variables renamed in the first place?
|
||||
// AG: the data structure seems too complex
|
||||
vector<rule_ref_vector> result;
|
||||
unsigned var_idx = 0;
|
||||
for (auto item : heads) {
|
||||
rule_ref_vector dst_vector(rm);
|
||||
for (auto *head : *item) {
|
||||
for (auto *r : rules.get_predicate_rules(head)) {
|
||||
rule_ref new_rule = rename_bound_vars_in_rule(r, var_idx);
|
||||
dst_vector.push_back(new_rule.get());
|
||||
}
|
||||
}
|
||||
result.push_back(dst_vector);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void mk_synchronize::add_rec_tail(vector< ptr_vector<app> > & recursive_calls,
|
||||
app_ref_vector & new_tail,
|
||||
svector<bool> & new_tail_neg,
|
||||
unsigned & tail_idx) {
|
||||
unsigned max_sz = 0;
|
||||
for (auto &rc : recursive_calls)
|
||||
max_sz= std::max(rc.size(), max_sz);
|
||||
|
||||
unsigned n = recursive_calls.size();
|
||||
ptr_vector<app> merged_recursive_calls;
|
||||
|
||||
for (unsigned j = 0; j < max_sz; ++j) {
|
||||
merged_recursive_calls.reset();
|
||||
merged_recursive_calls.resize(n);
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
unsigned sz = recursive_calls[i].size();
|
||||
merged_recursive_calls[i] =
|
||||
j < sz ? recursive_calls[i][j] : recursive_calls[i][sz - 1];
|
||||
}
|
||||
++tail_idx;
|
||||
new_tail[tail_idx] = product_application(merged_recursive_calls);
|
||||
new_tail_neg[tail_idx] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void mk_synchronize::add_non_rec_tail(rule & r, app_ref_vector & new_tail,
|
||||
svector<bool> & new_tail_neg,
|
||||
unsigned & tail_idx) {
|
||||
for (unsigned i = 0, sz = r.get_positive_tail_size(); i < sz; ++i) {
|
||||
app* tail = r.get_tail(i);
|
||||
if (!is_recursive(r, *tail)) {
|
||||
++tail_idx;
|
||||
new_tail[tail_idx] = tail;
|
||||
new_tail_neg[tail_idx] = false;
|
||||
}
|
||||
}
|
||||
for (unsigned i = r.get_positive_tail_size(),
|
||||
sz = r.get_uninterpreted_tail_size() ; i < sz; ++i) {
|
||||
++tail_idx;
|
||||
new_tail[tail_idx] = r.get_tail(i);
|
||||
new_tail_neg[tail_idx] = true;
|
||||
}
|
||||
for (unsigned i = r.get_uninterpreted_tail_size(),
|
||||
sz = r.get_tail_size(); i < sz; ++i) {
|
||||
++tail_idx;
|
||||
new_tail[tail_idx] = r.get_tail(i);
|
||||
new_tail_neg[tail_idx] = r.is_neg_tail(i);
|
||||
}
|
||||
}
|
||||
|
||||
app_ref mk_synchronize::product_application(ptr_vector<app> const &apps) {
|
||||
unsigned args_num = 0;
|
||||
string_buffer<> buffer;
|
||||
|
||||
// AG: factor out into mk_name
|
||||
for (auto *app : apps) {
|
||||
buffer << app->get_decl()->get_name() << "!!";
|
||||
args_num += app->get_num_args();
|
||||
}
|
||||
|
||||
symbol name = symbol(buffer.c_str());
|
||||
SASSERT(m_cache.contains(name));
|
||||
func_decl * pred = m_cache[name];
|
||||
|
||||
ptr_vector<expr> args;
|
||||
args.resize(args_num);
|
||||
unsigned idx = 0;
|
||||
for (auto *a : apps) {
|
||||
for (unsigned i = 0, sz = a->get_num_args(); i < sz; ++i, ++idx)
|
||||
args[idx] = a->get_arg(i);
|
||||
}
|
||||
|
||||
return app_ref(m.mk_app(pred, args_num, args.c_ptr()), m);
|
||||
}
|
||||
|
||||
rule_ref mk_synchronize::product_rule(rule_ref_vector const & rules) {
|
||||
unsigned n = rules.size();
|
||||
|
||||
string_buffer<> buffer;
|
||||
bool first_rule = true;
|
||||
for (auto it = rules.begin(); it != rules.end(); ++it, first_rule = false) {
|
||||
if (!first_rule) {
|
||||
buffer << "+";
|
||||
}
|
||||
buffer << (*it)->name();
|
||||
}
|
||||
|
||||
ptr_vector<app> heads;
|
||||
heads.resize(n);
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
heads[i] = rules[i]->get_head();
|
||||
}
|
||||
app_ref product_head = product_application(heads);
|
||||
unsigned product_tail_length = 0;
|
||||
bool has_recursion = false;
|
||||
vector< ptr_vector<app> > recursive_calls;
|
||||
recursive_calls.resize(n);
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
rule& rule = *rules[i];
|
||||
product_tail_length += rule.get_tail_size();
|
||||
for (unsigned j = 0; j < rule.get_positive_tail_size(); ++j) {
|
||||
app* tail = rule.get_tail(j);
|
||||
if (is_recursive(rule, *tail)) {
|
||||
has_recursion = true;
|
||||
recursive_calls[i].push_back(tail);
|
||||
}
|
||||
}
|
||||
if (recursive_calls[i].empty()) {
|
||||
recursive_calls[i].push_back(rule.get_head());
|
||||
}
|
||||
}
|
||||
|
||||
app_ref_vector new_tail(m);
|
||||
svector<bool> new_tail_neg;
|
||||
new_tail.resize(product_tail_length);
|
||||
new_tail_neg.resize(product_tail_length);
|
||||
unsigned tail_idx = -1;
|
||||
if (has_recursion) {
|
||||
add_rec_tail(recursive_calls, new_tail, new_tail_neg, tail_idx);
|
||||
}
|
||||
|
||||
for (rule_vector::const_iterator it = rules.begin(); it != rules.end(); ++it) {
|
||||
rule& rule = **it;
|
||||
add_non_rec_tail(rule, new_tail, new_tail_neg, tail_idx);
|
||||
}
|
||||
|
||||
rule_ref new_rule(rm);
|
||||
new_rule = rm.mk(product_head, tail_idx + 1,
|
||||
new_tail.c_ptr(), new_tail_neg.c_ptr(), symbol(buffer.c_str()), false);
|
||||
rm.fix_unbound_vars(new_rule, false);
|
||||
return new_rule;
|
||||
}
|
||||
|
||||
void mk_synchronize::merge_rules(unsigned idx, rule_ref_vector & buf,
|
||||
vector<rule_ref_vector> const & merged_rules,
|
||||
rule_set & all_rules) {
|
||||
if (idx >= merged_rules.size()) {
|
||||
rule_ref product = product_rule(buf);
|
||||
all_rules.add_rule(product.get());
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto *r : merged_rules[idx]) {
|
||||
buf[idx] = r;
|
||||
merge_rules(idx + 1, buf, merged_rules, all_rules);
|
||||
}
|
||||
}
|
||||
|
||||
void mk_synchronize::merge_applications(rule & r, rule_set & rules) {
|
||||
ptr_vector<app> non_recursive_preds;
|
||||
obj_hashtable<app> apps;
|
||||
for (unsigned i = 0; i < r.get_positive_tail_size(); ++i) {
|
||||
app* t = r.get_tail(i);
|
||||
if (!is_recursive(r, *t) && has_recursive_premise(t)) {
|
||||
apps.insert(t);
|
||||
}
|
||||
}
|
||||
if (apps.size() < 2) return;
|
||||
for (auto *a : apps) non_recursive_preds.push_back(a);
|
||||
|
||||
item_set_vector merged_decls = add_merged_decls(non_recursive_preds);
|
||||
|
||||
unsigned n = non_recursive_preds.size();
|
||||
ptr_vector<func_decl> decls_buf;
|
||||
decls_buf.resize(n);
|
||||
bool was_added = false;
|
||||
add_new_rel_symbols(0, merged_decls, decls_buf, was_added);
|
||||
if (was_added){
|
||||
rule_ref_vector rules_buf(rm);
|
||||
rules_buf.resize(n);
|
||||
vector<rule_ref_vector> renamed_rules = rename_bound_vars(merged_decls, rules);
|
||||
merge_rules(0, rules_buf, renamed_rules, rules);
|
||||
}
|
||||
|
||||
replace_applications(r, rules, non_recursive_preds);
|
||||
m_deps->populate(rules);
|
||||
m_stratifier = alloc(rule_stratifier, *m_deps);
|
||||
}
|
||||
|
||||
rule_set * mk_synchronize::operator()(rule_set const & source) {
|
||||
rule_set* rules = alloc(rule_set, m_ctx);
|
||||
rules->inherit_predicates(source);
|
||||
|
||||
for (auto *r : source) { rules->add_rule(r); }
|
||||
|
||||
m_deps = alloc(rule_dependencies, m_ctx);
|
||||
m_deps->populate(*rules);
|
||||
m_stratifier = alloc(rule_stratifier, *m_deps);
|
||||
|
||||
unsigned current_rule = 0;
|
||||
while (current_rule < rules->get_num_rules()) {
|
||||
rule *r = rules->get_rule(current_rule);
|
||||
merge_applications(*r, *rules);
|
||||
++current_rule;
|
||||
}
|
||||
|
||||
return rules;
|
||||
}
|
||||
|
||||
};
|
134
src/muz/transforms/dl_mk_synchronize.h
Normal file
134
src/muz/transforms/dl_mk_synchronize.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*++
|
||||
Copyright (c) 2017-2018 Saint-Petersburg State University
|
||||
|
||||
Module Name:
|
||||
|
||||
dl_mk_synchronize.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Rule transformer that attempts to merge recursive iterations
|
||||
relaxing the shape of the inductive invariant.
|
||||
|
||||
Example:
|
||||
|
||||
Q(z) :- A(x), B(y), phi1(x,y,z).
|
||||
A(x) :- A(x'), phi2(x,x').
|
||||
A(x) :- phi3(x).
|
||||
B(y) :- C(y'), phi4(y,y').
|
||||
C(y) :- B(y'), phi5(y,y').
|
||||
B(y) :- phi6(y).
|
||||
|
||||
Transformed clauses:
|
||||
|
||||
Q(z) :- AB(x,y), phi1(x,y,z).
|
||||
AB(x,y) :- AC(x',y'), phi2(x,x'), phi4(y,y').
|
||||
AC(x,y) :- AB(x',y'), phi2(x,x'), phi5(y,y').
|
||||
AB(x,y) :- AC(x, y'), phi3(x), phi4(y,y').
|
||||
AC(x,y) :- AB(x, y'), phi3(x), phi5(y,y').
|
||||
AB(x,y) :- AB(x',y), phi2(x,x'), phi6(y).
|
||||
AB(x,y) :- phi3(x), phi6(y).
|
||||
|
||||
Author:
|
||||
|
||||
Dmitry Mordvinov (dvvrd) 2017-05-24
|
||||
Lidiia Chernigovskaia (LChernigovskaya) 2017-10-20
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef DL_MK_SYNCHRONIZE_H_
|
||||
#define DL_MK_SYNCHRONIZE_H_
|
||||
|
||||
#include"muz/base/dl_context.h"
|
||||
#include"muz/base/dl_rule_set.h"
|
||||
#include"util/uint_set.h"
|
||||
#include"muz/base/dl_rule_transformer.h"
|
||||
#include"muz/transforms/dl_mk_rule_inliner.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
/**
|
||||
\brief Implements a synchronous product transformation.
|
||||
*/
|
||||
class mk_synchronize : public rule_transformer::plugin {
|
||||
public:
|
||||
typedef ptr_vector<rule_stratifier::item_set> item_set_vector;
|
||||
private:
|
||||
context& m_ctx;
|
||||
ast_manager& m;
|
||||
rule_manager& rm;
|
||||
|
||||
scoped_ptr<rule_dependencies> m_deps;
|
||||
scoped_ptr<rule_stratifier> m_stratifier;
|
||||
|
||||
// symbol table that maps new predicate names to corresponding
|
||||
// func_decl
|
||||
map<symbol, func_decl*, symbol_hash_proc, symbol_eq_proc> m_cache;
|
||||
|
||||
/// returns true if decl is recursive in the given rule
|
||||
/// requires that decl appears in the tail of r
|
||||
bool is_recursive(rule &r, func_decl &decl) const;
|
||||
bool is_recursive(rule &r, expr &e) const {
|
||||
SASSERT(is_app(&e));
|
||||
return is_app(&e) && is_recursive(r, *to_app(&e)->get_decl());
|
||||
}
|
||||
|
||||
/// returns true if the top-level predicate of app is recursive
|
||||
bool has_recursive_premise(app * app) const;
|
||||
|
||||
item_set_vector add_merged_decls(ptr_vector<app> & apps);
|
||||
|
||||
/**
|
||||
Compute Cartesian product of decls and create a new
|
||||
predicate for each element. For example, if decls is
|
||||
|
||||
( (a, b), (c, d) ) )
|
||||
|
||||
create new predicates: a!!c, a!!d, b!!c, and b!!d
|
||||
*/
|
||||
void add_new_rel_symbols(unsigned idx, item_set_vector const & decls,
|
||||
ptr_vector<func_decl> & buf, bool & was_added);
|
||||
|
||||
/**
|
||||
Convert vector of predicate apps into a single app. For example,
|
||||
(Foo a) (Bar b) becomes (Foo!!Bar a b)
|
||||
*/
|
||||
app_ref product_application(ptr_vector<app> const & apps);
|
||||
|
||||
/**
|
||||
Replace a given rule by a rule in which conjunction of
|
||||
predicates is replaced by a single product predicate
|
||||
*/
|
||||
void replace_applications(rule & r, rule_set & rules,
|
||||
ptr_vector<app> & apps);
|
||||
|
||||
rule_ref rename_bound_vars_in_rule(rule * r, unsigned & var_idx);
|
||||
vector<rule_ref_vector> rename_bound_vars(item_set_vector const & heads,
|
||||
rule_set & rules);
|
||||
|
||||
void add_rec_tail(vector< ptr_vector<app> > & recursive_calls,
|
||||
app_ref_vector & new_tail,
|
||||
svector<bool> & new_tail_neg, unsigned & tail_idx);
|
||||
void add_non_rec_tail(rule & r, app_ref_vector & new_tail,
|
||||
svector<bool> & new_tail_neg,
|
||||
unsigned & tail_idx);
|
||||
|
||||
rule_ref product_rule(rule_ref_vector const & rules);
|
||||
|
||||
void merge_rules(unsigned idx, rule_ref_vector & buf,
|
||||
vector<rule_ref_vector> const & merged_rules, rule_set & all_rules);
|
||||
void merge_applications(rule & r, rule_set & rules);
|
||||
|
||||
public:
|
||||
/**
|
||||
\brief Create synchronous product transformer.
|
||||
*/
|
||||
mk_synchronize(context & ctx, unsigned priority = 22500);
|
||||
|
||||
rule_set * operator()(rule_set const & source) override;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* DL_MK_SYNCHRONIZE_H_ */
|
|
@ -144,7 +144,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
virtual ~maxres() {}
|
||||
~maxres() override {}
|
||||
|
||||
bool is_literal(expr* l) {
|
||||
return
|
||||
|
@ -332,7 +332,7 @@ public:
|
|||
}
|
||||
|
||||
|
||||
virtual lbool operator()() {
|
||||
lbool operator()() override {
|
||||
m_defs.reset();
|
||||
switch(m_st) {
|
||||
case s_primal:
|
||||
|
@ -343,7 +343,7 @@ public:
|
|||
return l_undef;
|
||||
}
|
||||
|
||||
virtual void collect_statistics(statistics& st) const {
|
||||
void collect_statistics(statistics& st) const override {
|
||||
st.update("maxres-cores", m_stats.m_num_cores);
|
||||
st.update("maxres-correction-sets", m_stats.m_num_cs);
|
||||
}
|
||||
|
@ -781,7 +781,7 @@ public:
|
|||
TRACE("opt", tout << "after remove: " << asms << "\n";);
|
||||
}
|
||||
|
||||
virtual void updt_params(params_ref& _p) {
|
||||
void updt_params(params_ref& _p) override {
|
||||
maxsmt_solver_base::updt_params(_p);
|
||||
opt_params p(_p);
|
||||
m_hill_climb = p.maxres_hill_climb();
|
||||
|
@ -816,7 +816,7 @@ public:
|
|||
return l_true;
|
||||
}
|
||||
|
||||
virtual void commit_assignment() {
|
||||
void commit_assignment() override {
|
||||
if (m_found_feasible_optimum) {
|
||||
TRACE("opt", tout << "Committing feasible solution\n" << m_defs << " " << m_asms;);
|
||||
s().assert_expr(m_defs);
|
||||
|
|
|
@ -56,33 +56,33 @@ public:
|
|||
m_opt(opt)
|
||||
{}
|
||||
|
||||
virtual ~assert_soft_cmd() {
|
||||
~assert_soft_cmd() override {
|
||||
}
|
||||
|
||||
virtual void reset(cmd_context & ctx) {
|
||||
void reset(cmd_context & ctx) override {
|
||||
m_idx = 0;
|
||||
m_formula = nullptr;
|
||||
}
|
||||
|
||||
virtual char const * get_usage() const { return "<formula> [:weight <rational-weight>] [:id <symbol>]"; }
|
||||
virtual char const * get_main_descr() const { return "assert soft constraint with optional weight and identifier"; }
|
||||
char const * get_usage() const override { return "<formula> [:weight <rational-weight>] [:id <symbol>]"; }
|
||||
char const * get_main_descr() const override { return "assert soft constraint with optional weight and identifier"; }
|
||||
|
||||
// command invocation
|
||||
virtual void prepare(cmd_context & ctx) {
|
||||
void prepare(cmd_context & ctx) override {
|
||||
reset(ctx);
|
||||
}
|
||||
|
||||
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const {
|
||||
cmd_arg_kind next_arg_kind(cmd_context & ctx) const override {
|
||||
if (m_idx == 0) return CPK_EXPR;
|
||||
return parametric_cmd::next_arg_kind(ctx);
|
||||
}
|
||||
|
||||
virtual void init_pdescrs(cmd_context & ctx, param_descrs & p) {
|
||||
void init_pdescrs(cmd_context & ctx, param_descrs & p) override {
|
||||
p.insert("weight", CPK_NUMERAL, "(default: 1) penalty of not satisfying constraint.");
|
||||
p.insert("id", CPK_SYMBOL, "(default: null) partition identifier for soft constraints.");
|
||||
}
|
||||
|
||||
virtual void set_next_arg(cmd_context & ctx, expr * t) {
|
||||
void set_next_arg(cmd_context & ctx, expr * t) override {
|
||||
SASSERT(m_idx == 0);
|
||||
if (!ctx.m().is_bool(t)) {
|
||||
throw cmd_exception("Invalid type for expression. Expected Boolean type.");
|
||||
|
@ -91,11 +91,11 @@ public:
|
|||
++m_idx;
|
||||
}
|
||||
|
||||
virtual void failure_cleanup(cmd_context & ctx) {
|
||||
void failure_cleanup(cmd_context & ctx) override {
|
||||
reset(ctx);
|
||||
}
|
||||
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
void execute(cmd_context & ctx) override {
|
||||
if (!m_formula) {
|
||||
throw cmd_exception("assert-soft requires a formulas as argument.");
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ public:
|
|||
reset(ctx);
|
||||
}
|
||||
|
||||
virtual void finalize(cmd_context & ctx) {
|
||||
void finalize(cmd_context & ctx) override {
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -123,14 +123,14 @@ public:
|
|||
m_opt(opt)
|
||||
{}
|
||||
|
||||
virtual void reset(cmd_context & ctx) { }
|
||||
virtual char const * get_usage() const { return "<term>"; }
|
||||
virtual char const * get_descr(cmd_context & ctx) const { return "check sat modulo objective function";}
|
||||
virtual unsigned get_arity() const { return 1; }
|
||||
virtual void prepare(cmd_context & ctx) {}
|
||||
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_EXPR; }
|
||||
void reset(cmd_context & ctx) override { }
|
||||
char const * get_usage() const override { return "<term>"; }
|
||||
char const * get_descr(cmd_context & ctx) const override { return "check sat modulo objective function";}
|
||||
unsigned get_arity() const override { return 1; }
|
||||
void prepare(cmd_context & ctx) override {}
|
||||
cmd_arg_kind next_arg_kind(cmd_context & ctx) const override { return CPK_EXPR; }
|
||||
|
||||
virtual void set_next_arg(cmd_context & ctx, expr * t) {
|
||||
void set_next_arg(cmd_context & ctx, expr * t) override {
|
||||
if (!is_app(t)) {
|
||||
throw cmd_exception("malformed objective term: it cannot be a quantifier or bound variable");
|
||||
}
|
||||
|
@ -138,11 +138,11 @@ public:
|
|||
ctx.print_success();
|
||||
}
|
||||
|
||||
virtual void failure_cleanup(cmd_context & ctx) {
|
||||
void failure_cleanup(cmd_context & ctx) override {
|
||||
reset(ctx);
|
||||
}
|
||||
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
void execute(cmd_context & ctx) override {
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -154,18 +154,18 @@ public:
|
|||
m_opt(opt)
|
||||
{}
|
||||
|
||||
virtual void reset(cmd_context & ctx) { }
|
||||
virtual char const * get_usage() const { return "(get-objectives)"; }
|
||||
virtual char const * get_descr(cmd_context & ctx) const { return "retrieve the objective values (after optimization)"; }
|
||||
virtual unsigned get_arity() const { return 0; }
|
||||
virtual void prepare(cmd_context & ctx) {}
|
||||
void reset(cmd_context & ctx) override { }
|
||||
char const * get_usage() const override { return "(get-objectives)"; }
|
||||
char const * get_descr(cmd_context & ctx) const override { return "retrieve the objective values (after optimization)"; }
|
||||
unsigned get_arity() const override { return 0; }
|
||||
void prepare(cmd_context & ctx) override {}
|
||||
|
||||
|
||||
virtual void failure_cleanup(cmd_context & ctx) {
|
||||
void failure_cleanup(cmd_context & ctx) override {
|
||||
reset(ctx);
|
||||
}
|
||||
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
void execute(cmd_context & ctx) override {
|
||||
if (!ctx.ignore_check()) {
|
||||
get_opt(ctx, m_opt).display_assignment(ctx.regular_stream());
|
||||
}
|
||||
|
|
|
@ -79,13 +79,13 @@ namespace opt {
|
|||
m_hard.push_back(hard);
|
||||
}
|
||||
|
||||
bool context::scoped_state::set(ptr_vector<expr> & hard) {
|
||||
bool context::scoped_state::set(expr_ref_vector const & hard) {
|
||||
bool eq = hard.size() == m_hard.size();
|
||||
for (unsigned i = 0; eq && i < hard.size(); ++i) {
|
||||
eq = hard[i] == m_hard[i].get();
|
||||
eq = hard.get(i) == m_hard.get(i);
|
||||
}
|
||||
m_hard.reset();
|
||||
m_hard.append(hard.size(), hard.c_ptr());
|
||||
m_hard.append(hard);
|
||||
return !eq;
|
||||
}
|
||||
|
||||
|
@ -130,6 +130,7 @@ namespace opt {
|
|||
m_fm(alloc(generic_model_converter, m, "opt")),
|
||||
m_model_fixed(),
|
||||
m_objective_refs(m),
|
||||
m_core(m),
|
||||
m_enable_sat(false),
|
||||
m_is_clausal(false),
|
||||
m_pp_neat(false),
|
||||
|
@ -173,11 +174,10 @@ namespace opt {
|
|||
}
|
||||
|
||||
void context::get_unsat_core(expr_ref_vector & r) {
|
||||
throw default_exception("Unsat cores are not supported with optimization");
|
||||
r.append(m_core);
|
||||
}
|
||||
|
||||
|
||||
void context::set_hard_constraints(ptr_vector<expr>& fmls) {
|
||||
void context::set_hard_constraints(expr_ref_vector const& fmls) {
|
||||
if (m_scoped_state.set(fmls)) {
|
||||
clear_state();
|
||||
}
|
||||
|
@ -253,7 +253,7 @@ namespace opt {
|
|||
m_hard_constraints.append(s.m_hard);
|
||||
}
|
||||
|
||||
lbool context::optimize() {
|
||||
lbool context::optimize(expr_ref_vector const& asms) {
|
||||
if (m_pareto) {
|
||||
return execute_pareto();
|
||||
}
|
||||
|
@ -263,7 +263,10 @@ namespace opt {
|
|||
clear_state();
|
||||
init_solver();
|
||||
import_scoped_state();
|
||||
normalize();
|
||||
normalize(asms);
|
||||
if (m_hard_constraints.size() == 1 && m.is_false(m_hard_constraints.get(0))) {
|
||||
return l_false;
|
||||
}
|
||||
internalize();
|
||||
update_solver();
|
||||
if (contains_quantifiers()) {
|
||||
|
@ -281,7 +284,7 @@ namespace opt {
|
|||
symbol pri = optp.priority();
|
||||
|
||||
IF_VERBOSE(1, verbose_stream() << "(optimize:check-sat)\n");
|
||||
lbool is_sat = s.check_sat(0,0);
|
||||
lbool is_sat = s.check_sat(asms.size(),asms.c_ptr());
|
||||
TRACE("opt", s.display(tout << "initial search result: " << is_sat << "\n"););
|
||||
if (is_sat != l_false) {
|
||||
s.get_model(m_model);
|
||||
|
@ -289,7 +292,10 @@ namespace opt {
|
|||
model_updated(m_model.get());
|
||||
}
|
||||
if (is_sat != l_true) {
|
||||
TRACE("opt", tout << m_hard_constraints << "\n";);
|
||||
TRACE("opt", tout << m_hard_constraints << " " << asms << "\n";);
|
||||
if (!asms.empty()) {
|
||||
s.get_unsat_core(m_core);
|
||||
}
|
||||
return is_sat;
|
||||
}
|
||||
IF_VERBOSE(1, verbose_stream() << "(optimize:sat)\n");
|
||||
|
@ -479,7 +485,6 @@ namespace opt {
|
|||
return r;
|
||||
}
|
||||
|
||||
|
||||
expr_ref context::mk_le(unsigned i, model_ref& mdl) {
|
||||
objective const& obj = m_objectives[i];
|
||||
return mk_cmp(false, mdl, obj);
|
||||
|
@ -489,8 +494,7 @@ namespace opt {
|
|||
objective const& obj = m_objectives[i];
|
||||
return mk_cmp(true, mdl, obj);
|
||||
}
|
||||
|
||||
|
||||
|
||||
expr_ref context::mk_gt(unsigned i, model_ref& mdl) {
|
||||
expr_ref result = mk_le(i, mdl);
|
||||
result = mk_not(m, result);
|
||||
|
@ -751,22 +755,25 @@ namespace opt {
|
|||
return m_arith.is_numeral(e, n) || m_bv.is_numeral(e, n, sz);
|
||||
}
|
||||
|
||||
void context::normalize() {
|
||||
void context::normalize(expr_ref_vector const& asms) {
|
||||
expr_ref_vector fmls(m);
|
||||
to_fmls(fmls);
|
||||
simplify_fmls(fmls);
|
||||
simplify_fmls(fmls, asms);
|
||||
from_fmls(fmls);
|
||||
}
|
||||
|
||||
void context::simplify_fmls(expr_ref_vector& fmls) {
|
||||
void context::simplify_fmls(expr_ref_vector& fmls, expr_ref_vector const& asms) {
|
||||
if (m_is_clausal) {
|
||||
return;
|
||||
}
|
||||
|
||||
goal_ref g(alloc(goal, m, true, false));
|
||||
goal_ref g(alloc(goal, m, true, !asms.empty()));
|
||||
for (expr* fml : fmls) {
|
||||
g->assert_expr(fml);
|
||||
}
|
||||
for (expr * a : asms) {
|
||||
g->assert_expr(a, a);
|
||||
}
|
||||
tactic_ref tac0 =
|
||||
and_then(mk_simplify_tactic(m, m_params),
|
||||
mk_propagate_values_tactic(m),
|
||||
|
@ -788,6 +795,7 @@ namespace opt {
|
|||
set_simplify(tac0.get());
|
||||
}
|
||||
goal_ref_buffer result;
|
||||
TRACE("opt", g->display(tout););
|
||||
(*m_simplify)(g, result);
|
||||
SASSERT(result.size() == 1);
|
||||
goal* r = result[0];
|
||||
|
@ -795,8 +803,27 @@ namespace opt {
|
|||
fmls.reset();
|
||||
expr_ref tmp(m);
|
||||
for (unsigned i = 0; i < r->size(); ++i) {
|
||||
fmls.push_back(r->form(i));
|
||||
if (asms.empty()) {
|
||||
fmls.push_back(r->form(i));
|
||||
continue;
|
||||
}
|
||||
|
||||
ptr_vector<expr> deps;
|
||||
expr_dependency_ref core(r->dep(i), m);
|
||||
m.linearize(core, deps);
|
||||
if (!deps.empty()) {
|
||||
fmls.push_back(m.mk_implies(m.mk_and(deps.size(), deps.c_ptr()), r->form(i)));
|
||||
}
|
||||
else {
|
||||
fmls.push_back(r->form(i));
|
||||
}
|
||||
}
|
||||
if (r->inconsistent()) {
|
||||
ptr_vector<expr> core_elems;
|
||||
expr_dependency_ref core(r->dep(0), m);
|
||||
m.linearize(core, core_elems);
|
||||
m_core.append(core_elems.size(), core_elems.c_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
bool context::is_maximize(expr* fml, app_ref& term, expr_ref& orig_term, unsigned& index) {
|
||||
|
@ -1084,11 +1111,7 @@ namespace opt {
|
|||
}
|
||||
term = m_arith.mk_add(args.size(), args.c_ptr());
|
||||
}
|
||||
else if (m_arith.is_arith_expr(term) && !is_mul_const(term)) {
|
||||
TRACE("opt", tout << "Purifying " << term << "\n";);
|
||||
term = purify(fm, term);
|
||||
}
|
||||
else if (m.is_ite(term)) {
|
||||
else if (m.is_ite(term) || !is_mul_const(term)) {
|
||||
TRACE("opt", tout << "Purifying " << term << "\n";);
|
||||
term = purify(fm, term);
|
||||
}
|
||||
|
@ -1399,6 +1422,7 @@ namespace opt {
|
|||
m_box_index = UINT_MAX;
|
||||
m_model.reset();
|
||||
m_model_fixed.reset();
|
||||
m_core.reset();
|
||||
}
|
||||
|
||||
void context::set_pareto(pareto_base* p) {
|
||||
|
|
|
@ -133,7 +133,7 @@ namespace opt {
|
|||
void push();
|
||||
void pop();
|
||||
void add(expr* hard);
|
||||
bool set(ptr_vector<expr> & hard);
|
||||
bool set(expr_ref_vector const& hard);
|
||||
unsigned add(expr* soft, rational const& weight, symbol const& id);
|
||||
unsigned add(app* obj, bool is_max);
|
||||
unsigned get_index(symbol const& id) { return m_indices[id]; }
|
||||
|
@ -164,6 +164,7 @@ namespace opt {
|
|||
obj_map<func_decl, unsigned> m_objective_fns;
|
||||
obj_map<func_decl, expr*> m_objective_orig;
|
||||
func_decl_ref_vector m_objective_refs;
|
||||
expr_ref_vector m_core;
|
||||
tactic_ref m_simplify;
|
||||
bool m_enable_sat;
|
||||
bool m_enable_sls;
|
||||
|
@ -186,8 +187,8 @@ namespace opt {
|
|||
void push() override;
|
||||
void pop(unsigned n) override;
|
||||
bool empty() override { return m_scoped_state.m_objectives.empty(); }
|
||||
void set_hard_constraints(ptr_vector<expr> & hard) override;
|
||||
lbool optimize() override;
|
||||
void set_hard_constraints(expr_ref_vector const& hard) override;
|
||||
lbool optimize(expr_ref_vector const& asms) override;
|
||||
void set_model(model_ref& _m) override { m_model = _m; }
|
||||
void get_model_core(model_ref& _m) override;
|
||||
void get_box_model(model_ref& _m, unsigned index) override;
|
||||
|
@ -254,7 +255,7 @@ namespace opt {
|
|||
|
||||
void reset_maxsmts();
|
||||
void import_scoped_state();
|
||||
void normalize();
|
||||
void normalize(expr_ref_vector const& asms);
|
||||
void internalize();
|
||||
bool is_maximize(expr* fml, app_ref& term, expr_ref& orig_term, unsigned& index);
|
||||
bool is_minimize(expr* fml, app_ref& term, expr_ref& orig_term, unsigned& index);
|
||||
|
@ -270,7 +271,7 @@ namespace opt {
|
|||
expr* mk_objective_fn(unsigned index, objective_t ty, unsigned sz, expr*const* args);
|
||||
void to_fmls(expr_ref_vector& fmls);
|
||||
void from_fmls(expr_ref_vector const& fmls);
|
||||
void simplify_fmls(expr_ref_vector& fmls);
|
||||
void simplify_fmls(expr_ref_vector& fmls, expr_ref_vector const& asms);
|
||||
void mk_atomic(expr_ref_vector& terms);
|
||||
|
||||
void update_lower() { update_bound(true); }
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace opt {
|
|||
fmls.push_back(mk_or(gt));
|
||||
fml = mk_and(fmls);
|
||||
IF_VERBOSE(10, verbose_stream() << "dominates: " << fml << "\n";);
|
||||
TRACE("opt", tout << fml << "\n"; model_smt2_pp(tout, m, *m_model, 0););
|
||||
TRACE("opt", model_smt2_pp(tout << fml << "\n", m, *m_model, 0););
|
||||
m_solver->assert_expr(fml);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,9 +39,9 @@ namespace opt {
|
|||
sortmax(maxsat_context& c, weights_t& ws, expr_ref_vector const& soft):
|
||||
maxsmt_solver_base(c, ws, soft), m_sort(*this), m_trail(m), m_fresh(m) {}
|
||||
|
||||
virtual ~sortmax() {}
|
||||
~sortmax() override {}
|
||||
|
||||
lbool operator()() {
|
||||
lbool operator()() override {
|
||||
obj_map<expr, rational> soft;
|
||||
if (!init()) {
|
||||
return l_false;
|
||||
|
|
|
@ -49,9 +49,9 @@ namespace opt {
|
|||
m_trail(m),
|
||||
m_defs(m) {}
|
||||
|
||||
virtual ~wmax() {}
|
||||
~wmax() override {}
|
||||
|
||||
lbool operator()() {
|
||||
lbool operator()() override {
|
||||
TRACE("opt", tout << "weighted maxsat\n";);
|
||||
scoped_ensure_theory wth(*this);
|
||||
obj_map<expr, rational> soft;
|
||||
|
|
|
@ -36,11 +36,12 @@ std::string marshal(expr_ref e, ast_manager &m) {
|
|||
expr_ref unmarshal(std::istream &is, ast_manager &m) {
|
||||
cmd_context ctx(false, &m);
|
||||
ctx.set_ignore_check(true);
|
||||
if (!parse_smt2_commands(ctx, is)) { return expr_ref(nullptr, m); }
|
||||
if (!parse_smt2_commands(ctx, is)) {
|
||||
return expr_ref(nullptr, m);
|
||||
}
|
||||
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
unsigned size = static_cast<unsigned>(end - it);
|
||||
ptr_vector<expr>::const_iterator it = ctx.assertions().begin();
|
||||
unsigned size = ctx.assertions().size();
|
||||
return expr_ref(mk_and(m, size, it), m);
|
||||
}
|
||||
|
||||
|
|
|
@ -2614,7 +2614,7 @@ namespace smt2 {
|
|||
|
||||
check_rparen("invalid get-value command, ')' expected");
|
||||
model_ref md;
|
||||
if (!m_ctx.is_model_available(md) || m_ctx.get_check_sat_result() == 0)
|
||||
if (!m_ctx.is_model_available(md) || m_ctx.get_check_sat_result() == nullptr)
|
||||
throw cmd_exception("model is not available");
|
||||
if (index != 0) {
|
||||
m_ctx.get_opt()->get_box_model(md, index);
|
||||
|
|
|
@ -394,7 +394,7 @@ namespace eq {
|
|||
expr* const* args = &e;
|
||||
if (is_lambda(q)) {
|
||||
r = q;
|
||||
pr = 0;
|
||||
pr = nullptr;
|
||||
return;
|
||||
}
|
||||
flatten_args(q, num_args, args);
|
||||
|
|
|
@ -156,7 +156,7 @@ namespace qe {
|
|||
std::swap(e1, e2);
|
||||
}
|
||||
// y + -1*x == 0 --> y = x
|
||||
expr *a0 = 0, *a1 = 0, *x = 0;
|
||||
expr *a0 = nullptr, *a1 = nullptr, *x = nullptr;
|
||||
if (a.is_zero(e2) && a.is_add(e1, a0, a1)) {
|
||||
if (a.is_times_minus_one(a1, x)) {
|
||||
e1 = a0;
|
||||
|
|
|
@ -1266,9 +1266,9 @@ namespace qe {
|
|||
in->reset();
|
||||
in->inc_depth();
|
||||
result.push_back(in.get());
|
||||
if (in->models_enabled()) {
|
||||
if (in->models_enabled()) {
|
||||
model_converter_ref mc;
|
||||
mc = model2model_converter(m_model.get());
|
||||
mc = model2model_converter(m_model_save.get());
|
||||
mc = concat(m_pred_abs.fmc(), mc.get());
|
||||
in->add(mc.get());
|
||||
}
|
||||
|
|
|
@ -1862,8 +1862,9 @@ namespace sat {
|
|||
return p;
|
||||
}
|
||||
|
||||
ba_solver::ba_solver(): m_solver(0), m_lookahead(0), m_unit_walk(0),
|
||||
m_allocator("ba"), m_constraint_id(0), m_ba(*this), m_sort(m_ba) {
|
||||
ba_solver::ba_solver()
|
||||
: m_solver(nullptr), m_lookahead(nullptr), m_unit_walk(nullptr),
|
||||
m_constraint_id(0), m_ba(*this), m_sort(m_ba) {
|
||||
TRACE("ba", tout << this << "\n";);
|
||||
m_num_propagations_since_pop = 0;
|
||||
}
|
||||
|
@ -3838,7 +3839,7 @@ namespace sat {
|
|||
}
|
||||
init_visited();
|
||||
for (wliteral l : p1) {
|
||||
SASSERT(m_weights.get(l.second.index(), 0) == 0);
|
||||
SASSERT(m_weights.size() <= l.second.index() || m_weights[l.second.index()] == 0);
|
||||
m_weights.setx(l.second.index(), l.first, 0);
|
||||
mark_visited(l.second);
|
||||
}
|
||||
|
@ -4394,6 +4395,12 @@ namespace sat {
|
|||
}
|
||||
|
||||
if (slack >= k) {
|
||||
#if 0
|
||||
return active2constraint();
|
||||
active2pb(m_A);
|
||||
std::cout << "not asserting\n";
|
||||
display(std::cout, m_A, true);
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ namespace sat {
|
|||
virtual void set_k(unsigned k) { VERIFY(k < 4000000000); m_k = k; }
|
||||
virtual unsigned get_coeff(unsigned i) const { UNREACHABLE(); return 0; }
|
||||
unsigned k() const { return m_k; }
|
||||
virtual bool well_formed() const;
|
||||
bool well_formed() const override;
|
||||
};
|
||||
|
||||
class card : public pb_base {
|
||||
|
@ -146,13 +146,13 @@ namespace sat {
|
|||
literal& operator[](unsigned i) { return m_lits[i]; }
|
||||
literal const* begin() const { return m_lits; }
|
||||
literal const* end() const { return static_cast<literal const*>(m_lits) + m_size; }
|
||||
virtual void negate();
|
||||
virtual void swap(unsigned i, unsigned j) { std::swap(m_lits[i], m_lits[j]); }
|
||||
virtual literal_vector literals() const { return literal_vector(m_size, m_lits); }
|
||||
virtual bool is_watching(literal l) const;
|
||||
virtual literal get_lit(unsigned i) const { return m_lits[i]; }
|
||||
virtual void set_lit(unsigned i, literal l) { m_lits[i] = l; }
|
||||
virtual unsigned get_coeff(unsigned i) const { return 1; }
|
||||
void negate() override;
|
||||
void swap(unsigned i, unsigned j) override { std::swap(m_lits[i], m_lits[j]); }
|
||||
literal_vector literals() const override { return literal_vector(m_size, m_lits); }
|
||||
bool is_watching(literal l) const override;
|
||||
literal get_lit(unsigned i) const override { return m_lits[i]; }
|
||||
void set_lit(unsigned i, literal l) override { m_lits[i] = l; }
|
||||
unsigned get_coeff(unsigned i) const override { return 1; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -179,14 +179,14 @@ namespace sat {
|
|||
void update_max_sum();
|
||||
void set_num_watch(unsigned s) { m_num_watch = s; }
|
||||
bool is_cardinality() const;
|
||||
virtual void negate();
|
||||
virtual void set_k(unsigned k) { m_k = k; VERIFY(k < 4000000000); update_max_sum(); }
|
||||
virtual void swap(unsigned i, unsigned j) { std::swap(m_wlits[i], m_wlits[j]); }
|
||||
virtual literal_vector literals() const { literal_vector lits; for (auto wl : *this) lits.push_back(wl.second); return lits; }
|
||||
virtual bool is_watching(literal l) const;
|
||||
virtual literal get_lit(unsigned i) const { return m_wlits[i].second; }
|
||||
virtual void set_lit(unsigned i, literal l) { m_wlits[i].second = l; }
|
||||
virtual unsigned get_coeff(unsigned i) const { return m_wlits[i].first; }
|
||||
void negate() override;
|
||||
void set_k(unsigned k) override { m_k = k; VERIFY(k < 4000000000); update_max_sum(); }
|
||||
void swap(unsigned i, unsigned j) override { std::swap(m_wlits[i], m_wlits[j]); }
|
||||
literal_vector literals() const override { literal_vector lits; for (auto wl : *this) lits.push_back(wl.second); return lits; }
|
||||
bool is_watching(literal l) const override;
|
||||
literal get_lit(unsigned i) const override { return m_wlits[i].second; }
|
||||
void set_lit(unsigned i, literal l) override { m_wlits[i].second = l; }
|
||||
unsigned get_coeff(unsigned i) const override { return m_wlits[i].first; }
|
||||
};
|
||||
|
||||
class xr : public constraint {
|
||||
|
@ -197,13 +197,13 @@ namespace sat {
|
|||
literal operator[](unsigned i) const { return m_lits[i]; }
|
||||
literal const* begin() const { return m_lits; }
|
||||
literal const* end() const { return begin() + m_size; }
|
||||
virtual void negate() { m_lits[0].neg(); }
|
||||
virtual void swap(unsigned i, unsigned j) { std::swap(m_lits[i], m_lits[j]); }
|
||||
virtual bool is_watching(literal l) const;
|
||||
virtual literal_vector literals() const { return literal_vector(size(), begin()); }
|
||||
virtual literal get_lit(unsigned i) const { return m_lits[i]; }
|
||||
virtual void set_lit(unsigned i, literal l) { m_lits[i] = l; }
|
||||
virtual bool well_formed() const;
|
||||
void negate() override { m_lits[0].neg(); }
|
||||
void swap(unsigned i, unsigned j) override { std::swap(m_lits[i], m_lits[j]); }
|
||||
bool is_watching(literal l) const override;
|
||||
literal_vector literals() const override { return literal_vector(size(), begin()); }
|
||||
literal get_lit(unsigned i) const override { return m_lits[i]; }
|
||||
void set_lit(unsigned i, literal l) override { m_lits[i] = l; }
|
||||
bool well_formed() const override;
|
||||
};
|
||||
|
||||
|
||||
|
@ -524,44 +524,44 @@ namespace sat {
|
|||
|
||||
public:
|
||||
ba_solver();
|
||||
virtual ~ba_solver();
|
||||
virtual void set_solver(solver* s) { m_solver = s; }
|
||||
virtual void set_lookahead(lookahead* l) { m_lookahead = l; }
|
||||
virtual void set_unit_walk(unit_walk* u) { m_unit_walk = u; }
|
||||
~ba_solver() override;
|
||||
void set_solver(solver* s) override { m_solver = s; }
|
||||
void set_lookahead(lookahead* l) override { m_lookahead = l; }
|
||||
void set_unit_walk(unit_walk* u) override { m_unit_walk = u; }
|
||||
void add_at_least(bool_var v, literal_vector const& lits, unsigned k);
|
||||
void add_pb_ge(bool_var v, svector<wliteral> const& wlits, unsigned k);
|
||||
void add_xr(literal_vector const& lits);
|
||||
|
||||
virtual bool propagate(literal l, ext_constraint_idx idx);
|
||||
virtual lbool resolve_conflict();
|
||||
virtual void get_antecedents(literal l, ext_justification_idx idx, literal_vector & r);
|
||||
virtual void asserted(literal l);
|
||||
virtual check_result check();
|
||||
virtual void push();
|
||||
virtual void pop(unsigned n);
|
||||
virtual void simplify();
|
||||
virtual void clauses_modifed();
|
||||
virtual lbool get_phase(bool_var v);
|
||||
virtual bool set_root(literal l, literal r);
|
||||
virtual void flush_roots();
|
||||
virtual std::ostream& display(std::ostream& out) const;
|
||||
virtual std::ostream& display_justification(std::ostream& out, ext_justification_idx idx) const;
|
||||
virtual void collect_statistics(statistics& st) const;
|
||||
virtual extension* copy(solver* s);
|
||||
virtual extension* copy(lookahead* s, bool learned);
|
||||
virtual void find_mutexes(literal_vector& lits, vector<literal_vector> & mutexes);
|
||||
virtual void pop_reinit();
|
||||
virtual void gc();
|
||||
virtual double get_reward(literal l, ext_justification_idx idx, literal_occs_fun& occs) const;
|
||||
virtual bool is_extended_binary(ext_justification_idx idx, literal_vector & r);
|
||||
virtual void init_use_list(ext_use_list& ul);
|
||||
virtual bool is_blocked(literal l, ext_constraint_idx idx);
|
||||
virtual bool check_model(model const& m) const;
|
||||
bool propagate(literal l, ext_constraint_idx idx) override;
|
||||
lbool resolve_conflict() override;
|
||||
void get_antecedents(literal l, ext_justification_idx idx, literal_vector & r) override;
|
||||
void asserted(literal l) override;
|
||||
check_result check() override;
|
||||
void push() override;
|
||||
void pop(unsigned n) override;
|
||||
void simplify() override;
|
||||
void clauses_modifed() override;
|
||||
lbool get_phase(bool_var v) override;
|
||||
bool set_root(literal l, literal r) override;
|
||||
void flush_roots() override;
|
||||
std::ostream& display(std::ostream& out) const override;
|
||||
std::ostream& display_justification(std::ostream& out, ext_justification_idx idx) const override;
|
||||
void collect_statistics(statistics& st) const override;
|
||||
extension* copy(solver* s) override;
|
||||
extension* copy(lookahead* s, bool learned) override;
|
||||
void find_mutexes(literal_vector& lits, vector<literal_vector> & mutexes) override;
|
||||
void pop_reinit() override;
|
||||
void gc() override;
|
||||
double get_reward(literal l, ext_justification_idx idx, literal_occs_fun& occs) const override;
|
||||
bool is_extended_binary(ext_justification_idx idx, literal_vector & r) override;
|
||||
void init_use_list(ext_use_list& ul) override;
|
||||
bool is_blocked(literal l, ext_constraint_idx idx) override;
|
||||
bool check_model(model const& m) const override;
|
||||
|
||||
ptr_vector<constraint> const & constraints() const { return m_constraints; }
|
||||
void display(std::ostream& out, constraint const& c, bool values) const;
|
||||
|
||||
virtual bool validate();
|
||||
bool validate() override;
|
||||
|
||||
|
||||
};
|
||||
|
|
|
@ -152,6 +152,8 @@ namespace sat {
|
|||
m_gc_burst = p.gc_burst();
|
||||
m_gc_defrag = p.gc_defrag();
|
||||
|
||||
m_force_cleanup = p.force_cleanup();
|
||||
|
||||
m_minimize_lemmas = p.minimize_lemmas();
|
||||
m_core_minimize = p.core_minimize();
|
||||
m_core_minimize_partial = p.core_minimize_partial();
|
||||
|
|
|
@ -146,6 +146,8 @@ namespace sat {
|
|||
bool m_gc_burst;
|
||||
bool m_gc_defrag;
|
||||
|
||||
bool m_force_cleanup;
|
||||
|
||||
|
||||
bool m_minimize_lemmas;
|
||||
bool m_dyn_sub_res;
|
||||
|
|
|
@ -26,7 +26,7 @@ Notes:
|
|||
namespace sat {
|
||||
drat::drat(solver& s):
|
||||
s(s),
|
||||
m_out(0),
|
||||
m_out(nullptr),
|
||||
m_inconsistent(false),
|
||||
m_check_unsat(false),
|
||||
m_check_sat(false),
|
||||
|
|
|
@ -529,7 +529,7 @@ namespace sat {
|
|||
}
|
||||
|
||||
lbool local_search::check() {
|
||||
return check(0, 0);
|
||||
return check(0, nullptr);
|
||||
}
|
||||
|
||||
#define PROGRESS(tries, flips) \
|
||||
|
|
|
@ -277,7 +277,7 @@ namespace sat {
|
|||
|
||||
lbool check();
|
||||
|
||||
lbool check(unsigned sz, literal const* assumptions, parallel* p = 0);
|
||||
lbool check(unsigned sz, literal const* assumptions, parallel* p = nullptr);
|
||||
|
||||
local_search_config& config() { return m_config; }
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@ Author:
|
|||
|
||||
Notes:
|
||||
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include <cmath>
|
||||
|
@ -31,7 +33,7 @@ namespace sat {
|
|||
}
|
||||
|
||||
lookahead::scoped_ext::~scoped_ext() {
|
||||
if (p.m_s.m_ext) p.m_s.m_ext->set_lookahead(0);
|
||||
if (p.m_s.m_ext) p.m_s.m_ext->set_lookahead(nullptr);
|
||||
}
|
||||
|
||||
lookahead::scoped_assumptions::scoped_assumptions(lookahead& p, literal_vector const& lits): p(p), lits(lits) {
|
||||
|
@ -1215,7 +1217,7 @@ namespace sat {
|
|||
lookahead& lh;
|
||||
public:
|
||||
lookahead_literal_occs_fun(lookahead& lh): lh(lh) {}
|
||||
double operator()(literal l) { return lh.literal_occs(l); }
|
||||
double operator()(literal l) override { return lh.literal_occs(l); }
|
||||
};
|
||||
|
||||
// Ternary clause managagement:
|
||||
|
@ -2055,6 +2057,15 @@ namespace sat {
|
|||
return h;
|
||||
}
|
||||
|
||||
bool lookahead::should_cutoff(unsigned depth) {
|
||||
return depth > 0 &&
|
||||
((m_config.m_cube_cutoff == depth_cutoff && depth == m_config.m_cube_depth) ||
|
||||
(m_config.m_cube_cutoff == freevars_cutoff && m_freevars.size() <= m_init_freevars * m_config.m_cube_freevars) ||
|
||||
(m_config.m_cube_cutoff == psat_cutoff && psat_heur() >= m_config.m_cube_psat_trigger) ||
|
||||
(m_config.m_cube_cutoff == adaptive_freevars_cutoff && m_freevars.size() < m_cube_state.m_freevars_threshold) ||
|
||||
(m_config.m_cube_cutoff == adaptive_psat_cutoff && psat_heur() >= m_cube_state.m_psat_threshold));
|
||||
}
|
||||
|
||||
lbool lookahead::cube(bool_var_vector& vars, literal_vector& lits, unsigned backtrack_level) {
|
||||
scoped_ext _scoped_ext(*this);
|
||||
lits.reset();
|
||||
|
@ -2100,22 +2111,13 @@ namespace sat {
|
|||
}
|
||||
backtrack_level = UINT_MAX;
|
||||
depth = m_cube_state.m_cube.size();
|
||||
if ((m_config.m_cube_cutoff == depth_cutoff && depth == m_config.m_cube_depth) ||
|
||||
(m_config.m_cube_cutoff == freevars_cutoff && m_freevars.size() <= m_init_freevars * m_config.m_cube_freevars) ||
|
||||
(m_config.m_cube_cutoff == psat_cutoff && psat_heur() >= m_config.m_cube_psat_trigger) ||
|
||||
(m_config.m_cube_cutoff == adaptive_freevars_cutoff && m_freevars.size() < m_cube_state.m_freevars_threshold) ||
|
||||
(m_config.m_cube_cutoff == adaptive_psat_cutoff && psat_heur() >= m_cube_state.m_psat_threshold)) {
|
||||
if (should_cutoff(depth)) {
|
||||
double dec = (1.0 - pow(m_config.m_cube_fraction, depth));
|
||||
m_cube_state.m_freevars_threshold *= dec;
|
||||
m_cube_state.m_psat_threshold *= 2.0 - dec;
|
||||
set_conflict();
|
||||
m_cube_state.inc_cutoff();
|
||||
#if 0
|
||||
// return cube of all literals, not just the ones in the main cube
|
||||
lits.append(m_trail.size() - init_trail, m_trail.c_ptr() + init_trail);
|
||||
#else
|
||||
lits.append(m_cube_state.m_cube);
|
||||
#endif
|
||||
vars.reset();
|
||||
for (auto v : m_freevars) if (in_reduced_clause(v)) vars.push_back(v);
|
||||
backtrack(m_cube_state.m_cube, m_cube_state.m_is_decision);
|
||||
|
@ -2135,6 +2137,8 @@ namespace sat {
|
|||
if (lit == null_literal) {
|
||||
vars.reset();
|
||||
for (auto v : m_freevars) if (in_reduced_clause(v)) vars.push_back(v);
|
||||
m_model.reset();
|
||||
init_model();
|
||||
return l_true;
|
||||
}
|
||||
TRACE("sat", tout << "choose: " << lit << " cube: " << m_cube_state.m_cube << "\n";);
|
||||
|
|
|
@ -558,6 +558,8 @@ namespace sat {
|
|||
|
||||
double psat_heur();
|
||||
|
||||
bool should_cutoff(unsigned depth);
|
||||
|
||||
public:
|
||||
lookahead(solver& s) :
|
||||
m_s(s),
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
sat_par.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Utilities for parallel SAT solving.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2017-1-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include "sat/sat_par.h"
|
||||
|
||||
|
||||
namespace sat {
|
||||
|
||||
par::par() {}
|
||||
|
||||
void par::exchange(literal_vector const& in, unsigned& limit, literal_vector& out) {
|
||||
#pragma omp critical (par_solver)
|
||||
{
|
||||
if (limit < m_units.size()) {
|
||||
// this might repeat some literals.
|
||||
out.append(m_units.size() - limit, m_units.c_ptr() + limit);
|
||||
}
|
||||
for (unsigned i = 0; i < in.size(); ++i) {
|
||||
literal lit = in[i];
|
||||
if (!m_unit_set.contains(lit.index())) {
|
||||
m_unit_set.insert(lit.index());
|
||||
m_units.push_back(lit);
|
||||
}
|
||||
}
|
||||
limit = m_units.size();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
sat_par.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Utilities for parallel SAT solving.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2017-1-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef SAT_PAR_H_
|
||||
#define SAT_PAR_H_
|
||||
|
||||
#include "sat/sat_types.h"
|
||||
#include "util/hashtable.h"
|
||||
#include "util/map.h"
|
||||
|
||||
namespace sat {
|
||||
|
||||
class par {
|
||||
typedef hashtable<unsigned, u_hash, u_eq> index_set;
|
||||
literal_vector m_units;
|
||||
index_set m_unit_set;
|
||||
public:
|
||||
par();
|
||||
void exchange(literal_vector const& in, unsigned& limit, literal_vector& out);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -15,7 +15,7 @@ def_module_params('sat',
|
|||
('restart.margin', DOUBLE, 1.1, 'margin between fast and slow restart factors. For ema'),
|
||||
('restart.emafastglue', DOUBLE, 3e-2, 'ema alpha factor for fast moving average'),
|
||||
('restart.emaslowglue', DOUBLE, 1e-5, 'ema alpha factor for slow moving average'),
|
||||
('variable_decay', UINT, 110, 'multiplier (divided by 100) for the VSIDS activity increement'),
|
||||
('variable_decay', UINT, 110, 'multiplier (divided by 100) for the VSIDS activity increment'),
|
||||
('inprocess.max', UINT, UINT_MAX, 'maximal number of inprocessing passes'),
|
||||
('branching.heuristic', SYMBOL, 'vsids', 'branching heuristic vsids, lrb or chb'),
|
||||
('branching.anti_exploration', BOOL, False, 'apply anti-exploration heuristic for branch selection'),
|
||||
|
@ -31,6 +31,7 @@ def_module_params('sat',
|
|||
('gc.burst', BOOL, False, 'perform eager garbage collection during initialization'),
|
||||
('gc.defrag', BOOL, True, 'defragment clauses when garbage collecting'),
|
||||
('simplify.delay', UINT, 0, 'set initial delay of simplification by a conflict count'),
|
||||
('force_cleanup', BOOL, False, 'force cleanup to remove tautologies and simplify clauses'),
|
||||
('minimize_lemmas', BOOL, True, 'minimize learned clauses'),
|
||||
('dyn_sub_res', BOOL, True, 'dynamic subsumption resolution for minimizing learned clauses'),
|
||||
('core.minimize', BOOL, False, 'minimize computed core'),
|
||||
|
@ -52,17 +53,39 @@ def_module_params('sat',
|
|||
('unit_walk', BOOL, False, 'use unit-walk search instead of CDCL'),
|
||||
('unit_walk_threads', UINT, 0, 'number of unit-walk search threads to find satisfiable solution'),
|
||||
('lookahead.cube.cutoff', SYMBOL, 'depth', 'cutoff type used to create lookahead cubes: depth, freevars, psat, adaptive_freevars, adaptive_psat'),
|
||||
# - depth: the maximal cutoff is fixed to the value of lookahead.cube.depth.
|
||||
# So if the value is 10, at most 1024 cubes will be generated of length 10.
|
||||
# - freevars: cutoff based on a variable fraction of lookahead.cube.freevars.
|
||||
# Cut if the number of current unassigned variables drops below a fraction of number of initial variables.
|
||||
# - psat: Let psat_heur := (Sum_{clause C} (psat.clause_base ^ {-|C|+1})) / |freevars|^psat.var_exp
|
||||
# Cut if the value of psat_heur exceeds psat.trigger
|
||||
# - adaptive_freevars: Cut if the number of current unassigned variables drops below a fraction of free variables
|
||||
# at the time of the last conflict. The fraction is increased every time the cutoff is created.
|
||||
# - adative_psat: Cut based on psat_heur in an adaptive way.
|
||||
('lookahead.cube.fraction', DOUBLE, 0.4, 'adaptive fraction to create lookahead cubes. Used when lookahead.cube.cutoff is adaptive_freevars or adaptive_psat'),
|
||||
('lookahead.cube.depth', UINT, 1, 'cut-off depth to create cubes. Used when lookahead.cube.cutoff is depth.'),
|
||||
('lookahead.cube.freevars', DOUBLE, 0.8, 'cube free fariable fraction. Used when lookahead.cube.cutoff is freevars'),
|
||||
('lookahead.cube.freevars', DOUBLE, 0.8, 'cube free variable fraction. Used when lookahead.cube.cutoff is freevars'),
|
||||
('lookahead.cube.psat.var_exp', DOUBLE, 1, 'free variable exponent for PSAT cutoff'),
|
||||
('lookahead.cube.psat.clause_base', DOUBLE, 2, 'clause base for PSAT cutoff'),
|
||||
('lookahead.cube.psat.trigger', DOUBLE, 5, 'trigger value to create lookahead cubes for PSAT cutoff. Used when lookahead.cube.cutoff is psat'),
|
||||
('lookahead_search', BOOL, False, 'use lookahead solver'),
|
||||
('lookahead.preselect', BOOL, False, 'use pre-selection of subset of variables for branching'),
|
||||
('lookahead_simplify', BOOL, False, 'use lookahead solver during simplification'),
|
||||
('lookahead.use_learned', BOOL, False, 'use learned clauses when selecting lookahead literal'),
|
||||
('lookahead_simplify.bca', BOOL, True, 'add learned binary clauses as part of lookahead simplification'),
|
||||
('lookahead.global_autarky', BOOL, False, 'prefer to branch on variables that occur in clauses that are reduced'),
|
||||
('lookahead.reward', SYMBOL, 'march_cu', 'select lookahead heuristic: ternary, heule_schur (Heule Schur), heuleu (Heule Unit), unit, or march_cu')))
|
||||
('lookahead.reward', SYMBOL, 'march_cu', 'select lookahead heuristic: ternary, heule_schur (Heule Schur), heuleu (Heule Unit), unit, or march_cu'))
|
||||
# reward function used to determine which literal to cube on.
|
||||
# - ternary: reward function useful for random 3-SAT instances. Used by Heule and Knuth in March.
|
||||
# - heule_schur: reward function based on "Schur Number 5", Heule, AAAI 2018
|
||||
# The score of a literal lit is:
|
||||
# Sum_{C in Clauses | lit in C} 2 ^ (- |C|+1)
|
||||
# * Sum_{lit' in C | lit' != lit} lit_occs(~lit')
|
||||
# / | C |
|
||||
# where lit_occs(lit) is the number of clauses containing lit.
|
||||
# - heuleu: The score of a literal lit is: Sum_{C in Clauses | lit in C} 2 ^ (-|C| + 1)
|
||||
# - unit: heule_schur + also counts number of unit clauses.
|
||||
# - march_cu: default reward function used in a version of March
|
||||
# Each reward function also comes with its own variant of "mix_diff", which
|
||||
# is the function for combining reward metrics for the positive and negative variant of a literal.
|
||||
)
|
||||
|
||||
|
|
|
@ -66,18 +66,20 @@ namespace sat {
|
|||
m_next_simplify = 0;
|
||||
m_num_checkpoints = 0;
|
||||
m_simplifications = 0;
|
||||
m_ext = 0;
|
||||
m_ext = nullptr;
|
||||
m_cuber = nullptr;
|
||||
m_mc.set_solver(this);
|
||||
}
|
||||
|
||||
solver::~solver() {
|
||||
m_ext = 0;
|
||||
m_ext = nullptr;
|
||||
SASSERT(check_invariant());
|
||||
TRACE("sat", tout << "Delete clauses\n";);
|
||||
del_clauses(m_clauses);
|
||||
TRACE("sat", tout << "Delete learned\n";);
|
||||
del_clauses(m_learned);
|
||||
dealloc(m_cuber);
|
||||
m_cuber = nullptr;
|
||||
}
|
||||
|
||||
void solver::del_clauses(clause_vector& clauses) {
|
||||
|
@ -1008,14 +1010,39 @@ namespace sat {
|
|||
}
|
||||
|
||||
lbool solver::cube(bool_var_vector& vars, literal_vector& lits, unsigned backtrack_level) {
|
||||
if (!m_cuber) {
|
||||
bool is_first = !m_cuber;
|
||||
if (is_first) {
|
||||
m_cuber = alloc(lookahead, *this);
|
||||
}
|
||||
lbool result = m_cuber->cube(vars, lits, backtrack_level);
|
||||
m_cuber->update_cube_statistics(m_aux_stats);
|
||||
if (result == l_false) {
|
||||
switch (result) {
|
||||
case l_false:
|
||||
dealloc(m_cuber);
|
||||
m_cuber = nullptr;
|
||||
if (is_first) {
|
||||
pop_to_base_level();
|
||||
set_conflict(justification());
|
||||
}
|
||||
break;
|
||||
case l_true: {
|
||||
lits.reset();
|
||||
pop_to_base_level();
|
||||
model const& mdl = m_cuber->get_model();
|
||||
for (bool_var v = 0; v < mdl.size(); ++v) {
|
||||
if (value(v) != l_undef) {
|
||||
continue;
|
||||
}
|
||||
literal l(v, false);
|
||||
if (mdl[v] != l_true) l.neg();
|
||||
push();
|
||||
assign_core(l, justification());
|
||||
}
|
||||
mk_model();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1053,7 +1080,7 @@ namespace sat {
|
|||
init_assumptions(num_lits, lits);
|
||||
propagate(false);
|
||||
if (check_inconsistent()) return l_false;
|
||||
cleanup();
|
||||
cleanup(m_config.m_force_cleanup);
|
||||
|
||||
if (m_config.m_unit_walk) {
|
||||
return do_unit_walk();
|
||||
|
@ -1127,7 +1154,7 @@ namespace sat {
|
|||
srch.config().set_config(m_config);
|
||||
srch.import(*this, false);
|
||||
scoped_rl.push_child(&srch.rlimit());
|
||||
lbool r = srch.check(num_lits, lits, 0);
|
||||
lbool r = srch.check(num_lits, lits, nullptr);
|
||||
m_model = srch.get_model();
|
||||
// srch.collect_statistics(m_aux_stats);
|
||||
return r;
|
||||
|
@ -1264,7 +1291,7 @@ namespace sat {
|
|||
if (!canceled) {
|
||||
rlimit().reset_cancel();
|
||||
}
|
||||
set_par(0, 0);
|
||||
set_par(nullptr, 0);
|
||||
ls.reset();
|
||||
uw.reset();
|
||||
if (finished_id == -1) {
|
||||
|
@ -1425,7 +1452,7 @@ namespace sat {
|
|||
if (should_restart())
|
||||
return l_undef;
|
||||
if (at_base_lvl()) {
|
||||
cleanup(); // cleaner may propagate frozen clauses
|
||||
cleanup(false); // cleaner may propagate frozen clauses
|
||||
if (inconsistent()) {
|
||||
TRACE("sat", tout << "conflict at level 0\n";);
|
||||
return l_false;
|
||||
|
@ -1621,7 +1648,7 @@ namespace sat {
|
|||
|
||||
SASSERT(at_base_lvl());
|
||||
|
||||
m_cleaner();
|
||||
m_cleaner(m_config.m_force_cleanup);
|
||||
CASSERT("sat_simplify_bug", check_invariant());
|
||||
|
||||
m_scc();
|
||||
|
@ -3662,10 +3689,10 @@ namespace sat {
|
|||
// Simplification
|
||||
//
|
||||
// -----------------------
|
||||
void solver::cleanup() {
|
||||
void solver::cleanup(bool force) {
|
||||
if (!at_base_lvl() || inconsistent())
|
||||
return;
|
||||
if (m_cleaner() && m_ext)
|
||||
if (m_cleaner(force) && m_ext)
|
||||
m_ext->clauses_modifed();
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ Revision History:
|
|||
#include "sat/sat_drat.h"
|
||||
#include "sat/sat_parallel.h"
|
||||
#include "sat/sat_local_search.h"
|
||||
#include "sat/sat_par.h"
|
||||
#include "util/params.h"
|
||||
#include "util/statistics.h"
|
||||
#include "util/stopwatch.h"
|
||||
|
@ -550,7 +549,7 @@ namespace sat {
|
|||
//
|
||||
// -----------------------
|
||||
public:
|
||||
void cleanup();
|
||||
void cleanup(bool force);
|
||||
void simplify(bool learned = true);
|
||||
void asymmetric_branching();
|
||||
unsigned scc_bin();
|
||||
|
|
|
@ -8,4 +8,6 @@ z3_add_component(sat_solver
|
|||
core_tactics
|
||||
sat_tactic
|
||||
solver
|
||||
TACTIC_HEADERS
|
||||
inc_sat_solver.h
|
||||
)
|
||||
|
|
|
@ -259,7 +259,7 @@ public:
|
|||
return m_num_scopes;
|
||||
}
|
||||
|
||||
void assert_expr_core2(expr * t, expr * a) override {
|
||||
void assert_expr_core2(expr * t, expr * a) override {
|
||||
if (a) {
|
||||
m_asmsf.push_back(a);
|
||||
assert_expr_core(m.mk_implies(a, t));
|
||||
|
@ -308,10 +308,19 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
expr_ref_vector last_cube(bool is_sat) {
|
||||
expr_ref_vector result(m);
|
||||
result.push_back(is_sat ? m.mk_true() : m.mk_false());
|
||||
return result;
|
||||
}
|
||||
|
||||
expr_ref_vector cube(expr_ref_vector& vs, unsigned backtrack_level) override {
|
||||
if (!is_internalized()) {
|
||||
lbool r = internalize_formulas();
|
||||
if (r != l_true) return expr_ref_vector(m);
|
||||
if (r != l_true) {
|
||||
IF_VERBOSE(0, verbose_stream() << "internalize produced " << r << "\n");
|
||||
return expr_ref_vector(m);
|
||||
}
|
||||
}
|
||||
convert_internalized();
|
||||
obj_hashtable<expr> _vs;
|
||||
|
@ -323,14 +332,18 @@ public:
|
|||
}
|
||||
sat::literal_vector lits;
|
||||
lbool result = m_solver.cube(vars, lits, backtrack_level);
|
||||
if (result == l_false || lits.empty()) {
|
||||
expr_ref_vector result(m);
|
||||
result.push_back(m.mk_false());
|
||||
return result;
|
||||
switch (result) {
|
||||
case l_true:
|
||||
return last_cube(true);
|
||||
case l_false:
|
||||
return last_cube(false);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (result == l_true) {
|
||||
if (lits.empty()) {
|
||||
set_reason_unknown(m_solver.get_reason_unknown());
|
||||
return expr_ref_vector(m);
|
||||
}
|
||||
}
|
||||
expr_ref_vector fmls(m);
|
||||
expr_ref_vector lit2expr(m);
|
||||
lit2expr.resize(m_solver.num_vars() * 2);
|
||||
|
@ -473,6 +486,7 @@ public:
|
|||
}
|
||||
|
||||
void convert_internalized() {
|
||||
m_solver.pop_to_base_level();
|
||||
if (!is_internalized() && m_fmls_head > 0) {
|
||||
internalize_formulas();
|
||||
}
|
||||
|
|
|
@ -28,6 +28,9 @@ solver* mk_inc_sat_solver(ast_manager& m, params_ref const& p, bool incremental_
|
|||
|
||||
tactic* mk_psat_tactic(ast_manager& m, params_ref const& p);
|
||||
|
||||
/*
|
||||
ADD_TACTIC('psat', '(try to) solve goal using a parallel SAT solver.', 'mk_psat_tactic(m, p)')
|
||||
*/
|
||||
|
||||
void inc_sat_display(std::ostream& out, solver& s, unsigned sz, expr*const* soft, rational const* _weights);
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ struct goal2sat::imp {
|
|||
imp(ast_manager & _m, params_ref const & p, sat::solver & s, atom2bool_var & map, dep2asm_map& dep2asm, bool default_external):
|
||||
m(_m),
|
||||
pb(m),
|
||||
m_ext(0),
|
||||
m_ext(nullptr),
|
||||
m_solver(s),
|
||||
m_map(map),
|
||||
m_dep2asm(dep2asm),
|
||||
|
@ -452,7 +452,15 @@ struct goal2sat::imp {
|
|||
unsigned sz = m_result_stack.size();
|
||||
if (root) {
|
||||
m_result_stack.reset();
|
||||
m_ext->add_pb_ge(sat::null_bool_var, wlits, k.get_unsigned());
|
||||
unsigned k1 = k.get_unsigned();
|
||||
if (sign) {
|
||||
k1 = 1 - k1;
|
||||
for (wliteral& wl : wlits) {
|
||||
wl.second.neg();
|
||||
k1 += wl.first;
|
||||
}
|
||||
}
|
||||
m_ext->add_pb_ge(sat::null_bool_var, wlits, k1);
|
||||
}
|
||||
else {
|
||||
sat::bool_var v = m_solver.mk_var(true);
|
||||
|
@ -477,7 +485,15 @@ struct goal2sat::imp {
|
|||
unsigned sz = m_result_stack.size();
|
||||
if (root) {
|
||||
m_result_stack.reset();
|
||||
m_ext->add_pb_ge(sat::null_bool_var, wlits, k.get_unsigned());
|
||||
unsigned k1 = k.get_unsigned();
|
||||
if (sign) {
|
||||
k1 = 1 - k1;
|
||||
for (wliteral& wl : wlits) {
|
||||
wl.second.neg();
|
||||
k1 += wl.first;
|
||||
}
|
||||
}
|
||||
m_ext->add_pb_ge(sat::null_bool_var, wlits, k1);
|
||||
}
|
||||
else {
|
||||
sat::bool_var v = m_solver.mk_var(true);
|
||||
|
@ -1048,7 +1064,7 @@ void sat2goal::mc::insert(sat::bool_var v, app * atom, bool aux) {
|
|||
|
||||
expr_ref sat2goal::mc::lit2expr(sat::literal l) {
|
||||
if (!m_var2expr.get(l.var())) {
|
||||
app* aux = m.mk_fresh_const(0, m.mk_bool_sort());
|
||||
app* aux = m.mk_fresh_const(nullptr, m.mk_bool_sort());
|
||||
m_var2expr.set(l.var(), aux);
|
||||
if (!m_gmc) m_gmc = alloc(generic_model_converter, m, "sat2goal");
|
||||
m_gmc->hide(aux->get_decl());
|
||||
|
@ -1092,7 +1108,7 @@ struct sat2goal::imp {
|
|||
SASSERT(m_lit2expr.get((~l).index()) == 0);
|
||||
app* aux = mc ? mc->var2expr(l.var()) : nullptr;
|
||||
if (!aux) {
|
||||
aux = m.mk_fresh_const(0, m.mk_bool_sort());
|
||||
aux = m.mk_fresh_const(nullptr, m.mk_bool_sort());
|
||||
if (mc) {
|
||||
mc->insert(l.var(), aux, true);
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ public:
|
|||
|
||||
public:
|
||||
mc(ast_manager& m);
|
||||
virtual ~mc() {}
|
||||
~mc() override {}
|
||||
// flush model converter from SAT solver to this structure.
|
||||
void flush_smc(sat::solver& s, atom2bool_var const& map);
|
||||
void operator()(model_ref& md) override;
|
||||
|
|
|
@ -26,7 +26,7 @@ Revision History:
|
|||
#include "shell/smtlib_frontend.h"
|
||||
#include "shell/z3_log_frontend.h"
|
||||
#include "util/warning.h"
|
||||
#include "util/version.h"
|
||||
#include "util/z3_version.h"
|
||||
#include "shell/dimacs_frontend.h"
|
||||
#include "shell/datalog_frontend.h"
|
||||
#include "shell/opt_frontend.h"
|
||||
|
@ -91,7 +91,7 @@ void display_usage() {
|
|||
std::cout << " -pp:name display Z3 parameter description, if 'name' is not provided, then all module names are listed.\n";
|
||||
std::cout << " --" << " all remaining arguments are assumed to be part of the input file name. This option allows Z3 to read files with strange names such as: -foo.smt2.\n";
|
||||
std::cout << "\nResources:\n";
|
||||
// timeout and memout are now available on Linux and OSX too.
|
||||
// timeout and memout are now available on Linux and macOS too.
|
||||
std::cout << " -T:timeout set the timeout (in seconds).\n";
|
||||
std::cout << " -t:timeout set the soft timeout (in milli seconds). It only kills the current query.\n";
|
||||
std::cout << " -memory:Megabytes set a limit for virtual memory consumption.\n";
|
||||
|
|
|
@ -108,7 +108,8 @@ static unsigned parse_opt(std::istream& in, opt_format f) {
|
|||
unsigned rlimit = std::stoi(gparams::get_value("rlimit"));
|
||||
scoped_timer timer(timeout, &eh);
|
||||
scoped_rlimit _rlimit(m.limit(), rlimit);
|
||||
lbool r = opt.optimize();
|
||||
expr_ref_vector asms(m);
|
||||
lbool r = opt.optimize(asms);
|
||||
switch (r) {
|
||||
case l_true: std::cout << "sat\n"; break;
|
||||
case l_false: std::cout << "unsat\n"; break;
|
||||
|
|
|
@ -12,14 +12,11 @@ Abstract:
|
|||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-02-25
|
||||
|
||||
|
||||
--*/
|
||||
#include "smt/arith_eq_solver.h"
|
||||
|
||||
|
||||
arith_eq_solver::~arith_eq_solver() {
|
||||
}
|
||||
|
||||
arith_eq_solver::arith_eq_solver(ast_manager & m, params_ref const& p):
|
||||
m(m),
|
||||
m_params(p),
|
||||
|
@ -93,9 +90,9 @@ void arith_eq_solver::gcd_normalize(vector<numeral>& values) {
|
|||
if (g.is_zero() || g.is_one()) {
|
||||
return;
|
||||
}
|
||||
for (unsigned i = 0; i < values.size(); ++i) {
|
||||
values[i] = values[i] / g;
|
||||
SASSERT(values[i].is_int());
|
||||
for (auto &value : values) {
|
||||
value /= g;
|
||||
SASSERT(value.is_int());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,9 +113,9 @@ unsigned arith_eq_solver::find_abs_min(vector<numeral>& values) {
|
|||
#ifdef _TRACE
|
||||
|
||||
static void print_row(std::ostream& out, vector<rational> const& row) {
|
||||
for(unsigned i = 0; i < row.size(); ++i) {
|
||||
out << row[i] << " ";
|
||||
}
|
||||
for(unsigned i = 0; i < row.size(); ++i) {
|
||||
out << row[i] << " ";
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
|
@ -165,7 +162,7 @@ bool arith_eq_solver::solve_integer_equation(
|
|||
bool& is_fresh
|
||||
)
|
||||
{
|
||||
TRACE("arith_eq_solver",
|
||||
TRACE("arith_eq_solver",
|
||||
tout << "solving: ";
|
||||
print_row(tout, values);
|
||||
);
|
||||
|
@ -174,31 +171,31 @@ bool arith_eq_solver::solve_integer_equation(
|
|||
//
|
||||
// Given:
|
||||
// a1*x1 + a2*x2 + .. + a_n*x_n + a_{n+1} = 0
|
||||
//
|
||||
//
|
||||
// Assume gcd(a1,..,a_n,a_{n+1}) = 1
|
||||
// Assume gcd(a1,...,a_n) divides a_{n+1} (eg. gcd(a1,..,an) = 1)
|
||||
//
|
||||
//
|
||||
// post-condition: values[index] = -1.
|
||||
//
|
||||
//
|
||||
// Let a_index be index of least absolute value.
|
||||
//
|
||||
// If |a_index| = 1, then return row and index.
|
||||
// Otherwise:
|
||||
// Let m = |a_index| + 1
|
||||
// Set
|
||||
//
|
||||
// m*x_index'
|
||||
// =
|
||||
//
|
||||
// m*x_index'
|
||||
// =
|
||||
// ((a1 mod_hat m)*x1 + (a2 mod_hat m)*x2 + .. + (a_n mod_hat m)*x_n + (k mod_hat m))
|
||||
// =
|
||||
// =
|
||||
// (a1'*x1 + a2'*x2 + .. (-)1*x_index + ...)
|
||||
//
|
||||
//
|
||||
// <=> Normalize signs so that sign to x_index is -1.
|
||||
// (-)a1'*x1 + (-)a2'*x2 + .. -1*x_index + ... + m*x_index' = 0
|
||||
//
|
||||
//
|
||||
// Return row, where the coefficient to x_index is implicit.
|
||||
// Instead used the coefficient 'm' at position 'index'.
|
||||
//
|
||||
//
|
||||
|
||||
gcd_normalize(values);
|
||||
if (!gcd_test(values)) {
|
||||
|
@ -216,8 +213,8 @@ bool arith_eq_solver::solve_integer_equation(
|
|||
return true;
|
||||
}
|
||||
if (a.is_one()) {
|
||||
for (unsigned i = 0; i < values.size(); ++i) {
|
||||
values[i].neg();
|
||||
for (auto &value : values) {
|
||||
value.neg();
|
||||
}
|
||||
}
|
||||
is_fresh = !abs_a.is_one();
|
||||
|
@ -225,19 +222,19 @@ bool arith_eq_solver::solve_integer_equation(
|
|||
if (is_fresh) {
|
||||
|
||||
numeral m = abs_a + numeral(1);
|
||||
for (unsigned i = 0; i < values.size(); ++i) {
|
||||
values[i] = mod_hat(values[i], m);
|
||||
for (auto &value : values) {
|
||||
value = mod_hat(value, m);
|
||||
}
|
||||
if (values[index].is_one()) {
|
||||
for (unsigned i = 0; i < values.size(); ++i) {
|
||||
values[i].neg();
|
||||
for (auto &value : values) {
|
||||
value.neg();
|
||||
}
|
||||
}
|
||||
SASSERT(values[index].is_minus_one());
|
||||
values[index] = m;
|
||||
}
|
||||
|
||||
TRACE("arith_eq_solver",
|
||||
TRACE("arith_eq_solver",
|
||||
tout << "solved at index " << index << ": ";
|
||||
print_row(tout, values);
|
||||
);
|
||||
|
@ -253,7 +250,7 @@ void arith_eq_solver::substitute(
|
|||
)
|
||||
{
|
||||
SASSERT(1 <= index && index < s.size());
|
||||
TRACE("arith_eq_solver",
|
||||
TRACE("arith_eq_solver",
|
||||
tout << "substitute " << index << ":\n";
|
||||
print_row(tout, r);
|
||||
print_row(tout, s);
|
||||
|
@ -272,21 +269,21 @@ void arith_eq_solver::substitute(
|
|||
// s encodes an equation that contains a variable
|
||||
// with a unit coefficient.
|
||||
//
|
||||
// Let
|
||||
// Let
|
||||
// c = r[index]
|
||||
// s = s[index]*x + s'*y = 0
|
||||
// r = c*x + r'*y = 0
|
||||
//
|
||||
// =>
|
||||
//
|
||||
// =>
|
||||
//
|
||||
// 0
|
||||
// =
|
||||
// -sign(s[index])*c*s + r
|
||||
// =
|
||||
// =
|
||||
// -sign(s[index])*c*s + r
|
||||
// =
|
||||
// -s[index]*sign(s[index])*c*x - sign(s[index])*c*s'*y + c*x + r'*y
|
||||
// =
|
||||
// =
|
||||
// -c*x - sign(s[index])*c*s'*y + c*x + r'*y
|
||||
// =
|
||||
// =
|
||||
// -sign(s[index])*c*s'*y + r'*y
|
||||
//
|
||||
numeral sign_s = s[index].is_pos()?numeral(1):numeral(-1);
|
||||
|
@ -301,36 +298,36 @@ void arith_eq_solver::substitute(
|
|||
//
|
||||
// s encodes a substitution using an auxiliary variable.
|
||||
// the auxiliary variable is at position 'index'.
|
||||
//
|
||||
// Let
|
||||
//
|
||||
// Let
|
||||
// c = r[index]
|
||||
// s = s[index]*x + s'*y = 0
|
||||
// r = c*x + r'*y = 0
|
||||
//
|
||||
// s encodes : x |-> s[index]*x' + s'*y
|
||||
//
|
||||
// Set:
|
||||
// Set:
|
||||
//
|
||||
// r := c*s + r'*y
|
||||
//
|
||||
//
|
||||
r[index] = numeral(0);
|
||||
for (unsigned i = 0; i < r.size(); ++i) {
|
||||
r[i] += c*s[i];
|
||||
}
|
||||
}
|
||||
for (unsigned i = r.size(); i < s.size(); ++i) {
|
||||
r.push_back(c*s[i]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("arith_eq_solver",
|
||||
TRACE("arith_eq_solver",
|
||||
tout << "result: ";
|
||||
print_row(tout, r);
|
||||
);
|
||||
}
|
||||
|
||||
bool arith_eq_solver::solve_integer_equations(
|
||||
vector<row>& rows,
|
||||
vector<row>& rows,
|
||||
row& unsat_row
|
||||
)
|
||||
{
|
||||
|
@ -340,10 +337,10 @@ bool arith_eq_solver::solve_integer_equations(
|
|||
|
||||
//
|
||||
// Naive integer equation solver where only units are eliminated.
|
||||
//
|
||||
//
|
||||
|
||||
bool arith_eq_solver::solve_integer_equations_units(
|
||||
vector<row>& rows,
|
||||
vector<row>& rows,
|
||||
row& unsat_row
|
||||
)
|
||||
{
|
||||
|
@ -351,7 +348,7 @@ bool arith_eq_solver::solve_integer_equations_units(
|
|||
TRACE("arith_eq_solver", print_rows(tout << "solving:\n", rows););
|
||||
|
||||
unsigned_vector todo, done;
|
||||
|
||||
|
||||
for (unsigned i = 0; i < rows.size(); ++i) {
|
||||
todo.push_back(i);
|
||||
row& r = rows[i];
|
||||
|
@ -360,9 +357,9 @@ bool arith_eq_solver::solve_integer_equations_units(
|
|||
unsat_row = r;
|
||||
TRACE("arith_eq_solver", print_row(tout << "input is unsat: ", unsat_row); );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < todo.size(); ++i) {
|
||||
for (unsigned i = 0; i < todo.size(); ++i) {
|
||||
row& r = rows[todo[i]];
|
||||
gcd_normalize(r);
|
||||
if (!gcd_test(r)) {
|
||||
|
@ -388,7 +385,7 @@ bool arith_eq_solver::solve_integer_equations_units(
|
|||
todo.push_back(done[j]);
|
||||
done.erase(done.begin()+j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -396,7 +393,7 @@ bool arith_eq_solver::solve_integer_equations_units(
|
|||
}
|
||||
}
|
||||
|
||||
TRACE("arith_eq_solver",
|
||||
TRACE("arith_eq_solver",
|
||||
tout << ((done.size()<=1)?"solved ":"incomplete check ") << done.size() << "\n";
|
||||
for (unsigned i = 0; i < done.size(); ++i) {
|
||||
print_row(tout, rows[done[i]]);
|
||||
|
@ -411,12 +408,12 @@ bool arith_eq_solver::solve_integer_equations_units(
|
|||
|
||||
//
|
||||
// Partial solver based on the omega test equalities.
|
||||
// unsatisfiability is not preserved when eliminating
|
||||
// unsatisfiability is not preserved when eliminating
|
||||
// auxiliary variables.
|
||||
//
|
||||
|
||||
bool arith_eq_solver::solve_integer_equations_omega(
|
||||
vector<row> & rows,
|
||||
vector<row> & rows,
|
||||
row& unsat_row
|
||||
)
|
||||
{
|
||||
|
@ -460,16 +457,16 @@ bool arith_eq_solver::solve_integer_equations_omega(
|
|||
//
|
||||
// solved_row: -x_index + m*sigma + r1 = 0
|
||||
// unsat_row: k*sigma + r2 = 0
|
||||
//
|
||||
// <=>
|
||||
//
|
||||
//
|
||||
// <=>
|
||||
//
|
||||
// solved_row: -k*x_index + k*m*sigma + k*r1 = 0
|
||||
// unsat_row: m*k*sigma + m*r2 = 0
|
||||
//
|
||||
// =>
|
||||
//
|
||||
// m*k*sigma + m*r2 + k*x_index - k*m*sigma - k*r1 = 0
|
||||
//
|
||||
//
|
||||
for (unsigned l = 0; l < unsat_row.size(); ++l) {
|
||||
unsat_row[l] *= m;
|
||||
unsat_row[l] -= k*solved_row[l];
|
||||
|
@ -479,7 +476,7 @@ bool arith_eq_solver::solve_integer_equations_omega(
|
|||
}
|
||||
|
||||
gcd_normalize(unsat_row);
|
||||
TRACE("arith_eq_solver",
|
||||
TRACE("arith_eq_solver",
|
||||
tout << "gcd: ";
|
||||
print_row(tout, solved_row);
|
||||
print_row(tout, unsat_row);
|
||||
|
@ -525,18 +522,18 @@ bool arith_eq_solver::solve_integer_equations_omega(
|
|||
|
||||
//
|
||||
// Eliminate variables by searching for combination of rows where
|
||||
// the coefficients have gcd = 1.
|
||||
//
|
||||
// the coefficients have gcd = 1.
|
||||
//
|
||||
|
||||
bool arith_eq_solver::solve_integer_equations_gcd(
|
||||
vector<row> & rows,
|
||||
vector<row> & rows,
|
||||
row& unsat_row
|
||||
)
|
||||
{
|
||||
{
|
||||
unsigned_vector live, useful, gcd_pos;
|
||||
vector<rational> gcds;
|
||||
rational u, v;
|
||||
|
||||
|
||||
if (rows.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -548,7 +545,7 @@ bool arith_eq_solver::solve_integer_equations_gcd(
|
|||
unsat_row = r;
|
||||
TRACE("arith_eq_solver", print_row(tout << "input is unsat: ", unsat_row); );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned max_column = rows[0].size();
|
||||
bool change = true;
|
||||
|
@ -579,7 +576,7 @@ bool arith_eq_solver::solve_integer_equations_gcd(
|
|||
if (j == live.size()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
change = true;
|
||||
// found gcd, now identify reduced set of rows with GCD = 1.
|
||||
g = abs(rows[live[j]][i]);
|
||||
|
@ -592,7 +589,7 @@ bool arith_eq_solver::solve_integer_equations_gcd(
|
|||
useful.push_back(gcd_pos[j]);
|
||||
g = gcd(g, gcds[j]);
|
||||
SASSERT(j == 0 || gcd(g,gcds[j-1]).is_one());
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// we now have a set "useful" of rows whose combined GCD = 1.
|
||||
|
@ -600,7 +597,7 @@ bool arith_eq_solver::solve_integer_equations_gcd(
|
|||
//
|
||||
row& r0 = rows[useful[0]];
|
||||
for (j = 1; j < useful.size(); ++j) {
|
||||
row& r1 = rows[useful[j]];
|
||||
row& r1 = rows[useful[j]];
|
||||
g = gcd(r0[i], r1[i], u, v);
|
||||
for (unsigned k = 0; k < max_column; ++k) {
|
||||
r0[k] = u*r0[k] + v*r1[k];
|
||||
|
@ -626,7 +623,7 @@ bool arith_eq_solver::solve_integer_equations_gcd(
|
|||
}
|
||||
}
|
||||
|
||||
TRACE("arith_eq_solver",
|
||||
TRACE("arith_eq_solver",
|
||||
tout << ((live.size()<=1)?"solved ":"incomplete check ") << live.size() << "\n";
|
||||
for (unsigned i = 0; i < live.size(); ++i) {
|
||||
print_row(tout, rows[live[i]]);
|
||||
|
|
|
@ -12,7 +12,7 @@ Abstract:
|
|||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-02-25
|
||||
|
||||
|
||||
--*/
|
||||
#ifndef ARITH_EQ_SOLVER_H_
|
||||
#define ARITH_EQ_SOLVER_H_
|
||||
|
@ -35,45 +35,45 @@ class arith_eq_solver {
|
|||
|
||||
void prop_mod_const(expr * e, unsigned depth, numeral const& k, expr_ref& result);
|
||||
|
||||
bool gcd_test(vector<numeral>& value);
|
||||
bool gcd_test(vector<numeral>& values);
|
||||
unsigned find_abs_min(vector<numeral>& values);
|
||||
void gcd_normalize(vector<numeral>& values);
|
||||
void substitute(vector<numeral>& r, vector<numeral> const& s, unsigned index);
|
||||
bool solve_integer_equations_units(
|
||||
vector<vector<numeral> > & rows,
|
||||
vector<vector<numeral> > & rows,
|
||||
vector<numeral>& unsat_row
|
||||
);
|
||||
|
||||
|
||||
bool solve_integer_equations_omega(
|
||||
vector<vector<numeral> > & rows,
|
||||
vector<vector<numeral> > & rows,
|
||||
vector<numeral>& unsat_row
|
||||
);
|
||||
|
||||
void compute_hnf(vector<vector<numeral> >& A);
|
||||
|
||||
bool solve_integer_equations_hermite(
|
||||
vector<vector<numeral> > & rows,
|
||||
vector<vector<numeral> > & rows,
|
||||
vector<numeral>& unsat_row
|
||||
);
|
||||
|
||||
bool solve_integer_equations_gcd(
|
||||
vector<vector<numeral> > & rows,
|
||||
vector<vector<numeral> > & rows,
|
||||
vector<numeral>& unsat_row
|
||||
);
|
||||
|
||||
public:
|
||||
arith_eq_solver(ast_manager & m, params_ref const& p = params_ref());
|
||||
~arith_eq_solver();
|
||||
~arith_eq_solver() = default;
|
||||
|
||||
// Integer linear solver for a single equation.
|
||||
// The array values contains integer coefficients
|
||||
//
|
||||
//
|
||||
// Determine integer solutions to:
|
||||
//
|
||||
// a+k = 0
|
||||
//
|
||||
// where a = sum_i a_i*k_i
|
||||
//
|
||||
//
|
||||
|
||||
typedef vector<numeral> row;
|
||||
typedef vector<row> matrix;
|
||||
|
@ -90,14 +90,14 @@ public:
|
|||
// a+k = 0
|
||||
//
|
||||
// where a = sum_i a_i*k_i
|
||||
//
|
||||
//
|
||||
// Solution, if there is any, is returned as a substitution.
|
||||
// The return value is "true".
|
||||
// If there is no solution, then return "false".
|
||||
// together with equality "eq_unsat", such that
|
||||
//
|
||||
// eq_unsat = 0
|
||||
//
|
||||
//
|
||||
// is implied and is unsatisfiable over the integers.
|
||||
//
|
||||
|
||||
|
|
|
@ -2571,6 +2571,7 @@ namespace smt {
|
|||
m_n1 = m_context.get_enode_eq_to(static_cast<const get_cgr *>(m_pc)->m_label, static_cast<const get_cgr *>(m_pc)->m_num_args, m_args.c_ptr()); \
|
||||
if (m_n1 == 0 || !m_context.is_relevant(m_n1)) \
|
||||
goto backtrack; \
|
||||
update_max_generation(m_n1, nullptr); \
|
||||
m_registers[static_cast<const get_cgr *>(m_pc)->m_oreg] = m_n1; \
|
||||
m_pc = m_pc->m_next; \
|
||||
goto main_loop;
|
||||
|
|
|
@ -63,6 +63,7 @@ void smt_params::updt_params(params_ref const & p) {
|
|||
theory_bv_params::updt_params(p);
|
||||
theory_pb_params::updt_params(p);
|
||||
// theory_array_params::updt_params(p);
|
||||
theory_datatype_params::updt_params(p);
|
||||
updt_local_params(p);
|
||||
}
|
||||
|
||||
|
|
|
@ -94,5 +94,6 @@ def_module_params(module_name='smt',
|
|||
('core.extend_patterns', BOOL, False, 'extend unsat core with literals that trigger (potential) quantifier instances'),
|
||||
('core.extend_patterns.max_distance', UINT, UINT_MAX, 'limits the distance of a pattern-extended unsat core'),
|
||||
('core.extend_nonlocal_patterns', BOOL, False, 'extend unsat cores with literals that have quantifiers with patterns that contain symbols which are not in the quantifier\'s body'),
|
||||
('lemma_gc_strategy', UINT, 0, 'lemma garbage collection strategy: 0 - fixed, 1 - geometric, 2 - at restart, 3 - none')
|
||||
('lemma_gc_strategy', UINT, 0, 'lemma garbage collection strategy: 0 - fixed, 1 - geometric, 2 - at restart, 3 - none'),
|
||||
('dt_lazy_splits', UINT, 1, 'How lazy datatype splits are performed: 0- eager, 1- lazy for infinite types, 2- lazy')
|
||||
))
|
||||
|
|
|
@ -19,6 +19,8 @@ Revision History:
|
|||
#ifndef THEORY_DATATYPE_PARAMS_H_
|
||||
#define THEORY_DATATYPE_PARAMS_H_
|
||||
|
||||
#include "smt/params/smt_params_helper.hpp"
|
||||
|
||||
struct theory_datatype_params {
|
||||
unsigned m_dt_lazy_splits;
|
||||
|
||||
|
@ -26,11 +28,10 @@ struct theory_datatype_params {
|
|||
m_dt_lazy_splits(1) {
|
||||
}
|
||||
|
||||
#if 0
|
||||
void register_params(ini_params & p) {
|
||||
p.register_unsigned_param("dt_lazy_splits", m_dt_lazy_splits, "How lazy datatype splits are performed: 0- eager, 1- lazy for infinite types, 2- lazy");
|
||||
void updt_params(params_ref const & _p) {
|
||||
smt_params_helper p(_p);
|
||||
m_dt_lazy_splits = p.dt_lazy_splits();
|
||||
}
|
||||
#endif
|
||||
|
||||
void display(std::ostream & out) const { out << "m_dt_lazy_splits=" << m_dt_lazy_splits << std::endl; }
|
||||
};
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*++
|
||||
Copyright (c) 2018 Microsoft Corporation
|
||||
|
||||
|
@ -17,7 +16,6 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#pragma once;
|
||||
|
||||
#include "smt/smt_arith_value.h"
|
||||
#include "smt/theory_lra.h"
|
||||
|
@ -96,4 +94,10 @@ namespace smt {
|
|||
while (next != n);
|
||||
return false;
|
||||
}
|
||||
|
||||
final_check_status arith_value::final_check() {
|
||||
family_id afid = a.get_family_id();
|
||||
theory * th = m_ctx.get_theory(afid);
|
||||
return th->final_check_eh();
|
||||
}
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue