mirror of
https://github.com/Z3Prover/z3
synced 2025-04-10 19:27:06 +00:00
add cube mode
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
ae9a6664d4
20
.travis.yml
20
.travis.yml
|
@ -60,17 +60,15 @@ env:
|
|||
- LINUX_BASE=ubuntu_14.04 C_COMPILER=/usr/bin/gcc-4.8 CXX_COMPILER=/usr/bin/g++-4.8 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug
|
||||
|
||||
# macOS (a.k.a OSX) support
|
||||
# FIXME: macOS support is temporarily disabled due to @wintersteiger 's concerns.
|
||||
# See https://github.com/Z3Prover/z3/pull/1207#issuecomment-322200998
|
||||
# matrix:
|
||||
# include:
|
||||
# # For now just test a single configuration. macOS builds on TravisCI are
|
||||
# # very slow so we should keep the number of configurations we test on this
|
||||
# # OS to a minimum.
|
||||
# - os: osx
|
||||
# osx_image: xcode8.3
|
||||
# # Note: Apple Clang does not support OpenMP
|
||||
# env: Z3_BUILD_TYPE=RelWithDebInfo USE_OPENMP=0
|
||||
matrix:
|
||||
include:
|
||||
# For now just test a single configuration. macOS builds on TravisCI are
|
||||
# very slow so we should keep the number of configurations we test on this
|
||||
# OS to a minimum.
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
# Note: Apple Clang does not support OpenMP
|
||||
env: Z3_BUILD_TYPE=RelWithDebInfo USE_OPENMP=0
|
||||
script:
|
||||
# Use `travis_wait` when doing LTO builds because this configuration will
|
||||
# have long link times during which it will not show any output which
|
||||
|
|
|
@ -3,13 +3,13 @@ Copyright (c) 2015 Microsoft Corporation
|
|||
|
||||
Module Name:
|
||||
|
||||
ackr_model_converter.cpp
|
||||
ackr_model_converter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Author:
|
||||
|
||||
Mikolas Janota
|
||||
Mikolas Janota
|
||||
|
||||
Revision History:
|
||||
--*/
|
||||
|
@ -22,8 +22,8 @@ Revision History:
|
|||
class ackr_model_converter : public model_converter {
|
||||
public:
|
||||
ackr_model_converter(ast_manager & m,
|
||||
const ackr_info_ref& info,
|
||||
model_ref& abstr_model)
|
||||
const ackr_info_ref& info,
|
||||
model_ref& abstr_model)
|
||||
: m(m)
|
||||
, info(info)
|
||||
, abstr_model(abstr_model)
|
||||
|
@ -31,7 +31,7 @@ public:
|
|||
{ }
|
||||
|
||||
ackr_model_converter(ast_manager & m,
|
||||
const ackr_info_ref& info)
|
||||
const ackr_info_ref& info)
|
||||
: m(m)
|
||||
, info(info)
|
||||
, fixed_model(false)
|
||||
|
@ -51,8 +51,6 @@ public:
|
|||
|
||||
virtual void operator()(model_ref & md) { operator()(md, 0); }
|
||||
|
||||
//void display(std::ostream & out);
|
||||
|
||||
virtual model_converter * translate(ast_translation & translator) {
|
||||
ackr_info_ref retv_info = info->translate(translator);
|
||||
if (fixed_model) {
|
||||
|
@ -63,42 +61,45 @@ public:
|
|||
return alloc(ackr_model_converter, translator.to(), retv_info);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
ast_manager& m;
|
||||
ast_manager & m;
|
||||
const ackr_info_ref info;
|
||||
model_ref abstr_model;
|
||||
bool fixed_model;
|
||||
void convert(model * source, model * destination);
|
||||
void add_entry(model_evaluator & evaluator,
|
||||
app* term, expr* value,
|
||||
obj_map<func_decl, func_interp*>& interpretations);
|
||||
app* term, expr* value,
|
||||
obj_map<func_decl, func_interp*>& interpretations);
|
||||
void convert_constants(model * source, model * destination);
|
||||
};
|
||||
|
||||
void ackr_model_converter::convert(model * source, model * destination) {
|
||||
destination->copy_func_interps(*source);
|
||||
destination->copy_usort_interps(*source);
|
||||
convert_constants(source,destination);
|
||||
convert_constants(source, destination);
|
||||
}
|
||||
|
||||
void ackr_model_converter::convert_constants(model * source, model * destination) {
|
||||
TRACE("ackr_model", tout << "converting constants\n";);
|
||||
obj_map<func_decl, func_interp*> interpretations;
|
||||
model_evaluator evaluator(*source);
|
||||
evaluator.set_model_completion(true);
|
||||
for (unsigned i = 0; i < source->get_num_constants(); i++) {
|
||||
func_decl * const c = source->get_constant(i);
|
||||
app * const term = info->find_term(c);
|
||||
expr * value = source->get_const_interp(c);
|
||||
if(!term) {
|
||||
if (!term) {
|
||||
destination->register_decl(c, value);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
add_entry(evaluator, term, value, interpretations);
|
||||
}
|
||||
}
|
||||
|
||||
obj_map<func_decl, func_interp*>::iterator e = interpretations.end();
|
||||
for (obj_map<func_decl, func_interp*>::iterator i = interpretations.begin();
|
||||
i!=e; ++i) {
|
||||
i != e; ++i) {
|
||||
func_decl* const fd = i->m_key;
|
||||
func_interp* const fi = i->get_value();
|
||||
fi->set_else(m.get_some_value(fd->get_range()));
|
||||
|
@ -107,34 +108,40 @@ void ackr_model_converter::convert_constants(model * source, model * destination
|
|||
}
|
||||
|
||||
void ackr_model_converter::add_entry(model_evaluator & evaluator,
|
||||
app* term, expr* value,
|
||||
obj_map<func_decl, func_interp*>& interpretations) {
|
||||
app* term, expr* value,
|
||||
obj_map<func_decl, func_interp*>& interpretations) {
|
||||
TRACE("ackr_model", tout << "add_entry"
|
||||
<< mk_ismt2_pp(term, m, 2)
|
||||
<< "->"
|
||||
<< mk_ismt2_pp(value, m, 2) << "\n";
|
||||
<< mk_ismt2_pp(term, m, 2)
|
||||
<< "->"
|
||||
<< mk_ismt2_pp(value, m, 2) << "\n";
|
||||
);
|
||||
|
||||
func_interp* fi = 0;
|
||||
func_interp * fi = 0;
|
||||
func_decl * const declaration = term->get_decl();
|
||||
const unsigned sz = declaration->get_arity();
|
||||
SASSERT(sz == term->get_num_args());
|
||||
if (!interpretations.find(declaration, fi)) {
|
||||
fi = alloc(func_interp,m,sz);
|
||||
interpretations.insert(declaration, fi);
|
||||
if (!interpretations.find(declaration, fi)) {
|
||||
fi = alloc(func_interp, m, sz);
|
||||
interpretations.insert(declaration, fi);
|
||||
}
|
||||
expr_ref_vector args(m);
|
||||
for (unsigned gi = 0; gi < sz; ++gi) {
|
||||
expr * const arg = term->get_arg(gi);
|
||||
expr_ref aarg(m);
|
||||
info->abstract(arg, aarg);
|
||||
expr_ref arg_value(m);
|
||||
evaluator(aarg,arg_value);
|
||||
args.push_back(arg_value);
|
||||
expr * const arg = term->get_arg(gi);
|
||||
expr_ref aarg(m);
|
||||
info->abstract(arg, aarg);
|
||||
expr_ref arg_value(m);
|
||||
evaluator(aarg, arg_value);
|
||||
args.push_back(arg_value);
|
||||
}
|
||||
if (fi->get_entry(args.c_ptr()) == 0) {
|
||||
TRACE("ackr_model",
|
||||
tout << mk_ismt2_pp(declaration, m) << " args: " << std::endl;
|
||||
for (unsigned i = 0; i < args.size(); i++)
|
||||
tout << mk_ismt2_pp(args.get(i), m) << std::endl;
|
||||
tout << " -> " << mk_ismt2_pp(value, m) << "\n"; );
|
||||
fi->insert_new_entry(args.c_ptr(), value);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
TRACE("ackr_model", tout << "entry already present\n";);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,13 @@ Copyright (c) 2015 Microsoft Corporation
|
|||
|
||||
Module Name:
|
||||
|
||||
ackr_model_converter.h
|
||||
ackr_model_converter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Author:
|
||||
|
||||
Mikolas Janota
|
||||
Mikolas Janota
|
||||
|
||||
Revision History:
|
||||
--*/
|
||||
|
@ -19,7 +19,7 @@ Revision History:
|
|||
#include "tactic/model_converter.h"
|
||||
#include "ackermannization/ackr_info.h"
|
||||
|
||||
model_converter * mk_ackr_model_converter(ast_manager & m, const ackr_info_ref& info, model_ref& abstr_model);
|
||||
model_converter * mk_ackr_model_converter(ast_manager & m, const ackr_info_ref& info);
|
||||
model_converter * mk_ackr_model_converter(ast_manager & m, const ackr_info_ref & info, model_ref & abstr_model);
|
||||
model_converter * mk_ackr_model_converter(ast_manager & m, const ackr_info_ref & info);
|
||||
|
||||
#endif /* LACKR_MODEL_CONVERTER_H_ */
|
||||
|
|
|
@ -1204,16 +1204,8 @@ extern "C" {
|
|||
case OP_FPA_TO_SBV: return Z3_OP_FPA_TO_SBV;
|
||||
case OP_FPA_TO_REAL: return Z3_OP_FPA_TO_REAL;
|
||||
case OP_FPA_TO_IEEE_BV: return Z3_OP_FPA_TO_IEEE_BV;
|
||||
case OP_FPA_INTERNAL_MIN_I: return Z3_OP_FPA_MIN_I;
|
||||
case OP_FPA_INTERNAL_MAX_I: return Z3_OP_FPA_MAX_I;
|
||||
case OP_FPA_INTERNAL_BV2RM:
|
||||
case OP_FPA_INTERNAL_BVWRAP:
|
||||
case OP_FPA_INTERNAL_MIN_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_MAX_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED:
|
||||
case OP_FPA_BVWRAP: return Z3_OP_FPA_BVWRAP;
|
||||
case OP_FPA_BV2RM: return Z3_OP_FPA_BV2RM;
|
||||
return Z3_OP_UNINTERPRETED;
|
||||
default:
|
||||
return Z3_OP_INTERNAL;
|
||||
|
|
|
@ -354,7 +354,7 @@ namespace z3 {
|
|||
Z3_error_code check_error() const { return m_ctx->check_error(); }
|
||||
friend void check_context(object const & a, object const & b);
|
||||
};
|
||||
inline void check_context(object const & a, object const & b) { assert(a.m_ctx == b.m_ctx); }
|
||||
inline void check_context(object const & a, object const & b) { (void)a; (void)b; assert(a.m_ctx == b.m_ctx); }
|
||||
|
||||
class symbol : public object {
|
||||
Z3_symbol m_sym;
|
||||
|
|
|
@ -15,16 +15,16 @@ Copyright (c) 2015 Microsoft Corporation
|
|||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,78 +43,78 @@ add_custom_command(OUTPUT "${Z3_DOTNET_CONST_FILE}"
|
|||
)
|
||||
|
||||
set(Z3_DOTNET_ASSEMBLY_SOURCES_IN_SRC_TREE
|
||||
AlgebraicNum.cs
|
||||
ApplyResult.cs
|
||||
ArithExpr.cs
|
||||
ArithSort.cs
|
||||
ArrayExpr.cs
|
||||
ArraySort.cs
|
||||
AST.cs
|
||||
ASTMap.cs
|
||||
ASTVector.cs
|
||||
BitVecExpr.cs
|
||||
BitVecNum.cs
|
||||
BitVecSort.cs
|
||||
BoolExpr.cs
|
||||
BoolSort.cs
|
||||
Constructor.cs
|
||||
ConstructorList.cs
|
||||
Context.cs
|
||||
DatatypeExpr.cs
|
||||
DatatypeSort.cs
|
||||
Deprecated.cs
|
||||
EnumSort.cs
|
||||
Expr.cs
|
||||
FiniteDomainExpr.cs
|
||||
FiniteDomainNum.cs
|
||||
FiniteDomainSort.cs
|
||||
Fixedpoint.cs
|
||||
FPExpr.cs
|
||||
FPNum.cs
|
||||
FPRMExpr.cs
|
||||
FPRMNum.cs
|
||||
FPRMSort.cs
|
||||
FPSort.cs
|
||||
FuncDecl.cs
|
||||
FuncInterp.cs
|
||||
Global.cs
|
||||
Goal.cs
|
||||
IDecRefQueue.cs
|
||||
InterpolationContext.cs
|
||||
IntExpr.cs
|
||||
IntNum.cs
|
||||
IntSort.cs
|
||||
IntSymbol.cs
|
||||
ListSort.cs
|
||||
Log.cs
|
||||
Model.cs
|
||||
Optimize.cs
|
||||
ParamDescrs.cs
|
||||
Params.cs
|
||||
Pattern.cs
|
||||
Probe.cs
|
||||
Quantifier.cs
|
||||
RatNum.cs
|
||||
RealExpr.cs
|
||||
RealSort.cs
|
||||
ReExpr.cs
|
||||
RelationSort.cs
|
||||
ReSort.cs
|
||||
SeqExpr.cs
|
||||
SeqSort.cs
|
||||
SetSort.cs
|
||||
Solver.cs
|
||||
Sort.cs
|
||||
Statistics.cs
|
||||
Status.cs
|
||||
StringSymbol.cs
|
||||
Symbol.cs
|
||||
Tactic.cs
|
||||
TupleSort.cs
|
||||
UninterpretedSort.cs
|
||||
Version.cs
|
||||
Z3Exception.cs
|
||||
Z3Object.cs
|
||||
AlgebraicNum.cs
|
||||
ApplyResult.cs
|
||||
ArithExpr.cs
|
||||
ArithSort.cs
|
||||
ArrayExpr.cs
|
||||
ArraySort.cs
|
||||
AST.cs
|
||||
ASTMap.cs
|
||||
ASTVector.cs
|
||||
BitVecExpr.cs
|
||||
BitVecNum.cs
|
||||
BitVecSort.cs
|
||||
BoolExpr.cs
|
||||
BoolSort.cs
|
||||
Constructor.cs
|
||||
ConstructorList.cs
|
||||
Context.cs
|
||||
DatatypeExpr.cs
|
||||
DatatypeSort.cs
|
||||
Deprecated.cs
|
||||
EnumSort.cs
|
||||
Expr.cs
|
||||
FiniteDomainExpr.cs
|
||||
FiniteDomainNum.cs
|
||||
FiniteDomainSort.cs
|
||||
Fixedpoint.cs
|
||||
FPExpr.cs
|
||||
FPNum.cs
|
||||
FPRMExpr.cs
|
||||
FPRMNum.cs
|
||||
FPRMSort.cs
|
||||
FPSort.cs
|
||||
FuncDecl.cs
|
||||
FuncInterp.cs
|
||||
Global.cs
|
||||
Goal.cs
|
||||
IDecRefQueue.cs
|
||||
InterpolationContext.cs
|
||||
IntExpr.cs
|
||||
IntNum.cs
|
||||
IntSort.cs
|
||||
IntSymbol.cs
|
||||
ListSort.cs
|
||||
Log.cs
|
||||
Model.cs
|
||||
Optimize.cs
|
||||
ParamDescrs.cs
|
||||
Params.cs
|
||||
Pattern.cs
|
||||
Probe.cs
|
||||
Quantifier.cs
|
||||
RatNum.cs
|
||||
RealExpr.cs
|
||||
RealSort.cs
|
||||
ReExpr.cs
|
||||
RelationSort.cs
|
||||
ReSort.cs
|
||||
SeqExpr.cs
|
||||
SeqSort.cs
|
||||
SetSort.cs
|
||||
Solver.cs
|
||||
Sort.cs
|
||||
Statistics.cs
|
||||
Status.cs
|
||||
StringSymbol.cs
|
||||
Symbol.cs
|
||||
Tactic.cs
|
||||
TupleSort.cs
|
||||
UninterpretedSort.cs
|
||||
Version.cs
|
||||
Z3Exception.cs
|
||||
Z3Object.cs
|
||||
)
|
||||
|
||||
set(Z3_DOTNET_ASSEMBLY_SOURCES "")
|
||||
|
|
|
@ -126,7 +126,7 @@ namespace Microsoft.Z3
|
|||
private BoolSort m_boolSort = null;
|
||||
private IntSort m_intSort = null;
|
||||
private RealSort m_realSort = null;
|
||||
private SeqSort m_stringSort = null;
|
||||
private SeqSort m_stringSort = null;
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the Boolean sort of the context.
|
||||
|
@ -2426,7 +2426,7 @@ namespace Microsoft.Z3
|
|||
public SeqExpr IntToString(Expr e)
|
||||
{
|
||||
Contract.Requires(e != null);
|
||||
Contract.Requires(e is ArithExpr);
|
||||
Contract.Requires(e is ArithExpr);
|
||||
Contract.Ensures(Contract.Result<SeqExpr>() != null);
|
||||
return new SeqExpr(this, Native.Z3_mk_int_to_str(nCtx, e.NativeObject));
|
||||
}
|
||||
|
@ -2690,7 +2690,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Create a range expression.
|
||||
/// </summary>
|
||||
public ReExpr MkRange(SeqExpr lo, SeqExpr hi)
|
||||
public ReExpr MkRange(SeqExpr lo, SeqExpr hi)
|
||||
{
|
||||
Contract.Requires(lo != null);
|
||||
Contract.Requires(hi != null);
|
||||
|
|
|
@ -809,55 +809,55 @@ namespace Microsoft.Z3
|
|||
/// Check whether expression is a concatentation.
|
||||
/// </summary>
|
||||
/// <returns>a Boolean</returns>
|
||||
public bool IsConcat { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_CONCAT; } }
|
||||
public bool IsConcat { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_CONCAT; } }
|
||||
|
||||
/// <summary>
|
||||
/// Check whether expression is a prefix.
|
||||
/// </summary>
|
||||
/// <returns>a Boolean</returns>
|
||||
public bool IsPrefix { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_PREFIX; } }
|
||||
public bool IsPrefix { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_PREFIX; } }
|
||||
|
||||
/// <summary>
|
||||
/// Check whether expression is a suffix.
|
||||
/// </summary>
|
||||
/// <returns>a Boolean</returns>
|
||||
public bool IsSuffix { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_SUFFIX; } }
|
||||
public bool IsSuffix { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_SUFFIX; } }
|
||||
|
||||
/// <summary>
|
||||
/// Check whether expression is a contains.
|
||||
/// </summary>
|
||||
/// <returns>a Boolean</returns>
|
||||
public bool IsContains { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_CONTAINS; } }
|
||||
public bool IsContains { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_CONTAINS; } }
|
||||
|
||||
/// <summary>
|
||||
/// Check whether expression is an extract.
|
||||
/// </summary>
|
||||
/// <returns>a Boolean</returns>
|
||||
public bool IsExtract { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_EXTRACT; } }
|
||||
public bool IsExtract { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_EXTRACT; } }
|
||||
|
||||
/// <summary>
|
||||
/// Check whether expression is a replace.
|
||||
/// </summary>
|
||||
/// <returns>a Boolean</returns>
|
||||
public bool IsReplace { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_REPLACE; } }
|
||||
public bool IsReplace { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_REPLACE; } }
|
||||
|
||||
/// <summary>
|
||||
/// Check whether expression is an at.
|
||||
/// </summary>
|
||||
/// <returns>a Boolean</returns>
|
||||
public bool IsAt { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_AT; } }
|
||||
public bool IsAt { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_AT; } }
|
||||
|
||||
/// <summary>
|
||||
/// Check whether expression is a sequence length.
|
||||
/// </summary>
|
||||
/// <returns>a Boolean</returns>
|
||||
public bool IsLength { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_LENGTH; } }
|
||||
public bool IsLength { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_LENGTH; } }
|
||||
|
||||
/// <summary>
|
||||
/// Check whether expression is a sequence index.
|
||||
/// </summary>
|
||||
/// <returns>a Boolean</returns>
|
||||
public bool IsIndex { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_INDEX; } }
|
||||
public bool IsIndex { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_INDEX; } }
|
||||
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -123,7 +123,7 @@ namespace Microsoft.Z3
|
|||
|
||||
/// <summary>
|
||||
/// Retrieve a lower bound for the objective handle.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
public ArithExpr Lower
|
||||
{
|
||||
get { return opt.GetLower(handle); }
|
||||
|
@ -131,7 +131,7 @@ namespace Microsoft.Z3
|
|||
|
||||
/// <summary>
|
||||
/// Retrieve an upper bound for the objective handle.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
public ArithExpr Upper
|
||||
{
|
||||
get { return opt.GetUpper(handle); }
|
||||
|
@ -139,7 +139,7 @@ namespace Microsoft.Z3
|
|||
|
||||
/// <summary>
|
||||
/// Retrieve the value of an objective.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
public ArithExpr Value
|
||||
{
|
||||
get { return Lower; }
|
||||
|
@ -147,7 +147,7 @@ namespace Microsoft.Z3
|
|||
|
||||
/// <summary>
|
||||
/// Retrieve a lower bound for the objective handle.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
public ArithExpr[] LowerAsVector
|
||||
{
|
||||
get { return opt.GetLowerAsVector(handle); }
|
||||
|
@ -155,7 +155,7 @@ namespace Microsoft.Z3
|
|||
|
||||
/// <summary>
|
||||
/// Retrieve an upper bound for the objective handle.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
public ArithExpr[] UpperAsVector
|
||||
{
|
||||
get { return opt.GetUpperAsVector(handle); }
|
||||
|
@ -240,7 +240,7 @@ namespace Microsoft.Z3
|
|||
/// Declare an arithmetical maximization objective.
|
||||
/// Return a handle to the objective. The handle is used as
|
||||
/// to retrieve the values of objectives after calling Check.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
public Handle MkMaximize(ArithExpr e)
|
||||
{
|
||||
return new Handle(this, Native.Z3_optimize_maximize(Context.nCtx, NativeObject, e.NativeObject));
|
||||
|
@ -249,7 +249,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Declare an arithmetical minimization objective.
|
||||
/// Similar to MkMaximize.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
public Handle MkMinimize(ArithExpr e)
|
||||
{
|
||||
return new Handle(this, Native.Z3_optimize_minimize(Context.nCtx, NativeObject, e.NativeObject));
|
||||
|
@ -257,7 +257,7 @@ namespace Microsoft.Z3
|
|||
|
||||
/// <summary>
|
||||
/// Retrieve a lower bound for the objective handle.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
private ArithExpr GetLower(uint index)
|
||||
{
|
||||
return (ArithExpr)Expr.Create(Context, Native.Z3_optimize_get_lower(Context.nCtx, NativeObject, index));
|
||||
|
@ -266,7 +266,7 @@ namespace Microsoft.Z3
|
|||
|
||||
/// <summary>
|
||||
/// Retrieve an upper bound for the objective handle.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
private ArithExpr GetUpper(uint index)
|
||||
{
|
||||
return (ArithExpr)Expr.Create(Context, Native.Z3_optimize_get_upper(Context.nCtx, NativeObject, index));
|
||||
|
@ -274,7 +274,7 @@ namespace Microsoft.Z3
|
|||
|
||||
/// <summary>
|
||||
/// Retrieve a lower bound for the objective handle.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
private ArithExpr[] GetLowerAsVector(uint index)
|
||||
{
|
||||
ASTVector v = new ASTVector(Context, Native.Z3_optimize_get_lower_as_vector(Context.nCtx, NativeObject, index));
|
||||
|
@ -284,29 +284,29 @@ namespace Microsoft.Z3
|
|||
|
||||
/// <summary>
|
||||
/// Retrieve an upper bound for the objective handle.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
private ArithExpr[] GetUpperAsVector(uint index)
|
||||
{
|
||||
ASTVector v = new ASTVector(Context, Native.Z3_optimize_get_upper_as_vector(Context.nCtx, NativeObject, index));
|
||||
return v.ToArithExprArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a string the describes why the last to check returned unknown
|
||||
/// </summary>
|
||||
public String ReasonUnknown
|
||||
{
|
||||
/// <summary>
|
||||
/// Return a string the describes why the last to check returned unknown
|
||||
/// </summary>
|
||||
public String ReasonUnknown
|
||||
{
|
||||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<string>() != null);
|
||||
return Native.Z3_optimize_get_reason_unknown(Context.nCtx, NativeObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Print the context to a string (SMT-LIB parseable benchmark).
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
return Native.Z3_optimize_to_string(Context.nCtx, NativeObject);
|
||||
|
|
|
@ -8,41 +8,41 @@ EndProject
|
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example", "Example\Example.csproj", "{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x64.ActiveCfg = Release|x64
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x64.Build.0 = Release|x64
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|x64.ActiveCfg = Release|x64
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|x64.Build.0 = Release|x64
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x64.ActiveCfg = Release|x64
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x64.Build.0 = Release|x64
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|x64.ActiveCfg = Release|x64
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|x64.Build.0 = Release|x64
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -131,7 +131,7 @@ public class ASTVector extends Z3Object {
|
|||
Expr[] res = new Expr[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
res[i] = Expr.create(getContext(), get(i).getNativeObject());
|
||||
return res;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,57 +22,57 @@ package com.microsoft.z3;
|
|||
**/
|
||||
public class AlgebraicNum extends ArithExpr
|
||||
{
|
||||
/**
|
||||
* Return a upper bound for a given real algebraic number. The interval
|
||||
* isolating the number is smaller than 1/10^{@code precision}.
|
||||
*
|
||||
* @see Expr#isAlgebraicNumber
|
||||
* @param precision the precision of the result
|
||||
*
|
||||
* @return A numeral Expr of sort Real
|
||||
* @throws Z3Exception on error
|
||||
**/
|
||||
public RatNum toUpper(int precision)
|
||||
{
|
||||
/**
|
||||
* Return a upper bound for a given real algebraic number. The interval
|
||||
* isolating the number is smaller than 1/10^{@code precision}.
|
||||
*
|
||||
* @see Expr#isAlgebraicNumber
|
||||
* @param precision the precision of the result
|
||||
*
|
||||
* @return A numeral Expr of sort Real
|
||||
* @throws Z3Exception on error
|
||||
**/
|
||||
public RatNum toUpper(int precision)
|
||||
{
|
||||
|
||||
return new RatNum(getContext(), Native.getAlgebraicNumberUpper(getContext()
|
||||
.nCtx(), getNativeObject(), precision));
|
||||
}
|
||||
return new RatNum(getContext(), Native.getAlgebraicNumberUpper(getContext()
|
||||
.nCtx(), getNativeObject(), precision));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a lower bound for the given real algebraic number. The interval
|
||||
* isolating the number is smaller than 1/10^{@code precision}.
|
||||
*
|
||||
* @see Expr#isAlgebraicNumber
|
||||
* @param precision precision
|
||||
*
|
||||
* @return A numeral Expr of sort Real
|
||||
* @throws Z3Exception on error
|
||||
**/
|
||||
public RatNum toLower(int precision)
|
||||
{
|
||||
/**
|
||||
* Return a lower bound for the given real algebraic number. The interval
|
||||
* isolating the number is smaller than 1/10^{@code precision}.
|
||||
*
|
||||
* @see Expr#isAlgebraicNumber
|
||||
* @param precision precision
|
||||
*
|
||||
* @return A numeral Expr of sort Real
|
||||
* @throws Z3Exception on error
|
||||
**/
|
||||
public RatNum toLower(int precision)
|
||||
{
|
||||
|
||||
return new RatNum(getContext(), Native.getAlgebraicNumberLower(getContext()
|
||||
.nCtx(), getNativeObject(), precision));
|
||||
}
|
||||
return new RatNum(getContext(), Native.getAlgebraicNumberLower(getContext()
|
||||
.nCtx(), getNativeObject(), precision));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation in decimal notation.
|
||||
* Remarks: The result has at most {@code precision} decimal places.
|
||||
* @param precision precision
|
||||
* @return String
|
||||
* @throws Z3Exception on error
|
||||
**/
|
||||
public String toDecimal(int precision)
|
||||
{
|
||||
/**
|
||||
* Returns a string representation in decimal notation.
|
||||
* Remarks: The result has at most {@code precision} decimal places.
|
||||
* @param precision precision
|
||||
* @return String
|
||||
* @throws Z3Exception on error
|
||||
**/
|
||||
public String toDecimal(int precision)
|
||||
{
|
||||
|
||||
return Native.getNumeralDecimalString(getContext().nCtx(), getNativeObject(),
|
||||
precision);
|
||||
}
|
||||
return Native.getNumeralDecimalString(getContext().nCtx(), getNativeObject(),
|
||||
precision);
|
||||
}
|
||||
|
||||
AlgebraicNum(Context ctx, long obj)
|
||||
{
|
||||
super(ctx, obj);
|
||||
AlgebraicNum(Context ctx, long obj)
|
||||
{
|
||||
super(ctx, obj);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1898,8 +1898,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public SeqExpr mkEmptySeq(Sort s)
|
||||
{
|
||||
checkContextMatch(s);
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqEmpty(nCtx(), s.getNativeObject()));
|
||||
checkContextMatch(s);
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqEmpty(nCtx(), s.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1907,8 +1907,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public SeqExpr mkUnit(Expr elem)
|
||||
{
|
||||
checkContextMatch(elem);
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqUnit(nCtx(), elem.getNativeObject()));
|
||||
checkContextMatch(elem);
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqUnit(nCtx(), elem.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1916,7 +1916,7 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public SeqExpr mkString(String s)
|
||||
{
|
||||
return (SeqExpr) Expr.create(this, Native.mkString(nCtx(), s));
|
||||
return (SeqExpr) Expr.create(this, Native.mkString(nCtx(), s));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1924,8 +1924,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public SeqExpr mkConcat(SeqExpr... t)
|
||||
{
|
||||
checkContextMatch(t);
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqConcat(nCtx(), t.length, AST.arrayToNative(t)));
|
||||
checkContextMatch(t);
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqConcat(nCtx(), t.length, AST.arrayToNative(t)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1934,8 +1934,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public IntExpr mkLength(SeqExpr s)
|
||||
{
|
||||
checkContextMatch(s);
|
||||
return (IntExpr) Expr.create(this, Native.mkSeqLength(nCtx(), s.getNativeObject()));
|
||||
checkContextMatch(s);
|
||||
return (IntExpr) Expr.create(this, Native.mkSeqLength(nCtx(), s.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1943,8 +1943,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public BoolExpr mkPrefixOf(SeqExpr s1, SeqExpr s2)
|
||||
{
|
||||
checkContextMatch(s1, s2);
|
||||
return (BoolExpr) Expr.create(this, Native.mkSeqPrefix(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
|
||||
checkContextMatch(s1, s2);
|
||||
return (BoolExpr) Expr.create(this, Native.mkSeqPrefix(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1952,8 +1952,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public BoolExpr mkSuffixOf(SeqExpr s1, SeqExpr s2)
|
||||
{
|
||||
checkContextMatch(s1, s2);
|
||||
return (BoolExpr)Expr.create(this, Native.mkSeqSuffix(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
|
||||
checkContextMatch(s1, s2);
|
||||
return (BoolExpr)Expr.create(this, Native.mkSeqSuffix(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1961,8 +1961,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public BoolExpr mkContains(SeqExpr s1, SeqExpr s2)
|
||||
{
|
||||
checkContextMatch(s1, s2);
|
||||
return (BoolExpr) Expr.create(this, Native.mkSeqContains(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
|
||||
checkContextMatch(s1, s2);
|
||||
return (BoolExpr) Expr.create(this, Native.mkSeqContains(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1970,8 +1970,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public SeqExpr mkAt(SeqExpr s, IntExpr index)
|
||||
{
|
||||
checkContextMatch(s, index);
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqAt(nCtx(), s.getNativeObject(), index.getNativeObject()));
|
||||
checkContextMatch(s, index);
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqAt(nCtx(), s.getNativeObject(), index.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1979,8 +1979,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public SeqExpr mkExtract(SeqExpr s, IntExpr offset, IntExpr length)
|
||||
{
|
||||
checkContextMatch(s, offset, length);
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqExtract(nCtx(), s.getNativeObject(), offset.getNativeObject(), length.getNativeObject()));
|
||||
checkContextMatch(s, offset, length);
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqExtract(nCtx(), s.getNativeObject(), offset.getNativeObject(), length.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1988,8 +1988,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public IntExpr mkIndexOf(SeqExpr s, SeqExpr substr, ArithExpr offset)
|
||||
{
|
||||
checkContextMatch(s, substr, offset);
|
||||
return (IntExpr)Expr.create(this, Native.mkSeqIndex(nCtx(), s.getNativeObject(), substr.getNativeObject(), offset.getNativeObject()));
|
||||
checkContextMatch(s, substr, offset);
|
||||
return (IntExpr)Expr.create(this, Native.mkSeqIndex(nCtx(), s.getNativeObject(), substr.getNativeObject(), offset.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1997,8 +1997,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public SeqExpr mkReplace(SeqExpr s, SeqExpr src, SeqExpr dst)
|
||||
{
|
||||
checkContextMatch(s, src, dst);
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqReplace(nCtx(), s.getNativeObject(), src.getNativeObject(), dst.getNativeObject()));
|
||||
checkContextMatch(s, src, dst);
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqReplace(nCtx(), s.getNativeObject(), src.getNativeObject(), dst.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2006,8 +2006,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public ReExpr mkToRe(SeqExpr s)
|
||||
{
|
||||
checkContextMatch(s);
|
||||
return (ReExpr) Expr.create(this, Native.mkSeqToRe(nCtx(), s.getNativeObject()));
|
||||
checkContextMatch(s);
|
||||
return (ReExpr) Expr.create(this, Native.mkSeqToRe(nCtx(), s.getNativeObject()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2016,8 +2016,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public BoolExpr mkInRe(SeqExpr s, ReExpr re)
|
||||
{
|
||||
checkContextMatch(s, re);
|
||||
return (BoolExpr) Expr.create(this, Native.mkSeqInRe(nCtx(), s.getNativeObject(), re.getNativeObject()));
|
||||
checkContextMatch(s, re);
|
||||
return (BoolExpr) Expr.create(this, Native.mkSeqInRe(nCtx(), s.getNativeObject(), re.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2025,8 +2025,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public ReExpr mkStar(ReExpr re)
|
||||
{
|
||||
checkContextMatch(re);
|
||||
return (ReExpr) Expr.create(this, Native.mkReStar(nCtx(), re.getNativeObject()));
|
||||
checkContextMatch(re);
|
||||
return (ReExpr) Expr.create(this, Native.mkReStar(nCtx(), re.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2034,7 +2034,7 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public ReExpr mkLoop(ReExpr re, int lo, int hi)
|
||||
{
|
||||
return (ReExpr) Expr.create(this, Native.mkReLoop(nCtx(), re.getNativeObject(), lo, hi));
|
||||
return (ReExpr) Expr.create(this, Native.mkReLoop(nCtx(), re.getNativeObject(), lo, hi));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2042,7 +2042,7 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public ReExpr mkLoop(ReExpr re, int lo)
|
||||
{
|
||||
return (ReExpr) Expr.create(this, Native.mkReLoop(nCtx(), re.getNativeObject(), lo, 0));
|
||||
return (ReExpr) Expr.create(this, Native.mkReLoop(nCtx(), re.getNativeObject(), lo, 0));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2051,8 +2051,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public ReExpr mkPlus(ReExpr re)
|
||||
{
|
||||
checkContextMatch(re);
|
||||
return (ReExpr) Expr.create(this, Native.mkRePlus(nCtx(), re.getNativeObject()));
|
||||
checkContextMatch(re);
|
||||
return (ReExpr) Expr.create(this, Native.mkRePlus(nCtx(), re.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2060,8 +2060,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public ReExpr mkOption(ReExpr re)
|
||||
{
|
||||
checkContextMatch(re);
|
||||
return (ReExpr) Expr.create(this, Native.mkReOption(nCtx(), re.getNativeObject()));
|
||||
checkContextMatch(re);
|
||||
return (ReExpr) Expr.create(this, Native.mkReOption(nCtx(), re.getNativeObject()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2070,8 +2070,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public ReExpr mkComplement(ReExpr re)
|
||||
{
|
||||
checkContextMatch(re);
|
||||
return (ReExpr) Expr.create(this, Native.mkReComplement(nCtx(), re.getNativeObject()));
|
||||
checkContextMatch(re);
|
||||
return (ReExpr) Expr.create(this, Native.mkReComplement(nCtx(), re.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2079,8 +2079,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public ReExpr mkConcat(ReExpr... t)
|
||||
{
|
||||
checkContextMatch(t);
|
||||
return (ReExpr) Expr.create(this, Native.mkReConcat(nCtx(), t.length, AST.arrayToNative(t)));
|
||||
checkContextMatch(t);
|
||||
return (ReExpr) Expr.create(this, Native.mkReConcat(nCtx(), t.length, AST.arrayToNative(t)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2088,8 +2088,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public ReExpr mkUnion(ReExpr... t)
|
||||
{
|
||||
checkContextMatch(t);
|
||||
return (ReExpr) Expr.create(this, Native.mkReUnion(nCtx(), t.length, AST.arrayToNative(t)));
|
||||
checkContextMatch(t);
|
||||
return (ReExpr) Expr.create(this, Native.mkReUnion(nCtx(), t.length, AST.arrayToNative(t)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2097,8 +2097,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public ReExpr mkIntersect(ReExpr... t)
|
||||
{
|
||||
checkContextMatch(t);
|
||||
return (ReExpr) Expr.create(this, Native.mkReIntersect(nCtx(), t.length, AST.arrayToNative(t)));
|
||||
checkContextMatch(t);
|
||||
return (ReExpr) Expr.create(this, Native.mkReIntersect(nCtx(), t.length, AST.arrayToNative(t)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2106,8 +2106,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public ReExpr MkRange(SeqExpr lo, SeqExpr hi)
|
||||
{
|
||||
checkContextMatch(lo, hi);
|
||||
return (ReExpr) Expr.create(this, Native.mkReRange(nCtx(), lo.getNativeObject(), hi.getNativeObject()));
|
||||
checkContextMatch(lo, hi);
|
||||
return (ReExpr) Expr.create(this, Native.mkReRange(nCtx(), lo.getNativeObject(), hi.getNativeObject()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2116,8 +2116,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public BoolExpr mkAtMost(BoolExpr[] args, int k)
|
||||
{
|
||||
checkContextMatch(args);
|
||||
return (BoolExpr) Expr.create(this, Native.mkAtmost(nCtx(), args.length, AST.arrayToNative(args), k));
|
||||
checkContextMatch(args);
|
||||
return (BoolExpr) Expr.create(this, Native.mkAtmost(nCtx(), args.length, AST.arrayToNative(args), k));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2125,8 +2125,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public BoolExpr mkAtLeast(BoolExpr[] args, int k)
|
||||
{
|
||||
checkContextMatch(args);
|
||||
return (BoolExpr) Expr.create(this, Native.mkAtleast(nCtx(), args.length, AST.arrayToNative(args), k));
|
||||
checkContextMatch(args);
|
||||
return (BoolExpr) Expr.create(this, Native.mkAtleast(nCtx(), args.length, AST.arrayToNative(args), k));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2134,8 +2134,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public BoolExpr mkPBLe(int[] coeffs, BoolExpr[] args, int k)
|
||||
{
|
||||
checkContextMatch(args);
|
||||
return (BoolExpr) Expr.create(this, Native.mkPble(nCtx(), args.length, AST.arrayToNative(args), coeffs, k));
|
||||
checkContextMatch(args);
|
||||
return (BoolExpr) Expr.create(this, Native.mkPble(nCtx(), args.length, AST.arrayToNative(args), coeffs, k));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2143,8 +2143,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public BoolExpr mkPBGe(int[] coeffs, BoolExpr[] args, int k)
|
||||
{
|
||||
checkContextMatch(args);
|
||||
return (BoolExpr) Expr.create(this, Native.mkPbge(nCtx(), args.length, AST.arrayToNative(args), coeffs, k));
|
||||
checkContextMatch(args);
|
||||
return (BoolExpr) Expr.create(this, Native.mkPbge(nCtx(), args.length, AST.arrayToNative(args), coeffs, k));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2152,8 +2152,8 @@ public class Context implements AutoCloseable {
|
|||
*/
|
||||
public BoolExpr mkPBEq(int[] coeffs, BoolExpr[] args, int k)
|
||||
{
|
||||
checkContextMatch(args);
|
||||
return (BoolExpr) Expr.create(this, Native.mkPbeq(nCtx(), args.length, AST.arrayToNative(args), coeffs, k));
|
||||
checkContextMatch(args);
|
||||
return (BoolExpr) Expr.create(this, Native.mkPbeq(nCtx(), args.length, AST.arrayToNative(args), coeffs, k));
|
||||
}
|
||||
|
||||
|
||||
|
@ -3990,15 +3990,15 @@ public class Context implements AutoCloseable {
|
|||
|
||||
void checkContextMatch(Z3Object other1, Z3Object other2)
|
||||
{
|
||||
checkContextMatch(other1);
|
||||
checkContextMatch(other2);
|
||||
checkContextMatch(other1);
|
||||
checkContextMatch(other2);
|
||||
}
|
||||
|
||||
void checkContextMatch(Z3Object other1, Z3Object other2, Z3Object other3)
|
||||
{
|
||||
checkContextMatch(other1);
|
||||
checkContextMatch(other2);
|
||||
checkContextMatch(other3);
|
||||
checkContextMatch(other1);
|
||||
checkContextMatch(other2);
|
||||
checkContextMatch(other3);
|
||||
}
|
||||
|
||||
void checkContextMatch(Z3Object[] arr)
|
||||
|
|
|
@ -65,7 +65,7 @@ public class EnumSort extends Sort
|
|||
**/
|
||||
public Expr getConst(int inx)
|
||||
{
|
||||
return getContext().mkApp(getConstDecl(inx));
|
||||
return getContext().mkApp(getConstDecl(inx));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1287,7 +1287,7 @@ public class Expr extends AST
|
|||
*/
|
||||
public String getString()
|
||||
{
|
||||
return Native.getString(getContext().nCtx(), getNativeObject());
|
||||
return Native.getString(getContext().nCtx(), getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -200,7 +200,7 @@ public class Model extends Z3Object {
|
|||
* Remarks: This function may fail if {@code t} contains
|
||||
* quantifiers, is partial (MODEL_PARTIAL enabled), or if {@code t} is not well-sorted. In this case a
|
||||
* {@code ModelEvaluationFailedException} is thrown.
|
||||
* @param t the expression to evaluate
|
||||
* @param t the expression to evaluate
|
||||
* @param completion An expression {@code completion} When this flag
|
||||
* is enabled, a model value will be assigned to any constant or function
|
||||
* that does not have an interpretation in the model.
|
||||
|
|
|
@ -213,7 +213,7 @@ public class Optimize extends Z3Object {
|
|||
* Declare an arithmetical maximization objective.
|
||||
* Return a handle to the objective. The handle is used as
|
||||
* to retrieve the values of objectives after calling Check.
|
||||
**/
|
||||
**/
|
||||
public Handle MkMaximize(ArithExpr e)
|
||||
{
|
||||
return new Handle(this, Native.optimizeMaximize(getContext().nCtx(), getNativeObject(), e.getNativeObject()));
|
||||
|
@ -285,8 +285,7 @@ public class Optimize extends Z3Object {
|
|||
**/
|
||||
public String getReasonUnknown()
|
||||
{
|
||||
return Native.optimizeGetReasonUnknown(getContext().nCtx(),
|
||||
getNativeObject());
|
||||
return Native.optimizeGetReasonUnknown(getContext().nCtx(), getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -304,7 +303,7 @@ public class Optimize extends Z3Object {
|
|||
*/
|
||||
public void fromFile(String file)
|
||||
{
|
||||
Native.optimizeFromFile(getContext().nCtx(), getNativeObject(), file);
|
||||
Native.optimizeFromFile(getContext().nCtx(), getNativeObject(), file);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -312,7 +311,7 @@ public class Optimize extends Z3Object {
|
|||
*/
|
||||
public void fromString(String s)
|
||||
{
|
||||
Native.optimizeFromString(getContext().nCtx(), getNativeObject(), s);
|
||||
Native.optimizeFromString(getContext().nCtx(), getNativeObject(), s);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ public class ParamDescrs extends Z3Object {
|
|||
|
||||
public String getDocumentation(Symbol name)
|
||||
{
|
||||
return Native.paramDescrsGetDocumentation(getContext().nCtx(), getNativeObject(), name.getNativeObject());
|
||||
return Native.paramDescrsGetDocumentation(getContext().nCtx(), getNativeObject(), name.getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -302,7 +302,7 @@ public class Solver extends Z3Object {
|
|||
*/
|
||||
public Solver translate(Context ctx)
|
||||
{
|
||||
return new Solver(ctx, Native.solverTranslate(getContext().nCtx(), getNativeObject(), ctx.nCtx()));
|
||||
return new Solver(ctx, Native.solverTranslate(getContext().nCtx(), getNativeObject(), ctx.nCtx()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,12 +35,8 @@ public class Sort extends AST
|
|||
if (!(o instanceof Sort)) return false;
|
||||
Sort other = (Sort) o;
|
||||
|
||||
return (getContext().nCtx() == other.getContext().nCtx()) &&
|
||||
(Native.isEqSort(
|
||||
getContext().nCtx(),
|
||||
getNativeObject(),
|
||||
other.getNativeObject()
|
||||
));
|
||||
return (getContext().nCtx() == other.getContext().nCtx()) &&
|
||||
(Native.isEqSort(getContext().nCtx(), getNativeObject(), other.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,34 +25,34 @@ extern "C" {
|
|||
#include <z3native_stubs.h>
|
||||
|
||||
#define CAMLlocal6(X1,X2,X3,X4,X5,X6) \
|
||||
CAMLlocal5(X1,X2,X3,X4,X5); \
|
||||
CAMLlocal5(X1,X2,X3,X4,X5); \
|
||||
CAMLlocal1(X6)
|
||||
#define CAMLlocal7(X1,X2,X3,X4,X5,X6,X7) \
|
||||
CAMLlocal5(X1,X2,X3,X4,X5); \
|
||||
#define CAMLlocal7(X1,X2,X3,X4,X5,X6,X7) \
|
||||
CAMLlocal5(X1,X2,X3,X4,X5); \
|
||||
CAMLlocal2(X6,X7)
|
||||
#define CAMLlocal8(X1,X2,X3,X4,X5,X6,X7,X8) \
|
||||
CAMLlocal5(X1,X2,X3,X4,X5); \
|
||||
#define CAMLlocal8(X1,X2,X3,X4,X5,X6,X7,X8) \
|
||||
CAMLlocal5(X1,X2,X3,X4,X5); \
|
||||
CAMLlocal3(X6,X7,X8)
|
||||
|
||||
#define CAMLparam6(X1,X2,X3,X4,X5,X6) \
|
||||
CAMLparam5(X1,X2,X3,X4,X5); \
|
||||
#define CAMLparam6(X1,X2,X3,X4,X5,X6) \
|
||||
CAMLparam5(X1,X2,X3,X4,X5); \
|
||||
CAMLxparam1(X6)
|
||||
#define CAMLparam7(X1,X2,X3,X4,X5,X6,X7) \
|
||||
CAMLparam5(X1,X2,X3,X4,X5); \
|
||||
#define CAMLparam7(X1,X2,X3,X4,X5,X6,X7) \
|
||||
CAMLparam5(X1,X2,X3,X4,X5); \
|
||||
CAMLxparam2(X6,X7)
|
||||
#define CAMLparam8(X1,X2,X3,X4,X5,X6,X7,X8) \
|
||||
CAMLparam5(X1,X2,X3,X4,X5); \
|
||||
#define CAMLparam8(X1,X2,X3,X4,X5,X6,X7,X8) \
|
||||
CAMLparam5(X1,X2,X3,X4,X5); \
|
||||
CAMLxparam3(X6,X7,X8)
|
||||
#define CAMLparam9(X1,X2,X3,X4,X5,X6,X7,X8,X9) \
|
||||
CAMLparam5(X1,X2,X3,X4,X5); \
|
||||
#define CAMLparam9(X1,X2,X3,X4,X5,X6,X7,X8,X9) \
|
||||
CAMLparam5(X1,X2,X3,X4,X5); \
|
||||
CAMLxparam4(X6,X7,X8,X9)
|
||||
#define CAMLparam12(X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12) \
|
||||
CAMLparam5(X1,X2,X3,X4,X5); \
|
||||
CAMLxparam5(X6,X7,X8,X9,X10); \
|
||||
#define CAMLparam12(X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12) \
|
||||
CAMLparam5(X1,X2,X3,X4,X5); \
|
||||
CAMLxparam5(X6,X7,X8,X9,X10); \
|
||||
CAMLxparam2(X11,X12)
|
||||
#define CAMLparam13(X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12,X13) \
|
||||
CAMLparam5(X1,X2,X3,X4,X5); \
|
||||
CAMLxparam5(X6,X7,X8,X9,X10); \
|
||||
#define CAMLparam13(X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12,X13) \
|
||||
CAMLparam5(X1,X2,X3,X4,X5); \
|
||||
CAMLxparam5(X6,X7,X8,X9,X10); \
|
||||
CAMLxparam3(X11,X12,X13)
|
||||
|
||||
|
||||
|
|
|
@ -36,5 +36,5 @@ Notes:
|
|||
#define DLL_LOCAL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -397,23 +397,23 @@ typedef enum
|
|||
(xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3)
|
||||
|
||||
- Z3_OP_BSMUL_NO_OVFL: a predicate to check that bit-wise signed multiplication does not overflow.
|
||||
Signed multiplication overflows if the operands have the same sign and the result of multiplication
|
||||
Signed multiplication overflows if the operands have the same sign and the result of multiplication
|
||||
does not fit within the available bits. \sa Z3_mk_bvmul_no_overflow.
|
||||
|
||||
- Z3_OP_BUMUL_NO_OVFL: check that bit-wise unsigned multiplication does not overflow.
|
||||
Unsigned multiplication overflows if the result does not fit within the available bits.
|
||||
\sa Z3_mk_bvmul_no_overflow.
|
||||
|
||||
|
||||
- Z3_OP_BSMUL_NO_UDFL: check that bit-wise signed multiplication does not underflow.
|
||||
Signed multiplication underflows if the operands have opposite signs and the result of multiplication
|
||||
does not fit within the avaialble bits. Z3_mk_bvmul_no_underflow.
|
||||
|
||||
- Z3_OP_BSDIV_I: Binary signed division.
|
||||
|
||||
- Z3_OP_BSDIV_I: Binary signed division.
|
||||
It has the same semantics as Z3_OP_BSDIV, but created in a context where the second operand can be assumed to be non-zero.
|
||||
|
||||
- Z3_OP_BUDIV_I: Binary unsigned division.
|
||||
It has the same semantics as Z3_OP_BUDIV, but created in a context where the second operand can be assumed to be non-zero.
|
||||
|
||||
|
||||
- Z3_OP_BSREM_I: Binary signed remainder.
|
||||
It has the same semantics as Z3_OP_BSREM, but created in a context where the second operand can be assumed to be non-zero.
|
||||
|
||||
|
@ -979,7 +979,23 @@ typedef enum
|
|||
|
||||
- Z3_OP_FPA_TO_IEEE_BV: Floating-point conversion to IEEE-754 bit-vector
|
||||
|
||||
- Z3_OP_INTERNAL: internal (often interpreted) symbol, but no additional information is exposed. Tools may use the string representation of the function declaration to obtain more information.
|
||||
- Z3_OP_FPA_BVWRAP: (Implicitly) represents the internal bitvector-
|
||||
representation of a floating-point term (used for the lazy encoding
|
||||
of non-relevant terms in theory_fpa)
|
||||
|
||||
- Z3_OP_FPA_BV2RM: Conversion of a 3-bit bit-vector term to a
|
||||
floating-point rouding-mode term
|
||||
|
||||
The conversion uses the following values:
|
||||
0 = 000 = Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN,
|
||||
1 = 001 = Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY,
|
||||
2 = 010 = Z3_OP_FPA_RM_TOWARD_POSITIVE,
|
||||
3 = 011 = Z3_OP_FPA_RM_TOWARD_NEGATIVE,
|
||||
4 = 100 = Z3_OP_FPA_RM_TOWARD_ZERO.
|
||||
|
||||
- Z3_OP_INTERNAL: internal (often interpreted) symbol, but no additional
|
||||
information is exposed. Tools may use the string representation of the
|
||||
function declaration to obtain more information.
|
||||
|
||||
- Z3_OP_UNINTERPRETED: kind used for uninterpreted symbols.
|
||||
*/
|
||||
|
@ -1263,8 +1279,8 @@ typedef enum {
|
|||
|
||||
Z3_OP_FPA_TO_IEEE_BV,
|
||||
|
||||
Z3_OP_FPA_MIN_I,
|
||||
Z3_OP_FPA_MAX_I,
|
||||
Z3_OP_FPA_BVWRAP,
|
||||
Z3_OP_FPA_BV2RM,
|
||||
|
||||
Z3_OP_INTERNAL,
|
||||
|
||||
|
@ -3361,7 +3377,7 @@ extern "C" {
|
|||
\brief Convert string to integer.
|
||||
|
||||
def_API('Z3_mk_str_to_int' ,AST ,(_in(CONTEXT), _in(AST)))
|
||||
*/
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_str_to_int(Z3_context c, Z3_ast s);
|
||||
|
||||
|
||||
|
@ -3369,7 +3385,7 @@ extern "C" {
|
|||
\brief Integer to string conversion.
|
||||
|
||||
def_API('Z3_mk_int_to_str' ,AST ,(_in(CONTEXT), _in(AST)))
|
||||
*/
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_int_to_str(Z3_context c, Z3_ast s);
|
||||
|
||||
/**
|
||||
|
@ -4859,12 +4875,12 @@ extern "C" {
|
|||
Z3_func_decl Z3_API Z3_get_as_array_func_decl(Z3_context c, Z3_ast a);
|
||||
|
||||
/**
|
||||
\brief Create a fresh func_interp object, add it to a model for a specified function.
|
||||
It has reference count 0.
|
||||
\brief Create a fresh func_interp object, add it to a model for a specified function.
|
||||
It has reference count 0.
|
||||
|
||||
\param c context
|
||||
\param m model
|
||||
\param f function declaration
|
||||
\param f function declaration
|
||||
\param default_value default value for function interpretation
|
||||
|
||||
def_API('Z3_add_func_interp', FUNC_INTERP, (_in(CONTEXT), _in(MODEL), _in(FUNC_DECL), _in(AST)))
|
||||
|
@ -4950,7 +4966,7 @@ extern "C" {
|
|||
\param args list of arguments. They should be constant values (such as integers) and be of the same types as the domain of the function.
|
||||
\param value value of the function when the parameters match args.
|
||||
|
||||
It is assumed that entries added to a function cover disjoint arguments.
|
||||
It is assumed that entries added to a function cover disjoint arguments.
|
||||
If an two entries are added with the same arguments, only the second insertion survives and the
|
||||
first inserted entry is removed.
|
||||
|
||||
|
|
|
@ -197,4 +197,4 @@ extern "C" {
|
|||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1714,8 +1714,15 @@ ast * ast_manager::register_node_core(ast * n) {
|
|||
SASSERT(m_ast_table.contains(n));
|
||||
}
|
||||
|
||||
|
||||
n->m_id = is_decl(n) ? m_decl_id_gen.mk() : m_expr_id_gen.mk();
|
||||
|
||||
static unsigned count = 0;
|
||||
if (n->m_id == 404) {
|
||||
++count;
|
||||
//if (count == 2) SASSERT(false);
|
||||
}
|
||||
|
||||
TRACE("ast", tout << "Object " << n->m_id << " was created.\n";);
|
||||
TRACE("mk_var_bug", tout << "mk_ast: " << n->m_id << "\n";);
|
||||
// increment reference counters
|
||||
|
|
|
@ -584,6 +584,8 @@ class smt2_printer {
|
|||
string_buffer<> buf;
|
||||
buf.append("(:var ");
|
||||
buf.append(v->get_idx());
|
||||
//buf.append(" ");
|
||||
//buf.append(v->get_sort()->get_name().str().c_str());
|
||||
buf.append(")");
|
||||
f = mk_string(m(), buf.c_str());
|
||||
}
|
||||
|
|
|
@ -738,6 +738,7 @@ void bv_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const
|
|||
op_names.push_back(builtin_name("ext_rotate_right",OP_EXT_ROTATE_RIGHT));
|
||||
op_names.push_back(builtin_name("int2bv",OP_INT2BV));
|
||||
op_names.push_back(builtin_name("bv2int",OP_BV2INT));
|
||||
op_names.push_back(builtin_name("bv2nat",OP_BV2INT));
|
||||
op_names.push_back(builtin_name("mkbv",OP_MKBV));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,8 +62,8 @@ bv2fpa_converter::bv2fpa_converter(ast_manager & m, fpa2bv_converter & conv) :
|
|||
m.inc_ref(it->m_key);
|
||||
m.inc_ref(it->m_value);
|
||||
}
|
||||
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = conv.m_min_max_specials.begin();
|
||||
it != conv.m_min_max_specials.end();
|
||||
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = conv.m_min_max_ufs.begin();
|
||||
it != conv.m_min_max_ufs.end();
|
||||
it++) {
|
||||
m_specials.insert(it->m_key, it->m_value);
|
||||
m.inc_ref(it->m_key);
|
||||
|
@ -120,9 +120,9 @@ expr_ref bv2fpa_converter::convert_bv2fp(sort * s, expr * sgn, expr * exp, expr
|
|||
res = m_fpa_util.mk_value(fp_val);
|
||||
|
||||
TRACE("bv2fpa", tout << "[" << mk_ismt2_pp(sgn, m) <<
|
||||
" " << mk_ismt2_pp(exp, m) <<
|
||||
" " << mk_ismt2_pp(sig, m) << "] == " <<
|
||||
mk_ismt2_pp(res, m) << std::endl;);
|
||||
" " << mk_ismt2_pp(exp, m) <<
|
||||
" " << mk_ismt2_pp(sig, m) << "] == " <<
|
||||
mk_ismt2_pp(res, m) << std::endl;);
|
||||
m_fpa_util.fm().del(fp_val);
|
||||
|
||||
return res;
|
||||
|
@ -263,7 +263,7 @@ func_interp * bv2fpa_converter::convert_func_interp(model_core * mc, func_decl *
|
|||
unsigned arity = bv_f->get_arity();
|
||||
func_interp * bv_fi = mc->get_func_interp(bv_f);
|
||||
|
||||
if (bv_fi != 0) {
|
||||
if (bv_fi) {
|
||||
fpa_rewriter rw(m);
|
||||
expr_ref ai(m);
|
||||
result = alloc(func_interp, m, arity);
|
||||
|
@ -285,15 +285,31 @@ func_interp * bv2fpa_converter::convert_func_interp(model_core * mc, func_decl *
|
|||
bv_fres = bv_fe->get_result();
|
||||
ft_fres = rebuild_floats(mc, rng, to_app(bv_fres));
|
||||
m_th_rw(ft_fres);
|
||||
result->insert_new_entry(new_args.c_ptr(), ft_fres);
|
||||
TRACE("bv2fpa",
|
||||
for (unsigned i = 0; i < new_args.size(); i++)
|
||||
tout << mk_ismt2_pp(bv_args[i], m) << " == " <<
|
||||
mk_ismt2_pp(new_args[i], m) << std::endl;
|
||||
tout << mk_ismt2_pp(bv_fres, m) << " == " << mk_ismt2_pp(ft_fres, m) << std::endl;);
|
||||
func_entry * fe = result->get_entry(new_args.c_ptr());
|
||||
if (fe == 0)
|
||||
result->insert_new_entry(new_args.c_ptr(), ft_fres);
|
||||
else {
|
||||
// The BV model may have multiple equivalent entries using different
|
||||
// representations of NaN. We can only keep one and we check that
|
||||
// the results for all those entries are the same.
|
||||
if (ft_fres != fe->get_result())
|
||||
throw default_exception("BUG: UF function entries disagree with each other");
|
||||
}
|
||||
}
|
||||
|
||||
app_ref bv_els(m);
|
||||
expr_ref ft_els(m);
|
||||
bv_els = (app*)bv_fi->get_else();
|
||||
ft_els = rebuild_floats(mc, rng, bv_els);
|
||||
m_th_rw(ft_els);
|
||||
result->set_else(ft_els);
|
||||
if (bv_els != 0) {
|
||||
ft_els = rebuild_floats(mc, rng, bv_els);
|
||||
m_th_rw(ft_els);
|
||||
result->set_else(ft_els);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -382,7 +398,7 @@ void bv2fpa_converter::convert_rm_consts(model_core * mc, model_core * target_mo
|
|||
expr * bvval = to_app(val)->get_arg(0);
|
||||
expr_ref fv(m);
|
||||
fv = convert_bv2rm(mc, to_app(bvval));
|
||||
TRACE("bv2fpa", tout << var->get_name() << " == " << mk_ismt2_pp(fv, m) << ")" << std::endl;);
|
||||
TRACE("bv2fpa", tout << var->get_name() << " == " << mk_ismt2_pp(fv, m) << std::endl;);
|
||||
target_model->register_decl(var, fv);
|
||||
seen.insert(to_app(bvval)->get_decl());
|
||||
}
|
||||
|
@ -447,14 +463,34 @@ void bv2fpa_converter::convert_uf2bvuf(model_core * mc, model_core * target_mode
|
|||
}
|
||||
}
|
||||
else {
|
||||
func_interp * fmv = convert_func_interp(mc, f, it->m_value);
|
||||
if (fmv) target_model->register_decl(f, fmv);
|
||||
if (it->get_key().get_family_id() == m_fpa_util.get_fid()) {
|
||||
// it->m_value contains the model for the unspecified cases of it->m_key.
|
||||
|
||||
func_interp * fmv = convert_func_interp(mc, f, it->m_value);
|
||||
if (fmv) {
|
||||
#if 0
|
||||
// Upon request, add this 'recursive' definition?
|
||||
unsigned n = fmv->get_arity();
|
||||
expr_ref_vector args(m);
|
||||
for (unsigned i = 0; i < n; i++)
|
||||
args.push_back(m.mk_var(i, f->get_domain()[i]));
|
||||
fmv->set_else(m.mk_app(it->m_key, n, args.c_ptr()));
|
||||
#else
|
||||
|
||||
fmv->set_else(0);
|
||||
#endif
|
||||
target_model->register_decl(f, fmv);
|
||||
}
|
||||
}
|
||||
else {
|
||||
func_interp * fmv = convert_func_interp(mc, f, it->m_value);
|
||||
if (fmv) target_model->register_decl(f, fmv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bv2fpa_converter::display(std::ostream & out) {
|
||||
out << "(fpa2bv-model-converter";
|
||||
for (obj_map<func_decl, expr*>::iterator it = m_const2bv.begin();
|
||||
it != m_const2bv.end();
|
||||
it++) {
|
||||
|
@ -488,7 +524,6 @@ void bv2fpa_converter::display(std::ostream & out) {
|
|||
out << mk_ismt2_pp(it->m_value.first, m, indent) << "; " <<
|
||||
mk_ismt2_pp(it->m_value.second, m, indent) << ")";
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
|
||||
bv2fpa_converter * bv2fpa_converter::translate(ast_translation & translator) {
|
||||
|
@ -536,23 +571,3 @@ bv2fpa_converter * bv2fpa_converter::translate(ast_translation & translator) {
|
|||
return res;
|
||||
}
|
||||
|
||||
void bv2fpa_converter::convert(model_core * mc, model_core * float_mdl) {
|
||||
TRACE("bv2fpa", tout << "BV Model: " << std::endl;
|
||||
for (unsigned i = 0; i < mc->get_num_constants(); i++)
|
||||
tout << mc->get_constant(i)->get_name() << " --> " <<
|
||||
mk_ismt2_pp(mc->get_const_interp(mc->get_constant(i)), m) << std::endl;
|
||||
for (unsigned i = 0; i < mc->get_num_functions(); i++) {
|
||||
func_decl * f = mc->get_function(i);
|
||||
tout << f->get_name() << "(...) := " << std::endl;
|
||||
func_interp * fi = mc->get_func_interp(f);
|
||||
for (unsigned j = 0; j < fi->num_entries(); j++) {
|
||||
func_entry const * fe = fi->get_entry(j);
|
||||
for (unsigned k = 0; k < f->get_arity(); k++) {
|
||||
tout << mk_ismt2_pp(fe->get_arg(k), m) << " ";
|
||||
}
|
||||
tout << "--> " << mk_ismt2_pp(fe->get_result(), m) << std::endl;
|
||||
}
|
||||
tout << "else " << mk_ismt2_pp(fi->get_else(), m) << std::endl;
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ public:
|
|||
expr_ref convert_bv2rm(expr * eval_v);
|
||||
expr_ref convert_bv2rm(model_core * mc, app * val);
|
||||
|
||||
void convert(model_core * mc, model_core * float_mdl);
|
||||
void convert_consts(model_core * mc, model_core * target_model, obj_hashtable<func_decl> & seen);
|
||||
void convert_rm_consts(model_core * mc, model_core * target_model, obj_hashtable<func_decl> & seen);
|
||||
void convert_min_max_specials(model_core * mc, model_core * target_model, obj_hashtable<func_decl> & seen);
|
||||
|
|
|
@ -230,39 +230,7 @@ void fpa2bv_converter::mk_var(unsigned base_inx, sort * srt, expr_ref & result)
|
|||
result = m_util.mk_fp(sgn, e, s);
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_function_output(sort * rng, func_decl * fbv, expr * const * new_args, expr_ref & result) {
|
||||
if (m_util.is_float(rng)) {
|
||||
unsigned ebits = m_util.get_ebits(rng);
|
||||
unsigned sbits = m_util.get_sbits(rng);
|
||||
unsigned bv_sz = ebits + sbits;
|
||||
|
||||
app_ref na(m);
|
||||
na = m.mk_app(fbv, fbv->get_arity(), new_args);
|
||||
result = m_util.mk_fp(m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, na),
|
||||
m_bv_util.mk_extract(bv_sz - 2, sbits - 1, na),
|
||||
m_bv_util.mk_extract(sbits - 2, 0, na));
|
||||
}
|
||||
else if (m_util.is_rm(rng)) {
|
||||
app_ref na(m);
|
||||
na = m.mk_app(fbv, fbv->get_arity(), new_args);
|
||||
result = m_util.mk_bv2rm(na);
|
||||
}
|
||||
else
|
||||
result = m.mk_app(fbv, fbv->get_arity(), new_args);
|
||||
}
|
||||
|
||||
func_decl * fpa2bv_converter::get_bv_uf(func_decl * f, sort * bv_rng, unsigned arity) {
|
||||
func_decl * res;
|
||||
if (!m_uf2bvuf.find(f, res)) {
|
||||
res = m.mk_fresh_func_decl(f->get_name(), symbol("bv"), arity, f->get_domain(), bv_rng);
|
||||
m_uf2bvuf.insert(f, res);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(res);
|
||||
TRACE("fpa2bv", tout << "New UF func_decl: " << std::endl << mk_ismt2_pp(res, m) << std::endl;);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
void fpa2bv_converter::mk_function(func_decl * f, unsigned num, expr * const * args, expr_ref & result)
|
||||
void fpa2bv_converter::mk_uf(func_decl * f, unsigned num, expr * const * args, expr_ref & result)
|
||||
{
|
||||
TRACE("fpa2bv", tout << "UF: " << mk_ismt2_pp(f, m) << std::endl; );
|
||||
|
||||
|
@ -278,7 +246,7 @@ void fpa2bv_converter::mk_function(func_decl * f, unsigned num, expr * const * a
|
|||
unsigned sbits = m_util.get_sbits(rng);
|
||||
unsigned bv_sz = ebits+sbits;
|
||||
bv_rng = m_bv_util.mk_sort(bv_sz);
|
||||
func_decl * bv_f = get_bv_uf(f, bv_rng, num);
|
||||
func_decl * bv_f = mk_bv_uf(f, f->get_domain(), bv_rng);
|
||||
bv_app = m.mk_app(bv_f, num, args);
|
||||
flt_app = m_util.mk_fp(m_bv_util.mk_extract(bv_sz-1, bv_sz-1, bv_app),
|
||||
m_bv_util.mk_extract(sbits+ebits-2, sbits-1, bv_app),
|
||||
|
@ -291,7 +259,7 @@ void fpa2bv_converter::mk_function(func_decl * f, unsigned num, expr * const * a
|
|||
sort_ref bv_rng(m);
|
||||
expr_ref new_eq(m);
|
||||
bv_rng = m_bv_util.mk_sort(3);
|
||||
func_decl * bv_f = get_bv_uf(f, bv_rng, num);
|
||||
func_decl * bv_f = mk_bv_uf(f, f->get_domain(), bv_rng);
|
||||
bv_app = m.mk_app(bv_f, num, args);
|
||||
flt_app = m_util.mk_bv2rm(bv_app);
|
||||
new_eq = m.mk_eq(fapp, flt_app);
|
||||
|
@ -1211,61 +1179,89 @@ void fpa2bv_converter::mk_abs(sort * s, expr_ref & x, expr_ref & result) {
|
|||
}
|
||||
|
||||
void fpa2bv_converter::mk_min(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
expr_ref x(m), y(m);
|
||||
x = args[0];
|
||||
y = args[1];
|
||||
|
||||
expr_ref x_is_zero(m), y_is_zero(m), both_are_zero(m);
|
||||
x_is_zero = m_util.mk_is_zero(x);
|
||||
y_is_zero = m_util.mk_is_zero(y);
|
||||
both_are_zero = m.mk_and(x_is_zero, y_is_zero);
|
||||
|
||||
expr_ref x_is_positive(m), x_is_negative(m), y_is_positive(m), y_is_negative(m), pn(m), np(m), pn_or_np(m);
|
||||
x_is_positive = m_util.mk_is_positive(x);
|
||||
x_is_negative = m_util.mk_is_negative(x);
|
||||
y_is_positive = m_util.mk_is_positive(y);
|
||||
y_is_negative = m_util.mk_is_negative(y);
|
||||
pn = m.mk_and(x_is_positive, y_is_negative);
|
||||
np = m.mk_and(x_is_negative, y_is_positive);
|
||||
pn_or_np = m.mk_or(pn, np);
|
||||
|
||||
expr_ref c(m), v(m);
|
||||
c = m.mk_and(both_are_zero, pn_or_np);
|
||||
v = m.mk_app(m_util.get_family_id(), OP_FPA_INTERNAL_MIN_UNSPECIFIED, x, y);
|
||||
|
||||
// Note: This requires BR_REWRITE_FULL afterwards.
|
||||
expr_ref min_i(m);
|
||||
min_i = m.mk_app(m_util.get_family_id(), OP_FPA_INTERNAL_MIN_I, x, y);
|
||||
m_simp.mk_ite(c, v, min_i, result);
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_min_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 2);
|
||||
unsigned ebits = m_util.get_ebits(f->get_range());
|
||||
unsigned sbits = m_util.get_sbits(f->get_range());
|
||||
|
||||
expr * x = args[0], * y = args[1];
|
||||
|
||||
expr * x_sgn, * x_sig, * x_exp;
|
||||
expr * y_sgn, * y_sig, * y_exp;
|
||||
expr * x_sgn, *x_sig, *x_exp;
|
||||
expr * y_sgn, *y_sig, *y_exp;
|
||||
split_fp(x, x_sgn, x_exp, x_sig);
|
||||
split_fp(y, y_sgn, y_exp, y_sig);
|
||||
|
||||
expr_ref x_is_nan(m), y_is_nan(m), x_is_zero(m), y_is_zero(m), both_zero(m), pzero(m);
|
||||
mk_is_zero(x, x_is_zero);
|
||||
mk_is_zero(y, y_is_zero);
|
||||
m_simp.mk_and(x_is_zero, y_is_zero, both_zero);
|
||||
expr_ref bv0(m), bv1(m);
|
||||
bv0 = m_bv_util.mk_numeral(0, 1);
|
||||
bv1 = m_bv_util.mk_numeral(1, 1);
|
||||
|
||||
expr_ref x_is_nan(m), y_is_nan(m), x_is_zero(m), y_is_zero(m), xy_are_zero(m);
|
||||
mk_is_nan(x, x_is_nan);
|
||||
mk_is_nan(y, y_is_nan);
|
||||
mk_pzero(f, pzero);
|
||||
mk_is_zero(x, x_is_zero);
|
||||
mk_is_zero(y, y_is_zero);
|
||||
xy_are_zero = m.mk_and(x_is_zero, y_is_zero);
|
||||
|
||||
expr_ref sgn_eq(m), sgn_diff(m);
|
||||
sgn_eq = m.mk_eq(x_sgn, y_sgn);
|
||||
sgn_diff = m.mk_not(sgn_eq);
|
||||
expr_ref x_is_pos(m), x_is_neg(m);
|
||||
expr_ref y_is_pos(m), y_is_neg(m);
|
||||
expr_ref pn(m), np(m), pn_or_np_zeros(m);
|
||||
mk_is_pos(x, x_is_pos);
|
||||
mk_is_pos(y, y_is_pos);
|
||||
mk_is_neg(x, x_is_neg);
|
||||
mk_is_neg(y, y_is_neg);
|
||||
pn_or_np_zeros = m.mk_and(xy_are_zero, m.mk_not(m.mk_eq(x_sgn, y_sgn)));
|
||||
|
||||
expr_ref lt(m);
|
||||
mk_float_lt(f, num, args, lt);
|
||||
expr_ref unspec(m);
|
||||
unspec = mk_min_max_unspecified(f, x, y);
|
||||
|
||||
mk_ite(lt, x, y, result);
|
||||
mk_ite(both_zero, y, result, result);
|
||||
expr_ref x_lt_y(m);
|
||||
mk_float_lt(f, num, args, x_lt_y);
|
||||
|
||||
mk_ite(x_lt_y, x, y, result);
|
||||
mk_ite(xy_are_zero, y, result, result);
|
||||
mk_ite(pn_or_np_zeros, unspec, result, result);
|
||||
mk_ite(y_is_nan, x, result, result);
|
||||
mk_ite(x_is_nan, y, result, result);
|
||||
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 2);
|
||||
unsigned ebits = m_util.get_ebits(f->get_range());
|
||||
unsigned sbits = m_util.get_sbits(f->get_range());
|
||||
|
||||
expr * x = args[0], *y = args[1];
|
||||
|
||||
expr * x_sgn, *x_sig, *x_exp;
|
||||
expr * y_sgn, *y_sig, *y_exp;
|
||||
split_fp(x, x_sgn, x_exp, x_sig);
|
||||
split_fp(y, y_sgn, y_exp, y_sig);
|
||||
|
||||
expr_ref x_is_nan(m), y_is_nan(m), x_is_zero(m), y_is_zero(m), xy_are_zero(m);
|
||||
mk_is_nan(x, x_is_nan);
|
||||
mk_is_nan(y, y_is_nan);
|
||||
mk_is_zero(x, x_is_zero);
|
||||
mk_is_zero(y, y_is_zero);
|
||||
xy_are_zero = m.mk_and(x_is_zero, y_is_zero);
|
||||
|
||||
expr_ref x_is_pos(m), x_is_neg(m);
|
||||
expr_ref y_is_pos(m), y_is_neg(m);
|
||||
expr_ref pn(m), np(m), pn_or_np_zeros(m);
|
||||
mk_is_pos(x, x_is_pos);
|
||||
mk_is_pos(y, y_is_pos);
|
||||
mk_is_neg(x, x_is_neg);
|
||||
mk_is_neg(y, y_is_neg);
|
||||
pn_or_np_zeros = m.mk_and(xy_are_zero, m.mk_not(m.mk_eq(x_sgn, y_sgn)));
|
||||
|
||||
expr_ref unspec(m);
|
||||
unspec = mk_min_max_unspecified(f, x, y);
|
||||
|
||||
expr_ref x_gt_y(m);
|
||||
mk_float_gt(f, num, args, x_gt_y);
|
||||
|
||||
mk_ite(x_gt_y, x, y, result);
|
||||
mk_ite(xy_are_zero, y, result, result);
|
||||
mk_ite(pn_or_np_zeros, unspec, result, result);
|
||||
mk_ite(y_is_nan, x, result, result);
|
||||
mk_ite(x_is_nan, y, result, result);
|
||||
|
||||
|
@ -1281,10 +1277,10 @@ expr_ref fpa2bv_converter::mk_min_max_unspecified(func_decl * f, expr * x, expr
|
|||
// There is no "hardware interpretation" for fp.min/fp.max.
|
||||
|
||||
std::pair<app*, app*> decls(0, 0);
|
||||
if (!m_min_max_specials.find(f, decls)) {
|
||||
if (!m_min_max_ufs.find(f, decls)) {
|
||||
decls.first = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
decls.second = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
m_min_max_specials.insert(f, decls);
|
||||
m_min_max_ufs.insert(f, decls);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(decls.first);
|
||||
m.inc_ref(decls.second);
|
||||
|
@ -1303,68 +1299,6 @@ expr_ref fpa2bv_converter::mk_min_max_unspecified(func_decl * f, expr * x, expr
|
|||
return res;
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
expr_ref x(m), y(m);
|
||||
x = args[0];
|
||||
y = args[1];
|
||||
|
||||
expr_ref x_is_zero(m), y_is_zero(m), both_are_zero(m);
|
||||
x_is_zero = m_util.mk_is_zero(x);
|
||||
y_is_zero = m_util.mk_is_zero(y);
|
||||
both_are_zero = m.mk_and(x_is_zero, y_is_zero);
|
||||
|
||||
expr_ref x_is_positive(m), x_is_negative(m), y_is_positive(m), y_is_negative(m), pn(m), np(m), pn_or_np(m);
|
||||
x_is_positive = m_util.mk_is_positive(x);
|
||||
x_is_negative = m_util.mk_is_negative(x);
|
||||
y_is_positive = m_util.mk_is_positive(y);
|
||||
y_is_negative = m_util.mk_is_negative(y);
|
||||
pn = m.mk_and(x_is_positive, y_is_negative);
|
||||
np = m.mk_and(x_is_negative, y_is_positive);
|
||||
pn_or_np = m.mk_or(pn, np);
|
||||
|
||||
expr_ref c(m), v(m);
|
||||
c = m.mk_and(both_are_zero, pn_or_np);
|
||||
v = m.mk_app(m_util.get_family_id(), OP_FPA_INTERNAL_MAX_UNSPECIFIED, x, y);
|
||||
|
||||
// Note: This requires BR_REWRITE_FULL afterwards.
|
||||
expr_ref max_i(m);
|
||||
max_i = m.mk_app(m_util.get_family_id(), OP_FPA_INTERNAL_MAX_I, x, y);
|
||||
m_simp.mk_ite(c, v, max_i, result);
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_max_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 2);
|
||||
|
||||
expr * x = args[0], *y = args[1];
|
||||
|
||||
expr * x_sgn, *x_sig, *x_exp;
|
||||
expr * y_sgn, *y_sig, *y_exp;
|
||||
split_fp(x, x_sgn, x_exp, x_sig);
|
||||
split_fp(y, y_sgn, y_exp, y_sig);
|
||||
|
||||
expr_ref x_is_nan(m), y_is_nan(m), x_is_zero(m), y_is_zero(m), both_zero(m), pzero(m);
|
||||
mk_is_zero(x, x_is_zero);
|
||||
mk_is_zero(y, y_is_zero);
|
||||
m_simp.mk_and(x_is_zero, y_is_zero, both_zero);
|
||||
mk_is_nan(x, x_is_nan);
|
||||
mk_is_nan(y, y_is_nan);
|
||||
mk_pzero(f, pzero);
|
||||
|
||||
expr_ref sgn_diff(m), sgn_eq(m);
|
||||
sgn_eq = m.mk_eq(x_sgn, y_sgn);
|
||||
sgn_diff = m.mk_not(sgn_eq);
|
||||
|
||||
expr_ref gt(m);
|
||||
mk_float_gt(f, num, args, gt);
|
||||
|
||||
mk_ite(gt, x, y, result);
|
||||
mk_ite(both_zero, y, result, result);
|
||||
mk_ite(y_is_nan, x, result, result);
|
||||
mk_ite(x_is_nan, y, result, result);
|
||||
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 4);
|
||||
SASSERT(m_util.is_bv2rm(args[0]));
|
||||
|
@ -2855,8 +2789,7 @@ void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * ar
|
|||
tout << "exp2 = " << mk_ismt2_pp(exp2, m) << std::endl;);
|
||||
|
||||
expr_ref unspec(m);
|
||||
unspec = mk_to_real_unspecified(ebits, sbits);
|
||||
|
||||
mk_to_real_unspecified(f, num, args, unspec);
|
||||
result = m.mk_ite(x_is_zero, zero, res);
|
||||
result = m.mk_ite(x_is_inf, unspec, result);
|
||||
result = m.mk_ite(x_is_nan, unspec, result);
|
||||
|
@ -3151,59 +3084,43 @@ void fpa2bv_converter::mk_to_ieee_bv(func_decl * f, unsigned num, expr * const *
|
|||
unsigned ebits = m_util.get_ebits(fp_srt);
|
||||
unsigned sbits = m_util.get_sbits(fp_srt);
|
||||
|
||||
expr_ref nanv(m);
|
||||
if (m_hi_fp_unspecified)
|
||||
// The "hardware interpretation" is 01...10...01.
|
||||
nanv = m_bv_util.mk_concat(m_bv_util.mk_numeral(0, 1),
|
||||
m_bv_util.mk_concat(m_bv_util.mk_numeral(-1, ebits),
|
||||
m_bv_util.mk_concat(m_bv_util.mk_numeral(0, sbits - 2),
|
||||
m_bv_util.mk_numeral(1, 1))));
|
||||
else {
|
||||
app_ref unspec(m);
|
||||
unspec = m_util.mk_internal_to_ieee_bv_unspecified(ebits, sbits);
|
||||
mk_to_ieee_bv_unspecified(unspec->get_decl(), 0, 0, nanv);
|
||||
}
|
||||
expr_ref unspec(m);
|
||||
mk_to_ieee_bv_unspecified(f, num, args, unspec);
|
||||
|
||||
expr_ref sgn_e_s(m);
|
||||
sgn_e_s = m_bv_util.mk_concat(m_bv_util.mk_concat(sgn, e), s);
|
||||
m_simp.mk_ite(x_is_nan, nanv, sgn_e_s, result);
|
||||
join_fp(x, sgn_e_s);
|
||||
m_simp.mk_ite(x_is_nan, unspec, sgn_e_s, result);
|
||||
|
||||
TRACE("fpa2bv_to_ieee_bv", tout << "result=" << mk_ismt2_pp(result, m) << std::endl;);
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_to_ieee_bv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 0);
|
||||
unsigned ebits = f->get_parameter(0).get_int();
|
||||
unsigned sbits = f->get_parameter(1).get_int();
|
||||
SASSERT(num == 1);
|
||||
SASSERT(m_util.is_float(args[0]));
|
||||
unsigned ebits = f->get_domain()[0]->get_parameter(0).get_int();
|
||||
unsigned sbits = f->get_domain()[0]->get_parameter(1).get_int();
|
||||
|
||||
if (m_hi_fp_unspecified) {
|
||||
result = m_bv_util.mk_concat(m_bv_util.mk_concat(
|
||||
m_bv_util.mk_numeral(0, 1),
|
||||
m_bv_util.mk_numeral(-1, ebits)),
|
||||
m_bv_util.mk_numeral(1, sbits-1));
|
||||
}
|
||||
if (m_hi_fp_unspecified)
|
||||
mk_nan(f->get_range(), result);
|
||||
else {
|
||||
func_decl * fd;
|
||||
if (m_uf2bvuf.find(f, fd))
|
||||
result = m.mk_const(fd);
|
||||
else {
|
||||
fd = m.mk_fresh_func_decl(0, 0, 0, f->get_range());
|
||||
m_uf2bvuf.insert(f, fd);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(fd);
|
||||
result = m.mk_const(fd);
|
||||
expr * n = args[0];
|
||||
expr_ref n_bv(m);
|
||||
join_fp(n, n_bv);
|
||||
|
||||
expr_ref exp_bv(m), exp_all_ones(m);
|
||||
exp_bv = m_bv_util.mk_extract(ebits+sbits-2, sbits-1, result);
|
||||
exp_all_ones = m.mk_eq(exp_bv, m_bv_util.mk_numeral(-1, ebits));
|
||||
m_extra_assertions.push_back(exp_all_ones);
|
||||
sort * domain[1] = { m.get_sort(n_bv) };
|
||||
func_decl * f_bv = mk_bv_uf(f, domain, f->get_range());
|
||||
result = m.mk_app(f_bv, n_bv);
|
||||
|
||||
expr_ref sig_bv(m), sig_is_non_zero(m);
|
||||
sig_bv = m_bv_util.mk_extract(sbits-2, 0, result);
|
||||
sig_is_non_zero = m.mk_not(m.mk_eq(sig_bv, m_bv_util.mk_numeral(0, sbits-1)));
|
||||
m_extra_assertions.push_back(sig_is_non_zero);
|
||||
}
|
||||
expr_ref exp_bv(m), exp_all_ones(m);
|
||||
exp_bv = m_bv_util.mk_extract(ebits+sbits-2, sbits-1, result);
|
||||
exp_all_ones = m.mk_eq(exp_bv, m_bv_util.mk_numeral(-1, ebits));
|
||||
m_extra_assertions.push_back(exp_all_ones);
|
||||
|
||||
expr_ref sig_bv(m), sig_is_non_zero(m);
|
||||
sig_bv = m_bv_util.mk_extract(sbits-2, 0, result);
|
||||
sig_is_non_zero = m.mk_not(m.mk_eq(sig_bv, m_bv_util.mk_numeral(0, sbits-1)));
|
||||
m_extra_assertions.push_back(sig_is_non_zero);
|
||||
}
|
||||
|
||||
TRACE("fpa2bv_to_ieee_bv_unspecified", tout << "result=" << mk_ismt2_pp(result, m) << std::endl;);
|
||||
|
@ -3238,18 +3155,13 @@ void fpa2bv_converter::mk_to_bv(func_decl * f, unsigned num, expr * const * args
|
|||
mk_is_nzero(x, x_is_nzero);
|
||||
|
||||
// NaN, Inf, or negative (except -0) -> unspecified
|
||||
expr_ref c1(m), v1(m);
|
||||
if (!is_signed) {
|
||||
c1 = m.mk_or(x_is_nan, x_is_inf, m.mk_and(x_is_neg, m.mk_not(x_is_nzero)));
|
||||
v1 = mk_to_ubv_unspecified(ebits, sbits, bv_sz);
|
||||
}
|
||||
else {
|
||||
c1 = m.mk_or(x_is_nan, x_is_inf);
|
||||
v1 = mk_to_sbv_unspecified(ebits, sbits, bv_sz);
|
||||
}
|
||||
expr_ref c1(m), v1(m), unspec_v(m);
|
||||
c1 = m.mk_or(x_is_nan, x_is_inf);
|
||||
mk_to_bv_unspecified(f, num, args, unspec_v);
|
||||
v1 = unspec_v;
|
||||
dbg_decouple("fpa2bv_to_bv_c1", c1);
|
||||
|
||||
// +-Zero -> 0
|
||||
// +-0 -> 0
|
||||
expr_ref c2(m), v2(m);
|
||||
c2 = x_is_zero;
|
||||
v2 = m_bv_util.mk_numeral(rational(0), bv_srt);
|
||||
|
@ -3270,60 +3182,57 @@ void fpa2bv_converter::mk_to_bv(func_decl * f, unsigned num, expr * const * args
|
|||
SASSERT(m_bv_util.get_bv_size(exp) == ebits);
|
||||
SASSERT(m_bv_util.get_bv_size(lz) == ebits);
|
||||
|
||||
unsigned sig_sz = m_bv_util.get_bv_size(sig);
|
||||
SASSERT(sig_sz == sbits);
|
||||
unsigned sig_sz = sbits;
|
||||
if (sig_sz < (bv_sz + 3))
|
||||
sig = m_bv_util.mk_concat(sig, m_bv_util.mk_numeral(0, bv_sz - sig_sz + 3));
|
||||
sig = m_bv_util.mk_concat(sig, m_bv_util.mk_numeral(0, bv_sz-sig_sz+3));
|
||||
sig_sz = m_bv_util.get_bv_size(sig);
|
||||
SASSERT(sig_sz >= (bv_sz + 3));
|
||||
|
||||
expr_ref exp_m_lz(m), e_m_lz_m_bv_sz(m), shift(m), bv0_e2(m), shift_abs(m), shift_le_0(m);
|
||||
exp_m_lz = m_bv_util.mk_bv_sub(m_bv_util.mk_sign_extend(2, exp),
|
||||
m_bv_util.mk_zero_extend(2, lz));
|
||||
e_m_lz_m_bv_sz = m_bv_util.mk_bv_sub(exp_m_lz,
|
||||
m_bv_util.mk_numeral(bv_sz - 1, ebits + 2));
|
||||
shift = m_bv_util.mk_bv_neg(e_m_lz_m_bv_sz);
|
||||
bv0_e2 = m_bv_util.mk_numeral(0, ebits + 2);
|
||||
shift_le_0 = m_bv_util.mk_sle(shift, bv0_e2);
|
||||
shift_abs = m.mk_ite(shift_le_0, e_m_lz_m_bv_sz, shift);
|
||||
SASSERT(m_bv_util.get_bv_size(shift) == ebits + 2);
|
||||
SASSERT(m_bv_util.get_bv_size(shift_abs) == ebits + 2);
|
||||
dbg_decouple("fpa2bv_to_bv_shift", shift);
|
||||
dbg_decouple("fpa2bv_to_bv_shift_abs", shift_abs);
|
||||
|
||||
// x is of the form +- [1].[sig][r][g][s] ... and at least bv_sz + 3 long
|
||||
// [1][ ... sig ... ][r][g][ ... s ...]
|
||||
// [ ... ubv ... ][r][g][ ... s ... ]
|
||||
|
||||
shift_abs = m_bv_util.mk_zero_extend(sig_sz - ebits - 2, shift_abs);
|
||||
SASSERT(m_bv_util.get_bv_size(shift_abs) == sig_sz);
|
||||
expr_ref exp_m_lz(m), e_m_lz_m_bv_sz(m), shift(m), is_neg_shift(m), big_sig(m);
|
||||
exp_m_lz = m_bv_util.mk_bv_sub(m_bv_util.mk_sign_extend(2, exp),
|
||||
m_bv_util.mk_zero_extend(2, lz));
|
||||
|
||||
expr_ref c_in_limits(m);
|
||||
if (!is_signed)
|
||||
c_in_limits = m_bv_util.mk_sle(bv0_e2, shift);
|
||||
else {
|
||||
expr_ref one_sle_shift(m), one_eq_shift(m), p2(m), sig_is_p2(m), shift1_and_sig_p2(m);
|
||||
one_sle_shift = m_bv_util.mk_sle(m_bv_util.mk_numeral(1, ebits + 2), shift);
|
||||
one_eq_shift = m.mk_eq(m_bv_util.mk_numeral(0, ebits + 2), shift);
|
||||
p2 = m_bv_util.mk_concat(bv1, m_bv_util.mk_numeral(0, sig_sz-1));
|
||||
sig_is_p2 = m.mk_eq(sig, p2);
|
||||
shift1_and_sig_p2 = m.mk_and(one_eq_shift, sig_is_p2);
|
||||
c_in_limits = m.mk_or(one_sle_shift, shift1_and_sig_p2);
|
||||
// big_sig is +- [... bv_sz+2 bits ...].[r][g][ ... sbits-1 ... ]
|
||||
big_sig = m_bv_util.mk_zero_extend(bv_sz+2, sig);
|
||||
unsigned big_sig_sz = sig_sz+bv_sz+2;
|
||||
SASSERT(m_bv_util.get_bv_size(big_sig) == big_sig_sz);
|
||||
|
||||
is_neg_shift = m_bv_util.mk_sle(exp_m_lz, m_bv_util.mk_numeral(0, ebits+2));
|
||||
shift = m.mk_ite(is_neg_shift, m_bv_util.mk_bv_neg(exp_m_lz), exp_m_lz);
|
||||
if (ebits+2 < big_sig_sz)
|
||||
shift = m_bv_util.mk_zero_extend(big_sig_sz-ebits-2, shift);
|
||||
else if (ebits+2 > big_sig_sz) {
|
||||
expr_ref upper(m);
|
||||
upper = m_bv_util.mk_extract(big_sig_sz, ebits+2, shift);
|
||||
shift = m_bv_util.mk_extract(ebits+1, 0, shift);
|
||||
shift = m.mk_ite(m.mk_eq(upper, m_bv_util.mk_numeral(0, m_bv_util.get_bv_size(upper))),
|
||||
shift,
|
||||
m_bv_util.mk_numeral(big_sig_sz-1, ebits+2));
|
||||
}
|
||||
dbg_decouple("fpa2bv_to_bv_in_limits", c_in_limits);
|
||||
dbg_decouple("fpa2bv_to_bv_shift_uncapped", shift);
|
||||
SASSERT(m_bv_util.get_bv_size(shift) == m_bv_util.get_bv_size(big_sig));
|
||||
dbg_decouple("fpa2bv_to_bv_big_sig", big_sig);
|
||||
|
||||
expr_ref r_shifted_sig(m), l_shifted_sig(m);
|
||||
r_shifted_sig = m_bv_util.mk_bv_lshr(sig, shift_abs);
|
||||
l_shifted_sig = m_bv_util.mk_bv_shl(sig, m_bv_util.mk_bv_sub(
|
||||
m_bv_util.mk_numeral(m_bv_util.get_bv_size(sig), m_bv_util.get_bv_size(sig)),
|
||||
shift_abs));
|
||||
dbg_decouple("fpa2bv_to_bv_r_shifted_sig", r_shifted_sig);
|
||||
dbg_decouple("fpa2bv_to_bv_l_shifted_sig", l_shifted_sig);
|
||||
expr_ref shift_limit(m);
|
||||
shift_limit = m_bv_util.mk_numeral(bv_sz+2, m_bv_util.get_bv_size(shift));
|
||||
shift = m.mk_ite(m_bv_util.mk_ule(shift, shift_limit), shift, shift_limit);
|
||||
dbg_decouple("fpa2bv_to_bv_shift_limit", shift_limit);
|
||||
dbg_decouple("fpa2bv_to_bv_is_neg_shift", is_neg_shift);
|
||||
dbg_decouple("fpa2bv_to_bv_shift", shift);
|
||||
|
||||
expr_ref last(m), round(m), sticky(m);
|
||||
last = m_bv_util.mk_extract(sig_sz - bv_sz - 0, sig_sz - bv_sz - 0, r_shifted_sig);
|
||||
round = m_bv_util.mk_extract(sig_sz - bv_sz - 1, sig_sz - bv_sz - 1, r_shifted_sig);
|
||||
sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, l_shifted_sig.get());
|
||||
expr_ref big_sig_shifted(m), int_part(m), last(m), round(m), stickies(m), sticky(m);
|
||||
big_sig_shifted = m.mk_ite(is_neg_shift, m_bv_util.mk_bv_lshr(big_sig, shift),
|
||||
m_bv_util.mk_bv_shl(big_sig, shift));
|
||||
int_part = m_bv_util.mk_extract(big_sig_sz-1, big_sig_sz-(bv_sz+3), big_sig_shifted);
|
||||
SASSERT(m_bv_util.get_bv_size(int_part) == bv_sz+3);
|
||||
last = m_bv_util.mk_extract(big_sig_sz-(bv_sz+3), big_sig_sz-(bv_sz+3), big_sig_shifted);
|
||||
round = m_bv_util.mk_extract(big_sig_sz-(bv_sz+4), big_sig_sz-(bv_sz+4), big_sig_shifted);
|
||||
stickies = m_bv_util.mk_extract(big_sig_sz-(bv_sz+5), 0, big_sig_shifted);
|
||||
sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, stickies.get());
|
||||
dbg_decouple("fpa2bv_to_bv_big_sig_shifted", big_sig_shifted);
|
||||
dbg_decouple("fpa2bv_to_bv_int_part", int_part);
|
||||
dbg_decouple("fpa2bv_to_bv_last", last);
|
||||
dbg_decouple("fpa2bv_to_bv_round", round);
|
||||
dbg_decouple("fpa2bv_to_bv_sticky", sticky);
|
||||
|
@ -3333,33 +3242,31 @@ void fpa2bv_converter::mk_to_bv(func_decl * f, unsigned num, expr * const * args
|
|||
SASSERT(m_bv_util.get_bv_size(rounding_decision) == 1);
|
||||
dbg_decouple("fpa2bv_to_bv_rounding_decision", rounding_decision);
|
||||
|
||||
expr_ref unrounded_sig(m), pre_rounded(m), inc(m);
|
||||
unrounded_sig = m_bv_util.mk_zero_extend(1, m_bv_util.mk_extract(sig_sz - 1, sig_sz - bv_sz, r_shifted_sig));
|
||||
inc = m_bv_util.mk_zero_extend(1, m_bv_util.mk_zero_extend(bv_sz - 1, rounding_decision));
|
||||
pre_rounded = m_bv_util.mk_bv_add(unrounded_sig, inc);
|
||||
expr_ref inc(m), pre_rounded(m);
|
||||
inc = m_bv_util.mk_zero_extend(bv_sz+2, rounding_decision);
|
||||
pre_rounded = m_bv_util.mk_bv_add(int_part, inc);
|
||||
dbg_decouple("fpa2bv_to_bv_inc", inc);
|
||||
dbg_decouple("fpa2bv_to_bv_pre_rounded", pre_rounded);
|
||||
|
||||
expr_ref rnd_overflow(m), rnd(m), rnd_has_overflown(m);
|
||||
rnd_overflow = m_bv_util.mk_extract(bv_sz, bv_sz, pre_rounded);
|
||||
rnd = m_bv_util.mk_extract(bv_sz - 1, 0, pre_rounded);
|
||||
rnd_has_overflown = m.mk_eq(rnd_overflow, bv1);
|
||||
dbg_decouple("fpa2bv_to_bv_rnd_has_overflown", rnd_has_overflown);
|
||||
pre_rounded = m.mk_ite(x_is_neg, m_bv_util.mk_bv_neg(pre_rounded), pre_rounded);
|
||||
|
||||
if (is_signed) {
|
||||
expr_ref sgn_eq_1(m), neg_rnd(m);
|
||||
sgn_eq_1 = m.mk_eq(sgn, bv1);
|
||||
neg_rnd = m_bv_util.mk_bv_neg(rnd);
|
||||
m_simp.mk_ite(sgn_eq_1, neg_rnd, rnd, rnd);
|
||||
expr_ref ll(m), ul(m), in_range(m);
|
||||
if (!is_signed) {
|
||||
ll = m_bv_util.mk_numeral(0, bv_sz+3);
|
||||
ul = m_bv_util.mk_zero_extend(3, m_bv_util.mk_numeral(-1, bv_sz));
|
||||
}
|
||||
else {
|
||||
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_numeral(-1, bv_sz-1));
|
||||
}
|
||||
in_range = m.mk_and(m_bv_util.mk_sle(ll, pre_rounded), m_bv_util.mk_sle(pre_rounded, ul));
|
||||
dbg_decouple("fpa2bv_to_bv_in_range", in_range);
|
||||
|
||||
dbg_decouple("fpa2bv_to_bv_rnd", rnd);
|
||||
expr_ref rounded(m);
|
||||
rounded = m_bv_util.mk_extract(bv_sz-1, 0, pre_rounded);
|
||||
dbg_decouple("fpa2bv_to_bv_rounded", rounded);
|
||||
|
||||
expr_ref unspec(m);
|
||||
unspec = is_signed ? mk_to_sbv_unspecified(ebits, sbits, bv_sz) :
|
||||
mk_to_ubv_unspecified(ebits, sbits, bv_sz);
|
||||
result = m.mk_ite(rnd_has_overflown, unspec, rnd);
|
||||
result = m.mk_ite(c_in_limits, result, unspec);
|
||||
result = m.mk_ite(m.mk_not(in_range), unspec_v, rounded);
|
||||
result = m.mk_ite(c2, v2, result);
|
||||
result = m.mk_ite(c1, v1, result);
|
||||
|
||||
|
@ -3378,85 +3285,42 @@ void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * arg
|
|||
mk_to_bv(f, num, args, true, result);
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_to_ubv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 0);
|
||||
unsigned width = m_bv_util.get_bv_size(f->get_range());
|
||||
void fpa2bv_converter::mk_to_bv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 2);
|
||||
SASSERT(m_util.is_bv2rm(args[0]));
|
||||
SASSERT(m_util.is_float(args[1]));
|
||||
|
||||
if (m_hi_fp_unspecified)
|
||||
result = m_bv_util.mk_numeral(0, width);
|
||||
result = m_bv_util.mk_numeral(0, m_bv_util.get_bv_size(f->get_range()));
|
||||
else {
|
||||
func_decl * fd;
|
||||
if (!m_uf2bvuf.find(f, fd)) {
|
||||
fd = m.mk_fresh_func_decl(0, 0, 0, f->get_range());
|
||||
m_uf2bvuf.insert(f, fd);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(fd);
|
||||
}
|
||||
result = m.mk_const(fd);
|
||||
expr * rm_bv = to_app(args[0])->get_arg(0);
|
||||
expr * n = args[1];
|
||||
expr_ref n_bv(m);
|
||||
join_fp(n, n_bv);
|
||||
|
||||
sort * domain[2] = { m.get_sort(rm_bv), m.get_sort(n_bv) };
|
||||
func_decl * f_bv = mk_bv_uf(f, domain, f->get_range());
|
||||
result = m.mk_app(f_bv, rm_bv, n_bv);
|
||||
}
|
||||
|
||||
TRACE("fpa2bv_to_ubv_unspecified", tout << "result=" << mk_ismt2_pp(result, m) << std::endl;);
|
||||
TRACE("fpa2bv_to_bv_unspecified", tout << "result=" << mk_ismt2_pp(result, m) << std::endl;);
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
}
|
||||
|
||||
expr_ref fpa2bv_converter::mk_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned width) {
|
||||
expr_ref res(m);
|
||||
app_ref u(m);
|
||||
u = m_util.mk_internal_to_ubv_unspecified(ebits, sbits, width);
|
||||
mk_to_sbv_unspecified(u->get_decl(), 0, 0, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_to_sbv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 0);
|
||||
unsigned width = m_bv_util.get_bv_size(f->get_range());
|
||||
|
||||
if (m_hi_fp_unspecified)
|
||||
result = m_bv_util.mk_numeral(0, width);
|
||||
else {
|
||||
func_decl * fd;
|
||||
if (!m_uf2bvuf.find(f, fd)) {
|
||||
fd = m.mk_fresh_func_decl(0, 0, 0, f->get_range());
|
||||
m_uf2bvuf.insert(f, fd);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(fd);
|
||||
}
|
||||
result = m.mk_const(fd);
|
||||
}
|
||||
|
||||
TRACE("fpa2bv_to_sbv_unspecified", tout << "result=" << mk_ismt2_pp(result, m) << std::endl;);
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
}
|
||||
|
||||
expr_ref fpa2bv_converter::mk_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned width) {
|
||||
expr_ref res(m);
|
||||
app_ref u(m);
|
||||
u = m_util.mk_internal_to_sbv_unspecified(ebits, sbits, width);
|
||||
mk_to_sbv_unspecified(u->get_decl(), 0, 0, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_to_real_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 1);
|
||||
|
||||
if (m_hi_fp_unspecified)
|
||||
result = m_arith_util.mk_numeral(rational(0), false);
|
||||
else {
|
||||
func_decl * fd;
|
||||
if (!m_uf2bvuf.find(f, fd)) {
|
||||
fd = m.mk_fresh_func_decl(0, 0, 0, f->get_range());
|
||||
m_uf2bvuf.insert(f, fd);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(fd);
|
||||
}
|
||||
result = m.mk_const(fd);
|
||||
}
|
||||
}
|
||||
expr * n = args[0];
|
||||
expr_ref n_bv(m);
|
||||
join_fp(n, n_bv);
|
||||
|
||||
expr_ref fpa2bv_converter::mk_to_real_unspecified(unsigned ebits, unsigned sbits) {
|
||||
expr_ref res(m);
|
||||
app_ref u(m);
|
||||
u = m_util.mk_internal_to_real_unspecified(ebits, sbits);
|
||||
mk_to_real_unspecified(u->get_decl(), 0, 0, res);
|
||||
return res;
|
||||
sort * domain[1] = { m.get_sort(n_bv) };
|
||||
func_decl * f_bv = mk_bv_uf(f, domain, f->get_range());
|
||||
result = m.mk_app(f_bv, n_bv);
|
||||
}
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
|
@ -3467,6 +3331,7 @@ void fpa2bv_converter::mk_fp(func_decl * f, unsigned num, expr * const * args, e
|
|||
result = m_util.mk_fp(args[0], args[1], args[2]);
|
||||
TRACE("fpa2bv_mk_fp", tout << "mk_fp result = " << mk_ismt2_pp(result, m) << std::endl;);
|
||||
}
|
||||
|
||||
void fpa2bv_converter::split_fp(expr * e, expr * & sgn, expr * & exp, expr * & sig) const {
|
||||
SASSERT(m_util.is_fp(e));
|
||||
SASSERT(to_app(e)->get_num_args() == 3);
|
||||
|
@ -3485,6 +3350,14 @@ void fpa2bv_converter::split_fp(expr * e, expr_ref & sgn, expr_ref & exp, expr_r
|
|||
sig = e_sig;
|
||||
}
|
||||
|
||||
void fpa2bv_converter::join_fp(expr * e, expr_ref & res) {
|
||||
SASSERT(m_util.is_fp(e));
|
||||
SASSERT(to_app(e)->get_num_args() == 3);
|
||||
expr *sgn, *exp, *sig;
|
||||
split_fp(e, sgn, exp, sig);
|
||||
res = m_bv_util.mk_concat(m_bv_util.mk_concat(sgn, exp), sig);
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_is_nan(expr * e, expr_ref & result) {
|
||||
expr * sgn, * sig, * exp;
|
||||
split_fp(e, sgn, exp, sig);
|
||||
|
@ -4051,7 +3924,7 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref &
|
|||
// put the sticky bit into the significand.
|
||||
expr_ref ext_sticky(m);
|
||||
ext_sticky = m_bv_util.mk_zero_extend(sbits+1, sticky);
|
||||
expr * tmp[] = { sig, ext_sticky };
|
||||
expr * tmp[2] = { sig, ext_sticky };
|
||||
sig = m_bv_util.mk_bv_or(2, tmp);
|
||||
SASSERT(is_well_sorted(m, sig));
|
||||
SASSERT(m_bv_util.get_bv_size(sig) == sbits+2);
|
||||
|
@ -4221,13 +4094,25 @@ void fpa2bv_converter::reset(void) {
|
|||
dec_ref_map_key_values(m, m_const2bv);
|
||||
dec_ref_map_key_values(m, m_rm_const2bv);
|
||||
dec_ref_map_key_values(m, m_uf2bvuf);
|
||||
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = m_min_max_specials.begin();
|
||||
it != m_min_max_specials.end();
|
||||
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = m_min_max_ufs.begin();
|
||||
it != m_min_max_ufs.end();
|
||||
it++) {
|
||||
m.dec_ref(it->m_key);
|
||||
m.dec_ref(it->m_value.first);
|
||||
m.dec_ref(it->m_value.second);
|
||||
}
|
||||
m_min_max_specials.reset();
|
||||
m_min_max_ufs.reset();
|
||||
m_extra_assertions.reset();
|
||||
}
|
||||
|
||||
func_decl * fpa2bv_converter::mk_bv_uf(func_decl * f, sort * const * domain, sort * range) {
|
||||
func_decl * res;
|
||||
if (!m_uf2bvuf.find(f, res)) {
|
||||
res = m.mk_fresh_func_decl(0, f->get_arity(), domain, range);
|
||||
m_uf2bvuf.insert(f, res);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(res);
|
||||
TRACE("fpa2bv", tout << "New UF func_decl: " << std::endl << mk_ismt2_pp(res, m) << std::endl;);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ protected:
|
|||
const2bv_t m_const2bv;
|
||||
const2bv_t m_rm_const2bv;
|
||||
uf2bvuf_t m_uf2bvuf;
|
||||
special_t m_min_max_specials;
|
||||
special_t m_min_max_ufs;
|
||||
|
||||
friend class fpa2bv_model_converter;
|
||||
friend class bv2fpa_converter;
|
||||
|
@ -76,6 +76,7 @@ public:
|
|||
|
||||
void split_fp(expr * e, expr * & sgn, expr * & exp, expr * & sig) const;
|
||||
void split_fp(expr * e, expr_ref & sgn, expr_ref & exp, expr_ref & sig) const;
|
||||
void join_fp(expr * e, expr_ref & res);
|
||||
|
||||
void mk_eq(expr * a, expr * b, expr_ref & result);
|
||||
void mk_ite(expr * c, expr * t, expr * f, expr_ref & result);
|
||||
|
@ -86,7 +87,7 @@ public:
|
|||
void mk_numeral(sort * s, mpf const & v, expr_ref & result);
|
||||
virtual void mk_const(func_decl * f, expr_ref & result);
|
||||
virtual void mk_rm_const(func_decl * f, expr_ref & result);
|
||||
virtual void mk_function(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
virtual void mk_uf(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_var(unsigned base_inx, sort * srt, expr_ref & result);
|
||||
|
||||
void mk_pinf(func_decl * f, expr_ref & result);
|
||||
|
@ -138,27 +139,23 @@ public:
|
|||
void mk_to_fp_real_int(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
|
||||
void mk_to_ubv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_to_ubv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_to_sbv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_to_sbv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_to_bv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_to_real_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
|
||||
void set_unspecified_fp_hi(bool v) { m_hi_fp_unspecified = v; }
|
||||
|
||||
void mk_min(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_min_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
virtual expr_ref mk_min_max_unspecified(func_decl * f, expr * x, expr * y);
|
||||
|
||||
void mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_max_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
expr_ref mk_min_max_unspecified(func_decl * f, expr * x, expr * y);
|
||||
|
||||
void reset(void);
|
||||
|
||||
void dbg_decouple(const char * prefix, expr_ref & e);
|
||||
expr_ref_vector m_extra_assertions;
|
||||
|
||||
special_t const & get_min_max_specials() const { return m_min_max_specials; };
|
||||
special_t const & get_min_max_specials() const { return m_min_max_ufs; };
|
||||
const2bv_t const & get_const2bv() const { return m_const2bv; };
|
||||
const2bv_t const & get_rm_const2bv() const { return m_rm_const2bv; };
|
||||
uf2bvuf_t const & get_uf2bvuf() const { return m_uf2bvuf; };
|
||||
|
@ -202,12 +199,6 @@ protected:
|
|||
|
||||
void mk_to_bv(func_decl * f, unsigned num, expr * const * args, bool is_signed, expr_ref & result);
|
||||
|
||||
sort_ref replace_float_sorts(sort * s);
|
||||
func_decl_ref replace_function(func_decl * f);
|
||||
expr_ref replace_float_arg(expr * a);
|
||||
void mk_function_output(sort * rng, func_decl * fbv, expr * const * new_args, expr_ref & result);
|
||||
func_decl * get_bv_uf(func_decl * f, sort * bv_rng, unsigned arity);
|
||||
|
||||
private:
|
||||
void mk_nan(sort * s, expr_ref & result);
|
||||
void mk_nzero(sort * s, expr_ref & result);
|
||||
|
@ -227,9 +218,7 @@ private:
|
|||
|
||||
void mk_to_fp_float(sort * s, expr * rm, expr * x, expr_ref & result);
|
||||
|
||||
expr_ref mk_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned width);
|
||||
expr_ref mk_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned width);
|
||||
expr_ref mk_to_real_unspecified(unsigned ebits, unsigned sbits);
|
||||
func_decl * mk_bv_uf(func_decl * f, sort * const * domain, sort * range);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -124,6 +124,8 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
|
|||
case OP_FPA_DIV: m_conv.mk_div(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_REM: m_conv.mk_rem(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_ABS: m_conv.mk_abs(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_MIN: m_conv.mk_min(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_MAX: m_conv.mk_max(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_FMA: m_conv.mk_fma(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_SQRT: m_conv.mk_sqrt(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_ROUND_TO_INTEGRAL: m_conv.mk_round_to_integral(f, num, args, result); return BR_DONE;
|
||||
|
@ -143,24 +145,12 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
|
|||
case OP_FPA_TO_FP_UNSIGNED: m_conv.mk_to_fp_unsigned(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_TO_UBV: m_conv.mk_to_ubv(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED: m_conv.mk_to_ubv_unspecified(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED: m_conv.mk_to_sbv_unspecified(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED: m_conv.mk_to_real_unspecified(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED: m_conv.mk_to_ieee_bv_unspecified(f, num, args, result); return BR_DONE;
|
||||
|
||||
case OP_FPA_MIN: m_conv.mk_min(f, num, args, result); return BR_REWRITE_FULL;
|
||||
case OP_FPA_MAX: m_conv.mk_max(f, num, args, result); return BR_REWRITE_FULL;
|
||||
|
||||
case OP_FPA_INTERNAL_MIN_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_MAX_UNSPECIFIED: result = m_conv.mk_min_max_unspecified(f, args[0], args[1]); return BR_DONE;
|
||||
case OP_FPA_INTERNAL_MIN_I: m_conv.mk_min_i(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_INTERNAL_MAX_I: m_conv.mk_max_i(f, num, args, result); return BR_DONE;
|
||||
|
||||
case OP_FPA_INTERNAL_BVWRAP:
|
||||
case OP_FPA_INTERNAL_BV2RM:
|
||||
case OP_FPA_BVWRAP:
|
||||
case OP_FPA_BV2RM:
|
||||
return BR_FAILED;
|
||||
|
||||
default:
|
||||
|
@ -173,7 +163,7 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
|
|||
{
|
||||
SASSERT(!m_conv.is_float_family(f));
|
||||
if (m_conv.fu().contains_floats(f)) {
|
||||
m_conv.mk_function(f, num, args, result);
|
||||
m_conv.mk_uf(f, num, args, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -361,10 +361,6 @@ func_decl * fpa_decl_plugin::mk_binary_decl(decl_kind k, unsigned num_parameters
|
|||
case OP_FPA_REM: name = "fp.rem"; break;
|
||||
case OP_FPA_MIN: name = "fp.min"; break;
|
||||
case OP_FPA_MAX: name = "fp.max"; break;
|
||||
case OP_FPA_INTERNAL_MIN_I: name = "fp.min_i"; break;
|
||||
case OP_FPA_INTERNAL_MAX_I: name = "fp.max_i"; break;
|
||||
case OP_FPA_INTERNAL_MIN_UNSPECIFIED: name = "fp.min_unspecified"; break;
|
||||
case OP_FPA_INTERNAL_MAX_UNSPECIFIED: name = "fp.max_unspecified"; break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -676,10 +672,10 @@ func_decl * fpa_decl_plugin::mk_to_ieee_bv(decl_kind k, unsigned num_parameters,
|
|||
return m_manager->mk_func_decl(name, 1, domain, bv_srt, func_decl_info(m_family_id, k));
|
||||
}
|
||||
|
||||
func_decl * fpa_decl_plugin::mk_internal_bv2rm(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
func_decl * fpa_decl_plugin::mk_bv2rm(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 1)
|
||||
m_manager->raise_exception("invalid number of arguments to internal_rm");
|
||||
m_manager->raise_exception("invalid number of arguments to bv2rm");
|
||||
if (!is_sort_of(domain[0], m_bv_fid, BV_SORT) || domain[0]->get_parameter(0).get_int() != 3)
|
||||
m_manager->raise_exception("sort mismatch, expected argument of sort bitvector, size 3");
|
||||
if (!is_rm_sort(range))
|
||||
|
@ -690,7 +686,7 @@ func_decl * fpa_decl_plugin::mk_internal_bv2rm(decl_kind k, unsigned num_paramet
|
|||
return m_manager->mk_func_decl(symbol("rm"), 1, &bv_srt, range, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
|
||||
func_decl * fpa_decl_plugin::mk_internal_bv_wrap(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
func_decl * fpa_decl_plugin::mk_bv_wrap(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 1)
|
||||
m_manager->raise_exception("invalid number of arguments to bv_wrap");
|
||||
|
@ -711,65 +707,6 @@ func_decl * fpa_decl_plugin::mk_internal_bv_wrap(decl_kind k, unsigned num_param
|
|||
}
|
||||
}
|
||||
|
||||
func_decl * fpa_decl_plugin::mk_internal_to_ubv_unspecified(
|
||||
decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 0)
|
||||
m_manager->raise_exception("invalid number of arguments to fp.to_ubv_unspecified");
|
||||
if (num_parameters != 3)
|
||||
m_manager->raise_exception("invalid number of parameters to fp.to_ubv_unspecified; expecting 3");
|
||||
if (!parameters[0].is_int() || !parameters[1].is_int() || !parameters[2].is_int())
|
||||
m_manager->raise_exception("invalid parameters type provided to fp.to_ubv_unspecified; expecting 3 integers");
|
||||
|
||||
sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, ¶meters[2]);
|
||||
return m_manager->mk_func_decl(symbol("fp.to_ubv_unspecified"), 0, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
|
||||
func_decl * fpa_decl_plugin::mk_internal_to_sbv_unspecified(
|
||||
decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 0)
|
||||
m_manager->raise_exception("invalid number of arguments to fp.to_sbv_unspecified");
|
||||
if (num_parameters != 3)
|
||||
m_manager->raise_exception("invalid number of parameters to fp.to_sbv_unspecified; expecting 3");
|
||||
if (!parameters[0].is_int() || !parameters[1].is_int() || !parameters[2].is_int())
|
||||
m_manager->raise_exception("invalid parameters type provided to fp.to_sbv_unspecified; expecting 3 integers");
|
||||
|
||||
sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, ¶meters[2]);
|
||||
return m_manager->mk_func_decl(symbol("fp.to_sbv_unspecified"), 0, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
|
||||
func_decl * fpa_decl_plugin::mk_internal_to_real_unspecified(
|
||||
decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 0)
|
||||
m_manager->raise_exception("invalid number of arguments to fp.to_real_unspecified");
|
||||
if (num_parameters != 2)
|
||||
m_manager->raise_exception("invalid number of parameters to fp.to_real_unspecified; expecting 2");
|
||||
if (!parameters[0].is_int() || !parameters[1].is_int())
|
||||
m_manager->raise_exception("invalid parameters type provided to fp.to_real_unspecified; expecting 2 integers");
|
||||
if (!is_sort_of(range, m_arith_fid, REAL_SORT))
|
||||
m_manager->raise_exception("sort mismatch, expected range of Real sort");
|
||||
|
||||
return m_manager->mk_func_decl(symbol("fp.to_real_unspecified"), 0, domain, m_real_sort, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
|
||||
func_decl * fpa_decl_plugin::mk_internal_to_ieee_bv_unspecified(
|
||||
decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 0)
|
||||
m_manager->raise_exception("invalid number of arguments to fp.to_ieee_bv_unspecified; expecting none");
|
||||
if (num_parameters != 2)
|
||||
m_manager->raise_exception("invalid number of parameters to fp.to_ieee_bv_unspecified; expecting 2");
|
||||
if (!parameters[0].is_int() || !parameters[1].is_int())
|
||||
m_manager->raise_exception("invalid parameters type provided to fp.to_ieee_bv_unspecified; expecting 2 integers");
|
||||
|
||||
parameter width_p[1] = { parameter(parameters[0].get_int() + parameters[1].get_int()) };
|
||||
sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, width_p);
|
||||
return m_manager->mk_func_decl(symbol("fp.to_ieee_bv_unspecified"), 0, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
|
||||
|
||||
func_decl * fpa_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
switch (k) {
|
||||
|
@ -835,25 +772,11 @@ func_decl * fpa_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
|
|||
case OP_FPA_TO_IEEE_BV:
|
||||
return mk_to_ieee_bv(k, num_parameters, parameters, arity, domain, range);
|
||||
|
||||
case OP_FPA_INTERNAL_BVWRAP:
|
||||
return mk_internal_bv_wrap(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FPA_INTERNAL_BV2RM:
|
||||
return mk_internal_bv2rm(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FPA_BVWRAP:
|
||||
return mk_bv_wrap(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FPA_BV2RM:
|
||||
return mk_bv2rm(k, num_parameters, parameters, arity, domain, range);
|
||||
|
||||
case OP_FPA_INTERNAL_MIN_I:
|
||||
case OP_FPA_INTERNAL_MAX_I:
|
||||
case OP_FPA_INTERNAL_MIN_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_MAX_UNSPECIFIED:
|
||||
return mk_binary_decl(k, num_parameters, parameters, arity, domain, range);
|
||||
|
||||
case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED:
|
||||
return mk_internal_to_ubv_unspecified(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED:
|
||||
return mk_internal_to_sbv_unspecified(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED:
|
||||
return mk_internal_to_real_unspecified(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED:
|
||||
return mk_internal_to_ieee_bv_unspecified(k, num_parameters, parameters, arity, domain, range);
|
||||
default:
|
||||
m_manager->raise_exception("unsupported floating point operator");
|
||||
return 0;
|
||||
|
@ -1054,30 +977,6 @@ app * fpa_util::mk_nzero(unsigned ebits, unsigned sbits) {
|
|||
return mk_value(v);
|
||||
}
|
||||
|
||||
app * fpa_util::mk_internal_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned width) {
|
||||
parameter ps[] = { parameter(ebits), parameter(sbits), parameter(width) };
|
||||
sort * range = m_bv_util.mk_sort(width);
|
||||
return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED, 3, ps, 0, 0, range);
|
||||
}
|
||||
|
||||
app * fpa_util::mk_internal_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned width) {
|
||||
parameter ps[] = { parameter(ebits), parameter(sbits), parameter(width) };
|
||||
sort * range = m_bv_util.mk_sort(width);
|
||||
return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED, 3, ps, 0, 0, range);
|
||||
}
|
||||
|
||||
app * fpa_util::mk_internal_to_ieee_bv_unspecified(unsigned ebits, unsigned sbits) {
|
||||
parameter ps[] = { parameter(ebits), parameter(sbits) };
|
||||
sort * range = m_bv_util.mk_sort(ebits+sbits);
|
||||
return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED, 2, ps, 0, 0, range);
|
||||
}
|
||||
|
||||
app * fpa_util::mk_internal_to_real_unspecified(unsigned ebits, unsigned sbits) {
|
||||
parameter ps[] = { parameter(ebits), parameter(sbits) };
|
||||
sort * range = m_a_util.mk_real();
|
||||
return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED, 2, ps, 0, 0, range);
|
||||
}
|
||||
|
||||
bool fpa_util::contains_floats(ast * a) {
|
||||
switch (a->get_kind()) {
|
||||
case AST_APP: {
|
||||
|
|
|
@ -86,18 +86,8 @@ enum fpa_op_kind {
|
|||
/* Extensions */
|
||||
OP_FPA_TO_IEEE_BV,
|
||||
|
||||
/* Internal use only */
|
||||
OP_FPA_INTERNAL_BVWRAP,
|
||||
OP_FPA_INTERNAL_BV2RM,
|
||||
|
||||
OP_FPA_INTERNAL_MIN_I,
|
||||
OP_FPA_INTERNAL_MAX_I,
|
||||
OP_FPA_INTERNAL_MIN_UNSPECIFIED,
|
||||
OP_FPA_INTERNAL_MAX_UNSPECIFIED,
|
||||
OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED,
|
||||
OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED,
|
||||
OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED,
|
||||
OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED,
|
||||
OP_FPA_BVWRAP,
|
||||
OP_FPA_BV2RM,
|
||||
|
||||
LAST_FLOAT_OP
|
||||
};
|
||||
|
@ -164,40 +154,16 @@ class fpa_decl_plugin : public decl_plugin {
|
|||
func_decl * mk_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
|
||||
func_decl * mk_internal_bv2rm(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
func_decl * mk_bv2rm(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
func_decl * mk_internal_bv_wrap(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
func_decl * mk_bv_wrap(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
func_decl * mk_internal_bv_unwrap(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
func_decl * mk_internal_to_ubv_unspecified(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
func_decl * mk_internal_to_sbv_unspecified(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
func_decl * mk_internal_to_real_unspecified(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
func_decl * mk_internal_to_ieee_bv_unspecified(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
|
||||
virtual void set_manager(ast_manager * m, family_id id);
|
||||
unsigned mk_id(mpf const & v);
|
||||
void recycled_id(unsigned id);
|
||||
|
||||
virtual bool is_considered_uninterpreted(func_decl * f) {
|
||||
if (f->get_family_id() != get_family_id())
|
||||
return false;
|
||||
switch (f->get_decl_kind())
|
||||
{
|
||||
case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
virtual bool is_considered_uninterpreted(func_decl * f) { return false; }
|
||||
|
||||
public:
|
||||
fpa_decl_plugin();
|
||||
|
@ -251,6 +217,7 @@ public:
|
|||
family_id get_fid() const { return m_fid; }
|
||||
family_id get_family_id() const { return m_fid; }
|
||||
arith_util & au() { return m_a_util; }
|
||||
bv_util & bu() { return m_bv_util; }
|
||||
fpa_decl_plugin & plugin() { return *m_plugin; }
|
||||
|
||||
sort * mk_float_sort(unsigned ebits, unsigned sbits);
|
||||
|
@ -375,35 +342,18 @@ public:
|
|||
|
||||
app * mk_bv2rm(expr * bv3) {
|
||||
SASSERT(m_bv_util.is_bv(bv3) && m_bv_util.get_bv_size(bv3) == 3);
|
||||
return m().mk_app(m_fid, OP_FPA_INTERNAL_BV2RM, 0, 0, 1, &bv3, mk_rm_sort());
|
||||
return m().mk_app(m_fid, OP_FPA_BV2RM, 0, 0, 1, &bv3, mk_rm_sort());
|
||||
}
|
||||
app * mk_internal_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned width);
|
||||
app * mk_internal_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned width);
|
||||
app * mk_internal_to_ieee_bv_unspecified(unsigned ebits, unsigned sbits);
|
||||
app * mk_internal_to_real_unspecified(unsigned ebits, unsigned sbits);
|
||||
|
||||
bool is_bvwrap(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_BVWRAP); }
|
||||
bool is_bvwrap(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_BVWRAP; }
|
||||
bool is_bv2rm(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_BV2RM); }
|
||||
bool is_bv2rm(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_BV2RM; }
|
||||
bool is_bvwrap(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_BVWRAP); }
|
||||
bool is_bv2rm(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_BV2RM); }
|
||||
bool is_to_ubv(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_TO_UBV); }
|
||||
bool is_to_sbv(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_TO_SBV); }
|
||||
|
||||
bool is_min_interpreted(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_MIN_I); }
|
||||
bool is_min_unspecified(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_MIN_UNSPECIFIED); }
|
||||
bool is_max_interpreted(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_MAX_I); }
|
||||
bool is_max_unspecified(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_MAX_UNSPECIFIED); }
|
||||
bool is_to_ubv_unspecified(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED); }
|
||||
bool is_to_sbv_unspecified(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED); }
|
||||
bool is_to_ieee_bv_unspecified(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED); }
|
||||
bool is_to_real_unspecified(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED); }
|
||||
|
||||
bool is_min_interpreted(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_MIN_I; }
|
||||
bool is_min_unspecified(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_MIN_UNSPECIFIED; }
|
||||
bool is_max_interpreted(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_MAX_I; }
|
||||
bool is_max_unspecified(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_MAX_UNSPECIFIED; }
|
||||
bool is_to_ubv_unspecified(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED; }
|
||||
bool is_to_sbv_unspecified(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED; }
|
||||
bool is_to_ieee_bv_unspecified(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED; }
|
||||
bool is_to_real_unspecified(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED; }
|
||||
bool is_bvwrap(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_BVWRAP; }
|
||||
bool is_bv2rm(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_BV2RM; }
|
||||
bool is_to_ubv(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_TO_UBV; }
|
||||
bool is_to_sbv(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_TO_SBV; }
|
||||
|
||||
bool contains_floats(ast * a);
|
||||
};
|
||||
|
|
|
@ -244,7 +244,7 @@ struct pull_quant::imp {
|
|||
quantifier * q1 = m_manager.update_quantifier(to_quantifier(n), new_expr);
|
||||
proof * p1 = 0;
|
||||
if (n != q1) {
|
||||
proof * p0 = m_manager.mk_pull_quant(to_quantifier(n)->get_expr(), to_quantifier(new_expr));
|
||||
proof * p0 = m_manager.mk_pull_quant(n, to_quantifier(new_expr));
|
||||
p1 = m_manager.mk_quant_intro(to_quantifier(n), q1, p0);
|
||||
}
|
||||
proof * p2 = q1 == r ? 0 : m_manager.mk_pull_quant(q1, to_quantifier(r));
|
||||
|
|
|
@ -56,7 +56,6 @@ class arith_rewriter : public poly_rewriter<arith_rewriter_core> {
|
|||
bool m_anum_simp;
|
||||
bool m_elim_rem;
|
||||
bool m_eq2ineq;
|
||||
bool m_process_all_eqs;
|
||||
unsigned m_max_degree;
|
||||
|
||||
void get_coeffs_gcd(expr * t, numeral & g, bool & first, unsigned & num_consts);
|
||||
|
|
|
@ -2,5 +2,5 @@ def_module_params(module_name='rewriter',
|
|||
class_name='array_rewriter_params',
|
||||
export=True,
|
||||
params=(("expand_select_store", BOOL, False, "replace a (select (store ...) ...) term by an if-then-else term"),
|
||||
("expand_store_eq", BOOL, False, "reduce (store ...) = (store ...) with a common base into selects"),
|
||||
("expand_store_eq", BOOL, False, "reduce (store ...) = (store ...) with a common base into selects"),
|
||||
("sort_store", BOOL, False, "sort nested stores when the indices are known to be different")))
|
||||
|
|
|
@ -75,7 +75,7 @@ protected:
|
|||
bool mk_mul(expr* a, expr* b, expr_ref& result);
|
||||
bool mk_comp(eq_type ty, expr* e1, expr* e2, expr_ref& result);
|
||||
bool mk_add(expr* e1, expr* e2, expr_ref& result);
|
||||
|
||||
|
||||
expr * get_cached(expr * n) const;
|
||||
bool is_cached(expr * n) const { return get_cached(n) != 0; }
|
||||
void cache_result(expr * n, expr * r);
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
bv_bounds(ast_manager& m) : m_m(m), m_bv_util(m), m_okay(true) {};
|
||||
~bv_bounds();
|
||||
public: // bounds addition methods
|
||||
br_status rewrite(unsigned limit, func_decl * f, unsigned num, expr * const * args, expr_ref& result);
|
||||
br_status rewrite(unsigned limit, func_decl * f, unsigned num, expr * const * args, expr_ref& result);
|
||||
|
||||
/** \brief Add a constraint to the system.
|
||||
|
||||
|
@ -82,7 +82,7 @@ protected:
|
|||
bv_util m_bv_util;
|
||||
bool m_okay;
|
||||
bool is_sat(app * v);
|
||||
bool is_sat_core(app * v);
|
||||
bool is_sat_core(app * v);
|
||||
inline bool in_range(app *v, numeral l);
|
||||
inline bool is_constant_add(unsigned bv_sz, expr * e, app*& v, numeral& val);
|
||||
void record_singleton(app * v, numeral& singleton_value);
|
||||
|
@ -94,7 +94,7 @@ protected:
|
|||
inline bool bv_bounds::is_okay() { return m_okay; }
|
||||
|
||||
inline bool bv_bounds::to_bound(const expr * e) const {
|
||||
return is_app(e) && m_bv_util.is_bv(e)
|
||||
return is_app(e) && m_bv_util.is_bv(e)
|
||||
&& !m_bv_util.is_bv_add(e)
|
||||
&& !m_bv_util.is_numeral(e);
|
||||
}
|
||||
|
|
|
@ -94,21 +94,8 @@ br_status fpa_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
|
|||
case OP_FPA_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(f, args[0], result); break;
|
||||
case OP_FPA_TO_REAL: SASSERT(num_args == 1); st = mk_to_real(args[0], result); break;
|
||||
|
||||
case OP_FPA_INTERNAL_MIN_I:
|
||||
case OP_FPA_INTERNAL_MAX_I:
|
||||
case OP_FPA_INTERNAL_MIN_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_MAX_UNSPECIFIED:
|
||||
SASSERT(num_args == 2); st = BR_FAILED; break;
|
||||
|
||||
case OP_FPA_INTERNAL_BVWRAP: SASSERT(num_args == 1); st = mk_bvwrap(args[0], result); break;
|
||||
case OP_FPA_INTERNAL_BV2RM: SASSERT(num_args == 1); st = mk_bv2rm(args[0], result); break;
|
||||
|
||||
case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED:
|
||||
st = BR_FAILED;
|
||||
break;
|
||||
case OP_FPA_BVWRAP: SASSERT(num_args == 1); st = mk_bvwrap(args[0], result); break;
|
||||
case OP_FPA_BV2RM: SASSERT(num_args == 1); st = mk_bv2rm(args[0], result); break;
|
||||
|
||||
default:
|
||||
NOT_IMPLEMENTED_YET();
|
||||
|
@ -116,49 +103,10 @@ br_status fpa_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
|
|||
return st;
|
||||
}
|
||||
|
||||
br_status fpa_rewriter::mk_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned width, expr_ref & result) {
|
||||
bv_util bu(m());
|
||||
if (m_hi_fp_unspecified) {
|
||||
// The "hardware interpretation" is 0.
|
||||
result = bu.mk_numeral(0, width);
|
||||
return BR_DONE;
|
||||
}
|
||||
else {
|
||||
result = m_util.mk_internal_to_ubv_unspecified(ebits, sbits, width);
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
}
|
||||
|
||||
br_status fpa_rewriter::mk_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned width, expr_ref & result) {
|
||||
bv_util bu(m());
|
||||
if (m_hi_fp_unspecified) {
|
||||
// The "hardware interpretation" is 0.
|
||||
result = bu.mk_numeral(0, width);
|
||||
return BR_DONE;
|
||||
}
|
||||
else {
|
||||
result = m_util.mk_internal_to_sbv_unspecified(ebits, sbits, width);
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
}
|
||||
|
||||
br_status fpa_rewriter::mk_to_real_unspecified(unsigned ebits, unsigned sbits, expr_ref & result) {
|
||||
if (m_hi_fp_unspecified) {
|
||||
// The "hardware interpretation" is 0.
|
||||
result = m_util.au().mk_numeral(rational(0), false);
|
||||
return BR_DONE;
|
||||
}
|
||||
else {
|
||||
result = m_util.mk_internal_to_real_unspecified(ebits, sbits);
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
}
|
||||
|
||||
br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(f->get_num_parameters() == 2);
|
||||
SASSERT(f->get_parameter(0).is_int());
|
||||
SASSERT(f->get_parameter(1).is_int());
|
||||
bv_util bu(m());
|
||||
scoped_mpf v(m_fm);
|
||||
mpf_rounding_mode rmv;
|
||||
rational r1, r2, r3;
|
||||
|
@ -167,7 +115,7 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const
|
|||
unsigned sbits = f->get_parameter(1).get_int();
|
||||
|
||||
if (num_args == 1) {
|
||||
if (bu.is_numeral(args[0], r1, bvs1)) {
|
||||
if (m_util.bu().is_numeral(args[0], r1, bvs1)) {
|
||||
// BV -> float
|
||||
SASSERT(bvs1 == sbits + ebits);
|
||||
unsynch_mpz_manager & mpzm = m_fm.mpz_manager();
|
||||
|
@ -226,10 +174,10 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const
|
|||
// TRACE("fp_rewriter", tout << "result: " << result << std::endl; );
|
||||
return BR_DONE;
|
||||
}
|
||||
else if (bu.is_numeral(args[1], r1, bvs1)) {
|
||||
else if (m_util.bu().is_numeral(args[1], r1, bvs1)) {
|
||||
// rm + signed bv -> float
|
||||
TRACE("fp_rewriter", tout << "r1: " << r1 << std::endl;);
|
||||
r1 = bu.norm(r1, bvs1, true);
|
||||
r1 = m_util.bu().norm(r1, bvs1, true);
|
||||
TRACE("fp_rewriter", tout << "r1 norm: " << r1 << std::endl;);
|
||||
m_fm.set(v, ebits, sbits, rmv, r1.to_mpq());
|
||||
result = m_util.mk_value(v);
|
||||
|
@ -265,9 +213,9 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const
|
|||
result = m_util.mk_value(v);
|
||||
return BR_DONE;
|
||||
}
|
||||
else if (bu.is_numeral(args[0], r1, bvs1) &&
|
||||
bu.is_numeral(args[1], r2, bvs2) &&
|
||||
bu.is_numeral(args[2], r3, bvs3)) {
|
||||
else if (m_util.bu().is_numeral(args[0], r1, bvs1) &&
|
||||
m_util.bu().is_numeral(args[1], r2, bvs2) &&
|
||||
m_util.bu().is_numeral(args[2], r3, bvs3)) {
|
||||
// 3 BV -> float
|
||||
SASSERT(m_fm.mpz_manager().is_one(r2.to_mpq().denominator()));
|
||||
SASSERT(m_fm.mpz_manager().is_one(r3.to_mpq().denominator()));
|
||||
|
@ -290,7 +238,6 @@ br_status fpa_rewriter::mk_to_fp_unsigned(func_decl * f, expr * arg1, expr * arg
|
|||
SASSERT(f->get_num_parameters() == 2);
|
||||
SASSERT(f->get_parameter(0).is_int());
|
||||
SASSERT(f->get_parameter(1).is_int());
|
||||
bv_util bu(m());
|
||||
unsigned ebits = f->get_parameter(0).get_int();
|
||||
unsigned sbits = f->get_parameter(1).get_int();
|
||||
mpf_rounding_mode rmv;
|
||||
|
@ -298,7 +245,7 @@ br_status fpa_rewriter::mk_to_fp_unsigned(func_decl * f, expr * arg1, expr * arg
|
|||
unsigned bvs;
|
||||
|
||||
if (m_util.is_rm_numeral(arg1, rmv) &&
|
||||
bu.is_numeral(arg2, r, bvs)) {
|
||||
m_util.bu().is_numeral(arg2, r, bvs)) {
|
||||
scoped_mpf v(m_fm);
|
||||
m_fm.set(v, ebits, sbits, rmv, r.to_mpq());
|
||||
result = m_util.mk_value(v);
|
||||
|
@ -331,6 +278,7 @@ br_status fpa_rewriter::mk_sub(expr * arg1, expr * arg2, expr * arg3, expr_ref &
|
|||
|
||||
br_status fpa_rewriter::mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
|
||||
mpf_rounding_mode rm;
|
||||
|
||||
if (m_util.is_rm_numeral(arg1, rm)) {
|
||||
scoped_mpf v2(m_fm), v3(m_fm);
|
||||
if (m_util.is_numeral(arg2, v2) && m_util.is_numeral(arg3, v3)) {
|
||||
|
@ -346,6 +294,7 @@ br_status fpa_rewriter::mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref &
|
|||
|
||||
br_status fpa_rewriter::mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
|
||||
mpf_rounding_mode rm;
|
||||
|
||||
if (m_util.is_rm_numeral(arg1, rm)) {
|
||||
scoped_mpf v2(m_fm), v3(m_fm);
|
||||
if (m_util.is_numeral(arg2, v2) && m_util.is_numeral(arg3, v3)) {
|
||||
|
@ -355,7 +304,6 @@ br_status fpa_rewriter::mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref &
|
|||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
|
@ -393,6 +341,7 @@ br_status fpa_rewriter::mk_neg(expr * arg1, expr_ref & result) {
|
|||
|
||||
br_status fpa_rewriter::mk_rem(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
scoped_mpf v1(m_fm), v2(m_fm);
|
||||
|
||||
if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
|
||||
scoped_mpf t(m_fm);
|
||||
m_fm.rem(v1, v2, t);
|
||||
|
@ -431,27 +380,16 @@ br_status fpa_rewriter::mk_min(expr * arg1, expr * arg2, expr_ref & result) {
|
|||
|
||||
scoped_mpf v1(m_fm), v2(m_fm);
|
||||
if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
|
||||
if (m_fm.is_zero(v1) && m_fm.is_zero(v2) && m_fm.sgn(v1) != m_fm.sgn(v2)) {
|
||||
result = m().mk_app(get_fid(), OP_FPA_INTERNAL_MIN_UNSPECIFIED, arg1, arg2);
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
else {
|
||||
scoped_mpf r(m_fm);
|
||||
m_fm.minimum(v1, v2, r);
|
||||
result = m_util.mk_value(r);
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
expr_ref c(m()), v(m());
|
||||
c = m().mk_and(m().mk_and(m_util.mk_is_zero(arg1), m_util.mk_is_zero(arg2)),
|
||||
m().mk_or(m().mk_and(m_util.mk_is_positive(arg1), m_util.mk_is_negative(arg2)),
|
||||
m().mk_and(m_util.mk_is_negative(arg1), m_util.mk_is_positive(arg2))));
|
||||
v = m().mk_app(get_fid(), OP_FPA_INTERNAL_MIN_UNSPECIFIED, arg1, arg2);
|
||||
if (m_fm.is_zero(v1) && m_fm.is_zero(v2) && m_fm.sgn(v1) != m_fm.sgn(v2))
|
||||
return BR_FAILED;
|
||||
|
||||
result = m().mk_ite(c, v, m().mk_app(get_fid(), OP_FPA_INTERNAL_MIN_I, arg1, arg2));
|
||||
return BR_REWRITE_FULL;
|
||||
scoped_mpf r(m_fm);
|
||||
m_fm.minimum(v1, v2, r);
|
||||
result = m_util.mk_value(r);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status fpa_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
|
@ -466,31 +404,21 @@ br_status fpa_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) {
|
|||
|
||||
scoped_mpf v1(m_fm), v2(m_fm);
|
||||
if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
|
||||
if (m_fm.is_zero(v1) && m_fm.is_zero(v2) && m_fm.sgn(v1) != m_fm.sgn(v2)) {
|
||||
result = m().mk_app(get_fid(), OP_FPA_INTERNAL_MAX_UNSPECIFIED, arg1, arg2);
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
else {
|
||||
scoped_mpf r(m_fm);
|
||||
m_fm.maximum(v1, v2, r);
|
||||
result = m_util.mk_value(r);
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
expr_ref c(m()), v(m());
|
||||
c = m().mk_and(m().mk_and(m_util.mk_is_zero(arg1), m_util.mk_is_zero(arg2)),
|
||||
m().mk_or(m().mk_and(m_util.mk_is_positive(arg1), m_util.mk_is_negative(arg2)),
|
||||
m().mk_and(m_util.mk_is_negative(arg1), m_util.mk_is_positive(arg2))));
|
||||
v = m().mk_app(get_fid(), OP_FPA_INTERNAL_MAX_UNSPECIFIED, arg1, arg2);
|
||||
if (m_fm.is_zero(v1) && m_fm.is_zero(v2) && m_fm.sgn(v1) != m_fm.sgn(v2))
|
||||
return BR_FAILED;
|
||||
|
||||
result = m().mk_ite(c, v, m().mk_app(get_fid(), OP_FPA_INTERNAL_MAX_I, arg1, arg2));
|
||||
return BR_REWRITE_FULL;
|
||||
scoped_mpf r(m_fm);
|
||||
m_fm.maximum(v1, v2, r);
|
||||
result = m_util.mk_value(r);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status fpa_rewriter::mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result) {
|
||||
mpf_rounding_mode rm;
|
||||
|
||||
if (m_util.is_rm_numeral(arg1, rm)) {
|
||||
scoped_mpf v2(m_fm), v3(m_fm), v4(m_fm);
|
||||
if (m_util.is_numeral(arg2, v2) && m_util.is_numeral(arg3, v3) && m_util.is_numeral(arg4, v4)) {
|
||||
|
@ -506,6 +434,7 @@ br_status fpa_rewriter::mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg
|
|||
|
||||
br_status fpa_rewriter::mk_sqrt(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
mpf_rounding_mode rm;
|
||||
|
||||
if (m_util.is_rm_numeral(arg1, rm)) {
|
||||
scoped_mpf v2(m_fm);
|
||||
if (m_util.is_numeral(arg2, v2)) {
|
||||
|
@ -521,6 +450,7 @@ br_status fpa_rewriter::mk_sqrt(expr * arg1, expr * arg2, expr_ref & result) {
|
|||
|
||||
br_status fpa_rewriter::mk_round_to_integral(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
mpf_rounding_mode rm;
|
||||
|
||||
if (m_util.is_rm_numeral(arg1, rm)) {
|
||||
scoped_mpf v2(m_fm);
|
||||
if (m_util.is_numeral(arg2, v2)) {
|
||||
|
@ -588,7 +518,6 @@ br_status fpa_rewriter::mk_lt(expr * arg1, expr * arg2, expr_ref & result) {
|
|||
return BR_DONE;
|
||||
}
|
||||
|
||||
// TODO: more simplifications
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
|
@ -652,6 +581,7 @@ br_status fpa_rewriter::mk_is_pzero(expr * arg1, expr_ref & result) {
|
|||
|
||||
br_status fpa_rewriter::mk_is_nan(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_fm);
|
||||
|
||||
if (m_util.is_numeral(arg1, v)) {
|
||||
result = (m_fm.is_nan(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
|
@ -662,6 +592,7 @@ br_status fpa_rewriter::mk_is_nan(expr * arg1, expr_ref & result) {
|
|||
|
||||
br_status fpa_rewriter::mk_is_inf(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_fm);
|
||||
|
||||
if (m_util.is_numeral(arg1, v)) {
|
||||
result = (m_fm.is_inf(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
|
@ -672,6 +603,7 @@ br_status fpa_rewriter::mk_is_inf(expr * arg1, expr_ref & result) {
|
|||
|
||||
br_status fpa_rewriter::mk_is_normal(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_fm);
|
||||
|
||||
if (m_util.is_numeral(arg1, v)) {
|
||||
result = (m_fm.is_normal(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
|
@ -682,6 +614,7 @@ br_status fpa_rewriter::mk_is_normal(expr * arg1, expr_ref & result) {
|
|||
|
||||
br_status fpa_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_fm);
|
||||
|
||||
if (m_util.is_numeral(arg1, v)) {
|
||||
result = (m_fm.is_denormal(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
|
@ -692,6 +625,7 @@ br_status fpa_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) {
|
|||
|
||||
br_status fpa_rewriter::mk_is_negative(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_fm);
|
||||
|
||||
if (m_util.is_numeral(arg1, v)) {
|
||||
result = (m_fm.is_neg(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
|
@ -702,6 +636,7 @@ br_status fpa_rewriter::mk_is_negative(expr * arg1, expr_ref & result) {
|
|||
|
||||
br_status fpa_rewriter::mk_is_positive(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_fm);
|
||||
|
||||
if (m_util.is_numeral(arg1, v)) {
|
||||
result = (m_fm.is_neg(v) || m_fm.is_nan(v)) ? m().mk_false() : m().mk_true();
|
||||
return BR_DONE;
|
||||
|
@ -714,6 +649,7 @@ br_status fpa_rewriter::mk_is_positive(expr * arg1, expr_ref & result) {
|
|||
// This the SMT =
|
||||
br_status fpa_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
scoped_mpf v1(m_fm), v2(m_fm);
|
||||
|
||||
if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
|
||||
// Note: == is the floats-equality, here we need normal equality.
|
||||
result = (m_fm.is_nan(v1) && m_fm.is_nan(v2)) ? m().mk_true() :
|
||||
|
@ -727,10 +663,10 @@ br_status fpa_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result)
|
|||
}
|
||||
|
||||
br_status fpa_rewriter::mk_bv2rm(expr * arg, expr_ref & result) {
|
||||
bv_util bu(m());
|
||||
rational bv_val;
|
||||
unsigned sz = 0;
|
||||
if (bu.is_numeral(arg, bv_val, sz)) {
|
||||
|
||||
if (m_util.bu().is_numeral(arg, bv_val, sz)) {
|
||||
SASSERT(bv_val.is_uint64());
|
||||
switch (bv_val.get_uint64()) {
|
||||
case BV_RM_TIES_TO_AWAY: result = m_util.mk_round_nearest_ties_to_away(); break;
|
||||
|
@ -749,13 +685,12 @@ br_status fpa_rewriter::mk_bv2rm(expr * arg, expr_ref & result) {
|
|||
|
||||
br_status fpa_rewriter::mk_fp(expr * sgn, expr * exp, expr * sig, expr_ref & result) {
|
||||
unsynch_mpz_manager & mpzm = m_fm.mpz_manager();
|
||||
bv_util bu(m());
|
||||
rational rsgn, rexp, rsig;
|
||||
unsigned bvsz_sgn, bvsz_exp, bvsz_sig;
|
||||
|
||||
if (bu.is_numeral(sgn, rsgn, bvsz_sgn) &&
|
||||
bu.is_numeral(sig, rsig, bvsz_sig) &&
|
||||
bu.is_numeral(exp, rexp, bvsz_exp)) {
|
||||
if (m_util.bu().is_numeral(sgn, rsgn, bvsz_sgn) &&
|
||||
m_util.bu().is_numeral(sig, rsig, bvsz_sig) &&
|
||||
m_util.bu().is_numeral(exp, rexp, bvsz_exp)) {
|
||||
SASSERT(mpzm.is_one(rexp.to_mpq().denominator()));
|
||||
SASSERT(mpzm.is_one(rsig.to_mpq().denominator()));
|
||||
scoped_mpf v(m_fm);
|
||||
|
@ -772,7 +707,7 @@ br_status fpa_rewriter::mk_fp(expr * sgn, expr * exp, expr * sig, expr_ref & res
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status fpa_rewriter::mk_to_ubv(func_decl * f, expr * arg1, expr * arg2, expr_ref & result) {
|
||||
br_status fpa_rewriter::mk_to_bv(func_decl * f, expr * arg1, expr * arg2, bool is_signed, expr_ref & result) {
|
||||
SASSERT(f->get_num_parameters() == 1);
|
||||
SASSERT(f->get_parameter(0).is_int());
|
||||
int bv_sz = f->get_parameter(0).get_int();
|
||||
|
@ -781,10 +716,9 @@ br_status fpa_rewriter::mk_to_ubv(func_decl * f, expr * arg1, expr * arg2, expr_
|
|||
|
||||
if (m_util.is_rm_numeral(arg1, rmv) &&
|
||||
m_util.is_numeral(arg2, v)) {
|
||||
const mpf & x = v.get();
|
||||
|
||||
if (m_fm.is_nan(v) || m_fm.is_inf(v) || m_fm.is_neg(v))
|
||||
return mk_to_ubv_unspecified(x.get_ebits(), x.get_sbits(), bv_sz, result);
|
||||
if (m_fm.is_nan(v) || m_fm.is_inf(v))
|
||||
return mk_to_bv_unspecified(f, result);
|
||||
|
||||
bv_util bu(m());
|
||||
scoped_mpq q(m_fm.mpq_manager());
|
||||
|
@ -792,51 +726,41 @@ br_status fpa_rewriter::mk_to_ubv(func_decl * f, expr * arg1, expr * arg2, expr_
|
|||
|
||||
rational r(q);
|
||||
rational ul, ll;
|
||||
ul = m_fm.m_powers2.m1(bv_sz);
|
||||
ll = rational(0);
|
||||
if (!is_signed) {
|
||||
ul = m_fm.m_powers2.m1(bv_sz);
|
||||
ll = rational(0);
|
||||
}
|
||||
else {
|
||||
ul = m_fm.m_powers2.m1(bv_sz - 1);
|
||||
ll = -m_fm.m_powers2(bv_sz - 1);
|
||||
}
|
||||
if (r >= ll && r <= ul) {
|
||||
result = bu.mk_numeral(r, bv_sz);
|
||||
return BR_DONE;
|
||||
}
|
||||
else
|
||||
return mk_to_ubv_unspecified(x.get_ebits(), x.get_sbits(), bv_sz, result);
|
||||
|
||||
return mk_to_bv_unspecified(f, result);
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status fpa_rewriter::mk_to_sbv(func_decl * f, expr * arg1, expr * arg2, expr_ref & result) {
|
||||
SASSERT(f->get_num_parameters() == 1);
|
||||
SASSERT(f->get_parameter(0).is_int());
|
||||
int bv_sz = f->get_parameter(0).get_int();
|
||||
mpf_rounding_mode rmv;
|
||||
scoped_mpf v(m_fm);
|
||||
|
||||
if (m_util.is_rm_numeral(arg1, rmv) &&
|
||||
m_util.is_numeral(arg2, v)) {
|
||||
const mpf & x = v.get();
|
||||
|
||||
if (m_fm.is_nan(v) || m_fm.is_inf(v))
|
||||
return mk_to_sbv_unspecified(x.get_ebits(), x.get_sbits(), bv_sz, result);
|
||||
|
||||
bv_util bu(m());
|
||||
scoped_mpq q(m_fm.mpq_manager());
|
||||
m_fm.to_sbv_mpq(rmv, v, q);
|
||||
|
||||
rational r(q);
|
||||
rational ul, ll;
|
||||
ul = m_fm.m_powers2.m1(bv_sz - 1);
|
||||
ll = - m_fm.m_powers2(bv_sz - 1);
|
||||
if (r >= ll && r <= ul) {
|
||||
result = bu.mk_numeral(r, bv_sz);
|
||||
return BR_DONE;
|
||||
}
|
||||
else
|
||||
return mk_to_sbv_unspecified(x.get_ebits(), x.get_sbits(), bv_sz, result);
|
||||
br_status fpa_rewriter::mk_to_bv_unspecified(func_decl * f, expr_ref & result) {
|
||||
if (m_hi_fp_unspecified) {
|
||||
unsigned bv_sz = m_util.bu().get_bv_size(f->get_range());
|
||||
result = m_util.bu().mk_numeral(0, bv_sz);
|
||||
return BR_DONE;
|
||||
}
|
||||
else
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
br_status fpa_rewriter::mk_to_ubv(func_decl * f, expr * arg1, expr * arg2, expr_ref & result) {
|
||||
return mk_to_bv(f, arg1, arg2, false, result);
|
||||
}
|
||||
|
||||
br_status fpa_rewriter::mk_to_sbv(func_decl * f, expr * arg1, expr * arg2, expr_ref & result) {
|
||||
return mk_to_bv(f, arg1, arg2, true, result);
|
||||
}
|
||||
|
||||
br_status fpa_rewriter::mk_to_ieee_bv(func_decl * f, expr * arg, expr_ref & result) {
|
||||
|
@ -855,11 +779,8 @@ br_status fpa_rewriter::mk_to_ieee_bv(func_decl * f, expr * arg, expr_ref & resu
|
|||
bu.mk_numeral(0, x.get_sbits() - 2),
|
||||
bu.mk_numeral(1, 1) };
|
||||
result = bu.mk_concat(4, args);
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
else
|
||||
result = m_util.mk_internal_to_ieee_bv_unspecified(x.get_ebits(), x.get_sbits());
|
||||
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
else {
|
||||
scoped_mpz rz(m_fm.mpq_manager());
|
||||
|
@ -877,15 +798,17 @@ br_status fpa_rewriter::mk_to_real(expr * arg, expr_ref & result) {
|
|||
|
||||
if (m_util.is_numeral(arg, v)) {
|
||||
if (m_fm.is_nan(v) || m_fm.is_inf(v)) {
|
||||
const mpf & x = v.get();
|
||||
result = m_util.mk_internal_to_real_unspecified(x.get_ebits(), x.get_sbits());
|
||||
if (m_hi_fp_unspecified) {
|
||||
result = m_util.au().mk_numeral(rational(0), false);
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
scoped_mpq r(m_fm.mpq_manager());
|
||||
m_fm.to_rational(v, r);
|
||||
result = m_util.au().mk_numeral(r.get(), false);
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
|
|
|
@ -21,8 +21,9 @@ Notes:
|
|||
|
||||
#include "ast/ast.h"
|
||||
#include "ast/rewriter/rewriter.h"
|
||||
#include "util/params.h"
|
||||
#include "ast/fpa_decl_plugin.h"
|
||||
#include "ast/expr_map.h"
|
||||
#include "util/params.h"
|
||||
#include "util/mpf.h"
|
||||
|
||||
class fpa_rewriter {
|
||||
|
@ -33,6 +34,9 @@ class fpa_rewriter {
|
|||
app * mk_eq_nan(expr * arg);
|
||||
app * mk_neq_nan(expr * arg);
|
||||
|
||||
br_status mk_to_bv(func_decl * f, expr * arg1, expr * arg2, bool is_signed, expr_ref & result);
|
||||
br_status mk_to_bv_unspecified(func_decl * f, expr_ref & result);
|
||||
|
||||
public:
|
||||
fpa_rewriter(ast_manager & m, params_ref const & p = params_ref());
|
||||
~fpa_rewriter();
|
||||
|
@ -73,22 +77,17 @@ public:
|
|||
br_status mk_is_negative(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_positive(expr * arg1, expr_ref & result);
|
||||
|
||||
br_status mk_to_ieee_bv(expr * arg1, expr_ref & result);
|
||||
|
||||
br_status mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
br_status mk_to_fp_unsigned(func_decl * f, expr * arg1, expr * arg2, expr_ref & result);
|
||||
|
||||
br_status mk_bv2rm(expr * arg, expr_ref & result);
|
||||
br_status mk_fp(expr * sgn, expr * exp, expr * sig, expr_ref & result);
|
||||
br_status mk_to_fp_unsigned(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_to_ubv(func_decl * f, expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_to_sbv(func_decl * f, expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_to_ieee_bv(func_decl * f, expr * arg, expr_ref & result);
|
||||
br_status mk_to_real(expr * arg, expr_ref & result);
|
||||
|
||||
br_status mk_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned with, expr_ref & result);
|
||||
br_status mk_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned with, expr_ref & result);
|
||||
br_status mk_to_real_unspecified(unsigned ebits, unsigned sbits, expr_ref & result);
|
||||
br_status mk_min_i(func_decl * f, expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_max_i(func_decl * f, expr * arg1, expr * arg2, expr_ref & result);
|
||||
|
||||
br_status mk_bvwrap(expr * arg, expr_ref & result);
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
def_module_params(module_name='rewriter',
|
||||
class_name='fpa_rewriter_params',
|
||||
export=True,
|
||||
params=(("hi_fp_unspecified", BOOL, False, "use the 'hardware interpretation' for unspecified values in fp.to_ubv, fp.to_sbv, fp.to_real, and fp.to_ieee_bv"),
|
||||
params=(("hi_fp_unspecified", BOOL, False, "use the 'hardware interpretation' for unspecified values in fp.to_ubv, fp.to_sbv, fp.to_real, and fp.to_ieee_bv"),
|
||||
))
|
||||
|
|
|
@ -686,7 +686,7 @@ br_status poly_rewriter<Config>::mk_sub(unsigned num_args, expr * const * args,
|
|||
return BR_DONE;
|
||||
}
|
||||
set_curr_sort(m().get_sort(args[0]));
|
||||
expr * minus_one = mk_numeral(numeral(-1));
|
||||
expr_ref minus_one(mk_numeral(numeral(-1)), m());
|
||||
ptr_buffer<expr> new_args;
|
||||
new_args.push_back(args[0]);
|
||||
for (unsigned i = 1; i < num_args; i++) {
|
||||
|
@ -1010,7 +1010,6 @@ bool poly_rewriter<Config>::is_var_plus_ground(expr * n, bool & inv, var * & v,
|
|||
stop = true;
|
||||
}
|
||||
if (is_ground(arg)) {
|
||||
TRACE("model_checker_bug", tout << "pushing:\n" << mk_pp(arg, m()) << "\n";);
|
||||
args.push_back(arg);
|
||||
}
|
||||
else if (is_var(arg)) {
|
||||
|
|
|
@ -42,6 +42,10 @@ void rewriter_tpl<Config>::process_var(var * v) {
|
|||
unsigned index = m_bindings.size() - idx - 1;
|
||||
var * r = (var*)(m_bindings[index]);
|
||||
if (r != 0) {
|
||||
CTRACE("rewriter", v->get_sort() != m().get_sort(r),
|
||||
tout << expr_ref(v, m()) << ":" << sort_ref(v->get_sort(), m()) << " != " << expr_ref(r, m()) << ":" << sort_ref(m().get_sort(r), m());
|
||||
tout << "index " << index << " bindings " << m_bindings.size() << "\n";
|
||||
display_bindings(tout););
|
||||
SASSERT(v->get_sort() == m().get_sort(r));
|
||||
if (!is_ground(r) && m_shifts[index] != m_bindings.size()) {
|
||||
|
||||
|
|
|
@ -736,7 +736,6 @@ ast_manager & th_rewriter::m() const {
|
|||
void th_rewriter::updt_params(params_ref const & p) {
|
||||
m_params = p;
|
||||
m_imp->cfg().updt_params(p);
|
||||
IF_VERBOSE(10, verbose_stream() << p << "\n";);
|
||||
}
|
||||
|
||||
void th_rewriter::get_param_descrs(param_descrs & r) {
|
||||
|
|
|
@ -37,6 +37,7 @@ struct check_logic::imp {
|
|||
datatype_util m_dt_util;
|
||||
pb_util m_pb_util;
|
||||
bool m_uf; // true if the logic supports uninterpreted functions
|
||||
bool m_dt; // true if the lgoic supports dattypes
|
||||
bool m_arrays; // true if the logic supports arbitrary arrays
|
||||
bool m_bv_arrays; // true if the logic supports only bv arrays
|
||||
bool m_reals; // true if the logic supports reals
|
||||
|
@ -53,6 +54,7 @@ struct check_logic::imp {
|
|||
|
||||
void reset() {
|
||||
m_uf = false;
|
||||
m_dt = false;
|
||||
m_arrays = false;
|
||||
m_bv_arrays = false;
|
||||
m_reals = false;
|
||||
|
@ -105,6 +107,10 @@ struct check_logic::imp {
|
|||
m_uf = true;
|
||||
m_bvs = true;
|
||||
}
|
||||
else if (logic == "QF_DT") {
|
||||
m_uf = true;
|
||||
m_dt = true;
|
||||
}
|
||||
else if (logic == "QF_AUFLIA") {
|
||||
m_uf = true;
|
||||
m_arrays = true;
|
||||
|
@ -187,6 +193,7 @@ struct check_logic::imp {
|
|||
m_bvs = true;
|
||||
m_uf = true;
|
||||
m_ints = true;
|
||||
m_dt = true;
|
||||
m_nonlinear = true; // non-linear 0-1 variables may get eliminated
|
||||
}
|
||||
else {
|
||||
|
@ -443,7 +450,7 @@ struct check_logic::imp {
|
|||
else if (fid == m_seq_util.get_family_id()) {
|
||||
// nothing to check
|
||||
}
|
||||
else if (fid == m_dt_util.get_family_id() && m_logic == "QF_FD") {
|
||||
else if (fid == m_dt_util.get_family_id() && m_dt) {
|
||||
// nothing to check
|
||||
}
|
||||
else if (fid == m_pb_util.get_family_id() && m_logic == "QF_FD") {
|
||||
|
|
|
@ -202,7 +202,7 @@ func_decl * func_decls::find(unsigned arity, sort * const * domain, sort * range
|
|||
if (f->get_arity() != arity)
|
||||
continue;
|
||||
unsigned i = 0;
|
||||
for (i = 0; i < arity; i++) {
|
||||
for (i = 0; domain && i < arity; i++) {
|
||||
if (f->get_domain(i) != domain[i])
|
||||
break;
|
||||
}
|
||||
|
@ -937,7 +937,7 @@ static builtin_decl const & peek_builtin_decl(builtin_decl const & first, family
|
|||
func_decl * cmd_context::find_func_decl(symbol const & s, unsigned num_indices, unsigned const * indices,
|
||||
unsigned arity, sort * const * domain, sort * range) const {
|
||||
builtin_decl d;
|
||||
if (m_builtin_decls.find(s, d)) {
|
||||
if (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.
|
||||
|
@ -961,7 +961,7 @@ func_decl * cmd_context::find_func_decl(symbol const & s, unsigned num_indices,
|
|||
return f;
|
||||
}
|
||||
|
||||
if (contains_macro(s, arity, domain))
|
||||
if (domain && contains_macro(s, arity, domain))
|
||||
throw cmd_exception("invalid function declaration reference, named expressions (aka macros) cannot be referenced ", s);
|
||||
|
||||
if (num_indices > 0)
|
||||
|
@ -1545,6 +1545,26 @@ void cmd_context::reset_assertions() {
|
|||
}
|
||||
|
||||
|
||||
void cmd_context::display_dimacs() {
|
||||
if (m_solver) {
|
||||
try {
|
||||
gparams::set("sat.dimacs.display", "true");
|
||||
params_ref p;
|
||||
m_solver->updt_params(p);
|
||||
m_solver->check_sat(0, nullptr);
|
||||
}
|
||||
catch (...) {
|
||||
gparams::set("sat.dimacs.display", "false");
|
||||
params_ref p;
|
||||
m_solver->updt_params(p);
|
||||
throw;
|
||||
}
|
||||
gparams::set("sat.dimacs.display", "false");
|
||||
params_ref p;
|
||||
m_solver->updt_params(p);
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_context::display_model(model_ref& mdl) {
|
||||
if (mdl) {
|
||||
model_params p;
|
||||
|
@ -1609,12 +1629,16 @@ void cmd_context::set_diagnostic_stream(char const * name) {
|
|||
}
|
||||
}
|
||||
|
||||
struct contains_array_op_proc {
|
||||
struct contains_underspecified_op_proc {
|
||||
struct found {};
|
||||
family_id m_array_fid;
|
||||
contains_array_op_proc(ast_manager & m):m_array_fid(m.mk_family_id("array")) {}
|
||||
datatype_util m_dt;
|
||||
|
||||
contains_underspecified_op_proc(ast_manager & m):m_array_fid(m.mk_family_id("array")), m_dt(m) {}
|
||||
void operator()(var * n) {}
|
||||
void operator()(app * n) {
|
||||
if (m_dt.is_accessor(n->get_decl()))
|
||||
throw found();
|
||||
if (n->get_family_id() != m_array_fid)
|
||||
return;
|
||||
decl_kind k = n->get_decl_kind();
|
||||
|
@ -1665,6 +1689,16 @@ void cmd_context::complete_model() {
|
|||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < md->get_num_functions(); i++) {
|
||||
func_decl * f = md->get_function(i);
|
||||
func_interp * fi = md->get_func_interp(f);
|
||||
IF_VERBOSE(12, verbose_stream() << "(model.completion " << f->get_name() << ")\n"; );
|
||||
if (fi->is_partial()) {
|
||||
sort * range = f->get_range();
|
||||
fi->set_else(m().get_some_value(range));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto kd : m_func_decls) {
|
||||
symbol const & k = kd.m_key;
|
||||
func_decls & v = kd.m_value;
|
||||
|
@ -1703,7 +1737,7 @@ void cmd_context::validate_model() {
|
|||
p.set_bool("completion", true);
|
||||
model_evaluator evaluator(*(md.get()), p);
|
||||
evaluator.set_expand_array_equalities(false);
|
||||
contains_array_op_proc contains_array(m());
|
||||
contains_underspecified_op_proc contains_underspecified(m());
|
||||
{
|
||||
scoped_rlimit _rlimit(m().limit(), 0);
|
||||
cancel_eh<reslimit> eh(m().limit());
|
||||
|
@ -1729,9 +1763,9 @@ void cmd_context::validate_model() {
|
|||
continue;
|
||||
}
|
||||
try {
|
||||
for_each_expr(contains_array, r);
|
||||
for_each_expr(contains_underspecified, r);
|
||||
}
|
||||
catch (contains_array_op_proc::found) {
|
||||
catch (contains_underspecified_op_proc::found) {
|
||||
continue;
|
||||
}
|
||||
TRACE("model_validate", model_smt2_pp(tout, *this, *(md.get()), 0););
|
||||
|
@ -1948,13 +1982,13 @@ void cmd_context::dt_eh::operator()(sort * dt, pdecl* pd) {
|
|||
TRACE("new_dt_eh", tout << "new datatype: "; m_owner.pm().display(tout, dt); tout << "\n";);
|
||||
for (func_decl * c : *m_dt_util.get_datatype_constructors(dt)) {
|
||||
TRACE("new_dt_eh", tout << "new constructor: " << c->get_name() << "\n";);
|
||||
m_owner.insert(c);
|
||||
m_owner.insert(c);
|
||||
func_decl * r = m_dt_util.get_constructor_recognizer(c);
|
||||
m_owner.insert(r);
|
||||
TRACE("new_dt_eh", tout << "new recognizer: " << r->get_name() << "\n";);
|
||||
for (func_decl * a : *m_dt_util.get_constructor_accessors(c)) {
|
||||
TRACE("new_dt_eh", tout << "new accessor: " << a->get_name() << "\n";);
|
||||
m_owner.insert(a);
|
||||
m_owner.insert(a);
|
||||
}
|
||||
}
|
||||
if (m_owner.m_scopes.size() > 0) {
|
||||
|
|
|
@ -419,6 +419,7 @@ public:
|
|||
|
||||
void display_assertions();
|
||||
void display_statistics(bool show_total_time = false, double total_time = 0.0);
|
||||
void display_dimacs();
|
||||
void reset(bool finalize = false);
|
||||
void assert_expr(expr * t);
|
||||
void assert_expr(symbol const & name, expr * t);
|
||||
|
|
|
@ -31,7 +31,6 @@ Notes:
|
|||
#include "ast/rewriter/var_subst.h"
|
||||
#include "util/gparams.h"
|
||||
|
||||
#ifndef _EXTERNAL_RELEASE
|
||||
|
||||
BINARY_SYM_CMD(get_quantifier_body_cmd,
|
||||
"dbg-get-qbody",
|
||||
|
@ -343,10 +342,19 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
class print_dimacs_cmd : public cmd {
|
||||
public:
|
||||
print_dimacs_cmd():cmd("display-dimacs") {}
|
||||
virtual char const * get_usage() const { return ""; }
|
||||
virtual char const * get_descr(cmd_context & ctx) const { return "print benchmark in DIMACS format"; }
|
||||
virtual unsigned get_arity() const { return 0; }
|
||||
virtual void prepare(cmd_context & ctx) {}
|
||||
virtual void execute(cmd_context & ctx) { ctx.display_dimacs(); }
|
||||
};
|
||||
|
||||
|
||||
void install_dbg_cmds(cmd_context & ctx) {
|
||||
#ifndef _EXTERNAL_RELEASE
|
||||
ctx.insert(alloc(print_dimacs_cmd));
|
||||
ctx.insert(alloc(get_quantifier_body_cmd));
|
||||
ctx.insert(alloc(set_cmd));
|
||||
ctx.insert(alloc(pp_var_cmd));
|
||||
|
@ -369,5 +377,4 @@ void install_dbg_cmds(cmd_context & ctx) {
|
|||
ctx.insert(alloc(instantiate_cmd));
|
||||
ctx.insert(alloc(instantiate_nested_cmd));
|
||||
ctx.insert(alloc(set_next_id));
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -197,6 +197,9 @@ public:
|
|||
}
|
||||
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
if (!m_tactic) {
|
||||
throw cmd_exception("check-sat-using needs a tactic argument");
|
||||
}
|
||||
params_ref p = ctx.params().merge_default_params(ps());
|
||||
tactic_ref tref = using_params(sexpr2tactic(ctx, m_tactic), p);
|
||||
tref->set_logic(ctx.get_logic());
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "duality/duality_wrapper.h"
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
|
@ -41,9 +42,9 @@ namespace Duality {
|
|||
typedef expr Term;
|
||||
|
||||
Z3User(context &_ctx) : ctx(_ctx){}
|
||||
|
||||
|
||||
const char *string_of_int(int n);
|
||||
|
||||
|
||||
Term conjoin(const std::vector<Term> &args);
|
||||
|
||||
Term sum(const std::vector<Term> &args);
|
||||
|
@ -130,58 +131,58 @@ namespace Duality {
|
|||
|
||||
/** This class represents a relation post-fixed point (RPFP) problem as
|
||||
* a "problem graph". The graph consists of Nodes and hyper-edges.
|
||||
*
|
||||
*
|
||||
* A node consists of
|
||||
* - Annotation, a symbolic relation
|
||||
* - Bound, a symbolic relation giving an upper bound on Annotation
|
||||
*
|
||||
*
|
||||
*
|
||||
* A hyper-edge consists of:
|
||||
* - Children, a sequence of children Nodes,
|
||||
* - F, a symbolic relational transformer,
|
||||
* - Parent, a single parent Node.
|
||||
*
|
||||
*
|
||||
* The graph is "solved" when:
|
||||
* - For every Node n, n.Annotation subseteq n.Bound
|
||||
* - For every hyperedge e, e.F(e.Children.Annotation) subseteq e.Parent.Annotation
|
||||
*
|
||||
*
|
||||
* where, if x is a sequence of Nodes, x.Annotation is the sequences
|
||||
* of Annotations of the nodes in the sequence.
|
||||
*
|
||||
*
|
||||
* A symbolic Transformer consists of
|
||||
* - RelParams, a sequence of relational symbols
|
||||
* - IndParams, a sequence of individual symbols
|
||||
* - Formula, a formula over RelParams and IndParams
|
||||
*
|
||||
*
|
||||
* A Transformer t represents a function that takes sequence R of relations
|
||||
* and yields the relation lambda (t.Indparams). Formula(R/RelParams).
|
||||
*
|
||||
*
|
||||
* As a special case, a nullary Transformer (where RelParams is the empty sequence)
|
||||
* represents a fixed relation.
|
||||
*
|
||||
*
|
||||
* An RPFP consists of
|
||||
* - Nodes, a set of Nodes
|
||||
* - Edges, a set of hyper-edges
|
||||
* - Context, a prover context that contains formula AST's
|
||||
*
|
||||
*
|
||||
* Multiple RPFP's can use the same Context, but you should be careful
|
||||
* that only one RPFP asserts constraints in the context at any time.
|
||||
*
|
||||
* that only one RPFP asserts constraints in the context at any time.
|
||||
*
|
||||
* */
|
||||
class RPFP : public Z3User
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
class Edge;
|
||||
class Node;
|
||||
bool HornClauses;
|
||||
|
||||
|
||||
|
||||
/** Interface class for interpolating solver. */
|
||||
|
||||
class LogicSolver {
|
||||
public:
|
||||
|
||||
|
||||
context *ctx; /** Z3 context for formulas */
|
||||
solver *slvr; /** Z3 solver */
|
||||
bool need_goals; /** Can the solver use the goal tree to optimize interpolants? */
|
||||
|
@ -191,7 +192,7 @@ namespace Duality {
|
|||
"assumptions" are currently asserted in the solver. The return
|
||||
value indicates whether the assertions are satisfiable. In the
|
||||
UNSAT case, a tree interpolant is returned in "interpolants".
|
||||
In the SAT case, a model is returned.
|
||||
In the SAT case, a model is returned.
|
||||
*/
|
||||
|
||||
virtual
|
||||
|
@ -201,7 +202,7 @@ namespace Duality {
|
|||
TermTree *goals = 0,
|
||||
bool weak = false
|
||||
) = 0;
|
||||
|
||||
|
||||
/** Declare a constant in the background theory. */
|
||||
virtual void declare_constant(const func_decl &f) = 0;
|
||||
|
||||
|
@ -319,7 +320,7 @@ namespace Duality {
|
|||
virtual void declare_constant(const func_decl &f){
|
||||
bckg.insert(f);
|
||||
}
|
||||
|
||||
|
||||
/** Is this a background constant? */
|
||||
virtual bool is_constant(const func_decl &f){
|
||||
return bckg.find(f) != bckg.end();
|
||||
|
@ -344,9 +345,9 @@ namespace Duality {
|
|||
static iZ3LogicSolver *CreateLogicSolver(config &_config){
|
||||
return new iZ3LogicSolver(_config);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** Create a logic solver from a low-level Z3 context.
|
||||
/** Create a logic solver from a low-level Z3 context.
|
||||
Only use this if you know what you're doing. */
|
||||
static iZ3LogicSolver *CreateLogicSolver(context c){
|
||||
return new iZ3LogicSolver(c);
|
||||
|
@ -357,7 +358,7 @@ namespace Duality {
|
|||
protected:
|
||||
int nodeCount;
|
||||
int edgeCount;
|
||||
|
||||
|
||||
class stack_entry
|
||||
{
|
||||
public:
|
||||
|
@ -365,8 +366,8 @@ namespace Duality {
|
|||
std::list<Node *> nodes;
|
||||
std::list<std::pair<Edge *,Term> > constraints;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
model dualModel;
|
||||
protected:
|
||||
|
@ -375,14 +376,14 @@ namespace Duality {
|
|||
std::vector<Term> axioms; // only saved here for printing purposes
|
||||
solver &aux_solver;
|
||||
hash_set<ast> *proof_core;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/** Construct an RPFP graph with a given interpolating prover context. It is allowed to
|
||||
have multiple RPFP's use the same context, but you should never have teo RPFP's
|
||||
with the same conext asserting nodes or edges at the same time. Note, if you create
|
||||
axioms in one RPFP, them create a second RPFP with the same context, the second will
|
||||
inherit the axioms.
|
||||
inherit the axioms.
|
||||
*/
|
||||
|
||||
RPFP(LogicSolver *_ls) : Z3User(*(_ls->ctx)), dualModel(*(_ls->ctx)), aux_solver(_ls->aux_solver)
|
||||
|
@ -396,7 +397,7 @@ namespace Duality {
|
|||
}
|
||||
|
||||
virtual ~RPFP();
|
||||
|
||||
|
||||
/** Symbolic representation of a relational transformer */
|
||||
class Transformer
|
||||
{
|
||||
|
@ -406,12 +407,12 @@ namespace Duality {
|
|||
Term Formula;
|
||||
RPFP *owner;
|
||||
hash_map<std::string,Term> labels;
|
||||
|
||||
|
||||
Transformer *Clone()
|
||||
{
|
||||
return new Transformer(*this);
|
||||
}
|
||||
|
||||
|
||||
void SetEmpty(){
|
||||
Formula = owner->ctx.bool_val(false);
|
||||
}
|
||||
|
@ -451,7 +452,7 @@ namespace Duality {
|
|||
void Complement(){
|
||||
Formula = !Formula;
|
||||
}
|
||||
|
||||
|
||||
void Simplify(){
|
||||
Formula = Formula.simplify();
|
||||
}
|
||||
|
@ -459,7 +460,7 @@ namespace Duality {
|
|||
Transformer(const std::vector<FuncDecl> &_RelParams, const std::vector<Term> &_IndParams, const Term &_Formula, RPFP *_owner)
|
||||
: RelParams(_RelParams), IndParams(_IndParams), Formula(_Formula) {owner = _owner;}
|
||||
};
|
||||
|
||||
|
||||
/** Create a symbolic transformer. */
|
||||
Transformer CreateTransformer(const std::vector<FuncDecl> &_RelParams, const std::vector<Term> &_IndParams, const Term &_Formula)
|
||||
{
|
||||
|
@ -469,13 +470,13 @@ namespace Duality {
|
|||
// t.labels = foo.Item2;
|
||||
return Transformer(_RelParams,_IndParams,_Formula,this);
|
||||
}
|
||||
|
||||
|
||||
/** Create a relation (nullary relational transformer) */
|
||||
Transformer CreateRelation(const std::vector<Term> &_IndParams, const Term &_Formula)
|
||||
{
|
||||
return CreateTransformer(std::vector<FuncDecl>(), _IndParams, _Formula);
|
||||
}
|
||||
|
||||
|
||||
/** A node in the RPFP graph */
|
||||
class Node
|
||||
{
|
||||
|
@ -491,17 +492,17 @@ namespace Duality {
|
|||
Term dual;
|
||||
Node *map;
|
||||
unsigned recursion_bound;
|
||||
|
||||
|
||||
Node(const FuncDecl &_Name, const Transformer &_Annotation, const Transformer &_Bound, const Transformer &_Underapprox, const Term &_dual, RPFP *_owner, int _number)
|
||||
: Name(_Name), Annotation(_Annotation), Bound(_Bound), Underapprox(_Underapprox), dual(_dual) {owner = _owner; number = _number; Outgoing = 0; recursion_bound = UINT_MAX;}
|
||||
};
|
||||
|
||||
|
||||
/** Create a node in the graph. The input is a term R(v_1...v_n)
|
||||
* where R is an arbitrary relational symbol and v_1...v_n are
|
||||
* arbitary distinct variables. The names are only of mnemonic value,
|
||||
* however, the number and type of arguments determine the type
|
||||
* of the relation at this node. */
|
||||
|
||||
|
||||
Node *CreateNode(const Term &t)
|
||||
{
|
||||
std::vector<Term> _IndParams;
|
||||
|
@ -517,9 +518,9 @@ namespace Duality {
|
|||
nodes.push_back(n);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/** Clone a node (can be from another graph). */
|
||||
|
||||
|
||||
Node *CloneNode(Node *old)
|
||||
{
|
||||
Node *n = new Node(old->Name,
|
||||
|
@ -534,7 +535,7 @@ namespace Duality {
|
|||
n->map = old;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/** Delete a node. You can only do this if not connected to any edges.*/
|
||||
void DeleteNode(Node *node){
|
||||
if(node->Outgoing || !node->Incoming.empty())
|
||||
|
@ -549,7 +550,7 @@ namespace Duality {
|
|||
}
|
||||
|
||||
/** This class represents a hyper-edge in the RPFP graph */
|
||||
|
||||
|
||||
class Edge
|
||||
{
|
||||
public:
|
||||
|
@ -565,15 +566,15 @@ namespace Duality {
|
|||
Edge *map;
|
||||
Term labeled;
|
||||
std::vector<Term> constraints;
|
||||
|
||||
|
||||
Edge(Node *_Parent, const Transformer &_F, const std::vector<Node *> &_Children, RPFP *_owner, int _number)
|
||||
: F(_F), Parent(_Parent), Children(_Children), dual(expr(_owner->ctx)) {
|
||||
owner = _owner;
|
||||
number = _number;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/** Create a hyper-edge. */
|
||||
Edge *CreateEdge(Node *_Parent, const Transformer &_F, const std::vector<Node *> &_Children)
|
||||
{
|
||||
|
@ -584,8 +585,8 @@ namespace Duality {
|
|||
edges.push_back(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** Delete a hyper-edge and unlink it from any nodes. */
|
||||
void DeleteEdge(Edge *edge){
|
||||
if(edge->Parent)
|
||||
|
@ -607,19 +608,19 @@ namespace Duality {
|
|||
}
|
||||
delete edge;
|
||||
}
|
||||
|
||||
|
||||
/** Create an edge that lower-bounds its parent. */
|
||||
Edge *CreateLowerBoundEdge(Node *_Parent)
|
||||
{
|
||||
return CreateEdge(_Parent, _Parent->Annotation, std::vector<Node *>());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** For incremental solving, asserts the constraint associated
|
||||
* with this edge in the SMT context. If this edge is removed,
|
||||
* you must pop the context accordingly. The second argument is
|
||||
* the number of pushes we are inside. */
|
||||
|
||||
|
||||
virtual void AssertEdge(Edge *e, int persist = 0, bool with_children = false, bool underapprox = false);
|
||||
|
||||
/* Constrain an edge by the annotation of one of its children. */
|
||||
|
@ -629,19 +630,19 @@ namespace Duality {
|
|||
/** For incremental solving, asserts the negation of the upper bound associated
|
||||
* with a node.
|
||||
* */
|
||||
|
||||
|
||||
void AssertNode(Node *n);
|
||||
|
||||
/** Assert a constraint on an edge in the SMT context.
|
||||
/** Assert a constraint on an edge in the SMT context.
|
||||
*/
|
||||
void ConstrainEdge(Edge *e, const Term &t);
|
||||
|
||||
|
||||
/** Fix the truth values of atomic propositions in the given
|
||||
edge to their values in the current assignment. */
|
||||
void FixCurrentState(Edge *root);
|
||||
|
||||
|
||||
void FixCurrentStateFull(Edge *edge, const expr &extra);
|
||||
|
||||
|
||||
void FixCurrentStateFull(Edge *edge, const std::vector<expr> &assumps, const hash_map<ast,expr> &renaming);
|
||||
|
||||
/** Declare a constant in the background theory. */
|
||||
|
@ -660,78 +661,78 @@ namespace Duality {
|
|||
|
||||
#if 0
|
||||
/** Do not call this. */
|
||||
|
||||
|
||||
void RemoveAxiom(const Term &t);
|
||||
#endif
|
||||
|
||||
/** Solve an RPFP graph. This means either strengthen the annotation
|
||||
* so that the bound at the given root node is satisfied, or
|
||||
* show that this cannot be done by giving a dual solution
|
||||
* (i.e., a counterexample).
|
||||
*
|
||||
* show that this cannot be done by giving a dual solution
|
||||
* (i.e., a counterexample).
|
||||
*
|
||||
* In the current implementation, this only works for graphs that
|
||||
* are:
|
||||
* - tree-like
|
||||
*
|
||||
*
|
||||
* - closed.
|
||||
*
|
||||
*
|
||||
* In a tree-like graph, every nod has out most one incoming and one out-going edge,
|
||||
* and there are no cycles. In a closed graph, every node has exactly one out-going
|
||||
* edge. This means that the leaves of the tree are all hyper-edges with no
|
||||
* children. Such an edge represents a relation (nullary transformer) and thus
|
||||
* a lower bound on its parent. The parameter root must be the root of this tree.
|
||||
*
|
||||
*
|
||||
* If Solve returns LBool.False, this indicates success. The annotation of the tree
|
||||
* has been updated to satisfy the upper bound at the root.
|
||||
*
|
||||
* has been updated to satisfy the upper bound at the root.
|
||||
*
|
||||
* If Solve returns LBool.True, this indicates a counterexample. For each edge,
|
||||
* you can then call Eval to determine the values of symbols in the transformer formula.
|
||||
* You can also call Empty on a node to determine if its value in the counterexample
|
||||
* is the empty relation.
|
||||
*
|
||||
*
|
||||
* \param root The root of the tree
|
||||
* \param persist Number of context pops through which result should persist
|
||||
*
|
||||
*
|
||||
* \param persist Number of context pops through which result should persist
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
lbool Solve(Node *root, int persist);
|
||||
|
||||
|
||||
/** Same as Solve, but annotates only a single node. */
|
||||
|
||||
lbool SolveSingleNode(Node *root, Node *node);
|
||||
|
||||
/** Get the constraint tree (but don't solve it) */
|
||||
|
||||
|
||||
TermTree *GetConstraintTree(Node *root, Node *skip_descendant = 0);
|
||||
|
||||
|
||||
/** Dispose of the dual model (counterexample) if there is one. */
|
||||
|
||||
|
||||
void DisposeDualModel();
|
||||
|
||||
/** Check satisfiability of asserted edges and nodes. Same functionality as
|
||||
* Solve, except no primal solution (interpolant) is generated in the unsat case. */
|
||||
|
||||
check_result Check(Node *root, std::vector<Node *> underapproxes = std::vector<Node *>(),
|
||||
* Solve, except no primal solution (interpolant) is generated in the unsat case. */
|
||||
|
||||
check_result Check(Node *root, std::vector<Node *> underapproxes = std::vector<Node *>(),
|
||||
std::vector<Node *> *underapprox_core = 0);
|
||||
|
||||
/** Update the model, attempting to make the propositional literals in assumps true. If possible,
|
||||
return sat, else return unsat and keep the old model. */
|
||||
|
||||
|
||||
check_result CheckUpdateModel(Node *root, std::vector<expr> assumps);
|
||||
|
||||
/** Determines the value in the counterexample of a symbol occuring in the transformer formula of
|
||||
* a given edge. */
|
||||
|
||||
|
||||
Term Eval(Edge *e, Term t);
|
||||
|
||||
|
||||
/** Return the fact derived at node p in a counterexample. */
|
||||
|
||||
Term EvalNode(Node *p);
|
||||
|
||||
|
||||
/** Returns true if the given node is empty in the primal solution. For proecudure summaries,
|
||||
this means that the procedure is not called in the current counter-model. */
|
||||
|
||||
|
||||
bool Empty(Node *p);
|
||||
|
||||
/** Compute an underapproximation of every node in a tree rooted at "root",
|
||||
|
@ -747,11 +748,11 @@ namespace Duality {
|
|||
void InterpolateByCases(Node *root, Node *node);
|
||||
|
||||
/** Push a scope. Assertions made after Push can be undone by Pop. */
|
||||
|
||||
|
||||
void Push();
|
||||
|
||||
/** Exception thrown when bad clause is encountered */
|
||||
|
||||
|
||||
struct bad_clause {
|
||||
std::string msg;
|
||||
int i;
|
||||
|
@ -777,7 +778,7 @@ namespace Duality {
|
|||
// thrown on internal error
|
||||
struct Bad {
|
||||
};
|
||||
|
||||
|
||||
// thrown on more serious internal error
|
||||
struct ReallyBad {
|
||||
};
|
||||
|
@ -786,56 +787,56 @@ namespace Duality {
|
|||
struct greedy_reduce_failed {};
|
||||
|
||||
/** Pop a scope (see Push). Note, you cannot pop axioms. */
|
||||
|
||||
|
||||
void Pop(int num_scopes);
|
||||
|
||||
|
||||
/** Erase the proof by performing a Pop, Push and re-assertion of
|
||||
all the popped constraints */
|
||||
void PopPush();
|
||||
|
||||
/** Return true if the given edge is used in the proof of unsat.
|
||||
Can be called only after Solve or Check returns an unsat result. */
|
||||
|
||||
|
||||
bool EdgeUsedInProof(Edge *edge);
|
||||
|
||||
|
||||
/** Convert a collection of clauses to Nodes and Edges in the RPFP.
|
||||
|
||||
|
||||
Predicate unknowns are uninterpreted predicates not
|
||||
occurring in the background theory.
|
||||
|
||||
Clauses are of the form
|
||||
|
||||
|
||||
Clauses are of the form
|
||||
|
||||
B => P(t_1,...,t_k)
|
||||
|
||||
|
||||
where P is a predicate unknown and predicate unknowns
|
||||
occur only positivey in H and only under existential
|
||||
quantifiers in prenex form.
|
||||
|
||||
|
||||
Each predicate unknown maps to a node. Each clause maps to
|
||||
an edge. Let C be a clause B => P(t_1,...,t_k) where the
|
||||
sequence of predicate unknowns occurring in B (in order
|
||||
of occurrence) is P_1..P_n. The clause maps to a transformer
|
||||
T where:
|
||||
|
||||
|
||||
T.Relparams = P_1..P_n
|
||||
T.Indparams = x_1...x+k
|
||||
T.Formula = B /\ t_1 = x_1 /\ ... /\ t_k = x_k
|
||||
|
||||
|
||||
Throws exception bad_clause(msg,i) if a clause i is
|
||||
in the wrong form.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
struct label_struct {
|
||||
symbol name;
|
||||
expr value;
|
||||
bool pos;
|
||||
label_struct(const symbol &s, const expr &e, bool b)
|
||||
: name(s), value(e), pos(b) {}
|
||||
label_struct(const symbol &s, const expr &e, bool b)
|
||||
: name(s), value(e), pos(b) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef _WINDOWS
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
|
@ -847,7 +848,7 @@ namespace Duality {
|
|||
|
||||
void WriteCounterexample(std::ostream &s, Node *node);
|
||||
|
||||
enum FileFormat {DualityFormat, SMT2Format, HornFormat};
|
||||
enum FileFormat {DualityFormat, SMT2Format, HornFormat};
|
||||
|
||||
/** Write the RPFP to a file (currently in SMTLIB 1.2 format) */
|
||||
void WriteProblemToFile(std::string filename, FileFormat format = DualityFormat);
|
||||
|
@ -870,9 +871,9 @@ namespace Duality {
|
|||
/** Fuse a vector of transformers. If the total number of inputs of the transformers
|
||||
is N, then the result is an N-ary transfomer whose output is the union of
|
||||
the outputs of the given transformers. The is, suppose we have a vetor of transfoermers
|
||||
{T_i(r_i1,...,r_iN(i) : i=1..M}. The the result is a transformer
|
||||
|
||||
F(r_11,...,r_iN(1),...,r_M1,...,r_MN(M)) =
|
||||
{T_i(r_i1,...,r_iN(i) : i=1..M}. The the result is a transformer
|
||||
|
||||
F(r_11,...,r_iN(1),...,r_M1,...,r_MN(M)) =
|
||||
T_1(r_11,...,r_iN(1)) U ... U T_M(r_M1,...,r_MN(M))
|
||||
*/
|
||||
|
||||
|
@ -921,7 +922,7 @@ namespace Duality {
|
|||
}
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
void ClearProofCore(){
|
||||
if(proof_core)
|
||||
delete proof_core;
|
||||
|
@ -929,7 +930,7 @@ namespace Duality {
|
|||
}
|
||||
|
||||
Term SuffixVariable(const Term &t, int n);
|
||||
|
||||
|
||||
Term HideVariable(const Term &t, int n);
|
||||
|
||||
void RedVars(Node *node, Term &b, std::vector<Term> &v);
|
||||
|
@ -958,16 +959,16 @@ namespace Duality {
|
|||
|
||||
#if 0
|
||||
void WriteInterps(System.IO.StreamWriter f, TermTree t);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void WriteEdgeVars(Edge *e, hash_map<ast,int> &memo, const Term &t, std::ostream &s);
|
||||
|
||||
void WriteEdgeAssignment(std::ostream &s, Edge *e);
|
||||
|
||||
|
||||
|
||||
// Scan the clause body for occurrences of the predicate unknowns
|
||||
|
||||
Term ScanBody(hash_map<ast,Term> &memo,
|
||||
|
||||
Term ScanBody(hash_map<ast,Term> &memo,
|
||||
const Term &t,
|
||||
hash_map<func_decl,Node *> &pmap,
|
||||
std::vector<func_decl> &res,
|
||||
|
@ -1035,7 +1036,7 @@ namespace Duality {
|
|||
void ConstrainEdgeLocalized(Edge *e, const Term &t);
|
||||
|
||||
void GreedyReduce(solver &s, std::vector<expr> &conjuncts);
|
||||
|
||||
|
||||
void NegateLits(std::vector<expr> &lits);
|
||||
|
||||
expr SimplifyOr(std::vector<expr> &lits);
|
||||
|
@ -1053,7 +1054,7 @@ namespace Duality {
|
|||
void GetGroundLitsUnderQuants(hash_set<ast> *memo, const Term &f, std::vector<Term> &res, int under);
|
||||
|
||||
Term StrengthenFormulaByCaseSplitting(const Term &f, std::vector<expr> &case_lits);
|
||||
|
||||
|
||||
expr NegateLit(const expr &f);
|
||||
|
||||
expr GetEdgeFormula(Edge *e, int persist, bool with_children, bool underapprox);
|
||||
|
@ -1065,7 +1066,7 @@ namespace Duality {
|
|||
expr UnhoistPullRec(hash_map<ast,expr> & memo, const expr &w, hash_map<ast,expr> & init_defs, hash_map<ast,expr> & const_params, hash_map<ast,expr> &const_params_inv, std::vector<expr> &new_params);
|
||||
|
||||
void AddParamsToTransformer(Transformer &trans, const std::vector<expr> ¶ms);
|
||||
|
||||
|
||||
expr AddParamsToApp(const expr &app, const func_decl &new_decl, const std::vector<expr> ¶ms);
|
||||
|
||||
expr GetRelRec(hash_set<ast> &memo, const expr &t, const func_decl &rel);
|
||||
|
@ -1081,7 +1082,7 @@ namespace Duality {
|
|||
void UnhoistLoop(Edge *loop_edge, Edge *init_edge);
|
||||
|
||||
void Unhoist();
|
||||
|
||||
|
||||
Term ElimIteRec(hash_map<ast,expr> &memo, const Term &t, std::vector<expr> &cnsts);
|
||||
|
||||
Term ElimIte(const Term &t);
|
||||
|
@ -1089,11 +1090,11 @@ namespace Duality {
|
|||
void MarkLiveNodes(hash_map<Node *,std::vector<Edge *> > &outgoing, hash_set<Node *> &live_nodes, Node *node);
|
||||
|
||||
virtual void slvr_add(const expr &e);
|
||||
|
||||
|
||||
virtual void slvr_pop(int i);
|
||||
|
||||
virtual void slvr_push();
|
||||
|
||||
|
||||
virtual check_result slvr_check(unsigned n = 0, expr * const assumptions = 0, unsigned *core_size = 0, expr *core = 0);
|
||||
|
||||
virtual lbool ls_interpolate_tree(TermTree *assumptions,
|
||||
|
@ -1105,14 +1106,14 @@ namespace Duality {
|
|||
virtual bool proof_core_contains(const expr &e);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** RPFP solver base class. */
|
||||
|
||||
class Solver {
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
class Counterexample {
|
||||
private:
|
||||
RPFP *tree;
|
||||
|
@ -1148,18 +1149,18 @@ namespace Duality {
|
|||
Counterexample &operator=(const Counterexample &);
|
||||
Counterexample(const Counterexample &);
|
||||
};
|
||||
|
||||
|
||||
/** Solve the problem. You can optionally give an old
|
||||
counterexample to use as a guide. This is chiefly useful for
|
||||
abstraction refinement metholdologies, and is only used as a
|
||||
heuristic. */
|
||||
|
||||
|
||||
virtual bool Solve() = 0;
|
||||
|
||||
|
||||
virtual Counterexample &GetCounterexample() = 0;
|
||||
|
||||
|
||||
virtual bool SetOption(const std::string &option, const std::string &value) = 0;
|
||||
|
||||
|
||||
/** Learn heuristic information from another solver. This
|
||||
is chiefly useful for abstraction refinement, when we want to
|
||||
solve a series of similar problems. */
|
||||
|
@ -1184,7 +1185,7 @@ namespace Duality {
|
|||
|
||||
/** Object thrown on cancellation */
|
||||
struct Canceled {};
|
||||
|
||||
|
||||
/** Object thrown on incompleteness */
|
||||
struct Incompleteness {};
|
||||
};
|
||||
|
@ -1235,16 +1236,16 @@ namespace Duality {
|
|||
public:
|
||||
|
||||
/** appends assumption literals for edge to lits. if with_children is true,
|
||||
includes that annotation of the edge's children.
|
||||
*/
|
||||
includes that annotation of the edge's children.
|
||||
*/
|
||||
void AssertEdgeCache(Edge *e, std::vector<Term> &lits, bool with_children = false);
|
||||
|
||||
|
||||
/** appends assumption literals for node to lits */
|
||||
void AssertNodeCache(Node *, std::vector<Term> lits);
|
||||
|
||||
/** check assumption lits, and return core */
|
||||
check_result CheckCore(const std::vector<Term> &assumps, std::vector<Term> &core);
|
||||
|
||||
|
||||
/** Clone another RPFP into this one, keeping a map */
|
||||
void Clone(RPFP *other);
|
||||
|
||||
|
@ -1287,7 +1288,7 @@ namespace Duality {
|
|||
uptr<solver> slvr;
|
||||
};
|
||||
hash_map<Edge *, edge_solver > edge_solvers;
|
||||
|
||||
|
||||
#ifdef LIMIT_STACK_WEIGHT
|
||||
struct weight_counter {
|
||||
int val;
|
||||
|
@ -1296,7 +1297,7 @@ namespace Duality {
|
|||
std::swap(val,other.val);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct big_stack_entry {
|
||||
weight_counter weight_added;
|
||||
std::vector<expr> new_alits;
|
||||
|
@ -1319,11 +1320,11 @@ namespace Duality {
|
|||
void ConstrainEdgeLocalizedCache(Edge *e, const Term &tl, std::vector<expr> &lits);
|
||||
|
||||
virtual void slvr_add(const expr &e);
|
||||
|
||||
|
||||
virtual void slvr_pop(int i);
|
||||
|
||||
virtual void slvr_push();
|
||||
|
||||
|
||||
virtual check_result slvr_check(unsigned n = 0, expr * const assumptions = 0, unsigned *core_size = 0, expr *core = 0);
|
||||
|
||||
virtual lbool ls_interpolate_tree(TermTree *assumptions,
|
||||
|
@ -1348,7 +1349,7 @@ namespace Duality {
|
|||
scoped_solver_for_edge(RPFP_caching *_rpfp, Edge *edge, bool models = false, bool axioms = false){
|
||||
rpfp = _rpfp;
|
||||
orig_slvr = rpfp->ls->slvr;
|
||||
es = &(rpfp->SolverForEdge(edge,models,axioms));
|
||||
es = &(rpfp->SolverForEdge(edge,models,axioms));
|
||||
rpfp->ls->slvr = es->slvr.get();
|
||||
rpfp->AssumptionLits.swap(es->AssumptionLits);
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ namespace Duality {
|
|||
m_datalog_fid = m().mk_family_id("datalog_relation");
|
||||
}
|
||||
~context() { }
|
||||
|
||||
|
||||
ast_manager &m() const {return *(ast_manager *)&mgr;}
|
||||
|
||||
void set(char const * param, char const * value) { m_config.set(param,value); }
|
||||
|
@ -186,13 +186,13 @@ namespace Duality {
|
|||
|
||||
symbol str_symbol(char const * s);
|
||||
symbol int_symbol(int n);
|
||||
|
||||
|
||||
sort bool_sort();
|
||||
sort int_sort();
|
||||
sort real_sort();
|
||||
sort bv_sort(unsigned sz);
|
||||
sort array_sort(sort d, sort r);
|
||||
|
||||
|
||||
func_decl function(symbol const & name, unsigned arity, sort const * domain, sort const & range);
|
||||
func_decl function(char const * name, unsigned arity, sort const * domain, sort const & range);
|
||||
func_decl function(char const * name, sort const & domain, sort const & range);
|
||||
|
@ -210,22 +210,22 @@ namespace Duality {
|
|||
expr int_const(char const * name);
|
||||
expr real_const(char const * name);
|
||||
expr bv_const(char const * name, unsigned sz);
|
||||
|
||||
|
||||
expr bool_val(bool b);
|
||||
|
||||
|
||||
expr int_val(int n);
|
||||
expr int_val(unsigned n);
|
||||
expr int_val(char const * n);
|
||||
|
||||
|
||||
expr real_val(int n, int d);
|
||||
expr real_val(int n);
|
||||
expr real_val(unsigned n);
|
||||
expr real_val(char const * n);
|
||||
|
||||
|
||||
expr bv_val(int n, unsigned sz);
|
||||
expr bv_val(unsigned n, unsigned sz);
|
||||
expr bv_val(char const * n, unsigned sz);
|
||||
|
||||
|
||||
expr num_val(int n, sort const & s);
|
||||
|
||||
expr mki(family_id fid, ::decl_kind dk, int n, ::expr **args);
|
||||
|
@ -281,17 +281,17 @@ namespace Duality {
|
|||
object(object const & s):m_ctx(s.m_ctx) {}
|
||||
context & ctx() const { return *m_ctx; }
|
||||
friend void check_context(object const & a, object const & b) { assert(a.m_ctx == b.m_ctx); }
|
||||
ast_manager &m() const {return m_ctx->m();}
|
||||
ast_manager &m() const {return m_ctx->m();}
|
||||
};
|
||||
|
||||
class symbol : public object {
|
||||
::symbol m_sym;
|
||||
public:
|
||||
symbol(context & c, ::symbol s):object(c), m_sym(s) {}
|
||||
symbol(symbol const & s):object(s), m_sym(s.m_sym) {}
|
||||
symbol(context & c, ::symbol s):object(c), m_sym(s) {}
|
||||
symbol(symbol const & s):object(s), m_sym(s.m_sym) {}
|
||||
symbol & operator=(symbol const & s) { m_ctx = s.m_ctx; m_sym = s.m_sym; return *this; }
|
||||
operator ::symbol() const {return m_sym;}
|
||||
std::string str() const {
|
||||
operator ::symbol() const {return m_sym;}
|
||||
std::string str() const {
|
||||
if (m_sym.is_numerical()) {
|
||||
std::ostringstream buffer;
|
||||
buffer << m_sym.get_num();
|
||||
|
@ -300,13 +300,13 @@ namespace Duality {
|
|||
else {
|
||||
return m_sym.bare_str();
|
||||
}
|
||||
}
|
||||
friend std::ostream & operator<<(std::ostream & out, symbol const & s){
|
||||
}
|
||||
friend std::ostream & operator<<(std::ostream & out, symbol const & s) {
|
||||
return out << s.str();
|
||||
}
|
||||
friend bool operator==(const symbol &x, const symbol &y){
|
||||
}
|
||||
friend bool operator==(const symbol &x, const symbol &y) {
|
||||
return x.m_sym == y.m_sym;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class params : public config {};
|
||||
|
@ -318,7 +318,7 @@ namespace Duality {
|
|||
public:
|
||||
::ast * const &raw() const {return _ast;}
|
||||
ast_i(context & c, ::ast *a = 0) : object(c) {_ast = a;}
|
||||
|
||||
|
||||
ast_i(){_ast = 0;}
|
||||
bool eq(const ast_i &other) const {
|
||||
return _ast == other._ast;
|
||||
|
@ -345,19 +345,19 @@ namespace Duality {
|
|||
operator ::ast*() const { return raw(); }
|
||||
friend bool eq(ast const & a, ast const & b) { return a.raw() == b.raw(); }
|
||||
|
||||
|
||||
|
||||
ast(context &c, ::ast *a = 0) : ast_i(c,a) {
|
||||
if(_ast)
|
||||
m().inc_ref(a);
|
||||
}
|
||||
|
||||
|
||||
ast() {}
|
||||
|
||||
|
||||
ast(const ast &other) : ast_i(other) {
|
||||
if(_ast)
|
||||
m().inc_ref(_ast);
|
||||
}
|
||||
|
||||
|
||||
ast &operator=(const ast &other) {
|
||||
if(_ast)
|
||||
m().dec_ref(_ast);
|
||||
|
@ -367,7 +367,7 @@ namespace Duality {
|
|||
m().inc_ref(_ast);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
~ast(){
|
||||
if(_ast)
|
||||
m().dec_ref(_ast);
|
||||
|
@ -386,15 +386,15 @@ namespace Duality {
|
|||
sort & operator=(sort const & s) { return static_cast<sort&>(ast::operator=(s)); }
|
||||
|
||||
bool is_bool() const { return m().is_bool(*this); }
|
||||
bool is_int() const { return ctx().get_sort_kind(*this) == IntSort; }
|
||||
bool is_real() const { return ctx().get_sort_kind(*this) == RealSort; }
|
||||
bool is_int() const { return ctx().get_sort_kind(*this) == IntSort; }
|
||||
bool is_real() const { return ctx().get_sort_kind(*this) == RealSort; }
|
||||
bool is_arith() const;
|
||||
bool is_array() const { return ctx().get_sort_kind(*this) == ArraySort; }
|
||||
bool is_datatype() const;
|
||||
bool is_relation() const;
|
||||
bool is_finite_domain() const;
|
||||
bool is_array() const { return ctx().get_sort_kind(*this) == ArraySort; }
|
||||
bool is_datatype() const;
|
||||
bool is_relation() const;
|
||||
bool is_finite_domain() const;
|
||||
|
||||
|
||||
|
||||
sort array_domain() const;
|
||||
sort array_range() const;
|
||||
|
||||
|
@ -404,7 +404,7 @@ namespace Duality {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class func_decl : public ast {
|
||||
public:
|
||||
func_decl() : ast() {}
|
||||
|
@ -413,7 +413,7 @@ namespace Duality {
|
|||
func_decl(func_decl const & s):ast(s) {}
|
||||
operator ::func_decl*() const { return to_func_decl(*this); }
|
||||
func_decl & operator=(func_decl const & s) { return static_cast<func_decl&>(ast::operator=(s)); }
|
||||
|
||||
|
||||
unsigned arity() const;
|
||||
sort domain(unsigned i) const;
|
||||
sort range() const;
|
||||
|
@ -434,9 +434,9 @@ namespace Duality {
|
|||
expr operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4) const;
|
||||
expr operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4, expr const & a5) const;
|
||||
|
||||
func_decl get_func_decl_parameter(unsigned idx){
|
||||
func_decl get_func_decl_parameter(unsigned idx){
|
||||
return func_decl(ctx(),to_func_decl(to_func_decl(raw())->get_parameters()[idx].get_ast()));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@ -447,8 +447,8 @@ namespace Duality {
|
|||
expr(context & c, ::ast *n):ast(c, n) {}
|
||||
expr(expr const & n):ast(n) {}
|
||||
expr & operator=(expr const & n) { return static_cast<expr&>(ast::operator=(n)); }
|
||||
operator ::expr*() const { return to_expr(raw()); }
|
||||
unsigned get_id() const {return to_expr(raw())->get_id();}
|
||||
operator ::expr*() const { return to_expr(raw()); }
|
||||
unsigned get_id() const {return to_expr(raw())->get_id();}
|
||||
|
||||
sort get_sort() const { return sort(ctx(),m().get_sort(to_expr(raw()))); }
|
||||
|
||||
|
@ -460,27 +460,27 @@ namespace Duality {
|
|||
bool is_datatype() const { return get_sort().is_datatype(); }
|
||||
bool is_relation() const { return get_sort().is_relation(); }
|
||||
bool is_finite_domain() const { return get_sort().is_finite_domain(); }
|
||||
bool is_true() const {return is_app() && decl().get_decl_kind() == True; }
|
||||
bool is_true() const {return is_app() && decl().get_decl_kind() == True; }
|
||||
|
||||
bool is_numeral() const {
|
||||
return is_app() && decl().get_decl_kind() == OtherArith && m().is_unique_value(to_expr(raw()));
|
||||
}
|
||||
bool is_app() const {return raw()->get_kind() == AST_APP;}
|
||||
}
|
||||
bool is_app() const {return raw()->get_kind() == AST_APP;}
|
||||
bool is_quantifier() const {return raw()->get_kind() == AST_QUANTIFIER;}
|
||||
bool is_var() const {return raw()->get_kind() == AST_VAR;}
|
||||
bool is_label (bool &pos,std::vector<symbol> &names) const ;
|
||||
bool is_ground() const {return to_app(raw())->is_ground();}
|
||||
bool has_quantifiers() const {return to_app(raw())->has_quantifiers();}
|
||||
bool has_free(int idx) const {
|
||||
bool is_label (bool &pos,std::vector<symbol> &names) const ;
|
||||
bool is_ground() const {return to_app(raw())->is_ground();}
|
||||
bool has_quantifiers() const {return to_app(raw())->has_quantifiers();}
|
||||
bool has_free(int idx) const {
|
||||
used_vars proc;
|
||||
proc.process(to_expr(raw()));
|
||||
return proc.contains(idx);
|
||||
}
|
||||
unsigned get_max_var_idx_plus_1() const {
|
||||
}
|
||||
unsigned get_max_var_idx_plus_1() const {
|
||||
used_vars proc;
|
||||
proc.process(to_expr(raw()));
|
||||
return proc.get_max_found_var_idx_plus_1();
|
||||
}
|
||||
}
|
||||
|
||||
// operator Z3_app() const { assert(is_app()); return reinterpret_cast<Z3_app>(m_ast); }
|
||||
func_decl decl() const {return func_decl(ctx(),to_app(raw())->get_decl());}
|
||||
|
@ -493,11 +493,11 @@ namespace Duality {
|
|||
return 1;
|
||||
case AST_VAR:
|
||||
return 0;
|
||||
default:;
|
||||
default:;
|
||||
}
|
||||
SASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
expr arg(unsigned i) const {
|
||||
ast_kind dk = raw()->get_kind();
|
||||
switch(dk){
|
||||
|
@ -509,25 +509,25 @@ namespace Duality {
|
|||
}
|
||||
assert(0);
|
||||
return expr();
|
||||
}
|
||||
}
|
||||
|
||||
expr body() const {
|
||||
return ctx().cook(to_quantifier(raw())->get_expr());
|
||||
}
|
||||
}
|
||||
|
||||
friend expr operator!(expr const & a) {
|
||||
// ::expr *e = a;
|
||||
return expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_NOT,a));
|
||||
}
|
||||
}
|
||||
|
||||
friend expr operator&&(expr const & a, expr const & b) {
|
||||
return expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_AND,a,b));
|
||||
}
|
||||
}
|
||||
|
||||
friend expr operator||(expr const & a, expr const & b) {
|
||||
return expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_OR,a,b));
|
||||
}
|
||||
|
||||
|
||||
friend expr implies(expr const & a, expr const & b) {
|
||||
return expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_IMPLIES,a,b));
|
||||
}
|
||||
|
@ -546,12 +546,12 @@ namespace Duality {
|
|||
|
||||
friend expr operator*(expr const & a, expr const & b) {
|
||||
return a.ctx().make(Times,a,b); // expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_MUL,a,b));
|
||||
}
|
||||
}
|
||||
|
||||
friend expr operator/(expr const & a, expr const & b) {
|
||||
return a.ctx().make(Div,a,b); // expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_DIV,a,b));
|
||||
}
|
||||
|
||||
|
||||
friend expr operator-(expr const & a) {
|
||||
return a.ctx().make(Uminus,a); // expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_UMINUS,a));
|
||||
}
|
||||
|
@ -562,71 +562,71 @@ namespace Duality {
|
|||
|
||||
friend expr operator<=(expr const & a, expr const & b) {
|
||||
return a.ctx().make(Leq,a,b); // expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_LE,a,b));
|
||||
}
|
||||
}
|
||||
|
||||
friend expr operator>=(expr const & a, expr const & b) {
|
||||
return a.ctx().make(Geq,a,b); //expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_GE,a,b));
|
||||
}
|
||||
|
||||
|
||||
friend expr operator<(expr const & a, expr const & b) {
|
||||
return a.ctx().make(Lt,a,b); expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_LT,a,b));
|
||||
}
|
||||
|
||||
|
||||
friend expr operator>(expr const & a, expr const & b) {
|
||||
return a.ctx().make(Gt,a,b); expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_GT,a,b));
|
||||
}
|
||||
}
|
||||
|
||||
expr simplify() const;
|
||||
|
||||
expr simplify(params const & p) const;
|
||||
|
||||
|
||||
expr qe_lite() const;
|
||||
|
||||
expr qe_lite(const std::set<int> &idxs, bool index_of_bound) const;
|
||||
expr qe_lite(const std::set<int> &idxs, bool index_of_bound) const;
|
||||
|
||||
friend expr clone_quantifier(const expr &, const expr &);
|
||||
friend expr clone_quantifier(const expr &, const expr &);
|
||||
|
||||
friend expr clone_quantifier(const expr &q, const expr &b, const std::vector<expr> &patterns);
|
||||
|
||||
friend expr clone_quantifier(decl_kind, const expr &, const expr &);
|
||||
friend expr clone_quantifier(decl_kind, const expr &, const expr &);
|
||||
|
||||
friend std::ostream & operator<<(std::ostream & out, expr const & m){
|
||||
m.ctx().print_expr(out,m);
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
void get_patterns(std::vector<expr> &pats) const ;
|
||||
void get_patterns(std::vector<expr> &pats) const ;
|
||||
|
||||
unsigned get_quantifier_num_bound() const {
|
||||
unsigned get_quantifier_num_bound() const {
|
||||
return to_quantifier(raw())->get_num_decls();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned get_index_value() const {
|
||||
unsigned get_index_value() const {
|
||||
var* va = to_var(raw());
|
||||
return va->get_idx();
|
||||
}
|
||||
}
|
||||
|
||||
bool is_quantifier_forall() const {
|
||||
return to_quantifier(raw())->is_forall();
|
||||
}
|
||||
}
|
||||
|
||||
sort get_quantifier_bound_sort(unsigned n) const {
|
||||
sort get_quantifier_bound_sort(unsigned n) const {
|
||||
return sort(ctx(),to_quantifier(raw())->get_decl_sort(n));
|
||||
}
|
||||
}
|
||||
|
||||
symbol get_quantifier_bound_name(unsigned n) const {
|
||||
symbol get_quantifier_bound_name(unsigned n) const {
|
||||
return symbol(ctx(),to_quantifier(raw())->get_decl_names()[n]);
|
||||
}
|
||||
}
|
||||
|
||||
friend expr forall(const std::vector<expr> &quants, const expr &body);
|
||||
friend expr forall(const std::vector<expr> &quants, const expr &body);
|
||||
|
||||
friend expr exists(const std::vector<expr> &quants, const expr &body);
|
||||
friend expr exists(const std::vector<expr> &quants, const expr &body);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef ::decl_kind pfrule;
|
||||
|
||||
|
||||
class proof : public ast {
|
||||
public:
|
||||
proof(context & c):ast(c) {}
|
||||
|
@ -643,15 +643,15 @@ namespace Duality {
|
|||
unsigned num_prems() const {
|
||||
return to_app(raw())->get_num_args() - 1;
|
||||
}
|
||||
|
||||
|
||||
expr conc() const {
|
||||
return ctx().cook(to_app(raw())->get_arg(num_prems()));
|
||||
}
|
||||
|
||||
|
||||
proof prem(unsigned i) const {
|
||||
return proof(ctx(),to_app(to_app(raw())->get_arg(i)));
|
||||
}
|
||||
|
||||
|
||||
void get_assumptions(std::vector<expr> &assumps);
|
||||
};
|
||||
|
||||
|
@ -675,12 +675,12 @@ namespace Duality {
|
|||
T back() const { return operator[](size() - 1); }
|
||||
void pop_back() { assert(size() > 0); resize(size() - 1); }
|
||||
bool empty() const { return size() == 0; }
|
||||
ast_vector_tpl & operator=(ast_vector_tpl const & s) {
|
||||
Z3_ast_vector_inc_ref(s.ctx(), s.m_vector);
|
||||
ast_vector_tpl & operator=(ast_vector_tpl const & s) {
|
||||
Z3_ast_vector_inc_ref(s.ctx(), s.m_vector);
|
||||
// Z3_ast_vector_dec_ref(ctx(), m_vector);
|
||||
m_ctx = s.m_ctx;
|
||||
m_ctx = s.m_ctx;
|
||||
m_vector = s.m_vector;
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
friend std::ostream & operator<<(std::ostream & out, ast_vector_tpl const & v) { out << Z3_ast_vector_to_string(v.ctx(), v); return out; }
|
||||
};
|
||||
|
@ -705,9 +705,9 @@ namespace Duality {
|
|||
~func_interp() { }
|
||||
operator ::func_interp *() const { return m_interp; }
|
||||
func_interp & operator=(func_interp const & s) {
|
||||
m_ctx = s.m_ctx;
|
||||
m_ctx = s.m_ctx;
|
||||
m_interp = s.m_interp;
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
unsigned num_entries() const { return m_interp->num_entries(); }
|
||||
expr get_arg(unsigned ent, unsigned arg) const {
|
||||
|
@ -729,32 +729,32 @@ namespace Duality {
|
|||
m_model = m;
|
||||
}
|
||||
public:
|
||||
model(context & c, ::model * m = 0):object(c), m_model(m) { }
|
||||
model(model const & s):object(s), m_model(s.m_model) { }
|
||||
~model() { }
|
||||
model(context & c, ::model * m = 0):object(c), m_model(m) { }
|
||||
model(model const & s):object(s), m_model(s.m_model) { }
|
||||
~model() { }
|
||||
operator ::model *() const { return m_model.get(); }
|
||||
model & operator=(model const & s) {
|
||||
// ::model *_inc_ref(s.ctx(), s.m_model);
|
||||
// ::model *_dec_ref(ctx(), m_model);
|
||||
m_ctx = s.m_ctx;
|
||||
m_ctx = s.m_ctx;
|
||||
m_model = s.m_model.get();
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
model & operator=(::model *s) {
|
||||
m_model = s;
|
||||
return *this;
|
||||
m_model = s;
|
||||
return *this;
|
||||
}
|
||||
bool null() const {return !m_model;}
|
||||
|
||||
bool null() const {return !m_model;}
|
||||
|
||||
expr eval(expr const & n, bool model_completion=true) const {
|
||||
::model * _m = m_model.get();
|
||||
expr_ref result(ctx().m());
|
||||
_m->eval(n, result, model_completion);
|
||||
return expr(ctx(), result);
|
||||
}
|
||||
|
||||
|
||||
void show() const;
|
||||
void show_hash() const;
|
||||
void show_hash() const;
|
||||
|
||||
unsigned num_consts() const {return m_model.get()->get_num_constants();}
|
||||
unsigned num_funcs() const {return m_model.get()->get_num_functions();}
|
||||
|
@ -765,11 +765,11 @@ namespace Duality {
|
|||
|
||||
expr get_const_interp(func_decl f) const {
|
||||
return ctx().cook(m_model->get_const_interp(to_func_decl(f.raw())));
|
||||
}
|
||||
}
|
||||
|
||||
func_interp get_func_interp(func_decl f) const {
|
||||
return func_interp(ctx(),m_model->get_func_interp(to_func_decl(f.raw())));
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
friend std::ostream & operator<<(std::ostream & out, model const & m) { out << Z3_model_to_string(m.ctx(), m); return out; }
|
||||
|
@ -792,9 +792,9 @@ namespace Duality {
|
|||
stats & operator=(stats const & s) {
|
||||
Z3_stats_inc_ref(s.ctx(), s.m_stats);
|
||||
if (m_stats) Z3_stats_dec_ref(ctx(), m_stats);
|
||||
m_ctx = s.m_ctx;
|
||||
m_ctx = s.m_ctx;
|
||||
m_stats = s.m_stats;
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
unsigned size() const { return Z3_stats_size(ctx(), m_stats); }
|
||||
std::string key(unsigned i) const { Z3_string s = Z3_stats_get_key(ctx(), m_stats, i); check_error(); return s; }
|
||||
|
@ -820,7 +820,7 @@ namespace Duality {
|
|||
void assert_cnst(const expr &cnst);
|
||||
};
|
||||
|
||||
inline std::ostream & operator<<(std::ostream & out, check_result r) {
|
||||
inline std::ostream & operator<<(std::ostream & out, check_result r) {
|
||||
if (r == unsat) out << "unsat";
|
||||
else if (r == sat) out << "sat";
|
||||
else out << "unknown";
|
||||
|
@ -837,54 +837,54 @@ namespace Duality {
|
|||
protected:
|
||||
::solver *m_solver;
|
||||
model the_model;
|
||||
bool canceled;
|
||||
proof_gen_mode m_mode;
|
||||
bool extensional;
|
||||
bool canceled;
|
||||
proof_gen_mode m_mode;
|
||||
bool extensional;
|
||||
public:
|
||||
solver(context & c, bool extensional = false, bool models = true);
|
||||
solver(context & c, ::solver *s):object(c),the_model(c) { m_solver = s; canceled = false;}
|
||||
solver(solver const & s):object(s), the_model(s.the_model) { m_solver = s.m_solver; canceled = false;}
|
||||
solver(context & c, ::solver *s):object(c),the_model(c) { m_solver = s; canceled = false;}
|
||||
solver(solver const & s):object(s), the_model(s.the_model) { m_solver = s.m_solver; canceled = false;}
|
||||
~solver() {
|
||||
if(m_solver)
|
||||
dealloc(m_solver);
|
||||
}
|
||||
operator ::solver*() const { return m_solver; }
|
||||
solver & operator=(solver const & s) {
|
||||
m_ctx = s.m_ctx;
|
||||
m_solver = s.m_solver;
|
||||
the_model = s.the_model;
|
||||
m_mode = s.m_mode;
|
||||
return *this;
|
||||
}
|
||||
struct cancel_exception {};
|
||||
void checkpoint(){
|
||||
operator ::solver*() const { return m_solver; }
|
||||
solver & operator=(solver const & s) {
|
||||
m_ctx = s.m_ctx;
|
||||
m_solver = s.m_solver;
|
||||
the_model = s.the_model;
|
||||
m_mode = s.m_mode;
|
||||
return *this;
|
||||
}
|
||||
struct cancel_exception {};
|
||||
void checkpoint(){
|
||||
if(canceled)
|
||||
throw(cancel_exception());
|
||||
}
|
||||
}
|
||||
// void set(params const & p) { Z3_solver_set_params(ctx(), m_solver, p); check_error(); }
|
||||
void push() { scoped_proof_mode spm(m(),m_mode); m_solver->push(); }
|
||||
void pop(unsigned n = 1) { scoped_proof_mode spm(m(),m_mode); m_solver->pop(n); }
|
||||
// void reset() { Z3_solver_reset(ctx(), m_solver); check_error(); }
|
||||
void add(expr const & e) { scoped_proof_mode spm(m(),m_mode); m_solver->assert_expr(e); }
|
||||
check_result check() {
|
||||
scoped_proof_mode spm(m(),m_mode);
|
||||
check_result check() {
|
||||
scoped_proof_mode spm(m(),m_mode);
|
||||
checkpoint();
|
||||
lbool r = m_solver->check_sat(0,0);
|
||||
model_ref m;
|
||||
m_solver->get_model(m);
|
||||
the_model = m.get();
|
||||
return to_check_result(r);
|
||||
}
|
||||
check_result check_keep_model(unsigned n, expr * const assumptions, unsigned *core_size = 0, expr *core = 0) {
|
||||
scoped_proof_mode spm(m(),m_mode);
|
||||
}
|
||||
check_result check_keep_model(unsigned n, expr * const assumptions, unsigned *core_size = 0, expr *core = 0) {
|
||||
scoped_proof_mode spm(m(),m_mode);
|
||||
model old_model(the_model);
|
||||
check_result res = check(n,assumptions,core_size,core);
|
||||
if(the_model == 0)
|
||||
the_model = old_model;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
check_result check(unsigned n, expr * const assumptions, unsigned *core_size = 0, expr *core = 0) {
|
||||
scoped_proof_mode spm(m(),m_mode);
|
||||
scoped_proof_mode spm(m(),m_mode);
|
||||
checkpoint();
|
||||
std::vector< ::expr *> _assumptions(n);
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
|
@ -892,7 +892,7 @@ namespace Duality {
|
|||
}
|
||||
the_model = 0;
|
||||
lbool r = m_solver->check_sat(n, VEC2PTR(_assumptions));
|
||||
|
||||
|
||||
if(core_size && core){
|
||||
ptr_vector< ::expr> _core;
|
||||
m_solver->get_unsat_core(_core);
|
||||
|
@ -905,20 +905,20 @@ namespace Duality {
|
|||
m_solver->get_model(m);
|
||||
the_model = m.get();
|
||||
|
||||
return to_check_result(r);
|
||||
return to_check_result(r);
|
||||
}
|
||||
#if 0
|
||||
check_result check(expr_vector assumptions) {
|
||||
scoped_proof_mode spm(m(),m_mode);
|
||||
check_result check(expr_vector assumptions) {
|
||||
scoped_proof_mode spm(m(),m_mode);
|
||||
unsigned n = assumptions.size();
|
||||
z3array<Z3_ast> _assumptions(n);
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
check_context(*this, assumptions[i]);
|
||||
_assumptions[i] = assumptions[i];
|
||||
}
|
||||
Z3_lbool r = Z3_check_assumptions(ctx(), m_solver, n, _assumptions.ptr());
|
||||
check_error();
|
||||
return to_check_result(r);
|
||||
Z3_lbool r = Z3_check_assumptions(ctx(), m_solver, n, _assumptions.ptr());
|
||||
check_error();
|
||||
return to_check_result(r);
|
||||
}
|
||||
#endif
|
||||
model get_model() const { return model(ctx(), the_model); }
|
||||
|
@ -930,27 +930,26 @@ namespace Duality {
|
|||
#endif
|
||||
// expr proof() const { Z3_ast r = Z3_solver_proof(ctx(), m_solver); check_error(); return expr(ctx(), r); }
|
||||
// friend std::ostream & operator<<(std::ostream & out, solver const & s) { out << Z3_solver_to_string(s.ctx(), s); return out; }
|
||||
|
||||
int get_num_decisions();
|
||||
int get_num_decisions();
|
||||
|
||||
void cancel(){
|
||||
scoped_proof_mode spm(m(),m_mode);
|
||||
void cancel(){
|
||||
scoped_proof_mode spm(m(),m_mode);
|
||||
canceled = true;
|
||||
m().limit().cancel();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned get_scope_level(){ scoped_proof_mode spm(m(),m_mode); return m_solver->get_scope_level();}
|
||||
unsigned get_scope_level(){ scoped_proof_mode spm(m(),m_mode); return m_solver->get_scope_level();}
|
||||
|
||||
void show();
|
||||
void print(const char *filename);
|
||||
void show_assertion_ids();
|
||||
void show();
|
||||
void print(const char *filename);
|
||||
void show_assertion_ids();
|
||||
|
||||
proof get_proof(){
|
||||
scoped_proof_mode spm(m(),m_mode);
|
||||
proof get_proof(){
|
||||
scoped_proof_mode spm(m(),m_mode);
|
||||
return proof(ctx(),m_solver->get_proof());
|
||||
}
|
||||
}
|
||||
|
||||
bool extensional_array_theory() {return extensional;}
|
||||
bool extensional_array_theory() {return extensional;}
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
@ -969,20 +968,20 @@ namespace Duality {
|
|||
goal & operator=(goal const & s) {
|
||||
Z3_goal_inc_ref(s.ctx(), s.m_goal);
|
||||
Z3_goal_dec_ref(ctx(), m_goal);
|
||||
m_ctx = s.m_ctx;
|
||||
m_ctx = s.m_ctx;
|
||||
m_goal = s.m_goal;
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
void add(expr const & f) { check_context(*this, f); Z3_goal_assert(ctx(), m_goal, f); check_error(); }
|
||||
unsigned size() const { return Z3_goal_size(ctx(), m_goal); }
|
||||
expr operator[](unsigned i) const { Z3_ast r = Z3_goal_formula(ctx(), m_goal, i); check_error(); return expr(ctx(), r); }
|
||||
Z3_goal_prec precision() const { return Z3_goal_precision(ctx(), m_goal); }
|
||||
bool inconsistent() const { return Z3_goal_inconsistent(ctx(), m_goal) != 0; }
|
||||
unsigned depth() const { return Z3_goal_depth(ctx(), m_goal); }
|
||||
unsigned depth() const { return Z3_goal_depth(ctx(), m_goal); }
|
||||
void reset() { Z3_goal_reset(ctx(), m_goal); }
|
||||
unsigned num_exprs() const { Z3_goal_num_exprs(ctx(), m_goal); }
|
||||
bool is_decided_sat() const { return Z3_goal_is_decided_sat(ctx(), m_goal) != 0; }
|
||||
bool is_decided_unsat() const { return Z3_goal_is_decided_unsat(ctx(), m_goal) != 0; }
|
||||
bool is_decided_sat() const { return Z3_goal_is_decided_sat(ctx(), m_goal) != 0; }
|
||||
bool is_decided_unsat() const { return Z3_goal_is_decided_unsat(ctx(), m_goal) != 0; }
|
||||
friend std::ostream & operator<<(std::ostream & out, goal const & g) { out << Z3_goal_to_string(g.ctx(), g); return out; }
|
||||
};
|
||||
|
||||
|
@ -1000,15 +999,15 @@ namespace Duality {
|
|||
apply_result & operator=(apply_result const & s) {
|
||||
Z3_apply_result_inc_ref(s.ctx(), s.m_apply_result);
|
||||
Z3_apply_result_dec_ref(ctx(), m_apply_result);
|
||||
m_ctx = s.m_ctx;
|
||||
m_ctx = s.m_ctx;
|
||||
m_apply_result = s.m_apply_result;
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
unsigned size() const { return Z3_apply_result_get_num_subgoals(ctx(), m_apply_result); }
|
||||
goal operator[](unsigned i) const { Z3_goal r = Z3_apply_result_get_subgoal(ctx(), m_apply_result, i); check_error(); return goal(ctx(), r); }
|
||||
goal operator[](int i) const { assert(i >= 0); return this->operator[](static_cast<unsigned>(i)); }
|
||||
model convert_model(model const & m, unsigned i = 0) const {
|
||||
check_context(*this, m);
|
||||
model convert_model(model const & m, unsigned i = 0) const {
|
||||
check_context(*this, m);
|
||||
Z3_model new_m = Z3_apply_result_convert_model(ctx(), m_apply_result, i, m);
|
||||
check_error();
|
||||
return model(ctx(), new_m);
|
||||
|
@ -1031,16 +1030,16 @@ namespace Duality {
|
|||
tactic & operator=(tactic const & s) {
|
||||
Z3_tactic_inc_ref(s.ctx(), s.m_tactic);
|
||||
Z3_tactic_dec_ref(ctx(), m_tactic);
|
||||
m_ctx = s.m_ctx;
|
||||
m_ctx = s.m_ctx;
|
||||
m_tactic = s.m_tactic;
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
solver mk_solver() const { Z3_solver r = Z3_mk_solver_from_tactic(ctx(), m_tactic); check_error(); return solver(ctx(), r); }
|
||||
apply_result apply(goal const & g) const {
|
||||
apply_result apply(goal const & g) const {
|
||||
check_context(*this, g);
|
||||
Z3_apply_result r = Z3_tactic_apply(ctx(), m_tactic, g);
|
||||
check_error();
|
||||
return apply_result(ctx(), r);
|
||||
Z3_apply_result r = Z3_tactic_apply(ctx(), m_tactic, g);
|
||||
check_error();
|
||||
return apply_result(ctx(), r);
|
||||
}
|
||||
apply_result operator()(goal const & g) const {
|
||||
return apply(g);
|
||||
|
@ -1091,45 +1090,45 @@ namespace Duality {
|
|||
probe & operator=(probe const & s) {
|
||||
Z3_probe_inc_ref(s.ctx(), s.m_probe);
|
||||
Z3_probe_dec_ref(ctx(), m_probe);
|
||||
m_ctx = s.m_ctx;
|
||||
m_ctx = s.m_ctx;
|
||||
m_probe = s.m_probe;
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
double apply(goal const & g) const { double r = Z3_probe_apply(ctx(), m_probe, g); check_error(); return r; }
|
||||
double operator()(goal const & g) const { return apply(g); }
|
||||
friend probe operator<=(probe const & p1, probe const & p2) {
|
||||
check_context(p1, p2); Z3_probe r = Z3_probe_le(p1.ctx(), p1, p2); p1.check_error(); return probe(p1.ctx(), r);
|
||||
friend probe operator<=(probe const & p1, probe const & p2) {
|
||||
check_context(p1, p2); Z3_probe r = Z3_probe_le(p1.ctx(), p1, p2); p1.check_error(); return probe(p1.ctx(), r);
|
||||
}
|
||||
friend probe operator<=(probe const & p1, double p2) { return p1 <= probe(p1.ctx(), p2); }
|
||||
friend probe operator<=(double p1, probe const & p2) { return probe(p2.ctx(), p1) <= p2; }
|
||||
friend probe operator>=(probe const & p1, probe const & p2) {
|
||||
check_context(p1, p2); Z3_probe r = Z3_probe_ge(p1.ctx(), p1, p2); p1.check_error(); return probe(p1.ctx(), r);
|
||||
friend probe operator>=(probe const & p1, probe const & p2) {
|
||||
check_context(p1, p2); Z3_probe r = Z3_probe_ge(p1.ctx(), p1, p2); p1.check_error(); return probe(p1.ctx(), r);
|
||||
}
|
||||
friend probe operator>=(probe const & p1, double p2) { return p1 >= probe(p1.ctx(), p2); }
|
||||
friend probe operator>=(double p1, probe const & p2) { return probe(p2.ctx(), p1) >= p2; }
|
||||
friend probe operator<(probe const & p1, probe const & p2) {
|
||||
check_context(p1, p2); Z3_probe r = Z3_probe_lt(p1.ctx(), p1, p2); p1.check_error(); return probe(p1.ctx(), r);
|
||||
friend probe operator<(probe const & p1, probe const & p2) {
|
||||
check_context(p1, p2); Z3_probe r = Z3_probe_lt(p1.ctx(), p1, p2); p1.check_error(); return probe(p1.ctx(), r);
|
||||
}
|
||||
friend probe operator<(probe const & p1, double p2) { return p1 < probe(p1.ctx(), p2); }
|
||||
friend probe operator<(double p1, probe const & p2) { return probe(p2.ctx(), p1) < p2; }
|
||||
friend probe operator>(probe const & p1, probe const & p2) {
|
||||
check_context(p1, p2); Z3_probe r = Z3_probe_gt(p1.ctx(), p1, p2); p1.check_error(); return probe(p1.ctx(), r);
|
||||
friend probe operator>(probe const & p1, probe const & p2) {
|
||||
check_context(p1, p2); Z3_probe r = Z3_probe_gt(p1.ctx(), p1, p2); p1.check_error(); return probe(p1.ctx(), r);
|
||||
}
|
||||
friend probe operator>(probe const & p1, double p2) { return p1 > probe(p1.ctx(), p2); }
|
||||
friend probe operator>(double p1, probe const & p2) { return probe(p2.ctx(), p1) > p2; }
|
||||
friend probe operator==(probe const & p1, probe const & p2) {
|
||||
check_context(p1, p2); Z3_probe r = Z3_probe_eq(p1.ctx(), p1, p2); p1.check_error(); return probe(p1.ctx(), r);
|
||||
friend probe operator==(probe const & p1, probe const & p2) {
|
||||
check_context(p1, p2); Z3_probe r = Z3_probe_eq(p1.ctx(), p1, p2); p1.check_error(); return probe(p1.ctx(), r);
|
||||
}
|
||||
friend probe operator==(probe const & p1, double p2) { return p1 == probe(p1.ctx(), p2); }
|
||||
friend probe operator==(double p1, probe const & p2) { return probe(p2.ctx(), p1) == p2; }
|
||||
friend probe operator&&(probe const & p1, probe const & p2) {
|
||||
check_context(p1, p2); Z3_probe r = Z3_probe_and(p1.ctx(), p1, p2); p1.check_error(); return probe(p1.ctx(), r);
|
||||
friend probe operator&&(probe const & p1, probe const & p2) {
|
||||
check_context(p1, p2); Z3_probe r = Z3_probe_and(p1.ctx(), p1, p2); p1.check_error(); return probe(p1.ctx(), r);
|
||||
}
|
||||
friend probe operator||(probe const & p1, probe const & p2) {
|
||||
check_context(p1, p2); Z3_probe r = Z3_probe_or(p1.ctx(), p1, p2); p1.check_error(); return probe(p1.ctx(), r);
|
||||
friend probe operator||(probe const & p1, probe const & p2) {
|
||||
check_context(p1, p2); Z3_probe r = Z3_probe_or(p1.ctx(), p1, p2); p1.check_error(); return probe(p1.ctx(), r);
|
||||
}
|
||||
friend probe operator!(probe const & p) {
|
||||
Z3_probe r = Z3_probe_not(p.ctx(), p); p.check_error(); return probe(p.ctx(), r);
|
||||
Z3_probe r = Z3_probe_not(p.ctx(), p); p.check_error(); return probe(p.ctx(), r);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1159,15 +1158,15 @@ namespace Duality {
|
|||
inline symbol context::int_symbol(int n) { ::symbol r = ::symbol(n); return symbol(*this, r); }
|
||||
|
||||
inline sort context::bool_sort() {
|
||||
::sort *s = m().mk_sort(m_basic_fid, BOOL_SORT);
|
||||
::sort *s = m().mk_sort(m_basic_fid, BOOL_SORT);
|
||||
return sort(*this, s);
|
||||
}
|
||||
inline sort context::int_sort() {
|
||||
::sort *s = m().mk_sort(m_arith_fid, INT_SORT);
|
||||
::sort *s = m().mk_sort(m_arith_fid, INT_SORT);
|
||||
return sort(*this, s);
|
||||
}
|
||||
inline sort context::real_sort() {
|
||||
::sort *s = m().mk_sort(m_arith_fid, REAL_SORT);
|
||||
::sort *s = m().mk_sort(m_arith_fid, REAL_SORT);
|
||||
return sort(*this, s);
|
||||
}
|
||||
inline sort context::array_sort(sort d, sort r) {
|
||||
|
@ -1188,7 +1187,7 @@ namespace Duality {
|
|||
inline func_decl context::function(char const * name, unsigned arity, sort const * domain, sort const & range) {
|
||||
return function(str_symbol(name), arity, domain, range);
|
||||
}
|
||||
|
||||
|
||||
inline func_decl context::function(char const * name, sort const & domain, sort const & range) {
|
||||
sort args[1] = { domain };
|
||||
return function(name, 1, args, range);
|
||||
|
@ -1196,7 +1195,7 @@ namespace Duality {
|
|||
|
||||
inline func_decl context::function(char const * name, sort const & d1, sort const & d2, sort const & range) {
|
||||
sort args[2] = { d1, d2 };
|
||||
return function(name, 2, args, range);
|
||||
return function(name, 2, args, range);
|
||||
}
|
||||
|
||||
inline func_decl context::function(char const * name, sort const & d1, sort const & d2, sort const & d3, sort const & range) {
|
||||
|
@ -1208,7 +1207,7 @@ namespace Duality {
|
|||
sort args[4] = { d1, d2, d3, d4 };
|
||||
return function(name, 4, args, range);
|
||||
}
|
||||
|
||||
|
||||
inline func_decl context::function(char const * name, sort const & d1, sort const & d2, sort const & d3, sort const & d4, sort const & d5, sort const & range) {
|
||||
sort args[5] = { d1, d2, d3, d4, d5 };
|
||||
return function(name, 5, args, range);
|
||||
|
@ -1217,7 +1216,7 @@ namespace Duality {
|
|||
|
||||
inline expr context::constant(symbol const & name, sort const & s) {
|
||||
::expr *r = m().mk_const(m().mk_const_decl(name, s));
|
||||
return expr(*this, r);
|
||||
return expr(*this, r);
|
||||
}
|
||||
inline expr context::constant(char const * name, sort const & s) { return constant(str_symbol(name), s); }
|
||||
inline expr context::bool_const(char const * name) { return constant(name, bool_sort()); }
|
||||
|
@ -1250,11 +1249,11 @@ namespace Duality {
|
|||
expr args[5] = {a1,a2,a3,a4,a5};
|
||||
return operator()(5,args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
inline expr select(expr const & a, expr const & i) { return a.ctx().make(Select,a,i); }
|
||||
inline expr store(expr const & a, expr const & i, expr const & v) { return a.ctx().make(Store,a,i,v); }
|
||||
|
||||
|
||||
inline expr forall(const std::vector<expr> &quants, const expr &body){
|
||||
return body.ctx().make_quant(Forall,quants,body);
|
||||
}
|
||||
|
@ -1304,7 +1303,7 @@ namespace Duality {
|
|||
}
|
||||
|
||||
inline void setTerm(expr t){term = t;}
|
||||
|
||||
|
||||
inline void addTerm(expr t){terms.push_back(t);}
|
||||
|
||||
inline void setChildren(const std::vector<TermTree *> & _children){
|
||||
|
@ -1326,7 +1325,7 @@ namespace Duality {
|
|||
std::vector<TermTree *> children;
|
||||
int num;
|
||||
};
|
||||
|
||||
|
||||
typedef context interpolating_context;
|
||||
|
||||
class interpolating_solver : public solver {
|
||||
|
@ -1336,7 +1335,7 @@ namespace Duality {
|
|||
{
|
||||
weak_mode = false;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
lbool interpolate(const std::vector<expr> &assumptions,
|
||||
std::vector<expr> &interpolants,
|
||||
|
@ -1344,41 +1343,41 @@ namespace Duality {
|
|||
literals &lits,
|
||||
bool incremental
|
||||
);
|
||||
|
||||
|
||||
lbool interpolate_tree(TermTree *assumptions,
|
||||
TermTree *&interpolants,
|
||||
model &_model,
|
||||
literals &lits,
|
||||
bool incremental
|
||||
);
|
||||
|
||||
|
||||
bool read_interpolation_problem(const std::string &file_name,
|
||||
std::vector<expr> &assumptions,
|
||||
std::vector<expr> &theory,
|
||||
std::string &error_message
|
||||
);
|
||||
|
||||
|
||||
void write_interpolation_problem(const std::string &file_name,
|
||||
const std::vector<expr> &assumptions,
|
||||
const std::vector<expr> &theory
|
||||
);
|
||||
|
||||
|
||||
void AssertInterpolationAxiom(const expr &expr);
|
||||
void RemoveInterpolationAxiom(const expr &expr);
|
||||
|
||||
|
||||
void SetWeakInterpolants(bool weak);
|
||||
void SetPrintToFile(const std::string &file_name);
|
||||
|
||||
|
||||
const std::vector<expr> &GetInterpolationAxioms() {return theory;}
|
||||
const char *profile();
|
||||
|
||||
|
||||
private:
|
||||
bool weak_mode;
|
||||
std::string print_filename;
|
||||
std::vector<expr> theory;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
inline expr context::cook(::expr *a) {return expr(*this,a);}
|
||||
|
||||
inline std::vector<expr> context::cook(ptr_vector< ::expr> v) {
|
||||
|
|
|
@ -66,35 +66,35 @@ class iz3base : public iz3mgr, public scopes {
|
|||
|
||||
/** Constructor */
|
||||
|
||||
iz3base(ast_manager &_m_manager,
|
||||
const std::vector<ast> &_cnsts,
|
||||
const std::vector<int> &_parents,
|
||||
const std::vector<ast> &_theory)
|
||||
: iz3mgr(_m_manager), scopes(_parents) {
|
||||
iz3base(ast_manager &_m_manager,
|
||||
const std::vector<ast> &_cnsts,
|
||||
const std::vector<int> &_parents,
|
||||
const std::vector<ast> &_theory)
|
||||
: iz3mgr(_m_manager), scopes(_parents) {
|
||||
initialize(_cnsts,_parents,_theory);
|
||||
weak = false;
|
||||
}
|
||||
|
||||
iz3base(const iz3mgr& other,
|
||||
const std::vector<ast> &_cnsts,
|
||||
const std::vector<int> &_parents,
|
||||
const std::vector<ast> &_theory)
|
||||
: iz3mgr(other), scopes(_parents) {
|
||||
iz3base(const iz3mgr& other,
|
||||
const std::vector<ast> &_cnsts,
|
||||
const std::vector<int> &_parents,
|
||||
const std::vector<ast> &_theory)
|
||||
: iz3mgr(other), scopes(_parents) {
|
||||
initialize(_cnsts,_parents,_theory);
|
||||
weak = false;
|
||||
}
|
||||
|
||||
iz3base(const iz3mgr& other,
|
||||
const std::vector<std::vector<ast> > &_cnsts,
|
||||
const std::vector<int> &_parents,
|
||||
const std::vector<ast> &_theory)
|
||||
: iz3mgr(other), scopes(_parents) {
|
||||
iz3base(const iz3mgr& other,
|
||||
const std::vector<std::vector<ast> > &_cnsts,
|
||||
const std::vector<int> &_parents,
|
||||
const std::vector<ast> &_theory)
|
||||
: iz3mgr(other), scopes(_parents) {
|
||||
initialize(_cnsts,_parents,_theory);
|
||||
weak = false;
|
||||
}
|
||||
|
||||
iz3base(const iz3mgr& other)
|
||||
: iz3mgr(other), scopes() {
|
||||
iz3base(const iz3mgr& other)
|
||||
: iz3mgr(other), scopes() {
|
||||
weak = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,26 +24,26 @@
|
|||
#include "solver/solver.h"
|
||||
|
||||
bool iz3check(ast_manager &_m_manager,
|
||||
solver *s,
|
||||
std::ostream &err,
|
||||
const ptr_vector<ast> &cnsts,
|
||||
const ::vector<int> &parents,
|
||||
const ptr_vector<ast> &interps,
|
||||
const ptr_vector<ast> &theory);
|
||||
solver *s,
|
||||
std::ostream &err,
|
||||
const ptr_vector<ast> &cnsts,
|
||||
const ::vector<int> &parents,
|
||||
const ptr_vector<ast> &interps,
|
||||
const ptr_vector<ast> &theory);
|
||||
|
||||
bool iz3check(ast_manager &_m_manager,
|
||||
solver *s,
|
||||
std::ostream &err,
|
||||
const ptr_vector<ast> &cnsts,
|
||||
ast *tree,
|
||||
const ptr_vector<ast> &interps);
|
||||
solver *s,
|
||||
std::ostream &err,
|
||||
const ptr_vector<ast> &cnsts,
|
||||
ast *tree,
|
||||
const ptr_vector<ast> &interps);
|
||||
|
||||
bool iz3check(iz3mgr &mgr,
|
||||
solver *s,
|
||||
std::ostream &err,
|
||||
const std::vector<iz3mgr::ast> &cnsts,
|
||||
const std::vector<int> &parents,
|
||||
const std::vector<iz3mgr::ast> &interps,
|
||||
const ptr_vector<iz3mgr::ast> &theory);
|
||||
solver *s,
|
||||
std::ostream &err,
|
||||
const std::vector<iz3mgr::ast> &cnsts,
|
||||
const std::vector<int> &parents,
|
||||
const std::vector<iz3mgr::ast> &interps,
|
||||
const ptr_vector<iz3mgr::ast> &theory);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -468,10 +468,10 @@ namespace hash_space {
|
|||
: hashtable<std::pair<Key,Value>,Key,HashFun,proj1<Key,Value>,EqFun>(7) {}
|
||||
|
||||
Value &operator[](const Key& key) {
|
||||
std::pair<Key,Value> kvp(key,Value());
|
||||
return
|
||||
hashtable<std::pair<Key,Value>,Key,HashFun,proj1<Key,Value>,EqFun>::
|
||||
lookup(kvp,true)->val.second;
|
||||
std::pair<Key,Value> kvp(key,Value());
|
||||
return
|
||||
hashtable<std::pair<Key,Value>,Key,HashFun,proj1<Key,Value>,EqFun>::
|
||||
lookup(kvp,true)->val.second;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -73,22 +73,22 @@ typedef interpolation_options_struct *interpolation_options;
|
|||
representation, for compatibility with the old API. */
|
||||
|
||||
void iz3interpolate(ast_manager &_m_manager,
|
||||
ast *proof,
|
||||
const ptr_vector<ast> &cnsts,
|
||||
const ::vector<int> &parents,
|
||||
ptr_vector<ast> &interps,
|
||||
const ptr_vector<ast> &theory,
|
||||
interpolation_options_struct * options = 0);
|
||||
ast *proof,
|
||||
const ptr_vector<ast> &cnsts,
|
||||
const ::vector<int> &parents,
|
||||
ptr_vector<ast> &interps,
|
||||
const ptr_vector<ast> &theory,
|
||||
interpolation_options_struct * options = 0);
|
||||
|
||||
/* Same as above, but each constraint is a vector of formulas. */
|
||||
|
||||
void iz3interpolate(ast_manager &_m_manager,
|
||||
ast *proof,
|
||||
const vector<ptr_vector<ast> > &cnsts,
|
||||
const ::vector<int> &parents,
|
||||
ptr_vector<ast> &interps,
|
||||
const ptr_vector<ast> &theory,
|
||||
interpolation_options_struct * options = 0);
|
||||
ast *proof,
|
||||
const vector<ptr_vector<ast> > &cnsts,
|
||||
const ::vector<int> &parents,
|
||||
ptr_vector<ast> &interps,
|
||||
const ptr_vector<ast> &theory,
|
||||
interpolation_options_struct * options = 0);
|
||||
|
||||
/* Compute an interpolant from a proof. This version uses the ast
|
||||
representation, for compatibility with the new API. Here, cnsts is
|
||||
|
@ -98,11 +98,11 @@ void iz3interpolate(ast_manager &_m_manager,
|
|||
proof, so it can be considered a hint. */
|
||||
|
||||
void iz3interpolate(ast_manager &_m_manager,
|
||||
ast *proof,
|
||||
const ptr_vector<ast> &cnsts,
|
||||
ast *tree,
|
||||
ptr_vector<ast> &interps,
|
||||
interpolation_options_struct * options);
|
||||
ast *proof,
|
||||
const ptr_vector<ast> &cnsts,
|
||||
ast *tree,
|
||||
ptr_vector<ast> &interps,
|
||||
interpolation_options_struct * options);
|
||||
|
||||
|
||||
/* Compute an interpolant from an ast representing an interpolation
|
||||
|
@ -112,12 +112,12 @@ void iz3interpolate(ast_manager &_m_manager,
|
|||
*/
|
||||
|
||||
lbool iz3interpolate(ast_manager &_m_manager,
|
||||
solver &s,
|
||||
ast *tree,
|
||||
ptr_vector<ast> &cnsts,
|
||||
ptr_vector<ast> &interps,
|
||||
model_ref &m,
|
||||
interpolation_options_struct * options);
|
||||
solver &s,
|
||||
ast *tree,
|
||||
ptr_vector<ast> &cnsts,
|
||||
ptr_vector<ast> &interps,
|
||||
model_ref &m,
|
||||
interpolation_options_struct * options);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,7 +30,7 @@ struct iz3pp_bad_tree: public iz3_exception {
|
|||
};
|
||||
|
||||
void iz3pp(ast_manager &m,
|
||||
const ptr_vector<expr> &cnsts_vec,
|
||||
expr *tree,
|
||||
std::ostream& out);
|
||||
const ptr_vector<expr> &cnsts_vec,
|
||||
expr *tree,
|
||||
std::ostream& out);
|
||||
#endif
|
||||
|
|
|
@ -105,7 +105,7 @@ class scopes {
|
|||
|
||||
void range_add(int i, range &n){
|
||||
#if 0
|
||||
if(i < n.lo) n.lo = i;
|
||||
if(i < n.lo) n.lo = i;
|
||||
if(i > n.hi) n.hi = i;
|
||||
#else
|
||||
range rng; rng.lo = i; rng.hi = i;
|
||||
|
@ -119,7 +119,7 @@ class scopes {
|
|||
int thing = tree_lca(rng1.lo,rng2.hi);
|
||||
if(thing == rng1.lo) frame = rng1.lo;
|
||||
else frame = tree_gcd(thing,rng1.hi);
|
||||
return frame;
|
||||
return frame;
|
||||
}
|
||||
#else
|
||||
|
||||
|
|
|
@ -47,9 +47,9 @@ class iz3translation : public iz3base {
|
|||
|
||||
protected:
|
||||
iz3translation(iz3mgr &mgr,
|
||||
const std::vector<std::vector<ast> > &_cnsts,
|
||||
const std::vector<int> &_parents,
|
||||
const std::vector<ast> &_theory)
|
||||
const std::vector<std::vector<ast> > &_cnsts,
|
||||
const std::vector<int> &_parents,
|
||||
const std::vector<ast> &_theory)
|
||||
: iz3base(mgr,_cnsts,_parents,_theory) {}
|
||||
};
|
||||
|
||||
|
|
|
@ -478,7 +478,7 @@ public:
|
|||
unsigned out_degree(unsigned state) const { return m_delta[state].size(); }
|
||||
move const& get_move_from(unsigned state) const { SASSERT(m_delta[state].size() == 1); return m_delta[state][0]; }
|
||||
move const& get_move_to(unsigned state) const { SASSERT(m_delta_inv[state].size() == 1); return m_delta_inv[state][0]; }
|
||||
moves const& get_moves_from(unsigned state) const { return m_delta[state]; }
|
||||
moves const& get_moves_from(unsigned state) const { return m_delta[state]; }
|
||||
moves const& get_moves_to(unsigned state) const { return m_delta_inv[state]; }
|
||||
bool initial_state_is_source() const { return m_delta_inv[m_init].empty(); }
|
||||
bool is_final_state(unsigned s) const { return m_final_set.contains(s); }
|
||||
|
|
|
@ -40,9 +40,7 @@ template<class T>
|
|||
class boolean_algebra : public positive_boolean_algebra<T> {
|
||||
public:
|
||||
virtual ~boolean_algebra() {}
|
||||
virtual T mk_not(T x) = 0;
|
||||
//virtual lbool are_equivalent(T x, T y) = 0;
|
||||
//virtual T simplify(T x) = 0;
|
||||
virtual T mk_not(T x) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -451,7 +451,15 @@ typename symbolic_automata<T, M>::automaton_t* symbolic_automata<T, M>::mk_produ
|
|||
}
|
||||
}
|
||||
if (mvs1.empty()) {
|
||||
return alloc(automaton_t, m);
|
||||
if (a.is_final_state(a.init()) && b.is_final_state(b.init())) {
|
||||
// special case: automaton has no moves, but the initial state is final on both sides
|
||||
// this results in the automaton which accepts the empty sequence and nothing else
|
||||
final.clear();
|
||||
final.push_back(0);
|
||||
return alloc(automaton_t, m, 0, final, mvs1);
|
||||
} else {
|
||||
return alloc(automaton_t, m);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return alloc(automaton_t, m, 0, final, mvs1);
|
||||
|
|
|
@ -63,8 +63,8 @@ namespace polynomial {
|
|||
public:
|
||||
void set_degree(var x, unsigned d) { m_var2degree.setx(x, d, 0); }
|
||||
unsigned degree(var x) const { return m_var2degree.get(x, 0); }
|
||||
void display(std::ostream & out) const;
|
||||
friend std::ostream & operator<<(std::ostream & out, var2degree const & ideal) { ideal.display(out); return out; }
|
||||
void display(std::ostream & out) const;
|
||||
friend std::ostream & operator<<(std::ostream & out, var2degree const & ideal) { ideal.display(out); return out; }
|
||||
};
|
||||
|
||||
template<typename ValManager, typename Value = typename ValManager::numeral>
|
||||
|
|
|
@ -434,11 +434,11 @@ namespace upolynomial {
|
|||
m().reset(r[i]);
|
||||
}
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
typename polynomial::monomial * mon = pm.get_monomial(p, i);
|
||||
if (pm.size(mon) == 0) {
|
||||
typename polynomial::monomial * mon = pm.get_monomial(p, i);
|
||||
if (pm.size(mon) == 0) {
|
||||
m().set(r[0], pm.coeff(p, i));
|
||||
} else if (pm.size(mon) == 1 && pm.get_var(mon, 0) == x) {
|
||||
unsigned m_deg_x = pm.degree(mon, 0);
|
||||
} else if (pm.size(mon) == 1 && pm.get_var(mon, 0) == x) {
|
||||
unsigned m_deg_x = pm.degree(mon, 0);
|
||||
m().set(r[m_deg_x], pm.coeff(p, i));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,7 +140,6 @@ void func_interp::set_else(expr * e) {
|
|||
return;
|
||||
|
||||
reset_interp_cache();
|
||||
|
||||
ptr_vector<expr> args;
|
||||
while (e && is_fi_entry_expr(e, args)) {
|
||||
TRACE("func_interp", tout << "fi entry expr: " << mk_ismt2_pp(e, m()) << std::endl;);
|
||||
|
|
|
@ -86,13 +86,13 @@ void model_core::register_decl(func_decl * d, func_interp * fi) {
|
|||
void model_core::unregister_decl(func_decl * d) {
|
||||
decl2expr::obj_map_entry * ec = m_interp.find_core(d);
|
||||
if (ec && ec->get_data().m_value != 0) {
|
||||
m_manager.dec_ref(ec->get_data().m_key);
|
||||
m_manager.dec_ref(ec->get_data().m_value);
|
||||
m_manager.dec_ref(ec->get_data().m_key);
|
||||
m_manager.dec_ref(ec->get_data().m_value);
|
||||
m_interp.remove(d);
|
||||
m_const_decls.erase(d);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
decl2finterp::obj_map_entry * ef = m_finterp.find_core(d);
|
||||
if (ef && ef->get_data().m_value != 0) {
|
||||
m_manager.dec_ref(ef->get_data().m_key);
|
||||
|
|
|
@ -33,9 +33,11 @@ Revision History:
|
|||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "model/model_smt2_pp.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
|
||||
|
||||
struct evaluator_cfg : public default_rewriter_cfg {
|
||||
ast_manager & m;
|
||||
model_core & m_model;
|
||||
bool_rewriter m_b_rw;
|
||||
arith_rewriter m_a_rw;
|
||||
|
@ -53,6 +55,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
bool m_array_equalities;
|
||||
|
||||
evaluator_cfg(ast_manager & m, model_core & md, params_ref const & p):
|
||||
m(m),
|
||||
m_model(md),
|
||||
m_b_rw(m),
|
||||
// We must allow customers to set parameters for arithmetic rewriter/evaluator.
|
||||
|
@ -74,6 +77,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
m_ar_rw.set_expand_select_store(true);
|
||||
m_ar_rw.set_expand_select_ite(true);
|
||||
updt_params(p);
|
||||
//add_unspecified_function_models(md);
|
||||
}
|
||||
|
||||
void updt_params(params_ref const & _p) {
|
||||
|
@ -85,10 +89,8 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
m_array_equalities = p.array_equalities();
|
||||
}
|
||||
|
||||
ast_manager & m() const { return m_model.get_manager(); }
|
||||
|
||||
bool evaluate(func_decl* f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
func_interp* fi = m_model.get_func_interp(f);
|
||||
bool evaluate(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
func_interp * fi = m_model.get_func_interp(f);
|
||||
return (fi != 0) && eval_fi(fi, num, args, result);
|
||||
}
|
||||
|
||||
|
@ -101,9 +103,8 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
|
||||
bool actuals_are_values = true;
|
||||
|
||||
for (unsigned i = 0; actuals_are_values && i < num; i++) {
|
||||
actuals_are_values = m().is_value(args[i]);
|
||||
}
|
||||
for (unsigned i = 0; actuals_are_values && i < num; i++)
|
||||
actuals_are_values = m.is_value(args[i]);
|
||||
|
||||
if (!actuals_are_values)
|
||||
return false; // let get_macro handle it
|
||||
|
@ -120,7 +121,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
||||
result_pr = 0;
|
||||
family_id fid = f->get_family_id();
|
||||
bool is_uninterp = fid != null_family_id && m().get_plugin(fid)->is_considered_uninterpreted(f);
|
||||
bool is_uninterp = fid != null_family_id && m.get_plugin(fid)->is_considered_uninterpreted(f);
|
||||
if (num == 0 && (fid == null_family_id || is_uninterp)) {
|
||||
expr * val = m_model.get_const_interp(f);
|
||||
if (val != 0) {
|
||||
|
@ -145,7 +146,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
if (k == OP_EQ) {
|
||||
// theory dispatch for =
|
||||
SASSERT(num == 2);
|
||||
family_id s_fid = m().get_sort(args[0])->get_family_id();
|
||||
family_id s_fid = m.get_sort(args[0])->get_family_id();
|
||||
if (s_fid == m_a_rw.get_fid())
|
||||
st = m_a_rw.mk_eq_core(args[0], args[1], result);
|
||||
else if (s_fid == m_bv_rw.get_fid())
|
||||
|
@ -178,16 +179,18 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
st = m_f_rw.mk_app_core(f, num, args, result);
|
||||
else if (fid == m_seq_rw.get_fid())
|
||||
st = m_seq_rw.mk_app_core(f, num, args, result);
|
||||
else if (fid == m().get_label_family_id() && num == 1) {
|
||||
else if (fid == m.get_label_family_id() && num == 1) {
|
||||
result = args[0];
|
||||
st = BR_DONE;
|
||||
}
|
||||
else if (evaluate(f, num, args, result)) {
|
||||
TRACE("model_evaluator", tout << "reduce_app " << f->get_name() << "\n";
|
||||
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << "\n";
|
||||
tout << "---->\n" << mk_ismt2_pp(result, m()) << "\n";);
|
||||
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m) << "\n";
|
||||
tout << "---->\n" << mk_ismt2_pp(result, m) << "\n";);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (st == BR_FAILED && !m.is_builtin_family_id(fid))
|
||||
st = evaluate_partial_theory_func(f, num, args, result, result_pr);
|
||||
if (st == BR_DONE && is_app(result)) {
|
||||
app* a = to_app(result);
|
||||
if (evaluate(a->get_decl(), a->get_num_args(), a->get_args(), result)) {
|
||||
|
@ -200,14 +203,14 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
|
||||
void expand_value(expr_ref& val) {
|
||||
vector<expr_ref_vector> stores;
|
||||
expr_ref else_case(m());
|
||||
expr_ref else_case(m);
|
||||
bool _unused;
|
||||
if (m_ar.is_array(val) && extract_array_func_interp(val, stores, else_case, _unused)) {
|
||||
sort* srt = m().get_sort(val);
|
||||
sort* srt = m.get_sort(val);
|
||||
val = m_ar.mk_const_array(srt, else_case);
|
||||
for (unsigned i = stores.size(); i > 0; ) {
|
||||
--i;
|
||||
expr_ref_vector args(m());
|
||||
expr_ref_vector args(m);
|
||||
args.push_back(val);
|
||||
args.append(stores[i].size(), stores[i].c_ptr());
|
||||
val = m_ar.mk_store(args.size(), args.c_ptr());
|
||||
|
@ -220,6 +223,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
#define TRACE_MACRO TRACE("model_evaluator", tout << "get_macro for " << f->get_name() << " (model completion: " << m_model_completion << ")\n";);
|
||||
|
||||
func_interp * fi = m_model.get_func_interp(f);
|
||||
|
||||
if (fi != 0) {
|
||||
TRACE_MACRO;
|
||||
if (fi->is_partial()) {
|
||||
|
@ -228,31 +232,52 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
expr * val = m_model.get_some_value(s);
|
||||
fi->set_else(val);
|
||||
}
|
||||
else {
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
def = fi->get_interp();
|
||||
def = fi->get_interp();
|
||||
SASSERT(def != 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_model_completion &&
|
||||
(f->get_family_id() == null_family_id ||
|
||||
m().get_plugin(f->get_family_id())->is_considered_uninterpreted(f)))
|
||||
m.get_plugin(f->get_family_id())->is_considered_uninterpreted(f)))
|
||||
{
|
||||
TRACE_MACRO;
|
||||
sort * s = f->get_range();
|
||||
expr * val = m_model.get_some_value(s);
|
||||
func_interp * new_fi = alloc(func_interp, m(), f->get_arity());
|
||||
func_interp * new_fi = alloc(func_interp, m, f->get_arity());
|
||||
new_fi->set_else(val);
|
||||
m_model.register_decl(f, new_fi);
|
||||
def = val;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
br_status evaluate_partial_theory_func(func_decl * f,
|
||||
unsigned num, expr * const * args,
|
||||
expr_ref & result, proof_ref & result_pr) {
|
||||
SASSERT(f != 0);
|
||||
SASSERT(!m.is_builtin_family_id(f->get_family_id()));
|
||||
result = 0;
|
||||
result_pr = 0;
|
||||
|
||||
func_interp * fi = m_model.get_func_interp(f);
|
||||
if (fi) {
|
||||
if (fi->is_partial())
|
||||
fi->set_else(m.get_some_value(f->get_range()));
|
||||
|
||||
var_subst vs(m, false);
|
||||
vs(fi->get_interp(), num, args, result);
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
|
||||
bool max_steps_exceeded(unsigned num_steps) const {
|
||||
cooperate("model evaluator");
|
||||
|
@ -266,7 +291,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
|
||||
br_status mk_array_eq(expr* a, expr* b, expr_ref& result) {
|
||||
if (a == b) {
|
||||
result = m().mk_true();
|
||||
result = m.mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
if (!m_array_equalities) {
|
||||
|
@ -275,19 +300,19 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
|
||||
vector<expr_ref_vector> stores1, stores2;
|
||||
bool args_are_unique1, args_are_unique2;
|
||||
expr_ref else1(m()), else2(m());
|
||||
expr_ref else1(m), else2(m);
|
||||
if (extract_array_func_interp(a, stores1, else1, args_are_unique1) &&
|
||||
extract_array_func_interp(b, stores2, else2, args_are_unique2)) {
|
||||
expr_ref_vector conj(m()), args1(m()), args2(m());
|
||||
if (m().are_equal(else1, else2)) {
|
||||
expr_ref_vector conj(m), args1(m), args2(m);
|
||||
if (m.are_equal(else1, else2)) {
|
||||
// no op
|
||||
}
|
||||
else if (m().are_distinct(else1, else2) && !(m().get_sort(else1)->get_info()->get_num_elements().is_finite())) {
|
||||
result = m().mk_false();
|
||||
else if (m.are_distinct(else1, else2) && !(m.get_sort(else1)->get_info()->get_num_elements().is_finite())) {
|
||||
result = m.mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
else {
|
||||
conj.push_back(m().mk_eq(else1, else2));
|
||||
conj.push_back(m.mk_eq(else1, else2));
|
||||
}
|
||||
if (args_are_unique1 && args_are_unique2 && !stores1.empty()) {
|
||||
return mk_array_eq_core(stores1, else1, stores2, else2, conj, result);
|
||||
|
@ -300,11 +325,11 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
for (unsigned i = 0; i < stores1.size(); ++i) {
|
||||
args1.resize(1); args1.append(stores1[i].size() - 1, stores1[i].c_ptr());
|
||||
args2.resize(1); args2.append(stores1[i].size() - 1, stores1[i].c_ptr());
|
||||
expr_ref s1(m_ar.mk_select(args1.size(), args1.c_ptr()), m());
|
||||
expr_ref s2(m_ar.mk_select(args2.size(), args2.c_ptr()), m());
|
||||
conj.push_back(m().mk_eq(s1, s2));
|
||||
expr_ref s1(m_ar.mk_select(args1.size(), args1.c_ptr()), m);
|
||||
expr_ref s2(m_ar.mk_select(args2.size(), args2.c_ptr()), m);
|
||||
conj.push_back(m.mk_eq(s1, s2));
|
||||
}
|
||||
result = m().mk_and(conj.size(), conj.c_ptr());
|
||||
result = m.mk_and(conj.size(), conj.c_ptr());
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
return BR_FAILED;
|
||||
|
@ -362,15 +387,15 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
if (table1.find(stores2[i].c_ptr(), args)) {
|
||||
switch (compare(args[arity], val)) {
|
||||
case l_true: table1.remove(args); break;
|
||||
case l_false: result = m().mk_false(); return BR_DONE;
|
||||
default: conj.push_back(m().mk_eq(val, args[arity])); break;
|
||||
case l_false: result = m.mk_false(); return BR_DONE;
|
||||
default: conj.push_back(m.mk_eq(val, args[arity])); break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (compare(else1, val)) {
|
||||
case l_true: break;
|
||||
case l_false: result = m().mk_false(); return BR_DONE;
|
||||
default: conj.push_back(m().mk_eq(else1, val)); break;
|
||||
case l_false: result = m.mk_false(); return BR_DONE;
|
||||
default: conj.push_back(m.mk_eq(else1, val)); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -378,8 +403,8 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
for (; it != end; ++it) {
|
||||
switch (compare((*it)[arity], else2)) {
|
||||
case l_true: break;
|
||||
case l_false: result = m().mk_false(); return BR_DONE;
|
||||
default: conj.push_back(m().mk_eq((*it)[arity], else2)); break;
|
||||
case l_false: result = m.mk_false(); return BR_DONE;
|
||||
default: conj.push_back(m.mk_eq((*it)[arity], else2)); break;
|
||||
}
|
||||
}
|
||||
result = mk_and(conj);
|
||||
|
@ -387,8 +412,8 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
}
|
||||
|
||||
lbool compare(expr* a, expr* b) {
|
||||
if (m().are_equal(a, b)) return l_true;
|
||||
if (m().are_distinct(a, b)) return l_false;
|
||||
if (m.are_equal(a, b)) return l_true;
|
||||
if (m.are_distinct(a, b)) return l_false;
|
||||
return l_undef;
|
||||
}
|
||||
|
||||
|
@ -396,8 +421,8 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
bool args_are_values(expr_ref_vector const& store, bool& are_unique) {
|
||||
bool are_values = true;
|
||||
for (unsigned j = 0; are_values && j + 1 < store.size(); ++j) {
|
||||
are_values = m().is_value(store[j]);
|
||||
are_unique &= m().is_unique_value(store[j]);
|
||||
are_values = m.is_value(store[j]);
|
||||
are_unique &= m.is_unique_value(store[j]);
|
||||
}
|
||||
SASSERT(!are_unique || are_values);
|
||||
return are_values;
|
||||
|
@ -408,10 +433,10 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
SASSERT(m_ar.is_array(a));
|
||||
bool are_values = true;
|
||||
are_unique = true;
|
||||
TRACE("model_evaluator", tout << mk_pp(a, m()) << "\n";);
|
||||
TRACE("model_evaluator", tout << mk_pp(a, m) << "\n";);
|
||||
|
||||
while (m_ar.is_store(a)) {
|
||||
expr_ref_vector store(m());
|
||||
expr_ref_vector store(m);
|
||||
store.append(to_app(a)->get_num_args()-1, to_app(a)->get_args()+1);
|
||||
are_values &= args_are_values(store, are_unique);
|
||||
stores.push_back(store);
|
||||
|
@ -424,7 +449,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
}
|
||||
|
||||
if (!m_ar.is_as_array(a)) {
|
||||
TRACE("model_evaluator", tout << "no translation: " << mk_pp(a, m()) << "\n";);
|
||||
TRACE("model_evaluator", tout << "no translation: " << mk_pp(a, m) << "\n";);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -434,13 +459,13 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
unsigned arity = f->get_arity();
|
||||
unsigned base_sz = stores.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
expr_ref_vector store(m());
|
||||
expr_ref_vector store(m);
|
||||
func_entry const* fe = g->get_entry(i);
|
||||
store.append(arity, fe->get_args());
|
||||
store.push_back(fe->get_result());
|
||||
for (unsigned j = 0; j < store.size(); ++j) {
|
||||
if (!is_ground(store[j].get())) {
|
||||
TRACE("model_evaluator", tout << "could not extract array interpretation: " << mk_pp(a, m()) << "\n" << mk_pp(store[j].get(), m()) << "\n";);
|
||||
TRACE("model_evaluator", tout << "could not extract array interpretation: " << mk_pp(a, m) << "\n" << mk_pp(store[j].get(), m) << "\n";);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -448,18 +473,18 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
}
|
||||
else_case = g->get_else();
|
||||
if (!else_case) {
|
||||
TRACE("model_evaluator", tout << "no else case " << mk_pp(a, m()) << "\n";
|
||||
/*model_smt2_pp(tout, m(), m_model, 0);*/
|
||||
TRACE("model_evaluator", tout << "no else case " << mk_pp(a, m) << "\n";
|
||||
/*model_smt2_pp(tout, m, m_model, 0);*/
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (!is_ground(else_case)) {
|
||||
TRACE("model_evaluator", tout << "non-ground else case " << mk_pp(a, m()) << "\n" << else_case << "\n";);
|
||||
TRACE("model_evaluator", tout << "non-ground else case " << mk_pp(a, m) << "\n" << else_case << "\n";);
|
||||
return false;
|
||||
}
|
||||
for (unsigned i = stores.size(); are_values && i > base_sz; ) {
|
||||
--i;
|
||||
if (m().are_equal(else_case, stores[i].back())) {
|
||||
if (m.are_equal(else_case, stores[i].back())) {
|
||||
for (unsigned j = i + 1; j < stores.size(); ++j) {
|
||||
stores[j-1].reset();
|
||||
stores[j-1].append(stores[j]);
|
||||
|
@ -469,7 +494,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
}
|
||||
are_values &= args_are_values(stores[i], are_unique);
|
||||
}
|
||||
TRACE("model_evaluator", tout << "else case: " << mk_pp(else_case, m()) << "\n";);
|
||||
TRACE("model_evaluator", tout << "else case: " << mk_pp(else_case, m) << "\n";);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace datalog {
|
|||
MEMOUT,
|
||||
INPUT_ERROR,
|
||||
APPROX,
|
||||
BOUNDED,
|
||||
BOUNDED,
|
||||
CANCELED
|
||||
};
|
||||
|
||||
|
@ -318,7 +318,7 @@ namespace datalog {
|
|||
\brief Retrieve predicates
|
||||
*/
|
||||
func_decl_set const& get_predicates() const { return m_preds; }
|
||||
ast_ref_vector const &get_pinned() const {return m_pinned; }
|
||||
ast_ref_vector const &get_pinned() const {return m_pinned; }
|
||||
|
||||
bool is_predicate(func_decl* pred) const { return m_preds.contains(pred); }
|
||||
bool is_predicate(expr * e) const { return is_app(e) && is_predicate(to_app(e)->get_decl()); }
|
||||
|
@ -534,7 +534,7 @@ namespace datalog {
|
|||
\brief retrieve proof from derivation of the query.
|
||||
|
||||
\pre engine == 'pdr' || engine == 'duality'- this option is only supported
|
||||
for PDR mode and Duality mode.
|
||||
for PDR mode and Duality mode.
|
||||
*/
|
||||
proof_ref get_proof();
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace datalog {
|
|||
QBMC_ENGINE,
|
||||
TAB_ENGINE,
|
||||
CLP_ENGINE,
|
||||
DUALITY_ENGINE,
|
||||
DUALITY_ENGINE,
|
||||
DDNF_ENGINE,
|
||||
LAST_ENGINE
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ def_module_params('fixedpoint',
|
|||
params=(('timeout', UINT, UINT_MAX, 'set timeout'),
|
||||
('engine', SYMBOL, 'auto-config',
|
||||
'Select: auto-config, datalog, duality, pdr, bmc, spacer'),
|
||||
('datalog.default_table', SYMBOL, 'sparse',
|
||||
('datalog.default_table', SYMBOL, 'sparse',
|
||||
'default table implementation: sparse, hashtable, bitvector, interval'),
|
||||
('datalog.default_relation', SYMBOL, 'pentagon',
|
||||
'default relation implementation: external_relation, pentagon'),
|
||||
|
@ -56,18 +56,18 @@ def_module_params('fixedpoint',
|
|||
"table columns, if it would have been empty otherwise"),
|
||||
('datalog.subsumption', BOOL, True,
|
||||
"if true, removes/filters predicates with total transitions"),
|
||||
('duality.full_expand', BOOL, False, 'Fully expand derivation trees'),
|
||||
('duality.no_conj', BOOL, False, 'No forced covering (conjectures)'),
|
||||
('duality.feasible_edges', BOOL, True,
|
||||
('duality.full_expand', BOOL, False, 'Fully expand derivation trees'),
|
||||
('duality.no_conj', BOOL, False, 'No forced covering (conjectures)'),
|
||||
('duality.feasible_edges', BOOL, True,
|
||||
'Don\'t expand definitley infeasible edges'),
|
||||
('duality.use_underapprox', BOOL, False, 'Use underapproximations'),
|
||||
('duality.stratified_inlining', BOOL, False, 'Use stratified inlining'),
|
||||
('duality.recursion_bound', UINT, UINT_MAX,
|
||||
('duality.use_underapprox', BOOL, False, 'Use underapproximations'),
|
||||
('duality.stratified_inlining', BOOL, False, 'Use stratified inlining'),
|
||||
('duality.recursion_bound', UINT, UINT_MAX,
|
||||
'Recursion bound for stratified inlining'),
|
||||
('duality.profile', BOOL, False, 'profile run time'),
|
||||
('duality.mbqi', BOOL, True, 'use model-based quantifier instantiation'),
|
||||
('duality.batch_expand', BOOL, False, 'use batch expansion'),
|
||||
('duality.conjecture_file', STRING, '', 'save conjectures to file'),
|
||||
('duality.profile', BOOL, False, 'profile run time'),
|
||||
('duality.mbqi', BOOL, True, 'use model-based quantifier instantiation'),
|
||||
('duality.batch_expand', BOOL, False, 'use batch expansion'),
|
||||
('duality.conjecture_file', STRING, '', 'save conjectures to file'),
|
||||
('pdr.bfs_model_search', BOOL, True,
|
||||
"use BFS strategy for expanding model search"),
|
||||
('pdr.farkas', BOOL, True,
|
||||
|
@ -92,9 +92,9 @@ def_module_params('fixedpoint',
|
|||
"generalize lemmas using induction strengthening"),
|
||||
('pdr.use_arith_inductive_generalizer', BOOL, False,
|
||||
"generalize lemmas using arithmetic heuristics for induction strengthening"),
|
||||
('pdr.use_convex_closure_generalizer', BOOL, False,
|
||||
('pdr.use_convex_closure_generalizer', BOOL, False,
|
||||
"generalize using convex closures of lemmas"),
|
||||
('pdr.use_convex_interior_generalizer', BOOL, False,
|
||||
('pdr.use_convex_interior_generalizer', BOOL, False,
|
||||
"generalize using convex interiors of lemmas"),
|
||||
('pdr.cache_mode', UINT, 0, "use no (0), symbolic (1) or explicit " +
|
||||
"cache (2) for model search"),
|
||||
|
@ -104,7 +104,7 @@ def_module_params('fixedpoint',
|
|||
('pdr.max_num_contexts', UINT, 500, "maximal number of contexts to create"),
|
||||
('pdr.try_minimize_core', BOOL, False,
|
||||
"try to reduce core size (before inductive minimization)"),
|
||||
('pdr.utvpi', BOOL, True, 'Enable UTVPI strategy'),
|
||||
('pdr.utvpi', BOOL, True, 'Enable UTVPI strategy'),
|
||||
('print_fixedpoint_extensions', BOOL, True,
|
||||
"use SMT-LIB2 fixedpoint extensions, instead of pure SMT2, " +
|
||||
"when printing rules"),
|
||||
|
@ -123,7 +123,7 @@ def_module_params('fixedpoint',
|
|||
('print_statistics', BOOL, False, 'print statistics'),
|
||||
('print_aig', SYMBOL, '',
|
||||
'Dump clauses in AIG text format (AAG) to the given file name'),
|
||||
('tab.selection', SYMBOL, 'weight',
|
||||
('tab.selection', SYMBOL, 'weight',
|
||||
'selection method for tabular strategy: weight (default), first, var-use'),
|
||||
('xform.bit_blast', BOOL, False,
|
||||
'bit-blast bit-vectors'),
|
||||
|
@ -140,7 +140,7 @@ def_module_params('fixedpoint',
|
|||
('xform.unfold_rules', UINT, 0,
|
||||
"unfold rules statically using iterative squarring"),
|
||||
('xform.slice', BOOL, True, "simplify clause set using slicing"),
|
||||
('xform.karr', BOOL, False,
|
||||
('xform.karr', BOOL, False,
|
||||
"Add linear invariants to clauses using Karr's method"),
|
||||
('spacer.use_eqclass', BOOL, False, "Generalizes equalities to equivalence classes"),
|
||||
('xform.transform_arrays', BOOL, False,
|
||||
|
@ -153,24 +153,24 @@ def_module_params('fixedpoint',
|
|||
"Gives the number of quantifiers per array"),
|
||||
('xform.instantiate_arrays.slice_technique', SYMBOL, "no-slicing",
|
||||
"<no-slicing>=> GetId(i) = i, <smash> => GetId(i) = true"),
|
||||
('xform.quantify_arrays', BOOL, False,
|
||||
('xform.quantify_arrays', BOOL, False,
|
||||
"create quantified Horn clauses from clauses with arrays"),
|
||||
('xform.instantiate_quantifiers', BOOL, False,
|
||||
('xform.instantiate_quantifiers', BOOL, False,
|
||||
"instantiate quantified Horn clauses using E-matching heuristic"),
|
||||
('xform.coalesce_rules', BOOL, False, "coalesce rules"),
|
||||
('xform.tail_simplifier_pve', BOOL, True, "propagate_variable_equivalences"),
|
||||
('xform.subsumption_checker', BOOL, True, "Enable subsumption checker (no support for model conversion)"),
|
||||
('xform.coi', BOOL, True, "use cone of influence simplificaiton"),
|
||||
('duality.enable_restarts', BOOL, False, 'DUALITY: enable restarts'),
|
||||
('xform.coi', BOOL, True, "use cone of influence simplification"),
|
||||
('duality.enable_restarts', BOOL, False, 'DUALITY: enable restarts'),
|
||||
('spacer.order_children', UINT, 0, 'SPACER: order of enqueuing children in non-linear rules : 0 (original), 1 (reverse)'),
|
||||
('spacer.eager_reach_check', BOOL, True, 'SPACER: eagerly check if a query is reachable using reachability facts of predecessors'),
|
||||
('spacer.use_lemma_as_cti', BOOL, False, 'SPACER: use a lemma instead of a CTI in flexible_trace'),
|
||||
('spacer.reset_obligation_queue', BOOL, True, 'SPACER: reset obligation queue when entering a new level'),
|
||||
('spacer.init_reach_facts', BOOL, True, 'SPACER: initialize reachability facts with false'),
|
||||
('spacer.use_array_eq_generalizer', BOOL, True, 'SPACER: attempt to generalize lemmas with array equalities'),
|
||||
('spacer.use_derivations', BOOL, True, 'SPACER: using derivation mechanism to cache intermediate results for non-linear rules'),
|
||||
('spacer.use_derivations', BOOL, True, 'SPACER: using derivation mechanism to cache intermediate results for non-linear rules'),
|
||||
('xform.array_blast', BOOL, False, "try to eliminate local array terms using Ackermannization -- some array terms may remain"),
|
||||
('xform.array_blast_full', BOOL, False, "eliminate all local array variables by QE"),
|
||||
('xform.array_blast_full', BOOL, False, "eliminate all local array variables by QE"),
|
||||
('spacer.skip_propagate', BOOL, False, "Skip propagate/pushing phase. Turns PDR into a BMC that returns either reachable or unknown"),
|
||||
('spacer.max_level', UINT, UINT_MAX, "Maximum level to explore"),
|
||||
('spacer.elim_aux', BOOL, True, "Eliminate auxiliary variables in reachability facts"),
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace Duality {
|
|||
|
||||
class dl_interface : public datalog::engine_base {
|
||||
duality_data *_d;
|
||||
datalog::context &m_ctx;
|
||||
datalog::context &m_ctx;
|
||||
|
||||
public:
|
||||
dl_interface(datalog::context& ctx);
|
||||
|
@ -69,7 +69,7 @@ namespace Duality {
|
|||
|
||||
proof_ref get_proof();
|
||||
|
||||
duality_data *dd(){return _d;}
|
||||
duality_data *dd(){return _d;}
|
||||
|
||||
private:
|
||||
void display_certificate_non_const(std::ostream& out);
|
||||
|
|
|
@ -88,7 +88,7 @@ namespace pdr {
|
|||
virtual ~core_convex_hull_generalizer() {}
|
||||
virtual void operator()(model_node& n, expr_ref_vector const& core, bool uses_level, cores& new_cores);
|
||||
virtual void operator()(model_node& n, expr_ref_vector& core, bool& uses_level);
|
||||
};
|
||||
};
|
||||
|
||||
class core_multi_generalizer : public core_generalizer {
|
||||
core_bool_inductive_generalizer m_gen;
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace datalog {
|
|||
*/
|
||||
class mk_similarity_compressor : public rule_transformer::plugin {
|
||||
|
||||
context & m_context;
|
||||
context & m_context;
|
||||
ast_manager & m_manager;
|
||||
/** number of similar rules necessary for a group to be introduced */
|
||||
unsigned m_threshold_count;
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace datalog {
|
|||
We say that a rule containing C_i's is a rule with a "big tail".
|
||||
*/
|
||||
class mk_simple_joins : public rule_transformer::plugin {
|
||||
context & m_context;
|
||||
context & m_context;
|
||||
rule_manager & rm;
|
||||
public:
|
||||
mk_simple_joins(context & ctx);
|
||||
|
|
|
@ -1209,7 +1209,7 @@ namespace qe {
|
|||
|
||||
void operator()(model& mdl, app_ref_vector& vars, expr_ref& fml) {
|
||||
expr_map map (m);
|
||||
operator()(mdl, vars, fml, map);
|
||||
operator()(mdl, vars, fml, map);
|
||||
}
|
||||
|
||||
void operator()(model& mdl, app_ref_vector& vars, expr_ref& fml, expr_map& map) {
|
||||
|
|
|
@ -93,7 +93,7 @@ namespace datalog {
|
|||
typedef obj_map<func_decl, adornment> pred_adornment_map;
|
||||
typedef obj_map<func_decl, func_decl *> pred2pred;
|
||||
|
||||
context & m_context;
|
||||
context & m_context;
|
||||
ast_manager & m;
|
||||
rule_manager& rm;
|
||||
ast_ref_vector m_pinned;
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace datalog {
|
|||
typedef hashtable<c_info, c_info_hash, default_eq<c_info> > in_progress_table;
|
||||
typedef svector<c_info> todo_stack;
|
||||
|
||||
context & m_context;
|
||||
context & m_context;
|
||||
ast_manager & m;
|
||||
rule_manager & rm;
|
||||
rule_ref_vector m_rules;
|
||||
|
|
|
@ -96,6 +96,9 @@ public:
|
|||
}
|
||||
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
if (!m_formula) {
|
||||
throw cmd_exception("assert-soft requires a formulas as argument.");
|
||||
}
|
||||
symbol w("weight");
|
||||
rational weight = ps().get_rat(symbol("weight"), rational::one());
|
||||
symbol id = ps().get_sym(symbol("id"), symbol::null);
|
||||
|
|
|
@ -2,7 +2,7 @@ def_module_params('opt',
|
|||
description='optimization parameters',
|
||||
export=True,
|
||||
params=(('optsmt_engine', SYMBOL, 'basic', "select optimization engine: 'basic', 'farkas', 'symba'"),
|
||||
('maxsat_engine', SYMBOL, 'maxres', "select engine for maxsat: 'core_maxsat', 'wmax', 'maxres', 'pd-maxres'"),
|
||||
('maxsat_engine', SYMBOL, 'maxres', "select engine for maxsat: 'core_maxsat', 'wmax', 'maxres', 'pd-maxres'"),
|
||||
('priority', SYMBOL, 'lex', "select how to priortize objectives: 'lex' (lexicographic), 'pareto', or 'box'"),
|
||||
('dump_benchmarks', BOOL, False, 'dump benchmarks for profiling'),
|
||||
('timeout', UINT, UINT_MAX, 'timeout (in milliseconds) (UINT_MAX and 0 mean no timeout)'),
|
||||
|
|
|
@ -24,6 +24,7 @@ Revision History:
|
|||
#include "ast/ast_pp.h"
|
||||
#include "ast/well_sorted.h"
|
||||
#include "ast/rewriter/rewriter.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/has_free_vars.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "parsers/smt2/smt2parser.h"
|
||||
|
@ -68,6 +69,7 @@ namespace smt2 {
|
|||
|
||||
scoped_ptr<bv_util> m_bv_util;
|
||||
scoped_ptr<arith_util> m_arith_util;
|
||||
scoped_ptr<datatype_util> m_datatype_util;
|
||||
scoped_ptr<seq_util> m_seq_util;
|
||||
scoped_ptr<pattern_validator> m_pattern_validator;
|
||||
scoped_ptr<var_shifter> m_var_shifter;
|
||||
|
@ -108,6 +110,7 @@ namespace smt2 {
|
|||
symbol m_check_sat_assuming;
|
||||
symbol m_define_fun_rec;
|
||||
symbol m_define_funs_rec;
|
||||
symbol m_match;
|
||||
symbol m_underscore;
|
||||
|
||||
typedef std::pair<symbol, expr*> named_expr;
|
||||
|
@ -135,7 +138,7 @@ namespace smt2 {
|
|||
|
||||
typedef psort_frame sort_frame;
|
||||
|
||||
enum expr_frame_kind { EF_APP, EF_LET, EF_LET_DECL, EF_QUANT, EF_ATTR_EXPR, EF_PATTERN };
|
||||
enum expr_frame_kind { EF_APP, EF_LET, EF_LET_DECL, EF_MATCH, EF_QUANT, EF_ATTR_EXPR, EF_PATTERN };
|
||||
|
||||
struct expr_frame {
|
||||
expr_frame_kind m_kind;
|
||||
|
@ -172,6 +175,10 @@ namespace smt2 {
|
|||
m_expr_spos(expr_spos) {}
|
||||
};
|
||||
|
||||
struct match_frame : public expr_frame {
|
||||
match_frame():expr_frame(EF_MATCH) {}
|
||||
};
|
||||
|
||||
struct let_frame : public expr_frame {
|
||||
bool m_in_decls;
|
||||
unsigned m_sym_spos;
|
||||
|
@ -275,6 +282,12 @@ namespace smt2 {
|
|||
return *(m_arith_util.get());
|
||||
}
|
||||
|
||||
datatype_util & dtutil() {
|
||||
if (m_datatype_util.get() == 0)
|
||||
m_datatype_util = alloc(datatype_util, m());
|
||||
return *(m_datatype_util.get());
|
||||
}
|
||||
|
||||
seq_util & sutil() {
|
||||
if (m_seq_util.get() == 0)
|
||||
m_seq_util = alloc(seq_util, m());
|
||||
|
@ -389,6 +402,7 @@ namespace smt2 {
|
|||
|
||||
bool curr_id_is_underscore() const { SASSERT(curr_is_identifier()); return curr_id() == m_underscore; }
|
||||
bool curr_id_is_as() const { SASSERT(curr_is_identifier()); return curr_id() == m_as; }
|
||||
bool curr_id_is_match() const { SASSERT(curr_is_identifier()); return curr_id() == m_match; }
|
||||
bool curr_id_is_forall() const { SASSERT(curr_is_identifier()); return curr_id() == m_forall; }
|
||||
bool curr_id_is_exists() const { SASSERT(curr_is_identifier()); return curr_id() == m_exists; }
|
||||
bool curr_id_is_bang() const { SASSERT(curr_is_identifier()); return curr_id() == m_bang; }
|
||||
|
@ -1258,6 +1272,23 @@ namespace smt2 {
|
|||
return num;
|
||||
}
|
||||
|
||||
void push_let_frame() {
|
||||
next();
|
||||
check_lparen_next("invalid let declaration, '(' expected");
|
||||
void * mem = m_stack.allocate(sizeof(let_frame));
|
||||
new (mem) let_frame(symbol_stack().size(), expr_stack().size());
|
||||
m_num_expr_frames++;
|
||||
}
|
||||
|
||||
void push_bang_frame(expr_frame * curr) {
|
||||
TRACE("consume_attributes", tout << "begin bang, expr_stack.size(): " << expr_stack().size() << "\n";);
|
||||
next();
|
||||
void * mem = m_stack.allocate(sizeof(attr_expr_frame));
|
||||
new (mem) attr_expr_frame(curr, symbol_stack().size(), expr_stack().size());
|
||||
m_num_expr_frames++;
|
||||
}
|
||||
|
||||
|
||||
void push_quant_frame(bool is_forall) {
|
||||
SASSERT(curr_is_identifier());
|
||||
SASSERT(curr_id_is_forall() || curr_id_is_exists());
|
||||
|
@ -1273,6 +1304,202 @@ namespace smt2 {
|
|||
throw parser_exception("invalid quantifier, list of sorted variables is empty");
|
||||
}
|
||||
|
||||
/**
|
||||
* SMT-LIB 2.6 pattern matches are of the form
|
||||
* (match t ((p1 t1) ... (pm+1 tm+1)))
|
||||
*/
|
||||
void push_match_frame() {
|
||||
SASSERT(curr_is_identifier());
|
||||
SASSERT(curr_id() == m_match);
|
||||
next();
|
||||
void * mem = m_stack.allocate(sizeof(match_frame));
|
||||
new (mem) match_frame();
|
||||
unsigned num_frames = m_num_expr_frames;
|
||||
|
||||
parse_expr();
|
||||
expr_ref t(expr_stack().back(), m());
|
||||
expr_stack().pop_back();
|
||||
expr_ref_vector patterns(m()), cases(m());
|
||||
sort* srt = m().get_sort(t);
|
||||
|
||||
check_lparen_next("pattern bindings should be enclosed in a parenthesis");
|
||||
while (!curr_is_rparen()) {
|
||||
m_env.begin_scope();
|
||||
unsigned num_bindings = m_num_bindings;
|
||||
check_lparen_next("invalid pattern binding, '(' expected");
|
||||
parse_match_pattern(srt);
|
||||
patterns.push_back(expr_stack().back());
|
||||
expr_stack().pop_back();
|
||||
parse_expr();
|
||||
cases.push_back(expr_stack().back());
|
||||
expr_stack().pop_back();
|
||||
m_num_bindings = num_bindings;
|
||||
m_env.end_scope();
|
||||
check_rparen_next("invalid pattern binding, ')' expected");
|
||||
}
|
||||
next();
|
||||
m_num_expr_frames = num_frames + 1;
|
||||
expr_stack().push_back(compile_patterns(t, patterns, cases));
|
||||
}
|
||||
|
||||
void pop_match_frame(match_frame* fr) {
|
||||
m_stack.deallocate(fr);
|
||||
m_num_expr_frames--;
|
||||
}
|
||||
|
||||
expr_ref compile_patterns(expr* t, expr_ref_vector const& patterns, expr_ref_vector const& cases) {
|
||||
expr_ref result(m());
|
||||
var_subst sub(m(), false);
|
||||
TRACE("parse_expr", tout << "term\n" << expr_ref(t, m()) << "\npatterns\n" << patterns << "\ncases\n" << cases << "\n";);
|
||||
check_patterns(patterns, m().get_sort(t));
|
||||
for (unsigned i = patterns.size(); i > 0; ) {
|
||||
--i;
|
||||
expr_ref_vector subst(m());
|
||||
expr_ref cond = bind_match(t, patterns[i], subst);
|
||||
expr_ref new_case(m());
|
||||
if (subst.empty()) {
|
||||
new_case = cases[i];
|
||||
}
|
||||
else {
|
||||
sub(cases[i], subst.size(), subst.c_ptr(), new_case);
|
||||
inv_var_shifter inv(m());
|
||||
inv(new_case, subst.size(), new_case);
|
||||
}
|
||||
if (result) {
|
||||
result = m().mk_ite(cond, new_case, result);
|
||||
}
|
||||
else {
|
||||
// pattern match binding is ignored.
|
||||
result = new_case;
|
||||
}
|
||||
}
|
||||
TRACE("parse_expr", tout << result << "\n";);
|
||||
return result;
|
||||
}
|
||||
|
||||
void check_patterns(expr_ref_vector const& patterns, sort* s) {
|
||||
if (!dtutil().is_datatype(s))
|
||||
throw parser_exception("pattern matching is only supported for algebraic datatypes");
|
||||
ptr_vector<func_decl> const& cons = *dtutil().get_datatype_constructors(s);
|
||||
for (expr * arg : patterns) if (is_var(arg)) return;
|
||||
if (patterns.size() < cons.size())
|
||||
throw parser_exception("non-exhaustive pattern match");
|
||||
ast_fast_mark1 marked;
|
||||
for (expr * arg : patterns)
|
||||
marked.mark(to_app(arg)->get_decl(), true);
|
||||
for (func_decl * f : cons)
|
||||
if (!marked.is_marked(f))
|
||||
throw parser_exception("a constructor is missing from pattern match");
|
||||
}
|
||||
|
||||
// compute match condition and substitution
|
||||
// t is shifted by size of subst.
|
||||
expr_ref bind_match(expr* t, expr* pattern, expr_ref_vector& subst) {
|
||||
expr_ref tsh(m());
|
||||
if (is_var(pattern)) {
|
||||
shifter()(t, 1, tsh);
|
||||
subst.push_back(tsh);
|
||||
return expr_ref(m().mk_true(), m());
|
||||
}
|
||||
else {
|
||||
SASSERT(is_app(pattern));
|
||||
func_decl * f = to_app(pattern)->get_decl();
|
||||
func_decl * r = dtutil().get_constructor_recognizer(f);
|
||||
ptr_vector<func_decl> const * acc = dtutil().get_constructor_accessors(f);
|
||||
shifter()(t, acc->size(), tsh);
|
||||
for (func_decl* a : *acc) {
|
||||
subst.push_back(m().mk_app(a, tsh));
|
||||
}
|
||||
return expr_ref(m().mk_app(r, t), m());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* parse a match pattern
|
||||
* (C x1 .... xn)
|
||||
* C
|
||||
* _
|
||||
* x
|
||||
*/
|
||||
|
||||
bool parse_constructor_pattern(sort * srt) {
|
||||
if (!curr_is_lparen()) {
|
||||
return false;
|
||||
}
|
||||
next();
|
||||
svector<symbol> vars;
|
||||
expr_ref_vector args(m());
|
||||
symbol C(check_identifier_next("constructor symbol expected"));
|
||||
while (!curr_is_rparen()) {
|
||||
symbol v(check_identifier_next("variable symbol expected"));
|
||||
if (v != m_underscore && vars.contains(v)) {
|
||||
throw parser_exception("unexpected repeated variable in pattern expression");
|
||||
}
|
||||
vars.push_back(v);
|
||||
}
|
||||
next();
|
||||
|
||||
// now have C, vars
|
||||
// look up constructor C,
|
||||
// create bound variables based on constructor type.
|
||||
// store expression in expr_stack().
|
||||
// ensure that bound variables are adjusted to vars
|
||||
|
||||
func_decl* f = m_ctx.find_func_decl(C, 0, nullptr, vars.size(), nullptr, srt);
|
||||
if (!f) {
|
||||
throw parser_exception("expecting a constructor that has been declared");
|
||||
}
|
||||
if (!dtutil().is_constructor(f)) {
|
||||
throw parser_exception("expecting a constructor");
|
||||
}
|
||||
if (f->get_arity() != vars.size()) {
|
||||
throw parser_exception("mismatching number of variables supplied to constructor");
|
||||
}
|
||||
m_num_bindings += vars.size();
|
||||
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||
var * v = m().mk_var(i, f->get_domain(i));
|
||||
args.push_back(v);
|
||||
if (vars[i] != m_underscore) {
|
||||
m_env.insert(vars[i], local(v, m_num_bindings));
|
||||
}
|
||||
}
|
||||
expr_stack().push_back(m().mk_app(f, args.size(), args.c_ptr()));
|
||||
return true;
|
||||
}
|
||||
|
||||
void parse_match_pattern(sort* srt) {
|
||||
if (parse_constructor_pattern(srt)) {
|
||||
// done
|
||||
}
|
||||
else if (curr_id() == m_underscore) {
|
||||
// we have a wild-card.
|
||||
// store dummy variable in expr_stack()
|
||||
next();
|
||||
var* v = m().mk_var(0, srt);
|
||||
expr_stack().push_back(v);
|
||||
}
|
||||
else {
|
||||
symbol xC(check_identifier_next("constructor symbol or variable expected"));
|
||||
// check if xC is a constructor, otherwise make it a variable
|
||||
// of sort srt.
|
||||
try {
|
||||
func_decl* f = m_ctx.find_func_decl(xC, 0, nullptr, 0, nullptr, srt);
|
||||
if (!dtutil().is_constructor(f)) {
|
||||
throw parser_exception("expecting a constructor, got a previously declared function");
|
||||
}
|
||||
if (f->get_arity() > 0) {
|
||||
throw parser_exception("constructor expects arguments, but no arguments were supplied in pattern");
|
||||
}
|
||||
expr_stack().push_back(m().mk_const(f));
|
||||
}
|
||||
catch (cmd_exception &) {
|
||||
var* v = m().mk_var(0, srt);
|
||||
expr_stack().push_back(v);
|
||||
m_env.insert(xC, local(v, m_num_bindings++));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
symbol parse_indexed_identifier_core() {
|
||||
check_underscore_next("invalid indexed identifier, '_' expected");
|
||||
check_identifier("invalid indexed identifier, symbol expected");
|
||||
|
@ -1564,8 +1791,7 @@ namespace smt2 {
|
|||
new (mem) app_frame(f, expr_spos, param_spos, has_as);
|
||||
m_num_expr_frames++;
|
||||
}
|
||||
|
||||
// return true if a new frame was created.
|
||||
|
||||
void push_expr_frame(expr_frame * curr) {
|
||||
SASSERT(curr_is_lparen());
|
||||
next();
|
||||
|
@ -1573,11 +1799,7 @@ namespace smt2 {
|
|||
if (curr_is_identifier()) {
|
||||
TRACE("push_expr_frame", tout << "push_expr_frame(), curr_id(): " << curr_id() << "\n";);
|
||||
if (curr_id_is_let()) {
|
||||
next();
|
||||
check_lparen_next("invalid let declaration, '(' expected");
|
||||
void * mem = m_stack.allocate(sizeof(let_frame));
|
||||
new (mem) let_frame(symbol_stack().size(), expr_stack().size());
|
||||
m_num_expr_frames++;
|
||||
push_let_frame();
|
||||
}
|
||||
else if (curr_id_is_forall()) {
|
||||
push_quant_frame(true);
|
||||
|
@ -1586,19 +1808,17 @@ namespace smt2 {
|
|||
push_quant_frame(false);
|
||||
}
|
||||
else if (curr_id_is_bang()) {
|
||||
TRACE("consume_attributes", tout << "begin bang, expr_stack.size(): " << expr_stack().size() << "\n";);
|
||||
next();
|
||||
void * mem = m_stack.allocate(sizeof(attr_expr_frame));
|
||||
new (mem) attr_expr_frame(curr, symbol_stack().size(), expr_stack().size());
|
||||
m_num_expr_frames++;
|
||||
push_bang_frame(curr);
|
||||
}
|
||||
else if (curr_id_is_as() || curr_id_is_underscore()) {
|
||||
TRACE("push_expr_frame", tout << "push_expr_frame(): parse_qualified_name\n";);
|
||||
parse_qualified_name();
|
||||
}
|
||||
else if (curr_id_is_root_obj()) {
|
||||
parse_root_obj();
|
||||
}
|
||||
else if (curr_id_is_match()) {
|
||||
push_match_frame();
|
||||
}
|
||||
else {
|
||||
push_app_frame();
|
||||
}
|
||||
|
@ -1773,6 +1993,9 @@ namespace smt2 {
|
|||
m_stack.deallocate(static_cast<let_decl_frame*>(fr));
|
||||
m_num_expr_frames--;
|
||||
break;
|
||||
case EF_MATCH:
|
||||
pop_match_frame(static_cast<match_frame*>(fr));
|
||||
break;
|
||||
case EF_QUANT:
|
||||
pop_quant_frame(static_cast<quant_frame*>(fr));
|
||||
break;
|
||||
|
@ -2232,8 +2455,10 @@ namespace smt2 {
|
|||
throw cmd_exception("invalid assert command, expression required as argument");
|
||||
}
|
||||
expr * f = expr_stack().back();
|
||||
if (!m().is_bool(f))
|
||||
if (!m().is_bool(f)) {
|
||||
TRACE("smt2parser", tout << expr_ref(f, m()) << "\n";);
|
||||
throw cmd_exception("invalid assert command, term is not Boolean");
|
||||
}
|
||||
if (f == m_last_named_expr.second) {
|
||||
m_ctx.assert_expr(m_last_named_expr.first, f);
|
||||
}
|
||||
|
@ -2730,6 +2955,7 @@ namespace smt2 {
|
|||
m_check_sat_assuming("check-sat-assuming"),
|
||||
m_define_fun_rec("define-fun-rec"),
|
||||
m_define_funs_rec("define-funs-rec"),
|
||||
m_match("match"),
|
||||
m_underscore("_"),
|
||||
m_num_open_paren(0),
|
||||
m_current_file(filename) {
|
||||
|
|
|
@ -3,7 +3,6 @@ z3_add_component(sat
|
|||
ba_solver.cpp
|
||||
dimacs.cpp
|
||||
sat_asymm_branch.cpp
|
||||
sat_ccc.cpp
|
||||
sat_clause.cpp
|
||||
sat_clause_set.cpp
|
||||
sat_clause_use_list.cpp
|
||||
|
|
|
@ -1,604 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
sat_ccc.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
A variant of Concurrent Cube and Conquer
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2017-4-17
|
||||
|
||||
Notes:
|
||||
|
||||
The cube process spawns conquer threads to search parts of the
|
||||
state space.
|
||||
The conquer threads have two modes:
|
||||
- emulation mode - where they try to outpace the cuber on the same search tree
|
||||
- complement mode - where they solve a sub-branch not yet explored by the cuber.
|
||||
When the conquer thread returns a solved cube it is processed in the following ways:
|
||||
- ignore if solved_id \not\in decisions
|
||||
- mark d as closed if d \in decisions, such that d is marked by solved id
|
||||
- backjump otherwise, conquer thread has solved a branch attempted by the cuber
|
||||
|
||||
--*/
|
||||
|
||||
#include "sat_solver.h"
|
||||
#include "sat_lookahead.h"
|
||||
#include "sat_ccc.h"
|
||||
|
||||
using namespace sat;
|
||||
|
||||
// ------------
|
||||
// cuber
|
||||
|
||||
ccc::cuber::cuber(ccc& c): m_ccc(c), m_lh(alloc(lookahead, c.m_s)), m_branch_id(0) {}
|
||||
|
||||
lbool ccc::cuber::search() {
|
||||
while (true) {
|
||||
m_branch_id = 0;
|
||||
m_last_closure_level = 1000;
|
||||
|
||||
m_lh->init_search();
|
||||
m_lh->m_model.reset();
|
||||
|
||||
lookahead::scoped_level _sl(*m_lh.get(), m_lh->c_fixed_truth);
|
||||
m_lh->m_search_mode = lookahead_mode::searching;
|
||||
lbool r = research();
|
||||
if (r == l_true) {
|
||||
m_ccc.m_model = m_lh->get_model();
|
||||
}
|
||||
if (false && r == l_undef) {
|
||||
continue;
|
||||
}
|
||||
m_lh->collect_statistics(m_ccc.m_lh_stats);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
lbool ccc::cuber::research() {
|
||||
m_ccc.m_s.checkpoint();
|
||||
|
||||
if (m_lh->inconsistent()) {
|
||||
return l_false;
|
||||
}
|
||||
|
||||
if (pop_lookahead()) {
|
||||
return l_undef;
|
||||
}
|
||||
|
||||
if (get_solved()) {
|
||||
return l_false;
|
||||
}
|
||||
|
||||
m_lh->inc_istamp();
|
||||
literal l = m_lh->choose();
|
||||
if (m_lh->inconsistent()) {
|
||||
return l_false;
|
||||
}
|
||||
|
||||
if (l == null_literal) {
|
||||
return l_true;
|
||||
}
|
||||
|
||||
if (!m_decisions.empty()) {
|
||||
m_ccc.put_decision(m_decisions.back());
|
||||
}
|
||||
|
||||
|
||||
// update trail and m_decisions
|
||||
|
||||
++m_lh->m_stats.m_decisions;
|
||||
unsigned parent_id = m_decisions.empty() ? 0 : m_decisions.back().m_id;
|
||||
unsigned spawn_id = spawn_conquer();
|
||||
unsigned branch1 = m_branch_id++;
|
||||
unsigned branch2 = m_branch_id++;
|
||||
decision d(branch1, m_decisions.size() + 1, l, parent_id, spawn_id);
|
||||
m_decisions.push_back(d);
|
||||
|
||||
IF_VERBOSE(2, d.pp(verbose_stream() << "select " << m_last_closure_level << " ") << "\n";);
|
||||
IF_VERBOSE(2, verbose_stream() << "select " << pp_prefix(m_lh->m_prefix, m_lh->m_trail_lim.size()) << ": " << l << " " << m_lh->m_trail.size() << "\n";);
|
||||
IF_VERBOSE(3, pp(verbose_stream(), m_decisions) << "\n"; );
|
||||
|
||||
TRACE("sat", tout << "choose: " << l << "\n";);
|
||||
m_lh->push(l, m_lh->c_fixed_truth);
|
||||
lbool r = research();
|
||||
if (r == l_false) {
|
||||
m_lh->pop();
|
||||
if (m_decisions.back().is_closed()) {
|
||||
// branch was solved by a spawned conquer process
|
||||
IF_VERBOSE(1, m_decisions.back().pp(verbose_stream() << "closed ") << "\n";);
|
||||
r = l_false;
|
||||
m_decisions.pop_back();
|
||||
}
|
||||
else {
|
||||
if (spawn_id > 0) {
|
||||
free_conquer(spawn_id);
|
||||
m_last_closure_level *= 3;
|
||||
m_last_closure_level /= 4;
|
||||
}
|
||||
m_lh->inc_istamp();
|
||||
m_lh->flip_prefix();
|
||||
m_lh->push(~l, m_lh->c_fixed_truth);
|
||||
m_decisions.back().negate();
|
||||
m_decisions.back().m_id = branch2;
|
||||
m_decisions.back().m_spawn_id = 0;
|
||||
r = research();
|
||||
if (r == l_false) {
|
||||
m_lh->pop();
|
||||
m_decisions.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
bool ccc::cuber::pop_lookahead() {
|
||||
return false;
|
||||
|
||||
scoped_ptr<lookahead> new_lh;
|
||||
bool result = false;
|
||||
#pragma omp critical (ccc_new_lh)
|
||||
{
|
||||
if (m_ccc.m_new_lh) {
|
||||
new_lh = m_ccc.m_new_lh.detach();
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
if (new_lh) {
|
||||
m_lh->collect_statistics(m_ccc.m_lh_stats);
|
||||
m_lh = new_lh.detach();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ccc::cuber::update_closure_level(decision const& d, int offset) {
|
||||
m_last_closure_level = (d.m_depth + 3*m_last_closure_level) / 4;
|
||||
if (m_last_closure_level >= static_cast<unsigned>(abs(offset))) {
|
||||
m_last_closure_level += offset;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned ccc::cuber::spawn_conquer() {
|
||||
unsigned result = 0;
|
||||
//
|
||||
// decisions must have been solved at a higher level by a conquer thread
|
||||
//
|
||||
if (!m_free_threads.empty()) {
|
||||
if (m_last_closure_level <= m_decisions.size()) {
|
||||
result = m_free_threads.back();
|
||||
++m_ccc.m_ccc_stats.m_spawn_opened;
|
||||
m_free_threads.pop_back();
|
||||
}
|
||||
else {
|
||||
IF_VERBOSE(1, verbose_stream() << m_last_closure_level << " " << m_decisions.size() << "\n";);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void ccc::cuber::free_conquer(unsigned id) {
|
||||
if (id != 0) {
|
||||
m_free_threads.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ccc::cuber::get_solved() {
|
||||
// check if CDCL solver got ahead.
|
||||
bool do_pop = false;
|
||||
solution sol;
|
||||
while (true) {
|
||||
bool is_empty = true;
|
||||
#pragma omp critical (ccc_solved)
|
||||
{
|
||||
if (do_pop) m_ccc.m_solved.pop_front();
|
||||
if (!m_ccc.m_solved.empty()) {
|
||||
sol = m_ccc.m_solved.top();
|
||||
is_empty = false;
|
||||
}
|
||||
}
|
||||
if (is_empty) {
|
||||
return false;
|
||||
}
|
||||
do_pop = true;
|
||||
unsigned branch_id = sol.m_branch_id;
|
||||
unsigned thread_id = sol.m_thread_id;
|
||||
bool found = false;
|
||||
for (unsigned i = m_decisions.size(); i > 0; ) {
|
||||
--i;
|
||||
decision& d = m_decisions[i];
|
||||
if (branch_id == d.m_id) {
|
||||
if (d.m_spawn_id == thread_id && thread_id != 0) {
|
||||
SASSERT(d.m_spawn_id > 0);
|
||||
IF_VERBOSE(2, d.pp(verbose_stream() << thread_id << ": spawn close ") << "\n";);
|
||||
++m_ccc.m_ccc_stats.m_spawn_closed;
|
||||
d.close();
|
||||
free_conquer(thread_id);
|
||||
update_closure_level(d, -1);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
IF_VERBOSE(2, d.pp(verbose_stream() << thread_id << ": conquer ") << "\n";);
|
||||
++m_ccc.m_ccc_stats.m_cdcl_closed;
|
||||
update_closure_level(d, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// branch is even, d has moved to the next branch
|
||||
if (branch_id == (d.m_id & ~0x1) && d.m_spawn_id == thread_id && thread_id != 0) {
|
||||
IF_VERBOSE(1, d.pp(verbose_stream() << thread_id << ": spawn conquer ") << "\n";);
|
||||
++m_ccc.m_ccc_stats.m_cdcl_closed;
|
||||
update_closure_level(d, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
// conquer state machine
|
||||
|
||||
lbool ccc::conquer::search() {
|
||||
try {
|
||||
if (s.inconsistent()) return l_false;
|
||||
s.init_search();
|
||||
s.propagate(false);
|
||||
if (s.inconsistent()) return l_false;
|
||||
s.cleanup();
|
||||
s.simplify_problem();
|
||||
if (s.inconsistent()) return l_false;
|
||||
|
||||
while (true) {
|
||||
SASSERT(!s.inconsistent());
|
||||
|
||||
lbool r = bounded_search();
|
||||
if (r != l_undef)
|
||||
return r;
|
||||
|
||||
s.restart();
|
||||
s.simplify_problem();
|
||||
if (s.check_inconsistent()) return l_false;
|
||||
s.gc();
|
||||
push_lookahead();
|
||||
}
|
||||
}
|
||||
catch (solver::abort_solver) {
|
||||
return l_undef;
|
||||
}
|
||||
}
|
||||
|
||||
void ccc::conquer::replay_decisions() {
|
||||
s.propagate(true);
|
||||
for (unsigned i = s.scope_lvl(); !s.inconsistent() && i < m_decisions.size(); ++i) {
|
||||
decision const& d = m_decisions[i];
|
||||
IF_VERBOSE(2, verbose_stream() << thread_id << ": replay " << d.get_literal(thread_id) << " " << s.value(d.get_literal(thread_id)) << "\n";);
|
||||
|
||||
if (!push_decision(d)) {
|
||||
// negation of decision is implied.
|
||||
IF_VERBOSE(1, d.pp(verbose_stream() << thread_id << ": backjump to level " << i << " ") << "\n";);
|
||||
while (m_decisions.size() > i) {
|
||||
pop_decision(m_decisions.back());
|
||||
m_decisions.pop_back();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (d.m_spawn_id == thread_id && d.is_left()) {
|
||||
// we pushed the right branch on this thread.
|
||||
IF_VERBOSE(1, d.pp(verbose_stream() << thread_id << ": skip left branch on level " << i + 1 << " ") << "\n";);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ccc::conquer::pop_decision(decision const& d) {
|
||||
unsigned tid = 0;
|
||||
if (d.is_spawned(thread_id)) {
|
||||
tid = thread_id;
|
||||
m_spawned = false;
|
||||
IF_VERBOSE(1, d.pp(verbose_stream() << thread_id << ": retire spawn ") << "\n";);
|
||||
}
|
||||
#pragma omp critical (ccc_solved)
|
||||
{
|
||||
m_ccc.m_solved.push(solution(tid, d.m_id));
|
||||
}
|
||||
}
|
||||
|
||||
void ccc::conquer::push_lookahead() {
|
||||
return;
|
||||
|
||||
#pragma omp critical (ccc_new_lh)
|
||||
{
|
||||
if (!m_ccc.m_new_lh && m_ccc.m_num_clauses > s.num_clauses()) {
|
||||
std::cout << "push " << s.num_clauses() << "\n";
|
||||
m_ccc.m_new_lh = alloc(lookahead, s);
|
||||
m_ccc.m_num_clauses = s.num_clauses();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ccc::conquer::push_decision(decision const& d) {
|
||||
literal lit = d.get_literal(thread_id);
|
||||
switch (s.value(lit)) {
|
||||
case l_false:
|
||||
//TBD:
|
||||
s.m_restart_threshold = s.m_config.m_restart_initial;
|
||||
//s.m_conflicts_since_last_restart = 0;
|
||||
return false;
|
||||
case l_true:
|
||||
s.push();
|
||||
break;
|
||||
case l_undef:
|
||||
s.push();
|
||||
s.assign(lit, justification());
|
||||
s.propagate(true);
|
||||
break;
|
||||
}
|
||||
m_spawned |= d.is_spawned(thread_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ccc::conquer::cube_decision() {
|
||||
decision d;
|
||||
bool use_cube_decision = false;
|
||||
SASSERT(s.m_qhead == s.m_trail.size());
|
||||
|
||||
while (true) {
|
||||
if (!m_ccc.get_decision(thread_id, d)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (d.is_spawned(thread_id)) IF_VERBOSE(1, d.pp(verbose_stream() << thread_id << " ") << "\n";);
|
||||
|
||||
if (!m_decisions.empty() && m_decisions.back().m_depth + 1 < d.m_depth) {
|
||||
if (d.is_spawned(thread_id)) {
|
||||
pop_decision(d);
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
SASSERT(m_decisions.empty() || m_decisions.back().m_depth + 1 >= d.m_depth);
|
||||
|
||||
if (!m_decisions.empty() && m_decisions.back().is_spawned(thread_id) && m_decisions.back().m_depth == d.m_depth) {
|
||||
SASSERT(d.m_spawn_id == 0);
|
||||
SASSERT(m_decisions.back().is_left());
|
||||
SASSERT(!d.is_left());
|
||||
IF_VERBOSE(1, verbose_stream() << thread_id << " inherit spawn\n";);
|
||||
m_decisions.back().m_spawn_id = 0;
|
||||
m_spawned = false;
|
||||
}
|
||||
SASSERT(m_decisions.empty() || m_decisions.back().m_depth + 1 >= d.m_depth);
|
||||
|
||||
while (!m_decisions.empty() && m_decisions.back().m_depth >= d.m_depth) {
|
||||
// check_non_model("cube decision", m_decisions);
|
||||
if (m_decisions.back().is_spawned(thread_id)) {
|
||||
pop_decision(m_decisions.back());
|
||||
}
|
||||
m_decisions.pop_back();
|
||||
}
|
||||
|
||||
SASSERT(m_decisions.empty() || m_decisions.back().m_depth + 1 == d.m_depth);
|
||||
SASSERT(m_decisions.empty() || m_decisions.back().m_id == d.m_parent);
|
||||
if (m_spawned) {
|
||||
m_decisions.push_back(d);
|
||||
return true;
|
||||
}
|
||||
|
||||
s.pop_reinit(s.scope_lvl() - m_decisions.size());
|
||||
SASSERT(s.m_qhead == s.m_trail.size());
|
||||
SASSERT(s.scope_lvl() == m_decisions.size());
|
||||
literal lit = d.get_literal(thread_id);
|
||||
IF_VERBOSE(2, d.pp(verbose_stream() << thread_id << ": cube ") << "\n";);
|
||||
IF_VERBOSE(3, pp(verbose_stream() << thread_id << ": push ", m_decisions) << " @ " << s.scope_lvl() << " " << s.value(lit) << "\n";
|
||||
if (s.value(lit) == l_false) verbose_stream() << "level: " << s.lvl(lit) << "\n";);
|
||||
|
||||
if (push_decision(d)) {
|
||||
m_decisions.push_back(d);
|
||||
}
|
||||
else {
|
||||
pop_decision(d);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
lbool ccc::conquer::bounded_search() {
|
||||
while (true) {
|
||||
s.checkpoint();
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
replay_decisions();
|
||||
lbool is_sat = s.propagate_and_backjump_step(done);
|
||||
if (is_sat != l_true) return is_sat;
|
||||
}
|
||||
|
||||
s.gc();
|
||||
|
||||
if (!cube_decision() && !s.decide()) {
|
||||
lbool is_sat = s.final_check();
|
||||
if (is_sat != l_undef) {
|
||||
return is_sat;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --------------
|
||||
// shared state
|
||||
|
||||
std::ostream& ccc::decision::pp(std::ostream& out) const {
|
||||
out << "("
|
||||
<< "id:" << m_id
|
||||
<< " l:" << m_literal
|
||||
<< " d:" << m_depth;
|
||||
if (m_spawn_id != 0) {
|
||||
out << " s:" << m_spawn_id;
|
||||
}
|
||||
out << ") ";
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& ccc::pp(std::ostream& out, svector<decision> const& v) {
|
||||
for (unsigned i = 0; i < v.size(); ++i) {
|
||||
v[i].pp(out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
bool ccc::get_decision(unsigned thread_id, decision& d) {
|
||||
SASSERT(0 < thread_id && thread_id <= m_decisions.size());
|
||||
bool result = false;
|
||||
#pragma omp critical (ccc_decisions)
|
||||
{
|
||||
if (!m_decisions[thread_id - 1].empty()) {
|
||||
d = m_decisions[thread_id - 1].pop_front();
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ccc::put_decision(decision const& d) {
|
||||
for (unsigned i = 0; i < m_num_conquer; ++i) {
|
||||
#pragma omp critical (ccc_decisions)
|
||||
{
|
||||
while (false && !m_decisions[i].empty()) { // introduces contention.
|
||||
decision d = m_decisions[i].back();
|
||||
if (d.m_depth < d.m_depth || d.m_spawn_id != 0) {
|
||||
break;
|
||||
}
|
||||
m_decisions[i].pop_back();
|
||||
}
|
||||
m_decisions[i].push(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lbool ccc::search() {
|
||||
enum par_exception_kind {
|
||||
DEFAULT_EX,
|
||||
ERROR_EX
|
||||
};
|
||||
|
||||
// set_model();
|
||||
|
||||
m_cancel = false;
|
||||
|
||||
scoped_limits scoped_rlimit(m_s.rlimit());
|
||||
ptr_vector<conquer> solvers;
|
||||
int finished_id = -1;
|
||||
std::string ex_msg;
|
||||
par_exception_kind ex_kind;
|
||||
unsigned error_code = 0;
|
||||
lbool result = l_undef;
|
||||
m_decisions.reset();
|
||||
|
||||
cuber cuber(*this);
|
||||
|
||||
m_num_conquer = m_s.m_config.m_num_threads;
|
||||
int num_threads = 1 + m_num_conquer; // for ccc-infinity only two threads.
|
||||
|
||||
for (int i = 1; i < num_threads; ++i) {
|
||||
m_s.m_params.set_uint("random_seed", m_s.m_rand());
|
||||
conquer* s1 = alloc(conquer, *this, m_s.m_params, i);
|
||||
solvers.push_back(s1);
|
||||
s1->s.copy(m_s);
|
||||
scoped_rlimit.push_child(&(s1->m_limit));
|
||||
m_decisions.push_back(queue<decision>());
|
||||
}
|
||||
for (unsigned i = 1; i < m_num_conquer; ++i) {
|
||||
cuber.m_free_threads.push_back(i);
|
||||
}
|
||||
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < num_threads; ++i) {
|
||||
try {
|
||||
lbool r = l_undef;
|
||||
if (i == 0) {
|
||||
r = cuber.search();
|
||||
}
|
||||
else {
|
||||
r = solvers[i-1]->search();
|
||||
}
|
||||
bool first = false;
|
||||
#pragma omp critical (par_solver)
|
||||
{
|
||||
if (finished_id == -1) {
|
||||
finished_id = i;
|
||||
first = true;
|
||||
result = r;
|
||||
}
|
||||
}
|
||||
if (first) {
|
||||
for (unsigned j = 0; j < solvers.size(); ++j) {
|
||||
solvers[j]->m_limit.cancel();
|
||||
}
|
||||
// cancel lookahead solver:
|
||||
m_cancel = true;
|
||||
}
|
||||
}
|
||||
catch (z3_error & err) {
|
||||
error_code = err.error_code();
|
||||
ex_kind = ERROR_EX;
|
||||
}
|
||||
catch (z3_exception & ex) {
|
||||
ex_msg = ex.msg();
|
||||
ex_kind = DEFAULT_EX;
|
||||
}
|
||||
}
|
||||
|
||||
if (finished_id > 0 && result == l_true) {
|
||||
// set model from auxiliary solver
|
||||
m_model = solvers[finished_id - 1]->s.get_model();
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < solvers.size(); ++i) {
|
||||
solvers[i]->s.collect_statistics(m_lh_stats);
|
||||
dealloc(solvers[i]);
|
||||
}
|
||||
|
||||
if (finished_id == -1) {
|
||||
switch (ex_kind) {
|
||||
case ERROR_EX: throw z3_error(error_code);
|
||||
default: throw default_exception(ex_msg.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (result == l_true) {
|
||||
for (unsigned i = 1; i < m_model.size(); ++i) {
|
||||
std::cout << "push_model(" << i << ", " << (m_model[i] > 0 ? "false" : "true") << ");\n";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
void ccc::push_model(unsigned v, bool sign) {
|
||||
if (m_values.size() <= v) {
|
||||
m_values.resize(v + 1);
|
||||
}
|
||||
m_values[v] = sign;
|
||||
}
|
||||
|
||||
void ccc::check_non_model(char const* fn, svector<decision> const& decisions) {
|
||||
for (unsigned i = 0; i < decisions.size(); ++i) {
|
||||
decision d = decisions[i];
|
||||
literal lit = d.m_literal;
|
||||
if (m_values[lit.var()] != lit.sign()) return;
|
||||
}
|
||||
|
||||
IF_VERBOSE(1, pp(verbose_stream() << "backtracking from model " << fn << " ", decisions) << "\n";);
|
||||
}
|
||||
#endif
|
|
@ -1,150 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
sat_ccc.h
|
||||
|
||||
Abstract:
|
||||
|
||||
A variant of Concurrent Cube and Conquer
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2017-4-17
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _SAT_CCC_H_
|
||||
#define _SAT_CCC_H_
|
||||
|
||||
#include "util/queue.h"
|
||||
|
||||
namespace sat {
|
||||
|
||||
|
||||
class ccc {
|
||||
struct decision {
|
||||
unsigned m_id; // unique identifier for decision
|
||||
unsigned m_depth; // depth of decision
|
||||
literal m_literal; // decision literal
|
||||
unsigned m_parent; // id of parent
|
||||
int m_spawn_id; // thread id of conquer thread processing complented branch.
|
||||
// = 0 if not spawned.
|
||||
// > 0 if active spawn is in progress
|
||||
// < 0 if thread has closed the branch
|
||||
decision(unsigned id, unsigned d, literal last, unsigned parent_id, unsigned spawn):
|
||||
m_id(id), m_depth(d), m_literal(last), m_parent(parent_id), m_spawn_id(spawn) {}
|
||||
decision():
|
||||
m_id(0), m_depth(0), m_literal(null_literal), m_parent(0), m_spawn_id(0) {}
|
||||
|
||||
void close() { SASSERT(m_spawn_id > 0); m_spawn_id = -m_spawn_id; }
|
||||
bool is_closed() const { return m_spawn_id < 0; }
|
||||
void negate() { m_literal.neg(); }
|
||||
bool is_left() const { return 0 == (m_id & 0x1); }
|
||||
bool is_spawned(unsigned thread_id) const { return m_spawn_id == thread_id; }
|
||||
|
||||
// the left branch has an even branch_id.
|
||||
// the branch is spawned if it is even and the spawn_id is the same as the thread_id, and furthermore it is exploring the left branch.
|
||||
// it may explore the right branch, but is then not in a spawned mode.
|
||||
// we retain the spawn id so that the spawned thread can be re-spun.
|
||||
literal get_literal(unsigned thread_id) const { return ((m_id & 0x1) == 0 && thread_id == m_spawn_id) ? ~m_literal : m_literal; }
|
||||
std::ostream& pp(std::ostream& out) const;
|
||||
};
|
||||
|
||||
struct solution {
|
||||
unsigned m_thread_id;
|
||||
unsigned m_branch_id;
|
||||
solution(unsigned t, unsigned s): m_thread_id(t), m_branch_id(s) {}
|
||||
solution(): m_thread_id(0), m_branch_id(0) {}
|
||||
};
|
||||
|
||||
struct stats {
|
||||
unsigned m_spawn_closed;
|
||||
unsigned m_spawn_opened;
|
||||
unsigned m_cdcl_closed;
|
||||
stats() { reset(); }
|
||||
void reset() {
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
};
|
||||
|
||||
struct conquer {
|
||||
reslimit m_limit;
|
||||
ccc& m_ccc;
|
||||
solver s;
|
||||
svector<decision> m_decisions;
|
||||
unsigned thread_id;
|
||||
bool m_spawned;
|
||||
conquer(ccc& super, params_ref const& p, unsigned tid): m_ccc(super), s(p, m_limit), thread_id(tid), m_spawned(false) {}
|
||||
|
||||
lbool search();
|
||||
bool cube_decision();
|
||||
lbool bounded_search();
|
||||
bool push_decision(decision const& d);
|
||||
void pop_decision(decision const& d);
|
||||
void push_lookahead();
|
||||
void replay_decisions();
|
||||
};
|
||||
|
||||
struct cuber {
|
||||
ccc& m_ccc;
|
||||
scoped_ptr<lookahead> m_lh;
|
||||
unsigned m_branch_id;
|
||||
unsigned m_last_closure_level;
|
||||
unsigned_vector m_free_threads;
|
||||
svector<decision> m_decisions;
|
||||
|
||||
cuber(ccc& c);
|
||||
lbool search();
|
||||
lbool research();
|
||||
bool get_solved();
|
||||
void update_closure_level(decision const& d, int offset);
|
||||
unsigned spawn_conquer();
|
||||
void free_conquer(unsigned thread_id);
|
||||
bool pop_lookahead();
|
||||
};
|
||||
|
||||
solver& m_s;
|
||||
queue<solution> m_solved;
|
||||
vector<queue<decision> > m_decisions;
|
||||
scoped_ptr<lookahead> m_new_lh;
|
||||
unsigned m_num_clauses;
|
||||
unsigned m_num_conquer;
|
||||
model m_model;
|
||||
volatile bool m_cancel;
|
||||
::statistics m_lh_stats;
|
||||
stats m_ccc_stats;
|
||||
|
||||
void put_decision(decision const& d);
|
||||
bool get_decision(unsigned thread_id, decision& d);
|
||||
|
||||
static std::ostream& pp(std::ostream& out, svector<decision> const& v);
|
||||
|
||||
void push_model(unsigned v, bool sign);
|
||||
void set_model();
|
||||
bool trail_in_model(literal_vector const& trail) const;
|
||||
|
||||
void check_non_model(char const* fn, svector<decision> const& decisions);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
ccc(solver& s): m_s(s), m_num_clauses(s.num_clauses()) {}
|
||||
|
||||
lbool search();
|
||||
|
||||
model const& get_model() const { return m_model; }
|
||||
|
||||
void collect_statistics(::statistics& st) {
|
||||
st.copy(m_lh_stats);
|
||||
st.update("ccc-spawn-closed", m_ccc_stats.m_spawn_closed);
|
||||
st.update("ccc-cdcl-closed", m_ccc_stats.m_cdcl_closed);
|
||||
st.update("ccc-spawn-opened", m_ccc_stats.m_spawn_opened);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -39,7 +39,6 @@ namespace sat {
|
|||
m_local_search = 0;
|
||||
m_lookahead_search = false;
|
||||
m_lookahead_simplify = false;
|
||||
m_ccc = false;
|
||||
updt_params(p);
|
||||
}
|
||||
|
||||
|
@ -86,9 +85,11 @@ namespace sat {
|
|||
m_local_search = p.local_search();
|
||||
m_local_search_threads = p.local_search_threads();
|
||||
m_lookahead_simplify = p.lookahead_simplify();
|
||||
m_lookahead_cube = p.lookahead_cube();
|
||||
m_lookahead_search = p.lookahead_search();
|
||||
m_lookahead_reward = p.lookahead_reward();
|
||||
m_ccc = p.ccc();
|
||||
m_lookahead_cube_fraction = p.lookahead_cube_fraction();
|
||||
m_lookahead_cube_cutoff = p.lookahead_cube_cutoff();
|
||||
|
||||
// These parameters are not exposed
|
||||
m_simplify_mult1 = _p.get_uint("simplify_mult1", 300);
|
||||
|
@ -166,6 +167,7 @@ namespace sat {
|
|||
else {
|
||||
throw sat_param_exception("invalid PB solver: solver, totalizer, circuit, sorting");
|
||||
}
|
||||
m_dimacs_display = p.dimacs_display();
|
||||
}
|
||||
|
||||
void config::collect_param_descrs(param_descrs & r) {
|
||||
|
|
|
@ -75,8 +75,10 @@ namespace sat {
|
|||
bool m_local_search;
|
||||
bool m_lookahead_search;
|
||||
bool m_lookahead_simplify;
|
||||
bool m_lookahead_cube;
|
||||
unsigned m_lookahead_cube_cutoff;
|
||||
double m_lookahead_cube_fraction;
|
||||
symbol m_lookahead_reward;
|
||||
bool m_ccc;
|
||||
|
||||
unsigned m_simplify_mult1;
|
||||
double m_simplify_mult2;
|
||||
|
@ -96,6 +98,8 @@ namespace sat {
|
|||
symbol m_drat_file;
|
||||
bool m_drat_check;
|
||||
|
||||
bool m_dimacs_display;
|
||||
|
||||
symbol m_always_true;
|
||||
symbol m_always_false;
|
||||
symbol m_caching;
|
||||
|
|
|
@ -1710,6 +1710,47 @@ namespace sat {
|
|||
return true;
|
||||
}
|
||||
|
||||
void lookahead::cube() {
|
||||
m_model.reset();
|
||||
scoped_level _sl(*this, c_fixed_truth);
|
||||
literal_vector trail;
|
||||
m_search_mode = lookahead_mode::searching;
|
||||
double freevars_threshold = 0;
|
||||
while (true) {
|
||||
TRACE("sat", display(tout););
|
||||
inc_istamp();
|
||||
checkpoint();
|
||||
literal l = choose();
|
||||
if (inconsistent()) {
|
||||
freevars_threshold = m_freevars.size();
|
||||
if (!backtrack(trail)) return;
|
||||
continue;
|
||||
}
|
||||
unsigned depth = m_trail_lim.size();
|
||||
if (l == null_literal ||
|
||||
(m_config.m_cube_cutoff != 0 && depth == m_config.m_cube_cutoff) ||
|
||||
(m_config.m_cube_cutoff == 0 && m_freevars.size() < freevars_threshold)) {
|
||||
display_cube(std::cout);
|
||||
set_conflict();
|
||||
if (!backtrack(trail)) return;
|
||||
freevars_threshold *= (1.0 - pow(m_config.m_cube_fraction, depth));
|
||||
continue;
|
||||
}
|
||||
TRACE("sat", tout << "choose: " << l << " " << trail << "\n";);
|
||||
++m_stats.m_decisions;
|
||||
IF_VERBOSE(1, printf("\r");
|
||||
std::stringstream strm;
|
||||
strm << pp_prefix(m_prefix, m_trail_lim.size());
|
||||
for (unsigned i = 0; i < 50; ++i) strm << " ";
|
||||
printf(strm.str().c_str());
|
||||
fflush(stdout);
|
||||
);
|
||||
push(l, c_fixed_truth);
|
||||
trail.push_back(l);
|
||||
SASSERT(inconsistent() || !is_unsat());
|
||||
}
|
||||
}
|
||||
|
||||
lbool lookahead::search() {
|
||||
m_model.reset();
|
||||
scoped_level _sl(*this, c_fixed_truth);
|
||||
|
@ -1719,10 +1760,6 @@ namespace sat {
|
|||
TRACE("sat", display(tout););
|
||||
inc_istamp();
|
||||
checkpoint();
|
||||
if (inconsistent()) {
|
||||
if (!backtrack(trail)) return l_false;
|
||||
continue;
|
||||
}
|
||||
literal l = choose();
|
||||
if (inconsistent()) {
|
||||
if (!backtrack(trail)) return l_false;
|
||||
|
@ -1764,6 +1801,14 @@ namespace sat {
|
|||
}
|
||||
}
|
||||
|
||||
std::ostream& lookahead::display_cube(std::ostream& out) const {
|
||||
out << "c";
|
||||
for (literal l : m_assumptions) {
|
||||
out << " " << ~l;
|
||||
}
|
||||
return out << "\n";
|
||||
}
|
||||
|
||||
std::ostream& lookahead::display_binary(std::ostream& out) const {
|
||||
for (unsigned i = 0; i < m_binary.size(); ++i) {
|
||||
literal_vector const& lits = m_binary[i];
|
||||
|
@ -1818,7 +1863,7 @@ namespace sat {
|
|||
|
||||
literal lookahead::choose() {
|
||||
literal l = null_literal;
|
||||
while (l == null_literal) {
|
||||
while (l == null_literal && !inconsistent()) {
|
||||
pre_select();
|
||||
if (m_lookahead.empty()) {
|
||||
break;
|
||||
|
@ -2013,6 +2058,8 @@ namespace sat {
|
|||
else {
|
||||
warning_msg("Reward type not recognized");
|
||||
}
|
||||
m_config.m_cube_cutoff = m_s.m_config.m_lookahead_cube_cutoff;
|
||||
m_config.m_cube_fraction = m_s.m_config.m_lookahead_cube_fraction;
|
||||
}
|
||||
|
||||
void lookahead::collect_statistics(statistics& st) const {
|
||||
|
|
|
@ -84,6 +84,8 @@ namespace sat {
|
|||
unsigned m_dl_max_iterations;
|
||||
unsigned m_tc1_limit;
|
||||
reward_t m_reward_type;
|
||||
unsigned m_cube_cutoff;
|
||||
double m_cube_fraction;
|
||||
|
||||
config() {
|
||||
m_max_hlevel = 50;
|
||||
|
@ -95,6 +97,8 @@ namespace sat {
|
|||
m_dl_max_iterations = 32;
|
||||
m_tc1_limit = 10000000;
|
||||
m_reward_type = ternary_reward;
|
||||
m_cube_cutoff = 0;
|
||||
m_cube_fraction = 0.4;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -446,6 +450,8 @@ namespace sat {
|
|||
std::ostream& display_clauses(std::ostream& out) const;
|
||||
std::ostream& display_values(std::ostream& out) const;
|
||||
std::ostream& display_lookahead(std::ostream& out) const;
|
||||
std::ostream& display_cube(std::ostream& out) const;
|
||||
|
||||
void init_search();
|
||||
void checkpoint();
|
||||
|
||||
|
@ -474,6 +480,14 @@ namespace sat {
|
|||
return search();
|
||||
}
|
||||
|
||||
/**
|
||||
\brief create cubes to std-out in DIMACS form.
|
||||
The cubes are controlled using cut-depth and cut-fraction parameters.
|
||||
If cut-depth != 0, then it is used to control the depth of cuts.
|
||||
Otherwise, cut-fraction gives an adaptive threshold for creating cuts.
|
||||
*/
|
||||
void cube();
|
||||
|
||||
literal select_lookahead(literal_vector const& assumptions, bool_var_vector const& vars);
|
||||
/**
|
||||
\brief simplify set of clauses by extracting units from a lookahead at base level.
|
||||
|
|
|
@ -34,8 +34,11 @@ def_module_params('sat',
|
|||
('atmost1_encoding', SYMBOL, 'grouped', 'encoding used for at-most-1 constraints grouped, bimander, ordered'),
|
||||
('local_search_threads', UINT, 0, 'number of local search threads to find satisfiable solution'),
|
||||
('local_search', BOOL, False, 'use local search instead of CDCL'),
|
||||
('lookahead_cube', BOOL, False, 'use lookahead solver to create cubes'),
|
||||
('lookahead.cube.fraction', DOUBLE, 0.4, 'adaptive fraction to create lookahead cubes. Used when lookahead_cube is true'),
|
||||
('lookahead.cube.cutoff', UINT, 0, 'cut-off depth to create cubes. Only enabled when non-zero. Used when lookahead_cube is true.'),
|
||||
('lookahead_search', BOOL, False, 'use lookahead solver'),
|
||||
('lookahead_simplify', BOOL, False, 'use lookahead solver during simplification'),
|
||||
('lookahead.reward', SYMBOL, 'heuleu', 'select lookahead heuristic: ternary, hs (Heule Schur), heuleu (Heule Unit), or unit'),
|
||||
('ccc', BOOL, False, 'use Concurrent Cube and Conquer solver')
|
||||
))
|
||||
('dimacs.display', BOOL, False, 'display SAT instance in DIMACS format and return unknown instead of solving')))
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ Revision History:
|
|||
#include "sat/sat_solver.h"
|
||||
#include "sat/sat_integrity_checker.h"
|
||||
#include "sat/sat_lookahead.h"
|
||||
#include "sat/sat_ccc.h"
|
||||
#include "util/luby.h"
|
||||
#include "util/trace.h"
|
||||
#include "util/max_cliques.h"
|
||||
|
@ -847,16 +846,25 @@ namespace sat {
|
|||
pop_to_base_level();
|
||||
IF_VERBOSE(2, verbose_stream() << "(sat.sat-solver)\n";);
|
||||
SASSERT(at_base_lvl());
|
||||
if (m_config.m_dimacs_display) {
|
||||
display_dimacs(std::cout);
|
||||
for (unsigned i = 0; i < num_lits; ++lits) {
|
||||
std::cout << dimacs_lit(lits[i]) << " 0\n";
|
||||
}
|
||||
return l_undef;
|
||||
}
|
||||
if (m_config.m_lookahead_search && num_lits == 0) {
|
||||
return lookahead_search();
|
||||
}
|
||||
if (m_config.m_lookahead_cube && num_lits == 0) {
|
||||
lookahead_cube();
|
||||
return l_undef;
|
||||
}
|
||||
if (m_config.m_local_search) {
|
||||
return do_local_search(num_lits, lits);
|
||||
}
|
||||
if (m_config.m_ccc && num_lits == 0) {
|
||||
return do_ccc();
|
||||
}
|
||||
if ((m_config.m_num_threads > 1 || m_config.m_local_search_threads > 0) && !m_par) {
|
||||
SASSERT(scope_lvl() == 0);
|
||||
return check_par(num_lits, lits);
|
||||
}
|
||||
flet<bool> _searching(m_searching, true);
|
||||
|
@ -913,13 +921,6 @@ namespace sat {
|
|||
if (check_inconsistent()) return l_false;
|
||||
gc();
|
||||
|
||||
#if 0
|
||||
if (m_clauses.size() < 65000) {
|
||||
return do_ccc();
|
||||
return lookahead_search();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_config.m_restart_max <= m_restarts) {
|
||||
m_reason_unknown = "sat.max.restarts";
|
||||
IF_VERBOSE(SAT_VB_LVL, verbose_stream() << "(sat \"abort: max-restarts\")\n";);
|
||||
|
@ -951,12 +952,16 @@ namespace sat {
|
|||
return r;
|
||||
}
|
||||
|
||||
lbool solver::do_ccc() {
|
||||
ccc c(*this);
|
||||
lbool r = c.search();
|
||||
m_model = c.get_model();
|
||||
c.collect_statistics(m_aux_stats);
|
||||
return r;
|
||||
void solver::lookahead_cube() {
|
||||
lookahead lh(*this);
|
||||
try {
|
||||
lh.cube();
|
||||
}
|
||||
catch (z3_exception&) {
|
||||
lh.collect_statistics(m_aux_stats);
|
||||
throw;
|
||||
}
|
||||
lh.collect_statistics(m_aux_stats);
|
||||
}
|
||||
|
||||
lbool solver::lookahead_search() {
|
||||
|
@ -1497,10 +1502,7 @@ namespace sat {
|
|||
}
|
||||
|
||||
void solver::sort_watch_lits() {
|
||||
vector<watch_list>::iterator it = m_watches.begin();
|
||||
vector<watch_list>::iterator end = m_watches.end();
|
||||
for (; it != end; ++it) {
|
||||
watch_list & wlist = *it;
|
||||
for (watch_list & wlist : m_watches) {
|
||||
std::stable_sort(wlist.begin(), wlist.end(), watched_lt());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -403,6 +403,7 @@ namespace sat {
|
|||
void exchange_par();
|
||||
lbool check_par(unsigned num_lits, literal const* lits);
|
||||
lbool lookahead_search();
|
||||
void lookahead_cube();
|
||||
lbool do_local_search(unsigned num_lits, literal const* lits);
|
||||
lbool do_ccc();
|
||||
|
||||
|
|
|
@ -149,7 +149,6 @@ public:
|
|||
|
||||
virtual void set_progress_callback(progress_callback * callback) {}
|
||||
|
||||
|
||||
void display_weighted(std::ostream& out, unsigned sz, expr * const * assumptions, unsigned const* weights) {
|
||||
if (weights != 0) {
|
||||
for (unsigned i = 0; i < sz; ++i) m_weights.push_back(weights[i]);
|
||||
|
@ -212,6 +211,11 @@ public:
|
|||
|
||||
init_reason_unknown();
|
||||
r = m_solver.check(m_asms.size(), m_asms.c_ptr());
|
||||
if (r == l_undef && m_solver.get_config().m_dimacs_display) {
|
||||
for (auto const& kv : m_map) {
|
||||
std::cout << "c " << kv.m_value << " " << mk_pp(kv.m_key, m) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
switch (r) {
|
||||
case l_true:
|
||||
|
@ -806,14 +810,12 @@ private:
|
|||
}
|
||||
sat::model const & ll_m = m_solver.get_model();
|
||||
model_ref md = alloc(model, m);
|
||||
atom2bool_var::iterator it = m_map.begin();
|
||||
atom2bool_var::iterator end = m_map.end();
|
||||
for (; it != end; ++it) {
|
||||
expr * n = it->m_key;
|
||||
for (auto const& kv : m_map) {
|
||||
expr * n = kv.m_key;
|
||||
if (is_app(n) && to_app(n)->get_num_args() > 0) {
|
||||
continue;
|
||||
}
|
||||
sat::bool_var v = it->m_value;
|
||||
sat::bool_var v = kv.m_value;
|
||||
switch (sat::value_at(v, ll_m)) {
|
||||
case l_true:
|
||||
md->register_decl(to_app(n)->get_decl(), m.mk_true());
|
||||
|
|
|
@ -16,11 +16,11 @@ Author:
|
|||
Notes:
|
||||
|
||||
--*/
|
||||
#include "ast/ast_pp.h"
|
||||
#include "tactic/tactical.h"
|
||||
#include "tactic/filter_model_converter.h"
|
||||
#include "sat/tactic/goal2sat.h"
|
||||
#include "sat/sat_solver.h"
|
||||
#include "tactic/filter_model_converter.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "model/model_v2_pp.h"
|
||||
|
||||
class sat_tactic : public tactic {
|
||||
|
@ -56,11 +56,9 @@ class sat_tactic : public tactic {
|
|||
sat::literal_vector assumptions;
|
||||
m_goal2sat(*g, m_params, m_solver, map, dep2asm);
|
||||
TRACE("sat_solver_unknown", tout << "interpreted_atoms: " << map.interpreted_atoms() << "\n";
|
||||
atom2bool_var::iterator it = map.begin();
|
||||
atom2bool_var::iterator end = map.end();
|
||||
for (; it != end; ++it) {
|
||||
if (!is_uninterp_const(it->m_key))
|
||||
tout << mk_ismt2_pp(it->m_key, m) << "\n";
|
||||
for (auto const& kv : map) {
|
||||
if (!is_uninterp_const(kv.m_key))
|
||||
tout << mk_ismt2_pp(kv.m_key, m) << "\n";
|
||||
});
|
||||
g->reset();
|
||||
g->m().compact_memory();
|
||||
|
@ -70,6 +68,11 @@ class sat_tactic : public tactic {
|
|||
TRACE("sat_dimacs", m_solver.display_dimacs(tout););
|
||||
dep2assumptions(dep2asm, assumptions);
|
||||
lbool r = m_solver.check(assumptions.size(), assumptions.c_ptr());
|
||||
if (r == l_undef && m_solver.get_config().m_dimacs_display) {
|
||||
for (auto const& kv : map) {
|
||||
std::cout << "c " << kv.m_value << " " << mk_pp(kv.m_key, g->m()) << "\n";
|
||||
}
|
||||
}
|
||||
if (r == l_false) {
|
||||
expr_dependency * lcore = 0;
|
||||
if (produce_core) {
|
||||
|
@ -90,11 +93,9 @@ class sat_tactic : public tactic {
|
|||
model_ref md = alloc(model, m);
|
||||
sat::model const & ll_m = m_solver.get_model();
|
||||
TRACE("sat_tactic", for (unsigned i = 0; i < ll_m.size(); i++) tout << i << ":" << ll_m[i] << " "; tout << "\n";);
|
||||
atom2bool_var::iterator it = map.begin();
|
||||
atom2bool_var::iterator end = map.end();
|
||||
for (; it != end; ++it) {
|
||||
expr * n = it->m_key;
|
||||
sat::bool_var v = it->m_value;
|
||||
for (auto const& kv : map) {
|
||||
expr * n = kv.m_key;
|
||||
sat::bool_var v = kv.m_value;
|
||||
TRACE("sat_tactic", tout << "extracting value of " << mk_ismt2_pp(n, m) << "\nvar: " << v << "\n";);
|
||||
switch (sat::value_at(v, ll_m)) {
|
||||
case l_true:
|
||||
|
@ -126,17 +127,15 @@ class sat_tactic : public tactic {
|
|||
|
||||
void dep2assumptions(obj_map<expr, sat::literal>& dep2asm,
|
||||
sat::literal_vector& assumptions) {
|
||||
obj_map<expr, sat::literal>::iterator it = dep2asm.begin(), end = dep2asm.end();
|
||||
for (; it != end; ++it) {
|
||||
assumptions.push_back(it->m_value);
|
||||
for (auto const& kv : dep2asm) {
|
||||
assumptions.push_back(kv.m_value);
|
||||
}
|
||||
}
|
||||
|
||||
void mk_asm2dep(obj_map<expr, sat::literal>& dep2asm,
|
||||
u_map<expr*>& lit2asm) {
|
||||
obj_map<expr, sat::literal>::iterator it = dep2asm.begin(), end = dep2asm.end();
|
||||
for (; it != end; ++it) {
|
||||
lit2asm.insert(it->m_value.index(), it->m_key);
|
||||
for (auto const& kv : dep2asm) {
|
||||
lit2asm.insert(kv.m_value.index(), kv.m_key);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*++
|
||||
Copyright (c) 2016 Microsoft Corporation
|
||||
|
||||
Author:
|
||||
Author:
|
||||
|
||||
Lev Nachmanson 2016-10-27
|
||||
|
||||
|
@ -54,7 +54,7 @@ struct front_end_resource_limit : public lp::lp_resource_limit {
|
|||
|
||||
void run_solver(lp_params & params, char const * mps_file_name) {
|
||||
|
||||
reslimit rlim;
|
||||
reslimit rlim;
|
||||
unsigned timeout = gparams::get().get_uint("timeout", 0);
|
||||
unsigned rlimit = gparams::get().get_uint("rlimit", 0);
|
||||
front_end_resource_limit lp_limit(rlim);
|
||||
|
@ -80,19 +80,20 @@ void run_solver(lp_params & params, char const * mps_file_name) {
|
|||
solver->settings().set_message_ostream(&std::cout);
|
||||
solver->settings().report_frequency = params.rep_freq();
|
||||
solver->settings().print_statistics = params.print_stats();
|
||||
solver->settings().simplex_strategy() = lp::simplex_strategy_enum::lu;
|
||||
solver->settings().simplex_strategy() = lp:: simplex_strategy_enum::lu;
|
||||
|
||||
solver->find_maximal_solution();
|
||||
|
||||
*(solver->settings().get_message_ostream()) << "status is " << lp_status_to_string(solver->get_status()) << std::endl;
|
||||
if (solver->get_status() == lp::lp_status::OPTIMAL) {
|
||||
if (solver->get_status() == lp::OPTIMAL) {
|
||||
if (params.min()) {
|
||||
solver->flip_costs();
|
||||
}
|
||||
solver->print_model(std::cout);
|
||||
}
|
||||
|
||||
|
||||
// #pragma omp critical (g_display_stats)
|
||||
{
|
||||
{
|
||||
display_statistics();
|
||||
register_on_timeout_proc(0);
|
||||
g_solver = 0;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
:formula (forall (a Int) (i Int) (e Int)
|
||||
(= (?select (?store a i e) i) e)
|
||||
:pats { (?store a i e) }
|
||||
:weight { 0 })
|
||||
:weight { 0 })
|
||||
|
||||
:formula (forall (a Int) (i Int) (j Int) (e Int)
|
||||
(or (= i j) (= (?select (?store a i e) j) (?select a j)))
|
||||
|
|
|
@ -956,8 +956,8 @@ public:
|
|||
}
|
||||
|
||||
void get_neighbours_undirected(dl_var current, svector<dl_var> & neighbours) {
|
||||
neighbours.reset();
|
||||
edge_id_vector & out_edges = m_out_edges[current];
|
||||
neighbours.reset();
|
||||
edge_id_vector & out_edges = m_out_edges[current];
|
||||
typename edge_id_vector::iterator it = out_edges.begin(), end = out_edges.end();
|
||||
for (; it != end; ++it) {
|
||||
edge_id e_id = *it;
|
||||
|
@ -968,7 +968,7 @@ public:
|
|||
}
|
||||
edge_id_vector & in_edges = m_in_edges[current];
|
||||
typename edge_id_vector::iterator it2 = in_edges.begin(), end2 = in_edges.end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
for (; it2 != end2; ++it2) {
|
||||
edge_id e_id = *it2;
|
||||
edge & e = m_edges[e_id];
|
||||
SASSERT(e.get_target() == current);
|
||||
|
@ -980,19 +980,19 @@ public:
|
|||
void dfs_undirected(dl_var start, svector<dl_var> & threads) {
|
||||
threads.reset();
|
||||
threads.resize(get_num_nodes());
|
||||
uint_set discovered, explored;
|
||||
svector<dl_var> nodes;
|
||||
uint_set discovered, explored;
|
||||
svector<dl_var> nodes;
|
||||
discovered.insert(start);
|
||||
nodes.push_back(start);
|
||||
dl_var prev = start;
|
||||
while(!nodes.empty()) {
|
||||
dl_var current = nodes.back();
|
||||
nodes.push_back(start);
|
||||
dl_var prev = start;
|
||||
while(!nodes.empty()) {
|
||||
dl_var current = nodes.back();
|
||||
SASSERT(discovered.contains(current) && !explored.contains(current));
|
||||
svector<dl_var> neighbours;
|
||||
get_neighbours_undirected(current, neighbours);
|
||||
svector<dl_var> neighbours;
|
||||
get_neighbours_undirected(current, neighbours);
|
||||
SASSERT(!neighbours.empty());
|
||||
bool found = false;
|
||||
for (unsigned i = 0; i < neighbours.size(); ++i) {
|
||||
for (unsigned i = 0; i < neighbours.size(); ++i) {
|
||||
dl_var next = neighbours[i];
|
||||
DEBUG_CODE(
|
||||
edge_id id;
|
||||
|
@ -1002,18 +1002,18 @@ public:
|
|||
threads[prev] = next;
|
||||
prev = next;
|
||||
discovered.insert(next);
|
||||
nodes.push_back(next);
|
||||
nodes.push_back(next);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
SASSERT(!nodes.empty());
|
||||
if (!found) {
|
||||
explored.insert(current);
|
||||
nodes.pop_back();
|
||||
}
|
||||
}
|
||||
threads[prev] = start;
|
||||
}
|
||||
threads[prev] = start;
|
||||
}
|
||||
|
||||
void bfs_undirected(dl_var start, svector<dl_var> & parents, svector<dl_var> & depths) {
|
||||
|
@ -1022,31 +1022,31 @@ public:
|
|||
parents[start] = -1;
|
||||
depths.reset();
|
||||
depths.resize(get_num_nodes());
|
||||
uint_set visited;
|
||||
std::deque<dl_var> nodes;
|
||||
visited.insert(start);
|
||||
nodes.push_front(start);
|
||||
while(!nodes.empty()) {
|
||||
uint_set visited;
|
||||
std::deque<dl_var> nodes;
|
||||
visited.insert(start);
|
||||
nodes.push_front(start);
|
||||
while(!nodes.empty()) {
|
||||
dl_var current = nodes.back();
|
||||
nodes.pop_back();
|
||||
SASSERT(visited.contains(current));
|
||||
SASSERT(visited.contains(current));
|
||||
svector<dl_var> neighbours;
|
||||
get_neighbours_undirected(current, neighbours);
|
||||
get_neighbours_undirected(current, neighbours);
|
||||
SASSERT(!neighbours.empty());
|
||||
for (unsigned i = 0; i < neighbours.size(); ++i) {
|
||||
dl_var next = neighbours[i];
|
||||
for (unsigned i = 0; i < neighbours.size(); ++i) {
|
||||
dl_var next = neighbours[i];
|
||||
DEBUG_CODE(
|
||||
edge_id id;
|
||||
SASSERT(get_edge_id(current, next, id) || get_edge_id(next, current, id)););
|
||||
if (!visited.contains(next)) {
|
||||
TRACE("diff_logic", tout << "parents[" << next << "] --> " << current << std::endl;);
|
||||
parents[next] = current;
|
||||
depths[next] = depths[current] + 1;
|
||||
visited.insert(next);
|
||||
nodes.push_front(next);
|
||||
parents[next] = current;
|
||||
depths[next] = depths[current] + 1;
|
||||
visited.insert(next);
|
||||
nodes.push_front(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Functor>
|
||||
|
|
|
@ -1753,10 +1753,6 @@ namespace smt {
|
|||
m_use_filters(use_filters) {
|
||||
}
|
||||
|
||||
context & get_context() {
|
||||
return m_context;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Create a new code tree for the given quantifier.
|
||||
|
||||
|
@ -2020,26 +2016,20 @@ namespace smt {
|
|||
void execute(code_tree * t) {
|
||||
TRACE("trigger_bug", tout << "execute for code tree:\n"; t->display(tout););
|
||||
init(t);
|
||||
enode_vector::const_iterator it = t->get_candidates().begin();
|
||||
enode_vector::const_iterator end = t->get_candidates().end();
|
||||
if (t->filter_candidates()) {
|
||||
for (; it != end; ++it) {
|
||||
enode * app = *it;
|
||||
for (enode * app : t->get_candidates()) {
|
||||
if (!app->is_marked() && app->is_cgr()) {
|
||||
execute_core(t, app);
|
||||
app->set_mark();
|
||||
}
|
||||
}
|
||||
it = t->get_candidates().begin();
|
||||
for (; it != end; ++it) {
|
||||
enode * app = *it;
|
||||
for (enode * app : t->get_candidates()) {
|
||||
if (app->is_marked())
|
||||
app->unset_mark();
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (; it != end; ++it) {
|
||||
enode * app = *it;
|
||||
for (enode * app : t->get_candidates()) {
|
||||
TRACE("trigger_bug", tout << "candidate\n" << mk_ismt2_pp(app->get_owner(), m_ast_manager) << "\n";);
|
||||
if (app->is_cgr()) {
|
||||
TRACE("trigger_bug", tout << "is_cgr\n";);
|
||||
|
@ -2825,15 +2815,13 @@ namespace smt {
|
|||
} // end of execute_core
|
||||
|
||||
void display_trees(std::ostream & out, const ptr_vector<code_tree> & trees) {
|
||||
ptr_vector<code_tree>::const_iterator it = trees.begin();
|
||||
ptr_vector<code_tree>::const_iterator end = trees.end();
|
||||
unsigned lbl = 0;
|
||||
for (; it != end; ++it, ++lbl) {
|
||||
code_tree * tree = *it;
|
||||
for (code_tree* tree : trees) {
|
||||
if (tree) {
|
||||
out << "tree for f" << lbl << "\n";
|
||||
out << *tree;
|
||||
}
|
||||
++lbl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ expr * datatype_factory::get_some_value(sort * s) {
|
|||
}
|
||||
expr * r = m_manager.mk_app(c, args.size(), args.c_ptr());
|
||||
register_value(r);
|
||||
TRACE("datatype_factory", tout << mk_pp(r, m_util.get_manager()) << "\n";);
|
||||
TRACE("datatype", tout << mk_pp(r, m_util.get_manager()) << "\n";);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ expr * datatype_factory::get_some_value(sort * s) {
|
|||
expr * datatype_factory::get_last_fresh_value(sort * s) {
|
||||
expr * val = 0;
|
||||
if (m_last_fresh_value.find(s, val)) {
|
||||
TRACE("datatype_factory", tout << "cached fresh value: " << mk_pp(val, m_manager) << "\n";);
|
||||
TRACE("datatype", tout << "cached fresh value: " << mk_pp(val, m_manager) << "\n";);
|
||||
return val;
|
||||
}
|
||||
value_set * set = get_value_set(s);
|
||||
|
@ -68,7 +68,7 @@ bool datatype_factory::is_subterm_of_last_value(app* e) {
|
|||
}
|
||||
contains_app contains(m_manager, e);
|
||||
bool result = contains(last);
|
||||
TRACE("datatype_factory", tout << mk_pp(e, m_manager) << " in " << mk_pp(last, m_manager) << " " << result << "\n";);
|
||||
TRACE("datatype", tout << mk_pp(e, m_manager) << " in " << mk_pp(last, m_manager) << " " << result << "\n";);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -126,7 +126,7 @@ expr * datatype_factory::get_almost_fresh_value(sort * s) {
|
|||
m_last_fresh_value.insert(s, new_value);
|
||||
}
|
||||
}
|
||||
TRACE("datatype_factory", tout << "almost fresh: " << mk_pp(new_value, m_manager) << "\n";);
|
||||
TRACE("datatype", tout << "almost fresh: " << mk_pp(new_value, m_manager) << "\n";);
|
||||
return new_value;
|
||||
}
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ expr * datatype_factory::get_almost_fresh_value(sort * s) {
|
|||
|
||||
|
||||
expr * datatype_factory::get_fresh_value(sort * s) {
|
||||
TRACE("datatype_factory", tout << "generating fresh value for: " << s->get_name() << "\n";);
|
||||
TRACE("datatype", tout << "generating fresh value for: " << s->get_name() << "\n";);
|
||||
value_set * set = get_value_set(s);
|
||||
// Approach 0)
|
||||
// if no value for s was generated so far, then used get_some_value
|
||||
|
@ -144,7 +144,7 @@ expr * datatype_factory::get_fresh_value(sort * s) {
|
|||
expr * val = get_some_value(s);
|
||||
if (m_util.is_recursive(s))
|
||||
m_last_fresh_value.insert(s, val);
|
||||
TRACE("datatype_factory", tout << "0. result: " << mk_pp(val, m_manager) << "\n";);
|
||||
TRACE("datatype", tout << "0. result: " << mk_pp(val, m_manager) << "\n";);
|
||||
return val;
|
||||
}
|
||||
// Approach 1)
|
||||
|
@ -171,13 +171,13 @@ expr * datatype_factory::get_fresh_value(sort * s) {
|
|||
}
|
||||
expr_ref new_value(m_manager);
|
||||
new_value = m_manager.mk_app(constructor, args.size(), args.c_ptr());
|
||||
CTRACE("datatype_factory", found_fresh_arg && set->contains(new_value), tout << mk_pp(new_value, m_manager) << "\n";);
|
||||
CTRACE("datatype", found_fresh_arg && set->contains(new_value), tout << mk_pp(new_value, m_manager) << "\n";);
|
||||
SASSERT(!found_fresh_arg || !set->contains(new_value));
|
||||
if (!set->contains(new_value)) {
|
||||
register_value(new_value);
|
||||
if (m_util.is_recursive(s))
|
||||
m_last_fresh_value.insert(s, new_value);
|
||||
TRACE("datatype_factory", tout << "1. result: " << mk_pp(new_value, m_manager) << "\n";);
|
||||
TRACE("datatype", tout << "1. result: " << mk_pp(new_value, m_manager) << "\n";);
|
||||
return new_value;
|
||||
}
|
||||
}
|
||||
|
@ -188,16 +188,16 @@ expr * datatype_factory::get_fresh_value(sort * s) {
|
|||
if (m_util.is_recursive(s)) {
|
||||
while(true) {
|
||||
++num_iterations;
|
||||
TRACE("datatype_factory", tout << mk_pp(get_last_fresh_value(s), m_manager) << "\n";);
|
||||
TRACE("datatype", tout << mk_pp(get_last_fresh_value(s), m_manager) << "\n";);
|
||||
ptr_vector<func_decl> const & constructors = *m_util.get_datatype_constructors(s);
|
||||
for (func_decl * constructor : constructors) {
|
||||
expr_ref_vector args(m_manager);
|
||||
bool found_sibling = false;
|
||||
unsigned num = constructor->get_arity();
|
||||
TRACE("datatype_factory", tout << "checking constructor: " << constructor->get_name() << "\n";);
|
||||
TRACE("datatype", tout << "checking constructor: " << constructor->get_name() << "\n";);
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
sort * s_arg = constructor->get_domain(i);
|
||||
TRACE("datatype_factory", tout << mk_pp(s, m_manager) << " "
|
||||
TRACE("datatype", tout << mk_pp(s, m_manager) << " "
|
||||
<< mk_pp(s_arg, m_manager) << " are_siblings "
|
||||
<< m_util.are_siblings(s, s_arg) << " is_datatype "
|
||||
<< m_util.is_datatype(s_arg) << " found_sibling "
|
||||
|
@ -212,7 +212,7 @@ expr * datatype_factory::get_fresh_value(sort * s) {
|
|||
maybe_new_arg = get_fresh_value(s_arg);
|
||||
}
|
||||
if (!maybe_new_arg) {
|
||||
TRACE("datatype_factory",
|
||||
TRACE("datatype",
|
||||
tout << "no argument found for " << mk_pp(s_arg, m_manager) << "\n";);
|
||||
maybe_new_arg = m_model.get_some_value(s_arg);
|
||||
found_sibling = false;
|
||||
|
@ -229,11 +229,11 @@ expr * datatype_factory::get_fresh_value(sort * s) {
|
|||
if (found_sibling) {
|
||||
expr_ref new_value(m_manager);
|
||||
new_value = m_manager.mk_app(constructor, args.size(), args.c_ptr());
|
||||
TRACE("datatype_factory", tout << "potential new value: " << mk_pp(new_value, m_manager) << "\n";);
|
||||
TRACE("datatype", tout << "potential new value: " << mk_pp(new_value, m_manager) << "\n";);
|
||||
m_last_fresh_value.insert(s, new_value);
|
||||
if (!set->contains(new_value)) {
|
||||
register_value(new_value);
|
||||
TRACE("datatype_factory", tout << "2. result: " << mk_pp(new_value, m_manager) << "\n";);
|
||||
TRACE("datatype", tout << "2. result: " << mk_pp(new_value, m_manager) << "\n";);
|
||||
return new_value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,11 +148,8 @@ namespace smt {
|
|||
}
|
||||
|
||||
void qi_queue::instantiate() {
|
||||
svector<entry>::iterator it = m_new_entries.begin();
|
||||
svector<entry>::iterator end = m_new_entries.end();
|
||||
unsigned since_last_check = 0;
|
||||
for (; it != end; ++it) {
|
||||
entry & curr = *it;
|
||||
for (entry & curr : m_new_entries) {
|
||||
fingerprint * f = curr.m_qb;
|
||||
quantifier * qa = static_cast<quantifier*>(f->get_data());
|
||||
|
||||
|
|
|
@ -4387,9 +4387,17 @@ namespace smt {
|
|||
expr* fn = to_app(q->get_pattern(0))->get_arg(0);
|
||||
expr* body = to_app(q->get_pattern(1))->get_arg(0);
|
||||
SASSERT(is_app(fn));
|
||||
// reverse argument order so that variable 0 starts at the beginning.
|
||||
expr_ref_vector subst(m);
|
||||
for (expr* arg : *to_app(fn)) {
|
||||
subst.push_back(arg);
|
||||
}
|
||||
expr_ref bodyr(m);
|
||||
var_subst sub(m, false);
|
||||
sub(body, subst.size(), subst.c_ptr(), bodyr);
|
||||
func_decl* f = to_app(fn)->get_decl();
|
||||
func_interp* fi = alloc(func_interp, m, f->get_arity());
|
||||
fi->set_else(body);
|
||||
fi->set_else(bodyr);
|
||||
m_model->register_decl(f, fi);
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue