mirror of
https://github.com/Z3Prover/z3
synced 2025-06-28 08:58:44 +00:00
Merge branch 'master' of https://github.com/Z3Prover/z3
This commit is contained in:
commit
ef9486913b
47 changed files with 2232 additions and 1198 deletions
|
@ -1,4 +1,9 @@
|
||||||
|
# FIXME: We should build this as an external project and consume
|
||||||
|
# Z3 as `find_package(z3 CONFIG)`.
|
||||||
add_executable(cpp_example EXCLUDE_FROM_ALL example.cpp)
|
add_executable(cpp_example EXCLUDE_FROM_ALL example.cpp)
|
||||||
target_link_libraries(cpp_example PRIVATE libz3)
|
target_link_libraries(cpp_example PRIVATE libz3)
|
||||||
target_include_directories(cpp_example PRIVATE "${CMAKE_SOURCE_DIR}/src/api")
|
target_include_directories(cpp_example PRIVATE "${CMAKE_SOURCE_DIR}/src/api")
|
||||||
target_include_directories(cpp_example PRIVATE "${CMAKE_SOURCE_DIR}/src/api/c++")
|
target_include_directories(cpp_example PRIVATE "${CMAKE_SOURCE_DIR}/src/api/c++")
|
||||||
|
if (NOT BUILD_LIBZ3_SHARED)
|
||||||
|
z3_append_linker_flag_list_to_target(cpp_example ${Z3_DEPENDENT_EXTRA_CXX_LINK_FLAGS})
|
||||||
|
endif()
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
# FIXME: We should build this as an external project and consume
|
||||||
|
# Z3 as `find_package(z3 CONFIG)`.
|
||||||
add_executable(c_example EXCLUDE_FROM_ALL test_capi.c)
|
add_executable(c_example EXCLUDE_FROM_ALL test_capi.c)
|
||||||
target_link_libraries(c_example PRIVATE libz3)
|
target_link_libraries(c_example PRIVATE libz3)
|
||||||
target_include_directories(c_example PRIVATE "${CMAKE_SOURCE_DIR}/src/api")
|
target_include_directories(c_example PRIVATE "${CMAKE_SOURCE_DIR}/src/api")
|
||||||
|
# This is needed for when libz3 is built as a static library
|
||||||
|
if (NOT BUILD_LIBZ3_SHARED)
|
||||||
|
z3_append_linker_flag_list_to_target(c_example ${Z3_DEPENDENT_EXTRA_C_LINK_FLAGS})
|
||||||
|
endif()
|
||||||
|
|
|
@ -136,9 +136,10 @@ if (NOT MSVC)
|
||||||
set_target_properties(libz3 PROPERTIES OUTPUT_NAME z3)
|
set_target_properties(libz3 PROPERTIES OUTPUT_NAME z3)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Using INTERFACE means that targets that try link against libz3 will
|
# The `PRIVATE` usage requirement is specified so that when building Z3 as a
|
||||||
# automatically link against the libs in Z3_DEPENDENT_LIBS
|
# shared library the dependent libraries are specified on the link command line
|
||||||
target_link_libraries(libz3 INTERFACE ${Z3_DEPENDENT_LIBS})
|
# so that if those are also shared libraries they are referenced by `libz3.so`.
|
||||||
|
target_link_libraries(libz3 PRIVATE ${Z3_DEPENDENT_LIBS})
|
||||||
|
|
||||||
z3_append_linker_flag_list_to_target(libz3 ${Z3_DEPENDENT_EXTRA_CXX_LINK_FLAGS})
|
z3_append_linker_flag_list_to_target(libz3 ${Z3_DEPENDENT_EXTRA_CXX_LINK_FLAGS})
|
||||||
|
|
||||||
|
|
|
@ -156,7 +156,7 @@ elseif (DOTNET_TOOLCHAIN_IS_MONO)
|
||||||
# We need to give the assembly a strong name so that it can be installed
|
# We need to give the assembly a strong name so that it can be installed
|
||||||
# into the GAC.
|
# into the GAC.
|
||||||
list(APPEND CSC_FLAGS
|
list(APPEND CSC_FLAGS
|
||||||
"/keyfile:${CMAKE_CURRENT_SOURCE_DIR}/Microsoft.Z3.mono.snk"
|
"/keyfile:${CMAKE_CURRENT_SOURCE_DIR}/Microsoft.Z3.snk"
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "Unknown .NET toolchain")
|
message(FATAL_ERROR "Unknown .NET toolchain")
|
||||||
|
|
|
@ -110,7 +110,9 @@ set(Z3_JAVA_JAR_SOURCE_FILES
|
||||||
BitVecSort.java
|
BitVecSort.java
|
||||||
BoolExpr.java
|
BoolExpr.java
|
||||||
BoolSort.java
|
BoolSort.java
|
||||||
|
ConstructorDecRefQueue.java
|
||||||
Constructor.java
|
Constructor.java
|
||||||
|
ConstructorListDecRefQueue.java
|
||||||
ConstructorList.java
|
ConstructorList.java
|
||||||
Context.java
|
Context.java
|
||||||
DatatypeExpr.java
|
DatatypeExpr.java
|
||||||
|
@ -136,7 +138,6 @@ set(Z3_JAVA_JAR_SOURCE_FILES
|
||||||
GoalDecRefQueue.java
|
GoalDecRefQueue.java
|
||||||
Goal.java
|
Goal.java
|
||||||
IDecRefQueue.java
|
IDecRefQueue.java
|
||||||
IDisposable.java
|
|
||||||
InterpolationContext.java
|
InterpolationContext.java
|
||||||
IntExpr.java
|
IntExpr.java
|
||||||
IntNum.java
|
IntNum.java
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
z3_add_component(fpa
|
z3_add_component(fpa
|
||||||
SOURCES
|
SOURCES
|
||||||
|
bv2fpa_converter.cpp
|
||||||
fpa2bv_converter.cpp
|
fpa2bv_converter.cpp
|
||||||
fpa2bv_rewriter.cpp
|
fpa2bv_rewriter.cpp
|
||||||
COMPONENT_DEPENDENCIES
|
COMPONENT_DEPENDENCIES
|
||||||
ast
|
ast
|
||||||
simplifier
|
simplifier
|
||||||
|
model
|
||||||
util
|
util
|
||||||
PYG_FILES
|
PYG_FILES
|
||||||
fpa2bv_rewriter_params.pyg
|
fpa2bv_rewriter_params.pyg
|
||||||
|
|
|
@ -12,6 +12,7 @@ z3_add_component(rewriter
|
||||||
expr_replacer.cpp
|
expr_replacer.cpp
|
||||||
expr_safe_replace.cpp
|
expr_safe_replace.cpp
|
||||||
factor_rewriter.cpp
|
factor_rewriter.cpp
|
||||||
|
fd_rewriter.cpp
|
||||||
fpa_rewriter.cpp
|
fpa_rewriter.cpp
|
||||||
label_rewriter.cpp
|
label_rewriter.cpp
|
||||||
mk_simplified_app.cpp
|
mk_simplified_app.cpp
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
z3_add_component(portfolio
|
z3_add_component(portfolio
|
||||||
SOURCES
|
SOURCES
|
||||||
default_tactic.cpp
|
default_tactic.cpp
|
||||||
|
fd_solver.cpp
|
||||||
smt_strategic_solver.cpp
|
smt_strategic_solver.cpp
|
||||||
COMPONENT_DEPENDENCIES
|
COMPONENT_DEPENDENCIES
|
||||||
aig_tactic
|
aig_tactic
|
||||||
|
|
|
@ -42,6 +42,7 @@ add_executable(test-z3
|
||||||
factor_rewriter.cpp
|
factor_rewriter.cpp
|
||||||
fixed_bit_vector.cpp
|
fixed_bit_vector.cpp
|
||||||
for_each_file.cpp
|
for_each_file.cpp
|
||||||
|
get_consequences.cpp
|
||||||
get_implied_equalities.cpp
|
get_implied_equalities.cpp
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/gparams_register_modules.cpp"
|
"${CMAKE_CURRENT_BINARY_DIR}/gparams_register_modules.cpp"
|
||||||
hashtable.cpp
|
hashtable.cpp
|
||||||
|
|
|
@ -45,7 +45,7 @@ def init_project_def():
|
||||||
# Simplifier module will be deleted in the future.
|
# Simplifier module will be deleted in the future.
|
||||||
# It has been replaced with rewriter module.
|
# It has been replaced with rewriter module.
|
||||||
add_lib('simplifier', ['rewriter'], 'ast/simplifier')
|
add_lib('simplifier', ['rewriter'], 'ast/simplifier')
|
||||||
add_lib('fpa', ['ast', 'util', 'simplifier'], 'ast/fpa')
|
add_lib('fpa', ['ast', 'util', 'simplifier', 'model'], 'ast/fpa')
|
||||||
add_lib('macros', ['simplifier'], 'ast/macros')
|
add_lib('macros', ['simplifier'], 'ast/macros')
|
||||||
add_lib('pattern', ['normal_forms', 'smt2parser', 'simplifier'], 'ast/pattern')
|
add_lib('pattern', ['normal_forms', 'smt2parser', 'simplifier'], 'ast/pattern')
|
||||||
add_lib('bit_blaster', ['rewriter', 'simplifier'], 'ast/rewriter/bit_blaster')
|
add_lib('bit_blaster', ['rewriter', 'simplifier'], 'ast/rewriter/bit_blaster')
|
||||||
|
|
|
@ -1212,6 +1212,9 @@ std::ostream& operator<<(std::ostream& out, mk_ismt2_pp const & p) {
|
||||||
else if (is_sort(p.m_ast)) {
|
else if (is_sort(p.m_ast)) {
|
||||||
ast_smt2_pp(out, to_sort(p.m_ast), env, p.m_params, p.m_indent);
|
ast_smt2_pp(out, to_sort(p.m_ast), env, p.m_params, p.m_indent);
|
||||||
}
|
}
|
||||||
|
else if (p.m_ast == 0) {
|
||||||
|
out << "null";
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
SASSERT(is_func_decl(p.m_ast));
|
SASSERT(is_func_decl(p.m_ast));
|
||||||
ast_smt2_pp(out, to_func_decl(p.m_ast), env, p.m_params, p.m_indent);
|
ast_smt2_pp(out, to_func_decl(p.m_ast), env, p.m_params, p.m_indent);
|
||||||
|
|
|
@ -31,6 +31,14 @@ public:
|
||||||
virtual ~i_expr_pred() {}
|
virtual ~i_expr_pred() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class i_sort_pred {
|
||||||
|
public:
|
||||||
|
virtual bool operator()(sort* s) = 0;
|
||||||
|
virtual ~i_sort_pred() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Memoizing predicate functor on sub-expressions.
|
\brief Memoizing predicate functor on sub-expressions.
|
||||||
|
|
||||||
|
|
551
src/ast/fpa/bv2fpa_converter.cpp
Normal file
551
src/ast/fpa/bv2fpa_converter.cpp
Normal file
|
@ -0,0 +1,551 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) 2012 Microsoft Corporation
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
bv2fpa_converter.cpp
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Model conversion for fpa2bv_converter
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Christoph (cwinter) 2016-10-15
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
#include<math.h>
|
||||||
|
|
||||||
|
#include"ast_smt2_pp.h"
|
||||||
|
#include"well_sorted.h"
|
||||||
|
#include"th_rewriter.h"
|
||||||
|
#include"fpa_rewriter.h"
|
||||||
|
|
||||||
|
#include"bv2fpa_converter.h"
|
||||||
|
|
||||||
|
|
||||||
|
bv2fpa_converter::bv2fpa_converter(ast_manager & m) :
|
||||||
|
m(m),
|
||||||
|
m_fpa_util(m),
|
||||||
|
m_bv_util(m),
|
||||||
|
m_th_rw(m) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bv2fpa_converter::bv2fpa_converter(ast_manager & m, fpa2bv_converter & conv) :
|
||||||
|
m(m),
|
||||||
|
m_fpa_util(m),
|
||||||
|
m_bv_util(m),
|
||||||
|
m_th_rw(m) {
|
||||||
|
for (obj_map<func_decl, expr*>::iterator it = conv.m_const2bv.begin();
|
||||||
|
it != conv.m_const2bv.end();
|
||||||
|
it++)
|
||||||
|
{
|
||||||
|
m_const2bv.insert(it->m_key, it->m_value);
|
||||||
|
m.inc_ref(it->m_key);
|
||||||
|
m.inc_ref(it->m_value);
|
||||||
|
}
|
||||||
|
for (obj_map<func_decl, expr*>::iterator it = conv.m_rm_const2bv.begin();
|
||||||
|
it != conv.m_rm_const2bv.end();
|
||||||
|
it++)
|
||||||
|
{
|
||||||
|
m_rm_const2bv.insert(it->m_key, it->m_value);
|
||||||
|
m.inc_ref(it->m_key);
|
||||||
|
m.inc_ref(it->m_value);
|
||||||
|
}
|
||||||
|
for (obj_map<func_decl, func_decl*>::iterator it = conv.m_uf2bvuf.begin();
|
||||||
|
it != conv.m_uf2bvuf.end();
|
||||||
|
it++)
|
||||||
|
{
|
||||||
|
m_uf2bvuf.insert(it->m_key, it->m_value);
|
||||||
|
m.inc_ref(it->m_key);
|
||||||
|
m.inc_ref(it->m_value);
|
||||||
|
}
|
||||||
|
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = conv.m_min_max_specials.begin();
|
||||||
|
it != conv.m_min_max_specials.end();
|
||||||
|
it++) {
|
||||||
|
m_specials.insert(it->m_key, it->m_value);
|
||||||
|
m.inc_ref(it->m_key);
|
||||||
|
m.inc_ref(it->m_value.first);
|
||||||
|
m.inc_ref(it->m_value.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bv2fpa_converter::~bv2fpa_converter() {
|
||||||
|
dec_ref_map_key_values(m, m_const2bv);
|
||||||
|
dec_ref_map_key_values(m, m_rm_const2bv);
|
||||||
|
dec_ref_map_key_values(m, m_uf2bvuf);
|
||||||
|
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = m_specials.begin();
|
||||||
|
it != m_specials.end();
|
||||||
|
it++) {
|
||||||
|
m.dec_ref(it->m_key);
|
||||||
|
m.dec_ref(it->m_value.first);
|
||||||
|
m.dec_ref(it->m_value.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_ref bv2fpa_converter::convert_bv2fp(sort * s, expr * sgn, expr * exp, expr * sig) {
|
||||||
|
unsynch_mpz_manager & mpzm = m_fpa_util.fm().mpz_manager();
|
||||||
|
unsynch_mpq_manager & mpqm = m_fpa_util.fm().mpq_manager();
|
||||||
|
|
||||||
|
expr_ref res(m);
|
||||||
|
mpf fp_val;
|
||||||
|
|
||||||
|
unsigned ebits = m_fpa_util.get_ebits(s);
|
||||||
|
unsigned sbits = m_fpa_util.get_sbits(s);
|
||||||
|
|
||||||
|
unsigned sgn_sz = 1;
|
||||||
|
unsigned exp_sz = ebits;
|
||||||
|
unsigned sig_sz = sbits - 1;
|
||||||
|
|
||||||
|
rational sgn_q(0), sig_q(0), exp_q(0);
|
||||||
|
|
||||||
|
if (sgn) m_bv_util.is_numeral(sgn, sgn_q, sgn_sz);
|
||||||
|
if (exp) m_bv_util.is_numeral(exp, exp_q, exp_sz);
|
||||||
|
if (sig) m_bv_util.is_numeral(sig, sig_q, sig_sz);
|
||||||
|
|
||||||
|
// un-bias exponent
|
||||||
|
rational exp_unbiased_q;
|
||||||
|
exp_unbiased_q = exp_q - m_fpa_util.fm().m_powers2.m1(ebits - 1);
|
||||||
|
|
||||||
|
mpz sig_z; mpf_exp_t exp_z;
|
||||||
|
mpzm.set(sig_z, sig_q.to_mpq().numerator());
|
||||||
|
exp_z = mpzm.get_int64(exp_unbiased_q.to_mpq().numerator());
|
||||||
|
|
||||||
|
m_fpa_util.fm().set(fp_val, ebits, sbits, !mpqm.is_zero(sgn_q.to_mpq()), exp_z, sig_z);
|
||||||
|
|
||||||
|
mpzm.del(sig_z);
|
||||||
|
|
||||||
|
res = m_fpa_util.mk_value(fp_val);
|
||||||
|
|
||||||
|
TRACE("bv2fpa", tout << "[" << mk_ismt2_pp(sgn, m) <<
|
||||||
|
" " << mk_ismt2_pp(exp, m) <<
|
||||||
|
" " << mk_ismt2_pp(sig, m) << "] == " <<
|
||||||
|
mk_ismt2_pp(res, m) << std::endl;);
|
||||||
|
m_fpa_util.fm().del(fp_val);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_ref bv2fpa_converter::convert_bv2fp(model_core * mc, sort * s, app * bv) {
|
||||||
|
SASSERT(m_bv_util.is_bv(bv));
|
||||||
|
|
||||||
|
unsigned ebits = m_fpa_util.get_ebits(s);
|
||||||
|
unsigned sbits = m_fpa_util.get_sbits(s);
|
||||||
|
unsigned bv_sz = sbits + ebits;
|
||||||
|
|
||||||
|
expr_ref bv_num(m);
|
||||||
|
if (m_bv_util.is_numeral(bv))
|
||||||
|
bv_num = bv;
|
||||||
|
else if (!mc->eval(bv->get_decl(), bv_num))
|
||||||
|
bv_num = m_bv_util.mk_numeral(0, m_bv_util.get_bv_size(bv));
|
||||||
|
|
||||||
|
expr_ref sgn(m), exp(m), sig(m);
|
||||||
|
sgn = m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv_num);
|
||||||
|
exp = m_bv_util.mk_extract(bv_sz - 2, sbits - 1, bv_num);
|
||||||
|
sig = m_bv_util.mk_extract(sbits - 2, 0, bv_num);
|
||||||
|
|
||||||
|
expr_ref v_sgn(m), v_exp(m), v_sig(m);
|
||||||
|
m_th_rw(sgn, v_sgn);
|
||||||
|
m_th_rw(exp, v_exp);
|
||||||
|
m_th_rw(sig, v_sig);
|
||||||
|
|
||||||
|
return convert_bv2fp(s, v_sgn, v_exp, v_sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_ref bv2fpa_converter::convert_bv2rm(expr * bv_rm) {
|
||||||
|
expr_ref res(m);
|
||||||
|
rational bv_val(0);
|
||||||
|
unsigned sz = 0;
|
||||||
|
|
||||||
|
if (m_bv_util.is_numeral(bv_rm, bv_val, sz)) {
|
||||||
|
SASSERT(bv_val.is_uint64());
|
||||||
|
switch (bv_val.get_uint64()) {
|
||||||
|
case BV_RM_TIES_TO_AWAY: res = m_fpa_util.mk_round_nearest_ties_to_away(); break;
|
||||||
|
case BV_RM_TIES_TO_EVEN: res = m_fpa_util.mk_round_nearest_ties_to_even(); break;
|
||||||
|
case BV_RM_TO_NEGATIVE: res = m_fpa_util.mk_round_toward_negative(); break;
|
||||||
|
case BV_RM_TO_POSITIVE: res = m_fpa_util.mk_round_toward_positive(); break;
|
||||||
|
case BV_RM_TO_ZERO:
|
||||||
|
default: res = m_fpa_util.mk_round_toward_zero();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_ref bv2fpa_converter::convert_bv2rm(model_core * mc, app * val) {
|
||||||
|
expr_ref res(m);
|
||||||
|
|
||||||
|
if (val) {
|
||||||
|
expr_ref eval_v(m);
|
||||||
|
if (m_bv_util.is_numeral(val))
|
||||||
|
res = convert_bv2rm(val);
|
||||||
|
else if (mc->eval(val->get_decl(), eval_v))
|
||||||
|
res = convert_bv2rm(eval_v);
|
||||||
|
else
|
||||||
|
res = m_fpa_util.mk_round_toward_zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_ref bv2fpa_converter::rebuild_floats(model_core * mc, sort * s, app * e) {
|
||||||
|
expr_ref result(m);
|
||||||
|
TRACE("bv2fpa", tout << "rebuild floats in " << mk_ismt2_pp(s, m) << " for ";
|
||||||
|
if (e) tout << mk_ismt2_pp(e, m);
|
||||||
|
else tout << "nil";
|
||||||
|
tout << std::endl; );
|
||||||
|
|
||||||
|
if (m_fpa_util.is_float(s)) {
|
||||||
|
if (e == 0)
|
||||||
|
result = m_fpa_util.mk_pzero(s);
|
||||||
|
else if (m_fpa_util.is_numeral(e))
|
||||||
|
result = e;
|
||||||
|
else {
|
||||||
|
SASSERT(m_bv_util.is_bv(e) && m_bv_util.get_bv_size(e) == (m_fpa_util.get_ebits(s) + m_fpa_util.get_sbits(s)));
|
||||||
|
result = convert_bv2fp(mc, s, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_fpa_util.is_rm(s)) {
|
||||||
|
if (e == 0)
|
||||||
|
result = m_fpa_util.mk_round_toward_zero();
|
||||||
|
else if (m_fpa_util.is_rm_numeral(e))
|
||||||
|
result = e;
|
||||||
|
else {
|
||||||
|
SASSERT(m_bv_util.is_bv(e) && m_bv_util.get_bv_size(e) == 3);
|
||||||
|
result = convert_bv2rm(mc, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (is_app(e)) {
|
||||||
|
app * a = to_app(e);
|
||||||
|
expr_ref_vector new_args(m);
|
||||||
|
for (unsigned i = 0; i < a->get_num_args(); i++)
|
||||||
|
new_args.push_back(rebuild_floats(mc, a->get_decl()->get_domain()[i], to_app(a->get_arg(i))));
|
||||||
|
result = m.mk_app(a->get_decl(), new_args.size(), new_args.c_ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bv2fpa_converter::array_model bv2fpa_converter::convert_array_func_interp(model_core * mc, func_decl * f, func_decl * bv_f) {
|
||||||
|
SASSERT(f->get_arity() == 0);
|
||||||
|
array_util arr_util(m);
|
||||||
|
|
||||||
|
array_model am(m);
|
||||||
|
sort_ref_vector array_domain(m);
|
||||||
|
unsigned arity = f->get_range()->get_num_parameters()-1;
|
||||||
|
|
||||||
|
expr_ref as_arr_mdl(m);
|
||||||
|
as_arr_mdl = mc->get_const_interp(bv_f);
|
||||||
|
if (as_arr_mdl == 0) return am;
|
||||||
|
TRACE("bv2fpa", tout << "arity=0 func_interp for " << mk_ismt2_pp(f, m) << " := " << mk_ismt2_pp(as_arr_mdl, m) << std::endl;);
|
||||||
|
SASSERT(arr_util.is_as_array(as_arr_mdl));
|
||||||
|
for (unsigned i = 0; i < arity; i++)
|
||||||
|
array_domain.push_back(to_sort(f->get_range()->get_parameter(i).get_ast()));
|
||||||
|
sort * rng = to_sort(f->get_range()->get_parameter(arity).get_ast());
|
||||||
|
|
||||||
|
bv_f = arr_util.get_as_array_func_decl(to_app(as_arr_mdl));
|
||||||
|
|
||||||
|
am.new_float_fd = m.mk_fresh_func_decl(arity, array_domain.c_ptr(), rng);
|
||||||
|
am.new_float_fi = convert_func_interp(mc, am.new_float_fd, bv_f);
|
||||||
|
am.bv_fd = bv_f;
|
||||||
|
am.result = arr_util.mk_as_array(f->get_range(), am.new_float_fd);
|
||||||
|
return am;
|
||||||
|
}
|
||||||
|
|
||||||
|
func_interp * bv2fpa_converter::convert_func_interp(model_core * mc, func_decl * f, func_decl * bv_f) {
|
||||||
|
SASSERT(f->get_arity() > 0);
|
||||||
|
func_interp * result = 0;
|
||||||
|
sort * rng = f->get_range();
|
||||||
|
sort * const * dmn = f->get_domain();
|
||||||
|
|
||||||
|
unsigned arity = bv_f->get_arity();
|
||||||
|
func_interp * bv_fi = mc->get_func_interp(bv_f);
|
||||||
|
|
||||||
|
if (bv_fi != 0) {
|
||||||
|
fpa_rewriter rw(m);
|
||||||
|
expr_ref ai(m);
|
||||||
|
result = alloc(func_interp, m, arity);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < bv_fi->num_entries(); i++) {
|
||||||
|
func_entry const * bv_fe = bv_fi->get_entry(i);
|
||||||
|
expr * const * bv_args = bv_fe->get_args();
|
||||||
|
expr_ref_buffer new_args(m);
|
||||||
|
|
||||||
|
for (unsigned j = 0; j < arity; j++) {
|
||||||
|
sort * ft_dj = dmn[j];
|
||||||
|
expr * bv_aj = bv_args[j];
|
||||||
|
ai = rebuild_floats(mc, ft_dj, to_app(bv_aj));
|
||||||
|
m_th_rw(ai);
|
||||||
|
new_args.push_back(ai);
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_ref bv_fres(m), ft_fres(m);
|
||||||
|
bv_fres = bv_fe->get_result();
|
||||||
|
ft_fres = rebuild_floats(mc, rng, to_app(bv_fres));
|
||||||
|
m_th_rw(ft_fres);
|
||||||
|
result->insert_new_entry(new_args.c_ptr(), ft_fres);
|
||||||
|
}
|
||||||
|
|
||||||
|
app_ref bv_els(m);
|
||||||
|
expr_ref ft_els(m);
|
||||||
|
bv_els = (app*)bv_fi->get_else();
|
||||||
|
ft_els = rebuild_floats(mc, rng, bv_els);
|
||||||
|
m_th_rw(ft_els);
|
||||||
|
result->set_else(ft_els);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bv2fpa_converter::convert_consts(model_core * mc, model_core * target_model, obj_hashtable<func_decl> & seen) {
|
||||||
|
for (obj_map<func_decl, expr*>::iterator it = m_const2bv.begin();
|
||||||
|
it != m_const2bv.end();
|
||||||
|
it++)
|
||||||
|
{
|
||||||
|
func_decl * var = it->m_key;
|
||||||
|
app * val = to_app(it->m_value);
|
||||||
|
SASSERT(m_fpa_util.is_float(var->get_range()));
|
||||||
|
SASSERT(var->get_range()->get_num_parameters() == 2);
|
||||||
|
unsigned ebits = m_fpa_util.get_ebits(var->get_range());
|
||||||
|
unsigned sbits = m_fpa_util.get_sbits(var->get_range());
|
||||||
|
|
||||||
|
app * a0 = to_app(val->get_arg(0));
|
||||||
|
app * a1 = to_app(val->get_arg(1));
|
||||||
|
app * a2 = to_app(val->get_arg(2));
|
||||||
|
|
||||||
|
expr_ref v0(m), v1(m), v2(m);
|
||||||
|
#ifdef Z3DEBUG
|
||||||
|
v0 = mc->get_const_interp(a0->get_decl());
|
||||||
|
v1 = mc->get_const_interp(a1->get_decl());
|
||||||
|
v2 = mc->get_const_interp(a2->get_decl());
|
||||||
|
#else
|
||||||
|
expr * bv = mc->get_const_interp(to_app(to_app(a0)->get_arg(0))->get_decl());
|
||||||
|
unsigned bv_sz = m_bv_util.get_bv_size(bv);
|
||||||
|
v0 = m_bv_util.mk_extract(bv_sz-1, bv_sz-1, bv);
|
||||||
|
v1 = m_bv_util.mk_extract(bv_sz-2, sbits-1, bv);
|
||||||
|
v2 = m_bv_util.mk_extract(sbits-2, 0, bv);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!v0) v0 = m_bv_util.mk_numeral(0, 1);
|
||||||
|
if (!v1) v1 = m_bv_util.mk_numeral(0, ebits);
|
||||||
|
if (!v2) v2 = m_bv_util.mk_numeral(0, sbits-1);
|
||||||
|
|
||||||
|
expr_ref sgn(m), exp(m), sig(m);
|
||||||
|
m_th_rw(v0, sgn);
|
||||||
|
m_th_rw(v1, exp);
|
||||||
|
m_th_rw(v2, sig);
|
||||||
|
|
||||||
|
SASSERT(val->is_app_of(m_fpa_util.get_family_id(), OP_FPA_FP));
|
||||||
|
|
||||||
|
#ifdef Z3DEBUG
|
||||||
|
SASSERT(to_app(val->get_arg(0))->get_decl()->get_arity() == 0);
|
||||||
|
SASSERT(to_app(val->get_arg(1))->get_decl()->get_arity() == 0);
|
||||||
|
SASSERT(to_app(val->get_arg(2))->get_decl()->get_arity() == 0);
|
||||||
|
seen.insert(to_app(val->get_arg(0))->get_decl());
|
||||||
|
seen.insert(to_app(val->get_arg(1))->get_decl());
|
||||||
|
seen.insert(to_app(val->get_arg(2))->get_decl());
|
||||||
|
#else
|
||||||
|
SASSERT(a->get_arg(0)->get_kind() == OP_EXTRACT);
|
||||||
|
SASSERT(to_app(a->get_arg(0))->get_arg(0)->get_kind() == OP_EXTRACT);
|
||||||
|
seen.insert(to_app(to_app(val->get_arg(0))->get_arg(0))->get_decl());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!sgn && !sig && !exp)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
expr_ref cv(m);
|
||||||
|
cv = convert_bv2fp(var->get_range(), sgn, exp, sig);
|
||||||
|
target_model->register_decl(var, cv);
|
||||||
|
|
||||||
|
TRACE("bv2fpa", tout << var->get_name() << " == " << mk_ismt2_pp(cv, m) << std::endl;);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bv2fpa_converter::convert_rm_consts(model_core * mc, model_core * target_model, obj_hashtable<func_decl> & seen) {
|
||||||
|
for (obj_map<func_decl, expr*>::iterator it = m_rm_const2bv.begin();
|
||||||
|
it != m_rm_const2bv.end();
|
||||||
|
it++)
|
||||||
|
{
|
||||||
|
func_decl * var = it->m_key;
|
||||||
|
SASSERT(m_fpa_util.is_rm(var->get_range()));
|
||||||
|
expr * val = it->m_value;
|
||||||
|
SASSERT(m_fpa_util.is_bv2rm(val));
|
||||||
|
expr * bvval = to_app(val)->get_arg(0);
|
||||||
|
expr_ref fv(m);
|
||||||
|
fv = convert_bv2rm(mc, to_app(bvval));
|
||||||
|
TRACE("bv2fpa", tout << var->get_name() << " == " << mk_ismt2_pp(fv, m) << ")" << std::endl;);
|
||||||
|
target_model->register_decl(var, fv);
|
||||||
|
seen.insert(to_app(bvval)->get_decl());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bv2fpa_converter::convert_min_max_specials(model_core * mc, model_core * target_model, obj_hashtable<func_decl> & seen) {
|
||||||
|
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = m_specials.begin();
|
||||||
|
it != m_specials.end();
|
||||||
|
it++) {
|
||||||
|
func_decl * f = it->m_key;
|
||||||
|
app * pn_cnst = it->m_value.first;
|
||||||
|
app * np_cnst = it->m_value.second;
|
||||||
|
|
||||||
|
expr_ref pzero(m), nzero(m);
|
||||||
|
pzero = m_fpa_util.mk_pzero(f->get_range());
|
||||||
|
nzero = m_fpa_util.mk_nzero(f->get_range());
|
||||||
|
|
||||||
|
expr_ref pn(m), np(m);
|
||||||
|
if (!mc->eval(pn_cnst->get_decl(), pn)) pn = pzero;
|
||||||
|
if (!mc->eval(np_cnst->get_decl(), np)) np = pzero;
|
||||||
|
seen.insert(pn_cnst->get_decl());
|
||||||
|
seen.insert(np_cnst->get_decl());
|
||||||
|
|
||||||
|
rational pn_num, np_num;
|
||||||
|
unsigned bv_sz;
|
||||||
|
m_bv_util.is_numeral(pn, pn_num, bv_sz);
|
||||||
|
m_bv_util.is_numeral(np, np_num, bv_sz);
|
||||||
|
|
||||||
|
func_interp * flt_fi = alloc(func_interp, m, f->get_arity());
|
||||||
|
expr * pn_args[2] = { pzero, nzero };
|
||||||
|
if (pn != np) flt_fi->insert_new_entry(pn_args, (pn_num.is_one() ? nzero : pzero));
|
||||||
|
flt_fi->set_else(np_num.is_one() ? nzero : pzero);
|
||||||
|
|
||||||
|
target_model->register_decl(f, flt_fi);
|
||||||
|
TRACE("bv2fpa", tout << "fp.min/fp.max special: " << std::endl <<
|
||||||
|
mk_ismt2_pp(f, m) << " == " << mk_ismt2_pp(flt_fi->get_interp(), m) << std::endl;);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bv2fpa_converter::convert_uf2bvuf(model_core * mc, model_core * target_model, obj_hashtable<func_decl> & seen) {
|
||||||
|
for (obj_map<func_decl, func_decl*>::iterator it = m_uf2bvuf.begin();
|
||||||
|
it != m_uf2bvuf.end();
|
||||||
|
it++) {
|
||||||
|
seen.insert(it->m_value);
|
||||||
|
|
||||||
|
func_decl * f = it->m_key;
|
||||||
|
if (f->get_arity() == 0)
|
||||||
|
{
|
||||||
|
array_util au(m);
|
||||||
|
if (au.is_array(f->get_range())) {
|
||||||
|
array_model am = convert_array_func_interp(mc, f, it->m_value);
|
||||||
|
if (am.new_float_fd) target_model->register_decl(am.new_float_fd, am.new_float_fi);
|
||||||
|
if (am.result) target_model->register_decl(f, am.result);
|
||||||
|
if (am.bv_fd) seen.insert(am.bv_fd);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Just keep.
|
||||||
|
SASSERT(!m_fpa_util.is_float(f->get_range()) && !m_fpa_util.is_rm(f->get_range()));
|
||||||
|
expr_ref var(m), val(m);
|
||||||
|
if (mc->eval(it->m_value, val))
|
||||||
|
target_model->register_decl(f, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
func_interp * fmv = convert_func_interp(mc, f, it->m_value);
|
||||||
|
if (fmv) target_model->register_decl(f, fmv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bv2fpa_converter::display(std::ostream & out) {
|
||||||
|
out << "(fpa2bv-model-converter";
|
||||||
|
for (obj_map<func_decl, expr*>::iterator it = m_const2bv.begin();
|
||||||
|
it != m_const2bv.end();
|
||||||
|
it++) {
|
||||||
|
const symbol & n = it->m_key->get_name();
|
||||||
|
out << "\n (" << n << " ";
|
||||||
|
unsigned indent = n.size() + 4;
|
||||||
|
out << mk_ismt2_pp(it->m_value, m, indent) << ")";
|
||||||
|
}
|
||||||
|
for (obj_map<func_decl, expr*>::iterator it = m_rm_const2bv.begin();
|
||||||
|
it != m_rm_const2bv.end();
|
||||||
|
it++) {
|
||||||
|
const symbol & n = it->m_key->get_name();
|
||||||
|
out << "\n (" << n << " ";
|
||||||
|
unsigned indent = n.size() + 4;
|
||||||
|
out << mk_ismt2_pp(it->m_value, m, indent) << ")";
|
||||||
|
}
|
||||||
|
for (obj_map<func_decl, func_decl*>::iterator it = m_uf2bvuf.begin();
|
||||||
|
it != m_uf2bvuf.end();
|
||||||
|
it++) {
|
||||||
|
const symbol & n = it->m_key->get_name();
|
||||||
|
out << "\n (" << n << " ";
|
||||||
|
unsigned indent = n.size() + 4;
|
||||||
|
out << mk_ismt2_pp(it->m_value, m, indent) << ")";
|
||||||
|
}
|
||||||
|
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = m_specials.begin();
|
||||||
|
it != m_specials.end();
|
||||||
|
it++) {
|
||||||
|
const symbol & n = it->m_key->get_name();
|
||||||
|
out << "\n (" << n << " ";
|
||||||
|
unsigned indent = n.size() + 4;
|
||||||
|
out << mk_ismt2_pp(it->m_value.first, m, indent) << "; " <<
|
||||||
|
mk_ismt2_pp(it->m_value.second, m, indent) << ")";
|
||||||
|
}
|
||||||
|
out << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
bv2fpa_converter * bv2fpa_converter::translate(ast_translation & translator) {
|
||||||
|
bv2fpa_converter * res = alloc(bv2fpa_converter, translator.to());
|
||||||
|
for (obj_map<func_decl, expr*>::iterator it = m_const2bv.begin();
|
||||||
|
it != m_const2bv.end();
|
||||||
|
it++)
|
||||||
|
{
|
||||||
|
func_decl * k = translator(it->m_key);
|
||||||
|
expr * v = translator(it->m_value);
|
||||||
|
res->m_const2bv.insert(k, v);
|
||||||
|
translator.to().inc_ref(k);
|
||||||
|
translator.to().inc_ref(v);
|
||||||
|
}
|
||||||
|
for (obj_map<func_decl, expr*>::iterator it = m_rm_const2bv.begin();
|
||||||
|
it != m_rm_const2bv.end();
|
||||||
|
it++)
|
||||||
|
{
|
||||||
|
func_decl * k = translator(it->m_key);
|
||||||
|
expr * v = translator(it->m_value);
|
||||||
|
res->m_rm_const2bv.insert(k, v);
|
||||||
|
translator.to().inc_ref(k);
|
||||||
|
translator.to().inc_ref(v);
|
||||||
|
}
|
||||||
|
for (obj_map<func_decl, func_decl*>::iterator it = m_uf2bvuf.begin();
|
||||||
|
it != m_uf2bvuf.end();
|
||||||
|
it++) {
|
||||||
|
func_decl * k = translator(it->m_key);
|
||||||
|
func_decl * v = translator(it->m_value);
|
||||||
|
res->m_uf2bvuf.insert(k, v);
|
||||||
|
translator.to().inc_ref(k);
|
||||||
|
translator.to().inc_ref(v);
|
||||||
|
}
|
||||||
|
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = m_specials.begin();
|
||||||
|
it != m_specials.end();
|
||||||
|
it++) {
|
||||||
|
func_decl * k = translator(it->m_key);
|
||||||
|
app * v1 = translator(it->m_value.first);
|
||||||
|
app * v2 = translator(it->m_value.second);
|
||||||
|
res->m_specials.insert(k, std::pair<app*, app*>(v1, v2));
|
||||||
|
translator.to().inc_ref(k);
|
||||||
|
translator.to().inc_ref(v1);
|
||||||
|
translator.to().inc_ref(v2);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bv2fpa_converter::convert(model_core * mc, model_core * float_mdl) {
|
||||||
|
TRACE("bv2fpa", tout << "BV Model: " << std::endl;
|
||||||
|
for (unsigned i = 0; i < mc->get_num_constants(); i++)
|
||||||
|
tout << mc->get_constant(i)->get_name() << " --> " <<
|
||||||
|
mk_ismt2_pp(mc->get_const_interp(mc->get_constant(i)), m) << std::endl;
|
||||||
|
for (unsigned i = 0; i < mc->get_num_functions(); i++) {
|
||||||
|
func_decl * f = mc->get_function(i);
|
||||||
|
tout << f->get_name() << "(...) := " << std::endl;
|
||||||
|
func_interp * fi = mc->get_func_interp(f);
|
||||||
|
for (unsigned j = 0; j < fi->num_entries(); j++) {
|
||||||
|
func_entry const * fe = fi->get_entry(j);
|
||||||
|
for (unsigned k = 0; k < f->get_arity(); k++) {
|
||||||
|
tout << mk_ismt2_pp(fe->get_arg(k), m) << " ";
|
||||||
|
}
|
||||||
|
tout << "--> " << mk_ismt2_pp(fe->get_result(), m) << std::endl;
|
||||||
|
}
|
||||||
|
tout << "else " << mk_ismt2_pp(fi->get_else(), m) << std::endl;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
74
src/ast/fpa/bv2fpa_converter.h
Normal file
74
src/ast/fpa/bv2fpa_converter.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) 2016 Microsoft Corporation
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
bv2fpa_converter.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Model conversion for fpa2bv_converter
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Christoph (cwinter) 2016-10-15
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
#ifndef BV2FPA_CONVERTER_H_
|
||||||
|
#define BV2FPA_CONVERTER_H_
|
||||||
|
|
||||||
|
#include"fpa_decl_plugin.h"
|
||||||
|
#include"bv_decl_plugin.h"
|
||||||
|
#include"th_rewriter.h"
|
||||||
|
#include"model_core.h"
|
||||||
|
#include"fpa2bv_converter.h"
|
||||||
|
|
||||||
|
|
||||||
|
class bv2fpa_converter {
|
||||||
|
ast_manager & m;
|
||||||
|
fpa_util m_fpa_util;
|
||||||
|
bv_util m_bv_util;
|
||||||
|
th_rewriter m_th_rw;
|
||||||
|
|
||||||
|
obj_map<func_decl, expr*> m_const2bv;
|
||||||
|
obj_map<func_decl, expr*> m_rm_const2bv;
|
||||||
|
obj_map<func_decl, func_decl*> m_uf2bvuf;
|
||||||
|
obj_map<func_decl, std::pair<app*, app*> > m_specials;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bv2fpa_converter(ast_manager & m);
|
||||||
|
bv2fpa_converter(ast_manager & m, fpa2bv_converter & conv);
|
||||||
|
virtual ~bv2fpa_converter();
|
||||||
|
|
||||||
|
void display(std::ostream & out);
|
||||||
|
bv2fpa_converter * translate(ast_translation & translator);
|
||||||
|
|
||||||
|
expr_ref convert_bv2fp(sort * s, expr * sgn, expr * exp, expr * sig);
|
||||||
|
expr_ref convert_bv2fp(model_core * mc, sort * s, app * bv);
|
||||||
|
expr_ref convert_bv2rm(expr * eval_v);
|
||||||
|
expr_ref convert_bv2rm(model_core * mc, app * val);
|
||||||
|
|
||||||
|
void convert(model_core * mc, model_core * float_mdl);
|
||||||
|
void convert_consts(model_core * mc, model_core * target_model, obj_hashtable<func_decl> & seen);
|
||||||
|
void convert_rm_consts(model_core * mc, model_core * target_model, obj_hashtable<func_decl> & seen);
|
||||||
|
void convert_min_max_specials(model_core * mc, model_core * target_model, obj_hashtable<func_decl> & seen);
|
||||||
|
void convert_uf2bvuf(model_core * mc, model_core * target_model, obj_hashtable<func_decl> & seen);
|
||||||
|
|
||||||
|
func_interp * convert_func_interp(model_core * mc, func_decl * f, func_decl * bv_f);
|
||||||
|
expr_ref rebuild_floats(model_core * mc, sort * s, app * e);
|
||||||
|
|
||||||
|
class array_model {
|
||||||
|
public:
|
||||||
|
func_decl * new_float_fd;
|
||||||
|
func_interp * new_float_fi;
|
||||||
|
func_decl * bv_fd;
|
||||||
|
expr_ref result;
|
||||||
|
array_model(ast_manager & m) : new_float_fd(0), new_float_fi(0), bv_fd(0), result(m) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
array_model convert_array_func_interp(model_core * mc, func_decl * f, func_decl * bv_f);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -23,6 +23,7 @@ Notes:
|
||||||
#include"th_rewriter.h"
|
#include"th_rewriter.h"
|
||||||
|
|
||||||
#include"fpa2bv_converter.h"
|
#include"fpa2bv_converter.h"
|
||||||
|
#include"fpa_rewriter.h"
|
||||||
|
|
||||||
#define BVULT(X,Y,R) { expr_ref bvult_eq(m), bvult_not(m); m_simp.mk_eq(X, Y, bvult_eq); m_simp.mk_not(bvult_eq, bvult_not); expr_ref t(m); t = m_bv_util.mk_ule(X,Y); m_simp.mk_and(t, bvult_not, R); }
|
#define BVULT(X,Y,R) { expr_ref bvult_eq(m), bvult_not(m); m_simp.mk_eq(X, Y, bvult_eq); m_simp.mk_not(bvult_eq, bvult_not); expr_ref t(m); t = m_bv_util.mk_ule(X,Y); m_simp.mk_and(t, bvult_not, R); }
|
||||||
|
|
||||||
|
@ -32,7 +33,6 @@ fpa2bv_converter::fpa2bv_converter(ast_manager & m) :
|
||||||
m_util(m),
|
m_util(m),
|
||||||
m_bv_util(m),
|
m_bv_util(m),
|
||||||
m_arith_util(m),
|
m_arith_util(m),
|
||||||
m_array_util(m),
|
|
||||||
m_dt_util(m),
|
m_dt_util(m),
|
||||||
m_seq_util(m),
|
m_seq_util(m),
|
||||||
m_mpf_manager(m_util.fm()),
|
m_mpf_manager(m_util.fm()),
|
||||||
|
@ -165,7 +165,6 @@ void fpa2bv_converter::mk_numeral(sort * s, mpf const & v, expr_ref & result) {
|
||||||
result = m_util.mk_fp(bv_sgn, biased_exp, bv_sig);
|
result = m_util.mk_fp(bv_sgn, biased_exp, bv_sig);
|
||||||
TRACE("fpa2bv_dbg", tout << "value of [" << sign << " " << m_mpz_manager.to_string(sig) << " " << exp << "] is "
|
TRACE("fpa2bv_dbg", tout << "value of [" << sign << " " << m_mpz_manager.to_string(sig) << " " << exp << "] is "
|
||||||
<< mk_ismt2_pp(result, m) << std::endl;);
|
<< mk_ismt2_pp(result, m) << std::endl;);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2772,6 +2771,7 @@ void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * ar
|
||||||
|
|
||||||
expr_ref unspec(m);
|
expr_ref unspec(m);
|
||||||
unspec = mk_to_real_unspecified(ebits, sbits);
|
unspec = mk_to_real_unspecified(ebits, sbits);
|
||||||
|
|
||||||
result = m.mk_ite(x_is_zero, zero, res);
|
result = m.mk_ite(x_is_zero, zero, res);
|
||||||
result = m.mk_ite(x_is_inf, unspec, result);
|
result = m.mk_ite(x_is_inf, unspec, result);
|
||||||
result = m.mk_ite(x_is_nan, unspec, result);
|
result = m.mk_ite(x_is_nan, unspec, result);
|
||||||
|
@ -3073,13 +3073,55 @@ void fpa2bv_converter::mk_to_ieee_bv(func_decl * f, unsigned num, expr * const *
|
||||||
m_bv_util.mk_concat(m_bv_util.mk_numeral(-1, ebits),
|
m_bv_util.mk_concat(m_bv_util.mk_numeral(-1, ebits),
|
||||||
m_bv_util.mk_concat(m_bv_util.mk_numeral(0, sbits - 2),
|
m_bv_util.mk_concat(m_bv_util.mk_numeral(0, sbits - 2),
|
||||||
m_bv_util.mk_numeral(1, 1))));
|
m_bv_util.mk_numeral(1, 1))));
|
||||||
else
|
else {
|
||||||
nanv = mk_to_ieee_bv_unspecified(ebits, sbits);
|
app_ref unspec(m);
|
||||||
|
unspec = m_util.mk_internal_to_ieee_bv_unspecified(ebits, sbits);
|
||||||
|
mk_to_ieee_bv_unspecified(unspec->get_decl(), 0, 0, nanv);
|
||||||
|
}
|
||||||
|
|
||||||
expr_ref sgn_e_s(m);
|
expr_ref sgn_e_s(m);
|
||||||
sgn_e_s = m_bv_util.mk_concat(m_bv_util.mk_concat(sgn, e), s);
|
sgn_e_s = m_bv_util.mk_concat(m_bv_util.mk_concat(sgn, e), s);
|
||||||
m_simp.mk_ite(x_is_nan, nanv, sgn_e_s, result);
|
m_simp.mk_ite(x_is_nan, nanv, sgn_e_s, result);
|
||||||
|
|
||||||
|
TRACE("fpa2bv_to_ieee_bv", tout << "result=" << mk_ismt2_pp(result, m) << std::endl;);
|
||||||
|
SASSERT(is_well_sorted(m, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
void fpa2bv_converter::mk_to_ieee_bv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||||
|
SASSERT(num == 0);
|
||||||
|
unsigned ebits = f->get_parameter(0).get_int();
|
||||||
|
unsigned sbits = f->get_parameter(1).get_int();
|
||||||
|
|
||||||
|
if (m_hi_fp_unspecified) {
|
||||||
|
result = m_bv_util.mk_concat(m_bv_util.mk_concat(
|
||||||
|
m_bv_util.mk_numeral(0, 1),
|
||||||
|
m_bv_util.mk_numeral(-1, ebits)),
|
||||||
|
m_bv_util.mk_numeral(1, sbits-1));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
func_decl * fd;
|
||||||
|
if (m_uf2bvuf.find(f, fd))
|
||||||
|
result = m.mk_const(fd);
|
||||||
|
else {
|
||||||
|
fd = m.mk_fresh_func_decl(0, 0, 0, f->get_range());
|
||||||
|
m_uf2bvuf.insert(f, fd);
|
||||||
|
m.inc_ref(f);
|
||||||
|
m.inc_ref(fd);
|
||||||
|
result = m.mk_const(fd);
|
||||||
|
|
||||||
|
expr_ref exp_bv(m), exp_all_ones(m);
|
||||||
|
exp_bv = m_bv_util.mk_extract(ebits+sbits-2, sbits-1, result);
|
||||||
|
exp_all_ones = m.mk_eq(exp_bv, m_bv_util.mk_numeral(-1, ebits));
|
||||||
|
m_extra_assertions.push_back(exp_all_ones);
|
||||||
|
|
||||||
|
expr_ref sig_bv(m), sig_is_non_zero(m);
|
||||||
|
sig_bv = m_bv_util.mk_extract(sbits-2, 0, result);
|
||||||
|
sig_is_non_zero = m.mk_not(m.mk_eq(sig_bv, m_bv_util.mk_numeral(0, sbits-1)));
|
||||||
|
m_extra_assertions.push_back(sig_is_non_zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("fpa2bv_to_ieee_bv_unspecified", tout << "result=" << mk_ismt2_pp(result, m) << std::endl;);
|
||||||
SASSERT(is_well_sorted(m, result));
|
SASSERT(is_well_sorted(m, result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3112,11 +3154,14 @@ void fpa2bv_converter::mk_to_bv(func_decl * f, unsigned num, expr * const * args
|
||||||
|
|
||||||
// NaN, Inf, or negative (except -0) -> unspecified
|
// NaN, Inf, or negative (except -0) -> unspecified
|
||||||
expr_ref c1(m), v1(m);
|
expr_ref c1(m), v1(m);
|
||||||
if (!is_signed)
|
if (!is_signed) {
|
||||||
c1 = m.mk_or(x_is_nan, x_is_inf, m.mk_and(x_is_neg, m.mk_not(x_is_nzero)));
|
c1 = m.mk_or(x_is_nan, x_is_inf, m.mk_and(x_is_neg, m.mk_not(x_is_nzero)));
|
||||||
else
|
|
||||||
c1 = m.mk_or(x_is_nan, x_is_inf);
|
|
||||||
v1 = mk_to_ubv_unspecified(ebits, sbits, bv_sz);
|
v1 = mk_to_ubv_unspecified(ebits, sbits, bv_sz);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c1 = m.mk_or(x_is_nan, x_is_inf);
|
||||||
|
v1 = mk_to_sbv_unspecified(ebits, sbits, bv_sz);
|
||||||
|
}
|
||||||
dbg_decouple("fpa2bv_to_bv_c1", c1);
|
dbg_decouple("fpa2bv_to_bv_c1", c1);
|
||||||
|
|
||||||
// +-Zero -> 0
|
// +-Zero -> 0
|
||||||
|
@ -3226,7 +3271,8 @@ void fpa2bv_converter::mk_to_bv(func_decl * f, unsigned num, expr * const * args
|
||||||
dbg_decouple("fpa2bv_to_bv_rnd", rnd);
|
dbg_decouple("fpa2bv_to_bv_rnd", rnd);
|
||||||
|
|
||||||
expr_ref unspec(m);
|
expr_ref unspec(m);
|
||||||
unspec = mk_to_ubv_unspecified(ebits, sbits, bv_sz);
|
unspec = is_signed ? mk_to_sbv_unspecified(ebits, sbits, bv_sz) :
|
||||||
|
mk_to_ubv_unspecified(ebits, sbits, bv_sz);
|
||||||
result = m.mk_ite(rnd_has_overflown, unspec, rnd);
|
result = m.mk_ite(rnd_has_overflown, unspec, rnd);
|
||||||
result = m.mk_ite(c_in_limits, result, unspec);
|
result = m.mk_ite(c_in_limits, result, unspec);
|
||||||
result = m.mk_ite(c2, v2, result);
|
result = m.mk_ite(c2, v2, result);
|
||||||
|
@ -3247,101 +3293,85 @@ void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * arg
|
||||||
mk_to_bv(f, num, args, true, result);
|
mk_to_bv(f, num, args, true, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_ref fpa2bv_converter::mk_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned width) {
|
void fpa2bv_converter::mk_to_ubv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||||
expr_ref result(m);
|
SASSERT(num == 0);
|
||||||
|
unsigned width = m_bv_util.get_bv_size(f->get_range());
|
||||||
|
|
||||||
if (m_hi_fp_unspecified)
|
if (m_hi_fp_unspecified)
|
||||||
result = m_bv_util.mk_numeral(0, width);
|
result = m_bv_util.mk_numeral(0, width);
|
||||||
else {
|
else {
|
||||||
app_ref unspec(m);
|
|
||||||
unspec = m_util.mk_internal_to_ubv_unspecified(ebits, sbits, width);
|
|
||||||
func_decl * unspec_fd = unspec->get_decl();
|
|
||||||
func_decl * fd;
|
func_decl * fd;
|
||||||
if (!m_uf2bvuf.find(unspec_fd, fd)) {
|
if (!m_uf2bvuf.find(f, fd)) {
|
||||||
app_ref bvc(m);
|
fd = m.mk_fresh_func_decl(0, 0, 0, f->get_range());
|
||||||
bvc = m.mk_fresh_const(0, unspec_fd->get_range());
|
m_uf2bvuf.insert(f, fd);
|
||||||
fd = bvc->get_decl();
|
m.inc_ref(f);
|
||||||
m_uf2bvuf.insert(unspec_fd, fd);
|
|
||||||
m.inc_ref(unspec_fd);
|
|
||||||
m.inc_ref(fd);
|
m.inc_ref(fd);
|
||||||
}
|
}
|
||||||
result = m.mk_const(fd);
|
result = m.mk_const(fd);
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
|
TRACE("fpa2bv_to_ubv_unspecified", tout << "result=" << mk_ismt2_pp(result, m) << std::endl;);
|
||||||
|
SASSERT(is_well_sorted(m, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_ref fpa2bv_converter::mk_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned width) {
|
||||||
|
expr_ref res(m);
|
||||||
|
app_ref u(m);
|
||||||
|
u = m_util.mk_internal_to_ubv_unspecified(ebits, sbits, width);
|
||||||
|
mk_to_sbv_unspecified(u->get_decl(), 0, 0, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fpa2bv_converter::mk_to_sbv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||||
|
SASSERT(num == 0);
|
||||||
|
unsigned width = m_bv_util.get_bv_size(f->get_range());
|
||||||
|
|
||||||
|
if (m_hi_fp_unspecified)
|
||||||
|
result = m_bv_util.mk_numeral(0, width);
|
||||||
|
else {
|
||||||
|
func_decl * fd;
|
||||||
|
if (!m_uf2bvuf.find(f, fd)) {
|
||||||
|
fd = m.mk_fresh_func_decl(0, 0, 0, f->get_range());
|
||||||
|
m_uf2bvuf.insert(f, fd);
|
||||||
|
m.inc_ref(f);
|
||||||
|
m.inc_ref(fd);
|
||||||
|
}
|
||||||
|
result = m.mk_const(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("fpa2bv_to_sbv_unspecified", tout << "result=" << mk_ismt2_pp(result, m) << std::endl;);
|
||||||
|
SASSERT(is_well_sorted(m, result));
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_ref fpa2bv_converter::mk_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned width) {
|
expr_ref fpa2bv_converter::mk_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned width) {
|
||||||
expr_ref result(m);
|
expr_ref res(m);
|
||||||
if (m_hi_fp_unspecified)
|
app_ref u(m);
|
||||||
result = m_bv_util.mk_numeral(0, width);
|
u = m_util.mk_internal_to_sbv_unspecified(ebits, sbits, width);
|
||||||
else {
|
mk_to_sbv_unspecified(u->get_decl(), 0, 0, res);
|
||||||
app_ref unspec(m);
|
return res;
|
||||||
unspec = m_util.mk_internal_to_sbv_unspecified(ebits, sbits, width);
|
|
||||||
func_decl * unspec_fd = unspec->get_decl();
|
|
||||||
func_decl * fd;
|
|
||||||
if (!m_uf2bvuf.find(unspec_fd, fd)) {
|
|
||||||
app_ref bvc(m);
|
|
||||||
bvc = m.mk_fresh_const(0, unspec_fd->get_range());
|
|
||||||
fd = bvc->get_decl();
|
|
||||||
m_uf2bvuf.insert(unspec_fd, fd);
|
|
||||||
m.inc_ref(unspec_fd);
|
|
||||||
m.inc_ref(fd);
|
|
||||||
}
|
|
||||||
result = m.mk_const(fd);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_ref fpa2bv_converter::mk_to_real_unspecified(unsigned ebits, unsigned sbits) {
|
void fpa2bv_converter::mk_to_real_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||||
expr_ref result(m);
|
|
||||||
if (m_hi_fp_unspecified)
|
if (m_hi_fp_unspecified)
|
||||||
result = m_arith_util.mk_numeral(rational(0), false);
|
result = m_arith_util.mk_numeral(rational(0), false);
|
||||||
else {
|
else {
|
||||||
app_ref unspec(m);
|
|
||||||
unspec = m_util.mk_internal_to_real_unspecified(ebits, sbits);
|
|
||||||
func_decl * unspec_fd = unspec->get_decl();
|
|
||||||
func_decl * fd;
|
func_decl * fd;
|
||||||
if (!m_uf2bvuf.find(unspec_fd, fd)) {
|
if (!m_uf2bvuf.find(f, fd)) {
|
||||||
app_ref bvc(m);
|
fd = m.mk_fresh_func_decl(0, 0, 0, f->get_range());
|
||||||
bvc = m.mk_fresh_const(0, unspec_fd->get_range());
|
m_uf2bvuf.insert(f, fd);
|
||||||
fd = bvc->get_decl();
|
m.inc_ref(f);
|
||||||
m_uf2bvuf.insert(unspec_fd, fd);
|
|
||||||
m.inc_ref(unspec_fd);
|
|
||||||
m.inc_ref(fd);
|
m.inc_ref(fd);
|
||||||
}
|
}
|
||||||
result = m.mk_const(fd);
|
result = m.mk_const(fd);
|
||||||
result = unspec;
|
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_ref fpa2bv_converter::mk_to_ieee_bv_unspecified(unsigned ebits, unsigned sbits) {
|
expr_ref fpa2bv_converter::mk_to_real_unspecified(unsigned ebits, unsigned sbits) {
|
||||||
expr_ref result(m);
|
expr_ref res(m);
|
||||||
|
app_ref u(m);
|
||||||
app_ref unspec(m);
|
u = m_util.mk_internal_to_real_unspecified(ebits, sbits);
|
||||||
unspec = m_util.mk_internal_to_ieee_bv_unspecified(ebits, sbits);
|
mk_to_real_unspecified(u->get_decl(), 0, 0, res);
|
||||||
func_decl * unspec_fd = unspec->get_decl();
|
return res;
|
||||||
func_decl * fd;
|
|
||||||
if (!m_uf2bvuf.find(unspec_fd, fd)) {
|
|
||||||
app_ref bvc(m);
|
|
||||||
bvc = m.mk_fresh_const(0, unspec_fd->get_range());
|
|
||||||
fd = bvc->get_decl();
|
|
||||||
m_uf2bvuf.insert(unspec_fd, fd);
|
|
||||||
m.inc_ref(unspec_fd);
|
|
||||||
m.inc_ref(fd);
|
|
||||||
}
|
|
||||||
result = m.mk_const(fd);
|
|
||||||
|
|
||||||
app_ref mask(m), extra(m), result_and_mask(m);
|
|
||||||
mask = m_bv_util.mk_concat(m_bv_util.mk_numeral(0, 1),
|
|
||||||
m_bv_util.mk_concat(m_bv_util.mk_numeral(-1, ebits),
|
|
||||||
m_bv_util.mk_concat(m_bv_util.mk_numeral(0, sbits - 2),
|
|
||||||
m_bv_util.mk_numeral(1, 1))));
|
|
||||||
expr * args[2] = { result, mask };
|
|
||||||
result_and_mask = m.mk_app(m_bv_util.get_fid(), OP_BAND, 2, args);
|
|
||||||
extra = m.mk_eq(result_and_mask, mask);
|
|
||||||
m_extra_assertions.push_back(extra);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fpa2bv_converter::mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
void fpa2bv_converter::mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||||
|
|
|
@ -43,7 +43,6 @@ protected:
|
||||||
fpa_util m_util;
|
fpa_util m_util;
|
||||||
bv_util m_bv_util;
|
bv_util m_bv_util;
|
||||||
arith_util m_arith_util;
|
arith_util m_arith_util;
|
||||||
array_util m_array_util;
|
|
||||||
datatype_util m_dt_util;
|
datatype_util m_dt_util;
|
||||||
seq_util m_seq_util;
|
seq_util m_seq_util;
|
||||||
mpf_manager & m_mpf_manager;
|
mpf_manager & m_mpf_manager;
|
||||||
|
@ -57,6 +56,7 @@ protected:
|
||||||
special_t m_min_max_specials;
|
special_t m_min_max_specials;
|
||||||
|
|
||||||
friend class fpa2bv_model_converter;
|
friend class fpa2bv_model_converter;
|
||||||
|
friend class bv2fpa_converter;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
fpa2bv_converter(ast_manager & m);
|
fpa2bv_converter(ast_manager & m);
|
||||||
|
@ -133,12 +133,16 @@ public:
|
||||||
void mk_to_fp_signed(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
void mk_to_fp_signed(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||||
void mk_to_fp_unsigned(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
void mk_to_fp_unsigned(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||||
void mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
void mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||||
|
void mk_to_ieee_bv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||||
void mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result);
|
void mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result);
|
||||||
void mk_to_fp_real_int(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
void mk_to_fp_real_int(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||||
|
|
||||||
void mk_to_ubv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
void mk_to_ubv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||||
|
void mk_to_ubv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||||
void mk_to_sbv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
void mk_to_sbv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||||
|
void mk_to_sbv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||||
void mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
void mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||||
|
void mk_to_real_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||||
|
|
||||||
void set_unspecified_fp_hi(bool v) { m_hi_fp_unspecified = v; }
|
void set_unspecified_fp_hi(bool v) { m_hi_fp_unspecified = v; }
|
||||||
|
|
||||||
|
@ -149,11 +153,6 @@ public:
|
||||||
void mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
void mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||||
void mk_max_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
void mk_max_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||||
|
|
||||||
expr_ref mk_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned width);
|
|
||||||
expr_ref mk_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned width);
|
|
||||||
expr_ref mk_to_real_unspecified(unsigned ebits, unsigned sbits);
|
|
||||||
expr_ref mk_to_ieee_bv_unspecified(unsigned ebits, unsigned sbits);
|
|
||||||
|
|
||||||
void reset(void);
|
void reset(void);
|
||||||
|
|
||||||
void dbg_decouple(const char * prefix, expr_ref & e);
|
void dbg_decouple(const char * prefix, expr_ref & e);
|
||||||
|
@ -227,6 +226,10 @@ private:
|
||||||
void mk_round_to_integral(sort * s, expr_ref & rm, expr_ref & x, expr_ref & result);
|
void mk_round_to_integral(sort * s, expr_ref & rm, expr_ref & x, expr_ref & result);
|
||||||
|
|
||||||
void mk_to_fp_float(sort * s, expr * rm, expr * x, expr_ref & result);
|
void mk_to_fp_float(sort * s, expr * rm, expr * x, expr_ref & result);
|
||||||
|
|
||||||
|
expr_ref mk_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned width);
|
||||||
|
expr_ref mk_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned width);
|
||||||
|
expr_ref mk_to_real_unspecified(unsigned ebits, unsigned sbits);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -143,9 +143,13 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
|
||||||
case OP_FPA_TO_FP_UNSIGNED: m_conv.mk_to_fp_unsigned(f, num, args, result); return BR_DONE;
|
case OP_FPA_TO_FP_UNSIGNED: m_conv.mk_to_fp_unsigned(f, num, args, result); return BR_DONE;
|
||||||
case OP_FPA_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE;
|
case OP_FPA_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE;
|
||||||
case OP_FPA_TO_UBV: m_conv.mk_to_ubv(f, num, args, result); return BR_DONE;
|
case OP_FPA_TO_UBV: m_conv.mk_to_ubv(f, num, args, result); return BR_DONE;
|
||||||
|
case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED: m_conv.mk_to_ubv_unspecified(f, num, args, result); return BR_DONE;
|
||||||
case OP_FPA_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE;
|
case OP_FPA_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE;
|
||||||
|
case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED: m_conv.mk_to_sbv_unspecified(f, num, args, result); return BR_DONE;
|
||||||
case OP_FPA_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE;
|
case OP_FPA_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE;
|
||||||
|
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED: m_conv.mk_to_real_unspecified(f, num, args, result); return BR_DONE;
|
||||||
case OP_FPA_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE;
|
case OP_FPA_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE;
|
||||||
|
case OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED: m_conv.mk_to_ieee_bv_unspecified(f, num, args, result); return BR_DONE;
|
||||||
|
|
||||||
case OP_FPA_MIN: m_conv.mk_min(f, num, args, result); return BR_REWRITE_FULL;
|
case OP_FPA_MIN: m_conv.mk_min(f, num, args, result); return BR_REWRITE_FULL;
|
||||||
case OP_FPA_MAX: m_conv.mk_max(f, num, args, result); return BR_REWRITE_FULL;
|
case OP_FPA_MAX: m_conv.mk_max(f, num, args, result); return BR_REWRITE_FULL;
|
||||||
|
@ -157,12 +161,8 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
|
||||||
|
|
||||||
case OP_FPA_INTERNAL_BVWRAP:
|
case OP_FPA_INTERNAL_BVWRAP:
|
||||||
case OP_FPA_INTERNAL_BV2RM:
|
case OP_FPA_INTERNAL_BV2RM:
|
||||||
|
|
||||||
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED:
|
|
||||||
case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED:
|
|
||||||
case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED:
|
|
||||||
case OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED:
|
|
||||||
return BR_FAILED;
|
return BR_FAILED;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
TRACE("fpa2bv", tout << "unsupported operator: " << f->get_name() << "\n";
|
TRACE("fpa2bv", tout << "unsupported operator: " << f->get_name() << "\n";
|
||||||
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << std::endl;);
|
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << std::endl;);
|
||||||
|
|
|
@ -665,14 +665,14 @@ func_decl * fpa_decl_plugin::mk_to_real(decl_kind k, unsigned num_parameters, pa
|
||||||
func_decl * fpa_decl_plugin::mk_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
func_decl * fpa_decl_plugin::mk_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||||
unsigned arity, sort * const * domain, sort * range) {
|
unsigned arity, sort * const * domain, sort * range) {
|
||||||
if (arity != 1)
|
if (arity != 1)
|
||||||
m_manager->raise_exception("invalid number of arguments to to_ieee_bv");
|
m_manager->raise_exception("invalid number of arguments to fp.to_ieee_bv");
|
||||||
if (!is_float_sort(domain[0]))
|
if (!is_float_sort(domain[0]))
|
||||||
m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort");
|
m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort");
|
||||||
|
|
||||||
unsigned float_sz = domain[0]->get_parameter(0).get_int() + domain[0]->get_parameter(1).get_int();
|
unsigned float_sz = domain[0]->get_parameter(0).get_int() + domain[0]->get_parameter(1).get_int();
|
||||||
parameter ps[] = { parameter(float_sz) };
|
parameter ps[] = { parameter(float_sz) };
|
||||||
sort * bv_srt = m_bv_plugin->mk_sort(BV_SORT, 1, ps);
|
sort * bv_srt = m_bv_plugin->mk_sort(BV_SORT, 1, ps);
|
||||||
symbol name("to_ieee_bv");
|
symbol name("fp.to_ieee_bv");
|
||||||
return m_manager->mk_func_decl(name, 1, domain, bv_srt, func_decl_info(m_family_id, k));
|
return m_manager->mk_func_decl(name, 1, domain, bv_srt, func_decl_info(m_family_id, k));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,15 +758,15 @@ func_decl * fpa_decl_plugin::mk_internal_to_ieee_bv_unspecified(
|
||||||
decl_kind k, unsigned num_parameters, parameter const * parameters,
|
decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||||
unsigned arity, sort * const * domain, sort * range) {
|
unsigned arity, sort * const * domain, sort * range) {
|
||||||
if (arity != 0)
|
if (arity != 0)
|
||||||
m_manager->raise_exception("invalid number of arguments to to_ieee_bv_unspecified; expecting none");
|
m_manager->raise_exception("invalid number of arguments to fp.to_ieee_bv_unspecified; expecting none");
|
||||||
if (num_parameters != 2)
|
if (num_parameters != 2)
|
||||||
m_manager->raise_exception("invalid number of parameters to to_ieee_bv_unspecified; expecting 2");
|
m_manager->raise_exception("invalid number of parameters to fp.to_ieee_bv_unspecified; expecting 2");
|
||||||
if (!parameters[0].is_int() || !parameters[1].is_int())
|
if (!parameters[0].is_int() || !parameters[1].is_int())
|
||||||
m_manager->raise_exception("invalid parameters type provided to to_ieee_bv_unspecified; expecting 2 integers");
|
m_manager->raise_exception("invalid parameters type provided to fp.to_ieee_bv_unspecified; expecting 2 integers");
|
||||||
|
|
||||||
parameter width_p[1] = { parameter(parameters[0].get_int() + parameters[1].get_int()) };
|
parameter width_p[1] = { parameter(parameters[0].get_int() + parameters[1].get_int()) };
|
||||||
sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, width_p);
|
sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, width_p);
|
||||||
return m_manager->mk_func_decl(symbol("to_ieee_bv_unspecified"), 0, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters));
|
return m_manager->mk_func_decl(symbol("fp.to_ieee_bv_unspecified"), 0, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -916,6 +916,7 @@ void fpa_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol cons
|
||||||
|
|
||||||
/* Extensions */
|
/* Extensions */
|
||||||
op_names.push_back(builtin_name("to_ieee_bv", OP_FPA_TO_IEEE_BV));
|
op_names.push_back(builtin_name("to_ieee_bv", OP_FPA_TO_IEEE_BV));
|
||||||
|
op_names.push_back(builtin_name("fp.to_ieee_bv", OP_FPA_TO_IEEE_BV));
|
||||||
}
|
}
|
||||||
|
|
||||||
void fpa_decl_plugin::get_sort_names(svector<builtin_name> & sort_names, symbol const & logic) {
|
void fpa_decl_plugin::get_sort_names(svector<builtin_name> & sort_names, symbol const & logic) {
|
||||||
|
|
|
@ -377,28 +377,28 @@ public:
|
||||||
app * mk_internal_to_ieee_bv_unspecified(unsigned ebits, unsigned sbits);
|
app * mk_internal_to_ieee_bv_unspecified(unsigned ebits, unsigned sbits);
|
||||||
app * mk_internal_to_real_unspecified(unsigned ebits, unsigned sbits);
|
app * mk_internal_to_real_unspecified(unsigned ebits, unsigned sbits);
|
||||||
|
|
||||||
bool is_bvwrap(expr * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_BVWRAP); }
|
bool is_bvwrap(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_BVWRAP); }
|
||||||
bool is_bvwrap(func_decl * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_BVWRAP; }
|
bool is_bvwrap(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_BVWRAP; }
|
||||||
bool is_bv2rm(expr * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_BV2RM); }
|
bool is_bv2rm(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_BV2RM); }
|
||||||
bool is_bv2rm(func_decl * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_BV2RM; }
|
bool is_bv2rm(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_BV2RM; }
|
||||||
|
|
||||||
bool is_min_interpreted(expr * e) { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_MIN_I); }
|
bool is_min_interpreted(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_MIN_I); }
|
||||||
bool is_min_unspecified(expr * e) { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_MIN_UNSPECIFIED); }
|
bool is_min_unspecified(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_MIN_UNSPECIFIED); }
|
||||||
bool is_max_interpreted(expr * e) { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_MAX_I); }
|
bool is_max_interpreted(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_MAX_I); }
|
||||||
bool is_max_unspecified(expr * e) { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_MAX_UNSPECIFIED); }
|
bool is_max_unspecified(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_MAX_UNSPECIFIED); }
|
||||||
bool is_to_ubv_unspecified(expr * e) { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED); }
|
bool is_to_ubv_unspecified(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED); }
|
||||||
bool is_to_sbv_unspecified(expr * e) { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED); }
|
bool is_to_sbv_unspecified(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED); }
|
||||||
bool is_to_ieee_bv_unspecified(expr * e) { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED); }
|
bool is_to_ieee_bv_unspecified(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED); }
|
||||||
bool is_to_real_unspecified(expr * e) { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED); }
|
bool is_to_real_unspecified(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED); }
|
||||||
|
|
||||||
bool is_min_interpreted(func_decl * f) { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_MIN_I; }
|
bool is_min_interpreted(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_MIN_I; }
|
||||||
bool is_min_unspecified(func_decl * f) { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_MIN_UNSPECIFIED; }
|
bool is_min_unspecified(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_MIN_UNSPECIFIED; }
|
||||||
bool is_max_interpreted(func_decl * f) { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_MAX_I; }
|
bool is_max_interpreted(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_MAX_I; }
|
||||||
bool is_max_unspecified(func_decl * f) { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_MAX_UNSPECIFIED; }
|
bool is_max_unspecified(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_MAX_UNSPECIFIED; }
|
||||||
bool is_to_ubv_unspecified(func_decl * f) { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED; }
|
bool is_to_ubv_unspecified(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED; }
|
||||||
bool is_to_sbv_unspecified(func_decl * f) { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED; }
|
bool is_to_sbv_unspecified(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED; }
|
||||||
bool is_to_ieee_bv_unspecified(func_decl * f) { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED; }
|
bool is_to_ieee_bv_unspecified(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED; }
|
||||||
bool is_to_real_unspecified(func_decl * f) { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED; }
|
bool is_to_real_unspecified(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED; }
|
||||||
|
|
||||||
bool contains_floats(ast * a);
|
bool contains_floats(ast * a);
|
||||||
};
|
};
|
||||||
|
|
|
@ -101,35 +101,47 @@ void pb_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const
|
||||||
}
|
}
|
||||||
|
|
||||||
void pb_util::normalize(unsigned num_args, rational const* coeffs, rational const& k) {
|
void pb_util::normalize(unsigned num_args, rational const* coeffs, rational const& k) {
|
||||||
|
m_coeffs.reset();
|
||||||
|
bool all_ones = true;
|
||||||
|
for (unsigned i = 0; i < num_args && all_ones; ++i) {
|
||||||
|
all_ones = denominator(coeffs[i]).is_one();
|
||||||
|
}
|
||||||
|
if (all_ones) {
|
||||||
|
for (unsigned i = 0; i < num_args; ++i) {
|
||||||
|
m_coeffs.push_back(coeffs[i]);
|
||||||
|
}
|
||||||
|
m_k = k;
|
||||||
|
}
|
||||||
|
else {
|
||||||
rational d(1);
|
rational d(1);
|
||||||
for (unsigned i = 0; i < num_args; ++i) {
|
for (unsigned i = 0; i < num_args; ++i) {
|
||||||
d = lcm(d, denominator(coeffs[i]));
|
d = lcm(d, denominator(coeffs[i]));
|
||||||
}
|
}
|
||||||
m_coeffs.reset();
|
|
||||||
for (unsigned i = 0; i < num_args; ++i) {
|
for (unsigned i = 0; i < num_args; ++i) {
|
||||||
m_coeffs.push_back(d*coeffs[i]);
|
m_coeffs.push_back(d*coeffs[i]);
|
||||||
}
|
}
|
||||||
m_k = d*k;
|
m_k = d*k;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
app * pb_util::mk_le(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k) {
|
app * pb_util::mk_le(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k) {
|
||||||
normalize(num_args, coeffs, k);
|
normalize(num_args, coeffs, k);
|
||||||
vector<parameter> params;
|
m_params.reset();
|
||||||
params.push_back(parameter(floor(m_k)));
|
m_params.push_back(parameter(floor(m_k)));
|
||||||
for (unsigned i = 0; i < num_args; ++i) {
|
for (unsigned i = 0; i < num_args; ++i) {
|
||||||
params.push_back(parameter(m_coeffs[i]));
|
m_params.push_back(parameter(m_coeffs[i]));
|
||||||
}
|
}
|
||||||
return m.mk_app(m_fid, OP_PB_LE, params.size(), params.c_ptr(), num_args, args, m.mk_bool_sort());
|
return m.mk_app(m_fid, OP_PB_LE, m_params.size(), m_params.c_ptr(), num_args, args, m.mk_bool_sort());
|
||||||
}
|
}
|
||||||
|
|
||||||
app * pb_util::mk_ge(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k) {
|
app * pb_util::mk_ge(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k) {
|
||||||
normalize(num_args, coeffs, k);
|
normalize(num_args, coeffs, k);
|
||||||
vector<parameter> params;
|
m_params.reset();
|
||||||
params.push_back(parameter(ceil(m_k)));
|
m_params.push_back(parameter(ceil(m_k)));
|
||||||
for (unsigned i = 0; i < num_args; ++i) {
|
for (unsigned i = 0; i < num_args; ++i) {
|
||||||
params.push_back(parameter(m_coeffs[i]));
|
m_params.push_back(parameter(m_coeffs[i]));
|
||||||
}
|
}
|
||||||
return m.mk_app(m_fid, OP_PB_GE, params.size(), params.c_ptr(), num_args, args, m.mk_bool_sort());
|
return m.mk_app(m_fid, OP_PB_GE, m_params.size(), m_params.c_ptr(), num_args, args, m.mk_bool_sort());
|
||||||
}
|
}
|
||||||
|
|
||||||
app * pb_util::mk_eq(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k) {
|
app * pb_util::mk_eq(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k) {
|
||||||
|
@ -137,12 +149,12 @@ app * pb_util::mk_eq(unsigned num_args, rational const * coeffs, expr * const *
|
||||||
if (!m_k.is_int()) {
|
if (!m_k.is_int()) {
|
||||||
return m.mk_false();
|
return m.mk_false();
|
||||||
}
|
}
|
||||||
vector<parameter> params;
|
m_params.reset();
|
||||||
params.push_back(parameter(m_k));
|
m_params.push_back(parameter(m_k));
|
||||||
for (unsigned i = 0; i < num_args; ++i) {
|
for (unsigned i = 0; i < num_args; ++i) {
|
||||||
params.push_back(parameter(m_coeffs[i]));
|
m_params.push_back(parameter(m_coeffs[i]));
|
||||||
}
|
}
|
||||||
return m.mk_app(m_fid, OP_PB_EQ, params.size(), params.c_ptr(), num_args, args, m.mk_bool_sort());
|
return m.mk_app(m_fid, OP_PB_EQ, m_params.size(), m_params.c_ptr(), num_args, args, m.mk_bool_sort());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ax + by < k
|
// ax + by < k
|
||||||
|
|
|
@ -80,6 +80,7 @@ class pb_util {
|
||||||
ast_manager & m;
|
ast_manager & m;
|
||||||
family_id m_fid;
|
family_id m_fid;
|
||||||
vector<rational> m_coeffs;
|
vector<rational> m_coeffs;
|
||||||
|
vector<parameter> m_params;
|
||||||
rational m_k;
|
rational m_k;
|
||||||
void normalize(unsigned num_args, rational const* coeffs, rational const& k);
|
void normalize(unsigned num_args, rational const* coeffs, rational const& k);
|
||||||
public:
|
public:
|
||||||
|
|
292
src/ast/rewriter/fd_rewriter.cpp
Normal file
292
src/ast/rewriter/fd_rewriter.cpp
Normal file
|
@ -0,0 +1,292 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) 2016 Microsoft Corporation
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
fd_rewriter.cpp
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Conversion from enumeration types to bit-vectors.
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Nikolaj Bjorner (nbjorner) 2016-10-18
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include"rewriter.h"
|
||||||
|
#include"rewriter_def.h"
|
||||||
|
#include"fd_rewriter.h"
|
||||||
|
#include"ast_util.h"
|
||||||
|
#include"ast_pp.h"
|
||||||
|
|
||||||
|
struct fd_rewriter::imp {
|
||||||
|
ast_manager& m;
|
||||||
|
params_ref m_params;
|
||||||
|
obj_map<func_decl, func_decl*> m_enum2bv;
|
||||||
|
obj_map<func_decl, func_decl*> m_bv2enum;
|
||||||
|
obj_map<func_decl, expr*> m_enum2def;
|
||||||
|
expr_ref_vector m_bounds;
|
||||||
|
datatype_util m_dt;
|
||||||
|
func_decl_ref_vector m_enum_consts;
|
||||||
|
func_decl_ref_vector m_enum_bvs;
|
||||||
|
expr_ref_vector m_enum_defs;
|
||||||
|
unsigned_vector m_enum_consts_lim;
|
||||||
|
unsigned m_num_translated;
|
||||||
|
i_sort_pred* m_sort_pred;
|
||||||
|
|
||||||
|
struct rw_cfg : public default_rewriter_cfg {
|
||||||
|
imp& m_imp;
|
||||||
|
ast_manager& m;
|
||||||
|
datatype_util m_dt;
|
||||||
|
bv_util m_bv;
|
||||||
|
|
||||||
|
rw_cfg(imp& i, ast_manager & m) :
|
||||||
|
m_imp(i),
|
||||||
|
m(m),
|
||||||
|
m_dt(m),
|
||||||
|
m_bv(m)
|
||||||
|
{}
|
||||||
|
|
||||||
|
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
||||||
|
expr_ref a0(m), a1(m);
|
||||||
|
expr_ref_vector _args(m);
|
||||||
|
if (m.is_eq(f) && reduce_arg(args[0], a0) && reduce_arg(args[1], a1)) {
|
||||||
|
result = m.mk_eq(a0, a1);
|
||||||
|
return BR_DONE;
|
||||||
|
}
|
||||||
|
else if (m.is_distinct(f) && reduce_args(num, args, _args)) {
|
||||||
|
result = m.mk_distinct(_args.size(), _args.c_ptr());
|
||||||
|
return BR_DONE;
|
||||||
|
}
|
||||||
|
else if (m_dt.is_recognizer(f) && reduce_arg(args[0], a0)) {
|
||||||
|
unsigned idx = m_dt.get_recognizer_constructor_idx(f);
|
||||||
|
a1 = m_bv.mk_numeral(rational(idx), get_sort(a0));
|
||||||
|
result = m.mk_eq(a0, a1);
|
||||||
|
return BR_DONE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
check_for_fd(num, args);
|
||||||
|
return BR_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool reduce_args(unsigned sz, expr*const* as, expr_ref_vector& result) {
|
||||||
|
expr_ref tmp(m);
|
||||||
|
for (unsigned i = 0; i < sz; ++i) {
|
||||||
|
if (!reduce_arg(as[i], tmp)) return false;
|
||||||
|
result.push_back(tmp);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void throw_non_fd(expr* e) {
|
||||||
|
std::stringstream strm;
|
||||||
|
strm << "unabled nested data-type expression " << mk_pp(e, m);
|
||||||
|
throw rewriter_exception(strm.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_for_fd(unsigned n, expr* const* args) {
|
||||||
|
for (unsigned i = 0; i < n; ++i) {
|
||||||
|
if (m_imp.is_fd(get_sort(args[i]))) {
|
||||||
|
throw_non_fd(args[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool reduce_arg(expr* a, expr_ref& result) {
|
||||||
|
|
||||||
|
sort* s = get_sort(a);
|
||||||
|
if (!m_imp.is_fd(s)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
unsigned bv_size = get_bv_size(s);
|
||||||
|
|
||||||
|
if (is_var(a)) {
|
||||||
|
result = m.mk_var(to_var(a)->get_idx(), m_bv.mk_sort(bv_size));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
SASSERT(is_app(a));
|
||||||
|
func_decl* f = to_app(a)->get_decl();
|
||||||
|
if (m_dt.is_constructor(f)) {
|
||||||
|
unsigned idx = m_dt.get_constructor_idx(f);
|
||||||
|
result = m_bv.mk_numeral(idx, bv_size);
|
||||||
|
}
|
||||||
|
else if (is_uninterp_const(a)) {
|
||||||
|
func_decl* f_fresh;
|
||||||
|
if (m_imp.m_enum2bv.find(f, f_fresh)) {
|
||||||
|
result = m.mk_const(f_fresh);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a fresh variable, add bounds constraints for it.
|
||||||
|
unsigned nc = m_dt.get_datatype_num_constructors(s);
|
||||||
|
result = m.mk_fresh_const(f->get_name().str().c_str(), m_bv.mk_sort(bv_size));
|
||||||
|
f_fresh = to_app(result)->get_decl();
|
||||||
|
if (!is_power_of_two(nc)) {
|
||||||
|
m_imp.m_bounds.push_back(m_bv.mk_ule(result, m_bv.mk_numeral(nc-1, bv_size)));
|
||||||
|
}
|
||||||
|
expr_ref f_def(m);
|
||||||
|
ptr_vector<func_decl> const& cs = *m_dt.get_datatype_constructors(s);
|
||||||
|
f_def = m.mk_const(cs[nc-1]);
|
||||||
|
for (unsigned i = nc - 1; i > 0; ) {
|
||||||
|
--i;
|
||||||
|
f_def = m.mk_ite(m.mk_eq(result, m_bv.mk_numeral(i,bv_size)), m.mk_const(cs[i]), f_def);
|
||||||
|
}
|
||||||
|
m_imp.m_enum2def.insert(f, f_def);
|
||||||
|
m_imp.m_enum2bv.insert(f, f_fresh);
|
||||||
|
m_imp.m_bv2enum.insert(f_fresh, f);
|
||||||
|
m_imp.m_enum_consts.push_back(f);
|
||||||
|
m_imp.m_enum_bvs.push_back(f_fresh);
|
||||||
|
m_imp.m_enum_defs.push_back(f_def);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw_non_fd(a);
|
||||||
|
}
|
||||||
|
++m_imp.m_num_translated;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr_buffer<sort> m_sorts;
|
||||||
|
|
||||||
|
bool reduce_quantifier(
|
||||||
|
quantifier * q,
|
||||||
|
expr * old_body,
|
||||||
|
expr * const * new_patterns,
|
||||||
|
expr * const * new_no_patterns,
|
||||||
|
expr_ref & result,
|
||||||
|
proof_ref & result_pr) {
|
||||||
|
m_sorts.reset();
|
||||||
|
expr_ref_vector bounds(m);
|
||||||
|
bool found = false;
|
||||||
|
for (unsigned i = 0; i < q->get_num_decls(); ++i) {
|
||||||
|
sort* s = q->get_decl_sort(i);
|
||||||
|
if (m_imp.is_fd(s)) {
|
||||||
|
unsigned bv_size = get_bv_size(s);
|
||||||
|
m_sorts.push_back(m_bv.mk_sort(bv_size));
|
||||||
|
unsigned nc = m_dt.get_datatype_num_constructors(s);
|
||||||
|
if (!is_power_of_two(nc)) {
|
||||||
|
bounds.push_back(m_bv.mk_ule(m.mk_var(q->get_num_decls()-i-1, m_sorts[i]), m_bv.mk_numeral(nc-1, bv_size)));
|
||||||
|
}
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_sorts.push_back(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
expr_ref new_body_ref(old_body, m), tmp(m);
|
||||||
|
if (!bounds.empty()) {
|
||||||
|
if (q->is_forall()) {
|
||||||
|
new_body_ref = m.mk_implies(mk_and(bounds), new_body_ref);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bounds.push_back(new_body_ref);
|
||||||
|
new_body_ref = mk_and(bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = m.mk_quantifier(q->is_forall(), q->get_num_decls(), m_sorts.c_ptr(), q->get_decl_names(), new_body_ref,
|
||||||
|
q->get_weight(), q->get_qid(), q->get_skid(),
|
||||||
|
q->get_num_patterns(), new_patterns,
|
||||||
|
q->get_num_no_patterns(), new_no_patterns);
|
||||||
|
result_pr = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_bv_size(sort* s) {
|
||||||
|
unsigned nc = m_dt.get_datatype_num_constructors(s);
|
||||||
|
unsigned bv_size = 1;
|
||||||
|
while ((unsigned)(1 << bv_size) < nc) {
|
||||||
|
++bv_size;
|
||||||
|
}
|
||||||
|
return bv_size;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rw : public rewriter_tpl<rw_cfg> {
|
||||||
|
rw_cfg m_cfg;
|
||||||
|
|
||||||
|
rw(imp& t, ast_manager & m, params_ref const & p) :
|
||||||
|
rewriter_tpl<rw_cfg>(m, m.proofs_enabled(), m_cfg),
|
||||||
|
m_cfg(t, m) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
rw m_rw;
|
||||||
|
|
||||||
|
imp(ast_manager& m, params_ref const& p):
|
||||||
|
m(m), m_params(p), m_bounds(m),
|
||||||
|
m_dt(m),
|
||||||
|
m_enum_consts(m),
|
||||||
|
m_enum_bvs(m),
|
||||||
|
m_enum_defs(m),
|
||||||
|
m_num_translated(0),
|
||||||
|
m_sort_pred(0),
|
||||||
|
m_rw(*this, m, p) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void updt_params(params_ref const & p) {}
|
||||||
|
unsigned get_num_steps() const { return m_rw.get_num_steps(); }
|
||||||
|
void cleanup() { m_rw.cleanup(); }
|
||||||
|
void operator()(expr * e, expr_ref & result, proof_ref & result_proof) {
|
||||||
|
m_rw(e, result, result_proof);
|
||||||
|
}
|
||||||
|
void push() {
|
||||||
|
m_enum_consts_lim.push_back(m_enum_consts.size());
|
||||||
|
}
|
||||||
|
void pop(unsigned num_scopes) {
|
||||||
|
SASSERT(m_bounds.empty()); // bounds must be flushed before pop.
|
||||||
|
if (num_scopes > 0) {
|
||||||
|
SASSERT(num_scopes <= m_enum_consts_lim.size());
|
||||||
|
unsigned new_sz = m_enum_consts_lim.size() - num_scopes;
|
||||||
|
unsigned lim = m_enum_consts_lim[new_sz];
|
||||||
|
for (unsigned i = m_enum_consts.size(); i > lim; ) {
|
||||||
|
--i;
|
||||||
|
func_decl* f = m_enum_consts[i].get();
|
||||||
|
func_decl* f_fresh = m_enum2bv.find(f);
|
||||||
|
m_bv2enum.erase(f_fresh);
|
||||||
|
m_enum2bv.erase(f);
|
||||||
|
m_enum2def.erase(f);
|
||||||
|
}
|
||||||
|
m_enum_consts_lim.resize(new_sz);
|
||||||
|
m_enum_consts.resize(lim);
|
||||||
|
m_enum_defs.resize(lim);
|
||||||
|
m_enum_bvs.resize(lim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush_side_constraints(expr_ref_vector& side_constraints) {
|
||||||
|
side_constraints.append(m_bounds);
|
||||||
|
m_bounds.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_fd(sort* s) {
|
||||||
|
return m_dt.is_enum_sort(s) && (!m_sort_pred || (*m_sort_pred)(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_is_fd(i_sort_pred* sp) {
|
||||||
|
m_sort_pred = sp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
fd_rewriter::fd_rewriter(ast_manager & m, params_ref const& p) { m_imp = alloc(imp, m, p); }
|
||||||
|
fd_rewriter::~fd_rewriter() { dealloc(m_imp); }
|
||||||
|
void fd_rewriter::updt_params(params_ref const & p) { m_imp->updt_params(p); }
|
||||||
|
ast_manager & fd_rewriter::m() const { return m_imp->m; }
|
||||||
|
unsigned fd_rewriter::get_num_steps() const { return m_imp->get_num_steps(); }
|
||||||
|
void fd_rewriter::cleanup() { ast_manager& mgr = m(); params_ref p = m_imp->m_params; dealloc(m_imp); m_imp = alloc(imp, mgr, p); }
|
||||||
|
obj_map<func_decl, func_decl*> const& fd_rewriter::enum2bv() const { return m_imp->m_enum2bv; }
|
||||||
|
obj_map<func_decl, func_decl*> const& fd_rewriter::bv2enum() const { return m_imp->m_bv2enum; }
|
||||||
|
obj_map<func_decl, expr*> const& fd_rewriter::enum2def() const { return m_imp->m_enum2def; }
|
||||||
|
void fd_rewriter::operator()(expr * e, expr_ref & result, proof_ref & result_proof) { (*m_imp)(e, result, result_proof); }
|
||||||
|
void fd_rewriter::push() { m_imp->push(); }
|
||||||
|
void fd_rewriter::pop(unsigned num_scopes) { m_imp->pop(num_scopes); }
|
||||||
|
void fd_rewriter::flush_side_constraints(expr_ref_vector& side_constraints) { m_imp->flush_side_constraints(side_constraints); }
|
||||||
|
unsigned fd_rewriter::num_translated() const { return m_imp->m_num_translated; }
|
||||||
|
void fd_rewriter::set_is_fd(i_sort_pred* sp) const { m_imp->set_is_fd(sp); }
|
48
src/ast/rewriter/fd_rewriter.h
Normal file
48
src/ast/rewriter/fd_rewriter.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) 2016 Microsoft Corporation
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
fd_rewriter.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Conversion from enumeration types to bit-vectors.
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Nikolaj Bjorner (nbjorner) 2016-10-18
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
#ifndef ENUM_REWRITER_H_
|
||||||
|
#define ENUM_REWRITER_H_
|
||||||
|
|
||||||
|
#include"datatype_decl_plugin.h"
|
||||||
|
#include"rewriter_types.h"
|
||||||
|
#include"expr_functors.h"
|
||||||
|
|
||||||
|
class fd_rewriter {
|
||||||
|
struct imp;
|
||||||
|
imp* m_imp;
|
||||||
|
public:
|
||||||
|
fd_rewriter(ast_manager & m, params_ref const& p);
|
||||||
|
~fd_rewriter();
|
||||||
|
|
||||||
|
void updt_params(params_ref const & p);
|
||||||
|
ast_manager & m() const;
|
||||||
|
unsigned get_num_steps() const;
|
||||||
|
void cleanup();
|
||||||
|
obj_map<func_decl, func_decl*> const& enum2bv() const;
|
||||||
|
obj_map<func_decl, func_decl*> const& bv2enum() const;
|
||||||
|
obj_map<func_decl, expr*> const& enum2def() const;
|
||||||
|
void operator()(expr * e, expr_ref & result, proof_ref & result_proof);
|
||||||
|
void push();
|
||||||
|
void pop(unsigned num_scopes);
|
||||||
|
void flush_side_constraints(expr_ref_vector& side_constraints);
|
||||||
|
unsigned num_translated() const;
|
||||||
|
void set_is_fd(i_sort_pred* sp) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -18,11 +18,12 @@ Notes:
|
||||||
--*/
|
--*/
|
||||||
#include"fpa_rewriter.h"
|
#include"fpa_rewriter.h"
|
||||||
#include"fpa_rewriter_params.hpp"
|
#include"fpa_rewriter_params.hpp"
|
||||||
|
#include"ast_smt2_pp.h"
|
||||||
|
|
||||||
fpa_rewriter::fpa_rewriter(ast_manager & m, params_ref const & p) :
|
fpa_rewriter::fpa_rewriter(ast_manager & m, params_ref const & p) :
|
||||||
m_util(m),
|
m_util(m),
|
||||||
m_fm(m_util.fm()),
|
m_fm(m_util.fm()),
|
||||||
m_hi_fp_unspecified(true) {
|
m_hi_fp_unspecified(false) {
|
||||||
updt_params(p);
|
updt_params(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,35 +118,41 @@ br_status fpa_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
|
||||||
|
|
||||||
br_status fpa_rewriter::mk_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned width, expr_ref & result) {
|
br_status fpa_rewriter::mk_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned width, expr_ref & result) {
|
||||||
bv_util bu(m());
|
bv_util bu(m());
|
||||||
if (m_hi_fp_unspecified)
|
if (m_hi_fp_unspecified) {
|
||||||
// The "hardware interpretation" is 0.
|
// The "hardware interpretation" is 0.
|
||||||
result = bu.mk_numeral(0, width);
|
result = bu.mk_numeral(0, width);
|
||||||
else
|
|
||||||
result = m_util.mk_internal_to_ubv_unspecified(ebits, sbits, width);
|
|
||||||
|
|
||||||
return BR_DONE;
|
return BR_DONE;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
result = m_util.mk_internal_to_ubv_unspecified(ebits, sbits, width);
|
||||||
|
return BR_REWRITE1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
br_status fpa_rewriter::mk_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned width, expr_ref & result) {
|
br_status fpa_rewriter::mk_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned width, expr_ref & result) {
|
||||||
bv_util bu(m());
|
bv_util bu(m());
|
||||||
if (m_hi_fp_unspecified)
|
if (m_hi_fp_unspecified) {
|
||||||
// The "hardware interpretation" is 0.
|
// The "hardware interpretation" is 0.
|
||||||
result = bu.mk_numeral(0, width);
|
result = bu.mk_numeral(0, width);
|
||||||
else
|
|
||||||
result = m_util.mk_internal_to_sbv_unspecified(ebits, sbits, width);
|
|
||||||
|
|
||||||
return BR_DONE;
|
return BR_DONE;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
result = m_util.mk_internal_to_sbv_unspecified(ebits, sbits, width);
|
||||||
|
return BR_REWRITE1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
br_status fpa_rewriter::mk_to_real_unspecified(unsigned ebits, unsigned sbits, expr_ref & result) {
|
br_status fpa_rewriter::mk_to_real_unspecified(unsigned ebits, unsigned sbits, expr_ref & result) {
|
||||||
if (m_hi_fp_unspecified)
|
if (m_hi_fp_unspecified) {
|
||||||
// The "hardware interpretation" is 0.
|
// The "hardware interpretation" is 0.
|
||||||
result = m_util.au().mk_numeral(rational(0), false);
|
result = m_util.au().mk_numeral(rational(0), false);
|
||||||
else
|
|
||||||
result = m_util.mk_internal_to_real_unspecified(ebits, sbits);
|
|
||||||
|
|
||||||
return BR_DONE;
|
return BR_DONE;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
result = m_util.mk_internal_to_real_unspecified(ebits, sbits);
|
||||||
|
return BR_REWRITE1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||||
SASSERT(f->get_num_parameters() == 2);
|
SASSERT(f->get_num_parameters() == 2);
|
||||||
|
@ -776,10 +783,8 @@ br_status fpa_rewriter::mk_to_ubv(func_decl * f, expr * arg1, expr * arg2, expr_
|
||||||
m_util.is_numeral(arg2, v)) {
|
m_util.is_numeral(arg2, v)) {
|
||||||
const mpf & x = v.get();
|
const mpf & x = v.get();
|
||||||
|
|
||||||
if (m_fm.is_nan(v) || m_fm.is_inf(v) || m_fm.is_neg(v)) {
|
if (m_fm.is_nan(v) || m_fm.is_inf(v) || m_fm.is_neg(v))
|
||||||
mk_to_ubv_unspecified(x.get_ebits(), x.get_sbits(), bv_sz, result);
|
return mk_to_ubv_unspecified(x.get_ebits(), x.get_sbits(), bv_sz, result);
|
||||||
return BR_REWRITE_FULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bv_util bu(m());
|
bv_util bu(m());
|
||||||
scoped_mpq q(m_fm.mpq_manager());
|
scoped_mpq q(m_fm.mpq_manager());
|
||||||
|
@ -789,12 +794,14 @@ br_status fpa_rewriter::mk_to_ubv(func_decl * f, expr * arg1, expr * arg2, expr_
|
||||||
rational ul, ll;
|
rational ul, ll;
|
||||||
ul = m_fm.m_powers2.m1(bv_sz);
|
ul = m_fm.m_powers2.m1(bv_sz);
|
||||||
ll = rational(0);
|
ll = rational(0);
|
||||||
if (r >= ll && r <= ul)
|
if (r >= ll && r <= ul) {
|
||||||
result = bu.mk_numeral(r, bv_sz);
|
result = bu.mk_numeral(r, bv_sz);
|
||||||
else
|
|
||||||
mk_to_ubv_unspecified(x.get_ebits(), x.get_sbits(), bv_sz, result);
|
|
||||||
return BR_DONE;
|
return BR_DONE;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return mk_to_ubv_unspecified(x.get_ebits(), x.get_sbits(), bv_sz, result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return BR_FAILED;
|
return BR_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -810,10 +817,8 @@ br_status fpa_rewriter::mk_to_sbv(func_decl * f, expr * arg1, expr * arg2, expr_
|
||||||
m_util.is_numeral(arg2, v)) {
|
m_util.is_numeral(arg2, v)) {
|
||||||
const mpf & x = v.get();
|
const mpf & x = v.get();
|
||||||
|
|
||||||
if (m_fm.is_nan(v) || m_fm.is_inf(v)) {
|
if (m_fm.is_nan(v) || m_fm.is_inf(v))
|
||||||
mk_to_sbv_unspecified(x.get_ebits(), x.get_sbits(), bv_sz, result);
|
return mk_to_sbv_unspecified(x.get_ebits(), x.get_sbits(), bv_sz, result);
|
||||||
return BR_REWRITE_FULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bv_util bu(m());
|
bv_util bu(m());
|
||||||
scoped_mpq q(m_fm.mpq_manager());
|
scoped_mpq q(m_fm.mpq_manager());
|
||||||
|
@ -823,46 +828,42 @@ br_status fpa_rewriter::mk_to_sbv(func_decl * f, expr * arg1, expr * arg2, expr_
|
||||||
rational ul, ll;
|
rational ul, ll;
|
||||||
ul = m_fm.m_powers2.m1(bv_sz - 1);
|
ul = m_fm.m_powers2.m1(bv_sz - 1);
|
||||||
ll = - m_fm.m_powers2(bv_sz - 1);
|
ll = - m_fm.m_powers2(bv_sz - 1);
|
||||||
if (r >= ll && r <= ul)
|
if (r >= ll && r <= ul) {
|
||||||
result = bu.mk_numeral(r, bv_sz);
|
result = bu.mk_numeral(r, bv_sz);
|
||||||
else
|
|
||||||
mk_to_sbv_unspecified(x.get_ebits(), x.get_sbits(), bv_sz, result);
|
|
||||||
return BR_DONE;
|
return BR_DONE;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return mk_to_sbv_unspecified(x.get_ebits(), x.get_sbits(), bv_sz, result);
|
||||||
|
}
|
||||||
|
|
||||||
return BR_FAILED;
|
return BR_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
br_status fpa_rewriter::mk_to_ieee_bv(func_decl * f, expr * arg, expr_ref & result) {
|
br_status fpa_rewriter::mk_to_ieee_bv(func_decl * f, expr * arg, expr_ref & result) {
|
||||||
|
TRACE("fp_rewriter", tout << "to_ieee_bv of " << mk_ismt2_pp(arg, m()) << std::endl;);
|
||||||
scoped_mpf v(m_fm);
|
scoped_mpf v(m_fm);
|
||||||
|
|
||||||
if (m_util.is_numeral(arg, v)) {
|
if (m_util.is_numeral(arg, v)) {
|
||||||
|
TRACE("fp_rewriter", tout << "to_ieee_bv numeral: " << m_fm.to_string(v) << std::endl;);
|
||||||
bv_util bu(m());
|
bv_util bu(m());
|
||||||
const mpf & x = v.get();
|
const mpf & x = v.get();
|
||||||
|
|
||||||
if (m_fm.is_nan(v)) {
|
if (m_fm.is_nan(v)) {
|
||||||
if (m_hi_fp_unspecified) {
|
if (m_hi_fp_unspecified) {
|
||||||
result = bu.mk_concat(bu.mk_numeral(0, 1),
|
expr * args[4] = { bu.mk_numeral(0, 1),
|
||||||
bu.mk_concat(bu.mk_numeral(-1, x.get_ebits()),
|
bu.mk_numeral(-1, x.get_ebits()),
|
||||||
bu.mk_concat(bu.mk_numeral(0, x.get_sbits() - 2),
|
bu.mk_numeral(0, x.get_sbits() - 2),
|
||||||
bu.mk_numeral(1, 1))));
|
bu.mk_numeral(1, 1) };
|
||||||
|
result = bu.mk_concat(4, args);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
app_ref unspec(m()), mask(m()), extra(m());
|
result = m_util.mk_internal_to_ieee_bv_unspecified(x.get_ebits(), x.get_sbits());
|
||||||
unspec = m_util.mk_internal_to_ieee_bv_unspecified(x.get_ebits(), x.get_sbits());
|
|
||||||
mask = bu.mk_concat(bu.mk_numeral(0, 1),
|
return BR_REWRITE1;
|
||||||
bu.mk_concat(bu.mk_numeral(-1, x.get_ebits()),
|
|
||||||
bu.mk_concat(bu.mk_numeral(0, x.get_sbits() - 2),
|
|
||||||
bu.mk_numeral(1, 1))));
|
|
||||||
expr * args[2] = { unspec, mask };
|
|
||||||
result = m().mk_app(bu.get_fid(), OP_BOR, 2, args);
|
|
||||||
}
|
|
||||||
return BR_REWRITE_FULL;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
scoped_mpz rz(m_fm.mpq_manager());
|
scoped_mpz rz(m_fm.mpq_manager());
|
||||||
m_fm.to_ieee_bv_mpz(v, rz);
|
m_fm.to_ieee_bv_mpz(v, rz);
|
||||||
|
|
||||||
result = bu.mk_numeral(rational(rz), x.get_ebits() + x.get_sbits());
|
result = bu.mk_numeral(rational(rz), x.get_ebits() + x.get_sbits());
|
||||||
return BR_DONE;
|
return BR_DONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
def_module_params(module_name='rewriter',
|
def_module_params(module_name='rewriter',
|
||||||
class_name='fpa_rewriter_params',
|
class_name='fpa_rewriter_params',
|
||||||
export=True,
|
export=True,
|
||||||
params=(("hi_fp_unspecified", BOOL, True, "use the 'hardware interpretation' for unspecified values in fp.to_ubv, fp.to_sbv, and fp.to_real"),
|
params=(("hi_fp_unspecified", BOOL, False, "use the 'hardware interpretation' for unspecified values in fp.to_ubv, fp.to_sbv, fp.to_real, and fp.to_ieee_bv"),
|
||||||
))
|
))
|
||||||
|
|
|
@ -277,6 +277,7 @@ br_status pb_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * cons
|
||||||
tout << tmp << "\n";
|
tout << tmp << "\n";
|
||||||
tout << result << "\n";
|
tout << result << "\n";
|
||||||
);
|
);
|
||||||
|
|
||||||
TRACE("pb_validate",
|
TRACE("pb_validate",
|
||||||
validate_rewrite(f, num_args, args, result););
|
validate_rewrite(f, num_args, args, result););
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,10 @@ Revision History:
|
||||||
#include"array_decl_plugin.h"
|
#include"array_decl_plugin.h"
|
||||||
#include"bv_decl_plugin.h"
|
#include"bv_decl_plugin.h"
|
||||||
#include"seq_decl_plugin.h"
|
#include"seq_decl_plugin.h"
|
||||||
|
#include"datatype_decl_plugin.h"
|
||||||
#include"ast_pp.h"
|
#include"ast_pp.h"
|
||||||
#include"for_each_expr.h"
|
#include"for_each_expr.h"
|
||||||
|
#include<strstream>
|
||||||
|
|
||||||
struct check_logic::imp {
|
struct check_logic::imp {
|
||||||
ast_manager & m;
|
ast_manager & m;
|
||||||
|
@ -31,6 +33,7 @@ struct check_logic::imp {
|
||||||
bv_util m_bv_util;
|
bv_util m_bv_util;
|
||||||
array_util m_ar_util;
|
array_util m_ar_util;
|
||||||
seq_util m_seq_util;
|
seq_util m_seq_util;
|
||||||
|
datatype_util m_dt_util;
|
||||||
bool m_uf; // true if the logic supports uninterpreted functions
|
bool m_uf; // true if the logic supports uninterpreted functions
|
||||||
bool m_arrays; // true if the logic supports arbitrary arrays
|
bool m_arrays; // true if the logic supports arbitrary arrays
|
||||||
bool m_bv_arrays; // true if the logic supports only bv arrays
|
bool m_bv_arrays; // true if the logic supports only bv arrays
|
||||||
|
@ -42,7 +45,7 @@ struct check_logic::imp {
|
||||||
bool m_quantifiers; // true if the logic supports quantifiers
|
bool m_quantifiers; // true if the logic supports quantifiers
|
||||||
bool m_unknown_logic;
|
bool m_unknown_logic;
|
||||||
|
|
||||||
imp(ast_manager & _m):m(_m), m_a_util(m), m_bv_util(m), m_ar_util(m), m_seq_util(m) {
|
imp(ast_manager & _m):m(_m), m_a_util(m), m_bv_util(m), m_ar_util(m), m_seq_util(m), m_dt_util(m) {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,6 +181,11 @@ struct check_logic::imp {
|
||||||
m_reals = true;
|
m_reals = true;
|
||||||
m_quantifiers = false;
|
m_quantifiers = false;
|
||||||
}
|
}
|
||||||
|
else if (logic == "QF_FD") {
|
||||||
|
m_bvs = true;
|
||||||
|
m_uf = true;
|
||||||
|
m_ints = true;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
m_unknown_logic = true;
|
m_unknown_logic = true;
|
||||||
}
|
}
|
||||||
|
@ -432,8 +440,13 @@ struct check_logic::imp {
|
||||||
else if (fid == m_seq_util.get_family_id()) {
|
else if (fid == m_seq_util.get_family_id()) {
|
||||||
// nothing to check
|
// nothing to check
|
||||||
}
|
}
|
||||||
|
else if (fid == m_dt_util.get_family_id() && m_logic == "QF_FD") {
|
||||||
|
// nothing to check
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
fail("logic does not support theory");
|
std::stringstream strm;
|
||||||
|
strm << "logic does not support theory " << m.get_family_name(fid);
|
||||||
|
fail(strm.str().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -568,6 +568,7 @@ bool cmd_context::logic_has_bv_core(symbol const & s) const {
|
||||||
s == "QF_FPBV" ||
|
s == "QF_FPBV" ||
|
||||||
s == "QF_BVFP" ||
|
s == "QF_BVFP" ||
|
||||||
s == "ALL" ||
|
s == "ALL" ||
|
||||||
|
s == "QF_FD" ||
|
||||||
s == "HORN";
|
s == "HORN";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,7 +623,7 @@ bool cmd_context::logic_has_array() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cmd_context::logic_has_datatype() const {
|
bool cmd_context::logic_has_datatype() const {
|
||||||
return !has_logic();
|
return !has_logic() || m_logic == "QF_FD";
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmd_context::init_manager_core(bool new_manager) {
|
void cmd_context::init_manager_core(bool new_manager) {
|
||||||
|
@ -705,7 +706,7 @@ void cmd_context::init_external_manager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cmd_context::supported_logic(symbol const & s) const {
|
bool cmd_context::supported_logic(symbol const & s) const {
|
||||||
return s == "QF_UF" || s == "UF" || s == "ALL" ||
|
return s == "QF_UF" || s == "UF" || s == "ALL" || s == "QF_FD" ||
|
||||||
logic_has_arith_core(s) || logic_has_bv_core(s) ||
|
logic_has_arith_core(s) || logic_has_bv_core(s) ||
|
||||||
logic_has_array_core(s) || logic_has_seq_core(s) ||
|
logic_has_array_core(s) || logic_has_seq_core(s) ||
|
||||||
logic_has_horn(s) || logic_has_fpa_core(s);
|
logic_has_horn(s) || logic_has_fpa_core(s);
|
||||||
|
|
|
@ -87,3 +87,19 @@ void model_core::register_decl(func_decl * d, func_interp * fi) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void model_core::unregister_decl(func_decl * d) {
|
||||||
|
decl2expr::obj_map_entry * ec = m_interp.find_core(d);
|
||||||
|
if (ec && ec->get_data().m_value != 0) {
|
||||||
|
m_manager.dec_ref(ec->get_data().m_key);
|
||||||
|
m_manager.dec_ref(ec->get_data().m_value);
|
||||||
|
m_interp.remove(d);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
decl2finterp::obj_map_entry * ef = m_finterp.find_core(d);
|
||||||
|
if (ef && ef->get_data().m_value != 0) {
|
||||||
|
m_manager.dec_ref(ef->get_data().m_key);
|
||||||
|
dealloc(ef->get_data().m_value);
|
||||||
|
m_finterp.remove(d);
|
||||||
|
}
|
||||||
|
}
|
|
@ -60,6 +60,7 @@ public:
|
||||||
|
|
||||||
void register_decl(func_decl * d, expr * v);
|
void register_decl(func_decl * d, expr * v);
|
||||||
void register_decl(func_decl * f, func_interp * fi);
|
void register_decl(func_decl * f, func_interp * fi);
|
||||||
|
void unregister_decl(func_decl * d);
|
||||||
|
|
||||||
virtual expr * get_some_value(sort * s) = 0;
|
virtual expr * get_some_value(sort * s) = 0;
|
||||||
|
|
||||||
|
|
|
@ -3075,45 +3075,51 @@ namespace sat {
|
||||||
m_binary_clause_graph[l1.index()].push_back(l2);
|
m_binary_clause_graph[l1.index()].push_back(l2);
|
||||||
m_binary_clause_graph[l2.index()].push_back(l1);
|
m_binary_clause_graph[l2.index()].push_back(l1);
|
||||||
}
|
}
|
||||||
while (!ps.empty()) {
|
bool non_empty = true;
|
||||||
|
m_seen[0].reset();
|
||||||
|
while (non_empty) {
|
||||||
literal_vector mutex;
|
literal_vector mutex;
|
||||||
literal_set other(ps);
|
bool turn = false;
|
||||||
while (!other.empty()) {
|
m_reachable[turn] = ps;
|
||||||
literal_set conseq;
|
while (!m_reachable[turn].empty()) {
|
||||||
literal p = other.pop();
|
literal p = m_reachable[turn].pop();
|
||||||
|
if (m_seen[0].contains(p)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
m_reachable[turn].remove(p);
|
||||||
|
m_seen[0].insert(p);
|
||||||
mutex.push_back(p);
|
mutex.push_back(p);
|
||||||
if (other.empty()) {
|
if (m_reachable[turn].empty()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
get_reachable(p, other, conseq);
|
m_reachable[!turn].reset();
|
||||||
other = conseq;
|
get_reachable(p, m_reachable[turn], m_reachable[!turn]);
|
||||||
|
turn = !turn;
|
||||||
}
|
}
|
||||||
if (mutex.size() > 1) {
|
if (mutex.size() > 1) {
|
||||||
mutexes.push_back(mutex);
|
mutexes.push_back(mutex);
|
||||||
}
|
}
|
||||||
for (unsigned i = 0; i < mutex.size(); ++i) {
|
non_empty = !mutex.empty();
|
||||||
ps.erase(mutex[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return l_true;
|
return l_true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::get_reachable(literal p, literal_set const& goal, literal_set& reachable) {
|
void solver::get_reachable(literal p, literal_set const& goal, literal_set& reachable) {
|
||||||
literal_set seen;
|
m_seen[1].reset();
|
||||||
literal_vector todo;
|
m_todo.reset();
|
||||||
todo.push_back(p);
|
m_todo.push_back(p);
|
||||||
while (!todo.empty()) {
|
while (!m_todo.empty()) {
|
||||||
p = todo.back();
|
p = m_todo.back();
|
||||||
todo.pop_back();
|
m_todo.pop_back();
|
||||||
if (seen.contains(p)) {
|
if (m_seen[1].contains(p)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
seen.insert(p);
|
m_seen[1].insert(p);
|
||||||
literal np = ~p;
|
literal np = ~p;
|
||||||
if (goal.contains(np)) {
|
if (goal.contains(np)) {
|
||||||
reachable.insert(np);
|
reachable.insert(np);
|
||||||
}
|
}
|
||||||
todo.append(m_binary_clause_graph[np.index()]);
|
m_todo.append(m_binary_clause_graph[np.index()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3129,6 +3135,7 @@ namespace sat {
|
||||||
if (is_sat != l_true) {
|
if (is_sat != l_true) {
|
||||||
return is_sat;
|
return is_sat;
|
||||||
}
|
}
|
||||||
|
model mdl = get_model();
|
||||||
for (unsigned i = 0; i < vars.size(); ++i) {
|
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||||
bool_var v = vars[i];
|
bool_var v = vars[i];
|
||||||
switch (get_model()[v]) {
|
switch (get_model()[v]) {
|
||||||
|
@ -3137,7 +3144,9 @@ namespace sat {
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return get_consequences(asms, lits, conseq);
|
is_sat = get_consequences(asms, lits, conseq);
|
||||||
|
set_model(mdl);
|
||||||
|
return is_sat;
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool solver::get_consequences(literal_vector const& asms, literal_vector const& lits, vector<literal_vector>& conseq) {
|
lbool solver::get_consequences(literal_vector const& asms, literal_vector const& lits, vector<literal_vector>& conseq) {
|
||||||
|
@ -3158,13 +3167,11 @@ namespace sat {
|
||||||
while (!unfixed.empty()) {
|
while (!unfixed.empty()) {
|
||||||
checkpoint();
|
checkpoint();
|
||||||
literal_set::iterator it = unfixed.begin(), end = unfixed.end();
|
literal_set::iterator it = unfixed.begin(), end = unfixed.end();
|
||||||
unsigned chunk_size = 100;
|
for (; it != end; ++it) {
|
||||||
for (; it != end && chunk_size > 0; ++it) {
|
|
||||||
literal lit = *it;
|
literal lit = *it;
|
||||||
if (value(lit) != l_undef) {
|
if (value(lit) != l_undef) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
--chunk_size;
|
|
||||||
push();
|
push();
|
||||||
assign(~lit, justification());
|
assign(~lit, justification());
|
||||||
propagate(false);
|
propagate(false);
|
||||||
|
|
|
@ -447,6 +447,9 @@ namespace sat {
|
||||||
|
|
||||||
u_map<index_set> m_antecedents;
|
u_map<index_set> m_antecedents;
|
||||||
vector<literal_vector> m_binary_clause_graph;
|
vector<literal_vector> m_binary_clause_graph;
|
||||||
|
literal_set m_reachable[2];
|
||||||
|
literal_set m_seen[2];
|
||||||
|
literal_vector m_todo;
|
||||||
|
|
||||||
void extract_assumptions(literal lit, index_set& s);
|
void extract_assumptions(literal lit, index_set& s);
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ Notes:
|
||||||
#include "filter_model_converter.h"
|
#include "filter_model_converter.h"
|
||||||
#include "bit_blaster_model_converter.h"
|
#include "bit_blaster_model_converter.h"
|
||||||
#include "ast_translation.h"
|
#include "ast_translation.h"
|
||||||
|
#include "ast_util.h"
|
||||||
|
|
||||||
// incremental SAT solver.
|
// incremental SAT solver.
|
||||||
class inc_sat_solver : public solver {
|
class inc_sat_solver : public solver {
|
||||||
|
@ -232,6 +233,41 @@ public:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual lbool get_consequences_core(expr_ref_vector const& assumptions, expr_ref_vector const& vars, expr_ref_vector& conseq) {
|
||||||
|
TRACE("sat", tout << assumptions << "\n" << vars << "\n";);
|
||||||
|
sat::literal_vector asms;
|
||||||
|
sat::bool_var_vector bvars;
|
||||||
|
vector<sat::literal_vector> lconseq;
|
||||||
|
dep2asm_t dep2asm;
|
||||||
|
m_solver.pop_to_base_level();
|
||||||
|
lbool r = internalize_formulas();
|
||||||
|
if (r != l_true) return r;
|
||||||
|
r = internalize_assumptions(assumptions.size(), assumptions.c_ptr(), dep2asm);
|
||||||
|
if (r != l_true) return r;
|
||||||
|
r = internalize_vars(vars, bvars);
|
||||||
|
|
||||||
|
r = m_solver.get_consequences(m_asms, bvars, lconseq);
|
||||||
|
if (r != l_true) return r;
|
||||||
|
|
||||||
|
// build map from bound variables to
|
||||||
|
// the consequences that cover them.
|
||||||
|
u_map<unsigned> bool_var2conseq;
|
||||||
|
for (unsigned i = 0; i < lconseq.size(); ++i) {
|
||||||
|
TRACE("sat", tout << lconseq[i] << "\n";);
|
||||||
|
bool_var2conseq.insert(lconseq[i][0].var(), i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract original fixed variables
|
||||||
|
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||||
|
expr_ref cons(m);
|
||||||
|
if (extract_fixed_variable(dep2asm, vars[i], bool_var2conseq, lconseq, cons)) {
|
||||||
|
conseq.push_back(cons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
virtual lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes) {
|
virtual lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes) {
|
||||||
sat::literal_vector ls;
|
sat::literal_vector ls;
|
||||||
u_map<expr*> lit2var;
|
u_map<expr*> lit2var;
|
||||||
|
@ -359,6 +395,106 @@ private:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lbool internalize_vars(expr_ref_vector const& vars, sat::bool_var_vector& bvars) {
|
||||||
|
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||||
|
internalize_var(vars[i], bvars);
|
||||||
|
}
|
||||||
|
return l_true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool internalize_var(expr* v, sat::bool_var_vector& bvars) {
|
||||||
|
obj_map<func_decl, expr*> const& const2bits = m_bb_rewriter->const2bits();
|
||||||
|
expr* bv;
|
||||||
|
bv_util bvutil(m);
|
||||||
|
bool internalized = false;
|
||||||
|
if (is_uninterp_const(v) && m.is_bool(v)) {
|
||||||
|
sat::bool_var b = m_map.to_bool_var(v);
|
||||||
|
|
||||||
|
if (b != sat::null_bool_var) {
|
||||||
|
bvars.push_back(b);
|
||||||
|
internalized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (is_uninterp_const(v) && const2bits.find(to_app(v)->get_decl(), bv)) {
|
||||||
|
SASSERT(bvutil.is_bv(bv));
|
||||||
|
app* abv = to_app(bv);
|
||||||
|
internalized = true;
|
||||||
|
unsigned sz = abv->get_num_args();
|
||||||
|
for (unsigned j = 0; j < sz; ++j) {
|
||||||
|
SASSERT(is_uninterp_const(abv->get_arg(j)));
|
||||||
|
sat::bool_var b = m_map.to_bool_var(abv->get_arg(j));
|
||||||
|
if (b == sat::null_bool_var) {
|
||||||
|
internalized = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bvars.push_back(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CTRACE("sat", internalized, tout << "var: "; for (unsigned j = 0; j < sz; ++j) tout << bvars[bvars.size()-sz+j] << " "; tout << "\n";);
|
||||||
|
}
|
||||||
|
else if (is_uninterp_const(v) && bvutil.is_bv(v)) {
|
||||||
|
// variable does not occur in assertions, so is unconstrained.
|
||||||
|
}
|
||||||
|
CTRACE("sat", !internalized, tout << "unhandled variable " << mk_pp(v, m) << "\n";);
|
||||||
|
return internalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool extract_fixed_variable(dep2asm_t& dep2asm, expr* v, u_map<unsigned> const& bool_var2conseq, vector<sat::literal_vector> const& lconseq, expr_ref& conseq) {
|
||||||
|
u_map<expr*> asm2dep;
|
||||||
|
extract_asm2dep(dep2asm, asm2dep);
|
||||||
|
|
||||||
|
sat::bool_var_vector bvars;
|
||||||
|
if (!internalize_var(v, bvars)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sat::literal_vector value;
|
||||||
|
sat::literal_set premises;
|
||||||
|
for (unsigned i = 0; i < bvars.size(); ++i) {
|
||||||
|
unsigned index;
|
||||||
|
if (bool_var2conseq.find(bvars[i], index)) {
|
||||||
|
value.push_back(lconseq[index][0]);
|
||||||
|
for (unsigned j = 1; j < lconseq[index].size(); ++j) {
|
||||||
|
premises.insert(lconseq[index][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TRACE("sat", tout << "variable is not bound " << mk_pp(v, m) << "\n";);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expr_ref val(m);
|
||||||
|
expr_ref_vector conj(m);
|
||||||
|
internalize_value(value, v, val);
|
||||||
|
while (!premises.empty()) {
|
||||||
|
expr* e = 0;
|
||||||
|
VERIFY(asm2dep.find(premises.pop().index(), e));
|
||||||
|
conj.push_back(e);
|
||||||
|
}
|
||||||
|
conseq = m.mk_implies(mk_and(conj), val);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void internalize_value(sat::literal_vector const& value, expr* v, expr_ref& val) {
|
||||||
|
bv_util bvutil(m);
|
||||||
|
if (is_uninterp_const(v) && m.is_bool(v)) {
|
||||||
|
SASSERT(value.size() == 1);
|
||||||
|
val = value[0].sign() ? m.mk_not(v) : v;
|
||||||
|
}
|
||||||
|
else if (is_uninterp_const(v) && bvutil.is_bv_sort(m.get_sort(v))) {
|
||||||
|
SASSERT(value.size() == bvutil.get_bv_size(v));
|
||||||
|
rational r(0);
|
||||||
|
for (unsigned i = 0; i < value.size(); ++i) {
|
||||||
|
if (!value[i].sign()) {
|
||||||
|
r += rational(2).expt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = m.mk_eq(v, bvutil.mk_numeral(r, value.size()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lbool internalize_formulas() {
|
lbool internalize_formulas() {
|
||||||
if (m_fmls_head == m_fmls.size()) {
|
if (m_fmls_head == m_fmls.size()) {
|
||||||
return l_true;
|
return l_true;
|
||||||
|
@ -395,13 +531,17 @@ private:
|
||||||
SASSERT(dep2asm.size() == m_asms.size());
|
SASSERT(dep2asm.size() == m_asms.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void extract_core(dep2asm_t& dep2asm) {
|
void extract_asm2dep(dep2asm_t const& dep2asm, u_map<expr*>& asm2dep) {
|
||||||
u_map<expr*> asm2dep;
|
|
||||||
dep2asm_t::iterator it = dep2asm.begin(), end = dep2asm.end();
|
dep2asm_t::iterator it = dep2asm.begin(), end = dep2asm.end();
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
expr* e = it->m_key;
|
expr* e = it->m_key;
|
||||||
asm2dep.insert(it->m_value.index(), e);
|
asm2dep.insert(it->m_value.index(), e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void extract_core(dep2asm_t& dep2asm) {
|
||||||
|
u_map<expr*> asm2dep;
|
||||||
|
extract_asm2dep(dep2asm, asm2dep);
|
||||||
sat::literal_vector const& core = m_solver.get_core();
|
sat::literal_vector const& core = m_solver.get_core();
|
||||||
TRACE("sat",
|
TRACE("sat",
|
||||||
dep2asm_t::iterator it2 = dep2asm.begin();
|
dep2asm_t::iterator it2 = dep2asm.begin();
|
||||||
|
@ -440,7 +580,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void extract_model() {
|
void extract_model() {
|
||||||
TRACE("sat", tout << "retrieve model\n";);
|
TRACE("sat", tout << "retrieve model " << (m_solver.model_is_current()?"present":"absent") << "\n";);
|
||||||
if (!m_solver.model_is_current()) {
|
if (!m_solver.model_is_current()) {
|
||||||
m_model = 0;
|
m_model = 0;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -166,7 +166,8 @@ namespace sat {
|
||||||
if (contains(v)) {
|
if (contains(v)) {
|
||||||
m_in_set[v] = false;
|
m_in_set[v] = false;
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (i = 0; i < m_set.size() && m_set[i] != v; ++i);
|
for (i = 0; i < m_set.size() && m_set[i] != v; ++i)
|
||||||
|
;
|
||||||
SASSERT(i < m_set.size());
|
SASSERT(i < m_set.size());
|
||||||
m_set[i] = m_set.back();
|
m_set[i] = m_set.back();
|
||||||
m_set.pop_back();
|
m_set.pop_back();
|
||||||
|
@ -239,6 +240,18 @@ namespace sat {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
literal_set& operator=(literal_vector const& v) {
|
||||||
|
reset();
|
||||||
|
for (unsigned i = 0; i < v.size(); ++i) insert(v[i]);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
literal_set& operator=(literal_set const& other) {
|
||||||
|
if (this != &other) {
|
||||||
|
m_set = other.m_set;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
void insert(literal l) { m_set.insert(l.index()); }
|
void insert(literal l) { m_set.insert(l.index()); }
|
||||||
void remove(literal l) { m_set.remove(l.index()); }
|
void remove(literal l) { m_set.remove(l.index()); }
|
||||||
literal pop() { return to_literal(m_set.erase()); }
|
literal pop() { return to_literal(m_set.erase()); }
|
||||||
|
|
|
@ -589,10 +589,8 @@ namespace smt {
|
||||||
m_dep_manager.reset();
|
m_dep_manager.reset();
|
||||||
bool propagated = false;
|
bool propagated = false;
|
||||||
context & ctx = get_context();
|
context & ctx = get_context();
|
||||||
svector<theory_var>::const_iterator it = m_nl_monomials.begin();
|
for (unsigned i = 0; i < m_nl_monomials.size(); i++) {
|
||||||
svector<theory_var>::const_iterator end = m_nl_monomials.end();
|
theory_var v = m_nl_monomials[i];
|
||||||
for (; it != end; ++it) {
|
|
||||||
theory_var v = *it;
|
|
||||||
expr * m = var2expr(v);
|
expr * m = var2expr(v);
|
||||||
if (!ctx.is_relevant(m))
|
if (!ctx.is_relevant(m))
|
||||||
continue;
|
continue;
|
||||||
|
@ -706,10 +704,8 @@ namespace smt {
|
||||||
bool bounded = false;
|
bool bounded = false;
|
||||||
unsigned n = 0;
|
unsigned n = 0;
|
||||||
numeral range;
|
numeral range;
|
||||||
svector<theory_var>::const_iterator it = m_nl_monomials.begin();
|
for (unsigned i = 0; i < m_nl_monomials.size(); i++) {
|
||||||
svector<theory_var>::const_iterator end = m_nl_monomials.end();
|
theory_var v = m_nl_monomials[i];
|
||||||
for (; it != end; ++it) {
|
|
||||||
theory_var v = *it;
|
|
||||||
if (is_real(v))
|
if (is_real(v))
|
||||||
continue;
|
continue;
|
||||||
bool computed_epsilon = false;
|
bool computed_epsilon = false;
|
||||||
|
@ -965,10 +961,19 @@ namespace smt {
|
||||||
bool theory_arith<Ext>::propagate_linear_monomials() {
|
bool theory_arith<Ext>::propagate_linear_monomials() {
|
||||||
TRACE("non_linear", tout << "propagating linear monomials...\n";);
|
TRACE("non_linear", tout << "propagating linear monomials...\n";);
|
||||||
bool p = false;
|
bool p = false;
|
||||||
svector<theory_var>::const_iterator it = m_nl_monomials.begin();
|
// CMW: m_nl_monomials is sometimes modified while executing
|
||||||
svector<theory_var>::const_iterator end = m_nl_monomials.end();
|
// propagate_linear_monomial(...), invalidating the iterator `it'.
|
||||||
for (; it != end; ++it) {
|
// (Via the relevancy propagation that internalizes a new axiom
|
||||||
theory_var v = *it;
|
// in mk_div_axiom and possibly others.) I'm replacing the iterator
|
||||||
|
// with an index `i'.
|
||||||
|
|
||||||
|
// Was previously:
|
||||||
|
// svector<theory_var>::const_iterator it = m_nl_monomials.begin();
|
||||||
|
// svector<theory_var>::const_iterator end = m_nl_monomials.end();
|
||||||
|
// for (; it != end; ++it) {
|
||||||
|
// theory_var v = *it;
|
||||||
|
for (unsigned i = 0; i < m_nl_monomials.size(); i++) {
|
||||||
|
theory_var v = m_nl_monomials[i];
|
||||||
if (propagate_linear_monomial(v))
|
if (propagate_linear_monomial(v))
|
||||||
p = true;
|
p = true;
|
||||||
}
|
}
|
||||||
|
@ -2331,10 +2336,8 @@ namespace smt {
|
||||||
bool theory_arith<Ext>::max_min_nl_vars() {
|
bool theory_arith<Ext>::max_min_nl_vars() {
|
||||||
var_set already_found;
|
var_set already_found;
|
||||||
svector<theory_var> vars;
|
svector<theory_var> vars;
|
||||||
svector<theory_var>::const_iterator it = m_nl_monomials.begin();
|
for (unsigned i = 0; i < m_nl_monomials.size(); i++) {
|
||||||
svector<theory_var>::const_iterator end = m_nl_monomials.end();
|
theory_var v = m_nl_monomials[i];
|
||||||
for (; it != end; ++it) {
|
|
||||||
theory_var v = *it;
|
|
||||||
mark_var(v, vars, already_found);
|
mark_var(v, vars, already_found);
|
||||||
expr * n = var2expr(v);
|
expr * n = var2expr(v);
|
||||||
SASSERT(is_pure_monomial(n));
|
SASSERT(is_pure_monomial(n));
|
||||||
|
|
|
@ -21,6 +21,7 @@ Revision History:
|
||||||
#include"theory_fpa.h"
|
#include"theory_fpa.h"
|
||||||
#include"theory_bv.h"
|
#include"theory_bv.h"
|
||||||
#include"smt_model_generator.h"
|
#include"smt_model_generator.h"
|
||||||
|
#include"bv2fpa_converter.h"
|
||||||
|
|
||||||
namespace smt {
|
namespace smt {
|
||||||
|
|
||||||
|
@ -712,20 +713,6 @@ namespace smt {
|
||||||
ast_manager & m = get_manager();
|
ast_manager & m = get_manager();
|
||||||
m_factory = alloc(fpa_value_factory, m, get_family_id());
|
m_factory = alloc(fpa_value_factory, m, get_family_id());
|
||||||
mg.register_factory(m_factory);
|
mg.register_factory(m_factory);
|
||||||
|
|
||||||
fpa2bv_converter::uf2bvuf_t const & uf2bvuf = m_converter.get_uf2bvuf();
|
|
||||||
for (fpa2bv_converter::uf2bvuf_t::iterator it = uf2bvuf.begin();
|
|
||||||
it != uf2bvuf.end();
|
|
||||||
it++) {
|
|
||||||
mg.hide(it->m_value);
|
|
||||||
}
|
|
||||||
fpa2bv_converter::special_t const & specials = m_converter.get_min_max_specials();
|
|
||||||
for (fpa2bv_converter::special_t::iterator it = specials.begin();
|
|
||||||
it != specials.end();
|
|
||||||
it++) {
|
|
||||||
mg.hide(it->m_value.first->get_decl());
|
|
||||||
mg.hide(it->m_value.second->get_decl());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model_value_proc * theory_fpa::mk_value(enode * n, model_generator & mg) {
|
model_value_proc * theory_fpa::mk_value(enode * n, model_generator & mg) {
|
||||||
|
@ -811,7 +798,33 @@ namespace smt {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void theory_fpa::finalize_model(model_generator & mg) {}
|
void theory_fpa::finalize_model(model_generator & mg) {
|
||||||
|
ast_manager & m = get_manager();
|
||||||
|
proto_model & mdl = mg.get_model();
|
||||||
|
proto_model new_model(m);
|
||||||
|
|
||||||
|
bv2fpa_converter bv2fp(m, m_converter);
|
||||||
|
|
||||||
|
obj_hashtable<func_decl> seen;
|
||||||
|
bv2fp.convert_min_max_specials(&mdl, &new_model, seen);
|
||||||
|
bv2fp.convert_uf2bvuf(&mdl, &new_model, seen);
|
||||||
|
|
||||||
|
for (obj_hashtable<func_decl>::iterator it = seen.begin();
|
||||||
|
it != seen.end();
|
||||||
|
it++)
|
||||||
|
mdl.unregister_decl(*it);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < new_model.get_num_constants(); i++) {
|
||||||
|
func_decl * f = new_model.get_constant(i);
|
||||||
|
mdl.register_decl(f, new_model.get_const_interp(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < new_model.get_num_functions(); i++) {
|
||||||
|
func_decl * f = new_model.get_function(i);
|
||||||
|
func_interp * fi = new_model.get_func_interp(f)->copy();
|
||||||
|
mdl.register_decl(f, fi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void theory_fpa::display(std::ostream & out) const
|
void theory_fpa::display(std::ostream & out) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -519,7 +519,7 @@ namespace smt {
|
||||||
c->m_compilation_threshold = th;
|
c->m_compilation_threshold = th;
|
||||||
IF_VERBOSE(2, verbose_stream() << "(smt.pb setting compilation threhshold to " << th << ")\n";);
|
IF_VERBOSE(2, verbose_stream() << "(smt.pb setting compilation threhshold to " << th << ")\n";);
|
||||||
TRACE("pb", tout << "compilation threshold: " << th << "\n";);
|
TRACE("pb", tout << "compilation threshold: " << th << "\n";);
|
||||||
compile_ineq(*c);
|
//compile_ineq(*c);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
c->m_compilation_threshold = UINT_MAX;
|
c->m_compilation_threshold = UINT_MAX;
|
||||||
|
|
|
@ -29,6 +29,7 @@ Revision History:
|
||||||
#include "extension_model_converter.h"
|
#include "extension_model_converter.h"
|
||||||
#include "var_subst.h"
|
#include "var_subst.h"
|
||||||
#include "ast_util.h"
|
#include "ast_util.h"
|
||||||
|
#include "fd_rewriter.h"
|
||||||
|
|
||||||
|
|
||||||
class dt2bv_tactic : public tactic {
|
class dt2bv_tactic : public tactic {
|
||||||
|
@ -39,172 +40,7 @@ class dt2bv_tactic : public tactic {
|
||||||
bv_util m_bv;
|
bv_util m_bv;
|
||||||
obj_hashtable<sort> m_fd_sorts;
|
obj_hashtable<sort> m_fd_sorts;
|
||||||
obj_hashtable<sort> m_non_fd_sorts;
|
obj_hashtable<sort> m_non_fd_sorts;
|
||||||
expr_ref_vector m_bounds;
|
obj_map<func_decl, func_decl*>* m_translate;
|
||||||
ref<extension_model_converter> m_ext;
|
|
||||||
ref<filter_model_converter> m_filter;
|
|
||||||
unsigned m_num_translated;
|
|
||||||
|
|
||||||
struct rw_cfg : public default_rewriter_cfg {
|
|
||||||
dt2bv_tactic& m_t;
|
|
||||||
ast_manager& m;
|
|
||||||
params_ref m_params;
|
|
||||||
obj_map<expr, expr*> m_cache;
|
|
||||||
expr_ref_vector m_trail;
|
|
||||||
|
|
||||||
rw_cfg(dt2bv_tactic& t, ast_manager & m, params_ref const & p) :
|
|
||||||
m_t(t),
|
|
||||||
m(m),
|
|
||||||
m_params(p),
|
|
||||||
m_trail(m)
|
|
||||||
{}
|
|
||||||
|
|
||||||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
|
||||||
expr_ref a0(m), a1(m);
|
|
||||||
expr_ref_vector _args(m);
|
|
||||||
if (m.is_eq(f) && reduce_arg(args[0], a0) && reduce_arg(args[1], a1)) {
|
|
||||||
result = m.mk_eq(a0, a1);
|
|
||||||
return BR_DONE;
|
|
||||||
}
|
|
||||||
else if (m.is_distinct(f) && reduce_args(num, args, _args)) {
|
|
||||||
result = m.mk_distinct(_args.size(), _args.c_ptr());
|
|
||||||
return BR_DONE;
|
|
||||||
}
|
|
||||||
else if (m_t.m_dt.is_recognizer(f) && reduce_arg(args[0], a0)) {
|
|
||||||
unsigned idx = m_t.m_dt.get_recognizer_constructor_idx(f);
|
|
||||||
a1 = m_t.m_bv.mk_numeral(rational(idx), get_sort(a0));
|
|
||||||
result = m.mk_eq(a0, a1);
|
|
||||||
return BR_DONE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return BR_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool reduce_args(unsigned sz, expr*const* as, expr_ref_vector& result) {
|
|
||||||
expr_ref tmp(m);
|
|
||||||
for (unsigned i = 0; i < sz; ++i) {
|
|
||||||
if (!reduce_arg(as[i], tmp)) return false;
|
|
||||||
result.push_back(tmp);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool reduce_arg(expr* a, expr_ref& result) {
|
|
||||||
expr* b;
|
|
||||||
if (m_cache.find(a, b)) {
|
|
||||||
result = b;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
sort* s = get_sort(a);
|
|
||||||
if (!m_t.m_fd_sorts.contains(s)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
unsigned bv_size = get_bv_size(s);
|
|
||||||
|
|
||||||
if (is_var(a)) {
|
|
||||||
result = m.mk_var(to_var(a)->get_idx(), m_t.m_bv.mk_sort(bv_size));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
SASSERT(is_app(a));
|
|
||||||
func_decl* f = to_app(a)->get_decl();
|
|
||||||
if (m_t.m_dt.is_constructor(f)) {
|
|
||||||
unsigned idx = m_t.m_dt.get_constructor_idx(f);
|
|
||||||
result = m_t.m_bv.mk_numeral(idx, bv_size);
|
|
||||||
}
|
|
||||||
else if (is_uninterp_const(a)) {
|
|
||||||
// create a fresh variable, add bounds constraints for it.
|
|
||||||
unsigned nc = m_t.m_dt.get_datatype_num_constructors(s);
|
|
||||||
result = m.mk_fresh_const(f->get_name().str().c_str(), m_t.m_bv.mk_sort(bv_size));
|
|
||||||
if (!is_power_of_two(nc)) {
|
|
||||||
m_t.m_bounds.push_back(m_t.m_bv.mk_ule(result, m_t.m_bv.mk_numeral(nc, bv_size)));
|
|
||||||
}
|
|
||||||
expr_ref f_def(m);
|
|
||||||
ptr_vector<func_decl> const& cs = *m_t.m_dt.get_datatype_constructors(s);
|
|
||||||
f_def = m.mk_const(cs[nc-1]);
|
|
||||||
for (unsigned i = nc - 1; i > 0; ) {
|
|
||||||
--i;
|
|
||||||
f_def = m.mk_ite(m.mk_eq(result, m_t.m_bv.mk_numeral(i,bv_size)), m.mk_const(cs[i]), f_def);
|
|
||||||
}
|
|
||||||
// update model converters.
|
|
||||||
m_t.m_ext->insert(f, f_def);
|
|
||||||
m_t.m_filter->insert(to_app(result)->get_decl());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_cache.insert(a, result);
|
|
||||||
++m_t.m_num_translated;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr_buffer<sort> m_sorts;
|
|
||||||
|
|
||||||
bool reduce_quantifier(
|
|
||||||
quantifier * q,
|
|
||||||
expr * old_body,
|
|
||||||
expr * const * new_patterns,
|
|
||||||
expr * const * new_no_patterns,
|
|
||||||
expr_ref & result,
|
|
||||||
proof_ref & result_pr) {
|
|
||||||
m_sorts.reset();
|
|
||||||
expr_ref_vector bounds(m);
|
|
||||||
bool found = false;
|
|
||||||
for (unsigned i = 0; i < q->get_num_decls(); ++i) {
|
|
||||||
sort* s = q->get_decl_sort(i);
|
|
||||||
if (m_t.m_fd_sorts.contains(s)) {
|
|
||||||
unsigned bv_size = get_bv_size(s);
|
|
||||||
m_sorts.push_back(m_t.m_bv.mk_sort(bv_size));
|
|
||||||
unsigned nc = m_t.m_dt.get_datatype_num_constructors(s);
|
|
||||||
if (!is_power_of_two(nc)) {
|
|
||||||
bounds.push_back(m_t.m_bv.mk_ule(m.mk_var(q->get_num_decls()-i-1, m_sorts[i]), m_t.m_bv.mk_numeral(nc, bv_size)));
|
|
||||||
}
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_sorts.push_back(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
expr_ref new_body_ref(old_body, m), tmp(m);
|
|
||||||
if (!bounds.empty()) {
|
|
||||||
if (q->is_forall()) {
|
|
||||||
new_body_ref = m.mk_implies(mk_and(bounds), new_body_ref);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bounds.push_back(new_body_ref);
|
|
||||||
new_body_ref = mk_and(bounds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = m.mk_quantifier(q->is_forall(), q->get_num_decls(), m_sorts.c_ptr(), q->get_decl_names(), new_body_ref,
|
|
||||||
q->get_weight(), q->get_qid(), q->get_skid(),
|
|
||||||
q->get_num_patterns(), new_patterns,
|
|
||||||
q->get_num_no_patterns(), new_no_patterns);
|
|
||||||
result_pr = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned get_bv_size(sort* s) {
|
|
||||||
unsigned nc = m_t.m_dt.get_datatype_num_constructors(s);
|
|
||||||
unsigned bv_size = 1;
|
|
||||||
while ((unsigned)(1 << bv_size) < nc) {
|
|
||||||
++bv_size;
|
|
||||||
}
|
|
||||||
return bv_size;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct rw : public rewriter_tpl<rw_cfg> {
|
|
||||||
rw_cfg m_cfg;
|
|
||||||
|
|
||||||
rw(dt2bv_tactic& t, ast_manager & m, params_ref const & p) :
|
|
||||||
rewriter_tpl<rw_cfg>(m, m.proofs_enabled(), m_cfg),
|
|
||||||
m_cfg(t, m, p) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool is_fd(expr* a) { return is_fd(get_sort(a)); }
|
bool is_fd(expr* a) { return is_fd(get_sort(a)); }
|
||||||
|
@ -251,13 +87,23 @@ class dt2bv_tactic : public tactic {
|
||||||
void operator()(quantifier* q) {}
|
void operator()(quantifier* q) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sort_pred : public i_sort_pred {
|
||||||
|
dt2bv_tactic& m_t;
|
||||||
|
sort_pred(dt2bv_tactic& t): m_t(t) {}
|
||||||
|
virtual ~sort_pred() {}
|
||||||
|
virtual bool operator()(sort* s) {
|
||||||
|
return m_t.m_fd_sorts.contains(s);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
sort_pred m_is_fd;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
dt2bv_tactic(ast_manager& m, params_ref const& p):
|
dt2bv_tactic(ast_manager& m, params_ref const& p, obj_map<func_decl, func_decl*>* tr):
|
||||||
m(m), m_params(p), m_dt(m), m_bv(m), m_bounds(m) {}
|
m(m), m_params(p), m_dt(m), m_bv(m), m_translate(tr), m_is_fd(*this) {}
|
||||||
|
|
||||||
virtual tactic * translate(ast_manager & m) {
|
virtual tactic * translate(ast_manager & m) {
|
||||||
return alloc(dt2bv_tactic, m, m_params);
|
return alloc(dt2bv_tactic, m, m_params, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void updt_params(params_ref const & p) {
|
virtual void updt_params(params_ref const & p) {
|
||||||
|
@ -285,26 +131,43 @@ public:
|
||||||
m_fd_sorts.remove(*it);
|
m_fd_sorts.remove(*it);
|
||||||
}
|
}
|
||||||
if (!m_fd_sorts.empty()) {
|
if (!m_fd_sorts.empty()) {
|
||||||
m_bounds.reset();
|
ref<extension_model_converter> ext = alloc(extension_model_converter, m);
|
||||||
m_num_translated = 0;
|
ref<filter_model_converter> filter = alloc(filter_model_converter, m);
|
||||||
m_ext = alloc(extension_model_converter, m);
|
fd_rewriter rw(m, m_params);
|
||||||
m_filter = alloc(filter_model_converter, m);
|
rw.set_is_fd(&m_is_fd);
|
||||||
scoped_ptr<rw> r = alloc(rw, *this, m, m_params);
|
|
||||||
expr_ref new_curr(m);
|
expr_ref new_curr(m);
|
||||||
proof_ref new_pr(m);
|
proof_ref new_pr(m);
|
||||||
for (unsigned idx = 0; idx < size; idx++) {
|
for (unsigned idx = 0; idx < size; idx++) {
|
||||||
(*r)(g->form(idx), new_curr, new_pr);
|
rw(g->form(idx), new_curr, new_pr);
|
||||||
if (produce_proofs) {
|
if (produce_proofs) {
|
||||||
proof * pr = g->pr(idx);
|
proof * pr = g->pr(idx);
|
||||||
new_pr = m.mk_modus_ponens(pr, new_pr);
|
new_pr = m.mk_modus_ponens(pr, new_pr);
|
||||||
}
|
}
|
||||||
g->update(idx, new_curr, new_pr, g->dep(idx));
|
g->update(idx, new_curr, new_pr, g->dep(idx));
|
||||||
}
|
}
|
||||||
for (unsigned i = 0; i < m_bounds.size(); ++i) {
|
expr_ref_vector bounds(m);
|
||||||
g->assert_expr(m_bounds[i].get());
|
rw.flush_side_constraints(bounds);
|
||||||
|
for (unsigned i = 0; i < bounds.size(); ++i) {
|
||||||
|
g->assert_expr(bounds[i].get());
|
||||||
}
|
}
|
||||||
mc = concat(m_filter.get(), m_ext.get());
|
{
|
||||||
report_tactic_progress(":fd-num-translated", m_num_translated);
|
obj_map<func_decl, func_decl*>::iterator it = rw.enum2bv().begin(), end = rw.enum2bv().end();
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
filter->insert(it->m_value);
|
||||||
|
if (m_translate) {
|
||||||
|
m_translate->insert(it->m_key, it->m_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
obj_map<func_decl, expr*>::iterator it = rw.enum2def().begin(), end = rw.enum2def().end();
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
ext->insert(it->m_key, it->m_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mc = concat(filter.get(), ext.get());
|
||||||
|
report_tactic_progress(":fd-num-translated", rw.num_translated());
|
||||||
}
|
}
|
||||||
g->inc_depth();
|
g->inc_depth();
|
||||||
result.push_back(g.get());
|
result.push_back(g.get());
|
||||||
|
@ -315,11 +178,10 @@ public:
|
||||||
virtual void cleanup() {
|
virtual void cleanup() {
|
||||||
m_fd_sorts.reset();
|
m_fd_sorts.reset();
|
||||||
m_non_fd_sorts.reset();
|
m_non_fd_sorts.reset();
|
||||||
m_bounds.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
tactic * mk_dt2bv_tactic(ast_manager & m, params_ref const & p) {
|
tactic * mk_dt2bv_tactic(ast_manager & m, params_ref const & p, obj_map<func_decl, func_decl*>* tr) {
|
||||||
return alloc(dt2bv_tactic, m, p);
|
return alloc(dt2bv_tactic, m, p, tr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,11 @@ Revision History:
|
||||||
#define DT2BV_TACTIC_H_
|
#define DT2BV_TACTIC_H_
|
||||||
|
|
||||||
#include"params.h"
|
#include"params.h"
|
||||||
|
#include"obj_hashtable.h"
|
||||||
class ast_manager;
|
class ast_manager;
|
||||||
class tactic;
|
class tactic;
|
||||||
|
|
||||||
tactic * mk_dt2bv_tactic(ast_manager & m, params_ref const & p = params_ref());
|
tactic * mk_dt2bv_tactic(ast_manager & m, params_ref const & p = params_ref(), obj_map<func_decl, func_decl*>* tr = 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ADD_TACTIC("dt2bv", "eliminate finite domain data-types. Replace by bit-vectors.", "mk_dt2bv_tactic(m, p)")
|
ADD_TACTIC("dt2bv", "eliminate finite domain data-types. Replace by bit-vectors.", "mk_dt2bv_tactic(m, p)")
|
||||||
|
|
|
@ -22,448 +22,50 @@ Notes:
|
||||||
|
|
||||||
void fpa2bv_model_converter::display(std::ostream & out) {
|
void fpa2bv_model_converter::display(std::ostream & out) {
|
||||||
out << "(fpa2bv-model-converter";
|
out << "(fpa2bv-model-converter";
|
||||||
for (obj_map<func_decl, expr*>::iterator it = m_const2bv.begin();
|
m_bv2fp->display(out);
|
||||||
it != m_const2bv.end();
|
|
||||||
it++) {
|
|
||||||
const symbol & n = it->m_key->get_name();
|
|
||||||
out << "\n (" << n << " ";
|
|
||||||
unsigned indent = n.size() + 4;
|
|
||||||
out << mk_ismt2_pp(it->m_value, m, indent) << ")";
|
|
||||||
}
|
|
||||||
for (obj_map<func_decl, expr*>::iterator it = m_rm_const2bv.begin();
|
|
||||||
it != m_rm_const2bv.end();
|
|
||||||
it++) {
|
|
||||||
const symbol & n = it->m_key->get_name();
|
|
||||||
out << "\n (" << n << " ";
|
|
||||||
unsigned indent = n.size() + 4;
|
|
||||||
out << mk_ismt2_pp(it->m_value, m, indent) << ")";
|
|
||||||
}
|
|
||||||
for (obj_map<func_decl, func_decl*>::iterator it = m_uf2bvuf.begin();
|
|
||||||
it != m_uf2bvuf.end();
|
|
||||||
it++) {
|
|
||||||
const symbol & n = it->m_key->get_name();
|
|
||||||
out << "\n (" << n << " ";
|
|
||||||
unsigned indent = n.size() + 4;
|
|
||||||
out << mk_ismt2_pp(it->m_value, m, indent) << ")";
|
|
||||||
}
|
|
||||||
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = m_specials.begin();
|
|
||||||
it != m_specials.end();
|
|
||||||
it++) {
|
|
||||||
const symbol & n = it->m_key->get_name();
|
|
||||||
out << "\n (" << n << " ";
|
|
||||||
unsigned indent = n.size() + 4;
|
|
||||||
out << mk_ismt2_pp(it->m_value.first, m, indent) << "; " <<
|
|
||||||
mk_ismt2_pp(it->m_value.second, m, indent) << ")";
|
|
||||||
}
|
|
||||||
out << ")";
|
out << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
model_converter * fpa2bv_model_converter::translate(ast_translation & translator) {
|
model_converter * fpa2bv_model_converter::translate(ast_translation & translator) {
|
||||||
fpa2bv_model_converter * res = alloc(fpa2bv_model_converter, translator.to());
|
fpa2bv_model_converter * res = alloc(fpa2bv_model_converter, translator.to());
|
||||||
for (obj_map<func_decl, expr*>::iterator it = m_const2bv.begin();
|
res->m_bv2fp = m_bv2fp->translate(translator);
|
||||||
it != m_const2bv.end();
|
|
||||||
it++)
|
|
||||||
{
|
|
||||||
func_decl * k = translator(it->m_key);
|
|
||||||
expr * v = translator(it->m_value);
|
|
||||||
res->m_const2bv.insert(k, v);
|
|
||||||
translator.to().inc_ref(k);
|
|
||||||
translator.to().inc_ref(v);
|
|
||||||
}
|
|
||||||
for (obj_map<func_decl, expr*>::iterator it = m_rm_const2bv.begin();
|
|
||||||
it != m_rm_const2bv.end();
|
|
||||||
it++)
|
|
||||||
{
|
|
||||||
func_decl * k = translator(it->m_key);
|
|
||||||
expr * v = translator(it->m_value);
|
|
||||||
res->m_rm_const2bv.insert(k, v);
|
|
||||||
translator.to().inc_ref(k);
|
|
||||||
translator.to().inc_ref(v);
|
|
||||||
}
|
|
||||||
for (obj_map<func_decl, func_decl*>::iterator it = m_uf2bvuf.begin();
|
|
||||||
it != m_uf2bvuf.end();
|
|
||||||
it++) {
|
|
||||||
func_decl * k = translator(it->m_key);
|
|
||||||
func_decl * v = translator(it->m_value);
|
|
||||||
res->m_uf2bvuf.insert(k, v);
|
|
||||||
translator.to().inc_ref(k);
|
|
||||||
translator.to().inc_ref(v);
|
|
||||||
}
|
|
||||||
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = m_specials.begin();
|
|
||||||
it != m_specials.end();
|
|
||||||
it++) {
|
|
||||||
func_decl * k = translator(it->m_key);
|
|
||||||
app * v1 = translator(it->m_value.first);
|
|
||||||
app * v2 = translator(it->m_value.second);
|
|
||||||
res->m_specials.insert(k, std::pair<app*, app*>(v1, v2));
|
|
||||||
translator.to().inc_ref(k);
|
|
||||||
translator.to().inc_ref(v1);
|
|
||||||
translator.to().inc_ref(v2);
|
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_ref fpa2bv_model_converter::convert_bv2fp(sort * s, expr * sgn, expr * exp, expr * sig) {
|
void fpa2bv_model_converter::convert(model_core * mc, model * float_mdl) {
|
||||||
unsynch_mpz_manager & mpzm = m_fpa_util.fm().mpz_manager();
|
|
||||||
unsynch_mpq_manager & mpqm = m_fpa_util.fm().mpq_manager();
|
|
||||||
|
|
||||||
expr_ref res(m);
|
|
||||||
mpf fp_val;
|
|
||||||
|
|
||||||
unsigned ebits = m_fpa_util.get_ebits(s);
|
|
||||||
unsigned sbits = m_fpa_util.get_sbits(s);
|
|
||||||
|
|
||||||
unsigned sgn_sz = 1;
|
|
||||||
unsigned exp_sz = ebits;
|
|
||||||
unsigned sig_sz = sbits - 1;
|
|
||||||
|
|
||||||
rational sgn_q(0), sig_q(0), exp_q(0);
|
|
||||||
|
|
||||||
if (sgn) m_bv_util.is_numeral(sgn, sgn_q, sgn_sz);
|
|
||||||
if (exp) m_bv_util.is_numeral(exp, exp_q, exp_sz);
|
|
||||||
if (sig) m_bv_util.is_numeral(sig, sig_q, sig_sz);
|
|
||||||
|
|
||||||
// un-bias exponent
|
|
||||||
rational exp_unbiased_q;
|
|
||||||
exp_unbiased_q = exp_q - m_fpa_util.fm().m_powers2.m1(ebits - 1);
|
|
||||||
|
|
||||||
mpz sig_z; mpf_exp_t exp_z;
|
|
||||||
mpzm.set(sig_z, sig_q.to_mpq().numerator());
|
|
||||||
exp_z = mpzm.get_int64(exp_unbiased_q.to_mpq().numerator());
|
|
||||||
|
|
||||||
m_fpa_util.fm().set(fp_val, ebits, sbits, !mpqm.is_zero(sgn_q.to_mpq()), exp_z, sig_z);
|
|
||||||
|
|
||||||
mpzm.del(sig_z);
|
|
||||||
|
|
||||||
res = m_fpa_util.mk_value(fp_val);
|
|
||||||
|
|
||||||
TRACE("fpa2bv_mc", tout << "[" << mk_ismt2_pp(sgn, m) <<
|
|
||||||
" " << mk_ismt2_pp(exp, m) <<
|
|
||||||
" " << mk_ismt2_pp(sig, m) << "] == " <<
|
|
||||||
mk_ismt2_pp(res, m) << std::endl;);
|
|
||||||
m_fpa_util.fm().del(fp_val);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
expr_ref fpa2bv_model_converter::convert_bv2fp(model * bv_mdl, sort * s, expr * bv) {
|
|
||||||
SASSERT(m_bv_util.is_bv(bv));
|
|
||||||
|
|
||||||
unsigned ebits = m_fpa_util.get_ebits(s);
|
|
||||||
unsigned sbits = m_fpa_util.get_sbits(s);
|
|
||||||
unsigned bv_sz = sbits + ebits;
|
|
||||||
|
|
||||||
expr_ref sgn(m), exp(m), sig(m);
|
|
||||||
sgn = m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv);
|
|
||||||
exp = m_bv_util.mk_extract(bv_sz - 2, sbits - 1, bv);
|
|
||||||
sig = m_bv_util.mk_extract(sbits - 2, 0, bv);
|
|
||||||
|
|
||||||
expr_ref v_sgn(m), v_exp(m), v_sig(m);
|
|
||||||
bv_mdl->eval(sgn, v_sgn);
|
|
||||||
bv_mdl->eval(exp, v_exp);
|
|
||||||
bv_mdl->eval(sig, v_sig);
|
|
||||||
|
|
||||||
return convert_bv2fp(s, v_sgn, v_exp, v_sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
expr_ref fpa2bv_model_converter::convert_bv2rm(expr * bv_rm) {
|
|
||||||
expr_ref res(m);
|
|
||||||
rational bv_val(0);
|
|
||||||
unsigned sz = 0;
|
|
||||||
|
|
||||||
if (m_bv_util.is_numeral(bv_rm, bv_val, sz)) {
|
|
||||||
SASSERT(bv_val.is_uint64());
|
|
||||||
switch (bv_val.get_uint64()) {
|
|
||||||
case BV_RM_TIES_TO_AWAY: res = m_fpa_util.mk_round_nearest_ties_to_away(); break;
|
|
||||||
case BV_RM_TIES_TO_EVEN: res = m_fpa_util.mk_round_nearest_ties_to_even(); break;
|
|
||||||
case BV_RM_TO_NEGATIVE: res = m_fpa_util.mk_round_toward_negative(); break;
|
|
||||||
case BV_RM_TO_POSITIVE: res = m_fpa_util.mk_round_toward_positive(); break;
|
|
||||||
case BV_RM_TO_ZERO:
|
|
||||||
default: res = m_fpa_util.mk_round_toward_zero();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
expr_ref fpa2bv_model_converter::convert_bv2rm(model * bv_mdl, expr * val) {
|
|
||||||
expr_ref res(m);
|
|
||||||
expr_ref eval_v(m);
|
|
||||||
|
|
||||||
if (val && bv_mdl->eval(val, eval_v, true))
|
|
||||||
res = convert_bv2rm(eval_v);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
expr_ref fpa2bv_model_converter::rebuild_floats(model * bv_mdl, sort * s, expr * e) {
|
|
||||||
expr_ref result(m);
|
|
||||||
TRACE("fpa2bv_mc", tout << "rebuild floats in " << mk_ismt2_pp(s, m) << " for " << mk_ismt2_pp(e, m) << std::endl;);
|
|
||||||
|
|
||||||
if (m_fpa_util.is_float(s)) {
|
|
||||||
if (m_fpa_util.is_numeral(e)) {
|
|
||||||
result = e;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SASSERT(m_bv_util.is_bv(e) && m_bv_util.get_bv_size(e) == (m_fpa_util.get_ebits(s) + m_fpa_util.get_sbits(s)));
|
|
||||||
result = convert_bv2fp(bv_mdl, s, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (m_fpa_util.is_rm(s)) {
|
|
||||||
if (m_fpa_util.is_rm_numeral(e)) {
|
|
||||||
result = e;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SASSERT(m_bv_util.is_bv(e) && m_bv_util.get_bv_size(e) == 3);
|
|
||||||
result = convert_bv2rm(bv_mdl, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (is_app(e)) {
|
|
||||||
app * a = to_app(e);
|
|
||||||
expr_ref_vector new_args(m);
|
|
||||||
for (unsigned i = 0; i < a->get_num_args(); i++)
|
|
||||||
new_args.push_back(rebuild_floats(bv_mdl, a->get_decl()->get_domain()[i], a->get_arg(i)));
|
|
||||||
result = m.mk_app(a->get_decl(), new_args.size(), new_args.c_ptr());
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fpa2bv_model_converter::array_model fpa2bv_model_converter::convert_array_func_interp(func_decl * f, func_decl * bv_f, model * bv_mdl) {
|
|
||||||
SASSERT(f->get_arity() == 0);
|
|
||||||
array_util arr_util(m);
|
|
||||||
|
|
||||||
array_model am(m);
|
|
||||||
sort_ref_vector array_domain(m);
|
|
||||||
unsigned arity = f->get_range()->get_num_parameters()-1;
|
|
||||||
|
|
||||||
expr_ref as_arr_mdl(m);
|
|
||||||
as_arr_mdl = bv_mdl->get_const_interp(bv_f);
|
|
||||||
if (as_arr_mdl == 0) return am;
|
|
||||||
TRACE("fpa2bv_mc", tout << "arity=0 func_interp for " << mk_ismt2_pp(f, m) << " := " << mk_ismt2_pp(as_arr_mdl, m) << std::endl;);
|
|
||||||
SASSERT(arr_util.is_as_array(as_arr_mdl));
|
|
||||||
for (unsigned i = 0; i < arity; i++)
|
|
||||||
array_domain.push_back(to_sort(f->get_range()->get_parameter(i).get_ast()));
|
|
||||||
sort * rng = to_sort(f->get_range()->get_parameter(arity).get_ast());
|
|
||||||
|
|
||||||
bv_f = arr_util.get_as_array_func_decl(to_app(as_arr_mdl));
|
|
||||||
|
|
||||||
am.new_float_fd = m.mk_fresh_func_decl(arity, array_domain.c_ptr(), rng);
|
|
||||||
am.new_float_fi = convert_func_interp(am.new_float_fd, bv_f, bv_mdl);
|
|
||||||
am.bv_fd = bv_f;
|
|
||||||
am.result = arr_util.mk_as_array(f->get_range(), am.new_float_fd);
|
|
||||||
return am;
|
|
||||||
}
|
|
||||||
|
|
||||||
func_interp * fpa2bv_model_converter::convert_func_interp(func_decl * f, func_decl * bv_f, model * bv_mdl) {
|
|
||||||
SASSERT(f->get_arity() > 0);
|
|
||||||
func_interp * result = 0;
|
|
||||||
sort * rng = f->get_range();
|
|
||||||
sort * const * dmn = f->get_domain();
|
|
||||||
|
|
||||||
unsigned arity = bv_f->get_arity();
|
|
||||||
func_interp * bv_fi = bv_mdl->get_func_interp(bv_f);
|
|
||||||
|
|
||||||
if (bv_fi != 0) {
|
|
||||||
fpa_rewriter rw(m);
|
|
||||||
expr_ref ai(m);
|
|
||||||
result = alloc(func_interp, m, arity);
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < bv_fi->num_entries(); i++) {
|
|
||||||
func_entry const * bv_fe = bv_fi->get_entry(i);
|
|
||||||
expr * const * bv_args = bv_fe->get_args();
|
|
||||||
expr_ref_buffer new_args(m);
|
|
||||||
|
|
||||||
for (unsigned j = 0; j < arity; j++) {
|
|
||||||
sort * ft_dj = dmn[j];
|
|
||||||
expr * bv_aj = bv_args[j];
|
|
||||||
ai = rebuild_floats(bv_mdl, ft_dj, bv_aj);
|
|
||||||
m_th_rw(ai);
|
|
||||||
new_args.push_back(ai);
|
|
||||||
}
|
|
||||||
|
|
||||||
expr_ref bv_fres(m), ft_fres(m);
|
|
||||||
bv_fres = bv_fe->get_result();
|
|
||||||
ft_fres = rebuild_floats(bv_mdl, rng, bv_fres);
|
|
||||||
m_th_rw(ft_fres);
|
|
||||||
result->insert_new_entry(new_args.c_ptr(), ft_fres);
|
|
||||||
}
|
|
||||||
|
|
||||||
expr_ref bv_els(m), ft_els(m);
|
|
||||||
bv_els = bv_fi->get_else();
|
|
||||||
ft_els = rebuild_floats(bv_mdl, rng, bv_els);
|
|
||||||
m_th_rw(ft_els);
|
|
||||||
result->set_else(ft_els);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fpa2bv_model_converter::convert(model * bv_mdl, model * float_mdl) {
|
|
||||||
TRACE("fpa2bv_mc", tout << "BV Model: " << std::endl;
|
|
||||||
for (unsigned i = 0; i < bv_mdl->get_num_constants(); i++)
|
|
||||||
tout << bv_mdl->get_constant(i)->get_name() << " --> " <<
|
|
||||||
mk_ismt2_pp(bv_mdl->get_const_interp(bv_mdl->get_constant(i)), m) << std::endl;
|
|
||||||
for (unsigned i = 0; i < bv_mdl->get_num_functions(); i++) {
|
|
||||||
func_decl * f = bv_mdl->get_function(i);
|
|
||||||
tout << f->get_name() << "(...) := " << std::endl;
|
|
||||||
func_interp * fi = bv_mdl->get_func_interp(f);
|
|
||||||
for (unsigned j = 0; j < fi->num_entries(); j++) {
|
|
||||||
func_entry const * fe = fi->get_entry(j);
|
|
||||||
for (unsigned k = 0; k < f->get_arity(); k++) {
|
|
||||||
tout << mk_ismt2_pp(fe->get_arg(k), m) << " ";
|
|
||||||
}
|
|
||||||
tout << "--> " << mk_ismt2_pp(fe->get_result(), m) << std::endl;
|
|
||||||
}
|
|
||||||
tout << "else " << mk_ismt2_pp(fi->get_else(), m) << std::endl;
|
|
||||||
});
|
|
||||||
|
|
||||||
obj_hashtable<func_decl> seen;
|
obj_hashtable<func_decl> seen;
|
||||||
|
m_bv2fp->convert_consts(mc, float_mdl, seen);
|
||||||
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = m_specials.begin();
|
m_bv2fp->convert_rm_consts(mc, float_mdl, seen);
|
||||||
it != m_specials.end();
|
m_bv2fp->convert_min_max_specials(mc, float_mdl, seen);
|
||||||
it++) {
|
m_bv2fp->convert_uf2bvuf(mc, float_mdl, seen);
|
||||||
func_decl * f = it->m_key;
|
|
||||||
expr_ref pzero(m), nzero(m);
|
|
||||||
pzero = m_fpa_util.mk_pzero(f->get_range());
|
|
||||||
nzero = m_fpa_util.mk_nzero(f->get_range());
|
|
||||||
|
|
||||||
expr_ref pn(m), np(m);
|
|
||||||
bv_mdl->eval(it->m_value.first, pn, true);
|
|
||||||
bv_mdl->eval(it->m_value.second, np, true);
|
|
||||||
seen.insert(it->m_value.first->get_decl());
|
|
||||||
seen.insert(it->m_value.second->get_decl());
|
|
||||||
|
|
||||||
rational pn_num, np_num;
|
|
||||||
unsigned bv_sz;
|
|
||||||
m_bv_util.is_numeral(pn, pn_num, bv_sz);
|
|
||||||
m_bv_util.is_numeral(np, np_num, bv_sz);
|
|
||||||
|
|
||||||
func_interp * flt_fi = alloc(func_interp, m, f->get_arity());
|
|
||||||
expr * pn_args[2] = { pzero, nzero };
|
|
||||||
if (pn != np) flt_fi->insert_new_entry(pn_args, (pn_num.is_one() ? nzero : pzero));
|
|
||||||
flt_fi->set_else(np_num.is_one() ? nzero : pzero);
|
|
||||||
|
|
||||||
float_mdl->register_decl(f, flt_fi);
|
|
||||||
TRACE("fpa2bv_mc", tout << "fp.min/fp.max special: " << std::endl <<
|
|
||||||
mk_ismt2_pp(f, m) << " == " << mk_ismt2_pp(flt_fi->get_interp(), m) << std::endl;);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (obj_map<func_decl, expr*>::iterator it = m_const2bv.begin();
|
|
||||||
it != m_const2bv.end();
|
|
||||||
it++)
|
|
||||||
{
|
|
||||||
func_decl * var = it->m_key;
|
|
||||||
app * val = to_app(it->m_value);
|
|
||||||
SASSERT(m_fpa_util.is_float(var->get_range()));
|
|
||||||
SASSERT(var->get_range()->get_num_parameters() == 2);
|
|
||||||
|
|
||||||
expr_ref sgn(m), sig(m), exp(m);
|
|
||||||
bv_mdl->eval(val->get_arg(0), sgn, true);
|
|
||||||
bv_mdl->eval(val->get_arg(1), exp, true);
|
|
||||||
bv_mdl->eval(val->get_arg(2), sig, true);
|
|
||||||
|
|
||||||
SASSERT(val->is_app_of(m_fpa_util.get_family_id(), OP_FPA_FP));
|
|
||||||
|
|
||||||
#ifdef Z3DEBUG
|
|
||||||
SASSERT(to_app(val->get_arg(0))->get_decl()->get_arity() == 0);
|
|
||||||
SASSERT(to_app(val->get_arg(1))->get_decl()->get_arity() == 0);
|
|
||||||
SASSERT(to_app(val->get_arg(2))->get_decl()->get_arity() == 0);
|
|
||||||
seen.insert(to_app(val->get_arg(0))->get_decl());
|
|
||||||
seen.insert(to_app(val->get_arg(1))->get_decl());
|
|
||||||
seen.insert(to_app(val->get_arg(2))->get_decl());
|
|
||||||
#else
|
|
||||||
SASSERT(a->get_arg(0)->get_kind() == OP_EXTRACT);
|
|
||||||
SASSERT(to_app(a->get_arg(0))->get_arg(0)->get_kind() == OP_EXTRACT);
|
|
||||||
seen.insert(to_app(to_app(val->get_arg(0))->get_arg(0))->get_decl());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!sgn && !sig && !exp)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
expr_ref cv(m);
|
|
||||||
cv = convert_bv2fp(var->get_range(), sgn, exp, sig);
|
|
||||||
float_mdl->register_decl(var, cv);
|
|
||||||
|
|
||||||
TRACE("fpa2bv_mc", tout << var->get_name() << " == " << mk_ismt2_pp(cv, m) << std::endl;);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (obj_map<func_decl, expr*>::iterator it = m_rm_const2bv.begin();
|
|
||||||
it != m_rm_const2bv.end();
|
|
||||||
it++)
|
|
||||||
{
|
|
||||||
func_decl * var = it->m_key;
|
|
||||||
SASSERT(m_fpa_util.is_rm(var->get_range()));
|
|
||||||
expr * val = it->m_value;
|
|
||||||
SASSERT(m_fpa_util.is_bv2rm(val));
|
|
||||||
expr * bvval = to_app(val)->get_arg(0);
|
|
||||||
expr_ref fv(m);
|
|
||||||
fv = convert_bv2rm(bv_mdl, bvval);
|
|
||||||
TRACE("fpa2bv_mc", tout << var->get_name() << " == " << mk_ismt2_pp(fv, m) << ")" << std::endl;);
|
|
||||||
float_mdl->register_decl(var, fv);
|
|
||||||
seen.insert(to_app(bvval)->get_decl());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (obj_map<func_decl, func_decl*>::iterator it = m_uf2bvuf.begin();
|
|
||||||
it != m_uf2bvuf.end();
|
|
||||||
it++) {
|
|
||||||
seen.insert(it->m_value);
|
|
||||||
|
|
||||||
func_decl * f = it->m_key;
|
|
||||||
if (f->get_arity() == 0)
|
|
||||||
{
|
|
||||||
array_util au(m);
|
|
||||||
if (au.is_array(f->get_range())) {
|
|
||||||
array_model am = convert_array_func_interp(f, it->m_value, bv_mdl);
|
|
||||||
if (am.new_float_fd) float_mdl->register_decl(am.new_float_fd, am.new_float_fi);
|
|
||||||
if (am.result) float_mdl->register_decl(f, am.result);
|
|
||||||
if (am.bv_fd) seen.insert(am.bv_fd);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Just keep.
|
|
||||||
SASSERT(!m_fpa_util.is_float(f->get_range()) && !m_fpa_util.is_rm(f->get_range()));
|
|
||||||
expr_ref val(m);
|
|
||||||
bv_mdl->eval(it->m_value, val);
|
|
||||||
if (val) float_mdl->register_decl(f, val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
func_interp * fmv = convert_func_interp(f, it->m_value, bv_mdl);
|
|
||||||
if (fmv) float_mdl->register_decl(f, fmv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep all the non-float constants.
|
// Keep all the non-float constants.
|
||||||
unsigned sz = bv_mdl->get_num_constants();
|
unsigned sz = mc->get_num_constants();
|
||||||
for (unsigned i = 0; i < sz; i++)
|
for (unsigned i = 0; i < sz; i++) {
|
||||||
{
|
func_decl * c = mc->get_constant(i);
|
||||||
func_decl * c = bv_mdl->get_constant(i);
|
|
||||||
if (!seen.contains(c))
|
if (!seen.contains(c))
|
||||||
float_mdl->register_decl(c, bv_mdl->get_const_interp(c));
|
float_mdl->register_decl(c, mc->get_const_interp(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
// And keep everything else
|
// And keep everything else
|
||||||
sz = bv_mdl->get_num_functions();
|
sz = mc->get_num_functions();
|
||||||
for (unsigned i = 0; i < sz; i++)
|
for (unsigned i = 0; i < sz; i++) {
|
||||||
{
|
func_decl * f = mc->get_function(i);
|
||||||
func_decl * f = bv_mdl->get_function(i);
|
if (!seen.contains(f)) {
|
||||||
if (!seen.contains(f))
|
|
||||||
{
|
|
||||||
TRACE("fpa2bv_mc", tout << "Keeping: " << mk_ismt2_pp(f, m) << std::endl;);
|
TRACE("fpa2bv_mc", tout << "Keeping: " << mk_ismt2_pp(f, m) << std::endl;);
|
||||||
func_interp * val = bv_mdl->get_func_interp(f)->copy();
|
func_interp * val = mc->get_func_interp(f)->copy();
|
||||||
float_mdl->register_decl(f, val);
|
float_mdl->register_decl(f, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sz = bv_mdl->get_num_uninterpreted_sorts();
|
sz = mc->get_num_uninterpreted_sorts();
|
||||||
for (unsigned i = 0; i < sz; i++)
|
for (unsigned i = 0; i < sz; i++) {
|
||||||
{
|
sort * s = mc->get_uninterpreted_sort(i);
|
||||||
sort * s = bv_mdl->get_uninterpreted_sort(i);
|
ptr_vector<expr> u = mc->get_universe(s);
|
||||||
ptr_vector<expr> u = bv_mdl->get_universe(s);
|
|
||||||
float_mdl->register_usort(s, u.size(), u.c_ptr());
|
float_mdl->register_usort(s, u.size(), u.c_ptr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
model_converter * mk_fpa2bv_model_converter(ast_manager & m, fpa2bv_converter const & conv) {
|
model_converter * mk_fpa2bv_model_converter(ast_manager & m, fpa2bv_converter & conv) {
|
||||||
return alloc(fpa2bv_model_converter, m, conv);
|
return alloc(fpa2bv_model_converter, m, conv);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,78 +19,27 @@ Notes:
|
||||||
#ifndef FPA2BV_MODEL_CONVERTER_H_
|
#ifndef FPA2BV_MODEL_CONVERTER_H_
|
||||||
#define FPA2BV_MODEL_CONVERTER_H_
|
#define FPA2BV_MODEL_CONVERTER_H_
|
||||||
|
|
||||||
#include"th_rewriter.h"
|
|
||||||
#include"fpa2bv_converter.h"
|
#include"fpa2bv_converter.h"
|
||||||
#include"model_converter.h"
|
#include"model_converter.h"
|
||||||
|
#include"bv2fpa_converter.h"
|
||||||
|
|
||||||
class fpa2bv_model_converter : public model_converter {
|
class fpa2bv_model_converter : public model_converter {
|
||||||
ast_manager & m;
|
ast_manager & m;
|
||||||
fpa_util m_fpa_util;
|
bv2fpa_converter * m_bv2fp;
|
||||||
bv_util m_bv_util;
|
|
||||||
th_rewriter m_th_rw;
|
|
||||||
|
|
||||||
obj_map<func_decl, expr*> m_const2bv;
|
|
||||||
obj_map<func_decl, expr*> m_rm_const2bv;
|
|
||||||
obj_map<func_decl, func_decl*> m_uf2bvuf;
|
|
||||||
obj_map<func_decl, std::pair<app*, app*> > m_specials;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
fpa2bv_model_converter(ast_manager & m, fpa2bv_converter const & conv) :
|
fpa2bv_model_converter(ast_manager & m, fpa2bv_converter & conv):
|
||||||
m(m),
|
m(m),
|
||||||
m_fpa_util(m),
|
m_bv2fp(alloc(bv2fpa_converter, m, conv)) {
|
||||||
m_bv_util(m),
|
|
||||||
m_th_rw(m) {
|
|
||||||
for (obj_map<func_decl, expr*>::iterator it = conv.m_const2bv.begin();
|
|
||||||
it != conv.m_const2bv.end();
|
|
||||||
it++)
|
|
||||||
{
|
|
||||||
m_const2bv.insert(it->m_key, it->m_value);
|
|
||||||
m.inc_ref(it->m_key);
|
|
||||||
m.inc_ref(it->m_value);
|
|
||||||
}
|
|
||||||
for (obj_map<func_decl, expr*>::iterator it = conv.m_rm_const2bv.begin();
|
|
||||||
it != conv.m_rm_const2bv.end();
|
|
||||||
it++)
|
|
||||||
{
|
|
||||||
m_rm_const2bv.insert(it->m_key, it->m_value);
|
|
||||||
m.inc_ref(it->m_key);
|
|
||||||
m.inc_ref(it->m_value);
|
|
||||||
}
|
|
||||||
for (obj_map<func_decl, func_decl*>::iterator it = conv.m_uf2bvuf.begin();
|
|
||||||
it != conv.m_uf2bvuf.end();
|
|
||||||
it++)
|
|
||||||
{
|
|
||||||
m_uf2bvuf.insert(it->m_key, it->m_value);
|
|
||||||
m.inc_ref(it->m_key);
|
|
||||||
m.inc_ref(it->m_value);
|
|
||||||
}
|
|
||||||
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = conv.m_min_max_specials.begin();
|
|
||||||
it != conv.m_min_max_specials.end();
|
|
||||||
it++) {
|
|
||||||
m_specials.insert(it->m_key, it->m_value);
|
|
||||||
m.inc_ref(it->m_key);
|
|
||||||
m.inc_ref(it->m_value.first);
|
|
||||||
m.inc_ref(it->m_value.second);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~fpa2bv_model_converter() {
|
virtual ~fpa2bv_model_converter() {
|
||||||
dec_ref_map_key_values(m, m_const2bv);
|
dealloc(m_bv2fp);
|
||||||
dec_ref_map_key_values(m, m_rm_const2bv);
|
|
||||||
dec_ref_map_key_values(m, m_uf2bvuf);
|
|
||||||
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = m_specials.begin();
|
|
||||||
it != m_specials.end();
|
|
||||||
it++) {
|
|
||||||
m.dec_ref(it->m_key);
|
|
||||||
m.dec_ref(it->m_value.first);
|
|
||||||
m.dec_ref(it->m_value.second);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void operator()(model_ref & md, unsigned goal_idx) {
|
virtual void operator()(model_ref & md, unsigned goal_idx) {
|
||||||
SASSERT(goal_idx == 0);
|
SASSERT(goal_idx == 0);
|
||||||
model * new_model = alloc(model, m);
|
model * new_model = alloc(model, m);
|
||||||
obj_hashtable<func_decl> bits;
|
|
||||||
convert(md.get(), new_model);
|
convert(md.get(), new_model);
|
||||||
md = new_model;
|
md = new_model;
|
||||||
}
|
}
|
||||||
|
@ -106,32 +55,12 @@ public:
|
||||||
protected:
|
protected:
|
||||||
fpa2bv_model_converter(ast_manager & m) :
|
fpa2bv_model_converter(ast_manager & m) :
|
||||||
m(m),
|
m(m),
|
||||||
m_fpa_util(m),
|
m_bv2fp(0) {}
|
||||||
m_bv_util(m),
|
|
||||||
m_th_rw(m) {}
|
|
||||||
|
|
||||||
void convert(model * bv_mdl, model * float_mdl);
|
void convert(model_core * mc, model * float_mdl);
|
||||||
expr_ref convert_bv2fp(sort * s, expr * sgn, expr * exp, expr * sig);
|
|
||||||
expr_ref convert_bv2fp(model * bv_mdl, sort * s, expr * bv);
|
|
||||||
expr_ref convert_bv2rm(expr * eval_v);
|
|
||||||
expr_ref convert_bv2rm(model * bv_mdl, expr * val);
|
|
||||||
|
|
||||||
func_interp * convert_func_interp(func_decl * f, func_decl * bv_f, model * bv_mdl);
|
|
||||||
expr_ref rebuild_floats(model * bv_mdl, sort * s, expr * e);
|
|
||||||
|
|
||||||
class array_model {
|
|
||||||
public:
|
|
||||||
func_decl * new_float_fd;
|
|
||||||
func_interp * new_float_fi;
|
|
||||||
func_decl * bv_fd;
|
|
||||||
expr_ref result;
|
|
||||||
array_model(ast_manager & m) : new_float_fd(0), new_float_fi(0), bv_fd(0), result(m) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
array_model convert_array_func_interp(func_decl * f, func_decl * bv_f, model * bv_mdl);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
model_converter * mk_fpa2bv_model_converter(ast_manager & m, fpa2bv_converter const & conv);
|
model_converter * mk_fpa2bv_model_converter(ast_manager & m, fpa2bv_converter & conv);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
161
src/tactic/portfolio/fd_solver.cpp
Normal file
161
src/tactic/portfolio/fd_solver.cpp
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) 2016 Microsoft Corporation
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
fd_solver.cpp
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Finite domain solver.
|
||||||
|
|
||||||
|
Enumeration data-types are translated into bit-vectors, and then
|
||||||
|
the incremental sat-solver is applied to the resulting assertions.
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Nikolaj Bjorner (nbjorner) 2016-10-17
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "fd_solver.h"
|
||||||
|
#include "solver_na2as.h"
|
||||||
|
#include "tactic.h"
|
||||||
|
#include "inc_sat_solver.h"
|
||||||
|
#include "bv_decl_plugin.h"
|
||||||
|
#include "datatype_decl_plugin.h"
|
||||||
|
#include "fd_rewriter.h"
|
||||||
|
#include "extension_model_converter.h"
|
||||||
|
#include "filter_model_converter.h"
|
||||||
|
#include "ast_pp.h"
|
||||||
|
#include "model_smt2_pp.h"
|
||||||
|
|
||||||
|
class fd_solver : public solver_na2as {
|
||||||
|
ast_manager& m;
|
||||||
|
params_ref m_params;
|
||||||
|
ref<solver> m_solver;
|
||||||
|
fd_rewriter m_rewriter;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
fd_solver(ast_manager& m, params_ref const& p):
|
||||||
|
solver_na2as(m),
|
||||||
|
m(m),
|
||||||
|
m_params(p),
|
||||||
|
m_solver(mk_inc_sat_solver(m, p)),
|
||||||
|
m_rewriter(m, p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~fd_solver() {}
|
||||||
|
|
||||||
|
virtual solver* translate(ast_manager& m, params_ref const& p) {
|
||||||
|
return alloc(fd_solver, m, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void assert_expr(expr * t) {
|
||||||
|
expr_ref tmp(t, m);
|
||||||
|
expr_ref_vector bounds(m);
|
||||||
|
proof_ref tmp_proof(m);
|
||||||
|
m_rewriter(t, tmp, tmp_proof);
|
||||||
|
m_solver->assert_expr(tmp);
|
||||||
|
m_rewriter.flush_side_constraints(bounds);
|
||||||
|
m_solver->assert_expr(bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void push_core() {
|
||||||
|
m_rewriter.push();
|
||||||
|
m_solver->push();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void pop_core(unsigned n) {
|
||||||
|
m_solver->pop(n);
|
||||||
|
m_rewriter.pop(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions) {
|
||||||
|
return m_solver->check_sat(num_assumptions, assumptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void updt_params(params_ref const & p) { m_solver->updt_params(p); }
|
||||||
|
virtual void collect_param_descrs(param_descrs & r) { m_solver->collect_param_descrs(r); }
|
||||||
|
virtual void set_produce_models(bool f) { m_solver->set_produce_models(f); }
|
||||||
|
virtual void set_progress_callback(progress_callback * callback) { m_solver->set_progress_callback(callback); }
|
||||||
|
virtual void collect_statistics(statistics & st) const { m_solver->collect_statistics(st); }
|
||||||
|
virtual void get_unsat_core(ptr_vector<expr> & r) { m_solver->get_unsat_core(r); }
|
||||||
|
virtual void get_model(model_ref & mdl) {
|
||||||
|
m_solver->get_model(mdl);
|
||||||
|
if (mdl) {
|
||||||
|
extend_model(mdl);
|
||||||
|
filter_model(mdl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual proof * get_proof() { return m_solver->get_proof(); }
|
||||||
|
virtual std::string reason_unknown() const { return m_solver->reason_unknown(); }
|
||||||
|
virtual void set_reason_unknown(char const* msg) { m_solver->set_reason_unknown(msg); }
|
||||||
|
virtual void get_labels(svector<symbol> & r) { m_solver->get_labels(r); }
|
||||||
|
virtual ast_manager& get_manager() const { return m; }
|
||||||
|
virtual lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes) { return m_solver->find_mutexes(vars, mutexes); }
|
||||||
|
|
||||||
|
virtual lbool get_consequences_core(expr_ref_vector const& asms, expr_ref_vector const& vars, expr_ref_vector& consequences) {
|
||||||
|
|
||||||
|
datatype_util dt(m);
|
||||||
|
bv_util bv(m);
|
||||||
|
|
||||||
|
// translate enumeration constants to bit-vectors.
|
||||||
|
expr_ref_vector bvars(m), conseq(m);
|
||||||
|
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||||
|
func_decl* f;
|
||||||
|
if (is_app(vars[i]) && is_uninterp_const(vars[i]) && m_rewriter.enum2bv().find(to_app(vars[i])->get_decl(), f)) {
|
||||||
|
bvars.push_back(m.mk_const(f));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bvars.push_back(vars[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lbool r = m_solver->get_consequences(asms, bvars, consequences);
|
||||||
|
|
||||||
|
// translate bit-vector consequences back to enumeration types
|
||||||
|
for (unsigned i = 0; i < consequences.size(); ++i) {
|
||||||
|
expr* a, *b, *u, *v;
|
||||||
|
func_decl* f;
|
||||||
|
rational num;
|
||||||
|
unsigned bvsize;
|
||||||
|
VERIFY(m.is_implies(consequences[i].get(), a, b));
|
||||||
|
if (m.is_eq(b, u, v) && is_uninterp_const(u) && m_rewriter.bv2enum().find(to_app(u)->get_decl(), f) && bv.is_numeral(v, num, bvsize)) {
|
||||||
|
SASSERT(num.is_unsigned());
|
||||||
|
expr_ref head(m);
|
||||||
|
ptr_vector<func_decl> const& enums = *dt.get_datatype_constructors(f->get_range());
|
||||||
|
head = m.mk_eq(m.mk_const(f), m.mk_const(enums[num.get_unsigned()]));
|
||||||
|
consequences[i] = m.mk_implies(a, head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void filter_model(model_ref& mdl) {
|
||||||
|
filter_model_converter filter(m);
|
||||||
|
obj_map<func_decl, func_decl*>::iterator it = m_rewriter.enum2bv().begin(), end = m_rewriter.enum2bv().end();
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
filter.insert(it->m_value);
|
||||||
|
}
|
||||||
|
filter(mdl, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void extend_model(model_ref& mdl) {
|
||||||
|
extension_model_converter ext(m);
|
||||||
|
obj_map<func_decl, expr*>::iterator it = m_rewriter.enum2def().begin(), end = m_rewriter.enum2def().end();
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
ext.insert(it->m_key, it->m_value);
|
||||||
|
|
||||||
|
}
|
||||||
|
ext(mdl, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
solver * mk_fd_solver(ast_manager & m, params_ref const & p) {
|
||||||
|
return alloc(fd_solver, m, p);
|
||||||
|
}
|
29
src/tactic/portfolio/fd_solver.h
Normal file
29
src/tactic/portfolio/fd_solver.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) 2016 Microsoft Corporation
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
fd_solver.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Finite domain solver.
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Nikolaj Bjorner (nbjorner) 2016-10-17
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
#ifndef FD_SOLVER_H_
|
||||||
|
#define FD_SOLVER_H_
|
||||||
|
|
||||||
|
#include"ast.h"
|
||||||
|
#include"params.h"
|
||||||
|
|
||||||
|
class solver;
|
||||||
|
|
||||||
|
solver * mk_fd_solver(ast_manager & m, params_ref const & p);
|
||||||
|
|
||||||
|
#endif
|
|
@ -38,6 +38,7 @@ Notes:
|
||||||
#include"horn_tactic.h"
|
#include"horn_tactic.h"
|
||||||
#include"smt_solver.h"
|
#include"smt_solver.h"
|
||||||
#include"inc_sat_solver.h"
|
#include"inc_sat_solver.h"
|
||||||
|
#include"fd_solver.h"
|
||||||
#include"bv_rewriter.h"
|
#include"bv_rewriter.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,6 +99,8 @@ static solver* mk_solver_for_logic(ast_manager & m, params_ref const & p, symbol
|
||||||
bv_rewriter rw(m);
|
bv_rewriter rw(m);
|
||||||
if (logic == "QF_BV" && rw.hi_div0())
|
if (logic == "QF_BV" && rw.hi_div0())
|
||||||
return mk_inc_sat_solver(m, p);
|
return mk_inc_sat_solver(m, p);
|
||||||
|
if (logic == "QF_FD")
|
||||||
|
return mk_fd_solver(m, p);
|
||||||
return mk_smt_solver(m, p, logic);
|
return mk_smt_solver(m, p, logic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +119,6 @@ public:
|
||||||
tactic * t = mk_tactic_for_logic(m, p, l);
|
tactic * t = mk_tactic_for_logic(m, p, l);
|
||||||
return mk_combined_solver(mk_tactic2solver(m, t, p, proofs_enabled, models_enabled, unsat_core_enabled, l),
|
return mk_combined_solver(mk_tactic2solver(m, t, p, proofs_enabled, models_enabled, unsat_core_enabled, l),
|
||||||
mk_solver_for_logic(m, p, l),
|
mk_solver_for_logic(m, p, l),
|
||||||
//mk_smt_solver(m, p, l),
|
|
||||||
p);
|
p);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
194
src/test/get_consequences.cpp
Normal file
194
src/test/get_consequences.cpp
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) 2016 Microsoft Corporation
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "inc_sat_solver.h"
|
||||||
|
#include "bv_decl_plugin.h"
|
||||||
|
#include "datatype_decl_plugin.h"
|
||||||
|
#include "reg_decl_plugins.h"
|
||||||
|
#include "ast_pp.h"
|
||||||
|
#include "dt2bv_tactic.h"
|
||||||
|
#include "tactic.h"
|
||||||
|
#include "model_smt2_pp.h"
|
||||||
|
#include "fd_solver.h"
|
||||||
|
|
||||||
|
static expr_ref mk_const(ast_manager& m, char const* name, sort* s) {
|
||||||
|
return expr_ref(m.mk_const(symbol(name), s), m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static expr_ref mk_bool(ast_manager& m, char const* name) {
|
||||||
|
return expr_ref(m.mk_const(symbol(name), m.mk_bool_sort()), m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static expr_ref mk_bv(ast_manager& m, char const* name, unsigned sz) {
|
||||||
|
bv_util bv(m);
|
||||||
|
return expr_ref(m.mk_const(symbol(name), bv.mk_sort(sz)), m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test1() {
|
||||||
|
ast_manager m;
|
||||||
|
reg_decl_plugins(m);
|
||||||
|
bv_util bv(m);
|
||||||
|
params_ref p;
|
||||||
|
|
||||||
|
ref<solver> solver = mk_inc_sat_solver(m, p);
|
||||||
|
expr_ref a = mk_bool(m, "a"), b = mk_bool(m, "b"), c = mk_bool(m, "c");
|
||||||
|
expr_ref ba = mk_bv(m, "ba", 3), bb = mk_bv(m, "bb", 3), bc = mk_bv(m, "bc", 3);
|
||||||
|
|
||||||
|
solver->assert_expr(m.mk_implies(a, b));
|
||||||
|
solver->assert_expr(m.mk_implies(b, c));
|
||||||
|
expr_ref_vector asms(m), vars(m), conseq(m);
|
||||||
|
asms.push_back(a);
|
||||||
|
vars.push_back(b);
|
||||||
|
vars.push_back(c);
|
||||||
|
vars.push_back(bb);
|
||||||
|
vars.push_back(bc);
|
||||||
|
solver->assert_expr(m.mk_eq(ba, bc));
|
||||||
|
solver->assert_expr(m.mk_eq(bv.mk_numeral(2, 3), ba));
|
||||||
|
solver->get_consequences(asms, vars, conseq);
|
||||||
|
|
||||||
|
std::cout << conseq << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test2() {
|
||||||
|
ast_manager m;
|
||||||
|
reg_decl_plugins(m);
|
||||||
|
bv_util bv(m);
|
||||||
|
datatype_util dtutil(m);
|
||||||
|
params_ref p;
|
||||||
|
|
||||||
|
datatype_decl_plugin & dt = *(static_cast<datatype_decl_plugin*>(m.get_plugin(m.get_family_id("datatype"))));
|
||||||
|
sort_ref_vector new_sorts(m);
|
||||||
|
constructor_decl* R = mk_constructor_decl(symbol("R"), symbol("is-R"), 0, 0);
|
||||||
|
constructor_decl* G = mk_constructor_decl(symbol("G"), symbol("is-G"), 0, 0);
|
||||||
|
constructor_decl* B = mk_constructor_decl(symbol("B"), symbol("is-B"), 0, 0);
|
||||||
|
constructor_decl* constrs[3] = { R, G, B };
|
||||||
|
datatype_decl * enum_sort = mk_datatype_decl(symbol("RGB"), 3, constrs);
|
||||||
|
VERIFY(dt.mk_datatypes(1, &enum_sort, new_sorts));
|
||||||
|
del_constructor_decls(3, constrs);
|
||||||
|
sort* rgb = new_sorts[0].get();
|
||||||
|
|
||||||
|
expr_ref x = mk_const(m, "x", rgb), y = mk_const(m, "y", rgb), z = mk_const(m, "z", rgb);
|
||||||
|
ptr_vector<func_decl> const& enums = *dtutil.get_datatype_constructors(rgb);
|
||||||
|
expr_ref r = expr_ref(m.mk_const(enums[0]), m);
|
||||||
|
expr_ref g = expr_ref(m.mk_const(enums[1]), m);
|
||||||
|
expr_ref b = expr_ref(m.mk_const(enums[2]), m);
|
||||||
|
expr_ref val(m);
|
||||||
|
|
||||||
|
// Eliminate enumeration data-types:
|
||||||
|
goal_ref gl = alloc(goal, m);
|
||||||
|
gl->assert_expr(m.mk_not(m.mk_eq(x, r)));
|
||||||
|
gl->assert_expr(m.mk_not(m.mk_eq(x, b)));
|
||||||
|
gl->display(std::cout);
|
||||||
|
obj_map<func_decl, func_decl*> tr;
|
||||||
|
obj_map<func_decl, func_decl*> rev_tr;
|
||||||
|
ref<tactic> dt2bv = mk_dt2bv_tactic(m, p, &tr);
|
||||||
|
goal_ref_buffer result;
|
||||||
|
model_converter_ref mc;
|
||||||
|
proof_converter_ref pc;
|
||||||
|
expr_dependency_ref core(m);
|
||||||
|
(*dt2bv)(gl, result, mc, pc, core);
|
||||||
|
|
||||||
|
// Collect translations from enumerations to bit-vectors
|
||||||
|
obj_map<func_decl, func_decl*>::iterator it = tr.begin(), end = tr.end();
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
rev_tr.insert(it->m_value, it->m_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create bit-vector implication problem
|
||||||
|
val = m.mk_const(tr.find(to_app(x)->get_decl()));
|
||||||
|
std::cout << val << "\n";
|
||||||
|
ptr_vector<expr> fmls;
|
||||||
|
result[0]->get_formulas(fmls);
|
||||||
|
ref<solver> solver = mk_inc_sat_solver(m, p);
|
||||||
|
for (unsigned i = 0; i < fmls.size(); ++i) {
|
||||||
|
solver->assert_expr(fmls[i]);
|
||||||
|
}
|
||||||
|
expr_ref_vector asms(m), vars(m), conseq(m);
|
||||||
|
vars.push_back(val);
|
||||||
|
|
||||||
|
// retrieve consequences
|
||||||
|
solver->get_consequences(asms, vars, conseq);
|
||||||
|
|
||||||
|
// Convert consequences over bit-vectors to enumeration types.
|
||||||
|
std::cout << conseq << "\n";
|
||||||
|
for (unsigned i = 0; i < conseq.size(); ++i) {
|
||||||
|
expr* a, *b, *u, *v;
|
||||||
|
func_decl* f;
|
||||||
|
rational num;
|
||||||
|
unsigned bvsize;
|
||||||
|
VERIFY(m.is_implies(conseq[i].get(), a, b));
|
||||||
|
if (m.is_eq(b, u, v) && rev_tr.find(to_app(u)->get_decl(), f) && bv.is_numeral(v, num, bvsize)) {
|
||||||
|
SASSERT(num.is_unsigned());
|
||||||
|
expr_ref head(m);
|
||||||
|
head = m.mk_eq(m.mk_const(f), m.mk_const(enums[num.get_unsigned()]));
|
||||||
|
conseq[i] = m.mk_implies(a, head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << conseq << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void test3() {
|
||||||
|
ast_manager m;
|
||||||
|
reg_decl_plugins(m);
|
||||||
|
bv_util bv(m);
|
||||||
|
datatype_util dtutil(m);
|
||||||
|
params_ref p;
|
||||||
|
|
||||||
|
datatype_decl_plugin & dt = *(static_cast<datatype_decl_plugin*>(m.get_plugin(m.get_family_id("datatype"))));
|
||||||
|
sort_ref_vector new_sorts(m);
|
||||||
|
constructor_decl* R = mk_constructor_decl(symbol("R"), symbol("is-R"), 0, 0);
|
||||||
|
constructor_decl* G = mk_constructor_decl(symbol("G"), symbol("is-G"), 0, 0);
|
||||||
|
constructor_decl* B = mk_constructor_decl(symbol("B"), symbol("is-B"), 0, 0);
|
||||||
|
constructor_decl* constrs[3] = { R, G, B };
|
||||||
|
datatype_decl * enum_sort = mk_datatype_decl(symbol("RGB"), 3, constrs);
|
||||||
|
VERIFY(dt.mk_datatypes(1, &enum_sort, new_sorts));
|
||||||
|
del_constructor_decls(3, constrs);
|
||||||
|
sort* rgb = new_sorts[0].get();
|
||||||
|
|
||||||
|
expr_ref x = mk_const(m, "x", rgb), y = mk_const(m, "y", rgb), z = mk_const(m, "z", rgb);
|
||||||
|
ptr_vector<func_decl> const& enums = *dtutil.get_datatype_constructors(rgb);
|
||||||
|
expr_ref r = expr_ref(m.mk_const(enums[0]), m);
|
||||||
|
expr_ref g = expr_ref(m.mk_const(enums[1]), m);
|
||||||
|
expr_ref b = expr_ref(m.mk_const(enums[2]), m);
|
||||||
|
|
||||||
|
ref<solver> fd_solver = mk_fd_solver(m, p);
|
||||||
|
fd_solver->assert_expr(m.mk_not(m.mk_eq(x, r)));
|
||||||
|
fd_solver->assert_expr(m.mk_not(m.mk_eq(x, b)));
|
||||||
|
|
||||||
|
expr_ref_vector asms(m), vars(m), conseq(m);
|
||||||
|
vars.push_back(x);
|
||||||
|
vars.push_back(y);
|
||||||
|
|
||||||
|
VERIFY(l_true == fd_solver->get_consequences(asms, vars, conseq));
|
||||||
|
std::cout << conseq << "\n";
|
||||||
|
conseq.reset();
|
||||||
|
|
||||||
|
fd_solver->push();
|
||||||
|
fd_solver->assert_expr(m.mk_not(m.mk_eq(x, g)));
|
||||||
|
VERIFY(l_false == fd_solver->check_sat(0,0));
|
||||||
|
fd_solver->pop(1);
|
||||||
|
|
||||||
|
VERIFY(l_true == fd_solver->get_consequences(asms, vars, conseq));
|
||||||
|
|
||||||
|
std::cout << conseq << "\n";
|
||||||
|
conseq.reset();
|
||||||
|
|
||||||
|
model_ref mr;
|
||||||
|
fd_solver->get_model(mr);
|
||||||
|
model_smt2_pp(std::cout << "model:\n", m, *mr.get(), 0);
|
||||||
|
|
||||||
|
VERIFY(l_true == fd_solver->check_sat(0,0));
|
||||||
|
fd_solver->get_model(mr);
|
||||||
|
SASSERT(mr.get());
|
||||||
|
model_smt2_pp(std::cout, m, *mr.get(), 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_get_consequences() {
|
||||||
|
test1();
|
||||||
|
test2();
|
||||||
|
test3();
|
||||||
|
|
||||||
|
}
|
|
@ -228,6 +228,7 @@ int main(int argc, char ** argv) {
|
||||||
TST(pdr);
|
TST(pdr);
|
||||||
TST_ARGV(ddnf);
|
TST_ARGV(ddnf);
|
||||||
TST(model_evaluator);
|
TST(model_evaluator);
|
||||||
|
TST(get_consequences);
|
||||||
//TST_ARGV(hs);
|
//TST_ARGV(hs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue