3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-22 16:45:31 +00:00
This commit is contained in:
nilsbecker 2019-04-17 22:39:06 +02:00
commit 28ff338b88
189 changed files with 5509 additions and 1556 deletions

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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));
}

View file

@ -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);

View file

@ -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("");
}

View file

@ -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);
}

View file

@ -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 {

View file

@ -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 {

View file

@ -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);

View file

@ -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);
{

View 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, &param, 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);
};

View file

@ -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("");
}

View file

@ -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());

View file

@ -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);
}

View file

@ -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()); }
}
}
}

View file

@ -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")

View file

@ -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>

View file

@ -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>

View 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>

View file

@ -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>

View file

@ -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@")]

View file

@ -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); }
}
}
}

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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:

View file

@ -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 */
/*@{*/
/**

View file

@ -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

View file

@ -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) {

View file

@ -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); }

View file

@ -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";);

View file

@ -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); }

View file

@ -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

View file

@ -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());
}

View file

@ -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.
*/

View file

@ -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;
}
}

View file

@ -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) {

View file

@ -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);
};
};

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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";);

View file

@ -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";

View file

@ -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);

View file

@ -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);
}

View file

@ -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));

View file

@ -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));
}
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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());

View file

@ -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);

View file

@ -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"),

View file

@ -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;

View file

@ -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) {

View 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();
}

View 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_ */

View file

@ -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.

View file

@ -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);

View file

@ -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: {

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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);
}

View file

@ -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();

View file

@ -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:

View file

@ -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);

View 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;
}
}

View 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_ */

View file

@ -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);

View file

@ -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; //

View file

@ -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();
}

View file

@ -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);

View file

@ -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());

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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'),
))

View file

@ -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";

View file

@ -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);

View file

@ -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 {

View file

@ -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.

View file

@ -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);

View file

@ -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;}

View file

@ -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);
}

View file

@ -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) {

View file

@ -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); }
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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++) {

View file

@ -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")

View file

@ -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);
};
};

View file

@ -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