mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
Merge branch 'master' into polysat
This commit is contained in:
commit
1df749ad33
368 changed files with 12363 additions and 6152 deletions
|
@ -118,6 +118,27 @@ if (Z3_BUILD_LIBZ3_SHARED)
|
|||
else()
|
||||
set(lib_type "STATIC")
|
||||
endif()
|
||||
# Enable static msvc runtime.
|
||||
if (MSVC AND Z3_BUILD_LIBZ3_MSVC_STATIC)
|
||||
set(CompilerFlags
|
||||
CMAKE_CXX_FLAGS
|
||||
CMAKE_CXX_FLAGS_DEBUG
|
||||
CMAKE_CXX_FLAGS_RELEASE
|
||||
CMAKE_CXX_FLAGS_MINSIZEREL
|
||||
CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||
CMAKE_C_FLAGS
|
||||
CMAKE_C_FLAGS_DEBUG
|
||||
CMAKE_C_FLAGS_RELEASE
|
||||
CMAKE_C_FLAGS_MINSIZEREL
|
||||
CMAKE_C_FLAGS_RELWITHDEBINFO
|
||||
)
|
||||
foreach(CompilerFlag ${CompilerFlags})
|
||||
string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
|
||||
string(REPLACE "/MDd" "/MTd" ${CompilerFlag} "${${CompilerFlag}}")
|
||||
set(${CompilerFlag} "${${CompilerFlag}}" CACHE STRING "msvc compiler flags" FORCE)
|
||||
message("MSVC flags: ${CompilerFlag}:${${CompilerFlag}}")
|
||||
endforeach()
|
||||
endif(MSVC)
|
||||
add_library(libz3 ${lib_type} ${object_files})
|
||||
target_include_directories(libz3 INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/api>
|
||||
|
|
|
@ -22,6 +22,8 @@ Revision History:
|
|||
#include "ast/arith_decl_plugin.h"
|
||||
#include "math/polynomial/algebraic_numbers.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#define MK_ARITH_OP(NAME, OP) MK_NARY(NAME, mk_c(c)->get_arith_fid(), OP, SKIP)
|
||||
#define MK_BINARY_ARITH_OP(NAME, OP) MK_BINARY(NAME, mk_c(c)->get_arith_fid(), OP, SKIP)
|
||||
#define MK_ARITH_PRED(NAME, OP) MK_BINARY(NAME, mk_c(c)->get_arith_fid(), OP, SKIP)
|
||||
|
@ -88,7 +90,25 @@ extern "C" {
|
|||
MK_ARITH_PRED(Z3_mk_gt, OP_GT);
|
||||
MK_ARITH_PRED(Z3_mk_le, OP_LE);
|
||||
MK_ARITH_PRED(Z3_mk_ge, OP_GE);
|
||||
MK_ARITH_PRED(Z3_mk_divides, OP_IDIVIDES);
|
||||
|
||||
Z3_ast Z3_API Z3_mk_divides(Z3_context c, Z3_ast n1, Z3_ast n2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_divides(c, n1, n2);
|
||||
RESET_ERROR_CODE();
|
||||
rational val;
|
||||
if (!is_expr(n1) || !mk_c(c)->autil().is_numeral(to_expr(n1), val) || !val.is_unsigned()) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG, nullptr);
|
||||
RETURN_Z3(nullptr);
|
||||
}
|
||||
parameter p(val.get_unsigned());
|
||||
expr* arg = to_expr(n2);
|
||||
expr* a = mk_c(c)->m().mk_app(mk_c(c)->get_arith_fid(), OP_IDIVIDES, 1, &p, 1, &arg);
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
check_sorts(c, a);
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
MK_UNARY(Z3_mk_int2real, mk_c(c)->get_arith_fid(), OP_TO_REAL, SKIP);
|
||||
MK_UNARY(Z3_mk_real2int, mk_c(c)->get_arith_fid(), OP_TO_INT, SKIP);
|
||||
MK_UNARY(Z3_mk_is_int, mk_c(c)->get_arith_fid(), OP_IS_INT, SKIP);
|
||||
|
|
|
@ -294,14 +294,19 @@ extern "C" {
|
|||
return Z3_mk_store(c, set, elem, Z3_mk_false(c));
|
||||
}
|
||||
|
||||
static bool is_array_sort(Z3_context c, Z3_sort t) {
|
||||
return
|
||||
to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() &&
|
||||
to_sort(t)->get_decl_kind() == ARRAY_SORT;
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_get_array_sort_domain(Z3_context c, Z3_sort t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_array_sort_domain(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(t, nullptr);
|
||||
if (to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() &&
|
||||
to_sort(t)->get_decl_kind() == ARRAY_SORT) {
|
||||
Z3_sort r = reinterpret_cast<Z3_sort>(to_sort(t)->get_parameter(0).get_ast());
|
||||
if (is_array_sort(c, t)) {
|
||||
Z3_sort r = of_sort(get_array_domain(to_sort(t), 0));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG, nullptr);
|
||||
|
@ -314,10 +319,8 @@ extern "C" {
|
|||
LOG_Z3_get_array_sort_domain_n(c, t, idx);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(t, nullptr);
|
||||
if (to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() &&
|
||||
to_sort(t)->get_decl_kind() == ARRAY_SORT &&
|
||||
get_array_arity(to_sort(t)) > idx) {
|
||||
Z3_sort r = reinterpret_cast<Z3_sort>(get_array_domain(to_sort(t), idx));
|
||||
if (is_array_sort(c, t) && get_array_arity(to_sort(t)) > idx) {
|
||||
Z3_sort r = of_sort(get_array_domain(to_sort(t), idx));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG, nullptr);
|
||||
|
@ -330,10 +333,8 @@ extern "C" {
|
|||
LOG_Z3_get_array_sort_range(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(t, nullptr);
|
||||
if (to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() &&
|
||||
to_sort(t)->get_decl_kind() == ARRAY_SORT) {
|
||||
unsigned n = to_sort(t)->get_num_parameters();
|
||||
Z3_sort r = reinterpret_cast<Z3_sort>(to_sort(t)->get_parameter(n-1).get_ast());
|
||||
if (is_array_sort(c, t)) {
|
||||
Z3_sort r = of_sort(get_array_range(to_sort(t)));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG, nullptr);
|
||||
|
|
|
@ -1178,7 +1178,7 @@ extern "C" {
|
|||
case OP_BSMOD: return Z3_OP_BSMOD;
|
||||
case OP_BSDIV0: return Z3_OP_BSDIV0;
|
||||
case OP_BUDIV0: return Z3_OP_BUDIV0;
|
||||
case OP_BSREM0: return Z3_OP_BUREM0;
|
||||
case OP_BSREM0: return Z3_OP_BSREM0;
|
||||
case OP_BUREM0: return Z3_OP_BUREM0;
|
||||
case OP_BSMOD0: return Z3_OP_BSMOD0;
|
||||
case OP_ULEQ: return Z3_OP_ULEQ;
|
||||
|
|
|
@ -153,7 +153,7 @@ namespace api {
|
|||
flush_objects();
|
||||
for (auto& kv : m_allocated_objects) {
|
||||
api::object* val = kv.m_value;
|
||||
DEBUG_CODE(warning_msg("Uncollected memory: %d: %s", kv.m_key, typeid(*val).name()););
|
||||
DEBUG_CODE(if (!m_concurrent_dec_ref) warning_msg("Uncollected memory: %d: %s", kv.m_key, typeid(*val).name()););
|
||||
dealloc(val);
|
||||
}
|
||||
if (m_params.owns_manager())
|
||||
|
|
|
@ -124,7 +124,7 @@ extern "C" {
|
|||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_ast_vector Z3_parser_context_parse_stream(Z3_context c, scoped_ptr<cmd_context>& ctx, bool owned, std::istream& is) {
|
||||
static Z3_ast_vector Z3_parser_context_parse_stream(Z3_context c, scoped_ptr<cmd_context>& ctx, bool owned, std::istream& is) {
|
||||
Z3_TRY;
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
|
||||
mk_c(c)->save_object(v);
|
||||
|
@ -163,6 +163,7 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
static
|
||||
Z3_ast_vector parse_smtlib2_stream(bool exec, Z3_context c, std::istream& is,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const _sort_names[],
|
||||
|
@ -242,6 +243,7 @@ extern "C" {
|
|||
std::istringstream is(s);
|
||||
ctx->set_regular_stream(ous);
|
||||
ctx->set_diagnostic_stream(ous);
|
||||
cmd_context::scoped_redirect _redirect(*ctx);
|
||||
try {
|
||||
if (!parse_smt2_commands(*ctx.get(), is)) {
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR, ous.str());
|
||||
|
@ -256,6 +258,4 @@ extern "C" {
|
|||
RETURN_Z3(mk_c(c)->mk_external_string(ous.str()));
|
||||
Z3_CATCH_RETURN(mk_c(c)->mk_external_string(ous.str()));
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ Revision History:
|
|||
#include "smt/smt_implied_equalities.h"
|
||||
#include "solver/smt_logics.h"
|
||||
#include "solver/tactic2solver.h"
|
||||
#include "solver/solver_params.hpp"
|
||||
#include "params/solver_params.hpp"
|
||||
#include "cmd_context/cmd_context.h"
|
||||
#include "parsers/smt2/smt2parser.h"
|
||||
#include "sat/dimacs.h"
|
||||
|
|
|
@ -28,7 +28,7 @@ extern "C" {
|
|||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
to_stats_ref(s).display_smt2(buffer);
|
||||
std::string result = buffer.str();
|
||||
std::string result = std::move(buffer).str();
|
||||
// Hack for removing the trailing '\n'
|
||||
SASSERT(result.size() > 0);
|
||||
result.resize(result.size()-1);
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace api {
|
|||
context& m_context;
|
||||
public:
|
||||
object(context& c);
|
||||
virtual ~object() {}
|
||||
virtual ~object() = default;
|
||||
unsigned ref_count() const { return m_ref_count; }
|
||||
unsigned id() const { return m_id; }
|
||||
void inc_ref();
|
||||
|
|
|
@ -23,7 +23,6 @@ Notes:
|
|||
#include<cassert>
|
||||
#include<ostream>
|
||||
#include<string>
|
||||
#include<sstream>
|
||||
#include<memory>
|
||||
#include<vector>
|
||||
#include<z3.h>
|
||||
|
@ -88,7 +87,7 @@ namespace z3 {
|
|||
class exception : public std::exception {
|
||||
std::string m_msg;
|
||||
public:
|
||||
virtual ~exception() throw() {}
|
||||
virtual ~exception() throw() = default;
|
||||
exception(char const * msg):m_msg(msg) {}
|
||||
char const * msg() const { return m_msg.c_str(); }
|
||||
char const * what() const throw() { return m_msg.c_str(); }
|
||||
|
@ -4315,6 +4314,16 @@ namespace z3 {
|
|||
Z3_solver_propagate_consequence(ctx(), cb, fixed.size(), _fixed.ptr(), 0, nullptr, nullptr, conseq);
|
||||
}
|
||||
|
||||
void conflict(expr_vector const& fixed, expr_vector const& lhs, expr_vector const& rhs) {
|
||||
assert(cb);
|
||||
assert(lhs.size() == rhs.size());
|
||||
expr conseq = ctx().bool_val(false);
|
||||
array<Z3_ast> _fixed(fixed);
|
||||
array<Z3_ast> _lhs(lhs);
|
||||
array<Z3_ast> _rhs(rhs);
|
||||
Z3_solver_propagate_consequence(ctx(), cb, fixed.size(), _fixed.ptr(), lhs.size(), _lhs.ptr(), _rhs.ptr(), conseq);
|
||||
}
|
||||
|
||||
void propagate(expr_vector const& fixed, expr const& conseq) {
|
||||
assert(cb);
|
||||
assert((Z3_context)conseq.ctx() == (Z3_context)ctx());
|
||||
|
|
|
@ -208,37 +208,22 @@ namespace Microsoft.Z3
|
|||
internal AST(Context ctx) : base(ctx) { Debug.Assert(ctx != null); }
|
||||
internal AST(Context ctx, IntPtr obj) : base(ctx, obj) { Debug.Assert(ctx != null); }
|
||||
|
||||
internal class DecRefQueue : IDecRefQueue
|
||||
{
|
||||
public DecRefQueue() : base() { }
|
||||
public DecRefQueue(uint move_limit) : base(move_limit) { }
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_dec_ref(ctx.nCtx, obj);
|
||||
}
|
||||
};
|
||||
|
||||
internal override void IncRef(IntPtr o)
|
||||
{
|
||||
// Console.WriteLine("AST IncRef()");
|
||||
if (Context == null || o == IntPtr.Zero)
|
||||
return;
|
||||
Context.AST_DRQ.IncAndClear(Context, o);
|
||||
base.IncRef(o);
|
||||
if (Context != null && o != IntPtr.Zero)
|
||||
Native.Z3_inc_ref(Context.nCtx, o);
|
||||
}
|
||||
|
||||
internal override void DecRef(IntPtr o)
|
||||
{
|
||||
// Console.WriteLine("AST DecRef()");
|
||||
if (Context == null || o == IntPtr.Zero)
|
||||
return;
|
||||
Context.AST_DRQ.Add(o);
|
||||
base.DecRef(o);
|
||||
if (Context != null && o != IntPtr.Zero)
|
||||
{
|
||||
lock (Context)
|
||||
{
|
||||
if (Context.nCtx != IntPtr.Zero)
|
||||
Native.Z3_dec_ref(Context.nCtx, o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static AST Create(Context ctx, IntPtr obj)
|
||||
|
|
|
@ -125,31 +125,18 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(ctx != null);
|
||||
}
|
||||
|
||||
internal class DecRefQueue : IDecRefQueue
|
||||
{
|
||||
public DecRefQueue() : base() { }
|
||||
public DecRefQueue(uint move_limit) : base(move_limit) { }
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_ast_map_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_ast_map_dec_ref(ctx.nCtx, obj);
|
||||
}
|
||||
};
|
||||
|
||||
internal override void IncRef(IntPtr o)
|
||||
{
|
||||
Context.ASTMap_DRQ.IncAndClear(Context, o);
|
||||
base.IncRef(o);
|
||||
Native.Z3_ast_map_inc_ref(Context.nCtx, o);
|
||||
}
|
||||
|
||||
internal override void DecRef(IntPtr o)
|
||||
{
|
||||
Context.ASTMap_DRQ.Add(o);
|
||||
base.DecRef(o);
|
||||
lock (Context)
|
||||
{
|
||||
if (Context.nCtx != IntPtr.Zero)
|
||||
Native.Z3_ast_map_dec_ref(Context.nCtx, o);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -233,31 +233,19 @@ namespace Microsoft.Z3
|
|||
internal ASTVector(Context ctx, IntPtr obj) : base(ctx, obj) { Debug.Assert(ctx != null); }
|
||||
internal ASTVector(Context ctx) : base(ctx, Native.Z3_mk_ast_vector(ctx.nCtx)) { Debug.Assert(ctx != null); }
|
||||
|
||||
internal class DecRefQueue : IDecRefQueue
|
||||
{
|
||||
public DecRefQueue() : base() { }
|
||||
public DecRefQueue(uint move_limit) : base(move_limit) { }
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_ast_vector_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_ast_vector_dec_ref(ctx.nCtx, obj);
|
||||
}
|
||||
};
|
||||
|
||||
internal override void IncRef(IntPtr o)
|
||||
{
|
||||
Context.ASTVector_DRQ.IncAndClear(Context, o);
|
||||
base.IncRef(o);
|
||||
Native.Z3_ast_vector_inc_ref(Context.nCtx, o);
|
||||
}
|
||||
|
||||
internal override void DecRef(IntPtr o)
|
||||
{
|
||||
Context.ASTVector_DRQ.Add(o);
|
||||
base.DecRef(o);
|
||||
lock (Context)
|
||||
{
|
||||
if (Context.nCtx != IntPtr.Zero)
|
||||
Native.Z3_ast_vector_dec_ref(Context.nCtx, o);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -67,31 +67,18 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(ctx != null);
|
||||
}
|
||||
|
||||
internal class DecRefQueue : IDecRefQueue
|
||||
{
|
||||
public DecRefQueue() : base() { }
|
||||
public DecRefQueue(uint move_limit) : base(move_limit) { }
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_apply_result_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_apply_result_dec_ref(ctx.nCtx, obj);
|
||||
}
|
||||
};
|
||||
|
||||
internal override void IncRef(IntPtr o)
|
||||
{
|
||||
Context.ApplyResult_DRQ.IncAndClear(Context, o);
|
||||
base.IncRef(o);
|
||||
Native.Z3_apply_result_inc_ref(Context.nCtx, o);
|
||||
}
|
||||
|
||||
internal override void DecRef(IntPtr o)
|
||||
{
|
||||
Context.ApplyResult_DRQ.Add(o);
|
||||
base.DecRef(o);
|
||||
lock(Context)
|
||||
{
|
||||
if (Context.nCtx != IntPtr.Zero)
|
||||
Native.Z3_apply_result_dec_ref(Context.nCtx, o);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -59,7 +59,6 @@ set(Z3_DOTNET_ASSEMBLY_SOURCES_IN_SRC_TREE
|
|||
Context.cs
|
||||
DatatypeExpr.cs
|
||||
DatatypeSort.cs
|
||||
Deprecated.cs
|
||||
EnumSort.cs
|
||||
Expr.cs
|
||||
FiniteDomainExpr.cs
|
||||
|
@ -76,7 +75,6 @@ set(Z3_DOTNET_ASSEMBLY_SOURCES_IN_SRC_TREE
|
|||
FuncInterp.cs
|
||||
Global.cs
|
||||
Goal.cs
|
||||
IDecRefQueue.cs
|
||||
IntExpr.cs
|
||||
IntNum.cs
|
||||
IntSort.cs
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace Microsoft.Z3
|
|||
lock (creation_lock)
|
||||
{
|
||||
m_ctx = Native.Z3_mk_context_rc(IntPtr.Zero);
|
||||
Native.Z3_enable_concurrent_dec_ref(m_ctx);
|
||||
InitContext();
|
||||
}
|
||||
}
|
||||
|
@ -75,6 +76,7 @@ namespace Microsoft.Z3
|
|||
foreach (KeyValuePair<string, string> kv in settings)
|
||||
Native.Z3_set_param_value(cfg, kv.Key, kv.Value);
|
||||
m_ctx = Native.Z3_mk_context_rc(cfg);
|
||||
Native.Z3_enable_concurrent_dec_ref(m_ctx);
|
||||
Native.Z3_del_config(cfg);
|
||||
InitContext();
|
||||
}
|
||||
|
@ -124,7 +126,7 @@ namespace Microsoft.Z3
|
|||
/// </summary>
|
||||
internal Symbol[] MkSymbols(string[] names)
|
||||
{
|
||||
if (names == null) return null;
|
||||
if (names == null) return new Symbol[0];
|
||||
Symbol[] result = new Symbol[names.Length];
|
||||
for (int i = 0; i < names.Length; ++i) result[i] = MkSymbol(names[i]);
|
||||
return result;
|
||||
|
@ -4793,7 +4795,6 @@ namespace Microsoft.Z3
|
|||
PrintMode = Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT;
|
||||
m_n_err_handler = new Native.Z3_error_handler(NativeErrorHandler); // keep reference so it doesn't get collected.
|
||||
Native.Z3_set_error_handler(m_ctx, m_n_err_handler);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
internal void CheckContextMatch(Z3Object other)
|
||||
|
@ -4852,123 +4853,9 @@ namespace Microsoft.Z3
|
|||
|
||||
private void ObjectInvariant()
|
||||
{
|
||||
Debug.Assert(m_AST_DRQ != null);
|
||||
Debug.Assert(m_ASTMap_DRQ != null);
|
||||
Debug.Assert(m_ASTVector_DRQ != null);
|
||||
Debug.Assert(m_ApplyResult_DRQ != null);
|
||||
Debug.Assert(m_FuncEntry_DRQ != null);
|
||||
Debug.Assert(m_FuncInterp_DRQ != null);
|
||||
Debug.Assert(m_Goal_DRQ != null);
|
||||
Debug.Assert(m_Model_DRQ != null);
|
||||
Debug.Assert(m_Params_DRQ != null);
|
||||
Debug.Assert(m_ParamDescrs_DRQ != null);
|
||||
Debug.Assert(m_Probe_DRQ != null);
|
||||
Debug.Assert(m_Solver_DRQ != null);
|
||||
Debug.Assert(m_Statistics_DRQ != null);
|
||||
Debug.Assert(m_Tactic_DRQ != null);
|
||||
Debug.Assert(m_Fixedpoint_DRQ != null);
|
||||
Debug.Assert(m_Optimize_DRQ != null);
|
||||
// none
|
||||
}
|
||||
|
||||
readonly private AST.DecRefQueue m_AST_DRQ = new AST.DecRefQueue();
|
||||
readonly private ASTMap.DecRefQueue m_ASTMap_DRQ = new ASTMap.DecRefQueue(10);
|
||||
readonly private ASTVector.DecRefQueue m_ASTVector_DRQ = new ASTVector.DecRefQueue(10);
|
||||
readonly private ApplyResult.DecRefQueue m_ApplyResult_DRQ = new ApplyResult.DecRefQueue(10);
|
||||
readonly private FuncInterp.Entry.DecRefQueue m_FuncEntry_DRQ = new FuncInterp.Entry.DecRefQueue(10);
|
||||
readonly private FuncInterp.DecRefQueue m_FuncInterp_DRQ = new FuncInterp.DecRefQueue(10);
|
||||
readonly private Goal.DecRefQueue m_Goal_DRQ = new Goal.DecRefQueue(10);
|
||||
readonly private Model.DecRefQueue m_Model_DRQ = new Model.DecRefQueue(10);
|
||||
readonly private Params.DecRefQueue m_Params_DRQ = new Params.DecRefQueue(10);
|
||||
readonly private ParamDescrs.DecRefQueue m_ParamDescrs_DRQ = new ParamDescrs.DecRefQueue(10);
|
||||
readonly private Probe.DecRefQueue m_Probe_DRQ = new Probe.DecRefQueue(10);
|
||||
readonly private Solver.DecRefQueue m_Solver_DRQ = new Solver.DecRefQueue(10);
|
||||
readonly private Statistics.DecRefQueue m_Statistics_DRQ = new Statistics.DecRefQueue(10);
|
||||
readonly private Tactic.DecRefQueue m_Tactic_DRQ = new Tactic.DecRefQueue(10);
|
||||
readonly private Fixedpoint.DecRefQueue m_Fixedpoint_DRQ = new Fixedpoint.DecRefQueue(10);
|
||||
readonly private Optimize.DecRefQueue m_Optimize_DRQ = new Optimize.DecRefQueue(10);
|
||||
|
||||
/// <summary>
|
||||
/// AST DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue AST_DRQ { get { return m_AST_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// ASTMap DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue ASTMap_DRQ { get { return m_ASTMap_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// ASTVector DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue ASTVector_DRQ { get { return m_ASTVector_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// ApplyResult DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue ApplyResult_DRQ { get { return m_ApplyResult_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// FuncEntry DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue FuncEntry_DRQ { get { return m_FuncEntry_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// FuncInterp DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue FuncInterp_DRQ { get { return m_FuncInterp_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// Goal DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue Goal_DRQ { get { return m_Goal_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// Model DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue Model_DRQ { get { return m_Model_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// Params DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue Params_DRQ { get { return m_Params_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// ParamDescrs DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue ParamDescrs_DRQ { get { return m_ParamDescrs_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// Probe DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue Probe_DRQ { get { return m_Probe_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// Solver DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue Solver_DRQ { get { return m_Solver_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// Statistics DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue Statistics_DRQ { get { return m_Statistics_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// Tactic DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue Tactic_DRQ { get { return m_Tactic_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// FixedPoint DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue Fixedpoint_DRQ { get { return m_Fixedpoint_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// Optimize DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue Optimize_DRQ { get { return m_Fixedpoint_DRQ; } }
|
||||
|
||||
internal long refCount = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Finalizer.
|
||||
/// </summary>
|
||||
|
@ -4984,22 +4871,6 @@ namespace Microsoft.Z3
|
|||
public void Dispose()
|
||||
{
|
||||
// Console.WriteLine("Context Dispose from " + System.Threading.Thread.CurrentThread.ManagedThreadId);
|
||||
AST_DRQ.Clear(this);
|
||||
ASTMap_DRQ.Clear(this);
|
||||
ASTVector_DRQ.Clear(this);
|
||||
ApplyResult_DRQ.Clear(this);
|
||||
FuncEntry_DRQ.Clear(this);
|
||||
FuncInterp_DRQ.Clear(this);
|
||||
Goal_DRQ.Clear(this);
|
||||
Model_DRQ.Clear(this);
|
||||
Params_DRQ.Clear(this);
|
||||
ParamDescrs_DRQ.Clear(this);
|
||||
Probe_DRQ.Clear(this);
|
||||
Solver_DRQ.Clear(this);
|
||||
Statistics_DRQ.Clear(this);
|
||||
Tactic_DRQ.Clear(this);
|
||||
Fixedpoint_DRQ.Clear(this);
|
||||
Optimize_DRQ.Clear(this);
|
||||
|
||||
if (m_boolSort != null) m_boolSort.Dispose();
|
||||
if (m_intSort != null) m_intSort.Dispose();
|
||||
|
@ -5011,16 +4882,19 @@ namespace Microsoft.Z3
|
|||
m_realSort = null;
|
||||
m_stringSort = null;
|
||||
m_charSort = null;
|
||||
if (refCount == 0 && m_ctx != IntPtr.Zero)
|
||||
if (m_ctx != IntPtr.Zero)
|
||||
{
|
||||
m_n_err_handler = null;
|
||||
IntPtr ctx = m_ctx;
|
||||
m_ctx = IntPtr.Zero;
|
||||
if (!is_external)
|
||||
Native.Z3_del_context(ctx);
|
||||
lock (this)
|
||||
{
|
||||
m_n_err_handler = null;
|
||||
m_ctx = IntPtr.Zero;
|
||||
}
|
||||
if (!is_external)
|
||||
Native.Z3_del_context(ctx);
|
||||
}
|
||||
else
|
||||
GC.ReRegisterForFinalize(this);
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
Deprecated.cs
|
||||
|
||||
Abstract:
|
||||
|
||||
Expose deprecated features for use from the managed API
|
||||
those who use them for experiments.
|
||||
|
||||
Author:
|
||||
|
||||
Christoph Wintersteiger (cwinter) 2012-03-15
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
using System.Diagnostics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Z3
|
||||
{
|
||||
/// <summary>
|
||||
/// The main interaction with Z3 happens via the Context.
|
||||
/// </summary>
|
||||
public class Deprecated
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -318,31 +318,18 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(ctx != null);
|
||||
}
|
||||
|
||||
internal class DecRefQueue : IDecRefQueue
|
||||
{
|
||||
public DecRefQueue() : base() { }
|
||||
public DecRefQueue(uint move_limit) : base(move_limit) { }
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_fixedpoint_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_fixedpoint_dec_ref(ctx.nCtx, obj);
|
||||
}
|
||||
};
|
||||
|
||||
internal override void IncRef(IntPtr o)
|
||||
{
|
||||
Context.Fixedpoint_DRQ.IncAndClear(Context, o);
|
||||
base.IncRef(o);
|
||||
Native.Z3_fixedpoint_inc_ref(Context.nCtx, o);
|
||||
}
|
||||
|
||||
internal override void DecRef(IntPtr o)
|
||||
{
|
||||
Context.Fixedpoint_DRQ.Add(o);
|
||||
base.DecRef(o);
|
||||
lock (Context)
|
||||
{
|
||||
if (Context.nCtx != IntPtr.Zero)
|
||||
Native.Z3_fixedpoint_dec_ref(Context.nCtx, o);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -85,31 +85,18 @@ namespace Microsoft.Z3
|
|||
#region Internal
|
||||
internal Entry(Context ctx, IntPtr obj) : base(ctx, obj) { Debug.Assert(ctx != null); }
|
||||
|
||||
internal class DecRefQueue : IDecRefQueue
|
||||
{
|
||||
public DecRefQueue() : base() { }
|
||||
public DecRefQueue(uint move_limit) : base(move_limit) { }
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_func_entry_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_func_entry_dec_ref(ctx.nCtx, obj);
|
||||
}
|
||||
};
|
||||
|
||||
internal override void IncRef(IntPtr o)
|
||||
{
|
||||
Context.FuncEntry_DRQ.IncAndClear(Context, o);
|
||||
base.IncRef(o);
|
||||
Native.Z3_func_entry_inc_ref(Context.nCtx, o);
|
||||
}
|
||||
|
||||
internal override void DecRef(IntPtr o)
|
||||
{
|
||||
Context.FuncEntry_DRQ.Add(o);
|
||||
base.DecRef(o);
|
||||
lock (Context)
|
||||
{
|
||||
if (Context.nCtx != IntPtr.Zero)
|
||||
Native.Z3_func_entry_dec_ref(Context.nCtx, o);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
};
|
||||
|
@ -190,31 +177,18 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(ctx != null);
|
||||
}
|
||||
|
||||
internal class DecRefQueue : IDecRefQueue
|
||||
{
|
||||
public DecRefQueue() : base() { }
|
||||
public DecRefQueue(uint move_limit) : base(move_limit) { }
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_func_interp_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_func_interp_dec_ref(ctx.nCtx, obj);
|
||||
}
|
||||
};
|
||||
|
||||
internal override void IncRef(IntPtr o)
|
||||
{
|
||||
Context.FuncInterp_DRQ.IncAndClear(Context, o);
|
||||
base.IncRef(o);
|
||||
Native.Z3_func_interp_inc_ref(Context.nCtx, o);
|
||||
}
|
||||
|
||||
internal override void DecRef(IntPtr o)
|
||||
{
|
||||
Context.FuncInterp_DRQ.Add(o);
|
||||
base.DecRef(o);
|
||||
lock (Context)
|
||||
{
|
||||
if (Context.nCtx != IntPtr.Zero)
|
||||
Native.Z3_func_interp_dec_ref(Context.nCtx, o);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -252,33 +252,20 @@ namespace Microsoft.Z3
|
|||
: base(ctx, Native.Z3_mk_goal(ctx.nCtx, (byte)(models ? 1 : 0), (byte)(unsatCores ? 1 : 0), (byte)(proofs ? 1 : 0)))
|
||||
{
|
||||
Debug.Assert(ctx != null);
|
||||
}
|
||||
|
||||
internal class DecRefQueue : IDecRefQueue
|
||||
{
|
||||
public DecRefQueue() : base() { }
|
||||
public DecRefQueue(uint move_limit) : base(move_limit) { }
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_goal_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_goal_dec_ref(ctx.nCtx, obj);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
internal override void IncRef(IntPtr o)
|
||||
{
|
||||
Context.Goal_DRQ.IncAndClear(Context, o);
|
||||
base.IncRef(o);
|
||||
Native.Z3_goal_inc_ref(Context.nCtx, o);
|
||||
}
|
||||
|
||||
internal override void DecRef(IntPtr o)
|
||||
{
|
||||
Context.Goal_DRQ.Add(o);
|
||||
base.DecRef(o);
|
||||
lock (Context)
|
||||
{
|
||||
if (Context.nCtx != IntPtr.Zero)
|
||||
Native.Z3_goal_dec_ref(Context.nCtx, o);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -1,103 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
DecRefQueue.cs
|
||||
|
||||
Abstract:
|
||||
|
||||
Z3 Managed API: DecRef Queues
|
||||
|
||||
Author:
|
||||
|
||||
Christoph Wintersteiger (cwinter) 2012-03-16
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
|
||||
using System.Diagnostics;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.Z3
|
||||
{
|
||||
/// <summary>
|
||||
/// DecRefQueue interface
|
||||
/// </summary>
|
||||
public abstract class IDecRefQueue
|
||||
{
|
||||
#region Object invariant
|
||||
|
||||
private void ObjectInvariant()
|
||||
{
|
||||
Debug.Assert(this.m_queue != null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
readonly private Object m_lock = new Object();
|
||||
readonly private List<IntPtr> m_queue = new List<IntPtr>();
|
||||
private uint m_move_limit;
|
||||
|
||||
internal IDecRefQueue(uint move_limit = 1024)
|
||||
{
|
||||
m_move_limit = move_limit;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the limit on numbers of objects that are kept back at GC collection.
|
||||
/// </summary>
|
||||
/// <param name="l"></param>
|
||||
public void SetLimit(uint l) { m_move_limit = l; }
|
||||
|
||||
internal abstract void IncRef(Context ctx, IntPtr obj);
|
||||
internal abstract void DecRef(Context ctx, IntPtr obj);
|
||||
|
||||
internal void IncAndClear(Context ctx, IntPtr o)
|
||||
{
|
||||
Debug.Assert(ctx != null);
|
||||
|
||||
IncRef(ctx, o);
|
||||
if (m_queue.Count >= m_move_limit) Clear(ctx);
|
||||
}
|
||||
|
||||
internal void Add(IntPtr o)
|
||||
{
|
||||
if (o == IntPtr.Zero) return;
|
||||
|
||||
lock (m_lock)
|
||||
{
|
||||
m_queue.Add(o);
|
||||
}
|
||||
}
|
||||
|
||||
internal void Clear(Context ctx)
|
||||
{
|
||||
Debug.Assert(ctx != null);
|
||||
|
||||
lock (m_lock)
|
||||
{
|
||||
foreach (IntPtr o in m_queue)
|
||||
DecRef(ctx, o);
|
||||
m_queue.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class DecRefQueueContracts : IDecRefQueue
|
||||
{
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Debug.Assert(ctx != null);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Debug.Assert(ctx != null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -302,33 +302,20 @@ namespace Microsoft.Z3
|
|||
: base(ctx, obj)
|
||||
{
|
||||
Debug.Assert(ctx != null);
|
||||
}
|
||||
|
||||
internal class DecRefQueue : IDecRefQueue
|
||||
{
|
||||
public DecRefQueue() : base() { }
|
||||
public DecRefQueue(uint move_limit) : base(move_limit) { }
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_model_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_model_dec_ref(ctx.nCtx, obj);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
internal override void IncRef(IntPtr o)
|
||||
{
|
||||
Context.Model_DRQ.IncAndClear(Context, o);
|
||||
base.IncRef(o);
|
||||
Native.Z3_model_inc_ref(Context.nCtx, o);
|
||||
}
|
||||
|
||||
internal override void DecRef(IntPtr o)
|
||||
{
|
||||
Context.Model_DRQ.Add(o);
|
||||
base.DecRef(o);
|
||||
lock (Context)
|
||||
{
|
||||
if (Context.nCtx != IntPtr.Zero)
|
||||
Native.Z3_model_dec_ref(Context.nCtx, o);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -440,31 +440,18 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(ctx != null);
|
||||
}
|
||||
|
||||
internal class DecRefQueue : IDecRefQueue
|
||||
{
|
||||
public DecRefQueue() : base() { }
|
||||
public DecRefQueue(uint move_limit) : base(move_limit) { }
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_optimize_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_optimize_dec_ref(ctx.nCtx, obj);
|
||||
}
|
||||
};
|
||||
|
||||
internal override void IncRef(IntPtr o)
|
||||
{
|
||||
Context.Optimize_DRQ.IncAndClear(Context, o);
|
||||
base.IncRef(o);
|
||||
Native.Z3_optimize_inc_ref(Context.nCtx, o);
|
||||
}
|
||||
|
||||
internal override void DecRef(IntPtr o)
|
||||
{
|
||||
Context.Optimize_DRQ.Add(o);
|
||||
base.DecRef(o);
|
||||
lock (Context)
|
||||
{
|
||||
if (Context.nCtx != IntPtr.Zero)
|
||||
Native.Z3_optimize_dec_ref(Context.nCtx, o);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -91,33 +91,20 @@ namespace Microsoft.Z3
|
|||
: base(ctx, obj)
|
||||
{
|
||||
Debug.Assert(ctx != null);
|
||||
}
|
||||
|
||||
internal class DecRefQueue : IDecRefQueue
|
||||
{
|
||||
public DecRefQueue() : base() { }
|
||||
public DecRefQueue(uint move_limit) : base(move_limit) { }
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_param_descrs_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_param_descrs_dec_ref(ctx.nCtx, obj);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
internal override void IncRef(IntPtr o)
|
||||
{
|
||||
Context.ParamDescrs_DRQ.IncAndClear(Context, o);
|
||||
base.IncRef(o);
|
||||
Native.Z3_param_descrs_inc_ref(Context.nCtx, o);
|
||||
}
|
||||
|
||||
internal override void DecRef(IntPtr o)
|
||||
{
|
||||
Context.ParamDescrs_DRQ.Add(o);
|
||||
base.DecRef(o);
|
||||
lock (Context)
|
||||
{
|
||||
if (Context.nCtx != IntPtr.Zero)
|
||||
Native.Z3_param_descrs_dec_ref(Context.nCtx, o);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -147,33 +147,20 @@ namespace Microsoft.Z3
|
|||
: base(ctx, Native.Z3_mk_params(ctx.nCtx))
|
||||
{
|
||||
Debug.Assert(ctx != null);
|
||||
}
|
||||
|
||||
internal class DecRefQueue : IDecRefQueue
|
||||
{
|
||||
public DecRefQueue() : base() { }
|
||||
public DecRefQueue(uint move_limit) : base(move_limit) { }
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_params_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_params_dec_ref(ctx.nCtx, obj);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
internal override void IncRef(IntPtr o)
|
||||
{
|
||||
Context.Params_DRQ.IncAndClear(Context, o);
|
||||
base.IncRef(o);
|
||||
Native.Z3_params_inc_ref(Context.nCtx, o);
|
||||
}
|
||||
|
||||
internal override void DecRef(IntPtr o)
|
||||
{
|
||||
Context.Params_DRQ.Add(o);
|
||||
base.DecRef(o);
|
||||
lock (Context)
|
||||
{
|
||||
if (Context.nCtx != IntPtr.Zero)
|
||||
Native.Z3_params_dec_ref(Context.nCtx, o);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -70,31 +70,18 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(ctx != null);
|
||||
}
|
||||
|
||||
internal class DecRefQueue : IDecRefQueue
|
||||
{
|
||||
public DecRefQueue() : base() { }
|
||||
public DecRefQueue(uint move_limit) : base(move_limit) { }
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_probe_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_probe_dec_ref(ctx.nCtx, obj);
|
||||
}
|
||||
};
|
||||
|
||||
internal override void IncRef(IntPtr o)
|
||||
{
|
||||
Context.Probe_DRQ.IncAndClear(Context, o);
|
||||
base.IncRef(o);
|
||||
Native.Z3_probe_inc_ref(Context.nCtx, o);
|
||||
}
|
||||
|
||||
internal override void DecRef(IntPtr o)
|
||||
{
|
||||
Context.Probe_DRQ.Add(o);
|
||||
base.DecRef(o);
|
||||
lock (Context)
|
||||
{
|
||||
if (Context.nCtx != IntPtr.Zero)
|
||||
Native.Z3_probe_dec_ref(Context.nCtx, o);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -538,31 +538,18 @@ namespace Microsoft.Z3
|
|||
this.BacktrackLevel = uint.MaxValue;
|
||||
}
|
||||
|
||||
internal class DecRefQueue : IDecRefQueue
|
||||
{
|
||||
public DecRefQueue() : base() { }
|
||||
public DecRefQueue(uint move_limit) : base(move_limit) { }
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_solver_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_solver_dec_ref(ctx.nCtx, obj);
|
||||
}
|
||||
};
|
||||
|
||||
internal override void IncRef(IntPtr o)
|
||||
{
|
||||
Context.Solver_DRQ.IncAndClear(Context, o);
|
||||
base.IncRef(o);
|
||||
Native.Z3_solver_inc_ref(Context.nCtx, o);
|
||||
}
|
||||
|
||||
internal override void DecRef(IntPtr o)
|
||||
{
|
||||
Context.Solver_DRQ.Add(o);
|
||||
base.DecRef(o);
|
||||
lock (Context)
|
||||
{
|
||||
if (Context.nCtx != IntPtr.Zero)
|
||||
Native.Z3_solver_dec_ref(Context.nCtx, o);
|
||||
}
|
||||
}
|
||||
|
||||
private Status lboolToStatus(Z3_lbool r)
|
||||
|
|
|
@ -19,8 +19,6 @@ Notes:
|
|||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
|
||||
namespace Microsoft.Z3
|
||||
{
|
||||
|
||||
|
@ -189,31 +187,18 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(ctx != null);
|
||||
}
|
||||
|
||||
internal class DecRefQueue : IDecRefQueue
|
||||
{
|
||||
public DecRefQueue() : base() { }
|
||||
public DecRefQueue(uint move_limit) : base(move_limit) { }
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_stats_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_stats_dec_ref(ctx.nCtx, obj);
|
||||
}
|
||||
};
|
||||
|
||||
internal override void IncRef(IntPtr o)
|
||||
{
|
||||
Context.Statistics_DRQ.IncAndClear(Context, o);
|
||||
base.IncRef(o);
|
||||
Native.Z3_stats_inc_ref(Context.nCtx, o);
|
||||
}
|
||||
|
||||
internal override void DecRef(IntPtr o)
|
||||
{
|
||||
Context.Statistics_DRQ.Add(o);
|
||||
base.DecRef(o);
|
||||
lock (Context)
|
||||
{
|
||||
if (Context.nCtx != IntPtr.Zero)
|
||||
Native.Z3_stats_dec_ref(Context.nCtx, o);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -107,34 +107,18 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(ctx != null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DecRefQueue
|
||||
/// </summary>
|
||||
internal class DecRefQueue : IDecRefQueue
|
||||
{
|
||||
public DecRefQueue() : base() { }
|
||||
public DecRefQueue(uint move_limit) : base(move_limit) { }
|
||||
internal override void IncRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_tactic_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
internal override void DecRef(Context ctx, IntPtr obj)
|
||||
{
|
||||
Native.Z3_tactic_dec_ref(ctx.nCtx, obj);
|
||||
}
|
||||
};
|
||||
|
||||
internal override void IncRef(IntPtr o)
|
||||
{
|
||||
Context.Tactic_DRQ.IncAndClear(Context, o);
|
||||
base.IncRef(o);
|
||||
Native.Z3_tactic_inc_ref(Context.nCtx, o);
|
||||
}
|
||||
|
||||
internal override void DecRef(IntPtr o)
|
||||
{
|
||||
Context.Tactic_DRQ.Add(o);
|
||||
base.DecRef(o);
|
||||
lock (Context)
|
||||
{
|
||||
if (Context.nCtx != IntPtr.Zero)
|
||||
Native.Z3_tactic_dec_ref(Context.nCtx, o);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Propagator context for .Net
|
||||
/// </summary>
|
||||
public class UserPropagator
|
||||
public class UserPropagator : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Delegate type for fixed callback
|
||||
|
@ -71,6 +71,7 @@ namespace Microsoft.Z3
|
|||
Solver solver;
|
||||
Context ctx;
|
||||
Z3_solver_callback callback = IntPtr.Zero;
|
||||
int callbackNesting = 0;
|
||||
FixedEh fixed_eh;
|
||||
Action final_eh;
|
||||
EqEh eq_eh;
|
||||
|
@ -91,6 +92,7 @@ namespace Microsoft.Z3
|
|||
|
||||
void Callback(Action fn, Z3_solver_callback cb)
|
||||
{
|
||||
this.callbackNesting++;
|
||||
this.callback = cb;
|
||||
try
|
||||
{
|
||||
|
@ -102,7 +104,9 @@ namespace Microsoft.Z3
|
|||
}
|
||||
finally
|
||||
{
|
||||
this.callback = IntPtr.Zero;
|
||||
callbackNesting--;
|
||||
if (callbackNesting == 0) // callbacks can be nested (e.g., internalizing new element in "created")
|
||||
this.callback = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,10 +205,20 @@ namespace Microsoft.Z3
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release provate memory.
|
||||
/// Release private memory.
|
||||
/// </summary>
|
||||
~UserPropagator()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Must be called. The object will not be garbage collected automatically even if the context is disposed
|
||||
/// </summary>
|
||||
public virtual void Dispose()
|
||||
{
|
||||
if (!gch.IsAllocated)
|
||||
return;
|
||||
gch.Free();
|
||||
if (solver == null)
|
||||
ctx.Dispose();
|
||||
|
|
|
@ -50,12 +50,7 @@ namespace Microsoft.Z3
|
|||
m_n_obj = IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (m_ctx != null)
|
||||
{
|
||||
if (Interlocked.Decrement(ref m_ctx.refCount) == 0)
|
||||
GC.ReRegisterForFinalize(m_ctx);
|
||||
m_ctx = null;
|
||||
}
|
||||
m_ctx = null;
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
@ -76,19 +71,15 @@ namespace Microsoft.Z3
|
|||
internal Z3Object(Context ctx)
|
||||
{
|
||||
Debug.Assert(ctx != null);
|
||||
|
||||
Interlocked.Increment(ref ctx.refCount);
|
||||
m_ctx = ctx;
|
||||
}
|
||||
|
||||
internal Z3Object(Context ctx, IntPtr obj)
|
||||
{
|
||||
Debug.Assert(ctx != null);
|
||||
|
||||
Interlocked.Increment(ref ctx.refCount);
|
||||
m_ctx = ctx;
|
||||
IncRef(obj);
|
||||
m_n_obj = obj;
|
||||
IncRef(obj);
|
||||
}
|
||||
|
||||
internal virtual void IncRef(IntPtr o) { }
|
||||
|
@ -109,7 +100,7 @@ namespace Microsoft.Z3
|
|||
|
||||
internal static IntPtr GetNativeObject(Z3Object s)
|
||||
{
|
||||
if (s == null) return new IntPtr();
|
||||
if (s == null) return IntPtr.Zero;
|
||||
return s.NativeObject;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,18 @@ public class ArraySort<D extends Sort, R extends Sort> extends Sort
|
|||
Native.getArraySortDomain(getContext().nCtx(), getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* The domain of a multi-dimensional array sort.
|
||||
* @throws Z3Exception
|
||||
* @throws Z3Exception on error
|
||||
* @return a sort
|
||||
**/
|
||||
public D getDomain(int idx)
|
||||
{
|
||||
return (D) Sort.create(getContext(),
|
||||
Native.getArraySortDomainN(getContext().nCtx(), getNativeObject(), idx));
|
||||
}
|
||||
|
||||
/**
|
||||
* The range of the array sort.
|
||||
* @throws Z3Exception
|
||||
|
|
|
@ -110,7 +110,7 @@ public class Context implements AutoCloseable {
|
|||
Symbol[] mkSymbols(String[] names)
|
||||
{
|
||||
if (names == null)
|
||||
return null;
|
||||
return new Symbol[0];
|
||||
Symbol[] result = new Symbol[names.length];
|
||||
for (int i = 0; i < names.length; ++i)
|
||||
result[i] = mkSymbol(names[i]);
|
||||
|
|
|
@ -8,7 +8,7 @@ import { Arith, Bool, Model, Z3AssertionError, Z3HighLevel } from './types';
|
|||
*
|
||||
* **NOTE**: The set of solutions might be infinite.
|
||||
* Always ensure to limit amount generated, either by knowing that the
|
||||
* solution space is constrainted, or by taking only a specified
|
||||
* solution space is constrained, or by taking only a specified
|
||||
* amount of solutions
|
||||
* ```typescript
|
||||
* import { sliceAsync } from 'iter-tools';
|
||||
|
@ -46,7 +46,7 @@ async function* allSolutions<Name extends string>(...assertions: Bool<Name>[]):
|
|||
.filter(decl => decl.arity() === 0)
|
||||
.map(decl => {
|
||||
const term = decl.call();
|
||||
// TODO(ritave): Assert not an array / uinterpeted sort
|
||||
// TODO(ritave): Assert not an array / uninterpreted sort
|
||||
const value = model.eval(term, true);
|
||||
return term.neq(value);
|
||||
}),
|
||||
|
@ -109,6 +109,16 @@ describe('high-level', () => {
|
|||
expect(await solver.check()).toStrictEqual('unsat');
|
||||
});
|
||||
|
||||
it('test loading a solver state from a string', async () => {
|
||||
const { Solver, Not, Int } = api.Context('main');
|
||||
const solver = new Solver();
|
||||
solver.fromString("(declare-const x Int) (assert (and (< x 2) (> x 0)))")
|
||||
expect(await solver.check()).toStrictEqual('sat')
|
||||
const x = Int.const('x')
|
||||
solver.add(Not(x.eq(1)))
|
||||
expect(await solver.check()).toStrictEqual('unsat')
|
||||
});
|
||||
|
||||
it('disproves x = y implies g(g(x)) = g(y)', async () => {
|
||||
const { Solver, Int, Function, Implies, Not } = api.Context('main');
|
||||
const solver = new Solver();
|
||||
|
|
|
@ -224,6 +224,12 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
|||
function _toExpr(ast: Z3_ast): Bool<Name> | IntNum<Name> | RatNum<Name> | Arith<Name> | Expr<Name> {
|
||||
const kind = check(Z3.get_ast_kind(contextPtr, ast));
|
||||
if (kind === Z3_ast_kind.Z3_QUANTIFIER_AST) {
|
||||
if (Z3.is_quantifier_forall(contextPtr, ast))
|
||||
return new BoolImpl(ast);
|
||||
if (Z3.is_quantifier_exists(contextPtr, ast))
|
||||
return new BoolImpl(ast);
|
||||
if (Z3.is_lambda(contextPtr, ast))
|
||||
return new ExprImpl(ast);
|
||||
assert(false);
|
||||
}
|
||||
const sortKind = check(Z3.get_sort_kind(contextPtr, Z3.get_sort(contextPtr, ast)));
|
||||
|
@ -1012,6 +1018,11 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
|||
toString() {
|
||||
return check(Z3.solver_to_string(contextPtr, this.ptr));
|
||||
}
|
||||
|
||||
fromString(s : string) {
|
||||
Z3.solver_from_string(contextPtr, this.ptr, s);
|
||||
throwIfError();
|
||||
}
|
||||
}
|
||||
|
||||
class ModelImpl implements Model<Name> {
|
||||
|
|
|
@ -398,6 +398,7 @@ export interface Solver<Name extends string = 'main'> {
|
|||
add(...exprs: (Bool<Name> | AstVector<Name, Bool<Name>>)[]): void;
|
||||
addAndTrack(expr: Bool<Name>, constant: Bool<Name> | string): void;
|
||||
assertions(): AstVector<Name, Bool<Name>>;
|
||||
fromString(s : string): void;
|
||||
check(...exprs: (Bool<Name> | AstVector<Name, Bool<Name>>)[]): Promise<CheckSatResult>;
|
||||
model(): Model<Name>;
|
||||
}
|
||||
|
@ -616,7 +617,7 @@ export interface Arith<Name extends string = 'main'> extends Expr<Name, ArithSor
|
|||
*/
|
||||
mul(other: Arith<Name> | number | bigint | string): Arith<Name>;
|
||||
/**
|
||||
* Substract second number from the first one
|
||||
* Subtract second number from the first one
|
||||
*/
|
||||
sub(other: Arith<Name> | number | bigint | string): Arith<Name>;
|
||||
/**
|
||||
|
@ -708,7 +709,7 @@ export interface RatNum<Name extends string = 'main'> extends Arith<Name> {
|
|||
}
|
||||
|
||||
/**
|
||||
* A Sort represting Bit Vector numbers of specified {@link BitVecSort.size size}
|
||||
* A Sort representing Bit Vector numbers of specified {@link BitVecSort.size size}
|
||||
*
|
||||
* @typeParam Bits - A number representing amount of bits for this sort
|
||||
* @category Bit Vectors
|
||||
|
@ -877,42 +878,42 @@ export interface BitVec<Bits extends number = number, Name extends string = 'mai
|
|||
|
||||
/**
|
||||
* Creates a signed less-or-equal operation (`<=`)
|
||||
* @category Comparision
|
||||
* @category Comparison
|
||||
*/
|
||||
sle(other: CoercibleToBitVec<Bits, Name>): Bool<Name>;
|
||||
/**
|
||||
* Creates an unsigned less-or-equal operation (`<=`)
|
||||
* @category Comparision
|
||||
* @category Comparison
|
||||
*/
|
||||
ule(other: CoercibleToBitVec<Bits, Name>): Bool<Name>;
|
||||
/**
|
||||
* Creates a signed less-than operation (`<`)
|
||||
* @category Comparision
|
||||
* @category Comparison
|
||||
*/
|
||||
slt(other: CoercibleToBitVec<Bits, Name>): Bool<Name>;
|
||||
/**
|
||||
* Creates an unsigned less-than operation (`<`)
|
||||
* @category Comparision
|
||||
* @category Comparison
|
||||
*/
|
||||
ult(other: CoercibleToBitVec<Bits, Name>): Bool<Name>;
|
||||
/**
|
||||
* Creates a signed greater-or-equal operation (`>=`)
|
||||
* @category Comparision
|
||||
* @category Comparison
|
||||
*/
|
||||
sge(other: CoercibleToBitVec<Bits, Name>): Bool<Name>;
|
||||
/**
|
||||
* Creates an unsigned greater-or-equal operation (`>=`)
|
||||
* @category Comparision
|
||||
* @category Comparison
|
||||
*/
|
||||
uge(other: CoercibleToBitVec<Bits, Name>): Bool<Name>;
|
||||
/**
|
||||
* Creates a signed greater-than operation (`>`)
|
||||
* @category Comparision
|
||||
* @category Comparison
|
||||
*/
|
||||
sgt(other: CoercibleToBitVec<Bits, Name>): Bool<Name>;
|
||||
/**
|
||||
* Creates an unsigned greater-than operation (`>`)
|
||||
* @category Comparision
|
||||
* @category Comparison
|
||||
*/
|
||||
ugt(other: CoercibleToBitVec<Bits, Name>): Bool<Name>;
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "jlcxx/jlcxx.hpp"
|
||||
#include <sstream>
|
||||
#include "z3++.h"
|
||||
|
||||
using namespace z3;
|
||||
|
|
|
@ -39,7 +39,7 @@ $ ldd ./run
|
|||
/lib64/ld-linux-x86-64.so.2 (0x00007fb570de9000)
|
||||
```
|
||||
|
||||
The bytecode version will have a depedency on z3 and other external
|
||||
The bytecode version will have a dependency on z3 and other external
|
||||
libraries (packed as dlls and usually installed in opam switch):
|
||||
```
|
||||
$ ocamlobjinfo run | grep 'Used DLL' -A5
|
||||
|
@ -126,7 +126,7 @@ Using Dynlink
|
|||
-------------
|
||||
|
||||
The built z3ml.cmxs file is a self-contained shared library that
|
||||
doesn't have any depndencies on z3 (the z3 code is included in it) and
|
||||
doesn't have any dependencies on z3 (the z3 code is included in it) and
|
||||
could be loaded with `Dynlink.loadfile` in runtime.
|
||||
|
||||
Installation
|
||||
|
|
|
@ -122,7 +122,7 @@ bool array_decl_plugin::is_array_sort(sort* s) const {
|
|||
|
||||
func_decl * array_decl_plugin::mk_const(sort * s, unsigned arity, sort * const * domain) {
|
||||
if (arity != 1) {
|
||||
m_manager->raise_exception("invalid const array definition, invalid domain size");
|
||||
m_manager->raise_exception("invalid const array definition, expected one argument");
|
||||
return nullptr;
|
||||
}
|
||||
if (!is_array_sort(s)) {
|
||||
|
@ -326,7 +326,9 @@ func_decl * array_decl_plugin::mk_array_ext(unsigned arity, sort * const * domai
|
|||
}
|
||||
sort * r = to_sort(s->get_parameter(i).get_ast());
|
||||
parameter param(i);
|
||||
return m_manager->mk_func_decl(m_array_ext_sym, arity, domain, r, func_decl_info(m_family_id, OP_ARRAY_EXT, 1, ¶m));
|
||||
func_decl_info info(func_decl_info(m_family_id, OP_ARRAY_EXT, 1, ¶m));
|
||||
info.set_commutative(true);
|
||||
return m_manager->mk_func_decl(m_array_ext_sym, arity, domain, r, info);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -178,6 +178,7 @@ public:
|
|||
bool is_default(expr* n) const { return is_app_of(n, m_fid, OP_ARRAY_DEFAULT); }
|
||||
bool is_subset(expr const* n) const { return is_app_of(n, m_fid, OP_SET_SUBSET); }
|
||||
bool is_as_array(func_decl* f, func_decl*& g) const { return is_decl_of(f, m_fid, OP_AS_ARRAY) && (g = get_as_array_func_decl(f), true); }
|
||||
bool is_map(func_decl* f, func_decl*& g) const { return is_map(f) && (g = get_map_func_decl(f), true); }
|
||||
func_decl * get_as_array_func_decl(expr * n) const;
|
||||
func_decl * get_as_array_func_decl(func_decl* f) const;
|
||||
func_decl * get_map_func_decl(func_decl* f) const;
|
||||
|
|
|
@ -889,8 +889,10 @@ void basic_decl_plugin::set_manager(ast_manager * m, family_id id) {
|
|||
}
|
||||
|
||||
void basic_decl_plugin::get_sort_names(svector<builtin_name> & sort_names, symbol const & logic) {
|
||||
if (logic == symbol::null)
|
||||
if (logic == symbol::null) {
|
||||
sort_names.push_back(builtin_name("bool", BOOL_SORT));
|
||||
sort_names.push_back(builtin_name("Proof", PROOF_SORT)); // reserved name?
|
||||
}
|
||||
sort_names.push_back(builtin_name("Bool", BOOL_SORT));
|
||||
}
|
||||
|
||||
|
@ -3025,11 +3027,23 @@ proof * ast_manager::mk_unit_resolution(unsigned num_proofs, proof * const * pro
|
|||
found_complement = true;
|
||||
}
|
||||
}
|
||||
// patch to deal with lambdas introduced during search.
|
||||
// lambdas can occur in terms both internalized and in raw form.
|
||||
if (!found_complement && !is_or(f1) && num_proofs == 2) {
|
||||
args.push_back(proofs[0]);
|
||||
args.push_back(proofs[1]);
|
||||
args.push_back(mk_false());
|
||||
found_complement = true;
|
||||
}
|
||||
|
||||
if (!found_complement) {
|
||||
args.append(num_proofs, (expr**)proofs);
|
||||
CTRACE("mk_unit_resolution_bug", !is_or(f1), tout << mk_ll_pp(f1, *this) << "\n";
|
||||
for (unsigned i = 1; i < num_proofs; ++i)
|
||||
tout << mk_pp(proofs[i], *this) << "\n";
|
||||
tout << "facts\n";
|
||||
for (unsigned i = 0; i < num_proofs; ++i)
|
||||
tout << mk_pp(get_fact(proofs[i]), *this) << "\n";
|
||||
);
|
||||
SASSERT(is_or(f1));
|
||||
ptr_buffer<expr> new_lits;
|
||||
|
|
|
@ -531,6 +531,13 @@ public:
|
|||
#endif
|
||||
};
|
||||
|
||||
#define MATCH_QUATARY(_MATCHER_) \
|
||||
bool _MATCHER_(expr const* n, expr*& a1, expr*& a2, expr *& a3, expr *& a4) const { \
|
||||
if (_MATCHER_(n) && to_app(n)->get_num_args() == 4) { \
|
||||
a1 = to_app(n)->get_arg(0); a2 = to_app(n)->get_arg(1); a3 = to_app(n)->get_arg(2); a4 = to_app(n)->get_arg(3); return true; } \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define MATCH_TERNARY(_MATCHER_) \
|
||||
bool _MATCHER_(expr const* n, expr*& a1, expr*& a2, expr *& a3) const { \
|
||||
if (_MATCHER_(n) && to_app(n)->get_num_args() == 3) { \
|
||||
|
@ -1024,7 +1031,7 @@ protected:
|
|||
friend class ast_manager;
|
||||
|
||||
public:
|
||||
virtual ~decl_plugin() {}
|
||||
virtual ~decl_plugin() = default;
|
||||
virtual void finalize() {}
|
||||
|
||||
|
||||
|
@ -2582,7 +2589,7 @@ class ast_mark {
|
|||
obj_mark<expr> m_expr_marks;
|
||||
obj_mark<decl, bit_vector, decl2uint> m_decl_marks;
|
||||
public:
|
||||
virtual ~ast_mark() {}
|
||||
virtual ~ast_mark() = default;
|
||||
bool is_marked(ast * n) const;
|
||||
virtual void mark(ast * n, bool flag);
|
||||
virtual void reset();
|
||||
|
|
|
@ -64,6 +64,17 @@ void ast_pp_util::display_decls(std::ostream& out) {
|
|||
m_rec_decls = n;
|
||||
}
|
||||
|
||||
void ast_pp_util::display_skolem_decls(std::ostream& out) {
|
||||
ast_smt_pp pp(m);
|
||||
unsigned n = coll.get_num_decls();
|
||||
for (unsigned i = m_decls; i < n; ++i) {
|
||||
func_decl* f = coll.get_func_decls()[i];
|
||||
if (f->get_family_id() == null_family_id && !m_removed.contains(f) && f->is_skolem())
|
||||
ast_smt2_pp(out, f, m_env) << "\n";
|
||||
}
|
||||
m_decls = n;
|
||||
}
|
||||
|
||||
void ast_pp_util::remove_decl(func_decl* f) {
|
||||
m_removed.insert(f);
|
||||
}
|
||||
|
@ -118,6 +129,7 @@ void ast_pp_util::push() {
|
|||
m_rec_decls.push();
|
||||
m_decls.push();
|
||||
m_sorts.push();
|
||||
m_defined_lim.push_back(m_defined.size());
|
||||
}
|
||||
|
||||
void ast_pp_util::pop(unsigned n) {
|
||||
|
@ -125,4 +137,55 @@ void ast_pp_util::pop(unsigned n) {
|
|||
m_rec_decls.pop(n);
|
||||
m_decls.pop(n);
|
||||
m_sorts.pop(n);
|
||||
unsigned old_sz = m_defined_lim[m_defined_lim.size() - n];
|
||||
for (unsigned i = m_defined.size(); i-- > old_sz; )
|
||||
m_is_defined.mark(m_defined.get(i), false);
|
||||
m_defined.shrink(old_sz);
|
||||
m_defined_lim.shrink(m_defined_lim.size() - n);
|
||||
}
|
||||
|
||||
std::ostream& ast_pp_util::display_expr_def(std::ostream& out, expr* n) {
|
||||
if (is_app(n) && to_app(n)->get_num_args() == 0)
|
||||
return out << mk_pp(n, m);
|
||||
else
|
||||
return out << "$" << n->get_id();
|
||||
}
|
||||
|
||||
std::ostream& ast_pp_util::define_expr(std::ostream& out, expr* n) {
|
||||
ptr_buffer<expr> visit;
|
||||
visit.push_back(n);
|
||||
while (!visit.empty()) {
|
||||
n = visit.back();
|
||||
if (m_is_defined.is_marked(n)) {
|
||||
visit.pop_back();
|
||||
continue;
|
||||
}
|
||||
if (is_app(n)) {
|
||||
bool all_visit = true;
|
||||
for (auto* e : *to_app(n)) {
|
||||
if (m_is_defined.is_marked(e))
|
||||
continue;
|
||||
all_visit = false;
|
||||
visit.push_back(e);
|
||||
}
|
||||
if (!all_visit)
|
||||
continue;
|
||||
m_defined.push_back(n);
|
||||
m_is_defined.mark(n, true);
|
||||
visit.pop_back();
|
||||
if (to_app(n)->get_num_args() > 0) {
|
||||
out << "(define-const $" << n->get_id() << " " << mk_pp(n->get_sort(), m) << " (";
|
||||
out << mk_ismt2_func(to_app(n)->get_decl(), m);
|
||||
for (auto* e : *to_app(n))
|
||||
display_expr_def(out << " ", e);
|
||||
out << "))\n";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
out << "(define-const $" << n->get_id() << " " << mk_pp(n->get_sort(), m) << " " << mk_pp(n, m) << ")\n";
|
||||
m_defined.push_back(n);
|
||||
m_is_defined.mark(n, true);
|
||||
visit.pop_back();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -30,15 +30,18 @@ class ast_pp_util {
|
|||
stacked_value<unsigned> m_rec_decls;
|
||||
stacked_value<unsigned> m_decls;
|
||||
stacked_value<unsigned> m_sorts;
|
||||
expr_mark m_is_defined;
|
||||
expr_ref_vector m_defined;
|
||||
unsigned_vector m_defined_lim;
|
||||
|
||||
public:
|
||||
|
||||
decl_collector coll;
|
||||
|
||||
ast_pp_util(ast_manager& m): m(m), m_env(m), m_rec_decls(0), m_decls(0), m_sorts(0), m_defined(m), coll(m) {}
|
||||
|
||||
ast_pp_util(ast_manager& m): m(m), m_env(m), m_rec_decls(0), m_decls(0), m_sorts(0), coll(m) {}
|
||||
|
||||
void reset() { coll.reset(); m_removed.reset(); m_sorts.clear(0u); m_decls.clear(0u); m_rec_decls.clear(0u); }
|
||||
|
||||
void reset() { coll.reset(); m_removed.reset(); m_sorts.clear(0u); m_decls.clear(0u); m_rec_decls.clear(0u);
|
||||
m_is_defined.reset(); m_defined.reset(); m_defined_lim.reset(); }
|
||||
|
||||
void collect(expr* e);
|
||||
|
||||
|
@ -50,6 +53,8 @@ class ast_pp_util {
|
|||
|
||||
void display_decls(std::ostream& out);
|
||||
|
||||
void display_skolem_decls(std::ostream& out);
|
||||
|
||||
void display_asserts(std::ostream& out, expr_ref_vector const& fmls, bool neat = true);
|
||||
|
||||
void display_assert(std::ostream& out, expr* f, bool neat = true);
|
||||
|
@ -58,6 +63,10 @@ class ast_pp_util {
|
|||
|
||||
std::ostream& display_expr(std::ostream& out, expr* f, bool neat = true);
|
||||
|
||||
std::ostream& define_expr(std::ostream& out, expr* f);
|
||||
|
||||
std::ostream& display_expr_def(std::ostream& out, expr* f);
|
||||
|
||||
void push();
|
||||
|
||||
void pop(unsigned n);
|
||||
|
|
|
@ -24,7 +24,7 @@ Revision History:
|
|||
|
||||
class ast_printer {
|
||||
public:
|
||||
virtual ~ast_printer() {}
|
||||
virtual ~ast_printer() = default;
|
||||
virtual void pp(sort * s, format_ns::format_ref & r) const { UNREACHABLE(); }
|
||||
virtual void pp(func_decl * f, format_ns::format_ref & r) const { UNREACHABLE(); }
|
||||
virtual void pp(expr * n, unsigned num_vars, char const * var_prefix, format_ns::format_ref & r, sbuffer<symbol> & var_names) const { UNREACHABLE(); }
|
||||
|
|
|
@ -46,7 +46,7 @@ protected:
|
|||
format_ns::format * pp_as(format_ns::format * fname, sort * s);
|
||||
format_ns::format * pp_signature(format_ns::format * f_name, func_decl * f);
|
||||
public:
|
||||
virtual ~smt2_pp_environment() {}
|
||||
virtual ~smt2_pp_environment() = default;
|
||||
virtual ast_manager & get_manager() const = 0;
|
||||
virtual arith_util & get_autil() = 0;
|
||||
virtual bv_util & get_bvutil() = 0;
|
||||
|
|
|
@ -620,7 +620,7 @@ func_decl * bv_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p
|
|||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
if (args[i]->get_sort() != r->get_domain(i)) {
|
||||
std::ostringstream buffer;
|
||||
buffer << "Argument " << mk_pp(args[i], m) << " at position " << i << " does not match declaration " << mk_pp(r, m);
|
||||
buffer << "Argument " << mk_pp(args[i], m) << " at position " << i << " has sort " << mk_pp(args[i]->get_sort(), m) << " it does does not match declaration " << mk_pp(r, m);
|
||||
m.raise_exception(buffer.str());
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -635,6 +635,28 @@ namespace datatype {
|
|||
}
|
||||
}
|
||||
|
||||
bool plugin::are_distinct(app * a, app * b) const {
|
||||
if (a == b)
|
||||
return false;
|
||||
if (is_unique_value(a) && is_unique_value(b))
|
||||
return true;
|
||||
if (u().is_constructor(a) && u().is_constructor(b)) {
|
||||
if (a->get_decl() != b->get_decl())
|
||||
return true;
|
||||
for (unsigned i = a->get_num_args(); i-- > 0; ) {
|
||||
if (!is_app(a->get_arg(i)))
|
||||
continue;
|
||||
if (!is_app(b->get_arg(i)))
|
||||
continue;
|
||||
app* _a = to_app(a->get_arg(i));
|
||||
app* _b = to_app(b->get_arg(i));
|
||||
if (m_manager->are_distinct(_a, _b))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
expr * plugin::get_some_value(sort * s) {
|
||||
SASSERT(u().is_datatype(s));
|
||||
func_decl * c = u().get_non_rec_constructor(s);
|
||||
|
@ -882,18 +904,16 @@ namespace datatype {
|
|||
bool util::is_well_founded(unsigned num_types, sort* const* sorts) {
|
||||
buffer<bool> well_founded(num_types, false);
|
||||
obj_map<sort, unsigned> sort2id;
|
||||
for (unsigned i = 0; i < num_types; ++i) {
|
||||
for (unsigned i = 0; i < num_types; ++i)
|
||||
sort2id.insert(sorts[i], i);
|
||||
}
|
||||
unsigned num_well_founded = 0, id = 0;
|
||||
bool changed;
|
||||
ptr_vector<sort> subsorts;
|
||||
do {
|
||||
changed = false;
|
||||
for (unsigned tid = 0; tid < num_types; tid++) {
|
||||
if (well_founded[tid]) {
|
||||
if (well_founded[tid])
|
||||
continue;
|
||||
}
|
||||
sort* s = sorts[tid];
|
||||
def const& d = get_def(s);
|
||||
for (constructor const* c : d) {
|
||||
|
@ -901,9 +921,12 @@ namespace datatype {
|
|||
subsorts.reset();
|
||||
get_subsorts(a->range(), subsorts);
|
||||
for (sort* srt : subsorts) {
|
||||
if (sort2id.find(srt, id) && !well_founded[id]) {
|
||||
goto next_constructor;
|
||||
if (sort2id.find(srt, id)) {
|
||||
if (!well_founded[id])
|
||||
goto next_constructor;
|
||||
}
|
||||
else if (is_datatype(srt))
|
||||
break;
|
||||
}
|
||||
}
|
||||
changed = true;
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace datatype {
|
|||
class size {
|
||||
unsigned m_ref{ 0 };
|
||||
public:
|
||||
virtual ~size() { }
|
||||
virtual ~size() = default;
|
||||
void inc_ref() { ++m_ref; }
|
||||
void dec_ref();
|
||||
static size* mk_offset(sort_size const& s);
|
||||
|
@ -233,6 +233,8 @@ namespace datatype {
|
|||
bool is_value(app* e) const override { return is_value_aux(false, e); }
|
||||
|
||||
bool is_unique_value(app * e) const override { return is_value_aux(true, e); }
|
||||
|
||||
bool are_distinct(app * a, app * b) const override;
|
||||
|
||||
void get_op_names(svector<builtin_name> & op_names, symbol const & logic) override;
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ bool decl_collector::is_bool(sort * s) {
|
|||
}
|
||||
|
||||
void decl_collector::visit_func(func_decl * n) {
|
||||
func_decl* g;
|
||||
if (!m_visited.is_marked(n)) {
|
||||
family_id fid = n->get_family_id();
|
||||
if (fid == null_family_id)
|
||||
|
@ -57,6 +58,8 @@ void decl_collector::visit_func(func_decl * n) {
|
|||
recfun::util u(m());
|
||||
m_todo.push_back(u.get_def(n).get_rhs());
|
||||
}
|
||||
else if (m_ar_util.is_as_array(n, g))
|
||||
m_todo.push_back(g);
|
||||
m_visited.mark(n, true);
|
||||
m_trail.push_back(n);
|
||||
}
|
||||
|
@ -65,7 +68,8 @@ void decl_collector::visit_func(func_decl * n) {
|
|||
decl_collector::decl_collector(ast_manager & m):
|
||||
m_manager(m),
|
||||
m_trail(m),
|
||||
m_dt_util(m) {
|
||||
m_dt_util(m),
|
||||
m_ar_util(m) {
|
||||
m_basic_fid = m_manager.get_basic_family_id();
|
||||
m_dt_fid = m_dt_util.get_family_id();
|
||||
recfun::util rec_util(m);
|
||||
|
@ -156,8 +160,15 @@ void decl_collector::collect_deps(sort* s, sort_set& set) {
|
|||
for (unsigned i = 0; i < num_cnstr; i++) {
|
||||
func_decl * cnstr = m_dt_util.get_datatype_constructors(s)->get(i);
|
||||
set.insert(cnstr->get_range());
|
||||
for (unsigned j = 0; j < cnstr->get_arity(); ++j)
|
||||
set.insert(cnstr->get_domain(j));
|
||||
for (unsigned j = 0; j < cnstr->get_arity(); ++j) {
|
||||
sort* n = cnstr->get_domain(j);
|
||||
set.insert(n);
|
||||
for (unsigned i = n->get_num_parameters(); i-- > 0; ) {
|
||||
parameter const& p = n->get_parameter(i);
|
||||
if (p.is_ast() && is_sort(p.get_ast()))
|
||||
set.insert(to_sort(p.get_ast()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ Revision History:
|
|||
#include "util/lim_vector.h"
|
||||
#include "ast/ast.h"
|
||||
#include "ast/datatype_decl_plugin.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
|
||||
class decl_collector {
|
||||
ast_manager & m_manager;
|
||||
|
@ -35,6 +36,7 @@ class decl_collector {
|
|||
family_id m_basic_fid;
|
||||
family_id m_dt_fid;
|
||||
datatype_util m_dt_util;
|
||||
array_util m_ar_util;
|
||||
family_id m_rec_fid;
|
||||
ptr_vector<ast> m_todo;
|
||||
|
||||
|
|
|
@ -27,14 +27,14 @@ Revision History:
|
|||
class i_expr_pred {
|
||||
public:
|
||||
virtual bool operator()(expr* e) = 0;
|
||||
virtual ~i_expr_pred() {}
|
||||
virtual ~i_expr_pred() = default;
|
||||
};
|
||||
|
||||
|
||||
class i_sort_pred {
|
||||
public:
|
||||
virtual bool operator()(sort* s) = 0;
|
||||
virtual ~i_sort_pred() {}
|
||||
virtual ~i_sort_pred() = default;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -147,11 +147,36 @@ void fpa2bv_converter::mk_distinct(func_decl * f, unsigned num, expr * const * a
|
|||
|
||||
void fpa2bv_converter::mk_numeral(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 0);
|
||||
SASSERT(f->get_num_parameters() == 1);
|
||||
SASSERT(f->get_parameter(0).is_external());
|
||||
unsigned p_id = f->get_parameter(0).get_ext_id();
|
||||
mpf const & v = m_plugin->get_value(p_id);
|
||||
mk_numeral(f->get_range(), v, result);
|
||||
sort* s = f->get_range();
|
||||
if (f->get_num_parameters() == 1) {
|
||||
SASSERT(f->get_parameter(0).is_external());
|
||||
unsigned p_id = f->get_parameter(0).get_ext_id();
|
||||
mpf const& v = m_plugin->get_value(p_id);
|
||||
mk_numeral(s, v, result);
|
||||
return;
|
||||
}
|
||||
scoped_mpf v(m_mpf_manager);
|
||||
unsigned ebits = m_util.get_ebits(s), sbits = m_util.get_sbits(s);
|
||||
switch (f->get_decl_kind()) {
|
||||
case OP_FPA_PLUS_INF:
|
||||
m_util.fm().mk_pinf(ebits, sbits, v);
|
||||
break;
|
||||
case OP_FPA_MINUS_INF:
|
||||
m_util.fm().mk_ninf(ebits, sbits, v);
|
||||
break;
|
||||
case OP_FPA_NAN:
|
||||
m_util.fm().mk_nan(ebits, sbits, v);
|
||||
break;
|
||||
case OP_FPA_PLUS_ZERO:
|
||||
m_util.fm().mk_pzero(ebits, sbits, v);
|
||||
break;
|
||||
case OP_FPA_MINUS_ZERO:
|
||||
m_util.fm().mk_nzero(ebits, sbits, v);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
mk_numeral(s, v, result);
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_numeral(sort * s, mpf const & v, expr_ref & result) {
|
||||
|
@ -3406,8 +3431,14 @@ void fpa2bv_converter::mk_to_bv(func_decl * f, unsigned num, expr * const * args
|
|||
}
|
||||
else {
|
||||
expr_ref ll(m);
|
||||
ll = m_bv_util.mk_sign_extend(3, m_bv_util.mk_concat(bv1, m_bv_util.mk_numeral(0, bv_sz-1)));
|
||||
ul = m_bv_util.mk_zero_extend(4, m_bv_util.mk_bv_neg(m_bv_util.mk_numeral(1, bv_sz-1)));
|
||||
ll = bv1;
|
||||
if (bv_sz > 1)
|
||||
ll = m_bv_util.mk_concat(bv1, m_bv_util.mk_numeral(0, bv_sz - 1));
|
||||
ll = m_bv_util.mk_sign_extend(3, ll);
|
||||
if (bv_sz > 1)
|
||||
ul = m_bv_util.mk_zero_extend(4, m_bv_util.mk_bv_neg(m_bv_util.mk_numeral(1, bv_sz - 1)));
|
||||
else
|
||||
ul = m_bv_util.mk_numeral(0, 4);
|
||||
ovfl = m.mk_or(ovfl, m_bv_util.mk_sle(pre_rounded, m_bv_util.mk_bv_neg(m_bv_util.mk_numeral(1, bv_sz + 3))));
|
||||
pre_rounded = m.mk_ite(x_is_neg, m_bv_util.mk_bv_neg(pre_rounded), pre_rounded);
|
||||
in_range = m.mk_and(m.mk_not(ovfl),
|
||||
|
|
|
@ -376,7 +376,17 @@ bool macro_finder::expand_macros(unsigned num, justified_expr const * fmls, vect
|
|||
return found_new_macro;
|
||||
}
|
||||
|
||||
void macro_finder::revert_unsafe_macros(vector<justified_expr>& new_fmls) {
|
||||
auto& unsafe_macros = m_macro_manager.unsafe_macros();
|
||||
for (auto* f : unsafe_macros) {
|
||||
quantifier* q = m_macro_manager.get_macro_quantifier(f);
|
||||
new_fmls.push_back(justified_expr(m, q, nullptr));
|
||||
}
|
||||
unsafe_macros.reset();
|
||||
}
|
||||
|
||||
void macro_finder::operator()(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls) {
|
||||
m_macro_manager.unsafe_macros().reset();
|
||||
TRACE("macro_finder", tout << "processing macros...\n";);
|
||||
vector<justified_expr> _new_fmls;
|
||||
if (expand_macros(n, fmls, _new_fmls)) {
|
||||
|
@ -388,6 +398,7 @@ void macro_finder::operator()(unsigned n, justified_expr const* fmls, vector<jus
|
|||
break;
|
||||
}
|
||||
}
|
||||
revert_unsafe_macros(_new_fmls);
|
||||
new_fmls.append(_new_fmls);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ class macro_finder {
|
|||
|
||||
bool is_macro(expr * n, app_ref & head, expr_ref & def);
|
||||
|
||||
void revert_unsafe_macros(vector<justified_expr>& new_fmls);
|
||||
|
||||
public:
|
||||
macro_finder(ast_manager & m, macro_manager & mm);
|
||||
~macro_finder();
|
||||
|
|
|
@ -241,12 +241,14 @@ func_decl * macro_manager::get_macro_interpretation(unsigned i, expr_ref & inter
|
|||
struct macro_manager::macro_expander_cfg : public default_rewriter_cfg {
|
||||
ast_manager& m;
|
||||
macro_manager& mm;
|
||||
array_util a;
|
||||
expr_dependency_ref m_used_macro_dependencies;
|
||||
expr_ref_vector m_trail;
|
||||
|
||||
macro_expander_cfg(ast_manager& m, macro_manager& mm):
|
||||
m(m),
|
||||
mm(mm),
|
||||
a(m),
|
||||
m_used_macro_dependencies(m),
|
||||
m_trail(m)
|
||||
{}
|
||||
|
@ -296,7 +298,7 @@ struct macro_manager::macro_expander_cfg : public default_rewriter_cfg {
|
|||
return false;
|
||||
app * n = to_app(_n);
|
||||
quantifier * q = nullptr;
|
||||
func_decl * d = n->get_decl();
|
||||
func_decl * d = n->get_decl(), *d2 = nullptr;
|
||||
TRACE("macro_manager", tout << "trying to expand:\n" << mk_pp(n, m) << "\nd:\n" << d->get_name() << "\n";);
|
||||
if (mm.m_decl2macro.find(d, q)) {
|
||||
app * head = nullptr;
|
||||
|
@ -343,6 +345,12 @@ struct macro_manager::macro_expander_cfg : public default_rewriter_cfg {
|
|||
m_used_macro_dependencies = m.mk_join(m_used_macro_dependencies, ed);
|
||||
return true;
|
||||
}
|
||||
else if (a.is_as_array(d, d2) && mm.m_decl2macro.find(d2, q)) {
|
||||
mm.unsafe_macros().insert(d2);
|
||||
}
|
||||
else if (a.is_map(d, d2) && mm.m_decl2macro.find(d2, q)) {
|
||||
mm.unsafe_macros().insert(d2);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -29,7 +29,7 @@ Revision History:
|
|||
\brief Macros are universally quantified formulas of the form:
|
||||
(forall X (= (f X) T[X]))
|
||||
(forall X (iff (f X) T[X]))
|
||||
where T[X] does not contain X.
|
||||
where T[X] does not contain f.
|
||||
|
||||
This class is responsible for storing macros and expanding them.
|
||||
It has support for backtracking and tagging declarations in an expression as forbidded for being macros.
|
||||
|
@ -47,6 +47,7 @@ class macro_manager {
|
|||
expr_dependency_ref_vector m_macro_deps;
|
||||
obj_hashtable<func_decl> m_forbidden_set;
|
||||
func_decl_ref_vector m_forbidden;
|
||||
obj_hashtable<func_decl> m_unsafe_macros;
|
||||
struct scope {
|
||||
unsigned m_decls_lim;
|
||||
unsigned m_forbidden_lim;
|
||||
|
@ -86,7 +87,7 @@ public:
|
|||
quantifier * get_macro_quantifier(func_decl * f) const { quantifier * q = nullptr; m_decl2macro.find(f, q); return q; }
|
||||
void get_head_def(quantifier * q, func_decl * d, app * & head, expr_ref & def, bool& revert) const;
|
||||
void expand_macros(expr * n, proof * pr, expr_dependency * dep, expr_ref & r, proof_ref & new_pr, expr_dependency_ref & new_dep);
|
||||
|
||||
obj_hashtable<func_decl>& unsafe_macros() { return m_unsafe_macros; }
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ protected:
|
|||
void collect_macro_candidates(quantifier* q);
|
||||
public:
|
||||
quantifier_macro_info(ast_manager& m, quantifier* q);
|
||||
virtual ~quantifier_macro_info() {}
|
||||
virtual ~quantifier_macro_info() = default;
|
||||
bool is_auf() const { return m_is_auf; }
|
||||
quantifier* get_flat_q() const { return m_flat_q; }
|
||||
bool has_cond_macros() const { return !m_cond_macros.empty(); }
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
elim_term_ite_cfg(ast_manager & m, defined_names & d): m(m), m_defined_names(d) {
|
||||
// TBD enable_ac_support(false);
|
||||
}
|
||||
virtual ~elim_term_ite_cfg() {}
|
||||
virtual ~elim_term_ite_cfg() = default;
|
||||
vector<justified_expr> const& new_defs() const { return m_new_defs; }
|
||||
br_status reduce_app(func_decl* f, unsigned n, expr *const* args, expr_ref& result, proof_ref& result_pr);
|
||||
void push() { m_lim.push_back(m_new_defs.size()); }
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
|
||||
class name_exprs {
|
||||
public:
|
||||
virtual ~name_exprs() {}
|
||||
virtual ~name_exprs() = default;
|
||||
virtual void operator()(expr * n, // [IN] expression that contain the sub-expressions to be named
|
||||
expr_ref_vector & new_defs, // [OUT] new definitions
|
||||
proof_ref_vector & new_def_proofs, // [OUT] proofs of the new definitions
|
||||
|
|
|
@ -66,7 +66,6 @@ void pp(std::ostream & out, format * f, ast_manager & m, params_ref const & _p)
|
|||
bool single_line = p.single_line();
|
||||
|
||||
unsigned pos = 0;
|
||||
unsigned ribbon_pos = 0;
|
||||
unsigned line = 0;
|
||||
unsigned len;
|
||||
unsigned i;
|
||||
|
@ -92,7 +91,6 @@ void pp(std::ostream & out, format * f, ast_manager & m, params_ref const & _p)
|
|||
break;
|
||||
}
|
||||
pos += len;
|
||||
ribbon_pos += len;
|
||||
out << f->get_decl()->get_parameter(0).get_symbol();
|
||||
break;
|
||||
case OP_INDENT:
|
||||
|
@ -121,7 +119,6 @@ void pp(std::ostream & out, format * f, ast_manager & m, params_ref const & _p)
|
|||
break;
|
||||
}
|
||||
pos = indent;
|
||||
ribbon_pos = 0;
|
||||
line++;
|
||||
if (line < max_num_lines) {
|
||||
out << "\n";
|
||||
|
|
|
@ -291,7 +291,11 @@ namespace recfun {
|
|||
expr * e = stack.back();
|
||||
stack.pop_back();
|
||||
|
||||
if (m.is_ite(e)) {
|
||||
expr* cond = nullptr, *th = nullptr, *el = nullptr;
|
||||
if (m.is_ite(e, cond, th, el) && contains_def(u, cond)) {
|
||||
// skip
|
||||
}
|
||||
else if (m.is_ite(e)) {
|
||||
// need to do a case split on `e`, forking the search space
|
||||
b.to_split = st.cons_ite(to_app(e), b.to_split);
|
||||
}
|
||||
|
@ -338,9 +342,8 @@ namespace recfun {
|
|||
|
||||
// substitute, to get rid of `ite` terms
|
||||
expr_ref case_rhs = subst(rhs);
|
||||
for (unsigned i = 0; i < conditions.size(); ++i) {
|
||||
for (unsigned i = 0; i < conditions.size(); ++i)
|
||||
conditions[i] = subst(conditions.get(i));
|
||||
}
|
||||
|
||||
// yield new case
|
||||
bool is_imm = is_i(case_rhs);
|
||||
|
@ -471,9 +474,8 @@ namespace recfun {
|
|||
|
||||
void plugin::set_definition(replace& r, promise_def & d, bool is_macro, unsigned n_vars, var * const * vars, expr * rhs) {
|
||||
u().set_definition(r, d, is_macro, n_vars, vars, rhs);
|
||||
for (case_def & c : d.get_def()->get_cases()) {
|
||||
for (case_def & c : d.get_def()->get_cases())
|
||||
m_case_defs.insert(c.get_decl(), &c);
|
||||
}
|
||||
}
|
||||
|
||||
bool plugin::has_defs() const {
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace recfun {
|
|||
|
||||
class replace {
|
||||
public:
|
||||
virtual ~replace() {}
|
||||
virtual ~replace() = default;
|
||||
virtual void reset() = 0;
|
||||
virtual void insert(expr* d, expr* r) = 0;
|
||||
virtual expr_ref operator()(expr* e) = 0;
|
||||
|
|
|
@ -706,6 +706,31 @@ br_status arith_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result
|
|||
return st;
|
||||
}
|
||||
|
||||
br_status arith_rewriter::mk_and_core(unsigned n, expr* const* args, expr_ref& result) {
|
||||
if (n <= 1)
|
||||
return BR_FAILED;
|
||||
expr* x, * y, * z, * u;
|
||||
rational a, b;
|
||||
if (m_util.is_le(args[0], x, y) && m_util.is_numeral(x, a)) {
|
||||
expr* arg0 = args[0];
|
||||
ptr_buffer<expr> rest;
|
||||
for (unsigned i = 1; i < n; ++i) {
|
||||
if (m_util.is_le(args[i], z, u) && u == y && m_util.is_numeral(z, b)) {
|
||||
if (b > a)
|
||||
arg0 = args[i];
|
||||
}
|
||||
else
|
||||
rest.push_back(args[i]);
|
||||
}
|
||||
if (rest.size() < n - 1) {
|
||||
rest.push_back(arg0);
|
||||
result = m().mk_and(rest);
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
bool arith_rewriter::mk_eq_mod(expr* arg1, expr* arg2, expr_ref& result) {
|
||||
expr* x = nullptr, *y = nullptr, *z = nullptr, *u = nullptr;
|
||||
rational p, k, l;
|
||||
|
|
|
@ -149,6 +149,8 @@ public:
|
|||
|
||||
br_status mk_abs_core(expr * arg, expr_ref & result);
|
||||
|
||||
br_status mk_and_core(unsigned n, expr* const* args, expr_ref& result);
|
||||
|
||||
br_status mk_div_core(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_idiv_core(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_idivides(unsigned k, expr * arg, expr_ref & result);
|
||||
|
|
|
@ -86,12 +86,11 @@ br_status array_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c
|
|||
// l_true -- all equal
|
||||
// l_false -- at least one disequal
|
||||
// l_undef -- don't know
|
||||
template<bool CHECK_DISEQ>
|
||||
lbool array_rewriter::compare_args(unsigned num_args, expr * const * args1, expr * const * args2) {
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
if (args1[i] == args2[i])
|
||||
continue;
|
||||
if (CHECK_DISEQ && m().are_distinct(args1[i], args2[i]))
|
||||
if (m().are_distinct(args1[i], args2[i]))
|
||||
return l_false;
|
||||
return l_undef;
|
||||
}
|
||||
|
@ -102,9 +101,7 @@ br_status array_rewriter::mk_store_core(unsigned num_args, expr * const * args,
|
|||
SASSERT(num_args >= 3);
|
||||
|
||||
if (m_util.is_store(args[0])) {
|
||||
lbool r = m_sort_store ?
|
||||
compare_args<true>(num_args - 2, args + 1, to_app(args[0])->get_args() + 1) :
|
||||
compare_args<false>(num_args - 2, args + 1, to_app(args[0])->get_args() + 1);
|
||||
lbool r = compare_args(num_args - 2, args + 1, to_app(args[0])->get_args() + 1);
|
||||
switch (r) {
|
||||
case l_true: {
|
||||
//
|
||||
|
@ -118,12 +115,11 @@ br_status array_rewriter::mk_store_core(unsigned num_args, expr * const * args,
|
|||
return BR_DONE;
|
||||
}
|
||||
case l_false:
|
||||
SASSERT(m_sort_store);
|
||||
//
|
||||
// store(store(a,i,v),j,w) -> store(store(a,j,w),i,v)
|
||||
// if i, j are different, lt(i,j)
|
||||
//
|
||||
if (lex_lt(num_args-2, args+1, to_app(args[0])->get_args() + 1)) {
|
||||
//
|
||||
if (m_sort_store && lex_lt(num_args-2, args+1, to_app(args[0])->get_args() + 1)) {
|
||||
ptr_buffer<expr> new_args;
|
||||
new_args.push_back(to_app(args[0])->get_arg(0));
|
||||
new_args.append(num_args-1, args+1);
|
||||
|
@ -134,6 +130,9 @@ br_status array_rewriter::mk_store_core(unsigned num_args, expr * const * args,
|
|||
result = m().mk_app(get_fid(), OP_STORE, num_args, new_args.data());
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (squash_store(num_args, args, result))
|
||||
return BR_REWRITE2;
|
||||
|
||||
break;
|
||||
case l_undef:
|
||||
break;
|
||||
|
@ -155,7 +154,7 @@ br_status array_rewriter::mk_store_core(unsigned num_args, expr * const * args,
|
|||
// store(a, i, select(a, i)) --> a
|
||||
//
|
||||
if (m_util.is_select(v) &&
|
||||
compare_args<false>(num_args-1, args, to_app(v)->get_args())) {
|
||||
l_true == compare_args(num_args-1, args, to_app(v)->get_args())) {
|
||||
result = args[0];
|
||||
return BR_DONE;
|
||||
}
|
||||
|
@ -163,19 +162,52 @@ br_status array_rewriter::mk_store_core(unsigned num_args, expr * const * args,
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
bool array_rewriter::squash_store(unsigned n, expr* const* args, expr_ref& result) {
|
||||
ptr_buffer<expr> parents, sargs;
|
||||
expr* a = args[0];
|
||||
while (m_util.is_store(a)) {
|
||||
lbool r = compare_args(n - 2, args + 1, to_app(a)->get_args() + 1);
|
||||
switch (r) {
|
||||
case l_undef:
|
||||
return false;
|
||||
case l_true:
|
||||
result = to_app(a)->get_arg(0);
|
||||
for (unsigned i = parents.size(); i-- > 0; ) {
|
||||
expr* p = parents[i];
|
||||
sargs.reset();
|
||||
sargs.push_back(result);
|
||||
for (unsigned j = 1; j < to_app(p)->get_num_args(); ++j)
|
||||
sargs.push_back(to_app(p)->get_arg(j));
|
||||
result = m_util.mk_store(sargs.size(), sargs.data());
|
||||
}
|
||||
sargs.reset();
|
||||
sargs.push_back(result);
|
||||
for (unsigned j = 1; j < n; ++j)
|
||||
sargs.push_back(args[j]);
|
||||
result = m_util.mk_store(sargs.size(), sargs.data());
|
||||
return true;
|
||||
case l_false:
|
||||
parents.push_back(a);
|
||||
a = to_app(a)->get_arg(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
br_status array_rewriter::mk_select_core(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num_args >= 2);
|
||||
if (m_util.is_store(args[0])) {
|
||||
SASSERT(to_app(args[0])->get_num_args() == num_args+1);
|
||||
switch (compare_args<true>(num_args - 1, args+1, to_app(args[0])->get_args()+1)) {
|
||||
switch (compare_args(num_args - 1, args+1, to_app(args[0])->get_args()+1)) {
|
||||
case l_true:
|
||||
// select(store(a, I, v), I) --> v
|
||||
result = to_app(args[0])->get_arg(num_args);
|
||||
return BR_DONE;
|
||||
case l_false: {
|
||||
expr* arg0 = to_app(args[0])->get_arg(0);
|
||||
while (m_util.is_store(arg0) && compare_args<true>(num_args-1, args + 1, to_app(arg0)->get_args() + 1) == l_false) {
|
||||
while (m_util.is_store(arg0) && compare_args(num_args-1, args + 1, to_app(arg0)->get_args() + 1) == l_false) {
|
||||
arg0 = to_app(arg0)->get_arg(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,13 +28,13 @@ Notes:
|
|||
*/
|
||||
class array_rewriter {
|
||||
array_util m_util;
|
||||
bool m_sort_store { false };
|
||||
bool m_blast_select_store { false };
|
||||
bool m_expand_select_store { false };
|
||||
bool m_expand_store_eq { false };
|
||||
bool m_expand_select_ite { false };
|
||||
bool m_expand_nested_stores { false };
|
||||
template<bool CHECK_DISEQ>
|
||||
bool m_sort_store = false;
|
||||
bool m_blast_select_store = false;
|
||||
bool m_expand_select_store = false;
|
||||
bool m_expand_store_eq = false;
|
||||
bool m_expand_select_ite = false;
|
||||
bool m_expand_nested_stores = false;
|
||||
|
||||
lbool compare_args(unsigned num_args, expr * const * args1, expr * const * args2);
|
||||
void mk_eq(expr* e, expr* lhs, expr* rhs, expr_ref_vector& fmls);
|
||||
|
||||
|
@ -45,6 +45,8 @@ class array_rewriter {
|
|||
bool is_expandable_store(expr* s);
|
||||
expr_ref expand_store(expr* s);
|
||||
|
||||
bool squash_store(unsigned n, expr* const* args, expr_ref& result);
|
||||
|
||||
public:
|
||||
array_rewriter(ast_manager & m, params_ref const & p = params_ref()):
|
||||
m_util(m) {
|
||||
|
|
|
@ -175,7 +175,7 @@ br_status bool_rewriter::mk_flat_and_core(unsigned num_args, expr * const * args
|
|||
}
|
||||
if (mk_nflat_and_core(flat_args.size(), flat_args.data(), result) == BR_FAILED)
|
||||
result = m().mk_and(flat_args);
|
||||
return BR_DONE;
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
return mk_nflat_and_core(num_args, args, result);
|
||||
}
|
||||
|
@ -874,7 +874,7 @@ br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & re
|
|||
expr_ref tmp(m());
|
||||
mk_not(c, tmp);
|
||||
mk_and(tmp, e, result);
|
||||
return BR_DONE;
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
}
|
||||
if (m().is_true(e) && m_elim_ite) {
|
||||
|
@ -885,11 +885,11 @@ br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & re
|
|||
}
|
||||
if (m().is_false(e) && m_elim_ite) {
|
||||
mk_and(c, t, result);
|
||||
return BR_DONE;
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
if (c == e && m_elim_ite) {
|
||||
mk_and(c, t, result);
|
||||
return BR_DONE;
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
if (c == t && m_elim_ite) {
|
||||
mk_or(c, e, result);
|
||||
|
@ -912,13 +912,13 @@ br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & re
|
|||
expr_ref a(m());
|
||||
mk_and(c, t2, a);
|
||||
result = m().mk_not(m().mk_eq(t1, a));
|
||||
return BR_REWRITE2;
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
if (m().is_not(t, t1) && m().is_eq(t1, t2, t1) && e == t1) {
|
||||
expr_ref a(m());
|
||||
mk_and(c, t2, a);
|
||||
result = m().mk_eq(t1, a);
|
||||
return BR_REWRITE2;
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -931,14 +931,14 @@ br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & re
|
|||
expr_ref new_c(m());
|
||||
mk_and(c, not_c2, new_c);
|
||||
result = m().mk_ite(new_c, to_app(t)->get_arg(2), e);
|
||||
return BR_REWRITE1;
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
// (ite c1 (ite c2 t1 t2) t2) ==> (ite (and c1 c2) t1 t2)
|
||||
if (e == to_app(t)->get_arg(2)) {
|
||||
expr_ref new_c(m());
|
||||
mk_and(c, to_app(t)->get_arg(0), new_c);
|
||||
result = m().mk_ite(new_c, to_app(t)->get_arg(1), e);
|
||||
return BR_REWRITE1;
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
|
||||
|
||||
|
@ -955,7 +955,7 @@ br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & re
|
|||
expr_ref new_c(m());
|
||||
mk_or(and1, and2, new_c);
|
||||
result = m().mk_ite(new_c, to_app(t)->get_arg(1), to_app(t)->get_arg(2));
|
||||
return BR_REWRITE1;
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
|
||||
// (ite c1 (ite c2 t1 t2) (ite c3 t2 t1)) ==> (ite (or (and c1 c2) (and (not c1) (not c3))) t1 t2)
|
||||
|
@ -972,7 +972,7 @@ br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & re
|
|||
expr_ref new_c(m());
|
||||
mk_or(and1, and2, new_c);
|
||||
result = m().mk_ite(new_c, to_app(t)->get_arg(1), to_app(t)->get_arg(2));
|
||||
return BR_REWRITE1;
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,10 @@ br_status datatype_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr
|
|||
// simplify is_cons(nil) -> false
|
||||
//
|
||||
SASSERT(num_args == 1);
|
||||
if (m_util.get_datatype_num_constructors(args[0]->get_sort()) == 1) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
if (!is_app(args[0]) || !m_util.is_constructor(to_app(args[0])))
|
||||
return BR_FAILED;
|
||||
if (to_app(args[0])->get_decl() == m_util.get_recognizer_constructor(f))
|
||||
|
|
|
@ -28,7 +28,7 @@ Notes:
|
|||
class expr_replacer {
|
||||
struct scoped_set_subst;
|
||||
public:
|
||||
virtual ~expr_replacer() {}
|
||||
virtual ~expr_replacer() = default;
|
||||
|
||||
virtual ast_manager & m() const = 0;
|
||||
virtual void set_substitution(expr_substitution * s) = 0;
|
||||
|
|
|
@ -190,3 +190,17 @@ void expr_safe_replace::apply_substitution(expr* s, expr* def, expr_ref& t) {
|
|||
(*this)(t, t);
|
||||
reset();
|
||||
}
|
||||
|
||||
void expr_safe_replace::push_scope() {
|
||||
m_limit.push_back(m_src.size());
|
||||
}
|
||||
|
||||
void expr_safe_replace::pop_scope(unsigned n) {
|
||||
unsigned old_sz = m_limit[m_limit.size() - n];
|
||||
if (old_sz != m_src.size()) {
|
||||
m_cache.clear();
|
||||
m_src.shrink(old_sz);
|
||||
m_dst.shrink(old_sz);
|
||||
}
|
||||
m_limit.shrink(m_limit.size() - n);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ class expr_safe_replace {
|
|||
ast_manager& m;
|
||||
expr_ref_vector m_src;
|
||||
expr_ref_vector m_dst;
|
||||
unsigned_vector m_limit = 0;
|
||||
ptr_vector<expr> m_todo, m_args;
|
||||
expr_ref_vector m_refs;
|
||||
std::unordered_map<expr*,expr*> m_cache;
|
||||
|
@ -48,5 +49,9 @@ public:
|
|||
void reset();
|
||||
|
||||
bool empty() const { return m_src.empty(); }
|
||||
|
||||
void push_scope();
|
||||
|
||||
void pop_scope(unsigned n);
|
||||
};
|
||||
|
||||
|
|
|
@ -509,6 +509,8 @@ namespace seq {
|
|||
}
|
||||
|
||||
/**
|
||||
i = last_indexof(t, s):
|
||||
|
||||
!contains(t, s) => i = -1
|
||||
|t| = 0 => |s| = 0 or i = -1
|
||||
|t| = 0 & |s| = 0 => i = 0
|
||||
|
@ -1258,9 +1260,12 @@ namespace seq {
|
|||
expr_ref emp = mk_eq_empty(a);
|
||||
expr_ref cnt = expr_ref(e, m);
|
||||
add_clause(cnt, ~pref);
|
||||
add_clause(cnt, ~postf);
|
||||
add_clause(cnt, emp, ~postf);
|
||||
add_clause(~emp, mk_eq_empty(tail));
|
||||
add_clause(emp, mk_eq(a, seq.str.mk_concat(head, tail)));
|
||||
expr* s, *idx;
|
||||
if (m_sk.is_tail(tail, s, idx))
|
||||
add_clause(emp, mk_ge_e(mk_len(s), idx));
|
||||
}
|
||||
|
||||
expr_ref axioms::length_limit(expr* s, unsigned k) {
|
||||
|
|
|
@ -438,6 +438,10 @@ namespace seq {
|
|||
!seq.str.is_unit(a) &&
|
||||
!seq.str.is_itos(a) &&
|
||||
!seq.str.is_nth_i(a) &&
|
||||
!seq.str.is_map(a) &&
|
||||
!seq.str.is_mapi(a) &&
|
||||
!seq.str.is_foldl(a) &&
|
||||
!seq.str.is_foldli(a) &&
|
||||
!m.is_ite(a);
|
||||
}
|
||||
|
||||
|
|
|
@ -2068,7 +2068,7 @@ br_status seq_rewriter::mk_seq_replace_all(expr* a, expr* b, expr* c, expr_ref&
|
|||
*/
|
||||
br_status seq_rewriter::mk_seq_map(expr* f, expr* seqA, expr_ref& result) {
|
||||
if (str().is_empty(seqA)) {
|
||||
result = str().mk_empty(get_array_range(f->get_sort()));
|
||||
result = str().mk_empty(str().mk_seq(get_array_range(f->get_sort())));
|
||||
return BR_DONE;
|
||||
}
|
||||
expr* a, *s1, *s2;
|
||||
|
@ -2087,7 +2087,7 @@ br_status seq_rewriter::mk_seq_map(expr* f, expr* seqA, expr_ref& result) {
|
|||
|
||||
br_status seq_rewriter::mk_seq_mapi(expr* f, expr* i, expr* seqA, expr_ref& result) {
|
||||
if (str().is_empty(seqA)) {
|
||||
result = str().mk_empty(get_array_range(f->get_sort()));
|
||||
result = str().mk_empty(str().mk_seq(get_array_range(f->get_sort())));
|
||||
return BR_DONE;
|
||||
}
|
||||
expr* a, *s1, *s2;
|
||||
|
|
|
@ -83,7 +83,7 @@ public:
|
|||
|
||||
class expr_solver {
|
||||
public:
|
||||
virtual ~expr_solver() {}
|
||||
virtual ~expr_solver() = default;
|
||||
virtual lbool check_sat(expr* e) = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -26,10 +26,14 @@ skolem::skolem(ast_manager& m, th_rewriter& rw):
|
|||
m_suffix = "seq.s.prefix";
|
||||
m_accept = "aut.accept";
|
||||
m_tail = "seq.tail";
|
||||
m_left = "seq.left";
|
||||
m_right = "seq.right";
|
||||
m_seq_first = "seq.first";
|
||||
m_seq_last = "seq.last";
|
||||
m_indexof_left = "seq.idx.l";
|
||||
m_indexof_right = "seq.idx.r";
|
||||
m_lindexof_left = "seq.lidx.l";
|
||||
m_lindexof_right = "seq.lidx.r";
|
||||
m_aut_step = "aut.step";
|
||||
m_pre = "seq.pre"; // (seq.pre s l): prefix of string s of length l
|
||||
m_post = "seq.post"; // (seq.post s l): suffix of string s of length k, based on extract starting at index i of length l
|
||||
|
@ -155,6 +159,20 @@ bool skolem::is_tail(expr* e, expr*& s, expr*& idx) const {
|
|||
return is_tail(e) && (s = to_app(e)->get_arg(0), idx = to_app(e)->get_arg(1), true);
|
||||
}
|
||||
|
||||
bool skolem::is_left_or_right(expr* e, expr*& x, expr*& y, expr*& z) {
|
||||
if (!is_skolem(m_left, e) && !is_skolem(m_right, e))
|
||||
return false;
|
||||
x = nullptr;
|
||||
y = nullptr;
|
||||
z = nullptr;
|
||||
unsigned sz = to_app(e)->get_num_args();
|
||||
if (sz > 0) x = to_app(e)->get_arg(0);
|
||||
if (sz > 1) y = to_app(e)->get_arg(1);
|
||||
if (sz > 2) z = to_app(e)->get_arg(2);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool skolem::is_eq(expr* e, expr*& a, expr*& b) const {
|
||||
return is_skolem(m_eq, e) && (a = to_app(e)->get_arg(0), b = to_app(e)->get_arg(1), true);
|
||||
}
|
||||
|
|
|
@ -32,8 +32,10 @@ namespace seq {
|
|||
|
||||
symbol m_prefix, m_suffix;
|
||||
symbol m_tail;
|
||||
symbol m_left, m_right;
|
||||
symbol m_seq_first, m_seq_last;
|
||||
symbol m_indexof_left, m_indexof_right; // inverse of indexof: (indexof_left s t) + s + (indexof_right s t) = t, for s in t.
|
||||
symbol m_indexof_left, m_indexof_right; // inverse of indexof: (indexof_left s t) + s + (indexof_right s t) = t, for s in t.
|
||||
symbol m_lindexof_left, m_lindexof_right; // inverse of indexof: (indexof_left s t) + s + (indexof_right s t) = t, for s in t.
|
||||
symbol m_aut_step; // regex unfolding state
|
||||
symbol m_accept; // regex
|
||||
symbol m_is_empty; // regex emptiness check
|
||||
|
@ -81,8 +83,8 @@ namespace seq {
|
|||
expr_ref mk_indexof_right(expr* t, expr* s, expr* offset = nullptr) { return mk(m_indexof_right, t, s, offset); }
|
||||
expr_ref mk_contains_left(expr* t, expr* s, expr* offset = nullptr) { return mk("seq.cnt.l", t, s, offset); }
|
||||
expr_ref mk_contains_right(expr* t, expr* s, expr* offset = nullptr) { return mk("seq.cnt.r", t, s, offset); }
|
||||
expr_ref mk_last_indexof_left(expr* t, expr* s, expr* offset = nullptr) { return mk("seq.lidx.l", t, s, offset); }
|
||||
expr_ref mk_last_indexof_right(expr* t, expr* s, expr* offset = nullptr) { return mk("seq.lidx.r", t, s, offset); }
|
||||
expr_ref mk_last_indexof_left(expr* t, expr* s, expr* offset = nullptr) { return mk(m_lindexof_left, t, s, offset); }
|
||||
expr_ref mk_last_indexof_right(expr* t, expr* s, expr* offset = nullptr) { return mk(m_lindexof_right, t, s, offset); }
|
||||
|
||||
expr_ref mk_tail(expr* s, expr* i) { return mk(m_tail, s, i); }
|
||||
expr_ref mk_post(expr* s, expr* i) { return mk(m_post, s, i); }
|
||||
|
@ -100,8 +102,8 @@ namespace seq {
|
|||
expr_ref mk_digit2int(expr* ch) { return mk(symbol("seq.digit2int"), ch, nullptr, nullptr, nullptr, a.mk_int()); }
|
||||
expr_ref mk_digit2bv(expr* ch, sort* bv_sort);
|
||||
expr_ref mk_ubv2ch(expr* b) { return mk(symbol("seq.ubv2ch"), b, nullptr, nullptr, nullptr, seq.mk_char_sort()); }
|
||||
expr_ref mk_left(expr* x, expr* y, expr* z = nullptr) { return mk("seq.left", x, y, z); }
|
||||
expr_ref mk_right(expr* x, expr* y, expr* z = nullptr) { return mk("seq.right", x, y, z); }
|
||||
expr_ref mk_left(expr* x, expr* y, expr* z = nullptr) { return mk(m_left, x, y, z); }
|
||||
expr_ref mk_right(expr* x, expr* y, expr* z = nullptr) { return mk(m_right, x, y, z); }
|
||||
expr_ref mk_max_unfolding_depth(unsigned d);
|
||||
expr_ref mk_length_limit(expr* e, unsigned d);
|
||||
|
||||
|
@ -117,6 +119,8 @@ namespace seq {
|
|||
bool is_seq_first(expr* e) const { return is_skolem(m_seq_first, e); }
|
||||
bool is_indexof_left(expr* e) const { return is_skolem(m_indexof_left, e); }
|
||||
bool is_indexof_right(expr* e) const { return is_skolem(m_indexof_right, e); }
|
||||
bool is_last_indexof_left(expr* e) const { return is_skolem(m_lindexof_left, e); }
|
||||
bool is_last_indexof_right(expr* e) const { return is_skolem(m_lindexof_right, e); }
|
||||
bool is_indexof_left(expr* e, expr*& x, expr*& y) const {
|
||||
return is_indexof_left(e) && (x = to_app(e)->get_arg(0), y = to_app(e)->get_arg(1), true);
|
||||
}
|
||||
|
@ -124,6 +128,7 @@ namespace seq {
|
|||
return is_indexof_right(e) && (x = to_app(e)->get_arg(0), y = to_app(e)->get_arg(1), true);
|
||||
}
|
||||
|
||||
bool is_left_or_right(expr* e, expr*& x, expr*& y, expr*& z);
|
||||
bool is_step(expr* e) const { return is_skolem(m_aut_step, e); }
|
||||
bool is_step(expr* e, expr*& s, expr*& idx, expr*& re, expr*& i, expr*& j, expr*& t) const;
|
||||
bool is_accept(expr* acc) const { return is_skolem(m_accept, acc); }
|
||||
|
|
|
@ -215,6 +215,11 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
if (st != BR_FAILED)
|
||||
return st;
|
||||
}
|
||||
if (false && k == OP_AND) {
|
||||
st = m_a_rw.mk_and_core(num, args, result);
|
||||
if (st != BR_FAILED)
|
||||
return st;
|
||||
}
|
||||
if (k == OP_EQ && m_seq_rw.u().has_seq() && is_app(args[0]) &&
|
||||
to_app(args[0])->get_family_id() == m_seq_rw.get_fid()) {
|
||||
st = m_seq_rw.mk_eq_core(args[0], args[1], result);
|
||||
|
|
|
@ -29,8 +29,8 @@ public:
|
|||
m.toggle_proof_mode(mode);
|
||||
}
|
||||
~scoped_proof_mode() {
|
||||
m.toggle_proof_mode(m_mode);
|
||||
}
|
||||
m.toggle_proof_mode(m_mode);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -403,6 +403,7 @@ public:
|
|||
MATCH_BINARY(is_map);
|
||||
MATCH_TERNARY(is_mapi);
|
||||
MATCH_TERNARY(is_foldl);
|
||||
MATCH_QUATARY(is_foldli);
|
||||
MATCH_BINARY(is_last_index);
|
||||
MATCH_TERNARY(is_replace);
|
||||
MATCH_TERNARY(is_replace_re);
|
||||
|
@ -448,7 +449,7 @@ public:
|
|||
info() {}
|
||||
|
||||
/*
|
||||
Used for constructing either an invalid info that is only used to indicate uninitialzed entry, or valid but unknown info value.
|
||||
Used for constructing either an invalid info that is only used to indicate uninitialized entry, or valid but unknown info value.
|
||||
*/
|
||||
info(lbool is_known) : known(is_known) {}
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ public:
|
|||
return find(to_var(v.get_expr()), v.get_offset(), r);
|
||||
}
|
||||
|
||||
void get_binding(unsigned binding_num, var_offset& var, expr_offset& r) {
|
||||
void get_binding(unsigned binding_num, var_offset& var, expr_offset& r) const {
|
||||
var = m_vars[binding_num];
|
||||
VERIFY(m_subst.find(var.first, var.second, r));
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ protected:
|
|||
substitution & m_subst;
|
||||
public:
|
||||
st_visitor(substitution & s):m_subst(s) {}
|
||||
virtual ~st_visitor() {}
|
||||
virtual ~st_visitor() = default;
|
||||
substitution & get_substitution() { return m_subst; }
|
||||
virtual bool operator()(expr * e) { return true; }
|
||||
};
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
class value_generator_core {
|
||||
public:
|
||||
virtual ~value_generator_core() {}
|
||||
virtual ~value_generator_core() = default;
|
||||
virtual family_id get_fid() const = 0;
|
||||
virtual expr_ref get_value(sort* s, unsigned index) = 0;
|
||||
};
|
||||
|
|
|
@ -561,6 +561,7 @@ cmd_context::~cmd_context() {
|
|||
finalize_cmds();
|
||||
finalize_tactic_cmds();
|
||||
finalize_probes();
|
||||
m_proof_cmds = nullptr;
|
||||
reset(true);
|
||||
m_mcs.reset();
|
||||
m_solver = nullptr;
|
||||
|
@ -1054,7 +1055,7 @@ func_decl * cmd_context::find_func_decl(symbol const & s, unsigned num_indices,
|
|||
if (f)
|
||||
return f;
|
||||
builtin_decl d;
|
||||
if (domain && m_builtin_decls.find(s, d)) {
|
||||
if ((arity == 0 || domain) && m_builtin_decls.find(s, d)) {
|
||||
family_id fid = d.m_fid;
|
||||
decl_kind k = d.m_decl;
|
||||
// Hack: if d.m_next != 0, we use domain[0] (if available) to decide which plugin we use.
|
||||
|
|
|
@ -90,13 +90,24 @@ public:
|
|||
vector<macro_decl>::iterator end() const { return m_decls->end(); }
|
||||
};
|
||||
|
||||
|
||||
class proof_cmds {
|
||||
public:
|
||||
virtual ~proof_cmds() {}
|
||||
virtual void add_literal(expr* e) = 0;
|
||||
virtual void end_assumption() = 0;
|
||||
virtual void end_learned() = 0;
|
||||
virtual void end_deleted() = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
\brief Generic wrapper.
|
||||
*/
|
||||
class object_ref {
|
||||
unsigned m_ref_count = 0;
|
||||
public:
|
||||
virtual ~object_ref() {}
|
||||
virtual ~object_ref() = default;
|
||||
virtual void finalize(cmd_context & ctx) = 0;
|
||||
void inc_ref(cmd_context & ctx) {
|
||||
m_ref_count++;
|
||||
|
@ -172,6 +183,7 @@ public:
|
|||
bool owns_manager() const { return m_manager != nullptr; }
|
||||
};
|
||||
|
||||
|
||||
class cmd_context : public progress_callback, public tactic_manager, public ast_printer_context {
|
||||
public:
|
||||
enum status {
|
||||
|
@ -191,6 +203,22 @@ public:
|
|||
~scoped_watch() { m_ctx.m_watch.stop(); }
|
||||
};
|
||||
|
||||
struct scoped_redirect {
|
||||
cmd_context& m_ctx;
|
||||
std::ostream& m_verbose;
|
||||
std::ostream* m_warning;
|
||||
|
||||
scoped_redirect(cmd_context& ctx): m_ctx(ctx), m_verbose(verbose_stream()), m_warning(warning_stream()) {
|
||||
set_warning_stream(&(*m_ctx.m_diagnostic));
|
||||
set_verbose_stream(m_ctx.diagnostic_stream());
|
||||
}
|
||||
|
||||
~scoped_redirect() {
|
||||
set_verbose_stream(m_verbose);
|
||||
set_warning_stream(m_warning);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
@ -209,6 +237,7 @@ protected:
|
|||
bool m_ignore_check = false; // used by the API to disable check-sat() commands when parsing SMT 2.0 files.
|
||||
bool m_exit_on_error = false;
|
||||
bool m_allow_duplicate_declarations = false;
|
||||
scoped_ptr<proof_cmds> m_proof_cmds;
|
||||
|
||||
static std::ostringstream g_error_stream;
|
||||
|
||||
|
@ -381,6 +410,9 @@ public:
|
|||
pdecl_manager & pm() const { if (!m_pmanager) const_cast<cmd_context*>(this)->init_manager(); return *m_pmanager; }
|
||||
sexpr_manager & sm() const { if (!m_sexpr_manager) const_cast<cmd_context*>(this)->m_sexpr_manager = alloc(sexpr_manager); return *m_sexpr_manager; }
|
||||
|
||||
proof_cmds* get_proof_cmds() { return m_proof_cmds.get(); }
|
||||
void set_proof_cmds(proof_cmds* pc) { m_proof_cmds = pc; }
|
||||
|
||||
void set_solver_factory(solver_factory * s);
|
||||
void set_check_sat_result(check_sat_result * r) { m_check_sat_result = r; }
|
||||
check_sat_result * get_check_sat_result() const { return m_check_sat_result.get(); }
|
||||
|
|
|
@ -3,6 +3,7 @@ z3_add_component(extra_cmds
|
|||
dbg_cmds.cpp
|
||||
polynomial_cmds.cpp
|
||||
subpaving_cmds.cpp
|
||||
proof_cmds.cpp
|
||||
COMPONENT_DEPENDENCIES
|
||||
arith_tactics
|
||||
cmd_context
|
||||
|
|
269
src/cmd_context/extra_cmds/proof_cmds.cpp
Normal file
269
src/cmd_context/extra_cmds/proof_cmds.cpp
Normal file
|
@ -0,0 +1,269 @@
|
|||
/*++
|
||||
Copyright (c) 2022 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
proof_cmds.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Commands for reading and checking proofs.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2022-8-26
|
||||
|
||||
Notes:
|
||||
|
||||
Proof checker for clauses created during search.
|
||||
1. Clauses annotated by RUP (reverse unit propagation)
|
||||
are checked to be inferrable using reverse unit propagation
|
||||
based on previous clauses.
|
||||
2. Clauses annotated by supported proof rules (proof hints)
|
||||
are checked by custom proof checkers. There is a proof checker
|
||||
for each proof rule. Main proof checkers just have a single step
|
||||
but the framework allows to compose proof rules, each inference
|
||||
is checked for correctness by a plugin.
|
||||
3. When there are no supported plugin to justify the derived
|
||||
clause, or a custom check fails, the fallback is to check that the
|
||||
derived clause is a consequence of the input clauses using SMT.
|
||||
The last approach is a bail-out and offers a weaker notion of
|
||||
self-validation. It is often (but not always) sufficient for using proof
|
||||
checking for debugging, as the root-cause for an unsound inference in z3
|
||||
does not necessarily manifest when checking the conclusion of the
|
||||
inference. An external proof checker that uses such fallbacks could
|
||||
use several solvers, or bootstrap from a solver that can generate certificates
|
||||
when z3 does not.
|
||||
|
||||
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "util/small_object_allocator.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "smt/smt_solver.h"
|
||||
#include "sat/sat_solver.h"
|
||||
#include "sat/sat_drat.h"
|
||||
#include "sat/smt/euf_proof_checker.h"
|
||||
#include "cmd_context/cmd_context.h"
|
||||
#include <iostream>
|
||||
|
||||
class smt_checker {
|
||||
ast_manager& m;
|
||||
params_ref m_params;
|
||||
|
||||
// for checking proof rules (hints)
|
||||
euf::proof_checker m_checker;
|
||||
|
||||
// for fallback SMT checker
|
||||
scoped_ptr<solver> m_solver;
|
||||
|
||||
// for RUP
|
||||
symbol m_rup;
|
||||
sat::solver m_sat_solver;
|
||||
sat::drat m_drat;
|
||||
sat::literal_vector m_units;
|
||||
sat::literal_vector m_clause;
|
||||
|
||||
void add_units() {
|
||||
auto const& units = m_drat.units();
|
||||
for (unsigned i = m_units.size(); i < units.size(); ++i)
|
||||
m_units.push_back(units[i].first);
|
||||
}
|
||||
|
||||
public:
|
||||
smt_checker(ast_manager& m):
|
||||
m(m),
|
||||
m_checker(m),
|
||||
m_sat_solver(m_params, m.limit()),
|
||||
m_drat(m_sat_solver)
|
||||
{
|
||||
m_params.set_bool("drat.check_unsat", true);
|
||||
m_sat_solver.updt_params(m_params);
|
||||
m_drat.updt_config();
|
||||
m_solver = mk_smt_solver(m, m_params, symbol());
|
||||
m_rup = symbol("rup");
|
||||
}
|
||||
|
||||
bool is_rup(app* proof_hint) {
|
||||
return
|
||||
proof_hint &&
|
||||
proof_hint->get_name() == m_rup;
|
||||
}
|
||||
|
||||
void mk_clause(expr_ref_vector const& clause) {
|
||||
m_clause.reset();
|
||||
for (expr* e : clause) {
|
||||
bool sign = false;
|
||||
while (m.is_not(e, e))
|
||||
sign = !sign;
|
||||
m_clause.push_back(sat::literal(e->get_id(), sign));
|
||||
}
|
||||
}
|
||||
|
||||
void mk_clause(expr* e) {
|
||||
m_clause.reset();
|
||||
bool sign = false;
|
||||
while (m.is_not(e, e))
|
||||
sign = !sign;
|
||||
m_clause.push_back(sat::literal(e->get_id(), sign));
|
||||
}
|
||||
|
||||
bool check_rup(expr_ref_vector const& clause) {
|
||||
add_units();
|
||||
mk_clause(clause);
|
||||
return m_drat.is_drup(m_clause.size(), m_clause.data(), m_units);
|
||||
}
|
||||
|
||||
bool check_rup(expr* u) {
|
||||
add_units();
|
||||
mk_clause(u);
|
||||
return m_drat.is_drup(m_clause.size(), m_clause.data(), m_units);
|
||||
}
|
||||
|
||||
void add_clause(expr_ref_vector const& clause) {
|
||||
mk_clause(clause);
|
||||
m_drat.add(m_clause, sat::status::input());
|
||||
}
|
||||
|
||||
void check(expr_ref_vector& clause, app* proof_hint) {
|
||||
|
||||
if (is_rup(proof_hint) && check_rup(clause)) {
|
||||
std::cout << "(verified-rup)\n";
|
||||
return;
|
||||
}
|
||||
|
||||
expr_ref_vector units(m);
|
||||
if (m_checker.check(clause, proof_hint, units)) {
|
||||
bool units_are_rup = true;
|
||||
for (expr* u : units) {
|
||||
if (!check_rup(u)) {
|
||||
std::cout << "unit " << mk_pp(u, m) << " is not rup\n";
|
||||
units_are_rup = false;
|
||||
}
|
||||
}
|
||||
if (units_are_rup) {
|
||||
std::cout << "(verified-" << proof_hint->get_name() << ")\n";
|
||||
add_clause(clause);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_solver->push();
|
||||
for (expr* lit : clause)
|
||||
m_solver->assert_expr(m.mk_not(lit));
|
||||
lbool is_sat = m_solver->check_sat();
|
||||
if (is_sat != l_false) {
|
||||
std::cout << "did not verify: " << is_sat << " " << clause << "\n\n";
|
||||
m_solver->display(std::cout);
|
||||
if (is_sat == l_true) {
|
||||
model_ref mdl;
|
||||
m_solver->get_model(mdl);
|
||||
std::cout << *mdl << "\n";
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
m_solver->pop(1);
|
||||
std::cout << "(verified-smt)\n";
|
||||
if (proof_hint)
|
||||
std::cout << "(missed-hint " << mk_pp(proof_hint, m) << ")\n";
|
||||
add_clause(clause);
|
||||
}
|
||||
|
||||
void assume(expr_ref_vector const& clause) {
|
||||
add_clause(clause);
|
||||
m_solver->assert_expr(mk_or(clause));
|
||||
}
|
||||
};
|
||||
|
||||
class proof_cmds_imp : public proof_cmds {
|
||||
ast_manager& m;
|
||||
expr_ref_vector m_lits;
|
||||
app_ref m_proof_hint;
|
||||
smt_checker m_checker;
|
||||
public:
|
||||
proof_cmds_imp(ast_manager& m): m(m), m_lits(m), m_proof_hint(m), m_checker(m) {}
|
||||
|
||||
void add_literal(expr* e) override {
|
||||
if (m.is_proof(e))
|
||||
m_proof_hint = to_app(e);
|
||||
else
|
||||
m_lits.push_back(e);
|
||||
}
|
||||
|
||||
void end_assumption() override {
|
||||
m_checker.assume(m_lits);
|
||||
m_lits.reset();
|
||||
m_proof_hint.reset();
|
||||
}
|
||||
|
||||
void end_learned() override {
|
||||
m_checker.check(m_lits, m_proof_hint);
|
||||
m_lits.reset();
|
||||
m_proof_hint.reset();
|
||||
}
|
||||
|
||||
void end_deleted() override {
|
||||
m_lits.reset();
|
||||
m_proof_hint.reset();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static proof_cmds& get(cmd_context& ctx) {
|
||||
if (!ctx.get_proof_cmds())
|
||||
ctx.set_proof_cmds(alloc(proof_cmds_imp, ctx.m()));
|
||||
return *ctx.get_proof_cmds();
|
||||
}
|
||||
|
||||
// assumption
|
||||
class assume_cmd : public cmd {
|
||||
public:
|
||||
assume_cmd():cmd("assume") {}
|
||||
char const* get_usage() const override { return "<expr>+"; }
|
||||
char const * get_descr(cmd_context& ctx) const override { return "proof command for adding assumption (input assertion)"; }
|
||||
unsigned get_arity() const override { return VAR_ARITY; }
|
||||
void prepare(cmd_context & ctx) override {}
|
||||
void finalize(cmd_context & ctx) override {}
|
||||
void failure_cleanup(cmd_context & ctx) override {}
|
||||
cmd_arg_kind next_arg_kind(cmd_context & ctx) const override { return CPK_EXPR; }
|
||||
void set_next_arg(cmd_context & ctx, expr * arg) override { get(ctx).add_literal(arg); }
|
||||
void execute(cmd_context& ctx) override { get(ctx).end_assumption(); }
|
||||
};
|
||||
|
||||
// deleted clause
|
||||
class del_cmd : public cmd {
|
||||
public:
|
||||
del_cmd():cmd("del") {}
|
||||
char const* get_usage() const override { return "<expr>+"; }
|
||||
char const * get_descr(cmd_context& ctx) const override { return "proof command for clause deletion"; }
|
||||
unsigned get_arity() const override { return VAR_ARITY; }
|
||||
void prepare(cmd_context & ctx) override {}
|
||||
void finalize(cmd_context & ctx) override {}
|
||||
void failure_cleanup(cmd_context & ctx) override {}
|
||||
cmd_arg_kind next_arg_kind(cmd_context & ctx) const override { return CPK_EXPR; }
|
||||
void set_next_arg(cmd_context & ctx, expr * arg) override { get(ctx).add_literal(arg); }
|
||||
void execute(cmd_context& ctx) override { get(ctx).end_deleted(); }
|
||||
};
|
||||
|
||||
// learned/redundant clause
|
||||
class learn_cmd : public cmd {
|
||||
public:
|
||||
learn_cmd():cmd("learn") {}
|
||||
char const* get_usage() const override { return "<expr>+"; }
|
||||
char const* get_descr(cmd_context& ctx) const override { return "proof command for learned (redundant) clauses"; }
|
||||
unsigned get_arity() const override { return VAR_ARITY; }
|
||||
void prepare(cmd_context & ctx) override {}
|
||||
void finalize(cmd_context & ctx) override {}
|
||||
void failure_cleanup(cmd_context & ctx) override {}
|
||||
cmd_arg_kind next_arg_kind(cmd_context & ctx) const override { return CPK_EXPR; }
|
||||
void set_next_arg(cmd_context & ctx, expr * arg) override { get(ctx).add_literal(arg); }
|
||||
void execute(cmd_context& ctx) override { get(ctx).end_learned(); }
|
||||
};
|
||||
|
||||
void install_proof_cmds(cmd_context & ctx) {
|
||||
ctx.insert(alloc(del_cmd));
|
||||
ctx.insert(alloc(learn_cmd));
|
||||
ctx.insert(alloc(assume_cmd));
|
||||
}
|
36
src/cmd_context/extra_cmds/proof_cmds.h
Normal file
36
src/cmd_context/extra_cmds/proof_cmds.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*++
|
||||
Copyright (c) 2022 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
proof_cmds.h
|
||||
|
||||
Abstract:
|
||||
Commands for reading proofs.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2022-8-26
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
proof_cmds is a structure that tracks an evidence trail.
|
||||
|
||||
The main interface is to:
|
||||
add literals one by one,
|
||||
add proof hints
|
||||
until receiving end-command: assumption, learned, deleted.
|
||||
Evidence can be checked:
|
||||
- By DRUP
|
||||
- Theory lemmas
|
||||
|
||||
*/
|
||||
|
||||
|
||||
class cmd_context;
|
||||
void install_proof_cmds(cmd_context & ctx);
|
||||
|
|
@ -781,7 +781,7 @@ struct pdecl_manager::sort_info {
|
|||
m_decl(d) {
|
||||
m.inc_ref(d);
|
||||
}
|
||||
virtual ~sort_info() {}
|
||||
virtual ~sort_info() = default;
|
||||
virtual unsigned obj_size() const { return sizeof(sort_info); }
|
||||
virtual void finalize(pdecl_manager & m) { m.dec_ref(m_decl); }
|
||||
virtual void display(std::ostream & out, pdecl_manager const & m) const = 0;
|
||||
|
|
|
@ -38,7 +38,7 @@ protected:
|
|||
virtual size_t obj_size() const { UNREACHABLE(); return sizeof(*this); }
|
||||
pdecl(unsigned id, unsigned num_params):m_id(id), m_num_params(num_params), m_ref_count(0) {}
|
||||
virtual void finalize(pdecl_manager & m) {}
|
||||
virtual ~pdecl() {}
|
||||
virtual ~pdecl() = default;
|
||||
public:
|
||||
virtual bool check_num_params(pdecl * other) const { return m_num_params == other->m_num_params; }
|
||||
unsigned get_num_params() const { return m_num_params; }
|
||||
|
@ -257,7 +257,7 @@ public:
|
|||
|
||||
class new_datatype_eh {
|
||||
public:
|
||||
virtual ~new_datatype_eh() {}
|
||||
virtual ~new_datatype_eh() = default;
|
||||
virtual void operator()(sort * dt, pdecl* pd) = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ Revision History:
|
|||
template<class T>
|
||||
class positive_boolean_algebra {
|
||||
public:
|
||||
virtual ~positive_boolean_algebra() {}
|
||||
virtual ~positive_boolean_algebra() = default;
|
||||
virtual T mk_false() = 0;
|
||||
virtual T mk_true() = 0;
|
||||
virtual T mk_and(T x, T y) = 0;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
Extended Linear Simplification (as exploited in Bosphorus AAAI 2019):
|
||||
- multiply each polynomial by one variable from their orbits.
|
||||
- The orbit of a varible are the variables that occur in the same monomial as it in some polynomial.
|
||||
- The orbit of a variable are the variables that occur in the same monomial as it in some polynomial.
|
||||
- The extended set of polynomials is fed to a linear Gauss Jordan Eliminator that extracts
|
||||
additional linear equalities.
|
||||
- Bosphorus uses M4RI to perform efficient GJE to scale on large bit-matrices.
|
||||
|
@ -32,7 +32,7 @@
|
|||
The method seems rather specific to hardware multipliers so not clear it is useful to
|
||||
generalize.
|
||||
- find monomials that contain pairs of vanishing polynomials, transitively
|
||||
withtout actually inlining.
|
||||
without actually inlining.
|
||||
Then color polynomial variables w by p, resp, q if they occur in polynomial equalities
|
||||
w - r = 0, such that all paths in r contain a node colored by p, resp q.
|
||||
polynomial variables that get colored by both p and q can be set to 0.
|
||||
|
|
|
@ -61,8 +61,7 @@ namespace dd {
|
|||
|
||||
solver::solver(reslimit& lim, pdd_manager& m) :
|
||||
m(m),
|
||||
m_limit(lim),
|
||||
m_conflict(nullptr)
|
||||
m_limit(lim)
|
||||
{}
|
||||
|
||||
solver::~solver() {
|
||||
|
@ -179,9 +178,8 @@ namespace dd {
|
|||
set[i]->set_index(j++);
|
||||
}
|
||||
~scoped_update() {
|
||||
for (; i < sz; ++i) {
|
||||
for (; i < sz; ++i)
|
||||
nextj();
|
||||
}
|
||||
set.shrink(j);
|
||||
}
|
||||
};
|
||||
|
@ -191,23 +189,24 @@ namespace dd {
|
|||
equation& target = *set[sr.i];
|
||||
bool changed_leading_term = false;
|
||||
bool simplified = true;
|
||||
simplified = !done() && simplifier(target, changed_leading_term);
|
||||
simplified = !done() && simplifier(target, changed_leading_term);
|
||||
|
||||
|
||||
if (simplified && is_trivial(target)) {
|
||||
if (simplified && is_trivial(target))
|
||||
retire(&target);
|
||||
}
|
||||
else if (simplified && check_conflict(target)) {
|
||||
// pushed to solved
|
||||
}
|
||||
else if (simplified && changed_leading_term) {
|
||||
push_equation(to_simplify, target);
|
||||
if (!m_var2level.empty()) {
|
||||
if (&m_to_simplify == &set)
|
||||
sr.nextj();
|
||||
else
|
||||
push_equation(to_simplify, target);
|
||||
if (!m_var2level.empty())
|
||||
m_levelp1 = std::max(m_var2level[target.poly().var()]+1, m_levelp1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
sr.nextj();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ private:
|
|||
vector<std::tuple<unsigned, pdd, u_dependency*>> m_subst;
|
||||
mutable u_dependency_manager m_dep_manager;
|
||||
equation_vector m_all_eqs;
|
||||
equation* m_conflict;
|
||||
equation* m_conflict = nullptr;
|
||||
bool m_too_complex;
|
||||
public:
|
||||
solver(reslimit& lim, pdd_manager& m);
|
||||
|
|
|
@ -66,7 +66,7 @@ class heap_trie {
|
|||
unsigned m_ref;
|
||||
public:
|
||||
node(node_t t): m_type(t), m_ref(0) {}
|
||||
virtual ~node() {}
|
||||
virtual ~node() = default;
|
||||
node_t type() const { return m_type; }
|
||||
void inc_ref() { ++m_ref; }
|
||||
void dec_ref() { SASSERT(m_ref > 0); --m_ref; }
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
Abstract:
|
||||
|
||||
intervals with depedency tracking.
|
||||
intervals with dependency tracking.
|
||||
|
||||
Author:
|
||||
Nikolaj Bjorner (nbjorner)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
Abstract:
|
||||
|
||||
intervals with depedency tracking.
|
||||
intervals with dependency tracking.
|
||||
|
||||
Author:
|
||||
Nikolaj Bjorner (nbjorner)
|
||||
|
|
|
@ -518,7 +518,7 @@ std::ostream& emonics::display(std::ostream& out, cell* c) const {
|
|||
|
||||
bool emonics::invariant() const {
|
||||
TRACE("nla_solver_mons", display(tout););
|
||||
// the varible index contains exactly the active monomials
|
||||
// the variable index contains exactly the active monomials
|
||||
unsigned mons = 0;
|
||||
for (lpvar v = 0; v < m_var2index.size(); v++) {
|
||||
if (is_monic_var(v)) {
|
||||
|
@ -546,6 +546,7 @@ bool emonics::invariant() const {
|
|||
}
|
||||
CTRACE("nla_solver_mons", !found, tout << "not found v" << v << ": " << m << "\n";);
|
||||
SASSERT(found);
|
||||
(void)found;
|
||||
c = c->m_next;
|
||||
}
|
||||
while (c != ht.m_head);
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
|
||||
virtual vector<std::pair<mpq, var_index>> coeffs() const = 0;
|
||||
lar_base_constraint(unsigned j, lconstraint_kind kind, const mpq& right_side) :m_kind(kind), m_right_side(right_side), m_active(false), m_j(j) {}
|
||||
virtual ~lar_base_constraint() {}
|
||||
virtual ~lar_base_constraint() = default;
|
||||
|
||||
lconstraint_kind kind() const { return m_kind; }
|
||||
mpq const& rhs() const { return m_right_side; }
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue