3
0
Fork 0
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:
Nikolaj Bjorner 2017-09-24 10:53:57 -07:00
commit ae9a6664d4
144 changed files with 6012 additions and 3174 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -65,7 +65,7 @@ public class EnumSort extends Sort
**/
public Expr getConst(int inx)
{
return getContext().mkApp(getConstDecl(inx));
return getContext().mkApp(getConstDecl(inx));
}
/**

View file

@ -1287,7 +1287,7 @@ public class Expr extends AST
*/
public String getString()
{
return Native.getString(getContext().nCtx(), getNativeObject());
return Native.getString(getContext().nCtx(), getNativeObject());
}
/**

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -36,5 +36,5 @@ Notes:
#define DLL_LOCAL
#endif
#endif
#endif

View file

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

View file

@ -197,4 +197,4 @@ extern "C" {
}
#endif // __cplusplus
#endif
#endif

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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, &parameters[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, &parameters[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: {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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> &params);
expr AddParamsToApp(const expr &app, const func_decl &new_decl, const std::vector<expr> &params);
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);
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -32,7 +32,7 @@ namespace datalog {
QBMC_ENGINE,
TAB_ENGINE,
CLP_ENGINE,
DUALITY_ENGINE,
DUALITY_ENGINE,
DDNF_ENGINE,
LAST_ENGINE
};

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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