mirror of
https://github.com/Z3Prover/z3
synced 2025-04-22 16:45:31 +00:00
sync
This commit is contained in:
commit
28ff338b88
189 changed files with 5509 additions and 1556 deletions
|
@ -61,6 +61,7 @@ z3_add_component(api
|
|||
api_rcf.cpp
|
||||
api_seq.cpp
|
||||
api_solver.cpp
|
||||
api_special_relations.cpp
|
||||
api_stats.cpp
|
||||
api_tactic.cpp
|
||||
z3_replayer.cpp
|
||||
|
|
|
@ -263,6 +263,7 @@ extern "C" {
|
|||
MK_UNARY(Z3_mk_set_complement, mk_c(c)->get_array_fid(), OP_SET_COMPLEMENT, SKIP);
|
||||
MK_BINARY(Z3_mk_set_subset, mk_c(c)->get_array_fid(), OP_SET_SUBSET, SKIP);
|
||||
MK_BINARY(Z3_mk_array_ext, mk_c(c)->get_array_fid(), OP_ARRAY_EXT, SKIP);
|
||||
MK_BINARY(Z3_mk_set_has_size, mk_c(c)->get_array_fid(), OP_SET_HAS_SIZE, SKIP);
|
||||
|
||||
Z3_ast Z3_API Z3_mk_as_array(Z3_context c, Z3_func_decl f) {
|
||||
Z3_TRY;
|
||||
|
|
|
@ -1052,6 +1052,18 @@ extern "C" {
|
|||
}
|
||||
}
|
||||
|
||||
if (mk_c(c)->get_special_relations_fid() == _d->get_family_id()) {
|
||||
switch(_d->get_decl_kind()) {
|
||||
case OP_SPECIAL_RELATION_LO : return Z3_OP_SPECIAL_RELATION_LO;
|
||||
case OP_SPECIAL_RELATION_PO : return Z3_OP_SPECIAL_RELATION_PO;
|
||||
case OP_SPECIAL_RELATION_PLO: return Z3_OP_SPECIAL_RELATION_PLO;
|
||||
case OP_SPECIAL_RELATION_TO : return Z3_OP_SPECIAL_RELATION_TO;
|
||||
case OP_SPECIAL_RELATION_TC : return Z3_OP_SPECIAL_RELATION_TC;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (mk_c(c)->get_bv_fid() == _d->get_family_id()) {
|
||||
switch(_d->get_decl_kind()) {
|
||||
case OP_BV_NUM: return Z3_OP_BNUM;
|
||||
|
@ -1162,6 +1174,7 @@ extern "C" {
|
|||
case OP_SEQ_EXTRACT: return Z3_OP_SEQ_EXTRACT;
|
||||
case OP_SEQ_REPLACE: return Z3_OP_SEQ_REPLACE;
|
||||
case OP_SEQ_AT: return Z3_OP_SEQ_AT;
|
||||
case OP_SEQ_NTH: return Z3_OP_SEQ_NTH;
|
||||
case OP_SEQ_LENGTH: return Z3_OP_SEQ_LENGTH;
|
||||
case OP_SEQ_INDEX: return Z3_OP_SEQ_INDEX;
|
||||
case OP_SEQ_TO_RE: return Z3_OP_SEQ_TO_RE;
|
||||
|
@ -1191,8 +1204,8 @@ extern "C" {
|
|||
case OP_RE_UNION: return Z3_OP_RE_UNION;
|
||||
case OP_RE_INTERSECT: return Z3_OP_RE_INTERSECT;
|
||||
case OP_RE_LOOP: return Z3_OP_RE_LOOP;
|
||||
// case OP_RE_FULL_SEQ_SET: return Z3_OP_RE_FULL_SET;
|
||||
case OP_RE_FULL_CHAR_SET: return Z3_OP_RE_FULL_SET;
|
||||
case OP_RE_FULL_SEQ_SET: return Z3_OP_RE_FULL_SET;
|
||||
//case OP_RE_FULL_CHAR_SET: return Z3_OP_RE_FULL_SET;
|
||||
case OP_RE_EMPTY_SET: return Z3_OP_RE_EMPTY_SET;
|
||||
default:
|
||||
return Z3_OP_INTERNAL;
|
||||
|
|
|
@ -48,7 +48,7 @@ extern "C" {
|
|||
env_params::updt_params();
|
||||
}
|
||||
|
||||
std::string g_Z3_global_param_get_buffer;
|
||||
static std::string g_Z3_global_param_get_buffer;
|
||||
|
||||
Z3_bool_opt Z3_API Z3_global_param_get(Z3_string param_id, Z3_string_ptr param_value) {
|
||||
memory::initialize(UINT_MAX);
|
||||
|
|
|
@ -101,6 +101,7 @@ namespace api {
|
|||
m_datalog_fid = m().mk_family_id("datalog_relation");
|
||||
m_fpa_fid = m().mk_family_id("fpa");
|
||||
m_seq_fid = m().mk_family_id("seq");
|
||||
m_special_relations_fid = m().mk_family_id("special_relations");
|
||||
m_dt_plugin = static_cast<datatype_decl_plugin*>(m().get_plugin(m_dt_fid));
|
||||
|
||||
install_tactics(*this);
|
||||
|
@ -155,8 +156,6 @@ namespace api {
|
|||
m_error_code = Z3_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void context::check_searching() {
|
||||
if (m_searching) {
|
||||
set_error_code(Z3_INVALID_USAGE, "cannot use function while searching"); // TBD: error code could be fixed.
|
||||
|
@ -168,8 +167,8 @@ namespace api {
|
|||
return const_cast<char *>(m_string_buffer.c_str());
|
||||
}
|
||||
|
||||
char * context::mk_external_string(std::string const & str) {
|
||||
m_string_buffer = str;
|
||||
char * context::mk_external_string(std::string && str) {
|
||||
m_string_buffer = std::move(str);
|
||||
return const_cast<char *>(m_string_buffer.c_str());
|
||||
}
|
||||
|
||||
|
@ -466,17 +465,11 @@ extern "C" {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
Z3_API char const * Z3_get_error_msg(Z3_context c, Z3_error_code err) {
|
||||
LOG_Z3_get_error_msg(c, err);
|
||||
return _get_error_msg(c, err);
|
||||
}
|
||||
|
||||
Z3_API char const * Z3_get_error_msg_ex(Z3_context c, Z3_error_code err) {
|
||||
return Z3_get_error_msg(c, err);
|
||||
}
|
||||
|
||||
|
||||
void Z3_API Z3_set_ast_print_mode(Z3_context c, Z3_ast_print_mode mode) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_set_ast_print_mode(c, mode);
|
||||
|
|
|
@ -30,6 +30,7 @@ Revision History:
|
|||
#include "ast/dl_decl_plugin.h"
|
||||
#include "ast/fpa_decl_plugin.h"
|
||||
#include "ast/recfun_decl_plugin.h"
|
||||
#include "ast/special_relations_decl_plugin.h"
|
||||
#include "smt/smt_kernel.h"
|
||||
#include "smt/params/smt_params.h"
|
||||
#include "util/event_handler.h"
|
||||
|
@ -106,6 +107,7 @@ namespace api {
|
|||
family_id m_pb_fid;
|
||||
family_id m_fpa_fid;
|
||||
family_id m_seq_fid;
|
||||
family_id m_special_relations_fid;
|
||||
datatype_decl_plugin * m_dt_plugin;
|
||||
|
||||
std::string m_string_buffer; // temporary buffer used to cache strings sent to the "external" world.
|
||||
|
@ -162,6 +164,7 @@ namespace api {
|
|||
family_id get_fpa_fid() const { return m_fpa_fid; }
|
||||
family_id get_seq_fid() const { return m_seq_fid; }
|
||||
datatype_decl_plugin * get_dt_plugin() const { return m_dt_plugin; }
|
||||
family_id get_special_relations_fid() const { return m_special_relations_fid; }
|
||||
|
||||
Z3_error_code get_error_code() const { return m_error_code; }
|
||||
void reset_error_code();
|
||||
|
@ -179,7 +182,7 @@ namespace api {
|
|||
// Store a copy of str in m_string_buffer, and return a reference to it.
|
||||
// This method is used to communicate local/internal strings with the "external world"
|
||||
char * mk_external_string(char const * str);
|
||||
char * mk_external_string(std::string const & str);
|
||||
char * mk_external_string(std::string && str);
|
||||
|
||||
// Create a numeral of the given sort
|
||||
expr * mk_numeral_core(rational const & n, sort * s);
|
||||
|
|
|
@ -24,6 +24,7 @@ Revision History:
|
|||
#include "api/api_stats.h"
|
||||
#include "muz/fp/datalog_parser.h"
|
||||
#include "util/cancel_eh.h"
|
||||
#include "util/scoped_ctrl_c.h"
|
||||
#include "util/scoped_timer.h"
|
||||
#include "muz/fp/dl_cmds.h"
|
||||
#include "cmd_context/cmd_context.h"
|
||||
|
@ -280,11 +281,13 @@ extern "C" {
|
|||
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());
|
||||
bool use_ctrl_c = to_fixedpoint(d)->m_params.get_bool("ctrl_c", true);
|
||||
{
|
||||
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);
|
||||
scoped_ctrl_c ctrlc(eh, false, use_ctrl_c);
|
||||
try {
|
||||
r = to_fixedpoint_ref(d)->ctx().query(to_expr(q));
|
||||
}
|
||||
|
|
|
@ -160,69 +160,40 @@ extern "C" {
|
|||
LOG_Z3_mk_list_sort(c, name, elem_sort, nil_decl, is_nil_decl, cons_decl, is_cons_decl, head_decl, tail_decl);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
func_decl_ref nil(m), is_nil(m), cons(m), is_cons(m), head(m), tail(m);
|
||||
datatype_util& dt_util = mk_c(c)->dtutil();
|
||||
mk_c(c)->reset_last_result();
|
||||
datatype_util data_util(m);
|
||||
accessor_decl* head_tail[2] = {
|
||||
mk_accessor_decl(m, symbol("head"), type_ref(to_sort(elem_sort))),
|
||||
mk_accessor_decl(m, symbol("tail"), type_ref(0))
|
||||
};
|
||||
constructor_decl* constrs[2] = {
|
||||
mk_constructor_decl(symbol("nil"), symbol("is_nil"), 0, nullptr),
|
||||
// Leo: SMT 2.0 document uses 'insert' instead of cons
|
||||
mk_constructor_decl(symbol("cons"), symbol("is_cons"), 2, head_tail)
|
||||
};
|
||||
|
||||
sort_ref_vector sorts(m);
|
||||
{
|
||||
datatype_decl * decl = mk_datatype_decl(dt_util, to_symbol(name), 0, nullptr, 2, constrs);
|
||||
bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &decl, 0, nullptr, sorts);
|
||||
del_datatype_decl(decl);
|
||||
|
||||
if (!is_ok) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG, nullptr);
|
||||
RETURN_Z3(nullptr);
|
||||
}
|
||||
sort_ref s = dt_util.mk_list_datatype(to_sort(elem_sort), to_symbol(name), cons, is_cons, head, tail, nil, is_nil);
|
||||
|
||||
if (!s) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG, nullptr);
|
||||
RETURN_Z3(nullptr);
|
||||
}
|
||||
sort * s = sorts.get(0);
|
||||
|
||||
mk_c(c)->save_multiple_ast_trail(s);
|
||||
ptr_vector<func_decl> const& cnstrs = *data_util.get_datatype_constructors(s);
|
||||
SASSERT(cnstrs.size() == 2);
|
||||
func_decl* f;
|
||||
if (nil_decl) {
|
||||
f = cnstrs[0];
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*nil_decl = of_func_decl(f);
|
||||
mk_c(c)->save_multiple_ast_trail(nil);
|
||||
*nil_decl = of_func_decl(nil);
|
||||
}
|
||||
if (is_nil_decl) {
|
||||
f = data_util.get_constructor_is(cnstrs[0]);
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*is_nil_decl = of_func_decl(f);
|
||||
mk_c(c)->save_multiple_ast_trail(is_nil);
|
||||
*is_nil_decl = of_func_decl(is_nil);
|
||||
}
|
||||
if (cons_decl) {
|
||||
f = cnstrs[1];
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*cons_decl = of_func_decl(f);
|
||||
mk_c(c)->save_multiple_ast_trail(cons);
|
||||
*cons_decl = of_func_decl(cons);
|
||||
}
|
||||
if (is_cons_decl) {
|
||||
f = data_util.get_constructor_is(cnstrs[1]);
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*is_cons_decl = of_func_decl(f);
|
||||
mk_c(c)->save_multiple_ast_trail(is_cons);
|
||||
*is_cons_decl = of_func_decl(is_cons);
|
||||
}
|
||||
if (head_decl) {
|
||||
ptr_vector<func_decl> const& acc = *data_util.get_constructor_accessors(cnstrs[1]);
|
||||
SASSERT(acc.size() == 2);
|
||||
f = (acc)[0];
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*head_decl = of_func_decl(f);
|
||||
mk_c(c)->save_multiple_ast_trail(head);
|
||||
*head_decl = of_func_decl(head);
|
||||
}
|
||||
if (tail_decl) {
|
||||
ptr_vector<func_decl> const& acc = *data_util.get_constructor_accessors(cnstrs[1]);
|
||||
SASSERT(acc.size() == 2);
|
||||
f = (acc)[1];
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*tail_decl = of_func_decl(f);
|
||||
mk_c(c)->save_multiple_ast_trail(tail);
|
||||
*tail_decl = of_func_decl(tail);
|
||||
}
|
||||
RETURN_Z3_mk_list_sort(of_sort(s));
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
|
|
|
@ -189,7 +189,7 @@ extern "C" {
|
|||
std::string result = buffer.str();
|
||||
SASSERT(result.size() > 0);
|
||||
result.resize(result.size()-1);
|
||||
return mk_c(c)->mk_external_string(result);
|
||||
return mk_c(c)->mk_external_string(std::move(result));
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
|
@ -207,7 +207,7 @@ extern "C" {
|
|||
std::string result = buffer.str();
|
||||
SASSERT(result.size() > 0);
|
||||
result.resize(result.size()-1);
|
||||
return mk_c(c)->mk_external_string(result);
|
||||
return mk_c(c)->mk_external_string(std::move(result));
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include "api/z3.h"
|
||||
#include "api/api_log_macros.h"
|
||||
#include "api/api_context.h"
|
||||
|
@ -479,7 +478,7 @@ extern "C" {
|
|||
model_v2_pp(buffer, *(to_model_ref(m)), p.partial());
|
||||
result = buffer.str();
|
||||
}
|
||||
return mk_c(c)->mk_external_string(result);
|
||||
return mk_c(c)->mk_external_string(std::move(result));
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ Revision History:
|
|||
#include<iostream>
|
||||
#include "util/cancel_eh.h"
|
||||
#include "util/scoped_timer.h"
|
||||
#include "util/scoped_ctrl_c.h"
|
||||
#include "util/file_path.h"
|
||||
#include "parsers/smt2/smt2parser.h"
|
||||
#include "opt/opt_context.h"
|
||||
|
@ -148,8 +149,10 @@ extern "C" {
|
|||
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());
|
||||
unsigned rlimit = to_optimize_ptr(o)->get_params().get_uint("rlimit", mk_c(c)->get_rlimit());
|
||||
bool use_ctrl_c = to_optimize_ptr(o)->get_params().get_bool("ctrl_c", true);
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
{
|
||||
scoped_ctrl_c ctrlc(eh, false, use_ctrl_c);
|
||||
scoped_timer timer(timeout, &eh);
|
||||
scoped_rlimit _rlimit(mk_c(c)->m().limit(), rlimit);
|
||||
try {
|
||||
|
|
|
@ -34,28 +34,58 @@ extern "C" {
|
|||
// Support for SMTLIB2
|
||||
|
||||
Z3_ast_vector parse_smtlib2_stream(bool exec, Z3_context c, std::istream& is,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const sort_names[],
|
||||
Z3_sort const sorts[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_func_decl const decls[]) {
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const _sort_names[],
|
||||
Z3_sort const _sorts[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_func_decl const decls[]) {
|
||||
Z3_TRY;
|
||||
scoped_ptr<cmd_context> ctx = alloc(cmd_context, false, &(mk_c(c)->m()));
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
scoped_ptr<cmd_context> ctx = alloc(cmd_context, false, &(m));
|
||||
ctx->set_ignore_check(true);
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), m);
|
||||
|
||||
vector<symbol> sort_names;
|
||||
ptr_vector<sort> sorts;
|
||||
for (unsigned i = 0; i < num_sorts; ++i) {
|
||||
sorts.push_back(to_sort(_sorts[i]));
|
||||
sort_names.push_back(to_symbol(_sort_names[i]));
|
||||
}
|
||||
|
||||
mk_c(c)->save_object(v);
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
ctx->insert(to_symbol(decl_names[i]), to_func_decl(decls[i]));
|
||||
}
|
||||
for (unsigned i = 0; i < num_sorts; ++i) {
|
||||
sort* srt = to_sort(sorts[i]);
|
||||
symbol name(to_symbol(sort_names[i]));
|
||||
if (!ctx->find_psort_decl(name)) {
|
||||
psort* ps = ctx->pm().mk_psort_cnst(srt);
|
||||
ctx->insert(ctx->pm().mk_psort_user_decl(0, name, ps));
|
||||
func_decl* d = to_func_decl(decls[i]);
|
||||
ctx->insert(to_symbol(decl_names[i]), d);
|
||||
sort_names.push_back(d->get_range()->get_name());
|
||||
sorts.push_back(d->get_range());
|
||||
for (sort* s : *d) {
|
||||
sort_names.push_back(s->get_name());
|
||||
sorts.push_back(s);
|
||||
}
|
||||
}
|
||||
datatype_util dt(m);
|
||||
for (unsigned i = 0; i < num_sorts; ++i) {
|
||||
sort* srt = sorts[i];
|
||||
symbol name = sort_names[i];
|
||||
if (ctx->find_psort_decl(name)) {
|
||||
continue;
|
||||
}
|
||||
psort* ps = ctx->pm().mk_psort_cnst(srt);
|
||||
ctx->insert(ctx->pm().mk_psort_user_decl(0, name, ps));
|
||||
if (!dt.is_datatype(srt)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (func_decl * c : *dt.get_datatype_constructors(srt)) {
|
||||
ctx->insert(c->get_name(), c);
|
||||
func_decl * r = dt.get_constructor_recognizer(c);
|
||||
ctx->insert(r->get_name(), r);
|
||||
for (func_decl * a : *dt.get_constructor_accessors(c)) {
|
||||
ctx->insert(a->get_name(), a);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::stringstream errstrm;
|
||||
ctx->set_regular_stream(errstrm);
|
||||
try {
|
||||
|
|
|
@ -55,6 +55,20 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
||||
Z3_ast Z3_API Z3_mk_lstring(Z3_context c, unsigned sz, Z3_string str) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_string(c, str);
|
||||
RESET_ERROR_CODE();
|
||||
unsigned_vector chs;
|
||||
for (unsigned i = 0; i < sz; ++i) chs.push_back(str[i]);
|
||||
zstring s(sz, chs.c_ptr(), zstring::ascii);
|
||||
app* a = mk_c(c)->sutil().str.mk_string(s);
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_mk_string_sort(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_string_sort(c);
|
||||
|
@ -81,6 +95,32 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(false);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_get_seq_sort_basis(Z3_context c, Z3_sort s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_seq_sort_basis(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
sort* r = nullptr;
|
||||
if (!mk_c(c)->sutil().is_seq(to_sort(s), r)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG, "expected sequence sort");
|
||||
RETURN_Z3(nullptr);
|
||||
}
|
||||
RETURN_Z3(of_sort(r));
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_get_re_sort_basis(Z3_context c, Z3_sort s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_re_sort_basis(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
sort* r = nullptr;
|
||||
if (!mk_c(c)->sutil().is_re(to_sort(s), r)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG, "expected regex sort");
|
||||
RETURN_Z3(nullptr);
|
||||
}
|
||||
RETURN_Z3(of_sort(r));
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
bool Z3_API Z3_is_string_sort(Z3_context c, Z3_sort s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_is_string_sort(c, s);
|
||||
|
@ -106,8 +146,7 @@ extern "C" {
|
|||
SET_ERROR_CODE(Z3_INVALID_ARG, "expression is not a string literal");
|
||||
return "";
|
||||
}
|
||||
std::string s = str.encode();
|
||||
return mk_c(c)->mk_external_string(s);
|
||||
return mk_c(c)->mk_external_string(str.encode());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
|
@ -132,8 +171,10 @@ extern "C" {
|
|||
MK_TERNARY(Z3_mk_seq_extract, mk_c(c)->get_seq_fid(), OP_SEQ_EXTRACT, SKIP);
|
||||
MK_TERNARY(Z3_mk_seq_replace, mk_c(c)->get_seq_fid(), OP_SEQ_REPLACE, SKIP);
|
||||
MK_BINARY(Z3_mk_seq_at, mk_c(c)->get_seq_fid(), OP_SEQ_AT, SKIP);
|
||||
MK_BINARY(Z3_mk_seq_nth, mk_c(c)->get_seq_fid(), OP_SEQ_AT, SKIP);
|
||||
MK_UNARY(Z3_mk_seq_length, mk_c(c)->get_seq_fid(), OP_SEQ_LENGTH, SKIP);
|
||||
MK_TERNARY(Z3_mk_seq_index, mk_c(c)->get_seq_fid(), OP_SEQ_INDEX, SKIP);
|
||||
MK_BINARY(Z3_mk_seq_last_index, mk_c(c)->get_seq_fid(), OP_SEQ_LAST_INDEX, SKIP);
|
||||
MK_UNARY(Z3_mk_seq_to_re, mk_c(c)->get_seq_fid(), OP_SEQ_TO_RE, SKIP);
|
||||
MK_BINARY(Z3_mk_seq_in_re, mk_c(c)->get_seq_fid(), OP_SEQ_IN_RE, SKIP);
|
||||
|
||||
|
|
|
@ -31,9 +31,6 @@ Revision History:
|
|||
#include "api/api_stats.h"
|
||||
#include "api/api_ast_vector.h"
|
||||
#include "solver/tactic2solver.h"
|
||||
#include "util/scoped_ctrl_c.h"
|
||||
#include "util/cancel_eh.h"
|
||||
#include "util/scoped_timer.h"
|
||||
#include "util/file_path.h"
|
||||
#include "tactic/portfolio/smt_strategic_solver.h"
|
||||
#include "smt/smt_solver.h"
|
||||
|
@ -465,7 +462,7 @@ extern "C" {
|
|||
expr * const * _assumptions = to_exprs(assumptions);
|
||||
unsigned timeout = to_solver(s)->m_params.get_uint("timeout", mk_c(c)->get_timeout());
|
||||
unsigned rlimit = to_solver(s)->m_params.get_uint("rlimit", mk_c(c)->get_rlimit());
|
||||
bool use_ctrl_c = to_solver(s)->m_params.get_bool("ctrl_c", false);
|
||||
bool use_ctrl_c = to_solver(s)->m_params.get_bool("ctrl_c", true);
|
||||
cancel_eh<reslimit> eh(mk_c(c)->m().limit());
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
lbool result;
|
||||
|
@ -656,7 +653,7 @@ extern "C" {
|
|||
lbool result = l_undef;
|
||||
unsigned timeout = to_solver(s)->m_params.get_uint("timeout", mk_c(c)->get_timeout());
|
||||
unsigned rlimit = to_solver(s)->m_params.get_uint("rlimit", mk_c(c)->get_rlimit());
|
||||
bool use_ctrl_c = to_solver(s)->m_params.get_bool("ctrl_c", false);
|
||||
bool use_ctrl_c = to_solver(s)->m_params.get_bool("ctrl_c", true);
|
||||
cancel_eh<reslimit> eh(mk_c(c)->m().limit());
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
{
|
||||
|
@ -698,7 +695,7 @@ extern "C" {
|
|||
}
|
||||
unsigned timeout = to_solver(s)->m_params.get_uint("timeout", mk_c(c)->get_timeout());
|
||||
unsigned rlimit = to_solver(s)->m_params.get_uint("rlimit", mk_c(c)->get_rlimit());
|
||||
bool use_ctrl_c = to_solver(s)->m_params.get_bool("ctrl_c", false);
|
||||
bool use_ctrl_c = to_solver(s)->m_params.get_bool("ctrl_c", true);
|
||||
cancel_eh<reslimit> eh(mk_c(c)->m().limit());
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
{
|
||||
|
|
65
src/api/api_special_relations.cpp
Normal file
65
src/api/api_special_relations.cpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*++
|
||||
Copyright (c) 2019 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_special_relations.cpp
|
||||
|
||||
Abstract:
|
||||
Basic API for Special relations
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2019-03-25
|
||||
Ashutosh Gupta 2016
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include <iostream>
|
||||
#include "api/z3.h"
|
||||
#include "api/api_log_macros.h"
|
||||
#include "api/api_context.h"
|
||||
#include "api/api_util.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/special_relations_decl_plugin.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
|
||||
#define MK_SPECIAL_R(NAME, FID) \
|
||||
Z3_func_decl Z3_API NAME(Z3_context c, Z3_sort s, unsigned index) { \
|
||||
LOG_ ##NAME(c, s, index); \
|
||||
Z3_TRY; \
|
||||
parameter p(index); \
|
||||
sort* domain[2] = { to_sort(s), to_sort(s) }; \
|
||||
func_decl* f = mk_c(c)->m().mk_func_decl(mk_c(c)->get_special_relations_fid(), FID, 1, &p, 2, domain, mk_c(c)->m().mk_bool_sort()); \
|
||||
mk_c(c)->save_ast_trail(f); \
|
||||
RETURN_Z3(of_func_decl(f)); \
|
||||
Z3_CATCH_RETURN(nullptr); \
|
||||
}
|
||||
|
||||
MK_SPECIAL_R(Z3_mk_linear_order, OP_SPECIAL_RELATION_LO);
|
||||
MK_SPECIAL_R(Z3_mk_partial_order, OP_SPECIAL_RELATION_PO);
|
||||
MK_SPECIAL_R(Z3_mk_piecewise_linear_order, OP_SPECIAL_RELATION_PLO);
|
||||
MK_SPECIAL_R(Z3_mk_tree_order, OP_SPECIAL_RELATION_TO);
|
||||
|
||||
|
||||
#define MK_DECL(NAME, FID) \
|
||||
Z3_func_decl Z3_API NAME(Z3_context c,Z3_func_decl f) { \
|
||||
Z3_TRY; \
|
||||
LOG_ ##NAME(c, f); \
|
||||
RESET_ERROR_CODE(); \
|
||||
ast_manager & m = mk_c(c)->m(); \
|
||||
func_decl* _f = to_func_decl(f); \
|
||||
parameter param(_f); \
|
||||
sort* domain[2] = { _f->get_domain(0), _f->get_domain(1) }; \
|
||||
func_decl * d = m.mk_func_decl(mk_c(c)->get_special_relations_fid(), FID, 1, ¶m, 2, domain); \
|
||||
mk_c(c)->save_ast_trail(d); \
|
||||
RETURN_Z3(of_func_decl(d)); \
|
||||
Z3_CATCH_RETURN(nullptr); \
|
||||
}
|
||||
|
||||
MK_DECL(Z3_mk_transitive_closure, OP_SPECIAL_RELATION_TC);
|
||||
};
|
|
@ -34,7 +34,7 @@ extern "C" {
|
|||
result = buffer.str();
|
||||
SASSERT(result.size() > 0);
|
||||
result.resize(result.size()-1);
|
||||
return mk_c(c)->mk_external_string(result);
|
||||
return mk_c(c)->mk_external_string(std::move(result));
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,9 @@ extern "C" {
|
|||
RESET_ERROR_CODE();
|
||||
tactic_cmd * t = mk_c(c)->find_tactic_cmd(symbol(name));
|
||||
if (t == nullptr) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG, nullptr);
|
||||
std::stringstream err;
|
||||
err << "unknown tactic " << name;
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG, err.str().c_str());
|
||||
RETURN_Z3(nullptr);
|
||||
}
|
||||
tactic * new_t = t->mk(mk_c(c)->m());
|
||||
|
|
|
@ -633,6 +633,10 @@ namespace z3 {
|
|||
symbol name() const { Z3_symbol s = Z3_get_decl_name(ctx(), *this); check_error(); return symbol(ctx(), s); }
|
||||
Z3_decl_kind decl_kind() const { return Z3_get_decl_kind(ctx(), *this); }
|
||||
|
||||
func_decl transitive_closure(func_decl const& f) {
|
||||
Z3_func_decl tc = Z3_mk_transitive_closure(ctx(), *this); check_error(); return func_decl(ctx(), tc);
|
||||
}
|
||||
|
||||
bool is_const() const { return arity() == 0; }
|
||||
|
||||
expr operator()() const;
|
||||
|
@ -648,10 +652,17 @@ namespace z3 {
|
|||
expr operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4, expr const & a5) const;
|
||||
};
|
||||
|
||||
/**
|
||||
\brief forward declarations
|
||||
*/
|
||||
expr select(expr const & a, expr const& i);
|
||||
expr select(expr const & a, expr_vector const & i);
|
||||
|
||||
/**
|
||||
\brief A Z3 expression is used to represent formulas and terms. For Z3, a formula is any expression of sort Boolean.
|
||||
Every expression has a sort.
|
||||
*/
|
||||
|
||||
class expr : public ast {
|
||||
public:
|
||||
expr(context & c):ast(c) {}
|
||||
|
@ -996,6 +1007,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(); }
|
||||
bool is_distinct() const { return is_app() && Z3_OP_DISTINCT == decl().decl_kind(); }
|
||||
|
||||
friend expr distinct(expr_vector const& args);
|
||||
friend expr concat(expr const& a, expr const& b);
|
||||
|
@ -1135,6 +1147,12 @@ namespace z3 {
|
|||
check_error();
|
||||
return expr(ctx(), r);
|
||||
}
|
||||
expr nth(expr const& index) const {
|
||||
check_context(*this, index);
|
||||
Z3_ast r = Z3_mk_seq_nth(ctx(), *this, index);
|
||||
check_error();
|
||||
return expr(ctx(), r);
|
||||
}
|
||||
expr length() const {
|
||||
Z3_ast r = Z3_mk_seq_length(ctx(), *this);
|
||||
check_error();
|
||||
|
@ -1166,6 +1184,20 @@ namespace z3 {
|
|||
return expr(ctx(), r);
|
||||
}
|
||||
|
||||
/**
|
||||
* index operator defined on arrays and sequences.
|
||||
*/
|
||||
expr operator[](expr const& index) const {
|
||||
assert(is_array() || is_seq());
|
||||
if (is_array()) {
|
||||
return select(*this, index);
|
||||
}
|
||||
return nth(index);
|
||||
}
|
||||
|
||||
expr operator[](expr_vector const& index) const {
|
||||
return select(*this, index);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return a simplified version of this expression.
|
||||
|
@ -1679,6 +1711,19 @@ namespace z3 {
|
|||
*/
|
||||
inline expr sext(expr const & a, unsigned i) { return to_expr(a.ctx(), Z3_mk_sign_ext(a.ctx(), i, a)); }
|
||||
|
||||
inline func_decl linear_order(sort const& a, unsigned index) {
|
||||
return to_func_decl(a.ctx(), Z3_mk_linear_order(a.ctx(), a, index));
|
||||
}
|
||||
inline func_decl partial_order(sort const& a, unsigned index) {
|
||||
return to_func_decl(a.ctx(), Z3_mk_partial_order(a.ctx(), a, index));
|
||||
}
|
||||
inline func_decl piecewise_linear_order(sort const& a, unsigned index) {
|
||||
return to_func_decl(a.ctx(), Z3_mk_piecewise_linear_order(a.ctx(), a, index));
|
||||
}
|
||||
inline func_decl tree_order(sort const& a, unsigned index) {
|
||||
return to_func_decl(a.ctx(), Z3_mk_tree_order(a.ctx(), a, index));
|
||||
}
|
||||
|
||||
template<typename T> class cast_ast;
|
||||
|
||||
template<> class cast_ast<ast> {
|
||||
|
@ -2387,7 +2432,7 @@ namespace z3 {
|
|||
return *this;
|
||||
}
|
||||
void add(expr const & f) { check_context(*this, f); Z3_goal_assert(ctx(), m_goal, f); check_error(); }
|
||||
// void add(expr_vector const& v) { check_context(*this, v); for (expr e : v) add(e); }
|
||||
void add(expr_vector const& v) { check_context(*this, v); for (unsigned i = 0; i < v.size(); ++i) add(v[i]); }
|
||||
unsigned size() const { return Z3_goal_size(ctx(), m_goal); }
|
||||
expr operator[](int i) const { assert(0 <= i); Z3_ast r = Z3_goal_formula(ctx(), m_goal, i); check_error(); return expr(ctx(), r); }
|
||||
Z3_goal_prec precision() const { return Z3_goal_precision(ctx(), m_goal); }
|
||||
|
@ -3248,6 +3293,12 @@ namespace z3 {
|
|||
s.check_error();
|
||||
return expr(s.ctx(), r);
|
||||
}
|
||||
inline expr last_indexof(expr const& s, expr const& substr) {
|
||||
check_context(s, substr);
|
||||
Z3_ast r = Z3_mk_seq_last_index(s.ctx(), s, substr);
|
||||
s.check_error();
|
||||
return expr(s.ctx(), r);
|
||||
}
|
||||
inline expr to_re(expr const& s) {
|
||||
MK_EXPR1(Z3_mk_seq_to_re, s);
|
||||
}
|
||||
|
|
|
@ -38,5 +38,18 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(ctx != null);
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary> Single argument select </summary>
|
||||
public Expr this[Expr index]
|
||||
{
|
||||
get { return Context.MkSelect(this, index); }
|
||||
}
|
||||
|
||||
/// <summary> Multi argument select </summary>
|
||||
public Expr this[IEnumerable<Expr> index]
|
||||
{
|
||||
get { return Context.MkSelect(this, index.ToArray()); }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ find_package(Dotnet REQUIRED)
|
|||
set(VER_MAJOR "${Z3_VERSION_MAJOR}")
|
||||
set(VER_MINOR "${Z3_VERSION_MINOR}")
|
||||
set(VER_BUILD "${Z3_VERSION_PATCH}")
|
||||
set(VER_REVISION "${Z3_VERSION_TWEAK}")
|
||||
set(VER_TWEAK "${Z3_VERSION_TWEAK}")
|
||||
|
||||
# Generate Native.cs
|
||||
set(Z3_DOTNET_NATIVE_FILE "${CMAKE_CURRENT_BINARY_DIR}/Native.cs")
|
||||
|
|
|
@ -2079,6 +2079,7 @@ namespace Microsoft.Z3
|
|||
return Expr.Create(this, Native.Z3_mk_select_n(nCtx, a.NativeObject, AST.ArrayLength(args), AST.ArrayToNative(args)));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Array update.
|
||||
/// </summary>
|
||||
|
@ -2454,7 +2455,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Retrieve sequence of length one at index.
|
||||
/// </summary>
|
||||
public SeqExpr MkAt(SeqExpr s, IntExpr index)
|
||||
public SeqExpr MkAt(SeqExpr s, Expr index)
|
||||
{
|
||||
Debug.Assert(s != null);
|
||||
Debug.Assert(index != null);
|
||||
|
@ -2462,6 +2463,17 @@ namespace Microsoft.Z3
|
|||
return new SeqExpr(this, Native.Z3_mk_seq_at(nCtx, s.NativeObject, index.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve element at index.
|
||||
/// </summary>
|
||||
public SeqExpr MkNth(SeqExpr s, Expr index)
|
||||
{
|
||||
Debug.Assert(s != null);
|
||||
Debug.Assert(index != null);
|
||||
CheckContextMatch(s, index);
|
||||
return new SeqExpr(this, Native.Z3_mk_seq_nth(nCtx, s.NativeObject, index.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract subsequence.
|
||||
/// </summary>
|
||||
|
|
|
@ -21,11 +21,11 @@
|
|||
<Company>Microsoft Corporation</Company>
|
||||
<AssemblyCompany>Microsoft Corporation</AssemblyCompany>
|
||||
|
||||
<Version>@VER_MAJOR@.@VER_MINOR@.@VER_BUILD@.@VER_REVISION@</Version>
|
||||
<AssemblyVersion>@VER_MAJOR@.@VER_MINOR@.@VER_BUILD@.@VER_REVISION@</AssemblyVersion>
|
||||
<Version>@VER_MAJOR@.@VER_MINOR@.@VER_BUILD@.@VER_TWEAK@</Version>
|
||||
<AssemblyVersion>@VER_MAJOR@.@VER_MINOR@.@VER_BUILD@.@VER_TWEAK@</AssemblyVersion>
|
||||
|
||||
<FileVersion>@VER_MAJOR@.@VER_MINOR@.@VER_BUILD@.@VER_REVISION@</FileVersion>
|
||||
<AssemblyFileVersion>@VER_MAJOR@.@VER_MINOR@.@VER_BUILD@.@VER_REVISION@</AssemblyFileVersion>
|
||||
<FileVersion>@VER_MAJOR@.@VER_MINOR@.@VER_BUILD@.@VER_TWEAK@</FileVersion>
|
||||
<AssemblyFileVersion>@VER_MAJOR@.@VER_MINOR@.@VER_BUILD@.@VER_TWEAK@</AssemblyFileVersion>
|
||||
|
||||
<PackageVersion>${DOTNET_PACKAGE_VERSION}</PackageVersion>
|
||||
<PackageTags>smt constraint solver theorem prover</PackageTags>
|
||||
|
|
10
src/api/dotnet/Microsoft.Z3.targets.in
Normal file
10
src/api/dotnet/Microsoft.Z3.targets.in
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<None Include="$(MSBuildThisFileDirectory)..\runtimes\win-x64\native\libz3.dll">
|
||||
<Visible>false</Visible>
|
||||
<Link>libz3.dll</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -53,6 +53,47 @@ namespace Microsoft.Z3
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets parameter on the optimize solver
|
||||
/// </summary>
|
||||
public void Set(string name, bool value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
/// <summary>
|
||||
/// Sets parameter on the optimize solver
|
||||
/// </summary>
|
||||
public void Set(string name, uint value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
/// <summary>
|
||||
/// Sets parameter on the optimize solver
|
||||
/// </summary>
|
||||
public void Set(string name, double value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
/// <summary>
|
||||
/// Sets parameter on the optimize solver
|
||||
/// </summary>
|
||||
public void Set(string name, string value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
/// <summary>
|
||||
/// Sets parameter on the optimize solver
|
||||
/// </summary>
|
||||
public void Set(string name, Symbol value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
/// <summary>
|
||||
/// Sets parameter on the optimize solver
|
||||
/// </summary>
|
||||
public void Set(Symbol name, bool value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
/// <summary>
|
||||
/// Sets parameter on the optimize solver
|
||||
/// </summary>
|
||||
public void Set(Symbol name, uint value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
/// <summary>
|
||||
/// Sets parameter on the optimize solver
|
||||
/// </summary>
|
||||
public void Set(Symbol name, double value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
/// <summary>
|
||||
/// Sets parameter on the optimize solver
|
||||
/// </summary>
|
||||
public void Set(Symbol name, string value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
/// <summary>
|
||||
/// Sets parameter on the optimize solver
|
||||
/// </summary>
|
||||
public void Set(Symbol name, Symbol value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves parameter descriptions for Optimize solver.
|
||||
/// </summary>
|
||||
|
|
|
@ -34,5 +34,5 @@ using System.Security.Permissions;
|
|||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("4.2.0.0")]
|
||||
[assembly: AssemblyVersion("@VER_MAJOR@.@VER_MINOR@.@VER_BUILD@.@VER_REVISION@")]
|
||||
[assembly: AssemblyFileVersion("@VER_MAJOR@.@VER_MINOR@.@VER_BUILD@.@VER_REVISION@")]
|
||||
[assembly: AssemblyVersion("@VER_MAJOR@.@VER_MINOR@.@VER_BUILD@.@VER_TWEAK@")]
|
||||
[assembly: AssemblyFileVersion("@VER_MAJOR@.@VER_MINOR@.@VER_BUILD@.@VER_TWEAK@")]
|
||||
|
|
|
@ -38,5 +38,11 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(ctx != null);
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary> Access the nth element of a sequence </summary>
|
||||
public Expr this[Expr index]
|
||||
{
|
||||
get { return Context.MkNth(this, index); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -717,7 +717,7 @@ struct
|
|||
else
|
||||
mk_exists ctx sorts names body weight patterns nopatterns quantifier_id skolem_id
|
||||
|
||||
let mk_quantifier (ctx:context) (universal:bool) (bound_constants:expr list) (body:expr) (weight:int option) (patterns:Pattern.pattern list) (nopatterns:expr list) (quantifier_id:Symbol.symbol option) (skolem_id:Symbol.symbol option) =
|
||||
let mk_quantifier_const (ctx:context) (universal:bool) (bound_constants:expr list) (body:expr) (weight:int option) (patterns:Pattern.pattern list) (nopatterns:expr list) (quantifier_id:Symbol.symbol option) (skolem_id:Symbol.symbol option) =
|
||||
if universal then
|
||||
mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id
|
||||
else
|
||||
|
|
|
@ -743,10 +743,10 @@ sig
|
|||
val mk_lambda : context -> (Symbol.symbol * Sort.sort) list -> Expr.expr -> quantifier
|
||||
|
||||
(** Create a Quantifier. *)
|
||||
val mk_quantifier : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier
|
||||
val mk_quantifier : context -> bool -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier
|
||||
|
||||
(** Create a Quantifier. *)
|
||||
val mk_quantifier : context -> bool -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier
|
||||
val mk_quantifier_const : context -> bool -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier
|
||||
|
||||
(** A string representation of the quantifier. *)
|
||||
val to_string : quantifier -> string
|
||||
|
|
|
@ -609,6 +609,10 @@ def _to_sort_ref(s, ctx):
|
|||
return FPSortRef(s, ctx)
|
||||
elif k == Z3_ROUNDING_MODE_SORT:
|
||||
return FPRMSortRef(s, ctx)
|
||||
elif k == Z3_RE_SORT:
|
||||
return ReSortRef(s, ctx)
|
||||
elif k == Z3_SEQ_SORT:
|
||||
return SeqSortRef(s, ctx)
|
||||
return SortRef(s, ctx)
|
||||
|
||||
def _sort(ctx, a):
|
||||
|
@ -3837,7 +3841,7 @@ def Extract(high, low, a):
|
|||
>>> Extract(6, 2, x).sort()
|
||||
BitVec(5)
|
||||
>>> simplify(Extract(StringVal("abcd"),2,1))
|
||||
c
|
||||
"c"
|
||||
"""
|
||||
if isinstance(high, str):
|
||||
high = StringVal(high)
|
||||
|
@ -4500,6 +4504,11 @@ def Ext(a, b):
|
|||
_z3_assert(is_array(a) and is_array(b), "arguments must be arrays")
|
||||
return _to_expr_ref(Z3_mk_array_ext(ctx.ref(), a.as_ast(), b.as_ast()), ctx)
|
||||
|
||||
def SetHasSize(a, k):
|
||||
ctx = a.ctx
|
||||
k = _py2expr(k, ctx)
|
||||
return _to_expr_ref(Z3_mk_set_has_size(ctx.ref(), a.as_ast(), k.as_ast()), ctx)
|
||||
|
||||
def is_select(a):
|
||||
"""Return `True` if `a` is a Z3 array select application.
|
||||
|
||||
|
@ -4933,6 +4942,29 @@ class DatatypeRef(ExprRef):
|
|||
"""Return the datatype sort of the datatype expression `self`."""
|
||||
return DatatypeSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx)
|
||||
|
||||
def TupleSort(name, sorts, ctx = None):
|
||||
"""Create a named tuple sort base on a set of underlying sorts
|
||||
Example:
|
||||
>>> pair, mk_pair, (first, second) = TupleSort("pair", [IntSort(), StringSort()])
|
||||
"""
|
||||
tuple = Datatype(name, ctx)
|
||||
projects = [ ('project%d' % i, sorts[i]) for i in range(len(sorts)) ]
|
||||
tuple.declare(name, *projects)
|
||||
tuple = tuple.create()
|
||||
return tuple, tuple.constructor(0), [tuple.accessor(0, i) for i in range(len(sorts))]
|
||||
|
||||
def DisjointSum(name, sorts, ctx=None):
|
||||
"""Create a named tagged union sort base on a set of underlying sorts
|
||||
Example:
|
||||
>>> sum, ((inject0, extract0), (inject1, extract1)) = DisjointSum("+", [IntSort(), StringSort()])
|
||||
"""
|
||||
sum = Datatype(name, ctx)
|
||||
for i in range(len(sorts)):
|
||||
sum.declare("inject%d" % i, ("project%d" % i, sorts[i]))
|
||||
sum = sum.create()
|
||||
return sum, [(sum.constructor(i), sum.accessor(i, 0)) for i in range(len(sorts))]
|
||||
|
||||
|
||||
def EnumSort(name, values, ctx=None):
|
||||
"""Return a new enumeration sort named `name` containing the given values.
|
||||
|
||||
|
@ -9908,6 +9940,9 @@ class SeqSortRef(SortRef):
|
|||
False
|
||||
"""
|
||||
return Z3_is_string_sort(self.ctx_ref(), self.ast)
|
||||
|
||||
def basis(self):
|
||||
return _to_sort_ref(Z3_get_seq_sort_basis(self.ctx_ref(), self.ast), self.ctx)
|
||||
|
||||
|
||||
def StringSort(ctx=None):
|
||||
|
@ -9941,6 +9976,11 @@ class SeqRef(ExprRef):
|
|||
return Concat(other, self)
|
||||
|
||||
def __getitem__(self, i):
|
||||
if _is_int(i):
|
||||
i = IntVal(i, self.ctx)
|
||||
return SeqRef(Z3_mk_seq_nth(self.ctx_ref(), self.as_ast(), i.as_ast()), self.ctx)
|
||||
|
||||
def at(self, i):
|
||||
if _is_int(i):
|
||||
i = IntVal(i, self.ctx)
|
||||
return SeqRef(Z3_mk_seq_at(self.ctx_ref(), self.as_ast(), i.as_ast()), self.ctx)
|
||||
|
@ -10006,7 +10046,7 @@ def is_string_value(a):
|
|||
def StringVal(s, ctx=None):
|
||||
"""create a string expression"""
|
||||
ctx = _get_ctx(ctx)
|
||||
return SeqRef(Z3_mk_string(ctx.ref(), s), ctx)
|
||||
return SeqRef(Z3_mk_lstring(ctx.ref(), len(s), s), ctx)
|
||||
|
||||
def String(name, ctx=None):
|
||||
"""Return a string constant named `name`. If `ctx=None`, then the global context is used.
|
||||
|
@ -10039,10 +10079,10 @@ def Empty(s):
|
|||
True
|
||||
>>> e3 = Empty(SeqSort(IntSort()))
|
||||
>>> print(e3)
|
||||
seq.empty
|
||||
Empty(Seq(Int))
|
||||
>>> e4 = Empty(ReSort(SeqSort(IntSort())))
|
||||
>>> print(e4)
|
||||
re.empty
|
||||
Empty(ReSort(Seq(Int)))
|
||||
"""
|
||||
if isinstance(s, SeqSortRef):
|
||||
return SeqRef(Z3_mk_seq_empty(s.ctx_ref(), s.ast), s.ctx)
|
||||
|
@ -10054,10 +10094,10 @@ def Full(s):
|
|||
"""Create the regular expression that accepts the universal language
|
||||
>>> e = Full(ReSort(SeqSort(IntSort())))
|
||||
>>> print(e)
|
||||
re.all
|
||||
Full(ReSort(Seq(Int)))
|
||||
>>> e1 = Full(ReSort(StringSort()))
|
||||
>>> print(e1)
|
||||
re.all
|
||||
Full(ReSort(String))
|
||||
"""
|
||||
if isinstance(s, ReSortRef):
|
||||
return ReRef(Z3_mk_re_full(s.ctx_ref(), s.ast), s.ctx)
|
||||
|
@ -10119,7 +10159,7 @@ def Replace(s, src, dst):
|
|||
"""Replace the first occurrence of 'src' by 'dst' in 's'
|
||||
>>> r = Replace("aaa", "a", "b")
|
||||
>>> simplify(r)
|
||||
baa
|
||||
"baa"
|
||||
"""
|
||||
ctx = _get_ctx2(dst, s)
|
||||
if ctx is None and is_expr(src):
|
||||
|
@ -10147,7 +10187,16 @@ def IndexOf(s, substr, offset):
|
|||
substr = _coerce_seq(substr, ctx)
|
||||
if _is_int(offset):
|
||||
offset = IntVal(offset, ctx)
|
||||
return SeqRef(Z3_mk_seq_index(s.ctx_ref(), s.as_ast(), substr.as_ast(), offset.as_ast()), s.ctx)
|
||||
return ArithRef(Z3_mk_seq_index(s.ctx_ref(), s.as_ast(), substr.as_ast(), offset.as_ast()), s.ctx)
|
||||
|
||||
def LastIndexOf(s, substr):
|
||||
"""Retrieve the last index of substring within a string"""
|
||||
ctx = None
|
||||
ctx = _get_ctx2(s, substr, ctx)
|
||||
s = _coerce_seq(s, ctx)
|
||||
substr = _coerce_seq(substr, ctx)
|
||||
return ArithRef(Z3_mk_seq_last_index(s.ctx_ref(), s.as_ast(), substr.as_ast()), s.ctx)
|
||||
|
||||
|
||||
def Length(s):
|
||||
"""Obtain the length of a sequence 's'
|
||||
|
@ -10198,6 +10247,8 @@ def Re(s, ctx=None):
|
|||
class ReSortRef(SortRef):
|
||||
"""Regular expression sort."""
|
||||
|
||||
def basis(self):
|
||||
return _to_sort_ref(Z3_get_re_sort_basis(self.ctx_ref(), self.ast), self.ctx)
|
||||
|
||||
def ReSort(s):
|
||||
if is_ast(s):
|
||||
|
@ -10214,7 +10265,6 @@ class ReRef(ExprRef):
|
|||
def __add__(self, other):
|
||||
return Union(self, other)
|
||||
|
||||
|
||||
def is_re(s):
|
||||
return isinstance(s, ReRef)
|
||||
|
||||
|
@ -10251,6 +10301,23 @@ def Union(*args):
|
|||
v[i] = args[i].as_ast()
|
||||
return ReRef(Z3_mk_re_union(ctx.ref(), sz, v), ctx)
|
||||
|
||||
def Intersect(*args):
|
||||
"""Create intersection of regular expressions.
|
||||
>>> re = Intersect(Re("a"), Re("b"), Re("c"))
|
||||
"""
|
||||
args = _get_args(args)
|
||||
sz = len(args)
|
||||
if __debug__:
|
||||
_z3_assert(sz > 0, "At least one argument expected.")
|
||||
_z3_assert(all([is_re(a) for a in args]), "All arguments must be regular expressions.")
|
||||
if sz == 1:
|
||||
return args[0]
|
||||
ctx = args[0].ctx
|
||||
v = (Ast * sz)()
|
||||
for i in range(sz):
|
||||
v[i] = args[i].as_ast()
|
||||
return ReRef(Z3_mk_re_intersect(ctx.ref(), sz, v), ctx)
|
||||
|
||||
def Plus(re):
|
||||
"""Create the regular expression accepting one or more repetitions of argument.
|
||||
>>> re = Plus(Re("a"))
|
||||
|
@ -10302,3 +10369,37 @@ def Loop(re, lo, hi=0):
|
|||
False
|
||||
"""
|
||||
return ReRef(Z3_mk_re_loop(re.ctx_ref(), re.as_ast(), lo, hi), re.ctx)
|
||||
|
||||
def Range(lo, hi, ctx = None):
|
||||
"""Create the range regular expression over two sequences of length 1
|
||||
>>> range = Range("a","z")
|
||||
>>> print(simplify(InRe("b", range)))
|
||||
True
|
||||
>>> print(simplify(InRe("bb", range)))
|
||||
False
|
||||
"""
|
||||
lo = _coerce_seq(lo, ctx)
|
||||
hi = _coerce_seq(hi, ctx)
|
||||
return ReRef(Z3_mk_re_range(lo.ctx_ref(), lo.ast, hi.ast), lo.ctx)
|
||||
|
||||
# Special Relations
|
||||
|
||||
def PartialOrder(a, index):
|
||||
return FuncDeclRef(Z3_mk_partial_order(a.ctx_ref(), a.ast, index), a.ctx);
|
||||
|
||||
def LinearOrder(a, index):
|
||||
return FuncDeclRef(Z3_mk_linear_order(a.ctx_ref(), a.ast, index), a.ctx);
|
||||
|
||||
def TreeOrder(a, index):
|
||||
return FuncDeclRef(Z3_mk_tree_order(a.ctx_ref(), a.ast, index), a.ctx);
|
||||
|
||||
def PiecewiseLinearOrder(a, index):
|
||||
return FuncDeclRef(Z3_mk_piecewise_linear_order(a.ctx_ref(), a.ast, index), a.ctx);
|
||||
|
||||
def TransitiveClosure(f):
|
||||
"""Given a binary relation R, such that the two arguments have the same sort
|
||||
create the transitive closure relation R+.
|
||||
The transitive closure R+ is a new relation.
|
||||
"""
|
||||
return FuncDeclRef(Z3_mk_transitive_closure(f.ctx_ref(), f.ast), f.ctx)
|
||||
|
||||
|
|
|
@ -36,7 +36,15 @@ _z3_op_to_str = {
|
|||
Z3_OP_CONCAT : 'Concat', Z3_OP_EXTRACT : 'Extract', Z3_OP_BV2INT : 'BV2Int',
|
||||
Z3_OP_ARRAY_MAP : 'Map', Z3_OP_SELECT : 'Select', Z3_OP_STORE : 'Store',
|
||||
Z3_OP_CONST_ARRAY : 'K', Z3_OP_ARRAY_EXT : 'Ext',
|
||||
Z3_OP_PB_AT_MOST : 'AtMost', Z3_OP_PB_LE : 'PbLe', Z3_OP_PB_GE : 'PbGe', Z3_OP_PB_EQ : 'PbEq'
|
||||
Z3_OP_PB_AT_MOST : 'AtMost', Z3_OP_PB_LE : 'PbLe', Z3_OP_PB_GE : 'PbGe', Z3_OP_PB_EQ : 'PbEq',
|
||||
Z3_OP_SEQ_CONCAT : 'Concat', Z3_OP_SEQ_PREFIX : 'PrefixOf', Z3_OP_SEQ_SUFFIX : 'SuffixOf',
|
||||
Z3_OP_SEQ_UNIT : 'Unit', Z3_OP_SEQ_CONTAINS : 'Contains' , Z3_OP_SEQ_REPLACE : 'Replace',
|
||||
Z3_OP_SEQ_AT : 'At', Z3_OP_SEQ_NTH : 'Nth', Z3_OP_SEQ_INDEX : 'IndexOf',
|
||||
Z3_OP_SEQ_LAST_INDEX : 'LastIndexOf', Z3_OP_SEQ_LENGTH : 'Length', Z3_OP_STR_TO_INT : 'StrToInt', Z3_OP_INT_TO_STR : 'IntToStr',
|
||||
Z3_OP_SEQ_IN_RE : 'InRe', Z3_OP_SEQ_TO_RE : 'Re',
|
||||
Z3_OP_RE_PLUS : 'Plus', Z3_OP_RE_STAR : 'Star', Z3_OP_RE_OPTION : 'Option', Z3_OP_RE_UNION : 'Union', Z3_OP_RE_RANGE : 'Range',
|
||||
Z3_OP_RE_INTERSECT : 'Intersect', Z3_OP_RE_COMPLEMENT : 'Complement',
|
||||
|
||||
}
|
||||
|
||||
# List of infix operators
|
||||
|
@ -486,7 +494,7 @@ class PP:
|
|||
|
||||
def pp(self, f, indent):
|
||||
if isinstance(f, str):
|
||||
sef.pp_string(f, indent)
|
||||
self.pp_string(f, indent)
|
||||
elif f.is_string():
|
||||
self.pp_string(f, indent)
|
||||
elif f.is_indent():
|
||||
|
@ -558,10 +566,23 @@ class Formatter:
|
|||
return seq1('BitVec', (to_format(s.size()), ))
|
||||
elif isinstance(s, z3.FPSortRef):
|
||||
return seq1('FPSort', (to_format(s.ebits()), to_format(s.sbits())))
|
||||
elif isinstance(s, z3.ReSortRef):
|
||||
return seq1('ReSort', (self.pp_sort(s.basis()), ))
|
||||
elif isinstance(s, z3.SeqSortRef):
|
||||
if s.is_string():
|
||||
return to_format("String")
|
||||
return seq1('Seq', (self.pp_sort(s.basis()), ))
|
||||
else:
|
||||
return to_format(s.name())
|
||||
|
||||
def pp_const(self, a):
|
||||
k = a.decl().kind()
|
||||
if k == Z3_OP_RE_EMPTY_SET:
|
||||
return self.pp_set("Empty", a)
|
||||
elif k == Z3_OP_SEQ_EMPTY:
|
||||
return self.pp_set("Empty", a)
|
||||
elif k == Z3_OP_RE_FULL_SET:
|
||||
return self.pp_set("Full", a)
|
||||
return self.pp_name(a)
|
||||
|
||||
def pp_int(self, a):
|
||||
|
@ -577,7 +598,7 @@ class Formatter:
|
|||
return to_format(a.as_decimal(self.precision))
|
||||
|
||||
def pp_string(self, a):
|
||||
return to_format(a.as_string())
|
||||
return to_format("\"" + a.as_string() + "\"")
|
||||
|
||||
def pp_bv(self, a):
|
||||
return to_format(a.as_string())
|
||||
|
@ -842,6 +863,17 @@ class Formatter:
|
|||
arg = self.pp_expr(a.arg(0), d+1, xs)
|
||||
return seq1(self.pp_name(a), [ to_format(h), to_format(l), arg ])
|
||||
|
||||
def pp_loop(self, a, d, xs):
|
||||
l = Z3_get_decl_int_parameter(a.ctx_ref(), a.decl().ast, 0)
|
||||
arg = self.pp_expr(a.arg(0), d+1, xs)
|
||||
if Z3_get_decl_num_parameters(a.ctx_ref(), a.decl().ast) > 1:
|
||||
h = Z3_get_decl_int_parameter(a.ctx_ref(), a.decl().ast, 1)
|
||||
return seq1("Loop", [ arg, to_format(l), to_format(h) ])
|
||||
return seq1("Loop", [ arg, to_format(l) ])
|
||||
|
||||
def pp_set(self, id, a):
|
||||
return seq1(id, [self.pp_sort(a.sort())])
|
||||
|
||||
def pp_pattern(self, a, d, xs):
|
||||
if a.num_args() == 1:
|
||||
return self.pp_expr(a.arg(0), d, xs)
|
||||
|
@ -918,6 +950,8 @@ class Formatter:
|
|||
return self.pp_unary_param(a, d, xs)
|
||||
elif k == Z3_OP_EXTRACT:
|
||||
return self.pp_extract(a, d, xs)
|
||||
elif k == Z3_OP_RE_LOOP:
|
||||
return self.pp_loop(a, d, xs)
|
||||
elif k == Z3_OP_DT_IS:
|
||||
return self.pp_is(a, d, xs)
|
||||
elif k == Z3_OP_ARRAY_MAP:
|
||||
|
|
121
src/api/z3_api.h
121
src/api/z3_api.h
|
@ -875,6 +875,18 @@ typedef enum
|
|||
- Z3_OP_PB_EQ: Generalized Pseudo-Boolean equality constraint.
|
||||
Example 2*x + 1*y + 2*z + 1*u = 4
|
||||
|
||||
- Z3_OP_SPECIAL_RELATION_LO: A relation that is a total linear order
|
||||
|
||||
- Z3_OP_SPECIAL_RELATION_PO: A relation that is a partial order
|
||||
|
||||
- Z3_OP_SPECIAL_RELATION_PLO: A relation that is a piecewise linear order
|
||||
|
||||
- Z3_OP_SPECIAL_RELATION_TO: A relation that is a tree order
|
||||
|
||||
- Z3_OP_SPECIAL_RELATION_TC: Transitive closure of a relation
|
||||
|
||||
- Z3_OP_SPECIAL_RELATION_TRC: Transitive reflexive closure of a relation
|
||||
|
||||
- Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN: Floating-point rounding mode RNE
|
||||
|
||||
- Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY: Floating-point rounding mode RNA
|
||||
|
@ -1168,8 +1180,10 @@ typedef enum {
|
|||
Z3_OP_SEQ_EXTRACT,
|
||||
Z3_OP_SEQ_REPLACE,
|
||||
Z3_OP_SEQ_AT,
|
||||
Z3_OP_SEQ_NTH,
|
||||
Z3_OP_SEQ_LENGTH,
|
||||
Z3_OP_SEQ_INDEX,
|
||||
Z3_OP_SEQ_LAST_INDEX,
|
||||
Z3_OP_SEQ_TO_RE,
|
||||
Z3_OP_SEQ_IN_RE,
|
||||
|
||||
|
@ -1208,8 +1222,17 @@ typedef enum {
|
|||
Z3_OP_PB_GE,
|
||||
Z3_OP_PB_EQ,
|
||||
|
||||
// Special relations
|
||||
Z3_OP_SPECIAL_RELATION_LO = 0xa000,
|
||||
Z3_OP_SPECIAL_RELATION_PO,
|
||||
Z3_OP_SPECIAL_RELATION_PLO,
|
||||
Z3_OP_SPECIAL_RELATION_TO,
|
||||
Z3_OP_SPECIAL_RELATION_TC,
|
||||
Z3_OP_SPECIAL_RELATION_TRC,
|
||||
|
||||
|
||||
// Floating-Point Arithmetic
|
||||
Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN,
|
||||
Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN = 0xb000,
|
||||
Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY,
|
||||
Z3_OP_FPA_RM_TOWARD_POSITIVE,
|
||||
Z3_OP_FPA_RM_TOWARD_NEGATIVE,
|
||||
|
@ -3083,6 +3106,14 @@ extern "C" {
|
|||
def_API('Z3_mk_as_array', AST, (_in(CONTEXT), _in(FUNC_DECL)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_as_array(Z3_context c, Z3_func_decl f);
|
||||
|
||||
/**
|
||||
\brief Create predicate that holds if Boolean array \c set has \c k elements set to true.
|
||||
|
||||
def_API('Z3_mk_set_has_size', AST, (_in(CONTEXT), _in(AST), _in(AST)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_set_has_size(Z3_context c, Z3_ast set, Z3_ast k);
|
||||
|
||||
/*@}*/
|
||||
|
||||
/** @name Sets */
|
||||
|
@ -3290,6 +3321,13 @@ extern "C" {
|
|||
*/
|
||||
bool Z3_API Z3_is_seq_sort(Z3_context c, Z3_sort s);
|
||||
|
||||
/**
|
||||
\brief Retrieve basis sort for sequence sort.
|
||||
|
||||
def_API('Z3_get_seq_sort_basis', SORT, (_in(CONTEXT), _in(SORT)))
|
||||
*/
|
||||
Z3_sort Z3_API Z3_get_seq_sort_basis(Z3_context c, Z3_sort s);
|
||||
|
||||
/**
|
||||
\brief Create a regular expression sort out of a sequence sort.
|
||||
|
||||
|
@ -3304,6 +3342,13 @@ extern "C" {
|
|||
*/
|
||||
bool Z3_API Z3_is_re_sort(Z3_context c, Z3_sort s);
|
||||
|
||||
/**
|
||||
\brief Retrieve basis sort for regex sort.
|
||||
|
||||
def_API('Z3_get_re_sort_basis', SORT, (_in(CONTEXT), _in(SORT)))
|
||||
*/
|
||||
Z3_sort Z3_API Z3_get_re_sort_basis(Z3_context c, Z3_sort s);
|
||||
|
||||
/**
|
||||
\brief Create a sort for 8 bit strings.
|
||||
|
||||
|
@ -3327,6 +3372,15 @@ extern "C" {
|
|||
*/
|
||||
Z3_ast Z3_API Z3_mk_string(Z3_context c, Z3_string s);
|
||||
|
||||
/**
|
||||
\brief Create a string constant out of the string that is passed in
|
||||
It takes the length of the string as well to take into account
|
||||
0 characters.
|
||||
|
||||
def_API('Z3_mk_lstring' ,AST ,(_in(CONTEXT), _in(UINT), _in(STRING)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_lstring(Z3_context c, unsigned len, Z3_string s);
|
||||
|
||||
/**
|
||||
\brief Determine if \c s is a string constant.
|
||||
|
||||
|
@ -3411,11 +3465,20 @@ extern "C" {
|
|||
|
||||
/**
|
||||
\brief Retrieve from \c s the unit sequence positioned at position \c index.
|
||||
The sequence is empty if the index is out of bounds.
|
||||
|
||||
def_API('Z3_mk_seq_at' ,AST ,(_in(CONTEXT), _in(AST), _in(AST)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_seq_at(Z3_context c, Z3_ast s, Z3_ast index);
|
||||
|
||||
/**
|
||||
\brief Retrieve from \c s the element positioned at position \c index.
|
||||
The function is under-specified if the index is out of bounds.
|
||||
|
||||
def_API('Z3_mk_seq_nth' ,AST ,(_in(CONTEXT), _in(AST), _in(AST)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_seq_nth(Z3_context c, Z3_ast s, Z3_ast index);
|
||||
|
||||
/**
|
||||
\brief Return the length of the sequence \c s.
|
||||
|
||||
|
@ -3427,12 +3490,19 @@ extern "C" {
|
|||
/**
|
||||
\brief Return index of first occurrence of \c substr in \c s starting from offset \c offset.
|
||||
If \c s does not contain \c substr, then the value is -1, if \c offset is the length of \c s, then the value is -1 as well.
|
||||
The function is under-specified if \c offset is negative or larger than the length of \c s.
|
||||
The value is -1 if \c offset is negative or larger than the length of \c s.
|
||||
|
||||
def_API('Z3_mk_seq_index' ,AST ,(_in(CONTEXT), _in(AST), _in(AST), _in(AST)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_seq_index(Z3_context c, Z3_ast s, Z3_ast substr, Z3_ast offset);
|
||||
|
||||
/**
|
||||
\brief Return the last occurrence of \c substr in \c s.
|
||||
If \c s does not contain \c substr, then the value is -1,
|
||||
def_API('Z3_mk_seq_last_index', AST, (_in(CONTEXT), _in(AST), _in(AST)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_seq_last_index(Z3_context c, Z3_ast, Z3_ast substr);
|
||||
|
||||
/**
|
||||
\brief Convert string to integer.
|
||||
|
||||
|
@ -3554,10 +3624,55 @@ extern "C" {
|
|||
*/
|
||||
Z3_ast Z3_API Z3_mk_re_full(Z3_context c, Z3_sort re);
|
||||
|
||||
|
||||
/*@}*/
|
||||
|
||||
|
||||
/** @name Special relations */
|
||||
/*@{*/
|
||||
/**
|
||||
\brief declare \c a and \c b are in linear order over a relation indexed by \c id.
|
||||
|
||||
\pre a and b are of same type.
|
||||
|
||||
|
||||
def_API('Z3_mk_linear_order', FUNC_DECL ,(_in(CONTEXT), _in(SORT), _in(UINT)))
|
||||
*/
|
||||
Z3_func_decl Z3_API Z3_mk_linear_order(Z3_context c, Z3_sort a, unsigned id);
|
||||
|
||||
/**
|
||||
\brief create a partial ordering relation over signature \c a and index \c id.
|
||||
|
||||
def_API('Z3_mk_partial_order', FUNC_DECL ,(_in(CONTEXT), _in(SORT), _in(UINT)))
|
||||
*/
|
||||
Z3_func_decl Z3_API Z3_mk_partial_order(Z3_context c, Z3_sort a, unsigned id);
|
||||
|
||||
/**
|
||||
\brief create a piecewise linear ordering relation over signature \c a and index \c id.
|
||||
|
||||
def_API('Z3_mk_piecewise_linear_order', FUNC_DECL ,(_in(CONTEXT), _in(SORT), _in(UINT)))
|
||||
*/
|
||||
Z3_func_decl Z3_API Z3_mk_piecewise_linear_order(Z3_context c, Z3_sort a, unsigned id);
|
||||
|
||||
/**
|
||||
\brief create a tree ordering lreation over signature \c a identified using index \c id.
|
||||
|
||||
def_API('Z3_mk_tree_order', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT)))
|
||||
*/
|
||||
Z3_func_decl Z3_API Z3_mk_tree_order(Z3_context c, Z3_sort a, unsigned id);
|
||||
|
||||
/**
|
||||
\brief create transitive closure of binary relation.
|
||||
|
||||
\pre f is a binary relation, such that the two arguments have the same sorts.
|
||||
|
||||
The resulting relation f+ represents the transitive closure of f.
|
||||
|
||||
def_API('Z3_mk_transitive_closure', FUNC_DECL ,(_in(CONTEXT), _in(FUNC_DECL)))
|
||||
*/
|
||||
Z3_func_decl Z3_API Z3_mk_transitive_closure(Z3_context c, Z3_func_decl f);
|
||||
|
||||
/*@}*/
|
||||
|
||||
/** @name Quantifiers */
|
||||
/*@{*/
|
||||
/**
|
||||
|
|
|
@ -41,6 +41,7 @@ z3_add_component(ast
|
|||
reg_decl_plugins.cpp
|
||||
seq_decl_plugin.cpp
|
||||
shared_occs.cpp
|
||||
special_relations_decl_plugin.cpp
|
||||
static_features.cpp
|
||||
used_vars.cpp
|
||||
well_sorted.cpp
|
||||
|
|
|
@ -21,6 +21,7 @@ Revision History:
|
|||
#include "util/warning.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
|
||||
array_decl_plugin::array_decl_plugin():
|
||||
m_store_sym("store"),
|
||||
|
@ -34,7 +35,8 @@ array_decl_plugin::array_decl_plugin():
|
|||
m_set_complement_sym("complement"),
|
||||
m_set_subset_sym("subset"),
|
||||
m_array_ext_sym("array-ext"),
|
||||
m_as_array_sym("as-array") {
|
||||
m_as_array_sym("as-array"),
|
||||
m_set_has_size_sym("set-has-size") {
|
||||
}
|
||||
|
||||
#define ARRAY_SORT_STR "Array"
|
||||
|
@ -141,7 +143,7 @@ func_decl * array_decl_plugin::mk_map(func_decl* f, unsigned arity, sort* const*
|
|||
std::ostringstream buffer;
|
||||
buffer << "map expects to take as many arguments as the function being mapped, "
|
||||
<< "it was given " << arity << " but expects " << f->get_arity();
|
||||
m_manager->raise_exception(buffer.str().c_str());
|
||||
m_manager->raise_exception(buffer.str());
|
||||
return nullptr;
|
||||
}
|
||||
if (arity == 0) {
|
||||
|
@ -158,14 +160,14 @@ func_decl * array_decl_plugin::mk_map(func_decl* f, unsigned arity, sort* const*
|
|||
if (!is_array_sort(domain[i])) {
|
||||
std::ostringstream buffer;
|
||||
buffer << "map expects an array sort as argument at position " << i;
|
||||
m_manager->raise_exception(buffer.str().c_str());
|
||||
m_manager->raise_exception(buffer.str());
|
||||
return nullptr;
|
||||
}
|
||||
if (get_array_arity(domain[i]) != dom_arity) {
|
||||
std::ostringstream buffer;
|
||||
buffer << "map expects all arguments to have the same array domain, "
|
||||
<< "this is not the case for argument " << i;
|
||||
m_manager->raise_exception(buffer.str().c_str());
|
||||
m_manager->raise_exception(buffer.str());
|
||||
return nullptr;
|
||||
}
|
||||
for (unsigned j = 0; j < dom_arity; ++j) {
|
||||
|
@ -173,7 +175,7 @@ func_decl * array_decl_plugin::mk_map(func_decl* f, unsigned arity, sort* const*
|
|||
std::ostringstream buffer;
|
||||
buffer << "map expects all arguments to have the same array domain, "
|
||||
<< "this is not the case for argument " << i;
|
||||
m_manager->raise_exception(buffer.str().c_str());
|
||||
m_manager->raise_exception(buffer.str());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -181,7 +183,7 @@ func_decl * array_decl_plugin::mk_map(func_decl* f, unsigned arity, sort* const*
|
|||
std::ostringstream buffer;
|
||||
buffer << "map expects the argument at position " << i
|
||||
<< " to have the array range the same as the function";
|
||||
m_manager->raise_exception(buffer.str().c_str());
|
||||
m_manager->raise_exception(buffer.str());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -244,7 +246,7 @@ func_decl* array_decl_plugin::mk_select(unsigned arity, sort * const * domain) {
|
|||
if (num_parameters != arity) {
|
||||
std::stringstream strm;
|
||||
strm << "select requires " << num_parameters << " arguments, but was provided with " << arity << " arguments";
|
||||
m_manager->raise_exception(strm.str().c_str());
|
||||
m_manager->raise_exception(strm.str());
|
||||
return nullptr;
|
||||
}
|
||||
ptr_buffer<sort> new_domain; // we need this because of coercions.
|
||||
|
@ -256,7 +258,7 @@ func_decl* array_decl_plugin::mk_select(unsigned arity, sort * const * domain) {
|
|||
std::stringstream strm;
|
||||
strm << "domain sort " << sort_ref(domain[i+1], *m_manager) << " and parameter ";
|
||||
strm << parameter_pp(parameters[i], *m_manager) << " do not match";
|
||||
m_manager->raise_exception(strm.str().c_str());
|
||||
m_manager->raise_exception(strm.str());
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -284,7 +286,7 @@ func_decl * array_decl_plugin::mk_store(unsigned arity, sort * const * domain) {
|
|||
std::ostringstream buffer;
|
||||
buffer << "store expects the first argument to be an array taking " << num_parameters+1
|
||||
<< ", instead it was passed " << (arity - 1) << "arguments";
|
||||
m_manager->raise_exception(buffer.str().c_str());
|
||||
m_manager->raise_exception(buffer.str());
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -299,7 +301,7 @@ func_decl * array_decl_plugin::mk_store(unsigned arity, sort * const * domain) {
|
|||
sort* srt2 = domain[i+1];
|
||||
if (!m_manager->compatible_sorts(srt1, srt2)) {
|
||||
std::stringstream strm;
|
||||
strm << "domain sort " << sort_ref(srt2, *m_manager) << " and parameter sort " << sort_ref(srt2, *m_manager) << " do not match";
|
||||
strm << "domain sort " << sort_ref(srt2, *m_manager) << " and parameter sort " << sort_ref(srt1, *m_manager) << " do not match";
|
||||
m_manager->raise_exception(strm.str());
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
|
@ -438,6 +440,25 @@ func_decl * array_decl_plugin::mk_set_subset(unsigned arity, sort * const * doma
|
|||
func_decl_info(m_family_id, OP_SET_SUBSET));
|
||||
}
|
||||
|
||||
func_decl * array_decl_plugin::mk_set_has_size(unsigned arity, sort * const* domain) {
|
||||
if (arity != 2) {
|
||||
m_manager->raise_exception("set-has-size takes two arguments");
|
||||
return nullptr;
|
||||
}
|
||||
// domain[0] is a Boolean array,
|
||||
// domain[1] is Int
|
||||
arith_util arith(*m_manager);
|
||||
if (!arith.is_int(domain[1])) {
|
||||
m_manager->raise_exception("set-has-size expects second argument to be an integer");
|
||||
}
|
||||
if (!is_array_sort(domain[0]) || !m_manager->is_bool(get_array_range(domain[0]))) {
|
||||
m_manager->raise_exception("set-has-size expects first argument to be an array of Booleans");
|
||||
}
|
||||
sort * bool_sort = m_manager->mk_bool_sort();
|
||||
return m_manager->mk_func_decl(m_set_has_size_sym, arity, domain, bool_sort,
|
||||
func_decl_info(m_family_id, OP_SET_HAS_SIZE));
|
||||
}
|
||||
|
||||
func_decl * array_decl_plugin::mk_as_array(func_decl * f) {
|
||||
vector<parameter> parameters;
|
||||
for (unsigned i = 0; i < f->get_arity(); i++) {
|
||||
|
@ -502,6 +523,8 @@ func_decl * array_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
return mk_set_complement(arity, domain);
|
||||
case OP_SET_SUBSET:
|
||||
return mk_set_subset(arity, domain);
|
||||
case OP_SET_HAS_SIZE:
|
||||
return mk_set_has_size(arity, domain);
|
||||
case OP_AS_ARRAY: {
|
||||
if (num_parameters != 1 ||
|
||||
!parameters[0].is_ast() ||
|
||||
|
@ -544,6 +567,7 @@ void array_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol con
|
|||
op_names.push_back(builtin_name("subset",OP_SET_SUBSET));
|
||||
op_names.push_back(builtin_name("as-array", OP_AS_ARRAY));
|
||||
op_names.push_back(builtin_name("array-ext", OP_ARRAY_EXT));
|
||||
op_names.push_back(builtin_name("set-has-size", OP_SET_HAS_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -576,6 +600,26 @@ func_decl * array_recognizers::get_as_array_func_decl(func_decl * f) const {
|
|||
return to_func_decl(f->get_parameter(0).get_ast());
|
||||
}
|
||||
|
||||
bool array_recognizers::is_const(expr* e, expr*& v) const {
|
||||
return is_const(e) && (v = to_app(e)->get_arg(0), true);
|
||||
}
|
||||
|
||||
bool array_recognizers::is_store_ext(expr* _e, expr_ref& a, expr_ref_vector& args, expr_ref& value) {
|
||||
if (is_store(_e)) {
|
||||
app* e = to_app(_e);
|
||||
a = e->get_arg(0);
|
||||
unsigned sz = e->get_num_args();
|
||||
args.reset();
|
||||
for (unsigned i = 1; i < sz-1; ++i) {
|
||||
args.push_back(e->get_arg(i));
|
||||
}
|
||||
value = e->get_arg(sz-1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
array_util::array_util(ast_manager& m):
|
||||
array_recognizers(m.mk_family_id("array")),
|
||||
m_manager(m) {
|
||||
|
|
|
@ -51,6 +51,7 @@ enum array_op_kind {
|
|||
OP_SET_DIFFERENCE,
|
||||
OP_SET_COMPLEMENT,
|
||||
OP_SET_SUBSET,
|
||||
OP_SET_HAS_SIZE,
|
||||
OP_AS_ARRAY, // used for model construction
|
||||
LAST_ARRAY_OP
|
||||
};
|
||||
|
@ -68,6 +69,7 @@ class array_decl_plugin : public decl_plugin {
|
|||
symbol m_set_subset_sym;
|
||||
symbol m_array_ext_sym;
|
||||
symbol m_as_array_sym;
|
||||
symbol m_set_has_size_sym;
|
||||
|
||||
bool check_set_arguments(unsigned arity, sort * const * domain);
|
||||
|
||||
|
@ -95,6 +97,8 @@ class array_decl_plugin : public decl_plugin {
|
|||
|
||||
func_decl * mk_as_array(func_decl * f);
|
||||
|
||||
func_decl* mk_set_has_size(unsigned arity, sort * const* domain);
|
||||
|
||||
bool is_array_sort(sort* s) const;
|
||||
public:
|
||||
array_decl_plugin();
|
||||
|
@ -144,14 +148,20 @@ public:
|
|||
bool is_map(expr* n) const { return is_app_of(n, m_fid, OP_ARRAY_MAP); }
|
||||
bool is_as_array(expr * n) const { return is_app_of(n, m_fid, OP_AS_ARRAY); }
|
||||
bool is_as_array(expr * n, func_decl*& f) const { return is_as_array(n) && (f = get_as_array_func_decl(n), true); }
|
||||
bool is_set_has_size(expr* e) const { return is_app_of(e, m_fid, OP_SET_HAS_SIZE); }
|
||||
bool is_select(func_decl* f) const { return is_decl_of(f, m_fid, OP_SELECT); }
|
||||
bool is_store(func_decl* f) const { return is_decl_of(f, m_fid, OP_STORE); }
|
||||
bool is_const(func_decl* f) const { return is_decl_of(f, m_fid, OP_CONST_ARRAY); }
|
||||
bool is_map(func_decl* f) const { return is_decl_of(f, m_fid, OP_ARRAY_MAP); }
|
||||
bool is_as_array(func_decl* f) const { return is_decl_of(f, m_fid, OP_AS_ARRAY); }
|
||||
bool is_set_has_size(func_decl* f) const { return is_decl_of(f, m_fid, OP_SET_HAS_SIZE); }
|
||||
bool is_as_array(func_decl* f, func_decl*& g) const { return is_decl_of(f, m_fid, OP_AS_ARRAY) && (g = get_as_array_func_decl(f), true); }
|
||||
func_decl * get_as_array_func_decl(expr * n) const;
|
||||
func_decl * get_as_array_func_decl(func_decl* f) const;
|
||||
|
||||
bool is_const(expr* e, expr*& v) const;
|
||||
|
||||
bool is_store_ext(expr* e, expr_ref& a, expr_ref_vector& args, expr_ref& value);
|
||||
};
|
||||
|
||||
class array_util : public array_recognizers {
|
||||
|
@ -185,6 +195,10 @@ public:
|
|||
return mk_const_array(s, m_manager.mk_true());
|
||||
}
|
||||
|
||||
app* mk_has_size(expr* set, expr* n) {
|
||||
return m_manager.mk_app(m_fid, OP_SET_HAS_SIZE, set, n);
|
||||
}
|
||||
|
||||
func_decl * mk_array_ext(sort* domain, unsigned i);
|
||||
|
||||
sort * mk_array_sort(sort* dom, sort* range) { return mk_array_sort(1, &dom, range); }
|
||||
|
|
|
@ -1584,8 +1584,8 @@ void ast_manager::raise_exception(char const * msg) {
|
|||
throw ast_exception(msg);
|
||||
}
|
||||
|
||||
void ast_manager::raise_exception(std::string const& msg) {
|
||||
throw ast_exception(msg.c_str());
|
||||
void ast_manager::raise_exception(std::string && msg) {
|
||||
throw ast_exception(std::move(msg));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1875,7 +1875,6 @@ void ast_manager::delete_node(ast * n) {
|
|||
|
||||
while ((n = m_ast_table.pop_erase())) {
|
||||
|
||||
TRACE("ast", tout << "Deleting object " << n->m_id << " " << n << "\n";);
|
||||
CTRACE("del_quantifier", is_quantifier(n), tout << "deleting quantifier " << n->m_id << " " << n << "\n";);
|
||||
TRACE("mk_var_bug", tout << "del_ast: " << n->m_id << "\n";);
|
||||
TRACE("ast_delete_node", tout << mk_bounded_pp(n, *this) << "\n";);
|
||||
|
|
|
@ -1574,7 +1574,7 @@ public:
|
|||
|
||||
// Equivalent to throw ast_exception(msg)
|
||||
Z3_NORETURN void raise_exception(char const * msg);
|
||||
Z3_NORETURN void raise_exception(std::string const& s);
|
||||
Z3_NORETURN void raise_exception(std::string && s);
|
||||
|
||||
std::ostream& display(std::ostream& out, parameter const& p);
|
||||
|
||||
|
@ -2122,6 +2122,7 @@ public:
|
|||
app * mk_or(expr * arg1, expr * arg2) { return mk_app(m_basic_family_id, OP_OR, arg1, arg2); }
|
||||
app * mk_and(expr * arg1, expr * arg2) { return mk_app(m_basic_family_id, OP_AND, arg1, arg2); }
|
||||
app * mk_or(expr * arg1, expr * arg2, expr * arg3) { return mk_app(m_basic_family_id, OP_OR, arg1, arg2, arg3); }
|
||||
app * mk_or(expr* a, expr* b, expr* c, expr* d) { expr* args[4] = { a, b, c, d }; return mk_app(m_basic_family_id, OP_OR, 4, args); }
|
||||
app * mk_and(expr * arg1, expr * arg2, expr * arg3) { return mk_app(m_basic_family_id, OP_AND, arg1, arg2, arg3); }
|
||||
app * mk_implies(expr * arg1, expr * arg2) { return mk_app(m_basic_family_id, OP_IMPLIES, arg1, arg2); }
|
||||
app * mk_not(expr * n) { return mk_app(m_basic_family_id, OP_NOT, n); }
|
||||
|
|
|
@ -951,7 +951,7 @@ void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) {
|
|||
strm << "(set-logic " << m_logic << ")\n";
|
||||
}
|
||||
if (!m_attributes.empty()) {
|
||||
strm << "; " << m_attributes.c_str();
|
||||
strm << "; " << m_attributes;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -17,6 +17,7 @@ Revision History:
|
|||
|
||||
--*/
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
|
||||
app * mk_list_assoc_app(ast_manager & m, func_decl * f, unsigned num_args, expr * const * args) {
|
||||
SASSERT(f->is_associative());
|
||||
|
@ -361,3 +362,13 @@ void flatten_or(expr* fml, expr_ref_vector& result) {
|
|||
result.push_back(fml);
|
||||
flatten_or(result);
|
||||
}
|
||||
|
||||
static app_ref plus(ast_manager& m, expr* a, expr* b) {
|
||||
arith_util arith(m);
|
||||
return app_ref(arith.mk_add(a, b), m);
|
||||
}
|
||||
|
||||
|
||||
app_ref operator+(expr_ref& a, expr_ref& b) {
|
||||
return plus(a.m(), a.get(), b.get());
|
||||
}
|
||||
|
|
|
@ -111,6 +111,17 @@ app * mk_and(ast_manager & m, unsigned num_args, app * const * args);
|
|||
inline app_ref mk_and(app_ref_vector const& args) { return app_ref(mk_and(args.get_manager(), args.size(), args.c_ptr()), args.get_manager()); }
|
||||
inline expr_ref mk_and(expr_ref_vector const& args) { return expr_ref(mk_and(args.get_manager(), args.size(), args.c_ptr()), args.get_manager()); }
|
||||
|
||||
inline app_ref operator&(expr_ref& a, expr* b) { return app_ref(a.m().mk_and(a, b), a.m()); }
|
||||
inline app_ref operator&(app_ref& a, expr* b) { return app_ref(a.m().mk_and(a, b), a.m()); }
|
||||
inline app_ref operator&(var_ref& a, expr* b) { return app_ref(a.m().mk_and(a, b), a.m()); }
|
||||
inline app_ref operator&(quantifier_ref& a, expr* b) { return app_ref(a.m().mk_and(a, b), a.m()); }
|
||||
|
||||
inline app_ref operator|(expr_ref& a, expr* b) { return app_ref(a.m().mk_or(a, b), a.m()); }
|
||||
inline app_ref operator|(app_ref& a, expr* b) { return app_ref(a.m().mk_or(a, b), a.m()); }
|
||||
inline app_ref operator|(var_ref& a, expr* b) { return app_ref(a.m().mk_or(a, b), a.m()); }
|
||||
inline app_ref operator|(quantifier_ref& a, expr* b) { return app_ref(a.m().mk_or(a, b), a.m()); }
|
||||
app_ref operator+(expr_ref& a, expr_ref& b);
|
||||
|
||||
/**
|
||||
Return (or args[0] ... args[num_args-1]) if num_args >= 2
|
||||
Return args[0] if num_args == 1
|
||||
|
@ -129,6 +140,9 @@ expr * mk_not(ast_manager & m, expr * arg);
|
|||
|
||||
expr_ref mk_not(const expr_ref& e);
|
||||
|
||||
inline app_ref mk_not(const app_ref& e) { return app_ref(e.m().mk_not(e), e.m()); }
|
||||
|
||||
|
||||
/**
|
||||
Negate and push over conjunction or disjunction.
|
||||
*/
|
||||
|
|
|
@ -624,7 +624,7 @@ func_decl * bv_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p
|
|||
if (m.get_sort(args[i]) != r->get_domain(i)) {
|
||||
std::ostringstream buffer;
|
||||
buffer << "Argument " << mk_pp(args[i], m) << " at position " << i << " does not match declaration " << mk_pp(r, m);
|
||||
m.raise_exception(buffer.str().c_str());
|
||||
m.raise_exception(buffer.str());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -290,6 +290,7 @@ namespace datatype {
|
|||
obj_map<sort, sort_size> S;
|
||||
for (unsigned i = 0; i + 1 < num_parameters; ++i) {
|
||||
sort* r = to_sort(parameters[i + 1].get_ast());
|
||||
TRACE("datatype", tout << "inserting " << mk_ismt2_pp(r, *m_manager) << " " << r->get_num_elements() << "\n";);
|
||||
S.insert(d->params()[i], r->get_num_elements());
|
||||
}
|
||||
sort_size ts = d->sort_size()->eval(S);
|
||||
|
@ -342,7 +343,7 @@ namespace datatype {
|
|||
std::ostringstream buffer;
|
||||
buffer << "second argument to field update should be " << mk_ismt2_pp(rng, m)
|
||||
<< " instead of " << mk_ismt2_pp(domain[1], m);
|
||||
m.raise_exception(buffer.str().c_str());
|
||||
m.raise_exception(buffer.str());
|
||||
return nullptr;
|
||||
}
|
||||
range = domain[0];
|
||||
|
@ -454,6 +455,7 @@ namespace datatype {
|
|||
}
|
||||
|
||||
void plugin::log_axiom_definitions(symbol const& s, sort * new_sort) {
|
||||
std::ostream& out = m_manager->trace_stream();
|
||||
symbol const& family_name = m_manager->get_family_name(get_family_id());
|
||||
for (constructor const* c : *m_defs[s]) {
|
||||
func_decl_ref f = c->instantiate(new_sort);
|
||||
|
@ -462,19 +464,19 @@ namespace datatype {
|
|||
|
||||
// log constructor with quantified variables as arguments
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
m_manager->trace_stream() << "[mk-var] " << family_name << "#" << m_id_counter << " " << i << "\n";
|
||||
out << "[mk-var] " << family_name << "#" << m_id_counter << " " << i << "\n";
|
||||
++m_id_counter;
|
||||
}
|
||||
const unsigned constructor_id = m_id_counter;
|
||||
m_manager->trace_stream() << "[mk-app] " << family_name << "#" << constructor_id << " " << f->get_name();
|
||||
out << "[mk-app] " << family_name << "#" << constructor_id << " " << f->get_name();
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
m_manager->trace_stream() << " " << family_name << "#" << constructor_id - num_args + i;
|
||||
out << " " << family_name << "#" << constructor_id - num_args + i;
|
||||
}
|
||||
m_manager->trace_stream() << "\n";
|
||||
out << "\n";
|
||||
++m_id_counter;
|
||||
|
||||
// axioms for all accessors are generated when a constructor is applied => use constructor as pattern
|
||||
m_manager->trace_stream() << "[mk-app] " << family_name << "#" << m_id_counter << " pattern " << family_name << "#" << constructor_id << "\n";
|
||||
out << "[mk-app] " << family_name << "#" << m_id_counter << " pattern " << family_name << "#" << constructor_id << "\n";
|
||||
++m_id_counter;
|
||||
m_axiom_bases.insert(f->get_name(), constructor_id + 4);
|
||||
std::ostringstream var_sorts;
|
||||
|
@ -487,14 +489,14 @@ namespace datatype {
|
|||
unsigned i = 0;
|
||||
for (accessor const* a : *c) {
|
||||
func_decl_ref acc = a->instantiate(new_sort);
|
||||
m_manager->trace_stream() << "[mk-app] " << family_name << "#" << m_id_counter << " " << acc->get_name() << " " << family_name << "#" << constructor_id << "\n";
|
||||
out << "[mk-app] " << family_name << "#" << m_id_counter << " " << acc->get_name() << " " << family_name << "#" << constructor_id << "\n";
|
||||
++m_id_counter;
|
||||
m_manager->trace_stream() << "[mk-app] " << family_name << "#" << m_id_counter << " = " << family_name << "#" << constructor_id - num_args + i
|
||||
out << "[mk-app] " << family_name << "#" << m_id_counter << " = " << family_name << "#" << constructor_id - num_args + i
|
||||
<< " " << family_name << "#" << m_id_counter - 1 << "\n";
|
||||
++m_id_counter;
|
||||
m_manager->trace_stream() << "[mk-quant] " << family_name << "#" << m_id_counter << " constructor_accessor_axiom " << family_name << "#" << constructor_id + 1
|
||||
out << "[mk-quant] " << family_name << "#" << m_id_counter << " constructor_accessor_axiom " << family_name << "#" << constructor_id + 1
|
||||
<< " " << family_name << "#" << m_id_counter - 1 << "\n";
|
||||
m_manager->trace_stream() << "[attach-var-names] " << family_name << "#" << m_id_counter << var_description << "\n";
|
||||
out << "[attach-var-names] " << family_name << "#" << m_id_counter << var_description << "\n";
|
||||
++m_id_counter;
|
||||
++i;
|
||||
}
|
||||
|
@ -698,7 +700,7 @@ namespace datatype {
|
|||
}
|
||||
|
||||
param_size::size* util::get_sort_size(sort_ref_vector const& params, sort* s) {
|
||||
if (params.empty()) {
|
||||
if (params.empty() && !is_datatype(s)) {
|
||||
return param_size::size::mk_offset(s->get_num_elements());
|
||||
}
|
||||
if (is_datatype(s)) {
|
||||
|
@ -747,6 +749,7 @@ namespace datatype {
|
|||
map<symbol, status, symbol_hash_proc, symbol_eq_proc> already_found;
|
||||
map<symbol, param_size::size*, symbol_hash_proc, symbol_eq_proc> szs;
|
||||
|
||||
TRACE("datatype", for (auto const& s : names) tout << s << " "; tout << "\n";);
|
||||
svector<symbol> todo(names);
|
||||
status st;
|
||||
while (!todo.empty()) {
|
||||
|
@ -785,6 +788,7 @@ namespace datatype {
|
|||
todo.pop_back();
|
||||
already_found.insert(s, BLACK);
|
||||
if (is_infinite) {
|
||||
TRACE("datatype", tout << "infinite " << s << "\n";);
|
||||
d.set_sort_size(param_size::size::mk_offset(sort_size::mk_infinite()));
|
||||
continue;
|
||||
}
|
||||
|
@ -797,6 +801,7 @@ namespace datatype {
|
|||
}
|
||||
s_add.push_back(param_size::size::mk_times(s_mul));
|
||||
}
|
||||
TRACE("datatype", tout << "set sort size " << s << "\n";);
|
||||
d.set_sort_size(param_size::size::mk_plus(s_add));
|
||||
}
|
||||
}
|
||||
|
@ -1193,6 +1198,85 @@ namespace datatype {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort_ref util::mk_list_datatype(sort* elem, symbol const& name,
|
||||
func_decl_ref& cons, func_decl_ref& is_cons,
|
||||
func_decl_ref& hd, func_decl_ref& tl,
|
||||
func_decl_ref& nil, func_decl_ref& is_nil) {
|
||||
|
||||
accessor_decl* head_tail[2] = {
|
||||
mk_accessor_decl(m, symbol("head"), type_ref(elem)),
|
||||
mk_accessor_decl(m, symbol("tail"), type_ref(0))
|
||||
};
|
||||
constructor_decl* constrs[2] = {
|
||||
mk_constructor_decl(symbol("nil"), symbol("is_nil"), 0, nullptr),
|
||||
mk_constructor_decl(symbol("cons"), symbol("is_cons"), 2, head_tail)
|
||||
};
|
||||
decl::plugin& p = *get_plugin();
|
||||
|
||||
sort_ref_vector sorts(m);
|
||||
datatype_decl * decl = mk_datatype_decl(*this, name, 0, nullptr, 2, constrs);
|
||||
bool is_ok = p.mk_datatypes(1, &decl, 0, nullptr, sorts);
|
||||
del_datatype_decl(decl);
|
||||
|
||||
if (!is_ok) {
|
||||
return sort_ref(m);
|
||||
}
|
||||
sort* s = sorts.get(0);
|
||||
ptr_vector<func_decl> const& cnstrs = *get_datatype_constructors(s);
|
||||
SASSERT(cnstrs.size() == 2);
|
||||
nil = cnstrs[0];
|
||||
is_nil = get_constructor_is(cnstrs[0]);
|
||||
cons = cnstrs[1];
|
||||
is_cons = get_constructor_is(cnstrs[1]);
|
||||
ptr_vector<func_decl> const& acc = *get_constructor_accessors(cnstrs[1]);
|
||||
SASSERT(acc.size() == 2);
|
||||
hd = acc[0];
|
||||
tl = acc[1];
|
||||
return sort_ref(s, m);
|
||||
}
|
||||
|
||||
sort_ref util::mk_pair_datatype(sort* a, sort* b, func_decl_ref& fst, func_decl_ref& snd, func_decl_ref& pair) {
|
||||
type_ref t1(a), t2(b);
|
||||
accessor_decl* fstd = mk_accessor_decl(m, symbol("fst"), t1);
|
||||
accessor_decl* sndd = mk_accessor_decl(m, symbol("snd"), t2);
|
||||
accessor_decl* accd[2] = { fstd, sndd };
|
||||
auto * p = mk_constructor_decl(symbol("pair"), symbol("is-pair"), 2, accd);
|
||||
auto* dt = mk_datatype_decl(*this, symbol("pair"), 0, nullptr, 1, &p);
|
||||
sort_ref_vector sorts(m);
|
||||
VERIFY(get_plugin()->mk_datatypes(1, &dt, 0, nullptr, sorts));
|
||||
del_datatype_decl(dt);
|
||||
sort* s = sorts.get(0);
|
||||
ptr_vector<func_decl> const& cnstrs = *get_datatype_constructors(s);
|
||||
SASSERT(cnstrs.size() == 1);
|
||||
ptr_vector<func_decl> const& acc = *get_constructor_accessors(cnstrs[0]);
|
||||
SASSERT(acc.size() == 2);
|
||||
fst = acc[0];
|
||||
snd = acc[1];
|
||||
pair = cnstrs[0];
|
||||
return sort_ref(s, m);
|
||||
}
|
||||
|
||||
sort_ref util::mk_tuple_datatype(svector<std::pair<symbol, sort*>> const& elems, symbol const& name, symbol const& test, func_decl_ref& tup, func_decl_ref_vector& accs) {
|
||||
ptr_vector<accessor_decl> accd;
|
||||
for (auto const& e : elems) {
|
||||
type_ref t(e.second);
|
||||
accd.push_back(mk_accessor_decl(m, e.first, t));
|
||||
}
|
||||
auto* tuple = mk_constructor_decl(name, test, accd.size(), accd.c_ptr());
|
||||
auto* dt = mk_datatype_decl(*this, name, 0, nullptr, 1, &tuple);
|
||||
sort_ref_vector sorts(m);
|
||||
VERIFY(get_plugin()->mk_datatypes(1, &dt, 0, nullptr, sorts));
|
||||
del_datatype_decl(dt);
|
||||
sort* s = sorts.get(0);
|
||||
ptr_vector<func_decl> const& cnstrs = *get_datatype_constructors(s);
|
||||
SASSERT(cnstrs.size() == 1);
|
||||
ptr_vector<func_decl> const& acc = *get_constructor_accessors(cnstrs[0]);
|
||||
for (auto* f : acc) accs.push_back(f);
|
||||
tup = cnstrs[0];
|
||||
return sort_ref(s, m);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
datatype_decl * mk_datatype_decl(datatype_util& u, symbol const & n, unsigned num_params, sort*const* params, unsigned num_constructors, constructor_decl * const * cs) {
|
||||
|
|
|
@ -364,6 +364,12 @@ namespace datatype {
|
|||
decl::plugin* get_plugin() { return m_plugin; }
|
||||
void get_defs(sort* s, ptr_vector<def>& defs);
|
||||
def const& get_def(sort* s) const;
|
||||
sort_ref mk_list_datatype(sort* elem, symbol const& name,
|
||||
func_decl_ref& cons, func_decl_ref& is_cons,
|
||||
func_decl_ref& hd, func_decl_ref& tl,
|
||||
func_decl_ref& nil, func_decl_ref& is_nil);
|
||||
sort_ref mk_pair_datatype(sort* a, sort* b, func_decl_ref& fst, func_decl_ref& snd, func_decl_ref& pair);
|
||||
sort_ref mk_tuple_datatype(svector<std::pair<symbol, sort*>> const& elems, symbol const& name, symbol const& test, func_decl_ref& tup, func_decl_ref_vector& accs);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -26,6 +26,7 @@ std::ostream& display_dimacs(std::ostream& out, expr_ref_vector const& fmls) {
|
|||
ptr_vector<expr> exprs;
|
||||
unsigned num_vars = 0;
|
||||
unsigned num_cls = fmls.size();
|
||||
bool is_from_dimacs = true;
|
||||
for (expr * f : fmls) {
|
||||
unsigned num_lits;
|
||||
expr * const * lits;
|
||||
|
@ -41,10 +42,51 @@ std::ostream& display_dimacs(std::ostream& out, expr_ref_vector const& fmls) {
|
|||
expr * l = lits[j];
|
||||
if (m.is_not(l))
|
||||
l = to_app(l)->get_arg(0);
|
||||
if (expr2var.get(l->get_id(), UINT_MAX) == UINT_MAX) {
|
||||
num_vars++;
|
||||
expr2var.setx(l->get_id(), num_vars, UINT_MAX);
|
||||
exprs.setx(l->get_id(), l, nullptr);
|
||||
if (!is_uninterp_const(l)) {
|
||||
is_from_dimacs = false;
|
||||
break;
|
||||
}
|
||||
symbol const& s = to_app(l)->get_decl()->get_name();
|
||||
if (s.is_numerical() && s.get_num() > 0) {
|
||||
if (expr2var.get(l->get_id(), UINT_MAX) == UINT_MAX) {
|
||||
++num_vars;
|
||||
expr2var.setx(l->get_id(), s.get_num(), UINT_MAX);
|
||||
exprs.setx(l->get_id(), l, nullptr);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
is_from_dimacs = false;
|
||||
break;
|
||||
}
|
||||
if (!is_from_dimacs) {
|
||||
num_vars = 0;
|
||||
expr2var.reset();
|
||||
exprs.reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_from_dimacs) {
|
||||
for (expr * f : fmls) {
|
||||
unsigned num_lits;
|
||||
expr * const * lits;
|
||||
if (m.is_or(f)) {
|
||||
num_lits = to_app(f)->get_num_args();
|
||||
lits = to_app(f)->get_args();
|
||||
}
|
||||
else {
|
||||
num_lits = 1;
|
||||
lits = &f;
|
||||
}
|
||||
for (unsigned j = 0; j < num_lits; j++) {
|
||||
expr * l = lits[j];
|
||||
if (m.is_not(l))
|
||||
l = to_app(l)->get_arg(0);
|
||||
if (expr2var.get(l->get_id(), UINT_MAX) == UINT_MAX) {
|
||||
num_vars++;
|
||||
expr2var.setx(l->get_id(), num_vars, UINT_MAX);
|
||||
exprs.setx(l->get_id(), l, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,10 +113,12 @@ std::ostream& display_dimacs(std::ostream& out, expr_ref_vector const& fmls) {
|
|||
}
|
||||
out << "0\n";
|
||||
}
|
||||
for (expr* e : exprs) {
|
||||
if (e && is_app(e)) {
|
||||
symbol const& n = to_app(e)->get_decl()->get_name();
|
||||
out << "c " << expr2var[e->get_id()] << " " << n << "\n";
|
||||
if (!is_from_dimacs) {
|
||||
for (expr* e : exprs) {
|
||||
if (e && is_app(e)) {
|
||||
symbol const& n = to_app(e)->get_decl()->get_name();
|
||||
out << "c " << expr2var[e->get_id()] << " " << n << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace datalog {
|
|||
}
|
||||
std::ostringstream buffer;
|
||||
buffer << msg << ", value is not within bound " << low << " <= " << val << " <= " << up;
|
||||
m_manager->raise_exception(buffer.str().c_str());
|
||||
m_manager->raise_exception(buffer.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -676,7 +676,7 @@ namespace datalog {
|
|||
}
|
||||
std::stringstream strm;
|
||||
strm << "sort '" << mk_pp(s, m) << "' is not recognized as a sort that contains numeric values.\nUse Bool, BitVec, Int, Real, or a Finite domain sort";
|
||||
m.raise_exception(strm.str().c_str());
|
||||
m.raise_exception(strm.str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,8 +65,8 @@ std::ostream& expr_substitution::display(std::ostream& out) {
|
|||
}
|
||||
|
||||
void expr_substitution::insert(expr * c, expr * def, proof * def_pr, expr_dependency * def_dep) {
|
||||
obj_map<expr, expr*>::obj_map_entry * entry = m_subst.insert_if_not_there2(c, 0);
|
||||
if (entry->get_data().m_value == 0) {
|
||||
obj_map<expr, expr*>::obj_map_entry * entry = m_subst.insert_if_not_there2(c, nullptr);
|
||||
if (entry->get_data().m_value == nullptr) {
|
||||
// new entry
|
||||
m_manager.inc_ref(c);
|
||||
m_manager.inc_ref(def);
|
||||
|
@ -89,14 +89,14 @@ void expr_substitution::insert(expr * c, expr * def, proof * def_pr, expr_depend
|
|||
entry->get_data().m_value = def;
|
||||
if (proofs_enabled()) {
|
||||
obj_map<expr, proof*>::obj_map_entry * entry_pr = m_subst_pr->find_core(c);
|
||||
SASSERT(entry_pr != 0);
|
||||
SASSERT(entry_pr != nullptr);
|
||||
m_manager.inc_ref(def_pr);
|
||||
m_manager.dec_ref(entry_pr->get_data().m_value);
|
||||
entry_pr->get_data().m_value = def_pr;
|
||||
}
|
||||
if (unsat_core_enabled()) {
|
||||
obj_map<expr, expr_dependency*>::obj_map_entry * entry_dep = m_subst_dep->find_core(c);
|
||||
SASSERT(entry_dep != 0);
|
||||
SASSERT(entry_dep != nullptr);
|
||||
m_manager.inc_ref(def_dep);
|
||||
m_manager.dec_ref(entry_dep->get_data().m_value);
|
||||
entry_dep->get_data().m_value = def_dep;
|
||||
|
|
|
@ -1986,15 +1986,17 @@ void fpa2bv_converter::mk_round_to_integral(sort * s, expr_ref & rm, expr_ref &
|
|||
|
||||
SASSERT(is_well_sorted(m, v4));
|
||||
|
||||
// exponent >= sbits-1
|
||||
// exponent >= sbits-1 -> x
|
||||
expr_ref exp_is_large(m);
|
||||
exp_is_large = m_bv_util.mk_sle(m_bv_util.mk_numeral(sbits-1, ebits), a_exp);
|
||||
exp_is_large = log2(sbits-1)+1 <= ebits-1 ?
|
||||
m_bv_util.mk_sle(m_bv_util.mk_numeral(sbits-1, ebits), a_exp) :
|
||||
m.mk_false();
|
||||
dbg_decouple("fpa2bv_r2i_exp_is_large", exp_is_large);
|
||||
c5 = exp_is_large;
|
||||
v5 = x;
|
||||
|
||||
// Actual conversion with rounding.
|
||||
// x.exponent >= 0 && x.exponent < x.sbits - 1
|
||||
// exponent >= 0 && exponent < sbits - 1
|
||||
|
||||
expr_ref res_sgn(m), res_sig(m), res_exp(m);
|
||||
res_sgn = a_sgn;
|
||||
|
@ -2070,7 +2072,6 @@ void fpa2bv_converter::mk_round_to_integral(sort * s, expr_ref & rm, expr_ref &
|
|||
m_simp.mk_ite(c53, v53, res_sig, res_sig);
|
||||
m_simp.mk_ite(c52, v52, res_sig, res_sig);
|
||||
m_simp.mk_ite(c51, v51, res_sig, res_sig);
|
||||
res_sig = m_bv_util.mk_zero_extend(1, m_bv_util.mk_concat(res_sig, m_bv_util.mk_numeral(0, 3))); // rounding bits are all 0.
|
||||
|
||||
SASSERT(m_bv_util.get_bv_size(res_exp) == ebits);
|
||||
SASSERT(m_bv_util.get_bv_size(shift) == sbits);
|
||||
|
@ -2082,11 +2083,37 @@ void fpa2bv_converter::mk_round_to_integral(sort * s, expr_ref & rm, expr_ref &
|
|||
res_exp = m_bv_util.mk_bv_add(m_bv_util.mk_zero_extend(2, res_exp), e_shift);
|
||||
|
||||
SASSERT(m_bv_util.get_bv_size(res_sgn) == 1);
|
||||
SASSERT(m_bv_util.get_bv_size(res_sig) == sbits + 4);
|
||||
SASSERT(m_bv_util.get_bv_size(res_sig) == sbits);
|
||||
SASSERT(m_bv_util.get_bv_size(res_exp) == ebits + 2);
|
||||
|
||||
// CMW: We use the rounder for normalization.
|
||||
round(s, rm, res_sgn, res_sig, res_exp, v6);
|
||||
// Renormalize
|
||||
expr_ref zero_e2(m), min_exp(m), sig_lz(m), max_exp_delta(m), sig_lz_capped(m), renorm_delta(m);
|
||||
zero_e2 = m_bv_util.mk_numeral(0, ebits+2);
|
||||
mk_min_exp(ebits, min_exp);
|
||||
min_exp = m_bv_util.mk_sign_extend(2, min_exp);
|
||||
mk_leading_zeros(res_sig, ebits+2, sig_lz);
|
||||
max_exp_delta = m_bv_util.mk_bv_sub(res_exp, min_exp);
|
||||
sig_lz_capped = m.mk_ite(m_bv_util.mk_sle(sig_lz, max_exp_delta), sig_lz, max_exp_delta);
|
||||
renorm_delta = m.mk_ite(m_bv_util.mk_sle(zero_e2, sig_lz_capped), sig_lz_capped, zero_e2);
|
||||
SASSERT(m_bv_util.get_bv_size(renorm_delta) == ebits + 2);
|
||||
res_exp = m_bv_util.mk_bv_sub(res_exp, renorm_delta);
|
||||
res_sig = m_bv_util.mk_bv_shl(res_sig, m_bv_util.mk_zero_extend(sbits-ebits-2, renorm_delta));
|
||||
dbg_decouple("fpa2bv_r2i_renorm_delta", renorm_delta);
|
||||
|
||||
res_exp = m_bv_util.mk_extract(ebits-1, 0, res_exp);
|
||||
mk_bias(res_exp, res_exp);
|
||||
res_sig = m_bv_util.mk_extract(sbits-2, 0, res_sig);
|
||||
v6 = m_util.mk_fp(res_sgn, res_exp, res_sig);
|
||||
|
||||
dbg_decouple("fpa2bv_r2i_res_sgn", res_sgn);
|
||||
dbg_decouple("fpa2bv_r2i_res_sig", res_sig);
|
||||
dbg_decouple("fpa2bv_r2i_res_exp", res_exp);
|
||||
|
||||
dbg_decouple("fpa2bv_r2i_c1", c1);
|
||||
dbg_decouple("fpa2bv_r2i_c2", c2);
|
||||
dbg_decouple("fpa2bv_r2i_c3", c3);
|
||||
dbg_decouple("fpa2bv_r2i_c4", c4);
|
||||
dbg_decouple("fpa2bv_r2i_c5", c5);
|
||||
|
||||
// And finally, we tie them together.
|
||||
mk_ite(c5, v5, v6, result);
|
||||
|
|
|
@ -159,11 +159,11 @@ void defined_names::impl::bound_vars(sort_ref_buffer const & sorts, buffer<symbo
|
|||
expr * patterns[1] = { m.mk_pattern(name) };
|
||||
quantifier_ref q(m);
|
||||
q = m.mk_forall(sorts.size(),
|
||||
sorts.c_ptr(),
|
||||
names.c_ptr(),
|
||||
def_conjunct,
|
||||
1, qid, symbol::null,
|
||||
1, patterns);
|
||||
sorts.c_ptr(),
|
||||
names.c_ptr(),
|
||||
def_conjunct,
|
||||
1, qid, symbol::null,
|
||||
1, patterns);
|
||||
TRACE("mk_definition_bug", tout << "before elim_unused_vars:\n" << mk_ismt2_pp(q, m) << "\n";);
|
||||
result = elim_unused_vars(m, q, params_ref());
|
||||
TRACE("mk_definition_bug", tout << "after elim_unused_vars:\n" << result << "\n";);
|
||||
|
|
|
@ -52,35 +52,57 @@ expr_pattern_match::match_quantifier(quantifier* qf, app_ref_vector& patterns, u
|
|||
}
|
||||
m_regs[0] = qf->get_expr();
|
||||
for (unsigned i = 0; i < m_precompiled.size(); ++i) {
|
||||
quantifier* qf2 = m_precompiled[i].get();
|
||||
if (qf2->get_kind() != qf->get_kind() || is_lambda(qf)) {
|
||||
continue;
|
||||
}
|
||||
if (qf2->get_num_decls() != qf->get_num_decls()) {
|
||||
continue;
|
||||
}
|
||||
subst s;
|
||||
if (match(qf->get_expr(), m_first_instrs[i], s)) {
|
||||
for (unsigned j = 0; j < qf2->get_num_patterns(); ++j) {
|
||||
app* p = static_cast<app*>(qf2->get_pattern(j));
|
||||
expr_ref p_result(m_manager);
|
||||
instantiate(p, qf->get_num_decls(), s, p_result);
|
||||
patterns.push_back(to_app(p_result.get()));
|
||||
}
|
||||
weight = qf2->get_weight();
|
||||
return true;
|
||||
if (match_quantifier(i, qf, patterns, weight))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
expr_pattern_match::match_quantifier(unsigned i, quantifier* qf, app_ref_vector& patterns, unsigned& weight) {
|
||||
quantifier* qf2 = m_precompiled[i].get();
|
||||
if (qf2->get_kind() != qf->get_kind() || is_lambda(qf)) {
|
||||
return false;
|
||||
}
|
||||
if (qf2->get_num_decls() != qf->get_num_decls()) {
|
||||
return false;
|
||||
}
|
||||
subst s;
|
||||
if (match(qf->get_expr(), m_first_instrs[i], s)) {
|
||||
for (unsigned j = 0; j < qf2->get_num_patterns(); ++j) {
|
||||
app* p = static_cast<app*>(qf2->get_pattern(j));
|
||||
expr_ref p_result(m_manager);
|
||||
instantiate(p, qf->get_num_decls(), s, p_result);
|
||||
patterns.push_back(to_app(p_result.get()));
|
||||
}
|
||||
weight = qf2->get_weight();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool expr_pattern_match::match_quantifier_index(quantifier* qf, app_ref_vector& patterns, unsigned& index) {
|
||||
if (m_regs.empty()) return false;
|
||||
m_regs[0] = qf->get_expr();
|
||||
|
||||
for (unsigned i = 0; i < m_precompiled.size(); ++i) {
|
||||
unsigned weight = 0;
|
||||
if (match_quantifier(i, qf, patterns, weight)) {
|
||||
index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
expr_pattern_match::instantiate(expr* a, unsigned num_bound, subst& s, expr_ref& result) {
|
||||
bound b;
|
||||
for (unsigned i = 0; i < num_bound; ++i) {
|
||||
b.insert(m_bound_dom[i], m_bound_rng[i]);
|
||||
}
|
||||
|
||||
TRACE("expr_pattern_match", tout << mk_pp(a, m_manager) << " " << num_bound << "\n";);
|
||||
inst_proc proc(m_manager, s, b, m_regs);
|
||||
for_each_ast(proc, a);
|
||||
expr* v = nullptr;
|
||||
|
@ -251,11 +273,7 @@ expr_pattern_match::match(expr* a, unsigned init, subst& s)
|
|||
break;
|
||||
}
|
||||
case CHECK_BOUND:
|
||||
TRACE("expr_pattern_match",
|
||||
tout
|
||||
<< "check bound "
|
||||
<< pc.m_num_bound << " " << pc.m_reg;
|
||||
);
|
||||
TRACE("expr_pattern_match", tout << "check bound " << pc.m_num_bound << " " << pc.m_reg << "\n";);
|
||||
ok = m_bound_rng[pc.m_num_bound] == m_regs[pc.m_reg];
|
||||
break;
|
||||
case BIND:
|
||||
|
@ -396,11 +414,18 @@ expr_pattern_match::initialize(char const * spec_string) {
|
|||
for (expr * e : ctx.assertions()) {
|
||||
compile(e);
|
||||
}
|
||||
TRACE("expr_pattern_match", display(tout); );
|
||||
}
|
||||
|
||||
void
|
||||
expr_pattern_match::display(std::ostream& out) const {
|
||||
unsigned expr_pattern_match::initialize(quantifier* q) {
|
||||
if (m_instrs.empty()) {
|
||||
m_instrs.push_back(instr(BACKTRACK));
|
||||
}
|
||||
compile(q);
|
||||
return m_precompiled.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
void expr_pattern_match::display(std::ostream& out) const {
|
||||
for (unsigned i = 0; i < m_instrs.size(); ++i) {
|
||||
display(out, m_instrs[i]);
|
||||
}
|
||||
|
@ -414,7 +439,6 @@ expr_pattern_match::display(std::ostream& out, instr const& pc) const {
|
|||
break;
|
||||
case BIND:
|
||||
out << "bind ";
|
||||
out << mk_pp(to_app(pc.m_pat)->get_decl(), m_manager) << " ";
|
||||
out << mk_pp(pc.m_pat, m_manager) << "\n";
|
||||
out << "next: " << pc.m_next << "\n";
|
||||
out << "offset: " << pc.m_offset << "\n";
|
||||
|
@ -422,7 +446,6 @@ expr_pattern_match::display(std::ostream& out, instr const& pc) const {
|
|||
break;
|
||||
case BIND_AC:
|
||||
out << "bind_ac ";
|
||||
out << mk_pp(to_app(pc.m_pat)->get_decl(), m_manager) << " ";
|
||||
out << mk_pp(pc.m_pat, m_manager) << "\n";
|
||||
out << "next: " << pc.m_next << "\n";
|
||||
out << "offset: " << pc.m_offset << "\n";
|
||||
|
@ -430,7 +453,6 @@ expr_pattern_match::display(std::ostream& out, instr const& pc) const {
|
|||
break;
|
||||
case BIND_C:
|
||||
out << "bind_c ";
|
||||
out << mk_pp(to_app(pc.m_pat)->get_decl(), m_manager) << " ";
|
||||
out << mk_pp(pc.m_pat, m_manager) << "\n";
|
||||
out << "next: " << pc.m_next << "\n";
|
||||
out << "offset: " << pc.m_offset << "\n";
|
||||
|
|
|
@ -80,13 +80,7 @@ class expr_pattern_match {
|
|||
}
|
||||
|
||||
void operator()(var* v) {
|
||||
var* b = nullptr;
|
||||
if (m_bound.find(v, b)) {
|
||||
m_memoize.insert(v, b);
|
||||
}
|
||||
else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
m_memoize.insert(v, m_bound[v]);
|
||||
}
|
||||
|
||||
void operator()(app * n) {
|
||||
|
@ -98,15 +92,9 @@ class expr_pattern_match {
|
|||
if (m_subst.find(decl, r)) {
|
||||
decl = to_app(m_regs[r])->get_decl();
|
||||
}
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
expr* arg = nullptr;
|
||||
if (m_memoize.find(n->get_arg(i), arg)) {
|
||||
SASSERT(arg);
|
||||
args.push_back(arg);
|
||||
}
|
||||
else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
for (expr* arg : *n) {
|
||||
arg = m_memoize[arg];
|
||||
args.push_back(arg);
|
||||
}
|
||||
if (m_manager.is_pattern(n)) {
|
||||
result = m_manager.mk_pattern(num_args, reinterpret_cast<app**>(args.c_ptr()));
|
||||
|
@ -116,7 +104,6 @@ class expr_pattern_match {
|
|||
}
|
||||
m_pinned.push_back(result);
|
||||
m_memoize.insert(n, result);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -131,11 +118,14 @@ class expr_pattern_match {
|
|||
public:
|
||||
expr_pattern_match(ast_manager & manager);
|
||||
~expr_pattern_match();
|
||||
virtual bool match_quantifier(quantifier * qf, app_ref_vector & patterns, unsigned & weight);
|
||||
virtual void initialize(char const * database);
|
||||
bool match_quantifier(quantifier * qf, app_ref_vector & patterns, unsigned & weight);
|
||||
bool match_quantifier_index(quantifier* qf, app_ref_vector & patterns, unsigned& index);
|
||||
unsigned initialize(quantifier* qf);
|
||||
void initialize(char const * database);
|
||||
void display(std::ostream& out) const;
|
||||
|
||||
private:
|
||||
bool match_quantifier(unsigned i, quantifier * qf, app_ref_vector & patterns, unsigned & weight);
|
||||
void instantiate(expr* a, unsigned num_bound, subst& s, expr_ref& result);
|
||||
void compile(expr* q);
|
||||
bool match(expr* a, unsigned init, subst& s);
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace recfun {
|
|||
}
|
||||
|
||||
def::def(ast_manager &m, family_id fid, symbol const & s,
|
||||
unsigned arity, sort* const * domain, sort* range)
|
||||
unsigned arity, sort* const * domain, sort* range, bool is_generated)
|
||||
: m(m), m_name(s),
|
||||
m_domain(m, arity, domain),
|
||||
m_range(range, m), m_vars(m), m_cases(),
|
||||
|
@ -59,7 +59,8 @@ namespace recfun {
|
|||
m_fid(fid)
|
||||
{
|
||||
SASSERT(arity == get_arity());
|
||||
func_decl_info info(fid, OP_FUN_DEFINED);
|
||||
parameter p(is_generated);
|
||||
func_decl_info info(fid, OP_FUN_DEFINED, 1, &p);
|
||||
m_decl = m.mk_func_decl(s, arity, domain, range, info);
|
||||
}
|
||||
|
||||
|
@ -238,6 +239,7 @@ namespace recfun {
|
|||
while (! stack.empty()) {
|
||||
expr * e = stack.back();
|
||||
stack.pop_back();
|
||||
TRACEFN("unfold: " << mk_pp(e, m));
|
||||
|
||||
if (m.is_ite(e)) {
|
||||
// need to do a case split on `e`, forking the search space
|
||||
|
@ -257,6 +259,7 @@ namespace recfun {
|
|||
if (b.to_split != nullptr) {
|
||||
// split one `ite`, which will lead to distinct (sets of) cases
|
||||
app * ite = b.to_split->ite;
|
||||
TRACEFN("split: " << mk_pp(ite, m));
|
||||
expr* c = nullptr, *th = nullptr, *el = nullptr;
|
||||
VERIFY(m.is_ite(ite, c, th, el));
|
||||
|
||||
|
@ -287,6 +290,7 @@ namespace recfun {
|
|||
|
||||
// substitute, to get rid of `ite` terms
|
||||
expr_ref case_rhs = subst(rhs);
|
||||
TRACEFN("case_rhs: " << case_rhs);
|
||||
for (unsigned i = 0; i < conditions.size(); ++i) {
|
||||
conditions[i] = subst(conditions.get(i));
|
||||
}
|
||||
|
@ -312,10 +316,11 @@ namespace recfun {
|
|||
util::~util() {
|
||||
}
|
||||
|
||||
def * util::decl_fun(symbol const& name, unsigned n, sort *const * domain, sort * range) {
|
||||
return alloc(def, m(), m_fid, name, n, domain, range);
|
||||
def * util::decl_fun(symbol const& name, unsigned n, sort *const * domain, sort * range, bool is_generated) {
|
||||
return alloc(def, m(), m_fid, name, n, domain, range, is_generated);
|
||||
}
|
||||
|
||||
|
||||
void util::set_definition(replace& subst, promise_def & d, unsigned n_vars, var * const * vars, expr * rhs) {
|
||||
d.set_definition(subst, n_vars, vars, rhs);
|
||||
}
|
||||
|
@ -382,9 +387,19 @@ namespace recfun {
|
|||
return *(m_util.get());
|
||||
}
|
||||
|
||||
promise_def plugin::mk_def(symbol const& name, unsigned n, sort *const * params, sort * range) {
|
||||
def* d = u().decl_fun(name, n, params, range);
|
||||
SASSERT(! m_defs.contains(d->get_decl()));
|
||||
promise_def plugin::mk_def(symbol const& name, unsigned n, sort *const * params, sort * range, bool is_generated) {
|
||||
def* d = u().decl_fun(name, n, params, range, is_generated);
|
||||
SASSERT(!m_defs.contains(d->get_decl()));
|
||||
m_defs.insert(d->get_decl(), d);
|
||||
return promise_def(&u(), d);
|
||||
}
|
||||
|
||||
promise_def plugin::ensure_def(symbol const& name, unsigned n, sort *const * params, sort * range, bool is_generated) {
|
||||
def* d = u().decl_fun(name, n, params, range, is_generated);
|
||||
def* d2 = nullptr;
|
||||
if (m_defs.find(d->get_decl(), d2)) {
|
||||
dealloc(d2);
|
||||
}
|
||||
m_defs.insert(d->get_decl(), d);
|
||||
return promise_def(&u(), d);
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ namespace recfun {
|
|||
expr_ref m_rhs; //!< definition
|
||||
family_id m_fid;
|
||||
|
||||
def(ast_manager &m, family_id fid, symbol const & s, unsigned arity, sort *const * domain, sort* range);
|
||||
def(ast_manager &m, family_id fid, symbol const & s, unsigned arity, sort *const * domain, sort* range, bool is_generated);
|
||||
|
||||
// compute cases for a function, given its RHS (possibly containing `ite`).
|
||||
void compute_cases(replace& subst, is_immediate_pred &,
|
||||
|
@ -147,6 +147,7 @@ namespace recfun {
|
|||
class plugin : public decl_plugin {
|
||||
typedef obj_map<func_decl, def*> def_map;
|
||||
typedef obj_map<func_decl, case_def*> case_def_map;
|
||||
|
||||
|
||||
mutable scoped_ptr<util> m_util;
|
||||
def_map m_defs; // function->def
|
||||
|
@ -171,7 +172,9 @@ namespace recfun {
|
|||
func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) override;
|
||||
|
||||
promise_def mk_def(symbol const& name, unsigned n, sort *const * params, sort * range);
|
||||
promise_def mk_def(symbol const& name, unsigned n, sort *const * params, sort * range, bool is_generated = false);
|
||||
|
||||
promise_def ensure_def(symbol const& name, unsigned n, sort *const * params, sort * range, bool is_generated = false);
|
||||
|
||||
void set_definition(replace& r, promise_def & d, unsigned n_vars, var * const * vars, expr * rhs);
|
||||
|
||||
|
@ -214,6 +217,7 @@ namespace recfun {
|
|||
bool is_case_pred(expr * e) const { return is_app_of(e, m_fid, OP_FUN_CASE_PRED); }
|
||||
bool is_defined(expr * e) const { return is_app_of(e, m_fid, OP_FUN_DEFINED); }
|
||||
bool is_defined(func_decl* f) const { return is_decl_of(f, m_fid, OP_FUN_DEFINED); }
|
||||
bool is_generated(func_decl* f) const { return is_defined(f) && f->get_parameter(0).get_int() == 1; }
|
||||
bool is_depth_limit(expr * e) const { return is_app_of(e, m_fid, OP_DEPTH_LIMIT); }
|
||||
bool owns_app(app * e) const { return e->get_family_id() == m_fid; }
|
||||
|
||||
|
@ -221,8 +225,7 @@ namespace recfun {
|
|||
bool has_defs() const { return m_plugin->has_defs(); }
|
||||
|
||||
//<! add a function declaration
|
||||
def * decl_fun(symbol const & s, unsigned n_args, sort *const * args, sort * range);
|
||||
|
||||
def * decl_fun(symbol const & s, unsigned n_args, sort *const * args, sort * range, bool is_generated);
|
||||
|
||||
def& get_def(func_decl* f) {
|
||||
SASSERT(m_plugin->has_def(f));
|
||||
|
|
|
@ -27,6 +27,7 @@ Revision History:
|
|||
#include "ast/seq_decl_plugin.h"
|
||||
#include "ast/pb_decl_plugin.h"
|
||||
#include "ast/fpa_decl_plugin.h"
|
||||
#include "ast/special_relations_decl_plugin.h"
|
||||
|
||||
void reg_decl_plugins(ast_manager & m) {
|
||||
if (!m.get_plugin(m.mk_family_id(symbol("arith")))) {
|
||||
|
@ -56,4 +57,7 @@ void reg_decl_plugins(ast_manager & m) {
|
|||
if (!m.get_plugin(m.mk_family_id(symbol("pb")))) {
|
||||
m.register_plugin(symbol("pb"), alloc(pb_decl_plugin));
|
||||
}
|
||||
if (!m.get_plugin(m.mk_family_id(symbol("special_relations")))) {
|
||||
m.register_plugin(symbol("special_relations"), alloc(special_relations_decl_plugin));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ z3_add_component(rewriter
|
|||
factor_equivs.cpp
|
||||
factor_rewriter.cpp
|
||||
fpa_rewriter.cpp
|
||||
func_decl_replace.cpp
|
||||
hoist_rewriter.cpp
|
||||
inj_axiom.cpp
|
||||
label_rewriter.cpp
|
||||
|
|
|
@ -36,36 +36,48 @@ void array_rewriter::get_param_descrs(param_descrs & r) {
|
|||
|
||||
br_status array_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(f->get_family_id() == get_fid());
|
||||
TRACE("array_rewriter", tout << mk_pp(f, m()) << "\n";
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
tout << mk_pp(args[i], m()) << "\n";
|
||||
});
|
||||
br_status st;
|
||||
switch (f->get_decl_kind()) {
|
||||
case OP_SELECT:
|
||||
return mk_select_core(num_args, args, result);
|
||||
st = mk_select_core(num_args, args, result);
|
||||
break;
|
||||
case OP_STORE:
|
||||
return mk_store_core(num_args, args, result);
|
||||
st = mk_store_core(num_args, args, result);
|
||||
break;
|
||||
case OP_ARRAY_MAP:
|
||||
SASSERT(f->get_num_parameters() == 1);
|
||||
SASSERT(f->get_parameter(0).is_ast());
|
||||
SASSERT(is_func_decl(f->get_parameter(0).get_ast()));
|
||||
return mk_map_core(to_func_decl(f->get_parameter(0).get_ast()), num_args, args, result);
|
||||
st = mk_map_core(to_func_decl(f->get_parameter(0).get_ast()), num_args, args, result);
|
||||
break;
|
||||
case OP_SET_UNION:
|
||||
return mk_set_union(num_args, args, result);
|
||||
st = mk_set_union(num_args, args, result);
|
||||
break;
|
||||
case OP_SET_INTERSECT:
|
||||
return mk_set_intersect(num_args, args, result);
|
||||
st = mk_set_intersect(num_args, args, result);
|
||||
break;
|
||||
case OP_SET_SUBSET:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_set_subset(args[0], args[1], result);
|
||||
st = mk_set_subset(args[0], args[1], result);
|
||||
break;
|
||||
case OP_SET_COMPLEMENT:
|
||||
SASSERT(num_args == 1);
|
||||
return mk_set_complement(args[0], result);
|
||||
st = mk_set_complement(args[0], result);
|
||||
break;
|
||||
case OP_SET_DIFFERENCE:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_set_difference(args[0], args[1], result);
|
||||
st = mk_set_difference(args[0], args[1], result);
|
||||
break;
|
||||
default:
|
||||
return BR_FAILED;
|
||||
}
|
||||
TRACE("array_rewriter", tout << mk_pp(f, m()) << "\n";
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
tout << mk_pp(args[i], m()) << "\n";
|
||||
}
|
||||
tout << "\n --> " << result << "\n";
|
||||
);
|
||||
return st;
|
||||
}
|
||||
|
||||
// l_true -- all equal
|
||||
|
@ -230,105 +242,98 @@ br_status array_rewriter::mk_select_core(unsigned num_args, expr * const * args,
|
|||
}
|
||||
|
||||
br_status array_rewriter::mk_map_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num_args >= 0);
|
||||
bool is_store0 = m_util.is_store(args[0]);
|
||||
bool is_const0 = m_util.is_const(args[0]);
|
||||
if (num_args == 1) {
|
||||
//
|
||||
// map_f (store a j v) = (store (map_f a) j (f v))
|
||||
//
|
||||
if (is_store0) {
|
||||
app * store_expr = to_app(args[0]);
|
||||
unsigned num_args = store_expr->get_num_args();
|
||||
SASSERT(num_args >= 3);
|
||||
expr * a = store_expr->get_arg(0);
|
||||
expr * v = store_expr->get_arg(num_args-1);
|
||||
|
||||
ptr_buffer<expr> new_args;
|
||||
|
||||
new_args.push_back(m_util.mk_map(f, 1, &a)); // (map_f a)
|
||||
new_args.append(num_args - 2, store_expr->get_args() + 1); // j
|
||||
new_args.push_back(m().mk_app(f, v)); // (f v)
|
||||
|
||||
result = m().mk_app(get_fid(), OP_STORE, new_args.size(), new_args.c_ptr());
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
|
||||
//
|
||||
// map_f (const v) = (const (f v))
|
||||
//
|
||||
if (is_const0) {
|
||||
expr * fv = m().mk_app(f, to_app(args[0])->get_arg(0));
|
||||
result = m_util.mk_const_array(m().get_sort(args[0]), fv);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
SASSERT(num_args > 1);
|
||||
|
||||
if (is_store0) {
|
||||
unsigned num_indices = to_app(args[0])->get_num_args() - 2;
|
||||
unsigned i;
|
||||
for (i = 1; i < num_args; i++) {
|
||||
if (!m_util.is_store(args[i]))
|
||||
break;
|
||||
unsigned j;
|
||||
for (j = 1; j < num_indices+1; j++) {
|
||||
if (to_app(args[0])->get_arg(j) != to_app(args[i])->get_arg(j))
|
||||
break;
|
||||
}
|
||||
if (j < num_indices+1)
|
||||
break;
|
||||
app* store_expr = nullptr;
|
||||
unsigned num_indices = 0;
|
||||
bool same_store = true;
|
||||
for (unsigned i = 0; same_store && i < num_args; i++) {
|
||||
expr* a = args[i];
|
||||
if (m_util.is_const(a)) {
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// map_f (store a_1 j v_1) ... (store a_n j v_n) --> (store (map_f a_1 ... a_n) j (f v_1 ... v_n))
|
||||
//
|
||||
if (i == num_args) {
|
||||
ptr_buffer<expr> arrays;
|
||||
ptr_buffer<expr> values;
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
arrays.push_back(to_app(args[i])->get_arg(0));
|
||||
values.push_back(to_app(args[i])->get_arg(num_indices+1));
|
||||
else if (!m_util.is_store(a)) {
|
||||
same_store = false;
|
||||
}
|
||||
else if (!store_expr) {
|
||||
num_indices = to_app(a)->get_num_args() - 2;
|
||||
store_expr = to_app(a);
|
||||
}
|
||||
else {
|
||||
for (unsigned j = 1; same_store && j < num_indices + 1; j++) {
|
||||
same_store = (store_expr->get_arg(j) == to_app(a)->get_arg(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// map_f (store a_1 j v_1) ... (store a_n j v_n) --> (store (map_f a_1 ... a_n) j (f v_1 ... v_n))
|
||||
//
|
||||
if (same_store) {
|
||||
ptr_buffer<expr> arrays;
|
||||
ptr_buffer<expr> values;
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
expr* a = args[i];
|
||||
if (m_util.is_const(a)) {
|
||||
arrays.push_back(a);
|
||||
values.push_back(to_app(a)->get_arg(0));
|
||||
}
|
||||
else {
|
||||
arrays.push_back(to_app(a)->get_arg(0));
|
||||
values.push_back(to_app(a)->get_arg(num_indices+1));
|
||||
}
|
||||
}
|
||||
if (store_expr) {
|
||||
ptr_buffer<expr> new_args;
|
||||
new_args.push_back(m_util.mk_map(f, arrays.size(), arrays.c_ptr()));
|
||||
new_args.append(num_indices, to_app(args[0])->get_args() + 1);
|
||||
new_args.push_back(m().mk_app(f, values.size(), values.c_ptr()));
|
||||
result = m().mk_app(get_fid(), OP_STORE, new_args.size(), new_args.c_ptr());
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
return BR_FAILED;
|
||||
else {
|
||||
expr_ref value(m().mk_app(f, values.size(), values.c_ptr()), m());
|
||||
sort* s0 = m().get_sort(args[0]);
|
||||
unsigned sz = get_array_arity(s0);
|
||||
ptr_vector<sort> domain;
|
||||
for (unsigned i = 0; i < sz; ++i) domain.push_back(get_array_domain(s0, i));
|
||||
sort_ref s(m_util.mk_array_sort(sz, domain.c_ptr(), m().get_sort(value)), m());
|
||||
result = m_util.mk_const_array(s, value);
|
||||
}
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
|
||||
if (is_const0) {
|
||||
unsigned i;
|
||||
for (i = 1; i < num_args; i++) {
|
||||
if (!m_util.is_const(args[i]))
|
||||
break;
|
||||
//
|
||||
// map_f (lambda x1 b1) ... (lambda x1 bn) -> lambda x1 (f b1 .. bn)
|
||||
//
|
||||
quantifier* lam = nullptr;
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
if (is_lambda(args[i])) {
|
||||
lam = to_quantifier(args[i]);
|
||||
}
|
||||
if (i == num_args) {
|
||||
//
|
||||
// map_f (const v_1) ... (const v_n) = (const (f v_1 ... v_n))
|
||||
//
|
||||
ptr_buffer<expr> values;
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
values.push_back(to_app(args[i])->get_arg(0));
|
||||
}
|
||||
if (lam) {
|
||||
expr_ref_vector args1(m());
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
expr* a = args[i];
|
||||
if (m_util.is_const(a)) {
|
||||
args1.push_back(to_app(a)->get_arg(0));
|
||||
}
|
||||
else if (is_lambda(a)) {
|
||||
lam = to_quantifier(a);
|
||||
args1.push_back(lam->get_expr());
|
||||
}
|
||||
else {
|
||||
expr_ref_vector sel(m());
|
||||
sel.push_back(a);
|
||||
unsigned n = lam->get_num_decls();
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
sel.push_back(m().mk_var(n - i - 1, lam->get_decl_sort(i)));
|
||||
}
|
||||
args1.push_back(m_util.mk_select(sel.size(), sel.c_ptr()));
|
||||
}
|
||||
|
||||
expr * fv = m().mk_app(f, values.size(), values.c_ptr());
|
||||
sort * in_s = get_sort(args[0]);
|
||||
ptr_vector<sort> domain;
|
||||
unsigned domain_sz = get_array_arity(in_s);
|
||||
for (unsigned i = 0; i < domain_sz; i++)
|
||||
domain.push_back(get_array_domain(in_s, i));
|
||||
sort_ref out_s(m());
|
||||
out_s = m_util.mk_array_sort(domain_sz, domain.c_ptr(), f->get_range());
|
||||
parameter p(out_s.get());
|
||||
result = m().mk_app(get_fid(), OP_CONST_ARRAY, 1, &p, 1, &fv);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
return BR_FAILED;
|
||||
result = m().mk_app(f, args1.size(), args1.c_ptr());
|
||||
result = m().update_quantifier(lam, result);
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
|
@ -396,10 +401,107 @@ br_status array_rewriter::mk_set_subset(expr * arg1, expr * arg2, expr_ref & res
|
|||
return BR_REWRITE3;
|
||||
}
|
||||
|
||||
void array_rewriter::mk_eq(expr* e, expr* lhs, expr* rhs, expr_ref_vector& fmls) {
|
||||
expr_ref tmp1(m()), tmp2(m());
|
||||
expr_ref a(m()), v(m());
|
||||
expr_ref_vector args0(m()), args(m());
|
||||
while (m_util.is_store_ext(e, a, args0, v)) {
|
||||
args.reset();
|
||||
args.push_back(lhs);
|
||||
args.append(args0);
|
||||
mk_select(args.size(), args.c_ptr(), tmp1);
|
||||
args[0] = rhs;
|
||||
mk_select(args.size(), args.c_ptr(), tmp2);
|
||||
fmls.push_back(m().mk_eq(tmp1, tmp2));
|
||||
e = a;
|
||||
}
|
||||
}
|
||||
|
||||
bool array_rewriter::has_index_set(expr* e, expr_ref& e0, vector<expr_ref_vector>& indices) {
|
||||
expr_ref_vector args(m());
|
||||
expr_ref a(m()), v(m());
|
||||
a = e;
|
||||
while (m_util.is_store_ext(e, a, args, v)) {
|
||||
indices.push_back(args);
|
||||
e = a;
|
||||
}
|
||||
e0 = e;
|
||||
if (is_lambda(e0)) {
|
||||
quantifier* q = to_quantifier(e0);
|
||||
e = q->get_expr();
|
||||
unsigned num_idxs = q->get_num_decls();
|
||||
expr* e1, *e2, *e3;
|
||||
ptr_vector<expr> eqs;
|
||||
while (!is_ground(e) && m().is_ite(e, e1, e2, e3) && is_ground(e2)) {
|
||||
args.reset();
|
||||
args.resize(num_idxs, nullptr);
|
||||
eqs.reset();
|
||||
eqs.push_back(e1);
|
||||
for (unsigned i = 0; i < eqs.size(); ++i) {
|
||||
expr* e = eqs[i];
|
||||
if (m().is_and(e)) {
|
||||
eqs.append(to_app(e)->get_num_args(), to_app(e)->get_args());
|
||||
}
|
||||
else if (m().is_eq(e, e1, e2)) {
|
||||
if (is_var(e2)) {
|
||||
std::swap(e1, e2);
|
||||
}
|
||||
if (is_var(e1) && is_ground(e2)) {
|
||||
unsigned idx = to_var(e1)->get_idx();
|
||||
args[num_idxs - idx - 1] = e2;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < num_idxs; ++i) {
|
||||
if (!args.get(i)) return false;
|
||||
}
|
||||
indices.push_back(args);
|
||||
e = e3;
|
||||
}
|
||||
e0 = e;
|
||||
return is_ground(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
br_status array_rewriter::mk_eq_core(expr * lhs, expr * rhs, expr_ref & result) {
|
||||
TRACE("array_rewriter", tout << mk_pp(lhs, m()) << " " << mk_pp(rhs, m()) << "\n";);
|
||||
expr* v = nullptr;
|
||||
if (m_util.is_const(rhs) && is_lambda(lhs)) {
|
||||
std::swap(lhs, rhs);
|
||||
}
|
||||
if (m_util.is_const(lhs, v) && is_lambda(rhs)) {
|
||||
quantifier* lam = to_quantifier(rhs);
|
||||
expr_ref e(m().mk_eq(lam->get_expr(), v), m());
|
||||
result = m().update_quantifier(lam, quantifier_kind::forall_k, e);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (!m_expand_store_eq) {
|
||||
return BR_FAILED;
|
||||
}
|
||||
expr_ref_vector fmls(m());
|
||||
|
||||
#if 0
|
||||
// lambda friendly version of array equality rewriting.
|
||||
vector<expr_ref_vector> indices;
|
||||
expr_ref lhs0(m()), rhs0(m());
|
||||
expr_ref tmp1(m()), tmp2(m());
|
||||
if (has_index_set(lhs, lhs0, indices) && has_index_set(rhs, rhs0, indices) && lhs0 == rhs0) {
|
||||
expr_ref_vector args(m());
|
||||
for (auto const& idxs : indices) {
|
||||
args.reset();
|
||||
args.push_back(lhs);
|
||||
args.append(idxs);
|
||||
mk_select(args.size(), args.c_ptr(), tmp1);
|
||||
args[0] = rhs;
|
||||
mk_select(args.size(), args.c_ptr(), tmp2);
|
||||
fmls.push_back(m().mk_eq(tmp1, tmp2));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
expr* lhs1 = lhs;
|
||||
while (m_util.is_store(lhs1)) {
|
||||
lhs1 = to_app(lhs1)->get_arg(0);
|
||||
|
@ -411,25 +513,9 @@ br_status array_rewriter::mk_eq_core(expr * lhs, expr * rhs, expr_ref & result)
|
|||
if (lhs1 != rhs1) {
|
||||
return BR_FAILED;
|
||||
}
|
||||
ptr_buffer<expr> fmls, args;
|
||||
expr* e;
|
||||
expr_ref tmp1(m()), tmp2(m());
|
||||
#define MK_EQ() \
|
||||
while (m_util.is_store(e)) { \
|
||||
args.push_back(lhs); \
|
||||
args.append(to_app(e)->get_num_args()-2,to_app(e)->get_args()+1); \
|
||||
mk_select(args.size(), args.c_ptr(), tmp1); \
|
||||
args[0] = rhs; \
|
||||
mk_select(args.size(), args.c_ptr(), tmp2); \
|
||||
fmls.push_back(m().mk_eq(tmp1, tmp2)); \
|
||||
e = to_app(e)->get_arg(0); \
|
||||
args.reset(); \
|
||||
} \
|
||||
|
||||
e = lhs;
|
||||
MK_EQ();
|
||||
e = rhs;
|
||||
MK_EQ();
|
||||
|
||||
mk_eq(lhs, lhs, rhs, fmls);
|
||||
mk_eq(rhs, lhs, rhs, fmls);
|
||||
result = m().mk_and(fmls.size(), fmls.c_ptr());
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ class array_rewriter {
|
|||
bool m_expand_select_ite;
|
||||
template<bool CHECK_DISEQ>
|
||||
lbool compare_args(unsigned num_args, expr * const * args1, expr * const * args2);
|
||||
bool has_index_set(expr* e, expr_ref& e0, vector<expr_ref_vector>& indices);
|
||||
void mk_eq(expr* e, expr* lhs, expr* rhs, expr_ref_vector& fmls);
|
||||
public:
|
||||
array_rewriter(ast_manager & m, params_ref const & p = params_ref()):
|
||||
m_util(m) {
|
||||
|
@ -43,6 +45,7 @@ public:
|
|||
}
|
||||
ast_manager & m() const { return m_util.get_manager(); }
|
||||
family_id get_fid() const { return m_util.get_family_id(); }
|
||||
array_util& util() { return m_util; }
|
||||
|
||||
void set_expand_select_store(bool f) { m_expand_select_store = f; }
|
||||
void set_expand_select_ite(bool f) { m_expand_select_ite = f; }
|
||||
|
@ -66,6 +69,20 @@ public:
|
|||
br_status mk_set_difference(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_set_subset(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_eq_core(expr * lhs, expr * rhs, expr_ref & result);
|
||||
|
||||
expr_ref mk_set_difference(expr* a, expr* b) {
|
||||
expr_ref result(m());
|
||||
mk_set_difference(a, b, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
expr_ref mk_set_intersect(expr* a, expr* b) {
|
||||
expr_ref result(m());
|
||||
expr* args[2] = { a, b };
|
||||
mk_set_intersect(2, args, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,7 @@ void bool_rewriter::updt_params(params_ref const & _p) {
|
|||
bool_rewriter_params p(_p);
|
||||
m_flat = p.flat();
|
||||
m_elim_and = p.elim_and();
|
||||
m_elim_ite = p.elim_ite();
|
||||
m_local_ctx = p.local_ctx();
|
||||
m_local_ctx_limit = p.local_ctx_limit();
|
||||
m_blast_distinct = p.blast_distinct();
|
||||
|
@ -797,48 +798,52 @@ br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & re
|
|||
result = c;
|
||||
return BR_DONE;
|
||||
}
|
||||
mk_or(c, e, result);
|
||||
return BR_DONE;
|
||||
if (m_elim_ite) {
|
||||
mk_or(c, e, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
if (m().is_false(t)) {
|
||||
if (m().is_true(e)) {
|
||||
mk_not(c, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
expr_ref tmp(m());
|
||||
mk_not(c, tmp);
|
||||
mk_and(tmp, e, result);
|
||||
return BR_DONE;
|
||||
if (m_elim_ite) {
|
||||
expr_ref tmp(m());
|
||||
mk_not(c, tmp);
|
||||
mk_and(tmp, e, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
if (m().is_true(e)) {
|
||||
if (m().is_true(e) && m_elim_ite) {
|
||||
expr_ref tmp(m());
|
||||
mk_not(c, tmp);
|
||||
mk_or(tmp, t, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m().is_false(e)) {
|
||||
if (m().is_false(e) && m_elim_ite) {
|
||||
mk_and(c, t, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (c == e) {
|
||||
if (c == e && m_elim_ite) {
|
||||
mk_and(c, t, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (c == t) {
|
||||
if (c == t && m_elim_ite) {
|
||||
mk_or(c, e, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m().is_complement_core(t, e)) { // t = not(e)
|
||||
if (m().is_complement_core(t, e) && m_elim_ite) { // t = not(e)
|
||||
mk_eq(c, t, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m().is_complement_core(e, t)) { // e = not(t)
|
||||
if (m().is_complement_core(e, t) && m_elim_ite) { // e = not(t)
|
||||
mk_eq(c, t, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (m().is_ite(t) && m_ite_extra_rules) {
|
||||
if (m().is_ite(t) && m_ite_extra_rules && m_elim_ite) {
|
||||
// (ite c1 (ite c2 t1 t2) t1) ==> (ite (and c1 (not c2)) t2 t1)
|
||||
if (e == to_app(t)->get_arg(1)) {
|
||||
expr_ref not_c2(m());
|
||||
|
@ -891,7 +896,7 @@ br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & re
|
|||
}
|
||||
}
|
||||
|
||||
if (m().is_ite(e) && m_ite_extra_rules) {
|
||||
if (m().is_ite(e) && m_ite_extra_rules && m_elim_ite) {
|
||||
// (ite c1 t1 (ite c2 t1 t2)) ==> (ite (or c1 c2) t1 t2)
|
||||
if (t == to_app(e)->get_arg(1)) {
|
||||
expr_ref new_c(m());
|
||||
|
|
|
@ -59,6 +59,7 @@ class bool_rewriter {
|
|||
bool m_ite_extra_rules;
|
||||
unsigned m_local_ctx_limit;
|
||||
unsigned m_local_ctx_cost;
|
||||
bool m_elim_ite;
|
||||
|
||||
br_status mk_flat_and_core(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
br_status mk_flat_or_core(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
|
|
|
@ -4,6 +4,7 @@ def_module_params(module_name='rewriter',
|
|||
params=(("ite_extra_rules", BOOL, False, "extra ite simplifications, these additional simplifications may reduce size locally but increase globally"),
|
||||
("flat", BOOL, True, "create nary applications for and,or,+,*,bvadd,bvmul,bvand,bvor,bvxor"),
|
||||
("elim_and", BOOL, False, "conjunctions are rewritten using negation and disjunctions"),
|
||||
('elim_ite', BOOL, True, "eliminate ite in favor of and/or"),
|
||||
("local_ctx", BOOL, False, "perform local (i.e., cheap) context simplifications"),
|
||||
("local_ctx_limit", UINT, UINT_MAX, "limit for applying local context simplifier"),
|
||||
("blast_distinct", BOOL, False, "expand a distinct predicate into a quadratic number of disequalities"),
|
||||
|
|
|
@ -500,12 +500,14 @@ br_status bv_rewriter::mk_leq_core(bool is_signed, expr * a, expr * b, expr_ref
|
|||
// (bvsle (- x (srem x c1)) c2) -> (bvsle x (+ c1 c2 - 1))
|
||||
// (bvsle (+ x (* -1 (srem_i x c1))) c2)
|
||||
// pre: (and (> c1 0) (> c2 0) (= c2 % c1 0) (<= (+ c1 c2 -1) max_int))
|
||||
if (is_signed && is_num2 && m_util.is_bv_add(a, a1, a2) &&
|
||||
if (is_signed && is_num2 &&
|
||||
m_util.is_bv_add(a, a1, a2) &&
|
||||
m_util.is_bv_mul(a2, a3, a4) && is_numeral(a3, r1, sz) &&
|
||||
m_util.norm(r1, sz, is_signed).is_minus_one() &&
|
||||
m_util.is_bv_sremi(a4, a5, a6) && is_numeral(a6, r1, sz) &&
|
||||
(r1 = m_util.norm(r1, sz, is_signed), r1.is_pos()) &&
|
||||
r2.is_pos() &&
|
||||
(a1 == a5) &&
|
||||
(r2 % r1).is_zero() && r1 + r2 - rational::one() < rational::power_of_two(sz-1)) {
|
||||
result = m_util.mk_sle(a1, m_util.mk_numeral(r1 + r2 - rational::one(), sz));
|
||||
return BR_REWRITE2;
|
||||
|
|
|
@ -86,7 +86,7 @@ struct enum2bv_rewriter::imp {
|
|||
void throw_non_fd(expr* e) {
|
||||
std::stringstream strm;
|
||||
strm << "unable to handle nested data-type expression " << mk_pp(e, m);
|
||||
throw rewriter_exception(strm.str().c_str());
|
||||
throw rewriter_exception(strm.str());
|
||||
}
|
||||
|
||||
void check_for_fd(unsigned n, expr* const* args) {
|
||||
|
|
97
src/ast/rewriter/func_decl_replace.cpp
Normal file
97
src/ast/rewriter/func_decl_replace.cpp
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*++
|
||||
Copyright (c) 2019 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
func_decl_replace.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Replace functions in expressions.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2019-03-28
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#include "ast/rewriter/func_decl_replace.h"
|
||||
|
||||
expr_ref func_decl_replace::operator()(expr* e) {
|
||||
m_todo.push_back(e);
|
||||
|
||||
while (!m_todo.empty()) {
|
||||
expr* a = m_todo.back(), *b;
|
||||
if (m_cache.contains(a)) {
|
||||
m_todo.pop_back();
|
||||
}
|
||||
else if (is_var(a)) {
|
||||
m_cache.insert(a, a);
|
||||
m_todo.pop_back();
|
||||
}
|
||||
else if (is_app(a)) {
|
||||
app* c = to_app(a);
|
||||
unsigned n = c->get_num_args();
|
||||
m_args.reset();
|
||||
bool arg_differs = false;
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
expr* d = nullptr, *arg = c->get_arg(i);
|
||||
if (m_cache.find(arg, d)) {
|
||||
m_args.push_back(d);
|
||||
arg_differs |= arg != d;
|
||||
SASSERT(m.get_sort(arg) == m.get_sort(d));
|
||||
}
|
||||
else {
|
||||
m_todo.push_back(arg);
|
||||
}
|
||||
}
|
||||
if (m_args.size() == n) {
|
||||
if (arg_differs) {
|
||||
b = m.mk_app(c->get_decl(), m_args.size(), m_args.c_ptr());
|
||||
m_refs.push_back(b);
|
||||
SASSERT(m.get_sort(a) == m.get_sort(b));
|
||||
} else {
|
||||
b = a;
|
||||
}
|
||||
func_decl* f = nullptr;
|
||||
if (m_subst.find(c->get_decl(), f)) {
|
||||
b = m.mk_app(f, m_args.size(), m_args.c_ptr());
|
||||
m_refs.push_back(b);
|
||||
}
|
||||
m_cache.insert(a, b);
|
||||
m_todo.pop_back();
|
||||
}
|
||||
}
|
||||
else {
|
||||
quantifier* q = to_quantifier(a);
|
||||
SASSERT(is_quantifier(a));
|
||||
expr* body = q->get_expr(), *new_body;
|
||||
if (m_cache.find(body, new_body)) {
|
||||
if (new_body == body) {
|
||||
b = a;
|
||||
}
|
||||
else {
|
||||
b = m.update_quantifier(q, new_body);
|
||||
m_refs.push_back(b);
|
||||
}
|
||||
m_cache.insert(a, b);
|
||||
m_todo.pop_back();
|
||||
}
|
||||
else {
|
||||
m_todo.push_back(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
return expr_ref(m_cache.find(e), m);
|
||||
}
|
||||
|
||||
void func_decl_replace::reset() {
|
||||
m_cache.reset();
|
||||
m_subst.reset();
|
||||
m_refs.reset();
|
||||
m_funs.reset();
|
||||
}
|
46
src/ast/rewriter/func_decl_replace.h
Normal file
46
src/ast/rewriter/func_decl_replace.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*++
|
||||
Copyright (c) 2019 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
func_decl_replace.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Replace functions in expressions.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2019-03-28
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef FUNC_DECL_REPLACE_H_
|
||||
#define FUNC_DECL_REPLACE_H_
|
||||
|
||||
#include "ast/ast.h"
|
||||
|
||||
class func_decl_replace {
|
||||
ast_manager& m;
|
||||
obj_map<func_decl, func_decl*> m_subst;
|
||||
obj_map<expr, expr*> m_cache;
|
||||
ptr_vector<expr> m_todo, m_args;
|
||||
expr_ref_vector m_refs;
|
||||
func_decl_ref_vector m_funs;
|
||||
|
||||
public:
|
||||
func_decl_replace(ast_manager& m): m(m), m_refs(m), m_funs(m) {}
|
||||
|
||||
void insert(func_decl* src, func_decl* dst) { m_subst.insert(src, dst); m_funs.push_back(src), m_funs.push_back(dst); }
|
||||
|
||||
expr_ref operator()(expr* e);
|
||||
|
||||
void reset();
|
||||
|
||||
bool empty() const { return m_subst.empty(); }
|
||||
};
|
||||
|
||||
#endif /* FUNC_DECL_REPLACE_H_ */
|
|
@ -28,7 +28,7 @@ Notes:
|
|||
#include "util/uint_set.h"
|
||||
#include "util/gparams.h"
|
||||
|
||||
const unsigned g_primes[7] = { 2, 3, 5, 7, 11, 13, 17};
|
||||
static const unsigned g_primes[7] = { 2, 3, 5, 7, 11, 13, 17};
|
||||
|
||||
|
||||
struct pb2bv_rewriter::imp {
|
||||
|
@ -161,7 +161,6 @@ struct pb2bv_rewriter::imp {
|
|||
}
|
||||
|
||||
if (m_pb_solver == "segmented") {
|
||||
expr_ref result(m);
|
||||
switch (is_le) {
|
||||
case l_true: return mk_seg_le(k);
|
||||
case l_false: return mk_seg_ge(k);
|
||||
|
@ -169,6 +168,11 @@ struct pb2bv_rewriter::imp {
|
|||
}
|
||||
}
|
||||
|
||||
if (m_pb_solver == "binary_merge") {
|
||||
expr_ref result = binary_merge(is_le, k);
|
||||
if (result) return result;
|
||||
}
|
||||
|
||||
// fall back to divide and conquer encoding.
|
||||
SASSERT(k.is_pos());
|
||||
expr_ref zero(m), bound(m);
|
||||
|
@ -494,6 +498,37 @@ struct pb2bv_rewriter::imp {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief binary merge encoding.
|
||||
*/
|
||||
expr_ref binary_merge(lbool is_le, rational const& k) {
|
||||
expr_ref result(m);
|
||||
unsigned_vector coeffs;
|
||||
for (rational const& c : m_coeffs) {
|
||||
if (c.is_unsigned()) {
|
||||
coeffs.push_back(c.get_unsigned());
|
||||
}
|
||||
else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (!k.is_unsigned()) {
|
||||
return result;
|
||||
}
|
||||
switch (is_le) {
|
||||
case l_true:
|
||||
result = m_sort.le(k.get_unsigned(), coeffs.size(), coeffs.c_ptr(), m_args.c_ptr());
|
||||
break;
|
||||
case l_false:
|
||||
result = m_sort.ge(k.get_unsigned(), coeffs.size(), coeffs.c_ptr(), m_args.c_ptr());
|
||||
break;
|
||||
case l_undef:
|
||||
result = m_sort.eq(k.get_unsigned(), coeffs.size(), coeffs.c_ptr(), m_args.c_ptr());
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Segment based encoding.
|
||||
The PB terms are partitoned into segments, such that each segment contains arguments with the same cofficient.
|
||||
|
|
|
@ -300,7 +300,7 @@ protected:
|
|||
void process_var(var * v);
|
||||
|
||||
template<bool ProofGen>
|
||||
void process_const(app * t);
|
||||
bool process_const(app * t);
|
||||
|
||||
template<bool ProofGen>
|
||||
bool visit(expr * t, unsigned max_depth);
|
||||
|
|
|
@ -80,27 +80,42 @@ void rewriter_tpl<Config>::process_var(var * v) {
|
|||
|
||||
template<typename Config>
|
||||
template<bool ProofGen>
|
||||
void rewriter_tpl<Config>::process_const(app * t) {
|
||||
bool rewriter_tpl<Config>::process_const(app * t0) {
|
||||
app_ref t(t0, m());
|
||||
bool retried = false;
|
||||
retry:
|
||||
SASSERT(t->get_num_args() == 0);
|
||||
br_status st = m_cfg.reduce_app(t->get_decl(), 0, nullptr, m_r, m_pr);
|
||||
SASSERT(st != BR_DONE || m().get_sort(m_r) == m().get_sort(t));
|
||||
SASSERT(st == BR_FAILED || st == BR_DONE);
|
||||
if (st == BR_DONE) {
|
||||
switch (st) {
|
||||
case BR_FAILED:
|
||||
if (!retried) {
|
||||
result_stack().push_back(t);
|
||||
if (ProofGen)
|
||||
result_pr_stack().push_back(nullptr); // implicit reflexivity
|
||||
return true;
|
||||
}
|
||||
m_r = t;
|
||||
// fall through
|
||||
case BR_DONE:
|
||||
result_stack().push_back(m_r.get());
|
||||
if (ProofGen) {
|
||||
if (m_pr)
|
||||
result_pr_stack().push_back(m_pr);
|
||||
else
|
||||
result_pr_stack().push_back(m().mk_rewrite(t, m_r));
|
||||
result_pr_stack().push_back(m().mk_rewrite(t0, m_r));
|
||||
m_pr = nullptr;
|
||||
}
|
||||
m_r = nullptr;
|
||||
set_new_child_flag(t);
|
||||
}
|
||||
else {
|
||||
result_stack().push_back(t);
|
||||
if (ProofGen)
|
||||
result_pr_stack().push_back(nullptr); // implicit reflexivity
|
||||
set_new_child_flag(t0);
|
||||
return true;
|
||||
default:
|
||||
if (is_app(m_r) && to_app(m_r)->get_num_args() == 0) {
|
||||
t = to_app(m_r);
|
||||
retried = true;
|
||||
goto retry;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,6 +130,7 @@ void rewriter_tpl<Config>::process_const(app * t) {
|
|||
template<typename Config>
|
||||
template<bool ProofGen>
|
||||
bool rewriter_tpl<Config>::visit(expr * t, unsigned max_depth) {
|
||||
// retry:
|
||||
TRACE("rewriter_visit", tout << "visiting\n" << mk_ismt2_pp(t, m()) << "\n";);
|
||||
expr * new_t = nullptr;
|
||||
proof * new_t_pr = nullptr;
|
||||
|
@ -164,15 +180,14 @@ bool rewriter_tpl<Config>::visit(expr * t, unsigned max_depth) {
|
|||
switch (t->get_kind()) {
|
||||
case AST_APP:
|
||||
if (to_app(t)->get_num_args() == 0) {
|
||||
process_const<ProofGen>(to_app(t));
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (max_depth != RW_UNBOUNDED_DEPTH)
|
||||
max_depth--;
|
||||
push_frame(t, c, max_depth);
|
||||
return false;
|
||||
if (process_const<ProofGen>(to_app(t)))
|
||||
return true;
|
||||
t = m_r;
|
||||
}
|
||||
if (max_depth != RW_UNBOUNDED_DEPTH)
|
||||
max_depth--;
|
||||
push_frame(t, c, max_depth);
|
||||
return false;
|
||||
case AST_VAR:
|
||||
process_var<ProofGen>(to_var(t));
|
||||
return true;
|
||||
|
@ -224,7 +239,7 @@ bool rewriter_tpl<Config>::constant_fold(app * t, frame & fr) {
|
|||
template<typename Config>
|
||||
template<bool ProofGen>
|
||||
void rewriter_tpl<Config>::process_app(app * t, frame & fr) {
|
||||
SASSERT(t->get_num_args() > 0);
|
||||
// SASSERT(t->get_num_args() > 0);
|
||||
SASSERT(!frame_stack().empty());
|
||||
switch (fr.m_state) {
|
||||
case PROCESS_CHILDREN: {
|
||||
|
|
|
@ -46,7 +46,7 @@ inline br_status unsigned2br_status(unsigned u) {
|
|||
|
||||
class rewriter_exception : public default_exception {
|
||||
public:
|
||||
rewriter_exception(char const * msg):default_exception(msg) {}
|
||||
rewriter_exception(std::string && msg) : default_exception(std::move(msg)) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -391,44 +391,57 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
|
|||
|
||||
case OP_SEQ_UNIT:
|
||||
SASSERT(num_args == 1);
|
||||
return mk_seq_unit(args[0], result);
|
||||
st = mk_seq_unit(args[0], result);
|
||||
break;
|
||||
case OP_SEQ_EMPTY:
|
||||
return BR_FAILED;
|
||||
case OP_RE_PLUS:
|
||||
SASSERT(num_args == 1);
|
||||
return mk_re_plus(args[0], result);
|
||||
st = mk_re_plus(args[0], result);
|
||||
break;
|
||||
case OP_RE_STAR:
|
||||
SASSERT(num_args == 1);
|
||||
st = mk_re_star(args[0], result);
|
||||
break;
|
||||
case OP_RE_OPTION:
|
||||
SASSERT(num_args == 1);
|
||||
return mk_re_opt(args[0], result);
|
||||
st = mk_re_opt(args[0], result);
|
||||
break;
|
||||
case OP_RE_CONCAT:
|
||||
if (num_args == 1) {
|
||||
result = args[0];
|
||||
return BR_DONE;
|
||||
st = BR_DONE;
|
||||
}
|
||||
else {
|
||||
SASSERT(num_args == 2);
|
||||
st = mk_re_concat(args[0], args[1], result);
|
||||
}
|
||||
SASSERT(num_args == 2);
|
||||
st = mk_re_concat(args[0], args[1], result);
|
||||
break;
|
||||
case OP_RE_UNION:
|
||||
if (num_args == 1) {
|
||||
result = args[0]; return BR_DONE;
|
||||
result = args[0];
|
||||
st = BR_DONE;
|
||||
}
|
||||
SASSERT(num_args == 2);
|
||||
return mk_re_union(args[0], args[1], result);
|
||||
else {
|
||||
SASSERT(num_args == 2);
|
||||
st = mk_re_union(args[0], args[1], result);
|
||||
}
|
||||
break;
|
||||
case OP_RE_RANGE:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_re_range(args[0], args[1], result);
|
||||
st = mk_re_range(args[0], args[1], result);
|
||||
break;
|
||||
case OP_RE_INTERSECT:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_re_inter(args[0], args[1], result);
|
||||
st = mk_re_inter(args[0], args[1], result);
|
||||
break;
|
||||
case OP_RE_COMPLEMENT:
|
||||
SASSERT(num_args == 1);
|
||||
return mk_re_complement(args[0], result);
|
||||
st = mk_re_complement(args[0], result);
|
||||
break;
|
||||
case OP_RE_LOOP:
|
||||
return mk_re_loop(num_args, args, result);
|
||||
st = mk_re_loop(num_args, args, result);
|
||||
break;
|
||||
case OP_RE_EMPTY_SET:
|
||||
return BR_FAILED;
|
||||
case OP_RE_FULL_SEQ_SET:
|
||||
|
@ -442,23 +455,29 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
|
|||
case OP_SEQ_CONCAT:
|
||||
if (num_args == 1) {
|
||||
result = args[0];
|
||||
return BR_DONE;
|
||||
st = BR_DONE;
|
||||
}
|
||||
SASSERT(num_args == 2);
|
||||
return mk_seq_concat(args[0], args[1], result);
|
||||
else {
|
||||
SASSERT(num_args == 2);
|
||||
st = mk_seq_concat(args[0], args[1], result);
|
||||
}
|
||||
break;
|
||||
case OP_SEQ_LENGTH:
|
||||
SASSERT(num_args == 1);
|
||||
return mk_seq_length(args[0], result);
|
||||
st = mk_seq_length(args[0], result);
|
||||
break;
|
||||
case OP_SEQ_EXTRACT:
|
||||
SASSERT(num_args == 3);
|
||||
st = mk_seq_extract(args[0], args[1], args[2], result);
|
||||
break;
|
||||
case OP_SEQ_CONTAINS:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_seq_contains(args[0], args[1], result);
|
||||
st = mk_seq_contains(args[0], args[1], result);
|
||||
break;
|
||||
case OP_SEQ_AT:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_seq_at(args[0], args[1], result);
|
||||
st = mk_seq_at(args[0], args[1], result);
|
||||
break;
|
||||
#if 0
|
||||
case OP_SEQ_NTH:
|
||||
SASSERT(num_args == 2);
|
||||
|
@ -466,35 +485,49 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
|
|||
#endif
|
||||
case OP_SEQ_PREFIX:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_seq_prefix(args[0], args[1], result);
|
||||
st = mk_seq_prefix(args[0], args[1], result);
|
||||
break;
|
||||
case OP_SEQ_SUFFIX:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_seq_suffix(args[0], args[1], result);
|
||||
st = mk_seq_suffix(args[0], args[1], result);
|
||||
break;
|
||||
case OP_SEQ_INDEX:
|
||||
if (num_args == 2) {
|
||||
expr_ref arg3(m_autil.mk_int(0), m());
|
||||
result = m_util.str.mk_index(args[0], args[1], arg3);
|
||||
return BR_REWRITE1;
|
||||
st = BR_REWRITE1;
|
||||
}
|
||||
SASSERT(num_args == 3);
|
||||
return mk_seq_index(args[0], args[1], args[2], result);
|
||||
else {
|
||||
SASSERT(num_args == 3);
|
||||
st = mk_seq_index(args[0], args[1], args[2], result);
|
||||
}
|
||||
break;
|
||||
case OP_SEQ_LAST_INDEX:
|
||||
SASSERT(num_args == 2);
|
||||
st = mk_seq_last_index(args[0], args[1], result);
|
||||
break;
|
||||
case OP_SEQ_REPLACE:
|
||||
SASSERT(num_args == 3);
|
||||
return mk_seq_replace(args[0], args[1], args[2], result);
|
||||
st = mk_seq_replace(args[0], args[1], args[2], result);
|
||||
break;
|
||||
case OP_SEQ_TO_RE:
|
||||
SASSERT(num_args == 1);
|
||||
return mk_str_to_regexp(args[0], result);
|
||||
st = mk_str_to_regexp(args[0], result);
|
||||
break;
|
||||
case OP_SEQ_IN_RE:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_str_in_regexp(args[0], args[1], result);
|
||||
st = mk_str_in_regexp(args[0], args[1], result);
|
||||
break;
|
||||
case OP_STRING_CONST:
|
||||
return BR_FAILED;
|
||||
case OP_STRING_ITOS:
|
||||
SASSERT(num_args == 1);
|
||||
return mk_str_itos(args[0], result);
|
||||
st = mk_str_itos(args[0], result);
|
||||
break;
|
||||
case OP_STRING_STOI:
|
||||
SASSERT(num_args == 1);
|
||||
return mk_str_stoi(args[0], result);
|
||||
st = mk_str_stoi(args[0], result);
|
||||
break;
|
||||
case _OP_STRING_CONCAT:
|
||||
case _OP_STRING_PREFIX:
|
||||
case _OP_STRING_SUFFIX:
|
||||
|
@ -908,6 +941,18 @@ br_status seq_rewriter::mk_seq_nth(expr* a, expr* b, expr_ref& result) {
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_seq_last_index(expr* a, expr* b, expr_ref& result) {
|
||||
zstring s1, s2;
|
||||
bool isc1 = m_util.str.is_string(a, s1);
|
||||
bool isc2 = m_util.str.is_string(b, s2);
|
||||
if (isc1 && isc2) {
|
||||
int idx = s1.last_indexof(s2);
|
||||
result = m_autil.mk_numeral(rational(idx), true);
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_seq_index(expr* a, expr* b, expr* c, expr_ref& result) {
|
||||
zstring s1, s2;
|
||||
rational r;
|
||||
|
|
|
@ -116,6 +116,7 @@ class seq_rewriter {
|
|||
br_status mk_seq_at(expr* a, expr* b, expr_ref& result);
|
||||
br_status mk_seq_nth(expr* a, expr* b, expr_ref& result);
|
||||
br_status mk_seq_index(expr* a, expr* b, expr* c, expr_ref& result);
|
||||
br_status mk_seq_last_index(expr* a, expr* b, expr_ref& result);
|
||||
br_status mk_seq_replace(expr* a, expr* b, expr* c, expr_ref& result);
|
||||
br_status mk_seq_prefix(expr* a, expr* b, expr_ref& result);
|
||||
br_status mk_seq_suffix(expr* a, expr* b, expr_ref& result);
|
||||
|
|
|
@ -32,6 +32,7 @@ Notes:
|
|||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/expr_substitution.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/well_sorted.h"
|
||||
|
||||
|
@ -184,7 +185,6 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
st = m_ar_rw.mk_eq_core(args[0], args[1], result);
|
||||
else if (s_fid == m_seq_rw.get_fid())
|
||||
st = m_seq_rw.mk_eq_core(args[0], args[1], result);
|
||||
|
||||
if (st != BR_FAILED)
|
||||
return st;
|
||||
}
|
||||
|
@ -583,6 +583,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
m().trace_stream() << "[instance] " << static_cast<void *>(nullptr) << " #" << tmp->get_id() << "\n";
|
||||
m().trace_stream() << "[attach-enode] #" << tmp->get_id() << " 0\n";
|
||||
m().trace_stream() << "[end-of-instance]\n";
|
||||
m().trace_stream().flush();
|
||||
}
|
||||
|
||||
if (st != BR_DONE && st != BR_FAILED) {
|
||||
|
@ -661,6 +662,13 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
p1 = m().mk_pull_quant(old_q, q1);
|
||||
}
|
||||
}
|
||||
else if (
|
||||
old_q->get_kind() == lambda_k &&
|
||||
is_ground(new_body)) {
|
||||
result = m_ar_rw.util().mk_const_array(old_q->get_sort(), new_body);
|
||||
result_pr = nullptr;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
ptr_buffer<expr> new_patterns_buf;
|
||||
ptr_buffer<expr> new_no_patterns_buf;
|
||||
|
@ -677,10 +685,10 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
TRACE("reduce_quantifier", tout << mk_ismt2_pp(old_q, m()) << "\n----->\n" << mk_ismt2_pp(q1, m()) << "\n";);
|
||||
SASSERT(is_well_sorted(m(), q1));
|
||||
}
|
||||
|
||||
SASSERT(m().get_sort(old_q) == m().get_sort(q1));
|
||||
result = elim_unused_vars(m(), q1, params_ref());
|
||||
|
||||
|
||||
TRACE("reduce_quantifier", tout << "after elim_unused_vars:\n" << result << "\n";);
|
||||
|
||||
result_pr = nullptr;
|
||||
|
@ -839,3 +847,13 @@ expr_ref th_rewriter::mk_app(func_decl* f, unsigned num_args, expr* const* args)
|
|||
void th_rewriter::set_solver(expr_solver* solver) {
|
||||
m_imp->set_solver(solver);
|
||||
}
|
||||
|
||||
|
||||
bool th_rewriter::reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
return m_imp->cfg().reduce_quantifier(old_q, new_body, new_patterns, new_no_patterns, result, result_pr);
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
static void get_param_descrs(param_descrs & r);
|
||||
unsigned get_cache_size() const;
|
||||
unsigned get_num_steps() const;
|
||||
|
||||
|
||||
void operator()(expr_ref& term);
|
||||
void operator()(expr * t, expr_ref & result);
|
||||
void operator()(expr * t, expr_ref & result, proof_ref & result_pr);
|
||||
|
@ -49,6 +49,13 @@ public:
|
|||
|
||||
expr_ref mk_app(func_decl* f, unsigned num_args, expr* const* args);
|
||||
|
||||
bool reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr);
|
||||
|
||||
void cleanup();
|
||||
void reset();
|
||||
|
||||
|
|
|
@ -273,6 +273,21 @@ int zstring::indexof(zstring const& other, int offset) const {
|
|||
return -1;
|
||||
}
|
||||
|
||||
int zstring::last_indexof(zstring const& other) const {
|
||||
if (other.length() == 0) return length();
|
||||
if (other.length() > length()) return -1;
|
||||
for (unsigned last = length() - other.length(); last-- > 0; ) {
|
||||
bool suffix = true;
|
||||
for (unsigned j = 0; suffix && j < other.length(); ++j) {
|
||||
suffix = m_buffer[last + j] == other[j];
|
||||
}
|
||||
if (suffix) {
|
||||
return static_cast<int>(last);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
zstring zstring::extract(int offset, int len) const {
|
||||
zstring result(m_encoding);
|
||||
SASSERT(0 <= offset && 0 <= len);
|
||||
|
@ -400,7 +415,7 @@ void seq_decl_plugin::match_right_assoc(psig& sig, unsigned dsz, sort *const* do
|
|||
std::ostringstream strm;
|
||||
strm << "Unexpected number of arguments to '" << sig.m_name << "' ";
|
||||
strm << "at least one argument expected " << dsz << " given";
|
||||
m.raise_exception(strm.str().c_str());
|
||||
m.raise_exception(strm.str());
|
||||
}
|
||||
bool is_match = true;
|
||||
for (unsigned i = 0; is_match && i < dsz; ++i) {
|
||||
|
@ -420,7 +435,7 @@ void seq_decl_plugin::match_right_assoc(psig& sig, unsigned dsz, sort *const* do
|
|||
if (range) {
|
||||
strm << " and range: " << mk_pp(range, m);
|
||||
}
|
||||
m.raise_exception(strm.str().c_str());
|
||||
m.raise_exception(strm.str());
|
||||
}
|
||||
range_out = apply_binding(binding, sig.m_range);
|
||||
SASSERT(range_out);
|
||||
|
@ -434,7 +449,7 @@ void seq_decl_plugin::match(psig& sig, unsigned dsz, sort *const* dom, sort* ran
|
|||
std::ostringstream strm;
|
||||
strm << "Unexpected number of arguments to '" << sig.m_name << "' ";
|
||||
strm << sig.m_dom.size() << " arguments expected " << dsz << " given";
|
||||
m.raise_exception(strm.str().c_str());
|
||||
m.raise_exception(strm.str());
|
||||
}
|
||||
bool is_match = true;
|
||||
for (unsigned i = 0; is_match && i < dsz; ++i) {
|
||||
|
@ -459,13 +474,13 @@ void seq_decl_plugin::match(psig& sig, unsigned dsz, sort *const* dom, sort* ran
|
|||
strm << mk_pp(sig.m_dom[i].get(), m) << " ";
|
||||
}
|
||||
|
||||
m.raise_exception(strm.str().c_str());
|
||||
m.raise_exception(strm.str());
|
||||
}
|
||||
if (!range && dsz == 0) {
|
||||
std::ostringstream strm;
|
||||
strm << "Sort of polymorphic function '" << sig.m_name << "' ";
|
||||
strm << "is ambiguous. Function takes no arguments and sort of range has not been constrained";
|
||||
m.raise_exception(strm.str().c_str());
|
||||
m.raise_exception(strm.str());
|
||||
}
|
||||
range_out = apply_binding(m_binding, sig.m_range);
|
||||
SASSERT(range_out);
|
||||
|
@ -530,6 +545,7 @@ void seq_decl_plugin::init() {
|
|||
m_sigs[OP_SEQ_EXTRACT] = alloc(psig, m, "seq.extract", 1, 3, seqAint2T, seqA);
|
||||
m_sigs[OP_SEQ_REPLACE] = alloc(psig, m, "seq.replace", 1, 3, seq3A, seqA);
|
||||
m_sigs[OP_SEQ_INDEX] = alloc(psig, m, "seq.indexof", 1, 3, seq2AintT, intT);
|
||||
m_sigs[OP_SEQ_LAST_INDEX] = alloc(psig, m, "seq.last_indexof", 1, 2, seqAseqA, intT);
|
||||
m_sigs[OP_SEQ_AT] = alloc(psig, m, "seq.at", 1, 2, seqAintT, seqA);
|
||||
m_sigs[OP_SEQ_NTH] = alloc(psig, m, "seq.nth", 1, 2, seqAintT, A);
|
||||
m_sigs[OP_SEQ_LENGTH] = alloc(psig, m, "seq.len", 1, 1, &seqA, intT);
|
||||
|
@ -774,7 +790,13 @@ func_decl * seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
|
|||
return m.mk_func_decl(m_sigs[k]->m_name, arity, domain, rng, func_decl_info(m_family_id, OP_SEQ_INDEX));
|
||||
}
|
||||
return mk_str_fun(k, arity, domain, range, OP_SEQ_INDEX);
|
||||
|
||||
case OP_SEQ_LAST_INDEX:
|
||||
if (arity != 2) {
|
||||
m.raise_exception("two arguments expected tin last_indexof");
|
||||
}
|
||||
else {
|
||||
return mk_seq_fun(k, arity, domain, range, OP_SEQ_LAST_INDEX);
|
||||
}
|
||||
case OP_SEQ_PREFIX:
|
||||
return mk_seq_fun(k, arity, domain, range, _OP_STRING_PREFIX);
|
||||
case _OP_STRING_PREFIX:
|
||||
|
|
|
@ -43,6 +43,7 @@ enum seq_op_kind {
|
|||
OP_SEQ_NTH,
|
||||
OP_SEQ_LENGTH,
|
||||
OP_SEQ_INDEX,
|
||||
OP_SEQ_LAST_INDEX,
|
||||
OP_SEQ_TO_RE,
|
||||
OP_SEQ_IN_RE,
|
||||
|
||||
|
@ -113,6 +114,7 @@ public:
|
|||
bool prefixof(zstring const& other) const;
|
||||
bool contains(zstring const& other) const;
|
||||
int indexof(zstring const& other, int offset) const;
|
||||
int last_indexof(zstring const& other) const;
|
||||
zstring extract(int lo, int hi) const;
|
||||
zstring operator+(zstring const& other) const;
|
||||
bool operator==(const zstring& other) const;
|
||||
|
@ -260,6 +262,7 @@ public:
|
|||
app* mk_prefix(expr* a, expr* b) const { expr* es[2] = { a, b }; return m.mk_app(m_fid, OP_SEQ_PREFIX, 2, es); }
|
||||
app* mk_suffix(expr* a, expr* b) const { expr* es[2] = { a, b }; return m.mk_app(m_fid, OP_SEQ_SUFFIX, 2, es); }
|
||||
app* mk_index(expr* a, expr* b, expr* i) const { expr* es[3] = { a, b, i}; return m.mk_app(m_fid, OP_SEQ_INDEX, 3, es); }
|
||||
app* mk_last_index(expr* a, expr* b) const { expr* es[2] = { a, b}; return m.mk_app(m_fid, OP_SEQ_LAST_INDEX, 2, es); }
|
||||
app* mk_unit(expr* u) const { return m.mk_app(m_fid, OP_SEQ_UNIT, 1, &u); }
|
||||
app* mk_char(zstring const& s, unsigned idx) const;
|
||||
app* mk_itos(expr* i) const { return m.mk_app(m_fid, OP_STRING_ITOS, 1, &i); }
|
||||
|
@ -285,6 +288,7 @@ public:
|
|||
bool is_nth(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_NTH); }
|
||||
bool is_nth(expr const* n, expr*& s, unsigned& idx) const;
|
||||
bool is_index(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_INDEX); }
|
||||
bool is_last_index(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_LAST_INDEX); }
|
||||
bool is_replace(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_REPLACE); }
|
||||
bool is_prefix(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_PREFIX); }
|
||||
bool is_suffix(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_SUFFIX); }
|
||||
|
@ -311,6 +315,7 @@ public:
|
|||
MATCH_BINARY(is_nth);
|
||||
MATCH_BINARY(is_index);
|
||||
MATCH_TERNARY(is_index);
|
||||
MATCH_BINARY(is_last_index);
|
||||
MATCH_TERNARY(is_replace);
|
||||
MATCH_BINARY(is_prefix);
|
||||
MATCH_BINARY(is_suffix);
|
||||
|
|
83
src/ast/special_relations_decl_plugin.cpp
Normal file
83
src/ast/special_relations_decl_plugin.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*++
|
||||
Copyright (c) 2015 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
special_relations_decl_plugin.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2015-15-9.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include <sstream>
|
||||
#include "ast/ast.h"
|
||||
#include "ast/special_relations_decl_plugin.h"
|
||||
|
||||
special_relations_decl_plugin::special_relations_decl_plugin():
|
||||
m_lo("linear-order"),
|
||||
m_po("partial-order"),
|
||||
m_plo("piecewise-linear-order"),
|
||||
m_to("tree-order"),
|
||||
m_tc("transitive-closure")
|
||||
{}
|
||||
|
||||
func_decl * special_relations_decl_plugin::mk_func_decl(
|
||||
decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range)
|
||||
{
|
||||
if (arity != 2) {
|
||||
m_manager->raise_exception("special relations should have arity 2");
|
||||
return nullptr;
|
||||
}
|
||||
if (domain[0] != domain[1]) {
|
||||
m_manager->raise_exception("argument sort missmatch. The two arguments should have the same sort");
|
||||
return nullptr;
|
||||
}
|
||||
if (!range) {
|
||||
range = m_manager->mk_bool_sort();
|
||||
}
|
||||
if (!m_manager->is_bool(range)) {
|
||||
m_manager->raise_exception("range type is expected to be Boolean for special relations");
|
||||
}
|
||||
func_decl_info info(m_family_id, k, num_parameters, parameters);
|
||||
symbol name;
|
||||
switch(k) {
|
||||
case OP_SPECIAL_RELATION_PO: name = m_po; break;
|
||||
case OP_SPECIAL_RELATION_LO: name = m_lo; break;
|
||||
case OP_SPECIAL_RELATION_PLO: name = m_plo; break;
|
||||
case OP_SPECIAL_RELATION_TO: name = m_to; break;
|
||||
case OP_SPECIAL_RELATION_TC: name = m_tc; break;
|
||||
}
|
||||
return m_manager->mk_func_decl(name, arity, domain, range, info);
|
||||
}
|
||||
|
||||
void special_relations_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const & logic) {
|
||||
if (logic == symbol::null) {
|
||||
op_names.push_back(builtin_name(m_po.bare_str(), OP_SPECIAL_RELATION_PO));
|
||||
op_names.push_back(builtin_name(m_lo.bare_str(), OP_SPECIAL_RELATION_LO));
|
||||
op_names.push_back(builtin_name(m_plo.bare_str(), OP_SPECIAL_RELATION_PLO));
|
||||
op_names.push_back(builtin_name(m_to.bare_str(), OP_SPECIAL_RELATION_TO));
|
||||
op_names.push_back(builtin_name(m_tc.bare_str(), OP_SPECIAL_RELATION_TC));
|
||||
}
|
||||
}
|
||||
|
||||
sr_property special_relations_util::get_property(func_decl* f) const {
|
||||
switch (f->get_decl_kind()) {
|
||||
case OP_SPECIAL_RELATION_PO: return sr_po;
|
||||
case OP_SPECIAL_RELATION_LO: return sr_lo;
|
||||
case OP_SPECIAL_RELATION_PLO: return sr_plo;
|
||||
case OP_SPECIAL_RELATION_TO: return sr_to;
|
||||
case OP_SPECIAL_RELATION_TC: return sr_tc;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return sr_po;
|
||||
}
|
||||
}
|
108
src/ast/special_relations_decl_plugin.h
Normal file
108
src/ast/special_relations_decl_plugin.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*++
|
||||
Copyright (c) 2015 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
special_relations_decl_plugin.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2015-15-9.
|
||||
Ashutosh Gupta 2016
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef SPECIAL_RELATIONS_DECL_PLUGIN_H_
|
||||
#define SPECIAL_RELATIONS_DECL_PLUGIN_H_
|
||||
|
||||
#include "ast/ast.h"
|
||||
|
||||
|
||||
enum special_relations_op_kind {
|
||||
OP_SPECIAL_RELATION_LO,
|
||||
OP_SPECIAL_RELATION_PO,
|
||||
OP_SPECIAL_RELATION_PLO,
|
||||
OP_SPECIAL_RELATION_TO,
|
||||
OP_SPECIAL_RELATION_TC,
|
||||
LAST_SPECIAL_RELATIONS_OP
|
||||
};
|
||||
|
||||
class special_relations_decl_plugin : public decl_plugin {
|
||||
symbol m_lo;
|
||||
symbol m_po;
|
||||
symbol m_plo;
|
||||
symbol m_to;
|
||||
symbol m_tc;
|
||||
public:
|
||||
special_relations_decl_plugin();
|
||||
|
||||
~special_relations_decl_plugin() override {}
|
||||
|
||||
decl_plugin * mk_fresh() override {
|
||||
return alloc(special_relations_decl_plugin);
|
||||
}
|
||||
|
||||
func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) override;
|
||||
|
||||
void get_op_names(svector<builtin_name> & op_names, symbol const & logic) override;
|
||||
|
||||
sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) override { return nullptr; }
|
||||
};
|
||||
|
||||
enum sr_property {
|
||||
sr_none = 0x00,
|
||||
sr_transitive = 0x01, // Rxy & Ryz -> Rxz
|
||||
sr_reflexive = 0x02, // Rxx
|
||||
sr_antisymmetric = 0x04, // Rxy & Ryx -> x = y
|
||||
sr_lefttree = 0x08, // Ryx & Rzx -> Ryz | Rzy
|
||||
sr_righttree = 0x10, // Rxy & Rxz -> Ryx | Rzy
|
||||
sr_total = 0x20, // Rxy | Ryx
|
||||
sr_po = 0x01 | 0x02 | 0x04, // partial order
|
||||
sr_to = 0x01 | 0x02 | 0x04 | 0x10, // right-tree
|
||||
sr_plo = 0x01 | 0x02 | 0x04 | 0x08 | 0x10, // piecewise linear order
|
||||
sr_lo = 0x01 | 0x02 | 0x04 | 0x20, // linear order
|
||||
sr_tc = 0x40, // transitive closure of relation
|
||||
};
|
||||
|
||||
class special_relations_util {
|
||||
ast_manager& m;
|
||||
family_id m_fid;
|
||||
func_decl* mk_rel_decl(func_decl* f, decl_kind k) {
|
||||
parameter p(f); SASSERT(f->get_arity() == 2);
|
||||
return m.mk_func_decl(m_fid, k, 1, &p, 2, f->get_domain(), f->get_range());
|
||||
}
|
||||
public:
|
||||
special_relations_util(ast_manager& m) : m(m), m_fid(m.get_family_id("special_relations")) {}
|
||||
|
||||
bool is_special_relation(func_decl* f) const { return f->get_family_id() == m_fid; }
|
||||
bool is_special_relation(app* e) const { return is_special_relation(e->get_decl()); }
|
||||
sr_property get_property(func_decl* f) const;
|
||||
sr_property get_property(app* e) const { return get_property(e->get_decl()); }
|
||||
|
||||
func_decl* mk_to_decl(func_decl* f) { return mk_rel_decl(f, OP_SPECIAL_RELATION_TO); }
|
||||
func_decl* mk_po_decl(func_decl* f) { return mk_rel_decl(f, OP_SPECIAL_RELATION_PO); }
|
||||
func_decl* mk_plo_decl(func_decl* f) { return mk_rel_decl(f, OP_SPECIAL_RELATION_PLO); }
|
||||
func_decl* mk_lo_decl(func_decl* f) { return mk_rel_decl(f, OP_SPECIAL_RELATION_LO); }
|
||||
func_decl* mk_tc_decl(func_decl* f) { return mk_rel_decl(f, OP_SPECIAL_RELATION_TC); }
|
||||
|
||||
bool is_lo(expr const * e) const { return is_app_of(e, m_fid, OP_SPECIAL_RELATION_LO); }
|
||||
bool is_po(expr const * e) const { return is_app_of(e, m_fid, OP_SPECIAL_RELATION_PO); }
|
||||
bool is_plo(expr const * e) const { return is_app_of(e, m_fid, OP_SPECIAL_RELATION_PLO); }
|
||||
bool is_to(expr const * e) const { return is_app_of(e, m_fid, OP_SPECIAL_RELATION_TO); }
|
||||
bool is_tc(expr const * e) const { return is_app_of(e, m_fid, OP_SPECIAL_RELATION_TC); }
|
||||
|
||||
app * mk_lo (expr * arg1, expr * arg2) { return m.mk_app( m_fid, OP_SPECIAL_RELATION_LO, arg1, arg2); }
|
||||
app * mk_po (expr * arg1, expr * arg2) { return m.mk_app( m_fid, OP_SPECIAL_RELATION_PO, arg1, arg2); }
|
||||
app * mk_plo(expr * arg1, expr * arg2) { return m.mk_app( m_fid, OP_SPECIAL_RELATION_PLO, arg1, arg2); }
|
||||
app * mk_to (expr * arg1, expr * arg2) { return m.mk_app( m_fid, OP_SPECIAL_RELATION_TO, arg1, arg2); }
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* SPECIAL_RELATIONS_DECL_PLUGIN_H_ */
|
|
@ -30,6 +30,7 @@ static_features::static_features(ast_manager & m):
|
|||
m_afid(m.mk_family_id("arith")),
|
||||
m_lfid(m.mk_family_id("label")),
|
||||
m_arrfid(m.mk_family_id("array")),
|
||||
m_srfid(m.mk_family_id("special_relations")),
|
||||
m_label_sym("label"),
|
||||
m_pattern_sym("pattern"),
|
||||
m_expr_list_sym("expr-list") {
|
||||
|
@ -78,6 +79,7 @@ void static_features::reset() {
|
|||
m_has_real = false;
|
||||
m_has_bv = false;
|
||||
m_has_fpa = false;
|
||||
m_has_sr = false;
|
||||
m_has_str = false;
|
||||
m_has_seq_non_str = false;
|
||||
m_has_arrays = false;
|
||||
|
@ -274,6 +276,8 @@ void static_features::update_core(expr * e) {
|
|||
m_has_bv = true;
|
||||
if (!m_has_fpa && (m_fpautil.is_float(e) || m_fpautil.is_rm(e)))
|
||||
m_has_fpa = true;
|
||||
if (is_app(e) && to_app(e)->get_family_id() == m_srfid)
|
||||
m_has_sr = true;
|
||||
if (!m_has_arrays && m_arrayutil.is_array(e))
|
||||
m_has_arrays = true;
|
||||
if (!m_has_ext_arrays && m_arrayutil.is_array(e) &&
|
||||
|
@ -281,9 +285,8 @@ void static_features::update_core(expr * e) {
|
|||
m_has_ext_arrays = true;
|
||||
if (!m_has_str && m_sequtil.str.is_string_term(e))
|
||||
m_has_str = true;
|
||||
if (!m_has_seq_non_str && m_sequtil.str.is_non_string_sequence(e)) {
|
||||
if (!m_has_seq_non_str && m_sequtil.str.is_non_string_sequence(e))
|
||||
m_has_seq_non_str = true;
|
||||
}
|
||||
if (is_app(e)) {
|
||||
family_id fid = to_app(e)->get_family_id();
|
||||
mark_theory(fid);
|
||||
|
|
|
@ -25,6 +25,7 @@ Revision History:
|
|||
#include "ast/array_decl_plugin.h"
|
||||
#include "ast/fpa_decl_plugin.h"
|
||||
#include "ast/seq_decl_plugin.h"
|
||||
#include "ast/special_relations_decl_plugin.h"
|
||||
#include "util/map.h"
|
||||
|
||||
struct static_features {
|
||||
|
@ -38,6 +39,7 @@ struct static_features {
|
|||
family_id m_afid;
|
||||
family_id m_lfid;
|
||||
family_id m_arrfid;
|
||||
family_id m_srfid;
|
||||
ast_mark m_already_visited;
|
||||
bool m_cnf;
|
||||
unsigned m_num_exprs; //
|
||||
|
@ -79,6 +81,7 @@ struct static_features {
|
|||
bool m_has_real; //
|
||||
bool m_has_bv; //
|
||||
bool m_has_fpa; //
|
||||
bool m_has_sr; // has special relations
|
||||
bool m_has_str; // has String-typed terms
|
||||
bool m_has_seq_non_str; // has non-String-typed Sequence terms
|
||||
bool m_has_arrays; //
|
||||
|
|
|
@ -629,6 +629,7 @@ class get_info_cmd : public cmd {
|
|||
symbol m_reason_unknown;
|
||||
symbol m_all_statistics;
|
||||
symbol m_assertion_stack_levels;
|
||||
symbol m_rlimit;
|
||||
public:
|
||||
get_info_cmd():
|
||||
cmd("get-info"),
|
||||
|
@ -639,7 +640,8 @@ public:
|
|||
m_status(":status"),
|
||||
m_reason_unknown(":reason-unknown"),
|
||||
m_all_statistics(":all-statistics"),
|
||||
m_assertion_stack_levels(":assertion-stack-levels") {
|
||||
m_assertion_stack_levels(":assertion-stack-levels"),
|
||||
m_rlimit(":rlimit") {
|
||||
}
|
||||
char const * get_usage() const override { return "<keyword>"; }
|
||||
char const * get_descr(cmd_context & ctx) const override { return "get information."; }
|
||||
|
@ -671,6 +673,9 @@ public:
|
|||
else if (opt == m_reason_unknown) {
|
||||
ctx.regular_stream() << "(:reason-unknown \"" << escaped(ctx.reason_unknown().c_str()) << "\")" << std::endl;
|
||||
}
|
||||
else if (opt == m_rlimit) {
|
||||
ctx.regular_stream() << "(:rlimit " << ctx.m().limit().count() << ")" << std::endl;
|
||||
}
|
||||
else if (opt == m_all_statistics) {
|
||||
ctx.display_statistics();
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ Notes:
|
|||
#include "ast/pb_decl_plugin.h"
|
||||
#include "ast/fpa_decl_plugin.h"
|
||||
#include "ast/csp_decl_plugin.h"
|
||||
#include "ast/special_relations_decl_plugin.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/pp.h"
|
||||
|
@ -687,6 +688,7 @@ void cmd_context::init_manager_core(bool new_manager) {
|
|||
register_plugin(symbol("fpa"), alloc(fpa_decl_plugin), logic_has_fpa());
|
||||
register_plugin(symbol("datalog_relation"), alloc(datalog::dl_decl_plugin), !has_logic());
|
||||
register_plugin(symbol("csp"), alloc(csp_decl_plugin), smt_logics::logic_is_csp(m_logic));
|
||||
register_plugin(symbol("special_relations"), alloc(special_relations_decl_plugin), !has_logic());
|
||||
}
|
||||
else {
|
||||
// the manager was created by an external module
|
||||
|
@ -703,6 +705,7 @@ void cmd_context::init_manager_core(bool new_manager) {
|
|||
load_plugin(symbol("fpa"), logic_has_fpa(), fids);
|
||||
load_plugin(symbol("pb"), logic_has_pb(), fids);
|
||||
load_plugin(symbol("csp"), smt_logics::logic_is_csp(m_logic), fids);
|
||||
|
||||
for (family_id fid : fids) {
|
||||
decl_plugin * p = m_manager->get_plugin(fid);
|
||||
if (p) {
|
||||
|
@ -797,7 +800,7 @@ void cmd_context::insert(symbol const & s, func_decl * f) {
|
|||
msg += " '";
|
||||
msg += s.str();
|
||||
msg += "' (with the given signature) already declared";
|
||||
throw cmd_exception(msg.c_str());
|
||||
throw cmd_exception(std::move(msg));
|
||||
}
|
||||
if (s != f->get_name()) {
|
||||
TRACE("func_decl_alias", tout << "adding alias for: " << f->get_name() << ", alias: " << s << "\n";);
|
||||
|
@ -1142,7 +1145,7 @@ void cmd_context::mk_app(symbol const & s, unsigned num_args, expr * const * arg
|
|||
for (unsigned i = 0; i < fs.get_num_entries(); ++i) {
|
||||
buffer << "\ndeclared: " << mk_pp(fs.get_entry(i), m()) << " ";
|
||||
}
|
||||
throw cmd_exception(buffer.str().c_str());
|
||||
throw cmd_exception(buffer.str());
|
||||
}
|
||||
if (well_sorted_check_enabled())
|
||||
m().check_sort(f, num_args, args);
|
||||
|
|
|
@ -71,6 +71,7 @@ public:
|
|||
expr_ref r(ctx.m());
|
||||
unsigned timeout = m_params.get_uint("timeout", UINT_MAX);
|
||||
unsigned rlimit = m_params.get_uint("rlimit", 0);
|
||||
// md->compress();
|
||||
model_evaluator ev(*(md.get()), m_params);
|
||||
ev.set_solver(alloc(th_solver, ctx));
|
||||
cancel_eh<reslimit> eh(ctx.m().limit());
|
||||
|
|
|
@ -203,7 +203,7 @@ void func_interp::insert_new_entry(expr * const * args, expr * r) {
|
|||
}
|
||||
tout << "Old: " << mk_ismt2_pp(get_entry(args)->get_result(), m_manager) << "\n";
|
||||
);
|
||||
SASSERT(get_entry(args) == 0);
|
||||
SASSERT(get_entry(args) == nullptr);
|
||||
func_entry * new_entry = func_entry::mk(m_manager, m_arity, args, r);
|
||||
if (!new_entry->args_are_values())
|
||||
m_args_are_values = false;
|
||||
|
|
|
@ -170,7 +170,11 @@ struct model::top_sort : public ::top_sort<func_decl> {
|
|||
|
||||
top_sort(ast_manager& m):
|
||||
m_rewrite(m)
|
||||
{}
|
||||
{
|
||||
params_ref p;
|
||||
p.set_bool("elim_ite", false);
|
||||
m_rewrite.updt_params(p);
|
||||
}
|
||||
|
||||
void add_occurs(func_decl* f) {
|
||||
m_occur_count.insert(f, occur_count(f) + 1);
|
||||
|
@ -217,6 +221,7 @@ void model::compress() {
|
|||
}
|
||||
}
|
||||
if (removed.empty()) break;
|
||||
TRACE("model", tout << "remove\n"; for (func_decl* f : removed) tout << f->get_name() << "\n";);
|
||||
remove_decls(m_decls, removed);
|
||||
remove_decls(m_func_decls, removed);
|
||||
remove_decls(m_const_decls, removed);
|
||||
|
@ -427,7 +432,7 @@ expr_ref model::cleanup_expr(top_sort& ts, expr* e, unsigned current_partition)
|
|||
}
|
||||
#endif
|
||||
else {
|
||||
new_t = ts.m_rewrite.mk_app(f, args.size(), args.c_ptr());
|
||||
new_t = ts.m_rewrite.mk_app(f, args.size(), args.c_ptr());
|
||||
}
|
||||
|
||||
if (t != new_t.get()) trail.push_back(new_t);
|
||||
|
@ -442,7 +447,7 @@ expr_ref model::cleanup_expr(top_sort& ts, expr* e, unsigned current_partition)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ts.m_rewrite(cache[e], new_t);
|
||||
return new_t;
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ void model_core::register_decl(func_decl * d, expr * v) {
|
|||
}
|
||||
|
||||
void model_core::register_decl(func_decl * d, func_interp * fi) {
|
||||
TRACE("model", tout << "register " << d->get_name() << "\n";);
|
||||
SASSERT(d->get_arity() > 0);
|
||||
SASSERT(&fi->m() == &m);
|
||||
decl2finterp::obj_map_entry * entry = m_finterp.insert_if_not_there2(d, nullptr);
|
||||
|
|
|
@ -30,12 +30,14 @@ Revision History:
|
|||
#include "ast/rewriter/datatype_rewriter.h"
|
||||
#include "ast/rewriter/array_rewriter.h"
|
||||
#include "ast/rewriter/fpa_rewriter.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
#include "ast/rewriter/rewriter_def.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "model/model_smt2_pp.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
|
||||
namespace {
|
||||
|
||||
struct evaluator_cfg : public default_rewriter_cfg {
|
||||
ast_manager & m;
|
||||
|
@ -53,7 +55,6 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
unsigned long long m_max_memory;
|
||||
unsigned m_max_steps;
|
||||
bool m_model_completion;
|
||||
bool m_cache;
|
||||
bool m_array_equalities;
|
||||
bool m_array_as_stores;
|
||||
obj_map<func_decl, expr*> m_def_cache;
|
||||
|
@ -91,7 +92,6 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
model_evaluator_params p(_p);
|
||||
m_max_memory = megabytes_to_bytes(p.max_memory());
|
||||
m_max_steps = p.max_steps();
|
||||
m_cache = p.cache();
|
||||
m_model_completion = p.completion();
|
||||
m_array_equalities = p.array_equalities();
|
||||
m_array_as_stores = p.array_as_stores();
|
||||
|
@ -99,7 +99,11 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
|
||||
bool evaluate(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
func_interp * fi = m_model.get_func_interp(f);
|
||||
return (fi != nullptr) && eval_fi(fi, num, args, result);
|
||||
bool r = (fi != nullptr) && eval_fi(fi, num, args, result);
|
||||
CTRACE("model_evaluator", r, tout << "reduce_app " << f->get_name() << "\n";
|
||||
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m) << "\n";
|
||||
tout << "---->\n" << mk_ismt2_pp(result, m) << "\n";);
|
||||
return r;
|
||||
}
|
||||
|
||||
// Try to use the entries to quickly evaluate the fi
|
||||
|
@ -126,35 +130,49 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
th_rewriter th(m);
|
||||
return th.reduce_quantifier(old_q, new_body, new_patterns, new_no_patterns, result, result_pr);
|
||||
}
|
||||
|
||||
|
||||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
||||
TRACE("model_evaluator", tout << f->get_name() << "\n";);
|
||||
result_pr = nullptr;
|
||||
family_id fid = f->get_family_id();
|
||||
bool is_uninterp = fid != null_family_id && m.get_plugin(fid)->is_considered_uninterpreted(f);
|
||||
br_status st = BR_FAILED;
|
||||
if (num == 0 && (fid == null_family_id || is_uninterp)) {
|
||||
expr * val = m_model.get_const_interp(f);
|
||||
if (val != nullptr) {
|
||||
result = val;
|
||||
return BR_DONE;
|
||||
return m_ar.is_as_array(val)? BR_REWRITE1 : BR_DONE;
|
||||
}
|
||||
|
||||
if (m_model_completion) {
|
||||
else if (m_model_completion) {
|
||||
sort * s = f->get_range();
|
||||
expr * val = m_model.get_some_value(s);
|
||||
m_model.register_decl(f, val);
|
||||
result = val;
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
else {
|
||||
return BR_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
br_status st = BR_FAILED;
|
||||
|
||||
if (fid == m_b_rw.get_fid()) {
|
||||
decl_kind k = f->get_decl_kind();
|
||||
if (k == OP_EQ) {
|
||||
// theory dispatch for =
|
||||
SASSERT(num == 2);
|
||||
family_id s_fid = m.get_sort(args[0])->get_family_id();
|
||||
sort* s = m.get_sort(args[0]);
|
||||
family_id s_fid = s->get_family_id();
|
||||
if (s_fid == m_a_rw.get_fid())
|
||||
st = m_a_rw.mk_eq_core(args[0], args[1], result);
|
||||
else if (s_fid == m_bv_rw.get_fid())
|
||||
|
@ -167,12 +185,15 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
st = m_seq_rw.mk_eq_core(args[0], args[1], result);
|
||||
else if (s_fid == m_ar_rw.get_fid())
|
||||
st = mk_array_eq(args[0], args[1], result);
|
||||
TRACE("model_evaluator",
|
||||
tout << st << " " << mk_pp(s, m) << " " << s_fid << " " << m_ar_rw.get_fid() << " "
|
||||
<< mk_pp(args[0], m) << " " << mk_pp(args[1], m) << " " << result << "\n";);
|
||||
if (st != BR_FAILED)
|
||||
return st;
|
||||
}
|
||||
return m_b_rw.mk_app_core(f, num, args, result);
|
||||
}
|
||||
|
||||
CTRACE("model_evaluator", st != BR_FAILED, tout << result << "\n";);
|
||||
if (fid == m_a_rw.get_fid())
|
||||
st = m_a_rw.mk_app_core(f, num, args, result);
|
||||
else if (fid == m_bv_rw.get_fid())
|
||||
|
@ -192,20 +213,19 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
st = BR_DONE;
|
||||
}
|
||||
else if (evaluate(f, num, args, result)) {
|
||||
TRACE("model_evaluator", tout << "reduce_app " << f->get_name() << "\n";
|
||||
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m) << "\n";
|
||||
tout << "---->\n" << mk_ismt2_pp(result, m) << "\n";);
|
||||
return BR_REWRITE1;
|
||||
st = BR_REWRITE1;
|
||||
}
|
||||
if (st == BR_FAILED && !m.is_builtin_family_id(fid))
|
||||
CTRACE("model_evaluator", st != BR_FAILED, tout << result << "\n";);
|
||||
if (st == BR_FAILED && !m.is_builtin_family_id(fid)) {
|
||||
st = evaluate_partial_theory_func(f, num, args, result, result_pr);
|
||||
CTRACE("model_evaluator", st != BR_FAILED, tout << result << "\n";);
|
||||
}
|
||||
if (st == BR_DONE && is_app(result)) {
|
||||
app* a = to_app(result);
|
||||
if (evaluate(a->get_decl(), a->get_num_args(), a->get_args(), result)) {
|
||||
return BR_REWRITE1;
|
||||
st = BR_REWRITE1;
|
||||
}
|
||||
}
|
||||
#if 1
|
||||
if (st == BR_FAILED && num == 0 && m_ar.is_as_array(f) && m_model_completion) {
|
||||
func_decl* g = nullptr;
|
||||
VERIFY(m_ar.is_as_array(f, g));
|
||||
|
@ -236,13 +256,13 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
CTRACE("model_evaluator", st != BR_FAILED, tout << result << "\n";);
|
||||
return st;
|
||||
}
|
||||
|
||||
void expand_stores(expr_ref& val) {
|
||||
TRACE("model_evaluator", tout << val << "\n";);
|
||||
vector<expr_ref_vector> stores;
|
||||
expr_ref else_case(m);
|
||||
bool _unused;
|
||||
|
@ -278,7 +298,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
return false;
|
||||
}
|
||||
def = fi->get_interp();
|
||||
SASSERT(def != 0);
|
||||
SASSERT(def != nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -302,7 +322,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
br_status evaluate_partial_theory_func(func_decl * f,
|
||||
unsigned num, expr * const * args,
|
||||
expr_ref & result, proof_ref & result_pr) {
|
||||
SASSERT(f != 0);
|
||||
SASSERT(f != nullptr);
|
||||
SASSERT(!m.is_builtin_family_id(f->get_family_id()));
|
||||
result = nullptr;
|
||||
result_pr = nullptr;
|
||||
|
@ -328,8 +348,6 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
return num_steps > m_max_steps;
|
||||
}
|
||||
|
||||
bool cache_results() const { return m_cache; }
|
||||
|
||||
br_status mk_array_eq(expr* a, expr* b, expr_ref& result) {
|
||||
TRACE("model_evaluator", tout << "mk_array_eq " << m_array_equalities << "\n";);
|
||||
if (a == b) {
|
||||
|
@ -337,7 +355,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
return BR_DONE;
|
||||
}
|
||||
if (!m_array_equalities) {
|
||||
return BR_FAILED;
|
||||
return m_ar_rw.mk_eq_core(a, b, result);
|
||||
}
|
||||
|
||||
vector<expr_ref_vector> stores1, stores2;
|
||||
|
@ -378,7 +396,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
);
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
return BR_FAILED;
|
||||
return m_ar_rw.mk_eq_core(a, b, result);
|
||||
}
|
||||
|
||||
struct args_eq {
|
||||
|
@ -417,8 +435,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
args_table table2(DEFAULT_HASHTABLE_INITIAL_CAPACITY, ah, ae);
|
||||
|
||||
// stores with smaller index take precedence
|
||||
for (unsigned i = stores1.size(); i > 0; ) {
|
||||
--i;
|
||||
for (unsigned i = stores1.size(); i-- > 0; ) {
|
||||
table1.insert(stores1[i].c_ptr());
|
||||
}
|
||||
|
||||
|
@ -495,6 +512,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
|
||||
if (!m_ar.is_as_array(a)) {
|
||||
TRACE("model_evaluator", tout << "no translation: " << mk_pp(a, m) << "\n";);
|
||||
TRACE("model_evaluator", tout << m_model << "\n";);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -544,8 +562,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template class rewriter_tpl<evaluator_cfg>;
|
||||
}
|
||||
|
||||
struct model_evaluator::imp : public rewriter_tpl<evaluator_cfg> {
|
||||
evaluator_cfg m_cfg;
|
||||
|
@ -557,6 +574,11 @@ struct model_evaluator::imp : public rewriter_tpl<evaluator_cfg> {
|
|||
set_cancel_check(false);
|
||||
}
|
||||
void expand_stores(expr_ref &val) {m_cfg.expand_stores(val);}
|
||||
void reset() {
|
||||
rewriter_tpl<evaluator_cfg>::reset();
|
||||
m_cfg.reset();
|
||||
m_cfg.m_def_cache.reset();
|
||||
}
|
||||
};
|
||||
|
||||
model_evaluator::model_evaluator(model_core & md, params_ref const & p) {
|
||||
|
@ -580,7 +602,10 @@ void model_evaluator::get_param_descrs(param_descrs & r) {
|
|||
}
|
||||
|
||||
void model_evaluator::set_model_completion(bool f) {
|
||||
m_imp->cfg().m_model_completion = f;
|
||||
if (m_imp->cfg().m_model_completion != f) {
|
||||
reset();
|
||||
m_imp->cfg().m_model_completion = f;
|
||||
}
|
||||
}
|
||||
|
||||
bool model_evaluator::get_model_completion() const {
|
||||
|
@ -597,8 +622,8 @@ unsigned model_evaluator::get_num_steps() const {
|
|||
|
||||
void model_evaluator::cleanup(params_ref const & p) {
|
||||
model_core & md = m_imp->cfg().m_model;
|
||||
dealloc(m_imp);
|
||||
m_imp = alloc(imp, md, p);
|
||||
m_imp->~imp();
|
||||
new (m_imp) imp(md, p);
|
||||
}
|
||||
|
||||
void model_evaluator::reset(params_ref const & p) {
|
||||
|
@ -607,14 +632,15 @@ void model_evaluator::reset(params_ref const & p) {
|
|||
}
|
||||
|
||||
void model_evaluator::reset(model_core &model, params_ref const& p) {
|
||||
dealloc(m_imp);
|
||||
m_imp = alloc(imp, model, p);
|
||||
m_imp->~imp();
|
||||
new (m_imp) imp(model, p);
|
||||
}
|
||||
|
||||
|
||||
void model_evaluator::operator()(expr * t, expr_ref & result) {
|
||||
TRACE("model_evaluator", tout << mk_ismt2_pp(t, m()) << "\n";);
|
||||
m_imp->operator()(t, result);
|
||||
TRACE("model_evaluator", tout << result << "\n";);
|
||||
m_imp->expand_stores(result);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ def_module_params('model_evaluator',
|
|||
params=(max_memory_param(),
|
||||
max_steps_param(),
|
||||
('completion', BOOL, False, 'assigns an interptetation to symbols that do not have one in the current model, when evaluating expressions in the current model'),
|
||||
('cache', BOOL, True, 'cache intermediate results in the model evaluator'),
|
||||
('array_equalities', BOOL, True, 'evaluate array equalities'),
|
||||
('array_as_stores', BOOL, True, 'return array as a set of stores'),
|
||||
))
|
||||
|
|
|
@ -30,8 +30,7 @@ static void display_uninterp_sorts(std::ostream & out, model_core const & md) {
|
|||
for (unsigned i = 0; i < sz; i++) {
|
||||
sort * s = md.get_uninterpreted_sort(i);
|
||||
out << "(define-sort " << mk_pp(s, m);
|
||||
ptr_vector<expr> const & univ = md.get_universe(s);
|
||||
for (expr* e : univ) {
|
||||
for (expr* e : md.get_universe(s)) {
|
||||
out << " " << mk_ismt2_pp(e, m);
|
||||
}
|
||||
out << ")\n";
|
||||
|
|
|
@ -196,7 +196,7 @@ static void pp_funs(std::ostream & out, ast_printer_context & ctx, model_core co
|
|||
sort_fun_decls(m, md, func_decls);
|
||||
for (unsigned i = 0; i < func_decls.size(); i++) {
|
||||
func_decl * f = func_decls[i];
|
||||
if (recfun_util.is_defined(f)) {
|
||||
if (recfun_util.is_defined(f) && !recfun_util.is_generated(f)) {
|
||||
continue;
|
||||
}
|
||||
func_interp * f_i = md.get_func_interp(f);
|
||||
|
|
|
@ -730,6 +730,7 @@ namespace datalog {
|
|||
void context::collect_params(param_descrs& p) {
|
||||
fp_params::collect_param_descrs(p);
|
||||
insert_timeout(p);
|
||||
insert_ctrl_c(p);
|
||||
}
|
||||
|
||||
void context::updt_params(params_ref const& p) {
|
||||
|
@ -854,7 +855,11 @@ namespace datalog {
|
|||
UNREACHABLE();
|
||||
}
|
||||
ensure_engine();
|
||||
return m_engine->query(query);
|
||||
lbool r = m_engine->query(query);
|
||||
if (r != l_undef && get_params().print_certificate()) {
|
||||
display_certificate(std::cout) << "\n";
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
lbool context::query_from_lvl (expr* query, unsigned lvl) {
|
||||
|
@ -951,9 +956,10 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
void context::display_certificate(std::ostream& out) {
|
||||
std::ostream& context::display_certificate(std::ostream& out) {
|
||||
ensure_engine();
|
||||
m_engine->display_certificate(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
void context::display(std::ostream & out) const {
|
||||
|
|
|
@ -581,7 +581,7 @@ namespace datalog {
|
|||
/**
|
||||
\brief Display a certificate for reachability and/or unreachability.
|
||||
*/
|
||||
void display_certificate(std::ostream& out);
|
||||
std::ostream& display_certificate(std::ostream& out);
|
||||
|
||||
/**
|
||||
\brief query result if it contains fact.
|
||||
|
|
|
@ -2948,7 +2948,7 @@ proof_ref context::get_ground_refutation() {
|
|||
ground_sat_answer_op op(*this);
|
||||
return op(*m_query);
|
||||
}
|
||||
expr_ref context::get_ground_sat_answer() const {
|
||||
expr_ref context::get_ground_sat_answer() {
|
||||
if (m_last_result != l_true) {
|
||||
IF_VERBOSE(0, verbose_stream()
|
||||
<< "Sat answer unavailable when result is false\n";);
|
||||
|
@ -2994,6 +2994,7 @@ expr_ref context::get_ground_sat_answer() const {
|
|||
ref<solver> cex_ctx =
|
||||
mk_smt_solver(m, params_ref::get_empty(), symbol::null);
|
||||
|
||||
bool first = true;
|
||||
// preorder traversal of the query derivation tree
|
||||
for (unsigned curr = 0; curr < pts.size (); curr++) {
|
||||
// pick next pt, fact, and cex_fact
|
||||
|
@ -3032,6 +3033,7 @@ expr_ref context::get_ground_sat_answer() const {
|
|||
}
|
||||
cex_ctx->assert_expr(pt->transition());
|
||||
cex_ctx->assert_expr(pt->rule2tag(r));
|
||||
TRACE("cex", cex_ctx->display(tout););
|
||||
lbool res = cex_ctx->check_sat(0, nullptr);
|
||||
CTRACE("cex", res == l_false,
|
||||
tout << "Cex fact: " << mk_pp(cex_fact, m) << "\n";
|
||||
|
@ -3046,6 +3048,19 @@ expr_ref context::get_ground_sat_answer() const {
|
|||
cex_ctx->get_model (local_mdl);
|
||||
cex_ctx->pop (1);
|
||||
local_mdl->set_model_completion(true);
|
||||
if (first) {
|
||||
unsigned sig_size = pt->sig_size();
|
||||
expr_ref_vector ground_fact_conjs(m);
|
||||
expr_ref_vector ground_arg_vals(m);
|
||||
for (unsigned j = 0; j < sig_size; j++) {
|
||||
expr_ref sig_arg(m), sig_val(m);
|
||||
sig_arg = m.mk_const (m_pm.o2n(pt->sig(j), 0));
|
||||
sig_val = (*local_mdl)(sig_arg);
|
||||
ground_arg_vals.push_back(sig_val);
|
||||
}
|
||||
cex.push_back(m.mk_app(pt->head(), sig_size, ground_arg_vals.c_ptr()));
|
||||
first = false;
|
||||
}
|
||||
for (unsigned i = 0; i < child_pts.size(); i++) {
|
||||
pred_transformer& ch_pt = *(child_pts.get(i));
|
||||
unsigned sig_size = ch_pt.sig_size();
|
||||
|
@ -3073,10 +3088,10 @@ expr_ref context::get_ground_sat_answer() const {
|
|||
|
||||
TRACE ("spacer", tout << "ground cex\n" << cex << "\n";);
|
||||
|
||||
return expr_ref(m.mk_and(cex.size(), cex.c_ptr()), m);
|
||||
return mk_and(cex);
|
||||
}
|
||||
|
||||
void context::display_certificate(std::ostream &out) const {
|
||||
void context::display_certificate(std::ostream &out) {
|
||||
switch(m_last_result) {
|
||||
case l_false:
|
||||
out << mk_pp(mk_unsat_answer(), m);
|
||||
|
|
|
@ -1010,7 +1010,7 @@ class context {
|
|||
/**
|
||||
\brief Retrieve satisfying assignment with explanation.
|
||||
*/
|
||||
expr_ref mk_sat_answer() const {return get_ground_sat_answer();}
|
||||
expr_ref mk_sat_answer() {return get_ground_sat_answer();}
|
||||
expr_ref mk_unsat_answer() const;
|
||||
unsigned get_cex_depth ();
|
||||
|
||||
|
@ -1086,7 +1086,7 @@ public:
|
|||
* get bottom-up (from query) sequence of ground predicate instances
|
||||
* (for e.g. P(0,1,0,0,3)) that together form a ground derivation to query
|
||||
*/
|
||||
expr_ref get_ground_sat_answer () const;
|
||||
expr_ref get_ground_sat_answer ();
|
||||
proof_ref get_ground_refutation();
|
||||
void get_rules_along_trace (datalog::rule_ref_vector& rules);
|
||||
|
||||
|
@ -1095,7 +1095,7 @@ public:
|
|||
void reset();
|
||||
|
||||
std::ostream& display(std::ostream& out) const;
|
||||
void display_certificate(std::ostream& out) const;
|
||||
void display_certificate(std::ostream& out);
|
||||
|
||||
pob& get_root() const {return m_pob_queue.get_root();}
|
||||
void set_query(func_decl* q) {m_query_pred = q;}
|
||||
|
|
|
@ -342,7 +342,7 @@ namespace spacer {
|
|||
|
||||
proof_ref pr2(m);
|
||||
{
|
||||
scoped_watch _t_ (m_hyp_reduce2_sw);
|
||||
// scoped_watch _t_ (m_hyp_reduce2_sw);
|
||||
hypothesis_reducer hyp_reducer(m);
|
||||
pr2 = hyp_reducer.reduce(pr1);
|
||||
}
|
||||
|
|
|
@ -1487,6 +1487,8 @@ namespace opt {
|
|||
|
||||
void context::collect_param_descrs(param_descrs & r) {
|
||||
opt_params::collect_param_descrs(r);
|
||||
insert_timeout(r);
|
||||
insert_ctrl_c(r);
|
||||
}
|
||||
|
||||
void context::updt_params(params_ref const& p) {
|
||||
|
|
|
@ -411,13 +411,14 @@ private:
|
|||
}
|
||||
m_buffer.push_back(0);
|
||||
m_tokens.push_back(asymbol(symbol(m_buffer.c_ptr()), in.line()));
|
||||
IF_VERBOSE(10, verbose_stream() << "tok: " << m_tokens.back() << "\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_num(c)) {
|
||||
rational n(0);
|
||||
unsigned div = 1;
|
||||
rational div(1);
|
||||
while (is_num(c) && !in.eof()) {
|
||||
n = n*rational(10) + rational(c - '0');
|
||||
in.next();
|
||||
|
@ -429,11 +430,11 @@ private:
|
|||
while (is_num(c) && !in.eof()) {
|
||||
n = n*rational(10) + rational(c - '0');
|
||||
in.next();
|
||||
div *= 10;
|
||||
div *= rational(10);
|
||||
c = in.ch();
|
||||
}
|
||||
}
|
||||
if (div > 1) n = n / rational(div);
|
||||
if (div > rational(1)) n = n / div;
|
||||
if (neg) n.neg();
|
||||
m_tokens.push_back(asymbol(n, in.line()));
|
||||
IF_VERBOSE(10, verbose_stream() << "num: " << m_tokens.back() << "\n");
|
||||
|
@ -686,14 +687,22 @@ private:
|
|||
return peek(pos) == "<=" || peek(pos) == "=<";
|
||||
}
|
||||
|
||||
bool peek_minus_infty(unsigned pos) {
|
||||
bool peek_minus_infty_long(unsigned pos) {
|
||||
return peek(pos) == "-" && (peek(pos+1) == "inf" || peek(pos+1) == "infinity");
|
||||
}
|
||||
|
||||
bool peek_plus_infty(unsigned pos) {
|
||||
bool peek_minus_infty_short(unsigned pos) {
|
||||
return peek(pos) == "-inf" || peek(pos) == "-infinity";
|
||||
}
|
||||
|
||||
bool peek_plus_infty_long(unsigned pos) {
|
||||
return peek(pos) == "+" && (peek(pos+1) == "inf" || peek(pos+1) == "infinity");
|
||||
}
|
||||
|
||||
bool peek_plus_infty_short(unsigned pos) {
|
||||
return peek(pos) == "+inf" || peek(pos) == "+infinity";
|
||||
}
|
||||
|
||||
void parse_indicator(symbol& var, rational& val) {
|
||||
if (peek(1) == "=" && tok.peek_num(2) && peek(3) == "->") {
|
||||
var = peek(0);
|
||||
|
@ -730,14 +739,22 @@ private:
|
|||
tok.next(3);
|
||||
parse_upper(v);
|
||||
}
|
||||
else if (peek_minus_infty(0) && peek_le(2)) {
|
||||
else if (peek_minus_infty_long(0) && peek_le(2)) {
|
||||
v = peek(3);
|
||||
tok.next(4);
|
||||
parse_upper(v);
|
||||
}
|
||||
else if (peek_plus_infty(2) && peek_le(1)) {
|
||||
else if (peek_minus_infty_short(0) && peek_le(1)) {
|
||||
v = peek(2);
|
||||
tok.next(3);
|
||||
parse_upper(v);
|
||||
}
|
||||
else if (peek_plus_infty_long(2) && peek_le(1)) {
|
||||
tok.next(4);
|
||||
}
|
||||
else if (peek_plus_infty_short(2) && peek_le(1)) {
|
||||
tok.next(3);
|
||||
}
|
||||
else if (peek_le(1) && tok.peek_num(2)) {
|
||||
v = peek(0);
|
||||
tok.next(2);
|
||||
|
@ -756,9 +773,11 @@ private:
|
|||
update_upper(v, rhs);
|
||||
tok.next(2);
|
||||
}
|
||||
else if (peek_le(0) && peek_plus_infty(1)) {
|
||||
else if (peek_le(0) && peek_plus_infty_long(1)) {
|
||||
tok.next(3);
|
||||
}
|
||||
else if (peek_le(0) && peek_plus_infty_short(1)) {
|
||||
tok.next(2); }
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -233,7 +233,8 @@ namespace opt {
|
|||
get_model(m_model);
|
||||
inf_eps val2;
|
||||
m_valid_objectives[i] = true;
|
||||
TRACE("opt", tout << (has_shared?"has shared":"non-shared") << " " << val << "\n";);
|
||||
has_shared = true;
|
||||
TRACE("opt", tout << (has_shared?"has shared":"non-shared") << " " << val << " " << blocker << "\n";);
|
||||
if (!m_models[i]) {
|
||||
set_model(i);
|
||||
}
|
||||
|
|
|
@ -191,7 +191,10 @@ namespace opt {
|
|||
SASSERT(delta_per_step.is_int());
|
||||
SASSERT(delta_per_step.is_pos());
|
||||
is_sat = m_s->check_sat(0, nullptr);
|
||||
TRACE("opt", tout << "check " << is_sat << "\n";);
|
||||
TRACE("opt", tout << "check " << is_sat << "\n";
|
||||
tout << "lower: " << m_lower[obj_index] << "\n";
|
||||
tout << "upper: " << m_upper[obj_index] << "\n";
|
||||
);
|
||||
if (is_sat == l_true) {
|
||||
m_s->maximize_objective(obj_index, bound);
|
||||
m_s->get_model(m_model);
|
||||
|
@ -215,7 +218,7 @@ namespace opt {
|
|||
++num_scopes;
|
||||
bound = m_s->mk_ge(obj_index, obj + inf_eps(delta_per_step));
|
||||
}
|
||||
TRACE("opt", tout << delta_per_step << " " << bound << "\n";);
|
||||
TRACE("opt", tout << "delta: " << delta_per_step << " " << bound << "\n";);
|
||||
m_s->assert_expr(bound);
|
||||
}
|
||||
else if (is_sat == l_false && delta_per_step > rational::one()) {
|
||||
|
@ -232,6 +235,8 @@ namespace opt {
|
|||
}
|
||||
m_s->pop(num_scopes);
|
||||
|
||||
TRACE("opt", tout << is_sat << " " << num_scopes << "\n";);
|
||||
|
||||
if (is_sat == l_false && !m_model) {
|
||||
return l_false;
|
||||
}
|
||||
|
|
|
@ -482,7 +482,7 @@ namespace smt2 {
|
|||
if (context[0]) msg += ": ";
|
||||
msg += "unknown sort '";
|
||||
msg += id.str() + "'";
|
||||
throw parser_exception(msg.c_str());
|
||||
throw parser_exception(std::move(msg));
|
||||
}
|
||||
|
||||
void consume_sexpr() {
|
||||
|
@ -1591,7 +1591,7 @@ namespace smt2 {
|
|||
// parse:
|
||||
// 'as' <identifier> <sort> ')'
|
||||
// '_' <identifier> <num>+ ')'
|
||||
// 'as' <identifier '(' '_' <identifier> (<num>|<func-decl-ref>)+ ')' <sort> ')'
|
||||
// 'as' <identifier> '(' '_' <identifier> (<num>|<func-decl-ref>)+ ')' <sort> ')'
|
||||
symbol parse_qualified_identifier_core(bool & has_as) {
|
||||
SASSERT(curr_is_identifier());
|
||||
SASSERT(curr_id_is_underscore() || curr_id_is_as());
|
||||
|
@ -1633,7 +1633,7 @@ namespace smt2 {
|
|||
void unknown_var_const_name(symbol id) {
|
||||
std::string msg = "unknown constant/variable '";
|
||||
msg += id.str() + "'";
|
||||
throw parser_exception(msg.c_str());
|
||||
throw parser_exception(std::move(msg));
|
||||
}
|
||||
|
||||
rational m_last_bv_numeral; // for bv, bvbin, bvhex
|
||||
|
@ -2431,7 +2431,7 @@ namespace smt2 {
|
|||
buffer << "invalid function definition, sort mismatch. Expcected "
|
||||
<< mk_pp(f->get_range(), m()) << " but function body has sort "
|
||||
<< mk_pp(m().get_sort(body), m());
|
||||
throw parser_exception(buffer.str().c_str());
|
||||
throw parser_exception(buffer.str());
|
||||
}
|
||||
m_ctx.insert_rec_fun(f, bindings, ids, body);
|
||||
}
|
||||
|
@ -2677,6 +2677,7 @@ namespace smt2 {
|
|||
m_ctx.regular_stream() << "(";
|
||||
expr ** expr_it = expr_stack().c_ptr() + spos;
|
||||
expr ** expr_end = expr_it + m_cached_strings.size();
|
||||
// md->compress();
|
||||
for (unsigned i = 0; expr_it < expr_end; expr_it++, i++) {
|
||||
model::scoped_model_completion _scm(md, true);
|
||||
expr_ref v = (*md)(*expr_it);
|
||||
|
|
|
@ -2430,7 +2430,6 @@ class qe_lite_tactic : public tactic {
|
|||
tactic_report report("qe-lite", *g);
|
||||
proof_ref new_pr(m);
|
||||
expr_ref new_f(m);
|
||||
bool produce_proofs = g->proofs_enabled();
|
||||
|
||||
unsigned sz = g->size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
|
|
|
@ -191,18 +191,14 @@ namespace sat {
|
|||
|
||||
// PB parameters
|
||||
s = p.pb_solver();
|
||||
if (s == symbol("circuit"))
|
||||
m_pb_solver = PB_CIRCUIT;
|
||||
else if (s == symbol("sorting"))
|
||||
m_pb_solver = PB_SORTING;
|
||||
else if (s == symbol("totalizer"))
|
||||
m_pb_solver = PB_TOTALIZER;
|
||||
else if (s == symbol("solver"))
|
||||
m_pb_solver = PB_SOLVER;
|
||||
else if (s == symbol("segmented"))
|
||||
m_pb_solver = PB_SEGMENTED;
|
||||
else
|
||||
throw sat_param_exception("invalid PB solver: solver, totalizer, circuit, sorting, segmented");
|
||||
if (s != symbol("circuit") &&
|
||||
s != symbol("sorting") &&
|
||||
s != symbol("totalizer") &&
|
||||
s != symbol("solver") &&
|
||||
s != symbol("segmented") &&
|
||||
s != symbol("binary_merge")) {
|
||||
throw sat_param_exception("invalid PB solver: solver, totalizer, circuit, sorting, segmented, binary_merge");
|
||||
}
|
||||
|
||||
s = p.pb_resolve();
|
||||
if (s == "cardinality")
|
||||
|
|
|
@ -52,14 +52,6 @@ namespace sat {
|
|||
BH_LRB
|
||||
};
|
||||
|
||||
enum pb_solver {
|
||||
PB_SOLVER,
|
||||
PB_CIRCUIT,
|
||||
PB_SORTING,
|
||||
PB_TOTALIZER,
|
||||
PB_SEGMENTED
|
||||
};
|
||||
|
||||
enum pb_resolve {
|
||||
PB_CARDINALITY,
|
||||
PB_ROUNDING
|
||||
|
@ -162,7 +154,6 @@ namespace sat {
|
|||
bool m_drat_check_unsat;
|
||||
bool m_drat_check_sat;
|
||||
|
||||
pb_solver m_pb_solver;
|
||||
bool m_card_solver;
|
||||
pb_resolve m_pb_resolve;
|
||||
pb_lemma_format m_pb_lemma_format;
|
||||
|
@ -182,6 +173,7 @@ namespace sat {
|
|||
config(params_ref const & p);
|
||||
void updt_params(params_ref const & p);
|
||||
static void collect_param_descrs(param_descrs & d);
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace sat {
|
|||
void model_converter::operator()(model & m) const {
|
||||
vector<entry>::const_iterator begin = m_entries.begin();
|
||||
vector<entry>::const_iterator it = m_entries.end();
|
||||
bool first = false; // true; // false; // // true;
|
||||
bool first = false;
|
||||
//SASSERT(!m_solver || m_solver->check_clauses(m));
|
||||
while (it != begin) {
|
||||
--it;
|
||||
|
@ -144,16 +144,30 @@ namespace sat {
|
|||
DEBUG_CODE({
|
||||
// all clauses must be satisfied
|
||||
bool sat = false;
|
||||
for (literal l : it->m_clauses) {
|
||||
bool undef = false;
|
||||
for (literal const& l : it->m_clauses) {
|
||||
if (l == null_literal) {
|
||||
SASSERT(sat);
|
||||
CTRACE("sat", !sat,
|
||||
if (m_solver) m_solver->display(tout);
|
||||
display(tout);
|
||||
for (unsigned v = 0; v < m.size(); ++v) tout << v << ": " << m[v] << "\n";
|
||||
for (literal const& l2 : it->m_clauses) {
|
||||
if (l2 == null_literal) tout << "\n"; else tout << l2 << " ";
|
||||
if (&l == &l2) break;
|
||||
}
|
||||
);
|
||||
SASSERT(sat || undef);
|
||||
sat = false;
|
||||
undef = false;
|
||||
continue;
|
||||
}
|
||||
if (sat)
|
||||
continue;
|
||||
if (value_at(l, m) == l_true)
|
||||
sat = true;
|
||||
switch (value_at(l, m)) {
|
||||
case l_undef: undef = true; break;
|
||||
case l_true: sat = true; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -221,12 +235,7 @@ namespace sat {
|
|||
|
||||
void model_converter::add_elim_stack(entry & e) {
|
||||
e.m_elim_stack.push_back(stackv().empty() ? nullptr : alloc(elim_stack, stackv()));
|
||||
#if 0
|
||||
if (!stackv().empty() && e.get_kind() == ATE) {
|
||||
IF_VERBOSE(0, display(verbose_stream(), e) << "\n");
|
||||
}
|
||||
#endif
|
||||
for (auto const& s : stackv()) VERIFY(legal_to_flip(s.second.var()));
|
||||
// VERIFY(for (auto const& s : stackv()) VERIFY(legal_to_flip(s.second.var())););
|
||||
stackv().reset();
|
||||
}
|
||||
|
||||
|
|
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