3
0
Fork 0
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:
Jakob Rath 2022-09-23 17:14:26 +02:00
commit 1df749ad33
368 changed files with 12363 additions and 6152 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,5 @@
#include "jlcxx/jlcxx.hpp"
#include <sstream>
#include "z3++.h"
using namespace z3;

View file

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

View file

@ -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, &param));
func_decl_info info(func_decl_info(m_family_id, OP_ARRAY_EXT, 1, &param));
info.set_commutative(true);
return m_manager->mk_func_decl(m_array_ext_sym, arity, domain, r, info);
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -83,7 +83,7 @@ public:
class expr_solver {
public:
virtual ~expr_solver() {}
virtual ~expr_solver() = default;
virtual lbool check_sat(expr* e) = 0;
};

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -7,7 +7,7 @@
Abstract:
intervals with depedency tracking.
intervals with dependency tracking.
Author:
Nikolaj Bjorner (nbjorner)

View file

@ -7,7 +7,7 @@
Abstract:
intervals with depedency tracking.
intervals with dependency tracking.
Author:
Nikolaj Bjorner (nbjorner)

View file

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

View file

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